diff options
Diffstat (limited to 'drivers/media/video')
179 files changed, 9850 insertions, 3393 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 9adada0d7447..f2479c5c0eb2 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -273,6 +273,16 @@ config VIDEO_ADV7180 | |||
273 | To compile this driver as a module, choose M here: the | 273 | To compile this driver as a module, choose M here: the |
274 | module will be called adv7180. | 274 | module will be called adv7180. |
275 | 275 | ||
276 | config VIDEO_ADV7183 | ||
277 | tristate "Analog Devices ADV7183 decoder" | ||
278 | depends on VIDEO_V4L2 && I2C | ||
279 | ---help--- | ||
280 | V4l2 subdevice driver for the Analog Devices | ||
281 | ADV7183 video decoder. | ||
282 | |||
283 | To compile this driver as a module, choose M here: the | ||
284 | module will be called adv7183. | ||
285 | |||
276 | config VIDEO_BT819 | 286 | config VIDEO_BT819 |
277 | tristate "BT819A VideoStream decoder" | 287 | tristate "BT819A VideoStream decoder" |
278 | depends on VIDEO_V4L2 && I2C | 288 | depends on VIDEO_V4L2 && I2C |
@@ -459,6 +469,9 @@ config VIDEO_AK881X | |||
459 | 469 | ||
460 | comment "Camera sensor devices" | 470 | comment "Camera sensor devices" |
461 | 471 | ||
472 | config VIDEO_APTINA_PLL | ||
473 | tristate | ||
474 | |||
462 | config VIDEO_OV7670 | 475 | config VIDEO_OV7670 |
463 | tristate "OmniVision OV7670 sensor support" | 476 | tristate "OmniVision OV7670 sensor support" |
464 | depends on I2C && VIDEO_V4L2 | 477 | depends on I2C && VIDEO_V4L2 |
@@ -467,9 +480,28 @@ config VIDEO_OV7670 | |||
467 | OV7670 VGA camera. It currently only works with the M88ALP01 | 480 | OV7670 VGA camera. It currently only works with the M88ALP01 |
468 | controller. | 481 | controller. |
469 | 482 | ||
483 | config VIDEO_VS6624 | ||
484 | tristate "ST VS6624 sensor support" | ||
485 | depends on VIDEO_V4L2 && I2C | ||
486 | ---help--- | ||
487 | This is a Video4Linux2 sensor-level driver for the ST VS6624 | ||
488 | camera. | ||
489 | |||
490 | To compile this driver as a module, choose M here: the | ||
491 | module will be called vs6624. | ||
492 | |||
493 | config VIDEO_MT9M032 | ||
494 | tristate "MT9M032 camera sensor support" | ||
495 | depends on I2C && VIDEO_V4L2 | ||
496 | select VIDEO_APTINA_PLL | ||
497 | ---help--- | ||
498 | This driver supports MT9M032 camera sensors from Aptina, monochrome | ||
499 | models only. | ||
500 | |||
470 | config VIDEO_MT9P031 | 501 | config VIDEO_MT9P031 |
471 | tristate "Aptina MT9P031 support" | 502 | tristate "Aptina MT9P031 support" |
472 | depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API | 503 | depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API |
504 | select VIDEO_APTINA_PLL | ||
473 | ---help--- | 505 | ---help--- |
474 | This is a Video4Linux2 sensor-level driver for the Aptina | 506 | This is a Video4Linux2 sensor-level driver for the Aptina |
475 | (Micron) mt9p031 5 Mpixel camera. | 507 | (Micron) mt9p031 5 Mpixel camera. |
@@ -851,6 +883,8 @@ source "drivers/media/video/davinci/Kconfig" | |||
851 | 883 | ||
852 | source "drivers/media/video/omap/Kconfig" | 884 | source "drivers/media/video/omap/Kconfig" |
853 | 885 | ||
886 | source "drivers/media/video/blackfin/Kconfig" | ||
887 | |||
854 | config VIDEO_SH_VOU | 888 | config VIDEO_SH_VOU |
855 | tristate "SuperH VOU video output driver" | 889 | tristate "SuperH VOU video output driver" |
856 | depends on VIDEO_DEV && ARCH_SHMOBILE | 890 | depends on VIDEO_DEV && ARCH_SHMOBILE |
@@ -1087,7 +1121,7 @@ config VIDEO_MX2_HOSTSUPPORT | |||
1087 | config VIDEO_MX2 | 1121 | config VIDEO_MX2 |
1088 | tristate "i.MX27/i.MX25 Camera Sensor Interface driver" | 1122 | tristate "i.MX27/i.MX25 Camera Sensor Interface driver" |
1089 | depends on VIDEO_DEV && SOC_CAMERA && (MACH_MX27 || ARCH_MX25) | 1123 | depends on VIDEO_DEV && SOC_CAMERA && (MACH_MX27 || ARCH_MX25) |
1090 | select VIDEOBUF_DMA_CONTIG | 1124 | select VIDEOBUF2_DMA_CONTIG |
1091 | select VIDEO_MX2_HOSTSUPPORT | 1125 | select VIDEO_MX2_HOSTSUPPORT |
1092 | ---help--- | 1126 | ---help--- |
1093 | This is a v4l2 driver for the i.MX27 and the i.MX25 Camera Sensor | 1127 | This is a v4l2 driver for the i.MX27 and the i.MX25 Camera Sensor |
@@ -1116,7 +1150,8 @@ config VIDEO_ATMEL_ISI | |||
1116 | 1150 | ||
1117 | config VIDEO_S5P_MIPI_CSIS | 1151 | config VIDEO_S5P_MIPI_CSIS |
1118 | tristate "Samsung S5P and EXYNOS4 MIPI CSI receiver driver" | 1152 | tristate "Samsung S5P and EXYNOS4 MIPI CSI receiver driver" |
1119 | depends on VIDEO_V4L2 && PM_RUNTIME && PLAT_S5P && VIDEO_V4L2_SUBDEV_API | 1153 | depends on VIDEO_V4L2 && PM_RUNTIME && PLAT_S5P |
1154 | depends on VIDEO_V4L2_SUBDEV_API && REGULATOR | ||
1120 | ---help--- | 1155 | ---help--- |
1121 | This is a v4l2 driver for Samsung S5P/EXYNOS4 MIPI-CSI receiver. | 1156 | This is a v4l2 driver for Samsung S5P/EXYNOS4 MIPI-CSI receiver. |
1122 | 1157 | ||
@@ -1176,4 +1211,14 @@ config VIDEO_SAMSUNG_S5P_MFC | |||
1176 | help | 1211 | help |
1177 | MFC 5.1 driver for V4L2. | 1212 | MFC 5.1 driver for V4L2. |
1178 | 1213 | ||
1214 | config VIDEO_MX2_EMMAPRP | ||
1215 | tristate "MX2 eMMa-PrP support" | ||
1216 | depends on VIDEO_DEV && VIDEO_V4L2 && SOC_IMX27 | ||
1217 | select VIDEOBUF2_DMA_CONTIG | ||
1218 | select V4L2_MEM2MEM_DEV | ||
1219 | help | ||
1220 | MX2X chips have a PrP that can be used to process buffers from | ||
1221 | memory to memory. Operations include resizing and format | ||
1222 | conversion. | ||
1223 | |||
1179 | endif # V4L_MEM2MEM_DRIVERS | 1224 | endif # V4L_MEM2MEM_DRIVERS |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 354138804cda..a6282a3a6a82 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
@@ -12,16 +12,19 @@ omap2cam-objs := omap24xxcam.o omap24xxcam-dma.o | |||
12 | 12 | ||
13 | videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \ | 13 | videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \ |
14 | v4l2-event.o v4l2-ctrls.o v4l2-subdev.o | 14 | v4l2-event.o v4l2-ctrls.o v4l2-subdev.o |
15 | ifeq ($(CONFIG_COMPAT),y) | ||
16 | videodev-objs += v4l2-compat-ioctl32.o | ||
17 | endif | ||
15 | 18 | ||
16 | # V4L2 core modules | 19 | # V4L2 core modules |
17 | 20 | ||
18 | obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-int-device.o | 21 | obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-int-device.o |
19 | ifeq ($(CONFIG_COMPAT),y) | ||
20 | obj-$(CONFIG_VIDEO_DEV) += v4l2-compat-ioctl32.o | ||
21 | endif | ||
22 | |||
23 | obj-$(CONFIG_VIDEO_V4L2_COMMON) += v4l2-common.o | 22 | obj-$(CONFIG_VIDEO_V4L2_COMMON) += v4l2-common.o |
24 | 23 | ||
24 | # Helper modules | ||
25 | |||
26 | obj-$(CONFIG_VIDEO_APTINA_PLL) += aptina-pll.o | ||
27 | |||
25 | # All i2c modules must come first: | 28 | # All i2c modules must come first: |
26 | 29 | ||
27 | obj-$(CONFIG_VIDEO_TUNER) += tuner.o | 30 | obj-$(CONFIG_VIDEO_TUNER) += tuner.o |
@@ -40,8 +43,10 @@ obj-$(CONFIG_VIDEO_SAA7191) += saa7191.o | |||
40 | obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o | 43 | obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o |
41 | obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o | 44 | obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o |
42 | obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o | 45 | obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o |
46 | obj-$(CONFIG_VIDEO_ADV7183) += adv7183.o | ||
43 | obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o | 47 | obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o |
44 | obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o | 48 | obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o |
49 | obj-$(CONFIG_VIDEO_VS6624) += vs6624.o | ||
45 | obj-$(CONFIG_VIDEO_BT819) += bt819.o | 50 | obj-$(CONFIG_VIDEO_BT819) += bt819.o |
46 | obj-$(CONFIG_VIDEO_BT856) += bt856.o | 51 | obj-$(CONFIG_VIDEO_BT856) += bt856.o |
47 | obj-$(CONFIG_VIDEO_BT866) += bt866.o | 52 | obj-$(CONFIG_VIDEO_BT866) += bt866.o |
@@ -65,6 +70,7 @@ obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o | |||
65 | obj-$(CONFIG_VIDEO_OV7670) += ov7670.o | 70 | obj-$(CONFIG_VIDEO_OV7670) += ov7670.o |
66 | obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o | 71 | obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o |
67 | obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o | 72 | obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o |
73 | obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o | ||
68 | obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o | 74 | obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o |
69 | obj-$(CONFIG_VIDEO_MT9T001) += mt9t001.o | 75 | obj-$(CONFIG_VIDEO_MT9T001) += mt9t001.o |
70 | obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o | 76 | obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o |
@@ -177,6 +183,8 @@ obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o | |||
177 | obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o | 183 | obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o |
178 | obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel-isi.o | 184 | obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel-isi.o |
179 | 185 | ||
186 | obj-$(CONFIG_VIDEO_MX2_EMMAPRP) += mx2_emmaprp.o | ||
187 | |||
180 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) += s5p-fimc/ | 188 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) += s5p-fimc/ |
181 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG) += s5p-jpeg/ | 189 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG) += s5p-jpeg/ |
182 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) += s5p-mfc/ | 190 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) += s5p-mfc/ |
@@ -184,6 +192,8 @@ obj-$(CONFIG_VIDEO_SAMSUNG_S5P_TV) += s5p-tv/ | |||
184 | 192 | ||
185 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_G2D) += s5p-g2d/ | 193 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_G2D) += s5p-g2d/ |
186 | 194 | ||
195 | obj-$(CONFIG_BLACKFIN) += blackfin/ | ||
196 | |||
187 | obj-$(CONFIG_ARCH_DAVINCI) += davinci/ | 197 | obj-$(CONFIG_ARCH_DAVINCI) += davinci/ |
188 | 198 | ||
189 | obj-$(CONFIG_VIDEO_SH_VOU) += sh_vou.o | 199 | obj-$(CONFIG_VIDEO_SH_VOU) += sh_vou.o |
@@ -199,6 +209,6 @@ obj-y += davinci/ | |||
199 | 209 | ||
200 | obj-$(CONFIG_ARCH_OMAP) += omap/ | 210 | obj-$(CONFIG_ARCH_OMAP) += omap/ |
201 | 211 | ||
202 | ccflags-y += -Idrivers/media/dvb/dvb-core | 212 | ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core |
203 | ccflags-y += -Idrivers/media/dvb/frontends | 213 | ccflags-y += -I$(srctree)/drivers/media/dvb/frontends |
204 | ccflags-y += -Idrivers/media/common/tuners | 214 | ccflags-y += -I$(srctree)/drivers/media/common/tuners |
diff --git a/drivers/media/video/adp1653.c b/drivers/media/video/adp1653.c index 12eedf4d515a..5b045b4a66fe 100644 --- a/drivers/media/video/adp1653.c +++ b/drivers/media/video/adp1653.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <linux/delay.h> | 33 | #include <linux/delay.h> |
34 | #include <linux/module.h> | 34 | #include <linux/module.h> |
35 | #include <linux/i2c.h> | 35 | #include <linux/i2c.h> |
36 | #include <linux/module.h> | ||
37 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
38 | #include <linux/version.h> | 37 | #include <linux/version.h> |
39 | #include <media/adp1653.h> | 38 | #include <media/adp1653.h> |
@@ -482,24 +481,7 @@ static struct i2c_driver adp1653_i2c_driver = { | |||
482 | .id_table = adp1653_id_table, | 481 | .id_table = adp1653_id_table, |
483 | }; | 482 | }; |
484 | 483 | ||
485 | static int __init adp1653_init(void) | 484 | module_i2c_driver(adp1653_i2c_driver); |
486 | { | ||
487 | int rval; | ||
488 | |||
489 | rval = i2c_add_driver(&adp1653_i2c_driver); | ||
490 | if (rval) | ||
491 | printk(KERN_ALERT "%s: failed at i2c_add_driver\n", __func__); | ||
492 | |||
493 | return rval; | ||
494 | } | ||
495 | |||
496 | static void __exit adp1653_exit(void) | ||
497 | { | ||
498 | i2c_del_driver(&adp1653_i2c_driver); | ||
499 | } | ||
500 | |||
501 | module_init(adp1653_init); | ||
502 | module_exit(adp1653_exit); | ||
503 | 485 | ||
504 | MODULE_AUTHOR("Sakari Ailus <sakari.ailus@nokia.com>"); | 486 | MODULE_AUTHOR("Sakari Ailus <sakari.ailus@nokia.com>"); |
505 | MODULE_DESCRIPTION("Analog Devices ADP1653 LED flash driver"); | 487 | MODULE_DESCRIPTION("Analog Devices ADP1653 LED flash driver"); |
diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c index 879f1d839760..6bc01fb98ff8 100644 --- a/drivers/media/video/adv7170.c +++ b/drivers/media/video/adv7170.c | |||
@@ -407,15 +407,4 @@ static struct i2c_driver adv7170_driver = { | |||
407 | .id_table = adv7170_id, | 407 | .id_table = adv7170_id, |
408 | }; | 408 | }; |
409 | 409 | ||
410 | static __init int init_adv7170(void) | 410 | module_i2c_driver(adv7170_driver); |
411 | { | ||
412 | return i2c_add_driver(&adv7170_driver); | ||
413 | } | ||
414 | |||
415 | static __exit void exit_adv7170(void) | ||
416 | { | ||
417 | i2c_del_driver(&adv7170_driver); | ||
418 | } | ||
419 | |||
420 | module_init(init_adv7170); | ||
421 | module_exit(exit_adv7170); | ||
diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c index 206078eca853..c7640fab5730 100644 --- a/drivers/media/video/adv7175.c +++ b/drivers/media/video/adv7175.c | |||
@@ -457,15 +457,4 @@ static struct i2c_driver adv7175_driver = { | |||
457 | .id_table = adv7175_id, | 457 | .id_table = adv7175_id, |
458 | }; | 458 | }; |
459 | 459 | ||
460 | static __init int init_adv7175(void) | 460 | module_i2c_driver(adv7175_driver); |
461 | { | ||
462 | return i2c_add_driver(&adv7175_driver); | ||
463 | } | ||
464 | |||
465 | static __exit void exit_adv7175(void) | ||
466 | { | ||
467 | i2c_del_driver(&adv7175_driver); | ||
468 | } | ||
469 | |||
470 | module_init(init_adv7175); | ||
471 | module_exit(exit_adv7175); | ||
diff --git a/drivers/media/video/adv7180.c b/drivers/media/video/adv7180.c index d2138d06bcad..b8b6c4b0cad4 100644 --- a/drivers/media/video/adv7180.c +++ b/drivers/media/video/adv7180.c | |||
@@ -444,20 +444,8 @@ static struct i2c_driver adv7180_driver = { | |||
444 | .id_table = adv7180_id, | 444 | .id_table = adv7180_id, |
445 | }; | 445 | }; |
446 | 446 | ||
447 | static __init int adv7180_init(void) | 447 | module_i2c_driver(adv7180_driver); |
448 | { | ||
449 | return i2c_add_driver(&adv7180_driver); | ||
450 | } | ||
451 | |||
452 | static __exit void adv7180_exit(void) | ||
453 | { | ||
454 | i2c_del_driver(&adv7180_driver); | ||
455 | } | ||
456 | |||
457 | module_init(adv7180_init); | ||
458 | module_exit(adv7180_exit); | ||
459 | 448 | ||
460 | MODULE_DESCRIPTION("Analog Devices ADV7180 video decoder driver"); | 449 | MODULE_DESCRIPTION("Analog Devices ADV7180 video decoder driver"); |
461 | MODULE_AUTHOR("Mocean Laboratories"); | 450 | MODULE_AUTHOR("Mocean Laboratories"); |
462 | MODULE_LICENSE("GPL v2"); | 451 | MODULE_LICENSE("GPL v2"); |
463 | |||
diff --git a/drivers/media/video/adv7183.c b/drivers/media/video/adv7183.c new file mode 100644 index 000000000000..e1d4c89d7140 --- /dev/null +++ b/drivers/media/video/adv7183.c | |||
@@ -0,0 +1,699 @@ | |||
1 | /* | ||
2 | * adv7183.c Analog Devices ADV7183 video decoder driver | ||
3 | * | ||
4 | * Copyright (c) 2011 Analog Devices Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/delay.h> | ||
21 | #include <linux/errno.h> | ||
22 | #include <linux/gpio.h> | ||
23 | #include <linux/i2c.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/types.h> | ||
28 | #include <linux/videodev2.h> | ||
29 | |||
30 | #include <media/adv7183.h> | ||
31 | #include <media/v4l2-chip-ident.h> | ||
32 | #include <media/v4l2-ctrls.h> | ||
33 | #include <media/v4l2-device.h> | ||
34 | |||
35 | #include "adv7183_regs.h" | ||
36 | |||
37 | struct adv7183 { | ||
38 | struct v4l2_subdev sd; | ||
39 | struct v4l2_ctrl_handler hdl; | ||
40 | |||
41 | v4l2_std_id std; /* Current set standard */ | ||
42 | u32 input; | ||
43 | u32 output; | ||
44 | unsigned reset_pin; | ||
45 | unsigned oe_pin; | ||
46 | struct v4l2_mbus_framefmt fmt; | ||
47 | }; | ||
48 | |||
49 | /* EXAMPLES USING 27 MHz CLOCK | ||
50 | * Mode 1 CVBS Input (Composite Video on AIN5) | ||
51 | * All standards are supported through autodetect, 8-bit, 4:2:2, ITU-R BT.656 output on P15 to P8. | ||
52 | */ | ||
53 | static const unsigned char adv7183_init_regs[] = { | ||
54 | ADV7183_IN_CTRL, 0x04, /* CVBS input on AIN5 */ | ||
55 | ADV7183_DIGI_CLAMP_CTRL_1, 0x00, /* Slow down digital clamps */ | ||
56 | ADV7183_SHAP_FILT_CTRL, 0x41, /* Set CSFM to SH1 */ | ||
57 | ADV7183_ADC_CTRL, 0x16, /* Power down ADC 1 and ADC 2 */ | ||
58 | ADV7183_CTI_DNR_CTRL_4, 0x04, /* Set DNR threshold to 4 for flat response */ | ||
59 | /* ADI recommended programming sequence */ | ||
60 | ADV7183_ADI_CTRL, 0x80, | ||
61 | ADV7183_CTI_DNR_CTRL_4, 0x20, | ||
62 | 0x52, 0x18, | ||
63 | 0x58, 0xED, | ||
64 | 0x77, 0xC5, | ||
65 | 0x7C, 0x93, | ||
66 | 0x7D, 0x00, | ||
67 | 0xD0, 0x48, | ||
68 | 0xD5, 0xA0, | ||
69 | 0xD7, 0xEA, | ||
70 | ADV7183_SD_SATURATION_CR, 0x3E, | ||
71 | ADV7183_PAL_V_END, 0x3E, | ||
72 | ADV7183_PAL_F_TOGGLE, 0x0F, | ||
73 | ADV7183_ADI_CTRL, 0x00, | ||
74 | }; | ||
75 | |||
76 | static inline struct adv7183 *to_adv7183(struct v4l2_subdev *sd) | ||
77 | { | ||
78 | return container_of(sd, struct adv7183, sd); | ||
79 | } | ||
80 | static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) | ||
81 | { | ||
82 | return &container_of(ctrl->handler, struct adv7183, hdl)->sd; | ||
83 | } | ||
84 | |||
85 | static inline int adv7183_read(struct v4l2_subdev *sd, unsigned char reg) | ||
86 | { | ||
87 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
88 | |||
89 | return i2c_smbus_read_byte_data(client, reg); | ||
90 | } | ||
91 | |||
92 | static inline int adv7183_write(struct v4l2_subdev *sd, unsigned char reg, | ||
93 | unsigned char value) | ||
94 | { | ||
95 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
96 | |||
97 | return i2c_smbus_write_byte_data(client, reg, value); | ||
98 | } | ||
99 | |||
100 | static int adv7183_writeregs(struct v4l2_subdev *sd, | ||
101 | const unsigned char *regs, unsigned int num) | ||
102 | { | ||
103 | unsigned char reg, data; | ||
104 | unsigned int cnt = 0; | ||
105 | |||
106 | if (num & 0x1) { | ||
107 | v4l2_err(sd, "invalid regs array\n"); | ||
108 | return -1; | ||
109 | } | ||
110 | |||
111 | while (cnt < num) { | ||
112 | reg = *regs++; | ||
113 | data = *regs++; | ||
114 | cnt += 2; | ||
115 | |||
116 | adv7183_write(sd, reg, data); | ||
117 | } | ||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | static int adv7183_log_status(struct v4l2_subdev *sd) | ||
122 | { | ||
123 | struct adv7183 *decoder = to_adv7183(sd); | ||
124 | |||
125 | v4l2_info(sd, "adv7183: Input control = 0x%02x\n", | ||
126 | adv7183_read(sd, ADV7183_IN_CTRL)); | ||
127 | v4l2_info(sd, "adv7183: Video selection = 0x%02x\n", | ||
128 | adv7183_read(sd, ADV7183_VD_SEL)); | ||
129 | v4l2_info(sd, "adv7183: Output control = 0x%02x\n", | ||
130 | adv7183_read(sd, ADV7183_OUT_CTRL)); | ||
131 | v4l2_info(sd, "adv7183: Extended output control = 0x%02x\n", | ||
132 | adv7183_read(sd, ADV7183_EXT_OUT_CTRL)); | ||
133 | v4l2_info(sd, "adv7183: Autodetect enable = 0x%02x\n", | ||
134 | adv7183_read(sd, ADV7183_AUTO_DET_EN)); | ||
135 | v4l2_info(sd, "adv7183: Contrast = 0x%02x\n", | ||
136 | adv7183_read(sd, ADV7183_CONTRAST)); | ||
137 | v4l2_info(sd, "adv7183: Brightness = 0x%02x\n", | ||
138 | adv7183_read(sd, ADV7183_BRIGHTNESS)); | ||
139 | v4l2_info(sd, "adv7183: Hue = 0x%02x\n", | ||
140 | adv7183_read(sd, ADV7183_HUE)); | ||
141 | v4l2_info(sd, "adv7183: Default value Y = 0x%02x\n", | ||
142 | adv7183_read(sd, ADV7183_DEF_Y)); | ||
143 | v4l2_info(sd, "adv7183: Default value C = 0x%02x\n", | ||
144 | adv7183_read(sd, ADV7183_DEF_C)); | ||
145 | v4l2_info(sd, "adv7183: ADI control = 0x%02x\n", | ||
146 | adv7183_read(sd, ADV7183_ADI_CTRL)); | ||
147 | v4l2_info(sd, "adv7183: Power Management = 0x%02x\n", | ||
148 | adv7183_read(sd, ADV7183_POW_MANAGE)); | ||
149 | v4l2_info(sd, "adv7183: Status 1 2 and 3 = 0x%02x 0x%02x 0x%02x\n", | ||
150 | adv7183_read(sd, ADV7183_STATUS_1), | ||
151 | adv7183_read(sd, ADV7183_STATUS_2), | ||
152 | adv7183_read(sd, ADV7183_STATUS_3)); | ||
153 | v4l2_info(sd, "adv7183: Ident = 0x%02x\n", | ||
154 | adv7183_read(sd, ADV7183_IDENT)); | ||
155 | v4l2_info(sd, "adv7183: Analog clamp control = 0x%02x\n", | ||
156 | adv7183_read(sd, ADV7183_ANAL_CLAMP_CTRL)); | ||
157 | v4l2_info(sd, "adv7183: Digital clamp control 1 = 0x%02x\n", | ||
158 | adv7183_read(sd, ADV7183_DIGI_CLAMP_CTRL_1)); | ||
159 | v4l2_info(sd, "adv7183: Shaping filter control 1 and 2 = 0x%02x 0x%02x\n", | ||
160 | adv7183_read(sd, ADV7183_SHAP_FILT_CTRL), | ||
161 | adv7183_read(sd, ADV7183_SHAP_FILT_CTRL_2)); | ||
162 | v4l2_info(sd, "adv7183: Comb filter control = 0x%02x\n", | ||
163 | adv7183_read(sd, ADV7183_COMB_FILT_CTRL)); | ||
164 | v4l2_info(sd, "adv7183: ADI control 2 = 0x%02x\n", | ||
165 | adv7183_read(sd, ADV7183_ADI_CTRL_2)); | ||
166 | v4l2_info(sd, "adv7183: Pixel delay control = 0x%02x\n", | ||
167 | adv7183_read(sd, ADV7183_PIX_DELAY_CTRL)); | ||
168 | v4l2_info(sd, "adv7183: Misc gain control = 0x%02x\n", | ||
169 | adv7183_read(sd, ADV7183_MISC_GAIN_CTRL)); | ||
170 | v4l2_info(sd, "adv7183: AGC mode control = 0x%02x\n", | ||
171 | adv7183_read(sd, ADV7183_AGC_MODE_CTRL)); | ||
172 | v4l2_info(sd, "adv7183: Chroma gain control 1 and 2 = 0x%02x 0x%02x\n", | ||
173 | adv7183_read(sd, ADV7183_CHRO_GAIN_CTRL_1), | ||
174 | adv7183_read(sd, ADV7183_CHRO_GAIN_CTRL_2)); | ||
175 | v4l2_info(sd, "adv7183: Luma gain control 1 and 2 = 0x%02x 0x%02x\n", | ||
176 | adv7183_read(sd, ADV7183_LUMA_GAIN_CTRL_1), | ||
177 | adv7183_read(sd, ADV7183_LUMA_GAIN_CTRL_2)); | ||
178 | v4l2_info(sd, "adv7183: Vsync field control 1 2 and 3 = 0x%02x 0x%02x 0x%02x\n", | ||
179 | adv7183_read(sd, ADV7183_VS_FIELD_CTRL_1), | ||
180 | adv7183_read(sd, ADV7183_VS_FIELD_CTRL_2), | ||
181 | adv7183_read(sd, ADV7183_VS_FIELD_CTRL_3)); | ||
182 | v4l2_info(sd, "adv7183: Hsync positon control 1 2 and 3 = 0x%02x 0x%02x 0x%02x\n", | ||
183 | adv7183_read(sd, ADV7183_HS_POS_CTRL_1), | ||
184 | adv7183_read(sd, ADV7183_HS_POS_CTRL_2), | ||
185 | adv7183_read(sd, ADV7183_HS_POS_CTRL_3)); | ||
186 | v4l2_info(sd, "adv7183: Polarity = 0x%02x\n", | ||
187 | adv7183_read(sd, ADV7183_POLARITY)); | ||
188 | v4l2_info(sd, "adv7183: ADC control = 0x%02x\n", | ||
189 | adv7183_read(sd, ADV7183_ADC_CTRL)); | ||
190 | v4l2_info(sd, "adv7183: SD offset Cb and Cr = 0x%02x 0x%02x\n", | ||
191 | adv7183_read(sd, ADV7183_SD_OFFSET_CB), | ||
192 | adv7183_read(sd, ADV7183_SD_OFFSET_CR)); | ||
193 | v4l2_info(sd, "adv7183: SD saturation Cb and Cr = 0x%02x 0x%02x\n", | ||
194 | adv7183_read(sd, ADV7183_SD_SATURATION_CB), | ||
195 | adv7183_read(sd, ADV7183_SD_SATURATION_CR)); | ||
196 | v4l2_info(sd, "adv7183: Drive strength = 0x%02x\n", | ||
197 | adv7183_read(sd, ADV7183_DRIVE_STR)); | ||
198 | v4l2_ctrl_handler_log_status(&decoder->hdl, sd->name); | ||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | static int adv7183_g_std(struct v4l2_subdev *sd, v4l2_std_id *std) | ||
203 | { | ||
204 | struct adv7183 *decoder = to_adv7183(sd); | ||
205 | |||
206 | *std = decoder->std; | ||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | static int adv7183_s_std(struct v4l2_subdev *sd, v4l2_std_id std) | ||
211 | { | ||
212 | struct adv7183 *decoder = to_adv7183(sd); | ||
213 | int reg; | ||
214 | |||
215 | reg = adv7183_read(sd, ADV7183_IN_CTRL) & 0xF; | ||
216 | if (std == V4L2_STD_PAL_60) | ||
217 | reg |= 0x60; | ||
218 | else if (std == V4L2_STD_NTSC_443) | ||
219 | reg |= 0x70; | ||
220 | else if (std == V4L2_STD_PAL_N) | ||
221 | reg |= 0x90; | ||
222 | else if (std == V4L2_STD_PAL_M) | ||
223 | reg |= 0xA0; | ||
224 | else if (std == V4L2_STD_PAL_Nc) | ||
225 | reg |= 0xC0; | ||
226 | else if (std & V4L2_STD_PAL) | ||
227 | reg |= 0x80; | ||
228 | else if (std & V4L2_STD_NTSC) | ||
229 | reg |= 0x50; | ||
230 | else if (std & V4L2_STD_SECAM) | ||
231 | reg |= 0xE0; | ||
232 | else | ||
233 | return -EINVAL; | ||
234 | adv7183_write(sd, ADV7183_IN_CTRL, reg); | ||
235 | |||
236 | decoder->std = std; | ||
237 | |||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | static int adv7183_reset(struct v4l2_subdev *sd, u32 val) | ||
242 | { | ||
243 | int reg; | ||
244 | |||
245 | reg = adv7183_read(sd, ADV7183_POW_MANAGE) | 0x80; | ||
246 | adv7183_write(sd, ADV7183_POW_MANAGE, reg); | ||
247 | /* wait 5ms before any further i2c writes are performed */ | ||
248 | usleep_range(5000, 10000); | ||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | static int adv7183_s_routing(struct v4l2_subdev *sd, | ||
253 | u32 input, u32 output, u32 config) | ||
254 | { | ||
255 | struct adv7183 *decoder = to_adv7183(sd); | ||
256 | int reg; | ||
257 | |||
258 | if ((input > ADV7183_COMPONENT1) || (output > ADV7183_16BIT_OUT)) | ||
259 | return -EINVAL; | ||
260 | |||
261 | if (input != decoder->input) { | ||
262 | decoder->input = input; | ||
263 | reg = adv7183_read(sd, ADV7183_IN_CTRL) & 0xF0; | ||
264 | switch (input) { | ||
265 | case ADV7183_COMPOSITE1: | ||
266 | reg |= 0x1; | ||
267 | break; | ||
268 | case ADV7183_COMPOSITE2: | ||
269 | reg |= 0x2; | ||
270 | break; | ||
271 | case ADV7183_COMPOSITE3: | ||
272 | reg |= 0x3; | ||
273 | break; | ||
274 | case ADV7183_COMPOSITE4: | ||
275 | reg |= 0x4; | ||
276 | break; | ||
277 | case ADV7183_COMPOSITE5: | ||
278 | reg |= 0x5; | ||
279 | break; | ||
280 | case ADV7183_COMPOSITE6: | ||
281 | reg |= 0xB; | ||
282 | break; | ||
283 | case ADV7183_COMPOSITE7: | ||
284 | reg |= 0xC; | ||
285 | break; | ||
286 | case ADV7183_COMPOSITE8: | ||
287 | reg |= 0xD; | ||
288 | break; | ||
289 | case ADV7183_COMPOSITE9: | ||
290 | reg |= 0xE; | ||
291 | break; | ||
292 | case ADV7183_COMPOSITE10: | ||
293 | reg |= 0xF; | ||
294 | break; | ||
295 | case ADV7183_SVIDEO0: | ||
296 | reg |= 0x6; | ||
297 | break; | ||
298 | case ADV7183_SVIDEO1: | ||
299 | reg |= 0x7; | ||
300 | break; | ||
301 | case ADV7183_SVIDEO2: | ||
302 | reg |= 0x8; | ||
303 | break; | ||
304 | case ADV7183_COMPONENT0: | ||
305 | reg |= 0x9; | ||
306 | break; | ||
307 | case ADV7183_COMPONENT1: | ||
308 | reg |= 0xA; | ||
309 | break; | ||
310 | default: | ||
311 | break; | ||
312 | } | ||
313 | adv7183_write(sd, ADV7183_IN_CTRL, reg); | ||
314 | } | ||
315 | |||
316 | if (output != decoder->output) { | ||
317 | decoder->output = output; | ||
318 | reg = adv7183_read(sd, ADV7183_OUT_CTRL) & 0xC0; | ||
319 | switch (output) { | ||
320 | case ADV7183_16BIT_OUT: | ||
321 | reg |= 0x9; | ||
322 | break; | ||
323 | default: | ||
324 | reg |= 0xC; | ||
325 | break; | ||
326 | } | ||
327 | adv7183_write(sd, ADV7183_OUT_CTRL, reg); | ||
328 | } | ||
329 | |||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | static int adv7183_s_ctrl(struct v4l2_ctrl *ctrl) | ||
334 | { | ||
335 | struct v4l2_subdev *sd = to_sd(ctrl); | ||
336 | int val = ctrl->val; | ||
337 | |||
338 | switch (ctrl->id) { | ||
339 | case V4L2_CID_BRIGHTNESS: | ||
340 | if (val < 0) | ||
341 | val = 127 - val; | ||
342 | adv7183_write(sd, ADV7183_BRIGHTNESS, val); | ||
343 | break; | ||
344 | case V4L2_CID_CONTRAST: | ||
345 | adv7183_write(sd, ADV7183_CONTRAST, val); | ||
346 | break; | ||
347 | case V4L2_CID_SATURATION: | ||
348 | adv7183_write(sd, ADV7183_SD_SATURATION_CB, val >> 8); | ||
349 | adv7183_write(sd, ADV7183_SD_SATURATION_CR, (val & 0xFF)); | ||
350 | break; | ||
351 | case V4L2_CID_HUE: | ||
352 | adv7183_write(sd, ADV7183_SD_OFFSET_CB, val >> 8); | ||
353 | adv7183_write(sd, ADV7183_SD_OFFSET_CR, (val & 0xFF)); | ||
354 | break; | ||
355 | default: | ||
356 | return -EINVAL; | ||
357 | } | ||
358 | |||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | static int adv7183_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) | ||
363 | { | ||
364 | struct adv7183 *decoder = to_adv7183(sd); | ||
365 | int reg; | ||
366 | |||
367 | /* enable autodetection block */ | ||
368 | reg = adv7183_read(sd, ADV7183_IN_CTRL) & 0xF; | ||
369 | adv7183_write(sd, ADV7183_IN_CTRL, reg); | ||
370 | |||
371 | /* wait autodetection switch */ | ||
372 | mdelay(10); | ||
373 | |||
374 | /* get autodetection result */ | ||
375 | reg = adv7183_read(sd, ADV7183_STATUS_1); | ||
376 | switch ((reg >> 0x4) & 0x7) { | ||
377 | case 0: | ||
378 | *std = V4L2_STD_NTSC; | ||
379 | break; | ||
380 | case 1: | ||
381 | *std = V4L2_STD_NTSC_443; | ||
382 | break; | ||
383 | case 2: | ||
384 | *std = V4L2_STD_PAL_M; | ||
385 | break; | ||
386 | case 3: | ||
387 | *std = V4L2_STD_PAL_60; | ||
388 | break; | ||
389 | case 4: | ||
390 | *std = V4L2_STD_PAL; | ||
391 | break; | ||
392 | case 5: | ||
393 | *std = V4L2_STD_SECAM; | ||
394 | break; | ||
395 | case 6: | ||
396 | *std = V4L2_STD_PAL_Nc; | ||
397 | break; | ||
398 | case 7: | ||
399 | *std = V4L2_STD_SECAM; | ||
400 | break; | ||
401 | default: | ||
402 | *std = V4L2_STD_UNKNOWN; | ||
403 | break; | ||
404 | } | ||
405 | |||
406 | /* after std detection, write back user set std */ | ||
407 | adv7183_s_std(sd, decoder->std); | ||
408 | return 0; | ||
409 | } | ||
410 | |||
411 | static int adv7183_g_input_status(struct v4l2_subdev *sd, u32 *status) | ||
412 | { | ||
413 | int reg; | ||
414 | |||
415 | *status = V4L2_IN_ST_NO_SIGNAL; | ||
416 | reg = adv7183_read(sd, ADV7183_STATUS_1); | ||
417 | if (reg < 0) | ||
418 | return reg; | ||
419 | if (reg & 0x1) | ||
420 | *status = 0; | ||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | static int adv7183_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index, | ||
425 | enum v4l2_mbus_pixelcode *code) | ||
426 | { | ||
427 | if (index > 0) | ||
428 | return -EINVAL; | ||
429 | |||
430 | *code = V4L2_MBUS_FMT_UYVY8_2X8; | ||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | static int adv7183_try_mbus_fmt(struct v4l2_subdev *sd, | ||
435 | struct v4l2_mbus_framefmt *fmt) | ||
436 | { | ||
437 | struct adv7183 *decoder = to_adv7183(sd); | ||
438 | |||
439 | fmt->code = V4L2_MBUS_FMT_UYVY8_2X8; | ||
440 | fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
441 | if (decoder->std & V4L2_STD_525_60) { | ||
442 | fmt->field = V4L2_FIELD_SEQ_TB; | ||
443 | fmt->width = 720; | ||
444 | fmt->height = 480; | ||
445 | } else { | ||
446 | fmt->field = V4L2_FIELD_SEQ_BT; | ||
447 | fmt->width = 720; | ||
448 | fmt->height = 576; | ||
449 | } | ||
450 | return 0; | ||
451 | } | ||
452 | |||
453 | static int adv7183_s_mbus_fmt(struct v4l2_subdev *sd, | ||
454 | struct v4l2_mbus_framefmt *fmt) | ||
455 | { | ||
456 | struct adv7183 *decoder = to_adv7183(sd); | ||
457 | |||
458 | adv7183_try_mbus_fmt(sd, fmt); | ||
459 | decoder->fmt = *fmt; | ||
460 | return 0; | ||
461 | } | ||
462 | |||
463 | static int adv7183_g_mbus_fmt(struct v4l2_subdev *sd, | ||
464 | struct v4l2_mbus_framefmt *fmt) | ||
465 | { | ||
466 | struct adv7183 *decoder = to_adv7183(sd); | ||
467 | |||
468 | *fmt = decoder->fmt; | ||
469 | return 0; | ||
470 | } | ||
471 | |||
472 | static int adv7183_s_stream(struct v4l2_subdev *sd, int enable) | ||
473 | { | ||
474 | struct adv7183 *decoder = to_adv7183(sd); | ||
475 | |||
476 | if (enable) | ||
477 | gpio_direction_output(decoder->oe_pin, 0); | ||
478 | else | ||
479 | gpio_direction_output(decoder->oe_pin, 1); | ||
480 | udelay(1); | ||
481 | return 0; | ||
482 | } | ||
483 | |||
484 | static int adv7183_g_chip_ident(struct v4l2_subdev *sd, | ||
485 | struct v4l2_dbg_chip_ident *chip) | ||
486 | { | ||
487 | int rev; | ||
488 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
489 | |||
490 | /* 0x11 for adv7183, 0x13 for adv7183b */ | ||
491 | rev = adv7183_read(sd, ADV7183_IDENT); | ||
492 | |||
493 | return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7183, rev); | ||
494 | } | ||
495 | |||
496 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
497 | static int adv7183_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) | ||
498 | { | ||
499 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
500 | |||
501 | if (!v4l2_chip_match_i2c_client(client, ®->match)) | ||
502 | return -EINVAL; | ||
503 | if (!capable(CAP_SYS_ADMIN)) | ||
504 | return -EPERM; | ||
505 | reg->val = adv7183_read(sd, reg->reg & 0xff); | ||
506 | reg->size = 1; | ||
507 | return 0; | ||
508 | } | ||
509 | |||
510 | static int adv7183_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) | ||
511 | { | ||
512 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
513 | |||
514 | if (!v4l2_chip_match_i2c_client(client, ®->match)) | ||
515 | return -EINVAL; | ||
516 | if (!capable(CAP_SYS_ADMIN)) | ||
517 | return -EPERM; | ||
518 | adv7183_write(sd, reg->reg & 0xff, reg->val & 0xff); | ||
519 | return 0; | ||
520 | } | ||
521 | #endif | ||
522 | |||
523 | static const struct v4l2_ctrl_ops adv7183_ctrl_ops = { | ||
524 | .s_ctrl = adv7183_s_ctrl, | ||
525 | }; | ||
526 | |||
527 | static const struct v4l2_subdev_core_ops adv7183_core_ops = { | ||
528 | .log_status = adv7183_log_status, | ||
529 | .g_std = adv7183_g_std, | ||
530 | .s_std = adv7183_s_std, | ||
531 | .reset = adv7183_reset, | ||
532 | .g_chip_ident = adv7183_g_chip_ident, | ||
533 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
534 | .g_register = adv7183_g_register, | ||
535 | .s_register = adv7183_s_register, | ||
536 | #endif | ||
537 | }; | ||
538 | |||
539 | static const struct v4l2_subdev_video_ops adv7183_video_ops = { | ||
540 | .s_routing = adv7183_s_routing, | ||
541 | .querystd = adv7183_querystd, | ||
542 | .g_input_status = adv7183_g_input_status, | ||
543 | .enum_mbus_fmt = adv7183_enum_mbus_fmt, | ||
544 | .try_mbus_fmt = adv7183_try_mbus_fmt, | ||
545 | .s_mbus_fmt = adv7183_s_mbus_fmt, | ||
546 | .g_mbus_fmt = adv7183_g_mbus_fmt, | ||
547 | .s_stream = adv7183_s_stream, | ||
548 | }; | ||
549 | |||
550 | static const struct v4l2_subdev_ops adv7183_ops = { | ||
551 | .core = &adv7183_core_ops, | ||
552 | .video = &adv7183_video_ops, | ||
553 | }; | ||
554 | |||
555 | static int adv7183_probe(struct i2c_client *client, | ||
556 | const struct i2c_device_id *id) | ||
557 | { | ||
558 | struct adv7183 *decoder; | ||
559 | struct v4l2_subdev *sd; | ||
560 | struct v4l2_ctrl_handler *hdl; | ||
561 | int ret; | ||
562 | struct v4l2_mbus_framefmt fmt; | ||
563 | const unsigned *pin_array; | ||
564 | |||
565 | /* Check if the adapter supports the needed features */ | ||
566 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
567 | return -EIO; | ||
568 | |||
569 | v4l_info(client, "chip found @ 0x%02x (%s)\n", | ||
570 | client->addr << 1, client->adapter->name); | ||
571 | |||
572 | pin_array = client->dev.platform_data; | ||
573 | if (pin_array == NULL) | ||
574 | return -EINVAL; | ||
575 | |||
576 | decoder = kzalloc(sizeof(struct adv7183), GFP_KERNEL); | ||
577 | if (decoder == NULL) | ||
578 | return -ENOMEM; | ||
579 | |||
580 | decoder->reset_pin = pin_array[0]; | ||
581 | decoder->oe_pin = pin_array[1]; | ||
582 | |||
583 | if (gpio_request(decoder->reset_pin, "ADV7183 Reset")) { | ||
584 | v4l_err(client, "failed to request GPIO %d\n", decoder->reset_pin); | ||
585 | ret = -EBUSY; | ||
586 | goto err_free_decoder; | ||
587 | } | ||
588 | |||
589 | if (gpio_request(decoder->oe_pin, "ADV7183 Output Enable")) { | ||
590 | v4l_err(client, "failed to request GPIO %d\n", decoder->oe_pin); | ||
591 | ret = -EBUSY; | ||
592 | goto err_free_reset; | ||
593 | } | ||
594 | |||
595 | sd = &decoder->sd; | ||
596 | v4l2_i2c_subdev_init(sd, client, &adv7183_ops); | ||
597 | |||
598 | hdl = &decoder->hdl; | ||
599 | v4l2_ctrl_handler_init(hdl, 4); | ||
600 | v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops, | ||
601 | V4L2_CID_BRIGHTNESS, -128, 127, 1, 0); | ||
602 | v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops, | ||
603 | V4L2_CID_CONTRAST, 0, 0xFF, 1, 0x80); | ||
604 | v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops, | ||
605 | V4L2_CID_SATURATION, 0, 0xFFFF, 1, 0x8080); | ||
606 | v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops, | ||
607 | V4L2_CID_HUE, 0, 0xFFFF, 1, 0x8080); | ||
608 | /* hook the control handler into the driver */ | ||
609 | sd->ctrl_handler = hdl; | ||
610 | if (hdl->error) { | ||
611 | ret = hdl->error; | ||
612 | |||
613 | v4l2_ctrl_handler_free(hdl); | ||
614 | goto err_free_oe; | ||
615 | } | ||
616 | |||
617 | /* v4l2 doesn't support an autodetect standard, pick PAL as default */ | ||
618 | decoder->std = V4L2_STD_PAL; | ||
619 | decoder->input = ADV7183_COMPOSITE4; | ||
620 | decoder->output = ADV7183_8BIT_OUT; | ||
621 | |||
622 | gpio_direction_output(decoder->oe_pin, 1); | ||
623 | /* reset chip */ | ||
624 | gpio_direction_output(decoder->reset_pin, 0); | ||
625 | /* reset pulse width at least 5ms */ | ||
626 | mdelay(10); | ||
627 | gpio_direction_output(decoder->reset_pin, 1); | ||
628 | /* wait 5ms before any further i2c writes are performed */ | ||
629 | mdelay(5); | ||
630 | |||
631 | adv7183_writeregs(sd, adv7183_init_regs, ARRAY_SIZE(adv7183_init_regs)); | ||
632 | adv7183_s_std(sd, decoder->std); | ||
633 | fmt.width = 720; | ||
634 | fmt.height = 576; | ||
635 | adv7183_s_mbus_fmt(sd, &fmt); | ||
636 | |||
637 | /* initialize the hardware to the default control values */ | ||
638 | ret = v4l2_ctrl_handler_setup(hdl); | ||
639 | if (ret) { | ||
640 | v4l2_ctrl_handler_free(hdl); | ||
641 | goto err_free_oe; | ||
642 | } | ||
643 | |||
644 | return 0; | ||
645 | err_free_oe: | ||
646 | gpio_free(decoder->oe_pin); | ||
647 | err_free_reset: | ||
648 | gpio_free(decoder->reset_pin); | ||
649 | err_free_decoder: | ||
650 | kfree(decoder); | ||
651 | return ret; | ||
652 | } | ||
653 | |||
654 | static int adv7183_remove(struct i2c_client *client) | ||
655 | { | ||
656 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
657 | struct adv7183 *decoder = to_adv7183(sd); | ||
658 | |||
659 | v4l2_device_unregister_subdev(sd); | ||
660 | v4l2_ctrl_handler_free(sd->ctrl_handler); | ||
661 | gpio_free(decoder->oe_pin); | ||
662 | gpio_free(decoder->reset_pin); | ||
663 | kfree(decoder); | ||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | static const struct i2c_device_id adv7183_id[] = { | ||
668 | {"adv7183", 0}, | ||
669 | {}, | ||
670 | }; | ||
671 | |||
672 | MODULE_DEVICE_TABLE(i2c, adv7183_id); | ||
673 | |||
674 | static struct i2c_driver adv7183_driver = { | ||
675 | .driver = { | ||
676 | .owner = THIS_MODULE, | ||
677 | .name = "adv7183", | ||
678 | }, | ||
679 | .probe = adv7183_probe, | ||
680 | .remove = __devexit_p(adv7183_remove), | ||
681 | .id_table = adv7183_id, | ||
682 | }; | ||
683 | |||
684 | static __init int adv7183_init(void) | ||
685 | { | ||
686 | return i2c_add_driver(&adv7183_driver); | ||
687 | } | ||
688 | |||
689 | static __exit void adv7183_exit(void) | ||
690 | { | ||
691 | i2c_del_driver(&adv7183_driver); | ||
692 | } | ||
693 | |||
694 | module_init(adv7183_init); | ||
695 | module_exit(adv7183_exit); | ||
696 | |||
697 | MODULE_DESCRIPTION("Analog Devices ADV7183 video decoder driver"); | ||
698 | MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>"); | ||
699 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/media/video/adv7183_regs.h b/drivers/media/video/adv7183_regs.h new file mode 100644 index 000000000000..4a5b7d211d2f --- /dev/null +++ b/drivers/media/video/adv7183_regs.h | |||
@@ -0,0 +1,107 @@ | |||
1 | /* | ||
2 | * adv7183 - Analog Devices ADV7183 video decoder registers | ||
3 | * | ||
4 | * Copyright (c) 2011 Analog Devices Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | #ifndef _ADV7183_REGS_H_ | ||
21 | #define _ADV7183_REGS_H_ | ||
22 | |||
23 | #define ADV7183_IN_CTRL 0x00 /* Input control */ | ||
24 | #define ADV7183_VD_SEL 0x01 /* Video selection */ | ||
25 | #define ADV7183_OUT_CTRL 0x03 /* Output control */ | ||
26 | #define ADV7183_EXT_OUT_CTRL 0x04 /* Extended output control */ | ||
27 | #define ADV7183_AUTO_DET_EN 0x07 /* Autodetect enable */ | ||
28 | #define ADV7183_CONTRAST 0x08 /* Contrast */ | ||
29 | #define ADV7183_BRIGHTNESS 0x0A /* Brightness */ | ||
30 | #define ADV7183_HUE 0x0B /* Hue */ | ||
31 | #define ADV7183_DEF_Y 0x0C /* Default value Y */ | ||
32 | #define ADV7183_DEF_C 0x0D /* Default value C */ | ||
33 | #define ADV7183_ADI_CTRL 0x0E /* ADI control */ | ||
34 | #define ADV7183_POW_MANAGE 0x0F /* Power Management */ | ||
35 | #define ADV7183_STATUS_1 0x10 /* Status 1 */ | ||
36 | #define ADV7183_IDENT 0x11 /* Ident */ | ||
37 | #define ADV7183_STATUS_2 0x12 /* Status 2 */ | ||
38 | #define ADV7183_STATUS_3 0x13 /* Status 3 */ | ||
39 | #define ADV7183_ANAL_CLAMP_CTRL 0x14 /* Analog clamp control */ | ||
40 | #define ADV7183_DIGI_CLAMP_CTRL_1 0x15 /* Digital clamp control 1 */ | ||
41 | #define ADV7183_SHAP_FILT_CTRL 0x17 /* Shaping filter control */ | ||
42 | #define ADV7183_SHAP_FILT_CTRL_2 0x18 /* Shaping filter control 2 */ | ||
43 | #define ADV7183_COMB_FILT_CTRL 0x19 /* Comb filter control */ | ||
44 | #define ADV7183_ADI_CTRL_2 0x1D /* ADI control 2 */ | ||
45 | #define ADV7183_PIX_DELAY_CTRL 0x27 /* Pixel delay control */ | ||
46 | #define ADV7183_MISC_GAIN_CTRL 0x2B /* Misc gain control */ | ||
47 | #define ADV7183_AGC_MODE_CTRL 0x2C /* AGC mode control */ | ||
48 | #define ADV7183_CHRO_GAIN_CTRL_1 0x2D /* Chroma gain control 1 */ | ||
49 | #define ADV7183_CHRO_GAIN_CTRL_2 0x2E /* Chroma gain control 2 */ | ||
50 | #define ADV7183_LUMA_GAIN_CTRL_1 0x2F /* Luma gain control 1 */ | ||
51 | #define ADV7183_LUMA_GAIN_CTRL_2 0x30 /* Luma gain control 2 */ | ||
52 | #define ADV7183_VS_FIELD_CTRL_1 0x31 /* Vsync field control 1 */ | ||
53 | #define ADV7183_VS_FIELD_CTRL_2 0x32 /* Vsync field control 2 */ | ||
54 | #define ADV7183_VS_FIELD_CTRL_3 0x33 /* Vsync field control 3 */ | ||
55 | #define ADV7183_HS_POS_CTRL_1 0x34 /* Hsync positon control 1 */ | ||
56 | #define ADV7183_HS_POS_CTRL_2 0x35 /* Hsync positon control 2 */ | ||
57 | #define ADV7183_HS_POS_CTRL_3 0x36 /* Hsync positon control 3 */ | ||
58 | #define ADV7183_POLARITY 0x37 /* Polarity */ | ||
59 | #define ADV7183_NTSC_COMB_CTRL 0x38 /* NTSC comb control */ | ||
60 | #define ADV7183_PAL_COMB_CTRL 0x39 /* PAL comb control */ | ||
61 | #define ADV7183_ADC_CTRL 0x3A /* ADC control */ | ||
62 | #define ADV7183_MAN_WIN_CTRL 0x3D /* Manual window control */ | ||
63 | #define ADV7183_RESAMPLE_CTRL 0x41 /* Resample control */ | ||
64 | #define ADV7183_GEMSTAR_CTRL_1 0x48 /* Gemstar ctrl 1 */ | ||
65 | #define ADV7183_GEMSTAR_CTRL_2 0x49 /* Gemstar ctrl 2 */ | ||
66 | #define ADV7183_GEMSTAR_CTRL_3 0x4A /* Gemstar ctrl 3 */ | ||
67 | #define ADV7183_GEMSTAR_CTRL_4 0x4B /* Gemstar ctrl 4 */ | ||
68 | #define ADV7183_GEMSTAR_CTRL_5 0x4C /* Gemstar ctrl 5 */ | ||
69 | #define ADV7183_CTI_DNR_CTRL_1 0x4D /* CTI DNR ctrl 1 */ | ||
70 | #define ADV7183_CTI_DNR_CTRL_2 0x4E /* CTI DNR ctrl 2 */ | ||
71 | #define ADV7183_CTI_DNR_CTRL_4 0x50 /* CTI DNR ctrl 4 */ | ||
72 | #define ADV7183_LOCK_CNT 0x51 /* Lock count */ | ||
73 | #define ADV7183_FREE_LINE_LEN 0x8F /* Free-Run line length 1 */ | ||
74 | #define ADV7183_VBI_INFO 0x90 /* VBI info */ | ||
75 | #define ADV7183_WSS_1 0x91 /* WSS 1 */ | ||
76 | #define ADV7183_WSS_2 0x92 /* WSS 2 */ | ||
77 | #define ADV7183_EDTV_1 0x93 /* EDTV 1 */ | ||
78 | #define ADV7183_EDTV_2 0x94 /* EDTV 2 */ | ||
79 | #define ADV7183_EDTV_3 0x95 /* EDTV 3 */ | ||
80 | #define ADV7183_CGMS_1 0x96 /* CGMS 1 */ | ||
81 | #define ADV7183_CGMS_2 0x97 /* CGMS 2 */ | ||
82 | #define ADV7183_CGMS_3 0x98 /* CGMS 3 */ | ||
83 | #define ADV7183_CCAP_1 0x99 /* CCAP 1 */ | ||
84 | #define ADV7183_CCAP_2 0x9A /* CCAP 2 */ | ||
85 | #define ADV7183_LETTERBOX_1 0x9B /* Letterbox 1 */ | ||
86 | #define ADV7183_LETTERBOX_2 0x9C /* Letterbox 2 */ | ||
87 | #define ADV7183_LETTERBOX_3 0x9D /* Letterbox 3 */ | ||
88 | #define ADV7183_CRC_EN 0xB2 /* CRC enable */ | ||
89 | #define ADV7183_ADC_SWITCH_1 0xC3 /* ADC switch 1 */ | ||
90 | #define ADV7183_ADC_SWITCH_2 0xC4 /* ADC swithc 2 */ | ||
91 | #define ADV7183_LETTERBOX_CTRL_1 0xDC /* Letterbox control 1 */ | ||
92 | #define ADV7183_LETTERBOX_CTRL_2 0xDD /* Letterbox control 2 */ | ||
93 | #define ADV7183_SD_OFFSET_CB 0xE1 /* SD offset Cb */ | ||
94 | #define ADV7183_SD_OFFSET_CR 0xE2 /* SD offset Cr */ | ||
95 | #define ADV7183_SD_SATURATION_CB 0xE3 /* SD saturation Cb */ | ||
96 | #define ADV7183_SD_SATURATION_CR 0xE4 /* SD saturation Cr */ | ||
97 | #define ADV7183_NTSC_V_BEGIN 0xE5 /* NTSC V bit begin */ | ||
98 | #define ADV7183_NTSC_V_END 0xE6 /* NTSC V bit end */ | ||
99 | #define ADV7183_NTSC_F_TOGGLE 0xE7 /* NTSC F bit toggle */ | ||
100 | #define ADV7183_PAL_V_BEGIN 0xE8 /* PAL V bit begin */ | ||
101 | #define ADV7183_PAL_V_END 0xE9 /* PAL V bit end */ | ||
102 | #define ADV7183_PAL_F_TOGGLE 0xEA /* PAL F bit toggle */ | ||
103 | #define ADV7183_DRIVE_STR 0xF4 /* Drive strength */ | ||
104 | #define ADV7183_IF_COMP_CTRL 0xF8 /* IF comp control */ | ||
105 | #define ADV7183_VS_MODE_CTRL 0xF9 /* VS mode control */ | ||
106 | |||
107 | #endif | ||
diff --git a/drivers/media/video/adv7343.c b/drivers/media/video/adv7343.c index 021fab23070d..119b60401bf3 100644 --- a/drivers/media/video/adv7343.c +++ b/drivers/media/video/adv7343.c | |||
@@ -475,15 +475,4 @@ static struct i2c_driver adv7343_driver = { | |||
475 | .id_table = adv7343_id, | 475 | .id_table = adv7343_id, |
476 | }; | 476 | }; |
477 | 477 | ||
478 | static __init int init_adv7343(void) | 478 | module_i2c_driver(adv7343_driver); |
479 | { | ||
480 | return i2c_add_driver(&adv7343_driver); | ||
481 | } | ||
482 | |||
483 | static __exit void exit_adv7343(void) | ||
484 | { | ||
485 | i2c_del_driver(&adv7343_driver); | ||
486 | } | ||
487 | |||
488 | module_init(init_adv7343); | ||
489 | module_exit(exit_adv7343); | ||
diff --git a/drivers/media/video/ak881x.c b/drivers/media/video/ak881x.c index 53c496c00fb6..ba674656b10d 100644 --- a/drivers/media/video/ak881x.c +++ b/drivers/media/video/ak881x.c | |||
@@ -352,18 +352,7 @@ static struct i2c_driver ak881x_i2c_driver = { | |||
352 | .id_table = ak881x_id, | 352 | .id_table = ak881x_id, |
353 | }; | 353 | }; |
354 | 354 | ||
355 | static int __init ak881x_module_init(void) | 355 | module_i2c_driver(ak881x_i2c_driver); |
356 | { | ||
357 | return i2c_add_driver(&ak881x_i2c_driver); | ||
358 | } | ||
359 | |||
360 | static void __exit ak881x_module_exit(void) | ||
361 | { | ||
362 | i2c_del_driver(&ak881x_i2c_driver); | ||
363 | } | ||
364 | |||
365 | module_init(ak881x_module_init); | ||
366 | module_exit(ak881x_module_exit); | ||
367 | 356 | ||
368 | MODULE_DESCRIPTION("TV-output driver for ak8813/ak8814"); | 357 | MODULE_DESCRIPTION("TV-output driver for ak8813/ak8814"); |
369 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); | 358 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); |
diff --git a/drivers/media/video/aptina-pll.c b/drivers/media/video/aptina-pll.c new file mode 100644 index 000000000000..0bd3813bb59d --- /dev/null +++ b/drivers/media/video/aptina-pll.c | |||
@@ -0,0 +1,174 @@ | |||
1 | /* | ||
2 | * Aptina Sensor PLL Configuration | ||
3 | * | ||
4 | * Copyright (C) 2012 Laurent Pinchart <laurent.pinchart@ideasonboard.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/device.h> | ||
22 | #include <linux/gcd.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/lcm.h> | ||
25 | #include <linux/module.h> | ||
26 | |||
27 | #include "aptina-pll.h" | ||
28 | |||
29 | int aptina_pll_calculate(struct device *dev, | ||
30 | const struct aptina_pll_limits *limits, | ||
31 | struct aptina_pll *pll) | ||
32 | { | ||
33 | unsigned int mf_min; | ||
34 | unsigned int mf_max; | ||
35 | unsigned int p1_min; | ||
36 | unsigned int p1_max; | ||
37 | unsigned int p1; | ||
38 | unsigned int div; | ||
39 | |||
40 | dev_dbg(dev, "PLL: ext clock %u pix clock %u\n", | ||
41 | pll->ext_clock, pll->pix_clock); | ||
42 | |||
43 | if (pll->ext_clock < limits->ext_clock_min || | ||
44 | pll->ext_clock > limits->ext_clock_max) { | ||
45 | dev_err(dev, "pll: invalid external clock frequency.\n"); | ||
46 | return -EINVAL; | ||
47 | } | ||
48 | |||
49 | if (pll->pix_clock == 0 || pll->pix_clock > limits->pix_clock_max) { | ||
50 | dev_err(dev, "pll: invalid pixel clock frequency.\n"); | ||
51 | return -EINVAL; | ||
52 | } | ||
53 | |||
54 | /* Compute the multiplier M and combined N*P1 divisor. */ | ||
55 | div = gcd(pll->pix_clock, pll->ext_clock); | ||
56 | pll->m = pll->pix_clock / div; | ||
57 | div = pll->ext_clock / div; | ||
58 | |||
59 | /* We now have the smallest M and N*P1 values that will result in the | ||
60 | * desired pixel clock frequency, but they might be out of the valid | ||
61 | * range. Compute the factor by which we should multiply them given the | ||
62 | * following constraints: | ||
63 | * | ||
64 | * - minimum/maximum multiplier | ||
65 | * - minimum/maximum multiplier output clock frequency assuming the | ||
66 | * minimum/maximum N value | ||
67 | * - minimum/maximum combined N*P1 divisor | ||
68 | */ | ||
69 | mf_min = DIV_ROUND_UP(limits->m_min, pll->m); | ||
70 | mf_min = max(mf_min, limits->out_clock_min / | ||
71 | (pll->ext_clock / limits->n_min * pll->m)); | ||
72 | mf_min = max(mf_min, limits->n_min * limits->p1_min / div); | ||
73 | mf_max = limits->m_max / pll->m; | ||
74 | mf_max = min(mf_max, limits->out_clock_max / | ||
75 | (pll->ext_clock / limits->n_max * pll->m)); | ||
76 | mf_max = min(mf_max, DIV_ROUND_UP(limits->n_max * limits->p1_max, div)); | ||
77 | |||
78 | dev_dbg(dev, "pll: mf min %u max %u\n", mf_min, mf_max); | ||
79 | if (mf_min > mf_max) { | ||
80 | dev_err(dev, "pll: no valid combined N*P1 divisor.\n"); | ||
81 | return -EINVAL; | ||
82 | } | ||
83 | |||
84 | /* | ||
85 | * We're looking for the highest acceptable P1 value for which a | ||
86 | * multiplier factor MF exists that fulfills the following conditions: | ||
87 | * | ||
88 | * 1. p1 is in the [p1_min, p1_max] range given by the limits and is | ||
89 | * even | ||
90 | * 2. mf is in the [mf_min, mf_max] range computed above | ||
91 | * 3. div * mf is a multiple of p1, in order to compute | ||
92 | * n = div * mf / p1 | ||
93 | * m = pll->m * mf | ||
94 | * 4. the internal clock frequency, given by ext_clock / n, is in the | ||
95 | * [int_clock_min, int_clock_max] range given by the limits | ||
96 | * 5. the output clock frequency, given by ext_clock / n * m, is in the | ||
97 | * [out_clock_min, out_clock_max] range given by the limits | ||
98 | * | ||
99 | * The first naive approach is to iterate over all p1 values acceptable | ||
100 | * according to (1) and all mf values acceptable according to (2), and | ||
101 | * stop at the first combination that fulfills (3), (4) and (5). This | ||
102 | * has a O(n^2) complexity. | ||
103 | * | ||
104 | * Instead of iterating over all mf values in the [mf_min, mf_max] range | ||
105 | * we can compute the mf increment between two acceptable values | ||
106 | * according to (3) with | ||
107 | * | ||
108 | * mf_inc = p1 / gcd(div, p1) (6) | ||
109 | * | ||
110 | * and round the minimum up to the nearest multiple of mf_inc. This will | ||
111 | * restrict the number of mf values to be checked. | ||
112 | * | ||
113 | * Furthermore, conditions (4) and (5) only restrict the range of | ||
114 | * acceptable p1 and mf values by modifying the minimum and maximum | ||
115 | * limits. (5) can be expressed as | ||
116 | * | ||
117 | * ext_clock / (div * mf / p1) * m * mf >= out_clock_min | ||
118 | * ext_clock / (div * mf / p1) * m * mf <= out_clock_max | ||
119 | * | ||
120 | * or | ||
121 | * | ||
122 | * p1 >= out_clock_min * div / (ext_clock * m) (7) | ||
123 | * p1 <= out_clock_max * div / (ext_clock * m) | ||
124 | * | ||
125 | * Similarly, (4) can be expressed as | ||
126 | * | ||
127 | * mf >= ext_clock * p1 / (int_clock_max * div) (8) | ||
128 | * mf <= ext_clock * p1 / (int_clock_min * div) | ||
129 | * | ||
130 | * We can thus iterate over the restricted p1 range defined by the | ||
131 | * combination of (1) and (7), and then compute the restricted mf range | ||
132 | * defined by the combination of (2), (6) and (8). If the resulting mf | ||
133 | * range is not empty, any value in the mf range is acceptable. We thus | ||
134 | * select the mf lwoer bound and the corresponding p1 value. | ||
135 | */ | ||
136 | if (limits->p1_min == 0) { | ||
137 | dev_err(dev, "pll: P1 minimum value must be >0.\n"); | ||
138 | return -EINVAL; | ||
139 | } | ||
140 | |||
141 | p1_min = max(limits->p1_min, DIV_ROUND_UP(limits->out_clock_min * div, | ||
142 | pll->ext_clock * pll->m)); | ||
143 | p1_max = min(limits->p1_max, limits->out_clock_max * div / | ||
144 | (pll->ext_clock * pll->m)); | ||
145 | |||
146 | for (p1 = p1_max & ~1; p1 >= p1_min; p1 -= 2) { | ||
147 | unsigned int mf_inc = p1 / gcd(div, p1); | ||
148 | unsigned int mf_high; | ||
149 | unsigned int mf_low; | ||
150 | |||
151 | mf_low = max(roundup(mf_min, mf_inc), | ||
152 | DIV_ROUND_UP(pll->ext_clock * p1, | ||
153 | limits->int_clock_max * div)); | ||
154 | mf_high = min(mf_max, pll->ext_clock * p1 / | ||
155 | (limits->int_clock_min * div)); | ||
156 | |||
157 | if (mf_low > mf_high) | ||
158 | continue; | ||
159 | |||
160 | pll->n = div * mf_low / p1; | ||
161 | pll->m *= mf_low; | ||
162 | pll->p1 = p1; | ||
163 | dev_dbg(dev, "PLL: N %u M %u P1 %u\n", pll->n, pll->m, pll->p1); | ||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | dev_err(dev, "pll: no valid N and P1 divisors found.\n"); | ||
168 | return -EINVAL; | ||
169 | } | ||
170 | EXPORT_SYMBOL_GPL(aptina_pll_calculate); | ||
171 | |||
172 | MODULE_DESCRIPTION("Aptina PLL Helpers"); | ||
173 | MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); | ||
174 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/media/video/aptina-pll.h b/drivers/media/video/aptina-pll.h new file mode 100644 index 000000000000..b370e341e75d --- /dev/null +++ b/drivers/media/video/aptina-pll.h | |||
@@ -0,0 +1,56 @@ | |||
1 | /* | ||
2 | * Aptina Sensor PLL Configuration | ||
3 | * | ||
4 | * Copyright (C) 2012 Laurent Pinchart <laurent.pinchart@ideasonboard.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | */ | ||
20 | |||
21 | #ifndef __APTINA_PLL_H | ||
22 | #define __APTINA_PLL_H | ||
23 | |||
24 | struct aptina_pll { | ||
25 | unsigned int ext_clock; | ||
26 | unsigned int pix_clock; | ||
27 | |||
28 | unsigned int n; | ||
29 | unsigned int m; | ||
30 | unsigned int p1; | ||
31 | }; | ||
32 | |||
33 | struct aptina_pll_limits { | ||
34 | unsigned int ext_clock_min; | ||
35 | unsigned int ext_clock_max; | ||
36 | unsigned int int_clock_min; | ||
37 | unsigned int int_clock_max; | ||
38 | unsigned int out_clock_min; | ||
39 | unsigned int out_clock_max; | ||
40 | unsigned int pix_clock_max; | ||
41 | |||
42 | unsigned int n_min; | ||
43 | unsigned int n_max; | ||
44 | unsigned int m_min; | ||
45 | unsigned int m_max; | ||
46 | unsigned int p1_min; | ||
47 | unsigned int p1_max; | ||
48 | }; | ||
49 | |||
50 | struct device; | ||
51 | |||
52 | int aptina_pll_calculate(struct device *dev, | ||
53 | const struct aptina_pll_limits *limits, | ||
54 | struct aptina_pll *pll); | ||
55 | |||
56 | #endif /* __APTINA_PLL_H */ | ||
diff --git a/drivers/media/video/as3645a.c b/drivers/media/video/as3645a.c index f241702a0f36..7a3371f044fc 100644 --- a/drivers/media/video/as3645a.c +++ b/drivers/media/video/as3645a.c | |||
@@ -881,24 +881,7 @@ static struct i2c_driver as3645a_i2c_driver = { | |||
881 | .id_table = as3645a_id_table, | 881 | .id_table = as3645a_id_table, |
882 | }; | 882 | }; |
883 | 883 | ||
884 | static int __init as3645a_init(void) | 884 | module_i2c_driver(as3645a_i2c_driver); |
885 | { | ||
886 | int rval; | ||
887 | |||
888 | rval = i2c_add_driver(&as3645a_i2c_driver); | ||
889 | if (rval) | ||
890 | pr_err("%s: Failed to register the driver\n", AS3645A_NAME); | ||
891 | |||
892 | return rval; | ||
893 | } | ||
894 | |||
895 | static void __exit as3645a_exit(void) | ||
896 | { | ||
897 | i2c_del_driver(&as3645a_i2c_driver); | ||
898 | } | ||
899 | |||
900 | module_init(as3645a_init); | ||
901 | module_exit(as3645a_exit); | ||
902 | 885 | ||
903 | MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); | 886 | MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); |
904 | MODULE_DESCRIPTION("LED flash driver for AS3645A, LM3555 and their clones"); | 887 | MODULE_DESCRIPTION("LED flash driver for AS3645A, LM3555 and their clones"); |
diff --git a/drivers/media/video/blackfin/Kconfig b/drivers/media/video/blackfin/Kconfig new file mode 100644 index 000000000000..ecd5323768b7 --- /dev/null +++ b/drivers/media/video/blackfin/Kconfig | |||
@@ -0,0 +1,10 @@ | |||
1 | config VIDEO_BLACKFIN_CAPTURE | ||
2 | tristate "Blackfin Video Capture Driver" | ||
3 | depends on VIDEO_V4L2 && BLACKFIN && I2C | ||
4 | select VIDEOBUF2_DMA_CONTIG | ||
5 | help | ||
6 | V4L2 bridge driver for Blackfin video capture device. | ||
7 | Choose PPI or EPPI as its interface. | ||
8 | |||
9 | To compile this driver as a module, choose M here: the | ||
10 | module will be called bfin_video_capture. | ||
diff --git a/drivers/media/video/blackfin/Makefile b/drivers/media/video/blackfin/Makefile new file mode 100644 index 000000000000..aa3a0a216387 --- /dev/null +++ b/drivers/media/video/blackfin/Makefile | |||
@@ -0,0 +1,2 @@ | |||
1 | bfin_video_capture-objs := bfin_capture.o ppi.o | ||
2 | obj-$(CONFIG_VIDEO_BLACKFIN_CAPTURE) += bfin_video_capture.o | ||
diff --git a/drivers/media/video/blackfin/bfin_capture.c b/drivers/media/video/blackfin/bfin_capture.c new file mode 100644 index 000000000000..514fcf742f5a --- /dev/null +++ b/drivers/media/video/blackfin/bfin_capture.c | |||
@@ -0,0 +1,1059 @@ | |||
1 | /* | ||
2 | * Analog Devices video capture driver | ||
3 | * | ||
4 | * Copyright (c) 2011 Analog Devices Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/completion.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/errno.h> | ||
23 | #include <linux/fs.h> | ||
24 | #include <linux/i2c.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/io.h> | ||
28 | #include <linux/mm.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/platform_device.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <linux/time.h> | ||
33 | #include <linux/types.h> | ||
34 | |||
35 | #include <media/v4l2-chip-ident.h> | ||
36 | #include <media/v4l2-common.h> | ||
37 | #include <media/v4l2-ctrls.h> | ||
38 | #include <media/v4l2-device.h> | ||
39 | #include <media/v4l2-ioctl.h> | ||
40 | #include <media/videobuf2-dma-contig.h> | ||
41 | |||
42 | #include <asm/dma.h> | ||
43 | |||
44 | #include <media/blackfin/bfin_capture.h> | ||
45 | #include <media/blackfin/ppi.h> | ||
46 | |||
47 | #define CAPTURE_DRV_NAME "bfin_capture" | ||
48 | #define BCAP_MIN_NUM_BUF 2 | ||
49 | |||
50 | struct bcap_format { | ||
51 | char *desc; | ||
52 | u32 pixelformat; | ||
53 | enum v4l2_mbus_pixelcode mbus_code; | ||
54 | int bpp; /* bits per pixel */ | ||
55 | }; | ||
56 | |||
57 | struct bcap_buffer { | ||
58 | struct vb2_buffer vb; | ||
59 | struct list_head list; | ||
60 | }; | ||
61 | |||
62 | struct bcap_device { | ||
63 | /* capture device instance */ | ||
64 | struct v4l2_device v4l2_dev; | ||
65 | /* v4l2 control handler */ | ||
66 | struct v4l2_ctrl_handler ctrl_handler; | ||
67 | /* device node data */ | ||
68 | struct video_device *video_dev; | ||
69 | /* sub device instance */ | ||
70 | struct v4l2_subdev *sd; | ||
71 | /* capture config */ | ||
72 | struct bfin_capture_config *cfg; | ||
73 | /* ppi interface */ | ||
74 | struct ppi_if *ppi; | ||
75 | /* current input */ | ||
76 | unsigned int cur_input; | ||
77 | /* current selected standard */ | ||
78 | v4l2_std_id std; | ||
79 | /* used to store pixel format */ | ||
80 | struct v4l2_pix_format fmt; | ||
81 | /* bits per pixel*/ | ||
82 | int bpp; | ||
83 | /* used to store sensor supported format */ | ||
84 | struct bcap_format *sensor_formats; | ||
85 | /* number of sensor formats array */ | ||
86 | int num_sensor_formats; | ||
87 | /* pointing to current video buffer */ | ||
88 | struct bcap_buffer *cur_frm; | ||
89 | /* pointing to next video buffer */ | ||
90 | struct bcap_buffer *next_frm; | ||
91 | /* buffer queue used in videobuf2 */ | ||
92 | struct vb2_queue buffer_queue; | ||
93 | /* allocator-specific contexts for each plane */ | ||
94 | struct vb2_alloc_ctx *alloc_ctx; | ||
95 | /* queue of filled frames */ | ||
96 | struct list_head dma_queue; | ||
97 | /* used in videobuf2 callback */ | ||
98 | spinlock_t lock; | ||
99 | /* used to access capture device */ | ||
100 | struct mutex mutex; | ||
101 | /* used to wait ppi to complete one transfer */ | ||
102 | struct completion comp; | ||
103 | /* prepare to stop */ | ||
104 | bool stop; | ||
105 | }; | ||
106 | |||
107 | struct bcap_fh { | ||
108 | struct v4l2_fh fh; | ||
109 | /* indicates whether this file handle is doing IO */ | ||
110 | bool io_allowed; | ||
111 | }; | ||
112 | |||
113 | static const struct bcap_format bcap_formats[] = { | ||
114 | { | ||
115 | .desc = "YCbCr 4:2:2 Interleaved UYVY", | ||
116 | .pixelformat = V4L2_PIX_FMT_UYVY, | ||
117 | .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8, | ||
118 | .bpp = 16, | ||
119 | }, | ||
120 | { | ||
121 | .desc = "YCbCr 4:2:2 Interleaved YUYV", | ||
122 | .pixelformat = V4L2_PIX_FMT_YUYV, | ||
123 | .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, | ||
124 | .bpp = 16, | ||
125 | }, | ||
126 | { | ||
127 | .desc = "RGB 565", | ||
128 | .pixelformat = V4L2_PIX_FMT_RGB565, | ||
129 | .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE, | ||
130 | .bpp = 16, | ||
131 | }, | ||
132 | { | ||
133 | .desc = "RGB 444", | ||
134 | .pixelformat = V4L2_PIX_FMT_RGB444, | ||
135 | .mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE, | ||
136 | .bpp = 16, | ||
137 | }, | ||
138 | |||
139 | }; | ||
140 | #define BCAP_MAX_FMTS ARRAY_SIZE(bcap_formats) | ||
141 | |||
142 | static irqreturn_t bcap_isr(int irq, void *dev_id); | ||
143 | |||
144 | static struct bcap_buffer *to_bcap_vb(struct vb2_buffer *vb) | ||
145 | { | ||
146 | return container_of(vb, struct bcap_buffer, vb); | ||
147 | } | ||
148 | |||
149 | static int bcap_init_sensor_formats(struct bcap_device *bcap_dev) | ||
150 | { | ||
151 | enum v4l2_mbus_pixelcode code; | ||
152 | struct bcap_format *sf; | ||
153 | unsigned int num_formats = 0; | ||
154 | int i, j; | ||
155 | |||
156 | while (!v4l2_subdev_call(bcap_dev->sd, video, | ||
157 | enum_mbus_fmt, num_formats, &code)) | ||
158 | num_formats++; | ||
159 | if (!num_formats) | ||
160 | return -ENXIO; | ||
161 | |||
162 | sf = kzalloc(num_formats * sizeof(*sf), GFP_KERNEL); | ||
163 | if (!sf) | ||
164 | return -ENOMEM; | ||
165 | |||
166 | for (i = 0; i < num_formats; i++) { | ||
167 | v4l2_subdev_call(bcap_dev->sd, video, | ||
168 | enum_mbus_fmt, i, &code); | ||
169 | for (j = 0; j < BCAP_MAX_FMTS; j++) | ||
170 | if (code == bcap_formats[j].mbus_code) | ||
171 | break; | ||
172 | if (j == BCAP_MAX_FMTS) { | ||
173 | /* we don't allow this sensor working with our bridge */ | ||
174 | kfree(sf); | ||
175 | return -EINVAL; | ||
176 | } | ||
177 | sf[i] = bcap_formats[j]; | ||
178 | } | ||
179 | bcap_dev->sensor_formats = sf; | ||
180 | bcap_dev->num_sensor_formats = num_formats; | ||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static void bcap_free_sensor_formats(struct bcap_device *bcap_dev) | ||
185 | { | ||
186 | bcap_dev->num_sensor_formats = 0; | ||
187 | kfree(bcap_dev->sensor_formats); | ||
188 | bcap_dev->sensor_formats = NULL; | ||
189 | } | ||
190 | |||
191 | static int bcap_open(struct file *file) | ||
192 | { | ||
193 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
194 | struct video_device *vfd = bcap_dev->video_dev; | ||
195 | struct bcap_fh *bcap_fh; | ||
196 | |||
197 | if (!bcap_dev->sd) { | ||
198 | v4l2_err(&bcap_dev->v4l2_dev, "No sub device registered\n"); | ||
199 | return -ENODEV; | ||
200 | } | ||
201 | |||
202 | bcap_fh = kzalloc(sizeof(*bcap_fh), GFP_KERNEL); | ||
203 | if (!bcap_fh) { | ||
204 | v4l2_err(&bcap_dev->v4l2_dev, | ||
205 | "unable to allocate memory for file handle object\n"); | ||
206 | return -ENOMEM; | ||
207 | } | ||
208 | |||
209 | v4l2_fh_init(&bcap_fh->fh, vfd); | ||
210 | |||
211 | /* store pointer to v4l2_fh in private_data member of file */ | ||
212 | file->private_data = &bcap_fh->fh; | ||
213 | v4l2_fh_add(&bcap_fh->fh); | ||
214 | bcap_fh->io_allowed = false; | ||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static int bcap_release(struct file *file) | ||
219 | { | ||
220 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
221 | struct v4l2_fh *fh = file->private_data; | ||
222 | struct bcap_fh *bcap_fh = container_of(fh, struct bcap_fh, fh); | ||
223 | |||
224 | /* if this instance is doing IO */ | ||
225 | if (bcap_fh->io_allowed) | ||
226 | vb2_queue_release(&bcap_dev->buffer_queue); | ||
227 | |||
228 | file->private_data = NULL; | ||
229 | v4l2_fh_del(&bcap_fh->fh); | ||
230 | v4l2_fh_exit(&bcap_fh->fh); | ||
231 | kfree(bcap_fh); | ||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | static int bcap_mmap(struct file *file, struct vm_area_struct *vma) | ||
236 | { | ||
237 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
238 | |||
239 | return vb2_mmap(&bcap_dev->buffer_queue, vma); | ||
240 | } | ||
241 | |||
242 | #ifndef CONFIG_MMU | ||
243 | static unsigned long bcap_get_unmapped_area(struct file *file, | ||
244 | unsigned long addr, | ||
245 | unsigned long len, | ||
246 | unsigned long pgoff, | ||
247 | unsigned long flags) | ||
248 | { | ||
249 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
250 | |||
251 | return vb2_get_unmapped_area(&bcap_dev->buffer_queue, | ||
252 | addr, | ||
253 | len, | ||
254 | pgoff, | ||
255 | flags); | ||
256 | } | ||
257 | #endif | ||
258 | |||
259 | static unsigned int bcap_poll(struct file *file, poll_table *wait) | ||
260 | { | ||
261 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
262 | |||
263 | return vb2_poll(&bcap_dev->buffer_queue, file, wait); | ||
264 | } | ||
265 | |||
266 | static int bcap_queue_setup(struct vb2_queue *vq, | ||
267 | const struct v4l2_format *fmt, | ||
268 | unsigned int *nbuffers, unsigned int *nplanes, | ||
269 | unsigned int sizes[], void *alloc_ctxs[]) | ||
270 | { | ||
271 | struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); | ||
272 | |||
273 | if (*nbuffers < BCAP_MIN_NUM_BUF) | ||
274 | *nbuffers = BCAP_MIN_NUM_BUF; | ||
275 | |||
276 | *nplanes = 1; | ||
277 | sizes[0] = bcap_dev->fmt.sizeimage; | ||
278 | alloc_ctxs[0] = bcap_dev->alloc_ctx; | ||
279 | |||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static int bcap_buffer_init(struct vb2_buffer *vb) | ||
284 | { | ||
285 | struct bcap_buffer *buf = to_bcap_vb(vb); | ||
286 | |||
287 | INIT_LIST_HEAD(&buf->list); | ||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static int bcap_buffer_prepare(struct vb2_buffer *vb) | ||
292 | { | ||
293 | struct bcap_device *bcap_dev = vb2_get_drv_priv(vb->vb2_queue); | ||
294 | struct bcap_buffer *buf = to_bcap_vb(vb); | ||
295 | unsigned long size; | ||
296 | |||
297 | size = bcap_dev->fmt.sizeimage; | ||
298 | if (vb2_plane_size(vb, 0) < size) { | ||
299 | v4l2_err(&bcap_dev->v4l2_dev, "buffer too small (%lu < %lu)\n", | ||
300 | vb2_plane_size(vb, 0), size); | ||
301 | return -EINVAL; | ||
302 | } | ||
303 | vb2_set_plane_payload(&buf->vb, 0, size); | ||
304 | |||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static void bcap_buffer_queue(struct vb2_buffer *vb) | ||
309 | { | ||
310 | struct bcap_device *bcap_dev = vb2_get_drv_priv(vb->vb2_queue); | ||
311 | struct bcap_buffer *buf = to_bcap_vb(vb); | ||
312 | unsigned long flags; | ||
313 | |||
314 | spin_lock_irqsave(&bcap_dev->lock, flags); | ||
315 | list_add_tail(&buf->list, &bcap_dev->dma_queue); | ||
316 | spin_unlock_irqrestore(&bcap_dev->lock, flags); | ||
317 | } | ||
318 | |||
319 | static void bcap_buffer_cleanup(struct vb2_buffer *vb) | ||
320 | { | ||
321 | struct bcap_device *bcap_dev = vb2_get_drv_priv(vb->vb2_queue); | ||
322 | struct bcap_buffer *buf = to_bcap_vb(vb); | ||
323 | unsigned long flags; | ||
324 | |||
325 | spin_lock_irqsave(&bcap_dev->lock, flags); | ||
326 | list_del_init(&buf->list); | ||
327 | spin_unlock_irqrestore(&bcap_dev->lock, flags); | ||
328 | } | ||
329 | |||
330 | static void bcap_lock(struct vb2_queue *vq) | ||
331 | { | ||
332 | struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); | ||
333 | mutex_lock(&bcap_dev->mutex); | ||
334 | } | ||
335 | |||
336 | static void bcap_unlock(struct vb2_queue *vq) | ||
337 | { | ||
338 | struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); | ||
339 | mutex_unlock(&bcap_dev->mutex); | ||
340 | } | ||
341 | |||
342 | static int bcap_start_streaming(struct vb2_queue *vq, unsigned int count) | ||
343 | { | ||
344 | struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); | ||
345 | struct ppi_if *ppi = bcap_dev->ppi; | ||
346 | struct ppi_params params; | ||
347 | int ret; | ||
348 | |||
349 | /* enable streamon on the sub device */ | ||
350 | ret = v4l2_subdev_call(bcap_dev->sd, video, s_stream, 1); | ||
351 | if (ret && (ret != -ENOIOCTLCMD)) { | ||
352 | v4l2_err(&bcap_dev->v4l2_dev, "stream on failed in subdev\n"); | ||
353 | return ret; | ||
354 | } | ||
355 | |||
356 | /* set ppi params */ | ||
357 | params.width = bcap_dev->fmt.width; | ||
358 | params.height = bcap_dev->fmt.height; | ||
359 | params.bpp = bcap_dev->bpp; | ||
360 | params.ppi_control = bcap_dev->cfg->ppi_control; | ||
361 | params.int_mask = bcap_dev->cfg->int_mask; | ||
362 | params.blank_clocks = bcap_dev->cfg->blank_clocks; | ||
363 | ret = ppi->ops->set_params(ppi, ¶ms); | ||
364 | if (ret < 0) { | ||
365 | v4l2_err(&bcap_dev->v4l2_dev, | ||
366 | "Error in setting ppi params\n"); | ||
367 | return ret; | ||
368 | } | ||
369 | |||
370 | /* attach ppi DMA irq handler */ | ||
371 | ret = ppi->ops->attach_irq(ppi, bcap_isr); | ||
372 | if (ret < 0) { | ||
373 | v4l2_err(&bcap_dev->v4l2_dev, | ||
374 | "Error in attaching interrupt handler\n"); | ||
375 | return ret; | ||
376 | } | ||
377 | |||
378 | INIT_COMPLETION(bcap_dev->comp); | ||
379 | bcap_dev->stop = false; | ||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | static int bcap_stop_streaming(struct vb2_queue *vq) | ||
384 | { | ||
385 | struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); | ||
386 | struct ppi_if *ppi = bcap_dev->ppi; | ||
387 | int ret; | ||
388 | |||
389 | if (!vb2_is_streaming(vq)) | ||
390 | return 0; | ||
391 | |||
392 | bcap_dev->stop = true; | ||
393 | wait_for_completion(&bcap_dev->comp); | ||
394 | ppi->ops->stop(ppi); | ||
395 | ppi->ops->detach_irq(ppi); | ||
396 | ret = v4l2_subdev_call(bcap_dev->sd, video, s_stream, 0); | ||
397 | if (ret && (ret != -ENOIOCTLCMD)) | ||
398 | v4l2_err(&bcap_dev->v4l2_dev, | ||
399 | "stream off failed in subdev\n"); | ||
400 | |||
401 | /* release all active buffers */ | ||
402 | while (!list_empty(&bcap_dev->dma_queue)) { | ||
403 | bcap_dev->next_frm = list_entry(bcap_dev->dma_queue.next, | ||
404 | struct bcap_buffer, list); | ||
405 | list_del(&bcap_dev->next_frm->list); | ||
406 | vb2_buffer_done(&bcap_dev->next_frm->vb, VB2_BUF_STATE_ERROR); | ||
407 | } | ||
408 | return 0; | ||
409 | } | ||
410 | |||
411 | static struct vb2_ops bcap_video_qops = { | ||
412 | .queue_setup = bcap_queue_setup, | ||
413 | .buf_init = bcap_buffer_init, | ||
414 | .buf_prepare = bcap_buffer_prepare, | ||
415 | .buf_cleanup = bcap_buffer_cleanup, | ||
416 | .buf_queue = bcap_buffer_queue, | ||
417 | .wait_prepare = bcap_unlock, | ||
418 | .wait_finish = bcap_lock, | ||
419 | .start_streaming = bcap_start_streaming, | ||
420 | .stop_streaming = bcap_stop_streaming, | ||
421 | }; | ||
422 | |||
423 | static int bcap_reqbufs(struct file *file, void *priv, | ||
424 | struct v4l2_requestbuffers *req_buf) | ||
425 | { | ||
426 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
427 | struct vb2_queue *vq = &bcap_dev->buffer_queue; | ||
428 | struct v4l2_fh *fh = file->private_data; | ||
429 | struct bcap_fh *bcap_fh = container_of(fh, struct bcap_fh, fh); | ||
430 | |||
431 | if (vb2_is_busy(vq)) | ||
432 | return -EBUSY; | ||
433 | |||
434 | bcap_fh->io_allowed = true; | ||
435 | |||
436 | return vb2_reqbufs(vq, req_buf); | ||
437 | } | ||
438 | |||
439 | static int bcap_querybuf(struct file *file, void *priv, | ||
440 | struct v4l2_buffer *buf) | ||
441 | { | ||
442 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
443 | |||
444 | return vb2_querybuf(&bcap_dev->buffer_queue, buf); | ||
445 | } | ||
446 | |||
447 | static int bcap_qbuf(struct file *file, void *priv, | ||
448 | struct v4l2_buffer *buf) | ||
449 | { | ||
450 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
451 | struct v4l2_fh *fh = file->private_data; | ||
452 | struct bcap_fh *bcap_fh = container_of(fh, struct bcap_fh, fh); | ||
453 | |||
454 | if (!bcap_fh->io_allowed) | ||
455 | return -EBUSY; | ||
456 | |||
457 | return vb2_qbuf(&bcap_dev->buffer_queue, buf); | ||
458 | } | ||
459 | |||
460 | static int bcap_dqbuf(struct file *file, void *priv, | ||
461 | struct v4l2_buffer *buf) | ||
462 | { | ||
463 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
464 | struct v4l2_fh *fh = file->private_data; | ||
465 | struct bcap_fh *bcap_fh = container_of(fh, struct bcap_fh, fh); | ||
466 | |||
467 | if (!bcap_fh->io_allowed) | ||
468 | return -EBUSY; | ||
469 | |||
470 | return vb2_dqbuf(&bcap_dev->buffer_queue, | ||
471 | buf, file->f_flags & O_NONBLOCK); | ||
472 | } | ||
473 | |||
474 | static irqreturn_t bcap_isr(int irq, void *dev_id) | ||
475 | { | ||
476 | struct ppi_if *ppi = dev_id; | ||
477 | struct bcap_device *bcap_dev = ppi->priv; | ||
478 | struct timeval timevalue; | ||
479 | struct vb2_buffer *vb = &bcap_dev->cur_frm->vb; | ||
480 | dma_addr_t addr; | ||
481 | |||
482 | spin_lock(&bcap_dev->lock); | ||
483 | |||
484 | if (bcap_dev->cur_frm != bcap_dev->next_frm) { | ||
485 | do_gettimeofday(&timevalue); | ||
486 | vb->v4l2_buf.timestamp = timevalue; | ||
487 | vb2_buffer_done(vb, VB2_BUF_STATE_DONE); | ||
488 | bcap_dev->cur_frm = bcap_dev->next_frm; | ||
489 | } | ||
490 | |||
491 | ppi->ops->stop(ppi); | ||
492 | |||
493 | if (bcap_dev->stop) { | ||
494 | complete(&bcap_dev->comp); | ||
495 | } else { | ||
496 | if (!list_empty(&bcap_dev->dma_queue)) { | ||
497 | bcap_dev->next_frm = list_entry(bcap_dev->dma_queue.next, | ||
498 | struct bcap_buffer, list); | ||
499 | list_del(&bcap_dev->next_frm->list); | ||
500 | addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->next_frm->vb, 0); | ||
501 | ppi->ops->update_addr(ppi, (unsigned long)addr); | ||
502 | } | ||
503 | ppi->ops->start(ppi); | ||
504 | } | ||
505 | |||
506 | spin_unlock(&bcap_dev->lock); | ||
507 | |||
508 | return IRQ_HANDLED; | ||
509 | } | ||
510 | |||
511 | static int bcap_streamon(struct file *file, void *priv, | ||
512 | enum v4l2_buf_type buf_type) | ||
513 | { | ||
514 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
515 | struct bcap_fh *fh = file->private_data; | ||
516 | struct ppi_if *ppi = bcap_dev->ppi; | ||
517 | dma_addr_t addr; | ||
518 | int ret; | ||
519 | |||
520 | if (!fh->io_allowed) | ||
521 | return -EBUSY; | ||
522 | |||
523 | /* call streamon to start streaming in videobuf */ | ||
524 | ret = vb2_streamon(&bcap_dev->buffer_queue, buf_type); | ||
525 | if (ret) | ||
526 | return ret; | ||
527 | |||
528 | /* if dma queue is empty, return error */ | ||
529 | if (list_empty(&bcap_dev->dma_queue)) { | ||
530 | v4l2_err(&bcap_dev->v4l2_dev, "dma queue is empty\n"); | ||
531 | ret = -EINVAL; | ||
532 | goto err; | ||
533 | } | ||
534 | |||
535 | /* get the next frame from the dma queue */ | ||
536 | bcap_dev->next_frm = list_entry(bcap_dev->dma_queue.next, | ||
537 | struct bcap_buffer, list); | ||
538 | bcap_dev->cur_frm = bcap_dev->next_frm; | ||
539 | /* remove buffer from the dma queue */ | ||
540 | list_del(&bcap_dev->cur_frm->list); | ||
541 | addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb, 0); | ||
542 | /* update DMA address */ | ||
543 | ppi->ops->update_addr(ppi, (unsigned long)addr); | ||
544 | /* enable ppi */ | ||
545 | ppi->ops->start(ppi); | ||
546 | |||
547 | return 0; | ||
548 | err: | ||
549 | vb2_streamoff(&bcap_dev->buffer_queue, buf_type); | ||
550 | return ret; | ||
551 | } | ||
552 | |||
553 | static int bcap_streamoff(struct file *file, void *priv, | ||
554 | enum v4l2_buf_type buf_type) | ||
555 | { | ||
556 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
557 | struct bcap_fh *fh = file->private_data; | ||
558 | |||
559 | if (!fh->io_allowed) | ||
560 | return -EBUSY; | ||
561 | |||
562 | return vb2_streamoff(&bcap_dev->buffer_queue, buf_type); | ||
563 | } | ||
564 | |||
565 | static int bcap_querystd(struct file *file, void *priv, v4l2_std_id *std) | ||
566 | { | ||
567 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
568 | |||
569 | return v4l2_subdev_call(bcap_dev->sd, video, querystd, std); | ||
570 | } | ||
571 | |||
572 | static int bcap_g_std(struct file *file, void *priv, v4l2_std_id *std) | ||
573 | { | ||
574 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
575 | |||
576 | *std = bcap_dev->std; | ||
577 | return 0; | ||
578 | } | ||
579 | |||
580 | static int bcap_s_std(struct file *file, void *priv, v4l2_std_id *std) | ||
581 | { | ||
582 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
583 | int ret; | ||
584 | |||
585 | if (vb2_is_busy(&bcap_dev->buffer_queue)) | ||
586 | return -EBUSY; | ||
587 | |||
588 | ret = v4l2_subdev_call(bcap_dev->sd, core, s_std, *std); | ||
589 | if (ret < 0) | ||
590 | return ret; | ||
591 | |||
592 | bcap_dev->std = *std; | ||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | static int bcap_enum_input(struct file *file, void *priv, | ||
597 | struct v4l2_input *input) | ||
598 | { | ||
599 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
600 | struct bfin_capture_config *config = bcap_dev->cfg; | ||
601 | int ret; | ||
602 | u32 status; | ||
603 | |||
604 | if (input->index >= config->num_inputs) | ||
605 | return -EINVAL; | ||
606 | |||
607 | *input = config->inputs[input->index]; | ||
608 | /* get input status */ | ||
609 | ret = v4l2_subdev_call(bcap_dev->sd, video, g_input_status, &status); | ||
610 | if (!ret) | ||
611 | input->status = status; | ||
612 | return 0; | ||
613 | } | ||
614 | |||
615 | static int bcap_g_input(struct file *file, void *priv, unsigned int *index) | ||
616 | { | ||
617 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
618 | |||
619 | *index = bcap_dev->cur_input; | ||
620 | return 0; | ||
621 | } | ||
622 | |||
623 | static int bcap_s_input(struct file *file, void *priv, unsigned int index) | ||
624 | { | ||
625 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
626 | struct bfin_capture_config *config = bcap_dev->cfg; | ||
627 | struct bcap_route *route; | ||
628 | int ret; | ||
629 | |||
630 | if (vb2_is_busy(&bcap_dev->buffer_queue)) | ||
631 | return -EBUSY; | ||
632 | |||
633 | if (index >= config->num_inputs) | ||
634 | return -EINVAL; | ||
635 | |||
636 | route = &config->routes[index]; | ||
637 | ret = v4l2_subdev_call(bcap_dev->sd, video, s_routing, | ||
638 | route->input, route->output, 0); | ||
639 | if ((ret < 0) && (ret != -ENOIOCTLCMD)) { | ||
640 | v4l2_err(&bcap_dev->v4l2_dev, "Failed to set input\n"); | ||
641 | return ret; | ||
642 | } | ||
643 | bcap_dev->cur_input = index; | ||
644 | return 0; | ||
645 | } | ||
646 | |||
647 | static int bcap_try_format(struct bcap_device *bcap, | ||
648 | struct v4l2_pix_format *pixfmt, | ||
649 | enum v4l2_mbus_pixelcode *mbus_code, | ||
650 | int *bpp) | ||
651 | { | ||
652 | struct bcap_format *sf = bcap->sensor_formats; | ||
653 | struct bcap_format *fmt = NULL; | ||
654 | struct v4l2_mbus_framefmt mbus_fmt; | ||
655 | int ret, i; | ||
656 | |||
657 | for (i = 0; i < bcap->num_sensor_formats; i++) { | ||
658 | fmt = &sf[i]; | ||
659 | if (pixfmt->pixelformat == fmt->pixelformat) | ||
660 | break; | ||
661 | } | ||
662 | if (i == bcap->num_sensor_formats) | ||
663 | fmt = &sf[0]; | ||
664 | |||
665 | if (mbus_code) | ||
666 | *mbus_code = fmt->mbus_code; | ||
667 | if (bpp) | ||
668 | *bpp = fmt->bpp; | ||
669 | v4l2_fill_mbus_format(&mbus_fmt, pixfmt, fmt->mbus_code); | ||
670 | ret = v4l2_subdev_call(bcap->sd, video, | ||
671 | try_mbus_fmt, &mbus_fmt); | ||
672 | if (ret < 0) | ||
673 | return ret; | ||
674 | v4l2_fill_pix_format(pixfmt, &mbus_fmt); | ||
675 | pixfmt->bytesperline = pixfmt->width * fmt->bpp / 8; | ||
676 | pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height; | ||
677 | return 0; | ||
678 | } | ||
679 | |||
680 | static int bcap_enum_fmt_vid_cap(struct file *file, void *priv, | ||
681 | struct v4l2_fmtdesc *fmt) | ||
682 | { | ||
683 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
684 | struct bcap_format *sf = bcap_dev->sensor_formats; | ||
685 | |||
686 | if (fmt->index >= bcap_dev->num_sensor_formats) | ||
687 | return -EINVAL; | ||
688 | |||
689 | fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
690 | strlcpy(fmt->description, | ||
691 | sf[fmt->index].desc, | ||
692 | sizeof(fmt->description)); | ||
693 | fmt->pixelformat = sf[fmt->index].pixelformat; | ||
694 | return 0; | ||
695 | } | ||
696 | |||
697 | static int bcap_try_fmt_vid_cap(struct file *file, void *priv, | ||
698 | struct v4l2_format *fmt) | ||
699 | { | ||
700 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
701 | struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; | ||
702 | |||
703 | return bcap_try_format(bcap_dev, pixfmt, NULL, NULL); | ||
704 | } | ||
705 | |||
706 | static int bcap_g_fmt_vid_cap(struct file *file, void *priv, | ||
707 | struct v4l2_format *fmt) | ||
708 | { | ||
709 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
710 | |||
711 | fmt->fmt.pix = bcap_dev->fmt; | ||
712 | return 0; | ||
713 | } | ||
714 | |||
715 | static int bcap_s_fmt_vid_cap(struct file *file, void *priv, | ||
716 | struct v4l2_format *fmt) | ||
717 | { | ||
718 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
719 | struct v4l2_mbus_framefmt mbus_fmt; | ||
720 | enum v4l2_mbus_pixelcode mbus_code; | ||
721 | struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; | ||
722 | int ret, bpp; | ||
723 | |||
724 | if (vb2_is_busy(&bcap_dev->buffer_queue)) | ||
725 | return -EBUSY; | ||
726 | |||
727 | /* see if format works */ | ||
728 | ret = bcap_try_format(bcap_dev, pixfmt, &mbus_code, &bpp); | ||
729 | if (ret < 0) | ||
730 | return ret; | ||
731 | |||
732 | v4l2_fill_mbus_format(&mbus_fmt, pixfmt, mbus_code); | ||
733 | ret = v4l2_subdev_call(bcap_dev->sd, video, s_mbus_fmt, &mbus_fmt); | ||
734 | if (ret < 0) | ||
735 | return ret; | ||
736 | bcap_dev->fmt = *pixfmt; | ||
737 | bcap_dev->bpp = bpp; | ||
738 | return 0; | ||
739 | } | ||
740 | |||
741 | static int bcap_querycap(struct file *file, void *priv, | ||
742 | struct v4l2_capability *cap) | ||
743 | { | ||
744 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
745 | |||
746 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; | ||
747 | strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver)); | ||
748 | strlcpy(cap->bus_info, "Blackfin Platform", sizeof(cap->bus_info)); | ||
749 | strlcpy(cap->card, bcap_dev->cfg->card_name, sizeof(cap->card)); | ||
750 | return 0; | ||
751 | } | ||
752 | |||
753 | static int bcap_g_parm(struct file *file, void *fh, | ||
754 | struct v4l2_streamparm *a) | ||
755 | { | ||
756 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
757 | |||
758 | if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
759 | return -EINVAL; | ||
760 | return v4l2_subdev_call(bcap_dev->sd, video, g_parm, a); | ||
761 | } | ||
762 | |||
763 | static int bcap_s_parm(struct file *file, void *fh, | ||
764 | struct v4l2_streamparm *a) | ||
765 | { | ||
766 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
767 | |||
768 | if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
769 | return -EINVAL; | ||
770 | return v4l2_subdev_call(bcap_dev->sd, video, s_parm, a); | ||
771 | } | ||
772 | |||
773 | static int bcap_g_chip_ident(struct file *file, void *priv, | ||
774 | struct v4l2_dbg_chip_ident *chip) | ||
775 | { | ||
776 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
777 | |||
778 | chip->ident = V4L2_IDENT_NONE; | ||
779 | chip->revision = 0; | ||
780 | if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && | ||
781 | chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) | ||
782 | return -EINVAL; | ||
783 | |||
784 | return v4l2_subdev_call(bcap_dev->sd, core, | ||
785 | g_chip_ident, chip); | ||
786 | } | ||
787 | |||
788 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
789 | static int bcap_dbg_g_register(struct file *file, void *priv, | ||
790 | struct v4l2_dbg_register *reg) | ||
791 | { | ||
792 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
793 | |||
794 | return v4l2_subdev_call(bcap_dev->sd, core, | ||
795 | g_register, reg); | ||
796 | } | ||
797 | |||
798 | static int bcap_dbg_s_register(struct file *file, void *priv, | ||
799 | struct v4l2_dbg_register *reg) | ||
800 | { | ||
801 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
802 | |||
803 | return v4l2_subdev_call(bcap_dev->sd, core, | ||
804 | s_register, reg); | ||
805 | } | ||
806 | #endif | ||
807 | |||
808 | static int bcap_log_status(struct file *file, void *priv) | ||
809 | { | ||
810 | struct bcap_device *bcap_dev = video_drvdata(file); | ||
811 | /* status for sub devices */ | ||
812 | v4l2_device_call_all(&bcap_dev->v4l2_dev, 0, core, log_status); | ||
813 | return 0; | ||
814 | } | ||
815 | |||
816 | static const struct v4l2_ioctl_ops bcap_ioctl_ops = { | ||
817 | .vidioc_querycap = bcap_querycap, | ||
818 | .vidioc_g_fmt_vid_cap = bcap_g_fmt_vid_cap, | ||
819 | .vidioc_enum_fmt_vid_cap = bcap_enum_fmt_vid_cap, | ||
820 | .vidioc_s_fmt_vid_cap = bcap_s_fmt_vid_cap, | ||
821 | .vidioc_try_fmt_vid_cap = bcap_try_fmt_vid_cap, | ||
822 | .vidioc_enum_input = bcap_enum_input, | ||
823 | .vidioc_g_input = bcap_g_input, | ||
824 | .vidioc_s_input = bcap_s_input, | ||
825 | .vidioc_querystd = bcap_querystd, | ||
826 | .vidioc_s_std = bcap_s_std, | ||
827 | .vidioc_g_std = bcap_g_std, | ||
828 | .vidioc_reqbufs = bcap_reqbufs, | ||
829 | .vidioc_querybuf = bcap_querybuf, | ||
830 | .vidioc_qbuf = bcap_qbuf, | ||
831 | .vidioc_dqbuf = bcap_dqbuf, | ||
832 | .vidioc_streamon = bcap_streamon, | ||
833 | .vidioc_streamoff = bcap_streamoff, | ||
834 | .vidioc_g_parm = bcap_g_parm, | ||
835 | .vidioc_s_parm = bcap_s_parm, | ||
836 | .vidioc_g_chip_ident = bcap_g_chip_ident, | ||
837 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
838 | .vidioc_g_register = bcap_dbg_g_register, | ||
839 | .vidioc_s_register = bcap_dbg_s_register, | ||
840 | #endif | ||
841 | .vidioc_log_status = bcap_log_status, | ||
842 | }; | ||
843 | |||
844 | static struct v4l2_file_operations bcap_fops = { | ||
845 | .owner = THIS_MODULE, | ||
846 | .open = bcap_open, | ||
847 | .release = bcap_release, | ||
848 | .unlocked_ioctl = video_ioctl2, | ||
849 | .mmap = bcap_mmap, | ||
850 | #ifndef CONFIG_MMU | ||
851 | .get_unmapped_area = bcap_get_unmapped_area, | ||
852 | #endif | ||
853 | .poll = bcap_poll | ||
854 | }; | ||
855 | |||
856 | static int __devinit bcap_probe(struct platform_device *pdev) | ||
857 | { | ||
858 | struct bcap_device *bcap_dev; | ||
859 | struct video_device *vfd; | ||
860 | struct i2c_adapter *i2c_adap; | ||
861 | struct bfin_capture_config *config; | ||
862 | struct vb2_queue *q; | ||
863 | int ret; | ||
864 | |||
865 | config = pdev->dev.platform_data; | ||
866 | if (!config) { | ||
867 | v4l2_err(pdev->dev.driver, "Unable to get board config\n"); | ||
868 | return -ENODEV; | ||
869 | } | ||
870 | |||
871 | bcap_dev = kzalloc(sizeof(*bcap_dev), GFP_KERNEL); | ||
872 | if (!bcap_dev) { | ||
873 | v4l2_err(pdev->dev.driver, "Unable to alloc bcap_dev\n"); | ||
874 | return -ENOMEM; | ||
875 | } | ||
876 | |||
877 | bcap_dev->cfg = config; | ||
878 | |||
879 | bcap_dev->ppi = ppi_create_instance(config->ppi_info); | ||
880 | if (!bcap_dev->ppi) { | ||
881 | v4l2_err(pdev->dev.driver, "Unable to create ppi\n"); | ||
882 | ret = -ENODEV; | ||
883 | goto err_free_dev; | ||
884 | } | ||
885 | bcap_dev->ppi->priv = bcap_dev; | ||
886 | |||
887 | bcap_dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); | ||
888 | if (IS_ERR(bcap_dev->alloc_ctx)) { | ||
889 | ret = PTR_ERR(bcap_dev->alloc_ctx); | ||
890 | goto err_free_ppi; | ||
891 | } | ||
892 | |||
893 | vfd = video_device_alloc(); | ||
894 | if (!vfd) { | ||
895 | ret = -ENOMEM; | ||
896 | v4l2_err(pdev->dev.driver, "Unable to alloc video device\n"); | ||
897 | goto err_cleanup_ctx; | ||
898 | } | ||
899 | |||
900 | /* initialize field of video device */ | ||
901 | vfd->release = video_device_release; | ||
902 | vfd->fops = &bcap_fops; | ||
903 | vfd->ioctl_ops = &bcap_ioctl_ops; | ||
904 | vfd->tvnorms = 0; | ||
905 | vfd->v4l2_dev = &bcap_dev->v4l2_dev; | ||
906 | set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); | ||
907 | strncpy(vfd->name, CAPTURE_DRV_NAME, sizeof(vfd->name)); | ||
908 | bcap_dev->video_dev = vfd; | ||
909 | |||
910 | ret = v4l2_device_register(&pdev->dev, &bcap_dev->v4l2_dev); | ||
911 | if (ret) { | ||
912 | v4l2_err(pdev->dev.driver, | ||
913 | "Unable to register v4l2 device\n"); | ||
914 | goto err_release_vdev; | ||
915 | } | ||
916 | v4l2_info(&bcap_dev->v4l2_dev, "v4l2 device registered\n"); | ||
917 | |||
918 | bcap_dev->v4l2_dev.ctrl_handler = &bcap_dev->ctrl_handler; | ||
919 | ret = v4l2_ctrl_handler_init(&bcap_dev->ctrl_handler, 0); | ||
920 | if (ret) { | ||
921 | v4l2_err(&bcap_dev->v4l2_dev, | ||
922 | "Unable to init control handler\n"); | ||
923 | goto err_unreg_v4l2; | ||
924 | } | ||
925 | |||
926 | spin_lock_init(&bcap_dev->lock); | ||
927 | /* initialize queue */ | ||
928 | q = &bcap_dev->buffer_queue; | ||
929 | q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
930 | q->io_modes = VB2_MMAP; | ||
931 | q->drv_priv = bcap_dev; | ||
932 | q->buf_struct_size = sizeof(struct bcap_buffer); | ||
933 | q->ops = &bcap_video_qops; | ||
934 | q->mem_ops = &vb2_dma_contig_memops; | ||
935 | |||
936 | vb2_queue_init(q); | ||
937 | |||
938 | mutex_init(&bcap_dev->mutex); | ||
939 | init_completion(&bcap_dev->comp); | ||
940 | |||
941 | /* init video dma queues */ | ||
942 | INIT_LIST_HEAD(&bcap_dev->dma_queue); | ||
943 | |||
944 | vfd->lock = &bcap_dev->mutex; | ||
945 | |||
946 | /* register video device */ | ||
947 | ret = video_register_device(bcap_dev->video_dev, VFL_TYPE_GRABBER, -1); | ||
948 | if (ret) { | ||
949 | v4l2_err(&bcap_dev->v4l2_dev, | ||
950 | "Unable to register video device\n"); | ||
951 | goto err_free_handler; | ||
952 | } | ||
953 | video_set_drvdata(bcap_dev->video_dev, bcap_dev); | ||
954 | v4l2_info(&bcap_dev->v4l2_dev, "video device registered as: %s\n", | ||
955 | video_device_node_name(vfd)); | ||
956 | |||
957 | /* load up the subdevice */ | ||
958 | i2c_adap = i2c_get_adapter(config->i2c_adapter_id); | ||
959 | if (!i2c_adap) { | ||
960 | v4l2_err(&bcap_dev->v4l2_dev, | ||
961 | "Unable to find i2c adapter\n"); | ||
962 | goto err_unreg_vdev; | ||
963 | |||
964 | } | ||
965 | bcap_dev->sd = v4l2_i2c_new_subdev_board(&bcap_dev->v4l2_dev, | ||
966 | i2c_adap, | ||
967 | &config->board_info, | ||
968 | NULL); | ||
969 | if (bcap_dev->sd) { | ||
970 | int i; | ||
971 | /* update tvnorms from the sub devices */ | ||
972 | for (i = 0; i < config->num_inputs; i++) | ||
973 | vfd->tvnorms |= config->inputs[i].std; | ||
974 | } else { | ||
975 | v4l2_err(&bcap_dev->v4l2_dev, | ||
976 | "Unable to register sub device\n"); | ||
977 | goto err_unreg_vdev; | ||
978 | } | ||
979 | |||
980 | v4l2_info(&bcap_dev->v4l2_dev, "v4l2 sub device registered\n"); | ||
981 | |||
982 | /* now we can probe the default state */ | ||
983 | if (vfd->tvnorms) { | ||
984 | v4l2_std_id std; | ||
985 | ret = v4l2_subdev_call(bcap_dev->sd, core, g_std, &std); | ||
986 | if (ret) { | ||
987 | v4l2_err(&bcap_dev->v4l2_dev, | ||
988 | "Unable to get std\n"); | ||
989 | goto err_unreg_vdev; | ||
990 | } | ||
991 | bcap_dev->std = std; | ||
992 | } | ||
993 | ret = bcap_init_sensor_formats(bcap_dev); | ||
994 | if (ret) { | ||
995 | v4l2_err(&bcap_dev->v4l2_dev, | ||
996 | "Unable to create sensor formats table\n"); | ||
997 | goto err_unreg_vdev; | ||
998 | } | ||
999 | return 0; | ||
1000 | err_unreg_vdev: | ||
1001 | video_unregister_device(bcap_dev->video_dev); | ||
1002 | bcap_dev->video_dev = NULL; | ||
1003 | err_free_handler: | ||
1004 | v4l2_ctrl_handler_free(&bcap_dev->ctrl_handler); | ||
1005 | err_unreg_v4l2: | ||
1006 | v4l2_device_unregister(&bcap_dev->v4l2_dev); | ||
1007 | err_release_vdev: | ||
1008 | if (bcap_dev->video_dev) | ||
1009 | video_device_release(bcap_dev->video_dev); | ||
1010 | err_cleanup_ctx: | ||
1011 | vb2_dma_contig_cleanup_ctx(bcap_dev->alloc_ctx); | ||
1012 | err_free_ppi: | ||
1013 | ppi_delete_instance(bcap_dev->ppi); | ||
1014 | err_free_dev: | ||
1015 | kfree(bcap_dev); | ||
1016 | return ret; | ||
1017 | } | ||
1018 | |||
1019 | static int __devexit bcap_remove(struct platform_device *pdev) | ||
1020 | { | ||
1021 | struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); | ||
1022 | struct bcap_device *bcap_dev = container_of(v4l2_dev, | ||
1023 | struct bcap_device, v4l2_dev); | ||
1024 | |||
1025 | bcap_free_sensor_formats(bcap_dev); | ||
1026 | video_unregister_device(bcap_dev->video_dev); | ||
1027 | v4l2_ctrl_handler_free(&bcap_dev->ctrl_handler); | ||
1028 | v4l2_device_unregister(v4l2_dev); | ||
1029 | vb2_dma_contig_cleanup_ctx(bcap_dev->alloc_ctx); | ||
1030 | ppi_delete_instance(bcap_dev->ppi); | ||
1031 | kfree(bcap_dev); | ||
1032 | return 0; | ||
1033 | } | ||
1034 | |||
1035 | static struct platform_driver bcap_driver = { | ||
1036 | .driver = { | ||
1037 | .name = CAPTURE_DRV_NAME, | ||
1038 | .owner = THIS_MODULE, | ||
1039 | }, | ||
1040 | .probe = bcap_probe, | ||
1041 | .remove = __devexit_p(bcap_remove), | ||
1042 | }; | ||
1043 | |||
1044 | static __init int bcap_init(void) | ||
1045 | { | ||
1046 | return platform_driver_register(&bcap_driver); | ||
1047 | } | ||
1048 | |||
1049 | static __exit void bcap_exit(void) | ||
1050 | { | ||
1051 | platform_driver_unregister(&bcap_driver); | ||
1052 | } | ||
1053 | |||
1054 | module_init(bcap_init); | ||
1055 | module_exit(bcap_exit); | ||
1056 | |||
1057 | MODULE_DESCRIPTION("Analog Devices blackfin video capture driver"); | ||
1058 | MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>"); | ||
1059 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/media/video/blackfin/ppi.c b/drivers/media/video/blackfin/ppi.c new file mode 100644 index 000000000000..d29592186b02 --- /dev/null +++ b/drivers/media/video/blackfin/ppi.c | |||
@@ -0,0 +1,271 @@ | |||
1 | /* | ||
2 | * ppi.c Analog Devices Parallel Peripheral Interface driver | ||
3 | * | ||
4 | * Copyright (c) 2011 Analog Devices Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/slab.h> | ||
21 | |||
22 | #include <asm/bfin_ppi.h> | ||
23 | #include <asm/blackfin.h> | ||
24 | #include <asm/cacheflush.h> | ||
25 | #include <asm/dma.h> | ||
26 | #include <asm/portmux.h> | ||
27 | |||
28 | #include <media/blackfin/ppi.h> | ||
29 | |||
30 | static int ppi_attach_irq(struct ppi_if *ppi, irq_handler_t handler); | ||
31 | static void ppi_detach_irq(struct ppi_if *ppi); | ||
32 | static int ppi_start(struct ppi_if *ppi); | ||
33 | static int ppi_stop(struct ppi_if *ppi); | ||
34 | static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params); | ||
35 | static void ppi_update_addr(struct ppi_if *ppi, unsigned long addr); | ||
36 | |||
37 | static const struct ppi_ops ppi_ops = { | ||
38 | .attach_irq = ppi_attach_irq, | ||
39 | .detach_irq = ppi_detach_irq, | ||
40 | .start = ppi_start, | ||
41 | .stop = ppi_stop, | ||
42 | .set_params = ppi_set_params, | ||
43 | .update_addr = ppi_update_addr, | ||
44 | }; | ||
45 | |||
46 | static irqreturn_t ppi_irq_err(int irq, void *dev_id) | ||
47 | { | ||
48 | struct ppi_if *ppi = dev_id; | ||
49 | const struct ppi_info *info = ppi->info; | ||
50 | |||
51 | switch (info->type) { | ||
52 | case PPI_TYPE_PPI: | ||
53 | { | ||
54 | struct bfin_ppi_regs *reg = info->base; | ||
55 | unsigned short status; | ||
56 | |||
57 | /* register on bf561 is cleared when read | ||
58 | * others are W1C | ||
59 | */ | ||
60 | status = bfin_read16(®->status); | ||
61 | bfin_write16(®->status, 0xff00); | ||
62 | break; | ||
63 | } | ||
64 | case PPI_TYPE_EPPI: | ||
65 | { | ||
66 | struct bfin_eppi_regs *reg = info->base; | ||
67 | bfin_write16(®->status, 0xffff); | ||
68 | break; | ||
69 | } | ||
70 | default: | ||
71 | break; | ||
72 | } | ||
73 | |||
74 | return IRQ_HANDLED; | ||
75 | } | ||
76 | |||
77 | static int ppi_attach_irq(struct ppi_if *ppi, irq_handler_t handler) | ||
78 | { | ||
79 | const struct ppi_info *info = ppi->info; | ||
80 | int ret; | ||
81 | |||
82 | ret = request_dma(info->dma_ch, "PPI_DMA"); | ||
83 | |||
84 | if (ret) { | ||
85 | pr_err("Unable to allocate DMA channel for PPI\n"); | ||
86 | return ret; | ||
87 | } | ||
88 | set_dma_callback(info->dma_ch, handler, ppi); | ||
89 | |||
90 | if (ppi->err_int) { | ||
91 | ret = request_irq(info->irq_err, ppi_irq_err, 0, "PPI ERROR", ppi); | ||
92 | if (ret) { | ||
93 | pr_err("Unable to allocate IRQ for PPI\n"); | ||
94 | free_dma(info->dma_ch); | ||
95 | } | ||
96 | } | ||
97 | return ret; | ||
98 | } | ||
99 | |||
100 | static void ppi_detach_irq(struct ppi_if *ppi) | ||
101 | { | ||
102 | const struct ppi_info *info = ppi->info; | ||
103 | |||
104 | if (ppi->err_int) | ||
105 | free_irq(info->irq_err, ppi); | ||
106 | free_dma(info->dma_ch); | ||
107 | } | ||
108 | |||
109 | static int ppi_start(struct ppi_if *ppi) | ||
110 | { | ||
111 | const struct ppi_info *info = ppi->info; | ||
112 | |||
113 | /* enable DMA */ | ||
114 | enable_dma(info->dma_ch); | ||
115 | |||
116 | /* enable PPI */ | ||
117 | ppi->ppi_control |= PORT_EN; | ||
118 | switch (info->type) { | ||
119 | case PPI_TYPE_PPI: | ||
120 | { | ||
121 | struct bfin_ppi_regs *reg = info->base; | ||
122 | bfin_write16(®->control, ppi->ppi_control); | ||
123 | break; | ||
124 | } | ||
125 | case PPI_TYPE_EPPI: | ||
126 | { | ||
127 | struct bfin_eppi_regs *reg = info->base; | ||
128 | bfin_write32(®->control, ppi->ppi_control); | ||
129 | break; | ||
130 | } | ||
131 | default: | ||
132 | return -EINVAL; | ||
133 | } | ||
134 | |||
135 | SSYNC(); | ||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | static int ppi_stop(struct ppi_if *ppi) | ||
140 | { | ||
141 | const struct ppi_info *info = ppi->info; | ||
142 | |||
143 | /* disable PPI */ | ||
144 | ppi->ppi_control &= ~PORT_EN; | ||
145 | switch (info->type) { | ||
146 | case PPI_TYPE_PPI: | ||
147 | { | ||
148 | struct bfin_ppi_regs *reg = info->base; | ||
149 | bfin_write16(®->control, ppi->ppi_control); | ||
150 | break; | ||
151 | } | ||
152 | case PPI_TYPE_EPPI: | ||
153 | { | ||
154 | struct bfin_eppi_regs *reg = info->base; | ||
155 | bfin_write32(®->control, ppi->ppi_control); | ||
156 | break; | ||
157 | } | ||
158 | default: | ||
159 | return -EINVAL; | ||
160 | } | ||
161 | |||
162 | /* disable DMA */ | ||
163 | clear_dma_irqstat(info->dma_ch); | ||
164 | disable_dma(info->dma_ch); | ||
165 | |||
166 | SSYNC(); | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params) | ||
171 | { | ||
172 | const struct ppi_info *info = ppi->info; | ||
173 | int dma32 = 0; | ||
174 | int dma_config, bytes_per_line, lines_per_frame; | ||
175 | |||
176 | bytes_per_line = params->width * params->bpp / 8; | ||
177 | lines_per_frame = params->height; | ||
178 | if (params->int_mask == 0xFFFFFFFF) | ||
179 | ppi->err_int = false; | ||
180 | else | ||
181 | ppi->err_int = true; | ||
182 | |||
183 | dma_config = (DMA_FLOW_STOP | WNR | RESTART | DMA2D | DI_EN); | ||
184 | ppi->ppi_control = params->ppi_control & ~PORT_EN; | ||
185 | switch (info->type) { | ||
186 | case PPI_TYPE_PPI: | ||
187 | { | ||
188 | struct bfin_ppi_regs *reg = info->base; | ||
189 | |||
190 | if (params->ppi_control & DMA32) | ||
191 | dma32 = 1; | ||
192 | |||
193 | bfin_write16(®->control, ppi->ppi_control); | ||
194 | bfin_write16(®->count, bytes_per_line - 1); | ||
195 | bfin_write16(®->frame, lines_per_frame); | ||
196 | break; | ||
197 | } | ||
198 | case PPI_TYPE_EPPI: | ||
199 | { | ||
200 | struct bfin_eppi_regs *reg = info->base; | ||
201 | |||
202 | if ((params->ppi_control & PACK_EN) | ||
203 | || (params->ppi_control & 0x38000) > DLEN_16) | ||
204 | dma32 = 1; | ||
205 | |||
206 | bfin_write32(®->control, ppi->ppi_control); | ||
207 | bfin_write16(®->line, bytes_per_line + params->blank_clocks); | ||
208 | bfin_write16(®->frame, lines_per_frame); | ||
209 | bfin_write16(®->hdelay, 0); | ||
210 | bfin_write16(®->vdelay, 0); | ||
211 | bfin_write16(®->hcount, bytes_per_line); | ||
212 | bfin_write16(®->vcount, lines_per_frame); | ||
213 | break; | ||
214 | } | ||
215 | default: | ||
216 | return -EINVAL; | ||
217 | } | ||
218 | |||
219 | if (dma32) { | ||
220 | dma_config |= WDSIZE_32; | ||
221 | set_dma_x_count(info->dma_ch, bytes_per_line >> 2); | ||
222 | set_dma_x_modify(info->dma_ch, 4); | ||
223 | set_dma_y_modify(info->dma_ch, 4); | ||
224 | } else { | ||
225 | dma_config |= WDSIZE_16; | ||
226 | set_dma_x_count(info->dma_ch, bytes_per_line >> 1); | ||
227 | set_dma_x_modify(info->dma_ch, 2); | ||
228 | set_dma_y_modify(info->dma_ch, 2); | ||
229 | } | ||
230 | set_dma_y_count(info->dma_ch, lines_per_frame); | ||
231 | set_dma_config(info->dma_ch, dma_config); | ||
232 | |||
233 | SSYNC(); | ||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | static void ppi_update_addr(struct ppi_if *ppi, unsigned long addr) | ||
238 | { | ||
239 | set_dma_start_addr(ppi->info->dma_ch, addr); | ||
240 | } | ||
241 | |||
242 | struct ppi_if *ppi_create_instance(const struct ppi_info *info) | ||
243 | { | ||
244 | struct ppi_if *ppi; | ||
245 | |||
246 | if (!info || !info->pin_req) | ||
247 | return NULL; | ||
248 | |||
249 | if (peripheral_request_list(info->pin_req, KBUILD_MODNAME)) { | ||
250 | pr_err("request peripheral failed\n"); | ||
251 | return NULL; | ||
252 | } | ||
253 | |||
254 | ppi = kzalloc(sizeof(*ppi), GFP_KERNEL); | ||
255 | if (!ppi) { | ||
256 | peripheral_free_list(info->pin_req); | ||
257 | pr_err("unable to allocate memory for ppi handle\n"); | ||
258 | return NULL; | ||
259 | } | ||
260 | ppi->ops = &ppi_ops; | ||
261 | ppi->info = info; | ||
262 | |||
263 | pr_info("ppi probe success\n"); | ||
264 | return ppi; | ||
265 | } | ||
266 | |||
267 | void ppi_delete_instance(struct ppi_if *ppi) | ||
268 | { | ||
269 | peripheral_free_list(ppi->info->pin_req); | ||
270 | kfree(ppi); | ||
271 | } | ||
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c index 859eabf57978..377bf05b1efd 100644 --- a/drivers/media/video/bt819.c +++ b/drivers/media/video/bt819.c | |||
@@ -514,15 +514,4 @@ static struct i2c_driver bt819_driver = { | |||
514 | .id_table = bt819_id, | 514 | .id_table = bt819_id, |
515 | }; | 515 | }; |
516 | 516 | ||
517 | static __init int init_bt819(void) | 517 | module_i2c_driver(bt819_driver); |
518 | { | ||
519 | return i2c_add_driver(&bt819_driver); | ||
520 | } | ||
521 | |||
522 | static __exit void exit_bt819(void) | ||
523 | { | ||
524 | i2c_del_driver(&bt819_driver); | ||
525 | } | ||
526 | |||
527 | module_init(init_bt819); | ||
528 | module_exit(exit_bt819); | ||
diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c index a43059d4c799..7e5bd365c239 100644 --- a/drivers/media/video/bt856.c +++ b/drivers/media/video/bt856.c | |||
@@ -270,15 +270,4 @@ static struct i2c_driver bt856_driver = { | |||
270 | .id_table = bt856_id, | 270 | .id_table = bt856_id, |
271 | }; | 271 | }; |
272 | 272 | ||
273 | static __init int init_bt856(void) | 273 | module_i2c_driver(bt856_driver); |
274 | { | ||
275 | return i2c_add_driver(&bt856_driver); | ||
276 | } | ||
277 | |||
278 | static __exit void exit_bt856(void) | ||
279 | { | ||
280 | i2c_del_driver(&bt856_driver); | ||
281 | } | ||
282 | |||
283 | module_init(init_bt856); | ||
284 | module_exit(exit_bt856); | ||
diff --git a/drivers/media/video/bt866.c b/drivers/media/video/bt866.c index 4e5dcea0501d..905320b67a1c 100644 --- a/drivers/media/video/bt866.c +++ b/drivers/media/video/bt866.c | |||
@@ -240,15 +240,4 @@ static struct i2c_driver bt866_driver = { | |||
240 | .id_table = bt866_id, | 240 | .id_table = bt866_id, |
241 | }; | 241 | }; |
242 | 242 | ||
243 | static __init int init_bt866(void) | 243 | module_i2c_driver(bt866_driver); |
244 | { | ||
245 | return i2c_add_driver(&bt866_driver); | ||
246 | } | ||
247 | |||
248 | static __exit void exit_bt866(void) | ||
249 | { | ||
250 | i2c_del_driver(&bt866_driver); | ||
251 | } | ||
252 | |||
253 | module_init(init_bt866); | ||
254 | module_exit(exit_bt866); | ||
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 76c301f05095..e581b37be789 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c | |||
@@ -2035,11 +2035,7 @@ static int bttv_log_status(struct file *file, void *f) | |||
2035 | struct bttv_fh *fh = f; | 2035 | struct bttv_fh *fh = f; |
2036 | struct bttv *btv = fh->btv; | 2036 | struct bttv *btv = fh->btv; |
2037 | 2037 | ||
2038 | pr_info("%d: ======== START STATUS CARD #%d ========\n", | ||
2039 | btv->c.nr, btv->c.nr); | ||
2040 | bttv_call_all(btv, core, log_status); | 2038 | bttv_call_all(btv, core, log_status); |
2041 | pr_info("%d: ======== END STATUS CARD #%d ========\n", | ||
2042 | btv->c.nr, btv->c.nr); | ||
2043 | return 0; | 2039 | return 0; |
2044 | } | 2040 | } |
2045 | 2041 | ||
diff --git a/drivers/media/video/cs5345.c b/drivers/media/video/cs5345.c index 1d64af9adf71..c8581e26fa9c 100644 --- a/drivers/media/video/cs5345.c +++ b/drivers/media/video/cs5345.c | |||
@@ -249,15 +249,4 @@ static struct i2c_driver cs5345_driver = { | |||
249 | .id_table = cs5345_id, | 249 | .id_table = cs5345_id, |
250 | }; | 250 | }; |
251 | 251 | ||
252 | static __init int init_cs5345(void) | 252 | module_i2c_driver(cs5345_driver); |
253 | { | ||
254 | return i2c_add_driver(&cs5345_driver); | ||
255 | } | ||
256 | |||
257 | static __exit void exit_cs5345(void) | ||
258 | { | ||
259 | i2c_del_driver(&cs5345_driver); | ||
260 | } | ||
261 | |||
262 | module_init(init_cs5345); | ||
263 | module_exit(exit_cs5345); | ||
diff --git a/drivers/media/video/cs53l32a.c b/drivers/media/video/cs53l32a.c index 51c5b9ad67d8..b293912206eb 100644 --- a/drivers/media/video/cs53l32a.c +++ b/drivers/media/video/cs53l32a.c | |||
@@ -248,15 +248,4 @@ static struct i2c_driver cs53l32a_driver = { | |||
248 | .id_table = cs53l32a_id, | 248 | .id_table = cs53l32a_id, |
249 | }; | 249 | }; |
250 | 250 | ||
251 | static __init int init_cs53l32a(void) | 251 | module_i2c_driver(cs53l32a_driver); |
252 | { | ||
253 | return i2c_add_driver(&cs53l32a_driver); | ||
254 | } | ||
255 | |||
256 | static __exit void exit_cs53l32a(void) | ||
257 | { | ||
258 | i2c_del_driver(&cs53l32a_driver); | ||
259 | } | ||
260 | |||
261 | module_init(init_cs53l32a); | ||
262 | module_exit(exit_cs53l32a); | ||
diff --git a/drivers/media/video/cx18/cx18-alsa-main.c b/drivers/media/video/cx18/cx18-alsa-main.c index a1e6c2a32478..e118361c2e7b 100644 --- a/drivers/media/video/cx18/cx18-alsa-main.c +++ b/drivers/media/video/cx18/cx18-alsa-main.c | |||
@@ -285,7 +285,6 @@ static void __exit cx18_alsa_exit(void) | |||
285 | 285 | ||
286 | drv = driver_find("cx18", &pci_bus_type); | 286 | drv = driver_find("cx18", &pci_bus_type); |
287 | ret = driver_for_each_device(drv, NULL, NULL, cx18_alsa_exit_callback); | 287 | ret = driver_for_each_device(drv, NULL, NULL, cx18_alsa_exit_callback); |
288 | put_driver(drv); | ||
289 | 288 | ||
290 | cx18_ext_init = NULL; | 289 | cx18_ext_init = NULL; |
291 | printk(KERN_INFO "cx18-alsa: module unload complete\n"); | 290 | printk(KERN_INFO "cx18-alsa: module unload complete\n"); |
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 349bd9c2aff5..b55d57cc1a1c 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c | |||
@@ -38,7 +38,7 @@ | |||
38 | #include "cx18-ioctl.h" | 38 | #include "cx18-ioctl.h" |
39 | #include "cx18-controls.h" | 39 | #include "cx18-controls.h" |
40 | #include "tuner-xc2028.h" | 40 | #include "tuner-xc2028.h" |
41 | 41 | #include <linux/dma-mapping.h> | |
42 | #include <media/tveeprom.h> | 42 | #include <media/tveeprom.h> |
43 | 43 | ||
44 | /* If you have already X v4l cards, then set this to X. This way | 44 | /* If you have already X v4l cards, then set this to X. This way |
@@ -75,7 +75,7 @@ static int radio[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, | |||
75 | -1, -1, -1, -1, -1, -1, -1, -1 }; | 75 | -1, -1, -1, -1, -1, -1, -1, -1 }; |
76 | static unsigned cardtype_c = 1; | 76 | static unsigned cardtype_c = 1; |
77 | static unsigned tuner_c = 1; | 77 | static unsigned tuner_c = 1; |
78 | static bool radio_c = 1; | 78 | static unsigned radio_c = 1; |
79 | static char pal[] = "--"; | 79 | static char pal[] = "--"; |
80 | static char secam[] = "--"; | 80 | static char secam[] = "--"; |
81 | static char ntsc[] = "-"; | 81 | static char ntsc[] = "-"; |
@@ -110,7 +110,7 @@ static int retry_mmio = 1; | |||
110 | int cx18_debug; | 110 | int cx18_debug; |
111 | 111 | ||
112 | module_param_array(tuner, int, &tuner_c, 0644); | 112 | module_param_array(tuner, int, &tuner_c, 0644); |
113 | module_param_array(radio, bool, &radio_c, 0644); | 113 | module_param_array(radio, int, &radio_c, 0644); |
114 | module_param_array(cardtype, int, &cardtype_c, 0644); | 114 | module_param_array(cardtype, int, &cardtype_c, 0644); |
115 | module_param_string(pal, pal, sizeof(pal), 0644); | 115 | module_param_string(pal, pal, sizeof(pal), 0644); |
116 | module_param_string(secam, secam, sizeof(secam), 0644); | 116 | module_param_string(secam, secam, sizeof(secam), 0644); |
@@ -812,7 +812,7 @@ static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *pci_dev, | |||
812 | CX18_ERR("Can't enable device %d!\n", cx->instance); | 812 | CX18_ERR("Can't enable device %d!\n", cx->instance); |
813 | return -EIO; | 813 | return -EIO; |
814 | } | 814 | } |
815 | if (pci_set_dma_mask(pci_dev, 0xffffffff)) { | 815 | if (pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32))) { |
816 | CX18_ERR("No suitable DMA available, card %d\n", cx->instance); | 816 | CX18_ERR("No suitable DMA available, card %d\n", cx->instance); |
817 | return -EIO; | 817 | return -EIO; |
818 | } | 818 | } |
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index b9a94fc5146d..7a37e0ee136f 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h | |||
@@ -44,8 +44,6 @@ | |||
44 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
45 | #include <asm/byteorder.h> | 45 | #include <asm/byteorder.h> |
46 | 46 | ||
47 | #include <linux/dvb/video.h> | ||
48 | #include <linux/dvb/audio.h> | ||
49 | #include <media/v4l2-common.h> | 47 | #include <media/v4l2-common.h> |
50 | #include <media/v4l2-ioctl.h> | 48 | #include <media/v4l2-ioctl.h> |
51 | #include <media/v4l2-device.h> | 49 | #include <media/v4l2-device.h> |
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 66b1c15c3541..be49f68ddf37 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c | |||
@@ -1085,8 +1085,6 @@ static int cx18_log_status(struct file *file, void *fh) | |||
1085 | struct v4l2_audio audin; | 1085 | struct v4l2_audio audin; |
1086 | int i; | 1086 | int i; |
1087 | 1087 | ||
1088 | CX18_INFO("================= START STATUS CARD #%d " | ||
1089 | "=================\n", cx->instance); | ||
1090 | CX18_INFO("Version: %s Card: %s\n", CX18_VERSION, cx->card_name); | 1088 | CX18_INFO("Version: %s Card: %s\n", CX18_VERSION, cx->card_name); |
1091 | if (cx->hw_flags & CX18_HW_TVEEPROM) { | 1089 | if (cx->hw_flags & CX18_HW_TVEEPROM) { |
1092 | struct tveeprom tv; | 1090 | struct tveeprom tv; |
@@ -1120,8 +1118,6 @@ static int cx18_log_status(struct file *file, void *fh) | |||
1120 | CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n", | 1118 | CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n", |
1121 | (long long)cx->mpg_data_received, | 1119 | (long long)cx->mpg_data_received, |
1122 | (long long)cx->vbi_data_inserted); | 1120 | (long long)cx->vbi_data_inserted); |
1123 | CX18_INFO("================== END STATUS CARD #%d " | ||
1124 | "==================\n", cx->instance); | ||
1125 | return 0; | 1121 | return 0; |
1126 | } | 1122 | } |
1127 | 1123 | ||
diff --git a/drivers/media/video/cx231xx/cx231xx-417.c b/drivers/media/video/cx231xx/cx231xx-417.c index f8f0e59cd583..d4327dab5a36 100644 --- a/drivers/media/video/cx231xx/cx231xx-417.c +++ b/drivers/media/video/cx231xx/cx231xx-417.c | |||
@@ -1686,7 +1686,6 @@ static struct v4l2_capability pvr_capability = { | |||
1686 | .capabilities = (V4L2_CAP_VIDEO_CAPTURE | | 1686 | .capabilities = (V4L2_CAP_VIDEO_CAPTURE | |
1687 | V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO | | 1687 | V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO | |
1688 | V4L2_CAP_STREAMING | V4L2_CAP_READWRITE), | 1688 | V4L2_CAP_STREAMING | V4L2_CAP_READWRITE), |
1689 | .reserved = {0, 0, 0, 0} | ||
1690 | }; | 1689 | }; |
1691 | static int vidioc_querycap(struct file *file, void *priv, | 1690 | static int vidioc_querycap(struct file *file, void *priv, |
1692 | struct v4l2_capability *cap) | 1691 | struct v4l2_capability *cap) |
diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c index 875a7ce94736..8ed460d692e0 100644 --- a/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/drivers/media/video/cx231xx/cx231xx-cards.c | |||
@@ -861,7 +861,6 @@ void cx231xx_release_resources(struct cx231xx *dev) | |||
861 | kfree(dev->sliced_cc_mode.alt_max_pkt_size); | 861 | kfree(dev->sliced_cc_mode.alt_max_pkt_size); |
862 | kfree(dev->ts1_mode.alt_max_pkt_size); | 862 | kfree(dev->ts1_mode.alt_max_pkt_size); |
863 | kfree(dev); | 863 | kfree(dev); |
864 | dev = NULL; | ||
865 | } | 864 | } |
866 | 865 | ||
867 | /* | 866 | /* |
diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c index 829a41b0c9ef..7f916f0685e9 100644 --- a/drivers/media/video/cx231xx/cx231xx-video.c +++ b/drivers/media/video/cx231xx/cx231xx-video.c | |||
@@ -2319,8 +2319,7 @@ static int cx231xx_v4l2_close(struct file *filp) | |||
2319 | if (dev->state & DEV_DISCONNECTED) { | 2319 | if (dev->state & DEV_DISCONNECTED) { |
2320 | if (atomic_read(&dev->devlist_count) > 0) { | 2320 | if (atomic_read(&dev->devlist_count) > 0) { |
2321 | cx231xx_release_resources(dev); | 2321 | cx231xx_release_resources(dev); |
2322 | kfree(dev); | 2322 | fh->dev = NULL; |
2323 | dev = NULL; | ||
2324 | return 0; | 2323 | return 0; |
2325 | } | 2324 | } |
2326 | return 0; | 2325 | return 0; |
@@ -2350,8 +2349,7 @@ static int cx231xx_v4l2_close(struct file *filp) | |||
2350 | free the remaining resources */ | 2349 | free the remaining resources */ |
2351 | if (dev->state & DEV_DISCONNECTED) { | 2350 | if (dev->state & DEV_DISCONNECTED) { |
2352 | cx231xx_release_resources(dev); | 2351 | cx231xx_release_resources(dev); |
2353 | kfree(dev); | 2352 | fh->dev = NULL; |
2354 | dev = NULL; | ||
2355 | return 0; | 2353 | return 0; |
2356 | } | 2354 | } |
2357 | 2355 | ||
diff --git a/drivers/media/video/cx25821/cx25821-core.c b/drivers/media/video/cx25821/cx25821-core.c index f617474f9073..7930ca58349f 100644 --- a/drivers/media/video/cx25821/cx25821-core.c +++ b/drivers/media/video/cx25821/cx25821-core.c | |||
@@ -1474,8 +1474,13 @@ static DEFINE_PCI_DEVICE_TABLE(cx25821_pci_tbl) = { | |||
1474 | .device = 0x8210, | 1474 | .device = 0x8210, |
1475 | .subvendor = 0x14f1, | 1475 | .subvendor = 0x14f1, |
1476 | .subdevice = 0x0920, | 1476 | .subdevice = 0x0920, |
1477 | }, | 1477 | }, { |
1478 | { | 1478 | /* CX25821 No Brand */ |
1479 | .vendor = 0x14f1, | ||
1480 | .device = 0x8210, | ||
1481 | .subvendor = 0x0000, | ||
1482 | .subdevice = 0x0000, | ||
1483 | }, { | ||
1479 | /* --- end of list --- */ | 1484 | /* --- end of list --- */ |
1480 | } | 1485 | } |
1481 | }; | 1486 | }; |
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 05247d4c340a..fc1ff69cffd0 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c | |||
@@ -5301,15 +5301,4 @@ static struct i2c_driver cx25840_driver = { | |||
5301 | .id_table = cx25840_id, | 5301 | .id_table = cx25840_id, |
5302 | }; | 5302 | }; |
5303 | 5303 | ||
5304 | static __init int init_cx25840(void) | 5304 | module_i2c_driver(cx25840_driver); |
5305 | { | ||
5306 | return i2c_add_driver(&cx25840_driver); | ||
5307 | } | ||
5308 | |||
5309 | static __exit void exit_cx25840(void) | ||
5310 | { | ||
5311 | i2c_del_driver(&cx25840_driver); | ||
5312 | } | ||
5313 | |||
5314 | module_init(init_cx25840); | ||
5315 | module_exit(exit_cx25840); | ||
diff --git a/drivers/media/video/davinci/dm355_ccdc.c b/drivers/media/video/davinci/dm355_ccdc.c index f83baf3a52b0..5b68847d4017 100644 --- a/drivers/media/video/davinci/dm355_ccdc.c +++ b/drivers/media/video/davinci/dm355_ccdc.c | |||
@@ -292,7 +292,7 @@ static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam) | |||
292 | if ((ccdcparam->med_filt_thres < 0) || | 292 | if ((ccdcparam->med_filt_thres < 0) || |
293 | (ccdcparam->med_filt_thres > CCDC_MED_FILT_THRESH)) { | 293 | (ccdcparam->med_filt_thres > CCDC_MED_FILT_THRESH)) { |
294 | dev_dbg(ccdc_cfg.dev, | 294 | dev_dbg(ccdc_cfg.dev, |
295 | "Invalid value of median filter thresold\n"); | 295 | "Invalid value of median filter threshold\n"); |
296 | return -EINVAL; | 296 | return -EINVAL; |
297 | } | 297 | } |
298 | 298 | ||
diff --git a/drivers/media/video/davinci/isif.c b/drivers/media/video/davinci/isif.c index 1e63852374be..5278fe7d6d0c 100644 --- a/drivers/media/video/davinci/isif.c +++ b/drivers/media/video/davinci/isif.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/videodev2.h> | 34 | #include <linux/videodev2.h> |
35 | #include <linux/clk.h> | 35 | #include <linux/clk.h> |
36 | #include <linux/err.h> | 36 | #include <linux/err.h> |
37 | #include <linux/module.h> | ||
37 | 38 | ||
38 | #include <mach/mux.h> | 39 | #include <mach/mux.h> |
39 | 40 | ||
diff --git a/drivers/media/video/davinci/vpif.h b/drivers/media/video/davinci/vpif.h index 25036cb11bea..8bcac65f9294 100644 --- a/drivers/media/video/davinci/vpif.h +++ b/drivers/media/video/davinci/vpif.h | |||
@@ -18,8 +18,6 @@ | |||
18 | 18 | ||
19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
20 | #include <linux/videodev2.h> | 20 | #include <linux/videodev2.h> |
21 | #include <mach/hardware.h> | ||
22 | #include <mach/dm646x.h> | ||
23 | #include <media/davinci/vpif_types.h> | 21 | #include <media/davinci/vpif_types.h> |
24 | 22 | ||
25 | /* Maximum channel allowed */ | 23 | /* Maximum channel allowed */ |
diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c index 286f02910044..7fa34b4fae26 100644 --- a/drivers/media/video/davinci/vpif_display.c +++ b/drivers/media/video/davinci/vpif_display.c | |||
@@ -39,8 +39,6 @@ | |||
39 | #include <media/v4l2-ioctl.h> | 39 | #include <media/v4l2-ioctl.h> |
40 | #include <media/v4l2-chip-ident.h> | 40 | #include <media/v4l2-chip-ident.h> |
41 | 41 | ||
42 | #include <mach/dm646x.h> | ||
43 | |||
44 | #include "vpif_display.h" | 42 | #include "vpif_display.h" |
45 | #include "vpif.h" | 43 | #include "vpif.h" |
46 | 44 | ||
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 4561cd89938d..9fd8cc7dbb23 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -353,6 +353,44 @@ static struct em28xx_reg_seq hauppauge_930c_digital[] = { | |||
353 | }; | 353 | }; |
354 | #endif | 354 | #endif |
355 | 355 | ||
356 | /* 1b80:e425 MaxMedia UB425-TC | ||
357 | * GPIO_6 - demod reset, 0=active | ||
358 | * GPIO_7 - LED, 0=active | ||
359 | */ | ||
360 | static struct em28xx_reg_seq maxmedia_ub425_tc[] = { | ||
361 | {EM2874_R80_GPIO, 0x83, 0xff, 100}, | ||
362 | {EM2874_R80_GPIO, 0xc3, 0xff, 100}, /* GPIO_6 = 1 */ | ||
363 | {EM2874_R80_GPIO, 0x43, 0xff, 000}, /* GPIO_7 = 0 */ | ||
364 | {-1, -1, -1, -1}, | ||
365 | }; | ||
366 | |||
367 | /* 2304:0242 PCTV QuatroStick (510e) | ||
368 | * GPIO_2: decoder reset, 0=active | ||
369 | * GPIO_4: decoder suspend, 0=active | ||
370 | * GPIO_6: demod reset, 0=active | ||
371 | * GPIO_7: LED, 1=active | ||
372 | */ | ||
373 | static struct em28xx_reg_seq pctv_510e[] = { | ||
374 | {EM2874_R80_GPIO, 0x10, 0xff, 100}, | ||
375 | {EM2874_R80_GPIO, 0x14, 0xff, 100}, /* GPIO_2 = 1 */ | ||
376 | {EM2874_R80_GPIO, 0x54, 0xff, 050}, /* GPIO_6 = 1 */ | ||
377 | { -1, -1, -1, -1}, | ||
378 | }; | ||
379 | |||
380 | /* 2013:0251 PCTV QuatroStick nano (520e) | ||
381 | * GPIO_2: decoder reset, 0=active | ||
382 | * GPIO_4: decoder suspend, 0=active | ||
383 | * GPIO_6: demod reset, 0=active | ||
384 | * GPIO_7: LED, 1=active | ||
385 | */ | ||
386 | static struct em28xx_reg_seq pctv_520e[] = { | ||
387 | {EM2874_R80_GPIO, 0x10, 0xff, 100}, | ||
388 | {EM2874_R80_GPIO, 0x14, 0xff, 100}, /* GPIO_2 = 1 */ | ||
389 | {EM2874_R80_GPIO, 0x54, 0xff, 050}, /* GPIO_6 = 1 */ | ||
390 | {EM2874_R80_GPIO, 0xd4, 0xff, 000}, /* GPIO_7 = 1 */ | ||
391 | { -1, -1, -1, -1}, | ||
392 | }; | ||
393 | |||
356 | /* | 394 | /* |
357 | * Board definitions | 395 | * Board definitions |
358 | */ | 396 | */ |
@@ -1908,6 +1946,41 @@ struct em28xx_board em28xx_boards[] = { | |||
1908 | .amux = EM28XX_AMUX_LINE_IN, | 1946 | .amux = EM28XX_AMUX_LINE_IN, |
1909 | } }, | 1947 | } }, |
1910 | }, | 1948 | }, |
1949 | /* 1b80:e425 MaxMedia UB425-TC | ||
1950 | * Empia EM2874B + Micronas DRX 3913KA2 + NXP TDA18271HDC2 */ | ||
1951 | [EM2874_BOARD_MAXMEDIA_UB425_TC] = { | ||
1952 | .name = "MaxMedia UB425-TC", | ||
1953 | .tuner_type = TUNER_ABSENT, | ||
1954 | .tuner_gpio = maxmedia_ub425_tc, | ||
1955 | .has_dvb = 1, | ||
1956 | .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | | ||
1957 | EM28XX_I2C_CLK_WAIT_ENABLE | | ||
1958 | EM28XX_I2C_FREQ_400_KHZ, | ||
1959 | }, | ||
1960 | /* 2304:0242 PCTV QuatroStick (510e) | ||
1961 | * Empia EM2884 + Micronas DRX 3926K + NXP TDA18271HDC2 */ | ||
1962 | [EM2884_BOARD_PCTV_510E] = { | ||
1963 | .name = "PCTV QuatroStick (510e)", | ||
1964 | .tuner_type = TUNER_ABSENT, | ||
1965 | .tuner_gpio = pctv_510e, | ||
1966 | .has_dvb = 1, | ||
1967 | .ir_codes = RC_MAP_PINNACLE_PCTV_HD, | ||
1968 | .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | | ||
1969 | EM28XX_I2C_CLK_WAIT_ENABLE | | ||
1970 | EM28XX_I2C_FREQ_400_KHZ, | ||
1971 | }, | ||
1972 | /* 2013:0251 PCTV QuatroStick nano (520e) | ||
1973 | * Empia EM2884 + Micronas DRX 3926K + NXP TDA18271HDC2 */ | ||
1974 | [EM2884_BOARD_PCTV_520E] = { | ||
1975 | .name = "PCTV QuatroStick nano (520e)", | ||
1976 | .tuner_type = TUNER_ABSENT, | ||
1977 | .tuner_gpio = pctv_520e, | ||
1978 | .has_dvb = 1, | ||
1979 | .ir_codes = RC_MAP_PINNACLE_PCTV_HD, | ||
1980 | .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | | ||
1981 | EM28XX_I2C_CLK_WAIT_ENABLE | | ||
1982 | EM28XX_I2C_FREQ_400_KHZ, | ||
1983 | }, | ||
1911 | }; | 1984 | }; |
1912 | const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); | 1985 | const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); |
1913 | 1986 | ||
@@ -2059,6 +2132,12 @@ struct usb_device_id em28xx_id_table[] = { | |||
2059 | .driver_info = EM2860_BOARD_HT_VIDBOX_NW03 }, | 2132 | .driver_info = EM2860_BOARD_HT_VIDBOX_NW03 }, |
2060 | { USB_DEVICE(0x1b80, 0xe309), /* Sveon STV40 */ | 2133 | { USB_DEVICE(0x1b80, 0xe309), /* Sveon STV40 */ |
2061 | .driver_info = EM2860_BOARD_EASYCAP }, | 2134 | .driver_info = EM2860_BOARD_EASYCAP }, |
2135 | { USB_DEVICE(0x1b80, 0xe425), | ||
2136 | .driver_info = EM2874_BOARD_MAXMEDIA_UB425_TC }, | ||
2137 | { USB_DEVICE(0x2304, 0x0242), | ||
2138 | .driver_info = EM2884_BOARD_PCTV_510E }, | ||
2139 | { USB_DEVICE(0x2013, 0x0251), | ||
2140 | .driver_info = EM2884_BOARD_PCTV_520E }, | ||
2062 | { }, | 2141 | { }, |
2063 | }; | 2142 | }; |
2064 | MODULE_DEVICE_TABLE(usb, em28xx_id_table); | 2143 | MODULE_DEVICE_TABLE(usb, em28xx_id_table); |
@@ -3122,7 +3201,6 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
3122 | int i, nr; | 3201 | int i, nr; |
3123 | const int ifnum = interface->altsetting[0].desc.bInterfaceNumber; | 3202 | const int ifnum = interface->altsetting[0].desc.bInterfaceNumber; |
3124 | char *speed; | 3203 | char *speed; |
3125 | char descr[255] = ""; | ||
3126 | 3204 | ||
3127 | udev = usb_get_dev(interface_to_usbdev(interface)); | 3205 | udev = usb_get_dev(interface_to_usbdev(interface)); |
3128 | 3206 | ||
@@ -3227,21 +3305,11 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
3227 | speed = "unknown"; | 3305 | speed = "unknown"; |
3228 | } | 3306 | } |
3229 | 3307 | ||
3230 | if (udev->manufacturer) | ||
3231 | strlcpy(descr, udev->manufacturer, sizeof(descr)); | ||
3232 | |||
3233 | if (udev->product) { | ||
3234 | if (*descr) | ||
3235 | strlcat(descr, " ", sizeof(descr)); | ||
3236 | strlcat(descr, udev->product, sizeof(descr)); | ||
3237 | } | ||
3238 | |||
3239 | if (*descr) | ||
3240 | strlcat(descr, " ", sizeof(descr)); | ||
3241 | |||
3242 | printk(KERN_INFO DRIVER_NAME | 3308 | printk(KERN_INFO DRIVER_NAME |
3243 | ": New device %s@ %s Mbps (%04x:%04x, interface %d, class %d)\n", | 3309 | ": New device %s %s @ %s Mbps " |
3244 | descr, | 3310 | "(%04x:%04x, interface %d, class %d)\n", |
3311 | udev->manufacturer ? udev->manufacturer : "", | ||
3312 | udev->product ? udev->product : "", | ||
3245 | speed, | 3313 | speed, |
3246 | le16_to_cpu(udev->descriptor.idVendor), | 3314 | le16_to_cpu(udev->descriptor.idVendor), |
3247 | le16_to_cpu(udev->descriptor.idProduct), | 3315 | le16_to_cpu(udev->descriptor.idProduct), |
@@ -3307,6 +3375,17 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
3307 | goto unlock_and_free; | 3375 | goto unlock_and_free; |
3308 | } | 3376 | } |
3309 | 3377 | ||
3378 | if (has_dvb) { | ||
3379 | /* pre-allocate DVB isoc transfer buffers */ | ||
3380 | retval = em28xx_alloc_isoc(dev, EM28XX_DIGITAL_MODE, | ||
3381 | EM28XX_DVB_MAX_PACKETS, | ||
3382 | EM28XX_DVB_NUM_BUFS, | ||
3383 | dev->dvb_max_pkt_size); | ||
3384 | if (retval) { | ||
3385 | goto unlock_and_free; | ||
3386 | } | ||
3387 | } | ||
3388 | |||
3310 | request_modules(dev); | 3389 | request_modules(dev); |
3311 | 3390 | ||
3312 | /* Should be the last thing to do, to avoid newer udev's to | 3391 | /* Should be the last thing to do, to avoid newer udev's to |
@@ -3379,7 +3458,7 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) | |||
3379 | video_device_node_name(dev->vdev)); | 3458 | video_device_node_name(dev->vdev)); |
3380 | 3459 | ||
3381 | dev->state |= DEV_MISCONFIGURED; | 3460 | dev->state |= DEV_MISCONFIGURED; |
3382 | em28xx_uninit_isoc(dev); | 3461 | em28xx_uninit_isoc(dev, dev->mode); |
3383 | dev->state |= DEV_DISCONNECTED; | 3462 | dev->state |= DEV_DISCONNECTED; |
3384 | wake_up_interruptible(&dev->wait_frame); | 3463 | wake_up_interruptible(&dev->wait_frame); |
3385 | wake_up_interruptible(&dev->wait_stream); | 3464 | wake_up_interruptible(&dev->wait_stream); |
@@ -3388,6 +3467,9 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) | |||
3388 | em28xx_release_resources(dev); | 3467 | em28xx_release_resources(dev); |
3389 | } | 3468 | } |
3390 | 3469 | ||
3470 | /* free DVB isoc buffers */ | ||
3471 | em28xx_uninit_isoc(dev, EM28XX_DIGITAL_MODE); | ||
3472 | |||
3391 | mutex_unlock(&dev->lock); | 3473 | mutex_unlock(&dev->lock); |
3392 | 3474 | ||
3393 | em28xx_close_extension(dev); | 3475 | em28xx_close_extension(dev); |
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 0aacc96f9a23..53a9fb91e97e 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c | |||
@@ -666,6 +666,7 @@ int em28xx_capture_start(struct em28xx *dev, int start) | |||
666 | 666 | ||
667 | return rc; | 667 | return rc; |
668 | } | 668 | } |
669 | EXPORT_SYMBOL_GPL(em28xx_capture_start); | ||
669 | 670 | ||
670 | int em28xx_vbi_supported(struct em28xx *dev) | 671 | int em28xx_vbi_supported(struct em28xx *dev) |
671 | { | 672 | { |
@@ -961,146 +962,192 @@ static void em28xx_irq_callback(struct urb *urb) | |||
961 | /* | 962 | /* |
962 | * Stop and Deallocate URBs | 963 | * Stop and Deallocate URBs |
963 | */ | 964 | */ |
964 | void em28xx_uninit_isoc(struct em28xx *dev) | 965 | void em28xx_uninit_isoc(struct em28xx *dev, enum em28xx_mode mode) |
965 | { | 966 | { |
966 | struct urb *urb; | 967 | struct urb *urb; |
968 | struct em28xx_usb_isoc_bufs *isoc_bufs; | ||
967 | int i; | 969 | int i; |
968 | 970 | ||
969 | em28xx_isocdbg("em28xx: called em28xx_uninit_isoc\n"); | 971 | em28xx_isocdbg("em28xx: called em28xx_uninit_isoc in mode %d\n", mode); |
972 | |||
973 | if (mode == EM28XX_DIGITAL_MODE) | ||
974 | isoc_bufs = &dev->isoc_ctl.digital_bufs; | ||
975 | else | ||
976 | isoc_bufs = &dev->isoc_ctl.analog_bufs; | ||
970 | 977 | ||
971 | dev->isoc_ctl.nfields = -1; | 978 | dev->isoc_ctl.nfields = -1; |
972 | for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { | 979 | for (i = 0; i < isoc_bufs->num_bufs; i++) { |
973 | urb = dev->isoc_ctl.urb[i]; | 980 | urb = isoc_bufs->urb[i]; |
974 | if (urb) { | 981 | if (urb) { |
975 | if (!irqs_disabled()) | 982 | if (!irqs_disabled()) |
976 | usb_kill_urb(urb); | 983 | usb_kill_urb(urb); |
977 | else | 984 | else |
978 | usb_unlink_urb(urb); | 985 | usb_unlink_urb(urb); |
979 | 986 | ||
980 | if (dev->isoc_ctl.transfer_buffer[i]) { | 987 | if (isoc_bufs->transfer_buffer[i]) { |
981 | usb_free_coherent(dev->udev, | 988 | usb_free_coherent(dev->udev, |
982 | urb->transfer_buffer_length, | 989 | urb->transfer_buffer_length, |
983 | dev->isoc_ctl.transfer_buffer[i], | 990 | isoc_bufs->transfer_buffer[i], |
984 | urb->transfer_dma); | 991 | urb->transfer_dma); |
985 | } | 992 | } |
986 | usb_free_urb(urb); | 993 | usb_free_urb(urb); |
987 | dev->isoc_ctl.urb[i] = NULL; | 994 | isoc_bufs->urb[i] = NULL; |
988 | } | 995 | } |
989 | dev->isoc_ctl.transfer_buffer[i] = NULL; | 996 | isoc_bufs->transfer_buffer[i] = NULL; |
990 | } | 997 | } |
991 | 998 | ||
992 | kfree(dev->isoc_ctl.urb); | 999 | kfree(isoc_bufs->urb); |
993 | kfree(dev->isoc_ctl.transfer_buffer); | 1000 | kfree(isoc_bufs->transfer_buffer); |
994 | 1001 | ||
995 | dev->isoc_ctl.urb = NULL; | 1002 | isoc_bufs->urb = NULL; |
996 | dev->isoc_ctl.transfer_buffer = NULL; | 1003 | isoc_bufs->transfer_buffer = NULL; |
997 | dev->isoc_ctl.num_bufs = 0; | 1004 | isoc_bufs->num_bufs = 0; |
998 | 1005 | ||
999 | em28xx_capture_start(dev, 0); | 1006 | em28xx_capture_start(dev, 0); |
1000 | } | 1007 | } |
1001 | EXPORT_SYMBOL_GPL(em28xx_uninit_isoc); | 1008 | EXPORT_SYMBOL_GPL(em28xx_uninit_isoc); |
1002 | 1009 | ||
1003 | /* | 1010 | /* |
1004 | * Allocate URBs and start IRQ | 1011 | * Allocate URBs |
1005 | */ | 1012 | */ |
1006 | int em28xx_init_isoc(struct em28xx *dev, int max_packets, | 1013 | int em28xx_alloc_isoc(struct em28xx *dev, enum em28xx_mode mode, |
1007 | int num_bufs, int max_pkt_size, | 1014 | int max_packets, int num_bufs, int max_pkt_size) |
1008 | int (*isoc_copy) (struct em28xx *dev, struct urb *urb)) | ||
1009 | { | 1015 | { |
1010 | struct em28xx_dmaqueue *dma_q = &dev->vidq; | 1016 | struct em28xx_usb_isoc_bufs *isoc_bufs; |
1011 | struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq; | ||
1012 | int i; | 1017 | int i; |
1013 | int sb_size, pipe; | 1018 | int sb_size, pipe; |
1014 | struct urb *urb; | 1019 | struct urb *urb; |
1015 | int j, k; | 1020 | int j, k; |
1016 | int rc; | ||
1017 | 1021 | ||
1018 | em28xx_isocdbg("em28xx: called em28xx_prepare_isoc\n"); | 1022 | em28xx_isocdbg("em28xx: called em28xx_alloc_isoc in mode %d\n", mode); |
1023 | |||
1024 | if (mode == EM28XX_DIGITAL_MODE) | ||
1025 | isoc_bufs = &dev->isoc_ctl.digital_bufs; | ||
1026 | else | ||
1027 | isoc_bufs = &dev->isoc_ctl.analog_bufs; | ||
1019 | 1028 | ||
1020 | /* De-allocates all pending stuff */ | 1029 | /* De-allocates all pending stuff */ |
1021 | em28xx_uninit_isoc(dev); | 1030 | em28xx_uninit_isoc(dev, mode); |
1022 | 1031 | ||
1023 | dev->isoc_ctl.isoc_copy = isoc_copy; | 1032 | isoc_bufs->num_bufs = num_bufs; |
1024 | dev->isoc_ctl.num_bufs = num_bufs; | ||
1025 | 1033 | ||
1026 | dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); | 1034 | isoc_bufs->urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL); |
1027 | if (!dev->isoc_ctl.urb) { | 1035 | if (!isoc_bufs->urb) { |
1028 | em28xx_errdev("cannot alloc memory for usb buffers\n"); | 1036 | em28xx_errdev("cannot alloc memory for usb buffers\n"); |
1029 | return -ENOMEM; | 1037 | return -ENOMEM; |
1030 | } | 1038 | } |
1031 | 1039 | ||
1032 | dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs, | 1040 | isoc_bufs->transfer_buffer = kzalloc(sizeof(void *)*num_bufs, |
1033 | GFP_KERNEL); | 1041 | GFP_KERNEL); |
1034 | if (!dev->isoc_ctl.transfer_buffer) { | 1042 | if (!isoc_bufs->transfer_buffer) { |
1035 | em28xx_errdev("cannot allocate memory for usb transfer\n"); | 1043 | em28xx_errdev("cannot allocate memory for usb transfer\n"); |
1036 | kfree(dev->isoc_ctl.urb); | 1044 | kfree(isoc_bufs->urb); |
1037 | return -ENOMEM; | 1045 | return -ENOMEM; |
1038 | } | 1046 | } |
1039 | 1047 | ||
1040 | dev->isoc_ctl.max_pkt_size = max_pkt_size; | 1048 | isoc_bufs->max_pkt_size = max_pkt_size; |
1049 | isoc_bufs->num_packets = max_packets; | ||
1041 | dev->isoc_ctl.vid_buf = NULL; | 1050 | dev->isoc_ctl.vid_buf = NULL; |
1042 | dev->isoc_ctl.vbi_buf = NULL; | 1051 | dev->isoc_ctl.vbi_buf = NULL; |
1043 | 1052 | ||
1044 | sb_size = max_packets * dev->isoc_ctl.max_pkt_size; | 1053 | sb_size = isoc_bufs->num_packets * isoc_bufs->max_pkt_size; |
1045 | 1054 | ||
1046 | /* allocate urbs and transfer buffers */ | 1055 | /* allocate urbs and transfer buffers */ |
1047 | for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { | 1056 | for (i = 0; i < isoc_bufs->num_bufs; i++) { |
1048 | urb = usb_alloc_urb(max_packets, GFP_KERNEL); | 1057 | urb = usb_alloc_urb(isoc_bufs->num_packets, GFP_KERNEL); |
1049 | if (!urb) { | 1058 | if (!urb) { |
1050 | em28xx_err("cannot alloc isoc_ctl.urb %i\n", i); | 1059 | em28xx_err("cannot alloc isoc_ctl.urb %i\n", i); |
1051 | em28xx_uninit_isoc(dev); | 1060 | em28xx_uninit_isoc(dev, mode); |
1052 | return -ENOMEM; | 1061 | return -ENOMEM; |
1053 | } | 1062 | } |
1054 | dev->isoc_ctl.urb[i] = urb; | 1063 | isoc_bufs->urb[i] = urb; |
1055 | 1064 | ||
1056 | dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev, | 1065 | isoc_bufs->transfer_buffer[i] = usb_alloc_coherent(dev->udev, |
1057 | sb_size, GFP_KERNEL, &urb->transfer_dma); | 1066 | sb_size, GFP_KERNEL, &urb->transfer_dma); |
1058 | if (!dev->isoc_ctl.transfer_buffer[i]) { | 1067 | if (!isoc_bufs->transfer_buffer[i]) { |
1059 | em28xx_err("unable to allocate %i bytes for transfer" | 1068 | em28xx_err("unable to allocate %i bytes for transfer" |
1060 | " buffer %i%s\n", | 1069 | " buffer %i%s\n", |
1061 | sb_size, i, | 1070 | sb_size, i, |
1062 | in_interrupt() ? " while in int" : ""); | 1071 | in_interrupt() ? " while in int" : ""); |
1063 | em28xx_uninit_isoc(dev); | 1072 | em28xx_uninit_isoc(dev, mode); |
1064 | return -ENOMEM; | 1073 | return -ENOMEM; |
1065 | } | 1074 | } |
1066 | memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size); | 1075 | memset(isoc_bufs->transfer_buffer[i], 0, sb_size); |
1067 | 1076 | ||
1068 | /* FIXME: this is a hack - should be | 1077 | /* FIXME: this is a hack - should be |
1069 | 'desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK' | 1078 | 'desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK' |
1070 | should also be using 'desc.bInterval' | 1079 | should also be using 'desc.bInterval' |
1071 | */ | 1080 | */ |
1072 | pipe = usb_rcvisocpipe(dev->udev, | 1081 | pipe = usb_rcvisocpipe(dev->udev, |
1073 | dev->mode == EM28XX_ANALOG_MODE ? | 1082 | mode == EM28XX_ANALOG_MODE ? |
1074 | EM28XX_EP_ANALOG : EM28XX_EP_DIGITAL); | 1083 | EM28XX_EP_ANALOG : EM28XX_EP_DIGITAL); |
1075 | 1084 | ||
1076 | usb_fill_int_urb(urb, dev->udev, pipe, | 1085 | usb_fill_int_urb(urb, dev->udev, pipe, |
1077 | dev->isoc_ctl.transfer_buffer[i], sb_size, | 1086 | isoc_bufs->transfer_buffer[i], sb_size, |
1078 | em28xx_irq_callback, dev, 1); | 1087 | em28xx_irq_callback, dev, 1); |
1079 | 1088 | ||
1080 | urb->number_of_packets = max_packets; | 1089 | urb->number_of_packets = isoc_bufs->num_packets; |
1081 | urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; | 1090 | urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; |
1082 | 1091 | ||
1083 | k = 0; | 1092 | k = 0; |
1084 | for (j = 0; j < max_packets; j++) { | 1093 | for (j = 0; j < isoc_bufs->num_packets; j++) { |
1085 | urb->iso_frame_desc[j].offset = k; | 1094 | urb->iso_frame_desc[j].offset = k; |
1086 | urb->iso_frame_desc[j].length = | 1095 | urb->iso_frame_desc[j].length = |
1087 | dev->isoc_ctl.max_pkt_size; | 1096 | isoc_bufs->max_pkt_size; |
1088 | k += dev->isoc_ctl.max_pkt_size; | 1097 | k += isoc_bufs->max_pkt_size; |
1089 | } | 1098 | } |
1090 | } | 1099 | } |
1091 | 1100 | ||
1101 | return 0; | ||
1102 | } | ||
1103 | EXPORT_SYMBOL_GPL(em28xx_alloc_isoc); | ||
1104 | |||
1105 | /* | ||
1106 | * Allocate URBs and start IRQ | ||
1107 | */ | ||
1108 | int em28xx_init_isoc(struct em28xx *dev, enum em28xx_mode mode, | ||
1109 | int max_packets, int num_bufs, int max_pkt_size, | ||
1110 | int (*isoc_copy) (struct em28xx *dev, struct urb *urb)) | ||
1111 | { | ||
1112 | struct em28xx_dmaqueue *dma_q = &dev->vidq; | ||
1113 | struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq; | ||
1114 | struct em28xx_usb_isoc_bufs *isoc_bufs; | ||
1115 | int i; | ||
1116 | int rc; | ||
1117 | int alloc; | ||
1118 | |||
1119 | em28xx_isocdbg("em28xx: called em28xx_init_isoc in mode %d\n", mode); | ||
1120 | |||
1121 | dev->isoc_ctl.isoc_copy = isoc_copy; | ||
1122 | |||
1123 | if (mode == EM28XX_DIGITAL_MODE) { | ||
1124 | isoc_bufs = &dev->isoc_ctl.digital_bufs; | ||
1125 | /* no need to free/alloc isoc buffers in digital mode */ | ||
1126 | alloc = 0; | ||
1127 | } else { | ||
1128 | isoc_bufs = &dev->isoc_ctl.analog_bufs; | ||
1129 | alloc = 1; | ||
1130 | } | ||
1131 | |||
1132 | if (alloc) { | ||
1133 | rc = em28xx_alloc_isoc(dev, mode, max_packets, | ||
1134 | num_bufs, max_pkt_size); | ||
1135 | if (rc) | ||
1136 | return rc; | ||
1137 | } | ||
1138 | |||
1092 | init_waitqueue_head(&dma_q->wq); | 1139 | init_waitqueue_head(&dma_q->wq); |
1093 | init_waitqueue_head(&vbi_dma_q->wq); | 1140 | init_waitqueue_head(&vbi_dma_q->wq); |
1094 | 1141 | ||
1095 | em28xx_capture_start(dev, 1); | 1142 | em28xx_capture_start(dev, 1); |
1096 | 1143 | ||
1097 | /* submit urbs and enables IRQ */ | 1144 | /* submit urbs and enables IRQ */ |
1098 | for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { | 1145 | for (i = 0; i < isoc_bufs->num_bufs; i++) { |
1099 | rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC); | 1146 | rc = usb_submit_urb(isoc_bufs->urb[i], GFP_ATOMIC); |
1100 | if (rc) { | 1147 | if (rc) { |
1101 | em28xx_err("submit of urb %i failed (error=%i)\n", i, | 1148 | em28xx_err("submit of urb %i failed (error=%i)\n", i, |
1102 | rc); | 1149 | rc); |
1103 | em28xx_uninit_isoc(dev); | 1150 | em28xx_uninit_isoc(dev, mode); |
1104 | return rc; | 1151 | return rc; |
1105 | } | 1152 | } |
1106 | } | 1153 | } |
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index aabbf4854f66..503a8d5b5382 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c | |||
@@ -61,9 +61,6 @@ if (debug >= level) \ | |||
61 | printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \ | 61 | printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \ |
62 | } while (0) | 62 | } while (0) |
63 | 63 | ||
64 | #define EM28XX_DVB_NUM_BUFS 5 | ||
65 | #define EM28XX_DVB_MAX_PACKETS 64 | ||
66 | |||
67 | struct em28xx_dvb { | 64 | struct em28xx_dvb { |
68 | struct dvb_frontend *fe[2]; | 65 | struct dvb_frontend *fe[2]; |
69 | 66 | ||
@@ -172,20 +169,21 @@ static int em28xx_start_streaming(struct em28xx_dvb *dvb) | |||
172 | max_dvb_packet_size = dev->dvb_max_pkt_size; | 169 | max_dvb_packet_size = dev->dvb_max_pkt_size; |
173 | if (max_dvb_packet_size < 0) | 170 | if (max_dvb_packet_size < 0) |
174 | return max_dvb_packet_size; | 171 | return max_dvb_packet_size; |
175 | dprintk(1, "Using %d buffers each with %d bytes\n", | 172 | dprintk(1, "Using %d buffers each with %d x %d bytes\n", |
176 | EM28XX_DVB_NUM_BUFS, | 173 | EM28XX_DVB_NUM_BUFS, |
174 | EM28XX_DVB_MAX_PACKETS, | ||
177 | max_dvb_packet_size); | 175 | max_dvb_packet_size); |
178 | 176 | ||
179 | return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS, | 177 | return em28xx_init_isoc(dev, EM28XX_DIGITAL_MODE, |
180 | EM28XX_DVB_NUM_BUFS, max_dvb_packet_size, | 178 | EM28XX_DVB_MAX_PACKETS, EM28XX_DVB_NUM_BUFS, |
181 | em28xx_dvb_isoc_copy); | 179 | max_dvb_packet_size, em28xx_dvb_isoc_copy); |
182 | } | 180 | } |
183 | 181 | ||
184 | static int em28xx_stop_streaming(struct em28xx_dvb *dvb) | 182 | static int em28xx_stop_streaming(struct em28xx_dvb *dvb) |
185 | { | 183 | { |
186 | struct em28xx *dev = dvb->adapter.priv; | 184 | struct em28xx *dev = dvb->adapter.priv; |
187 | 185 | ||
188 | em28xx_uninit_isoc(dev); | 186 | em28xx_capture_start(dev, 0); |
189 | 187 | ||
190 | em28xx_set_mode(dev, EM28XX_SUSPEND); | 188 | em28xx_set_mode(dev, EM28XX_SUSPEND); |
191 | 189 | ||
@@ -327,6 +325,19 @@ struct drxk_config hauppauge_930c_drxk = { | |||
327 | .chunk_size = 56, | 325 | .chunk_size = 56, |
328 | }; | 326 | }; |
329 | 327 | ||
328 | struct drxk_config maxmedia_ub425_tc_drxk = { | ||
329 | .adr = 0x29, | ||
330 | .single_master = 1, | ||
331 | .no_i2c_bridge = 1, | ||
332 | }; | ||
333 | |||
334 | struct drxk_config pctv_520e_drxk = { | ||
335 | .adr = 0x29, | ||
336 | .single_master = 1, | ||
337 | .microcode_name = "dvb-demod-drxk-pctv.fw", | ||
338 | .chunk_size = 58, | ||
339 | }; | ||
340 | |||
330 | static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) | 341 | static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) |
331 | { | 342 | { |
332 | struct em28xx_dvb *dvb = fe->sec_priv; | 343 | struct em28xx_dvb *dvb = fe->sec_priv; |
@@ -460,6 +471,33 @@ static void terratec_h5_init(struct em28xx *dev) | |||
460 | em28xx_gpio_set(dev, terratec_h5_end); | 471 | em28xx_gpio_set(dev, terratec_h5_end); |
461 | }; | 472 | }; |
462 | 473 | ||
474 | static void pctv_520e_init(struct em28xx *dev) | ||
475 | { | ||
476 | /* | ||
477 | * Init TDA8295(?) analog demodulator. Looks like I2C traffic to | ||
478 | * digital demodulator and tuner are routed via TDA8295. | ||
479 | */ | ||
480 | int i; | ||
481 | struct { | ||
482 | unsigned char r[4]; | ||
483 | int len; | ||
484 | } regs[] = { | ||
485 | {{ 0x06, 0x02, 0x00, 0x31 }, 4}, | ||
486 | {{ 0x01, 0x02 }, 2}, | ||
487 | {{ 0x01, 0x02, 0x00, 0xc6 }, 4}, | ||
488 | {{ 0x01, 0x00 }, 2}, | ||
489 | {{ 0x01, 0x00, 0xff, 0xaf }, 4}, | ||
490 | {{ 0x01, 0x00, 0x03, 0xa0 }, 4}, | ||
491 | {{ 0x01, 0x00 }, 2}, | ||
492 | {{ 0x01, 0x00, 0x73, 0xaf }, 4}, | ||
493 | }; | ||
494 | |||
495 | dev->i2c_client.addr = 0x82 >> 1; /* 0x41 */ | ||
496 | |||
497 | for (i = 0; i < ARRAY_SIZE(regs); i++) | ||
498 | i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len); | ||
499 | }; | ||
500 | |||
463 | static int em28xx_mt352_terratec_xs_init(struct dvb_frontend *fe) | 501 | static int em28xx_mt352_terratec_xs_init(struct dvb_frontend *fe) |
464 | { | 502 | { |
465 | /* Values extracted from a USB trace of the Terratec Windows driver */ | 503 | /* Values extracted from a USB trace of the Terratec Windows driver */ |
@@ -938,6 +976,48 @@ static int em28xx_dvb_init(struct em28xx *dev) | |||
938 | dvb_attach(a8293_attach, dvb->fe[0], &dev->i2c_adap, | 976 | dvb_attach(a8293_attach, dvb->fe[0], &dev->i2c_adap, |
939 | &em28xx_a8293_config); | 977 | &em28xx_a8293_config); |
940 | break; | 978 | break; |
979 | case EM2874_BOARD_MAXMEDIA_UB425_TC: | ||
980 | /* attach demodulator */ | ||
981 | dvb->fe[0] = dvb_attach(drxk_attach, &maxmedia_ub425_tc_drxk, | ||
982 | &dev->i2c_adap); | ||
983 | |||
984 | if (dvb->fe[0]) { | ||
985 | /* disable I2C-gate */ | ||
986 | dvb->fe[0]->ops.i2c_gate_ctrl = NULL; | ||
987 | |||
988 | /* attach tuner */ | ||
989 | if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0], | ||
990 | &dev->i2c_adap, 0x60)) { | ||
991 | dvb_frontend_detach(dvb->fe[0]); | ||
992 | result = -EINVAL; | ||
993 | goto out_free; | ||
994 | } | ||
995 | } | ||
996 | |||
997 | /* TODO: we need drx-3913k firmware in order to support DVB-T */ | ||
998 | em28xx_info("MaxMedia UB425-TC: only DVB-C supported by that " \ | ||
999 | "driver version\n"); | ||
1000 | |||
1001 | break; | ||
1002 | case EM2884_BOARD_PCTV_510E: | ||
1003 | case EM2884_BOARD_PCTV_520E: | ||
1004 | pctv_520e_init(dev); | ||
1005 | |||
1006 | /* attach demodulator */ | ||
1007 | dvb->fe[0] = dvb_attach(drxk_attach, &pctv_520e_drxk, | ||
1008 | &dev->i2c_adap); | ||
1009 | |||
1010 | if (dvb->fe[0]) { | ||
1011 | /* attach tuner */ | ||
1012 | if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, | ||
1013 | &dev->i2c_adap, | ||
1014 | &em28xx_cxd2820r_tda18271_config)) { | ||
1015 | dvb_frontend_detach(dvb->fe[0]); | ||
1016 | result = -EINVAL; | ||
1017 | goto out_free; | ||
1018 | } | ||
1019 | } | ||
1020 | break; | ||
941 | default: | 1021 | default: |
942 | em28xx_errdev("/2: The frontend of your DVB/ATSC card" | 1022 | em28xx_errdev("/2: The frontend of your DVB/ATSC card" |
943 | " isn't supported yet\n"); | 1023 | " isn't supported yet\n"); |
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 36f5a9bc8b76..a88e169dba23 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c | |||
@@ -41,14 +41,6 @@ static unsigned int i2c_debug; | |||
41 | module_param(i2c_debug, int, 0644); | 41 | module_param(i2c_debug, int, 0644); |
42 | MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); | 42 | MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); |
43 | 43 | ||
44 | |||
45 | #define dprintk1(lvl, fmt, args...) \ | ||
46 | do { \ | ||
47 | if (i2c_debug >= lvl) { \ | ||
48 | printk(fmt, ##args); \ | ||
49 | } \ | ||
50 | } while (0) | ||
51 | |||
52 | #define dprintk2(lvl, fmt, args...) \ | 44 | #define dprintk2(lvl, fmt, args...) \ |
53 | do { \ | 45 | do { \ |
54 | if (i2c_debug >= lvl) { \ | 46 | if (i2c_debug >= lvl) { \ |
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 613300b51a9e..324b695c0724 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -760,17 +760,19 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, | |||
760 | goto fail; | 760 | goto fail; |
761 | } | 761 | } |
762 | 762 | ||
763 | if (!dev->isoc_ctl.num_bufs) | 763 | if (!dev->isoc_ctl.analog_bufs.num_bufs) |
764 | urb_init = 1; | 764 | urb_init = 1; |
765 | 765 | ||
766 | if (urb_init) { | 766 | if (urb_init) { |
767 | if (em28xx_vbi_supported(dev) == 1) | 767 | if (em28xx_vbi_supported(dev) == 1) |
768 | rc = em28xx_init_isoc(dev, EM28XX_NUM_PACKETS, | 768 | rc = em28xx_init_isoc(dev, EM28XX_ANALOG_MODE, |
769 | EM28XX_NUM_PACKETS, | ||
769 | EM28XX_NUM_BUFS, | 770 | EM28XX_NUM_BUFS, |
770 | dev->max_pkt_size, | 771 | dev->max_pkt_size, |
771 | em28xx_isoc_copy_vbi); | 772 | em28xx_isoc_copy_vbi); |
772 | else | 773 | else |
773 | rc = em28xx_init_isoc(dev, EM28XX_NUM_PACKETS, | 774 | rc = em28xx_init_isoc(dev, EM28XX_ANALOG_MODE, |
775 | EM28XX_NUM_PACKETS, | ||
774 | EM28XX_NUM_BUFS, | 776 | EM28XX_NUM_BUFS, |
775 | dev->max_pkt_size, | 777 | dev->max_pkt_size, |
776 | em28xx_isoc_copy); | 778 | em28xx_isoc_copy); |
@@ -2267,7 +2269,7 @@ static int em28xx_v4l2_close(struct file *filp) | |||
2267 | v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0); | 2269 | v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0); |
2268 | 2270 | ||
2269 | /* do this before setting alternate! */ | 2271 | /* do this before setting alternate! */ |
2270 | em28xx_uninit_isoc(dev); | 2272 | em28xx_uninit_isoc(dev, EM28XX_ANALOG_MODE); |
2271 | em28xx_set_mode(dev, EM28XX_SUSPEND); | 2273 | em28xx_set_mode(dev, EM28XX_SUSPEND); |
2272 | 2274 | ||
2273 | /* set alternate 0 */ | 2275 | /* set alternate 0 */ |
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 22e252bcc41e..2868b19f8b54 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
@@ -125,6 +125,9 @@ | |||
125 | #define EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C 81 | 125 | #define EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C 81 |
126 | #define EM2884_BOARD_CINERGY_HTC_STICK 82 | 126 | #define EM2884_BOARD_CINERGY_HTC_STICK 82 |
127 | #define EM2860_BOARD_HT_VIDBOX_NW03 83 | 127 | #define EM2860_BOARD_HT_VIDBOX_NW03 83 |
128 | #define EM2874_BOARD_MAXMEDIA_UB425_TC 84 | ||
129 | #define EM2884_BOARD_PCTV_510E 85 | ||
130 | #define EM2884_BOARD_PCTV_520E 86 | ||
128 | 131 | ||
129 | /* Limits minimum and default number of buffers */ | 132 | /* Limits minimum and default number of buffers */ |
130 | #define EM28XX_MIN_BUF 4 | 133 | #define EM28XX_MIN_BUF 4 |
@@ -151,12 +154,14 @@ | |||
151 | 154 | ||
152 | /* number of buffers for isoc transfers */ | 155 | /* number of buffers for isoc transfers */ |
153 | #define EM28XX_NUM_BUFS 5 | 156 | #define EM28XX_NUM_BUFS 5 |
157 | #define EM28XX_DVB_NUM_BUFS 5 | ||
154 | 158 | ||
155 | /* number of packets for each buffer | 159 | /* number of packets for each buffer |
156 | windows requests only 64 packets .. so we better do the same | 160 | windows requests only 64 packets .. so we better do the same |
157 | this is what I found out for all alternate numbers there! | 161 | this is what I found out for all alternate numbers there! |
158 | */ | 162 | */ |
159 | #define EM28XX_NUM_PACKETS 64 | 163 | #define EM28XX_NUM_PACKETS 64 |
164 | #define EM28XX_DVB_MAX_PACKETS 64 | ||
160 | 165 | ||
161 | #define EM28XX_INTERLACED_DEFAULT 1 | 166 | #define EM28XX_INTERLACED_DEFAULT 1 |
162 | 167 | ||
@@ -197,10 +202,13 @@ enum em28xx_mode { | |||
197 | 202 | ||
198 | struct em28xx; | 203 | struct em28xx; |
199 | 204 | ||
200 | struct em28xx_usb_isoc_ctl { | 205 | struct em28xx_usb_isoc_bufs { |
201 | /* max packet size of isoc transaction */ | 206 | /* max packet size of isoc transaction */ |
202 | int max_pkt_size; | 207 | int max_pkt_size; |
203 | 208 | ||
209 | /* number of packets in each buffer */ | ||
210 | int num_packets; | ||
211 | |||
204 | /* number of allocated urbs */ | 212 | /* number of allocated urbs */ |
205 | int num_bufs; | 213 | int num_bufs; |
206 | 214 | ||
@@ -209,6 +217,14 @@ struct em28xx_usb_isoc_ctl { | |||
209 | 217 | ||
210 | /* transfer buffers for isoc transfer */ | 218 | /* transfer buffers for isoc transfer */ |
211 | char **transfer_buffer; | 219 | char **transfer_buffer; |
220 | }; | ||
221 | |||
222 | struct em28xx_usb_isoc_ctl { | ||
223 | /* isoc transfer buffers for analog mode */ | ||
224 | struct em28xx_usb_isoc_bufs analog_bufs; | ||
225 | |||
226 | /* isoc transfer buffers for digital mode */ | ||
227 | struct em28xx_usb_isoc_bufs digital_bufs; | ||
212 | 228 | ||
213 | /* Last buffer command and region */ | 229 | /* Last buffer command and region */ |
214 | u8 cmd; | 230 | u8 cmd; |
@@ -600,9 +616,6 @@ struct em28xx { | |||
600 | unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ | 616 | unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ |
601 | int dvb_alt; /* alternate for DVB */ | 617 | int dvb_alt; /* alternate for DVB */ |
602 | unsigned int dvb_max_pkt_size; /* wMaxPacketSize for DVB */ | 618 | unsigned int dvb_max_pkt_size; /* wMaxPacketSize for DVB */ |
603 | struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */ | ||
604 | char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc | ||
605 | transfer */ | ||
606 | char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */ | 619 | char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */ |
607 | 620 | ||
608 | /* helper funcs that call usb_control_msg */ | 621 | /* helper funcs that call usb_control_msg */ |
@@ -676,10 +689,12 @@ int em28xx_vbi_supported(struct em28xx *dev); | |||
676 | int em28xx_set_outfmt(struct em28xx *dev); | 689 | int em28xx_set_outfmt(struct em28xx *dev); |
677 | int em28xx_resolution_set(struct em28xx *dev); | 690 | int em28xx_resolution_set(struct em28xx *dev); |
678 | int em28xx_set_alternate(struct em28xx *dev); | 691 | int em28xx_set_alternate(struct em28xx *dev); |
679 | int em28xx_init_isoc(struct em28xx *dev, int max_packets, | 692 | int em28xx_alloc_isoc(struct em28xx *dev, enum em28xx_mode mode, |
680 | int num_bufs, int max_pkt_size, | 693 | int max_packets, int num_bufs, int max_pkt_size); |
694 | int em28xx_init_isoc(struct em28xx *dev, enum em28xx_mode mode, | ||
695 | int max_packets, int num_bufs, int max_pkt_size, | ||
681 | int (*isoc_copy) (struct em28xx *dev, struct urb *urb)); | 696 | int (*isoc_copy) (struct em28xx *dev, struct urb *urb)); |
682 | void em28xx_uninit_isoc(struct em28xx *dev); | 697 | void em28xx_uninit_isoc(struct em28xx *dev, enum em28xx_mode mode); |
683 | int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev); | 698 | int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev); |
684 | int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode); | 699 | int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode); |
685 | int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio); | 700 | int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio); |
diff --git a/drivers/media/video/gspca/gl860/Makefile b/drivers/media/video/gspca/gl860/Makefile index f511eccdfd9c..773ea3426561 100644 --- a/drivers/media/video/gspca/gl860/Makefile +++ b/drivers/media/video/gspca/gl860/Makefile | |||
@@ -6,5 +6,5 @@ gspca_gl860-objs := gl860.o \ | |||
6 | gl860-ov9655.o \ | 6 | gl860-ov9655.o \ |
7 | gl860-mi2020.o | 7 | gl860-mi2020.o |
8 | 8 | ||
9 | ccflags-y += -Idrivers/media/video/gspca | 9 | ccflags-y += -I$(srctree)/drivers/media/video/gspca |
10 | 10 | ||
diff --git a/drivers/media/video/gspca/m5602/Makefile b/drivers/media/video/gspca/m5602/Makefile index 7f52961f439c..575b75bacb62 100644 --- a/drivers/media/video/gspca/m5602/Makefile +++ b/drivers/media/video/gspca/m5602/Makefile | |||
@@ -8,4 +8,4 @@ gspca_m5602-objs := m5602_core.o \ | |||
8 | m5602_s5k83a.o \ | 8 | m5602_s5k83a.o \ |
9 | m5602_s5k4aa.o | 9 | m5602_s5k4aa.o |
10 | 10 | ||
11 | ccflags-y += -Idrivers/media/video/gspca | 11 | ccflags-y += -I$(srctree)/drivers/media/video/gspca |
diff --git a/drivers/media/video/gspca/ov534_9.c b/drivers/media/video/gspca/ov534_9.c index fbfa02affa13..e6601b886032 100644 --- a/drivers/media/video/gspca/ov534_9.c +++ b/drivers/media/video/gspca/ov534_9.c | |||
@@ -1107,16 +1107,34 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
1107 | { | 1107 | { |
1108 | struct sd *sd = (struct sd *) gspca_dev; | 1108 | struct sd *sd = (struct sd *) gspca_dev; |
1109 | u8 val; | 1109 | u8 val; |
1110 | s8 sval; | ||
1110 | 1111 | ||
1111 | if (gspca_dev->ctrl_dis & (1 << BRIGHTNESS)) | 1112 | if (gspca_dev->ctrl_dis & (1 << BRIGHTNESS)) |
1112 | return; | 1113 | return; |
1113 | val = sd->ctrls[BRIGHTNESS].val; | 1114 | if (sd->sensor == SENSOR_OV562x) { |
1114 | if (val < 8) | 1115 | sval = sd->ctrls[BRIGHTNESS].val; |
1115 | val = 15 - val; /* f .. 8 */ | 1116 | val = 0x76; |
1116 | else | 1117 | val += sval; |
1117 | val = val - 8; /* 0 .. 7 */ | 1118 | sccb_write(gspca_dev, 0x24, val); |
1118 | sccb_write(gspca_dev, 0x55, /* brtn - brightness adjustment */ | 1119 | val = 0x6a; |
1119 | 0x0f | (val << 4)); | 1120 | val += sval; |
1121 | sccb_write(gspca_dev, 0x25, val); | ||
1122 | if (sval < -40) | ||
1123 | val = 0x71; | ||
1124 | else if (sval < 20) | ||
1125 | val = 0x94; | ||
1126 | else | ||
1127 | val = 0xe6; | ||
1128 | sccb_write(gspca_dev, 0x26, val); | ||
1129 | } else { | ||
1130 | val = sd->ctrls[BRIGHTNESS].val; | ||
1131 | if (val < 8) | ||
1132 | val = 15 - val; /* f .. 8 */ | ||
1133 | else | ||
1134 | val = val - 8; /* 0 .. 7 */ | ||
1135 | sccb_write(gspca_dev, 0x55, /* brtn - brightness adjustment */ | ||
1136 | 0x0f | (val << 4)); | ||
1137 | } | ||
1120 | } | 1138 | } |
1121 | 1139 | ||
1122 | static void setcontrast(struct gspca_dev *gspca_dev) | 1140 | static void setcontrast(struct gspca_dev *gspca_dev) |
@@ -1339,7 +1357,16 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1339 | reg_w(gspca_dev, 0x56, 0x17); | 1357 | reg_w(gspca_dev, 0x56, 0x17); |
1340 | } else if ((sensor_id & 0xfff0) == 0x5620) { | 1358 | } else if ((sensor_id & 0xfff0) == 0x5620) { |
1341 | sd->sensor = SENSOR_OV562x; | 1359 | sd->sensor = SENSOR_OV562x; |
1342 | 1360 | gspca_dev->ctrl_dis = (1 << CONTRAST) | | |
1361 | (1 << AUTOGAIN) | | ||
1362 | (1 << EXPOSURE) | | ||
1363 | (1 << SHARPNESS) | | ||
1364 | (1 << SATUR) | | ||
1365 | (1 << LIGHTFREQ); | ||
1366 | |||
1367 | sd->ctrls[BRIGHTNESS].min = -90; | ||
1368 | sd->ctrls[BRIGHTNESS].max = 90; | ||
1369 | sd->ctrls[BRIGHTNESS].def = 0; | ||
1343 | gspca_dev->cam.cam_mode = ov562x_mode; | 1370 | gspca_dev->cam.cam_mode = ov562x_mode; |
1344 | gspca_dev->cam.nmodes = ARRAY_SIZE(ov562x_mode); | 1371 | gspca_dev->cam.nmodes = ARRAY_SIZE(ov562x_mode); |
1345 | 1372 | ||
@@ -1360,8 +1387,12 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1360 | { | 1387 | { |
1361 | struct sd *sd = (struct sd *) gspca_dev; | 1388 | struct sd *sd = (struct sd *) gspca_dev; |
1362 | 1389 | ||
1363 | if (sd->sensor == SENSOR_OV971x || sd->sensor == SENSOR_OV562x) | 1390 | if (sd->sensor == SENSOR_OV971x) |
1364 | return gspca_dev->usb_err; | 1391 | return gspca_dev->usb_err; |
1392 | else if (sd->sensor == SENSOR_OV562x) { | ||
1393 | setbrightness(gspca_dev); | ||
1394 | return gspca_dev->usb_err; | ||
1395 | } | ||
1365 | switch (gspca_dev->curr_mode) { | 1396 | switch (gspca_dev->curr_mode) { |
1366 | case QVGA_MODE: /* 320x240 */ | 1397 | case QVGA_MODE: /* 320x240 */ |
1367 | sccb_w_array(gspca_dev, ov965x_start_1_vga, | 1398 | sccb_w_array(gspca_dev, ov965x_start_1_vga, |
diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index 9db2b34d172c..30662fccb0cf 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Pixart PAC7302 library | 2 | * Pixart PAC7302 driver |
3 | * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li | ||
4 | * | 3 | * |
5 | * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> | 4 | * Copyright (C) 2008-2012 Jean-Francois Moine <http://moinejf.free.fr> |
5 | * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li | ||
6 | * | 6 | * |
7 | * Separated from Pixart PAC7311 library by Márton Németh | 7 | * Separated from Pixart PAC7311 library by Márton Németh |
8 | * Camera button input handling by Márton Németh <nm127@freemail.hu> | 8 | * Camera button input handling by Márton Németh <nm127@freemail.hu> |
@@ -63,67 +63,61 @@ | |||
63 | 63 | ||
64 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 64 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
65 | 65 | ||
66 | #define MODULE_NAME "pac7302" | ||
67 | |||
68 | #include <linux/input.h> | 66 | #include <linux/input.h> |
69 | #include <media/v4l2-chip-ident.h> | 67 | #include <media/v4l2-chip-ident.h> |
70 | #include "gspca.h" | 68 | #include "gspca.h" |
69 | /* Include pac common sof detection functions */ | ||
70 | #include "pac_common.h" | ||
71 | 71 | ||
72 | MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); | 72 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, " |
73 | "Thomas Kaiser thomas@kaiser-linux.li"); | ||
73 | MODULE_DESCRIPTION("Pixart PAC7302"); | 74 | MODULE_DESCRIPTION("Pixart PAC7302"); |
74 | MODULE_LICENSE("GPL"); | 75 | MODULE_LICENSE("GPL"); |
75 | 76 | ||
77 | enum e_ctrl { | ||
78 | BRIGHTNESS, | ||
79 | CONTRAST, | ||
80 | COLORS, | ||
81 | WHITE_BALANCE, | ||
82 | RED_BALANCE, | ||
83 | BLUE_BALANCE, | ||
84 | GAIN, | ||
85 | AUTOGAIN, | ||
86 | EXPOSURE, | ||
87 | VFLIP, | ||
88 | HFLIP, | ||
89 | NCTRLS /* number of controls */ | ||
90 | }; | ||
91 | |||
76 | /* specific webcam descriptor for pac7302 */ | 92 | /* specific webcam descriptor for pac7302 */ |
77 | struct sd { | 93 | struct sd { |
78 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 94 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
79 | 95 | ||
80 | unsigned char brightness; | 96 | struct gspca_ctrl ctrls[NCTRLS]; |
81 | unsigned char contrast; | 97 | |
82 | unsigned char colors; | ||
83 | unsigned char white_balance; | ||
84 | unsigned char red_balance; | ||
85 | unsigned char blue_balance; | ||
86 | unsigned char gain; | ||
87 | unsigned char autogain; | ||
88 | unsigned short exposure; | ||
89 | __u8 hflip; | ||
90 | __u8 vflip; | ||
91 | u8 flags; | 98 | u8 flags; |
92 | #define FL_HFLIP 0x01 /* mirrored by default */ | 99 | #define FL_HFLIP 0x01 /* mirrored by default */ |
93 | #define FL_VFLIP 0x02 /* vertical flipped by default */ | 100 | #define FL_VFLIP 0x02 /* vertical flipped by default */ |
94 | 101 | ||
95 | u8 sof_read; | 102 | u8 sof_read; |
96 | u8 autogain_ignore_frames; | 103 | s8 autogain_ignore_frames; |
97 | 104 | ||
98 | atomic_t avg_lum; | 105 | atomic_t avg_lum; |
99 | }; | 106 | }; |
100 | 107 | ||
101 | /* V4L2 controls supported by the driver */ | 108 | /* V4L2 controls supported by the driver */ |
102 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | 109 | static void setbrightcont(struct gspca_dev *gspca_dev); |
103 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | 110 | static void setcolors(struct gspca_dev *gspca_dev); |
104 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | 111 | static void setwhitebalance(struct gspca_dev *gspca_dev); |
105 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | 112 | static void setredbalance(struct gspca_dev *gspca_dev); |
106 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); | 113 | static void setbluebalance(struct gspca_dev *gspca_dev); |
107 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | 114 | static void setgain(struct gspca_dev *gspca_dev); |
108 | static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val); | 115 | static void setexposure(struct gspca_dev *gspca_dev); |
109 | static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val); | 116 | static void setautogain(struct gspca_dev *gspca_dev); |
110 | static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val); | 117 | static void sethvflip(struct gspca_dev *gspca_dev); |
111 | static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val); | ||
112 | static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val); | ||
113 | static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val); | ||
114 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
115 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | ||
116 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); | ||
117 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
118 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); | ||
119 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); | ||
120 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); | ||
121 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | ||
122 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | ||
123 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
124 | 118 | ||
125 | static const struct ctrl sd_ctrls[] = { | 119 | static const struct ctrl sd_ctrls[] = { |
126 | { | 120 | [BRIGHTNESS] = { |
127 | { | 121 | { |
128 | .id = V4L2_CID_BRIGHTNESS, | 122 | .id = V4L2_CID_BRIGHTNESS, |
129 | .type = V4L2_CTRL_TYPE_INTEGER, | 123 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -132,13 +126,11 @@ static const struct ctrl sd_ctrls[] = { | |||
132 | #define BRIGHTNESS_MAX 0x20 | 126 | #define BRIGHTNESS_MAX 0x20 |
133 | .maximum = BRIGHTNESS_MAX, | 127 | .maximum = BRIGHTNESS_MAX, |
134 | .step = 1, | 128 | .step = 1, |
135 | #define BRIGHTNESS_DEF 0x10 | 129 | .default_value = 0x10, |
136 | .default_value = BRIGHTNESS_DEF, | ||
137 | }, | 130 | }, |
138 | .set = sd_setbrightness, | 131 | .set_control = setbrightcont |
139 | .get = sd_getbrightness, | ||
140 | }, | 132 | }, |
141 | { | 133 | [CONTRAST] = { |
142 | { | 134 | { |
143 | .id = V4L2_CID_CONTRAST, | 135 | .id = V4L2_CID_CONTRAST, |
144 | .type = V4L2_CTRL_TYPE_INTEGER, | 136 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -147,13 +139,11 @@ static const struct ctrl sd_ctrls[] = { | |||
147 | #define CONTRAST_MAX 255 | 139 | #define CONTRAST_MAX 255 |
148 | .maximum = CONTRAST_MAX, | 140 | .maximum = CONTRAST_MAX, |
149 | .step = 1, | 141 | .step = 1, |
150 | #define CONTRAST_DEF 127 | 142 | .default_value = 127, |
151 | .default_value = CONTRAST_DEF, | ||
152 | }, | 143 | }, |
153 | .set = sd_setcontrast, | 144 | .set_control = setbrightcont |
154 | .get = sd_getcontrast, | ||
155 | }, | 145 | }, |
156 | { | 146 | [COLORS] = { |
157 | { | 147 | { |
158 | .id = V4L2_CID_SATURATION, | 148 | .id = V4L2_CID_SATURATION, |
159 | .type = V4L2_CTRL_TYPE_INTEGER, | 149 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -162,13 +152,11 @@ static const struct ctrl sd_ctrls[] = { | |||
162 | #define COLOR_MAX 255 | 152 | #define COLOR_MAX 255 |
163 | .maximum = COLOR_MAX, | 153 | .maximum = COLOR_MAX, |
164 | .step = 1, | 154 | .step = 1, |
165 | #define COLOR_DEF 127 | 155 | .default_value = 127 |
166 | .default_value = COLOR_DEF, | ||
167 | }, | 156 | }, |
168 | .set = sd_setcolors, | 157 | .set_control = setcolors |
169 | .get = sd_getcolors, | ||
170 | }, | 158 | }, |
171 | { | 159 | [WHITE_BALANCE] = { |
172 | { | 160 | { |
173 | .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE, | 161 | .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE, |
174 | .type = V4L2_CTRL_TYPE_INTEGER, | 162 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -176,13 +164,11 @@ static const struct ctrl sd_ctrls[] = { | |||
176 | .minimum = 0, | 164 | .minimum = 0, |
177 | .maximum = 255, | 165 | .maximum = 255, |
178 | .step = 1, | 166 | .step = 1, |
179 | #define WHITEBALANCE_DEF 4 | 167 | .default_value = 4, |
180 | .default_value = WHITEBALANCE_DEF, | ||
181 | }, | 168 | }, |
182 | .set = sd_setwhitebalance, | 169 | .set_control = setwhitebalance |
183 | .get = sd_getwhitebalance, | ||
184 | }, | 170 | }, |
185 | { | 171 | [RED_BALANCE] = { |
186 | { | 172 | { |
187 | .id = V4L2_CID_RED_BALANCE, | 173 | .id = V4L2_CID_RED_BALANCE, |
188 | .type = V4L2_CTRL_TYPE_INTEGER, | 174 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -190,13 +176,11 @@ static const struct ctrl sd_ctrls[] = { | |||
190 | .minimum = 0, | 176 | .minimum = 0, |
191 | .maximum = 3, | 177 | .maximum = 3, |
192 | .step = 1, | 178 | .step = 1, |
193 | #define REDBALANCE_DEF 1 | 179 | .default_value = 1, |
194 | .default_value = REDBALANCE_DEF, | ||
195 | }, | 180 | }, |
196 | .set = sd_setredbalance, | 181 | .set_control = setredbalance |
197 | .get = sd_getredbalance, | ||
198 | }, | 182 | }, |
199 | { | 183 | [BLUE_BALANCE] = { |
200 | { | 184 | { |
201 | .id = V4L2_CID_BLUE_BALANCE, | 185 | .id = V4L2_CID_BLUE_BALANCE, |
202 | .type = V4L2_CTRL_TYPE_INTEGER, | 186 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -204,29 +188,25 @@ static const struct ctrl sd_ctrls[] = { | |||
204 | .minimum = 0, | 188 | .minimum = 0, |
205 | .maximum = 3, | 189 | .maximum = 3, |
206 | .step = 1, | 190 | .step = 1, |
207 | #define BLUEBALANCE_DEF 1 | 191 | .default_value = 1, |
208 | .default_value = BLUEBALANCE_DEF, | ||
209 | }, | 192 | }, |
210 | .set = sd_setbluebalance, | 193 | .set_control = setbluebalance |
211 | .get = sd_getbluebalance, | ||
212 | }, | 194 | }, |
213 | { | 195 | [GAIN] = { |
214 | { | 196 | { |
215 | .id = V4L2_CID_GAIN, | 197 | .id = V4L2_CID_GAIN, |
216 | .type = V4L2_CTRL_TYPE_INTEGER, | 198 | .type = V4L2_CTRL_TYPE_INTEGER, |
217 | .name = "Gain", | 199 | .name = "Gain", |
218 | .minimum = 0, | 200 | .minimum = 0, |
219 | #define GAIN_MAX 255 | 201 | .maximum = 255, |
220 | .maximum = GAIN_MAX, | ||
221 | .step = 1, | 202 | .step = 1, |
222 | #define GAIN_DEF 127 | 203 | #define GAIN_DEF 127 |
223 | #define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */ | 204 | #define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */ |
224 | .default_value = GAIN_DEF, | 205 | .default_value = GAIN_DEF, |
225 | }, | 206 | }, |
226 | .set = sd_setgain, | 207 | .set_control = setgain |
227 | .get = sd_getgain, | ||
228 | }, | 208 | }, |
229 | { | 209 | [EXPOSURE] = { |
230 | { | 210 | { |
231 | .id = V4L2_CID_EXPOSURE, | 211 | .id = V4L2_CID_EXPOSURE, |
232 | .type = V4L2_CTRL_TYPE_INTEGER, | 212 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -238,10 +218,9 @@ static const struct ctrl sd_ctrls[] = { | |||
238 | #define EXPOSURE_KNEE 133 /* 66 ms / 15 fps */ | 218 | #define EXPOSURE_KNEE 133 /* 66 ms / 15 fps */ |
239 | .default_value = EXPOSURE_DEF, | 219 | .default_value = EXPOSURE_DEF, |
240 | }, | 220 | }, |
241 | .set = sd_setexposure, | 221 | .set_control = setexposure |
242 | .get = sd_getexposure, | ||
243 | }, | 222 | }, |
244 | { | 223 | [AUTOGAIN] = { |
245 | { | 224 | { |
246 | .id = V4L2_CID_AUTOGAIN, | 225 | .id = V4L2_CID_AUTOGAIN, |
247 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 226 | .type = V4L2_CTRL_TYPE_BOOLEAN, |
@@ -252,10 +231,9 @@ static const struct ctrl sd_ctrls[] = { | |||
252 | #define AUTOGAIN_DEF 1 | 231 | #define AUTOGAIN_DEF 1 |
253 | .default_value = AUTOGAIN_DEF, | 232 | .default_value = AUTOGAIN_DEF, |
254 | }, | 233 | }, |
255 | .set = sd_setautogain, | 234 | .set_control = setautogain, |
256 | .get = sd_getautogain, | ||
257 | }, | 235 | }, |
258 | { | 236 | [HFLIP] = { |
259 | { | 237 | { |
260 | .id = V4L2_CID_HFLIP, | 238 | .id = V4L2_CID_HFLIP, |
261 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 239 | .type = V4L2_CTRL_TYPE_BOOLEAN, |
@@ -263,13 +241,11 @@ static const struct ctrl sd_ctrls[] = { | |||
263 | .minimum = 0, | 241 | .minimum = 0, |
264 | .maximum = 1, | 242 | .maximum = 1, |
265 | .step = 1, | 243 | .step = 1, |
266 | #define HFLIP_DEF 0 | 244 | .default_value = 0, |
267 | .default_value = HFLIP_DEF, | ||
268 | }, | 245 | }, |
269 | .set = sd_sethflip, | 246 | .set_control = sethvflip, |
270 | .get = sd_gethflip, | ||
271 | }, | 247 | }, |
272 | { | 248 | [VFLIP] = { |
273 | { | 249 | { |
274 | .id = V4L2_CID_VFLIP, | 250 | .id = V4L2_CID_VFLIP, |
275 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 251 | .type = V4L2_CTRL_TYPE_BOOLEAN, |
@@ -277,11 +253,9 @@ static const struct ctrl sd_ctrls[] = { | |||
277 | .minimum = 0, | 253 | .minimum = 0, |
278 | .maximum = 1, | 254 | .maximum = 1, |
279 | .step = 1, | 255 | .step = 1, |
280 | #define VFLIP_DEF 0 | 256 | .default_value = 0, |
281 | .default_value = VFLIP_DEF, | ||
282 | }, | 257 | }, |
283 | .set = sd_setvflip, | 258 | .set_control = sethvflip |
284 | .get = sd_getvflip, | ||
285 | }, | 259 | }, |
286 | }; | 260 | }; |
287 | 261 | ||
@@ -290,21 +264,21 @@ static const struct v4l2_pix_format vga_mode[] = { | |||
290 | .bytesperline = 640, | 264 | .bytesperline = 640, |
291 | .sizeimage = 640 * 480 * 3 / 8 + 590, | 265 | .sizeimage = 640 * 480 * 3 / 8 + 590, |
292 | .colorspace = V4L2_COLORSPACE_JPEG, | 266 | .colorspace = V4L2_COLORSPACE_JPEG, |
293 | .priv = 0}, | 267 | }, |
294 | }; | 268 | }; |
295 | 269 | ||
296 | #define LOAD_PAGE3 255 | 270 | #define LOAD_PAGE3 255 |
297 | #define END_OF_SEQUENCE 0 | 271 | #define END_OF_SEQUENCE 0 |
298 | 272 | ||
299 | /* pac 7302 */ | 273 | /* pac 7302 */ |
300 | static const __u8 init_7302[] = { | 274 | static const u8 init_7302[] = { |
301 | /* index,value */ | 275 | /* index,value */ |
302 | 0xff, 0x01, /* page 1 */ | 276 | 0xff, 0x01, /* page 1 */ |
303 | 0x78, 0x00, /* deactivate */ | 277 | 0x78, 0x00, /* deactivate */ |
304 | 0xff, 0x01, | 278 | 0xff, 0x01, |
305 | 0x78, 0x40, /* led off */ | 279 | 0x78, 0x40, /* led off */ |
306 | }; | 280 | }; |
307 | static const __u8 start_7302[] = { | 281 | static const u8 start_7302[] = { |
308 | /* index, len, [value]* */ | 282 | /* index, len, [value]* */ |
309 | 0xff, 1, 0x00, /* page 0 */ | 283 | 0xff, 1, 0x00, /* page 0 */ |
310 | 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80, | 284 | 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80, |
@@ -319,7 +293,7 @@ static const __u8 start_7302[] = { | |||
319 | 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11, | 293 | 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11, |
320 | 0x00, 0x54, 0x11, | 294 | 0x00, 0x54, 0x11, |
321 | 0x55, 1, 0x00, | 295 | 0x55, 1, 0x00, |
322 | 0x62, 4, 0x10, 0x1e, 0x1e, 0x18, | 296 | 0x62, 4, 0x10, 0x1e, 0x1e, 0x18, |
323 | 0x6b, 1, 0x00, | 297 | 0x6b, 1, 0x00, |
324 | 0x6e, 3, 0x08, 0x06, 0x00, | 298 | 0x6e, 3, 0x08, 0x06, 0x00, |
325 | 0x72, 3, 0x00, 0xff, 0x00, | 299 | 0x72, 3, 0x00, 0xff, 0x00, |
@@ -370,7 +344,7 @@ static const __u8 start_7302[] = { | |||
370 | 344 | ||
371 | #define SKIP 0xaa | 345 | #define SKIP 0xaa |
372 | /* page 3 - the value SKIP says skip the index - see reg_w_page() */ | 346 | /* page 3 - the value SKIP says skip the index - see reg_w_page() */ |
373 | static const __u8 page3_7302[] = { | 347 | static const u8 page3_7302[] = { |
374 | 0x90, 0x40, 0x03, 0x00, 0xc0, 0x01, 0x14, 0x16, | 348 | 0x90, 0x40, 0x03, 0x00, 0xc0, 0x01, 0x14, 0x16, |
375 | 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00, | 349 | 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00, |
376 | 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 350 | 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
@@ -394,7 +368,7 @@ static const __u8 page3_7302[] = { | |||
394 | }; | 368 | }; |
395 | 369 | ||
396 | static void reg_w_buf(struct gspca_dev *gspca_dev, | 370 | static void reg_w_buf(struct gspca_dev *gspca_dev, |
397 | __u8 index, | 371 | u8 index, |
398 | const u8 *buffer, int len) | 372 | const u8 *buffer, int len) |
399 | { | 373 | { |
400 | int ret; | 374 | int ret; |
@@ -410,7 +384,7 @@ static void reg_w_buf(struct gspca_dev *gspca_dev, | |||
410 | index, gspca_dev->usb_buf, len, | 384 | index, gspca_dev->usb_buf, len, |
411 | 500); | 385 | 500); |
412 | if (ret < 0) { | 386 | if (ret < 0) { |
413 | pr_err("reg_w_buf failed index 0x%02x, error %d\n", | 387 | pr_err("reg_w_buf failed i: %02x error %d\n", |
414 | index, ret); | 388 | index, ret); |
415 | gspca_dev->usb_err = ret; | 389 | gspca_dev->usb_err = ret; |
416 | } | 390 | } |
@@ -418,8 +392,8 @@ static void reg_w_buf(struct gspca_dev *gspca_dev, | |||
418 | 392 | ||
419 | 393 | ||
420 | static void reg_w(struct gspca_dev *gspca_dev, | 394 | static void reg_w(struct gspca_dev *gspca_dev, |
421 | __u8 index, | 395 | u8 index, |
422 | __u8 value) | 396 | u8 value) |
423 | { | 397 | { |
424 | int ret; | 398 | int ret; |
425 | 399 | ||
@@ -433,14 +407,14 @@ static void reg_w(struct gspca_dev *gspca_dev, | |||
433 | 0, index, gspca_dev->usb_buf, 1, | 407 | 0, index, gspca_dev->usb_buf, 1, |
434 | 500); | 408 | 500); |
435 | if (ret < 0) { | 409 | if (ret < 0) { |
436 | pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n", | 410 | pr_err("reg_w() failed i: %02x v: %02x error %d\n", |
437 | index, value, ret); | 411 | index, value, ret); |
438 | gspca_dev->usb_err = ret; | 412 | gspca_dev->usb_err = ret; |
439 | } | 413 | } |
440 | } | 414 | } |
441 | 415 | ||
442 | static void reg_w_seq(struct gspca_dev *gspca_dev, | 416 | static void reg_w_seq(struct gspca_dev *gspca_dev, |
443 | const __u8 *seq, int len) | 417 | const u8 *seq, int len) |
444 | { | 418 | { |
445 | while (--len >= 0) { | 419 | while (--len >= 0) { |
446 | reg_w(gspca_dev, seq[0], seq[1]); | 420 | reg_w(gspca_dev, seq[0], seq[1]); |
@@ -450,7 +424,7 @@ static void reg_w_seq(struct gspca_dev *gspca_dev, | |||
450 | 424 | ||
451 | /* load the beginning of a page */ | 425 | /* load the beginning of a page */ |
452 | static void reg_w_page(struct gspca_dev *gspca_dev, | 426 | static void reg_w_page(struct gspca_dev *gspca_dev, |
453 | const __u8 *page, int len) | 427 | const u8 *page, int len) |
454 | { | 428 | { |
455 | int index; | 429 | int index; |
456 | int ret = 0; | 430 | int ret = 0; |
@@ -468,7 +442,7 @@ static void reg_w_page(struct gspca_dev *gspca_dev, | |||
468 | 0, index, gspca_dev->usb_buf, 1, | 442 | 0, index, gspca_dev->usb_buf, 1, |
469 | 500); | 443 | 500); |
470 | if (ret < 0) { | 444 | if (ret < 0) { |
471 | pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n", | 445 | pr_err("reg_w_page() failed i: %02x v: %02x error %d\n", |
472 | index, page[index], ret); | 446 | index, page[index], ret); |
473 | gspca_dev->usb_err = ret; | 447 | gspca_dev->usb_err = ret; |
474 | break; | 448 | break; |
@@ -478,8 +452,8 @@ static void reg_w_page(struct gspca_dev *gspca_dev, | |||
478 | 452 | ||
479 | /* output a variable sequence */ | 453 | /* output a variable sequence */ |
480 | static void reg_w_var(struct gspca_dev *gspca_dev, | 454 | static void reg_w_var(struct gspca_dev *gspca_dev, |
481 | const __u8 *seq, | 455 | const u8 *seq, |
482 | const __u8 *page3, unsigned int page3_len) | 456 | const u8 *page3, unsigned int page3_len) |
483 | { | 457 | { |
484 | int index, len; | 458 | int index, len; |
485 | 459 | ||
@@ -493,11 +467,13 @@ static void reg_w_var(struct gspca_dev *gspca_dev, | |||
493 | reg_w_page(gspca_dev, page3, page3_len); | 467 | reg_w_page(gspca_dev, page3, page3_len); |
494 | break; | 468 | break; |
495 | default: | 469 | default: |
470 | #ifdef GSPCA_DEBUG | ||
496 | if (len > USB_BUF_SZ) { | 471 | if (len > USB_BUF_SZ) { |
497 | PDEBUG(D_ERR|D_STREAM, | 472 | PDEBUG(D_ERR|D_STREAM, |
498 | "Incorrect variable sequence"); | 473 | "Incorrect variable sequence"); |
499 | return; | 474 | return; |
500 | } | 475 | } |
476 | #endif | ||
501 | while (len > 0) { | 477 | while (len > 0) { |
502 | if (len < 8) { | 478 | if (len < 8) { |
503 | reg_w_buf(gspca_dev, | 479 | reg_w_buf(gspca_dev, |
@@ -524,21 +500,11 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
524 | 500 | ||
525 | cam = &gspca_dev->cam; | 501 | cam = &gspca_dev->cam; |
526 | 502 | ||
527 | PDEBUG(D_CONF, "Find Sensor PAC7302"); | ||
528 | cam->cam_mode = vga_mode; /* only 640x480 */ | 503 | cam->cam_mode = vga_mode; /* only 640x480 */ |
529 | cam->nmodes = ARRAY_SIZE(vga_mode); | 504 | cam->nmodes = ARRAY_SIZE(vga_mode); |
530 | 505 | ||
531 | sd->brightness = BRIGHTNESS_DEF; | 506 | gspca_dev->cam.ctrls = sd->ctrls; |
532 | sd->contrast = CONTRAST_DEF; | 507 | |
533 | sd->colors = COLOR_DEF; | ||
534 | sd->white_balance = WHITEBALANCE_DEF; | ||
535 | sd->red_balance = REDBALANCE_DEF; | ||
536 | sd->blue_balance = BLUEBALANCE_DEF; | ||
537 | sd->gain = GAIN_DEF; | ||
538 | sd->exposure = EXPOSURE_DEF; | ||
539 | sd->autogain = AUTOGAIN_DEF; | ||
540 | sd->hflip = HFLIP_DEF; | ||
541 | sd->vflip = VFLIP_DEF; | ||
542 | sd->flags = id->driver_info; | 508 | sd->flags = id->driver_info; |
543 | return 0; | 509 | return 0; |
544 | } | 510 | } |
@@ -548,19 +514,19 @@ static void setbrightcont(struct gspca_dev *gspca_dev) | |||
548 | { | 514 | { |
549 | struct sd *sd = (struct sd *) gspca_dev; | 515 | struct sd *sd = (struct sd *) gspca_dev; |
550 | int i, v; | 516 | int i, v; |
551 | static const __u8 max[10] = | 517 | static const u8 max[10] = |
552 | {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb, | 518 | {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb, |
553 | 0xd4, 0xec}; | 519 | 0xd4, 0xec}; |
554 | static const __u8 delta[10] = | 520 | static const u8 delta[10] = |
555 | {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17, | 521 | {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17, |
556 | 0x11, 0x0b}; | 522 | 0x11, 0x0b}; |
557 | 523 | ||
558 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | 524 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ |
559 | for (i = 0; i < 10; i++) { | 525 | for (i = 0; i < 10; i++) { |
560 | v = max[i]; | 526 | v = max[i]; |
561 | v += (sd->brightness - BRIGHTNESS_MAX) | 527 | v += (sd->ctrls[BRIGHTNESS].val - BRIGHTNESS_MAX) |
562 | * 150 / BRIGHTNESS_MAX; /* 200 ? */ | 528 | * 150 / BRIGHTNESS_MAX; /* 200 ? */ |
563 | v -= delta[i] * sd->contrast / CONTRAST_MAX; | 529 | v -= delta[i] * sd->ctrls[CONTRAST].val / CONTRAST_MAX; |
564 | if (v < 0) | 530 | if (v < 0) |
565 | v = 0; | 531 | v = 0; |
566 | else if (v > 0xff) | 532 | else if (v > 0xff) |
@@ -584,12 +550,11 @@ static void setcolors(struct gspca_dev *gspca_dev) | |||
584 | reg_w(gspca_dev, 0x11, 0x01); | 550 | reg_w(gspca_dev, 0x11, 0x01); |
585 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | 551 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ |
586 | for (i = 0; i < 9; i++) { | 552 | for (i = 0; i < 9; i++) { |
587 | v = a[i] * sd->colors / COLOR_MAX + b[i]; | 553 | v = a[i] * sd->ctrls[COLORS].val / COLOR_MAX + b[i]; |
588 | reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); | 554 | reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); |
589 | reg_w(gspca_dev, 0x0f + 2 * i + 1, v); | 555 | reg_w(gspca_dev, 0x0f + 2 * i + 1, v); |
590 | } | 556 | } |
591 | reg_w(gspca_dev, 0xdc, 0x01); | 557 | reg_w(gspca_dev, 0xdc, 0x01); |
592 | PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors); | ||
593 | } | 558 | } |
594 | 559 | ||
595 | static void setwhitebalance(struct gspca_dev *gspca_dev) | 560 | static void setwhitebalance(struct gspca_dev *gspca_dev) |
@@ -597,10 +562,9 @@ static void setwhitebalance(struct gspca_dev *gspca_dev) | |||
597 | struct sd *sd = (struct sd *) gspca_dev; | 562 | struct sd *sd = (struct sd *) gspca_dev; |
598 | 563 | ||
599 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | 564 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ |
600 | reg_w(gspca_dev, 0xc6, sd->white_balance); | 565 | reg_w(gspca_dev, 0xc6, sd->ctrls[WHITE_BALANCE].val); |
601 | 566 | ||
602 | reg_w(gspca_dev, 0xdc, 0x01); | 567 | reg_w(gspca_dev, 0xdc, 0x01); |
603 | PDEBUG(D_CONF|D_STREAM, "white_balance: %i", sd->white_balance); | ||
604 | } | 568 | } |
605 | 569 | ||
606 | static void setredbalance(struct gspca_dev *gspca_dev) | 570 | static void setredbalance(struct gspca_dev *gspca_dev) |
@@ -608,10 +572,9 @@ static void setredbalance(struct gspca_dev *gspca_dev) | |||
608 | struct sd *sd = (struct sd *) gspca_dev; | 572 | struct sd *sd = (struct sd *) gspca_dev; |
609 | 573 | ||
610 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | 574 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ |
611 | reg_w(gspca_dev, 0xc5, sd->red_balance); | 575 | reg_w(gspca_dev, 0xc5, sd->ctrls[RED_BALANCE].val); |
612 | 576 | ||
613 | reg_w(gspca_dev, 0xdc, 0x01); | 577 | reg_w(gspca_dev, 0xdc, 0x01); |
614 | PDEBUG(D_CONF|D_STREAM, "red_balance: %i", sd->red_balance); | ||
615 | } | 578 | } |
616 | 579 | ||
617 | static void setbluebalance(struct gspca_dev *gspca_dev) | 580 | static void setbluebalance(struct gspca_dev *gspca_dev) |
@@ -619,10 +582,9 @@ static void setbluebalance(struct gspca_dev *gspca_dev) | |||
619 | struct sd *sd = (struct sd *) gspca_dev; | 582 | struct sd *sd = (struct sd *) gspca_dev; |
620 | 583 | ||
621 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | 584 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ |
622 | reg_w(gspca_dev, 0xc7, sd->blue_balance); | 585 | reg_w(gspca_dev, 0xc7, sd->ctrls[BLUE_BALANCE].val); |
623 | 586 | ||
624 | reg_w(gspca_dev, 0xdc, 0x01); | 587 | reg_w(gspca_dev, 0xdc, 0x01); |
625 | PDEBUG(D_CONF|D_STREAM, "blue_balance: %i", sd->blue_balance); | ||
626 | } | 588 | } |
627 | 589 | ||
628 | static void setgain(struct gspca_dev *gspca_dev) | 590 | static void setgain(struct gspca_dev *gspca_dev) |
@@ -630,7 +592,7 @@ static void setgain(struct gspca_dev *gspca_dev) | |||
630 | struct sd *sd = (struct sd *) gspca_dev; | 592 | struct sd *sd = (struct sd *) gspca_dev; |
631 | 593 | ||
632 | reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ | 594 | reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ |
633 | reg_w(gspca_dev, 0x10, sd->gain >> 3); | 595 | reg_w(gspca_dev, 0x10, sd->ctrls[GAIN].val >> 3); |
634 | 596 | ||
635 | /* load registers to sensor (Bit 0, auto clear) */ | 597 | /* load registers to sensor (Bit 0, auto clear) */ |
636 | reg_w(gspca_dev, 0x11, 0x01); | 598 | reg_w(gspca_dev, 0x11, 0x01); |
@@ -639,13 +601,13 @@ static void setgain(struct gspca_dev *gspca_dev) | |||
639 | static void setexposure(struct gspca_dev *gspca_dev) | 601 | static void setexposure(struct gspca_dev *gspca_dev) |
640 | { | 602 | { |
641 | struct sd *sd = (struct sd *) gspca_dev; | 603 | struct sd *sd = (struct sd *) gspca_dev; |
642 | __u8 clockdiv; | 604 | u8 clockdiv; |
643 | __u16 exposure; | 605 | u16 exposure; |
644 | 606 | ||
645 | /* register 2 of frame 3 contains the clock divider configuring the | 607 | /* register 2 of frame 3 contains the clock divider configuring the |
646 | no fps according to the formula: 90 / reg. sd->exposure is the | 608 | no fps according to the formula: 90 / reg. sd->exposure is the |
647 | desired exposure time in 0.5 ms. */ | 609 | desired exposure time in 0.5 ms. */ |
648 | clockdiv = (90 * sd->exposure + 1999) / 2000; | 610 | clockdiv = (90 * sd->ctrls[EXPOSURE].val + 1999) / 2000; |
649 | 611 | ||
650 | /* Note clockdiv = 3 also works, but when running at 30 fps, depending | 612 | /* Note clockdiv = 3 also works, but when running at 30 fps, depending |
651 | on the scene being recorded, the camera switches to another | 613 | on the scene being recorded, the camera switches to another |
@@ -664,7 +626,7 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
664 | 626 | ||
665 | /* frame exposure time in ms = 1000 * clockdiv / 90 -> | 627 | /* frame exposure time in ms = 1000 * clockdiv / 90 -> |
666 | exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90) */ | 628 | exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90) */ |
667 | exposure = (sd->exposure * 45 * 448) / (1000 * clockdiv); | 629 | exposure = (sd->ctrls[EXPOSURE].val * 45 * 448) / (1000 * clockdiv); |
668 | /* 0 = use full frametime, 448 = no exposure, reverse it */ | 630 | /* 0 = use full frametime, 448 = no exposure, reverse it */ |
669 | exposure = 448 - exposure; | 631 | exposure = 448 - exposure; |
670 | 632 | ||
@@ -677,15 +639,35 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
677 | reg_w(gspca_dev, 0x11, 0x01); | 639 | reg_w(gspca_dev, 0x11, 0x01); |
678 | } | 640 | } |
679 | 641 | ||
642 | static void setautogain(struct gspca_dev *gspca_dev) | ||
643 | { | ||
644 | struct sd *sd = (struct sd *) gspca_dev; | ||
645 | |||
646 | /* when switching to autogain set defaults to make sure | ||
647 | we are on a valid point of the autogain gain / | ||
648 | exposure knee graph, and give this change time to | ||
649 | take effect before doing autogain. */ | ||
650 | if (sd->ctrls[AUTOGAIN].val) { | ||
651 | sd->ctrls[EXPOSURE].val = EXPOSURE_DEF; | ||
652 | sd->ctrls[GAIN].val = GAIN_DEF; | ||
653 | sd->autogain_ignore_frames = | ||
654 | PAC_AUTOGAIN_IGNORE_FRAMES; | ||
655 | } else { | ||
656 | sd->autogain_ignore_frames = -1; | ||
657 | } | ||
658 | setexposure(gspca_dev); | ||
659 | setgain(gspca_dev); | ||
660 | } | ||
661 | |||
680 | static void sethvflip(struct gspca_dev *gspca_dev) | 662 | static void sethvflip(struct gspca_dev *gspca_dev) |
681 | { | 663 | { |
682 | struct sd *sd = (struct sd *) gspca_dev; | 664 | struct sd *sd = (struct sd *) gspca_dev; |
683 | u8 data, hflip, vflip; | 665 | u8 data, hflip, vflip; |
684 | 666 | ||
685 | hflip = sd->hflip; | 667 | hflip = sd->ctrls[HFLIP].val; |
686 | if (sd->flags & FL_HFLIP) | 668 | if (sd->flags & FL_HFLIP) |
687 | hflip = !hflip; | 669 | hflip = !hflip; |
688 | vflip = sd->vflip; | 670 | vflip = sd->ctrls[VFLIP].val; |
689 | if (sd->flags & FL_VFLIP) | 671 | if (sd->flags & FL_VFLIP) |
690 | vflip = !vflip; | 672 | vflip = !vflip; |
691 | 673 | ||
@@ -708,8 +690,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
708 | { | 690 | { |
709 | struct sd *sd = (struct sd *) gspca_dev; | 691 | struct sd *sd = (struct sd *) gspca_dev; |
710 | 692 | ||
711 | sd->sof_read = 0; | ||
712 | |||
713 | reg_w_var(gspca_dev, start_7302, | 693 | reg_w_var(gspca_dev, start_7302, |
714 | page3_7302, sizeof(page3_7302)); | 694 | page3_7302, sizeof(page3_7302)); |
715 | setbrightcont(gspca_dev); | 695 | setbrightcont(gspca_dev); |
@@ -717,15 +697,13 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
717 | setwhitebalance(gspca_dev); | 697 | setwhitebalance(gspca_dev); |
718 | setredbalance(gspca_dev); | 698 | setredbalance(gspca_dev); |
719 | setbluebalance(gspca_dev); | 699 | setbluebalance(gspca_dev); |
720 | setgain(gspca_dev); | 700 | setautogain(gspca_dev); |
721 | setexposure(gspca_dev); | ||
722 | sethvflip(gspca_dev); | 701 | sethvflip(gspca_dev); |
723 | 702 | ||
724 | /* only resolution 640x480 is supported for pac7302 */ | 703 | /* only resolution 640x480 is supported for pac7302 */ |
725 | 704 | ||
726 | sd->sof_read = 0; | 705 | sd->sof_read = 0; |
727 | sd->autogain_ignore_frames = 0; | 706 | atomic_set(&sd->avg_lum, 270 + sd->ctrls[BRIGHTNESS].val); |
728 | atomic_set(&sd->avg_lum, -1); | ||
729 | 707 | ||
730 | /* start stream */ | 708 | /* start stream */ |
731 | reg_w(gspca_dev, 0xff, 0x01); | 709 | reg_w(gspca_dev, 0xff, 0x01); |
@@ -751,8 +729,10 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
751 | reg_w(gspca_dev, 0x78, 0x40); | 729 | reg_w(gspca_dev, 0x78, 0x40); |
752 | } | 730 | } |
753 | 731 | ||
754 | /* Include pac common sof detection functions */ | 732 | /* !! coarse_grained_expo_autogain is not used !! */ |
755 | #include "pac_common.h" | 733 | #define exp_too_low_cnt flags |
734 | #define exp_too_high_cnt sof_read | ||
735 | #include "autogain_functions.h" | ||
756 | 736 | ||
757 | static void do_autogain(struct gspca_dev *gspca_dev) | 737 | static void do_autogain(struct gspca_dev *gspca_dev) |
758 | { | 738 | { |
@@ -761,65 +741,44 @@ static void do_autogain(struct gspca_dev *gspca_dev) | |||
761 | int desired_lum; | 741 | int desired_lum; |
762 | const int deadzone = 30; | 742 | const int deadzone = 30; |
763 | 743 | ||
764 | if (avg_lum == -1) | 744 | if (sd->autogain_ignore_frames < 0) |
765 | return; | 745 | return; |
766 | 746 | ||
767 | desired_lum = 270 + sd->brightness; | 747 | if (sd->autogain_ignore_frames > 0) { |
768 | |||
769 | if (sd->autogain_ignore_frames > 0) | ||
770 | sd->autogain_ignore_frames--; | 748 | sd->autogain_ignore_frames--; |
771 | else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum, | 749 | } else { |
772 | deadzone, GAIN_KNEE, EXPOSURE_KNEE)) | 750 | desired_lum = 270 + sd->ctrls[BRIGHTNESS].val; |
751 | |||
752 | auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum, | ||
753 | deadzone, GAIN_KNEE, EXPOSURE_KNEE); | ||
773 | sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; | 754 | sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; |
755 | } | ||
774 | } | 756 | } |
775 | 757 | ||
776 | /* JPEG header, part 1 */ | 758 | /* JPEG header */ |
777 | static const unsigned char pac_jpeg_header1[] = { | 759 | static const u8 jpeg_header[] = { |
778 | 0xff, 0xd8, /* SOI: Start of Image */ | 760 | 0xff, 0xd8, /* SOI: Start of Image */ |
779 | 761 | ||
780 | 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */ | 762 | 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */ |
781 | 0x00, 0x11, /* length = 17 bytes (including this length field) */ | 763 | 0x00, 0x11, /* length = 17 bytes (including this length field) */ |
782 | 0x08 /* Precision: 8 */ | 764 | 0x08, /* Precision: 8 */ |
783 | /* 2 bytes is placed here: number of image lines */ | 765 | 0x02, 0x80, /* height = 640 (image rotated) */ |
784 | /* 2 bytes is placed here: samples per line */ | 766 | 0x01, 0xe0, /* width = 480 */ |
785 | }; | 767 | 0x03, /* Number of image components: 3 */ |
786 | 768 | 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */ | |
787 | /* JPEG header, continued */ | 769 | 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */ |
788 | static const unsigned char pac_jpeg_header2[] = { | 770 | 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */ |
789 | 0x03, /* Number of image components: 3 */ | 771 | |
790 | 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */ | 772 | 0xff, 0xda, /* SOS: Start Of Scan */ |
791 | 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */ | 773 | 0x00, 0x0c, /* length = 12 bytes (including this length field) */ |
792 | 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */ | 774 | 0x03, /* number of components: 3 */ |
793 | 775 | 0x01, 0x00, /* selector 1, table 0x00 */ | |
794 | 0xff, 0xda, /* SOS: Start Of Scan */ | 776 | 0x02, 0x11, /* selector 2, table 0x11 */ |
795 | 0x00, 0x0c, /* length = 12 bytes (including this length field) */ | 777 | 0x03, 0x11, /* selector 3, table 0x11 */ |
796 | 0x03, /* number of components: 3 */ | 778 | 0x00, 0x3f, /* Spectral selection: 0 .. 63 */ |
797 | 0x01, 0x00, /* selector 1, table 0x00 */ | 779 | 0x00 /* Successive approximation: 0 */ |
798 | 0x02, 0x11, /* selector 2, table 0x11 */ | ||
799 | 0x03, 0x11, /* selector 3, table 0x11 */ | ||
800 | 0x00, 0x3f, /* Spectral selection: 0 .. 63 */ | ||
801 | 0x00 /* Successive approximation: 0 */ | ||
802 | }; | 780 | }; |
803 | 781 | ||
804 | static void pac_start_frame(struct gspca_dev *gspca_dev, | ||
805 | __u16 lines, __u16 samples_per_line) | ||
806 | { | ||
807 | unsigned char tmpbuf[4]; | ||
808 | |||
809 | gspca_frame_add(gspca_dev, FIRST_PACKET, | ||
810 | pac_jpeg_header1, sizeof(pac_jpeg_header1)); | ||
811 | |||
812 | tmpbuf[0] = lines >> 8; | ||
813 | tmpbuf[1] = lines & 0xff; | ||
814 | tmpbuf[2] = samples_per_line >> 8; | ||
815 | tmpbuf[3] = samples_per_line & 0xff; | ||
816 | |||
817 | gspca_frame_add(gspca_dev, INTER_PACKET, | ||
818 | tmpbuf, sizeof(tmpbuf)); | ||
819 | gspca_frame_add(gspca_dev, INTER_PACKET, | ||
820 | pac_jpeg_header2, sizeof(pac_jpeg_header2)); | ||
821 | } | ||
822 | |||
823 | /* this function is run at interrupt level */ | 782 | /* this function is run at interrupt level */ |
824 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 783 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
825 | u8 *data, /* isoc packet */ | 784 | u8 *data, /* isoc packet */ |
@@ -827,7 +786,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
827 | { | 786 | { |
828 | struct sd *sd = (struct sd *) gspca_dev; | 787 | struct sd *sd = (struct sd *) gspca_dev; |
829 | u8 *image; | 788 | u8 *image; |
830 | unsigned char *sof; | 789 | u8 *sof; |
831 | 790 | ||
832 | sof = pac_find_sof(&sd->sof_read, data, len); | 791 | sof = pac_find_sof(&sd->sof_read, data, len); |
833 | if (sof) { | 792 | if (sof) { |
@@ -864,234 +823,21 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
864 | n >= lum_offset) | 823 | n >= lum_offset) |
865 | atomic_set(&sd->avg_lum, data[-lum_offset] + | 824 | atomic_set(&sd->avg_lum, data[-lum_offset] + |
866 | data[-lum_offset + 1]); | 825 | data[-lum_offset + 1]); |
867 | else | ||
868 | atomic_set(&sd->avg_lum, -1); | ||
869 | 826 | ||
870 | /* Start the new frame with the jpeg header */ | 827 | /* Start the new frame with the jpeg header */ |
871 | /* The PAC7302 has the image rotated 90 degrees */ | 828 | /* The PAC7302 has the image rotated 90 degrees */ |
872 | pac_start_frame(gspca_dev, | 829 | gspca_frame_add(gspca_dev, FIRST_PACKET, |
873 | gspca_dev->width, gspca_dev->height); | 830 | jpeg_header, sizeof jpeg_header); |
874 | } | 831 | } |
875 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | 832 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
876 | } | 833 | } |
877 | 834 | ||
878 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | ||
879 | { | ||
880 | struct sd *sd = (struct sd *) gspca_dev; | ||
881 | |||
882 | sd->brightness = val; | ||
883 | if (gspca_dev->streaming) | ||
884 | setbrightcont(gspca_dev); | ||
885 | return gspca_dev->usb_err; | ||
886 | } | ||
887 | |||
888 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
889 | { | ||
890 | struct sd *sd = (struct sd *) gspca_dev; | ||
891 | |||
892 | *val = sd->brightness; | ||
893 | return 0; | ||
894 | } | ||
895 | |||
896 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | ||
897 | { | ||
898 | struct sd *sd = (struct sd *) gspca_dev; | ||
899 | |||
900 | sd->contrast = val; | ||
901 | if (gspca_dev->streaming) | ||
902 | setbrightcont(gspca_dev); | ||
903 | return gspca_dev->usb_err; | ||
904 | } | ||
905 | |||
906 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | ||
907 | { | ||
908 | struct sd *sd = (struct sd *) gspca_dev; | ||
909 | |||
910 | *val = sd->contrast; | ||
911 | return 0; | ||
912 | } | ||
913 | |||
914 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) | ||
915 | { | ||
916 | struct sd *sd = (struct sd *) gspca_dev; | ||
917 | |||
918 | sd->colors = val; | ||
919 | if (gspca_dev->streaming) | ||
920 | setcolors(gspca_dev); | ||
921 | return gspca_dev->usb_err; | ||
922 | } | ||
923 | |||
924 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) | ||
925 | { | ||
926 | struct sd *sd = (struct sd *) gspca_dev; | ||
927 | |||
928 | *val = sd->colors; | ||
929 | return 0; | ||
930 | } | ||
931 | |||
932 | static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val) | ||
933 | { | ||
934 | struct sd *sd = (struct sd *) gspca_dev; | ||
935 | |||
936 | sd->white_balance = val; | ||
937 | if (gspca_dev->streaming) | ||
938 | setwhitebalance(gspca_dev); | ||
939 | return gspca_dev->usb_err; | ||
940 | } | ||
941 | |||
942 | static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val) | ||
943 | { | ||
944 | struct sd *sd = (struct sd *) gspca_dev; | ||
945 | |||
946 | *val = sd->white_balance; | ||
947 | return 0; | ||
948 | } | ||
949 | |||
950 | static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val) | ||
951 | { | ||
952 | struct sd *sd = (struct sd *) gspca_dev; | ||
953 | |||
954 | sd->red_balance = val; | ||
955 | if (gspca_dev->streaming) | ||
956 | setredbalance(gspca_dev); | ||
957 | return gspca_dev->usb_err; | ||
958 | } | ||
959 | |||
960 | static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val) | ||
961 | { | ||
962 | struct sd *sd = (struct sd *) gspca_dev; | ||
963 | |||
964 | *val = sd->red_balance; | ||
965 | return 0; | ||
966 | } | ||
967 | |||
968 | static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val) | ||
969 | { | ||
970 | struct sd *sd = (struct sd *) gspca_dev; | ||
971 | |||
972 | sd->blue_balance = val; | ||
973 | if (gspca_dev->streaming) | ||
974 | setbluebalance(gspca_dev); | ||
975 | return gspca_dev->usb_err; | ||
976 | } | ||
977 | |||
978 | static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val) | ||
979 | { | ||
980 | struct sd *sd = (struct sd *) gspca_dev; | ||
981 | |||
982 | *val = sd->blue_balance; | ||
983 | return 0; | ||
984 | } | ||
985 | |||
986 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) | ||
987 | { | ||
988 | struct sd *sd = (struct sd *) gspca_dev; | ||
989 | |||
990 | sd->gain = val; | ||
991 | if (gspca_dev->streaming) | ||
992 | setgain(gspca_dev); | ||
993 | return gspca_dev->usb_err; | ||
994 | } | ||
995 | |||
996 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) | ||
997 | { | ||
998 | struct sd *sd = (struct sd *) gspca_dev; | ||
999 | |||
1000 | *val = sd->gain; | ||
1001 | return 0; | ||
1002 | } | ||
1003 | |||
1004 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) | ||
1005 | { | ||
1006 | struct sd *sd = (struct sd *) gspca_dev; | ||
1007 | |||
1008 | sd->exposure = val; | ||
1009 | if (gspca_dev->streaming) | ||
1010 | setexposure(gspca_dev); | ||
1011 | return gspca_dev->usb_err; | ||
1012 | } | ||
1013 | |||
1014 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) | ||
1015 | { | ||
1016 | struct sd *sd = (struct sd *) gspca_dev; | ||
1017 | |||
1018 | *val = sd->exposure; | ||
1019 | return 0; | ||
1020 | } | ||
1021 | |||
1022 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | ||
1023 | { | ||
1024 | struct sd *sd = (struct sd *) gspca_dev; | ||
1025 | |||
1026 | sd->autogain = val; | ||
1027 | /* when switching to autogain set defaults to make sure | ||
1028 | we are on a valid point of the autogain gain / | ||
1029 | exposure knee graph, and give this change time to | ||
1030 | take effect before doing autogain. */ | ||
1031 | if (sd->autogain) { | ||
1032 | sd->exposure = EXPOSURE_DEF; | ||
1033 | sd->gain = GAIN_DEF; | ||
1034 | if (gspca_dev->streaming) { | ||
1035 | sd->autogain_ignore_frames = | ||
1036 | PAC_AUTOGAIN_IGNORE_FRAMES; | ||
1037 | setexposure(gspca_dev); | ||
1038 | setgain(gspca_dev); | ||
1039 | } | ||
1040 | } | ||
1041 | |||
1042 | return gspca_dev->usb_err; | ||
1043 | } | ||
1044 | |||
1045 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) | ||
1046 | { | ||
1047 | struct sd *sd = (struct sd *) gspca_dev; | ||
1048 | |||
1049 | *val = sd->autogain; | ||
1050 | return 0; | ||
1051 | } | ||
1052 | |||
1053 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) | ||
1054 | { | ||
1055 | struct sd *sd = (struct sd *) gspca_dev; | ||
1056 | |||
1057 | sd->hflip = val; | ||
1058 | if (gspca_dev->streaming) | ||
1059 | sethvflip(gspca_dev); | ||
1060 | return gspca_dev->usb_err; | ||
1061 | } | ||
1062 | |||
1063 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
1064 | { | ||
1065 | struct sd *sd = (struct sd *) gspca_dev; | ||
1066 | |||
1067 | *val = sd->hflip; | ||
1068 | return 0; | ||
1069 | } | ||
1070 | |||
1071 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) | ||
1072 | { | ||
1073 | struct sd *sd = (struct sd *) gspca_dev; | ||
1074 | |||
1075 | sd->vflip = val; | ||
1076 | if (gspca_dev->streaming) | ||
1077 | sethvflip(gspca_dev); | ||
1078 | return gspca_dev->usb_err; | ||
1079 | } | ||
1080 | |||
1081 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) | ||
1082 | { | ||
1083 | struct sd *sd = (struct sd *) gspca_dev; | ||
1084 | |||
1085 | *val = sd->vflip; | ||
1086 | return 0; | ||
1087 | } | ||
1088 | |||
1089 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 835 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
1090 | static int sd_dbg_s_register(struct gspca_dev *gspca_dev, | 836 | static int sd_dbg_s_register(struct gspca_dev *gspca_dev, |
1091 | struct v4l2_dbg_register *reg) | 837 | struct v4l2_dbg_register *reg) |
1092 | { | 838 | { |
1093 | __u8 index; | 839 | u8 index; |
1094 | __u8 value; | 840 | u8 value; |
1095 | 841 | ||
1096 | /* reg->reg: bit0..15: reserved for register index (wIndex is 16bit | 842 | /* reg->reg: bit0..15: reserved for register index (wIndex is 16bit |
1097 | long on the USB bus) | 843 | long on the USB bus) |
@@ -1103,8 +849,8 @@ static int sd_dbg_s_register(struct gspca_dev *gspca_dev, | |||
1103 | ) { | 849 | ) { |
1104 | /* Currently writing to page 0 is only supported. */ | 850 | /* Currently writing to page 0 is only supported. */ |
1105 | /* reg_w() only supports 8bit index */ | 851 | /* reg_w() only supports 8bit index */ |
1106 | index = reg->reg & 0x000000ff; | 852 | index = reg->reg; |
1107 | value = reg->val & 0x000000ff; | 853 | value = reg->val; |
1108 | 854 | ||
1109 | /* Note that there shall be no access to other page | 855 | /* Note that there shall be no access to other page |
1110 | by any other function between the page swith and | 856 | by any other function between the page swith and |
@@ -1165,7 +911,7 @@ static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, | |||
1165 | 911 | ||
1166 | /* sub-driver description for pac7302 */ | 912 | /* sub-driver description for pac7302 */ |
1167 | static const struct sd_desc sd_desc = { | 913 | static const struct sd_desc sd_desc = { |
1168 | .name = MODULE_NAME, | 914 | .name = KBUILD_MODNAME, |
1169 | .ctrls = sd_ctrls, | 915 | .ctrls = sd_ctrls, |
1170 | .nctrls = ARRAY_SIZE(sd_ctrls), | 916 | .nctrls = ARRAY_SIZE(sd_ctrls), |
1171 | .config = sd_config, | 917 | .config = sd_config, |
@@ -1187,6 +933,7 @@ static const struct sd_desc sd_desc = { | |||
1187 | /* -- module initialisation -- */ | 933 | /* -- module initialisation -- */ |
1188 | static const struct usb_device_id device_table[] = { | 934 | static const struct usb_device_id device_table[] = { |
1189 | {USB_DEVICE(0x06f8, 0x3009)}, | 935 | {USB_DEVICE(0x06f8, 0x3009)}, |
936 | {USB_DEVICE(0x06f8, 0x301b)}, | ||
1190 | {USB_DEVICE(0x093a, 0x2620)}, | 937 | {USB_DEVICE(0x093a, 0x2620)}, |
1191 | {USB_DEVICE(0x093a, 0x2621)}, | 938 | {USB_DEVICE(0x093a, 0x2621)}, |
1192 | {USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP}, | 939 | {USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP}, |
@@ -1211,7 +958,7 @@ static int sd_probe(struct usb_interface *intf, | |||
1211 | } | 958 | } |
1212 | 959 | ||
1213 | static struct usb_driver sd_driver = { | 960 | static struct usb_driver sd_driver = { |
1214 | .name = MODULE_NAME, | 961 | .name = KBUILD_MODNAME, |
1215 | .id_table = device_table, | 962 | .id_table = device_table, |
1216 | .probe = sd_probe, | 963 | .probe = sd_probe, |
1217 | .disconnect = gspca_disconnect, | 964 | .disconnect = gspca_disconnect, |
diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 9e198b45c3c8..7e71aa2d2522 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c | |||
@@ -1,5 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Sonix sn9c201 sn9c202 library | 2 | * Sonix sn9c201 sn9c202 library |
3 | * | ||
4 | * Copyright (C) 2012 Jean-Francois Moine <http://moinejf.free.fr> | ||
3 | * Copyright (C) 2008-2009 microdia project <microdia@googlegroups.com> | 5 | * Copyright (C) 2008-2009 microdia project <microdia@googlegroups.com> |
4 | * Copyright (C) 2009 Brian Johnson <brijohn@gmail.com> | 6 | * Copyright (C) 2009 Brian Johnson <brijohn@gmail.com> |
5 | * | 7 | * |
@@ -33,8 +35,6 @@ MODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, " | |||
33 | MODULE_DESCRIPTION("GSPCA/SN9C20X USB Camera Driver"); | 35 | MODULE_DESCRIPTION("GSPCA/SN9C20X USB Camera Driver"); |
34 | MODULE_LICENSE("GPL"); | 36 | MODULE_LICENSE("GPL"); |
35 | 37 | ||
36 | #define MODULE_NAME "sn9c20x" | ||
37 | |||
38 | /* | 38 | /* |
39 | * Pixel format private data | 39 | * Pixel format private data |
40 | */ | 40 | */ |
@@ -66,10 +66,37 @@ MODULE_LICENSE("GPL"); | |||
66 | #define LED_REVERSE 0x2 /* some cameras unset gpio to turn on leds */ | 66 | #define LED_REVERSE 0x2 /* some cameras unset gpio to turn on leds */ |
67 | #define FLIP_DETECT 0x4 | 67 | #define FLIP_DETECT 0x4 |
68 | 68 | ||
69 | enum e_ctrl { | ||
70 | BRIGHTNESS, | ||
71 | CONTRAST, | ||
72 | SATURATION, | ||
73 | HUE, | ||
74 | GAMMA, | ||
75 | BLUE, | ||
76 | RED, | ||
77 | VFLIP, | ||
78 | HFLIP, | ||
79 | EXPOSURE, | ||
80 | GAIN, | ||
81 | AUTOGAIN, | ||
82 | QUALITY, | ||
83 | NCTRLS /* number of controls */ | ||
84 | }; | ||
85 | |||
69 | /* specific webcam descriptor */ | 86 | /* specific webcam descriptor */ |
70 | struct sd { | 87 | struct sd { |
71 | struct gspca_dev gspca_dev; | 88 | struct gspca_dev gspca_dev; |
72 | 89 | ||
90 | struct gspca_ctrl ctrls[NCTRLS]; | ||
91 | |||
92 | struct work_struct work; | ||
93 | struct workqueue_struct *work_thread; | ||
94 | |||
95 | u32 pktsz; /* (used by pkt_scan) */ | ||
96 | u16 npkt; | ||
97 | s8 nchg; | ||
98 | u8 fmt; /* (used for JPEG QTAB update */ | ||
99 | |||
73 | #define MIN_AVG_LUM 80 | 100 | #define MIN_AVG_LUM 80 |
74 | #define MAX_AVG_LUM 130 | 101 | #define MAX_AVG_LUM 130 |
75 | atomic_t avg_lum; | 102 | atomic_t avg_lum; |
@@ -77,31 +104,18 @@ struct sd { | |||
77 | u8 older_step; | 104 | u8 older_step; |
78 | u8 exposure_step; | 105 | u8 exposure_step; |
79 | 106 | ||
80 | u8 brightness; | ||
81 | u8 contrast; | ||
82 | u8 saturation; | ||
83 | s16 hue; | ||
84 | u8 gamma; | ||
85 | u8 red; | ||
86 | u8 blue; | ||
87 | |||
88 | u8 hflip; | ||
89 | u8 vflip; | ||
90 | u8 gain; | ||
91 | u16 exposure; | ||
92 | u8 auto_exposure; | ||
93 | |||
94 | u8 i2c_addr; | 107 | u8 i2c_addr; |
95 | u8 sensor; | 108 | u8 sensor; |
96 | u8 hstart; | 109 | u8 hstart; |
97 | u8 vstart; | 110 | u8 vstart; |
98 | 111 | ||
99 | u8 jpeg_hdr[JPEG_HDR_SZ]; | 112 | u8 jpeg_hdr[JPEG_HDR_SZ]; |
100 | u8 quality; | ||
101 | 113 | ||
102 | u8 flags; | 114 | u8 flags; |
103 | }; | 115 | }; |
104 | 116 | ||
117 | static void qual_upd(struct work_struct *work); | ||
118 | |||
105 | struct i2c_reg_u8 { | 119 | struct i2c_reg_u8 { |
106 | u8 reg; | 120 | u8 reg; |
107 | u8 val; | 121 | u8 val; |
@@ -112,31 +126,6 @@ struct i2c_reg_u16 { | |||
112 | u16 val; | 126 | u16 val; |
113 | }; | 127 | }; |
114 | 128 | ||
115 | static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val); | ||
116 | static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val); | ||
117 | static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val); | ||
118 | static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val); | ||
119 | static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val); | ||
120 | static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val); | ||
121 | static int sd_sethue(struct gspca_dev *gspca_dev, s32 val); | ||
122 | static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val); | ||
123 | static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val); | ||
124 | static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val); | ||
125 | static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val); | ||
126 | static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val); | ||
127 | static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val); | ||
128 | static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val); | ||
129 | static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val); | ||
130 | static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val); | ||
131 | static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val); | ||
132 | static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val); | ||
133 | static int sd_setgain(struct gspca_dev *gspca_dev, s32 val); | ||
134 | static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val); | ||
135 | static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val); | ||
136 | static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val); | ||
137 | static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val); | ||
138 | static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val); | ||
139 | |||
140 | static const struct dmi_system_id flip_dmi_table[] = { | 129 | static const struct dmi_system_id flip_dmi_table[] = { |
141 | { | 130 | { |
142 | .ident = "MSI MS-1034", | 131 | .ident = "MSI MS-1034", |
@@ -177,9 +166,16 @@ static const struct dmi_system_id flip_dmi_table[] = { | |||
177 | {} | 166 | {} |
178 | }; | 167 | }; |
179 | 168 | ||
180 | static const struct ctrl sd_ctrls[] = { | 169 | static void set_cmatrix(struct gspca_dev *gspca_dev); |
181 | { | 170 | static void set_gamma(struct gspca_dev *gspca_dev); |
182 | #define BRIGHTNESS_IDX 0 | 171 | static void set_redblue(struct gspca_dev *gspca_dev); |
172 | static void set_hvflip(struct gspca_dev *gspca_dev); | ||
173 | static void set_exposure(struct gspca_dev *gspca_dev); | ||
174 | static void set_gain(struct gspca_dev *gspca_dev); | ||
175 | static void set_quality(struct gspca_dev *gspca_dev); | ||
176 | |||
177 | static const struct ctrl sd_ctrls[NCTRLS] = { | ||
178 | [BRIGHTNESS] = { | ||
183 | { | 179 | { |
184 | .id = V4L2_CID_BRIGHTNESS, | 180 | .id = V4L2_CID_BRIGHTNESS, |
185 | .type = V4L2_CTRL_TYPE_INTEGER, | 181 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -187,14 +183,11 @@ static const struct ctrl sd_ctrls[] = { | |||
187 | .minimum = 0, | 183 | .minimum = 0, |
188 | .maximum = 0xff, | 184 | .maximum = 0xff, |
189 | .step = 1, | 185 | .step = 1, |
190 | #define BRIGHTNESS_DEFAULT 0x7f | 186 | .default_value = 0x7f |
191 | .default_value = BRIGHTNESS_DEFAULT, | ||
192 | }, | 187 | }, |
193 | .set = sd_setbrightness, | 188 | .set_control = set_cmatrix |
194 | .get = sd_getbrightness, | ||
195 | }, | 189 | }, |
196 | { | 190 | [CONTRAST] = { |
197 | #define CONTRAST_IDX 1 | ||
198 | { | 191 | { |
199 | .id = V4L2_CID_CONTRAST, | 192 | .id = V4L2_CID_CONTRAST, |
200 | .type = V4L2_CTRL_TYPE_INTEGER, | 193 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -202,14 +195,11 @@ static const struct ctrl sd_ctrls[] = { | |||
202 | .minimum = 0, | 195 | .minimum = 0, |
203 | .maximum = 0xff, | 196 | .maximum = 0xff, |
204 | .step = 1, | 197 | .step = 1, |
205 | #define CONTRAST_DEFAULT 0x7f | 198 | .default_value = 0x7f |
206 | .default_value = CONTRAST_DEFAULT, | ||
207 | }, | 199 | }, |
208 | .set = sd_setcontrast, | 200 | .set_control = set_cmatrix |
209 | .get = sd_getcontrast, | ||
210 | }, | 201 | }, |
211 | { | 202 | [SATURATION] = { |
212 | #define SATURATION_IDX 2 | ||
213 | { | 203 | { |
214 | .id = V4L2_CID_SATURATION, | 204 | .id = V4L2_CID_SATURATION, |
215 | .type = V4L2_CTRL_TYPE_INTEGER, | 205 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -217,14 +207,11 @@ static const struct ctrl sd_ctrls[] = { | |||
217 | .minimum = 0, | 207 | .minimum = 0, |
218 | .maximum = 0xff, | 208 | .maximum = 0xff, |
219 | .step = 1, | 209 | .step = 1, |
220 | #define SATURATION_DEFAULT 0x7f | 210 | .default_value = 0x7f |
221 | .default_value = SATURATION_DEFAULT, | ||
222 | }, | 211 | }, |
223 | .set = sd_setsaturation, | 212 | .set_control = set_cmatrix |
224 | .get = sd_getsaturation, | ||
225 | }, | 213 | }, |
226 | { | 214 | [HUE] = { |
227 | #define HUE_IDX 3 | ||
228 | { | 215 | { |
229 | .id = V4L2_CID_HUE, | 216 | .id = V4L2_CID_HUE, |
230 | .type = V4L2_CTRL_TYPE_INTEGER, | 217 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -232,14 +219,11 @@ static const struct ctrl sd_ctrls[] = { | |||
232 | .minimum = -180, | 219 | .minimum = -180, |
233 | .maximum = 180, | 220 | .maximum = 180, |
234 | .step = 1, | 221 | .step = 1, |
235 | #define HUE_DEFAULT 0 | 222 | .default_value = 0 |
236 | .default_value = HUE_DEFAULT, | ||
237 | }, | 223 | }, |
238 | .set = sd_sethue, | 224 | .set_control = set_cmatrix |
239 | .get = sd_gethue, | ||
240 | }, | 225 | }, |
241 | { | 226 | [GAMMA] = { |
242 | #define GAMMA_IDX 4 | ||
243 | { | 227 | { |
244 | .id = V4L2_CID_GAMMA, | 228 | .id = V4L2_CID_GAMMA, |
245 | .type = V4L2_CTRL_TYPE_INTEGER, | 229 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -247,14 +231,11 @@ static const struct ctrl sd_ctrls[] = { | |||
247 | .minimum = 0, | 231 | .minimum = 0, |
248 | .maximum = 0xff, | 232 | .maximum = 0xff, |
249 | .step = 1, | 233 | .step = 1, |
250 | #define GAMMA_DEFAULT 0x10 | 234 | .default_value = 0x10 |
251 | .default_value = GAMMA_DEFAULT, | ||
252 | }, | 235 | }, |
253 | .set = sd_setgamma, | 236 | .set_control = set_gamma |
254 | .get = sd_getgamma, | ||
255 | }, | 237 | }, |
256 | { | 238 | [BLUE] = { |
257 | #define BLUE_IDX 5 | ||
258 | { | 239 | { |
259 | .id = V4L2_CID_BLUE_BALANCE, | 240 | .id = V4L2_CID_BLUE_BALANCE, |
260 | .type = V4L2_CTRL_TYPE_INTEGER, | 241 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -262,14 +243,11 @@ static const struct ctrl sd_ctrls[] = { | |||
262 | .minimum = 0, | 243 | .minimum = 0, |
263 | .maximum = 0x7f, | 244 | .maximum = 0x7f, |
264 | .step = 1, | 245 | .step = 1, |
265 | #define BLUE_DEFAULT 0x28 | 246 | .default_value = 0x28 |
266 | .default_value = BLUE_DEFAULT, | ||
267 | }, | 247 | }, |
268 | .set = sd_setbluebalance, | 248 | .set_control = set_redblue |
269 | .get = sd_getbluebalance, | ||
270 | }, | 249 | }, |
271 | { | 250 | [RED] = { |
272 | #define RED_IDX 6 | ||
273 | { | 251 | { |
274 | .id = V4L2_CID_RED_BALANCE, | 252 | .id = V4L2_CID_RED_BALANCE, |
275 | .type = V4L2_CTRL_TYPE_INTEGER, | 253 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -277,14 +255,11 @@ static const struct ctrl sd_ctrls[] = { | |||
277 | .minimum = 0, | 255 | .minimum = 0, |
278 | .maximum = 0x7f, | 256 | .maximum = 0x7f, |
279 | .step = 1, | 257 | .step = 1, |
280 | #define RED_DEFAULT 0x28 | 258 | .default_value = 0x28 |
281 | .default_value = RED_DEFAULT, | ||
282 | }, | 259 | }, |
283 | .set = sd_setredbalance, | 260 | .set_control = set_redblue |
284 | .get = sd_getredbalance, | ||
285 | }, | 261 | }, |
286 | { | 262 | [HFLIP] = { |
287 | #define HFLIP_IDX 7 | ||
288 | { | 263 | { |
289 | .id = V4L2_CID_HFLIP, | 264 | .id = V4L2_CID_HFLIP, |
290 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 265 | .type = V4L2_CTRL_TYPE_BOOLEAN, |
@@ -292,14 +267,11 @@ static const struct ctrl sd_ctrls[] = { | |||
292 | .minimum = 0, | 267 | .minimum = 0, |
293 | .maximum = 1, | 268 | .maximum = 1, |
294 | .step = 1, | 269 | .step = 1, |
295 | #define HFLIP_DEFAULT 0 | 270 | .default_value = 0, |
296 | .default_value = HFLIP_DEFAULT, | ||
297 | }, | 271 | }, |
298 | .set = sd_sethflip, | 272 | .set_control = set_hvflip |
299 | .get = sd_gethflip, | ||
300 | }, | 273 | }, |
301 | { | 274 | [VFLIP] = { |
302 | #define VFLIP_IDX 8 | ||
303 | { | 275 | { |
304 | .id = V4L2_CID_VFLIP, | 276 | .id = V4L2_CID_VFLIP, |
305 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 277 | .type = V4L2_CTRL_TYPE_BOOLEAN, |
@@ -307,14 +279,11 @@ static const struct ctrl sd_ctrls[] = { | |||
307 | .minimum = 0, | 279 | .minimum = 0, |
308 | .maximum = 1, | 280 | .maximum = 1, |
309 | .step = 1, | 281 | .step = 1, |
310 | #define VFLIP_DEFAULT 0 | 282 | .default_value = 0, |
311 | .default_value = VFLIP_DEFAULT, | ||
312 | }, | 283 | }, |
313 | .set = sd_setvflip, | 284 | .set_control = set_hvflip |
314 | .get = sd_getvflip, | ||
315 | }, | 285 | }, |
316 | { | 286 | [EXPOSURE] = { |
317 | #define EXPOSURE_IDX 9 | ||
318 | { | 287 | { |
319 | .id = V4L2_CID_EXPOSURE, | 288 | .id = V4L2_CID_EXPOSURE, |
320 | .type = V4L2_CTRL_TYPE_INTEGER, | 289 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -322,14 +291,11 @@ static const struct ctrl sd_ctrls[] = { | |||
322 | .minimum = 0, | 291 | .minimum = 0, |
323 | .maximum = 0x1780, | 292 | .maximum = 0x1780, |
324 | .step = 1, | 293 | .step = 1, |
325 | #define EXPOSURE_DEFAULT 0x33 | 294 | .default_value = 0x33, |
326 | .default_value = EXPOSURE_DEFAULT, | ||
327 | }, | 295 | }, |
328 | .set = sd_setexposure, | 296 | .set_control = set_exposure |
329 | .get = sd_getexposure, | ||
330 | }, | 297 | }, |
331 | { | 298 | [GAIN] = { |
332 | #define GAIN_IDX 10 | ||
333 | { | 299 | { |
334 | .id = V4L2_CID_GAIN, | 300 | .id = V4L2_CID_GAIN, |
335 | .type = V4L2_CTRL_TYPE_INTEGER, | 301 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -337,14 +303,11 @@ static const struct ctrl sd_ctrls[] = { | |||
337 | .minimum = 0, | 303 | .minimum = 0, |
338 | .maximum = 28, | 304 | .maximum = 28, |
339 | .step = 1, | 305 | .step = 1, |
340 | #define GAIN_DEFAULT 0x00 | 306 | .default_value = 0, |
341 | .default_value = GAIN_DEFAULT, | ||
342 | }, | 307 | }, |
343 | .set = sd_setgain, | 308 | .set_control = set_gain |
344 | .get = sd_getgain, | ||
345 | }, | 309 | }, |
346 | { | 310 | [AUTOGAIN] = { |
347 | #define AUTOGAIN_IDX 11 | ||
348 | { | 311 | { |
349 | .id = V4L2_CID_AUTOGAIN, | 312 | .id = V4L2_CID_AUTOGAIN, |
350 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 313 | .type = V4L2_CTRL_TYPE_BOOLEAN, |
@@ -352,11 +315,23 @@ static const struct ctrl sd_ctrls[] = { | |||
352 | .minimum = 0, | 315 | .minimum = 0, |
353 | .maximum = 1, | 316 | .maximum = 1, |
354 | .step = 1, | 317 | .step = 1, |
355 | #define AUTO_EXPOSURE_DEFAULT 1 | 318 | .default_value = 1, |
356 | .default_value = AUTO_EXPOSURE_DEFAULT, | 319 | }, |
320 | }, | ||
321 | [QUALITY] = { | ||
322 | { | ||
323 | .id = V4L2_CID_JPEG_COMPRESSION_QUALITY, | ||
324 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
325 | .name = "Compression Quality", | ||
326 | #define QUALITY_MIN 50 | ||
327 | #define QUALITY_MAX 90 | ||
328 | #define QUALITY_DEF 80 | ||
329 | .minimum = QUALITY_MIN, | ||
330 | .maximum = QUALITY_MAX, | ||
331 | .step = 1, | ||
332 | .default_value = QUALITY_DEF, | ||
357 | }, | 333 | }, |
358 | .set = sd_setautoexposure, | 334 | .set_control = set_quality |
359 | .get = sd_getautoexposure, | ||
360 | }, | 335 | }, |
361 | }; | 336 | }; |
362 | 337 | ||
@@ -876,7 +851,7 @@ static u8 hv7131r_gain[] = { | |||
876 | }; | 851 | }; |
877 | 852 | ||
878 | static struct i2c_reg_u8 soi968_init[] = { | 853 | static struct i2c_reg_u8 soi968_init[] = { |
879 | {0x12, 0x80}, {0x0c, 0x00}, {0x0f, 0x1f}, | 854 | {0x0c, 0x00}, {0x0f, 0x1f}, |
880 | {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00}, | 855 | {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00}, |
881 | {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c}, | 856 | {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c}, |
882 | {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff}, | 857 | {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff}, |
@@ -902,7 +877,7 @@ static struct i2c_reg_u8 ov7660_init[] = { | |||
902 | }; | 877 | }; |
903 | 878 | ||
904 | static struct i2c_reg_u8 ov7670_init[] = { | 879 | static struct i2c_reg_u8 ov7670_init[] = { |
905 | {0x12, 0x80}, {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01}, | 880 | {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01}, |
906 | {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00}, | 881 | {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00}, |
907 | {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0}, | 882 | {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0}, |
908 | {0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00}, | 883 | {0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00}, |
@@ -959,7 +934,7 @@ static struct i2c_reg_u8 ov7670_init[] = { | |||
959 | }; | 934 | }; |
960 | 935 | ||
961 | static struct i2c_reg_u8 ov9650_init[] = { | 936 | static struct i2c_reg_u8 ov9650_init[] = { |
962 | {0x12, 0x80}, {0x00, 0x00}, {0x01, 0x78}, | 937 | {0x00, 0x00}, {0x01, 0x78}, |
963 | {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03}, | 938 | {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03}, |
964 | {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00}, | 939 | {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00}, |
965 | {0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00}, | 940 | {0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00}, |
@@ -989,7 +964,7 @@ static struct i2c_reg_u8 ov9650_init[] = { | |||
989 | }; | 964 | }; |
990 | 965 | ||
991 | static struct i2c_reg_u8 ov9655_init[] = { | 966 | static struct i2c_reg_u8 ov9655_init[] = { |
992 | {0x12, 0x80}, {0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba}, | 967 | {0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba}, |
993 | {0x14, 0x2e}, {0x16, 0x24}, {0x1e, 0x04}, {0x27, 0x08}, | 968 | {0x14, 0x2e}, {0x16, 0x24}, {0x1e, 0x04}, {0x27, 0x08}, |
994 | {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x34, 0x3d}, | 969 | {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x34, 0x3d}, |
995 | {0x35, 0x00}, {0x38, 0x12}, {0x0f, 0x42}, {0x39, 0x57}, | 970 | {0x35, 0x00}, {0x38, 0x12}, {0x0f, 0x42}, {0x39, 0x57}, |
@@ -1112,10 +1087,13 @@ static struct i2c_reg_u8 hv7131r_init[] = { | |||
1112 | {0x23, 0x09}, {0x01, 0x08}, | 1087 | {0x23, 0x09}, {0x01, 0x08}, |
1113 | }; | 1088 | }; |
1114 | 1089 | ||
1115 | static int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length) | 1090 | static void reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length) |
1116 | { | 1091 | { |
1117 | struct usb_device *dev = gspca_dev->dev; | 1092 | struct usb_device *dev = gspca_dev->dev; |
1118 | int result; | 1093 | int result; |
1094 | |||
1095 | if (gspca_dev->usb_err < 0) | ||
1096 | return; | ||
1119 | result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | 1097 | result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), |
1120 | 0x00, | 1098 | 0x00, |
1121 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, | 1099 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, |
@@ -1125,17 +1103,19 @@ static int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length) | |||
1125 | length, | 1103 | length, |
1126 | 500); | 1104 | 500); |
1127 | if (unlikely(result < 0 || result != length)) { | 1105 | if (unlikely(result < 0 || result != length)) { |
1128 | pr_err("Read register failed 0x%02X\n", reg); | 1106 | pr_err("Read register %02x failed %d\n", reg, result); |
1129 | return -EIO; | 1107 | gspca_dev->usb_err = result; |
1130 | } | 1108 | } |
1131 | return 0; | ||
1132 | } | 1109 | } |
1133 | 1110 | ||
1134 | static int reg_w(struct gspca_dev *gspca_dev, u16 reg, | 1111 | static void reg_w(struct gspca_dev *gspca_dev, u16 reg, |
1135 | const u8 *buffer, int length) | 1112 | const u8 *buffer, int length) |
1136 | { | 1113 | { |
1137 | struct usb_device *dev = gspca_dev->dev; | 1114 | struct usb_device *dev = gspca_dev->dev; |
1138 | int result; | 1115 | int result; |
1116 | |||
1117 | if (gspca_dev->usb_err < 0) | ||
1118 | return; | ||
1139 | memcpy(gspca_dev->usb_buf, buffer, length); | 1119 | memcpy(gspca_dev->usb_buf, buffer, length); |
1140 | result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 1120 | result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
1141 | 0x08, | 1121 | 0x08, |
@@ -1146,38 +1126,41 @@ static int reg_w(struct gspca_dev *gspca_dev, u16 reg, | |||
1146 | length, | 1126 | length, |
1147 | 500); | 1127 | 500); |
1148 | if (unlikely(result < 0 || result != length)) { | 1128 | if (unlikely(result < 0 || result != length)) { |
1149 | pr_err("Write register failed index 0x%02X\n", reg); | 1129 | pr_err("Write register %02x failed %d\n", reg, result); |
1150 | return -EIO; | 1130 | gspca_dev->usb_err = result; |
1151 | } | 1131 | } |
1152 | return 0; | ||
1153 | } | 1132 | } |
1154 | 1133 | ||
1155 | static int reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value) | 1134 | static void reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value) |
1156 | { | 1135 | { |
1157 | u8 data[1] = {value}; | 1136 | reg_w(gspca_dev, reg, &value, 1); |
1158 | return reg_w(gspca_dev, reg, data, 1); | ||
1159 | } | 1137 | } |
1160 | 1138 | ||
1161 | static int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer) | 1139 | static void i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer) |
1162 | { | 1140 | { |
1163 | int i; | 1141 | int i; |
1142 | |||
1164 | reg_w(gspca_dev, 0x10c0, buffer, 8); | 1143 | reg_w(gspca_dev, 0x10c0, buffer, 8); |
1165 | for (i = 0; i < 5; i++) { | 1144 | for (i = 0; i < 5; i++) { |
1166 | reg_r(gspca_dev, 0x10c0, 1); | 1145 | reg_r(gspca_dev, 0x10c0, 1); |
1146 | if (gspca_dev->usb_err < 0) | ||
1147 | return; | ||
1167 | if (gspca_dev->usb_buf[0] & 0x04) { | 1148 | if (gspca_dev->usb_buf[0] & 0x04) { |
1168 | if (gspca_dev->usb_buf[0] & 0x08) | 1149 | if (gspca_dev->usb_buf[0] & 0x08) { |
1169 | return -EIO; | 1150 | pr_err("i2c_w error\n"); |
1170 | return 0; | 1151 | gspca_dev->usb_err = -EIO; |
1152 | } | ||
1153 | return; | ||
1171 | } | 1154 | } |
1172 | msleep(1); | 1155 | msleep(10); |
1173 | } | 1156 | } |
1174 | return -EIO; | 1157 | pr_err("i2c_w reg %02x no response\n", buffer[2]); |
1158 | /* gspca_dev->usb_err = -EIO; fixme: may occur */ | ||
1175 | } | 1159 | } |
1176 | 1160 | ||
1177 | static int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) | 1161 | static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) |
1178 | { | 1162 | { |
1179 | struct sd *sd = (struct sd *) gspca_dev; | 1163 | struct sd *sd = (struct sd *) gspca_dev; |
1180 | |||
1181 | u8 row[8]; | 1164 | u8 row[8]; |
1182 | 1165 | ||
1183 | /* | 1166 | /* |
@@ -1193,10 +1176,19 @@ static int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) | |||
1193 | row[6] = 0x00; | 1176 | row[6] = 0x00; |
1194 | row[7] = 0x10; | 1177 | row[7] = 0x10; |
1195 | 1178 | ||
1196 | return i2c_w(gspca_dev, row); | 1179 | i2c_w(gspca_dev, row); |
1180 | } | ||
1181 | |||
1182 | static void i2c_w1_buf(struct gspca_dev *gspca_dev, | ||
1183 | struct i2c_reg_u8 *buf, int sz) | ||
1184 | { | ||
1185 | while (--sz >= 0) { | ||
1186 | i2c_w1(gspca_dev, buf->reg, buf->val); | ||
1187 | buf++; | ||
1188 | } | ||
1197 | } | 1189 | } |
1198 | 1190 | ||
1199 | static int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val) | 1191 | static void i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val) |
1200 | { | 1192 | { |
1201 | struct sd *sd = (struct sd *) gspca_dev; | 1193 | struct sd *sd = (struct sd *) gspca_dev; |
1202 | u8 row[8]; | 1194 | u8 row[8]; |
@@ -1208,16 +1200,25 @@ static int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val) | |||
1208 | row[0] = 0x81 | (3 << 4); | 1200 | row[0] = 0x81 | (3 << 4); |
1209 | row[1] = sd->i2c_addr; | 1201 | row[1] = sd->i2c_addr; |
1210 | row[2] = reg; | 1202 | row[2] = reg; |
1211 | row[3] = (val >> 8) & 0xff; | 1203 | row[3] = val >> 8; |
1212 | row[4] = val & 0xff; | 1204 | row[4] = val; |
1213 | row[5] = 0x00; | 1205 | row[5] = 0x00; |
1214 | row[6] = 0x00; | 1206 | row[6] = 0x00; |
1215 | row[7] = 0x10; | 1207 | row[7] = 0x10; |
1216 | 1208 | ||
1217 | return i2c_w(gspca_dev, row); | 1209 | i2c_w(gspca_dev, row); |
1210 | } | ||
1211 | |||
1212 | static void i2c_w2_buf(struct gspca_dev *gspca_dev, | ||
1213 | struct i2c_reg_u16 *buf, int sz) | ||
1214 | { | ||
1215 | while (--sz >= 0) { | ||
1216 | i2c_w2(gspca_dev, buf->reg, buf->val); | ||
1217 | buf++; | ||
1218 | } | ||
1218 | } | 1219 | } |
1219 | 1220 | ||
1220 | static int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val) | 1221 | static void i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val) |
1221 | { | 1222 | { |
1222 | struct sd *sd = (struct sd *) gspca_dev; | 1223 | struct sd *sd = (struct sd *) gspca_dev; |
1223 | u8 row[8]; | 1224 | u8 row[8]; |
@@ -1230,19 +1231,15 @@ static int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val) | |||
1230 | row[5] = 0; | 1231 | row[5] = 0; |
1231 | row[6] = 0; | 1232 | row[6] = 0; |
1232 | row[7] = 0x10; | 1233 | row[7] = 0x10; |
1233 | if (i2c_w(gspca_dev, row) < 0) | 1234 | i2c_w(gspca_dev, row); |
1234 | return -EIO; | ||
1235 | row[0] = 0x81 | (1 << 4) | 0x02; | 1235 | row[0] = 0x81 | (1 << 4) | 0x02; |
1236 | row[2] = 0; | 1236 | row[2] = 0; |
1237 | if (i2c_w(gspca_dev, row) < 0) | 1237 | i2c_w(gspca_dev, row); |
1238 | return -EIO; | 1238 | reg_r(gspca_dev, 0x10c2, 5); |
1239 | if (reg_r(gspca_dev, 0x10c2, 5) < 0) | ||
1240 | return -EIO; | ||
1241 | *val = gspca_dev->usb_buf[4]; | 1239 | *val = gspca_dev->usb_buf[4]; |
1242 | return 0; | ||
1243 | } | 1240 | } |
1244 | 1241 | ||
1245 | static int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val) | 1242 | static void i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val) |
1246 | { | 1243 | { |
1247 | struct sd *sd = (struct sd *) gspca_dev; | 1244 | struct sd *sd = (struct sd *) gspca_dev; |
1248 | u8 row[8]; | 1245 | u8 row[8]; |
@@ -1255,233 +1252,204 @@ static int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val) | |||
1255 | row[5] = 0; | 1252 | row[5] = 0; |
1256 | row[6] = 0; | 1253 | row[6] = 0; |
1257 | row[7] = 0x10; | 1254 | row[7] = 0x10; |
1258 | if (i2c_w(gspca_dev, row) < 0) | 1255 | i2c_w(gspca_dev, row); |
1259 | return -EIO; | ||
1260 | row[0] = 0x81 | (2 << 4) | 0x02; | 1256 | row[0] = 0x81 | (2 << 4) | 0x02; |
1261 | row[2] = 0; | 1257 | row[2] = 0; |
1262 | if (i2c_w(gspca_dev, row) < 0) | 1258 | i2c_w(gspca_dev, row); |
1263 | return -EIO; | 1259 | reg_r(gspca_dev, 0x10c2, 5); |
1264 | if (reg_r(gspca_dev, 0x10c2, 5) < 0) | ||
1265 | return -EIO; | ||
1266 | *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4]; | 1260 | *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4]; |
1267 | return 0; | ||
1268 | } | 1261 | } |
1269 | 1262 | ||
1270 | static int ov9650_init_sensor(struct gspca_dev *gspca_dev) | 1263 | static void ov9650_init_sensor(struct gspca_dev *gspca_dev) |
1271 | { | 1264 | { |
1272 | int i; | ||
1273 | u16 id; | 1265 | u16 id; |
1274 | struct sd *sd = (struct sd *) gspca_dev; | 1266 | struct sd *sd = (struct sd *) gspca_dev; |
1275 | 1267 | ||
1276 | if (i2c_r2(gspca_dev, 0x1c, &id) < 0) | 1268 | i2c_r2(gspca_dev, 0x1c, &id); |
1277 | return -EINVAL; | 1269 | if (gspca_dev->usb_err < 0) |
1270 | return; | ||
1278 | 1271 | ||
1279 | if (id != 0x7fa2) { | 1272 | if (id != 0x7fa2) { |
1280 | pr_err("sensor id for ov9650 doesn't match (0x%04x)\n", id); | 1273 | pr_err("sensor id for ov9650 doesn't match (0x%04x)\n", id); |
1281 | return -ENODEV; | 1274 | gspca_dev->usb_err = -ENODEV; |
1275 | return; | ||
1282 | } | 1276 | } |
1283 | 1277 | ||
1284 | for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) { | 1278 | i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ |
1285 | if (i2c_w1(gspca_dev, ov9650_init[i].reg, | 1279 | msleep(200); |
1286 | ov9650_init[i].val) < 0) { | 1280 | i2c_w1_buf(gspca_dev, ov9650_init, ARRAY_SIZE(ov9650_init)); |
1287 | pr_err("OV9650 sensor initialization failed\n"); | 1281 | if (gspca_dev->usb_err < 0) |
1288 | return -ENODEV; | 1282 | pr_err("OV9650 sensor initialization failed\n"); |
1289 | } | ||
1290 | } | ||
1291 | sd->hstart = 1; | 1283 | sd->hstart = 1; |
1292 | sd->vstart = 7; | 1284 | sd->vstart = 7; |
1293 | return 0; | ||
1294 | } | 1285 | } |
1295 | 1286 | ||
1296 | static int ov9655_init_sensor(struct gspca_dev *gspca_dev) | 1287 | static void ov9655_init_sensor(struct gspca_dev *gspca_dev) |
1297 | { | 1288 | { |
1298 | int i; | ||
1299 | struct sd *sd = (struct sd *) gspca_dev; | 1289 | struct sd *sd = (struct sd *) gspca_dev; |
1300 | 1290 | ||
1301 | for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) { | 1291 | i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ |
1302 | if (i2c_w1(gspca_dev, ov9655_init[i].reg, | 1292 | msleep(200); |
1303 | ov9655_init[i].val) < 0) { | 1293 | i2c_w1_buf(gspca_dev, ov9655_init, ARRAY_SIZE(ov9655_init)); |
1304 | pr_err("OV9655 sensor initialization failed\n"); | 1294 | if (gspca_dev->usb_err < 0) |
1305 | return -ENODEV; | 1295 | pr_err("OV9655 sensor initialization failed\n"); |
1306 | } | 1296 | |
1307 | } | ||
1308 | /* disable hflip and vflip */ | 1297 | /* disable hflip and vflip */ |
1309 | gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); | 1298 | gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP); |
1310 | sd->hstart = 1; | 1299 | sd->hstart = 1; |
1311 | sd->vstart = 2; | 1300 | sd->vstart = 2; |
1312 | return 0; | ||
1313 | } | 1301 | } |
1314 | 1302 | ||
1315 | static int soi968_init_sensor(struct gspca_dev *gspca_dev) | 1303 | static void soi968_init_sensor(struct gspca_dev *gspca_dev) |
1316 | { | 1304 | { |
1317 | int i; | ||
1318 | struct sd *sd = (struct sd *) gspca_dev; | 1305 | struct sd *sd = (struct sd *) gspca_dev; |
1319 | 1306 | ||
1320 | for (i = 0; i < ARRAY_SIZE(soi968_init); i++) { | 1307 | i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ |
1321 | if (i2c_w1(gspca_dev, soi968_init[i].reg, | 1308 | msleep(200); |
1322 | soi968_init[i].val) < 0) { | 1309 | i2c_w1_buf(gspca_dev, soi968_init, ARRAY_SIZE(soi968_init)); |
1323 | pr_err("SOI968 sensor initialization failed\n"); | 1310 | if (gspca_dev->usb_err < 0) |
1324 | return -ENODEV; | 1311 | pr_err("SOI968 sensor initialization failed\n"); |
1325 | } | 1312 | |
1326 | } | ||
1327 | /* disable hflip and vflip */ | 1313 | /* disable hflip and vflip */ |
1328 | gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | 1314 | gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP) |
1329 | | (1 << EXPOSURE_IDX); | 1315 | | (1 << EXPOSURE); |
1330 | sd->hstart = 60; | 1316 | sd->hstart = 60; |
1331 | sd->vstart = 11; | 1317 | sd->vstart = 11; |
1332 | return 0; | ||
1333 | } | 1318 | } |
1334 | 1319 | ||
1335 | static int ov7660_init_sensor(struct gspca_dev *gspca_dev) | 1320 | static void ov7660_init_sensor(struct gspca_dev *gspca_dev) |
1336 | { | 1321 | { |
1337 | int i; | ||
1338 | struct sd *sd = (struct sd *) gspca_dev; | 1322 | struct sd *sd = (struct sd *) gspca_dev; |
1339 | 1323 | ||
1340 | for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) { | 1324 | i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ |
1341 | if (i2c_w1(gspca_dev, ov7660_init[i].reg, | 1325 | msleep(200); |
1342 | ov7660_init[i].val) < 0) { | 1326 | i2c_w1_buf(gspca_dev, ov7660_init, ARRAY_SIZE(ov7660_init)); |
1343 | pr_err("OV7660 sensor initialization failed\n"); | 1327 | if (gspca_dev->usb_err < 0) |
1344 | return -ENODEV; | 1328 | pr_err("OV7660 sensor initialization failed\n"); |
1345 | } | ||
1346 | } | ||
1347 | sd->hstart = 3; | 1329 | sd->hstart = 3; |
1348 | sd->vstart = 3; | 1330 | sd->vstart = 3; |
1349 | return 0; | ||
1350 | } | 1331 | } |
1351 | 1332 | ||
1352 | static int ov7670_init_sensor(struct gspca_dev *gspca_dev) | 1333 | static void ov7670_init_sensor(struct gspca_dev *gspca_dev) |
1353 | { | 1334 | { |
1354 | int i; | ||
1355 | struct sd *sd = (struct sd *) gspca_dev; | 1335 | struct sd *sd = (struct sd *) gspca_dev; |
1356 | 1336 | ||
1357 | for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) { | 1337 | i2c_w1(gspca_dev, 0x12, 0x80); /* sensor reset */ |
1358 | if (i2c_w1(gspca_dev, ov7670_init[i].reg, | 1338 | msleep(200); |
1359 | ov7670_init[i].val) < 0) { | 1339 | i2c_w1_buf(gspca_dev, ov7670_init, ARRAY_SIZE(ov7670_init)); |
1360 | pr_err("OV7670 sensor initialization failed\n"); | 1340 | if (gspca_dev->usb_err < 0) |
1361 | return -ENODEV; | 1341 | pr_err("OV7670 sensor initialization failed\n"); |
1362 | } | 1342 | |
1363 | } | ||
1364 | /* disable hflip and vflip */ | 1343 | /* disable hflip and vflip */ |
1365 | gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); | 1344 | gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP); |
1366 | sd->hstart = 0; | 1345 | sd->hstart = 0; |
1367 | sd->vstart = 1; | 1346 | sd->vstart = 1; |
1368 | return 0; | ||
1369 | } | 1347 | } |
1370 | 1348 | ||
1371 | static int mt9v_init_sensor(struct gspca_dev *gspca_dev) | 1349 | static void mt9v_init_sensor(struct gspca_dev *gspca_dev) |
1372 | { | 1350 | { |
1373 | struct sd *sd = (struct sd *) gspca_dev; | 1351 | struct sd *sd = (struct sd *) gspca_dev; |
1374 | int i; | ||
1375 | u16 value; | 1352 | u16 value; |
1376 | int ret; | ||
1377 | 1353 | ||
1378 | sd->i2c_addr = 0x5d; | 1354 | sd->i2c_addr = 0x5d; |
1379 | ret = i2c_r2(gspca_dev, 0xff, &value); | 1355 | i2c_r2(gspca_dev, 0xff, &value); |
1380 | if ((ret == 0) && (value == 0x8243)) { | 1356 | if (gspca_dev->usb_err >= 0 |
1381 | for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) { | 1357 | && value == 0x8243) { |
1382 | if (i2c_w2(gspca_dev, mt9v011_init[i].reg, | 1358 | i2c_w2_buf(gspca_dev, mt9v011_init, ARRAY_SIZE(mt9v011_init)); |
1383 | mt9v011_init[i].val) < 0) { | 1359 | if (gspca_dev->usb_err < 0) { |
1384 | pr_err("MT9V011 sensor initialization failed\n"); | 1360 | pr_err("MT9V011 sensor initialization failed\n"); |
1385 | return -ENODEV; | 1361 | return; |
1386 | } | ||
1387 | } | 1362 | } |
1388 | sd->hstart = 2; | 1363 | sd->hstart = 2; |
1389 | sd->vstart = 2; | 1364 | sd->vstart = 2; |
1390 | sd->sensor = SENSOR_MT9V011; | 1365 | sd->sensor = SENSOR_MT9V011; |
1391 | pr_info("MT9V011 sensor detected\n"); | 1366 | pr_info("MT9V011 sensor detected\n"); |
1392 | return 0; | 1367 | return; |
1393 | } | 1368 | } |
1394 | 1369 | ||
1370 | gspca_dev->usb_err = 0; | ||
1395 | sd->i2c_addr = 0x5c; | 1371 | sd->i2c_addr = 0x5c; |
1396 | i2c_w2(gspca_dev, 0x01, 0x0004); | 1372 | i2c_w2(gspca_dev, 0x01, 0x0004); |
1397 | ret = i2c_r2(gspca_dev, 0xff, &value); | 1373 | i2c_r2(gspca_dev, 0xff, &value); |
1398 | if ((ret == 0) && (value == 0x823a)) { | 1374 | if (gspca_dev->usb_err >= 0 |
1399 | for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) { | 1375 | && value == 0x823a) { |
1400 | if (i2c_w2(gspca_dev, mt9v111_init[i].reg, | 1376 | i2c_w2_buf(gspca_dev, mt9v111_init, ARRAY_SIZE(mt9v111_init)); |
1401 | mt9v111_init[i].val) < 0) { | 1377 | if (gspca_dev->usb_err < 0) { |
1402 | pr_err("MT9V111 sensor initialization failed\n"); | 1378 | pr_err("MT9V111 sensor initialization failed\n"); |
1403 | return -ENODEV; | 1379 | return; |
1404 | } | ||
1405 | } | 1380 | } |
1406 | gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | 1381 | gspca_dev->ctrl_dis = (1 << EXPOSURE) |
1407 | | (1 << AUTOGAIN_IDX) | 1382 | | (1 << AUTOGAIN) |
1408 | | (1 << GAIN_IDX); | 1383 | | (1 << GAIN); |
1409 | sd->hstart = 2; | 1384 | sd->hstart = 2; |
1410 | sd->vstart = 2; | 1385 | sd->vstart = 2; |
1411 | sd->sensor = SENSOR_MT9V111; | 1386 | sd->sensor = SENSOR_MT9V111; |
1412 | pr_info("MT9V111 sensor detected\n"); | 1387 | pr_info("MT9V111 sensor detected\n"); |
1413 | return 0; | 1388 | return; |
1414 | } | 1389 | } |
1415 | 1390 | ||
1391 | gspca_dev->usb_err = 0; | ||
1416 | sd->i2c_addr = 0x5d; | 1392 | sd->i2c_addr = 0x5d; |
1417 | ret = i2c_w2(gspca_dev, 0xf0, 0x0000); | 1393 | i2c_w2(gspca_dev, 0xf0, 0x0000); |
1418 | if (ret < 0) { | 1394 | if (gspca_dev->usb_err < 0) { |
1395 | gspca_dev->usb_err = 0; | ||
1419 | sd->i2c_addr = 0x48; | 1396 | sd->i2c_addr = 0x48; |
1420 | i2c_w2(gspca_dev, 0xf0, 0x0000); | 1397 | i2c_w2(gspca_dev, 0xf0, 0x0000); |
1421 | } | 1398 | } |
1422 | ret = i2c_r2(gspca_dev, 0x00, &value); | 1399 | i2c_r2(gspca_dev, 0x00, &value); |
1423 | if ((ret == 0) && (value == 0x1229)) { | 1400 | if (gspca_dev->usb_err >= 0 |
1424 | for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) { | 1401 | && value == 0x1229) { |
1425 | if (i2c_w2(gspca_dev, mt9v112_init[i].reg, | 1402 | i2c_w2_buf(gspca_dev, mt9v112_init, ARRAY_SIZE(mt9v112_init)); |
1426 | mt9v112_init[i].val) < 0) { | 1403 | if (gspca_dev->usb_err < 0) { |
1427 | pr_err("MT9V112 sensor initialization failed\n"); | 1404 | pr_err("MT9V112 sensor initialization failed\n"); |
1428 | return -ENODEV; | 1405 | return; |
1429 | } | ||
1430 | } | 1406 | } |
1431 | sd->hstart = 6; | 1407 | sd->hstart = 6; |
1432 | sd->vstart = 2; | 1408 | sd->vstart = 2; |
1433 | sd->sensor = SENSOR_MT9V112; | 1409 | sd->sensor = SENSOR_MT9V112; |
1434 | pr_info("MT9V112 sensor detected\n"); | 1410 | pr_info("MT9V112 sensor detected\n"); |
1435 | return 0; | 1411 | return; |
1436 | } | 1412 | } |
1437 | 1413 | ||
1438 | return -ENODEV; | 1414 | gspca_dev->usb_err = -ENODEV; |
1439 | } | 1415 | } |
1440 | 1416 | ||
1441 | static int mt9m112_init_sensor(struct gspca_dev *gspca_dev) | 1417 | static void mt9m112_init_sensor(struct gspca_dev *gspca_dev) |
1442 | { | 1418 | { |
1443 | struct sd *sd = (struct sd *) gspca_dev; | 1419 | struct sd *sd = (struct sd *) gspca_dev; |
1444 | int i; | 1420 | |
1445 | for (i = 0; i < ARRAY_SIZE(mt9m112_init); i++) { | 1421 | i2c_w2_buf(gspca_dev, mt9m112_init, ARRAY_SIZE(mt9m112_init)); |
1446 | if (i2c_w2(gspca_dev, mt9m112_init[i].reg, | 1422 | if (gspca_dev->usb_err < 0) |
1447 | mt9m112_init[i].val) < 0) { | 1423 | pr_err("MT9M112 sensor initialization failed\n"); |
1448 | pr_err("MT9M112 sensor initialization failed\n"); | 1424 | |
1449 | return -ENODEV; | 1425 | gspca_dev->ctrl_dis = (1 << EXPOSURE) | (1 << AUTOGAIN) |
1450 | } | 1426 | | (1 << GAIN); |
1451 | } | ||
1452 | gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | ||
1453 | | (1 << GAIN_IDX); | ||
1454 | sd->hstart = 0; | 1427 | sd->hstart = 0; |
1455 | sd->vstart = 2; | 1428 | sd->vstart = 2; |
1456 | return 0; | ||
1457 | } | 1429 | } |
1458 | 1430 | ||
1459 | static int mt9m111_init_sensor(struct gspca_dev *gspca_dev) | 1431 | static void mt9m111_init_sensor(struct gspca_dev *gspca_dev) |
1460 | { | 1432 | { |
1461 | struct sd *sd = (struct sd *) gspca_dev; | 1433 | struct sd *sd = (struct sd *) gspca_dev; |
1462 | int i; | 1434 | |
1463 | for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) { | 1435 | i2c_w2_buf(gspca_dev, mt9m111_init, ARRAY_SIZE(mt9m111_init)); |
1464 | if (i2c_w2(gspca_dev, mt9m111_init[i].reg, | 1436 | if (gspca_dev->usb_err < 0) |
1465 | mt9m111_init[i].val) < 0) { | 1437 | pr_err("MT9M111 sensor initialization failed\n"); |
1466 | pr_err("MT9M111 sensor initialization failed\n"); | 1438 | |
1467 | return -ENODEV; | 1439 | gspca_dev->ctrl_dis = (1 << EXPOSURE) | (1 << AUTOGAIN) |
1468 | } | 1440 | | (1 << GAIN); |
1469 | } | ||
1470 | gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | ||
1471 | | (1 << GAIN_IDX); | ||
1472 | sd->hstart = 0; | 1441 | sd->hstart = 0; |
1473 | sd->vstart = 2; | 1442 | sd->vstart = 2; |
1474 | return 0; | ||
1475 | } | 1443 | } |
1476 | 1444 | ||
1477 | static int mt9m001_init_sensor(struct gspca_dev *gspca_dev) | 1445 | static void mt9m001_init_sensor(struct gspca_dev *gspca_dev) |
1478 | { | 1446 | { |
1479 | struct sd *sd = (struct sd *) gspca_dev; | 1447 | struct sd *sd = (struct sd *) gspca_dev; |
1480 | int i; | ||
1481 | u16 id; | 1448 | u16 id; |
1482 | 1449 | ||
1483 | if (i2c_r2(gspca_dev, 0x00, &id) < 0) | 1450 | i2c_r2(gspca_dev, 0x00, &id); |
1484 | return -EINVAL; | 1451 | if (gspca_dev->usb_err < 0) |
1452 | return; | ||
1485 | 1453 | ||
1486 | /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */ | 1454 | /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */ |
1487 | switch (id) { | 1455 | switch (id) { |
@@ -1494,85 +1462,78 @@ static int mt9m001_init_sensor(struct gspca_dev *gspca_dev) | |||
1494 | break; | 1462 | break; |
1495 | default: | 1463 | default: |
1496 | pr_err("No MT9M001 chip detected, ID = %x\n\n", id); | 1464 | pr_err("No MT9M001 chip detected, ID = %x\n\n", id); |
1497 | return -ENODEV; | 1465 | gspca_dev->usb_err = -ENODEV; |
1466 | return; | ||
1498 | } | 1467 | } |
1499 | 1468 | ||
1500 | for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) { | 1469 | i2c_w2_buf(gspca_dev, mt9m001_init, ARRAY_SIZE(mt9m001_init)); |
1501 | if (i2c_w2(gspca_dev, mt9m001_init[i].reg, | 1470 | if (gspca_dev->usb_err < 0) |
1502 | mt9m001_init[i].val) < 0) { | 1471 | pr_err("MT9M001 sensor initialization failed\n"); |
1503 | pr_err("MT9M001 sensor initialization failed\n"); | 1472 | |
1504 | return -ENODEV; | ||
1505 | } | ||
1506 | } | ||
1507 | /* disable hflip and vflip */ | 1473 | /* disable hflip and vflip */ |
1508 | gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); | 1474 | gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP); |
1509 | sd->hstart = 1; | 1475 | sd->hstart = 1; |
1510 | sd->vstart = 1; | 1476 | sd->vstart = 1; |
1511 | return 0; | ||
1512 | } | 1477 | } |
1513 | 1478 | ||
1514 | static int hv7131r_init_sensor(struct gspca_dev *gspca_dev) | 1479 | static void hv7131r_init_sensor(struct gspca_dev *gspca_dev) |
1515 | { | 1480 | { |
1516 | int i; | ||
1517 | struct sd *sd = (struct sd *) gspca_dev; | 1481 | struct sd *sd = (struct sd *) gspca_dev; |
1518 | 1482 | ||
1519 | for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) { | 1483 | i2c_w1_buf(gspca_dev, hv7131r_init, ARRAY_SIZE(hv7131r_init)); |
1520 | if (i2c_w1(gspca_dev, hv7131r_init[i].reg, | 1484 | if (gspca_dev->usb_err < 0) |
1521 | hv7131r_init[i].val) < 0) { | 1485 | pr_err("HV7131R Sensor initialization failed\n"); |
1522 | pr_err("HV7131R Sensor initialization failed\n"); | 1486 | |
1523 | return -ENODEV; | ||
1524 | } | ||
1525 | } | ||
1526 | sd->hstart = 0; | 1487 | sd->hstart = 0; |
1527 | sd->vstart = 1; | 1488 | sd->vstart = 1; |
1528 | return 0; | ||
1529 | } | 1489 | } |
1530 | 1490 | ||
1531 | static int set_cmatrix(struct gspca_dev *gspca_dev) | 1491 | static void set_cmatrix(struct gspca_dev *gspca_dev) |
1532 | { | 1492 | { |
1533 | struct sd *sd = (struct sd *) gspca_dev; | 1493 | struct sd *sd = (struct sd *) gspca_dev; |
1534 | s32 hue_coord, hue_index = 180 + sd->hue; | 1494 | int satur; |
1495 | s32 hue_coord, hue_index = 180 + sd->ctrls[HUE].val; | ||
1535 | u8 cmatrix[21]; | 1496 | u8 cmatrix[21]; |
1536 | 1497 | ||
1537 | memset(cmatrix, 0, sizeof cmatrix); | 1498 | memset(cmatrix, 0, sizeof cmatrix); |
1538 | cmatrix[2] = (sd->contrast * 0x25 / 0x100) + 0x26; | 1499 | cmatrix[2] = (sd->ctrls[CONTRAST].val * 0x25 / 0x100) + 0x26; |
1539 | cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25; | 1500 | cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25; |
1540 | cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25; | 1501 | cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25; |
1541 | cmatrix[18] = sd->brightness - 0x80; | 1502 | cmatrix[18] = sd->ctrls[BRIGHTNESS].val - 0x80; |
1542 | 1503 | ||
1543 | hue_coord = (hsv_red_x[hue_index] * sd->saturation) >> 8; | 1504 | satur = sd->ctrls[SATURATION].val; |
1505 | hue_coord = (hsv_red_x[hue_index] * satur) >> 8; | ||
1544 | cmatrix[6] = hue_coord; | 1506 | cmatrix[6] = hue_coord; |
1545 | cmatrix[7] = (hue_coord >> 8) & 0x0f; | 1507 | cmatrix[7] = (hue_coord >> 8) & 0x0f; |
1546 | 1508 | ||
1547 | hue_coord = (hsv_red_y[hue_index] * sd->saturation) >> 8; | 1509 | hue_coord = (hsv_red_y[hue_index] * satur) >> 8; |
1548 | cmatrix[8] = hue_coord; | 1510 | cmatrix[8] = hue_coord; |
1549 | cmatrix[9] = (hue_coord >> 8) & 0x0f; | 1511 | cmatrix[9] = (hue_coord >> 8) & 0x0f; |
1550 | 1512 | ||
1551 | hue_coord = (hsv_green_x[hue_index] * sd->saturation) >> 8; | 1513 | hue_coord = (hsv_green_x[hue_index] * satur) >> 8; |
1552 | cmatrix[10] = hue_coord; | 1514 | cmatrix[10] = hue_coord; |
1553 | cmatrix[11] = (hue_coord >> 8) & 0x0f; | 1515 | cmatrix[11] = (hue_coord >> 8) & 0x0f; |
1554 | 1516 | ||
1555 | hue_coord = (hsv_green_y[hue_index] * sd->saturation) >> 8; | 1517 | hue_coord = (hsv_green_y[hue_index] * satur) >> 8; |
1556 | cmatrix[12] = hue_coord; | 1518 | cmatrix[12] = hue_coord; |
1557 | cmatrix[13] = (hue_coord >> 8) & 0x0f; | 1519 | cmatrix[13] = (hue_coord >> 8) & 0x0f; |
1558 | 1520 | ||
1559 | hue_coord = (hsv_blue_x[hue_index] * sd->saturation) >> 8; | 1521 | hue_coord = (hsv_blue_x[hue_index] * satur) >> 8; |
1560 | cmatrix[14] = hue_coord; | 1522 | cmatrix[14] = hue_coord; |
1561 | cmatrix[15] = (hue_coord >> 8) & 0x0f; | 1523 | cmatrix[15] = (hue_coord >> 8) & 0x0f; |
1562 | 1524 | ||
1563 | hue_coord = (hsv_blue_y[hue_index] * sd->saturation) >> 8; | 1525 | hue_coord = (hsv_blue_y[hue_index] * satur) >> 8; |
1564 | cmatrix[16] = hue_coord; | 1526 | cmatrix[16] = hue_coord; |
1565 | cmatrix[17] = (hue_coord >> 8) & 0x0f; | 1527 | cmatrix[17] = (hue_coord >> 8) & 0x0f; |
1566 | 1528 | ||
1567 | return reg_w(gspca_dev, 0x10e1, cmatrix, 21); | 1529 | reg_w(gspca_dev, 0x10e1, cmatrix, 21); |
1568 | } | 1530 | } |
1569 | 1531 | ||
1570 | static int set_gamma(struct gspca_dev *gspca_dev) | 1532 | static void set_gamma(struct gspca_dev *gspca_dev) |
1571 | { | 1533 | { |
1572 | struct sd *sd = (struct sd *) gspca_dev; | 1534 | struct sd *sd = (struct sd *) gspca_dev; |
1573 | u8 gamma[17]; | 1535 | u8 gamma[17]; |
1574 | u8 gval = sd->gamma * 0xb8 / 0x100; | 1536 | u8 gval = sd->ctrls[GAMMA].val * 0xb8 / 0x100; |
1575 | |||
1576 | 1537 | ||
1577 | gamma[0] = 0x0a; | 1538 | gamma[0] = 0x0a; |
1578 | gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8); | 1539 | gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8); |
@@ -1592,29 +1553,29 @@ static int set_gamma(struct gspca_dev *gspca_dev) | |||
1592 | gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8); | 1553 | gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8); |
1593 | gamma[16] = 0xf5; | 1554 | gamma[16] = 0xf5; |
1594 | 1555 | ||
1595 | return reg_w(gspca_dev, 0x1190, gamma, 17); | 1556 | reg_w(gspca_dev, 0x1190, gamma, 17); |
1596 | } | 1557 | } |
1597 | 1558 | ||
1598 | static int set_redblue(struct gspca_dev *gspca_dev) | 1559 | static void set_redblue(struct gspca_dev *gspca_dev) |
1599 | { | 1560 | { |
1600 | struct sd *sd = (struct sd *) gspca_dev; | 1561 | struct sd *sd = (struct sd *) gspca_dev; |
1601 | reg_w1(gspca_dev, 0x118c, sd->red); | 1562 | |
1602 | reg_w1(gspca_dev, 0x118f, sd->blue); | 1563 | reg_w1(gspca_dev, 0x118c, sd->ctrls[RED].val); |
1603 | return 0; | 1564 | reg_w1(gspca_dev, 0x118f, sd->ctrls[BLUE].val); |
1604 | } | 1565 | } |
1605 | 1566 | ||
1606 | static int set_hvflip(struct gspca_dev *gspca_dev) | 1567 | static void set_hvflip(struct gspca_dev *gspca_dev) |
1607 | { | 1568 | { |
1608 | u8 value, tslb, hflip, vflip; | 1569 | u8 value, tslb, hflip, vflip; |
1609 | u16 value2; | 1570 | u16 value2; |
1610 | struct sd *sd = (struct sd *) gspca_dev; | 1571 | struct sd *sd = (struct sd *) gspca_dev; |
1611 | 1572 | ||
1612 | if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) { | 1573 | if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) { |
1613 | hflip = !sd->hflip; | 1574 | hflip = !sd->ctrls[HFLIP].val; |
1614 | vflip = !sd->vflip; | 1575 | vflip = !sd->ctrls[VFLIP].val; |
1615 | } else { | 1576 | } else { |
1616 | hflip = sd->hflip; | 1577 | hflip = sd->ctrls[HFLIP].val; |
1617 | vflip = sd->vflip; | 1578 | vflip = sd->ctrls[VFLIP].val; |
1618 | } | 1579 | } |
1619 | 1580 | ||
1620 | switch (sd->sensor) { | 1581 | switch (sd->sensor) { |
@@ -1625,8 +1586,9 @@ static int set_hvflip(struct gspca_dev *gspca_dev) | |||
1625 | if (vflip) { | 1586 | if (vflip) { |
1626 | value |= 0x10; | 1587 | value |= 0x10; |
1627 | sd->vstart = 2; | 1588 | sd->vstart = 2; |
1628 | } else | 1589 | } else { |
1629 | sd->vstart = 3; | 1590 | sd->vstart = 3; |
1591 | } | ||
1630 | reg_w1(gspca_dev, 0x1182, sd->vstart); | 1592 | reg_w1(gspca_dev, 0x1182, sd->vstart); |
1631 | i2c_w1(gspca_dev, 0x1e, value); | 1593 | i2c_w1(gspca_dev, 0x1e, value); |
1632 | break; | 1594 | break; |
@@ -1674,13 +1636,15 @@ static int set_hvflip(struct gspca_dev *gspca_dev) | |||
1674 | i2c_w1(gspca_dev, 0x01, value); | 1636 | i2c_w1(gspca_dev, 0x01, value); |
1675 | break; | 1637 | break; |
1676 | } | 1638 | } |
1677 | return 0; | ||
1678 | } | 1639 | } |
1679 | 1640 | ||
1680 | static int set_exposure(struct gspca_dev *gspca_dev) | 1641 | static void set_exposure(struct gspca_dev *gspca_dev) |
1681 | { | 1642 | { |
1682 | struct sd *sd = (struct sd *) gspca_dev; | 1643 | struct sd *sd = (struct sd *) gspca_dev; |
1683 | u8 exp[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e}; | 1644 | u8 exp[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e}; |
1645 | int expo; | ||
1646 | |||
1647 | expo = sd->ctrls[EXPOSURE].val; | ||
1684 | switch (sd->sensor) { | 1648 | switch (sd->sensor) { |
1685 | case SENSOR_OV7660: | 1649 | case SENSOR_OV7660: |
1686 | case SENSOR_OV7670: | 1650 | case SENSOR_OV7670: |
@@ -1688,35 +1652,37 @@ static int set_exposure(struct gspca_dev *gspca_dev) | |||
1688 | case SENSOR_OV9650: | 1652 | case SENSOR_OV9650: |
1689 | exp[0] |= (3 << 4); | 1653 | exp[0] |= (3 << 4); |
1690 | exp[2] = 0x2d; | 1654 | exp[2] = 0x2d; |
1691 | exp[3] = sd->exposure & 0xff; | 1655 | exp[3] = expo; |
1692 | exp[4] = sd->exposure >> 8; | 1656 | exp[4] = expo >> 8; |
1693 | break; | 1657 | break; |
1694 | case SENSOR_MT9M001: | 1658 | case SENSOR_MT9M001: |
1695 | case SENSOR_MT9V112: | 1659 | case SENSOR_MT9V112: |
1696 | case SENSOR_MT9V011: | 1660 | case SENSOR_MT9V011: |
1697 | exp[0] |= (3 << 4); | 1661 | exp[0] |= (3 << 4); |
1698 | exp[2] = 0x09; | 1662 | exp[2] = 0x09; |
1699 | exp[3] = sd->exposure >> 8; | 1663 | exp[3] = expo >> 8; |
1700 | exp[4] = sd->exposure & 0xff; | 1664 | exp[4] = expo; |
1701 | break; | 1665 | break; |
1702 | case SENSOR_HV7131R: | 1666 | case SENSOR_HV7131R: |
1703 | exp[0] |= (4 << 4); | 1667 | exp[0] |= (4 << 4); |
1704 | exp[2] = 0x25; | 1668 | exp[2] = 0x25; |
1705 | exp[3] = (sd->exposure >> 5) & 0xff; | 1669 | exp[3] = expo >> 5; |
1706 | exp[4] = (sd->exposure << 3) & 0xff; | 1670 | exp[4] = expo << 3; |
1707 | exp[5] = 0; | 1671 | exp[5] = 0; |
1708 | break; | 1672 | break; |
1709 | default: | 1673 | default: |
1710 | return 0; | 1674 | return; |
1711 | } | 1675 | } |
1712 | i2c_w(gspca_dev, exp); | 1676 | i2c_w(gspca_dev, exp); |
1713 | return 0; | ||
1714 | } | 1677 | } |
1715 | 1678 | ||
1716 | static int set_gain(struct gspca_dev *gspca_dev) | 1679 | static void set_gain(struct gspca_dev *gspca_dev) |
1717 | { | 1680 | { |
1718 | struct sd *sd = (struct sd *) gspca_dev; | 1681 | struct sd *sd = (struct sd *) gspca_dev; |
1719 | u8 gain[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d}; | 1682 | u8 gain[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d}; |
1683 | int g; | ||
1684 | |||
1685 | g = sd->ctrls[GAIN].val; | ||
1720 | switch (sd->sensor) { | 1686 | switch (sd->sensor) { |
1721 | case SENSOR_OV7660: | 1687 | case SENSOR_OV7660: |
1722 | case SENSOR_OV7670: | 1688 | case SENSOR_OV7670: |
@@ -1724,238 +1690,50 @@ static int set_gain(struct gspca_dev *gspca_dev) | |||
1724 | case SENSOR_OV9655: | 1690 | case SENSOR_OV9655: |
1725 | case SENSOR_OV9650: | 1691 | case SENSOR_OV9650: |
1726 | gain[0] |= (2 << 4); | 1692 | gain[0] |= (2 << 4); |
1727 | gain[3] = ov_gain[sd->gain]; | 1693 | gain[3] = ov_gain[g]; |
1728 | break; | 1694 | break; |
1729 | case SENSOR_MT9V011: | 1695 | case SENSOR_MT9V011: |
1730 | gain[0] |= (3 << 4); | 1696 | gain[0] |= (3 << 4); |
1731 | gain[2] = 0x35; | 1697 | gain[2] = 0x35; |
1732 | gain[3] = micron1_gain[sd->gain] >> 8; | 1698 | gain[3] = micron1_gain[g] >> 8; |
1733 | gain[4] = micron1_gain[sd->gain] & 0xff; | 1699 | gain[4] = micron1_gain[g]; |
1734 | break; | 1700 | break; |
1735 | case SENSOR_MT9V112: | 1701 | case SENSOR_MT9V112: |
1736 | gain[0] |= (3 << 4); | 1702 | gain[0] |= (3 << 4); |
1737 | gain[2] = 0x2f; | 1703 | gain[2] = 0x2f; |
1738 | gain[3] = micron1_gain[sd->gain] >> 8; | 1704 | gain[3] = micron1_gain[g] >> 8; |
1739 | gain[4] = micron1_gain[sd->gain] & 0xff; | 1705 | gain[4] = micron1_gain[g]; |
1740 | break; | 1706 | break; |
1741 | case SENSOR_MT9M001: | 1707 | case SENSOR_MT9M001: |
1742 | gain[0] |= (3 << 4); | 1708 | gain[0] |= (3 << 4); |
1743 | gain[2] = 0x2f; | 1709 | gain[2] = 0x2f; |
1744 | gain[3] = micron2_gain[sd->gain] >> 8; | 1710 | gain[3] = micron2_gain[g] >> 8; |
1745 | gain[4] = micron2_gain[sd->gain] & 0xff; | 1711 | gain[4] = micron2_gain[g]; |
1746 | break; | 1712 | break; |
1747 | case SENSOR_HV7131R: | 1713 | case SENSOR_HV7131R: |
1748 | gain[0] |= (2 << 4); | 1714 | gain[0] |= (2 << 4); |
1749 | gain[2] = 0x30; | 1715 | gain[2] = 0x30; |
1750 | gain[3] = hv7131r_gain[sd->gain]; | 1716 | gain[3] = hv7131r_gain[g]; |
1751 | break; | 1717 | break; |
1752 | default: | 1718 | default: |
1753 | return 0; | 1719 | return; |
1754 | } | 1720 | } |
1755 | i2c_w(gspca_dev, gain); | 1721 | i2c_w(gspca_dev, gain); |
1756 | return 0; | ||
1757 | } | ||
1758 | |||
1759 | static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val) | ||
1760 | { | ||
1761 | struct sd *sd = (struct sd *) gspca_dev; | ||
1762 | |||
1763 | sd->brightness = val; | ||
1764 | if (gspca_dev->streaming) | ||
1765 | return set_cmatrix(gspca_dev); | ||
1766 | return 0; | ||
1767 | } | ||
1768 | |||
1769 | static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val) | ||
1770 | { | ||
1771 | struct sd *sd = (struct sd *) gspca_dev; | ||
1772 | *val = sd->brightness; | ||
1773 | return 0; | ||
1774 | } | ||
1775 | |||
1776 | |||
1777 | static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val) | ||
1778 | { | ||
1779 | struct sd *sd = (struct sd *) gspca_dev; | ||
1780 | |||
1781 | sd->contrast = val; | ||
1782 | if (gspca_dev->streaming) | ||
1783 | return set_cmatrix(gspca_dev); | ||
1784 | return 0; | ||
1785 | } | ||
1786 | |||
1787 | static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val) | ||
1788 | { | ||
1789 | struct sd *sd = (struct sd *) gspca_dev; | ||
1790 | *val = sd->contrast; | ||
1791 | return 0; | ||
1792 | } | ||
1793 | |||
1794 | static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val) | ||
1795 | { | ||
1796 | struct sd *sd = (struct sd *) gspca_dev; | ||
1797 | |||
1798 | sd->saturation = val; | ||
1799 | if (gspca_dev->streaming) | ||
1800 | return set_cmatrix(gspca_dev); | ||
1801 | return 0; | ||
1802 | } | 1722 | } |
1803 | 1723 | ||
1804 | static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val) | 1724 | static void set_quality(struct gspca_dev *gspca_dev) |
1805 | { | 1725 | { |
1806 | struct sd *sd = (struct sd *) gspca_dev; | 1726 | struct sd *sd = (struct sd *) gspca_dev; |
1807 | *val = sd->saturation; | ||
1808 | return 0; | ||
1809 | } | ||
1810 | |||
1811 | static int sd_sethue(struct gspca_dev *gspca_dev, s32 val) | ||
1812 | { | ||
1813 | struct sd *sd = (struct sd *) gspca_dev; | ||
1814 | |||
1815 | sd->hue = val; | ||
1816 | if (gspca_dev->streaming) | ||
1817 | return set_cmatrix(gspca_dev); | ||
1818 | return 0; | ||
1819 | } | ||
1820 | |||
1821 | static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val) | ||
1822 | { | ||
1823 | struct sd *sd = (struct sd *) gspca_dev; | ||
1824 | *val = sd->hue; | ||
1825 | return 0; | ||
1826 | } | ||
1827 | |||
1828 | static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val) | ||
1829 | { | ||
1830 | struct sd *sd = (struct sd *) gspca_dev; | ||
1831 | |||
1832 | sd->gamma = val; | ||
1833 | if (gspca_dev->streaming) | ||
1834 | return set_gamma(gspca_dev); | ||
1835 | return 0; | ||
1836 | } | ||
1837 | |||
1838 | static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val) | ||
1839 | { | ||
1840 | struct sd *sd = (struct sd *) gspca_dev; | ||
1841 | *val = sd->gamma; | ||
1842 | return 0; | ||
1843 | } | ||
1844 | |||
1845 | static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val) | ||
1846 | { | ||
1847 | struct sd *sd = (struct sd *) gspca_dev; | ||
1848 | |||
1849 | sd->red = val; | ||
1850 | if (gspca_dev->streaming) | ||
1851 | return set_redblue(gspca_dev); | ||
1852 | return 0; | ||
1853 | } | ||
1854 | |||
1855 | static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val) | ||
1856 | { | ||
1857 | struct sd *sd = (struct sd *) gspca_dev; | ||
1858 | *val = sd->red; | ||
1859 | return 0; | ||
1860 | } | ||
1861 | |||
1862 | static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val) | ||
1863 | { | ||
1864 | struct sd *sd = (struct sd *) gspca_dev; | ||
1865 | |||
1866 | sd->blue = val; | ||
1867 | if (gspca_dev->streaming) | ||
1868 | return set_redblue(gspca_dev); | ||
1869 | return 0; | ||
1870 | } | ||
1871 | |||
1872 | static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val) | ||
1873 | { | ||
1874 | struct sd *sd = (struct sd *) gspca_dev; | ||
1875 | *val = sd->blue; | ||
1876 | return 0; | ||
1877 | } | ||
1878 | |||
1879 | static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val) | ||
1880 | { | ||
1881 | struct sd *sd = (struct sd *) gspca_dev; | ||
1882 | |||
1883 | sd->hflip = val; | ||
1884 | if (gspca_dev->streaming) | ||
1885 | return set_hvflip(gspca_dev); | ||
1886 | return 0; | ||
1887 | } | ||
1888 | |||
1889 | static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val) | ||
1890 | { | ||
1891 | struct sd *sd = (struct sd *) gspca_dev; | ||
1892 | *val = sd->hflip; | ||
1893 | return 0; | ||
1894 | } | ||
1895 | |||
1896 | static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val) | ||
1897 | { | ||
1898 | struct sd *sd = (struct sd *) gspca_dev; | ||
1899 | |||
1900 | sd->vflip = val; | ||
1901 | if (gspca_dev->streaming) | ||
1902 | return set_hvflip(gspca_dev); | ||
1903 | return 0; | ||
1904 | } | ||
1905 | |||
1906 | static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val) | ||
1907 | { | ||
1908 | struct sd *sd = (struct sd *) gspca_dev; | ||
1909 | *val = sd->vflip; | ||
1910 | return 0; | ||
1911 | } | ||
1912 | |||
1913 | static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val) | ||
1914 | { | ||
1915 | struct sd *sd = (struct sd *) gspca_dev; | ||
1916 | |||
1917 | sd->exposure = val; | ||
1918 | if (gspca_dev->streaming) | ||
1919 | return set_exposure(gspca_dev); | ||
1920 | return 0; | ||
1921 | } | ||
1922 | |||
1923 | static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val) | ||
1924 | { | ||
1925 | struct sd *sd = (struct sd *) gspca_dev; | ||
1926 | *val = sd->exposure; | ||
1927 | return 0; | ||
1928 | } | ||
1929 | |||
1930 | static int sd_setgain(struct gspca_dev *gspca_dev, s32 val) | ||
1931 | { | ||
1932 | struct sd *sd = (struct sd *) gspca_dev; | ||
1933 | |||
1934 | sd->gain = val; | ||
1935 | if (gspca_dev->streaming) | ||
1936 | return set_gain(gspca_dev); | ||
1937 | return 0; | ||
1938 | } | ||
1939 | |||
1940 | static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val) | ||
1941 | { | ||
1942 | struct sd *sd = (struct sd *) gspca_dev; | ||
1943 | *val = sd->gain; | ||
1944 | return 0; | ||
1945 | } | ||
1946 | |||
1947 | static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val) | ||
1948 | { | ||
1949 | struct sd *sd = (struct sd *) gspca_dev; | ||
1950 | sd->auto_exposure = val; | ||
1951 | return 0; | ||
1952 | } | ||
1953 | 1727 | ||
1954 | static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val) | 1728 | jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val); |
1955 | { | 1729 | reg_w1(gspca_dev, 0x1061, 0x01); /* stop transfer */ |
1956 | struct sd *sd = (struct sd *) gspca_dev; | 1730 | reg_w1(gspca_dev, 0x10e0, sd->fmt | 0x20); /* write QTAB */ |
1957 | *val = sd->auto_exposure; | 1731 | reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64); |
1958 | return 0; | 1732 | reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64); |
1733 | reg_w1(gspca_dev, 0x1061, 0x03); /* restart transfer */ | ||
1734 | reg_w1(gspca_dev, 0x10e0, sd->fmt); | ||
1735 | sd->fmt ^= 0x0c; /* invert QTAB use + write */ | ||
1736 | reg_w1(gspca_dev, 0x10e0, sd->fmt); | ||
1959 | } | 1737 | } |
1960 | 1738 | ||
1961 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 1739 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
@@ -1963,28 +1741,26 @@ static int sd_dbg_g_register(struct gspca_dev *gspca_dev, | |||
1963 | struct v4l2_dbg_register *reg) | 1741 | struct v4l2_dbg_register *reg) |
1964 | { | 1742 | { |
1965 | struct sd *sd = (struct sd *) gspca_dev; | 1743 | struct sd *sd = (struct sd *) gspca_dev; |
1744 | |||
1966 | switch (reg->match.type) { | 1745 | switch (reg->match.type) { |
1967 | case V4L2_CHIP_MATCH_HOST: | 1746 | case V4L2_CHIP_MATCH_HOST: |
1968 | if (reg->match.addr != 0) | 1747 | if (reg->match.addr != 0) |
1969 | return -EINVAL; | 1748 | return -EINVAL; |
1970 | if (reg->reg < 0x1000 || reg->reg > 0x11ff) | 1749 | if (reg->reg < 0x1000 || reg->reg > 0x11ff) |
1971 | return -EINVAL; | 1750 | return -EINVAL; |
1972 | if (reg_r(gspca_dev, reg->reg, 1) < 0) | 1751 | reg_r(gspca_dev, reg->reg, 1); |
1973 | return -EINVAL; | ||
1974 | reg->val = gspca_dev->usb_buf[0]; | 1752 | reg->val = gspca_dev->usb_buf[0]; |
1975 | return 0; | 1753 | return gspca_dev->usb_err; |
1976 | case V4L2_CHIP_MATCH_I2C_ADDR: | 1754 | case V4L2_CHIP_MATCH_I2C_ADDR: |
1977 | if (reg->match.addr != sd->i2c_addr) | 1755 | if (reg->match.addr != sd->i2c_addr) |
1978 | return -EINVAL; | 1756 | return -EINVAL; |
1979 | if (sd->sensor >= SENSOR_MT9V011 && | 1757 | if (sd->sensor >= SENSOR_MT9V011 && |
1980 | sd->sensor <= SENSOR_MT9M112) { | 1758 | sd->sensor <= SENSOR_MT9M112) { |
1981 | if (i2c_r2(gspca_dev, reg->reg, (u16 *)®->val) < 0) | 1759 | i2c_r2(gspca_dev, reg->reg, (u16 *) ®->val); |
1982 | return -EINVAL; | ||
1983 | } else { | 1760 | } else { |
1984 | if (i2c_r1(gspca_dev, reg->reg, (u8 *)®->val) < 0) | 1761 | i2c_r1(gspca_dev, reg->reg, (u8 *) ®->val); |
1985 | return -EINVAL; | ||
1986 | } | 1762 | } |
1987 | return 0; | 1763 | return gspca_dev->usb_err; |
1988 | } | 1764 | } |
1989 | return -EINVAL; | 1765 | return -EINVAL; |
1990 | } | 1766 | } |
@@ -1993,27 +1769,25 @@ static int sd_dbg_s_register(struct gspca_dev *gspca_dev, | |||
1993 | struct v4l2_dbg_register *reg) | 1769 | struct v4l2_dbg_register *reg) |
1994 | { | 1770 | { |
1995 | struct sd *sd = (struct sd *) gspca_dev; | 1771 | struct sd *sd = (struct sd *) gspca_dev; |
1772 | |||
1996 | switch (reg->match.type) { | 1773 | switch (reg->match.type) { |
1997 | case V4L2_CHIP_MATCH_HOST: | 1774 | case V4L2_CHIP_MATCH_HOST: |
1998 | if (reg->match.addr != 0) | 1775 | if (reg->match.addr != 0) |
1999 | return -EINVAL; | 1776 | return -EINVAL; |
2000 | if (reg->reg < 0x1000 || reg->reg > 0x11ff) | 1777 | if (reg->reg < 0x1000 || reg->reg > 0x11ff) |
2001 | return -EINVAL; | 1778 | return -EINVAL; |
2002 | if (reg_w1(gspca_dev, reg->reg, reg->val) < 0) | 1779 | reg_w1(gspca_dev, reg->reg, reg->val); |
2003 | return -EINVAL; | 1780 | return gspca_dev->usb_err; |
2004 | return 0; | ||
2005 | case V4L2_CHIP_MATCH_I2C_ADDR: | 1781 | case V4L2_CHIP_MATCH_I2C_ADDR: |
2006 | if (reg->match.addr != sd->i2c_addr) | 1782 | if (reg->match.addr != sd->i2c_addr) |
2007 | return -EINVAL; | 1783 | return -EINVAL; |
2008 | if (sd->sensor >= SENSOR_MT9V011 && | 1784 | if (sd->sensor >= SENSOR_MT9V011 && |
2009 | sd->sensor <= SENSOR_MT9M112) { | 1785 | sd->sensor <= SENSOR_MT9M112) { |
2010 | if (i2c_w2(gspca_dev, reg->reg, reg->val) < 0) | 1786 | i2c_w2(gspca_dev, reg->reg, reg->val); |
2011 | return -EINVAL; | ||
2012 | } else { | 1787 | } else { |
2013 | if (i2c_w1(gspca_dev, reg->reg, reg->val) < 0) | 1788 | i2c_w1(gspca_dev, reg->reg, reg->val); |
2014 | return -EINVAL; | ||
2015 | } | 1789 | } |
2016 | return 0; | 1790 | return gspca_dev->usb_err; |
2017 | } | 1791 | } |
2018 | return -EINVAL; | 1792 | return -EINVAL; |
2019 | } | 1793 | } |
@@ -2050,9 +1824,9 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
2050 | cam = &gspca_dev->cam; | 1824 | cam = &gspca_dev->cam; |
2051 | cam->needs_full_bandwidth = 1; | 1825 | cam->needs_full_bandwidth = 1; |
2052 | 1826 | ||
2053 | sd->sensor = (id->driver_info >> 8) & 0xff; | 1827 | sd->sensor = id->driver_info >> 8; |
2054 | sd->i2c_addr = id->driver_info & 0xff; | 1828 | sd->i2c_addr = id->driver_info; |
2055 | sd->flags = (id->driver_info >> 16) & 0xff; | 1829 | sd->flags = id->driver_info >> 16; |
2056 | 1830 | ||
2057 | switch (sd->sensor) { | 1831 | switch (sd->sensor) { |
2058 | case SENSOR_MT9M112: | 1832 | case SENSOR_MT9M112: |
@@ -2076,21 +1850,9 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
2076 | sd->older_step = 0; | 1850 | sd->older_step = 0; |
2077 | sd->exposure_step = 16; | 1851 | sd->exposure_step = 16; |
2078 | 1852 | ||
2079 | sd->brightness = BRIGHTNESS_DEFAULT; | 1853 | gspca_dev->cam.ctrls = sd->ctrls; |
2080 | sd->contrast = CONTRAST_DEFAULT; | ||
2081 | sd->saturation = SATURATION_DEFAULT; | ||
2082 | sd->hue = HUE_DEFAULT; | ||
2083 | sd->gamma = GAMMA_DEFAULT; | ||
2084 | sd->red = RED_DEFAULT; | ||
2085 | sd->blue = BLUE_DEFAULT; | ||
2086 | 1854 | ||
2087 | sd->hflip = HFLIP_DEFAULT; | 1855 | INIT_WORK(&sd->work, qual_upd); |
2088 | sd->vflip = VFLIP_DEFAULT; | ||
2089 | sd->exposure = EXPOSURE_DEFAULT; | ||
2090 | sd->gain = GAIN_DEFAULT; | ||
2091 | sd->auto_exposure = AUTO_EXPOSURE_DEFAULT; | ||
2092 | |||
2093 | sd->quality = 95; | ||
2094 | 1856 | ||
2095 | return 0; | 1857 | return 0; |
2096 | } | 1858 | } |
@@ -2105,9 +1867,10 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
2105 | 1867 | ||
2106 | for (i = 0; i < ARRAY_SIZE(bridge_init); i++) { | 1868 | for (i = 0; i < ARRAY_SIZE(bridge_init); i++) { |
2107 | value = bridge_init[i][1]; | 1869 | value = bridge_init[i][1]; |
2108 | if (reg_w(gspca_dev, bridge_init[i][0], &value, 1) < 0) { | 1870 | reg_w(gspca_dev, bridge_init[i][0], &value, 1); |
1871 | if (gspca_dev->usb_err < 0) { | ||
2109 | pr_err("Device initialization failed\n"); | 1872 | pr_err("Device initialization failed\n"); |
2110 | return -ENODEV; | 1873 | return gspca_dev->usb_err; |
2111 | } | 1874 | } |
2112 | } | 1875 | } |
2113 | 1876 | ||
@@ -2116,72 +1879,85 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
2116 | else | 1879 | else |
2117 | reg_w1(gspca_dev, 0x1006, 0x20); | 1880 | reg_w1(gspca_dev, 0x1006, 0x20); |
2118 | 1881 | ||
2119 | if (reg_w(gspca_dev, 0x10c0, i2c_init, 9) < 0) { | 1882 | reg_w(gspca_dev, 0x10c0, i2c_init, 9); |
1883 | if (gspca_dev->usb_err < 0) { | ||
2120 | pr_err("Device initialization failed\n"); | 1884 | pr_err("Device initialization failed\n"); |
2121 | return -ENODEV; | 1885 | return gspca_dev->usb_err; |
2122 | } | 1886 | } |
2123 | 1887 | ||
2124 | switch (sd->sensor) { | 1888 | switch (sd->sensor) { |
2125 | case SENSOR_OV9650: | 1889 | case SENSOR_OV9650: |
2126 | if (ov9650_init_sensor(gspca_dev) < 0) | 1890 | ov9650_init_sensor(gspca_dev); |
2127 | return -ENODEV; | 1891 | if (gspca_dev->usb_err < 0) |
1892 | break; | ||
2128 | pr_info("OV9650 sensor detected\n"); | 1893 | pr_info("OV9650 sensor detected\n"); |
2129 | break; | 1894 | break; |
2130 | case SENSOR_OV9655: | 1895 | case SENSOR_OV9655: |
2131 | if (ov9655_init_sensor(gspca_dev) < 0) | 1896 | ov9655_init_sensor(gspca_dev); |
2132 | return -ENODEV; | 1897 | if (gspca_dev->usb_err < 0) |
1898 | break; | ||
2133 | pr_info("OV9655 sensor detected\n"); | 1899 | pr_info("OV9655 sensor detected\n"); |
2134 | break; | 1900 | break; |
2135 | case SENSOR_SOI968: | 1901 | case SENSOR_SOI968: |
2136 | if (soi968_init_sensor(gspca_dev) < 0) | 1902 | soi968_init_sensor(gspca_dev); |
2137 | return -ENODEV; | 1903 | if (gspca_dev->usb_err < 0) |
1904 | break; | ||
2138 | pr_info("SOI968 sensor detected\n"); | 1905 | pr_info("SOI968 sensor detected\n"); |
2139 | break; | 1906 | break; |
2140 | case SENSOR_OV7660: | 1907 | case SENSOR_OV7660: |
2141 | if (ov7660_init_sensor(gspca_dev) < 0) | 1908 | ov7660_init_sensor(gspca_dev); |
2142 | return -ENODEV; | 1909 | if (gspca_dev->usb_err < 0) |
1910 | break; | ||
2143 | pr_info("OV7660 sensor detected\n"); | 1911 | pr_info("OV7660 sensor detected\n"); |
2144 | break; | 1912 | break; |
2145 | case SENSOR_OV7670: | 1913 | case SENSOR_OV7670: |
2146 | if (ov7670_init_sensor(gspca_dev) < 0) | 1914 | ov7670_init_sensor(gspca_dev); |
2147 | return -ENODEV; | 1915 | if (gspca_dev->usb_err < 0) |
1916 | break; | ||
2148 | pr_info("OV7670 sensor detected\n"); | 1917 | pr_info("OV7670 sensor detected\n"); |
2149 | break; | 1918 | break; |
2150 | case SENSOR_MT9VPRB: | 1919 | case SENSOR_MT9VPRB: |
2151 | if (mt9v_init_sensor(gspca_dev) < 0) | 1920 | mt9v_init_sensor(gspca_dev); |
2152 | return -ENODEV; | 1921 | if (gspca_dev->usb_err < 0) |
1922 | break; | ||
1923 | pr_info("MT9VPRB sensor detected\n"); | ||
2153 | break; | 1924 | break; |
2154 | case SENSOR_MT9M111: | 1925 | case SENSOR_MT9M111: |
2155 | if (mt9m111_init_sensor(gspca_dev) < 0) | 1926 | mt9m111_init_sensor(gspca_dev); |
2156 | return -ENODEV; | 1927 | if (gspca_dev->usb_err < 0) |
1928 | break; | ||
2157 | pr_info("MT9M111 sensor detected\n"); | 1929 | pr_info("MT9M111 sensor detected\n"); |
2158 | break; | 1930 | break; |
2159 | case SENSOR_MT9M112: | 1931 | case SENSOR_MT9M112: |
2160 | if (mt9m112_init_sensor(gspca_dev) < 0) | 1932 | mt9m112_init_sensor(gspca_dev); |
2161 | return -ENODEV; | 1933 | if (gspca_dev->usb_err < 0) |
1934 | break; | ||
2162 | pr_info("MT9M112 sensor detected\n"); | 1935 | pr_info("MT9M112 sensor detected\n"); |
2163 | break; | 1936 | break; |
2164 | case SENSOR_MT9M001: | 1937 | case SENSOR_MT9M001: |
2165 | if (mt9m001_init_sensor(gspca_dev) < 0) | 1938 | mt9m001_init_sensor(gspca_dev); |
2166 | return -ENODEV; | 1939 | if (gspca_dev->usb_err < 0) |
1940 | break; | ||
2167 | break; | 1941 | break; |
2168 | case SENSOR_HV7131R: | 1942 | case SENSOR_HV7131R: |
2169 | if (hv7131r_init_sensor(gspca_dev) < 0) | 1943 | hv7131r_init_sensor(gspca_dev); |
2170 | return -ENODEV; | 1944 | if (gspca_dev->usb_err < 0) |
1945 | break; | ||
2171 | pr_info("HV7131R sensor detected\n"); | 1946 | pr_info("HV7131R sensor detected\n"); |
2172 | break; | 1947 | break; |
2173 | default: | 1948 | default: |
2174 | pr_info("Unsupported Sensor\n"); | 1949 | pr_err("Unsupported sensor\n"); |
2175 | return -ENODEV; | 1950 | gspca_dev->usb_err = -ENODEV; |
2176 | } | 1951 | } |
2177 | 1952 | ||
2178 | return 0; | 1953 | return gspca_dev->usb_err; |
2179 | } | 1954 | } |
2180 | 1955 | ||
2181 | static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode) | 1956 | static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode) |
2182 | { | 1957 | { |
2183 | struct sd *sd = (struct sd *) gspca_dev; | 1958 | struct sd *sd = (struct sd *) gspca_dev; |
2184 | u8 value; | 1959 | u8 value; |
1960 | |||
2185 | switch (sd->sensor) { | 1961 | switch (sd->sensor) { |
2186 | case SENSOR_SOI968: | 1962 | case SENSOR_SOI968: |
2187 | if (mode & MODE_SXGA) { | 1963 | if (mode & MODE_SXGA) { |
@@ -2264,6 +2040,7 @@ static int sd_isoc_init(struct gspca_dev *gspca_dev) | |||
2264 | break; | 2040 | break; |
2265 | default: /* >= 640x480 */ | 2041 | default: /* >= 640x480 */ |
2266 | gspca_dev->alt = 9; | 2042 | gspca_dev->alt = 9; |
2043 | break; | ||
2267 | } | 2044 | } |
2268 | } | 2045 | } |
2269 | 2046 | ||
@@ -2290,14 +2067,15 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2290 | 2067 | ||
2291 | jpeg_define(sd->jpeg_hdr, height, width, | 2068 | jpeg_define(sd->jpeg_hdr, height, width, |
2292 | 0x21); | 2069 | 0x21); |
2293 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | 2070 | jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val); |
2294 | 2071 | ||
2295 | if (mode & MODE_RAW) | 2072 | if (mode & MODE_RAW) |
2296 | fmt = 0x2d; | 2073 | fmt = 0x2d; |
2297 | else if (mode & MODE_JPEG) | 2074 | else if (mode & MODE_JPEG) |
2298 | fmt = 0x2c; | 2075 | fmt = 0x24; |
2299 | else | 2076 | else |
2300 | fmt = 0x2f; /* YUV 420 */ | 2077 | fmt = 0x2f; /* YUV 420 */ |
2078 | sd->fmt = fmt; | ||
2301 | 2079 | ||
2302 | switch (mode & SCALE_MASK) { | 2080 | switch (mode & SCALE_MASK) { |
2303 | case SCALE_1280x1024: | 2081 | case SCALE_1280x1024: |
@@ -2334,18 +2112,37 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2334 | set_hvflip(gspca_dev); | 2112 | set_hvflip(gspca_dev); |
2335 | 2113 | ||
2336 | reg_w1(gspca_dev, 0x1007, 0x20); | 2114 | reg_w1(gspca_dev, 0x1007, 0x20); |
2115 | reg_w1(gspca_dev, 0x1061, 0x03); | ||
2116 | |||
2117 | /* if JPEG, prepare the compression quality update */ | ||
2118 | if (mode & MODE_JPEG) { | ||
2119 | sd->pktsz = sd->npkt = 0; | ||
2120 | sd->nchg = 0; | ||
2121 | sd->work_thread = | ||
2122 | create_singlethread_workqueue(KBUILD_MODNAME); | ||
2123 | } | ||
2337 | 2124 | ||
2338 | reg_r(gspca_dev, 0x1061, 1); | 2125 | return gspca_dev->usb_err; |
2339 | reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] | 0x02); | ||
2340 | return 0; | ||
2341 | } | 2126 | } |
2342 | 2127 | ||
2343 | static void sd_stopN(struct gspca_dev *gspca_dev) | 2128 | static void sd_stopN(struct gspca_dev *gspca_dev) |
2344 | { | 2129 | { |
2345 | reg_w1(gspca_dev, 0x1007, 0x00); | 2130 | reg_w1(gspca_dev, 0x1007, 0x00); |
2131 | reg_w1(gspca_dev, 0x1061, 0x01); | ||
2132 | } | ||
2133 | |||
2134 | /* called on streamoff with alt==0 and on disconnect */ | ||
2135 | /* the usb_lock is held at entry - restore on exit */ | ||
2136 | static void sd_stop0(struct gspca_dev *gspca_dev) | ||
2137 | { | ||
2138 | struct sd *sd = (struct sd *) gspca_dev; | ||
2346 | 2139 | ||
2347 | reg_r(gspca_dev, 0x1061, 1); | 2140 | if (sd->work_thread != NULL) { |
2348 | reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02); | 2141 | mutex_unlock(&gspca_dev->usb_lock); |
2142 | destroy_workqueue(sd->work_thread); | ||
2143 | mutex_lock(&gspca_dev->usb_lock); | ||
2144 | sd->work_thread = NULL; | ||
2145 | } | ||
2349 | } | 2146 | } |
2350 | 2147 | ||
2351 | static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum) | 2148 | static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum) |
@@ -2359,15 +2156,15 @@ static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum) | |||
2359 | * and exposure steps | 2156 | * and exposure steps |
2360 | */ | 2157 | */ |
2361 | if (avg_lum < MIN_AVG_LUM) { | 2158 | if (avg_lum < MIN_AVG_LUM) { |
2362 | if (sd->exposure > 0x1770) | 2159 | if (sd->ctrls[EXPOSURE].val > 0x1770) |
2363 | return; | 2160 | return; |
2364 | 2161 | ||
2365 | new_exp = sd->exposure + sd->exposure_step; | 2162 | new_exp = sd->ctrls[EXPOSURE].val + sd->exposure_step; |
2366 | if (new_exp > 0x1770) | 2163 | if (new_exp > 0x1770) |
2367 | new_exp = 0x1770; | 2164 | new_exp = 0x1770; |
2368 | if (new_exp < 0x10) | 2165 | if (new_exp < 0x10) |
2369 | new_exp = 0x10; | 2166 | new_exp = 0x10; |
2370 | sd->exposure = new_exp; | 2167 | sd->ctrls[EXPOSURE].val = new_exp; |
2371 | set_exposure(gspca_dev); | 2168 | set_exposure(gspca_dev); |
2372 | 2169 | ||
2373 | sd->older_step = sd->old_step; | 2170 | sd->older_step = sd->old_step; |
@@ -2379,14 +2176,14 @@ static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum) | |||
2379 | sd->exposure_step += 2; | 2176 | sd->exposure_step += 2; |
2380 | } | 2177 | } |
2381 | if (avg_lum > MAX_AVG_LUM) { | 2178 | if (avg_lum > MAX_AVG_LUM) { |
2382 | if (sd->exposure < 0x10) | 2179 | if (sd->ctrls[EXPOSURE].val < 0x10) |
2383 | return; | 2180 | return; |
2384 | new_exp = sd->exposure - sd->exposure_step; | 2181 | new_exp = sd->ctrls[EXPOSURE].val - sd->exposure_step; |
2385 | if (new_exp > 0x1700) | 2182 | if (new_exp > 0x1700) |
2386 | new_exp = 0x1770; | 2183 | new_exp = 0x1770; |
2387 | if (new_exp < 0x10) | 2184 | if (new_exp < 0x10) |
2388 | new_exp = 0x10; | 2185 | new_exp = 0x10; |
2389 | sd->exposure = new_exp; | 2186 | sd->ctrls[EXPOSURE].val = new_exp; |
2390 | set_exposure(gspca_dev); | 2187 | set_exposure(gspca_dev); |
2391 | sd->older_step = sd->old_step; | 2188 | sd->older_step = sd->old_step; |
2392 | sd->old_step = 0; | 2189 | sd->old_step = 0; |
@@ -2403,14 +2200,14 @@ static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum) | |||
2403 | struct sd *sd = (struct sd *) gspca_dev; | 2200 | struct sd *sd = (struct sd *) gspca_dev; |
2404 | 2201 | ||
2405 | if (avg_lum < MIN_AVG_LUM) { | 2202 | if (avg_lum < MIN_AVG_LUM) { |
2406 | if (sd->gain + 1 <= 28) { | 2203 | if (sd->ctrls[GAIN].val + 1 <= 28) { |
2407 | sd->gain++; | 2204 | sd->ctrls[GAIN].val++; |
2408 | set_gain(gspca_dev); | 2205 | set_gain(gspca_dev); |
2409 | } | 2206 | } |
2410 | } | 2207 | } |
2411 | if (avg_lum > MAX_AVG_LUM) { | 2208 | if (avg_lum > MAX_AVG_LUM) { |
2412 | if (sd->gain > 0) { | 2209 | if (sd->ctrls[GAIN].val > 0) { |
2413 | sd->gain--; | 2210 | sd->ctrls[GAIN].val--; |
2414 | set_gain(gspca_dev); | 2211 | set_gain(gspca_dev); |
2415 | } | 2212 | } |
2416 | } | 2213 | } |
@@ -2421,7 +2218,7 @@ static void sd_dqcallback(struct gspca_dev *gspca_dev) | |||
2421 | struct sd *sd = (struct sd *) gspca_dev; | 2218 | struct sd *sd = (struct sd *) gspca_dev; |
2422 | int avg_lum; | 2219 | int avg_lum; |
2423 | 2220 | ||
2424 | if (!sd->auto_exposure) | 2221 | if (!sd->ctrls[AUTOGAIN].val) |
2425 | return; | 2222 | return; |
2426 | 2223 | ||
2427 | avg_lum = atomic_read(&sd->avg_lum); | 2224 | avg_lum = atomic_read(&sd->avg_lum); |
@@ -2431,33 +2228,92 @@ static void sd_dqcallback(struct gspca_dev *gspca_dev) | |||
2431 | do_autoexposure(gspca_dev, avg_lum); | 2228 | do_autoexposure(gspca_dev, avg_lum); |
2432 | } | 2229 | } |
2433 | 2230 | ||
2231 | /* JPEG quality update */ | ||
2232 | /* This function is executed from a work queue. */ | ||
2233 | static void qual_upd(struct work_struct *work) | ||
2234 | { | ||
2235 | struct sd *sd = container_of(work, struct sd, work); | ||
2236 | struct gspca_dev *gspca_dev = &sd->gspca_dev; | ||
2237 | |||
2238 | mutex_lock(&gspca_dev->usb_lock); | ||
2239 | PDEBUG(D_STREAM, "qual_upd %d%%", sd->ctrls[QUALITY].val); | ||
2240 | set_quality(gspca_dev); | ||
2241 | mutex_unlock(&gspca_dev->usb_lock); | ||
2242 | } | ||
2243 | |||
2434 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) | 2244 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) |
2435 | static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, | 2245 | static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, |
2436 | u8 *data, /* interrupt packet */ | 2246 | u8 *data, /* interrupt packet */ |
2437 | int len) /* interrupt packet length */ | 2247 | int len) /* interrupt packet length */ |
2438 | { | 2248 | { |
2439 | struct sd *sd = (struct sd *) gspca_dev; | 2249 | struct sd *sd = (struct sd *) gspca_dev; |
2440 | int ret = -EINVAL; | 2250 | |
2441 | if (!(sd->flags & HAS_NO_BUTTON) && len == 1) { | 2251 | if (!(sd->flags & HAS_NO_BUTTON) && len == 1) { |
2442 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); | 2252 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); |
2443 | input_sync(gspca_dev->input_dev); | 2253 | input_sync(gspca_dev->input_dev); |
2444 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); | 2254 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); |
2445 | input_sync(gspca_dev->input_dev); | 2255 | input_sync(gspca_dev->input_dev); |
2446 | ret = 0; | 2256 | return 0; |
2447 | } | 2257 | } |
2448 | return ret; | 2258 | return -EINVAL; |
2449 | } | 2259 | } |
2450 | #endif | 2260 | #endif |
2451 | 2261 | ||
2262 | /* check the JPEG compression */ | ||
2263 | static void transfer_check(struct gspca_dev *gspca_dev, | ||
2264 | u8 *data) | ||
2265 | { | ||
2266 | struct sd *sd = (struct sd *) gspca_dev; | ||
2267 | int new_qual, r; | ||
2268 | |||
2269 | new_qual = 0; | ||
2270 | |||
2271 | /* if USB error, discard the frame and decrease the quality */ | ||
2272 | if (data[6] & 0x08) { /* USB FIFO full */ | ||
2273 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
2274 | new_qual = -5; | ||
2275 | } else { | ||
2276 | |||
2277 | /* else, compute the filling rate and a new JPEG quality */ | ||
2278 | r = (sd->pktsz * 100) / | ||
2279 | (sd->npkt * | ||
2280 | gspca_dev->urb[0]->iso_frame_desc[0].length); | ||
2281 | if (r >= 85) | ||
2282 | new_qual = -3; | ||
2283 | else if (r < 75) | ||
2284 | new_qual = 2; | ||
2285 | } | ||
2286 | if (new_qual != 0) { | ||
2287 | sd->nchg += new_qual; | ||
2288 | if (sd->nchg < -6 || sd->nchg >= 12) { | ||
2289 | sd->nchg = 0; | ||
2290 | new_qual += sd->ctrls[QUALITY].val; | ||
2291 | if (new_qual < QUALITY_MIN) | ||
2292 | new_qual = QUALITY_MIN; | ||
2293 | else if (new_qual > QUALITY_MAX) | ||
2294 | new_qual = QUALITY_MAX; | ||
2295 | if (new_qual != sd->ctrls[QUALITY].val) { | ||
2296 | sd->ctrls[QUALITY].val = new_qual; | ||
2297 | queue_work(sd->work_thread, &sd->work); | ||
2298 | } | ||
2299 | } | ||
2300 | } else { | ||
2301 | sd->nchg = 0; | ||
2302 | } | ||
2303 | sd->pktsz = sd->npkt = 0; | ||
2304 | } | ||
2305 | |||
2452 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 2306 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
2453 | u8 *data, /* isoc packet */ | 2307 | u8 *data, /* isoc packet */ |
2454 | int len) /* iso packet length */ | 2308 | int len) /* iso packet length */ |
2455 | { | 2309 | { |
2456 | struct sd *sd = (struct sd *) gspca_dev; | 2310 | struct sd *sd = (struct sd *) gspca_dev; |
2457 | int avg_lum; | 2311 | int avg_lum, is_jpeg; |
2458 | static u8 frame_header[] = | 2312 | static u8 frame_header[] = |
2459 | {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96}; | 2313 | {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96}; |
2460 | if (len == 64 && memcmp(data, frame_header, 6) == 0) { | 2314 | |
2315 | is_jpeg = (sd->fmt & 0x03) == 0; | ||
2316 | if (len >= 64 && memcmp(data, frame_header, 6) == 0) { | ||
2461 | avg_lum = ((data[35] >> 2) & 3) | | 2317 | avg_lum = ((data[35] >> 2) & 3) | |
2462 | (data[20] << 2) | | 2318 | (data[20] << 2) | |
2463 | (data[19] << 10); | 2319 | (data[19] << 10); |
@@ -2484,12 +2340,18 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
2484 | (data[33] << 10); | 2340 | (data[33] << 10); |
2485 | avg_lum >>= 9; | 2341 | avg_lum >>= 9; |
2486 | atomic_set(&sd->avg_lum, avg_lum); | 2342 | atomic_set(&sd->avg_lum, avg_lum); |
2343 | |||
2344 | if (is_jpeg) | ||
2345 | transfer_check(gspca_dev, data); | ||
2346 | |||
2487 | gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); | 2347 | gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); |
2488 | return; | 2348 | len -= 64; |
2349 | if (len == 0) | ||
2350 | return; | ||
2351 | data += 64; | ||
2489 | } | 2352 | } |
2490 | if (gspca_dev->last_packet_type == LAST_PACKET) { | 2353 | if (gspca_dev->last_packet_type == LAST_PACKET) { |
2491 | if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv | 2354 | if (is_jpeg) { |
2492 | & MODE_JPEG) { | ||
2493 | gspca_frame_add(gspca_dev, FIRST_PACKET, | 2355 | gspca_frame_add(gspca_dev, FIRST_PACKET, |
2494 | sd->jpeg_hdr, JPEG_HDR_SZ); | 2356 | sd->jpeg_hdr, JPEG_HDR_SZ); |
2495 | gspca_frame_add(gspca_dev, INTER_PACKET, | 2357 | gspca_frame_add(gspca_dev, INTER_PACKET, |
@@ -2499,13 +2361,18 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
2499 | data, len); | 2361 | data, len); |
2500 | } | 2362 | } |
2501 | } else { | 2363 | } else { |
2364 | /* if JPEG, count the packets and their size */ | ||
2365 | if (is_jpeg) { | ||
2366 | sd->npkt++; | ||
2367 | sd->pktsz += len; | ||
2368 | } | ||
2502 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | 2369 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
2503 | } | 2370 | } |
2504 | } | 2371 | } |
2505 | 2372 | ||
2506 | /* sub-driver description */ | 2373 | /* sub-driver description */ |
2507 | static const struct sd_desc sd_desc = { | 2374 | static const struct sd_desc sd_desc = { |
2508 | .name = MODULE_NAME, | 2375 | .name = KBUILD_MODNAME, |
2509 | .ctrls = sd_ctrls, | 2376 | .ctrls = sd_ctrls, |
2510 | .nctrls = ARRAY_SIZE(sd_ctrls), | 2377 | .nctrls = ARRAY_SIZE(sd_ctrls), |
2511 | .config = sd_config, | 2378 | .config = sd_config, |
@@ -2513,6 +2380,7 @@ static const struct sd_desc sd_desc = { | |||
2513 | .isoc_init = sd_isoc_init, | 2380 | .isoc_init = sd_isoc_init, |
2514 | .start = sd_start, | 2381 | .start = sd_start, |
2515 | .stopN = sd_stopN, | 2382 | .stopN = sd_stopN, |
2383 | .stop0 = sd_stop0, | ||
2516 | .pkt_scan = sd_pkt_scan, | 2384 | .pkt_scan = sd_pkt_scan, |
2517 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) | 2385 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) |
2518 | .int_pkt_scan = sd_int_pkt_scan, | 2386 | .int_pkt_scan = sd_int_pkt_scan, |
@@ -2581,7 +2449,7 @@ static int sd_probe(struct usb_interface *intf, | |||
2581 | } | 2449 | } |
2582 | 2450 | ||
2583 | static struct usb_driver sd_driver = { | 2451 | static struct usb_driver sd_driver = { |
2584 | .name = MODULE_NAME, | 2452 | .name = KBUILD_MODNAME, |
2585 | .id_table = device_table, | 2453 | .id_table = device_table, |
2586 | .probe = sd_probe, | 2454 | .probe = sd_probe, |
2587 | .disconnect = gspca_disconnect, | 2455 | .disconnect = gspca_disconnect, |
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 0c9e6ddabd2c..db8e5084df06 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c | |||
@@ -39,7 +39,9 @@ enum e_ctrl { | |||
39 | BLUE, | 39 | BLUE, |
40 | RED, | 40 | RED, |
41 | GAMMA, | 41 | GAMMA, |
42 | EXPOSURE, | ||
42 | AUTOGAIN, | 43 | AUTOGAIN, |
44 | GAIN, | ||
43 | HFLIP, | 45 | HFLIP, |
44 | VFLIP, | 46 | VFLIP, |
45 | SHARPNESS, | 47 | SHARPNESS, |
@@ -131,7 +133,9 @@ static void setcontrast(struct gspca_dev *gspca_dev); | |||
131 | static void setcolors(struct gspca_dev *gspca_dev); | 133 | static void setcolors(struct gspca_dev *gspca_dev); |
132 | static void setredblue(struct gspca_dev *gspca_dev); | 134 | static void setredblue(struct gspca_dev *gspca_dev); |
133 | static void setgamma(struct gspca_dev *gspca_dev); | 135 | static void setgamma(struct gspca_dev *gspca_dev); |
134 | static void setautogain(struct gspca_dev *gspca_dev); | 136 | static void setexposure(struct gspca_dev *gspca_dev); |
137 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
138 | static void setgain(struct gspca_dev *gspca_dev); | ||
135 | static void sethvflip(struct gspca_dev *gspca_dev); | 139 | static void sethvflip(struct gspca_dev *gspca_dev); |
136 | static void setsharpness(struct gspca_dev *gspca_dev); | 140 | static void setsharpness(struct gspca_dev *gspca_dev); |
137 | static void setillum(struct gspca_dev *gspca_dev); | 141 | static void setillum(struct gspca_dev *gspca_dev); |
@@ -213,6 +217,18 @@ static const struct ctrl sd_ctrls[NCTRLS] = { | |||
213 | }, | 217 | }, |
214 | .set_control = setgamma | 218 | .set_control = setgamma |
215 | }, | 219 | }, |
220 | [EXPOSURE] = { | ||
221 | { | ||
222 | .id = V4L2_CID_EXPOSURE, | ||
223 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
224 | .name = "Exposure", | ||
225 | .minimum = 500, | ||
226 | .maximum = 1500, | ||
227 | .step = 1, | ||
228 | .default_value = 1024 | ||
229 | }, | ||
230 | .set_control = setexposure | ||
231 | }, | ||
216 | [AUTOGAIN] = { | 232 | [AUTOGAIN] = { |
217 | { | 233 | { |
218 | .id = V4L2_CID_AUTOGAIN, | 234 | .id = V4L2_CID_AUTOGAIN, |
@@ -223,7 +239,19 @@ static const struct ctrl sd_ctrls[NCTRLS] = { | |||
223 | .step = 1, | 239 | .step = 1, |
224 | .default_value = 1 | 240 | .default_value = 1 |
225 | }, | 241 | }, |
226 | .set_control = setautogain | 242 | .set = sd_setautogain, |
243 | }, | ||
244 | [GAIN] = { | ||
245 | { | ||
246 | .id = V4L2_CID_GAIN, | ||
247 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
248 | .name = "Gain", | ||
249 | .minimum = 4, | ||
250 | .maximum = 49, | ||
251 | .step = 1, | ||
252 | .default_value = 15 | ||
253 | }, | ||
254 | .set_control = setgain | ||
227 | }, | 255 | }, |
228 | [HFLIP] = { | 256 | [HFLIP] = { |
229 | { | 257 | { |
@@ -290,60 +318,87 @@ static const struct ctrl sd_ctrls[NCTRLS] = { | |||
290 | 318 | ||
291 | /* table of the disabled controls */ | 319 | /* table of the disabled controls */ |
292 | static const __u32 ctrl_dis[] = { | 320 | static const __u32 ctrl_dis[] = { |
293 | [SENSOR_ADCM1700] = (1 << AUTOGAIN) | | 321 | [SENSOR_ADCM1700] = (1 << EXPOSURE) | |
322 | (1 << AUTOGAIN) | | ||
323 | (1 << GAIN) | | ||
294 | (1 << HFLIP) | | 324 | (1 << HFLIP) | |
295 | (1 << VFLIP) | | 325 | (1 << VFLIP) | |
296 | (1 << FREQ), | 326 | (1 << FREQ), |
297 | 327 | ||
298 | [SENSOR_GC0307] = (1 << HFLIP) | | 328 | [SENSOR_GC0307] = (1 << EXPOSURE) | |
329 | (1 << GAIN) | | ||
330 | (1 << HFLIP) | | ||
299 | (1 << VFLIP) | | 331 | (1 << VFLIP) | |
300 | (1 << FREQ), | 332 | (1 << FREQ), |
301 | 333 | ||
302 | [SENSOR_HV7131R] = (1 << HFLIP) | | 334 | [SENSOR_HV7131R] = (1 << EXPOSURE) | |
335 | (1 << GAIN) | | ||
336 | (1 << HFLIP) | | ||
303 | (1 << FREQ), | 337 | (1 << FREQ), |
304 | 338 | ||
305 | [SENSOR_MI0360] = (1 << HFLIP) | | 339 | [SENSOR_MI0360] = (1 << EXPOSURE) | |
340 | (1 << GAIN) | | ||
341 | (1 << HFLIP) | | ||
306 | (1 << VFLIP) | | 342 | (1 << VFLIP) | |
307 | (1 << FREQ), | 343 | (1 << FREQ), |
308 | 344 | ||
309 | [SENSOR_MI0360B] = (1 << HFLIP) | | 345 | [SENSOR_MI0360B] = (1 << EXPOSURE) | |
346 | (1 << GAIN) | | ||
347 | (1 << HFLIP) | | ||
310 | (1 << VFLIP) | | 348 | (1 << VFLIP) | |
311 | (1 << FREQ), | 349 | (1 << FREQ), |
312 | 350 | ||
313 | [SENSOR_MO4000] = (1 << HFLIP) | | 351 | [SENSOR_MO4000] = (1 << EXPOSURE) | |
352 | (1 << GAIN) | | ||
353 | (1 << HFLIP) | | ||
314 | (1 << VFLIP) | | 354 | (1 << VFLIP) | |
315 | (1 << FREQ), | 355 | (1 << FREQ), |
316 | 356 | ||
317 | [SENSOR_MT9V111] = (1 << HFLIP) | | 357 | [SENSOR_MT9V111] = (1 << EXPOSURE) | |
358 | (1 << GAIN) | | ||
359 | (1 << HFLIP) | | ||
318 | (1 << VFLIP) | | 360 | (1 << VFLIP) | |
319 | (1 << FREQ), | 361 | (1 << FREQ), |
320 | 362 | ||
321 | [SENSOR_OM6802] = (1 << HFLIP) | | 363 | [SENSOR_OM6802] = (1 << EXPOSURE) | |
364 | (1 << GAIN) | | ||
365 | (1 << HFLIP) | | ||
322 | (1 << VFLIP) | | 366 | (1 << VFLIP) | |
323 | (1 << FREQ), | 367 | (1 << FREQ), |
324 | 368 | ||
325 | [SENSOR_OV7630] = (1 << HFLIP), | 369 | [SENSOR_OV7630] = (1 << EXPOSURE) | |
370 | (1 << GAIN) | | ||
371 | (1 << HFLIP), | ||
326 | 372 | ||
327 | [SENSOR_OV7648] = (1 << HFLIP), | 373 | [SENSOR_OV7648] = (1 << EXPOSURE) | |
374 | (1 << GAIN) | | ||
375 | (1 << HFLIP), | ||
328 | 376 | ||
329 | [SENSOR_OV7660] = (1 << AUTOGAIN) | | 377 | [SENSOR_OV7660] = (1 << EXPOSURE) | |
378 | (1 << AUTOGAIN) | | ||
379 | (1 << GAIN) | | ||
330 | (1 << HFLIP) | | 380 | (1 << HFLIP) | |
331 | (1 << VFLIP), | 381 | (1 << VFLIP), |
332 | 382 | ||
333 | [SENSOR_PO1030] = (1 << AUTOGAIN) | | 383 | [SENSOR_PO1030] = (1 << EXPOSURE) | |
384 | (1 << AUTOGAIN) | | ||
385 | (1 << GAIN) | | ||
334 | (1 << HFLIP) | | 386 | (1 << HFLIP) | |
335 | (1 << VFLIP) | | 387 | (1 << VFLIP) | |
336 | (1 << FREQ), | 388 | (1 << FREQ), |
337 | 389 | ||
338 | [SENSOR_PO2030N] = (1 << AUTOGAIN) | | 390 | [SENSOR_PO2030N] = (1 << FREQ), |
339 | (1 << FREQ), | ||
340 | 391 | ||
341 | [SENSOR_SOI768] = (1 << AUTOGAIN) | | 392 | [SENSOR_SOI768] = (1 << EXPOSURE) | |
393 | (1 << AUTOGAIN) | | ||
394 | (1 << GAIN) | | ||
342 | (1 << HFLIP) | | 395 | (1 << HFLIP) | |
343 | (1 << VFLIP) | | 396 | (1 << VFLIP) | |
344 | (1 << FREQ), | 397 | (1 << FREQ), |
345 | 398 | ||
346 | [SENSOR_SP80708] = (1 << AUTOGAIN) | | 399 | [SENSOR_SP80708] = (1 << EXPOSURE) | |
400 | (1 << AUTOGAIN) | | ||
401 | (1 << GAIN) | | ||
347 | (1 << HFLIP) | | 402 | (1 << HFLIP) | |
348 | (1 << VFLIP) | | 403 | (1 << VFLIP) | |
349 | (1 << FREQ), | 404 | (1 << FREQ), |
@@ -1242,14 +1297,6 @@ static const u8 po2030n_sensor_param1[][8] = { | |||
1242 | {0xa1, 0x6e, 0x05, 0x6f, 0x00, 0x00, 0x00, 0x10}, | 1297 | {0xa1, 0x6e, 0x05, 0x6f, 0x00, 0x00, 0x00, 0x10}, |
1243 | {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10}, | 1298 | {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10}, |
1244 | {0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10}, | 1299 | {0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10}, |
1245 | {0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10}, | ||
1246 | {0xc1, 0x6e, 0x16, 0x52, 0x40, 0x48, 0x00, 0x10}, | ||
1247 | /*after start*/ | ||
1248 | {0xa1, 0x6e, 0x15, 0x0f, 0x00, 0x00, 0x00, 0x10}, | ||
1249 | {DELAY, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 5ms */ | ||
1250 | {0xa1, 0x6e, 0x1a, 0x05, 0x00, 0x00, 0x00, 0x10}, | ||
1251 | {DELAY, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 5ms */ | ||
1252 | {0xa1, 0x6e, 0x1b, 0x53, 0x00, 0x00, 0x00, 0x10}, | ||
1253 | {} | 1300 | {} |
1254 | }; | 1301 | }; |
1255 | 1302 | ||
@@ -1858,7 +1905,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1858 | return gspca_dev->usb_err; | 1905 | return gspca_dev->usb_err; |
1859 | } | 1906 | } |
1860 | 1907 | ||
1861 | static u32 setexposure(struct gspca_dev *gspca_dev, | 1908 | static u32 expo_adjust(struct gspca_dev *gspca_dev, |
1862 | u32 expo) | 1909 | u32 expo) |
1863 | { | 1910 | { |
1864 | struct sd *sd = (struct sd *) gspca_dev; | 1911 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -1982,28 +2029,28 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
1982 | expo = 0x002dc6c0; | 2029 | expo = 0x002dc6c0; |
1983 | else if (expo < 0x02a0) | 2030 | else if (expo < 0x02a0) |
1984 | expo = 0x02a0; | 2031 | expo = 0x02a0; |
1985 | sd->exposure = setexposure(gspca_dev, expo); | 2032 | sd->exposure = expo_adjust(gspca_dev, expo); |
1986 | break; | 2033 | break; |
1987 | case SENSOR_MI0360: | 2034 | case SENSOR_MI0360: |
1988 | case SENSOR_MO4000: | 2035 | case SENSOR_MO4000: |
1989 | expo = brightness << 4; | 2036 | expo = brightness << 4; |
1990 | sd->exposure = setexposure(gspca_dev, expo); | 2037 | sd->exposure = expo_adjust(gspca_dev, expo); |
1991 | break; | 2038 | break; |
1992 | case SENSOR_MI0360B: | 2039 | case SENSOR_MI0360B: |
1993 | expo = brightness << 2; | 2040 | expo = brightness << 2; |
1994 | sd->exposure = setexposure(gspca_dev, expo); | 2041 | sd->exposure = expo_adjust(gspca_dev, expo); |
1995 | break; | 2042 | break; |
1996 | case SENSOR_GC0307: | 2043 | case SENSOR_GC0307: |
1997 | expo = brightness; | 2044 | expo = brightness; |
1998 | sd->exposure = setexposure(gspca_dev, expo); | 2045 | sd->exposure = expo_adjust(gspca_dev, expo); |
1999 | return; /* don't set the Y offset */ | 2046 | return; /* don't set the Y offset */ |
2000 | case SENSOR_MT9V111: | 2047 | case SENSOR_MT9V111: |
2001 | expo = brightness << 2; | 2048 | expo = brightness << 2; |
2002 | sd->exposure = setexposure(gspca_dev, expo); | 2049 | sd->exposure = expo_adjust(gspca_dev, expo); |
2003 | return; /* don't set the Y offset */ | 2050 | return; /* don't set the Y offset */ |
2004 | case SENSOR_OM6802: | 2051 | case SENSOR_OM6802: |
2005 | expo = brightness << 2; | 2052 | expo = brightness << 2; |
2006 | sd->exposure = setexposure(gspca_dev, expo); | 2053 | sd->exposure = expo_adjust(gspca_dev, expo); |
2007 | return; /* Y offset already set */ | 2054 | return; /* Y offset already set */ |
2008 | } | 2055 | } |
2009 | 2056 | ||
@@ -2112,6 +2159,23 @@ static void setgamma(struct gspca_dev *gspca_dev) | |||
2112 | reg_w(gspca_dev, 0x20, gamma, sizeof gamma); | 2159 | reg_w(gspca_dev, 0x20, gamma, sizeof gamma); |
2113 | } | 2160 | } |
2114 | 2161 | ||
2162 | static void setexposure(struct gspca_dev *gspca_dev) | ||
2163 | { | ||
2164 | struct sd *sd = (struct sd *) gspca_dev; | ||
2165 | |||
2166 | if (sd->sensor == SENSOR_PO2030N) { | ||
2167 | u8 rexpo[] = /* 1a: expo H, 1b: expo M */ | ||
2168 | {0xa1, 0x6e, 0x1a, 0x00, 0x40, 0x00, 0x00, 0x10}; | ||
2169 | |||
2170 | rexpo[3] = sd->ctrls[EXPOSURE].val >> 8; | ||
2171 | i2c_w8(gspca_dev, rexpo); | ||
2172 | msleep(6); | ||
2173 | rexpo[2] = 0x1b; | ||
2174 | rexpo[3] = sd->ctrls[EXPOSURE].val; | ||
2175 | i2c_w8(gspca_dev, rexpo); | ||
2176 | } | ||
2177 | } | ||
2178 | |||
2115 | static void setautogain(struct gspca_dev *gspca_dev) | 2179 | static void setautogain(struct gspca_dev *gspca_dev) |
2116 | { | 2180 | { |
2117 | struct sd *sd = (struct sd *) gspca_dev; | 2181 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -2139,6 +2203,19 @@ static void setautogain(struct gspca_dev *gspca_dev) | |||
2139 | sd->ag_cnt = -1; | 2203 | sd->ag_cnt = -1; |
2140 | } | 2204 | } |
2141 | 2205 | ||
2206 | static void setgain(struct gspca_dev *gspca_dev) | ||
2207 | { | ||
2208 | struct sd *sd = (struct sd *) gspca_dev; | ||
2209 | |||
2210 | if (sd->sensor == SENSOR_PO2030N) { | ||
2211 | u8 rgain[] = /* 15: gain */ | ||
2212 | {0xa1, 0x6e, 0x15, 0x00, 0x40, 0x00, 0x00, 0x15}; | ||
2213 | |||
2214 | rgain[3] = sd->ctrls[GAIN].val; | ||
2215 | i2c_w8(gspca_dev, rgain); | ||
2216 | } | ||
2217 | } | ||
2218 | |||
2142 | static void sethvflip(struct gspca_dev *gspca_dev) | 2219 | static void sethvflip(struct gspca_dev *gspca_dev) |
2143 | { | 2220 | { |
2144 | struct sd *sd = (struct sd *) gspca_dev; | 2221 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -2623,6 +2700,10 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2623 | setcontrast(gspca_dev); | 2700 | setcontrast(gspca_dev); |
2624 | setcolors(gspca_dev); | 2701 | setcolors(gspca_dev); |
2625 | setautogain(gspca_dev); | 2702 | setautogain(gspca_dev); |
2703 | if (!(gspca_dev->ctrl_inac & ((1 << EXPOSURE) | (1 << GAIN)))) { | ||
2704 | setexposure(gspca_dev); | ||
2705 | setgain(gspca_dev); | ||
2706 | } | ||
2626 | setfreq(gspca_dev); | 2707 | setfreq(gspca_dev); |
2627 | 2708 | ||
2628 | sd->pktsz = sd->npkt = 0; | 2709 | sd->pktsz = sd->npkt = 0; |
@@ -2719,6 +2800,12 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
2719 | } | 2800 | } |
2720 | } | 2801 | } |
2721 | 2802 | ||
2803 | /* !! coarse_grained_expo_autogain is not used !! */ | ||
2804 | #define exp_too_low_cnt bridge | ||
2805 | #define exp_too_high_cnt sensor | ||
2806 | |||
2807 | #include "autogain_functions.h" | ||
2808 | |||
2722 | static void do_autogain(struct gspca_dev *gspca_dev) | 2809 | static void do_autogain(struct gspca_dev *gspca_dev) |
2723 | { | 2810 | { |
2724 | struct sd *sd = (struct sd *) gspca_dev; | 2811 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -2736,6 +2823,13 @@ static void do_autogain(struct gspca_dev *gspca_dev) | |||
2736 | 2823 | ||
2737 | delta = atomic_read(&sd->avg_lum); | 2824 | delta = atomic_read(&sd->avg_lum); |
2738 | PDEBUG(D_FRAM, "mean lum %d", delta); | 2825 | PDEBUG(D_FRAM, "mean lum %d", delta); |
2826 | |||
2827 | if (sd->sensor == SENSOR_PO2030N) { | ||
2828 | auto_gain_n_exposure(gspca_dev, delta, luma_mean, luma_delta, | ||
2829 | 15, 1024); | ||
2830 | return; | ||
2831 | } | ||
2832 | |||
2739 | if (delta < luma_mean - luma_delta || | 2833 | if (delta < luma_mean - luma_delta || |
2740 | delta > luma_mean + luma_delta) { | 2834 | delta > luma_mean + luma_delta) { |
2741 | switch (sd->sensor) { | 2835 | switch (sd->sensor) { |
@@ -2744,7 +2838,7 @@ static void do_autogain(struct gspca_dev *gspca_dev) | |||
2744 | expotimes += (luma_mean - delta) >> 6; | 2838 | expotimes += (luma_mean - delta) >> 6; |
2745 | if (expotimes < 0) | 2839 | if (expotimes < 0) |
2746 | expotimes = 0; | 2840 | expotimes = 0; |
2747 | sd->exposure = setexposure(gspca_dev, | 2841 | sd->exposure = expo_adjust(gspca_dev, |
2748 | (unsigned int) expotimes); | 2842 | (unsigned int) expotimes); |
2749 | break; | 2843 | break; |
2750 | case SENSOR_HV7131R: | 2844 | case SENSOR_HV7131R: |
@@ -2752,7 +2846,7 @@ static void do_autogain(struct gspca_dev *gspca_dev) | |||
2752 | expotimes += (luma_mean - delta) >> 4; | 2846 | expotimes += (luma_mean - delta) >> 4; |
2753 | if (expotimes < 0) | 2847 | if (expotimes < 0) |
2754 | expotimes = 0; | 2848 | expotimes = 0; |
2755 | sd->exposure = setexposure(gspca_dev, | 2849 | sd->exposure = expo_adjust(gspca_dev, |
2756 | (unsigned int) (expotimes << 8)); | 2850 | (unsigned int) (expotimes << 8)); |
2757 | break; | 2851 | break; |
2758 | case SENSOR_OM6802: | 2852 | case SENSOR_OM6802: |
@@ -2761,7 +2855,7 @@ static void do_autogain(struct gspca_dev *gspca_dev) | |||
2761 | expotimes += (luma_mean - delta) >> 2; | 2855 | expotimes += (luma_mean - delta) >> 2; |
2762 | if (expotimes < 0) | 2856 | if (expotimes < 0) |
2763 | expotimes = 0; | 2857 | expotimes = 0; |
2764 | sd->exposure = setexposure(gspca_dev, | 2858 | sd->exposure = expo_adjust(gspca_dev, |
2765 | (unsigned int) expotimes); | 2859 | (unsigned int) expotimes); |
2766 | setredblue(gspca_dev); | 2860 | setredblue(gspca_dev); |
2767 | break; | 2861 | break; |
@@ -2773,7 +2867,7 @@ static void do_autogain(struct gspca_dev *gspca_dev) | |||
2773 | expotimes += (luma_mean - delta) >> 6; | 2867 | expotimes += (luma_mean - delta) >> 6; |
2774 | if (expotimes < 0) | 2868 | if (expotimes < 0) |
2775 | expotimes = 0; | 2869 | expotimes = 0; |
2776 | sd->exposure = setexposure(gspca_dev, | 2870 | sd->exposure = expo_adjust(gspca_dev, |
2777 | (unsigned int) expotimes); | 2871 | (unsigned int) expotimes); |
2778 | setredblue(gspca_dev); | 2872 | setredblue(gspca_dev); |
2779 | break; | 2873 | break; |
@@ -2948,16 +3042,18 @@ marker_found: | |||
2948 | } | 3042 | } |
2949 | } | 3043 | } |
2950 | 3044 | ||
2951 | static int sd_get_jcomp(struct gspca_dev *gspca_dev, | 3045 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) |
2952 | struct v4l2_jpegcompression *jcomp) | ||
2953 | { | 3046 | { |
2954 | struct sd *sd = (struct sd *) gspca_dev; | 3047 | struct sd *sd = (struct sd *) gspca_dev; |
2955 | 3048 | ||
2956 | memset(jcomp, 0, sizeof *jcomp); | 3049 | sd->ctrls[AUTOGAIN].val = val; |
2957 | jcomp->quality = sd->quality; | 3050 | if (val) |
2958 | jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT | 3051 | gspca_dev->ctrl_inac |= (1 << EXPOSURE) | (1 << GAIN); |
2959 | | V4L2_JPEG_MARKER_DQT; | 3052 | else |
2960 | return 0; | 3053 | gspca_dev->ctrl_inac &= ~(1 << EXPOSURE) & ~(1 << GAIN); |
3054 | if (gspca_dev->streaming) | ||
3055 | setautogain(gspca_dev); | ||
3056 | return gspca_dev->usb_err; | ||
2961 | } | 3057 | } |
2962 | 3058 | ||
2963 | static int sd_querymenu(struct gspca_dev *gspca_dev, | 3059 | static int sd_querymenu(struct gspca_dev *gspca_dev, |
@@ -3012,7 +3108,6 @@ static const struct sd_desc sd_desc = { | |||
3012 | .stop0 = sd_stop0, | 3108 | .stop0 = sd_stop0, |
3013 | .pkt_scan = sd_pkt_scan, | 3109 | .pkt_scan = sd_pkt_scan, |
3014 | .dq_callback = do_autogain, | 3110 | .dq_callback = do_autogain, |
3015 | .get_jcomp = sd_get_jcomp, | ||
3016 | .querymenu = sd_querymenu, | 3111 | .querymenu = sd_querymenu, |
3017 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) | 3112 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) |
3018 | .int_pkt_scan = sd_int_pkt_scan, | 3113 | .int_pkt_scan = sd_int_pkt_scan, |
diff --git a/drivers/media/video/gspca/stv06xx/Makefile b/drivers/media/video/gspca/stv06xx/Makefile index 5b318faf9aa8..38bc41061d83 100644 --- a/drivers/media/video/gspca/stv06xx/Makefile +++ b/drivers/media/video/gspca/stv06xx/Makefile | |||
@@ -6,5 +6,5 @@ gspca_stv06xx-objs := stv06xx.o \ | |||
6 | stv06xx_pb0100.o \ | 6 | stv06xx_pb0100.o \ |
7 | stv06xx_st6422.o | 7 | stv06xx_st6422.o |
8 | 8 | ||
9 | ccflags-y += -Idrivers/media/video/gspca | 9 | ccflags-y += -I$(srctree)/drivers/media/video/gspca |
10 | 10 | ||
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index b9e15bb0328b..7d9a4f1be9dc 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Z-Star/Vimicro zc301/zc302p/vc30x library | 2 | * Z-Star/Vimicro zc301/zc302p/vc30x driver |
3 | * | 3 | * |
4 | * Copyright (C) 2009-2011 Jean-Francois Moine <http://moinejf.free.fr> | 4 | * Copyright (C) 2009-2012 Jean-Francois Moine <http://moinejf.free.fr> |
5 | * Copyright (C) 2004 2005 2006 Michel Xhaard mxhaard@magic.fr | 5 | * Copyright (C) 2004 2005 2006 Michel Xhaard mxhaard@magic.fr |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -21,8 +21,6 @@ | |||
21 | 21 | ||
22 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 22 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
23 | 23 | ||
24 | #define MODULE_NAME "zc3xx" | ||
25 | |||
26 | #include <linux/input.h> | 24 | #include <linux/input.h> |
27 | #include "gspca.h" | 25 | #include "gspca.h" |
28 | #include "jpeg.h" | 26 | #include "jpeg.h" |
@@ -34,7 +32,7 @@ MODULE_LICENSE("GPL"); | |||
34 | 32 | ||
35 | static int force_sensor = -1; | 33 | static int force_sensor = -1; |
36 | 34 | ||
37 | #define QUANT_VAL 1 /* quantization table */ | 35 | #define REG08_DEF 3 /* default JPEG compression (70%) */ |
38 | #include "zc3xx-reg.h" | 36 | #include "zc3xx-reg.h" |
39 | 37 | ||
40 | /* controls */ | 38 | /* controls */ |
@@ -46,6 +44,7 @@ enum e_ctrl { | |||
46 | AUTOGAIN, | 44 | AUTOGAIN, |
47 | LIGHTFREQ, | 45 | LIGHTFREQ, |
48 | SHARPNESS, | 46 | SHARPNESS, |
47 | QUALITY, | ||
49 | NCTRLS /* number of controls */ | 48 | NCTRLS /* number of controls */ |
50 | }; | 49 | }; |
51 | 50 | ||
@@ -57,10 +56,10 @@ struct sd { | |||
57 | 56 | ||
58 | struct gspca_ctrl ctrls[NCTRLS]; | 57 | struct gspca_ctrl ctrls[NCTRLS]; |
59 | 58 | ||
60 | u8 quality; /* image quality */ | 59 | struct work_struct work; |
61 | #define QUALITY_MIN 50 | 60 | struct workqueue_struct *work_thread; |
62 | #define QUALITY_MAX 80 | 61 | |
63 | #define QUALITY_DEF 70 | 62 | u8 reg08; /* webcam compression quality */ |
64 | 63 | ||
65 | u8 bridge; | 64 | u8 bridge; |
66 | u8 sensor; /* Type of image sensor chip */ | 65 | u8 sensor; /* Type of image sensor chip */ |
@@ -101,6 +100,7 @@ static void setexposure(struct gspca_dev *gspca_dev); | |||
101 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | 100 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); |
102 | static void setlightfreq(struct gspca_dev *gspca_dev); | 101 | static void setlightfreq(struct gspca_dev *gspca_dev); |
103 | static void setsharpness(struct gspca_dev *gspca_dev); | 102 | static void setsharpness(struct gspca_dev *gspca_dev); |
103 | static int sd_setquality(struct gspca_dev *gspca_dev, __s32 val); | ||
104 | 104 | ||
105 | static const struct ctrl sd_ctrls[NCTRLS] = { | 105 | static const struct ctrl sd_ctrls[NCTRLS] = { |
106 | [BRIGHTNESS] = { | 106 | [BRIGHTNESS] = { |
@@ -188,6 +188,18 @@ static const struct ctrl sd_ctrls[NCTRLS] = { | |||
188 | }, | 188 | }, |
189 | .set_control = setsharpness | 189 | .set_control = setsharpness |
190 | }, | 190 | }, |
191 | [QUALITY] = { | ||
192 | { | ||
193 | .id = V4L2_CID_JPEG_COMPRESSION_QUALITY, | ||
194 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
195 | .name = "Compression Quality", | ||
196 | .minimum = 40, | ||
197 | .maximum = 70, | ||
198 | .step = 1, | ||
199 | .default_value = 70 /* updated in sd_init() */ | ||
200 | }, | ||
201 | .set = sd_setquality | ||
202 | }, | ||
191 | }; | 203 | }; |
192 | 204 | ||
193 | static const struct v4l2_pix_format vga_mode[] = { | 205 | static const struct v4l2_pix_format vga_mode[] = { |
@@ -229,6 +241,9 @@ static const struct v4l2_pix_format sif_mode[] = { | |||
229 | .priv = 0}, | 241 | .priv = 0}, |
230 | }; | 242 | }; |
231 | 243 | ||
244 | /* bridge reg08 -> JPEG quality conversion table */ | ||
245 | static u8 jpeg_qual[] = {40, 50, 60, 70, /*80*/}; | ||
246 | |||
232 | /* usb exchanges */ | 247 | /* usb exchanges */ |
233 | struct usb_action { | 248 | struct usb_action { |
234 | u8 req; | 249 | u8 req; |
@@ -3894,7 +3909,6 @@ static const struct usb_action pas106b_Initial[] = { /* 352x288 */ | |||
3894 | /* Gains */ | 3909 | /* Gains */ |
3895 | {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF}, | 3910 | {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF}, |
3896 | {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, | 3911 | {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, |
3897 | {0xa0, 0xa0, ZC3XX_R11D_GLOBALGAIN}, | ||
3898 | {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, | 3912 | {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, |
3899 | /* Auto correction */ | 3913 | /* Auto correction */ |
3900 | {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, | 3914 | {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, |
@@ -5640,7 +5654,7 @@ static const struct usb_action gc0303_NoFlikerScale[] = { | |||
5640 | {} | 5654 | {} |
5641 | }; | 5655 | }; |
5642 | 5656 | ||
5643 | static u8 reg_r_i(struct gspca_dev *gspca_dev, | 5657 | static u8 reg_r(struct gspca_dev *gspca_dev, |
5644 | u16 index) | 5658 | u16 index) |
5645 | { | 5659 | { |
5646 | int ret; | 5660 | int ret; |
@@ -5655,24 +5669,14 @@ static u8 reg_r_i(struct gspca_dev *gspca_dev, | |||
5655 | index, gspca_dev->usb_buf, 1, | 5669 | index, gspca_dev->usb_buf, 1, |
5656 | 500); | 5670 | 500); |
5657 | if (ret < 0) { | 5671 | if (ret < 0) { |
5658 | pr_err("reg_r_i err %d\n", ret); | 5672 | pr_err("reg_r err %d\n", ret); |
5659 | gspca_dev->usb_err = ret; | 5673 | gspca_dev->usb_err = ret; |
5660 | return 0; | 5674 | return 0; |
5661 | } | 5675 | } |
5662 | return gspca_dev->usb_buf[0]; | 5676 | return gspca_dev->usb_buf[0]; |
5663 | } | 5677 | } |
5664 | 5678 | ||
5665 | static u8 reg_r(struct gspca_dev *gspca_dev, | 5679 | static void reg_w(struct gspca_dev *gspca_dev, |
5666 | u16 index) | ||
5667 | { | ||
5668 | u8 ret; | ||
5669 | |||
5670 | ret = reg_r_i(gspca_dev, index); | ||
5671 | PDEBUG(D_USBI, "reg r [%04x] -> %02x", index, ret); | ||
5672 | return ret; | ||
5673 | } | ||
5674 | |||
5675 | static void reg_w_i(struct gspca_dev *gspca_dev, | ||
5676 | u8 value, | 5680 | u8 value, |
5677 | u16 index) | 5681 | u16 index) |
5678 | { | 5682 | { |
@@ -5692,14 +5696,6 @@ static void reg_w_i(struct gspca_dev *gspca_dev, | |||
5692 | } | 5696 | } |
5693 | } | 5697 | } |
5694 | 5698 | ||
5695 | static void reg_w(struct gspca_dev *gspca_dev, | ||
5696 | u8 value, | ||
5697 | u16 index) | ||
5698 | { | ||
5699 | PDEBUG(D_USBO, "reg w [%04x] = %02x", index, value); | ||
5700 | reg_w_i(gspca_dev, value, index); | ||
5701 | } | ||
5702 | |||
5703 | static u16 i2c_read(struct gspca_dev *gspca_dev, | 5699 | static u16 i2c_read(struct gspca_dev *gspca_dev, |
5704 | u8 reg) | 5700 | u8 reg) |
5705 | { | 5701 | { |
@@ -5708,16 +5704,14 @@ static u16 i2c_read(struct gspca_dev *gspca_dev, | |||
5708 | 5704 | ||
5709 | if (gspca_dev->usb_err < 0) | 5705 | if (gspca_dev->usb_err < 0) |
5710 | return 0; | 5706 | return 0; |
5711 | reg_w_i(gspca_dev, reg, 0x0092); | 5707 | reg_w(gspca_dev, reg, 0x0092); |
5712 | reg_w_i(gspca_dev, 0x02, 0x0090); /* <- read command */ | 5708 | reg_w(gspca_dev, 0x02, 0x0090); /* <- read command */ |
5713 | msleep(20); | 5709 | msleep(20); |
5714 | retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */ | 5710 | retbyte = reg_r(gspca_dev, 0x0091); /* read status */ |
5715 | if (retbyte != 0x00) | 5711 | if (retbyte != 0x00) |
5716 | pr_err("i2c_r status error %02x\n", retbyte); | 5712 | pr_err("i2c_r status error %02x\n", retbyte); |
5717 | retval = reg_r_i(gspca_dev, 0x0095); /* read Lowbyte */ | 5713 | retval = reg_r(gspca_dev, 0x0095); /* read Lowbyte */ |
5718 | retval |= reg_r_i(gspca_dev, 0x0096) << 8; /* read Hightbyte */ | 5714 | retval |= reg_r(gspca_dev, 0x0096) << 8; /* read Hightbyte */ |
5719 | PDEBUG(D_USBI, "i2c r [%02x] -> %04x (%02x)", | ||
5720 | reg, retval, retbyte); | ||
5721 | return retval; | 5715 | return retval; |
5722 | } | 5716 | } |
5723 | 5717 | ||
@@ -5730,16 +5724,14 @@ static u8 i2c_write(struct gspca_dev *gspca_dev, | |||
5730 | 5724 | ||
5731 | if (gspca_dev->usb_err < 0) | 5725 | if (gspca_dev->usb_err < 0) |
5732 | return 0; | 5726 | return 0; |
5733 | reg_w_i(gspca_dev, reg, 0x92); | 5727 | reg_w(gspca_dev, reg, 0x92); |
5734 | reg_w_i(gspca_dev, valL, 0x93); | 5728 | reg_w(gspca_dev, valL, 0x93); |
5735 | reg_w_i(gspca_dev, valH, 0x94); | 5729 | reg_w(gspca_dev, valH, 0x94); |
5736 | reg_w_i(gspca_dev, 0x01, 0x90); /* <- write command */ | 5730 | reg_w(gspca_dev, 0x01, 0x90); /* <- write command */ |
5737 | msleep(1); | 5731 | msleep(1); |
5738 | retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */ | 5732 | retbyte = reg_r(gspca_dev, 0x0091); /* read status */ |
5739 | if (retbyte != 0x00) | 5733 | if (retbyte != 0x00) |
5740 | pr_err("i2c_w status error %02x\n", retbyte); | 5734 | pr_err("i2c_w status error %02x\n", retbyte); |
5741 | PDEBUG(D_USBO, "i2c w [%02x] = %02x%02x (%02x)", | ||
5742 | reg, valH, valL, retbyte); | ||
5743 | return retbyte; | 5735 | return retbyte; |
5744 | } | 5736 | } |
5745 | 5737 | ||
@@ -5906,6 +5898,8 @@ static void getexposure(struct gspca_dev *gspca_dev) | |||
5906 | { | 5898 | { |
5907 | struct sd *sd = (struct sd *) gspca_dev; | 5899 | struct sd *sd = (struct sd *) gspca_dev; |
5908 | 5900 | ||
5901 | if (sd->sensor != SENSOR_HV7131R) | ||
5902 | return; | ||
5909 | sd->ctrls[EXPOSURE].val = (i2c_read(gspca_dev, 0x25) << 9) | 5903 | sd->ctrls[EXPOSURE].val = (i2c_read(gspca_dev, 0x25) << 9) |
5910 | | (i2c_read(gspca_dev, 0x26) << 1) | 5904 | | (i2c_read(gspca_dev, 0x26) << 1) |
5911 | | (i2c_read(gspca_dev, 0x27) >> 7); | 5905 | | (i2c_read(gspca_dev, 0x27) >> 7); |
@@ -5916,6 +5910,8 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
5916 | struct sd *sd = (struct sd *) gspca_dev; | 5910 | struct sd *sd = (struct sd *) gspca_dev; |
5917 | int val; | 5911 | int val; |
5918 | 5912 | ||
5913 | if (sd->sensor != SENSOR_HV7131R) | ||
5914 | return; | ||
5919 | val = sd->ctrls[EXPOSURE].val; | 5915 | val = sd->ctrls[EXPOSURE].val; |
5920 | i2c_write(gspca_dev, 0x25, val >> 9, 0x00); | 5916 | i2c_write(gspca_dev, 0x25, val >> 9, 0x00); |
5921 | i2c_write(gspca_dev, 0x26, val >> 1, 0x00); | 5917 | i2c_write(gspca_dev, 0x26, val >> 1, 0x00); |
@@ -5925,32 +5921,20 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
5925 | static void setquality(struct gspca_dev *gspca_dev) | 5921 | static void setquality(struct gspca_dev *gspca_dev) |
5926 | { | 5922 | { |
5927 | struct sd *sd = (struct sd *) gspca_dev; | 5923 | struct sd *sd = (struct sd *) gspca_dev; |
5928 | u8 frxt; | 5924 | s8 reg07; |
5929 | 5925 | ||
5926 | reg07 = 0; | ||
5930 | switch (sd->sensor) { | 5927 | switch (sd->sensor) { |
5931 | case SENSOR_ADCM2700: | ||
5932 | case SENSOR_GC0305: | ||
5933 | case SENSOR_HV7131B: | ||
5934 | case SENSOR_HV7131R: | ||
5935 | case SENSOR_OV7620: | 5928 | case SENSOR_OV7620: |
5929 | reg07 = 0x30; | ||
5930 | break; | ||
5931 | case SENSOR_HV7131R: | ||
5936 | case SENSOR_PAS202B: | 5932 | case SENSOR_PAS202B: |
5937 | case SENSOR_PO2030: | 5933 | return; /* done by work queue */ |
5938 | return; | ||
5939 | } | 5934 | } |
5940 | /*fixme: is it really 0008 0007 0018 for all other sensors? */ | 5935 | reg_w(gspca_dev, sd->reg08, ZC3XX_R008_CLOCKSETTING); |
5941 | reg_w(gspca_dev, QUANT_VAL, 0x0008); | 5936 | if (reg07 != 0) |
5942 | frxt = 0x30; | 5937 | reg_w(gspca_dev, reg07, 0x0007); |
5943 | reg_w(gspca_dev, frxt, 0x0007); | ||
5944 | #if QUANT_VAL == 0 || QUANT_VAL == 1 || QUANT_VAL == 2 | ||
5945 | frxt = 0xff; | ||
5946 | #elif QUANT_VAL == 3 | ||
5947 | frxt = 0xf0; | ||
5948 | #elif QUANT_VAL == 4 | ||
5949 | frxt = 0xe0; | ||
5950 | #else | ||
5951 | frxt = 0x20; | ||
5952 | #endif | ||
5953 | reg_w(gspca_dev, frxt, 0x0018); | ||
5954 | } | 5938 | } |
5955 | 5939 | ||
5956 | /* Matches the sensor's internal frame rate to the lighting frequency. | 5940 | /* Matches the sensor's internal frame rate to the lighting frequency. |
@@ -6084,6 +6068,115 @@ static void setautogain(struct gspca_dev *gspca_dev) | |||
6084 | reg_w(gspca_dev, autoval, 0x0180); | 6068 | reg_w(gspca_dev, autoval, 0x0180); |
6085 | } | 6069 | } |
6086 | 6070 | ||
6071 | /* update the transfer parameters */ | ||
6072 | /* This function is executed from a work queue. */ | ||
6073 | /* The exact use of the bridge registers 07 and 08 is not known. | ||
6074 | * The following algorithm has been adapted from ms-win traces */ | ||
6075 | static void transfer_update(struct work_struct *work) | ||
6076 | { | ||
6077 | struct sd *sd = container_of(work, struct sd, work); | ||
6078 | struct gspca_dev *gspca_dev = &sd->gspca_dev; | ||
6079 | int change, good; | ||
6080 | u8 reg07, reg11; | ||
6081 | |||
6082 | /* synchronize with the main driver and initialize the registers */ | ||
6083 | mutex_lock(&gspca_dev->usb_lock); | ||
6084 | reg07 = 0; /* max */ | ||
6085 | reg_w(gspca_dev, reg07, 0x0007); | ||
6086 | reg_w(gspca_dev, sd->reg08, ZC3XX_R008_CLOCKSETTING); | ||
6087 | mutex_unlock(&gspca_dev->usb_lock); | ||
6088 | |||
6089 | good = 0; | ||
6090 | for (;;) { | ||
6091 | msleep(100); | ||
6092 | |||
6093 | /* get the transfer status */ | ||
6094 | /* the bit 0 of the bridge register 11 indicates overflow */ | ||
6095 | mutex_lock(&gspca_dev->usb_lock); | ||
6096 | if (!gspca_dev->present || !gspca_dev->streaming) | ||
6097 | goto err; | ||
6098 | reg11 = reg_r(gspca_dev, 0x0011); | ||
6099 | if (gspca_dev->usb_err < 0 | ||
6100 | || !gspca_dev->present || !gspca_dev->streaming) | ||
6101 | goto err; | ||
6102 | |||
6103 | change = reg11 & 0x01; | ||
6104 | if (change) { /* overflow */ | ||
6105 | switch (reg07) { | ||
6106 | case 0: /* max */ | ||
6107 | reg07 = sd->sensor == SENSOR_HV7131R | ||
6108 | ? 0x30 : 0x32; | ||
6109 | if (sd->reg08 != 0) { | ||
6110 | change = 3; | ||
6111 | sd->reg08--; | ||
6112 | } | ||
6113 | break; | ||
6114 | case 0x32: | ||
6115 | reg07 -= 4; | ||
6116 | break; | ||
6117 | default: | ||
6118 | reg07 -= 2; | ||
6119 | break; | ||
6120 | case 2: | ||
6121 | change = 0; /* already min */ | ||
6122 | break; | ||
6123 | } | ||
6124 | good = 0; | ||
6125 | } else { /* no overflow */ | ||
6126 | if (reg07 != 0) { /* if not max */ | ||
6127 | good++; | ||
6128 | if (good >= 10) { | ||
6129 | good = 0; | ||
6130 | change = 1; | ||
6131 | reg07 += 2; | ||
6132 | switch (reg07) { | ||
6133 | case 0x30: | ||
6134 | if (sd->sensor == SENSOR_PAS202B) | ||
6135 | reg07 += 2; | ||
6136 | break; | ||
6137 | case 0x32: | ||
6138 | case 0x34: | ||
6139 | reg07 = 0; | ||
6140 | break; | ||
6141 | } | ||
6142 | } | ||
6143 | } else { /* reg07 max */ | ||
6144 | if (sd->reg08 < sizeof jpeg_qual - 1) { | ||
6145 | good++; | ||
6146 | if (good > 10) { | ||
6147 | sd->reg08++; | ||
6148 | change = 2; | ||
6149 | } | ||
6150 | } | ||
6151 | } | ||
6152 | } | ||
6153 | if (change) { | ||
6154 | if (change & 1) { | ||
6155 | reg_w(gspca_dev, reg07, 0x0007); | ||
6156 | if (gspca_dev->usb_err < 0 | ||
6157 | || !gspca_dev->present | ||
6158 | || !gspca_dev->streaming) | ||
6159 | goto err; | ||
6160 | } | ||
6161 | if (change & 2) { | ||
6162 | reg_w(gspca_dev, sd->reg08, | ||
6163 | ZC3XX_R008_CLOCKSETTING); | ||
6164 | if (gspca_dev->usb_err < 0 | ||
6165 | || !gspca_dev->present | ||
6166 | || !gspca_dev->streaming) | ||
6167 | goto err; | ||
6168 | sd->ctrls[QUALITY].val = jpeg_qual[sd->reg08]; | ||
6169 | jpeg_set_qual(sd->jpeg_hdr, | ||
6170 | jpeg_qual[sd->reg08]); | ||
6171 | } | ||
6172 | } | ||
6173 | mutex_unlock(&gspca_dev->usb_lock); | ||
6174 | } | ||
6175 | return; | ||
6176 | err: | ||
6177 | mutex_unlock(&gspca_dev->usb_lock); | ||
6178 | } | ||
6179 | |||
6087 | static void send_unknown(struct gspca_dev *gspca_dev, int sensor) | 6180 | static void send_unknown(struct gspca_dev *gspca_dev, int sensor) |
6088 | { | 6181 | { |
6089 | reg_w(gspca_dev, 0x01, 0x0000); /* bridge reset */ | 6182 | reg_w(gspca_dev, 0x01, 0x0000); /* bridge reset */ |
@@ -6411,7 +6504,9 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
6411 | sd->sensor = id->driver_info; | 6504 | sd->sensor = id->driver_info; |
6412 | 6505 | ||
6413 | gspca_dev->cam.ctrls = sd->ctrls; | 6506 | gspca_dev->cam.ctrls = sd->ctrls; |
6414 | sd->quality = QUALITY_DEF; | 6507 | sd->reg08 = REG08_DEF; |
6508 | |||
6509 | INIT_WORK(&sd->work, transfer_update); | ||
6415 | 6510 | ||
6416 | return 0; | 6511 | return 0; |
6417 | } | 6512 | } |
@@ -6464,6 +6559,27 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
6464 | [SENSOR_PO2030] = 1, | 6559 | [SENSOR_PO2030] = 1, |
6465 | [SENSOR_TAS5130C] = 1, | 6560 | [SENSOR_TAS5130C] = 1, |
6466 | }; | 6561 | }; |
6562 | static const u8 reg08_tb[SENSOR_MAX] = { | ||
6563 | [SENSOR_ADCM2700] = 1, | ||
6564 | [SENSOR_CS2102] = 3, | ||
6565 | [SENSOR_CS2102K] = 3, | ||
6566 | [SENSOR_GC0303] = 2, | ||
6567 | [SENSOR_GC0305] = 3, | ||
6568 | [SENSOR_HDCS2020] = 1, | ||
6569 | [SENSOR_HV7131B] = 3, | ||
6570 | [SENSOR_HV7131R] = 3, | ||
6571 | [SENSOR_ICM105A] = 3, | ||
6572 | [SENSOR_MC501CB] = 3, | ||
6573 | [SENSOR_MT9V111_1] = 3, | ||
6574 | [SENSOR_MT9V111_3] = 3, | ||
6575 | [SENSOR_OV7620] = 1, | ||
6576 | [SENSOR_OV7630C] = 3, | ||
6577 | [SENSOR_PAS106] = 3, | ||
6578 | [SENSOR_PAS202B] = 3, | ||
6579 | [SENSOR_PB0330] = 3, | ||
6580 | [SENSOR_PO2030] = 2, | ||
6581 | [SENSOR_TAS5130C] = 3, | ||
6582 | }; | ||
6467 | 6583 | ||
6468 | sensor = zcxx_probeSensor(gspca_dev); | 6584 | sensor = zcxx_probeSensor(gspca_dev); |
6469 | if (sensor >= 0) | 6585 | if (sensor >= 0) |
@@ -6528,7 +6644,6 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
6528 | case 0x0e: | 6644 | case 0x0e: |
6529 | PDEBUG(D_PROBE, "Find Sensor PAS202B"); | 6645 | PDEBUG(D_PROBE, "Find Sensor PAS202B"); |
6530 | sd->sensor = SENSOR_PAS202B; | 6646 | sd->sensor = SENSOR_PAS202B; |
6531 | /* sd->sharpness = 1; */ | ||
6532 | break; | 6647 | break; |
6533 | case 0x0f: | 6648 | case 0x0f: |
6534 | PDEBUG(D_PROBE, "Find Sensor PAS106"); | 6649 | PDEBUG(D_PROBE, "Find Sensor PAS106"); |
@@ -6616,13 +6731,21 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
6616 | } | 6731 | } |
6617 | 6732 | ||
6618 | sd->ctrls[GAMMA].def = gamma[sd->sensor]; | 6733 | sd->ctrls[GAMMA].def = gamma[sd->sensor]; |
6734 | sd->reg08 = reg08_tb[sd->sensor]; | ||
6735 | sd->ctrls[QUALITY].def = jpeg_qual[sd->reg08]; | ||
6736 | sd->ctrls[QUALITY].min = jpeg_qual[0]; | ||
6737 | sd->ctrls[QUALITY].max = jpeg_qual[ARRAY_SIZE(jpeg_qual) - 1]; | ||
6619 | 6738 | ||
6620 | switch (sd->sensor) { | 6739 | switch (sd->sensor) { |
6621 | case SENSOR_HV7131R: | 6740 | case SENSOR_HV7131R: |
6741 | gspca_dev->ctrl_dis = (1 << QUALITY); | ||
6622 | break; | 6742 | break; |
6623 | case SENSOR_OV7630C: | 6743 | case SENSOR_OV7630C: |
6624 | gspca_dev->ctrl_dis = (1 << LIGHTFREQ) | (1 << EXPOSURE); | 6744 | gspca_dev->ctrl_dis = (1 << LIGHTFREQ) | (1 << EXPOSURE); |
6625 | break; | 6745 | break; |
6746 | case SENSOR_PAS202B: | ||
6747 | gspca_dev->ctrl_dis = (1 << QUALITY) | (1 << EXPOSURE); | ||
6748 | break; | ||
6626 | default: | 6749 | default: |
6627 | gspca_dev->ctrl_dis = (1 << EXPOSURE); | 6750 | gspca_dev->ctrl_dis = (1 << EXPOSURE); |
6628 | break; | 6751 | break; |
@@ -6685,7 +6808,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6685 | /* create the JPEG header */ | 6808 | /* create the JPEG header */ |
6686 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, | 6809 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, |
6687 | 0x21); /* JPEG 422 */ | 6810 | 0x21); /* JPEG 422 */ |
6688 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | ||
6689 | 6811 | ||
6690 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; | 6812 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; |
6691 | switch (sd->sensor) { | 6813 | switch (sd->sensor) { |
@@ -6761,10 +6883,9 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6761 | reg_r(gspca_dev, 0x0180); /* from win */ | 6883 | reg_r(gspca_dev, 0x0180); /* from win */ |
6762 | reg_w(gspca_dev, 0x00, 0x0180); | 6884 | reg_w(gspca_dev, 0x00, 0x0180); |
6763 | break; | 6885 | break; |
6764 | default: | ||
6765 | setquality(gspca_dev); | ||
6766 | break; | ||
6767 | } | 6886 | } |
6887 | setquality(gspca_dev); | ||
6888 | jpeg_set_qual(sd->jpeg_hdr, jpeg_qual[sd->reg08]); | ||
6768 | setlightfreq(gspca_dev); | 6889 | setlightfreq(gspca_dev); |
6769 | 6890 | ||
6770 | switch (sd->sensor) { | 6891 | switch (sd->sensor) { |
@@ -6776,8 +6897,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6776 | reg_w(gspca_dev, 0x40, 0x0117); | 6897 | reg_w(gspca_dev, 0x40, 0x0117); |
6777 | break; | 6898 | break; |
6778 | case SENSOR_HV7131R: | 6899 | case SENSOR_HV7131R: |
6779 | if (!sd->ctrls[AUTOGAIN].val) | 6900 | setexposure(gspca_dev); |
6780 | setexposure(gspca_dev); | ||
6781 | reg_w(gspca_dev, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN); | 6901 | reg_w(gspca_dev, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN); |
6782 | break; | 6902 | break; |
6783 | case SENSOR_GC0305: | 6903 | case SENSOR_GC0305: |
@@ -6802,13 +6922,19 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6802 | } | 6922 | } |
6803 | 6923 | ||
6804 | setautogain(gspca_dev); | 6924 | setautogain(gspca_dev); |
6805 | switch (sd->sensor) { | 6925 | |
6806 | case SENSOR_PO2030: | 6926 | /* start the transfer update thread if needed */ |
6807 | msleep(50); | 6927 | if (gspca_dev->usb_err >= 0) { |
6808 | reg_w(gspca_dev, 0x00, 0x0007); /* (from win traces) */ | 6928 | switch (sd->sensor) { |
6809 | reg_w(gspca_dev, 0x02, ZC3XX_R008_CLOCKSETTING); | 6929 | case SENSOR_HV7131R: |
6810 | break; | 6930 | case SENSOR_PAS202B: |
6931 | sd->work_thread = | ||
6932 | create_singlethread_workqueue(KBUILD_MODNAME); | ||
6933 | queue_work(sd->work_thread, &sd->work); | ||
6934 | break; | ||
6935 | } | ||
6811 | } | 6936 | } |
6937 | |||
6812 | return gspca_dev->usb_err; | 6938 | return gspca_dev->usb_err; |
6813 | } | 6939 | } |
6814 | 6940 | ||
@@ -6817,6 +6943,12 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
6817 | { | 6943 | { |
6818 | struct sd *sd = (struct sd *) gspca_dev; | 6944 | struct sd *sd = (struct sd *) gspca_dev; |
6819 | 6945 | ||
6946 | if (sd->work_thread != NULL) { | ||
6947 | mutex_unlock(&gspca_dev->usb_lock); | ||
6948 | destroy_workqueue(sd->work_thread); | ||
6949 | mutex_lock(&gspca_dev->usb_lock); | ||
6950 | sd->work_thread = NULL; | ||
6951 | } | ||
6820 | if (!gspca_dev->present) | 6952 | if (!gspca_dev->present) |
6821 | return; | 6953 | return; |
6822 | send_unknown(gspca_dev, sd->sensor); | 6954 | send_unknown(gspca_dev, sd->sensor); |
@@ -6893,19 +7025,33 @@ static int sd_querymenu(struct gspca_dev *gspca_dev, | |||
6893 | return -EINVAL; | 7025 | return -EINVAL; |
6894 | } | 7026 | } |
6895 | 7027 | ||
7028 | static int sd_setquality(struct gspca_dev *gspca_dev, __s32 val) | ||
7029 | { | ||
7030 | struct sd *sd = (struct sd *) gspca_dev; | ||
7031 | int i; | ||
7032 | |||
7033 | for (i = 0; i < ARRAY_SIZE(jpeg_qual) - 1; i++) { | ||
7034 | if (val <= jpeg_qual[i]) | ||
7035 | break; | ||
7036 | } | ||
7037 | if (i > 0 | ||
7038 | && i == sd->reg08 | ||
7039 | && val < jpeg_qual[sd->reg08]) | ||
7040 | i--; | ||
7041 | sd->reg08 = i; | ||
7042 | sd->ctrls[QUALITY].val = jpeg_qual[i]; | ||
7043 | if (gspca_dev->streaming) | ||
7044 | jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val); | ||
7045 | return gspca_dev->usb_err; | ||
7046 | } | ||
7047 | |||
6896 | static int sd_set_jcomp(struct gspca_dev *gspca_dev, | 7048 | static int sd_set_jcomp(struct gspca_dev *gspca_dev, |
6897 | struct v4l2_jpegcompression *jcomp) | 7049 | struct v4l2_jpegcompression *jcomp) |
6898 | { | 7050 | { |
6899 | struct sd *sd = (struct sd *) gspca_dev; | 7051 | struct sd *sd = (struct sd *) gspca_dev; |
6900 | 7052 | ||
6901 | if (jcomp->quality < QUALITY_MIN) | 7053 | sd_setquality(gspca_dev, jcomp->quality); |
6902 | sd->quality = QUALITY_MIN; | 7054 | jcomp->quality = sd->ctrls[QUALITY].val; |
6903 | else if (jcomp->quality > QUALITY_MAX) | ||
6904 | sd->quality = QUALITY_MAX; | ||
6905 | else | ||
6906 | sd->quality = jcomp->quality; | ||
6907 | if (gspca_dev->streaming) | ||
6908 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | ||
6909 | return gspca_dev->usb_err; | 7055 | return gspca_dev->usb_err; |
6910 | } | 7056 | } |
6911 | 7057 | ||
@@ -6915,7 +7061,7 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev, | |||
6915 | struct sd *sd = (struct sd *) gspca_dev; | 7061 | struct sd *sd = (struct sd *) gspca_dev; |
6916 | 7062 | ||
6917 | memset(jcomp, 0, sizeof *jcomp); | 7063 | memset(jcomp, 0, sizeof *jcomp); |
6918 | jcomp->quality = sd->quality; | 7064 | jcomp->quality = sd->ctrls[QUALITY].val; |
6919 | jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT | 7065 | jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT |
6920 | | V4L2_JPEG_MARKER_DQT; | 7066 | | V4L2_JPEG_MARKER_DQT; |
6921 | return 0; | 7067 | return 0; |
@@ -6938,7 +7084,7 @@ static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, | |||
6938 | #endif | 7084 | #endif |
6939 | 7085 | ||
6940 | static const struct sd_desc sd_desc = { | 7086 | static const struct sd_desc sd_desc = { |
6941 | .name = MODULE_NAME, | 7087 | .name = KBUILD_MODNAME, |
6942 | .ctrls = sd_ctrls, | 7088 | .ctrls = sd_ctrls, |
6943 | .nctrls = ARRAY_SIZE(sd_ctrls), | 7089 | .nctrls = ARRAY_SIZE(sd_ctrls), |
6944 | .config = sd_config, | 7090 | .config = sd_config, |
@@ -7023,7 +7169,7 @@ static int sd_probe(struct usb_interface *intf, | |||
7023 | 7169 | ||
7024 | /* USB driver */ | 7170 | /* USB driver */ |
7025 | static struct usb_driver sd_driver = { | 7171 | static struct usb_driver sd_driver = { |
7026 | .name = MODULE_NAME, | 7172 | .name = KBUILD_MODNAME, |
7027 | .id_table = device_table, | 7173 | .id_table = device_table, |
7028 | .probe = sd_probe, | 7174 | .probe = sd_probe, |
7029 | .disconnect = gspca_disconnect, | 7175 | .disconnect = gspca_disconnect, |
diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c index e5eb56a5b618..6510110f53d0 100644 --- a/drivers/media/video/hdpvr/hdpvr-core.c +++ b/drivers/media/video/hdpvr/hdpvr-core.c | |||
@@ -154,10 +154,20 @@ static int device_authorization(struct hdpvr_device *dev) | |||
154 | } | 154 | } |
155 | #endif | 155 | #endif |
156 | 156 | ||
157 | dev->fw_ver = dev->usbc_buf[1]; | ||
158 | |||
157 | v4l2_info(&dev->v4l2_dev, "firmware version 0x%x dated %s\n", | 159 | v4l2_info(&dev->v4l2_dev, "firmware version 0x%x dated %s\n", |
158 | dev->usbc_buf[1], &dev->usbc_buf[2]); | 160 | dev->fw_ver, &dev->usbc_buf[2]); |
161 | |||
162 | if (dev->fw_ver > 0x15) { | ||
163 | dev->options.brightness = 0x80; | ||
164 | dev->options.contrast = 0x40; | ||
165 | dev->options.hue = 0xf; | ||
166 | dev->options.saturation = 0x40; | ||
167 | dev->options.sharpness = 0x80; | ||
168 | } | ||
159 | 169 | ||
160 | switch (dev->usbc_buf[1]) { | 170 | switch (dev->fw_ver) { |
161 | case HDPVR_FIRMWARE_VERSION: | 171 | case HDPVR_FIRMWARE_VERSION: |
162 | dev->flags &= ~HDPVR_FLAG_AC3_CAP; | 172 | dev->flags &= ~HDPVR_FLAG_AC3_CAP; |
163 | break; | 173 | break; |
@@ -169,7 +179,7 @@ static int device_authorization(struct hdpvr_device *dev) | |||
169 | default: | 179 | default: |
170 | v4l2_info(&dev->v4l2_dev, "untested firmware, the driver might" | 180 | v4l2_info(&dev->v4l2_dev, "untested firmware, the driver might" |
171 | " not work.\n"); | 181 | " not work.\n"); |
172 | if (dev->usbc_buf[1] >= HDPVR_FIRMWARE_VERSION_AC3) | 182 | if (dev->fw_ver >= HDPVR_FIRMWARE_VERSION_AC3) |
173 | dev->flags |= HDPVR_FLAG_AC3_CAP; | 183 | dev->flags |= HDPVR_FLAG_AC3_CAP; |
174 | else | 184 | else |
175 | dev->flags &= ~HDPVR_FLAG_AC3_CAP; | 185 | dev->flags &= ~HDPVR_FLAG_AC3_CAP; |
@@ -270,6 +280,8 @@ static const struct hdpvr_options hdpvr_default_options = { | |||
270 | .bitrate_mode = HDPVR_CONSTANT, | 280 | .bitrate_mode = HDPVR_CONSTANT, |
271 | .gop_mode = HDPVR_SIMPLE_IDR_GOP, | 281 | .gop_mode = HDPVR_SIMPLE_IDR_GOP, |
272 | .audio_codec = V4L2_MPEG_AUDIO_ENCODING_AAC, | 282 | .audio_codec = V4L2_MPEG_AUDIO_ENCODING_AAC, |
283 | /* original picture controls for firmware version <= 0x15 */ | ||
284 | /* updated in device_authorization() for newer firmware */ | ||
273 | .brightness = 0x86, | 285 | .brightness = 0x86, |
274 | .contrast = 0x80, | 286 | .contrast = 0x80, |
275 | .hue = 0x80, | 287 | .hue = 0x80, |
diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c index 087f7c08cb85..11ffe9cc1780 100644 --- a/drivers/media/video/hdpvr/hdpvr-video.c +++ b/drivers/media/video/hdpvr/hdpvr-video.c | |||
@@ -283,12 +283,13 @@ static int hdpvr_start_streaming(struct hdpvr_device *dev) | |||
283 | 283 | ||
284 | hdpvr_config_call(dev, CTRL_START_STREAMING_VALUE, 0x00); | 284 | hdpvr_config_call(dev, CTRL_START_STREAMING_VALUE, 0x00); |
285 | 285 | ||
286 | dev->status = STATUS_STREAMING; | ||
287 | |||
286 | INIT_WORK(&dev->worker, hdpvr_transmit_buffers); | 288 | INIT_WORK(&dev->worker, hdpvr_transmit_buffers); |
287 | queue_work(dev->workqueue, &dev->worker); | 289 | queue_work(dev->workqueue, &dev->worker); |
288 | 290 | ||
289 | v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, | 291 | v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, |
290 | "streaming started\n"); | 292 | "streaming started\n"); |
291 | dev->status = STATUS_STREAMING; | ||
292 | 293 | ||
293 | return 0; | 294 | return 0; |
294 | } | 295 | } |
@@ -722,21 +723,39 @@ static const s32 supported_v4l2_ctrls[] = { | |||
722 | }; | 723 | }; |
723 | 724 | ||
724 | static int fill_queryctrl(struct hdpvr_options *opt, struct v4l2_queryctrl *qc, | 725 | static int fill_queryctrl(struct hdpvr_options *opt, struct v4l2_queryctrl *qc, |
725 | int ac3) | 726 | int ac3, int fw_ver) |
726 | { | 727 | { |
727 | int err; | 728 | int err; |
728 | 729 | ||
730 | if (fw_ver > 0x15) { | ||
731 | switch (qc->id) { | ||
732 | case V4L2_CID_BRIGHTNESS: | ||
733 | return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); | ||
734 | case V4L2_CID_CONTRAST: | ||
735 | return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x40); | ||
736 | case V4L2_CID_SATURATION: | ||
737 | return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x40); | ||
738 | case V4L2_CID_HUE: | ||
739 | return v4l2_ctrl_query_fill(qc, 0x0, 0x1e, 1, 0xf); | ||
740 | case V4L2_CID_SHARPNESS: | ||
741 | return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); | ||
742 | } | ||
743 | } else { | ||
744 | switch (qc->id) { | ||
745 | case V4L2_CID_BRIGHTNESS: | ||
746 | return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x86); | ||
747 | case V4L2_CID_CONTRAST: | ||
748 | return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); | ||
749 | case V4L2_CID_SATURATION: | ||
750 | return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); | ||
751 | case V4L2_CID_HUE: | ||
752 | return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); | ||
753 | case V4L2_CID_SHARPNESS: | ||
754 | return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); | ||
755 | } | ||
756 | } | ||
757 | |||
729 | switch (qc->id) { | 758 | switch (qc->id) { |
730 | case V4L2_CID_BRIGHTNESS: | ||
731 | return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x86); | ||
732 | case V4L2_CID_CONTRAST: | ||
733 | return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); | ||
734 | case V4L2_CID_SATURATION: | ||
735 | return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); | ||
736 | case V4L2_CID_HUE: | ||
737 | return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); | ||
738 | case V4L2_CID_SHARPNESS: | ||
739 | return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80); | ||
740 | case V4L2_CID_MPEG_AUDIO_ENCODING: | 759 | case V4L2_CID_MPEG_AUDIO_ENCODING: |
741 | return v4l2_ctrl_query_fill( | 760 | return v4l2_ctrl_query_fill( |
742 | qc, V4L2_MPEG_AUDIO_ENCODING_AAC, | 761 | qc, V4L2_MPEG_AUDIO_ENCODING_AAC, |
@@ -794,7 +813,8 @@ static int vidioc_queryctrl(struct file *file, void *private_data, | |||
794 | 813 | ||
795 | if (qc->id == supported_v4l2_ctrls[i]) | 814 | if (qc->id == supported_v4l2_ctrls[i]) |
796 | return fill_queryctrl(&dev->options, qc, | 815 | return fill_queryctrl(&dev->options, qc, |
797 | dev->flags & HDPVR_FLAG_AC3_CAP); | 816 | dev->flags & HDPVR_FLAG_AC3_CAP, |
817 | dev->fw_ver); | ||
798 | 818 | ||
799 | if (qc->id < supported_v4l2_ctrls[i]) | 819 | if (qc->id < supported_v4l2_ctrls[i]) |
800 | break; | 820 | break; |
diff --git a/drivers/media/video/hdpvr/hdpvr.h b/drivers/media/video/hdpvr/hdpvr.h index d6439db1d18b..fea3c6926997 100644 --- a/drivers/media/video/hdpvr/hdpvr.h +++ b/drivers/media/video/hdpvr/hdpvr.h | |||
@@ -113,6 +113,7 @@ struct hdpvr_device { | |||
113 | /* usb control transfer buffer and lock */ | 113 | /* usb control transfer buffer and lock */ |
114 | struct mutex usbc_mutex; | 114 | struct mutex usbc_mutex; |
115 | u8 *usbc_buf; | 115 | u8 *usbc_buf; |
116 | u8 fw_ver; | ||
116 | }; | 117 | }; |
117 | 118 | ||
118 | static inline struct hdpvr_device *to_hdpvr_dev(struct v4l2_device *v4l2_dev) | 119 | static inline struct hdpvr_device *to_hdpvr_dev(struct v4l2_device *v4l2_dev) |
diff --git a/drivers/media/video/imx074.c b/drivers/media/video/imx074.c index eec75bb57203..351e9bafe8fe 100644 --- a/drivers/media/video/imx074.c +++ b/drivers/media/video/imx074.c | |||
@@ -468,18 +468,7 @@ static struct i2c_driver imx074_i2c_driver = { | |||
468 | .id_table = imx074_id, | 468 | .id_table = imx074_id, |
469 | }; | 469 | }; |
470 | 470 | ||
471 | static int __init imx074_mod_init(void) | 471 | module_i2c_driver(imx074_i2c_driver); |
472 | { | ||
473 | return i2c_add_driver(&imx074_i2c_driver); | ||
474 | } | ||
475 | |||
476 | static void __exit imx074_mod_exit(void) | ||
477 | { | ||
478 | i2c_del_driver(&imx074_i2c_driver); | ||
479 | } | ||
480 | |||
481 | module_init(imx074_mod_init); | ||
482 | module_exit(imx074_mod_exit); | ||
483 | 472 | ||
484 | MODULE_DESCRIPTION("Sony IMX074 Camera driver"); | 473 | MODULE_DESCRIPTION("Sony IMX074 Camera driver"); |
485 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); | 474 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); |
diff --git a/drivers/media/video/indycam.c b/drivers/media/video/indycam.c index e5ed4db32e7b..548236333cce 100644 --- a/drivers/media/video/indycam.c +++ b/drivers/media/video/indycam.c | |||
@@ -387,15 +387,4 @@ static struct i2c_driver indycam_driver = { | |||
387 | .id_table = indycam_id, | 387 | .id_table = indycam_id, |
388 | }; | 388 | }; |
389 | 389 | ||
390 | static __init int init_indycam(void) | 390 | module_i2c_driver(indycam_driver); |
391 | { | ||
392 | return i2c_add_driver(&indycam_driver); | ||
393 | } | ||
394 | |||
395 | static __exit void exit_indycam(void) | ||
396 | { | ||
397 | i2c_del_driver(&indycam_driver); | ||
398 | } | ||
399 | |||
400 | module_init(init_indycam); | ||
401 | module_exit(exit_indycam); | ||
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index a7c41d32f414..04f192a0398a 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c | |||
@@ -471,7 +471,7 @@ static const struct i2c_device_id ir_kbd_id[] = { | |||
471 | { } | 471 | { } |
472 | }; | 472 | }; |
473 | 473 | ||
474 | static struct i2c_driver driver = { | 474 | static struct i2c_driver ir_kbd_driver = { |
475 | .driver = { | 475 | .driver = { |
476 | .name = "ir-kbd-i2c", | 476 | .name = "ir-kbd-i2c", |
477 | }, | 477 | }, |
@@ -480,21 +480,10 @@ static struct i2c_driver driver = { | |||
480 | .id_table = ir_kbd_id, | 480 | .id_table = ir_kbd_id, |
481 | }; | 481 | }; |
482 | 482 | ||
483 | module_i2c_driver(ir_kbd_driver); | ||
484 | |||
483 | /* ----------------------------------------------------------------------- */ | 485 | /* ----------------------------------------------------------------------- */ |
484 | 486 | ||
485 | MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, Ulrich Mueller"); | 487 | MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, Ulrich Mueller"); |
486 | MODULE_DESCRIPTION("input driver for i2c IR remote controls"); | 488 | MODULE_DESCRIPTION("input driver for i2c IR remote controls"); |
487 | MODULE_LICENSE("GPL"); | 489 | MODULE_LICENSE("GPL"); |
488 | |||
489 | static int __init ir_init(void) | ||
490 | { | ||
491 | return i2c_add_driver(&driver); | ||
492 | } | ||
493 | |||
494 | static void __exit ir_fini(void) | ||
495 | { | ||
496 | i2c_del_driver(&driver); | ||
497 | } | ||
498 | |||
499 | module_init(ir_init); | ||
500 | module_exit(ir_fini); | ||
diff --git a/drivers/media/video/ivtv/Makefile b/drivers/media/video/ivtv/Makefile index 71ab76a5ab26..77de8a45b46f 100644 --- a/drivers/media/video/ivtv/Makefile +++ b/drivers/media/video/ivtv/Makefile | |||
@@ -7,8 +7,8 @@ ivtv-objs := ivtv-routing.o ivtv-cards.o ivtv-controls.o \ | |||
7 | obj-$(CONFIG_VIDEO_IVTV) += ivtv.o | 7 | obj-$(CONFIG_VIDEO_IVTV) += ivtv.o |
8 | obj-$(CONFIG_VIDEO_FB_IVTV) += ivtvfb.o | 8 | obj-$(CONFIG_VIDEO_FB_IVTV) += ivtvfb.o |
9 | 9 | ||
10 | ccflags-y += -Idrivers/media/video | 10 | ccflags-y += -I$(srctree)/drivers/media/video |
11 | ccflags-y += -Idrivers/media/common/tuners | 11 | ccflags-y += -I$(srctree)/drivers/media/common/tuners |
12 | ccflags-y += -Idrivers/media/dvb/dvb-core | 12 | ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core |
13 | ccflags-y += -Idrivers/media/dvb/frontends | 13 | ccflags-y += -I$(srctree)/drivers/media/dvb/frontends |
14 | 14 | ||
diff --git a/drivers/media/video/ivtv/ivtv-controls.c b/drivers/media/video/ivtv/ivtv-controls.c index b31ee1bceef8..c60424601cb9 100644 --- a/drivers/media/video/ivtv/ivtv-controls.c +++ b/drivers/media/video/ivtv/ivtv-controls.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include "ivtv-driver.h" | 21 | #include "ivtv-driver.h" |
22 | #include "ivtv-ioctl.h" | 22 | #include "ivtv-ioctl.h" |
23 | #include "ivtv-controls.h" | 23 | #include "ivtv-controls.h" |
24 | #include "ivtv-mailbox.h" | ||
24 | 25 | ||
25 | static int ivtv_s_stream_vbi_fmt(struct cx2341x_handler *cxhdl, u32 fmt) | 26 | static int ivtv_s_stream_vbi_fmt(struct cx2341x_handler *cxhdl, u32 fmt) |
26 | { | 27 | { |
@@ -99,3 +100,64 @@ struct cx2341x_handler_ops ivtv_cxhdl_ops = { | |||
99 | .s_video_encoding = ivtv_s_video_encoding, | 100 | .s_video_encoding = ivtv_s_video_encoding, |
100 | .s_stream_vbi_fmt = ivtv_s_stream_vbi_fmt, | 101 | .s_stream_vbi_fmt = ivtv_s_stream_vbi_fmt, |
101 | }; | 102 | }; |
103 | |||
104 | int ivtv_g_pts_frame(struct ivtv *itv, s64 *pts, s64 *frame) | ||
105 | { | ||
106 | u32 data[CX2341X_MBOX_MAX_DATA]; | ||
107 | |||
108 | if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) { | ||
109 | *pts = (s64)((u64)itv->last_dec_timing[2] << 32) | | ||
110 | (u64)itv->last_dec_timing[1]; | ||
111 | *frame = itv->last_dec_timing[0]; | ||
112 | return 0; | ||
113 | } | ||
114 | *pts = 0; | ||
115 | *frame = 0; | ||
116 | if (atomic_read(&itv->decoding)) { | ||
117 | if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) { | ||
118 | IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n"); | ||
119 | return -EIO; | ||
120 | } | ||
121 | memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing)); | ||
122 | set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); | ||
123 | *pts = (s64)((u64) data[2] << 32) | (u64) data[1]; | ||
124 | *frame = data[0]; | ||
125 | /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/ | ||
126 | } | ||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | static int ivtv_g_volatile_ctrl(struct v4l2_ctrl *ctrl) | ||
131 | { | ||
132 | struct ivtv *itv = container_of(ctrl->handler, struct ivtv, cxhdl.hdl); | ||
133 | |||
134 | switch (ctrl->id) { | ||
135 | /* V4L2_CID_MPEG_VIDEO_DEC_PTS and V4L2_CID_MPEG_VIDEO_DEC_FRAME | ||
136 | control cluster */ | ||
137 | case V4L2_CID_MPEG_VIDEO_DEC_PTS: | ||
138 | return ivtv_g_pts_frame(itv, &itv->ctrl_pts->val64, | ||
139 | &itv->ctrl_frame->val64); | ||
140 | } | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static int ivtv_s_ctrl(struct v4l2_ctrl *ctrl) | ||
145 | { | ||
146 | struct ivtv *itv = container_of(ctrl->handler, struct ivtv, cxhdl.hdl); | ||
147 | |||
148 | switch (ctrl->id) { | ||
149 | /* V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK and MULTILINGUAL_PLAYBACK | ||
150 | control cluster */ | ||
151 | case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK: | ||
152 | itv->audio_stereo_mode = itv->ctrl_audio_playback->val - 1; | ||
153 | itv->audio_bilingual_mode = itv->ctrl_audio_multilingual_playback->val - 1; | ||
154 | ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); | ||
155 | break; | ||
156 | } | ||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | const struct v4l2_ctrl_ops ivtv_hdl_out_ops = { | ||
161 | .s_ctrl = ivtv_s_ctrl, | ||
162 | .g_volatile_ctrl = ivtv_g_volatile_ctrl, | ||
163 | }; | ||
diff --git a/drivers/media/video/ivtv/ivtv-controls.h b/drivers/media/video/ivtv/ivtv-controls.h index d12893dd0183..3999e6358312 100644 --- a/drivers/media/video/ivtv/ivtv-controls.h +++ b/drivers/media/video/ivtv/ivtv-controls.h | |||
@@ -22,5 +22,7 @@ | |||
22 | #define IVTV_CONTROLS_H | 22 | #define IVTV_CONTROLS_H |
23 | 23 | ||
24 | extern struct cx2341x_handler_ops ivtv_cxhdl_ops; | 24 | extern struct cx2341x_handler_ops ivtv_cxhdl_ops; |
25 | extern const struct v4l2_ctrl_ops ivtv_hdl_out_ops; | ||
26 | int ivtv_g_pts_frame(struct ivtv *itv, s64 *pts, s64 *frame); | ||
25 | 27 | ||
26 | #endif | 28 | #endif |
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 3949b7dc2368..679262ed13bc 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c | |||
@@ -55,7 +55,7 @@ | |||
55 | #include "ivtv-routing.h" | 55 | #include "ivtv-routing.h" |
56 | #include "ivtv-controls.h" | 56 | #include "ivtv-controls.h" |
57 | #include "ivtv-gpio.h" | 57 | #include "ivtv-gpio.h" |
58 | 58 | #include <linux/dma-mapping.h> | |
59 | #include <media/tveeprom.h> | 59 | #include <media/tveeprom.h> |
60 | #include <media/saa7115.h> | 60 | #include <media/saa7115.h> |
61 | #include <media/v4l2-chip-ident.h> | 61 | #include <media/v4l2-chip-ident.h> |
@@ -99,7 +99,7 @@ static int i2c_clock_period[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, | |||
99 | 99 | ||
100 | static unsigned int cardtype_c = 1; | 100 | static unsigned int cardtype_c = 1; |
101 | static unsigned int tuner_c = 1; | 101 | static unsigned int tuner_c = 1; |
102 | static bool radio_c = 1; | 102 | static int radio_c = 1; |
103 | static unsigned int i2c_clock_period_c = 1; | 103 | static unsigned int i2c_clock_period_c = 1; |
104 | static char pal[] = "---"; | 104 | static char pal[] = "---"; |
105 | static char secam[] = "--"; | 105 | static char secam[] = "--"; |
@@ -139,7 +139,7 @@ static int tunertype = -1; | |||
139 | static int newi2c = -1; | 139 | static int newi2c = -1; |
140 | 140 | ||
141 | module_param_array(tuner, int, &tuner_c, 0644); | 141 | module_param_array(tuner, int, &tuner_c, 0644); |
142 | module_param_array(radio, bool, &radio_c, 0644); | 142 | module_param_array(radio, int, &radio_c, 0644); |
143 | module_param_array(cardtype, int, &cardtype_c, 0644); | 143 | module_param_array(cardtype, int, &cardtype_c, 0644); |
144 | module_param_string(pal, pal, sizeof(pal), 0644); | 144 | module_param_string(pal, pal, sizeof(pal), 0644); |
145 | module_param_string(secam, secam, sizeof(secam), 0644); | 145 | module_param_string(secam, secam, sizeof(secam), 0644); |
@@ -744,8 +744,6 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv) | |||
744 | 744 | ||
745 | itv->cur_dma_stream = -1; | 745 | itv->cur_dma_stream = -1; |
746 | itv->cur_pio_stream = -1; | 746 | itv->cur_pio_stream = -1; |
747 | itv->audio_stereo_mode = AUDIO_STEREO; | ||
748 | itv->audio_bilingual_mode = AUDIO_MONO_LEFT; | ||
749 | 747 | ||
750 | /* Ctrls */ | 748 | /* Ctrls */ |
751 | itv->speed = 1000; | 749 | itv->speed = 1000; |
@@ -815,7 +813,7 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev, | |||
815 | IVTV_ERR("Can't enable device!\n"); | 813 | IVTV_ERR("Can't enable device!\n"); |
816 | return -EIO; | 814 | return -EIO; |
817 | } | 815 | } |
818 | if (pci_set_dma_mask(pdev, 0xffffffff)) { | 816 | if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { |
819 | IVTV_ERR("No suitable DMA available.\n"); | 817 | IVTV_ERR("No suitable DMA available.\n"); |
820 | return -EIO; | 818 | return -EIO; |
821 | } | 819 | } |
@@ -1200,6 +1198,32 @@ static int __devinit ivtv_probe(struct pci_dev *pdev, | |||
1200 | itv->tuner_std = itv->std; | 1198 | itv->tuner_std = itv->std; |
1201 | 1199 | ||
1202 | if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { | 1200 | if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { |
1201 | struct v4l2_ctrl_handler *hdl = itv->v4l2_dev.ctrl_handler; | ||
1202 | |||
1203 | itv->ctrl_pts = v4l2_ctrl_new_std(hdl, &ivtv_hdl_out_ops, | ||
1204 | V4L2_CID_MPEG_VIDEO_DEC_PTS, 0, 0, 1, 0); | ||
1205 | itv->ctrl_frame = v4l2_ctrl_new_std(hdl, &ivtv_hdl_out_ops, | ||
1206 | V4L2_CID_MPEG_VIDEO_DEC_FRAME, 0, 0x7fffffff, 1, 0); | ||
1207 | /* Note: V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO is not supported, | ||
1208 | mask that menu item. */ | ||
1209 | itv->ctrl_audio_playback = | ||
1210 | v4l2_ctrl_new_std_menu(hdl, &ivtv_hdl_out_ops, | ||
1211 | V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK, | ||
1212 | V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO, | ||
1213 | 1 << V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO, | ||
1214 | V4L2_MPEG_AUDIO_DEC_PLAYBACK_STEREO); | ||
1215 | itv->ctrl_audio_multilingual_playback = | ||
1216 | v4l2_ctrl_new_std_menu(hdl, &ivtv_hdl_out_ops, | ||
1217 | V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK, | ||
1218 | V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO, | ||
1219 | 1 << V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO, | ||
1220 | V4L2_MPEG_AUDIO_DEC_PLAYBACK_LEFT); | ||
1221 | if (hdl->error) { | ||
1222 | retval = hdl->error; | ||
1223 | goto free_i2c; | ||
1224 | } | ||
1225 | v4l2_ctrl_cluster(2, &itv->ctrl_pts); | ||
1226 | v4l2_ctrl_cluster(2, &itv->ctrl_audio_playback); | ||
1203 | ivtv_call_all(itv, video, s_std_output, itv->std); | 1227 | ivtv_call_all(itv, video, s_std_output, itv->std); |
1204 | /* Turn off the output signal. The mpeg decoder is not yet | 1228 | /* Turn off the output signal. The mpeg decoder is not yet |
1205 | active so without this you would get a green image until the | 1229 | active so without this you would get a green image until the |
@@ -1236,6 +1260,7 @@ free_streams: | |||
1236 | free_irq: | 1260 | free_irq: |
1237 | free_irq(itv->pdev->irq, (void *)itv); | 1261 | free_irq(itv->pdev->irq, (void *)itv); |
1238 | free_i2c: | 1262 | free_i2c: |
1263 | v4l2_ctrl_handler_free(&itv->cxhdl.hdl); | ||
1239 | exit_ivtv_i2c(itv); | 1264 | exit_ivtv_i2c(itv); |
1240 | free_io: | 1265 | free_io: |
1241 | ivtv_iounmap(itv); | 1266 | ivtv_iounmap(itv); |
@@ -1375,7 +1400,7 @@ static void ivtv_remove(struct pci_dev *pdev) | |||
1375 | else | 1400 | else |
1376 | type = IVTV_DEC_STREAM_TYPE_MPG; | 1401 | type = IVTV_DEC_STREAM_TYPE_MPG; |
1377 | ivtv_stop_v4l2_decode_stream(&itv->streams[type], | 1402 | ivtv_stop_v4l2_decode_stream(&itv->streams[type], |
1378 | VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); | 1403 | V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY, 0); |
1379 | } | 1404 | } |
1380 | ivtv_halt_firmware(itv); | 1405 | ivtv_halt_firmware(itv); |
1381 | } | 1406 | } |
@@ -1391,6 +1416,8 @@ static void ivtv_remove(struct pci_dev *pdev) | |||
1391 | ivtv_streams_cleanup(itv, 1); | 1416 | ivtv_streams_cleanup(itv, 1); |
1392 | ivtv_udma_free(itv); | 1417 | ivtv_udma_free(itv); |
1393 | 1418 | ||
1419 | v4l2_ctrl_handler_free(&itv->cxhdl.hdl); | ||
1420 | |||
1394 | exit_ivtv_i2c(itv); | 1421 | exit_ivtv_i2c(itv); |
1395 | 1422 | ||
1396 | free_irq(itv->pdev->irq, (void *)itv); | 1423 | free_irq(itv->pdev->irq, (void *)itv); |
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 06f3d78389bf..2e220028aad2 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h | |||
@@ -54,7 +54,6 @@ | |||
54 | #include <linux/mutex.h> | 54 | #include <linux/mutex.h> |
55 | #include <linux/slab.h> | 55 | #include <linux/slab.h> |
56 | #include <asm/uaccess.h> | 56 | #include <asm/uaccess.h> |
57 | #include <asm/system.h> | ||
58 | #include <asm/byteorder.h> | 57 | #include <asm/byteorder.h> |
59 | 58 | ||
60 | #include <linux/dvb/video.h> | 59 | #include <linux/dvb/video.h> |
@@ -331,6 +330,7 @@ struct ivtv_stream { | |||
331 | struct ivtv *itv; /* for ease of use */ | 330 | struct ivtv *itv; /* for ease of use */ |
332 | const char *name; /* name of the stream */ | 331 | const char *name; /* name of the stream */ |
333 | int type; /* stream type */ | 332 | int type; /* stream type */ |
333 | u32 caps; /* V4L2 capabilities */ | ||
334 | 334 | ||
335 | struct v4l2_fh *fh; /* pointer to the streaming filehandle */ | 335 | struct v4l2_fh *fh; /* pointer to the streaming filehandle */ |
336 | spinlock_t qlock; /* locks access to the queues */ | 336 | spinlock_t qlock; /* locks access to the queues */ |
@@ -630,6 +630,16 @@ struct ivtv { | |||
630 | 630 | ||
631 | struct v4l2_device v4l2_dev; | 631 | struct v4l2_device v4l2_dev; |
632 | struct cx2341x_handler cxhdl; | 632 | struct cx2341x_handler cxhdl; |
633 | struct { | ||
634 | /* PTS/Frame count control cluster */ | ||
635 | struct v4l2_ctrl *ctrl_pts; | ||
636 | struct v4l2_ctrl *ctrl_frame; | ||
637 | }; | ||
638 | struct { | ||
639 | /* Audio Playback control cluster */ | ||
640 | struct v4l2_ctrl *ctrl_audio_playback; | ||
641 | struct v4l2_ctrl *ctrl_audio_multilingual_playback; | ||
642 | }; | ||
633 | struct v4l2_ctrl_handler hdl_gpio; | 643 | struct v4l2_ctrl_handler hdl_gpio; |
634 | struct v4l2_subdev sd_gpio; /* GPIO sub-device */ | 644 | struct v4l2_subdev sd_gpio; /* GPIO sub-device */ |
635 | u16 instance; | 645 | u16 instance; |
@@ -649,7 +659,6 @@ struct ivtv { | |||
649 | u8 audio_stereo_mode; /* decoder setting how to handle stereo MPEG audio */ | 659 | u8 audio_stereo_mode; /* decoder setting how to handle stereo MPEG audio */ |
650 | u8 audio_bilingual_mode; /* decoder setting how to handle bilingual MPEG audio */ | 660 | u8 audio_bilingual_mode; /* decoder setting how to handle bilingual MPEG audio */ |
651 | 661 | ||
652 | |||
653 | /* Locking */ | 662 | /* Locking */ |
654 | spinlock_t lock; /* lock access to this struct */ | 663 | spinlock_t lock; /* lock access to this struct */ |
655 | struct mutex serialize_lock; /* mutex used to serialize open/close/start/stop/ioctl operations */ | 664 | struct mutex serialize_lock; /* mutex used to serialize open/close/start/stop/ioctl operations */ |
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 2cd6c89b7d91..c9663e885b9f 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c | |||
@@ -900,7 +900,7 @@ int ivtv_v4l2_close(struct file *filp) | |||
900 | if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) { | 900 | if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) { |
901 | struct ivtv_stream *s_vout = &itv->streams[IVTV_DEC_STREAM_TYPE_VOUT]; | 901 | struct ivtv_stream *s_vout = &itv->streams[IVTV_DEC_STREAM_TYPE_VOUT]; |
902 | 902 | ||
903 | ivtv_stop_decoding(id, VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); | 903 | ivtv_stop_decoding(id, V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY, 0); |
904 | 904 | ||
905 | /* If all output streams are closed, and if the user doesn't have | 905 | /* If all output streams are closed, and if the user doesn't have |
906 | IVTV_DEC_STREAM_TYPE_VOUT open, then disable CC on TV-out. */ | 906 | IVTV_DEC_STREAM_TYPE_VOUT open, then disable CC on TV-out. */ |
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index c4bc48143098..5452beef8e11 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c | |||
@@ -246,34 +246,40 @@ static int ivtv_validate_speed(int cur_speed, int new_speed) | |||
246 | } | 246 | } |
247 | 247 | ||
248 | static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id, | 248 | static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id, |
249 | struct video_command *vc, int try) | 249 | struct v4l2_decoder_cmd *dc, int try) |
250 | { | 250 | { |
251 | struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; | 251 | struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; |
252 | 252 | ||
253 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | 253 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) |
254 | return -EINVAL; | 254 | return -EINVAL; |
255 | 255 | ||
256 | switch (vc->cmd) { | 256 | switch (dc->cmd) { |
257 | case VIDEO_CMD_PLAY: { | 257 | case V4L2_DEC_CMD_START: { |
258 | vc->flags = 0; | 258 | dc->flags &= V4L2_DEC_CMD_START_MUTE_AUDIO; |
259 | vc->play.speed = ivtv_validate_speed(itv->speed, vc->play.speed); | 259 | dc->start.speed = ivtv_validate_speed(itv->speed, dc->start.speed); |
260 | if (vc->play.speed < 0) | 260 | if (dc->start.speed < 0) |
261 | vc->play.format = VIDEO_PLAY_FMT_GOP; | 261 | dc->start.format = V4L2_DEC_START_FMT_GOP; |
262 | else | ||
263 | dc->start.format = V4L2_DEC_START_FMT_NONE; | ||
264 | if (dc->start.speed != 500 && dc->start.speed != 1500) | ||
265 | dc->flags = dc->start.speed == 1000 ? 0 : | ||
266 | V4L2_DEC_CMD_START_MUTE_AUDIO; | ||
262 | if (try) break; | 267 | if (try) break; |
263 | 268 | ||
269 | itv->speed_mute_audio = dc->flags & V4L2_DEC_CMD_START_MUTE_AUDIO; | ||
264 | if (ivtv_set_output_mode(itv, OUT_MPG) != OUT_MPG) | 270 | if (ivtv_set_output_mode(itv, OUT_MPG) != OUT_MPG) |
265 | return -EBUSY; | 271 | return -EBUSY; |
266 | if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) { | 272 | if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) { |
267 | /* forces ivtv_set_speed to be called */ | 273 | /* forces ivtv_set_speed to be called */ |
268 | itv->speed = 0; | 274 | itv->speed = 0; |
269 | } | 275 | } |
270 | return ivtv_start_decoding(id, vc->play.speed); | 276 | return ivtv_start_decoding(id, dc->start.speed); |
271 | } | 277 | } |
272 | 278 | ||
273 | case VIDEO_CMD_STOP: | 279 | case V4L2_DEC_CMD_STOP: |
274 | vc->flags &= VIDEO_CMD_STOP_IMMEDIATELY|VIDEO_CMD_STOP_TO_BLACK; | 280 | dc->flags &= V4L2_DEC_CMD_STOP_IMMEDIATELY | V4L2_DEC_CMD_STOP_TO_BLACK; |
275 | if (vc->flags & VIDEO_CMD_STOP_IMMEDIATELY) | 281 | if (dc->flags & V4L2_DEC_CMD_STOP_IMMEDIATELY) |
276 | vc->stop.pts = 0; | 282 | dc->stop.pts = 0; |
277 | if (try) break; | 283 | if (try) break; |
278 | if (atomic_read(&itv->decoding) == 0) | 284 | if (atomic_read(&itv->decoding) == 0) |
279 | return 0; | 285 | return 0; |
@@ -281,22 +287,22 @@ static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id, | |||
281 | return -EBUSY; | 287 | return -EBUSY; |
282 | 288 | ||
283 | itv->output_mode = OUT_NONE; | 289 | itv->output_mode = OUT_NONE; |
284 | return ivtv_stop_v4l2_decode_stream(s, vc->flags, vc->stop.pts); | 290 | return ivtv_stop_v4l2_decode_stream(s, dc->flags, dc->stop.pts); |
285 | 291 | ||
286 | case VIDEO_CMD_FREEZE: | 292 | case V4L2_DEC_CMD_PAUSE: |
287 | vc->flags &= VIDEO_CMD_FREEZE_TO_BLACK; | 293 | dc->flags &= V4L2_DEC_CMD_PAUSE_TO_BLACK; |
288 | if (try) break; | 294 | if (try) break; |
289 | if (itv->output_mode != OUT_MPG) | 295 | if (itv->output_mode != OUT_MPG) |
290 | return -EBUSY; | 296 | return -EBUSY; |
291 | if (atomic_read(&itv->decoding) > 0) { | 297 | if (atomic_read(&itv->decoding) > 0) { |
292 | ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, | 298 | ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, |
293 | (vc->flags & VIDEO_CMD_FREEZE_TO_BLACK) ? 1 : 0); | 299 | (dc->flags & V4L2_DEC_CMD_PAUSE_TO_BLACK) ? 1 : 0); |
294 | set_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags); | 300 | set_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags); |
295 | } | 301 | } |
296 | break; | 302 | break; |
297 | 303 | ||
298 | case VIDEO_CMD_CONTINUE: | 304 | case V4L2_DEC_CMD_RESUME: |
299 | vc->flags = 0; | 305 | dc->flags = 0; |
300 | if (try) break; | 306 | if (try) break; |
301 | if (itv->output_mode != OUT_MPG) | 307 | if (itv->output_mode != OUT_MPG) |
302 | return -EBUSY; | 308 | return -EBUSY; |
@@ -754,12 +760,15 @@ static int ivtv_s_register(struct file *file, void *fh, struct v4l2_dbg_register | |||
754 | 760 | ||
755 | static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vcap) | 761 | static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vcap) |
756 | { | 762 | { |
757 | struct ivtv *itv = fh2id(fh)->itv; | 763 | struct ivtv_open_id *id = fh2id(file->private_data); |
764 | struct ivtv *itv = id->itv; | ||
765 | struct ivtv_stream *s = &itv->streams[id->type]; | ||
758 | 766 | ||
759 | strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver)); | 767 | strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver)); |
760 | strlcpy(vcap->card, itv->card_name, sizeof(vcap->card)); | 768 | strlcpy(vcap->card, itv->card_name, sizeof(vcap->card)); |
761 | snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->pdev)); | 769 | snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->pdev)); |
762 | vcap->capabilities = itv->v4l2_cap; /* capabilities */ | 770 | vcap->capabilities = itv->v4l2_cap | V4L2_CAP_DEVICE_CAPS; |
771 | vcap->device_caps = s->caps; | ||
763 | return 0; | 772 | return 0; |
764 | } | 773 | } |
765 | 774 | ||
@@ -1476,8 +1485,6 @@ static int ivtv_log_status(struct file *file, void *fh) | |||
1476 | struct v4l2_audio audin; | 1485 | struct v4l2_audio audin; |
1477 | int i; | 1486 | int i; |
1478 | 1487 | ||
1479 | IVTV_INFO("================= START STATUS CARD #%d =================\n", | ||
1480 | itv->instance); | ||
1481 | IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name); | 1488 | IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name); |
1482 | if (itv->hw_flags & IVTV_HW_TVEEPROM) { | 1489 | if (itv->hw_flags & IVTV_HW_TVEEPROM) { |
1483 | struct tveeprom tv; | 1490 | struct tveeprom tv; |
@@ -1501,13 +1508,6 @@ static int ivtv_log_status(struct file *file, void *fh) | |||
1501 | "YUV Frames", | 1508 | "YUV Frames", |
1502 | "Passthrough", | 1509 | "Passthrough", |
1503 | }; | 1510 | }; |
1504 | static const char * const audio_modes[5] = { | ||
1505 | "Stereo", | ||
1506 | "Left", | ||
1507 | "Right", | ||
1508 | "Mono", | ||
1509 | "Swapped" | ||
1510 | }; | ||
1511 | static const char * const alpha_mode[4] = { | 1511 | static const char * const alpha_mode[4] = { |
1512 | "None", | 1512 | "None", |
1513 | "Global", | 1513 | "Global", |
@@ -1536,9 +1536,6 @@ static int ivtv_log_status(struct file *file, void *fh) | |||
1536 | ivtv_get_output(itv, itv->active_output, &vidout); | 1536 | ivtv_get_output(itv, itv->active_output, &vidout); |
1537 | ivtv_get_audio_output(itv, 0, &audout); | 1537 | ivtv_get_audio_output(itv, 0, &audout); |
1538 | IVTV_INFO("Video Output: %s\n", vidout.name); | 1538 | IVTV_INFO("Video Output: %s\n", vidout.name); |
1539 | IVTV_INFO("Audio Output: %s (Stereo/Bilingual: %s/%s)\n", audout.name, | ||
1540 | audio_modes[itv->audio_stereo_mode], | ||
1541 | audio_modes[itv->audio_bilingual_mode]); | ||
1542 | if (mode < 0 || mode > OUT_PASSTHROUGH) | 1539 | if (mode < 0 || mode > OUT_PASSTHROUGH) |
1543 | mode = OUT_NONE; | 1540 | mode = OUT_NONE; |
1544 | IVTV_INFO("Output Mode: %s\n", output_modes[mode]); | 1541 | IVTV_INFO("Output Mode: %s\n", output_modes[mode]); |
@@ -1566,12 +1563,27 @@ static int ivtv_log_status(struct file *file, void *fh) | |||
1566 | IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n", | 1563 | IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n", |
1567 | (long long)itv->mpg_data_received, | 1564 | (long long)itv->mpg_data_received, |
1568 | (long long)itv->vbi_data_inserted); | 1565 | (long long)itv->vbi_data_inserted); |
1569 | IVTV_INFO("================== END STATUS CARD #%d ==================\n", | ||
1570 | itv->instance); | ||
1571 | |||
1572 | return 0; | 1566 | return 0; |
1573 | } | 1567 | } |
1574 | 1568 | ||
1569 | static int ivtv_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec) | ||
1570 | { | ||
1571 | struct ivtv_open_id *id = fh2id(file->private_data); | ||
1572 | struct ivtv *itv = id->itv; | ||
1573 | |||
1574 | IVTV_DEBUG_IOCTL("VIDIOC_DECODER_CMD %d\n", dec->cmd); | ||
1575 | return ivtv_video_command(itv, id, dec, false); | ||
1576 | } | ||
1577 | |||
1578 | static int ivtv_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec) | ||
1579 | { | ||
1580 | struct ivtv_open_id *id = fh2id(file->private_data); | ||
1581 | struct ivtv *itv = id->itv; | ||
1582 | |||
1583 | IVTV_DEBUG_IOCTL("VIDIOC_TRY_DECODER_CMD %d\n", dec->cmd); | ||
1584 | return ivtv_video_command(itv, id, dec, true); | ||
1585 | } | ||
1586 | |||
1575 | static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) | 1587 | static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) |
1576 | { | 1588 | { |
1577 | struct ivtv_open_id *id = fh2id(filp->private_data); | 1589 | struct ivtv_open_id *id = fh2id(filp->private_data); |
@@ -1605,9 +1617,15 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) | |||
1605 | return ivtv_yuv_prep_frame(itv, args); | 1617 | return ivtv_yuv_prep_frame(itv, args); |
1606 | } | 1618 | } |
1607 | 1619 | ||
1620 | case IVTV_IOC_PASSTHROUGH_MODE: | ||
1621 | IVTV_DEBUG_IOCTL("IVTV_IOC_PASSTHROUGH_MODE\n"); | ||
1622 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | ||
1623 | return -EINVAL; | ||
1624 | return ivtv_passthrough_mode(itv, *(int *)arg != 0); | ||
1625 | |||
1608 | case VIDEO_GET_PTS: { | 1626 | case VIDEO_GET_PTS: { |
1609 | u32 data[CX2341X_MBOX_MAX_DATA]; | 1627 | s64 *pts = arg; |
1610 | u64 *pts = arg; | 1628 | s64 frame; |
1611 | 1629 | ||
1612 | IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n"); | 1630 | IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n"); |
1613 | if (s->type < IVTV_DEC_STREAM_TYPE_MPG) { | 1631 | if (s->type < IVTV_DEC_STREAM_TYPE_MPG) { |
@@ -1616,29 +1634,12 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) | |||
1616 | } | 1634 | } |
1617 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | 1635 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) |
1618 | return -EINVAL; | 1636 | return -EINVAL; |
1619 | 1637 | return ivtv_g_pts_frame(itv, pts, &frame); | |
1620 | if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) { | ||
1621 | *pts = (u64) ((u64)itv->last_dec_timing[2] << 32) | | ||
1622 | (u64)itv->last_dec_timing[1]; | ||
1623 | break; | ||
1624 | } | ||
1625 | *pts = 0; | ||
1626 | if (atomic_read(&itv->decoding)) { | ||
1627 | if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) { | ||
1628 | IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n"); | ||
1629 | return -EIO; | ||
1630 | } | ||
1631 | memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing)); | ||
1632 | set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); | ||
1633 | *pts = (u64) ((u64) data[2] << 32) | (u64) data[1]; | ||
1634 | /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/ | ||
1635 | } | ||
1636 | break; | ||
1637 | } | 1638 | } |
1638 | 1639 | ||
1639 | case VIDEO_GET_FRAME_COUNT: { | 1640 | case VIDEO_GET_FRAME_COUNT: { |
1640 | u32 data[CX2341X_MBOX_MAX_DATA]; | 1641 | s64 *frame = arg; |
1641 | u64 *frame = arg; | 1642 | s64 pts; |
1642 | 1643 | ||
1643 | IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n"); | 1644 | IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n"); |
1644 | if (s->type < IVTV_DEC_STREAM_TYPE_MPG) { | 1645 | if (s->type < IVTV_DEC_STREAM_TYPE_MPG) { |
@@ -1647,71 +1648,58 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) | |||
1647 | } | 1648 | } |
1648 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) | 1649 | if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) |
1649 | return -EINVAL; | 1650 | return -EINVAL; |
1650 | 1651 | return ivtv_g_pts_frame(itv, &pts, frame); | |
1651 | if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) { | ||
1652 | *frame = itv->last_dec_timing[0]; | ||
1653 | break; | ||
1654 | } | ||
1655 | *frame = 0; | ||
1656 | if (atomic_read(&itv->decoding)) { | ||
1657 | if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) { | ||
1658 | IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n"); | ||
1659 | return -EIO; | ||
1660 | } | ||
1661 | memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing)); | ||
1662 | set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); | ||
1663 | *frame = data[0]; | ||
1664 | } | ||
1665 | break; | ||
1666 | } | 1652 | } |
1667 | 1653 | ||
1668 | case VIDEO_PLAY: { | 1654 | case VIDEO_PLAY: { |
1669 | struct video_command vc; | 1655 | struct v4l2_decoder_cmd dc; |
1670 | 1656 | ||
1671 | IVTV_DEBUG_IOCTL("VIDEO_PLAY\n"); | 1657 | IVTV_DEBUG_IOCTL("VIDEO_PLAY\n"); |
1672 | memset(&vc, 0, sizeof(vc)); | 1658 | memset(&dc, 0, sizeof(dc)); |
1673 | vc.cmd = VIDEO_CMD_PLAY; | 1659 | dc.cmd = V4L2_DEC_CMD_START; |
1674 | return ivtv_video_command(itv, id, &vc, 0); | 1660 | return ivtv_video_command(itv, id, &dc, 0); |
1675 | } | 1661 | } |
1676 | 1662 | ||
1677 | case VIDEO_STOP: { | 1663 | case VIDEO_STOP: { |
1678 | struct video_command vc; | 1664 | struct v4l2_decoder_cmd dc; |
1679 | 1665 | ||
1680 | IVTV_DEBUG_IOCTL("VIDEO_STOP\n"); | 1666 | IVTV_DEBUG_IOCTL("VIDEO_STOP\n"); |
1681 | memset(&vc, 0, sizeof(vc)); | 1667 | memset(&dc, 0, sizeof(dc)); |
1682 | vc.cmd = VIDEO_CMD_STOP; | 1668 | dc.cmd = V4L2_DEC_CMD_STOP; |
1683 | vc.flags = VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY; | 1669 | dc.flags = V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY; |
1684 | return ivtv_video_command(itv, id, &vc, 0); | 1670 | return ivtv_video_command(itv, id, &dc, 0); |
1685 | } | 1671 | } |
1686 | 1672 | ||
1687 | case VIDEO_FREEZE: { | 1673 | case VIDEO_FREEZE: { |
1688 | struct video_command vc; | 1674 | struct v4l2_decoder_cmd dc; |
1689 | 1675 | ||
1690 | IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n"); | 1676 | IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n"); |
1691 | memset(&vc, 0, sizeof(vc)); | 1677 | memset(&dc, 0, sizeof(dc)); |
1692 | vc.cmd = VIDEO_CMD_FREEZE; | 1678 | dc.cmd = V4L2_DEC_CMD_PAUSE; |
1693 | return ivtv_video_command(itv, id, &vc, 0); | 1679 | return ivtv_video_command(itv, id, &dc, 0); |
1694 | } | 1680 | } |
1695 | 1681 | ||
1696 | case VIDEO_CONTINUE: { | 1682 | case VIDEO_CONTINUE: { |
1697 | struct video_command vc; | 1683 | struct v4l2_decoder_cmd dc; |
1698 | 1684 | ||
1699 | IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n"); | 1685 | IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n"); |
1700 | memset(&vc, 0, sizeof(vc)); | 1686 | memset(&dc, 0, sizeof(dc)); |
1701 | vc.cmd = VIDEO_CMD_CONTINUE; | 1687 | dc.cmd = V4L2_DEC_CMD_RESUME; |
1702 | return ivtv_video_command(itv, id, &vc, 0); | 1688 | return ivtv_video_command(itv, id, &dc, 0); |
1703 | } | 1689 | } |
1704 | 1690 | ||
1705 | case VIDEO_COMMAND: | 1691 | case VIDEO_COMMAND: |
1706 | case VIDEO_TRY_COMMAND: { | 1692 | case VIDEO_TRY_COMMAND: { |
1707 | struct video_command *vc = arg; | 1693 | /* Note: struct v4l2_decoder_cmd has the same layout as |
1694 | struct video_command */ | ||
1695 | struct v4l2_decoder_cmd *dc = arg; | ||
1708 | int try = (cmd == VIDEO_TRY_COMMAND); | 1696 | int try = (cmd == VIDEO_TRY_COMMAND); |
1709 | 1697 | ||
1710 | if (try) | 1698 | if (try) |
1711 | IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", vc->cmd); | 1699 | IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", dc->cmd); |
1712 | else | 1700 | else |
1713 | IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", vc->cmd); | 1701 | IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", dc->cmd); |
1714 | return ivtv_video_command(itv, id, vc, try); | 1702 | return ivtv_video_command(itv, id, dc, try); |
1715 | } | 1703 | } |
1716 | 1704 | ||
1717 | case VIDEO_GET_EVENT: { | 1705 | case VIDEO_GET_EVENT: { |
@@ -1775,17 +1763,13 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) | |||
1775 | IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n"); | 1763 | IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n"); |
1776 | if (iarg > AUDIO_STEREO_SWAPPED) | 1764 | if (iarg > AUDIO_STEREO_SWAPPED) |
1777 | return -EINVAL; | 1765 | return -EINVAL; |
1778 | itv->audio_stereo_mode = iarg; | 1766 | return v4l2_ctrl_s_ctrl(itv->ctrl_audio_playback, iarg); |
1779 | ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); | ||
1780 | return 0; | ||
1781 | 1767 | ||
1782 | case AUDIO_BILINGUAL_CHANNEL_SELECT: | 1768 | case AUDIO_BILINGUAL_CHANNEL_SELECT: |
1783 | IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n"); | 1769 | IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n"); |
1784 | if (iarg > AUDIO_STEREO_SWAPPED) | 1770 | if (iarg > AUDIO_STEREO_SWAPPED) |
1785 | return -EINVAL; | 1771 | return -EINVAL; |
1786 | itv->audio_bilingual_mode = iarg; | 1772 | return v4l2_ctrl_s_ctrl(itv->ctrl_audio_multilingual_playback, iarg); |
1787 | ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); | ||
1788 | return 0; | ||
1789 | 1773 | ||
1790 | default: | 1774 | default: |
1791 | return -EINVAL; | 1775 | return -EINVAL; |
@@ -1800,6 +1784,7 @@ static long ivtv_default(struct file *file, void *fh, bool valid_prio, | |||
1800 | 1784 | ||
1801 | if (!valid_prio) { | 1785 | if (!valid_prio) { |
1802 | switch (cmd) { | 1786 | switch (cmd) { |
1787 | case IVTV_IOC_PASSTHROUGH_MODE: | ||
1803 | case VIDEO_PLAY: | 1788 | case VIDEO_PLAY: |
1804 | case VIDEO_STOP: | 1789 | case VIDEO_STOP: |
1805 | case VIDEO_FREEZE: | 1790 | case VIDEO_FREEZE: |
@@ -1825,6 +1810,7 @@ static long ivtv_default(struct file *file, void *fh, bool valid_prio, | |||
1825 | } | 1810 | } |
1826 | 1811 | ||
1827 | case IVTV_IOC_DMA_FRAME: | 1812 | case IVTV_IOC_DMA_FRAME: |
1813 | case IVTV_IOC_PASSTHROUGH_MODE: | ||
1828 | case VIDEO_GET_PTS: | 1814 | case VIDEO_GET_PTS: |
1829 | case VIDEO_GET_FRAME_COUNT: | 1815 | case VIDEO_GET_FRAME_COUNT: |
1830 | case VIDEO_GET_EVENT: | 1816 | case VIDEO_GET_EVENT: |
@@ -1889,6 +1875,8 @@ static const struct v4l2_ioctl_ops ivtv_ioctl_ops = { | |||
1889 | .vidioc_enum_fmt_vid_cap = ivtv_enum_fmt_vid_cap, | 1875 | .vidioc_enum_fmt_vid_cap = ivtv_enum_fmt_vid_cap, |
1890 | .vidioc_encoder_cmd = ivtv_encoder_cmd, | 1876 | .vidioc_encoder_cmd = ivtv_encoder_cmd, |
1891 | .vidioc_try_encoder_cmd = ivtv_try_encoder_cmd, | 1877 | .vidioc_try_encoder_cmd = ivtv_try_encoder_cmd, |
1878 | .vidioc_decoder_cmd = ivtv_decoder_cmd, | ||
1879 | .vidioc_try_decoder_cmd = ivtv_try_decoder_cmd, | ||
1892 | .vidioc_enum_fmt_vid_out = ivtv_enum_fmt_vid_out, | 1880 | .vidioc_enum_fmt_vid_out = ivtv_enum_fmt_vid_out, |
1893 | .vidioc_g_fmt_vid_cap = ivtv_g_fmt_vid_cap, | 1881 | .vidioc_g_fmt_vid_cap = ivtv_g_fmt_vid_cap, |
1894 | .vidioc_g_fmt_vbi_cap = ivtv_g_fmt_vbi_cap, | 1882 | .vidioc_g_fmt_vbi_cap = ivtv_g_fmt_vbi_cap, |
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index c6e28b4ebbed..7ea5ca7f012b 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c | |||
@@ -78,60 +78,73 @@ static struct { | |||
78 | int num_offset; | 78 | int num_offset; |
79 | int dma, pio; | 79 | int dma, pio; |
80 | enum v4l2_buf_type buf_type; | 80 | enum v4l2_buf_type buf_type; |
81 | u32 v4l2_caps; | ||
81 | const struct v4l2_file_operations *fops; | 82 | const struct v4l2_file_operations *fops; |
82 | } ivtv_stream_info[] = { | 83 | } ivtv_stream_info[] = { |
83 | { /* IVTV_ENC_STREAM_TYPE_MPG */ | 84 | { /* IVTV_ENC_STREAM_TYPE_MPG */ |
84 | "encoder MPG", | 85 | "encoder MPG", |
85 | VFL_TYPE_GRABBER, 0, | 86 | VFL_TYPE_GRABBER, 0, |
86 | PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, | 87 | PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, |
88 | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | | ||
89 | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, | ||
87 | &ivtv_v4l2_enc_fops | 90 | &ivtv_v4l2_enc_fops |
88 | }, | 91 | }, |
89 | { /* IVTV_ENC_STREAM_TYPE_YUV */ | 92 | { /* IVTV_ENC_STREAM_TYPE_YUV */ |
90 | "encoder YUV", | 93 | "encoder YUV", |
91 | VFL_TYPE_GRABBER, IVTV_V4L2_ENC_YUV_OFFSET, | 94 | VFL_TYPE_GRABBER, IVTV_V4L2_ENC_YUV_OFFSET, |
92 | PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, | 95 | PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, |
96 | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | | ||
97 | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, | ||
93 | &ivtv_v4l2_enc_fops | 98 | &ivtv_v4l2_enc_fops |
94 | }, | 99 | }, |
95 | { /* IVTV_ENC_STREAM_TYPE_VBI */ | 100 | { /* IVTV_ENC_STREAM_TYPE_VBI */ |
96 | "encoder VBI", | 101 | "encoder VBI", |
97 | VFL_TYPE_VBI, 0, | 102 | VFL_TYPE_VBI, 0, |
98 | PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VBI_CAPTURE, | 103 | PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VBI_CAPTURE, |
104 | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_TUNER | | ||
105 | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, | ||
99 | &ivtv_v4l2_enc_fops | 106 | &ivtv_v4l2_enc_fops |
100 | }, | 107 | }, |
101 | { /* IVTV_ENC_STREAM_TYPE_PCM */ | 108 | { /* IVTV_ENC_STREAM_TYPE_PCM */ |
102 | "encoder PCM", | 109 | "encoder PCM", |
103 | VFL_TYPE_GRABBER, IVTV_V4L2_ENC_PCM_OFFSET, | 110 | VFL_TYPE_GRABBER, IVTV_V4L2_ENC_PCM_OFFSET, |
104 | PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_PRIVATE, | 111 | PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_PRIVATE, |
112 | V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, | ||
105 | &ivtv_v4l2_enc_fops | 113 | &ivtv_v4l2_enc_fops |
106 | }, | 114 | }, |
107 | { /* IVTV_ENC_STREAM_TYPE_RAD */ | 115 | { /* IVTV_ENC_STREAM_TYPE_RAD */ |
108 | "encoder radio", | 116 | "encoder radio", |
109 | VFL_TYPE_RADIO, 0, | 117 | VFL_TYPE_RADIO, 0, |
110 | PCI_DMA_NONE, 1, V4L2_BUF_TYPE_PRIVATE, | 118 | PCI_DMA_NONE, 1, V4L2_BUF_TYPE_PRIVATE, |
119 | V4L2_CAP_RADIO | V4L2_CAP_TUNER, | ||
111 | &ivtv_v4l2_enc_fops | 120 | &ivtv_v4l2_enc_fops |
112 | }, | 121 | }, |
113 | { /* IVTV_DEC_STREAM_TYPE_MPG */ | 122 | { /* IVTV_DEC_STREAM_TYPE_MPG */ |
114 | "decoder MPG", | 123 | "decoder MPG", |
115 | VFL_TYPE_GRABBER, IVTV_V4L2_DEC_MPG_OFFSET, | 124 | VFL_TYPE_GRABBER, IVTV_V4L2_DEC_MPG_OFFSET, |
116 | PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT, | 125 | PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT, |
126 | V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, | ||
117 | &ivtv_v4l2_dec_fops | 127 | &ivtv_v4l2_dec_fops |
118 | }, | 128 | }, |
119 | { /* IVTV_DEC_STREAM_TYPE_VBI */ | 129 | { /* IVTV_DEC_STREAM_TYPE_VBI */ |
120 | "decoder VBI", | 130 | "decoder VBI", |
121 | VFL_TYPE_VBI, IVTV_V4L2_DEC_VBI_OFFSET, | 131 | VFL_TYPE_VBI, IVTV_V4L2_DEC_VBI_OFFSET, |
122 | PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_CAPTURE, | 132 | PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_CAPTURE, |
133 | V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_READWRITE, | ||
123 | &ivtv_v4l2_enc_fops | 134 | &ivtv_v4l2_enc_fops |
124 | }, | 135 | }, |
125 | { /* IVTV_DEC_STREAM_TYPE_VOUT */ | 136 | { /* IVTV_DEC_STREAM_TYPE_VOUT */ |
126 | "decoder VOUT", | 137 | "decoder VOUT", |
127 | VFL_TYPE_VBI, IVTV_V4L2_DEC_VOUT_OFFSET, | 138 | VFL_TYPE_VBI, IVTV_V4L2_DEC_VOUT_OFFSET, |
128 | PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_OUTPUT, | 139 | PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_OUTPUT, |
140 | V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, | ||
129 | &ivtv_v4l2_dec_fops | 141 | &ivtv_v4l2_dec_fops |
130 | }, | 142 | }, |
131 | { /* IVTV_DEC_STREAM_TYPE_YUV */ | 143 | { /* IVTV_DEC_STREAM_TYPE_YUV */ |
132 | "decoder YUV", | 144 | "decoder YUV", |
133 | VFL_TYPE_GRABBER, IVTV_V4L2_DEC_YUV_OFFSET, | 145 | VFL_TYPE_GRABBER, IVTV_V4L2_DEC_YUV_OFFSET, |
134 | PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT, | 146 | PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT, |
147 | V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, | ||
135 | &ivtv_v4l2_dec_fops | 148 | &ivtv_v4l2_dec_fops |
136 | } | 149 | } |
137 | }; | 150 | }; |
@@ -149,6 +162,7 @@ static void ivtv_stream_init(struct ivtv *itv, int type) | |||
149 | s->itv = itv; | 162 | s->itv = itv; |
150 | s->type = type; | 163 | s->type = type; |
151 | s->name = ivtv_stream_info[type].name; | 164 | s->name = ivtv_stream_info[type].name; |
165 | s->caps = ivtv_stream_info[type].v4l2_caps; | ||
152 | 166 | ||
153 | if (ivtv_stream_info[type].pio) | 167 | if (ivtv_stream_info[type].pio) |
154 | s->dma = PCI_DMA_NONE; | 168 | s->dma = PCI_DMA_NONE; |
@@ -209,8 +223,8 @@ static int ivtv_prep_dev(struct ivtv *itv, int type) | |||
209 | 223 | ||
210 | s->vdev->num = num; | 224 | s->vdev->num = num; |
211 | s->vdev->v4l2_dev = &itv->v4l2_dev; | 225 | s->vdev->v4l2_dev = &itv->v4l2_dev; |
212 | s->vdev->ctrl_handler = itv->v4l2_dev.ctrl_handler; | ||
213 | s->vdev->fops = ivtv_stream_info[type].fops; | 226 | s->vdev->fops = ivtv_stream_info[type].fops; |
227 | s->vdev->ctrl_handler = itv->v4l2_dev.ctrl_handler; | ||
214 | s->vdev->release = video_device_release; | 228 | s->vdev->release = video_device_release; |
215 | s->vdev->tvnorms = V4L2_STD_ALL; | 229 | s->vdev->tvnorms = V4L2_STD_ALL; |
216 | s->vdev->lock = &itv->serialize_lock; | 230 | s->vdev->lock = &itv->serialize_lock; |
@@ -891,7 +905,7 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts) | |||
891 | IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", (unsigned long long)pts, flags); | 905 | IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", (unsigned long long)pts, flags); |
892 | 906 | ||
893 | /* Stop Decoder */ | 907 | /* Stop Decoder */ |
894 | if (!(flags & VIDEO_CMD_STOP_IMMEDIATELY) || pts) { | 908 | if (!(flags & V4L2_DEC_CMD_STOP_IMMEDIATELY) || pts) { |
895 | u32 tmp = 0; | 909 | u32 tmp = 0; |
896 | 910 | ||
897 | /* Wait until the decoder is no longer running */ | 911 | /* Wait until the decoder is no longer running */ |
@@ -911,7 +925,7 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts) | |||
911 | break; | 925 | break; |
912 | } | 926 | } |
913 | } | 927 | } |
914 | ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, flags & VIDEO_CMD_STOP_TO_BLACK, 0, 0); | 928 | ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, flags & V4L2_DEC_CMD_STOP_TO_BLACK, 0, 0); |
915 | 929 | ||
916 | /* turn off notification of dual/stereo mode change */ | 930 | /* turn off notification of dual/stereo mode change */ |
917 | ivtv_vapi(itv, CX2341X_DEC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_DEC_AUD_MODE_CHG, -1); | 931 | ivtv_vapi(itv, CX2341X_DEC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_DEC_AUD_MODE_CHG, -1); |
diff --git a/drivers/media/video/ivtv/ivtv-udma.c b/drivers/media/video/ivtv/ivtv-udma.c index 69cc8166b20b..7338cb2d0a38 100644 --- a/drivers/media/video/ivtv/ivtv-udma.c +++ b/drivers/media/video/ivtv/ivtv-udma.c | |||
@@ -57,9 +57,9 @@ int ivtv_udma_fill_sg_list (struct ivtv_user_dma *dma, struct ivtv_dma_page_info | |||
57 | if (dma->bouncemap[map_offset] == NULL) | 57 | if (dma->bouncemap[map_offset] == NULL) |
58 | return -1; | 58 | return -1; |
59 | local_irq_save(flags); | 59 | local_irq_save(flags); |
60 | src = kmap_atomic(dma->map[map_offset], KM_BOUNCE_READ) + offset; | 60 | src = kmap_atomic(dma->map[map_offset]) + offset; |
61 | memcpy(page_address(dma->bouncemap[map_offset]) + offset, src, len); | 61 | memcpy(page_address(dma->bouncemap[map_offset]) + offset, src, len); |
62 | kunmap_atomic(src, KM_BOUNCE_READ); | 62 | kunmap_atomic(src); |
63 | local_irq_restore(flags); | 63 | local_irq_restore(flags); |
64 | sg_set_page(&dma->SGlist[map_offset], dma->bouncemap[map_offset], len, offset); | 64 | sg_set_page(&dma->SGlist[map_offset], dma->bouncemap[map_offset], len, offset); |
65 | } | 65 | } |
diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c index d0fbfcf7133d..e5e7fa9e737b 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/video/ivtv/ivtvfb.c | |||
@@ -1293,7 +1293,6 @@ static int __init ivtvfb_init(void) | |||
1293 | 1293 | ||
1294 | drv = driver_find("ivtv", &pci_bus_type); | 1294 | drv = driver_find("ivtv", &pci_bus_type); |
1295 | err = driver_for_each_device(drv, NULL, ®istered, ivtvfb_callback_init); | 1295 | err = driver_for_each_device(drv, NULL, ®istered, ivtvfb_callback_init); |
1296 | put_driver(drv); | ||
1297 | if (!registered) { | 1296 | if (!registered) { |
1298 | printk(KERN_ERR "ivtvfb: no cards found\n"); | 1297 | printk(KERN_ERR "ivtvfb: no cards found\n"); |
1299 | return -ENODEV; | 1298 | return -ENODEV; |
@@ -1310,7 +1309,6 @@ static void ivtvfb_cleanup(void) | |||
1310 | 1309 | ||
1311 | drv = driver_find("ivtv", &pci_bus_type); | 1310 | drv = driver_find("ivtv", &pci_bus_type); |
1312 | err = driver_for_each_device(drv, NULL, NULL, ivtvfb_callback_cleanup); | 1311 | err = driver_for_each_device(drv, NULL, NULL, ivtvfb_callback_cleanup); |
1313 | put_driver(drv); | ||
1314 | } | 1312 | } |
1315 | 1313 | ||
1316 | module_init(ivtvfb_init); | 1314 | module_init(ivtvfb_init); |
diff --git a/drivers/media/video/ks0127.c b/drivers/media/video/ks0127.c index afa91182b448..ee7ca2dcca2f 100644 --- a/drivers/media/video/ks0127.c +++ b/drivers/media/video/ks0127.c | |||
@@ -721,15 +721,4 @@ static struct i2c_driver ks0127_driver = { | |||
721 | .id_table = ks0127_id, | 721 | .id_table = ks0127_id, |
722 | }; | 722 | }; |
723 | 723 | ||
724 | static __init int init_ks0127(void) | 724 | module_i2c_driver(ks0127_driver); |
725 | { | ||
726 | return i2c_add_driver(&ks0127_driver); | ||
727 | } | ||
728 | |||
729 | static __exit void exit_ks0127(void) | ||
730 | { | ||
731 | i2c_del_driver(&ks0127_driver); | ||
732 | } | ||
733 | |||
734 | module_init(init_ks0127); | ||
735 | module_exit(exit_ks0127); | ||
diff --git a/drivers/media/video/m52790.c b/drivers/media/video/m52790.c index 303ffa7df4ac..0991576f4c82 100644 --- a/drivers/media/video/m52790.c +++ b/drivers/media/video/m52790.c | |||
@@ -213,15 +213,4 @@ static struct i2c_driver m52790_driver = { | |||
213 | .id_table = m52790_id, | 213 | .id_table = m52790_id, |
214 | }; | 214 | }; |
215 | 215 | ||
216 | static __init int init_m52790(void) | 216 | module_i2c_driver(m52790_driver); |
217 | { | ||
218 | return i2c_add_driver(&m52790_driver); | ||
219 | } | ||
220 | |||
221 | static __exit void exit_m52790(void) | ||
222 | { | ||
223 | i2c_del_driver(&m52790_driver); | ||
224 | } | ||
225 | |||
226 | module_init(init_m52790); | ||
227 | module_exit(exit_m52790); | ||
diff --git a/drivers/media/video/m5mols/m5mols_core.c b/drivers/media/video/m5mols/m5mols_core.c index 93d768db9f33..d718aee01c77 100644 --- a/drivers/media/video/m5mols/m5mols_core.c +++ b/drivers/media/video/m5mols/m5mols_core.c | |||
@@ -982,8 +982,8 @@ static int __devinit m5mols_probe(struct i2c_client *client, | |||
982 | } | 982 | } |
983 | 983 | ||
984 | sd = &info->sd; | 984 | sd = &info->sd; |
985 | strlcpy(sd->name, MODULE_NAME, sizeof(sd->name)); | ||
986 | v4l2_i2c_subdev_init(sd, client, &m5mols_ops); | 985 | v4l2_i2c_subdev_init(sd, client, &m5mols_ops); |
986 | strlcpy(sd->name, MODULE_NAME, sizeof(sd->name)); | ||
987 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | 987 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
988 | 988 | ||
989 | sd->internal_ops = &m5mols_subdev_internal_ops; | 989 | sd->internal_ops = &m5mols_subdev_internal_ops; |
@@ -1057,18 +1057,7 @@ static struct i2c_driver m5mols_i2c_driver = { | |||
1057 | .id_table = m5mols_id, | 1057 | .id_table = m5mols_id, |
1058 | }; | 1058 | }; |
1059 | 1059 | ||
1060 | static int __init m5mols_mod_init(void) | 1060 | module_i2c_driver(m5mols_i2c_driver); |
1061 | { | ||
1062 | return i2c_add_driver(&m5mols_i2c_driver); | ||
1063 | } | ||
1064 | |||
1065 | static void __exit m5mols_mod_exit(void) | ||
1066 | { | ||
1067 | i2c_del_driver(&m5mols_i2c_driver); | ||
1068 | } | ||
1069 | |||
1070 | module_init(m5mols_mod_init); | ||
1071 | module_exit(m5mols_mod_exit); | ||
1072 | 1061 | ||
1073 | MODULE_AUTHOR("HeungJun Kim <riverful.kim@samsung.com>"); | 1062 | MODULE_AUTHOR("HeungJun Kim <riverful.kim@samsung.com>"); |
1074 | MODULE_AUTHOR("Dongsoo Kim <dongsoo45.kim@samsung.com>"); | 1063 | MODULE_AUTHOR("Dongsoo Kim <dongsoo45.kim@samsung.com>"); |
diff --git a/drivers/media/video/marvell-ccic/mcam-core.c b/drivers/media/video/marvell-ccic/mcam-core.c index 37d20e73908a..996ac34d9a89 100644 --- a/drivers/media/video/marvell-ccic/mcam-core.c +++ b/drivers/media/video/marvell-ccic/mcam-core.c | |||
@@ -509,11 +509,17 @@ static void mcam_sg_next_buffer(struct mcam_camera *cam) | |||
509 | 509 | ||
510 | buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, queue); | 510 | buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, queue); |
511 | list_del_init(&buf->queue); | 511 | list_del_init(&buf->queue); |
512 | /* | ||
513 | * Very Bad Not Good Things happen if you don't clear | ||
514 | * C1_DESC_ENA before making any descriptor changes. | ||
515 | */ | ||
516 | mcam_reg_clear_bit(cam, REG_CTRL1, C1_DESC_ENA); | ||
512 | mcam_reg_write(cam, REG_DMA_DESC_Y, buf->dma_desc_pa); | 517 | mcam_reg_write(cam, REG_DMA_DESC_Y, buf->dma_desc_pa); |
513 | mcam_reg_write(cam, REG_DESC_LEN_Y, | 518 | mcam_reg_write(cam, REG_DESC_LEN_Y, |
514 | buf->dma_desc_nent*sizeof(struct mcam_dma_desc)); | 519 | buf->dma_desc_nent*sizeof(struct mcam_dma_desc)); |
515 | mcam_reg_write(cam, REG_DESC_LEN_U, 0); | 520 | mcam_reg_write(cam, REG_DESC_LEN_U, 0); |
516 | mcam_reg_write(cam, REG_DESC_LEN_V, 0); | 521 | mcam_reg_write(cam, REG_DESC_LEN_V, 0); |
522 | mcam_reg_set_bit(cam, REG_CTRL1, C1_DESC_ENA); | ||
517 | cam->vb_bufs[0] = buf; | 523 | cam->vb_bufs[0] = buf; |
518 | } | 524 | } |
519 | 525 | ||
@@ -533,7 +539,6 @@ static void mcam_ctlr_dma_sg(struct mcam_camera *cam) | |||
533 | 539 | ||
534 | mcam_reg_clear_bit(cam, REG_CTRL1, C1_DESC_3WORD); | 540 | mcam_reg_clear_bit(cam, REG_CTRL1, C1_DESC_3WORD); |
535 | mcam_sg_next_buffer(cam); | 541 | mcam_sg_next_buffer(cam); |
536 | mcam_reg_set_bit(cam, REG_CTRL1, C1_DESC_ENA); | ||
537 | cam->nbufs = 3; | 542 | cam->nbufs = 3; |
538 | } | 543 | } |
539 | 544 | ||
@@ -556,17 +561,16 @@ static void mcam_dma_sg_done(struct mcam_camera *cam, int frame) | |||
556 | struct mcam_vb_buffer *buf = cam->vb_bufs[0]; | 561 | struct mcam_vb_buffer *buf = cam->vb_bufs[0]; |
557 | 562 | ||
558 | /* | 563 | /* |
559 | * Very Bad Not Good Things happen if you don't clear | 564 | * If we're no longer supposed to be streaming, don't do anything. |
560 | * C1_DESC_ENA before making any descriptor changes. | ||
561 | */ | 565 | */ |
562 | mcam_reg_clear_bit(cam, REG_CTRL1, C1_DESC_ENA); | 566 | if (cam->state != S_STREAMING) |
567 | return; | ||
563 | /* | 568 | /* |
564 | * If we have another buffer available, put it in and | 569 | * If we have another buffer available, put it in and |
565 | * restart the engine. | 570 | * restart the engine. |
566 | */ | 571 | */ |
567 | if (!list_empty(&cam->buffers)) { | 572 | if (!list_empty(&cam->buffers)) { |
568 | mcam_sg_next_buffer(cam); | 573 | mcam_sg_next_buffer(cam); |
569 | mcam_reg_set_bit(cam, REG_CTRL1, C1_DESC_ENA); | ||
570 | mcam_ctlr_start(cam); | 574 | mcam_ctlr_start(cam); |
571 | /* | 575 | /* |
572 | * Otherwise set CF_SG_RESTART and the controller will | 576 | * Otherwise set CF_SG_RESTART and the controller will |
@@ -737,7 +741,14 @@ static void mcam_ctlr_stop_dma(struct mcam_camera *cam) | |||
737 | mcam_ctlr_stop(cam); | 741 | mcam_ctlr_stop(cam); |
738 | cam->state = S_IDLE; | 742 | cam->state = S_IDLE; |
739 | spin_unlock_irqrestore(&cam->dev_lock, flags); | 743 | spin_unlock_irqrestore(&cam->dev_lock, flags); |
740 | msleep(40); | 744 | /* |
745 | * This is a brutally long sleep, but experience shows that | ||
746 | * it can take the controller a while to get the message that | ||
747 | * it needs to stop grabbing frames. In particular, we can | ||
748 | * sometimes (on mmp) get a frame at the end WITHOUT the | ||
749 | * start-of-frame indication. | ||
750 | */ | ||
751 | msleep(150); | ||
741 | if (test_bit(CF_DMA_ACTIVE, &cam->flags)) | 752 | if (test_bit(CF_DMA_ACTIVE, &cam->flags)) |
742 | cam_err(cam, "Timeout waiting for DMA to end\n"); | 753 | cam_err(cam, "Timeout waiting for DMA to end\n"); |
743 | /* This would be bad news - what now? */ | 754 | /* This would be bad news - what now? */ |
@@ -880,6 +891,7 @@ static int mcam_read_setup(struct mcam_camera *cam) | |||
880 | * Turn it loose. | 891 | * Turn it loose. |
881 | */ | 892 | */ |
882 | spin_lock_irqsave(&cam->dev_lock, flags); | 893 | spin_lock_irqsave(&cam->dev_lock, flags); |
894 | clear_bit(CF_DMA_ACTIVE, &cam->flags); | ||
883 | mcam_reset_buffers(cam); | 895 | mcam_reset_buffers(cam); |
884 | mcam_ctlr_irq_enable(cam); | 896 | mcam_ctlr_irq_enable(cam); |
885 | cam->state = S_STREAMING; | 897 | cam->state = S_STREAMING; |
@@ -922,7 +934,7 @@ static void mcam_vb_buf_queue(struct vb2_buffer *vb) | |||
922 | spin_lock_irqsave(&cam->dev_lock, flags); | 934 | spin_lock_irqsave(&cam->dev_lock, flags); |
923 | start = (cam->state == S_BUFWAIT) && !list_empty(&cam->buffers); | 935 | start = (cam->state == S_BUFWAIT) && !list_empty(&cam->buffers); |
924 | list_add(&mvb->queue, &cam->buffers); | 936 | list_add(&mvb->queue, &cam->buffers); |
925 | if (test_bit(CF_SG_RESTART, &cam->flags)) | 937 | if (cam->state == S_STREAMING && test_bit(CF_SG_RESTART, &cam->flags)) |
926 | mcam_sg_restart(cam); | 938 | mcam_sg_restart(cam); |
927 | spin_unlock_irqrestore(&cam->dev_lock, flags); | 939 | spin_unlock_irqrestore(&cam->dev_lock, flags); |
928 | if (start) | 940 | if (start) |
@@ -1555,15 +1567,12 @@ static int mcam_v4l_release(struct file *filp) | |||
1555 | { | 1567 | { |
1556 | struct mcam_camera *cam = filp->private_data; | 1568 | struct mcam_camera *cam = filp->private_data; |
1557 | 1569 | ||
1558 | cam_err(cam, "Release, %d frames, %d singles, %d delivered\n", frames, | 1570 | cam_dbg(cam, "Release, %d frames, %d singles, %d delivered\n", frames, |
1559 | singles, delivered); | 1571 | singles, delivered); |
1560 | mutex_lock(&cam->s_mutex); | 1572 | mutex_lock(&cam->s_mutex); |
1561 | (cam->users)--; | 1573 | (cam->users)--; |
1562 | if (filp == cam->owner) { | ||
1563 | mcam_ctlr_stop_dma(cam); | ||
1564 | cam->owner = NULL; | ||
1565 | } | ||
1566 | if (cam->users == 0) { | 1574 | if (cam->users == 0) { |
1575 | mcam_ctlr_stop_dma(cam); | ||
1567 | mcam_cleanup_vb2(cam); | 1576 | mcam_cleanup_vb2(cam); |
1568 | mcam_ctlr_power_down(cam); | 1577 | mcam_ctlr_power_down(cam); |
1569 | if (cam->buffer_mode == B_vmalloc && alloc_bufs_at_read) | 1578 | if (cam->buffer_mode == B_vmalloc && alloc_bufs_at_read) |
@@ -1688,6 +1697,8 @@ int mccic_irq(struct mcam_camera *cam, unsigned int irqs) | |||
1688 | if (irqs & (IRQ_EOF0 << frame)) { | 1697 | if (irqs & (IRQ_EOF0 << frame)) { |
1689 | mcam_frame_complete(cam, frame); | 1698 | mcam_frame_complete(cam, frame); |
1690 | handled = 1; | 1699 | handled = 1; |
1700 | if (cam->buffer_mode == B_DMA_sg) | ||
1701 | break; | ||
1691 | } | 1702 | } |
1692 | /* | 1703 | /* |
1693 | * If a frame starts, note that we have DMA active. This | 1704 | * If a frame starts, note that we have DMA active. This |
diff --git a/drivers/media/video/marvell-ccic/mcam-core.h b/drivers/media/video/marvell-ccic/mcam-core.h index 917200e63255..bd6acba9fb37 100644 --- a/drivers/media/video/marvell-ccic/mcam-core.h +++ b/drivers/media/video/marvell-ccic/mcam-core.h | |||
@@ -107,7 +107,6 @@ struct mcam_camera { | |||
107 | enum mcam_state state; | 107 | enum mcam_state state; |
108 | unsigned long flags; /* Buffer status, mainly (dev_lock) */ | 108 | unsigned long flags; /* Buffer status, mainly (dev_lock) */ |
109 | int users; /* How many open FDs */ | 109 | int users; /* How many open FDs */ |
110 | struct file *owner; /* Who has data access (v4l2) */ | ||
111 | 110 | ||
112 | /* | 111 | /* |
113 | * Subsystem structures. | 112 | * Subsystem structures. |
diff --git a/drivers/media/video/marvell-ccic/mmp-driver.c b/drivers/media/video/marvell-ccic/mmp-driver.c index 0d64e2d7474a..d23552323f45 100644 --- a/drivers/media/video/marvell-ccic/mmp-driver.c +++ b/drivers/media/video/marvell-ccic/mmp-driver.c | |||
@@ -106,6 +106,13 @@ static struct mmp_camera *mmpcam_find_device(struct platform_device *pdev) | |||
106 | /* | 106 | /* |
107 | * Power control. | 107 | * Power control. |
108 | */ | 108 | */ |
109 | static void mmpcam_power_up_ctlr(struct mmp_camera *cam) | ||
110 | { | ||
111 | iowrite32(0x3f, cam->power_regs + REG_CCIC_DCGCR); | ||
112 | iowrite32(0x3805b, cam->power_regs + REG_CCIC_CRCR); | ||
113 | mdelay(1); | ||
114 | } | ||
115 | |||
109 | static void mmpcam_power_up(struct mcam_camera *mcam) | 116 | static void mmpcam_power_up(struct mcam_camera *mcam) |
110 | { | 117 | { |
111 | struct mmp_camera *cam = mcam_to_cam(mcam); | 118 | struct mmp_camera *cam = mcam_to_cam(mcam); |
@@ -113,9 +120,7 @@ static void mmpcam_power_up(struct mcam_camera *mcam) | |||
113 | /* | 120 | /* |
114 | * Turn on power and clocks to the controller. | 121 | * Turn on power and clocks to the controller. |
115 | */ | 122 | */ |
116 | iowrite32(0x3f, cam->power_regs + REG_CCIC_DCGCR); | 123 | mmpcam_power_up_ctlr(cam); |
117 | iowrite32(0x3805b, cam->power_regs + REG_CCIC_CRCR); | ||
118 | mdelay(1); | ||
119 | /* | 124 | /* |
120 | * Provide power to the sensor. | 125 | * Provide power to the sensor. |
121 | */ | 126 | */ |
@@ -335,7 +340,7 @@ static int mmpcam_resume(struct platform_device *pdev) | |||
335 | * touch a register even if nothing was active before; trust | 340 | * touch a register even if nothing was active before; trust |
336 | * me, it's better this way. | 341 | * me, it's better this way. |
337 | */ | 342 | */ |
338 | mmpcam_power_up(&cam->mcam); | 343 | mmpcam_power_up_ctlr(cam); |
339 | return mccic_resume(&cam->mcam); | 344 | return mccic_resume(&cam->mcam); |
340 | } | 345 | } |
341 | 346 | ||
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index d7cd0f633f63..82ce50721de3 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c | |||
@@ -881,18 +881,7 @@ static struct i2c_driver msp_driver = { | |||
881 | .id_table = msp_id, | 881 | .id_table = msp_id, |
882 | }; | 882 | }; |
883 | 883 | ||
884 | static __init int init_msp(void) | 884 | module_i2c_driver(msp_driver); |
885 | { | ||
886 | return i2c_add_driver(&msp_driver); | ||
887 | } | ||
888 | |||
889 | static __exit void exit_msp(void) | ||
890 | { | ||
891 | i2c_del_driver(&msp_driver); | ||
892 | } | ||
893 | |||
894 | module_init(init_msp); | ||
895 | module_exit(exit_msp); | ||
896 | 885 | ||
897 | /* | 886 | /* |
898 | * Overrides for Emacs so that we follow Linus's tabbing style. | 887 | * Overrides for Emacs so that we follow Linus's tabbing style. |
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index 097c9d3d04a8..7e648183f157 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c | |||
@@ -730,18 +730,7 @@ static struct i2c_driver mt9m001_i2c_driver = { | |||
730 | .id_table = mt9m001_id, | 730 | .id_table = mt9m001_id, |
731 | }; | 731 | }; |
732 | 732 | ||
733 | static int __init mt9m001_mod_init(void) | 733 | module_i2c_driver(mt9m001_i2c_driver); |
734 | { | ||
735 | return i2c_add_driver(&mt9m001_i2c_driver); | ||
736 | } | ||
737 | |||
738 | static void __exit mt9m001_mod_exit(void) | ||
739 | { | ||
740 | i2c_del_driver(&mt9m001_i2c_driver); | ||
741 | } | ||
742 | |||
743 | module_init(mt9m001_mod_init); | ||
744 | module_exit(mt9m001_mod_exit); | ||
745 | 734 | ||
746 | MODULE_DESCRIPTION("Micron MT9M001 Camera driver"); | 735 | MODULE_DESCRIPTION("Micron MT9M001 Camera driver"); |
747 | MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>"); | 736 | MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>"); |
diff --git a/drivers/media/video/mt9m032.c b/drivers/media/video/mt9m032.c new file mode 100644 index 000000000000..7636672c3548 --- /dev/null +++ b/drivers/media/video/mt9m032.c | |||
@@ -0,0 +1,868 @@ | |||
1 | /* | ||
2 | * Driver for MT9M032 CMOS Image Sensor from Micron | ||
3 | * | ||
4 | * Copyright (C) 2010-2011 Lund Engineering | ||
5 | * Contact: Gil Lund <gwlund@lundeng.com> | ||
6 | * Author: Martin Hostettler <martin@neutronstar.dyndns.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | */ | ||
22 | |||
23 | #include <linux/delay.h> | ||
24 | #include <linux/i2c.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/math64.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/mutex.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/v4l2-mediabus.h> | ||
32 | |||
33 | #include <media/media-entity.h> | ||
34 | #include <media/mt9m032.h> | ||
35 | #include <media/v4l2-ctrls.h> | ||
36 | #include <media/v4l2-device.h> | ||
37 | #include <media/v4l2-subdev.h> | ||
38 | |||
39 | #include "aptina-pll.h" | ||
40 | |||
41 | /* | ||
42 | * width and height include active boundary and black parts | ||
43 | * | ||
44 | * column 0- 15 active boundary | ||
45 | * column 16-1455 image | ||
46 | * column 1456-1471 active boundary | ||
47 | * column 1472-1599 black | ||
48 | * | ||
49 | * row 0- 51 black | ||
50 | * row 53- 59 active boundary | ||
51 | * row 60-1139 image | ||
52 | * row 1140-1147 active boundary | ||
53 | * row 1148-1151 black | ||
54 | */ | ||
55 | |||
56 | #define MT9M032_PIXEL_ARRAY_WIDTH 1600 | ||
57 | #define MT9M032_PIXEL_ARRAY_HEIGHT 1152 | ||
58 | |||
59 | #define MT9M032_CHIP_VERSION 0x00 | ||
60 | #define MT9M032_CHIP_VERSION_VALUE 0x1402 | ||
61 | #define MT9M032_ROW_START 0x01 | ||
62 | #define MT9M032_ROW_START_MIN 0 | ||
63 | #define MT9M032_ROW_START_MAX 1152 | ||
64 | #define MT9M032_ROW_START_DEF 60 | ||
65 | #define MT9M032_COLUMN_START 0x02 | ||
66 | #define MT9M032_COLUMN_START_MIN 0 | ||
67 | #define MT9M032_COLUMN_START_MAX 1600 | ||
68 | #define MT9M032_COLUMN_START_DEF 16 | ||
69 | #define MT9M032_ROW_SIZE 0x03 | ||
70 | #define MT9M032_ROW_SIZE_MIN 32 | ||
71 | #define MT9M032_ROW_SIZE_MAX 1152 | ||
72 | #define MT9M032_ROW_SIZE_DEF 1080 | ||
73 | #define MT9M032_COLUMN_SIZE 0x04 | ||
74 | #define MT9M032_COLUMN_SIZE_MIN 32 | ||
75 | #define MT9M032_COLUMN_SIZE_MAX 1600 | ||
76 | #define MT9M032_COLUMN_SIZE_DEF 1440 | ||
77 | #define MT9M032_HBLANK 0x05 | ||
78 | #define MT9M032_VBLANK 0x06 | ||
79 | #define MT9M032_VBLANK_MAX 0x7ff | ||
80 | #define MT9M032_SHUTTER_WIDTH_HIGH 0x08 | ||
81 | #define MT9M032_SHUTTER_WIDTH_LOW 0x09 | ||
82 | #define MT9M032_SHUTTER_WIDTH_MIN 1 | ||
83 | #define MT9M032_SHUTTER_WIDTH_MAX 1048575 | ||
84 | #define MT9M032_SHUTTER_WIDTH_DEF 1943 | ||
85 | #define MT9M032_PIX_CLK_CTRL 0x0a | ||
86 | #define MT9M032_PIX_CLK_CTRL_INV_PIXCLK 0x8000 | ||
87 | #define MT9M032_RESTART 0x0b | ||
88 | #define MT9M032_RESET 0x0d | ||
89 | #define MT9M032_PLL_CONFIG1 0x11 | ||
90 | #define MT9M032_PLL_CONFIG1_OUTDIV_MASK 0x3f | ||
91 | #define MT9M032_PLL_CONFIG1_MUL_SHIFT 8 | ||
92 | #define MT9M032_READ_MODE1 0x1e | ||
93 | #define MT9M032_READ_MODE2 0x20 | ||
94 | #define MT9M032_READ_MODE2_VFLIP_SHIFT 15 | ||
95 | #define MT9M032_READ_MODE2_HFLIP_SHIFT 14 | ||
96 | #define MT9M032_READ_MODE2_ROW_BLC 0x40 | ||
97 | #define MT9M032_GAIN_GREEN1 0x2b | ||
98 | #define MT9M032_GAIN_BLUE 0x2c | ||
99 | #define MT9M032_GAIN_RED 0x2d | ||
100 | #define MT9M032_GAIN_GREEN2 0x2e | ||
101 | |||
102 | /* write only */ | ||
103 | #define MT9M032_GAIN_ALL 0x35 | ||
104 | #define MT9M032_GAIN_DIGITAL_MASK 0x7f | ||
105 | #define MT9M032_GAIN_DIGITAL_SHIFT 8 | ||
106 | #define MT9M032_GAIN_AMUL_SHIFT 6 | ||
107 | #define MT9M032_GAIN_ANALOG_MASK 0x3f | ||
108 | #define MT9M032_FORMATTER1 0x9e | ||
109 | #define MT9M032_FORMATTER2 0x9f | ||
110 | #define MT9M032_FORMATTER2_DOUT_EN 0x1000 | ||
111 | #define MT9M032_FORMATTER2_PIXCLK_EN 0x2000 | ||
112 | |||
113 | /* | ||
114 | * The available MT9M032 datasheet is missing documentation for register 0x10 | ||
115 | * MT9P031 seems to be close enough, so use constants from that datasheet for | ||
116 | * now. | ||
117 | * But keep the name MT9P031 to remind us, that this isn't really confirmed | ||
118 | * for this sensor. | ||
119 | */ | ||
120 | #define MT9P031_PLL_CONTROL 0x10 | ||
121 | #define MT9P031_PLL_CONTROL_PWROFF 0x0050 | ||
122 | #define MT9P031_PLL_CONTROL_PWRON 0x0051 | ||
123 | #define MT9P031_PLL_CONTROL_USEPLL 0x0052 | ||
124 | #define MT9P031_PLL_CONFIG2 0x11 | ||
125 | #define MT9P031_PLL_CONFIG2_P1_DIV_MASK 0x1f | ||
126 | |||
127 | struct mt9m032 { | ||
128 | struct v4l2_subdev subdev; | ||
129 | struct media_pad pad; | ||
130 | struct mt9m032_platform_data *pdata; | ||
131 | |||
132 | unsigned int pix_clock; | ||
133 | |||
134 | struct v4l2_ctrl_handler ctrls; | ||
135 | struct { | ||
136 | struct v4l2_ctrl *hflip; | ||
137 | struct v4l2_ctrl *vflip; | ||
138 | }; | ||
139 | |||
140 | struct mutex lock; /* Protects streaming, format, interval and crop */ | ||
141 | |||
142 | bool streaming; | ||
143 | |||
144 | struct v4l2_mbus_framefmt format; | ||
145 | struct v4l2_rect crop; | ||
146 | struct v4l2_fract frame_interval; | ||
147 | }; | ||
148 | |||
149 | #define to_mt9m032(sd) container_of(sd, struct mt9m032, subdev) | ||
150 | #define to_dev(sensor) \ | ||
151 | (&((struct i2c_client *)v4l2_get_subdevdata(&(sensor)->subdev))->dev) | ||
152 | |||
153 | static int mt9m032_read(struct i2c_client *client, u8 reg) | ||
154 | { | ||
155 | return i2c_smbus_read_word_swapped(client, reg); | ||
156 | } | ||
157 | |||
158 | static int mt9m032_write(struct i2c_client *client, u8 reg, const u16 data) | ||
159 | { | ||
160 | return i2c_smbus_write_word_swapped(client, reg, data); | ||
161 | } | ||
162 | |||
163 | static u32 mt9m032_row_time(struct mt9m032 *sensor, unsigned int width) | ||
164 | { | ||
165 | unsigned int effective_width; | ||
166 | u32 ns; | ||
167 | |||
168 | effective_width = width + 716; /* empirical value */ | ||
169 | ns = div_u64(1000000000ULL * effective_width, sensor->pix_clock); | ||
170 | dev_dbg(to_dev(sensor), "MT9M032 line time: %u ns\n", ns); | ||
171 | return ns; | ||
172 | } | ||
173 | |||
174 | static int mt9m032_update_timing(struct mt9m032 *sensor, | ||
175 | struct v4l2_fract *interval) | ||
176 | { | ||
177 | struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); | ||
178 | struct v4l2_rect *crop = &sensor->crop; | ||
179 | unsigned int min_vblank; | ||
180 | unsigned int vblank; | ||
181 | u32 row_time; | ||
182 | |||
183 | if (!interval) | ||
184 | interval = &sensor->frame_interval; | ||
185 | |||
186 | row_time = mt9m032_row_time(sensor, crop->width); | ||
187 | |||
188 | vblank = div_u64(1000000000ULL * interval->numerator, | ||
189 | (u64)row_time * interval->denominator) | ||
190 | - crop->height; | ||
191 | |||
192 | if (vblank > MT9M032_VBLANK_MAX) { | ||
193 | /* hardware limits to 11 bit values */ | ||
194 | interval->denominator = 1000; | ||
195 | interval->numerator = | ||
196 | div_u64((crop->height + MT9M032_VBLANK_MAX) * | ||
197 | (u64)row_time * interval->denominator, | ||
198 | 1000000000ULL); | ||
199 | vblank = div_u64(1000000000ULL * interval->numerator, | ||
200 | (u64)row_time * interval->denominator) | ||
201 | - crop->height; | ||
202 | } | ||
203 | /* enforce minimal 1.6ms blanking time. */ | ||
204 | min_vblank = 1600000 / row_time; | ||
205 | vblank = clamp_t(unsigned int, vblank, min_vblank, MT9M032_VBLANK_MAX); | ||
206 | |||
207 | return mt9m032_write(client, MT9M032_VBLANK, vblank); | ||
208 | } | ||
209 | |||
210 | static int mt9m032_update_geom_timing(struct mt9m032 *sensor) | ||
211 | { | ||
212 | struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); | ||
213 | int ret; | ||
214 | |||
215 | ret = mt9m032_write(client, MT9M032_COLUMN_SIZE, | ||
216 | sensor->crop.width - 1); | ||
217 | if (!ret) | ||
218 | ret = mt9m032_write(client, MT9M032_ROW_SIZE, | ||
219 | sensor->crop.height - 1); | ||
220 | if (!ret) | ||
221 | ret = mt9m032_write(client, MT9M032_COLUMN_START, | ||
222 | sensor->crop.left); | ||
223 | if (!ret) | ||
224 | ret = mt9m032_write(client, MT9M032_ROW_START, | ||
225 | sensor->crop.top); | ||
226 | if (!ret) | ||
227 | ret = mt9m032_update_timing(sensor, NULL); | ||
228 | return ret; | ||
229 | } | ||
230 | |||
231 | static int update_formatter2(struct mt9m032 *sensor, bool streaming) | ||
232 | { | ||
233 | struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); | ||
234 | u16 reg_val = MT9M032_FORMATTER2_DOUT_EN | ||
235 | | 0x0070; /* parts reserved! */ | ||
236 | /* possibly for changing to 14-bit mode */ | ||
237 | |||
238 | if (streaming) | ||
239 | reg_val |= MT9M032_FORMATTER2_PIXCLK_EN; /* pixclock enable */ | ||
240 | |||
241 | return mt9m032_write(client, MT9M032_FORMATTER2, reg_val); | ||
242 | } | ||
243 | |||
244 | static int mt9m032_setup_pll(struct mt9m032 *sensor) | ||
245 | { | ||
246 | static const struct aptina_pll_limits limits = { | ||
247 | .ext_clock_min = 8000000, | ||
248 | .ext_clock_max = 16500000, | ||
249 | .int_clock_min = 2000000, | ||
250 | .int_clock_max = 24000000, | ||
251 | .out_clock_min = 322000000, | ||
252 | .out_clock_max = 693000000, | ||
253 | .pix_clock_max = 99000000, | ||
254 | .n_min = 1, | ||
255 | .n_max = 64, | ||
256 | .m_min = 16, | ||
257 | .m_max = 255, | ||
258 | .p1_min = 1, | ||
259 | .p1_max = 128, | ||
260 | }; | ||
261 | |||
262 | struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); | ||
263 | struct mt9m032_platform_data *pdata = sensor->pdata; | ||
264 | struct aptina_pll pll; | ||
265 | int ret; | ||
266 | |||
267 | pll.ext_clock = pdata->ext_clock; | ||
268 | pll.pix_clock = pdata->pix_clock; | ||
269 | |||
270 | ret = aptina_pll_calculate(&client->dev, &limits, &pll); | ||
271 | if (ret < 0) | ||
272 | return ret; | ||
273 | |||
274 | sensor->pix_clock = pdata->pix_clock; | ||
275 | |||
276 | ret = mt9m032_write(client, MT9M032_PLL_CONFIG1, | ||
277 | (pll.m << MT9M032_PLL_CONFIG1_MUL_SHIFT) | ||
278 | | (pll.p1 - 1)); | ||
279 | if (!ret) | ||
280 | ret = mt9m032_write(client, MT9P031_PLL_CONFIG2, pll.n - 1); | ||
281 | if (!ret) | ||
282 | ret = mt9m032_write(client, MT9P031_PLL_CONTROL, | ||
283 | MT9P031_PLL_CONTROL_PWRON | | ||
284 | MT9P031_PLL_CONTROL_USEPLL); | ||
285 | if (!ret) /* more reserved, Continuous, Master Mode */ | ||
286 | ret = mt9m032_write(client, MT9M032_READ_MODE1, 0x8006); | ||
287 | if (!ret) /* Set 14-bit mode, select 7 divider */ | ||
288 | ret = mt9m032_write(client, MT9M032_FORMATTER1, 0x111e); | ||
289 | |||
290 | return ret; | ||
291 | } | ||
292 | |||
293 | /* ----------------------------------------------------------------------------- | ||
294 | * Subdev pad operations | ||
295 | */ | ||
296 | |||
297 | static int mt9m032_enum_mbus_code(struct v4l2_subdev *subdev, | ||
298 | struct v4l2_subdev_fh *fh, | ||
299 | struct v4l2_subdev_mbus_code_enum *code) | ||
300 | { | ||
301 | if (code->index != 0) | ||
302 | return -EINVAL; | ||
303 | |||
304 | code->code = V4L2_MBUS_FMT_Y8_1X8; | ||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static int mt9m032_enum_frame_size(struct v4l2_subdev *subdev, | ||
309 | struct v4l2_subdev_fh *fh, | ||
310 | struct v4l2_subdev_frame_size_enum *fse) | ||
311 | { | ||
312 | if (fse->index != 0 || fse->code != V4L2_MBUS_FMT_Y8_1X8) | ||
313 | return -EINVAL; | ||
314 | |||
315 | fse->min_width = MT9M032_COLUMN_SIZE_DEF; | ||
316 | fse->max_width = MT9M032_COLUMN_SIZE_DEF; | ||
317 | fse->min_height = MT9M032_ROW_SIZE_DEF; | ||
318 | fse->max_height = MT9M032_ROW_SIZE_DEF; | ||
319 | |||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | /** | ||
324 | * __mt9m032_get_pad_crop() - get crop rect | ||
325 | * @sensor: pointer to the sensor struct | ||
326 | * @fh: file handle for getting the try crop rect from | ||
327 | * @which: select try or active crop rect | ||
328 | * | ||
329 | * Returns a pointer the current active or fh relative try crop rect | ||
330 | */ | ||
331 | static struct v4l2_rect * | ||
332 | __mt9m032_get_pad_crop(struct mt9m032 *sensor, struct v4l2_subdev_fh *fh, | ||
333 | enum v4l2_subdev_format_whence which) | ||
334 | { | ||
335 | switch (which) { | ||
336 | case V4L2_SUBDEV_FORMAT_TRY: | ||
337 | return v4l2_subdev_get_try_crop(fh, 0); | ||
338 | case V4L2_SUBDEV_FORMAT_ACTIVE: | ||
339 | return &sensor->crop; | ||
340 | default: | ||
341 | return NULL; | ||
342 | } | ||
343 | } | ||
344 | |||
345 | /** | ||
346 | * __mt9m032_get_pad_format() - get format | ||
347 | * @sensor: pointer to the sensor struct | ||
348 | * @fh: file handle for getting the try format from | ||
349 | * @which: select try or active format | ||
350 | * | ||
351 | * Returns a pointer the current active or fh relative try format | ||
352 | */ | ||
353 | static struct v4l2_mbus_framefmt * | ||
354 | __mt9m032_get_pad_format(struct mt9m032 *sensor, struct v4l2_subdev_fh *fh, | ||
355 | enum v4l2_subdev_format_whence which) | ||
356 | { | ||
357 | switch (which) { | ||
358 | case V4L2_SUBDEV_FORMAT_TRY: | ||
359 | return v4l2_subdev_get_try_format(fh, 0); | ||
360 | case V4L2_SUBDEV_FORMAT_ACTIVE: | ||
361 | return &sensor->format; | ||
362 | default: | ||
363 | return NULL; | ||
364 | } | ||
365 | } | ||
366 | |||
367 | static int mt9m032_get_pad_format(struct v4l2_subdev *subdev, | ||
368 | struct v4l2_subdev_fh *fh, | ||
369 | struct v4l2_subdev_format *fmt) | ||
370 | { | ||
371 | struct mt9m032 *sensor = to_mt9m032(subdev); | ||
372 | |||
373 | mutex_lock(&sensor->lock); | ||
374 | fmt->format = *__mt9m032_get_pad_format(sensor, fh, fmt->which); | ||
375 | mutex_unlock(&sensor->lock); | ||
376 | |||
377 | return 0; | ||
378 | } | ||
379 | |||
380 | static int mt9m032_set_pad_format(struct v4l2_subdev *subdev, | ||
381 | struct v4l2_subdev_fh *fh, | ||
382 | struct v4l2_subdev_format *fmt) | ||
383 | { | ||
384 | struct mt9m032 *sensor = to_mt9m032(subdev); | ||
385 | int ret; | ||
386 | |||
387 | mutex_lock(&sensor->lock); | ||
388 | |||
389 | if (sensor->streaming && fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { | ||
390 | ret = -EBUSY; | ||
391 | goto done; | ||
392 | } | ||
393 | |||
394 | /* Scaling is not supported, the format is thus fixed. */ | ||
395 | ret = mt9m032_get_pad_format(subdev, fh, fmt); | ||
396 | |||
397 | done: | ||
398 | mutex_lock(&sensor->lock); | ||
399 | return ret; | ||
400 | } | ||
401 | |||
402 | static int mt9m032_get_pad_crop(struct v4l2_subdev *subdev, | ||
403 | struct v4l2_subdev_fh *fh, | ||
404 | struct v4l2_subdev_crop *crop) | ||
405 | { | ||
406 | struct mt9m032 *sensor = to_mt9m032(subdev); | ||
407 | |||
408 | mutex_lock(&sensor->lock); | ||
409 | crop->rect = *__mt9m032_get_pad_crop(sensor, fh, crop->which); | ||
410 | mutex_unlock(&sensor->lock); | ||
411 | |||
412 | return 0; | ||
413 | } | ||
414 | |||
415 | static int mt9m032_set_pad_crop(struct v4l2_subdev *subdev, | ||
416 | struct v4l2_subdev_fh *fh, | ||
417 | struct v4l2_subdev_crop *crop) | ||
418 | { | ||
419 | struct mt9m032 *sensor = to_mt9m032(subdev); | ||
420 | struct v4l2_mbus_framefmt *format; | ||
421 | struct v4l2_rect *__crop; | ||
422 | struct v4l2_rect rect; | ||
423 | int ret = 0; | ||
424 | |||
425 | mutex_lock(&sensor->lock); | ||
426 | |||
427 | if (sensor->streaming && crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) { | ||
428 | ret = -EBUSY; | ||
429 | goto done; | ||
430 | } | ||
431 | |||
432 | /* Clamp the crop rectangle boundaries and align them to a multiple of 2 | ||
433 | * pixels to ensure a GRBG Bayer pattern. | ||
434 | */ | ||
435 | rect.left = clamp(ALIGN(crop->rect.left, 2), MT9M032_COLUMN_START_MIN, | ||
436 | MT9M032_COLUMN_START_MAX); | ||
437 | rect.top = clamp(ALIGN(crop->rect.top, 2), MT9M032_ROW_START_MIN, | ||
438 | MT9M032_ROW_START_MAX); | ||
439 | rect.width = clamp(ALIGN(crop->rect.width, 2), MT9M032_COLUMN_SIZE_MIN, | ||
440 | MT9M032_COLUMN_SIZE_MAX); | ||
441 | rect.height = clamp(ALIGN(crop->rect.height, 2), MT9M032_ROW_SIZE_MIN, | ||
442 | MT9M032_ROW_SIZE_MAX); | ||
443 | |||
444 | rect.width = min(rect.width, MT9M032_PIXEL_ARRAY_WIDTH - rect.left); | ||
445 | rect.height = min(rect.height, MT9M032_PIXEL_ARRAY_HEIGHT - rect.top); | ||
446 | |||
447 | __crop = __mt9m032_get_pad_crop(sensor, fh, crop->which); | ||
448 | |||
449 | if (rect.width != __crop->width || rect.height != __crop->height) { | ||
450 | /* Reset the output image size if the crop rectangle size has | ||
451 | * been modified. | ||
452 | */ | ||
453 | format = __mt9m032_get_pad_format(sensor, fh, crop->which); | ||
454 | format->width = rect.width; | ||
455 | format->height = rect.height; | ||
456 | } | ||
457 | |||
458 | *__crop = rect; | ||
459 | crop->rect = rect; | ||
460 | |||
461 | if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) | ||
462 | ret = mt9m032_update_geom_timing(sensor); | ||
463 | |||
464 | done: | ||
465 | mutex_unlock(&sensor->lock); | ||
466 | return ret; | ||
467 | } | ||
468 | |||
469 | static int mt9m032_get_frame_interval(struct v4l2_subdev *subdev, | ||
470 | struct v4l2_subdev_frame_interval *fi) | ||
471 | { | ||
472 | struct mt9m032 *sensor = to_mt9m032(subdev); | ||
473 | |||
474 | mutex_lock(&sensor->lock); | ||
475 | memset(fi, 0, sizeof(*fi)); | ||
476 | fi->interval = sensor->frame_interval; | ||
477 | mutex_unlock(&sensor->lock); | ||
478 | |||
479 | return 0; | ||
480 | } | ||
481 | |||
482 | static int mt9m032_set_frame_interval(struct v4l2_subdev *subdev, | ||
483 | struct v4l2_subdev_frame_interval *fi) | ||
484 | { | ||
485 | struct mt9m032 *sensor = to_mt9m032(subdev); | ||
486 | int ret; | ||
487 | |||
488 | mutex_lock(&sensor->lock); | ||
489 | |||
490 | if (sensor->streaming) { | ||
491 | ret = -EBUSY; | ||
492 | goto done; | ||
493 | } | ||
494 | |||
495 | /* Avoid divisions by 0. */ | ||
496 | if (fi->interval.denominator == 0) | ||
497 | fi->interval.denominator = 1; | ||
498 | |||
499 | ret = mt9m032_update_timing(sensor, &fi->interval); | ||
500 | if (!ret) | ||
501 | sensor->frame_interval = fi->interval; | ||
502 | |||
503 | done: | ||
504 | mutex_unlock(&sensor->lock); | ||
505 | return ret; | ||
506 | } | ||
507 | |||
508 | static int mt9m032_s_stream(struct v4l2_subdev *subdev, int streaming) | ||
509 | { | ||
510 | struct mt9m032 *sensor = to_mt9m032(subdev); | ||
511 | int ret; | ||
512 | |||
513 | mutex_lock(&sensor->lock); | ||
514 | ret = update_formatter2(sensor, streaming); | ||
515 | if (!ret) | ||
516 | sensor->streaming = streaming; | ||
517 | mutex_unlock(&sensor->lock); | ||
518 | |||
519 | return ret; | ||
520 | } | ||
521 | |||
522 | /* ----------------------------------------------------------------------------- | ||
523 | * V4L2 subdev core operations | ||
524 | */ | ||
525 | |||
526 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
527 | static int mt9m032_g_register(struct v4l2_subdev *sd, | ||
528 | struct v4l2_dbg_register *reg) | ||
529 | { | ||
530 | struct mt9m032 *sensor = to_mt9m032(sd); | ||
531 | struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); | ||
532 | int val; | ||
533 | |||
534 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) | ||
535 | return -EINVAL; | ||
536 | if (reg->match.addr != client->addr) | ||
537 | return -ENODEV; | ||
538 | |||
539 | val = mt9m032_read(client, reg->reg); | ||
540 | if (val < 0) | ||
541 | return -EIO; | ||
542 | |||
543 | reg->size = 2; | ||
544 | reg->val = val; | ||
545 | |||
546 | return 0; | ||
547 | } | ||
548 | |||
549 | static int mt9m032_s_register(struct v4l2_subdev *sd, | ||
550 | struct v4l2_dbg_register *reg) | ||
551 | { | ||
552 | struct mt9m032 *sensor = to_mt9m032(sd); | ||
553 | struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); | ||
554 | |||
555 | if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) | ||
556 | return -EINVAL; | ||
557 | |||
558 | if (reg->match.addr != client->addr) | ||
559 | return -ENODEV; | ||
560 | |||
561 | return mt9m032_write(client, reg->reg, reg->val); | ||
562 | } | ||
563 | #endif | ||
564 | |||
565 | /* ----------------------------------------------------------------------------- | ||
566 | * V4L2 subdev control operations | ||
567 | */ | ||
568 | |||
569 | static int update_read_mode2(struct mt9m032 *sensor, bool vflip, bool hflip) | ||
570 | { | ||
571 | struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); | ||
572 | int reg_val = (vflip << MT9M032_READ_MODE2_VFLIP_SHIFT) | ||
573 | | (hflip << MT9M032_READ_MODE2_HFLIP_SHIFT) | ||
574 | | MT9M032_READ_MODE2_ROW_BLC | ||
575 | | 0x0007; | ||
576 | |||
577 | return mt9m032_write(client, MT9M032_READ_MODE2, reg_val); | ||
578 | } | ||
579 | |||
580 | static int mt9m032_set_gain(struct mt9m032 *sensor, s32 val) | ||
581 | { | ||
582 | struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); | ||
583 | int digital_gain_val; /* in 1/8th (0..127) */ | ||
584 | int analog_mul; /* 0 or 1 */ | ||
585 | int analog_gain_val; /* in 1/16th. (0..63) */ | ||
586 | u16 reg_val; | ||
587 | |||
588 | digital_gain_val = 51; /* from setup example */ | ||
589 | |||
590 | if (val < 63) { | ||
591 | analog_mul = 0; | ||
592 | analog_gain_val = val; | ||
593 | } else { | ||
594 | analog_mul = 1; | ||
595 | analog_gain_val = val / 2; | ||
596 | } | ||
597 | |||
598 | /* a_gain = (1 + analog_mul) + (analog_gain_val + 1) / 16 */ | ||
599 | /* overall_gain = a_gain * (1 + digital_gain_val / 8) */ | ||
600 | |||
601 | reg_val = ((digital_gain_val & MT9M032_GAIN_DIGITAL_MASK) | ||
602 | << MT9M032_GAIN_DIGITAL_SHIFT) | ||
603 | | ((analog_mul & 1) << MT9M032_GAIN_AMUL_SHIFT) | ||
604 | | (analog_gain_val & MT9M032_GAIN_ANALOG_MASK); | ||
605 | |||
606 | return mt9m032_write(client, MT9M032_GAIN_ALL, reg_val); | ||
607 | } | ||
608 | |||
609 | static int mt9m032_try_ctrl(struct v4l2_ctrl *ctrl) | ||
610 | { | ||
611 | if (ctrl->id == V4L2_CID_GAIN && ctrl->val >= 63) { | ||
612 | /* round because of multiplier used for values >= 63 */ | ||
613 | ctrl->val &= ~1; | ||
614 | } | ||
615 | |||
616 | return 0; | ||
617 | } | ||
618 | |||
619 | static int mt9m032_set_ctrl(struct v4l2_ctrl *ctrl) | ||
620 | { | ||
621 | struct mt9m032 *sensor = | ||
622 | container_of(ctrl->handler, struct mt9m032, ctrls); | ||
623 | struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); | ||
624 | int ret; | ||
625 | |||
626 | switch (ctrl->id) { | ||
627 | case V4L2_CID_GAIN: | ||
628 | return mt9m032_set_gain(sensor, ctrl->val); | ||
629 | |||
630 | case V4L2_CID_HFLIP: | ||
631 | /* case V4L2_CID_VFLIP: -- In the same cluster */ | ||
632 | return update_read_mode2(sensor, sensor->vflip->val, | ||
633 | sensor->hflip->val); | ||
634 | |||
635 | case V4L2_CID_EXPOSURE: | ||
636 | ret = mt9m032_write(client, MT9M032_SHUTTER_WIDTH_HIGH, | ||
637 | (ctrl->val >> 16) & 0xffff); | ||
638 | if (ret < 0) | ||
639 | return ret; | ||
640 | |||
641 | return mt9m032_write(client, MT9M032_SHUTTER_WIDTH_LOW, | ||
642 | ctrl->val & 0xffff); | ||
643 | } | ||
644 | |||
645 | return 0; | ||
646 | } | ||
647 | |||
648 | static struct v4l2_ctrl_ops mt9m032_ctrl_ops = { | ||
649 | .s_ctrl = mt9m032_set_ctrl, | ||
650 | .try_ctrl = mt9m032_try_ctrl, | ||
651 | }; | ||
652 | |||
653 | /* -------------------------------------------------------------------------- */ | ||
654 | |||
655 | static const struct v4l2_subdev_core_ops mt9m032_core_ops = { | ||
656 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
657 | .g_register = mt9m032_g_register, | ||
658 | .s_register = mt9m032_s_register, | ||
659 | #endif | ||
660 | }; | ||
661 | |||
662 | static const struct v4l2_subdev_video_ops mt9m032_video_ops = { | ||
663 | .s_stream = mt9m032_s_stream, | ||
664 | .g_frame_interval = mt9m032_get_frame_interval, | ||
665 | .s_frame_interval = mt9m032_set_frame_interval, | ||
666 | }; | ||
667 | |||
668 | static const struct v4l2_subdev_pad_ops mt9m032_pad_ops = { | ||
669 | .enum_mbus_code = mt9m032_enum_mbus_code, | ||
670 | .enum_frame_size = mt9m032_enum_frame_size, | ||
671 | .get_fmt = mt9m032_get_pad_format, | ||
672 | .set_fmt = mt9m032_set_pad_format, | ||
673 | .set_crop = mt9m032_set_pad_crop, | ||
674 | .get_crop = mt9m032_get_pad_crop, | ||
675 | }; | ||
676 | |||
677 | static const struct v4l2_subdev_ops mt9m032_ops = { | ||
678 | .core = &mt9m032_core_ops, | ||
679 | .video = &mt9m032_video_ops, | ||
680 | .pad = &mt9m032_pad_ops, | ||
681 | }; | ||
682 | |||
683 | /* ----------------------------------------------------------------------------- | ||
684 | * Driver initialization and probing | ||
685 | */ | ||
686 | |||
687 | static int mt9m032_probe(struct i2c_client *client, | ||
688 | const struct i2c_device_id *devid) | ||
689 | { | ||
690 | struct i2c_adapter *adapter = client->adapter; | ||
691 | struct mt9m032 *sensor; | ||
692 | int chip_version; | ||
693 | int ret; | ||
694 | |||
695 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { | ||
696 | dev_warn(&client->dev, | ||
697 | "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); | ||
698 | return -EIO; | ||
699 | } | ||
700 | |||
701 | if (!client->dev.platform_data) | ||
702 | return -ENODEV; | ||
703 | |||
704 | sensor = kzalloc(sizeof(*sensor), GFP_KERNEL); | ||
705 | if (sensor == NULL) | ||
706 | return -ENOMEM; | ||
707 | |||
708 | mutex_init(&sensor->lock); | ||
709 | |||
710 | sensor->pdata = client->dev.platform_data; | ||
711 | |||
712 | v4l2_i2c_subdev_init(&sensor->subdev, client, &mt9m032_ops); | ||
713 | sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | ||
714 | |||
715 | chip_version = mt9m032_read(client, MT9M032_CHIP_VERSION); | ||
716 | if (chip_version != MT9M032_CHIP_VERSION_VALUE) { | ||
717 | dev_err(&client->dev, "MT9M032 not detected, wrong version " | ||
718 | "0x%04x\n", chip_version); | ||
719 | ret = -ENODEV; | ||
720 | goto error_sensor; | ||
721 | } | ||
722 | |||
723 | dev_info(&client->dev, "MT9M032 detected at address 0x%02x\n", | ||
724 | client->addr); | ||
725 | |||
726 | sensor->frame_interval.numerator = 1; | ||
727 | sensor->frame_interval.denominator = 30; | ||
728 | |||
729 | sensor->crop.left = MT9M032_COLUMN_START_DEF; | ||
730 | sensor->crop.top = MT9M032_ROW_START_DEF; | ||
731 | sensor->crop.width = MT9M032_COLUMN_SIZE_DEF; | ||
732 | sensor->crop.height = MT9M032_ROW_SIZE_DEF; | ||
733 | |||
734 | sensor->format.width = sensor->crop.width; | ||
735 | sensor->format.height = sensor->crop.height; | ||
736 | sensor->format.code = V4L2_MBUS_FMT_Y8_1X8; | ||
737 | sensor->format.field = V4L2_FIELD_NONE; | ||
738 | sensor->format.colorspace = V4L2_COLORSPACE_SRGB; | ||
739 | |||
740 | v4l2_ctrl_handler_init(&sensor->ctrls, 4); | ||
741 | |||
742 | v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops, | ||
743 | V4L2_CID_GAIN, 0, 127, 1, 64); | ||
744 | |||
745 | sensor->hflip = v4l2_ctrl_new_std(&sensor->ctrls, | ||
746 | &mt9m032_ctrl_ops, | ||
747 | V4L2_CID_HFLIP, 0, 1, 1, 0); | ||
748 | sensor->vflip = v4l2_ctrl_new_std(&sensor->ctrls, | ||
749 | &mt9m032_ctrl_ops, | ||
750 | V4L2_CID_VFLIP, 0, 1, 1, 0); | ||
751 | |||
752 | v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops, | ||
753 | V4L2_CID_EXPOSURE, MT9M032_SHUTTER_WIDTH_MIN, | ||
754 | MT9M032_SHUTTER_WIDTH_MAX, 1, | ||
755 | MT9M032_SHUTTER_WIDTH_DEF); | ||
756 | |||
757 | if (sensor->ctrls.error) { | ||
758 | ret = sensor->ctrls.error; | ||
759 | dev_err(&client->dev, "control initialization error %d\n", ret); | ||
760 | goto error_ctrl; | ||
761 | } | ||
762 | |||
763 | v4l2_ctrl_cluster(2, &sensor->hflip); | ||
764 | |||
765 | sensor->subdev.ctrl_handler = &sensor->ctrls; | ||
766 | sensor->pad.flags = MEDIA_PAD_FL_SOURCE; | ||
767 | ret = media_entity_init(&sensor->subdev.entity, 1, &sensor->pad, 0); | ||
768 | if (ret < 0) | ||
769 | goto error_ctrl; | ||
770 | |||
771 | ret = mt9m032_write(client, MT9M032_RESET, 1); /* reset on */ | ||
772 | if (ret < 0) | ||
773 | goto error_entity; | ||
774 | mt9m032_write(client, MT9M032_RESET, 0); /* reset off */ | ||
775 | if (ret < 0) | ||
776 | goto error_entity; | ||
777 | |||
778 | ret = mt9m032_setup_pll(sensor); | ||
779 | if (ret < 0) | ||
780 | goto error_entity; | ||
781 | usleep_range(10000, 11000); | ||
782 | |||
783 | ret = v4l2_ctrl_handler_setup(&sensor->ctrls); | ||
784 | if (ret < 0) | ||
785 | goto error_entity; | ||
786 | |||
787 | /* SIZE */ | ||
788 | ret = mt9m032_update_geom_timing(sensor); | ||
789 | if (ret < 0) | ||
790 | goto error_entity; | ||
791 | |||
792 | ret = mt9m032_write(client, 0x41, 0x0000); /* reserved !!! */ | ||
793 | if (ret < 0) | ||
794 | goto error_entity; | ||
795 | ret = mt9m032_write(client, 0x42, 0x0003); /* reserved !!! */ | ||
796 | if (ret < 0) | ||
797 | goto error_entity; | ||
798 | ret = mt9m032_write(client, 0x43, 0x0003); /* reserved !!! */ | ||
799 | if (ret < 0) | ||
800 | goto error_entity; | ||
801 | ret = mt9m032_write(client, 0x7f, 0x0000); /* reserved !!! */ | ||
802 | if (ret < 0) | ||
803 | goto error_entity; | ||
804 | if (sensor->pdata->invert_pixclock) { | ||
805 | ret = mt9m032_write(client, MT9M032_PIX_CLK_CTRL, | ||
806 | MT9M032_PIX_CLK_CTRL_INV_PIXCLK); | ||
807 | if (ret < 0) | ||
808 | goto error_entity; | ||
809 | } | ||
810 | |||
811 | ret = mt9m032_write(client, MT9M032_RESTART, 1); /* Restart on */ | ||
812 | if (ret < 0) | ||
813 | goto error_entity; | ||
814 | msleep(100); | ||
815 | ret = mt9m032_write(client, MT9M032_RESTART, 0); /* Restart off */ | ||
816 | if (ret < 0) | ||
817 | goto error_entity; | ||
818 | msleep(100); | ||
819 | ret = update_formatter2(sensor, false); | ||
820 | if (ret < 0) | ||
821 | goto error_entity; | ||
822 | |||
823 | return ret; | ||
824 | |||
825 | error_entity: | ||
826 | media_entity_cleanup(&sensor->subdev.entity); | ||
827 | error_ctrl: | ||
828 | v4l2_ctrl_handler_free(&sensor->ctrls); | ||
829 | error_sensor: | ||
830 | mutex_destroy(&sensor->lock); | ||
831 | kfree(sensor); | ||
832 | return ret; | ||
833 | } | ||
834 | |||
835 | static int mt9m032_remove(struct i2c_client *client) | ||
836 | { | ||
837 | struct v4l2_subdev *subdev = i2c_get_clientdata(client); | ||
838 | struct mt9m032 *sensor = to_mt9m032(subdev); | ||
839 | |||
840 | v4l2_device_unregister_subdev(&sensor->subdev); | ||
841 | v4l2_ctrl_handler_free(&sensor->ctrls); | ||
842 | media_entity_cleanup(&sensor->subdev.entity); | ||
843 | mutex_destroy(&sensor->lock); | ||
844 | kfree(sensor); | ||
845 | return 0; | ||
846 | } | ||
847 | |||
848 | static const struct i2c_device_id mt9m032_id_table[] = { | ||
849 | { MT9M032_NAME, 0 }, | ||
850 | { } | ||
851 | }; | ||
852 | |||
853 | MODULE_DEVICE_TABLE(i2c, mt9m032_id_table); | ||
854 | |||
855 | static struct i2c_driver mt9m032_i2c_driver = { | ||
856 | .driver = { | ||
857 | .name = MT9M032_NAME, | ||
858 | }, | ||
859 | .probe = mt9m032_probe, | ||
860 | .remove = mt9m032_remove, | ||
861 | .id_table = mt9m032_id_table, | ||
862 | }; | ||
863 | |||
864 | module_i2c_driver(mt9m032_i2c_driver); | ||
865 | |||
866 | MODULE_AUTHOR("Martin Hostettler <martin@neutronstar.dyndns.org>"); | ||
867 | MODULE_DESCRIPTION("MT9M032 camera sensor driver"); | ||
868 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index bee65bff46e8..b0c529964329 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/video/mt9m111.c | |||
@@ -1008,18 +1008,7 @@ static struct i2c_driver mt9m111_i2c_driver = { | |||
1008 | .id_table = mt9m111_id, | 1008 | .id_table = mt9m111_id, |
1009 | }; | 1009 | }; |
1010 | 1010 | ||
1011 | static int __init mt9m111_mod_init(void) | 1011 | module_i2c_driver(mt9m111_i2c_driver); |
1012 | { | ||
1013 | return i2c_add_driver(&mt9m111_i2c_driver); | ||
1014 | } | ||
1015 | |||
1016 | static void __exit mt9m111_mod_exit(void) | ||
1017 | { | ||
1018 | i2c_del_driver(&mt9m111_i2c_driver); | ||
1019 | } | ||
1020 | |||
1021 | module_init(mt9m111_mod_init); | ||
1022 | module_exit(mt9m111_mod_exit); | ||
1023 | 1012 | ||
1024 | MODULE_DESCRIPTION("Micron/Aptina MT9M111/MT9M112/MT9M131 Camera driver"); | 1013 | MODULE_DESCRIPTION("Micron/Aptina MT9M111/MT9M112/MT9M131 Camera driver"); |
1025 | MODULE_AUTHOR("Robert Jarzmik"); | 1014 | MODULE_AUTHOR("Robert Jarzmik"); |
diff --git a/drivers/media/video/mt9p031.c b/drivers/media/video/mt9p031.c index 93c3ec7426e8..c81eaf4fbe01 100644 --- a/drivers/media/video/mt9p031.c +++ b/drivers/media/video/mt9p031.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/log2.h> | 19 | #include <linux/log2.h> |
20 | #include <linux/pm.h> | 20 | #include <linux/pm.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <media/v4l2-subdev.h> | ||
23 | #include <linux/videodev2.h> | 22 | #include <linux/videodev2.h> |
24 | 23 | ||
25 | #include <media/mt9p031.h> | 24 | #include <media/mt9p031.h> |
@@ -28,6 +27,8 @@ | |||
28 | #include <media/v4l2-device.h> | 27 | #include <media/v4l2-device.h> |
29 | #include <media/v4l2-subdev.h> | 28 | #include <media/v4l2-subdev.h> |
30 | 29 | ||
30 | #include "aptina-pll.h" | ||
31 | |||
31 | #define MT9P031_PIXEL_ARRAY_WIDTH 2752 | 32 | #define MT9P031_PIXEL_ARRAY_WIDTH 2752 |
32 | #define MT9P031_PIXEL_ARRAY_HEIGHT 2004 | 33 | #define MT9P031_PIXEL_ARRAY_HEIGHT 2004 |
33 | 34 | ||
@@ -98,14 +99,6 @@ | |||
98 | #define MT9P031_TEST_PATTERN_RED 0xa2 | 99 | #define MT9P031_TEST_PATTERN_RED 0xa2 |
99 | #define MT9P031_TEST_PATTERN_BLUE 0xa3 | 100 | #define MT9P031_TEST_PATTERN_BLUE 0xa3 |
100 | 101 | ||
101 | struct mt9p031_pll_divs { | ||
102 | u32 ext_freq; | ||
103 | u32 target_freq; | ||
104 | u8 m; | ||
105 | u8 n; | ||
106 | u8 p1; | ||
107 | }; | ||
108 | |||
109 | struct mt9p031 { | 102 | struct mt9p031 { |
110 | struct v4l2_subdev subdev; | 103 | struct v4l2_subdev subdev; |
111 | struct media_pad pad; | 104 | struct media_pad pad; |
@@ -115,10 +108,8 @@ struct mt9p031 { | |||
115 | struct mt9p031_platform_data *pdata; | 108 | struct mt9p031_platform_data *pdata; |
116 | struct mutex power_lock; /* lock to protect power_count */ | 109 | struct mutex power_lock; /* lock to protect power_count */ |
117 | int power_count; | 110 | int power_count; |
118 | u16 xskip; | ||
119 | u16 yskip; | ||
120 | 111 | ||
121 | const struct mt9p031_pll_divs *pll; | 112 | struct aptina_pll pll; |
122 | 113 | ||
123 | /* Registers cache */ | 114 | /* Registers cache */ |
124 | u16 output_control; | 115 | u16 output_control; |
@@ -186,33 +177,31 @@ static int mt9p031_reset(struct mt9p031 *mt9p031) | |||
186 | 0); | 177 | 0); |
187 | } | 178 | } |
188 | 179 | ||
189 | /* | 180 | static int mt9p031_pll_setup(struct mt9p031 *mt9p031) |
190 | * This static table uses ext_freq and vdd_io values to select suitable | ||
191 | * PLL dividers m, n and p1 which have been calculated as specifiec in p36 | ||
192 | * of Aptina's mt9p031 datasheet. New values should be added here. | ||
193 | */ | ||
194 | static const struct mt9p031_pll_divs mt9p031_divs[] = { | ||
195 | /* ext_freq target_freq m n p1 */ | ||
196 | {21000000, 48000000, 26, 2, 6} | ||
197 | }; | ||
198 | |||
199 | static int mt9p031_pll_get_divs(struct mt9p031 *mt9p031) | ||
200 | { | 181 | { |
182 | static const struct aptina_pll_limits limits = { | ||
183 | .ext_clock_min = 6000000, | ||
184 | .ext_clock_max = 27000000, | ||
185 | .int_clock_min = 2000000, | ||
186 | .int_clock_max = 13500000, | ||
187 | .out_clock_min = 180000000, | ||
188 | .out_clock_max = 360000000, | ||
189 | .pix_clock_max = 96000000, | ||
190 | .n_min = 1, | ||
191 | .n_max = 64, | ||
192 | .m_min = 16, | ||
193 | .m_max = 255, | ||
194 | .p1_min = 1, | ||
195 | .p1_max = 128, | ||
196 | }; | ||
197 | |||
201 | struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); | 198 | struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); |
202 | int i; | 199 | struct mt9p031_platform_data *pdata = mt9p031->pdata; |
203 | 200 | ||
204 | for (i = 0; i < ARRAY_SIZE(mt9p031_divs); i++) { | 201 | mt9p031->pll.ext_clock = pdata->ext_freq; |
205 | if (mt9p031_divs[i].ext_freq == mt9p031->pdata->ext_freq && | 202 | mt9p031->pll.pix_clock = pdata->target_freq; |
206 | mt9p031_divs[i].target_freq == mt9p031->pdata->target_freq) { | ||
207 | mt9p031->pll = &mt9p031_divs[i]; | ||
208 | return 0; | ||
209 | } | ||
210 | } | ||
211 | 203 | ||
212 | dev_err(&client->dev, "Couldn't find PLL dividers for ext_freq = %d, " | 204 | return aptina_pll_calculate(&client->dev, &limits, &mt9p031->pll); |
213 | "target_freq = %d\n", mt9p031->pdata->ext_freq, | ||
214 | mt9p031->pdata->target_freq); | ||
215 | return -EINVAL; | ||
216 | } | 205 | } |
217 | 206 | ||
218 | static int mt9p031_pll_enable(struct mt9p031 *mt9p031) | 207 | static int mt9p031_pll_enable(struct mt9p031 *mt9p031) |
@@ -226,11 +215,11 @@ static int mt9p031_pll_enable(struct mt9p031 *mt9p031) | |||
226 | return ret; | 215 | return ret; |
227 | 216 | ||
228 | ret = mt9p031_write(client, MT9P031_PLL_CONFIG_1, | 217 | ret = mt9p031_write(client, MT9P031_PLL_CONFIG_1, |
229 | (mt9p031->pll->m << 8) | (mt9p031->pll->n - 1)); | 218 | (mt9p031->pll.m << 8) | (mt9p031->pll.n - 1)); |
230 | if (ret < 0) | 219 | if (ret < 0) |
231 | return ret; | 220 | return ret; |
232 | 221 | ||
233 | ret = mt9p031_write(client, MT9P031_PLL_CONFIG_2, mt9p031->pll->p1 - 1); | 222 | ret = mt9p031_write(client, MT9P031_PLL_CONFIG_2, mt9p031->pll.p1 - 1); |
234 | if (ret < 0) | 223 | if (ret < 0) |
235 | return ret; | 224 | return ret; |
236 | 225 | ||
@@ -785,8 +774,6 @@ static int mt9p031_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) | |||
785 | format->field = V4L2_FIELD_NONE; | 774 | format->field = V4L2_FIELD_NONE; |
786 | format->colorspace = V4L2_COLORSPACE_SRGB; | 775 | format->colorspace = V4L2_COLORSPACE_SRGB; |
787 | 776 | ||
788 | mt9p031->xskip = 1; | ||
789 | mt9p031->yskip = 1; | ||
790 | return mt9p031_set_power(subdev, 1); | 777 | return mt9p031_set_power(subdev, 1); |
791 | } | 778 | } |
792 | 779 | ||
@@ -905,7 +892,7 @@ static int mt9p031_probe(struct i2c_client *client, | |||
905 | mt9p031->format.field = V4L2_FIELD_NONE; | 892 | mt9p031->format.field = V4L2_FIELD_NONE; |
906 | mt9p031->format.colorspace = V4L2_COLORSPACE_SRGB; | 893 | mt9p031->format.colorspace = V4L2_COLORSPACE_SRGB; |
907 | 894 | ||
908 | ret = mt9p031_pll_get_divs(mt9p031); | 895 | ret = mt9p031_pll_setup(mt9p031); |
909 | 896 | ||
910 | done: | 897 | done: |
911 | if (ret < 0) { | 898 | if (ret < 0) { |
@@ -945,18 +932,7 @@ static struct i2c_driver mt9p031_i2c_driver = { | |||
945 | .id_table = mt9p031_id, | 932 | .id_table = mt9p031_id, |
946 | }; | 933 | }; |
947 | 934 | ||
948 | static int __init mt9p031_mod_init(void) | 935 | module_i2c_driver(mt9p031_i2c_driver); |
949 | { | ||
950 | return i2c_add_driver(&mt9p031_i2c_driver); | ||
951 | } | ||
952 | |||
953 | static void __exit mt9p031_mod_exit(void) | ||
954 | { | ||
955 | i2c_del_driver(&mt9p031_i2c_driver); | ||
956 | } | ||
957 | |||
958 | module_init(mt9p031_mod_init); | ||
959 | module_exit(mt9p031_mod_exit); | ||
960 | 936 | ||
961 | MODULE_DESCRIPTION("Aptina MT9P031 Camera driver"); | 937 | MODULE_DESCRIPTION("Aptina MT9P031 Camera driver"); |
962 | MODULE_AUTHOR("Bastian Hecht <hechtb@gmail.com>"); | 938 | MODULE_AUTHOR("Bastian Hecht <hechtb@gmail.com>"); |
diff --git a/drivers/media/video/mt9t001.c b/drivers/media/video/mt9t001.c index cd81d04a529e..49ca3cbfc6f1 100644 --- a/drivers/media/video/mt9t001.c +++ b/drivers/media/video/mt9t001.c | |||
@@ -817,18 +817,7 @@ static struct i2c_driver mt9t001_driver = { | |||
817 | .id_table = mt9t001_id, | 817 | .id_table = mt9t001_id, |
818 | }; | 818 | }; |
819 | 819 | ||
820 | static int __init mt9t001_init(void) | 820 | module_i2c_driver(mt9t001_driver); |
821 | { | ||
822 | return i2c_add_driver(&mt9t001_driver); | ||
823 | } | ||
824 | |||
825 | static void __exit mt9t001_exit(void) | ||
826 | { | ||
827 | i2c_del_driver(&mt9t001_driver); | ||
828 | } | ||
829 | |||
830 | module_init(mt9t001_init); | ||
831 | module_exit(mt9t001_exit); | ||
832 | 821 | ||
833 | MODULE_DESCRIPTION("Aptina (Micron) MT9T001 Camera driver"); | 822 | MODULE_DESCRIPTION("Aptina (Micron) MT9T001 Camera driver"); |
834 | MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); | 823 | MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); |
diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c index 84add1aef139..1415074138a5 100644 --- a/drivers/media/video/mt9t031.c +++ b/drivers/media/video/mt9t031.c | |||
@@ -850,18 +850,7 @@ static struct i2c_driver mt9t031_i2c_driver = { | |||
850 | .id_table = mt9t031_id, | 850 | .id_table = mt9t031_id, |
851 | }; | 851 | }; |
852 | 852 | ||
853 | static int __init mt9t031_mod_init(void) | 853 | module_i2c_driver(mt9t031_i2c_driver); |
854 | { | ||
855 | return i2c_add_driver(&mt9t031_i2c_driver); | ||
856 | } | ||
857 | |||
858 | static void __exit mt9t031_mod_exit(void) | ||
859 | { | ||
860 | i2c_del_driver(&mt9t031_i2c_driver); | ||
861 | } | ||
862 | |||
863 | module_init(mt9t031_mod_init); | ||
864 | module_exit(mt9t031_mod_exit); | ||
865 | 854 | ||
866 | MODULE_DESCRIPTION("Micron MT9T031 Camera driver"); | 855 | MODULE_DESCRIPTION("Micron MT9T031 Camera driver"); |
867 | MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>"); | 856 | MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>"); |
diff --git a/drivers/media/video/mt9t112.c b/drivers/media/video/mt9t112.c index 7b34b11daf24..8d1445f12708 100644 --- a/drivers/media/video/mt9t112.c +++ b/drivers/media/video/mt9t112.c | |||
@@ -1117,21 +1117,7 @@ static struct i2c_driver mt9t112_i2c_driver = { | |||
1117 | .id_table = mt9t112_id, | 1117 | .id_table = mt9t112_id, |
1118 | }; | 1118 | }; |
1119 | 1119 | ||
1120 | /************************************************************************ | 1120 | module_i2c_driver(mt9t112_i2c_driver); |
1121 | module function | ||
1122 | ************************************************************************/ | ||
1123 | static int __init mt9t112_module_init(void) | ||
1124 | { | ||
1125 | return i2c_add_driver(&mt9t112_i2c_driver); | ||
1126 | } | ||
1127 | |||
1128 | static void __exit mt9t112_module_exit(void) | ||
1129 | { | ||
1130 | i2c_del_driver(&mt9t112_i2c_driver); | ||
1131 | } | ||
1132 | |||
1133 | module_init(mt9t112_module_init); | ||
1134 | module_exit(mt9t112_module_exit); | ||
1135 | 1121 | ||
1136 | MODULE_DESCRIPTION("SoC Camera driver for mt9t112"); | 1122 | MODULE_DESCRIPTION("SoC Camera driver for mt9t112"); |
1137 | MODULE_AUTHOR("Kuninori Morimoto"); | 1123 | MODULE_AUTHOR("Kuninori Morimoto"); |
diff --git a/drivers/media/video/mt9v011.c b/drivers/media/video/mt9v011.c index db74dd27c722..6bf01ad62765 100644 --- a/drivers/media/video/mt9v011.c +++ b/drivers/media/video/mt9v011.c | |||
@@ -709,15 +709,4 @@ static struct i2c_driver mt9v011_driver = { | |||
709 | .id_table = mt9v011_id, | 709 | .id_table = mt9v011_id, |
710 | }; | 710 | }; |
711 | 711 | ||
712 | static __init int init_mt9v011(void) | 712 | module_i2c_driver(mt9v011_driver); |
713 | { | ||
714 | return i2c_add_driver(&mt9v011_driver); | ||
715 | } | ||
716 | |||
717 | static __exit void exit_mt9v011(void) | ||
718 | { | ||
719 | i2c_del_driver(&mt9v011_driver); | ||
720 | } | ||
721 | |||
722 | module_init(init_mt9v011); | ||
723 | module_exit(exit_mt9v011); | ||
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index 944940758fa3..bf63417adb8f 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c | |||
@@ -872,18 +872,7 @@ static struct i2c_driver mt9v022_i2c_driver = { | |||
872 | .id_table = mt9v022_id, | 872 | .id_table = mt9v022_id, |
873 | }; | 873 | }; |
874 | 874 | ||
875 | static int __init mt9v022_mod_init(void) | 875 | module_i2c_driver(mt9v022_i2c_driver); |
876 | { | ||
877 | return i2c_add_driver(&mt9v022_i2c_driver); | ||
878 | } | ||
879 | |||
880 | static void __exit mt9v022_mod_exit(void) | ||
881 | { | ||
882 | i2c_del_driver(&mt9v022_i2c_driver); | ||
883 | } | ||
884 | |||
885 | module_init(mt9v022_mod_init); | ||
886 | module_exit(mt9v022_mod_exit); | ||
887 | 876 | ||
888 | MODULE_DESCRIPTION("Micron MT9V022 Camera driver"); | 877 | MODULE_DESCRIPTION("Micron MT9V022 Camera driver"); |
889 | MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>"); | 878 | MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>"); |
diff --git a/drivers/media/video/mt9v032.c b/drivers/media/video/mt9v032.c index d90b982cc218..75e253a343c5 100644 --- a/drivers/media/video/mt9v032.c +++ b/drivers/media/video/mt9v032.c | |||
@@ -756,18 +756,7 @@ static struct i2c_driver mt9v032_driver = { | |||
756 | .id_table = mt9v032_id, | 756 | .id_table = mt9v032_id, |
757 | }; | 757 | }; |
758 | 758 | ||
759 | static int __init mt9v032_init(void) | 759 | module_i2c_driver(mt9v032_driver); |
760 | { | ||
761 | return i2c_add_driver(&mt9v032_driver); | ||
762 | } | ||
763 | |||
764 | static void __exit mt9v032_exit(void) | ||
765 | { | ||
766 | i2c_del_driver(&mt9v032_driver); | ||
767 | } | ||
768 | |||
769 | module_init(mt9v032_init); | ||
770 | module_exit(mt9v032_exit); | ||
771 | 760 | ||
772 | MODULE_DESCRIPTION("Aptina MT9V032 Camera driver"); | 761 | MODULE_DESCRIPTION("Aptina MT9V032 Camera driver"); |
773 | MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); | 762 | MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); |
diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c index 04aab0c538aa..18afaeeadb7b 100644 --- a/drivers/media/video/mx2_camera.c +++ b/drivers/media/video/mx2_camera.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2008, Sascha Hauer, Pengutronix | 4 | * Copyright (C) 2008, Sascha Hauer, Pengutronix |
5 | * Copyright (C) 2010, Baruch Siach, Orex Computed Radiography | 5 | * Copyright (C) 2010, Baruch Siach, Orex Computed Radiography |
6 | * Copyright (C) 2012, Javier Martin, Vista Silicon S.L. | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
@@ -18,6 +19,7 @@ | |||
18 | #include <linux/dma-mapping.h> | 19 | #include <linux/dma-mapping.h> |
19 | #include <linux/errno.h> | 20 | #include <linux/errno.h> |
20 | #include <linux/fs.h> | 21 | #include <linux/fs.h> |
22 | #include <linux/gcd.h> | ||
21 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
22 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
23 | #include <linux/mm.h> | 25 | #include <linux/mm.h> |
@@ -30,17 +32,14 @@ | |||
30 | 32 | ||
31 | #include <media/v4l2-common.h> | 33 | #include <media/v4l2-common.h> |
32 | #include <media/v4l2-dev.h> | 34 | #include <media/v4l2-dev.h> |
33 | #include <media/videobuf-core.h> | 35 | #include <media/videobuf2-core.h> |
34 | #include <media/videobuf-dma-contig.h> | 36 | #include <media/videobuf2-dma-contig.h> |
35 | #include <media/soc_camera.h> | 37 | #include <media/soc_camera.h> |
36 | #include <media/soc_mediabus.h> | 38 | #include <media/soc_mediabus.h> |
37 | 39 | ||
38 | #include <linux/videodev2.h> | 40 | #include <linux/videodev2.h> |
39 | 41 | ||
40 | #include <mach/mx2_cam.h> | 42 | #include <mach/mx2_cam.h> |
41 | #ifdef CONFIG_MACH_MX27 | ||
42 | #include <mach/dma-mx1-mx2.h> | ||
43 | #endif | ||
44 | #include <mach/hardware.h> | 43 | #include <mach/hardware.h> |
45 | 44 | ||
46 | #include <asm/dma.h> | 45 | #include <asm/dma.h> |
@@ -206,10 +205,23 @@ | |||
206 | #define PRP_INTR_LBOVF (1 << 7) | 205 | #define PRP_INTR_LBOVF (1 << 7) |
207 | #define PRP_INTR_CH2OVF (1 << 8) | 206 | #define PRP_INTR_CH2OVF (1 << 8) |
208 | 207 | ||
209 | #define mx27_camera_emma(pcdev) (cpu_is_mx27() && pcdev->use_emma) | 208 | /* Resizing registers */ |
209 | #define PRP_RZ_VALID_TBL_LEN(x) ((x) << 24) | ||
210 | #define PRP_RZ_VALID_BILINEAR (1 << 31) | ||
210 | 211 | ||
211 | #define MAX_VIDEO_MEM 16 | 212 | #define MAX_VIDEO_MEM 16 |
212 | 213 | ||
214 | #define RESIZE_NUM_MIN 1 | ||
215 | #define RESIZE_NUM_MAX 20 | ||
216 | #define BC_COEF 3 | ||
217 | #define SZ_COEF (1 << BC_COEF) | ||
218 | |||
219 | #define RESIZE_DIR_H 0 | ||
220 | #define RESIZE_DIR_V 1 | ||
221 | |||
222 | #define RESIZE_ALGO_BILINEAR 0 | ||
223 | #define RESIZE_ALGO_AVERAGING 1 | ||
224 | |||
213 | struct mx2_prp_cfg { | 225 | struct mx2_prp_cfg { |
214 | int channel; | 226 | int channel; |
215 | u32 in_fmt; | 227 | u32 in_fmt; |
@@ -219,6 +231,13 @@ struct mx2_prp_cfg { | |||
219 | u32 irq_flags; | 231 | u32 irq_flags; |
220 | }; | 232 | }; |
221 | 233 | ||
234 | /* prp resizing parameters */ | ||
235 | struct emma_prp_resize { | ||
236 | int algo; /* type of algorithm used */ | ||
237 | int len; /* number of coefficients */ | ||
238 | unsigned char s[RESIZE_NUM_MAX]; /* table of coefficients */ | ||
239 | }; | ||
240 | |||
222 | /* prp configuration for a client-host fmt pair */ | 241 | /* prp configuration for a client-host fmt pair */ |
223 | struct mx2_fmt_cfg { | 242 | struct mx2_fmt_cfg { |
224 | enum v4l2_mbus_pixelcode in_fmt; | 243 | enum v4l2_mbus_pixelcode in_fmt; |
@@ -226,6 +245,26 @@ struct mx2_fmt_cfg { | |||
226 | struct mx2_prp_cfg cfg; | 245 | struct mx2_prp_cfg cfg; |
227 | }; | 246 | }; |
228 | 247 | ||
248 | enum mx2_buffer_state { | ||
249 | MX2_STATE_QUEUED, | ||
250 | MX2_STATE_ACTIVE, | ||
251 | MX2_STATE_DONE, | ||
252 | }; | ||
253 | |||
254 | struct mx2_buf_internal { | ||
255 | struct list_head queue; | ||
256 | int bufnum; | ||
257 | bool discard; | ||
258 | }; | ||
259 | |||
260 | /* buffer for one video frame */ | ||
261 | struct mx2_buffer { | ||
262 | /* common v4l buffer stuff -- must be first */ | ||
263 | struct vb2_buffer vb; | ||
264 | enum mx2_buffer_state state; | ||
265 | struct mx2_buf_internal internal; | ||
266 | }; | ||
267 | |||
229 | struct mx2_camera_dev { | 268 | struct mx2_camera_dev { |
230 | struct device *dev; | 269 | struct device *dev; |
231 | struct soc_camera_host soc_host; | 270 | struct soc_camera_host soc_host; |
@@ -242,6 +281,7 @@ struct mx2_camera_dev { | |||
242 | 281 | ||
243 | struct list_head capture; | 282 | struct list_head capture; |
244 | struct list_head active_bufs; | 283 | struct list_head active_bufs; |
284 | struct list_head discard; | ||
245 | 285 | ||
246 | spinlock_t lock; | 286 | spinlock_t lock; |
247 | 287 | ||
@@ -250,26 +290,23 @@ struct mx2_camera_dev { | |||
250 | struct mx2_buffer *fb1_active; | 290 | struct mx2_buffer *fb1_active; |
251 | struct mx2_buffer *fb2_active; | 291 | struct mx2_buffer *fb2_active; |
252 | 292 | ||
253 | int use_emma; | ||
254 | |||
255 | u32 csicr1; | 293 | u32 csicr1; |
256 | 294 | ||
295 | struct mx2_buf_internal buf_discard[2]; | ||
257 | void *discard_buffer; | 296 | void *discard_buffer; |
258 | dma_addr_t discard_buffer_dma; | 297 | dma_addr_t discard_buffer_dma; |
259 | size_t discard_size; | 298 | size_t discard_size; |
260 | struct mx2_fmt_cfg *emma_prp; | 299 | struct mx2_fmt_cfg *emma_prp; |
300 | struct emma_prp_resize resizing[2]; | ||
301 | unsigned int s_width, s_height; | ||
261 | u32 frame_count; | 302 | u32 frame_count; |
303 | struct vb2_alloc_ctx *alloc_ctx; | ||
262 | }; | 304 | }; |
263 | 305 | ||
264 | /* buffer for one video frame */ | 306 | static struct mx2_buffer *mx2_ibuf_to_buf(struct mx2_buf_internal *int_buf) |
265 | struct mx2_buffer { | 307 | { |
266 | /* common v4l buffer stuff -- must be first */ | 308 | return container_of(int_buf, struct mx2_buffer, internal); |
267 | struct videobuf_buffer vb; | 309 | } |
268 | |||
269 | enum v4l2_mbus_pixelcode code; | ||
270 | |||
271 | int bufnum; | ||
272 | }; | ||
273 | 310 | ||
274 | static struct mx2_fmt_cfg mx27_emma_prp_table[] = { | 311 | static struct mx2_fmt_cfg mx27_emma_prp_table[] = { |
275 | /* | 312 | /* |
@@ -324,13 +361,36 @@ static struct mx2_fmt_cfg *mx27_emma_prp_get_format( | |||
324 | return &mx27_emma_prp_table[0]; | 361 | return &mx27_emma_prp_table[0]; |
325 | }; | 362 | }; |
326 | 363 | ||
364 | static void mx27_update_emma_buf(struct mx2_camera_dev *pcdev, | ||
365 | unsigned long phys, int bufnum) | ||
366 | { | ||
367 | struct mx2_fmt_cfg *prp = pcdev->emma_prp; | ||
368 | |||
369 | if (prp->cfg.channel == 1) { | ||
370 | writel(phys, pcdev->base_emma + | ||
371 | PRP_DEST_RGB1_PTR + 4 * bufnum); | ||
372 | } else { | ||
373 | writel(phys, pcdev->base_emma + | ||
374 | PRP_DEST_Y_PTR - 0x14 * bufnum); | ||
375 | if (prp->out_fmt == V4L2_PIX_FMT_YUV420) { | ||
376 | u32 imgsize = pcdev->icd->user_height * | ||
377 | pcdev->icd->user_width; | ||
378 | |||
379 | writel(phys + imgsize, pcdev->base_emma + | ||
380 | PRP_DEST_CB_PTR - 0x14 * bufnum); | ||
381 | writel(phys + ((5 * imgsize) / 4), pcdev->base_emma + | ||
382 | PRP_DEST_CR_PTR - 0x14 * bufnum); | ||
383 | } | ||
384 | } | ||
385 | } | ||
386 | |||
327 | static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev) | 387 | static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev) |
328 | { | 388 | { |
329 | unsigned long flags; | 389 | unsigned long flags; |
330 | 390 | ||
331 | clk_disable(pcdev->clk_csi); | 391 | clk_disable(pcdev->clk_csi); |
332 | writel(0, pcdev->base_csi + CSICR1); | 392 | writel(0, pcdev->base_csi + CSICR1); |
333 | if (mx27_camera_emma(pcdev)) { | 393 | if (cpu_is_mx27()) { |
334 | writel(0, pcdev->base_emma + PRP_CNTL); | 394 | writel(0, pcdev->base_emma + PRP_CNTL); |
335 | } else if (cpu_is_mx25()) { | 395 | } else if (cpu_is_mx25()) { |
336 | spin_lock_irqsave(&pcdev->lock, flags); | 396 | spin_lock_irqsave(&pcdev->lock, flags); |
@@ -362,7 +422,7 @@ static int mx2_camera_add_device(struct soc_camera_device *icd) | |||
362 | 422 | ||
363 | csicr1 = CSICR1_MCLKEN; | 423 | csicr1 = CSICR1_MCLKEN; |
364 | 424 | ||
365 | if (mx27_camera_emma(pcdev)) { | 425 | if (cpu_is_mx27()) { |
366 | csicr1 |= CSICR1_PRP_IF_EN | CSICR1_FCC | | 426 | csicr1 |= CSICR1_PRP_IF_EN | CSICR1_FCC | |
367 | CSICR1_RXFF_LEVEL(0); | 427 | CSICR1_RXFF_LEVEL(0); |
368 | } else if (cpu_is_mx27()) | 428 | } else if (cpu_is_mx27()) |
@@ -392,56 +452,13 @@ static void mx2_camera_remove_device(struct soc_camera_device *icd) | |||
392 | 452 | ||
393 | mx2_camera_deactivate(pcdev); | 453 | mx2_camera_deactivate(pcdev); |
394 | 454 | ||
395 | if (pcdev->discard_buffer) { | ||
396 | dma_free_coherent(ici->v4l2_dev.dev, pcdev->discard_size, | ||
397 | pcdev->discard_buffer, | ||
398 | pcdev->discard_buffer_dma); | ||
399 | pcdev->discard_buffer = NULL; | ||
400 | } | ||
401 | |||
402 | pcdev->icd = NULL; | 455 | pcdev->icd = NULL; |
403 | } | 456 | } |
404 | 457 | ||
405 | #ifdef CONFIG_MACH_MX27 | ||
406 | static void mx27_camera_dma_enable(struct mx2_camera_dev *pcdev) | ||
407 | { | ||
408 | u32 tmp; | ||
409 | |||
410 | imx_dma_enable(pcdev->dma); | ||
411 | |||
412 | tmp = readl(pcdev->base_csi + CSICR1); | ||
413 | tmp |= CSICR1_RF_OR_INTEN; | ||
414 | writel(tmp, pcdev->base_csi + CSICR1); | ||
415 | } | ||
416 | |||
417 | static irqreturn_t mx27_camera_irq(int irq_csi, void *data) | ||
418 | { | ||
419 | struct mx2_camera_dev *pcdev = data; | ||
420 | u32 status = readl(pcdev->base_csi + CSISR); | ||
421 | |||
422 | if (status & CSISR_SOF_INT && pcdev->active) { | ||
423 | u32 tmp; | ||
424 | |||
425 | tmp = readl(pcdev->base_csi + CSICR1); | ||
426 | writel(tmp | CSICR1_CLR_RXFIFO, pcdev->base_csi + CSICR1); | ||
427 | mx27_camera_dma_enable(pcdev); | ||
428 | } | ||
429 | |||
430 | writel(CSISR_SOF_INT | CSISR_RFF_OR_INT, pcdev->base_csi + CSISR); | ||
431 | |||
432 | return IRQ_HANDLED; | ||
433 | } | ||
434 | #else | ||
435 | static irqreturn_t mx27_camera_irq(int irq_csi, void *data) | ||
436 | { | ||
437 | return IRQ_NONE; | ||
438 | } | ||
439 | #endif /* CONFIG_MACH_MX27 */ | ||
440 | |||
441 | static void mx25_camera_frame_done(struct mx2_camera_dev *pcdev, int fb, | 458 | static void mx25_camera_frame_done(struct mx2_camera_dev *pcdev, int fb, |
442 | int state) | 459 | int state) |
443 | { | 460 | { |
444 | struct videobuf_buffer *vb; | 461 | struct vb2_buffer *vb; |
445 | struct mx2_buffer *buf; | 462 | struct mx2_buffer *buf; |
446 | struct mx2_buffer **fb_active = fb == 1 ? &pcdev->fb1_active : | 463 | struct mx2_buffer **fb_active = fb == 1 ? &pcdev->fb1_active : |
447 | &pcdev->fb2_active; | 464 | &pcdev->fb2_active; |
@@ -454,25 +471,24 @@ static void mx25_camera_frame_done(struct mx2_camera_dev *pcdev, int fb, | |||
454 | goto out; | 471 | goto out; |
455 | 472 | ||
456 | vb = &(*fb_active)->vb; | 473 | vb = &(*fb_active)->vb; |
457 | dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, | 474 | dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__, |
458 | vb, vb->baddr, vb->bsize); | 475 | vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); |
459 | 476 | ||
460 | vb->state = state; | 477 | do_gettimeofday(&vb->v4l2_buf.timestamp); |
461 | do_gettimeofday(&vb->ts); | 478 | vb->v4l2_buf.sequence++; |
462 | vb->field_count++; | 479 | vb2_buffer_done(vb, VB2_BUF_STATE_DONE); |
463 | |||
464 | wake_up(&vb->done); | ||
465 | 480 | ||
466 | if (list_empty(&pcdev->capture)) { | 481 | if (list_empty(&pcdev->capture)) { |
467 | buf = NULL; | 482 | buf = NULL; |
468 | writel(0, pcdev->base_csi + fb_reg); | 483 | writel(0, pcdev->base_csi + fb_reg); |
469 | } else { | 484 | } else { |
470 | buf = list_entry(pcdev->capture.next, struct mx2_buffer, | 485 | buf = list_first_entry(&pcdev->capture, struct mx2_buffer, |
471 | vb.queue); | 486 | internal.queue); |
472 | vb = &buf->vb; | 487 | vb = &buf->vb; |
473 | list_del(&vb->queue); | 488 | list_del(&buf->internal.queue); |
474 | vb->state = VIDEOBUF_ACTIVE; | 489 | buf->state = MX2_STATE_ACTIVE; |
475 | writel(videobuf_to_dma_contig(vb), pcdev->base_csi + fb_reg); | 490 | writel(vb2_dma_contig_plane_dma_addr(vb, 0), |
491 | pcdev->base_csi + fb_reg); | ||
476 | } | 492 | } |
477 | 493 | ||
478 | *fb_active = buf; | 494 | *fb_active = buf; |
@@ -487,9 +503,9 @@ static irqreturn_t mx25_camera_irq(int irq_csi, void *data) | |||
487 | u32 status = readl(pcdev->base_csi + CSISR); | 503 | u32 status = readl(pcdev->base_csi + CSISR); |
488 | 504 | ||
489 | if (status & CSISR_DMA_TSF_FB1_INT) | 505 | if (status & CSISR_DMA_TSF_FB1_INT) |
490 | mx25_camera_frame_done(pcdev, 1, VIDEOBUF_DONE); | 506 | mx25_camera_frame_done(pcdev, 1, MX2_STATE_DONE); |
491 | else if (status & CSISR_DMA_TSF_FB2_INT) | 507 | else if (status & CSISR_DMA_TSF_FB2_INT) |
492 | mx25_camera_frame_done(pcdev, 2, VIDEOBUF_DONE); | 508 | mx25_camera_frame_done(pcdev, 2, MX2_STATE_DONE); |
493 | 509 | ||
494 | /* FIXME: handle CSISR_RFF_OR_INT */ | 510 | /* FIXME: handle CSISR_RFF_OR_INT */ |
495 | 511 | ||
@@ -501,59 +517,50 @@ static irqreturn_t mx25_camera_irq(int irq_csi, void *data) | |||
501 | /* | 517 | /* |
502 | * Videobuf operations | 518 | * Videobuf operations |
503 | */ | 519 | */ |
504 | static int mx2_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, | 520 | static int mx2_videobuf_setup(struct vb2_queue *vq, |
505 | unsigned int *size) | 521 | const struct v4l2_format *fmt, |
522 | unsigned int *count, unsigned int *num_planes, | ||
523 | unsigned int sizes[], void *alloc_ctxs[]) | ||
506 | { | 524 | { |
507 | struct soc_camera_device *icd = vq->priv_data; | 525 | struct soc_camera_device *icd = soc_camera_from_vb2q(vq); |
526 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
527 | struct mx2_camera_dev *pcdev = ici->priv; | ||
508 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, | 528 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, |
509 | icd->current_fmt->host_fmt); | 529 | icd->current_fmt->host_fmt); |
510 | 530 | ||
511 | dev_dbg(icd->parent, "count=%d, size=%d\n", *count, *size); | 531 | dev_dbg(icd->parent, "count=%d, size=%d\n", *count, sizes[0]); |
532 | |||
533 | /* TODO: support for VIDIOC_CREATE_BUFS not ready */ | ||
534 | if (fmt != NULL) | ||
535 | return -ENOTTY; | ||
512 | 536 | ||
513 | if (bytes_per_line < 0) | 537 | if (bytes_per_line < 0) |
514 | return bytes_per_line; | 538 | return bytes_per_line; |
515 | 539 | ||
516 | *size = bytes_per_line * icd->user_height; | 540 | alloc_ctxs[0] = pcdev->alloc_ctx; |
541 | |||
542 | sizes[0] = bytes_per_line * icd->user_height; | ||
517 | 543 | ||
518 | if (0 == *count) | 544 | if (0 == *count) |
519 | *count = 32; | 545 | *count = 32; |
520 | if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024) | 546 | if (!*num_planes && |
521 | *count = (MAX_VIDEO_MEM * 1024 * 1024) / *size; | 547 | sizes[0] * *count > MAX_VIDEO_MEM * 1024 * 1024) |
548 | *count = (MAX_VIDEO_MEM * 1024 * 1024) / sizes[0]; | ||
522 | 549 | ||
523 | return 0; | 550 | *num_planes = 1; |
524 | } | ||
525 | 551 | ||
526 | static void free_buffer(struct videobuf_queue *vq, struct mx2_buffer *buf) | 552 | return 0; |
527 | { | ||
528 | struct soc_camera_device *icd = vq->priv_data; | ||
529 | struct videobuf_buffer *vb = &buf->vb; | ||
530 | |||
531 | dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, | ||
532 | vb, vb->baddr, vb->bsize); | ||
533 | |||
534 | /* | ||
535 | * This waits until this buffer is out of danger, i.e., until it is no | ||
536 | * longer in state VIDEOBUF_QUEUED or VIDEOBUF_ACTIVE | ||
537 | */ | ||
538 | videobuf_waiton(vq, vb, 0, 0); | ||
539 | |||
540 | videobuf_dma_contig_free(vq, vb); | ||
541 | dev_dbg(icd->parent, "%s freed\n", __func__); | ||
542 | |||
543 | vb->state = VIDEOBUF_NEEDS_INIT; | ||
544 | } | 553 | } |
545 | 554 | ||
546 | static int mx2_videobuf_prepare(struct videobuf_queue *vq, | 555 | static int mx2_videobuf_prepare(struct vb2_buffer *vb) |
547 | struct videobuf_buffer *vb, enum v4l2_field field) | ||
548 | { | 556 | { |
549 | struct soc_camera_device *icd = vq->priv_data; | 557 | struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); |
550 | struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb); | ||
551 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, | 558 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, |
552 | icd->current_fmt->host_fmt); | 559 | icd->current_fmt->host_fmt); |
553 | int ret = 0; | 560 | int ret = 0; |
554 | 561 | ||
555 | dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, | 562 | dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, |
556 | vb, vb->baddr, vb->bsize); | 563 | vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); |
557 | 564 | ||
558 | if (bytes_per_line < 0) | 565 | if (bytes_per_line < 0) |
559 | return bytes_per_line; | 566 | return bytes_per_line; |
@@ -563,99 +570,58 @@ static int mx2_videobuf_prepare(struct videobuf_queue *vq, | |||
563 | * This can be useful if you want to see if we actually fill | 570 | * This can be useful if you want to see if we actually fill |
564 | * the buffer with something | 571 | * the buffer with something |
565 | */ | 572 | */ |
566 | memset((void *)vb->baddr, 0xaa, vb->bsize); | 573 | memset((void *)vb2_plane_vaddr(vb, 0), |
574 | 0xaa, vb2_get_plane_payload(vb, 0)); | ||
567 | #endif | 575 | #endif |
568 | 576 | ||
569 | if (buf->code != icd->current_fmt->code || | 577 | vb2_set_plane_payload(vb, 0, bytes_per_line * icd->user_height); |
570 | vb->width != icd->user_width || | 578 | if (vb2_plane_vaddr(vb, 0) && |
571 | vb->height != icd->user_height || | 579 | vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) { |
572 | vb->field != field) { | ||
573 | buf->code = icd->current_fmt->code; | ||
574 | vb->width = icd->user_width; | ||
575 | vb->height = icd->user_height; | ||
576 | vb->field = field; | ||
577 | vb->state = VIDEOBUF_NEEDS_INIT; | ||
578 | } | ||
579 | |||
580 | vb->size = bytes_per_line * vb->height; | ||
581 | if (vb->baddr && vb->bsize < vb->size) { | ||
582 | ret = -EINVAL; | 580 | ret = -EINVAL; |
583 | goto out; | 581 | goto out; |
584 | } | 582 | } |
585 | 583 | ||
586 | if (vb->state == VIDEOBUF_NEEDS_INIT) { | ||
587 | ret = videobuf_iolock(vq, vb, NULL); | ||
588 | if (ret) | ||
589 | goto fail; | ||
590 | |||
591 | vb->state = VIDEOBUF_PREPARED; | ||
592 | } | ||
593 | |||
594 | return 0; | 584 | return 0; |
595 | 585 | ||
596 | fail: | ||
597 | free_buffer(vq, buf); | ||
598 | out: | 586 | out: |
599 | return ret; | 587 | return ret; |
600 | } | 588 | } |
601 | 589 | ||
602 | static void mx2_videobuf_queue(struct videobuf_queue *vq, | 590 | static void mx2_videobuf_queue(struct vb2_buffer *vb) |
603 | struct videobuf_buffer *vb) | ||
604 | { | 591 | { |
605 | struct soc_camera_device *icd = vq->priv_data; | 592 | struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); |
606 | struct soc_camera_host *ici = | 593 | struct soc_camera_host *ici = |
607 | to_soc_camera_host(icd->parent); | 594 | to_soc_camera_host(icd->parent); |
608 | struct mx2_camera_dev *pcdev = ici->priv; | 595 | struct mx2_camera_dev *pcdev = ici->priv; |
609 | struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb); | 596 | struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb); |
610 | unsigned long flags; | 597 | unsigned long flags; |
611 | 598 | ||
612 | dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, | 599 | dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, |
613 | vb, vb->baddr, vb->bsize); | 600 | vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); |
614 | 601 | ||
615 | spin_lock_irqsave(&pcdev->lock, flags); | 602 | spin_lock_irqsave(&pcdev->lock, flags); |
616 | 603 | ||
617 | vb->state = VIDEOBUF_QUEUED; | 604 | buf->state = MX2_STATE_QUEUED; |
618 | list_add_tail(&vb->queue, &pcdev->capture); | 605 | list_add_tail(&buf->internal.queue, &pcdev->capture); |
619 | 606 | ||
620 | if (mx27_camera_emma(pcdev)) { | 607 | if (cpu_is_mx25()) { |
621 | goto out; | ||
622 | #ifdef CONFIG_MACH_MX27 | ||
623 | } else if (cpu_is_mx27()) { | ||
624 | int ret; | ||
625 | |||
626 | if (pcdev->active == NULL) { | ||
627 | ret = imx_dma_setup_single(pcdev->dma, | ||
628 | videobuf_to_dma_contig(vb), vb->size, | ||
629 | (u32)pcdev->base_dma + 0x10, | ||
630 | DMA_MODE_READ); | ||
631 | if (ret) { | ||
632 | vb->state = VIDEOBUF_ERROR; | ||
633 | wake_up(&vb->done); | ||
634 | goto out; | ||
635 | } | ||
636 | |||
637 | vb->state = VIDEOBUF_ACTIVE; | ||
638 | pcdev->active = buf; | ||
639 | } | ||
640 | #endif | ||
641 | } else { /* cpu_is_mx25() */ | ||
642 | u32 csicr3, dma_inten = 0; | 608 | u32 csicr3, dma_inten = 0; |
643 | 609 | ||
644 | if (pcdev->fb1_active == NULL) { | 610 | if (pcdev->fb1_active == NULL) { |
645 | writel(videobuf_to_dma_contig(vb), | 611 | writel(vb2_dma_contig_plane_dma_addr(vb, 0), |
646 | pcdev->base_csi + CSIDMASA_FB1); | 612 | pcdev->base_csi + CSIDMASA_FB1); |
647 | pcdev->fb1_active = buf; | 613 | pcdev->fb1_active = buf; |
648 | dma_inten = CSICR1_FB1_DMA_INTEN; | 614 | dma_inten = CSICR1_FB1_DMA_INTEN; |
649 | } else if (pcdev->fb2_active == NULL) { | 615 | } else if (pcdev->fb2_active == NULL) { |
650 | writel(videobuf_to_dma_contig(vb), | 616 | writel(vb2_dma_contig_plane_dma_addr(vb, 0), |
651 | pcdev->base_csi + CSIDMASA_FB2); | 617 | pcdev->base_csi + CSIDMASA_FB2); |
652 | pcdev->fb2_active = buf; | 618 | pcdev->fb2_active = buf; |
653 | dma_inten = CSICR1_FB2_DMA_INTEN; | 619 | dma_inten = CSICR1_FB2_DMA_INTEN; |
654 | } | 620 | } |
655 | 621 | ||
656 | if (dma_inten) { | 622 | if (dma_inten) { |
657 | list_del(&vb->queue); | 623 | list_del(&buf->internal.queue); |
658 | vb->state = VIDEOBUF_ACTIVE; | 624 | buf->state = MX2_STATE_ACTIVE; |
659 | 625 | ||
660 | csicr3 = readl(pcdev->base_csi + CSICR3); | 626 | csicr3 = readl(pcdev->base_csi + CSICR3); |
661 | 627 | ||
@@ -674,36 +640,31 @@ static void mx2_videobuf_queue(struct videobuf_queue *vq, | |||
674 | } | 640 | } |
675 | } | 641 | } |
676 | 642 | ||
677 | out: | ||
678 | spin_unlock_irqrestore(&pcdev->lock, flags); | 643 | spin_unlock_irqrestore(&pcdev->lock, flags); |
679 | } | 644 | } |
680 | 645 | ||
681 | static void mx2_videobuf_release(struct videobuf_queue *vq, | 646 | static void mx2_videobuf_release(struct vb2_buffer *vb) |
682 | struct videobuf_buffer *vb) | ||
683 | { | 647 | { |
684 | struct soc_camera_device *icd = vq->priv_data; | 648 | struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); |
685 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 649 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
686 | struct mx2_camera_dev *pcdev = ici->priv; | 650 | struct mx2_camera_dev *pcdev = ici->priv; |
687 | struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb); | 651 | struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb); |
688 | unsigned long flags; | 652 | unsigned long flags; |
689 | 653 | ||
690 | #ifdef DEBUG | 654 | #ifdef DEBUG |
691 | dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, | 655 | dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, |
692 | vb, vb->baddr, vb->bsize); | 656 | vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); |
693 | 657 | ||
694 | switch (vb->state) { | 658 | switch (buf->state) { |
695 | case VIDEOBUF_ACTIVE: | 659 | case MX2_STATE_ACTIVE: |
696 | dev_info(icd->parent, "%s (active)\n", __func__); | 660 | dev_info(icd->parent, "%s (active)\n", __func__); |
697 | break; | 661 | break; |
698 | case VIDEOBUF_QUEUED: | 662 | case MX2_STATE_QUEUED: |
699 | dev_info(icd->parent, "%s (queued)\n", __func__); | 663 | dev_info(icd->parent, "%s (queued)\n", __func__); |
700 | break; | 664 | break; |
701 | case VIDEOBUF_PREPARED: | ||
702 | dev_info(icd->parent, "%s (prepared)\n", __func__); | ||
703 | break; | ||
704 | default: | 665 | default: |
705 | dev_info(icd->parent, "%s (unknown) %d\n", __func__, | 666 | dev_info(icd->parent, "%s (unknown) %d\n", __func__, |
706 | vb->state); | 667 | buf->state); |
707 | break; | 668 | break; |
708 | } | 669 | } |
709 | #endif | 670 | #endif |
@@ -717,11 +678,9 @@ static void mx2_videobuf_release(struct videobuf_queue *vq, | |||
717 | * state. This requires a specific handling for each of the these DMA | 678 | * state. This requires a specific handling for each of the these DMA |
718 | * types. | 679 | * types. |
719 | */ | 680 | */ |
681 | |||
720 | spin_lock_irqsave(&pcdev->lock, flags); | 682 | spin_lock_irqsave(&pcdev->lock, flags); |
721 | if (vb->state == VIDEOBUF_QUEUED) { | 683 | if (cpu_is_mx25() && buf->state == MX2_STATE_ACTIVE) { |
722 | list_del(&vb->queue); | ||
723 | vb->state = VIDEOBUF_ERROR; | ||
724 | } else if (cpu_is_mx25() && vb->state == VIDEOBUF_ACTIVE) { | ||
725 | if (pcdev->fb1_active == buf) { | 684 | if (pcdev->fb1_active == buf) { |
726 | pcdev->csicr1 &= ~CSICR1_FB1_DMA_INTEN; | 685 | pcdev->csicr1 &= ~CSICR1_FB1_DMA_INTEN; |
727 | writel(0, pcdev->base_csi + CSIDMASA_FB1); | 686 | writel(0, pcdev->base_csi + CSIDMASA_FB1); |
@@ -732,75 +691,178 @@ static void mx2_videobuf_release(struct videobuf_queue *vq, | |||
732 | pcdev->fb2_active = NULL; | 691 | pcdev->fb2_active = NULL; |
733 | } | 692 | } |
734 | writel(pcdev->csicr1, pcdev->base_csi + CSICR1); | 693 | writel(pcdev->csicr1, pcdev->base_csi + CSICR1); |
735 | vb->state = VIDEOBUF_ERROR; | ||
736 | } | 694 | } |
737 | spin_unlock_irqrestore(&pcdev->lock, flags); | 695 | spin_unlock_irqrestore(&pcdev->lock, flags); |
738 | |||
739 | free_buffer(vq, buf); | ||
740 | } | 696 | } |
741 | 697 | ||
742 | static struct videobuf_queue_ops mx2_videobuf_ops = { | 698 | static void mx27_camera_emma_buf_init(struct soc_camera_device *icd, |
743 | .buf_setup = mx2_videobuf_setup, | 699 | int bytesperline) |
744 | .buf_prepare = mx2_videobuf_prepare, | ||
745 | .buf_queue = mx2_videobuf_queue, | ||
746 | .buf_release = mx2_videobuf_release, | ||
747 | }; | ||
748 | |||
749 | static void mx2_camera_init_videobuf(struct videobuf_queue *q, | ||
750 | struct soc_camera_device *icd) | ||
751 | { | 700 | { |
752 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 701 | struct soc_camera_host *ici = |
702 | to_soc_camera_host(icd->parent); | ||
753 | struct mx2_camera_dev *pcdev = ici->priv; | 703 | struct mx2_camera_dev *pcdev = ici->priv; |
704 | struct mx2_fmt_cfg *prp = pcdev->emma_prp; | ||
754 | 705 | ||
755 | videobuf_queue_dma_contig_init(q, &mx2_videobuf_ops, pcdev->dev, | 706 | writel((pcdev->s_width << 16) | pcdev->s_height, |
756 | &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, | 707 | pcdev->base_emma + PRP_SRC_FRAME_SIZE); |
757 | V4L2_FIELD_NONE, sizeof(struct mx2_buffer), | 708 | writel(prp->cfg.src_pixel, |
758 | icd, &icd->video_lock); | 709 | pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL); |
759 | } | 710 | if (prp->cfg.channel == 1) { |
711 | writel((icd->user_width << 16) | icd->user_height, | ||
712 | pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE); | ||
713 | writel(bytesperline, | ||
714 | pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE); | ||
715 | writel(prp->cfg.ch1_pixel, | ||
716 | pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL); | ||
717 | } else { /* channel 2 */ | ||
718 | writel((icd->user_width << 16) | icd->user_height, | ||
719 | pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE); | ||
720 | } | ||
760 | 721 | ||
761 | #define MX2_BUS_FLAGS (V4L2_MBUS_MASTER | \ | 722 | /* Enable interrupts */ |
762 | V4L2_MBUS_VSYNC_ACTIVE_HIGH | \ | 723 | writel(prp->cfg.irq_flags, pcdev->base_emma + PRP_INTR_CNTL); |
763 | V4L2_MBUS_VSYNC_ACTIVE_LOW | \ | 724 | } |
764 | V4L2_MBUS_HSYNC_ACTIVE_HIGH | \ | ||
765 | V4L2_MBUS_HSYNC_ACTIVE_LOW | \ | ||
766 | V4L2_MBUS_PCLK_SAMPLE_RISING | \ | ||
767 | V4L2_MBUS_PCLK_SAMPLE_FALLING | \ | ||
768 | V4L2_MBUS_DATA_ACTIVE_HIGH | \ | ||
769 | V4L2_MBUS_DATA_ACTIVE_LOW) | ||
770 | 725 | ||
771 | static int mx27_camera_emma_prp_reset(struct mx2_camera_dev *pcdev) | 726 | static void mx2_prp_resize_commit(struct mx2_camera_dev *pcdev) |
772 | { | 727 | { |
773 | u32 cntl; | 728 | int dir; |
774 | int count = 0; | ||
775 | 729 | ||
776 | cntl = readl(pcdev->base_emma + PRP_CNTL); | 730 | for (dir = RESIZE_DIR_H; dir <= RESIZE_DIR_V; dir++) { |
777 | writel(PRP_CNTL_SWRST, pcdev->base_emma + PRP_CNTL); | 731 | unsigned char *s = pcdev->resizing[dir].s; |
778 | while (count++ < 100) { | 732 | int len = pcdev->resizing[dir].len; |
779 | if (!(readl(pcdev->base_emma + PRP_CNTL) & PRP_CNTL_SWRST)) | 733 | unsigned int coeff[2] = {0, 0}; |
780 | return 0; | 734 | unsigned int valid = 0; |
781 | barrier(); | 735 | int i; |
782 | udelay(1); | ||
783 | } | ||
784 | 736 | ||
785 | return -ETIMEDOUT; | 737 | if (len == 0) |
738 | continue; | ||
739 | |||
740 | for (i = RESIZE_NUM_MAX - 1; i >= 0; i--) { | ||
741 | int j; | ||
742 | |||
743 | j = i > 9 ? 1 : 0; | ||
744 | coeff[j] = (coeff[j] << BC_COEF) | | ||
745 | (s[i] & (SZ_COEF - 1)); | ||
746 | |||
747 | if (i == 5 || i == 15) | ||
748 | coeff[j] <<= 1; | ||
749 | |||
750 | valid = (valid << 1) | (s[i] >> BC_COEF); | ||
751 | } | ||
752 | |||
753 | valid |= PRP_RZ_VALID_TBL_LEN(len); | ||
754 | |||
755 | if (pcdev->resizing[dir].algo == RESIZE_ALGO_BILINEAR) | ||
756 | valid |= PRP_RZ_VALID_BILINEAR; | ||
757 | |||
758 | if (pcdev->emma_prp->cfg.channel == 1) { | ||
759 | if (dir == RESIZE_DIR_H) { | ||
760 | writel(coeff[0], pcdev->base_emma + | ||
761 | PRP_CH1_RZ_HORI_COEF1); | ||
762 | writel(coeff[1], pcdev->base_emma + | ||
763 | PRP_CH1_RZ_HORI_COEF2); | ||
764 | writel(valid, pcdev->base_emma + | ||
765 | PRP_CH1_RZ_HORI_VALID); | ||
766 | } else { | ||
767 | writel(coeff[0], pcdev->base_emma + | ||
768 | PRP_CH1_RZ_VERT_COEF1); | ||
769 | writel(coeff[1], pcdev->base_emma + | ||
770 | PRP_CH1_RZ_VERT_COEF2); | ||
771 | writel(valid, pcdev->base_emma + | ||
772 | PRP_CH1_RZ_VERT_VALID); | ||
773 | } | ||
774 | } else { | ||
775 | if (dir == RESIZE_DIR_H) { | ||
776 | writel(coeff[0], pcdev->base_emma + | ||
777 | PRP_CH2_RZ_HORI_COEF1); | ||
778 | writel(coeff[1], pcdev->base_emma + | ||
779 | PRP_CH2_RZ_HORI_COEF2); | ||
780 | writel(valid, pcdev->base_emma + | ||
781 | PRP_CH2_RZ_HORI_VALID); | ||
782 | } else { | ||
783 | writel(coeff[0], pcdev->base_emma + | ||
784 | PRP_CH2_RZ_VERT_COEF1); | ||
785 | writel(coeff[1], pcdev->base_emma + | ||
786 | PRP_CH2_RZ_VERT_COEF2); | ||
787 | writel(valid, pcdev->base_emma + | ||
788 | PRP_CH2_RZ_VERT_VALID); | ||
789 | } | ||
790 | } | ||
791 | } | ||
786 | } | 792 | } |
787 | 793 | ||
788 | static void mx27_camera_emma_buf_init(struct soc_camera_device *icd, | 794 | static int mx2_start_streaming(struct vb2_queue *q, unsigned int count) |
789 | int bytesperline) | ||
790 | { | 795 | { |
796 | struct soc_camera_device *icd = soc_camera_from_vb2q(q); | ||
791 | struct soc_camera_host *ici = | 797 | struct soc_camera_host *ici = |
792 | to_soc_camera_host(icd->parent); | 798 | to_soc_camera_host(icd->parent); |
793 | struct mx2_camera_dev *pcdev = ici->priv; | 799 | struct mx2_camera_dev *pcdev = ici->priv; |
794 | struct mx2_fmt_cfg *prp = pcdev->emma_prp; | 800 | struct mx2_fmt_cfg *prp = pcdev->emma_prp; |
795 | u32 imgsize = pcdev->icd->user_height * pcdev->icd->user_width; | 801 | struct vb2_buffer *vb; |
802 | struct mx2_buffer *buf; | ||
803 | unsigned long phys; | ||
804 | int bytesperline; | ||
796 | 805 | ||
797 | if (prp->cfg.channel == 1) { | 806 | if (cpu_is_mx27()) { |
798 | writel(pcdev->discard_buffer_dma, | 807 | unsigned long flags; |
799 | pcdev->base_emma + PRP_DEST_RGB1_PTR); | 808 | if (count < 2) |
800 | writel(pcdev->discard_buffer_dma, | 809 | return -EINVAL; |
801 | pcdev->base_emma + PRP_DEST_RGB2_PTR); | 810 | |
811 | spin_lock_irqsave(&pcdev->lock, flags); | ||
812 | |||
813 | buf = list_first_entry(&pcdev->capture, struct mx2_buffer, | ||
814 | internal.queue); | ||
815 | buf->internal.bufnum = 0; | ||
816 | vb = &buf->vb; | ||
817 | buf->state = MX2_STATE_ACTIVE; | ||
818 | |||
819 | phys = vb2_dma_contig_plane_dma_addr(vb, 0); | ||
820 | mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum); | ||
821 | list_move_tail(pcdev->capture.next, &pcdev->active_bufs); | ||
822 | |||
823 | buf = list_first_entry(&pcdev->capture, struct mx2_buffer, | ||
824 | internal.queue); | ||
825 | buf->internal.bufnum = 1; | ||
826 | vb = &buf->vb; | ||
827 | buf->state = MX2_STATE_ACTIVE; | ||
802 | 828 | ||
803 | writel(PRP_CNTL_CH1EN | | 829 | phys = vb2_dma_contig_plane_dma_addr(vb, 0); |
830 | mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum); | ||
831 | list_move_tail(pcdev->capture.next, &pcdev->active_bufs); | ||
832 | |||
833 | bytesperline = soc_mbus_bytes_per_line(icd->user_width, | ||
834 | icd->current_fmt->host_fmt); | ||
835 | if (bytesperline < 0) | ||
836 | return bytesperline; | ||
837 | |||
838 | /* | ||
839 | * I didn't manage to properly enable/disable the prp | ||
840 | * on a per frame basis during running transfers, | ||
841 | * thus we allocate a buffer here and use it to | ||
842 | * discard frames when no buffer is available. | ||
843 | * Feel free to work on this ;) | ||
844 | */ | ||
845 | pcdev->discard_size = icd->user_height * bytesperline; | ||
846 | pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev, | ||
847 | pcdev->discard_size, &pcdev->discard_buffer_dma, | ||
848 | GFP_KERNEL); | ||
849 | if (!pcdev->discard_buffer) | ||
850 | return -ENOMEM; | ||
851 | |||
852 | pcdev->buf_discard[0].discard = true; | ||
853 | list_add_tail(&pcdev->buf_discard[0].queue, | ||
854 | &pcdev->discard); | ||
855 | |||
856 | pcdev->buf_discard[1].discard = true; | ||
857 | list_add_tail(&pcdev->buf_discard[1].queue, | ||
858 | &pcdev->discard); | ||
859 | |||
860 | mx2_prp_resize_commit(pcdev); | ||
861 | |||
862 | mx27_camera_emma_buf_init(icd, bytesperline); | ||
863 | |||
864 | if (prp->cfg.channel == 1) { | ||
865 | writel(PRP_CNTL_CH1EN | | ||
804 | PRP_CNTL_CSIEN | | 866 | PRP_CNTL_CSIEN | |
805 | prp->cfg.in_fmt | | 867 | prp->cfg.in_fmt | |
806 | prp->cfg.out_fmt | | 868 | prp->cfg.out_fmt | |
@@ -809,56 +871,107 @@ static void mx27_camera_emma_buf_init(struct soc_camera_device *icd, | |||
809 | PRP_CNTL_CH1_TSKIP(0) | | 871 | PRP_CNTL_CH1_TSKIP(0) | |
810 | PRP_CNTL_IN_TSKIP(0), | 872 | PRP_CNTL_IN_TSKIP(0), |
811 | pcdev->base_emma + PRP_CNTL); | 873 | pcdev->base_emma + PRP_CNTL); |
874 | } else { | ||
875 | writel(PRP_CNTL_CH2EN | | ||
876 | PRP_CNTL_CSIEN | | ||
877 | prp->cfg.in_fmt | | ||
878 | prp->cfg.out_fmt | | ||
879 | PRP_CNTL_CH2_LEN | | ||
880 | PRP_CNTL_CH2_TSKIP(0) | | ||
881 | PRP_CNTL_IN_TSKIP(0), | ||
882 | pcdev->base_emma + PRP_CNTL); | ||
883 | } | ||
884 | spin_unlock_irqrestore(&pcdev->lock, flags); | ||
885 | } | ||
812 | 886 | ||
813 | writel((icd->user_width << 16) | icd->user_height, | 887 | return 0; |
814 | pcdev->base_emma + PRP_SRC_FRAME_SIZE); | 888 | } |
815 | writel((icd->user_width << 16) | icd->user_height, | 889 | |
816 | pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE); | 890 | static int mx2_stop_streaming(struct vb2_queue *q) |
817 | writel(bytesperline, | 891 | { |
818 | pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE); | 892 | struct soc_camera_device *icd = soc_camera_from_vb2q(q); |
819 | writel(prp->cfg.src_pixel, | 893 | struct soc_camera_host *ici = |
820 | pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL); | 894 | to_soc_camera_host(icd->parent); |
821 | writel(prp->cfg.ch1_pixel, | 895 | struct mx2_camera_dev *pcdev = ici->priv; |
822 | pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL); | 896 | struct mx2_fmt_cfg *prp = pcdev->emma_prp; |
823 | } else { /* channel 2 */ | 897 | unsigned long flags; |
824 | writel(pcdev->discard_buffer_dma, | 898 | void *b; |
825 | pcdev->base_emma + PRP_DEST_Y_PTR); | 899 | u32 cntl; |
826 | writel(pcdev->discard_buffer_dma, | 900 | |
827 | pcdev->base_emma + PRP_SOURCE_Y_PTR); | 901 | if (cpu_is_mx27()) { |
828 | 902 | spin_lock_irqsave(&pcdev->lock, flags); | |
829 | if (prp->cfg.out_fmt == PRP_CNTL_CH2_OUT_YUV420) { | 903 | |
830 | writel(pcdev->discard_buffer_dma + imgsize, | 904 | cntl = readl(pcdev->base_emma + PRP_CNTL); |
831 | pcdev->base_emma + PRP_DEST_CB_PTR); | 905 | if (prp->cfg.channel == 1) { |
832 | writel(pcdev->discard_buffer_dma + ((5 * imgsize) / 4), | 906 | writel(cntl & ~PRP_CNTL_CH1EN, |
833 | pcdev->base_emma + PRP_DEST_CR_PTR); | 907 | pcdev->base_emma + PRP_CNTL); |
834 | writel(pcdev->discard_buffer_dma + imgsize, | 908 | } else { |
835 | pcdev->base_emma + PRP_SOURCE_CB_PTR); | 909 | writel(cntl & ~PRP_CNTL_CH2EN, |
836 | writel(pcdev->discard_buffer_dma + ((5 * imgsize) / 4), | 910 | pcdev->base_emma + PRP_CNTL); |
837 | pcdev->base_emma + PRP_SOURCE_CR_PTR); | ||
838 | } | 911 | } |
912 | INIT_LIST_HEAD(&pcdev->capture); | ||
913 | INIT_LIST_HEAD(&pcdev->active_bufs); | ||
914 | INIT_LIST_HEAD(&pcdev->discard); | ||
839 | 915 | ||
840 | writel(PRP_CNTL_CH2EN | | 916 | b = pcdev->discard_buffer; |
841 | PRP_CNTL_CSIEN | | 917 | pcdev->discard_buffer = NULL; |
842 | prp->cfg.in_fmt | | ||
843 | prp->cfg.out_fmt | | ||
844 | PRP_CNTL_CH2_LEN | | ||
845 | PRP_CNTL_CH2_TSKIP(0) | | ||
846 | PRP_CNTL_IN_TSKIP(0), | ||
847 | pcdev->base_emma + PRP_CNTL); | ||
848 | 918 | ||
849 | writel((icd->user_width << 16) | icd->user_height, | 919 | spin_unlock_irqrestore(&pcdev->lock, flags); |
850 | pcdev->base_emma + PRP_SRC_FRAME_SIZE); | ||
851 | 920 | ||
852 | writel((icd->user_width << 16) | icd->user_height, | 921 | dma_free_coherent(ici->v4l2_dev.dev, |
853 | pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE); | 922 | pcdev->discard_size, b, pcdev->discard_buffer_dma); |
923 | } | ||
854 | 924 | ||
855 | writel(prp->cfg.src_pixel, | 925 | return 0; |
856 | pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL); | 926 | } |
927 | |||
928 | static struct vb2_ops mx2_videobuf_ops = { | ||
929 | .queue_setup = mx2_videobuf_setup, | ||
930 | .buf_prepare = mx2_videobuf_prepare, | ||
931 | .buf_queue = mx2_videobuf_queue, | ||
932 | .buf_cleanup = mx2_videobuf_release, | ||
933 | .start_streaming = mx2_start_streaming, | ||
934 | .stop_streaming = mx2_stop_streaming, | ||
935 | }; | ||
936 | |||
937 | static int mx2_camera_init_videobuf(struct vb2_queue *q, | ||
938 | struct soc_camera_device *icd) | ||
939 | { | ||
940 | q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
941 | q->io_modes = VB2_MMAP | VB2_USERPTR; | ||
942 | q->drv_priv = icd; | ||
943 | q->ops = &mx2_videobuf_ops; | ||
944 | q->mem_ops = &vb2_dma_contig_memops; | ||
945 | q->buf_struct_size = sizeof(struct mx2_buffer); | ||
946 | |||
947 | return vb2_queue_init(q); | ||
948 | } | ||
857 | 949 | ||
950 | #define MX2_BUS_FLAGS (V4L2_MBUS_MASTER | \ | ||
951 | V4L2_MBUS_VSYNC_ACTIVE_HIGH | \ | ||
952 | V4L2_MBUS_VSYNC_ACTIVE_LOW | \ | ||
953 | V4L2_MBUS_HSYNC_ACTIVE_HIGH | \ | ||
954 | V4L2_MBUS_HSYNC_ACTIVE_LOW | \ | ||
955 | V4L2_MBUS_PCLK_SAMPLE_RISING | \ | ||
956 | V4L2_MBUS_PCLK_SAMPLE_FALLING | \ | ||
957 | V4L2_MBUS_DATA_ACTIVE_HIGH | \ | ||
958 | V4L2_MBUS_DATA_ACTIVE_LOW) | ||
959 | |||
960 | static int mx27_camera_emma_prp_reset(struct mx2_camera_dev *pcdev) | ||
961 | { | ||
962 | u32 cntl; | ||
963 | int count = 0; | ||
964 | |||
965 | cntl = readl(pcdev->base_emma + PRP_CNTL); | ||
966 | writel(PRP_CNTL_SWRST, pcdev->base_emma + PRP_CNTL); | ||
967 | while (count++ < 100) { | ||
968 | if (!(readl(pcdev->base_emma + PRP_CNTL) & PRP_CNTL_SWRST)) | ||
969 | return 0; | ||
970 | barrier(); | ||
971 | udelay(1); | ||
858 | } | 972 | } |
859 | 973 | ||
860 | /* Enable interrupts */ | 974 | return -ETIMEDOUT; |
861 | writel(prp->cfg.irq_flags, pcdev->base_emma + PRP_INTR_CNTL); | ||
862 | } | 975 | } |
863 | 976 | ||
864 | static int mx2_camera_set_bus_param(struct soc_camera_device *icd) | 977 | static int mx2_camera_set_bus_param(struct soc_camera_device *icd) |
@@ -939,31 +1052,10 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd) | |||
939 | if (bytesperline < 0) | 1052 | if (bytesperline < 0) |
940 | return bytesperline; | 1053 | return bytesperline; |
941 | 1054 | ||
942 | if (mx27_camera_emma(pcdev)) { | 1055 | if (cpu_is_mx27()) { |
943 | ret = mx27_camera_emma_prp_reset(pcdev); | 1056 | ret = mx27_camera_emma_prp_reset(pcdev); |
944 | if (ret) | 1057 | if (ret) |
945 | return ret; | 1058 | return ret; |
946 | |||
947 | if (pcdev->discard_buffer) | ||
948 | dma_free_coherent(ici->v4l2_dev.dev, | ||
949 | pcdev->discard_size, pcdev->discard_buffer, | ||
950 | pcdev->discard_buffer_dma); | ||
951 | |||
952 | /* | ||
953 | * I didn't manage to properly enable/disable the prp | ||
954 | * on a per frame basis during running transfers, | ||
955 | * thus we allocate a buffer here and use it to | ||
956 | * discard frames when no buffer is available. | ||
957 | * Feel free to work on this ;) | ||
958 | */ | ||
959 | pcdev->discard_size = icd->user_height * bytesperline; | ||
960 | pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev, | ||
961 | pcdev->discard_size, &pcdev->discard_buffer_dma, | ||
962 | GFP_KERNEL); | ||
963 | if (!pcdev->discard_buffer) | ||
964 | return -ENOMEM; | ||
965 | |||
966 | mx27_camera_emma_buf_init(icd, bytesperline); | ||
967 | } else if (cpu_is_mx25()) { | 1059 | } else if (cpu_is_mx25()) { |
968 | writel((bytesperline * icd->user_height) >> 2, | 1060 | writel((bytesperline * icd->user_height) >> 2, |
969 | pcdev->base_csi + CSIRXCNT); | 1061 | pcdev->base_csi + CSIRXCNT); |
@@ -1052,6 +1144,123 @@ static int mx2_camera_get_formats(struct soc_camera_device *icd, | |||
1052 | return formats; | 1144 | return formats; |
1053 | } | 1145 | } |
1054 | 1146 | ||
1147 | static int mx2_emmaprp_resize(struct mx2_camera_dev *pcdev, | ||
1148 | struct v4l2_mbus_framefmt *mf_in, | ||
1149 | struct v4l2_pix_format *pix_out, bool apply) | ||
1150 | { | ||
1151 | int num, den; | ||
1152 | unsigned long m; | ||
1153 | int i, dir; | ||
1154 | |||
1155 | for (dir = RESIZE_DIR_H; dir <= RESIZE_DIR_V; dir++) { | ||
1156 | struct emma_prp_resize tmprsz; | ||
1157 | unsigned char *s = tmprsz.s; | ||
1158 | int len = 0; | ||
1159 | int in, out; | ||
1160 | |||
1161 | if (dir == RESIZE_DIR_H) { | ||
1162 | in = mf_in->width; | ||
1163 | out = pix_out->width; | ||
1164 | } else { | ||
1165 | in = mf_in->height; | ||
1166 | out = pix_out->height; | ||
1167 | } | ||
1168 | |||
1169 | if (in < out) | ||
1170 | return -EINVAL; | ||
1171 | else if (in == out) | ||
1172 | continue; | ||
1173 | |||
1174 | /* Calculate ratio */ | ||
1175 | m = gcd(in, out); | ||
1176 | num = in / m; | ||
1177 | den = out / m; | ||
1178 | if (num > RESIZE_NUM_MAX) | ||
1179 | return -EINVAL; | ||
1180 | |||
1181 | if ((num >= 2 * den) && (den == 1) && | ||
1182 | (num < 9) && (!(num & 0x01))) { | ||
1183 | int sum = 0; | ||
1184 | int j; | ||
1185 | |||
1186 | /* Average scaling for >= 2:1 ratios */ | ||
1187 | /* Support can be added for num >=9 and odd values */ | ||
1188 | |||
1189 | tmprsz.algo = RESIZE_ALGO_AVERAGING; | ||
1190 | len = num; | ||
1191 | |||
1192 | for (i = 0; i < (len / 2); i++) | ||
1193 | s[i] = 8; | ||
1194 | |||
1195 | do { | ||
1196 | for (i = 0; i < (len / 2); i++) { | ||
1197 | s[i] = s[i] >> 1; | ||
1198 | sum = 0; | ||
1199 | for (j = 0; j < (len / 2); j++) | ||
1200 | sum += s[j]; | ||
1201 | if (sum == 4) | ||
1202 | break; | ||
1203 | } | ||
1204 | } while (sum != 4); | ||
1205 | |||
1206 | for (i = (len / 2); i < len; i++) | ||
1207 | s[i] = s[len - i - 1]; | ||
1208 | |||
1209 | s[len - 1] |= SZ_COEF; | ||
1210 | } else { | ||
1211 | /* bilinear scaling for < 2:1 ratios */ | ||
1212 | int v; /* overflow counter */ | ||
1213 | int coeff, nxt; /* table output */ | ||
1214 | int in_pos_inc = 2 * den; | ||
1215 | int out_pos = num; | ||
1216 | int out_pos_inc = 2 * num; | ||
1217 | int init_carry = num - den; | ||
1218 | int carry = init_carry; | ||
1219 | |||
1220 | tmprsz.algo = RESIZE_ALGO_BILINEAR; | ||
1221 | v = den + in_pos_inc; | ||
1222 | do { | ||
1223 | coeff = v - out_pos; | ||
1224 | out_pos += out_pos_inc; | ||
1225 | carry += out_pos_inc; | ||
1226 | for (nxt = 0; v < out_pos; nxt++) { | ||
1227 | v += in_pos_inc; | ||
1228 | carry -= in_pos_inc; | ||
1229 | } | ||
1230 | |||
1231 | if (len > RESIZE_NUM_MAX) | ||
1232 | return -EINVAL; | ||
1233 | |||
1234 | coeff = ((coeff << BC_COEF) + | ||
1235 | (in_pos_inc >> 1)) / in_pos_inc; | ||
1236 | |||
1237 | if (coeff >= (SZ_COEF - 1)) | ||
1238 | coeff--; | ||
1239 | |||
1240 | coeff |= SZ_COEF; | ||
1241 | s[len] = (unsigned char)coeff; | ||
1242 | len++; | ||
1243 | |||
1244 | for (i = 1; i < nxt; i++) { | ||
1245 | if (len >= RESIZE_NUM_MAX) | ||
1246 | return -EINVAL; | ||
1247 | s[len] = 0; | ||
1248 | len++; | ||
1249 | } | ||
1250 | } while (carry != init_carry); | ||
1251 | } | ||
1252 | tmprsz.len = len; | ||
1253 | if (dir == RESIZE_DIR_H) | ||
1254 | mf_in->width = pix_out->width; | ||
1255 | else | ||
1256 | mf_in->height = pix_out->height; | ||
1257 | |||
1258 | if (apply) | ||
1259 | memcpy(&pcdev->resizing[dir], &tmprsz, sizeof(tmprsz)); | ||
1260 | } | ||
1261 | return 0; | ||
1262 | } | ||
1263 | |||
1055 | static int mx2_camera_set_fmt(struct soc_camera_device *icd, | 1264 | static int mx2_camera_set_fmt(struct soc_camera_device *icd, |
1056 | struct v4l2_format *f) | 1265 | struct v4l2_format *f) |
1057 | { | 1266 | { |
@@ -1063,6 +1272,9 @@ static int mx2_camera_set_fmt(struct soc_camera_device *icd, | |||
1063 | struct v4l2_mbus_framefmt mf; | 1272 | struct v4l2_mbus_framefmt mf; |
1064 | int ret; | 1273 | int ret; |
1065 | 1274 | ||
1275 | dev_dbg(icd->parent, "%s: requested params: width = %d, height = %d\n", | ||
1276 | __func__, pix->width, pix->height); | ||
1277 | |||
1066 | xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); | 1278 | xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); |
1067 | if (!xlate) { | 1279 | if (!xlate) { |
1068 | dev_warn(icd->parent, "Format %x not found\n", | 1280 | dev_warn(icd->parent, "Format %x not found\n", |
@@ -1080,6 +1292,22 @@ static int mx2_camera_set_fmt(struct soc_camera_device *icd, | |||
1080 | if (ret < 0 && ret != -ENOIOCTLCMD) | 1292 | if (ret < 0 && ret != -ENOIOCTLCMD) |
1081 | return ret; | 1293 | return ret; |
1082 | 1294 | ||
1295 | /* Store width and height returned by the sensor for resizing */ | ||
1296 | pcdev->s_width = mf.width; | ||
1297 | pcdev->s_height = mf.height; | ||
1298 | dev_dbg(icd->parent, "%s: sensor params: width = %d, height = %d\n", | ||
1299 | __func__, pcdev->s_width, pcdev->s_height); | ||
1300 | |||
1301 | pcdev->emma_prp = mx27_emma_prp_get_format(xlate->code, | ||
1302 | xlate->host_fmt->fourcc); | ||
1303 | |||
1304 | memset(pcdev->resizing, 0, sizeof(pcdev->resizing)); | ||
1305 | if ((mf.width != pix->width || mf.height != pix->height) && | ||
1306 | pcdev->emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) { | ||
1307 | if (mx2_emmaprp_resize(pcdev, &mf, pix, true) < 0) | ||
1308 | dev_dbg(icd->parent, "%s: can't resize\n", __func__); | ||
1309 | } | ||
1310 | |||
1083 | if (mf.code != xlate->code) | 1311 | if (mf.code != xlate->code) |
1084 | return -EINVAL; | 1312 | return -EINVAL; |
1085 | 1313 | ||
@@ -1089,9 +1317,8 @@ static int mx2_camera_set_fmt(struct soc_camera_device *icd, | |||
1089 | pix->colorspace = mf.colorspace; | 1317 | pix->colorspace = mf.colorspace; |
1090 | icd->current_fmt = xlate; | 1318 | icd->current_fmt = xlate; |
1091 | 1319 | ||
1092 | if (mx27_camera_emma(pcdev)) | 1320 | dev_dbg(icd->parent, "%s: returned params: width = %d, height = %d\n", |
1093 | pcdev->emma_prp = mx27_emma_prp_get_format(xlate->code, | 1321 | __func__, pix->width, pix->height); |
1094 | xlate->host_fmt->fourcc); | ||
1095 | 1322 | ||
1096 | return 0; | 1323 | return 0; |
1097 | } | 1324 | } |
@@ -1104,9 +1331,14 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd, | |||
1104 | struct v4l2_pix_format *pix = &f->fmt.pix; | 1331 | struct v4l2_pix_format *pix = &f->fmt.pix; |
1105 | struct v4l2_mbus_framefmt mf; | 1332 | struct v4l2_mbus_framefmt mf; |
1106 | __u32 pixfmt = pix->pixelformat; | 1333 | __u32 pixfmt = pix->pixelformat; |
1334 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
1335 | struct mx2_camera_dev *pcdev = ici->priv; | ||
1107 | unsigned int width_limit; | 1336 | unsigned int width_limit; |
1108 | int ret; | 1337 | int ret; |
1109 | 1338 | ||
1339 | dev_dbg(icd->parent, "%s: requested params: width = %d, height = %d\n", | ||
1340 | __func__, pix->width, pix->height); | ||
1341 | |||
1110 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); | 1342 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); |
1111 | if (pixfmt && !xlate) { | 1343 | if (pixfmt && !xlate) { |
1112 | dev_warn(icd->parent, "Format %x not found\n", pixfmt); | 1344 | dev_warn(icd->parent, "Format %x not found\n", pixfmt); |
@@ -1156,6 +1388,20 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd, | |||
1156 | if (ret < 0) | 1388 | if (ret < 0) |
1157 | return ret; | 1389 | return ret; |
1158 | 1390 | ||
1391 | dev_dbg(icd->parent, "%s: sensor params: width = %d, height = %d\n", | ||
1392 | __func__, pcdev->s_width, pcdev->s_height); | ||
1393 | |||
1394 | /* If the sensor does not support image size try PrP resizing */ | ||
1395 | pcdev->emma_prp = mx27_emma_prp_get_format(xlate->code, | ||
1396 | xlate->host_fmt->fourcc); | ||
1397 | |||
1398 | memset(pcdev->resizing, 0, sizeof(pcdev->resizing)); | ||
1399 | if ((mf.width != pix->width || mf.height != pix->height) && | ||
1400 | pcdev->emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) { | ||
1401 | if (mx2_emmaprp_resize(pcdev, &mf, pix, false) < 0) | ||
1402 | dev_dbg(icd->parent, "%s: can't resize\n", __func__); | ||
1403 | } | ||
1404 | |||
1159 | if (mf.field == V4L2_FIELD_ANY) | 1405 | if (mf.field == V4L2_FIELD_ANY) |
1160 | mf.field = V4L2_FIELD_NONE; | 1406 | mf.field = V4L2_FIELD_NONE; |
1161 | /* | 1407 | /* |
@@ -1174,6 +1420,9 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd, | |||
1174 | pix->field = mf.field; | 1420 | pix->field = mf.field; |
1175 | pix->colorspace = mf.colorspace; | 1421 | pix->colorspace = mf.colorspace; |
1176 | 1422 | ||
1423 | dev_dbg(icd->parent, "%s: returned params: width = %d, height = %d\n", | ||
1424 | __func__, pix->width, pix->height); | ||
1425 | |||
1177 | return 0; | 1426 | return 0; |
1178 | } | 1427 | } |
1179 | 1428 | ||
@@ -1187,136 +1436,11 @@ static int mx2_camera_querycap(struct soc_camera_host *ici, | |||
1187 | return 0; | 1436 | return 0; |
1188 | } | 1437 | } |
1189 | 1438 | ||
1190 | static int mx2_camera_reqbufs(struct soc_camera_device *icd, | ||
1191 | struct v4l2_requestbuffers *p) | ||
1192 | { | ||
1193 | int i; | ||
1194 | |||
1195 | for (i = 0; i < p->count; i++) { | ||
1196 | struct mx2_buffer *buf = container_of(icd->vb_vidq.bufs[i], | ||
1197 | struct mx2_buffer, vb); | ||
1198 | INIT_LIST_HEAD(&buf->vb.queue); | ||
1199 | } | ||
1200 | |||
1201 | return 0; | ||
1202 | } | ||
1203 | |||
1204 | #ifdef CONFIG_MACH_MX27 | ||
1205 | static void mx27_camera_frame_done(struct mx2_camera_dev *pcdev, int state) | ||
1206 | { | ||
1207 | struct videobuf_buffer *vb; | ||
1208 | struct mx2_buffer *buf; | ||
1209 | unsigned long flags; | ||
1210 | int ret; | ||
1211 | |||
1212 | spin_lock_irqsave(&pcdev->lock, flags); | ||
1213 | |||
1214 | if (!pcdev->active) { | ||
1215 | dev_err(pcdev->dev, "%s called with no active buffer!\n", | ||
1216 | __func__); | ||
1217 | goto out; | ||
1218 | } | ||
1219 | |||
1220 | vb = &pcdev->active->vb; | ||
1221 | buf = container_of(vb, struct mx2_buffer, vb); | ||
1222 | WARN_ON(list_empty(&vb->queue)); | ||
1223 | dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, | ||
1224 | vb, vb->baddr, vb->bsize); | ||
1225 | |||
1226 | /* _init is used to debug races, see comment in pxa_camera_reqbufs() */ | ||
1227 | list_del_init(&vb->queue); | ||
1228 | vb->state = state; | ||
1229 | do_gettimeofday(&vb->ts); | ||
1230 | vb->field_count++; | ||
1231 | |||
1232 | wake_up(&vb->done); | ||
1233 | |||
1234 | if (list_empty(&pcdev->capture)) { | ||
1235 | pcdev->active = NULL; | ||
1236 | goto out; | ||
1237 | } | ||
1238 | |||
1239 | pcdev->active = list_entry(pcdev->capture.next, | ||
1240 | struct mx2_buffer, vb.queue); | ||
1241 | |||
1242 | vb = &pcdev->active->vb; | ||
1243 | vb->state = VIDEOBUF_ACTIVE; | ||
1244 | |||
1245 | ret = imx_dma_setup_single(pcdev->dma, videobuf_to_dma_contig(vb), | ||
1246 | vb->size, (u32)pcdev->base_dma + 0x10, DMA_MODE_READ); | ||
1247 | |||
1248 | if (ret) { | ||
1249 | vb->state = VIDEOBUF_ERROR; | ||
1250 | pcdev->active = NULL; | ||
1251 | wake_up(&vb->done); | ||
1252 | } | ||
1253 | |||
1254 | out: | ||
1255 | spin_unlock_irqrestore(&pcdev->lock, flags); | ||
1256 | } | ||
1257 | |||
1258 | static void mx27_camera_dma_err_callback(int channel, void *data, int err) | ||
1259 | { | ||
1260 | struct mx2_camera_dev *pcdev = data; | ||
1261 | |||
1262 | mx27_camera_frame_done(pcdev, VIDEOBUF_ERROR); | ||
1263 | } | ||
1264 | |||
1265 | static void mx27_camera_dma_callback(int channel, void *data) | ||
1266 | { | ||
1267 | struct mx2_camera_dev *pcdev = data; | ||
1268 | |||
1269 | mx27_camera_frame_done(pcdev, VIDEOBUF_DONE); | ||
1270 | } | ||
1271 | |||
1272 | #define DMA_REQ_CSI_RX 31 /* FIXME: Add this to a resource */ | ||
1273 | |||
1274 | static int __devinit mx27_camera_dma_init(struct platform_device *pdev, | ||
1275 | struct mx2_camera_dev *pcdev) | ||
1276 | { | ||
1277 | int err; | ||
1278 | |||
1279 | pcdev->dma = imx_dma_request_by_prio("CSI RX DMA", DMA_PRIO_HIGH); | ||
1280 | if (pcdev->dma < 0) { | ||
1281 | dev_err(&pdev->dev, "%s failed to request DMA channel\n", | ||
1282 | __func__); | ||
1283 | return pcdev->dma; | ||
1284 | } | ||
1285 | |||
1286 | err = imx_dma_setup_handlers(pcdev->dma, mx27_camera_dma_callback, | ||
1287 | mx27_camera_dma_err_callback, pcdev); | ||
1288 | if (err) { | ||
1289 | dev_err(&pdev->dev, "%s failed to set DMA callback\n", | ||
1290 | __func__); | ||
1291 | goto err_out; | ||
1292 | } | ||
1293 | |||
1294 | err = imx_dma_config_channel(pcdev->dma, | ||
1295 | IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_FIFO, | ||
1296 | IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR, | ||
1297 | DMA_REQ_CSI_RX, 1); | ||
1298 | if (err) { | ||
1299 | dev_err(&pdev->dev, "%s failed to config DMA channel\n", | ||
1300 | __func__); | ||
1301 | goto err_out; | ||
1302 | } | ||
1303 | |||
1304 | imx_dma_config_burstlen(pcdev->dma, 64); | ||
1305 | |||
1306 | return 0; | ||
1307 | |||
1308 | err_out: | ||
1309 | imx_dma_free(pcdev->dma); | ||
1310 | |||
1311 | return err; | ||
1312 | } | ||
1313 | #endif /* CONFIG_MACH_MX27 */ | ||
1314 | |||
1315 | static unsigned int mx2_camera_poll(struct file *file, poll_table *pt) | 1439 | static unsigned int mx2_camera_poll(struct file *file, poll_table *pt) |
1316 | { | 1440 | { |
1317 | struct soc_camera_device *icd = file->private_data; | 1441 | struct soc_camera_device *icd = file->private_data; |
1318 | 1442 | ||
1319 | return videobuf_poll_stream(file, &icd->vb_vidq, pt); | 1443 | return vb2_poll(&icd->vb2_vidq, file, pt); |
1320 | } | 1444 | } |
1321 | 1445 | ||
1322 | static struct soc_camera_host_ops mx2_soc_camera_host_ops = { | 1446 | static struct soc_camera_host_ops mx2_soc_camera_host_ops = { |
@@ -1327,144 +1451,148 @@ static struct soc_camera_host_ops mx2_soc_camera_host_ops = { | |||
1327 | .set_crop = mx2_camera_set_crop, | 1451 | .set_crop = mx2_camera_set_crop, |
1328 | .get_formats = mx2_camera_get_formats, | 1452 | .get_formats = mx2_camera_get_formats, |
1329 | .try_fmt = mx2_camera_try_fmt, | 1453 | .try_fmt = mx2_camera_try_fmt, |
1330 | .init_videobuf = mx2_camera_init_videobuf, | 1454 | .init_videobuf2 = mx2_camera_init_videobuf, |
1331 | .reqbufs = mx2_camera_reqbufs, | ||
1332 | .poll = mx2_camera_poll, | 1455 | .poll = mx2_camera_poll, |
1333 | .querycap = mx2_camera_querycap, | 1456 | .querycap = mx2_camera_querycap, |
1334 | .set_bus_param = mx2_camera_set_bus_param, | 1457 | .set_bus_param = mx2_camera_set_bus_param, |
1335 | }; | 1458 | }; |
1336 | 1459 | ||
1337 | static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, | 1460 | static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, |
1338 | int bufnum, int state) | 1461 | int bufnum, bool err) |
1339 | { | 1462 | { |
1340 | u32 imgsize = pcdev->icd->user_height * pcdev->icd->user_width; | 1463 | #ifdef DEBUG |
1341 | struct mx2_fmt_cfg *prp = pcdev->emma_prp; | 1464 | struct mx2_fmt_cfg *prp = pcdev->emma_prp; |
1465 | #endif | ||
1466 | struct mx2_buf_internal *ibuf; | ||
1342 | struct mx2_buffer *buf; | 1467 | struct mx2_buffer *buf; |
1343 | struct videobuf_buffer *vb; | 1468 | struct vb2_buffer *vb; |
1344 | unsigned long phys; | 1469 | unsigned long phys; |
1345 | 1470 | ||
1346 | if (!list_empty(&pcdev->active_bufs)) { | 1471 | ibuf = list_first_entry(&pcdev->active_bufs, struct mx2_buf_internal, |
1347 | buf = list_entry(pcdev->active_bufs.next, | 1472 | queue); |
1348 | struct mx2_buffer, vb.queue); | 1473 | |
1474 | BUG_ON(ibuf->bufnum != bufnum); | ||
1349 | 1475 | ||
1350 | BUG_ON(buf->bufnum != bufnum); | 1476 | if (ibuf->discard) { |
1477 | /* | ||
1478 | * Discard buffer must not be returned to user space. | ||
1479 | * Just return it to the discard queue. | ||
1480 | */ | ||
1481 | list_move_tail(pcdev->active_bufs.next, &pcdev->discard); | ||
1482 | } else { | ||
1483 | buf = mx2_ibuf_to_buf(ibuf); | ||
1351 | 1484 | ||
1352 | vb = &buf->vb; | 1485 | vb = &buf->vb; |
1353 | #ifdef DEBUG | 1486 | #ifdef DEBUG |
1354 | phys = videobuf_to_dma_contig(vb); | 1487 | phys = vb2_dma_contig_plane_dma_addr(vb, 0); |
1355 | if (prp->cfg.channel == 1) { | 1488 | if (prp->cfg.channel == 1) { |
1356 | if (readl(pcdev->base_emma + PRP_DEST_RGB1_PTR + | 1489 | if (readl(pcdev->base_emma + PRP_DEST_RGB1_PTR + |
1357 | 4 * bufnum) != phys) { | 1490 | 4 * bufnum) != phys) { |
1358 | dev_err(pcdev->dev, "%p != %p\n", phys, | 1491 | dev_err(pcdev->dev, "%lx != %x\n", phys, |
1359 | readl(pcdev->base_emma + | 1492 | readl(pcdev->base_emma + |
1360 | PRP_DEST_RGB1_PTR + | 1493 | PRP_DEST_RGB1_PTR + 4 * bufnum)); |
1361 | 4 * bufnum)); | ||
1362 | } | 1494 | } |
1363 | } else { | 1495 | } else { |
1364 | if (readl(pcdev->base_emma + PRP_DEST_Y_PTR - | 1496 | if (readl(pcdev->base_emma + PRP_DEST_Y_PTR - |
1365 | 0x14 * bufnum) != phys) { | 1497 | 0x14 * bufnum) != phys) { |
1366 | dev_err(pcdev->dev, "%p != %p\n", phys, | 1498 | dev_err(pcdev->dev, "%lx != %x\n", phys, |
1367 | readl(pcdev->base_emma + | 1499 | readl(pcdev->base_emma + |
1368 | PRP_DEST_Y_PTR - | 1500 | PRP_DEST_Y_PTR - 0x14 * bufnum)); |
1369 | 0x14 * bufnum)); | ||
1370 | } | 1501 | } |
1371 | } | 1502 | } |
1372 | #endif | 1503 | #endif |
1373 | dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, | 1504 | dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__, vb, |
1374 | vb->baddr, vb->bsize); | 1505 | vb2_plane_vaddr(vb, 0), |
1506 | vb2_get_plane_payload(vb, 0)); | ||
1375 | 1507 | ||
1376 | list_del(&vb->queue); | 1508 | list_del_init(&buf->internal.queue); |
1377 | vb->state = state; | 1509 | do_gettimeofday(&vb->v4l2_buf.timestamp); |
1378 | do_gettimeofday(&vb->ts); | 1510 | vb->v4l2_buf.sequence = pcdev->frame_count; |
1379 | vb->field_count = pcdev->frame_count * 2; | 1511 | if (err) |
1380 | pcdev->frame_count++; | 1512 | vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); |
1381 | 1513 | else | |
1382 | wake_up(&vb->done); | 1514 | vb2_buffer_done(vb, VB2_BUF_STATE_DONE); |
1383 | } | 1515 | } |
1384 | 1516 | ||
1517 | pcdev->frame_count++; | ||
1518 | |||
1385 | if (list_empty(&pcdev->capture)) { | 1519 | if (list_empty(&pcdev->capture)) { |
1386 | if (prp->cfg.channel == 1) { | 1520 | if (list_empty(&pcdev->discard)) { |
1387 | writel(pcdev->discard_buffer_dma, pcdev->base_emma + | 1521 | dev_warn(pcdev->dev, "%s: trying to access empty discard list\n", |
1388 | PRP_DEST_RGB1_PTR + 4 * bufnum); | 1522 | __func__); |
1389 | } else { | 1523 | return; |
1390 | writel(pcdev->discard_buffer_dma, pcdev->base_emma + | ||
1391 | PRP_DEST_Y_PTR - | ||
1392 | 0x14 * bufnum); | ||
1393 | if (prp->out_fmt == V4L2_PIX_FMT_YUV420) { | ||
1394 | writel(pcdev->discard_buffer_dma + imgsize, | ||
1395 | pcdev->base_emma + PRP_DEST_CB_PTR - | ||
1396 | 0x14 * bufnum); | ||
1397 | writel(pcdev->discard_buffer_dma + | ||
1398 | ((5 * imgsize) / 4), pcdev->base_emma + | ||
1399 | PRP_DEST_CR_PTR - 0x14 * bufnum); | ||
1400 | } | ||
1401 | } | 1524 | } |
1525 | |||
1526 | ibuf = list_first_entry(&pcdev->discard, | ||
1527 | struct mx2_buf_internal, queue); | ||
1528 | ibuf->bufnum = bufnum; | ||
1529 | |||
1530 | list_move_tail(pcdev->discard.next, &pcdev->active_bufs); | ||
1531 | mx27_update_emma_buf(pcdev, pcdev->discard_buffer_dma, bufnum); | ||
1402 | return; | 1532 | return; |
1403 | } | 1533 | } |
1404 | 1534 | ||
1405 | buf = list_entry(pcdev->capture.next, | 1535 | buf = list_first_entry(&pcdev->capture, struct mx2_buffer, |
1406 | struct mx2_buffer, vb.queue); | 1536 | internal.queue); |
1407 | 1537 | ||
1408 | buf->bufnum = !bufnum; | 1538 | buf->internal.bufnum = bufnum; |
1409 | 1539 | ||
1410 | list_move_tail(pcdev->capture.next, &pcdev->active_bufs); | 1540 | list_move_tail(pcdev->capture.next, &pcdev->active_bufs); |
1411 | 1541 | ||
1412 | vb = &buf->vb; | 1542 | vb = &buf->vb; |
1413 | vb->state = VIDEOBUF_ACTIVE; | 1543 | buf->state = MX2_STATE_ACTIVE; |
1414 | 1544 | ||
1415 | phys = videobuf_to_dma_contig(vb); | 1545 | phys = vb2_dma_contig_plane_dma_addr(vb, 0); |
1416 | if (prp->cfg.channel == 1) { | 1546 | mx27_update_emma_buf(pcdev, phys, bufnum); |
1417 | writel(phys, pcdev->base_emma + PRP_DEST_RGB1_PTR + 4 * bufnum); | ||
1418 | } else { | ||
1419 | writel(phys, pcdev->base_emma + | ||
1420 | PRP_DEST_Y_PTR - 0x14 * bufnum); | ||
1421 | if (prp->cfg.out_fmt == PRP_CNTL_CH2_OUT_YUV420) { | ||
1422 | writel(phys + imgsize, pcdev->base_emma + | ||
1423 | PRP_DEST_CB_PTR - 0x14 * bufnum); | ||
1424 | writel(phys + ((5 * imgsize) / 4), pcdev->base_emma + | ||
1425 | PRP_DEST_CR_PTR - 0x14 * bufnum); | ||
1426 | } | ||
1427 | } | ||
1428 | } | 1547 | } |
1429 | 1548 | ||
1430 | static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data) | 1549 | static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data) |
1431 | { | 1550 | { |
1432 | struct mx2_camera_dev *pcdev = data; | 1551 | struct mx2_camera_dev *pcdev = data; |
1433 | unsigned int status = readl(pcdev->base_emma + PRP_INTRSTATUS); | 1552 | unsigned int status = readl(pcdev->base_emma + PRP_INTRSTATUS); |
1434 | struct mx2_buffer *buf; | 1553 | struct mx2_buf_internal *ibuf; |
1554 | |||
1555 | spin_lock(&pcdev->lock); | ||
1556 | |||
1557 | if (list_empty(&pcdev->active_bufs)) { | ||
1558 | dev_warn(pcdev->dev, "%s: called while active list is empty\n", | ||
1559 | __func__); | ||
1560 | |||
1561 | if (!status) { | ||
1562 | spin_unlock(&pcdev->lock); | ||
1563 | return IRQ_NONE; | ||
1564 | } | ||
1565 | } | ||
1435 | 1566 | ||
1436 | if (status & (1 << 7)) { /* overflow */ | 1567 | if (status & (1 << 7)) { /* overflow */ |
1437 | u32 cntl; | 1568 | u32 cntl = readl(pcdev->base_emma + PRP_CNTL); |
1438 | /* | ||
1439 | * We only disable channel 1 here since this is the only | ||
1440 | * enabled channel | ||
1441 | * | ||
1442 | * FIXME: the correct DMA overflow handling should be resetting | ||
1443 | * the buffer, returning an error frame, and continuing with | ||
1444 | * the next one. | ||
1445 | */ | ||
1446 | cntl = readl(pcdev->base_emma + PRP_CNTL); | ||
1447 | writel(cntl & ~(PRP_CNTL_CH1EN | PRP_CNTL_CH2EN), | 1569 | writel(cntl & ~(PRP_CNTL_CH1EN | PRP_CNTL_CH2EN), |
1448 | pcdev->base_emma + PRP_CNTL); | 1570 | pcdev->base_emma + PRP_CNTL); |
1449 | writel(cntl, pcdev->base_emma + PRP_CNTL); | 1571 | writel(cntl, pcdev->base_emma + PRP_CNTL); |
1450 | } | 1572 | |
1451 | if ((((status & (3 << 5)) == (3 << 5)) || | 1573 | ibuf = list_first_entry(&pcdev->active_bufs, |
1452 | ((status & (3 << 3)) == (3 << 3))) | 1574 | struct mx2_buf_internal, queue); |
1453 | && !list_empty(&pcdev->active_bufs)) { | 1575 | mx27_camera_frame_done_emma(pcdev, |
1576 | ibuf->bufnum, true); | ||
1577 | |||
1578 | status &= ~(1 << 7); | ||
1579 | } else if (((status & (3 << 5)) == (3 << 5)) || | ||
1580 | ((status & (3 << 3)) == (3 << 3))) { | ||
1454 | /* | 1581 | /* |
1455 | * Both buffers have triggered, process the one we're expecting | 1582 | * Both buffers have triggered, process the one we're expecting |
1456 | * to first | 1583 | * to first |
1457 | */ | 1584 | */ |
1458 | buf = list_entry(pcdev->active_bufs.next, | 1585 | ibuf = list_first_entry(&pcdev->active_bufs, |
1459 | struct mx2_buffer, vb.queue); | 1586 | struct mx2_buf_internal, queue); |
1460 | mx27_camera_frame_done_emma(pcdev, buf->bufnum, VIDEOBUF_DONE); | 1587 | mx27_camera_frame_done_emma(pcdev, ibuf->bufnum, false); |
1461 | status &= ~(1 << (6 - buf->bufnum)); /* mark processed */ | 1588 | status &= ~(1 << (6 - ibuf->bufnum)); /* mark processed */ |
1589 | } else if ((status & (1 << 6)) || (status & (1 << 4))) { | ||
1590 | mx27_camera_frame_done_emma(pcdev, 0, false); | ||
1591 | } else if ((status & (1 << 5)) || (status & (1 << 3))) { | ||
1592 | mx27_camera_frame_done_emma(pcdev, 1, false); | ||
1462 | } | 1593 | } |
1463 | if ((status & (1 << 6)) || (status & (1 << 4))) | ||
1464 | mx27_camera_frame_done_emma(pcdev, 0, VIDEOBUF_DONE); | ||
1465 | if ((status & (1 << 5)) || (status & (1 << 3))) | ||
1466 | mx27_camera_frame_done_emma(pcdev, 1, VIDEOBUF_DONE); | ||
1467 | 1594 | ||
1595 | spin_unlock(&pcdev->lock); | ||
1468 | writel(status, pcdev->base_emma + PRP_INTRSTATUS); | 1596 | writel(status, pcdev->base_emma + PRP_INTRSTATUS); |
1469 | 1597 | ||
1470 | return IRQ_HANDLED; | 1598 | return IRQ_HANDLED; |
@@ -1527,8 +1655,6 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev) | |||
1527 | struct resource *res_csi, *res_emma; | 1655 | struct resource *res_csi, *res_emma; |
1528 | void __iomem *base_csi; | 1656 | void __iomem *base_csi; |
1529 | int irq_csi, irq_emma; | 1657 | int irq_csi, irq_emma; |
1530 | irq_handler_t mx2_cam_irq_handler = cpu_is_mx25() ? mx25_camera_irq | ||
1531 | : mx27_camera_irq; | ||
1532 | int err = 0; | 1658 | int err = 0; |
1533 | 1659 | ||
1534 | dev_dbg(&pdev->dev, "initialising\n"); | 1660 | dev_dbg(&pdev->dev, "initialising\n"); |
@@ -1550,22 +1676,11 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev) | |||
1550 | 1676 | ||
1551 | pcdev->clk_csi = clk_get(&pdev->dev, NULL); | 1677 | pcdev->clk_csi = clk_get(&pdev->dev, NULL); |
1552 | if (IS_ERR(pcdev->clk_csi)) { | 1678 | if (IS_ERR(pcdev->clk_csi)) { |
1679 | dev_err(&pdev->dev, "Could not get csi clock\n"); | ||
1553 | err = PTR_ERR(pcdev->clk_csi); | 1680 | err = PTR_ERR(pcdev->clk_csi); |
1554 | goto exit_kfree; | 1681 | goto exit_kfree; |
1555 | } | 1682 | } |
1556 | 1683 | ||
1557 | dev_dbg(&pdev->dev, "Camera clock frequency: %ld\n", | ||
1558 | clk_get_rate(pcdev->clk_csi)); | ||
1559 | |||
1560 | /* Initialize DMA */ | ||
1561 | #ifdef CONFIG_MACH_MX27 | ||
1562 | if (cpu_is_mx27()) { | ||
1563 | err = mx27_camera_dma_init(pdev, pcdev); | ||
1564 | if (err) | ||
1565 | goto exit_clk_put; | ||
1566 | } | ||
1567 | #endif /* CONFIG_MACH_MX27 */ | ||
1568 | |||
1569 | pcdev->res_csi = res_csi; | 1684 | pcdev->res_csi = res_csi; |
1570 | pcdev->pdata = pdev->dev.platform_data; | 1685 | pcdev->pdata = pdev->dev.platform_data; |
1571 | if (pcdev->pdata) { | 1686 | if (pcdev->pdata) { |
@@ -1585,6 +1700,7 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev) | |||
1585 | 1700 | ||
1586 | INIT_LIST_HEAD(&pcdev->capture); | 1701 | INIT_LIST_HEAD(&pcdev->capture); |
1587 | INIT_LIST_HEAD(&pcdev->active_bufs); | 1702 | INIT_LIST_HEAD(&pcdev->active_bufs); |
1703 | INIT_LIST_HEAD(&pcdev->discard); | ||
1588 | spin_lock_init(&pcdev->lock); | 1704 | spin_lock_init(&pcdev->lock); |
1589 | 1705 | ||
1590 | /* | 1706 | /* |
@@ -1606,11 +1722,13 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev) | |||
1606 | pcdev->base_dma = res_csi->start; | 1722 | pcdev->base_dma = res_csi->start; |
1607 | pcdev->dev = &pdev->dev; | 1723 | pcdev->dev = &pdev->dev; |
1608 | 1724 | ||
1609 | err = request_irq(pcdev->irq_csi, mx2_cam_irq_handler, 0, | 1725 | if (cpu_is_mx25()) { |
1610 | MX2_CAM_DRV_NAME, pcdev); | 1726 | err = request_irq(pcdev->irq_csi, mx25_camera_irq, 0, |
1611 | if (err) { | 1727 | MX2_CAM_DRV_NAME, pcdev); |
1612 | dev_err(pcdev->dev, "Camera interrupt register failed \n"); | 1728 | if (err) { |
1613 | goto exit_iounmap; | 1729 | dev_err(pcdev->dev, "Camera interrupt register failed \n"); |
1730 | goto exit_iounmap; | ||
1731 | } | ||
1614 | } | 1732 | } |
1615 | 1733 | ||
1616 | if (cpu_is_mx27()) { | 1734 | if (cpu_is_mx27()) { |
@@ -1618,14 +1736,15 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev) | |||
1618 | res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 1736 | res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
1619 | irq_emma = platform_get_irq(pdev, 1); | 1737 | irq_emma = platform_get_irq(pdev, 1); |
1620 | 1738 | ||
1621 | if (res_emma && irq_emma >= 0) { | 1739 | if (!res_emma || !irq_emma) { |
1622 | dev_info(&pdev->dev, "Using EMMA\n"); | 1740 | dev_err(&pdev->dev, "no EMMA resources\n"); |
1623 | pcdev->use_emma = 1; | 1741 | goto exit_free_irq; |
1624 | pcdev->res_emma = res_emma; | ||
1625 | pcdev->irq_emma = irq_emma; | ||
1626 | if (mx27_camera_emma_init(pcdev)) | ||
1627 | goto exit_free_irq; | ||
1628 | } | 1742 | } |
1743 | |||
1744 | pcdev->res_emma = res_emma; | ||
1745 | pcdev->irq_emma = irq_emma; | ||
1746 | if (mx27_camera_emma_init(pcdev)) | ||
1747 | goto exit_free_irq; | ||
1629 | } | 1748 | } |
1630 | 1749 | ||
1631 | pcdev->soc_host.drv_name = MX2_CAM_DRV_NAME, | 1750 | pcdev->soc_host.drv_name = MX2_CAM_DRV_NAME, |
@@ -1633,6 +1752,12 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev) | |||
1633 | pcdev->soc_host.priv = pcdev; | 1752 | pcdev->soc_host.priv = pcdev; |
1634 | pcdev->soc_host.v4l2_dev.dev = &pdev->dev; | 1753 | pcdev->soc_host.v4l2_dev.dev = &pdev->dev; |
1635 | pcdev->soc_host.nr = pdev->id; | 1754 | pcdev->soc_host.nr = pdev->id; |
1755 | |||
1756 | pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); | ||
1757 | if (IS_ERR(pcdev->alloc_ctx)) { | ||
1758 | err = PTR_ERR(pcdev->alloc_ctx); | ||
1759 | goto eallocctx; | ||
1760 | } | ||
1636 | err = soc_camera_host_register(&pcdev->soc_host); | 1761 | err = soc_camera_host_register(&pcdev->soc_host); |
1637 | if (err) | 1762 | if (err) |
1638 | goto exit_free_emma; | 1763 | goto exit_free_emma; |
@@ -1643,26 +1768,24 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev) | |||
1643 | return 0; | 1768 | return 0; |
1644 | 1769 | ||
1645 | exit_free_emma: | 1770 | exit_free_emma: |
1646 | if (mx27_camera_emma(pcdev)) { | 1771 | vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); |
1772 | eallocctx: | ||
1773 | if (cpu_is_mx27()) { | ||
1647 | free_irq(pcdev->irq_emma, pcdev); | 1774 | free_irq(pcdev->irq_emma, pcdev); |
1648 | clk_disable(pcdev->clk_emma); | 1775 | clk_disable(pcdev->clk_emma); |
1649 | clk_put(pcdev->clk_emma); | 1776 | clk_put(pcdev->clk_emma); |
1650 | iounmap(pcdev->base_emma); | 1777 | iounmap(pcdev->base_emma); |
1651 | release_mem_region(res_emma->start, resource_size(res_emma)); | 1778 | release_mem_region(pcdev->res_emma->start, resource_size(pcdev->res_emma)); |
1652 | } | 1779 | } |
1653 | exit_free_irq: | 1780 | exit_free_irq: |
1654 | free_irq(pcdev->irq_csi, pcdev); | 1781 | if (cpu_is_mx25()) |
1782 | free_irq(pcdev->irq_csi, pcdev); | ||
1655 | exit_iounmap: | 1783 | exit_iounmap: |
1656 | iounmap(base_csi); | 1784 | iounmap(base_csi); |
1657 | exit_release: | 1785 | exit_release: |
1658 | release_mem_region(res_csi->start, resource_size(res_csi)); | 1786 | release_mem_region(res_csi->start, resource_size(res_csi)); |
1659 | exit_dma_free: | 1787 | exit_dma_free: |
1660 | #ifdef CONFIG_MACH_MX27 | ||
1661 | if (cpu_is_mx27()) | ||
1662 | imx_dma_free(pcdev->dma); | ||
1663 | exit_clk_put: | ||
1664 | clk_put(pcdev->clk_csi); | 1788 | clk_put(pcdev->clk_csi); |
1665 | #endif /* CONFIG_MACH_MX27 */ | ||
1666 | exit_kfree: | 1789 | exit_kfree: |
1667 | kfree(pcdev); | 1790 | kfree(pcdev); |
1668 | exit: | 1791 | exit: |
@@ -1677,19 +1800,18 @@ static int __devexit mx2_camera_remove(struct platform_device *pdev) | |||
1677 | struct resource *res; | 1800 | struct resource *res; |
1678 | 1801 | ||
1679 | clk_put(pcdev->clk_csi); | 1802 | clk_put(pcdev->clk_csi); |
1680 | #ifdef CONFIG_MACH_MX27 | 1803 | if (cpu_is_mx25()) |
1804 | free_irq(pcdev->irq_csi, pcdev); | ||
1681 | if (cpu_is_mx27()) | 1805 | if (cpu_is_mx27()) |
1682 | imx_dma_free(pcdev->dma); | ||
1683 | #endif /* CONFIG_MACH_MX27 */ | ||
1684 | free_irq(pcdev->irq_csi, pcdev); | ||
1685 | if (mx27_camera_emma(pcdev)) | ||
1686 | free_irq(pcdev->irq_emma, pcdev); | 1806 | free_irq(pcdev->irq_emma, pcdev); |
1687 | 1807 | ||
1688 | soc_camera_host_unregister(&pcdev->soc_host); | 1808 | soc_camera_host_unregister(&pcdev->soc_host); |
1689 | 1809 | ||
1810 | vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); | ||
1811 | |||
1690 | iounmap(pcdev->base_csi); | 1812 | iounmap(pcdev->base_csi); |
1691 | 1813 | ||
1692 | if (mx27_camera_emma(pcdev)) { | 1814 | if (cpu_is_mx27()) { |
1693 | clk_disable(pcdev->clk_emma); | 1815 | clk_disable(pcdev->clk_emma); |
1694 | clk_put(pcdev->clk_emma); | 1816 | clk_put(pcdev->clk_emma); |
1695 | iounmap(pcdev->base_emma); | 1817 | iounmap(pcdev->base_emma); |
diff --git a/drivers/media/video/mx2_emmaprp.c b/drivers/media/video/mx2_emmaprp.c new file mode 100644 index 000000000000..ba89a7401c8c --- /dev/null +++ b/drivers/media/video/mx2_emmaprp.c | |||
@@ -0,0 +1,1008 @@ | |||
1 | /* | ||
2 | * Support eMMa-PrP through mem2mem framework. | ||
3 | * | ||
4 | * eMMa-PrP is a piece of HW that allows fetching buffers | ||
5 | * from one memory location and do several operations on | ||
6 | * them such as scaling or format conversion giving, as a result | ||
7 | * a new processed buffer in another memory location. | ||
8 | * | ||
9 | * Based on mem2mem_testdev.c by Pawel Osciak. | ||
10 | * | ||
11 | * Copyright (c) 2011 Vista Silicon S.L. | ||
12 | * Javier Martin <javier.martin@vista-silicon.com> | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by the | ||
16 | * Free Software Foundation; either version 2 of the | ||
17 | * License, or (at your option) any later version | ||
18 | */ | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/clk.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/io.h> | ||
24 | |||
25 | #include <linux/platform_device.h> | ||
26 | #include <media/v4l2-mem2mem.h> | ||
27 | #include <media/v4l2-device.h> | ||
28 | #include <media/v4l2-ioctl.h> | ||
29 | #include <media/videobuf2-dma-contig.h> | ||
30 | #include <asm/sizes.h> | ||
31 | |||
32 | #define EMMAPRP_MODULE_NAME "mem2mem-emmaprp" | ||
33 | |||
34 | MODULE_DESCRIPTION("Mem-to-mem device which supports eMMa-PrP present in mx2 SoCs"); | ||
35 | MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com"); | ||
36 | MODULE_LICENSE("GPL"); | ||
37 | MODULE_VERSION("0.0.1"); | ||
38 | |||
39 | static bool debug; | ||
40 | module_param(debug, bool, 0644); | ||
41 | |||
42 | #define MIN_W 32 | ||
43 | #define MIN_H 32 | ||
44 | #define MAX_W 2040 | ||
45 | #define MAX_H 2046 | ||
46 | |||
47 | #define S_ALIGN 1 /* multiple of 2 */ | ||
48 | #define W_ALIGN_YUV420 3 /* multiple of 8 */ | ||
49 | #define W_ALIGN_OTHERS 2 /* multiple of 4 */ | ||
50 | #define H_ALIGN 1 /* multiple of 2 */ | ||
51 | |||
52 | /* Flags that indicate a format can be used for capture/output */ | ||
53 | #define MEM2MEM_CAPTURE (1 << 0) | ||
54 | #define MEM2MEM_OUTPUT (1 << 1) | ||
55 | |||
56 | #define MEM2MEM_NAME "m2m-emmaprp" | ||
57 | |||
58 | /* In bytes, per queue */ | ||
59 | #define MEM2MEM_VID_MEM_LIMIT SZ_16M | ||
60 | |||
61 | #define dprintk(dev, fmt, arg...) \ | ||
62 | v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg) | ||
63 | |||
64 | /* EMMA PrP */ | ||
65 | #define PRP_CNTL 0x00 | ||
66 | #define PRP_INTR_CNTL 0x04 | ||
67 | #define PRP_INTRSTATUS 0x08 | ||
68 | #define PRP_SOURCE_Y_PTR 0x0c | ||
69 | #define PRP_SOURCE_CB_PTR 0x10 | ||
70 | #define PRP_SOURCE_CR_PTR 0x14 | ||
71 | #define PRP_DEST_RGB1_PTR 0x18 | ||
72 | #define PRP_DEST_RGB2_PTR 0x1c | ||
73 | #define PRP_DEST_Y_PTR 0x20 | ||
74 | #define PRP_DEST_CB_PTR 0x24 | ||
75 | #define PRP_DEST_CR_PTR 0x28 | ||
76 | #define PRP_SRC_FRAME_SIZE 0x2c | ||
77 | #define PRP_DEST_CH1_LINE_STRIDE 0x30 | ||
78 | #define PRP_SRC_PIXEL_FORMAT_CNTL 0x34 | ||
79 | #define PRP_CH1_PIXEL_FORMAT_CNTL 0x38 | ||
80 | #define PRP_CH1_OUT_IMAGE_SIZE 0x3c | ||
81 | #define PRP_CH2_OUT_IMAGE_SIZE 0x40 | ||
82 | #define PRP_SRC_LINE_STRIDE 0x44 | ||
83 | #define PRP_CSC_COEF_012 0x48 | ||
84 | #define PRP_CSC_COEF_345 0x4c | ||
85 | #define PRP_CSC_COEF_678 0x50 | ||
86 | #define PRP_CH1_RZ_HORI_COEF1 0x54 | ||
87 | #define PRP_CH1_RZ_HORI_COEF2 0x58 | ||
88 | #define PRP_CH1_RZ_HORI_VALID 0x5c | ||
89 | #define PRP_CH1_RZ_VERT_COEF1 0x60 | ||
90 | #define PRP_CH1_RZ_VERT_COEF2 0x64 | ||
91 | #define PRP_CH1_RZ_VERT_VALID 0x68 | ||
92 | #define PRP_CH2_RZ_HORI_COEF1 0x6c | ||
93 | #define PRP_CH2_RZ_HORI_COEF2 0x70 | ||
94 | #define PRP_CH2_RZ_HORI_VALID 0x74 | ||
95 | #define PRP_CH2_RZ_VERT_COEF1 0x78 | ||
96 | #define PRP_CH2_RZ_VERT_COEF2 0x7c | ||
97 | #define PRP_CH2_RZ_VERT_VALID 0x80 | ||
98 | |||
99 | #define PRP_CNTL_CH1EN (1 << 0) | ||
100 | #define PRP_CNTL_CH2EN (1 << 1) | ||
101 | #define PRP_CNTL_CSIEN (1 << 2) | ||
102 | #define PRP_CNTL_DATA_IN_YUV420 (0 << 3) | ||
103 | #define PRP_CNTL_DATA_IN_YUV422 (1 << 3) | ||
104 | #define PRP_CNTL_DATA_IN_RGB16 (2 << 3) | ||
105 | #define PRP_CNTL_DATA_IN_RGB32 (3 << 3) | ||
106 | #define PRP_CNTL_CH1_OUT_RGB8 (0 << 5) | ||
107 | #define PRP_CNTL_CH1_OUT_RGB16 (1 << 5) | ||
108 | #define PRP_CNTL_CH1_OUT_RGB32 (2 << 5) | ||
109 | #define PRP_CNTL_CH1_OUT_YUV422 (3 << 5) | ||
110 | #define PRP_CNTL_CH2_OUT_YUV420 (0 << 7) | ||
111 | #define PRP_CNTL_CH2_OUT_YUV422 (1 << 7) | ||
112 | #define PRP_CNTL_CH2_OUT_YUV444 (2 << 7) | ||
113 | #define PRP_CNTL_CH1_LEN (1 << 9) | ||
114 | #define PRP_CNTL_CH2_LEN (1 << 10) | ||
115 | #define PRP_CNTL_SKIP_FRAME (1 << 11) | ||
116 | #define PRP_CNTL_SWRST (1 << 12) | ||
117 | #define PRP_CNTL_CLKEN (1 << 13) | ||
118 | #define PRP_CNTL_WEN (1 << 14) | ||
119 | #define PRP_CNTL_CH1BYP (1 << 15) | ||
120 | #define PRP_CNTL_IN_TSKIP(x) ((x) << 16) | ||
121 | #define PRP_CNTL_CH1_TSKIP(x) ((x) << 19) | ||
122 | #define PRP_CNTL_CH2_TSKIP(x) ((x) << 22) | ||
123 | #define PRP_CNTL_INPUT_FIFO_LEVEL(x) ((x) << 25) | ||
124 | #define PRP_CNTL_RZ_FIFO_LEVEL(x) ((x) << 27) | ||
125 | #define PRP_CNTL_CH2B1EN (1 << 29) | ||
126 | #define PRP_CNTL_CH2B2EN (1 << 30) | ||
127 | #define PRP_CNTL_CH2FEN (1 << 31) | ||
128 | |||
129 | #define PRP_SIZE_HEIGHT(x) (x) | ||
130 | #define PRP_SIZE_WIDTH(x) ((x) << 16) | ||
131 | |||
132 | /* IRQ Enable and status register */ | ||
133 | #define PRP_INTR_RDERR (1 << 0) | ||
134 | #define PRP_INTR_CH1WERR (1 << 1) | ||
135 | #define PRP_INTR_CH2WERR (1 << 2) | ||
136 | #define PRP_INTR_CH1FC (1 << 3) | ||
137 | #define PRP_INTR_CH2FC (1 << 5) | ||
138 | #define PRP_INTR_LBOVF (1 << 7) | ||
139 | #define PRP_INTR_CH2OVF (1 << 8) | ||
140 | |||
141 | #define PRP_INTR_ST_RDERR (1 << 0) | ||
142 | #define PRP_INTR_ST_CH1WERR (1 << 1) | ||
143 | #define PRP_INTR_ST_CH2WERR (1 << 2) | ||
144 | #define PRP_INTR_ST_CH2B2CI (1 << 3) | ||
145 | #define PRP_INTR_ST_CH2B1CI (1 << 4) | ||
146 | #define PRP_INTR_ST_CH1B2CI (1 << 5) | ||
147 | #define PRP_INTR_ST_CH1B1CI (1 << 6) | ||
148 | #define PRP_INTR_ST_LBOVF (1 << 7) | ||
149 | #define PRP_INTR_ST_CH2OVF (1 << 8) | ||
150 | |||
151 | struct emmaprp_fmt { | ||
152 | char *name; | ||
153 | u32 fourcc; | ||
154 | /* Types the format can be used for */ | ||
155 | u32 types; | ||
156 | }; | ||
157 | |||
158 | static struct emmaprp_fmt formats[] = { | ||
159 | { | ||
160 | .name = "YUV 4:2:0 Planar", | ||
161 | .fourcc = V4L2_PIX_FMT_YUV420, | ||
162 | .types = MEM2MEM_CAPTURE, | ||
163 | }, | ||
164 | { | ||
165 | .name = "4:2:2, packed, YUYV", | ||
166 | .fourcc = V4L2_PIX_FMT_YUYV, | ||
167 | .types = MEM2MEM_OUTPUT, | ||
168 | }, | ||
169 | }; | ||
170 | |||
171 | /* Per-queue, driver-specific private data */ | ||
172 | struct emmaprp_q_data { | ||
173 | unsigned int width; | ||
174 | unsigned int height; | ||
175 | unsigned int sizeimage; | ||
176 | struct emmaprp_fmt *fmt; | ||
177 | }; | ||
178 | |||
179 | enum { | ||
180 | V4L2_M2M_SRC = 0, | ||
181 | V4L2_M2M_DST = 1, | ||
182 | }; | ||
183 | |||
184 | #define NUM_FORMATS ARRAY_SIZE(formats) | ||
185 | |||
186 | static struct emmaprp_fmt *find_format(struct v4l2_format *f) | ||
187 | { | ||
188 | struct emmaprp_fmt *fmt; | ||
189 | unsigned int k; | ||
190 | |||
191 | for (k = 0; k < NUM_FORMATS; k++) { | ||
192 | fmt = &formats[k]; | ||
193 | if (fmt->fourcc == f->fmt.pix.pixelformat) | ||
194 | break; | ||
195 | } | ||
196 | |||
197 | if (k == NUM_FORMATS) | ||
198 | return NULL; | ||
199 | |||
200 | return &formats[k]; | ||
201 | } | ||
202 | |||
203 | struct emmaprp_dev { | ||
204 | struct v4l2_device v4l2_dev; | ||
205 | struct video_device *vfd; | ||
206 | |||
207 | struct mutex dev_mutex; | ||
208 | spinlock_t irqlock; | ||
209 | |||
210 | int irq_emma; | ||
211 | void __iomem *base_emma; | ||
212 | struct clk *clk_emma; | ||
213 | struct resource *res_emma; | ||
214 | |||
215 | struct v4l2_m2m_dev *m2m_dev; | ||
216 | struct vb2_alloc_ctx *alloc_ctx; | ||
217 | }; | ||
218 | |||
219 | struct emmaprp_ctx { | ||
220 | struct emmaprp_dev *dev; | ||
221 | /* Abort requested by m2m */ | ||
222 | int aborting; | ||
223 | struct emmaprp_q_data q_data[2]; | ||
224 | struct v4l2_m2m_ctx *m2m_ctx; | ||
225 | }; | ||
226 | |||
227 | static struct emmaprp_q_data *get_q_data(struct emmaprp_ctx *ctx, | ||
228 | enum v4l2_buf_type type) | ||
229 | { | ||
230 | switch (type) { | ||
231 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: | ||
232 | return &(ctx->q_data[V4L2_M2M_SRC]); | ||
233 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
234 | return &(ctx->q_data[V4L2_M2M_DST]); | ||
235 | default: | ||
236 | BUG(); | ||
237 | } | ||
238 | return NULL; | ||
239 | } | ||
240 | |||
241 | /* | ||
242 | * mem2mem callbacks | ||
243 | */ | ||
244 | static void emmaprp_job_abort(void *priv) | ||
245 | { | ||
246 | struct emmaprp_ctx *ctx = priv; | ||
247 | struct emmaprp_dev *pcdev = ctx->dev; | ||
248 | |||
249 | ctx->aborting = 1; | ||
250 | |||
251 | dprintk(pcdev, "Aborting task\n"); | ||
252 | |||
253 | v4l2_m2m_job_finish(pcdev->m2m_dev, ctx->m2m_ctx); | ||
254 | } | ||
255 | |||
256 | static void emmaprp_lock(void *priv) | ||
257 | { | ||
258 | struct emmaprp_ctx *ctx = priv; | ||
259 | struct emmaprp_dev *pcdev = ctx->dev; | ||
260 | mutex_lock(&pcdev->dev_mutex); | ||
261 | } | ||
262 | |||
263 | static void emmaprp_unlock(void *priv) | ||
264 | { | ||
265 | struct emmaprp_ctx *ctx = priv; | ||
266 | struct emmaprp_dev *pcdev = ctx->dev; | ||
267 | mutex_unlock(&pcdev->dev_mutex); | ||
268 | } | ||
269 | |||
270 | static inline void emmaprp_dump_regs(struct emmaprp_dev *pcdev) | ||
271 | { | ||
272 | dprintk(pcdev, | ||
273 | "eMMa-PrP Registers:\n" | ||
274 | " SOURCE_Y_PTR = 0x%08X\n" | ||
275 | " SRC_FRAME_SIZE = 0x%08X\n" | ||
276 | " DEST_Y_PTR = 0x%08X\n" | ||
277 | " DEST_CR_PTR = 0x%08X\n" | ||
278 | " DEST_CB_PTR = 0x%08X\n" | ||
279 | " CH2_OUT_IMAGE_SIZE = 0x%08X\n" | ||
280 | " CNTL = 0x%08X\n", | ||
281 | readl(pcdev->base_emma + PRP_SOURCE_Y_PTR), | ||
282 | readl(pcdev->base_emma + PRP_SRC_FRAME_SIZE), | ||
283 | readl(pcdev->base_emma + PRP_DEST_Y_PTR), | ||
284 | readl(pcdev->base_emma + PRP_DEST_CR_PTR), | ||
285 | readl(pcdev->base_emma + PRP_DEST_CB_PTR), | ||
286 | readl(pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE), | ||
287 | readl(pcdev->base_emma + PRP_CNTL)); | ||
288 | } | ||
289 | |||
290 | static void emmaprp_device_run(void *priv) | ||
291 | { | ||
292 | struct emmaprp_ctx *ctx = priv; | ||
293 | struct emmaprp_q_data *s_q_data, *d_q_data; | ||
294 | struct vb2_buffer *src_buf, *dst_buf; | ||
295 | struct emmaprp_dev *pcdev = ctx->dev; | ||
296 | unsigned int s_width, s_height; | ||
297 | unsigned int d_width, d_height; | ||
298 | unsigned int d_size; | ||
299 | dma_addr_t p_in, p_out; | ||
300 | u32 tmp; | ||
301 | |||
302 | src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); | ||
303 | dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); | ||
304 | |||
305 | s_q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); | ||
306 | s_width = s_q_data->width; | ||
307 | s_height = s_q_data->height; | ||
308 | |||
309 | d_q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); | ||
310 | d_width = d_q_data->width; | ||
311 | d_height = d_q_data->height; | ||
312 | d_size = d_width * d_height; | ||
313 | |||
314 | p_in = vb2_dma_contig_plane_dma_addr(src_buf, 0); | ||
315 | p_out = vb2_dma_contig_plane_dma_addr(dst_buf, 0); | ||
316 | if (!p_in || !p_out) { | ||
317 | v4l2_err(&pcdev->v4l2_dev, | ||
318 | "Acquiring kernel pointers to buffers failed\n"); | ||
319 | return; | ||
320 | } | ||
321 | |||
322 | /* Input frame parameters */ | ||
323 | writel(p_in, pcdev->base_emma + PRP_SOURCE_Y_PTR); | ||
324 | writel(PRP_SIZE_WIDTH(s_width) | PRP_SIZE_HEIGHT(s_height), | ||
325 | pcdev->base_emma + PRP_SRC_FRAME_SIZE); | ||
326 | |||
327 | /* Output frame parameters */ | ||
328 | writel(p_out, pcdev->base_emma + PRP_DEST_Y_PTR); | ||
329 | writel(p_out + d_size, pcdev->base_emma + PRP_DEST_CB_PTR); | ||
330 | writel(p_out + d_size + (d_size >> 2), | ||
331 | pcdev->base_emma + PRP_DEST_CR_PTR); | ||
332 | writel(PRP_SIZE_WIDTH(d_width) | PRP_SIZE_HEIGHT(d_height), | ||
333 | pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE); | ||
334 | |||
335 | /* IRQ configuration */ | ||
336 | tmp = readl(pcdev->base_emma + PRP_INTR_CNTL); | ||
337 | writel(tmp | PRP_INTR_RDERR | | ||
338 | PRP_INTR_CH2WERR | | ||
339 | PRP_INTR_CH2FC, | ||
340 | pcdev->base_emma + PRP_INTR_CNTL); | ||
341 | |||
342 | emmaprp_dump_regs(pcdev); | ||
343 | |||
344 | /* Enable transfer */ | ||
345 | tmp = readl(pcdev->base_emma + PRP_CNTL); | ||
346 | writel(tmp | PRP_CNTL_CH2_OUT_YUV420 | | ||
347 | PRP_CNTL_DATA_IN_YUV422 | | ||
348 | PRP_CNTL_CH2EN, | ||
349 | pcdev->base_emma + PRP_CNTL); | ||
350 | } | ||
351 | |||
352 | static irqreturn_t emmaprp_irq(int irq_emma, void *data) | ||
353 | { | ||
354 | struct emmaprp_dev *pcdev = data; | ||
355 | struct emmaprp_ctx *curr_ctx; | ||
356 | struct vb2_buffer *src_vb, *dst_vb; | ||
357 | unsigned long flags; | ||
358 | u32 irqst; | ||
359 | |||
360 | /* Check irq flags and clear irq */ | ||
361 | irqst = readl(pcdev->base_emma + PRP_INTRSTATUS); | ||
362 | writel(irqst, pcdev->base_emma + PRP_INTRSTATUS); | ||
363 | dprintk(pcdev, "irqst = 0x%08x\n", irqst); | ||
364 | |||
365 | curr_ctx = v4l2_m2m_get_curr_priv(pcdev->m2m_dev); | ||
366 | if (curr_ctx == NULL) { | ||
367 | pr_err("Instance released before the end of transaction\n"); | ||
368 | return IRQ_HANDLED; | ||
369 | } | ||
370 | |||
371 | if (!curr_ctx->aborting) { | ||
372 | if ((irqst & PRP_INTR_ST_RDERR) || | ||
373 | (irqst & PRP_INTR_ST_CH2WERR)) { | ||
374 | pr_err("PrP bus error ocurred, this transfer is probably corrupted\n"); | ||
375 | writel(PRP_CNTL_SWRST, pcdev->base_emma + PRP_CNTL); | ||
376 | } else if (irqst & PRP_INTR_ST_CH2B1CI) { /* buffer ready */ | ||
377 | src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx); | ||
378 | dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx); | ||
379 | |||
380 | spin_lock_irqsave(&pcdev->irqlock, flags); | ||
381 | v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE); | ||
382 | v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE); | ||
383 | spin_unlock_irqrestore(&pcdev->irqlock, flags); | ||
384 | } | ||
385 | } | ||
386 | |||
387 | v4l2_m2m_job_finish(pcdev->m2m_dev, curr_ctx->m2m_ctx); | ||
388 | return IRQ_HANDLED; | ||
389 | } | ||
390 | |||
391 | /* | ||
392 | * video ioctls | ||
393 | */ | ||
394 | static int vidioc_querycap(struct file *file, void *priv, | ||
395 | struct v4l2_capability *cap) | ||
396 | { | ||
397 | strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1); | ||
398 | strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1); | ||
399 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | ||
400 | | V4L2_CAP_STREAMING; | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | static int enum_fmt(struct v4l2_fmtdesc *f, u32 type) | ||
406 | { | ||
407 | int i, num; | ||
408 | struct emmaprp_fmt *fmt; | ||
409 | |||
410 | num = 0; | ||
411 | |||
412 | for (i = 0; i < NUM_FORMATS; ++i) { | ||
413 | if (formats[i].types & type) { | ||
414 | /* index-th format of type type found ? */ | ||
415 | if (num == f->index) | ||
416 | break; | ||
417 | /* Correct type but haven't reached our index yet, | ||
418 | * just increment per-type index */ | ||
419 | ++num; | ||
420 | } | ||
421 | } | ||
422 | |||
423 | if (i < NUM_FORMATS) { | ||
424 | /* Format found */ | ||
425 | fmt = &formats[i]; | ||
426 | strlcpy(f->description, fmt->name, sizeof(f->description) - 1); | ||
427 | f->pixelformat = fmt->fourcc; | ||
428 | return 0; | ||
429 | } | ||
430 | |||
431 | /* Format not found */ | ||
432 | return -EINVAL; | ||
433 | } | ||
434 | |||
435 | static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | ||
436 | struct v4l2_fmtdesc *f) | ||
437 | { | ||
438 | return enum_fmt(f, MEM2MEM_CAPTURE); | ||
439 | } | ||
440 | |||
441 | static int vidioc_enum_fmt_vid_out(struct file *file, void *priv, | ||
442 | struct v4l2_fmtdesc *f) | ||
443 | { | ||
444 | return enum_fmt(f, MEM2MEM_OUTPUT); | ||
445 | } | ||
446 | |||
447 | static int vidioc_g_fmt(struct emmaprp_ctx *ctx, struct v4l2_format *f) | ||
448 | { | ||
449 | struct vb2_queue *vq; | ||
450 | struct emmaprp_q_data *q_data; | ||
451 | |||
452 | vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); | ||
453 | if (!vq) | ||
454 | return -EINVAL; | ||
455 | |||
456 | q_data = get_q_data(ctx, f->type); | ||
457 | |||
458 | f->fmt.pix.width = q_data->width; | ||
459 | f->fmt.pix.height = q_data->height; | ||
460 | f->fmt.pix.field = V4L2_FIELD_NONE; | ||
461 | f->fmt.pix.pixelformat = q_data->fmt->fourcc; | ||
462 | if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) | ||
463 | f->fmt.pix.bytesperline = q_data->width * 3 / 2; | ||
464 | else /* YUYV */ | ||
465 | f->fmt.pix.bytesperline = q_data->width * 2; | ||
466 | f->fmt.pix.sizeimage = q_data->sizeimage; | ||
467 | |||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | static int vidioc_g_fmt_vid_out(struct file *file, void *priv, | ||
472 | struct v4l2_format *f) | ||
473 | { | ||
474 | return vidioc_g_fmt(priv, f); | ||
475 | } | ||
476 | |||
477 | static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | ||
478 | struct v4l2_format *f) | ||
479 | { | ||
480 | return vidioc_g_fmt(priv, f); | ||
481 | } | ||
482 | |||
483 | static int vidioc_try_fmt(struct v4l2_format *f) | ||
484 | { | ||
485 | enum v4l2_field field; | ||
486 | |||
487 | |||
488 | if (!find_format(f)) | ||
489 | return -EINVAL; | ||
490 | |||
491 | field = f->fmt.pix.field; | ||
492 | if (field == V4L2_FIELD_ANY) | ||
493 | field = V4L2_FIELD_NONE; | ||
494 | else if (V4L2_FIELD_NONE != field) | ||
495 | return -EINVAL; | ||
496 | |||
497 | /* V4L2 specification suggests the driver corrects the format struct | ||
498 | * if any of the dimensions is unsupported */ | ||
499 | f->fmt.pix.field = field; | ||
500 | |||
501 | if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) { | ||
502 | v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W, | ||
503 | W_ALIGN_YUV420, &f->fmt.pix.height, | ||
504 | MIN_H, MAX_H, H_ALIGN, S_ALIGN); | ||
505 | f->fmt.pix.bytesperline = f->fmt.pix.width * 3 / 2; | ||
506 | } else { | ||
507 | v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W, | ||
508 | W_ALIGN_OTHERS, &f->fmt.pix.height, | ||
509 | MIN_H, MAX_H, H_ALIGN, S_ALIGN); | ||
510 | f->fmt.pix.bytesperline = f->fmt.pix.width * 2; | ||
511 | } | ||
512 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
513 | |||
514 | return 0; | ||
515 | } | ||
516 | |||
517 | static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | ||
518 | struct v4l2_format *f) | ||
519 | { | ||
520 | struct emmaprp_fmt *fmt; | ||
521 | struct emmaprp_ctx *ctx = priv; | ||
522 | |||
523 | fmt = find_format(f); | ||
524 | if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) { | ||
525 | v4l2_err(&ctx->dev->v4l2_dev, | ||
526 | "Fourcc format (0x%08x) invalid.\n", | ||
527 | f->fmt.pix.pixelformat); | ||
528 | return -EINVAL; | ||
529 | } | ||
530 | |||
531 | return vidioc_try_fmt(f); | ||
532 | } | ||
533 | |||
534 | static int vidioc_try_fmt_vid_out(struct file *file, void *priv, | ||
535 | struct v4l2_format *f) | ||
536 | { | ||
537 | struct emmaprp_fmt *fmt; | ||
538 | struct emmaprp_ctx *ctx = priv; | ||
539 | |||
540 | fmt = find_format(f); | ||
541 | if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) { | ||
542 | v4l2_err(&ctx->dev->v4l2_dev, | ||
543 | "Fourcc format (0x%08x) invalid.\n", | ||
544 | f->fmt.pix.pixelformat); | ||
545 | return -EINVAL; | ||
546 | } | ||
547 | |||
548 | return vidioc_try_fmt(f); | ||
549 | } | ||
550 | |||
551 | static int vidioc_s_fmt(struct emmaprp_ctx *ctx, struct v4l2_format *f) | ||
552 | { | ||
553 | struct emmaprp_q_data *q_data; | ||
554 | struct vb2_queue *vq; | ||
555 | int ret; | ||
556 | |||
557 | vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); | ||
558 | if (!vq) | ||
559 | return -EINVAL; | ||
560 | |||
561 | q_data = get_q_data(ctx, f->type); | ||
562 | if (!q_data) | ||
563 | return -EINVAL; | ||
564 | |||
565 | if (vb2_is_busy(vq)) { | ||
566 | v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__); | ||
567 | return -EBUSY; | ||
568 | } | ||
569 | |||
570 | ret = vidioc_try_fmt(f); | ||
571 | if (ret) | ||
572 | return ret; | ||
573 | |||
574 | q_data->fmt = find_format(f); | ||
575 | q_data->width = f->fmt.pix.width; | ||
576 | q_data->height = f->fmt.pix.height; | ||
577 | if (q_data->fmt->fourcc == V4L2_PIX_FMT_YUV420) | ||
578 | q_data->sizeimage = q_data->width * q_data->height * 3 / 2; | ||
579 | else /* YUYV */ | ||
580 | q_data->sizeimage = q_data->width * q_data->height * 2; | ||
581 | |||
582 | dprintk(ctx->dev, | ||
583 | "Setting format for type %d, wxh: %dx%d, fmt: %d\n", | ||
584 | f->type, q_data->width, q_data->height, q_data->fmt->fourcc); | ||
585 | |||
586 | return 0; | ||
587 | } | ||
588 | |||
589 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | ||
590 | struct v4l2_format *f) | ||
591 | { | ||
592 | int ret; | ||
593 | |||
594 | ret = vidioc_try_fmt_vid_cap(file, priv, f); | ||
595 | if (ret) | ||
596 | return ret; | ||
597 | |||
598 | return vidioc_s_fmt(priv, f); | ||
599 | } | ||
600 | |||
601 | static int vidioc_s_fmt_vid_out(struct file *file, void *priv, | ||
602 | struct v4l2_format *f) | ||
603 | { | ||
604 | int ret; | ||
605 | |||
606 | ret = vidioc_try_fmt_vid_out(file, priv, f); | ||
607 | if (ret) | ||
608 | return ret; | ||
609 | |||
610 | return vidioc_s_fmt(priv, f); | ||
611 | } | ||
612 | |||
613 | static int vidioc_reqbufs(struct file *file, void *priv, | ||
614 | struct v4l2_requestbuffers *reqbufs) | ||
615 | { | ||
616 | struct emmaprp_ctx *ctx = priv; | ||
617 | |||
618 | return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); | ||
619 | } | ||
620 | |||
621 | static int vidioc_querybuf(struct file *file, void *priv, | ||
622 | struct v4l2_buffer *buf) | ||
623 | { | ||
624 | struct emmaprp_ctx *ctx = priv; | ||
625 | |||
626 | return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); | ||
627 | } | ||
628 | |||
629 | static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | ||
630 | { | ||
631 | struct emmaprp_ctx *ctx = priv; | ||
632 | |||
633 | return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); | ||
634 | } | ||
635 | |||
636 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | ||
637 | { | ||
638 | struct emmaprp_ctx *ctx = priv; | ||
639 | |||
640 | return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); | ||
641 | } | ||
642 | |||
643 | static int vidioc_streamon(struct file *file, void *priv, | ||
644 | enum v4l2_buf_type type) | ||
645 | { | ||
646 | struct emmaprp_ctx *ctx = priv; | ||
647 | |||
648 | return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); | ||
649 | } | ||
650 | |||
651 | static int vidioc_streamoff(struct file *file, void *priv, | ||
652 | enum v4l2_buf_type type) | ||
653 | { | ||
654 | struct emmaprp_ctx *ctx = priv; | ||
655 | |||
656 | return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); | ||
657 | } | ||
658 | |||
659 | static const struct v4l2_ioctl_ops emmaprp_ioctl_ops = { | ||
660 | .vidioc_querycap = vidioc_querycap, | ||
661 | |||
662 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
663 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
664 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
665 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
666 | |||
667 | .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out, | ||
668 | .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out, | ||
669 | .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out, | ||
670 | .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out, | ||
671 | |||
672 | .vidioc_reqbufs = vidioc_reqbufs, | ||
673 | .vidioc_querybuf = vidioc_querybuf, | ||
674 | |||
675 | .vidioc_qbuf = vidioc_qbuf, | ||
676 | .vidioc_dqbuf = vidioc_dqbuf, | ||
677 | |||
678 | .vidioc_streamon = vidioc_streamon, | ||
679 | .vidioc_streamoff = vidioc_streamoff, | ||
680 | }; | ||
681 | |||
682 | |||
683 | /* | ||
684 | * Queue operations | ||
685 | */ | ||
686 | static int emmaprp_queue_setup(struct vb2_queue *vq, | ||
687 | const struct v4l2_format *fmt, | ||
688 | unsigned int *nbuffers, unsigned int *nplanes, | ||
689 | unsigned int sizes[], void *alloc_ctxs[]) | ||
690 | { | ||
691 | struct emmaprp_ctx *ctx = vb2_get_drv_priv(vq); | ||
692 | struct emmaprp_q_data *q_data; | ||
693 | unsigned int size, count = *nbuffers; | ||
694 | |||
695 | q_data = get_q_data(ctx, vq->type); | ||
696 | |||
697 | if (q_data->fmt->fourcc == V4L2_PIX_FMT_YUV420) | ||
698 | size = q_data->width * q_data->height * 3 / 2; | ||
699 | else | ||
700 | size = q_data->width * q_data->height * 2; | ||
701 | |||
702 | while (size * count > MEM2MEM_VID_MEM_LIMIT) | ||
703 | (count)--; | ||
704 | |||
705 | *nplanes = 1; | ||
706 | *nbuffers = count; | ||
707 | sizes[0] = size; | ||
708 | |||
709 | alloc_ctxs[0] = ctx->dev->alloc_ctx; | ||
710 | |||
711 | dprintk(ctx->dev, "get %d buffer(s) of size %d each.\n", count, size); | ||
712 | |||
713 | return 0; | ||
714 | } | ||
715 | |||
716 | static int emmaprp_buf_prepare(struct vb2_buffer *vb) | ||
717 | { | ||
718 | struct emmaprp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); | ||
719 | struct emmaprp_q_data *q_data; | ||
720 | |||
721 | dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type); | ||
722 | |||
723 | q_data = get_q_data(ctx, vb->vb2_queue->type); | ||
724 | |||
725 | if (vb2_plane_size(vb, 0) < q_data->sizeimage) { | ||
726 | dprintk(ctx->dev, "%s data will not fit into plane" | ||
727 | "(%lu < %lu)\n", __func__, | ||
728 | vb2_plane_size(vb, 0), | ||
729 | (long)q_data->sizeimage); | ||
730 | return -EINVAL; | ||
731 | } | ||
732 | |||
733 | vb2_set_plane_payload(vb, 0, q_data->sizeimage); | ||
734 | |||
735 | return 0; | ||
736 | } | ||
737 | |||
738 | static void emmaprp_buf_queue(struct vb2_buffer *vb) | ||
739 | { | ||
740 | struct emmaprp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); | ||
741 | v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); | ||
742 | } | ||
743 | |||
744 | static struct vb2_ops emmaprp_qops = { | ||
745 | .queue_setup = emmaprp_queue_setup, | ||
746 | .buf_prepare = emmaprp_buf_prepare, | ||
747 | .buf_queue = emmaprp_buf_queue, | ||
748 | }; | ||
749 | |||
750 | static int queue_init(void *priv, struct vb2_queue *src_vq, | ||
751 | struct vb2_queue *dst_vq) | ||
752 | { | ||
753 | struct emmaprp_ctx *ctx = priv; | ||
754 | int ret; | ||
755 | |||
756 | memset(src_vq, 0, sizeof(*src_vq)); | ||
757 | src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; | ||
758 | src_vq->io_modes = VB2_MMAP; | ||
759 | src_vq->drv_priv = ctx; | ||
760 | src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); | ||
761 | src_vq->ops = &emmaprp_qops; | ||
762 | src_vq->mem_ops = &vb2_dma_contig_memops; | ||
763 | |||
764 | ret = vb2_queue_init(src_vq); | ||
765 | if (ret) | ||
766 | return ret; | ||
767 | |||
768 | memset(dst_vq, 0, sizeof(*dst_vq)); | ||
769 | dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
770 | dst_vq->io_modes = VB2_MMAP; | ||
771 | dst_vq->drv_priv = ctx; | ||
772 | dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); | ||
773 | dst_vq->ops = &emmaprp_qops; | ||
774 | dst_vq->mem_ops = &vb2_dma_contig_memops; | ||
775 | |||
776 | return vb2_queue_init(dst_vq); | ||
777 | } | ||
778 | |||
779 | /* | ||
780 | * File operations | ||
781 | */ | ||
782 | static int emmaprp_open(struct file *file) | ||
783 | { | ||
784 | struct emmaprp_dev *pcdev = video_drvdata(file); | ||
785 | struct emmaprp_ctx *ctx; | ||
786 | |||
787 | ctx = kzalloc(sizeof *ctx, GFP_KERNEL); | ||
788 | if (!ctx) | ||
789 | return -ENOMEM; | ||
790 | |||
791 | file->private_data = ctx; | ||
792 | ctx->dev = pcdev; | ||
793 | |||
794 | ctx->m2m_ctx = v4l2_m2m_ctx_init(pcdev->m2m_dev, ctx, &queue_init); | ||
795 | |||
796 | if (IS_ERR(ctx->m2m_ctx)) { | ||
797 | int ret = PTR_ERR(ctx->m2m_ctx); | ||
798 | |||
799 | kfree(ctx); | ||
800 | return ret; | ||
801 | } | ||
802 | |||
803 | clk_enable(pcdev->clk_emma); | ||
804 | ctx->q_data[V4L2_M2M_SRC].fmt = &formats[1]; | ||
805 | ctx->q_data[V4L2_M2M_DST].fmt = &formats[0]; | ||
806 | |||
807 | dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx); | ||
808 | |||
809 | return 0; | ||
810 | } | ||
811 | |||
812 | static int emmaprp_release(struct file *file) | ||
813 | { | ||
814 | struct emmaprp_dev *pcdev = video_drvdata(file); | ||
815 | struct emmaprp_ctx *ctx = file->private_data; | ||
816 | |||
817 | dprintk(pcdev, "Releasing instance %p\n", ctx); | ||
818 | |||
819 | clk_disable(pcdev->clk_emma); | ||
820 | v4l2_m2m_ctx_release(ctx->m2m_ctx); | ||
821 | kfree(ctx); | ||
822 | |||
823 | return 0; | ||
824 | } | ||
825 | |||
826 | static unsigned int emmaprp_poll(struct file *file, | ||
827 | struct poll_table_struct *wait) | ||
828 | { | ||
829 | struct emmaprp_ctx *ctx = file->private_data; | ||
830 | |||
831 | return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); | ||
832 | } | ||
833 | |||
834 | static int emmaprp_mmap(struct file *file, struct vm_area_struct *vma) | ||
835 | { | ||
836 | struct emmaprp_ctx *ctx = file->private_data; | ||
837 | |||
838 | return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); | ||
839 | } | ||
840 | |||
841 | static const struct v4l2_file_operations emmaprp_fops = { | ||
842 | .owner = THIS_MODULE, | ||
843 | .open = emmaprp_open, | ||
844 | .release = emmaprp_release, | ||
845 | .poll = emmaprp_poll, | ||
846 | .unlocked_ioctl = video_ioctl2, | ||
847 | .mmap = emmaprp_mmap, | ||
848 | }; | ||
849 | |||
850 | static struct video_device emmaprp_videodev = { | ||
851 | .name = MEM2MEM_NAME, | ||
852 | .fops = &emmaprp_fops, | ||
853 | .ioctl_ops = &emmaprp_ioctl_ops, | ||
854 | .minor = -1, | ||
855 | .release = video_device_release, | ||
856 | }; | ||
857 | |||
858 | static struct v4l2_m2m_ops m2m_ops = { | ||
859 | .device_run = emmaprp_device_run, | ||
860 | .job_abort = emmaprp_job_abort, | ||
861 | .lock = emmaprp_lock, | ||
862 | .unlock = emmaprp_unlock, | ||
863 | }; | ||
864 | |||
865 | static int emmaprp_probe(struct platform_device *pdev) | ||
866 | { | ||
867 | struct emmaprp_dev *pcdev; | ||
868 | struct video_device *vfd; | ||
869 | struct resource *res_emma; | ||
870 | int irq_emma; | ||
871 | int ret; | ||
872 | |||
873 | pcdev = kzalloc(sizeof *pcdev, GFP_KERNEL); | ||
874 | if (!pcdev) | ||
875 | return -ENOMEM; | ||
876 | |||
877 | spin_lock_init(&pcdev->irqlock); | ||
878 | |||
879 | pcdev->clk_emma = clk_get(&pdev->dev, NULL); | ||
880 | if (IS_ERR(pcdev->clk_emma)) { | ||
881 | ret = PTR_ERR(pcdev->clk_emma); | ||
882 | goto free_dev; | ||
883 | } | ||
884 | |||
885 | irq_emma = platform_get_irq(pdev, 0); | ||
886 | res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
887 | if (irq_emma < 0 || res_emma == NULL) { | ||
888 | dev_err(&pdev->dev, "Missing platform resources data\n"); | ||
889 | ret = -ENODEV; | ||
890 | goto free_clk; | ||
891 | } | ||
892 | |||
893 | ret = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev); | ||
894 | if (ret) | ||
895 | goto free_clk; | ||
896 | |||
897 | mutex_init(&pcdev->dev_mutex); | ||
898 | |||
899 | vfd = video_device_alloc(); | ||
900 | if (!vfd) { | ||
901 | v4l2_err(&pcdev->v4l2_dev, "Failed to allocate video device\n"); | ||
902 | ret = -ENOMEM; | ||
903 | goto unreg_dev; | ||
904 | } | ||
905 | |||
906 | *vfd = emmaprp_videodev; | ||
907 | vfd->lock = &pcdev->dev_mutex; | ||
908 | |||
909 | video_set_drvdata(vfd, pcdev); | ||
910 | snprintf(vfd->name, sizeof(vfd->name), "%s", emmaprp_videodev.name); | ||
911 | pcdev->vfd = vfd; | ||
912 | v4l2_info(&pcdev->v4l2_dev, EMMAPRP_MODULE_NAME | ||
913 | " Device registered as /dev/video%d\n", vfd->num); | ||
914 | |||
915 | platform_set_drvdata(pdev, pcdev); | ||
916 | |||
917 | if (devm_request_mem_region(&pdev->dev, res_emma->start, | ||
918 | resource_size(res_emma), MEM2MEM_NAME) == NULL) | ||
919 | goto rel_vdev; | ||
920 | |||
921 | pcdev->base_emma = devm_ioremap(&pdev->dev, res_emma->start, | ||
922 | resource_size(res_emma)); | ||
923 | if (!pcdev->base_emma) | ||
924 | goto rel_vdev; | ||
925 | |||
926 | pcdev->irq_emma = irq_emma; | ||
927 | pcdev->res_emma = res_emma; | ||
928 | |||
929 | if (devm_request_irq(&pdev->dev, pcdev->irq_emma, emmaprp_irq, | ||
930 | 0, MEM2MEM_NAME, pcdev) < 0) | ||
931 | goto rel_vdev; | ||
932 | |||
933 | pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); | ||
934 | if (IS_ERR(pcdev->alloc_ctx)) { | ||
935 | v4l2_err(&pcdev->v4l2_dev, "Failed to alloc vb2 context\n"); | ||
936 | ret = PTR_ERR(pcdev->alloc_ctx); | ||
937 | goto rel_vdev; | ||
938 | } | ||
939 | |||
940 | pcdev->m2m_dev = v4l2_m2m_init(&m2m_ops); | ||
941 | if (IS_ERR(pcdev->m2m_dev)) { | ||
942 | v4l2_err(&pcdev->v4l2_dev, "Failed to init mem2mem device\n"); | ||
943 | ret = PTR_ERR(pcdev->m2m_dev); | ||
944 | goto rel_ctx; | ||
945 | } | ||
946 | |||
947 | ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); | ||
948 | if (ret) { | ||
949 | v4l2_err(&pcdev->v4l2_dev, "Failed to register video device\n"); | ||
950 | goto rel_m2m; | ||
951 | } | ||
952 | |||
953 | return 0; | ||
954 | |||
955 | |||
956 | rel_m2m: | ||
957 | v4l2_m2m_release(pcdev->m2m_dev); | ||
958 | rel_ctx: | ||
959 | vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); | ||
960 | rel_vdev: | ||
961 | video_device_release(vfd); | ||
962 | unreg_dev: | ||
963 | v4l2_device_unregister(&pcdev->v4l2_dev); | ||
964 | free_clk: | ||
965 | clk_put(pcdev->clk_emma); | ||
966 | free_dev: | ||
967 | kfree(pcdev); | ||
968 | |||
969 | return ret; | ||
970 | } | ||
971 | |||
972 | static int emmaprp_remove(struct platform_device *pdev) | ||
973 | { | ||
974 | struct emmaprp_dev *pcdev = platform_get_drvdata(pdev); | ||
975 | |||
976 | v4l2_info(&pcdev->v4l2_dev, "Removing " EMMAPRP_MODULE_NAME); | ||
977 | |||
978 | video_unregister_device(pcdev->vfd); | ||
979 | v4l2_m2m_release(pcdev->m2m_dev); | ||
980 | vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); | ||
981 | v4l2_device_unregister(&pcdev->v4l2_dev); | ||
982 | clk_put(pcdev->clk_emma); | ||
983 | kfree(pcdev); | ||
984 | |||
985 | return 0; | ||
986 | } | ||
987 | |||
988 | static struct platform_driver emmaprp_pdrv = { | ||
989 | .probe = emmaprp_probe, | ||
990 | .remove = emmaprp_remove, | ||
991 | .driver = { | ||
992 | .name = MEM2MEM_NAME, | ||
993 | .owner = THIS_MODULE, | ||
994 | }, | ||
995 | }; | ||
996 | |||
997 | static void __exit emmaprp_exit(void) | ||
998 | { | ||
999 | platform_driver_unregister(&emmaprp_pdrv); | ||
1000 | } | ||
1001 | |||
1002 | static int __init emmaprp_init(void) | ||
1003 | { | ||
1004 | return platform_driver_register(&emmaprp_pdrv); | ||
1005 | } | ||
1006 | |||
1007 | module_init(emmaprp_init); | ||
1008 | module_exit(emmaprp_exit); | ||
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c index 74522773e934..93c35ef5f0ad 100644 --- a/drivers/media/video/mx3_camera.c +++ b/drivers/media/video/mx3_camera.c | |||
@@ -286,7 +286,7 @@ static void mx3_videobuf_queue(struct vb2_buffer *vb) | |||
286 | sg_dma_address(sg) = vb2_dma_contig_plane_dma_addr(vb, 0); | 286 | sg_dma_address(sg) = vb2_dma_contig_plane_dma_addr(vb, 0); |
287 | sg_dma_len(sg) = new_size; | 287 | sg_dma_len(sg) = new_size; |
288 | 288 | ||
289 | txd = ichan->dma_chan.device->device_prep_slave_sg( | 289 | txd = dmaengine_prep_slave_sg( |
290 | &ichan->dma_chan, sg, 1, DMA_DEV_TO_MEM, | 290 | &ichan->dma_chan, sg, 1, DMA_DEV_TO_MEM, |
291 | DMA_PREP_INTERRUPT); | 291 | DMA_PREP_INTERRUPT); |
292 | if (!txd) | 292 | if (!txd) |
diff --git a/drivers/media/video/noon010pc30.c b/drivers/media/video/noon010pc30.c index 50838bf84204..440c12962bae 100644 --- a/drivers/media/video/noon010pc30.c +++ b/drivers/media/video/noon010pc30.c | |||
@@ -725,8 +725,8 @@ static int noon010_probe(struct i2c_client *client, | |||
725 | 725 | ||
726 | mutex_init(&info->lock); | 726 | mutex_init(&info->lock); |
727 | sd = &info->sd; | 727 | sd = &info->sd; |
728 | strlcpy(sd->name, MODULE_NAME, sizeof(sd->name)); | ||
729 | v4l2_i2c_subdev_init(sd, client, &noon010_ops); | 728 | v4l2_i2c_subdev_init(sd, client, &noon010_ops); |
729 | strlcpy(sd->name, MODULE_NAME, sizeof(sd->name)); | ||
730 | 730 | ||
731 | sd->internal_ops = &noon010_subdev_internal_ops; | 731 | sd->internal_ops = &noon010_subdev_internal_ops; |
732 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | 732 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
@@ -844,18 +844,7 @@ static struct i2c_driver noon010_i2c_driver = { | |||
844 | .id_table = noon010_id, | 844 | .id_table = noon010_id, |
845 | }; | 845 | }; |
846 | 846 | ||
847 | static int __init noon010_init(void) | 847 | module_i2c_driver(noon010_i2c_driver); |
848 | { | ||
849 | return i2c_add_driver(&noon010_i2c_driver); | ||
850 | } | ||
851 | |||
852 | static void __exit noon010_exit(void) | ||
853 | { | ||
854 | i2c_del_driver(&noon010_i2c_driver); | ||
855 | } | ||
856 | |||
857 | module_init(noon010_init); | ||
858 | module_exit(noon010_exit); | ||
859 | 848 | ||
860 | MODULE_DESCRIPTION("Siliconfile NOON010PC30 camera driver"); | 849 | MODULE_DESCRIPTION("Siliconfile NOON010PC30 camera driver"); |
861 | MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); | 850 | MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); |
diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c index 1fb7d5bd5ec2..88cf9d952631 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/video/omap/omap_vout.c | |||
@@ -2268,13 +2268,12 @@ static struct platform_driver omap_vout_driver = { | |||
2268 | .driver = { | 2268 | .driver = { |
2269 | .name = VOUT_NAME, | 2269 | .name = VOUT_NAME, |
2270 | }, | 2270 | }, |
2271 | .probe = omap_vout_probe, | ||
2272 | .remove = omap_vout_remove, | 2271 | .remove = omap_vout_remove, |
2273 | }; | 2272 | }; |
2274 | 2273 | ||
2275 | static int __init omap_vout_init(void) | 2274 | static int __init omap_vout_init(void) |
2276 | { | 2275 | { |
2277 | if (platform_driver_register(&omap_vout_driver) != 0) { | 2276 | if (platform_driver_probe(&omap_vout_driver, omap_vout_probe) != 0) { |
2278 | printk(KERN_ERR VOUT_NAME ":Could not register Video driver\n"); | 2277 | printk(KERN_ERR VOUT_NAME ":Could not register Video driver\n"); |
2279 | return -EINVAL; | 2278 | return -EINVAL; |
2280 | } | 2279 | } |
diff --git a/drivers/media/video/omap3isp/ispccdc.c b/drivers/media/video/omap3isp/ispccdc.c index a74a79701d34..eaabc27f0fa2 100644 --- a/drivers/media/video/omap3isp/ispccdc.c +++ b/drivers/media/video/omap3isp/ispccdc.c | |||
@@ -1407,7 +1407,7 @@ static int __ccdc_handle_stopping(struct isp_ccdc_device *ccdc, u32 event) | |||
1407 | static void ccdc_hs_vs_isr(struct isp_ccdc_device *ccdc) | 1407 | static void ccdc_hs_vs_isr(struct isp_ccdc_device *ccdc) |
1408 | { | 1408 | { |
1409 | struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity); | 1409 | struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity); |
1410 | struct video_device *vdev = &ccdc->subdev.devnode; | 1410 | struct video_device *vdev = ccdc->subdev.devnode; |
1411 | struct v4l2_event event; | 1411 | struct v4l2_event event; |
1412 | 1412 | ||
1413 | memset(&event, 0, sizeof(event)); | 1413 | memset(&event, 0, sizeof(event)); |
diff --git a/drivers/media/video/ov2640.c b/drivers/media/video/ov2640.c index b5247cb64fde..3c2c5d3bcc6b 100644 --- a/drivers/media/video/ov2640.c +++ b/drivers/media/video/ov2640.c | |||
@@ -1103,21 +1103,7 @@ static struct i2c_driver ov2640_i2c_driver = { | |||
1103 | .id_table = ov2640_id, | 1103 | .id_table = ov2640_id, |
1104 | }; | 1104 | }; |
1105 | 1105 | ||
1106 | /* | 1106 | module_i2c_driver(ov2640_i2c_driver); |
1107 | * Module functions | ||
1108 | */ | ||
1109 | static int __init ov2640_module_init(void) | ||
1110 | { | ||
1111 | return i2c_add_driver(&ov2640_i2c_driver); | ||
1112 | } | ||
1113 | |||
1114 | static void __exit ov2640_module_exit(void) | ||
1115 | { | ||
1116 | i2c_del_driver(&ov2640_i2c_driver); | ||
1117 | } | ||
1118 | |||
1119 | module_init(ov2640_module_init); | ||
1120 | module_exit(ov2640_module_exit); | ||
1121 | 1107 | ||
1122 | MODULE_DESCRIPTION("SoC Camera driver for Omni Vision 2640 sensor"); | 1108 | MODULE_DESCRIPTION("SoC Camera driver for Omni Vision 2640 sensor"); |
1123 | MODULE_AUTHOR("Alberto Panizzo"); | 1109 | MODULE_AUTHOR("Alberto Panizzo"); |
diff --git a/drivers/media/video/ov5642.c b/drivers/media/video/ov5642.c index bb37ec80f274..80e07794ac8e 100644 --- a/drivers/media/video/ov5642.c +++ b/drivers/media/video/ov5642.c | |||
@@ -1068,18 +1068,7 @@ static struct i2c_driver ov5642_i2c_driver = { | |||
1068 | .id_table = ov5642_id, | 1068 | .id_table = ov5642_id, |
1069 | }; | 1069 | }; |
1070 | 1070 | ||
1071 | static int __init ov5642_mod_init(void) | 1071 | module_i2c_driver(ov5642_i2c_driver); |
1072 | { | ||
1073 | return i2c_add_driver(&ov5642_i2c_driver); | ||
1074 | } | ||
1075 | |||
1076 | static void __exit ov5642_mod_exit(void) | ||
1077 | { | ||
1078 | i2c_del_driver(&ov5642_i2c_driver); | ||
1079 | } | ||
1080 | |||
1081 | module_init(ov5642_mod_init); | ||
1082 | module_exit(ov5642_mod_exit); | ||
1083 | 1072 | ||
1084 | MODULE_DESCRIPTION("Omnivision OV5642 Camera driver"); | 1073 | MODULE_DESCRIPTION("Omnivision OV5642 Camera driver"); |
1085 | MODULE_AUTHOR("Bastian Hecht <hechtb@gmail.com>"); | 1074 | MODULE_AUTHOR("Bastian Hecht <hechtb@gmail.com>"); |
diff --git a/drivers/media/video/ov6650.c b/drivers/media/video/ov6650.c index 6806345ec2f0..3e028b1970dd 100644 --- a/drivers/media/video/ov6650.c +++ b/drivers/media/video/ov6650.c | |||
@@ -649,7 +649,7 @@ static int ov6650_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) | |||
649 | clkrc = CLKRC_24MHz; | 649 | clkrc = CLKRC_24MHz; |
650 | } else { | 650 | } else { |
651 | dev_err(&client->dev, | 651 | dev_err(&client->dev, |
652 | "unspported input clock, check platform data\n"); | 652 | "unsupported input clock, check platform data\n"); |
653 | return -EINVAL; | 653 | return -EINVAL; |
654 | } | 654 | } |
655 | mclk = sense->master_clock; | 655 | mclk = sense->master_clock; |
@@ -1046,18 +1046,7 @@ static struct i2c_driver ov6650_i2c_driver = { | |||
1046 | .id_table = ov6650_id, | 1046 | .id_table = ov6650_id, |
1047 | }; | 1047 | }; |
1048 | 1048 | ||
1049 | static int __init ov6650_module_init(void) | 1049 | module_i2c_driver(ov6650_i2c_driver); |
1050 | { | ||
1051 | return i2c_add_driver(&ov6650_i2c_driver); | ||
1052 | } | ||
1053 | |||
1054 | static void __exit ov6650_module_exit(void) | ||
1055 | { | ||
1056 | i2c_del_driver(&ov6650_i2c_driver); | ||
1057 | } | ||
1058 | |||
1059 | module_init(ov6650_module_init); | ||
1060 | module_exit(ov6650_module_exit); | ||
1061 | 1050 | ||
1062 | MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV6650"); | 1051 | MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV6650"); |
1063 | MODULE_AUTHOR("Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>"); | 1052 | MODULE_AUTHOR("Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>"); |
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c index 6a564964853a..e7c82b297514 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/video/ov7670.c | |||
@@ -1583,15 +1583,4 @@ static struct i2c_driver ov7670_driver = { | |||
1583 | .id_table = ov7670_id, | 1583 | .id_table = ov7670_id, |
1584 | }; | 1584 | }; |
1585 | 1585 | ||
1586 | static __init int init_ov7670(void) | 1586 | module_i2c_driver(ov7670_driver); |
1587 | { | ||
1588 | return i2c_add_driver(&ov7670_driver); | ||
1589 | } | ||
1590 | |||
1591 | static __exit void exit_ov7670(void) | ||
1592 | { | ||
1593 | i2c_del_driver(&ov7670_driver); | ||
1594 | } | ||
1595 | |||
1596 | module_init(init_ov7670); | ||
1597 | module_exit(exit_ov7670); | ||
diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c index 9f6ce3d8a29e..74e77d327ed8 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/video/ov772x.c | |||
@@ -1123,22 +1123,7 @@ static struct i2c_driver ov772x_i2c_driver = { | |||
1123 | .id_table = ov772x_id, | 1123 | .id_table = ov772x_id, |
1124 | }; | 1124 | }; |
1125 | 1125 | ||
1126 | /* | 1126 | module_i2c_driver(ov772x_i2c_driver); |
1127 | * module function | ||
1128 | */ | ||
1129 | |||
1130 | static int __init ov772x_module_init(void) | ||
1131 | { | ||
1132 | return i2c_add_driver(&ov772x_i2c_driver); | ||
1133 | } | ||
1134 | |||
1135 | static void __exit ov772x_module_exit(void) | ||
1136 | { | ||
1137 | i2c_del_driver(&ov772x_i2c_driver); | ||
1138 | } | ||
1139 | |||
1140 | module_init(ov772x_module_init); | ||
1141 | module_exit(ov772x_module_exit); | ||
1142 | 1127 | ||
1143 | MODULE_DESCRIPTION("SoC Camera driver for ov772x"); | 1128 | MODULE_DESCRIPTION("SoC Camera driver for ov772x"); |
1144 | MODULE_AUTHOR("Kuninori Morimoto"); | 1129 | MODULE_AUTHOR("Kuninori Morimoto"); |
diff --git a/drivers/media/video/ov9640.c b/drivers/media/video/ov9640.c index a4f99797eb56..23412debb36b 100644 --- a/drivers/media/video/ov9640.c +++ b/drivers/media/video/ov9640.c | |||
@@ -738,18 +738,7 @@ static struct i2c_driver ov9640_i2c_driver = { | |||
738 | .id_table = ov9640_id, | 738 | .id_table = ov9640_id, |
739 | }; | 739 | }; |
740 | 740 | ||
741 | static int __init ov9640_module_init(void) | 741 | module_i2c_driver(ov9640_i2c_driver); |
742 | { | ||
743 | return i2c_add_driver(&ov9640_i2c_driver); | ||
744 | } | ||
745 | |||
746 | static void __exit ov9640_module_exit(void) | ||
747 | { | ||
748 | i2c_del_driver(&ov9640_i2c_driver); | ||
749 | } | ||
750 | |||
751 | module_init(ov9640_module_init); | ||
752 | module_exit(ov9640_module_exit); | ||
753 | 742 | ||
754 | MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV96xx"); | 743 | MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV96xx"); |
755 | MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); | 744 | MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); |
diff --git a/drivers/media/video/ov9740.c b/drivers/media/video/ov9740.c index d9a9f7174f7a..3eb07c22516e 100644 --- a/drivers/media/video/ov9740.c +++ b/drivers/media/video/ov9740.c | |||
@@ -998,18 +998,7 @@ static struct i2c_driver ov9740_i2c_driver = { | |||
998 | .id_table = ov9740_id, | 998 | .id_table = ov9740_id, |
999 | }; | 999 | }; |
1000 | 1000 | ||
1001 | static int __init ov9740_module_init(void) | 1001 | module_i2c_driver(ov9740_i2c_driver); |
1002 | { | ||
1003 | return i2c_add_driver(&ov9740_i2c_driver); | ||
1004 | } | ||
1005 | |||
1006 | static void __exit ov9740_module_exit(void) | ||
1007 | { | ||
1008 | i2c_del_driver(&ov9740_i2c_driver); | ||
1009 | } | ||
1010 | |||
1011 | module_init(ov9740_module_init); | ||
1012 | module_exit(ov9740_module_exit); | ||
1013 | 1002 | ||
1014 | MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV9740"); | 1003 | MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV9740"); |
1015 | MODULE_AUTHOR("Andrew Chew <achew@nvidia.com>"); | 1004 | MODULE_AUTHOR("Andrew Chew <achew@nvidia.com>"); |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index c6da8f77e1a2..d8c898278e8c 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c | |||
@@ -320,7 +320,17 @@ static struct tda829x_config tda829x_no_probe = { | |||
320 | .probe_tuner = TDA829X_DONT_PROBE, | 320 | .probe_tuner = TDA829X_DONT_PROBE, |
321 | }; | 321 | }; |
322 | 322 | ||
323 | static struct tda18271_std_map hauppauge_tda18271_dvbt_std_map = { | ||
324 | .dvbt_6 = { .if_freq = 3300, .agc_mode = 3, .std = 4, | ||
325 | .if_lvl = 1, .rfagc_top = 0x37, }, | ||
326 | .dvbt_7 = { .if_freq = 3800, .agc_mode = 3, .std = 5, | ||
327 | .if_lvl = 1, .rfagc_top = 0x37, }, | ||
328 | .dvbt_8 = { .if_freq = 4300, .agc_mode = 3, .std = 6, | ||
329 | .if_lvl = 1, .rfagc_top = 0x37, }, | ||
330 | }; | ||
331 | |||
323 | static struct tda18271_config hauppauge_tda18271_dvb_config = { | 332 | static struct tda18271_config hauppauge_tda18271_dvb_config = { |
333 | .std_map = &hauppauge_tda18271_dvbt_std_map, | ||
324 | .gate = TDA18271_GATE_ANALOG, | 334 | .gate = TDA18271_GATE_ANALOG, |
325 | .output_opt = TDA18271_OUTPUT_LT_OFF, | 335 | .output_opt = TDA18271_OUTPUT_LT_OFF, |
326 | }; | 336 | }; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 6d666174dbb4..e1111d968a3d 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | |||
@@ -96,7 +96,6 @@ static struct v4l2_capability pvr_capability ={ | |||
96 | .capabilities = (V4L2_CAP_VIDEO_CAPTURE | | 96 | .capabilities = (V4L2_CAP_VIDEO_CAPTURE | |
97 | V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO | | 97 | V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO | |
98 | V4L2_CAP_READWRITE), | 98 | V4L2_CAP_READWRITE), |
99 | .reserved = {0,0,0,0} | ||
100 | }; | 99 | }; |
101 | 100 | ||
102 | static struct v4l2_fmtdesc pvr_fmtdesc [] = { | 101 | static struct v4l2_fmtdesc pvr_fmtdesc [] = { |
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c index f495eeb5403a..2834e3e65b39 100644 --- a/drivers/media/video/pwc/pwc-v4l.c +++ b/drivers/media/video/pwc/pwc-v4l.c | |||
@@ -1146,14 +1146,6 @@ leave: | |||
1146 | return ret; | 1146 | return ret; |
1147 | } | 1147 | } |
1148 | 1148 | ||
1149 | static int pwc_log_status(struct file *file, void *priv) | ||
1150 | { | ||
1151 | struct pwc_device *pdev = video_drvdata(file); | ||
1152 | |||
1153 | v4l2_ctrl_handler_log_status(&pdev->ctrl_handler, PWC_NAME); | ||
1154 | return 0; | ||
1155 | } | ||
1156 | |||
1157 | const struct v4l2_ioctl_ops pwc_ioctl_ops = { | 1149 | const struct v4l2_ioctl_ops pwc_ioctl_ops = { |
1158 | .vidioc_querycap = pwc_querycap, | 1150 | .vidioc_querycap = pwc_querycap, |
1159 | .vidioc_enum_input = pwc_enum_input, | 1151 | .vidioc_enum_input = pwc_enum_input, |
@@ -1169,7 +1161,7 @@ const struct v4l2_ioctl_ops pwc_ioctl_ops = { | |||
1169 | .vidioc_dqbuf = pwc_dqbuf, | 1161 | .vidioc_dqbuf = pwc_dqbuf, |
1170 | .vidioc_streamon = pwc_streamon, | 1162 | .vidioc_streamon = pwc_streamon, |
1171 | .vidioc_streamoff = pwc_streamoff, | 1163 | .vidioc_streamoff = pwc_streamoff, |
1172 | .vidioc_log_status = pwc_log_status, | 1164 | .vidioc_log_status = v4l2_ctrl_log_status, |
1173 | .vidioc_enum_framesizes = pwc_enum_framesizes, | 1165 | .vidioc_enum_framesizes = pwc_enum_framesizes, |
1174 | .vidioc_enum_frameintervals = pwc_enum_frameintervals, | 1166 | .vidioc_enum_frameintervals = pwc_enum_frameintervals, |
1175 | .vidioc_g_parm = pwc_g_parm, | 1167 | .vidioc_g_parm = pwc_g_parm, |
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 0bd7da26d018..5a413f4427e0 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c | |||
@@ -921,12 +921,12 @@ static void pxa_camera_activate(struct pxa_camera_dev *pcdev) | |||
921 | /* "Safe default" - 13MHz */ | 921 | /* "Safe default" - 13MHz */ |
922 | recalculate_fifo_timeout(pcdev, 13000000); | 922 | recalculate_fifo_timeout(pcdev, 13000000); |
923 | 923 | ||
924 | clk_enable(pcdev->clk); | 924 | clk_prepare_enable(pcdev->clk); |
925 | } | 925 | } |
926 | 926 | ||
927 | static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev) | 927 | static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev) |
928 | { | 928 | { |
929 | clk_disable(pcdev->clk); | 929 | clk_disable_unprepare(pcdev->clk); |
930 | } | 930 | } |
931 | 931 | ||
932 | static irqreturn_t pxa_camera_irq(int irq, void *data) | 932 | static irqreturn_t pxa_camera_irq(int irq, void *data) |
diff --git a/drivers/media/video/rj54n1cb0c.c b/drivers/media/video/rj54n1cb0c.c index 9937386a3bae..f6419b22c258 100644 --- a/drivers/media/video/rj54n1cb0c.c +++ b/drivers/media/video/rj54n1cb0c.c | |||
@@ -1407,18 +1407,7 @@ static struct i2c_driver rj54n1_i2c_driver = { | |||
1407 | .id_table = rj54n1_id, | 1407 | .id_table = rj54n1_id, |
1408 | }; | 1408 | }; |
1409 | 1409 | ||
1410 | static int __init rj54n1_mod_init(void) | 1410 | module_i2c_driver(rj54n1_i2c_driver); |
1411 | { | ||
1412 | return i2c_add_driver(&rj54n1_i2c_driver); | ||
1413 | } | ||
1414 | |||
1415 | static void __exit rj54n1_mod_exit(void) | ||
1416 | { | ||
1417 | i2c_del_driver(&rj54n1_i2c_driver); | ||
1418 | } | ||
1419 | |||
1420 | module_init(rj54n1_mod_init); | ||
1421 | module_exit(rj54n1_mod_exit); | ||
1422 | 1411 | ||
1423 | MODULE_DESCRIPTION("Sharp RJ54N1CB0C Camera driver"); | 1412 | MODULE_DESCRIPTION("Sharp RJ54N1CB0C Camera driver"); |
1424 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); | 1413 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); |
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index c1bef6187661..4894cbb1c547 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c | |||
@@ -134,7 +134,7 @@ | |||
134 | 134 | ||
135 | /* usb config commands */ | 135 | /* usb config commands */ |
136 | #define IN_DATA_TOKEN cpu_to_le32(0x2255c0de) | 136 | #define IN_DATA_TOKEN cpu_to_le32(0x2255c0de) |
137 | #define CMD_2255 cpu_to_le32(0xc2255000) | 137 | #define CMD_2255 0xc2255000 |
138 | #define CMD_SET_MODE cpu_to_le32((CMD_2255 | 0x10)) | 138 | #define CMD_SET_MODE cpu_to_le32((CMD_2255 | 0x10)) |
139 | #define CMD_START cpu_to_le32((CMD_2255 | 0x20)) | 139 | #define CMD_START cpu_to_le32((CMD_2255 | 0x20)) |
140 | #define CMD_STOP cpu_to_le32((CMD_2255 | 0x30)) | 140 | #define CMD_STOP cpu_to_le32((CMD_2255 | 0x30)) |
@@ -852,15 +852,13 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
852 | static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | 852 | static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, |
853 | struct v4l2_fmtdesc *f) | 853 | struct v4l2_fmtdesc *f) |
854 | { | 854 | { |
855 | int index = 0; | 855 | int index = f->index; |
856 | if (f) | ||
857 | index = f->index; | ||
858 | 856 | ||
859 | if (index >= ARRAY_SIZE(formats)) | 857 | if (index >= ARRAY_SIZE(formats)) |
860 | return -EINVAL; | 858 | return -EINVAL; |
861 | if (!jpeg_enable && ((formats[index].fourcc == V4L2_PIX_FMT_JPEG) || | 859 | if (!jpeg_enable && ((formats[index].fourcc == V4L2_PIX_FMT_JPEG) || |
862 | (formats[index].fourcc == V4L2_PIX_FMT_MJPEG))) | 860 | (formats[index].fourcc == V4L2_PIX_FMT_MJPEG))) |
863 | return -EINVAL; | 861 | return -EINVAL; |
864 | dprintk(4, "name %s\n", formats[index].name); | 862 | dprintk(4, "name %s\n", formats[index].name); |
865 | strlcpy(f->description, formats[index].name, sizeof(f->description)); | 863 | strlcpy(f->description, formats[index].name, sizeof(f->description)); |
866 | f->pixelformat = formats[index].fourcc; | 864 | f->pixelformat = formats[index].fourcc; |
@@ -2027,7 +2025,7 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) | |||
2027 | pdata[1]); | 2025 | pdata[1]); |
2028 | offset = jj + PREFIX_SIZE; | 2026 | offset = jj + PREFIX_SIZE; |
2029 | bframe = 1; | 2027 | bframe = 1; |
2030 | cc = pdword[1]; | 2028 | cc = le32_to_cpu(pdword[1]); |
2031 | if (cc >= MAX_CHANNELS) { | 2029 | if (cc >= MAX_CHANNELS) { |
2032 | printk(KERN_ERR | 2030 | printk(KERN_ERR |
2033 | "bad channel\n"); | 2031 | "bad channel\n"); |
@@ -2036,22 +2034,22 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) | |||
2036 | /* reverse it */ | 2034 | /* reverse it */ |
2037 | dev->cc = G_chnmap[cc]; | 2035 | dev->cc = G_chnmap[cc]; |
2038 | channel = &dev->channel[dev->cc]; | 2036 | channel = &dev->channel[dev->cc]; |
2039 | payload = pdword[3]; | 2037 | payload = le32_to_cpu(pdword[3]); |
2040 | if (payload > channel->req_image_size) { | 2038 | if (payload > channel->req_image_size) { |
2041 | channel->bad_payload++; | 2039 | channel->bad_payload++; |
2042 | /* discard the bad frame */ | 2040 | /* discard the bad frame */ |
2043 | return -EINVAL; | 2041 | return -EINVAL; |
2044 | } | 2042 | } |
2045 | channel->pkt_size = payload; | 2043 | channel->pkt_size = payload; |
2046 | channel->jpg_size = pdword[4]; | 2044 | channel->jpg_size = le32_to_cpu(pdword[4]); |
2047 | break; | 2045 | break; |
2048 | case S2255_MARKER_RESPONSE: | 2046 | case S2255_MARKER_RESPONSE: |
2049 | 2047 | ||
2050 | pdata += DEF_USB_BLOCK; | 2048 | pdata += DEF_USB_BLOCK; |
2051 | jj += DEF_USB_BLOCK; | 2049 | jj += DEF_USB_BLOCK; |
2052 | if (pdword[1] >= MAX_CHANNELS) | 2050 | if (le32_to_cpu(pdword[1]) >= MAX_CHANNELS) |
2053 | break; | 2051 | break; |
2054 | cc = G_chnmap[pdword[1]]; | 2052 | cc = G_chnmap[le32_to_cpu(pdword[1])]; |
2055 | if (cc >= MAX_CHANNELS) | 2053 | if (cc >= MAX_CHANNELS) |
2056 | break; | 2054 | break; |
2057 | channel = &dev->channel[cc]; | 2055 | channel = &dev->channel[cc]; |
@@ -2074,11 +2072,11 @@ static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info) | |||
2074 | wake_up(&dev->fw_data->wait_fw); | 2072 | wake_up(&dev->fw_data->wait_fw); |
2075 | break; | 2073 | break; |
2076 | case S2255_RESPONSE_STATUS: | 2074 | case S2255_RESPONSE_STATUS: |
2077 | channel->vidstatus = pdword[3]; | 2075 | channel->vidstatus = le32_to_cpu(pdword[3]); |
2078 | channel->vidstatus_ready = 1; | 2076 | channel->vidstatus_ready = 1; |
2079 | wake_up(&channel->wait_vidstatus); | 2077 | wake_up(&channel->wait_vidstatus); |
2080 | dprintk(5, "got vidstatus %x chan %d\n", | 2078 | dprintk(5, "got vidstatus %x chan %d\n", |
2081 | pdword[3], cc); | 2079 | le32_to_cpu(pdword[3]), cc); |
2082 | break; | 2080 | break; |
2083 | default: | 2081 | default: |
2084 | printk(KERN_INFO "s2255 unknown resp\n"); | 2082 | printk(KERN_INFO "s2255 unknown resp\n"); |
@@ -2605,10 +2603,11 @@ static int s2255_probe(struct usb_interface *interface, | |||
2605 | __le32 *pRel; | 2603 | __le32 *pRel; |
2606 | pRel = (__le32 *) &dev->fw_data->fw->data[fw_size - 4]; | 2604 | pRel = (__le32 *) &dev->fw_data->fw->data[fw_size - 4]; |
2607 | printk(KERN_INFO "s2255 dsp fw version %x\n", *pRel); | 2605 | printk(KERN_INFO "s2255 dsp fw version %x\n", *pRel); |
2608 | dev->dsp_fw_ver = *pRel; | 2606 | dev->dsp_fw_ver = le32_to_cpu(*pRel); |
2609 | if (*pRel < S2255_CUR_DSP_FWVER) | 2607 | if (dev->dsp_fw_ver < S2255_CUR_DSP_FWVER) |
2610 | printk(KERN_INFO "s2255: f2255usb.bin out of date.\n"); | 2608 | printk(KERN_INFO "s2255: f2255usb.bin out of date.\n"); |
2611 | if (dev->pid == 0x2257 && *pRel < S2255_MIN_DSP_COLORFILTER) | 2609 | if (dev->pid == 0x2257 && |
2610 | dev->dsp_fw_ver < S2255_MIN_DSP_COLORFILTER) | ||
2612 | printk(KERN_WARNING "s2255: 2257 requires firmware %d" | 2611 | printk(KERN_WARNING "s2255: 2257 requires firmware %d" |
2613 | " or above.\n", S2255_MIN_DSP_COLORFILTER); | 2612 | " or above.\n", S2255_MIN_DSP_COLORFILTER); |
2614 | } | 2613 | } |
diff --git a/drivers/media/video/s5k6aa.c b/drivers/media/video/s5k6aa.c index 0df7f2a41814..6625e46a4638 100644 --- a/drivers/media/video/s5k6aa.c +++ b/drivers/media/video/s5k6aa.c | |||
@@ -1582,8 +1582,8 @@ static int s5k6aa_probe(struct i2c_client *client, | |||
1582 | s5k6aa->inv_vflip = pdata->vert_flip; | 1582 | s5k6aa->inv_vflip = pdata->vert_flip; |
1583 | 1583 | ||
1584 | sd = &s5k6aa->sd; | 1584 | sd = &s5k6aa->sd; |
1585 | strlcpy(sd->name, DRIVER_NAME, sizeof(sd->name)); | ||
1586 | v4l2_i2c_subdev_init(sd, client, &s5k6aa_subdev_ops); | 1585 | v4l2_i2c_subdev_init(sd, client, &s5k6aa_subdev_ops); |
1586 | strlcpy(sd->name, DRIVER_NAME, sizeof(sd->name)); | ||
1587 | 1587 | ||
1588 | sd->internal_ops = &s5k6aa_subdev_internal_ops; | 1588 | sd->internal_ops = &s5k6aa_subdev_internal_ops; |
1589 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | 1589 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
@@ -1663,18 +1663,7 @@ static struct i2c_driver s5k6aa_i2c_driver = { | |||
1663 | .id_table = s5k6aa_id, | 1663 | .id_table = s5k6aa_id, |
1664 | }; | 1664 | }; |
1665 | 1665 | ||
1666 | static int __init s5k6aa_init(void) | 1666 | module_i2c_driver(s5k6aa_i2c_driver); |
1667 | { | ||
1668 | return i2c_add_driver(&s5k6aa_i2c_driver); | ||
1669 | } | ||
1670 | |||
1671 | static void __exit s5k6aa_exit(void) | ||
1672 | { | ||
1673 | i2c_del_driver(&s5k6aa_i2c_driver); | ||
1674 | } | ||
1675 | |||
1676 | module_init(s5k6aa_init); | ||
1677 | module_exit(s5k6aa_exit); | ||
1678 | 1667 | ||
1679 | MODULE_DESCRIPTION("Samsung S5K6AA(FX) SXGA camera driver"); | 1668 | MODULE_DESCRIPTION("Samsung S5K6AA(FX) SXGA camera driver"); |
1680 | MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); | 1669 | MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); |
diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c index a9e9653beeb4..b06efd208328 100644 --- a/drivers/media/video/s5p-fimc/fimc-capture.c +++ b/drivers/media/video/s5p-fimc/fimc-capture.c | |||
@@ -1019,52 +1019,117 @@ static int fimc_cap_dqbuf(struct file *file, void *priv, | |||
1019 | return vb2_dqbuf(&fimc->vid_cap.vbq, buf, file->f_flags & O_NONBLOCK); | 1019 | return vb2_dqbuf(&fimc->vid_cap.vbq, buf, file->f_flags & O_NONBLOCK); |
1020 | } | 1020 | } |
1021 | 1021 | ||
1022 | static int fimc_cap_cropcap(struct file *file, void *fh, | 1022 | static int fimc_cap_create_bufs(struct file *file, void *priv, |
1023 | struct v4l2_cropcap *cr) | 1023 | struct v4l2_create_buffers *create) |
1024 | { | 1024 | { |
1025 | struct fimc_dev *fimc = video_drvdata(file); | 1025 | struct fimc_dev *fimc = video_drvdata(file); |
1026 | struct fimc_frame *f = &fimc->vid_cap.ctx->s_frame; | ||
1027 | 1026 | ||
1028 | if (cr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) | 1027 | return vb2_create_bufs(&fimc->vid_cap.vbq, create); |
1029 | return -EINVAL; | 1028 | } |
1030 | 1029 | ||
1031 | cr->bounds.left = 0; | 1030 | static int fimc_cap_prepare_buf(struct file *file, void *priv, |
1032 | cr->bounds.top = 0; | 1031 | struct v4l2_buffer *b) |
1033 | cr->bounds.width = f->o_width; | 1032 | { |
1034 | cr->bounds.height = f->o_height; | 1033 | struct fimc_dev *fimc = video_drvdata(file); |
1035 | cr->defrect = cr->bounds; | ||
1036 | 1034 | ||
1037 | return 0; | 1035 | return vb2_prepare_buf(&fimc->vid_cap.vbq, b); |
1038 | } | 1036 | } |
1039 | 1037 | ||
1040 | static int fimc_cap_g_crop(struct file *file, void *fh, struct v4l2_crop *cr) | 1038 | static int fimc_cap_g_selection(struct file *file, void *fh, |
1039 | struct v4l2_selection *s) | ||
1041 | { | 1040 | { |
1042 | struct fimc_dev *fimc = video_drvdata(file); | 1041 | struct fimc_dev *fimc = video_drvdata(file); |
1043 | struct fimc_frame *f = &fimc->vid_cap.ctx->s_frame; | 1042 | struct fimc_ctx *ctx = fimc->vid_cap.ctx; |
1043 | struct fimc_frame *f = &ctx->s_frame; | ||
1044 | 1044 | ||
1045 | cr->c.left = f->offs_h; | 1045 | if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) |
1046 | cr->c.top = f->offs_v; | 1046 | return -EINVAL; |
1047 | cr->c.width = f->width; | ||
1048 | cr->c.height = f->height; | ||
1049 | 1047 | ||
1050 | return 0; | 1048 | switch (s->target) { |
1049 | case V4L2_SEL_TGT_COMPOSE_DEFAULT: | ||
1050 | case V4L2_SEL_TGT_COMPOSE_BOUNDS: | ||
1051 | f = &ctx->d_frame; | ||
1052 | case V4L2_SEL_TGT_CROP_BOUNDS: | ||
1053 | case V4L2_SEL_TGT_CROP_DEFAULT: | ||
1054 | s->r.left = 0; | ||
1055 | s->r.top = 0; | ||
1056 | s->r.width = f->o_width; | ||
1057 | s->r.height = f->o_height; | ||
1058 | return 0; | ||
1059 | |||
1060 | case V4L2_SEL_TGT_COMPOSE_ACTIVE: | ||
1061 | f = &ctx->d_frame; | ||
1062 | case V4L2_SEL_TGT_CROP_ACTIVE: | ||
1063 | s->r.left = f->offs_h; | ||
1064 | s->r.top = f->offs_v; | ||
1065 | s->r.width = f->width; | ||
1066 | s->r.height = f->height; | ||
1067 | return 0; | ||
1068 | } | ||
1069 | |||
1070 | return -EINVAL; | ||
1051 | } | 1071 | } |
1052 | 1072 | ||
1053 | static int fimc_cap_s_crop(struct file *file, void *fh, struct v4l2_crop *cr) | 1073 | /* Return 1 if rectangle a is enclosed in rectangle b, or 0 otherwise. */ |
1074 | int enclosed_rectangle(struct v4l2_rect *a, struct v4l2_rect *b) | ||
1075 | { | ||
1076 | if (a->left < b->left || a->top < b->top) | ||
1077 | return 0; | ||
1078 | if (a->left + a->width > b->left + b->width) | ||
1079 | return 0; | ||
1080 | if (a->top + a->height > b->top + b->height) | ||
1081 | return 0; | ||
1082 | |||
1083 | return 1; | ||
1084 | } | ||
1085 | |||
1086 | static int fimc_cap_s_selection(struct file *file, void *fh, | ||
1087 | struct v4l2_selection *s) | ||
1054 | { | 1088 | { |
1055 | struct fimc_dev *fimc = video_drvdata(file); | 1089 | struct fimc_dev *fimc = video_drvdata(file); |
1056 | struct fimc_ctx *ctx = fimc->vid_cap.ctx; | 1090 | struct fimc_ctx *ctx = fimc->vid_cap.ctx; |
1057 | struct fimc_frame *ff; | 1091 | struct v4l2_rect rect = s->r; |
1092 | struct fimc_frame *f; | ||
1058 | unsigned long flags; | 1093 | unsigned long flags; |
1094 | unsigned int pad; | ||
1059 | 1095 | ||
1060 | fimc_capture_try_crop(ctx, &cr->c, FIMC_SD_PAD_SINK); | 1096 | if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) |
1061 | ff = &ctx->s_frame; | 1097 | return -EINVAL; |
1062 | 1098 | ||
1099 | switch (s->target) { | ||
1100 | case V4L2_SEL_TGT_COMPOSE_DEFAULT: | ||
1101 | case V4L2_SEL_TGT_COMPOSE_BOUNDS: | ||
1102 | case V4L2_SEL_TGT_COMPOSE_ACTIVE: | ||
1103 | f = &ctx->d_frame; | ||
1104 | pad = FIMC_SD_PAD_SOURCE; | ||
1105 | break; | ||
1106 | case V4L2_SEL_TGT_CROP_BOUNDS: | ||
1107 | case V4L2_SEL_TGT_CROP_DEFAULT: | ||
1108 | case V4L2_SEL_TGT_CROP_ACTIVE: | ||
1109 | f = &ctx->s_frame; | ||
1110 | pad = FIMC_SD_PAD_SINK; | ||
1111 | break; | ||
1112 | default: | ||
1113 | return -EINVAL; | ||
1114 | } | ||
1115 | |||
1116 | fimc_capture_try_crop(ctx, &rect, pad); | ||
1117 | |||
1118 | if (s->flags & V4L2_SEL_FLAG_LE && | ||
1119 | !enclosed_rectangle(&rect, &s->r)) | ||
1120 | return -ERANGE; | ||
1121 | |||
1122 | if (s->flags & V4L2_SEL_FLAG_GE && | ||
1123 | !enclosed_rectangle(&s->r, &rect)) | ||
1124 | return -ERANGE; | ||
1125 | |||
1126 | s->r = rect; | ||
1063 | spin_lock_irqsave(&fimc->slock, flags); | 1127 | spin_lock_irqsave(&fimc->slock, flags); |
1064 | set_frame_crop(ff, cr->c.left, cr->c.top, cr->c.width, cr->c.height); | 1128 | set_frame_crop(f, s->r.left, s->r.top, s->r.width, |
1065 | set_bit(ST_CAPT_APPLY_CFG, &fimc->state); | 1129 | s->r.height); |
1066 | spin_unlock_irqrestore(&fimc->slock, flags); | 1130 | spin_unlock_irqrestore(&fimc->slock, flags); |
1067 | 1131 | ||
1132 | set_bit(ST_CAPT_APPLY_CFG, &fimc->state); | ||
1068 | return 0; | 1133 | return 0; |
1069 | } | 1134 | } |
1070 | 1135 | ||
@@ -1082,12 +1147,14 @@ static const struct v4l2_ioctl_ops fimc_capture_ioctl_ops = { | |||
1082 | .vidioc_qbuf = fimc_cap_qbuf, | 1147 | .vidioc_qbuf = fimc_cap_qbuf, |
1083 | .vidioc_dqbuf = fimc_cap_dqbuf, | 1148 | .vidioc_dqbuf = fimc_cap_dqbuf, |
1084 | 1149 | ||
1150 | .vidioc_prepare_buf = fimc_cap_prepare_buf, | ||
1151 | .vidioc_create_bufs = fimc_cap_create_bufs, | ||
1152 | |||
1085 | .vidioc_streamon = fimc_cap_streamon, | 1153 | .vidioc_streamon = fimc_cap_streamon, |
1086 | .vidioc_streamoff = fimc_cap_streamoff, | 1154 | .vidioc_streamoff = fimc_cap_streamoff, |
1087 | 1155 | ||
1088 | .vidioc_g_crop = fimc_cap_g_crop, | 1156 | .vidioc_g_selection = fimc_cap_g_selection, |
1089 | .vidioc_s_crop = fimc_cap_s_crop, | 1157 | .vidioc_s_selection = fimc_cap_s_selection, |
1090 | .vidioc_cropcap = fimc_cap_cropcap, | ||
1091 | 1158 | ||
1092 | .vidioc_enum_input = fimc_cap_enum_input, | 1159 | .vidioc_enum_input = fimc_cap_enum_input, |
1093 | .vidioc_s_input = fimc_cap_s_input, | 1160 | .vidioc_s_input = fimc_cap_s_input, |
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c index 81bcbb9492ea..e184e650022a 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.c +++ b/drivers/media/video/s5p-fimc/fimc-core.c | |||
@@ -1602,24 +1602,35 @@ static void fimc_clk_put(struct fimc_dev *fimc) | |||
1602 | { | 1602 | { |
1603 | int i; | 1603 | int i; |
1604 | for (i = 0; i < fimc->num_clocks; i++) { | 1604 | for (i = 0; i < fimc->num_clocks; i++) { |
1605 | if (fimc->clock[i]) | 1605 | if (IS_ERR_OR_NULL(fimc->clock[i])) |
1606 | clk_put(fimc->clock[i]); | 1606 | continue; |
1607 | clk_unprepare(fimc->clock[i]); | ||
1608 | clk_put(fimc->clock[i]); | ||
1609 | fimc->clock[i] = NULL; | ||
1607 | } | 1610 | } |
1608 | } | 1611 | } |
1609 | 1612 | ||
1610 | static int fimc_clk_get(struct fimc_dev *fimc) | 1613 | static int fimc_clk_get(struct fimc_dev *fimc) |
1611 | { | 1614 | { |
1612 | int i; | 1615 | int i, ret; |
1616 | |||
1613 | for (i = 0; i < fimc->num_clocks; i++) { | 1617 | for (i = 0; i < fimc->num_clocks; i++) { |
1614 | fimc->clock[i] = clk_get(&fimc->pdev->dev, fimc_clocks[i]); | 1618 | fimc->clock[i] = clk_get(&fimc->pdev->dev, fimc_clocks[i]); |
1615 | if (!IS_ERR_OR_NULL(fimc->clock[i])) | 1619 | if (IS_ERR(fimc->clock[i])) |
1616 | continue; | 1620 | goto err; |
1617 | dev_err(&fimc->pdev->dev, "failed to get fimc clock: %s\n", | 1621 | ret = clk_prepare(fimc->clock[i]); |
1618 | fimc_clocks[i]); | 1622 | if (ret < 0) { |
1619 | return -ENXIO; | 1623 | clk_put(fimc->clock[i]); |
1624 | fimc->clock[i] = NULL; | ||
1625 | goto err; | ||
1626 | } | ||
1620 | } | 1627 | } |
1621 | |||
1622 | return 0; | 1628 | return 0; |
1629 | err: | ||
1630 | fimc_clk_put(fimc); | ||
1631 | dev_err(&fimc->pdev->dev, "failed to get clock: %s\n", | ||
1632 | fimc_clocks[i]); | ||
1633 | return -ENXIO; | ||
1623 | } | 1634 | } |
1624 | 1635 | ||
1625 | static int fimc_m2m_suspend(struct fimc_dev *fimc) | 1636 | static int fimc_m2m_suspend(struct fimc_dev *fimc) |
@@ -1667,8 +1678,6 @@ static int fimc_probe(struct platform_device *pdev) | |||
1667 | struct s5p_platform_fimc *pdata; | 1678 | struct s5p_platform_fimc *pdata; |
1668 | int ret = 0; | 1679 | int ret = 0; |
1669 | 1680 | ||
1670 | dev_dbg(&pdev->dev, "%s():\n", __func__); | ||
1671 | |||
1672 | drv_data = (struct samsung_fimc_driverdata *) | 1681 | drv_data = (struct samsung_fimc_driverdata *) |
1673 | platform_get_device_id(pdev)->driver_data; | 1682 | platform_get_device_id(pdev)->driver_data; |
1674 | 1683 | ||
@@ -1678,7 +1687,7 @@ static int fimc_probe(struct platform_device *pdev) | |||
1678 | return -EINVAL; | 1687 | return -EINVAL; |
1679 | } | 1688 | } |
1680 | 1689 | ||
1681 | fimc = kzalloc(sizeof(struct fimc_dev), GFP_KERNEL); | 1690 | fimc = devm_kzalloc(&pdev->dev, sizeof(*fimc), GFP_KERNEL); |
1682 | if (!fimc) | 1691 | if (!fimc) |
1683 | return -ENOMEM; | 1692 | return -ENOMEM; |
1684 | 1693 | ||
@@ -1689,51 +1698,35 @@ static int fimc_probe(struct platform_device *pdev) | |||
1689 | pdata = pdev->dev.platform_data; | 1698 | pdata = pdev->dev.platform_data; |
1690 | fimc->pdata = pdata; | 1699 | fimc->pdata = pdata; |
1691 | 1700 | ||
1692 | |||
1693 | init_waitqueue_head(&fimc->irq_queue); | 1701 | init_waitqueue_head(&fimc->irq_queue); |
1694 | spin_lock_init(&fimc->slock); | 1702 | spin_lock_init(&fimc->slock); |
1695 | mutex_init(&fimc->lock); | 1703 | mutex_init(&fimc->lock); |
1696 | 1704 | ||
1697 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1705 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1698 | if (!res) { | 1706 | fimc->regs = devm_request_and_ioremap(&pdev->dev, res); |
1699 | dev_err(&pdev->dev, "failed to find the registers\n"); | 1707 | if (fimc->regs == NULL) { |
1700 | ret = -ENOENT; | 1708 | dev_err(&pdev->dev, "Failed to obtain io memory\n"); |
1701 | goto err_info; | 1709 | return -ENOENT; |
1702 | } | ||
1703 | |||
1704 | fimc->regs_res = request_mem_region(res->start, resource_size(res), | ||
1705 | dev_name(&pdev->dev)); | ||
1706 | if (!fimc->regs_res) { | ||
1707 | dev_err(&pdev->dev, "failed to obtain register region\n"); | ||
1708 | ret = -ENOENT; | ||
1709 | goto err_info; | ||
1710 | } | ||
1711 | |||
1712 | fimc->regs = ioremap(res->start, resource_size(res)); | ||
1713 | if (!fimc->regs) { | ||
1714 | dev_err(&pdev->dev, "failed to map registers\n"); | ||
1715 | ret = -ENXIO; | ||
1716 | goto err_req_region; | ||
1717 | } | 1710 | } |
1718 | 1711 | ||
1719 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 1712 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
1720 | if (!res) { | 1713 | if (res == NULL) { |
1721 | dev_err(&pdev->dev, "failed to get IRQ resource\n"); | 1714 | dev_err(&pdev->dev, "Failed to get IRQ resource\n"); |
1722 | ret = -ENXIO; | 1715 | return -ENXIO; |
1723 | goto err_regs_unmap; | ||
1724 | } | 1716 | } |
1725 | fimc->irq = res->start; | 1717 | fimc->irq = res->start; |
1726 | 1718 | ||
1727 | fimc->num_clocks = MAX_FIMC_CLOCKS; | 1719 | fimc->num_clocks = MAX_FIMC_CLOCKS; |
1728 | ret = fimc_clk_get(fimc); | 1720 | ret = fimc_clk_get(fimc); |
1729 | if (ret) | 1721 | if (ret) |
1730 | goto err_regs_unmap; | 1722 | return ret; |
1731 | clk_set_rate(fimc->clock[CLK_BUS], drv_data->lclk_frequency); | 1723 | clk_set_rate(fimc->clock[CLK_BUS], drv_data->lclk_frequency); |
1732 | clk_enable(fimc->clock[CLK_BUS]); | 1724 | clk_enable(fimc->clock[CLK_BUS]); |
1733 | 1725 | ||
1734 | platform_set_drvdata(pdev, fimc); | 1726 | platform_set_drvdata(pdev, fimc); |
1735 | 1727 | ||
1736 | ret = request_irq(fimc->irq, fimc_irq_handler, 0, pdev->name, fimc); | 1728 | ret = devm_request_irq(&pdev->dev, fimc->irq, fimc_irq_handler, |
1729 | 0, pdev->name, fimc); | ||
1737 | if (ret) { | 1730 | if (ret) { |
1738 | dev_err(&pdev->dev, "failed to install irq (%d)\n", ret); | 1731 | dev_err(&pdev->dev, "failed to install irq (%d)\n", ret); |
1739 | goto err_clk; | 1732 | goto err_clk; |
@@ -1742,7 +1735,7 @@ static int fimc_probe(struct platform_device *pdev) | |||
1742 | pm_runtime_enable(&pdev->dev); | 1735 | pm_runtime_enable(&pdev->dev); |
1743 | ret = pm_runtime_get_sync(&pdev->dev); | 1736 | ret = pm_runtime_get_sync(&pdev->dev); |
1744 | if (ret < 0) | 1737 | if (ret < 0) |
1745 | goto err_irq; | 1738 | goto err_clk; |
1746 | /* Initialize contiguous memory allocator */ | 1739 | /* Initialize contiguous memory allocator */ |
1747 | fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); | 1740 | fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); |
1748 | if (IS_ERR(fimc->alloc_ctx)) { | 1741 | if (IS_ERR(fimc->alloc_ctx)) { |
@@ -1757,17 +1750,8 @@ static int fimc_probe(struct platform_device *pdev) | |||
1757 | 1750 | ||
1758 | err_pm: | 1751 | err_pm: |
1759 | pm_runtime_put(&pdev->dev); | 1752 | pm_runtime_put(&pdev->dev); |
1760 | err_irq: | ||
1761 | free_irq(fimc->irq, fimc); | ||
1762 | err_clk: | 1753 | err_clk: |
1763 | fimc_clk_put(fimc); | 1754 | fimc_clk_put(fimc); |
1764 | err_regs_unmap: | ||
1765 | iounmap(fimc->regs); | ||
1766 | err_req_region: | ||
1767 | release_resource(fimc->regs_res); | ||
1768 | kfree(fimc->regs_res); | ||
1769 | err_info: | ||
1770 | kfree(fimc); | ||
1771 | return ret; | 1755 | return ret; |
1772 | } | 1756 | } |
1773 | 1757 | ||
@@ -1854,11 +1838,6 @@ static int __devexit fimc_remove(struct platform_device *pdev) | |||
1854 | 1838 | ||
1855 | clk_disable(fimc->clock[CLK_BUS]); | 1839 | clk_disable(fimc->clock[CLK_BUS]); |
1856 | fimc_clk_put(fimc); | 1840 | fimc_clk_put(fimc); |
1857 | free_irq(fimc->irq, fimc); | ||
1858 | iounmap(fimc->regs); | ||
1859 | release_resource(fimc->regs_res); | ||
1860 | kfree(fimc->regs_res); | ||
1861 | kfree(fimc); | ||
1862 | 1841 | ||
1863 | dev_info(&pdev->dev, "driver unloaded\n"); | 1842 | dev_info(&pdev->dev, "driver unloaded\n"); |
1864 | return 0; | 1843 | return 0; |
diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h index 4e20560c73d4..a18291e648e2 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.h +++ b/drivers/media/video/s5p-fimc/fimc-core.h | |||
@@ -434,7 +434,6 @@ struct fimc_ctx; | |||
434 | * @num_clocks: the number of clocks managed by this device instance | 434 | * @num_clocks: the number of clocks managed by this device instance |
435 | * @clock: clocks required for FIMC operation | 435 | * @clock: clocks required for FIMC operation |
436 | * @regs: the mapped hardware registers | 436 | * @regs: the mapped hardware registers |
437 | * @regs_res: the resource claimed for IO registers | ||
438 | * @irq: FIMC interrupt number | 437 | * @irq: FIMC interrupt number |
439 | * @irq_queue: interrupt handler waitqueue | 438 | * @irq_queue: interrupt handler waitqueue |
440 | * @v4l2_dev: root v4l2_device | 439 | * @v4l2_dev: root v4l2_device |
@@ -454,7 +453,6 @@ struct fimc_dev { | |||
454 | u16 num_clocks; | 453 | u16 num_clocks; |
455 | struct clk *clock[MAX_FIMC_CLOCKS]; | 454 | struct clk *clock[MAX_FIMC_CLOCKS]; |
456 | void __iomem *regs; | 455 | void __iomem *regs; |
457 | struct resource *regs_res; | ||
458 | int irq; | 456 | int irq; |
459 | wait_queue_head_t irq_queue; | 457 | wait_queue_head_t irq_queue; |
460 | struct v4l2_device *v4l2_dev; | 458 | struct v4l2_device *v4l2_dev; |
diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.c b/drivers/media/video/s5p-fimc/fimc-mdevice.c index 8ea4ee116e46..62ed37e40149 100644 --- a/drivers/media/video/s5p-fimc/fimc-mdevice.c +++ b/drivers/media/video/s5p-fimc/fimc-mdevice.c | |||
@@ -344,16 +344,13 @@ static int fimc_md_register_platform_entities(struct fimc_md *fmd) | |||
344 | return -ENODEV; | 344 | return -ENODEV; |
345 | ret = driver_for_each_device(driver, NULL, fmd, | 345 | ret = driver_for_each_device(driver, NULL, fmd, |
346 | fimc_register_callback); | 346 | fimc_register_callback); |
347 | put_driver(driver); | ||
348 | if (ret) | 347 | if (ret) |
349 | return ret; | 348 | return ret; |
350 | 349 | ||
351 | driver = driver_find(CSIS_DRIVER_NAME, &platform_bus_type); | 350 | driver = driver_find(CSIS_DRIVER_NAME, &platform_bus_type); |
352 | if (driver) { | 351 | if (driver) |
353 | ret = driver_for_each_device(driver, NULL, fmd, | 352 | ret = driver_for_each_device(driver, NULL, fmd, |
354 | csis_register_callback); | 353 | csis_register_callback); |
355 | put_driver(driver); | ||
356 | } | ||
357 | return ret; | 354 | return ret; |
358 | } | 355 | } |
359 | 356 | ||
@@ -753,7 +750,7 @@ static int __devinit fimc_md_probe(struct platform_device *pdev) | |||
753 | struct fimc_md *fmd; | 750 | struct fimc_md *fmd; |
754 | int ret; | 751 | int ret; |
755 | 752 | ||
756 | fmd = kzalloc(sizeof(struct fimc_md), GFP_KERNEL); | 753 | fmd = devm_kzalloc(&pdev->dev, sizeof(*fmd), GFP_KERNEL); |
757 | if (!fmd) | 754 | if (!fmd) |
758 | return -ENOMEM; | 755 | return -ENOMEM; |
759 | 756 | ||
@@ -774,7 +771,7 @@ static int __devinit fimc_md_probe(struct platform_device *pdev) | |||
774 | ret = v4l2_device_register(&pdev->dev, &fmd->v4l2_dev); | 771 | ret = v4l2_device_register(&pdev->dev, &fmd->v4l2_dev); |
775 | if (ret < 0) { | 772 | if (ret < 0) { |
776 | v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret); | 773 | v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret); |
777 | goto err1; | 774 | return ret; |
778 | } | 775 | } |
779 | ret = media_device_register(&fmd->media_dev); | 776 | ret = media_device_register(&fmd->media_dev); |
780 | if (ret < 0) { | 777 | if (ret < 0) { |
@@ -816,8 +813,6 @@ err3: | |||
816 | fimc_md_unregister_entities(fmd); | 813 | fimc_md_unregister_entities(fmd); |
817 | err2: | 814 | err2: |
818 | v4l2_device_unregister(&fmd->v4l2_dev); | 815 | v4l2_device_unregister(&fmd->v4l2_dev); |
819 | err1: | ||
820 | kfree(fmd); | ||
821 | return ret; | 816 | return ret; |
822 | } | 817 | } |
823 | 818 | ||
@@ -831,7 +826,6 @@ static int __devexit fimc_md_remove(struct platform_device *pdev) | |||
831 | fimc_md_unregister_entities(fmd); | 826 | fimc_md_unregister_entities(fmd); |
832 | media_device_unregister(&fmd->media_dev); | 827 | media_device_unregister(&fmd->media_dev); |
833 | fimc_md_put_clocks(fmd); | 828 | fimc_md_put_clocks(fmd); |
834 | kfree(fmd); | ||
835 | return 0; | 829 | return 0; |
836 | } | 830 | } |
837 | 831 | ||
diff --git a/drivers/media/video/s5p-fimc/mipi-csis.c b/drivers/media/video/s5p-fimc/mipi-csis.c index 130335cf62fd..f44f690397f7 100644 --- a/drivers/media/video/s5p-fimc/mipi-csis.c +++ b/drivers/media/video/s5p-fimc/mipi-csis.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver | 2 | * Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver |
3 | * | 3 | * |
4 | * Copyright (C) 2011 Samsung Electronics Co., Ltd. | 4 | * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. |
5 | * Contact: Sylwester Nawrocki, <s.nawrocki@samsung.com> | 5 | * Sylwester Nawrocki, <s.nawrocki@samsung.com> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
@@ -100,7 +100,6 @@ enum { | |||
100 | * @pads: CSIS pads array | 100 | * @pads: CSIS pads array |
101 | * @sd: v4l2_subdev associated with CSIS device instance | 101 | * @sd: v4l2_subdev associated with CSIS device instance |
102 | * @pdev: CSIS platform device | 102 | * @pdev: CSIS platform device |
103 | * @regs_res: requested I/O register memory resource | ||
104 | * @regs: mmaped I/O registers memory | 103 | * @regs: mmaped I/O registers memory |
105 | * @clock: CSIS clocks | 104 | * @clock: CSIS clocks |
106 | * @irq: requested s5p-mipi-csis irq number | 105 | * @irq: requested s5p-mipi-csis irq number |
@@ -113,7 +112,6 @@ struct csis_state { | |||
113 | struct media_pad pads[CSIS_PADS_NUM]; | 112 | struct media_pad pads[CSIS_PADS_NUM]; |
114 | struct v4l2_subdev sd; | 113 | struct v4l2_subdev sd; |
115 | struct platform_device *pdev; | 114 | struct platform_device *pdev; |
116 | struct resource *regs_res; | ||
117 | void __iomem *regs; | 115 | void __iomem *regs; |
118 | struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES]; | 116 | struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES]; |
119 | struct clk *clock[NUM_CSIS_CLOCKS]; | 117 | struct clk *clock[NUM_CSIS_CLOCKS]; |
@@ -258,26 +256,36 @@ static void s5pcsis_clk_put(struct csis_state *state) | |||
258 | { | 256 | { |
259 | int i; | 257 | int i; |
260 | 258 | ||
261 | for (i = 0; i < NUM_CSIS_CLOCKS; i++) | 259 | for (i = 0; i < NUM_CSIS_CLOCKS; i++) { |
262 | if (!IS_ERR_OR_NULL(state->clock[i])) | 260 | if (IS_ERR_OR_NULL(state->clock[i])) |
263 | clk_put(state->clock[i]); | 261 | continue; |
262 | clk_unprepare(state->clock[i]); | ||
263 | clk_put(state->clock[i]); | ||
264 | state->clock[i] = NULL; | ||
265 | } | ||
264 | } | 266 | } |
265 | 267 | ||
266 | static int s5pcsis_clk_get(struct csis_state *state) | 268 | static int s5pcsis_clk_get(struct csis_state *state) |
267 | { | 269 | { |
268 | struct device *dev = &state->pdev->dev; | 270 | struct device *dev = &state->pdev->dev; |
269 | int i; | 271 | int i, ret; |
270 | 272 | ||
271 | for (i = 0; i < NUM_CSIS_CLOCKS; i++) { | 273 | for (i = 0; i < NUM_CSIS_CLOCKS; i++) { |
272 | state->clock[i] = clk_get(dev, csi_clock_name[i]); | 274 | state->clock[i] = clk_get(dev, csi_clock_name[i]); |
273 | if (IS_ERR(state->clock[i])) { | 275 | if (IS_ERR(state->clock[i])) |
274 | s5pcsis_clk_put(state); | 276 | goto err; |
275 | dev_err(dev, "failed to get clock: %s\n", | 277 | ret = clk_prepare(state->clock[i]); |
276 | csi_clock_name[i]); | 278 | if (ret < 0) { |
277 | return -ENXIO; | 279 | clk_put(state->clock[i]); |
280 | state->clock[i] = NULL; | ||
281 | goto err; | ||
278 | } | 282 | } |
279 | } | 283 | } |
280 | return 0; | 284 | return 0; |
285 | err: | ||
286 | s5pcsis_clk_put(state); | ||
287 | dev_err(dev, "failed to get clock: %s\n", csi_clock_name[i]); | ||
288 | return -ENXIO; | ||
281 | } | 289 | } |
282 | 290 | ||
283 | static int s5pcsis_s_power(struct v4l2_subdev *sd, int on) | 291 | static int s5pcsis_s_power(struct v4l2_subdev *sd, int on) |
@@ -480,12 +488,11 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev) | |||
480 | { | 488 | { |
481 | struct s5p_platform_mipi_csis *pdata; | 489 | struct s5p_platform_mipi_csis *pdata; |
482 | struct resource *mem_res; | 490 | struct resource *mem_res; |
483 | struct resource *regs_res; | ||
484 | struct csis_state *state; | 491 | struct csis_state *state; |
485 | int ret = -ENOMEM; | 492 | int ret = -ENOMEM; |
486 | int i; | 493 | int i; |
487 | 494 | ||
488 | state = kzalloc(sizeof(*state), GFP_KERNEL); | 495 | state = devm_kzalloc(&pdev->dev, sizeof(*state), GFP_KERNEL); |
489 | if (!state) | 496 | if (!state) |
490 | return -ENOMEM; | 497 | return -ENOMEM; |
491 | 498 | ||
@@ -495,52 +502,27 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev) | |||
495 | pdata = pdev->dev.platform_data; | 502 | pdata = pdev->dev.platform_data; |
496 | if (pdata == NULL || pdata->phy_enable == NULL) { | 503 | if (pdata == NULL || pdata->phy_enable == NULL) { |
497 | dev_err(&pdev->dev, "Platform data not fully specified\n"); | 504 | dev_err(&pdev->dev, "Platform data not fully specified\n"); |
498 | goto e_free; | 505 | return -EINVAL; |
499 | } | 506 | } |
500 | 507 | ||
501 | if ((pdev->id == 1 && pdata->lanes > CSIS1_MAX_LANES) || | 508 | if ((pdev->id == 1 && pdata->lanes > CSIS1_MAX_LANES) || |
502 | pdata->lanes > CSIS0_MAX_LANES) { | 509 | pdata->lanes > CSIS0_MAX_LANES) { |
503 | ret = -EINVAL; | ||
504 | dev_err(&pdev->dev, "Unsupported number of data lanes: %d\n", | 510 | dev_err(&pdev->dev, "Unsupported number of data lanes: %d\n", |
505 | pdata->lanes); | 511 | pdata->lanes); |
506 | goto e_free; | 512 | return -EINVAL; |
507 | } | 513 | } |
508 | 514 | ||
509 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 515 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
510 | if (!mem_res) { | 516 | state->regs = devm_request_and_ioremap(&pdev->dev, mem_res); |
511 | dev_err(&pdev->dev, "Failed to get IO memory region\n"); | 517 | if (state->regs == NULL) { |
512 | goto e_free; | 518 | dev_err(&pdev->dev, "Failed to request and remap io memory\n"); |
519 | return -ENXIO; | ||
513 | } | 520 | } |
514 | 521 | ||
515 | regs_res = request_mem_region(mem_res->start, resource_size(mem_res), | ||
516 | pdev->name); | ||
517 | if (!regs_res) { | ||
518 | dev_err(&pdev->dev, "Failed to request IO memory region\n"); | ||
519 | goto e_free; | ||
520 | } | ||
521 | state->regs_res = regs_res; | ||
522 | |||
523 | state->regs = ioremap(mem_res->start, resource_size(mem_res)); | ||
524 | if (!state->regs) { | ||
525 | dev_err(&pdev->dev, "Failed to remap IO region\n"); | ||
526 | goto e_reqmem; | ||
527 | } | ||
528 | |||
529 | ret = s5pcsis_clk_get(state); | ||
530 | if (ret) | ||
531 | goto e_unmap; | ||
532 | |||
533 | clk_enable(state->clock[CSIS_CLK_MUX]); | ||
534 | if (pdata->clk_rate) | ||
535 | clk_set_rate(state->clock[CSIS_CLK_MUX], pdata->clk_rate); | ||
536 | else | ||
537 | dev_WARN(&pdev->dev, "No clock frequency specified!\n"); | ||
538 | |||
539 | state->irq = platform_get_irq(pdev, 0); | 522 | state->irq = platform_get_irq(pdev, 0); |
540 | if (state->irq < 0) { | 523 | if (state->irq < 0) { |
541 | ret = state->irq; | ||
542 | dev_err(&pdev->dev, "Failed to get irq\n"); | 524 | dev_err(&pdev->dev, "Failed to get irq\n"); |
543 | goto e_clkput; | 525 | return state->irq; |
544 | } | 526 | } |
545 | 527 | ||
546 | for (i = 0; i < CSIS_NUM_SUPPLIES; i++) | 528 | for (i = 0; i < CSIS_NUM_SUPPLIES; i++) |
@@ -549,12 +531,22 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev) | |||
549 | ret = regulator_bulk_get(&pdev->dev, CSIS_NUM_SUPPLIES, | 531 | ret = regulator_bulk_get(&pdev->dev, CSIS_NUM_SUPPLIES, |
550 | state->supplies); | 532 | state->supplies); |
551 | if (ret) | 533 | if (ret) |
534 | return ret; | ||
535 | |||
536 | ret = s5pcsis_clk_get(state); | ||
537 | if (ret) | ||
552 | goto e_clkput; | 538 | goto e_clkput; |
553 | 539 | ||
554 | ret = request_irq(state->irq, s5pcsis_irq_handler, 0, | 540 | clk_enable(state->clock[CSIS_CLK_MUX]); |
555 | dev_name(&pdev->dev), state); | 541 | if (pdata->clk_rate) |
542 | clk_set_rate(state->clock[CSIS_CLK_MUX], pdata->clk_rate); | ||
543 | else | ||
544 | dev_WARN(&pdev->dev, "No clock frequency specified!\n"); | ||
545 | |||
546 | ret = devm_request_irq(&pdev->dev, state->irq, s5pcsis_irq_handler, | ||
547 | 0, dev_name(&pdev->dev), state); | ||
556 | if (ret) { | 548 | if (ret) { |
557 | dev_err(&pdev->dev, "request_irq failed\n"); | 549 | dev_err(&pdev->dev, "Interrupt request failed\n"); |
558 | goto e_regput; | 550 | goto e_regput; |
559 | } | 551 | } |
560 | 552 | ||
@@ -573,7 +565,7 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev) | |||
573 | ret = media_entity_init(&state->sd.entity, | 565 | ret = media_entity_init(&state->sd.entity, |
574 | CSIS_PADS_NUM, state->pads, 0); | 566 | CSIS_PADS_NUM, state->pads, 0); |
575 | if (ret < 0) | 567 | if (ret < 0) |
576 | goto e_irqfree; | 568 | goto e_clkput; |
577 | 569 | ||
578 | /* This allows to retrieve the platform device id by the host driver */ | 570 | /* This allows to retrieve the platform device id by the host driver */ |
579 | v4l2_set_subdevdata(&state->sd, pdev); | 571 | v4l2_set_subdevdata(&state->sd, pdev); |
@@ -582,22 +574,13 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev) | |||
582 | platform_set_drvdata(pdev, &state->sd); | 574 | platform_set_drvdata(pdev, &state->sd); |
583 | 575 | ||
584 | pm_runtime_enable(&pdev->dev); | 576 | pm_runtime_enable(&pdev->dev); |
585 | |||
586 | return 0; | 577 | return 0; |
587 | 578 | ||
588 | e_irqfree: | ||
589 | free_irq(state->irq, state); | ||
590 | e_regput: | 579 | e_regput: |
591 | regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies); | 580 | regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies); |
592 | e_clkput: | 581 | e_clkput: |
593 | clk_disable(state->clock[CSIS_CLK_MUX]); | 582 | clk_disable(state->clock[CSIS_CLK_MUX]); |
594 | s5pcsis_clk_put(state); | 583 | s5pcsis_clk_put(state); |
595 | e_unmap: | ||
596 | iounmap(state->regs); | ||
597 | e_reqmem: | ||
598 | release_mem_region(regs_res->start, resource_size(regs_res)); | ||
599 | e_free: | ||
600 | kfree(state); | ||
601 | return ret; | 584 | return ret; |
602 | } | 585 | } |
603 | 586 | ||
@@ -699,21 +682,15 @@ static int __devexit s5pcsis_remove(struct platform_device *pdev) | |||
699 | { | 682 | { |
700 | struct v4l2_subdev *sd = platform_get_drvdata(pdev); | 683 | struct v4l2_subdev *sd = platform_get_drvdata(pdev); |
701 | struct csis_state *state = sd_to_csis_state(sd); | 684 | struct csis_state *state = sd_to_csis_state(sd); |
702 | struct resource *res = state->regs_res; | ||
703 | 685 | ||
704 | pm_runtime_disable(&pdev->dev); | 686 | pm_runtime_disable(&pdev->dev); |
705 | s5pcsis_suspend(&pdev->dev); | 687 | s5pcsis_pm_suspend(&pdev->dev, false); |
706 | clk_disable(state->clock[CSIS_CLK_MUX]); | 688 | clk_disable(state->clock[CSIS_CLK_MUX]); |
707 | pm_runtime_set_suspended(&pdev->dev); | 689 | pm_runtime_set_suspended(&pdev->dev); |
708 | |||
709 | s5pcsis_clk_put(state); | 690 | s5pcsis_clk_put(state); |
710 | regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies); | 691 | regulator_bulk_free(CSIS_NUM_SUPPLIES, state->supplies); |
711 | 692 | ||
712 | media_entity_cleanup(&state->sd.entity); | 693 | media_entity_cleanup(&state->sd.entity); |
713 | free_irq(state->irq, state); | ||
714 | iounmap(state->regs); | ||
715 | release_mem_region(res->start, resource_size(res)); | ||
716 | kfree(state); | ||
717 | 694 | ||
718 | return 0; | 695 | return 0; |
719 | } | 696 | } |
diff --git a/drivers/media/video/s5p-g2d/g2d-hw.c b/drivers/media/video/s5p-g2d/g2d-hw.c index 39937cf03c88..5b86cbe408e2 100644 --- a/drivers/media/video/s5p-g2d/g2d-hw.c +++ b/drivers/media/video/s5p-g2d/g2d-hw.c | |||
@@ -77,6 +77,11 @@ void g2d_set_rop4(struct g2d_dev *d, u32 r) | |||
77 | w(r, ROP4_REG); | 77 | w(r, ROP4_REG); |
78 | } | 78 | } |
79 | 79 | ||
80 | void g2d_set_flip(struct g2d_dev *d, u32 r) | ||
81 | { | ||
82 | w(r, SRC_MSK_DIRECT_REG); | ||
83 | } | ||
84 | |||
80 | u32 g2d_cmd_stretch(u32 e) | 85 | u32 g2d_cmd_stretch(u32 e) |
81 | { | 86 | { |
82 | e &= 1; | 87 | e &= 1; |
diff --git a/drivers/media/video/s5p-g2d/g2d.c b/drivers/media/video/s5p-g2d/g2d.c index febaa673d363..789de74014e5 100644 --- a/drivers/media/video/s5p-g2d/g2d.c +++ b/drivers/media/video/s5p-g2d/g2d.c | |||
@@ -178,6 +178,9 @@ static int g2d_s_ctrl(struct v4l2_ctrl *ctrl) | |||
178 | { | 178 | { |
179 | struct g2d_ctx *ctx = container_of(ctrl->handler, struct g2d_ctx, | 179 | struct g2d_ctx *ctx = container_of(ctrl->handler, struct g2d_ctx, |
180 | ctrl_handler); | 180 | ctrl_handler); |
181 | unsigned long flags; | ||
182 | |||
183 | spin_lock_irqsave(&ctx->dev->ctrl_lock, flags); | ||
181 | switch (ctrl->id) { | 184 | switch (ctrl->id) { |
182 | case V4L2_CID_COLORFX: | 185 | case V4L2_CID_COLORFX: |
183 | if (ctrl->val == V4L2_COLORFX_NEGATIVE) | 186 | if (ctrl->val == V4L2_COLORFX_NEGATIVE) |
@@ -185,10 +188,13 @@ static int g2d_s_ctrl(struct v4l2_ctrl *ctrl) | |||
185 | else | 188 | else |
186 | ctx->rop = ROP4_COPY; | 189 | ctx->rop = ROP4_COPY; |
187 | break; | 190 | break; |
188 | default: | 191 | |
189 | v4l2_err(&ctx->dev->v4l2_dev, "unknown control\n"); | 192 | case V4L2_CID_HFLIP: |
190 | return -EINVAL; | 193 | ctx->flip = ctx->ctrl_hflip->val | (ctx->ctrl_vflip->val << 1); |
194 | break; | ||
195 | |||
191 | } | 196 | } |
197 | spin_unlock_irqrestore(&ctx->dev->ctrl_lock, flags); | ||
192 | return 0; | 198 | return 0; |
193 | } | 199 | } |
194 | 200 | ||
@@ -200,11 +206,13 @@ int g2d_setup_ctrls(struct g2d_ctx *ctx) | |||
200 | { | 206 | { |
201 | struct g2d_dev *dev = ctx->dev; | 207 | struct g2d_dev *dev = ctx->dev; |
202 | 208 | ||
203 | v4l2_ctrl_handler_init(&ctx->ctrl_handler, 1); | 209 | v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3); |
204 | if (ctx->ctrl_handler.error) { | 210 | |
205 | v4l2_err(&dev->v4l2_dev, "v4l2_ctrl_handler_init failed\n"); | 211 | ctx->ctrl_hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &g2d_ctrl_ops, |
206 | return ctx->ctrl_handler.error; | 212 | V4L2_CID_HFLIP, 0, 1, 1, 0); |
207 | } | 213 | |
214 | ctx->ctrl_vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &g2d_ctrl_ops, | ||
215 | V4L2_CID_VFLIP, 0, 1, 1, 0); | ||
208 | 216 | ||
209 | v4l2_ctrl_new_std_menu( | 217 | v4l2_ctrl_new_std_menu( |
210 | &ctx->ctrl_handler, | 218 | &ctx->ctrl_handler, |
@@ -215,10 +223,14 @@ int g2d_setup_ctrls(struct g2d_ctx *ctx) | |||
215 | V4L2_COLORFX_NONE); | 223 | V4L2_COLORFX_NONE); |
216 | 224 | ||
217 | if (ctx->ctrl_handler.error) { | 225 | if (ctx->ctrl_handler.error) { |
218 | v4l2_err(&dev->v4l2_dev, "v4l2_ctrl_handler_init failed\n"); | 226 | int err = ctx->ctrl_handler.error; |
219 | return ctx->ctrl_handler.error; | 227 | v4l2_err(&dev->v4l2_dev, "g2d_setup_ctrls failed\n"); |
228 | v4l2_ctrl_handler_free(&ctx->ctrl_handler); | ||
229 | return err; | ||
220 | } | 230 | } |
221 | 231 | ||
232 | v4l2_ctrl_cluster(2, &ctx->ctrl_hflip); | ||
233 | |||
222 | return 0; | 234 | return 0; |
223 | } | 235 | } |
224 | 236 | ||
@@ -547,6 +559,7 @@ static void device_run(void *prv) | |||
547 | struct g2d_ctx *ctx = prv; | 559 | struct g2d_ctx *ctx = prv; |
548 | struct g2d_dev *dev = ctx->dev; | 560 | struct g2d_dev *dev = ctx->dev; |
549 | struct vb2_buffer *src, *dst; | 561 | struct vb2_buffer *src, *dst; |
562 | unsigned long flags; | ||
550 | u32 cmd = 0; | 563 | u32 cmd = 0; |
551 | 564 | ||
552 | dev->curr = ctx; | 565 | dev->curr = ctx; |
@@ -557,6 +570,8 @@ static void device_run(void *prv) | |||
557 | clk_enable(dev->gate); | 570 | clk_enable(dev->gate); |
558 | g2d_reset(dev); | 571 | g2d_reset(dev); |
559 | 572 | ||
573 | spin_lock_irqsave(&dev->ctrl_lock, flags); | ||
574 | |||
560 | g2d_set_src_size(dev, &ctx->in); | 575 | g2d_set_src_size(dev, &ctx->in); |
561 | g2d_set_src_addr(dev, vb2_dma_contig_plane_dma_addr(src, 0)); | 576 | g2d_set_src_addr(dev, vb2_dma_contig_plane_dma_addr(src, 0)); |
562 | 577 | ||
@@ -564,11 +579,15 @@ static void device_run(void *prv) | |||
564 | g2d_set_dst_addr(dev, vb2_dma_contig_plane_dma_addr(dst, 0)); | 579 | g2d_set_dst_addr(dev, vb2_dma_contig_plane_dma_addr(dst, 0)); |
565 | 580 | ||
566 | g2d_set_rop4(dev, ctx->rop); | 581 | g2d_set_rop4(dev, ctx->rop); |
582 | g2d_set_flip(dev, ctx->flip); | ||
583 | |||
567 | if (ctx->in.c_width != ctx->out.c_width || | 584 | if (ctx->in.c_width != ctx->out.c_width || |
568 | ctx->in.c_height != ctx->out.c_height) | 585 | ctx->in.c_height != ctx->out.c_height) |
569 | cmd |= g2d_cmd_stretch(1); | 586 | cmd |= g2d_cmd_stretch(1); |
570 | g2d_set_cmd(dev, cmd); | 587 | g2d_set_cmd(dev, cmd); |
571 | g2d_start(dev); | 588 | g2d_start(dev); |
589 | |||
590 | spin_unlock_irqrestore(&dev->ctrl_lock, flags); | ||
572 | } | 591 | } |
573 | 592 | ||
574 | static irqreturn_t g2d_isr(int irq, void *prv) | 593 | static irqreturn_t g2d_isr(int irq, void *prv) |
@@ -658,7 +677,7 @@ static int g2d_probe(struct platform_device *pdev) | |||
658 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 677 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
659 | if (!dev) | 678 | if (!dev) |
660 | return -ENOMEM; | 679 | return -ENOMEM; |
661 | spin_lock_init(&dev->irqlock); | 680 | spin_lock_init(&dev->ctrl_lock); |
662 | mutex_init(&dev->mutex); | 681 | mutex_init(&dev->mutex); |
663 | atomic_set(&dev->num_inst, 0); | 682 | atomic_set(&dev->num_inst, 0); |
664 | init_waitqueue_head(&dev->irq_queue); | 683 | init_waitqueue_head(&dev->irq_queue); |
@@ -693,18 +712,30 @@ static int g2d_probe(struct platform_device *pdev) | |||
693 | goto unmap_regs; | 712 | goto unmap_regs; |
694 | } | 713 | } |
695 | 714 | ||
715 | ret = clk_prepare(dev->clk); | ||
716 | if (ret) { | ||
717 | dev_err(&pdev->dev, "failed to prepare g2d clock\n"); | ||
718 | goto put_clk; | ||
719 | } | ||
720 | |||
696 | dev->gate = clk_get(&pdev->dev, "fimg2d"); | 721 | dev->gate = clk_get(&pdev->dev, "fimg2d"); |
697 | if (IS_ERR_OR_NULL(dev->gate)) { | 722 | if (IS_ERR_OR_NULL(dev->gate)) { |
698 | dev_err(&pdev->dev, "failed to get g2d clock gate\n"); | 723 | dev_err(&pdev->dev, "failed to get g2d clock gate\n"); |
699 | ret = -ENXIO; | 724 | ret = -ENXIO; |
700 | goto put_clk; | 725 | goto unprep_clk; |
726 | } | ||
727 | |||
728 | ret = clk_prepare(dev->gate); | ||
729 | if (ret) { | ||
730 | dev_err(&pdev->dev, "failed to prepare g2d clock gate\n"); | ||
731 | goto put_clk_gate; | ||
701 | } | 732 | } |
702 | 733 | ||
703 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 734 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
704 | if (!res) { | 735 | if (!res) { |
705 | dev_err(&pdev->dev, "failed to find IRQ\n"); | 736 | dev_err(&pdev->dev, "failed to find IRQ\n"); |
706 | ret = -ENXIO; | 737 | ret = -ENXIO; |
707 | goto put_clk_gate; | 738 | goto unprep_clk_gate; |
708 | } | 739 | } |
709 | 740 | ||
710 | dev->irq = res->start; | 741 | dev->irq = res->start; |
@@ -764,8 +795,12 @@ alloc_ctx_cleanup: | |||
764 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); | 795 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); |
765 | rel_irq: | 796 | rel_irq: |
766 | free_irq(dev->irq, dev); | 797 | free_irq(dev->irq, dev); |
798 | unprep_clk_gate: | ||
799 | clk_unprepare(dev->gate); | ||
767 | put_clk_gate: | 800 | put_clk_gate: |
768 | clk_put(dev->gate); | 801 | clk_put(dev->gate); |
802 | unprep_clk: | ||
803 | clk_unprepare(dev->clk); | ||
769 | put_clk: | 804 | put_clk: |
770 | clk_put(dev->clk); | 805 | clk_put(dev->clk); |
771 | unmap_regs: | 806 | unmap_regs: |
@@ -787,7 +822,9 @@ static int g2d_remove(struct platform_device *pdev) | |||
787 | v4l2_device_unregister(&dev->v4l2_dev); | 822 | v4l2_device_unregister(&dev->v4l2_dev); |
788 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); | 823 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); |
789 | free_irq(dev->irq, dev); | 824 | free_irq(dev->irq, dev); |
825 | clk_unprepare(dev->gate); | ||
790 | clk_put(dev->gate); | 826 | clk_put(dev->gate); |
827 | clk_unprepare(dev->clk); | ||
791 | clk_put(dev->clk); | 828 | clk_put(dev->clk); |
792 | iounmap(dev->regs); | 829 | iounmap(dev->regs); |
793 | release_resource(dev->res_regs); | 830 | release_resource(dev->res_regs); |
diff --git a/drivers/media/video/s5p-g2d/g2d.h b/drivers/media/video/s5p-g2d/g2d.h index 5eae90107bf8..1b82065aeaef 100644 --- a/drivers/media/video/s5p-g2d/g2d.h +++ b/drivers/media/video/s5p-g2d/g2d.h | |||
@@ -20,7 +20,7 @@ struct g2d_dev { | |||
20 | struct v4l2_m2m_dev *m2m_dev; | 20 | struct v4l2_m2m_dev *m2m_dev; |
21 | struct video_device *vfd; | 21 | struct video_device *vfd; |
22 | struct mutex mutex; | 22 | struct mutex mutex; |
23 | spinlock_t irqlock; | 23 | spinlock_t ctrl_lock; |
24 | atomic_t num_inst; | 24 | atomic_t num_inst; |
25 | struct vb2_alloc_ctx *alloc_ctx; | 25 | struct vb2_alloc_ctx *alloc_ctx; |
26 | struct resource *res_regs; | 26 | struct resource *res_regs; |
@@ -57,8 +57,11 @@ struct g2d_ctx { | |||
57 | struct v4l2_m2m_ctx *m2m_ctx; | 57 | struct v4l2_m2m_ctx *m2m_ctx; |
58 | struct g2d_frame in; | 58 | struct g2d_frame in; |
59 | struct g2d_frame out; | 59 | struct g2d_frame out; |
60 | struct v4l2_ctrl *ctrl_hflip; | ||
61 | struct v4l2_ctrl *ctrl_vflip; | ||
60 | struct v4l2_ctrl_handler ctrl_handler; | 62 | struct v4l2_ctrl_handler ctrl_handler; |
61 | u32 rop; | 63 | u32 rop; |
64 | u32 flip; | ||
62 | }; | 65 | }; |
63 | 66 | ||
64 | struct g2d_fmt { | 67 | struct g2d_fmt { |
@@ -77,6 +80,7 @@ void g2d_set_dst_addr(struct g2d_dev *d, dma_addr_t a); | |||
77 | void g2d_start(struct g2d_dev *d); | 80 | void g2d_start(struct g2d_dev *d); |
78 | void g2d_clear_int(struct g2d_dev *d); | 81 | void g2d_clear_int(struct g2d_dev *d); |
79 | void g2d_set_rop4(struct g2d_dev *d, u32 r); | 82 | void g2d_set_rop4(struct g2d_dev *d, u32 r); |
83 | void g2d_set_flip(struct g2d_dev *d, u32 r); | ||
80 | u32 g2d_cmd_stretch(u32 e); | 84 | u32 g2d_cmd_stretch(u32 e); |
81 | void g2d_set_cmd(struct g2d_dev *d, u32 c); | 85 | void g2d_set_cmd(struct g2d_dev *d, u32 c); |
82 | 86 | ||
diff --git a/drivers/media/video/s5p-jpeg/jpeg-core.c b/drivers/media/video/s5p-jpeg/jpeg-core.c index 1105a8749c8b..5a49c307f9c1 100644 --- a/drivers/media/video/s5p-jpeg/jpeg-core.c +++ b/drivers/media/video/s5p-jpeg/jpeg-core.c | |||
@@ -32,10 +32,9 @@ | |||
32 | 32 | ||
33 | static struct s5p_jpeg_fmt formats_enc[] = { | 33 | static struct s5p_jpeg_fmt formats_enc[] = { |
34 | { | 34 | { |
35 | .name = "YUV 4:2:0 planar, YCbCr", | 35 | .name = "JPEG JFIF", |
36 | .fourcc = V4L2_PIX_FMT_YUV420, | 36 | .fourcc = V4L2_PIX_FMT_JPEG, |
37 | .depth = 12, | 37 | .colplanes = 1, |
38 | .colplanes = 3, | ||
39 | .types = MEM2MEM_CAPTURE, | 38 | .types = MEM2MEM_CAPTURE, |
40 | }, | 39 | }, |
41 | { | 40 | { |
@@ -43,7 +42,7 @@ static struct s5p_jpeg_fmt formats_enc[] = { | |||
43 | .fourcc = V4L2_PIX_FMT_YUYV, | 42 | .fourcc = V4L2_PIX_FMT_YUYV, |
44 | .depth = 16, | 43 | .depth = 16, |
45 | .colplanes = 1, | 44 | .colplanes = 1, |
46 | .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, | 45 | .types = MEM2MEM_OUTPUT, |
47 | }, | 46 | }, |
48 | { | 47 | { |
49 | .name = "RGB565", | 48 | .name = "RGB565", |
@@ -203,6 +202,16 @@ static const unsigned char hactblg0[162] = { | |||
203 | 0xf9, 0xfa | 202 | 0xf9, 0xfa |
204 | }; | 203 | }; |
205 | 204 | ||
205 | static inline struct s5p_jpeg_ctx *ctrl_to_ctx(struct v4l2_ctrl *c) | ||
206 | { | ||
207 | return container_of(c->handler, struct s5p_jpeg_ctx, ctrl_handler); | ||
208 | } | ||
209 | |||
210 | static inline struct s5p_jpeg_ctx *fh_to_ctx(struct v4l2_fh *fh) | ||
211 | { | ||
212 | return container_of(fh, struct s5p_jpeg_ctx, fh); | ||
213 | } | ||
214 | |||
206 | static inline void jpeg_set_qtbl(void __iomem *regs, const unsigned char *qtbl, | 215 | static inline void jpeg_set_qtbl(void __iomem *regs, const unsigned char *qtbl, |
207 | unsigned long tab, int len) | 216 | unsigned long tab, int len) |
208 | { | 217 | { |
@@ -269,6 +278,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, | |||
269 | struct vb2_queue *dst_vq); | 278 | struct vb2_queue *dst_vq); |
270 | static struct s5p_jpeg_fmt *s5p_jpeg_find_format(unsigned int mode, | 279 | static struct s5p_jpeg_fmt *s5p_jpeg_find_format(unsigned int mode, |
271 | __u32 pixelformat); | 280 | __u32 pixelformat); |
281 | static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx); | ||
272 | 282 | ||
273 | static int s5p_jpeg_open(struct file *file) | 283 | static int s5p_jpeg_open(struct file *file) |
274 | { | 284 | { |
@@ -276,12 +286,18 @@ static int s5p_jpeg_open(struct file *file) | |||
276 | struct video_device *vfd = video_devdata(file); | 286 | struct video_device *vfd = video_devdata(file); |
277 | struct s5p_jpeg_ctx *ctx; | 287 | struct s5p_jpeg_ctx *ctx; |
278 | struct s5p_jpeg_fmt *out_fmt; | 288 | struct s5p_jpeg_fmt *out_fmt; |
289 | int ret = 0; | ||
279 | 290 | ||
280 | ctx = kzalloc(sizeof *ctx, GFP_KERNEL); | 291 | ctx = kzalloc(sizeof *ctx, GFP_KERNEL); |
281 | if (!ctx) | 292 | if (!ctx) |
282 | return -ENOMEM; | 293 | return -ENOMEM; |
283 | 294 | ||
284 | file->private_data = ctx; | 295 | v4l2_fh_init(&ctx->fh, vfd); |
296 | /* Use separate control handler per file handle */ | ||
297 | ctx->fh.ctrl_handler = &ctx->ctrl_handler; | ||
298 | file->private_data = &ctx->fh; | ||
299 | v4l2_fh_add(&ctx->fh); | ||
300 | |||
285 | ctx->jpeg = jpeg; | 301 | ctx->jpeg = jpeg; |
286 | if (vfd == jpeg->vfd_encoder) { | 302 | if (vfd == jpeg->vfd_encoder) { |
287 | ctx->mode = S5P_JPEG_ENCODE; | 303 | ctx->mode = S5P_JPEG_ENCODE; |
@@ -291,24 +307,35 @@ static int s5p_jpeg_open(struct file *file) | |||
291 | out_fmt = s5p_jpeg_find_format(ctx->mode, V4L2_PIX_FMT_JPEG); | 307 | out_fmt = s5p_jpeg_find_format(ctx->mode, V4L2_PIX_FMT_JPEG); |
292 | } | 308 | } |
293 | 309 | ||
310 | ret = s5p_jpeg_controls_create(ctx); | ||
311 | if (ret < 0) | ||
312 | goto error; | ||
313 | |||
294 | ctx->m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, queue_init); | 314 | ctx->m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, queue_init); |
295 | if (IS_ERR(ctx->m2m_ctx)) { | 315 | if (IS_ERR(ctx->m2m_ctx)) { |
296 | int err = PTR_ERR(ctx->m2m_ctx); | 316 | ret = PTR_ERR(ctx->m2m_ctx); |
297 | kfree(ctx); | 317 | goto error; |
298 | return err; | ||
299 | } | 318 | } |
300 | 319 | ||
301 | ctx->out_q.fmt = out_fmt; | 320 | ctx->out_q.fmt = out_fmt; |
302 | ctx->cap_q.fmt = s5p_jpeg_find_format(ctx->mode, V4L2_PIX_FMT_YUYV); | 321 | ctx->cap_q.fmt = s5p_jpeg_find_format(ctx->mode, V4L2_PIX_FMT_YUYV); |
303 | |||
304 | return 0; | 322 | return 0; |
323 | |||
324 | error: | ||
325 | v4l2_fh_del(&ctx->fh); | ||
326 | v4l2_fh_exit(&ctx->fh); | ||
327 | kfree(ctx); | ||
328 | return ret; | ||
305 | } | 329 | } |
306 | 330 | ||
307 | static int s5p_jpeg_release(struct file *file) | 331 | static int s5p_jpeg_release(struct file *file) |
308 | { | 332 | { |
309 | struct s5p_jpeg_ctx *ctx = file->private_data; | 333 | struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data); |
310 | 334 | ||
311 | v4l2_m2m_ctx_release(ctx->m2m_ctx); | 335 | v4l2_m2m_ctx_release(ctx->m2m_ctx); |
336 | v4l2_ctrl_handler_free(&ctx->ctrl_handler); | ||
337 | v4l2_fh_del(&ctx->fh); | ||
338 | v4l2_fh_exit(&ctx->fh); | ||
312 | kfree(ctx); | 339 | kfree(ctx); |
313 | 340 | ||
314 | return 0; | 341 | return 0; |
@@ -317,14 +344,14 @@ static int s5p_jpeg_release(struct file *file) | |||
317 | static unsigned int s5p_jpeg_poll(struct file *file, | 344 | static unsigned int s5p_jpeg_poll(struct file *file, |
318 | struct poll_table_struct *wait) | 345 | struct poll_table_struct *wait) |
319 | { | 346 | { |
320 | struct s5p_jpeg_ctx *ctx = file->private_data; | 347 | struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data); |
321 | 348 | ||
322 | return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); | 349 | return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); |
323 | } | 350 | } |
324 | 351 | ||
325 | static int s5p_jpeg_mmap(struct file *file, struct vm_area_struct *vma) | 352 | static int s5p_jpeg_mmap(struct file *file, struct vm_area_struct *vma) |
326 | { | 353 | { |
327 | struct s5p_jpeg_ctx *ctx = file->private_data; | 354 | struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data); |
328 | 355 | ||
329 | return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); | 356 | return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); |
330 | } | 357 | } |
@@ -448,7 +475,7 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, | |||
448 | static int s5p_jpeg_querycap(struct file *file, void *priv, | 475 | static int s5p_jpeg_querycap(struct file *file, void *priv, |
449 | struct v4l2_capability *cap) | 476 | struct v4l2_capability *cap) |
450 | { | 477 | { |
451 | struct s5p_jpeg_ctx *ctx = priv; | 478 | struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); |
452 | 479 | ||
453 | if (ctx->mode == S5P_JPEG_ENCODE) { | 480 | if (ctx->mode == S5P_JPEG_ENCODE) { |
454 | strlcpy(cap->driver, S5P_JPEG_M2M_NAME " encoder", | 481 | strlcpy(cap->driver, S5P_JPEG_M2M_NAME " encoder", |
@@ -497,9 +524,7 @@ static int enum_fmt(struct s5p_jpeg_fmt *formats, int n, | |||
497 | static int s5p_jpeg_enum_fmt_vid_cap(struct file *file, void *priv, | 524 | static int s5p_jpeg_enum_fmt_vid_cap(struct file *file, void *priv, |
498 | struct v4l2_fmtdesc *f) | 525 | struct v4l2_fmtdesc *f) |
499 | { | 526 | { |
500 | struct s5p_jpeg_ctx *ctx; | 527 | struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); |
501 | |||
502 | ctx = priv; | ||
503 | 528 | ||
504 | if (ctx->mode == S5P_JPEG_ENCODE) | 529 | if (ctx->mode == S5P_JPEG_ENCODE) |
505 | return enum_fmt(formats_enc, NUM_FORMATS_ENC, f, | 530 | return enum_fmt(formats_enc, NUM_FORMATS_ENC, f, |
@@ -511,9 +536,7 @@ static int s5p_jpeg_enum_fmt_vid_cap(struct file *file, void *priv, | |||
511 | static int s5p_jpeg_enum_fmt_vid_out(struct file *file, void *priv, | 536 | static int s5p_jpeg_enum_fmt_vid_out(struct file *file, void *priv, |
512 | struct v4l2_fmtdesc *f) | 537 | struct v4l2_fmtdesc *f) |
513 | { | 538 | { |
514 | struct s5p_jpeg_ctx *ctx; | 539 | struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); |
515 | |||
516 | ctx = priv; | ||
517 | 540 | ||
518 | if (ctx->mode == S5P_JPEG_ENCODE) | 541 | if (ctx->mode == S5P_JPEG_ENCODE) |
519 | return enum_fmt(formats_enc, NUM_FORMATS_ENC, f, | 542 | return enum_fmt(formats_enc, NUM_FORMATS_ENC, f, |
@@ -538,7 +561,7 @@ static int s5p_jpeg_g_fmt(struct file *file, void *priv, struct v4l2_format *f) | |||
538 | struct vb2_queue *vq; | 561 | struct vb2_queue *vq; |
539 | struct s5p_jpeg_q_data *q_data = NULL; | 562 | struct s5p_jpeg_q_data *q_data = NULL; |
540 | struct v4l2_pix_format *pix = &f->fmt.pix; | 563 | struct v4l2_pix_format *pix = &f->fmt.pix; |
541 | struct s5p_jpeg_ctx *ct = priv; | 564 | struct s5p_jpeg_ctx *ct = fh_to_ctx(priv); |
542 | 565 | ||
543 | vq = v4l2_m2m_get_vq(ct->m2m_ctx, f->type); | 566 | vq = v4l2_m2m_get_vq(ct->m2m_ctx, f->type); |
544 | if (!vq) | 567 | if (!vq) |
@@ -659,8 +682,8 @@ static int vidioc_try_fmt(struct v4l2_format *f, struct s5p_jpeg_fmt *fmt, | |||
659 | static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv, | 682 | static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv, |
660 | struct v4l2_format *f) | 683 | struct v4l2_format *f) |
661 | { | 684 | { |
685 | struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); | ||
662 | struct s5p_jpeg_fmt *fmt; | 686 | struct s5p_jpeg_fmt *fmt; |
663 | struct s5p_jpeg_ctx *ctx = priv; | ||
664 | 687 | ||
665 | fmt = s5p_jpeg_find_format(ctx->mode, f->fmt.pix.pixelformat); | 688 | fmt = s5p_jpeg_find_format(ctx->mode, f->fmt.pix.pixelformat); |
666 | if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) { | 689 | if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) { |
@@ -676,8 +699,8 @@ static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv, | |||
676 | static int s5p_jpeg_try_fmt_vid_out(struct file *file, void *priv, | 699 | static int s5p_jpeg_try_fmt_vid_out(struct file *file, void *priv, |
677 | struct v4l2_format *f) | 700 | struct v4l2_format *f) |
678 | { | 701 | { |
702 | struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); | ||
679 | struct s5p_jpeg_fmt *fmt; | 703 | struct s5p_jpeg_fmt *fmt; |
680 | struct s5p_jpeg_ctx *ctx = priv; | ||
681 | 704 | ||
682 | fmt = s5p_jpeg_find_format(ctx->mode, f->fmt.pix.pixelformat); | 705 | fmt = s5p_jpeg_find_format(ctx->mode, f->fmt.pix.pixelformat); |
683 | if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) { | 706 | if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) { |
@@ -728,7 +751,7 @@ static int s5p_jpeg_s_fmt_vid_cap(struct file *file, void *priv, | |||
728 | if (ret) | 751 | if (ret) |
729 | return ret; | 752 | return ret; |
730 | 753 | ||
731 | return s5p_jpeg_s_fmt(priv, f); | 754 | return s5p_jpeg_s_fmt(fh_to_ctx(priv), f); |
732 | } | 755 | } |
733 | 756 | ||
734 | static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv, | 757 | static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv, |
@@ -740,13 +763,13 @@ static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv, | |||
740 | if (ret) | 763 | if (ret) |
741 | return ret; | 764 | return ret; |
742 | 765 | ||
743 | return s5p_jpeg_s_fmt(priv, f); | 766 | return s5p_jpeg_s_fmt(fh_to_ctx(priv), f); |
744 | } | 767 | } |
745 | 768 | ||
746 | static int s5p_jpeg_reqbufs(struct file *file, void *priv, | 769 | static int s5p_jpeg_reqbufs(struct file *file, void *priv, |
747 | struct v4l2_requestbuffers *reqbufs) | 770 | struct v4l2_requestbuffers *reqbufs) |
748 | { | 771 | { |
749 | struct s5p_jpeg_ctx *ctx = priv; | 772 | struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); |
750 | 773 | ||
751 | return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); | 774 | return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); |
752 | } | 775 | } |
@@ -754,14 +777,14 @@ static int s5p_jpeg_reqbufs(struct file *file, void *priv, | |||
754 | static int s5p_jpeg_querybuf(struct file *file, void *priv, | 777 | static int s5p_jpeg_querybuf(struct file *file, void *priv, |
755 | struct v4l2_buffer *buf) | 778 | struct v4l2_buffer *buf) |
756 | { | 779 | { |
757 | struct s5p_jpeg_ctx *ctx = priv; | 780 | struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); |
758 | 781 | ||
759 | return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); | 782 | return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); |
760 | } | 783 | } |
761 | 784 | ||
762 | static int s5p_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | 785 | static int s5p_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) |
763 | { | 786 | { |
764 | struct s5p_jpeg_ctx *ctx = priv; | 787 | struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); |
765 | 788 | ||
766 | return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); | 789 | return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); |
767 | } | 790 | } |
@@ -769,7 +792,7 @@ static int s5p_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | |||
769 | static int s5p_jpeg_dqbuf(struct file *file, void *priv, | 792 | static int s5p_jpeg_dqbuf(struct file *file, void *priv, |
770 | struct v4l2_buffer *buf) | 793 | struct v4l2_buffer *buf) |
771 | { | 794 | { |
772 | struct s5p_jpeg_ctx *ctx = priv; | 795 | struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); |
773 | 796 | ||
774 | return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); | 797 | return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); |
775 | } | 798 | } |
@@ -777,7 +800,7 @@ static int s5p_jpeg_dqbuf(struct file *file, void *priv, | |||
777 | static int s5p_jpeg_streamon(struct file *file, void *priv, | 800 | static int s5p_jpeg_streamon(struct file *file, void *priv, |
778 | enum v4l2_buf_type type) | 801 | enum v4l2_buf_type type) |
779 | { | 802 | { |
780 | struct s5p_jpeg_ctx *ctx = priv; | 803 | struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); |
781 | 804 | ||
782 | return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); | 805 | return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); |
783 | } | 806 | } |
@@ -785,7 +808,7 @@ static int s5p_jpeg_streamon(struct file *file, void *priv, | |||
785 | static int s5p_jpeg_streamoff(struct file *file, void *priv, | 808 | static int s5p_jpeg_streamoff(struct file *file, void *priv, |
786 | enum v4l2_buf_type type) | 809 | enum v4l2_buf_type type) |
787 | { | 810 | { |
788 | struct s5p_jpeg_ctx *ctx = priv; | 811 | struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); |
789 | 812 | ||
790 | return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); | 813 | return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); |
791 | } | 814 | } |
@@ -793,7 +816,7 @@ static int s5p_jpeg_streamoff(struct file *file, void *priv, | |||
793 | int s5p_jpeg_g_selection(struct file *file, void *priv, | 816 | int s5p_jpeg_g_selection(struct file *file, void *priv, |
794 | struct v4l2_selection *s) | 817 | struct v4l2_selection *s) |
795 | { | 818 | { |
796 | struct s5p_jpeg_ctx *ctx = priv; | 819 | struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); |
797 | 820 | ||
798 | if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && | 821 | if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && |
799 | s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 822 | s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
@@ -822,33 +845,89 @@ int s5p_jpeg_g_selection(struct file *file, void *priv, | |||
822 | return 0; | 845 | return 0; |
823 | } | 846 | } |
824 | 847 | ||
825 | static int s5p_jpeg_g_jpegcomp(struct file *file, void *priv, | 848 | /* |
826 | struct v4l2_jpegcompression *compr) | 849 | * V4L2 controls |
850 | */ | ||
851 | |||
852 | static int s5p_jpeg_g_volatile_ctrl(struct v4l2_ctrl *ctrl) | ||
827 | { | 853 | { |
828 | struct s5p_jpeg_ctx *ctx = priv; | 854 | struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl); |
855 | struct s5p_jpeg *jpeg = ctx->jpeg; | ||
856 | unsigned long flags; | ||
829 | 857 | ||
830 | if (ctx->mode == S5P_JPEG_DECODE) | 858 | switch (ctrl->id) { |
831 | return -ENOTTY; | 859 | case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: |
860 | spin_lock_irqsave(&jpeg->slock, flags); | ||
832 | 861 | ||
833 | memset(compr, 0, sizeof(*compr)); | 862 | WARN_ON(ctx->subsampling > S5P_SUBSAMPLING_MODE_GRAY); |
834 | compr->quality = ctx->compr_quality; | 863 | if (ctx->subsampling > 2) |
864 | ctrl->val = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; | ||
865 | else | ||
866 | ctrl->val = ctx->subsampling; | ||
867 | spin_unlock_irqrestore(&jpeg->slock, flags); | ||
868 | break; | ||
869 | } | ||
835 | 870 | ||
836 | return 0; | 871 | return 0; |
837 | } | 872 | } |
838 | 873 | ||
839 | static int s5p_jpeg_s_jpegcomp(struct file *file, void *priv, | 874 | static int s5p_jpeg_s_ctrl(struct v4l2_ctrl *ctrl) |
840 | struct v4l2_jpegcompression *compr) | ||
841 | { | 875 | { |
842 | struct s5p_jpeg_ctx *ctx = priv; | 876 | struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl); |
877 | unsigned long flags; | ||
843 | 878 | ||
844 | if (ctx->mode == S5P_JPEG_DECODE) | 879 | spin_lock_irqsave(&ctx->jpeg->slock, flags); |
845 | return -ENOTTY; | ||
846 | 880 | ||
847 | compr->quality = clamp(compr->quality, S5P_JPEG_COMPR_QUAL_BEST, | 881 | switch (ctrl->id) { |
848 | S5P_JPEG_COMPR_QUAL_WORST); | 882 | case V4L2_CID_JPEG_COMPRESSION_QUALITY: |
883 | ctx->compr_quality = S5P_JPEG_COMPR_QUAL_WORST - ctrl->val; | ||
884 | break; | ||
885 | case V4L2_CID_JPEG_RESTART_INTERVAL: | ||
886 | ctx->restart_interval = ctrl->val; | ||
887 | break; | ||
888 | case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: | ||
889 | ctx->subsampling = ctrl->val; | ||
890 | break; | ||
891 | } | ||
849 | 892 | ||
850 | ctx->compr_quality = S5P_JPEG_COMPR_QUAL_WORST - compr->quality; | 893 | spin_unlock_irqrestore(&ctx->jpeg->slock, flags); |
894 | return 0; | ||
895 | } | ||
896 | |||
897 | static const struct v4l2_ctrl_ops s5p_jpeg_ctrl_ops = { | ||
898 | .g_volatile_ctrl = s5p_jpeg_g_volatile_ctrl, | ||
899 | .s_ctrl = s5p_jpeg_s_ctrl, | ||
900 | }; | ||
851 | 901 | ||
902 | static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx) | ||
903 | { | ||
904 | unsigned int mask = ~0x27; /* 444, 422, 420, GRAY */ | ||
905 | struct v4l2_ctrl *ctrl; | ||
906 | |||
907 | v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3); | ||
908 | |||
909 | if (ctx->mode == S5P_JPEG_ENCODE) { | ||
910 | v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops, | ||
911 | V4L2_CID_JPEG_COMPRESSION_QUALITY, | ||
912 | 0, 3, 1, 3); | ||
913 | |||
914 | v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops, | ||
915 | V4L2_CID_JPEG_RESTART_INTERVAL, | ||
916 | 0, 3, 0xffff, 0); | ||
917 | mask = ~0x06; /* 422, 420 */ | ||
918 | } | ||
919 | |||
920 | ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops, | ||
921 | V4L2_CID_JPEG_CHROMA_SUBSAMPLING, | ||
922 | V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY, mask, | ||
923 | V4L2_JPEG_CHROMA_SUBSAMPLING_422); | ||
924 | |||
925 | if (ctx->ctrl_handler.error) | ||
926 | return ctx->ctrl_handler.error; | ||
927 | |||
928 | if (ctx->mode == S5P_JPEG_DECODE) | ||
929 | ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE | | ||
930 | V4L2_CTRL_FLAG_READ_ONLY; | ||
852 | return 0; | 931 | return 0; |
853 | } | 932 | } |
854 | 933 | ||
@@ -877,9 +956,6 @@ static const struct v4l2_ioctl_ops s5p_jpeg_ioctl_ops = { | |||
877 | .vidioc_streamoff = s5p_jpeg_streamoff, | 956 | .vidioc_streamoff = s5p_jpeg_streamoff, |
878 | 957 | ||
879 | .vidioc_g_selection = s5p_jpeg_g_selection, | 958 | .vidioc_g_selection = s5p_jpeg_g_selection, |
880 | |||
881 | .vidioc_g_jpegcomp = s5p_jpeg_g_jpegcomp, | ||
882 | .vidioc_s_jpegcomp = s5p_jpeg_s_jpegcomp, | ||
883 | }; | 959 | }; |
884 | 960 | ||
885 | /* | 961 | /* |
@@ -908,13 +984,8 @@ static void s5p_jpeg_device_run(void *priv) | |||
908 | jpeg_input_raw_mode(jpeg->regs, S5P_JPEG_RAW_IN_565); | 984 | jpeg_input_raw_mode(jpeg->regs, S5P_JPEG_RAW_IN_565); |
909 | else | 985 | else |
910 | jpeg_input_raw_mode(jpeg->regs, S5P_JPEG_RAW_IN_422); | 986 | jpeg_input_raw_mode(jpeg->regs, S5P_JPEG_RAW_IN_422); |
911 | if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV) | 987 | jpeg_subsampling_mode(jpeg->regs, ctx->subsampling); |
912 | jpeg_subsampling_mode(jpeg->regs, | 988 | jpeg_dri(jpeg->regs, ctx->restart_interval); |
913 | S5P_JPEG_SUBSAMPLING_422); | ||
914 | else | ||
915 | jpeg_subsampling_mode(jpeg->regs, | ||
916 | S5P_JPEG_SUBSAMPLING_420); | ||
917 | jpeg_dri(jpeg->regs, 0); | ||
918 | jpeg_x(jpeg->regs, ctx->out_q.w); | 989 | jpeg_x(jpeg->regs, ctx->out_q.w); |
919 | jpeg_y(jpeg->regs, ctx->out_q.h); | 990 | jpeg_y(jpeg->regs, ctx->out_q.h); |
920 | jpeg_imgadr(jpeg->regs, src_addr); | 991 | jpeg_imgadr(jpeg->regs, src_addr); |
@@ -953,14 +1024,18 @@ static void s5p_jpeg_device_run(void *priv) | |||
953 | jpeg_htbl_dc(jpeg->regs, 2); | 1024 | jpeg_htbl_dc(jpeg->regs, 2); |
954 | jpeg_htbl_ac(jpeg->regs, 3); | 1025 | jpeg_htbl_ac(jpeg->regs, 3); |
955 | jpeg_htbl_dc(jpeg->regs, 3); | 1026 | jpeg_htbl_dc(jpeg->regs, 3); |
956 | } else { | 1027 | } else { /* S5P_JPEG_DECODE */ |
957 | jpeg_rst_int_enable(jpeg->regs, true); | 1028 | jpeg_rst_int_enable(jpeg->regs, true); |
958 | jpeg_data_num_int_enable(jpeg->regs, true); | 1029 | jpeg_data_num_int_enable(jpeg->regs, true); |
959 | jpeg_final_mcu_num_int_enable(jpeg->regs, true); | 1030 | jpeg_final_mcu_num_int_enable(jpeg->regs, true); |
960 | jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_422); | 1031 | if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV) |
1032 | jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_422); | ||
1033 | else | ||
1034 | jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_420); | ||
961 | jpeg_jpgadr(jpeg->regs, src_addr); | 1035 | jpeg_jpgadr(jpeg->regs, src_addr); |
962 | jpeg_imgadr(jpeg->regs, dst_addr); | 1036 | jpeg_imgadr(jpeg->regs, dst_addr); |
963 | } | 1037 | } |
1038 | |||
964 | jpeg_start(jpeg->regs); | 1039 | jpeg_start(jpeg->regs); |
965 | } | 1040 | } |
966 | 1041 | ||
@@ -1162,6 +1237,8 @@ static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id) | |||
1162 | bool timer_elapsed = false; | 1237 | bool timer_elapsed = false; |
1163 | bool op_completed = false; | 1238 | bool op_completed = false; |
1164 | 1239 | ||
1240 | spin_lock(&jpeg->slock); | ||
1241 | |||
1165 | curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev); | 1242 | curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev); |
1166 | 1243 | ||
1167 | src_buf = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx); | 1244 | src_buf = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx); |
@@ -1192,6 +1269,9 @@ static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id) | |||
1192 | v4l2_m2m_buf_done(dst_buf, state); | 1269 | v4l2_m2m_buf_done(dst_buf, state); |
1193 | v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->m2m_ctx); | 1270 | v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->m2m_ctx); |
1194 | 1271 | ||
1272 | curr_ctx->subsampling = jpeg_get_subsampling_mode(jpeg->regs); | ||
1273 | spin_unlock(&jpeg->slock); | ||
1274 | |||
1195 | jpeg_clear_int(jpeg->regs); | 1275 | jpeg_clear_int(jpeg->regs); |
1196 | 1276 | ||
1197 | return IRQ_HANDLED; | 1277 | return IRQ_HANDLED; |
@@ -1215,6 +1295,7 @@ static int s5p_jpeg_probe(struct platform_device *pdev) | |||
1215 | return -ENOMEM; | 1295 | return -ENOMEM; |
1216 | 1296 | ||
1217 | mutex_init(&jpeg->lock); | 1297 | mutex_init(&jpeg->lock); |
1298 | spin_lock_init(&jpeg->slock); | ||
1218 | jpeg->dev = &pdev->dev; | 1299 | jpeg->dev = &pdev->dev; |
1219 | 1300 | ||
1220 | /* memory-mapped registers */ | 1301 | /* memory-mapped registers */ |
diff --git a/drivers/media/video/s5p-jpeg/jpeg-core.h b/drivers/media/video/s5p-jpeg/jpeg-core.h index facad6114f5e..38d7367f7a6d 100644 --- a/drivers/media/video/s5p-jpeg/jpeg-core.h +++ b/drivers/media/video/s5p-jpeg/jpeg-core.h | |||
@@ -14,6 +14,8 @@ | |||
14 | #define JPEG_CORE_H_ | 14 | #define JPEG_CORE_H_ |
15 | 15 | ||
16 | #include <media/v4l2-device.h> | 16 | #include <media/v4l2-device.h> |
17 | #include <media/v4l2-fh.h> | ||
18 | #include <media/v4l2-ctrls.h> | ||
17 | 19 | ||
18 | #define S5P_JPEG_M2M_NAME "s5p-jpeg" | 20 | #define S5P_JPEG_M2M_NAME "s5p-jpeg" |
19 | 21 | ||
@@ -47,6 +49,7 @@ | |||
47 | /** | 49 | /** |
48 | * struct s5p_jpeg - JPEG IP abstraction | 50 | * struct s5p_jpeg - JPEG IP abstraction |
49 | * @lock: the mutex protecting this structure | 51 | * @lock: the mutex protecting this structure |
52 | * @slock: spinlock protecting the device contexts | ||
50 | * @v4l2_dev: v4l2 device for mem2mem mode | 53 | * @v4l2_dev: v4l2 device for mem2mem mode |
51 | * @vfd_encoder: video device node for encoder mem2mem mode | 54 | * @vfd_encoder: video device node for encoder mem2mem mode |
52 | * @vfd_decoder: video device node for decoder mem2mem mode | 55 | * @vfd_decoder: video device node for decoder mem2mem mode |
@@ -60,6 +63,7 @@ | |||
60 | */ | 63 | */ |
61 | struct s5p_jpeg { | 64 | struct s5p_jpeg { |
62 | struct mutex lock; | 65 | struct mutex lock; |
66 | struct spinlock slock; | ||
63 | 67 | ||
64 | struct v4l2_device v4l2_dev; | 68 | struct v4l2_device v4l2_dev; |
65 | struct video_device *vfd_encoder; | 69 | struct video_device *vfd_encoder; |
@@ -117,15 +121,20 @@ struct s5p_jpeg_q_data { | |||
117 | * @out_q: source (output) queue information | 121 | * @out_q: source (output) queue information |
118 | * @cap_fmt: destination (capture) queue queue information | 122 | * @cap_fmt: destination (capture) queue queue information |
119 | * @hdr_parsed: set if header has been parsed during decompression | 123 | * @hdr_parsed: set if header has been parsed during decompression |
124 | * @ctrl_handler: controls handler | ||
120 | */ | 125 | */ |
121 | struct s5p_jpeg_ctx { | 126 | struct s5p_jpeg_ctx { |
122 | struct s5p_jpeg *jpeg; | 127 | struct s5p_jpeg *jpeg; |
123 | unsigned int mode; | 128 | unsigned int mode; |
124 | unsigned int compr_quality; | 129 | unsigned short compr_quality; |
130 | unsigned short restart_interval; | ||
131 | unsigned short subsampling; | ||
125 | struct v4l2_m2m_ctx *m2m_ctx; | 132 | struct v4l2_m2m_ctx *m2m_ctx; |
126 | struct s5p_jpeg_q_data out_q; | 133 | struct s5p_jpeg_q_data out_q; |
127 | struct s5p_jpeg_q_data cap_q; | 134 | struct s5p_jpeg_q_data cap_q; |
135 | struct v4l2_fh fh; | ||
128 | bool hdr_parsed; | 136 | bool hdr_parsed; |
137 | struct v4l2_ctrl_handler ctrl_handler; | ||
129 | }; | 138 | }; |
130 | 139 | ||
131 | /** | 140 | /** |
diff --git a/drivers/media/video/s5p-jpeg/jpeg-hw.h b/drivers/media/video/s5p-jpeg/jpeg-hw.h index e10c744e9f23..f12f0fdbde7c 100644 --- a/drivers/media/video/s5p-jpeg/jpeg-hw.h +++ b/drivers/media/video/s5p-jpeg/jpeg-hw.h | |||
@@ -13,6 +13,7 @@ | |||
13 | #define JPEG_HW_H_ | 13 | #define JPEG_HW_H_ |
14 | 14 | ||
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <linux/videodev2.h> | ||
16 | 17 | ||
17 | #include "jpeg-hw.h" | 18 | #include "jpeg-hw.h" |
18 | #include "jpeg-regs.h" | 19 | #include "jpeg-regs.h" |
@@ -25,8 +26,6 @@ | |||
25 | #define S5P_JPEG_DECODE 1 | 26 | #define S5P_JPEG_DECODE 1 |
26 | #define S5P_JPEG_RAW_IN_565 0 | 27 | #define S5P_JPEG_RAW_IN_565 0 |
27 | #define S5P_JPEG_RAW_IN_422 1 | 28 | #define S5P_JPEG_RAW_IN_422 1 |
28 | #define S5P_JPEG_SUBSAMPLING_422 0 | ||
29 | #define S5P_JPEG_SUBSAMPLING_420 1 | ||
30 | #define S5P_JPEG_RAW_OUT_422 0 | 29 | #define S5P_JPEG_RAW_OUT_422 0 |
31 | #define S5P_JPEG_RAW_OUT_420 1 | 30 | #define S5P_JPEG_RAW_OUT_420 1 |
32 | 31 | ||
@@ -91,21 +90,26 @@ static inline void jpeg_proc_mode(void __iomem *regs, unsigned long mode) | |||
91 | writel(reg, regs + S5P_JPGMOD); | 90 | writel(reg, regs + S5P_JPGMOD); |
92 | } | 91 | } |
93 | 92 | ||
94 | static inline void jpeg_subsampling_mode(void __iomem *regs, unsigned long mode) | 93 | static inline void jpeg_subsampling_mode(void __iomem *regs, unsigned int mode) |
95 | { | 94 | { |
96 | unsigned long reg, m; | 95 | unsigned long reg, m; |
97 | 96 | ||
98 | m = S5P_SUBSAMPLING_MODE_422; | 97 | if (mode == V4L2_JPEG_CHROMA_SUBSAMPLING_420) |
99 | if (mode == S5P_JPEG_SUBSAMPLING_422) | ||
100 | m = S5P_SUBSAMPLING_MODE_422; | ||
101 | else if (mode == S5P_JPEG_SUBSAMPLING_420) | ||
102 | m = S5P_SUBSAMPLING_MODE_420; | 98 | m = S5P_SUBSAMPLING_MODE_420; |
99 | else | ||
100 | m = S5P_SUBSAMPLING_MODE_422; | ||
101 | |||
103 | reg = readl(regs + S5P_JPGMOD); | 102 | reg = readl(regs + S5P_JPGMOD); |
104 | reg &= ~S5P_SUBSAMPLING_MODE_MASK; | 103 | reg &= ~S5P_SUBSAMPLING_MODE_MASK; |
105 | reg |= m; | 104 | reg |= m; |
106 | writel(reg, regs + S5P_JPGMOD); | 105 | writel(reg, regs + S5P_JPGMOD); |
107 | } | 106 | } |
108 | 107 | ||
108 | static inline unsigned int jpeg_get_subsampling_mode(void __iomem *regs) | ||
109 | { | ||
110 | return readl(regs + S5P_JPGMOD) & S5P_SUBSAMPLING_MODE_MASK; | ||
111 | } | ||
112 | |||
109 | static inline void jpeg_dri(void __iomem *regs, unsigned int dri) | 113 | static inline void jpeg_dri(void __iomem *regs, unsigned int dri) |
110 | { | 114 | { |
111 | unsigned long reg; | 115 | unsigned long reg; |
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_pm.c b/drivers/media/video/s5p-mfc/s5p_mfc_pm.c index f6a3035c4fb7..738a607be43c 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc_pm.c +++ b/drivers/media/video/s5p-mfc/s5p_mfc_pm.c | |||
@@ -41,15 +41,29 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *dev) | |||
41 | pm->clock_gate = clk_get(&dev->plat_dev->dev, MFC_GATE_CLK_NAME); | 41 | pm->clock_gate = clk_get(&dev->plat_dev->dev, MFC_GATE_CLK_NAME); |
42 | if (IS_ERR(pm->clock_gate)) { | 42 | if (IS_ERR(pm->clock_gate)) { |
43 | mfc_err("Failed to get clock-gating control\n"); | 43 | mfc_err("Failed to get clock-gating control\n"); |
44 | ret = -ENOENT; | 44 | ret = PTR_ERR(pm->clock_gate); |
45 | goto err_g_ip_clk; | 45 | goto err_g_ip_clk; |
46 | } | 46 | } |
47 | |||
48 | ret = clk_prepare(pm->clock_gate); | ||
49 | if (ret) { | ||
50 | mfc_err("Failed to preapre clock-gating control\n"); | ||
51 | goto err_p_ip_clk; | ||
52 | } | ||
53 | |||
47 | pm->clock = clk_get(&dev->plat_dev->dev, MFC_CLKNAME); | 54 | pm->clock = clk_get(&dev->plat_dev->dev, MFC_CLKNAME); |
48 | if (IS_ERR(pm->clock)) { | 55 | if (IS_ERR(pm->clock)) { |
49 | mfc_err("Failed to get MFC clock\n"); | 56 | mfc_err("Failed to get MFC clock\n"); |
50 | ret = -ENOENT; | 57 | ret = PTR_ERR(pm->clock); |
51 | goto err_g_ip_clk_2; | 58 | goto err_g_ip_clk_2; |
52 | } | 59 | } |
60 | |||
61 | ret = clk_prepare(pm->clock); | ||
62 | if (ret) { | ||
63 | mfc_err("Failed to prepare MFC clock\n"); | ||
64 | goto err_p_ip_clk_2; | ||
65 | } | ||
66 | |||
53 | atomic_set(&pm->power, 0); | 67 | atomic_set(&pm->power, 0); |
54 | #ifdef CONFIG_PM_RUNTIME | 68 | #ifdef CONFIG_PM_RUNTIME |
55 | pm->device = &dev->plat_dev->dev; | 69 | pm->device = &dev->plat_dev->dev; |
@@ -59,7 +73,11 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *dev) | |||
59 | atomic_set(&clk_ref, 0); | 73 | atomic_set(&clk_ref, 0); |
60 | #endif | 74 | #endif |
61 | return 0; | 75 | return 0; |
76 | err_p_ip_clk_2: | ||
77 | clk_put(pm->clock); | ||
62 | err_g_ip_clk_2: | 78 | err_g_ip_clk_2: |
79 | clk_unprepare(pm->clock_gate); | ||
80 | err_p_ip_clk: | ||
63 | clk_put(pm->clock_gate); | 81 | clk_put(pm->clock_gate); |
64 | err_g_ip_clk: | 82 | err_g_ip_clk: |
65 | return ret; | 83 | return ret; |
@@ -67,7 +85,9 @@ err_g_ip_clk: | |||
67 | 85 | ||
68 | void s5p_mfc_final_pm(struct s5p_mfc_dev *dev) | 86 | void s5p_mfc_final_pm(struct s5p_mfc_dev *dev) |
69 | { | 87 | { |
88 | clk_unprepare(pm->clock_gate); | ||
70 | clk_put(pm->clock_gate); | 89 | clk_put(pm->clock_gate); |
90 | clk_unprepare(pm->clock); | ||
71 | clk_put(pm->clock); | 91 | clk_put(pm->clock); |
72 | #ifdef CONFIG_PM_RUNTIME | 92 | #ifdef CONFIG_PM_RUNTIME |
73 | pm_runtime_disable(pm->device); | 93 | pm_runtime_disable(pm->device); |
diff --git a/drivers/media/video/s5p-tv/Kconfig b/drivers/media/video/s5p-tv/Kconfig index f2a09779ec8f..f248b2856720 100644 --- a/drivers/media/video/s5p-tv/Kconfig +++ b/drivers/media/video/s5p-tv/Kconfig | |||
@@ -46,6 +46,16 @@ config VIDEO_SAMSUNG_S5P_HDMIPHY | |||
46 | as module. It is an I2C driver, that exposes a V4L2 | 46 | as module. It is an I2C driver, that exposes a V4L2 |
47 | subdev for use by other drivers. | 47 | subdev for use by other drivers. |
48 | 48 | ||
49 | config VIDEO_SAMSUNG_S5P_SII9234 | ||
50 | tristate "Samsung SII9234 Driver" | ||
51 | depends on VIDEO_DEV && VIDEO_V4L2 && I2C | ||
52 | depends on VIDEO_SAMSUNG_S5P_TV | ||
53 | help | ||
54 | Say Y here if you want support for the MHL interface | ||
55 | in S5P Samsung SoC. The driver can be compiled | ||
56 | as module. It is an I2C driver, that exposes a V4L2 | ||
57 | subdev for use by other drivers. | ||
58 | |||
49 | config VIDEO_SAMSUNG_S5P_SDO | 59 | config VIDEO_SAMSUNG_S5P_SDO |
50 | tristate "Samsung Analog TV Driver" | 60 | tristate "Samsung Analog TV Driver" |
51 | depends on VIDEO_DEV && VIDEO_V4L2 | 61 | depends on VIDEO_DEV && VIDEO_V4L2 |
diff --git a/drivers/media/video/s5p-tv/Makefile b/drivers/media/video/s5p-tv/Makefile index 37e4c17663b4..f49e756a2fde 100644 --- a/drivers/media/video/s5p-tv/Makefile +++ b/drivers/media/video/s5p-tv/Makefile | |||
@@ -8,6 +8,8 @@ | |||
8 | 8 | ||
9 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_HDMIPHY) += s5p-hdmiphy.o | 9 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_HDMIPHY) += s5p-hdmiphy.o |
10 | s5p-hdmiphy-y += hdmiphy_drv.o | 10 | s5p-hdmiphy-y += hdmiphy_drv.o |
11 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_SII9234) += s5p-sii9234.o | ||
12 | s5p-sii9234-y += sii9234_drv.o | ||
11 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_HDMI) += s5p-hdmi.o | 13 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_HDMI) += s5p-hdmi.o |
12 | s5p-hdmi-y += hdmi_drv.o | 14 | s5p-hdmi-y += hdmi_drv.o |
13 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_SDO) += s5p-sdo.o | 15 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_SDO) += s5p-sdo.o |
diff --git a/drivers/media/video/s5p-tv/hdmi_drv.c b/drivers/media/video/s5p-tv/hdmi_drv.c index 8b41a0410ab1..4865d25a0e57 100644 --- a/drivers/media/video/s5p-tv/hdmi_drv.c +++ b/drivers/media/video/s5p-tv/hdmi_drv.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
31 | #include <linux/regulator/consumer.h> | 31 | #include <linux/regulator/consumer.h> |
32 | 32 | ||
33 | #include <media/s5p_hdmi.h> | ||
33 | #include <media/v4l2-common.h> | 34 | #include <media/v4l2-common.h> |
34 | #include <media/v4l2-dev.h> | 35 | #include <media/v4l2-dev.h> |
35 | #include <media/v4l2-device.h> | 36 | #include <media/v4l2-device.h> |
@@ -66,6 +67,8 @@ struct hdmi_device { | |||
66 | struct v4l2_device v4l2_dev; | 67 | struct v4l2_device v4l2_dev; |
67 | /** subdev of HDMIPHY interface */ | 68 | /** subdev of HDMIPHY interface */ |
68 | struct v4l2_subdev *phy_sd; | 69 | struct v4l2_subdev *phy_sd; |
70 | /** subdev of MHL interface */ | ||
71 | struct v4l2_subdev *mhl_sd; | ||
69 | /** configuration of current graphic mode */ | 72 | /** configuration of current graphic mode */ |
70 | const struct hdmi_preset_conf *cur_conf; | 73 | const struct hdmi_preset_conf *cur_conf; |
71 | /** current preset */ | 74 | /** current preset */ |
@@ -74,10 +77,6 @@ struct hdmi_device { | |||
74 | struct hdmi_resources res; | 77 | struct hdmi_resources res; |
75 | }; | 78 | }; |
76 | 79 | ||
77 | struct hdmi_driver_data { | ||
78 | int hdmiphy_bus; | ||
79 | }; | ||
80 | |||
81 | struct hdmi_tg_regs { | 80 | struct hdmi_tg_regs { |
82 | u8 cmd; | 81 | u8 cmd; |
83 | u8 h_fsz_l; | 82 | u8 h_fsz_l; |
@@ -129,23 +128,11 @@ struct hdmi_preset_conf { | |||
129 | struct v4l2_mbus_framefmt mbus_fmt; | 128 | struct v4l2_mbus_framefmt mbus_fmt; |
130 | }; | 129 | }; |
131 | 130 | ||
132 | /* I2C module and id for HDMIPHY */ | ||
133 | static struct i2c_board_info hdmiphy_info = { | ||
134 | I2C_BOARD_INFO("hdmiphy", 0x38), | ||
135 | }; | ||
136 | |||
137 | static struct hdmi_driver_data hdmi_driver_data[] = { | ||
138 | { .hdmiphy_bus = 3 }, | ||
139 | { .hdmiphy_bus = 8 }, | ||
140 | }; | ||
141 | |||
142 | static struct platform_device_id hdmi_driver_types[] = { | 131 | static struct platform_device_id hdmi_driver_types[] = { |
143 | { | 132 | { |
144 | .name = "s5pv210-hdmi", | 133 | .name = "s5pv210-hdmi", |
145 | .driver_data = (unsigned long)&hdmi_driver_data[0], | ||
146 | }, { | 134 | }, { |
147 | .name = "exynos4-hdmi", | 135 | .name = "exynos4-hdmi", |
148 | .driver_data = (unsigned long)&hdmi_driver_data[1], | ||
149 | }, { | 136 | }, { |
150 | /* end node */ | 137 | /* end node */ |
151 | } | 138 | } |
@@ -587,7 +574,15 @@ static int hdmi_streamon(struct hdmi_device *hdev) | |||
587 | if (tries == 0) { | 574 | if (tries == 0) { |
588 | dev_err(dev, "hdmiphy's pll could not reach steady state.\n"); | 575 | dev_err(dev, "hdmiphy's pll could not reach steady state.\n"); |
589 | v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0); | 576 | v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0); |
590 | hdmi_dumpregs(hdev, "s_stream"); | 577 | hdmi_dumpregs(hdev, "hdmiphy - s_stream"); |
578 | return -EIO; | ||
579 | } | ||
580 | |||
581 | /* starting MHL */ | ||
582 | ret = v4l2_subdev_call(hdev->mhl_sd, video, s_stream, 1); | ||
583 | if (hdev->mhl_sd && ret) { | ||
584 | v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0); | ||
585 | hdmi_dumpregs(hdev, "mhl - s_stream"); | ||
591 | return -EIO; | 586 | return -EIO; |
592 | } | 587 | } |
593 | 588 | ||
@@ -618,6 +613,7 @@ static int hdmi_streamoff(struct hdmi_device *hdev) | |||
618 | clk_set_parent(res->sclk_hdmi, res->sclk_pixel); | 613 | clk_set_parent(res->sclk_hdmi, res->sclk_pixel); |
619 | clk_enable(res->sclk_hdmi); | 614 | clk_enable(res->sclk_hdmi); |
620 | 615 | ||
616 | v4l2_subdev_call(hdev->mhl_sd, video, s_stream, 0); | ||
621 | v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0); | 617 | v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0); |
622 | 618 | ||
623 | hdmi_dumpregs(hdev, "streamoff"); | 619 | hdmi_dumpregs(hdev, "streamoff"); |
@@ -739,6 +735,7 @@ static int hdmi_runtime_suspend(struct device *dev) | |||
739 | struct hdmi_device *hdev = sd_to_hdmi_dev(sd); | 735 | struct hdmi_device *hdev = sd_to_hdmi_dev(sd); |
740 | 736 | ||
741 | dev_dbg(dev, "%s\n", __func__); | 737 | dev_dbg(dev, "%s\n", __func__); |
738 | v4l2_subdev_call(hdev->mhl_sd, core, s_power, 0); | ||
742 | hdmi_resource_poweroff(&hdev->res); | 739 | hdmi_resource_poweroff(&hdev->res); |
743 | return 0; | 740 | return 0; |
744 | } | 741 | } |
@@ -757,6 +754,11 @@ static int hdmi_runtime_resume(struct device *dev) | |||
757 | if (ret) | 754 | if (ret) |
758 | goto fail; | 755 | goto fail; |
759 | 756 | ||
757 | /* starting MHL */ | ||
758 | ret = v4l2_subdev_call(hdev->mhl_sd, core, s_power, 1); | ||
759 | if (hdev->mhl_sd && ret) | ||
760 | goto fail; | ||
761 | |||
760 | dev_dbg(dev, "poweron succeed\n"); | 762 | dev_dbg(dev, "poweron succeed\n"); |
761 | 763 | ||
762 | return 0; | 764 | return 0; |
@@ -867,15 +869,21 @@ static int __devinit hdmi_probe(struct platform_device *pdev) | |||
867 | { | 869 | { |
868 | struct device *dev = &pdev->dev; | 870 | struct device *dev = &pdev->dev; |
869 | struct resource *res; | 871 | struct resource *res; |
870 | struct i2c_adapter *phy_adapter; | 872 | struct i2c_adapter *adapter; |
871 | struct v4l2_subdev *sd; | 873 | struct v4l2_subdev *sd; |
872 | struct hdmi_device *hdmi_dev = NULL; | 874 | struct hdmi_device *hdmi_dev = NULL; |
873 | struct hdmi_driver_data *drv_data; | 875 | struct s5p_hdmi_platform_data *pdata = dev->platform_data; |
874 | int ret; | 876 | int ret; |
875 | 877 | ||
876 | dev_dbg(dev, "probe start\n"); | 878 | dev_dbg(dev, "probe start\n"); |
877 | 879 | ||
878 | hdmi_dev = kzalloc(sizeof(*hdmi_dev), GFP_KERNEL); | 880 | if (!pdata) { |
881 | dev_err(dev, "platform data is missing\n"); | ||
882 | ret = -ENODEV; | ||
883 | goto fail; | ||
884 | } | ||
885 | |||
886 | hdmi_dev = devm_kzalloc(&pdev->dev, sizeof(*hdmi_dev), GFP_KERNEL); | ||
879 | if (!hdmi_dev) { | 887 | if (!hdmi_dev) { |
880 | dev_err(dev, "out of memory\n"); | 888 | dev_err(dev, "out of memory\n"); |
881 | ret = -ENOMEM; | 889 | ret = -ENOMEM; |
@@ -886,7 +894,7 @@ static int __devinit hdmi_probe(struct platform_device *pdev) | |||
886 | 894 | ||
887 | ret = hdmi_resources_init(hdmi_dev); | 895 | ret = hdmi_resources_init(hdmi_dev); |
888 | if (ret) | 896 | if (ret) |
889 | goto fail_hdev; | 897 | goto fail; |
890 | 898 | ||
891 | /* mapping HDMI registers */ | 899 | /* mapping HDMI registers */ |
892 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 900 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -896,24 +904,26 @@ static int __devinit hdmi_probe(struct platform_device *pdev) | |||
896 | goto fail_init; | 904 | goto fail_init; |
897 | } | 905 | } |
898 | 906 | ||
899 | hdmi_dev->regs = ioremap(res->start, resource_size(res)); | 907 | hdmi_dev->regs = devm_ioremap(&pdev->dev, res->start, |
908 | resource_size(res)); | ||
900 | if (hdmi_dev->regs == NULL) { | 909 | if (hdmi_dev->regs == NULL) { |
901 | dev_err(dev, "register mapping failed.\n"); | 910 | dev_err(dev, "register mapping failed.\n"); |
902 | ret = -ENXIO; | 911 | ret = -ENXIO; |
903 | goto fail_hdev; | 912 | goto fail_init; |
904 | } | 913 | } |
905 | 914 | ||
906 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 915 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
907 | if (res == NULL) { | 916 | if (res == NULL) { |
908 | dev_err(dev, "get interrupt resource failed.\n"); | 917 | dev_err(dev, "get interrupt resource failed.\n"); |
909 | ret = -ENXIO; | 918 | ret = -ENXIO; |
910 | goto fail_regs; | 919 | goto fail_init; |
911 | } | 920 | } |
912 | 921 | ||
913 | ret = request_irq(res->start, hdmi_irq_handler, 0, "hdmi", hdmi_dev); | 922 | ret = devm_request_irq(&pdev->dev, res->start, hdmi_irq_handler, 0, |
923 | "hdmi", hdmi_dev); | ||
914 | if (ret) { | 924 | if (ret) { |
915 | dev_err(dev, "request interrupt failed.\n"); | 925 | dev_err(dev, "request interrupt failed.\n"); |
916 | goto fail_regs; | 926 | goto fail_init; |
917 | } | 927 | } |
918 | hdmi_dev->irq = res->start; | 928 | hdmi_dev->irq = res->start; |
919 | 929 | ||
@@ -924,28 +934,54 @@ static int __devinit hdmi_probe(struct platform_device *pdev) | |||
924 | ret = v4l2_device_register(NULL, &hdmi_dev->v4l2_dev); | 934 | ret = v4l2_device_register(NULL, &hdmi_dev->v4l2_dev); |
925 | if (ret) { | 935 | if (ret) { |
926 | dev_err(dev, "could not register v4l2 device.\n"); | 936 | dev_err(dev, "could not register v4l2 device.\n"); |
927 | goto fail_irq; | 937 | goto fail_init; |
928 | } | 938 | } |
929 | 939 | ||
930 | drv_data = (struct hdmi_driver_data *) | 940 | /* testing if hdmiphy info is present */ |
931 | platform_get_device_id(pdev)->driver_data; | 941 | if (!pdata->hdmiphy_info) { |
932 | phy_adapter = i2c_get_adapter(drv_data->hdmiphy_bus); | 942 | dev_err(dev, "hdmiphy info is missing in platform data\n"); |
933 | if (phy_adapter == NULL) { | 943 | ret = -ENXIO; |
934 | dev_err(dev, "adapter request failed\n"); | 944 | goto fail_vdev; |
945 | } | ||
946 | |||
947 | adapter = i2c_get_adapter(pdata->hdmiphy_bus); | ||
948 | if (adapter == NULL) { | ||
949 | dev_err(dev, "hdmiphy adapter request failed\n"); | ||
935 | ret = -ENXIO; | 950 | ret = -ENXIO; |
936 | goto fail_vdev; | 951 | goto fail_vdev; |
937 | } | 952 | } |
938 | 953 | ||
939 | hdmi_dev->phy_sd = v4l2_i2c_new_subdev_board(&hdmi_dev->v4l2_dev, | 954 | hdmi_dev->phy_sd = v4l2_i2c_new_subdev_board(&hdmi_dev->v4l2_dev, |
940 | phy_adapter, &hdmiphy_info, NULL); | 955 | adapter, pdata->hdmiphy_info, NULL); |
941 | /* on failure or not adapter is no longer useful */ | 956 | /* on failure or not adapter is no longer useful */ |
942 | i2c_put_adapter(phy_adapter); | 957 | i2c_put_adapter(adapter); |
943 | if (hdmi_dev->phy_sd == NULL) { | 958 | if (hdmi_dev->phy_sd == NULL) { |
944 | dev_err(dev, "missing subdev for hdmiphy\n"); | 959 | dev_err(dev, "missing subdev for hdmiphy\n"); |
945 | ret = -ENODEV; | 960 | ret = -ENODEV; |
946 | goto fail_vdev; | 961 | goto fail_vdev; |
947 | } | 962 | } |
948 | 963 | ||
964 | /* initialization of MHL interface if present */ | ||
965 | if (pdata->mhl_info) { | ||
966 | adapter = i2c_get_adapter(pdata->mhl_bus); | ||
967 | if (adapter == NULL) { | ||
968 | dev_err(dev, "MHL adapter request failed\n"); | ||
969 | ret = -ENXIO; | ||
970 | goto fail_vdev; | ||
971 | } | ||
972 | |||
973 | hdmi_dev->mhl_sd = v4l2_i2c_new_subdev_board( | ||
974 | &hdmi_dev->v4l2_dev, adapter, | ||
975 | pdata->mhl_info, NULL); | ||
976 | /* on failure or not adapter is no longer useful */ | ||
977 | i2c_put_adapter(adapter); | ||
978 | if (hdmi_dev->mhl_sd == NULL) { | ||
979 | dev_err(dev, "missing subdev for MHL\n"); | ||
980 | ret = -ENODEV; | ||
981 | goto fail_vdev; | ||
982 | } | ||
983 | } | ||
984 | |||
949 | clk_enable(hdmi_dev->res.hdmi); | 985 | clk_enable(hdmi_dev->res.hdmi); |
950 | 986 | ||
951 | pm_runtime_enable(dev); | 987 | pm_runtime_enable(dev); |
@@ -962,25 +998,16 @@ static int __devinit hdmi_probe(struct platform_device *pdev) | |||
962 | /* storing subdev for call that have only access to struct device */ | 998 | /* storing subdev for call that have only access to struct device */ |
963 | dev_set_drvdata(dev, sd); | 999 | dev_set_drvdata(dev, sd); |
964 | 1000 | ||
965 | dev_info(dev, "probe sucessful\n"); | 1001 | dev_info(dev, "probe successful\n"); |
966 | 1002 | ||
967 | return 0; | 1003 | return 0; |
968 | 1004 | ||
969 | fail_vdev: | 1005 | fail_vdev: |
970 | v4l2_device_unregister(&hdmi_dev->v4l2_dev); | 1006 | v4l2_device_unregister(&hdmi_dev->v4l2_dev); |
971 | 1007 | ||
972 | fail_irq: | ||
973 | free_irq(hdmi_dev->irq, hdmi_dev); | ||
974 | |||
975 | fail_regs: | ||
976 | iounmap(hdmi_dev->regs); | ||
977 | |||
978 | fail_init: | 1008 | fail_init: |
979 | hdmi_resources_cleanup(hdmi_dev); | 1009 | hdmi_resources_cleanup(hdmi_dev); |
980 | 1010 | ||
981 | fail_hdev: | ||
982 | kfree(hdmi_dev); | ||
983 | |||
984 | fail: | 1011 | fail: |
985 | dev_err(dev, "probe failed\n"); | 1012 | dev_err(dev, "probe failed\n"); |
986 | return ret; | 1013 | return ret; |
@@ -996,11 +1023,8 @@ static int __devexit hdmi_remove(struct platform_device *pdev) | |||
996 | clk_disable(hdmi_dev->res.hdmi); | 1023 | clk_disable(hdmi_dev->res.hdmi); |
997 | v4l2_device_unregister(&hdmi_dev->v4l2_dev); | 1024 | v4l2_device_unregister(&hdmi_dev->v4l2_dev); |
998 | disable_irq(hdmi_dev->irq); | 1025 | disable_irq(hdmi_dev->irq); |
999 | free_irq(hdmi_dev->irq, hdmi_dev); | ||
1000 | iounmap(hdmi_dev->regs); | ||
1001 | hdmi_resources_cleanup(hdmi_dev); | 1026 | hdmi_resources_cleanup(hdmi_dev); |
1002 | kfree(hdmi_dev); | 1027 | dev_info(dev, "remove successful\n"); |
1003 | dev_info(dev, "remove sucessful\n"); | ||
1004 | 1028 | ||
1005 | return 0; | 1029 | return 0; |
1006 | } | 1030 | } |
diff --git a/drivers/media/video/s5p-tv/hdmiphy_drv.c b/drivers/media/video/s5p-tv/hdmiphy_drv.c index 6693f4aff108..0afef77747e5 100644 --- a/drivers/media/video/s5p-tv/hdmiphy_drv.c +++ b/drivers/media/video/s5p-tv/hdmiphy_drv.c | |||
@@ -175,14 +175,4 @@ static struct i2c_driver hdmiphy_driver = { | |||
175 | .id_table = hdmiphy_id, | 175 | .id_table = hdmiphy_id, |
176 | }; | 176 | }; |
177 | 177 | ||
178 | static int __init hdmiphy_init(void) | 178 | module_i2c_driver(hdmiphy_driver); |
179 | { | ||
180 | return i2c_add_driver(&hdmiphy_driver); | ||
181 | } | ||
182 | module_init(hdmiphy_init); | ||
183 | |||
184 | static void __exit hdmiphy_exit(void) | ||
185 | { | ||
186 | i2c_del_driver(&hdmiphy_driver); | ||
187 | } | ||
188 | module_exit(hdmiphy_exit); | ||
diff --git a/drivers/media/video/s5p-tv/mixer_drv.c b/drivers/media/video/s5p-tv/mixer_drv.c index 00643094b221..a2c0c25ad130 100644 --- a/drivers/media/video/s5p-tv/mixer_drv.c +++ b/drivers/media/video/s5p-tv/mixer_drv.c | |||
@@ -444,7 +444,7 @@ static int __devexit mxr_remove(struct platform_device *pdev) | |||
444 | 444 | ||
445 | kfree(mdev); | 445 | kfree(mdev); |
446 | 446 | ||
447 | dev_info(dev, "remove sucessful\n"); | 447 | dev_info(dev, "remove successful\n"); |
448 | return 0; | 448 | return 0; |
449 | } | 449 | } |
450 | 450 | ||
diff --git a/drivers/media/video/s5p-tv/mixer_video.c b/drivers/media/video/s5p-tv/mixer_video.c index 7884baeff76a..f7ca5cc143c6 100644 --- a/drivers/media/video/s5p-tv/mixer_video.c +++ b/drivers/media/video/s5p-tv/mixer_video.c | |||
@@ -58,7 +58,6 @@ static struct v4l2_subdev *find_and_register_subdev( | |||
58 | } | 58 | } |
59 | 59 | ||
60 | done: | 60 | done: |
61 | put_driver(drv); | ||
62 | return sd; | 61 | return sd; |
63 | } | 62 | } |
64 | 63 | ||
diff --git a/drivers/media/video/s5p-tv/sdo_drv.c b/drivers/media/video/s5p-tv/sdo_drv.c index 059e7749ce95..f6bca2c20e89 100644 --- a/drivers/media/video/s5p-tv/sdo_drv.c +++ b/drivers/media/video/s5p-tv/sdo_drv.c | |||
@@ -301,7 +301,7 @@ static int __devinit sdo_probe(struct platform_device *pdev) | |||
301 | struct clk *sclk_vpll; | 301 | struct clk *sclk_vpll; |
302 | 302 | ||
303 | dev_info(dev, "probe start\n"); | 303 | dev_info(dev, "probe start\n"); |
304 | sdev = kzalloc(sizeof *sdev, GFP_KERNEL); | 304 | sdev = devm_kzalloc(&pdev->dev, sizeof *sdev, GFP_KERNEL); |
305 | if (!sdev) { | 305 | if (!sdev) { |
306 | dev_err(dev, "not enough memory.\n"); | 306 | dev_err(dev, "not enough memory.\n"); |
307 | ret = -ENOMEM; | 307 | ret = -ENOMEM; |
@@ -314,14 +314,14 @@ static int __devinit sdo_probe(struct platform_device *pdev) | |||
314 | if (res == NULL) { | 314 | if (res == NULL) { |
315 | dev_err(dev, "get memory resource failed.\n"); | 315 | dev_err(dev, "get memory resource failed.\n"); |
316 | ret = -ENXIO; | 316 | ret = -ENXIO; |
317 | goto fail_sdev; | 317 | goto fail; |
318 | } | 318 | } |
319 | 319 | ||
320 | sdev->regs = ioremap(res->start, resource_size(res)); | 320 | sdev->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); |
321 | if (sdev->regs == NULL) { | 321 | if (sdev->regs == NULL) { |
322 | dev_err(dev, "register mapping failed.\n"); | 322 | dev_err(dev, "register mapping failed.\n"); |
323 | ret = -ENXIO; | 323 | ret = -ENXIO; |
324 | goto fail_sdev; | 324 | goto fail; |
325 | } | 325 | } |
326 | 326 | ||
327 | /* acquiring interrupt */ | 327 | /* acquiring interrupt */ |
@@ -329,12 +329,13 @@ static int __devinit sdo_probe(struct platform_device *pdev) | |||
329 | if (res == NULL) { | 329 | if (res == NULL) { |
330 | dev_err(dev, "get interrupt resource failed.\n"); | 330 | dev_err(dev, "get interrupt resource failed.\n"); |
331 | ret = -ENXIO; | 331 | ret = -ENXIO; |
332 | goto fail_regs; | 332 | goto fail; |
333 | } | 333 | } |
334 | ret = request_irq(res->start, sdo_irq_handler, 0, "s5p-sdo", sdev); | 334 | ret = devm_request_irq(&pdev->dev, res->start, sdo_irq_handler, 0, |
335 | "s5p-sdo", sdev); | ||
335 | if (ret) { | 336 | if (ret) { |
336 | dev_err(dev, "request interrupt failed.\n"); | 337 | dev_err(dev, "request interrupt failed.\n"); |
337 | goto fail_regs; | 338 | goto fail; |
338 | } | 339 | } |
339 | sdev->irq = res->start; | 340 | sdev->irq = res->start; |
340 | 341 | ||
@@ -343,7 +344,7 @@ static int __devinit sdo_probe(struct platform_device *pdev) | |||
343 | if (IS_ERR_OR_NULL(sdev->sclk_dac)) { | 344 | if (IS_ERR_OR_NULL(sdev->sclk_dac)) { |
344 | dev_err(dev, "failed to get clock 'sclk_dac'\n"); | 345 | dev_err(dev, "failed to get clock 'sclk_dac'\n"); |
345 | ret = -ENXIO; | 346 | ret = -ENXIO; |
346 | goto fail_irq; | 347 | goto fail; |
347 | } | 348 | } |
348 | sdev->dac = clk_get(dev, "dac"); | 349 | sdev->dac = clk_get(dev, "dac"); |
349 | if (IS_ERR_OR_NULL(sdev->dac)) { | 350 | if (IS_ERR_OR_NULL(sdev->dac)) { |
@@ -415,12 +416,6 @@ fail_dac: | |||
415 | clk_put(sdev->dac); | 416 | clk_put(sdev->dac); |
416 | fail_sclk_dac: | 417 | fail_sclk_dac: |
417 | clk_put(sdev->sclk_dac); | 418 | clk_put(sdev->sclk_dac); |
418 | fail_irq: | ||
419 | free_irq(sdev->irq, sdev); | ||
420 | fail_regs: | ||
421 | iounmap(sdev->regs); | ||
422 | fail_sdev: | ||
423 | kfree(sdev); | ||
424 | fail: | 419 | fail: |
425 | dev_info(dev, "probe failed\n"); | 420 | dev_info(dev, "probe failed\n"); |
426 | return ret; | 421 | return ret; |
@@ -439,9 +434,6 @@ static int __devexit sdo_remove(struct platform_device *pdev) | |||
439 | clk_put(sdev->dacphy); | 434 | clk_put(sdev->dacphy); |
440 | clk_put(sdev->dac); | 435 | clk_put(sdev->dac); |
441 | clk_put(sdev->sclk_dac); | 436 | clk_put(sdev->sclk_dac); |
442 | free_irq(sdev->irq, sdev); | ||
443 | iounmap(sdev->regs); | ||
444 | kfree(sdev); | ||
445 | 437 | ||
446 | dev_info(&pdev->dev, "remove successful\n"); | 438 | dev_info(&pdev->dev, "remove successful\n"); |
447 | return 0; | 439 | return 0; |
diff --git a/drivers/media/video/s5p-tv/sii9234_drv.c b/drivers/media/video/s5p-tv/sii9234_drv.c new file mode 100644 index 000000000000..0f31eccd7b80 --- /dev/null +++ b/drivers/media/video/s5p-tv/sii9234_drv.c | |||
@@ -0,0 +1,432 @@ | |||
1 | /* | ||
2 | * Samsung MHL interface driver | ||
3 | * | ||
4 | * Copyright (C) 2011 Samsung Electronics Co.Ltd | ||
5 | * Author: Tomasz Stanislawski <t.stanislaws@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/delay.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/freezer.h> | ||
16 | #include <linux/gpio.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/irq.h> | ||
20 | #include <linux/kthread.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/pm_runtime.h> | ||
23 | #include <linux/regulator/machine.h> | ||
24 | #include <linux/slab.h> | ||
25 | |||
26 | #include <mach/gpio.h> | ||
27 | #include <plat/gpio-cfg.h> | ||
28 | |||
29 | #include <media/sii9234.h> | ||
30 | #include <media/v4l2-subdev.h> | ||
31 | |||
32 | MODULE_AUTHOR("Tomasz Stanislawski <t.stanislaws@samsung.com>"); | ||
33 | MODULE_DESCRIPTION("Samsung MHL interface driver"); | ||
34 | MODULE_LICENSE("GPL"); | ||
35 | |||
36 | struct sii9234_context { | ||
37 | struct i2c_client *client; | ||
38 | struct regulator *power; | ||
39 | int gpio_n_reset; | ||
40 | struct v4l2_subdev sd; | ||
41 | }; | ||
42 | |||
43 | static inline struct sii9234_context *sd_to_context(struct v4l2_subdev *sd) | ||
44 | { | ||
45 | return container_of(sd, struct sii9234_context, sd); | ||
46 | } | ||
47 | |||
48 | static inline int sii9234_readb(struct i2c_client *client, int addr) | ||
49 | { | ||
50 | return i2c_smbus_read_byte_data(client, addr); | ||
51 | } | ||
52 | |||
53 | static inline int sii9234_writeb(struct i2c_client *client, int addr, int value) | ||
54 | { | ||
55 | return i2c_smbus_write_byte_data(client, addr, value); | ||
56 | } | ||
57 | |||
58 | static inline int sii9234_writeb_mask(struct i2c_client *client, int addr, | ||
59 | int value, int mask) | ||
60 | { | ||
61 | int ret; | ||
62 | |||
63 | ret = i2c_smbus_read_byte_data(client, addr); | ||
64 | if (ret < 0) | ||
65 | return ret; | ||
66 | ret = (ret & ~mask) | (value & mask); | ||
67 | return i2c_smbus_write_byte_data(client, addr, ret); | ||
68 | } | ||
69 | |||
70 | static inline int sii9234_readb_idx(struct i2c_client *client, int addr) | ||
71 | { | ||
72 | int ret; | ||
73 | ret = i2c_smbus_write_byte_data(client, 0xbc, addr >> 8); | ||
74 | if (ret < 0) | ||
75 | return ret; | ||
76 | ret = i2c_smbus_write_byte_data(client, 0xbd, addr & 0xff); | ||
77 | if (ret < 0) | ||
78 | return ret; | ||
79 | return i2c_smbus_read_byte_data(client, 0xbe); | ||
80 | } | ||
81 | |||
82 | static inline int sii9234_writeb_idx(struct i2c_client *client, int addr, | ||
83 | int value) | ||
84 | { | ||
85 | int ret; | ||
86 | ret = i2c_smbus_write_byte_data(client, 0xbc, addr >> 8); | ||
87 | if (ret < 0) | ||
88 | return ret; | ||
89 | ret = i2c_smbus_write_byte_data(client, 0xbd, addr & 0xff); | ||
90 | if (ret < 0) | ||
91 | return ret; | ||
92 | ret = i2c_smbus_write_byte_data(client, 0xbe, value); | ||
93 | return ret; | ||
94 | } | ||
95 | |||
96 | static inline int sii9234_writeb_idx_mask(struct i2c_client *client, int addr, | ||
97 | int value, int mask) | ||
98 | { | ||
99 | int ret; | ||
100 | |||
101 | ret = sii9234_readb_idx(client, addr); | ||
102 | if (ret < 0) | ||
103 | return ret; | ||
104 | ret = (ret & ~mask) | (value & mask); | ||
105 | return sii9234_writeb_idx(client, addr, ret); | ||
106 | } | ||
107 | |||
108 | static int sii9234_reset(struct sii9234_context *ctx) | ||
109 | { | ||
110 | struct i2c_client *client = ctx->client; | ||
111 | struct device *dev = &client->dev; | ||
112 | int ret, tries; | ||
113 | |||
114 | gpio_direction_output(ctx->gpio_n_reset, 1); | ||
115 | mdelay(1); | ||
116 | gpio_direction_output(ctx->gpio_n_reset, 0); | ||
117 | mdelay(1); | ||
118 | gpio_direction_output(ctx->gpio_n_reset, 1); | ||
119 | mdelay(1); | ||
120 | |||
121 | /* going to TTPI mode */ | ||
122 | ret = sii9234_writeb(client, 0xc7, 0); | ||
123 | if (ret < 0) { | ||
124 | dev_err(dev, "failed to set TTPI mode\n"); | ||
125 | return ret; | ||
126 | } | ||
127 | for (tries = 0; tries < 100 ; ++tries) { | ||
128 | ret = sii9234_readb(client, 0x1b); | ||
129 | if (ret > 0) | ||
130 | break; | ||
131 | if (ret < 0) { | ||
132 | dev_err(dev, "failed to reset device\n"); | ||
133 | return -EIO; | ||
134 | } | ||
135 | mdelay(1); | ||
136 | } | ||
137 | if (tries == 100) { | ||
138 | dev_err(dev, "maximal number of tries reached\n"); | ||
139 | return -EIO; | ||
140 | } | ||
141 | |||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | static int sii9234_verify_version(struct i2c_client *client) | ||
146 | { | ||
147 | struct device *dev = &client->dev; | ||
148 | int family, rev, tpi_rev, dev_id, sub_id, hdcp, id; | ||
149 | |||
150 | family = sii9234_readb(client, 0x1b); | ||
151 | rev = sii9234_readb(client, 0x1c) & 0x0f; | ||
152 | tpi_rev = sii9234_readb(client, 0x1d) & 0x7f; | ||
153 | dev_id = sii9234_readb_idx(client, 0x0103); | ||
154 | sub_id = sii9234_readb_idx(client, 0x0102); | ||
155 | hdcp = sii9234_readb(client, 0x30); | ||
156 | |||
157 | if (family < 0 || rev < 0 || tpi_rev < 0 || dev_id < 0 || | ||
158 | sub_id < 0 || hdcp < 0) { | ||
159 | dev_err(dev, "failed to read chip's version\n"); | ||
160 | return -EIO; | ||
161 | } | ||
162 | |||
163 | id = (dev_id << 8) | sub_id; | ||
164 | |||
165 | dev_info(dev, "chip: SiL%02x family: %02x, rev: %02x\n", | ||
166 | id, family, rev); | ||
167 | dev_info(dev, "tpi_rev:%02x, hdcp: %02x\n", tpi_rev, hdcp); | ||
168 | if (id != 0x9234) { | ||
169 | dev_err(dev, "not supported chip\n"); | ||
170 | return -ENODEV; | ||
171 | } | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static u8 data[][3] = { | ||
177 | /* setup from driver created by doonsoo45.kim */ | ||
178 | { 0x01, 0x05, 0x04 }, /* Enable Auto soft reset on SCDT = 0 */ | ||
179 | { 0x01, 0x08, 0x35 }, /* Power Up TMDS Tx Core */ | ||
180 | { 0x01, 0x0d, 0x1c }, /* HDMI Transcode mode enable */ | ||
181 | { 0x01, 0x2b, 0x01 }, /* Enable HDCP Compliance workaround */ | ||
182 | { 0x01, 0x79, 0x40 }, /* daniel test...MHL_INT */ | ||
183 | { 0x01, 0x80, 0x34 }, /* Enable Rx PLL Clock Value */ | ||
184 | { 0x01, 0x90, 0x27 }, /* Enable CBUS discovery */ | ||
185 | { 0x01, 0x91, 0xe5 }, /* Skip RGND detection */ | ||
186 | { 0x01, 0x92, 0x46 }, /* Force MHD mode */ | ||
187 | { 0x01, 0x93, 0xdc }, /* Disable CBUS pull-up during RGND measurement */ | ||
188 | { 0x01, 0x94, 0x66 }, /* 1.8V CBUS VTH & GND threshold */ | ||
189 | { 0x01, 0x95, 0x31 }, /* RGND block & single discovery attempt */ | ||
190 | { 0x01, 0x96, 0x22 }, /* use 1K and 2K setting */ | ||
191 | { 0x01, 0xa0, 0x10 }, /* SIMG: Term mode */ | ||
192 | { 0x01, 0xa1, 0xfc }, /* Disable internal Mobile HD driver */ | ||
193 | { 0x01, 0xa3, 0xfa }, /* SIMG: Output Swing default EB, 3x Clk Mult */ | ||
194 | { 0x01, 0xa5, 0x80 }, /* SIMG: RGND Hysterisis, 3x mode for Beast */ | ||
195 | { 0x01, 0xa6, 0x0c }, /* SIMG: Swing Offset */ | ||
196 | { 0x02, 0x3d, 0x3f }, /* Power up CVCC 1.2V core */ | ||
197 | { 0x03, 0x00, 0x00 }, /* SIMG: correcting HW default */ | ||
198 | { 0x03, 0x11, 0x01 }, /* Enable TxPLL Clock */ | ||
199 | { 0x03, 0x12, 0x15 }, /* Enable Tx Clock Path & Equalizer */ | ||
200 | { 0x03, 0x13, 0x60 }, /* SIMG: Set termination value */ | ||
201 | { 0x03, 0x14, 0xf0 }, /* SIMG: Change CKDT level */ | ||
202 | { 0x03, 0x17, 0x07 }, /* SIMG: PLL Calrefsel */ | ||
203 | { 0x03, 0x1a, 0x20 }, /* VCO Cal */ | ||
204 | { 0x03, 0x22, 0xe0 }, /* SIMG: Auto EQ */ | ||
205 | { 0x03, 0x23, 0xc0 }, /* SIMG: Auto EQ */ | ||
206 | { 0x03, 0x24, 0xa0 }, /* SIMG: Auto EQ */ | ||
207 | { 0x03, 0x25, 0x80 }, /* SIMG: Auto EQ */ | ||
208 | { 0x03, 0x26, 0x60 }, /* SIMG: Auto EQ */ | ||
209 | { 0x03, 0x27, 0x40 }, /* SIMG: Auto EQ */ | ||
210 | { 0x03, 0x28, 0x20 }, /* SIMG: Auto EQ */ | ||
211 | { 0x03, 0x29, 0x00 }, /* SIMG: Auto EQ */ | ||
212 | { 0x03, 0x31, 0x0b }, /* SIMG: Rx PLL BW value from I2C BW ~ 4MHz */ | ||
213 | { 0x03, 0x45, 0x06 }, /* SIMG: DPLL Mode */ | ||
214 | { 0x03, 0x4b, 0x06 }, /* SIMG: Correcting HW default */ | ||
215 | { 0x03, 0x4c, 0xa0 }, /* Manual zone control */ | ||
216 | { 0x03, 0x4d, 0x02 }, /* SIMG: PLL Mode Value (order is important) */ | ||
217 | }; | ||
218 | |||
219 | static int sii9234_set_internal(struct sii9234_context *ctx) | ||
220 | { | ||
221 | struct i2c_client *client = ctx->client; | ||
222 | int i, ret; | ||
223 | |||
224 | for (i = 0; i < ARRAY_SIZE(data); ++i) { | ||
225 | int addr = (data[i][0] << 8) | data[i][1]; | ||
226 | ret = sii9234_writeb_idx(client, addr, data[i][2]); | ||
227 | if (ret < 0) | ||
228 | return ret; | ||
229 | } | ||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | static int sii9234_runtime_suspend(struct device *dev) | ||
234 | { | ||
235 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
236 | struct sii9234_context *ctx = sd_to_context(sd); | ||
237 | struct i2c_client *client = ctx->client; | ||
238 | |||
239 | dev_info(dev, "suspend start\n"); | ||
240 | |||
241 | sii9234_writeb_mask(client, 0x1e, 3, 3); | ||
242 | regulator_disable(ctx->power); | ||
243 | |||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | static int sii9234_runtime_resume(struct device *dev) | ||
248 | { | ||
249 | struct v4l2_subdev *sd = dev_get_drvdata(dev); | ||
250 | struct sii9234_context *ctx = sd_to_context(sd); | ||
251 | struct i2c_client *client = ctx->client; | ||
252 | int ret; | ||
253 | |||
254 | dev_info(dev, "resume start\n"); | ||
255 | regulator_enable(ctx->power); | ||
256 | |||
257 | ret = sii9234_reset(ctx); | ||
258 | if (ret) | ||
259 | goto fail; | ||
260 | |||
261 | /* enable tpi */ | ||
262 | ret = sii9234_writeb_mask(client, 0x1e, 1, 0); | ||
263 | if (ret < 0) | ||
264 | goto fail; | ||
265 | ret = sii9234_set_internal(ctx); | ||
266 | if (ret < 0) | ||
267 | goto fail; | ||
268 | |||
269 | return 0; | ||
270 | |||
271 | fail: | ||
272 | dev_err(dev, "failed to resume\n"); | ||
273 | regulator_disable(ctx->power); | ||
274 | |||
275 | return ret; | ||
276 | } | ||
277 | |||
278 | static const struct dev_pm_ops sii9234_pm_ops = { | ||
279 | .runtime_suspend = sii9234_runtime_suspend, | ||
280 | .runtime_resume = sii9234_runtime_resume, | ||
281 | }; | ||
282 | |||
283 | static int sii9234_s_power(struct v4l2_subdev *sd, int on) | ||
284 | { | ||
285 | struct sii9234_context *ctx = sd_to_context(sd); | ||
286 | int ret; | ||
287 | |||
288 | if (on) | ||
289 | ret = pm_runtime_get_sync(&ctx->client->dev); | ||
290 | else | ||
291 | ret = pm_runtime_put(&ctx->client->dev); | ||
292 | /* only values < 0 indicate errors */ | ||
293 | return IS_ERR_VALUE(ret) ? ret : 0; | ||
294 | } | ||
295 | |||
296 | static int sii9234_s_stream(struct v4l2_subdev *sd, int enable) | ||
297 | { | ||
298 | struct sii9234_context *ctx = sd_to_context(sd); | ||
299 | |||
300 | /* (dis/en)able TDMS output */ | ||
301 | sii9234_writeb_mask(ctx->client, 0x1a, enable ? 0 : ~0 , 1 << 4); | ||
302 | return 0; | ||
303 | } | ||
304 | |||
305 | static const struct v4l2_subdev_core_ops sii9234_core_ops = { | ||
306 | .s_power = sii9234_s_power, | ||
307 | }; | ||
308 | |||
309 | static const struct v4l2_subdev_video_ops sii9234_video_ops = { | ||
310 | .s_stream = sii9234_s_stream, | ||
311 | }; | ||
312 | |||
313 | static const struct v4l2_subdev_ops sii9234_ops = { | ||
314 | .core = &sii9234_core_ops, | ||
315 | .video = &sii9234_video_ops, | ||
316 | }; | ||
317 | |||
318 | static int __devinit sii9234_probe(struct i2c_client *client, | ||
319 | const struct i2c_device_id *id) | ||
320 | { | ||
321 | struct device *dev = &client->dev; | ||
322 | struct sii9234_platform_data *pdata = dev->platform_data; | ||
323 | struct sii9234_context *ctx; | ||
324 | int ret; | ||
325 | |||
326 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); | ||
327 | if (!ctx) { | ||
328 | dev_err(dev, "out of memory\n"); | ||
329 | ret = -ENOMEM; | ||
330 | goto fail; | ||
331 | } | ||
332 | ctx->client = client; | ||
333 | |||
334 | ctx->power = regulator_get(dev, "hdmi-en"); | ||
335 | if (IS_ERR(ctx->power)) { | ||
336 | dev_err(dev, "failed to acquire regulator hdmi-en\n"); | ||
337 | ret = PTR_ERR(ctx->power); | ||
338 | goto fail_ctx; | ||
339 | } | ||
340 | |||
341 | ctx->gpio_n_reset = pdata->gpio_n_reset; | ||
342 | ret = gpio_request(ctx->gpio_n_reset, "MHL_RST"); | ||
343 | if (ret) { | ||
344 | dev_err(dev, "failed to acquire MHL_RST gpio\n"); | ||
345 | goto fail_power; | ||
346 | } | ||
347 | |||
348 | v4l2_i2c_subdev_init(&ctx->sd, client, &sii9234_ops); | ||
349 | |||
350 | pm_runtime_enable(dev); | ||
351 | |||
352 | /* enable device */ | ||
353 | ret = pm_runtime_get_sync(dev); | ||
354 | if (ret) | ||
355 | goto fail_pm; | ||
356 | |||
357 | /* verify chip version */ | ||
358 | ret = sii9234_verify_version(client); | ||
359 | if (ret) | ||
360 | goto fail_pm_get; | ||
361 | |||
362 | /* stop processing */ | ||
363 | pm_runtime_put(dev); | ||
364 | |||
365 | dev_info(dev, "probe successful\n"); | ||
366 | |||
367 | return 0; | ||
368 | |||
369 | fail_pm_get: | ||
370 | pm_runtime_put_sync(dev); | ||
371 | |||
372 | fail_pm: | ||
373 | pm_runtime_disable(dev); | ||
374 | gpio_free(ctx->gpio_n_reset); | ||
375 | |||
376 | fail_power: | ||
377 | regulator_put(ctx->power); | ||
378 | |||
379 | fail_ctx: | ||
380 | kfree(ctx); | ||
381 | |||
382 | fail: | ||
383 | dev_err(dev, "probe failed\n"); | ||
384 | |||
385 | return ret; | ||
386 | } | ||
387 | |||
388 | static int __devexit sii9234_remove(struct i2c_client *client) | ||
389 | { | ||
390 | struct device *dev = &client->dev; | ||
391 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
392 | struct sii9234_context *ctx = sd_to_context(sd); | ||
393 | |||
394 | pm_runtime_disable(dev); | ||
395 | gpio_free(ctx->gpio_n_reset); | ||
396 | regulator_put(ctx->power); | ||
397 | kfree(ctx); | ||
398 | |||
399 | dev_info(dev, "remove successful\n"); | ||
400 | |||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | |||
405 | static const struct i2c_device_id sii9234_id[] = { | ||
406 | { "SII9234", 0 }, | ||
407 | { }, | ||
408 | }; | ||
409 | |||
410 | MODULE_DEVICE_TABLE(i2c, sii9234_id); | ||
411 | static struct i2c_driver sii9234_driver = { | ||
412 | .driver = { | ||
413 | .name = "sii9234", | ||
414 | .owner = THIS_MODULE, | ||
415 | .pm = &sii9234_pm_ops, | ||
416 | }, | ||
417 | .probe = sii9234_probe, | ||
418 | .remove = __devexit_p(sii9234_remove), | ||
419 | .id_table = sii9234_id, | ||
420 | }; | ||
421 | |||
422 | static int __init sii9234_init(void) | ||
423 | { | ||
424 | return i2c_add_driver(&sii9234_driver); | ||
425 | } | ||
426 | module_init(sii9234_init); | ||
427 | |||
428 | static void __exit sii9234_exit(void) | ||
429 | { | ||
430 | i2c_del_driver(&sii9234_driver); | ||
431 | } | ||
432 | module_exit(sii9234_exit); | ||
diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index 99a2ac16f9e5..0caac50d7cf4 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c | |||
@@ -539,15 +539,4 @@ static struct i2c_driver saa6588_driver = { | |||
539 | .id_table = saa6588_id, | 539 | .id_table = saa6588_id, |
540 | }; | 540 | }; |
541 | 541 | ||
542 | static __init int init_saa6588(void) | 542 | module_i2c_driver(saa6588_driver); |
543 | { | ||
544 | return i2c_add_driver(&saa6588_driver); | ||
545 | } | ||
546 | |||
547 | static __exit void exit_saa6588(void) | ||
548 | { | ||
549 | i2c_del_driver(&saa6588_driver); | ||
550 | } | ||
551 | |||
552 | module_init(init_saa6588); | ||
553 | module_exit(exit_saa6588); | ||
diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c index 99664205ef4e..51cd4c8f0520 100644 --- a/drivers/media/video/saa7110.c +++ b/drivers/media/video/saa7110.c | |||
@@ -491,15 +491,4 @@ static struct i2c_driver saa7110_driver = { | |||
491 | .id_table = saa7110_id, | 491 | .id_table = saa7110_id, |
492 | }; | 492 | }; |
493 | 493 | ||
494 | static __init int init_saa7110(void) | 494 | module_i2c_driver(saa7110_driver); |
495 | { | ||
496 | return i2c_add_driver(&saa7110_driver); | ||
497 | } | ||
498 | |||
499 | static __exit void exit_saa7110(void) | ||
500 | { | ||
501 | i2c_del_driver(&saa7110_driver); | ||
502 | } | ||
503 | |||
504 | module_init(init_saa7110); | ||
505 | module_exit(exit_saa7110); | ||
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 0ef5484696b6..2107336cd836 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c | |||
@@ -1724,15 +1724,4 @@ static struct i2c_driver saa711x_driver = { | |||
1724 | .id_table = saa711x_id, | 1724 | .id_table = saa711x_id, |
1725 | }; | 1725 | }; |
1726 | 1726 | ||
1727 | static __init int init_saa711x(void) | 1727 | module_i2c_driver(saa711x_driver); |
1728 | { | ||
1729 | return i2c_add_driver(&saa711x_driver); | ||
1730 | } | ||
1731 | |||
1732 | static __exit void exit_saa711x(void) | ||
1733 | { | ||
1734 | i2c_del_driver(&saa711x_driver); | ||
1735 | } | ||
1736 | |||
1737 | module_init(init_saa711x); | ||
1738 | module_exit(exit_saa711x); | ||
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index ad964616c9d2..39c90b08eea8 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c | |||
@@ -852,15 +852,4 @@ static struct i2c_driver saa7127_driver = { | |||
852 | .id_table = saa7127_id, | 852 | .id_table = saa7127_id, |
853 | }; | 853 | }; |
854 | 854 | ||
855 | static __init int init_saa7127(void) | 855 | module_i2c_driver(saa7127_driver); |
856 | { | ||
857 | return i2c_add_driver(&saa7127_driver); | ||
858 | } | ||
859 | |||
860 | static __exit void exit_saa7127(void) | ||
861 | { | ||
862 | i2c_del_driver(&saa7127_driver); | ||
863 | } | ||
864 | |||
865 | module_init(init_saa7127); | ||
866 | module_exit(exit_saa7127); | ||
diff --git a/drivers/media/video/saa7134/Makefile b/drivers/media/video/saa7134/Makefile index a646ccf51696..da3899329f52 100644 --- a/drivers/media/video/saa7134/Makefile +++ b/drivers/media/video/saa7134/Makefile | |||
@@ -10,7 +10,7 @@ obj-$(CONFIG_VIDEO_SAA7134_ALSA) += saa7134-alsa.o | |||
10 | 10 | ||
11 | obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o | 11 | obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o |
12 | 12 | ||
13 | ccflags-y += -Idrivers/media/video | 13 | ccflags-y += -I$(srctree)/drivers/media/video |
14 | ccflags-y += -Idrivers/media/common/tuners | 14 | ccflags-y += -I$(srctree)/drivers/media/common/tuners |
15 | ccflags-y += -Idrivers/media/dvb/dvb-core | 15 | ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core |
16 | ccflags-y += -Idrivers/media/dvb/frontends | 16 | ccflags-y += -I$(srctree)/drivers/media/dvb/frontends |
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index f9f29cc93a8a..f147b05bd860 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c | |||
@@ -1001,18 +1001,7 @@ static struct i2c_driver saa6752hs_driver = { | |||
1001 | .id_table = saa6752hs_id, | 1001 | .id_table = saa6752hs_id, |
1002 | }; | 1002 | }; |
1003 | 1003 | ||
1004 | static __init int init_saa6752hs(void) | 1004 | module_i2c_driver(saa6752hs_driver); |
1005 | { | ||
1006 | return i2c_add_driver(&saa6752hs_driver); | ||
1007 | } | ||
1008 | |||
1009 | static __exit void exit_saa6752hs(void) | ||
1010 | { | ||
1011 | i2c_del_driver(&saa6752hs_driver); | ||
1012 | } | ||
1013 | |||
1014 | module_init(init_saa6752hs); | ||
1015 | module_exit(exit_saa6752hs); | ||
1016 | 1005 | ||
1017 | /* | 1006 | /* |
1018 | * Overrides for Emacs so that we follow Linus's tabbing style. | 1007 | * Overrides for Emacs so that we follow Linus's tabbing style. |
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 065d0f6be4a0..53aae5968ffb 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include "tea5767.h" | 33 | #include "tea5767.h" |
34 | #include "tda18271.h" | 34 | #include "tda18271.h" |
35 | #include "xc5000.h" | 35 | #include "xc5000.h" |
36 | #include "s5h1411.h" | ||
36 | 37 | ||
37 | /* commly used strings */ | 38 | /* commly used strings */ |
38 | static char name_mute[] = "mute"; | 39 | static char name_mute[] = "mute"; |
@@ -5712,6 +5713,36 @@ struct saa7134_board saa7134_boards[] = { | |||
5712 | .amux = LINE1, | 5713 | .amux = LINE1, |
5713 | } }, | 5714 | } }, |
5714 | }, | 5715 | }, |
5716 | [SAA7134_BOARD_KWORLD_PC150U] = { | ||
5717 | .name = "Kworld PC150-U", | ||
5718 | .audio_clock = 0x00187de7, | ||
5719 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
5720 | .radio_type = UNSET, | ||
5721 | .tuner_addr = ADDR_UNSET, | ||
5722 | .radio_addr = ADDR_UNSET, | ||
5723 | .mpeg = SAA7134_MPEG_DVB, | ||
5724 | .gpiomask = 1 << 21, | ||
5725 | .ts_type = SAA7134_MPEG_TS_PARALLEL, | ||
5726 | .inputs = { { | ||
5727 | .name = name_tv, | ||
5728 | .vmux = 1, | ||
5729 | .amux = TV, | ||
5730 | .tv = 1, | ||
5731 | }, { | ||
5732 | .name = name_comp, | ||
5733 | .vmux = 3, | ||
5734 | .amux = LINE1, | ||
5735 | }, { | ||
5736 | .name = name_svideo, | ||
5737 | .vmux = 8, | ||
5738 | .amux = LINE2, | ||
5739 | } }, | ||
5740 | .radio = { | ||
5741 | .name = name_radio, | ||
5742 | .amux = TV, | ||
5743 | .gpio = 0x0000000, | ||
5744 | }, | ||
5745 | }, | ||
5715 | 5746 | ||
5716 | }; | 5747 | }; |
5717 | 5748 | ||
@@ -6306,6 +6337,12 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
6306 | .driver_data = SAA7134_BOARD_KWORLD_ATSC110, /* ATSC 115 */ | 6337 | .driver_data = SAA7134_BOARD_KWORLD_ATSC110, /* ATSC 115 */ |
6307 | },{ | 6338 | },{ |
6308 | .vendor = PCI_VENDOR_ID_PHILIPS, | 6339 | .vendor = PCI_VENDOR_ID_PHILIPS, |
6340 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */ | ||
6341 | .subvendor = 0x17de, | ||
6342 | .subdevice = 0xa134, | ||
6343 | .driver_data = SAA7134_BOARD_KWORLD_PC150U, | ||
6344 | }, { | ||
6345 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
6309 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, | 6346 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, |
6310 | .subvendor = 0x1461, | 6347 | .subvendor = 0x1461, |
6311 | .subdevice = 0x7360, | 6348 | .subdevice = 0x7360, |
@@ -7134,6 +7171,23 @@ static inline int saa7134_kworld_sbtvd_toggle_agc(struct saa7134_dev *dev, | |||
7134 | return 0; | 7171 | return 0; |
7135 | } | 7172 | } |
7136 | 7173 | ||
7174 | static int saa7134_kworld_pc150u_toggle_agc(struct saa7134_dev *dev, | ||
7175 | enum tda18271_mode mode) | ||
7176 | { | ||
7177 | switch (mode) { | ||
7178 | case TDA18271_ANALOG: | ||
7179 | saa7134_set_gpio(dev, 18, 0); | ||
7180 | break; | ||
7181 | case TDA18271_DIGITAL: | ||
7182 | saa7134_set_gpio(dev, 18, 1); | ||
7183 | msleep(30); | ||
7184 | break; | ||
7185 | default: | ||
7186 | return -EINVAL; | ||
7187 | } | ||
7188 | return 0; | ||
7189 | } | ||
7190 | |||
7137 | static int saa7134_tda8290_18271_callback(struct saa7134_dev *dev, | 7191 | static int saa7134_tda8290_18271_callback(struct saa7134_dev *dev, |
7138 | int command, int arg) | 7192 | int command, int arg) |
7139 | { | 7193 | { |
@@ -7150,6 +7204,9 @@ static int saa7134_tda8290_18271_callback(struct saa7134_dev *dev, | |||
7150 | case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: | 7204 | case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: |
7151 | ret = saa7134_kworld_sbtvd_toggle_agc(dev, arg); | 7205 | ret = saa7134_kworld_sbtvd_toggle_agc(dev, arg); |
7152 | break; | 7206 | break; |
7207 | case SAA7134_BOARD_KWORLD_PC150U: | ||
7208 | ret = saa7134_kworld_pc150u_toggle_agc(dev, arg); | ||
7209 | break; | ||
7153 | default: | 7210 | default: |
7154 | break; | 7211 | break; |
7155 | } | 7212 | } |
@@ -7171,6 +7228,7 @@ static int saa7134_tda8290_callback(struct saa7134_dev *dev, | |||
7171 | case SAA7134_BOARD_HAUPPAUGE_HVR1120: | 7228 | case SAA7134_BOARD_HAUPPAUGE_HVR1120: |
7172 | case SAA7134_BOARD_AVERMEDIA_M733A: | 7229 | case SAA7134_BOARD_AVERMEDIA_M733A: |
7173 | case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: | 7230 | case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG: |
7231 | case SAA7134_BOARD_KWORLD_PC150U: | ||
7174 | case SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2: | 7232 | case SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2: |
7175 | /* tda8290 + tda18271 */ | 7233 | /* tda8290 + tda18271 */ |
7176 | ret = saa7134_tda8290_18271_callback(dev, command, arg); | 7234 | ret = saa7134_tda8290_18271_callback(dev, command, arg); |
@@ -7452,6 +7510,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
7452 | case SAA7134_BOARD_BEHOLD_X7: | 7510 | case SAA7134_BOARD_BEHOLD_X7: |
7453 | case SAA7134_BOARD_BEHOLD_H7: | 7511 | case SAA7134_BOARD_BEHOLD_H7: |
7454 | case SAA7134_BOARD_BEHOLD_A7: | 7512 | case SAA7134_BOARD_BEHOLD_A7: |
7513 | case SAA7134_BOARD_KWORLD_PC150U: | ||
7455 | dev->has_remote = SAA7134_REMOTE_I2C; | 7514 | dev->has_remote = SAA7134_REMOTE_I2C; |
7456 | break; | 7515 | break; |
7457 | case SAA7134_BOARD_AVERMEDIA_A169_B: | 7516 | case SAA7134_BOARD_AVERMEDIA_A169_B: |
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 089fa0fb5c94..aaa5c97a7216 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c | |||
@@ -61,6 +61,7 @@ | |||
61 | #include "zl10036.h" | 61 | #include "zl10036.h" |
62 | #include "zl10039.h" | 62 | #include "zl10039.h" |
63 | #include "mt312.h" | 63 | #include "mt312.h" |
64 | #include "s5h1411.h" | ||
64 | 65 | ||
65 | MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); | 66 | MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); |
66 | MODULE_LICENSE("GPL"); | 67 | MODULE_LICENSE("GPL"); |
@@ -1158,6 +1159,33 @@ static struct tda18271_config prohdtv_pro2_tda18271_config = { | |||
1158 | .output_opt = TDA18271_OUTPUT_LT_OFF, | 1159 | .output_opt = TDA18271_OUTPUT_LT_OFF, |
1159 | }; | 1160 | }; |
1160 | 1161 | ||
1162 | static struct tda18271_std_map kworld_tda18271_std_map = { | ||
1163 | .atsc_6 = { .if_freq = 3250, .agc_mode = 3, .std = 3, | ||
1164 | .if_lvl = 6, .rfagc_top = 0x37 }, | ||
1165 | .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 0, | ||
1166 | .if_lvl = 6, .rfagc_top = 0x37 }, | ||
1167 | }; | ||
1168 | |||
1169 | static struct tda18271_config kworld_pc150u_tda18271_config = { | ||
1170 | .std_map = &kworld_tda18271_std_map, | ||
1171 | .gate = TDA18271_GATE_ANALOG, | ||
1172 | .output_opt = TDA18271_OUTPUT_LT_OFF, | ||
1173 | .config = 3, /* Use tuner callback for AGC */ | ||
1174 | .rf_cal_on_startup = 1 | ||
1175 | }; | ||
1176 | |||
1177 | static struct s5h1411_config kworld_s5h1411_config = { | ||
1178 | .output_mode = S5H1411_PARALLEL_OUTPUT, | ||
1179 | .gpio = S5H1411_GPIO_OFF, | ||
1180 | .qam_if = S5H1411_IF_4000, | ||
1181 | .vsb_if = S5H1411_IF_3250, | ||
1182 | .inversion = S5H1411_INVERSION_ON, | ||
1183 | .status_mode = S5H1411_DEMODLOCKING, | ||
1184 | .mpeg_timing = | ||
1185 | S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, | ||
1186 | }; | ||
1187 | |||
1188 | |||
1161 | /* ================================================================== | 1189 | /* ================================================================== |
1162 | * Core code | 1190 | * Core code |
1163 | */ | 1191 | */ |
@@ -1438,6 +1466,22 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1438 | &dev->i2c_adap, 0x61, | 1466 | &dev->i2c_adap, 0x61, |
1439 | TUNER_PHILIPS_TUV1236D); | 1467 | TUNER_PHILIPS_TUV1236D); |
1440 | break; | 1468 | break; |
1469 | case SAA7134_BOARD_KWORLD_PC150U: | ||
1470 | saa7134_set_gpio(dev, 18, 1); /* Switch to digital mode */ | ||
1471 | saa7134_tuner_callback(dev, 0, | ||
1472 | TDA18271_CALLBACK_CMD_AGC_ENABLE, 1); | ||
1473 | fe0->dvb.frontend = dvb_attach(s5h1411_attach, | ||
1474 | &kworld_s5h1411_config, | ||
1475 | &dev->i2c_adap); | ||
1476 | if (fe0->dvb.frontend != NULL) { | ||
1477 | dvb_attach(tda829x_attach, fe0->dvb.frontend, | ||
1478 | &dev->i2c_adap, 0x4b, | ||
1479 | &tda829x_no_probe); | ||
1480 | dvb_attach(tda18271_attach, fe0->dvb.frontend, | ||
1481 | 0x60, &dev->i2c_adap, | ||
1482 | &kworld_pc150u_tda18271_config); | ||
1483 | } | ||
1484 | break; | ||
1441 | case SAA7134_BOARD_FLYDVBS_LR300: | 1485 | case SAA7134_BOARD_FLYDVBS_LR300: |
1442 | fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, | 1486 | fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, |
1443 | &dev->i2c_adap); | 1487 | &dev->i2c_adap); |
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index 2d3f6d265bbf..a176ec3285e0 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c | |||
@@ -254,7 +254,9 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap, | |||
254 | addr = msgs[i].addr << 1; | 254 | addr = msgs[i].addr << 1; |
255 | if (msgs[i].flags & I2C_M_RD) | 255 | if (msgs[i].flags & I2C_M_RD) |
256 | addr |= 1; | 256 | addr |= 1; |
257 | if (i > 0 && msgs[i].flags & I2C_M_RD && msgs[i].addr != 0x40) { | 257 | if (i > 0 && msgs[i].flags & |
258 | I2C_M_RD && msgs[i].addr != 0x40 && | ||
259 | msgs[i].addr != 0x19) { | ||
258 | /* workaround for a saa7134 i2c bug | 260 | /* workaround for a saa7134 i2c bug |
259 | * needed to talk to the mt352 demux | 261 | * needed to talk to the mt352 demux |
260 | * thanks to pinnacle for the hint */ | 262 | * thanks to pinnacle for the hint */ |
@@ -279,6 +281,16 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap, | |||
279 | d1printk("%02x", rc); | 281 | d1printk("%02x", rc); |
280 | msgs[i].buf[byte] = rc; | 282 | msgs[i].buf[byte] = rc; |
281 | } | 283 | } |
284 | /* discard mysterious extra byte when reading | ||
285 | from Samsung S5H1411. i2c bus gets error | ||
286 | if we do not. */ | ||
287 | if (0x19 == msgs[i].addr) { | ||
288 | d1printk(" ?"); | ||
289 | rc = i2c_recv_byte(dev); | ||
290 | if (rc < 0) | ||
291 | goto err; | ||
292 | d1printk("%02x", rc); | ||
293 | } | ||
282 | } else { | 294 | } else { |
283 | /* write bytes */ | 295 | /* write bytes */ |
284 | d2printk("write bytes\n"); | 296 | d2printk("write bytes\n"); |
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 22ecd7297d2d..48d2878699b7 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -210,6 +210,54 @@ static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key, | |||
210 | return 1; | 210 | return 1; |
211 | } | 211 | } |
212 | 212 | ||
213 | /* copied and modified from get_key_msi_tvanywhere_plus() */ | ||
214 | static int get_key_kworld_pc150u(struct IR_i2c *ir, u32 *ir_key, | ||
215 | u32 *ir_raw) | ||
216 | { | ||
217 | unsigned char b; | ||
218 | unsigned int gpio; | ||
219 | |||
220 | /* <dev> is needed to access GPIO. Used by the saa_readl macro. */ | ||
221 | struct saa7134_dev *dev = ir->c->adapter->algo_data; | ||
222 | if (dev == NULL) { | ||
223 | i2cdprintk("get_key_kworld_pc150u: " | ||
224 | "ir->c->adapter->algo_data is NULL!\n"); | ||
225 | return -EIO; | ||
226 | } | ||
227 | |||
228 | /* rising SAA7134_GPIO_GPRESCAN reads the status */ | ||
229 | |||
230 | saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
231 | saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
232 | |||
233 | gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); | ||
234 | |||
235 | /* GPIO&0x100 is pulsed low when a button is pressed. Don't do | ||
236 | I2C receive if gpio&0x100 is not low. */ | ||
237 | |||
238 | if (gpio & 0x100) | ||
239 | return 0; /* No button press */ | ||
240 | |||
241 | /* GPIO says there is a button press. Get it. */ | ||
242 | |||
243 | if (1 != i2c_master_recv(ir->c, &b, 1)) { | ||
244 | i2cdprintk("read error\n"); | ||
245 | return -EIO; | ||
246 | } | ||
247 | |||
248 | /* No button press */ | ||
249 | |||
250 | if (b == 0xff) | ||
251 | return 0; | ||
252 | |||
253 | /* Button pressed */ | ||
254 | |||
255 | dprintk("get_key_kworld_pc150u: Key = 0x%02X\n", b); | ||
256 | *ir_key = b; | ||
257 | *ir_raw = b; | ||
258 | return 1; | ||
259 | } | ||
260 | |||
213 | static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | 261 | static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) |
214 | { | 262 | { |
215 | unsigned char b; | 263 | unsigned char b; |
@@ -901,6 +949,21 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) | |||
901 | msg_msi.addr, dev->i2c_adap.name, | 949 | msg_msi.addr, dev->i2c_adap.name, |
902 | (1 == rc) ? "yes" : "no"); | 950 | (1 == rc) ? "yes" : "no"); |
903 | break; | 951 | break; |
952 | case SAA7134_BOARD_KWORLD_PC150U: | ||
953 | /* copied and modified from MSI TV@nywhere Plus */ | ||
954 | dev->init_data.name = "Kworld PC150-U"; | ||
955 | dev->init_data.get_key = get_key_kworld_pc150u; | ||
956 | dev->init_data.ir_codes = RC_MAP_KWORLD_PC150U; | ||
957 | info.addr = 0x30; | ||
958 | /* MSI TV@nywhere Plus controller doesn't seem to | ||
959 | respond to probes unless we read something from | ||
960 | an existing device. Weird... | ||
961 | REVISIT: might no longer be needed */ | ||
962 | rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1); | ||
963 | dprintk("probe 0x%02x @ %s: %s\n", | ||
964 | msg_msi.addr, dev->i2c_adap.name, | ||
965 | (1 == rc) ? "yes" : "no"); | ||
966 | break; | ||
904 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: | 967 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: |
905 | dev->init_data.name = "HVR 1110"; | 968 | dev->init_data.name = "HVR 1110"; |
906 | dev->init_data.get_key = get_key_hvr1110; | 969 | dev->init_data.get_key = get_key_hvr1110; |
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 42fba4f93c72..f625060e6a0f 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h | |||
@@ -126,8 +126,8 @@ struct saa7134_card_ir { | |||
126 | unsigned users; | 126 | unsigned users; |
127 | 127 | ||
128 | u32 polling; | 128 | u32 polling; |
129 | u32 last_gpio; | 129 | u32 last_gpio; |
130 | u32 mask_keycode, mask_keydown, mask_keyup; | 130 | u32 mask_keycode, mask_keydown, mask_keyup; |
131 | 131 | ||
132 | bool running; | 132 | bool running; |
133 | bool active; | 133 | bool active; |
@@ -331,6 +331,7 @@ struct saa7134_card_ir { | |||
331 | #define SAA7134_BOARD_BEHOLD_501 186 | 331 | #define SAA7134_BOARD_BEHOLD_501 186 |
332 | #define SAA7134_BOARD_BEHOLD_503FM 187 | 332 | #define SAA7134_BOARD_BEHOLD_503FM 187 |
333 | #define SAA7134_BOARD_SENSORAY811_911 188 | 333 | #define SAA7134_BOARD_SENSORAY811_911 188 |
334 | #define SAA7134_BOARD_KWORLD_PC150U 189 | ||
334 | 335 | ||
335 | #define SAA7134_MAXBOARDS 32 | 336 | #define SAA7134_MAXBOARDS 32 |
336 | #define SAA7134_INPUT_MAX 8 | 337 | #define SAA7134_INPUT_MAX 8 |
diff --git a/drivers/media/video/saa7164/Makefile b/drivers/media/video/saa7164/Makefile index ecd5811dc486..068443af30c8 100644 --- a/drivers/media/video/saa7164/Makefile +++ b/drivers/media/video/saa7164/Makefile | |||
@@ -4,9 +4,9 @@ saa7164-objs := saa7164-cards.o saa7164-core.o saa7164-i2c.o saa7164-dvb.o \ | |||
4 | 4 | ||
5 | obj-$(CONFIG_VIDEO_SAA7164) += saa7164.o | 5 | obj-$(CONFIG_VIDEO_SAA7164) += saa7164.o |
6 | 6 | ||
7 | ccflags-y += -Idrivers/media/video | 7 | ccflags-y += -I$(srctree)/drivers/media/video |
8 | ccflags-y += -Idrivers/media/common/tuners | 8 | ccflags-y += -I$(srctree)/drivers/media/common/tuners |
9 | ccflags-y += -Idrivers/media/dvb/dvb-core | 9 | ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core |
10 | ccflags-y += -Idrivers/media/dvb/frontends | 10 | ccflags-y += -I$(srctree)/drivers/media/dvb/frontends |
11 | 11 | ||
12 | ccflags-y += $(extra-cflags-y) $(extra-cflags-m) | 12 | ccflags-y += $(extra-cflags-y) $(extra-cflags-m) |
diff --git a/drivers/media/video/saa7164/saa7164-encoder.c b/drivers/media/video/saa7164/saa7164-encoder.c index 2fd38a01887f..a9ed686ad08a 100644 --- a/drivers/media/video/saa7164/saa7164-encoder.c +++ b/drivers/media/video/saa7164/saa7164-encoder.c | |||
@@ -791,11 +791,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
791 | return 0; | 791 | return 0; |
792 | } | 792 | } |
793 | 793 | ||
794 | static int vidioc_log_status(struct file *file, void *priv) | ||
795 | { | ||
796 | return 0; | ||
797 | } | ||
798 | |||
799 | static int fill_queryctrl(struct saa7164_encoder_params *params, | 794 | static int fill_queryctrl(struct saa7164_encoder_params *params, |
800 | struct v4l2_queryctrl *c) | 795 | struct v4l2_queryctrl *c) |
801 | { | 796 | { |
@@ -1347,7 +1342,6 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { | |||
1347 | .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls, | 1342 | .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls, |
1348 | .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, | 1343 | .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, |
1349 | .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, | 1344 | .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, |
1350 | .vidioc_log_status = vidioc_log_status, | ||
1351 | .vidioc_queryctrl = vidioc_queryctrl, | 1345 | .vidioc_queryctrl = vidioc_queryctrl, |
1352 | .vidioc_g_chip_ident = saa7164_g_chip_ident, | 1346 | .vidioc_g_chip_ident = saa7164_g_chip_ident, |
1353 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 1347 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
diff --git a/drivers/media/video/saa7164/saa7164-vbi.c b/drivers/media/video/saa7164/saa7164-vbi.c index e2e034158718..273cf807401c 100644 --- a/drivers/media/video/saa7164/saa7164-vbi.c +++ b/drivers/media/video/saa7164/saa7164-vbi.c | |||
@@ -730,11 +730,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
730 | return 0; | 730 | return 0; |
731 | } | 731 | } |
732 | 732 | ||
733 | static int vidioc_log_status(struct file *file, void *priv) | ||
734 | { | ||
735 | return 0; | ||
736 | } | ||
737 | |||
738 | static int fill_queryctrl(struct saa7164_vbi_params *params, | 733 | static int fill_queryctrl(struct saa7164_vbi_params *params, |
739 | struct v4l2_queryctrl *c) | 734 | struct v4l2_queryctrl *c) |
740 | { | 735 | { |
@@ -1256,7 +1251,6 @@ static const struct v4l2_ioctl_ops vbi_ioctl_ops = { | |||
1256 | .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls, | 1251 | .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls, |
1257 | .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, | 1252 | .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, |
1258 | .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, | 1253 | .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, |
1259 | .vidioc_log_status = vidioc_log_status, | ||
1260 | .vidioc_queryctrl = vidioc_queryctrl, | 1254 | .vidioc_queryctrl = vidioc_queryctrl, |
1261 | #if 0 | 1255 | #if 0 |
1262 | .vidioc_g_chip_ident = saa7164_g_chip_ident, | 1256 | .vidioc_g_chip_ident = saa7164_g_chip_ident, |
diff --git a/drivers/media/video/saa717x.c b/drivers/media/video/saa717x.c index b6172c2c517e..1e84466515aa 100644 --- a/drivers/media/video/saa717x.c +++ b/drivers/media/video/saa717x.c | |||
@@ -1375,15 +1375,4 @@ static struct i2c_driver saa717x_driver = { | |||
1375 | .id_table = saa717x_id, | 1375 | .id_table = saa717x_id, |
1376 | }; | 1376 | }; |
1377 | 1377 | ||
1378 | static __init int init_saa717x(void) | 1378 | module_i2c_driver(saa717x_driver); |
1379 | { | ||
1380 | return i2c_add_driver(&saa717x_driver); | ||
1381 | } | ||
1382 | |||
1383 | static __exit void exit_saa717x(void) | ||
1384 | { | ||
1385 | i2c_del_driver(&saa717x_driver); | ||
1386 | } | ||
1387 | |||
1388 | module_init(init_saa717x); | ||
1389 | module_exit(exit_saa717x); | ||
diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c index 96f56c2f11f3..2c6b65c76e2b 100644 --- a/drivers/media/video/saa7185.c +++ b/drivers/media/video/saa7185.c | |||
@@ -374,15 +374,4 @@ static struct i2c_driver saa7185_driver = { | |||
374 | .id_table = saa7185_id, | 374 | .id_table = saa7185_id, |
375 | }; | 375 | }; |
376 | 376 | ||
377 | static __init int init_saa7185(void) | 377 | module_i2c_driver(saa7185_driver); |
378 | { | ||
379 | return i2c_add_driver(&saa7185_driver); | ||
380 | } | ||
381 | |||
382 | static __exit void exit_saa7185(void) | ||
383 | { | ||
384 | i2c_del_driver(&saa7185_driver); | ||
385 | } | ||
386 | |||
387 | module_init(init_saa7185); | ||
388 | module_exit(exit_saa7185); | ||
diff --git a/drivers/media/video/saa7191.c b/drivers/media/video/saa7191.c index 211fa25a1239..d7d1670e0ca3 100644 --- a/drivers/media/video/saa7191.c +++ b/drivers/media/video/saa7191.c | |||
@@ -656,15 +656,4 @@ static struct i2c_driver saa7191_driver = { | |||
656 | .id_table = saa7191_id, | 656 | .id_table = saa7191_id, |
657 | }; | 657 | }; |
658 | 658 | ||
659 | static __init int init_saa7191(void) | 659 | module_i2c_driver(saa7191_driver); |
660 | { | ||
661 | return i2c_add_driver(&saa7191_driver); | ||
662 | } | ||
663 | |||
664 | static __exit void exit_saa7191(void) | ||
665 | { | ||
666 | i2c_del_driver(&saa7191_driver); | ||
667 | } | ||
668 | |||
669 | module_init(init_saa7191); | ||
670 | module_exit(exit_saa7191); | ||
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index f854d85a387c..424dfacd263a 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c | |||
@@ -112,6 +112,10 @@ struct sh_mobile_ceu_dev { | |||
112 | 112 | ||
113 | u32 cflcr; | 113 | u32 cflcr; |
114 | 114 | ||
115 | /* static max sizes either from platform data or default */ | ||
116 | int max_width; | ||
117 | int max_height; | ||
118 | |||
115 | enum v4l2_field field; | 119 | enum v4l2_field field; |
116 | int sequence; | 120 | int sequence; |
117 | 121 | ||
@@ -1081,7 +1085,15 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int | |||
1081 | if (ret < 0) | 1085 | if (ret < 0) |
1082 | return ret; | 1086 | return ret; |
1083 | 1087 | ||
1084 | while ((mf.width > 2560 || mf.height > 1920) && shift < 4) { | 1088 | /* |
1089 | * All currently existing CEU implementations support 2560x1920 | ||
1090 | * or larger frames. If the sensor is proposing too big a frame, | ||
1091 | * don't bother with possibly supportred by the CEU larger | ||
1092 | * sizes, just try VGA multiples. If needed, this can be | ||
1093 | * adjusted in the future. | ||
1094 | */ | ||
1095 | while ((mf.width > pcdev->max_width || | ||
1096 | mf.height > pcdev->max_height) && shift < 4) { | ||
1085 | /* Try 2560x1920, 1280x960, 640x480, 320x240 */ | 1097 | /* Try 2560x1920, 1280x960, 640x480, 320x240 */ |
1086 | mf.width = 2560 >> shift; | 1098 | mf.width = 2560 >> shift; |
1087 | mf.height = 1920 >> shift; | 1099 | mf.height = 1920 >> shift; |
@@ -1377,6 +1389,8 @@ static int client_s_crop(struct soc_camera_device *icd, struct v4l2_crop *crop, | |||
1377 | static int client_s_fmt(struct soc_camera_device *icd, | 1389 | static int client_s_fmt(struct soc_camera_device *icd, |
1378 | struct v4l2_mbus_framefmt *mf, bool ceu_can_scale) | 1390 | struct v4l2_mbus_framefmt *mf, bool ceu_can_scale) |
1379 | { | 1391 | { |
1392 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
1393 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | ||
1380 | struct sh_mobile_ceu_cam *cam = icd->host_priv; | 1394 | struct sh_mobile_ceu_cam *cam = icd->host_priv; |
1381 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 1395 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
1382 | struct device *dev = icd->parent; | 1396 | struct device *dev = icd->parent; |
@@ -1410,8 +1424,8 @@ static int client_s_fmt(struct soc_camera_device *icd, | |||
1410 | if (ret < 0) | 1424 | if (ret < 0) |
1411 | return ret; | 1425 | return ret; |
1412 | 1426 | ||
1413 | max_width = min(cap.bounds.width, 2560); | 1427 | max_width = min(cap.bounds.width, pcdev->max_width); |
1414 | max_height = min(cap.bounds.height, 1920); | 1428 | max_height = min(cap.bounds.height, pcdev->max_height); |
1415 | 1429 | ||
1416 | /* Camera set a format, but geometry is not precise, try to improve */ | 1430 | /* Camera set a format, but geometry is not precise, try to improve */ |
1417 | tmp_w = mf->width; | 1431 | tmp_w = mf->width; |
@@ -1551,7 +1565,7 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, | |||
1551 | if (ret < 0) | 1565 | if (ret < 0) |
1552 | return ret; | 1566 | return ret; |
1553 | 1567 | ||
1554 | if (mf.width > 2560 || mf.height > 1920) | 1568 | if (mf.width > pcdev->max_width || mf.height > pcdev->max_height) |
1555 | return -EINVAL; | 1569 | return -EINVAL; |
1556 | 1570 | ||
1557 | /* 4. Calculate camera scales */ | 1571 | /* 4. Calculate camera scales */ |
@@ -1834,6 +1848,8 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, | |||
1834 | static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, | 1848 | static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, |
1835 | struct v4l2_format *f) | 1849 | struct v4l2_format *f) |
1836 | { | 1850 | { |
1851 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
1852 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | ||
1837 | const struct soc_camera_format_xlate *xlate; | 1853 | const struct soc_camera_format_xlate *xlate; |
1838 | struct v4l2_pix_format *pix = &f->fmt.pix; | 1854 | struct v4l2_pix_format *pix = &f->fmt.pix; |
1839 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 1855 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
@@ -1854,8 +1870,8 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, | |||
1854 | /* FIXME: calculate using depth and bus width */ | 1870 | /* FIXME: calculate using depth and bus width */ |
1855 | 1871 | ||
1856 | /* CFSZR requires height and width to be 4-pixel aligned */ | 1872 | /* CFSZR requires height and width to be 4-pixel aligned */ |
1857 | v4l_bound_align_image(&pix->width, 2, 2560, 2, | 1873 | v4l_bound_align_image(&pix->width, 2, pcdev->max_width, 2, |
1858 | &pix->height, 4, 1920, 2, 0); | 1874 | &pix->height, 4, pcdev->max_height, 2, 0); |
1859 | 1875 | ||
1860 | width = pix->width; | 1876 | width = pix->width; |
1861 | height = pix->height; | 1877 | height = pix->height; |
@@ -1890,8 +1906,8 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, | |||
1890 | * requested a bigger rectangle, it will not return a | 1906 | * requested a bigger rectangle, it will not return a |
1891 | * smaller one. | 1907 | * smaller one. |
1892 | */ | 1908 | */ |
1893 | mf.width = 2560; | 1909 | mf.width = pcdev->max_width; |
1894 | mf.height = 1920; | 1910 | mf.height = pcdev->max_height; |
1895 | ret = v4l2_device_call_until_err(sd->v4l2_dev, | 1911 | ret = v4l2_device_call_until_err(sd->v4l2_dev, |
1896 | soc_camera_grp_id(icd), video, | 1912 | soc_camera_grp_id(icd), video, |
1897 | try_mbus_fmt, &mf); | 1913 | try_mbus_fmt, &mf); |
@@ -2082,6 +2098,9 @@ static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev) | |||
2082 | goto exit_kfree; | 2098 | goto exit_kfree; |
2083 | } | 2099 | } |
2084 | 2100 | ||
2101 | pcdev->max_width = pcdev->pdata->max_width ? : 2560; | ||
2102 | pcdev->max_height = pcdev->pdata->max_height ? : 1920; | ||
2103 | |||
2085 | base = ioremap_nocache(res->start, resource_size(res)); | 2104 | base = ioremap_nocache(res->start, resource_size(res)); |
2086 | if (!base) { | 2105 | if (!base) { |
2087 | err = -ENXIO; | 2106 | err = -ENXIO; |
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index b82710745ba8..eb25756a07af 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c | |||
@@ -526,10 +526,6 @@ static int soc_camera_open(struct file *file) | |||
526 | }, | 526 | }, |
527 | }; | 527 | }; |
528 | 528 | ||
529 | ret = soc_camera_power_on(icd, icl); | ||
530 | if (ret < 0) | ||
531 | goto epower; | ||
532 | |||
533 | /* The camera could have been already on, try to reset */ | 529 | /* The camera could have been already on, try to reset */ |
534 | if (icl->reset) | 530 | if (icl->reset) |
535 | icl->reset(icd->pdev); | 531 | icl->reset(icd->pdev); |
@@ -540,6 +536,10 @@ static int soc_camera_open(struct file *file) | |||
540 | goto eiciadd; | 536 | goto eiciadd; |
541 | } | 537 | } |
542 | 538 | ||
539 | ret = soc_camera_power_on(icd, icl); | ||
540 | if (ret < 0) | ||
541 | goto epower; | ||
542 | |||
543 | pm_runtime_enable(&icd->vdev->dev); | 543 | pm_runtime_enable(&icd->vdev->dev); |
544 | ret = pm_runtime_resume(&icd->vdev->dev); | 544 | ret = pm_runtime_resume(&icd->vdev->dev); |
545 | if (ret < 0 && ret != -ENOSYS) | 545 | if (ret < 0 && ret != -ENOSYS) |
@@ -578,10 +578,10 @@ einitvb: | |||
578 | esfmt: | 578 | esfmt: |
579 | pm_runtime_disable(&icd->vdev->dev); | 579 | pm_runtime_disable(&icd->vdev->dev); |
580 | eresume: | 580 | eresume: |
581 | ici->ops->remove(icd); | ||
582 | eiciadd: | ||
583 | soc_camera_power_off(icd, icl); | 581 | soc_camera_power_off(icd, icl); |
584 | epower: | 582 | epower: |
583 | ici->ops->remove(icd); | ||
584 | eiciadd: | ||
585 | icd->use_count--; | 585 | icd->use_count--; |
586 | module_put(ici->ops->owner); | 586 | module_put(ici->ops->owner); |
587 | 587 | ||
@@ -1050,6 +1050,14 @@ static int soc_camera_probe(struct soc_camera_device *icd) | |||
1050 | if (ret < 0) | 1050 | if (ret < 0) |
1051 | goto ereg; | 1051 | goto ereg; |
1052 | 1052 | ||
1053 | /* The camera could have been already on, try to reset */ | ||
1054 | if (icl->reset) | ||
1055 | icl->reset(icd->pdev); | ||
1056 | |||
1057 | ret = ici->ops->add(icd); | ||
1058 | if (ret < 0) | ||
1059 | goto eadd; | ||
1060 | |||
1053 | /* | 1061 | /* |
1054 | * This will not yet call v4l2_subdev_core_ops::s_power(1), because the | 1062 | * This will not yet call v4l2_subdev_core_ops::s_power(1), because the |
1055 | * subdevice has not been initialised yet. We'll have to call it once | 1063 | * subdevice has not been initialised yet. We'll have to call it once |
@@ -1060,14 +1068,6 @@ static int soc_camera_probe(struct soc_camera_device *icd) | |||
1060 | if (ret < 0) | 1068 | if (ret < 0) |
1061 | goto epower; | 1069 | goto epower; |
1062 | 1070 | ||
1063 | /* The camera could have been already on, try to reset */ | ||
1064 | if (icl->reset) | ||
1065 | icl->reset(icd->pdev); | ||
1066 | |||
1067 | ret = ici->ops->add(icd); | ||
1068 | if (ret < 0) | ||
1069 | goto eadd; | ||
1070 | |||
1071 | /* Must have icd->vdev before registering the device */ | 1071 | /* Must have icd->vdev before registering the device */ |
1072 | ret = video_dev_create(icd); | 1072 | ret = video_dev_create(icd); |
1073 | if (ret < 0) | 1073 | if (ret < 0) |
@@ -1165,10 +1165,10 @@ eadddev: | |||
1165 | video_device_release(icd->vdev); | 1165 | video_device_release(icd->vdev); |
1166 | icd->vdev = NULL; | 1166 | icd->vdev = NULL; |
1167 | evdc: | 1167 | evdc: |
1168 | ici->ops->remove(icd); | ||
1169 | eadd: | ||
1170 | soc_camera_power_off(icd, icl); | 1168 | soc_camera_power_off(icd, icl); |
1171 | epower: | 1169 | epower: |
1170 | ici->ops->remove(icd); | ||
1171 | eadd: | ||
1172 | regulator_bulk_free(icl->num_regulators, icl->regulators); | 1172 | regulator_bulk_free(icl->num_regulators, icl->regulators); |
1173 | ereg: | 1173 | ereg: |
1174 | v4l2_ctrl_handler_free(&icd->ctrl_handler); | 1174 | v4l2_ctrl_handler_free(&icd->ctrl_handler); |
diff --git a/drivers/media/video/sr030pc30.c b/drivers/media/video/sr030pc30.c index d1b07aceaf94..e9d95bda2ab1 100644 --- a/drivers/media/video/sr030pc30.c +++ b/drivers/media/video/sr030pc30.c | |||
@@ -864,18 +864,7 @@ static struct i2c_driver sr030pc30_i2c_driver = { | |||
864 | .id_table = sr030pc30_id, | 864 | .id_table = sr030pc30_id, |
865 | }; | 865 | }; |
866 | 866 | ||
867 | static int __init sr030pc30_init(void) | 867 | module_i2c_driver(sr030pc30_i2c_driver); |
868 | { | ||
869 | return i2c_add_driver(&sr030pc30_i2c_driver); | ||
870 | } | ||
871 | |||
872 | static void __exit sr030pc30_exit(void) | ||
873 | { | ||
874 | i2c_del_driver(&sr030pc30_i2c_driver); | ||
875 | } | ||
876 | |||
877 | module_init(sr030pc30_init); | ||
878 | module_exit(sr030pc30_exit); | ||
879 | 868 | ||
880 | MODULE_DESCRIPTION("Siliconfile SR030PC30 camera driver"); | 869 | MODULE_DESCRIPTION("Siliconfile SR030PC30 camera driver"); |
881 | MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); | 870 | MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); |
diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c index bd218545da9c..f7707e65761e 100644 --- a/drivers/media/video/tda7432.c +++ b/drivers/media/video/tda7432.c | |||
@@ -482,15 +482,4 @@ static struct i2c_driver tda7432_driver = { | |||
482 | .id_table = tda7432_id, | 482 | .id_table = tda7432_id, |
483 | }; | 483 | }; |
484 | 484 | ||
485 | static __init int init_tda7432(void) | 485 | module_i2c_driver(tda7432_driver); |
486 | { | ||
487 | return i2c_add_driver(&tda7432_driver); | ||
488 | } | ||
489 | |||
490 | static __exit void exit_tda7432(void) | ||
491 | { | ||
492 | i2c_del_driver(&tda7432_driver); | ||
493 | } | ||
494 | |||
495 | module_init(init_tda7432); | ||
496 | module_exit(exit_tda7432); | ||
diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c index 22fa8202d5ca..465d7086babf 100644 --- a/drivers/media/video/tda9840.c +++ b/drivers/media/video/tda9840.c | |||
@@ -208,15 +208,4 @@ static struct i2c_driver tda9840_driver = { | |||
208 | .id_table = tda9840_id, | 208 | .id_table = tda9840_id, |
209 | }; | 209 | }; |
210 | 210 | ||
211 | static __init int init_tda9840(void) | 211 | module_i2c_driver(tda9840_driver); |
212 | { | ||
213 | return i2c_add_driver(&tda9840_driver); | ||
214 | } | ||
215 | |||
216 | static __exit void exit_tda9840(void) | ||
217 | { | ||
218 | i2c_del_driver(&tda9840_driver); | ||
219 | } | ||
220 | |||
221 | module_init(init_tda9840); | ||
222 | module_exit(exit_tda9840); | ||
diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c index 827425c5b866..d1d6ea1dd273 100644 --- a/drivers/media/video/tea6415c.c +++ b/drivers/media/video/tea6415c.c | |||
@@ -184,15 +184,4 @@ static struct i2c_driver tea6415c_driver = { | |||
184 | .id_table = tea6415c_id, | 184 | .id_table = tea6415c_id, |
185 | }; | 185 | }; |
186 | 186 | ||
187 | static __init int init_tea6415c(void) | 187 | module_i2c_driver(tea6415c_driver); |
188 | { | ||
189 | return i2c_add_driver(&tea6415c_driver); | ||
190 | } | ||
191 | |||
192 | static __exit void exit_tea6415c(void) | ||
193 | { | ||
194 | i2c_del_driver(&tea6415c_driver); | ||
195 | } | ||
196 | |||
197 | module_init(init_tea6415c); | ||
198 | module_exit(exit_tea6415c); | ||
diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c index f350b6c24500..38757217a074 100644 --- a/drivers/media/video/tea6420.c +++ b/drivers/media/video/tea6420.c | |||
@@ -166,15 +166,4 @@ static struct i2c_driver tea6420_driver = { | |||
166 | .id_table = tea6420_id, | 166 | .id_table = tea6420_id, |
167 | }; | 167 | }; |
168 | 168 | ||
169 | static __init int init_tea6420(void) | 169 | module_i2c_driver(tea6420_driver); |
170 | { | ||
171 | return i2c_add_driver(&tea6420_driver); | ||
172 | } | ||
173 | |||
174 | static __exit void exit_tea6420(void) | ||
175 | { | ||
176 | i2c_del_driver(&tea6420_driver); | ||
177 | } | ||
178 | |||
179 | module_init(init_tea6420); | ||
180 | module_exit(exit_tea6420); | ||
diff --git a/drivers/media/video/ths7303.c b/drivers/media/video/ths7303.c index 61b1dd118364..e5c0eedebc58 100644 --- a/drivers/media/video/ths7303.c +++ b/drivers/media/video/ths7303.c | |||
@@ -137,16 +137,4 @@ static struct i2c_driver ths7303_driver = { | |||
137 | .id_table = ths7303_id, | 137 | .id_table = ths7303_id, |
138 | }; | 138 | }; |
139 | 139 | ||
140 | static int __init ths7303_init(void) | 140 | module_i2c_driver(ths7303_driver); |
141 | { | ||
142 | return i2c_add_driver(&ths7303_driver); | ||
143 | } | ||
144 | |||
145 | static void __exit ths7303_exit(void) | ||
146 | { | ||
147 | i2c_del_driver(&ths7303_driver); | ||
148 | } | ||
149 | |||
150 | module_init(ths7303_init); | ||
151 | module_exit(ths7303_exit); | ||
152 | |||
diff --git a/drivers/media/video/timblogiw.c b/drivers/media/video/timblogiw.c index 4ed1c7c28ae7..02194c056b00 100644 --- a/drivers/media/video/timblogiw.c +++ b/drivers/media/video/timblogiw.c | |||
@@ -564,7 +564,7 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | |||
564 | 564 | ||
565 | spin_unlock_irq(&fh->queue_lock); | 565 | spin_unlock_irq(&fh->queue_lock); |
566 | 566 | ||
567 | desc = fh->chan->device->device_prep_slave_sg(fh->chan, | 567 | desc = dmaengine_prep_slave_sg(fh->chan, |
568 | buf->sg, sg_elems, DMA_DEV_TO_MEM, | 568 | buf->sg, sg_elems, DMA_DEV_TO_MEM, |
569 | DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP); | 569 | DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP); |
570 | if (!desc) { | 570 | if (!desc) { |
diff --git a/drivers/media/video/tlv320aic23b.c b/drivers/media/video/tlv320aic23b.c index 286ec7e7062a..809a75a558ee 100644 --- a/drivers/media/video/tlv320aic23b.c +++ b/drivers/media/video/tlv320aic23b.c | |||
@@ -227,15 +227,4 @@ static struct i2c_driver tlv320aic23b_driver = { | |||
227 | .id_table = tlv320aic23b_id, | 227 | .id_table = tlv320aic23b_id, |
228 | }; | 228 | }; |
229 | 229 | ||
230 | static __init int init_tlv320aic23b(void) | 230 | module_i2c_driver(tlv320aic23b_driver); |
231 | { | ||
232 | return i2c_add_driver(&tlv320aic23b_driver); | ||
233 | } | ||
234 | |||
235 | static __exit void exit_tlv320aic23b(void) | ||
236 | { | ||
237 | i2c_del_driver(&tlv320aic23b_driver); | ||
238 | } | ||
239 | |||
240 | module_init(init_tlv320aic23b); | ||
241 | module_exit(exit_tlv320aic23b); | ||
diff --git a/drivers/media/video/tm6000/tm6000-input.c b/drivers/media/video/tm6000/tm6000-input.c index 7844607dd45a..859eb90e4d56 100644 --- a/drivers/media/video/tm6000/tm6000-input.c +++ b/drivers/media/video/tm6000/tm6000-input.c | |||
@@ -481,8 +481,6 @@ int tm6000_ir_fini(struct tm6000_core *dev) | |||
481 | 481 | ||
482 | dprintk(2, "%s\n",__func__); | 482 | dprintk(2, "%s\n",__func__); |
483 | 483 | ||
484 | rc_unregister_device(ir->rc); | ||
485 | |||
486 | if (!ir->polling) | 484 | if (!ir->polling) |
487 | __tm6000_ir_int_stop(ir->rc); | 485 | __tm6000_ir_int_stop(ir->rc); |
488 | 486 | ||
@@ -492,6 +490,7 @@ int tm6000_ir_fini(struct tm6000_core *dev) | |||
492 | tm6000_flash_led(dev, 0); | 490 | tm6000_flash_led(dev, 0); |
493 | ir->pwled = 0; | 491 | ir->pwled = 0; |
494 | 492 | ||
493 | rc_unregister_device(ir->rc); | ||
495 | 494 | ||
496 | kfree(ir); | 495 | kfree(ir); |
497 | dev->ir = NULL; | 496 | dev->ir = NULL; |
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 4059ea178c2d..a5c6397ad591 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c | |||
@@ -380,6 +380,21 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
380 | tune_now = 0; | 380 | tune_now = 0; |
381 | break; | 381 | break; |
382 | } | 382 | } |
383 | case TUNER_XC5000C: | ||
384 | { | ||
385 | struct xc5000_config xc5000c_cfg = { | ||
386 | .i2c_address = t->i2c->addr, | ||
387 | /* if_khz will be set at dvb_attach() */ | ||
388 | .if_khz = 0, | ||
389 | .chip_id = XC5000C, | ||
390 | }; | ||
391 | |||
392 | if (!dvb_attach(xc5000_attach, | ||
393 | &t->fe, t->i2c->adapter, &xc5000c_cfg)) | ||
394 | goto attach_failed; | ||
395 | tune_now = 0; | ||
396 | break; | ||
397 | } | ||
383 | case TUNER_NXP_TDA18271: | 398 | case TUNER_NXP_TDA18271: |
384 | { | 399 | { |
385 | struct tda18271_config cfg = { | 400 | struct tda18271_config cfg = { |
@@ -1314,18 +1329,7 @@ static struct i2c_driver tuner_driver = { | |||
1314 | .id_table = tuner_id, | 1329 | .id_table = tuner_id, |
1315 | }; | 1330 | }; |
1316 | 1331 | ||
1317 | static __init int init_tuner(void) | 1332 | module_i2c_driver(tuner_driver); |
1318 | { | ||
1319 | return i2c_add_driver(&tuner_driver); | ||
1320 | } | ||
1321 | |||
1322 | static __exit void exit_tuner(void) | ||
1323 | { | ||
1324 | i2c_del_driver(&tuner_driver); | ||
1325 | } | ||
1326 | |||
1327 | module_init(init_tuner); | ||
1328 | module_exit(exit_tuner); | ||
1329 | 1333 | ||
1330 | MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners"); | 1334 | MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners"); |
1331 | MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); | 1335 | MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer"); |
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index f22dbef9b95b..c5b1a7365e4f 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c | |||
@@ -2078,15 +2078,4 @@ static struct i2c_driver tvaudio_driver = { | |||
2078 | .id_table = tvaudio_id, | 2078 | .id_table = tvaudio_id, |
2079 | }; | 2079 | }; |
2080 | 2080 | ||
2081 | static __init int init_tvaudio(void) | 2081 | module_i2c_driver(tvaudio_driver); |
2082 | { | ||
2083 | return i2c_add_driver(&tvaudio_driver); | ||
2084 | } | ||
2085 | |||
2086 | static __exit void exit_tvaudio(void) | ||
2087 | { | ||
2088 | i2c_del_driver(&tvaudio_driver); | ||
2089 | } | ||
2090 | |||
2091 | module_init(init_tvaudio); | ||
2092 | module_exit(exit_tvaudio); | ||
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 6103d1b1081e..3b6cf034976a 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c | |||
@@ -286,8 +286,16 @@ hauppauge_tuner[] = | |||
286 | { TUNER_ABSENT, "MaxLinear 301"}, | 286 | { TUNER_ABSENT, "MaxLinear 301"}, |
287 | { TUNER_ABSENT, "Mirics MSi001"}, | 287 | { TUNER_ABSENT, "Mirics MSi001"}, |
288 | { TUNER_ABSENT, "MaxLinear MxL241SF"}, | 288 | { TUNER_ABSENT, "MaxLinear MxL241SF"}, |
289 | { TUNER_ABSENT, "Xceive XC5000C"}, | 289 | { TUNER_XC5000C, "Xceive XC5000C"}, |
290 | { TUNER_ABSENT, "Montage M68TS2020"}, | 290 | { TUNER_ABSENT, "Montage M68TS2020"}, |
291 | { TUNER_ABSENT, "Siano SMS1530"}, | ||
292 | { TUNER_ABSENT, "Dibcom 7090"}, | ||
293 | { TUNER_ABSENT, "Xceive XC5200C"}, | ||
294 | { TUNER_ABSENT, "NXP 18273"}, | ||
295 | { TUNER_ABSENT, "Montage M88TS2022"}, | ||
296 | /* 180-189 */ | ||
297 | { TUNER_ABSENT, "NXP 18272M"}, | ||
298 | { TUNER_ABSENT, "NXP 18272S"}, | ||
291 | }; | 299 | }; |
292 | 300 | ||
293 | /* Use V4L2_IDENT_AMBIGUOUS for those audio 'chips' that are | 301 | /* Use V4L2_IDENT_AMBIGUOUS for those audio 'chips' that are |
diff --git a/drivers/media/video/tvp514x.c b/drivers/media/video/tvp514x.c index dd26cacd0556..cd615c1d6011 100644 --- a/drivers/media/video/tvp514x.c +++ b/drivers/media/video/tvp514x.c | |||
@@ -1163,15 +1163,4 @@ static struct i2c_driver tvp514x_driver = { | |||
1163 | .id_table = tvp514x_id, | 1163 | .id_table = tvp514x_id, |
1164 | }; | 1164 | }; |
1165 | 1165 | ||
1166 | static int __init tvp514x_init(void) | 1166 | module_i2c_driver(tvp514x_driver); |
1167 | { | ||
1168 | return i2c_add_driver(&tvp514x_driver); | ||
1169 | } | ||
1170 | |||
1171 | static void __exit tvp514x_exit(void) | ||
1172 | { | ||
1173 | i2c_del_driver(&tvp514x_driver); | ||
1174 | } | ||
1175 | |||
1176 | module_init(tvp514x_init); | ||
1177 | module_exit(tvp514x_exit); | ||
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 6be9910a6e24..1326e11cf4a9 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c | |||
@@ -17,6 +17,13 @@ | |||
17 | 17 | ||
18 | #include "tvp5150_reg.h" | 18 | #include "tvp5150_reg.h" |
19 | 19 | ||
20 | #define TVP5150_H_MAX 720 | ||
21 | #define TVP5150_V_MAX_525_60 480 | ||
22 | #define TVP5150_V_MAX_OTHERS 576 | ||
23 | #define TVP5150_MAX_CROP_LEFT 511 | ||
24 | #define TVP5150_MAX_CROP_TOP 127 | ||
25 | #define TVP5150_CROP_SHIFT 2 | ||
26 | |||
20 | MODULE_DESCRIPTION("Texas Instruments TVP5150A video decoder driver"); | 27 | MODULE_DESCRIPTION("Texas Instruments TVP5150A video decoder driver"); |
21 | MODULE_AUTHOR("Mauro Carvalho Chehab"); | 28 | MODULE_AUTHOR("Mauro Carvalho Chehab"); |
22 | MODULE_LICENSE("GPL"); | 29 | MODULE_LICENSE("GPL"); |
@@ -29,6 +36,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)"); | |||
29 | struct tvp5150 { | 36 | struct tvp5150 { |
30 | struct v4l2_subdev sd; | 37 | struct v4l2_subdev sd; |
31 | struct v4l2_ctrl_handler hdl; | 38 | struct v4l2_ctrl_handler hdl; |
39 | struct v4l2_rect rect; | ||
32 | 40 | ||
33 | v4l2_std_id norm; /* Current set standard */ | 41 | v4l2_std_id norm; /* Current set standard */ |
34 | u32 input; | 42 | u32 input; |
@@ -732,6 +740,13 @@ static int tvp5150_s_std(struct v4l2_subdev *sd, v4l2_std_id std) | |||
732 | if (decoder->norm == std) | 740 | if (decoder->norm == std) |
733 | return 0; | 741 | return 0; |
734 | 742 | ||
743 | /* Change cropping height limits */ | ||
744 | if (std & V4L2_STD_525_60) | ||
745 | decoder->rect.height = TVP5150_V_MAX_525_60; | ||
746 | else | ||
747 | decoder->rect.height = TVP5150_V_MAX_OTHERS; | ||
748 | |||
749 | |||
735 | return tvp5150_set_std(sd, std); | 750 | return tvp5150_set_std(sd, std); |
736 | } | 751 | } |
737 | 752 | ||
@@ -828,11 +843,8 @@ static int tvp5150_mbus_fmt(struct v4l2_subdev *sd, | |||
828 | else | 843 | else |
829 | std = decoder->norm; | 844 | std = decoder->norm; |
830 | 845 | ||
831 | f->width = 720; | 846 | f->width = decoder->rect.width; |
832 | if (std & V4L2_STD_525_60) | 847 | f->height = decoder->rect.height; |
833 | f->height = 480; | ||
834 | else | ||
835 | f->height = 576; | ||
836 | 848 | ||
837 | f->code = V4L2_MBUS_FMT_YUYV8_2X8; | 849 | f->code = V4L2_MBUS_FMT_YUYV8_2X8; |
838 | f->field = V4L2_FIELD_SEQ_TB; | 850 | f->field = V4L2_FIELD_SEQ_TB; |
@@ -843,6 +855,99 @@ static int tvp5150_mbus_fmt(struct v4l2_subdev *sd, | |||
843 | return 0; | 855 | return 0; |
844 | } | 856 | } |
845 | 857 | ||
858 | static int tvp5150_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | ||
859 | { | ||
860 | struct v4l2_rect rect = a->c; | ||
861 | struct tvp5150 *decoder = to_tvp5150(sd); | ||
862 | v4l2_std_id std; | ||
863 | int hmax; | ||
864 | |||
865 | v4l2_dbg(1, debug, sd, "%s left=%d, top=%d, width=%d, height=%d\n", | ||
866 | __func__, rect.left, rect.top, rect.width, rect.height); | ||
867 | |||
868 | if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
869 | return -EINVAL; | ||
870 | |||
871 | /* tvp5150 has some special limits */ | ||
872 | rect.left = clamp(rect.left, 0, TVP5150_MAX_CROP_LEFT); | ||
873 | rect.width = clamp(rect.width, | ||
874 | TVP5150_H_MAX - TVP5150_MAX_CROP_LEFT - rect.left, | ||
875 | TVP5150_H_MAX - rect.left); | ||
876 | rect.top = clamp(rect.top, 0, TVP5150_MAX_CROP_TOP); | ||
877 | |||
878 | /* Calculate height based on current standard */ | ||
879 | if (decoder->norm == V4L2_STD_ALL) | ||
880 | std = tvp5150_read_std(sd); | ||
881 | else | ||
882 | std = decoder->norm; | ||
883 | |||
884 | if (std & V4L2_STD_525_60) | ||
885 | hmax = TVP5150_V_MAX_525_60; | ||
886 | else | ||
887 | hmax = TVP5150_V_MAX_OTHERS; | ||
888 | |||
889 | rect.height = clamp(rect.height, | ||
890 | hmax - TVP5150_MAX_CROP_TOP - rect.top, | ||
891 | hmax - rect.top); | ||
892 | |||
893 | tvp5150_write(sd, TVP5150_VERT_BLANKING_START, rect.top); | ||
894 | tvp5150_write(sd, TVP5150_VERT_BLANKING_STOP, | ||
895 | rect.top + rect.height - hmax); | ||
896 | tvp5150_write(sd, TVP5150_ACT_VD_CROP_ST_MSB, | ||
897 | rect.left >> TVP5150_CROP_SHIFT); | ||
898 | tvp5150_write(sd, TVP5150_ACT_VD_CROP_ST_LSB, | ||
899 | rect.left | (1 << TVP5150_CROP_SHIFT)); | ||
900 | tvp5150_write(sd, TVP5150_ACT_VD_CROP_STP_MSB, | ||
901 | (rect.left + rect.width - TVP5150_MAX_CROP_LEFT) >> | ||
902 | TVP5150_CROP_SHIFT); | ||
903 | tvp5150_write(sd, TVP5150_ACT_VD_CROP_STP_LSB, | ||
904 | rect.left + rect.width - TVP5150_MAX_CROP_LEFT); | ||
905 | |||
906 | decoder->rect = rect; | ||
907 | |||
908 | return 0; | ||
909 | } | ||
910 | |||
911 | static int tvp5150_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | ||
912 | { | ||
913 | struct tvp5150 *decoder = container_of(sd, struct tvp5150, sd); | ||
914 | |||
915 | a->c = decoder->rect; | ||
916 | a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
917 | |||
918 | return 0; | ||
919 | } | ||
920 | |||
921 | static int tvp5150_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) | ||
922 | { | ||
923 | struct tvp5150 *decoder = container_of(sd, struct tvp5150, sd); | ||
924 | v4l2_std_id std; | ||
925 | |||
926 | if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
927 | return -EINVAL; | ||
928 | |||
929 | a->bounds.left = 0; | ||
930 | a->bounds.top = 0; | ||
931 | a->bounds.width = TVP5150_H_MAX; | ||
932 | |||
933 | /* Calculate height based on current standard */ | ||
934 | if (decoder->norm == V4L2_STD_ALL) | ||
935 | std = tvp5150_read_std(sd); | ||
936 | else | ||
937 | std = decoder->norm; | ||
938 | |||
939 | if (std & V4L2_STD_525_60) | ||
940 | a->bounds.height = TVP5150_V_MAX_525_60; | ||
941 | else | ||
942 | a->bounds.height = TVP5150_V_MAX_OTHERS; | ||
943 | |||
944 | a->defrect = a->bounds; | ||
945 | a->pixelaspect.numerator = 1; | ||
946 | a->pixelaspect.denominator = 1; | ||
947 | |||
948 | return 0; | ||
949 | } | ||
950 | |||
846 | /**************************************************************************** | 951 | /**************************************************************************** |
847 | I2C Command | 952 | I2C Command |
848 | ****************************************************************************/ | 953 | ****************************************************************************/ |
@@ -998,6 +1103,10 @@ static const struct v4l2_subdev_video_ops tvp5150_video_ops = { | |||
998 | .enum_mbus_fmt = tvp5150_enum_mbus_fmt, | 1103 | .enum_mbus_fmt = tvp5150_enum_mbus_fmt, |
999 | .s_mbus_fmt = tvp5150_mbus_fmt, | 1104 | .s_mbus_fmt = tvp5150_mbus_fmt, |
1000 | .try_mbus_fmt = tvp5150_mbus_fmt, | 1105 | .try_mbus_fmt = tvp5150_mbus_fmt, |
1106 | .g_mbus_fmt = tvp5150_mbus_fmt, | ||
1107 | .s_crop = tvp5150_s_crop, | ||
1108 | .g_crop = tvp5150_g_crop, | ||
1109 | .cropcap = tvp5150_cropcap, | ||
1001 | }; | 1110 | }; |
1002 | 1111 | ||
1003 | static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { | 1112 | static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { |
@@ -1083,6 +1192,15 @@ static int tvp5150_probe(struct i2c_client *c, | |||
1083 | } | 1192 | } |
1084 | v4l2_ctrl_handler_setup(&core->hdl); | 1193 | v4l2_ctrl_handler_setup(&core->hdl); |
1085 | 1194 | ||
1195 | /* Default is no cropping */ | ||
1196 | core->rect.top = 0; | ||
1197 | if (tvp5150_read_std(sd) & V4L2_STD_525_60) | ||
1198 | core->rect.height = TVP5150_V_MAX_525_60; | ||
1199 | else | ||
1200 | core->rect.height = TVP5150_V_MAX_OTHERS; | ||
1201 | core->rect.left = 0; | ||
1202 | core->rect.width = TVP5150_H_MAX; | ||
1203 | |||
1086 | if (debug > 1) | 1204 | if (debug > 1) |
1087 | tvp5150_log_status(sd); | 1205 | tvp5150_log_status(sd); |
1088 | return 0; | 1206 | return 0; |
@@ -1121,15 +1239,4 @@ static struct i2c_driver tvp5150_driver = { | |||
1121 | .id_table = tvp5150_id, | 1239 | .id_table = tvp5150_id, |
1122 | }; | 1240 | }; |
1123 | 1241 | ||
1124 | static __init int init_tvp5150(void) | 1242 | module_i2c_driver(tvp5150_driver); |
1125 | { | ||
1126 | return i2c_add_driver(&tvp5150_driver); | ||
1127 | } | ||
1128 | |||
1129 | static __exit void exit_tvp5150(void) | ||
1130 | { | ||
1131 | i2c_del_driver(&tvp5150_driver); | ||
1132 | } | ||
1133 | |||
1134 | module_init(init_tvp5150); | ||
1135 | module_exit(exit_tvp5150); | ||
diff --git a/drivers/media/video/tvp7002.c b/drivers/media/video/tvp7002.c index 236c559d5f51..d7676d85c4df 100644 --- a/drivers/media/video/tvp7002.c +++ b/drivers/media/video/tvp7002.c | |||
@@ -1069,27 +1069,4 @@ static struct i2c_driver tvp7002_driver = { | |||
1069 | .id_table = tvp7002_id, | 1069 | .id_table = tvp7002_id, |
1070 | }; | 1070 | }; |
1071 | 1071 | ||
1072 | /* | 1072 | module_i2c_driver(tvp7002_driver); |
1073 | * tvp7002_init - Initialize driver via I2C interface | ||
1074 | * | ||
1075 | * Register the TVP7002 driver. | ||
1076 | * Return 0 on success or error code on failure. | ||
1077 | */ | ||
1078 | static int __init tvp7002_init(void) | ||
1079 | { | ||
1080 | return i2c_add_driver(&tvp7002_driver); | ||
1081 | } | ||
1082 | |||
1083 | /* | ||
1084 | * tvp7002_exit - Remove driver via I2C interface | ||
1085 | * | ||
1086 | * Unregister the TVP7002 driver. | ||
1087 | * Returns nothing. | ||
1088 | */ | ||
1089 | static void __exit tvp7002_exit(void) | ||
1090 | { | ||
1091 | i2c_del_driver(&tvp7002_driver); | ||
1092 | } | ||
1093 | |||
1094 | module_init(tvp7002_init); | ||
1095 | module_exit(tvp7002_exit); | ||
diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index a514fa61116c..8768efb8508a 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c | |||
@@ -951,21 +951,7 @@ static struct i2c_driver tw9910_i2c_driver = { | |||
951 | .id_table = tw9910_id, | 951 | .id_table = tw9910_id, |
952 | }; | 952 | }; |
953 | 953 | ||
954 | /* | 954 | module_i2c_driver(tw9910_i2c_driver); |
955 | * module function | ||
956 | */ | ||
957 | static int __init tw9910_module_init(void) | ||
958 | { | ||
959 | return i2c_add_driver(&tw9910_i2c_driver); | ||
960 | } | ||
961 | |||
962 | static void __exit tw9910_module_exit(void) | ||
963 | { | ||
964 | i2c_del_driver(&tw9910_i2c_driver); | ||
965 | } | ||
966 | |||
967 | module_init(tw9910_module_init); | ||
968 | module_exit(tw9910_module_exit); | ||
969 | 955 | ||
970 | MODULE_DESCRIPTION("SoC Camera driver for tw9910"); | 956 | MODULE_DESCRIPTION("SoC Camera driver for tw9910"); |
971 | MODULE_AUTHOR("Kuninori Morimoto"); | 957 | MODULE_AUTHOR("Kuninori Morimoto"); |
diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c index 1aab96a88203..1e7446542091 100644 --- a/drivers/media/video/upd64031a.c +++ b/drivers/media/video/upd64031a.c | |||
@@ -271,15 +271,4 @@ static struct i2c_driver upd64031a_driver = { | |||
271 | .id_table = upd64031a_id, | 271 | .id_table = upd64031a_id, |
272 | }; | 272 | }; |
273 | 273 | ||
274 | static __init int init_upd64031a(void) | 274 | module_i2c_driver(upd64031a_driver); |
275 | { | ||
276 | return i2c_add_driver(&upd64031a_driver); | ||
277 | } | ||
278 | |||
279 | static __exit void exit_upd64031a(void) | ||
280 | { | ||
281 | i2c_del_driver(&upd64031a_driver); | ||
282 | } | ||
283 | |||
284 | module_init(init_upd64031a); | ||
285 | module_exit(exit_upd64031a); | ||
diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c index 65d065aa6091..75d6acc62018 100644 --- a/drivers/media/video/upd64083.c +++ b/drivers/media/video/upd64083.c | |||
@@ -243,15 +243,4 @@ static struct i2c_driver upd64083_driver = { | |||
243 | .id_table = upd64083_id, | 243 | .id_table = upd64083_id, |
244 | }; | 244 | }; |
245 | 245 | ||
246 | static __init int init_upd64083(void) | 246 | module_i2c_driver(upd64083_driver); |
247 | { | ||
248 | return i2c_add_driver(&upd64083_driver); | ||
249 | } | ||
250 | |||
251 | static __exit void exit_upd64083(void) | ||
252 | { | ||
253 | i2c_del_driver(&upd64083_driver); | ||
254 | } | ||
255 | |||
256 | module_init(init_upd64083); | ||
257 | module_exit(exit_upd64083); | ||
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index a240d43d15d1..1d131720b6d7 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c | |||
@@ -23,6 +23,7 @@ | |||
23 | * codec can't handle MJPEG data. | 23 | * codec can't handle MJPEG data. |
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <linux/atomic.h> | ||
26 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
27 | #include <linux/list.h> | 28 | #include <linux/list.h> |
28 | #include <linux/module.h> | 29 | #include <linux/module.h> |
@@ -32,7 +33,6 @@ | |||
32 | #include <linux/vmalloc.h> | 33 | #include <linux/vmalloc.h> |
33 | #include <linux/wait.h> | 34 | #include <linux/wait.h> |
34 | #include <linux/version.h> | 35 | #include <linux/version.h> |
35 | #include <asm/atomic.h> | ||
36 | #include <asm/unaligned.h> | 36 | #include <asm/unaligned.h> |
37 | 37 | ||
38 | #include <media/v4l2-common.h> | 38 | #include <media/v4l2-common.h> |
@@ -2139,6 +2139,15 @@ static struct usb_device_id uvc_ids[] = { | |||
2139 | .bInterfaceSubClass = 1, | 2139 | .bInterfaceSubClass = 1, |
2140 | .bInterfaceProtocol = 0, | 2140 | .bInterfaceProtocol = 0, |
2141 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | 2141 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, |
2142 | /* Dell XPS m1530 */ | ||
2143 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
2144 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
2145 | .idVendor = 0x05a9, | ||
2146 | .idProduct = 0x2640, | ||
2147 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
2148 | .bInterfaceSubClass = 1, | ||
2149 | .bInterfaceProtocol = 0, | ||
2150 | .driver_info = UVC_QUIRK_PROBE_DEF }, | ||
2142 | /* Apple Built-In iSight */ | 2151 | /* Apple Built-In iSight */ |
2143 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 2152 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
2144 | | USB_DEVICE_ID_MATCH_INT_INFO, | 2153 | | USB_DEVICE_ID_MATCH_INT_INFO, |
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index 518f77d3a4d8..8f54e24e3f35 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c | |||
@@ -126,7 +126,7 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type, | |||
126 | int drop_corrupted) | 126 | int drop_corrupted) |
127 | { | 127 | { |
128 | queue->queue.type = type; | 128 | queue->queue.type = type; |
129 | queue->queue.io_modes = VB2_MMAP; | 129 | queue->queue.io_modes = VB2_MMAP | VB2_USERPTR; |
130 | queue->queue.drv_priv = queue; | 130 | queue->queue.drv_priv = queue; |
131 | queue->queue.buf_struct_size = sizeof(struct uvc_buffer); | 131 | queue->queue.buf_struct_size = sizeof(struct uvc_buffer); |
132 | queue->queue.ops = &uvc_queue_qops; | 132 | queue->queue.ops = &uvc_queue_qops; |
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index 2ae4f880ea05..ff2cdddf9bc6 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c | |||
@@ -11,6 +11,7 @@ | |||
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/compat.h> | ||
14 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
15 | #include <linux/version.h> | 16 | #include <linux/version.h> |
16 | #include <linux/list.h> | 17 | #include <linux/list.h> |
@@ -1012,7 +1013,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
1012 | 1013 | ||
1013 | default: | 1014 | default: |
1014 | uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n", cmd); | 1015 | uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n", cmd); |
1015 | return -EINVAL; | 1016 | return -ENOTTY; |
1016 | } | 1017 | } |
1017 | 1018 | ||
1018 | return ret; | 1019 | return ret; |
@@ -1030,6 +1031,207 @@ static long uvc_v4l2_ioctl(struct file *file, | |||
1030 | return video_usercopy(file, cmd, arg, uvc_v4l2_do_ioctl); | 1031 | return video_usercopy(file, cmd, arg, uvc_v4l2_do_ioctl); |
1031 | } | 1032 | } |
1032 | 1033 | ||
1034 | #ifdef CONFIG_COMPAT | ||
1035 | struct uvc_xu_control_mapping32 { | ||
1036 | __u32 id; | ||
1037 | __u8 name[32]; | ||
1038 | __u8 entity[16]; | ||
1039 | __u8 selector; | ||
1040 | |||
1041 | __u8 size; | ||
1042 | __u8 offset; | ||
1043 | __u32 v4l2_type; | ||
1044 | __u32 data_type; | ||
1045 | |||
1046 | compat_caddr_t menu_info; | ||
1047 | __u32 menu_count; | ||
1048 | |||
1049 | __u32 reserved[4]; | ||
1050 | }; | ||
1051 | |||
1052 | static int uvc_v4l2_get_xu_mapping(struct uvc_xu_control_mapping *kp, | ||
1053 | const struct uvc_xu_control_mapping32 __user *up) | ||
1054 | { | ||
1055 | struct uvc_menu_info __user *umenus; | ||
1056 | struct uvc_menu_info __user *kmenus; | ||
1057 | compat_caddr_t p; | ||
1058 | |||
1059 | if (!access_ok(VERIFY_READ, up, sizeof(*up)) || | ||
1060 | __copy_from_user(kp, up, offsetof(typeof(*up), menu_info)) || | ||
1061 | __get_user(kp->menu_count, &up->menu_count)) | ||
1062 | return -EFAULT; | ||
1063 | |||
1064 | memset(kp->reserved, 0, sizeof(kp->reserved)); | ||
1065 | |||
1066 | if (kp->menu_count == 0) { | ||
1067 | kp->menu_info = NULL; | ||
1068 | return 0; | ||
1069 | } | ||
1070 | |||
1071 | if (__get_user(p, &up->menu_info)) | ||
1072 | return -EFAULT; | ||
1073 | umenus = compat_ptr(p); | ||
1074 | if (!access_ok(VERIFY_READ, umenus, kp->menu_count * sizeof(*umenus))) | ||
1075 | return -EFAULT; | ||
1076 | |||
1077 | kmenus = compat_alloc_user_space(kp->menu_count * sizeof(*kmenus)); | ||
1078 | if (kmenus == NULL) | ||
1079 | return -EFAULT; | ||
1080 | kp->menu_info = kmenus; | ||
1081 | |||
1082 | if (copy_in_user(kmenus, umenus, kp->menu_count * sizeof(*umenus))) | ||
1083 | return -EFAULT; | ||
1084 | |||
1085 | return 0; | ||
1086 | } | ||
1087 | |||
1088 | static int uvc_v4l2_put_xu_mapping(const struct uvc_xu_control_mapping *kp, | ||
1089 | struct uvc_xu_control_mapping32 __user *up) | ||
1090 | { | ||
1091 | struct uvc_menu_info __user *umenus; | ||
1092 | struct uvc_menu_info __user *kmenus = kp->menu_info; | ||
1093 | compat_caddr_t p; | ||
1094 | |||
1095 | if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || | ||
1096 | __copy_to_user(up, kp, offsetof(typeof(*up), menu_info)) || | ||
1097 | __put_user(kp->menu_count, &up->menu_count)) | ||
1098 | return -EFAULT; | ||
1099 | |||
1100 | __clear_user(up->reserved, sizeof(up->reserved)); | ||
1101 | |||
1102 | if (kp->menu_count == 0) | ||
1103 | return 0; | ||
1104 | |||
1105 | if (get_user(p, &up->menu_info)) | ||
1106 | return -EFAULT; | ||
1107 | umenus = compat_ptr(p); | ||
1108 | if (!access_ok(VERIFY_WRITE, umenus, kp->menu_count * sizeof(*umenus))) | ||
1109 | return -EFAULT; | ||
1110 | |||
1111 | if (copy_in_user(umenus, kmenus, kp->menu_count * sizeof(*umenus))) | ||
1112 | return -EFAULT; | ||
1113 | |||
1114 | return 0; | ||
1115 | } | ||
1116 | |||
1117 | struct uvc_xu_control_query32 { | ||
1118 | __u8 unit; | ||
1119 | __u8 selector; | ||
1120 | __u8 query; | ||
1121 | __u16 size; | ||
1122 | compat_caddr_t data; | ||
1123 | }; | ||
1124 | |||
1125 | static int uvc_v4l2_get_xu_query(struct uvc_xu_control_query *kp, | ||
1126 | const struct uvc_xu_control_query32 __user *up) | ||
1127 | { | ||
1128 | u8 __user *udata; | ||
1129 | u8 __user *kdata; | ||
1130 | compat_caddr_t p; | ||
1131 | |||
1132 | if (!access_ok(VERIFY_READ, up, sizeof(*up)) || | ||
1133 | __copy_from_user(kp, up, offsetof(typeof(*up), data))) | ||
1134 | return -EFAULT; | ||
1135 | |||
1136 | if (kp->size == 0) { | ||
1137 | kp->data = NULL; | ||
1138 | return 0; | ||
1139 | } | ||
1140 | |||
1141 | if (__get_user(p, &up->data)) | ||
1142 | return -EFAULT; | ||
1143 | udata = compat_ptr(p); | ||
1144 | if (!access_ok(VERIFY_READ, udata, kp->size)) | ||
1145 | return -EFAULT; | ||
1146 | |||
1147 | kdata = compat_alloc_user_space(kp->size); | ||
1148 | if (kdata == NULL) | ||
1149 | return -EFAULT; | ||
1150 | kp->data = kdata; | ||
1151 | |||
1152 | if (copy_in_user(kdata, udata, kp->size)) | ||
1153 | return -EFAULT; | ||
1154 | |||
1155 | return 0; | ||
1156 | } | ||
1157 | |||
1158 | static int uvc_v4l2_put_xu_query(const struct uvc_xu_control_query *kp, | ||
1159 | struct uvc_xu_control_query32 __user *up) | ||
1160 | { | ||
1161 | u8 __user *udata; | ||
1162 | u8 __user *kdata = kp->data; | ||
1163 | compat_caddr_t p; | ||
1164 | |||
1165 | if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || | ||
1166 | __copy_to_user(up, kp, offsetof(typeof(*up), data))) | ||
1167 | return -EFAULT; | ||
1168 | |||
1169 | if (kp->size == 0) | ||
1170 | return 0; | ||
1171 | |||
1172 | if (get_user(p, &up->data)) | ||
1173 | return -EFAULT; | ||
1174 | udata = compat_ptr(p); | ||
1175 | if (!access_ok(VERIFY_READ, udata, kp->size)) | ||
1176 | return -EFAULT; | ||
1177 | |||
1178 | if (copy_in_user(udata, kdata, kp->size)) | ||
1179 | return -EFAULT; | ||
1180 | |||
1181 | return 0; | ||
1182 | } | ||
1183 | |||
1184 | #define UVCIOC_CTRL_MAP32 _IOWR('u', 0x20, struct uvc_xu_control_mapping32) | ||
1185 | #define UVCIOC_CTRL_QUERY32 _IOWR('u', 0x21, struct uvc_xu_control_query32) | ||
1186 | |||
1187 | static long uvc_v4l2_compat_ioctl32(struct file *file, | ||
1188 | unsigned int cmd, unsigned long arg) | ||
1189 | { | ||
1190 | union { | ||
1191 | struct uvc_xu_control_mapping xmap; | ||
1192 | struct uvc_xu_control_query xqry; | ||
1193 | } karg; | ||
1194 | void __user *up = compat_ptr(arg); | ||
1195 | mm_segment_t old_fs; | ||
1196 | long ret; | ||
1197 | |||
1198 | switch (cmd) { | ||
1199 | case UVCIOC_CTRL_MAP32: | ||
1200 | cmd = UVCIOC_CTRL_MAP; | ||
1201 | ret = uvc_v4l2_get_xu_mapping(&karg.xmap, up); | ||
1202 | break; | ||
1203 | |||
1204 | case UVCIOC_CTRL_QUERY32: | ||
1205 | cmd = UVCIOC_CTRL_QUERY; | ||
1206 | ret = uvc_v4l2_get_xu_query(&karg.xqry, up); | ||
1207 | break; | ||
1208 | |||
1209 | default: | ||
1210 | return -ENOIOCTLCMD; | ||
1211 | } | ||
1212 | |||
1213 | old_fs = get_fs(); | ||
1214 | set_fs(KERNEL_DS); | ||
1215 | ret = uvc_v4l2_ioctl(file, cmd, (unsigned long)&karg); | ||
1216 | set_fs(old_fs); | ||
1217 | |||
1218 | if (ret < 0) | ||
1219 | return ret; | ||
1220 | |||
1221 | switch (cmd) { | ||
1222 | case UVCIOC_CTRL_MAP: | ||
1223 | ret = uvc_v4l2_put_xu_mapping(&karg.xmap, up); | ||
1224 | break; | ||
1225 | |||
1226 | case UVCIOC_CTRL_QUERY: | ||
1227 | ret = uvc_v4l2_put_xu_query(&karg.xqry, up); | ||
1228 | break; | ||
1229 | } | ||
1230 | |||
1231 | return ret; | ||
1232 | } | ||
1233 | #endif | ||
1234 | |||
1033 | static ssize_t uvc_v4l2_read(struct file *file, char __user *data, | 1235 | static ssize_t uvc_v4l2_read(struct file *file, char __user *data, |
1034 | size_t count, loff_t *ppos) | 1236 | size_t count, loff_t *ppos) |
1035 | { | 1237 | { |
@@ -1076,6 +1278,9 @@ const struct v4l2_file_operations uvc_fops = { | |||
1076 | .open = uvc_v4l2_open, | 1278 | .open = uvc_v4l2_open, |
1077 | .release = uvc_v4l2_release, | 1279 | .release = uvc_v4l2_release, |
1078 | .unlocked_ioctl = uvc_v4l2_ioctl, | 1280 | .unlocked_ioctl = uvc_v4l2_ioctl, |
1281 | #ifdef CONFIG_COMPAT | ||
1282 | .compat_ioctl32 = uvc_v4l2_compat_ioctl32, | ||
1283 | #endif | ||
1079 | .read = uvc_v4l2_read, | 1284 | .read = uvc_v4l2_read, |
1080 | .mmap = uvc_v4l2_mmap, | 1285 | .mmap = uvc_v4l2_mmap, |
1081 | .poll = uvc_v4l2_poll, | 1286 | .poll = uvc_v4l2_poll, |
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index c7e69b8f81c9..4a44f9a1bae0 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c | |||
@@ -611,9 +611,11 @@ void uvc_video_clock_update(struct uvc_streaming *stream, | |||
611 | delta_stc = buf->pts - (1UL << 31); | 611 | delta_stc = buf->pts - (1UL << 31); |
612 | x1 = first->dev_stc - delta_stc; | 612 | x1 = first->dev_stc - delta_stc; |
613 | x2 = last->dev_stc - delta_stc; | 613 | x2 = last->dev_stc - delta_stc; |
614 | if (x1 == x2) | ||
615 | goto done; | ||
616 | |||
614 | y1 = (first->dev_sof + 2048) << 16; | 617 | y1 = (first->dev_sof + 2048) << 16; |
615 | y2 = (last->dev_sof + 2048) << 16; | 618 | y2 = (last->dev_sof + 2048) << 16; |
616 | |||
617 | if (y2 < y1) | 619 | if (y2 < y1) |
618 | y2 += 2048 << 16; | 620 | y2 += 2048 << 16; |
619 | 621 | ||
@@ -631,14 +633,16 @@ void uvc_video_clock_update(struct uvc_streaming *stream, | |||
631 | x1, x2, y1, y2, clock->sof_offset); | 633 | x1, x2, y1, y2, clock->sof_offset); |
632 | 634 | ||
633 | /* Second step, SOF to host clock conversion. */ | 635 | /* Second step, SOF to host clock conversion. */ |
634 | ts = timespec_sub(last->host_ts, first->host_ts); | ||
635 | x1 = (uvc_video_clock_host_sof(first) + 2048) << 16; | 636 | x1 = (uvc_video_clock_host_sof(first) + 2048) << 16; |
636 | x2 = (uvc_video_clock_host_sof(last) + 2048) << 16; | 637 | x2 = (uvc_video_clock_host_sof(last) + 2048) << 16; |
637 | y1 = NSEC_PER_SEC; | ||
638 | y2 = (ts.tv_sec + 1) * NSEC_PER_SEC + ts.tv_nsec; | ||
639 | |||
640 | if (x2 < x1) | 638 | if (x2 < x1) |
641 | x2 += 2048 << 16; | 639 | x2 += 2048 << 16; |
640 | if (x1 == x2) | ||
641 | goto done; | ||
642 | |||
643 | ts = timespec_sub(last->host_ts, first->host_ts); | ||
644 | y1 = NSEC_PER_SEC; | ||
645 | y2 = (ts.tv_sec + 1) * NSEC_PER_SEC + ts.tv_nsec; | ||
642 | 646 | ||
643 | /* Interpolated and host SOF timestamps can wrap around at slightly | 647 | /* Interpolated and host SOF timestamps can wrap around at slightly |
644 | * different times. Handle this by adding or removing 2048 to or from | 648 | * different times. Handle this by adding or removing 2048 to or from |
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 5c6100fb4072..1baec8393306 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c | |||
@@ -55,7 +55,6 @@ | |||
55 | #include <linux/spi/spi.h> | 55 | #include <linux/spi/spi.h> |
56 | #endif | 56 | #endif |
57 | #include <asm/uaccess.h> | 57 | #include <asm/uaccess.h> |
58 | #include <asm/system.h> | ||
59 | #include <asm/pgtable.h> | 58 | #include <asm/pgtable.h> |
60 | #include <asm/io.h> | 59 | #include <asm/io.h> |
61 | #include <asm/div64.h> | 60 | #include <asm/div64.h> |
diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c index af4419e6c658..2829d256e4b7 100644 --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c | |||
@@ -14,12 +14,11 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/compat.h> | 16 | #include <linux/compat.h> |
17 | #include <linux/videodev2.h> | ||
18 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/videodev2.h> | ||
19 | #include <media/v4l2-dev.h> | ||
19 | #include <media/v4l2-ioctl.h> | 20 | #include <media/v4l2-ioctl.h> |
20 | 21 | ||
21 | #ifdef CONFIG_COMPAT | ||
22 | |||
23 | static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 22 | static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
24 | { | 23 | { |
25 | long ret = -ENOIOCTLCMD; | 24 | long ret = -ENOIOCTLCMD; |
@@ -937,6 +936,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar | |||
937 | 936 | ||
938 | long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) | 937 | long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) |
939 | { | 938 | { |
939 | struct video_device *vdev = video_devdata(file); | ||
940 | long ret = -ENOIOCTLCMD; | 940 | long ret = -ENOIOCTLCMD; |
941 | 941 | ||
942 | if (!file->f_op->unlocked_ioctl) | 942 | if (!file->f_op->unlocked_ioctl) |
@@ -1005,6 +1005,8 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) | |||
1005 | case VIDIOC_G_ENC_INDEX: | 1005 | case VIDIOC_G_ENC_INDEX: |
1006 | case VIDIOC_ENCODER_CMD: | 1006 | case VIDIOC_ENCODER_CMD: |
1007 | case VIDIOC_TRY_ENCODER_CMD: | 1007 | case VIDIOC_TRY_ENCODER_CMD: |
1008 | case VIDIOC_DECODER_CMD: | ||
1009 | case VIDIOC_TRY_DECODER_CMD: | ||
1008 | case VIDIOC_DBG_S_REGISTER: | 1010 | case VIDIOC_DBG_S_REGISTER: |
1009 | case VIDIOC_DBG_G_REGISTER: | 1011 | case VIDIOC_DBG_G_REGISTER: |
1010 | case VIDIOC_DBG_G_CHIP_IDENT: | 1012 | case VIDIOC_DBG_G_CHIP_IDENT: |
@@ -1025,14 +1027,16 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) | |||
1025 | break; | 1027 | break; |
1026 | 1028 | ||
1027 | default: | 1029 | default: |
1028 | printk(KERN_WARNING "compat_ioctl32: " | 1030 | if (vdev->fops->compat_ioctl32) |
1029 | "unknown ioctl '%c', dir=%d, #%d (0x%08x)\n", | 1031 | ret = vdev->fops->compat_ioctl32(file, cmd, arg); |
1030 | _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd); | 1032 | |
1033 | if (ret == -ENOIOCTLCMD) | ||
1034 | printk(KERN_WARNING "compat_ioctl32: " | ||
1035 | "unknown ioctl '%c', dir=%d, #%d (0x%08x)\n", | ||
1036 | _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), | ||
1037 | cmd); | ||
1031 | break; | 1038 | break; |
1032 | } | 1039 | } |
1033 | return ret; | 1040 | return ret; |
1034 | } | 1041 | } |
1035 | EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32); | 1042 | EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32); |
1036 | #endif | ||
1037 | |||
1038 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c index cccd42be718a..18015c0a8d31 100644 --- a/drivers/media/video/v4l2-ctrls.c +++ b/drivers/media/video/v4l2-ctrls.c | |||
@@ -175,6 +175,15 @@ const char * const *v4l2_ctrl_get_menu(u32 id) | |||
175 | "16-bit CRC", | 175 | "16-bit CRC", |
176 | NULL | 176 | NULL |
177 | }; | 177 | }; |
178 | static const char * const mpeg_audio_dec_playback[] = { | ||
179 | "Auto", | ||
180 | "Stereo", | ||
181 | "Left", | ||
182 | "Right", | ||
183 | "Mono", | ||
184 | "Swapped Stereo", | ||
185 | NULL | ||
186 | }; | ||
178 | static const char * const mpeg_video_encoding[] = { | 187 | static const char * const mpeg_video_encoding[] = { |
179 | "MPEG-1", | 188 | "MPEG-1", |
180 | "MPEG-2", | 189 | "MPEG-2", |
@@ -236,8 +245,8 @@ const char * const *v4l2_ctrl_get_menu(u32 id) | |||
236 | }; | 245 | }; |
237 | static const char * const tune_preemphasis[] = { | 246 | static const char * const tune_preemphasis[] = { |
238 | "No Preemphasis", | 247 | "No Preemphasis", |
239 | "50 useconds", | 248 | "50 Microseconds", |
240 | "75 useconds", | 249 | "75 Microseconds", |
241 | NULL, | 250 | NULL, |
242 | }; | 251 | }; |
243 | static const char * const header_mode[] = { | 252 | static const char * const header_mode[] = { |
@@ -334,7 +343,7 @@ const char * const *v4l2_ctrl_get_menu(u32 id) | |||
334 | }; | 343 | }; |
335 | static const char * const mpeg4_profile[] = { | 344 | static const char * const mpeg4_profile[] = { |
336 | "Simple", | 345 | "Simple", |
337 | "Adcanved Simple", | 346 | "Advanced Simple", |
338 | "Core", | 347 | "Core", |
339 | "Simple Scalable", | 348 | "Simple Scalable", |
340 | "Advanced Coding Efficency", | 349 | "Advanced Coding Efficency", |
@@ -353,6 +362,16 @@ const char * const *v4l2_ctrl_get_menu(u32 id) | |||
353 | NULL, | 362 | NULL, |
354 | }; | 363 | }; |
355 | 364 | ||
365 | static const char * const jpeg_chroma_subsampling[] = { | ||
366 | "4:4:4", | ||
367 | "4:2:2", | ||
368 | "4:2:0", | ||
369 | "4:1:1", | ||
370 | "4:1:0", | ||
371 | "Gray", | ||
372 | NULL, | ||
373 | }; | ||
374 | |||
356 | switch (id) { | 375 | switch (id) { |
357 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: | 376 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: |
358 | return mpeg_audio_sampling_freq; | 377 | return mpeg_audio_sampling_freq; |
@@ -374,6 +393,9 @@ const char * const *v4l2_ctrl_get_menu(u32 id) | |||
374 | return mpeg_audio_emphasis; | 393 | return mpeg_audio_emphasis; |
375 | case V4L2_CID_MPEG_AUDIO_CRC: | 394 | case V4L2_CID_MPEG_AUDIO_CRC: |
376 | return mpeg_audio_crc; | 395 | return mpeg_audio_crc; |
396 | case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK: | ||
397 | case V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK: | ||
398 | return mpeg_audio_dec_playback; | ||
377 | case V4L2_CID_MPEG_VIDEO_ENCODING: | 399 | case V4L2_CID_MPEG_VIDEO_ENCODING: |
378 | return mpeg_video_encoding; | 400 | return mpeg_video_encoding; |
379 | case V4L2_CID_MPEG_VIDEO_ASPECT: | 401 | case V4L2_CID_MPEG_VIDEO_ASPECT: |
@@ -414,6 +436,9 @@ const char * const *v4l2_ctrl_get_menu(u32 id) | |||
414 | return mpeg_mpeg4_level; | 436 | return mpeg_mpeg4_level; |
415 | case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: | 437 | case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: |
416 | return mpeg4_profile; | 438 | return mpeg4_profile; |
439 | case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: | ||
440 | return jpeg_chroma_subsampling; | ||
441 | |||
417 | default: | 442 | default: |
418 | return NULL; | 443 | return NULL; |
419 | } | 444 | } |
@@ -492,6 +517,8 @@ const char *v4l2_ctrl_get_name(u32 id) | |||
492 | case V4L2_CID_MPEG_AUDIO_MUTE: return "Audio Mute"; | 517 | case V4L2_CID_MPEG_AUDIO_MUTE: return "Audio Mute"; |
493 | case V4L2_CID_MPEG_AUDIO_AAC_BITRATE: return "Audio AAC Bitrate"; | 518 | case V4L2_CID_MPEG_AUDIO_AAC_BITRATE: return "Audio AAC Bitrate"; |
494 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: return "Audio AC-3 Bitrate"; | 519 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: return "Audio AC-3 Bitrate"; |
520 | case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK: return "Audio Playback"; | ||
521 | case V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK: return "Audio Multilingual Playback"; | ||
495 | case V4L2_CID_MPEG_VIDEO_ENCODING: return "Video Encoding"; | 522 | case V4L2_CID_MPEG_VIDEO_ENCODING: return "Video Encoding"; |
496 | case V4L2_CID_MPEG_VIDEO_ASPECT: return "Video Aspect"; | 523 | case V4L2_CID_MPEG_VIDEO_ASPECT: return "Video Aspect"; |
497 | case V4L2_CID_MPEG_VIDEO_B_FRAMES: return "Video B Frames"; | 524 | case V4L2_CID_MPEG_VIDEO_B_FRAMES: return "Video B Frames"; |
@@ -546,6 +573,8 @@ const char *v4l2_ctrl_get_name(u32 id) | |||
546 | case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB: return "Number of MBs in a Slice"; | 573 | case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB: return "Number of MBs in a Slice"; |
547 | case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE: return "Slice Partitioning Method"; | 574 | case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE: return "Slice Partitioning Method"; |
548 | case V4L2_CID_MPEG_VIDEO_VBV_SIZE: return "VBV Buffer Size"; | 575 | case V4L2_CID_MPEG_VIDEO_VBV_SIZE: return "VBV Buffer Size"; |
576 | case V4L2_CID_MPEG_VIDEO_DEC_PTS: return "Video Decoder PTS"; | ||
577 | case V4L2_CID_MPEG_VIDEO_DEC_FRAME: return "Video Decoder Frame Count"; | ||
549 | 578 | ||
550 | /* CAMERA controls */ | 579 | /* CAMERA controls */ |
551 | /* Keep the order of the 'case's the same as in videodev2.h! */ | 580 | /* Keep the order of the 'case's the same as in videodev2.h! */ |
@@ -607,6 +636,14 @@ const char *v4l2_ctrl_get_name(u32 id) | |||
607 | case V4L2_CID_FLASH_CHARGE: return "Charge"; | 636 | case V4L2_CID_FLASH_CHARGE: return "Charge"; |
608 | case V4L2_CID_FLASH_READY: return "Ready to Strobe"; | 637 | case V4L2_CID_FLASH_READY: return "Ready to Strobe"; |
609 | 638 | ||
639 | /* JPEG encoder controls */ | ||
640 | /* Keep the order of the 'case's the same as in videodev2.h! */ | ||
641 | case V4L2_CID_JPEG_CLASS: return "JPEG Compression Controls"; | ||
642 | case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: return "Chroma Subsampling"; | ||
643 | case V4L2_CID_JPEG_RESTART_INTERVAL: return "Restart Interval"; | ||
644 | case V4L2_CID_JPEG_COMPRESSION_QUALITY: return "Compression Quality"; | ||
645 | case V4L2_CID_JPEG_ACTIVE_MARKER: return "Active Markers"; | ||
646 | |||
610 | default: | 647 | default: |
611 | return NULL; | 648 | return NULL; |
612 | } | 649 | } |
@@ -674,6 +711,8 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, | |||
674 | case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: | 711 | case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: |
675 | case V4L2_CID_MPEG_AUDIO_EMPHASIS: | 712 | case V4L2_CID_MPEG_AUDIO_EMPHASIS: |
676 | case V4L2_CID_MPEG_AUDIO_CRC: | 713 | case V4L2_CID_MPEG_AUDIO_CRC: |
714 | case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK: | ||
715 | case V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK: | ||
677 | case V4L2_CID_MPEG_VIDEO_ENCODING: | 716 | case V4L2_CID_MPEG_VIDEO_ENCODING: |
678 | case V4L2_CID_MPEG_VIDEO_ASPECT: | 717 | case V4L2_CID_MPEG_VIDEO_ASPECT: |
679 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | 718 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: |
@@ -693,6 +732,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, | |||
693 | case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC: | 732 | case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC: |
694 | case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: | 733 | case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: |
695 | case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: | 734 | case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: |
735 | case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: | ||
696 | *type = V4L2_CTRL_TYPE_MENU; | 736 | *type = V4L2_CTRL_TYPE_MENU; |
697 | break; | 737 | break; |
698 | case V4L2_CID_RDS_TX_PS_NAME: | 738 | case V4L2_CID_RDS_TX_PS_NAME: |
@@ -704,6 +744,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, | |||
704 | case V4L2_CID_MPEG_CLASS: | 744 | case V4L2_CID_MPEG_CLASS: |
705 | case V4L2_CID_FM_TX_CLASS: | 745 | case V4L2_CID_FM_TX_CLASS: |
706 | case V4L2_CID_FLASH_CLASS: | 746 | case V4L2_CID_FLASH_CLASS: |
747 | case V4L2_CID_JPEG_CLASS: | ||
707 | *type = V4L2_CTRL_TYPE_CTRL_CLASS; | 748 | *type = V4L2_CTRL_TYPE_CTRL_CLASS; |
708 | /* You can neither read not write these */ | 749 | /* You can neither read not write these */ |
709 | *flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY; | 750 | *flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY; |
@@ -717,6 +758,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, | |||
717 | *max = 0xFFFFFF; | 758 | *max = 0xFFFFFF; |
718 | break; | 759 | break; |
719 | case V4L2_CID_FLASH_FAULT: | 760 | case V4L2_CID_FLASH_FAULT: |
761 | case V4L2_CID_JPEG_ACTIVE_MARKER: | ||
720 | *type = V4L2_CTRL_TYPE_BITMASK; | 762 | *type = V4L2_CTRL_TYPE_BITMASK; |
721 | break; | 763 | break; |
722 | case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: | 764 | case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: |
@@ -724,6 +766,11 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, | |||
724 | *type = V4L2_CTRL_TYPE_INTEGER; | 766 | *type = V4L2_CTRL_TYPE_INTEGER; |
725 | *flags |= V4L2_CTRL_FLAG_READ_ONLY; | 767 | *flags |= V4L2_CTRL_FLAG_READ_ONLY; |
726 | break; | 768 | break; |
769 | case V4L2_CID_MPEG_VIDEO_DEC_FRAME: | ||
770 | case V4L2_CID_MPEG_VIDEO_DEC_PTS: | ||
771 | *type = V4L2_CTRL_TYPE_INTEGER64; | ||
772 | *flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_VOLATILE; | ||
773 | break; | ||
727 | default: | 774 | default: |
728 | *type = V4L2_CTRL_TYPE_INTEGER; | 775 | *type = V4L2_CTRL_TYPE_INTEGER; |
729 | break; | 776 | break; |
@@ -1470,7 +1517,7 @@ EXPORT_SYMBOL(v4l2_ctrl_add_ctrl); | |||
1470 | int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl, | 1517 | int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl, |
1471 | struct v4l2_ctrl_handler *add) | 1518 | struct v4l2_ctrl_handler *add) |
1472 | { | 1519 | { |
1473 | struct v4l2_ctrl *ctrl; | 1520 | struct v4l2_ctrl_ref *ref; |
1474 | int ret = 0; | 1521 | int ret = 0; |
1475 | 1522 | ||
1476 | /* Do nothing if either handler is NULL or if they are the same */ | 1523 | /* Do nothing if either handler is NULL or if they are the same */ |
@@ -1479,7 +1526,9 @@ int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl, | |||
1479 | if (hdl->error) | 1526 | if (hdl->error) |
1480 | return hdl->error; | 1527 | return hdl->error; |
1481 | mutex_lock(&add->lock); | 1528 | mutex_lock(&add->lock); |
1482 | list_for_each_entry(ctrl, &add->ctrls, node) { | 1529 | list_for_each_entry(ref, &add->ctrl_refs, node) { |
1530 | struct v4l2_ctrl *ctrl = ref->ctrl; | ||
1531 | |||
1483 | /* Skip handler-private controls. */ | 1532 | /* Skip handler-private controls. */ |
1484 | if (ctrl->is_private) | 1533 | if (ctrl->is_private) |
1485 | continue; | 1534 | continue; |
@@ -2359,3 +2408,35 @@ void v4l2_ctrl_del_event(struct v4l2_ctrl *ctrl, | |||
2359 | v4l2_ctrl_unlock(ctrl); | 2408 | v4l2_ctrl_unlock(ctrl); |
2360 | } | 2409 | } |
2361 | EXPORT_SYMBOL(v4l2_ctrl_del_event); | 2410 | EXPORT_SYMBOL(v4l2_ctrl_del_event); |
2411 | |||
2412 | int v4l2_ctrl_log_status(struct file *file, void *fh) | ||
2413 | { | ||
2414 | struct video_device *vfd = video_devdata(file); | ||
2415 | struct v4l2_fh *vfh = file->private_data; | ||
2416 | |||
2417 | if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) && vfd->v4l2_dev) | ||
2418 | v4l2_ctrl_handler_log_status(vfh->ctrl_handler, | ||
2419 | vfd->v4l2_dev->name); | ||
2420 | return 0; | ||
2421 | } | ||
2422 | EXPORT_SYMBOL(v4l2_ctrl_log_status); | ||
2423 | |||
2424 | int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh, | ||
2425 | struct v4l2_event_subscription *sub) | ||
2426 | { | ||
2427 | if (sub->type == V4L2_EVENT_CTRL) | ||
2428 | return v4l2_event_subscribe(fh, sub, 0); | ||
2429 | return -EINVAL; | ||
2430 | } | ||
2431 | EXPORT_SYMBOL(v4l2_ctrl_subscribe_event); | ||
2432 | |||
2433 | unsigned int v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait) | ||
2434 | { | ||
2435 | struct v4l2_fh *fh = file->private_data; | ||
2436 | |||
2437 | if (v4l2_event_pending(fh)) | ||
2438 | return POLLPRI; | ||
2439 | poll_wait(file, &fh->wait, wait); | ||
2440 | return 0; | ||
2441 | } | ||
2442 | EXPORT_SYMBOL(v4l2_ctrl_poll); | ||
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 96e9615663e9..70bec548d904 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/kmod.h> | 26 | #include <linux/kmod.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
29 | #include <asm/system.h> | ||
30 | 29 | ||
31 | #include <media/v4l2-common.h> | 30 | #include <media/v4l2-common.h> |
32 | #include <media/v4l2-device.h> | 31 | #include <media/v4l2-device.h> |
@@ -788,7 +787,7 @@ static void __exit videodev_exit(void) | |||
788 | unregister_chrdev_region(dev, VIDEO_NUM_DEVICES); | 787 | unregister_chrdev_region(dev, VIDEO_NUM_DEVICES); |
789 | } | 788 | } |
790 | 789 | ||
791 | module_init(videodev_init) | 790 | subsys_initcall(videodev_init); |
792 | module_exit(videodev_exit) | 791 | module_exit(videodev_exit) |
793 | 792 | ||
794 | MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab <mchehab@infradead.org>"); | 793 | MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab <mchehab@infradead.org>"); |
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 3f623859a337..5b2ec1fd2d0a 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c | |||
@@ -260,6 +260,8 @@ static const char *v4l2_ioctls[] = { | |||
260 | [_IOC_NR(VIDIOC_ENCODER_CMD)] = "VIDIOC_ENCODER_CMD", | 260 | [_IOC_NR(VIDIOC_ENCODER_CMD)] = "VIDIOC_ENCODER_CMD", |
261 | [_IOC_NR(VIDIOC_TRY_ENCODER_CMD)] = "VIDIOC_TRY_ENCODER_CMD", | 261 | [_IOC_NR(VIDIOC_TRY_ENCODER_CMD)] = "VIDIOC_TRY_ENCODER_CMD", |
262 | 262 | ||
263 | [_IOC_NR(VIDIOC_DECODER_CMD)] = "VIDIOC_DECODER_CMD", | ||
264 | [_IOC_NR(VIDIOC_TRY_DECODER_CMD)] = "VIDIOC_TRY_DECODER_CMD", | ||
263 | [_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER", | 265 | [_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER", |
264 | [_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER", | 266 | [_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER", |
265 | 267 | ||
@@ -540,10 +542,12 @@ static long __video_do_ioctl(struct file *file, | |||
540 | if (!ret) | 542 | if (!ret) |
541 | dbgarg(cmd, "driver=%s, card=%s, bus=%s, " | 543 | dbgarg(cmd, "driver=%s, card=%s, bus=%s, " |
542 | "version=0x%08x, " | 544 | "version=0x%08x, " |
543 | "capabilities=0x%08x\n", | 545 | "capabilities=0x%08x, " |
546 | "device_caps=0x%08x\n", | ||
544 | cap->driver, cap->card, cap->bus_info, | 547 | cap->driver, cap->card, cap->bus_info, |
545 | cap->version, | 548 | cap->version, |
546 | cap->capabilities); | 549 | cap->capabilities, |
550 | cap->device_caps); | ||
547 | break; | 551 | break; |
548 | } | 552 | } |
549 | 553 | ||
@@ -1762,6 +1766,32 @@ static long __video_do_ioctl(struct file *file, | |||
1762 | dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); | 1766 | dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); |
1763 | break; | 1767 | break; |
1764 | } | 1768 | } |
1769 | case VIDIOC_DECODER_CMD: | ||
1770 | { | ||
1771 | struct v4l2_decoder_cmd *p = arg; | ||
1772 | |||
1773 | if (!ops->vidioc_decoder_cmd) | ||
1774 | break; | ||
1775 | if (ret_prio) { | ||
1776 | ret = ret_prio; | ||
1777 | break; | ||
1778 | } | ||
1779 | ret = ops->vidioc_decoder_cmd(file, fh, p); | ||
1780 | if (!ret) | ||
1781 | dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); | ||
1782 | break; | ||
1783 | } | ||
1784 | case VIDIOC_TRY_DECODER_CMD: | ||
1785 | { | ||
1786 | struct v4l2_decoder_cmd *p = arg; | ||
1787 | |||
1788 | if (!ops->vidioc_try_decoder_cmd) | ||
1789 | break; | ||
1790 | ret = ops->vidioc_try_decoder_cmd(file, fh, p); | ||
1791 | if (!ret) | ||
1792 | dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags); | ||
1793 | break; | ||
1794 | } | ||
1765 | case VIDIOC_G_PARM: | 1795 | case VIDIOC_G_PARM: |
1766 | { | 1796 | { |
1767 | struct v4l2_streamparm *p = arg; | 1797 | struct v4l2_streamparm *p = arg; |
@@ -1909,7 +1939,13 @@ static long __video_do_ioctl(struct file *file, | |||
1909 | { | 1939 | { |
1910 | if (!ops->vidioc_log_status) | 1940 | if (!ops->vidioc_log_status) |
1911 | break; | 1941 | break; |
1942 | if (vfd->v4l2_dev) | ||
1943 | pr_info("%s: ================= START STATUS =================\n", | ||
1944 | vfd->v4l2_dev->name); | ||
1912 | ret = ops->vidioc_log_status(file, fh); | 1945 | ret = ops->vidioc_log_status(file, fh); |
1946 | if (vfd->v4l2_dev) | ||
1947 | pr_info("%s: ================== END STATUS ==================\n", | ||
1948 | vfd->v4l2_dev->name); | ||
1913 | break; | 1949 | break; |
1914 | } | 1950 | } |
1915 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 1951 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
@@ -2419,7 +2455,7 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, | |||
2419 | /* Handles IOCTL */ | 2455 | /* Handles IOCTL */ |
2420 | err = func(file, cmd, parg); | 2456 | err = func(file, cmd, parg); |
2421 | if (err == -ENOIOCTLCMD) | 2457 | if (err == -ENOIOCTLCMD) |
2422 | err = -EINVAL; | 2458 | err = -ENOTTY; |
2423 | 2459 | ||
2424 | if (has_array_args) { | 2460 | if (has_array_args) { |
2425 | *kernel_ptr = user_ptr; | 2461 | *kernel_ptr = user_ptr; |
diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index 41d118ee2de6..6fe88e965a8c 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c | |||
@@ -194,8 +194,16 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
194 | } | 194 | } |
195 | #endif | 195 | #endif |
196 | 196 | ||
197 | case VIDIOC_LOG_STATUS: | 197 | case VIDIOC_LOG_STATUS: { |
198 | return v4l2_subdev_call(sd, core, log_status); | 198 | int ret; |
199 | |||
200 | pr_info("%s: ================= START STATUS =================\n", | ||
201 | sd->name); | ||
202 | ret = v4l2_subdev_call(sd, core, log_status); | ||
203 | pr_info("%s: ================== END STATUS ==================\n", | ||
204 | sd->name); | ||
205 | return ret; | ||
206 | } | ||
199 | 207 | ||
200 | #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) | 208 | #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) |
201 | case VIDIOC_SUBDEV_G_FMT: { | 209 | case VIDIOC_SUBDEV_G_FMT: { |
diff --git a/drivers/media/video/videobuf2-vmalloc.c b/drivers/media/video/videobuf2-vmalloc.c index 4e789a178f8a..6b5ca6c70a46 100644 --- a/drivers/media/video/videobuf2-vmalloc.c +++ b/drivers/media/video/videobuf2-vmalloc.c | |||
@@ -10,6 +10,7 @@ | |||
10 | * the Free Software Foundation. | 10 | * the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/io.h> | ||
13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
14 | #include <linux/mm.h> | 15 | #include <linux/mm.h> |
15 | #include <linux/sched.h> | 16 | #include <linux/sched.h> |
@@ -22,6 +23,7 @@ | |||
22 | struct vb2_vmalloc_buf { | 23 | struct vb2_vmalloc_buf { |
23 | void *vaddr; | 24 | void *vaddr; |
24 | struct page **pages; | 25 | struct page **pages; |
26 | struct vm_area_struct *vma; | ||
25 | int write; | 27 | int write; |
26 | unsigned long size; | 28 | unsigned long size; |
27 | unsigned int n_pages; | 29 | unsigned int n_pages; |
@@ -71,6 +73,8 @@ static void *vb2_vmalloc_get_userptr(void *alloc_ctx, unsigned long vaddr, | |||
71 | struct vb2_vmalloc_buf *buf; | 73 | struct vb2_vmalloc_buf *buf; |
72 | unsigned long first, last; | 74 | unsigned long first, last; |
73 | int n_pages, offset; | 75 | int n_pages, offset; |
76 | struct vm_area_struct *vma; | ||
77 | dma_addr_t physp; | ||
74 | 78 | ||
75 | buf = kzalloc(sizeof(*buf), GFP_KERNEL); | 79 | buf = kzalloc(sizeof(*buf), GFP_KERNEL); |
76 | if (!buf) | 80 | if (!buf) |
@@ -80,23 +84,37 @@ static void *vb2_vmalloc_get_userptr(void *alloc_ctx, unsigned long vaddr, | |||
80 | offset = vaddr & ~PAGE_MASK; | 84 | offset = vaddr & ~PAGE_MASK; |
81 | buf->size = size; | 85 | buf->size = size; |
82 | 86 | ||
83 | first = vaddr >> PAGE_SHIFT; | ||
84 | last = (vaddr + size - 1) >> PAGE_SHIFT; | ||
85 | buf->n_pages = last - first + 1; | ||
86 | buf->pages = kzalloc(buf->n_pages * sizeof(struct page *), GFP_KERNEL); | ||
87 | if (!buf->pages) | ||
88 | goto fail_pages_array_alloc; | ||
89 | 87 | ||
90 | /* current->mm->mmap_sem is taken by videobuf2 core */ | 88 | vma = find_vma(current->mm, vaddr); |
91 | n_pages = get_user_pages(current, current->mm, vaddr & PAGE_MASK, | 89 | if (vma && (vma->vm_flags & VM_PFNMAP) && (vma->vm_pgoff)) { |
92 | buf->n_pages, write, 1, /* force */ | 90 | if (vb2_get_contig_userptr(vaddr, size, &vma, &physp)) |
93 | buf->pages, NULL); | 91 | goto fail_pages_array_alloc; |
94 | if (n_pages != buf->n_pages) | 92 | buf->vma = vma; |
95 | goto fail_get_user_pages; | 93 | buf->vaddr = ioremap_nocache(physp, size); |
96 | 94 | if (!buf->vaddr) | |
97 | buf->vaddr = vm_map_ram(buf->pages, buf->n_pages, -1, PAGE_KERNEL); | 95 | goto fail_pages_array_alloc; |
98 | if (!buf->vaddr) | 96 | } else { |
99 | goto fail_get_user_pages; | 97 | first = vaddr >> PAGE_SHIFT; |
98 | last = (vaddr + size - 1) >> PAGE_SHIFT; | ||
99 | buf->n_pages = last - first + 1; | ||
100 | buf->pages = kzalloc(buf->n_pages * sizeof(struct page *), | ||
101 | GFP_KERNEL); | ||
102 | if (!buf->pages) | ||
103 | goto fail_pages_array_alloc; | ||
104 | |||
105 | /* current->mm->mmap_sem is taken by videobuf2 core */ | ||
106 | n_pages = get_user_pages(current, current->mm, | ||
107 | vaddr & PAGE_MASK, buf->n_pages, | ||
108 | write, 1, /* force */ | ||
109 | buf->pages, NULL); | ||
110 | if (n_pages != buf->n_pages) | ||
111 | goto fail_get_user_pages; | ||
112 | |||
113 | buf->vaddr = vm_map_ram(buf->pages, buf->n_pages, -1, | ||
114 | PAGE_KERNEL); | ||
115 | if (!buf->vaddr) | ||
116 | goto fail_get_user_pages; | ||
117 | } | ||
100 | 118 | ||
101 | buf->vaddr += offset; | 119 | buf->vaddr += offset; |
102 | return buf; | 120 | return buf; |
@@ -120,14 +138,20 @@ static void vb2_vmalloc_put_userptr(void *buf_priv) | |||
120 | unsigned long vaddr = (unsigned long)buf->vaddr & PAGE_MASK; | 138 | unsigned long vaddr = (unsigned long)buf->vaddr & PAGE_MASK; |
121 | unsigned int i; | 139 | unsigned int i; |
122 | 140 | ||
123 | if (vaddr) | 141 | if (buf->pages) { |
124 | vm_unmap_ram((void *)vaddr, buf->n_pages); | 142 | if (vaddr) |
125 | for (i = 0; i < buf->n_pages; ++i) { | 143 | vm_unmap_ram((void *)vaddr, buf->n_pages); |
126 | if (buf->write) | 144 | for (i = 0; i < buf->n_pages; ++i) { |
127 | set_page_dirty_lock(buf->pages[i]); | 145 | if (buf->write) |
128 | put_page(buf->pages[i]); | 146 | set_page_dirty_lock(buf->pages[i]); |
147 | put_page(buf->pages[i]); | ||
148 | } | ||
149 | kfree(buf->pages); | ||
150 | } else { | ||
151 | if (buf->vma) | ||
152 | vb2_put_vma(buf->vma); | ||
153 | iounmap(buf->vaddr); | ||
129 | } | 154 | } |
130 | kfree(buf->pages); | ||
131 | kfree(buf); | 155 | kfree(buf); |
132 | } | 156 | } |
133 | 157 | ||
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 7d754fbcccbf..5e8b0710105b 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c | |||
@@ -819,8 +819,9 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
819 | strcpy(cap->driver, "vivi"); | 819 | strcpy(cap->driver, "vivi"); |
820 | strcpy(cap->card, "vivi"); | 820 | strcpy(cap->card, "vivi"); |
821 | strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info)); | 821 | strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info)); |
822 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | \ | 822 | cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | |
823 | V4L2_CAP_READWRITE; | 823 | V4L2_CAP_READWRITE; |
824 | cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; | ||
824 | return 0; | 825 | return 0; |
825 | } | 826 | } |
826 | 827 | ||
@@ -958,14 +959,6 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | |||
958 | return vb2_streamoff(&dev->vb_vidq, i); | 959 | return vb2_streamoff(&dev->vb_vidq, i); |
959 | } | 960 | } |
960 | 961 | ||
961 | static int vidioc_log_status(struct file *file, void *priv) | ||
962 | { | ||
963 | struct vivi_dev *dev = video_drvdata(file); | ||
964 | |||
965 | v4l2_ctrl_handler_log_status(&dev->ctrl_handler, dev->v4l2_dev.name); | ||
966 | return 0; | ||
967 | } | ||
968 | |||
969 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i) | 962 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i) |
970 | { | 963 | { |
971 | return 0; | 964 | return 0; |
@@ -1008,17 +1001,6 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | |||
1008 | return 0; | 1001 | return 0; |
1009 | } | 1002 | } |
1010 | 1003 | ||
1011 | static int vidioc_subscribe_event(struct v4l2_fh *fh, | ||
1012 | struct v4l2_event_subscription *sub) | ||
1013 | { | ||
1014 | switch (sub->type) { | ||
1015 | case V4L2_EVENT_CTRL: | ||
1016 | return v4l2_event_subscribe(fh, sub, 0); | ||
1017 | default: | ||
1018 | return -EINVAL; | ||
1019 | } | ||
1020 | } | ||
1021 | |||
1022 | /* --- controls ---------------------------------------------- */ | 1004 | /* --- controls ---------------------------------------------- */ |
1023 | 1005 | ||
1024 | static int vivi_g_volatile_ctrl(struct v4l2_ctrl *ctrl) | 1006 | static int vivi_g_volatile_ctrl(struct v4l2_ctrl *ctrl) |
@@ -1209,8 +1191,8 @@ static const struct v4l2_ioctl_ops vivi_ioctl_ops = { | |||
1209 | .vidioc_s_input = vidioc_s_input, | 1191 | .vidioc_s_input = vidioc_s_input, |
1210 | .vidioc_streamon = vidioc_streamon, | 1192 | .vidioc_streamon = vidioc_streamon, |
1211 | .vidioc_streamoff = vidioc_streamoff, | 1193 | .vidioc_streamoff = vidioc_streamoff, |
1212 | .vidioc_log_status = vidioc_log_status, | 1194 | .vidioc_log_status = v4l2_ctrl_log_status, |
1213 | .vidioc_subscribe_event = vidioc_subscribe_event, | 1195 | .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, |
1214 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, | 1196 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, |
1215 | }; | 1197 | }; |
1216 | 1198 | ||
diff --git a/drivers/media/video/vp27smpx.c b/drivers/media/video/vp27smpx.c index c15efb6e7771..7cfbc9d94a48 100644 --- a/drivers/media/video/vp27smpx.c +++ b/drivers/media/video/vp27smpx.c | |||
@@ -208,15 +208,4 @@ static struct i2c_driver vp27smpx_driver = { | |||
208 | .id_table = vp27smpx_id, | 208 | .id_table = vp27smpx_id, |
209 | }; | 209 | }; |
210 | 210 | ||
211 | static __init int init_vp27smpx(void) | 211 | module_i2c_driver(vp27smpx_driver); |
212 | { | ||
213 | return i2c_add_driver(&vp27smpx_driver); | ||
214 | } | ||
215 | |||
216 | static __exit void exit_vp27smpx(void) | ||
217 | { | ||
218 | i2c_del_driver(&vp27smpx_driver); | ||
219 | } | ||
220 | |||
221 | module_init(init_vp27smpx); | ||
222 | module_exit(exit_vp27smpx); | ||
diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c index e5cad6ff64a1..2f67b4c5c823 100644 --- a/drivers/media/video/vpx3220.c +++ b/drivers/media/video/vpx3220.c | |||
@@ -588,15 +588,4 @@ static struct i2c_driver vpx3220_driver = { | |||
588 | .id_table = vpx3220_id, | 588 | .id_table = vpx3220_id, |
589 | }; | 589 | }; |
590 | 590 | ||
591 | static __init int init_vpx3220(void) | 591 | module_i2c_driver(vpx3220_driver); |
592 | { | ||
593 | return i2c_add_driver(&vpx3220_driver); | ||
594 | } | ||
595 | |||
596 | static __exit void exit_vpx3220(void) | ||
597 | { | ||
598 | i2c_del_driver(&vpx3220_driver); | ||
599 | } | ||
600 | |||
601 | module_init(init_vpx3220); | ||
602 | module_exit(exit_vpx3220); | ||
diff --git a/drivers/media/video/vs6624.c b/drivers/media/video/vs6624.c new file mode 100644 index 000000000000..42ae9dc9c574 --- /dev/null +++ b/drivers/media/video/vs6624.c | |||
@@ -0,0 +1,928 @@ | |||
1 | /* | ||
2 | * vs6624.c ST VS6624 CMOS image sensor driver | ||
3 | * | ||
4 | * Copyright (c) 2011 Analog Devices Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/delay.h> | ||
21 | #include <linux/errno.h> | ||
22 | #include <linux/gpio.h> | ||
23 | #include <linux/i2c.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/types.h> | ||
28 | #include <linux/videodev2.h> | ||
29 | |||
30 | #include <media/v4l2-chip-ident.h> | ||
31 | #include <media/v4l2-ctrls.h> | ||
32 | #include <media/v4l2-device.h> | ||
33 | #include <media/v4l2-mediabus.h> | ||
34 | |||
35 | #include "vs6624_regs.h" | ||
36 | |||
37 | #define VGA_WIDTH 640 | ||
38 | #define VGA_HEIGHT 480 | ||
39 | #define QVGA_WIDTH 320 | ||
40 | #define QVGA_HEIGHT 240 | ||
41 | #define QQVGA_WIDTH 160 | ||
42 | #define QQVGA_HEIGHT 120 | ||
43 | #define CIF_WIDTH 352 | ||
44 | #define CIF_HEIGHT 288 | ||
45 | #define QCIF_WIDTH 176 | ||
46 | #define QCIF_HEIGHT 144 | ||
47 | #define QQCIF_WIDTH 88 | ||
48 | #define QQCIF_HEIGHT 72 | ||
49 | |||
50 | #define MAX_FRAME_RATE 30 | ||
51 | |||
52 | struct vs6624 { | ||
53 | struct v4l2_subdev sd; | ||
54 | struct v4l2_ctrl_handler hdl; | ||
55 | struct v4l2_fract frame_rate; | ||
56 | struct v4l2_mbus_framefmt fmt; | ||
57 | unsigned ce_pin; | ||
58 | }; | ||
59 | |||
60 | static const struct vs6624_format { | ||
61 | enum v4l2_mbus_pixelcode mbus_code; | ||
62 | enum v4l2_colorspace colorspace; | ||
63 | } vs6624_formats[] = { | ||
64 | { | ||
65 | .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8, | ||
66 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
67 | }, | ||
68 | { | ||
69 | .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, | ||
70 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
71 | }, | ||
72 | { | ||
73 | .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE, | ||
74 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
75 | }, | ||
76 | }; | ||
77 | |||
78 | static struct v4l2_mbus_framefmt vs6624_default_fmt = { | ||
79 | .width = VGA_WIDTH, | ||
80 | .height = VGA_HEIGHT, | ||
81 | .code = V4L2_MBUS_FMT_UYVY8_2X8, | ||
82 | .field = V4L2_FIELD_NONE, | ||
83 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
84 | }; | ||
85 | |||
86 | static const u16 vs6624_p1[] = { | ||
87 | 0x8104, 0x03, | ||
88 | 0x8105, 0x01, | ||
89 | 0xc900, 0x03, | ||
90 | 0xc904, 0x47, | ||
91 | 0xc905, 0x10, | ||
92 | 0xc906, 0x80, | ||
93 | 0xc907, 0x3a, | ||
94 | 0x903a, 0x02, | ||
95 | 0x903b, 0x47, | ||
96 | 0x903c, 0x15, | ||
97 | 0xc908, 0x31, | ||
98 | 0xc909, 0xdc, | ||
99 | 0xc90a, 0x80, | ||
100 | 0xc90b, 0x44, | ||
101 | 0x9044, 0x02, | ||
102 | 0x9045, 0x31, | ||
103 | 0x9046, 0xe2, | ||
104 | 0xc90c, 0x07, | ||
105 | 0xc90d, 0xe0, | ||
106 | 0xc90e, 0x80, | ||
107 | 0xc90f, 0x47, | ||
108 | 0x9047, 0x90, | ||
109 | 0x9048, 0x83, | ||
110 | 0x9049, 0x81, | ||
111 | 0x904a, 0xe0, | ||
112 | 0x904b, 0x60, | ||
113 | 0x904c, 0x08, | ||
114 | 0x904d, 0x90, | ||
115 | 0x904e, 0xc0, | ||
116 | 0x904f, 0x43, | ||
117 | 0x9050, 0x74, | ||
118 | 0x9051, 0x01, | ||
119 | 0x9052, 0xf0, | ||
120 | 0x9053, 0x80, | ||
121 | 0x9054, 0x05, | ||
122 | 0x9055, 0xE4, | ||
123 | 0x9056, 0x90, | ||
124 | 0x9057, 0xc0, | ||
125 | 0x9058, 0x43, | ||
126 | 0x9059, 0xf0, | ||
127 | 0x905a, 0x02, | ||
128 | 0x905b, 0x07, | ||
129 | 0x905c, 0xec, | ||
130 | 0xc910, 0x5d, | ||
131 | 0xc911, 0xca, | ||
132 | 0xc912, 0x80, | ||
133 | 0xc913, 0x5d, | ||
134 | 0x905d, 0xa3, | ||
135 | 0x905e, 0x04, | ||
136 | 0x905f, 0xf0, | ||
137 | 0x9060, 0xa3, | ||
138 | 0x9061, 0x04, | ||
139 | 0x9062, 0xf0, | ||
140 | 0x9063, 0x22, | ||
141 | 0xc914, 0x72, | ||
142 | 0xc915, 0x92, | ||
143 | 0xc916, 0x80, | ||
144 | 0xc917, 0x64, | ||
145 | 0x9064, 0x74, | ||
146 | 0x9065, 0x01, | ||
147 | 0x9066, 0x02, | ||
148 | 0x9067, 0x72, | ||
149 | 0x9068, 0x95, | ||
150 | 0xc918, 0x47, | ||
151 | 0xc919, 0xf2, | ||
152 | 0xc91a, 0x81, | ||
153 | 0xc91b, 0x69, | ||
154 | 0x9169, 0x74, | ||
155 | 0x916a, 0x02, | ||
156 | 0x916b, 0xf0, | ||
157 | 0x916c, 0xec, | ||
158 | 0x916d, 0xb4, | ||
159 | 0x916e, 0x10, | ||
160 | 0x916f, 0x0a, | ||
161 | 0x9170, 0x90, | ||
162 | 0x9171, 0x80, | ||
163 | 0x9172, 0x16, | ||
164 | 0x9173, 0xe0, | ||
165 | 0x9174, 0x70, | ||
166 | 0x9175, 0x04, | ||
167 | 0x9176, 0x90, | ||
168 | 0x9177, 0xd3, | ||
169 | 0x9178, 0xc4, | ||
170 | 0x9179, 0xf0, | ||
171 | 0x917a, 0x22, | ||
172 | 0xc91c, 0x0a, | ||
173 | 0xc91d, 0xbe, | ||
174 | 0xc91e, 0x80, | ||
175 | 0xc91f, 0x73, | ||
176 | 0x9073, 0xfc, | ||
177 | 0x9074, 0xa3, | ||
178 | 0x9075, 0xe0, | ||
179 | 0x9076, 0xf5, | ||
180 | 0x9077, 0x82, | ||
181 | 0x9078, 0x8c, | ||
182 | 0x9079, 0x83, | ||
183 | 0x907a, 0xa3, | ||
184 | 0x907b, 0xa3, | ||
185 | 0x907c, 0xe0, | ||
186 | 0x907d, 0xfc, | ||
187 | 0x907e, 0xa3, | ||
188 | 0x907f, 0xe0, | ||
189 | 0x9080, 0xc3, | ||
190 | 0x9081, 0x9f, | ||
191 | 0x9082, 0xff, | ||
192 | 0x9083, 0xec, | ||
193 | 0x9084, 0x9e, | ||
194 | 0x9085, 0xfe, | ||
195 | 0x9086, 0x02, | ||
196 | 0x9087, 0x0a, | ||
197 | 0x9088, 0xea, | ||
198 | 0xc920, 0x47, | ||
199 | 0xc921, 0x38, | ||
200 | 0xc922, 0x80, | ||
201 | 0xc923, 0x89, | ||
202 | 0x9089, 0xec, | ||
203 | 0x908a, 0xd3, | ||
204 | 0x908b, 0x94, | ||
205 | 0x908c, 0x20, | ||
206 | 0x908d, 0x40, | ||
207 | 0x908e, 0x01, | ||
208 | 0x908f, 0x1c, | ||
209 | 0x9090, 0x90, | ||
210 | 0x9091, 0xd3, | ||
211 | 0x9092, 0xd4, | ||
212 | 0x9093, 0xec, | ||
213 | 0x9094, 0xf0, | ||
214 | 0x9095, 0x02, | ||
215 | 0x9096, 0x47, | ||
216 | 0x9097, 0x3d, | ||
217 | 0xc924, 0x45, | ||
218 | 0xc925, 0xca, | ||
219 | 0xc926, 0x80, | ||
220 | 0xc927, 0x98, | ||
221 | 0x9098, 0x12, | ||
222 | 0x9099, 0x77, | ||
223 | 0x909a, 0xd6, | ||
224 | 0x909b, 0x02, | ||
225 | 0x909c, 0x45, | ||
226 | 0x909d, 0xcd, | ||
227 | 0xc928, 0x20, | ||
228 | 0xc929, 0xd5, | ||
229 | 0xc92a, 0x80, | ||
230 | 0xc92b, 0x9e, | ||
231 | 0x909e, 0x90, | ||
232 | 0x909f, 0x82, | ||
233 | 0x90a0, 0x18, | ||
234 | 0x90a1, 0xe0, | ||
235 | 0x90a2, 0xb4, | ||
236 | 0x90a3, 0x03, | ||
237 | 0x90a4, 0x0e, | ||
238 | 0x90a5, 0x90, | ||
239 | 0x90a6, 0x83, | ||
240 | 0x90a7, 0xbf, | ||
241 | 0x90a8, 0xe0, | ||
242 | 0x90a9, 0x60, | ||
243 | 0x90aa, 0x08, | ||
244 | 0x90ab, 0x90, | ||
245 | 0x90ac, 0x81, | ||
246 | 0x90ad, 0xfc, | ||
247 | 0x90ae, 0xe0, | ||
248 | 0x90af, 0xff, | ||
249 | 0x90b0, 0xc3, | ||
250 | 0x90b1, 0x13, | ||
251 | 0x90b2, 0xf0, | ||
252 | 0x90b3, 0x90, | ||
253 | 0x90b4, 0x81, | ||
254 | 0x90b5, 0xfc, | ||
255 | 0x90b6, 0xe0, | ||
256 | 0x90b7, 0xff, | ||
257 | 0x90b8, 0x02, | ||
258 | 0x90b9, 0x20, | ||
259 | 0x90ba, 0xda, | ||
260 | 0xc92c, 0x70, | ||
261 | 0xc92d, 0xbc, | ||
262 | 0xc92e, 0x80, | ||
263 | 0xc92f, 0xbb, | ||
264 | 0x90bb, 0x90, | ||
265 | 0x90bc, 0x82, | ||
266 | 0x90bd, 0x18, | ||
267 | 0x90be, 0xe0, | ||
268 | 0x90bf, 0xb4, | ||
269 | 0x90c0, 0x03, | ||
270 | 0x90c1, 0x06, | ||
271 | 0x90c2, 0x90, | ||
272 | 0x90c3, 0xc1, | ||
273 | 0x90c4, 0x06, | ||
274 | 0x90c5, 0x74, | ||
275 | 0x90c6, 0x05, | ||
276 | 0x90c7, 0xf0, | ||
277 | 0x90c8, 0x90, | ||
278 | 0x90c9, 0xd3, | ||
279 | 0x90ca, 0xa0, | ||
280 | 0x90cb, 0x02, | ||
281 | 0x90cc, 0x70, | ||
282 | 0x90cd, 0xbf, | ||
283 | 0xc930, 0x72, | ||
284 | 0xc931, 0x21, | ||
285 | 0xc932, 0x81, | ||
286 | 0xc933, 0x3b, | ||
287 | 0x913b, 0x7d, | ||
288 | 0x913c, 0x02, | ||
289 | 0x913d, 0x7f, | ||
290 | 0x913e, 0x7b, | ||
291 | 0x913f, 0x02, | ||
292 | 0x9140, 0x72, | ||
293 | 0x9141, 0x25, | ||
294 | 0xc934, 0x28, | ||
295 | 0xc935, 0xae, | ||
296 | 0xc936, 0x80, | ||
297 | 0xc937, 0xd2, | ||
298 | 0x90d2, 0xf0, | ||
299 | 0x90d3, 0x90, | ||
300 | 0x90d4, 0xd2, | ||
301 | 0x90d5, 0x0a, | ||
302 | 0x90d6, 0x02, | ||
303 | 0x90d7, 0x28, | ||
304 | 0x90d8, 0xb4, | ||
305 | 0xc938, 0x28, | ||
306 | 0xc939, 0xb1, | ||
307 | 0xc93a, 0x80, | ||
308 | 0xc93b, 0xd9, | ||
309 | 0x90d9, 0x90, | ||
310 | 0x90da, 0x83, | ||
311 | 0x90db, 0xba, | ||
312 | 0x90dc, 0xe0, | ||
313 | 0x90dd, 0xff, | ||
314 | 0x90de, 0x90, | ||
315 | 0x90df, 0xd2, | ||
316 | 0x90e0, 0x08, | ||
317 | 0x90e1, 0xe0, | ||
318 | 0x90e2, 0xe4, | ||
319 | 0x90e3, 0xef, | ||
320 | 0x90e4, 0xf0, | ||
321 | 0x90e5, 0xa3, | ||
322 | 0x90e6, 0xe0, | ||
323 | 0x90e7, 0x74, | ||
324 | 0x90e8, 0xff, | ||
325 | 0x90e9, 0xf0, | ||
326 | 0x90ea, 0x90, | ||
327 | 0x90eb, 0xd2, | ||
328 | 0x90ec, 0x0a, | ||
329 | 0x90ed, 0x02, | ||
330 | 0x90ee, 0x28, | ||
331 | 0x90ef, 0xb4, | ||
332 | 0xc93c, 0x29, | ||
333 | 0xc93d, 0x79, | ||
334 | 0xc93e, 0x80, | ||
335 | 0xc93f, 0xf0, | ||
336 | 0x90f0, 0xf0, | ||
337 | 0x90f1, 0x90, | ||
338 | 0x90f2, 0xd2, | ||
339 | 0x90f3, 0x0e, | ||
340 | 0x90f4, 0x02, | ||
341 | 0x90f5, 0x29, | ||
342 | 0x90f6, 0x7f, | ||
343 | 0xc940, 0x29, | ||
344 | 0xc941, 0x7c, | ||
345 | 0xc942, 0x80, | ||
346 | 0xc943, 0xf7, | ||
347 | 0x90f7, 0x90, | ||
348 | 0x90f8, 0x83, | ||
349 | 0x90f9, 0xba, | ||
350 | 0x90fa, 0xe0, | ||
351 | 0x90fb, 0xff, | ||
352 | 0x90fc, 0x90, | ||
353 | 0x90fd, 0xd2, | ||
354 | 0x90fe, 0x0c, | ||
355 | 0x90ff, 0xe0, | ||
356 | 0x9100, 0xe4, | ||
357 | 0x9101, 0xef, | ||
358 | 0x9102, 0xf0, | ||
359 | 0x9103, 0xa3, | ||
360 | 0x9104, 0xe0, | ||
361 | 0x9105, 0x74, | ||
362 | 0x9106, 0xff, | ||
363 | 0x9107, 0xf0, | ||
364 | 0x9108, 0x90, | ||
365 | 0x9109, 0xd2, | ||
366 | 0x910a, 0x0e, | ||
367 | 0x910b, 0x02, | ||
368 | 0x910c, 0x29, | ||
369 | 0x910d, 0x7f, | ||
370 | 0xc944, 0x2a, | ||
371 | 0xc945, 0x42, | ||
372 | 0xc946, 0x81, | ||
373 | 0xc947, 0x0e, | ||
374 | 0x910e, 0xf0, | ||
375 | 0x910f, 0x90, | ||
376 | 0x9110, 0xd2, | ||
377 | 0x9111, 0x12, | ||
378 | 0x9112, 0x02, | ||
379 | 0x9113, 0x2a, | ||
380 | 0x9114, 0x48, | ||
381 | 0xc948, 0x2a, | ||
382 | 0xc949, 0x45, | ||
383 | 0xc94a, 0x81, | ||
384 | 0xc94b, 0x15, | ||
385 | 0x9115, 0x90, | ||
386 | 0x9116, 0x83, | ||
387 | 0x9117, 0xba, | ||
388 | 0x9118, 0xe0, | ||
389 | 0x9119, 0xff, | ||
390 | 0x911a, 0x90, | ||
391 | 0x911b, 0xd2, | ||
392 | 0x911c, 0x10, | ||
393 | 0x911d, 0xe0, | ||
394 | 0x911e, 0xe4, | ||
395 | 0x911f, 0xef, | ||
396 | 0x9120, 0xf0, | ||
397 | 0x9121, 0xa3, | ||
398 | 0x9122, 0xe0, | ||
399 | 0x9123, 0x74, | ||
400 | 0x9124, 0xff, | ||
401 | 0x9125, 0xf0, | ||
402 | 0x9126, 0x90, | ||
403 | 0x9127, 0xd2, | ||
404 | 0x9128, 0x12, | ||
405 | 0x9129, 0x02, | ||
406 | 0x912a, 0x2a, | ||
407 | 0x912b, 0x48, | ||
408 | 0xc900, 0x01, | ||
409 | 0x0000, 0x00, | ||
410 | }; | ||
411 | |||
412 | static const u16 vs6624_p2[] = { | ||
413 | 0x806f, 0x01, | ||
414 | 0x058c, 0x01, | ||
415 | 0x0000, 0x00, | ||
416 | }; | ||
417 | |||
418 | static const u16 vs6624_run_setup[] = { | ||
419 | 0x1d18, 0x00, /* Enableconstrainedwhitebalance */ | ||
420 | VS6624_PEAK_MIN_OUT_G_MSB, 0x3c, /* Damper PeakGain Output MSB */ | ||
421 | VS6624_PEAK_MIN_OUT_G_LSB, 0x66, /* Damper PeakGain Output LSB */ | ||
422 | VS6624_CM_LOW_THR_MSB, 0x65, /* Damper Low MSB */ | ||
423 | VS6624_CM_LOW_THR_LSB, 0xd1, /* Damper Low LSB */ | ||
424 | VS6624_CM_HIGH_THR_MSB, 0x66, /* Damper High MSB */ | ||
425 | VS6624_CM_HIGH_THR_LSB, 0x62, /* Damper High LSB */ | ||
426 | VS6624_CM_MIN_OUT_MSB, 0x00, /* Damper Min output MSB */ | ||
427 | VS6624_CM_MIN_OUT_LSB, 0x00, /* Damper Min output LSB */ | ||
428 | VS6624_NORA_DISABLE, 0x00, /* Nora fDisable */ | ||
429 | VS6624_NORA_USAGE, 0x04, /* Nora usage */ | ||
430 | VS6624_NORA_LOW_THR_MSB, 0x63, /* Damper Low MSB Changed 0x63 to 0x65 */ | ||
431 | VS6624_NORA_LOW_THR_LSB, 0xd1, /* Damper Low LSB */ | ||
432 | VS6624_NORA_HIGH_THR_MSB, 0x68, /* Damper High MSB */ | ||
433 | VS6624_NORA_HIGH_THR_LSB, 0xdd, /* Damper High LSB */ | ||
434 | VS6624_NORA_MIN_OUT_MSB, 0x3a, /* Damper Min output MSB */ | ||
435 | VS6624_NORA_MIN_OUT_LSB, 0x00, /* Damper Min output LSB */ | ||
436 | VS6624_F2B_DISABLE, 0x00, /* Disable */ | ||
437 | 0x1d8a, 0x30, /* MAXWeightHigh */ | ||
438 | 0x1d91, 0x62, /* fpDamperLowThresholdHigh MSB */ | ||
439 | 0x1d92, 0x4a, /* fpDamperLowThresholdHigh LSB */ | ||
440 | 0x1d95, 0x65, /* fpDamperHighThresholdHigh MSB */ | ||
441 | 0x1d96, 0x0e, /* fpDamperHighThresholdHigh LSB */ | ||
442 | 0x1da1, 0x3a, /* fpMinimumDamperOutputLow MSB */ | ||
443 | 0x1da2, 0xb8, /* fpMinimumDamperOutputLow LSB */ | ||
444 | 0x1e08, 0x06, /* MAXWeightLow */ | ||
445 | 0x1e0a, 0x0a, /* MAXWeightHigh */ | ||
446 | 0x1601, 0x3a, /* Red A MSB */ | ||
447 | 0x1602, 0x14, /* Red A LSB */ | ||
448 | 0x1605, 0x3b, /* Blue A MSB */ | ||
449 | 0x1606, 0x85, /* BLue A LSB */ | ||
450 | 0x1609, 0x3b, /* RED B MSB */ | ||
451 | 0x160a, 0x85, /* RED B LSB */ | ||
452 | 0x160d, 0x3a, /* Blue B MSB */ | ||
453 | 0x160e, 0x14, /* Blue B LSB */ | ||
454 | 0x1611, 0x30, /* Max Distance from Locus MSB */ | ||
455 | 0x1612, 0x8f, /* Max Distance from Locus MSB */ | ||
456 | 0x1614, 0x01, /* Enable constrainer */ | ||
457 | 0x0000, 0x00, | ||
458 | }; | ||
459 | |||
460 | static const u16 vs6624_default[] = { | ||
461 | VS6624_CONTRAST0, 0x84, | ||
462 | VS6624_SATURATION0, 0x75, | ||
463 | VS6624_GAMMA0, 0x11, | ||
464 | VS6624_CONTRAST1, 0x84, | ||
465 | VS6624_SATURATION1, 0x75, | ||
466 | VS6624_GAMMA1, 0x11, | ||
467 | VS6624_MAN_RG, 0x80, | ||
468 | VS6624_MAN_GG, 0x80, | ||
469 | VS6624_MAN_BG, 0x80, | ||
470 | VS6624_WB_MODE, 0x1, | ||
471 | VS6624_EXPO_COMPENSATION, 0xfe, | ||
472 | VS6624_EXPO_METER, 0x0, | ||
473 | VS6624_LIGHT_FREQ, 0x64, | ||
474 | VS6624_PEAK_GAIN, 0xe, | ||
475 | VS6624_PEAK_LOW_THR, 0x28, | ||
476 | VS6624_HMIRROR0, 0x0, | ||
477 | VS6624_VFLIP0, 0x0, | ||
478 | VS6624_ZOOM_HSTEP0_MSB, 0x0, | ||
479 | VS6624_ZOOM_HSTEP0_LSB, 0x1, | ||
480 | VS6624_ZOOM_VSTEP0_MSB, 0x0, | ||
481 | VS6624_ZOOM_VSTEP0_LSB, 0x1, | ||
482 | VS6624_PAN_HSTEP0_MSB, 0x0, | ||
483 | VS6624_PAN_HSTEP0_LSB, 0xf, | ||
484 | VS6624_PAN_VSTEP0_MSB, 0x0, | ||
485 | VS6624_PAN_VSTEP0_LSB, 0xf, | ||
486 | VS6624_SENSOR_MODE, 0x1, | ||
487 | VS6624_SYNC_CODE_SETUP, 0x21, | ||
488 | VS6624_DISABLE_FR_DAMPER, 0x0, | ||
489 | VS6624_FR_DEN, 0x1, | ||
490 | VS6624_FR_NUM_LSB, 0xf, | ||
491 | VS6624_INIT_PIPE_SETUP, 0x0, | ||
492 | VS6624_IMG_FMT0, 0x0, | ||
493 | VS6624_YUV_SETUP, 0x1, | ||
494 | VS6624_IMAGE_SIZE0, 0x2, | ||
495 | 0x0000, 0x00, | ||
496 | }; | ||
497 | |||
498 | static inline struct vs6624 *to_vs6624(struct v4l2_subdev *sd) | ||
499 | { | ||
500 | return container_of(sd, struct vs6624, sd); | ||
501 | } | ||
502 | static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) | ||
503 | { | ||
504 | return &container_of(ctrl->handler, struct vs6624, hdl)->sd; | ||
505 | } | ||
506 | |||
507 | static int vs6624_read(struct v4l2_subdev *sd, u16 index) | ||
508 | { | ||
509 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
510 | u8 buf[2]; | ||
511 | |||
512 | buf[0] = index >> 8; | ||
513 | buf[1] = index; | ||
514 | i2c_master_send(client, buf, 2); | ||
515 | i2c_master_recv(client, buf, 1); | ||
516 | |||
517 | return buf[0]; | ||
518 | } | ||
519 | |||
520 | static int vs6624_write(struct v4l2_subdev *sd, u16 index, | ||
521 | u8 value) | ||
522 | { | ||
523 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
524 | u8 buf[3]; | ||
525 | |||
526 | buf[0] = index >> 8; | ||
527 | buf[1] = index; | ||
528 | buf[2] = value; | ||
529 | |||
530 | return i2c_master_send(client, buf, 3); | ||
531 | } | ||
532 | |||
533 | static int vs6624_writeregs(struct v4l2_subdev *sd, const u16 *regs) | ||
534 | { | ||
535 | u16 reg; | ||
536 | u8 data; | ||
537 | |||
538 | while (*regs != 0x00) { | ||
539 | reg = *regs++; | ||
540 | data = *regs++; | ||
541 | |||
542 | vs6624_write(sd, reg, data); | ||
543 | } | ||
544 | return 0; | ||
545 | } | ||
546 | |||
547 | static int vs6624_s_ctrl(struct v4l2_ctrl *ctrl) | ||
548 | { | ||
549 | struct v4l2_subdev *sd = to_sd(ctrl); | ||
550 | |||
551 | switch (ctrl->id) { | ||
552 | case V4L2_CID_CONTRAST: | ||
553 | vs6624_write(sd, VS6624_CONTRAST0, ctrl->val); | ||
554 | break; | ||
555 | case V4L2_CID_SATURATION: | ||
556 | vs6624_write(sd, VS6624_SATURATION0, ctrl->val); | ||
557 | break; | ||
558 | case V4L2_CID_HFLIP: | ||
559 | vs6624_write(sd, VS6624_HMIRROR0, ctrl->val); | ||
560 | break; | ||
561 | case V4L2_CID_VFLIP: | ||
562 | vs6624_write(sd, VS6624_VFLIP0, ctrl->val); | ||
563 | break; | ||
564 | default: | ||
565 | return -EINVAL; | ||
566 | } | ||
567 | |||
568 | return 0; | ||
569 | } | ||
570 | |||
571 | static int vs6624_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index, | ||
572 | enum v4l2_mbus_pixelcode *code) | ||
573 | { | ||
574 | if (index >= ARRAY_SIZE(vs6624_formats)) | ||
575 | return -EINVAL; | ||
576 | |||
577 | *code = vs6624_formats[index].mbus_code; | ||
578 | return 0; | ||
579 | } | ||
580 | |||
581 | static int vs6624_try_mbus_fmt(struct v4l2_subdev *sd, | ||
582 | struct v4l2_mbus_framefmt *fmt) | ||
583 | { | ||
584 | int index; | ||
585 | |||
586 | for (index = 0; index < ARRAY_SIZE(vs6624_formats); index++) | ||
587 | if (vs6624_formats[index].mbus_code == fmt->code) | ||
588 | break; | ||
589 | if (index >= ARRAY_SIZE(vs6624_formats)) { | ||
590 | /* default to first format */ | ||
591 | index = 0; | ||
592 | fmt->code = vs6624_formats[0].mbus_code; | ||
593 | } | ||
594 | |||
595 | /* sensor mode is VGA */ | ||
596 | if (fmt->width > VGA_WIDTH) | ||
597 | fmt->width = VGA_WIDTH; | ||
598 | if (fmt->height > VGA_HEIGHT) | ||
599 | fmt->height = VGA_HEIGHT; | ||
600 | fmt->width = fmt->width & (~3); | ||
601 | fmt->height = fmt->height & (~3); | ||
602 | fmt->field = V4L2_FIELD_NONE; | ||
603 | fmt->colorspace = vs6624_formats[index].colorspace; | ||
604 | return 0; | ||
605 | } | ||
606 | |||
607 | static int vs6624_s_mbus_fmt(struct v4l2_subdev *sd, | ||
608 | struct v4l2_mbus_framefmt *fmt) | ||
609 | { | ||
610 | struct vs6624 *sensor = to_vs6624(sd); | ||
611 | int ret; | ||
612 | |||
613 | ret = vs6624_try_mbus_fmt(sd, fmt); | ||
614 | if (ret) | ||
615 | return ret; | ||
616 | |||
617 | /* set image format */ | ||
618 | switch (fmt->code) { | ||
619 | case V4L2_MBUS_FMT_UYVY8_2X8: | ||
620 | vs6624_write(sd, VS6624_IMG_FMT0, 0x0); | ||
621 | vs6624_write(sd, VS6624_YUV_SETUP, 0x1); | ||
622 | break; | ||
623 | case V4L2_MBUS_FMT_YUYV8_2X8: | ||
624 | vs6624_write(sd, VS6624_IMG_FMT0, 0x0); | ||
625 | vs6624_write(sd, VS6624_YUV_SETUP, 0x3); | ||
626 | break; | ||
627 | case V4L2_MBUS_FMT_RGB565_2X8_LE: | ||
628 | vs6624_write(sd, VS6624_IMG_FMT0, 0x4); | ||
629 | vs6624_write(sd, VS6624_RGB_SETUP, 0x0); | ||
630 | break; | ||
631 | default: | ||
632 | return -EINVAL; | ||
633 | } | ||
634 | |||
635 | /* set image size */ | ||
636 | if ((fmt->width == VGA_WIDTH) && (fmt->height == VGA_HEIGHT)) | ||
637 | vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x2); | ||
638 | else if ((fmt->width == QVGA_WIDTH) && (fmt->height == QVGA_HEIGHT)) | ||
639 | vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x4); | ||
640 | else if ((fmt->width == QQVGA_WIDTH) && (fmt->height == QQVGA_HEIGHT)) | ||
641 | vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x6); | ||
642 | else if ((fmt->width == CIF_WIDTH) && (fmt->height == CIF_HEIGHT)) | ||
643 | vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x3); | ||
644 | else if ((fmt->width == QCIF_WIDTH) && (fmt->height == QCIF_HEIGHT)) | ||
645 | vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x5); | ||
646 | else if ((fmt->width == QQCIF_WIDTH) && (fmt->height == QQCIF_HEIGHT)) | ||
647 | vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x7); | ||
648 | else { | ||
649 | vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x8); | ||
650 | vs6624_write(sd, VS6624_MAN_HSIZE0_MSB, fmt->width >> 8); | ||
651 | vs6624_write(sd, VS6624_MAN_HSIZE0_LSB, fmt->width & 0xFF); | ||
652 | vs6624_write(sd, VS6624_MAN_VSIZE0_MSB, fmt->height >> 8); | ||
653 | vs6624_write(sd, VS6624_MAN_VSIZE0_LSB, fmt->height & 0xFF); | ||
654 | vs6624_write(sd, VS6624_CROP_CTRL0, 0x1); | ||
655 | } | ||
656 | |||
657 | sensor->fmt = *fmt; | ||
658 | |||
659 | return 0; | ||
660 | } | ||
661 | |||
662 | static int vs6624_g_mbus_fmt(struct v4l2_subdev *sd, | ||
663 | struct v4l2_mbus_framefmt *fmt) | ||
664 | { | ||
665 | struct vs6624 *sensor = to_vs6624(sd); | ||
666 | |||
667 | *fmt = sensor->fmt; | ||
668 | return 0; | ||
669 | } | ||
670 | |||
671 | static int vs6624_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) | ||
672 | { | ||
673 | struct vs6624 *sensor = to_vs6624(sd); | ||
674 | struct v4l2_captureparm *cp = &parms->parm.capture; | ||
675 | |||
676 | if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
677 | return -EINVAL; | ||
678 | |||
679 | memset(cp, 0, sizeof(*cp)); | ||
680 | cp->capability = V4L2_CAP_TIMEPERFRAME; | ||
681 | cp->timeperframe.numerator = sensor->frame_rate.denominator; | ||
682 | cp->timeperframe.denominator = sensor->frame_rate.numerator; | ||
683 | return 0; | ||
684 | } | ||
685 | |||
686 | static int vs6624_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) | ||
687 | { | ||
688 | struct vs6624 *sensor = to_vs6624(sd); | ||
689 | struct v4l2_captureparm *cp = &parms->parm.capture; | ||
690 | struct v4l2_fract *tpf = &cp->timeperframe; | ||
691 | |||
692 | if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
693 | return -EINVAL; | ||
694 | if (cp->extendedmode != 0) | ||
695 | return -EINVAL; | ||
696 | |||
697 | if (tpf->numerator == 0 || tpf->denominator == 0 | ||
698 | || (tpf->denominator > tpf->numerator * MAX_FRAME_RATE)) { | ||
699 | /* reset to max frame rate */ | ||
700 | tpf->numerator = 1; | ||
701 | tpf->denominator = MAX_FRAME_RATE; | ||
702 | } | ||
703 | sensor->frame_rate.numerator = tpf->denominator; | ||
704 | sensor->frame_rate.denominator = tpf->numerator; | ||
705 | vs6624_write(sd, VS6624_DISABLE_FR_DAMPER, 0x0); | ||
706 | vs6624_write(sd, VS6624_FR_NUM_MSB, | ||
707 | sensor->frame_rate.numerator >> 8); | ||
708 | vs6624_write(sd, VS6624_FR_NUM_LSB, | ||
709 | sensor->frame_rate.numerator & 0xFF); | ||
710 | vs6624_write(sd, VS6624_FR_DEN, | ||
711 | sensor->frame_rate.denominator & 0xFF); | ||
712 | return 0; | ||
713 | } | ||
714 | |||
715 | static int vs6624_s_stream(struct v4l2_subdev *sd, int enable) | ||
716 | { | ||
717 | if (enable) | ||
718 | vs6624_write(sd, VS6624_USER_CMD, 0x2); | ||
719 | else | ||
720 | vs6624_write(sd, VS6624_USER_CMD, 0x4); | ||
721 | udelay(100); | ||
722 | return 0; | ||
723 | } | ||
724 | |||
725 | static int vs6624_g_chip_ident(struct v4l2_subdev *sd, | ||
726 | struct v4l2_dbg_chip_ident *chip) | ||
727 | { | ||
728 | int rev; | ||
729 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
730 | |||
731 | rev = (vs6624_read(sd, VS6624_FW_VSN_MAJOR) << 8) | ||
732 | | vs6624_read(sd, VS6624_FW_VSN_MINOR); | ||
733 | |||
734 | return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_VS6624, rev); | ||
735 | } | ||
736 | |||
737 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
738 | static int vs6624_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) | ||
739 | { | ||
740 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
741 | |||
742 | if (!v4l2_chip_match_i2c_client(client, ®->match)) | ||
743 | return -EINVAL; | ||
744 | if (!capable(CAP_SYS_ADMIN)) | ||
745 | return -EPERM; | ||
746 | reg->val = vs6624_read(sd, reg->reg & 0xffff); | ||
747 | reg->size = 1; | ||
748 | return 0; | ||
749 | } | ||
750 | |||
751 | static int vs6624_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) | ||
752 | { | ||
753 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
754 | |||
755 | if (!v4l2_chip_match_i2c_client(client, ®->match)) | ||
756 | return -EINVAL; | ||
757 | if (!capable(CAP_SYS_ADMIN)) | ||
758 | return -EPERM; | ||
759 | vs6624_write(sd, reg->reg & 0xffff, reg->val & 0xff); | ||
760 | return 0; | ||
761 | } | ||
762 | #endif | ||
763 | |||
764 | static const struct v4l2_ctrl_ops vs6624_ctrl_ops = { | ||
765 | .s_ctrl = vs6624_s_ctrl, | ||
766 | }; | ||
767 | |||
768 | static const struct v4l2_subdev_core_ops vs6624_core_ops = { | ||
769 | .g_chip_ident = vs6624_g_chip_ident, | ||
770 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
771 | .g_register = vs6624_g_register, | ||
772 | .s_register = vs6624_s_register, | ||
773 | #endif | ||
774 | }; | ||
775 | |||
776 | static const struct v4l2_subdev_video_ops vs6624_video_ops = { | ||
777 | .enum_mbus_fmt = vs6624_enum_mbus_fmt, | ||
778 | .try_mbus_fmt = vs6624_try_mbus_fmt, | ||
779 | .s_mbus_fmt = vs6624_s_mbus_fmt, | ||
780 | .g_mbus_fmt = vs6624_g_mbus_fmt, | ||
781 | .s_parm = vs6624_s_parm, | ||
782 | .g_parm = vs6624_g_parm, | ||
783 | .s_stream = vs6624_s_stream, | ||
784 | }; | ||
785 | |||
786 | static const struct v4l2_subdev_ops vs6624_ops = { | ||
787 | .core = &vs6624_core_ops, | ||
788 | .video = &vs6624_video_ops, | ||
789 | }; | ||
790 | |||
791 | static int __devinit vs6624_probe(struct i2c_client *client, | ||
792 | const struct i2c_device_id *id) | ||
793 | { | ||
794 | struct vs6624 *sensor; | ||
795 | struct v4l2_subdev *sd; | ||
796 | struct v4l2_ctrl_handler *hdl; | ||
797 | const unsigned *ce; | ||
798 | int ret; | ||
799 | |||
800 | /* Check if the adapter supports the needed features */ | ||
801 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) | ||
802 | return -EIO; | ||
803 | |||
804 | ce = client->dev.platform_data; | ||
805 | if (ce == NULL) | ||
806 | return -EINVAL; | ||
807 | |||
808 | ret = gpio_request(*ce, "VS6624 Chip Enable"); | ||
809 | if (ret) { | ||
810 | v4l_err(client, "failed to request GPIO %d\n", *ce); | ||
811 | return ret; | ||
812 | } | ||
813 | gpio_direction_output(*ce, 1); | ||
814 | /* wait 100ms before any further i2c writes are performed */ | ||
815 | mdelay(100); | ||
816 | |||
817 | sensor = kzalloc(sizeof(*sensor), GFP_KERNEL); | ||
818 | if (sensor == NULL) { | ||
819 | gpio_free(*ce); | ||
820 | return -ENOMEM; | ||
821 | } | ||
822 | |||
823 | sd = &sensor->sd; | ||
824 | v4l2_i2c_subdev_init(sd, client, &vs6624_ops); | ||
825 | |||
826 | vs6624_writeregs(sd, vs6624_p1); | ||
827 | vs6624_write(sd, VS6624_MICRO_EN, 0x2); | ||
828 | vs6624_write(sd, VS6624_DIO_EN, 0x1); | ||
829 | mdelay(10); | ||
830 | vs6624_writeregs(sd, vs6624_p2); | ||
831 | |||
832 | vs6624_writeregs(sd, vs6624_default); | ||
833 | vs6624_write(sd, VS6624_HSYNC_SETUP, 0xF); | ||
834 | vs6624_writeregs(sd, vs6624_run_setup); | ||
835 | |||
836 | /* set frame rate */ | ||
837 | sensor->frame_rate.numerator = MAX_FRAME_RATE; | ||
838 | sensor->frame_rate.denominator = 1; | ||
839 | vs6624_write(sd, VS6624_DISABLE_FR_DAMPER, 0x0); | ||
840 | vs6624_write(sd, VS6624_FR_NUM_MSB, | ||
841 | sensor->frame_rate.numerator >> 8); | ||
842 | vs6624_write(sd, VS6624_FR_NUM_LSB, | ||
843 | sensor->frame_rate.numerator & 0xFF); | ||
844 | vs6624_write(sd, VS6624_FR_DEN, | ||
845 | sensor->frame_rate.denominator & 0xFF); | ||
846 | |||
847 | sensor->fmt = vs6624_default_fmt; | ||
848 | sensor->ce_pin = *ce; | ||
849 | |||
850 | v4l_info(client, "chip found @ 0x%02x (%s)\n", | ||
851 | client->addr << 1, client->adapter->name); | ||
852 | |||
853 | hdl = &sensor->hdl; | ||
854 | v4l2_ctrl_handler_init(hdl, 4); | ||
855 | v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops, | ||
856 | V4L2_CID_CONTRAST, 0, 0xFF, 1, 0x87); | ||
857 | v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops, | ||
858 | V4L2_CID_SATURATION, 0, 0xFF, 1, 0x78); | ||
859 | v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops, | ||
860 | V4L2_CID_HFLIP, 0, 1, 1, 0); | ||
861 | v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops, | ||
862 | V4L2_CID_VFLIP, 0, 1, 1, 0); | ||
863 | /* hook the control handler into the driver */ | ||
864 | sd->ctrl_handler = hdl; | ||
865 | if (hdl->error) { | ||
866 | int err = hdl->error; | ||
867 | |||
868 | v4l2_ctrl_handler_free(hdl); | ||
869 | kfree(sensor); | ||
870 | gpio_free(*ce); | ||
871 | return err; | ||
872 | } | ||
873 | |||
874 | /* initialize the hardware to the default control values */ | ||
875 | ret = v4l2_ctrl_handler_setup(hdl); | ||
876 | if (ret) { | ||
877 | v4l2_ctrl_handler_free(hdl); | ||
878 | kfree(sensor); | ||
879 | gpio_free(*ce); | ||
880 | } | ||
881 | return ret; | ||
882 | } | ||
883 | |||
884 | static int __devexit vs6624_remove(struct i2c_client *client) | ||
885 | { | ||
886 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
887 | struct vs6624 *sensor = to_vs6624(sd); | ||
888 | |||
889 | v4l2_device_unregister_subdev(sd); | ||
890 | v4l2_ctrl_handler_free(sd->ctrl_handler); | ||
891 | gpio_free(sensor->ce_pin); | ||
892 | kfree(sensor); | ||
893 | return 0; | ||
894 | } | ||
895 | |||
896 | static const struct i2c_device_id vs6624_id[] = { | ||
897 | {"vs6624", 0}, | ||
898 | {}, | ||
899 | }; | ||
900 | |||
901 | MODULE_DEVICE_TABLE(i2c, vs6624_id); | ||
902 | |||
903 | static struct i2c_driver vs6624_driver = { | ||
904 | .driver = { | ||
905 | .owner = THIS_MODULE, | ||
906 | .name = "vs6624", | ||
907 | }, | ||
908 | .probe = vs6624_probe, | ||
909 | .remove = __devexit_p(vs6624_remove), | ||
910 | .id_table = vs6624_id, | ||
911 | }; | ||
912 | |||
913 | static __init int vs6624_init(void) | ||
914 | { | ||
915 | return i2c_add_driver(&vs6624_driver); | ||
916 | } | ||
917 | |||
918 | static __exit void vs6624_exit(void) | ||
919 | { | ||
920 | i2c_del_driver(&vs6624_driver); | ||
921 | } | ||
922 | |||
923 | module_init(vs6624_init); | ||
924 | module_exit(vs6624_exit); | ||
925 | |||
926 | MODULE_DESCRIPTION("VS6624 sensor driver"); | ||
927 | MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>"); | ||
928 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/media/video/vs6624_regs.h b/drivers/media/video/vs6624_regs.h new file mode 100644 index 000000000000..6ba2ee25827e --- /dev/null +++ b/drivers/media/video/vs6624_regs.h | |||
@@ -0,0 +1,337 @@ | |||
1 | /* | ||
2 | * vs6624 - ST VS6624 CMOS image sensor registers | ||
3 | * | ||
4 | * Copyright (c) 2011 Analog Devices Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | |||
20 | #ifndef _VS6624_REGS_H_ | ||
21 | #define _VS6624_REGS_H_ | ||
22 | |||
23 | /* low level control registers */ | ||
24 | #define VS6624_MICRO_EN 0xC003 /* power enable for all MCU clock */ | ||
25 | #define VS6624_DIO_EN 0xC044 /* enable digital I/O */ | ||
26 | /* device parameters */ | ||
27 | #define VS6624_DEV_ID_MSB 0x0001 /* device id MSB */ | ||
28 | #define VS6624_DEV_ID_LSB 0x0002 /* device id LSB */ | ||
29 | #define VS6624_FW_VSN_MAJOR 0x0004 /* firmware version major */ | ||
30 | #define VS6624_FW_VSN_MINOR 0x0006 /* firmware version minor */ | ||
31 | #define VS6624_PATCH_VSN_MAJOR 0x0008 /* patch version major */ | ||
32 | #define VS6624_PATCH_VSN_MINOR 0x000A /* patch version minor */ | ||
33 | /* host interface manager control */ | ||
34 | #define VS6624_USER_CMD 0x0180 /* user level control of operating states */ | ||
35 | /* host interface manager status */ | ||
36 | #define VS6624_STATE 0x0202 /* current state of the mode manager */ | ||
37 | /* run mode control */ | ||
38 | #define VS6624_METER_ON 0x0280 /* if false AE and AWB are disabled */ | ||
39 | /* mode setup */ | ||
40 | #define VS6624_ACTIVE_PIPE_SETUP 0x0302 /* select the active bank for non view live mode */ | ||
41 | #define VS6624_SENSOR_MODE 0x0308 /* select the different sensor mode */ | ||
42 | /* pipe setup bank0 */ | ||
43 | #define VS6624_IMAGE_SIZE0 0x0380 /* required output dimension */ | ||
44 | #define VS6624_MAN_HSIZE0_MSB 0x0383 /* input required manual H size MSB */ | ||
45 | #define VS6624_MAN_HSIZE0_LSB 0x0384 /* input required manual H size LSB */ | ||
46 | #define VS6624_MAN_VSIZE0_MSB 0x0387 /* input required manual V size MSB */ | ||
47 | #define VS6624_MAN_VSIZE0_LSB 0x0388 /* input required manual V size LSB */ | ||
48 | #define VS6624_ZOOM_HSTEP0_MSB 0x038B /* set the zoom H step MSB */ | ||
49 | #define VS6624_ZOOM_HSTEP0_LSB 0x038C /* set the zoom H step LSB */ | ||
50 | #define VS6624_ZOOM_VSTEP0_MSB 0x038F /* set the zoom V step MSB */ | ||
51 | #define VS6624_ZOOM_VSTEP0_LSB 0x0390 /* set the zoom V step LSB */ | ||
52 | #define VS6624_ZOOM_CTRL0 0x0392 /* control zoon in, out and stop */ | ||
53 | #define VS6624_PAN_HSTEP0_MSB 0x0395 /* set the pan H step MSB */ | ||
54 | #define VS6624_PAN_HSTEP0_LSB 0x0396 /* set the pan H step LSB */ | ||
55 | #define VS6624_PAN_VSTEP0_MSB 0x0399 /* set the pan V step MSB */ | ||
56 | #define VS6624_PAN_VSTEP0_LSB 0x039A /* set the pan V step LSB */ | ||
57 | #define VS6624_PAN_CTRL0 0x039C /* control pan operation */ | ||
58 | #define VS6624_CROP_CTRL0 0x039E /* select cropping mode */ | ||
59 | #define VS6624_CROP_HSTART0_MSB 0x03A1 /* set the cropping H start address MSB */ | ||
60 | #define VS6624_CROP_HSTART0_LSB 0x03A2 /* set the cropping H start address LSB */ | ||
61 | #define VS6624_CROP_HSIZE0_MSB 0x03A5 /* set the cropping H size MSB */ | ||
62 | #define VS6624_CROP_HSIZE0_LSB 0x03A6 /* set the cropping H size LSB */ | ||
63 | #define VS6624_CROP_VSTART0_MSB 0x03A9 /* set the cropping V start address MSB */ | ||
64 | #define VS6624_CROP_VSTART0_LSB 0x03AA /* set the cropping V start address LSB */ | ||
65 | #define VS6624_CROP_VSIZE0_MSB 0x03AD /* set the cropping V size MSB */ | ||
66 | #define VS6624_CROP_VSIZE0_LSB 0x03AE /* set the cropping V size LSB */ | ||
67 | #define VS6624_IMG_FMT0 0x03B0 /* select required output image format */ | ||
68 | #define VS6624_BAYER_OUT_ALIGN0 0x03B2 /* set bayer output alignment */ | ||
69 | #define VS6624_CONTRAST0 0x03B4 /* contrast control for output */ | ||
70 | #define VS6624_SATURATION0 0x03B6 /* saturation control for output */ | ||
71 | #define VS6624_GAMMA0 0x03B8 /* gamma settings */ | ||
72 | #define VS6624_HMIRROR0 0x03BA /* horizontal image orientation flip */ | ||
73 | #define VS6624_VFLIP0 0x03BC /* vertical image orientation flip */ | ||
74 | #define VS6624_CHANNEL_ID0 0x03BE /* logical DMA channel number */ | ||
75 | /* pipe setup bank1 */ | ||
76 | #define VS6624_IMAGE_SIZE1 0x0400 /* required output dimension */ | ||
77 | #define VS6624_MAN_HSIZE1_MSB 0x0403 /* input required manual H size MSB */ | ||
78 | #define VS6624_MAN_HSIZE1_LSB 0x0404 /* input required manual H size LSB */ | ||
79 | #define VS6624_MAN_VSIZE1_MSB 0x0407 /* input required manual V size MSB */ | ||
80 | #define VS6624_MAN_VSIZE1_LSB 0x0408 /* input required manual V size LSB */ | ||
81 | #define VS6624_ZOOM_HSTEP1_MSB 0x040B /* set the zoom H step MSB */ | ||
82 | #define VS6624_ZOOM_HSTEP1_LSB 0x040C /* set the zoom H step LSB */ | ||
83 | #define VS6624_ZOOM_VSTEP1_MSB 0x040F /* set the zoom V step MSB */ | ||
84 | #define VS6624_ZOOM_VSTEP1_LSB 0x0410 /* set the zoom V step LSB */ | ||
85 | #define VS6624_ZOOM_CTRL1 0x0412 /* control zoon in, out and stop */ | ||
86 | #define VS6624_PAN_HSTEP1_MSB 0x0415 /* set the pan H step MSB */ | ||
87 | #define VS6624_PAN_HSTEP1_LSB 0x0416 /* set the pan H step LSB */ | ||
88 | #define VS6624_PAN_VSTEP1_MSB 0x0419 /* set the pan V step MSB */ | ||
89 | #define VS6624_PAN_VSTEP1_LSB 0x041A /* set the pan V step LSB */ | ||
90 | #define VS6624_PAN_CTRL1 0x041C /* control pan operation */ | ||
91 | #define VS6624_CROP_CTRL1 0x041E /* select cropping mode */ | ||
92 | #define VS6624_CROP_HSTART1_MSB 0x0421 /* set the cropping H start address MSB */ | ||
93 | #define VS6624_CROP_HSTART1_LSB 0x0422 /* set the cropping H start address LSB */ | ||
94 | #define VS6624_CROP_HSIZE1_MSB 0x0425 /* set the cropping H size MSB */ | ||
95 | #define VS6624_CROP_HSIZE1_LSB 0x0426 /* set the cropping H size LSB */ | ||
96 | #define VS6624_CROP_VSTART1_MSB 0x0429 /* set the cropping V start address MSB */ | ||
97 | #define VS6624_CROP_VSTART1_LSB 0x042A /* set the cropping V start address LSB */ | ||
98 | #define VS6624_CROP_VSIZE1_MSB 0x042D /* set the cropping V size MSB */ | ||
99 | #define VS6624_CROP_VSIZE1_LSB 0x042E /* set the cropping V size LSB */ | ||
100 | #define VS6624_IMG_FMT1 0x0430 /* select required output image format */ | ||
101 | #define VS6624_BAYER_OUT_ALIGN1 0x0432 /* set bayer output alignment */ | ||
102 | #define VS6624_CONTRAST1 0x0434 /* contrast control for output */ | ||
103 | #define VS6624_SATURATION1 0x0436 /* saturation control for output */ | ||
104 | #define VS6624_GAMMA1 0x0438 /* gamma settings */ | ||
105 | #define VS6624_HMIRROR1 0x043A /* horizontal image orientation flip */ | ||
106 | #define VS6624_VFLIP1 0x043C /* vertical image orientation flip */ | ||
107 | #define VS6624_CHANNEL_ID1 0x043E /* logical DMA channel number */ | ||
108 | /* view live control */ | ||
109 | #define VS6624_VIEW_LIVE_EN 0x0480 /* enable view live mode */ | ||
110 | #define VS6624_INIT_PIPE_SETUP 0x0482 /* select initial pipe setup bank */ | ||
111 | /* view live status */ | ||
112 | #define VS6624_CUR_PIPE_SETUP 0x0500 /* indicates most recently applied setup bank */ | ||
113 | /* power management */ | ||
114 | #define VS6624_TIME_TO_POWER_DOWN 0x0580 /* automatically transition time to stop mode */ | ||
115 | /* video timing parameter host inputs */ | ||
116 | #define VS6624_EXT_CLK_FREQ_NUM_MSB 0x0605 /* external clock frequency numerator MSB */ | ||
117 | #define VS6624_EXT_CLK_FREQ_NUM_LSB 0x0606 /* external clock frequency numerator LSB */ | ||
118 | #define VS6624_EXT_CLK_FREQ_DEN 0x0608 /* external clock frequency denominator */ | ||
119 | /* video timing control */ | ||
120 | #define VS6624_SYS_CLK_MODE 0x0880 /* decides system clock frequency */ | ||
121 | /* frame dimension parameter host inputs */ | ||
122 | #define VS6624_LIGHT_FREQ 0x0C80 /* AC frequency used for flicker free time */ | ||
123 | #define VS6624_FLICKER_COMPAT 0x0C82 /* flicker compatible frame length */ | ||
124 | /* static frame rate control */ | ||
125 | #define VS6624_FR_NUM_MSB 0x0D81 /* desired frame rate numerator MSB */ | ||
126 | #define VS6624_FR_NUM_LSB 0x0D82 /* desired frame rate numerator LSB */ | ||
127 | #define VS6624_FR_DEN 0x0D84 /* desired frame rate denominator */ | ||
128 | /* automatic frame rate control */ | ||
129 | #define VS6624_DISABLE_FR_DAMPER 0x0E80 /* defines frame rate mode */ | ||
130 | #define VS6624_MIN_DAMPER_OUT_MSB 0x0E8C /* minimum frame rate MSB */ | ||
131 | #define VS6624_MIN_DAMPER_OUT_LSB 0x0E8A /* minimum frame rate LSB */ | ||
132 | /* exposure controls */ | ||
133 | #define VS6624_EXPO_MODE 0x1180 /* exposure mode */ | ||
134 | #define VS6624_EXPO_METER 0x1182 /* weights to be associated with the zones */ | ||
135 | #define VS6624_EXPO_TIME_NUM 0x1184 /* exposure time numerator */ | ||
136 | #define VS6624_EXPO_TIME_DEN 0x1186 /* exposure time denominator */ | ||
137 | #define VS6624_EXPO_TIME_MSB 0x1189 /* exposure time for the Manual Mode MSB */ | ||
138 | #define VS6624_EXPO_TIME_LSB 0x118A /* exposure time for the Manual Mode LSB */ | ||
139 | #define VS6624_EXPO_COMPENSATION 0x1190 /* exposure compensation */ | ||
140 | #define VS6624_DIRECT_COARSE_MSB 0x1195 /* coarse integration lines for Direct Mode MSB */ | ||
141 | #define VS6624_DIRECT_COARSE_LSB 0x1196 /* coarse integration lines for Direct Mode LSB */ | ||
142 | #define VS6624_DIRECT_FINE_MSB 0x1199 /* fine integration pixels for Direct Mode MSB */ | ||
143 | #define VS6624_DIRECT_FINE_LSB 0x119A /* fine integration pixels for Direct Mode LSB */ | ||
144 | #define VS6624_DIRECT_ANAL_GAIN_MSB 0x119D /* analog gain for Direct Mode MSB */ | ||
145 | #define VS6624_DIRECT_ANAL_GAIN_LSB 0x119E /* analog gain for Direct Mode LSB */ | ||
146 | #define VS6624_DIRECT_DIGI_GAIN_MSB 0x11A1 /* digital gain for Direct Mode MSB */ | ||
147 | #define VS6624_DIRECT_DIGI_GAIN_LSB 0x11A2 /* digital gain for Direct Mode LSB */ | ||
148 | #define VS6624_FLASH_COARSE_MSB 0x11A5 /* coarse integration lines for Flash Gun Mode MSB */ | ||
149 | #define VS6624_FLASH_COARSE_LSB 0x11A6 /* coarse integration lines for Flash Gun Mode LSB */ | ||
150 | #define VS6624_FLASH_FINE_MSB 0x11A9 /* fine integration pixels for Flash Gun Mode MSB */ | ||
151 | #define VS6624_FLASH_FINE_LSB 0x11AA /* fine integration pixels for Flash Gun Mode LSB */ | ||
152 | #define VS6624_FLASH_ANAL_GAIN_MSB 0x11AD /* analog gain for Flash Gun Mode MSB */ | ||
153 | #define VS6624_FLASH_ANAL_GAIN_LSB 0x11AE /* analog gain for Flash Gun Mode LSB */ | ||
154 | #define VS6624_FLASH_DIGI_GAIN_MSB 0x11B1 /* digital gain for Flash Gun Mode MSB */ | ||
155 | #define VS6624_FLASH_DIGI_GAIN_LSB 0x11B2 /* digital gain for Flash Gun Mode LSB */ | ||
156 | #define VS6624_FREEZE_AE 0x11B4 /* freeze auto exposure */ | ||
157 | #define VS6624_MAX_INT_TIME_MSB 0x11B7 /* user maximum integration time MSB */ | ||
158 | #define VS6624_MAX_INT_TIME_LSB 0x11B8 /* user maximum integration time LSB */ | ||
159 | #define VS6624_FLASH_AG_THR_MSB 0x11BB /* recommend flash gun analog gain threshold MSB */ | ||
160 | #define VS6624_FLASH_AG_THR_LSB 0x11BC /* recommend flash gun analog gain threshold LSB */ | ||
161 | #define VS6624_ANTI_FLICKER_MODE 0x11C0 /* anti flicker mode */ | ||
162 | /* white balance control */ | ||
163 | #define VS6624_WB_MODE 0x1480 /* set white balance mode */ | ||
164 | #define VS6624_MAN_RG 0x1482 /* user setting for red channel gain */ | ||
165 | #define VS6624_MAN_GG 0x1484 /* user setting for green channel gain */ | ||
166 | #define VS6624_MAN_BG 0x1486 /* user setting for blue channel gain */ | ||
167 | #define VS6624_FLASH_RG_MSB 0x148B /* red gain for Flash Gun MSB */ | ||
168 | #define VS6624_FLASH_RG_LSB 0x148C /* red gain for Flash Gun LSB */ | ||
169 | #define VS6624_FLASH_GG_MSB 0x148F /* green gain for Flash Gun MSB */ | ||
170 | #define VS6624_FLASH_GG_LSB 0x1490 /* green gain for Flash Gun LSB */ | ||
171 | #define VS6624_FLASH_BG_MSB 0x1493 /* blue gain for Flash Gun MSB */ | ||
172 | #define VS6624_FLASH_BG_LSB 0x1494 /* blue gain for Flash Gun LSB */ | ||
173 | /* sensor setup */ | ||
174 | #define VS6624_BC_OFFSET 0x1990 /* Black Correction Offset */ | ||
175 | /* image stability */ | ||
176 | #define VS6624_STABLE_WB 0x1900 /* white balance stable */ | ||
177 | #define VS6624_STABLE_EXPO 0x1902 /* exposure stable */ | ||
178 | #define VS6624_STABLE 0x1906 /* system stable */ | ||
179 | /* flash control */ | ||
180 | #define VS6624_FLASH_MODE 0x1A80 /* flash mode */ | ||
181 | #define VS6624_FLASH_OFF_LINE_MSB 0x1A83 /* off line at flash pulse mode MSB */ | ||
182 | #define VS6624_FLASH_OFF_LINE_LSB 0x1A84 /* off line at flash pulse mode LSB */ | ||
183 | /* flash status */ | ||
184 | #define VS6624_FLASH_RECOM 0x1B00 /* flash gun is recommended */ | ||
185 | #define VS6624_FLASH_GRAB_COMPLETE 0x1B02 /* flash gun image has been grabbed */ | ||
186 | /* scythe filter controls */ | ||
187 | #define VS6624_SCYTHE_FILTER 0x1D80 /* disable scythe defect correction */ | ||
188 | /* jack filter controls */ | ||
189 | #define VS6624_JACK_FILTER 0x1E00 /* disable jack defect correction */ | ||
190 | /* demosaic control */ | ||
191 | #define VS6624_ANTI_ALIAS_FILTER 0x1E80 /* anti alias filter suppress */ | ||
192 | /* color matrix dampers */ | ||
193 | #define VS6624_CM_DISABLE 0x1F00 /* disable color matrix damper */ | ||
194 | #define VS6624_CM_LOW_THR_MSB 0x1F03 /* low threshold for exposure MSB */ | ||
195 | #define VS6624_CM_LOW_THR_LSB 0x1F04 /* low threshold for exposure LSB */ | ||
196 | #define VS6624_CM_HIGH_THR_MSB 0x1F07 /* high threshold for exposure MSB */ | ||
197 | #define VS6624_CM_HIGH_THR_LSB 0x1F08 /* high threshold for exposure LSB */ | ||
198 | #define VS6624_CM_MIN_OUT_MSB 0x1F0B /* minimum possible damper output MSB */ | ||
199 | #define VS6624_CM_MIN_OUT_LSB 0x1F0C /* minimum possible damper output LSB */ | ||
200 | /* peaking control */ | ||
201 | #define VS6624_PEAK_GAIN 0x2000 /* controls peaking gain */ | ||
202 | #define VS6624_PEAK_G_DISABLE 0x2002 /* disable peak gain damping */ | ||
203 | #define VS6624_PEAK_LOW_THR_G_MSB 0x2005 /* low threshold for exposure for gain MSB */ | ||
204 | #define VS6624_PEAK_LOW_THR_G_LSB 0x2006 /* low threshold for exposure for gain LSB */ | ||
205 | #define VS6624_PEAK_HIGH_THR_G_MSB 0x2009 /* high threshold for exposure for gain MSB */ | ||
206 | #define VS6624_PEAK_HIGH_THR_G_LSB 0x200A /* high threshold for exposure for gain LSB */ | ||
207 | #define VS6624_PEAK_MIN_OUT_G_MSB 0x200D /* minimum damper output for gain MSB */ | ||
208 | #define VS6624_PEAK_MIN_OUT_G_LSB 0x200E /* minimum damper output for gain LSB */ | ||
209 | #define VS6624_PEAK_LOW_THR 0x2010 /* adjust degree of coring */ | ||
210 | #define VS6624_PEAK_C_DISABLE 0x2012 /* disable coring damping */ | ||
211 | #define VS6624_PEAK_HIGH_THR 0x2014 /* adjust maximum gain */ | ||
212 | #define VS6624_PEAK_LOW_THR_C_MSB 0x2017 /* low threshold for exposure for coring MSB */ | ||
213 | #define VS6624_PEAK_LOW_THR_C_LSB 0x2018 /* low threshold for exposure for coring LSB */ | ||
214 | #define VS6624_PEAK_HIGH_THR_C_MSB 0x201B /* high threshold for exposure for coring MSB */ | ||
215 | #define VS6624_PEAK_HIGH_THR_C_LSB 0x201C /* high threshold for exposure for coring LSB */ | ||
216 | #define VS6624_PEAK_MIN_OUT_C_MSB 0x201F /* minimum damper output for coring MSB */ | ||
217 | #define VS6624_PEAK_MIN_OUT_C_LSB 0x2020 /* minimum damper output for coring LSB */ | ||
218 | /* pipe 0 RGB to YUV matrix manual control */ | ||
219 | #define VS6624_RYM0_MAN_CTRL 0x2180 /* enable manual RGB to YUV matrix */ | ||
220 | #define VS6624_RYM0_W00_MSB 0x2183 /* row 0 column 0 of YUV matrix MSB */ | ||
221 | #define VS6624_RYM0_W00_LSB 0x2184 /* row 0 column 0 of YUV matrix LSB */ | ||
222 | #define VS6624_RYM0_W01_MSB 0x2187 /* row 0 column 1 of YUV matrix MSB */ | ||
223 | #define VS6624_RYM0_W01_LSB 0x2188 /* row 0 column 1 of YUV matrix LSB */ | ||
224 | #define VS6624_RYM0_W02_MSB 0x218C /* row 0 column 2 of YUV matrix MSB */ | ||
225 | #define VS6624_RYM0_W02_LSB 0x218D /* row 0 column 2 of YUV matrix LSB */ | ||
226 | #define VS6624_RYM0_W10_MSB 0x2190 /* row 1 column 0 of YUV matrix MSB */ | ||
227 | #define VS6624_RYM0_W10_LSB 0x218F /* row 1 column 0 of YUV matrix LSB */ | ||
228 | #define VS6624_RYM0_W11_MSB 0x2193 /* row 1 column 1 of YUV matrix MSB */ | ||
229 | #define VS6624_RYM0_W11_LSB 0x2194 /* row 1 column 1 of YUV matrix LSB */ | ||
230 | #define VS6624_RYM0_W12_MSB 0x2197 /* row 1 column 2 of YUV matrix MSB */ | ||
231 | #define VS6624_RYM0_W12_LSB 0x2198 /* row 1 column 2 of YUV matrix LSB */ | ||
232 | #define VS6624_RYM0_W20_MSB 0x219B /* row 2 column 0 of YUV matrix MSB */ | ||
233 | #define VS6624_RYM0_W20_LSB 0x219C /* row 2 column 0 of YUV matrix LSB */ | ||
234 | #define VS6624_RYM0_W21_MSB 0x21A0 /* row 2 column 1 of YUV matrix MSB */ | ||
235 | #define VS6624_RYM0_W21_LSB 0x219F /* row 2 column 1 of YUV matrix LSB */ | ||
236 | #define VS6624_RYM0_W22_MSB 0x21A3 /* row 2 column 2 of YUV matrix MSB */ | ||
237 | #define VS6624_RYM0_W22_LSB 0x21A4 /* row 2 column 2 of YUV matrix LSB */ | ||
238 | #define VS6624_RYM0_YINY_MSB 0x21A7 /* Y in Y MSB */ | ||
239 | #define VS6624_RYM0_YINY_LSB 0x21A8 /* Y in Y LSB */ | ||
240 | #define VS6624_RYM0_YINCB_MSB 0x21AB /* Y in Cb MSB */ | ||
241 | #define VS6624_RYM0_YINCB_LSB 0x21AC /* Y in Cb LSB */ | ||
242 | #define VS6624_RYM0_YINCR_MSB 0x21B0 /* Y in Cr MSB */ | ||
243 | #define VS6624_RYM0_YINCR_LSB 0x21AF /* Y in Cr LSB */ | ||
244 | /* pipe 1 RGB to YUV matrix manual control */ | ||
245 | #define VS6624_RYM1_MAN_CTRL 0x2200 /* enable manual RGB to YUV matrix */ | ||
246 | #define VS6624_RYM1_W00_MSB 0x2203 /* row 0 column 0 of YUV matrix MSB */ | ||
247 | #define VS6624_RYM1_W00_LSB 0x2204 /* row 0 column 0 of YUV matrix LSB */ | ||
248 | #define VS6624_RYM1_W01_MSB 0x2207 /* row 0 column 1 of YUV matrix MSB */ | ||
249 | #define VS6624_RYM1_W01_LSB 0x2208 /* row 0 column 1 of YUV matrix LSB */ | ||
250 | #define VS6624_RYM1_W02_MSB 0x220C /* row 0 column 2 of YUV matrix MSB */ | ||
251 | #define VS6624_RYM1_W02_LSB 0x220D /* row 0 column 2 of YUV matrix LSB */ | ||
252 | #define VS6624_RYM1_W10_MSB 0x2210 /* row 1 column 0 of YUV matrix MSB */ | ||
253 | #define VS6624_RYM1_W10_LSB 0x220F /* row 1 column 0 of YUV matrix LSB */ | ||
254 | #define VS6624_RYM1_W11_MSB 0x2213 /* row 1 column 1 of YUV matrix MSB */ | ||
255 | #define VS6624_RYM1_W11_LSB 0x2214 /* row 1 column 1 of YUV matrix LSB */ | ||
256 | #define VS6624_RYM1_W12_MSB 0x2217 /* row 1 column 2 of YUV matrix MSB */ | ||
257 | #define VS6624_RYM1_W12_LSB 0x2218 /* row 1 column 2 of YUV matrix LSB */ | ||
258 | #define VS6624_RYM1_W20_MSB 0x221B /* row 2 column 0 of YUV matrix MSB */ | ||
259 | #define VS6624_RYM1_W20_LSB 0x221C /* row 2 column 0 of YUV matrix LSB */ | ||
260 | #define VS6624_RYM1_W21_MSB 0x2220 /* row 2 column 1 of YUV matrix MSB */ | ||
261 | #define VS6624_RYM1_W21_LSB 0x221F /* row 2 column 1 of YUV matrix LSB */ | ||
262 | #define VS6624_RYM1_W22_MSB 0x2223 /* row 2 column 2 of YUV matrix MSB */ | ||
263 | #define VS6624_RYM1_W22_LSB 0x2224 /* row 2 column 2 of YUV matrix LSB */ | ||
264 | #define VS6624_RYM1_YINY_MSB 0x2227 /* Y in Y MSB */ | ||
265 | #define VS6624_RYM1_YINY_LSB 0x2228 /* Y in Y LSB */ | ||
266 | #define VS6624_RYM1_YINCB_MSB 0x222B /* Y in Cb MSB */ | ||
267 | #define VS6624_RYM1_YINCB_LSB 0x222C /* Y in Cb LSB */ | ||
268 | #define VS6624_RYM1_YINCR_MSB 0x2220 /* Y in Cr MSB */ | ||
269 | #define VS6624_RYM1_YINCR_LSB 0x222F /* Y in Cr LSB */ | ||
270 | /* pipe 0 gamma manual control */ | ||
271 | #define VS6624_GAMMA_MAN_CTRL0 0x2280 /* enable manual gamma setup */ | ||
272 | #define VS6624_GAMMA_PEAK_R0 0x2282 /* peaked red channel gamma value */ | ||
273 | #define VS6624_GAMMA_PEAK_G0 0x2284 /* peaked green channel gamma value */ | ||
274 | #define VS6624_GAMMA_PEAK_B0 0x2286 /* peaked blue channel gamma value */ | ||
275 | #define VS6624_GAMMA_UNPEAK_R0 0x2288 /* unpeaked red channel gamma value */ | ||
276 | #define VS6624_GAMMA_UNPEAK_G0 0x228A /* unpeaked green channel gamma value */ | ||
277 | #define VS6624_GAMMA_UNPEAK_B0 0x228C /* unpeaked blue channel gamma value */ | ||
278 | /* pipe 1 gamma manual control */ | ||
279 | #define VS6624_GAMMA_MAN_CTRL1 0x2300 /* enable manual gamma setup */ | ||
280 | #define VS6624_GAMMA_PEAK_R1 0x2302 /* peaked red channel gamma value */ | ||
281 | #define VS6624_GAMMA_PEAK_G1 0x2304 /* peaked green channel gamma value */ | ||
282 | #define VS6624_GAMMA_PEAK_B1 0x2306 /* peaked blue channel gamma value */ | ||
283 | #define VS6624_GAMMA_UNPEAK_R1 0x2308 /* unpeaked red channel gamma value */ | ||
284 | #define VS6624_GAMMA_UNPEAK_G1 0x230A /* unpeaked green channel gamma value */ | ||
285 | #define VS6624_GAMMA_UNPEAK_B1 0x230C /* unpeaked blue channel gamma value */ | ||
286 | /* fade to black */ | ||
287 | #define VS6624_F2B_DISABLE 0x2480 /* disable fade to black */ | ||
288 | #define VS6624_F2B_BLACK_VAL_MSB 0x2483 /* black value MSB */ | ||
289 | #define VS6624_F2B_BLACK_VAL_LSB 0x2484 /* black value LSB */ | ||
290 | #define VS6624_F2B_LOW_THR_MSB 0x2487 /* low threshold for exposure MSB */ | ||
291 | #define VS6624_F2B_LOW_THR_LSB 0x2488 /* low threshold for exposure LSB */ | ||
292 | #define VS6624_F2B_HIGH_THR_MSB 0x248B /* high threshold for exposure MSB */ | ||
293 | #define VS6624_F2B_HIGH_THR_LSB 0x248C /* high threshold for exposure LSB */ | ||
294 | #define VS6624_F2B_MIN_OUT_MSB 0x248F /* minimum damper output MSB */ | ||
295 | #define VS6624_F2B_MIN_OUT_LSB 0x2490 /* minimum damper output LSB */ | ||
296 | /* output formatter control */ | ||
297 | #define VS6624_CODE_CK_EN 0x2580 /* code check enable */ | ||
298 | #define VS6624_BLANK_FMT 0x2582 /* blank format */ | ||
299 | #define VS6624_SYNC_CODE_SETUP 0x2584 /* sync code setup */ | ||
300 | #define VS6624_HSYNC_SETUP 0x2586 /* H sync setup */ | ||
301 | #define VS6624_VSYNC_SETUP 0x2588 /* V sync setup */ | ||
302 | #define VS6624_PCLK_SETUP 0x258A /* PCLK setup */ | ||
303 | #define VS6624_PCLK_EN 0x258C /* PCLK enable */ | ||
304 | #define VS6624_OPF_SP_SETUP 0x258E /* output formatter sp setup */ | ||
305 | #define VS6624_BLANK_DATA_MSB 0x2590 /* blank data MSB */ | ||
306 | #define VS6624_BLANK_DATA_LSB 0x2592 /* blank data LSB */ | ||
307 | #define VS6624_RGB_SETUP 0x2594 /* RGB setup */ | ||
308 | #define VS6624_YUV_SETUP 0x2596 /* YUV setup */ | ||
309 | #define VS6624_VSYNC_RIS_COARSE_H 0x2598 /* V sync rising coarse high */ | ||
310 | #define VS6624_VSYNC_RIS_COARSE_L 0x259A /* V sync rising coarse low */ | ||
311 | #define VS6624_VSYNC_RIS_FINE_H 0x259C /* V sync rising fine high */ | ||
312 | #define VS6624_VSYNC_RIS_FINE_L 0x259E /* V sync rising fine low */ | ||
313 | #define VS6624_VSYNC_FALL_COARSE_H 0x25A0 /* V sync falling coarse high */ | ||
314 | #define VS6624_VSYNC_FALL_COARSE_L 0x25A2 /* V sync falling coarse low */ | ||
315 | #define VS6624_VSYNC_FALL_FINE_H 0x25A4 /* V sync falling fine high */ | ||
316 | #define VS6624_VSYNC_FALL_FINE_L 0x25A6 /* V sync falling fine low */ | ||
317 | #define VS6624_HSYNC_RIS_H 0x25A8 /* H sync rising high */ | ||
318 | #define VS6624_HSYNC_RIS_L 0x25AA /* H sync rising low */ | ||
319 | #define VS6624_HSYNC_FALL_H 0x25AC /* H sync falling high */ | ||
320 | #define VS6624_HSYNC_FALL_L 0x25AE /* H sync falling low */ | ||
321 | #define VS6624_OUT_IF 0x25B0 /* output interface */ | ||
322 | #define VS6624_CCP_EXT_DATA 0x25B2 /* CCP extra data */ | ||
323 | /* NoRA controls */ | ||
324 | #define VS6624_NORA_DISABLE 0x2600 /* NoRA control mode */ | ||
325 | #define VS6624_NORA_USAGE 0x2602 /* usage */ | ||
326 | #define VS6624_NORA_SPLIT_KN 0x2604 /* split kn */ | ||
327 | #define VS6624_NORA_SPLIT_NI 0x2606 /* split ni */ | ||
328 | #define VS6624_NORA_TIGHT_G 0x2608 /* tight green */ | ||
329 | #define VS6624_NORA_DISABLE_NP 0x260A /* disable noro promoting */ | ||
330 | #define VS6624_NORA_LOW_THR_MSB 0x260D /* low threshold for exposure MSB */ | ||
331 | #define VS6624_NORA_LOW_THR_LSB 0x260E /* low threshold for exposure LSB */ | ||
332 | #define VS6624_NORA_HIGH_THR_MSB 0x2611 /* high threshold for exposure MSB */ | ||
333 | #define VS6624_NORA_HIGH_THR_LSB 0x2612 /* high threshold for exposure LSB */ | ||
334 | #define VS6624_NORA_MIN_OUT_MSB 0x2615 /* minimum damper output MSB */ | ||
335 | #define VS6624_NORA_MIN_OUT_LSB 0x2616 /* minimum damper output LSB */ | ||
336 | |||
337 | #endif | ||
diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c index 453dbbd1e6e8..7fd7ac567e1a 100644 --- a/drivers/media/video/w9966.c +++ b/drivers/media/video/w9966.c | |||
@@ -129,9 +129,9 @@ MODULE_LICENSE("GPL"); | |||
129 | MODULE_VERSION("0.33.1"); | 129 | MODULE_VERSION("0.33.1"); |
130 | 130 | ||
131 | #ifdef MODULE | 131 | #ifdef MODULE |
132 | static const char *pardev[] = {[0 ... W9966_MAXCAMS] = ""}; | 132 | static char *pardev[] = {[0 ... W9966_MAXCAMS] = ""}; |
133 | #else | 133 | #else |
134 | static const char *pardev[] = {[0 ... W9966_MAXCAMS] = "aggressive"}; | 134 | static char *pardev[] = {[0 ... W9966_MAXCAMS] = "aggressive"}; |
135 | #endif | 135 | #endif |
136 | module_param_array(pardev, charp, NULL, 0); | 136 | module_param_array(pardev, charp, NULL, 0); |
137 | MODULE_PARM_DESC(pardev, "pardev: where to search for\n" | 137 | MODULE_PARM_DESC(pardev, "pardev: where to search for\n" |
diff --git a/drivers/media/video/wm8739.c b/drivers/media/video/wm8739.c index a22f765e968a..3bb99e93febe 100644 --- a/drivers/media/video/wm8739.c +++ b/drivers/media/video/wm8739.c | |||
@@ -291,15 +291,4 @@ static struct i2c_driver wm8739_driver = { | |||
291 | .id_table = wm8739_id, | 291 | .id_table = wm8739_id, |
292 | }; | 292 | }; |
293 | 293 | ||
294 | static __init int init_wm8739(void) | 294 | module_i2c_driver(wm8739_driver); |
295 | { | ||
296 | return i2c_add_driver(&wm8739_driver); | ||
297 | } | ||
298 | |||
299 | static __exit void exit_wm8739(void) | ||
300 | { | ||
301 | i2c_del_driver(&wm8739_driver); | ||
302 | } | ||
303 | |||
304 | module_init(init_wm8739); | ||
305 | module_exit(exit_wm8739); | ||
diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c index 9cedb1e69b58..bee77ea9f49e 100644 --- a/drivers/media/video/wm8775.c +++ b/drivers/media/video/wm8775.c | |||
@@ -339,15 +339,4 @@ static struct i2c_driver wm8775_driver = { | |||
339 | .id_table = wm8775_id, | 339 | .id_table = wm8775_id, |
340 | }; | 340 | }; |
341 | 341 | ||
342 | static __init int init_wm8775(void) | 342 | module_i2c_driver(wm8775_driver); |
343 | { | ||
344 | return i2c_add_driver(&wm8775_driver); | ||
345 | } | ||
346 | |||
347 | static __exit void exit_wm8775(void) | ||
348 | { | ||
349 | i2c_del_driver(&wm8775_driver); | ||
350 | } | ||
351 | |||
352 | module_init(init_wm8775); | ||
353 | module_exit(exit_wm8775); | ||