diff options
author | Tony Lindgren <tony@atomide.com> | 2010-03-01 17:19:05 -0500 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2010-03-01 17:19:05 -0500 |
commit | d702d12167a2c05a346f49aac7a311d597762495 (patch) | |
tree | baae42c299cce34d6df24b5d01f8b1d0b481bd9a /drivers/media/video | |
parent | 9418c65f9bd861d0f7e39aab9cfb3aa6f2275d11 (diff) | |
parent | ac0f6f927db539e03e1f3f61bcd4ed57d5cde7a9 (diff) |
Merge with mainline to remove plat-omap/Kconfig conflict
Conflicts:
arch/arm/plat-omap/Kconfig
Diffstat (limited to 'drivers/media/video')
174 files changed, 17982 insertions, 3386 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 2f83be766d9f..f8fc8654693d 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -388,6 +388,15 @@ config VIDEO_TVP5150 | |||
388 | To compile this driver as a module, choose M here: the | 388 | To compile this driver as a module, choose M here: the |
389 | module will be called tvp5150. | 389 | module will be called tvp5150. |
390 | 390 | ||
391 | config VIDEO_TVP7002 | ||
392 | tristate "Texas Instruments TVP7002 video decoder" | ||
393 | depends on VIDEO_V4L2 && I2C | ||
394 | ---help--- | ||
395 | Support for the Texas Instruments TVP7002 video decoder. | ||
396 | |||
397 | To compile this driver as a module, choose M here: the | ||
398 | module will be called tvp7002. | ||
399 | |||
391 | config VIDEO_VPX3220 | 400 | config VIDEO_VPX3220 |
392 | tristate "vpx3220a, vpx3216b & vpx3214c video decoders" | 401 | tristate "vpx3220a, vpx3216b & vpx3214c video decoders" |
393 | depends on VIDEO_V4L2 && I2C | 402 | depends on VIDEO_V4L2 && I2C |
@@ -548,7 +557,6 @@ config VIDEO_VPSS_SYSTEM | |||
548 | depends on ARCH_DAVINCI | 557 | depends on ARCH_DAVINCI |
549 | help | 558 | help |
550 | Support for vpss system module for video driver | 559 | Support for vpss system module for video driver |
551 | default y | ||
552 | 560 | ||
553 | config VIDEO_VPFE_CAPTURE | 561 | config VIDEO_VPFE_CAPTURE |
554 | tristate "VPFE Video Capture Driver" | 562 | tristate "VPFE Video Capture Driver" |
@@ -592,6 +600,19 @@ config VIDEO_DM355_CCDC | |||
592 | To compile this driver as a module, choose M here: the | 600 | To compile this driver as a module, choose M here: the |
593 | module will be called vpfe. | 601 | module will be called vpfe. |
594 | 602 | ||
603 | config VIDEO_ISIF | ||
604 | tristate "ISIF HW module" | ||
605 | depends on ARCH_DAVINCI_DM365 && VIDEO_VPFE_CAPTURE | ||
606 | select VIDEO_VPSS_SYSTEM | ||
607 | default y | ||
608 | help | ||
609 | Enables ISIF hw module. This is the hardware module for | ||
610 | configuring ISIF in VPFE to capture Raw Bayer RGB data from | ||
611 | a image sensor or YUV data from a YUV source. | ||
612 | |||
613 | To compile this driver as a module, choose M here: the | ||
614 | module will be called vpfe. | ||
615 | |||
595 | source "drivers/media/video/bt8xx/Kconfig" | 616 | source "drivers/media/video/bt8xx/Kconfig" |
596 | 617 | ||
597 | config VIDEO_PMS | 618 | config VIDEO_PMS |
@@ -638,9 +659,14 @@ config VIDEO_W9966 | |||
638 | information. | 659 | information. |
639 | 660 | ||
640 | config VIDEO_CPIA | 661 | config VIDEO_CPIA |
641 | tristate "CPiA Video For Linux" | 662 | tristate "CPiA Video For Linux (DEPRECATED)" |
642 | depends on VIDEO_V4L1 | 663 | depends on VIDEO_V4L1 |
664 | default n | ||
643 | ---help--- | 665 | ---help--- |
666 | This driver is DEPRECATED please use the gspca cpia1 module | ||
667 | instead. Note that you need atleast version 0.6.4 of libv4l for | ||
668 | the cpia1 gspca module. | ||
669 | |||
644 | This is the video4linux driver for cameras based on Vision's CPiA | 670 | This is the video4linux driver for cameras based on Vision's CPiA |
645 | (Colour Processor Interface ASIC), such as the Creative Labs Video | 671 | (Colour Processor Interface ASIC), such as the Creative Labs Video |
646 | Blaster Webcam II. If you have one of these cameras, say Y here | 672 | Blaster Webcam II. If you have one of these cameras, say Y here |
@@ -944,6 +970,8 @@ source "drivers/media/video/hdpvr/Kconfig" | |||
944 | 970 | ||
945 | source "drivers/media/video/em28xx/Kconfig" | 971 | source "drivers/media/video/em28xx/Kconfig" |
946 | 972 | ||
973 | source "drivers/media/video/tlg2300/Kconfig" | ||
974 | |||
947 | source "drivers/media/video/cx231xx/Kconfig" | 975 | source "drivers/media/video/cx231xx/Kconfig" |
948 | 976 | ||
949 | source "drivers/media/video/usbvision/Kconfig" | 977 | source "drivers/media/video/usbvision/Kconfig" |
@@ -955,6 +983,7 @@ source "drivers/media/video/et61x251/Kconfig" | |||
955 | config VIDEO_OVCAMCHIP | 983 | config VIDEO_OVCAMCHIP |
956 | tristate "OmniVision Camera Chip support (DEPRECATED)" | 984 | tristate "OmniVision Camera Chip support (DEPRECATED)" |
957 | depends on I2C && VIDEO_V4L1 | 985 | depends on I2C && VIDEO_V4L1 |
986 | default n | ||
958 | ---help--- | 987 | ---help--- |
959 | This driver is DEPRECATED please use the gspca ov519 module | 988 | This driver is DEPRECATED please use the gspca ov519 module |
960 | instead. Note that for the ov511 / ov518 support of the gspca module | 989 | instead. Note that for the ov511 / ov518 support of the gspca module |
@@ -971,6 +1000,7 @@ config VIDEO_OVCAMCHIP | |||
971 | config USB_W9968CF | 1000 | config USB_W9968CF |
972 | tristate "USB W996[87]CF JPEG Dual Mode Camera support (DEPRECATED)" | 1001 | tristate "USB W996[87]CF JPEG Dual Mode Camera support (DEPRECATED)" |
973 | depends on VIDEO_V4L1 && I2C && VIDEO_OVCAMCHIP | 1002 | depends on VIDEO_V4L1 && I2C && VIDEO_OVCAMCHIP |
1003 | default n | ||
974 | ---help--- | 1004 | ---help--- |
975 | This driver is DEPRECATED please use the gspca ov519 module | 1005 | This driver is DEPRECATED please use the gspca ov519 module |
976 | instead. Note that for the w9968cf support of the gspca module | 1006 | instead. Note that for the w9968cf support of the gspca module |
@@ -992,6 +1022,7 @@ config USB_W9968CF | |||
992 | config USB_OV511 | 1022 | config USB_OV511 |
993 | tristate "USB OV511 Camera support (DEPRECATED)" | 1023 | tristate "USB OV511 Camera support (DEPRECATED)" |
994 | depends on VIDEO_V4L1 | 1024 | depends on VIDEO_V4L1 |
1025 | default n | ||
995 | ---help--- | 1026 | ---help--- |
996 | This driver is DEPRECATED please use the gspca ov519 module | 1027 | This driver is DEPRECATED please use the gspca ov519 module |
997 | instead. Note that for the ov511 / ov518 support of the gspca module | 1028 | instead. Note that for the ov511 / ov518 support of the gspca module |
@@ -1020,6 +1051,7 @@ source "drivers/media/video/sn9c102/Kconfig" | |||
1020 | config USB_STV680 | 1051 | config USB_STV680 |
1021 | tristate "USB STV680 (Pencam) Camera support (DEPRECATED)" | 1052 | tristate "USB STV680 (Pencam) Camera support (DEPRECATED)" |
1022 | depends on VIDEO_V4L1 | 1053 | depends on VIDEO_V4L1 |
1054 | default n | ||
1023 | ---help--- | 1055 | ---help--- |
1024 | This driver is DEPRECATED please use the gspca stv0680 module | 1056 | This driver is DEPRECATED please use the gspca stv0680 module |
1025 | instead. Note that for the gspca stv0680 module you need | 1057 | instead. Note that for the gspca stv0680 module you need |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 2af68ee84122..b88b6174a331 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
@@ -56,6 +56,7 @@ obj-$(CONFIG_VIDEO_THS7303) += ths7303.o | |||
56 | obj-$(CONFIG_VIDEO_VINO) += indycam.o | 56 | obj-$(CONFIG_VIDEO_VINO) += indycam.o |
57 | obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o | 57 | obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o |
58 | obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o | 58 | obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o |
59 | obj-$(CONFIG_VIDEO_TVP7002) += tvp7002.o | ||
59 | obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o | 60 | obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o |
60 | obj-$(CONFIG_VIDEO_CS5345) += cs5345.o | 61 | obj-$(CONFIG_VIDEO_CS5345) += cs5345.o |
61 | obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o | 62 | obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o |
@@ -99,6 +100,7 @@ obj-$(CONFIG_VIDEO_MEYE) += meye.o | |||
99 | obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ | 100 | obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ |
100 | obj-$(CONFIG_VIDEO_CX88) += cx88/ | 101 | obj-$(CONFIG_VIDEO_CX88) += cx88/ |
101 | obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ | 102 | obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ |
103 | obj-$(CONFIG_VIDEO_TLG2300) += tlg2300/ | ||
102 | obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/ | 104 | obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/ |
103 | obj-$(CONFIG_VIDEO_USBVISION) += usbvision/ | 105 | obj-$(CONFIG_VIDEO_USBVISION) += usbvision/ |
104 | obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/ | 106 | obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/ |
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c index 5bb0f9e71583..547e1a93c421 100644 --- a/drivers/media/video/bt819.c +++ b/drivers/media/video/bt819.c | |||
@@ -254,7 +254,7 @@ static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std) | |||
254 | v4l2_err(sd, "no notify found!\n"); | 254 | v4l2_err(sd, "no notify found!\n"); |
255 | 255 | ||
256 | if (std & V4L2_STD_NTSC) { | 256 | if (std & V4L2_STD_NTSC) { |
257 | v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, 0); | 257 | v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, NULL); |
258 | bt819_setbit(decoder, 0x01, 0, 1); | 258 | bt819_setbit(decoder, 0x01, 0, 1); |
259 | bt819_setbit(decoder, 0x01, 1, 0); | 259 | bt819_setbit(decoder, 0x01, 1, 0); |
260 | bt819_setbit(decoder, 0x01, 5, 0); | 260 | bt819_setbit(decoder, 0x01, 5, 0); |
@@ -263,7 +263,7 @@ static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std) | |||
263 | /* bt819_setbit(decoder, 0x1a, 5, 1); */ | 263 | /* bt819_setbit(decoder, 0x1a, 5, 1); */ |
264 | timing = &timing_data[1]; | 264 | timing = &timing_data[1]; |
265 | } else if (std & V4L2_STD_PAL) { | 265 | } else if (std & V4L2_STD_PAL) { |
266 | v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, 0); | 266 | v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, NULL); |
267 | bt819_setbit(decoder, 0x01, 0, 1); | 267 | bt819_setbit(decoder, 0x01, 0, 1); |
268 | bt819_setbit(decoder, 0x01, 1, 1); | 268 | bt819_setbit(decoder, 0x01, 1, 1); |
269 | bt819_setbit(decoder, 0x01, 5, 1); | 269 | bt819_setbit(decoder, 0x01, 5, 1); |
@@ -288,7 +288,7 @@ static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std) | |||
288 | bt819_write(decoder, 0x08, (timing->hscale >> 8) & 0xff); | 288 | bt819_write(decoder, 0x08, (timing->hscale >> 8) & 0xff); |
289 | bt819_write(decoder, 0x09, timing->hscale & 0xff); | 289 | bt819_write(decoder, 0x09, timing->hscale & 0xff); |
290 | decoder->norm = std; | 290 | decoder->norm = std; |
291 | v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, 0); | 291 | v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, NULL); |
292 | return 0; | 292 | return 0; |
293 | } | 293 | } |
294 | 294 | ||
@@ -306,7 +306,7 @@ static int bt819_s_routing(struct v4l2_subdev *sd, | |||
306 | v4l2_err(sd, "no notify found!\n"); | 306 | v4l2_err(sd, "no notify found!\n"); |
307 | 307 | ||
308 | if (decoder->input != input) { | 308 | if (decoder->input != input) { |
309 | v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, 0); | 309 | v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, NULL); |
310 | decoder->input = input; | 310 | decoder->input = input; |
311 | /* select mode */ | 311 | /* select mode */ |
312 | if (decoder->input == 0) { | 312 | if (decoder->input == 0) { |
@@ -316,7 +316,7 @@ static int bt819_s_routing(struct v4l2_subdev *sd, | |||
316 | bt819_setbit(decoder, 0x0b, 6, 1); | 316 | bt819_setbit(decoder, 0x0b, 6, 1); |
317 | bt819_setbit(decoder, 0x1a, 1, 0); | 317 | bt819_setbit(decoder, 0x1a, 1, 0); |
318 | } | 318 | } |
319 | v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, 0); | 319 | v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, NULL); |
320 | } | 320 | } |
321 | return 0; | 321 | return 0; |
322 | } | 322 | } |
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 3182a406bdd1..cb46e8fa8aaa 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c | |||
@@ -81,6 +81,7 @@ static int video_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 }; | |||
81 | static int radio_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 }; | 81 | static int radio_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 }; |
82 | static int vbi_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 }; | 82 | static int vbi_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 }; |
83 | static int debug_latency; | 83 | static int debug_latency; |
84 | static int disable_ir; | ||
84 | 85 | ||
85 | static unsigned int fdsr; | 86 | static unsigned int fdsr; |
86 | 87 | ||
@@ -107,6 +108,7 @@ module_param(bttv_gpio, int, 0644); | |||
107 | module_param(bttv_debug, int, 0644); | 108 | module_param(bttv_debug, int, 0644); |
108 | module_param(irq_debug, int, 0644); | 109 | module_param(irq_debug, int, 0644); |
109 | module_param(debug_latency, int, 0644); | 110 | module_param(debug_latency, int, 0644); |
111 | module_param(disable_ir, int, 0444); | ||
110 | 112 | ||
111 | module_param(fdsr, int, 0444); | 113 | module_param(fdsr, int, 0444); |
112 | module_param(gbuffers, int, 0444); | 114 | module_param(gbuffers, int, 0444); |
@@ -139,6 +141,7 @@ MODULE_PARM_DESC(bttv_verbose,"verbose startup messages, default is 1 (yes)"); | |||
139 | MODULE_PARM_DESC(bttv_gpio,"log gpio changes, default is 0 (no)"); | 141 | MODULE_PARM_DESC(bttv_gpio,"log gpio changes, default is 0 (no)"); |
140 | MODULE_PARM_DESC(bttv_debug,"debug messages, default is 0 (no)"); | 142 | MODULE_PARM_DESC(bttv_debug,"debug messages, default is 0 (no)"); |
141 | MODULE_PARM_DESC(irq_debug,"irq handler debug messages, default is 0 (no)"); | 143 | MODULE_PARM_DESC(irq_debug,"irq handler debug messages, default is 0 (no)"); |
144 | MODULE_PARM_DESC(disable_ir, "disable infrared remote support"); | ||
142 | MODULE_PARM_DESC(gbuffers,"number of capture buffers. range 2-32, default 8"); | 145 | MODULE_PARM_DESC(gbuffers,"number of capture buffers. range 2-32, default 8"); |
143 | MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000"); | 146 | MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000"); |
144 | MODULE_PARM_DESC(reset_crop,"reset cropping parameters at open(), default " | 147 | MODULE_PARM_DESC(reset_crop,"reset cropping parameters at open(), default " |
@@ -4461,7 +4464,10 @@ static int __devinit bttv_probe(struct pci_dev *dev, | |||
4461 | request_modules(btv); | 4464 | request_modules(btv); |
4462 | } | 4465 | } |
4463 | 4466 | ||
4464 | bttv_input_init(btv); | 4467 | if (!disable_ir) { |
4468 | init_bttv_i2c_ir(btv); | ||
4469 | bttv_input_init(btv); | ||
4470 | } | ||
4465 | 4471 | ||
4466 | /* everything is fine */ | 4472 | /* everything is fine */ |
4467 | bttv_num++; | 4473 | bttv_num++; |
diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c index 63aa31a041e8..407fa61e4cda 100644 --- a/drivers/media/video/bt8xx/bttv-i2c.c +++ b/drivers/media/video/bt8xx/bttv-i2c.c | |||
@@ -388,7 +388,12 @@ int __devinit init_bttv_i2c(struct bttv *btv) | |||
388 | if (0 == btv->i2c_rc && i2c_scan) | 388 | if (0 == btv->i2c_rc && i2c_scan) |
389 | do_i2c_scan(btv->c.v4l2_dev.name, &btv->i2c_client); | 389 | do_i2c_scan(btv->c.v4l2_dev.name, &btv->i2c_client); |
390 | 390 | ||
391 | /* Instantiate the IR receiver device, if present */ | 391 | return btv->i2c_rc; |
392 | } | ||
393 | |||
394 | /* Instantiate the I2C IR receiver device, if present */ | ||
395 | void __devinit init_bttv_i2c_ir(struct bttv *btv) | ||
396 | { | ||
392 | if (0 == btv->i2c_rc) { | 397 | if (0 == btv->i2c_rc) { |
393 | struct i2c_board_info info; | 398 | struct i2c_board_info info; |
394 | /* The external IR receiver is at i2c address 0x34 (0x35 for | 399 | /* The external IR receiver is at i2c address 0x34 (0x35 for |
@@ -408,7 +413,6 @@ int __devinit init_bttv_i2c(struct bttv *btv) | |||
408 | strlcpy(info.type, "ir_video", I2C_NAME_SIZE); | 413 | strlcpy(info.type, "ir_video", I2C_NAME_SIZE); |
409 | i2c_new_probed_device(&btv->c.i2c_adap, &info, addr_list); | 414 | i2c_new_probed_device(&btv->c.i2c_adap, &info, addr_list); |
410 | } | 415 | } |
411 | return btv->i2c_rc; | ||
412 | } | 416 | } |
413 | 417 | ||
414 | int __devexit fini_bttv_i2c(struct bttv *btv) | 418 | int __devexit fini_bttv_i2c(struct bttv *btv) |
diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index 277a092e1214..b320dbd635aa 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c | |||
@@ -247,7 +247,7 @@ int bttv_input_init(struct bttv *btv) | |||
247 | struct card_ir *ir; | 247 | struct card_ir *ir; |
248 | struct ir_scancode_table *ir_codes = NULL; | 248 | struct ir_scancode_table *ir_codes = NULL; |
249 | struct input_dev *input_dev; | 249 | struct input_dev *input_dev; |
250 | int ir_type = IR_TYPE_OTHER; | 250 | u64 ir_type = IR_TYPE_OTHER; |
251 | int err = -ENOMEM; | 251 | int err = -ENOMEM; |
252 | 252 | ||
253 | if (!btv->has_remote) | 253 | if (!btv->has_remote) |
@@ -389,7 +389,7 @@ int bttv_input_init(struct bttv *btv) | |||
389 | bttv_ir_start(btv, ir); | 389 | bttv_ir_start(btv, ir); |
390 | 390 | ||
391 | /* all done */ | 391 | /* all done */ |
392 | err = ir_input_register(btv->remote->dev, ir_codes); | 392 | err = ir_input_register(btv->remote->dev, ir_codes, NULL); |
393 | if (err) | 393 | if (err) |
394 | goto err_out_stop; | 394 | goto err_out_stop; |
395 | 395 | ||
diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h index a1d0e9c9f286..6cccc2a17eee 100644 --- a/drivers/media/video/bt8xx/bttvp.h +++ b/drivers/media/video/bt8xx/bttvp.h | |||
@@ -279,6 +279,7 @@ extern unsigned int bttv_debug; | |||
279 | extern unsigned int bttv_gpio; | 279 | extern unsigned int bttv_gpio; |
280 | extern void bttv_gpio_tracking(struct bttv *btv, char *comment); | 280 | extern void bttv_gpio_tracking(struct bttv *btv, char *comment); |
281 | extern int init_bttv_i2c(struct bttv *btv); | 281 | extern int init_bttv_i2c(struct bttv *btv); |
282 | extern void init_bttv_i2c_ir(struct bttv *btv); | ||
282 | extern int fini_bttv_i2c(struct bttv *btv); | 283 | extern int fini_bttv_i2c(struct bttv *btv); |
283 | 284 | ||
284 | #define bttv_printk if (bttv_verbose) printk | 285 | #define bttv_printk if (bttv_verbose) printk |
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 7bb9c1ec7819..cbbf7e80d2cf 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c | |||
@@ -1907,7 +1907,6 @@ static int cafe_pci_probe(struct pci_dev *pdev, | |||
1907 | goto out_free; | 1907 | goto out_free; |
1908 | 1908 | ||
1909 | mutex_init(&cam->s_mutex); | 1909 | mutex_init(&cam->s_mutex); |
1910 | mutex_lock(&cam->s_mutex); | ||
1911 | spin_lock_init(&cam->dev_lock); | 1910 | spin_lock_init(&cam->dev_lock); |
1912 | cam->state = S_NOTREADY; | 1911 | cam->state = S_NOTREADY; |
1913 | cafe_set_config_needed(cam, 1); | 1912 | cafe_set_config_needed(cam, 1); |
@@ -1947,7 +1946,6 @@ static int cafe_pci_probe(struct pci_dev *pdev, | |||
1947 | * because the sensor could attach in this call chain, leading to | 1946 | * because the sensor could attach in this call chain, leading to |
1948 | * unsightly deadlocks. | 1947 | * unsightly deadlocks. |
1949 | */ | 1948 | */ |
1950 | mutex_unlock(&cam->s_mutex); /* attach can deadlock */ | ||
1951 | ret = cafe_smbus_setup(cam); | 1949 | ret = cafe_smbus_setup(cam); |
1952 | if (ret) | 1950 | if (ret) |
1953 | goto out_freeirq; | 1951 | goto out_freeirq; |
@@ -1973,7 +1971,7 @@ static int cafe_pci_probe(struct pci_dev *pdev, | |||
1973 | cam->vdev.v4l2_dev = &cam->v4l2_dev; | 1971 | cam->vdev.v4l2_dev = &cam->v4l2_dev; |
1974 | ret = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1); | 1972 | ret = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1); |
1975 | if (ret) | 1973 | if (ret) |
1976 | goto out_smbus; | 1974 | goto out_unlock; |
1977 | video_set_drvdata(&cam->vdev, cam); | 1975 | video_set_drvdata(&cam->vdev, cam); |
1978 | 1976 | ||
1979 | /* | 1977 | /* |
@@ -1988,6 +1986,8 @@ static int cafe_pci_probe(struct pci_dev *pdev, | |||
1988 | mutex_unlock(&cam->s_mutex); | 1986 | mutex_unlock(&cam->s_mutex); |
1989 | return 0; | 1987 | return 0; |
1990 | 1988 | ||
1989 | out_unlock: | ||
1990 | mutex_unlock(&cam->s_mutex); | ||
1991 | out_smbus: | 1991 | out_smbus: |
1992 | cafe_smbus_shutdown(cam); | 1992 | cafe_smbus_shutdown(cam); |
1993 | out_freeirq: | 1993 | out_freeirq: |
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index 551ddf216a4b..933ae4c8cb9a 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c | |||
@@ -3737,9 +3737,6 @@ static int cpia_mmap(struct file *file, struct vm_area_struct *vma) | |||
3737 | if (size > FRAME_NUM*CPIA_MAX_FRAME_SIZE) | 3737 | if (size > FRAME_NUM*CPIA_MAX_FRAME_SIZE) |
3738 | return -EINVAL; | 3738 | return -EINVAL; |
3739 | 3739 | ||
3740 | if (!cam || !cam->ops) | ||
3741 | return -ENODEV; | ||
3742 | |||
3743 | /* make this _really_ smp-safe */ | 3740 | /* make this _really_ smp-safe */ |
3744 | if (mutex_lock_interruptible(&cam->busy_lock)) | 3741 | if (mutex_lock_interruptible(&cam->busy_lock)) |
3745 | return -EINTR; | 3742 | return -EINTR; |
diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/video/cx18/Kconfig index e8a50a611ebc..baf7e91ee0f5 100644 --- a/drivers/media/video/cx18/Kconfig +++ b/drivers/media/video/cx18/Kconfig | |||
@@ -19,3 +19,14 @@ config VIDEO_CX18 | |||
19 | 19 | ||
20 | To compile this driver as a module, choose M here: the | 20 | To compile this driver as a module, choose M here: the |
21 | module will be called cx18. | 21 | module will be called cx18. |
22 | |||
23 | config VIDEO_CX18_ALSA | ||
24 | tristate "Conexant 23418 DMA audio support" | ||
25 | depends on VIDEO_CX18 && SND && EXPERIMENTAL | ||
26 | select SND_PCM | ||
27 | ---help--- | ||
28 | This is a video4linux driver for direct (DMA) audio on | ||
29 | Conexant 23418 based TV cards using ALSA. | ||
30 | |||
31 | To compile this driver as a module, choose M here: the | ||
32 | module will be called cx18-alsa. | ||
diff --git a/drivers/media/video/cx18/Makefile b/drivers/media/video/cx18/Makefile index f7bf0edf93f9..2fadd9ded340 100644 --- a/drivers/media/video/cx18/Makefile +++ b/drivers/media/video/cx18/Makefile | |||
@@ -3,8 +3,10 @@ cx18-objs := cx18-driver.o cx18-cards.o cx18-i2c.o cx18-firmware.o cx18-gpio. | |||
3 | cx18-mailbox.o cx18-vbi.o cx18-audio.o cx18-video.o cx18-irq.o \ | 3 | cx18-mailbox.o cx18-vbi.o cx18-audio.o cx18-video.o cx18-irq.o \ |
4 | cx18-av-core.o cx18-av-audio.o cx18-av-firmware.o cx18-av-vbi.o cx18-scb.o \ | 4 | cx18-av-core.o cx18-av-audio.o cx18-av-firmware.o cx18-av-vbi.o cx18-scb.o \ |
5 | cx18-dvb.o cx18-io.o | 5 | cx18-dvb.o cx18-io.o |
6 | cx18-alsa-objs := cx18-alsa-main.o cx18-alsa-pcm.o | ||
6 | 7 | ||
7 | obj-$(CONFIG_VIDEO_CX18) += cx18.o | 8 | obj-$(CONFIG_VIDEO_CX18) += cx18.o |
9 | obj-$(CONFIG_VIDEO_CX18_ALSA) += cx18-alsa.o | ||
8 | 10 | ||
9 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core | 11 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core |
10 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends | 12 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends |
diff --git a/drivers/media/video/cx18/cx18-alsa-main.c b/drivers/media/video/cx18/cx18-alsa-main.c new file mode 100644 index 000000000000..eb41d7ec65b9 --- /dev/null +++ b/drivers/media/video/cx18/cx18-alsa-main.c | |||
@@ -0,0 +1,293 @@ | |||
1 | /* | ||
2 | * ALSA interface to cx18 PCM capture streams | ||
3 | * | ||
4 | * Copyright (C) 2009 Andy Walls <awalls@radix.net> | ||
5 | * Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com> | ||
6 | * | ||
7 | * Portions of this work were sponsored by ONELAN Limited. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
22 | * 02111-1307 USA | ||
23 | */ | ||
24 | |||
25 | #include <linux/init.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/device.h> | ||
29 | #include <linux/spinlock.h> | ||
30 | |||
31 | #include <media/v4l2-device.h> | ||
32 | |||
33 | #include <sound/core.h> | ||
34 | #include <sound/initval.h> | ||
35 | |||
36 | #include "cx18-driver.h" | ||
37 | #include "cx18-version.h" | ||
38 | #include "cx18-alsa.h" | ||
39 | #include "cx18-alsa-mixer.h" | ||
40 | #include "cx18-alsa-pcm.h" | ||
41 | |||
42 | int cx18_alsa_debug; | ||
43 | |||
44 | #define CX18_DEBUG_ALSA_INFO(fmt, arg...) \ | ||
45 | do { \ | ||
46 | if (cx18_alsa_debug & 2) \ | ||
47 | printk(KERN_INFO "%s: " fmt, "cx18-alsa", ## arg); \ | ||
48 | } while (0); | ||
49 | |||
50 | module_param_named(debug, cx18_alsa_debug, int, 0644); | ||
51 | MODULE_PARM_DESC(debug, | ||
52 | "Debug level (bitmask). Default: 0\n" | ||
53 | "\t\t\t 1/0x0001: warning\n" | ||
54 | "\t\t\t 2/0x0002: info\n"); | ||
55 | |||
56 | MODULE_AUTHOR("Andy Walls"); | ||
57 | MODULE_DESCRIPTION("CX23418 ALSA Interface"); | ||
58 | MODULE_SUPPORTED_DEVICE("CX23418 MPEG2 encoder"); | ||
59 | MODULE_LICENSE("GPL"); | ||
60 | |||
61 | MODULE_VERSION(CX18_VERSION); | ||
62 | |||
63 | static inline | ||
64 | struct snd_cx18_card *to_snd_cx18_card(struct v4l2_device *v4l2_dev) | ||
65 | { | ||
66 | return to_cx18(v4l2_dev)->alsa; | ||
67 | } | ||
68 | |||
69 | static inline | ||
70 | struct snd_cx18_card *p_to_snd_cx18_card(struct v4l2_device **v4l2_dev) | ||
71 | { | ||
72 | return container_of(v4l2_dev, struct snd_cx18_card, v4l2_dev); | ||
73 | } | ||
74 | |||
75 | static void snd_cx18_card_free(struct snd_cx18_card *cxsc) | ||
76 | { | ||
77 | if (cxsc == NULL) | ||
78 | return; | ||
79 | |||
80 | if (cxsc->v4l2_dev != NULL) | ||
81 | to_cx18(cxsc->v4l2_dev)->alsa = NULL; | ||
82 | |||
83 | /* FIXME - take any other stopping actions needed */ | ||
84 | |||
85 | kfree(cxsc); | ||
86 | } | ||
87 | |||
88 | static void snd_cx18_card_private_free(struct snd_card *sc) | ||
89 | { | ||
90 | if (sc == NULL) | ||
91 | return; | ||
92 | snd_cx18_card_free(sc->private_data); | ||
93 | sc->private_data = NULL; | ||
94 | sc->private_free = NULL; | ||
95 | } | ||
96 | |||
97 | static int snd_cx18_card_create(struct v4l2_device *v4l2_dev, | ||
98 | struct snd_card *sc, | ||
99 | struct snd_cx18_card **cxsc) | ||
100 | { | ||
101 | *cxsc = kzalloc(sizeof(struct snd_cx18_card), GFP_KERNEL); | ||
102 | if (*cxsc == NULL) | ||
103 | return -ENOMEM; | ||
104 | |||
105 | (*cxsc)->v4l2_dev = v4l2_dev; | ||
106 | (*cxsc)->sc = sc; | ||
107 | |||
108 | sc->private_data = *cxsc; | ||
109 | sc->private_free = snd_cx18_card_private_free; | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static int snd_cx18_card_set_names(struct snd_cx18_card *cxsc) | ||
115 | { | ||
116 | struct cx18 *cx = to_cx18(cxsc->v4l2_dev); | ||
117 | struct snd_card *sc = cxsc->sc; | ||
118 | |||
119 | /* sc->driver is used by alsa-lib's configurator: simple, unique */ | ||
120 | strlcpy(sc->driver, "CX23418", sizeof(sc->driver)); | ||
121 | |||
122 | /* sc->shortname is a symlink in /proc/asound: CX18-M -> cardN */ | ||
123 | snprintf(sc->shortname, sizeof(sc->shortname), "CX18-%d", | ||
124 | cx->instance); | ||
125 | |||
126 | /* sc->longname is read from /proc/asound/cards */ | ||
127 | snprintf(sc->longname, sizeof(sc->longname), | ||
128 | "CX23418 #%d %s TV/FM Radio/Line-In Capture", | ||
129 | cx->instance, cx->card_name); | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static int snd_cx18_init(struct v4l2_device *v4l2_dev) | ||
135 | { | ||
136 | struct cx18 *cx = to_cx18(v4l2_dev); | ||
137 | struct snd_card *sc = NULL; | ||
138 | struct snd_cx18_card *cxsc; | ||
139 | int ret; | ||
140 | |||
141 | /* Numbrs steps from "Writing an ALSA Driver" by Takashi Iwai */ | ||
142 | |||
143 | /* (1) Check and increment the device index */ | ||
144 | /* This is a no-op for us. We'll use the cx->instance */ | ||
145 | |||
146 | /* (2) Create a card instance */ | ||
147 | ret = snd_card_create(SNDRV_DEFAULT_IDX1, /* use first available id */ | ||
148 | SNDRV_DEFAULT_STR1, /* xid from end of shortname*/ | ||
149 | THIS_MODULE, 0, &sc); | ||
150 | if (ret) { | ||
151 | CX18_ALSA_ERR("%s: snd_card_create() failed with err %d\n", | ||
152 | __func__, ret); | ||
153 | goto err_exit; | ||
154 | } | ||
155 | |||
156 | /* (3) Create a main component */ | ||
157 | ret = snd_cx18_card_create(v4l2_dev, sc, &cxsc); | ||
158 | if (ret) { | ||
159 | CX18_ALSA_ERR("%s: snd_cx18_card_create() failed with err %d\n", | ||
160 | __func__, ret); | ||
161 | goto err_exit_free; | ||
162 | } | ||
163 | |||
164 | /* (4) Set the driver ID and name strings */ | ||
165 | snd_cx18_card_set_names(cxsc); | ||
166 | |||
167 | |||
168 | ret = snd_cx18_pcm_create(cxsc); | ||
169 | if (ret) { | ||
170 | CX18_ALSA_ERR("%s: snd_cx18_pcm_create() failed with err %d\n", | ||
171 | __func__, ret); | ||
172 | goto err_exit_free; | ||
173 | } | ||
174 | /* FIXME - proc files */ | ||
175 | |||
176 | /* (7) Set the driver data and return 0 */ | ||
177 | /* We do this out of normal order for PCI drivers to avoid races */ | ||
178 | cx->alsa = cxsc; | ||
179 | |||
180 | /* (6) Register the card instance */ | ||
181 | ret = snd_card_register(sc); | ||
182 | if (ret) { | ||
183 | cx->alsa = NULL; | ||
184 | CX18_ALSA_ERR("%s: snd_card_register() failed with err %d\n", | ||
185 | __func__, ret); | ||
186 | goto err_exit_free; | ||
187 | } | ||
188 | |||
189 | return 0; | ||
190 | |||
191 | err_exit_free: | ||
192 | if (sc != NULL) | ||
193 | snd_card_free(sc); | ||
194 | err_exit: | ||
195 | return ret; | ||
196 | } | ||
197 | |||
198 | int cx18_alsa_load(struct cx18 *cx) | ||
199 | { | ||
200 | struct v4l2_device *v4l2_dev = &cx->v4l2_dev; | ||
201 | struct cx18_stream *s; | ||
202 | |||
203 | if (v4l2_dev == NULL) { | ||
204 | printk(KERN_ERR "cx18-alsa: %s: struct v4l2_device * is NULL\n", | ||
205 | __func__); | ||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | cx = to_cx18(v4l2_dev); | ||
210 | if (cx == NULL) { | ||
211 | printk(KERN_ERR "cx18-alsa cx is NULL\n"); | ||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | s = &cx->streams[CX18_ENC_STREAM_TYPE_PCM]; | ||
216 | if (s->video_dev == NULL) { | ||
217 | CX18_DEBUG_ALSA_INFO("%s: PCM stream for card is disabled - " | ||
218 | "skipping\n", __func__); | ||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | if (cx->alsa != NULL) { | ||
223 | CX18_ALSA_ERR("%s: struct snd_cx18_card * already exists\n", | ||
224 | __func__); | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | if (snd_cx18_init(v4l2_dev)) { | ||
229 | CX18_ALSA_ERR("%s: failed to create struct snd_cx18_card\n", | ||
230 | __func__); | ||
231 | } else { | ||
232 | CX18_DEBUG_ALSA_INFO("%s: created cx18 ALSA interface instance " | ||
233 | "\n", __func__); | ||
234 | } | ||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | static int __init cx18_alsa_init(void) | ||
239 | { | ||
240 | printk(KERN_INFO "cx18-alsa: module loading...\n"); | ||
241 | cx18_ext_init = &cx18_alsa_load; | ||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | static void __exit snd_cx18_exit(struct snd_cx18_card *cxsc) | ||
246 | { | ||
247 | struct cx18 *cx = to_cx18(cxsc->v4l2_dev); | ||
248 | |||
249 | /* FIXME - pointer checks & shutdown cxsc */ | ||
250 | |||
251 | snd_card_free(cxsc->sc); | ||
252 | cx->alsa = NULL; | ||
253 | } | ||
254 | |||
255 | static int __exit cx18_alsa_exit_callback(struct device *dev, void *data) | ||
256 | { | ||
257 | struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); | ||
258 | struct snd_cx18_card *cxsc; | ||
259 | |||
260 | if (v4l2_dev == NULL) { | ||
261 | printk(KERN_ERR "cx18-alsa: %s: struct v4l2_device * is NULL\n", | ||
262 | __func__); | ||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | cxsc = to_snd_cx18_card(v4l2_dev); | ||
267 | if (cxsc == NULL) { | ||
268 | CX18_ALSA_WARN("%s: struct snd_cx18_card * is NULL\n", | ||
269 | __func__); | ||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | snd_cx18_exit(cxsc); | ||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | static void __exit cx18_alsa_exit(void) | ||
278 | { | ||
279 | struct device_driver *drv; | ||
280 | int ret; | ||
281 | |||
282 | printk(KERN_INFO "cx18-alsa: module unloading...\n"); | ||
283 | |||
284 | drv = driver_find("cx18", &pci_bus_type); | ||
285 | ret = driver_for_each_device(drv, NULL, NULL, cx18_alsa_exit_callback); | ||
286 | put_driver(drv); | ||
287 | |||
288 | cx18_ext_init = NULL; | ||
289 | printk(KERN_INFO "cx18-alsa: module unload complete\n"); | ||
290 | } | ||
291 | |||
292 | module_init(cx18_alsa_init); | ||
293 | module_exit(cx18_alsa_exit); | ||
diff --git a/drivers/media/video/cx18/cx18-alsa-mixer.c b/drivers/media/video/cx18/cx18-alsa-mixer.c new file mode 100644 index 000000000000..ef21114309fe --- /dev/null +++ b/drivers/media/video/cx18/cx18-alsa-mixer.c | |||
@@ -0,0 +1,175 @@ | |||
1 | /* | ||
2 | * ALSA mixer controls for the | ||
3 | * ALSA interface to cx18 PCM capture streams | ||
4 | * | ||
5 | * Copyright (C) 2009 Andy Walls <awalls@radix.net> | ||
6 | * | ||
7 | * 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 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU 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., 59 Temple Place, Suite 330, Boston, MA | ||
20 | * 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #include <linux/init.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/device.h> | ||
26 | #include <linux/spinlock.h> | ||
27 | #include <linux/videodev2.h> | ||
28 | |||
29 | #include <media/v4l2-device.h> | ||
30 | |||
31 | #include <sound/core.h> | ||
32 | #include <sound/control.h> | ||
33 | #include <sound/tlv.h> | ||
34 | |||
35 | #include "cx18-alsa.h" | ||
36 | #include "cx18-driver.h" | ||
37 | |||
38 | /* | ||
39 | * Note the cx18-av-core volume scale is funny, due to the alignment of the | ||
40 | * scale with another chip's range: | ||
41 | * | ||
42 | * v4l2_control value /512 indicated dB actual dB reg 0x8d4 | ||
43 | * 0x0000 - 0x01ff 0 -119 -96 228 | ||
44 | * 0x0200 - 0x02ff 1 -118 -96 228 | ||
45 | * ... | ||
46 | * 0x2c00 - 0x2dff 22 -97 -96 228 | ||
47 | * 0x2e00 - 0x2fff 23 -96 -96 228 | ||
48 | * 0x3000 - 0x31ff 24 -95 -95 226 | ||
49 | * ... | ||
50 | * 0xee00 - 0xefff 119 0 0 36 | ||
51 | * ... | ||
52 | * 0xfe00 - 0xffff 127 +8 +8 20 | ||
53 | */ | ||
54 | static inline int dB_to_cx18_av_vol(int dB) | ||
55 | { | ||
56 | if (dB < -96) | ||
57 | dB = -96; | ||
58 | else if (dB > 8) | ||
59 | dB = 8; | ||
60 | return (dB + 119) << 9; | ||
61 | } | ||
62 | |||
63 | static inline int cx18_av_vol_to_dB(int v) | ||
64 | { | ||
65 | if (v < (23 << 9)) | ||
66 | v = (23 << 9); | ||
67 | else if (v > (127 << 9)) | ||
68 | v = (127 << 9); | ||
69 | return (v >> 9) - 119; | ||
70 | } | ||
71 | |||
72 | static int snd_cx18_mixer_tv_vol_info(struct snd_kcontrol *kcontrol, | ||
73 | struct snd_ctl_elem_info *uinfo) | ||
74 | { | ||
75 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
76 | uinfo->count = 1; | ||
77 | /* We're already translating values, just keep this control in dB */ | ||
78 | uinfo->value.integer.min = -96; | ||
79 | uinfo->value.integer.max = 8; | ||
80 | uinfo->value.integer.step = 1; | ||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | static int snd_cx18_mixer_tv_vol_get(struct snd_kcontrol *kctl, | ||
85 | struct snd_ctl_elem_value *uctl) | ||
86 | { | ||
87 | struct snd_cx18_card *cxsc = snd_kcontrol_chip(kctl); | ||
88 | struct cx18 *cx = to_cx18(cxsc->v4l2_dev); | ||
89 | struct v4l2_control vctrl; | ||
90 | int ret; | ||
91 | |||
92 | vctrl.id = V4L2_CID_AUDIO_VOLUME; | ||
93 | vctrl.value = dB_to_cx18_av_vol(uctl->value.integer.value[0]); | ||
94 | |||
95 | snd_cx18_lock(cxsc); | ||
96 | ret = v4l2_subdev_call(cx->sd_av, core, g_ctrl, &vctrl); | ||
97 | snd_cx18_unlock(cxsc); | ||
98 | |||
99 | if (!ret) | ||
100 | uctl->value.integer.value[0] = cx18_av_vol_to_dB(vctrl.value); | ||
101 | return ret; | ||
102 | } | ||
103 | |||
104 | static int snd_cx18_mixer_tv_vol_put(struct snd_kcontrol *kctl, | ||
105 | struct snd_ctl_elem_value *uctl) | ||
106 | { | ||
107 | struct snd_cx18_card *cxsc = snd_kcontrol_chip(kctl); | ||
108 | struct cx18 *cx = to_cx18(cxsc->v4l2_dev); | ||
109 | struct v4l2_control vctrl; | ||
110 | int ret; | ||
111 | |||
112 | vctrl.id = V4L2_CID_AUDIO_VOLUME; | ||
113 | vctrl.value = dB_to_cx18_av_vol(uctl->value.integer.value[0]); | ||
114 | |||
115 | snd_cx18_lock(cxsc); | ||
116 | |||
117 | /* Fetch current state */ | ||
118 | ret = v4l2_subdev_call(cx->sd_av, core, g_ctrl, &vctrl); | ||
119 | |||
120 | if (ret || | ||
121 | (cx18_av_vol_to_dB(vctrl.value) != uctl->value.integer.value[0])) { | ||
122 | |||
123 | /* Set, if needed */ | ||
124 | vctrl.value = dB_to_cx18_av_vol(uctl->value.integer.value[0]); | ||
125 | ret = v4l2_subdev_call(cx->sd_av, core, s_ctrl, &vctrl); | ||
126 | if (!ret) | ||
127 | ret = 1; /* Indicate control was changed w/o error */ | ||
128 | } | ||
129 | snd_cx18_unlock(cxsc); | ||
130 | |||
131 | return ret; | ||
132 | } | ||
133 | |||
134 | |||
135 | /* This is a bit of overkill, the slider is already in dB internally */ | ||
136 | static DECLARE_TLV_DB_SCALE(snd_cx18_mixer_tv_vol_db_scale, -9600, 100, 0); | ||
137 | |||
138 | static struct snd_kcontrol_new snd_cx18_mixer_tv_vol __initdata = { | ||
139 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
140 | .name = "Analog TV Capture Volume", | ||
141 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
142 | SNDRV_CTL_ELEM_ACCESS_TLV_READ, | ||
143 | .info = snd_cx18_mixer_tv_volume_info, | ||
144 | .get = snd_cx18_mixer_tv_volume_get, | ||
145 | .put = snd_cx18_mixer_tv_volume_put, | ||
146 | .tlv.p = snd_cx18_mixer_tv_vol_db_scale | ||
147 | }; | ||
148 | |||
149 | /* FIXME - add mute switch and balance, bass, treble sliders: | ||
150 | V4L2_CID_AUDIO_MUTE | ||
151 | |||
152 | V4L2_CID_AUDIO_BALANCE | ||
153 | |||
154 | V4L2_CID_AUDIO_BASS | ||
155 | V4L2_CID_AUDIO_TREBLE | ||
156 | */ | ||
157 | |||
158 | /* FIXME - add stereo, lang1, lang2, mono menu */ | ||
159 | /* FIXME - add CS5345 I2S volume for HVR-1600 */ | ||
160 | |||
161 | int __init snd_cx18_mixer_create(struct snd_cx18_card *cxsc) | ||
162 | { | ||
163 | struct v4l2_device *v4l2_dev = cxsc->v4l2_dev; | ||
164 | struct snd_card *sc = cxsc->sc; | ||
165 | int ret; | ||
166 | |||
167 | strlcpy(sc->mixername, "CX23418 Mixer", sizeof(sc->mixername)); | ||
168 | |||
169 | ret = snd_ctl_add(sc, snd_ctl_new1(snd_cx18_mixer_tv_vol, cxsc)); | ||
170 | if (ret) { | ||
171 | CX18_ALSA_WARN("%s: failed to add %s control, err %d\n", | ||
172 | __func__, snd_cx18_mixer_tv_vol.name, ret); | ||
173 | } | ||
174 | return ret; | ||
175 | } | ||
diff --git a/drivers/media/video/cx18/cx18-alsa-mixer.h b/drivers/media/video/cx18/cx18-alsa-mixer.h new file mode 100644 index 000000000000..2d418db000fe --- /dev/null +++ b/drivers/media/video/cx18/cx18-alsa-mixer.h | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * ALSA mixer controls for the | ||
3 | * ALSA interface to cx18 PCM capture streams | ||
4 | * | ||
5 | * Copyright (C) 2009 Andy Walls <awalls@radix.net> | ||
6 | * | ||
7 | * 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 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU 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., 59 Temple Place, Suite 330, Boston, MA | ||
20 | * 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | int __init snd_cx18_mixer_create(struct snd_cx18_card *cxsc); | ||
diff --git a/drivers/media/video/cx18/cx18-alsa-pcm.c b/drivers/media/video/cx18/cx18-alsa-pcm.c new file mode 100644 index 000000000000..2bd312daeb1e --- /dev/null +++ b/drivers/media/video/cx18/cx18-alsa-pcm.c | |||
@@ -0,0 +1,354 @@ | |||
1 | /* | ||
2 | * ALSA PCM device for the | ||
3 | * ALSA interface to cx18 PCM capture streams | ||
4 | * | ||
5 | * Copyright (C) 2009 Andy Walls <awalls@radix.net> | ||
6 | * Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com> | ||
7 | * | ||
8 | * Portions of this work were sponsored by ONELAN Limited. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
23 | * 02111-1307 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/init.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/vmalloc.h> | ||
29 | |||
30 | #include <media/v4l2-device.h> | ||
31 | |||
32 | #include <sound/core.h> | ||
33 | #include <sound/pcm.h> | ||
34 | |||
35 | #include "cx18-driver.h" | ||
36 | #include "cx18-queue.h" | ||
37 | #include "cx18-streams.h" | ||
38 | #include "cx18-fileops.h" | ||
39 | #include "cx18-alsa.h" | ||
40 | |||
41 | static unsigned int pcm_debug; | ||
42 | module_param(pcm_debug, int, 0644); | ||
43 | MODULE_PARM_DESC(pcm_debug, "enable debug messages for pcm"); | ||
44 | |||
45 | #define dprintk(fmt, arg...) do { \ | ||
46 | if (pcm_debug) \ | ||
47 | printk(KERN_INFO "cx18-alsa-pcm %s: " fmt, \ | ||
48 | __func__, ##arg); \ | ||
49 | } while (0) | ||
50 | |||
51 | static struct snd_pcm_hardware snd_cx18_hw_capture = { | ||
52 | .info = SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
53 | SNDRV_PCM_INFO_MMAP | | ||
54 | SNDRV_PCM_INFO_INTERLEAVED | | ||
55 | SNDRV_PCM_INFO_MMAP_VALID, | ||
56 | |||
57 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
58 | |||
59 | .rates = SNDRV_PCM_RATE_48000, | ||
60 | |||
61 | .rate_min = 48000, | ||
62 | .rate_max = 48000, | ||
63 | .channels_min = 2, | ||
64 | .channels_max = 2, | ||
65 | .buffer_bytes_max = 62720 * 8, /* just about the value in usbaudio.c */ | ||
66 | .period_bytes_min = 64, /* 12544/2, */ | ||
67 | .period_bytes_max = 12544, | ||
68 | .periods_min = 2, | ||
69 | .periods_max = 98, /* 12544, */ | ||
70 | }; | ||
71 | |||
72 | void cx18_alsa_announce_pcm_data(struct snd_cx18_card *cxsc, u8 *pcm_data, | ||
73 | size_t num_bytes) | ||
74 | { | ||
75 | struct snd_pcm_substream *substream; | ||
76 | struct snd_pcm_runtime *runtime; | ||
77 | unsigned int oldptr; | ||
78 | unsigned int stride; | ||
79 | int period_elapsed = 0; | ||
80 | int length; | ||
81 | |||
82 | dprintk("cx18 alsa announce ptr=%p data=%p num_bytes=%zd\n", cxsc, | ||
83 | pcm_data, num_bytes); | ||
84 | |||
85 | substream = cxsc->capture_pcm_substream; | ||
86 | if (substream == NULL) { | ||
87 | dprintk("substream was NULL\n"); | ||
88 | return; | ||
89 | } | ||
90 | |||
91 | runtime = substream->runtime; | ||
92 | if (runtime == NULL) { | ||
93 | dprintk("runtime was NULL\n"); | ||
94 | return; | ||
95 | } | ||
96 | |||
97 | stride = runtime->frame_bits >> 3; | ||
98 | if (stride == 0) { | ||
99 | dprintk("stride is zero\n"); | ||
100 | return; | ||
101 | } | ||
102 | |||
103 | length = num_bytes / stride; | ||
104 | if (length == 0) { | ||
105 | dprintk("%s: length was zero\n", __func__); | ||
106 | return; | ||
107 | } | ||
108 | |||
109 | if (runtime->dma_area == NULL) { | ||
110 | dprintk("dma area was NULL - ignoring\n"); | ||
111 | return; | ||
112 | } | ||
113 | |||
114 | oldptr = cxsc->hwptr_done_capture; | ||
115 | if (oldptr + length >= runtime->buffer_size) { | ||
116 | unsigned int cnt = | ||
117 | runtime->buffer_size - oldptr; | ||
118 | memcpy(runtime->dma_area + oldptr * stride, pcm_data, | ||
119 | cnt * stride); | ||
120 | memcpy(runtime->dma_area, pcm_data + cnt * stride, | ||
121 | length * stride - cnt * stride); | ||
122 | } else { | ||
123 | memcpy(runtime->dma_area + oldptr * stride, pcm_data, | ||
124 | length * stride); | ||
125 | } | ||
126 | snd_pcm_stream_lock(substream); | ||
127 | |||
128 | cxsc->hwptr_done_capture += length; | ||
129 | if (cxsc->hwptr_done_capture >= | ||
130 | runtime->buffer_size) | ||
131 | cxsc->hwptr_done_capture -= | ||
132 | runtime->buffer_size; | ||
133 | |||
134 | cxsc->capture_transfer_done += length; | ||
135 | if (cxsc->capture_transfer_done >= | ||
136 | runtime->period_size) { | ||
137 | cxsc->capture_transfer_done -= | ||
138 | runtime->period_size; | ||
139 | period_elapsed = 1; | ||
140 | } | ||
141 | |||
142 | snd_pcm_stream_unlock(substream); | ||
143 | |||
144 | if (period_elapsed) | ||
145 | snd_pcm_period_elapsed(substream); | ||
146 | } | ||
147 | |||
148 | static int snd_cx18_pcm_capture_open(struct snd_pcm_substream *substream) | ||
149 | { | ||
150 | struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream); | ||
151 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
152 | struct v4l2_device *v4l2_dev = cxsc->v4l2_dev; | ||
153 | struct cx18 *cx = to_cx18(v4l2_dev); | ||
154 | struct cx18_stream *s; | ||
155 | struct cx18_open_id item; | ||
156 | int ret; | ||
157 | |||
158 | /* Instruct the cx18 to start sending packets */ | ||
159 | snd_cx18_lock(cxsc); | ||
160 | s = &cx->streams[CX18_ENC_STREAM_TYPE_PCM]; | ||
161 | |||
162 | item.cx = cx; | ||
163 | item.type = s->type; | ||
164 | item.open_id = cx->open_id++; | ||
165 | |||
166 | /* See if the stream is available */ | ||
167 | if (cx18_claim_stream(&item, item.type)) { | ||
168 | /* No, it's already in use */ | ||
169 | snd_cx18_unlock(cxsc); | ||
170 | return -EBUSY; | ||
171 | } | ||
172 | |||
173 | if (test_bit(CX18_F_S_STREAMOFF, &s->s_flags) || | ||
174 | test_and_set_bit(CX18_F_S_STREAMING, &s->s_flags)) { | ||
175 | /* We're already streaming. No additional action required */ | ||
176 | snd_cx18_unlock(cxsc); | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | |||
181 | runtime->hw = snd_cx18_hw_capture; | ||
182 | snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | ||
183 | cxsc->capture_pcm_substream = substream; | ||
184 | runtime->private_data = cx; | ||
185 | |||
186 | cx->pcm_announce_callback = cx18_alsa_announce_pcm_data; | ||
187 | |||
188 | /* Not currently streaming, so start it up */ | ||
189 | set_bit(CX18_F_S_STREAMING, &s->s_flags); | ||
190 | ret = cx18_start_v4l2_encode_stream(s); | ||
191 | snd_cx18_unlock(cxsc); | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | static int snd_cx18_pcm_capture_close(struct snd_pcm_substream *substream) | ||
197 | { | ||
198 | struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream); | ||
199 | struct v4l2_device *v4l2_dev = cxsc->v4l2_dev; | ||
200 | struct cx18 *cx = to_cx18(v4l2_dev); | ||
201 | struct cx18_stream *s; | ||
202 | int ret; | ||
203 | |||
204 | /* Instruct the cx18 to stop sending packets */ | ||
205 | snd_cx18_lock(cxsc); | ||
206 | s = &cx->streams[CX18_ENC_STREAM_TYPE_PCM]; | ||
207 | ret = cx18_stop_v4l2_encode_stream(s, 0); | ||
208 | clear_bit(CX18_F_S_STREAMING, &s->s_flags); | ||
209 | |||
210 | cx18_release_stream(s); | ||
211 | |||
212 | cx->pcm_announce_callback = NULL; | ||
213 | snd_cx18_unlock(cxsc); | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static int snd_cx18_pcm_ioctl(struct snd_pcm_substream *substream, | ||
219 | unsigned int cmd, void *arg) | ||
220 | { | ||
221 | return snd_pcm_lib_ioctl(substream, cmd, arg); | ||
222 | } | ||
223 | |||
224 | |||
225 | static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, | ||
226 | size_t size) | ||
227 | { | ||
228 | struct snd_pcm_runtime *runtime = subs->runtime; | ||
229 | |||
230 | dprintk("Allocating vbuffer\n"); | ||
231 | if (runtime->dma_area) { | ||
232 | if (runtime->dma_bytes > size) | ||
233 | return 0; | ||
234 | |||
235 | vfree(runtime->dma_area); | ||
236 | } | ||
237 | runtime->dma_area = vmalloc(size); | ||
238 | if (!runtime->dma_area) | ||
239 | return -ENOMEM; | ||
240 | |||
241 | runtime->dma_bytes = size; | ||
242 | |||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static int snd_cx18_pcm_hw_params(struct snd_pcm_substream *substream, | ||
247 | struct snd_pcm_hw_params *params) | ||
248 | { | ||
249 | int ret; | ||
250 | |||
251 | dprintk("%s called\n", __func__); | ||
252 | |||
253 | ret = snd_pcm_alloc_vmalloc_buffer(substream, | ||
254 | params_buffer_bytes(params)); | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static int snd_cx18_pcm_hw_free(struct snd_pcm_substream *substream) | ||
259 | { | ||
260 | struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream); | ||
261 | unsigned long flags; | ||
262 | |||
263 | spin_lock_irqsave(&cxsc->slock, flags); | ||
264 | if (substream->runtime->dma_area) { | ||
265 | dprintk("freeing pcm capture region\n"); | ||
266 | vfree(substream->runtime->dma_area); | ||
267 | substream->runtime->dma_area = NULL; | ||
268 | } | ||
269 | spin_unlock_irqrestore(&cxsc->slock, flags); | ||
270 | |||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | static int snd_cx18_pcm_prepare(struct snd_pcm_substream *substream) | ||
275 | { | ||
276 | struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream); | ||
277 | |||
278 | cxsc->hwptr_done_capture = 0; | ||
279 | cxsc->capture_transfer_done = 0; | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static int snd_cx18_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | ||
285 | { | ||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | static | ||
290 | snd_pcm_uframes_t snd_cx18_pcm_pointer(struct snd_pcm_substream *substream) | ||
291 | { | ||
292 | unsigned long flags; | ||
293 | snd_pcm_uframes_t hwptr_done; | ||
294 | struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream); | ||
295 | |||
296 | spin_lock_irqsave(&cxsc->slock, flags); | ||
297 | hwptr_done = cxsc->hwptr_done_capture; | ||
298 | spin_unlock_irqrestore(&cxsc->slock, flags); | ||
299 | |||
300 | return hwptr_done; | ||
301 | } | ||
302 | |||
303 | static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs, | ||
304 | unsigned long offset) | ||
305 | { | ||
306 | void *pageptr = subs->runtime->dma_area + offset; | ||
307 | |||
308 | return vmalloc_to_page(pageptr); | ||
309 | } | ||
310 | |||
311 | static struct snd_pcm_ops snd_cx18_pcm_capture_ops = { | ||
312 | .open = snd_cx18_pcm_capture_open, | ||
313 | .close = snd_cx18_pcm_capture_close, | ||
314 | .ioctl = snd_cx18_pcm_ioctl, | ||
315 | .hw_params = snd_cx18_pcm_hw_params, | ||
316 | .hw_free = snd_cx18_pcm_hw_free, | ||
317 | .prepare = snd_cx18_pcm_prepare, | ||
318 | .trigger = snd_cx18_pcm_trigger, | ||
319 | .pointer = snd_cx18_pcm_pointer, | ||
320 | .page = snd_pcm_get_vmalloc_page, | ||
321 | }; | ||
322 | |||
323 | int snd_cx18_pcm_create(struct snd_cx18_card *cxsc) | ||
324 | { | ||
325 | struct snd_pcm *sp; | ||
326 | struct snd_card *sc = cxsc->sc; | ||
327 | struct v4l2_device *v4l2_dev = cxsc->v4l2_dev; | ||
328 | struct cx18 *cx = to_cx18(v4l2_dev); | ||
329 | int ret; | ||
330 | |||
331 | ret = snd_pcm_new(sc, "CX23418 PCM", | ||
332 | 0, /* PCM device 0, the only one for this card */ | ||
333 | 0, /* 0 playback substreams */ | ||
334 | 1, /* 1 capture substream */ | ||
335 | &sp); | ||
336 | if (ret) { | ||
337 | CX18_ALSA_ERR("%s: snd_cx18_pcm_create() failed with err %d\n", | ||
338 | __func__, ret); | ||
339 | goto err_exit; | ||
340 | } | ||
341 | |||
342 | spin_lock_init(&cxsc->slock); | ||
343 | |||
344 | snd_pcm_set_ops(sp, SNDRV_PCM_STREAM_CAPTURE, | ||
345 | &snd_cx18_pcm_capture_ops); | ||
346 | sp->info_flags = 0; | ||
347 | sp->private_data = cxsc; | ||
348 | strlcpy(sp->name, cx->card_name, sizeof(sp->name)); | ||
349 | |||
350 | return 0; | ||
351 | |||
352 | err_exit: | ||
353 | return ret; | ||
354 | } | ||
diff --git a/drivers/media/video/cx18/cx18-alsa-pcm.h b/drivers/media/video/cx18/cx18-alsa-pcm.h new file mode 100644 index 000000000000..325662c647a0 --- /dev/null +++ b/drivers/media/video/cx18/cx18-alsa-pcm.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * ALSA PCM device for the | ||
3 | * ALSA interface to cx18 PCM capture streams | ||
4 | * | ||
5 | * Copyright (C) 2009 Andy Walls <awalls@radix.net> | ||
6 | * | ||
7 | * 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 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU 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., 59 Temple Place, Suite 330, Boston, MA | ||
20 | * 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | int __init snd_cx18_pcm_create(struct snd_cx18_card *cxsc); | ||
24 | |||
25 | /* Used by cx18-mailbox to announce the PCM data to the module */ | ||
26 | void cx18_alsa_announce_pcm_data(struct snd_cx18_card *card, u8 *pcm_data, | ||
27 | size_t num_bytes); | ||
diff --git a/drivers/media/video/cx18/cx18-alsa.h b/drivers/media/video/cx18/cx18-alsa.h new file mode 100644 index 000000000000..88a1cde7540b --- /dev/null +++ b/drivers/media/video/cx18/cx18-alsa.h | |||
@@ -0,0 +1,75 @@ | |||
1 | /* | ||
2 | * ALSA interface to cx18 PCM capture streams | ||
3 | * | ||
4 | * Copyright (C) 2009 Andy Walls <awalls@radix.net> | ||
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 as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
19 | * 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | struct snd_card; | ||
23 | |||
24 | struct snd_cx18_card { | ||
25 | struct v4l2_device *v4l2_dev; | ||
26 | struct snd_card *sc; | ||
27 | unsigned int capture_transfer_done; | ||
28 | unsigned int hwptr_done_capture; | ||
29 | struct snd_pcm_substream *capture_pcm_substream; | ||
30 | spinlock_t slock; | ||
31 | }; | ||
32 | |||
33 | extern int cx18_alsa_debug; | ||
34 | |||
35 | /* | ||
36 | * File operations that manipulate the encoder or video or audio subdevices | ||
37 | * need to be serialized. Use the same lock we use for v4l2 file ops. | ||
38 | */ | ||
39 | static inline void snd_cx18_lock(struct snd_cx18_card *cxsc) | ||
40 | { | ||
41 | struct cx18 *cx = to_cx18(cxsc->v4l2_dev); | ||
42 | mutex_lock(&cx->serialize_lock); | ||
43 | } | ||
44 | |||
45 | static inline void snd_cx18_unlock(struct snd_cx18_card *cxsc) | ||
46 | { | ||
47 | struct cx18 *cx = to_cx18(cxsc->v4l2_dev); | ||
48 | mutex_unlock(&cx->serialize_lock); | ||
49 | } | ||
50 | |||
51 | #define CX18_ALSA_DBGFLG_WARN (1 << 0) | ||
52 | #define CX18_ALSA_DBGFLG_WARN (1 << 0) | ||
53 | #define CX18_ALSA_DBGFLG_INFO (1 << 1) | ||
54 | |||
55 | #define CX18_ALSA_DEBUG(x, type, fmt, args...) \ | ||
56 | do { \ | ||
57 | if ((x) & cx18_alsa_debug) \ | ||
58 | printk(KERN_INFO "%s-alsa: " type ": " fmt, \ | ||
59 | v4l2_dev->name , ## args); \ | ||
60 | } while (0) | ||
61 | |||
62 | #define CX18_ALSA_DEBUG_WARN(fmt, args...) \ | ||
63 | CX18_ALSA_DEBUG(CX18_ALSA_DBGFLG_WARN, "warning", fmt , ## args) | ||
64 | |||
65 | #define CX18_ALSA_DEBUG_INFO(fmt, args...) \ | ||
66 | CX18_ALSA_DEBUG(CX18_ALSA_DBGFLG_INFO, "info", fmt , ## args) | ||
67 | |||
68 | #define CX18_ALSA_ERR(fmt, args...) \ | ||
69 | printk(KERN_ERR "%s-alsa: " fmt, v4l2_dev->name , ## args) | ||
70 | |||
71 | #define CX18_ALSA_WARN(fmt, args...) \ | ||
72 | printk(KERN_WARNING "%s-alsa: " fmt, v4l2_dev->name , ## args) | ||
73 | |||
74 | #define CX18_ALSA_INFO(fmt, args...) \ | ||
75 | printk(KERN_INFO "%s-alsa: " fmt, v4l2_dev->name , ## args) | ||
diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index f11e47a58286..f808fb6fc1c1 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c | |||
@@ -393,7 +393,7 @@ static const struct cx18_card cx18_card_leadtek_pvr2100 = { | |||
393 | .gpio_init.direction = 0x7, | 393 | .gpio_init.direction = 0x7, |
394 | .gpio_audio_input = { .mask = 0x7, | 394 | .gpio_audio_input = { .mask = 0x7, |
395 | .tuner = 0x6, .linein = 0x2, .radio = 0x2 }, | 395 | .tuner = 0x6, .linein = 0x2, .radio = 0x2 }, |
396 | .xceive_pin = 15, | 396 | .xceive_pin = 1, |
397 | .pci_list = cx18_pci_leadtek_pvr2100, | 397 | .pci_list = cx18_pci_leadtek_pvr2100, |
398 | .i2c = &cx18_i2c_std, | 398 | .i2c = &cx18_i2c_std, |
399 | }; | 399 | }; |
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 7f65a47f12e1..c95a86ba33b0 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c | |||
@@ -47,6 +47,10 @@ | |||
47 | setting this to 1 you ensure that radio0 is now also radio1. */ | 47 | setting this to 1 you ensure that radio0 is now also radio1. */ |
48 | int cx18_first_minor; | 48 | int cx18_first_minor; |
49 | 49 | ||
50 | /* Callback for registering extensions */ | ||
51 | int (*cx18_ext_init)(struct cx18 *); | ||
52 | EXPORT_SYMBOL(cx18_ext_init); | ||
53 | |||
50 | /* add your revision and whatnot here */ | 54 | /* add your revision and whatnot here */ |
51 | static struct pci_device_id cx18_pci_tbl[] __devinitdata = { | 55 | static struct pci_device_id cx18_pci_tbl[] __devinitdata = { |
52 | {PCI_VENDOR_ID_CX, PCI_DEVICE_ID_CX23418, | 56 | {PCI_VENDOR_ID_CX, PCI_DEVICE_ID_CX23418, |
@@ -91,7 +95,7 @@ static int enc_pcm_bufsize = CX18_DEFAULT_ENC_PCM_BUFSIZE; | |||
91 | 95 | ||
92 | static int enc_ts_bufs = -1; | 96 | static int enc_ts_bufs = -1; |
93 | static int enc_mpg_bufs = -1; | 97 | static int enc_mpg_bufs = -1; |
94 | static int enc_idx_bufs = -1; | 98 | static int enc_idx_bufs = CX18_MAX_FW_MDLS_PER_STREAM; |
95 | static int enc_yuv_bufs = -1; | 99 | static int enc_yuv_bufs = -1; |
96 | static int enc_vbi_bufs = -1; | 100 | static int enc_vbi_bufs = -1; |
97 | static int enc_pcm_bufs = -1; | 101 | static int enc_pcm_bufs = -1; |
@@ -196,14 +200,17 @@ MODULE_PARM_DESC(enc_mpg_bufs, | |||
196 | "Number of encoder MPG buffers\n" | 200 | "Number of encoder MPG buffers\n" |
197 | "\t\t\tDefault is computed from other enc_mpg_* parameters"); | 201 | "\t\t\tDefault is computed from other enc_mpg_* parameters"); |
198 | MODULE_PARM_DESC(enc_idx_buffers, | 202 | MODULE_PARM_DESC(enc_idx_buffers, |
199 | "Encoder IDX buffer memory (MB). (enc_idx_bufs can override)\n" | 203 | "(Deprecated) Encoder IDX buffer memory (MB)\n" |
200 | "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_IDX_BUFFERS)); | 204 | "\t\t\tIgnored, except 0 disables IDX buffer allocations\n" |
205 | "\t\t\tDefault: 1 [Enabled]"); | ||
201 | MODULE_PARM_DESC(enc_idx_bufsize, | 206 | MODULE_PARM_DESC(enc_idx_bufsize, |
202 | "Size of an encoder IDX buffer (kB)\n" | 207 | "Size of an encoder IDX buffer (kB)\n" |
203 | "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_IDX_BUFSIZE)); | 208 | "\t\t\tAllowed values are multiples of 1.5 kB rounded up\n" |
209 | "\t\t\t(multiples of size required for 64 index entries)\n" | ||
210 | "\t\t\tDefault: 2"); | ||
204 | MODULE_PARM_DESC(enc_idx_bufs, | 211 | MODULE_PARM_DESC(enc_idx_bufs, |
205 | "Number of encoder IDX buffers\n" | 212 | "Number of encoder IDX buffers\n" |
206 | "\t\t\tDefault is computed from other enc_idx_* parameters"); | 213 | "\t\t\tDefault: " __stringify(CX18_MAX_FW_MDLS_PER_STREAM)); |
207 | MODULE_PARM_DESC(enc_yuv_buffers, | 214 | MODULE_PARM_DESC(enc_yuv_buffers, |
208 | "Encoder YUV buffer memory (MB). (enc_yuv_bufs can override)\n" | 215 | "Encoder YUV buffer memory (MB). (enc_yuv_bufs can override)\n" |
209 | "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFFERS)); | 216 | "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFFERS)); |
@@ -231,7 +238,8 @@ MODULE_PARM_DESC(enc_pcm_bufs, | |||
231 | "Number of encoder PCM buffers\n" | 238 | "Number of encoder PCM buffers\n" |
232 | "\t\t\tDefault is computed from other enc_pcm_* parameters"); | 239 | "\t\t\tDefault is computed from other enc_pcm_* parameters"); |
233 | 240 | ||
234 | MODULE_PARM_DESC(cx18_first_minor, "Set device node number assigned to first card"); | 241 | MODULE_PARM_DESC(cx18_first_minor, |
242 | "Set device node number assigned to first card"); | ||
235 | 243 | ||
236 | MODULE_AUTHOR("Hans Verkuil"); | 244 | MODULE_AUTHOR("Hans Verkuil"); |
237 | MODULE_DESCRIPTION("CX23418 driver"); | 245 | MODULE_DESCRIPTION("CX23418 driver"); |
@@ -240,6 +248,28 @@ MODULE_LICENSE("GPL"); | |||
240 | 248 | ||
241 | MODULE_VERSION(CX18_VERSION); | 249 | MODULE_VERSION(CX18_VERSION); |
242 | 250 | ||
251 | #if defined(CONFIG_MODULES) && defined(MODULE) | ||
252 | static void request_module_async(struct work_struct *work) | ||
253 | { | ||
254 | struct cx18 *dev = container_of(work, struct cx18, request_module_wk); | ||
255 | |||
256 | /* Make sure cx18-alsa module is loaded */ | ||
257 | request_module("cx18-alsa"); | ||
258 | |||
259 | /* Initialize cx18-alsa for this instance of the cx18 device */ | ||
260 | if (cx18_ext_init != NULL) | ||
261 | cx18_ext_init(dev); | ||
262 | } | ||
263 | |||
264 | static void request_modules(struct cx18 *dev) | ||
265 | { | ||
266 | INIT_WORK(&dev->request_module_wk, request_module_async); | ||
267 | schedule_work(&dev->request_module_wk); | ||
268 | } | ||
269 | #else | ||
270 | #define request_modules(dev) | ||
271 | #endif /* CONFIG_MODULES */ | ||
272 | |||
243 | /* Generic utility functions */ | 273 | /* Generic utility functions */ |
244 | int cx18_msleep_timeout(unsigned int msecs, int intr) | 274 | int cx18_msleep_timeout(unsigned int msecs, int intr) |
245 | { | 275 | { |
@@ -501,7 +531,12 @@ static void cx18_process_options(struct cx18 *cx) | |||
501 | /* | 531 | /* |
502 | * YUV is a special case where the stream_buf_size needs to be | 532 | * YUV is a special case where the stream_buf_size needs to be |
503 | * an integral multiple of 33.75 kB (storage for 32 screens | 533 | * an integral multiple of 33.75 kB (storage for 32 screens |
504 | * lines to maintain alignment in case of lost buffers | 534 | * lines to maintain alignment in case of lost buffers). |
535 | * | ||
536 | * IDX is a special case where the stream_buf_size should be | ||
537 | * an integral multiple of 1.5 kB (storage for 64 index entries | ||
538 | * to maintain alignment in case of lost buffers). | ||
539 | * | ||
505 | */ | 540 | */ |
506 | if (i == CX18_ENC_STREAM_TYPE_YUV) { | 541 | if (i == CX18_ENC_STREAM_TYPE_YUV) { |
507 | cx->stream_buf_size[i] *= 1024; | 542 | cx->stream_buf_size[i] *= 1024; |
@@ -511,15 +546,24 @@ static void cx18_process_options(struct cx18 *cx) | |||
511 | if (cx->stream_buf_size[i] < CX18_UNIT_ENC_YUV_BUFSIZE) | 546 | if (cx->stream_buf_size[i] < CX18_UNIT_ENC_YUV_BUFSIZE) |
512 | cx->stream_buf_size[i] = | 547 | cx->stream_buf_size[i] = |
513 | CX18_UNIT_ENC_YUV_BUFSIZE; | 548 | CX18_UNIT_ENC_YUV_BUFSIZE; |
549 | } else if (i == CX18_ENC_STREAM_TYPE_IDX) { | ||
550 | cx->stream_buf_size[i] *= 1024; | ||
551 | cx->stream_buf_size[i] -= | ||
552 | (cx->stream_buf_size[i] % CX18_UNIT_ENC_IDX_BUFSIZE); | ||
553 | |||
554 | if (cx->stream_buf_size[i] < CX18_UNIT_ENC_IDX_BUFSIZE) | ||
555 | cx->stream_buf_size[i] = | ||
556 | CX18_UNIT_ENC_IDX_BUFSIZE; | ||
514 | } | 557 | } |
515 | /* | 558 | /* |
516 | * YUV is a special case where the stream_buf_size is | 559 | * YUV and IDX are special cases where the stream_buf_size is |
517 | * now in bytes. | 560 | * now in bytes. |
518 | * VBI is a special case where the stream_buf_size is fixed | 561 | * VBI is a special case where the stream_buf_size is fixed |
519 | * and already in bytes | 562 | * and already in bytes |
520 | */ | 563 | */ |
521 | if (i == CX18_ENC_STREAM_TYPE_VBI || | 564 | if (i == CX18_ENC_STREAM_TYPE_VBI || |
522 | i == CX18_ENC_STREAM_TYPE_YUV) { | 565 | i == CX18_ENC_STREAM_TYPE_YUV || |
566 | i == CX18_ENC_STREAM_TYPE_IDX) { | ||
523 | if (cx->stream_buffers[i] < 0) { | 567 | if (cx->stream_buffers[i] < 0) { |
524 | cx->stream_buffers[i] = | 568 | cx->stream_buffers[i] = |
525 | cx->options.megabytes[i] * 1024 * 1024 | 569 | cx->options.megabytes[i] * 1024 * 1024 |
@@ -1032,6 +1076,10 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev, | |||
1032 | } | 1076 | } |
1033 | 1077 | ||
1034 | CX18_INFO("Initialized card: %s\n", cx->card_name); | 1078 | CX18_INFO("Initialized card: %s\n", cx->card_name); |
1079 | |||
1080 | /* Load cx18 submodules (cx18-alsa) */ | ||
1081 | request_modules(cx); | ||
1082 | |||
1035 | return 0; | 1083 | return 0; |
1036 | 1084 | ||
1037 | free_streams: | 1085 | free_streams: |
@@ -1220,6 +1268,7 @@ static void cx18_remove(struct pci_dev *pci_dev) | |||
1220 | kfree(cx); | 1268 | kfree(cx); |
1221 | } | 1269 | } |
1222 | 1270 | ||
1271 | |||
1223 | /* define a pci_driver for card detection */ | 1272 | /* define a pci_driver for card detection */ |
1224 | static struct pci_driver cx18_pci_driver = { | 1273 | static struct pci_driver cx18_pci_driver = { |
1225 | .name = "cx18", | 1274 | .name = "cx18", |
@@ -1230,7 +1279,8 @@ static struct pci_driver cx18_pci_driver = { | |||
1230 | 1279 | ||
1231 | static int __init module_start(void) | 1280 | static int __init module_start(void) |
1232 | { | 1281 | { |
1233 | printk(KERN_INFO "cx18: Start initialization, version %s\n", CX18_VERSION); | 1282 | printk(KERN_INFO "cx18: Start initialization, version %s\n", |
1283 | CX18_VERSION); | ||
1234 | 1284 | ||
1235 | /* Validate parameters */ | 1285 | /* Validate parameters */ |
1236 | if (cx18_first_minor < 0 || cx18_first_minor >= CX18_MAX_CARDS) { | 1286 | if (cx18_first_minor < 0 || cx18_first_minor >= CX18_MAX_CARDS) { |
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index e3f7911a7385..23ad6d548dc5 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h | |||
@@ -126,10 +126,22 @@ | |||
126 | #define CX18_625_LINE_ENC_YUV_BUFSIZE (CX18_UNIT_ENC_YUV_BUFSIZE * 576/32) | 126 | #define CX18_625_LINE_ENC_YUV_BUFSIZE (CX18_UNIT_ENC_YUV_BUFSIZE * 576/32) |
127 | #define CX18_525_LINE_ENC_YUV_BUFSIZE (CX18_UNIT_ENC_YUV_BUFSIZE * 480/32) | 127 | #define CX18_525_LINE_ENC_YUV_BUFSIZE (CX18_UNIT_ENC_YUV_BUFSIZE * 480/32) |
128 | 128 | ||
129 | /* IDX buffer size should be a multiple of the index entry size from the chip */ | ||
130 | struct cx18_enc_idx_entry { | ||
131 | __le32 length; | ||
132 | __le32 offset_low; | ||
133 | __le32 offset_high; | ||
134 | __le32 flags; | ||
135 | __le32 pts_low; | ||
136 | __le32 pts_high; | ||
137 | } __attribute__ ((packed)); | ||
138 | #define CX18_UNIT_ENC_IDX_BUFSIZE \ | ||
139 | (sizeof(struct cx18_enc_idx_entry) * V4L2_ENC_IDX_ENTRIES) | ||
140 | |||
129 | /* DMA buffer, default size in kB allocated */ | 141 | /* DMA buffer, default size in kB allocated */ |
130 | #define CX18_DEFAULT_ENC_TS_BUFSIZE 32 | 142 | #define CX18_DEFAULT_ENC_TS_BUFSIZE 32 |
131 | #define CX18_DEFAULT_ENC_MPG_BUFSIZE 32 | 143 | #define CX18_DEFAULT_ENC_MPG_BUFSIZE 32 |
132 | #define CX18_DEFAULT_ENC_IDX_BUFSIZE 32 | 144 | #define CX18_DEFAULT_ENC_IDX_BUFSIZE (CX18_UNIT_ENC_IDX_BUFSIZE * 1 / 1024 + 1) |
133 | #define CX18_DEFAULT_ENC_YUV_BUFSIZE (CX18_UNIT_ENC_YUV_BUFSIZE * 3 / 1024 + 1) | 145 | #define CX18_DEFAULT_ENC_YUV_BUFSIZE (CX18_UNIT_ENC_YUV_BUFSIZE * 3 / 1024 + 1) |
134 | #define CX18_DEFAULT_ENC_PCM_BUFSIZE 4 | 146 | #define CX18_DEFAULT_ENC_PCM_BUFSIZE 4 |
135 | 147 | ||
@@ -234,16 +246,8 @@ | |||
234 | #define CX18_WARN_DEV(dev, fmt, args...) v4l2_warn(dev, fmt , ## args) | 246 | #define CX18_WARN_DEV(dev, fmt, args...) v4l2_warn(dev, fmt , ## args) |
235 | #define CX18_INFO_DEV(dev, fmt, args...) v4l2_info(dev, fmt , ## args) | 247 | #define CX18_INFO_DEV(dev, fmt, args...) v4l2_info(dev, fmt , ## args) |
236 | 248 | ||
237 | /* Values for CX18_API_DEC_PLAYBACK_SPEED mpeg_frame_type_mask parameter: */ | ||
238 | #define MPEG_FRAME_TYPE_IFRAME 1 | ||
239 | #define MPEG_FRAME_TYPE_IFRAME_PFRAME 3 | ||
240 | #define MPEG_FRAME_TYPE_ALL 7 | ||
241 | |||
242 | #define CX18_MAX_PGM_INDEX (400) | ||
243 | |||
244 | extern int cx18_debug; | 249 | extern int cx18_debug; |
245 | 250 | ||
246 | |||
247 | struct cx18_options { | 251 | struct cx18_options { |
248 | int megabytes[CX18_MAX_STREAMS]; /* Size in megabytes of each stream */ | 252 | int megabytes[CX18_MAX_STREAMS]; /* Size in megabytes of each stream */ |
249 | int cardtype; /* force card type on load */ | 253 | int cardtype; /* force card type on load */ |
@@ -276,6 +280,18 @@ struct cx18_options { | |||
276 | #define CX18_SLICED_TYPE_WSS_625 (5) | 280 | #define CX18_SLICED_TYPE_WSS_625 (5) |
277 | #define CX18_SLICED_TYPE_VPS (7) | 281 | #define CX18_SLICED_TYPE_VPS (7) |
278 | 282 | ||
283 | /** | ||
284 | * list_entry_is_past_end - check if a previous loop cursor is off list end | ||
285 | * @pos: the type * previously used as a loop cursor. | ||
286 | * @head: the head for your list. | ||
287 | * @member: the name of the list_struct within the struct. | ||
288 | * | ||
289 | * Check if the entry's list_head is the head of the list, thus it's not a | ||
290 | * real entry but was the loop cursor that walked past the end | ||
291 | */ | ||
292 | #define list_entry_is_past_end(pos, head, member) \ | ||
293 | (&pos->member == (head)) | ||
294 | |||
279 | struct cx18_buffer { | 295 | struct cx18_buffer { |
280 | struct list_head list; | 296 | struct list_head list; |
281 | dma_addr_t dma_handle; | 297 | dma_addr_t dma_handle; |
@@ -558,6 +574,10 @@ struct cx18 { | |||
558 | int stream_buffers[CX18_MAX_STREAMS]; /* # of buffers for each stream */ | 574 | int stream_buffers[CX18_MAX_STREAMS]; /* # of buffers for each stream */ |
559 | int stream_buf_size[CX18_MAX_STREAMS]; /* Stream buffer size */ | 575 | int stream_buf_size[CX18_MAX_STREAMS]; /* Stream buffer size */ |
560 | struct cx18_stream streams[CX18_MAX_STREAMS]; /* Stream data */ | 576 | struct cx18_stream streams[CX18_MAX_STREAMS]; /* Stream data */ |
577 | struct snd_cx18_card *alsa; /* ALSA interface for PCM capture stream */ | ||
578 | void (*pcm_announce_callback)(struct snd_cx18_card *card, u8 *pcm_data, | ||
579 | size_t num_bytes); | ||
580 | |||
561 | unsigned long i_flags; /* global cx18 flags */ | 581 | unsigned long i_flags; /* global cx18 flags */ |
562 | atomic_t ana_capturing; /* count number of active analog capture streams */ | 582 | atomic_t ana_capturing; /* count number of active analog capture streams */ |
563 | atomic_t tot_capturing; /* total count number of active capture streams */ | 583 | atomic_t tot_capturing; /* total count number of active capture streams */ |
@@ -575,12 +595,6 @@ struct cx18 { | |||
575 | 595 | ||
576 | struct vbi_info vbi; | 596 | struct vbi_info vbi; |
577 | 597 | ||
578 | u32 pgm_info_offset; | ||
579 | u32 pgm_info_num; | ||
580 | u32 pgm_info_write_idx; | ||
581 | u32 pgm_info_read_idx; | ||
582 | struct v4l2_enc_idx_entry pgm_info[CX18_MAX_PGM_INDEX]; | ||
583 | |||
584 | u64 mpg_data_received; | 598 | u64 mpg_data_received; |
585 | u64 vbi_data_inserted; | 599 | u64 vbi_data_inserted; |
586 | 600 | ||
@@ -623,6 +637,9 @@ struct cx18 { | |||
623 | u32 active_input; | 637 | u32 active_input; |
624 | v4l2_std_id std; | 638 | v4l2_std_id std; |
625 | v4l2_std_id tuner_std; /* The norm of the tuner (fixed) */ | 639 | v4l2_std_id tuner_std; /* The norm of the tuner (fixed) */ |
640 | |||
641 | /* Used for cx18-alsa module loading */ | ||
642 | struct work_struct request_module_wk; | ||
626 | }; | 643 | }; |
627 | 644 | ||
628 | static inline struct cx18 *to_cx18(struct v4l2_device *v4l2_dev) | 645 | static inline struct cx18 *to_cx18(struct v4l2_device *v4l2_dev) |
@@ -630,6 +647,9 @@ static inline struct cx18 *to_cx18(struct v4l2_device *v4l2_dev) | |||
630 | return container_of(v4l2_dev, struct cx18, v4l2_dev); | 647 | return container_of(v4l2_dev, struct cx18, v4l2_dev); |
631 | } | 648 | } |
632 | 649 | ||
650 | /* cx18 extensions to be loaded */ | ||
651 | extern int (*cx18_ext_init)(struct cx18 *); | ||
652 | |||
633 | /* Globals */ | 653 | /* Globals */ |
634 | extern int cx18_first_minor; | 654 | extern int cx18_first_minor; |
635 | 655 | ||
diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index 71ad2d1b4c2c..0ae2c2e1eab5 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c | |||
@@ -213,10 +213,14 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) | |||
213 | { | 213 | { |
214 | struct dvb_demux *demux = feed->demux; | 214 | struct dvb_demux *demux = feed->demux; |
215 | struct cx18_stream *stream = (struct cx18_stream *) demux->priv; | 215 | struct cx18_stream *stream = (struct cx18_stream *) demux->priv; |
216 | struct cx18 *cx = stream->cx; | 216 | struct cx18 *cx; |
217 | int ret; | 217 | int ret; |
218 | u32 v; | 218 | u32 v; |
219 | 219 | ||
220 | if (!stream) | ||
221 | return -EINVAL; | ||
222 | |||
223 | cx = stream->cx; | ||
220 | CX18_DEBUG_INFO("Start feed: pid = 0x%x index = %d\n", | 224 | CX18_DEBUG_INFO("Start feed: pid = 0x%x index = %d\n", |
221 | feed->pid, feed->index); | 225 | feed->pid, feed->index); |
222 | 226 | ||
@@ -253,12 +257,10 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) | |||
253 | if (!demux->dmx.frontend) | 257 | if (!demux->dmx.frontend) |
254 | return -EINVAL; | 258 | return -EINVAL; |
255 | 259 | ||
256 | if (!stream) | ||
257 | return -EINVAL; | ||
258 | |||
259 | mutex_lock(&stream->dvb.feedlock); | 260 | mutex_lock(&stream->dvb.feedlock); |
260 | if (stream->dvb.feeding++ == 0) { | 261 | if (stream->dvb.feeding++ == 0) { |
261 | CX18_DEBUG_INFO("Starting Transport DMA\n"); | 262 | CX18_DEBUG_INFO("Starting Transport DMA\n"); |
263 | mutex_lock(&cx->serialize_lock); | ||
262 | set_bit(CX18_F_S_STREAMING, &stream->s_flags); | 264 | set_bit(CX18_F_S_STREAMING, &stream->s_flags); |
263 | ret = cx18_start_v4l2_encode_stream(stream); | 265 | ret = cx18_start_v4l2_encode_stream(stream); |
264 | if (ret < 0) { | 266 | if (ret < 0) { |
@@ -267,6 +269,7 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) | |||
267 | if (stream->dvb.feeding == 0) | 269 | if (stream->dvb.feeding == 0) |
268 | clear_bit(CX18_F_S_STREAMING, &stream->s_flags); | 270 | clear_bit(CX18_F_S_STREAMING, &stream->s_flags); |
269 | } | 271 | } |
272 | mutex_unlock(&cx->serialize_lock); | ||
270 | } else | 273 | } else |
271 | ret = 0; | 274 | ret = 0; |
272 | mutex_unlock(&stream->dvb.feedlock); | 275 | mutex_unlock(&stream->dvb.feedlock); |
@@ -279,17 +282,20 @@ static int cx18_dvb_stop_feed(struct dvb_demux_feed *feed) | |||
279 | { | 282 | { |
280 | struct dvb_demux *demux = feed->demux; | 283 | struct dvb_demux *demux = feed->demux; |
281 | struct cx18_stream *stream = (struct cx18_stream *)demux->priv; | 284 | struct cx18_stream *stream = (struct cx18_stream *)demux->priv; |
282 | struct cx18 *cx = stream->cx; | 285 | struct cx18 *cx; |
283 | int ret = -EINVAL; | 286 | int ret = -EINVAL; |
284 | 287 | ||
285 | CX18_DEBUG_INFO("Stop feed: pid = 0x%x index = %d\n", | ||
286 | feed->pid, feed->index); | ||
287 | |||
288 | if (stream) { | 288 | if (stream) { |
289 | cx = stream->cx; | ||
290 | CX18_DEBUG_INFO("Stop feed: pid = 0x%x index = %d\n", | ||
291 | feed->pid, feed->index); | ||
292 | |||
289 | mutex_lock(&stream->dvb.feedlock); | 293 | mutex_lock(&stream->dvb.feedlock); |
290 | if (--stream->dvb.feeding == 0) { | 294 | if (--stream->dvb.feeding == 0) { |
291 | CX18_DEBUG_INFO("Stopping Transport DMA\n"); | 295 | CX18_DEBUG_INFO("Stopping Transport DMA\n"); |
296 | mutex_lock(&cx->serialize_lock); | ||
292 | ret = cx18_stop_v4l2_encode_stream(stream, 0); | 297 | ret = cx18_stop_v4l2_encode_stream(stream, 0); |
298 | mutex_unlock(&cx->serialize_lock); | ||
293 | } else | 299 | } else |
294 | ret = 0; | 300 | ret = 0; |
295 | mutex_unlock(&stream->dvb.feedlock); | 301 | mutex_unlock(&stream->dvb.feedlock); |
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index c0885c69fd89..863ce7758239 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c | |||
@@ -37,15 +37,21 @@ | |||
37 | 37 | ||
38 | /* This function tries to claim the stream for a specific file descriptor. | 38 | /* This function tries to claim the stream for a specific file descriptor. |
39 | If no one else is using this stream then the stream is claimed and | 39 | If no one else is using this stream then the stream is claimed and |
40 | associated VBI streams are also automatically claimed. | 40 | associated VBI and IDX streams are also automatically claimed. |
41 | Possible error returns: -EBUSY if someone else has claimed | 41 | Possible error returns: -EBUSY if someone else has claimed |
42 | the stream or 0 on success. */ | 42 | the stream or 0 on success. */ |
43 | static int cx18_claim_stream(struct cx18_open_id *id, int type) | 43 | int cx18_claim_stream(struct cx18_open_id *id, int type) |
44 | { | 44 | { |
45 | struct cx18 *cx = id->cx; | 45 | struct cx18 *cx = id->cx; |
46 | struct cx18_stream *s = &cx->streams[type]; | 46 | struct cx18_stream *s = &cx->streams[type]; |
47 | struct cx18_stream *s_vbi; | 47 | struct cx18_stream *s_assoc; |
48 | int vbi_type; | 48 | |
49 | /* Nothing should ever try to directly claim the IDX stream */ | ||
50 | if (type == CX18_ENC_STREAM_TYPE_IDX) { | ||
51 | CX18_WARN("MPEG Index stream cannot be claimed " | ||
52 | "directly, but something tried.\n"); | ||
53 | return -EINVAL; | ||
54 | } | ||
49 | 55 | ||
50 | if (test_and_set_bit(CX18_F_S_CLAIMED, &s->s_flags)) { | 56 | if (test_and_set_bit(CX18_F_S_CLAIMED, &s->s_flags)) { |
51 | /* someone already claimed this stream */ | 57 | /* someone already claimed this stream */ |
@@ -67,32 +73,47 @@ static int cx18_claim_stream(struct cx18_open_id *id, int type) | |||
67 | } | 73 | } |
68 | s->id = id->open_id; | 74 | s->id = id->open_id; |
69 | 75 | ||
70 | /* CX18_ENC_STREAM_TYPE_MPG needs to claim CX18_ENC_STREAM_TYPE_VBI | 76 | /* |
71 | (provided VBI insertion is on and sliced VBI is selected), for all | 77 | * CX18_ENC_STREAM_TYPE_MPG needs to claim: |
72 | other streams we're done */ | 78 | * CX18_ENC_STREAM_TYPE_VBI, if VBI insertion is on for sliced VBI, or |
73 | if (type == CX18_ENC_STREAM_TYPE_MPG && | 79 | * CX18_ENC_STREAM_TYPE_IDX, if VBI insertion is off for sliced VBI |
74 | cx->vbi.insert_mpeg && !cx18_raw_vbi(cx)) { | 80 | * (We don't yet fix up MPEG Index entries for our inserted packets). |
75 | vbi_type = CX18_ENC_STREAM_TYPE_VBI; | 81 | * |
76 | } else { | 82 | * For all other streams we're done. |
83 | */ | ||
84 | if (type != CX18_ENC_STREAM_TYPE_MPG) | ||
77 | return 0; | 85 | return 0; |
78 | } | ||
79 | s_vbi = &cx->streams[vbi_type]; | ||
80 | 86 | ||
81 | set_bit(CX18_F_S_CLAIMED, &s_vbi->s_flags); | 87 | s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX]; |
88 | if (cx->vbi.insert_mpeg && !cx18_raw_vbi(cx)) | ||
89 | s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; | ||
90 | else if (!cx18_stream_enabled(s_assoc)) | ||
91 | return 0; | ||
92 | |||
93 | set_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags); | ||
82 | 94 | ||
83 | /* mark that it is used internally */ | 95 | /* mark that it is used internally */ |
84 | set_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags); | 96 | set_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags); |
85 | return 0; | 97 | return 0; |
86 | } | 98 | } |
99 | EXPORT_SYMBOL(cx18_claim_stream); | ||
87 | 100 | ||
88 | /* This function releases a previously claimed stream. It will take into | 101 | /* This function releases a previously claimed stream. It will take into |
89 | account associated VBI streams. */ | 102 | account associated VBI streams. */ |
90 | static void cx18_release_stream(struct cx18_stream *s) | 103 | void cx18_release_stream(struct cx18_stream *s) |
91 | { | 104 | { |
92 | struct cx18 *cx = s->cx; | 105 | struct cx18 *cx = s->cx; |
93 | struct cx18_stream *s_vbi; | 106 | struct cx18_stream *s_assoc; |
94 | 107 | ||
95 | s->id = -1; | 108 | s->id = -1; |
109 | if (s->type == CX18_ENC_STREAM_TYPE_IDX) { | ||
110 | /* | ||
111 | * The IDX stream is only used internally, and can | ||
112 | * only be indirectly unclaimed by unclaiming the MPG stream. | ||
113 | */ | ||
114 | return; | ||
115 | } | ||
116 | |||
96 | if (s->type == CX18_ENC_STREAM_TYPE_VBI && | 117 | if (s->type == CX18_ENC_STREAM_TYPE_VBI && |
97 | test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) { | 118 | test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) { |
98 | /* this stream is still in use internally */ | 119 | /* this stream is still in use internally */ |
@@ -105,25 +126,36 @@ static void cx18_release_stream(struct cx18_stream *s) | |||
105 | 126 | ||
106 | cx18_flush_queues(s); | 127 | cx18_flush_queues(s); |
107 | 128 | ||
108 | /* CX18_ENC_STREAM_TYPE_MPG needs to release CX18_ENC_STREAM_TYPE_VBI, | 129 | /* |
109 | for all other streams we're done */ | 130 | * CX18_ENC_STREAM_TYPE_MPG needs to release the |
110 | if (s->type == CX18_ENC_STREAM_TYPE_MPG) | 131 | * CX18_ENC_STREAM_TYPE_VBI and/or CX18_ENC_STREAM_TYPE_IDX streams. |
111 | s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; | 132 | * |
112 | else | 133 | * For all other streams we're done. |
134 | */ | ||
135 | if (s->type != CX18_ENC_STREAM_TYPE_MPG) | ||
113 | return; | 136 | return; |
114 | 137 | ||
115 | /* clear internal use flag */ | 138 | /* Unclaim the associated MPEG Index stream */ |
116 | if (!test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags)) { | 139 | s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX]; |
117 | /* was already cleared */ | 140 | if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) { |
118 | return; | 141 | clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags); |
142 | cx18_flush_queues(s_assoc); | ||
119 | } | 143 | } |
120 | if (s_vbi->id != -1) { | 144 | |
121 | /* VBI stream still claimed by a file descriptor */ | 145 | /* Unclaim the associated VBI stream */ |
122 | return; | 146 | s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; |
147 | if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) { | ||
148 | if (s_assoc->id == -1) { | ||
149 | /* | ||
150 | * The VBI stream is not still claimed by a file | ||
151 | * descriptor, so completely unclaim it. | ||
152 | */ | ||
153 | clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags); | ||
154 | cx18_flush_queues(s_assoc); | ||
155 | } | ||
123 | } | 156 | } |
124 | clear_bit(CX18_F_S_CLAIMED, &s_vbi->s_flags); | ||
125 | cx18_flush_queues(s_vbi); | ||
126 | } | 157 | } |
158 | EXPORT_SYMBOL(cx18_release_stream); | ||
127 | 159 | ||
128 | static void cx18_dualwatch(struct cx18 *cx) | 160 | static void cx18_dualwatch(struct cx18 *cx) |
129 | { | 161 | { |
@@ -177,9 +209,7 @@ static struct cx18_mdl *cx18_get_mdl(struct cx18_stream *s, int non_block, | |||
177 | *err = 0; | 209 | *err = 0; |
178 | while (1) { | 210 | while (1) { |
179 | if (s->type == CX18_ENC_STREAM_TYPE_MPG) { | 211 | if (s->type == CX18_ENC_STREAM_TYPE_MPG) { |
180 | /* Process pending program info updates and pending | 212 | /* Process pending program updates and VBI data */ |
181 | VBI data */ | ||
182 | |||
183 | if (time_after(jiffies, cx->dualwatch_jiffies + msecs_to_jiffies(1000))) { | 213 | if (time_after(jiffies, cx->dualwatch_jiffies + msecs_to_jiffies(1000))) { |
184 | cx->dualwatch_jiffies = jiffies; | 214 | cx->dualwatch_jiffies = jiffies; |
185 | cx18_dualwatch(cx); | 215 | cx18_dualwatch(cx); |
@@ -362,18 +392,6 @@ static size_t cx18_copy_buf_to_user(struct cx18_stream *s, | |||
362 | return len; | 392 | return len; |
363 | } | 393 | } |
364 | 394 | ||
365 | /** | ||
366 | * list_entry_is_past_end - check if a previous loop cursor is off list end | ||
367 | * @pos: the type * previously used as a loop cursor. | ||
368 | * @head: the head for your list. | ||
369 | * @member: the name of the list_struct within the struct. | ||
370 | * | ||
371 | * Check if the entry's list_head is the head of the list, thus it's not a | ||
372 | * real entry but was the loop cursor that walked past the end | ||
373 | */ | ||
374 | #define list_entry_is_past_end(pos, head, member) \ | ||
375 | (&pos->member == (head)) | ||
376 | |||
377 | static size_t cx18_copy_mdl_to_user(struct cx18_stream *s, | 395 | static size_t cx18_copy_mdl_to_user(struct cx18_stream *s, |
378 | struct cx18_mdl *mdl, char __user *ubuf, size_t ucount) | 396 | struct cx18_mdl *mdl, char __user *ubuf, size_t ucount) |
379 | { | 397 | { |
@@ -498,6 +516,7 @@ int cx18_start_capture(struct cx18_open_id *id) | |||
498 | struct cx18 *cx = id->cx; | 516 | struct cx18 *cx = id->cx; |
499 | struct cx18_stream *s = &cx->streams[id->type]; | 517 | struct cx18_stream *s = &cx->streams[id->type]; |
500 | struct cx18_stream *s_vbi; | 518 | struct cx18_stream *s_vbi; |
519 | struct cx18_stream *s_idx; | ||
501 | 520 | ||
502 | if (s->type == CX18_ENC_STREAM_TYPE_RAD) { | 521 | if (s->type == CX18_ENC_STREAM_TYPE_RAD) { |
503 | /* you cannot read from these stream types. */ | 522 | /* you cannot read from these stream types. */ |
@@ -516,25 +535,33 @@ int cx18_start_capture(struct cx18_open_id *id) | |||
516 | return 0; | 535 | return 0; |
517 | } | 536 | } |
518 | 537 | ||
519 | /* Start VBI capture if required */ | 538 | /* Start associated VBI or IDX stream capture if required */ |
520 | s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; | 539 | s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; |
521 | if (s->type == CX18_ENC_STREAM_TYPE_MPG && | 540 | s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX]; |
522 | test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) && | 541 | if (s->type == CX18_ENC_STREAM_TYPE_MPG) { |
523 | !test_and_set_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) { | 542 | /* |
524 | /* Note: the CX18_ENC_STREAM_TYPE_VBI is claimed | 543 | * The VBI and IDX streams should have been claimed |
525 | automatically when the MPG stream is claimed. | 544 | * automatically, if for internal use, when the MPG stream was |
526 | We only need to start the VBI capturing. */ | 545 | * claimed. We only need to start these streams capturing. |
527 | if (cx18_start_v4l2_encode_stream(s_vbi)) { | 546 | */ |
528 | CX18_DEBUG_WARN("VBI capture start failed\n"); | 547 | if (test_bit(CX18_F_S_INTERNAL_USE, &s_idx->s_flags) && |
529 | 548 | !test_and_set_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) { | |
530 | /* Failure, clean up and return an error */ | 549 | if (cx18_start_v4l2_encode_stream(s_idx)) { |
531 | clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags); | 550 | CX18_DEBUG_WARN("IDX capture start failed\n"); |
532 | clear_bit(CX18_F_S_STREAMING, &s->s_flags); | 551 | clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags); |
533 | /* also releases the associated VBI stream */ | 552 | goto start_failed; |
534 | cx18_release_stream(s); | 553 | } |
535 | return -EIO; | 554 | CX18_DEBUG_INFO("IDX capture started\n"); |
555 | } | ||
556 | if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) && | ||
557 | !test_and_set_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) { | ||
558 | if (cx18_start_v4l2_encode_stream(s_vbi)) { | ||
559 | CX18_DEBUG_WARN("VBI capture start failed\n"); | ||
560 | clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags); | ||
561 | goto start_failed; | ||
562 | } | ||
563 | CX18_DEBUG_INFO("VBI insertion started\n"); | ||
536 | } | 564 | } |
537 | CX18_DEBUG_INFO("VBI insertion started\n"); | ||
538 | } | 565 | } |
539 | 566 | ||
540 | /* Tell the card to start capturing */ | 567 | /* Tell the card to start capturing */ |
@@ -547,19 +574,29 @@ int cx18_start_capture(struct cx18_open_id *id) | |||
547 | return 0; | 574 | return 0; |
548 | } | 575 | } |
549 | 576 | ||
550 | /* failure, clean up */ | 577 | start_failed: |
551 | CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name); | 578 | CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name); |
552 | 579 | ||
553 | /* Note: the CX18_ENC_STREAM_TYPE_VBI is released | 580 | /* |
554 | automatically when the MPG stream is released. | 581 | * The associated VBI and IDX streams for internal use are released |
555 | We only need to stop the VBI capturing. */ | 582 | * automatically when the MPG stream is released. We only need to stop |
556 | if (s->type == CX18_ENC_STREAM_TYPE_MPG && | 583 | * the associated stream. |
557 | test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) { | 584 | */ |
558 | cx18_stop_v4l2_encode_stream(s_vbi, 0); | 585 | if (s->type == CX18_ENC_STREAM_TYPE_MPG) { |
559 | clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags); | 586 | /* Stop the IDX stream which is always for internal use */ |
587 | if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) { | ||
588 | cx18_stop_v4l2_encode_stream(s_idx, 0); | ||
589 | clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags); | ||
590 | } | ||
591 | /* Stop the VBI stream, if only running for internal use */ | ||
592 | if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) && | ||
593 | !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) { | ||
594 | cx18_stop_v4l2_encode_stream(s_vbi, 0); | ||
595 | clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags); | ||
596 | } | ||
560 | } | 597 | } |
561 | clear_bit(CX18_F_S_STREAMING, &s->s_flags); | 598 | clear_bit(CX18_F_S_STREAMING, &s->s_flags); |
562 | cx18_release_stream(s); | 599 | cx18_release_stream(s); /* Also releases associated streams */ |
563 | return -EIO; | 600 | return -EIO; |
564 | } | 601 | } |
565 | 602 | ||
@@ -618,6 +655,8 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end) | |||
618 | { | 655 | { |
619 | struct cx18 *cx = id->cx; | 656 | struct cx18 *cx = id->cx; |
620 | struct cx18_stream *s = &cx->streams[id->type]; | 657 | struct cx18_stream *s = &cx->streams[id->type]; |
658 | struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; | ||
659 | struct cx18_stream *s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX]; | ||
621 | 660 | ||
622 | CX18_DEBUG_IOCTL("close() of %s\n", s->name); | 661 | CX18_DEBUG_IOCTL("close() of %s\n", s->name); |
623 | 662 | ||
@@ -625,17 +664,19 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end) | |||
625 | 664 | ||
626 | /* Stop capturing */ | 665 | /* Stop capturing */ |
627 | if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) { | 666 | if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) { |
628 | struct cx18_stream *s_vbi = | ||
629 | &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; | ||
630 | |||
631 | CX18_DEBUG_INFO("close stopping capture\n"); | 667 | CX18_DEBUG_INFO("close stopping capture\n"); |
632 | /* Special case: a running VBI capture for VBI insertion | 668 | if (id->type == CX18_ENC_STREAM_TYPE_MPG) { |
633 | in the mpeg stream. Need to stop that too. */ | 669 | /* Stop internal use associated VBI and IDX streams */ |
634 | if (id->type == CX18_ENC_STREAM_TYPE_MPG && | 670 | if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) && |
635 | test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) && | 671 | !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) { |
636 | !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) { | 672 | CX18_DEBUG_INFO("close stopping embedded VBI " |
637 | CX18_DEBUG_INFO("close stopping embedded VBI capture\n"); | 673 | "capture\n"); |
638 | cx18_stop_v4l2_encode_stream(s_vbi, 0); | 674 | cx18_stop_v4l2_encode_stream(s_vbi, 0); |
675 | } | ||
676 | if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) { | ||
677 | CX18_DEBUG_INFO("close stopping IDX capture\n"); | ||
678 | cx18_stop_v4l2_encode_stream(s_idx, 0); | ||
679 | } | ||
639 | } | 680 | } |
640 | if (id->type == CX18_ENC_STREAM_TYPE_VBI && | 681 | if (id->type == CX18_ENC_STREAM_TYPE_VBI && |
641 | test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) | 682 | test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) |
diff --git a/drivers/media/video/cx18/cx18-fileops.h b/drivers/media/video/cx18/cx18-fileops.h index 92e2d5dab936..5c8fcb884f0a 100644 --- a/drivers/media/video/cx18/cx18-fileops.h +++ b/drivers/media/video/cx18/cx18-fileops.h | |||
@@ -34,3 +34,6 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end); | |||
34 | void cx18_mute(struct cx18 *cx); | 34 | void cx18_mute(struct cx18 *cx); |
35 | void cx18_unmute(struct cx18 *cx); | 35 | void cx18_unmute(struct cx18 *cx); |
36 | 36 | ||
37 | /* Shared with cx18-alsa module */ | ||
38 | int cx18_claim_stream(struct cx18_open_id *id, int type); | ||
39 | void cx18_release_stream(struct cx18_stream *s); | ||
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 3e4fc192fdec..b81dd0ea8eb9 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c | |||
@@ -775,10 +775,143 @@ static int cx18_g_sliced_vbi_cap(struct file *file, void *fh, | |||
775 | return 0; | 775 | return 0; |
776 | } | 776 | } |
777 | 777 | ||
778 | static int _cx18_process_idx_data(struct cx18_buffer *buf, | ||
779 | struct v4l2_enc_idx *idx) | ||
780 | { | ||
781 | int consumed, remaining; | ||
782 | struct v4l2_enc_idx_entry *e_idx; | ||
783 | struct cx18_enc_idx_entry *e_buf; | ||
784 | |||
785 | /* Frame type lookup: 1=I, 2=P, 4=B */ | ||
786 | const int mapping[8] = { | ||
787 | -1, V4L2_ENC_IDX_FRAME_I, V4L2_ENC_IDX_FRAME_P, | ||
788 | -1, V4L2_ENC_IDX_FRAME_B, -1, -1, -1 | ||
789 | }; | ||
790 | |||
791 | /* | ||
792 | * Assumption here is that a buf holds an integral number of | ||
793 | * struct cx18_enc_idx_entry objects and is properly aligned. | ||
794 | * This is enforced by the module options on IDX buffer sizes. | ||
795 | */ | ||
796 | remaining = buf->bytesused - buf->readpos; | ||
797 | consumed = 0; | ||
798 | e_idx = &idx->entry[idx->entries]; | ||
799 | e_buf = (struct cx18_enc_idx_entry *) &buf->buf[buf->readpos]; | ||
800 | |||
801 | while (remaining >= sizeof(struct cx18_enc_idx_entry) && | ||
802 | idx->entries < V4L2_ENC_IDX_ENTRIES) { | ||
803 | |||
804 | e_idx->offset = (((u64) le32_to_cpu(e_buf->offset_high)) << 32) | ||
805 | | le32_to_cpu(e_buf->offset_low); | ||
806 | |||
807 | e_idx->pts = (((u64) (le32_to_cpu(e_buf->pts_high) & 1)) << 32) | ||
808 | | le32_to_cpu(e_buf->pts_low); | ||
809 | |||
810 | e_idx->length = le32_to_cpu(e_buf->length); | ||
811 | |||
812 | e_idx->flags = mapping[le32_to_cpu(e_buf->flags) & 0x7]; | ||
813 | |||
814 | e_idx->reserved[0] = 0; | ||
815 | e_idx->reserved[1] = 0; | ||
816 | |||
817 | idx->entries++; | ||
818 | e_idx = &idx->entry[idx->entries]; | ||
819 | e_buf++; | ||
820 | |||
821 | remaining -= sizeof(struct cx18_enc_idx_entry); | ||
822 | consumed += sizeof(struct cx18_enc_idx_entry); | ||
823 | } | ||
824 | |||
825 | /* Swallow any partial entries at the end, if there are any */ | ||
826 | if (remaining > 0 && remaining < sizeof(struct cx18_enc_idx_entry)) | ||
827 | consumed += remaining; | ||
828 | |||
829 | buf->readpos += consumed; | ||
830 | return consumed; | ||
831 | } | ||
832 | |||
833 | static int cx18_process_idx_data(struct cx18_stream *s, struct cx18_mdl *mdl, | ||
834 | struct v4l2_enc_idx *idx) | ||
835 | { | ||
836 | if (s->type != CX18_ENC_STREAM_TYPE_IDX) | ||
837 | return -EINVAL; | ||
838 | |||
839 | if (mdl->curr_buf == NULL) | ||
840 | mdl->curr_buf = list_first_entry(&mdl->buf_list, | ||
841 | struct cx18_buffer, list); | ||
842 | |||
843 | if (list_entry_is_past_end(mdl->curr_buf, &mdl->buf_list, list)) { | ||
844 | /* | ||
845 | * For some reason we've exhausted the buffers, but the MDL | ||
846 | * object still said some data was unread. | ||
847 | * Fix that and bail out. | ||
848 | */ | ||
849 | mdl->readpos = mdl->bytesused; | ||
850 | return 0; | ||
851 | } | ||
852 | |||
853 | list_for_each_entry_from(mdl->curr_buf, &mdl->buf_list, list) { | ||
854 | |||
855 | /* Skip any empty buffers in the MDL */ | ||
856 | if (mdl->curr_buf->readpos >= mdl->curr_buf->bytesused) | ||
857 | continue; | ||
858 | |||
859 | mdl->readpos += _cx18_process_idx_data(mdl->curr_buf, idx); | ||
860 | |||
861 | /* exit when MDL drained or request satisfied */ | ||
862 | if (idx->entries >= V4L2_ENC_IDX_ENTRIES || | ||
863 | mdl->curr_buf->readpos < mdl->curr_buf->bytesused || | ||
864 | mdl->readpos >= mdl->bytesused) | ||
865 | break; | ||
866 | } | ||
867 | return 0; | ||
868 | } | ||
869 | |||
778 | static int cx18_g_enc_index(struct file *file, void *fh, | 870 | static int cx18_g_enc_index(struct file *file, void *fh, |
779 | struct v4l2_enc_idx *idx) | 871 | struct v4l2_enc_idx *idx) |
780 | { | 872 | { |
781 | return -EINVAL; | 873 | struct cx18 *cx = ((struct cx18_open_id *)fh)->cx; |
874 | struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_IDX]; | ||
875 | s32 tmp; | ||
876 | struct cx18_mdl *mdl; | ||
877 | |||
878 | if (!cx18_stream_enabled(s)) /* Module options inhibited IDX stream */ | ||
879 | return -EINVAL; | ||
880 | |||
881 | /* Compute the best case number of entries we can buffer */ | ||
882 | tmp = s->buffers - | ||
883 | s->bufs_per_mdl * CX18_ENC_STREAM_TYPE_IDX_FW_MDL_MIN; | ||
884 | if (tmp <= 0) | ||
885 | tmp = 1; | ||
886 | tmp = tmp * s->buf_size / sizeof(struct cx18_enc_idx_entry); | ||
887 | |||
888 | /* Fill out the header of the return structure */ | ||
889 | idx->entries = 0; | ||
890 | idx->entries_cap = tmp; | ||
891 | memset(idx->reserved, 0, sizeof(idx->reserved)); | ||
892 | |||
893 | /* Pull IDX MDLs and buffers from q_full and populate the entries */ | ||
894 | do { | ||
895 | mdl = cx18_dequeue(s, &s->q_full); | ||
896 | if (mdl == NULL) /* No more IDX data right now */ | ||
897 | break; | ||
898 | |||
899 | /* Extract the Index entry data from the MDL and buffers */ | ||
900 | cx18_process_idx_data(s, mdl, idx); | ||
901 | if (mdl->readpos < mdl->bytesused) { | ||
902 | /* We finished with data remaining, push the MDL back */ | ||
903 | cx18_push(s, mdl, &s->q_full); | ||
904 | break; | ||
905 | } | ||
906 | |||
907 | /* We drained this MDL, schedule it to go to the firmware */ | ||
908 | cx18_enqueue(s, mdl, &s->q_free); | ||
909 | |||
910 | } while (idx->entries < V4L2_ENC_IDX_ENTRIES); | ||
911 | |||
912 | /* Tell the work handler to send free IDX MDLs to the firmware */ | ||
913 | cx18_stream_load_fw_queue(s); | ||
914 | return 0; | ||
782 | } | 915 | } |
783 | 916 | ||
784 | static int cx18_encoder_cmd(struct file *file, void *fh, | 917 | static int cx18_encoder_cmd(struct file *file, void *fh, |
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index f231dd09c720..6dcce297752f 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "cx18-mailbox.h" | 29 | #include "cx18-mailbox.h" |
30 | #include "cx18-queue.h" | 30 | #include "cx18-queue.h" |
31 | #include "cx18-streams.h" | 31 | #include "cx18-streams.h" |
32 | #include "cx18-alsa-pcm.h" /* FIXME make configurable */ | ||
32 | 33 | ||
33 | static const char *rpu_str[] = { "APU", "CPU", "EPU", "HPU" }; | 34 | static const char *rpu_str[] = { "APU", "CPU", "EPU", "HPU" }; |
34 | 35 | ||
@@ -157,6 +158,34 @@ static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl) | |||
157 | } | 158 | } |
158 | } | 159 | } |
159 | 160 | ||
161 | |||
162 | static void cx18_mdl_send_to_alsa(struct cx18 *cx, struct cx18_stream *s, | ||
163 | struct cx18_mdl *mdl) | ||
164 | { | ||
165 | struct cx18_buffer *buf; | ||
166 | |||
167 | if (mdl->bytesused == 0) | ||
168 | return; | ||
169 | |||
170 | /* We ignore mdl and buf readpos accounting here - it doesn't matter */ | ||
171 | |||
172 | /* The likely case */ | ||
173 | if (list_is_singular(&mdl->buf_list)) { | ||
174 | buf = list_first_entry(&mdl->buf_list, struct cx18_buffer, | ||
175 | list); | ||
176 | if (buf->bytesused) | ||
177 | cx->pcm_announce_callback(cx->alsa, buf->buf, | ||
178 | buf->bytesused); | ||
179 | return; | ||
180 | } | ||
181 | |||
182 | list_for_each_entry(buf, &mdl->buf_list, list) { | ||
183 | if (buf->bytesused == 0) | ||
184 | break; | ||
185 | cx->pcm_announce_callback(cx->alsa, buf->buf, buf->bytesused); | ||
186 | } | ||
187 | } | ||
188 | |||
160 | static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order) | 189 | static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order) |
161 | { | 190 | { |
162 | u32 handle, mdl_ack_count, id; | 191 | u32 handle, mdl_ack_count, id; |
@@ -223,11 +252,21 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order) | |||
223 | CX18_DEBUG_HI_DMA("%s recv bytesused = %d\n", | 252 | CX18_DEBUG_HI_DMA("%s recv bytesused = %d\n", |
224 | s->name, mdl->bytesused); | 253 | s->name, mdl->bytesused); |
225 | 254 | ||
226 | if (s->type != CX18_ENC_STREAM_TYPE_TS) | 255 | if (s->type == CX18_ENC_STREAM_TYPE_TS) { |
227 | cx18_enqueue(s, mdl, &s->q_full); | ||
228 | else { | ||
229 | cx18_mdl_send_to_dvb(s, mdl); | 256 | cx18_mdl_send_to_dvb(s, mdl); |
230 | cx18_enqueue(s, mdl, &s->q_free); | 257 | cx18_enqueue(s, mdl, &s->q_free); |
258 | } else if (s->type == CX18_ENC_STREAM_TYPE_PCM) { | ||
259 | /* Pass the data to cx18-alsa */ | ||
260 | if (cx->pcm_announce_callback != NULL) { | ||
261 | cx18_mdl_send_to_alsa(cx, s, mdl); | ||
262 | cx18_enqueue(s, mdl, &s->q_free); | ||
263 | } else { | ||
264 | cx18_enqueue(s, mdl, &s->q_full); | ||
265 | } | ||
266 | } else { | ||
267 | cx18_enqueue(s, mdl, &s->q_full); | ||
268 | if (s->type == CX18_ENC_STREAM_TYPE_IDX) | ||
269 | cx18_stream_rotate_idx_mdls(cx); | ||
231 | } | 270 | } |
232 | } | 271 | } |
233 | /* Put as many MDLs as possible back into fw use */ | 272 | /* Put as many MDLs as possible back into fw use */ |
diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index 63304823cef5..aefc8c8cf3c1 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c | |||
@@ -419,6 +419,9 @@ void cx18_stream_free(struct cx18_stream *s) | |||
419 | { | 419 | { |
420 | struct cx18_mdl *mdl; | 420 | struct cx18_mdl *mdl; |
421 | struct cx18_buffer *buf; | 421 | struct cx18_buffer *buf; |
422 | struct cx18 *cx = s->cx; | ||
423 | |||
424 | CX18_DEBUG_INFO("Deallocating buffers for %s stream\n", s->name); | ||
422 | 425 | ||
423 | /* move all buffers to buf_pool and all MDLs to q_idle */ | 426 | /* move all buffers to buf_pool and all MDLs to q_idle */ |
424 | cx18_unload_queues(s); | 427 | cx18_unload_queues(s); |
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 987a9308d938..054450f65a60 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c | |||
@@ -319,11 +319,27 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister) | |||
319 | 319 | ||
320 | /* Teardown all streams */ | 320 | /* Teardown all streams */ |
321 | for (type = 0; type < CX18_MAX_STREAMS; type++) { | 321 | for (type = 0; type < CX18_MAX_STREAMS; type++) { |
322 | if (cx->streams[type].dvb.enabled) { | 322 | |
323 | cx18_dvb_unregister(&cx->streams[type]); | 323 | /* No struct video_device, but can have buffers allocated */ |
324 | cx->streams[type].dvb.enabled = false; | 324 | if (type == CX18_ENC_STREAM_TYPE_TS) { |
325 | if (cx->streams[type].dvb.enabled) { | ||
326 | cx18_dvb_unregister(&cx->streams[type]); | ||
327 | cx->streams[type].dvb.enabled = false; | ||
328 | cx18_stream_free(&cx->streams[type]); | ||
329 | } | ||
330 | continue; | ||
331 | } | ||
332 | |||
333 | /* No struct video_device, but can have buffers allocated */ | ||
334 | if (type == CX18_ENC_STREAM_TYPE_IDX) { | ||
335 | if (cx->stream_buffers[type] != 0) { | ||
336 | cx->stream_buffers[type] = 0; | ||
337 | cx18_stream_free(&cx->streams[type]); | ||
338 | } | ||
339 | continue; | ||
325 | } | 340 | } |
326 | 341 | ||
342 | /* If struct video_device exists, can have buffers allocated */ | ||
327 | vdev = cx->streams[type].video_dev; | 343 | vdev = cx->streams[type].video_dev; |
328 | 344 | ||
329 | cx->streams[type].video_dev = NULL; | 345 | cx->streams[type].video_dev = NULL; |
@@ -447,6 +463,32 @@ static void cx18_vbi_setup(struct cx18_stream *s) | |||
447 | cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data); | 463 | cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data); |
448 | } | 464 | } |
449 | 465 | ||
466 | void cx18_stream_rotate_idx_mdls(struct cx18 *cx) | ||
467 | { | ||
468 | struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_IDX]; | ||
469 | struct cx18_mdl *mdl; | ||
470 | |||
471 | if (!cx18_stream_enabled(s)) | ||
472 | return; | ||
473 | |||
474 | /* Return if the firmware is not running low on MDLs */ | ||
475 | if ((atomic_read(&s->q_free.depth) + atomic_read(&s->q_busy.depth)) >= | ||
476 | CX18_ENC_STREAM_TYPE_IDX_FW_MDL_MIN) | ||
477 | return; | ||
478 | |||
479 | /* Return if there are no MDLs to rotate back to the firmware */ | ||
480 | if (atomic_read(&s->q_full.depth) < 2) | ||
481 | return; | ||
482 | |||
483 | /* | ||
484 | * Take the oldest IDX MDL still holding data, and discard its index | ||
485 | * entries by scheduling the MDL to go back to the firmware | ||
486 | */ | ||
487 | mdl = cx18_dequeue(s, &s->q_full); | ||
488 | if (mdl != NULL) | ||
489 | cx18_enqueue(s, mdl, &s->q_free); | ||
490 | } | ||
491 | |||
450 | static | 492 | static |
451 | struct cx18_queue *_cx18_stream_put_mdl_fw(struct cx18_stream *s, | 493 | struct cx18_queue *_cx18_stream_put_mdl_fw(struct cx18_stream *s, |
452 | struct cx18_mdl *mdl) | 494 | struct cx18_mdl *mdl) |
@@ -546,8 +588,9 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
546 | struct cx18 *cx = s->cx; | 588 | struct cx18 *cx = s->cx; |
547 | int captype = 0; | 589 | int captype = 0; |
548 | struct cx18_api_func_private priv; | 590 | struct cx18_api_func_private priv; |
591 | struct cx18_stream *s_idx; | ||
549 | 592 | ||
550 | if (s->video_dev == NULL && s->dvb.enabled == 0) | 593 | if (!cx18_stream_enabled(s)) |
551 | return -EINVAL; | 594 | return -EINVAL; |
552 | 595 | ||
553 | CX18_DEBUG_INFO("Start encoder stream %s\n", s->name); | 596 | CX18_DEBUG_INFO("Start encoder stream %s\n", s->name); |
@@ -561,6 +604,9 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
561 | cx->search_pack_header = 0; | 604 | cx->search_pack_header = 0; |
562 | break; | 605 | break; |
563 | 606 | ||
607 | case CX18_ENC_STREAM_TYPE_IDX: | ||
608 | captype = CAPTURE_CHANNEL_TYPE_INDEX; | ||
609 | break; | ||
564 | case CX18_ENC_STREAM_TYPE_TS: | 610 | case CX18_ENC_STREAM_TYPE_TS: |
565 | captype = CAPTURE_CHANNEL_TYPE_TS; | 611 | captype = CAPTURE_CHANNEL_TYPE_TS; |
566 | break; | 612 | break; |
@@ -635,11 +681,13 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
635 | cx18_vbi_setup(s); | 681 | cx18_vbi_setup(s); |
636 | 682 | ||
637 | /* | 683 | /* |
638 | * assign program index info. | 684 | * Select to receive I, P, and B frame index entries, if the |
639 | * Mask 7: select I/P/B, Num_req: 400 max | 685 | * index stream is enabled. Otherwise disable index entry |
640 | * FIXME - currently we have this hardcoded as disabled | 686 | * generation. |
641 | */ | 687 | */ |
642 | cx18_vapi_result(cx, data, CX18_CPU_SET_INDEXTABLE, 1, 0); | 688 | s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX]; |
689 | cx18_vapi_result(cx, data, CX18_CPU_SET_INDEXTABLE, 2, | ||
690 | s->handle, cx18_stream_enabled(s_idx) ? 7 : 0); | ||
643 | 691 | ||
644 | /* Call out to the common CX2341x API setup for user controls */ | 692 | /* Call out to the common CX2341x API setup for user controls */ |
645 | priv.cx = cx; | 693 | priv.cx = cx; |
@@ -697,6 +745,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
697 | atomic_inc(&cx->tot_capturing); | 745 | atomic_inc(&cx->tot_capturing); |
698 | return 0; | 746 | return 0; |
699 | } | 747 | } |
748 | EXPORT_SYMBOL(cx18_start_v4l2_encode_stream); | ||
700 | 749 | ||
701 | void cx18_stop_all_captures(struct cx18 *cx) | 750 | void cx18_stop_all_captures(struct cx18 *cx) |
702 | { | 751 | { |
@@ -705,7 +754,7 @@ void cx18_stop_all_captures(struct cx18 *cx) | |||
705 | for (i = CX18_MAX_STREAMS - 1; i >= 0; i--) { | 754 | for (i = CX18_MAX_STREAMS - 1; i >= 0; i--) { |
706 | struct cx18_stream *s = &cx->streams[i]; | 755 | struct cx18_stream *s = &cx->streams[i]; |
707 | 756 | ||
708 | if (s->video_dev == NULL && s->dvb.enabled == 0) | 757 | if (!cx18_stream_enabled(s)) |
709 | continue; | 758 | continue; |
710 | if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) | 759 | if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) |
711 | cx18_stop_v4l2_encode_stream(s, 0); | 760 | cx18_stop_v4l2_encode_stream(s, 0); |
@@ -717,7 +766,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) | |||
717 | struct cx18 *cx = s->cx; | 766 | struct cx18 *cx = s->cx; |
718 | unsigned long then; | 767 | unsigned long then; |
719 | 768 | ||
720 | if (s->video_dev == NULL && s->dvb.enabled == 0) | 769 | if (!cx18_stream_enabled(s)) |
721 | return -EINVAL; | 770 | return -EINVAL; |
722 | 771 | ||
723 | /* This function assumes that you are allowed to stop the capture | 772 | /* This function assumes that you are allowed to stop the capture |
@@ -762,6 +811,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) | |||
762 | 811 | ||
763 | return 0; | 812 | return 0; |
764 | } | 813 | } |
814 | EXPORT_SYMBOL(cx18_stop_v4l2_encode_stream); | ||
765 | 815 | ||
766 | u32 cx18_find_handle(struct cx18 *cx) | 816 | u32 cx18_find_handle(struct cx18 *cx) |
767 | { | 817 | { |
@@ -789,7 +839,7 @@ struct cx18_stream *cx18_handle_to_stream(struct cx18 *cx, u32 handle) | |||
789 | s = &cx->streams[i]; | 839 | s = &cx->streams[i]; |
790 | if (s->handle != handle) | 840 | if (s->handle != handle) |
791 | continue; | 841 | continue; |
792 | if (s->video_dev || s->dvb.enabled) | 842 | if (cx18_stream_enabled(s)) |
793 | return s; | 843 | return s; |
794 | } | 844 | } |
795 | return NULL; | 845 | return NULL; |
diff --git a/drivers/media/video/cx18/cx18-streams.h b/drivers/media/video/cx18/cx18-streams.h index 4a01db5e5a35..0bff0fa29763 100644 --- a/drivers/media/video/cx18/cx18-streams.h +++ b/drivers/media/video/cx18/cx18-streams.h | |||
@@ -28,6 +28,16 @@ int cx18_streams_setup(struct cx18 *cx); | |||
28 | int cx18_streams_register(struct cx18 *cx); | 28 | int cx18_streams_register(struct cx18 *cx); |
29 | void cx18_streams_cleanup(struct cx18 *cx, int unregister); | 29 | void cx18_streams_cleanup(struct cx18 *cx, int unregister); |
30 | 30 | ||
31 | #define CX18_ENC_STREAM_TYPE_IDX_FW_MDL_MIN (3) | ||
32 | void cx18_stream_rotate_idx_mdls(struct cx18 *cx); | ||
33 | |||
34 | static inline bool cx18_stream_enabled(struct cx18_stream *s) | ||
35 | { | ||
36 | return s->video_dev || s->dvb.enabled || | ||
37 | (s->type == CX18_ENC_STREAM_TYPE_IDX && | ||
38 | s->cx->stream_buffers[CX18_ENC_STREAM_TYPE_IDX] != 0); | ||
39 | } | ||
40 | |||
31 | /* Related to submission of mdls to firmware */ | 41 | /* Related to submission of mdls to firmware */ |
32 | static inline void cx18_stream_load_fw_queue(struct cx18_stream *s) | 42 | static inline void cx18_stream_load_fw_queue(struct cx18_stream *s) |
33 | { | 43 | { |
diff --git a/drivers/media/video/cx18/cx18-version.h b/drivers/media/video/cx18/cx18-version.h index 9c0b5bb1b019..3e1aec4bcfde 100644 --- a/drivers/media/video/cx18/cx18-version.h +++ b/drivers/media/video/cx18/cx18-version.h | |||
@@ -24,7 +24,7 @@ | |||
24 | 24 | ||
25 | #define CX18_DRIVER_NAME "cx18" | 25 | #define CX18_DRIVER_NAME "cx18" |
26 | #define CX18_DRIVER_VERSION_MAJOR 1 | 26 | #define CX18_DRIVER_VERSION_MAJOR 1 |
27 | #define CX18_DRIVER_VERSION_MINOR 3 | 27 | #define CX18_DRIVER_VERSION_MINOR 4 |
28 | #define CX18_DRIVER_VERSION_PATCHLEVEL 0 | 28 | #define CX18_DRIVER_VERSION_PATCHLEVEL 0 |
29 | 29 | ||
30 | #define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL) | 30 | #define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL) |
diff --git a/drivers/media/video/cx18/cx23418.h b/drivers/media/video/cx18/cx23418.h index 868806effdcf..2c00980acfcb 100644 --- a/drivers/media/video/cx18/cx23418.h +++ b/drivers/media/video/cx18/cx23418.h | |||
@@ -191,7 +191,8 @@ | |||
191 | #define CX18_CPU_SET_MEDIAN_CORING (CPU_CMD_MASK_CAPTURE | 0x000E) | 191 | #define CX18_CPU_SET_MEDIAN_CORING (CPU_CMD_MASK_CAPTURE | 0x000E) |
192 | 192 | ||
193 | /* Description: This command set the picture type mask for index file | 193 | /* Description: This command set the picture type mask for index file |
194 | IN[0] - 0 = disable index file output | 194 | IN[0] - Task handle (ignored by firmware) |
195 | IN[1] - 0 = disable index file output | ||
195 | 1 = output I picture | 196 | 1 = output I picture |
196 | 2 = P picture | 197 | 2 = P picture |
197 | 4 = B picture | 198 | 4 = B picture |
diff --git a/drivers/media/video/cx231xx/cx231xx-dvb.c b/drivers/media/video/cx231xx/cx231xx-dvb.c index c5082a4e8ced..64e025e2bdf1 100644 --- a/drivers/media/video/cx231xx/cx231xx-dvb.c +++ b/drivers/media/video/cx231xx/cx231xx-dvb.c | |||
@@ -464,9 +464,9 @@ static int dvb_init(struct cx231xx *dev) | |||
464 | /* define general-purpose callback pointer */ | 464 | /* define general-purpose callback pointer */ |
465 | dvb->frontend->callback = cx231xx_tuner_callback; | 465 | dvb->frontend->callback = cx231xx_tuner_callback; |
466 | 466 | ||
467 | if (dvb_attach(xc5000_attach, dev->dvb->frontend, | 467 | if (!dvb_attach(xc5000_attach, dev->dvb->frontend, |
468 | &dev->i2c_bus[1].i2c_adap, | 468 | &dev->i2c_bus[1].i2c_adap, |
469 | &cnxt_rde250_tunerconfig) < 0) { | 469 | &cnxt_rde250_tunerconfig)) { |
470 | result = -EINVAL; | 470 | result = -EINVAL; |
471 | goto out_free; | 471 | goto out_free; |
472 | } | 472 | } |
@@ -486,9 +486,9 @@ static int dvb_init(struct cx231xx *dev) | |||
486 | /* define general-purpose callback pointer */ | 486 | /* define general-purpose callback pointer */ |
487 | dvb->frontend->callback = cx231xx_tuner_callback; | 487 | dvb->frontend->callback = cx231xx_tuner_callback; |
488 | 488 | ||
489 | if (dvb_attach(xc5000_attach, dev->dvb->frontend, | 489 | if (!dvb_attach(xc5000_attach, dev->dvb->frontend, |
490 | &dev->i2c_bus[1].i2c_adap, | 490 | &dev->i2c_bus[1].i2c_adap, |
491 | &cnxt_rde250_tunerconfig) < 0) { | 491 | &cnxt_rde250_tunerconfig)) { |
492 | result = -EINVAL; | 492 | result = -EINVAL; |
493 | goto out_free; | 493 | goto out_free; |
494 | } | 494 | } |
diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c index 15826f98b688..c5771db3bfce 100644 --- a/drivers/media/video/cx231xx/cx231xx-input.c +++ b/drivers/media/video/cx231xx/cx231xx-input.c | |||
@@ -216,7 +216,7 @@ int cx231xx_ir_init(struct cx231xx *dev) | |||
216 | cx231xx_ir_start(ir); | 216 | cx231xx_ir_start(ir); |
217 | 217 | ||
218 | /* all done */ | 218 | /* all done */ |
219 | err = ir_input_register(ir->input, dev->board.ir_codes); | 219 | err = ir_input_register(ir->input, dev->board.ir_codes, NULL); |
220 | if (err) | 220 | if (err) |
221 | goto err_out_stop; | 221 | goto err_out_stop; |
222 | 222 | ||
diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c index 88c0d2481118..2ab97ad7b6fb 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c | |||
@@ -681,7 +681,7 @@ static char *cmd_to_str(int cmd) | |||
681 | case CX2341X_ENC_SET_VIDEO_ID: | 681 | case CX2341X_ENC_SET_VIDEO_ID: |
682 | return "SET_VIDEO_ID"; | 682 | return "SET_VIDEO_ID"; |
683 | case CX2341X_ENC_SET_PCR_ID: | 683 | case CX2341X_ENC_SET_PCR_ID: |
684 | return "SET_PCR_PID"; | 684 | return "SET_PCR_ID"; |
685 | case CX2341X_ENC_SET_FRAME_RATE: | 685 | case CX2341X_ENC_SET_FRAME_RATE: |
686 | return "SET_FRAME_RATE"; | 686 | return "SET_FRAME_RATE"; |
687 | case CX2341X_ENC_SET_FRAME_SIZE: | 687 | case CX2341X_ENC_SET_FRAME_SIZE: |
@@ -693,7 +693,7 @@ static char *cmd_to_str(int cmd) | |||
693 | case CX2341X_ENC_SET_ASPECT_RATIO: | 693 | case CX2341X_ENC_SET_ASPECT_RATIO: |
694 | return "SET_ASPECT_RATIO"; | 694 | return "SET_ASPECT_RATIO"; |
695 | case CX2341X_ENC_SET_DNR_FILTER_MODE: | 695 | case CX2341X_ENC_SET_DNR_FILTER_MODE: |
696 | return "SET_DNR_FILTER_PROPS"; | 696 | return "SET_DNR_FILTER_MODE"; |
697 | case CX2341X_ENC_SET_DNR_FILTER_PROPS: | 697 | case CX2341X_ENC_SET_DNR_FILTER_PROPS: |
698 | return "SET_DNR_FILTER_PROPS"; | 698 | return "SET_DNR_FILTER_PROPS"; |
699 | case CX2341X_ENC_SET_CORING_LEVELS: | 699 | case CX2341X_ENC_SET_CORING_LEVELS: |
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 1ec48169277d..d639186f645d 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c | |||
@@ -274,6 +274,31 @@ struct cx23885_board cx23885_boards[] = { | |||
274 | .portb = CX23885_MPEG_DVB, | 274 | .portb = CX23885_MPEG_DVB, |
275 | .portc = CX23885_MPEG_DVB, | 275 | .portc = CX23885_MPEG_DVB, |
276 | }, | 276 | }, |
277 | [CX23885_BOARD_LEADTEK_WINFAST_PXTV1200] = { | ||
278 | .name = "LEADTEK WinFast PxTV1200", | ||
279 | .porta = CX23885_ANALOG_VIDEO, | ||
280 | .tuner_type = TUNER_XC2028, | ||
281 | .tuner_addr = 0x61, | ||
282 | .input = {{ | ||
283 | .type = CX23885_VMUX_TELEVISION, | ||
284 | .vmux = CX25840_VIN2_CH1 | | ||
285 | CX25840_VIN5_CH2 | | ||
286 | CX25840_NONE0_CH3, | ||
287 | }, { | ||
288 | .type = CX23885_VMUX_COMPOSITE1, | ||
289 | .vmux = CX25840_COMPOSITE1, | ||
290 | }, { | ||
291 | .type = CX23885_VMUX_SVIDEO, | ||
292 | .vmux = CX25840_SVIDEO_LUMA3 | | ||
293 | CX25840_SVIDEO_CHROMA4, | ||
294 | }, { | ||
295 | .type = CX23885_VMUX_COMPONENT, | ||
296 | .vmux = CX25840_VIN7_CH1 | | ||
297 | CX25840_VIN6_CH2 | | ||
298 | CX25840_VIN8_CH3 | | ||
299 | CX25840_COMPONENT_ON, | ||
300 | } }, | ||
301 | }, | ||
277 | }; | 302 | }; |
278 | const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); | 303 | const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); |
279 | 304 | ||
@@ -417,6 +442,10 @@ struct cx23885_subid cx23885_subids[] = { | |||
417 | .subvendor = 0x14f1, | 442 | .subvendor = 0x14f1, |
418 | .subdevice = 0x8578, | 443 | .subdevice = 0x8578, |
419 | .card = CX23885_BOARD_MYGICA_X8558PRO, | 444 | .card = CX23885_BOARD_MYGICA_X8558PRO, |
445 | }, { | ||
446 | .subvendor = 0x107d, | ||
447 | .subdevice = 0x6f22, | ||
448 | .card = CX23885_BOARD_LEADTEK_WINFAST_PXTV1200, | ||
420 | }, | 449 | }, |
421 | }; | 450 | }; |
422 | const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); | 451 | const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); |
@@ -617,6 +646,7 @@ int cx23885_tuner_callback(void *priv, int component, int command, int arg) | |||
617 | case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: | 646 | case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: |
618 | case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: | 647 | case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: |
619 | case CX23885_BOARD_COMPRO_VIDEOMATE_E800: | 648 | case CX23885_BOARD_COMPRO_VIDEOMATE_E800: |
649 | case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200: | ||
620 | /* Tuner Reset Command */ | 650 | /* Tuner Reset Command */ |
621 | bitmask = 0x04; | 651 | bitmask = 0x04; |
622 | break; | 652 | break; |
@@ -769,6 +799,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) | |||
769 | case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: | 799 | case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: |
770 | case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: | 800 | case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: |
771 | case CX23885_BOARD_COMPRO_VIDEOMATE_E800: | 801 | case CX23885_BOARD_COMPRO_VIDEOMATE_E800: |
802 | case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200: | ||
772 | /* GPIO-2 xc3028 tuner reset */ | 803 | /* GPIO-2 xc3028 tuner reset */ |
773 | 804 | ||
774 | /* The following GPIO's are on the internal AVCore (cx25840) */ | 805 | /* The following GPIO's are on the internal AVCore (cx25840) */ |
@@ -1076,6 +1107,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) | |||
1076 | case CX23885_BOARD_MYGICA_X8506: | 1107 | case CX23885_BOARD_MYGICA_X8506: |
1077 | case CX23885_BOARD_MAGICPRO_PROHDTVE2: | 1108 | case CX23885_BOARD_MAGICPRO_PROHDTVE2: |
1078 | case CX23885_BOARD_HAUPPAUGE_HVR1290: | 1109 | case CX23885_BOARD_HAUPPAUGE_HVR1290: |
1110 | case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200: | ||
1079 | dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, | 1111 | dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, |
1080 | &dev->i2c_bus[2].i2c_adap, | 1112 | &dev->i2c_bus[2].i2c_adap, |
1081 | "cx25840", "cx25840", 0x88 >> 1, NULL); | 1113 | "cx25840", "cx25840", 0x88 >> 1, NULL); |
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index e45d2df08138..939079d7bbb9 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c | |||
@@ -542,6 +542,9 @@ static struct atbm8830_config mygica_x8558pro_atbm8830_cfg1 = { | |||
542 | .osc_clk_freq = 30400, /* in kHz */ | 542 | .osc_clk_freq = 30400, /* in kHz */ |
543 | .if_freq = 0, /* zero IF */ | 543 | .if_freq = 0, /* zero IF */ |
544 | .zif_swap_iq = 1, | 544 | .zif_swap_iq = 1, |
545 | .agc_min = 0x2E, | ||
546 | .agc_max = 0xFF, | ||
547 | .agc_hold_loop = 0, | ||
545 | }; | 548 | }; |
546 | 549 | ||
547 | static struct max2165_config mygic_x8558pro_max2165_cfg1 = { | 550 | static struct max2165_config mygic_x8558pro_max2165_cfg1 = { |
@@ -558,6 +561,9 @@ static struct atbm8830_config mygica_x8558pro_atbm8830_cfg2 = { | |||
558 | .osc_clk_freq = 30400, /* in kHz */ | 561 | .osc_clk_freq = 30400, /* in kHz */ |
559 | .if_freq = 0, /* zero IF */ | 562 | .if_freq = 0, /* zero IF */ |
560 | .zif_swap_iq = 1, | 563 | .zif_swap_iq = 1, |
564 | .agc_min = 0x2E, | ||
565 | .agc_max = 0xFF, | ||
566 | .agc_hold_loop = 0, | ||
561 | }; | 567 | }; |
562 | 568 | ||
563 | static struct max2165_config mygic_x8558pro_max2165_cfg2 = { | 569 | static struct max2165_config mygic_x8558pro_max2165_cfg2 = { |
@@ -994,15 +1000,8 @@ static int dvb_register(struct cx23885_tsport *port) | |||
994 | netup_get_card_info(&dev->i2c_bus[0].i2c_adap, &cinfo); | 1000 | netup_get_card_info(&dev->i2c_bus[0].i2c_adap, &cinfo); |
995 | memcpy(port->frontends.adapter.proposed_mac, | 1001 | memcpy(port->frontends.adapter.proposed_mac, |
996 | cinfo.port[port->nr - 1].mac, 6); | 1002 | cinfo.port[port->nr - 1].mac, 6); |
997 | printk(KERN_INFO "NetUP Dual DVB-S2 CI card port%d MAC=" | 1003 | printk(KERN_INFO "NetUP Dual DVB-S2 CI card port%d MAC=%pM\n", |
998 | "%02X:%02X:%02X:%02X:%02X:%02X\n", | 1004 | port->nr, port->frontends.adapter.proposed_mac); |
999 | port->nr, | ||
1000 | port->frontends.adapter.proposed_mac[0], | ||
1001 | port->frontends.adapter.proposed_mac[1], | ||
1002 | port->frontends.adapter.proposed_mac[2], | ||
1003 | port->frontends.adapter.proposed_mac[3], | ||
1004 | port->frontends.adapter.proposed_mac[4], | ||
1005 | port->frontends.adapter.proposed_mac[5]); | ||
1006 | 1005 | ||
1007 | netup_ci_init(port); | 1006 | netup_ci_init(port); |
1008 | break; | 1007 | break; |
diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c index 768eec92ccf9..9c6620f86dca 100644 --- a/drivers/media/video/cx23885/cx23885-input.c +++ b/drivers/media/video/cx23885/cx23885-input.c | |||
@@ -397,7 +397,7 @@ int cx23885_input_init(struct cx23885_dev *dev) | |||
397 | dev->ir_input = ir; | 397 | dev->ir_input = ir; |
398 | cx23885_input_ir_start(dev); | 398 | cx23885_input_ir_start(dev); |
399 | 399 | ||
400 | ret = ir_input_register(ir->dev, ir_codes); | 400 | ret = ir_input_register(ir->dev, ir_codes, NULL); |
401 | if (ret) | 401 | if (ret) |
402 | goto err_out_stop; | 402 | goto err_out_stop; |
403 | 403 | ||
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index 8934d61cf660..2d3ac8b83dc3 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <media/v4l2-common.h> | 36 | #include <media/v4l2-common.h> |
37 | #include <media/v4l2-ioctl.h> | 37 | #include <media/v4l2-ioctl.h> |
38 | #include "cx23885-ioctl.h" | 38 | #include "cx23885-ioctl.h" |
39 | #include "tuner-xc2028.h" | ||
39 | 40 | ||
40 | MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards"); | 41 | MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards"); |
41 | MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); | 42 | MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); |
@@ -1505,6 +1506,18 @@ int cx23885_video_register(struct cx23885_dev *dev) | |||
1505 | tun_setup.tuner_callback = cx23885_tuner_callback; | 1506 | tun_setup.tuner_callback = cx23885_tuner_callback; |
1506 | 1507 | ||
1507 | v4l2_subdev_call(sd, tuner, s_type_addr, &tun_setup); | 1508 | v4l2_subdev_call(sd, tuner, s_type_addr, &tun_setup); |
1509 | |||
1510 | if (dev->board == CX23885_BOARD_LEADTEK_WINFAST_PXTV1200) { | ||
1511 | struct xc2028_ctrl ctrl = { | ||
1512 | .fname = XC2028_DEFAULT_FIRMWARE, | ||
1513 | .max_len = 64 | ||
1514 | }; | ||
1515 | struct v4l2_priv_tun_config cfg = { | ||
1516 | .tuner = dev->tuner_type, | ||
1517 | .priv = &ctrl | ||
1518 | }; | ||
1519 | v4l2_subdev_call(sd, tuner, s_config, &cfg); | ||
1520 | } | ||
1508 | } | 1521 | } |
1509 | } | 1522 | } |
1510 | 1523 | ||
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 08b3f6b136a0..0e3a98d243c5 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h | |||
@@ -81,6 +81,7 @@ | |||
81 | #define CX23885_BOARD_COMPRO_VIDEOMATE_E800 25 | 81 | #define CX23885_BOARD_COMPRO_VIDEOMATE_E800 25 |
82 | #define CX23885_BOARD_HAUPPAUGE_HVR1290 26 | 82 | #define CX23885_BOARD_HAUPPAUGE_HVR1290 26 |
83 | #define CX23885_BOARD_MYGICA_X8558PRO 27 | 83 | #define CX23885_BOARD_MYGICA_X8558PRO 27 |
84 | #define CX23885_BOARD_LEADTEK_WINFAST_PXTV1200 28 | ||
84 | 85 | ||
85 | #define GPIO_0 0x00000001 | 86 | #define GPIO_0 0x00000001 |
86 | #define GPIO_1 0x00000002 | 87 | #define GPIO_1 0x00000002 |
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 385ecd58f1c0..f2461cd3de5a 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c | |||
@@ -734,10 +734,8 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp | |||
734 | v4l_dbg(1, cx25840_debug, client, "vid_input 0x%x\n", | 734 | v4l_dbg(1, cx25840_debug, client, "vid_input 0x%x\n", |
735 | vid_input); | 735 | vid_input); |
736 | reg = vid_input & 0xff; | 736 | reg = vid_input & 0xff; |
737 | if ((vid_input & CX25840_SVIDEO_ON) == CX25840_SVIDEO_ON) | 737 | is_composite = !is_component && |
738 | is_composite = 0; | 738 | ((vid_input & CX25840_SVIDEO_ON) != CX25840_SVIDEO_ON); |
739 | else if ((vid_input & CX25840_COMPONENT_ON) == 0) | ||
740 | is_composite = 1; | ||
741 | 739 | ||
742 | v4l_dbg(1, cx25840_debug, client, "mux cfg 0x%x comp=%d\n", | 740 | v4l_dbg(1, cx25840_debug, client, "mux cfg 0x%x comp=%d\n", |
743 | reg, is_composite); | 741 | reg, is_composite); |
@@ -1347,30 +1345,59 @@ static int cx25840_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * | |||
1347 | } | 1345 | } |
1348 | #endif | 1346 | #endif |
1349 | 1347 | ||
1348 | static int cx25840_s_audio_stream(struct v4l2_subdev *sd, int enable) | ||
1349 | { | ||
1350 | struct cx25840_state *state = to_state(sd); | ||
1351 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
1352 | u8 v; | ||
1353 | |||
1354 | if (is_cx2583x(state) || is_cx2388x(state) || is_cx231xx(state)) | ||
1355 | return 0; | ||
1356 | |||
1357 | v4l_dbg(1, cx25840_debug, client, "%s audio output\n", | ||
1358 | enable ? "enable" : "disable"); | ||
1359 | |||
1360 | if (enable) { | ||
1361 | v = cx25840_read(client, 0x115) | 0x80; | ||
1362 | cx25840_write(client, 0x115, v); | ||
1363 | v = cx25840_read(client, 0x116) | 0x03; | ||
1364 | cx25840_write(client, 0x116, v); | ||
1365 | } else { | ||
1366 | v = cx25840_read(client, 0x115) & ~(0x80); | ||
1367 | cx25840_write(client, 0x115, v); | ||
1368 | v = cx25840_read(client, 0x116) & ~(0x03); | ||
1369 | cx25840_write(client, 0x116, v); | ||
1370 | } | ||
1371 | return 0; | ||
1372 | } | ||
1373 | |||
1350 | static int cx25840_s_stream(struct v4l2_subdev *sd, int enable) | 1374 | static int cx25840_s_stream(struct v4l2_subdev *sd, int enable) |
1351 | { | 1375 | { |
1352 | struct cx25840_state *state = to_state(sd); | 1376 | struct cx25840_state *state = to_state(sd); |
1353 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 1377 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1378 | u8 v; | ||
1354 | 1379 | ||
1355 | v4l_dbg(1, cx25840_debug, client, "%s output\n", | 1380 | v4l_dbg(1, cx25840_debug, client, "%s video output\n", |
1356 | enable ? "enable" : "disable"); | 1381 | enable ? "enable" : "disable"); |
1357 | if (enable) { | 1382 | if (enable) { |
1358 | if (is_cx2388x(state) || is_cx231xx(state)) { | 1383 | if (is_cx2388x(state) || is_cx231xx(state)) { |
1359 | u8 v = (cx25840_read(client, 0x421) | 0x0b); | 1384 | v = cx25840_read(client, 0x421) | 0x0b; |
1360 | cx25840_write(client, 0x421, v); | 1385 | cx25840_write(client, 0x421, v); |
1361 | } else { | 1386 | } else { |
1362 | cx25840_write(client, 0x115, | 1387 | v = cx25840_read(client, 0x115) | 0x0c; |
1363 | is_cx2583x(state) ? 0x0c : 0x8c); | 1388 | cx25840_write(client, 0x115, v); |
1364 | cx25840_write(client, 0x116, | 1389 | v = cx25840_read(client, 0x116) | 0x04; |
1365 | is_cx2583x(state) ? 0x04 : 0x07); | 1390 | cx25840_write(client, 0x116, v); |
1366 | } | 1391 | } |
1367 | } else { | 1392 | } else { |
1368 | if (is_cx2388x(state) || is_cx231xx(state)) { | 1393 | if (is_cx2388x(state) || is_cx231xx(state)) { |
1369 | u8 v = cx25840_read(client, 0x421) & ~(0x0b); | 1394 | v = cx25840_read(client, 0x421) & ~(0x0b); |
1370 | cx25840_write(client, 0x421, v); | 1395 | cx25840_write(client, 0x421, v); |
1371 | } else { | 1396 | } else { |
1372 | cx25840_write(client, 0x115, 0x00); | 1397 | v = cx25840_read(client, 0x115) & ~(0x0c); |
1373 | cx25840_write(client, 0x116, 0x00); | 1398 | cx25840_write(client, 0x115, v); |
1399 | v = cx25840_read(client, 0x116) & ~(0x04); | ||
1400 | cx25840_write(client, 0x116, v); | ||
1374 | } | 1401 | } |
1375 | } | 1402 | } |
1376 | return 0; | 1403 | return 0; |
@@ -1601,6 +1628,7 @@ static const struct v4l2_subdev_tuner_ops cx25840_tuner_ops = { | |||
1601 | static const struct v4l2_subdev_audio_ops cx25840_audio_ops = { | 1628 | static const struct v4l2_subdev_audio_ops cx25840_audio_ops = { |
1602 | .s_clock_freq = cx25840_s_clock_freq, | 1629 | .s_clock_freq = cx25840_s_clock_freq, |
1603 | .s_routing = cx25840_s_audio_routing, | 1630 | .s_routing = cx25840_s_audio_routing, |
1631 | .s_stream = cx25840_s_audio_stream, | ||
1604 | }; | 1632 | }; |
1605 | 1633 | ||
1606 | static const struct v4l2_subdev_video_ops cx25840_video_ops = { | 1634 | static const struct v4l2_subdev_video_ops cx25840_video_ops = { |
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 5a67445dd6ed..64b350df78e3 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c | |||
@@ -583,16 +583,18 @@ static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol, | |||
583 | { | 583 | { |
584 | snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); | 584 | snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); |
585 | struct cx88_core *core=chip->core; | 585 | struct cx88_core *core=chip->core; |
586 | int v, b; | 586 | int left, right, v, b; |
587 | int changed = 0; | 587 | int changed = 0; |
588 | u32 old; | 588 | u32 old; |
589 | 589 | ||
590 | b = value->value.integer.value[1] - value->value.integer.value[0]; | 590 | left = value->value.integer.value[0] & 0x3f; |
591 | right = value->value.integer.value[1] & 0x3f; | ||
592 | b = right - left; | ||
591 | if (b < 0) { | 593 | if (b < 0) { |
592 | v = 0x3f - value->value.integer.value[0]; | 594 | v = 0x3f - left; |
593 | b = (-b) | 0x40; | 595 | b = (-b) | 0x40; |
594 | } else { | 596 | } else { |
595 | v = 0x3f - value->value.integer.value[1]; | 597 | v = 0x3f - right; |
596 | } | 598 | } |
597 | /* Do we really know this will always be called with IRQs on? */ | 599 | /* Do we really know this will always be called with IRQs on? */ |
598 | spin_lock_irq(&chip->reg_lock); | 600 | spin_lock_irq(&chip->reg_lock); |
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index d844f2aaa01d..eaf0ee7de832 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c | |||
@@ -1466,6 +1466,18 @@ static const struct cx88_board cx88_boards[] = { | |||
1466 | .audioroute = 8, | 1466 | .audioroute = 8, |
1467 | }, | 1467 | }, |
1468 | }, | 1468 | }, |
1469 | [CX88_BOARD_SAMSUNG_SMT_7020] = { | ||
1470 | .name = "Samsung SMT 7020 DVB-S", | ||
1471 | .tuner_type = TUNER_ABSENT, | ||
1472 | .radio_type = UNSET, | ||
1473 | .tuner_addr = ADDR_UNSET, | ||
1474 | .radio_addr = ADDR_UNSET, | ||
1475 | .input = { { | ||
1476 | .type = CX88_VMUX_DVB, | ||
1477 | .vmux = 0, | ||
1478 | } }, | ||
1479 | .mpeg = CX88_MPEG_DVB, | ||
1480 | }, | ||
1469 | [CX88_BOARD_ADSTECH_PTV_390] = { | 1481 | [CX88_BOARD_ADSTECH_PTV_390] = { |
1470 | .name = "ADS Tech Instant Video PCI", | 1482 | .name = "ADS Tech Instant Video PCI", |
1471 | .tuner_type = TUNER_ABSENT, | 1483 | .tuner_type = TUNER_ABSENT, |
@@ -2355,6 +2367,14 @@ static const struct cx88_subid cx88_subids[] = { | |||
2355 | .subvendor = 0x0070, | 2367 | .subvendor = 0x0070, |
2356 | .subdevice = 0x1404, | 2368 | .subdevice = 0x1404, |
2357 | .card = CX88_BOARD_HAUPPAUGE_HVR3000, | 2369 | .card = CX88_BOARD_HAUPPAUGE_HVR3000, |
2370 | }, { | ||
2371 | .subvendor = 0x18ac, | ||
2372 | .subdevice = 0xdc00, | ||
2373 | .card = CX88_BOARD_SAMSUNG_SMT_7020, | ||
2374 | }, { | ||
2375 | .subvendor = 0x18ac, | ||
2376 | .subdevice = 0xdccd, | ||
2377 | .card = CX88_BOARD_SAMSUNG_SMT_7020, | ||
2358 | },{ | 2378 | },{ |
2359 | .subvendor = 0x1461, | 2379 | .subvendor = 0x1461, |
2360 | .subdevice = 0xc111, /* AverMedia M150-D */ | 2380 | .subdevice = 0xc111, /* AverMedia M150-D */ |
@@ -2633,6 +2653,9 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) | |||
2633 | case 98559: /* WinTV-HVR1100LP (Video no IR, Retail - Low Profile) */ | 2653 | case 98559: /* WinTV-HVR1100LP (Video no IR, Retail - Low Profile) */ |
2634 | /* known */ | 2654 | /* known */ |
2635 | break; | 2655 | break; |
2656 | case CX88_BOARD_SAMSUNG_SMT_7020: | ||
2657 | cx_set(MO_GP0_IO, 0x008989FF); | ||
2658 | break; | ||
2636 | default: | 2659 | default: |
2637 | warn_printk(core, "warning: unknown hauppauge model #%d\n", | 2660 | warn_printk(core, "warning: unknown hauppauge model #%d\n", |
2638 | tv.model); | 2661 | tv.model); |
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index b14296923250..94ab862f0219 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
@@ -674,6 +674,194 @@ static int cx8802_alloc_frontends(struct cx8802_dev *dev) | |||
674 | return 0; | 674 | return 0; |
675 | } | 675 | } |
676 | 676 | ||
677 | |||
678 | |||
679 | static u8 samsung_smt_7020_inittab[] = { | ||
680 | 0x01, 0x15, | ||
681 | 0x02, 0x00, | ||
682 | 0x03, 0x00, | ||
683 | 0x04, 0x7D, | ||
684 | 0x05, 0x0F, | ||
685 | 0x06, 0x02, | ||
686 | 0x07, 0x00, | ||
687 | 0x08, 0x60, | ||
688 | |||
689 | 0x0A, 0xC2, | ||
690 | 0x0B, 0x00, | ||
691 | 0x0C, 0x01, | ||
692 | 0x0D, 0x81, | ||
693 | 0x0E, 0x44, | ||
694 | 0x0F, 0x09, | ||
695 | 0x10, 0x3C, | ||
696 | 0x11, 0x84, | ||
697 | 0x12, 0xDA, | ||
698 | 0x13, 0x99, | ||
699 | 0x14, 0x8D, | ||
700 | 0x15, 0xCE, | ||
701 | 0x16, 0xE8, | ||
702 | 0x17, 0x43, | ||
703 | 0x18, 0x1C, | ||
704 | 0x19, 0x1B, | ||
705 | 0x1A, 0x1D, | ||
706 | |||
707 | 0x1C, 0x12, | ||
708 | 0x1D, 0x00, | ||
709 | 0x1E, 0x00, | ||
710 | 0x1F, 0x00, | ||
711 | 0x20, 0x00, | ||
712 | 0x21, 0x00, | ||
713 | 0x22, 0x00, | ||
714 | 0x23, 0x00, | ||
715 | |||
716 | 0x28, 0x02, | ||
717 | 0x29, 0x28, | ||
718 | 0x2A, 0x14, | ||
719 | 0x2B, 0x0F, | ||
720 | 0x2C, 0x09, | ||
721 | 0x2D, 0x05, | ||
722 | |||
723 | 0x31, 0x1F, | ||
724 | 0x32, 0x19, | ||
725 | 0x33, 0xFC, | ||
726 | 0x34, 0x13, | ||
727 | 0xff, 0xff, | ||
728 | }; | ||
729 | |||
730 | |||
731 | static int samsung_smt_7020_tuner_set_params(struct dvb_frontend *fe, | ||
732 | struct dvb_frontend_parameters *params) | ||
733 | { | ||
734 | struct cx8802_dev *dev = fe->dvb->priv; | ||
735 | u8 buf[4]; | ||
736 | u32 div; | ||
737 | struct i2c_msg msg = { | ||
738 | .addr = 0x61, | ||
739 | .flags = 0, | ||
740 | .buf = buf, | ||
741 | .len = sizeof(buf) }; | ||
742 | |||
743 | div = params->frequency / 125; | ||
744 | |||
745 | buf[0] = (div >> 8) & 0x7f; | ||
746 | buf[1] = div & 0xff; | ||
747 | buf[2] = 0x84; /* 0xC4 */ | ||
748 | buf[3] = 0x00; | ||
749 | |||
750 | if (params->frequency < 1500000) | ||
751 | buf[3] |= 0x10; | ||
752 | |||
753 | if (fe->ops.i2c_gate_ctrl) | ||
754 | fe->ops.i2c_gate_ctrl(fe, 1); | ||
755 | |||
756 | if (i2c_transfer(&dev->core->i2c_adap, &msg, 1) != 1) | ||
757 | return -EIO; | ||
758 | |||
759 | return 0; | ||
760 | } | ||
761 | |||
762 | static int samsung_smt_7020_set_tone(struct dvb_frontend *fe, | ||
763 | fe_sec_tone_mode_t tone) | ||
764 | { | ||
765 | struct cx8802_dev *dev = fe->dvb->priv; | ||
766 | struct cx88_core *core = dev->core; | ||
767 | |||
768 | cx_set(MO_GP0_IO, 0x0800); | ||
769 | |||
770 | switch (tone) { | ||
771 | case SEC_TONE_ON: | ||
772 | cx_set(MO_GP0_IO, 0x08); | ||
773 | break; | ||
774 | case SEC_TONE_OFF: | ||
775 | cx_clear(MO_GP0_IO, 0x08); | ||
776 | break; | ||
777 | default: | ||
778 | return -EINVAL; | ||
779 | } | ||
780 | |||
781 | return 0; | ||
782 | } | ||
783 | |||
784 | static int samsung_smt_7020_set_voltage(struct dvb_frontend *fe, | ||
785 | fe_sec_voltage_t voltage) | ||
786 | { | ||
787 | struct cx8802_dev *dev = fe->dvb->priv; | ||
788 | struct cx88_core *core = dev->core; | ||
789 | |||
790 | u8 data; | ||
791 | struct i2c_msg msg = { | ||
792 | .addr = 8, | ||
793 | .flags = 0, | ||
794 | .buf = &data, | ||
795 | .len = sizeof(data) }; | ||
796 | |||
797 | cx_set(MO_GP0_IO, 0x8000); | ||
798 | |||
799 | switch (voltage) { | ||
800 | case SEC_VOLTAGE_OFF: | ||
801 | break; | ||
802 | case SEC_VOLTAGE_13: | ||
803 | data = ISL6421_EN1 | ISL6421_LLC1; | ||
804 | cx_clear(MO_GP0_IO, 0x80); | ||
805 | break; | ||
806 | case SEC_VOLTAGE_18: | ||
807 | data = ISL6421_EN1 | ISL6421_LLC1 | ISL6421_VSEL1; | ||
808 | cx_clear(MO_GP0_IO, 0x80); | ||
809 | break; | ||
810 | default: | ||
811 | return -EINVAL; | ||
812 | }; | ||
813 | |||
814 | return (i2c_transfer(&dev->core->i2c_adap, &msg, 1) == 1) ? 0 : -EIO; | ||
815 | } | ||
816 | |||
817 | static int samsung_smt_7020_stv0299_set_symbol_rate(struct dvb_frontend *fe, | ||
818 | u32 srate, u32 ratio) | ||
819 | { | ||
820 | u8 aclk = 0; | ||
821 | u8 bclk = 0; | ||
822 | |||
823 | if (srate < 1500000) { | ||
824 | aclk = 0xb7; | ||
825 | bclk = 0x47; | ||
826 | } else if (srate < 3000000) { | ||
827 | aclk = 0xb7; | ||
828 | bclk = 0x4b; | ||
829 | } else if (srate < 7000000) { | ||
830 | aclk = 0xb7; | ||
831 | bclk = 0x4f; | ||
832 | } else if (srate < 14000000) { | ||
833 | aclk = 0xb7; | ||
834 | bclk = 0x53; | ||
835 | } else if (srate < 30000000) { | ||
836 | aclk = 0xb6; | ||
837 | bclk = 0x53; | ||
838 | } else if (srate < 45000000) { | ||
839 | aclk = 0xb4; | ||
840 | bclk = 0x51; | ||
841 | } | ||
842 | |||
843 | stv0299_writereg(fe, 0x13, aclk); | ||
844 | stv0299_writereg(fe, 0x14, bclk); | ||
845 | stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); | ||
846 | stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); | ||
847 | stv0299_writereg(fe, 0x21, ratio & 0xf0); | ||
848 | |||
849 | return 0; | ||
850 | } | ||
851 | |||
852 | |||
853 | static struct stv0299_config samsung_stv0299_config = { | ||
854 | .demod_address = 0x68, | ||
855 | .inittab = samsung_smt_7020_inittab, | ||
856 | .mclk = 88000000UL, | ||
857 | .invert = 0, | ||
858 | .skip_reinit = 0, | ||
859 | .lock_output = STV0299_LOCKOUTPUT_LK, | ||
860 | .volt13_op0_op1 = STV0299_VOLT13_OP1, | ||
861 | .min_delay_ms = 100, | ||
862 | .set_symbol_rate = samsung_smt_7020_stv0299_set_symbol_rate, | ||
863 | }; | ||
864 | |||
677 | static int dvb_register(struct cx8802_dev *dev) | 865 | static int dvb_register(struct cx8802_dev *dev) |
678 | { | 866 | { |
679 | struct cx88_core *core = dev->core; | 867 | struct cx88_core *core = dev->core; |
@@ -1203,6 +1391,32 @@ static int dvb_register(struct cx8802_dev *dev) | |||
1203 | } | 1391 | } |
1204 | break; | 1392 | break; |
1205 | } | 1393 | } |
1394 | case CX88_BOARD_SAMSUNG_SMT_7020: | ||
1395 | dev->ts_gen_cntrl = 0x08; | ||
1396 | |||
1397 | cx_set(MO_GP0_IO, 0x0101); | ||
1398 | |||
1399 | cx_clear(MO_GP0_IO, 0x01); | ||
1400 | mdelay(100); | ||
1401 | cx_set(MO_GP0_IO, 0x01); | ||
1402 | mdelay(200); | ||
1403 | |||
1404 | fe0->dvb.frontend = dvb_attach(stv0299_attach, | ||
1405 | &samsung_stv0299_config, | ||
1406 | &dev->core->i2c_adap); | ||
1407 | if (fe0->dvb.frontend) { | ||
1408 | fe0->dvb.frontend->ops.tuner_ops.set_params = | ||
1409 | samsung_smt_7020_tuner_set_params; | ||
1410 | fe0->dvb.frontend->tuner_priv = | ||
1411 | &dev->core->i2c_adap; | ||
1412 | fe0->dvb.frontend->ops.set_voltage = | ||
1413 | samsung_smt_7020_set_voltage; | ||
1414 | fe0->dvb.frontend->ops.set_tone = | ||
1415 | samsung_smt_7020_set_tone; | ||
1416 | } | ||
1417 | |||
1418 | break; | ||
1419 | |||
1206 | default: | 1420 | default: |
1207 | printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", | 1421 | printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", |
1208 | core->name); | 1422 | core->name); |
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index f9fda18b410c..de180d4d5a21 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c | |||
@@ -192,7 +192,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
192 | struct cx88_IR *ir; | 192 | struct cx88_IR *ir; |
193 | struct input_dev *input_dev; | 193 | struct input_dev *input_dev; |
194 | struct ir_scancode_table *ir_codes = NULL; | 194 | struct ir_scancode_table *ir_codes = NULL; |
195 | int ir_type = IR_TYPE_OTHER; | 195 | u64 ir_type = IR_TYPE_OTHER; |
196 | int err = -ENOMEM; | 196 | int err = -ENOMEM; |
197 | 197 | ||
198 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); | 198 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); |
@@ -383,7 +383,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
383 | cx88_ir_start(core, ir); | 383 | cx88_ir_start(core, ir); |
384 | 384 | ||
385 | /* all done */ | 385 | /* all done */ |
386 | err = ir_input_register(ir->input, ir_codes); | 386 | err = ir_input_register(ir->input, ir_codes, NULL); |
387 | if (err) | 387 | if (err) |
388 | goto err_out_stop; | 388 | goto err_out_stop; |
389 | 389 | ||
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index bb5104893411..338af77f7f01 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c | |||
@@ -110,6 +110,9 @@ static int cx8802_start_dma(struct cx8802_dev *dev, | |||
110 | case CX88_BOARD_PCHDTV_HD5500: | 110 | case CX88_BOARD_PCHDTV_HD5500: |
111 | cx_write(TS_SOP_STAT, 1<<13); | 111 | cx_write(TS_SOP_STAT, 1<<13); |
112 | break; | 112 | break; |
113 | case CX88_BOARD_SAMSUNG_SMT_7020: | ||
114 | cx_write(TS_SOP_STAT, 0x00); | ||
115 | break; | ||
113 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: | 116 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: |
114 | case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: | 117 | case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: |
115 | cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */ | 118 | cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */ |
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index b1499bf604ea..48b6c04fb497 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h | |||
@@ -239,6 +239,7 @@ extern struct sram_channel cx88_sram_channels[]; | |||
239 | #define CX88_BOARD_WINFAST_DTV1800H 81 | 239 | #define CX88_BOARD_WINFAST_DTV1800H 81 |
240 | #define CX88_BOARD_WINFAST_DTV2000H_J 82 | 240 | #define CX88_BOARD_WINFAST_DTV2000H_J 82 |
241 | #define CX88_BOARD_PROF_7301 83 | 241 | #define CX88_BOARD_PROF_7301 83 |
242 | #define CX88_BOARD_SAMSUNG_SMT_7020 84 | ||
242 | 243 | ||
243 | enum cx88_itype { | 244 | enum cx88_itype { |
244 | CX88_VMUX_COMPOSITE1 = 1, | 245 | CX88_VMUX_COMPOSITE1 = 1, |
diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c index ee43876adb06..9b413a35e048 100644 --- a/drivers/media/video/dabusb.c +++ b/drivers/media/video/dabusb.c | |||
@@ -913,6 +913,8 @@ static void __exit dabusb_cleanup (void) | |||
913 | MODULE_AUTHOR( DRIVER_AUTHOR ); | 913 | MODULE_AUTHOR( DRIVER_AUTHOR ); |
914 | MODULE_DESCRIPTION( DRIVER_DESC ); | 914 | MODULE_DESCRIPTION( DRIVER_DESC ); |
915 | MODULE_LICENSE("GPL"); | 915 | MODULE_LICENSE("GPL"); |
916 | MODULE_FIRMWARE("dabusb/firmware.fw"); | ||
917 | MODULE_FIRMWARE("dabusb/bitstream.bin"); | ||
916 | 918 | ||
917 | module_param(buffers, int, 0); | 919 | module_param(buffers, int, 0); |
918 | MODULE_PARM_DESC (buffers, "Number of buffers (default=256)"); | 920 | MODULE_PARM_DESC (buffers, "Number of buffers (default=256)"); |
diff --git a/drivers/media/video/davinci/Makefile b/drivers/media/video/davinci/Makefile index 1a8b8f3f182e..a37955745aaa 100644 --- a/drivers/media/video/davinci/Makefile +++ b/drivers/media/video/davinci/Makefile | |||
@@ -15,3 +15,4 @@ obj-$(CONFIG_VIDEO_VPSS_SYSTEM) += vpss.o | |||
15 | obj-$(CONFIG_VIDEO_VPFE_CAPTURE) += vpfe_capture.o | 15 | obj-$(CONFIG_VIDEO_VPFE_CAPTURE) += vpfe_capture.o |
16 | obj-$(CONFIG_VIDEO_DM6446_CCDC) += dm644x_ccdc.o | 16 | obj-$(CONFIG_VIDEO_DM6446_CCDC) += dm644x_ccdc.o |
17 | obj-$(CONFIG_VIDEO_DM355_CCDC) += dm355_ccdc.o | 17 | obj-$(CONFIG_VIDEO_DM355_CCDC) += dm355_ccdc.o |
18 | obj-$(CONFIG_VIDEO_ISIF) += isif.o | ||
diff --git a/drivers/media/video/davinci/dm355_ccdc.c b/drivers/media/video/davinci/dm355_ccdc.c index 314390016370..c29ac88ffd78 100644 --- a/drivers/media/video/davinci/dm355_ccdc.c +++ b/drivers/media/video/davinci/dm355_ccdc.c | |||
@@ -37,8 +37,12 @@ | |||
37 | #include <linux/platform_device.h> | 37 | #include <linux/platform_device.h> |
38 | #include <linux/uaccess.h> | 38 | #include <linux/uaccess.h> |
39 | #include <linux/videodev2.h> | 39 | #include <linux/videodev2.h> |
40 | #include <linux/clk.h> | ||
41 | #include <linux/err.h> | ||
42 | |||
40 | #include <media/davinci/dm355_ccdc.h> | 43 | #include <media/davinci/dm355_ccdc.h> |
41 | #include <media/davinci/vpss.h> | 44 | #include <media/davinci/vpss.h> |
45 | |||
42 | #include "dm355_ccdc_regs.h" | 46 | #include "dm355_ccdc_regs.h" |
43 | #include "ccdc_hw_device.h" | 47 | #include "ccdc_hw_device.h" |
44 | 48 | ||
@@ -46,67 +50,75 @@ MODULE_LICENSE("GPL"); | |||
46 | MODULE_DESCRIPTION("CCDC Driver for DM355"); | 50 | MODULE_DESCRIPTION("CCDC Driver for DM355"); |
47 | MODULE_AUTHOR("Texas Instruments"); | 51 | MODULE_AUTHOR("Texas Instruments"); |
48 | 52 | ||
49 | static struct device *dev; | 53 | static struct ccdc_oper_config { |
50 | 54 | struct device *dev; | |
51 | /* Object for CCDC raw mode */ | 55 | /* CCDC interface type */ |
52 | static struct ccdc_params_raw ccdc_hw_params_raw = { | 56 | enum vpfe_hw_if_type if_type; |
53 | .pix_fmt = CCDC_PIXFMT_RAW, | 57 | /* Raw Bayer configuration */ |
54 | .frm_fmt = CCDC_FRMFMT_PROGRESSIVE, | 58 | struct ccdc_params_raw bayer; |
55 | .win = CCDC_WIN_VGA, | 59 | /* YCbCr configuration */ |
56 | .fid_pol = VPFE_PINPOL_POSITIVE, | 60 | struct ccdc_params_ycbcr ycbcr; |
57 | .vd_pol = VPFE_PINPOL_POSITIVE, | 61 | /* Master clock */ |
58 | .hd_pol = VPFE_PINPOL_POSITIVE, | 62 | struct clk *mclk; |
59 | .gain = { | 63 | /* slave clock */ |
60 | .r_ye = 256, | 64 | struct clk *sclk; |
61 | .gb_g = 256, | 65 | /* ccdc base address */ |
62 | .gr_cy = 256, | 66 | void __iomem *base_addr; |
63 | .b_mg = 256 | 67 | } ccdc_cfg = { |
64 | }, | 68 | /* Raw configurations */ |
65 | .config_params = { | 69 | .bayer = { |
66 | .datasft = 2, | 70 | .pix_fmt = CCDC_PIXFMT_RAW, |
67 | .data_sz = CCDC_DATA_10BITS, | 71 | .frm_fmt = CCDC_FRMFMT_PROGRESSIVE, |
68 | .mfilt1 = CCDC_NO_MEDIAN_FILTER1, | 72 | .win = CCDC_WIN_VGA, |
69 | .mfilt2 = CCDC_NO_MEDIAN_FILTER2, | 73 | .fid_pol = VPFE_PINPOL_POSITIVE, |
70 | .alaw = { | 74 | .vd_pol = VPFE_PINPOL_POSITIVE, |
71 | .gama_wd = 2, | 75 | .hd_pol = VPFE_PINPOL_POSITIVE, |
76 | .gain = { | ||
77 | .r_ye = 256, | ||
78 | .gb_g = 256, | ||
79 | .gr_cy = 256, | ||
80 | .b_mg = 256 | ||
72 | }, | 81 | }, |
73 | .blk_clamp = { | 82 | .config_params = { |
74 | .sample_pixel = 1, | 83 | .datasft = 2, |
75 | .dc_sub = 25 | 84 | .mfilt1 = CCDC_NO_MEDIAN_FILTER1, |
76 | }, | 85 | .mfilt2 = CCDC_NO_MEDIAN_FILTER2, |
77 | .col_pat_field0 = { | 86 | .alaw = { |
78 | .olop = CCDC_GREEN_BLUE, | 87 | .gama_wd = 2, |
79 | .olep = CCDC_BLUE, | 88 | }, |
80 | .elop = CCDC_RED, | 89 | .blk_clamp = { |
81 | .elep = CCDC_GREEN_RED | 90 | .sample_pixel = 1, |
82 | }, | 91 | .dc_sub = 25 |
83 | .col_pat_field1 = { | 92 | }, |
84 | .olop = CCDC_GREEN_BLUE, | 93 | .col_pat_field0 = { |
85 | .olep = CCDC_BLUE, | 94 | .olop = CCDC_GREEN_BLUE, |
86 | .elop = CCDC_RED, | 95 | .olep = CCDC_BLUE, |
87 | .elep = CCDC_GREEN_RED | 96 | .elop = CCDC_RED, |
97 | .elep = CCDC_GREEN_RED | ||
98 | }, | ||
99 | .col_pat_field1 = { | ||
100 | .olop = CCDC_GREEN_BLUE, | ||
101 | .olep = CCDC_BLUE, | ||
102 | .elop = CCDC_RED, | ||
103 | .elep = CCDC_GREEN_RED | ||
104 | }, | ||
88 | }, | 105 | }, |
89 | }, | 106 | }, |
107 | /* YCbCr configuration */ | ||
108 | .ycbcr = { | ||
109 | .win = CCDC_WIN_PAL, | ||
110 | .pix_fmt = CCDC_PIXFMT_YCBCR_8BIT, | ||
111 | .frm_fmt = CCDC_FRMFMT_INTERLACED, | ||
112 | .fid_pol = VPFE_PINPOL_POSITIVE, | ||
113 | .vd_pol = VPFE_PINPOL_POSITIVE, | ||
114 | .hd_pol = VPFE_PINPOL_POSITIVE, | ||
115 | .bt656_enable = 1, | ||
116 | .pix_order = CCDC_PIXORDER_CBYCRY, | ||
117 | .buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED | ||
118 | }, | ||
90 | }; | 119 | }; |
91 | 120 | ||
92 | 121 | ||
93 | /* Object for CCDC ycbcr mode */ | ||
94 | static struct ccdc_params_ycbcr ccdc_hw_params_ycbcr = { | ||
95 | .win = CCDC_WIN_PAL, | ||
96 | .pix_fmt = CCDC_PIXFMT_YCBCR_8BIT, | ||
97 | .frm_fmt = CCDC_FRMFMT_INTERLACED, | ||
98 | .fid_pol = VPFE_PINPOL_POSITIVE, | ||
99 | .vd_pol = VPFE_PINPOL_POSITIVE, | ||
100 | .hd_pol = VPFE_PINPOL_POSITIVE, | ||
101 | .bt656_enable = 1, | ||
102 | .pix_order = CCDC_PIXORDER_CBYCRY, | ||
103 | .buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED | ||
104 | }; | ||
105 | |||
106 | static enum vpfe_hw_if_type ccdc_if_type; | ||
107 | static void *__iomem ccdc_base_addr; | ||
108 | static int ccdc_addr_size; | ||
109 | |||
110 | /* Raw Bayer formats */ | 122 | /* Raw Bayer formats */ |
111 | static u32 ccdc_raw_bayer_pix_formats[] = | 123 | static u32 ccdc_raw_bayer_pix_formats[] = |
112 | {V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SBGGR16}; | 124 | {V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SBGGR16}; |
@@ -118,18 +130,12 @@ static u32 ccdc_raw_yuv_pix_formats[] = | |||
118 | /* register access routines */ | 130 | /* register access routines */ |
119 | static inline u32 regr(u32 offset) | 131 | static inline u32 regr(u32 offset) |
120 | { | 132 | { |
121 | return __raw_readl(ccdc_base_addr + offset); | 133 | return __raw_readl(ccdc_cfg.base_addr + offset); |
122 | } | 134 | } |
123 | 135 | ||
124 | static inline void regw(u32 val, u32 offset) | 136 | static inline void regw(u32 val, u32 offset) |
125 | { | 137 | { |
126 | __raw_writel(val, ccdc_base_addr + offset); | 138 | __raw_writel(val, ccdc_cfg.base_addr + offset); |
127 | } | ||
128 | |||
129 | static void ccdc_set_ccdc_base(void *addr, int size) | ||
130 | { | ||
131 | ccdc_base_addr = addr; | ||
132 | ccdc_addr_size = size; | ||
133 | } | 139 | } |
134 | 140 | ||
135 | static void ccdc_enable(int en) | 141 | static void ccdc_enable(int en) |
@@ -153,12 +159,12 @@ static void ccdc_enable_output_to_sdram(int en) | |||
153 | static void ccdc_config_gain_offset(void) | 159 | static void ccdc_config_gain_offset(void) |
154 | { | 160 | { |
155 | /* configure gain */ | 161 | /* configure gain */ |
156 | regw(ccdc_hw_params_raw.gain.r_ye, RYEGAIN); | 162 | regw(ccdc_cfg.bayer.gain.r_ye, RYEGAIN); |
157 | regw(ccdc_hw_params_raw.gain.gr_cy, GRCYGAIN); | 163 | regw(ccdc_cfg.bayer.gain.gr_cy, GRCYGAIN); |
158 | regw(ccdc_hw_params_raw.gain.gb_g, GBGGAIN); | 164 | regw(ccdc_cfg.bayer.gain.gb_g, GBGGAIN); |
159 | regw(ccdc_hw_params_raw.gain.b_mg, BMGGAIN); | 165 | regw(ccdc_cfg.bayer.gain.b_mg, BMGGAIN); |
160 | /* configure offset */ | 166 | /* configure offset */ |
161 | regw(ccdc_hw_params_raw.ccdc_offset, OFFSET); | 167 | regw(ccdc_cfg.bayer.ccdc_offset, OFFSET); |
162 | } | 168 | } |
163 | 169 | ||
164 | /* | 170 | /* |
@@ -169,7 +175,7 @@ static int ccdc_restore_defaults(void) | |||
169 | { | 175 | { |
170 | int i; | 176 | int i; |
171 | 177 | ||
172 | dev_dbg(dev, "\nstarting ccdc_restore_defaults..."); | 178 | dev_dbg(ccdc_cfg.dev, "\nstarting ccdc_restore_defaults..."); |
173 | /* set all registers to zero */ | 179 | /* set all registers to zero */ |
174 | for (i = 0; i <= CCDC_REG_LAST; i += 4) | 180 | for (i = 0; i <= CCDC_REG_LAST; i += 4) |
175 | regw(0, i); | 181 | regw(0, i); |
@@ -180,30 +186,29 @@ static int ccdc_restore_defaults(void) | |||
180 | regw(CULH_DEFAULT, CULH); | 186 | regw(CULH_DEFAULT, CULH); |
181 | regw(CULV_DEFAULT, CULV); | 187 | regw(CULV_DEFAULT, CULV); |
182 | /* Set default Gain and Offset */ | 188 | /* Set default Gain and Offset */ |
183 | ccdc_hw_params_raw.gain.r_ye = GAIN_DEFAULT; | 189 | ccdc_cfg.bayer.gain.r_ye = GAIN_DEFAULT; |
184 | ccdc_hw_params_raw.gain.gb_g = GAIN_DEFAULT; | 190 | ccdc_cfg.bayer.gain.gb_g = GAIN_DEFAULT; |
185 | ccdc_hw_params_raw.gain.gr_cy = GAIN_DEFAULT; | 191 | ccdc_cfg.bayer.gain.gr_cy = GAIN_DEFAULT; |
186 | ccdc_hw_params_raw.gain.b_mg = GAIN_DEFAULT; | 192 | ccdc_cfg.bayer.gain.b_mg = GAIN_DEFAULT; |
187 | ccdc_config_gain_offset(); | 193 | ccdc_config_gain_offset(); |
188 | regw(OUTCLIP_DEFAULT, OUTCLIP); | 194 | regw(OUTCLIP_DEFAULT, OUTCLIP); |
189 | regw(LSCCFG2_DEFAULT, LSCCFG2); | 195 | regw(LSCCFG2_DEFAULT, LSCCFG2); |
190 | /* select ccdc input */ | 196 | /* select ccdc input */ |
191 | if (vpss_select_ccdc_source(VPSS_CCDCIN)) { | 197 | if (vpss_select_ccdc_source(VPSS_CCDCIN)) { |
192 | dev_dbg(dev, "\ncouldn't select ccdc input source"); | 198 | dev_dbg(ccdc_cfg.dev, "\ncouldn't select ccdc input source"); |
193 | return -EFAULT; | 199 | return -EFAULT; |
194 | } | 200 | } |
195 | /* select ccdc clock */ | 201 | /* select ccdc clock */ |
196 | if (vpss_enable_clock(VPSS_CCDC_CLOCK, 1) < 0) { | 202 | if (vpss_enable_clock(VPSS_CCDC_CLOCK, 1) < 0) { |
197 | dev_dbg(dev, "\ncouldn't enable ccdc clock"); | 203 | dev_dbg(ccdc_cfg.dev, "\ncouldn't enable ccdc clock"); |
198 | return -EFAULT; | 204 | return -EFAULT; |
199 | } | 205 | } |
200 | dev_dbg(dev, "\nEnd of ccdc_restore_defaults..."); | 206 | dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_restore_defaults..."); |
201 | return 0; | 207 | return 0; |
202 | } | 208 | } |
203 | 209 | ||
204 | static int ccdc_open(struct device *device) | 210 | static int ccdc_open(struct device *device) |
205 | { | 211 | { |
206 | dev = device; | ||
207 | return ccdc_restore_defaults(); | 212 | return ccdc_restore_defaults(); |
208 | } | 213 | } |
209 | 214 | ||
@@ -226,7 +231,7 @@ static void ccdc_setwin(struct v4l2_rect *image_win, | |||
226 | int vert_start, vert_nr_lines; | 231 | int vert_start, vert_nr_lines; |
227 | int mid_img = 0; | 232 | int mid_img = 0; |
228 | 233 | ||
229 | dev_dbg(dev, "\nStarting ccdc_setwin..."); | 234 | dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_setwin..."); |
230 | 235 | ||
231 | /* | 236 | /* |
232 | * ppc - per pixel count. indicates how many pixels per cell | 237 | * ppc - per pixel count. indicates how many pixels per cell |
@@ -260,45 +265,46 @@ static void ccdc_setwin(struct v4l2_rect *image_win, | |||
260 | regw(vert_start & CCDC_START_VER_ONE_MASK, SLV0); | 265 | regw(vert_start & CCDC_START_VER_ONE_MASK, SLV0); |
261 | regw(vert_start & CCDC_START_VER_TWO_MASK, SLV1); | 266 | regw(vert_start & CCDC_START_VER_TWO_MASK, SLV1); |
262 | regw(vert_nr_lines & CCDC_NUM_LINES_VER, NLV); | 267 | regw(vert_nr_lines & CCDC_NUM_LINES_VER, NLV); |
263 | dev_dbg(dev, "\nEnd of ccdc_setwin..."); | 268 | dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_setwin..."); |
264 | } | 269 | } |
265 | 270 | ||
266 | static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam) | 271 | static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam) |
267 | { | 272 | { |
268 | if (ccdcparam->datasft < CCDC_DATA_NO_SHIFT || | 273 | if (ccdcparam->datasft < CCDC_DATA_NO_SHIFT || |
269 | ccdcparam->datasft > CCDC_DATA_SHIFT_6BIT) { | 274 | ccdcparam->datasft > CCDC_DATA_SHIFT_6BIT) { |
270 | dev_dbg(dev, "Invalid value of data shift\n"); | 275 | dev_dbg(ccdc_cfg.dev, "Invalid value of data shift\n"); |
271 | return -EINVAL; | 276 | return -EINVAL; |
272 | } | 277 | } |
273 | 278 | ||
274 | if (ccdcparam->mfilt1 < CCDC_NO_MEDIAN_FILTER1 || | 279 | if (ccdcparam->mfilt1 < CCDC_NO_MEDIAN_FILTER1 || |
275 | ccdcparam->mfilt1 > CCDC_MEDIAN_FILTER1) { | 280 | ccdcparam->mfilt1 > CCDC_MEDIAN_FILTER1) { |
276 | dev_dbg(dev, "Invalid value of median filter1\n"); | 281 | dev_dbg(ccdc_cfg.dev, "Invalid value of median filter1\n"); |
277 | return -EINVAL; | 282 | return -EINVAL; |
278 | } | 283 | } |
279 | 284 | ||
280 | if (ccdcparam->mfilt2 < CCDC_NO_MEDIAN_FILTER2 || | 285 | if (ccdcparam->mfilt2 < CCDC_NO_MEDIAN_FILTER2 || |
281 | ccdcparam->mfilt2 > CCDC_MEDIAN_FILTER2) { | 286 | ccdcparam->mfilt2 > CCDC_MEDIAN_FILTER2) { |
282 | dev_dbg(dev, "Invalid value of median filter2\n"); | 287 | dev_dbg(ccdc_cfg.dev, "Invalid value of median filter2\n"); |
283 | return -EINVAL; | 288 | return -EINVAL; |
284 | } | 289 | } |
285 | 290 | ||
286 | if ((ccdcparam->med_filt_thres < 0) || | 291 | if ((ccdcparam->med_filt_thres < 0) || |
287 | (ccdcparam->med_filt_thres > CCDC_MED_FILT_THRESH)) { | 292 | (ccdcparam->med_filt_thres > CCDC_MED_FILT_THRESH)) { |
288 | dev_dbg(dev, "Invalid value of median filter threshold\n"); | 293 | dev_dbg(ccdc_cfg.dev, |
294 | "Invalid value of median filter thresold\n"); | ||
289 | return -EINVAL; | 295 | return -EINVAL; |
290 | } | 296 | } |
291 | 297 | ||
292 | if (ccdcparam->data_sz < CCDC_DATA_16BITS || | 298 | if (ccdcparam->data_sz < CCDC_DATA_16BITS || |
293 | ccdcparam->data_sz > CCDC_DATA_8BITS) { | 299 | ccdcparam->data_sz > CCDC_DATA_8BITS) { |
294 | dev_dbg(dev, "Invalid value of data size\n"); | 300 | dev_dbg(ccdc_cfg.dev, "Invalid value of data size\n"); |
295 | return -EINVAL; | 301 | return -EINVAL; |
296 | } | 302 | } |
297 | 303 | ||
298 | if (ccdcparam->alaw.enable) { | 304 | if (ccdcparam->alaw.enable) { |
299 | if (ccdcparam->alaw.gama_wd < CCDC_GAMMA_BITS_13_4 || | 305 | if (ccdcparam->alaw.gama_wd < CCDC_GAMMA_BITS_13_4 || |
300 | ccdcparam->alaw.gama_wd > CCDC_GAMMA_BITS_09_0) { | 306 | ccdcparam->alaw.gama_wd > CCDC_GAMMA_BITS_09_0) { |
301 | dev_dbg(dev, "Invalid value of ALAW\n"); | 307 | dev_dbg(ccdc_cfg.dev, "Invalid value of ALAW\n"); |
302 | return -EINVAL; | 308 | return -EINVAL; |
303 | } | 309 | } |
304 | } | 310 | } |
@@ -306,12 +312,14 @@ static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam) | |||
306 | if (ccdcparam->blk_clamp.b_clamp_enable) { | 312 | if (ccdcparam->blk_clamp.b_clamp_enable) { |
307 | if (ccdcparam->blk_clamp.sample_pixel < CCDC_SAMPLE_1PIXELS || | 313 | if (ccdcparam->blk_clamp.sample_pixel < CCDC_SAMPLE_1PIXELS || |
308 | ccdcparam->blk_clamp.sample_pixel > CCDC_SAMPLE_16PIXELS) { | 314 | ccdcparam->blk_clamp.sample_pixel > CCDC_SAMPLE_16PIXELS) { |
309 | dev_dbg(dev, "Invalid value of sample pixel\n"); | 315 | dev_dbg(ccdc_cfg.dev, |
316 | "Invalid value of sample pixel\n"); | ||
310 | return -EINVAL; | 317 | return -EINVAL; |
311 | } | 318 | } |
312 | if (ccdcparam->blk_clamp.sample_ln < CCDC_SAMPLE_1LINES || | 319 | if (ccdcparam->blk_clamp.sample_ln < CCDC_SAMPLE_1LINES || |
313 | ccdcparam->blk_clamp.sample_ln > CCDC_SAMPLE_16LINES) { | 320 | ccdcparam->blk_clamp.sample_ln > CCDC_SAMPLE_16LINES) { |
314 | dev_dbg(dev, "Invalid value of sample lines\n"); | 321 | dev_dbg(ccdc_cfg.dev, |
322 | "Invalid value of sample lines\n"); | ||
315 | return -EINVAL; | 323 | return -EINVAL; |
316 | } | 324 | } |
317 | } | 325 | } |
@@ -325,18 +333,18 @@ static int ccdc_set_params(void __user *params) | |||
325 | int x; | 333 | int x; |
326 | 334 | ||
327 | /* only raw module parameters can be set through the IOCTL */ | 335 | /* only raw module parameters can be set through the IOCTL */ |
328 | if (ccdc_if_type != VPFE_RAW_BAYER) | 336 | if (ccdc_cfg.if_type != VPFE_RAW_BAYER) |
329 | return -EINVAL; | 337 | return -EINVAL; |
330 | 338 | ||
331 | x = copy_from_user(&ccdc_raw_params, params, sizeof(ccdc_raw_params)); | 339 | x = copy_from_user(&ccdc_raw_params, params, sizeof(ccdc_raw_params)); |
332 | if (x) { | 340 | if (x) { |
333 | dev_dbg(dev, "ccdc_set_params: error in copying ccdc" | 341 | dev_dbg(ccdc_cfg.dev, "ccdc_set_params: error in copying ccdc" |
334 | "params, %d\n", x); | 342 | "params, %d\n", x); |
335 | return -EFAULT; | 343 | return -EFAULT; |
336 | } | 344 | } |
337 | 345 | ||
338 | if (!validate_ccdc_param(&ccdc_raw_params)) { | 346 | if (!validate_ccdc_param(&ccdc_raw_params)) { |
339 | memcpy(&ccdc_hw_params_raw.config_params, | 347 | memcpy(&ccdc_cfg.bayer.config_params, |
340 | &ccdc_raw_params, | 348 | &ccdc_raw_params, |
341 | sizeof(ccdc_raw_params)); | 349 | sizeof(ccdc_raw_params)); |
342 | return 0; | 350 | return 0; |
@@ -347,11 +355,11 @@ static int ccdc_set_params(void __user *params) | |||
347 | /* This function will configure CCDC for YCbCr video capture */ | 355 | /* This function will configure CCDC for YCbCr video capture */ |
348 | static void ccdc_config_ycbcr(void) | 356 | static void ccdc_config_ycbcr(void) |
349 | { | 357 | { |
350 | struct ccdc_params_ycbcr *params = &ccdc_hw_params_ycbcr; | 358 | struct ccdc_params_ycbcr *params = &ccdc_cfg.ycbcr; |
351 | u32 temp; | 359 | u32 temp; |
352 | 360 | ||
353 | /* first set the CCDC power on defaults values in all registers */ | 361 | /* first set the CCDC power on defaults values in all registers */ |
354 | dev_dbg(dev, "\nStarting ccdc_config_ycbcr..."); | 362 | dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_config_ycbcr..."); |
355 | ccdc_restore_defaults(); | 363 | ccdc_restore_defaults(); |
356 | 364 | ||
357 | /* configure pixel format & video frame format */ | 365 | /* configure pixel format & video frame format */ |
@@ -403,7 +411,7 @@ static void ccdc_config_ycbcr(void) | |||
403 | regw(CCDC_SDOFST_FIELD_INTERLEAVED, SDOFST); | 411 | regw(CCDC_SDOFST_FIELD_INTERLEAVED, SDOFST); |
404 | } | 412 | } |
405 | 413 | ||
406 | dev_dbg(dev, "\nEnd of ccdc_config_ycbcr...\n"); | 414 | dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_config_ycbcr...\n"); |
407 | } | 415 | } |
408 | 416 | ||
409 | /* | 417 | /* |
@@ -483,7 +491,7 @@ int ccdc_write_dfc_entry(int index, struct ccdc_vertical_dft *dfc) | |||
483 | */ | 491 | */ |
484 | 492 | ||
485 | if (count) { | 493 | if (count) { |
486 | dev_err(dev, "defect table write timeout !!!\n"); | 494 | dev_err(ccdc_cfg.dev, "defect table write timeout !!!\n"); |
487 | return -1; | 495 | return -1; |
488 | } | 496 | } |
489 | return 0; | 497 | return 0; |
@@ -605,12 +613,12 @@ static void ccdc_config_color_patterns(struct ccdc_col_pat *pat0, | |||
605 | /* This function will configure CCDC for Raw mode image capture */ | 613 | /* This function will configure CCDC for Raw mode image capture */ |
606 | static int ccdc_config_raw(void) | 614 | static int ccdc_config_raw(void) |
607 | { | 615 | { |
608 | struct ccdc_params_raw *params = &ccdc_hw_params_raw; | 616 | struct ccdc_params_raw *params = &ccdc_cfg.bayer; |
609 | struct ccdc_config_params_raw *config_params = | 617 | struct ccdc_config_params_raw *config_params = |
610 | &ccdc_hw_params_raw.config_params; | 618 | &ccdc_cfg.bayer.config_params; |
611 | unsigned int val; | 619 | unsigned int val; |
612 | 620 | ||
613 | dev_dbg(dev, "\nStarting ccdc_config_raw..."); | 621 | dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_config_raw..."); |
614 | 622 | ||
615 | /* restore power on defaults to register */ | 623 | /* restore power on defaults to register */ |
616 | ccdc_restore_defaults(); | 624 | ccdc_restore_defaults(); |
@@ -659,7 +667,7 @@ static int ccdc_config_raw(void) | |||
659 | val |= (config_params->datasft & CCDC_DATASFT_MASK) << | 667 | val |= (config_params->datasft & CCDC_DATASFT_MASK) << |
660 | CCDC_DATASFT_SHIFT; | 668 | CCDC_DATASFT_SHIFT; |
661 | regw(val , MODESET); | 669 | regw(val , MODESET); |
662 | dev_dbg(dev, "\nWriting 0x%x to MODESET...\n", val); | 670 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to MODESET...\n", val); |
663 | 671 | ||
664 | /* Configure the Median Filter threshold */ | 672 | /* Configure the Median Filter threshold */ |
665 | regw((config_params->med_filt_thres) & CCDC_MED_FILT_THRESH, MEDFILT); | 673 | regw((config_params->med_filt_thres) & CCDC_MED_FILT_THRESH, MEDFILT); |
@@ -681,7 +689,7 @@ static int ccdc_config_raw(void) | |||
681 | (config_params->mfilt2 << CCDC_MFILT2_SHIFT)); | 689 | (config_params->mfilt2 << CCDC_MFILT2_SHIFT)); |
682 | 690 | ||
683 | regw(val, GAMMAWD); | 691 | regw(val, GAMMAWD); |
684 | dev_dbg(dev, "\nWriting 0x%x to GAMMAWD...\n", val); | 692 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to GAMMAWD...\n", val); |
685 | 693 | ||
686 | /* configure video window */ | 694 | /* configure video window */ |
687 | ccdc_setwin(¶ms->win, params->frm_fmt, 1); | 695 | ccdc_setwin(¶ms->win, params->frm_fmt, 1); |
@@ -706,7 +714,7 @@ static int ccdc_config_raw(void) | |||
706 | /* Configure the Gain & offset control */ | 714 | /* Configure the Gain & offset control */ |
707 | ccdc_config_gain_offset(); | 715 | ccdc_config_gain_offset(); |
708 | 716 | ||
709 | dev_dbg(dev, "\nWriting %x to COLPTN...\n", val); | 717 | dev_dbg(ccdc_cfg.dev, "\nWriting %x to COLPTN...\n", val); |
710 | 718 | ||
711 | /* Configure DATAOFST register */ | 719 | /* Configure DATAOFST register */ |
712 | val = (config_params->data_offset.horz_offset & CCDC_DATAOFST_MASK) << | 720 | val = (config_params->data_offset.horz_offset & CCDC_DATAOFST_MASK) << |
@@ -726,7 +734,7 @@ static int ccdc_config_raw(void) | |||
726 | CCDC_HSIZE_VAL_MASK; | 734 | CCDC_HSIZE_VAL_MASK; |
727 | 735 | ||
728 | /* adjust to multiple of 32 */ | 736 | /* adjust to multiple of 32 */ |
729 | dev_dbg(dev, "\nWriting 0x%x to HSIZE...\n", | 737 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to HSIZE...\n", |
730 | (((params->win.width) + 31) >> 5) & | 738 | (((params->win.width) + 31) >> 5) & |
731 | CCDC_HSIZE_VAL_MASK); | 739 | CCDC_HSIZE_VAL_MASK); |
732 | } else { | 740 | } else { |
@@ -734,7 +742,7 @@ static int ccdc_config_raw(void) | |||
734 | val |= (((params->win.width * 2) + 31) >> 5) & | 742 | val |= (((params->win.width * 2) + 31) >> 5) & |
735 | CCDC_HSIZE_VAL_MASK; | 743 | CCDC_HSIZE_VAL_MASK; |
736 | 744 | ||
737 | dev_dbg(dev, "\nWriting 0x%x to HSIZE...\n", | 745 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to HSIZE...\n", |
738 | (((params->win.width * 2) + 31) >> 5) & | 746 | (((params->win.width * 2) + 31) >> 5) & |
739 | CCDC_HSIZE_VAL_MASK); | 747 | CCDC_HSIZE_VAL_MASK); |
740 | } | 748 | } |
@@ -745,34 +753,34 @@ static int ccdc_config_raw(void) | |||
745 | if (params->image_invert_enable) { | 753 | if (params->image_invert_enable) { |
746 | /* For interlace inverse mode */ | 754 | /* For interlace inverse mode */ |
747 | regw(CCDC_SDOFST_INTERLACE_INVERSE, SDOFST); | 755 | regw(CCDC_SDOFST_INTERLACE_INVERSE, SDOFST); |
748 | dev_dbg(dev, "\nWriting %x to SDOFST...\n", | 756 | dev_dbg(ccdc_cfg.dev, "\nWriting %x to SDOFST...\n", |
749 | CCDC_SDOFST_INTERLACE_INVERSE); | 757 | CCDC_SDOFST_INTERLACE_INVERSE); |
750 | } else { | 758 | } else { |
751 | /* For interlace non inverse mode */ | 759 | /* For interlace non inverse mode */ |
752 | regw(CCDC_SDOFST_INTERLACE_NORMAL, SDOFST); | 760 | regw(CCDC_SDOFST_INTERLACE_NORMAL, SDOFST); |
753 | dev_dbg(dev, "\nWriting %x to SDOFST...\n", | 761 | dev_dbg(ccdc_cfg.dev, "\nWriting %x to SDOFST...\n", |
754 | CCDC_SDOFST_INTERLACE_NORMAL); | 762 | CCDC_SDOFST_INTERLACE_NORMAL); |
755 | } | 763 | } |
756 | } else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) { | 764 | } else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) { |
757 | if (params->image_invert_enable) { | 765 | if (params->image_invert_enable) { |
758 | /* For progessive inverse mode */ | 766 | /* For progessive inverse mode */ |
759 | regw(CCDC_SDOFST_PROGRESSIVE_INVERSE, SDOFST); | 767 | regw(CCDC_SDOFST_PROGRESSIVE_INVERSE, SDOFST); |
760 | dev_dbg(dev, "\nWriting %x to SDOFST...\n", | 768 | dev_dbg(ccdc_cfg.dev, "\nWriting %x to SDOFST...\n", |
761 | CCDC_SDOFST_PROGRESSIVE_INVERSE); | 769 | CCDC_SDOFST_PROGRESSIVE_INVERSE); |
762 | } else { | 770 | } else { |
763 | /* For progessive non inverse mode */ | 771 | /* For progessive non inverse mode */ |
764 | regw(CCDC_SDOFST_PROGRESSIVE_NORMAL, SDOFST); | 772 | regw(CCDC_SDOFST_PROGRESSIVE_NORMAL, SDOFST); |
765 | dev_dbg(dev, "\nWriting %x to SDOFST...\n", | 773 | dev_dbg(ccdc_cfg.dev, "\nWriting %x to SDOFST...\n", |
766 | CCDC_SDOFST_PROGRESSIVE_NORMAL); | 774 | CCDC_SDOFST_PROGRESSIVE_NORMAL); |
767 | } | 775 | } |
768 | } | 776 | } |
769 | dev_dbg(dev, "\nend of ccdc_config_raw..."); | 777 | dev_dbg(ccdc_cfg.dev, "\nend of ccdc_config_raw..."); |
770 | return 0; | 778 | return 0; |
771 | } | 779 | } |
772 | 780 | ||
773 | static int ccdc_configure(void) | 781 | static int ccdc_configure(void) |
774 | { | 782 | { |
775 | if (ccdc_if_type == VPFE_RAW_BAYER) | 783 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
776 | return ccdc_config_raw(); | 784 | return ccdc_config_raw(); |
777 | else | 785 | else |
778 | ccdc_config_ycbcr(); | 786 | ccdc_config_ycbcr(); |
@@ -781,23 +789,23 @@ static int ccdc_configure(void) | |||
781 | 789 | ||
782 | static int ccdc_set_buftype(enum ccdc_buftype buf_type) | 790 | static int ccdc_set_buftype(enum ccdc_buftype buf_type) |
783 | { | 791 | { |
784 | if (ccdc_if_type == VPFE_RAW_BAYER) | 792 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
785 | ccdc_hw_params_raw.buf_type = buf_type; | 793 | ccdc_cfg.bayer.buf_type = buf_type; |
786 | else | 794 | else |
787 | ccdc_hw_params_ycbcr.buf_type = buf_type; | 795 | ccdc_cfg.ycbcr.buf_type = buf_type; |
788 | return 0; | 796 | return 0; |
789 | } | 797 | } |
790 | static enum ccdc_buftype ccdc_get_buftype(void) | 798 | static enum ccdc_buftype ccdc_get_buftype(void) |
791 | { | 799 | { |
792 | if (ccdc_if_type == VPFE_RAW_BAYER) | 800 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
793 | return ccdc_hw_params_raw.buf_type; | 801 | return ccdc_cfg.bayer.buf_type; |
794 | return ccdc_hw_params_ycbcr.buf_type; | 802 | return ccdc_cfg.ycbcr.buf_type; |
795 | } | 803 | } |
796 | 804 | ||
797 | static int ccdc_enum_pix(u32 *pix, int i) | 805 | static int ccdc_enum_pix(u32 *pix, int i) |
798 | { | 806 | { |
799 | int ret = -EINVAL; | 807 | int ret = -EINVAL; |
800 | if (ccdc_if_type == VPFE_RAW_BAYER) { | 808 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) { |
801 | if (i < ARRAY_SIZE(ccdc_raw_bayer_pix_formats)) { | 809 | if (i < ARRAY_SIZE(ccdc_raw_bayer_pix_formats)) { |
802 | *pix = ccdc_raw_bayer_pix_formats[i]; | 810 | *pix = ccdc_raw_bayer_pix_formats[i]; |
803 | ret = 0; | 811 | ret = 0; |
@@ -813,20 +821,19 @@ static int ccdc_enum_pix(u32 *pix, int i) | |||
813 | 821 | ||
814 | static int ccdc_set_pixel_format(u32 pixfmt) | 822 | static int ccdc_set_pixel_format(u32 pixfmt) |
815 | { | 823 | { |
816 | struct ccdc_a_law *alaw = | 824 | struct ccdc_a_law *alaw = &ccdc_cfg.bayer.config_params.alaw; |
817 | &ccdc_hw_params_raw.config_params.alaw; | ||
818 | 825 | ||
819 | if (ccdc_if_type == VPFE_RAW_BAYER) { | 826 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) { |
820 | ccdc_hw_params_raw.pix_fmt = CCDC_PIXFMT_RAW; | 827 | ccdc_cfg.bayer.pix_fmt = CCDC_PIXFMT_RAW; |
821 | if (pixfmt == V4L2_PIX_FMT_SBGGR8) | 828 | if (pixfmt == V4L2_PIX_FMT_SBGGR8) |
822 | alaw->enable = 1; | 829 | alaw->enable = 1; |
823 | else if (pixfmt != V4L2_PIX_FMT_SBGGR16) | 830 | else if (pixfmt != V4L2_PIX_FMT_SBGGR16) |
824 | return -EINVAL; | 831 | return -EINVAL; |
825 | } else { | 832 | } else { |
826 | if (pixfmt == V4L2_PIX_FMT_YUYV) | 833 | if (pixfmt == V4L2_PIX_FMT_YUYV) |
827 | ccdc_hw_params_ycbcr.pix_order = CCDC_PIXORDER_YCBYCR; | 834 | ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_YCBYCR; |
828 | else if (pixfmt == V4L2_PIX_FMT_UYVY) | 835 | else if (pixfmt == V4L2_PIX_FMT_UYVY) |
829 | ccdc_hw_params_ycbcr.pix_order = CCDC_PIXORDER_CBYCRY; | 836 | ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY; |
830 | else | 837 | else |
831 | return -EINVAL; | 838 | return -EINVAL; |
832 | } | 839 | } |
@@ -834,17 +841,16 @@ static int ccdc_set_pixel_format(u32 pixfmt) | |||
834 | } | 841 | } |
835 | static u32 ccdc_get_pixel_format(void) | 842 | static u32 ccdc_get_pixel_format(void) |
836 | { | 843 | { |
837 | struct ccdc_a_law *alaw = | 844 | struct ccdc_a_law *alaw = &ccdc_cfg.bayer.config_params.alaw; |
838 | &ccdc_hw_params_raw.config_params.alaw; | ||
839 | u32 pixfmt; | 845 | u32 pixfmt; |
840 | 846 | ||
841 | if (ccdc_if_type == VPFE_RAW_BAYER) | 847 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
842 | if (alaw->enable) | 848 | if (alaw->enable) |
843 | pixfmt = V4L2_PIX_FMT_SBGGR8; | 849 | pixfmt = V4L2_PIX_FMT_SBGGR8; |
844 | else | 850 | else |
845 | pixfmt = V4L2_PIX_FMT_SBGGR16; | 851 | pixfmt = V4L2_PIX_FMT_SBGGR16; |
846 | else { | 852 | else { |
847 | if (ccdc_hw_params_ycbcr.pix_order == CCDC_PIXORDER_YCBYCR) | 853 | if (ccdc_cfg.ycbcr.pix_order == CCDC_PIXORDER_YCBYCR) |
848 | pixfmt = V4L2_PIX_FMT_YUYV; | 854 | pixfmt = V4L2_PIX_FMT_YUYV; |
849 | else | 855 | else |
850 | pixfmt = V4L2_PIX_FMT_UYVY; | 856 | pixfmt = V4L2_PIX_FMT_UYVY; |
@@ -853,53 +859,53 @@ static u32 ccdc_get_pixel_format(void) | |||
853 | } | 859 | } |
854 | static int ccdc_set_image_window(struct v4l2_rect *win) | 860 | static int ccdc_set_image_window(struct v4l2_rect *win) |
855 | { | 861 | { |
856 | if (ccdc_if_type == VPFE_RAW_BAYER) | 862 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
857 | ccdc_hw_params_raw.win = *win; | 863 | ccdc_cfg.bayer.win = *win; |
858 | else | 864 | else |
859 | ccdc_hw_params_ycbcr.win = *win; | 865 | ccdc_cfg.ycbcr.win = *win; |
860 | return 0; | 866 | return 0; |
861 | } | 867 | } |
862 | 868 | ||
863 | static void ccdc_get_image_window(struct v4l2_rect *win) | 869 | static void ccdc_get_image_window(struct v4l2_rect *win) |
864 | { | 870 | { |
865 | if (ccdc_if_type == VPFE_RAW_BAYER) | 871 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
866 | *win = ccdc_hw_params_raw.win; | 872 | *win = ccdc_cfg.bayer.win; |
867 | else | 873 | else |
868 | *win = ccdc_hw_params_ycbcr.win; | 874 | *win = ccdc_cfg.ycbcr.win; |
869 | } | 875 | } |
870 | 876 | ||
871 | static unsigned int ccdc_get_line_length(void) | 877 | static unsigned int ccdc_get_line_length(void) |
872 | { | 878 | { |
873 | struct ccdc_config_params_raw *config_params = | 879 | struct ccdc_config_params_raw *config_params = |
874 | &ccdc_hw_params_raw.config_params; | 880 | &ccdc_cfg.bayer.config_params; |
875 | unsigned int len; | 881 | unsigned int len; |
876 | 882 | ||
877 | if (ccdc_if_type == VPFE_RAW_BAYER) { | 883 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) { |
878 | if ((config_params->alaw.enable) || | 884 | if ((config_params->alaw.enable) || |
879 | (config_params->data_sz == CCDC_DATA_8BITS)) | 885 | (config_params->data_sz == CCDC_DATA_8BITS)) |
880 | len = ccdc_hw_params_raw.win.width; | 886 | len = ccdc_cfg.bayer.win.width; |
881 | else | 887 | else |
882 | len = ccdc_hw_params_raw.win.width * 2; | 888 | len = ccdc_cfg.bayer.win.width * 2; |
883 | } else | 889 | } else |
884 | len = ccdc_hw_params_ycbcr.win.width * 2; | 890 | len = ccdc_cfg.ycbcr.win.width * 2; |
885 | return ALIGN(len, 32); | 891 | return ALIGN(len, 32); |
886 | } | 892 | } |
887 | 893 | ||
888 | static int ccdc_set_frame_format(enum ccdc_frmfmt frm_fmt) | 894 | static int ccdc_set_frame_format(enum ccdc_frmfmt frm_fmt) |
889 | { | 895 | { |
890 | if (ccdc_if_type == VPFE_RAW_BAYER) | 896 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
891 | ccdc_hw_params_raw.frm_fmt = frm_fmt; | 897 | ccdc_cfg.bayer.frm_fmt = frm_fmt; |
892 | else | 898 | else |
893 | ccdc_hw_params_ycbcr.frm_fmt = frm_fmt; | 899 | ccdc_cfg.ycbcr.frm_fmt = frm_fmt; |
894 | return 0; | 900 | return 0; |
895 | } | 901 | } |
896 | 902 | ||
897 | static enum ccdc_frmfmt ccdc_get_frame_format(void) | 903 | static enum ccdc_frmfmt ccdc_get_frame_format(void) |
898 | { | 904 | { |
899 | if (ccdc_if_type == VPFE_RAW_BAYER) | 905 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
900 | return ccdc_hw_params_raw.frm_fmt; | 906 | return ccdc_cfg.bayer.frm_fmt; |
901 | else | 907 | else |
902 | return ccdc_hw_params_ycbcr.frm_fmt; | 908 | return ccdc_cfg.ycbcr.frm_fmt; |
903 | } | 909 | } |
904 | 910 | ||
905 | static int ccdc_getfid(void) | 911 | static int ccdc_getfid(void) |
@@ -916,14 +922,14 @@ static inline void ccdc_setfbaddr(unsigned long addr) | |||
916 | 922 | ||
917 | static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params) | 923 | static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params) |
918 | { | 924 | { |
919 | ccdc_if_type = params->if_type; | 925 | ccdc_cfg.if_type = params->if_type; |
920 | 926 | ||
921 | switch (params->if_type) { | 927 | switch (params->if_type) { |
922 | case VPFE_BT656: | 928 | case VPFE_BT656: |
923 | case VPFE_YCBCR_SYNC_16: | 929 | case VPFE_YCBCR_SYNC_16: |
924 | case VPFE_YCBCR_SYNC_8: | 930 | case VPFE_YCBCR_SYNC_8: |
925 | ccdc_hw_params_ycbcr.vd_pol = params->vdpol; | 931 | ccdc_cfg.ycbcr.vd_pol = params->vdpol; |
926 | ccdc_hw_params_ycbcr.hd_pol = params->hdpol; | 932 | ccdc_cfg.ycbcr.hd_pol = params->hdpol; |
927 | break; | 933 | break; |
928 | default: | 934 | default: |
929 | /* TODO add support for raw bayer here */ | 935 | /* TODO add support for raw bayer here */ |
@@ -938,7 +944,6 @@ static struct ccdc_hw_device ccdc_hw_dev = { | |||
938 | .hw_ops = { | 944 | .hw_ops = { |
939 | .open = ccdc_open, | 945 | .open = ccdc_open, |
940 | .close = ccdc_close, | 946 | .close = ccdc_close, |
941 | .set_ccdc_base = ccdc_set_ccdc_base, | ||
942 | .enable = ccdc_enable, | 947 | .enable = ccdc_enable, |
943 | .enable_out_to_sdram = ccdc_enable_output_to_sdram, | 948 | .enable_out_to_sdram = ccdc_enable_output_to_sdram, |
944 | .set_hw_if_params = ccdc_set_hw_if_params, | 949 | .set_hw_if_params = ccdc_set_hw_if_params, |
@@ -959,19 +964,118 @@ static struct ccdc_hw_device ccdc_hw_dev = { | |||
959 | }, | 964 | }, |
960 | }; | 965 | }; |
961 | 966 | ||
962 | static int __init dm355_ccdc_init(void) | 967 | static int __init dm355_ccdc_probe(struct platform_device *pdev) |
963 | { | 968 | { |
964 | printk(KERN_NOTICE "dm355_ccdc_init\n"); | 969 | void (*setup_pinmux)(void); |
965 | if (vpfe_register_ccdc_device(&ccdc_hw_dev) < 0) | 970 | struct resource *res; |
966 | return -1; | 971 | int status = 0; |
967 | printk(KERN_NOTICE "%s is registered with vpfe.\n", | 972 | |
968 | ccdc_hw_dev.name); | 973 | /* |
974 | * first try to register with vpfe. If not correct platform, then we | ||
975 | * don't have to iomap | ||
976 | */ | ||
977 | status = vpfe_register_ccdc_device(&ccdc_hw_dev); | ||
978 | if (status < 0) | ||
979 | return status; | ||
980 | |||
981 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
982 | if (!res) { | ||
983 | status = -ENODEV; | ||
984 | goto fail_nores; | ||
985 | } | ||
986 | |||
987 | res = request_mem_region(res->start, resource_size(res), res->name); | ||
988 | if (!res) { | ||
989 | status = -EBUSY; | ||
990 | goto fail_nores; | ||
991 | } | ||
992 | |||
993 | ccdc_cfg.base_addr = ioremap_nocache(res->start, resource_size(res)); | ||
994 | if (!ccdc_cfg.base_addr) { | ||
995 | status = -ENOMEM; | ||
996 | goto fail_nomem; | ||
997 | } | ||
998 | |||
999 | /* Get and enable Master clock */ | ||
1000 | ccdc_cfg.mclk = clk_get(&pdev->dev, "master"); | ||
1001 | if (IS_ERR(ccdc_cfg.mclk)) { | ||
1002 | status = PTR_ERR(ccdc_cfg.mclk); | ||
1003 | goto fail_nomap; | ||
1004 | } | ||
1005 | if (clk_enable(ccdc_cfg.mclk)) { | ||
1006 | status = -ENODEV; | ||
1007 | goto fail_mclk; | ||
1008 | } | ||
1009 | |||
1010 | /* Get and enable Slave clock */ | ||
1011 | ccdc_cfg.sclk = clk_get(&pdev->dev, "slave"); | ||
1012 | if (IS_ERR(ccdc_cfg.sclk)) { | ||
1013 | status = PTR_ERR(ccdc_cfg.sclk); | ||
1014 | goto fail_mclk; | ||
1015 | } | ||
1016 | if (clk_enable(ccdc_cfg.sclk)) { | ||
1017 | status = -ENODEV; | ||
1018 | goto fail_sclk; | ||
1019 | } | ||
1020 | |||
1021 | /* Platform data holds setup_pinmux function ptr */ | ||
1022 | if (NULL == pdev->dev.platform_data) { | ||
1023 | status = -ENODEV; | ||
1024 | goto fail_sclk; | ||
1025 | } | ||
1026 | setup_pinmux = pdev->dev.platform_data; | ||
1027 | /* | ||
1028 | * setup Mux configuration for ccdc which may be different for | ||
1029 | * different SoCs using this CCDC | ||
1030 | */ | ||
1031 | setup_pinmux(); | ||
1032 | ccdc_cfg.dev = &pdev->dev; | ||
1033 | printk(KERN_NOTICE "%s is registered with vpfe.\n", ccdc_hw_dev.name); | ||
969 | return 0; | 1034 | return 0; |
1035 | fail_sclk: | ||
1036 | clk_put(ccdc_cfg.sclk); | ||
1037 | fail_mclk: | ||
1038 | clk_put(ccdc_cfg.mclk); | ||
1039 | fail_nomap: | ||
1040 | iounmap(ccdc_cfg.base_addr); | ||
1041 | fail_nomem: | ||
1042 | release_mem_region(res->start, resource_size(res)); | ||
1043 | fail_nores: | ||
1044 | vpfe_unregister_ccdc_device(&ccdc_hw_dev); | ||
1045 | return status; | ||
970 | } | 1046 | } |
971 | 1047 | ||
972 | static void __exit dm355_ccdc_exit(void) | 1048 | static int dm355_ccdc_remove(struct platform_device *pdev) |
973 | { | 1049 | { |
1050 | struct resource *res; | ||
1051 | |||
1052 | clk_put(ccdc_cfg.mclk); | ||
1053 | clk_put(ccdc_cfg.sclk); | ||
1054 | iounmap(ccdc_cfg.base_addr); | ||
1055 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1056 | if (res) | ||
1057 | release_mem_region(res->start, resource_size(res)); | ||
974 | vpfe_unregister_ccdc_device(&ccdc_hw_dev); | 1058 | vpfe_unregister_ccdc_device(&ccdc_hw_dev); |
1059 | return 0; | ||
1060 | } | ||
1061 | |||
1062 | static struct platform_driver dm355_ccdc_driver = { | ||
1063 | .driver = { | ||
1064 | .name = "dm355_ccdc", | ||
1065 | .owner = THIS_MODULE, | ||
1066 | }, | ||
1067 | .remove = __devexit_p(dm355_ccdc_remove), | ||
1068 | .probe = dm355_ccdc_probe, | ||
1069 | }; | ||
1070 | |||
1071 | static int __init dm355_ccdc_init(void) | ||
1072 | { | ||
1073 | return platform_driver_register(&dm355_ccdc_driver); | ||
1074 | } | ||
1075 | |||
1076 | static void __exit dm355_ccdc_exit(void) | ||
1077 | { | ||
1078 | platform_driver_unregister(&dm355_ccdc_driver); | ||
975 | } | 1079 | } |
976 | 1080 | ||
977 | module_init(dm355_ccdc_init); | 1081 | module_init(dm355_ccdc_init); |
diff --git a/drivers/media/video/davinci/dm644x_ccdc.c b/drivers/media/video/davinci/dm644x_ccdc.c index d5fa193f32d2..0c394cade22a 100644 --- a/drivers/media/video/davinci/dm644x_ccdc.c +++ b/drivers/media/video/davinci/dm644x_ccdc.c | |||
@@ -37,8 +37,12 @@ | |||
37 | #include <linux/platform_device.h> | 37 | #include <linux/platform_device.h> |
38 | #include <linux/uaccess.h> | 38 | #include <linux/uaccess.h> |
39 | #include <linux/videodev2.h> | 39 | #include <linux/videodev2.h> |
40 | #include <linux/clk.h> | ||
41 | #include <linux/err.h> | ||
42 | |||
40 | #include <media/davinci/dm644x_ccdc.h> | 43 | #include <media/davinci/dm644x_ccdc.h> |
41 | #include <media/davinci/vpss.h> | 44 | #include <media/davinci/vpss.h> |
45 | |||
42 | #include "dm644x_ccdc_regs.h" | 46 | #include "dm644x_ccdc_regs.h" |
43 | #include "ccdc_hw_device.h" | 47 | #include "ccdc_hw_device.h" |
44 | 48 | ||
@@ -46,32 +50,44 @@ MODULE_LICENSE("GPL"); | |||
46 | MODULE_DESCRIPTION("CCDC Driver for DM6446"); | 50 | MODULE_DESCRIPTION("CCDC Driver for DM6446"); |
47 | MODULE_AUTHOR("Texas Instruments"); | 51 | MODULE_AUTHOR("Texas Instruments"); |
48 | 52 | ||
49 | static struct device *dev; | 53 | static struct ccdc_oper_config { |
50 | 54 | struct device *dev; | |
51 | /* Object for CCDC raw mode */ | 55 | /* CCDC interface type */ |
52 | static struct ccdc_params_raw ccdc_hw_params_raw = { | 56 | enum vpfe_hw_if_type if_type; |
53 | .pix_fmt = CCDC_PIXFMT_RAW, | 57 | /* Raw Bayer configuration */ |
54 | .frm_fmt = CCDC_FRMFMT_PROGRESSIVE, | 58 | struct ccdc_params_raw bayer; |
55 | .win = CCDC_WIN_VGA, | 59 | /* YCbCr configuration */ |
56 | .fid_pol = VPFE_PINPOL_POSITIVE, | 60 | struct ccdc_params_ycbcr ycbcr; |
57 | .vd_pol = VPFE_PINPOL_POSITIVE, | 61 | /* Master clock */ |
58 | .hd_pol = VPFE_PINPOL_POSITIVE, | 62 | struct clk *mclk; |
59 | .config_params = { | 63 | /* slave clock */ |
60 | .data_sz = CCDC_DATA_10BITS, | 64 | struct clk *sclk; |
65 | /* ccdc base address */ | ||
66 | void __iomem *base_addr; | ||
67 | } ccdc_cfg = { | ||
68 | /* Raw configurations */ | ||
69 | .bayer = { | ||
70 | .pix_fmt = CCDC_PIXFMT_RAW, | ||
71 | .frm_fmt = CCDC_FRMFMT_PROGRESSIVE, | ||
72 | .win = CCDC_WIN_VGA, | ||
73 | .fid_pol = VPFE_PINPOL_POSITIVE, | ||
74 | .vd_pol = VPFE_PINPOL_POSITIVE, | ||
75 | .hd_pol = VPFE_PINPOL_POSITIVE, | ||
76 | .config_params = { | ||
77 | .data_sz = CCDC_DATA_10BITS, | ||
78 | }, | ||
79 | }, | ||
80 | .ycbcr = { | ||
81 | .pix_fmt = CCDC_PIXFMT_YCBCR_8BIT, | ||
82 | .frm_fmt = CCDC_FRMFMT_INTERLACED, | ||
83 | .win = CCDC_WIN_PAL, | ||
84 | .fid_pol = VPFE_PINPOL_POSITIVE, | ||
85 | .vd_pol = VPFE_PINPOL_POSITIVE, | ||
86 | .hd_pol = VPFE_PINPOL_POSITIVE, | ||
87 | .bt656_enable = 1, | ||
88 | .pix_order = CCDC_PIXORDER_CBYCRY, | ||
89 | .buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED | ||
61 | }, | 90 | }, |
62 | }; | ||
63 | |||
64 | /* Object for CCDC ycbcr mode */ | ||
65 | static struct ccdc_params_ycbcr ccdc_hw_params_ycbcr = { | ||
66 | .pix_fmt = CCDC_PIXFMT_YCBCR_8BIT, | ||
67 | .frm_fmt = CCDC_FRMFMT_INTERLACED, | ||
68 | .win = CCDC_WIN_PAL, | ||
69 | .fid_pol = VPFE_PINPOL_POSITIVE, | ||
70 | .vd_pol = VPFE_PINPOL_POSITIVE, | ||
71 | .hd_pol = VPFE_PINPOL_POSITIVE, | ||
72 | .bt656_enable = 1, | ||
73 | .pix_order = CCDC_PIXORDER_CBYCRY, | ||
74 | .buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED | ||
75 | }; | 91 | }; |
76 | 92 | ||
77 | #define CCDC_MAX_RAW_YUV_FORMATS 2 | 93 | #define CCDC_MAX_RAW_YUV_FORMATS 2 |
@@ -84,25 +100,15 @@ static u32 ccdc_raw_bayer_pix_formats[] = | |||
84 | static u32 ccdc_raw_yuv_pix_formats[] = | 100 | static u32 ccdc_raw_yuv_pix_formats[] = |
85 | {V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_YUYV}; | 101 | {V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_YUYV}; |
86 | 102 | ||
87 | static void *__iomem ccdc_base_addr; | ||
88 | static int ccdc_addr_size; | ||
89 | static enum vpfe_hw_if_type ccdc_if_type; | ||
90 | |||
91 | /* register access routines */ | 103 | /* register access routines */ |
92 | static inline u32 regr(u32 offset) | 104 | static inline u32 regr(u32 offset) |
93 | { | 105 | { |
94 | return __raw_readl(ccdc_base_addr + offset); | 106 | return __raw_readl(ccdc_cfg.base_addr + offset); |
95 | } | 107 | } |
96 | 108 | ||
97 | static inline void regw(u32 val, u32 offset) | 109 | static inline void regw(u32 val, u32 offset) |
98 | { | 110 | { |
99 | __raw_writel(val, ccdc_base_addr + offset); | 111 | __raw_writel(val, ccdc_cfg.base_addr + offset); |
100 | } | ||
101 | |||
102 | static void ccdc_set_ccdc_base(void *addr, int size) | ||
103 | { | ||
104 | ccdc_base_addr = addr; | ||
105 | ccdc_addr_size = size; | ||
106 | } | 112 | } |
107 | 113 | ||
108 | static void ccdc_enable(int flag) | 114 | static void ccdc_enable(int flag) |
@@ -132,7 +138,7 @@ void ccdc_setwin(struct v4l2_rect *image_win, | |||
132 | int vert_start, vert_nr_lines; | 138 | int vert_start, vert_nr_lines; |
133 | int val = 0, mid_img = 0; | 139 | int val = 0, mid_img = 0; |
134 | 140 | ||
135 | dev_dbg(dev, "\nStarting ccdc_setwin..."); | 141 | dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_setwin..."); |
136 | /* | 142 | /* |
137 | * ppc - per pixel count. indicates how many pixels per cell | 143 | * ppc - per pixel count. indicates how many pixels per cell |
138 | * output to SDRAM. example, for ycbcr, it is one y and one c, so 2. | 144 | * output to SDRAM. example, for ycbcr, it is one y and one c, so 2. |
@@ -171,7 +177,7 @@ void ccdc_setwin(struct v4l2_rect *image_win, | |||
171 | regw((vert_start << CCDC_VERT_START_SLV0_SHIFT) | vert_start, | 177 | regw((vert_start << CCDC_VERT_START_SLV0_SHIFT) | vert_start, |
172 | CCDC_VERT_START); | 178 | CCDC_VERT_START); |
173 | regw(vert_nr_lines, CCDC_VERT_LINES); | 179 | regw(vert_nr_lines, CCDC_VERT_LINES); |
174 | dev_dbg(dev, "\nEnd of ccdc_setwin..."); | 180 | dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_setwin..."); |
175 | } | 181 | } |
176 | 182 | ||
177 | static void ccdc_readregs(void) | 183 | static void ccdc_readregs(void) |
@@ -179,39 +185,39 @@ static void ccdc_readregs(void) | |||
179 | unsigned int val = 0; | 185 | unsigned int val = 0; |
180 | 186 | ||
181 | val = regr(CCDC_ALAW); | 187 | val = regr(CCDC_ALAW); |
182 | dev_notice(dev, "\nReading 0x%x to ALAW...\n", val); | 188 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to ALAW...\n", val); |
183 | val = regr(CCDC_CLAMP); | 189 | val = regr(CCDC_CLAMP); |
184 | dev_notice(dev, "\nReading 0x%x to CLAMP...\n", val); | 190 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to CLAMP...\n", val); |
185 | val = regr(CCDC_DCSUB); | 191 | val = regr(CCDC_DCSUB); |
186 | dev_notice(dev, "\nReading 0x%x to DCSUB...\n", val); | 192 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to DCSUB...\n", val); |
187 | val = regr(CCDC_BLKCMP); | 193 | val = regr(CCDC_BLKCMP); |
188 | dev_notice(dev, "\nReading 0x%x to BLKCMP...\n", val); | 194 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to BLKCMP...\n", val); |
189 | val = regr(CCDC_FPC_ADDR); | 195 | val = regr(CCDC_FPC_ADDR); |
190 | dev_notice(dev, "\nReading 0x%x to FPC_ADDR...\n", val); | 196 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FPC_ADDR...\n", val); |
191 | val = regr(CCDC_FPC); | 197 | val = regr(CCDC_FPC); |
192 | dev_notice(dev, "\nReading 0x%x to FPC...\n", val); | 198 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FPC...\n", val); |
193 | val = regr(CCDC_FMTCFG); | 199 | val = regr(CCDC_FMTCFG); |
194 | dev_notice(dev, "\nReading 0x%x to FMTCFG...\n", val); | 200 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FMTCFG...\n", val); |
195 | val = regr(CCDC_COLPTN); | 201 | val = regr(CCDC_COLPTN); |
196 | dev_notice(dev, "\nReading 0x%x to COLPTN...\n", val); | 202 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to COLPTN...\n", val); |
197 | val = regr(CCDC_FMT_HORZ); | 203 | val = regr(CCDC_FMT_HORZ); |
198 | dev_notice(dev, "\nReading 0x%x to FMT_HORZ...\n", val); | 204 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FMT_HORZ...\n", val); |
199 | val = regr(CCDC_FMT_VERT); | 205 | val = regr(CCDC_FMT_VERT); |
200 | dev_notice(dev, "\nReading 0x%x to FMT_VERT...\n", val); | 206 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FMT_VERT...\n", val); |
201 | val = regr(CCDC_HSIZE_OFF); | 207 | val = regr(CCDC_HSIZE_OFF); |
202 | dev_notice(dev, "\nReading 0x%x to HSIZE_OFF...\n", val); | 208 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to HSIZE_OFF...\n", val); |
203 | val = regr(CCDC_SDOFST); | 209 | val = regr(CCDC_SDOFST); |
204 | dev_notice(dev, "\nReading 0x%x to SDOFST...\n", val); | 210 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to SDOFST...\n", val); |
205 | val = regr(CCDC_VP_OUT); | 211 | val = regr(CCDC_VP_OUT); |
206 | dev_notice(dev, "\nReading 0x%x to VP_OUT...\n", val); | 212 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to VP_OUT...\n", val); |
207 | val = regr(CCDC_SYN_MODE); | 213 | val = regr(CCDC_SYN_MODE); |
208 | dev_notice(dev, "\nReading 0x%x to SYN_MODE...\n", val); | 214 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to SYN_MODE...\n", val); |
209 | val = regr(CCDC_HORZ_INFO); | 215 | val = regr(CCDC_HORZ_INFO); |
210 | dev_notice(dev, "\nReading 0x%x to HORZ_INFO...\n", val); | 216 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to HORZ_INFO...\n", val); |
211 | val = regr(CCDC_VERT_START); | 217 | val = regr(CCDC_VERT_START); |
212 | dev_notice(dev, "\nReading 0x%x to VERT_START...\n", val); | 218 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to VERT_START...\n", val); |
213 | val = regr(CCDC_VERT_LINES); | 219 | val = regr(CCDC_VERT_LINES); |
214 | dev_notice(dev, "\nReading 0x%x to VERT_LINES...\n", val); | 220 | dev_notice(ccdc_cfg.dev, "\nReading 0x%x to VERT_LINES...\n", val); |
215 | } | 221 | } |
216 | 222 | ||
217 | static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam) | 223 | static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam) |
@@ -220,7 +226,7 @@ static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam) | |||
220 | if ((ccdcparam->alaw.gama_wd > CCDC_GAMMA_BITS_09_0) || | 226 | if ((ccdcparam->alaw.gama_wd > CCDC_GAMMA_BITS_09_0) || |
221 | (ccdcparam->alaw.gama_wd < CCDC_GAMMA_BITS_15_6) || | 227 | (ccdcparam->alaw.gama_wd < CCDC_GAMMA_BITS_15_6) || |
222 | (ccdcparam->alaw.gama_wd < ccdcparam->data_sz)) { | 228 | (ccdcparam->alaw.gama_wd < ccdcparam->data_sz)) { |
223 | dev_dbg(dev, "\nInvalid data line select"); | 229 | dev_dbg(ccdc_cfg.dev, "\nInvalid data line select"); |
224 | return -1; | 230 | return -1; |
225 | } | 231 | } |
226 | } | 232 | } |
@@ -230,7 +236,7 @@ static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam) | |||
230 | static int ccdc_update_raw_params(struct ccdc_config_params_raw *raw_params) | 236 | static int ccdc_update_raw_params(struct ccdc_config_params_raw *raw_params) |
231 | { | 237 | { |
232 | struct ccdc_config_params_raw *config_params = | 238 | struct ccdc_config_params_raw *config_params = |
233 | &ccdc_hw_params_raw.config_params; | 239 | &ccdc_cfg.bayer.config_params; |
234 | unsigned int *fpc_virtaddr = NULL; | 240 | unsigned int *fpc_virtaddr = NULL; |
235 | unsigned int *fpc_physaddr = NULL; | 241 | unsigned int *fpc_physaddr = NULL; |
236 | 242 | ||
@@ -266,7 +272,7 @@ static int ccdc_update_raw_params(struct ccdc_config_params_raw *raw_params) | |||
266 | FP_NUM_BYTES)); | 272 | FP_NUM_BYTES)); |
267 | 273 | ||
268 | if (fpc_virtaddr == NULL) { | 274 | if (fpc_virtaddr == NULL) { |
269 | dev_dbg(dev, | 275 | dev_dbg(ccdc_cfg.dev, |
270 | "\nUnable to allocate memory for FPC"); | 276 | "\nUnable to allocate memory for FPC"); |
271 | return -EFAULT; | 277 | return -EFAULT; |
272 | } | 278 | } |
@@ -279,7 +285,7 @@ static int ccdc_update_raw_params(struct ccdc_config_params_raw *raw_params) | |||
279 | if (copy_from_user(fpc_virtaddr, | 285 | if (copy_from_user(fpc_virtaddr, |
280 | (void __user *)raw_params->fault_pxl.fpc_table_addr, | 286 | (void __user *)raw_params->fault_pxl.fpc_table_addr, |
281 | config_params->fault_pxl.fp_num * FP_NUM_BYTES)) { | 287 | config_params->fault_pxl.fp_num * FP_NUM_BYTES)) { |
282 | dev_dbg(dev, "\n copy_from_user failed"); | 288 | dev_dbg(ccdc_cfg.dev, "\n copy_from_user failed"); |
283 | return -EFAULT; | 289 | return -EFAULT; |
284 | } | 290 | } |
285 | config_params->fault_pxl.fpc_table_addr = (unsigned int)fpc_physaddr; | 291 | config_params->fault_pxl.fpc_table_addr = (unsigned int)fpc_physaddr; |
@@ -289,7 +295,7 @@ static int ccdc_update_raw_params(struct ccdc_config_params_raw *raw_params) | |||
289 | static int ccdc_close(struct device *dev) | 295 | static int ccdc_close(struct device *dev) |
290 | { | 296 | { |
291 | struct ccdc_config_params_raw *config_params = | 297 | struct ccdc_config_params_raw *config_params = |
292 | &ccdc_hw_params_raw.config_params; | 298 | &ccdc_cfg.bayer.config_params; |
293 | unsigned int *fpc_physaddr = NULL, *fpc_virtaddr = NULL; | 299 | unsigned int *fpc_physaddr = NULL, *fpc_virtaddr = NULL; |
294 | 300 | ||
295 | fpc_physaddr = (unsigned int *)config_params->fault_pxl.fpc_table_addr; | 301 | fpc_physaddr = (unsigned int *)config_params->fault_pxl.fpc_table_addr; |
@@ -323,9 +329,8 @@ static void ccdc_restore_defaults(void) | |||
323 | 329 | ||
324 | static int ccdc_open(struct device *device) | 330 | static int ccdc_open(struct device *device) |
325 | { | 331 | { |
326 | dev = device; | ||
327 | ccdc_restore_defaults(); | 332 | ccdc_restore_defaults(); |
328 | if (ccdc_if_type == VPFE_RAW_BAYER) | 333 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
329 | ccdc_enable_vport(1); | 334 | ccdc_enable_vport(1); |
330 | return 0; | 335 | return 0; |
331 | } | 336 | } |
@@ -341,12 +346,12 @@ static int ccdc_set_params(void __user *params) | |||
341 | struct ccdc_config_params_raw ccdc_raw_params; | 346 | struct ccdc_config_params_raw ccdc_raw_params; |
342 | int x; | 347 | int x; |
343 | 348 | ||
344 | if (ccdc_if_type != VPFE_RAW_BAYER) | 349 | if (ccdc_cfg.if_type != VPFE_RAW_BAYER) |
345 | return -EINVAL; | 350 | return -EINVAL; |
346 | 351 | ||
347 | x = copy_from_user(&ccdc_raw_params, params, sizeof(ccdc_raw_params)); | 352 | x = copy_from_user(&ccdc_raw_params, params, sizeof(ccdc_raw_params)); |
348 | if (x) { | 353 | if (x) { |
349 | dev_dbg(dev, "ccdc_set_params: error in copying" | 354 | dev_dbg(ccdc_cfg.dev, "ccdc_set_params: error in copying" |
350 | "ccdc params, %d\n", x); | 355 | "ccdc params, %d\n", x); |
351 | return -EFAULT; | 356 | return -EFAULT; |
352 | } | 357 | } |
@@ -364,10 +369,10 @@ static int ccdc_set_params(void __user *params) | |||
364 | */ | 369 | */ |
365 | void ccdc_config_ycbcr(void) | 370 | void ccdc_config_ycbcr(void) |
366 | { | 371 | { |
367 | struct ccdc_params_ycbcr *params = &ccdc_hw_params_ycbcr; | 372 | struct ccdc_params_ycbcr *params = &ccdc_cfg.ycbcr; |
368 | u32 syn_mode; | 373 | u32 syn_mode; |
369 | 374 | ||
370 | dev_dbg(dev, "\nStarting ccdc_config_ycbcr..."); | 375 | dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_config_ycbcr..."); |
371 | /* | 376 | /* |
372 | * first restore the CCDC registers to default values | 377 | * first restore the CCDC registers to default values |
373 | * This is important since we assume default values to be set in | 378 | * This is important since we assume default values to be set in |
@@ -428,7 +433,7 @@ void ccdc_config_ycbcr(void) | |||
428 | regw(CCDC_SDOFST_FIELD_INTERLEAVED, CCDC_SDOFST); | 433 | regw(CCDC_SDOFST_FIELD_INTERLEAVED, CCDC_SDOFST); |
429 | 434 | ||
430 | ccdc_sbl_reset(); | 435 | ccdc_sbl_reset(); |
431 | dev_dbg(dev, "\nEnd of ccdc_config_ycbcr...\n"); | 436 | dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_config_ycbcr...\n"); |
432 | ccdc_readregs(); | 437 | ccdc_readregs(); |
433 | } | 438 | } |
434 | 439 | ||
@@ -440,9 +445,9 @@ static void ccdc_config_black_clamp(struct ccdc_black_clamp *bclamp) | |||
440 | /* configure DCSub */ | 445 | /* configure DCSub */ |
441 | val = (bclamp->dc_sub) & CCDC_BLK_DC_SUB_MASK; | 446 | val = (bclamp->dc_sub) & CCDC_BLK_DC_SUB_MASK; |
442 | regw(val, CCDC_DCSUB); | 447 | regw(val, CCDC_DCSUB); |
443 | dev_dbg(dev, "\nWriting 0x%x to DCSUB...\n", val); | 448 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to DCSUB...\n", val); |
444 | regw(CCDC_CLAMP_DEFAULT_VAL, CCDC_CLAMP); | 449 | regw(CCDC_CLAMP_DEFAULT_VAL, CCDC_CLAMP); |
445 | dev_dbg(dev, "\nWriting 0x0000 to CLAMP...\n"); | 450 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x0000 to CLAMP...\n"); |
446 | return; | 451 | return; |
447 | } | 452 | } |
448 | /* | 453 | /* |
@@ -457,10 +462,10 @@ static void ccdc_config_black_clamp(struct ccdc_black_clamp *bclamp) | |||
457 | ((bclamp->sample_pixel & CCDC_BLK_SAMPLE_LN_MASK) << | 462 | ((bclamp->sample_pixel & CCDC_BLK_SAMPLE_LN_MASK) << |
458 | CCDC_BLK_SAMPLE_LN_SHIFT) | CCDC_BLK_CLAMP_ENABLE); | 463 | CCDC_BLK_SAMPLE_LN_SHIFT) | CCDC_BLK_CLAMP_ENABLE); |
459 | regw(val, CCDC_CLAMP); | 464 | regw(val, CCDC_CLAMP); |
460 | dev_dbg(dev, "\nWriting 0x%x to CLAMP...\n", val); | 465 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to CLAMP...\n", val); |
461 | /* If Black clamping is enable then make dcsub 0 */ | 466 | /* If Black clamping is enable then make dcsub 0 */ |
462 | regw(CCDC_DCSUB_DEFAULT_VAL, CCDC_DCSUB); | 467 | regw(CCDC_DCSUB_DEFAULT_VAL, CCDC_DCSUB); |
463 | dev_dbg(dev, "\nWriting 0x00000000 to DCSUB...\n"); | 468 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x00000000 to DCSUB...\n"); |
464 | } | 469 | } |
465 | 470 | ||
466 | static void ccdc_config_black_compense(struct ccdc_black_compensation *bcomp) | 471 | static void ccdc_config_black_compense(struct ccdc_black_compensation *bcomp) |
@@ -490,17 +495,17 @@ static void ccdc_config_fpc(struct ccdc_fault_pixel *fpc) | |||
490 | 495 | ||
491 | /* Configure Fault pixel if needed */ | 496 | /* Configure Fault pixel if needed */ |
492 | regw(fpc->fpc_table_addr, CCDC_FPC_ADDR); | 497 | regw(fpc->fpc_table_addr, CCDC_FPC_ADDR); |
493 | dev_dbg(dev, "\nWriting 0x%x to FPC_ADDR...\n", | 498 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FPC_ADDR...\n", |
494 | (fpc->fpc_table_addr)); | 499 | (fpc->fpc_table_addr)); |
495 | /* Write the FPC params with FPC disable */ | 500 | /* Write the FPC params with FPC disable */ |
496 | val = fpc->fp_num & CCDC_FPC_FPC_NUM_MASK; | 501 | val = fpc->fp_num & CCDC_FPC_FPC_NUM_MASK; |
497 | regw(val, CCDC_FPC); | 502 | regw(val, CCDC_FPC); |
498 | 503 | ||
499 | dev_dbg(dev, "\nWriting 0x%x to FPC...\n", val); | 504 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FPC...\n", val); |
500 | /* read the FPC register */ | 505 | /* read the FPC register */ |
501 | val = regr(CCDC_FPC) | CCDC_FPC_ENABLE; | 506 | val = regr(CCDC_FPC) | CCDC_FPC_ENABLE; |
502 | regw(val, CCDC_FPC); | 507 | regw(val, CCDC_FPC); |
503 | dev_dbg(dev, "\nWriting 0x%x to FPC...\n", val); | 508 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FPC...\n", val); |
504 | } | 509 | } |
505 | 510 | ||
506 | /* | 511 | /* |
@@ -509,13 +514,13 @@ static void ccdc_config_fpc(struct ccdc_fault_pixel *fpc) | |||
509 | */ | 514 | */ |
510 | void ccdc_config_raw(void) | 515 | void ccdc_config_raw(void) |
511 | { | 516 | { |
512 | struct ccdc_params_raw *params = &ccdc_hw_params_raw; | 517 | struct ccdc_params_raw *params = &ccdc_cfg.bayer; |
513 | struct ccdc_config_params_raw *config_params = | 518 | struct ccdc_config_params_raw *config_params = |
514 | &ccdc_hw_params_raw.config_params; | 519 | &ccdc_cfg.bayer.config_params; |
515 | unsigned int syn_mode = 0; | 520 | unsigned int syn_mode = 0; |
516 | unsigned int val; | 521 | unsigned int val; |
517 | 522 | ||
518 | dev_dbg(dev, "\nStarting ccdc_config_raw..."); | 523 | dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_config_raw..."); |
519 | 524 | ||
520 | /* Reset CCDC */ | 525 | /* Reset CCDC */ |
521 | ccdc_restore_defaults(); | 526 | ccdc_restore_defaults(); |
@@ -545,7 +550,7 @@ void ccdc_config_raw(void) | |||
545 | val = ((config_params->alaw.gama_wd & | 550 | val = ((config_params->alaw.gama_wd & |
546 | CCDC_ALAW_GAMA_WD_MASK) | CCDC_ALAW_ENABLE); | 551 | CCDC_ALAW_GAMA_WD_MASK) | CCDC_ALAW_ENABLE); |
547 | regw(val, CCDC_ALAW); | 552 | regw(val, CCDC_ALAW); |
548 | dev_dbg(dev, "\nWriting 0x%x to ALAW...\n", val); | 553 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to ALAW...\n", val); |
549 | } | 554 | } |
550 | 555 | ||
551 | /* Configure video window */ | 556 | /* Configure video window */ |
@@ -582,11 +587,11 @@ void ccdc_config_raw(void) | |||
582 | /* Write value in FMTCFG */ | 587 | /* Write value in FMTCFG */ |
583 | regw(val, CCDC_FMTCFG); | 588 | regw(val, CCDC_FMTCFG); |
584 | 589 | ||
585 | dev_dbg(dev, "\nWriting 0x%x to FMTCFG...\n", val); | 590 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FMTCFG...\n", val); |
586 | /* Configure the color pattern according to mt9t001 sensor */ | 591 | /* Configure the color pattern according to mt9t001 sensor */ |
587 | regw(CCDC_COLPTN_VAL, CCDC_COLPTN); | 592 | regw(CCDC_COLPTN_VAL, CCDC_COLPTN); |
588 | 593 | ||
589 | dev_dbg(dev, "\nWriting 0xBB11BB11 to COLPTN...\n"); | 594 | dev_dbg(ccdc_cfg.dev, "\nWriting 0xBB11BB11 to COLPTN...\n"); |
590 | /* | 595 | /* |
591 | * Configure Data formatter(Video port) pixel selection | 596 | * Configure Data formatter(Video port) pixel selection |
592 | * (FMT_HORZ, FMT_VERT) | 597 | * (FMT_HORZ, FMT_VERT) |
@@ -596,7 +601,7 @@ void ccdc_config_raw(void) | |||
596 | (params->win.width & CCDC_FMT_HORZ_FMTLNH_MASK); | 601 | (params->win.width & CCDC_FMT_HORZ_FMTLNH_MASK); |
597 | regw(val, CCDC_FMT_HORZ); | 602 | regw(val, CCDC_FMT_HORZ); |
598 | 603 | ||
599 | dev_dbg(dev, "\nWriting 0x%x to FMT_HORZ...\n", val); | 604 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FMT_HORZ...\n", val); |
600 | val = (params->win.top & CCDC_FMT_VERT_FMTSLV_MASK) | 605 | val = (params->win.top & CCDC_FMT_VERT_FMTSLV_MASK) |
601 | << CCDC_FMT_VERT_FMTSLV_SHIFT; | 606 | << CCDC_FMT_VERT_FMTSLV_SHIFT; |
602 | if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) | 607 | if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) |
@@ -604,13 +609,13 @@ void ccdc_config_raw(void) | |||
604 | else | 609 | else |
605 | val |= (params->win.height >> 1) & CCDC_FMT_VERT_FMTLNV_MASK; | 610 | val |= (params->win.height >> 1) & CCDC_FMT_VERT_FMTLNV_MASK; |
606 | 611 | ||
607 | dev_dbg(dev, "\nparams->win.height 0x%x ...\n", | 612 | dev_dbg(ccdc_cfg.dev, "\nparams->win.height 0x%x ...\n", |
608 | params->win.height); | 613 | params->win.height); |
609 | regw(val, CCDC_FMT_VERT); | 614 | regw(val, CCDC_FMT_VERT); |
610 | 615 | ||
611 | dev_dbg(dev, "\nWriting 0x%x to FMT_VERT...\n", val); | 616 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FMT_VERT...\n", val); |
612 | 617 | ||
613 | dev_dbg(dev, "\nbelow regw(val, FMT_VERT)..."); | 618 | dev_dbg(ccdc_cfg.dev, "\nbelow regw(val, FMT_VERT)..."); |
614 | 619 | ||
615 | /* | 620 | /* |
616 | * Configure Horizontal offset register. If pack 8 is enabled then | 621 | * Configure Horizontal offset register. If pack 8 is enabled then |
@@ -631,17 +636,17 @@ void ccdc_config_raw(void) | |||
631 | if (params->image_invert_enable) { | 636 | if (params->image_invert_enable) { |
632 | /* For intelace inverse mode */ | 637 | /* For intelace inverse mode */ |
633 | regw(CCDC_INTERLACED_IMAGE_INVERT, CCDC_SDOFST); | 638 | regw(CCDC_INTERLACED_IMAGE_INVERT, CCDC_SDOFST); |
634 | dev_dbg(dev, "\nWriting 0x4B6D to SDOFST...\n"); | 639 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x4B6D to SDOFST..\n"); |
635 | } | 640 | } |
636 | 641 | ||
637 | else { | 642 | else { |
638 | /* For intelace non inverse mode */ | 643 | /* For intelace non inverse mode */ |
639 | regw(CCDC_INTERLACED_NO_IMAGE_INVERT, CCDC_SDOFST); | 644 | regw(CCDC_INTERLACED_NO_IMAGE_INVERT, CCDC_SDOFST); |
640 | dev_dbg(dev, "\nWriting 0x0249 to SDOFST...\n"); | 645 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x0249 to SDOFST..\n"); |
641 | } | 646 | } |
642 | } else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) { | 647 | } else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) { |
643 | regw(CCDC_PROGRESSIVE_NO_IMAGE_INVERT, CCDC_SDOFST); | 648 | regw(CCDC_PROGRESSIVE_NO_IMAGE_INVERT, CCDC_SDOFST); |
644 | dev_dbg(dev, "\nWriting 0x0000 to SDOFST...\n"); | 649 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x0000 to SDOFST...\n"); |
645 | } | 650 | } |
646 | 651 | ||
647 | /* | 652 | /* |
@@ -662,18 +667,18 @@ void ccdc_config_raw(void) | |||
662 | val |= (params->win.left) & CCDC_VP_OUT_HORZ_ST_MASK; | 667 | val |= (params->win.left) & CCDC_VP_OUT_HORZ_ST_MASK; |
663 | regw(val, CCDC_VP_OUT); | 668 | regw(val, CCDC_VP_OUT); |
664 | 669 | ||
665 | dev_dbg(dev, "\nWriting 0x%x to VP_OUT...\n", val); | 670 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to VP_OUT...\n", val); |
666 | regw(syn_mode, CCDC_SYN_MODE); | 671 | regw(syn_mode, CCDC_SYN_MODE); |
667 | dev_dbg(dev, "\nWriting 0x%x to SYN_MODE...\n", syn_mode); | 672 | dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to SYN_MODE...\n", syn_mode); |
668 | 673 | ||
669 | ccdc_sbl_reset(); | 674 | ccdc_sbl_reset(); |
670 | dev_dbg(dev, "\nend of ccdc_config_raw..."); | 675 | dev_dbg(ccdc_cfg.dev, "\nend of ccdc_config_raw..."); |
671 | ccdc_readregs(); | 676 | ccdc_readregs(); |
672 | } | 677 | } |
673 | 678 | ||
674 | static int ccdc_configure(void) | 679 | static int ccdc_configure(void) |
675 | { | 680 | { |
676 | if (ccdc_if_type == VPFE_RAW_BAYER) | 681 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
677 | ccdc_config_raw(); | 682 | ccdc_config_raw(); |
678 | else | 683 | else |
679 | ccdc_config_ycbcr(); | 684 | ccdc_config_ycbcr(); |
@@ -682,24 +687,24 @@ static int ccdc_configure(void) | |||
682 | 687 | ||
683 | static int ccdc_set_buftype(enum ccdc_buftype buf_type) | 688 | static int ccdc_set_buftype(enum ccdc_buftype buf_type) |
684 | { | 689 | { |
685 | if (ccdc_if_type == VPFE_RAW_BAYER) | 690 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
686 | ccdc_hw_params_raw.buf_type = buf_type; | 691 | ccdc_cfg.bayer.buf_type = buf_type; |
687 | else | 692 | else |
688 | ccdc_hw_params_ycbcr.buf_type = buf_type; | 693 | ccdc_cfg.ycbcr.buf_type = buf_type; |
689 | return 0; | 694 | return 0; |
690 | } | 695 | } |
691 | 696 | ||
692 | static enum ccdc_buftype ccdc_get_buftype(void) | 697 | static enum ccdc_buftype ccdc_get_buftype(void) |
693 | { | 698 | { |
694 | if (ccdc_if_type == VPFE_RAW_BAYER) | 699 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
695 | return ccdc_hw_params_raw.buf_type; | 700 | return ccdc_cfg.bayer.buf_type; |
696 | return ccdc_hw_params_ycbcr.buf_type; | 701 | return ccdc_cfg.ycbcr.buf_type; |
697 | } | 702 | } |
698 | 703 | ||
699 | static int ccdc_enum_pix(u32 *pix, int i) | 704 | static int ccdc_enum_pix(u32 *pix, int i) |
700 | { | 705 | { |
701 | int ret = -EINVAL; | 706 | int ret = -EINVAL; |
702 | if (ccdc_if_type == VPFE_RAW_BAYER) { | 707 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) { |
703 | if (i < ARRAY_SIZE(ccdc_raw_bayer_pix_formats)) { | 708 | if (i < ARRAY_SIZE(ccdc_raw_bayer_pix_formats)) { |
704 | *pix = ccdc_raw_bayer_pix_formats[i]; | 709 | *pix = ccdc_raw_bayer_pix_formats[i]; |
705 | ret = 0; | 710 | ret = 0; |
@@ -715,17 +720,17 @@ static int ccdc_enum_pix(u32 *pix, int i) | |||
715 | 720 | ||
716 | static int ccdc_set_pixel_format(u32 pixfmt) | 721 | static int ccdc_set_pixel_format(u32 pixfmt) |
717 | { | 722 | { |
718 | if (ccdc_if_type == VPFE_RAW_BAYER) { | 723 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) { |
719 | ccdc_hw_params_raw.pix_fmt = CCDC_PIXFMT_RAW; | 724 | ccdc_cfg.bayer.pix_fmt = CCDC_PIXFMT_RAW; |
720 | if (pixfmt == V4L2_PIX_FMT_SBGGR8) | 725 | if (pixfmt == V4L2_PIX_FMT_SBGGR8) |
721 | ccdc_hw_params_raw.config_params.alaw.enable = 1; | 726 | ccdc_cfg.bayer.config_params.alaw.enable = 1; |
722 | else if (pixfmt != V4L2_PIX_FMT_SBGGR16) | 727 | else if (pixfmt != V4L2_PIX_FMT_SBGGR16) |
723 | return -EINVAL; | 728 | return -EINVAL; |
724 | } else { | 729 | } else { |
725 | if (pixfmt == V4L2_PIX_FMT_YUYV) | 730 | if (pixfmt == V4L2_PIX_FMT_YUYV) |
726 | ccdc_hw_params_ycbcr.pix_order = CCDC_PIXORDER_YCBYCR; | 731 | ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_YCBYCR; |
727 | else if (pixfmt == V4L2_PIX_FMT_UYVY) | 732 | else if (pixfmt == V4L2_PIX_FMT_UYVY) |
728 | ccdc_hw_params_ycbcr.pix_order = CCDC_PIXORDER_CBYCRY; | 733 | ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY; |
729 | else | 734 | else |
730 | return -EINVAL; | 735 | return -EINVAL; |
731 | } | 736 | } |
@@ -734,17 +739,16 @@ static int ccdc_set_pixel_format(u32 pixfmt) | |||
734 | 739 | ||
735 | static u32 ccdc_get_pixel_format(void) | 740 | static u32 ccdc_get_pixel_format(void) |
736 | { | 741 | { |
737 | struct ccdc_a_law *alaw = | 742 | struct ccdc_a_law *alaw = &ccdc_cfg.bayer.config_params.alaw; |
738 | &ccdc_hw_params_raw.config_params.alaw; | ||
739 | u32 pixfmt; | 743 | u32 pixfmt; |
740 | 744 | ||
741 | if (ccdc_if_type == VPFE_RAW_BAYER) | 745 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
742 | if (alaw->enable) | 746 | if (alaw->enable) |
743 | pixfmt = V4L2_PIX_FMT_SBGGR8; | 747 | pixfmt = V4L2_PIX_FMT_SBGGR8; |
744 | else | 748 | else |
745 | pixfmt = V4L2_PIX_FMT_SBGGR16; | 749 | pixfmt = V4L2_PIX_FMT_SBGGR16; |
746 | else { | 750 | else { |
747 | if (ccdc_hw_params_ycbcr.pix_order == CCDC_PIXORDER_YCBYCR) | 751 | if (ccdc_cfg.ycbcr.pix_order == CCDC_PIXORDER_YCBYCR) |
748 | pixfmt = V4L2_PIX_FMT_YUYV; | 752 | pixfmt = V4L2_PIX_FMT_YUYV; |
749 | else | 753 | else |
750 | pixfmt = V4L2_PIX_FMT_UYVY; | 754 | pixfmt = V4L2_PIX_FMT_UYVY; |
@@ -754,53 +758,53 @@ static u32 ccdc_get_pixel_format(void) | |||
754 | 758 | ||
755 | static int ccdc_set_image_window(struct v4l2_rect *win) | 759 | static int ccdc_set_image_window(struct v4l2_rect *win) |
756 | { | 760 | { |
757 | if (ccdc_if_type == VPFE_RAW_BAYER) | 761 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
758 | ccdc_hw_params_raw.win = *win; | 762 | ccdc_cfg.bayer.win = *win; |
759 | else | 763 | else |
760 | ccdc_hw_params_ycbcr.win = *win; | 764 | ccdc_cfg.ycbcr.win = *win; |
761 | return 0; | 765 | return 0; |
762 | } | 766 | } |
763 | 767 | ||
764 | static void ccdc_get_image_window(struct v4l2_rect *win) | 768 | static void ccdc_get_image_window(struct v4l2_rect *win) |
765 | { | 769 | { |
766 | if (ccdc_if_type == VPFE_RAW_BAYER) | 770 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
767 | *win = ccdc_hw_params_raw.win; | 771 | *win = ccdc_cfg.bayer.win; |
768 | else | 772 | else |
769 | *win = ccdc_hw_params_ycbcr.win; | 773 | *win = ccdc_cfg.ycbcr.win; |
770 | } | 774 | } |
771 | 775 | ||
772 | static unsigned int ccdc_get_line_length(void) | 776 | static unsigned int ccdc_get_line_length(void) |
773 | { | 777 | { |
774 | struct ccdc_config_params_raw *config_params = | 778 | struct ccdc_config_params_raw *config_params = |
775 | &ccdc_hw_params_raw.config_params; | 779 | &ccdc_cfg.bayer.config_params; |
776 | unsigned int len; | 780 | unsigned int len; |
777 | 781 | ||
778 | if (ccdc_if_type == VPFE_RAW_BAYER) { | 782 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) { |
779 | if ((config_params->alaw.enable) || | 783 | if ((config_params->alaw.enable) || |
780 | (config_params->data_sz == CCDC_DATA_8BITS)) | 784 | (config_params->data_sz == CCDC_DATA_8BITS)) |
781 | len = ccdc_hw_params_raw.win.width; | 785 | len = ccdc_cfg.bayer.win.width; |
782 | else | 786 | else |
783 | len = ccdc_hw_params_raw.win.width * 2; | 787 | len = ccdc_cfg.bayer.win.width * 2; |
784 | } else | 788 | } else |
785 | len = ccdc_hw_params_ycbcr.win.width * 2; | 789 | len = ccdc_cfg.ycbcr.win.width * 2; |
786 | return ALIGN(len, 32); | 790 | return ALIGN(len, 32); |
787 | } | 791 | } |
788 | 792 | ||
789 | static int ccdc_set_frame_format(enum ccdc_frmfmt frm_fmt) | 793 | static int ccdc_set_frame_format(enum ccdc_frmfmt frm_fmt) |
790 | { | 794 | { |
791 | if (ccdc_if_type == VPFE_RAW_BAYER) | 795 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
792 | ccdc_hw_params_raw.frm_fmt = frm_fmt; | 796 | ccdc_cfg.bayer.frm_fmt = frm_fmt; |
793 | else | 797 | else |
794 | ccdc_hw_params_ycbcr.frm_fmt = frm_fmt; | 798 | ccdc_cfg.ycbcr.frm_fmt = frm_fmt; |
795 | return 0; | 799 | return 0; |
796 | } | 800 | } |
797 | 801 | ||
798 | static enum ccdc_frmfmt ccdc_get_frame_format(void) | 802 | static enum ccdc_frmfmt ccdc_get_frame_format(void) |
799 | { | 803 | { |
800 | if (ccdc_if_type == VPFE_RAW_BAYER) | 804 | if (ccdc_cfg.if_type == VPFE_RAW_BAYER) |
801 | return ccdc_hw_params_raw.frm_fmt; | 805 | return ccdc_cfg.bayer.frm_fmt; |
802 | else | 806 | else |
803 | return ccdc_hw_params_ycbcr.frm_fmt; | 807 | return ccdc_cfg.ycbcr.frm_fmt; |
804 | } | 808 | } |
805 | 809 | ||
806 | static int ccdc_getfid(void) | 810 | static int ccdc_getfid(void) |
@@ -816,14 +820,14 @@ static inline void ccdc_setfbaddr(unsigned long addr) | |||
816 | 820 | ||
817 | static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params) | 821 | static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params) |
818 | { | 822 | { |
819 | ccdc_if_type = params->if_type; | 823 | ccdc_cfg.if_type = params->if_type; |
820 | 824 | ||
821 | switch (params->if_type) { | 825 | switch (params->if_type) { |
822 | case VPFE_BT656: | 826 | case VPFE_BT656: |
823 | case VPFE_YCBCR_SYNC_16: | 827 | case VPFE_YCBCR_SYNC_16: |
824 | case VPFE_YCBCR_SYNC_8: | 828 | case VPFE_YCBCR_SYNC_8: |
825 | ccdc_hw_params_ycbcr.vd_pol = params->vdpol; | 829 | ccdc_cfg.ycbcr.vd_pol = params->vdpol; |
826 | ccdc_hw_params_ycbcr.hd_pol = params->hdpol; | 830 | ccdc_cfg.ycbcr.hd_pol = params->hdpol; |
827 | break; | 831 | break; |
828 | default: | 832 | default: |
829 | /* TODO add support for raw bayer here */ | 833 | /* TODO add support for raw bayer here */ |
@@ -838,7 +842,6 @@ static struct ccdc_hw_device ccdc_hw_dev = { | |||
838 | .hw_ops = { | 842 | .hw_ops = { |
839 | .open = ccdc_open, | 843 | .open = ccdc_open, |
840 | .close = ccdc_close, | 844 | .close = ccdc_close, |
841 | .set_ccdc_base = ccdc_set_ccdc_base, | ||
842 | .reset = ccdc_sbl_reset, | 845 | .reset = ccdc_sbl_reset, |
843 | .enable = ccdc_enable, | 846 | .enable = ccdc_enable, |
844 | .set_hw_if_params = ccdc_set_hw_if_params, | 847 | .set_hw_if_params = ccdc_set_hw_if_params, |
@@ -859,19 +862,105 @@ static struct ccdc_hw_device ccdc_hw_dev = { | |||
859 | }, | 862 | }, |
860 | }; | 863 | }; |
861 | 864 | ||
862 | static int __init dm644x_ccdc_init(void) | 865 | static int __init dm644x_ccdc_probe(struct platform_device *pdev) |
863 | { | 866 | { |
864 | printk(KERN_NOTICE "dm644x_ccdc_init\n"); | 867 | struct resource *res; |
865 | if (vpfe_register_ccdc_device(&ccdc_hw_dev) < 0) | 868 | int status = 0; |
866 | return -1; | 869 | |
867 | printk(KERN_NOTICE "%s is registered with vpfe.\n", | 870 | /* |
868 | ccdc_hw_dev.name); | 871 | * first try to register with vpfe. If not correct platform, then we |
872 | * don't have to iomap | ||
873 | */ | ||
874 | status = vpfe_register_ccdc_device(&ccdc_hw_dev); | ||
875 | if (status < 0) | ||
876 | return status; | ||
877 | |||
878 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
879 | if (!res) { | ||
880 | status = -ENODEV; | ||
881 | goto fail_nores; | ||
882 | } | ||
883 | |||
884 | res = request_mem_region(res->start, resource_size(res), res->name); | ||
885 | if (!res) { | ||
886 | status = -EBUSY; | ||
887 | goto fail_nores; | ||
888 | } | ||
889 | |||
890 | ccdc_cfg.base_addr = ioremap_nocache(res->start, resource_size(res)); | ||
891 | if (!ccdc_cfg.base_addr) { | ||
892 | status = -ENOMEM; | ||
893 | goto fail_nomem; | ||
894 | } | ||
895 | |||
896 | /* Get and enable Master clock */ | ||
897 | ccdc_cfg.mclk = clk_get(&pdev->dev, "master"); | ||
898 | if (IS_ERR(ccdc_cfg.mclk)) { | ||
899 | status = PTR_ERR(ccdc_cfg.mclk); | ||
900 | goto fail_nomap; | ||
901 | } | ||
902 | if (clk_enable(ccdc_cfg.mclk)) { | ||
903 | status = -ENODEV; | ||
904 | goto fail_mclk; | ||
905 | } | ||
906 | |||
907 | /* Get and enable Slave clock */ | ||
908 | ccdc_cfg.sclk = clk_get(&pdev->dev, "slave"); | ||
909 | if (IS_ERR(ccdc_cfg.sclk)) { | ||
910 | status = PTR_ERR(ccdc_cfg.sclk); | ||
911 | goto fail_mclk; | ||
912 | } | ||
913 | if (clk_enable(ccdc_cfg.sclk)) { | ||
914 | status = -ENODEV; | ||
915 | goto fail_sclk; | ||
916 | } | ||
917 | ccdc_cfg.dev = &pdev->dev; | ||
918 | printk(KERN_NOTICE "%s is registered with vpfe.\n", ccdc_hw_dev.name); | ||
869 | return 0; | 919 | return 0; |
920 | fail_sclk: | ||
921 | clk_put(ccdc_cfg.sclk); | ||
922 | fail_mclk: | ||
923 | clk_put(ccdc_cfg.mclk); | ||
924 | fail_nomap: | ||
925 | iounmap(ccdc_cfg.base_addr); | ||
926 | fail_nomem: | ||
927 | release_mem_region(res->start, resource_size(res)); | ||
928 | fail_nores: | ||
929 | vpfe_unregister_ccdc_device(&ccdc_hw_dev); | ||
930 | return status; | ||
870 | } | 931 | } |
871 | 932 | ||
872 | static void __exit dm644x_ccdc_exit(void) | 933 | static int dm644x_ccdc_remove(struct platform_device *pdev) |
873 | { | 934 | { |
935 | struct resource *res; | ||
936 | |||
937 | clk_put(ccdc_cfg.mclk); | ||
938 | clk_put(ccdc_cfg.sclk); | ||
939 | iounmap(ccdc_cfg.base_addr); | ||
940 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
941 | if (res) | ||
942 | release_mem_region(res->start, resource_size(res)); | ||
874 | vpfe_unregister_ccdc_device(&ccdc_hw_dev); | 943 | vpfe_unregister_ccdc_device(&ccdc_hw_dev); |
944 | return 0; | ||
945 | } | ||
946 | |||
947 | static struct platform_driver dm644x_ccdc_driver = { | ||
948 | .driver = { | ||
949 | .name = "dm644x_ccdc", | ||
950 | .owner = THIS_MODULE, | ||
951 | }, | ||
952 | .remove = __devexit_p(dm644x_ccdc_remove), | ||
953 | .probe = dm644x_ccdc_probe, | ||
954 | }; | ||
955 | |||
956 | static int __init dm644x_ccdc_init(void) | ||
957 | { | ||
958 | return platform_driver_register(&dm644x_ccdc_driver); | ||
959 | } | ||
960 | |||
961 | static void __exit dm644x_ccdc_exit(void) | ||
962 | { | ||
963 | platform_driver_unregister(&dm644x_ccdc_driver); | ||
875 | } | 964 | } |
876 | 965 | ||
877 | module_init(dm644x_ccdc_init); | 966 | module_init(dm644x_ccdc_init); |
diff --git a/drivers/media/video/davinci/isif.c b/drivers/media/video/davinci/isif.c new file mode 100644 index 000000000000..29c29c668596 --- /dev/null +++ b/drivers/media/video/davinci/isif.c | |||
@@ -0,0 +1,1172 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008-2009 Texas Instruments Inc | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | * | ||
18 | * Image Sensor Interface (ISIF) driver | ||
19 | * | ||
20 | * This driver is for configuring the ISIF IP available on DM365 or any other | ||
21 | * TI SoCs. This is used for capturing yuv or bayer video or image data | ||
22 | * from a decoder or sensor. This IP is similar to the CCDC IP on DM355 | ||
23 | * and DM6446, but with enhanced or additional ip blocks. The driver | ||
24 | * configures the ISIF upon commands from the vpfe bridge driver through | ||
25 | * ccdc_hw_device interface. | ||
26 | * | ||
27 | * TODO: 1) Raw bayer parameter settings and bayer capture | ||
28 | * 2) Add support for control ioctl | ||
29 | */ | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/platform_device.h> | ||
32 | #include <linux/uaccess.h> | ||
33 | #include <linux/io.h> | ||
34 | #include <linux/videodev2.h> | ||
35 | #include <linux/clk.h> | ||
36 | #include <linux/err.h> | ||
37 | |||
38 | #include <mach/mux.h> | ||
39 | |||
40 | #include <media/davinci/isif.h> | ||
41 | #include <media/davinci/vpss.h> | ||
42 | |||
43 | #include "isif_regs.h" | ||
44 | #include "ccdc_hw_device.h" | ||
45 | |||
46 | /* Defaults for module configuration parameters */ | ||
47 | static struct isif_config_params_raw isif_config_defaults = { | ||
48 | .linearize = { | ||
49 | .en = 0, | ||
50 | .corr_shft = ISIF_NO_SHIFT, | ||
51 | .scale_fact = {1, 0}, | ||
52 | }, | ||
53 | .df_csc = { | ||
54 | .df_or_csc = 0, | ||
55 | .csc = { | ||
56 | .en = 0, | ||
57 | }, | ||
58 | }, | ||
59 | .dfc = { | ||
60 | .en = 0, | ||
61 | }, | ||
62 | .bclamp = { | ||
63 | .en = 0, | ||
64 | }, | ||
65 | .gain_offset = { | ||
66 | .gain = { | ||
67 | .r_ye = {1, 0}, | ||
68 | .gr_cy = {1, 0}, | ||
69 | .gb_g = {1, 0}, | ||
70 | .b_mg = {1, 0}, | ||
71 | }, | ||
72 | }, | ||
73 | .culling = { | ||
74 | .hcpat_odd = 0xff, | ||
75 | .hcpat_even = 0xff, | ||
76 | .vcpat = 0xff, | ||
77 | }, | ||
78 | .compress = { | ||
79 | .alg = ISIF_ALAW, | ||
80 | }, | ||
81 | }; | ||
82 | |||
83 | /* ISIF operation configuration */ | ||
84 | static struct isif_oper_config { | ||
85 | struct device *dev; | ||
86 | enum vpfe_hw_if_type if_type; | ||
87 | struct isif_ycbcr_config ycbcr; | ||
88 | struct isif_params_raw bayer; | ||
89 | enum isif_data_pack data_pack; | ||
90 | /* Master clock */ | ||
91 | struct clk *mclk; | ||
92 | /* ISIF base address */ | ||
93 | void __iomem *base_addr; | ||
94 | /* ISIF Linear Table 0 */ | ||
95 | void __iomem *linear_tbl0_addr; | ||
96 | /* ISIF Linear Table 1 */ | ||
97 | void __iomem *linear_tbl1_addr; | ||
98 | } isif_cfg = { | ||
99 | .ycbcr = { | ||
100 | .pix_fmt = CCDC_PIXFMT_YCBCR_8BIT, | ||
101 | .frm_fmt = CCDC_FRMFMT_INTERLACED, | ||
102 | .win = ISIF_WIN_NTSC, | ||
103 | .fid_pol = VPFE_PINPOL_POSITIVE, | ||
104 | .vd_pol = VPFE_PINPOL_POSITIVE, | ||
105 | .hd_pol = VPFE_PINPOL_POSITIVE, | ||
106 | .pix_order = CCDC_PIXORDER_CBYCRY, | ||
107 | .buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED, | ||
108 | }, | ||
109 | .bayer = { | ||
110 | .pix_fmt = CCDC_PIXFMT_RAW, | ||
111 | .frm_fmt = CCDC_FRMFMT_PROGRESSIVE, | ||
112 | .win = ISIF_WIN_VGA, | ||
113 | .fid_pol = VPFE_PINPOL_POSITIVE, | ||
114 | .vd_pol = VPFE_PINPOL_POSITIVE, | ||
115 | .hd_pol = VPFE_PINPOL_POSITIVE, | ||
116 | .gain = { | ||
117 | .r_ye = {1, 0}, | ||
118 | .gr_cy = {1, 0}, | ||
119 | .gb_g = {1, 0}, | ||
120 | .b_mg = {1, 0}, | ||
121 | }, | ||
122 | .cfa_pat = ISIF_CFA_PAT_MOSAIC, | ||
123 | .data_msb = ISIF_BIT_MSB_11, | ||
124 | .config_params = { | ||
125 | .data_shift = ISIF_NO_SHIFT, | ||
126 | .col_pat_field0 = { | ||
127 | .olop = ISIF_GREEN_BLUE, | ||
128 | .olep = ISIF_BLUE, | ||
129 | .elop = ISIF_RED, | ||
130 | .elep = ISIF_GREEN_RED, | ||
131 | }, | ||
132 | .col_pat_field1 = { | ||
133 | .olop = ISIF_GREEN_BLUE, | ||
134 | .olep = ISIF_BLUE, | ||
135 | .elop = ISIF_RED, | ||
136 | .elep = ISIF_GREEN_RED, | ||
137 | }, | ||
138 | .test_pat_gen = 0, | ||
139 | }, | ||
140 | }, | ||
141 | .data_pack = ISIF_DATA_PACK8, | ||
142 | }; | ||
143 | |||
144 | /* Raw Bayer formats */ | ||
145 | static const u32 isif_raw_bayer_pix_formats[] = { | ||
146 | V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SBGGR16}; | ||
147 | |||
148 | /* Raw YUV formats */ | ||
149 | static const u32 isif_raw_yuv_pix_formats[] = { | ||
150 | V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_YUYV}; | ||
151 | |||
152 | /* register access routines */ | ||
153 | static inline u32 regr(u32 offset) | ||
154 | { | ||
155 | return __raw_readl(isif_cfg.base_addr + offset); | ||
156 | } | ||
157 | |||
158 | static inline void regw(u32 val, u32 offset) | ||
159 | { | ||
160 | __raw_writel(val, isif_cfg.base_addr + offset); | ||
161 | } | ||
162 | |||
163 | /* reg_modify() - read, modify and write register */ | ||
164 | static inline u32 reg_modify(u32 mask, u32 val, u32 offset) | ||
165 | { | ||
166 | u32 new_val = (regr(offset) & ~mask) | (val & mask); | ||
167 | |||
168 | regw(new_val, offset); | ||
169 | return new_val; | ||
170 | } | ||
171 | |||
172 | static inline void regw_lin_tbl(u32 val, u32 offset, int i) | ||
173 | { | ||
174 | if (!i) | ||
175 | __raw_writel(val, isif_cfg.linear_tbl0_addr + offset); | ||
176 | else | ||
177 | __raw_writel(val, isif_cfg.linear_tbl1_addr + offset); | ||
178 | } | ||
179 | |||
180 | static void isif_disable_all_modules(void) | ||
181 | { | ||
182 | /* disable BC */ | ||
183 | regw(0, CLAMPCFG); | ||
184 | /* disable vdfc */ | ||
185 | regw(0, DFCCTL); | ||
186 | /* disable CSC */ | ||
187 | regw(0, CSCCTL); | ||
188 | /* disable linearization */ | ||
189 | regw(0, LINCFG0); | ||
190 | /* disable other modules here as they are supported */ | ||
191 | } | ||
192 | |||
193 | static void isif_enable(int en) | ||
194 | { | ||
195 | if (!en) { | ||
196 | /* Before disable isif, disable all ISIF modules */ | ||
197 | isif_disable_all_modules(); | ||
198 | /* | ||
199 | * wait for next VD. Assume lowest scan rate is 12 Hz. So | ||
200 | * 100 msec delay is good enough | ||
201 | */ | ||
202 | msleep(100); | ||
203 | } | ||
204 | reg_modify(ISIF_SYNCEN_VDHDEN_MASK, en, SYNCEN); | ||
205 | } | ||
206 | |||
207 | static void isif_enable_output_to_sdram(int en) | ||
208 | { | ||
209 | reg_modify(ISIF_SYNCEN_WEN_MASK, en << ISIF_SYNCEN_WEN_SHIFT, SYNCEN); | ||
210 | } | ||
211 | |||
212 | static void isif_config_culling(struct isif_cul *cul) | ||
213 | { | ||
214 | u32 val; | ||
215 | |||
216 | /* Horizontal pattern */ | ||
217 | val = (cul->hcpat_even << CULL_PAT_EVEN_LINE_SHIFT) | cul->hcpat_odd; | ||
218 | regw(val, CULH); | ||
219 | |||
220 | /* vertical pattern */ | ||
221 | regw(cul->vcpat, CULV); | ||
222 | |||
223 | /* LPF */ | ||
224 | reg_modify(ISIF_LPF_MASK << ISIF_LPF_SHIFT, | ||
225 | cul->en_lpf << ISIF_LPF_SHIFT, MODESET); | ||
226 | } | ||
227 | |||
228 | static void isif_config_gain_offset(void) | ||
229 | { | ||
230 | struct isif_gain_offsets_adj *gain_off_p = | ||
231 | &isif_cfg.bayer.config_params.gain_offset; | ||
232 | u32 val; | ||
233 | |||
234 | val = (!!gain_off_p->gain_sdram_en << GAIN_SDRAM_EN_SHIFT) | | ||
235 | (!!gain_off_p->gain_ipipe_en << GAIN_IPIPE_EN_SHIFT) | | ||
236 | (!!gain_off_p->gain_h3a_en << GAIN_H3A_EN_SHIFT) | | ||
237 | (!!gain_off_p->offset_sdram_en << OFST_SDRAM_EN_SHIFT) | | ||
238 | (!!gain_off_p->offset_ipipe_en << OFST_IPIPE_EN_SHIFT) | | ||
239 | (!!gain_off_p->offset_h3a_en << OFST_H3A_EN_SHIFT); | ||
240 | |||
241 | reg_modify(GAIN_OFFSET_EN_MASK, val, CGAMMAWD); | ||
242 | |||
243 | val = (gain_off_p->gain.r_ye.integer << GAIN_INTEGER_SHIFT) | | ||
244 | gain_off_p->gain.r_ye.decimal; | ||
245 | regw(val, CRGAIN); | ||
246 | |||
247 | val = (gain_off_p->gain.gr_cy.integer << GAIN_INTEGER_SHIFT) | | ||
248 | gain_off_p->gain.gr_cy.decimal; | ||
249 | regw(val, CGRGAIN); | ||
250 | |||
251 | val = (gain_off_p->gain.gb_g.integer << GAIN_INTEGER_SHIFT) | | ||
252 | gain_off_p->gain.gb_g.decimal; | ||
253 | regw(val, CGBGAIN); | ||
254 | |||
255 | val = (gain_off_p->gain.b_mg.integer << GAIN_INTEGER_SHIFT) | | ||
256 | gain_off_p->gain.b_mg.decimal; | ||
257 | regw(val, CBGAIN); | ||
258 | |||
259 | regw(gain_off_p->offset, COFSTA); | ||
260 | } | ||
261 | |||
262 | static void isif_restore_defaults(void) | ||
263 | { | ||
264 | enum vpss_ccdc_source_sel source = VPSS_CCDCIN; | ||
265 | |||
266 | dev_dbg(isif_cfg.dev, "\nstarting isif_restore_defaults..."); | ||
267 | isif_cfg.bayer.config_params = isif_config_defaults; | ||
268 | /* Enable clock to ISIF, IPIPEIF and BL */ | ||
269 | vpss_enable_clock(VPSS_CCDC_CLOCK, 1); | ||
270 | vpss_enable_clock(VPSS_IPIPEIF_CLOCK, 1); | ||
271 | vpss_enable_clock(VPSS_BL_CLOCK, 1); | ||
272 | /* Set default offset and gain */ | ||
273 | isif_config_gain_offset(); | ||
274 | vpss_select_ccdc_source(source); | ||
275 | dev_dbg(isif_cfg.dev, "\nEnd of isif_restore_defaults..."); | ||
276 | } | ||
277 | |||
278 | static int isif_open(struct device *device) | ||
279 | { | ||
280 | isif_restore_defaults(); | ||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | /* This function will configure the window size to be capture in ISIF reg */ | ||
285 | static void isif_setwin(struct v4l2_rect *image_win, | ||
286 | enum ccdc_frmfmt frm_fmt, int ppc) | ||
287 | { | ||
288 | int horz_start, horz_nr_pixels; | ||
289 | int vert_start, vert_nr_lines; | ||
290 | int mid_img = 0; | ||
291 | |||
292 | dev_dbg(isif_cfg.dev, "\nStarting isif_setwin..."); | ||
293 | /* | ||
294 | * ppc - per pixel count. indicates how many pixels per cell | ||
295 | * output to SDRAM. example, for ycbcr, it is one y and one c, so 2. | ||
296 | * raw capture this is 1 | ||
297 | */ | ||
298 | horz_start = image_win->left << (ppc - 1); | ||
299 | horz_nr_pixels = ((image_win->width) << (ppc - 1)) - 1; | ||
300 | |||
301 | /* Writing the horizontal info into the registers */ | ||
302 | regw(horz_start & START_PX_HOR_MASK, SPH); | ||
303 | regw(horz_nr_pixels & NUM_PX_HOR_MASK, LNH); | ||
304 | vert_start = image_win->top; | ||
305 | |||
306 | if (frm_fmt == CCDC_FRMFMT_INTERLACED) { | ||
307 | vert_nr_lines = (image_win->height >> 1) - 1; | ||
308 | vert_start >>= 1; | ||
309 | /* To account for VD since line 0 doesn't have any data */ | ||
310 | vert_start += 1; | ||
311 | } else { | ||
312 | /* To account for VD since line 0 doesn't have any data */ | ||
313 | vert_start += 1; | ||
314 | vert_nr_lines = image_win->height - 1; | ||
315 | /* configure VDINT0 and VDINT1 */ | ||
316 | mid_img = vert_start + (image_win->height / 2); | ||
317 | regw(mid_img, VDINT1); | ||
318 | } | ||
319 | |||
320 | regw(0, VDINT0); | ||
321 | regw(vert_start & START_VER_ONE_MASK, SLV0); | ||
322 | regw(vert_start & START_VER_TWO_MASK, SLV1); | ||
323 | regw(vert_nr_lines & NUM_LINES_VER, LNV); | ||
324 | } | ||
325 | |||
326 | static void isif_config_bclamp(struct isif_black_clamp *bc) | ||
327 | { | ||
328 | u32 val; | ||
329 | |||
330 | /* | ||
331 | * DC Offset is always added to image data irrespective of bc enable | ||
332 | * status | ||
333 | */ | ||
334 | regw(bc->dc_offset, CLDCOFST); | ||
335 | |||
336 | if (bc->en) { | ||
337 | val = bc->bc_mode_color << ISIF_BC_MODE_COLOR_SHIFT; | ||
338 | |||
339 | /* Enable BC and horizontal clamp caculation paramaters */ | ||
340 | val = val | 1 | (bc->horz.mode << ISIF_HORZ_BC_MODE_SHIFT); | ||
341 | |||
342 | regw(val, CLAMPCFG); | ||
343 | |||
344 | if (bc->horz.mode != ISIF_HORZ_BC_DISABLE) { | ||
345 | /* | ||
346 | * Window count for calculation | ||
347 | * Base window selection | ||
348 | * pixel limit | ||
349 | * Horizontal size of window | ||
350 | * vertical size of the window | ||
351 | * Horizontal start position of the window | ||
352 | * Vertical start position of the window | ||
353 | */ | ||
354 | val = bc->horz.win_count_calc | | ||
355 | ((!!bc->horz.base_win_sel_calc) << | ||
356 | ISIF_HORZ_BC_WIN_SEL_SHIFT) | | ||
357 | ((!!bc->horz.clamp_pix_limit) << | ||
358 | ISIF_HORZ_BC_PIX_LIMIT_SHIFT) | | ||
359 | (bc->horz.win_h_sz_calc << | ||
360 | ISIF_HORZ_BC_WIN_H_SIZE_SHIFT) | | ||
361 | (bc->horz.win_v_sz_calc << | ||
362 | ISIF_HORZ_BC_WIN_V_SIZE_SHIFT); | ||
363 | regw(val, CLHWIN0); | ||
364 | |||
365 | regw(bc->horz.win_start_h_calc, CLHWIN1); | ||
366 | regw(bc->horz.win_start_v_calc, CLHWIN2); | ||
367 | } | ||
368 | |||
369 | /* vertical clamp caculation paramaters */ | ||
370 | |||
371 | /* Reset clamp value sel for previous line */ | ||
372 | val |= | ||
373 | (bc->vert.reset_val_sel << ISIF_VERT_BC_RST_VAL_SEL_SHIFT) | | ||
374 | (bc->vert.line_ave_coef << ISIF_VERT_BC_LINE_AVE_COEF_SHIFT); | ||
375 | regw(val, CLVWIN0); | ||
376 | |||
377 | /* Optical Black horizontal start position */ | ||
378 | regw(bc->vert.ob_start_h, CLVWIN1); | ||
379 | /* Optical Black vertical start position */ | ||
380 | regw(bc->vert.ob_start_v, CLVWIN2); | ||
381 | /* Optical Black vertical size for calculation */ | ||
382 | regw(bc->vert.ob_v_sz_calc, CLVWIN3); | ||
383 | /* Vertical start position for BC subtraction */ | ||
384 | regw(bc->vert_start_sub, CLSV); | ||
385 | } | ||
386 | } | ||
387 | |||
388 | static void isif_config_linearization(struct isif_linearize *linearize) | ||
389 | { | ||
390 | u32 val, i; | ||
391 | |||
392 | if (!linearize->en) { | ||
393 | regw(0, LINCFG0); | ||
394 | return; | ||
395 | } | ||
396 | |||
397 | /* shift value for correction & enable linearization (set lsb) */ | ||
398 | val = (linearize->corr_shft << ISIF_LIN_CORRSFT_SHIFT) | 1; | ||
399 | regw(val, LINCFG0); | ||
400 | |||
401 | /* Scale factor */ | ||
402 | val = ((!!linearize->scale_fact.integer) << | ||
403 | ISIF_LIN_SCALE_FACT_INTEG_SHIFT) | | ||
404 | linearize->scale_fact.decimal; | ||
405 | regw(val, LINCFG1); | ||
406 | |||
407 | for (i = 0; i < ISIF_LINEAR_TAB_SIZE; i++) { | ||
408 | if (i % 2) | ||
409 | regw_lin_tbl(linearize->table[i], ((i >> 1) << 2), 1); | ||
410 | else | ||
411 | regw_lin_tbl(linearize->table[i], ((i >> 1) << 2), 0); | ||
412 | } | ||
413 | } | ||
414 | |||
415 | static int isif_config_dfc(struct isif_dfc *vdfc) | ||
416 | { | ||
417 | /* initialize retries to loop for max ~ 250 usec */ | ||
418 | u32 val, count, retries = loops_per_jiffy / (4000/HZ); | ||
419 | int i; | ||
420 | |||
421 | if (!vdfc->en) | ||
422 | return 0; | ||
423 | |||
424 | /* Correction mode */ | ||
425 | val = (vdfc->corr_mode << ISIF_VDFC_CORR_MOD_SHIFT); | ||
426 | |||
427 | /* Correct whole line or partial */ | ||
428 | if (vdfc->corr_whole_line) | ||
429 | val |= 1 << ISIF_VDFC_CORR_WHOLE_LN_SHIFT; | ||
430 | |||
431 | /* level shift value */ | ||
432 | val |= vdfc->def_level_shift << ISIF_VDFC_LEVEL_SHFT_SHIFT; | ||
433 | |||
434 | regw(val, DFCCTL); | ||
435 | |||
436 | /* Defect saturation level */ | ||
437 | regw(vdfc->def_sat_level, VDFSATLV); | ||
438 | |||
439 | regw(vdfc->table[0].pos_vert, DFCMEM0); | ||
440 | regw(vdfc->table[0].pos_horz, DFCMEM1); | ||
441 | if (vdfc->corr_mode == ISIF_VDFC_NORMAL || | ||
442 | vdfc->corr_mode == ISIF_VDFC_HORZ_INTERPOL_IF_SAT) { | ||
443 | regw(vdfc->table[0].level_at_pos, DFCMEM2); | ||
444 | regw(vdfc->table[0].level_up_pixels, DFCMEM3); | ||
445 | regw(vdfc->table[0].level_low_pixels, DFCMEM4); | ||
446 | } | ||
447 | |||
448 | /* set DFCMARST and set DFCMWR */ | ||
449 | val = regr(DFCMEMCTL) | (1 << ISIF_DFCMEMCTL_DFCMARST_SHIFT) | 1; | ||
450 | regw(val, DFCMEMCTL); | ||
451 | |||
452 | count = retries; | ||
453 | while (count && (regr(DFCMEMCTL) & 0x1)) | ||
454 | count--; | ||
455 | |||
456 | if (!count) { | ||
457 | dev_dbg(isif_cfg.dev, "defect table write timeout !!!\n"); | ||
458 | return -1; | ||
459 | } | ||
460 | |||
461 | for (i = 1; i < vdfc->num_vdefects; i++) { | ||
462 | regw(vdfc->table[i].pos_vert, DFCMEM0); | ||
463 | regw(vdfc->table[i].pos_horz, DFCMEM1); | ||
464 | if (vdfc->corr_mode == ISIF_VDFC_NORMAL || | ||
465 | vdfc->corr_mode == ISIF_VDFC_HORZ_INTERPOL_IF_SAT) { | ||
466 | regw(vdfc->table[i].level_at_pos, DFCMEM2); | ||
467 | regw(vdfc->table[i].level_up_pixels, DFCMEM3); | ||
468 | regw(vdfc->table[i].level_low_pixels, DFCMEM4); | ||
469 | } | ||
470 | val = regr(DFCMEMCTL); | ||
471 | /* clear DFCMARST and set DFCMWR */ | ||
472 | val &= ~BIT(ISIF_DFCMEMCTL_DFCMARST_SHIFT); | ||
473 | val |= 1; | ||
474 | regw(val, DFCMEMCTL); | ||
475 | |||
476 | count = retries; | ||
477 | while (count && (regr(DFCMEMCTL) & 0x1)) | ||
478 | count--; | ||
479 | |||
480 | if (!count) { | ||
481 | dev_err(isif_cfg.dev, | ||
482 | "defect table write timeout !!!\n"); | ||
483 | return -1; | ||
484 | } | ||
485 | } | ||
486 | if (vdfc->num_vdefects < ISIF_VDFC_TABLE_SIZE) { | ||
487 | /* Extra cycle needed */ | ||
488 | regw(0, DFCMEM0); | ||
489 | regw(0x1FFF, DFCMEM1); | ||
490 | regw(1, DFCMEMCTL); | ||
491 | } | ||
492 | |||
493 | /* enable VDFC */ | ||
494 | reg_modify((1 << ISIF_VDFC_EN_SHIFT), (1 << ISIF_VDFC_EN_SHIFT), | ||
495 | DFCCTL); | ||
496 | return 0; | ||
497 | } | ||
498 | |||
499 | static void isif_config_csc(struct isif_df_csc *df_csc) | ||
500 | { | ||
501 | u32 val1 = 0, val2 = 0, i; | ||
502 | |||
503 | if (!df_csc->csc.en) { | ||
504 | regw(0, CSCCTL); | ||
505 | return; | ||
506 | } | ||
507 | for (i = 0; i < ISIF_CSC_NUM_COEFF; i++) { | ||
508 | if ((i % 2) == 0) { | ||
509 | /* CSCM - LSB */ | ||
510 | val1 = (df_csc->csc.coeff[i].integer << | ||
511 | ISIF_CSC_COEF_INTEG_SHIFT) | | ||
512 | df_csc->csc.coeff[i].decimal; | ||
513 | } else { | ||
514 | |||
515 | /* CSCM - MSB */ | ||
516 | val2 = (df_csc->csc.coeff[i].integer << | ||
517 | ISIF_CSC_COEF_INTEG_SHIFT) | | ||
518 | df_csc->csc.coeff[i].decimal; | ||
519 | val2 <<= ISIF_CSCM_MSB_SHIFT; | ||
520 | val2 |= val1; | ||
521 | regw(val2, (CSCM0 + ((i - 1) << 1))); | ||
522 | } | ||
523 | } | ||
524 | |||
525 | /* program the active area */ | ||
526 | regw(df_csc->start_pix, FMTSPH); | ||
527 | /* | ||
528 | * one extra pixel as required for CSC. Actually number of | ||
529 | * pixel - 1 should be configured in this register. So we | ||
530 | * need to subtract 1 before writing to FMTSPH, but we will | ||
531 | * not do this since csc requires one extra pixel | ||
532 | */ | ||
533 | regw(df_csc->num_pixels, FMTLNH); | ||
534 | regw(df_csc->start_line, FMTSLV); | ||
535 | /* | ||
536 | * one extra line as required for CSC. See reason documented for | ||
537 | * num_pixels | ||
538 | */ | ||
539 | regw(df_csc->num_lines, FMTLNV); | ||
540 | |||
541 | /* Enable CSC */ | ||
542 | regw(1, CSCCTL); | ||
543 | } | ||
544 | |||
545 | static int isif_config_raw(void) | ||
546 | { | ||
547 | struct isif_params_raw *params = &isif_cfg.bayer; | ||
548 | struct isif_config_params_raw *module_params = | ||
549 | &isif_cfg.bayer.config_params; | ||
550 | struct vpss_pg_frame_size frame_size; | ||
551 | struct vpss_sync_pol sync; | ||
552 | u32 val; | ||
553 | |||
554 | dev_dbg(isif_cfg.dev, "\nStarting isif_config_raw..\n"); | ||
555 | |||
556 | /* | ||
557 | * Configure CCDCFG register:- | ||
558 | * Set CCD Not to swap input since input is RAW data | ||
559 | * Set FID detection function to Latch at V-Sync | ||
560 | * Set WENLOG - isif valid area | ||
561 | * Set TRGSEL | ||
562 | * Set EXTRG | ||
563 | * Packed to 8 or 16 bits | ||
564 | */ | ||
565 | |||
566 | val = ISIF_YCINSWP_RAW | ISIF_CCDCFG_FIDMD_LATCH_VSYNC | | ||
567 | ISIF_CCDCFG_WENLOG_AND | ISIF_CCDCFG_TRGSEL_WEN | | ||
568 | ISIF_CCDCFG_EXTRG_DISABLE | isif_cfg.data_pack; | ||
569 | |||
570 | dev_dbg(isif_cfg.dev, "Writing 0x%x to ...CCDCFG \n", val); | ||
571 | regw(val, CCDCFG); | ||
572 | |||
573 | /* | ||
574 | * Configure the vertical sync polarity(MODESET.VDPOL) | ||
575 | * Configure the horizontal sync polarity (MODESET.HDPOL) | ||
576 | * Configure frame id polarity (MODESET.FLDPOL) | ||
577 | * Configure data polarity | ||
578 | * Configure External WEN Selection | ||
579 | * Configure frame format(progressive or interlace) | ||
580 | * Configure pixel format (Input mode) | ||
581 | * Configure the data shift | ||
582 | */ | ||
583 | |||
584 | val = ISIF_VDHDOUT_INPUT | (params->vd_pol << ISIF_VD_POL_SHIFT) | | ||
585 | (params->hd_pol << ISIF_HD_POL_SHIFT) | | ||
586 | (params->fid_pol << ISIF_FID_POL_SHIFT) | | ||
587 | (ISIF_DATAPOL_NORMAL << ISIF_DATAPOL_SHIFT) | | ||
588 | (ISIF_EXWEN_DISABLE << ISIF_EXWEN_SHIFT) | | ||
589 | (params->frm_fmt << ISIF_FRM_FMT_SHIFT) | | ||
590 | (params->pix_fmt << ISIF_INPUT_SHIFT) | | ||
591 | (params->config_params.data_shift << ISIF_DATASFT_SHIFT); | ||
592 | |||
593 | regw(val, MODESET); | ||
594 | dev_dbg(isif_cfg.dev, "Writing 0x%x to MODESET...\n", val); | ||
595 | |||
596 | /* | ||
597 | * Configure GAMMAWD register | ||
598 | * CFA pattern setting | ||
599 | */ | ||
600 | val = params->cfa_pat << ISIF_GAMMAWD_CFA_SHIFT; | ||
601 | |||
602 | /* Gamma msb */ | ||
603 | if (module_params->compress.alg == ISIF_ALAW) | ||
604 | val |= ISIF_ALAW_ENABLE; | ||
605 | |||
606 | val |= (params->data_msb << ISIF_ALAW_GAMA_WD_SHIFT); | ||
607 | regw(val, CGAMMAWD); | ||
608 | |||
609 | /* Configure DPCM compression settings */ | ||
610 | if (module_params->compress.alg == ISIF_DPCM) { | ||
611 | val = BIT(ISIF_DPCM_EN_SHIFT) | | ||
612 | (module_params->compress.pred << | ||
613 | ISIF_DPCM_PREDICTOR_SHIFT); | ||
614 | } | ||
615 | |||
616 | regw(val, MISC); | ||
617 | |||
618 | /* Configure Gain & Offset */ | ||
619 | isif_config_gain_offset(); | ||
620 | |||
621 | /* Configure Color pattern */ | ||
622 | val = (params->config_params.col_pat_field0.olop) | | ||
623 | (params->config_params.col_pat_field0.olep << 2) | | ||
624 | (params->config_params.col_pat_field0.elop << 4) | | ||
625 | (params->config_params.col_pat_field0.elep << 6) | | ||
626 | (params->config_params.col_pat_field1.olop << 8) | | ||
627 | (params->config_params.col_pat_field1.olep << 10) | | ||
628 | (params->config_params.col_pat_field1.elop << 12) | | ||
629 | (params->config_params.col_pat_field1.elep << 14); | ||
630 | regw(val, CCOLP); | ||
631 | dev_dbg(isif_cfg.dev, "Writing %x to CCOLP ...\n", val); | ||
632 | |||
633 | /* Configure HSIZE register */ | ||
634 | val = (!!params->horz_flip_en) << ISIF_HSIZE_FLIP_SHIFT; | ||
635 | |||
636 | /* calculate line offset in 32 bytes based on pack value */ | ||
637 | if (isif_cfg.data_pack == ISIF_PACK_8BIT) | ||
638 | val |= ((params->win.width + 31) >> 5); | ||
639 | else if (isif_cfg.data_pack == ISIF_PACK_12BIT) | ||
640 | val |= (((params->win.width + | ||
641 | (params->win.width >> 2)) + 31) >> 5); | ||
642 | else | ||
643 | val |= (((params->win.width * 2) + 31) >> 5); | ||
644 | regw(val, HSIZE); | ||
645 | |||
646 | /* Configure SDOFST register */ | ||
647 | if (params->frm_fmt == CCDC_FRMFMT_INTERLACED) { | ||
648 | if (params->image_invert_en) { | ||
649 | /* For interlace inverse mode */ | ||
650 | regw(0x4B6D, SDOFST); | ||
651 | dev_dbg(isif_cfg.dev, "Writing 0x4B6D to SDOFST...\n"); | ||
652 | } else { | ||
653 | /* For interlace non inverse mode */ | ||
654 | regw(0x0B6D, SDOFST); | ||
655 | dev_dbg(isif_cfg.dev, "Writing 0x0B6D to SDOFST...\n"); | ||
656 | } | ||
657 | } else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) { | ||
658 | if (params->image_invert_en) { | ||
659 | /* For progressive inverse mode */ | ||
660 | regw(0x4000, SDOFST); | ||
661 | dev_dbg(isif_cfg.dev, "Writing 0x4000 to SDOFST...\n"); | ||
662 | } else { | ||
663 | /* For progressive non inverse mode */ | ||
664 | regw(0x0000, SDOFST); | ||
665 | dev_dbg(isif_cfg.dev, "Writing 0x0000 to SDOFST...\n"); | ||
666 | } | ||
667 | } | ||
668 | |||
669 | /* Configure video window */ | ||
670 | isif_setwin(¶ms->win, params->frm_fmt, 1); | ||
671 | |||
672 | /* Configure Black Clamp */ | ||
673 | isif_config_bclamp(&module_params->bclamp); | ||
674 | |||
675 | /* Configure Vertical Defection Pixel Correction */ | ||
676 | if (isif_config_dfc(&module_params->dfc) < 0) | ||
677 | return -EFAULT; | ||
678 | |||
679 | if (!module_params->df_csc.df_or_csc) | ||
680 | /* Configure Color Space Conversion */ | ||
681 | isif_config_csc(&module_params->df_csc); | ||
682 | |||
683 | isif_config_linearization(&module_params->linearize); | ||
684 | |||
685 | /* Configure Culling */ | ||
686 | isif_config_culling(&module_params->culling); | ||
687 | |||
688 | /* Configure horizontal and vertical offsets(DFC,LSC,Gain) */ | ||
689 | regw(module_params->horz_offset, DATAHOFST); | ||
690 | regw(module_params->vert_offset, DATAVOFST); | ||
691 | |||
692 | /* Setup test pattern if enabled */ | ||
693 | if (params->config_params.test_pat_gen) { | ||
694 | /* Use the HD/VD pol settings from user */ | ||
695 | sync.ccdpg_hdpol = params->hd_pol; | ||
696 | sync.ccdpg_vdpol = params->vd_pol; | ||
697 | dm365_vpss_set_sync_pol(sync); | ||
698 | frame_size.hlpfr = isif_cfg.bayer.win.width; | ||
699 | frame_size.pplen = isif_cfg.bayer.win.height; | ||
700 | dm365_vpss_set_pg_frame_size(frame_size); | ||
701 | vpss_select_ccdc_source(VPSS_PGLPBK); | ||
702 | } | ||
703 | |||
704 | dev_dbg(isif_cfg.dev, "\nEnd of isif_config_ycbcr...\n"); | ||
705 | return 0; | ||
706 | } | ||
707 | |||
708 | static int isif_set_buftype(enum ccdc_buftype buf_type) | ||
709 | { | ||
710 | if (isif_cfg.if_type == VPFE_RAW_BAYER) | ||
711 | isif_cfg.bayer.buf_type = buf_type; | ||
712 | else | ||
713 | isif_cfg.ycbcr.buf_type = buf_type; | ||
714 | |||
715 | return 0; | ||
716 | |||
717 | } | ||
718 | static enum ccdc_buftype isif_get_buftype(void) | ||
719 | { | ||
720 | if (isif_cfg.if_type == VPFE_RAW_BAYER) | ||
721 | return isif_cfg.bayer.buf_type; | ||
722 | |||
723 | return isif_cfg.ycbcr.buf_type; | ||
724 | } | ||
725 | |||
726 | static int isif_enum_pix(u32 *pix, int i) | ||
727 | { | ||
728 | int ret = -EINVAL; | ||
729 | |||
730 | if (isif_cfg.if_type == VPFE_RAW_BAYER) { | ||
731 | if (i < ARRAY_SIZE(isif_raw_bayer_pix_formats)) { | ||
732 | *pix = isif_raw_bayer_pix_formats[i]; | ||
733 | ret = 0; | ||
734 | } | ||
735 | } else { | ||
736 | if (i < ARRAY_SIZE(isif_raw_yuv_pix_formats)) { | ||
737 | *pix = isif_raw_yuv_pix_formats[i]; | ||
738 | ret = 0; | ||
739 | } | ||
740 | } | ||
741 | |||
742 | return ret; | ||
743 | } | ||
744 | |||
745 | static int isif_set_pixel_format(unsigned int pixfmt) | ||
746 | { | ||
747 | if (isif_cfg.if_type == VPFE_RAW_BAYER) { | ||
748 | if (pixfmt == V4L2_PIX_FMT_SBGGR8) { | ||
749 | if ((isif_cfg.bayer.config_params.compress.alg != | ||
750 | ISIF_ALAW) && | ||
751 | (isif_cfg.bayer.config_params.compress.alg != | ||
752 | ISIF_DPCM)) { | ||
753 | dev_dbg(isif_cfg.dev, | ||
754 | "Either configure A-Law or DPCM\n"); | ||
755 | return -EINVAL; | ||
756 | } | ||
757 | isif_cfg.data_pack = ISIF_PACK_8BIT; | ||
758 | } else if (pixfmt == V4L2_PIX_FMT_SBGGR16) { | ||
759 | isif_cfg.bayer.config_params.compress.alg = | ||
760 | ISIF_NO_COMPRESSION; | ||
761 | isif_cfg.data_pack = ISIF_PACK_16BIT; | ||
762 | } else | ||
763 | return -EINVAL; | ||
764 | isif_cfg.bayer.pix_fmt = CCDC_PIXFMT_RAW; | ||
765 | } else { | ||
766 | if (pixfmt == V4L2_PIX_FMT_YUYV) | ||
767 | isif_cfg.ycbcr.pix_order = CCDC_PIXORDER_YCBYCR; | ||
768 | else if (pixfmt == V4L2_PIX_FMT_UYVY) | ||
769 | isif_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY; | ||
770 | else | ||
771 | return -EINVAL; | ||
772 | isif_cfg.data_pack = ISIF_PACK_8BIT; | ||
773 | } | ||
774 | return 0; | ||
775 | } | ||
776 | |||
777 | static u32 isif_get_pixel_format(void) | ||
778 | { | ||
779 | u32 pixfmt; | ||
780 | |||
781 | if (isif_cfg.if_type == VPFE_RAW_BAYER) | ||
782 | if (isif_cfg.bayer.config_params.compress.alg == ISIF_ALAW || | ||
783 | isif_cfg.bayer.config_params.compress.alg == ISIF_DPCM) | ||
784 | pixfmt = V4L2_PIX_FMT_SBGGR8; | ||
785 | else | ||
786 | pixfmt = V4L2_PIX_FMT_SBGGR16; | ||
787 | else { | ||
788 | if (isif_cfg.ycbcr.pix_order == CCDC_PIXORDER_YCBYCR) | ||
789 | pixfmt = V4L2_PIX_FMT_YUYV; | ||
790 | else | ||
791 | pixfmt = V4L2_PIX_FMT_UYVY; | ||
792 | } | ||
793 | return pixfmt; | ||
794 | } | ||
795 | |||
796 | static int isif_set_image_window(struct v4l2_rect *win) | ||
797 | { | ||
798 | if (isif_cfg.if_type == VPFE_RAW_BAYER) { | ||
799 | isif_cfg.bayer.win.top = win->top; | ||
800 | isif_cfg.bayer.win.left = win->left; | ||
801 | isif_cfg.bayer.win.width = win->width; | ||
802 | isif_cfg.bayer.win.height = win->height; | ||
803 | } else { | ||
804 | isif_cfg.ycbcr.win.top = win->top; | ||
805 | isif_cfg.ycbcr.win.left = win->left; | ||
806 | isif_cfg.ycbcr.win.width = win->width; | ||
807 | isif_cfg.ycbcr.win.height = win->height; | ||
808 | } | ||
809 | return 0; | ||
810 | } | ||
811 | |||
812 | static void isif_get_image_window(struct v4l2_rect *win) | ||
813 | { | ||
814 | if (isif_cfg.if_type == VPFE_RAW_BAYER) | ||
815 | *win = isif_cfg.bayer.win; | ||
816 | else | ||
817 | *win = isif_cfg.ycbcr.win; | ||
818 | } | ||
819 | |||
820 | static unsigned int isif_get_line_length(void) | ||
821 | { | ||
822 | unsigned int len; | ||
823 | |||
824 | if (isif_cfg.if_type == VPFE_RAW_BAYER) { | ||
825 | if (isif_cfg.data_pack == ISIF_PACK_8BIT) | ||
826 | len = ((isif_cfg.bayer.win.width)); | ||
827 | else if (isif_cfg.data_pack == ISIF_PACK_12BIT) | ||
828 | len = (((isif_cfg.bayer.win.width * 2) + | ||
829 | (isif_cfg.bayer.win.width >> 2))); | ||
830 | else | ||
831 | len = (((isif_cfg.bayer.win.width * 2))); | ||
832 | } else | ||
833 | len = (((isif_cfg.ycbcr.win.width * 2))); | ||
834 | return ALIGN(len, 32); | ||
835 | } | ||
836 | |||
837 | static int isif_set_frame_format(enum ccdc_frmfmt frm_fmt) | ||
838 | { | ||
839 | if (isif_cfg.if_type == VPFE_RAW_BAYER) | ||
840 | isif_cfg.bayer.frm_fmt = frm_fmt; | ||
841 | else | ||
842 | isif_cfg.ycbcr.frm_fmt = frm_fmt; | ||
843 | return 0; | ||
844 | } | ||
845 | static enum ccdc_frmfmt isif_get_frame_format(void) | ||
846 | { | ||
847 | if (isif_cfg.if_type == VPFE_RAW_BAYER) | ||
848 | return isif_cfg.bayer.frm_fmt; | ||
849 | return isif_cfg.ycbcr.frm_fmt; | ||
850 | } | ||
851 | |||
852 | static int isif_getfid(void) | ||
853 | { | ||
854 | return (regr(MODESET) >> 15) & 0x1; | ||
855 | } | ||
856 | |||
857 | /* misc operations */ | ||
858 | static void isif_setfbaddr(unsigned long addr) | ||
859 | { | ||
860 | regw((addr >> 21) & 0x07ff, CADU); | ||
861 | regw((addr >> 5) & 0x0ffff, CADL); | ||
862 | } | ||
863 | |||
864 | static int isif_set_hw_if_params(struct vpfe_hw_if_param *params) | ||
865 | { | ||
866 | isif_cfg.if_type = params->if_type; | ||
867 | |||
868 | switch (params->if_type) { | ||
869 | case VPFE_BT656: | ||
870 | case VPFE_BT656_10BIT: | ||
871 | case VPFE_YCBCR_SYNC_8: | ||
872 | isif_cfg.ycbcr.pix_fmt = CCDC_PIXFMT_YCBCR_8BIT; | ||
873 | isif_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY; | ||
874 | break; | ||
875 | case VPFE_BT1120: | ||
876 | case VPFE_YCBCR_SYNC_16: | ||
877 | isif_cfg.ycbcr.pix_fmt = CCDC_PIXFMT_YCBCR_16BIT; | ||
878 | isif_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY; | ||
879 | break; | ||
880 | case VPFE_RAW_BAYER: | ||
881 | isif_cfg.bayer.pix_fmt = CCDC_PIXFMT_RAW; | ||
882 | break; | ||
883 | default: | ||
884 | dev_dbg(isif_cfg.dev, "Invalid interface type\n"); | ||
885 | return -EINVAL; | ||
886 | } | ||
887 | |||
888 | return 0; | ||
889 | } | ||
890 | |||
891 | /* This function will configure ISIF for YCbCr parameters. */ | ||
892 | static int isif_config_ycbcr(void) | ||
893 | { | ||
894 | struct isif_ycbcr_config *params = &isif_cfg.ycbcr; | ||
895 | struct vpss_pg_frame_size frame_size; | ||
896 | u32 modeset = 0, ccdcfg = 0; | ||
897 | struct vpss_sync_pol sync; | ||
898 | |||
899 | dev_dbg(isif_cfg.dev, "\nStarting isif_config_ycbcr..."); | ||
900 | |||
901 | /* configure pixel format or input mode */ | ||
902 | modeset = modeset | (params->pix_fmt << ISIF_INPUT_SHIFT) | | ||
903 | (params->frm_fmt << ISIF_FRM_FMT_SHIFT) | | ||
904 | (params->fid_pol << ISIF_FID_POL_SHIFT) | | ||
905 | (params->hd_pol << ISIF_HD_POL_SHIFT) | | ||
906 | (params->vd_pol << ISIF_VD_POL_SHIFT); | ||
907 | |||
908 | /* pack the data to 8-bit ISIFCFG */ | ||
909 | switch (isif_cfg.if_type) { | ||
910 | case VPFE_BT656: | ||
911 | if (params->pix_fmt != CCDC_PIXFMT_YCBCR_8BIT) { | ||
912 | dev_dbg(isif_cfg.dev, "Invalid pix_fmt(input mode)\n"); | ||
913 | return -EINVAL; | ||
914 | } | ||
915 | modeset |= (VPFE_PINPOL_NEGATIVE << ISIF_VD_POL_SHIFT); | ||
916 | regw(3, REC656IF); | ||
917 | ccdcfg = ccdcfg | ISIF_DATA_PACK8 | ISIF_YCINSWP_YCBCR; | ||
918 | break; | ||
919 | case VPFE_BT656_10BIT: | ||
920 | if (params->pix_fmt != CCDC_PIXFMT_YCBCR_8BIT) { | ||
921 | dev_dbg(isif_cfg.dev, "Invalid pix_fmt(input mode)\n"); | ||
922 | return -EINVAL; | ||
923 | } | ||
924 | /* setup BT.656, embedded sync */ | ||
925 | regw(3, REC656IF); | ||
926 | /* enable 10 bit mode in ccdcfg */ | ||
927 | ccdcfg = ccdcfg | ISIF_DATA_PACK8 | ISIF_YCINSWP_YCBCR | | ||
928 | ISIF_BW656_ENABLE; | ||
929 | break; | ||
930 | case VPFE_BT1120: | ||
931 | if (params->pix_fmt != CCDC_PIXFMT_YCBCR_16BIT) { | ||
932 | dev_dbg(isif_cfg.dev, "Invalid pix_fmt(input mode)\n"); | ||
933 | return -EINVAL; | ||
934 | } | ||
935 | regw(3, REC656IF); | ||
936 | break; | ||
937 | |||
938 | case VPFE_YCBCR_SYNC_8: | ||
939 | ccdcfg |= ISIF_DATA_PACK8; | ||
940 | ccdcfg |= ISIF_YCINSWP_YCBCR; | ||
941 | if (params->pix_fmt != CCDC_PIXFMT_YCBCR_8BIT) { | ||
942 | dev_dbg(isif_cfg.dev, "Invalid pix_fmt(input mode)\n"); | ||
943 | return -EINVAL; | ||
944 | } | ||
945 | break; | ||
946 | case VPFE_YCBCR_SYNC_16: | ||
947 | if (params->pix_fmt != CCDC_PIXFMT_YCBCR_16BIT) { | ||
948 | dev_dbg(isif_cfg.dev, "Invalid pix_fmt(input mode)\n"); | ||
949 | return -EINVAL; | ||
950 | } | ||
951 | break; | ||
952 | default: | ||
953 | /* should never come here */ | ||
954 | dev_dbg(isif_cfg.dev, "Invalid interface type\n"); | ||
955 | return -EINVAL; | ||
956 | } | ||
957 | |||
958 | regw(modeset, MODESET); | ||
959 | |||
960 | /* Set up pix order */ | ||
961 | ccdcfg |= params->pix_order << ISIF_PIX_ORDER_SHIFT; | ||
962 | |||
963 | regw(ccdcfg, CCDCFG); | ||
964 | |||
965 | /* configure video window */ | ||
966 | if ((isif_cfg.if_type == VPFE_BT1120) || | ||
967 | (isif_cfg.if_type == VPFE_YCBCR_SYNC_16)) | ||
968 | isif_setwin(¶ms->win, params->frm_fmt, 1); | ||
969 | else | ||
970 | isif_setwin(¶ms->win, params->frm_fmt, 2); | ||
971 | |||
972 | /* | ||
973 | * configure the horizontal line offset | ||
974 | * this is done by rounding up width to a multiple of 16 pixels | ||
975 | * and multiply by two to account for y:cb:cr 4:2:2 data | ||
976 | */ | ||
977 | regw(((((params->win.width * 2) + 31) & 0xffffffe0) >> 5), HSIZE); | ||
978 | |||
979 | /* configure the memory line offset */ | ||
980 | if ((params->frm_fmt == CCDC_FRMFMT_INTERLACED) && | ||
981 | (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED)) | ||
982 | /* two fields are interleaved in memory */ | ||
983 | regw(0x00000249, SDOFST); | ||
984 | |||
985 | /* Setup test pattern if enabled */ | ||
986 | if (isif_cfg.bayer.config_params.test_pat_gen) { | ||
987 | sync.ccdpg_hdpol = params->hd_pol; | ||
988 | sync.ccdpg_vdpol = params->vd_pol; | ||
989 | dm365_vpss_set_sync_pol(sync); | ||
990 | dm365_vpss_set_pg_frame_size(frame_size); | ||
991 | } | ||
992 | return 0; | ||
993 | } | ||
994 | |||
995 | static int isif_configure(void) | ||
996 | { | ||
997 | if (isif_cfg.if_type == VPFE_RAW_BAYER) | ||
998 | return isif_config_raw(); | ||
999 | return isif_config_ycbcr(); | ||
1000 | } | ||
1001 | |||
1002 | static int isif_close(struct device *device) | ||
1003 | { | ||
1004 | /* copy defaults to module params */ | ||
1005 | isif_cfg.bayer.config_params = isif_config_defaults; | ||
1006 | return 0; | ||
1007 | } | ||
1008 | |||
1009 | static struct ccdc_hw_device isif_hw_dev = { | ||
1010 | .name = "ISIF", | ||
1011 | .owner = THIS_MODULE, | ||
1012 | .hw_ops = { | ||
1013 | .open = isif_open, | ||
1014 | .close = isif_close, | ||
1015 | .enable = isif_enable, | ||
1016 | .enable_out_to_sdram = isif_enable_output_to_sdram, | ||
1017 | .set_hw_if_params = isif_set_hw_if_params, | ||
1018 | .configure = isif_configure, | ||
1019 | .set_buftype = isif_set_buftype, | ||
1020 | .get_buftype = isif_get_buftype, | ||
1021 | .enum_pix = isif_enum_pix, | ||
1022 | .set_pixel_format = isif_set_pixel_format, | ||
1023 | .get_pixel_format = isif_get_pixel_format, | ||
1024 | .set_frame_format = isif_set_frame_format, | ||
1025 | .get_frame_format = isif_get_frame_format, | ||
1026 | .set_image_window = isif_set_image_window, | ||
1027 | .get_image_window = isif_get_image_window, | ||
1028 | .get_line_length = isif_get_line_length, | ||
1029 | .setfbaddr = isif_setfbaddr, | ||
1030 | .getfid = isif_getfid, | ||
1031 | }, | ||
1032 | }; | ||
1033 | |||
1034 | static int __init isif_probe(struct platform_device *pdev) | ||
1035 | { | ||
1036 | void (*setup_pinmux)(void); | ||
1037 | struct resource *res; | ||
1038 | void *__iomem addr; | ||
1039 | int status = 0, i; | ||
1040 | |||
1041 | /* | ||
1042 | * first try to register with vpfe. If not correct platform, then we | ||
1043 | * don't have to iomap | ||
1044 | */ | ||
1045 | status = vpfe_register_ccdc_device(&isif_hw_dev); | ||
1046 | if (status < 0) | ||
1047 | return status; | ||
1048 | |||
1049 | /* Get and enable Master clock */ | ||
1050 | isif_cfg.mclk = clk_get(&pdev->dev, "master"); | ||
1051 | if (IS_ERR(isif_cfg.mclk)) { | ||
1052 | status = PTR_ERR(isif_cfg.mclk); | ||
1053 | goto fail_mclk; | ||
1054 | } | ||
1055 | if (clk_enable(isif_cfg.mclk)) { | ||
1056 | status = -ENODEV; | ||
1057 | goto fail_mclk; | ||
1058 | } | ||
1059 | |||
1060 | /* Platform data holds setup_pinmux function ptr */ | ||
1061 | if (NULL == pdev->dev.platform_data) { | ||
1062 | status = -ENODEV; | ||
1063 | goto fail_mclk; | ||
1064 | } | ||
1065 | setup_pinmux = pdev->dev.platform_data; | ||
1066 | /* | ||
1067 | * setup Mux configuration for ccdc which may be different for | ||
1068 | * different SoCs using this CCDC | ||
1069 | */ | ||
1070 | setup_pinmux(); | ||
1071 | |||
1072 | i = 0; | ||
1073 | /* Get the ISIF base address, linearization table0 and table1 addr. */ | ||
1074 | while (i < 3) { | ||
1075 | res = platform_get_resource(pdev, IORESOURCE_MEM, i); | ||
1076 | if (!res) { | ||
1077 | status = -ENODEV; | ||
1078 | goto fail_nobase_res; | ||
1079 | } | ||
1080 | res = request_mem_region(res->start, resource_size(res), | ||
1081 | res->name); | ||
1082 | if (!res) { | ||
1083 | status = -EBUSY; | ||
1084 | goto fail_nobase_res; | ||
1085 | } | ||
1086 | addr = ioremap_nocache(res->start, resource_size(res)); | ||
1087 | if (!addr) { | ||
1088 | status = -ENOMEM; | ||
1089 | goto fail_base_iomap; | ||
1090 | } | ||
1091 | switch (i) { | ||
1092 | case 0: | ||
1093 | /* ISIF base address */ | ||
1094 | isif_cfg.base_addr = addr; | ||
1095 | break; | ||
1096 | case 1: | ||
1097 | /* ISIF linear tbl0 address */ | ||
1098 | isif_cfg.linear_tbl0_addr = addr; | ||
1099 | break; | ||
1100 | default: | ||
1101 | /* ISIF linear tbl0 address */ | ||
1102 | isif_cfg.linear_tbl1_addr = addr; | ||
1103 | break; | ||
1104 | } | ||
1105 | i++; | ||
1106 | } | ||
1107 | isif_cfg.dev = &pdev->dev; | ||
1108 | |||
1109 | printk(KERN_NOTICE "%s is registered with vpfe.\n", | ||
1110 | isif_hw_dev.name); | ||
1111 | return 0; | ||
1112 | fail_base_iomap: | ||
1113 | release_mem_region(res->start, resource_size(res)); | ||
1114 | i--; | ||
1115 | fail_nobase_res: | ||
1116 | if (isif_cfg.base_addr) | ||
1117 | iounmap(isif_cfg.base_addr); | ||
1118 | if (isif_cfg.linear_tbl0_addr) | ||
1119 | iounmap(isif_cfg.linear_tbl0_addr); | ||
1120 | |||
1121 | while (i >= 0) { | ||
1122 | res = platform_get_resource(pdev, IORESOURCE_MEM, i); | ||
1123 | release_mem_region(res->start, resource_size(res)); | ||
1124 | i--; | ||
1125 | } | ||
1126 | fail_mclk: | ||
1127 | clk_put(isif_cfg.mclk); | ||
1128 | vpfe_unregister_ccdc_device(&isif_hw_dev); | ||
1129 | return status; | ||
1130 | } | ||
1131 | |||
1132 | static int isif_remove(struct platform_device *pdev) | ||
1133 | { | ||
1134 | struct resource *res; | ||
1135 | int i = 0; | ||
1136 | |||
1137 | iounmap(isif_cfg.base_addr); | ||
1138 | iounmap(isif_cfg.linear_tbl0_addr); | ||
1139 | iounmap(isif_cfg.linear_tbl1_addr); | ||
1140 | while (i < 3) { | ||
1141 | res = platform_get_resource(pdev, IORESOURCE_MEM, i); | ||
1142 | if (res) | ||
1143 | release_mem_region(res->start, resource_size(res)); | ||
1144 | i++; | ||
1145 | } | ||
1146 | vpfe_unregister_ccdc_device(&isif_hw_dev); | ||
1147 | return 0; | ||
1148 | } | ||
1149 | |||
1150 | static struct platform_driver isif_driver = { | ||
1151 | .driver = { | ||
1152 | .name = "isif", | ||
1153 | .owner = THIS_MODULE, | ||
1154 | }, | ||
1155 | .remove = __devexit_p(isif_remove), | ||
1156 | .probe = isif_probe, | ||
1157 | }; | ||
1158 | |||
1159 | static int __init isif_init(void) | ||
1160 | { | ||
1161 | return platform_driver_register(&isif_driver); | ||
1162 | } | ||
1163 | |||
1164 | static void isif_exit(void) | ||
1165 | { | ||
1166 | platform_driver_unregister(&isif_driver); | ||
1167 | } | ||
1168 | |||
1169 | module_init(isif_init); | ||
1170 | module_exit(isif_exit); | ||
1171 | |||
1172 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/davinci/isif_regs.h b/drivers/media/video/davinci/isif_regs.h new file mode 100644 index 000000000000..f7b8893a2957 --- /dev/null +++ b/drivers/media/video/davinci/isif_regs.h | |||
@@ -0,0 +1,269 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008-2009 Texas Instruments Inc | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | #ifndef _ISIF_REGS_H | ||
19 | #define _ISIF_REGS_H | ||
20 | |||
21 | /* ISIF registers relative offsets */ | ||
22 | #define SYNCEN 0x00 | ||
23 | #define MODESET 0x04 | ||
24 | #define HDW 0x08 | ||
25 | #define VDW 0x0c | ||
26 | #define PPLN 0x10 | ||
27 | #define LPFR 0x14 | ||
28 | #define SPH 0x18 | ||
29 | #define LNH 0x1c | ||
30 | #define SLV0 0x20 | ||
31 | #define SLV1 0x24 | ||
32 | #define LNV 0x28 | ||
33 | #define CULH 0x2c | ||
34 | #define CULV 0x30 | ||
35 | #define HSIZE 0x34 | ||
36 | #define SDOFST 0x38 | ||
37 | #define CADU 0x3c | ||
38 | #define CADL 0x40 | ||
39 | #define LINCFG0 0x44 | ||
40 | #define LINCFG1 0x48 | ||
41 | #define CCOLP 0x4c | ||
42 | #define CRGAIN 0x50 | ||
43 | #define CGRGAIN 0x54 | ||
44 | #define CGBGAIN 0x58 | ||
45 | #define CBGAIN 0x5c | ||
46 | #define COFSTA 0x60 | ||
47 | #define FLSHCFG0 0x64 | ||
48 | #define FLSHCFG1 0x68 | ||
49 | #define FLSHCFG2 0x6c | ||
50 | #define VDINT0 0x70 | ||
51 | #define VDINT1 0x74 | ||
52 | #define VDINT2 0x78 | ||
53 | #define MISC 0x7c | ||
54 | #define CGAMMAWD 0x80 | ||
55 | #define REC656IF 0x84 | ||
56 | #define CCDCFG 0x88 | ||
57 | /***************************************************** | ||
58 | * Defect Correction registers | ||
59 | *****************************************************/ | ||
60 | #define DFCCTL 0x8c | ||
61 | #define VDFSATLV 0x90 | ||
62 | #define DFCMEMCTL 0x94 | ||
63 | #define DFCMEM0 0x98 | ||
64 | #define DFCMEM1 0x9c | ||
65 | #define DFCMEM2 0xa0 | ||
66 | #define DFCMEM3 0xa4 | ||
67 | #define DFCMEM4 0xa8 | ||
68 | /**************************************************** | ||
69 | * Black Clamp registers | ||
70 | ****************************************************/ | ||
71 | #define CLAMPCFG 0xac | ||
72 | #define CLDCOFST 0xb0 | ||
73 | #define CLSV 0xb4 | ||
74 | #define CLHWIN0 0xb8 | ||
75 | #define CLHWIN1 0xbc | ||
76 | #define CLHWIN2 0xc0 | ||
77 | #define CLVRV 0xc4 | ||
78 | #define CLVWIN0 0xc8 | ||
79 | #define CLVWIN1 0xcc | ||
80 | #define CLVWIN2 0xd0 | ||
81 | #define CLVWIN3 0xd4 | ||
82 | /**************************************************** | ||
83 | * Lense Shading Correction | ||
84 | ****************************************************/ | ||
85 | #define DATAHOFST 0xd8 | ||
86 | #define DATAVOFST 0xdc | ||
87 | #define LSCHVAL 0xe0 | ||
88 | #define LSCVVAL 0xe4 | ||
89 | #define TWODLSCCFG 0xe8 | ||
90 | #define TWODLSCOFST 0xec | ||
91 | #define TWODLSCINI 0xf0 | ||
92 | #define TWODLSCGRBU 0xf4 | ||
93 | #define TWODLSCGRBL 0xf8 | ||
94 | #define TWODLSCGROF 0xfc | ||
95 | #define TWODLSCORBU 0x100 | ||
96 | #define TWODLSCORBL 0x104 | ||
97 | #define TWODLSCOROF 0x108 | ||
98 | #define TWODLSCIRQEN 0x10c | ||
99 | #define TWODLSCIRQST 0x110 | ||
100 | /**************************************************** | ||
101 | * Data formatter | ||
102 | ****************************************************/ | ||
103 | #define FMTCFG 0x114 | ||
104 | #define FMTPLEN 0x118 | ||
105 | #define FMTSPH 0x11c | ||
106 | #define FMTLNH 0x120 | ||
107 | #define FMTSLV 0x124 | ||
108 | #define FMTLNV 0x128 | ||
109 | #define FMTRLEN 0x12c | ||
110 | #define FMTHCNT 0x130 | ||
111 | #define FMTAPTR_BASE 0x134 | ||
112 | /* Below macro for addresses FMTAPTR0 - FMTAPTR15 */ | ||
113 | #define FMTAPTR(i) (FMTAPTR_BASE + (i * 4)) | ||
114 | #define FMTPGMVF0 0x174 | ||
115 | #define FMTPGMVF1 0x178 | ||
116 | #define FMTPGMAPU0 0x17c | ||
117 | #define FMTPGMAPU1 0x180 | ||
118 | #define FMTPGMAPS0 0x184 | ||
119 | #define FMTPGMAPS1 0x188 | ||
120 | #define FMTPGMAPS2 0x18c | ||
121 | #define FMTPGMAPS3 0x190 | ||
122 | #define FMTPGMAPS4 0x194 | ||
123 | #define FMTPGMAPS5 0x198 | ||
124 | #define FMTPGMAPS6 0x19c | ||
125 | #define FMTPGMAPS7 0x1a0 | ||
126 | /************************************************ | ||
127 | * Color Space Converter | ||
128 | ************************************************/ | ||
129 | #define CSCCTL 0x1a4 | ||
130 | #define CSCM0 0x1a8 | ||
131 | #define CSCM1 0x1ac | ||
132 | #define CSCM2 0x1b0 | ||
133 | #define CSCM3 0x1b4 | ||
134 | #define CSCM4 0x1b8 | ||
135 | #define CSCM5 0x1bc | ||
136 | #define CSCM6 0x1c0 | ||
137 | #define CSCM7 0x1c4 | ||
138 | #define OBWIN0 0x1c8 | ||
139 | #define OBWIN1 0x1cc | ||
140 | #define OBWIN2 0x1d0 | ||
141 | #define OBWIN3 0x1d4 | ||
142 | #define OBVAL0 0x1d8 | ||
143 | #define OBVAL1 0x1dc | ||
144 | #define OBVAL2 0x1e0 | ||
145 | #define OBVAL3 0x1e4 | ||
146 | #define OBVAL4 0x1e8 | ||
147 | #define OBVAL5 0x1ec | ||
148 | #define OBVAL6 0x1f0 | ||
149 | #define OBVAL7 0x1f4 | ||
150 | #define CLKCTL 0x1f8 | ||
151 | |||
152 | /* Masks & Shifts below */ | ||
153 | #define START_PX_HOR_MASK 0x7FFF | ||
154 | #define NUM_PX_HOR_MASK 0x7FFF | ||
155 | #define START_VER_ONE_MASK 0x7FFF | ||
156 | #define START_VER_TWO_MASK 0x7FFF | ||
157 | #define NUM_LINES_VER 0x7FFF | ||
158 | |||
159 | /* gain - offset masks */ | ||
160 | #define GAIN_INTEGER_SHIFT 9 | ||
161 | #define OFFSET_MASK 0xFFF | ||
162 | #define GAIN_SDRAM_EN_SHIFT 12 | ||
163 | #define GAIN_IPIPE_EN_SHIFT 13 | ||
164 | #define GAIN_H3A_EN_SHIFT 14 | ||
165 | #define OFST_SDRAM_EN_SHIFT 8 | ||
166 | #define OFST_IPIPE_EN_SHIFT 9 | ||
167 | #define OFST_H3A_EN_SHIFT 10 | ||
168 | #define GAIN_OFFSET_EN_MASK 0x7700 | ||
169 | |||
170 | /* Culling */ | ||
171 | #define CULL_PAT_EVEN_LINE_SHIFT 8 | ||
172 | |||
173 | /* CCDCFG register */ | ||
174 | #define ISIF_YCINSWP_RAW (0x00 << 4) | ||
175 | #define ISIF_YCINSWP_YCBCR (0x01 << 4) | ||
176 | #define ISIF_CCDCFG_FIDMD_LATCH_VSYNC (0x00 << 6) | ||
177 | #define ISIF_CCDCFG_WENLOG_AND (0x00 << 8) | ||
178 | #define ISIF_CCDCFG_TRGSEL_WEN (0x00 << 9) | ||
179 | #define ISIF_CCDCFG_EXTRG_DISABLE (0x00 << 10) | ||
180 | #define ISIF_LATCH_ON_VSYNC_DISABLE (0x01 << 15) | ||
181 | #define ISIF_LATCH_ON_VSYNC_ENABLE (0x00 << 15) | ||
182 | #define ISIF_DATA_PACK_MASK 3 | ||
183 | #define ISIF_DATA_PACK16 0 | ||
184 | #define ISIF_DATA_PACK12 1 | ||
185 | #define ISIF_DATA_PACK8 2 | ||
186 | #define ISIF_PIX_ORDER_SHIFT 11 | ||
187 | #define ISIF_BW656_ENABLE (0x01 << 5) | ||
188 | |||
189 | /* MODESET registers */ | ||
190 | #define ISIF_VDHDOUT_INPUT (0x00 << 0) | ||
191 | #define ISIF_INPUT_SHIFT 12 | ||
192 | #define ISIF_RAW_INPUT_MODE 0 | ||
193 | #define ISIF_FID_POL_SHIFT 4 | ||
194 | #define ISIF_HD_POL_SHIFT 3 | ||
195 | #define ISIF_VD_POL_SHIFT 2 | ||
196 | #define ISIF_DATAPOL_NORMAL 0 | ||
197 | #define ISIF_DATAPOL_SHIFT 6 | ||
198 | #define ISIF_EXWEN_DISABLE 0 | ||
199 | #define ISIF_EXWEN_SHIFT 5 | ||
200 | #define ISIF_FRM_FMT_SHIFT 7 | ||
201 | #define ISIF_DATASFT_SHIFT 8 | ||
202 | #define ISIF_LPF_SHIFT 14 | ||
203 | #define ISIF_LPF_MASK 1 | ||
204 | |||
205 | /* GAMMAWD registers */ | ||
206 | #define ISIF_ALAW_GAMA_WD_MASK 0xF | ||
207 | #define ISIF_ALAW_GAMA_WD_SHIFT 1 | ||
208 | #define ISIF_ALAW_ENABLE 1 | ||
209 | #define ISIF_GAMMAWD_CFA_SHIFT 5 | ||
210 | |||
211 | /* HSIZE registers */ | ||
212 | #define ISIF_HSIZE_FLIP_MASK 1 | ||
213 | #define ISIF_HSIZE_FLIP_SHIFT 12 | ||
214 | |||
215 | /* MISC registers */ | ||
216 | #define ISIF_DPCM_EN_SHIFT 12 | ||
217 | #define ISIF_DPCM_PREDICTOR_SHIFT 13 | ||
218 | |||
219 | /* Black clamp related */ | ||
220 | #define ISIF_BC_MODE_COLOR_SHIFT 4 | ||
221 | #define ISIF_HORZ_BC_MODE_SHIFT 1 | ||
222 | #define ISIF_HORZ_BC_WIN_SEL_SHIFT 5 | ||
223 | #define ISIF_HORZ_BC_PIX_LIMIT_SHIFT 6 | ||
224 | #define ISIF_HORZ_BC_WIN_H_SIZE_SHIFT 8 | ||
225 | #define ISIF_HORZ_BC_WIN_V_SIZE_SHIFT 12 | ||
226 | #define ISIF_VERT_BC_RST_VAL_SEL_SHIFT 4 | ||
227 | #define ISIF_VERT_BC_LINE_AVE_COEF_SHIFT 8 | ||
228 | |||
229 | /* VDFC registers */ | ||
230 | #define ISIF_VDFC_EN_SHIFT 4 | ||
231 | #define ISIF_VDFC_CORR_MOD_SHIFT 5 | ||
232 | #define ISIF_VDFC_CORR_WHOLE_LN_SHIFT 7 | ||
233 | #define ISIF_VDFC_LEVEL_SHFT_SHIFT 8 | ||
234 | #define ISIF_VDFC_POS_MASK 0x1FFF | ||
235 | #define ISIF_DFCMEMCTL_DFCMARST_SHIFT 2 | ||
236 | |||
237 | /* CSC registers */ | ||
238 | #define ISIF_CSC_COEF_INTEG_MASK 7 | ||
239 | #define ISIF_CSC_COEF_DECIMAL_MASK 0x1f | ||
240 | #define ISIF_CSC_COEF_INTEG_SHIFT 5 | ||
241 | #define ISIF_CSCM_MSB_SHIFT 8 | ||
242 | #define ISIF_DF_CSC_SPH_MASK 0x1FFF | ||
243 | #define ISIF_DF_CSC_LNH_MASK 0x1FFF | ||
244 | #define ISIF_DF_CSC_SLV_MASK 0x1FFF | ||
245 | #define ISIF_DF_CSC_LNV_MASK 0x1FFF | ||
246 | #define ISIF_DF_NUMLINES 0x7FFF | ||
247 | #define ISIF_DF_NUMPIX 0x1FFF | ||
248 | |||
249 | /* Offsets for LSC/DFC/Gain */ | ||
250 | #define ISIF_DATA_H_OFFSET_MASK 0x1FFF | ||
251 | #define ISIF_DATA_V_OFFSET_MASK 0x1FFF | ||
252 | |||
253 | /* Linearization */ | ||
254 | #define ISIF_LIN_CORRSFT_SHIFT 4 | ||
255 | #define ISIF_LIN_SCALE_FACT_INTEG_SHIFT 10 | ||
256 | |||
257 | |||
258 | /* Pattern registers */ | ||
259 | #define ISIF_PG_EN (1 << 3) | ||
260 | #define ISIF_SEL_PG_SRC (3 << 4) | ||
261 | #define ISIF_PG_VD_POL_SHIFT 0 | ||
262 | #define ISIF_PG_HD_POL_SHIFT 1 | ||
263 | |||
264 | /*random other junk*/ | ||
265 | #define ISIF_SYNCEN_VDHDEN_MASK (1 << 0) | ||
266 | #define ISIF_SYNCEN_WEN_MASK (1 << 1) | ||
267 | #define ISIF_SYNCEN_WEN_SHIFT 1 | ||
268 | |||
269 | #endif | ||
diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index de22bc9faf21..885cd54499cf 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c | |||
@@ -107,9 +107,6 @@ struct ccdc_config { | |||
107 | int vpfe_probed; | 107 | int vpfe_probed; |
108 | /* name of ccdc device */ | 108 | /* name of ccdc device */ |
109 | char name[32]; | 109 | char name[32]; |
110 | /* for storing mem maps for CCDC */ | ||
111 | int ccdc_addr_size; | ||
112 | void *__iomem ccdc_addr; | ||
113 | }; | 110 | }; |
114 | 111 | ||
115 | /* data structures */ | 112 | /* data structures */ |
@@ -229,7 +226,6 @@ int vpfe_register_ccdc_device(struct ccdc_hw_device *dev) | |||
229 | BUG_ON(!dev->hw_ops.set_image_window); | 226 | BUG_ON(!dev->hw_ops.set_image_window); |
230 | BUG_ON(!dev->hw_ops.get_image_window); | 227 | BUG_ON(!dev->hw_ops.get_image_window); |
231 | BUG_ON(!dev->hw_ops.get_line_length); | 228 | BUG_ON(!dev->hw_ops.get_line_length); |
232 | BUG_ON(!dev->hw_ops.setfbaddr); | ||
233 | BUG_ON(!dev->hw_ops.getfid); | 229 | BUG_ON(!dev->hw_ops.getfid); |
234 | 230 | ||
235 | mutex_lock(&ccdc_lock); | 231 | mutex_lock(&ccdc_lock); |
@@ -240,25 +236,23 @@ int vpfe_register_ccdc_device(struct ccdc_hw_device *dev) | |||
240 | * walk through it during vpfe probe | 236 | * walk through it during vpfe probe |
241 | */ | 237 | */ |
242 | printk(KERN_ERR "vpfe capture not initialized\n"); | 238 | printk(KERN_ERR "vpfe capture not initialized\n"); |
243 | ret = -1; | 239 | ret = -EFAULT; |
244 | goto unlock; | 240 | goto unlock; |
245 | } | 241 | } |
246 | 242 | ||
247 | if (strcmp(dev->name, ccdc_cfg->name)) { | 243 | if (strcmp(dev->name, ccdc_cfg->name)) { |
248 | /* ignore this ccdc */ | 244 | /* ignore this ccdc */ |
249 | ret = -1; | 245 | ret = -EINVAL; |
250 | goto unlock; | 246 | goto unlock; |
251 | } | 247 | } |
252 | 248 | ||
253 | if (ccdc_dev) { | 249 | if (ccdc_dev) { |
254 | printk(KERN_ERR "ccdc already registered\n"); | 250 | printk(KERN_ERR "ccdc already registered\n"); |
255 | ret = -1; | 251 | ret = -EINVAL; |
256 | goto unlock; | 252 | goto unlock; |
257 | } | 253 | } |
258 | 254 | ||
259 | ccdc_dev = dev; | 255 | ccdc_dev = dev; |
260 | dev->hw_ops.set_ccdc_base(ccdc_cfg->ccdc_addr, | ||
261 | ccdc_cfg->ccdc_addr_size); | ||
262 | unlock: | 256 | unlock: |
263 | mutex_unlock(&ccdc_lock); | 257 | mutex_unlock(&ccdc_lock); |
264 | return ret; | 258 | return ret; |
@@ -1786,61 +1780,6 @@ static struct vpfe_device *vpfe_initialize(void) | |||
1786 | return vpfe_dev; | 1780 | return vpfe_dev; |
1787 | } | 1781 | } |
1788 | 1782 | ||
1789 | static void vpfe_disable_clock(struct vpfe_device *vpfe_dev) | ||
1790 | { | ||
1791 | struct vpfe_config *vpfe_cfg = vpfe_dev->cfg; | ||
1792 | |||
1793 | clk_disable(vpfe_cfg->vpssclk); | ||
1794 | clk_put(vpfe_cfg->vpssclk); | ||
1795 | clk_disable(vpfe_cfg->slaveclk); | ||
1796 | clk_put(vpfe_cfg->slaveclk); | ||
1797 | v4l2_info(vpfe_dev->pdev->driver, | ||
1798 | "vpfe vpss master & slave clocks disabled\n"); | ||
1799 | } | ||
1800 | |||
1801 | static int vpfe_enable_clock(struct vpfe_device *vpfe_dev) | ||
1802 | { | ||
1803 | struct vpfe_config *vpfe_cfg = vpfe_dev->cfg; | ||
1804 | int ret = -ENOENT; | ||
1805 | |||
1806 | vpfe_cfg->vpssclk = clk_get(vpfe_dev->pdev, "vpss_master"); | ||
1807 | if (NULL == vpfe_cfg->vpssclk) { | ||
1808 | v4l2_err(vpfe_dev->pdev->driver, "No clock defined for" | ||
1809 | "vpss_master\n"); | ||
1810 | return ret; | ||
1811 | } | ||
1812 | |||
1813 | if (clk_enable(vpfe_cfg->vpssclk)) { | ||
1814 | v4l2_err(vpfe_dev->pdev->driver, | ||
1815 | "vpfe vpss master clock not enabled\n"); | ||
1816 | goto out; | ||
1817 | } | ||
1818 | v4l2_info(vpfe_dev->pdev->driver, | ||
1819 | "vpfe vpss master clock enabled\n"); | ||
1820 | |||
1821 | vpfe_cfg->slaveclk = clk_get(vpfe_dev->pdev, "vpss_slave"); | ||
1822 | if (NULL == vpfe_cfg->slaveclk) { | ||
1823 | v4l2_err(vpfe_dev->pdev->driver, | ||
1824 | "No clock defined for vpss slave\n"); | ||
1825 | goto out; | ||
1826 | } | ||
1827 | |||
1828 | if (clk_enable(vpfe_cfg->slaveclk)) { | ||
1829 | v4l2_err(vpfe_dev->pdev->driver, | ||
1830 | "vpfe vpss slave clock not enabled\n"); | ||
1831 | goto out; | ||
1832 | } | ||
1833 | v4l2_info(vpfe_dev->pdev->driver, "vpfe vpss slave clock enabled\n"); | ||
1834 | return 0; | ||
1835 | out: | ||
1836 | if (vpfe_cfg->vpssclk) | ||
1837 | clk_put(vpfe_cfg->vpssclk); | ||
1838 | if (vpfe_cfg->slaveclk) | ||
1839 | clk_put(vpfe_cfg->slaveclk); | ||
1840 | |||
1841 | return -1; | ||
1842 | } | ||
1843 | |||
1844 | /* | 1783 | /* |
1845 | * vpfe_probe : This function creates device entries by register | 1784 | * vpfe_probe : This function creates device entries by register |
1846 | * itself to the V4L2 driver and initializes fields of each | 1785 | * itself to the V4L2 driver and initializes fields of each |
@@ -1870,7 +1809,7 @@ static __init int vpfe_probe(struct platform_device *pdev) | |||
1870 | 1809 | ||
1871 | if (NULL == pdev->dev.platform_data) { | 1810 | if (NULL == pdev->dev.platform_data) { |
1872 | v4l2_err(pdev->dev.driver, "Unable to get vpfe config\n"); | 1811 | v4l2_err(pdev->dev.driver, "Unable to get vpfe config\n"); |
1873 | ret = -ENOENT; | 1812 | ret = -ENODEV; |
1874 | goto probe_free_dev_mem; | 1813 | goto probe_free_dev_mem; |
1875 | } | 1814 | } |
1876 | 1815 | ||
@@ -1884,18 +1823,13 @@ static __init int vpfe_probe(struct platform_device *pdev) | |||
1884 | goto probe_free_dev_mem; | 1823 | goto probe_free_dev_mem; |
1885 | } | 1824 | } |
1886 | 1825 | ||
1887 | /* enable vpss clocks */ | ||
1888 | ret = vpfe_enable_clock(vpfe_dev); | ||
1889 | if (ret) | ||
1890 | goto probe_free_dev_mem; | ||
1891 | |||
1892 | mutex_lock(&ccdc_lock); | 1826 | mutex_lock(&ccdc_lock); |
1893 | /* Allocate memory for ccdc configuration */ | 1827 | /* Allocate memory for ccdc configuration */ |
1894 | ccdc_cfg = kmalloc(sizeof(struct ccdc_config), GFP_KERNEL); | 1828 | ccdc_cfg = kmalloc(sizeof(struct ccdc_config), GFP_KERNEL); |
1895 | if (NULL == ccdc_cfg) { | 1829 | if (NULL == ccdc_cfg) { |
1896 | v4l2_err(pdev->dev.driver, | 1830 | v4l2_err(pdev->dev.driver, |
1897 | "Memory allocation failed for ccdc_cfg\n"); | 1831 | "Memory allocation failed for ccdc_cfg\n"); |
1898 | goto probe_disable_clock; | 1832 | goto probe_free_dev_mem; |
1899 | } | 1833 | } |
1900 | 1834 | ||
1901 | strncpy(ccdc_cfg->name, vpfe_cfg->ccdc, 32); | 1835 | strncpy(ccdc_cfg->name, vpfe_cfg->ccdc, 32); |
@@ -1904,61 +1838,34 @@ static __init int vpfe_probe(struct platform_device *pdev) | |||
1904 | if (!res1) { | 1838 | if (!res1) { |
1905 | v4l2_err(pdev->dev.driver, | 1839 | v4l2_err(pdev->dev.driver, |
1906 | "Unable to get interrupt for VINT0\n"); | 1840 | "Unable to get interrupt for VINT0\n"); |
1907 | ret = -ENOENT; | 1841 | ret = -ENODEV; |
1908 | goto probe_disable_clock; | 1842 | goto probe_free_ccdc_cfg_mem; |
1909 | } | 1843 | } |
1910 | vpfe_dev->ccdc_irq0 = res1->start; | 1844 | vpfe_dev->ccdc_irq0 = res1->start; |
1911 | 1845 | ||
1912 | /* Get VINT1 irq resource */ | 1846 | /* Get VINT1 irq resource */ |
1913 | res1 = platform_get_resource(pdev, | 1847 | res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 1); |
1914 | IORESOURCE_IRQ, 1); | ||
1915 | if (!res1) { | 1848 | if (!res1) { |
1916 | v4l2_err(pdev->dev.driver, | 1849 | v4l2_err(pdev->dev.driver, |
1917 | "Unable to get interrupt for VINT1\n"); | 1850 | "Unable to get interrupt for VINT1\n"); |
1918 | ret = -ENOENT; | 1851 | ret = -ENODEV; |
1919 | goto probe_disable_clock; | 1852 | goto probe_free_ccdc_cfg_mem; |
1920 | } | 1853 | } |
1921 | vpfe_dev->ccdc_irq1 = res1->start; | 1854 | vpfe_dev->ccdc_irq1 = res1->start; |
1922 | 1855 | ||
1923 | /* Get address base of CCDC */ | ||
1924 | res1 = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1925 | if (!res1) { | ||
1926 | v4l2_err(pdev->dev.driver, | ||
1927 | "Unable to get register address map\n"); | ||
1928 | ret = -ENOENT; | ||
1929 | goto probe_disable_clock; | ||
1930 | } | ||
1931 | |||
1932 | ccdc_cfg->ccdc_addr_size = res1->end - res1->start + 1; | ||
1933 | if (!request_mem_region(res1->start, ccdc_cfg->ccdc_addr_size, | ||
1934 | pdev->dev.driver->name)) { | ||
1935 | v4l2_err(pdev->dev.driver, | ||
1936 | "Failed request_mem_region for ccdc base\n"); | ||
1937 | ret = -ENXIO; | ||
1938 | goto probe_disable_clock; | ||
1939 | } | ||
1940 | ccdc_cfg->ccdc_addr = ioremap_nocache(res1->start, | ||
1941 | ccdc_cfg->ccdc_addr_size); | ||
1942 | if (!ccdc_cfg->ccdc_addr) { | ||
1943 | v4l2_err(pdev->dev.driver, "Unable to ioremap ccdc addr\n"); | ||
1944 | ret = -ENXIO; | ||
1945 | goto probe_out_release_mem1; | ||
1946 | } | ||
1947 | |||
1948 | ret = request_irq(vpfe_dev->ccdc_irq0, vpfe_isr, IRQF_DISABLED, | 1856 | ret = request_irq(vpfe_dev->ccdc_irq0, vpfe_isr, IRQF_DISABLED, |
1949 | "vpfe_capture0", vpfe_dev); | 1857 | "vpfe_capture0", vpfe_dev); |
1950 | 1858 | ||
1951 | if (0 != ret) { | 1859 | if (0 != ret) { |
1952 | v4l2_err(pdev->dev.driver, "Unable to request interrupt\n"); | 1860 | v4l2_err(pdev->dev.driver, "Unable to request interrupt\n"); |
1953 | goto probe_out_unmap1; | 1861 | goto probe_free_ccdc_cfg_mem; |
1954 | } | 1862 | } |
1955 | 1863 | ||
1956 | /* Allocate memory for video device */ | 1864 | /* Allocate memory for video device */ |
1957 | vfd = video_device_alloc(); | 1865 | vfd = video_device_alloc(); |
1958 | if (NULL == vfd) { | 1866 | if (NULL == vfd) { |
1959 | ret = -ENOMEM; | 1867 | ret = -ENOMEM; |
1960 | v4l2_err(pdev->dev.driver, | 1868 | v4l2_err(pdev->dev.driver, "Unable to alloc video device\n"); |
1961 | "Unable to alloc video device\n"); | ||
1962 | goto probe_out_release_irq; | 1869 | goto probe_out_release_irq; |
1963 | } | 1870 | } |
1964 | 1871 | ||
@@ -2073,12 +1980,7 @@ probe_out_video_release: | |||
2073 | video_device_release(vpfe_dev->video_dev); | 1980 | video_device_release(vpfe_dev->video_dev); |
2074 | probe_out_release_irq: | 1981 | probe_out_release_irq: |
2075 | free_irq(vpfe_dev->ccdc_irq0, vpfe_dev); | 1982 | free_irq(vpfe_dev->ccdc_irq0, vpfe_dev); |
2076 | probe_out_unmap1: | 1983 | probe_free_ccdc_cfg_mem: |
2077 | iounmap(ccdc_cfg->ccdc_addr); | ||
2078 | probe_out_release_mem1: | ||
2079 | release_mem_region(res1->start, res1->end - res1->start + 1); | ||
2080 | probe_disable_clock: | ||
2081 | vpfe_disable_clock(vpfe_dev); | ||
2082 | mutex_unlock(&ccdc_lock); | 1984 | mutex_unlock(&ccdc_lock); |
2083 | kfree(ccdc_cfg); | 1985 | kfree(ccdc_cfg); |
2084 | probe_free_dev_mem: | 1986 | probe_free_dev_mem: |
@@ -2092,7 +1994,6 @@ probe_free_dev_mem: | |||
2092 | static int __devexit vpfe_remove(struct platform_device *pdev) | 1994 | static int __devexit vpfe_remove(struct platform_device *pdev) |
2093 | { | 1995 | { |
2094 | struct vpfe_device *vpfe_dev = platform_get_drvdata(pdev); | 1996 | struct vpfe_device *vpfe_dev = platform_get_drvdata(pdev); |
2095 | struct resource *res; | ||
2096 | 1997 | ||
2097 | v4l2_info(pdev->dev.driver, "vpfe_remove\n"); | 1998 | v4l2_info(pdev->dev.driver, "vpfe_remove\n"); |
2098 | 1999 | ||
@@ -2100,12 +2001,6 @@ static int __devexit vpfe_remove(struct platform_device *pdev) | |||
2100 | kfree(vpfe_dev->sd); | 2001 | kfree(vpfe_dev->sd); |
2101 | v4l2_device_unregister(&vpfe_dev->v4l2_dev); | 2002 | v4l2_device_unregister(&vpfe_dev->v4l2_dev); |
2102 | video_unregister_device(vpfe_dev->video_dev); | 2003 | video_unregister_device(vpfe_dev->video_dev); |
2103 | mutex_lock(&ccdc_lock); | ||
2104 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
2105 | release_mem_region(res->start, res->end - res->start + 1); | ||
2106 | iounmap(ccdc_cfg->ccdc_addr); | ||
2107 | mutex_unlock(&ccdc_lock); | ||
2108 | vpfe_disable_clock(vpfe_dev); | ||
2109 | kfree(vpfe_dev); | 2004 | kfree(vpfe_dev); |
2110 | kfree(ccdc_cfg); | 2005 | kfree(ccdc_cfg); |
2111 | return 0; | 2006 | return 0; |
diff --git a/drivers/media/video/davinci/vpss.c b/drivers/media/video/davinci/vpss.c index 7ee72ecd3d81..7918680917d0 100644 --- a/drivers/media/video/davinci/vpss.c +++ b/drivers/media/video/davinci/vpss.c | |||
@@ -15,7 +15,7 @@ | |||
15 | * along with this program; if not, write to the Free Software | 15 | * along with this program; if not, write to the Free Software |
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
17 | * | 17 | * |
18 | * common vpss driver for all video drivers. | 18 | * common vpss system module platform driver for all video drivers. |
19 | */ | 19 | */ |
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/sched.h> | 21 | #include <linux/sched.h> |
@@ -35,12 +35,52 @@ MODULE_AUTHOR("Texas Instruments"); | |||
35 | /* DM644x defines */ | 35 | /* DM644x defines */ |
36 | #define DM644X_SBL_PCR_VPSS (4) | 36 | #define DM644X_SBL_PCR_VPSS (4) |
37 | 37 | ||
38 | #define DM355_VPSSBL_INTSEL 0x10 | ||
39 | #define DM355_VPSSBL_EVTSEL 0x14 | ||
38 | /* vpss BL register offsets */ | 40 | /* vpss BL register offsets */ |
39 | #define DM355_VPSSBL_CCDCMUX 0x1c | 41 | #define DM355_VPSSBL_CCDCMUX 0x1c |
40 | /* vpss CLK register offsets */ | 42 | /* vpss CLK register offsets */ |
41 | #define DM355_VPSSCLK_CLKCTRL 0x04 | 43 | #define DM355_VPSSCLK_CLKCTRL 0x04 |
42 | /* masks and shifts */ | 44 | /* masks and shifts */ |
43 | #define VPSS_HSSISEL_SHIFT 4 | 45 | #define VPSS_HSSISEL_SHIFT 4 |
46 | /* | ||
47 | * VDINT0 - vpss_int0, VDINT1 - vpss_int1, H3A - vpss_int4, | ||
48 | * IPIPE_INT1_SDR - vpss_int5 | ||
49 | */ | ||
50 | #define DM355_VPSSBL_INTSEL_DEFAULT 0xff83ff10 | ||
51 | /* VENCINT - vpss_int8 */ | ||
52 | #define DM355_VPSSBL_EVTSEL_DEFAULT 0x4 | ||
53 | |||
54 | #define DM365_ISP5_PCCR 0x04 | ||
55 | #define DM365_ISP5_INTSEL1 0x10 | ||
56 | #define DM365_ISP5_INTSEL2 0x14 | ||
57 | #define DM365_ISP5_INTSEL3 0x18 | ||
58 | #define DM365_ISP5_CCDCMUX 0x20 | ||
59 | #define DM365_ISP5_PG_FRAME_SIZE 0x28 | ||
60 | #define DM365_VPBE_CLK_CTRL 0x00 | ||
61 | /* | ||
62 | * vpss interrupts. VDINT0 - vpss_int0, VDINT1 - vpss_int1, | ||
63 | * AF - vpss_int3 | ||
64 | */ | ||
65 | #define DM365_ISP5_INTSEL1_DEFAULT 0x0b1f0100 | ||
66 | /* AEW - vpss_int6, RSZ_INT_DMA - vpss_int5 */ | ||
67 | #define DM365_ISP5_INTSEL2_DEFAULT 0x1f0a0f1f | ||
68 | /* VENC - vpss_int8 */ | ||
69 | #define DM365_ISP5_INTSEL3_DEFAULT 0x00000015 | ||
70 | |||
71 | /* masks and shifts for DM365*/ | ||
72 | #define DM365_CCDC_PG_VD_POL_SHIFT 0 | ||
73 | #define DM365_CCDC_PG_HD_POL_SHIFT 1 | ||
74 | |||
75 | #define CCD_SRC_SEL_MASK (BIT_MASK(5) | BIT_MASK(4)) | ||
76 | #define CCD_SRC_SEL_SHIFT 4 | ||
77 | |||
78 | /* Different SoC platforms supported by this driver */ | ||
79 | enum vpss_platform_type { | ||
80 | DM644X, | ||
81 | DM355, | ||
82 | DM365, | ||
83 | }; | ||
44 | 84 | ||
45 | /* | 85 | /* |
46 | * vpss operations. Depends on platform. Not all functions are available | 86 | * vpss operations. Depends on platform. Not all functions are available |
@@ -59,13 +99,9 @@ struct vpss_hw_ops { | |||
59 | 99 | ||
60 | /* vpss configuration */ | 100 | /* vpss configuration */ |
61 | struct vpss_oper_config { | 101 | struct vpss_oper_config { |
62 | __iomem void *vpss_bl_regs_base; | 102 | __iomem void *vpss_regs_base0; |
63 | __iomem void *vpss_regs_base; | 103 | __iomem void *vpss_regs_base1; |
64 | struct resource *r1; | 104 | enum vpss_platform_type platform; |
65 | resource_size_t len1; | ||
66 | struct resource *r2; | ||
67 | resource_size_t len2; | ||
68 | char vpss_name[32]; | ||
69 | spinlock_t vpss_lock; | 105 | spinlock_t vpss_lock; |
70 | struct vpss_hw_ops hw_ops; | 106 | struct vpss_hw_ops hw_ops; |
71 | }; | 107 | }; |
@@ -75,22 +111,46 @@ static struct vpss_oper_config oper_cfg; | |||
75 | /* register access routines */ | 111 | /* register access routines */ |
76 | static inline u32 bl_regr(u32 offset) | 112 | static inline u32 bl_regr(u32 offset) |
77 | { | 113 | { |
78 | return __raw_readl(oper_cfg.vpss_bl_regs_base + offset); | 114 | return __raw_readl(oper_cfg.vpss_regs_base0 + offset); |
79 | } | 115 | } |
80 | 116 | ||
81 | static inline void bl_regw(u32 val, u32 offset) | 117 | static inline void bl_regw(u32 val, u32 offset) |
82 | { | 118 | { |
83 | __raw_writel(val, oper_cfg.vpss_bl_regs_base + offset); | 119 | __raw_writel(val, oper_cfg.vpss_regs_base0 + offset); |
84 | } | 120 | } |
85 | 121 | ||
86 | static inline u32 vpss_regr(u32 offset) | 122 | static inline u32 vpss_regr(u32 offset) |
87 | { | 123 | { |
88 | return __raw_readl(oper_cfg.vpss_regs_base + offset); | 124 | return __raw_readl(oper_cfg.vpss_regs_base1 + offset); |
89 | } | 125 | } |
90 | 126 | ||
91 | static inline void vpss_regw(u32 val, u32 offset) | 127 | static inline void vpss_regw(u32 val, u32 offset) |
92 | { | 128 | { |
93 | __raw_writel(val, oper_cfg.vpss_regs_base + offset); | 129 | __raw_writel(val, oper_cfg.vpss_regs_base1 + offset); |
130 | } | ||
131 | |||
132 | /* For DM365 only */ | ||
133 | static inline u32 isp5_read(u32 offset) | ||
134 | { | ||
135 | return __raw_readl(oper_cfg.vpss_regs_base0 + offset); | ||
136 | } | ||
137 | |||
138 | /* For DM365 only */ | ||
139 | static inline void isp5_write(u32 val, u32 offset) | ||
140 | { | ||
141 | __raw_writel(val, oper_cfg.vpss_regs_base0 + offset); | ||
142 | } | ||
143 | |||
144 | static void dm365_select_ccdc_source(enum vpss_ccdc_source_sel src_sel) | ||
145 | { | ||
146 | u32 temp = isp5_read(DM365_ISP5_CCDCMUX) & ~CCD_SRC_SEL_MASK; | ||
147 | |||
148 | /* if we are using pattern generator, enable it */ | ||
149 | if (src_sel == VPSS_PGLPBK || src_sel == VPSS_CCDCPG) | ||
150 | temp |= 0x08; | ||
151 | |||
152 | temp |= (src_sel << CCD_SRC_SEL_SHIFT); | ||
153 | isp5_write(temp, DM365_ISP5_CCDCMUX); | ||
94 | } | 154 | } |
95 | 155 | ||
96 | static void dm355_select_ccdc_source(enum vpss_ccdc_source_sel src_sel) | 156 | static void dm355_select_ccdc_source(enum vpss_ccdc_source_sel src_sel) |
@@ -101,9 +161,9 @@ static void dm355_select_ccdc_source(enum vpss_ccdc_source_sel src_sel) | |||
101 | int vpss_select_ccdc_source(enum vpss_ccdc_source_sel src_sel) | 161 | int vpss_select_ccdc_source(enum vpss_ccdc_source_sel src_sel) |
102 | { | 162 | { |
103 | if (!oper_cfg.hw_ops.select_ccdc_source) | 163 | if (!oper_cfg.hw_ops.select_ccdc_source) |
104 | return -1; | 164 | return -EINVAL; |
105 | 165 | ||
106 | dm355_select_ccdc_source(src_sel); | 166 | oper_cfg.hw_ops.select_ccdc_source(src_sel); |
107 | return 0; | 167 | return 0; |
108 | } | 168 | } |
109 | EXPORT_SYMBOL(vpss_select_ccdc_source); | 169 | EXPORT_SYMBOL(vpss_select_ccdc_source); |
@@ -114,7 +174,7 @@ static int dm644x_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel) | |||
114 | 174 | ||
115 | if (wbl_sel < VPSS_PCR_AEW_WBL_0 || | 175 | if (wbl_sel < VPSS_PCR_AEW_WBL_0 || |
116 | wbl_sel > VPSS_PCR_CCDC_WBL_O) | 176 | wbl_sel > VPSS_PCR_CCDC_WBL_O) |
117 | return -1; | 177 | return -EINVAL; |
118 | 178 | ||
119 | /* writing a 0 clear the overflow */ | 179 | /* writing a 0 clear the overflow */ |
120 | mask = ~(mask << wbl_sel); | 180 | mask = ~(mask << wbl_sel); |
@@ -126,7 +186,7 @@ static int dm644x_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel) | |||
126 | int vpss_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel) | 186 | int vpss_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel) |
127 | { | 187 | { |
128 | if (!oper_cfg.hw_ops.clear_wbl_overflow) | 188 | if (!oper_cfg.hw_ops.clear_wbl_overflow) |
129 | return -1; | 189 | return -EINVAL; |
130 | 190 | ||
131 | return oper_cfg.hw_ops.clear_wbl_overflow(wbl_sel); | 191 | return oper_cfg.hw_ops.clear_wbl_overflow(wbl_sel); |
132 | } | 192 | } |
@@ -166,7 +226,7 @@ static int dm355_enable_clock(enum vpss_clock_sel clock_sel, int en) | |||
166 | default: | 226 | default: |
167 | printk(KERN_ERR "dm355_enable_clock:" | 227 | printk(KERN_ERR "dm355_enable_clock:" |
168 | " Invalid selector: %d\n", clock_sel); | 228 | " Invalid selector: %d\n", clock_sel); |
169 | return -1; | 229 | return -EINVAL; |
170 | } | 230 | } |
171 | 231 | ||
172 | spin_lock_irqsave(&oper_cfg.vpss_lock, flags); | 232 | spin_lock_irqsave(&oper_cfg.vpss_lock, flags); |
@@ -181,100 +241,221 @@ static int dm355_enable_clock(enum vpss_clock_sel clock_sel, int en) | |||
181 | return 0; | 241 | return 0; |
182 | } | 242 | } |
183 | 243 | ||
244 | static int dm365_enable_clock(enum vpss_clock_sel clock_sel, int en) | ||
245 | { | ||
246 | unsigned long flags; | ||
247 | u32 utemp, mask = 0x1, shift = 0, offset = DM365_ISP5_PCCR; | ||
248 | u32 (*read)(u32 offset) = isp5_read; | ||
249 | void(*write)(u32 val, u32 offset) = isp5_write; | ||
250 | |||
251 | switch (clock_sel) { | ||
252 | case VPSS_BL_CLOCK: | ||
253 | break; | ||
254 | case VPSS_CCDC_CLOCK: | ||
255 | shift = 1; | ||
256 | break; | ||
257 | case VPSS_H3A_CLOCK: | ||
258 | shift = 2; | ||
259 | break; | ||
260 | case VPSS_RSZ_CLOCK: | ||
261 | shift = 3; | ||
262 | break; | ||
263 | case VPSS_IPIPE_CLOCK: | ||
264 | shift = 4; | ||
265 | break; | ||
266 | case VPSS_IPIPEIF_CLOCK: | ||
267 | shift = 5; | ||
268 | break; | ||
269 | case VPSS_PCLK_INTERNAL: | ||
270 | shift = 6; | ||
271 | break; | ||
272 | case VPSS_PSYNC_CLOCK_SEL: | ||
273 | shift = 7; | ||
274 | break; | ||
275 | case VPSS_VPBE_CLOCK: | ||
276 | read = vpss_regr; | ||
277 | write = vpss_regw; | ||
278 | offset = DM365_VPBE_CLK_CTRL; | ||
279 | break; | ||
280 | case VPSS_VENC_CLOCK_SEL: | ||
281 | shift = 2; | ||
282 | read = vpss_regr; | ||
283 | write = vpss_regw; | ||
284 | offset = DM365_VPBE_CLK_CTRL; | ||
285 | break; | ||
286 | case VPSS_LDC_CLOCK: | ||
287 | shift = 3; | ||
288 | read = vpss_regr; | ||
289 | write = vpss_regw; | ||
290 | offset = DM365_VPBE_CLK_CTRL; | ||
291 | break; | ||
292 | case VPSS_FDIF_CLOCK: | ||
293 | shift = 4; | ||
294 | read = vpss_regr; | ||
295 | write = vpss_regw; | ||
296 | offset = DM365_VPBE_CLK_CTRL; | ||
297 | break; | ||
298 | case VPSS_OSD_CLOCK_SEL: | ||
299 | shift = 6; | ||
300 | read = vpss_regr; | ||
301 | write = vpss_regw; | ||
302 | offset = DM365_VPBE_CLK_CTRL; | ||
303 | break; | ||
304 | case VPSS_LDC_CLOCK_SEL: | ||
305 | shift = 7; | ||
306 | read = vpss_regr; | ||
307 | write = vpss_regw; | ||
308 | offset = DM365_VPBE_CLK_CTRL; | ||
309 | break; | ||
310 | default: | ||
311 | printk(KERN_ERR "dm365_enable_clock: Invalid selector: %d\n", | ||
312 | clock_sel); | ||
313 | return -1; | ||
314 | } | ||
315 | |||
316 | spin_lock_irqsave(&oper_cfg.vpss_lock, flags); | ||
317 | utemp = read(offset); | ||
318 | if (!en) { | ||
319 | mask = ~mask; | ||
320 | utemp &= (mask << shift); | ||
321 | } else | ||
322 | utemp |= (mask << shift); | ||
323 | |||
324 | write(utemp, offset); | ||
325 | spin_unlock_irqrestore(&oper_cfg.vpss_lock, flags); | ||
326 | |||
327 | return 0; | ||
328 | } | ||
329 | |||
184 | int vpss_enable_clock(enum vpss_clock_sel clock_sel, int en) | 330 | int vpss_enable_clock(enum vpss_clock_sel clock_sel, int en) |
185 | { | 331 | { |
186 | if (!oper_cfg.hw_ops.enable_clock) | 332 | if (!oper_cfg.hw_ops.enable_clock) |
187 | return -1; | 333 | return -EINVAL; |
188 | 334 | ||
189 | return oper_cfg.hw_ops.enable_clock(clock_sel, en); | 335 | return oper_cfg.hw_ops.enable_clock(clock_sel, en); |
190 | } | 336 | } |
191 | EXPORT_SYMBOL(vpss_enable_clock); | 337 | EXPORT_SYMBOL(vpss_enable_clock); |
192 | 338 | ||
339 | void dm365_vpss_set_sync_pol(struct vpss_sync_pol sync) | ||
340 | { | ||
341 | int val = 0; | ||
342 | val = isp5_read(DM365_ISP5_CCDCMUX); | ||
343 | |||
344 | val |= (sync.ccdpg_hdpol << DM365_CCDC_PG_HD_POL_SHIFT); | ||
345 | val |= (sync.ccdpg_vdpol << DM365_CCDC_PG_VD_POL_SHIFT); | ||
346 | |||
347 | isp5_write(val, DM365_ISP5_CCDCMUX); | ||
348 | } | ||
349 | EXPORT_SYMBOL(dm365_vpss_set_sync_pol); | ||
350 | |||
351 | void dm365_vpss_set_pg_frame_size(struct vpss_pg_frame_size frame_size) | ||
352 | { | ||
353 | int current_reg = ((frame_size.hlpfr >> 1) - 1) << 16; | ||
354 | |||
355 | current_reg |= (frame_size.pplen - 1); | ||
356 | isp5_write(current_reg, DM365_ISP5_PG_FRAME_SIZE); | ||
357 | } | ||
358 | EXPORT_SYMBOL(dm365_vpss_set_pg_frame_size); | ||
359 | |||
193 | static int __init vpss_probe(struct platform_device *pdev) | 360 | static int __init vpss_probe(struct platform_device *pdev) |
194 | { | 361 | { |
195 | int status, dm355 = 0; | 362 | struct resource *r1, *r2; |
363 | char *platform_name; | ||
364 | int status; | ||
196 | 365 | ||
197 | if (!pdev->dev.platform_data) { | 366 | if (!pdev->dev.platform_data) { |
198 | dev_err(&pdev->dev, "no platform data\n"); | 367 | dev_err(&pdev->dev, "no platform data\n"); |
199 | return -ENOENT; | 368 | return -ENOENT; |
200 | } | 369 | } |
201 | strcpy(oper_cfg.vpss_name, pdev->dev.platform_data); | ||
202 | 370 | ||
203 | if (!strcmp(oper_cfg.vpss_name, "dm355_vpss")) | 371 | platform_name = pdev->dev.platform_data; |
204 | dm355 = 1; | 372 | if (!strcmp(platform_name, "dm355_vpss")) |
205 | else if (strcmp(oper_cfg.vpss_name, "dm644x_vpss")) { | 373 | oper_cfg.platform = DM355; |
374 | else if (!strcmp(platform_name, "dm365_vpss")) | ||
375 | oper_cfg.platform = DM365; | ||
376 | else if (!strcmp(platform_name, "dm644x_vpss")) | ||
377 | oper_cfg.platform = DM644X; | ||
378 | else { | ||
206 | dev_err(&pdev->dev, "vpss driver not supported on" | 379 | dev_err(&pdev->dev, "vpss driver not supported on" |
207 | " this platform\n"); | 380 | " this platform\n"); |
208 | return -ENODEV; | 381 | return -ENODEV; |
209 | } | 382 | } |
210 | 383 | ||
211 | dev_info(&pdev->dev, "%s vpss probed\n", oper_cfg.vpss_name); | 384 | dev_info(&pdev->dev, "%s vpss probed\n", platform_name); |
212 | oper_cfg.r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 385 | r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
213 | if (!oper_cfg.r1) | 386 | if (!r1) |
214 | return -ENOENT; | 387 | return -ENOENT; |
215 | 388 | ||
216 | oper_cfg.len1 = oper_cfg.r1->end - oper_cfg.r1->start + 1; | 389 | r1 = request_mem_region(r1->start, resource_size(r1), r1->name); |
217 | 390 | if (!r1) | |
218 | oper_cfg.r1 = request_mem_region(oper_cfg.r1->start, oper_cfg.len1, | ||
219 | oper_cfg.r1->name); | ||
220 | if (!oper_cfg.r1) | ||
221 | return -EBUSY; | 391 | return -EBUSY; |
222 | 392 | ||
223 | oper_cfg.vpss_bl_regs_base = ioremap(oper_cfg.r1->start, oper_cfg.len1); | 393 | oper_cfg.vpss_regs_base0 = ioremap(r1->start, resource_size(r1)); |
224 | if (!oper_cfg.vpss_bl_regs_base) { | 394 | if (!oper_cfg.vpss_regs_base0) { |
225 | status = -EBUSY; | 395 | status = -EBUSY; |
226 | goto fail1; | 396 | goto fail1; |
227 | } | 397 | } |
228 | 398 | ||
229 | if (dm355) { | 399 | if (oper_cfg.platform == DM355 || oper_cfg.platform == DM365) { |
230 | oper_cfg.r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 400 | r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
231 | if (!oper_cfg.r2) { | 401 | if (!r2) { |
232 | status = -ENOENT; | 402 | status = -ENOENT; |
233 | goto fail2; | 403 | goto fail2; |
234 | } | 404 | } |
235 | oper_cfg.len2 = oper_cfg.r2->end - oper_cfg.r2->start + 1; | 405 | r2 = request_mem_region(r2->start, resource_size(r2), r2->name); |
236 | oper_cfg.r2 = request_mem_region(oper_cfg.r2->start, | 406 | if (!r2) { |
237 | oper_cfg.len2, | ||
238 | oper_cfg.r2->name); | ||
239 | if (!oper_cfg.r2) { | ||
240 | status = -EBUSY; | 407 | status = -EBUSY; |
241 | goto fail2; | 408 | goto fail2; |
242 | } | 409 | } |
243 | 410 | ||
244 | oper_cfg.vpss_regs_base = ioremap(oper_cfg.r2->start, | 411 | oper_cfg.vpss_regs_base1 = ioremap(r2->start, |
245 | oper_cfg.len2); | 412 | resource_size(r2)); |
246 | if (!oper_cfg.vpss_regs_base) { | 413 | if (!oper_cfg.vpss_regs_base1) { |
247 | status = -EBUSY; | 414 | status = -EBUSY; |
248 | goto fail3; | 415 | goto fail3; |
249 | } | 416 | } |
250 | } | 417 | } |
251 | 418 | ||
252 | if (dm355) { | 419 | if (oper_cfg.platform == DM355) { |
253 | oper_cfg.hw_ops.enable_clock = dm355_enable_clock; | 420 | oper_cfg.hw_ops.enable_clock = dm355_enable_clock; |
254 | oper_cfg.hw_ops.select_ccdc_source = dm355_select_ccdc_source; | 421 | oper_cfg.hw_ops.select_ccdc_source = dm355_select_ccdc_source; |
422 | /* Setup vpss interrupts */ | ||
423 | bl_regw(DM355_VPSSBL_INTSEL_DEFAULT, DM355_VPSSBL_INTSEL); | ||
424 | bl_regw(DM355_VPSSBL_EVTSEL_DEFAULT, DM355_VPSSBL_EVTSEL); | ||
425 | } else if (oper_cfg.platform == DM365) { | ||
426 | oper_cfg.hw_ops.enable_clock = dm365_enable_clock; | ||
427 | oper_cfg.hw_ops.select_ccdc_source = dm365_select_ccdc_source; | ||
428 | /* Setup vpss interrupts */ | ||
429 | isp5_write(DM365_ISP5_INTSEL1_DEFAULT, DM365_ISP5_INTSEL1); | ||
430 | isp5_write(DM365_ISP5_INTSEL2_DEFAULT, DM365_ISP5_INTSEL2); | ||
431 | isp5_write(DM365_ISP5_INTSEL3_DEFAULT, DM365_ISP5_INTSEL3); | ||
255 | } else | 432 | } else |
256 | oper_cfg.hw_ops.clear_wbl_overflow = dm644x_clear_wbl_overflow; | 433 | oper_cfg.hw_ops.clear_wbl_overflow = dm644x_clear_wbl_overflow; |
257 | 434 | ||
258 | spin_lock_init(&oper_cfg.vpss_lock); | 435 | spin_lock_init(&oper_cfg.vpss_lock); |
259 | dev_info(&pdev->dev, "%s vpss probe success\n", oper_cfg.vpss_name); | 436 | dev_info(&pdev->dev, "%s vpss probe success\n", platform_name); |
260 | return 0; | 437 | return 0; |
261 | 438 | ||
262 | fail3: | 439 | fail3: |
263 | release_mem_region(oper_cfg.r2->start, oper_cfg.len2); | 440 | release_mem_region(r2->start, resource_size(r2)); |
264 | fail2: | 441 | fail2: |
265 | iounmap(oper_cfg.vpss_bl_regs_base); | 442 | iounmap(oper_cfg.vpss_regs_base0); |
266 | fail1: | 443 | fail1: |
267 | release_mem_region(oper_cfg.r1->start, oper_cfg.len1); | 444 | release_mem_region(r1->start, resource_size(r1)); |
268 | return status; | 445 | return status; |
269 | } | 446 | } |
270 | 447 | ||
271 | static int __devexit vpss_remove(struct platform_device *pdev) | 448 | static int __devexit vpss_remove(struct platform_device *pdev) |
272 | { | 449 | { |
273 | iounmap(oper_cfg.vpss_bl_regs_base); | 450 | struct resource *res; |
274 | release_mem_region(oper_cfg.r1->start, oper_cfg.len1); | 451 | |
275 | if (!strcmp(oper_cfg.vpss_name, "dm355_vpss")) { | 452 | iounmap(oper_cfg.vpss_regs_base0); |
276 | iounmap(oper_cfg.vpss_regs_base); | 453 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
277 | release_mem_region(oper_cfg.r2->start, oper_cfg.len2); | 454 | release_mem_region(res->start, resource_size(res)); |
455 | if (oper_cfg.platform == DM355 || oper_cfg.platform == DM365) { | ||
456 | iounmap(oper_cfg.vpss_regs_base1); | ||
457 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
458 | release_mem_region(res->start, resource_size(res)); | ||
278 | } | 459 | } |
279 | return 0; | 460 | return 0; |
280 | } | 461 | } |
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 25100001ffff..ecbcefb08739 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -232,6 +232,12 @@ static struct em28xx_reg_seq vc211a_enable[] = { | |||
232 | { -1, -1, -1, -1}, | 232 | { -1, -1, -1, -1}, |
233 | }; | 233 | }; |
234 | 234 | ||
235 | static struct em28xx_reg_seq dikom_dk300_digital[] = { | ||
236 | {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, | ||
237 | {EM2880_R04_GPO, 0x08, 0xff, 10}, | ||
238 | { -1, -1, -1, -1}, | ||
239 | }; | ||
240 | |||
235 | 241 | ||
236 | /* | 242 | /* |
237 | * Board definitions | 243 | * Board definitions |
@@ -461,21 +467,30 @@ struct em28xx_board em28xx_boards[] = { | |||
461 | .name = "Leadtek Winfast USB II Deluxe", | 467 | .name = "Leadtek Winfast USB II Deluxe", |
462 | .valid = EM28XX_BOARD_NOT_VALIDATED, | 468 | .valid = EM28XX_BOARD_NOT_VALIDATED, |
463 | .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, | 469 | .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, |
464 | .tda9887_conf = TDA9887_PRESENT, | 470 | .has_ir_i2c = 1, |
471 | .tvaudio_addr = 0x58, | ||
472 | .tda9887_conf = TDA9887_PRESENT | | ||
473 | TDA9887_PORT2_ACTIVE | | ||
474 | TDA9887_QSS, | ||
465 | .decoder = EM28XX_SAA711X, | 475 | .decoder = EM28XX_SAA711X, |
476 | .adecoder = EM28XX_TVAUDIO, | ||
466 | .input = { { | 477 | .input = { { |
467 | .type = EM28XX_VMUX_TELEVISION, | 478 | .type = EM28XX_VMUX_TELEVISION, |
468 | .vmux = SAA7115_COMPOSITE2, | 479 | .vmux = SAA7115_COMPOSITE4, |
469 | .amux = EM28XX_AMUX_VIDEO, | 480 | .amux = EM28XX_AMUX_AUX, |
470 | }, { | 481 | }, { |
471 | .type = EM28XX_VMUX_COMPOSITE1, | 482 | .type = EM28XX_VMUX_COMPOSITE1, |
472 | .vmux = SAA7115_COMPOSITE0, | 483 | .vmux = SAA7115_COMPOSITE5, |
473 | .amux = EM28XX_AMUX_LINE_IN, | 484 | .amux = EM28XX_AMUX_LINE_IN, |
474 | }, { | 485 | }, { |
475 | .type = EM28XX_VMUX_SVIDEO, | 486 | .type = EM28XX_VMUX_SVIDEO, |
476 | .vmux = SAA7115_COMPOSITE0, | 487 | .vmux = SAA7115_SVIDEO3, |
477 | .amux = EM28XX_AMUX_LINE_IN, | 488 | .amux = EM28XX_AMUX_LINE_IN, |
478 | } }, | 489 | } }, |
490 | .radio = { | ||
491 | .type = EM28XX_RADIO, | ||
492 | .amux = EM28XX_AMUX_AUX, | ||
493 | } | ||
479 | }, | 494 | }, |
480 | [EM2820_BOARD_VIDEOLOGY_20K14XUSB] = { | 495 | [EM2820_BOARD_VIDEOLOGY_20K14XUSB] = { |
481 | .name = "Videology 20K14XUSB USB2.0", | 496 | .name = "Videology 20K14XUSB USB2.0", |
@@ -730,11 +745,12 @@ struct em28xx_board em28xx_boards[] = { | |||
730 | 745 | ||
731 | [EM2880_BOARD_TERRATEC_HYBRID_XS_FR] = { | 746 | [EM2880_BOARD_TERRATEC_HYBRID_XS_FR] = { |
732 | .name = "Terratec Hybrid XS Secam", | 747 | .name = "Terratec Hybrid XS Secam", |
733 | .valid = EM28XX_BOARD_NOT_VALIDATED, | ||
734 | .has_msp34xx = 1, | 748 | .has_msp34xx = 1, |
735 | .tuner_type = TUNER_XC2028, | 749 | .tuner_type = TUNER_XC2028, |
736 | .tuner_gpio = default_tuner_gpio, | 750 | .tuner_gpio = default_tuner_gpio, |
737 | .decoder = EM28XX_TVP5150, | 751 | .decoder = EM28XX_TVP5150, |
752 | .has_dvb = 1, | ||
753 | .dvb_gpio = default_digital, | ||
738 | .input = { { | 754 | .input = { { |
739 | .type = EM28XX_VMUX_TELEVISION, | 755 | .type = EM28XX_VMUX_TELEVISION, |
740 | .vmux = TVP5150_COMPOSITE0, | 756 | .vmux = TVP5150_COMPOSITE0, |
@@ -1265,6 +1281,7 @@ struct em28xx_board em28xx_boards[] = { | |||
1265 | .decoder = EM28XX_SAA711X, | 1281 | .decoder = EM28XX_SAA711X, |
1266 | .has_dvb = 1, | 1282 | .has_dvb = 1, |
1267 | .dvb_gpio = em2882_kworld_315u_digital, | 1283 | .dvb_gpio = em2882_kworld_315u_digital, |
1284 | .ir_codes = &ir_codes_kworld_315u_table, | ||
1268 | .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, | 1285 | .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, |
1269 | .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE, | 1286 | .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE, |
1270 | /* Analog mode - still not ready */ | 1287 | /* Analog mode - still not ready */ |
@@ -1431,6 +1448,21 @@ struct em28xx_board em28xx_boards[] = { | |||
1431 | .gpio = hauppauge_wintv_hvr_900_analog, | 1448 | .gpio = hauppauge_wintv_hvr_900_analog, |
1432 | } }, | 1449 | } }, |
1433 | }, | 1450 | }, |
1451 | [EM2882_BOARD_DIKOM_DK300] = { | ||
1452 | .name = "Dikom DK300", | ||
1453 | .tuner_type = TUNER_XC2028, | ||
1454 | .tuner_gpio = default_tuner_gpio, | ||
1455 | .decoder = EM28XX_TVP5150, | ||
1456 | .mts_firmware = 1, | ||
1457 | .has_dvb = 1, | ||
1458 | .dvb_gpio = dikom_dk300_digital, | ||
1459 | .input = { { | ||
1460 | .type = EM28XX_VMUX_TELEVISION, | ||
1461 | .vmux = TVP5150_COMPOSITE0, | ||
1462 | .amux = EM28XX_AMUX_VIDEO, | ||
1463 | .gpio = default_analog, | ||
1464 | } }, | ||
1465 | }, | ||
1434 | [EM2883_BOARD_KWORLD_HYBRID_330U] = { | 1466 | [EM2883_BOARD_KWORLD_HYBRID_330U] = { |
1435 | .name = "Kworld PlusTV HD Hybrid 330", | 1467 | .name = "Kworld PlusTV HD Hybrid 330", |
1436 | .tuner_type = TUNER_XC2028, | 1468 | .tuner_type = TUNER_XC2028, |
@@ -1751,6 +1783,7 @@ static struct em28xx_hash_table em28xx_eeprom_hash[] = { | |||
1751 | {0xcee44a99, EM2882_BOARD_EVGA_INDTUBE, TUNER_XC2028}, | 1783 | {0xcee44a99, EM2882_BOARD_EVGA_INDTUBE, TUNER_XC2028}, |
1752 | {0xb8846b20, EM2881_BOARD_PINNACLE_HYBRID_PRO, TUNER_XC2028}, | 1784 | {0xb8846b20, EM2881_BOARD_PINNACLE_HYBRID_PRO, TUNER_XC2028}, |
1753 | {0x63f653bd, EM2870_BOARD_REDDO_DVB_C_USB_BOX, TUNER_ABSENT}, | 1785 | {0x63f653bd, EM2870_BOARD_REDDO_DVB_C_USB_BOX, TUNER_ABSENT}, |
1786 | {0x4e913442, EM2882_BOARD_DIKOM_DK300, TUNER_XC2028}, | ||
1754 | }; | 1787 | }; |
1755 | 1788 | ||
1756 | /* I2C devicelist hash table for devices with generic USB IDs */ | 1789 | /* I2C devicelist hash table for devices with generic USB IDs */ |
@@ -2103,6 +2136,7 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) | |||
2103 | ctl->demod = XC3028_FE_DEFAULT; | 2136 | ctl->demod = XC3028_FE_DEFAULT; |
2104 | break; | 2137 | break; |
2105 | case EM2883_BOARD_KWORLD_HYBRID_330U: | 2138 | case EM2883_BOARD_KWORLD_HYBRID_330U: |
2139 | case EM2882_BOARD_DIKOM_DK300: | ||
2106 | ctl->demod = XC3028_FE_CHINA; | 2140 | ctl->demod = XC3028_FE_CHINA; |
2107 | ctl->fname = XC2028_DEFAULT_FIRMWARE; | 2141 | ctl->fname = XC2028_DEFAULT_FIRMWARE; |
2108 | break; | 2142 | break; |
@@ -2259,9 +2293,12 @@ static int em28xx_hint_board(struct em28xx *dev) | |||
2259 | /* ----------------------------------------------------------------------- */ | 2293 | /* ----------------------------------------------------------------------- */ |
2260 | void em28xx_register_i2c_ir(struct em28xx *dev) | 2294 | void em28xx_register_i2c_ir(struct em28xx *dev) |
2261 | { | 2295 | { |
2296 | /* Leadtek winfast tv USBII deluxe can find a non working IR-device */ | ||
2297 | /* at address 0x18, so if that address is needed for another board in */ | ||
2298 | /* the future, please put it after 0x1f. */ | ||
2262 | struct i2c_board_info info; | 2299 | struct i2c_board_info info; |
2263 | const unsigned short addr_list[] = { | 2300 | const unsigned short addr_list[] = { |
2264 | 0x30, 0x47, I2C_CLIENT_END | 2301 | 0x1f, 0x30, 0x47, I2C_CLIENT_END |
2265 | }; | 2302 | }; |
2266 | 2303 | ||
2267 | if (disable_ir) | 2304 | if (disable_ir) |
@@ -2288,6 +2325,10 @@ void em28xx_register_i2c_ir(struct em28xx *dev) | |||
2288 | dev->init_data.ir_codes = &ir_codes_rc5_hauppauge_new_table; | 2325 | dev->init_data.ir_codes = &ir_codes_rc5_hauppauge_new_table; |
2289 | dev->init_data.get_key = em28xx_get_key_em_haup; | 2326 | dev->init_data.get_key = em28xx_get_key_em_haup; |
2290 | dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; | 2327 | dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; |
2328 | case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE: | ||
2329 | dev->init_data.ir_codes = &ir_codes_winfast_usbii_deluxe_table;; | ||
2330 | dev->init_data.get_key = em28xx_get_key_winfast_usbii_deluxe; | ||
2331 | dev->init_data.name = "i2c IR (EM2820 Winfast TV USBII Deluxe)"; | ||
2291 | break; | 2332 | break; |
2292 | } | 2333 | } |
2293 | 2334 | ||
@@ -2381,6 +2422,31 @@ void em28xx_card_setup(struct em28xx *dev) | |||
2381 | em28xx_gpio_set(dev, dev->board.tuner_gpio); | 2422 | em28xx_gpio_set(dev, dev->board.tuner_gpio); |
2382 | em28xx_set_mode(dev, EM28XX_ANALOG_MODE); | 2423 | em28xx_set_mode(dev, EM28XX_ANALOG_MODE); |
2383 | break; | 2424 | break; |
2425 | |||
2426 | /* | ||
2427 | * The Dikom DK300 is detected as an Kworld VS-DVB-T 323UR. | ||
2428 | * | ||
2429 | * This occurs because they share identical USB vendor and | ||
2430 | * product IDs. | ||
2431 | * | ||
2432 | * What we do here is look up the EEPROM hash of the Dikom | ||
2433 | * and if it is found then we decide that we do not have | ||
2434 | * a Kworld and reset the device to the Dikom instead. | ||
2435 | * | ||
2436 | * This solution is only valid if they do not share eeprom | ||
2437 | * hash identities which has not been determined as yet. | ||
2438 | */ | ||
2439 | case EM2882_BOARD_KWORLD_VS_DVBT: | ||
2440 | if (!em28xx_hint_board(dev)) | ||
2441 | em28xx_set_model(dev); | ||
2442 | |||
2443 | /* In cases where we had to use a board hint, the call to | ||
2444 | em28xx_set_mode() in em28xx_pre_card_setup() was a no-op, | ||
2445 | so make the call now so the analog GPIOs are set properly | ||
2446 | before probing the i2c bus. */ | ||
2447 | em28xx_gpio_set(dev, dev->board.tuner_gpio); | ||
2448 | em28xx_set_mode(dev, EM28XX_ANALOG_MODE); | ||
2449 | break; | ||
2384 | } | 2450 | } |
2385 | 2451 | ||
2386 | #if defined(CONFIG_MODULES) && defined(MODULE) | 2452 | #if defined(CONFIG_MODULES) && defined(MODULE) |
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index b311d4514bdf..5a37eccbd7d6 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c | |||
@@ -691,9 +691,15 @@ int em28xx_set_outfmt(struct em28xx *dev) | |||
691 | if (em28xx_vbi_supported(dev) == 1) { | 691 | if (em28xx_vbi_supported(dev) == 1) { |
692 | vinctrl |= EM28XX_VINCTRL_VBI_RAW; | 692 | vinctrl |= EM28XX_VINCTRL_VBI_RAW; |
693 | em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00); | 693 | em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00); |
694 | em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09); | 694 | em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, dev->vbi_width/4); |
695 | em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, 0xb4); | 695 | em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, dev->vbi_height); |
696 | em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, 0x0c); | 696 | if (dev->norm & V4L2_STD_525_60) { |
697 | /* NTSC */ | ||
698 | em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09); | ||
699 | } else if (dev->norm & V4L2_STD_625_50) { | ||
700 | /* PAL */ | ||
701 | em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x07); | ||
702 | } | ||
697 | } | 703 | } |
698 | 704 | ||
699 | return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl); | 705 | return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl); |
@@ -760,6 +766,13 @@ int em28xx_resolution_set(struct em28xx *dev) | |||
760 | width = norm_maxw(dev); | 766 | width = norm_maxw(dev); |
761 | height = norm_maxh(dev); | 767 | height = norm_maxh(dev); |
762 | 768 | ||
769 | /* Properly setup VBI */ | ||
770 | dev->vbi_width = 720; | ||
771 | if (dev->norm & V4L2_STD_525_60) | ||
772 | dev->vbi_height = 12; | ||
773 | else | ||
774 | dev->vbi_height = 18; | ||
775 | |||
763 | if (!dev->progressive) | 776 | if (!dev->progressive) |
764 | height >>= norm_maxh(dev); | 777 | height >>= norm_maxh(dev); |
765 | 778 | ||
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index cc0505eb900f..1b96356b3ab2 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c | |||
@@ -502,7 +502,9 @@ static int dvb_init(struct em28xx *dev) | |||
502 | } | 502 | } |
503 | break; | 503 | break; |
504 | case EM2880_BOARD_TERRATEC_HYBRID_XS: | 504 | case EM2880_BOARD_TERRATEC_HYBRID_XS: |
505 | case EM2880_BOARD_TERRATEC_HYBRID_XS_FR: | ||
505 | case EM2881_BOARD_PINNACLE_HYBRID_PRO: | 506 | case EM2881_BOARD_PINNACLE_HYBRID_PRO: |
507 | case EM2882_BOARD_DIKOM_DK300: | ||
506 | dvb->frontend = dvb_attach(zl10353_attach, | 508 | dvb->frontend = dvb_attach(zl10353_attach, |
507 | &em28xx_zl10353_xc3028_no_i2c_gate, | 509 | &em28xx_zl10353_xc3028_no_i2c_gate, |
508 | &dev->i2c_adap); | 510 | &dev->i2c_adap); |
@@ -606,6 +608,7 @@ static int dvb_fini(struct em28xx *dev) | |||
606 | 608 | ||
607 | if (dev->dvb) { | 609 | if (dev->dvb) { |
608 | unregister_dvb(dev->dvb); | 610 | unregister_dvb(dev->dvb); |
611 | kfree(dev->dvb); | ||
609 | dev->dvb = NULL; | 612 | dev->dvb = NULL; |
610 | } | 613 | } |
611 | 614 | ||
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index af0d935c29be..1fb754e20875 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c | |||
@@ -75,6 +75,10 @@ struct em28xx_IR { | |||
75 | unsigned int repeat_interval; | 75 | unsigned int repeat_interval; |
76 | 76 | ||
77 | int (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *); | 77 | int (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *); |
78 | |||
79 | /* IR device properties */ | ||
80 | |||
81 | struct ir_dev_props props; | ||
78 | }; | 82 | }; |
79 | 83 | ||
80 | /********************************************************** | 84 | /********************************************************** |
@@ -180,6 +184,36 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, | |||
180 | return 1; | 184 | return 1; |
181 | } | 185 | } |
182 | 186 | ||
187 | int em28xx_get_key_winfast_usbii_deluxe(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | ||
188 | { | ||
189 | unsigned char subaddr, keydetect, key; | ||
190 | |||
191 | struct i2c_msg msg[] = { { .addr = ir->c->addr, .flags = 0, .buf = &subaddr, .len = 1}, | ||
192 | |||
193 | { .addr = ir->c->addr, .flags = I2C_M_RD, .buf = &keydetect, .len = 1} }; | ||
194 | |||
195 | subaddr = 0x10; | ||
196 | if (2 != i2c_transfer(ir->c->adapter, msg, 2)) { | ||
197 | i2cdprintk("read error\n"); | ||
198 | return -EIO; | ||
199 | } | ||
200 | if (keydetect == 0x00) | ||
201 | return 0; | ||
202 | |||
203 | subaddr = 0x00; | ||
204 | msg[1].buf = &key; | ||
205 | if (2 != i2c_transfer(ir->c->adapter, msg, 2)) { | ||
206 | i2cdprintk("read error\n"); | ||
207 | return -EIO; | ||
208 | } | ||
209 | if (key == 0x00) | ||
210 | return 0; | ||
211 | |||
212 | *ir_key = key; | ||
213 | *ir_raw = key; | ||
214 | return 1; | ||
215 | } | ||
216 | |||
183 | /********************************************************** | 217 | /********************************************************** |
184 | Poll based get keycode functions | 218 | Poll based get keycode functions |
185 | **********************************************************/ | 219 | **********************************************************/ |
@@ -336,35 +370,28 @@ static void em28xx_ir_stop(struct em28xx_IR *ir) | |||
336 | cancel_delayed_work_sync(&ir->work); | 370 | cancel_delayed_work_sync(&ir->work); |
337 | } | 371 | } |
338 | 372 | ||
339 | int em28xx_ir_init(struct em28xx *dev) | 373 | int em28xx_ir_change_protocol(void *priv, u64 ir_type) |
340 | { | 374 | { |
341 | struct em28xx_IR *ir; | 375 | int rc = 0; |
342 | struct input_dev *input_dev; | 376 | struct em28xx_IR *ir = priv; |
343 | u8 ir_config; | 377 | struct em28xx *dev = ir->dev; |
344 | int err = -ENOMEM; | 378 | u8 ir_config = EM2874_IR_RC5; |
345 | |||
346 | if (dev->board.ir_codes == NULL) { | ||
347 | /* No remote control support */ | ||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); | ||
352 | input_dev = input_allocate_device(); | ||
353 | if (!ir || !input_dev) | ||
354 | goto err_out_free; | ||
355 | |||
356 | ir->input = input_dev; | ||
357 | ir_config = EM2874_IR_RC5; | ||
358 | 379 | ||
359 | /* Adjust xclk based o IR table for RC5/NEC tables */ | 380 | /* Adjust xclk based o IR table for RC5/NEC tables */ |
360 | if (dev->board.ir_codes->ir_type == IR_TYPE_RC5) { | 381 | |
382 | dev->board.ir_codes->ir_type = IR_TYPE_OTHER; | ||
383 | if (ir_type == IR_TYPE_RC5) { | ||
361 | dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE; | 384 | dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE; |
362 | ir->full_code = 1; | 385 | ir->full_code = 1; |
363 | } else if (dev->board.ir_codes->ir_type == IR_TYPE_NEC) { | 386 | } else if (ir_type == IR_TYPE_NEC) { |
364 | dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE; | 387 | dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE; |
365 | ir_config = EM2874_IR_NEC; | 388 | ir_config = EM2874_IR_NEC; |
366 | ir->full_code = 1; | 389 | ir->full_code = 1; |
367 | } | 390 | } else |
391 | rc = -EINVAL; | ||
392 | |||
393 | dev->board.ir_codes->ir_type = ir_type; | ||
394 | |||
368 | em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk, | 395 | em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk, |
369 | EM28XX_XCLK_IR_RC5_MODE); | 396 | EM28XX_XCLK_IR_RC5_MODE); |
370 | 397 | ||
@@ -380,9 +407,42 @@ int em28xx_ir_init(struct em28xx *dev) | |||
380 | break; | 407 | break; |
381 | default: | 408 | default: |
382 | printk("Unrecognized em28xx chip id: IR not supported\n"); | 409 | printk("Unrecognized em28xx chip id: IR not supported\n"); |
383 | goto err_out_free; | 410 | rc = -EINVAL; |
411 | } | ||
412 | |||
413 | return rc; | ||
414 | } | ||
415 | |||
416 | int em28xx_ir_init(struct em28xx *dev) | ||
417 | { | ||
418 | struct em28xx_IR *ir; | ||
419 | struct input_dev *input_dev; | ||
420 | int err = -ENOMEM; | ||
421 | |||
422 | if (dev->board.ir_codes == NULL) { | ||
423 | /* No remote control support */ | ||
424 | return 0; | ||
384 | } | 425 | } |
385 | 426 | ||
427 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); | ||
428 | input_dev = input_allocate_device(); | ||
429 | if (!ir || !input_dev) | ||
430 | goto err_out_free; | ||
431 | |||
432 | /* record handles to ourself */ | ||
433 | ir->dev = dev; | ||
434 | dev->ir = ir; | ||
435 | |||
436 | ir->input = input_dev; | ||
437 | |||
438 | /* | ||
439 | * em2874 supports more protocols. For now, let's just announce | ||
440 | * the two protocols that were already tested | ||
441 | */ | ||
442 | ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC; | ||
443 | ir->props.priv = ir; | ||
444 | ir->props.change_protocol = em28xx_ir_change_protocol; | ||
445 | |||
386 | /* This is how often we ask the chip for IR information */ | 446 | /* This is how often we ask the chip for IR information */ |
387 | ir->polling = 100; /* ms */ | 447 | ir->polling = 100; /* ms */ |
388 | 448 | ||
@@ -393,6 +453,8 @@ int em28xx_ir_init(struct em28xx *dev) | |||
393 | usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); | 453 | usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); |
394 | strlcat(ir->phys, "/input0", sizeof(ir->phys)); | 454 | strlcat(ir->phys, "/input0", sizeof(ir->phys)); |
395 | 455 | ||
456 | /* Set IR protocol */ | ||
457 | em28xx_ir_change_protocol(ir, dev->board.ir_codes->ir_type); | ||
396 | err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER); | 458 | err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER); |
397 | if (err < 0) | 459 | if (err < 0) |
398 | goto err_out_free; | 460 | goto err_out_free; |
@@ -405,14 +467,13 @@ int em28xx_ir_init(struct em28xx *dev) | |||
405 | input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct); | 467 | input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct); |
406 | 468 | ||
407 | input_dev->dev.parent = &dev->udev->dev; | 469 | input_dev->dev.parent = &dev->udev->dev; |
408 | /* record handles to ourself */ | 470 | |
409 | ir->dev = dev; | ||
410 | dev->ir = ir; | ||
411 | 471 | ||
412 | em28xx_ir_start(ir); | 472 | em28xx_ir_start(ir); |
413 | 473 | ||
414 | /* all done */ | 474 | /* all done */ |
415 | err = ir_input_register(ir->input, dev->board.ir_codes); | 475 | err = ir_input_register(ir->input, dev->board.ir_codes, |
476 | &ir->props); | ||
416 | if (err) | 477 | if (err) |
417 | goto err_out_stop; | 478 | goto err_out_stop; |
418 | 479 | ||
diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/video/em28xx/em28xx-reg.h index 058ac87639ce..91e90559642b 100644 --- a/drivers/media/video/em28xx/em28xx-reg.h +++ b/drivers/media/video/em28xx/em28xx-reg.h | |||
@@ -173,8 +173,8 @@ | |||
173 | /* em2874 IR config register (0x50) */ | 173 | /* em2874 IR config register (0x50) */ |
174 | #define EM2874_IR_NEC 0x00 | 174 | #define EM2874_IR_NEC 0x00 |
175 | #define EM2874_IR_RC5 0x04 | 175 | #define EM2874_IR_RC5 0x04 |
176 | #define EM2874_IR_RC5_MODE_0 0x08 | 176 | #define EM2874_IR_RC6_MODE_0 0x08 |
177 | #define EM2874_IR_RC5_MODE_6A 0x0b | 177 | #define EM2874_IR_RC6_MODE_6A 0x0b |
178 | 178 | ||
179 | /* em2874 Transport Stream Enable Register (0x5f) */ | 179 | /* em2874 Transport Stream Enable Register (0x5f) */ |
180 | #define EM2874_TS1_CAPTURE_ENABLE (1 << 0) | 180 | #define EM2874_TS1_CAPTURE_ENABLE (1 << 0) |
diff --git a/drivers/media/video/em28xx/em28xx-vbi.c b/drivers/media/video/em28xx/em28xx-vbi.c index 94943e5a1529..c7dce39823d8 100644 --- a/drivers/media/video/em28xx/em28xx-vbi.c +++ b/drivers/media/video/em28xx/em28xx-vbi.c | |||
@@ -71,7 +71,11 @@ free_buffer(struct videobuf_queue *vq, struct em28xx_buffer *buf) | |||
71 | static int | 71 | static int |
72 | vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) | 72 | vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) |
73 | { | 73 | { |
74 | *size = 720 * 12 * 2; | 74 | struct em28xx_fh *fh = q->priv_data; |
75 | struct em28xx *dev = fh->dev; | ||
76 | |||
77 | *size = dev->vbi_width * dev->vbi_height * 2; | ||
78 | |||
75 | if (0 == *count) | 79 | if (0 == *count) |
76 | *count = vbibufs; | 80 | *count = vbibufs; |
77 | if (*count < 2) | 81 | if (*count < 2) |
@@ -85,19 +89,18 @@ static int | |||
85 | vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | 89 | vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, |
86 | enum v4l2_field field) | 90 | enum v4l2_field field) |
87 | { | 91 | { |
92 | struct em28xx_fh *fh = q->priv_data; | ||
93 | struct em28xx *dev = fh->dev; | ||
88 | struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); | 94 | struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb); |
89 | int rc = 0; | 95 | int rc = 0; |
90 | unsigned int size; | ||
91 | |||
92 | size = 720 * 12 * 2; | ||
93 | 96 | ||
94 | buf->vb.size = size; | 97 | buf->vb.size = dev->vbi_width * dev->vbi_height * 2; |
95 | 98 | ||
96 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) | 99 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) |
97 | return -EINVAL; | 100 | return -EINVAL; |
98 | 101 | ||
99 | buf->vb.width = 720; | 102 | buf->vb.width = dev->vbi_width; |
100 | buf->vb.height = 12; | 103 | buf->vb.height = dev->vbi_height; |
101 | buf->vb.field = field; | 104 | buf->vb.field = field; |
102 | 105 | ||
103 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | 106 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { |
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 849b18c94037..ac2bd935927e 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -282,7 +282,7 @@ static void em28xx_copy_vbi(struct em28xx *dev, | |||
282 | { | 282 | { |
283 | void *startwrite, *startread; | 283 | void *startwrite, *startread; |
284 | int offset; | 284 | int offset; |
285 | int bytesperline = 720; | 285 | int bytesperline = dev->vbi_width; |
286 | 286 | ||
287 | if (dev == NULL) { | 287 | if (dev == NULL) { |
288 | em28xx_isocdbg("dev is null\n"); | 288 | em28xx_isocdbg("dev is null\n"); |
@@ -323,8 +323,8 @@ static void em28xx_copy_vbi(struct em28xx *dev, | |||
323 | 323 | ||
324 | /* Make sure the bottom field populates the second half of the frame */ | 324 | /* Make sure the bottom field populates the second half of the frame */ |
325 | if (buf->top_field == 0) { | 325 | if (buf->top_field == 0) { |
326 | startwrite += bytesperline * 0x0c; | 326 | startwrite += bytesperline * dev->vbi_height; |
327 | offset += bytesperline * 0x0c; | 327 | offset += bytesperline * dev->vbi_height; |
328 | } | 328 | } |
329 | 329 | ||
330 | memcpy(startwrite, startread, len); | 330 | memcpy(startwrite, startread, len); |
@@ -578,8 +578,7 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) | |||
578 | dev->cur_field = p[2]; | 578 | dev->cur_field = p[2]; |
579 | } | 579 | } |
580 | 580 | ||
581 | /* FIXME: get rid of hard-coded value */ | 581 | vbi_size = dev->vbi_width * dev->vbi_height; |
582 | vbi_size = 720 * 0x0c; | ||
583 | 582 | ||
584 | if (dev->capture_type == 0) { | 583 | if (dev->capture_type == 0) { |
585 | if (dev->vbi_read >= vbi_size) { | 584 | if (dev->vbi_read >= vbi_size) { |
@@ -1850,18 +1849,27 @@ static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv, | |||
1850 | static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, | 1849 | static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, |
1851 | struct v4l2_format *format) | 1850 | struct v4l2_format *format) |
1852 | { | 1851 | { |
1853 | format->fmt.vbi.samples_per_line = 720; | 1852 | struct em28xx_fh *fh = priv; |
1853 | struct em28xx *dev = fh->dev; | ||
1854 | |||
1855 | format->fmt.vbi.samples_per_line = dev->vbi_width; | ||
1854 | format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; | 1856 | format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; |
1855 | format->fmt.vbi.offset = 0; | 1857 | format->fmt.vbi.offset = 0; |
1856 | format->fmt.vbi.flags = 0; | 1858 | format->fmt.vbi.flags = 0; |
1859 | format->fmt.vbi.sampling_rate = 6750000 * 4 / 2; | ||
1860 | format->fmt.vbi.count[0] = dev->vbi_height; | ||
1861 | format->fmt.vbi.count[1] = dev->vbi_height; | ||
1857 | 1862 | ||
1858 | /* Varies by video standard (NTSC, PAL, etc.) */ | 1863 | /* Varies by video standard (NTSC, PAL, etc.) */ |
1859 | /* FIXME: hard-coded for NTSC support */ | 1864 | if (dev->norm & V4L2_STD_525_60) { |
1860 | format->fmt.vbi.sampling_rate = 6750000 * 4 / 2; /* FIXME: ??? */ | 1865 | /* NTSC */ |
1861 | format->fmt.vbi.count[0] = 12; | 1866 | format->fmt.vbi.start[0] = 10; |
1862 | format->fmt.vbi.count[1] = 12; | 1867 | format->fmt.vbi.start[1] = 273; |
1863 | format->fmt.vbi.start[0] = 10; | 1868 | } else if (dev->norm & V4L2_STD_625_50) { |
1864 | format->fmt.vbi.start[1] = 273; | 1869 | /* PAL */ |
1870 | format->fmt.vbi.start[0] = 6; | ||
1871 | format->fmt.vbi.start[1] = 318; | ||
1872 | } | ||
1865 | 1873 | ||
1866 | return 0; | 1874 | return 0; |
1867 | } | 1875 | } |
@@ -1869,18 +1877,27 @@ static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, | |||
1869 | static int vidioc_s_fmt_vbi_cap(struct file *file, void *priv, | 1877 | static int vidioc_s_fmt_vbi_cap(struct file *file, void *priv, |
1870 | struct v4l2_format *format) | 1878 | struct v4l2_format *format) |
1871 | { | 1879 | { |
1872 | format->fmt.vbi.samples_per_line = 720; | 1880 | struct em28xx_fh *fh = priv; |
1881 | struct em28xx *dev = fh->dev; | ||
1882 | |||
1883 | format->fmt.vbi.samples_per_line = dev->vbi_width; | ||
1873 | format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; | 1884 | format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; |
1874 | format->fmt.vbi.offset = 0; | 1885 | format->fmt.vbi.offset = 0; |
1875 | format->fmt.vbi.flags = 0; | 1886 | format->fmt.vbi.flags = 0; |
1887 | format->fmt.vbi.sampling_rate = 6750000 * 4 / 2; | ||
1888 | format->fmt.vbi.count[0] = dev->vbi_height; | ||
1889 | format->fmt.vbi.count[1] = dev->vbi_height; | ||
1876 | 1890 | ||
1877 | /* Varies by video standard (NTSC, PAL, etc.) */ | 1891 | /* Varies by video standard (NTSC, PAL, etc.) */ |
1878 | /* FIXME: hard-coded for NTSC support */ | 1892 | if (dev->norm & V4L2_STD_525_60) { |
1879 | format->fmt.vbi.sampling_rate = 6750000 * 4 / 2; /* FIXME: ??? */ | 1893 | /* NTSC */ |
1880 | format->fmt.vbi.count[0] = 12; | 1894 | format->fmt.vbi.start[0] = 10; |
1881 | format->fmt.vbi.count[1] = 12; | 1895 | format->fmt.vbi.start[1] = 273; |
1882 | format->fmt.vbi.start[0] = 10; | 1896 | } else if (dev->norm & V4L2_STD_625_50) { |
1883 | format->fmt.vbi.start[1] = 273; | 1897 | /* PAL */ |
1898 | format->fmt.vbi.start[0] = 6; | ||
1899 | format->fmt.vbi.start[1] = 318; | ||
1900 | } | ||
1884 | 1901 | ||
1885 | return 0; | 1902 | return 0; |
1886 | } | 1903 | } |
@@ -1922,7 +1939,8 @@ static int vidioc_querybuf(struct file *file, void *priv, | |||
1922 | At a minimum, it causes a crash in zvbi since it does | 1939 | At a minimum, it causes a crash in zvbi since it does |
1923 | a memcpy based on the source buffer length */ | 1940 | a memcpy based on the source buffer length */ |
1924 | int result = videobuf_querybuf(&fh->vb_vbiq, b); | 1941 | int result = videobuf_querybuf(&fh->vb_vbiq, b); |
1925 | b->length = 17280; | 1942 | b->length = dev->vbi_width * dev->vbi_height * 2; |
1943 | |||
1926 | return result; | 1944 | return result; |
1927 | } | 1945 | } |
1928 | } | 1946 | } |
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 80d9b4fa1b97..ba6fe5daff84 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
@@ -111,6 +111,7 @@ | |||
111 | #define EM2861_BOARD_GADMEI_UTV330PLUS 72 | 111 | #define EM2861_BOARD_GADMEI_UTV330PLUS 72 |
112 | #define EM2870_BOARD_REDDO_DVB_C_USB_BOX 73 | 112 | #define EM2870_BOARD_REDDO_DVB_C_USB_BOX 73 |
113 | #define EM2800_BOARD_VC211A 74 | 113 | #define EM2800_BOARD_VC211A 74 |
114 | #define EM2882_BOARD_DIKOM_DK300 75 | ||
114 | 115 | ||
115 | /* Limits minimum and default number of buffers */ | 116 | /* Limits minimum and default number of buffers */ |
116 | #define EM28XX_MIN_BUF 4 | 117 | #define EM28XX_MIN_BUF 4 |
@@ -552,7 +553,8 @@ struct em28xx { | |||
552 | int capture_type; | 553 | int capture_type; |
553 | int vbi_read; | 554 | int vbi_read; |
554 | unsigned char cur_field; | 555 | unsigned char cur_field; |
555 | 556 | unsigned int vbi_width; | |
557 | unsigned int vbi_height; /* lines per field */ | ||
556 | 558 | ||
557 | struct work_struct request_module_wk; | 559 | struct work_struct request_module_wk; |
558 | 560 | ||
@@ -693,6 +695,8 @@ int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw); | |||
693 | int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw); | 695 | int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw); |
694 | int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, | 696 | int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, |
695 | u32 *ir_raw); | 697 | u32 *ir_raw); |
698 | int em28xx_get_key_winfast_usbii_deluxe(struct IR_i2c *ir, u32 *ir_key, | ||
699 | u32 *ir_raw); | ||
696 | void em28xx_register_snapshot_button(struct em28xx *dev); | 700 | void em28xx_register_snapshot_button(struct em28xx *dev); |
697 | void em28xx_deregister_snapshot_button(struct em28xx *dev); | 701 | void em28xx_deregister_snapshot_button(struct em28xx *dev); |
698 | 702 | ||
diff --git a/drivers/media/video/et61x251/Kconfig b/drivers/media/video/et61x251/Kconfig index dcc1a0335440..87981b078fe6 100644 --- a/drivers/media/video/et61x251/Kconfig +++ b/drivers/media/video/et61x251/Kconfig | |||
@@ -1,7 +1,11 @@ | |||
1 | config USB_ET61X251 | 1 | config USB_ET61X251 |
2 | tristate "USB ET61X[12]51 PC Camera Controller support" | 2 | tristate "USB ET61X[12]51 PC Camera Controller support (DEPRECATED)" |
3 | depends on VIDEO_V4L2 | 3 | depends on VIDEO_V4L2 |
4 | default n | ||
4 | ---help--- | 5 | ---help--- |
6 | This driver is DEPRECATED please use the gspca zc3xx module | ||
7 | instead. | ||
8 | |||
5 | Say Y here if you want support for cameras based on Etoms ET61X151 | 9 | Say Y here if you want support for cameras based on Etoms ET61X151 |
6 | or ET61X251 PC Camera Controllers. | 10 | or ET61X251 PC Camera Controllers. |
7 | 11 | ||
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index 609d65b0b10d..e0060c1f0544 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig | |||
@@ -21,6 +21,15 @@ source "drivers/media/video/gspca/m5602/Kconfig" | |||
21 | source "drivers/media/video/gspca/stv06xx/Kconfig" | 21 | source "drivers/media/video/gspca/stv06xx/Kconfig" |
22 | source "drivers/media/video/gspca/gl860/Kconfig" | 22 | source "drivers/media/video/gspca/gl860/Kconfig" |
23 | 23 | ||
24 | config USB_GSPCA_BENQ | ||
25 | tristate "Benq USB Camera Driver" | ||
26 | depends on VIDEO_V4L2 && USB_GSPCA | ||
27 | help | ||
28 | Say Y here if you want support for the Benq DC E300 camera. | ||
29 | |||
30 | To compile this driver as a module, choose M here: the | ||
31 | module will be called gspca_benq. | ||
32 | |||
24 | config USB_GSPCA_CONEX | 33 | config USB_GSPCA_CONEX |
25 | tristate "Conexant Camera Driver" | 34 | tristate "Conexant Camera Driver" |
26 | depends on VIDEO_V4L2 && USB_GSPCA | 35 | depends on VIDEO_V4L2 && USB_GSPCA |
@@ -30,6 +39,17 @@ config USB_GSPCA_CONEX | |||
30 | To compile this driver as a module, choose M here: the | 39 | To compile this driver as a module, choose M here: the |
31 | module will be called gspca_conex. | 40 | module will be called gspca_conex. |
32 | 41 | ||
42 | config USB_GSPCA_CPIA1 | ||
43 | tristate "cpia CPiA (version 1) Camera Driver" | ||
44 | depends on VIDEO_V4L2 && USB_GSPCA | ||
45 | help | ||
46 | Say Y here if you want support for USB cameras based on the cpia | ||
47 | CPiA chip. Note that you need atleast version 0.6.4 of libv4l for | ||
48 | applications to understand the videoformat generated by this driver. | ||
49 | |||
50 | To compile this driver as a module, choose M here: the | ||
51 | module will be called gspca_cpia1. | ||
52 | |||
33 | config USB_GSPCA_ETOMS | 53 | config USB_GSPCA_ETOMS |
34 | tristate "Etoms USB Camera Driver" | 54 | tristate "Etoms USB Camera Driver" |
35 | depends on VIDEO_V4L2 && USB_GSPCA | 55 | depends on VIDEO_V4L2 && USB_GSPCA |
@@ -86,15 +106,25 @@ config USB_GSPCA_OV519 | |||
86 | module will be called gspca_ov519. | 106 | module will be called gspca_ov519. |
87 | 107 | ||
88 | config USB_GSPCA_OV534 | 108 | config USB_GSPCA_OV534 |
89 | tristate "OV534 USB Camera Driver" | 109 | tristate "OV534 OV772x USB Camera Driver" |
90 | depends on VIDEO_V4L2 && USB_GSPCA | 110 | depends on VIDEO_V4L2 && USB_GSPCA |
91 | help | 111 | help |
92 | Say Y here if you want support for cameras based on the OV534 chip. | 112 | Say Y here if you want support for cameras based on the OV534 chip |
93 | (e.g. Sony Playstation EYE) | 113 | and sensor OV772x (e.g. Sony Playstation EYE) |
94 | 114 | ||
95 | To compile this driver as a module, choose M here: the | 115 | To compile this driver as a module, choose M here: the |
96 | module will be called gspca_ov534. | 116 | module will be called gspca_ov534. |
97 | 117 | ||
118 | config USB_GSPCA_OV534_9 | ||
119 | tristate "OV534 OV965x USB Camera Driver" | ||
120 | depends on VIDEO_V4L2 && USB_GSPCA | ||
121 | help | ||
122 | Say Y here if you want support for cameras based on the OV534 chip | ||
123 | and sensor OV965x (e.g. Hercules Dualpix) | ||
124 | |||
125 | To compile this driver as a module, choose M here: the | ||
126 | module will be called gspca_ov534_9. | ||
127 | |||
98 | config USB_GSPCA_PAC207 | 128 | config USB_GSPCA_PAC207 |
99 | tristate "Pixart PAC207 USB Camera Driver" | 129 | tristate "Pixart PAC207 USB Camera Driver" |
100 | depends on VIDEO_V4L2 && USB_GSPCA | 130 | depends on VIDEO_V4L2 && USB_GSPCA |
@@ -122,6 +152,16 @@ config USB_GSPCA_PAC7311 | |||
122 | To compile this driver as a module, choose M here: the | 152 | To compile this driver as a module, choose M here: the |
123 | module will be called gspca_pac7311. | 153 | module will be called gspca_pac7311. |
124 | 154 | ||
155 | config USB_GSPCA_SN9C2028 | ||
156 | tristate "SONIX Dual-Mode USB Camera Driver" | ||
157 | depends on VIDEO_V4L2 && USB_GSPCA | ||
158 | help | ||
159 | Say Y here if you want streaming support for Sonix SN9C2028 cameras. | ||
160 | These are supported as stillcams in libgphoto2/camlibs/sonix. | ||
161 | |||
162 | To compile this driver as a module, choose M here: the | ||
163 | module will be called gspca_sn9c2028. | ||
164 | |||
125 | config USB_GSPCA_SN9C20X | 165 | config USB_GSPCA_SN9C20X |
126 | tristate "SN9C20X USB Camera Driver" | 166 | tristate "SN9C20X USB Camera Driver" |
127 | depends on VIDEO_V4L2 && USB_GSPCA | 167 | depends on VIDEO_V4L2 && USB_GSPCA |
diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile index ff2c7279d82e..6e4cf1ce01c9 100644 --- a/drivers/media/video/gspca/Makefile +++ b/drivers/media/video/gspca/Makefile | |||
@@ -1,5 +1,7 @@ | |||
1 | obj-$(CONFIG_USB_GSPCA) += gspca_main.o | 1 | obj-$(CONFIG_USB_GSPCA) += gspca_main.o |
2 | obj-$(CONFIG_USB_GSPCA_BENQ) += gspca_benq.o | ||
2 | obj-$(CONFIG_USB_GSPCA_CONEX) += gspca_conex.o | 3 | obj-$(CONFIG_USB_GSPCA_CONEX) += gspca_conex.o |
4 | obj-$(CONFIG_USB_GSPCA_CPIA1) += gspca_cpia1.o | ||
3 | obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o | 5 | obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o |
4 | obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o | 6 | obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o |
5 | obj-$(CONFIG_USB_GSPCA_JEILINJ) += gspca_jeilinj.o | 7 | obj-$(CONFIG_USB_GSPCA_JEILINJ) += gspca_jeilinj.o |
@@ -7,9 +9,11 @@ obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o | |||
7 | obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o | 9 | obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o |
8 | obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o | 10 | obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o |
9 | obj-$(CONFIG_USB_GSPCA_OV534) += gspca_ov534.o | 11 | obj-$(CONFIG_USB_GSPCA_OV534) += gspca_ov534.o |
12 | obj-$(CONFIG_USB_GSPCA_OV534_9) += gspca_ov534_9.o | ||
10 | obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o | 13 | obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o |
11 | obj-$(CONFIG_USB_GSPCA_PAC7302) += gspca_pac7302.o | 14 | obj-$(CONFIG_USB_GSPCA_PAC7302) += gspca_pac7302.o |
12 | obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o | 15 | obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o |
16 | obj-$(CONFIG_USB_GSPCA_SN9C2028) += gspca_sn9c2028.o | ||
13 | obj-$(CONFIG_USB_GSPCA_SN9C20X) += gspca_sn9c20x.o | 17 | obj-$(CONFIG_USB_GSPCA_SN9C20X) += gspca_sn9c20x.o |
14 | obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o | 18 | obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o |
15 | obj-$(CONFIG_USB_GSPCA_SONIXJ) += gspca_sonixj.o | 19 | obj-$(CONFIG_USB_GSPCA_SONIXJ) += gspca_sonixj.o |
@@ -30,7 +34,9 @@ obj-$(CONFIG_USB_GSPCA_VC032X) += gspca_vc032x.o | |||
30 | obj-$(CONFIG_USB_GSPCA_ZC3XX) += gspca_zc3xx.o | 34 | obj-$(CONFIG_USB_GSPCA_ZC3XX) += gspca_zc3xx.o |
31 | 35 | ||
32 | gspca_main-objs := gspca.o | 36 | gspca_main-objs := gspca.o |
37 | gspca_benq-objs := benq.o | ||
33 | gspca_conex-objs := conex.o | 38 | gspca_conex-objs := conex.o |
39 | gspca_cpia1-objs := cpia1.o | ||
34 | gspca_etoms-objs := etoms.o | 40 | gspca_etoms-objs := etoms.o |
35 | gspca_finepix-objs := finepix.o | 41 | gspca_finepix-objs := finepix.o |
36 | gspca_jeilinj-objs := jeilinj.o | 42 | gspca_jeilinj-objs := jeilinj.o |
@@ -38,9 +44,11 @@ gspca_mars-objs := mars.o | |||
38 | gspca_mr97310a-objs := mr97310a.o | 44 | gspca_mr97310a-objs := mr97310a.o |
39 | gspca_ov519-objs := ov519.o | 45 | gspca_ov519-objs := ov519.o |
40 | gspca_ov534-objs := ov534.o | 46 | gspca_ov534-objs := ov534.o |
47 | gspca_ov534_9-objs := ov534_9.o | ||
41 | gspca_pac207-objs := pac207.o | 48 | gspca_pac207-objs := pac207.o |
42 | gspca_pac7302-objs := pac7302.o | 49 | gspca_pac7302-objs := pac7302.o |
43 | gspca_pac7311-objs := pac7311.o | 50 | gspca_pac7311-objs := pac7311.o |
51 | gspca_sn9c2028-objs := sn9c2028.o | ||
44 | gspca_sn9c20x-objs := sn9c20x.o | 52 | gspca_sn9c20x-objs := sn9c20x.o |
45 | gspca_sonixb-objs := sonixb.o | 53 | gspca_sonixb-objs := sonixb.o |
46 | gspca_sonixj-objs := sonixj.o | 54 | gspca_sonixj-objs := sonixj.o |
diff --git a/drivers/media/video/gspca/benq.c b/drivers/media/video/gspca/benq.c new file mode 100644 index 000000000000..43ac4af8d3ed --- /dev/null +++ b/drivers/media/video/gspca/benq.c | |||
@@ -0,0 +1,322 @@ | |||
1 | /* | ||
2 | * Benq DC E300 subdriver | ||
3 | * | ||
4 | * Copyright (C) 2009 Jean-Francois Moine (http://moinejf.free.fr) | ||
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 as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #define MODULE_NAME "benq" | ||
22 | |||
23 | #include "gspca.h" | ||
24 | |||
25 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | ||
26 | MODULE_DESCRIPTION("Benq DC E300 USB Camera Driver"); | ||
27 | MODULE_LICENSE("GPL"); | ||
28 | |||
29 | /* specific webcam descriptor */ | ||
30 | struct sd { | ||
31 | struct gspca_dev gspca_dev; /* !! must be the first item */ | ||
32 | }; | ||
33 | |||
34 | /* V4L2 controls supported by the driver */ | ||
35 | static const struct ctrl sd_ctrls[] = { | ||
36 | }; | ||
37 | |||
38 | static const struct v4l2_pix_format vga_mode[] = { | ||
39 | {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
40 | .bytesperline = 320, | ||
41 | .sizeimage = 320 * 240 * 3 / 8 + 590, | ||
42 | .colorspace = V4L2_COLORSPACE_JPEG}, | ||
43 | }; | ||
44 | |||
45 | static void sd_isoc_irq(struct urb *urb); | ||
46 | |||
47 | /* -- write a register -- */ | ||
48 | static void reg_w(struct gspca_dev *gspca_dev, | ||
49 | u16 value, u16 index) | ||
50 | { | ||
51 | struct usb_device *dev = gspca_dev->dev; | ||
52 | int ret; | ||
53 | |||
54 | if (gspca_dev->usb_err < 0) | ||
55 | return; | ||
56 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
57 | 0x02, | ||
58 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
59 | value, | ||
60 | index, | ||
61 | NULL, | ||
62 | 0, | ||
63 | 500); | ||
64 | if (ret < 0) { | ||
65 | PDEBUG(D_ERR, "reg_w err %d", ret); | ||
66 | gspca_dev->usb_err = ret; | ||
67 | } | ||
68 | } | ||
69 | |||
70 | /* this function is called at probe time */ | ||
71 | static int sd_config(struct gspca_dev *gspca_dev, | ||
72 | const struct usb_device_id *id) | ||
73 | { | ||
74 | gspca_dev->cam.cam_mode = vga_mode; | ||
75 | gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode); | ||
76 | gspca_dev->cam.no_urb_create = 1; | ||
77 | gspca_dev->cam.reverse_alts = 1; | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | /* this function is called at probe and resume time */ | ||
82 | static int sd_init(struct gspca_dev *gspca_dev) | ||
83 | { | ||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static int sd_isoc_init(struct gspca_dev *gspca_dev) | ||
88 | { | ||
89 | int ret; | ||
90 | |||
91 | ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, | ||
92 | gspca_dev->nbalt - 1); | ||
93 | if (ret < 0) { | ||
94 | err("usb_set_interface failed"); | ||
95 | return ret; | ||
96 | } | ||
97 | /* reg_w(gspca_dev, 0x0003, 0x0002); */ | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | /* -- start the camera -- */ | ||
102 | static int sd_start(struct gspca_dev *gspca_dev) | ||
103 | { | ||
104 | struct urb *urb; | ||
105 | int i, n; | ||
106 | |||
107 | /* create 4 URBs - 2 on endpoint 0x83 and 2 on 0x082 */ | ||
108 | #if MAX_NURBS < 4 | ||
109 | #error "Not enough URBs in the gspca table" | ||
110 | #endif | ||
111 | #define SD_PKT_SZ 64 | ||
112 | #define SD_NPKT 32 | ||
113 | for (n = 0; n < 4; n++) { | ||
114 | urb = usb_alloc_urb(SD_NPKT, GFP_KERNEL); | ||
115 | if (!urb) { | ||
116 | err("usb_alloc_urb failed"); | ||
117 | return -ENOMEM; | ||
118 | } | ||
119 | gspca_dev->urb[n] = urb; | ||
120 | urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev, | ||
121 | SD_PKT_SZ * SD_NPKT, | ||
122 | GFP_KERNEL, | ||
123 | &urb->transfer_dma); | ||
124 | |||
125 | if (urb->transfer_buffer == NULL) { | ||
126 | err("usb_buffer_alloc failed"); | ||
127 | return -ENOMEM; | ||
128 | } | ||
129 | urb->dev = gspca_dev->dev; | ||
130 | urb->context = gspca_dev; | ||
131 | urb->transfer_buffer_length = SD_PKT_SZ * SD_NPKT; | ||
132 | urb->pipe = usb_rcvisocpipe(gspca_dev->dev, | ||
133 | n & 1 ? 0x82 : 0x83); | ||
134 | urb->transfer_flags = URB_ISO_ASAP | ||
135 | | URB_NO_TRANSFER_DMA_MAP; | ||
136 | urb->interval = 1; | ||
137 | urb->complete = sd_isoc_irq; | ||
138 | urb->number_of_packets = SD_NPKT; | ||
139 | for (i = 0; i < SD_NPKT; i++) { | ||
140 | urb->iso_frame_desc[i].length = SD_PKT_SZ; | ||
141 | urb->iso_frame_desc[i].offset = SD_PKT_SZ * i; | ||
142 | } | ||
143 | } | ||
144 | |||
145 | return gspca_dev->usb_err; | ||
146 | } | ||
147 | |||
148 | static void sd_stopN(struct gspca_dev *gspca_dev) | ||
149 | { | ||
150 | reg_w(gspca_dev, 0x003c, 0x0003); | ||
151 | reg_w(gspca_dev, 0x003c, 0x0004); | ||
152 | reg_w(gspca_dev, 0x003c, 0x0005); | ||
153 | reg_w(gspca_dev, 0x003c, 0x0006); | ||
154 | reg_w(gspca_dev, 0x003c, 0x0007); | ||
155 | usb_set_interface(gspca_dev->dev, gspca_dev->iface, gspca_dev->nbalt - 1); | ||
156 | } | ||
157 | |||
158 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | ||
159 | u8 *data, /* isoc packet */ | ||
160 | int len) /* iso packet length */ | ||
161 | { | ||
162 | /* unused */ | ||
163 | } | ||
164 | |||
165 | /* reception of an URB */ | ||
166 | static void sd_isoc_irq(struct urb *urb) | ||
167 | { | ||
168 | struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; | ||
169 | struct urb *urb0; | ||
170 | u8 *data; | ||
171 | int i, st; | ||
172 | |||
173 | PDEBUG(D_PACK, "sd isoc irq"); | ||
174 | if (!gspca_dev->streaming) | ||
175 | return; | ||
176 | if (urb->status != 0) { | ||
177 | if (urb->status == -ESHUTDOWN) | ||
178 | return; /* disconnection */ | ||
179 | #ifdef CONFIG_PM | ||
180 | if (gspca_dev->frozen) | ||
181 | return; | ||
182 | #endif | ||
183 | PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status); | ||
184 | return; | ||
185 | } | ||
186 | |||
187 | /* if this is a control URN (ep 0x83), wait */ | ||
188 | if (urb == gspca_dev->urb[0] || urb == gspca_dev->urb[2]) | ||
189 | return; | ||
190 | |||
191 | /* scan both received URBs */ | ||
192 | if (urb == gspca_dev->urb[1]) | ||
193 | urb0 = gspca_dev->urb[0]; | ||
194 | else | ||
195 | urb0 = gspca_dev->urb[2]; | ||
196 | for (i = 0; i < urb->number_of_packets; i++) { | ||
197 | |||
198 | /* check the packet status and length */ | ||
199 | if (urb0->iso_frame_desc[i].actual_length != SD_PKT_SZ | ||
200 | || urb->iso_frame_desc[i].actual_length != SD_PKT_SZ) { | ||
201 | PDEBUG(D_ERR, "ISOC bad lengths %d / %d", | ||
202 | urb0->iso_frame_desc[i].actual_length, | ||
203 | urb->iso_frame_desc[i].actual_length); | ||
204 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
205 | continue; | ||
206 | } | ||
207 | st = urb0->iso_frame_desc[i].status; | ||
208 | if (st == 0) | ||
209 | st = urb->iso_frame_desc[i].status; | ||
210 | if (st) { | ||
211 | PDEBUG(D_ERR, | ||
212 | "ISOC data error: [%d] status=%d", | ||
213 | i, st); | ||
214 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
215 | continue; | ||
216 | } | ||
217 | |||
218 | /* | ||
219 | * The images are received in URBs of different endpoints | ||
220 | * (0x83 and 0x82). | ||
221 | * Image pieces in URBs of ep 0x83 are continuated in URBs of | ||
222 | * ep 0x82 of the same index. | ||
223 | * The packets in the URBs of endpoint 0x83 start with: | ||
224 | * - 80 ba/bb 00 00 = start of image followed by 'ff d8' | ||
225 | * - 04 ba/bb oo oo = image piece | ||
226 | * where 'oo oo' is the image offset | ||
227 | (not cheked) | ||
228 | * - (other -> bad frame) | ||
229 | * The images are JPEG encoded with full header and | ||
230 | * normal ff escape. | ||
231 | * The end of image ('ff d9') may occur in any URB. | ||
232 | * (not cheked) | ||
233 | */ | ||
234 | data = (u8 *) urb0->transfer_buffer | ||
235 | + urb0->iso_frame_desc[i].offset; | ||
236 | if (data[0] == 0x80 && (data[1] & 0xfe) == 0xba) { | ||
237 | |||
238 | /* new image */ | ||
239 | gspca_frame_add(gspca_dev, LAST_PACKET, | ||
240 | NULL, 0); | ||
241 | gspca_frame_add(gspca_dev, FIRST_PACKET, | ||
242 | data + 4, SD_PKT_SZ - 4); | ||
243 | } else if (data[0] == 0x04 && (data[1] & 0xfe) == 0xba) { | ||
244 | gspca_frame_add(gspca_dev, INTER_PACKET, | ||
245 | data + 4, SD_PKT_SZ - 4); | ||
246 | } else { | ||
247 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
248 | continue; | ||
249 | } | ||
250 | data = (u8 *) urb->transfer_buffer | ||
251 | + urb->iso_frame_desc[i].offset; | ||
252 | gspca_frame_add(gspca_dev, INTER_PACKET, | ||
253 | data, SD_PKT_SZ); | ||
254 | } | ||
255 | |||
256 | /* resubmit the URBs */ | ||
257 | st = usb_submit_urb(urb0, GFP_ATOMIC); | ||
258 | if (st < 0) | ||
259 | PDEBUG(D_ERR|D_PACK, "usb_submit_urb(0) ret %d", st); | ||
260 | st = usb_submit_urb(urb, GFP_ATOMIC); | ||
261 | if (st < 0) | ||
262 | PDEBUG(D_ERR|D_PACK, "usb_submit_urb() ret %d", st); | ||
263 | } | ||
264 | |||
265 | /* sub-driver description */ | ||
266 | static const struct sd_desc sd_desc = { | ||
267 | .name = MODULE_NAME, | ||
268 | .ctrls = sd_ctrls, | ||
269 | .nctrls = ARRAY_SIZE(sd_ctrls), | ||
270 | .config = sd_config, | ||
271 | .init = sd_init, | ||
272 | .isoc_init = sd_isoc_init, | ||
273 | .start = sd_start, | ||
274 | .stopN = sd_stopN, | ||
275 | .pkt_scan = sd_pkt_scan, | ||
276 | }; | ||
277 | |||
278 | /* -- module initialisation -- */ | ||
279 | static const __devinitdata struct usb_device_id device_table[] = { | ||
280 | {USB_DEVICE(0x04a5, 0x3035)}, | ||
281 | {} | ||
282 | }; | ||
283 | MODULE_DEVICE_TABLE(usb, device_table); | ||
284 | |||
285 | /* -- device connect -- */ | ||
286 | static int sd_probe(struct usb_interface *intf, | ||
287 | const struct usb_device_id *id) | ||
288 | { | ||
289 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | ||
290 | THIS_MODULE); | ||
291 | } | ||
292 | |||
293 | static struct usb_driver sd_driver = { | ||
294 | .name = MODULE_NAME, | ||
295 | .id_table = device_table, | ||
296 | .probe = sd_probe, | ||
297 | .disconnect = gspca_disconnect, | ||
298 | #ifdef CONFIG_PM | ||
299 | .suspend = gspca_suspend, | ||
300 | .resume = gspca_resume, | ||
301 | #endif | ||
302 | }; | ||
303 | |||
304 | /* -- module insert / remove -- */ | ||
305 | static int __init sd_mod_init(void) | ||
306 | { | ||
307 | int ret; | ||
308 | |||
309 | ret = usb_register(&sd_driver); | ||
310 | if (ret < 0) | ||
311 | return ret; | ||
312 | info("registered"); | ||
313 | return 0; | ||
314 | } | ||
315 | static void __exit sd_mod_exit(void) | ||
316 | { | ||
317 | usb_deregister(&sd_driver); | ||
318 | info("deregistered"); | ||
319 | } | ||
320 | |||
321 | module_init(sd_mod_init); | ||
322 | module_exit(sd_mod_exit); | ||
diff --git a/drivers/media/video/gspca/coarse_expo_autogain.h b/drivers/media/video/gspca/coarse_expo_autogain.h new file mode 100644 index 000000000000..1cb9d941eaf6 --- /dev/null +++ b/drivers/media/video/gspca/coarse_expo_autogain.h | |||
@@ -0,0 +1,116 @@ | |||
1 | /* | ||
2 | * Auto gain algorithm for camera's with a coarse exposure control | ||
3 | * | ||
4 | * Copyright (C) 2010 Hans de Goede <hdegoede@redhat.com> | ||
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 as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | /* Autogain + exposure algorithm for cameras with a coarse exposure control | ||
22 | (usually this means we can only control the clockdiv to change exposure) | ||
23 | As changing the clockdiv so that the fps drops from 30 to 15 fps for | ||
24 | example, will lead to a huge exposure change (it effectively doubles), | ||
25 | this algorithm normally tries to only adjust the gain (between 40 and | ||
26 | 80 %) and if that does not help, only then changes exposure. This leads | ||
27 | to a much more stable image then using the knee algorithm which at | ||
28 | certain points of the knee graph will only try to adjust exposure, | ||
29 | which leads to oscilating as one exposure step is huge. | ||
30 | |||
31 | Note this assumes that the sd struct for the cam in question has | ||
32 | exp_too_high_cnt and exp_too_high_cnt int members for use by this function. | ||
33 | |||
34 | Returns 0 if no changes were made, 1 if the gain and or exposure settings | ||
35 | where changed. */ | ||
36 | static int gspca_coarse_grained_expo_autogain(struct gspca_dev *gspca_dev, | ||
37 | int avg_lum, int desired_avg_lum, int deadzone) | ||
38 | { | ||
39 | int i, steps, gain, orig_gain, exposure, orig_exposure; | ||
40 | int gain_low, gain_high; | ||
41 | const struct ctrl *gain_ctrl = NULL; | ||
42 | const struct ctrl *exposure_ctrl = NULL; | ||
43 | struct sd *sd = (struct sd *) gspca_dev; | ||
44 | int retval = 0; | ||
45 | |||
46 | for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) { | ||
47 | if (gspca_dev->ctrl_dis & (1 << i)) | ||
48 | continue; | ||
49 | if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_GAIN) | ||
50 | gain_ctrl = &gspca_dev->sd_desc->ctrls[i]; | ||
51 | if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_EXPOSURE) | ||
52 | exposure_ctrl = &gspca_dev->sd_desc->ctrls[i]; | ||
53 | } | ||
54 | if (!gain_ctrl || !exposure_ctrl) { | ||
55 | PDEBUG(D_ERR, "Error: gspca_coarse_grained_expo_autogain " | ||
56 | "called on cam without gain or exposure"); | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | if (gain_ctrl->get(gspca_dev, &gain) || | ||
61 | exposure_ctrl->get(gspca_dev, &exposure)) | ||
62 | return 0; | ||
63 | |||
64 | orig_gain = gain; | ||
65 | orig_exposure = exposure; | ||
66 | gain_low = | ||
67 | (gain_ctrl->qctrl.maximum - gain_ctrl->qctrl.minimum) / 5 * 2; | ||
68 | gain_low += gain_ctrl->qctrl.minimum; | ||
69 | gain_high = | ||
70 | (gain_ctrl->qctrl.maximum - gain_ctrl->qctrl.minimum) / 5 * 4; | ||
71 | gain_high += gain_ctrl->qctrl.minimum; | ||
72 | |||
73 | /* If we are of a multiple of deadzone, do multiple steps to reach the | ||
74 | desired lumination fast (with the risc of a slight overshoot) */ | ||
75 | steps = (desired_avg_lum - avg_lum) / deadzone; | ||
76 | |||
77 | PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d", | ||
78 | avg_lum, desired_avg_lum, steps); | ||
79 | |||
80 | if ((gain + steps) > gain_high && | ||
81 | sd->exposure < exposure_ctrl->qctrl.maximum) { | ||
82 | gain = gain_high; | ||
83 | sd->exp_too_low_cnt++; | ||
84 | } else if ((gain + steps) < gain_low && | ||
85 | sd->exposure > exposure_ctrl->qctrl.minimum) { | ||
86 | gain = gain_low; | ||
87 | sd->exp_too_high_cnt++; | ||
88 | } else { | ||
89 | gain += steps; | ||
90 | if (gain > gain_ctrl->qctrl.maximum) | ||
91 | gain = gain_ctrl->qctrl.maximum; | ||
92 | else if (gain < gain_ctrl->qctrl.minimum) | ||
93 | gain = gain_ctrl->qctrl.minimum; | ||
94 | sd->exp_too_high_cnt = 0; | ||
95 | sd->exp_too_low_cnt = 0; | ||
96 | } | ||
97 | |||
98 | if (sd->exp_too_high_cnt > 3) { | ||
99 | exposure--; | ||
100 | sd->exp_too_high_cnt = 0; | ||
101 | } else if (sd->exp_too_low_cnt > 3) { | ||
102 | exposure++; | ||
103 | sd->exp_too_low_cnt = 0; | ||
104 | } | ||
105 | |||
106 | if (gain != orig_gain) { | ||
107 | gain_ctrl->set(gspca_dev, gain); | ||
108 | retval = 1; | ||
109 | } | ||
110 | if (exposure != orig_exposure) { | ||
111 | exposure_ctrl->set(gspca_dev, exposure); | ||
112 | retval = 1; | ||
113 | } | ||
114 | |||
115 | return retval; | ||
116 | } | ||
diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c index c98b5d69c438..19fe6b24c9a3 100644 --- a/drivers/media/video/gspca/conex.c +++ b/drivers/media/video/gspca/conex.c | |||
@@ -52,7 +52,7 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | |||
52 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); | 52 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); |
53 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | 53 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); |
54 | 54 | ||
55 | static struct ctrl sd_ctrls[] = { | 55 | static const struct ctrl sd_ctrls[] = { |
56 | { | 56 | { |
57 | { | 57 | { |
58 | .id = V4L2_CID_BRIGHTNESS, | 58 | .id = V4L2_CID_BRIGHTNESS, |
@@ -1032,7 +1032,7 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev, | |||
1032 | } | 1032 | } |
1033 | 1033 | ||
1034 | /* sub-driver description */ | 1034 | /* sub-driver description */ |
1035 | static struct sd_desc sd_desc = { | 1035 | static const struct sd_desc sd_desc = { |
1036 | .name = MODULE_NAME, | 1036 | .name = MODULE_NAME, |
1037 | .ctrls = sd_ctrls, | 1037 | .ctrls = sd_ctrls, |
1038 | .nctrls = ARRAY_SIZE(sd_ctrls), | 1038 | .nctrls = ARRAY_SIZE(sd_ctrls), |
diff --git a/drivers/media/video/gspca/cpia1.c b/drivers/media/video/gspca/cpia1.c new file mode 100644 index 000000000000..82945ed5cbe5 --- /dev/null +++ b/drivers/media/video/gspca/cpia1.c | |||
@@ -0,0 +1,2022 @@ | |||
1 | /* | ||
2 | * cpia CPiA (1) gspca driver | ||
3 | * | ||
4 | * Copyright (C) 2010 Hans de Goede <hdgoede@redhat.com> | ||
5 | * | ||
6 | * This module is adapted from the in kernel v4l1 cpia driver which is : | ||
7 | * | ||
8 | * (C) Copyright 1999-2000 Peter Pregler | ||
9 | * (C) Copyright 1999-2000 Scott J. Bertin | ||
10 | * (C) Copyright 1999-2000 Johannes Erdfelt <johannes@erdfelt.com> | ||
11 | * (C) Copyright 2000 STMicroelectronics | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | #define MODULE_NAME "cpia1" | ||
30 | |||
31 | #include "gspca.h" | ||
32 | |||
33 | MODULE_AUTHOR("Hans de Goede <hdgoede@redhat.com>"); | ||
34 | MODULE_DESCRIPTION("Vision CPiA"); | ||
35 | MODULE_LICENSE("GPL"); | ||
36 | |||
37 | /* constant value's */ | ||
38 | #define MAGIC_0 0x19 | ||
39 | #define MAGIC_1 0x68 | ||
40 | #define DATA_IN 0xC0 | ||
41 | #define DATA_OUT 0x40 | ||
42 | #define VIDEOSIZE_QCIF 0 /* 176x144 */ | ||
43 | #define VIDEOSIZE_CIF 1 /* 352x288 */ | ||
44 | #define SUBSAMPLE_420 0 | ||
45 | #define SUBSAMPLE_422 1 | ||
46 | #define YUVORDER_YUYV 0 | ||
47 | #define YUVORDER_UYVY 1 | ||
48 | #define NOT_COMPRESSED 0 | ||
49 | #define COMPRESSED 1 | ||
50 | #define NO_DECIMATION 0 | ||
51 | #define DECIMATION_ENAB 1 | ||
52 | #define EOI 0xff /* End Of Image */ | ||
53 | #define EOL 0xfd /* End Of Line */ | ||
54 | #define FRAME_HEADER_SIZE 64 | ||
55 | |||
56 | /* Image grab modes */ | ||
57 | #define CPIA_GRAB_SINGLE 0 | ||
58 | #define CPIA_GRAB_CONTINEOUS 1 | ||
59 | |||
60 | /* Compression parameters */ | ||
61 | #define CPIA_COMPRESSION_NONE 0 | ||
62 | #define CPIA_COMPRESSION_AUTO 1 | ||
63 | #define CPIA_COMPRESSION_MANUAL 2 | ||
64 | #define CPIA_COMPRESSION_TARGET_QUALITY 0 | ||
65 | #define CPIA_COMPRESSION_TARGET_FRAMERATE 1 | ||
66 | |||
67 | /* Return offsets for GetCameraState */ | ||
68 | #define SYSTEMSTATE 0 | ||
69 | #define GRABSTATE 1 | ||
70 | #define STREAMSTATE 2 | ||
71 | #define FATALERROR 3 | ||
72 | #define CMDERROR 4 | ||
73 | #define DEBUGFLAGS 5 | ||
74 | #define VPSTATUS 6 | ||
75 | #define ERRORCODE 7 | ||
76 | |||
77 | /* SystemState */ | ||
78 | #define UNINITIALISED_STATE 0 | ||
79 | #define PASS_THROUGH_STATE 1 | ||
80 | #define LO_POWER_STATE 2 | ||
81 | #define HI_POWER_STATE 3 | ||
82 | #define WARM_BOOT_STATE 4 | ||
83 | |||
84 | /* GrabState */ | ||
85 | #define GRAB_IDLE 0 | ||
86 | #define GRAB_ACTIVE 1 | ||
87 | #define GRAB_DONE 2 | ||
88 | |||
89 | /* StreamState */ | ||
90 | #define STREAM_NOT_READY 0 | ||
91 | #define STREAM_READY 1 | ||
92 | #define STREAM_OPEN 2 | ||
93 | #define STREAM_PAUSED 3 | ||
94 | #define STREAM_FINISHED 4 | ||
95 | |||
96 | /* Fatal Error, CmdError, and DebugFlags */ | ||
97 | #define CPIA_FLAG 1 | ||
98 | #define SYSTEM_FLAG 2 | ||
99 | #define INT_CTRL_FLAG 4 | ||
100 | #define PROCESS_FLAG 8 | ||
101 | #define COM_FLAG 16 | ||
102 | #define VP_CTRL_FLAG 32 | ||
103 | #define CAPTURE_FLAG 64 | ||
104 | #define DEBUG_FLAG 128 | ||
105 | |||
106 | /* VPStatus */ | ||
107 | #define VP_STATE_OK 0x00 | ||
108 | |||
109 | #define VP_STATE_FAILED_VIDEOINIT 0x01 | ||
110 | #define VP_STATE_FAILED_AECACBINIT 0x02 | ||
111 | #define VP_STATE_AEC_MAX 0x04 | ||
112 | #define VP_STATE_ACB_BMAX 0x08 | ||
113 | |||
114 | #define VP_STATE_ACB_RMIN 0x10 | ||
115 | #define VP_STATE_ACB_GMIN 0x20 | ||
116 | #define VP_STATE_ACB_RMAX 0x40 | ||
117 | #define VP_STATE_ACB_GMAX 0x80 | ||
118 | |||
119 | /* default (minimum) compensation values */ | ||
120 | #define COMP_RED 220 | ||
121 | #define COMP_GREEN1 214 | ||
122 | #define COMP_GREEN2 COMP_GREEN1 | ||
123 | #define COMP_BLUE 230 | ||
124 | |||
125 | /* exposure status */ | ||
126 | #define EXPOSURE_VERY_LIGHT 0 | ||
127 | #define EXPOSURE_LIGHT 1 | ||
128 | #define EXPOSURE_NORMAL 2 | ||
129 | #define EXPOSURE_DARK 3 | ||
130 | #define EXPOSURE_VERY_DARK 4 | ||
131 | |||
132 | #define CPIA_MODULE_CPIA (0 << 5) | ||
133 | #define CPIA_MODULE_SYSTEM (1 << 5) | ||
134 | #define CPIA_MODULE_VP_CTRL (5 << 5) | ||
135 | #define CPIA_MODULE_CAPTURE (6 << 5) | ||
136 | #define CPIA_MODULE_DEBUG (7 << 5) | ||
137 | |||
138 | #define INPUT (DATA_IN << 8) | ||
139 | #define OUTPUT (DATA_OUT << 8) | ||
140 | |||
141 | #define CPIA_COMMAND_GetCPIAVersion (INPUT | CPIA_MODULE_CPIA | 1) | ||
142 | #define CPIA_COMMAND_GetPnPID (INPUT | CPIA_MODULE_CPIA | 2) | ||
143 | #define CPIA_COMMAND_GetCameraStatus (INPUT | CPIA_MODULE_CPIA | 3) | ||
144 | #define CPIA_COMMAND_GotoHiPower (OUTPUT | CPIA_MODULE_CPIA | 4) | ||
145 | #define CPIA_COMMAND_GotoLoPower (OUTPUT | CPIA_MODULE_CPIA | 5) | ||
146 | #define CPIA_COMMAND_GotoSuspend (OUTPUT | CPIA_MODULE_CPIA | 7) | ||
147 | #define CPIA_COMMAND_GotoPassThrough (OUTPUT | CPIA_MODULE_CPIA | 8) | ||
148 | #define CPIA_COMMAND_ModifyCameraStatus (OUTPUT | CPIA_MODULE_CPIA | 10) | ||
149 | |||
150 | #define CPIA_COMMAND_ReadVCRegs (INPUT | CPIA_MODULE_SYSTEM | 1) | ||
151 | #define CPIA_COMMAND_WriteVCReg (OUTPUT | CPIA_MODULE_SYSTEM | 2) | ||
152 | #define CPIA_COMMAND_ReadMCPorts (INPUT | CPIA_MODULE_SYSTEM | 3) | ||
153 | #define CPIA_COMMAND_WriteMCPort (OUTPUT | CPIA_MODULE_SYSTEM | 4) | ||
154 | #define CPIA_COMMAND_SetBaudRate (OUTPUT | CPIA_MODULE_SYSTEM | 5) | ||
155 | #define CPIA_COMMAND_SetECPTiming (OUTPUT | CPIA_MODULE_SYSTEM | 6) | ||
156 | #define CPIA_COMMAND_ReadIDATA (INPUT | CPIA_MODULE_SYSTEM | 7) | ||
157 | #define CPIA_COMMAND_WriteIDATA (OUTPUT | CPIA_MODULE_SYSTEM | 8) | ||
158 | #define CPIA_COMMAND_GenericCall (OUTPUT | CPIA_MODULE_SYSTEM | 9) | ||
159 | #define CPIA_COMMAND_I2CStart (OUTPUT | CPIA_MODULE_SYSTEM | 10) | ||
160 | #define CPIA_COMMAND_I2CStop (OUTPUT | CPIA_MODULE_SYSTEM | 11) | ||
161 | #define CPIA_COMMAND_I2CWrite (OUTPUT | CPIA_MODULE_SYSTEM | 12) | ||
162 | #define CPIA_COMMAND_I2CRead (INPUT | CPIA_MODULE_SYSTEM | 13) | ||
163 | |||
164 | #define CPIA_COMMAND_GetVPVersion (INPUT | CPIA_MODULE_VP_CTRL | 1) | ||
165 | #define CPIA_COMMAND_ResetFrameCounter (INPUT | CPIA_MODULE_VP_CTRL | 2) | ||
166 | #define CPIA_COMMAND_SetColourParams (OUTPUT | CPIA_MODULE_VP_CTRL | 3) | ||
167 | #define CPIA_COMMAND_SetExposure (OUTPUT | CPIA_MODULE_VP_CTRL | 4) | ||
168 | #define CPIA_COMMAND_SetColourBalance (OUTPUT | CPIA_MODULE_VP_CTRL | 6) | ||
169 | #define CPIA_COMMAND_SetSensorFPS (OUTPUT | CPIA_MODULE_VP_CTRL | 7) | ||
170 | #define CPIA_COMMAND_SetVPDefaults (OUTPUT | CPIA_MODULE_VP_CTRL | 8) | ||
171 | #define CPIA_COMMAND_SetApcor (OUTPUT | CPIA_MODULE_VP_CTRL | 9) | ||
172 | #define CPIA_COMMAND_SetFlickerCtrl (OUTPUT | CPIA_MODULE_VP_CTRL | 10) | ||
173 | #define CPIA_COMMAND_SetVLOffset (OUTPUT | CPIA_MODULE_VP_CTRL | 11) | ||
174 | #define CPIA_COMMAND_GetColourParams (INPUT | CPIA_MODULE_VP_CTRL | 16) | ||
175 | #define CPIA_COMMAND_GetColourBalance (INPUT | CPIA_MODULE_VP_CTRL | 17) | ||
176 | #define CPIA_COMMAND_GetExposure (INPUT | CPIA_MODULE_VP_CTRL | 18) | ||
177 | #define CPIA_COMMAND_SetSensorMatrix (OUTPUT | CPIA_MODULE_VP_CTRL | 19) | ||
178 | #define CPIA_COMMAND_ColourBars (OUTPUT | CPIA_MODULE_VP_CTRL | 25) | ||
179 | #define CPIA_COMMAND_ReadVPRegs (INPUT | CPIA_MODULE_VP_CTRL | 30) | ||
180 | #define CPIA_COMMAND_WriteVPReg (OUTPUT | CPIA_MODULE_VP_CTRL | 31) | ||
181 | |||
182 | #define CPIA_COMMAND_GrabFrame (OUTPUT | CPIA_MODULE_CAPTURE | 1) | ||
183 | #define CPIA_COMMAND_UploadFrame (OUTPUT | CPIA_MODULE_CAPTURE | 2) | ||
184 | #define CPIA_COMMAND_SetGrabMode (OUTPUT | CPIA_MODULE_CAPTURE | 3) | ||
185 | #define CPIA_COMMAND_InitStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 4) | ||
186 | #define CPIA_COMMAND_FiniStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 5) | ||
187 | #define CPIA_COMMAND_StartStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 6) | ||
188 | #define CPIA_COMMAND_EndStreamCap (OUTPUT | CPIA_MODULE_CAPTURE | 7) | ||
189 | #define CPIA_COMMAND_SetFormat (OUTPUT | CPIA_MODULE_CAPTURE | 8) | ||
190 | #define CPIA_COMMAND_SetROI (OUTPUT | CPIA_MODULE_CAPTURE | 9) | ||
191 | #define CPIA_COMMAND_SetCompression (OUTPUT | CPIA_MODULE_CAPTURE | 10) | ||
192 | #define CPIA_COMMAND_SetCompressionTarget (OUTPUT | CPIA_MODULE_CAPTURE | 11) | ||
193 | #define CPIA_COMMAND_SetYUVThresh (OUTPUT | CPIA_MODULE_CAPTURE | 12) | ||
194 | #define CPIA_COMMAND_SetCompressionParams (OUTPUT | CPIA_MODULE_CAPTURE | 13) | ||
195 | #define CPIA_COMMAND_DiscardFrame (OUTPUT | CPIA_MODULE_CAPTURE | 14) | ||
196 | #define CPIA_COMMAND_GrabReset (OUTPUT | CPIA_MODULE_CAPTURE | 15) | ||
197 | |||
198 | #define CPIA_COMMAND_OutputRS232 (OUTPUT | CPIA_MODULE_DEBUG | 1) | ||
199 | #define CPIA_COMMAND_AbortProcess (OUTPUT | CPIA_MODULE_DEBUG | 4) | ||
200 | #define CPIA_COMMAND_SetDramPage (OUTPUT | CPIA_MODULE_DEBUG | 5) | ||
201 | #define CPIA_COMMAND_StartDramUpload (OUTPUT | CPIA_MODULE_DEBUG | 6) | ||
202 | #define CPIA_COMMAND_StartDummyDtream (OUTPUT | CPIA_MODULE_DEBUG | 8) | ||
203 | #define CPIA_COMMAND_AbortStream (OUTPUT | CPIA_MODULE_DEBUG | 9) | ||
204 | #define CPIA_COMMAND_DownloadDRAM (OUTPUT | CPIA_MODULE_DEBUG | 10) | ||
205 | #define CPIA_COMMAND_Null (OUTPUT | CPIA_MODULE_DEBUG | 11) | ||
206 | |||
207 | #define ROUND_UP_EXP_FOR_FLICKER 15 | ||
208 | |||
209 | /* Constants for automatic frame rate adjustment */ | ||
210 | #define MAX_EXP 302 | ||
211 | #define MAX_EXP_102 255 | ||
212 | #define LOW_EXP 140 | ||
213 | #define VERY_LOW_EXP 70 | ||
214 | #define TC 94 | ||
215 | #define EXP_ACC_DARK 50 | ||
216 | #define EXP_ACC_LIGHT 90 | ||
217 | #define HIGH_COMP_102 160 | ||
218 | #define MAX_COMP 239 | ||
219 | #define DARK_TIME 3 | ||
220 | #define LIGHT_TIME 3 | ||
221 | |||
222 | #define FIRMWARE_VERSION(x, y) (sd->params.version.firmwareVersion == (x) && \ | ||
223 | sd->params.version.firmwareRevision == (y)) | ||
224 | |||
225 | /* Developer's Guide Table 5 p 3-34 | ||
226 | * indexed by [mains][sensorFps.baserate][sensorFps.divisor]*/ | ||
227 | static u8 flicker_jumps[2][2][4] = | ||
228 | { { { 76, 38, 19, 9 }, { 92, 46, 23, 11 } }, | ||
229 | { { 64, 32, 16, 8 }, { 76, 38, 19, 9} } | ||
230 | }; | ||
231 | |||
232 | struct cam_params { | ||
233 | struct { | ||
234 | u8 firmwareVersion; | ||
235 | u8 firmwareRevision; | ||
236 | u8 vcVersion; | ||
237 | u8 vcRevision; | ||
238 | } version; | ||
239 | struct { | ||
240 | u16 vendor; | ||
241 | u16 product; | ||
242 | u16 deviceRevision; | ||
243 | } pnpID; | ||
244 | struct { | ||
245 | u8 vpVersion; | ||
246 | u8 vpRevision; | ||
247 | u16 cameraHeadID; | ||
248 | } vpVersion; | ||
249 | struct { | ||
250 | u8 systemState; | ||
251 | u8 grabState; | ||
252 | u8 streamState; | ||
253 | u8 fatalError; | ||
254 | u8 cmdError; | ||
255 | u8 debugFlags; | ||
256 | u8 vpStatus; | ||
257 | u8 errorCode; | ||
258 | } status; | ||
259 | struct { | ||
260 | u8 brightness; | ||
261 | u8 contrast; | ||
262 | u8 saturation; | ||
263 | } colourParams; | ||
264 | struct { | ||
265 | u8 gainMode; | ||
266 | u8 expMode; | ||
267 | u8 compMode; | ||
268 | u8 centreWeight; | ||
269 | u8 gain; | ||
270 | u8 fineExp; | ||
271 | u8 coarseExpLo; | ||
272 | u8 coarseExpHi; | ||
273 | u8 redComp; | ||
274 | u8 green1Comp; | ||
275 | u8 green2Comp; | ||
276 | u8 blueComp; | ||
277 | } exposure; | ||
278 | struct { | ||
279 | u8 balanceMode; | ||
280 | u8 redGain; | ||
281 | u8 greenGain; | ||
282 | u8 blueGain; | ||
283 | } colourBalance; | ||
284 | struct { | ||
285 | u8 divisor; | ||
286 | u8 baserate; | ||
287 | } sensorFps; | ||
288 | struct { | ||
289 | u8 gain1; | ||
290 | u8 gain2; | ||
291 | u8 gain4; | ||
292 | u8 gain8; | ||
293 | } apcor; | ||
294 | struct { | ||
295 | u8 disabled; | ||
296 | u8 flickerMode; | ||
297 | u8 coarseJump; | ||
298 | u8 allowableOverExposure; | ||
299 | } flickerControl; | ||
300 | struct { | ||
301 | u8 gain1; | ||
302 | u8 gain2; | ||
303 | u8 gain4; | ||
304 | u8 gain8; | ||
305 | } vlOffset; | ||
306 | struct { | ||
307 | u8 mode; | ||
308 | u8 decimation; | ||
309 | } compression; | ||
310 | struct { | ||
311 | u8 frTargeting; | ||
312 | u8 targetFR; | ||
313 | u8 targetQ; | ||
314 | } compressionTarget; | ||
315 | struct { | ||
316 | u8 yThreshold; | ||
317 | u8 uvThreshold; | ||
318 | } yuvThreshold; | ||
319 | struct { | ||
320 | u8 hysteresis; | ||
321 | u8 threshMax; | ||
322 | u8 smallStep; | ||
323 | u8 largeStep; | ||
324 | u8 decimationHysteresis; | ||
325 | u8 frDiffStepThresh; | ||
326 | u8 qDiffStepThresh; | ||
327 | u8 decimationThreshMod; | ||
328 | } compressionParams; | ||
329 | struct { | ||
330 | u8 videoSize; /* CIF/QCIF */ | ||
331 | u8 subSample; | ||
332 | u8 yuvOrder; | ||
333 | } format; | ||
334 | struct { /* Intel QX3 specific data */ | ||
335 | u8 qx3_detected; /* a QX3 is present */ | ||
336 | u8 toplight; /* top light lit , R/W */ | ||
337 | u8 bottomlight; /* bottom light lit, R/W */ | ||
338 | u8 button; /* snapshot button pressed (R/O) */ | ||
339 | u8 cradled; /* microscope is in cradle (R/O) */ | ||
340 | } qx3; | ||
341 | struct { | ||
342 | u8 colStart; /* skip first 8*colStart pixels */ | ||
343 | u8 colEnd; /* finish at 8*colEnd pixels */ | ||
344 | u8 rowStart; /* skip first 4*rowStart lines */ | ||
345 | u8 rowEnd; /* finish at 4*rowEnd lines */ | ||
346 | } roi; | ||
347 | u8 ecpTiming; | ||
348 | u8 streamStartLine; | ||
349 | }; | ||
350 | |||
351 | /* specific webcam descriptor */ | ||
352 | struct sd { | ||
353 | struct gspca_dev gspca_dev; /* !! must be the first item */ | ||
354 | struct cam_params params; /* camera settings */ | ||
355 | |||
356 | atomic_t cam_exposure; | ||
357 | atomic_t fps; | ||
358 | int exposure_count; | ||
359 | u8 exposure_status; | ||
360 | u8 mainsFreq; /* 0 = 50hz, 1 = 60hz */ | ||
361 | u8 first_frame; | ||
362 | u8 freq; | ||
363 | }; | ||
364 | |||
365 | /* V4L2 controls supported by the driver */ | ||
366 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
367 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
368 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
369 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
370 | static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val); | ||
371 | static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val); | ||
372 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | ||
373 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | ||
374 | static int sd_setcomptarget(struct gspca_dev *gspca_dev, __s32 val); | ||
375 | static int sd_getcomptarget(struct gspca_dev *gspca_dev, __s32 *val); | ||
376 | |||
377 | static struct ctrl sd_ctrls[] = { | ||
378 | { | ||
379 | { | ||
380 | .id = V4L2_CID_BRIGHTNESS, | ||
381 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
382 | .name = "Brightness", | ||
383 | .minimum = 0, | ||
384 | .maximum = 100, | ||
385 | .step = 1, | ||
386 | #define BRIGHTNESS_DEF 50 | ||
387 | .default_value = BRIGHTNESS_DEF, | ||
388 | .flags = 0, | ||
389 | }, | ||
390 | .set = sd_setbrightness, | ||
391 | .get = sd_getbrightness, | ||
392 | }, | ||
393 | { | ||
394 | { | ||
395 | .id = V4L2_CID_CONTRAST, | ||
396 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
397 | .name = "Contrast", | ||
398 | .minimum = 0, | ||
399 | .maximum = 96, | ||
400 | .step = 8, | ||
401 | #define CONTRAST_DEF 48 | ||
402 | .default_value = CONTRAST_DEF, | ||
403 | }, | ||
404 | .set = sd_setcontrast, | ||
405 | .get = sd_getcontrast, | ||
406 | }, | ||
407 | { | ||
408 | { | ||
409 | .id = V4L2_CID_SATURATION, | ||
410 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
411 | .name = "Saturation", | ||
412 | .minimum = 0, | ||
413 | .maximum = 100, | ||
414 | .step = 1, | ||
415 | #define SATURATION_DEF 50 | ||
416 | .default_value = SATURATION_DEF, | ||
417 | }, | ||
418 | .set = sd_setsaturation, | ||
419 | .get = sd_getsaturation, | ||
420 | }, | ||
421 | { | ||
422 | { | ||
423 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | ||
424 | .type = V4L2_CTRL_TYPE_MENU, | ||
425 | .name = "Light frequency filter", | ||
426 | .minimum = 0, | ||
427 | .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ | ||
428 | .step = 1, | ||
429 | #define FREQ_DEF 1 | ||
430 | .default_value = FREQ_DEF, | ||
431 | }, | ||
432 | .set = sd_setfreq, | ||
433 | .get = sd_getfreq, | ||
434 | }, | ||
435 | { | ||
436 | { | ||
437 | #define V4L2_CID_COMP_TARGET V4L2_CID_PRIVATE_BASE | ||
438 | .id = V4L2_CID_COMP_TARGET, | ||
439 | .type = V4L2_CTRL_TYPE_MENU, | ||
440 | .name = "Compression Target", | ||
441 | .minimum = 0, | ||
442 | .maximum = 1, | ||
443 | .step = 1, | ||
444 | #define COMP_TARGET_DEF CPIA_COMPRESSION_TARGET_QUALITY | ||
445 | .default_value = COMP_TARGET_DEF, | ||
446 | }, | ||
447 | .set = sd_setcomptarget, | ||
448 | .get = sd_getcomptarget, | ||
449 | }, | ||
450 | }; | ||
451 | |||
452 | static const struct v4l2_pix_format mode[] = { | ||
453 | {160, 120, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE, | ||
454 | /* The sizeimage is trial and error, as with low framerates | ||
455 | the camera will pad out usb frames, making the image | ||
456 | data larger then strictly necessary */ | ||
457 | .bytesperline = 160, | ||
458 | .sizeimage = 65536, | ||
459 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
460 | .priv = 3}, | ||
461 | {176, 144, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE, | ||
462 | .bytesperline = 172, | ||
463 | .sizeimage = 65536, | ||
464 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
465 | .priv = 2}, | ||
466 | {320, 240, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE, | ||
467 | .bytesperline = 320, | ||
468 | .sizeimage = 262144, | ||
469 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
470 | .priv = 1}, | ||
471 | {352, 288, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE, | ||
472 | .bytesperline = 352, | ||
473 | .sizeimage = 262144, | ||
474 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
475 | .priv = 0}, | ||
476 | }; | ||
477 | |||
478 | /********************************************************************** | ||
479 | * | ||
480 | * General functions | ||
481 | * | ||
482 | **********************************************************************/ | ||
483 | |||
484 | static int cpia_usb_transferCmd(struct gspca_dev *gspca_dev, u8 *command) | ||
485 | { | ||
486 | u8 requesttype; | ||
487 | unsigned int pipe; | ||
488 | int ret, databytes = command[6] | (command[7] << 8); | ||
489 | /* Sometimes we see spurious EPIPE errors */ | ||
490 | int retries = 3; | ||
491 | |||
492 | if (command[0] == DATA_IN) { | ||
493 | pipe = usb_rcvctrlpipe(gspca_dev->dev, 0); | ||
494 | requesttype = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE; | ||
495 | } else if (command[0] == DATA_OUT) { | ||
496 | pipe = usb_sndctrlpipe(gspca_dev->dev, 0); | ||
497 | requesttype = USB_TYPE_VENDOR | USB_RECIP_DEVICE; | ||
498 | } else { | ||
499 | PDEBUG(D_ERR, "Unexpected first byte of command: %x", | ||
500 | command[0]); | ||
501 | return -EINVAL; | ||
502 | } | ||
503 | |||
504 | retry: | ||
505 | ret = usb_control_msg(gspca_dev->dev, pipe, | ||
506 | command[1], | ||
507 | requesttype, | ||
508 | command[2] | (command[3] << 8), | ||
509 | command[4] | (command[5] << 8), | ||
510 | gspca_dev->usb_buf, databytes, 1000); | ||
511 | |||
512 | if (ret < 0) | ||
513 | PDEBUG(D_ERR, "usb_control_msg %02x, error %d", command[1], | ||
514 | ret); | ||
515 | |||
516 | if (ret == -EPIPE && retries > 0) { | ||
517 | retries--; | ||
518 | goto retry; | ||
519 | } | ||
520 | |||
521 | return (ret < 0) ? ret : 0; | ||
522 | } | ||
523 | |||
524 | /* send an arbitrary command to the camera */ | ||
525 | static int do_command(struct gspca_dev *gspca_dev, u16 command, | ||
526 | u8 a, u8 b, u8 c, u8 d) | ||
527 | { | ||
528 | struct sd *sd = (struct sd *) gspca_dev; | ||
529 | int ret, datasize; | ||
530 | u8 cmd[8]; | ||
531 | |||
532 | switch (command) { | ||
533 | case CPIA_COMMAND_GetCPIAVersion: | ||
534 | case CPIA_COMMAND_GetPnPID: | ||
535 | case CPIA_COMMAND_GetCameraStatus: | ||
536 | case CPIA_COMMAND_GetVPVersion: | ||
537 | case CPIA_COMMAND_GetColourParams: | ||
538 | case CPIA_COMMAND_GetColourBalance: | ||
539 | case CPIA_COMMAND_GetExposure: | ||
540 | datasize = 8; | ||
541 | break; | ||
542 | case CPIA_COMMAND_ReadMCPorts: | ||
543 | case CPIA_COMMAND_ReadVCRegs: | ||
544 | datasize = 4; | ||
545 | break; | ||
546 | default: | ||
547 | datasize = 0; | ||
548 | break; | ||
549 | } | ||
550 | |||
551 | cmd[0] = command >> 8; | ||
552 | cmd[1] = command & 0xff; | ||
553 | cmd[2] = a; | ||
554 | cmd[3] = b; | ||
555 | cmd[4] = c; | ||
556 | cmd[5] = d; | ||
557 | cmd[6] = datasize; | ||
558 | cmd[7] = 0; | ||
559 | |||
560 | ret = cpia_usb_transferCmd(gspca_dev, cmd); | ||
561 | if (ret) | ||
562 | return ret; | ||
563 | |||
564 | switch (command) { | ||
565 | case CPIA_COMMAND_GetCPIAVersion: | ||
566 | sd->params.version.firmwareVersion = gspca_dev->usb_buf[0]; | ||
567 | sd->params.version.firmwareRevision = gspca_dev->usb_buf[1]; | ||
568 | sd->params.version.vcVersion = gspca_dev->usb_buf[2]; | ||
569 | sd->params.version.vcRevision = gspca_dev->usb_buf[3]; | ||
570 | break; | ||
571 | case CPIA_COMMAND_GetPnPID: | ||
572 | sd->params.pnpID.vendor = | ||
573 | gspca_dev->usb_buf[0] | (gspca_dev->usb_buf[1] << 8); | ||
574 | sd->params.pnpID.product = | ||
575 | gspca_dev->usb_buf[2] | (gspca_dev->usb_buf[3] << 8); | ||
576 | sd->params.pnpID.deviceRevision = | ||
577 | gspca_dev->usb_buf[4] | (gspca_dev->usb_buf[5] << 8); | ||
578 | break; | ||
579 | case CPIA_COMMAND_GetCameraStatus: | ||
580 | sd->params.status.systemState = gspca_dev->usb_buf[0]; | ||
581 | sd->params.status.grabState = gspca_dev->usb_buf[1]; | ||
582 | sd->params.status.streamState = gspca_dev->usb_buf[2]; | ||
583 | sd->params.status.fatalError = gspca_dev->usb_buf[3]; | ||
584 | sd->params.status.cmdError = gspca_dev->usb_buf[4]; | ||
585 | sd->params.status.debugFlags = gspca_dev->usb_buf[5]; | ||
586 | sd->params.status.vpStatus = gspca_dev->usb_buf[6]; | ||
587 | sd->params.status.errorCode = gspca_dev->usb_buf[7]; | ||
588 | break; | ||
589 | case CPIA_COMMAND_GetVPVersion: | ||
590 | sd->params.vpVersion.vpVersion = gspca_dev->usb_buf[0]; | ||
591 | sd->params.vpVersion.vpRevision = gspca_dev->usb_buf[1]; | ||
592 | sd->params.vpVersion.cameraHeadID = | ||
593 | gspca_dev->usb_buf[2] | (gspca_dev->usb_buf[3] << 8); | ||
594 | break; | ||
595 | case CPIA_COMMAND_GetColourParams: | ||
596 | sd->params.colourParams.brightness = gspca_dev->usb_buf[0]; | ||
597 | sd->params.colourParams.contrast = gspca_dev->usb_buf[1]; | ||
598 | sd->params.colourParams.saturation = gspca_dev->usb_buf[2]; | ||
599 | break; | ||
600 | case CPIA_COMMAND_GetColourBalance: | ||
601 | sd->params.colourBalance.redGain = gspca_dev->usb_buf[0]; | ||
602 | sd->params.colourBalance.greenGain = gspca_dev->usb_buf[1]; | ||
603 | sd->params.colourBalance.blueGain = gspca_dev->usb_buf[2]; | ||
604 | break; | ||
605 | case CPIA_COMMAND_GetExposure: | ||
606 | sd->params.exposure.gain = gspca_dev->usb_buf[0]; | ||
607 | sd->params.exposure.fineExp = gspca_dev->usb_buf[1]; | ||
608 | sd->params.exposure.coarseExpLo = gspca_dev->usb_buf[2]; | ||
609 | sd->params.exposure.coarseExpHi = gspca_dev->usb_buf[3]; | ||
610 | sd->params.exposure.redComp = gspca_dev->usb_buf[4]; | ||
611 | sd->params.exposure.green1Comp = gspca_dev->usb_buf[5]; | ||
612 | sd->params.exposure.green2Comp = gspca_dev->usb_buf[6]; | ||
613 | sd->params.exposure.blueComp = gspca_dev->usb_buf[7]; | ||
614 | break; | ||
615 | |||
616 | case CPIA_COMMAND_ReadMCPorts: | ||
617 | if (!sd->params.qx3.qx3_detected) | ||
618 | break; | ||
619 | /* test button press */ | ||
620 | sd->params.qx3.button = ((gspca_dev->usb_buf[1] & 0x02) == 0); | ||
621 | if (sd->params.qx3.button) { | ||
622 | /* button pressed - unlock the latch */ | ||
623 | do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, | ||
624 | 3, 0xDF, 0xDF, 0); | ||
625 | do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, | ||
626 | 3, 0xFF, 0xFF, 0); | ||
627 | } | ||
628 | |||
629 | /* test whether microscope is cradled */ | ||
630 | sd->params.qx3.cradled = ((gspca_dev->usb_buf[2] & 0x40) == 0); | ||
631 | break; | ||
632 | } | ||
633 | |||
634 | return 0; | ||
635 | } | ||
636 | |||
637 | /* send a command to the camera with an additional data transaction */ | ||
638 | static int do_command_extended(struct gspca_dev *gspca_dev, u16 command, | ||
639 | u8 a, u8 b, u8 c, u8 d, | ||
640 | u8 e, u8 f, u8 g, u8 h, | ||
641 | u8 i, u8 j, u8 k, u8 l) | ||
642 | { | ||
643 | u8 cmd[8]; | ||
644 | |||
645 | cmd[0] = command >> 8; | ||
646 | cmd[1] = command & 0xff; | ||
647 | cmd[2] = a; | ||
648 | cmd[3] = b; | ||
649 | cmd[4] = c; | ||
650 | cmd[5] = d; | ||
651 | cmd[6] = 8; | ||
652 | cmd[7] = 0; | ||
653 | gspca_dev->usb_buf[0] = e; | ||
654 | gspca_dev->usb_buf[1] = f; | ||
655 | gspca_dev->usb_buf[2] = g; | ||
656 | gspca_dev->usb_buf[3] = h; | ||
657 | gspca_dev->usb_buf[4] = i; | ||
658 | gspca_dev->usb_buf[5] = j; | ||
659 | gspca_dev->usb_buf[6] = k; | ||
660 | gspca_dev->usb_buf[7] = l; | ||
661 | |||
662 | return cpia_usb_transferCmd(gspca_dev, cmd); | ||
663 | } | ||
664 | |||
665 | /* find_over_exposure | ||
666 | * Finds a suitable value of OverExposure for use with SetFlickerCtrl | ||
667 | * Some calculation is required because this value changes with the brightness | ||
668 | * set with SetColourParameters | ||
669 | * | ||
670 | * Parameters: Brightness - last brightness value set with SetColourParameters | ||
671 | * | ||
672 | * Returns: OverExposure value to use with SetFlickerCtrl | ||
673 | */ | ||
674 | #define FLICKER_MAX_EXPOSURE 250 | ||
675 | #define FLICKER_ALLOWABLE_OVER_EXPOSURE 146 | ||
676 | #define FLICKER_BRIGHTNESS_CONSTANT 59 | ||
677 | static int find_over_exposure(int brightness) | ||
678 | { | ||
679 | int MaxAllowableOverExposure, OverExposure; | ||
680 | |||
681 | MaxAllowableOverExposure = FLICKER_MAX_EXPOSURE - brightness - | ||
682 | FLICKER_BRIGHTNESS_CONSTANT; | ||
683 | |||
684 | if (MaxAllowableOverExposure < FLICKER_ALLOWABLE_OVER_EXPOSURE) | ||
685 | OverExposure = MaxAllowableOverExposure; | ||
686 | else | ||
687 | OverExposure = FLICKER_ALLOWABLE_OVER_EXPOSURE; | ||
688 | |||
689 | return OverExposure; | ||
690 | } | ||
691 | #undef FLICKER_MAX_EXPOSURE | ||
692 | #undef FLICKER_ALLOWABLE_OVER_EXPOSURE | ||
693 | #undef FLICKER_BRIGHTNESS_CONSTANT | ||
694 | |||
695 | /* initialise cam_data structure */ | ||
696 | static void reset_camera_params(struct gspca_dev *gspca_dev) | ||
697 | { | ||
698 | struct sd *sd = (struct sd *) gspca_dev; | ||
699 | struct cam_params *params = &sd->params; | ||
700 | |||
701 | /* The following parameter values are the defaults from | ||
702 | * "Software Developer's Guide for CPiA Cameras". Any changes | ||
703 | * to the defaults are noted in comments. */ | ||
704 | params->colourParams.brightness = BRIGHTNESS_DEF; | ||
705 | params->colourParams.contrast = CONTRAST_DEF; | ||
706 | params->colourParams.saturation = SATURATION_DEF; | ||
707 | params->exposure.gainMode = 4; | ||
708 | params->exposure.expMode = 2; /* AEC */ | ||
709 | params->exposure.compMode = 1; | ||
710 | params->exposure.centreWeight = 1; | ||
711 | params->exposure.gain = 0; | ||
712 | params->exposure.fineExp = 0; | ||
713 | params->exposure.coarseExpLo = 185; | ||
714 | params->exposure.coarseExpHi = 0; | ||
715 | params->exposure.redComp = COMP_RED; | ||
716 | params->exposure.green1Comp = COMP_GREEN1; | ||
717 | params->exposure.green2Comp = COMP_GREEN2; | ||
718 | params->exposure.blueComp = COMP_BLUE; | ||
719 | params->colourBalance.balanceMode = 2; /* ACB */ | ||
720 | params->colourBalance.redGain = 32; | ||
721 | params->colourBalance.greenGain = 6; | ||
722 | params->colourBalance.blueGain = 92; | ||
723 | params->apcor.gain1 = 0x18; | ||
724 | params->apcor.gain2 = 0x16; | ||
725 | params->apcor.gain4 = 0x24; | ||
726 | params->apcor.gain8 = 0x34; | ||
727 | params->flickerControl.flickerMode = 0; | ||
728 | params->flickerControl.disabled = 1; | ||
729 | |||
730 | params->flickerControl.coarseJump = | ||
731 | flicker_jumps[sd->mainsFreq] | ||
732 | [params->sensorFps.baserate] | ||
733 | [params->sensorFps.divisor]; | ||
734 | params->flickerControl.allowableOverExposure = | ||
735 | find_over_exposure(params->colourParams.brightness); | ||
736 | params->vlOffset.gain1 = 20; | ||
737 | params->vlOffset.gain2 = 24; | ||
738 | params->vlOffset.gain4 = 26; | ||
739 | params->vlOffset.gain8 = 26; | ||
740 | params->compressionParams.hysteresis = 3; | ||
741 | params->compressionParams.threshMax = 11; | ||
742 | params->compressionParams.smallStep = 1; | ||
743 | params->compressionParams.largeStep = 3; | ||
744 | params->compressionParams.decimationHysteresis = 2; | ||
745 | params->compressionParams.frDiffStepThresh = 5; | ||
746 | params->compressionParams.qDiffStepThresh = 3; | ||
747 | params->compressionParams.decimationThreshMod = 2; | ||
748 | /* End of default values from Software Developer's Guide */ | ||
749 | |||
750 | /* Set Sensor FPS to 15fps. This seems better than 30fps | ||
751 | * for indoor lighting. */ | ||
752 | params->sensorFps.divisor = 1; | ||
753 | params->sensorFps.baserate = 1; | ||
754 | |||
755 | params->yuvThreshold.yThreshold = 6; /* From windows driver */ | ||
756 | params->yuvThreshold.uvThreshold = 6; /* From windows driver */ | ||
757 | |||
758 | params->format.subSample = SUBSAMPLE_420; | ||
759 | params->format.yuvOrder = YUVORDER_YUYV; | ||
760 | |||
761 | params->compression.mode = CPIA_COMPRESSION_AUTO; | ||
762 | params->compression.decimation = NO_DECIMATION; | ||
763 | |||
764 | params->compressionTarget.frTargeting = COMP_TARGET_DEF; | ||
765 | params->compressionTarget.targetFR = 15; /* From windows driver */ | ||
766 | params->compressionTarget.targetQ = 5; /* From windows driver */ | ||
767 | |||
768 | params->qx3.qx3_detected = 0; | ||
769 | params->qx3.toplight = 0; | ||
770 | params->qx3.bottomlight = 0; | ||
771 | params->qx3.button = 0; | ||
772 | params->qx3.cradled = 0; | ||
773 | } | ||
774 | |||
775 | static void printstatus(struct cam_params *params) | ||
776 | { | ||
777 | PDEBUG(D_PROBE, "status: %02x %02x %02x %02x %02x %02x %02x %02x", | ||
778 | params->status.systemState, params->status.grabState, | ||
779 | params->status.streamState, params->status.fatalError, | ||
780 | params->status.cmdError, params->status.debugFlags, | ||
781 | params->status.vpStatus, params->status.errorCode); | ||
782 | } | ||
783 | |||
784 | static int goto_low_power(struct gspca_dev *gspca_dev) | ||
785 | { | ||
786 | struct sd *sd = (struct sd *) gspca_dev; | ||
787 | int ret; | ||
788 | |||
789 | ret = do_command(gspca_dev, CPIA_COMMAND_GotoLoPower, 0, 0, 0, 0); | ||
790 | if (ret) | ||
791 | return ret; | ||
792 | |||
793 | do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); | ||
794 | if (ret) | ||
795 | return ret; | ||
796 | |||
797 | if (sd->params.status.systemState != LO_POWER_STATE) { | ||
798 | if (sd->params.status.systemState != WARM_BOOT_STATE) { | ||
799 | PDEBUG(D_ERR, | ||
800 | "unexpected state after lo power cmd: %02x", | ||
801 | sd->params.status.systemState); | ||
802 | printstatus(&sd->params); | ||
803 | } | ||
804 | return -EIO; | ||
805 | } | ||
806 | |||
807 | PDEBUG(D_CONF, "camera now in LOW power state"); | ||
808 | return 0; | ||
809 | } | ||
810 | |||
811 | static int goto_high_power(struct gspca_dev *gspca_dev) | ||
812 | { | ||
813 | struct sd *sd = (struct sd *) gspca_dev; | ||
814 | int ret; | ||
815 | |||
816 | ret = do_command(gspca_dev, CPIA_COMMAND_GotoHiPower, 0, 0, 0, 0); | ||
817 | if (ret) | ||
818 | return ret; | ||
819 | |||
820 | msleep_interruptible(40); /* windows driver does it too */ | ||
821 | |||
822 | if (signal_pending(current)) | ||
823 | return -EINTR; | ||
824 | |||
825 | do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); | ||
826 | if (ret) | ||
827 | return ret; | ||
828 | |||
829 | if (sd->params.status.systemState != HI_POWER_STATE) { | ||
830 | PDEBUG(D_ERR, "unexpected state after hi power cmd: %02x", | ||
831 | sd->params.status.systemState); | ||
832 | printstatus(&sd->params); | ||
833 | return -EIO; | ||
834 | } | ||
835 | |||
836 | PDEBUG(D_CONF, "camera now in HIGH power state"); | ||
837 | return 0; | ||
838 | } | ||
839 | |||
840 | static int get_version_information(struct gspca_dev *gspca_dev) | ||
841 | { | ||
842 | int ret; | ||
843 | |||
844 | /* GetCPIAVersion */ | ||
845 | ret = do_command(gspca_dev, CPIA_COMMAND_GetCPIAVersion, 0, 0, 0, 0); | ||
846 | if (ret) | ||
847 | return ret; | ||
848 | |||
849 | /* GetPnPID */ | ||
850 | return do_command(gspca_dev, CPIA_COMMAND_GetPnPID, 0, 0, 0, 0); | ||
851 | } | ||
852 | |||
853 | static int save_camera_state(struct gspca_dev *gspca_dev) | ||
854 | { | ||
855 | int ret; | ||
856 | |||
857 | ret = do_command(gspca_dev, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0); | ||
858 | if (ret) | ||
859 | return ret; | ||
860 | |||
861 | return do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0); | ||
862 | } | ||
863 | |||
864 | int command_setformat(struct gspca_dev *gspca_dev) | ||
865 | { | ||
866 | struct sd *sd = (struct sd *) gspca_dev; | ||
867 | int ret; | ||
868 | |||
869 | ret = do_command(gspca_dev, CPIA_COMMAND_SetFormat, | ||
870 | sd->params.format.videoSize, | ||
871 | sd->params.format.subSample, | ||
872 | sd->params.format.yuvOrder, 0); | ||
873 | if (ret) | ||
874 | return ret; | ||
875 | |||
876 | return do_command(gspca_dev, CPIA_COMMAND_SetROI, | ||
877 | sd->params.roi.colStart, sd->params.roi.colEnd, | ||
878 | sd->params.roi.rowStart, sd->params.roi.rowEnd); | ||
879 | } | ||
880 | |||
881 | int command_setcolourparams(struct gspca_dev *gspca_dev) | ||
882 | { | ||
883 | struct sd *sd = (struct sd *) gspca_dev; | ||
884 | return do_command(gspca_dev, CPIA_COMMAND_SetColourParams, | ||
885 | sd->params.colourParams.brightness, | ||
886 | sd->params.colourParams.contrast, | ||
887 | sd->params.colourParams.saturation, 0); | ||
888 | } | ||
889 | |||
890 | int command_setapcor(struct gspca_dev *gspca_dev) | ||
891 | { | ||
892 | struct sd *sd = (struct sd *) gspca_dev; | ||
893 | return do_command(gspca_dev, CPIA_COMMAND_SetApcor, | ||
894 | sd->params.apcor.gain1, | ||
895 | sd->params.apcor.gain2, | ||
896 | sd->params.apcor.gain4, | ||
897 | sd->params.apcor.gain8); | ||
898 | } | ||
899 | |||
900 | int command_setvloffset(struct gspca_dev *gspca_dev) | ||
901 | { | ||
902 | struct sd *sd = (struct sd *) gspca_dev; | ||
903 | return do_command(gspca_dev, CPIA_COMMAND_SetVLOffset, | ||
904 | sd->params.vlOffset.gain1, | ||
905 | sd->params.vlOffset.gain2, | ||
906 | sd->params.vlOffset.gain4, | ||
907 | sd->params.vlOffset.gain8); | ||
908 | } | ||
909 | |||
910 | int command_setexposure(struct gspca_dev *gspca_dev) | ||
911 | { | ||
912 | struct sd *sd = (struct sd *) gspca_dev; | ||
913 | int ret; | ||
914 | |||
915 | ret = do_command_extended(gspca_dev, CPIA_COMMAND_SetExposure, | ||
916 | sd->params.exposure.gainMode, | ||
917 | 1, | ||
918 | sd->params.exposure.compMode, | ||
919 | sd->params.exposure.centreWeight, | ||
920 | sd->params.exposure.gain, | ||
921 | sd->params.exposure.fineExp, | ||
922 | sd->params.exposure.coarseExpLo, | ||
923 | sd->params.exposure.coarseExpHi, | ||
924 | sd->params.exposure.redComp, | ||
925 | sd->params.exposure.green1Comp, | ||
926 | sd->params.exposure.green2Comp, | ||
927 | sd->params.exposure.blueComp); | ||
928 | if (ret) | ||
929 | return ret; | ||
930 | |||
931 | if (sd->params.exposure.expMode != 1) { | ||
932 | ret = do_command_extended(gspca_dev, CPIA_COMMAND_SetExposure, | ||
933 | 0, | ||
934 | sd->params.exposure.expMode, | ||
935 | 0, 0, | ||
936 | sd->params.exposure.gain, | ||
937 | sd->params.exposure.fineExp, | ||
938 | sd->params.exposure.coarseExpLo, | ||
939 | sd->params.exposure.coarseExpHi, | ||
940 | 0, 0, 0, 0); | ||
941 | } | ||
942 | |||
943 | return ret; | ||
944 | } | ||
945 | |||
946 | int command_setcolourbalance(struct gspca_dev *gspca_dev) | ||
947 | { | ||
948 | struct sd *sd = (struct sd *) gspca_dev; | ||
949 | |||
950 | if (sd->params.colourBalance.balanceMode == 1) { | ||
951 | int ret; | ||
952 | |||
953 | ret = do_command(gspca_dev, CPIA_COMMAND_SetColourBalance, | ||
954 | 1, | ||
955 | sd->params.colourBalance.redGain, | ||
956 | sd->params.colourBalance.greenGain, | ||
957 | sd->params.colourBalance.blueGain); | ||
958 | if (ret) | ||
959 | return ret; | ||
960 | |||
961 | return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance, | ||
962 | 3, 0, 0, 0); | ||
963 | } | ||
964 | if (sd->params.colourBalance.balanceMode == 2) { | ||
965 | return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance, | ||
966 | 2, 0, 0, 0); | ||
967 | } | ||
968 | if (sd->params.colourBalance.balanceMode == 3) { | ||
969 | return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance, | ||
970 | 3, 0, 0, 0); | ||
971 | } | ||
972 | |||
973 | return -EINVAL; | ||
974 | } | ||
975 | |||
976 | int command_setcompressiontarget(struct gspca_dev *gspca_dev) | ||
977 | { | ||
978 | struct sd *sd = (struct sd *) gspca_dev; | ||
979 | |||
980 | return do_command(gspca_dev, CPIA_COMMAND_SetCompressionTarget, | ||
981 | sd->params.compressionTarget.frTargeting, | ||
982 | sd->params.compressionTarget.targetFR, | ||
983 | sd->params.compressionTarget.targetQ, 0); | ||
984 | } | ||
985 | |||
986 | int command_setyuvtresh(struct gspca_dev *gspca_dev) | ||
987 | { | ||
988 | struct sd *sd = (struct sd *) gspca_dev; | ||
989 | |||
990 | return do_command(gspca_dev, CPIA_COMMAND_SetYUVThresh, | ||
991 | sd->params.yuvThreshold.yThreshold, | ||
992 | sd->params.yuvThreshold.uvThreshold, 0, 0); | ||
993 | } | ||
994 | |||
995 | int command_setcompressionparams(struct gspca_dev *gspca_dev) | ||
996 | { | ||
997 | struct sd *sd = (struct sd *) gspca_dev; | ||
998 | |||
999 | return do_command_extended(gspca_dev, | ||
1000 | CPIA_COMMAND_SetCompressionParams, | ||
1001 | 0, 0, 0, 0, | ||
1002 | sd->params.compressionParams.hysteresis, | ||
1003 | sd->params.compressionParams.threshMax, | ||
1004 | sd->params.compressionParams.smallStep, | ||
1005 | sd->params.compressionParams.largeStep, | ||
1006 | sd->params.compressionParams.decimationHysteresis, | ||
1007 | sd->params.compressionParams.frDiffStepThresh, | ||
1008 | sd->params.compressionParams.qDiffStepThresh, | ||
1009 | sd->params.compressionParams.decimationThreshMod); | ||
1010 | } | ||
1011 | |||
1012 | int command_setcompression(struct gspca_dev *gspca_dev) | ||
1013 | { | ||
1014 | struct sd *sd = (struct sd *) gspca_dev; | ||
1015 | |||
1016 | return do_command(gspca_dev, CPIA_COMMAND_SetCompression, | ||
1017 | sd->params.compression.mode, | ||
1018 | sd->params.compression.decimation, 0, 0); | ||
1019 | } | ||
1020 | |||
1021 | int command_setsensorfps(struct gspca_dev *gspca_dev) | ||
1022 | { | ||
1023 | struct sd *sd = (struct sd *) gspca_dev; | ||
1024 | |||
1025 | return do_command(gspca_dev, CPIA_COMMAND_SetSensorFPS, | ||
1026 | sd->params.sensorFps.divisor, | ||
1027 | sd->params.sensorFps.baserate, 0, 0); | ||
1028 | } | ||
1029 | |||
1030 | int command_setflickerctrl(struct gspca_dev *gspca_dev) | ||
1031 | { | ||
1032 | struct sd *sd = (struct sd *) gspca_dev; | ||
1033 | |||
1034 | return do_command(gspca_dev, CPIA_COMMAND_SetFlickerCtrl, | ||
1035 | sd->params.flickerControl.flickerMode, | ||
1036 | sd->params.flickerControl.coarseJump, | ||
1037 | sd->params.flickerControl.allowableOverExposure, | ||
1038 | 0); | ||
1039 | } | ||
1040 | |||
1041 | int command_setecptiming(struct gspca_dev *gspca_dev) | ||
1042 | { | ||
1043 | struct sd *sd = (struct sd *) gspca_dev; | ||
1044 | |||
1045 | return do_command(gspca_dev, CPIA_COMMAND_SetECPTiming, | ||
1046 | sd->params.ecpTiming, 0, 0, 0); | ||
1047 | } | ||
1048 | |||
1049 | int command_pause(struct gspca_dev *gspca_dev) | ||
1050 | { | ||
1051 | return do_command(gspca_dev, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0); | ||
1052 | } | ||
1053 | |||
1054 | int command_resume(struct gspca_dev *gspca_dev) | ||
1055 | { | ||
1056 | struct sd *sd = (struct sd *) gspca_dev; | ||
1057 | |||
1058 | return do_command(gspca_dev, CPIA_COMMAND_InitStreamCap, | ||
1059 | 0, sd->params.streamStartLine, 0, 0); | ||
1060 | } | ||
1061 | |||
1062 | int command_setlights(struct gspca_dev *gspca_dev) | ||
1063 | { | ||
1064 | struct sd *sd = (struct sd *) gspca_dev; | ||
1065 | int ret, p1, p2; | ||
1066 | |||
1067 | if (!sd->params.qx3.qx3_detected) | ||
1068 | return 0; | ||
1069 | |||
1070 | p1 = (sd->params.qx3.bottomlight == 0) << 1; | ||
1071 | p2 = (sd->params.qx3.toplight == 0) << 3; | ||
1072 | |||
1073 | ret = do_command(gspca_dev, CPIA_COMMAND_WriteVCReg, | ||
1074 | 0x90, 0x8F, 0x50, 0); | ||
1075 | if (ret) | ||
1076 | return ret; | ||
1077 | |||
1078 | return do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, 2, 0, | ||
1079 | p1 | p2 | 0xE0, 0); | ||
1080 | } | ||
1081 | |||
1082 | static int set_flicker(struct gspca_dev *gspca_dev, int on, int apply) | ||
1083 | { | ||
1084 | /* Everything in here is from the Windows driver */ | ||
1085 | /* define for compgain calculation */ | ||
1086 | #if 0 | ||
1087 | #define COMPGAIN(base, curexp, newexp) \ | ||
1088 | (u8) ((((float) base - 128.0) * ((float) curexp / (float) newexp)) + 128.5) | ||
1089 | #define EXP_FROM_COMP(basecomp, curcomp, curexp) \ | ||
1090 | (u16)((float)curexp * (float)(u8)(curcomp + 128) / \ | ||
1091 | (float)(u8)(basecomp - 128)) | ||
1092 | #else | ||
1093 | /* equivalent functions without floating point math */ | ||
1094 | #define COMPGAIN(base, curexp, newexp) \ | ||
1095 | (u8)(128 + (((u32)(2*(base-128)*curexp + newexp)) / (2 * newexp))) | ||
1096 | #define EXP_FROM_COMP(basecomp, curcomp, curexp) \ | ||
1097 | (u16)(((u32)(curexp * (u8)(curcomp + 128)) / (u8)(basecomp - 128))) | ||
1098 | #endif | ||
1099 | |||
1100 | struct sd *sd = (struct sd *) gspca_dev; | ||
1101 | int currentexp = sd->params.exposure.coarseExpLo + | ||
1102 | sd->params.exposure.coarseExpHi * 256; | ||
1103 | int ret, startexp; | ||
1104 | |||
1105 | if (on) { | ||
1106 | int cj = sd->params.flickerControl.coarseJump; | ||
1107 | sd->params.flickerControl.flickerMode = 1; | ||
1108 | sd->params.flickerControl.disabled = 0; | ||
1109 | if (sd->params.exposure.expMode != 2) { | ||
1110 | sd->params.exposure.expMode = 2; | ||
1111 | sd->exposure_status = EXPOSURE_NORMAL; | ||
1112 | } | ||
1113 | currentexp = currentexp << sd->params.exposure.gain; | ||
1114 | sd->params.exposure.gain = 0; | ||
1115 | /* round down current exposure to nearest value */ | ||
1116 | startexp = (currentexp + ROUND_UP_EXP_FOR_FLICKER) / cj; | ||
1117 | if (startexp < 1) | ||
1118 | startexp = 1; | ||
1119 | startexp = (startexp * cj) - 1; | ||
1120 | if (FIRMWARE_VERSION(1, 2)) | ||
1121 | while (startexp > MAX_EXP_102) | ||
1122 | startexp -= cj; | ||
1123 | else | ||
1124 | while (startexp > MAX_EXP) | ||
1125 | startexp -= cj; | ||
1126 | sd->params.exposure.coarseExpLo = startexp & 0xff; | ||
1127 | sd->params.exposure.coarseExpHi = startexp >> 8; | ||
1128 | if (currentexp > startexp) { | ||
1129 | if (currentexp > (2 * startexp)) | ||
1130 | currentexp = 2 * startexp; | ||
1131 | sd->params.exposure.redComp = | ||
1132 | COMPGAIN(COMP_RED, currentexp, startexp); | ||
1133 | sd->params.exposure.green1Comp = | ||
1134 | COMPGAIN(COMP_GREEN1, currentexp, startexp); | ||
1135 | sd->params.exposure.green2Comp = | ||
1136 | COMPGAIN(COMP_GREEN2, currentexp, startexp); | ||
1137 | sd->params.exposure.blueComp = | ||
1138 | COMPGAIN(COMP_BLUE, currentexp, startexp); | ||
1139 | } else { | ||
1140 | sd->params.exposure.redComp = COMP_RED; | ||
1141 | sd->params.exposure.green1Comp = COMP_GREEN1; | ||
1142 | sd->params.exposure.green2Comp = COMP_GREEN2; | ||
1143 | sd->params.exposure.blueComp = COMP_BLUE; | ||
1144 | } | ||
1145 | if (FIRMWARE_VERSION(1, 2)) | ||
1146 | sd->params.exposure.compMode = 0; | ||
1147 | else | ||
1148 | sd->params.exposure.compMode = 1; | ||
1149 | |||
1150 | sd->params.apcor.gain1 = 0x18; | ||
1151 | sd->params.apcor.gain2 = 0x18; | ||
1152 | sd->params.apcor.gain4 = 0x16; | ||
1153 | sd->params.apcor.gain8 = 0x14; | ||
1154 | } else { | ||
1155 | sd->params.flickerControl.flickerMode = 0; | ||
1156 | sd->params.flickerControl.disabled = 1; | ||
1157 | /* Average equivalent coarse for each comp channel */ | ||
1158 | startexp = EXP_FROM_COMP(COMP_RED, | ||
1159 | sd->params.exposure.redComp, currentexp); | ||
1160 | startexp += EXP_FROM_COMP(COMP_GREEN1, | ||
1161 | sd->params.exposure.green1Comp, currentexp); | ||
1162 | startexp += EXP_FROM_COMP(COMP_GREEN2, | ||
1163 | sd->params.exposure.green2Comp, currentexp); | ||
1164 | startexp += EXP_FROM_COMP(COMP_BLUE, | ||
1165 | sd->params.exposure.blueComp, currentexp); | ||
1166 | startexp = startexp >> 2; | ||
1167 | while (startexp > MAX_EXP && sd->params.exposure.gain < | ||
1168 | sd->params.exposure.gainMode - 1) { | ||
1169 | startexp = startexp >> 1; | ||
1170 | ++sd->params.exposure.gain; | ||
1171 | } | ||
1172 | if (FIRMWARE_VERSION(1, 2) && startexp > MAX_EXP_102) | ||
1173 | startexp = MAX_EXP_102; | ||
1174 | if (startexp > MAX_EXP) | ||
1175 | startexp = MAX_EXP; | ||
1176 | sd->params.exposure.coarseExpLo = startexp & 0xff; | ||
1177 | sd->params.exposure.coarseExpHi = startexp >> 8; | ||
1178 | sd->params.exposure.redComp = COMP_RED; | ||
1179 | sd->params.exposure.green1Comp = COMP_GREEN1; | ||
1180 | sd->params.exposure.green2Comp = COMP_GREEN2; | ||
1181 | sd->params.exposure.blueComp = COMP_BLUE; | ||
1182 | sd->params.exposure.compMode = 1; | ||
1183 | sd->params.apcor.gain1 = 0x18; | ||
1184 | sd->params.apcor.gain2 = 0x16; | ||
1185 | sd->params.apcor.gain4 = 0x24; | ||
1186 | sd->params.apcor.gain8 = 0x34; | ||
1187 | } | ||
1188 | sd->params.vlOffset.gain1 = 20; | ||
1189 | sd->params.vlOffset.gain2 = 24; | ||
1190 | sd->params.vlOffset.gain4 = 26; | ||
1191 | sd->params.vlOffset.gain8 = 26; | ||
1192 | |||
1193 | if (apply) { | ||
1194 | ret = command_setexposure(gspca_dev); | ||
1195 | if (ret) | ||
1196 | return ret; | ||
1197 | |||
1198 | ret = command_setapcor(gspca_dev); | ||
1199 | if (ret) | ||
1200 | return ret; | ||
1201 | |||
1202 | ret = command_setvloffset(gspca_dev); | ||
1203 | if (ret) | ||
1204 | return ret; | ||
1205 | |||
1206 | ret = command_setflickerctrl(gspca_dev); | ||
1207 | if (ret) | ||
1208 | return ret; | ||
1209 | } | ||
1210 | |||
1211 | return 0; | ||
1212 | #undef EXP_FROM_COMP | ||
1213 | #undef COMPGAIN | ||
1214 | } | ||
1215 | |||
1216 | /* monitor the exposure and adjust the sensor frame rate if needed */ | ||
1217 | static void monitor_exposure(struct gspca_dev *gspca_dev) | ||
1218 | { | ||
1219 | struct sd *sd = (struct sd *) gspca_dev; | ||
1220 | u8 exp_acc, bcomp, gain, coarseL, cmd[8]; | ||
1221 | int ret, light_exp, dark_exp, very_dark_exp; | ||
1222 | int old_exposure, new_exposure, framerate; | ||
1223 | int setfps = 0, setexp = 0, setflicker = 0; | ||
1224 | |||
1225 | /* get necessary stats and register settings from camera */ | ||
1226 | /* do_command can't handle this, so do it ourselves */ | ||
1227 | cmd[0] = CPIA_COMMAND_ReadVPRegs >> 8; | ||
1228 | cmd[1] = CPIA_COMMAND_ReadVPRegs & 0xff; | ||
1229 | cmd[2] = 30; | ||
1230 | cmd[3] = 4; | ||
1231 | cmd[4] = 9; | ||
1232 | cmd[5] = 8; | ||
1233 | cmd[6] = 8; | ||
1234 | cmd[7] = 0; | ||
1235 | ret = cpia_usb_transferCmd(gspca_dev, cmd); | ||
1236 | if (ret) { | ||
1237 | PDEBUG(D_ERR, "ReadVPRegs(30,4,9,8) - failed: %d", ret); | ||
1238 | return; | ||
1239 | } | ||
1240 | exp_acc = gspca_dev->usb_buf[0]; | ||
1241 | bcomp = gspca_dev->usb_buf[1]; | ||
1242 | gain = gspca_dev->usb_buf[2]; | ||
1243 | coarseL = gspca_dev->usb_buf[3]; | ||
1244 | |||
1245 | light_exp = sd->params.colourParams.brightness + | ||
1246 | TC - 50 + EXP_ACC_LIGHT; | ||
1247 | if (light_exp > 255) | ||
1248 | light_exp = 255; | ||
1249 | dark_exp = sd->params.colourParams.brightness + | ||
1250 | TC - 50 - EXP_ACC_DARK; | ||
1251 | if (dark_exp < 0) | ||
1252 | dark_exp = 0; | ||
1253 | very_dark_exp = dark_exp / 2; | ||
1254 | |||
1255 | old_exposure = sd->params.exposure.coarseExpHi * 256 + | ||
1256 | sd->params.exposure.coarseExpLo; | ||
1257 | |||
1258 | if (!sd->params.flickerControl.disabled) { | ||
1259 | /* Flicker control on */ | ||
1260 | int max_comp = FIRMWARE_VERSION(1, 2) ? MAX_COMP : | ||
1261 | HIGH_COMP_102; | ||
1262 | bcomp += 128; /* decode */ | ||
1263 | if (bcomp >= max_comp && exp_acc < dark_exp) { | ||
1264 | /* dark */ | ||
1265 | if (exp_acc < very_dark_exp) { | ||
1266 | /* very dark */ | ||
1267 | if (sd->exposure_status == EXPOSURE_VERY_DARK) | ||
1268 | ++sd->exposure_count; | ||
1269 | else { | ||
1270 | sd->exposure_status = | ||
1271 | EXPOSURE_VERY_DARK; | ||
1272 | sd->exposure_count = 1; | ||
1273 | } | ||
1274 | } else { | ||
1275 | /* just dark */ | ||
1276 | if (sd->exposure_status == EXPOSURE_DARK) | ||
1277 | ++sd->exposure_count; | ||
1278 | else { | ||
1279 | sd->exposure_status = EXPOSURE_DARK; | ||
1280 | sd->exposure_count = 1; | ||
1281 | } | ||
1282 | } | ||
1283 | } else if (old_exposure <= LOW_EXP || exp_acc > light_exp) { | ||
1284 | /* light */ | ||
1285 | if (old_exposure <= VERY_LOW_EXP) { | ||
1286 | /* very light */ | ||
1287 | if (sd->exposure_status == EXPOSURE_VERY_LIGHT) | ||
1288 | ++sd->exposure_count; | ||
1289 | else { | ||
1290 | sd->exposure_status = | ||
1291 | EXPOSURE_VERY_LIGHT; | ||
1292 | sd->exposure_count = 1; | ||
1293 | } | ||
1294 | } else { | ||
1295 | /* just light */ | ||
1296 | if (sd->exposure_status == EXPOSURE_LIGHT) | ||
1297 | ++sd->exposure_count; | ||
1298 | else { | ||
1299 | sd->exposure_status = EXPOSURE_LIGHT; | ||
1300 | sd->exposure_count = 1; | ||
1301 | } | ||
1302 | } | ||
1303 | } else { | ||
1304 | /* not dark or light */ | ||
1305 | sd->exposure_status = EXPOSURE_NORMAL; | ||
1306 | } | ||
1307 | } else { | ||
1308 | /* Flicker control off */ | ||
1309 | if (old_exposure >= MAX_EXP && exp_acc < dark_exp) { | ||
1310 | /* dark */ | ||
1311 | if (exp_acc < very_dark_exp) { | ||
1312 | /* very dark */ | ||
1313 | if (sd->exposure_status == EXPOSURE_VERY_DARK) | ||
1314 | ++sd->exposure_count; | ||
1315 | else { | ||
1316 | sd->exposure_status = | ||
1317 | EXPOSURE_VERY_DARK; | ||
1318 | sd->exposure_count = 1; | ||
1319 | } | ||
1320 | } else { | ||
1321 | /* just dark */ | ||
1322 | if (sd->exposure_status == EXPOSURE_DARK) | ||
1323 | ++sd->exposure_count; | ||
1324 | else { | ||
1325 | sd->exposure_status = EXPOSURE_DARK; | ||
1326 | sd->exposure_count = 1; | ||
1327 | } | ||
1328 | } | ||
1329 | } else if (old_exposure <= LOW_EXP || exp_acc > light_exp) { | ||
1330 | /* light */ | ||
1331 | if (old_exposure <= VERY_LOW_EXP) { | ||
1332 | /* very light */ | ||
1333 | if (sd->exposure_status == EXPOSURE_VERY_LIGHT) | ||
1334 | ++sd->exposure_count; | ||
1335 | else { | ||
1336 | sd->exposure_status = | ||
1337 | EXPOSURE_VERY_LIGHT; | ||
1338 | sd->exposure_count = 1; | ||
1339 | } | ||
1340 | } else { | ||
1341 | /* just light */ | ||
1342 | if (sd->exposure_status == EXPOSURE_LIGHT) | ||
1343 | ++sd->exposure_count; | ||
1344 | else { | ||
1345 | sd->exposure_status = EXPOSURE_LIGHT; | ||
1346 | sd->exposure_count = 1; | ||
1347 | } | ||
1348 | } | ||
1349 | } else { | ||
1350 | /* not dark or light */ | ||
1351 | sd->exposure_status = EXPOSURE_NORMAL; | ||
1352 | } | ||
1353 | } | ||
1354 | |||
1355 | framerate = atomic_read(&sd->fps); | ||
1356 | if (framerate > 30 || framerate < 1) | ||
1357 | framerate = 1; | ||
1358 | |||
1359 | if (!sd->params.flickerControl.disabled) { | ||
1360 | /* Flicker control on */ | ||
1361 | if ((sd->exposure_status == EXPOSURE_VERY_DARK || | ||
1362 | sd->exposure_status == EXPOSURE_DARK) && | ||
1363 | sd->exposure_count >= DARK_TIME * framerate && | ||
1364 | sd->params.sensorFps.divisor < 3) { | ||
1365 | |||
1366 | /* dark for too long */ | ||
1367 | ++sd->params.sensorFps.divisor; | ||
1368 | setfps = 1; | ||
1369 | |||
1370 | sd->params.flickerControl.coarseJump = | ||
1371 | flicker_jumps[sd->mainsFreq] | ||
1372 | [sd->params.sensorFps.baserate] | ||
1373 | [sd->params.sensorFps.divisor]; | ||
1374 | setflicker = 1; | ||
1375 | |||
1376 | new_exposure = sd->params.flickerControl.coarseJump-1; | ||
1377 | while (new_exposure < old_exposure / 2) | ||
1378 | new_exposure += | ||
1379 | sd->params.flickerControl.coarseJump; | ||
1380 | sd->params.exposure.coarseExpLo = new_exposure & 0xff; | ||
1381 | sd->params.exposure.coarseExpHi = new_exposure >> 8; | ||
1382 | setexp = 1; | ||
1383 | sd->exposure_status = EXPOSURE_NORMAL; | ||
1384 | PDEBUG(D_CONF, "Automatically decreasing sensor_fps"); | ||
1385 | |||
1386 | } else if ((sd->exposure_status == EXPOSURE_VERY_LIGHT || | ||
1387 | sd->exposure_status == EXPOSURE_LIGHT) && | ||
1388 | sd->exposure_count >= LIGHT_TIME * framerate && | ||
1389 | sd->params.sensorFps.divisor > 0) { | ||
1390 | |||
1391 | /* light for too long */ | ||
1392 | int max_exp = FIRMWARE_VERSION(1, 2) ? MAX_EXP_102 : | ||
1393 | MAX_EXP; | ||
1394 | --sd->params.sensorFps.divisor; | ||
1395 | setfps = 1; | ||
1396 | |||
1397 | sd->params.flickerControl.coarseJump = | ||
1398 | flicker_jumps[sd->mainsFreq] | ||
1399 | [sd->params.sensorFps.baserate] | ||
1400 | [sd->params.sensorFps.divisor]; | ||
1401 | setflicker = 1; | ||
1402 | |||
1403 | new_exposure = sd->params.flickerControl.coarseJump-1; | ||
1404 | while (new_exposure < 2 * old_exposure && | ||
1405 | new_exposure + | ||
1406 | sd->params.flickerControl.coarseJump < max_exp) | ||
1407 | new_exposure += | ||
1408 | sd->params.flickerControl.coarseJump; | ||
1409 | sd->params.exposure.coarseExpLo = new_exposure & 0xff; | ||
1410 | sd->params.exposure.coarseExpHi = new_exposure >> 8; | ||
1411 | setexp = 1; | ||
1412 | sd->exposure_status = EXPOSURE_NORMAL; | ||
1413 | PDEBUG(D_CONF, "Automatically increasing sensor_fps"); | ||
1414 | } | ||
1415 | } else { | ||
1416 | /* Flicker control off */ | ||
1417 | if ((sd->exposure_status == EXPOSURE_VERY_DARK || | ||
1418 | sd->exposure_status == EXPOSURE_DARK) && | ||
1419 | sd->exposure_count >= DARK_TIME * framerate && | ||
1420 | sd->params.sensorFps.divisor < 3) { | ||
1421 | |||
1422 | /* dark for too long */ | ||
1423 | ++sd->params.sensorFps.divisor; | ||
1424 | setfps = 1; | ||
1425 | |||
1426 | if (sd->params.exposure.gain > 0) { | ||
1427 | --sd->params.exposure.gain; | ||
1428 | setexp = 1; | ||
1429 | } | ||
1430 | sd->exposure_status = EXPOSURE_NORMAL; | ||
1431 | PDEBUG(D_CONF, "Automatically decreasing sensor_fps"); | ||
1432 | |||
1433 | } else if ((sd->exposure_status == EXPOSURE_VERY_LIGHT || | ||
1434 | sd->exposure_status == EXPOSURE_LIGHT) && | ||
1435 | sd->exposure_count >= LIGHT_TIME * framerate && | ||
1436 | sd->params.sensorFps.divisor > 0) { | ||
1437 | |||
1438 | /* light for too long */ | ||
1439 | --sd->params.sensorFps.divisor; | ||
1440 | setfps = 1; | ||
1441 | |||
1442 | if (sd->params.exposure.gain < | ||
1443 | sd->params.exposure.gainMode - 1) { | ||
1444 | ++sd->params.exposure.gain; | ||
1445 | setexp = 1; | ||
1446 | } | ||
1447 | sd->exposure_status = EXPOSURE_NORMAL; | ||
1448 | PDEBUG(D_CONF, "Automatically increasing sensor_fps"); | ||
1449 | } | ||
1450 | } | ||
1451 | |||
1452 | if (setexp) | ||
1453 | command_setexposure(gspca_dev); | ||
1454 | |||
1455 | if (setfps) | ||
1456 | command_setsensorfps(gspca_dev); | ||
1457 | |||
1458 | if (setflicker) | ||
1459 | command_setflickerctrl(gspca_dev); | ||
1460 | } | ||
1461 | |||
1462 | /*-----------------------------------------------------------------*/ | ||
1463 | /* if flicker is switched off, this function switches it back on.It checks, | ||
1464 | however, that conditions are suitable before restarting it. | ||
1465 | This should only be called for firmware version 1.2. | ||
1466 | |||
1467 | It also adjust the colour balance when an exposure step is detected - as | ||
1468 | long as flicker is running | ||
1469 | */ | ||
1470 | static void restart_flicker(struct gspca_dev *gspca_dev) | ||
1471 | { | ||
1472 | struct sd *sd = (struct sd *) gspca_dev; | ||
1473 | int cam_exposure, old_exp; | ||
1474 | |||
1475 | if (!FIRMWARE_VERSION(1, 2)) | ||
1476 | return; | ||
1477 | |||
1478 | cam_exposure = atomic_read(&sd->cam_exposure); | ||
1479 | |||
1480 | if (sd->params.flickerControl.flickerMode == 0 || | ||
1481 | cam_exposure == 0) | ||
1482 | return; | ||
1483 | |||
1484 | old_exp = sd->params.exposure.coarseExpLo + | ||
1485 | sd->params.exposure.coarseExpHi*256; | ||
1486 | /* | ||
1487 | see how far away camera exposure is from a valid | ||
1488 | flicker exposure value | ||
1489 | */ | ||
1490 | cam_exposure %= sd->params.flickerControl.coarseJump; | ||
1491 | if (!sd->params.flickerControl.disabled && | ||
1492 | cam_exposure <= sd->params.flickerControl.coarseJump - 3) { | ||
1493 | /* Flicker control auto-disabled */ | ||
1494 | sd->params.flickerControl.disabled = 1; | ||
1495 | } | ||
1496 | |||
1497 | if (sd->params.flickerControl.disabled && | ||
1498 | old_exp > sd->params.flickerControl.coarseJump + | ||
1499 | ROUND_UP_EXP_FOR_FLICKER) { | ||
1500 | /* exposure is now high enough to switch | ||
1501 | flicker control back on */ | ||
1502 | set_flicker(gspca_dev, 1, 1); | ||
1503 | } | ||
1504 | } | ||
1505 | |||
1506 | /* this function is called at probe time */ | ||
1507 | static int sd_config(struct gspca_dev *gspca_dev, | ||
1508 | const struct usb_device_id *id) | ||
1509 | { | ||
1510 | struct cam *cam; | ||
1511 | |||
1512 | reset_camera_params(gspca_dev); | ||
1513 | |||
1514 | PDEBUG(D_PROBE, "cpia CPiA camera detected (vid/pid 0x%04X:0x%04X)", | ||
1515 | id->idVendor, id->idProduct); | ||
1516 | |||
1517 | cam = &gspca_dev->cam; | ||
1518 | cam->cam_mode = mode; | ||
1519 | cam->nmodes = ARRAY_SIZE(mode); | ||
1520 | |||
1521 | sd_setfreq(gspca_dev, FREQ_DEF); | ||
1522 | |||
1523 | return 0; | ||
1524 | } | ||
1525 | |||
1526 | /* -- start the camera -- */ | ||
1527 | static int sd_start(struct gspca_dev *gspca_dev) | ||
1528 | { | ||
1529 | struct sd *sd = (struct sd *) gspca_dev; | ||
1530 | int priv, ret; | ||
1531 | |||
1532 | /* Start the camera in low power mode */ | ||
1533 | if (goto_low_power(gspca_dev)) { | ||
1534 | if (sd->params.status.systemState != WARM_BOOT_STATE) { | ||
1535 | PDEBUG(D_ERR, "unexpected systemstate: %02x", | ||
1536 | sd->params.status.systemState); | ||
1537 | printstatus(&sd->params); | ||
1538 | return -ENODEV; | ||
1539 | } | ||
1540 | |||
1541 | /* FIXME: this is just dirty trial and error */ | ||
1542 | ret = goto_high_power(gspca_dev); | ||
1543 | if (ret) | ||
1544 | return ret; | ||
1545 | |||
1546 | ret = do_command(gspca_dev, CPIA_COMMAND_DiscardFrame, | ||
1547 | 0, 0, 0, 0); | ||
1548 | if (ret) | ||
1549 | return ret; | ||
1550 | |||
1551 | ret = goto_low_power(gspca_dev); | ||
1552 | if (ret) | ||
1553 | return ret; | ||
1554 | } | ||
1555 | |||
1556 | /* procedure described in developer's guide p3-28 */ | ||
1557 | |||
1558 | /* Check the firmware version. */ | ||
1559 | sd->params.version.firmwareVersion = 0; | ||
1560 | get_version_information(gspca_dev); | ||
1561 | if (sd->params.version.firmwareVersion != 1) { | ||
1562 | PDEBUG(D_ERR, "only firmware version 1 is supported (got: %d)", | ||
1563 | sd->params.version.firmwareVersion); | ||
1564 | return -ENODEV; | ||
1565 | } | ||
1566 | |||
1567 | /* A bug in firmware 1-02 limits gainMode to 2 */ | ||
1568 | if (sd->params.version.firmwareRevision <= 2 && | ||
1569 | sd->params.exposure.gainMode > 2) { | ||
1570 | sd->params.exposure.gainMode = 2; | ||
1571 | } | ||
1572 | |||
1573 | /* set QX3 detected flag */ | ||
1574 | sd->params.qx3.qx3_detected = (sd->params.pnpID.vendor == 0x0813 && | ||
1575 | sd->params.pnpID.product == 0x0001); | ||
1576 | |||
1577 | /* The fatal error checking should be done after | ||
1578 | * the camera powers up (developer's guide p 3-38) */ | ||
1579 | |||
1580 | /* Set streamState before transition to high power to avoid bug | ||
1581 | * in firmware 1-02 */ | ||
1582 | ret = do_command(gspca_dev, CPIA_COMMAND_ModifyCameraStatus, | ||
1583 | STREAMSTATE, 0, STREAM_NOT_READY, 0); | ||
1584 | if (ret) | ||
1585 | return ret; | ||
1586 | |||
1587 | /* GotoHiPower */ | ||
1588 | ret = goto_high_power(gspca_dev); | ||
1589 | if (ret) | ||
1590 | return ret; | ||
1591 | |||
1592 | /* Check the camera status */ | ||
1593 | ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); | ||
1594 | if (ret) | ||
1595 | return ret; | ||
1596 | |||
1597 | if (sd->params.status.fatalError) { | ||
1598 | PDEBUG(D_ERR, "fatal_error: %04x, vp_status: %04x", | ||
1599 | sd->params.status.fatalError, | ||
1600 | sd->params.status.vpStatus); | ||
1601 | return -EIO; | ||
1602 | } | ||
1603 | |||
1604 | /* VPVersion can't be retrieved before the camera is in HiPower, | ||
1605 | * so get it here instead of in get_version_information. */ | ||
1606 | ret = do_command(gspca_dev, CPIA_COMMAND_GetVPVersion, 0, 0, 0, 0); | ||
1607 | if (ret) | ||
1608 | return ret; | ||
1609 | |||
1610 | /* Determine video mode settings */ | ||
1611 | sd->params.streamStartLine = 120; | ||
1612 | |||
1613 | priv = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; | ||
1614 | if (priv & 0x01) { /* crop */ | ||
1615 | sd->params.roi.colStart = 2; | ||
1616 | sd->params.roi.rowStart = 6; | ||
1617 | } else { | ||
1618 | sd->params.roi.colStart = 0; | ||
1619 | sd->params.roi.rowStart = 0; | ||
1620 | } | ||
1621 | |||
1622 | if (priv & 0x02) { /* quarter */ | ||
1623 | sd->params.format.videoSize = VIDEOSIZE_QCIF; | ||
1624 | sd->params.roi.colStart /= 2; | ||
1625 | sd->params.roi.rowStart /= 2; | ||
1626 | sd->params.streamStartLine /= 2; | ||
1627 | } else | ||
1628 | sd->params.format.videoSize = VIDEOSIZE_CIF; | ||
1629 | |||
1630 | sd->params.roi.colEnd = sd->params.roi.colStart + | ||
1631 | (gspca_dev->width >> 3); | ||
1632 | sd->params.roi.rowEnd = sd->params.roi.rowStart + | ||
1633 | (gspca_dev->height >> 2); | ||
1634 | |||
1635 | /* And now set the camera to a known state */ | ||
1636 | ret = do_command(gspca_dev, CPIA_COMMAND_SetGrabMode, | ||
1637 | CPIA_GRAB_CONTINEOUS, 0, 0, 0); | ||
1638 | if (ret) | ||
1639 | return ret; | ||
1640 | /* We start with compression disabled, as we need one uncompressed | ||
1641 | frame to handle later compressed frames */ | ||
1642 | ret = do_command(gspca_dev, CPIA_COMMAND_SetCompression, | ||
1643 | CPIA_COMPRESSION_NONE, | ||
1644 | NO_DECIMATION, 0, 0); | ||
1645 | if (ret) | ||
1646 | return ret; | ||
1647 | ret = command_setcompressiontarget(gspca_dev); | ||
1648 | if (ret) | ||
1649 | return ret; | ||
1650 | ret = command_setcolourparams(gspca_dev); | ||
1651 | if (ret) | ||
1652 | return ret; | ||
1653 | ret = command_setformat(gspca_dev); | ||
1654 | if (ret) | ||
1655 | return ret; | ||
1656 | ret = command_setyuvtresh(gspca_dev); | ||
1657 | if (ret) | ||
1658 | return ret; | ||
1659 | ret = command_setecptiming(gspca_dev); | ||
1660 | if (ret) | ||
1661 | return ret; | ||
1662 | ret = command_setcompressionparams(gspca_dev); | ||
1663 | if (ret) | ||
1664 | return ret; | ||
1665 | ret = command_setexposure(gspca_dev); | ||
1666 | if (ret) | ||
1667 | return ret; | ||
1668 | ret = command_setcolourbalance(gspca_dev); | ||
1669 | if (ret) | ||
1670 | return ret; | ||
1671 | ret = command_setsensorfps(gspca_dev); | ||
1672 | if (ret) | ||
1673 | return ret; | ||
1674 | ret = command_setapcor(gspca_dev); | ||
1675 | if (ret) | ||
1676 | return ret; | ||
1677 | ret = command_setflickerctrl(gspca_dev); | ||
1678 | if (ret) | ||
1679 | return ret; | ||
1680 | ret = command_setvloffset(gspca_dev); | ||
1681 | if (ret) | ||
1682 | return ret; | ||
1683 | |||
1684 | /* Start stream */ | ||
1685 | ret = command_resume(gspca_dev); | ||
1686 | if (ret) | ||
1687 | return ret; | ||
1688 | |||
1689 | /* Wait 6 frames before turning compression on for the sensor to get | ||
1690 | all settings and AEC/ACB to settle */ | ||
1691 | sd->first_frame = 6; | ||
1692 | sd->exposure_status = EXPOSURE_NORMAL; | ||
1693 | sd->exposure_count = 0; | ||
1694 | atomic_set(&sd->cam_exposure, 0); | ||
1695 | atomic_set(&sd->fps, 0); | ||
1696 | |||
1697 | return 0; | ||
1698 | } | ||
1699 | |||
1700 | static void sd_stopN(struct gspca_dev *gspca_dev) | ||
1701 | { | ||
1702 | command_pause(gspca_dev); | ||
1703 | |||
1704 | /* save camera state for later open (developers guide ch 3.5.3) */ | ||
1705 | save_camera_state(gspca_dev); | ||
1706 | |||
1707 | /* GotoLoPower */ | ||
1708 | goto_low_power(gspca_dev); | ||
1709 | |||
1710 | /* Update the camera status */ | ||
1711 | do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0); | ||
1712 | } | ||
1713 | |||
1714 | /* this function is called at probe and resume time */ | ||
1715 | static int sd_init(struct gspca_dev *gspca_dev) | ||
1716 | { | ||
1717 | struct sd *sd = (struct sd *) gspca_dev; | ||
1718 | int ret; | ||
1719 | |||
1720 | /* Start / Stop the camera to make sure we are talking to | ||
1721 | a supported camera, and to get some information from it | ||
1722 | to print. */ | ||
1723 | ret = sd_start(gspca_dev); | ||
1724 | if (ret) | ||
1725 | return ret; | ||
1726 | |||
1727 | sd_stopN(gspca_dev); | ||
1728 | |||
1729 | PDEBUG(D_PROBE, "CPIA Version: %d.%02d (%d.%d)", | ||
1730 | sd->params.version.firmwareVersion, | ||
1731 | sd->params.version.firmwareRevision, | ||
1732 | sd->params.version.vcVersion, | ||
1733 | sd->params.version.vcRevision); | ||
1734 | PDEBUG(D_PROBE, "CPIA PnP-ID: %04x:%04x:%04x", | ||
1735 | sd->params.pnpID.vendor, sd->params.pnpID.product, | ||
1736 | sd->params.pnpID.deviceRevision); | ||
1737 | PDEBUG(D_PROBE, "VP-Version: %d.%d %04x", | ||
1738 | sd->params.vpVersion.vpVersion, | ||
1739 | sd->params.vpVersion.vpRevision, | ||
1740 | sd->params.vpVersion.cameraHeadID); | ||
1741 | |||
1742 | return 0; | ||
1743 | } | ||
1744 | |||
1745 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | ||
1746 | u8 *data, | ||
1747 | int len) | ||
1748 | { | ||
1749 | struct sd *sd = (struct sd *) gspca_dev; | ||
1750 | |||
1751 | /* Check for SOF */ | ||
1752 | if (len >= 64 && | ||
1753 | data[0] == MAGIC_0 && data[1] == MAGIC_1 && | ||
1754 | data[16] == sd->params.format.videoSize && | ||
1755 | data[17] == sd->params.format.subSample && | ||
1756 | data[18] == sd->params.format.yuvOrder && | ||
1757 | data[24] == sd->params.roi.colStart && | ||
1758 | data[25] == sd->params.roi.colEnd && | ||
1759 | data[26] == sd->params.roi.rowStart && | ||
1760 | data[27] == sd->params.roi.rowEnd) { | ||
1761 | struct gspca_frame *frame = gspca_get_i_frame(gspca_dev); | ||
1762 | |||
1763 | atomic_set(&sd->cam_exposure, data[39] * 2); | ||
1764 | atomic_set(&sd->fps, data[41]); | ||
1765 | |||
1766 | if (frame == NULL) { | ||
1767 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
1768 | return; | ||
1769 | } | ||
1770 | |||
1771 | /* Check for proper EOF for last frame */ | ||
1772 | if ((frame->data_end - frame->data) > 4 && | ||
1773 | frame->data_end[-4] == 0xff && | ||
1774 | frame->data_end[-3] == 0xff && | ||
1775 | frame->data_end[-2] == 0xff && | ||
1776 | frame->data_end[-1] == 0xff) | ||
1777 | gspca_frame_add(gspca_dev, LAST_PACKET, | ||
1778 | NULL, 0); | ||
1779 | |||
1780 | gspca_frame_add(gspca_dev, FIRST_PACKET, data, len); | ||
1781 | return; | ||
1782 | } | ||
1783 | |||
1784 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | ||
1785 | } | ||
1786 | |||
1787 | static void sd_dq_callback(struct gspca_dev *gspca_dev) | ||
1788 | { | ||
1789 | struct sd *sd = (struct sd *) gspca_dev; | ||
1790 | |||
1791 | /* Set the normal compression settings once we have captured a | ||
1792 | few uncompressed frames (and AEC has hopefully settled) */ | ||
1793 | if (sd->first_frame) { | ||
1794 | sd->first_frame--; | ||
1795 | if (sd->first_frame == 0) | ||
1796 | command_setcompression(gspca_dev); | ||
1797 | } | ||
1798 | |||
1799 | /* Switch flicker control back on if it got turned off */ | ||
1800 | restart_flicker(gspca_dev); | ||
1801 | |||
1802 | /* If AEC is enabled, monitor the exposure and | ||
1803 | adjust the sensor frame rate if needed */ | ||
1804 | if (sd->params.exposure.expMode == 2) | ||
1805 | monitor_exposure(gspca_dev); | ||
1806 | |||
1807 | /* Update our knowledge of the camera state */ | ||
1808 | do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0); | ||
1809 | if (sd->params.qx3.qx3_detected) | ||
1810 | do_command(gspca_dev, CPIA_COMMAND_ReadMCPorts, 0, 0, 0, 0); | ||
1811 | } | ||
1812 | |||
1813 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | ||
1814 | { | ||
1815 | struct sd *sd = (struct sd *) gspca_dev; | ||
1816 | int ret; | ||
1817 | |||
1818 | sd->params.colourParams.brightness = val; | ||
1819 | sd->params.flickerControl.allowableOverExposure = | ||
1820 | find_over_exposure(sd->params.colourParams.brightness); | ||
1821 | if (gspca_dev->streaming) { | ||
1822 | ret = command_setcolourparams(gspca_dev); | ||
1823 | if (ret) | ||
1824 | return ret; | ||
1825 | return command_setflickerctrl(gspca_dev); | ||
1826 | } | ||
1827 | return 0; | ||
1828 | } | ||
1829 | |||
1830 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
1831 | { | ||
1832 | struct sd *sd = (struct sd *) gspca_dev; | ||
1833 | |||
1834 | *val = sd->params.colourParams.brightness; | ||
1835 | return 0; | ||
1836 | } | ||
1837 | |||
1838 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | ||
1839 | { | ||
1840 | struct sd *sd = (struct sd *) gspca_dev; | ||
1841 | |||
1842 | sd->params.colourParams.contrast = val; | ||
1843 | if (gspca_dev->streaming) | ||
1844 | return command_setcolourparams(gspca_dev); | ||
1845 | |||
1846 | return 0; | ||
1847 | } | ||
1848 | |||
1849 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | ||
1850 | { | ||
1851 | struct sd *sd = (struct sd *) gspca_dev; | ||
1852 | |||
1853 | *val = sd->params.colourParams.contrast; | ||
1854 | return 0; | ||
1855 | } | ||
1856 | |||
1857 | static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val) | ||
1858 | { | ||
1859 | struct sd *sd = (struct sd *) gspca_dev; | ||
1860 | |||
1861 | sd->params.colourParams.saturation = val; | ||
1862 | if (gspca_dev->streaming) | ||
1863 | return command_setcolourparams(gspca_dev); | ||
1864 | |||
1865 | return 0; | ||
1866 | } | ||
1867 | |||
1868 | static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val) | ||
1869 | { | ||
1870 | struct sd *sd = (struct sd *) gspca_dev; | ||
1871 | |||
1872 | *val = sd->params.colourParams.saturation; | ||
1873 | return 0; | ||
1874 | } | ||
1875 | |||
1876 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) | ||
1877 | { | ||
1878 | struct sd *sd = (struct sd *) gspca_dev; | ||
1879 | int on; | ||
1880 | |||
1881 | switch (val) { | ||
1882 | case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */ | ||
1883 | on = 0; | ||
1884 | break; | ||
1885 | case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ | ||
1886 | on = 1; | ||
1887 | sd->mainsFreq = 0; | ||
1888 | break; | ||
1889 | case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ | ||
1890 | on = 1; | ||
1891 | sd->mainsFreq = 1; | ||
1892 | break; | ||
1893 | default: | ||
1894 | return -EINVAL; | ||
1895 | } | ||
1896 | |||
1897 | sd->freq = val; | ||
1898 | sd->params.flickerControl.coarseJump = | ||
1899 | flicker_jumps[sd->mainsFreq] | ||
1900 | [sd->params.sensorFps.baserate] | ||
1901 | [sd->params.sensorFps.divisor]; | ||
1902 | |||
1903 | return set_flicker(gspca_dev, on, gspca_dev->streaming); | ||
1904 | } | ||
1905 | |||
1906 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val) | ||
1907 | { | ||
1908 | struct sd *sd = (struct sd *) gspca_dev; | ||
1909 | |||
1910 | *val = sd->freq; | ||
1911 | return 0; | ||
1912 | } | ||
1913 | |||
1914 | static int sd_setcomptarget(struct gspca_dev *gspca_dev, __s32 val) | ||
1915 | { | ||
1916 | struct sd *sd = (struct sd *) gspca_dev; | ||
1917 | |||
1918 | sd->params.compressionTarget.frTargeting = val; | ||
1919 | if (gspca_dev->streaming) | ||
1920 | return command_setcompressiontarget(gspca_dev); | ||
1921 | |||
1922 | return 0; | ||
1923 | } | ||
1924 | |||
1925 | static int sd_getcomptarget(struct gspca_dev *gspca_dev, __s32 *val) | ||
1926 | { | ||
1927 | struct sd *sd = (struct sd *) gspca_dev; | ||
1928 | |||
1929 | *val = sd->params.compressionTarget.frTargeting; | ||
1930 | return 0; | ||
1931 | } | ||
1932 | |||
1933 | static int sd_querymenu(struct gspca_dev *gspca_dev, | ||
1934 | struct v4l2_querymenu *menu) | ||
1935 | { | ||
1936 | switch (menu->id) { | ||
1937 | case V4L2_CID_POWER_LINE_FREQUENCY: | ||
1938 | switch (menu->index) { | ||
1939 | case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */ | ||
1940 | strcpy((char *) menu->name, "NoFliker"); | ||
1941 | return 0; | ||
1942 | case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ | ||
1943 | strcpy((char *) menu->name, "50 Hz"); | ||
1944 | return 0; | ||
1945 | case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ | ||
1946 | strcpy((char *) menu->name, "60 Hz"); | ||
1947 | return 0; | ||
1948 | } | ||
1949 | break; | ||
1950 | case V4L2_CID_COMP_TARGET: | ||
1951 | switch (menu->index) { | ||
1952 | case CPIA_COMPRESSION_TARGET_QUALITY: | ||
1953 | strcpy((char *) menu->name, "Quality"); | ||
1954 | return 0; | ||
1955 | case CPIA_COMPRESSION_TARGET_FRAMERATE: | ||
1956 | strcpy((char *) menu->name, "Framerate"); | ||
1957 | return 0; | ||
1958 | } | ||
1959 | break; | ||
1960 | } | ||
1961 | return -EINVAL; | ||
1962 | } | ||
1963 | |||
1964 | /* sub-driver description */ | ||
1965 | static const struct sd_desc sd_desc = { | ||
1966 | .name = MODULE_NAME, | ||
1967 | .ctrls = sd_ctrls, | ||
1968 | .nctrls = ARRAY_SIZE(sd_ctrls), | ||
1969 | .config = sd_config, | ||
1970 | .init = sd_init, | ||
1971 | .start = sd_start, | ||
1972 | .stopN = sd_stopN, | ||
1973 | .dq_callback = sd_dq_callback, | ||
1974 | .pkt_scan = sd_pkt_scan, | ||
1975 | .querymenu = sd_querymenu, | ||
1976 | }; | ||
1977 | |||
1978 | /* -- module initialisation -- */ | ||
1979 | static const __devinitdata struct usb_device_id device_table[] = { | ||
1980 | {USB_DEVICE(0x0553, 0x0002)}, | ||
1981 | {USB_DEVICE(0x0813, 0x0001)}, | ||
1982 | {} | ||
1983 | }; | ||
1984 | MODULE_DEVICE_TABLE(usb, device_table); | ||
1985 | |||
1986 | /* -- device connect -- */ | ||
1987 | static int sd_probe(struct usb_interface *intf, | ||
1988 | const struct usb_device_id *id) | ||
1989 | { | ||
1990 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | ||
1991 | THIS_MODULE); | ||
1992 | } | ||
1993 | |||
1994 | static struct usb_driver sd_driver = { | ||
1995 | .name = MODULE_NAME, | ||
1996 | .id_table = device_table, | ||
1997 | .probe = sd_probe, | ||
1998 | .disconnect = gspca_disconnect, | ||
1999 | #ifdef CONFIG_PM | ||
2000 | .suspend = gspca_suspend, | ||
2001 | .resume = gspca_resume, | ||
2002 | #endif | ||
2003 | }; | ||
2004 | |||
2005 | /* -- module insert / remove -- */ | ||
2006 | static int __init sd_mod_init(void) | ||
2007 | { | ||
2008 | int ret; | ||
2009 | ret = usb_register(&sd_driver); | ||
2010 | if (ret < 0) | ||
2011 | return ret; | ||
2012 | PDEBUG(D_PROBE, "registered"); | ||
2013 | return 0; | ||
2014 | } | ||
2015 | static void __exit sd_mod_exit(void) | ||
2016 | { | ||
2017 | usb_deregister(&sd_driver); | ||
2018 | PDEBUG(D_PROBE, "deregistered"); | ||
2019 | } | ||
2020 | |||
2021 | module_init(sd_mod_init); | ||
2022 | module_exit(sd_mod_exit); | ||
diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c index fdf4c0ec5e7a..ecd4d743d2bc 100644 --- a/drivers/media/video/gspca/etoms.c +++ b/drivers/media/video/gspca/etoms.c | |||
@@ -52,7 +52,7 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | |||
52 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | 52 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); |
53 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | 53 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); |
54 | 54 | ||
55 | static struct ctrl sd_ctrls[] = { | 55 | static const struct ctrl sd_ctrls[] = { |
56 | { | 56 | { |
57 | { | 57 | { |
58 | .id = V4L2_CID_BRIGHTNESS, | 58 | .id = V4L2_CID_BRIGHTNESS, |
@@ -851,7 +851,7 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) | |||
851 | } | 851 | } |
852 | 852 | ||
853 | /* sub-driver description */ | 853 | /* sub-driver description */ |
854 | static struct sd_desc sd_desc = { | 854 | static const struct sd_desc sd_desc = { |
855 | .name = MODULE_NAME, | 855 | .name = MODULE_NAME, |
856 | .ctrls = sd_ctrls, | 856 | .ctrls = sd_ctrls, |
857 | .nctrls = ARRAY_SIZE(sd_ctrls), | 857 | .nctrls = ARRAY_SIZE(sd_ctrls), |
diff --git a/drivers/media/video/gspca/gl860/gl860.c b/drivers/media/video/gspca/gl860/gl860.c index 4878c8f66543..9e42476c0eaf 100644 --- a/drivers/media/video/gspca/gl860/gl860.c +++ b/drivers/media/video/gspca/gl860/gl860.c | |||
@@ -161,7 +161,7 @@ static int gl860_build_control_table(struct gspca_dev *gspca_dev) | |||
161 | 161 | ||
162 | /*==================== sud-driver structure initialisation =================*/ | 162 | /*==================== sud-driver structure initialisation =================*/ |
163 | 163 | ||
164 | static struct sd_desc sd_desc_mi1320 = { | 164 | static const struct sd_desc sd_desc_mi1320 = { |
165 | .name = MODULE_NAME, | 165 | .name = MODULE_NAME, |
166 | .ctrls = sd_ctrls_mi1320, | 166 | .ctrls = sd_ctrls_mi1320, |
167 | .nctrls = GL860_NCTRLS, | 167 | .nctrls = GL860_NCTRLS, |
@@ -174,7 +174,7 @@ static struct sd_desc sd_desc_mi1320 = { | |||
174 | .dq_callback = sd_callback, | 174 | .dq_callback = sd_callback, |
175 | }; | 175 | }; |
176 | 176 | ||
177 | static struct sd_desc sd_desc_mi2020 = { | 177 | static const struct sd_desc sd_desc_mi2020 = { |
178 | .name = MODULE_NAME, | 178 | .name = MODULE_NAME, |
179 | .ctrls = sd_ctrls_mi2020, | 179 | .ctrls = sd_ctrls_mi2020, |
180 | .nctrls = GL860_NCTRLS, | 180 | .nctrls = GL860_NCTRLS, |
@@ -187,7 +187,7 @@ static struct sd_desc sd_desc_mi2020 = { | |||
187 | .dq_callback = sd_callback, | 187 | .dq_callback = sd_callback, |
188 | }; | 188 | }; |
189 | 189 | ||
190 | static struct sd_desc sd_desc_mi2020b = { | 190 | static const struct sd_desc sd_desc_mi2020b = { |
191 | .name = MODULE_NAME, | 191 | .name = MODULE_NAME, |
192 | .ctrls = sd_ctrls_mi2020b, | 192 | .ctrls = sd_ctrls_mi2020b, |
193 | .nctrls = GL860_NCTRLS, | 193 | .nctrls = GL860_NCTRLS, |
@@ -200,7 +200,7 @@ static struct sd_desc sd_desc_mi2020b = { | |||
200 | .dq_callback = sd_callback, | 200 | .dq_callback = sd_callback, |
201 | }; | 201 | }; |
202 | 202 | ||
203 | static struct sd_desc sd_desc_ov2640 = { | 203 | static const struct sd_desc sd_desc_ov2640 = { |
204 | .name = MODULE_NAME, | 204 | .name = MODULE_NAME, |
205 | .ctrls = sd_ctrls_ov2640, | 205 | .ctrls = sd_ctrls_ov2640, |
206 | .nctrls = GL860_NCTRLS, | 206 | .nctrls = GL860_NCTRLS, |
@@ -213,7 +213,7 @@ static struct sd_desc sd_desc_ov2640 = { | |||
213 | .dq_callback = sd_callback, | 213 | .dq_callback = sd_callback, |
214 | }; | 214 | }; |
215 | 215 | ||
216 | static struct sd_desc sd_desc_ov9655 = { | 216 | static const struct sd_desc sd_desc_ov9655 = { |
217 | .name = MODULE_NAME, | 217 | .name = MODULE_NAME, |
218 | .ctrls = sd_ctrls_ov9655, | 218 | .ctrls = sd_ctrls_ov9655, |
219 | .nctrls = GL860_NCTRLS, | 219 | .nctrls = GL860_NCTRLS, |
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index bd6214d4ab3b..222af479150b 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c | |||
@@ -3,6 +3,9 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2008-2009 Jean-Francois Moine (http://moinejf.free.fr) | 4 | * Copyright (C) 2008-2009 Jean-Francois Moine (http://moinejf.free.fr) |
5 | * | 5 | * |
6 | * Camera button input handling by Márton Németh | ||
7 | * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu> | ||
8 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | 9 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License as published by the | 10 | * under the terms of the GNU General Public License as published by the |
8 | * Free Software Foundation; either version 2 of the License, or (at your | 11 | * Free Software Foundation; either version 2 of the License, or (at your |
@@ -37,6 +40,11 @@ | |||
37 | 40 | ||
38 | #include "gspca.h" | 41 | #include "gspca.h" |
39 | 42 | ||
43 | #ifdef CONFIG_INPUT | ||
44 | #include <linux/input.h> | ||
45 | #include <linux/usb/input.h> | ||
46 | #endif | ||
47 | |||
40 | /* global values */ | 48 | /* global values */ |
41 | #define DEF_NURBS 3 /* default number of URBs */ | 49 | #define DEF_NURBS 3 /* default number of URBs */ |
42 | #if DEF_NURBS > MAX_NURBS | 50 | #if DEF_NURBS > MAX_NURBS |
@@ -47,7 +55,7 @@ MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | |||
47 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); | 55 | MODULE_DESCRIPTION("GSPCA USB Camera Driver"); |
48 | MODULE_LICENSE("GPL"); | 56 | MODULE_LICENSE("GPL"); |
49 | 57 | ||
50 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 8, 0) | 58 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 9, 0) |
51 | 59 | ||
52 | #ifdef GSPCA_DEBUG | 60 | #ifdef GSPCA_DEBUG |
53 | int gspca_debug = D_ERR | D_PROBE; | 61 | int gspca_debug = D_ERR | D_PROBE; |
@@ -104,15 +112,185 @@ static const struct vm_operations_struct gspca_vm_ops = { | |||
104 | .close = gspca_vm_close, | 112 | .close = gspca_vm_close, |
105 | }; | 113 | }; |
106 | 114 | ||
115 | /* | ||
116 | * Input and interrupt endpoint handling functions | ||
117 | */ | ||
118 | #ifdef CONFIG_INPUT | ||
119 | static void int_irq(struct urb *urb) | ||
120 | { | ||
121 | struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; | ||
122 | int ret; | ||
123 | |||
124 | ret = urb->status; | ||
125 | switch (ret) { | ||
126 | case 0: | ||
127 | if (gspca_dev->sd_desc->int_pkt_scan(gspca_dev, | ||
128 | urb->transfer_buffer, urb->actual_length) < 0) { | ||
129 | PDEBUG(D_ERR, "Unknown packet received"); | ||
130 | } | ||
131 | break; | ||
132 | |||
133 | case -ENOENT: | ||
134 | case -ECONNRESET: | ||
135 | case -ENODEV: | ||
136 | case -ESHUTDOWN: | ||
137 | /* Stop is requested either by software or hardware is gone, | ||
138 | * keep the ret value non-zero and don't resubmit later. | ||
139 | */ | ||
140 | break; | ||
141 | |||
142 | default: | ||
143 | PDEBUG(D_ERR, "URB error %i, resubmitting", urb->status); | ||
144 | urb->status = 0; | ||
145 | ret = 0; | ||
146 | } | ||
147 | |||
148 | if (ret == 0) { | ||
149 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
150 | if (ret < 0) | ||
151 | PDEBUG(D_ERR, "Resubmit URB failed with error %i", ret); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | static int gspca_input_connect(struct gspca_dev *dev) | ||
156 | { | ||
157 | struct input_dev *input_dev; | ||
158 | int err = 0; | ||
159 | |||
160 | dev->input_dev = NULL; | ||
161 | if (dev->sd_desc->int_pkt_scan || dev->sd_desc->other_input) { | ||
162 | input_dev = input_allocate_device(); | ||
163 | if (!input_dev) | ||
164 | return -ENOMEM; | ||
165 | |||
166 | usb_make_path(dev->dev, dev->phys, sizeof(dev->phys)); | ||
167 | strlcat(dev->phys, "/input0", sizeof(dev->phys)); | ||
168 | |||
169 | input_dev->name = dev->sd_desc->name; | ||
170 | input_dev->phys = dev->phys; | ||
171 | |||
172 | usb_to_input_id(dev->dev, &input_dev->id); | ||
173 | |||
174 | input_dev->evbit[0] = BIT_MASK(EV_KEY); | ||
175 | input_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA); | ||
176 | input_dev->dev.parent = &dev->dev->dev; | ||
177 | |||
178 | err = input_register_device(input_dev); | ||
179 | if (err) { | ||
180 | PDEBUG(D_ERR, "Input device registration failed " | ||
181 | "with error %i", err); | ||
182 | input_dev->dev.parent = NULL; | ||
183 | input_free_device(input_dev); | ||
184 | } else { | ||
185 | dev->input_dev = input_dev; | ||
186 | } | ||
187 | } | ||
188 | |||
189 | return err; | ||
190 | } | ||
191 | |||
192 | static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev, | ||
193 | struct usb_endpoint_descriptor *ep) | ||
194 | { | ||
195 | unsigned int buffer_len; | ||
196 | int interval; | ||
197 | struct urb *urb; | ||
198 | struct usb_device *dev; | ||
199 | void *buffer = NULL; | ||
200 | int ret = -EINVAL; | ||
201 | |||
202 | buffer_len = ep->wMaxPacketSize; | ||
203 | interval = ep->bInterval; | ||
204 | PDEBUG(D_PROBE, "found int in endpoint: 0x%x, " | ||
205 | "buffer_len=%u, interval=%u", | ||
206 | ep->bEndpointAddress, buffer_len, interval); | ||
207 | |||
208 | dev = gspca_dev->dev; | ||
209 | |||
210 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
211 | if (!urb) { | ||
212 | ret = -ENOMEM; | ||
213 | goto error; | ||
214 | } | ||
215 | |||
216 | buffer = usb_buffer_alloc(dev, ep->wMaxPacketSize, | ||
217 | GFP_KERNEL, &urb->transfer_dma); | ||
218 | if (!buffer) { | ||
219 | ret = -ENOMEM; | ||
220 | goto error_buffer; | ||
221 | } | ||
222 | usb_fill_int_urb(urb, dev, | ||
223 | usb_rcvintpipe(dev, ep->bEndpointAddress), | ||
224 | buffer, buffer_len, | ||
225 | int_irq, (void *)gspca_dev, interval); | ||
226 | gspca_dev->int_urb = urb; | ||
227 | ret = usb_submit_urb(urb, GFP_KERNEL); | ||
228 | if (ret < 0) { | ||
229 | PDEBUG(D_ERR, "submit URB failed with error %i", ret); | ||
230 | goto error_submit; | ||
231 | } | ||
232 | return ret; | ||
233 | |||
234 | error_submit: | ||
235 | usb_buffer_free(dev, | ||
236 | urb->transfer_buffer_length, | ||
237 | urb->transfer_buffer, | ||
238 | urb->transfer_dma); | ||
239 | error_buffer: | ||
240 | usb_free_urb(urb); | ||
241 | error: | ||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | static void gspca_input_create_urb(struct gspca_dev *gspca_dev) | ||
246 | { | ||
247 | struct usb_interface *intf; | ||
248 | struct usb_host_interface *intf_desc; | ||
249 | struct usb_endpoint_descriptor *ep; | ||
250 | int i; | ||
251 | |||
252 | if (gspca_dev->sd_desc->int_pkt_scan) { | ||
253 | intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface); | ||
254 | intf_desc = intf->cur_altsetting; | ||
255 | for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) { | ||
256 | ep = &intf_desc->endpoint[i].desc; | ||
257 | if (usb_endpoint_dir_in(ep) && | ||
258 | usb_endpoint_xfer_int(ep)) { | ||
259 | |||
260 | alloc_and_submit_int_urb(gspca_dev, ep); | ||
261 | break; | ||
262 | } | ||
263 | } | ||
264 | } | ||
265 | } | ||
266 | |||
267 | static void gspca_input_destroy_urb(struct gspca_dev *gspca_dev) | ||
268 | { | ||
269 | struct urb *urb; | ||
270 | |||
271 | urb = gspca_dev->int_urb; | ||
272 | if (urb) { | ||
273 | gspca_dev->int_urb = NULL; | ||
274 | usb_kill_urb(urb); | ||
275 | usb_buffer_free(gspca_dev->dev, | ||
276 | urb->transfer_buffer_length, | ||
277 | urb->transfer_buffer, | ||
278 | urb->transfer_dma); | ||
279 | usb_free_urb(urb); | ||
280 | } | ||
281 | } | ||
282 | #else | ||
283 | #define gspca_input_connect(gspca_dev) 0 | ||
284 | #define gspca_input_create_urb(gspca_dev) | ||
285 | #define gspca_input_destroy_urb(gspca_dev) | ||
286 | #endif | ||
287 | |||
107 | /* get the current input frame buffer */ | 288 | /* get the current input frame buffer */ |
108 | struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev) | 289 | struct gspca_frame *gspca_get_i_frame(struct gspca_dev *gspca_dev) |
109 | { | 290 | { |
110 | struct gspca_frame *frame; | 291 | struct gspca_frame *frame; |
111 | int i; | ||
112 | 292 | ||
113 | i = gspca_dev->fr_i; | 293 | frame = gspca_dev->cur_frame; |
114 | i = gspca_dev->fr_queue[i]; | ||
115 | frame = &gspca_dev->frame[i]; | ||
116 | if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS) | 294 | if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS) |
117 | != V4L2_BUF_FLAG_QUEUED) | 295 | != V4L2_BUF_FLAG_QUEUED) |
118 | return NULL; | 296 | return NULL; |
@@ -486,11 +664,13 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev) | |||
486 | i, ep->desc.bEndpointAddress); | 664 | i, ep->desc.bEndpointAddress); |
487 | gspca_dev->alt = i; /* memorize the current alt setting */ | 665 | gspca_dev->alt = i; /* memorize the current alt setting */ |
488 | if (gspca_dev->nbalt > 1) { | 666 | if (gspca_dev->nbalt > 1) { |
667 | gspca_input_destroy_urb(gspca_dev); | ||
489 | ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i); | 668 | ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i); |
490 | if (ret < 0) { | 669 | if (ret < 0) { |
491 | err("set alt %d err %d", i, ret); | 670 | err("set alt %d err %d", i, ret); |
492 | return NULL; | 671 | ep = NULL; |
493 | } | 672 | } |
673 | gspca_input_create_urb(gspca_dev); | ||
494 | } | 674 | } |
495 | return ep; | 675 | return ep; |
496 | } | 676 | } |
@@ -534,26 +714,22 @@ static int create_urbs(struct gspca_dev *gspca_dev, | |||
534 | nurbs = 1; | 714 | nurbs = 1; |
535 | } | 715 | } |
536 | 716 | ||
537 | gspca_dev->nurbs = nurbs; | ||
538 | for (n = 0; n < nurbs; n++) { | 717 | for (n = 0; n < nurbs; n++) { |
539 | urb = usb_alloc_urb(npkt, GFP_KERNEL); | 718 | urb = usb_alloc_urb(npkt, GFP_KERNEL); |
540 | if (!urb) { | 719 | if (!urb) { |
541 | err("usb_alloc_urb failed"); | 720 | err("usb_alloc_urb failed"); |
542 | destroy_urbs(gspca_dev); | ||
543 | return -ENOMEM; | 721 | return -ENOMEM; |
544 | } | 722 | } |
723 | gspca_dev->urb[n] = urb; | ||
545 | urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev, | 724 | urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev, |
546 | bsize, | 725 | bsize, |
547 | GFP_KERNEL, | 726 | GFP_KERNEL, |
548 | &urb->transfer_dma); | 727 | &urb->transfer_dma); |
549 | 728 | ||
550 | if (urb->transfer_buffer == NULL) { | 729 | if (urb->transfer_buffer == NULL) { |
551 | usb_free_urb(urb); | 730 | err("usb_buffer_alloc failed"); |
552 | err("usb_buffer_urb failed"); | ||
553 | destroy_urbs(gspca_dev); | ||
554 | return -ENOMEM; | 731 | return -ENOMEM; |
555 | } | 732 | } |
556 | gspca_dev->urb[n] = urb; | ||
557 | urb->dev = gspca_dev->dev; | 733 | urb->dev = gspca_dev->dev; |
558 | urb->context = gspca_dev; | 734 | urb->context = gspca_dev; |
559 | urb->transfer_buffer_length = bsize; | 735 | urb->transfer_buffer_length = bsize; |
@@ -585,6 +761,7 @@ static int create_urbs(struct gspca_dev *gspca_dev, | |||
585 | static int gspca_init_transfer(struct gspca_dev *gspca_dev) | 761 | static int gspca_init_transfer(struct gspca_dev *gspca_dev) |
586 | { | 762 | { |
587 | struct usb_host_endpoint *ep; | 763 | struct usb_host_endpoint *ep; |
764 | struct urb *urb; | ||
588 | int n, ret; | 765 | int n, ret; |
589 | 766 | ||
590 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | 767 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) |
@@ -595,6 +772,8 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
595 | goto out; | 772 | goto out; |
596 | } | 773 | } |
597 | 774 | ||
775 | gspca_dev->usb_err = 0; | ||
776 | |||
598 | /* set the higher alternate setting and | 777 | /* set the higher alternate setting and |
599 | * loop until urb submit succeeds */ | 778 | * loop until urb submit succeeds */ |
600 | if (gspca_dev->cam.reverse_alts) | 779 | if (gspca_dev->cam.reverse_alts) |
@@ -613,10 +792,15 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
613 | goto out; | 792 | goto out; |
614 | } | 793 | } |
615 | for (;;) { | 794 | for (;;) { |
616 | PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt); | 795 | if (!gspca_dev->cam.no_urb_create) { |
617 | ret = create_urbs(gspca_dev, ep); | 796 | PDEBUG(D_STREAM, "init transfer alt %d", |
618 | if (ret < 0) | 797 | gspca_dev->alt); |
619 | goto out; | 798 | ret = create_urbs(gspca_dev, ep); |
799 | if (ret < 0) { | ||
800 | destroy_urbs(gspca_dev); | ||
801 | goto out; | ||
802 | } | ||
803 | } | ||
620 | 804 | ||
621 | /* clear the bulk endpoint */ | 805 | /* clear the bulk endpoint */ |
622 | if (gspca_dev->cam.bulk) | 806 | if (gspca_dev->cam.bulk) |
@@ -636,8 +820,11 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
636 | break; | 820 | break; |
637 | 821 | ||
638 | /* submit the URBs */ | 822 | /* submit the URBs */ |
639 | for (n = 0; n < gspca_dev->nurbs; n++) { | 823 | for (n = 0; n < MAX_NURBS; n++) { |
640 | ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL); | 824 | urb = gspca_dev->urb[n]; |
825 | if (urb == NULL) | ||
826 | break; | ||
827 | ret = usb_submit_urb(urb, GFP_KERNEL); | ||
641 | if (ret < 0) | 828 | if (ret < 0) |
642 | break; | 829 | break; |
643 | } | 830 | } |
@@ -694,7 +881,9 @@ static void gspca_stream_off(struct gspca_dev *gspca_dev) | |||
694 | if (gspca_dev->sd_desc->stopN) | 881 | if (gspca_dev->sd_desc->stopN) |
695 | gspca_dev->sd_desc->stopN(gspca_dev); | 882 | gspca_dev->sd_desc->stopN(gspca_dev); |
696 | destroy_urbs(gspca_dev); | 883 | destroy_urbs(gspca_dev); |
884 | gspca_input_destroy_urb(gspca_dev); | ||
697 | gspca_set_alt0(gspca_dev); | 885 | gspca_set_alt0(gspca_dev); |
886 | gspca_input_create_urb(gspca_dev); | ||
698 | } | 887 | } |
699 | 888 | ||
700 | /* always call stop0 to free the subdriver's resources */ | 889 | /* always call stop0 to free the subdriver's resources */ |
@@ -2060,11 +2249,12 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
2060 | PDEBUG(D_ERR, "Too many config"); | 2249 | PDEBUG(D_ERR, "Too many config"); |
2061 | return -ENODEV; | 2250 | return -ENODEV; |
2062 | } | 2251 | } |
2252 | |||
2253 | /* the USB video interface must be the first one */ | ||
2063 | interface = &intf->cur_altsetting->desc; | 2254 | interface = &intf->cur_altsetting->desc; |
2064 | if (interface->bInterfaceNumber > 0) { | 2255 | if (dev->config->desc.bNumInterfaces != 1 && |
2065 | PDEBUG(D_ERR, "intf != 0"); | 2256 | interface->bInterfaceNumber != 0) |
2066 | return -ENODEV; | 2257 | return -ENODEV; |
2067 | } | ||
2068 | 2258 | ||
2069 | /* create the device */ | 2259 | /* create the device */ |
2070 | if (dev_size < sizeof *gspca_dev) | 2260 | if (dev_size < sizeof *gspca_dev) |
@@ -2096,6 +2286,10 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
2096 | goto out; | 2286 | goto out; |
2097 | gspca_set_default_mode(gspca_dev); | 2287 | gspca_set_default_mode(gspca_dev); |
2098 | 2288 | ||
2289 | ret = gspca_input_connect(gspca_dev); | ||
2290 | if (ret) | ||
2291 | goto out; | ||
2292 | |||
2099 | mutex_init(&gspca_dev->usb_lock); | 2293 | mutex_init(&gspca_dev->usb_lock); |
2100 | mutex_init(&gspca_dev->read_lock); | 2294 | mutex_init(&gspca_dev->read_lock); |
2101 | mutex_init(&gspca_dev->queue_lock); | 2295 | mutex_init(&gspca_dev->queue_lock); |
@@ -2116,8 +2310,15 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
2116 | 2310 | ||
2117 | usb_set_intfdata(intf, gspca_dev); | 2311 | usb_set_intfdata(intf, gspca_dev); |
2118 | PDEBUG(D_PROBE, "%s created", video_device_node_name(&gspca_dev->vdev)); | 2312 | PDEBUG(D_PROBE, "%s created", video_device_node_name(&gspca_dev->vdev)); |
2313 | |||
2314 | gspca_input_create_urb(gspca_dev); | ||
2315 | |||
2119 | return 0; | 2316 | return 0; |
2120 | out: | 2317 | out: |
2318 | #ifdef CONFIG_INPUT | ||
2319 | if (gspca_dev->input_dev) | ||
2320 | input_unregister_device(gspca_dev->input_dev); | ||
2321 | #endif | ||
2121 | kfree(gspca_dev->usb_buf); | 2322 | kfree(gspca_dev->usb_buf); |
2122 | kfree(gspca_dev); | 2323 | kfree(gspca_dev); |
2123 | return ret; | 2324 | return ret; |
@@ -2133,6 +2334,9 @@ EXPORT_SYMBOL(gspca_dev_probe); | |||
2133 | void gspca_disconnect(struct usb_interface *intf) | 2334 | void gspca_disconnect(struct usb_interface *intf) |
2134 | { | 2335 | { |
2135 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); | 2336 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); |
2337 | #ifdef CONFIG_INPUT | ||
2338 | struct input_dev *input_dev; | ||
2339 | #endif | ||
2136 | 2340 | ||
2137 | PDEBUG(D_PROBE, "%s disconnect", | 2341 | PDEBUG(D_PROBE, "%s disconnect", |
2138 | video_device_node_name(&gspca_dev->vdev)); | 2342 | video_device_node_name(&gspca_dev->vdev)); |
@@ -2144,6 +2348,15 @@ void gspca_disconnect(struct usb_interface *intf) | |||
2144 | wake_up_interruptible(&gspca_dev->wq); | 2348 | wake_up_interruptible(&gspca_dev->wq); |
2145 | } | 2349 | } |
2146 | 2350 | ||
2351 | #ifdef CONFIG_INPUT | ||
2352 | gspca_input_destroy_urb(gspca_dev); | ||
2353 | input_dev = gspca_dev->input_dev; | ||
2354 | if (input_dev) { | ||
2355 | gspca_dev->input_dev = NULL; | ||
2356 | input_unregister_device(input_dev); | ||
2357 | } | ||
2358 | #endif | ||
2359 | |||
2147 | /* the device is freed at exit of this function */ | 2360 | /* the device is freed at exit of this function */ |
2148 | gspca_dev->dev = NULL; | 2361 | gspca_dev->dev = NULL; |
2149 | mutex_unlock(&gspca_dev->usb_lock); | 2362 | mutex_unlock(&gspca_dev->usb_lock); |
@@ -2169,6 +2382,7 @@ int gspca_suspend(struct usb_interface *intf, pm_message_t message) | |||
2169 | if (gspca_dev->sd_desc->stopN) | 2382 | if (gspca_dev->sd_desc->stopN) |
2170 | gspca_dev->sd_desc->stopN(gspca_dev); | 2383 | gspca_dev->sd_desc->stopN(gspca_dev); |
2171 | destroy_urbs(gspca_dev); | 2384 | destroy_urbs(gspca_dev); |
2385 | gspca_input_destroy_urb(gspca_dev); | ||
2172 | gspca_set_alt0(gspca_dev); | 2386 | gspca_set_alt0(gspca_dev); |
2173 | if (gspca_dev->sd_desc->stop0) | 2387 | if (gspca_dev->sd_desc->stop0) |
2174 | gspca_dev->sd_desc->stop0(gspca_dev); | 2388 | gspca_dev->sd_desc->stop0(gspca_dev); |
@@ -2182,6 +2396,7 @@ int gspca_resume(struct usb_interface *intf) | |||
2182 | 2396 | ||
2183 | gspca_dev->frozen = 0; | 2397 | gspca_dev->frozen = 0; |
2184 | gspca_dev->sd_desc->init(gspca_dev); | 2398 | gspca_dev->sd_desc->init(gspca_dev); |
2399 | gspca_input_create_urb(gspca_dev); | ||
2185 | if (gspca_dev->streaming) | 2400 | if (gspca_dev->streaming) |
2186 | return gspca_init_transfer(gspca_dev); | 2401 | return gspca_init_transfer(gspca_dev); |
2187 | return 0; | 2402 | return 0; |
@@ -2205,6 +2420,8 @@ int gspca_auto_gain_n_exposure(struct gspca_dev *gspca_dev, int avg_lum, | |||
2205 | int retval = 0; | 2420 | int retval = 0; |
2206 | 2421 | ||
2207 | for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) { | 2422 | for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) { |
2423 | if (gspca_dev->ctrl_dis & (1 << i)) | ||
2424 | continue; | ||
2208 | if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_GAIN) | 2425 | if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_GAIN) |
2209 | gain_ctrl = &gspca_dev->sd_desc->ctrls[i]; | 2426 | gain_ctrl = &gspca_dev->sd_desc->ctrls[i]; |
2210 | if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_EXPOSURE) | 2427 | if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_EXPOSURE) |
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 59c7941da999..02c696a22be0 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h | |||
@@ -48,26 +48,27 @@ extern int gspca_debug; | |||
48 | 48 | ||
49 | /* used to list framerates supported by a camera mode (resolution) */ | 49 | /* used to list framerates supported by a camera mode (resolution) */ |
50 | struct framerates { | 50 | struct framerates { |
51 | int *rates; | 51 | const u8 *rates; |
52 | int nrates; | 52 | int nrates; |
53 | }; | 53 | }; |
54 | 54 | ||
55 | /* device information - set at probe time */ | 55 | /* device information - set at probe time */ |
56 | struct cam { | 56 | struct cam { |
57 | int bulk_size; /* buffer size when image transfer by bulk */ | ||
58 | const struct v4l2_pix_format *cam_mode; /* size nmodes */ | 57 | const struct v4l2_pix_format *cam_mode; /* size nmodes */ |
59 | char nmodes; | ||
60 | const struct framerates *mode_framerates; /* must have size nmode, | 58 | const struct framerates *mode_framerates; /* must have size nmode, |
61 | * just like cam_mode */ | 59 | * just like cam_mode */ |
62 | __u8 bulk_nurbs; /* number of URBs in bulk mode | 60 | u32 bulk_size; /* buffer size when image transfer by bulk */ |
61 | u32 input_flags; /* value for ENUM_INPUT status flags */ | ||
62 | u8 nmodes; /* size of cam_mode */ | ||
63 | u8 no_urb_create; /* don't create transfer URBs */ | ||
64 | u8 bulk_nurbs; /* number of URBs in bulk mode | ||
63 | * - cannot be > MAX_NURBS | 65 | * - cannot be > MAX_NURBS |
64 | * - when 0 and bulk_size != 0 means | 66 | * - when 0 and bulk_size != 0 means |
65 | * 1 URB and submit done by subdriver */ | 67 | * 1 URB and submit done by subdriver */ |
66 | u8 bulk; /* image transfer by 0:isoc / 1:bulk */ | 68 | u8 bulk; /* image transfer by 0:isoc / 1:bulk */ |
67 | u8 npkt; /* number of packets in an ISOC message | 69 | u8 npkt; /* number of packets in an ISOC message |
68 | * 0 is the default value: 32 packets */ | 70 | * 0 is the default value: 32 packets */ |
69 | u32 input_flags; /* value for ENUM_INPUT status flags */ | 71 | u8 reverse_alts; /* Alt settings are in high to low order */ |
70 | char reverse_alts; /* Alt settings are in high to low order */ | ||
71 | }; | 72 | }; |
72 | 73 | ||
73 | struct gspca_dev; | 74 | struct gspca_dev; |
@@ -90,6 +91,9 @@ typedef int (*cam_qmnu_op) (struct gspca_dev *, | |||
90 | typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev, | 91 | typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev, |
91 | u8 *data, | 92 | u8 *data, |
92 | int len); | 93 | int len); |
94 | typedef int (*cam_int_pkt_op) (struct gspca_dev *gspca_dev, | ||
95 | u8 *data, | ||
96 | int len); | ||
93 | 97 | ||
94 | struct ctrl { | 98 | struct ctrl { |
95 | struct v4l2_queryctrl qctrl; | 99 | struct v4l2_queryctrl qctrl; |
@@ -125,6 +129,12 @@ struct sd_desc { | |||
125 | cam_reg_op get_register; | 129 | cam_reg_op get_register; |
126 | #endif | 130 | #endif |
127 | cam_ident_op get_chip_ident; | 131 | cam_ident_op get_chip_ident; |
132 | #ifdef CONFIG_INPUT | ||
133 | cam_int_pkt_op int_pkt_scan; | ||
134 | /* other_input makes the gspca core create gspca_dev->input even when | ||
135 | int_pkt_scan is NULL, for cams with non interrupt driven buttons */ | ||
136 | u8 other_input; | ||
137 | #endif | ||
128 | }; | 138 | }; |
129 | 139 | ||
130 | /* packet types when moving from iso buf to frame buf */ | 140 | /* packet types when moving from iso buf to frame buf */ |
@@ -147,6 +157,10 @@ struct gspca_dev { | |||
147 | struct module *module; /* subdriver handling the device */ | 157 | struct module *module; /* subdriver handling the device */ |
148 | struct usb_device *dev; | 158 | struct usb_device *dev; |
149 | struct file *capt_file; /* file doing video capture */ | 159 | struct file *capt_file; /* file doing video capture */ |
160 | #ifdef CONFIG_INPUT | ||
161 | struct input_dev *input_dev; | ||
162 | char phys[64]; /* physical device path */ | ||
163 | #endif | ||
150 | 164 | ||
151 | struct cam cam; /* device information */ | 165 | struct cam cam; /* device information */ |
152 | const struct sd_desc *sd_desc; /* subdriver description */ | 166 | const struct sd_desc *sd_desc; /* subdriver description */ |
@@ -156,6 +170,9 @@ struct gspca_dev { | |||
156 | #define USB_BUF_SZ 64 | 170 | #define USB_BUF_SZ 64 |
157 | __u8 *usb_buf; /* buffer for USB exchanges */ | 171 | __u8 *usb_buf; /* buffer for USB exchanges */ |
158 | struct urb *urb[MAX_NURBS]; | 172 | struct urb *urb[MAX_NURBS]; |
173 | #ifdef CONFIG_INPUT | ||
174 | struct urb *int_urb; | ||
175 | #endif | ||
159 | 176 | ||
160 | __u8 *frbuf; /* buffer for nframes */ | 177 | __u8 *frbuf; /* buffer for nframes */ |
161 | struct gspca_frame frame[GSPCA_MAX_FRAMES]; | 178 | struct gspca_frame frame[GSPCA_MAX_FRAMES]; |
@@ -187,7 +204,6 @@ struct gspca_dev { | |||
187 | char users; /* number of opens */ | 204 | char users; /* number of opens */ |
188 | char present; /* device connected */ | 205 | char present; /* device connected */ |
189 | char nbufread; /* number of buffers for read() */ | 206 | char nbufread; /* number of buffers for read() */ |
190 | char nurbs; /* number of allocated URBs */ | ||
191 | char memory; /* memory type (V4L2_MEMORY_xxx) */ | 207 | char memory; /* memory type (V4L2_MEMORY_xxx) */ |
192 | __u8 iface; /* USB interface number */ | 208 | __u8 iface; /* USB interface number */ |
193 | __u8 alt; /* USB alternate setting */ | 209 | __u8 alt; /* USB alternate setting */ |
diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/drivers/media/video/gspca/m5602/m5602_mt9m111.c index 8d071dff6944..c0722fa64606 100644 --- a/drivers/media/video/gspca/m5602/m5602_mt9m111.c +++ b/drivers/media/video/gspca/m5602/m5602_mt9m111.c | |||
@@ -48,7 +48,7 @@ static struct v4l2_pix_format mt9m111_modes[] = { | |||
48 | } | 48 | } |
49 | }; | 49 | }; |
50 | 50 | ||
51 | const static struct ctrl mt9m111_ctrls[] = { | 51 | static const struct ctrl mt9m111_ctrls[] = { |
52 | #define VFLIP_IDX 0 | 52 | #define VFLIP_IDX 0 |
53 | { | 53 | { |
54 | { | 54 | { |
@@ -171,7 +171,7 @@ int mt9m111_probe(struct sd *sd) | |||
171 | return -ENODEV; | 171 | return -ENODEV; |
172 | } | 172 | } |
173 | 173 | ||
174 | info("Probing for a mt9m111 sensor"); | 174 | PDEBUG(D_PROBE, "Probing for a mt9m111 sensor"); |
175 | 175 | ||
176 | /* Do the preinit */ | 176 | /* Do the preinit */ |
177 | for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) { | 177 | for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) { |
diff --git a/drivers/media/video/gspca/m5602/m5602_ov7660.c b/drivers/media/video/gspca/m5602/m5602_ov7660.c index 2a28b74cb3f9..62c1cbf06666 100644 --- a/drivers/media/video/gspca/m5602/m5602_ov7660.c +++ b/drivers/media/video/gspca/m5602/m5602_ov7660.c | |||
@@ -33,7 +33,7 @@ static int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val); | |||
33 | static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); | 33 | static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val); |
34 | static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val); | 34 | static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val); |
35 | 35 | ||
36 | const static struct ctrl ov7660_ctrls[] = { | 36 | static const struct ctrl ov7660_ctrls[] = { |
37 | #define GAIN_IDX 1 | 37 | #define GAIN_IDX 1 |
38 | { | 38 | { |
39 | { | 39 | { |
diff --git a/drivers/media/video/gspca/m5602/m5602_ov7660.h b/drivers/media/video/gspca/m5602/m5602_ov7660.h index f5588ebe667c..4d9dcf29da2e 100644 --- a/drivers/media/video/gspca/m5602/m5602_ov7660.h +++ b/drivers/media/video/gspca/m5602/m5602_ov7660.h | |||
@@ -94,7 +94,7 @@ int ov7660_start(struct sd *sd); | |||
94 | int ov7660_stop(struct sd *sd); | 94 | int ov7660_stop(struct sd *sd); |
95 | void ov7660_disconnect(struct sd *sd); | 95 | void ov7660_disconnect(struct sd *sd); |
96 | 96 | ||
97 | const static struct m5602_sensor ov7660 = { | 97 | static const struct m5602_sensor ov7660 = { |
98 | .name = "ov7660", | 98 | .name = "ov7660", |
99 | .i2c_slave_id = 0x42, | 99 | .i2c_slave_id = 0x42, |
100 | .i2c_regW = 1, | 100 | .i2c_regW = 1, |
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c index 923cdd5f7a6b..069ba0044f8b 100644 --- a/drivers/media/video/gspca/m5602/m5602_ov9650.c +++ b/drivers/media/video/gspca/m5602/m5602_ov9650.c | |||
@@ -307,7 +307,7 @@ int ov9650_probe(struct sd *sd) | |||
307 | return -ENODEV; | 307 | return -ENODEV; |
308 | } | 308 | } |
309 | 309 | ||
310 | info("Probing for an ov9650 sensor"); | 310 | PDEBUG(D_PROBE, "Probing for an ov9650 sensor"); |
311 | 311 | ||
312 | /* Run the pre-init before probing the sensor */ | 312 | /* Run the pre-init before probing the sensor */ |
313 | for (i = 0; i < ARRAY_SIZE(preinit_ov9650) && !err; i++) { | 313 | for (i = 0; i < ARRAY_SIZE(preinit_ov9650) && !err; i++) { |
diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.c b/drivers/media/video/gspca/m5602/m5602_po1030.c index 8d74d8065b79..925b87d66f40 100644 --- a/drivers/media/video/gspca/m5602/m5602_po1030.c +++ b/drivers/media/video/gspca/m5602/m5602_po1030.c | |||
@@ -205,7 +205,7 @@ int po1030_probe(struct sd *sd) | |||
205 | return -ENODEV; | 205 | return -ENODEV; |
206 | } | 206 | } |
207 | 207 | ||
208 | info("Probing for a po1030 sensor"); | 208 | PDEBUG(D_PROBE, "Probing for a po1030 sensor"); |
209 | 209 | ||
210 | /* Run the pre-init to actually probe the unit */ | 210 | /* Run the pre-init to actually probe the unit */ |
211 | for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) { | 211 | for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) { |
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index 1b536f7d30cf..da0a38c78708 100644 --- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c | |||
@@ -248,7 +248,7 @@ int s5k4aa_probe(struct sd *sd) | |||
248 | return -ENODEV; | 248 | return -ENODEV; |
249 | } | 249 | } |
250 | 250 | ||
251 | info("Probing for a s5k4aa sensor"); | 251 | PDEBUG(D_PROBE, "Probing for a s5k4aa sensor"); |
252 | 252 | ||
253 | /* Preinit the sensor */ | 253 | /* Preinit the sensor */ |
254 | for (i = 0; i < ARRAY_SIZE(preinit_s5k4aa) && !err; i++) { | 254 | for (i = 0; i < ARRAY_SIZE(preinit_s5k4aa) && !err; i++) { |
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/drivers/media/video/gspca/m5602/m5602_s5k83a.c index 6b89f33a4ce0..fbd91545497a 100644 --- a/drivers/media/video/gspca/m5602/m5602_s5k83a.c +++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.c | |||
@@ -143,7 +143,7 @@ int s5k83a_probe(struct sd *sd) | |||
143 | return -ENODEV; | 143 | return -ENODEV; |
144 | } | 144 | } |
145 | 145 | ||
146 | info("Probing for a s5k83a sensor"); | 146 | PDEBUG(D_PROBE, "Probing for a s5k83a sensor"); |
147 | 147 | ||
148 | /* Preinit the sensor */ | 148 | /* Preinit the sensor */ |
149 | for (i = 0; i < ARRAY_SIZE(preinit_s5k83a) && !err; i++) { | 149 | for (i = 0; i < ARRAY_SIZE(preinit_s5k83a) && !err; i++) { |
diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c index 9cf8d68c71bf..3d9229e22b25 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/video/gspca/mars.c | |||
@@ -54,7 +54,7 @@ static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val); | |||
54 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); | 54 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); |
55 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | 55 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); |
56 | 56 | ||
57 | static struct ctrl sd_ctrls[] = { | 57 | static const struct ctrl sd_ctrls[] = { |
58 | { | 58 | { |
59 | { | 59 | { |
60 | .id = V4L2_CID_BRIGHTNESS, | 60 | .id = V4L2_CID_BRIGHTNESS, |
diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index 9154870e07d2..33744e724eaa 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c | |||
@@ -57,6 +57,14 @@ | |||
57 | #define MR97310A_GAIN_MAX 31 | 57 | #define MR97310A_GAIN_MAX 31 |
58 | #define MR97310A_GAIN_DEFAULT 25 | 58 | #define MR97310A_GAIN_DEFAULT 25 |
59 | 59 | ||
60 | #define MR97310A_CONTRAST_MIN 0 | ||
61 | #define MR97310A_CONTRAST_MAX 31 | ||
62 | #define MR97310A_CONTRAST_DEFAULT 23 | ||
63 | |||
64 | #define MR97310A_CS_GAIN_MIN 0 | ||
65 | #define MR97310A_CS_GAIN_MAX 0x7ff | ||
66 | #define MR97310A_CS_GAIN_DEFAULT 0x110 | ||
67 | |||
60 | #define MR97310A_MIN_CLOCKDIV_MIN 3 | 68 | #define MR97310A_MIN_CLOCKDIV_MIN 3 |
61 | #define MR97310A_MIN_CLOCKDIV_MAX 8 | 69 | #define MR97310A_MIN_CLOCKDIV_MAX 8 |
62 | #define MR97310A_MIN_CLOCKDIV_DEFAULT 3 | 70 | #define MR97310A_MIN_CLOCKDIV_DEFAULT 3 |
@@ -82,7 +90,8 @@ struct sd { | |||
82 | 90 | ||
83 | int brightness; | 91 | int brightness; |
84 | u16 exposure; | 92 | u16 exposure; |
85 | u8 gain; | 93 | u32 gain; |
94 | u8 contrast; | ||
86 | u8 min_clockdiv; | 95 | u8 min_clockdiv; |
87 | }; | 96 | }; |
88 | 97 | ||
@@ -98,6 +107,8 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | |||
98 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | 107 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); |
99 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | 108 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); |
100 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | 109 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); |
110 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
111 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
101 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); | 112 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); |
102 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | 113 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); |
103 | static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val); | 114 | static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val); |
@@ -105,11 +116,13 @@ static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val); | |||
105 | static void setbrightness(struct gspca_dev *gspca_dev); | 116 | static void setbrightness(struct gspca_dev *gspca_dev); |
106 | static void setexposure(struct gspca_dev *gspca_dev); | 117 | static void setexposure(struct gspca_dev *gspca_dev); |
107 | static void setgain(struct gspca_dev *gspca_dev); | 118 | static void setgain(struct gspca_dev *gspca_dev); |
119 | static void setcontrast(struct gspca_dev *gspca_dev); | ||
108 | 120 | ||
109 | /* V4L2 controls supported by the driver */ | 121 | /* V4L2 controls supported by the driver */ |
110 | static struct ctrl sd_ctrls[] = { | 122 | static const struct ctrl sd_ctrls[] = { |
111 | /* Separate brightness control description for Argus QuickClix as it has | 123 | /* Separate brightness control description for Argus QuickClix as it has |
112 | different limits from the other mr97310a cameras */ | 124 | * different limits from the other mr97310a cameras, and separate gain |
125 | * control for Sakar CyberPix camera. */ | ||
113 | { | 126 | { |
114 | #define NORM_BRIGHTNESS_IDX 0 | 127 | #define NORM_BRIGHTNESS_IDX 0 |
115 | { | 128 | { |
@@ -171,7 +184,37 @@ static struct ctrl sd_ctrls[] = { | |||
171 | .get = sd_getgain, | 184 | .get = sd_getgain, |
172 | }, | 185 | }, |
173 | { | 186 | { |
174 | #define MIN_CLOCKDIV_IDX 4 | 187 | #define SAKAR_CS_GAIN_IDX 4 |
188 | { | ||
189 | .id = V4L2_CID_GAIN, | ||
190 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
191 | .name = "Gain", | ||
192 | .minimum = MR97310A_CS_GAIN_MIN, | ||
193 | .maximum = MR97310A_CS_GAIN_MAX, | ||
194 | .step = 1, | ||
195 | .default_value = MR97310A_CS_GAIN_DEFAULT, | ||
196 | .flags = 0, | ||
197 | }, | ||
198 | .set = sd_setgain, | ||
199 | .get = sd_getgain, | ||
200 | }, | ||
201 | { | ||
202 | #define CONTRAST_IDX 5 | ||
203 | { | ||
204 | .id = V4L2_CID_CONTRAST, | ||
205 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
206 | .name = "Contrast", | ||
207 | .minimum = MR97310A_CONTRAST_MIN, | ||
208 | .maximum = MR97310A_CONTRAST_MAX, | ||
209 | .step = 1, | ||
210 | .default_value = MR97310A_CONTRAST_DEFAULT, | ||
211 | .flags = 0, | ||
212 | }, | ||
213 | .set = sd_setcontrast, | ||
214 | .get = sd_getcontrast, | ||
215 | }, | ||
216 | { | ||
217 | #define MIN_CLOCKDIV_IDX 6 | ||
175 | { | 218 | { |
176 | .id = V4L2_CID_PRIVATE_BASE, | 219 | .id = V4L2_CID_PRIVATE_BASE, |
177 | .type = V4L2_CTRL_TYPE_INTEGER, | 220 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -327,7 +370,6 @@ static int zero_the_pointer(struct gspca_dev *gspca_dev) | |||
327 | if (err_code < 0) | 370 | if (err_code < 0) |
328 | return err_code; | 371 | return err_code; |
329 | 372 | ||
330 | err_code = mr_write(gspca_dev, 1); | ||
331 | data[0] = 0x19; | 373 | data[0] = 0x19; |
332 | data[1] = 0x51; | 374 | data[1] = 0x51; |
333 | err_code = mr_write(gspca_dev, 2); | 375 | err_code = mr_write(gspca_dev, 2); |
@@ -437,6 +479,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
437 | { | 479 | { |
438 | struct sd *sd = (struct sd *) gspca_dev; | 480 | struct sd *sd = (struct sd *) gspca_dev; |
439 | struct cam *cam; | 481 | struct cam *cam; |
482 | int gain_default = MR97310A_GAIN_DEFAULT; | ||
440 | int err_code; | 483 | int err_code; |
441 | 484 | ||
442 | cam = &gspca_dev->cam; | 485 | cam = &gspca_dev->cam; |
@@ -460,12 +503,14 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
460 | if (err_code < 0) | 503 | if (err_code < 0) |
461 | return err_code; | 504 | return err_code; |
462 | 505 | ||
506 | /* Now, the query for sensor type. */ | ||
507 | err_code = cam_get_response16(gspca_dev, 0x07, 1); | ||
508 | if (err_code < 0) | ||
509 | return err_code; | ||
510 | |||
463 | if (id->idProduct == 0x0110 || id->idProduct == 0x010e) { | 511 | if (id->idProduct == 0x0110 || id->idProduct == 0x010e) { |
464 | sd->cam_type = CAM_TYPE_CIF; | 512 | sd->cam_type = CAM_TYPE_CIF; |
465 | cam->nmodes--; | 513 | cam->nmodes--; |
466 | err_code = cam_get_response16(gspca_dev, 0x06, 1); | ||
467 | if (err_code < 0) | ||
468 | return err_code; | ||
469 | /* | 514 | /* |
470 | * All but one of the known CIF cameras share the same USB ID, | 515 | * All but one of the known CIF cameras share the same USB ID, |
471 | * but two different init routines are in use, and the control | 516 | * but two different init routines are in use, and the control |
@@ -473,12 +518,12 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
473 | * of the two known varieties is connected! | 518 | * of the two known varieties is connected! |
474 | * | 519 | * |
475 | * A list of known CIF cameras follows. They all report either | 520 | * A list of known CIF cameras follows. They all report either |
476 | * 0002 for type 0 or 0003 for type 1. | 521 | * 0200 for type 0 or 0300 for type 1. |
477 | * If you have another to report, please do | 522 | * If you have another to report, please do |
478 | * | 523 | * |
479 | * Name sd->sensor_type reported by | 524 | * Name sd->sensor_type reported by |
480 | * | 525 | * |
481 | * Sakar Spy-shot 0 T. Kilgore | 526 | * Sakar 56379 Spy-shot 0 T. Kilgore |
482 | * Innovage 0 T. Kilgore | 527 | * Innovage 0 T. Kilgore |
483 | * Vivitar Mini 0 H. De Goede | 528 | * Vivitar Mini 0 H. De Goede |
484 | * Vivitar Mini 0 E. Rodriguez | 529 | * Vivitar Mini 0 E. Rodriguez |
@@ -487,7 +532,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
487 | * Philips dig. keych. 1 T. Kilgore | 532 | * Philips dig. keych. 1 T. Kilgore |
488 | * Trust Spyc@m 100 1 A. Jacobs | 533 | * Trust Spyc@m 100 1 A. Jacobs |
489 | */ | 534 | */ |
490 | switch (gspca_dev->usb_buf[1]) { | 535 | switch (gspca_dev->usb_buf[0]) { |
491 | case 2: | 536 | case 2: |
492 | sd->sensor_type = 0; | 537 | sd->sensor_type = 0; |
493 | break; | 538 | break; |
@@ -504,20 +549,19 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
504 | } else { | 549 | } else { |
505 | sd->cam_type = CAM_TYPE_VGA; | 550 | sd->cam_type = CAM_TYPE_VGA; |
506 | 551 | ||
507 | err_code = cam_get_response16(gspca_dev, 0x07, 1); | ||
508 | if (err_code < 0) | ||
509 | return err_code; | ||
510 | |||
511 | /* | 552 | /* |
512 | * Here is a table of the responses to the previous command | 553 | * Here is a table of the responses to the query for sensor |
513 | * from the known MR97310A VGA cameras. | 554 | * type, from the known MR97310A VGA cameras. Six different |
555 | * cameras of which five share the same USB ID. | ||
514 | * | 556 | * |
515 | * Name gspca_dev->usb_buf[] sd->sensor_type | 557 | * Name gspca_dev->usb_buf[] sd->sensor_type |
516 | * sd->do_lcd_stop | 558 | * sd->do_lcd_stop |
517 | * Aiptek Pencam VGA+ 0300 0 1 | 559 | * Aiptek Pencam VGA+ 0300 0 1 |
518 | * ION digital 0350 0 1 | 560 | * ION digital 0300 0 1 |
519 | * Argus DC-1620 0450 1 0 | 561 | * Argus DC-1620 0450 1 0 |
520 | * Argus QuickClix 0420 1 1 | 562 | * Argus QuickClix 0420 1 1 |
563 | * Sakar 77379 Digital 0350 0 1 | ||
564 | * Sakar 1638x CyberPix 0120 0 2 | ||
521 | * | 565 | * |
522 | * Based upon these results, we assume default settings | 566 | * Based upon these results, we assume default settings |
523 | * and then correct as necessary, as follows. | 567 | * and then correct as necessary, as follows. |
@@ -527,10 +571,12 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
527 | sd->sensor_type = 1; | 571 | sd->sensor_type = 1; |
528 | sd->do_lcd_stop = 0; | 572 | sd->do_lcd_stop = 0; |
529 | sd->adj_colors = 0; | 573 | sd->adj_colors = 0; |
530 | if ((gspca_dev->usb_buf[0] != 0x03) && | 574 | if (gspca_dev->usb_buf[0] == 0x01) { |
575 | sd->sensor_type = 2; | ||
576 | } else if ((gspca_dev->usb_buf[0] != 0x03) && | ||
531 | (gspca_dev->usb_buf[0] != 0x04)) { | 577 | (gspca_dev->usb_buf[0] != 0x04)) { |
532 | PDEBUG(D_ERR, "Unknown VGA Sensor id Byte 0: %02x", | 578 | PDEBUG(D_ERR, "Unknown VGA Sensor id Byte 0: %02x", |
533 | gspca_dev->usb_buf[1]); | 579 | gspca_dev->usb_buf[0]); |
534 | PDEBUG(D_ERR, "Defaults assumed, may not work"); | 580 | PDEBUG(D_ERR, "Defaults assumed, may not work"); |
535 | PDEBUG(D_ERR, "Please report this"); | 581 | PDEBUG(D_ERR, "Please report this"); |
536 | } | 582 | } |
@@ -560,7 +606,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
560 | PDEBUG(D_PROBE, "MR97310A VGA camera detected, sensor: %d", | 606 | PDEBUG(D_PROBE, "MR97310A VGA camera detected, sensor: %d", |
561 | sd->sensor_type); | 607 | sd->sensor_type); |
562 | } | 608 | } |
563 | /* Stop streaming as we've started it to probe the sensor type. */ | 609 | /* Stop streaming as we've started it only to probe the sensor type. */ |
564 | sd_stopN(gspca_dev); | 610 | sd_stopN(gspca_dev); |
565 | 611 | ||
566 | if (force_sensor_type != -1) { | 612 | if (force_sensor_type != -1) { |
@@ -574,9 +620,13 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
574 | /* No brightness for sensor_type 0 */ | 620 | /* No brightness for sensor_type 0 */ |
575 | if (sd->sensor_type == 0) | 621 | if (sd->sensor_type == 0) |
576 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | | 622 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | |
577 | (1 << ARGUS_QC_BRIGHTNESS_IDX); | 623 | (1 << ARGUS_QC_BRIGHTNESS_IDX) | |
624 | (1 << CONTRAST_IDX) | | ||
625 | (1 << SAKAR_CS_GAIN_IDX); | ||
578 | else | 626 | else |
579 | gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) | | 627 | gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) | |
628 | (1 << CONTRAST_IDX) | | ||
629 | (1 << SAKAR_CS_GAIN_IDX) | | ||
580 | (1 << MIN_CLOCKDIV_IDX); | 630 | (1 << MIN_CLOCKDIV_IDX); |
581 | } else { | 631 | } else { |
582 | /* All controls need to be disabled if VGA sensor_type is 0 */ | 632 | /* All controls need to be disabled if VGA sensor_type is 0 */ |
@@ -585,17 +635,30 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
585 | (1 << ARGUS_QC_BRIGHTNESS_IDX) | | 635 | (1 << ARGUS_QC_BRIGHTNESS_IDX) | |
586 | (1 << EXPOSURE_IDX) | | 636 | (1 << EXPOSURE_IDX) | |
587 | (1 << GAIN_IDX) | | 637 | (1 << GAIN_IDX) | |
638 | (1 << CONTRAST_IDX) | | ||
639 | (1 << SAKAR_CS_GAIN_IDX) | | ||
588 | (1 << MIN_CLOCKDIV_IDX); | 640 | (1 << MIN_CLOCKDIV_IDX); |
589 | else if (sd->do_lcd_stop) | 641 | else if (sd->sensor_type == 2) { |
642 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | | ||
643 | (1 << ARGUS_QC_BRIGHTNESS_IDX) | | ||
644 | (1 << GAIN_IDX) | | ||
645 | (1 << MIN_CLOCKDIV_IDX); | ||
646 | gain_default = MR97310A_CS_GAIN_DEFAULT; | ||
647 | } else if (sd->do_lcd_stop) | ||
590 | /* Argus QuickClix has different brightness limits */ | 648 | /* Argus QuickClix has different brightness limits */ |
591 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX); | 649 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | |
650 | (1 << CONTRAST_IDX) | | ||
651 | (1 << SAKAR_CS_GAIN_IDX); | ||
592 | else | 652 | else |
593 | gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX); | 653 | gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) | |
654 | (1 << CONTRAST_IDX) | | ||
655 | (1 << SAKAR_CS_GAIN_IDX); | ||
594 | } | 656 | } |
595 | 657 | ||
596 | sd->brightness = MR97310A_BRIGHTNESS_DEFAULT; | 658 | sd->brightness = MR97310A_BRIGHTNESS_DEFAULT; |
597 | sd->exposure = MR97310A_EXPOSURE_DEFAULT; | 659 | sd->exposure = MR97310A_EXPOSURE_DEFAULT; |
598 | sd->gain = MR97310A_GAIN_DEFAULT; | 660 | sd->gain = gain_default; |
661 | sd->contrast = MR97310A_CONTRAST_DEFAULT; | ||
599 | sd->min_clockdiv = MR97310A_MIN_CLOCKDIV_DEFAULT; | 662 | sd->min_clockdiv = MR97310A_MIN_CLOCKDIV_DEFAULT; |
600 | 663 | ||
601 | return 0; | 664 | return 0; |
@@ -697,6 +760,12 @@ static int start_cif_cam(struct gspca_dev *gspca_dev) | |||
697 | {0x13, 0x00, {0x01}, 1}, | 760 | {0x13, 0x00, {0x01}, 1}, |
698 | {0, 0, {0}, 0} | 761 | {0, 0, {0}, 0} |
699 | }; | 762 | }; |
763 | /* Without this command the cam won't work with USB-UHCI */ | ||
764 | gspca_dev->usb_buf[0] = 0x0a; | ||
765 | gspca_dev->usb_buf[1] = 0x00; | ||
766 | err_code = mr_write(gspca_dev, 2); | ||
767 | if (err_code < 0) | ||
768 | return err_code; | ||
700 | err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data, | 769 | err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data, |
701 | ARRAY_SIZE(cif_sensor1_init_data)); | 770 | ARRAY_SIZE(cif_sensor1_init_data)); |
702 | } | 771 | } |
@@ -717,6 +786,10 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
717 | data[5] = 0x00; | 786 | data[5] = 0x00; |
718 | data[10] = 0x91; | 787 | data[10] = 0x91; |
719 | } | 788 | } |
789 | if (sd->sensor_type == 2) { | ||
790 | data[5] = 0x00; | ||
791 | data[10] = 0x18; | ||
792 | } | ||
720 | 793 | ||
721 | switch (gspca_dev->width) { | 794 | switch (gspca_dev->width) { |
722 | case 160: | 795 | case 160: |
@@ -731,6 +804,10 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
731 | data[4] = 0x78; /* reg 3, V size/4 */ | 804 | data[4] = 0x78; /* reg 3, V size/4 */ |
732 | data[6] = 0x04; /* reg 5, H start */ | 805 | data[6] = 0x04; /* reg 5, H start */ |
733 | data[8] = 0x03; /* reg 7, V start */ | 806 | data[8] = 0x03; /* reg 7, V start */ |
807 | if (sd->sensor_type == 2) { | ||
808 | data[6] = 2; | ||
809 | data[8] = 1; | ||
810 | } | ||
734 | if (sd->do_lcd_stop) | 811 | if (sd->do_lcd_stop) |
735 | data[8] = 0x04; /* Bayer tile shifted */ | 812 | data[8] = 0x04; /* Bayer tile shifted */ |
736 | break; | 813 | break; |
@@ -753,7 +830,6 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
753 | return err_code; | 830 | return err_code; |
754 | 831 | ||
755 | if (!sd->sensor_type) { | 832 | if (!sd->sensor_type) { |
756 | /* The only known sensor_type 0 cam is the Argus DC-1620 */ | ||
757 | const struct sensor_w_data vga_sensor0_init_data[] = { | 833 | const struct sensor_w_data vga_sensor0_init_data[] = { |
758 | {0x01, 0x00, {0x0c, 0x00, 0x04}, 3}, | 834 | {0x01, 0x00, {0x0c, 0x00, 0x04}, 3}, |
759 | {0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4}, | 835 | {0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4}, |
@@ -764,7 +840,7 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
764 | }; | 840 | }; |
765 | err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data, | 841 | err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data, |
766 | ARRAY_SIZE(vga_sensor0_init_data)); | 842 | ARRAY_SIZE(vga_sensor0_init_data)); |
767 | } else { /* sd->sensor_type = 1 */ | 843 | } else if (sd->sensor_type == 1) { |
768 | const struct sensor_w_data color_adj[] = { | 844 | const struct sensor_w_data color_adj[] = { |
769 | {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00, | 845 | {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00, |
770 | /* adjusted blue, green, red gain correct | 846 | /* adjusted blue, green, red gain correct |
@@ -802,6 +878,48 @@ static int start_vga_cam(struct gspca_dev *gspca_dev) | |||
802 | 878 | ||
803 | err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data, | 879 | err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data, |
804 | ARRAY_SIZE(vga_sensor1_init_data)); | 880 | ARRAY_SIZE(vga_sensor1_init_data)); |
881 | } else { /* sensor type == 2 */ | ||
882 | const struct sensor_w_data vga_sensor2_init_data[] = { | ||
883 | |||
884 | {0x01, 0x00, {0x48}, 1}, | ||
885 | {0x02, 0x00, {0x22}, 1}, | ||
886 | /* Reg 3 msb and 4 is lsb of the exposure setting*/ | ||
887 | {0x05, 0x00, {0x10}, 1}, | ||
888 | {0x06, 0x00, {0x00}, 1}, | ||
889 | {0x07, 0x00, {0x00}, 1}, | ||
890 | {0x08, 0x00, {0x00}, 1}, | ||
891 | {0x09, 0x00, {0x00}, 1}, | ||
892 | /* The following are used in the gain control | ||
893 | * which is BTW completely borked in the OEM driver | ||
894 | * The values for each color go from 0 to 0x7ff | ||
895 | *{0x0a, 0x00, {0x01}, 1}, green1 gain msb | ||
896 | *{0x0b, 0x00, {0x10}, 1}, green1 gain lsb | ||
897 | *{0x0c, 0x00, {0x01}, 1}, red gain msb | ||
898 | *{0x0d, 0x00, {0x10}, 1}, red gain lsb | ||
899 | *{0x0e, 0x00, {0x01}, 1}, blue gain msb | ||
900 | *{0x0f, 0x00, {0x10}, 1}, blue gain lsb | ||
901 | *{0x10, 0x00, {0x01}, 1}, green2 gain msb | ||
902 | *{0x11, 0x00, {0x10}, 1}, green2 gain lsb | ||
903 | */ | ||
904 | {0x12, 0x00, {0x00}, 1}, | ||
905 | {0x13, 0x00, {0x04}, 1}, /* weird effect on colors */ | ||
906 | {0x14, 0x00, {0x00}, 1}, | ||
907 | {0x15, 0x00, {0x06}, 1}, | ||
908 | {0x16, 0x00, {0x01}, 1}, | ||
909 | {0x17, 0x00, {0xe2}, 1}, /* vertical alignment */ | ||
910 | {0x18, 0x00, {0x02}, 1}, | ||
911 | {0x19, 0x00, {0x82}, 1}, /* don't mess with */ | ||
912 | {0x1a, 0x00, {0x00}, 1}, | ||
913 | {0x1b, 0x00, {0x20}, 1}, | ||
914 | /* {0x1c, 0x00, {0x17}, 1}, contrast control */ | ||
915 | {0x1d, 0x00, {0x80}, 1}, /* moving causes a mess */ | ||
916 | {0x1e, 0x00, {0x08}, 1}, /* moving jams the camera */ | ||
917 | {0x1f, 0x00, {0x0c}, 1}, | ||
918 | {0x20, 0x00, {0x00}, 1}, | ||
919 | {0, 0, {0}, 0} | ||
920 | }; | ||
921 | err_code = sensor_write_regs(gspca_dev, vga_sensor2_init_data, | ||
922 | ARRAY_SIZE(vga_sensor2_init_data)); | ||
805 | } | 923 | } |
806 | return err_code; | 924 | return err_code; |
807 | } | 925 | } |
@@ -834,6 +952,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
834 | return err_code; | 952 | return err_code; |
835 | 953 | ||
836 | setbrightness(gspca_dev); | 954 | setbrightness(gspca_dev); |
955 | setcontrast(gspca_dev); | ||
837 | setexposure(gspca_dev); | 956 | setexposure(gspca_dev); |
838 | setgain(gspca_dev); | 957 | setgain(gspca_dev); |
839 | 958 | ||
@@ -893,7 +1012,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
893 | static void setexposure(struct gspca_dev *gspca_dev) | 1012 | static void setexposure(struct gspca_dev *gspca_dev) |
894 | { | 1013 | { |
895 | struct sd *sd = (struct sd *) gspca_dev; | 1014 | struct sd *sd = (struct sd *) gspca_dev; |
896 | int exposure; | 1015 | int exposure = MR97310A_EXPOSURE_DEFAULT; |
897 | u8 buf[2]; | 1016 | u8 buf[2]; |
898 | 1017 | ||
899 | if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX)) | 1018 | if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX)) |
@@ -905,6 +1024,11 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
905 | exposure = (sd->exposure * 9267) / 10000 + 300; | 1024 | exposure = (sd->exposure * 9267) / 10000 + 300; |
906 | sensor_write1(gspca_dev, 3, exposure >> 4); | 1025 | sensor_write1(gspca_dev, 3, exposure >> 4); |
907 | sensor_write1(gspca_dev, 4, exposure & 0x0f); | 1026 | sensor_write1(gspca_dev, 4, exposure & 0x0f); |
1027 | } else if (sd->sensor_type == 2) { | ||
1028 | exposure = sd->exposure; | ||
1029 | exposure >>= 3; | ||
1030 | sensor_write1(gspca_dev, 3, exposure >> 8); | ||
1031 | sensor_write1(gspca_dev, 4, exposure & 0xff); | ||
908 | } else { | 1032 | } else { |
909 | /* We have both a clock divider and an exposure register. | 1033 | /* We have both a clock divider and an exposure register. |
910 | We first calculate the clock divider, as that determines | 1034 | We first calculate the clock divider, as that determines |
@@ -943,17 +1067,34 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
943 | static void setgain(struct gspca_dev *gspca_dev) | 1067 | static void setgain(struct gspca_dev *gspca_dev) |
944 | { | 1068 | { |
945 | struct sd *sd = (struct sd *) gspca_dev; | 1069 | struct sd *sd = (struct sd *) gspca_dev; |
1070 | u8 gainreg; | ||
946 | 1071 | ||
947 | if (gspca_dev->ctrl_dis & (1 << GAIN_IDX)) | 1072 | if ((gspca_dev->ctrl_dis & (1 << GAIN_IDX)) && |
1073 | (gspca_dev->ctrl_dis & (1 << SAKAR_CS_GAIN_IDX))) | ||
948 | return; | 1074 | return; |
949 | 1075 | ||
950 | if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) { | 1076 | if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) |
951 | sensor_write1(gspca_dev, 0x0e, sd->gain); | 1077 | sensor_write1(gspca_dev, 0x0e, sd->gain); |
952 | } else { | 1078 | else if (sd->cam_type == CAM_TYPE_VGA && sd->sensor_type == 2) |
1079 | for (gainreg = 0x0a; gainreg < 0x11; gainreg += 2) { | ||
1080 | sensor_write1(gspca_dev, gainreg, sd->gain >> 8); | ||
1081 | sensor_write1(gspca_dev, gainreg + 1, sd->gain & 0xff); | ||
1082 | } | ||
1083 | else | ||
953 | sensor_write1(gspca_dev, 0x10, sd->gain); | 1084 | sensor_write1(gspca_dev, 0x10, sd->gain); |
954 | } | ||
955 | } | 1085 | } |
956 | 1086 | ||
1087 | static void setcontrast(struct gspca_dev *gspca_dev) | ||
1088 | { | ||
1089 | struct sd *sd = (struct sd *) gspca_dev; | ||
1090 | |||
1091 | if (gspca_dev->ctrl_dis & (1 << CONTRAST_IDX)) | ||
1092 | return; | ||
1093 | |||
1094 | sensor_write1(gspca_dev, 0x1c, sd->contrast); | ||
1095 | } | ||
1096 | |||
1097 | |||
957 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 1098 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) |
958 | { | 1099 | { |
959 | struct sd *sd = (struct sd *) gspca_dev; | 1100 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -1008,6 +1149,25 @@ static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) | |||
1008 | return 0; | 1149 | return 0; |
1009 | } | 1150 | } |
1010 | 1151 | ||
1152 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | ||
1153 | { | ||
1154 | struct sd *sd = (struct sd *) gspca_dev; | ||
1155 | |||
1156 | sd->contrast = val; | ||
1157 | if (gspca_dev->streaming) | ||
1158 | setcontrast(gspca_dev); | ||
1159 | return 0; | ||
1160 | } | ||
1161 | |||
1162 | |||
1163 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | ||
1164 | { | ||
1165 | struct sd *sd = (struct sd *) gspca_dev; | ||
1166 | |||
1167 | *val = sd->contrast; | ||
1168 | return 0; | ||
1169 | } | ||
1170 | |||
1011 | static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val) | 1171 | static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val) |
1012 | { | 1172 | { |
1013 | struct sd *sd = (struct sd *) gspca_dev; | 1173 | struct sd *sd = (struct sd *) gspca_dev; |
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index b4f965731244..bc4ced6c013b 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c | |||
@@ -38,6 +38,7 @@ | |||
38 | */ | 38 | */ |
39 | #define MODULE_NAME "ov519" | 39 | #define MODULE_NAME "ov519" |
40 | 40 | ||
41 | #include <linux/input.h> | ||
41 | #include "gspca.h" | 42 | #include "gspca.h" |
42 | 43 | ||
43 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | 44 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); |
@@ -70,6 +71,9 @@ struct sd { | |||
70 | char invert_led; | 71 | char invert_led; |
71 | #define BRIDGE_INVERT_LED 8 | 72 | #define BRIDGE_INVERT_LED 8 |
72 | 73 | ||
74 | char snapshot_pressed; | ||
75 | char snapshot_needs_reset; | ||
76 | |||
73 | /* Determined by sensor type */ | 77 | /* Determined by sensor type */ |
74 | __u8 sif; | 78 | __u8 sif; |
75 | 79 | ||
@@ -99,10 +103,12 @@ struct sd { | |||
99 | #define SEN_OV66308AF 5 | 103 | #define SEN_OV66308AF 5 |
100 | #define SEN_OV7610 6 | 104 | #define SEN_OV7610 6 |
101 | #define SEN_OV7620 7 | 105 | #define SEN_OV7620 7 |
102 | #define SEN_OV7640 8 | 106 | #define SEN_OV7620AE 8 |
103 | #define SEN_OV7670 9 | 107 | #define SEN_OV7640 9 |
104 | #define SEN_OV76BE 10 | 108 | #define SEN_OV7648 10 |
105 | #define SEN_OV8610 11 | 109 | #define SEN_OV7670 11 |
110 | #define SEN_OV76BE 12 | ||
111 | #define SEN_OV8610 13 | ||
106 | 112 | ||
107 | u8 sensor_addr; | 113 | u8 sensor_addr; |
108 | int sensor_width; | 114 | int sensor_width; |
@@ -139,6 +145,7 @@ static void setautobrightness(struct sd *sd); | |||
139 | static void setfreq(struct sd *sd); | 145 | static void setfreq(struct sd *sd); |
140 | 146 | ||
141 | static const struct ctrl sd_ctrls[] = { | 147 | static const struct ctrl sd_ctrls[] = { |
148 | #define BRIGHTNESS_IDX 0 | ||
142 | { | 149 | { |
143 | { | 150 | { |
144 | .id = V4L2_CID_BRIGHTNESS, | 151 | .id = V4L2_CID_BRIGHTNESS, |
@@ -153,6 +160,7 @@ static const struct ctrl sd_ctrls[] = { | |||
153 | .set = sd_setbrightness, | 160 | .set = sd_setbrightness, |
154 | .get = sd_getbrightness, | 161 | .get = sd_getbrightness, |
155 | }, | 162 | }, |
163 | #define CONTRAST_IDX 1 | ||
156 | { | 164 | { |
157 | { | 165 | { |
158 | .id = V4L2_CID_CONTRAST, | 166 | .id = V4L2_CID_CONTRAST, |
@@ -167,6 +175,7 @@ static const struct ctrl sd_ctrls[] = { | |||
167 | .set = sd_setcontrast, | 175 | .set = sd_setcontrast, |
168 | .get = sd_getcontrast, | 176 | .get = sd_getcontrast, |
169 | }, | 177 | }, |
178 | #define COLOR_IDX 2 | ||
170 | { | 179 | { |
171 | { | 180 | { |
172 | .id = V4L2_CID_SATURATION, | 181 | .id = V4L2_CID_SATURATION, |
@@ -2554,7 +2563,7 @@ static int ov7xx0_configure(struct sd *sd) | |||
2554 | /* I don't know what's different about the 76BE yet. */ | 2563 | /* I don't know what's different about the 76BE yet. */ |
2555 | if (i2c_r(sd, 0x15) & 1) { | 2564 | if (i2c_r(sd, 0x15) & 1) { |
2556 | PDEBUG(D_PROBE, "Sensor is an OV7620AE"); | 2565 | PDEBUG(D_PROBE, "Sensor is an OV7620AE"); |
2557 | sd->sensor = SEN_OV7620; | 2566 | sd->sensor = SEN_OV7620AE; |
2558 | } else { | 2567 | } else { |
2559 | PDEBUG(D_PROBE, "Sensor is an OV76BE"); | 2568 | PDEBUG(D_PROBE, "Sensor is an OV76BE"); |
2560 | sd->sensor = SEN_OV76BE; | 2569 | sd->sensor = SEN_OV76BE; |
@@ -2588,7 +2597,7 @@ static int ov7xx0_configure(struct sd *sd) | |||
2588 | break; | 2597 | break; |
2589 | case 0x48: | 2598 | case 0x48: |
2590 | PDEBUG(D_PROBE, "Sensor is an OV7648"); | 2599 | PDEBUG(D_PROBE, "Sensor is an OV7648"); |
2591 | sd->sensor = SEN_OV7640; /* FIXME */ | 2600 | sd->sensor = SEN_OV7648; |
2592 | break; | 2601 | break; |
2593 | default: | 2602 | default: |
2594 | PDEBUG(D_PROBE, "Unknown sensor: 0x76%x", low); | 2603 | PDEBUG(D_PROBE, "Unknown sensor: 0x76%x", low); |
@@ -2680,6 +2689,36 @@ static void ov51x_led_control(struct sd *sd, int on) | |||
2680 | } | 2689 | } |
2681 | } | 2690 | } |
2682 | 2691 | ||
2692 | static void sd_reset_snapshot(struct gspca_dev *gspca_dev) | ||
2693 | { | ||
2694 | struct sd *sd = (struct sd *) gspca_dev; | ||
2695 | |||
2696 | if (!sd->snapshot_needs_reset) | ||
2697 | return; | ||
2698 | |||
2699 | /* Note it is important that we clear sd->snapshot_needs_reset, | ||
2700 | before actually clearing the snapshot state in the bridge | ||
2701 | otherwise we might race with the pkt_scan interrupt handler */ | ||
2702 | sd->snapshot_needs_reset = 0; | ||
2703 | |||
2704 | switch (sd->bridge) { | ||
2705 | case BRIDGE_OV511: | ||
2706 | case BRIDGE_OV511PLUS: | ||
2707 | reg_w(sd, R51x_SYS_SNAP, 0x02); | ||
2708 | reg_w(sd, R51x_SYS_SNAP, 0x00); | ||
2709 | break; | ||
2710 | case BRIDGE_OV518: | ||
2711 | case BRIDGE_OV518PLUS: | ||
2712 | reg_w(sd, R51x_SYS_SNAP, 0x02); /* Reset */ | ||
2713 | reg_w(sd, R51x_SYS_SNAP, 0x01); /* Enable */ | ||
2714 | break; | ||
2715 | case BRIDGE_OV519: | ||
2716 | reg_w(sd, R51x_SYS_RESET, 0x40); | ||
2717 | reg_w(sd, R51x_SYS_RESET, 0x00); | ||
2718 | break; | ||
2719 | } | ||
2720 | } | ||
2721 | |||
2683 | static int ov51x_upload_quan_tables(struct sd *sd) | 2722 | static int ov51x_upload_quan_tables(struct sd *sd) |
2684 | { | 2723 | { |
2685 | const unsigned char yQuanTable511[] = { | 2724 | const unsigned char yQuanTable511[] = { |
@@ -3115,7 +3154,11 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
3115 | (1 << OV7670_FREQ_IDX); | 3154 | (1 << OV7670_FREQ_IDX); |
3116 | } | 3155 | } |
3117 | sd->quality = QUALITY_DEF; | 3156 | sd->quality = QUALITY_DEF; |
3118 | if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670) | 3157 | if (sd->sensor == SEN_OV7640 || |
3158 | sd->sensor == SEN_OV7648) | ||
3159 | gspca_dev->ctrl_dis |= (1 << AUTOBRIGHT_IDX) | | ||
3160 | (1 << CONTRAST_IDX); | ||
3161 | if (sd->sensor == SEN_OV7670) | ||
3119 | gspca_dev->ctrl_dis |= 1 << AUTOBRIGHT_IDX; | 3162 | gspca_dev->ctrl_dis |= 1 << AUTOBRIGHT_IDX; |
3120 | /* OV8610 Frequency filter control should work but needs testing */ | 3163 | /* OV8610 Frequency filter control should work but needs testing */ |
3121 | if (sd->sensor == SEN_OV8610) | 3164 | if (sd->sensor == SEN_OV8610) |
@@ -3169,10 +3212,12 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
3169 | return -EIO; | 3212 | return -EIO; |
3170 | break; | 3213 | break; |
3171 | case SEN_OV7620: | 3214 | case SEN_OV7620: |
3215 | case SEN_OV7620AE: | ||
3172 | if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620))) | 3216 | if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620))) |
3173 | return -EIO; | 3217 | return -EIO; |
3174 | break; | 3218 | break; |
3175 | case SEN_OV7640: | 3219 | case SEN_OV7640: |
3220 | case SEN_OV7648: | ||
3176 | if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640))) | 3221 | if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640))) |
3177 | return -EIO; | 3222 | return -EIO; |
3178 | break; | 3223 | break; |
@@ -3246,7 +3291,9 @@ static int ov511_mode_init_regs(struct sd *sd) | |||
3246 | /* Note once the FIXME's in mode_init_ov_sensor_regs() are fixed | 3291 | /* Note once the FIXME's in mode_init_ov_sensor_regs() are fixed |
3247 | for more sensors we need to do this for them too */ | 3292 | for more sensors we need to do this for them too */ |
3248 | case SEN_OV7620: | 3293 | case SEN_OV7620: |
3294 | case SEN_OV7620AE: | ||
3249 | case SEN_OV7640: | 3295 | case SEN_OV7640: |
3296 | case SEN_OV7648: | ||
3250 | case SEN_OV76BE: | 3297 | case SEN_OV76BE: |
3251 | if (sd->gspca_dev.width == 320) | 3298 | if (sd->gspca_dev.width == 320) |
3252 | interlaced = 1; | 3299 | interlaced = 1; |
@@ -3377,7 +3424,7 @@ static int ov518_mode_init_regs(struct sd *sd) | |||
3377 | 3424 | ||
3378 | if (sd->bridge == BRIDGE_OV518PLUS) { | 3425 | if (sd->bridge == BRIDGE_OV518PLUS) { |
3379 | switch (sd->sensor) { | 3426 | switch (sd->sensor) { |
3380 | case SEN_OV7620: | 3427 | case SEN_OV7620AE: |
3381 | if (sd->gspca_dev.width == 320) { | 3428 | if (sd->gspca_dev.width == 320) { |
3382 | reg_w(sd, 0x20, 0x00); | 3429 | reg_w(sd, 0x20, 0x00); |
3383 | reg_w(sd, 0x21, 0x19); | 3430 | reg_w(sd, 0x21, 0x19); |
@@ -3386,6 +3433,10 @@ static int ov518_mode_init_regs(struct sd *sd) | |||
3386 | reg_w(sd, 0x21, 0x1f); | 3433 | reg_w(sd, 0x21, 0x1f); |
3387 | } | 3434 | } |
3388 | break; | 3435 | break; |
3436 | case SEN_OV7620: | ||
3437 | reg_w(sd, 0x20, 0x00); | ||
3438 | reg_w(sd, 0x21, 0x19); | ||
3439 | break; | ||
3389 | default: | 3440 | default: |
3390 | reg_w(sd, 0x21, 0x19); | 3441 | reg_w(sd, 0x21, 0x19); |
3391 | } | 3442 | } |
@@ -3488,7 +3539,8 @@ static int ov519_mode_init_regs(struct sd *sd) | |||
3488 | if (write_regvals(sd, mode_init_519, | 3539 | if (write_regvals(sd, mode_init_519, |
3489 | ARRAY_SIZE(mode_init_519))) | 3540 | ARRAY_SIZE(mode_init_519))) |
3490 | return -EIO; | 3541 | return -EIO; |
3491 | if (sd->sensor == SEN_OV7640) { | 3542 | if (sd->sensor == SEN_OV7640 || |
3543 | sd->sensor == SEN_OV7648) { | ||
3492 | /* Select 8-bit input mode */ | 3544 | /* Select 8-bit input mode */ |
3493 | reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10); | 3545 | reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10); |
3494 | } | 3546 | } |
@@ -3503,6 +3555,9 @@ static int ov519_mode_init_regs(struct sd *sd) | |||
3503 | if (sd->sensor == SEN_OV7670 && | 3555 | if (sd->sensor == SEN_OV7670 && |
3504 | sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv) | 3556 | sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv) |
3505 | reg_w(sd, OV519_R12_X_OFFSETL, 0x04); | 3557 | reg_w(sd, OV519_R12_X_OFFSETL, 0x04); |
3558 | else if (sd->sensor == SEN_OV7648 && | ||
3559 | sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv) | ||
3560 | reg_w(sd, OV519_R12_X_OFFSETL, 0x01); | ||
3506 | else | 3561 | else |
3507 | reg_w(sd, OV519_R12_X_OFFSETL, 0x00); | 3562 | reg_w(sd, OV519_R12_X_OFFSETL, 0x00); |
3508 | reg_w(sd, OV519_R13_X_OFFSETH, 0x00); | 3563 | reg_w(sd, OV519_R13_X_OFFSETH, 0x00); |
@@ -3520,6 +3575,7 @@ static int ov519_mode_init_regs(struct sd *sd) | |||
3520 | sd->clockdiv = 0; | 3575 | sd->clockdiv = 0; |
3521 | switch (sd->sensor) { | 3576 | switch (sd->sensor) { |
3522 | case SEN_OV7640: | 3577 | case SEN_OV7640: |
3578 | case SEN_OV7648: | ||
3523 | switch (sd->frame_rate) { | 3579 | switch (sd->frame_rate) { |
3524 | default: | 3580 | default: |
3525 | /* case 30: */ | 3581 | /* case 30: */ |
@@ -3649,6 +3705,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd) | |||
3649 | i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ | 3705 | i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ |
3650 | break; | 3706 | break; |
3651 | case SEN_OV7620: | 3707 | case SEN_OV7620: |
3708 | case SEN_OV7620AE: | ||
3652 | case SEN_OV76BE: | 3709 | case SEN_OV76BE: |
3653 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); | 3710 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); |
3654 | i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); | 3711 | i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); |
@@ -3663,13 +3720,16 @@ static int mode_init_ov_sensor_regs(struct sd *sd) | |||
3663 | i2c_w(sd, 0x35, qvga ? 0x1e : 0x9e); | 3720 | i2c_w(sd, 0x35, qvga ? 0x1e : 0x9e); |
3664 | break; | 3721 | break; |
3665 | case SEN_OV7640: | 3722 | case SEN_OV7640: |
3723 | case SEN_OV7648: | ||
3666 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); | 3724 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); |
3667 | i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); | 3725 | i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); |
3668 | /* i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a); */ | 3726 | /* Setting this undocumented bit in qvga mode removes a very |
3669 | /* i2c_w(sd, 0x25, qvga ? 0x30 : 0x60); */ | 3727 | annoying vertical shaking of the image */ |
3670 | /* i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); */ | 3728 | i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); |
3671 | /* i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); */ | 3729 | /* Unknown */ |
3672 | /* i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); */ | 3730 | i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); |
3731 | /* Allow higher automatic gain (to allow higher framerates) */ | ||
3732 | i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); | ||
3673 | i2c_w_mask(sd, 0x12, 0x04, 0x04); /* AWB: 1 */ | 3733 | i2c_w_mask(sd, 0x12, 0x04, 0x04); /* AWB: 1 */ |
3674 | break; | 3734 | break; |
3675 | case SEN_OV7670: | 3735 | case SEN_OV7670: |
@@ -3795,11 +3855,13 @@ static int set_ov_sensor_window(struct sd *sd) | |||
3795 | } | 3855 | } |
3796 | break; | 3856 | break; |
3797 | case SEN_OV7620: | 3857 | case SEN_OV7620: |
3858 | case SEN_OV7620AE: | ||
3798 | hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */ | 3859 | hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */ |
3799 | hwebase = 0x2f; | 3860 | hwebase = 0x2f; |
3800 | vwsbase = vwebase = 0x05; | 3861 | vwsbase = vwebase = 0x05; |
3801 | break; | 3862 | break; |
3802 | case SEN_OV7640: | 3863 | case SEN_OV7640: |
3864 | case SEN_OV7648: | ||
3803 | hwsbase = 0x1a; | 3865 | hwsbase = 0x1a; |
3804 | hwebase = 0x1a; | 3866 | hwebase = 0x1a; |
3805 | vwsbase = vwebase = 0x03; | 3867 | vwsbase = vwebase = 0x03; |
@@ -3893,6 +3955,12 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
3893 | setautobrightness(sd); | 3955 | setautobrightness(sd); |
3894 | setfreq(sd); | 3956 | setfreq(sd); |
3895 | 3957 | ||
3958 | /* Force clear snapshot state in case the snapshot button was | ||
3959 | pressed while we weren't streaming */ | ||
3960 | sd->snapshot_needs_reset = 1; | ||
3961 | sd_reset_snapshot(gspca_dev); | ||
3962 | sd->snapshot_pressed = 0; | ||
3963 | |||
3896 | ret = ov51x_restart(sd); | 3964 | ret = ov51x_restart(sd); |
3897 | if (ret < 0) | 3965 | if (ret < 0) |
3898 | goto out; | 3966 | goto out; |
@@ -3919,6 +3987,34 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
3919 | w9968cf_stop0(sd); | 3987 | w9968cf_stop0(sd); |
3920 | } | 3988 | } |
3921 | 3989 | ||
3990 | static void ov51x_handle_button(struct gspca_dev *gspca_dev, u8 state) | ||
3991 | { | ||
3992 | struct sd *sd = (struct sd *) gspca_dev; | ||
3993 | |||
3994 | if (sd->snapshot_pressed != state) { | ||
3995 | #ifdef CONFIG_INPUT | ||
3996 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, state); | ||
3997 | input_sync(gspca_dev->input_dev); | ||
3998 | #endif | ||
3999 | if (state) | ||
4000 | sd->snapshot_needs_reset = 1; | ||
4001 | |||
4002 | sd->snapshot_pressed = state; | ||
4003 | } else { | ||
4004 | /* On the ov511 / ov519 we need to reset the button state | ||
4005 | multiple times, as resetting does not work as long as the | ||
4006 | button stays pressed */ | ||
4007 | switch (sd->bridge) { | ||
4008 | case BRIDGE_OV511: | ||
4009 | case BRIDGE_OV511PLUS: | ||
4010 | case BRIDGE_OV519: | ||
4011 | if (state) | ||
4012 | sd->snapshot_needs_reset = 1; | ||
4013 | break; | ||
4014 | } | ||
4015 | } | ||
4016 | } | ||
4017 | |||
3922 | static void ov511_pkt_scan(struct gspca_dev *gspca_dev, | 4018 | static void ov511_pkt_scan(struct gspca_dev *gspca_dev, |
3923 | u8 *in, /* isoc packet */ | 4019 | u8 *in, /* isoc packet */ |
3924 | int len) /* iso packet length */ | 4020 | int len) /* iso packet length */ |
@@ -3940,6 +4036,7 @@ static void ov511_pkt_scan(struct gspca_dev *gspca_dev, | |||
3940 | */ | 4036 | */ |
3941 | if (!(in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) && | 4037 | if (!(in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) && |
3942 | (in[8] & 0x08)) { | 4038 | (in[8] & 0x08)) { |
4039 | ov51x_handle_button(gspca_dev, (in[8] >> 2) & 1); | ||
3943 | if (in[8] & 0x80) { | 4040 | if (in[8] & 0x80) { |
3944 | /* Frame end */ | 4041 | /* Frame end */ |
3945 | if ((in[9] + 1) * 8 != gspca_dev->width || | 4042 | if ((in[9] + 1) * 8 != gspca_dev->width || |
@@ -3977,6 +4074,7 @@ static void ov518_pkt_scan(struct gspca_dev *gspca_dev, | |||
3977 | /* A false positive here is likely, until OVT gives me | 4074 | /* A false positive here is likely, until OVT gives me |
3978 | * the definitive SOF/EOF format */ | 4075 | * the definitive SOF/EOF format */ |
3979 | if ((!(data[0] | data[1] | data[2] | data[3] | data[5])) && data[6]) { | 4076 | if ((!(data[0] | data[1] | data[2] | data[3] | data[5])) && data[6]) { |
4077 | ov51x_handle_button(gspca_dev, (data[6] >> 1) & 1); | ||
3980 | gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); | 4078 | gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); |
3981 | gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); | 4079 | gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0); |
3982 | sd->packet_nr = 0; | 4080 | sd->packet_nr = 0; |
@@ -4024,6 +4122,9 @@ static void ov519_pkt_scan(struct gspca_dev *gspca_dev, | |||
4024 | if (data[0] == 0xff && data[1] == 0xff && data[2] == 0xff) { | 4122 | if (data[0] == 0xff && data[1] == 0xff && data[2] == 0xff) { |
4025 | switch (data[3]) { | 4123 | switch (data[3]) { |
4026 | case 0x50: /* start of frame */ | 4124 | case 0x50: /* start of frame */ |
4125 | /* Don't check the button state here, as the state | ||
4126 | usually (always ?) changes at EOF and checking it | ||
4127 | here leads to unnecessary snapshot state resets. */ | ||
4027 | #define HDRSZ 16 | 4128 | #define HDRSZ 16 |
4028 | data += HDRSZ; | 4129 | data += HDRSZ; |
4029 | len -= HDRSZ; | 4130 | len -= HDRSZ; |
@@ -4035,6 +4136,7 @@ static void ov519_pkt_scan(struct gspca_dev *gspca_dev, | |||
4035 | gspca_dev->last_packet_type = DISCARD_PACKET; | 4136 | gspca_dev->last_packet_type = DISCARD_PACKET; |
4036 | return; | 4137 | return; |
4037 | case 0x51: /* end of frame */ | 4138 | case 0x51: /* end of frame */ |
4139 | ov51x_handle_button(gspca_dev, data[11] & 1); | ||
4038 | if (data[9] != 0) | 4140 | if (data[9] != 0) |
4039 | gspca_dev->last_packet_type = DISCARD_PACKET; | 4141 | gspca_dev->last_packet_type = DISCARD_PACKET; |
4040 | gspca_frame_add(gspca_dev, LAST_PACKET, | 4142 | gspca_frame_add(gspca_dev, LAST_PACKET, |
@@ -4103,9 +4205,11 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
4103 | case SEN_OV6630: | 4205 | case SEN_OV6630: |
4104 | case SEN_OV66308AF: | 4206 | case SEN_OV66308AF: |
4105 | case SEN_OV7640: | 4207 | case SEN_OV7640: |
4208 | case SEN_OV7648: | ||
4106 | i2c_w(sd, OV7610_REG_BRT, val); | 4209 | i2c_w(sd, OV7610_REG_BRT, val); |
4107 | break; | 4210 | break; |
4108 | case SEN_OV7620: | 4211 | case SEN_OV7620: |
4212 | case SEN_OV7620AE: | ||
4109 | /* 7620 doesn't like manual changes when in auto mode */ | 4213 | /* 7620 doesn't like manual changes when in auto mode */ |
4110 | if (!sd->autobrightness) | 4214 | if (!sd->autobrightness) |
4111 | i2c_w(sd, OV7610_REG_BRT, val); | 4215 | i2c_w(sd, OV7610_REG_BRT, val); |
@@ -4142,7 +4246,8 @@ static void setcontrast(struct gspca_dev *gspca_dev) | |||
4142 | i2c_w(sd, 0x64, ctab[val >> 5]); | 4246 | i2c_w(sd, 0x64, ctab[val >> 5]); |
4143 | break; | 4247 | break; |
4144 | } | 4248 | } |
4145 | case SEN_OV7620: { | 4249 | case SEN_OV7620: |
4250 | case SEN_OV7620AE: { | ||
4146 | static const __u8 ctab[] = { | 4251 | static const __u8 ctab[] = { |
4147 | 0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57, | 4252 | 0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57, |
4148 | 0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff | 4253 | 0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff |
@@ -4152,10 +4257,6 @@ static void setcontrast(struct gspca_dev *gspca_dev) | |||
4152 | i2c_w(sd, 0x64, ctab[val >> 4]); | 4257 | i2c_w(sd, 0x64, ctab[val >> 4]); |
4153 | break; | 4258 | break; |
4154 | } | 4259 | } |
4155 | case SEN_OV7640: | ||
4156 | /* Use gain control instead. */ | ||
4157 | i2c_w(sd, OV7610_REG_GAIN, val >> 2); | ||
4158 | break; | ||
4159 | case SEN_OV7670: | 4260 | case SEN_OV7670: |
4160 | /* check that this isn't just the same as ov7610 */ | 4261 | /* check that this isn't just the same as ov7610 */ |
4161 | i2c_w(sd, OV7670_REG_CONTRAS, val >> 1); | 4262 | i2c_w(sd, OV7670_REG_CONTRAS, val >> 1); |
@@ -4179,6 +4280,7 @@ static void setcolors(struct gspca_dev *gspca_dev) | |||
4179 | i2c_w(sd, OV7610_REG_SAT, val); | 4280 | i2c_w(sd, OV7610_REG_SAT, val); |
4180 | break; | 4281 | break; |
4181 | case SEN_OV7620: | 4282 | case SEN_OV7620: |
4283 | case SEN_OV7620AE: | ||
4182 | /* Use UV gamma control instead. Bits 0 & 7 are reserved. */ | 4284 | /* Use UV gamma control instead. Bits 0 & 7 are reserved. */ |
4183 | /* rc = ov_i2c_write(sd->dev, 0x62, (val >> 9) & 0x7e); | 4285 | /* rc = ov_i2c_write(sd->dev, 0x62, (val >> 9) & 0x7e); |
4184 | if (rc < 0) | 4286 | if (rc < 0) |
@@ -4186,6 +4288,7 @@ static void setcolors(struct gspca_dev *gspca_dev) | |||
4186 | i2c_w(sd, OV7610_REG_SAT, val); | 4288 | i2c_w(sd, OV7610_REG_SAT, val); |
4187 | break; | 4289 | break; |
4188 | case SEN_OV7640: | 4290 | case SEN_OV7640: |
4291 | case SEN_OV7648: | ||
4189 | i2c_w(sd, OV7610_REG_SAT, val & 0xf0); | 4292 | i2c_w(sd, OV7610_REG_SAT, val & 0xf0); |
4190 | break; | 4293 | break; |
4191 | case SEN_OV7670: | 4294 | case SEN_OV7670: |
@@ -4198,7 +4301,8 @@ static void setcolors(struct gspca_dev *gspca_dev) | |||
4198 | 4301 | ||
4199 | static void setautobrightness(struct sd *sd) | 4302 | static void setautobrightness(struct sd *sd) |
4200 | { | 4303 | { |
4201 | if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670 || | 4304 | if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7648 || |
4305 | sd->sensor == SEN_OV7670 || | ||
4202 | sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610) | 4306 | sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610) |
4203 | return; | 4307 | return; |
4204 | 4308 | ||
@@ -4475,9 +4579,13 @@ static const struct sd_desc sd_desc = { | |||
4475 | .stopN = sd_stopN, | 4579 | .stopN = sd_stopN, |
4476 | .stop0 = sd_stop0, | 4580 | .stop0 = sd_stop0, |
4477 | .pkt_scan = sd_pkt_scan, | 4581 | .pkt_scan = sd_pkt_scan, |
4582 | .dq_callback = sd_reset_snapshot, | ||
4478 | .querymenu = sd_querymenu, | 4583 | .querymenu = sd_querymenu, |
4479 | .get_jcomp = sd_get_jcomp, | 4584 | .get_jcomp = sd_get_jcomp, |
4480 | .set_jcomp = sd_set_jcomp, | 4585 | .set_jcomp = sd_set_jcomp, |
4586 | #ifdef CONFIG_INPUT | ||
4587 | .other_input = 1, | ||
4588 | #endif | ||
4481 | }; | 4589 | }; |
4482 | 4590 | ||
4483 | /* -- module initialisation -- */ | 4591 | /* -- module initialisation -- */ |
@@ -4494,7 +4602,8 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
4494 | .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, | 4602 | .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, |
4495 | {USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 }, | 4603 | {USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 }, |
4496 | {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 }, | 4604 | {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 }, |
4497 | {USB_DEVICE(0x054c, 0x0155), .driver_info = BRIDGE_OV519 }, | 4605 | {USB_DEVICE(0x054c, 0x0155), |
4606 | .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, | ||
4498 | {USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 }, | 4607 | {USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 }, |
4499 | {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 }, | 4608 | {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 }, |
4500 | {USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 }, | 4609 | {USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 }, |
diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 0a6b8f07a69d..957e05e2d08f 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * ov534 gspca driver | 2 | * ov534-ov772x gspca driver |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it> | 4 | * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it> |
5 | * Copyright (C) 2008 Jim Paris <jim@jtan.com> | 5 | * Copyright (C) 2008 Jim Paris <jim@jtan.com> |
@@ -68,12 +68,7 @@ struct sd { | |||
68 | s8 sharpness; | 68 | s8 sharpness; |
69 | u8 hflip; | 69 | u8 hflip; |
70 | u8 vflip; | 70 | u8 vflip; |
71 | u8 satur; | ||
72 | u8 lightfreq; | ||
73 | 71 | ||
74 | u8 sensor; | ||
75 | #define SENSOR_OV772X 0 | ||
76 | #define SENSOR_OV965X 1 | ||
77 | }; | 72 | }; |
78 | 73 | ||
79 | /* V4L2 controls supported by the driver */ | 74 | /* V4L2 controls supported by the driver */ |
@@ -101,12 +96,8 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | |||
101 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | 96 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); |
102 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | 97 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); |
103 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | 98 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); |
104 | static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val); | ||
105 | static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val); | ||
106 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | ||
107 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | ||
108 | 99 | ||
109 | static struct ctrl sd_ctrls_ov772x[] = { | 100 | static const struct ctrl sd_ctrls[] = { |
110 | { /* 0 */ | 101 | { /* 0 */ |
111 | { | 102 | { |
112 | .id = V4L2_CID_BRIGHTNESS, | 103 | .id = V4L2_CID_BRIGHTNESS, |
@@ -115,8 +106,8 @@ static struct ctrl sd_ctrls_ov772x[] = { | |||
115 | .minimum = 0, | 106 | .minimum = 0, |
116 | .maximum = 255, | 107 | .maximum = 255, |
117 | .step = 1, | 108 | .step = 1, |
118 | #define BRIGHTNESS_77_DEF 20 | 109 | #define BRIGHTNESS_DEF 20 |
119 | .default_value = BRIGHTNESS_77_DEF, | 110 | .default_value = BRIGHTNESS_DEF, |
120 | }, | 111 | }, |
121 | .set = sd_setbrightness, | 112 | .set = sd_setbrightness, |
122 | .get = sd_getbrightness, | 113 | .get = sd_getbrightness, |
@@ -129,8 +120,8 @@ static struct ctrl sd_ctrls_ov772x[] = { | |||
129 | .minimum = 0, | 120 | .minimum = 0, |
130 | .maximum = 255, | 121 | .maximum = 255, |
131 | .step = 1, | 122 | .step = 1, |
132 | #define CONTRAST_77_DEF 37 | 123 | #define CONTRAST_DEF 37 |
133 | .default_value = CONTRAST_77_DEF, | 124 | .default_value = CONTRAST_DEF, |
134 | }, | 125 | }, |
135 | .set = sd_setcontrast, | 126 | .set = sd_setcontrast, |
136 | .get = sd_getcontrast, | 127 | .get = sd_getcontrast, |
@@ -157,8 +148,8 @@ static struct ctrl sd_ctrls_ov772x[] = { | |||
157 | .minimum = 0, | 148 | .minimum = 0, |
158 | .maximum = 255, | 149 | .maximum = 255, |
159 | .step = 1, | 150 | .step = 1, |
160 | #define EXPO_77_DEF 120 | 151 | #define EXPO_DEF 120 |
161 | .default_value = EXPO_77_DEF, | 152 | .default_value = EXPO_DEF, |
162 | }, | 153 | }, |
163 | .set = sd_setexposure, | 154 | .set = sd_setexposure, |
164 | .get = sd_getexposure, | 155 | .get = sd_getexposure, |
@@ -213,13 +204,13 @@ static struct ctrl sd_ctrls_ov772x[] = { | |||
213 | .minimum = 0, | 204 | .minimum = 0, |
214 | .maximum = 1, | 205 | .maximum = 1, |
215 | .step = 1, | 206 | .step = 1, |
216 | #define AUTOGAIN_77_DEF 0 | 207 | #define AUTOGAIN_DEF 0 |
217 | .default_value = AUTOGAIN_77_DEF, | 208 | .default_value = AUTOGAIN_DEF, |
218 | }, | 209 | }, |
219 | .set = sd_setautogain, | 210 | .set = sd_setautogain, |
220 | .get = sd_getautogain, | 211 | .get = sd_getautogain, |
221 | }, | 212 | }, |
222 | #define AWB_77_IDX 8 | 213 | #define AWB_IDX 8 |
223 | { /* 8 */ | 214 | { /* 8 */ |
224 | { | 215 | { |
225 | .id = V4L2_CID_AUTO_WHITE_BALANCE, | 216 | .id = V4L2_CID_AUTO_WHITE_BALANCE, |
@@ -242,8 +233,8 @@ static struct ctrl sd_ctrls_ov772x[] = { | |||
242 | .minimum = 0, | 233 | .minimum = 0, |
243 | .maximum = 63, | 234 | .maximum = 63, |
244 | .step = 1, | 235 | .step = 1, |
245 | #define SHARPNESS_77_DEF 0 | 236 | #define SHARPNESS_DEF 0 |
246 | .default_value = SHARPNESS_77_DEF, | 237 | .default_value = SHARPNESS_DEF, |
247 | }, | 238 | }, |
248 | .set = sd_setsharpness, | 239 | .set = sd_setsharpness, |
249 | .get = sd_getsharpness, | 240 | .get = sd_getsharpness, |
@@ -277,107 +268,6 @@ static struct ctrl sd_ctrls_ov772x[] = { | |||
277 | .get = sd_getvflip, | 268 | .get = sd_getvflip, |
278 | }, | 269 | }, |
279 | }; | 270 | }; |
280 | static struct ctrl sd_ctrls_ov965x[] = { | ||
281 | { /* 0 */ | ||
282 | { | ||
283 | .id = V4L2_CID_BRIGHTNESS, | ||
284 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
285 | .name = "Brightness", | ||
286 | .minimum = 0, | ||
287 | .maximum = 15, | ||
288 | .step = 1, | ||
289 | #define BRIGHTNESS_96_DEF 7 | ||
290 | .default_value = BRIGHTNESS_96_DEF, | ||
291 | }, | ||
292 | .set = sd_setbrightness, | ||
293 | .get = sd_getbrightness, | ||
294 | }, | ||
295 | { /* 1 */ | ||
296 | { | ||
297 | .id = V4L2_CID_CONTRAST, | ||
298 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
299 | .name = "Contrast", | ||
300 | .minimum = 0, | ||
301 | .maximum = 15, | ||
302 | .step = 1, | ||
303 | #define CONTRAST_96_DEF 3 | ||
304 | .default_value = CONTRAST_96_DEF, | ||
305 | }, | ||
306 | .set = sd_setcontrast, | ||
307 | .get = sd_getcontrast, | ||
308 | }, | ||
309 | { /* 2 */ | ||
310 | { | ||
311 | .id = V4L2_CID_AUTOGAIN, | ||
312 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
313 | .name = "Autogain", | ||
314 | .minimum = 0, | ||
315 | .maximum = 1, | ||
316 | .step = 1, | ||
317 | #define AUTOGAIN_96_DEF 1 | ||
318 | .default_value = AUTOGAIN_96_DEF, | ||
319 | }, | ||
320 | .set = sd_setautogain, | ||
321 | .get = sd_getautogain, | ||
322 | }, | ||
323 | #define EXPO_96_IDX 3 | ||
324 | { /* 3 */ | ||
325 | { | ||
326 | .id = V4L2_CID_EXPOSURE, | ||
327 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
328 | .name = "Exposure", | ||
329 | .minimum = 0, | ||
330 | .maximum = 3, | ||
331 | .step = 1, | ||
332 | #define EXPO_96_DEF 0 | ||
333 | .default_value = EXPO_96_DEF, | ||
334 | }, | ||
335 | .set = sd_setexposure, | ||
336 | .get = sd_getexposure, | ||
337 | }, | ||
338 | { /* 4 */ | ||
339 | { | ||
340 | .id = V4L2_CID_SHARPNESS, | ||
341 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
342 | .name = "Sharpness", | ||
343 | .minimum = -1, /* -1 = auto */ | ||
344 | .maximum = 4, | ||
345 | .step = 1, | ||
346 | #define SHARPNESS_96_DEF -1 | ||
347 | .default_value = SHARPNESS_96_DEF, | ||
348 | }, | ||
349 | .set = sd_setsharpness, | ||
350 | .get = sd_getsharpness, | ||
351 | }, | ||
352 | { /* 5 */ | ||
353 | { | ||
354 | .id = V4L2_CID_SATURATION, | ||
355 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
356 | .name = "Saturation", | ||
357 | .minimum = 0, | ||
358 | .maximum = 4, | ||
359 | .step = 1, | ||
360 | #define SATUR_DEF 2 | ||
361 | .default_value = SATUR_DEF, | ||
362 | }, | ||
363 | .set = sd_setsatur, | ||
364 | .get = sd_getsatur, | ||
365 | }, | ||
366 | { | ||
367 | { | ||
368 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | ||
369 | .type = V4L2_CTRL_TYPE_MENU, | ||
370 | .name = "Light frequency filter", | ||
371 | .minimum = 0, | ||
372 | .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ | ||
373 | .step = 1, | ||
374 | #define FREQ_DEF 0 | ||
375 | .default_value = FREQ_DEF, | ||
376 | }, | ||
377 | .set = sd_setfreq, | ||
378 | .get = sd_getfreq, | ||
379 | }, | ||
380 | }; | ||
381 | 271 | ||
382 | static const struct v4l2_pix_format ov772x_mode[] = { | 272 | static const struct v4l2_pix_format ov772x_mode[] = { |
383 | {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, | 273 | {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, |
@@ -392,35 +282,21 @@ static const struct v4l2_pix_format ov772x_mode[] = { | |||
392 | .priv = 0}, | 282 | .priv = 0}, |
393 | }; | 283 | }; |
394 | 284 | ||
395 | static const struct v4l2_pix_format ov965x_mode[] = { | 285 | static const u8 qvga_rates[] = {125, 100, 75, 60, 50, 40, 30}; |
396 | {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 286 | static const u8 vga_rates[] = {60, 50, 40, 30, 15}; |
397 | .bytesperline = 320, | 287 | |
398 | .sizeimage = 320 * 240 * 3 / 8 + 590, | 288 | static const struct framerates ov772x_framerates[] = { |
399 | .colorspace = V4L2_COLORSPACE_JPEG, | 289 | { /* 320x240 */ |
400 | .priv = 4}, | 290 | .rates = qvga_rates, |
401 | {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 291 | .nrates = ARRAY_SIZE(qvga_rates), |
402 | .bytesperline = 640, | 292 | }, |
403 | .sizeimage = 640 * 480 * 3 / 8 + 590, | 293 | { /* 640x480 */ |
404 | .colorspace = V4L2_COLORSPACE_JPEG, | 294 | .rates = vga_rates, |
405 | .priv = 3}, | 295 | .nrates = ARRAY_SIZE(vga_rates), |
406 | {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 296 | }, |
407 | .bytesperline = 800, | ||
408 | .sizeimage = 800 * 600 * 3 / 8 + 590, | ||
409 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
410 | .priv = 2}, | ||
411 | {1024, 768, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
412 | .bytesperline = 1024, | ||
413 | .sizeimage = 1024 * 768 * 3 / 8 + 590, | ||
414 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
415 | .priv = 1}, | ||
416 | {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
417 | .bytesperline = 1280, | ||
418 | .sizeimage = 1280 * 1024 * 3 / 8 + 590, | ||
419 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
420 | .priv = 0}, | ||
421 | }; | 297 | }; |
422 | 298 | ||
423 | static const u8 bridge_init_ov772x[][2] = { | 299 | static const u8 bridge_init[][2] = { |
424 | { 0xc2, 0x0c }, | 300 | { 0xc2, 0x0c }, |
425 | { 0x88, 0xf8 }, | 301 | { 0x88, 0xf8 }, |
426 | { 0xc3, 0x69 }, | 302 | { 0xc3, 0x69 }, |
@@ -478,7 +354,7 @@ static const u8 bridge_init_ov772x[][2] = { | |||
478 | { 0xc1, 0x3c }, | 354 | { 0xc1, 0x3c }, |
479 | { 0xc2, 0x0c }, | 355 | { 0xc2, 0x0c }, |
480 | }; | 356 | }; |
481 | static const u8 sensor_init_ov772x[][2] = { | 357 | static const u8 sensor_init[][2] = { |
482 | { 0x12, 0x80 }, | 358 | { 0x12, 0x80 }, |
483 | { 0x11, 0x01 }, | 359 | { 0x11, 0x01 }, |
484 | /*fixme: better have a delay?*/ | 360 | /*fixme: better have a delay?*/ |
@@ -571,7 +447,7 @@ static const u8 sensor_init_ov772x[][2] = { | |||
571 | { 0x8e, 0x00 }, /* De-noise threshold */ | 447 | { 0x8e, 0x00 }, /* De-noise threshold */ |
572 | { 0x0c, 0xd0 } | 448 | { 0x0c, 0xd0 } |
573 | }; | 449 | }; |
574 | static const u8 bridge_start_ov772x_vga[][2] = { | 450 | static const u8 bridge_start_vga[][2] = { |
575 | {0x1c, 0x00}, | 451 | {0x1c, 0x00}, |
576 | {0x1d, 0x40}, | 452 | {0x1d, 0x40}, |
577 | {0x1d, 0x02}, | 453 | {0x1d, 0x02}, |
@@ -582,7 +458,7 @@ static const u8 bridge_start_ov772x_vga[][2] = { | |||
582 | {0xc0, 0x50}, | 458 | {0xc0, 0x50}, |
583 | {0xc1, 0x3c}, | 459 | {0xc1, 0x3c}, |
584 | }; | 460 | }; |
585 | static const u8 sensor_start_ov772x_vga[][2] = { | 461 | static const u8 sensor_start_vga[][2] = { |
586 | {0x12, 0x00}, | 462 | {0x12, 0x00}, |
587 | {0x17, 0x26}, | 463 | {0x17, 0x26}, |
588 | {0x18, 0xa0}, | 464 | {0x18, 0xa0}, |
@@ -592,7 +468,7 @@ static const u8 sensor_start_ov772x_vga[][2] = { | |||
592 | {0x2c, 0xf0}, | 468 | {0x2c, 0xf0}, |
593 | {0x65, 0x20}, | 469 | {0x65, 0x20}, |
594 | }; | 470 | }; |
595 | static const u8 bridge_start_ov772x_qvga[][2] = { | 471 | static const u8 bridge_start_qvga[][2] = { |
596 | {0x1c, 0x00}, | 472 | {0x1c, 0x00}, |
597 | {0x1d, 0x40}, | 473 | {0x1d, 0x40}, |
598 | {0x1d, 0x02}, | 474 | {0x1d, 0x02}, |
@@ -603,7 +479,7 @@ static const u8 bridge_start_ov772x_qvga[][2] = { | |||
603 | {0xc0, 0x28}, | 479 | {0xc0, 0x28}, |
604 | {0xc1, 0x1e}, | 480 | {0xc1, 0x1e}, |
605 | }; | 481 | }; |
606 | static const u8 sensor_start_ov772x_qvga[][2] = { | 482 | static const u8 sensor_start_qvga[][2] = { |
607 | {0x12, 0x40}, | 483 | {0x12, 0x40}, |
608 | {0x17, 0x3f}, | 484 | {0x17, 0x3f}, |
609 | {0x18, 0x50}, | 485 | {0x18, 0x50}, |
@@ -614,571 +490,6 @@ static const u8 sensor_start_ov772x_qvga[][2] = { | |||
614 | {0x65, 0x2f}, | 490 | {0x65, 0x2f}, |
615 | }; | 491 | }; |
616 | 492 | ||
617 | static const u8 bridge_init_ov965x[][2] = { | ||
618 | {0x88, 0xf8}, | ||
619 | {0x89, 0xff}, | ||
620 | {0x76, 0x03}, | ||
621 | {0x92, 0x03}, | ||
622 | {0x95, 0x10}, | ||
623 | {0xe2, 0x00}, | ||
624 | {0xe7, 0x3e}, | ||
625 | {0x8d, 0x1c}, | ||
626 | {0x8e, 0x00}, | ||
627 | {0x8f, 0x00}, | ||
628 | {0x1f, 0x00}, | ||
629 | {0xc3, 0xf9}, | ||
630 | {0x89, 0xff}, | ||
631 | {0x88, 0xf8}, | ||
632 | {0x76, 0x03}, | ||
633 | {0x92, 0x01}, | ||
634 | {0x93, 0x18}, | ||
635 | {0x1c, 0x0a}, | ||
636 | {0x1d, 0x48}, | ||
637 | {0xc0, 0x50}, | ||
638 | {0xc1, 0x3c}, | ||
639 | {0x34, 0x05}, | ||
640 | {0xc2, 0x0c}, | ||
641 | {0xc3, 0xf9}, | ||
642 | {0x34, 0x05}, | ||
643 | {0xe7, 0x2e}, | ||
644 | {0x31, 0xf9}, | ||
645 | {0x35, 0x02}, | ||
646 | {0xd9, 0x10}, | ||
647 | {0x25, 0x42}, | ||
648 | {0x94, 0x11}, | ||
649 | }; | ||
650 | |||
651 | static const u8 sensor_init_ov965x[][2] = { | ||
652 | {0x12, 0x80}, /* com7 - SSCB reset */ | ||
653 | {0x00, 0x00}, /* gain */ | ||
654 | {0x01, 0x80}, /* blue */ | ||
655 | {0x02, 0x80}, /* red */ | ||
656 | {0x03, 0x1b}, /* vref */ | ||
657 | {0x04, 0x03}, /* com1 - exposure low bits */ | ||
658 | {0x0b, 0x57}, /* ver */ | ||
659 | {0x0e, 0x61}, /* com5 */ | ||
660 | {0x0f, 0x42}, /* com6 */ | ||
661 | {0x11, 0x00}, /* clkrc */ | ||
662 | {0x12, 0x02}, /* com7 - 15fps VGA YUYV */ | ||
663 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
664 | {0x14, 0x28}, /* com9 */ | ||
665 | {0x16, 0x24}, /* reg16 */ | ||
666 | {0x17, 0x1d}, /* hstart*/ | ||
667 | {0x18, 0xbd}, /* hstop */ | ||
668 | {0x19, 0x01}, /* vstrt */ | ||
669 | {0x1a, 0x81}, /* vstop*/ | ||
670 | {0x1e, 0x04}, /* mvfp */ | ||
671 | {0x24, 0x3c}, /* aew */ | ||
672 | {0x25, 0x36}, /* aeb */ | ||
673 | {0x26, 0x71}, /* vpt */ | ||
674 | {0x27, 0x08}, /* bbias */ | ||
675 | {0x28, 0x08}, /* gbbias */ | ||
676 | {0x29, 0x15}, /* gr com */ | ||
677 | {0x2a, 0x00}, /* exhch */ | ||
678 | {0x2b, 0x00}, /* exhcl */ | ||
679 | {0x2c, 0x08}, /* rbias */ | ||
680 | {0x32, 0xff}, /* href */ | ||
681 | {0x33, 0x00}, /* chlf */ | ||
682 | {0x34, 0x3f}, /* aref1 */ | ||
683 | {0x35, 0x00}, /* aref2 */ | ||
684 | {0x36, 0xf8}, /* aref3 */ | ||
685 | {0x38, 0x72}, /* adc2 */ | ||
686 | {0x39, 0x57}, /* aref4 */ | ||
687 | {0x3a, 0x80}, /* tslb - yuyv */ | ||
688 | {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ | ||
689 | {0x3d, 0x99}, /* com13 */ | ||
690 | {0x3f, 0xc1}, /* edge */ | ||
691 | {0x40, 0xc0}, /* com15 */ | ||
692 | {0x41, 0x40}, /* com16 */ | ||
693 | {0x42, 0xc0}, /* com17 */ | ||
694 | {0x43, 0x0a}, /* rsvd */ | ||
695 | {0x44, 0xf0}, | ||
696 | {0x45, 0x46}, | ||
697 | {0x46, 0x62}, | ||
698 | {0x47, 0x2a}, | ||
699 | {0x48, 0x3c}, | ||
700 | {0x4a, 0xfc}, | ||
701 | {0x4b, 0xfc}, | ||
702 | {0x4c, 0x7f}, | ||
703 | {0x4d, 0x7f}, | ||
704 | {0x4e, 0x7f}, | ||
705 | {0x4f, 0x98}, /* matrix */ | ||
706 | {0x50, 0x98}, | ||
707 | {0x51, 0x00}, | ||
708 | {0x52, 0x28}, | ||
709 | {0x53, 0x70}, | ||
710 | {0x54, 0x98}, | ||
711 | {0x58, 0x1a}, /* matrix coef sign */ | ||
712 | {0x59, 0x85}, /* AWB control */ | ||
713 | {0x5a, 0xa9}, | ||
714 | {0x5b, 0x64}, | ||
715 | {0x5c, 0x84}, | ||
716 | {0x5d, 0x53}, | ||
717 | {0x5e, 0x0e}, | ||
718 | {0x5f, 0xf0}, /* AWB blue limit */ | ||
719 | {0x60, 0xf0}, /* AWB red limit */ | ||
720 | {0x61, 0xf0}, /* AWB green limit */ | ||
721 | {0x62, 0x00}, /* lcc1 */ | ||
722 | {0x63, 0x00}, /* lcc2 */ | ||
723 | {0x64, 0x02}, /* lcc3 */ | ||
724 | {0x65, 0x16}, /* lcc4 */ | ||
725 | {0x66, 0x01}, /* lcc5 */ | ||
726 | {0x69, 0x02}, /* hv */ | ||
727 | {0x6b, 0x5a}, /* dbvl */ | ||
728 | {0x6c, 0x04}, | ||
729 | {0x6d, 0x55}, | ||
730 | {0x6e, 0x00}, | ||
731 | {0x6f, 0x9d}, | ||
732 | {0x70, 0x21}, /* dnsth */ | ||
733 | {0x71, 0x78}, | ||
734 | {0x72, 0x00}, /* poidx */ | ||
735 | {0x73, 0x01}, /* pckdv */ | ||
736 | {0x74, 0x3a}, /* xindx */ | ||
737 | {0x75, 0x35}, /* yindx */ | ||
738 | {0x76, 0x01}, | ||
739 | {0x77, 0x02}, | ||
740 | {0x7a, 0x12}, /* gamma curve */ | ||
741 | {0x7b, 0x08}, | ||
742 | {0x7c, 0x16}, | ||
743 | {0x7d, 0x30}, | ||
744 | {0x7e, 0x5e}, | ||
745 | {0x7f, 0x72}, | ||
746 | {0x80, 0x82}, | ||
747 | {0x81, 0x8e}, | ||
748 | {0x82, 0x9a}, | ||
749 | {0x83, 0xa4}, | ||
750 | {0x84, 0xac}, | ||
751 | {0x85, 0xb8}, | ||
752 | {0x86, 0xc3}, | ||
753 | {0x87, 0xd6}, | ||
754 | {0x88, 0xe6}, | ||
755 | {0x89, 0xf2}, | ||
756 | {0x8a, 0x03}, | ||
757 | {0x8c, 0x89}, /* com19 */ | ||
758 | {0x14, 0x28}, /* com9 */ | ||
759 | {0x90, 0x7d}, | ||
760 | {0x91, 0x7b}, | ||
761 | {0x9d, 0x03}, /* lcc6 */ | ||
762 | {0x9e, 0x04}, /* lcc7 */ | ||
763 | {0x9f, 0x7a}, | ||
764 | {0xa0, 0x79}, | ||
765 | {0xa1, 0x40}, /* aechm */ | ||
766 | {0xa4, 0x50}, /* com21 */ | ||
767 | {0xa5, 0x68}, /* com26 */ | ||
768 | {0xa6, 0x4a}, /* AWB green */ | ||
769 | {0xa8, 0xc1}, /* refa8 */ | ||
770 | {0xa9, 0xef}, /* refa9 */ | ||
771 | {0xaa, 0x92}, | ||
772 | {0xab, 0x04}, | ||
773 | {0xac, 0x80}, /* black level control */ | ||
774 | {0xad, 0x80}, | ||
775 | {0xae, 0x80}, | ||
776 | {0xaf, 0x80}, | ||
777 | {0xb2, 0xf2}, | ||
778 | {0xb3, 0x20}, | ||
779 | {0xb4, 0x20}, /* ctrlb4 */ | ||
780 | {0xb5, 0x00}, | ||
781 | {0xb6, 0xaf}, | ||
782 | {0xbb, 0xae}, | ||
783 | {0xbc, 0x7f}, /* ADC channel offsets */ | ||
784 | {0xdb, 0x7f}, | ||
785 | {0xbe, 0x7f}, | ||
786 | {0xbf, 0x7f}, | ||
787 | {0xc0, 0xe2}, | ||
788 | {0xc1, 0xc0}, | ||
789 | {0xc2, 0x01}, | ||
790 | {0xc3, 0x4e}, | ||
791 | {0xc6, 0x85}, | ||
792 | {0xc7, 0x80}, /* com24 */ | ||
793 | {0xc9, 0xe0}, | ||
794 | {0xca, 0xe8}, | ||
795 | {0xcb, 0xf0}, | ||
796 | {0xcc, 0xd8}, | ||
797 | {0xcd, 0xf1}, | ||
798 | {0x4f, 0x98}, /* matrix */ | ||
799 | {0x50, 0x98}, | ||
800 | {0x51, 0x00}, | ||
801 | {0x52, 0x28}, | ||
802 | {0x53, 0x70}, | ||
803 | {0x54, 0x98}, | ||
804 | {0x58, 0x1a}, | ||
805 | {0xff, 0x41}, /* read 41, write ff 00 */ | ||
806 | {0x41, 0x40}, /* com16 */ | ||
807 | |||
808 | {0xc5, 0x03}, /* 60 Hz banding filter */ | ||
809 | {0x6a, 0x02}, /* 50 Hz banding filter */ | ||
810 | |||
811 | {0x12, 0x62}, /* com7 - 30fps VGA YUV */ | ||
812 | {0x36, 0xfa}, /* aref3 */ | ||
813 | {0x69, 0x0a}, /* hv */ | ||
814 | {0x8c, 0x89}, /* com22 */ | ||
815 | {0x14, 0x28}, /* com9 */ | ||
816 | {0x3e, 0x0c}, | ||
817 | {0x41, 0x40}, /* com16 */ | ||
818 | {0x72, 0x00}, | ||
819 | {0x73, 0x00}, | ||
820 | {0x74, 0x3a}, | ||
821 | {0x75, 0x35}, | ||
822 | {0x76, 0x01}, | ||
823 | {0xc7, 0x80}, | ||
824 | {0x03, 0x12}, /* vref */ | ||
825 | {0x17, 0x16}, /* hstart */ | ||
826 | {0x18, 0x02}, /* hstop */ | ||
827 | {0x19, 0x01}, /* vstrt */ | ||
828 | {0x1a, 0x3d}, /* vstop */ | ||
829 | {0x32, 0xff}, /* href */ | ||
830 | {0xc0, 0xaa}, | ||
831 | }; | ||
832 | |||
833 | static const u8 bridge_init_ov965x_2[][2] = { | ||
834 | {0x94, 0xaa}, | ||
835 | {0xf1, 0x60}, | ||
836 | {0xe5, 0x04}, | ||
837 | {0xc0, 0x50}, | ||
838 | {0xc1, 0x3c}, | ||
839 | {0x8c, 0x00}, | ||
840 | {0x8d, 0x1c}, | ||
841 | {0x34, 0x05}, | ||
842 | |||
843 | {0xc2, 0x0c}, | ||
844 | {0xc3, 0xf9}, | ||
845 | {0xda, 0x01}, | ||
846 | {0x50, 0x00}, | ||
847 | {0x51, 0xa0}, | ||
848 | {0x52, 0x3c}, | ||
849 | {0x53, 0x00}, | ||
850 | {0x54, 0x00}, | ||
851 | {0x55, 0x00}, | ||
852 | {0x57, 0x00}, | ||
853 | {0x5c, 0x00}, | ||
854 | {0x5a, 0xa0}, | ||
855 | {0x5b, 0x78}, | ||
856 | {0x35, 0x02}, | ||
857 | {0xd9, 0x10}, | ||
858 | {0x94, 0x11}, | ||
859 | }; | ||
860 | |||
861 | static const u8 sensor_init_ov965x_2[][2] = { | ||
862 | {0x3b, 0xc4}, | ||
863 | {0x1e, 0x04}, /* mvfp */ | ||
864 | {0x13, 0xe0}, /* com8 */ | ||
865 | {0x00, 0x00}, /* gain */ | ||
866 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
867 | {0x11, 0x03}, /* clkrc */ | ||
868 | {0x6b, 0x5a}, /* dblv */ | ||
869 | {0x6a, 0x05}, | ||
870 | {0xc5, 0x07}, | ||
871 | {0xa2, 0x4b}, | ||
872 | {0xa3, 0x3e}, | ||
873 | {0x2d, 0x00}, | ||
874 | {0xff, 0x42}, /* read 42, write ff 00 */ | ||
875 | {0x42, 0xc0}, /* com17 */ | ||
876 | {0x2d, 0x00}, | ||
877 | {0xff, 0x42}, /* read 42, write ff 00 */ | ||
878 | {0x42, 0xc1}, /* com17 */ | ||
879 | /* sharpness */ | ||
880 | {0x3f, 0x01}, | ||
881 | {0xff, 0x42}, /* read 42, write ff 00 */ | ||
882 | {0x42, 0xc1}, /* com17 */ | ||
883 | /* saturation */ | ||
884 | {0x4f, 0x98}, /* matrix */ | ||
885 | {0x50, 0x98}, | ||
886 | {0x51, 0x00}, | ||
887 | {0x52, 0x28}, | ||
888 | {0x53, 0x70}, | ||
889 | {0x54, 0x98}, | ||
890 | {0x58, 0x1a}, | ||
891 | {0xff, 0x41}, /* read 41, write ff 00 */ | ||
892 | {0x41, 0x40}, /* com16 */ | ||
893 | /* contrast */ | ||
894 | {0x56, 0x40}, | ||
895 | /* brightness */ | ||
896 | {0x55, 0x8f}, | ||
897 | /* expo */ | ||
898 | {0x10, 0x25}, /* aech - exposure high bits */ | ||
899 | {0xff, 0x13}, /* read 13, write ff 00 */ | ||
900 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
901 | }; | ||
902 | |||
903 | static const u8 sensor_start_ov965x_1_vga[][2] = { /* same for qvga */ | ||
904 | {0x12, 0x62}, /* com7 - 30fps VGA YUV */ | ||
905 | {0x36, 0xfa}, /* aref3 */ | ||
906 | {0x69, 0x0a}, /* hv */ | ||
907 | {0x8c, 0x89}, /* com22 */ | ||
908 | {0x14, 0x28}, /* com9 */ | ||
909 | {0x3e, 0x0c}, /* com14 */ | ||
910 | {0x41, 0x40}, /* com16 */ | ||
911 | {0x72, 0x00}, | ||
912 | {0x73, 0x00}, | ||
913 | {0x74, 0x3a}, | ||
914 | {0x75, 0x35}, | ||
915 | {0x76, 0x01}, | ||
916 | {0xc7, 0x80}, /* com24 */ | ||
917 | {0x03, 0x12}, /* vref */ | ||
918 | {0x17, 0x16}, /* hstart */ | ||
919 | {0x18, 0x02}, /* hstop */ | ||
920 | {0x19, 0x01}, /* vstrt */ | ||
921 | {0x1a, 0x3d}, /* vstop */ | ||
922 | {0x32, 0xff}, /* href */ | ||
923 | {0xc0, 0xaa}, | ||
924 | }; | ||
925 | |||
926 | static const u8 sensor_start_ov965x_1_svga[][2] = { | ||
927 | {0x12, 0x02}, /* com7 - YUYV - VGA 15 full resolution */ | ||
928 | {0x36, 0xf8}, /* aref3 */ | ||
929 | {0x69, 0x02}, /* hv */ | ||
930 | {0x8c, 0x0d}, /* com22 */ | ||
931 | {0x3e, 0x0c}, /* com14 */ | ||
932 | {0x41, 0x40}, /* com16 */ | ||
933 | {0x72, 0x00}, | ||
934 | {0x73, 0x01}, | ||
935 | {0x74, 0x3a}, | ||
936 | {0x75, 0x35}, | ||
937 | {0x76, 0x01}, | ||
938 | {0xc7, 0x80}, /* com24 */ | ||
939 | {0x03, 0x1b}, /* vref */ | ||
940 | {0x17, 0x1d}, /* hstart */ | ||
941 | {0x18, 0xbd}, /* hstop */ | ||
942 | {0x19, 0x01}, /* vstrt */ | ||
943 | {0x1a, 0x81}, /* vstop */ | ||
944 | {0x32, 0xff}, /* href */ | ||
945 | {0xc0, 0xe2}, | ||
946 | }; | ||
947 | |||
948 | static const u8 sensor_start_ov965x_1_xga[][2] = { | ||
949 | {0x12, 0x02}, /* com7 */ | ||
950 | {0x36, 0xf8}, /* aref3 */ | ||
951 | {0x69, 0x02}, /* hv */ | ||
952 | {0x8c, 0x89}, /* com22 */ | ||
953 | {0x14, 0x28}, /* com9 */ | ||
954 | {0x3e, 0x0c}, /* com14 */ | ||
955 | {0x41, 0x40}, /* com16 */ | ||
956 | {0x72, 0x00}, | ||
957 | {0x73, 0x01}, | ||
958 | {0x74, 0x3a}, | ||
959 | {0x75, 0x35}, | ||
960 | {0x76, 0x01}, | ||
961 | {0xc7, 0x80}, /* com24 */ | ||
962 | {0x03, 0x1b}, /* vref */ | ||
963 | {0x17, 0x1d}, /* hstart */ | ||
964 | {0x18, 0xbd}, /* hstop */ | ||
965 | {0x19, 0x01}, /* vstrt */ | ||
966 | {0x1a, 0x81}, /* vstop */ | ||
967 | {0x32, 0xff}, /* href */ | ||
968 | {0xc0, 0xe2}, | ||
969 | }; | ||
970 | |||
971 | static const u8 sensor_start_ov965x_1_sxga[][2] = { | ||
972 | {0x12, 0x02}, /* com7 */ | ||
973 | {0x36, 0xf8}, /* aref3 */ | ||
974 | {0x69, 0x02}, /* hv */ | ||
975 | {0x8c, 0x89}, /* com22 */ | ||
976 | {0x14, 0x28}, /* com9 */ | ||
977 | {0x3e, 0x0c}, /* com14 */ | ||
978 | {0x41, 0x40}, /* com16 */ | ||
979 | {0x72, 0x00}, | ||
980 | {0x73, 0x01}, | ||
981 | {0x74, 0x3a}, | ||
982 | {0x75, 0x35}, | ||
983 | {0x76, 0x01}, | ||
984 | {0xc7, 0x80}, /* com24 */ | ||
985 | {0x03, 0x1b}, /* vref */ | ||
986 | {0x17, 0x1d}, /* hstart */ | ||
987 | {0x18, 0x02}, /* hstop */ | ||
988 | {0x19, 0x01}, /* vstrt */ | ||
989 | {0x1a, 0x81}, /* vstop */ | ||
990 | {0x32, 0xff}, /* href */ | ||
991 | {0xc0, 0xe2}, | ||
992 | }; | ||
993 | |||
994 | static const u8 bridge_start_ov965x_qvga[][2] = { | ||
995 | {0x94, 0xaa}, | ||
996 | {0xf1, 0x60}, | ||
997 | {0xe5, 0x04}, | ||
998 | {0xc0, 0x50}, | ||
999 | {0xc1, 0x3c}, | ||
1000 | {0x8c, 0x00}, | ||
1001 | {0x8d, 0x1c}, | ||
1002 | {0x34, 0x05}, | ||
1003 | |||
1004 | {0xc2, 0x4c}, | ||
1005 | {0xc3, 0xf9}, | ||
1006 | {0xda, 0x00}, | ||
1007 | {0x50, 0x00}, | ||
1008 | {0x51, 0xa0}, | ||
1009 | {0x52, 0x78}, | ||
1010 | {0x53, 0x00}, | ||
1011 | {0x54, 0x00}, | ||
1012 | {0x55, 0x00}, | ||
1013 | {0x57, 0x00}, | ||
1014 | {0x5c, 0x00}, | ||
1015 | {0x5a, 0x50}, | ||
1016 | {0x5b, 0x3c}, | ||
1017 | {0x35, 0x02}, | ||
1018 | {0xd9, 0x10}, | ||
1019 | {0x94, 0x11}, | ||
1020 | }; | ||
1021 | |||
1022 | static const u8 bridge_start_ov965x_vga[][2] = { | ||
1023 | {0x94, 0xaa}, | ||
1024 | {0xf1, 0x60}, | ||
1025 | {0xe5, 0x04}, | ||
1026 | {0xc0, 0x50}, | ||
1027 | {0xc1, 0x3c}, | ||
1028 | {0x8c, 0x00}, | ||
1029 | {0x8d, 0x1c}, | ||
1030 | {0x34, 0x05}, | ||
1031 | {0xc2, 0x0c}, | ||
1032 | {0xc3, 0xf9}, | ||
1033 | {0xda, 0x01}, | ||
1034 | {0x50, 0x00}, | ||
1035 | {0x51, 0xa0}, | ||
1036 | {0x52, 0x3c}, | ||
1037 | {0x53, 0x00}, | ||
1038 | {0x54, 0x00}, | ||
1039 | {0x55, 0x00}, | ||
1040 | {0x57, 0x00}, | ||
1041 | {0x5c, 0x00}, | ||
1042 | {0x5a, 0xa0}, | ||
1043 | {0x5b, 0x78}, | ||
1044 | {0x35, 0x02}, | ||
1045 | {0xd9, 0x10}, | ||
1046 | {0x94, 0x11}, | ||
1047 | }; | ||
1048 | |||
1049 | static const u8 bridge_start_ov965x_svga[][2] = { | ||
1050 | {0x94, 0xaa}, | ||
1051 | {0xf1, 0x60}, | ||
1052 | {0xe5, 0x04}, | ||
1053 | {0xc0, 0xa0}, | ||
1054 | {0xc1, 0x80}, | ||
1055 | {0x8c, 0x00}, | ||
1056 | {0x8d, 0x1c}, | ||
1057 | {0x34, 0x05}, | ||
1058 | {0xc2, 0x4c}, | ||
1059 | {0xc3, 0xf9}, | ||
1060 | {0x50, 0x00}, | ||
1061 | {0x51, 0x40}, | ||
1062 | {0x52, 0x00}, | ||
1063 | {0x53, 0x00}, | ||
1064 | {0x54, 0x00}, | ||
1065 | {0x55, 0x88}, | ||
1066 | {0x57, 0x00}, | ||
1067 | {0x5c, 0x00}, | ||
1068 | {0x5a, 0xc8}, | ||
1069 | {0x5b, 0x96}, | ||
1070 | {0x35, 0x02}, | ||
1071 | {0xd9, 0x10}, | ||
1072 | {0xda, 0x00}, | ||
1073 | {0x94, 0x11}, | ||
1074 | }; | ||
1075 | |||
1076 | static const u8 bridge_start_ov965x_xga[][2] = { | ||
1077 | {0x94, 0xaa}, | ||
1078 | {0xf1, 0x60}, | ||
1079 | {0xe5, 0x04}, | ||
1080 | {0xc0, 0xa0}, | ||
1081 | {0xc1, 0x80}, | ||
1082 | {0x8c, 0x00}, | ||
1083 | {0x8d, 0x1c}, | ||
1084 | {0x34, 0x05}, | ||
1085 | {0xc2, 0x4c}, | ||
1086 | {0xc3, 0xf9}, | ||
1087 | {0x50, 0x00}, | ||
1088 | {0x51, 0x40}, | ||
1089 | {0x52, 0x00}, | ||
1090 | {0x53, 0x00}, | ||
1091 | {0x54, 0x00}, | ||
1092 | {0x55, 0x88}, | ||
1093 | {0x57, 0x00}, | ||
1094 | {0x5c, 0x01}, | ||
1095 | {0x5a, 0x00}, | ||
1096 | {0x5b, 0xc0}, | ||
1097 | {0x35, 0x02}, | ||
1098 | {0xd9, 0x10}, | ||
1099 | {0xda, 0x01}, | ||
1100 | {0x94, 0x11}, | ||
1101 | }; | ||
1102 | |||
1103 | static const u8 bridge_start_ov965x_sxga[][2] = { | ||
1104 | {0x94, 0xaa}, | ||
1105 | {0xf1, 0x60}, | ||
1106 | {0xe5, 0x04}, | ||
1107 | {0xc0, 0xa0}, | ||
1108 | {0xc1, 0x80}, | ||
1109 | {0x8c, 0x00}, | ||
1110 | {0x8d, 0x1c}, | ||
1111 | {0x34, 0x05}, | ||
1112 | {0xc2, 0x0c}, | ||
1113 | {0xc3, 0xf9}, | ||
1114 | {0xda, 0x00}, | ||
1115 | {0x35, 0x02}, | ||
1116 | {0xd9, 0x10}, | ||
1117 | {0x94, 0x11}, | ||
1118 | }; | ||
1119 | |||
1120 | static const u8 sensor_start_ov965x_2_qvga[][2] = { | ||
1121 | {0x3b, 0xe4}, /* com11 - night mode 1/4 frame rate */ | ||
1122 | {0x1e, 0x04}, /* mvfp */ | ||
1123 | {0x13, 0xe0}, /* com8 */ | ||
1124 | {0x00, 0x00}, | ||
1125 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
1126 | {0x11, 0x01}, /* clkrc */ | ||
1127 | {0x6b, 0x5a}, /* dblv */ | ||
1128 | {0x6a, 0x02}, /* 50 Hz banding filter */ | ||
1129 | {0xc5, 0x03}, /* 60 Hz banding filter */ | ||
1130 | {0xa2, 0x96}, /* bd50 */ | ||
1131 | {0xa3, 0x7d}, /* bd60 */ | ||
1132 | |||
1133 | {0xff, 0x13}, /* read 13, write ff 00 */ | ||
1134 | {0x13, 0xe7}, | ||
1135 | {0x3a, 0x80}, /* tslb - yuyv */ | ||
1136 | }; | ||
1137 | |||
1138 | static const u8 sensor_start_ov965x_2_vga[][2] = { | ||
1139 | {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ | ||
1140 | {0x1e, 0x04}, /* mvfp */ | ||
1141 | {0x13, 0xe0}, /* com8 */ | ||
1142 | {0x00, 0x00}, | ||
1143 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
1144 | {0x11, 0x03}, /* clkrc */ | ||
1145 | {0x6b, 0x5a}, /* dblv */ | ||
1146 | {0x6a, 0x05}, /* 50 Hz banding filter */ | ||
1147 | {0xc5, 0x07}, /* 60 Hz banding filter */ | ||
1148 | {0xa2, 0x4b}, /* bd50 */ | ||
1149 | {0xa3, 0x3e}, /* bd60 */ | ||
1150 | |||
1151 | {0x2d, 0x00}, /* advfl */ | ||
1152 | }; | ||
1153 | |||
1154 | static const u8 sensor_start_ov965x_2_svga[][2] = { /* same for xga */ | ||
1155 | {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ | ||
1156 | {0x1e, 0x04}, /* mvfp */ | ||
1157 | {0x13, 0xe0}, /* com8 */ | ||
1158 | {0x00, 0x00}, | ||
1159 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
1160 | {0x11, 0x01}, /* clkrc */ | ||
1161 | {0x6b, 0x5a}, /* dblv */ | ||
1162 | {0x6a, 0x0c}, /* 50 Hz banding filter */ | ||
1163 | {0xc5, 0x0f}, /* 60 Hz banding filter */ | ||
1164 | {0xa2, 0x4e}, /* bd50 */ | ||
1165 | {0xa3, 0x41}, /* bd60 */ | ||
1166 | }; | ||
1167 | |||
1168 | static const u8 sensor_start_ov965x_2_sxga[][2] = { | ||
1169 | {0x13, 0xe0}, /* com8 */ | ||
1170 | {0x00, 0x00}, | ||
1171 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
1172 | {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ | ||
1173 | {0x1e, 0x04}, /* mvfp */ | ||
1174 | {0x11, 0x01}, /* clkrc */ | ||
1175 | {0x6b, 0x5a}, /* dblv */ | ||
1176 | {0x6a, 0x0c}, /* 50 Hz banding filter */ | ||
1177 | {0xc5, 0x0f}, /* 60 Hz banding filter */ | ||
1178 | {0xa2, 0x4e}, /* bd50 */ | ||
1179 | {0xa3, 0x41}, /* bd60 */ | ||
1180 | }; | ||
1181 | |||
1182 | static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val) | 493 | static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val) |
1183 | { | 494 | { |
1184 | struct usb_device *udev = gspca_dev->dev; | 495 | struct usb_device *udev = gspca_dev->dev; |
@@ -1360,14 +671,14 @@ static void set_frame_rate(struct gspca_dev *gspca_dev) | |||
1360 | PDEBUG(D_PROBE, "frame_rate: %d", r->fps); | 671 | PDEBUG(D_PROBE, "frame_rate: %d", r->fps); |
1361 | } | 672 | } |
1362 | 673 | ||
1363 | static void setbrightness_77(struct gspca_dev *gspca_dev) | 674 | static void setbrightness(struct gspca_dev *gspca_dev) |
1364 | { | 675 | { |
1365 | struct sd *sd = (struct sd *) gspca_dev; | 676 | struct sd *sd = (struct sd *) gspca_dev; |
1366 | 677 | ||
1367 | sccb_reg_write(gspca_dev, 0x9B, sd->brightness); | 678 | sccb_reg_write(gspca_dev, 0x9B, sd->brightness); |
1368 | } | 679 | } |
1369 | 680 | ||
1370 | static void setcontrast_77(struct gspca_dev *gspca_dev) | 681 | static void setcontrast(struct gspca_dev *gspca_dev) |
1371 | { | 682 | { |
1372 | struct sd *sd = (struct sd *) gspca_dev; | 683 | struct sd *sd = (struct sd *) gspca_dev; |
1373 | 684 | ||
@@ -1401,7 +712,7 @@ static void setgain(struct gspca_dev *gspca_dev) | |||
1401 | sccb_reg_write(gspca_dev, 0x00, val); | 712 | sccb_reg_write(gspca_dev, 0x00, val); |
1402 | } | 713 | } |
1403 | 714 | ||
1404 | static void setexposure_77(struct gspca_dev *gspca_dev) | 715 | static void setexposure(struct gspca_dev *gspca_dev) |
1405 | { | 716 | { |
1406 | struct sd *sd = (struct sd *) gspca_dev; | 717 | struct sd *sd = (struct sd *) gspca_dev; |
1407 | u8 val; | 718 | u8 val; |
@@ -1432,7 +743,7 @@ static void sethue(struct gspca_dev *gspca_dev) | |||
1432 | sccb_reg_write(gspca_dev, 0x01, sd->hue); | 743 | sccb_reg_write(gspca_dev, 0x01, sd->hue); |
1433 | } | 744 | } |
1434 | 745 | ||
1435 | static void setautogain_77(struct gspca_dev *gspca_dev) | 746 | static void setautogain(struct gspca_dev *gspca_dev) |
1436 | { | 747 | { |
1437 | struct sd *sd = (struct sd *) gspca_dev; | 748 | struct sd *sd = (struct sd *) gspca_dev; |
1438 | 749 | ||
@@ -1457,7 +768,7 @@ static void setawb(struct gspca_dev *gspca_dev) | |||
1457 | sccb_reg_write(gspca_dev, 0x63, 0xaa); /* AWB off */ | 768 | sccb_reg_write(gspca_dev, 0x63, 0xaa); /* AWB off */ |
1458 | } | 769 | } |
1459 | 770 | ||
1460 | static void setsharpness_77(struct gspca_dev *gspca_dev) | 771 | static void setsharpness(struct gspca_dev *gspca_dev) |
1461 | { | 772 | { |
1462 | struct sd *sd = (struct sd *) gspca_dev; | 773 | struct sd *sd = (struct sd *) gspca_dev; |
1463 | u8 val; | 774 | u8 val; |
@@ -1491,132 +802,6 @@ static void setvflip(struct gspca_dev *gspca_dev) | |||
1491 | sccb_reg_read(gspca_dev, 0x0c) & 0x7f); | 802 | sccb_reg_read(gspca_dev, 0x0c) & 0x7f); |
1492 | } | 803 | } |
1493 | 804 | ||
1494 | /* ov965x specific controls */ | ||
1495 | static void setbrightness_96(struct gspca_dev *gspca_dev) | ||
1496 | { | ||
1497 | struct sd *sd = (struct sd *) gspca_dev; | ||
1498 | u8 val; | ||
1499 | |||
1500 | val = sd->brightness; | ||
1501 | if (val < 8) | ||
1502 | val = 15 - val; /* f .. 8 */ | ||
1503 | else | ||
1504 | val = val - 8; /* 0 .. 7 */ | ||
1505 | sccb_reg_write(gspca_dev, 0x55, /* brtn - brightness adjustment */ | ||
1506 | 0x0f | (val << 4)); | ||
1507 | } | ||
1508 | |||
1509 | static void setcontrast_96(struct gspca_dev *gspca_dev) | ||
1510 | { | ||
1511 | struct sd *sd = (struct sd *) gspca_dev; | ||
1512 | |||
1513 | sccb_reg_write(gspca_dev, 0x56, /* cnst1 - contrast 1 ctrl coeff */ | ||
1514 | sd->contrast << 4); | ||
1515 | } | ||
1516 | |||
1517 | static void setexposure_96(struct gspca_dev *gspca_dev) | ||
1518 | { | ||
1519 | struct sd *sd = (struct sd *) gspca_dev; | ||
1520 | u8 val; | ||
1521 | static const u8 expo[4] = {0x00, 0x25, 0x38, 0x5e}; | ||
1522 | |||
1523 | sccb_reg_write(gspca_dev, 0x10, /* aec[9:2] */ | ||
1524 | expo[sd->exposure]); | ||
1525 | val = sccb_reg_read(gspca_dev, 0x13); /* com8 */ | ||
1526 | sccb_reg_write(gspca_dev, 0xff, 0x00); | ||
1527 | sccb_reg_write(gspca_dev, 0x13, val); | ||
1528 | val = sccb_reg_read(gspca_dev, 0xa1); /* aech */ | ||
1529 | sccb_reg_write(gspca_dev, 0xff, 0x00); | ||
1530 | sccb_reg_write(gspca_dev, 0xa1, val & 0xe0); /* aec[15:10] = 0 */ | ||
1531 | } | ||
1532 | |||
1533 | static void setsharpness_96(struct gspca_dev *gspca_dev) | ||
1534 | { | ||
1535 | struct sd *sd = (struct sd *) gspca_dev; | ||
1536 | s8 val; | ||
1537 | |||
1538 | val = sd->sharpness; | ||
1539 | if (val < 0) { /* auto */ | ||
1540 | val = sccb_reg_read(gspca_dev, 0x42); /* com17 */ | ||
1541 | sccb_reg_write(gspca_dev, 0xff, 0x00); | ||
1542 | sccb_reg_write(gspca_dev, 0x42, val | 0x40); | ||
1543 | /* Edge enhancement strength auto adjust */ | ||
1544 | return; | ||
1545 | } | ||
1546 | if (val != 0) | ||
1547 | val = 1 << (val - 1); | ||
1548 | sccb_reg_write(gspca_dev, 0x3f, /* edge - edge enhance. factor */ | ||
1549 | val); | ||
1550 | val = sccb_reg_read(gspca_dev, 0x42); /* com17 */ | ||
1551 | sccb_reg_write(gspca_dev, 0xff, 0x00); | ||
1552 | sccb_reg_write(gspca_dev, 0x42, val & 0xbf); | ||
1553 | } | ||
1554 | |||
1555 | static void setautogain_96(struct gspca_dev *gspca_dev) | ||
1556 | { | ||
1557 | struct sd *sd = (struct sd *) gspca_dev; | ||
1558 | u8 val; | ||
1559 | |||
1560 | /*fixme: should adjust agc/awb/aec by different controls */ | ||
1561 | val = sd->autogain; | ||
1562 | val = sccb_reg_read(gspca_dev, 0x13); /* com8 */ | ||
1563 | sccb_reg_write(gspca_dev, 0xff, 0x00); | ||
1564 | if (sd->autogain) | ||
1565 | val |= 0x05; /* agc & aec */ | ||
1566 | else | ||
1567 | val &= 0xfa; | ||
1568 | sccb_reg_write(gspca_dev, 0x13, val); | ||
1569 | } | ||
1570 | |||
1571 | static void setsatur(struct gspca_dev *gspca_dev) | ||
1572 | { | ||
1573 | struct sd *sd = (struct sd *) gspca_dev; | ||
1574 | u8 val1, val2, val3; | ||
1575 | static const u8 matrix[5][2] = { | ||
1576 | {0x14, 0x38}, | ||
1577 | {0x1e, 0x54}, | ||
1578 | {0x28, 0x70}, | ||
1579 | {0x32, 0x8c}, | ||
1580 | {0x48, 0x90} | ||
1581 | }; | ||
1582 | |||
1583 | val1 = matrix[sd->satur][0]; | ||
1584 | val2 = matrix[sd->satur][1]; | ||
1585 | val3 = val1 + val2; | ||
1586 | sccb_reg_write(gspca_dev, 0x4f, val3); /* matrix coeff */ | ||
1587 | sccb_reg_write(gspca_dev, 0x50, val3); | ||
1588 | sccb_reg_write(gspca_dev, 0x51, 0x00); | ||
1589 | sccb_reg_write(gspca_dev, 0x52, val1); | ||
1590 | sccb_reg_write(gspca_dev, 0x53, val2); | ||
1591 | sccb_reg_write(gspca_dev, 0x54, val3); | ||
1592 | sccb_reg_write(gspca_dev, 0x58, 0x1a); /* mtxs - coeff signs */ | ||
1593 | val1 = sccb_reg_read(gspca_dev, 0x41); /* com16 */ | ||
1594 | sccb_reg_write(gspca_dev, 0xff, 0x00); | ||
1595 | sccb_reg_write(gspca_dev, 0x41, val1); | ||
1596 | } | ||
1597 | |||
1598 | static void setfreq(struct gspca_dev *gspca_dev) | ||
1599 | { | ||
1600 | struct sd *sd = (struct sd *) gspca_dev; | ||
1601 | u8 val; | ||
1602 | |||
1603 | val = sccb_reg_read(gspca_dev, 0x13); /* com8 */ | ||
1604 | sccb_reg_write(gspca_dev, 0xff, 0x00); | ||
1605 | if (sd->lightfreq == 0) { | ||
1606 | sccb_reg_write(gspca_dev, 0x13, val & 0xdf); | ||
1607 | return; | ||
1608 | } | ||
1609 | sccb_reg_write(gspca_dev, 0x13, val | 0x20); | ||
1610 | |||
1611 | val = sccb_reg_read(gspca_dev, 0x42); /* com17 */ | ||
1612 | sccb_reg_write(gspca_dev, 0xff, 0x00); | ||
1613 | if (sd->lightfreq == 1) | ||
1614 | val |= 0x01; | ||
1615 | else | ||
1616 | val &= 0xfe; | ||
1617 | sccb_reg_write(gspca_dev, 0x42, val); | ||
1618 | } | ||
1619 | |||
1620 | /* this function is called at probe time */ | 805 | /* this function is called at probe time */ |
1621 | static int sd_config(struct gspca_dev *gspca_dev, | 806 | static int sd_config(struct gspca_dev *gspca_dev, |
1622 | const struct usb_device_id *id) | 807 | const struct usb_device_id *id) |
@@ -1624,77 +809,50 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1624 | struct sd *sd = (struct sd *) gspca_dev; | 809 | struct sd *sd = (struct sd *) gspca_dev; |
1625 | struct cam *cam; | 810 | struct cam *cam; |
1626 | 811 | ||
1627 | sd->sensor = id->driver_info; | ||
1628 | |||
1629 | cam = &gspca_dev->cam; | 812 | cam = &gspca_dev->cam; |
1630 | 813 | ||
1631 | if (sd->sensor == SENSOR_OV772X) { | 814 | cam->cam_mode = ov772x_mode; |
1632 | cam->cam_mode = ov772x_mode; | 815 | cam->nmodes = ARRAY_SIZE(ov772x_mode); |
1633 | cam->nmodes = ARRAY_SIZE(ov772x_mode); | 816 | cam->mode_framerates = ov772x_framerates; |
1634 | 817 | ||
1635 | cam->bulk = 1; | 818 | cam->bulk = 1; |
1636 | cam->bulk_size = 16384; | 819 | cam->bulk_size = 16384; |
1637 | cam->bulk_nurbs = 2; | 820 | cam->bulk_nurbs = 2; |
1638 | } else { /* ov965x */ | ||
1639 | cam->cam_mode = ov965x_mode; | ||
1640 | cam->nmodes = ARRAY_SIZE(ov965x_mode); | ||
1641 | } | ||
1642 | 821 | ||
1643 | sd->frame_rate = 30; | 822 | sd->frame_rate = 30; |
1644 | 823 | ||
1645 | if (sd->sensor == SENSOR_OV772X) { | 824 | sd->brightness = BRIGHTNESS_DEF; |
1646 | sd->brightness = BRIGHTNESS_77_DEF; | 825 | sd->contrast = CONTRAST_DEF; |
1647 | sd->contrast = CONTRAST_77_DEF; | 826 | sd->gain = GAIN_DEF; |
1648 | sd->gain = GAIN_DEF; | 827 | sd->exposure = EXPO_DEF; |
1649 | sd->exposure = EXPO_77_DEF; | 828 | sd->redblc = RED_BALANCE_DEF; |
1650 | sd->redblc = RED_BALANCE_DEF; | 829 | sd->blueblc = BLUE_BALANCE_DEF; |
1651 | sd->blueblc = BLUE_BALANCE_DEF; | 830 | sd->hue = HUE_DEF; |
1652 | sd->hue = HUE_DEF; | 831 | #if AUTOGAIN_DEF != 0 |
1653 | #if AUTOGAIN_77_DEF != 0 | 832 | sd->autogain = AUTOGAIN_DEF; |
1654 | sd->autogain = AUTOGAIN_77_DEF; | ||
1655 | #else | 833 | #else |
1656 | gspca_dev->ctrl_inac |= (1 << AWB_77_IDX); | 834 | gspca_dev->ctrl_inac |= (1 << AWB_IDX); |
1657 | #endif | 835 | #endif |
1658 | #if AWB_DEF != 0 | 836 | #if AWB_DEF != 0 |
1659 | sd->awb = AWB_DEF | 837 | sd->awb = AWB_DEF |
1660 | #endif | 838 | #endif |
1661 | #if SHARPNESS_77_DEF != 0 | 839 | #if SHARPNESS_DEF != 0 |
1662 | sd->sharpness = SHARPNESS_77_DEF; | 840 | sd->sharpness = SHARPNESS_DEF; |
1663 | #endif | 841 | #endif |
1664 | #if HFLIP_DEF != 0 | 842 | #if HFLIP_DEF != 0 |
1665 | sd->hflip = HFLIP_DEF; | 843 | sd->hflip = HFLIP_DEF; |
1666 | #endif | 844 | #endif |
1667 | #if VFLIP_DEF != 0 | 845 | #if VFLIP_DEF != 0 |
1668 | sd->vflip = VFLIP_DEF; | 846 | sd->vflip = VFLIP_DEF; |
1669 | #endif | ||
1670 | } else { | ||
1671 | sd->brightness = BRIGHTNESS_96_DEF; | ||
1672 | sd->contrast = CONTRAST_96_DEF; | ||
1673 | #if AUTOGAIN_96_DEF != 0 | ||
1674 | sd->autogain = AUTOGAIN_96_DEF; | ||
1675 | gspca_dev->ctrl_inac |= (1 << EXPO_96_IDX); | ||
1676 | #endif | 847 | #endif |
1677 | #if EXPO_96_DEF != 0 | 848 | |
1678 | sd->exposure = EXPO_96_DEF; | ||
1679 | #endif | ||
1680 | #if SHARPNESS_96_DEF != 0 | ||
1681 | sd->sharpness = SHARPNESS_96_DEF; | ||
1682 | #endif | ||
1683 | sd->satur = SATUR_DEF; | ||
1684 | sd->lightfreq = FREQ_DEF; | ||
1685 | } | ||
1686 | return 0; | 849 | return 0; |
1687 | } | 850 | } |
1688 | 851 | ||
1689 | /* this function is called at probe and resume time */ | 852 | /* this function is called at probe and resume time */ |
1690 | static int sd_init(struct gspca_dev *gspca_dev) | 853 | static int sd_init(struct gspca_dev *gspca_dev) |
1691 | { | 854 | { |
1692 | struct sd *sd = (struct sd *) gspca_dev; | ||
1693 | u16 sensor_id; | 855 | u16 sensor_id; |
1694 | static const u8 sensor_addr[2] = { | ||
1695 | 0x42, /* 0 SENSOR_OV772X */ | ||
1696 | 0x60, /* 1 SENSOR_OV965X */ | ||
1697 | }; | ||
1698 | 856 | ||
1699 | /* reset bridge */ | 857 | /* reset bridge */ |
1700 | ov534_reg_write(gspca_dev, 0xe7, 0x3a); | 858 | ov534_reg_write(gspca_dev, 0xe7, 0x3a); |
@@ -1702,8 +860,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1702 | msleep(100); | 860 | msleep(100); |
1703 | 861 | ||
1704 | /* initialize the sensor address */ | 862 | /* initialize the sensor address */ |
1705 | ov534_reg_write(gspca_dev, OV534_REG_ADDRESS, | 863 | ov534_reg_write(gspca_dev, OV534_REG_ADDRESS, 0x42); |
1706 | sensor_addr[sd->sensor]); | ||
1707 | 864 | ||
1708 | /* reset sensor */ | 865 | /* reset sensor */ |
1709 | sccb_reg_write(gspca_dev, 0x12, 0x80); | 866 | sccb_reg_write(gspca_dev, 0x12, 0x80); |
@@ -1717,64 +874,46 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1717 | PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id); | 874 | PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id); |
1718 | 875 | ||
1719 | /* initialize */ | 876 | /* initialize */ |
1720 | switch (sd->sensor) { | 877 | reg_w_array(gspca_dev, bridge_init, |
1721 | case SENSOR_OV772X: | 878 | ARRAY_SIZE(bridge_init)); |
1722 | reg_w_array(gspca_dev, bridge_init_ov772x, | 879 | ov534_set_led(gspca_dev, 1); |
1723 | ARRAY_SIZE(bridge_init_ov772x)); | 880 | sccb_w_array(gspca_dev, sensor_init, |
1724 | ov534_set_led(gspca_dev, 1); | 881 | ARRAY_SIZE(sensor_init)); |
1725 | sccb_w_array(gspca_dev, sensor_init_ov772x, | 882 | ov534_reg_write(gspca_dev, 0xe0, 0x09); |
1726 | ARRAY_SIZE(sensor_init_ov772x)); | 883 | ov534_set_led(gspca_dev, 0); |
1727 | ov534_reg_write(gspca_dev, 0xe0, 0x09); | 884 | set_frame_rate(gspca_dev); |
1728 | ov534_set_led(gspca_dev, 0); | ||
1729 | set_frame_rate(gspca_dev); | ||
1730 | break; | ||
1731 | default: | ||
1732 | /* case SENSOR_OV965X: */ | ||
1733 | reg_w_array(gspca_dev, bridge_init_ov965x, | ||
1734 | ARRAY_SIZE(bridge_init_ov965x)); | ||
1735 | sccb_w_array(gspca_dev, sensor_init_ov965x, | ||
1736 | ARRAY_SIZE(sensor_init_ov965x)); | ||
1737 | reg_w_array(gspca_dev, bridge_init_ov965x_2, | ||
1738 | ARRAY_SIZE(bridge_init_ov965x_2)); | ||
1739 | sccb_w_array(gspca_dev, sensor_init_ov965x_2, | ||
1740 | ARRAY_SIZE(sensor_init_ov965x_2)); | ||
1741 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | ||
1742 | ov534_reg_write(gspca_dev, 0xe0, 0x01); | ||
1743 | ov534_set_led(gspca_dev, 0); | ||
1744 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | ||
1745 | } | ||
1746 | 885 | ||
1747 | return 0; | 886 | return 0; |
1748 | } | 887 | } |
1749 | 888 | ||
1750 | static int sd_start_ov772x(struct gspca_dev *gspca_dev) | 889 | static int sd_start(struct gspca_dev *gspca_dev) |
1751 | { | 890 | { |
1752 | int mode; | 891 | int mode; |
1753 | 892 | ||
1754 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; | 893 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; |
1755 | if (mode != 0) { /* 320x240 */ | 894 | if (mode != 0) { /* 320x240 */ |
1756 | reg_w_array(gspca_dev, bridge_start_ov772x_qvga, | 895 | reg_w_array(gspca_dev, bridge_start_qvga, |
1757 | ARRAY_SIZE(bridge_start_ov772x_qvga)); | 896 | ARRAY_SIZE(bridge_start_qvga)); |
1758 | sccb_w_array(gspca_dev, sensor_start_ov772x_qvga, | 897 | sccb_w_array(gspca_dev, sensor_start_qvga, |
1759 | ARRAY_SIZE(sensor_start_ov772x_qvga)); | 898 | ARRAY_SIZE(sensor_start_qvga)); |
1760 | } else { /* 640x480 */ | 899 | } else { /* 640x480 */ |
1761 | reg_w_array(gspca_dev, bridge_start_ov772x_vga, | 900 | reg_w_array(gspca_dev, bridge_start_vga, |
1762 | ARRAY_SIZE(bridge_start_ov772x_vga)); | 901 | ARRAY_SIZE(bridge_start_vga)); |
1763 | sccb_w_array(gspca_dev, sensor_start_ov772x_vga, | 902 | sccb_w_array(gspca_dev, sensor_start_vga, |
1764 | ARRAY_SIZE(sensor_start_ov772x_vga)); | 903 | ARRAY_SIZE(sensor_start_vga)); |
1765 | } | 904 | } |
1766 | set_frame_rate(gspca_dev); | 905 | set_frame_rate(gspca_dev); |
1767 | 906 | ||
1768 | setautogain_77(gspca_dev); | 907 | setautogain(gspca_dev); |
1769 | setawb(gspca_dev); | 908 | setawb(gspca_dev); |
1770 | setgain(gspca_dev); | 909 | setgain(gspca_dev); |
1771 | setredblc(gspca_dev); | 910 | setredblc(gspca_dev); |
1772 | setblueblc(gspca_dev); | 911 | setblueblc(gspca_dev); |
1773 | sethue(gspca_dev); | 912 | sethue(gspca_dev); |
1774 | setexposure_77(gspca_dev); | 913 | setexposure(gspca_dev); |
1775 | setbrightness_77(gspca_dev); | 914 | setbrightness(gspca_dev); |
1776 | setcontrast_77(gspca_dev); | 915 | setcontrast(gspca_dev); |
1777 | setsharpness_77(gspca_dev); | 916 | setsharpness(gspca_dev); |
1778 | setvflip(gspca_dev); | 917 | setvflip(gspca_dev); |
1779 | sethflip(gspca_dev); | 918 | sethflip(gspca_dev); |
1780 | 919 | ||
@@ -1783,81 +922,12 @@ static int sd_start_ov772x(struct gspca_dev *gspca_dev) | |||
1783 | return 0; | 922 | return 0; |
1784 | } | 923 | } |
1785 | 924 | ||
1786 | static int sd_start_ov965x(struct gspca_dev *gspca_dev) | 925 | static void sd_stopN(struct gspca_dev *gspca_dev) |
1787 | { | ||
1788 | int mode; | ||
1789 | |||
1790 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; | ||
1791 | switch (mode) { | ||
1792 | default: | ||
1793 | /* case 4: * 320x240 */ | ||
1794 | sccb_w_array(gspca_dev, sensor_start_ov965x_1_vga, | ||
1795 | ARRAY_SIZE(sensor_start_ov965x_1_vga)); | ||
1796 | reg_w_array(gspca_dev, bridge_start_ov965x_qvga, | ||
1797 | ARRAY_SIZE(bridge_start_ov965x_qvga)); | ||
1798 | sccb_w_array(gspca_dev, sensor_start_ov965x_2_qvga, | ||
1799 | ARRAY_SIZE(sensor_start_ov965x_2_qvga)); | ||
1800 | break; | ||
1801 | case 3: /* 640x480 */ | ||
1802 | sccb_w_array(gspca_dev, sensor_start_ov965x_1_vga, | ||
1803 | ARRAY_SIZE(sensor_start_ov965x_1_vga)); | ||
1804 | reg_w_array(gspca_dev, bridge_start_ov965x_vga, | ||
1805 | ARRAY_SIZE(bridge_start_ov965x_vga)); | ||
1806 | sccb_w_array(gspca_dev, sensor_start_ov965x_2_vga, | ||
1807 | ARRAY_SIZE(sensor_start_ov965x_2_vga)); | ||
1808 | break; | ||
1809 | case 2: /* 800x600 */ | ||
1810 | sccb_w_array(gspca_dev, sensor_start_ov965x_1_svga, | ||
1811 | ARRAY_SIZE(sensor_start_ov965x_1_svga)); | ||
1812 | reg_w_array(gspca_dev, bridge_start_ov965x_svga, | ||
1813 | ARRAY_SIZE(bridge_start_ov965x_svga)); | ||
1814 | sccb_w_array(gspca_dev, sensor_start_ov965x_2_svga, | ||
1815 | ARRAY_SIZE(sensor_start_ov965x_2_svga)); | ||
1816 | break; | ||
1817 | case 1: /* 1024x768 */ | ||
1818 | sccb_w_array(gspca_dev, sensor_start_ov965x_1_xga, | ||
1819 | ARRAY_SIZE(sensor_start_ov965x_1_xga)); | ||
1820 | reg_w_array(gspca_dev, bridge_start_ov965x_xga, | ||
1821 | ARRAY_SIZE(bridge_start_ov965x_xga)); | ||
1822 | sccb_w_array(gspca_dev, sensor_start_ov965x_2_svga, | ||
1823 | ARRAY_SIZE(sensor_start_ov965x_2_svga)); | ||
1824 | break; | ||
1825 | case 0: /* 1280x1024 */ | ||
1826 | sccb_w_array(gspca_dev, sensor_start_ov965x_1_sxga, | ||
1827 | ARRAY_SIZE(sensor_start_ov965x_1_sxga)); | ||
1828 | reg_w_array(gspca_dev, bridge_start_ov965x_sxga, | ||
1829 | ARRAY_SIZE(bridge_start_ov965x_sxga)); | ||
1830 | sccb_w_array(gspca_dev, sensor_start_ov965x_2_sxga, | ||
1831 | ARRAY_SIZE(sensor_start_ov965x_2_sxga)); | ||
1832 | break; | ||
1833 | } | ||
1834 | setfreq(gspca_dev); | ||
1835 | setautogain_96(gspca_dev); | ||
1836 | setbrightness_96(gspca_dev); | ||
1837 | setcontrast_96(gspca_dev); | ||
1838 | setexposure_96(gspca_dev); | ||
1839 | setsharpness_96(gspca_dev); | ||
1840 | setsatur(gspca_dev); | ||
1841 | |||
1842 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | ||
1843 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | ||
1844 | ov534_set_led(gspca_dev, 1); | ||
1845 | return 0; | ||
1846 | } | ||
1847 | |||
1848 | static void sd_stopN_ov772x(struct gspca_dev *gspca_dev) | ||
1849 | { | 926 | { |
1850 | ov534_reg_write(gspca_dev, 0xe0, 0x09); | 927 | ov534_reg_write(gspca_dev, 0xe0, 0x09); |
1851 | ov534_set_led(gspca_dev, 0); | 928 | ov534_set_led(gspca_dev, 0); |
1852 | } | 929 | } |
1853 | 930 | ||
1854 | static void sd_stopN_ov965x(struct gspca_dev *gspca_dev) | ||
1855 | { | ||
1856 | ov534_reg_write(gspca_dev, 0xe0, 0x01); | ||
1857 | ov534_set_led(gspca_dev, 0); | ||
1858 | ov534_reg_write(gspca_dev, 0xe0, 0x00); | ||
1859 | } | ||
1860 | |||
1861 | /* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */ | 931 | /* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */ |
1862 | #define UVC_STREAM_EOH (1 << 7) | 932 | #define UVC_STREAM_EOH (1 << 7) |
1863 | #define UVC_STREAM_ERR (1 << 6) | 933 | #define UVC_STREAM_ERR (1 << 6) |
@@ -1875,11 +945,9 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
1875 | __u32 this_pts; | 945 | __u32 this_pts; |
1876 | u16 this_fid; | 946 | u16 this_fid; |
1877 | int remaining_len = len; | 947 | int remaining_len = len; |
1878 | int payload_len; | ||
1879 | 948 | ||
1880 | payload_len = gspca_dev->cam.bulk ? 2048 : 2040; | ||
1881 | do { | 949 | do { |
1882 | len = min(remaining_len, payload_len); | 950 | len = min(remaining_len, 2048); |
1883 | 951 | ||
1884 | /* Payloads are prefixed with a UVC-style header. We | 952 | /* Payloads are prefixed with a UVC-style header. We |
1885 | consider a frame to start when the FID toggles, or the PTS | 953 | consider a frame to start when the FID toggles, or the PTS |
@@ -1918,7 +986,17 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
1918 | data + 12, len - 12); | 986 | data + 12, len - 12); |
1919 | /* If this packet is marked as EOF, end the frame */ | 987 | /* If this packet is marked as EOF, end the frame */ |
1920 | } else if (data[1] & UVC_STREAM_EOF) { | 988 | } else if (data[1] & UVC_STREAM_EOF) { |
989 | struct gspca_frame *frame; | ||
990 | |||
1921 | sd->last_pts = 0; | 991 | sd->last_pts = 0; |
992 | frame = gspca_get_i_frame(gspca_dev); | ||
993 | if (frame == NULL) | ||
994 | goto discard; | ||
995 | if (frame->data_end - frame->data + (len - 12) != | ||
996 | gspca_dev->width * gspca_dev->height * 2) { | ||
997 | PDEBUG(D_PACK, "wrong sized frame"); | ||
998 | goto discard; | ||
999 | } | ||
1922 | gspca_frame_add(gspca_dev, LAST_PACKET, | 1000 | gspca_frame_add(gspca_dev, LAST_PACKET, |
1923 | data + 12, len - 12); | 1001 | data + 12, len - 12); |
1924 | } else { | 1002 | } else { |
@@ -1965,12 +1043,8 @@ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) | |||
1965 | struct sd *sd = (struct sd *) gspca_dev; | 1043 | struct sd *sd = (struct sd *) gspca_dev; |
1966 | 1044 | ||
1967 | sd->exposure = val; | 1045 | sd->exposure = val; |
1968 | if (gspca_dev->streaming) { | 1046 | if (gspca_dev->streaming) |
1969 | if (sd->sensor == SENSOR_OV772X) | 1047 | setexposure(gspca_dev); |
1970 | setexposure_77(gspca_dev); | ||
1971 | else | ||
1972 | setexposure_96(gspca_dev); | ||
1973 | } | ||
1974 | return 0; | 1048 | return 0; |
1975 | } | 1049 | } |
1976 | 1050 | ||
@@ -1987,12 +1061,8 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | |||
1987 | struct sd *sd = (struct sd *) gspca_dev; | 1061 | struct sd *sd = (struct sd *) gspca_dev; |
1988 | 1062 | ||
1989 | sd->brightness = val; | 1063 | sd->brightness = val; |
1990 | if (gspca_dev->streaming) { | 1064 | if (gspca_dev->streaming) |
1991 | if (sd->sensor == SENSOR_OV772X) | 1065 | setbrightness(gspca_dev); |
1992 | setbrightness_77(gspca_dev); | ||
1993 | else | ||
1994 | setbrightness_96(gspca_dev); | ||
1995 | } | ||
1996 | return 0; | 1066 | return 0; |
1997 | } | 1067 | } |
1998 | 1068 | ||
@@ -2009,12 +1079,8 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | |||
2009 | struct sd *sd = (struct sd *) gspca_dev; | 1079 | struct sd *sd = (struct sd *) gspca_dev; |
2010 | 1080 | ||
2011 | sd->contrast = val; | 1081 | sd->contrast = val; |
2012 | if (gspca_dev->streaming) { | 1082 | if (gspca_dev->streaming) |
2013 | if (sd->sensor == SENSOR_OV772X) | 1083 | setcontrast(gspca_dev); |
2014 | setcontrast_77(gspca_dev); | ||
2015 | else | ||
2016 | setcontrast_96(gspca_dev); | ||
2017 | } | ||
2018 | return 0; | 1084 | return 0; |
2019 | } | 1085 | } |
2020 | 1086 | ||
@@ -2026,41 +1092,6 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | |||
2026 | return 0; | 1092 | return 0; |
2027 | } | 1093 | } |
2028 | 1094 | ||
2029 | static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val) | ||
2030 | { | ||
2031 | struct sd *sd = (struct sd *) gspca_dev; | ||
2032 | |||
2033 | sd->satur = val; | ||
2034 | if (gspca_dev->streaming) | ||
2035 | setsatur(gspca_dev); | ||
2036 | return 0; | ||
2037 | } | ||
2038 | |||
2039 | static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val) | ||
2040 | { | ||
2041 | struct sd *sd = (struct sd *) gspca_dev; | ||
2042 | |||
2043 | *val = sd->satur; | ||
2044 | return 0; | ||
2045 | } | ||
2046 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) | ||
2047 | { | ||
2048 | struct sd *sd = (struct sd *) gspca_dev; | ||
2049 | |||
2050 | sd->lightfreq = val; | ||
2051 | if (gspca_dev->streaming) | ||
2052 | setfreq(gspca_dev); | ||
2053 | return 0; | ||
2054 | } | ||
2055 | |||
2056 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val) | ||
2057 | { | ||
2058 | struct sd *sd = (struct sd *) gspca_dev; | ||
2059 | |||
2060 | *val = sd->lightfreq; | ||
2061 | return 0; | ||
2062 | } | ||
2063 | |||
2064 | static int sd_setredblc(struct gspca_dev *gspca_dev, __s32 val) | 1095 | static int sd_setredblc(struct gspca_dev *gspca_dev, __s32 val) |
2065 | { | 1096 | { |
2066 | struct sd *sd = (struct sd *) gspca_dev; | 1097 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -2122,22 +1153,14 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | |||
2122 | sd->autogain = val; | 1153 | sd->autogain = val; |
2123 | 1154 | ||
2124 | if (gspca_dev->streaming) { | 1155 | if (gspca_dev->streaming) { |
2125 | if (sd->sensor == SENSOR_OV772X) { | 1156 | |
2126 | 1157 | /* the auto white balance control works only | |
2127 | /* the auto white balance control works only | 1158 | * when auto gain is set */ |
2128 | * when auto gain is set */ | 1159 | if (val) |
2129 | if (val) | 1160 | gspca_dev->ctrl_inac &= ~(1 << AWB_IDX); |
2130 | gspca_dev->ctrl_inac &= ~(1 << AWB_77_IDX); | 1161 | else |
2131 | else | 1162 | gspca_dev->ctrl_inac |= (1 << AWB_IDX); |
2132 | gspca_dev->ctrl_inac |= (1 << AWB_77_IDX); | 1163 | setautogain(gspca_dev); |
2133 | setautogain_77(gspca_dev); | ||
2134 | } else { | ||
2135 | if (val) | ||
2136 | gspca_dev->ctrl_inac |= (1 << EXPO_96_IDX); | ||
2137 | else | ||
2138 | gspca_dev->ctrl_inac &= ~(1 << EXPO_96_IDX); | ||
2139 | setautogain_96(gspca_dev); | ||
2140 | } | ||
2141 | } | 1164 | } |
2142 | return 0; | 1165 | return 0; |
2143 | } | 1166 | } |
@@ -2173,12 +1196,8 @@ static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val) | |||
2173 | struct sd *sd = (struct sd *) gspca_dev; | 1196 | struct sd *sd = (struct sd *) gspca_dev; |
2174 | 1197 | ||
2175 | sd->sharpness = val; | 1198 | sd->sharpness = val; |
2176 | if (gspca_dev->streaming) { | 1199 | if (gspca_dev->streaming) |
2177 | if (sd->sensor == SENSOR_OV772X) | 1200 | setsharpness(gspca_dev); |
2178 | setsharpness_77(gspca_dev); | ||
2179 | else | ||
2180 | setsharpness_96(gspca_dev); | ||
2181 | } | ||
2182 | return 0; | 1201 | return 0; |
2183 | } | 1202 | } |
2184 | 1203 | ||
@@ -2257,7 +1276,7 @@ static int sd_set_streamparm(struct gspca_dev *gspca_dev, | |||
2257 | 1276 | ||
2258 | /* Set requested framerate */ | 1277 | /* Set requested framerate */ |
2259 | sd->frame_rate = tpf->denominator / tpf->numerator; | 1278 | sd->frame_rate = tpf->denominator / tpf->numerator; |
2260 | if (gspca_dev->streaming && sd->sensor == SENSOR_OV772X) | 1279 | if (gspca_dev->streaming) |
2261 | set_frame_rate(gspca_dev); | 1280 | set_frame_rate(gspca_dev); |
2262 | 1281 | ||
2263 | /* Return the actual framerate */ | 1282 | /* Return the actual framerate */ |
@@ -2267,57 +1286,23 @@ static int sd_set_streamparm(struct gspca_dev *gspca_dev, | |||
2267 | return 0; | 1286 | return 0; |
2268 | } | 1287 | } |
2269 | 1288 | ||
2270 | static int sd_querymenu(struct gspca_dev *gspca_dev, | ||
2271 | struct v4l2_querymenu *menu) | ||
2272 | { | ||
2273 | switch (menu->id) { | ||
2274 | case V4L2_CID_POWER_LINE_FREQUENCY: | ||
2275 | switch (menu->index) { | ||
2276 | case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */ | ||
2277 | strcpy((char *) menu->name, "NoFliker"); | ||
2278 | return 0; | ||
2279 | case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ | ||
2280 | strcpy((char *) menu->name, "50 Hz"); | ||
2281 | return 0; | ||
2282 | case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ | ||
2283 | strcpy((char *) menu->name, "60 Hz"); | ||
2284 | return 0; | ||
2285 | } | ||
2286 | break; | ||
2287 | } | ||
2288 | return -EINVAL; | ||
2289 | } | ||
2290 | |||
2291 | /* sub-driver description */ | 1289 | /* sub-driver description */ |
2292 | static const struct sd_desc sd_desc_ov772x = { | 1290 | static const struct sd_desc sd_desc = { |
2293 | .name = MODULE_NAME, | 1291 | .name = MODULE_NAME, |
2294 | .ctrls = sd_ctrls_ov772x, | 1292 | .ctrls = sd_ctrls, |
2295 | .nctrls = ARRAY_SIZE(sd_ctrls_ov772x), | 1293 | .nctrls = ARRAY_SIZE(sd_ctrls), |
2296 | .config = sd_config, | 1294 | .config = sd_config, |
2297 | .init = sd_init, | 1295 | .init = sd_init, |
2298 | .start = sd_start_ov772x, | 1296 | .start = sd_start, |
2299 | .stopN = sd_stopN_ov772x, | 1297 | .stopN = sd_stopN, |
2300 | .pkt_scan = sd_pkt_scan, | 1298 | .pkt_scan = sd_pkt_scan, |
2301 | .get_streamparm = sd_get_streamparm, | 1299 | .get_streamparm = sd_get_streamparm, |
2302 | .set_streamparm = sd_set_streamparm, | 1300 | .set_streamparm = sd_set_streamparm, |
2303 | }; | 1301 | }; |
2304 | 1302 | ||
2305 | static const struct sd_desc sd_desc_ov965x = { | ||
2306 | .name = MODULE_NAME, | ||
2307 | .ctrls = sd_ctrls_ov965x, | ||
2308 | .nctrls = ARRAY_SIZE(sd_ctrls_ov965x), | ||
2309 | .config = sd_config, | ||
2310 | .init = sd_init, | ||
2311 | .start = sd_start_ov965x, | ||
2312 | .stopN = sd_stopN_ov965x, | ||
2313 | .pkt_scan = sd_pkt_scan, | ||
2314 | .querymenu = sd_querymenu, | ||
2315 | }; | ||
2316 | |||
2317 | /* -- module initialisation -- */ | 1303 | /* -- module initialisation -- */ |
2318 | static const __devinitdata struct usb_device_id device_table[] = { | 1304 | static const __devinitdata struct usb_device_id device_table[] = { |
2319 | {USB_DEVICE(0x06f8, 0x3003), .driver_info = SENSOR_OV965X}, | 1305 | {USB_DEVICE(0x1415, 0x2000)}, |
2320 | {USB_DEVICE(0x1415, 0x2000), .driver_info = SENSOR_OV772X}, | ||
2321 | {} | 1306 | {} |
2322 | }; | 1307 | }; |
2323 | 1308 | ||
@@ -2326,11 +1311,7 @@ MODULE_DEVICE_TABLE(usb, device_table); | |||
2326 | /* -- device connect -- */ | 1311 | /* -- device connect -- */ |
2327 | static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id) | 1312 | static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id) |
2328 | { | 1313 | { |
2329 | return gspca_dev_probe(intf, id, | 1314 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), |
2330 | id->driver_info == SENSOR_OV772X | ||
2331 | ? &sd_desc_ov772x | ||
2332 | : &sd_desc_ov965x, | ||
2333 | sizeof(struct sd), | ||
2334 | THIS_MODULE); | 1315 | THIS_MODULE); |
2335 | } | 1316 | } |
2336 | 1317 | ||
diff --git a/drivers/media/video/gspca/ov534_9.c b/drivers/media/video/gspca/ov534_9.c new file mode 100644 index 000000000000..bbe5a030e3b4 --- /dev/null +++ b/drivers/media/video/gspca/ov534_9.c | |||
@@ -0,0 +1,1477 @@ | |||
1 | /* | ||
2 | * ov534-ov965x gspca driver | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Jean-Francois Moine http://moinejf.free.fr | ||
5 | * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it> | ||
6 | * Copyright (C) 2008 Jim Paris <jim@jtan.com> | ||
7 | * | ||
8 | * Based on a prototype written by Mark Ferrell <majortrips@gmail.com> | ||
9 | * USB protocol reverse engineered by Jim Paris <jim@jtan.com> | ||
10 | * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/ | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | */ | ||
26 | |||
27 | #define MODULE_NAME "ov534_9" | ||
28 | |||
29 | #include "gspca.h" | ||
30 | |||
31 | #define OV534_REG_ADDRESS 0xf1 /* sensor address */ | ||
32 | #define OV534_REG_SUBADDR 0xf2 | ||
33 | #define OV534_REG_WRITE 0xf3 | ||
34 | #define OV534_REG_READ 0xf4 | ||
35 | #define OV534_REG_OPERATION 0xf5 | ||
36 | #define OV534_REG_STATUS 0xf6 | ||
37 | |||
38 | #define OV534_OP_WRITE_3 0x37 | ||
39 | #define OV534_OP_WRITE_2 0x33 | ||
40 | #define OV534_OP_READ_2 0xf9 | ||
41 | |||
42 | #define CTRL_TIMEOUT 500 | ||
43 | |||
44 | MODULE_AUTHOR("Jean-Francois Moine <moinejf@free.fr>"); | ||
45 | MODULE_DESCRIPTION("GSPCA/OV534_9 USB Camera Driver"); | ||
46 | MODULE_LICENSE("GPL"); | ||
47 | |||
48 | /* specific webcam descriptor */ | ||
49 | struct sd { | ||
50 | struct gspca_dev gspca_dev; /* !! must be the first item */ | ||
51 | __u32 last_pts; | ||
52 | u8 last_fid; | ||
53 | |||
54 | u8 brightness; | ||
55 | u8 contrast; | ||
56 | u8 autogain; | ||
57 | u8 exposure; | ||
58 | s8 sharpness; | ||
59 | u8 satur; | ||
60 | u8 freq; | ||
61 | }; | ||
62 | |||
63 | /* V4L2 controls supported by the driver */ | ||
64 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
65 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
66 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
67 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
68 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
69 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | ||
70 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | ||
71 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
72 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); | ||
73 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | ||
74 | static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val); | ||
75 | static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val); | ||
76 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | ||
77 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | ||
78 | |||
79 | static const struct ctrl sd_ctrls[] = { | ||
80 | { /* 0 */ | ||
81 | { | ||
82 | .id = V4L2_CID_BRIGHTNESS, | ||
83 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
84 | .name = "Brightness", | ||
85 | .minimum = 0, | ||
86 | .maximum = 15, | ||
87 | .step = 1, | ||
88 | #define BRIGHTNESS_DEF 7 | ||
89 | .default_value = BRIGHTNESS_DEF, | ||
90 | }, | ||
91 | .set = sd_setbrightness, | ||
92 | .get = sd_getbrightness, | ||
93 | }, | ||
94 | { /* 1 */ | ||
95 | { | ||
96 | .id = V4L2_CID_CONTRAST, | ||
97 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
98 | .name = "Contrast", | ||
99 | .minimum = 0, | ||
100 | .maximum = 15, | ||
101 | .step = 1, | ||
102 | #define CONTRAST_DEF 3 | ||
103 | .default_value = CONTRAST_DEF, | ||
104 | }, | ||
105 | .set = sd_setcontrast, | ||
106 | .get = sd_getcontrast, | ||
107 | }, | ||
108 | { /* 2 */ | ||
109 | { | ||
110 | .id = V4L2_CID_AUTOGAIN, | ||
111 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
112 | .name = "Autogain", | ||
113 | .minimum = 0, | ||
114 | .maximum = 1, | ||
115 | .step = 1, | ||
116 | #define AUTOGAIN_DEF 1 | ||
117 | .default_value = AUTOGAIN_DEF, | ||
118 | }, | ||
119 | .set = sd_setautogain, | ||
120 | .get = sd_getautogain, | ||
121 | }, | ||
122 | #define EXPO_IDX 3 | ||
123 | { /* 3 */ | ||
124 | { | ||
125 | .id = V4L2_CID_EXPOSURE, | ||
126 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
127 | .name = "Exposure", | ||
128 | .minimum = 0, | ||
129 | .maximum = 3, | ||
130 | .step = 1, | ||
131 | #define EXPO_DEF 0 | ||
132 | .default_value = EXPO_DEF, | ||
133 | }, | ||
134 | .set = sd_setexposure, | ||
135 | .get = sd_getexposure, | ||
136 | }, | ||
137 | { /* 4 */ | ||
138 | { | ||
139 | .id = V4L2_CID_SHARPNESS, | ||
140 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
141 | .name = "Sharpness", | ||
142 | .minimum = -1, /* -1 = auto */ | ||
143 | .maximum = 4, | ||
144 | .step = 1, | ||
145 | #define SHARPNESS_DEF -1 | ||
146 | .default_value = SHARPNESS_DEF, | ||
147 | }, | ||
148 | .set = sd_setsharpness, | ||
149 | .get = sd_getsharpness, | ||
150 | }, | ||
151 | { /* 5 */ | ||
152 | { | ||
153 | .id = V4L2_CID_SATURATION, | ||
154 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
155 | .name = "Saturation", | ||
156 | .minimum = 0, | ||
157 | .maximum = 4, | ||
158 | .step = 1, | ||
159 | #define SATUR_DEF 2 | ||
160 | .default_value = SATUR_DEF, | ||
161 | }, | ||
162 | .set = sd_setsatur, | ||
163 | .get = sd_getsatur, | ||
164 | }, | ||
165 | { | ||
166 | { | ||
167 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | ||
168 | .type = V4L2_CTRL_TYPE_MENU, | ||
169 | .name = "Light frequency filter", | ||
170 | .minimum = 0, | ||
171 | .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ | ||
172 | .step = 1, | ||
173 | #define FREQ_DEF 0 | ||
174 | .default_value = FREQ_DEF, | ||
175 | }, | ||
176 | .set = sd_setfreq, | ||
177 | .get = sd_getfreq, | ||
178 | }, | ||
179 | }; | ||
180 | |||
181 | static const struct v4l2_pix_format ov965x_mode[] = { | ||
182 | #define QVGA_MODE 0 | ||
183 | {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
184 | .bytesperline = 320, | ||
185 | .sizeimage = 320 * 240 * 3 / 8 + 590, | ||
186 | .colorspace = V4L2_COLORSPACE_JPEG}, | ||
187 | #define VGA_MODE 1 | ||
188 | {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
189 | .bytesperline = 640, | ||
190 | .sizeimage = 640 * 480 * 3 / 8 + 590, | ||
191 | .colorspace = V4L2_COLORSPACE_JPEG}, | ||
192 | #define SVGA_MODE 2 | ||
193 | {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
194 | .bytesperline = 800, | ||
195 | .sizeimage = 800 * 600 * 3 / 8 + 590, | ||
196 | .colorspace = V4L2_COLORSPACE_JPEG}, | ||
197 | #define XGA_MODE 3 | ||
198 | {1024, 768, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
199 | .bytesperline = 1024, | ||
200 | .sizeimage = 1024 * 768 * 3 / 8 + 590, | ||
201 | .colorspace = V4L2_COLORSPACE_JPEG}, | ||
202 | #define SXGA_MODE 4 | ||
203 | {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
204 | .bytesperline = 1280, | ||
205 | .sizeimage = 1280 * 1024 * 3 / 8 + 590, | ||
206 | .colorspace = V4L2_COLORSPACE_JPEG}, | ||
207 | }; | ||
208 | |||
209 | static const u8 bridge_init[][2] = { | ||
210 | {0x88, 0xf8}, | ||
211 | {0x89, 0xff}, | ||
212 | {0x76, 0x03}, | ||
213 | {0x92, 0x03}, | ||
214 | {0x95, 0x10}, | ||
215 | {0xe2, 0x00}, | ||
216 | {0xe7, 0x3e}, | ||
217 | {0x8d, 0x1c}, | ||
218 | {0x8e, 0x00}, | ||
219 | {0x8f, 0x00}, | ||
220 | {0x1f, 0x00}, | ||
221 | {0xc3, 0xf9}, | ||
222 | {0x89, 0xff}, | ||
223 | {0x88, 0xf8}, | ||
224 | {0x76, 0x03}, | ||
225 | {0x92, 0x01}, | ||
226 | {0x93, 0x18}, | ||
227 | {0x1c, 0x0a}, | ||
228 | {0x1d, 0x48}, | ||
229 | {0xc0, 0x50}, | ||
230 | {0xc1, 0x3c}, | ||
231 | {0x34, 0x05}, | ||
232 | {0xc2, 0x0c}, | ||
233 | {0xc3, 0xf9}, | ||
234 | {0x34, 0x05}, | ||
235 | {0xe7, 0x2e}, | ||
236 | {0x31, 0xf9}, | ||
237 | {0x35, 0x02}, | ||
238 | {0xd9, 0x10}, | ||
239 | {0x25, 0x42}, | ||
240 | {0x94, 0x11}, | ||
241 | }; | ||
242 | |||
243 | static const u8 sensor_init[][2] = { | ||
244 | {0x12, 0x80}, /* com7 - SSCB reset */ | ||
245 | {0x00, 0x00}, /* gain */ | ||
246 | {0x01, 0x80}, /* blue */ | ||
247 | {0x02, 0x80}, /* red */ | ||
248 | {0x03, 0x1b}, /* vref */ | ||
249 | {0x04, 0x03}, /* com1 - exposure low bits */ | ||
250 | {0x0b, 0x57}, /* ver */ | ||
251 | {0x0e, 0x61}, /* com5 */ | ||
252 | {0x0f, 0x42}, /* com6 */ | ||
253 | {0x11, 0x00}, /* clkrc */ | ||
254 | {0x12, 0x02}, /* com7 - 15fps VGA YUYV */ | ||
255 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
256 | {0x14, 0x28}, /* com9 */ | ||
257 | {0x16, 0x24}, /* reg16 */ | ||
258 | {0x17, 0x1d}, /* hstart*/ | ||
259 | {0x18, 0xbd}, /* hstop */ | ||
260 | {0x19, 0x01}, /* vstrt */ | ||
261 | {0x1a, 0x81}, /* vstop*/ | ||
262 | {0x1e, 0x04}, /* mvfp */ | ||
263 | {0x24, 0x3c}, /* aew */ | ||
264 | {0x25, 0x36}, /* aeb */ | ||
265 | {0x26, 0x71}, /* vpt */ | ||
266 | {0x27, 0x08}, /* bbias */ | ||
267 | {0x28, 0x08}, /* gbbias */ | ||
268 | {0x29, 0x15}, /* gr com */ | ||
269 | {0x2a, 0x00}, /* exhch */ | ||
270 | {0x2b, 0x00}, /* exhcl */ | ||
271 | {0x2c, 0x08}, /* rbias */ | ||
272 | {0x32, 0xff}, /* href */ | ||
273 | {0x33, 0x00}, /* chlf */ | ||
274 | {0x34, 0x3f}, /* aref1 */ | ||
275 | {0x35, 0x00}, /* aref2 */ | ||
276 | {0x36, 0xf8}, /* aref3 */ | ||
277 | {0x38, 0x72}, /* adc2 */ | ||
278 | {0x39, 0x57}, /* aref4 */ | ||
279 | {0x3a, 0x80}, /* tslb - yuyv */ | ||
280 | {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ | ||
281 | {0x3d, 0x99}, /* com13 */ | ||
282 | {0x3f, 0xc1}, /* edge */ | ||
283 | {0x40, 0xc0}, /* com15 */ | ||
284 | {0x41, 0x40}, /* com16 */ | ||
285 | {0x42, 0xc0}, /* com17 */ | ||
286 | {0x43, 0x0a}, /* rsvd */ | ||
287 | {0x44, 0xf0}, | ||
288 | {0x45, 0x46}, | ||
289 | {0x46, 0x62}, | ||
290 | {0x47, 0x2a}, | ||
291 | {0x48, 0x3c}, | ||
292 | {0x4a, 0xfc}, | ||
293 | {0x4b, 0xfc}, | ||
294 | {0x4c, 0x7f}, | ||
295 | {0x4d, 0x7f}, | ||
296 | {0x4e, 0x7f}, | ||
297 | {0x4f, 0x98}, /* matrix */ | ||
298 | {0x50, 0x98}, | ||
299 | {0x51, 0x00}, | ||
300 | {0x52, 0x28}, | ||
301 | {0x53, 0x70}, | ||
302 | {0x54, 0x98}, | ||
303 | {0x58, 0x1a}, /* matrix coef sign */ | ||
304 | {0x59, 0x85}, /* AWB control */ | ||
305 | {0x5a, 0xa9}, | ||
306 | {0x5b, 0x64}, | ||
307 | {0x5c, 0x84}, | ||
308 | {0x5d, 0x53}, | ||
309 | {0x5e, 0x0e}, | ||
310 | {0x5f, 0xf0}, /* AWB blue limit */ | ||
311 | {0x60, 0xf0}, /* AWB red limit */ | ||
312 | {0x61, 0xf0}, /* AWB green limit */ | ||
313 | {0x62, 0x00}, /* lcc1 */ | ||
314 | {0x63, 0x00}, /* lcc2 */ | ||
315 | {0x64, 0x02}, /* lcc3 */ | ||
316 | {0x65, 0x16}, /* lcc4 */ | ||
317 | {0x66, 0x01}, /* lcc5 */ | ||
318 | {0x69, 0x02}, /* hv */ | ||
319 | {0x6b, 0x5a}, /* dbvl */ | ||
320 | {0x6c, 0x04}, | ||
321 | {0x6d, 0x55}, | ||
322 | {0x6e, 0x00}, | ||
323 | {0x6f, 0x9d}, | ||
324 | {0x70, 0x21}, /* dnsth */ | ||
325 | {0x71, 0x78}, | ||
326 | {0x72, 0x00}, /* poidx */ | ||
327 | {0x73, 0x01}, /* pckdv */ | ||
328 | {0x74, 0x3a}, /* xindx */ | ||
329 | {0x75, 0x35}, /* yindx */ | ||
330 | {0x76, 0x01}, | ||
331 | {0x77, 0x02}, | ||
332 | {0x7a, 0x12}, /* gamma curve */ | ||
333 | {0x7b, 0x08}, | ||
334 | {0x7c, 0x16}, | ||
335 | {0x7d, 0x30}, | ||
336 | {0x7e, 0x5e}, | ||
337 | {0x7f, 0x72}, | ||
338 | {0x80, 0x82}, | ||
339 | {0x81, 0x8e}, | ||
340 | {0x82, 0x9a}, | ||
341 | {0x83, 0xa4}, | ||
342 | {0x84, 0xac}, | ||
343 | {0x85, 0xb8}, | ||
344 | {0x86, 0xc3}, | ||
345 | {0x87, 0xd6}, | ||
346 | {0x88, 0xe6}, | ||
347 | {0x89, 0xf2}, | ||
348 | {0x8a, 0x03}, | ||
349 | {0x8c, 0x89}, /* com19 */ | ||
350 | {0x14, 0x28}, /* com9 */ | ||
351 | {0x90, 0x7d}, | ||
352 | {0x91, 0x7b}, | ||
353 | {0x9d, 0x03}, /* lcc6 */ | ||
354 | {0x9e, 0x04}, /* lcc7 */ | ||
355 | {0x9f, 0x7a}, | ||
356 | {0xa0, 0x79}, | ||
357 | {0xa1, 0x40}, /* aechm */ | ||
358 | {0xa4, 0x50}, /* com21 */ | ||
359 | {0xa5, 0x68}, /* com26 */ | ||
360 | {0xa6, 0x4a}, /* AWB green */ | ||
361 | {0xa8, 0xc1}, /* refa8 */ | ||
362 | {0xa9, 0xef}, /* refa9 */ | ||
363 | {0xaa, 0x92}, | ||
364 | {0xab, 0x04}, | ||
365 | {0xac, 0x80}, /* black level control */ | ||
366 | {0xad, 0x80}, | ||
367 | {0xae, 0x80}, | ||
368 | {0xaf, 0x80}, | ||
369 | {0xb2, 0xf2}, | ||
370 | {0xb3, 0x20}, | ||
371 | {0xb4, 0x20}, /* ctrlb4 */ | ||
372 | {0xb5, 0x00}, | ||
373 | {0xb6, 0xaf}, | ||
374 | {0xbb, 0xae}, | ||
375 | {0xbc, 0x7f}, /* ADC channel offsets */ | ||
376 | {0xdb, 0x7f}, | ||
377 | {0xbe, 0x7f}, | ||
378 | {0xbf, 0x7f}, | ||
379 | {0xc0, 0xe2}, | ||
380 | {0xc1, 0xc0}, | ||
381 | {0xc2, 0x01}, | ||
382 | {0xc3, 0x4e}, | ||
383 | {0xc6, 0x85}, | ||
384 | {0xc7, 0x80}, /* com24 */ | ||
385 | {0xc9, 0xe0}, | ||
386 | {0xca, 0xe8}, | ||
387 | {0xcb, 0xf0}, | ||
388 | {0xcc, 0xd8}, | ||
389 | {0xcd, 0xf1}, | ||
390 | {0x4f, 0x98}, /* matrix */ | ||
391 | {0x50, 0x98}, | ||
392 | {0x51, 0x00}, | ||
393 | {0x52, 0x28}, | ||
394 | {0x53, 0x70}, | ||
395 | {0x54, 0x98}, | ||
396 | {0x58, 0x1a}, | ||
397 | {0xff, 0x41}, /* read 41, write ff 00 */ | ||
398 | {0x41, 0x40}, /* com16 */ | ||
399 | |||
400 | {0xc5, 0x03}, /* 60 Hz banding filter */ | ||
401 | {0x6a, 0x02}, /* 50 Hz banding filter */ | ||
402 | |||
403 | {0x12, 0x62}, /* com7 - 30fps VGA YUV */ | ||
404 | {0x36, 0xfa}, /* aref3 */ | ||
405 | {0x69, 0x0a}, /* hv */ | ||
406 | {0x8c, 0x89}, /* com22 */ | ||
407 | {0x14, 0x28}, /* com9 */ | ||
408 | {0x3e, 0x0c}, | ||
409 | {0x41, 0x40}, /* com16 */ | ||
410 | {0x72, 0x00}, | ||
411 | {0x73, 0x00}, | ||
412 | {0x74, 0x3a}, | ||
413 | {0x75, 0x35}, | ||
414 | {0x76, 0x01}, | ||
415 | {0xc7, 0x80}, | ||
416 | {0x03, 0x12}, /* vref */ | ||
417 | {0x17, 0x16}, /* hstart */ | ||
418 | {0x18, 0x02}, /* hstop */ | ||
419 | {0x19, 0x01}, /* vstrt */ | ||
420 | {0x1a, 0x3d}, /* vstop */ | ||
421 | {0x32, 0xff}, /* href */ | ||
422 | {0xc0, 0xaa}, | ||
423 | }; | ||
424 | |||
425 | static const u8 bridge_init_2[][2] = { | ||
426 | {0x94, 0xaa}, | ||
427 | {0xf1, 0x60}, | ||
428 | {0xe5, 0x04}, | ||
429 | {0xc0, 0x50}, | ||
430 | {0xc1, 0x3c}, | ||
431 | {0x8c, 0x00}, | ||
432 | {0x8d, 0x1c}, | ||
433 | {0x34, 0x05}, | ||
434 | |||
435 | {0xc2, 0x0c}, | ||
436 | {0xc3, 0xf9}, | ||
437 | {0xda, 0x01}, | ||
438 | {0x50, 0x00}, | ||
439 | {0x51, 0xa0}, | ||
440 | {0x52, 0x3c}, | ||
441 | {0x53, 0x00}, | ||
442 | {0x54, 0x00}, | ||
443 | {0x55, 0x00}, | ||
444 | {0x57, 0x00}, | ||
445 | {0x5c, 0x00}, | ||
446 | {0x5a, 0xa0}, | ||
447 | {0x5b, 0x78}, | ||
448 | {0x35, 0x02}, | ||
449 | {0xd9, 0x10}, | ||
450 | {0x94, 0x11}, | ||
451 | }; | ||
452 | |||
453 | static const u8 sensor_init_2[][2] = { | ||
454 | {0x3b, 0xc4}, | ||
455 | {0x1e, 0x04}, /* mvfp */ | ||
456 | {0x13, 0xe0}, /* com8 */ | ||
457 | {0x00, 0x00}, /* gain */ | ||
458 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
459 | {0x11, 0x03}, /* clkrc */ | ||
460 | {0x6b, 0x5a}, /* dblv */ | ||
461 | {0x6a, 0x05}, | ||
462 | {0xc5, 0x07}, | ||
463 | {0xa2, 0x4b}, | ||
464 | {0xa3, 0x3e}, | ||
465 | {0x2d, 0x00}, | ||
466 | {0xff, 0x42}, /* read 42, write ff 00 */ | ||
467 | {0x42, 0xc0}, /* com17 */ | ||
468 | {0x2d, 0x00}, | ||
469 | {0xff, 0x42}, /* read 42, write ff 00 */ | ||
470 | {0x42, 0xc1}, /* com17 */ | ||
471 | /* sharpness */ | ||
472 | {0x3f, 0x01}, | ||
473 | {0xff, 0x42}, /* read 42, write ff 00 */ | ||
474 | {0x42, 0xc1}, /* com17 */ | ||
475 | /* saturation */ | ||
476 | {0x4f, 0x98}, /* matrix */ | ||
477 | {0x50, 0x98}, | ||
478 | {0x51, 0x00}, | ||
479 | {0x52, 0x28}, | ||
480 | {0x53, 0x70}, | ||
481 | {0x54, 0x98}, | ||
482 | {0x58, 0x1a}, | ||
483 | {0xff, 0x41}, /* read 41, write ff 00 */ | ||
484 | {0x41, 0x40}, /* com16 */ | ||
485 | /* contrast */ | ||
486 | {0x56, 0x40}, | ||
487 | /* brightness */ | ||
488 | {0x55, 0x8f}, | ||
489 | /* expo */ | ||
490 | {0x10, 0x25}, /* aech - exposure high bits */ | ||
491 | {0xff, 0x13}, /* read 13, write ff 00 */ | ||
492 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
493 | }; | ||
494 | |||
495 | static const u8 sensor_start_1_vga[][2] = { /* same for qvga */ | ||
496 | {0x12, 0x62}, /* com7 - 30fps VGA YUV */ | ||
497 | {0x36, 0xfa}, /* aref3 */ | ||
498 | {0x69, 0x0a}, /* hv */ | ||
499 | {0x8c, 0x89}, /* com22 */ | ||
500 | {0x14, 0x28}, /* com9 */ | ||
501 | {0x3e, 0x0c}, /* com14 */ | ||
502 | {0x41, 0x40}, /* com16 */ | ||
503 | {0x72, 0x00}, | ||
504 | {0x73, 0x00}, | ||
505 | {0x74, 0x3a}, | ||
506 | {0x75, 0x35}, | ||
507 | {0x76, 0x01}, | ||
508 | {0xc7, 0x80}, /* com24 */ | ||
509 | {0x03, 0x12}, /* vref */ | ||
510 | {0x17, 0x16}, /* hstart */ | ||
511 | {0x18, 0x02}, /* hstop */ | ||
512 | {0x19, 0x01}, /* vstrt */ | ||
513 | {0x1a, 0x3d}, /* vstop */ | ||
514 | {0x32, 0xff}, /* href */ | ||
515 | {0xc0, 0xaa}, | ||
516 | }; | ||
517 | |||
518 | static const u8 sensor_start_1_svga[][2] = { | ||
519 | {0x12, 0x02}, /* com7 - YUYV - VGA 15 full resolution */ | ||
520 | {0x36, 0xf8}, /* aref3 */ | ||
521 | {0x69, 0x02}, /* hv */ | ||
522 | {0x8c, 0x0d}, /* com22 */ | ||
523 | {0x3e, 0x0c}, /* com14 */ | ||
524 | {0x41, 0x40}, /* com16 */ | ||
525 | {0x72, 0x00}, | ||
526 | {0x73, 0x01}, | ||
527 | {0x74, 0x3a}, | ||
528 | {0x75, 0x35}, | ||
529 | {0x76, 0x01}, | ||
530 | {0xc7, 0x80}, /* com24 */ | ||
531 | {0x03, 0x1b}, /* vref */ | ||
532 | {0x17, 0x1d}, /* hstart */ | ||
533 | {0x18, 0xbd}, /* hstop */ | ||
534 | {0x19, 0x01}, /* vstrt */ | ||
535 | {0x1a, 0x81}, /* vstop */ | ||
536 | {0x32, 0xff}, /* href */ | ||
537 | {0xc0, 0xe2}, | ||
538 | }; | ||
539 | |||
540 | static const u8 sensor_start_1_xga[][2] = { | ||
541 | {0x12, 0x02}, /* com7 */ | ||
542 | {0x36, 0xf8}, /* aref3 */ | ||
543 | {0x69, 0x02}, /* hv */ | ||
544 | {0x8c, 0x89}, /* com22 */ | ||
545 | {0x14, 0x28}, /* com9 */ | ||
546 | {0x3e, 0x0c}, /* com14 */ | ||
547 | {0x41, 0x40}, /* com16 */ | ||
548 | {0x72, 0x00}, | ||
549 | {0x73, 0x01}, | ||
550 | {0x74, 0x3a}, | ||
551 | {0x75, 0x35}, | ||
552 | {0x76, 0x01}, | ||
553 | {0xc7, 0x80}, /* com24 */ | ||
554 | {0x03, 0x1b}, /* vref */ | ||
555 | {0x17, 0x1d}, /* hstart */ | ||
556 | {0x18, 0xbd}, /* hstop */ | ||
557 | {0x19, 0x01}, /* vstrt */ | ||
558 | {0x1a, 0x81}, /* vstop */ | ||
559 | {0x32, 0xff}, /* href */ | ||
560 | {0xc0, 0xe2}, | ||
561 | }; | ||
562 | |||
563 | static const u8 sensor_start_1_sxga[][2] = { | ||
564 | {0x12, 0x02}, /* com7 */ | ||
565 | {0x36, 0xf8}, /* aref3 */ | ||
566 | {0x69, 0x02}, /* hv */ | ||
567 | {0x8c, 0x89}, /* com22 */ | ||
568 | {0x14, 0x28}, /* com9 */ | ||
569 | {0x3e, 0x0c}, /* com14 */ | ||
570 | {0x41, 0x40}, /* com16 */ | ||
571 | {0x72, 0x00}, | ||
572 | {0x73, 0x01}, | ||
573 | {0x74, 0x3a}, | ||
574 | {0x75, 0x35}, | ||
575 | {0x76, 0x01}, | ||
576 | {0xc7, 0x80}, /* com24 */ | ||
577 | {0x03, 0x1b}, /* vref */ | ||
578 | {0x17, 0x1d}, /* hstart */ | ||
579 | {0x18, 0x02}, /* hstop */ | ||
580 | {0x19, 0x01}, /* vstrt */ | ||
581 | {0x1a, 0x81}, /* vstop */ | ||
582 | {0x32, 0xff}, /* href */ | ||
583 | {0xc0, 0xe2}, | ||
584 | }; | ||
585 | |||
586 | static const u8 bridge_start_qvga[][2] = { | ||
587 | {0x94, 0xaa}, | ||
588 | {0xf1, 0x60}, | ||
589 | {0xe5, 0x04}, | ||
590 | {0xc0, 0x50}, | ||
591 | {0xc1, 0x3c}, | ||
592 | {0x8c, 0x00}, | ||
593 | {0x8d, 0x1c}, | ||
594 | {0x34, 0x05}, | ||
595 | |||
596 | {0xc2, 0x4c}, | ||
597 | {0xc3, 0xf9}, | ||
598 | {0xda, 0x00}, | ||
599 | {0x50, 0x00}, | ||
600 | {0x51, 0xa0}, | ||
601 | {0x52, 0x78}, | ||
602 | {0x53, 0x00}, | ||
603 | {0x54, 0x00}, | ||
604 | {0x55, 0x00}, | ||
605 | {0x57, 0x00}, | ||
606 | {0x5c, 0x00}, | ||
607 | {0x5a, 0x50}, | ||
608 | {0x5b, 0x3c}, | ||
609 | {0x35, 0x02}, | ||
610 | {0xd9, 0x10}, | ||
611 | {0x94, 0x11}, | ||
612 | }; | ||
613 | |||
614 | static const u8 bridge_start_vga[][2] = { | ||
615 | {0x94, 0xaa}, | ||
616 | {0xf1, 0x60}, | ||
617 | {0xe5, 0x04}, | ||
618 | {0xc0, 0x50}, | ||
619 | {0xc1, 0x3c}, | ||
620 | {0x8c, 0x00}, | ||
621 | {0x8d, 0x1c}, | ||
622 | {0x34, 0x05}, | ||
623 | {0xc2, 0x0c}, | ||
624 | {0xc3, 0xf9}, | ||
625 | {0xda, 0x01}, | ||
626 | {0x50, 0x00}, | ||
627 | {0x51, 0xa0}, | ||
628 | {0x52, 0x3c}, | ||
629 | {0x53, 0x00}, | ||
630 | {0x54, 0x00}, | ||
631 | {0x55, 0x00}, | ||
632 | {0x57, 0x00}, | ||
633 | {0x5c, 0x00}, | ||
634 | {0x5a, 0xa0}, | ||
635 | {0x5b, 0x78}, | ||
636 | {0x35, 0x02}, | ||
637 | {0xd9, 0x10}, | ||
638 | {0x94, 0x11}, | ||
639 | }; | ||
640 | |||
641 | static const u8 bridge_start_svga[][2] = { | ||
642 | {0x94, 0xaa}, | ||
643 | {0xf1, 0x60}, | ||
644 | {0xe5, 0x04}, | ||
645 | {0xc0, 0xa0}, | ||
646 | {0xc1, 0x80}, | ||
647 | {0x8c, 0x00}, | ||
648 | {0x8d, 0x1c}, | ||
649 | {0x34, 0x05}, | ||
650 | {0xc2, 0x4c}, | ||
651 | {0xc3, 0xf9}, | ||
652 | {0x50, 0x00}, | ||
653 | {0x51, 0x40}, | ||
654 | {0x52, 0x00}, | ||
655 | {0x53, 0x00}, | ||
656 | {0x54, 0x00}, | ||
657 | {0x55, 0x88}, | ||
658 | {0x57, 0x00}, | ||
659 | {0x5c, 0x00}, | ||
660 | {0x5a, 0xc8}, | ||
661 | {0x5b, 0x96}, | ||
662 | {0x35, 0x02}, | ||
663 | {0xd9, 0x10}, | ||
664 | {0xda, 0x00}, | ||
665 | {0x94, 0x11}, | ||
666 | }; | ||
667 | |||
668 | static const u8 bridge_start_xga[][2] = { | ||
669 | {0x94, 0xaa}, | ||
670 | {0xf1, 0x60}, | ||
671 | {0xe5, 0x04}, | ||
672 | {0xc0, 0xa0}, | ||
673 | {0xc1, 0x80}, | ||
674 | {0x8c, 0x00}, | ||
675 | {0x8d, 0x1c}, | ||
676 | {0x34, 0x05}, | ||
677 | {0xc2, 0x4c}, | ||
678 | {0xc3, 0xf9}, | ||
679 | {0x50, 0x00}, | ||
680 | {0x51, 0x40}, | ||
681 | {0x52, 0x00}, | ||
682 | {0x53, 0x00}, | ||
683 | {0x54, 0x00}, | ||
684 | {0x55, 0x88}, | ||
685 | {0x57, 0x00}, | ||
686 | {0x5c, 0x01}, | ||
687 | {0x5a, 0x00}, | ||
688 | {0x5b, 0xc0}, | ||
689 | {0x35, 0x02}, | ||
690 | {0xd9, 0x10}, | ||
691 | {0xda, 0x01}, | ||
692 | {0x94, 0x11}, | ||
693 | }; | ||
694 | |||
695 | static const u8 bridge_start_sxga[][2] = { | ||
696 | {0x94, 0xaa}, | ||
697 | {0xf1, 0x60}, | ||
698 | {0xe5, 0x04}, | ||
699 | {0xc0, 0xa0}, | ||
700 | {0xc1, 0x80}, | ||
701 | {0x8c, 0x00}, | ||
702 | {0x8d, 0x1c}, | ||
703 | {0x34, 0x05}, | ||
704 | {0xc2, 0x0c}, | ||
705 | {0xc3, 0xf9}, | ||
706 | {0xda, 0x00}, | ||
707 | {0x35, 0x02}, | ||
708 | {0xd9, 0x10}, | ||
709 | {0x94, 0x11}, | ||
710 | }; | ||
711 | |||
712 | static const u8 sensor_start_2_qvga[][2] = { | ||
713 | {0x3b, 0xe4}, /* com11 - night mode 1/4 frame rate */ | ||
714 | {0x1e, 0x04}, /* mvfp */ | ||
715 | {0x13, 0xe0}, /* com8 */ | ||
716 | {0x00, 0x00}, | ||
717 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
718 | {0x11, 0x01}, /* clkrc */ | ||
719 | {0x6b, 0x5a}, /* dblv */ | ||
720 | {0x6a, 0x02}, /* 50 Hz banding filter */ | ||
721 | {0xc5, 0x03}, /* 60 Hz banding filter */ | ||
722 | {0xa2, 0x96}, /* bd50 */ | ||
723 | {0xa3, 0x7d}, /* bd60 */ | ||
724 | |||
725 | {0xff, 0x13}, /* read 13, write ff 00 */ | ||
726 | {0x13, 0xe7}, | ||
727 | {0x3a, 0x80}, /* tslb - yuyv */ | ||
728 | }; | ||
729 | |||
730 | static const u8 sensor_start_2_vga[][2] = { | ||
731 | {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ | ||
732 | {0x1e, 0x04}, /* mvfp */ | ||
733 | {0x13, 0xe0}, /* com8 */ | ||
734 | {0x00, 0x00}, | ||
735 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
736 | {0x11, 0x03}, /* clkrc */ | ||
737 | {0x6b, 0x5a}, /* dblv */ | ||
738 | {0x6a, 0x05}, /* 50 Hz banding filter */ | ||
739 | {0xc5, 0x07}, /* 60 Hz banding filter */ | ||
740 | {0xa2, 0x4b}, /* bd50 */ | ||
741 | {0xa3, 0x3e}, /* bd60 */ | ||
742 | |||
743 | {0x2d, 0x00}, /* advfl */ | ||
744 | }; | ||
745 | |||
746 | static const u8 sensor_start_2_svga[][2] = { /* same for xga */ | ||
747 | {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ | ||
748 | {0x1e, 0x04}, /* mvfp */ | ||
749 | {0x13, 0xe0}, /* com8 */ | ||
750 | {0x00, 0x00}, | ||
751 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
752 | {0x11, 0x01}, /* clkrc */ | ||
753 | {0x6b, 0x5a}, /* dblv */ | ||
754 | {0x6a, 0x0c}, /* 50 Hz banding filter */ | ||
755 | {0xc5, 0x0f}, /* 60 Hz banding filter */ | ||
756 | {0xa2, 0x4e}, /* bd50 */ | ||
757 | {0xa3, 0x41}, /* bd60 */ | ||
758 | }; | ||
759 | |||
760 | static const u8 sensor_start_2_sxga[][2] = { | ||
761 | {0x13, 0xe0}, /* com8 */ | ||
762 | {0x00, 0x00}, | ||
763 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
764 | {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ | ||
765 | {0x1e, 0x04}, /* mvfp */ | ||
766 | {0x11, 0x01}, /* clkrc */ | ||
767 | {0x6b, 0x5a}, /* dblv */ | ||
768 | {0x6a, 0x0c}, /* 50 Hz banding filter */ | ||
769 | {0xc5, 0x0f}, /* 60 Hz banding filter */ | ||
770 | {0xa2, 0x4e}, /* bd50 */ | ||
771 | {0xa3, 0x41}, /* bd60 */ | ||
772 | }; | ||
773 | |||
774 | static void reg_w_i(struct gspca_dev *gspca_dev, u16 reg, u8 val) | ||
775 | { | ||
776 | struct usb_device *udev = gspca_dev->dev; | ||
777 | int ret; | ||
778 | |||
779 | if (gspca_dev->usb_err < 0) | ||
780 | return; | ||
781 | gspca_dev->usb_buf[0] = val; | ||
782 | ret = usb_control_msg(udev, | ||
783 | usb_sndctrlpipe(udev, 0), | ||
784 | 0x01, | ||
785 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
786 | 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT); | ||
787 | if (ret < 0) { | ||
788 | PDEBUG(D_ERR, "reg_w failed %d", ret); | ||
789 | gspca_dev->usb_err = ret; | ||
790 | } | ||
791 | } | ||
792 | |||
793 | static void reg_w(struct gspca_dev *gspca_dev, u16 reg, u8 val) | ||
794 | { | ||
795 | PDEBUG(D_USBO, "reg_w [%04x] = %02x", reg, val); | ||
796 | reg_w_i(gspca_dev, reg, val); | ||
797 | } | ||
798 | |||
799 | static u8 reg_r(struct gspca_dev *gspca_dev, u16 reg) | ||
800 | { | ||
801 | struct usb_device *udev = gspca_dev->dev; | ||
802 | int ret; | ||
803 | |||
804 | if (gspca_dev->usb_err < 0) | ||
805 | return 0; | ||
806 | ret = usb_control_msg(udev, | ||
807 | usb_rcvctrlpipe(udev, 0), | ||
808 | 0x01, | ||
809 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
810 | 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT); | ||
811 | PDEBUG(D_USBI, "reg_r [%04x] -> %02x", reg, gspca_dev->usb_buf[0]); | ||
812 | if (ret < 0) { | ||
813 | PDEBUG(D_ERR, "reg_r err %d", ret); | ||
814 | gspca_dev->usb_err = ret; | ||
815 | } | ||
816 | return gspca_dev->usb_buf[0]; | ||
817 | } | ||
818 | |||
819 | static int sccb_check_status(struct gspca_dev *gspca_dev) | ||
820 | { | ||
821 | u8 data; | ||
822 | int i; | ||
823 | |||
824 | for (i = 0; i < 5; i++) { | ||
825 | data = reg_r(gspca_dev, OV534_REG_STATUS); | ||
826 | |||
827 | switch (data) { | ||
828 | case 0x00: | ||
829 | return 1; | ||
830 | case 0x04: | ||
831 | return 0; | ||
832 | case 0x03: | ||
833 | break; | ||
834 | default: | ||
835 | PDEBUG(D_USBI|D_USBO, | ||
836 | "sccb status 0x%02x, attempt %d/5", | ||
837 | data, i + 1); | ||
838 | } | ||
839 | } | ||
840 | return 0; | ||
841 | } | ||
842 | |||
843 | static void sccb_write(struct gspca_dev *gspca_dev, u8 reg, u8 val) | ||
844 | { | ||
845 | PDEBUG(D_USBO, "sccb_write [%02x] = %02x", reg, val); | ||
846 | reg_w_i(gspca_dev, OV534_REG_SUBADDR, reg); | ||
847 | reg_w_i(gspca_dev, OV534_REG_WRITE, val); | ||
848 | reg_w_i(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3); | ||
849 | |||
850 | if (!sccb_check_status(gspca_dev)) | ||
851 | PDEBUG(D_ERR, "sccb_write failed"); | ||
852 | } | ||
853 | |||
854 | static u8 sccb_read(struct gspca_dev *gspca_dev, u16 reg) | ||
855 | { | ||
856 | reg_w(gspca_dev, OV534_REG_SUBADDR, reg); | ||
857 | reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2); | ||
858 | if (!sccb_check_status(gspca_dev)) | ||
859 | PDEBUG(D_ERR, "sccb_read failed 1"); | ||
860 | |||
861 | reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2); | ||
862 | if (!sccb_check_status(gspca_dev)) | ||
863 | PDEBUG(D_ERR, "sccb_read failed 2"); | ||
864 | |||
865 | return reg_r(gspca_dev, OV534_REG_READ); | ||
866 | } | ||
867 | |||
868 | /* output a bridge sequence (reg - val) */ | ||
869 | static void reg_w_array(struct gspca_dev *gspca_dev, | ||
870 | const u8 (*data)[2], int len) | ||
871 | { | ||
872 | while (--len >= 0) { | ||
873 | reg_w(gspca_dev, (*data)[0], (*data)[1]); | ||
874 | data++; | ||
875 | } | ||
876 | } | ||
877 | |||
878 | /* output a sensor sequence (reg - val) */ | ||
879 | static void sccb_w_array(struct gspca_dev *gspca_dev, | ||
880 | const u8 (*data)[2], int len) | ||
881 | { | ||
882 | while (--len >= 0) { | ||
883 | if ((*data)[0] != 0xff) { | ||
884 | sccb_write(gspca_dev, (*data)[0], (*data)[1]); | ||
885 | } else { | ||
886 | sccb_read(gspca_dev, (*data)[1]); | ||
887 | sccb_write(gspca_dev, 0xff, 0x00); | ||
888 | } | ||
889 | data++; | ||
890 | } | ||
891 | } | ||
892 | |||
893 | /* Two bits control LED: 0x21 bit 7 and 0x23 bit 7. | ||
894 | * (direction and output)? */ | ||
895 | static void set_led(struct gspca_dev *gspca_dev, int status) | ||
896 | { | ||
897 | u8 data; | ||
898 | |||
899 | PDEBUG(D_CONF, "led status: %d", status); | ||
900 | |||
901 | data = reg_r(gspca_dev, 0x21); | ||
902 | data |= 0x80; | ||
903 | reg_w(gspca_dev, 0x21, data); | ||
904 | |||
905 | data = reg_r(gspca_dev, 0x23); | ||
906 | if (status) | ||
907 | data |= 0x80; | ||
908 | else | ||
909 | data &= ~0x80; | ||
910 | |||
911 | reg_w(gspca_dev, 0x23, data); | ||
912 | |||
913 | if (!status) { | ||
914 | data = reg_r(gspca_dev, 0x21); | ||
915 | data &= ~0x80; | ||
916 | reg_w(gspca_dev, 0x21, data); | ||
917 | } | ||
918 | } | ||
919 | |||
920 | static void setbrightness(struct gspca_dev *gspca_dev) | ||
921 | { | ||
922 | struct sd *sd = (struct sd *) gspca_dev; | ||
923 | u8 val; | ||
924 | |||
925 | val = sd->brightness; | ||
926 | if (val < 8) | ||
927 | val = 15 - val; /* f .. 8 */ | ||
928 | else | ||
929 | val = val - 8; /* 0 .. 7 */ | ||
930 | sccb_write(gspca_dev, 0x55, /* brtn - brightness adjustment */ | ||
931 | 0x0f | (val << 4)); | ||
932 | } | ||
933 | |||
934 | static void setcontrast(struct gspca_dev *gspca_dev) | ||
935 | { | ||
936 | struct sd *sd = (struct sd *) gspca_dev; | ||
937 | |||
938 | sccb_write(gspca_dev, 0x56, /* cnst1 - contrast 1 ctrl coeff */ | ||
939 | sd->contrast << 4); | ||
940 | } | ||
941 | |||
942 | static void setautogain(struct gspca_dev *gspca_dev) | ||
943 | { | ||
944 | struct sd *sd = (struct sd *) gspca_dev; | ||
945 | u8 val; | ||
946 | |||
947 | /*fixme: should adjust agc/awb/aec by different controls */ | ||
948 | val = sd->autogain; | ||
949 | val = sccb_read(gspca_dev, 0x13); /* com8 */ | ||
950 | sccb_write(gspca_dev, 0xff, 0x00); | ||
951 | if (sd->autogain) | ||
952 | val |= 0x05; /* agc & aec */ | ||
953 | else | ||
954 | val &= 0xfa; | ||
955 | sccb_write(gspca_dev, 0x13, val); | ||
956 | } | ||
957 | |||
958 | static void setexposure(struct gspca_dev *gspca_dev) | ||
959 | { | ||
960 | struct sd *sd = (struct sd *) gspca_dev; | ||
961 | u8 val; | ||
962 | static const u8 expo[4] = {0x00, 0x25, 0x38, 0x5e}; | ||
963 | |||
964 | sccb_write(gspca_dev, 0x10, /* aec[9:2] */ | ||
965 | expo[sd->exposure]); | ||
966 | |||
967 | val = sccb_read(gspca_dev, 0x13); /* com8 */ | ||
968 | sccb_write(gspca_dev, 0xff, 0x00); | ||
969 | sccb_write(gspca_dev, 0x13, val); | ||
970 | |||
971 | val = sccb_read(gspca_dev, 0xa1); /* aech */ | ||
972 | sccb_write(gspca_dev, 0xff, 0x00); | ||
973 | sccb_write(gspca_dev, 0xa1, val & 0xe0); /* aec[15:10] = 0 */ | ||
974 | } | ||
975 | |||
976 | static void setsharpness(struct gspca_dev *gspca_dev) | ||
977 | { | ||
978 | struct sd *sd = (struct sd *) gspca_dev; | ||
979 | s8 val; | ||
980 | |||
981 | val = sd->sharpness; | ||
982 | if (val < 0) { /* auto */ | ||
983 | val = sccb_read(gspca_dev, 0x42); /* com17 */ | ||
984 | sccb_write(gspca_dev, 0xff, 0x00); | ||
985 | sccb_write(gspca_dev, 0x42, val | 0x40); | ||
986 | /* Edge enhancement strength auto adjust */ | ||
987 | return; | ||
988 | } | ||
989 | if (val != 0) | ||
990 | val = 1 << (val - 1); | ||
991 | sccb_write(gspca_dev, 0x3f, /* edge - edge enhance. factor */ | ||
992 | val); | ||
993 | val = sccb_read(gspca_dev, 0x42); /* com17 */ | ||
994 | sccb_write(gspca_dev, 0xff, 0x00); | ||
995 | sccb_write(gspca_dev, 0x42, val & 0xbf); | ||
996 | } | ||
997 | |||
998 | static void setsatur(struct gspca_dev *gspca_dev) | ||
999 | { | ||
1000 | struct sd *sd = (struct sd *) gspca_dev; | ||
1001 | u8 val1, val2, val3; | ||
1002 | static const u8 matrix[5][2] = { | ||
1003 | {0x14, 0x38}, | ||
1004 | {0x1e, 0x54}, | ||
1005 | {0x28, 0x70}, | ||
1006 | {0x32, 0x8c}, | ||
1007 | {0x48, 0x90} | ||
1008 | }; | ||
1009 | |||
1010 | val1 = matrix[sd->satur][0]; | ||
1011 | val2 = matrix[sd->satur][1]; | ||
1012 | val3 = val1 + val2; | ||
1013 | sccb_write(gspca_dev, 0x4f, val3); /* matrix coeff */ | ||
1014 | sccb_write(gspca_dev, 0x50, val3); | ||
1015 | sccb_write(gspca_dev, 0x51, 0x00); | ||
1016 | sccb_write(gspca_dev, 0x52, val1); | ||
1017 | sccb_write(gspca_dev, 0x53, val2); | ||
1018 | sccb_write(gspca_dev, 0x54, val3); | ||
1019 | sccb_write(gspca_dev, 0x58, 0x1a); /* mtxs - coeff signs */ | ||
1020 | |||
1021 | val1 = sccb_read(gspca_dev, 0x41); /* com16 */ | ||
1022 | sccb_write(gspca_dev, 0xff, 0x00); | ||
1023 | sccb_write(gspca_dev, 0x41, val1); | ||
1024 | } | ||
1025 | |||
1026 | static void setfreq(struct gspca_dev *gspca_dev) | ||
1027 | { | ||
1028 | struct sd *sd = (struct sd *) gspca_dev; | ||
1029 | u8 val; | ||
1030 | |||
1031 | val = sccb_read(gspca_dev, 0x13); /* com8 */ | ||
1032 | sccb_write(gspca_dev, 0xff, 0x00); | ||
1033 | if (sd->freq == 0) { | ||
1034 | sccb_write(gspca_dev, 0x13, val & 0xdf); | ||
1035 | return; | ||
1036 | } | ||
1037 | sccb_write(gspca_dev, 0x13, val | 0x20); | ||
1038 | |||
1039 | val = sccb_read(gspca_dev, 0x42); /* com17 */ | ||
1040 | sccb_write(gspca_dev, 0xff, 0x00); | ||
1041 | if (sd->freq == 1) | ||
1042 | val |= 0x01; | ||
1043 | else | ||
1044 | val &= 0xfe; | ||
1045 | sccb_write(gspca_dev, 0x42, val); | ||
1046 | } | ||
1047 | |||
1048 | /* this function is called at probe time */ | ||
1049 | static int sd_config(struct gspca_dev *gspca_dev, | ||
1050 | const struct usb_device_id *id) | ||
1051 | { | ||
1052 | struct sd *sd = (struct sd *) gspca_dev; | ||
1053 | struct cam *cam; | ||
1054 | |||
1055 | cam = &gspca_dev->cam; | ||
1056 | |||
1057 | cam->cam_mode = ov965x_mode; | ||
1058 | cam->nmodes = ARRAY_SIZE(ov965x_mode); | ||
1059 | |||
1060 | sd->brightness = BRIGHTNESS_DEF; | ||
1061 | sd->contrast = CONTRAST_DEF; | ||
1062 | #if AUTOGAIN_DEF != 0 | ||
1063 | sd->autogain = AUTOGAIN_DEF; | ||
1064 | gspca_dev->ctrl_inac |= (1 << EXPO_IDX); | ||
1065 | #endif | ||
1066 | #if EXPO_DEF != 0 | ||
1067 | sd->exposure = EXPO_DEF; | ||
1068 | #endif | ||
1069 | #if SHARPNESS_DEF != 0 | ||
1070 | sd->sharpness = SHARPNESS_DEF; | ||
1071 | #endif | ||
1072 | sd->satur = SATUR_DEF; | ||
1073 | sd->freq = FREQ_DEF; | ||
1074 | |||
1075 | return 0; | ||
1076 | } | ||
1077 | |||
1078 | /* this function is called at probe and resume time */ | ||
1079 | static int sd_init(struct gspca_dev *gspca_dev) | ||
1080 | { | ||
1081 | u16 sensor_id; | ||
1082 | |||
1083 | /* reset bridge */ | ||
1084 | reg_w(gspca_dev, 0xe7, 0x3a); | ||
1085 | reg_w(gspca_dev, 0xe0, 0x08); | ||
1086 | msleep(100); | ||
1087 | |||
1088 | /* initialize the sensor address */ | ||
1089 | reg_w(gspca_dev, OV534_REG_ADDRESS, 0x60); | ||
1090 | |||
1091 | /* reset sensor */ | ||
1092 | sccb_write(gspca_dev, 0x12, 0x80); | ||
1093 | msleep(10); | ||
1094 | |||
1095 | /* probe the sensor */ | ||
1096 | sccb_read(gspca_dev, 0x0a); | ||
1097 | sensor_id = sccb_read(gspca_dev, 0x0a) << 8; | ||
1098 | sccb_read(gspca_dev, 0x0b); | ||
1099 | sensor_id |= sccb_read(gspca_dev, 0x0b); | ||
1100 | PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id); | ||
1101 | |||
1102 | /* initialize */ | ||
1103 | reg_w_array(gspca_dev, bridge_init, | ||
1104 | ARRAY_SIZE(bridge_init)); | ||
1105 | sccb_w_array(gspca_dev, sensor_init, | ||
1106 | ARRAY_SIZE(sensor_init)); | ||
1107 | reg_w_array(gspca_dev, bridge_init_2, | ||
1108 | ARRAY_SIZE(bridge_init_2)); | ||
1109 | sccb_w_array(gspca_dev, sensor_init_2, | ||
1110 | ARRAY_SIZE(sensor_init_2)); | ||
1111 | reg_w(gspca_dev, 0xe0, 0x00); | ||
1112 | reg_w(gspca_dev, 0xe0, 0x01); | ||
1113 | set_led(gspca_dev, 0); | ||
1114 | reg_w(gspca_dev, 0xe0, 0x00); | ||
1115 | |||
1116 | return gspca_dev->usb_err; | ||
1117 | } | ||
1118 | |||
1119 | static int sd_start(struct gspca_dev *gspca_dev) | ||
1120 | { | ||
1121 | switch (gspca_dev->curr_mode) { | ||
1122 | case QVGA_MODE: /* 320x240 */ | ||
1123 | sccb_w_array(gspca_dev, sensor_start_1_vga, | ||
1124 | ARRAY_SIZE(sensor_start_1_vga)); | ||
1125 | reg_w_array(gspca_dev, bridge_start_qvga, | ||
1126 | ARRAY_SIZE(bridge_start_qvga)); | ||
1127 | sccb_w_array(gspca_dev, sensor_start_2_qvga, | ||
1128 | ARRAY_SIZE(sensor_start_2_qvga)); | ||
1129 | break; | ||
1130 | case VGA_MODE: /* 640x480 */ | ||
1131 | sccb_w_array(gspca_dev, sensor_start_1_vga, | ||
1132 | ARRAY_SIZE(sensor_start_1_vga)); | ||
1133 | reg_w_array(gspca_dev, bridge_start_vga, | ||
1134 | ARRAY_SIZE(bridge_start_vga)); | ||
1135 | sccb_w_array(gspca_dev, sensor_start_2_vga, | ||
1136 | ARRAY_SIZE(sensor_start_2_vga)); | ||
1137 | break; | ||
1138 | case SVGA_MODE: /* 800x600 */ | ||
1139 | sccb_w_array(gspca_dev, sensor_start_1_svga, | ||
1140 | ARRAY_SIZE(sensor_start_1_svga)); | ||
1141 | reg_w_array(gspca_dev, bridge_start_svga, | ||
1142 | ARRAY_SIZE(bridge_start_svga)); | ||
1143 | sccb_w_array(gspca_dev, sensor_start_2_svga, | ||
1144 | ARRAY_SIZE(sensor_start_2_svga)); | ||
1145 | break; | ||
1146 | case XGA_MODE: /* 1024x768 */ | ||
1147 | sccb_w_array(gspca_dev, sensor_start_1_xga, | ||
1148 | ARRAY_SIZE(sensor_start_1_xga)); | ||
1149 | reg_w_array(gspca_dev, bridge_start_xga, | ||
1150 | ARRAY_SIZE(bridge_start_xga)); | ||
1151 | sccb_w_array(gspca_dev, sensor_start_2_svga, | ||
1152 | ARRAY_SIZE(sensor_start_2_svga)); | ||
1153 | break; | ||
1154 | default: | ||
1155 | /* case SXGA_MODE: * 1280x1024 */ | ||
1156 | sccb_w_array(gspca_dev, sensor_start_1_sxga, | ||
1157 | ARRAY_SIZE(sensor_start_1_sxga)); | ||
1158 | reg_w_array(gspca_dev, bridge_start_sxga, | ||
1159 | ARRAY_SIZE(bridge_start_sxga)); | ||
1160 | sccb_w_array(gspca_dev, sensor_start_2_sxga, | ||
1161 | ARRAY_SIZE(sensor_start_2_sxga)); | ||
1162 | break; | ||
1163 | } | ||
1164 | setfreq(gspca_dev); | ||
1165 | setautogain(gspca_dev); | ||
1166 | setbrightness(gspca_dev); | ||
1167 | setcontrast(gspca_dev); | ||
1168 | setexposure(gspca_dev); | ||
1169 | setsharpness(gspca_dev); | ||
1170 | setsatur(gspca_dev); | ||
1171 | |||
1172 | reg_w(gspca_dev, 0xe0, 0x00); | ||
1173 | reg_w(gspca_dev, 0xe0, 0x00); | ||
1174 | set_led(gspca_dev, 1); | ||
1175 | return gspca_dev->usb_err; | ||
1176 | } | ||
1177 | |||
1178 | static void sd_stopN(struct gspca_dev *gspca_dev) | ||
1179 | { | ||
1180 | reg_w(gspca_dev, 0xe0, 0x01); | ||
1181 | set_led(gspca_dev, 0); | ||
1182 | reg_w(gspca_dev, 0xe0, 0x00); | ||
1183 | } | ||
1184 | |||
1185 | /* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */ | ||
1186 | #define UVC_STREAM_EOH (1 << 7) | ||
1187 | #define UVC_STREAM_ERR (1 << 6) | ||
1188 | #define UVC_STREAM_STI (1 << 5) | ||
1189 | #define UVC_STREAM_RES (1 << 4) | ||
1190 | #define UVC_STREAM_SCR (1 << 3) | ||
1191 | #define UVC_STREAM_PTS (1 << 2) | ||
1192 | #define UVC_STREAM_EOF (1 << 1) | ||
1193 | #define UVC_STREAM_FID (1 << 0) | ||
1194 | |||
1195 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | ||
1196 | u8 *data, int len) | ||
1197 | { | ||
1198 | struct sd *sd = (struct sd *) gspca_dev; | ||
1199 | __u32 this_pts; | ||
1200 | u8 this_fid; | ||
1201 | int remaining_len = len; | ||
1202 | |||
1203 | do { | ||
1204 | len = min(remaining_len, 2040); | ||
1205 | |||
1206 | /* Payloads are prefixed with a UVC-style header. We | ||
1207 | consider a frame to start when the FID toggles, or the PTS | ||
1208 | changes. A frame ends when EOF is set, and we've received | ||
1209 | the correct number of bytes. */ | ||
1210 | |||
1211 | /* Verify UVC header. Header length is always 12 */ | ||
1212 | if (data[0] != 12 || len < 12) { | ||
1213 | PDEBUG(D_PACK, "bad header"); | ||
1214 | goto discard; | ||
1215 | } | ||
1216 | |||
1217 | /* Check errors */ | ||
1218 | if (data[1] & UVC_STREAM_ERR) { | ||
1219 | PDEBUG(D_PACK, "payload error"); | ||
1220 | goto discard; | ||
1221 | } | ||
1222 | |||
1223 | /* Extract PTS and FID */ | ||
1224 | if (!(data[1] & UVC_STREAM_PTS)) { | ||
1225 | PDEBUG(D_PACK, "PTS not present"); | ||
1226 | goto discard; | ||
1227 | } | ||
1228 | this_pts = (data[5] << 24) | (data[4] << 16) | ||
1229 | | (data[3] << 8) | data[2]; | ||
1230 | this_fid = data[1] & UVC_STREAM_FID; | ||
1231 | |||
1232 | /* If PTS or FID has changed, start a new frame. */ | ||
1233 | if (this_pts != sd->last_pts || this_fid != sd->last_fid) { | ||
1234 | if (gspca_dev->last_packet_type == INTER_PACKET) | ||
1235 | gspca_frame_add(gspca_dev, LAST_PACKET, | ||
1236 | NULL, 0); | ||
1237 | sd->last_pts = this_pts; | ||
1238 | sd->last_fid = this_fid; | ||
1239 | gspca_frame_add(gspca_dev, FIRST_PACKET, | ||
1240 | data + 12, len - 12); | ||
1241 | /* If this packet is marked as EOF, end the frame */ | ||
1242 | } else if (data[1] & UVC_STREAM_EOF) { | ||
1243 | sd->last_pts = 0; | ||
1244 | gspca_frame_add(gspca_dev, LAST_PACKET, | ||
1245 | data + 12, len - 12); | ||
1246 | } else { | ||
1247 | |||
1248 | /* Add the data from this payload */ | ||
1249 | gspca_frame_add(gspca_dev, INTER_PACKET, | ||
1250 | data + 12, len - 12); | ||
1251 | } | ||
1252 | |||
1253 | /* Done this payload */ | ||
1254 | goto scan_next; | ||
1255 | |||
1256 | discard: | ||
1257 | /* Discard data until a new frame starts. */ | ||
1258 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
1259 | |||
1260 | scan_next: | ||
1261 | remaining_len -= len; | ||
1262 | data += len; | ||
1263 | } while (remaining_len > 0); | ||
1264 | } | ||
1265 | |||
1266 | /* controls */ | ||
1267 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | ||
1268 | { | ||
1269 | struct sd *sd = (struct sd *) gspca_dev; | ||
1270 | |||
1271 | sd->brightness = val; | ||
1272 | if (gspca_dev->streaming) | ||
1273 | setbrightness(gspca_dev); | ||
1274 | return gspca_dev->usb_err; | ||
1275 | } | ||
1276 | |||
1277 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
1278 | { | ||
1279 | struct sd *sd = (struct sd *) gspca_dev; | ||
1280 | |||
1281 | *val = sd->brightness; | ||
1282 | return 0; | ||
1283 | } | ||
1284 | |||
1285 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | ||
1286 | { | ||
1287 | struct sd *sd = (struct sd *) gspca_dev; | ||
1288 | |||
1289 | sd->contrast = val; | ||
1290 | if (gspca_dev->streaming) | ||
1291 | setcontrast(gspca_dev); | ||
1292 | return gspca_dev->usb_err; | ||
1293 | } | ||
1294 | |||
1295 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | ||
1296 | { | ||
1297 | struct sd *sd = (struct sd *) gspca_dev; | ||
1298 | |||
1299 | *val = sd->contrast; | ||
1300 | return 0; | ||
1301 | } | ||
1302 | |||
1303 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | ||
1304 | { | ||
1305 | struct sd *sd = (struct sd *) gspca_dev; | ||
1306 | |||
1307 | sd->autogain = val; | ||
1308 | |||
1309 | if (gspca_dev->streaming) { | ||
1310 | if (val) | ||
1311 | gspca_dev->ctrl_inac |= (1 << EXPO_IDX); | ||
1312 | else | ||
1313 | gspca_dev->ctrl_inac &= ~(1 << EXPO_IDX); | ||
1314 | setautogain(gspca_dev); | ||
1315 | } | ||
1316 | return gspca_dev->usb_err; | ||
1317 | } | ||
1318 | |||
1319 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) | ||
1320 | { | ||
1321 | struct sd *sd = (struct sd *) gspca_dev; | ||
1322 | |||
1323 | *val = sd->autogain; | ||
1324 | return 0; | ||
1325 | } | ||
1326 | |||
1327 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) | ||
1328 | { | ||
1329 | struct sd *sd = (struct sd *) gspca_dev; | ||
1330 | |||
1331 | sd->exposure = val; | ||
1332 | if (gspca_dev->streaming) | ||
1333 | setexposure(gspca_dev); | ||
1334 | return gspca_dev->usb_err; | ||
1335 | } | ||
1336 | |||
1337 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) | ||
1338 | { | ||
1339 | struct sd *sd = (struct sd *) gspca_dev; | ||
1340 | |||
1341 | *val = sd->exposure; | ||
1342 | return 0; | ||
1343 | } | ||
1344 | |||
1345 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val) | ||
1346 | { | ||
1347 | struct sd *sd = (struct sd *) gspca_dev; | ||
1348 | |||
1349 | sd->sharpness = val; | ||
1350 | if (gspca_dev->streaming) | ||
1351 | setsharpness(gspca_dev); | ||
1352 | return gspca_dev->usb_err; | ||
1353 | } | ||
1354 | |||
1355 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val) | ||
1356 | { | ||
1357 | struct sd *sd = (struct sd *) gspca_dev; | ||
1358 | |||
1359 | *val = sd->sharpness; | ||
1360 | return 0; | ||
1361 | } | ||
1362 | |||
1363 | static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val) | ||
1364 | { | ||
1365 | struct sd *sd = (struct sd *) gspca_dev; | ||
1366 | |||
1367 | sd->satur = val; | ||
1368 | if (gspca_dev->streaming) | ||
1369 | setsatur(gspca_dev); | ||
1370 | return gspca_dev->usb_err; | ||
1371 | } | ||
1372 | |||
1373 | static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val) | ||
1374 | { | ||
1375 | struct sd *sd = (struct sd *) gspca_dev; | ||
1376 | |||
1377 | *val = sd->satur; | ||
1378 | return 0; | ||
1379 | } | ||
1380 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) | ||
1381 | { | ||
1382 | struct sd *sd = (struct sd *) gspca_dev; | ||
1383 | |||
1384 | sd->freq = val; | ||
1385 | if (gspca_dev->streaming) | ||
1386 | setfreq(gspca_dev); | ||
1387 | return gspca_dev->usb_err; | ||
1388 | } | ||
1389 | |||
1390 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val) | ||
1391 | { | ||
1392 | struct sd *sd = (struct sd *) gspca_dev; | ||
1393 | |||
1394 | *val = sd->freq; | ||
1395 | return 0; | ||
1396 | } | ||
1397 | |||
1398 | static int sd_querymenu(struct gspca_dev *gspca_dev, | ||
1399 | struct v4l2_querymenu *menu) | ||
1400 | { | ||
1401 | switch (menu->id) { | ||
1402 | case V4L2_CID_POWER_LINE_FREQUENCY: | ||
1403 | switch (menu->index) { | ||
1404 | case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */ | ||
1405 | strcpy((char *) menu->name, "NoFliker"); | ||
1406 | return 0; | ||
1407 | case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ | ||
1408 | strcpy((char *) menu->name, "50 Hz"); | ||
1409 | return 0; | ||
1410 | case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ | ||
1411 | strcpy((char *) menu->name, "60 Hz"); | ||
1412 | return 0; | ||
1413 | } | ||
1414 | break; | ||
1415 | } | ||
1416 | return -EINVAL; | ||
1417 | } | ||
1418 | |||
1419 | /* sub-driver description */ | ||
1420 | static const struct sd_desc sd_desc = { | ||
1421 | .name = MODULE_NAME, | ||
1422 | .ctrls = sd_ctrls, | ||
1423 | .nctrls = ARRAY_SIZE(sd_ctrls), | ||
1424 | .config = sd_config, | ||
1425 | .init = sd_init, | ||
1426 | .start = sd_start, | ||
1427 | .stopN = sd_stopN, | ||
1428 | .pkt_scan = sd_pkt_scan, | ||
1429 | .querymenu = sd_querymenu, | ||
1430 | }; | ||
1431 | |||
1432 | /* -- module initialisation -- */ | ||
1433 | static const __devinitdata struct usb_device_id device_table[] = { | ||
1434 | {USB_DEVICE(0x06f8, 0x3003)}, | ||
1435 | {} | ||
1436 | }; | ||
1437 | |||
1438 | MODULE_DEVICE_TABLE(usb, device_table); | ||
1439 | |||
1440 | /* -- device connect -- */ | ||
1441 | static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
1442 | { | ||
1443 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | ||
1444 | THIS_MODULE); | ||
1445 | } | ||
1446 | |||
1447 | static struct usb_driver sd_driver = { | ||
1448 | .name = MODULE_NAME, | ||
1449 | .id_table = device_table, | ||
1450 | .probe = sd_probe, | ||
1451 | .disconnect = gspca_disconnect, | ||
1452 | #ifdef CONFIG_PM | ||
1453 | .suspend = gspca_suspend, | ||
1454 | .resume = gspca_resume, | ||
1455 | #endif | ||
1456 | }; | ||
1457 | |||
1458 | /* -- module insert / remove -- */ | ||
1459 | static int __init sd_mod_init(void) | ||
1460 | { | ||
1461 | int ret; | ||
1462 | |||
1463 | ret = usb_register(&sd_driver); | ||
1464 | if (ret < 0) | ||
1465 | return ret; | ||
1466 | PDEBUG(D_PROBE, "registered"); | ||
1467 | return 0; | ||
1468 | } | ||
1469 | |||
1470 | static void __exit sd_mod_exit(void) | ||
1471 | { | ||
1472 | usb_deregister(&sd_driver); | ||
1473 | PDEBUG(D_PROBE, "deregistered"); | ||
1474 | } | ||
1475 | |||
1476 | module_init(sd_mod_init); | ||
1477 | module_exit(sd_mod_exit); | ||
diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index 4706a823add0..0c87c3490b1e 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c | |||
@@ -25,6 +25,7 @@ | |||
25 | 25 | ||
26 | #define MODULE_NAME "pac207" | 26 | #define MODULE_NAME "pac207" |
27 | 27 | ||
28 | #include <linux/input.h> | ||
28 | #include "gspca.h" | 29 | #include "gspca.h" |
29 | 30 | ||
30 | MODULE_AUTHOR("Hans de Goede <hdgoede@redhat.com>"); | 31 | MODULE_AUTHOR("Hans de Goede <hdgoede@redhat.com>"); |
@@ -77,7 +78,7 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | |||
77 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); | 78 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); |
78 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | 79 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); |
79 | 80 | ||
80 | static struct ctrl sd_ctrls[] = { | 81 | static const struct ctrl sd_ctrls[] = { |
81 | #define SD_BRIGHTNESS 0 | 82 | #define SD_BRIGHTNESS 0 |
82 | { | 83 | { |
83 | { | 84 | { |
@@ -495,6 +496,25 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) | |||
495 | return 0; | 496 | return 0; |
496 | } | 497 | } |
497 | 498 | ||
499 | #ifdef CONFIG_INPUT | ||
500 | static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, | ||
501 | u8 *data, /* interrupt packet data */ | ||
502 | int len) /* interrput packet length */ | ||
503 | { | ||
504 | int ret = -EINVAL; | ||
505 | |||
506 | if (len == 2 && data[0] == 0x5a && data[1] == 0x5a) { | ||
507 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); | ||
508 | input_sync(gspca_dev->input_dev); | ||
509 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); | ||
510 | input_sync(gspca_dev->input_dev); | ||
511 | ret = 0; | ||
512 | } | ||
513 | |||
514 | return ret; | ||
515 | } | ||
516 | #endif | ||
517 | |||
498 | /* sub-driver description */ | 518 | /* sub-driver description */ |
499 | static const struct sd_desc sd_desc = { | 519 | static const struct sd_desc sd_desc = { |
500 | .name = MODULE_NAME, | 520 | .name = MODULE_NAME, |
@@ -506,6 +526,9 @@ static const struct sd_desc sd_desc = { | |||
506 | .stopN = sd_stopN, | 526 | .stopN = sd_stopN, |
507 | .dq_callback = pac207_do_auto_gain, | 527 | .dq_callback = pac207_do_auto_gain, |
508 | .pkt_scan = sd_pkt_scan, | 528 | .pkt_scan = sd_pkt_scan, |
529 | #ifdef CONFIG_INPUT | ||
530 | .int_pkt_scan = sd_int_pkt_scan, | ||
531 | #endif | ||
509 | }; | 532 | }; |
510 | 533 | ||
511 | /* -- module initialisation -- */ | 534 | /* -- module initialisation -- */ |
diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index de0b66c4b56e..2a68220d1ada 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c | |||
@@ -4,7 +4,9 @@ | |||
4 | * | 4 | * |
5 | * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> | 5 | * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> |
6 | * | 6 | * |
7 | * Separated from Pixart PAC7311 library by Márton Németh <nm127@freemail.hu> | 7 | * Separated from Pixart PAC7311 library by Márton Németh |
8 | * Camera button input handling by Márton Németh <nm127@freemail.hu> | ||
9 | * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu> | ||
8 | * | 10 | * |
9 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by | 12 | * it under the terms of the GNU General Public License as published by |
@@ -22,33 +24,26 @@ | |||
22 | */ | 24 | */ |
23 | 25 | ||
24 | /* Some documentation about various registers as determined by trial and error. | 26 | /* Some documentation about various registers as determined by trial and error. |
25 | When the register addresses differ between the 7202 and the 7311 the 2 | ||
26 | different addresses are written as 7302addr/7311addr, when one of the 2 | ||
27 | addresses is a - sign that register description is not valid for the | ||
28 | matching IC. | ||
29 | 27 | ||
30 | Register page 1: | 28 | Register page 1: |
31 | 29 | ||
32 | Address Description | 30 | Address Description |
33 | -/0x08 Unknown compressor related, must always be 8 except when not | ||
34 | in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 ! | ||
35 | -/0x1b Auto white balance related, bit 0 is AWB enable (inverted) | ||
36 | bits 345 seem to toggle per color gains on/off (inverted) | ||
37 | 0x78 Global control, bit 6 controls the LED (inverted) | 31 | 0x78 Global control, bit 6 controls the LED (inverted) |
38 | -/0x80 JPEG compression ratio ? Best not touched | ||
39 | 32 | ||
40 | Register page 3/4: | 33 | Register page 3: |
41 | 34 | ||
42 | Address Description | 35 | Address Description |
43 | 0x02 Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on | 36 | 0x02 Clock divider 3-63, fps = 90 / val. Must be a multiple of 3 on |
44 | the 7302, so one of 3, 6, 9, ..., except when between 6 and 12? | 37 | the 7302, so one of 3, 6, 9, ..., except when between 6 and 12? |
45 | -/0x0f Master gain 1-245, low value = high gain | 38 | 0x03 Variable framerate ctrl reg2==3: 0 -> ~30 fps, 255 -> ~22fps |
46 | 0x10/- Master gain 0-31 | 39 | 0x04 Another var framerate ctrl reg2==3, reg3==0: 0 -> ~30 fps, |
47 | -/0x10 Another gain 0-15, limited influence (1-2x gain I guess) | 40 | 63 -> ~27 fps, the 2 msb's must always be 1 !! |
41 | 0x05 Another var framerate ctrl reg2==3, reg3==0, reg4==0xc0: | ||
42 | 1 -> ~30 fps, 2 -> ~20 fps | ||
43 | 0x0e Exposure bits 0-7, 0-448, 0 = use full frame time | ||
44 | 0x0f Exposure bit 8, 0-448, 448 = no exposure at all | ||
45 | 0x10 Master gain 0-31 | ||
48 | 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused | 46 | 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused |
49 | -/0x27 Seems to toggle various gains on / off, Setting bit 7 seems to | ||
50 | completely disable the analog amplification block. Set to 0x68 | ||
51 | for max gain, 0x14 for minimal gain. | ||
52 | 47 | ||
53 | The registers are accessed in the following functions: | 48 | The registers are accessed in the following functions: |
54 | 49 | ||
@@ -68,6 +63,7 @@ | |||
68 | 63 | ||
69 | #define MODULE_NAME "pac7302" | 64 | #define MODULE_NAME "pac7302" |
70 | 65 | ||
66 | #include <linux/input.h> | ||
71 | #include <media/v4l2-chip-ident.h> | 67 | #include <media/v4l2-chip-ident.h> |
72 | #include "gspca.h" | 68 | #include "gspca.h" |
73 | 69 | ||
@@ -86,8 +82,8 @@ struct sd { | |||
86 | unsigned char red_balance; | 82 | unsigned char red_balance; |
87 | unsigned char blue_balance; | 83 | unsigned char blue_balance; |
88 | unsigned char gain; | 84 | unsigned char gain; |
89 | unsigned char exposure; | ||
90 | unsigned char autogain; | 85 | unsigned char autogain; |
86 | unsigned short exposure; | ||
91 | __u8 hflip; | 87 | __u8 hflip; |
92 | __u8 vflip; | 88 | __u8 vflip; |
93 | u8 flags; | 89 | u8 flags; |
@@ -124,8 +120,7 @@ static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | |||
124 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | 120 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); |
125 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | 121 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); |
126 | 122 | ||
127 | static struct ctrl sd_ctrls[] = { | 123 | static const struct ctrl sd_ctrls[] = { |
128 | /* This control is pac7302 only */ | ||
129 | { | 124 | { |
130 | { | 125 | { |
131 | .id = V4L2_CID_BRIGHTNESS, | 126 | .id = V4L2_CID_BRIGHTNESS, |
@@ -141,7 +136,6 @@ static struct ctrl sd_ctrls[] = { | |||
141 | .set = sd_setbrightness, | 136 | .set = sd_setbrightness, |
142 | .get = sd_getbrightness, | 137 | .get = sd_getbrightness, |
143 | }, | 138 | }, |
144 | /* This control is for both the 7302 and the 7311 */ | ||
145 | { | 139 | { |
146 | { | 140 | { |
147 | .id = V4L2_CID_CONTRAST, | 141 | .id = V4L2_CID_CONTRAST, |
@@ -157,7 +151,6 @@ static struct ctrl sd_ctrls[] = { | |||
157 | .set = sd_setcontrast, | 151 | .set = sd_setcontrast, |
158 | .get = sd_getcontrast, | 152 | .get = sd_getcontrast, |
159 | }, | 153 | }, |
160 | /* This control is pac7302 only */ | ||
161 | { | 154 | { |
162 | { | 155 | { |
163 | .id = V4L2_CID_SATURATION, | 156 | .id = V4L2_CID_SATURATION, |
@@ -215,7 +208,6 @@ static struct ctrl sd_ctrls[] = { | |||
215 | .set = sd_setbluebalance, | 208 | .set = sd_setbluebalance, |
216 | .get = sd_getbluebalance, | 209 | .get = sd_getbluebalance, |
217 | }, | 210 | }, |
218 | /* All controls below are for both the 7302 and the 7311 */ | ||
219 | { | 211 | { |
220 | { | 212 | { |
221 | .id = V4L2_CID_GAIN, | 213 | .id = V4L2_CID_GAIN, |
@@ -238,11 +230,10 @@ static struct ctrl sd_ctrls[] = { | |||
238 | .type = V4L2_CTRL_TYPE_INTEGER, | 230 | .type = V4L2_CTRL_TYPE_INTEGER, |
239 | .name = "Exposure", | 231 | .name = "Exposure", |
240 | .minimum = 0, | 232 | .minimum = 0, |
241 | #define EXPOSURE_MAX 255 | 233 | .maximum = 1023, |
242 | .maximum = EXPOSURE_MAX, | ||
243 | .step = 1, | 234 | .step = 1, |
244 | #define EXPOSURE_DEF 16 /* 32 ms / 30 fps */ | 235 | #define EXPOSURE_DEF 66 /* 33 ms / 30 fps */ |
245 | #define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */ | 236 | #define EXPOSURE_KNEE 133 /* 66 ms / 15 fps */ |
246 | .default_value = EXPOSURE_DEF, | 237 | .default_value = EXPOSURE_DEF, |
247 | }, | 238 | }, |
248 | .set = sd_setexposure, | 239 | .set = sd_setexposure, |
@@ -301,7 +292,6 @@ static const struct v4l2_pix_format vga_mode[] = { | |||
301 | }; | 292 | }; |
302 | 293 | ||
303 | #define LOAD_PAGE3 255 | 294 | #define LOAD_PAGE3 255 |
304 | #define LOAD_PAGE4 254 | ||
305 | #define END_OF_SEQUENCE 0 | 295 | #define END_OF_SEQUENCE 0 |
306 | 296 | ||
307 | /* pac 7302 */ | 297 | /* pac 7302 */ |
@@ -379,7 +369,7 @@ static const __u8 start_7302[] = { | |||
379 | #define SKIP 0xaa | 369 | #define SKIP 0xaa |
380 | /* page 3 - the value SKIP says skip the index - see reg_w_page() */ | 370 | /* page 3 - the value SKIP says skip the index - see reg_w_page() */ |
381 | static const __u8 page3_7302[] = { | 371 | static const __u8 page3_7302[] = { |
382 | 0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16, | 372 | 0x90, 0x40, 0x03, 0x00, 0xc0, 0x01, 0x14, 0x16, |
383 | 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00, | 373 | 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00, |
384 | 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 374 | 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
385 | 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00, | 375 | 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00, |
@@ -388,7 +378,7 @@ static const __u8 page3_7302[] = { | |||
388 | 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00, | 378 | 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00, |
389 | 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 379 | 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
390 | 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00, | 380 | 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00, |
391 | 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00, | 381 | SKIP, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00, |
392 | 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 382 | 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
393 | 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00, | 383 | 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00, |
394 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 384 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
@@ -401,12 +391,14 @@ static const __u8 page3_7302[] = { | |||
401 | 0x00 | 391 | 0x00 |
402 | }; | 392 | }; |
403 | 393 | ||
404 | static int reg_w_buf(struct gspca_dev *gspca_dev, | 394 | static void reg_w_buf(struct gspca_dev *gspca_dev, |
405 | __u8 index, | 395 | __u8 index, |
406 | const char *buffer, int len) | 396 | const char *buffer, int len) |
407 | { | 397 | { |
408 | int ret; | 398 | int ret; |
409 | 399 | ||
400 | if (gspca_dev->usb_err < 0) | ||
401 | return; | ||
410 | memcpy(gspca_dev->usb_buf, buffer, len); | 402 | memcpy(gspca_dev->usb_buf, buffer, len); |
411 | ret = usb_control_msg(gspca_dev->dev, | 403 | ret = usb_control_msg(gspca_dev->dev, |
412 | usb_sndctrlpipe(gspca_dev->dev, 0), | 404 | usb_sndctrlpipe(gspca_dev->dev, 0), |
@@ -415,20 +407,23 @@ static int reg_w_buf(struct gspca_dev *gspca_dev, | |||
415 | 0, /* value */ | 407 | 0, /* value */ |
416 | index, gspca_dev->usb_buf, len, | 408 | index, gspca_dev->usb_buf, len, |
417 | 500); | 409 | 500); |
418 | if (ret < 0) | 410 | if (ret < 0) { |
419 | PDEBUG(D_ERR, "reg_w_buf(): " | 411 | PDEBUG(D_ERR, "reg_w_buf(): " |
420 | "Failed to write registers to index 0x%x, error %i", | 412 | "Failed to write registers to index 0x%x, error %i", |
421 | index, ret); | 413 | index, ret); |
422 | return ret; | 414 | gspca_dev->usb_err = ret; |
415 | } | ||
423 | } | 416 | } |
424 | 417 | ||
425 | 418 | ||
426 | static int reg_w(struct gspca_dev *gspca_dev, | 419 | static void reg_w(struct gspca_dev *gspca_dev, |
427 | __u8 index, | 420 | __u8 index, |
428 | __u8 value) | 421 | __u8 value) |
429 | { | 422 | { |
430 | int ret; | 423 | int ret; |
431 | 424 | ||
425 | if (gspca_dev->usb_err < 0) | ||
426 | return; | ||
432 | gspca_dev->usb_buf[0] = value; | 427 | gspca_dev->usb_buf[0] = value; |
433 | ret = usb_control_msg(gspca_dev->dev, | 428 | ret = usb_control_msg(gspca_dev->dev, |
434 | usb_sndctrlpipe(gspca_dev->dev, 0), | 429 | usb_sndctrlpipe(gspca_dev->dev, 0), |
@@ -436,32 +431,32 @@ static int reg_w(struct gspca_dev *gspca_dev, | |||
436 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 431 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
437 | 0, index, gspca_dev->usb_buf, 1, | 432 | 0, index, gspca_dev->usb_buf, 1, |
438 | 500); | 433 | 500); |
439 | if (ret < 0) | 434 | if (ret < 0) { |
440 | PDEBUG(D_ERR, "reg_w(): " | 435 | PDEBUG(D_ERR, "reg_w(): " |
441 | "Failed to write register to index 0x%x, value 0x%x, error %i", | 436 | "Failed to write register to index 0x%x, value 0x%x, error %i", |
442 | index, value, ret); | 437 | index, value, ret); |
443 | return ret; | 438 | gspca_dev->usb_err = ret; |
439 | } | ||
444 | } | 440 | } |
445 | 441 | ||
446 | static int reg_w_seq(struct gspca_dev *gspca_dev, | 442 | static void reg_w_seq(struct gspca_dev *gspca_dev, |
447 | const __u8 *seq, int len) | 443 | const __u8 *seq, int len) |
448 | { | 444 | { |
449 | int ret = 0; | ||
450 | while (--len >= 0) { | 445 | while (--len >= 0) { |
451 | if (0 <= ret) | 446 | reg_w(gspca_dev, seq[0], seq[1]); |
452 | ret = reg_w(gspca_dev, seq[0], seq[1]); | ||
453 | seq += 2; | 447 | seq += 2; |
454 | } | 448 | } |
455 | return ret; | ||
456 | } | 449 | } |
457 | 450 | ||
458 | /* load the beginning of a page */ | 451 | /* load the beginning of a page */ |
459 | static int reg_w_page(struct gspca_dev *gspca_dev, | 452 | static void reg_w_page(struct gspca_dev *gspca_dev, |
460 | const __u8 *page, int len) | 453 | const __u8 *page, int len) |
461 | { | 454 | { |
462 | int index; | 455 | int index; |
463 | int ret = 0; | 456 | int ret = 0; |
464 | 457 | ||
458 | if (gspca_dev->usb_err < 0) | ||
459 | return; | ||
465 | for (index = 0; index < len; index++) { | 460 | for (index = 0; index < len; index++) { |
466 | if (page[index] == SKIP) /* skip this index */ | 461 | if (page[index] == SKIP) /* skip this index */ |
467 | continue; | 462 | continue; |
@@ -477,56 +472,47 @@ static int reg_w_page(struct gspca_dev *gspca_dev, | |||
477 | "Failed to write register to index 0x%x, " | 472 | "Failed to write register to index 0x%x, " |
478 | "value 0x%x, error %i", | 473 | "value 0x%x, error %i", |
479 | index, page[index], ret); | 474 | index, page[index], ret); |
475 | gspca_dev->usb_err = ret; | ||
480 | break; | 476 | break; |
481 | } | 477 | } |
482 | } | 478 | } |
483 | return ret; | ||
484 | } | 479 | } |
485 | 480 | ||
486 | /* output a variable sequence */ | 481 | /* output a variable sequence */ |
487 | static int reg_w_var(struct gspca_dev *gspca_dev, | 482 | static void reg_w_var(struct gspca_dev *gspca_dev, |
488 | const __u8 *seq, | 483 | const __u8 *seq, |
489 | const __u8 *page3, unsigned int page3_len, | 484 | const __u8 *page3, unsigned int page3_len) |
490 | const __u8 *page4, unsigned int page4_len) | ||
491 | { | 485 | { |
492 | int index, len; | 486 | int index, len; |
493 | int ret = 0; | ||
494 | 487 | ||
495 | for (;;) { | 488 | for (;;) { |
496 | index = *seq++; | 489 | index = *seq++; |
497 | len = *seq++; | 490 | len = *seq++; |
498 | switch (len) { | 491 | switch (len) { |
499 | case END_OF_SEQUENCE: | 492 | case END_OF_SEQUENCE: |
500 | return ret; | 493 | return; |
501 | case LOAD_PAGE4: | ||
502 | ret = reg_w_page(gspca_dev, page4, page4_len); | ||
503 | break; | ||
504 | case LOAD_PAGE3: | 494 | case LOAD_PAGE3: |
505 | ret = reg_w_page(gspca_dev, page3, page3_len); | 495 | reg_w_page(gspca_dev, page3, page3_len); |
506 | break; | 496 | break; |
507 | default: | 497 | default: |
508 | if (len > USB_BUF_SZ) { | 498 | if (len > USB_BUF_SZ) { |
509 | PDEBUG(D_ERR|D_STREAM, | 499 | PDEBUG(D_ERR|D_STREAM, |
510 | "Incorrect variable sequence"); | 500 | "Incorrect variable sequence"); |
511 | return -EINVAL; | 501 | return; |
512 | } | 502 | } |
513 | while (len > 0) { | 503 | while (len > 0) { |
514 | if (len < 8) { | 504 | if (len < 8) { |
515 | ret = reg_w_buf(gspca_dev, | 505 | reg_w_buf(gspca_dev, |
516 | index, seq, len); | 506 | index, seq, len); |
517 | if (ret < 0) | ||
518 | return ret; | ||
519 | seq += len; | 507 | seq += len; |
520 | break; | 508 | break; |
521 | } | 509 | } |
522 | ret = reg_w_buf(gspca_dev, index, seq, 8); | 510 | reg_w_buf(gspca_dev, index, seq, 8); |
523 | seq += 8; | 511 | seq += 8; |
524 | index += 8; | 512 | index += 8; |
525 | len -= 8; | 513 | len -= 8; |
526 | } | 514 | } |
527 | } | 515 | } |
528 | if (ret < 0) | ||
529 | return ret; | ||
530 | } | 516 | } |
531 | /* not reached */ | 517 | /* not reached */ |
532 | } | 518 | } |
@@ -560,11 +546,10 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
560 | } | 546 | } |
561 | 547 | ||
562 | /* This function is used by pac7302 only */ | 548 | /* This function is used by pac7302 only */ |
563 | static int setbrightcont(struct gspca_dev *gspca_dev) | 549 | static void setbrightcont(struct gspca_dev *gspca_dev) |
564 | { | 550 | { |
565 | struct sd *sd = (struct sd *) gspca_dev; | 551 | struct sd *sd = (struct sd *) gspca_dev; |
566 | int i, v; | 552 | int i, v; |
567 | int ret; | ||
568 | static const __u8 max[10] = | 553 | static const __u8 max[10] = |
569 | {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb, | 554 | {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb, |
570 | 0xd4, 0xec}; | 555 | 0xd4, 0xec}; |
@@ -572,7 +557,7 @@ static int setbrightcont(struct gspca_dev *gspca_dev) | |||
572 | {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17, | 557 | {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17, |
573 | 0x11, 0x0b}; | 558 | 0x11, 0x0b}; |
574 | 559 | ||
575 | ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | 560 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ |
576 | for (i = 0; i < 10; i++) { | 561 | for (i = 0; i < 10; i++) { |
577 | v = max[i]; | 562 | v = max[i]; |
578 | v += (sd->brightness - BRIGHTNESS_MAX) | 563 | v += (sd->brightness - BRIGHTNESS_MAX) |
@@ -582,136 +567,121 @@ static int setbrightcont(struct gspca_dev *gspca_dev) | |||
582 | v = 0; | 567 | v = 0; |
583 | else if (v > 0xff) | 568 | else if (v > 0xff) |
584 | v = 0xff; | 569 | v = 0xff; |
585 | if (0 <= ret) | 570 | reg_w(gspca_dev, 0xa2 + i, v); |
586 | ret = reg_w(gspca_dev, 0xa2 + i, v); | ||
587 | } | 571 | } |
588 | if (0 <= ret) | 572 | reg_w(gspca_dev, 0xdc, 0x01); |
589 | ret = reg_w(gspca_dev, 0xdc, 0x01); | ||
590 | return ret; | ||
591 | } | 573 | } |
592 | 574 | ||
593 | /* This function is used by pac7302 only */ | 575 | /* This function is used by pac7302 only */ |
594 | static int setcolors(struct gspca_dev *gspca_dev) | 576 | static void setcolors(struct gspca_dev *gspca_dev) |
595 | { | 577 | { |
596 | struct sd *sd = (struct sd *) gspca_dev; | 578 | struct sd *sd = (struct sd *) gspca_dev; |
597 | int i, v; | 579 | int i, v; |
598 | int ret; | ||
599 | static const int a[9] = | 580 | static const int a[9] = |
600 | {217, -212, 0, -101, 170, -67, -38, -315, 355}; | 581 | {217, -212, 0, -101, 170, -67, -38, -315, 355}; |
601 | static const int b[9] = | 582 | static const int b[9] = |
602 | {19, 106, 0, 19, 106, 1, 19, 106, 1}; | 583 | {19, 106, 0, 19, 106, 1, 19, 106, 1}; |
603 | 584 | ||
604 | ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ | 585 | reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ |
605 | if (0 <= ret) | 586 | reg_w(gspca_dev, 0x11, 0x01); |
606 | ret = reg_w(gspca_dev, 0x11, 0x01); | 587 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ |
607 | if (0 <= ret) | ||
608 | ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | ||
609 | for (i = 0; i < 9; i++) { | 588 | for (i = 0; i < 9; i++) { |
610 | v = a[i] * sd->colors / COLOR_MAX + b[i]; | 589 | v = a[i] * sd->colors / COLOR_MAX + b[i]; |
611 | if (0 <= ret) | 590 | reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); |
612 | ret = reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); | 591 | reg_w(gspca_dev, 0x0f + 2 * i + 1, v); |
613 | if (0 <= ret) | ||
614 | ret = reg_w(gspca_dev, 0x0f + 2 * i + 1, v); | ||
615 | } | 592 | } |
616 | if (0 <= ret) | 593 | reg_w(gspca_dev, 0xdc, 0x01); |
617 | ret = reg_w(gspca_dev, 0xdc, 0x01); | ||
618 | PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors); | 594 | PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors); |
619 | return ret; | ||
620 | } | 595 | } |
621 | 596 | ||
622 | static int setwhitebalance(struct gspca_dev *gspca_dev) | 597 | static void setwhitebalance(struct gspca_dev *gspca_dev) |
623 | { | 598 | { |
624 | struct sd *sd = (struct sd *) gspca_dev; | 599 | struct sd *sd = (struct sd *) gspca_dev; |
625 | int ret; | ||
626 | 600 | ||
627 | ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | 601 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ |
628 | if (0 <= ret) | 602 | reg_w(gspca_dev, 0xc6, sd->white_balance); |
629 | ret = reg_w(gspca_dev, 0xc6, sd->white_balance); | ||
630 | 603 | ||
631 | if (0 <= ret) | 604 | reg_w(gspca_dev, 0xdc, 0x01); |
632 | ret = reg_w(gspca_dev, 0xdc, 0x01); | ||
633 | PDEBUG(D_CONF|D_STREAM, "white_balance: %i", sd->white_balance); | 605 | PDEBUG(D_CONF|D_STREAM, "white_balance: %i", sd->white_balance); |
634 | return ret; | ||
635 | } | 606 | } |
636 | 607 | ||
637 | static int setredbalance(struct gspca_dev *gspca_dev) | 608 | static void setredbalance(struct gspca_dev *gspca_dev) |
638 | { | 609 | { |
639 | struct sd *sd = (struct sd *) gspca_dev; | 610 | struct sd *sd = (struct sd *) gspca_dev; |
640 | int ret; | ||
641 | 611 | ||
642 | ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | 612 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ |
643 | if (0 <= ret) | 613 | reg_w(gspca_dev, 0xc5, sd->red_balance); |
644 | ret = reg_w(gspca_dev, 0xc5, sd->red_balance); | ||
645 | 614 | ||
646 | if (0 <= ret) | 615 | reg_w(gspca_dev, 0xdc, 0x01); |
647 | ret = reg_w(gspca_dev, 0xdc, 0x01); | ||
648 | PDEBUG(D_CONF|D_STREAM, "red_balance: %i", sd->red_balance); | 616 | PDEBUG(D_CONF|D_STREAM, "red_balance: %i", sd->red_balance); |
649 | return ret; | ||
650 | } | 617 | } |
651 | 618 | ||
652 | static int setbluebalance(struct gspca_dev *gspca_dev) | 619 | static void setbluebalance(struct gspca_dev *gspca_dev) |
653 | { | 620 | { |
654 | struct sd *sd = (struct sd *) gspca_dev; | 621 | struct sd *sd = (struct sd *) gspca_dev; |
655 | int ret; | ||
656 | 622 | ||
657 | ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | 623 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ |
658 | if (0 <= ret) | 624 | reg_w(gspca_dev, 0xc7, sd->blue_balance); |
659 | ret = reg_w(gspca_dev, 0xc7, sd->blue_balance); | ||
660 | 625 | ||
661 | if (0 <= ret) | 626 | reg_w(gspca_dev, 0xdc, 0x01); |
662 | ret = reg_w(gspca_dev, 0xdc, 0x01); | ||
663 | PDEBUG(D_CONF|D_STREAM, "blue_balance: %i", sd->blue_balance); | 627 | PDEBUG(D_CONF|D_STREAM, "blue_balance: %i", sd->blue_balance); |
664 | return ret; | ||
665 | } | 628 | } |
666 | 629 | ||
667 | static int setgain(struct gspca_dev *gspca_dev) | 630 | static void setgain(struct gspca_dev *gspca_dev) |
668 | { | 631 | { |
669 | struct sd *sd = (struct sd *) gspca_dev; | 632 | struct sd *sd = (struct sd *) gspca_dev; |
670 | int ret; | ||
671 | 633 | ||
672 | ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ | 634 | reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ |
673 | if (0 <= ret) | 635 | reg_w(gspca_dev, 0x10, sd->gain >> 3); |
674 | ret = reg_w(gspca_dev, 0x10, sd->gain >> 3); | ||
675 | 636 | ||
676 | /* load registers to sensor (Bit 0, auto clear) */ | 637 | /* load registers to sensor (Bit 0, auto clear) */ |
677 | if (0 <= ret) | 638 | reg_w(gspca_dev, 0x11, 0x01); |
678 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
679 | return ret; | ||
680 | } | 639 | } |
681 | 640 | ||
682 | static int setexposure(struct gspca_dev *gspca_dev) | 641 | static void setexposure(struct gspca_dev *gspca_dev) |
683 | { | 642 | { |
684 | struct sd *sd = (struct sd *) gspca_dev; | 643 | struct sd *sd = (struct sd *) gspca_dev; |
685 | int ret; | 644 | __u8 clockdiv; |
686 | __u8 reg; | 645 | __u16 exposure; |
687 | 646 | ||
688 | /* register 2 of frame 3/4 contains the clock divider configuring the | 647 | /* register 2 of frame 3 contains the clock divider configuring the |
689 | no fps according to the formula: 60 / reg. sd->exposure is the | 648 | no fps according to the formula: 90 / reg. sd->exposure is the |
690 | desired exposure time in ms. */ | 649 | desired exposure time in 0.5 ms. */ |
691 | reg = 120 * sd->exposure / 1000; | 650 | clockdiv = (90 * sd->exposure + 1999) / 2000; |
692 | if (reg < 2) | 651 | |
693 | reg = 2; | 652 | /* Note clockdiv = 3 also works, but when running at 30 fps, depending |
694 | else if (reg > 63) | 653 | on the scene being recorded, the camera switches to another |
695 | reg = 63; | 654 | quantization table for certain JPEG blocks, and we don't know how |
696 | 655 | to decompress these blocks. So we cap the framerate at 15 fps */ | |
697 | /* On the pac7302 reg2 MUST be a multiple of 3, so round it to | 656 | if (clockdiv < 6) |
698 | the nearest multiple of 3, except when between 6 and 12? */ | 657 | clockdiv = 6; |
699 | if (reg < 6 || reg > 12) | 658 | else if (clockdiv > 63) |
700 | reg = ((reg + 1) / 3) * 3; | 659 | clockdiv = 63; |
701 | ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ | 660 | |
702 | if (0 <= ret) | 661 | /* reg2 MUST be a multiple of 3, except when between 6 and 12? |
703 | ret = reg_w(gspca_dev, 0x02, reg); | 662 | Always round up, otherwise we cannot get the desired frametime |
663 | using the partial frame time exposure control */ | ||
664 | if (clockdiv < 6 || clockdiv > 12) | ||
665 | clockdiv = ((clockdiv + 2) / 3) * 3; | ||
666 | |||
667 | /* frame exposure time in ms = 1000 * clockdiv / 90 -> | ||
668 | exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90) */ | ||
669 | exposure = (sd->exposure * 45 * 448) / (1000 * clockdiv); | ||
670 | /* 0 = use full frametime, 448 = no exposure, reverse it */ | ||
671 | exposure = 448 - exposure; | ||
672 | |||
673 | reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ | ||
674 | reg_w(gspca_dev, 0x02, clockdiv); | ||
675 | reg_w(gspca_dev, 0x0e, exposure & 0xff); | ||
676 | reg_w(gspca_dev, 0x0f, exposure >> 8); | ||
704 | 677 | ||
705 | /* load registers to sensor (Bit 0, auto clear) */ | 678 | /* load registers to sensor (Bit 0, auto clear) */ |
706 | if (0 <= ret) | 679 | reg_w(gspca_dev, 0x11, 0x01); |
707 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
708 | return ret; | ||
709 | } | 680 | } |
710 | 681 | ||
711 | static int sethvflip(struct gspca_dev *gspca_dev) | 682 | static void sethvflip(struct gspca_dev *gspca_dev) |
712 | { | 683 | { |
713 | struct sd *sd = (struct sd *) gspca_dev; | 684 | struct sd *sd = (struct sd *) gspca_dev; |
714 | int ret; | ||
715 | u8 data, hflip, vflip; | 685 | u8 data, hflip, vflip; |
716 | 686 | ||
717 | hflip = sd->hflip; | 687 | hflip = sd->hflip; |
@@ -721,48 +691,37 @@ static int sethvflip(struct gspca_dev *gspca_dev) | |||
721 | if (sd->flags & FL_VFLIP) | 691 | if (sd->flags & FL_VFLIP) |
722 | vflip = !vflip; | 692 | vflip = !vflip; |
723 | 693 | ||
724 | ret = reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ | 694 | reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ |
725 | data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00); | 695 | data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00); |
726 | if (0 <= ret) | 696 | reg_w(gspca_dev, 0x21, data); |
727 | ret = reg_w(gspca_dev, 0x21, data); | 697 | |
728 | /* load registers to sensor (Bit 0, auto clear) */ | 698 | /* load registers to sensor (Bit 0, auto clear) */ |
729 | if (0 <= ret) | 699 | reg_w(gspca_dev, 0x11, 0x01); |
730 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
731 | return ret; | ||
732 | } | 700 | } |
733 | 701 | ||
734 | /* this function is called at probe and resume time for pac7302 */ | 702 | /* this function is called at probe and resume time for pac7302 */ |
735 | static int sd_init(struct gspca_dev *gspca_dev) | 703 | static int sd_init(struct gspca_dev *gspca_dev) |
736 | { | 704 | { |
737 | return reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2); | 705 | reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2); |
706 | return gspca_dev->usb_err; | ||
738 | } | 707 | } |
739 | 708 | ||
740 | static int sd_start(struct gspca_dev *gspca_dev) | 709 | static int sd_start(struct gspca_dev *gspca_dev) |
741 | { | 710 | { |
742 | struct sd *sd = (struct sd *) gspca_dev; | 711 | struct sd *sd = (struct sd *) gspca_dev; |
743 | int ret = 0; | ||
744 | 712 | ||
745 | sd->sof_read = 0; | 713 | sd->sof_read = 0; |
746 | 714 | ||
747 | ret = reg_w_var(gspca_dev, start_7302, | 715 | reg_w_var(gspca_dev, start_7302, |
748 | page3_7302, sizeof(page3_7302), | 716 | page3_7302, sizeof(page3_7302)); |
749 | NULL, 0); | 717 | setbrightcont(gspca_dev); |
750 | if (0 <= ret) | 718 | setcolors(gspca_dev); |
751 | ret = setbrightcont(gspca_dev); | 719 | setwhitebalance(gspca_dev); |
752 | if (0 <= ret) | 720 | setredbalance(gspca_dev); |
753 | ret = setcolors(gspca_dev); | 721 | setbluebalance(gspca_dev); |
754 | if (0 <= ret) | 722 | setgain(gspca_dev); |
755 | ret = setwhitebalance(gspca_dev); | 723 | setexposure(gspca_dev); |
756 | if (0 <= ret) | 724 | sethvflip(gspca_dev); |
757 | ret = setredbalance(gspca_dev); | ||
758 | if (0 <= ret) | ||
759 | ret = setbluebalance(gspca_dev); | ||
760 | if (0 <= ret) | ||
761 | ret = setgain(gspca_dev); | ||
762 | if (0 <= ret) | ||
763 | ret = setexposure(gspca_dev); | ||
764 | if (0 <= ret) | ||
765 | ret = sethvflip(gspca_dev); | ||
766 | 725 | ||
767 | /* only resolution 640x480 is supported for pac7302 */ | 726 | /* only resolution 640x480 is supported for pac7302 */ |
768 | 727 | ||
@@ -771,34 +730,27 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
771 | atomic_set(&sd->avg_lum, -1); | 730 | atomic_set(&sd->avg_lum, -1); |
772 | 731 | ||
773 | /* start stream */ | 732 | /* start stream */ |
774 | if (0 <= ret) | 733 | reg_w(gspca_dev, 0xff, 0x01); |
775 | ret = reg_w(gspca_dev, 0xff, 0x01); | 734 | reg_w(gspca_dev, 0x78, 0x01); |
776 | if (0 <= ret) | ||
777 | ret = reg_w(gspca_dev, 0x78, 0x01); | ||
778 | 735 | ||
779 | return ret; | 736 | return gspca_dev->usb_err; |
780 | } | 737 | } |
781 | 738 | ||
782 | static void sd_stopN(struct gspca_dev *gspca_dev) | 739 | static void sd_stopN(struct gspca_dev *gspca_dev) |
783 | { | 740 | { |
784 | int ret; | ||
785 | 741 | ||
786 | /* stop stream */ | 742 | /* stop stream */ |
787 | ret = reg_w(gspca_dev, 0xff, 0x01); | 743 | reg_w(gspca_dev, 0xff, 0x01); |
788 | if (0 <= ret) | 744 | reg_w(gspca_dev, 0x78, 0x00); |
789 | ret = reg_w(gspca_dev, 0x78, 0x00); | ||
790 | } | 745 | } |
791 | 746 | ||
792 | /* called on streamoff with alt 0 and on disconnect for pac7302 */ | 747 | /* called on streamoff with alt 0 and on disconnect for pac7302 */ |
793 | static void sd_stop0(struct gspca_dev *gspca_dev) | 748 | static void sd_stop0(struct gspca_dev *gspca_dev) |
794 | { | 749 | { |
795 | int ret; | ||
796 | |||
797 | if (!gspca_dev->present) | 750 | if (!gspca_dev->present) |
798 | return; | 751 | return; |
799 | ret = reg_w(gspca_dev, 0xff, 0x01); | 752 | reg_w(gspca_dev, 0xff, 0x01); |
800 | if (0 <= ret) | 753 | reg_w(gspca_dev, 0x78, 0x40); |
801 | ret = reg_w(gspca_dev, 0x78, 0x40); | ||
802 | } | 754 | } |
803 | 755 | ||
804 | /* Include pac common sof detection functions */ | 756 | /* Include pac common sof detection functions */ |
@@ -808,22 +760,13 @@ static void do_autogain(struct gspca_dev *gspca_dev) | |||
808 | { | 760 | { |
809 | struct sd *sd = (struct sd *) gspca_dev; | 761 | struct sd *sd = (struct sd *) gspca_dev; |
810 | int avg_lum = atomic_read(&sd->avg_lum); | 762 | int avg_lum = atomic_read(&sd->avg_lum); |
811 | int desired_lum, deadzone; | 763 | int desired_lum; |
764 | const int deadzone = 30; | ||
812 | 765 | ||
813 | if (avg_lum == -1) | 766 | if (avg_lum == -1) |
814 | return; | 767 | return; |
815 | 768 | ||
816 | desired_lum = 270 + sd->brightness * 4; | 769 | desired_lum = 270 + sd->brightness; |
817 | /* Hack hack, with the 7202 the first exposure step is | ||
818 | pretty large, so if we're about to make the first | ||
819 | exposure increase make the deadzone large to avoid | ||
820 | oscilating */ | ||
821 | if (desired_lum > avg_lum && sd->gain == GAIN_DEF && | ||
822 | sd->exposure > EXPOSURE_DEF && | ||
823 | sd->exposure < 42) | ||
824 | deadzone = 90; | ||
825 | else | ||
826 | deadzone = 30; | ||
827 | 770 | ||
828 | if (sd->autogain_ignore_frames > 0) | 771 | if (sd->autogain_ignore_frames > 0) |
829 | sd->autogain_ignore_frames--; | 772 | sd->autogain_ignore_frames--; |
@@ -947,7 +890,7 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | |||
947 | sd->brightness = val; | 890 | sd->brightness = val; |
948 | if (gspca_dev->streaming) | 891 | if (gspca_dev->streaming) |
949 | setbrightcont(gspca_dev); | 892 | setbrightcont(gspca_dev); |
950 | return 0; | 893 | return gspca_dev->usb_err; |
951 | } | 894 | } |
952 | 895 | ||
953 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | 896 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -966,7 +909,7 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | |||
966 | if (gspca_dev->streaming) { | 909 | if (gspca_dev->streaming) { |
967 | setbrightcont(gspca_dev); | 910 | setbrightcont(gspca_dev); |
968 | } | 911 | } |
969 | return 0; | 912 | return gspca_dev->usb_err; |
970 | } | 913 | } |
971 | 914 | ||
972 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | 915 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -984,7 +927,7 @@ static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) | |||
984 | sd->colors = val; | 927 | sd->colors = val; |
985 | if (gspca_dev->streaming) | 928 | if (gspca_dev->streaming) |
986 | setcolors(gspca_dev); | 929 | setcolors(gspca_dev); |
987 | return 0; | 930 | return gspca_dev->usb_err; |
988 | } | 931 | } |
989 | 932 | ||
990 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) | 933 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -998,14 +941,11 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) | |||
998 | static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val) | 941 | static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val) |
999 | { | 942 | { |
1000 | struct sd *sd = (struct sd *) gspca_dev; | 943 | struct sd *sd = (struct sd *) gspca_dev; |
1001 | int ret = 0; | ||
1002 | 944 | ||
1003 | sd->white_balance = val; | 945 | sd->white_balance = val; |
1004 | if (gspca_dev->streaming) | 946 | if (gspca_dev->streaming) |
1005 | ret = setwhitebalance(gspca_dev); | 947 | setwhitebalance(gspca_dev); |
1006 | if (0 <= ret) | 948 | return gspca_dev->usb_err; |
1007 | ret = 0; | ||
1008 | return ret; | ||
1009 | } | 949 | } |
1010 | 950 | ||
1011 | static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val) | 951 | static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -1019,14 +959,11 @@ static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val) | |||
1019 | static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val) | 959 | static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val) |
1020 | { | 960 | { |
1021 | struct sd *sd = (struct sd *) gspca_dev; | 961 | struct sd *sd = (struct sd *) gspca_dev; |
1022 | int ret = 0; | ||
1023 | 962 | ||
1024 | sd->red_balance = val; | 963 | sd->red_balance = val; |
1025 | if (gspca_dev->streaming) | 964 | if (gspca_dev->streaming) |
1026 | ret = setredbalance(gspca_dev); | 965 | setredbalance(gspca_dev); |
1027 | if (0 <= ret) | 966 | return gspca_dev->usb_err; |
1028 | ret = 0; | ||
1029 | return ret; | ||
1030 | } | 967 | } |
1031 | 968 | ||
1032 | static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val) | 969 | static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -1040,14 +977,11 @@ static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val) | |||
1040 | static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val) | 977 | static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val) |
1041 | { | 978 | { |
1042 | struct sd *sd = (struct sd *) gspca_dev; | 979 | struct sd *sd = (struct sd *) gspca_dev; |
1043 | int ret = 0; | ||
1044 | 980 | ||
1045 | sd->blue_balance = val; | 981 | sd->blue_balance = val; |
1046 | if (gspca_dev->streaming) | 982 | if (gspca_dev->streaming) |
1047 | ret = setbluebalance(gspca_dev); | 983 | setbluebalance(gspca_dev); |
1048 | if (0 <= ret) | 984 | return gspca_dev->usb_err; |
1049 | ret = 0; | ||
1050 | return ret; | ||
1051 | } | 985 | } |
1052 | 986 | ||
1053 | static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val) | 987 | static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -1065,7 +999,7 @@ static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) | |||
1065 | sd->gain = val; | 999 | sd->gain = val; |
1066 | if (gspca_dev->streaming) | 1000 | if (gspca_dev->streaming) |
1067 | setgain(gspca_dev); | 1001 | setgain(gspca_dev); |
1068 | return 0; | 1002 | return gspca_dev->usb_err; |
1069 | } | 1003 | } |
1070 | 1004 | ||
1071 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) | 1005 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -1083,7 +1017,7 @@ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) | |||
1083 | sd->exposure = val; | 1017 | sd->exposure = val; |
1084 | if (gspca_dev->streaming) | 1018 | if (gspca_dev->streaming) |
1085 | setexposure(gspca_dev); | 1019 | setexposure(gspca_dev); |
1086 | return 0; | 1020 | return gspca_dev->usb_err; |
1087 | } | 1021 | } |
1088 | 1022 | ||
1089 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) | 1023 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -1114,7 +1048,7 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | |||
1114 | } | 1048 | } |
1115 | } | 1049 | } |
1116 | 1050 | ||
1117 | return 0; | 1051 | return gspca_dev->usb_err; |
1118 | } | 1052 | } |
1119 | 1053 | ||
1120 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) | 1054 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -1132,7 +1066,7 @@ static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) | |||
1132 | sd->hflip = val; | 1066 | sd->hflip = val; |
1133 | if (gspca_dev->streaming) | 1067 | if (gspca_dev->streaming) |
1134 | sethvflip(gspca_dev); | 1068 | sethvflip(gspca_dev); |
1135 | return 0; | 1069 | return gspca_dev->usb_err; |
1136 | } | 1070 | } |
1137 | 1071 | ||
1138 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) | 1072 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -1150,7 +1084,7 @@ static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) | |||
1150 | sd->vflip = val; | 1084 | sd->vflip = val; |
1151 | if (gspca_dev->streaming) | 1085 | if (gspca_dev->streaming) |
1152 | sethvflip(gspca_dev); | 1086 | sethvflip(gspca_dev); |
1153 | return 0; | 1087 | return gspca_dev->usb_err; |
1154 | } | 1088 | } |
1155 | 1089 | ||
1156 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) | 1090 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -1165,7 +1099,6 @@ static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) | |||
1165 | static int sd_dbg_s_register(struct gspca_dev *gspca_dev, | 1099 | static int sd_dbg_s_register(struct gspca_dev *gspca_dev, |
1166 | struct v4l2_dbg_register *reg) | 1100 | struct v4l2_dbg_register *reg) |
1167 | { | 1101 | { |
1168 | int ret = -EINVAL; | ||
1169 | __u8 index; | 1102 | __u8 index; |
1170 | __u8 value; | 1103 | __u8 value; |
1171 | 1104 | ||
@@ -1185,14 +1118,12 @@ static int sd_dbg_s_register(struct gspca_dev *gspca_dev, | |||
1185 | /* Note that there shall be no access to other page | 1118 | /* Note that there shall be no access to other page |
1186 | by any other function between the page swith and | 1119 | by any other function between the page swith and |
1187 | the actual register write */ | 1120 | the actual register write */ |
1188 | ret = reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | 1121 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ |
1189 | if (0 <= ret) | 1122 | reg_w(gspca_dev, index, value); |
1190 | ret = reg_w(gspca_dev, index, value); | ||
1191 | 1123 | ||
1192 | if (0 <= ret) | 1124 | reg_w(gspca_dev, 0xdc, 0x01); |
1193 | ret = reg_w(gspca_dev, 0xdc, 0x01); | ||
1194 | } | 1125 | } |
1195 | return ret; | 1126 | return gspca_dev->usb_err; |
1196 | } | 1127 | } |
1197 | 1128 | ||
1198 | static int sd_chip_ident(struct gspca_dev *gspca_dev, | 1129 | static int sd_chip_ident(struct gspca_dev *gspca_dev, |
@@ -1210,8 +1141,39 @@ static int sd_chip_ident(struct gspca_dev *gspca_dev, | |||
1210 | } | 1141 | } |
1211 | #endif | 1142 | #endif |
1212 | 1143 | ||
1144 | #ifdef CONFIG_INPUT | ||
1145 | static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, | ||
1146 | u8 *data, /* interrupt packet data */ | ||
1147 | int len) /* interrput packet length */ | ||
1148 | { | ||
1149 | int ret = -EINVAL; | ||
1150 | u8 data0, data1; | ||
1151 | |||
1152 | if (len == 2) { | ||
1153 | data0 = data[0]; | ||
1154 | data1 = data[1]; | ||
1155 | if ((data0 == 0x00 && data1 == 0x11) || | ||
1156 | (data0 == 0x22 && data1 == 0x33) || | ||
1157 | (data0 == 0x44 && data1 == 0x55) || | ||
1158 | (data0 == 0x66 && data1 == 0x77) || | ||
1159 | (data0 == 0x88 && data1 == 0x99) || | ||
1160 | (data0 == 0xaa && data1 == 0xbb) || | ||
1161 | (data0 == 0xcc && data1 == 0xdd) || | ||
1162 | (data0 == 0xee && data1 == 0xff)) { | ||
1163 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); | ||
1164 | input_sync(gspca_dev->input_dev); | ||
1165 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); | ||
1166 | input_sync(gspca_dev->input_dev); | ||
1167 | ret = 0; | ||
1168 | } | ||
1169 | } | ||
1170 | |||
1171 | return ret; | ||
1172 | } | ||
1173 | #endif | ||
1174 | |||
1213 | /* sub-driver description for pac7302 */ | 1175 | /* sub-driver description for pac7302 */ |
1214 | static struct sd_desc sd_desc = { | 1176 | static const struct sd_desc sd_desc = { |
1215 | .name = MODULE_NAME, | 1177 | .name = MODULE_NAME, |
1216 | .ctrls = sd_ctrls, | 1178 | .ctrls = sd_ctrls, |
1217 | .nctrls = ARRAY_SIZE(sd_ctrls), | 1179 | .nctrls = ARRAY_SIZE(sd_ctrls), |
@@ -1226,6 +1188,9 @@ static struct sd_desc sd_desc = { | |||
1226 | .set_register = sd_dbg_s_register, | 1188 | .set_register = sd_dbg_s_register, |
1227 | .get_chip_ident = sd_chip_ident, | 1189 | .get_chip_ident = sd_chip_ident, |
1228 | #endif | 1190 | #endif |
1191 | #ifdef CONFIG_INPUT | ||
1192 | .int_pkt_scan = sd_int_pkt_scan, | ||
1193 | #endif | ||
1229 | }; | 1194 | }; |
1230 | 1195 | ||
1231 | /* -- module initialisation -- */ | 1196 | /* -- module initialisation -- */ |
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 42cfcdfd8f4f..44fed9686729 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c | |||
@@ -51,6 +51,7 @@ | |||
51 | 51 | ||
52 | #define MODULE_NAME "pac7311" | 52 | #define MODULE_NAME "pac7311" |
53 | 53 | ||
54 | #include <linux/input.h> | ||
54 | #include "gspca.h" | 55 | #include "gspca.h" |
55 | 56 | ||
56 | MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); | 57 | MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); |
@@ -88,7 +89,7 @@ static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | |||
88 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | 89 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); |
89 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | 90 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); |
90 | 91 | ||
91 | static struct ctrl sd_ctrls[] = { | 92 | static const struct ctrl sd_ctrls[] = { |
92 | /* This control is for both the 7302 and the 7311 */ | 93 | /* This control is for both the 7302 and the 7311 */ |
93 | { | 94 | { |
94 | { | 95 | { |
@@ -200,7 +201,6 @@ static const struct v4l2_pix_format vga_mode[] = { | |||
200 | .priv = 0}, | 201 | .priv = 0}, |
201 | }; | 202 | }; |
202 | 203 | ||
203 | #define LOAD_PAGE3 255 | ||
204 | #define LOAD_PAGE4 254 | 204 | #define LOAD_PAGE4 254 |
205 | #define END_OF_SEQUENCE 0 | 205 | #define END_OF_SEQUENCE 0 |
206 | 206 | ||
@@ -259,12 +259,14 @@ static const __u8 page4_7311[] = { | |||
259 | 0x23, 0x28, 0x04, 0x11, 0x00, 0x00 | 259 | 0x23, 0x28, 0x04, 0x11, 0x00, 0x00 |
260 | }; | 260 | }; |
261 | 261 | ||
262 | static int reg_w_buf(struct gspca_dev *gspca_dev, | 262 | static void reg_w_buf(struct gspca_dev *gspca_dev, |
263 | __u8 index, | 263 | __u8 index, |
264 | const char *buffer, int len) | 264 | const char *buffer, int len) |
265 | { | 265 | { |
266 | int ret; | 266 | int ret; |
267 | 267 | ||
268 | if (gspca_dev->usb_err < 0) | ||
269 | return; | ||
268 | memcpy(gspca_dev->usb_buf, buffer, len); | 270 | memcpy(gspca_dev->usb_buf, buffer, len); |
269 | ret = usb_control_msg(gspca_dev->dev, | 271 | ret = usb_control_msg(gspca_dev->dev, |
270 | usb_sndctrlpipe(gspca_dev->dev, 0), | 272 | usb_sndctrlpipe(gspca_dev->dev, 0), |
@@ -273,20 +275,23 @@ static int reg_w_buf(struct gspca_dev *gspca_dev, | |||
273 | 0, /* value */ | 275 | 0, /* value */ |
274 | index, gspca_dev->usb_buf, len, | 276 | index, gspca_dev->usb_buf, len, |
275 | 500); | 277 | 500); |
276 | if (ret < 0) | 278 | if (ret < 0) { |
277 | PDEBUG(D_ERR, "reg_w_buf(): " | 279 | PDEBUG(D_ERR, "reg_w_buf(): " |
278 | "Failed to write registers to index 0x%x, error %i", | 280 | "Failed to write registers to index 0x%x, error %i", |
279 | index, ret); | 281 | index, ret); |
280 | return ret; | 282 | gspca_dev->usb_err = ret; |
283 | } | ||
281 | } | 284 | } |
282 | 285 | ||
283 | 286 | ||
284 | static int reg_w(struct gspca_dev *gspca_dev, | 287 | static void reg_w(struct gspca_dev *gspca_dev, |
285 | __u8 index, | 288 | __u8 index, |
286 | __u8 value) | 289 | __u8 value) |
287 | { | 290 | { |
288 | int ret; | 291 | int ret; |
289 | 292 | ||
293 | if (gspca_dev->usb_err < 0) | ||
294 | return; | ||
290 | gspca_dev->usb_buf[0] = value; | 295 | gspca_dev->usb_buf[0] = value; |
291 | ret = usb_control_msg(gspca_dev->dev, | 296 | ret = usb_control_msg(gspca_dev->dev, |
292 | usb_sndctrlpipe(gspca_dev->dev, 0), | 297 | usb_sndctrlpipe(gspca_dev->dev, 0), |
@@ -294,32 +299,32 @@ static int reg_w(struct gspca_dev *gspca_dev, | |||
294 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 299 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
295 | 0, index, gspca_dev->usb_buf, 1, | 300 | 0, index, gspca_dev->usb_buf, 1, |
296 | 500); | 301 | 500); |
297 | if (ret < 0) | 302 | if (ret < 0) { |
298 | PDEBUG(D_ERR, "reg_w(): " | 303 | PDEBUG(D_ERR, "reg_w(): " |
299 | "Failed to write register to index 0x%x, value 0x%x, error %i", | 304 | "Failed to write register to index 0x%x, value 0x%x, error %i", |
300 | index, value, ret); | 305 | index, value, ret); |
301 | return ret; | 306 | gspca_dev->usb_err = ret; |
307 | } | ||
302 | } | 308 | } |
303 | 309 | ||
304 | static int reg_w_seq(struct gspca_dev *gspca_dev, | 310 | static void reg_w_seq(struct gspca_dev *gspca_dev, |
305 | const __u8 *seq, int len) | 311 | const __u8 *seq, int len) |
306 | { | 312 | { |
307 | int ret = 0; | ||
308 | while (--len >= 0) { | 313 | while (--len >= 0) { |
309 | if (0 <= ret) | 314 | reg_w(gspca_dev, seq[0], seq[1]); |
310 | ret = reg_w(gspca_dev, seq[0], seq[1]); | ||
311 | seq += 2; | 315 | seq += 2; |
312 | } | 316 | } |
313 | return ret; | ||
314 | } | 317 | } |
315 | 318 | ||
316 | /* load the beginning of a page */ | 319 | /* load the beginning of a page */ |
317 | static int reg_w_page(struct gspca_dev *gspca_dev, | 320 | static void reg_w_page(struct gspca_dev *gspca_dev, |
318 | const __u8 *page, int len) | 321 | const __u8 *page, int len) |
319 | { | 322 | { |
320 | int index; | 323 | int index; |
321 | int ret = 0; | 324 | int ret = 0; |
322 | 325 | ||
326 | if (gspca_dev->usb_err < 0) | ||
327 | return; | ||
323 | for (index = 0; index < len; index++) { | 328 | for (index = 0; index < len; index++) { |
324 | if (page[index] == SKIP) /* skip this index */ | 329 | if (page[index] == SKIP) /* skip this index */ |
325 | continue; | 330 | continue; |
@@ -335,56 +340,47 @@ static int reg_w_page(struct gspca_dev *gspca_dev, | |||
335 | "Failed to write register to index 0x%x, " | 340 | "Failed to write register to index 0x%x, " |
336 | "value 0x%x, error %i", | 341 | "value 0x%x, error %i", |
337 | index, page[index], ret); | 342 | index, page[index], ret); |
343 | gspca_dev->usb_err = ret; | ||
338 | break; | 344 | break; |
339 | } | 345 | } |
340 | } | 346 | } |
341 | return ret; | ||
342 | } | 347 | } |
343 | 348 | ||
344 | /* output a variable sequence */ | 349 | /* output a variable sequence */ |
345 | static int reg_w_var(struct gspca_dev *gspca_dev, | 350 | static void reg_w_var(struct gspca_dev *gspca_dev, |
346 | const __u8 *seq, | 351 | const __u8 *seq, |
347 | const __u8 *page3, unsigned int page3_len, | ||
348 | const __u8 *page4, unsigned int page4_len) | 352 | const __u8 *page4, unsigned int page4_len) |
349 | { | 353 | { |
350 | int index, len; | 354 | int index, len; |
351 | int ret = 0; | ||
352 | 355 | ||
353 | for (;;) { | 356 | for (;;) { |
354 | index = *seq++; | 357 | index = *seq++; |
355 | len = *seq++; | 358 | len = *seq++; |
356 | switch (len) { | 359 | switch (len) { |
357 | case END_OF_SEQUENCE: | 360 | case END_OF_SEQUENCE: |
358 | return ret; | 361 | return; |
359 | case LOAD_PAGE4: | 362 | case LOAD_PAGE4: |
360 | ret = reg_w_page(gspca_dev, page4, page4_len); | 363 | reg_w_page(gspca_dev, page4, page4_len); |
361 | break; | ||
362 | case LOAD_PAGE3: | ||
363 | ret = reg_w_page(gspca_dev, page3, page3_len); | ||
364 | break; | 364 | break; |
365 | default: | 365 | default: |
366 | if (len > USB_BUF_SZ) { | 366 | if (len > USB_BUF_SZ) { |
367 | PDEBUG(D_ERR|D_STREAM, | 367 | PDEBUG(D_ERR|D_STREAM, |
368 | "Incorrect variable sequence"); | 368 | "Incorrect variable sequence"); |
369 | return -EINVAL; | 369 | return; |
370 | } | 370 | } |
371 | while (len > 0) { | 371 | while (len > 0) { |
372 | if (len < 8) { | 372 | if (len < 8) { |
373 | ret = reg_w_buf(gspca_dev, | 373 | reg_w_buf(gspca_dev, |
374 | index, seq, len); | 374 | index, seq, len); |
375 | if (ret < 0) | ||
376 | return ret; | ||
377 | seq += len; | 375 | seq += len; |
378 | break; | 376 | break; |
379 | } | 377 | } |
380 | ret = reg_w_buf(gspca_dev, index, seq, 8); | 378 | reg_w_buf(gspca_dev, index, seq, 8); |
381 | seq += 8; | 379 | seq += 8; |
382 | index += 8; | 380 | index += 8; |
383 | len -= 8; | 381 | len -= 8; |
384 | } | 382 | } |
385 | } | 383 | } |
386 | if (ret < 0) | ||
387 | return ret; | ||
388 | } | 384 | } |
389 | /* not reached */ | 385 | /* not reached */ |
390 | } | 386 | } |
@@ -412,46 +408,36 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
412 | } | 408 | } |
413 | 409 | ||
414 | /* This function is used by pac7311 only */ | 410 | /* This function is used by pac7311 only */ |
415 | static int setcontrast(struct gspca_dev *gspca_dev) | 411 | static void setcontrast(struct gspca_dev *gspca_dev) |
416 | { | 412 | { |
417 | struct sd *sd = (struct sd *) gspca_dev; | 413 | struct sd *sd = (struct sd *) gspca_dev; |
418 | int ret; | ||
419 | 414 | ||
420 | ret = reg_w(gspca_dev, 0xff, 0x04); | 415 | reg_w(gspca_dev, 0xff, 0x04); |
421 | if (0 <= ret) | 416 | reg_w(gspca_dev, 0x10, sd->contrast >> 4); |
422 | ret = reg_w(gspca_dev, 0x10, sd->contrast >> 4); | ||
423 | /* load registers to sensor (Bit 0, auto clear) */ | 417 | /* load registers to sensor (Bit 0, auto clear) */ |
424 | if (0 <= ret) | 418 | reg_w(gspca_dev, 0x11, 0x01); |
425 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
426 | return ret; | ||
427 | } | 419 | } |
428 | 420 | ||
429 | static int setgain(struct gspca_dev *gspca_dev) | 421 | static void setgain(struct gspca_dev *gspca_dev) |
430 | { | 422 | { |
431 | struct sd *sd = (struct sd *) gspca_dev; | 423 | struct sd *sd = (struct sd *) gspca_dev; |
432 | int gain = GAIN_MAX - sd->gain; | 424 | int gain = GAIN_MAX - sd->gain; |
433 | int ret; | ||
434 | 425 | ||
435 | if (gain < 1) | 426 | if (gain < 1) |
436 | gain = 1; | 427 | gain = 1; |
437 | else if (gain > 245) | 428 | else if (gain > 245) |
438 | gain = 245; | 429 | gain = 245; |
439 | ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ | 430 | reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ |
440 | if (0 <= ret) | 431 | reg_w(gspca_dev, 0x0e, 0x00); |
441 | ret = reg_w(gspca_dev, 0x0e, 0x00); | 432 | reg_w(gspca_dev, 0x0f, gain); |
442 | if (0 <= ret) | ||
443 | ret = reg_w(gspca_dev, 0x0f, gain); | ||
444 | 433 | ||
445 | /* load registers to sensor (Bit 0, auto clear) */ | 434 | /* load registers to sensor (Bit 0, auto clear) */ |
446 | if (0 <= ret) | 435 | reg_w(gspca_dev, 0x11, 0x01); |
447 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
448 | return ret; | ||
449 | } | 436 | } |
450 | 437 | ||
451 | static int setexposure(struct gspca_dev *gspca_dev) | 438 | static void setexposure(struct gspca_dev *gspca_dev) |
452 | { | 439 | { |
453 | struct sd *sd = (struct sd *) gspca_dev; | 440 | struct sd *sd = (struct sd *) gspca_dev; |
454 | int ret; | ||
455 | __u8 reg; | 441 | __u8 reg; |
456 | 442 | ||
457 | /* register 2 of frame 3/4 contains the clock divider configuring the | 443 | /* register 2 of frame 3/4 contains the clock divider configuring the |
@@ -463,94 +449,72 @@ static int setexposure(struct gspca_dev *gspca_dev) | |||
463 | else if (reg > 63) | 449 | else if (reg > 63) |
464 | reg = 63; | 450 | reg = 63; |
465 | 451 | ||
466 | ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ | 452 | reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ |
467 | if (0 <= ret) | 453 | reg_w(gspca_dev, 0x02, reg); |
468 | ret = reg_w(gspca_dev, 0x02, reg); | 454 | |
469 | /* Page 1 register 8 must always be 0x08 except when not in | 455 | /* Page 1 register 8 must always be 0x08 except when not in |
470 | 640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */ | 456 | 640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */ |
471 | if (0 <= ret) | 457 | reg_w(gspca_dev, 0xff, 0x01); |
472 | ret = reg_w(gspca_dev, 0xff, 0x01); | ||
473 | if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv && | 458 | if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv && |
474 | reg <= 3) { | 459 | reg <= 3) { |
475 | if (0 <= ret) | 460 | reg_w(gspca_dev, 0x08, 0x09); |
476 | ret = reg_w(gspca_dev, 0x08, 0x09); | ||
477 | } else { | 461 | } else { |
478 | if (0 <= ret) | 462 | reg_w(gspca_dev, 0x08, 0x08); |
479 | ret = reg_w(gspca_dev, 0x08, 0x08); | ||
480 | } | 463 | } |
481 | 464 | ||
482 | /* load registers to sensor (Bit 0, auto clear) */ | 465 | /* load registers to sensor (Bit 0, auto clear) */ |
483 | if (0 <= ret) | 466 | reg_w(gspca_dev, 0x11, 0x01); |
484 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
485 | return ret; | ||
486 | } | 467 | } |
487 | 468 | ||
488 | static int sethvflip(struct gspca_dev *gspca_dev) | 469 | static void sethvflip(struct gspca_dev *gspca_dev) |
489 | { | 470 | { |
490 | struct sd *sd = (struct sd *) gspca_dev; | 471 | struct sd *sd = (struct sd *) gspca_dev; |
491 | int ret; | ||
492 | __u8 data; | 472 | __u8 data; |
493 | 473 | ||
494 | ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ | 474 | reg_w(gspca_dev, 0xff, 0x04); /* page 4 */ |
495 | data = (sd->hflip ? 0x04 : 0x00) | (sd->vflip ? 0x08 : 0x00); | 475 | data = (sd->hflip ? 0x04 : 0x00) | (sd->vflip ? 0x08 : 0x00); |
496 | if (0 <= ret) | 476 | reg_w(gspca_dev, 0x21, data); |
497 | ret = reg_w(gspca_dev, 0x21, data); | 477 | |
498 | /* load registers to sensor (Bit 0, auto clear) */ | 478 | /* load registers to sensor (Bit 0, auto clear) */ |
499 | if (0 <= ret) | 479 | reg_w(gspca_dev, 0x11, 0x01); |
500 | ret = reg_w(gspca_dev, 0x11, 0x01); | ||
501 | return ret; | ||
502 | } | 480 | } |
503 | 481 | ||
504 | /* this function is called at probe and resume time for pac7311 */ | 482 | /* this function is called at probe and resume time for pac7311 */ |
505 | static int sd_init(struct gspca_dev *gspca_dev) | 483 | static int sd_init(struct gspca_dev *gspca_dev) |
506 | { | 484 | { |
507 | return reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2); | 485 | reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2); |
486 | return gspca_dev->usb_err; | ||
508 | } | 487 | } |
509 | 488 | ||
510 | static int sd_start(struct gspca_dev *gspca_dev) | 489 | static int sd_start(struct gspca_dev *gspca_dev) |
511 | { | 490 | { |
512 | struct sd *sd = (struct sd *) gspca_dev; | 491 | struct sd *sd = (struct sd *) gspca_dev; |
513 | int ret; | ||
514 | 492 | ||
515 | sd->sof_read = 0; | 493 | sd->sof_read = 0; |
516 | 494 | ||
517 | ret = reg_w_var(gspca_dev, start_7311, | 495 | reg_w_var(gspca_dev, start_7311, |
518 | NULL, 0, | ||
519 | page4_7311, sizeof(page4_7311)); | 496 | page4_7311, sizeof(page4_7311)); |
520 | if (0 <= ret) | 497 | setcontrast(gspca_dev); |
521 | ret = setcontrast(gspca_dev); | 498 | setgain(gspca_dev); |
522 | if (0 <= ret) | 499 | setexposure(gspca_dev); |
523 | ret = setgain(gspca_dev); | 500 | sethvflip(gspca_dev); |
524 | if (0 <= ret) | ||
525 | ret = setexposure(gspca_dev); | ||
526 | if (0 <= ret) | ||
527 | ret = sethvflip(gspca_dev); | ||
528 | 501 | ||
529 | /* set correct resolution */ | 502 | /* set correct resolution */ |
530 | switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { | 503 | switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { |
531 | case 2: /* 160x120 pac7311 */ | 504 | case 2: /* 160x120 pac7311 */ |
532 | if (0 <= ret) | 505 | reg_w(gspca_dev, 0xff, 0x01); |
533 | ret = reg_w(gspca_dev, 0xff, 0x01); | 506 | reg_w(gspca_dev, 0x17, 0x20); |
534 | if (0 <= ret) | 507 | reg_w(gspca_dev, 0x87, 0x10); |
535 | ret = reg_w(gspca_dev, 0x17, 0x20); | ||
536 | if (0 <= ret) | ||
537 | ret = reg_w(gspca_dev, 0x87, 0x10); | ||
538 | break; | 508 | break; |
539 | case 1: /* 320x240 pac7311 */ | 509 | case 1: /* 320x240 pac7311 */ |
540 | if (0 <= ret) | 510 | reg_w(gspca_dev, 0xff, 0x01); |
541 | ret = reg_w(gspca_dev, 0xff, 0x01); | 511 | reg_w(gspca_dev, 0x17, 0x30); |
542 | if (0 <= ret) | 512 | reg_w(gspca_dev, 0x87, 0x11); |
543 | ret = reg_w(gspca_dev, 0x17, 0x30); | ||
544 | if (0 <= ret) | ||
545 | ret = reg_w(gspca_dev, 0x87, 0x11); | ||
546 | break; | 513 | break; |
547 | case 0: /* 640x480 */ | 514 | case 0: /* 640x480 */ |
548 | if (0 <= ret) | 515 | reg_w(gspca_dev, 0xff, 0x01); |
549 | ret = reg_w(gspca_dev, 0xff, 0x01); | 516 | reg_w(gspca_dev, 0x17, 0x00); |
550 | if (0 <= ret) | 517 | reg_w(gspca_dev, 0x87, 0x12); |
551 | ret = reg_w(gspca_dev, 0x17, 0x00); | ||
552 | if (0 <= ret) | ||
553 | ret = reg_w(gspca_dev, 0x87, 0x12); | ||
554 | break; | 518 | break; |
555 | } | 519 | } |
556 | 520 | ||
@@ -559,37 +523,24 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
559 | atomic_set(&sd->avg_lum, -1); | 523 | atomic_set(&sd->avg_lum, -1); |
560 | 524 | ||
561 | /* start stream */ | 525 | /* start stream */ |
562 | if (0 <= ret) | 526 | reg_w(gspca_dev, 0xff, 0x01); |
563 | ret = reg_w(gspca_dev, 0xff, 0x01); | 527 | reg_w(gspca_dev, 0x78, 0x05); |
564 | if (0 <= ret) | ||
565 | ret = reg_w(gspca_dev, 0x78, 0x05); | ||
566 | 528 | ||
567 | return ret; | 529 | return gspca_dev->usb_err; |
568 | } | 530 | } |
569 | 531 | ||
570 | static void sd_stopN(struct gspca_dev *gspca_dev) | 532 | static void sd_stopN(struct gspca_dev *gspca_dev) |
571 | { | 533 | { |
572 | int ret; | 534 | reg_w(gspca_dev, 0xff, 0x04); |
573 | 535 | reg_w(gspca_dev, 0x27, 0x80); | |
574 | ret = reg_w(gspca_dev, 0xff, 0x04); | 536 | reg_w(gspca_dev, 0x28, 0xca); |
575 | if (0 <= ret) | 537 | reg_w(gspca_dev, 0x29, 0x53); |
576 | ret = reg_w(gspca_dev, 0x27, 0x80); | 538 | reg_w(gspca_dev, 0x2a, 0x0e); |
577 | if (0 <= ret) | 539 | reg_w(gspca_dev, 0xff, 0x01); |
578 | ret = reg_w(gspca_dev, 0x28, 0xca); | 540 | reg_w(gspca_dev, 0x3e, 0x20); |
579 | if (0 <= ret) | 541 | reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ |
580 | ret = reg_w(gspca_dev, 0x29, 0x53); | 542 | reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ |
581 | if (0 <= ret) | 543 | reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ |
582 | ret = reg_w(gspca_dev, 0x2a, 0x0e); | ||
583 | if (0 <= ret) | ||
584 | ret = reg_w(gspca_dev, 0xff, 0x01); | ||
585 | if (0 <= ret) | ||
586 | ret = reg_w(gspca_dev, 0x3e, 0x20); | ||
587 | if (0 <= ret) | ||
588 | ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ | ||
589 | if (0 <= ret) | ||
590 | ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ | ||
591 | if (0 <= ret) | ||
592 | ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ | ||
593 | } | 544 | } |
594 | 545 | ||
595 | /* called on streamoff with alt 0 and on disconnect for 7311 */ | 546 | /* called on streamoff with alt 0 and on disconnect for 7311 */ |
@@ -734,7 +685,7 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | |||
734 | if (gspca_dev->streaming) { | 685 | if (gspca_dev->streaming) { |
735 | setcontrast(gspca_dev); | 686 | setcontrast(gspca_dev); |
736 | } | 687 | } |
737 | return 0; | 688 | return gspca_dev->usb_err; |
738 | } | 689 | } |
739 | 690 | ||
740 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | 691 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -752,7 +703,7 @@ static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) | |||
752 | sd->gain = val; | 703 | sd->gain = val; |
753 | if (gspca_dev->streaming) | 704 | if (gspca_dev->streaming) |
754 | setgain(gspca_dev); | 705 | setgain(gspca_dev); |
755 | return 0; | 706 | return gspca_dev->usb_err; |
756 | } | 707 | } |
757 | 708 | ||
758 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) | 709 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -770,7 +721,7 @@ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) | |||
770 | sd->exposure = val; | 721 | sd->exposure = val; |
771 | if (gspca_dev->streaming) | 722 | if (gspca_dev->streaming) |
772 | setexposure(gspca_dev); | 723 | setexposure(gspca_dev); |
773 | return 0; | 724 | return gspca_dev->usb_err; |
774 | } | 725 | } |
775 | 726 | ||
776 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) | 727 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -801,7 +752,7 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | |||
801 | } | 752 | } |
802 | } | 753 | } |
803 | 754 | ||
804 | return 0; | 755 | return gspca_dev->usb_err; |
805 | } | 756 | } |
806 | 757 | ||
807 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) | 758 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -819,7 +770,7 @@ static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) | |||
819 | sd->hflip = val; | 770 | sd->hflip = val; |
820 | if (gspca_dev->streaming) | 771 | if (gspca_dev->streaming) |
821 | sethvflip(gspca_dev); | 772 | sethvflip(gspca_dev); |
822 | return 0; | 773 | return gspca_dev->usb_err; |
823 | } | 774 | } |
824 | 775 | ||
825 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) | 776 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -837,7 +788,7 @@ static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) | |||
837 | sd->vflip = val; | 788 | sd->vflip = val; |
838 | if (gspca_dev->streaming) | 789 | if (gspca_dev->streaming) |
839 | sethvflip(gspca_dev); | 790 | sethvflip(gspca_dev); |
840 | return 0; | 791 | return gspca_dev->usb_err; |
841 | } | 792 | } |
842 | 793 | ||
843 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) | 794 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) |
@@ -848,8 +799,39 @@ static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) | |||
848 | return 0; | 799 | return 0; |
849 | } | 800 | } |
850 | 801 | ||
802 | #ifdef CONFIG_INPUT | ||
803 | static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, | ||
804 | u8 *data, /* interrupt packet data */ | ||
805 | int len) /* interrupt packet length */ | ||
806 | { | ||
807 | int ret = -EINVAL; | ||
808 | u8 data0, data1; | ||
809 | |||
810 | if (len == 2) { | ||
811 | data0 = data[0]; | ||
812 | data1 = data[1]; | ||
813 | if ((data0 == 0x00 && data1 == 0x11) || | ||
814 | (data0 == 0x22 && data1 == 0x33) || | ||
815 | (data0 == 0x44 && data1 == 0x55) || | ||
816 | (data0 == 0x66 && data1 == 0x77) || | ||
817 | (data0 == 0x88 && data1 == 0x99) || | ||
818 | (data0 == 0xaa && data1 == 0xbb) || | ||
819 | (data0 == 0xcc && data1 == 0xdd) || | ||
820 | (data0 == 0xee && data1 == 0xff)) { | ||
821 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); | ||
822 | input_sync(gspca_dev->input_dev); | ||
823 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); | ||
824 | input_sync(gspca_dev->input_dev); | ||
825 | ret = 0; | ||
826 | } | ||
827 | } | ||
828 | |||
829 | return ret; | ||
830 | } | ||
831 | #endif | ||
832 | |||
851 | /* sub-driver description for pac7311 */ | 833 | /* sub-driver description for pac7311 */ |
852 | static struct sd_desc sd_desc = { | 834 | static const struct sd_desc sd_desc = { |
853 | .name = MODULE_NAME, | 835 | .name = MODULE_NAME, |
854 | .ctrls = sd_ctrls, | 836 | .ctrls = sd_ctrls, |
855 | .nctrls = ARRAY_SIZE(sd_ctrls), | 837 | .nctrls = ARRAY_SIZE(sd_ctrls), |
@@ -860,6 +842,9 @@ static struct sd_desc sd_desc = { | |||
860 | .stop0 = sd_stop0, | 842 | .stop0 = sd_stop0, |
861 | .pkt_scan = sd_pkt_scan, | 843 | .pkt_scan = sd_pkt_scan, |
862 | .dq_callback = do_autogain, | 844 | .dq_callback = do_autogain, |
845 | #ifdef CONFIG_INPUT | ||
846 | .int_pkt_scan = sd_int_pkt_scan, | ||
847 | #endif | ||
863 | }; | 848 | }; |
864 | 849 | ||
865 | /* -- module initialisation -- */ | 850 | /* -- module initialisation -- */ |
diff --git a/drivers/media/video/gspca/pac_common.h b/drivers/media/video/gspca/pac_common.h index 20f67d9b8c06..8462a7c1a338 100644 --- a/drivers/media/video/gspca/pac_common.h +++ b/drivers/media/video/gspca/pac_common.h | |||
@@ -24,11 +24,10 @@ | |||
24 | */ | 24 | */ |
25 | 25 | ||
26 | /* We calculate the autogain at the end of the transfer of a frame, at this | 26 | /* We calculate the autogain at the end of the transfer of a frame, at this |
27 | moment a frame with the old settings is being transmitted, and a frame is | 27 | moment a frame with the old settings is being captured and transmitted. So |
28 | being captured with the old settings. So if we adjust the autogain we must | 28 | if we adjust the gain or exposure we must ignore atleast the next frame for |
29 | ignore atleast the 2 next frames for the new settings to come into effect | 29 | the new settings to come into effect before doing any other adjustments. */ |
30 | before doing any other adjustments */ | 30 | #define PAC_AUTOGAIN_IGNORE_FRAMES 2 |
31 | #define PAC_AUTOGAIN_IGNORE_FRAMES 3 | ||
32 | 31 | ||
33 | static const unsigned char pac_sof_marker[5] = | 32 | static const unsigned char pac_sof_marker[5] = |
34 | { 0xff, 0xff, 0x00, 0xff, 0x96 }; | 33 | { 0xff, 0xff, 0x00, 0xff, 0x96 }; |
diff --git a/drivers/media/video/gspca/sn9c2028.c b/drivers/media/video/gspca/sn9c2028.c new file mode 100644 index 000000000000..dda5fd4aa69e --- /dev/null +++ b/drivers/media/video/gspca/sn9c2028.c | |||
@@ -0,0 +1,757 @@ | |||
1 | /* | ||
2 | * SN9C2028 library | ||
3 | * | ||
4 | * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu> | ||
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 as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #define MODULE_NAME "sn9c2028" | ||
22 | |||
23 | #include "gspca.h" | ||
24 | |||
25 | MODULE_AUTHOR("Theodore Kilgore"); | ||
26 | MODULE_DESCRIPTION("Sonix SN9C2028 USB Camera Driver"); | ||
27 | MODULE_LICENSE("GPL"); | ||
28 | |||
29 | /* specific webcam descriptor */ | ||
30 | struct sd { | ||
31 | struct gspca_dev gspca_dev; /* !! must be the first item */ | ||
32 | u8 sof_read; | ||
33 | u16 model; | ||
34 | }; | ||
35 | |||
36 | struct init_command { | ||
37 | unsigned char instruction[6]; | ||
38 | unsigned char to_read; /* length to read. 0 means no reply requested */ | ||
39 | }; | ||
40 | |||
41 | /* V4L2 controls supported by the driver */ | ||
42 | static struct ctrl sd_ctrls[] = { | ||
43 | }; | ||
44 | |||
45 | /* How to change the resolution of any of the VGA cams is unknown */ | ||
46 | static const struct v4l2_pix_format vga_mode[] = { | ||
47 | {640, 480, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE, | ||
48 | .bytesperline = 640, | ||
49 | .sizeimage = 640 * 480 * 3 / 4, | ||
50 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
51 | .priv = 0}, | ||
52 | }; | ||
53 | |||
54 | /* No way to change the resolution of the CIF cams is known */ | ||
55 | static const struct v4l2_pix_format cif_mode[] = { | ||
56 | {352, 288, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE, | ||
57 | .bytesperline = 352, | ||
58 | .sizeimage = 352 * 288 * 3 / 4, | ||
59 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
60 | .priv = 0}, | ||
61 | }; | ||
62 | |||
63 | /* the bytes to write are in gspca_dev->usb_buf */ | ||
64 | static int sn9c2028_command(struct gspca_dev *gspca_dev, u8 *command) | ||
65 | { | ||
66 | int rc; | ||
67 | |||
68 | PDEBUG(D_USBO, "sending command %02x%02x%02x%02x%02x%02x", command[0], | ||
69 | command[1], command[2], command[3], command[4], command[5]); | ||
70 | |||
71 | memcpy(gspca_dev->usb_buf, command, 6); | ||
72 | rc = usb_control_msg(gspca_dev->dev, | ||
73 | usb_sndctrlpipe(gspca_dev->dev, 0), | ||
74 | USB_REQ_GET_CONFIGURATION, | ||
75 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, | ||
76 | 2, 0, gspca_dev->usb_buf, 6, 500); | ||
77 | if (rc < 0) { | ||
78 | PDEBUG(D_ERR, "command write [%02x] error %d", | ||
79 | gspca_dev->usb_buf[0], rc); | ||
80 | return rc; | ||
81 | } | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static int sn9c2028_read1(struct gspca_dev *gspca_dev) | ||
87 | { | ||
88 | int rc; | ||
89 | |||
90 | rc = usb_control_msg(gspca_dev->dev, | ||
91 | usb_rcvctrlpipe(gspca_dev->dev, 0), | ||
92 | USB_REQ_GET_STATUS, | ||
93 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, | ||
94 | 1, 0, gspca_dev->usb_buf, 1, 500); | ||
95 | if (rc != 1) { | ||
96 | PDEBUG(D_ERR, "read1 error %d", rc); | ||
97 | return (rc < 0) ? rc : -EIO; | ||
98 | } | ||
99 | PDEBUG(D_USBI, "read1 response %02x", gspca_dev->usb_buf[0]); | ||
100 | return gspca_dev->usb_buf[0]; | ||
101 | } | ||
102 | |||
103 | static int sn9c2028_read4(struct gspca_dev *gspca_dev, u8 *reading) | ||
104 | { | ||
105 | int rc; | ||
106 | rc = usb_control_msg(gspca_dev->dev, | ||
107 | usb_rcvctrlpipe(gspca_dev->dev, 0), | ||
108 | USB_REQ_GET_STATUS, | ||
109 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, | ||
110 | 4, 0, gspca_dev->usb_buf, 4, 500); | ||
111 | if (rc != 4) { | ||
112 | PDEBUG(D_ERR, "read4 error %d", rc); | ||
113 | return (rc < 0) ? rc : -EIO; | ||
114 | } | ||
115 | memcpy(reading, gspca_dev->usb_buf, 4); | ||
116 | PDEBUG(D_USBI, "read4 response %02x%02x%02x%02x", reading[0], | ||
117 | reading[1], reading[2], reading[3]); | ||
118 | return rc; | ||
119 | } | ||
120 | |||
121 | static int sn9c2028_long_command(struct gspca_dev *gspca_dev, u8 *command) | ||
122 | { | ||
123 | int i, status; | ||
124 | __u8 reading[4]; | ||
125 | |||
126 | status = sn9c2028_command(gspca_dev, command); | ||
127 | if (status < 0) | ||
128 | return status; | ||
129 | |||
130 | status = -1; | ||
131 | for (i = 0; i < 256 && status < 2; i++) | ||
132 | status = sn9c2028_read1(gspca_dev); | ||
133 | if (status != 2) { | ||
134 | PDEBUG(D_ERR, "long command status read error %d", status); | ||
135 | return (status < 0) ? status : -EIO; | ||
136 | } | ||
137 | |||
138 | memset(reading, 0, 4); | ||
139 | status = sn9c2028_read4(gspca_dev, reading); | ||
140 | if (status < 0) | ||
141 | return status; | ||
142 | |||
143 | /* in general, the first byte of the response is the first byte of | ||
144 | * the command, or'ed with 8 */ | ||
145 | status = sn9c2028_read1(gspca_dev); | ||
146 | if (status < 0) | ||
147 | return status; | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static int sn9c2028_short_command(struct gspca_dev *gspca_dev, u8 *command) | ||
153 | { | ||
154 | int err_code; | ||
155 | |||
156 | err_code = sn9c2028_command(gspca_dev, command); | ||
157 | if (err_code < 0) | ||
158 | return err_code; | ||
159 | |||
160 | err_code = sn9c2028_read1(gspca_dev); | ||
161 | if (err_code < 0) | ||
162 | return err_code; | ||
163 | |||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | /* this function is called at probe time */ | ||
168 | static int sd_config(struct gspca_dev *gspca_dev, | ||
169 | const struct usb_device_id *id) | ||
170 | { | ||
171 | struct sd *sd = (struct sd *) gspca_dev; | ||
172 | struct cam *cam = &gspca_dev->cam; | ||
173 | |||
174 | PDEBUG(D_PROBE, "SN9C2028 camera detected (vid/pid 0x%04X:0x%04X)", | ||
175 | id->idVendor, id->idProduct); | ||
176 | |||
177 | sd->model = id->idProduct; | ||
178 | |||
179 | switch (sd->model) { | ||
180 | case 0x7005: | ||
181 | PDEBUG(D_PROBE, "Genius Smart 300 camera"); | ||
182 | break; | ||
183 | case 0x8000: | ||
184 | PDEBUG(D_PROBE, "DC31VC"); | ||
185 | break; | ||
186 | case 0x8001: | ||
187 | PDEBUG(D_PROBE, "Spy camera"); | ||
188 | break; | ||
189 | case 0x8003: | ||
190 | PDEBUG(D_PROBE, "CIF camera"); | ||
191 | break; | ||
192 | case 0x8008: | ||
193 | PDEBUG(D_PROBE, "Mini-Shotz ms-350 camera"); | ||
194 | break; | ||
195 | case 0x800a: | ||
196 | PDEBUG(D_PROBE, "Vivitar 3350b type camera"); | ||
197 | cam->input_flags = V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP; | ||
198 | break; | ||
199 | } | ||
200 | |||
201 | switch (sd->model) { | ||
202 | case 0x8000: | ||
203 | case 0x8001: | ||
204 | case 0x8003: | ||
205 | cam->cam_mode = cif_mode; | ||
206 | cam->nmodes = ARRAY_SIZE(cif_mode); | ||
207 | break; | ||
208 | default: | ||
209 | cam->cam_mode = vga_mode; | ||
210 | cam->nmodes = ARRAY_SIZE(vga_mode); | ||
211 | } | ||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | /* this function is called at probe and resume time */ | ||
216 | static int sd_init(struct gspca_dev *gspca_dev) | ||
217 | { | ||
218 | int status = -1; | ||
219 | |||
220 | sn9c2028_read1(gspca_dev); | ||
221 | sn9c2028_read1(gspca_dev); | ||
222 | status = sn9c2028_read1(gspca_dev); | ||
223 | |||
224 | return (status < 0) ? status : 0; | ||
225 | } | ||
226 | |||
227 | static int run_start_commands(struct gspca_dev *gspca_dev, | ||
228 | struct init_command *cam_commands, int n) | ||
229 | { | ||
230 | int i, err_code = -1; | ||
231 | |||
232 | for (i = 0; i < n; i++) { | ||
233 | switch (cam_commands[i].to_read) { | ||
234 | case 4: | ||
235 | err_code = sn9c2028_long_command(gspca_dev, | ||
236 | cam_commands[i].instruction); | ||
237 | break; | ||
238 | case 1: | ||
239 | err_code = sn9c2028_short_command(gspca_dev, | ||
240 | cam_commands[i].instruction); | ||
241 | break; | ||
242 | case 0: | ||
243 | err_code = sn9c2028_command(gspca_dev, | ||
244 | cam_commands[i].instruction); | ||
245 | break; | ||
246 | } | ||
247 | if (err_code < 0) | ||
248 | return err_code; | ||
249 | } | ||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | static int start_spy_cam(struct gspca_dev *gspca_dev) | ||
254 | { | ||
255 | struct init_command spy_start_commands[] = { | ||
256 | {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
257 | {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
258 | {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
259 | {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4}, | ||
260 | {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4}, | ||
261 | {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
262 | {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, /* width 352 */ | ||
263 | {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, /* height 288 */ | ||
264 | /* {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, */ | ||
265 | {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, | ||
266 | {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* red gain ?*/ | ||
267 | /* {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, */ | ||
268 | {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
269 | /* {{0x13, 0x29, 0x01, 0x0c, 0x00, 0x00}, 4}, */ | ||
270 | {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
271 | {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
272 | /* {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, */ | ||
273 | {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, | ||
274 | {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4}, | ||
275 | /* {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, */ | ||
276 | {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, | ||
277 | {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4}, | ||
278 | {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
279 | {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, | ||
280 | {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
281 | {{0x11, 0x02, 0x06, 0x00, 0x00, 0x00}, 4}, | ||
282 | {{0x11, 0x03, 0x13, 0x00, 0x00, 0x00}, 4}, /*don't mess with*/ | ||
283 | /*{{0x11, 0x04, 0x06, 0x00, 0x00, 0x00}, 4}, observed */ | ||
284 | {{0x11, 0x04, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */ | ||
285 | /*{{0x11, 0x05, 0x65, 0x00, 0x00, 0x00}, 4}, observed */ | ||
286 | {{0x11, 0x05, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */ | ||
287 | {{0x11, 0x06, 0xb1, 0x00, 0x00, 0x00}, 4}, /* observed */ | ||
288 | {{0x11, 0x07, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
289 | /*{{0x11, 0x08, 0x06, 0x00, 0x00, 0x00}, 4}, observed */ | ||
290 | {{0x11, 0x08, 0x0b, 0x00, 0x00, 0x00}, 4}, | ||
291 | {{0x11, 0x09, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
292 | {{0x11, 0x0a, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
293 | {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
294 | {{0x11, 0x0c, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
295 | {{0x11, 0x0d, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
296 | {{0x11, 0x0e, 0x04, 0x00, 0x00, 0x00}, 4}, | ||
297 | /* {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4}, */ | ||
298 | /* brightness or gain. 0 is default. 4 is good | ||
299 | * indoors at night with incandescent lighting */ | ||
300 | {{0x11, 0x0f, 0x04, 0x00, 0x00, 0x00}, 4}, | ||
301 | {{0x11, 0x10, 0x06, 0x00, 0x00, 0x00}, 4}, /*hstart or hoffs*/ | ||
302 | {{0x11, 0x11, 0x06, 0x00, 0x00, 0x00}, 4}, | ||
303 | {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
304 | {{0x11, 0x14, 0x02, 0x00, 0x00, 0x00}, 4}, | ||
305 | {{0x11, 0x13, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
306 | /* {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, observed */ | ||
307 | {{0x1b, 0x02, 0x11, 0x00, 0x00, 0x00}, 1}, /* brighter */ | ||
308 | /* {{0x1b, 0x13, 0x01, 0x00, 0x00, 0x00}, 1}, observed */ | ||
309 | {{0x1b, 0x13, 0x11, 0x00, 0x00, 0x00}, 1}, | ||
310 | {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}, /* compresses */ | ||
311 | /* Camera should start to capture now. */ | ||
312 | }; | ||
313 | |||
314 | return run_start_commands(gspca_dev, spy_start_commands, | ||
315 | ARRAY_SIZE(spy_start_commands)); | ||
316 | } | ||
317 | |||
318 | static int start_cif_cam(struct gspca_dev *gspca_dev) | ||
319 | { | ||
320 | struct init_command cif_start_commands[] = { | ||
321 | {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
322 | /* The entire sequence below seems redundant */ | ||
323 | /* {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
324 | {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
325 | {{0x13, 0x22, 0x01, 0x06, 0x00, 0x00}, 4}, | ||
326 | {{0x13, 0x23, 0x01, 0x02, 0x00, 0x00}, 4}, | ||
327 | {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
328 | {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, width? | ||
329 | {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, height? | ||
330 | {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample? | ||
331 | {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
332 | {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4}, | ||
333 | {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
334 | {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
335 | {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, | ||
336 | {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, | ||
337 | {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, | ||
338 | {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, | ||
339 | {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
340 | {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, | ||
341 | {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},*/ | ||
342 | {{0x1b, 0x21, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
343 | {{0x1b, 0x17, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
344 | {{0x1b, 0x19, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
345 | {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, | ||
346 | {{0x1b, 0x03, 0x5a, 0x00, 0x00, 0x00}, 1}, | ||
347 | {{0x1b, 0x04, 0x27, 0x00, 0x00, 0x00}, 1}, | ||
348 | {{0x1b, 0x05, 0x01, 0x00, 0x00, 0x00}, 1}, | ||
349 | {{0x1b, 0x12, 0x14, 0x00, 0x00, 0x00}, 1}, | ||
350 | {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
351 | {{0x1b, 0x14, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
352 | {{0x1b, 0x15, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
353 | {{0x1b, 0x16, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
354 | {{0x1b, 0x77, 0xa2, 0x00, 0x00, 0x00}, 1}, | ||
355 | {{0x1b, 0x06, 0x0f, 0x00, 0x00, 0x00}, 1}, | ||
356 | {{0x1b, 0x07, 0x14, 0x00, 0x00, 0x00}, 1}, | ||
357 | {{0x1b, 0x08, 0x0f, 0x00, 0x00, 0x00}, 1}, | ||
358 | {{0x1b, 0x09, 0x10, 0x00, 0x00, 0x00}, 1}, | ||
359 | {{0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
360 | {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
361 | {{0x1b, 0x12, 0x07, 0x00, 0x00, 0x00}, 1}, | ||
362 | {{0x1b, 0x10, 0x1f, 0x00, 0x00, 0x00}, 1}, | ||
363 | {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1}, | ||
364 | {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 1}, /* width/8 */ | ||
365 | {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 1}, /* height/8 */ | ||
366 | /* {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample? | ||
367 | * {{0x13, 0x28, 0x01, 0x1e, 0x00, 0x00}, 4}, does nothing | ||
368 | * {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, */ | ||
369 | /* {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4}, | ||
370 | * causes subsampling | ||
371 | * but not a change in the resolution setting! */ | ||
372 | {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, | ||
373 | {{0x13, 0x2d, 0x01, 0x01, 0x00, 0x00}, 4}, | ||
374 | {{0x13, 0x2e, 0x01, 0x08, 0x00, 0x00}, 4}, | ||
375 | {{0x13, 0x2f, 0x01, 0x06, 0x00, 0x00}, 4}, | ||
376 | {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
377 | {{0x1b, 0x04, 0x6d, 0x00, 0x00, 0x00}, 1}, | ||
378 | {{0x1b, 0x05, 0x03, 0x00, 0x00, 0x00}, 1}, | ||
379 | {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1}, | ||
380 | {{0x1b, 0x0e, 0x01, 0x00, 0x00, 0x00}, 1}, | ||
381 | {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
382 | {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
383 | {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1}, | ||
384 | {{0x1b, 0x10, 0x0f, 0x00, 0x00, 0x00}, 1}, | ||
385 | {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, | ||
386 | {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1}, | ||
387 | {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1},/* use compression */ | ||
388 | /* Camera should start to capture now. */ | ||
389 | }; | ||
390 | |||
391 | return run_start_commands(gspca_dev, cif_start_commands, | ||
392 | ARRAY_SIZE(cif_start_commands)); | ||
393 | } | ||
394 | |||
395 | static int start_ms350_cam(struct gspca_dev *gspca_dev) | ||
396 | { | ||
397 | struct init_command ms350_start_commands[] = { | ||
398 | {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
399 | {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
400 | {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
401 | {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
402 | {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4}, | ||
403 | {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4}, | ||
404 | {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
405 | {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, | ||
406 | {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, | ||
407 | {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, | ||
408 | {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, | ||
409 | {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
410 | {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
411 | {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
412 | {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, | ||
413 | {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, | ||
414 | {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, | ||
415 | {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, | ||
416 | {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
417 | {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, | ||
418 | {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
419 | {{0x11, 0x00, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
420 | {{0x11, 0x01, 0x70, 0x00, 0x00, 0x00}, 4}, | ||
421 | {{0x11, 0x02, 0x05, 0x00, 0x00, 0x00}, 4}, | ||
422 | {{0x11, 0x03, 0x5d, 0x00, 0x00, 0x00}, 4}, | ||
423 | {{0x11, 0x04, 0x07, 0x00, 0x00, 0x00}, 4}, | ||
424 | {{0x11, 0x05, 0x25, 0x00, 0x00, 0x00}, 4}, | ||
425 | {{0x11, 0x06, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
426 | {{0x11, 0x07, 0x09, 0x00, 0x00, 0x00}, 4}, | ||
427 | {{0x11, 0x08, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
428 | {{0x11, 0x09, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
429 | {{0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
430 | {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
431 | {{0x11, 0x0c, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
432 | {{0x11, 0x0d, 0x0c, 0x00, 0x00, 0x00}, 4}, | ||
433 | {{0x11, 0x0e, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
434 | {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
435 | {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
436 | {{0x11, 0x11, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
437 | {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
438 | {{0x11, 0x13, 0x63, 0x00, 0x00, 0x00}, 4}, | ||
439 | {{0x11, 0x15, 0x70, 0x00, 0x00, 0x00}, 4}, | ||
440 | {{0x11, 0x18, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
441 | {{0x11, 0x11, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
442 | {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* width */ | ||
443 | {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* height */ | ||
444 | {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* vstart? */ | ||
445 | {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, | ||
446 | {{0x13, 0x29, 0x01, 0x40, 0x00, 0x00}, 4}, /* hstart? */ | ||
447 | {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, | ||
448 | {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, | ||
449 | {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, | ||
450 | {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, | ||
451 | {{0x1b, 0x02, 0x05, 0x00, 0x00, 0x00}, 1}, | ||
452 | {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1}, | ||
453 | {{0x20, 0x18, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
454 | {{0x1b, 0x02, 0x0a, 0x00, 0x00, 0x00}, 1}, | ||
455 | {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 0}, | ||
456 | /* Camera should start to capture now. */ | ||
457 | }; | ||
458 | |||
459 | return run_start_commands(gspca_dev, ms350_start_commands, | ||
460 | ARRAY_SIZE(ms350_start_commands)); | ||
461 | } | ||
462 | |||
463 | static int start_genius_cam(struct gspca_dev *gspca_dev) | ||
464 | { | ||
465 | struct init_command genius_start_commands[] = { | ||
466 | {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
467 | {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
468 | {{0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
469 | {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, | ||
470 | {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, | ||
471 | /* "preliminary" width and height settings */ | ||
472 | {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4}, | ||
473 | {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, | ||
474 | {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4}, | ||
475 | {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, | ||
476 | {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4}, | ||
477 | {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, | ||
478 | {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4}, | ||
479 | {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
480 | {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4}, | ||
481 | {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
482 | {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4}, | ||
483 | {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
484 | {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4}, | ||
485 | {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
486 | {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4}, | ||
487 | {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
488 | {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4}, | ||
489 | {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
490 | {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4}, | ||
491 | {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
492 | {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4}, | ||
493 | {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
494 | {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4}, | ||
495 | {{0x11, 0x25, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
496 | {{0x11, 0x26, 0x02, 0x00, 0x00, 0x00}, 4}, | ||
497 | {{0x11, 0x27, 0x88, 0x00, 0x00, 0x00}, 4}, | ||
498 | {{0x11, 0x30, 0x38, 0x00, 0x00, 0x00}, 4}, | ||
499 | {{0x11, 0x31, 0x2a, 0x00, 0x00, 0x00}, 4}, | ||
500 | {{0x11, 0x32, 0x2a, 0x00, 0x00, 0x00}, 4}, | ||
501 | {{0x11, 0x33, 0x2a, 0x00, 0x00, 0x00}, 4}, | ||
502 | {{0x11, 0x34, 0x02, 0x00, 0x00, 0x00}, 4}, | ||
503 | {{0x11, 0x5b, 0x0a, 0x00, 0x00, 0x00}, 4}, | ||
504 | {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* real width */ | ||
505 | {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* real height */ | ||
506 | {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4}, | ||
507 | {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, | ||
508 | {{0x13, 0x29, 0x01, 0x62, 0x00, 0x00}, 4}, | ||
509 | {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, | ||
510 | {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, | ||
511 | {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, | ||
512 | {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, | ||
513 | {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
514 | {{0x11, 0x21, 0x2a, 0x00, 0x00, 0x00}, 4}, | ||
515 | {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
516 | {{0x11, 0x23, 0x28, 0x00, 0x00, 0x00}, 4}, | ||
517 | {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
518 | {{0x11, 0x11, 0x04, 0x00, 0x00, 0x00}, 4}, | ||
519 | {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
520 | {{0x11, 0x13, 0x03, 0x00, 0x00, 0x00}, 4}, | ||
521 | {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
522 | {{0x11, 0x15, 0xe0, 0x00, 0x00, 0x00}, 4}, | ||
523 | {{0x11, 0x16, 0x02, 0x00, 0x00, 0x00}, 4}, | ||
524 | {{0x11, 0x17, 0x80, 0x00, 0x00, 0x00}, 4}, | ||
525 | {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1}, | ||
526 | {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1}, | ||
527 | {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 0} | ||
528 | /* Camera should start to capture now. */ | ||
529 | }; | ||
530 | |||
531 | return run_start_commands(gspca_dev, genius_start_commands, | ||
532 | ARRAY_SIZE(genius_start_commands)); | ||
533 | } | ||
534 | |||
535 | static int start_vivitar_cam(struct gspca_dev *gspca_dev) | ||
536 | { | ||
537 | struct init_command vivitar_start_commands[] = { | ||
538 | {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4}, | ||
539 | {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
540 | {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
541 | {{0x13, 0x22, 0x01, 0x01, 0x00, 0x00}, 4}, | ||
542 | {{0x13, 0x23, 0x01, 0x01, 0x00, 0x00}, 4}, | ||
543 | {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
544 | {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, | ||
545 | {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, | ||
546 | {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, | ||
547 | {{0x13, 0x28, 0x01, 0x0a, 0x00, 0x00}, 4}, | ||
548 | /* | ||
549 | * Above is changed from OEM 0x0b. Fixes Bayer tiling. | ||
550 | * Presumably gives a vertical shift of one row. | ||
551 | */ | ||
552 | {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4}, | ||
553 | /* Above seems to do horizontal shift. */ | ||
554 | {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
555 | {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
556 | {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, | ||
557 | {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4}, | ||
558 | {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4}, | ||
559 | {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4}, | ||
560 | /* Above three commands seem to relate to brightness. */ | ||
561 | {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
562 | {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4}, | ||
563 | {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
564 | {{0x1b, 0x12, 0x80, 0x00, 0x00, 0x00}, 1}, | ||
565 | {{0x1b, 0x01, 0x77, 0x00, 0x00, 0x00}, 1}, | ||
566 | {{0x1b, 0x02, 0x3a, 0x00, 0x00, 0x00}, 1}, | ||
567 | {{0x1b, 0x12, 0x78, 0x00, 0x00, 0x00}, 1}, | ||
568 | {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
569 | {{0x1b, 0x14, 0x80, 0x00, 0x00, 0x00}, 1}, | ||
570 | {{0x1b, 0x15, 0x34, 0x00, 0x00, 0x00}, 1}, | ||
571 | {{0x1b, 0x1b, 0x04, 0x00, 0x00, 0x00}, 1}, | ||
572 | {{0x1b, 0x20, 0x44, 0x00, 0x00, 0x00}, 1}, | ||
573 | {{0x1b, 0x23, 0xee, 0x00, 0x00, 0x00}, 1}, | ||
574 | {{0x1b, 0x26, 0xa0, 0x00, 0x00, 0x00}, 1}, | ||
575 | {{0x1b, 0x27, 0x9a, 0x00, 0x00, 0x00}, 1}, | ||
576 | {{0x1b, 0x28, 0xa0, 0x00, 0x00, 0x00}, 1}, | ||
577 | {{0x1b, 0x29, 0x30, 0x00, 0x00, 0x00}, 1}, | ||
578 | {{0x1b, 0x2a, 0x80, 0x00, 0x00, 0x00}, 1}, | ||
579 | {{0x1b, 0x2b, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
580 | {{0x1b, 0x2f, 0x3d, 0x00, 0x00, 0x00}, 1}, | ||
581 | {{0x1b, 0x30, 0x24, 0x00, 0x00, 0x00}, 1}, | ||
582 | {{0x1b, 0x32, 0x86, 0x00, 0x00, 0x00}, 1}, | ||
583 | {{0x1b, 0x60, 0xa9, 0x00, 0x00, 0x00}, 1}, | ||
584 | {{0x1b, 0x61, 0x42, 0x00, 0x00, 0x00}, 1}, | ||
585 | {{0x1b, 0x65, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
586 | {{0x1b, 0x69, 0x38, 0x00, 0x00, 0x00}, 1}, | ||
587 | {{0x1b, 0x6f, 0x88, 0x00, 0x00, 0x00}, 1}, | ||
588 | {{0x1b, 0x70, 0x0b, 0x00, 0x00, 0x00}, 1}, | ||
589 | {{0x1b, 0x71, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
590 | {{0x1b, 0x74, 0x21, 0x00, 0x00, 0x00}, 1}, | ||
591 | {{0x1b, 0x75, 0x86, 0x00, 0x00, 0x00}, 1}, | ||
592 | {{0x1b, 0x76, 0x00, 0x00, 0x00, 0x00}, 1}, | ||
593 | {{0x1b, 0x7d, 0xf3, 0x00, 0x00, 0x00}, 1}, | ||
594 | {{0x1b, 0x17, 0x1c, 0x00, 0x00, 0x00}, 1}, | ||
595 | {{0x1b, 0x18, 0xc0, 0x00, 0x00, 0x00}, 1}, | ||
596 | {{0x1b, 0x19, 0x05, 0x00, 0x00, 0x00}, 1}, | ||
597 | {{0x1b, 0x1a, 0xf6, 0x00, 0x00, 0x00}, 1}, | ||
598 | /* {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, | ||
599 | {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, | ||
600 | {{0x13, 0x28, 0x01, 0x0b, 0x00, 0x00}, 4}, */ | ||
601 | {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1}, | ||
602 | {{0x1b, 0x10, 0x26, 0x00, 0x00, 0x00}, 1}, | ||
603 | {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
604 | {{0x1b, 0x76, 0x03, 0x00, 0x00, 0x00}, 1}, | ||
605 | {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1}, | ||
606 | {{0x1b, 0x00, 0x3f, 0x00, 0x00, 0x00}, 1}, | ||
607 | /* Above is brightness; OEM driver setting is 0x10 */ | ||
608 | {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4}, | ||
609 | {{0x20, 0x29, 0x30, 0x00, 0x00, 0x00}, 1}, | ||
610 | {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1} | ||
611 | }; | ||
612 | |||
613 | return run_start_commands(gspca_dev, vivitar_start_commands, | ||
614 | ARRAY_SIZE(vivitar_start_commands)); | ||
615 | } | ||
616 | |||
617 | static int sd_start(struct gspca_dev *gspca_dev) | ||
618 | { | ||
619 | struct sd *sd = (struct sd *) gspca_dev; | ||
620 | int err_code; | ||
621 | |||
622 | sd->sof_read = 0; | ||
623 | |||
624 | switch (sd->model) { | ||
625 | case 0x7005: | ||
626 | err_code = start_genius_cam(gspca_dev); | ||
627 | break; | ||
628 | case 0x8001: | ||
629 | err_code = start_spy_cam(gspca_dev); | ||
630 | break; | ||
631 | case 0x8003: | ||
632 | err_code = start_cif_cam(gspca_dev); | ||
633 | break; | ||
634 | case 0x8008: | ||
635 | err_code = start_ms350_cam(gspca_dev); | ||
636 | break; | ||
637 | case 0x800a: | ||
638 | err_code = start_vivitar_cam(gspca_dev); | ||
639 | break; | ||
640 | default: | ||
641 | PDEBUG(D_ERR, "Starting unknown camera, please report this"); | ||
642 | return -ENXIO; | ||
643 | } | ||
644 | |||
645 | return err_code; | ||
646 | } | ||
647 | |||
648 | static void sd_stopN(struct gspca_dev *gspca_dev) | ||
649 | { | ||
650 | int result; | ||
651 | __u8 data[6]; | ||
652 | |||
653 | result = sn9c2028_read1(gspca_dev); | ||
654 | if (result < 0) | ||
655 | PDEBUG(D_ERR, "Camera Stop read failed"); | ||
656 | |||
657 | memset(data, 0, 6); | ||
658 | data[0] = 0x14; | ||
659 | result = sn9c2028_command(gspca_dev, data); | ||
660 | if (result < 0) | ||
661 | PDEBUG(D_ERR, "Camera Stop command failed"); | ||
662 | } | ||
663 | |||
664 | /* Include sn9c2028 sof detection functions */ | ||
665 | #include "sn9c2028.h" | ||
666 | |||
667 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | ||
668 | __u8 *data, /* isoc packet */ | ||
669 | int len) /* iso packet length */ | ||
670 | { | ||
671 | unsigned char *sof; | ||
672 | |||
673 | sof = sn9c2028_find_sof(gspca_dev, data, len); | ||
674 | if (sof) { | ||
675 | int n; | ||
676 | |||
677 | /* finish decoding current frame */ | ||
678 | n = sof - data; | ||
679 | if (n > sizeof sn9c2028_sof_marker) | ||
680 | n -= sizeof sn9c2028_sof_marker; | ||
681 | else | ||
682 | n = 0; | ||
683 | gspca_frame_add(gspca_dev, LAST_PACKET, data, n); | ||
684 | /* Start next frame. */ | ||
685 | gspca_frame_add(gspca_dev, FIRST_PACKET, | ||
686 | sn9c2028_sof_marker, sizeof sn9c2028_sof_marker); | ||
687 | len -= sof - data; | ||
688 | data = sof; | ||
689 | } | ||
690 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | ||
691 | } | ||
692 | |||
693 | /* sub-driver description */ | ||
694 | static const struct sd_desc sd_desc = { | ||
695 | .name = MODULE_NAME, | ||
696 | .ctrls = sd_ctrls, | ||
697 | .nctrls = ARRAY_SIZE(sd_ctrls), | ||
698 | .config = sd_config, | ||
699 | .init = sd_init, | ||
700 | .start = sd_start, | ||
701 | .stopN = sd_stopN, | ||
702 | .pkt_scan = sd_pkt_scan, | ||
703 | }; | ||
704 | |||
705 | /* -- module initialisation -- */ | ||
706 | static const __devinitdata struct usb_device_id device_table[] = { | ||
707 | {USB_DEVICE(0x0458, 0x7005)}, /* Genius Smart 300, version 2 */ | ||
708 | /* The Genius Smart is untested. I can't find an owner ! */ | ||
709 | /* {USB_DEVICE(0x0c45, 0x8000)}, DC31VC, Don't know this camera */ | ||
710 | {USB_DEVICE(0x0c45, 0x8001)}, /* Wild Planet digital spy cam */ | ||
711 | {USB_DEVICE(0x0c45, 0x8003)}, /* Several small CIF cameras */ | ||
712 | /* {USB_DEVICE(0x0c45, 0x8006)}, Unknown VGA camera */ | ||
713 | {USB_DEVICE(0x0c45, 0x8008)}, /* Mini-Shotz ms-350 */ | ||
714 | {USB_DEVICE(0x0c45, 0x800a)}, /* Vivicam 3350B */ | ||
715 | {} | ||
716 | }; | ||
717 | MODULE_DEVICE_TABLE(usb, device_table); | ||
718 | |||
719 | /* -- device connect -- */ | ||
720 | static int sd_probe(struct usb_interface *intf, | ||
721 | const struct usb_device_id *id) | ||
722 | { | ||
723 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | ||
724 | THIS_MODULE); | ||
725 | } | ||
726 | |||
727 | static struct usb_driver sd_driver = { | ||
728 | .name = MODULE_NAME, | ||
729 | .id_table = device_table, | ||
730 | .probe = sd_probe, | ||
731 | .disconnect = gspca_disconnect, | ||
732 | #ifdef CONFIG_PM | ||
733 | .suspend = gspca_suspend, | ||
734 | .resume = gspca_resume, | ||
735 | #endif | ||
736 | }; | ||
737 | |||
738 | /* -- module insert / remove -- */ | ||
739 | static int __init sd_mod_init(void) | ||
740 | { | ||
741 | int ret; | ||
742 | |||
743 | ret = usb_register(&sd_driver); | ||
744 | if (ret < 0) | ||
745 | return ret; | ||
746 | PDEBUG(D_PROBE, "registered"); | ||
747 | return 0; | ||
748 | } | ||
749 | |||
750 | static void __exit sd_mod_exit(void) | ||
751 | { | ||
752 | usb_deregister(&sd_driver); | ||
753 | PDEBUG(D_PROBE, "deregistered"); | ||
754 | } | ||
755 | |||
756 | module_init(sd_mod_init); | ||
757 | module_exit(sd_mod_exit); | ||
diff --git a/drivers/media/video/gspca/sn9c2028.h b/drivers/media/video/gspca/sn9c2028.h new file mode 100644 index 000000000000..8fd1d3e05665 --- /dev/null +++ b/drivers/media/video/gspca/sn9c2028.h | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | * SN9C2028 common functions | ||
3 | * | ||
4 | * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn,edu> | ||
5 | * | ||
6 | * Based closely upon the file gspca/pac_common.h | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | static const unsigned char sn9c2028_sof_marker[5] = | ||
25 | { 0xff, 0xff, 0x00, 0xc4, 0xc4 }; | ||
26 | |||
27 | static unsigned char *sn9c2028_find_sof(struct gspca_dev *gspca_dev, | ||
28 | unsigned char *m, int len) | ||
29 | { | ||
30 | struct sd *sd = (struct sd *) gspca_dev; | ||
31 | int i; | ||
32 | |||
33 | /* Search for the SOF marker (fixed part) in the header */ | ||
34 | for (i = 0; i < len; i++) { | ||
35 | if (m[i] == sn9c2028_sof_marker[sd->sof_read]) { | ||
36 | sd->sof_read++; | ||
37 | if (sd->sof_read == sizeof(sn9c2028_sof_marker)) { | ||
38 | PDEBUG(D_FRAM, | ||
39 | "SOF found, bytes to analyze: %u." | ||
40 | " Frame starts at byte #%u", | ||
41 | len, i + 1); | ||
42 | sd->sof_read = 0; | ||
43 | return m + i + 1; | ||
44 | } | ||
45 | } else { | ||
46 | sd->sof_read = 0; | ||
47 | } | ||
48 | } | ||
49 | |||
50 | return NULL; | ||
51 | } | ||
diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 0ca1c06652b1..4a1bc08f82b9 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c | |||
@@ -129,7 +129,7 @@ static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val); | |||
129 | static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val); | 129 | static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val); |
130 | static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val); | 130 | static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val); |
131 | 131 | ||
132 | static struct ctrl sd_ctrls[] = { | 132 | static const struct ctrl sd_ctrls[] = { |
133 | { | 133 | { |
134 | #define BRIGHTNESS_IDX 0 | 134 | #define BRIGHTNESS_IDX 0 |
135 | { | 135 | { |
@@ -1506,36 +1506,36 @@ static int set_cmatrix(struct gspca_dev *gspca_dev) | |||
1506 | struct sd *sd = (struct sd *) gspca_dev; | 1506 | struct sd *sd = (struct sd *) gspca_dev; |
1507 | s32 hue_coord, hue_index = 180 + sd->hue; | 1507 | s32 hue_coord, hue_index = 180 + sd->hue; |
1508 | u8 cmatrix[21]; | 1508 | u8 cmatrix[21]; |
1509 | memset(cmatrix, 0, 21); | ||
1510 | 1509 | ||
1510 | memset(cmatrix, 0, sizeof cmatrix); | ||
1511 | cmatrix[2] = (sd->contrast * 0x25 / 0x100) + 0x26; | 1511 | cmatrix[2] = (sd->contrast * 0x25 / 0x100) + 0x26; |
1512 | cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25; | 1512 | cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25; |
1513 | cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25; | 1513 | cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25; |
1514 | cmatrix[18] = sd->brightness - 0x80; | 1514 | cmatrix[18] = sd->brightness - 0x80; |
1515 | 1515 | ||
1516 | hue_coord = (hsv_red_x[hue_index] * sd->saturation) >> 8; | 1516 | hue_coord = (hsv_red_x[hue_index] * sd->saturation) >> 8; |
1517 | cmatrix[6] = (unsigned char)(hue_coord & 0xff); | 1517 | cmatrix[6] = hue_coord; |
1518 | cmatrix[7] = (unsigned char)((hue_coord >> 8) & 0x0f); | 1518 | cmatrix[7] = (hue_coord >> 8) & 0x0f; |
1519 | 1519 | ||
1520 | hue_coord = (hsv_red_y[hue_index] * sd->saturation) >> 8; | 1520 | hue_coord = (hsv_red_y[hue_index] * sd->saturation) >> 8; |
1521 | cmatrix[8] = (unsigned char)(hue_coord & 0xff); | 1521 | cmatrix[8] = hue_coord; |
1522 | cmatrix[9] = (unsigned char)((hue_coord >> 8) & 0x0f); | 1522 | cmatrix[9] = (hue_coord >> 8) & 0x0f; |
1523 | 1523 | ||
1524 | hue_coord = (hsv_green_x[hue_index] * sd->saturation) >> 8; | 1524 | hue_coord = (hsv_green_x[hue_index] * sd->saturation) >> 8; |
1525 | cmatrix[10] = (unsigned char)(hue_coord & 0xff); | 1525 | cmatrix[10] = hue_coord; |
1526 | cmatrix[11] = (unsigned char)((hue_coord >> 8) & 0x0f); | 1526 | cmatrix[11] = (hue_coord >> 8) & 0x0f; |
1527 | 1527 | ||
1528 | hue_coord = (hsv_green_y[hue_index] * sd->saturation) >> 8; | 1528 | hue_coord = (hsv_green_y[hue_index] * sd->saturation) >> 8; |
1529 | cmatrix[12] = (unsigned char)(hue_coord & 0xff); | 1529 | cmatrix[12] = hue_coord; |
1530 | cmatrix[13] = (unsigned char)((hue_coord >> 8) & 0x0f); | 1530 | cmatrix[13] = (hue_coord >> 8) & 0x0f; |
1531 | 1531 | ||
1532 | hue_coord = (hsv_blue_x[hue_index] * sd->saturation) >> 8; | 1532 | hue_coord = (hsv_blue_x[hue_index] * sd->saturation) >> 8; |
1533 | cmatrix[14] = (unsigned char)(hue_coord & 0xff); | 1533 | cmatrix[14] = hue_coord; |
1534 | cmatrix[15] = (unsigned char)((hue_coord >> 8) & 0x0f); | 1534 | cmatrix[15] = (hue_coord >> 8) & 0x0f; |
1535 | 1535 | ||
1536 | hue_coord = (hsv_blue_y[hue_index] * sd->saturation) >> 8; | 1536 | hue_coord = (hsv_blue_y[hue_index] * sd->saturation) >> 8; |
1537 | cmatrix[16] = (unsigned char)(hue_coord & 0xff); | 1537 | cmatrix[16] = hue_coord; |
1538 | cmatrix[17] = (unsigned char)((hue_coord >> 8) & 0x0f); | 1538 | cmatrix[17] = (hue_coord >> 8) & 0x0f; |
1539 | 1539 | ||
1540 | return reg_w(gspca_dev, 0x10e1, cmatrix, 21); | 1540 | return reg_w(gspca_dev, 0x10e1, cmatrix, 21); |
1541 | } | 1541 | } |
@@ -2015,6 +2015,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
2015 | default: | 2015 | default: |
2016 | cam->cam_mode = vga_mode; | 2016 | cam->cam_mode = vga_mode; |
2017 | cam->nmodes = ARRAY_SIZE(vga_mode); | 2017 | cam->nmodes = ARRAY_SIZE(vga_mode); |
2018 | break; | ||
2018 | } | 2019 | } |
2019 | 2020 | ||
2020 | sd->old_step = 0; | 2021 | sd->old_step = 0; |
@@ -2319,7 +2320,7 @@ static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum) | |||
2319 | } | 2320 | } |
2320 | } | 2321 | } |
2321 | if (avg_lum > MAX_AVG_LUM) { | 2322 | if (avg_lum > MAX_AVG_LUM) { |
2322 | if (sd->gain >= 1) { | 2323 | if (sd->gain > 0) { |
2323 | sd->gain--; | 2324 | sd->gain--; |
2324 | set_gain(gspca_dev); | 2325 | set_gain(gspca_dev); |
2325 | } | 2326 | } |
@@ -2347,7 +2348,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
2347 | { | 2348 | { |
2348 | struct sd *sd = (struct sd *) gspca_dev; | 2349 | struct sd *sd = (struct sd *) gspca_dev; |
2349 | int avg_lum; | 2350 | int avg_lum; |
2350 | static unsigned char frame_header[] = | 2351 | static u8 frame_header[] = |
2351 | {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96}; | 2352 | {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96}; |
2352 | if (len == 64 && memcmp(data, frame_header, 6) == 0) { | 2353 | if (len == 64 && memcmp(data, frame_header, 6) == 0) { |
2353 | avg_lum = ((data[35] >> 2) & 3) | | 2354 | avg_lum = ((data[35] >> 2) & 3) | |
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index ddff2b5ee5c2..785eeb4c2014 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c | |||
@@ -42,6 +42,7 @@ Reg Use | |||
42 | 42 | ||
43 | #define MODULE_NAME "sonixb" | 43 | #define MODULE_NAME "sonixb" |
44 | 44 | ||
45 | #include <linux/input.h> | ||
45 | #include "gspca.h" | 46 | #include "gspca.h" |
46 | 47 | ||
47 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); | 48 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); |
@@ -53,9 +54,11 @@ struct sd { | |||
53 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 54 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
54 | atomic_t avg_lum; | 55 | atomic_t avg_lum; |
55 | int prev_avg_lum; | 56 | int prev_avg_lum; |
57 | int exp_too_low_cnt; | ||
58 | int exp_too_high_cnt; | ||
56 | 59 | ||
60 | unsigned short exposure; | ||
57 | unsigned char gain; | 61 | unsigned char gain; |
58 | unsigned char exposure; | ||
59 | unsigned char brightness; | 62 | unsigned char brightness; |
60 | unsigned char autogain; | 63 | unsigned char autogain; |
61 | unsigned char autogain_ignore_frames; | 64 | unsigned char autogain_ignore_frames; |
@@ -73,8 +76,9 @@ struct sd { | |||
73 | #define SENSOR_OV7630 2 | 76 | #define SENSOR_OV7630 2 |
74 | #define SENSOR_PAS106 3 | 77 | #define SENSOR_PAS106 3 |
75 | #define SENSOR_PAS202 4 | 78 | #define SENSOR_PAS202 4 |
76 | #define SENSOR_TAS5110 5 | 79 | #define SENSOR_TAS5110C 5 |
77 | #define SENSOR_TAS5130CXX 6 | 80 | #define SENSOR_TAS5110D 6 |
81 | #define SENSOR_TAS5130CXX 7 | ||
78 | __u8 reg11; | 82 | __u8 reg11; |
79 | }; | 83 | }; |
80 | 84 | ||
@@ -95,13 +99,15 @@ struct sensor_data { | |||
95 | /* sensor_data flags */ | 99 | /* sensor_data flags */ |
96 | #define F_GAIN 0x01 /* has gain */ | 100 | #define F_GAIN 0x01 /* has gain */ |
97 | #define F_SIF 0x02 /* sif or vga */ | 101 | #define F_SIF 0x02 /* sif or vga */ |
102 | #define F_COARSE_EXPO 0x04 /* exposure control is coarse */ | ||
98 | 103 | ||
99 | /* priv field of struct v4l2_pix_format flags (do not use low nibble!) */ | 104 | /* priv field of struct v4l2_pix_format flags (do not use low nibble!) */ |
100 | #define MODE_RAW 0x10 /* raw bayer mode */ | 105 | #define MODE_RAW 0x10 /* raw bayer mode */ |
101 | #define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */ | 106 | #define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */ |
102 | 107 | ||
103 | /* ctrl_dis helper macros */ | 108 | /* ctrl_dis helper macros */ |
104 | #define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX)) | 109 | #define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << COARSE_EXPOSURE_IDX) | \ |
110 | (1 << AUTOGAIN_IDX)) | ||
105 | #define NO_FREQ (1 << FREQ_IDX) | 111 | #define NO_FREQ (1 << FREQ_IDX) |
106 | #define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX) | 112 | #define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX) |
107 | 113 | ||
@@ -127,11 +133,10 @@ struct sensor_data { | |||
127 | } | 133 | } |
128 | 134 | ||
129 | /* We calculate the autogain at the end of the transfer of a frame, at this | 135 | /* We calculate the autogain at the end of the transfer of a frame, at this |
130 | moment a frame with the old settings is being transmitted, and a frame is | 136 | moment a frame with the old settings is being captured and transmitted. So |
131 | being captured with the old settings. So if we adjust the autogain we must | 137 | if we adjust the gain or exposure we must ignore atleast the next frame for |
132 | ignore atleast the 2 next frames for the new settings to come into effect | 138 | the new settings to come into effect before doing any other adjustments. */ |
133 | before doing any other adjustments */ | 139 | #define AUTOGAIN_IGNORE_FRAMES 1 |
134 | #define AUTOGAIN_IGNORE_FRAMES 3 | ||
135 | 140 | ||
136 | /* V4L2 controls supported by the driver */ | 141 | /* V4L2 controls supported by the driver */ |
137 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | 142 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); |
@@ -145,7 +150,7 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | |||
145 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | 150 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); |
146 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | 151 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); |
147 | 152 | ||
148 | static struct ctrl sd_ctrls[] = { | 153 | static const struct ctrl sd_ctrls[] = { |
149 | #define BRIGHTNESS_IDX 0 | 154 | #define BRIGHTNESS_IDX 0 |
150 | { | 155 | { |
151 | { | 156 | { |
@@ -171,7 +176,7 @@ static struct ctrl sd_ctrls[] = { | |||
171 | .maximum = 255, | 176 | .maximum = 255, |
172 | .step = 1, | 177 | .step = 1, |
173 | #define GAIN_DEF 127 | 178 | #define GAIN_DEF 127 |
174 | #define GAIN_KNEE 200 | 179 | #define GAIN_KNEE 230 |
175 | .default_value = GAIN_DEF, | 180 | .default_value = GAIN_DEF, |
176 | }, | 181 | }, |
177 | .set = sd_setgain, | 182 | .set = sd_setgain, |
@@ -183,10 +188,10 @@ static struct ctrl sd_ctrls[] = { | |||
183 | .id = V4L2_CID_EXPOSURE, | 188 | .id = V4L2_CID_EXPOSURE, |
184 | .type = V4L2_CTRL_TYPE_INTEGER, | 189 | .type = V4L2_CTRL_TYPE_INTEGER, |
185 | .name = "Exposure", | 190 | .name = "Exposure", |
186 | #define EXPOSURE_DEF 16 /* 32 ms / 30 fps */ | 191 | #define EXPOSURE_DEF 66 /* 33 ms / 30 fps (except on PASXXX) */ |
187 | #define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */ | 192 | #define EXPOSURE_KNEE 200 /* 100 ms / 10 fps (except on PASXXX) */ |
188 | .minimum = 0, | 193 | .minimum = 0, |
189 | .maximum = 255, | 194 | .maximum = 1023, |
190 | .step = 1, | 195 | .step = 1, |
191 | .default_value = EXPOSURE_DEF, | 196 | .default_value = EXPOSURE_DEF, |
192 | .flags = 0, | 197 | .flags = 0, |
@@ -194,7 +199,23 @@ static struct ctrl sd_ctrls[] = { | |||
194 | .set = sd_setexposure, | 199 | .set = sd_setexposure, |
195 | .get = sd_getexposure, | 200 | .get = sd_getexposure, |
196 | }, | 201 | }, |
197 | #define AUTOGAIN_IDX 3 | 202 | #define COARSE_EXPOSURE_IDX 3 |
203 | { | ||
204 | { | ||
205 | .id = V4L2_CID_EXPOSURE, | ||
206 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
207 | .name = "Exposure", | ||
208 | #define COARSE_EXPOSURE_DEF 2 /* 30 fps */ | ||
209 | .minimum = 2, | ||
210 | .maximum = 15, | ||
211 | .step = 1, | ||
212 | .default_value = COARSE_EXPOSURE_DEF, | ||
213 | .flags = 0, | ||
214 | }, | ||
215 | .set = sd_setexposure, | ||
216 | .get = sd_getexposure, | ||
217 | }, | ||
218 | #define AUTOGAIN_IDX 4 | ||
198 | { | 219 | { |
199 | { | 220 | { |
200 | .id = V4L2_CID_AUTOGAIN, | 221 | .id = V4L2_CID_AUTOGAIN, |
@@ -210,7 +231,7 @@ static struct ctrl sd_ctrls[] = { | |||
210 | .set = sd_setautogain, | 231 | .set = sd_setautogain, |
211 | .get = sd_getautogain, | 232 | .get = sd_getautogain, |
212 | }, | 233 | }, |
213 | #define FREQ_IDX 4 | 234 | #define FREQ_IDX 5 |
214 | { | 235 | { |
215 | { | 236 | { |
216 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | 237 | .id = V4L2_CID_POWER_LINE_FREQUENCY, |
@@ -219,7 +240,7 @@ static struct ctrl sd_ctrls[] = { | |||
219 | .minimum = 0, | 240 | .minimum = 0, |
220 | .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ | 241 | .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ |
221 | .step = 1, | 242 | .step = 1, |
222 | #define FREQ_DEF 1 | 243 | #define FREQ_DEF 0 |
223 | .default_value = FREQ_DEF, | 244 | .default_value = FREQ_DEF, |
224 | }, | 245 | }, |
225 | .set = sd_setfreq, | 246 | .set = sd_setfreq, |
@@ -345,7 +366,7 @@ static const __u8 initOv7630[] = { | |||
345 | }; | 366 | }; |
346 | static const __u8 initOv7630_3[] = { | 367 | static const __u8 initOv7630_3[] = { |
347 | 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */ | 368 | 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */ |
348 | 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */ | 369 | 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */ |
349 | 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */ | 370 | 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */ |
350 | 0x28, 0x1e, /* H & V sizes r15 .. r16 */ | 371 | 0x28, 0x1e, /* H & V sizes r15 .. r16 */ |
351 | 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */ | 372 | 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */ |
@@ -387,6 +408,30 @@ static const __u8 initPas106[] = { | |||
387 | 0x18, 0x10, 0x02, 0x02, 0x09, 0x07 | 408 | 0x18, 0x10, 0x02, 0x02, 0x09, 0x07 |
388 | }; | 409 | }; |
389 | /* compression 0x86 mckinit1 0x2b */ | 410 | /* compression 0x86 mckinit1 0x2b */ |
411 | |||
412 | /* "Known" PAS106B registers: | ||
413 | 0x02 clock divider | ||
414 | 0x03 Variable framerate bits 4-11 | ||
415 | 0x04 Var framerate bits 0-3, one must leave the 4 msb's at 0 !! | ||
416 | The variable framerate control must never be set lower then 300, | ||
417 | which sets the framerate at 90 / reg02, otherwise vsync is lost. | ||
418 | 0x05 Shutter Time Line Offset, this can be used as an exposure control: | ||
419 | 0 = use full frame time, 255 = no exposure at all | ||
420 | Note this may never be larger then "var-framerate control" / 2 - 2. | ||
421 | When var-framerate control is < 514, no exposure is reached at the max | ||
422 | allowed value for the framerate control value, rather then at 255. | ||
423 | 0x06 Shutter Time Pixel Offset, like reg05 this influences exposure, but | ||
424 | only a very little bit, leave at 0xcd | ||
425 | 0x07 offset sign bit (bit0 1 > negative offset) | ||
426 | 0x08 offset | ||
427 | 0x09 Blue Gain | ||
428 | 0x0a Green1 Gain | ||
429 | 0x0b Green2 Gain | ||
430 | 0x0c Red Gain | ||
431 | 0x0e Global gain | ||
432 | 0x13 Write 1 to commit settings to sensor | ||
433 | */ | ||
434 | |||
390 | static const __u8 pas106_sensor_init[][8] = { | 435 | static const __u8 pas106_sensor_init[][8] = { |
391 | /* Pixel Clock Divider 6 */ | 436 | /* Pixel Clock Divider 6 */ |
392 | { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 }, | 437 | { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 }, |
@@ -433,37 +478,55 @@ static const __u8 initPas202[] = { | |||
433 | 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, | 478 | 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, |
434 | 0x00, 0x00, | 479 | 0x00, 0x00, |
435 | 0x00, 0x00, 0x00, 0x06, 0x03, 0x0a, | 480 | 0x00, 0x00, 0x00, 0x06, 0x03, 0x0a, |
436 | 0x28, 0x1e, 0x28, 0x89, 0x20, | 481 | 0x28, 0x1e, 0x20, 0x89, 0x20, |
437 | 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c | 482 | 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c |
438 | }; | 483 | }; |
484 | |||
485 | /* "Known" PAS202BCB registers: | ||
486 | 0x02 clock divider | ||
487 | 0x04 Variable framerate bits 6-11 (*) | ||
488 | 0x05 Var framerate bits 0-5, one must leave the 2 msb's at 0 !! | ||
489 | 0x07 Blue Gain | ||
490 | 0x08 Green Gain | ||
491 | 0x09 Red Gain | ||
492 | 0x0b offset sign bit (bit0 1 > negative offset) | ||
493 | 0x0c offset | ||
494 | 0x0e Unknown image is slightly brighter when bit 0 is 0, if reg0f is 0 too, | ||
495 | leave at 1 otherwise we get a jump in our exposure control | ||
496 | 0x0f Exposure 0-255, 0 = use full frame time, 255 = no exposure at all | ||
497 | 0x10 Master gain 0 - 31 | ||
498 | 0x11 write 1 to apply changes | ||
499 | (*) The variable framerate control must never be set lower then 500 | ||
500 | which sets the framerate at 30 / reg02, otherwise vsync is lost. | ||
501 | */ | ||
439 | static const __u8 pas202_sensor_init[][8] = { | 502 | static const __u8 pas202_sensor_init[][8] = { |
440 | {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10}, | 503 | /* Set the clock divider to 4 -> 30 / 4 = 7.5 fps, we would like |
504 | to set it lower, but for some reason the bridge starts missing | ||
505 | vsync's then */ | ||
506 | {0xa0, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x10}, | ||
441 | {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10}, | 507 | {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10}, |
442 | {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10}, | 508 | {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10}, |
443 | {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10}, | 509 | {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x01, 0x32, 0x10}, |
444 | {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10}, | 510 | {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10}, |
445 | {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10}, | 511 | {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10}, |
446 | {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10}, | 512 | {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10}, |
447 | {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10}, | 513 | {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10}, |
448 | {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10}, | 514 | {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10}, |
449 | {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10}, | 515 | {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10}, |
450 | {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10}, | ||
451 | {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10}, | ||
452 | |||
453 | {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16}, | ||
454 | {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15}, | ||
455 | {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16}, | ||
456 | {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16}, | ||
457 | {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16}, | ||
458 | {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16}, | ||
459 | {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15}, | ||
460 | {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16}, | ||
461 | }; | 516 | }; |
462 | 517 | ||
463 | static const __u8 initTas5110[] = { | 518 | static const __u8 initTas5110c[] = { |
464 | 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, | 519 | 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, |
465 | 0x00, 0x00, | 520 | 0x00, 0x00, |
466 | 0x00, 0x01, 0x00, 0x45, 0x09, 0x0a, | 521 | 0x00, 0x00, 0x00, 0x45, 0x09, 0x0a, |
522 | 0x16, 0x12, 0x60, 0x86, 0x2b, | ||
523 | 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07 | ||
524 | }; | ||
525 | /* Same as above, except a different hstart */ | ||
526 | static const __u8 initTas5110d[] = { | ||
527 | 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, | ||
528 | 0x00, 0x00, | ||
529 | 0x00, 0x00, 0x00, 0x41, 0x09, 0x0a, | ||
467 | 0x16, 0x12, 0x60, 0x86, 0x2b, | 530 | 0x16, 0x12, 0x60, 0x86, 0x2b, |
468 | 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07 | 531 | 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07 |
469 | }; | 532 | }; |
@@ -476,7 +539,7 @@ static const __u8 tas5110_sensor_init[][8] = { | |||
476 | static const __u8 initTas5130[] = { | 539 | static const __u8 initTas5130[] = { |
477 | 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, | 540 | 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, |
478 | 0x00, 0x00, | 541 | 0x00, 0x00, |
479 | 0x00, 0x01, 0x00, 0x68, 0x0c, 0x0a, | 542 | 0x00, 0x00, 0x00, 0x68, 0x0c, 0x0a, |
480 | 0x28, 0x1e, 0x60, COMP, MCK_INIT, | 543 | 0x28, 0x1e, 0x60, COMP, MCK_INIT, |
481 | 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c | 544 | 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c |
482 | }; | 545 | }; |
@@ -493,12 +556,14 @@ SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0), | |||
493 | SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60), | 556 | SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60), |
494 | SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, | 557 | SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, |
495 | F_GAIN, 0, 0x21), | 558 | F_GAIN, 0, 0x21), |
496 | SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_SIF, NO_EXPO|NO_FREQ, | 559 | SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_GAIN|F_SIF, NO_FREQ, |
497 | 0), | 560 | 0), |
498 | SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, 0, | 561 | SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, F_GAIN, |
499 | NO_EXPO|NO_FREQ, 0), | 562 | NO_FREQ, 0), |
500 | SENS(initTas5110, NULL, tas5110_sensor_init, NULL, NULL, F_GAIN|F_SIF, | 563 | SENS(initTas5110c, NULL, tas5110_sensor_init, NULL, NULL, |
501 | NO_BRIGHTNESS|NO_FREQ, 0), | 564 | F_GAIN|F_SIF|F_COARSE_EXPO, NO_BRIGHTNESS|NO_FREQ, 0), |
565 | SENS(initTas5110d, NULL, tas5110_sensor_init, NULL, NULL, | ||
566 | F_GAIN|F_SIF|F_COARSE_EXPO, NO_BRIGHTNESS|NO_FREQ, 0), | ||
502 | SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, | 567 | SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, |
503 | 0), | 568 | 0), |
504 | }; | 569 | }; |
@@ -587,42 +652,28 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
587 | goto err; | 652 | goto err; |
588 | break; | 653 | break; |
589 | } | 654 | } |
590 | case SENSOR_PAS106: { | 655 | case SENSOR_PAS106: |
591 | __u8 i2c1[] = | ||
592 | {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14}; | ||
593 | |||
594 | i2c1[3] = sd->brightness >> 3; | ||
595 | i2c1[2] = 0x0e; | ||
596 | if (i2c_w(gspca_dev, i2c1) < 0) | ||
597 | goto err; | ||
598 | i2c1[3] = 0x01; | ||
599 | i2c1[2] = 0x13; | ||
600 | if (i2c_w(gspca_dev, i2c1) < 0) | ||
601 | goto err; | ||
602 | break; | ||
603 | } | ||
604 | case SENSOR_PAS202: { | 656 | case SENSOR_PAS202: { |
605 | /* __u8 i2cpexpo1[] = | 657 | __u8 i2cpbright[] = |
606 | {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */ | 658 | {0xb0, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x16}; |
607 | __u8 i2cpexpo[] = | 659 | __u8 i2cpdoit[] = |
608 | {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16}; | 660 | {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16}; |
609 | __u8 i2cp202[] = | 661 | |
610 | {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15}; | 662 | /* PAS106 uses reg 7 and 8 instead of b and c */ |
611 | static __u8 i2cpdoit[] = | 663 | if (sd->sensor == SENSOR_PAS106) { |
612 | {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16}; | 664 | i2cpbright[2] = 7; |
613 | 665 | i2cpdoit[2] = 0x13; | |
614 | /* change reg 0x10 */ | 666 | } |
615 | i2cpexpo[4] = 0xff - sd->brightness; | 667 | |
616 | /* if(i2c_w(gspca_dev,i2cpexpo1) < 0) | 668 | if (sd->brightness < 127) { |
617 | goto err; */ | 669 | /* change reg 0x0b, signreg */ |
618 | /* if(i2c_w(gspca_dev,i2cpdoit) < 0) | 670 | i2cpbright[3] = 0x01; |
619 | goto err; */ | 671 | /* set reg 0x0c, offset */ |
620 | if (i2c_w(gspca_dev, i2cpexpo) < 0) | 672 | i2cpbright[4] = 127 - sd->brightness; |
621 | goto err; | 673 | } else |
622 | if (i2c_w(gspca_dev, i2cpdoit) < 0) | 674 | i2cpbright[4] = sd->brightness - 127; |
623 | goto err; | 675 | |
624 | i2cp202[3] = sd->brightness >> 3; | 676 | if (i2c_w(gspca_dev, i2cpbright) < 0) |
625 | if (i2c_w(gspca_dev, i2cp202) < 0) | ||
626 | goto err; | 677 | goto err; |
627 | if (i2c_w(gspca_dev, i2cpdoit) < 0) | 678 | if (i2c_w(gspca_dev, i2cpdoit) < 0) |
628 | goto err; | 679 | goto err; |
@@ -652,7 +703,8 @@ static void setsensorgain(struct gspca_dev *gspca_dev) | |||
652 | 703 | ||
653 | switch (sd->sensor) { | 704 | switch (sd->sensor) { |
654 | 705 | ||
655 | case SENSOR_TAS5110: { | 706 | case SENSOR_TAS5110C: |
707 | case SENSOR_TAS5110D: { | ||
656 | __u8 i2c[] = | 708 | __u8 i2c[] = |
657 | {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10}; | 709 | {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10}; |
658 | 710 | ||
@@ -674,6 +726,37 @@ static void setsensorgain(struct gspca_dev *gspca_dev) | |||
674 | goto err; | 726 | goto err; |
675 | break; | 727 | break; |
676 | } | 728 | } |
729 | case SENSOR_PAS106: | ||
730 | case SENSOR_PAS202: { | ||
731 | __u8 i2cpgain[] = | ||
732 | {0xa0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x15}; | ||
733 | __u8 i2cpcolorgain[] = | ||
734 | {0xc0, 0x40, 0x07, 0x00, 0x00, 0x00, 0x00, 0x15}; | ||
735 | __u8 i2cpdoit[] = | ||
736 | {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16}; | ||
737 | |||
738 | /* PAS106 uses different regs (and has split green gains) */ | ||
739 | if (sd->sensor == SENSOR_PAS106) { | ||
740 | i2cpgain[2] = 0x0e; | ||
741 | i2cpcolorgain[0] = 0xd0; | ||
742 | i2cpcolorgain[2] = 0x09; | ||
743 | i2cpdoit[2] = 0x13; | ||
744 | } | ||
745 | |||
746 | i2cpgain[3] = sd->gain >> 3; | ||
747 | i2cpcolorgain[3] = sd->gain >> 4; | ||
748 | i2cpcolorgain[4] = sd->gain >> 4; | ||
749 | i2cpcolorgain[5] = sd->gain >> 4; | ||
750 | i2cpcolorgain[6] = sd->gain >> 4; | ||
751 | |||
752 | if (i2c_w(gspca_dev, i2cpgain) < 0) | ||
753 | goto err; | ||
754 | if (i2c_w(gspca_dev, i2cpcolorgain) < 0) | ||
755 | goto err; | ||
756 | if (i2c_w(gspca_dev, i2cpdoit) < 0) | ||
757 | goto err; | ||
758 | break; | ||
759 | } | ||
677 | } | 760 | } |
678 | return; | 761 | return; |
679 | err: | 762 | err: |
@@ -684,19 +767,21 @@ static void setgain(struct gspca_dev *gspca_dev) | |||
684 | { | 767 | { |
685 | struct sd *sd = (struct sd *) gspca_dev; | 768 | struct sd *sd = (struct sd *) gspca_dev; |
686 | __u8 gain; | 769 | __u8 gain; |
687 | __u8 rgb_value; | 770 | __u8 buf[2] = { 0, 0 }; |
771 | |||
772 | if (sensor_data[sd->sensor].flags & F_GAIN) { | ||
773 | /* Use the sensor gain to do the actual gain */ | ||
774 | setsensorgain(gspca_dev); | ||
775 | return; | ||
776 | } | ||
688 | 777 | ||
689 | gain = sd->gain >> 4; | 778 | gain = sd->gain >> 4; |
690 | 779 | ||
691 | /* red and blue gain */ | 780 | /* red and blue gain */ |
692 | rgb_value = gain << 4 | gain; | 781 | buf[0] = gain << 4 | gain; |
693 | reg_w(gspca_dev, 0x10, &rgb_value, 1); | ||
694 | /* green gain */ | 782 | /* green gain */ |
695 | rgb_value = gain; | 783 | buf[1] = gain; |
696 | reg_w(gspca_dev, 0x11, &rgb_value, 1); | 784 | reg_w(gspca_dev, 0x10, buf, 2); |
697 | |||
698 | if (sensor_data[sd->sensor].flags & F_GAIN) | ||
699 | setsensorgain(gspca_dev); | ||
700 | } | 785 | } |
701 | 786 | ||
702 | static void setexposure(struct gspca_dev *gspca_dev) | 787 | static void setexposure(struct gspca_dev *gspca_dev) |
@@ -704,17 +789,12 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
704 | struct sd *sd = (struct sd *) gspca_dev; | 789 | struct sd *sd = (struct sd *) gspca_dev; |
705 | 790 | ||
706 | switch (sd->sensor) { | 791 | switch (sd->sensor) { |
707 | case SENSOR_TAS5110: { | 792 | case SENSOR_TAS5110C: |
708 | __u8 reg; | 793 | case SENSOR_TAS5110D: { |
709 | |||
710 | /* register 19's high nibble contains the sn9c10x clock divider | 794 | /* register 19's high nibble contains the sn9c10x clock divider |
711 | The high nibble configures the no fps according to the | 795 | The high nibble configures the no fps according to the |
712 | formula: 60 / high_nibble. With a maximum of 30 fps */ | 796 | formula: 60 / high_nibble. With a maximum of 30 fps */ |
713 | reg = 120 * sd->exposure / 1000; | 797 | __u8 reg = sd->exposure; |
714 | if (reg < 2) | ||
715 | reg = 2; | ||
716 | else if (reg > 15) | ||
717 | reg = 15; | ||
718 | reg = (reg << 4) | 0x0b; | 798 | reg = (reg << 4) | 0x0b; |
719 | reg_w(gspca_dev, 0x19, ®, 1); | 799 | reg_w(gspca_dev, 0x19, ®, 1); |
720 | break; | 800 | break; |
@@ -750,20 +830,21 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
750 | } else | 830 | } else |
751 | reg10_max = 0x41; | 831 | reg10_max = 0x41; |
752 | 832 | ||
753 | reg11 = (60 * sd->exposure + 999) / 1000; | 833 | reg11 = (15 * sd->exposure + 999) / 1000; |
754 | if (reg11 < 1) | 834 | if (reg11 < 1) |
755 | reg11 = 1; | 835 | reg11 = 1; |
756 | else if (reg11 > 16) | 836 | else if (reg11 > 16) |
757 | reg11 = 16; | 837 | reg11 = 16; |
758 | 838 | ||
759 | /* In 640x480, if the reg11 has less than 3, the image is | 839 | /* In 640x480, if the reg11 has less than 4, the image is |
760 | unstable (not enough bandwidth). */ | 840 | unstable (the bridge goes into a higher compression mode |
761 | if (gspca_dev->width == 640 && reg11 < 3) | 841 | which we have not reverse engineered yet). */ |
762 | reg11 = 3; | 842 | if (gspca_dev->width == 640 && reg11 < 4) |
843 | reg11 = 4; | ||
763 | 844 | ||
764 | /* frame exposure time in ms = 1000 * reg11 / 30 -> | 845 | /* frame exposure time in ms = 1000 * reg11 / 30 -> |
765 | reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */ | 846 | reg10 = (sd->exposure / 2) * reg10_max / (1000 * reg11 / 30) */ |
766 | reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11); | 847 | reg10 = (sd->exposure * 15 * reg10_max) / (1000 * reg11); |
767 | 848 | ||
768 | /* Don't allow this to get below 10 when using autogain, the | 849 | /* Don't allow this to get below 10 when using autogain, the |
769 | steps become very large (relatively) when below 10 causing | 850 | steps become very large (relatively) when below 10 causing |
@@ -786,10 +867,85 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
786 | if (i2c_w(gspca_dev, i2c) == 0) | 867 | if (i2c_w(gspca_dev, i2c) == 0) |
787 | sd->reg11 = reg11; | 868 | sd->reg11 = reg11; |
788 | else | 869 | else |
789 | PDEBUG(D_ERR, "i2c error exposure"); | 870 | goto err; |
871 | break; | ||
872 | } | ||
873 | case SENSOR_PAS202: { | ||
874 | __u8 i2cpframerate[] = | ||
875 | {0xb0, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x16}; | ||
876 | __u8 i2cpexpo[] = | ||
877 | {0xa0, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x16}; | ||
878 | const __u8 i2cpdoit[] = | ||
879 | {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16}; | ||
880 | int framerate_ctrl; | ||
881 | |||
882 | /* The exposure knee for the autogain algorithm is 200 | ||
883 | (100 ms / 10 fps on other sensors), for values below this | ||
884 | use the control for setting the partial frame expose time, | ||
885 | above that use variable framerate. This way we run at max | ||
886 | framerate (640x480@7.5 fps, 320x240@10fps) until the knee | ||
887 | is reached. Using the variable framerate control above 200 | ||
888 | is better then playing around with both clockdiv + partial | ||
889 | frame exposure times (like we are doing with the ov chips), | ||
890 | as that sometimes leads to jumps in the exposure control, | ||
891 | which are bad for auto exposure. */ | ||
892 | if (sd->exposure < 200) { | ||
893 | i2cpexpo[3] = 255 - (sd->exposure * 255) / 200; | ||
894 | framerate_ctrl = 500; | ||
895 | } else { | ||
896 | /* The PAS202's exposure control goes from 0 - 4095, | ||
897 | but anything below 500 causes vsync issues, so scale | ||
898 | our 200-1023 to 500-4095 */ | ||
899 | framerate_ctrl = (sd->exposure - 200) * 1000 / 229 + | ||
900 | 500; | ||
901 | } | ||
902 | |||
903 | i2cpframerate[3] = framerate_ctrl >> 6; | ||
904 | i2cpframerate[4] = framerate_ctrl & 0x3f; | ||
905 | if (i2c_w(gspca_dev, i2cpframerate) < 0) | ||
906 | goto err; | ||
907 | if (i2c_w(gspca_dev, i2cpexpo) < 0) | ||
908 | goto err; | ||
909 | if (i2c_w(gspca_dev, i2cpdoit) < 0) | ||
910 | goto err; | ||
911 | break; | ||
912 | } | ||
913 | case SENSOR_PAS106: { | ||
914 | __u8 i2cpframerate[] = | ||
915 | {0xb1, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x14}; | ||
916 | __u8 i2cpexpo[] = | ||
917 | {0xa1, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x14}; | ||
918 | const __u8 i2cpdoit[] = | ||
919 | {0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14}; | ||
920 | int framerate_ctrl; | ||
921 | |||
922 | /* For values below 150 use partial frame exposure, above | ||
923 | that use framerate ctrl */ | ||
924 | if (sd->exposure < 150) { | ||
925 | i2cpexpo[3] = 150 - sd->exposure; | ||
926 | framerate_ctrl = 300; | ||
927 | } else { | ||
928 | /* The PAS106's exposure control goes from 0 - 4095, | ||
929 | but anything below 300 causes vsync issues, so scale | ||
930 | our 150-1023 to 300-4095 */ | ||
931 | framerate_ctrl = (sd->exposure - 150) * 1000 / 230 + | ||
932 | 300; | ||
933 | } | ||
934 | |||
935 | i2cpframerate[3] = framerate_ctrl >> 4; | ||
936 | i2cpframerate[4] = framerate_ctrl & 0x0f; | ||
937 | if (i2c_w(gspca_dev, i2cpframerate) < 0) | ||
938 | goto err; | ||
939 | if (i2c_w(gspca_dev, i2cpexpo) < 0) | ||
940 | goto err; | ||
941 | if (i2c_w(gspca_dev, i2cpdoit) < 0) | ||
942 | goto err; | ||
790 | break; | 943 | break; |
791 | } | 944 | } |
792 | } | 945 | } |
946 | return; | ||
947 | err: | ||
948 | PDEBUG(D_ERR, "i2c error exposure"); | ||
793 | } | 949 | } |
794 | 950 | ||
795 | static void setfreq(struct gspca_dev *gspca_dev) | 951 | static void setfreq(struct gspca_dev *gspca_dev) |
@@ -823,30 +979,43 @@ static void setfreq(struct gspca_dev *gspca_dev) | |||
823 | } | 979 | } |
824 | } | 980 | } |
825 | 981 | ||
982 | #include "coarse_expo_autogain.h" | ||
983 | |||
826 | static void do_autogain(struct gspca_dev *gspca_dev) | 984 | static void do_autogain(struct gspca_dev *gspca_dev) |
827 | { | 985 | { |
828 | int deadzone, desired_avg_lum; | 986 | int deadzone, desired_avg_lum, result; |
829 | struct sd *sd = (struct sd *) gspca_dev; | 987 | struct sd *sd = (struct sd *) gspca_dev; |
830 | int avg_lum = atomic_read(&sd->avg_lum); | 988 | int avg_lum = atomic_read(&sd->avg_lum); |
831 | 989 | ||
832 | if (avg_lum == -1) | 990 | if (avg_lum == -1 || !sd->autogain) |
833 | return; | 991 | return; |
834 | 992 | ||
993 | if (sd->autogain_ignore_frames > 0) { | ||
994 | sd->autogain_ignore_frames--; | ||
995 | return; | ||
996 | } | ||
997 | |||
835 | /* SIF / VGA sensors have a different autoexposure area and thus | 998 | /* SIF / VGA sensors have a different autoexposure area and thus |
836 | different avg_lum values for the same picture brightness */ | 999 | different avg_lum values for the same picture brightness */ |
837 | if (sensor_data[sd->sensor].flags & F_SIF) { | 1000 | if (sensor_data[sd->sensor].flags & F_SIF) { |
838 | deadzone = 1000; | 1001 | deadzone = 500; |
839 | desired_avg_lum = 7000; | 1002 | /* SIF sensors tend to overexpose, so keep this small */ |
1003 | desired_avg_lum = 5000; | ||
840 | } else { | 1004 | } else { |
841 | deadzone = 3000; | 1005 | deadzone = 1500; |
842 | desired_avg_lum = 23000; | 1006 | desired_avg_lum = 18000; |
843 | } | 1007 | } |
844 | 1008 | ||
845 | if (sd->autogain_ignore_frames > 0) | 1009 | if (sensor_data[sd->sensor].flags & F_COARSE_EXPO) |
846 | sd->autogain_ignore_frames--; | 1010 | result = gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum, |
847 | else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, | 1011 | sd->brightness * desired_avg_lum / 127, |
848 | sd->brightness * desired_avg_lum / 127, | 1012 | deadzone); |
849 | deadzone, GAIN_KNEE, EXPOSURE_KNEE)) { | 1013 | else |
1014 | result = gspca_auto_gain_n_exposure(gspca_dev, avg_lum, | ||
1015 | sd->brightness * desired_avg_lum / 127, | ||
1016 | deadzone, GAIN_KNEE, EXPOSURE_KNEE); | ||
1017 | |||
1018 | if (result) { | ||
850 | PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d", | 1019 | PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d", |
851 | (int)sd->gain, (int)sd->exposure); | 1020 | (int)sd->gain, (int)sd->exposure); |
852 | sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES; | 1021 | sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES; |
@@ -881,7 +1050,13 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
881 | 1050 | ||
882 | sd->brightness = BRIGHTNESS_DEF; | 1051 | sd->brightness = BRIGHTNESS_DEF; |
883 | sd->gain = GAIN_DEF; | 1052 | sd->gain = GAIN_DEF; |
884 | sd->exposure = EXPOSURE_DEF; | 1053 | if (sensor_data[sd->sensor].flags & F_COARSE_EXPO) { |
1054 | sd->exposure = COARSE_EXPOSURE_DEF; | ||
1055 | gspca_dev->ctrl_dis |= (1 << EXPOSURE_IDX); | ||
1056 | } else { | ||
1057 | sd->exposure = EXPOSURE_DEF; | ||
1058 | gspca_dev->ctrl_dis |= (1 << COARSE_EXPOSURE_IDX); | ||
1059 | } | ||
885 | if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX)) | 1060 | if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX)) |
886 | sd->autogain = 0; /* Disable do_autogain callback */ | 1061 | sd->autogain = 0; /* Disable do_autogain callback */ |
887 | else | 1062 | else |
@@ -917,9 +1092,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
917 | reg12_19[6] = sn9c10x[0x18 - 1] | (mode << 4); | 1092 | reg12_19[6] = sn9c10x[0x18 - 1] | (mode << 4); |
918 | /* Special cases where reg 17 and or 19 value depends on mode */ | 1093 | /* Special cases where reg 17 and or 19 value depends on mode */ |
919 | switch (sd->sensor) { | 1094 | switch (sd->sensor) { |
920 | case SENSOR_PAS202: | ||
921 | reg12_19[5] = mode ? 0x24 : 0x20; | ||
922 | break; | ||
923 | case SENSOR_TAS5130CXX: | 1095 | case SENSOR_TAS5130CXX: |
924 | /* probably not mode specific at all most likely the upper | 1096 | /* probably not mode specific at all most likely the upper |
925 | nibble of 0x19 is exposure (clock divider) just as with | 1097 | nibble of 0x19 is exposure (clock divider) just as with |
@@ -955,6 +1127,16 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
955 | sensor_data[sd->sensor].sensor_bridge_init_size[ | 1127 | sensor_data[sd->sensor].sensor_bridge_init_size[ |
956 | sd->bridge]); | 1128 | sd->bridge]); |
957 | 1129 | ||
1130 | /* Mode specific sensor setup */ | ||
1131 | switch (sd->sensor) { | ||
1132 | case SENSOR_PAS202: { | ||
1133 | const __u8 i2cpclockdiv[] = | ||
1134 | {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10}; | ||
1135 | /* clockdiv from 4 to 3 (7.5 -> 10 fps) when in low res mode */ | ||
1136 | if (mode) | ||
1137 | i2c_w(gspca_dev, i2cpclockdiv); | ||
1138 | } | ||
1139 | } | ||
958 | /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */ | 1140 | /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */ |
959 | reg_w(gspca_dev, 0x15, ®12_19[3], 2); | 1141 | reg_w(gspca_dev, 0x15, ®12_19[3], 2); |
960 | /* compression register */ | 1142 | /* compression register */ |
@@ -985,6 +1167,8 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
985 | 1167 | ||
986 | sd->frames_to_drop = 0; | 1168 | sd->frames_to_drop = 0; |
987 | sd->autogain_ignore_frames = 0; | 1169 | sd->autogain_ignore_frames = 0; |
1170 | sd->exp_too_high_cnt = 0; | ||
1171 | sd->exp_too_low_cnt = 0; | ||
988 | atomic_set(&sd->avg_lum, -1); | 1172 | atomic_set(&sd->avg_lum, -1); |
989 | return 0; | 1173 | return 0; |
990 | } | 1174 | } |
@@ -1143,11 +1327,14 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | |||
1143 | struct sd *sd = (struct sd *) gspca_dev; | 1327 | struct sd *sd = (struct sd *) gspca_dev; |
1144 | 1328 | ||
1145 | sd->autogain = val; | 1329 | sd->autogain = val; |
1330 | sd->exp_too_high_cnt = 0; | ||
1331 | sd->exp_too_low_cnt = 0; | ||
1332 | |||
1146 | /* when switching to autogain set defaults to make sure | 1333 | /* when switching to autogain set defaults to make sure |
1147 | we are on a valid point of the autogain gain / | 1334 | we are on a valid point of the autogain gain / |
1148 | exposure knee graph, and give this change time to | 1335 | exposure knee graph, and give this change time to |
1149 | take effect before doing autogain. */ | 1336 | take effect before doing autogain. */ |
1150 | if (sd->autogain) { | 1337 | if (sd->autogain && !(sensor_data[sd->sensor].flags & F_COARSE_EXPO)) { |
1151 | sd->exposure = EXPOSURE_DEF; | 1338 | sd->exposure = EXPOSURE_DEF; |
1152 | sd->gain = GAIN_DEF; | 1339 | sd->gain = GAIN_DEF; |
1153 | if (gspca_dev->streaming) { | 1340 | if (gspca_dev->streaming) { |
@@ -1207,6 +1394,25 @@ static int sd_querymenu(struct gspca_dev *gspca_dev, | |||
1207 | return -EINVAL; | 1394 | return -EINVAL; |
1208 | } | 1395 | } |
1209 | 1396 | ||
1397 | #ifdef CONFIG_INPUT | ||
1398 | static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, | ||
1399 | u8 *data, /* interrupt packet data */ | ||
1400 | int len) /* interrupt packet length */ | ||
1401 | { | ||
1402 | int ret = -EINVAL; | ||
1403 | |||
1404 | if (len == 1 && data[0] == 1) { | ||
1405 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); | ||
1406 | input_sync(gspca_dev->input_dev); | ||
1407 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); | ||
1408 | input_sync(gspca_dev->input_dev); | ||
1409 | ret = 0; | ||
1410 | } | ||
1411 | |||
1412 | return ret; | ||
1413 | } | ||
1414 | #endif | ||
1415 | |||
1210 | /* sub-driver description */ | 1416 | /* sub-driver description */ |
1211 | static const struct sd_desc sd_desc = { | 1417 | static const struct sd_desc sd_desc = { |
1212 | .name = MODULE_NAME, | 1418 | .name = MODULE_NAME, |
@@ -1219,6 +1425,9 @@ static const struct sd_desc sd_desc = { | |||
1219 | .pkt_scan = sd_pkt_scan, | 1425 | .pkt_scan = sd_pkt_scan, |
1220 | .querymenu = sd_querymenu, | 1426 | .querymenu = sd_querymenu, |
1221 | .dq_callback = do_autogain, | 1427 | .dq_callback = do_autogain, |
1428 | #ifdef CONFIG_INPUT | ||
1429 | .int_pkt_scan = sd_int_pkt_scan, | ||
1430 | #endif | ||
1222 | }; | 1431 | }; |
1223 | 1432 | ||
1224 | /* -- module initialisation -- */ | 1433 | /* -- module initialisation -- */ |
@@ -1227,21 +1436,21 @@ static const struct sd_desc sd_desc = { | |||
1227 | 1436 | ||
1228 | 1437 | ||
1229 | static const struct usb_device_id device_table[] __devinitconst = { | 1438 | static const struct usb_device_id device_table[] __devinitconst = { |
1230 | {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110, 102)}, /* TAS5110C1B */ | 1439 | {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110C, 102)}, /* TAS5110C1B */ |
1231 | {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110, 101)}, /* TAS5110C1B */ | 1440 | {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110C, 101)}, /* TAS5110C1B */ |
1232 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE | 1441 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE |
1233 | {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110, 101)}, /* TAS5110D */ | 1442 | {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110D, 101)}, /* TAS5110D */ |
1443 | #endif | ||
1234 | {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)}, | 1444 | {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)}, |
1235 | {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)}, | 1445 | {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)}, |
1236 | #endif | ||
1237 | {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)}, | 1446 | {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)}, |
1238 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE | 1447 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE |
1239 | {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)}, | 1448 | {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)}, |
1240 | {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)}, | 1449 | {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)}, |
1241 | {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)}, | 1450 | {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)}, |
1451 | #endif | ||
1242 | {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)}, | 1452 | {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)}, |
1243 | {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)}, | 1453 | {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)}, |
1244 | #endif | ||
1245 | {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)}, | 1454 | {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)}, |
1246 | {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)}, | 1455 | {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)}, |
1247 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE | 1456 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE |
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index 0bd36a00dd2a..83d5773d4629 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c | |||
@@ -21,6 +21,7 @@ | |||
21 | 21 | ||
22 | #define MODULE_NAME "sonixj" | 22 | #define MODULE_NAME "sonixj" |
23 | 23 | ||
24 | #include <linux/input.h> | ||
24 | #include "gspca.h" | 25 | #include "gspca.h" |
25 | #include "jpeg.h" | 26 | #include "jpeg.h" |
26 | 27 | ||
@@ -45,6 +46,7 @@ struct sd { | |||
45 | u8 red; | 46 | u8 red; |
46 | u8 gamma; | 47 | u8 gamma; |
47 | u8 vflip; /* ov7630/ov7648 only */ | 48 | u8 vflip; /* ov7630/ov7648 only */ |
49 | u8 sharpness; | ||
48 | u8 infrared; /* mt9v111 only */ | 50 | u8 infrared; /* mt9v111 only */ |
49 | u8 freq; /* ov76xx only */ | 51 | u8 freq; /* ov76xx only */ |
50 | u8 quality; /* image quality */ | 52 | u8 quality; /* image quality */ |
@@ -64,16 +66,17 @@ struct sd { | |||
64 | #define BRIDGE_SN9C110 2 | 66 | #define BRIDGE_SN9C110 2 |
65 | #define BRIDGE_SN9C120 3 | 67 | #define BRIDGE_SN9C120 3 |
66 | u8 sensor; /* Type of image sensor chip */ | 68 | u8 sensor; /* Type of image sensor chip */ |
67 | #define SENSOR_HV7131R 0 | 69 | #define SENSOR_ADCM1700 0 |
68 | #define SENSOR_MI0360 1 | 70 | #define SENSOR_HV7131R 1 |
69 | #define SENSOR_MO4000 2 | 71 | #define SENSOR_MI0360 2 |
70 | #define SENSOR_MT9V111 3 | 72 | #define SENSOR_MO4000 3 |
71 | #define SENSOR_OM6802 4 | 73 | #define SENSOR_MT9V111 4 |
72 | #define SENSOR_OV7630 5 | 74 | #define SENSOR_OM6802 5 |
73 | #define SENSOR_OV7648 6 | 75 | #define SENSOR_OV7630 6 |
74 | #define SENSOR_OV7660 7 | 76 | #define SENSOR_OV7648 7 |
75 | #define SENSOR_PO1030 8 | 77 | #define SENSOR_OV7660 8 |
76 | #define SENSOR_SP80708 9 | 78 | #define SENSOR_PO1030 9 |
79 | #define SENSOR_SP80708 10 | ||
77 | u8 i2c_addr; | 80 | u8 i2c_addr; |
78 | 81 | ||
79 | u8 *jpeg_hdr; | 82 | u8 *jpeg_hdr; |
@@ -96,12 +99,14 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | |||
96 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | 99 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); |
97 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); | 100 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); |
98 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); | 101 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); |
102 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); | ||
103 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | ||
99 | static int sd_setinfrared(struct gspca_dev *gspca_dev, __s32 val); | 104 | static int sd_setinfrared(struct gspca_dev *gspca_dev, __s32 val); |
100 | static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val); | 105 | static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val); |
101 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | 106 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); |
102 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | 107 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); |
103 | 108 | ||
104 | static struct ctrl sd_ctrls[] = { | 109 | static const struct ctrl sd_ctrls[] = { |
105 | #define BRIGHTNESS_IDX 0 | 110 | #define BRIGHTNESS_IDX 0 |
106 | { | 111 | { |
107 | { | 112 | { |
@@ -225,8 +230,23 @@ static struct ctrl sd_ctrls[] = { | |||
225 | .set = sd_setvflip, | 230 | .set = sd_setvflip, |
226 | .get = sd_getvflip, | 231 | .get = sd_getvflip, |
227 | }, | 232 | }, |
233 | #define SHARPNESS_IDX 8 | ||
234 | { | ||
235 | { | ||
236 | .id = V4L2_CID_SHARPNESS, | ||
237 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
238 | .name = "Sharpness", | ||
239 | .minimum = 0, | ||
240 | .maximum = 255, | ||
241 | .step = 1, | ||
242 | #define SHARPNESS_DEF 90 | ||
243 | .default_value = SHARPNESS_DEF, | ||
244 | }, | ||
245 | .set = sd_setsharpness, | ||
246 | .get = sd_getsharpness, | ||
247 | }, | ||
228 | /* mt9v111 only */ | 248 | /* mt9v111 only */ |
229 | #define INFRARED_IDX 8 | 249 | #define INFRARED_IDX 9 |
230 | { | 250 | { |
231 | { | 251 | { |
232 | .id = V4L2_CID_INFRARED, | 252 | .id = V4L2_CID_INFRARED, |
@@ -242,7 +262,7 @@ static struct ctrl sd_ctrls[] = { | |||
242 | .get = sd_getinfrared, | 262 | .get = sd_getinfrared, |
243 | }, | 263 | }, |
244 | /* ov7630/ov7648/ov7660 only */ | 264 | /* ov7630/ov7648/ov7660 only */ |
245 | #define FREQ_IDX 9 | 265 | #define FREQ_IDX 10 |
246 | { | 266 | { |
247 | { | 267 | { |
248 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | 268 | .id = V4L2_CID_POWER_LINE_FREQUENCY, |
@@ -261,28 +281,37 @@ static struct ctrl sd_ctrls[] = { | |||
261 | 281 | ||
262 | /* table of the disabled controls */ | 282 | /* table of the disabled controls */ |
263 | static __u32 ctrl_dis[] = { | 283 | static __u32 ctrl_dis[] = { |
284 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX) | | ||
285 | (1 << AUTOGAIN_IDX), /* SENSOR_ADCM1700 0 */ | ||
286 | (1 << INFRARED_IDX) | (1 << FREQ_IDX), | ||
287 | /* SENSOR_HV7131R 1 */ | ||
264 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), | 288 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), |
265 | /* SENSOR_HV7131R 0 */ | 289 | /* SENSOR_MI0360 2 */ |
266 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), | 290 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), |
267 | /* SENSOR_MI0360 1 */ | 291 | /* SENSOR_MO4000 3 */ |
268 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), | ||
269 | /* SENSOR_MO4000 2 */ | ||
270 | (1 << VFLIP_IDX) | (1 << FREQ_IDX), | 292 | (1 << VFLIP_IDX) | (1 << FREQ_IDX), |
271 | /* SENSOR_MT9V111 3 */ | 293 | /* SENSOR_MT9V111 4 */ |
272 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), | 294 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), |
273 | /* SENSOR_OM6802 4 */ | 295 | /* SENSOR_OM6802 5 */ |
274 | (1 << INFRARED_IDX), | 296 | (1 << INFRARED_IDX), |
275 | /* SENSOR_OV7630 5 */ | 297 | /* SENSOR_OV7630 6 */ |
276 | (1 << INFRARED_IDX), | 298 | (1 << INFRARED_IDX), |
277 | /* SENSOR_OV7648 6 */ | 299 | /* SENSOR_OV7648 7 */ |
278 | (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), | 300 | (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), |
279 | /* SENSOR_OV7660 7 */ | 301 | /* SENSOR_OV7660 8 */ |
280 | (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | | 302 | (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | |
281 | (1 << FREQ_IDX), /* SENSOR_PO1030 8 */ | 303 | (1 << FREQ_IDX), /* SENSOR_PO1030 9 */ |
282 | (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | | 304 | (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | |
283 | (1 << FREQ_IDX), /* SENSOR_SP80708 9 */ | 305 | (1 << FREQ_IDX), /* SENSOR_SP80708 10 */ |
284 | }; | 306 | }; |
285 | 307 | ||
308 | static const struct v4l2_pix_format cif_mode[] = { | ||
309 | {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
310 | .bytesperline = 352, | ||
311 | .sizeimage = 352 * 288 * 4 / 8 + 590, | ||
312 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
313 | .priv = 0}, | ||
314 | }; | ||
286 | static const struct v4l2_pix_format vga_mode[] = { | 315 | static const struct v4l2_pix_format vga_mode[] = { |
287 | {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 316 | {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, |
288 | .bytesperline = 160, | 317 | .bytesperline = 160, |
@@ -302,6 +331,17 @@ static const struct v4l2_pix_format vga_mode[] = { | |||
302 | .priv = 0}, | 331 | .priv = 0}, |
303 | }; | 332 | }; |
304 | 333 | ||
334 | static const u8 sn_adcm1700[0x1c] = { | ||
335 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ | ||
336 | 0x00, 0x43, 0x60, 0x00, 0x1a, 0x00, 0x00, 0x00, | ||
337 | /* reg8 reg9 rega regb regc regd rege regf */ | ||
338 | 0x80, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
339 | /* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */ | ||
340 | 0x03, 0x00, 0x05, 0x01, 0x05, 0x16, 0x12, 0x42, | ||
341 | /* reg18 reg19 reg1a reg1b */ | ||
342 | 0x06, 0x00, 0x00, 0x00 | ||
343 | }; | ||
344 | |||
305 | /*Data from sn9c102p+hv7131r */ | 345 | /*Data from sn9c102p+hv7131r */ |
306 | static const u8 sn_hv7131[0x1c] = { | 346 | static const u8 sn_hv7131[0x1c] = { |
307 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ | 347 | /* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */ |
@@ -415,6 +455,7 @@ static const u8 sn_sp80708[0x1c] = { | |||
415 | 455 | ||
416 | /* sequence specific to the sensors - !! index = SENSOR_xxx */ | 456 | /* sequence specific to the sensors - !! index = SENSOR_xxx */ |
417 | static const u8 *sn_tb[] = { | 457 | static const u8 *sn_tb[] = { |
458 | sn_adcm1700, | ||
418 | sn_hv7131, | 459 | sn_hv7131, |
419 | sn_mi0360, | 460 | sn_mi0360, |
420 | sn_mo4000, | 461 | sn_mo4000, |
@@ -432,6 +473,11 @@ static const u8 gamma_def[17] = { | |||
432 | 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99, | 473 | 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99, |
433 | 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff | 474 | 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff |
434 | }; | 475 | }; |
476 | /* gamma for sensor ADCM1700 */ | ||
477 | static const u8 gamma_spec_0[17] = { | ||
478 | 0x0f, 0x39, 0x5a, 0x74, 0x86, 0x95, 0xa6, 0xb4, | ||
479 | 0xbd, 0xc4, 0xcc, 0xd4, 0xd5, 0xde, 0xe4, 0xed, 0xf5 | ||
480 | }; | ||
435 | /* gamma for sensors HV7131R and MT9V111 */ | 481 | /* gamma for sensors HV7131R and MT9V111 */ |
436 | static const u8 gamma_spec_1[17] = { | 482 | static const u8 gamma_spec_1[17] = { |
437 | 0x08, 0x3a, 0x52, 0x65, 0x75, 0x83, 0x91, 0x9d, | 483 | 0x08, 0x3a, 0x52, 0x65, 0x75, 0x83, 0x91, 0x9d, |
@@ -450,6 +496,42 @@ static const u8 reg84[] = { | |||
450 | 0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f, /* VR VG VB */ | 496 | 0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f, /* VR VG VB */ |
451 | 0x00, 0x00, 0x00 /* YUV offsets */ | 497 | 0x00, 0x00, 0x00 /* YUV offsets */ |
452 | }; | 498 | }; |
499 | static const u8 adcm1700_sensor_init[][8] = { | ||
500 | {0xa0, 0x51, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
501 | {0xb0, 0x51, 0x04, 0x08, 0x00, 0x00, 0x00, 0x10}, /* reset */ | ||
502 | {0xdd, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, | ||
503 | {0xb0, 0x51, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
504 | {0xdd, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, | ||
505 | {0xb0, 0x51, 0x0c, 0xe0, 0x2e, 0x00, 0x00, 0x10}, | ||
506 | {0xb0, 0x51, 0x10, 0x02, 0x02, 0x00, 0x00, 0x10}, | ||
507 | {0xb0, 0x51, 0x14, 0x0e, 0x0e, 0x00, 0x00, 0x10}, | ||
508 | {0xb0, 0x51, 0x1c, 0x00, 0x80, 0x00, 0x00, 0x10}, | ||
509 | {0xb0, 0x51, 0x20, 0x01, 0x00, 0x00, 0x00, 0x10}, | ||
510 | {0xdd, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, | ||
511 | {0xb0, 0x51, 0x04, 0x04, 0x00, 0x00, 0x00, 0x10}, | ||
512 | {0xdd, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, | ||
513 | {0xb0, 0x51, 0x04, 0x01, 0x00, 0x00, 0x00, 0x10}, | ||
514 | {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10}, | ||
515 | {0xb0, 0x51, 0x14, 0x01, 0x00, 0x00, 0x00, 0x10}, | ||
516 | {0xb0, 0x51, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10}, | ||
517 | {} | ||
518 | }; | ||
519 | static const u8 adcm1700_sensor_param1[][8] = { | ||
520 | {0xb0, 0x51, 0x26, 0xf9, 0x01, 0x00, 0x00, 0x10}, /* exposure? */ | ||
521 | {0xd0, 0x51, 0x1e, 0x8e, 0x8e, 0x8e, 0x8e, 0x10}, | ||
522 | |||
523 | {0xa0, 0x51, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x10}, | ||
524 | {0xb0, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10}, | ||
525 | {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10}, | ||
526 | {0xb0, 0x51, 0x32, 0x00, 0x72, 0x00, 0x00, 0x10}, | ||
527 | {0xd0, 0x51, 0x1e, 0xbe, 0xd7, 0xe8, 0xbe, 0x10}, /* exposure? */ | ||
528 | |||
529 | {0xa0, 0x51, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x10}, | ||
530 | {0xb0, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10}, | ||
531 | {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10}, | ||
532 | {0xb0, 0x51, 0x32, 0x00, 0xa2, 0x00, 0x00, 0x10}, | ||
533 | {} | ||
534 | }; | ||
453 | static const u8 hv7131r_sensor_init[][8] = { | 535 | static const u8 hv7131r_sensor_init[][8] = { |
454 | {0xc1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10}, | 536 | {0xc1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10}, |
455 | {0xb1, 0x11, 0x34, 0x17, 0x7f, 0x00, 0x00, 0x10}, | 537 | {0xb1, 0x11, 0x34, 0x17, 0x7f, 0x00, 0x00, 0x10}, |
@@ -986,17 +1068,18 @@ static const u8 sp80708_sensor_param1[][8] = { | |||
986 | {} | 1068 | {} |
987 | }; | 1069 | }; |
988 | 1070 | ||
989 | static const u8 (*sensor_init[10])[8] = { | 1071 | static const u8 (*sensor_init[11])[8] = { |
990 | hv7131r_sensor_init, /* HV7131R 0 */ | 1072 | adcm1700_sensor_init, /* ADCM1700 0 */ |
991 | mi0360_sensor_init, /* MI0360 1 */ | 1073 | hv7131r_sensor_init, /* HV7131R 1 */ |
992 | mo4000_sensor_init, /* MO4000 2 */ | 1074 | mi0360_sensor_init, /* MI0360 2 */ |
993 | mt9v111_sensor_init, /* MT9V111 3 */ | 1075 | mo4000_sensor_init, /* MO4000 3 */ |
994 | om6802_sensor_init, /* OM6802 4 */ | 1076 | mt9v111_sensor_init, /* MT9V111 4 */ |
995 | ov7630_sensor_init, /* OV7630 5 */ | 1077 | om6802_sensor_init, /* OM6802 5 */ |
996 | ov7648_sensor_init, /* OV7648 6 */ | 1078 | ov7630_sensor_init, /* OV7630 6 */ |
997 | ov7660_sensor_init, /* OV7660 7 */ | 1079 | ov7648_sensor_init, /* OV7648 7 */ |
998 | po1030_sensor_init, /* PO1030 8 */ | 1080 | ov7660_sensor_init, /* OV7660 8 */ |
999 | sp80708_sensor_init, /* SP80708 9 */ | 1081 | po1030_sensor_init, /* PO1030 9 */ |
1082 | sp80708_sensor_init, /* SP80708 10 */ | ||
1000 | }; | 1083 | }; |
1001 | 1084 | ||
1002 | /* read <len> bytes to gspca_dev->usb_buf */ | 1085 | /* read <len> bytes to gspca_dev->usb_buf */ |
@@ -1064,6 +1147,7 @@ static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) | |||
1064 | 1147 | ||
1065 | PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val); | 1148 | PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val); |
1066 | switch (sd->sensor) { | 1149 | switch (sd->sensor) { |
1150 | case SENSOR_ADCM1700: | ||
1067 | case SENSOR_OM6802: /* i2c command = a0 (100 kHz) */ | 1151 | case SENSOR_OM6802: /* i2c command = a0 (100 kHz) */ |
1068 | gspca_dev->usb_buf[0] = 0x80 | (2 << 4); | 1152 | gspca_dev->usb_buf[0] = 0x80 | (2 << 4); |
1069 | break; | 1153 | break; |
@@ -1110,6 +1194,7 @@ static void i2c_r(struct gspca_dev *gspca_dev, u8 reg, int len) | |||
1110 | u8 mode[8]; | 1194 | u8 mode[8]; |
1111 | 1195 | ||
1112 | switch (sd->sensor) { | 1196 | switch (sd->sensor) { |
1197 | case SENSOR_ADCM1700: | ||
1113 | case SENSOR_OM6802: /* i2c command = 90 (100 kHz) */ | 1198 | case SENSOR_OM6802: /* i2c command = 90 (100 kHz) */ |
1114 | mode[0] = 0x80 | 0x10; | 1199 | mode[0] = 0x80 | 0x10; |
1115 | break; | 1200 | break; |
@@ -1260,7 +1345,8 @@ static void bridge_init(struct gspca_dev *gspca_dev, | |||
1260 | {0x00, 0x40, 0x38, 0x30, 0x00, 0x20}; | 1345 | {0x00, 0x40, 0x38, 0x30, 0x00, 0x20}; |
1261 | static const u8 regd4[] = {0x60, 0x00, 0x00}; | 1346 | static const u8 regd4[] = {0x60, 0x00, 0x00}; |
1262 | 1347 | ||
1263 | reg_w1(gspca_dev, 0xf1, 0x00); | 1348 | /* sensor clock already enabled in sd_init */ |
1349 | /* reg_w1(gspca_dev, 0xf1, 0x00); */ | ||
1264 | reg_w1(gspca_dev, 0x01, sn9c1xx[1]); | 1350 | reg_w1(gspca_dev, 0x01, sn9c1xx[1]); |
1265 | 1351 | ||
1266 | /* configure gpio */ | 1352 | /* configure gpio */ |
@@ -1284,6 +1370,12 @@ static void bridge_init(struct gspca_dev *gspca_dev, | |||
1284 | reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f); | 1370 | reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f); |
1285 | 1371 | ||
1286 | switch (sd->sensor) { | 1372 | switch (sd->sensor) { |
1373 | case SENSOR_ADCM1700: | ||
1374 | reg_w1(gspca_dev, 0x01, 0x43); | ||
1375 | reg_w1(gspca_dev, 0x17, 0x62); | ||
1376 | reg_w1(gspca_dev, 0x01, 0x42); | ||
1377 | reg_w1(gspca_dev, 0x01, 0x42); | ||
1378 | break; | ||
1287 | case SENSOR_MT9V111: | 1379 | case SENSOR_MT9V111: |
1288 | reg_w1(gspca_dev, 0x01, 0x61); | 1380 | reg_w1(gspca_dev, 0x01, 0x61); |
1289 | reg_w1(gspca_dev, 0x17, 0x61); | 1381 | reg_w1(gspca_dev, 0x17, 0x61); |
@@ -1357,14 +1449,19 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1357 | struct sd *sd = (struct sd *) gspca_dev; | 1449 | struct sd *sd = (struct sd *) gspca_dev; |
1358 | struct cam *cam; | 1450 | struct cam *cam; |
1359 | 1451 | ||
1360 | cam = &gspca_dev->cam; | ||
1361 | cam->cam_mode = vga_mode; | ||
1362 | cam->nmodes = ARRAY_SIZE(vga_mode); | ||
1363 | cam->npkt = 24; /* 24 packets per ISOC message */ | ||
1364 | |||
1365 | sd->bridge = id->driver_info >> 16; | 1452 | sd->bridge = id->driver_info >> 16; |
1366 | sd->sensor = id->driver_info; | 1453 | sd->sensor = id->driver_info; |
1367 | 1454 | ||
1455 | cam = &gspca_dev->cam; | ||
1456 | if (sd->sensor == SENSOR_ADCM1700) { | ||
1457 | cam->cam_mode = cif_mode; | ||
1458 | cam->nmodes = ARRAY_SIZE(cif_mode); | ||
1459 | } else { | ||
1460 | cam->cam_mode = vga_mode; | ||
1461 | cam->nmodes = ARRAY_SIZE(vga_mode); | ||
1462 | } | ||
1463 | cam->npkt = 24; /* 24 packets per ISOC message */ | ||
1464 | |||
1368 | sd->brightness = BRIGHTNESS_DEF; | 1465 | sd->brightness = BRIGHTNESS_DEF; |
1369 | sd->contrast = CONTRAST_DEF; | 1466 | sd->contrast = CONTRAST_DEF; |
1370 | sd->colors = COLOR_DEF; | 1467 | sd->colors = COLOR_DEF; |
@@ -1374,6 +1471,14 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1374 | sd->autogain = AUTOGAIN_DEF; | 1471 | sd->autogain = AUTOGAIN_DEF; |
1375 | sd->ag_cnt = -1; | 1472 | sd->ag_cnt = -1; |
1376 | sd->vflip = VFLIP_DEF; | 1473 | sd->vflip = VFLIP_DEF; |
1474 | switch (sd->sensor) { | ||
1475 | case SENSOR_OM6802: | ||
1476 | sd->sharpness = 0x10; | ||
1477 | break; | ||
1478 | default: | ||
1479 | sd->sharpness = SHARPNESS_DEF; | ||
1480 | break; | ||
1481 | } | ||
1377 | sd->infrared = INFRARED_DEF; | 1482 | sd->infrared = INFRARED_DEF; |
1378 | sd->freq = FREQ_DEF; | 1483 | sd->freq = FREQ_DEF; |
1379 | sd->quality = QUALITY_DEF; | 1484 | sd->quality = QUALITY_DEF; |
@@ -1433,7 +1538,9 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1433 | break; | 1538 | break; |
1434 | } | 1539 | } |
1435 | 1540 | ||
1436 | reg_w1(gspca_dev, 0xf1, 0x01); | 1541 | /* Note we do not disable the sensor clock here (power saving mode), |
1542 | as that also disables the button on the cam. */ | ||
1543 | reg_w1(gspca_dev, 0xf1, 0x00); | ||
1437 | 1544 | ||
1438 | /* set the i2c address */ | 1545 | /* set the i2c address */ |
1439 | sn9c1xx = sn_tb[sd->sensor]; | 1546 | sn9c1xx = sn_tb[sd->sensor]; |
@@ -1543,6 +1650,10 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
1543 | 1650 | ||
1544 | k2 = ((int) sd->brightness - 0x8000) >> 10; | 1651 | k2 = ((int) sd->brightness - 0x8000) >> 10; |
1545 | switch (sd->sensor) { | 1652 | switch (sd->sensor) { |
1653 | case SENSOR_ADCM1700: | ||
1654 | if (k2 > 0x1f) | ||
1655 | k2 = 0; /* only positive Y offset */ | ||
1656 | break; | ||
1546 | case SENSOR_HV7131R: | 1657 | case SENSOR_HV7131R: |
1547 | expo = sd->brightness << 4; | 1658 | expo = sd->brightness << 4; |
1548 | if (expo > 0x002dc6c0) | 1659 | if (expo > 0x002dc6c0) |
@@ -1625,6 +1736,9 @@ static void setgamma(struct gspca_dev *gspca_dev) | |||
1625 | }; | 1736 | }; |
1626 | 1737 | ||
1627 | switch (sd->sensor) { | 1738 | switch (sd->sensor) { |
1739 | case SENSOR_ADCM1700: | ||
1740 | gamma_base = gamma_spec_0; | ||
1741 | break; | ||
1628 | case SENSOR_HV7131R: | 1742 | case SENSOR_HV7131R: |
1629 | case SENSOR_MT9V111: | 1743 | case SENSOR_MT9V111: |
1630 | gamma_base = gamma_spec_1; | 1744 | gamma_base = gamma_spec_1; |
@@ -1670,23 +1784,39 @@ static void setautogain(struct gspca_dev *gspca_dev) | |||
1670 | sd->ag_cnt = -1; | 1784 | sd->ag_cnt = -1; |
1671 | } | 1785 | } |
1672 | 1786 | ||
1673 | /* ov7630/ov7648 only */ | 1787 | /* hv7131r/ov7630/ov7648 only */ |
1674 | static void setvflip(struct sd *sd) | 1788 | static void setvflip(struct sd *sd) |
1675 | { | 1789 | { |
1676 | u8 comn; | 1790 | u8 comn; |
1677 | 1791 | ||
1678 | if (sd->gspca_dev.ctrl_dis & (1 << VFLIP_IDX)) | 1792 | if (sd->gspca_dev.ctrl_dis & (1 << VFLIP_IDX)) |
1679 | return; | 1793 | return; |
1680 | if (sd->sensor == SENSOR_OV7630) { | 1794 | switch (sd->sensor) { |
1795 | case SENSOR_HV7131R: | ||
1796 | comn = 0x18; /* clkdiv = 1, ablcen = 1 */ | ||
1797 | if (sd->vflip) | ||
1798 | comn |= 0x01; | ||
1799 | i2c_w1(&sd->gspca_dev, 0x01, comn); /* sctra */ | ||
1800 | break; | ||
1801 | case SENSOR_OV7630: | ||
1681 | comn = 0x02; | 1802 | comn = 0x02; |
1682 | if (!sd->vflip) | 1803 | if (!sd->vflip) |
1683 | comn |= 0x80; | 1804 | comn |= 0x80; |
1684 | } else { | 1805 | i2c_w1(&sd->gspca_dev, 0x75, comn); |
1806 | break; | ||
1807 | default: | ||
1808 | /* case SENSOR_OV7648: */ | ||
1685 | comn = 0x06; | 1809 | comn = 0x06; |
1686 | if (sd->vflip) | 1810 | if (sd->vflip) |
1687 | comn |= 0x80; | 1811 | comn |= 0x80; |
1812 | i2c_w1(&sd->gspca_dev, 0x75, comn); | ||
1813 | break; | ||
1688 | } | 1814 | } |
1689 | i2c_w1(&sd->gspca_dev, 0x75, comn); | 1815 | } |
1816 | |||
1817 | static void setsharpness(struct sd *sd) | ||
1818 | { | ||
1819 | reg_w1(&sd->gspca_dev, 0x99, sd->sharpness); | ||
1690 | } | 1820 | } |
1691 | 1821 | ||
1692 | static void setinfrared(struct sd *sd) | 1822 | static void setinfrared(struct sd *sd) |
@@ -1804,6 +1934,8 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1804 | int mode; | 1934 | int mode; |
1805 | static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f }; | 1935 | static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f }; |
1806 | static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec }; | 1936 | static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec }; |
1937 | static const u8 CA_adcm1700[] = | ||
1938 | { 0x14, 0xec, 0x0a, 0xf6 }; | ||
1807 | static const u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */ | 1939 | static const u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */ |
1808 | static const u8 CE_ov76xx[] = | 1940 | static const u8 CE_ov76xx[] = |
1809 | { 0x32, 0xdd, 0x32, 0xdd }; | 1941 | { 0x32, 0xdd, 0x32, 0xdd }; |
@@ -1824,6 +1956,9 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1824 | i2c_w_seq(gspca_dev, sensor_init[sd->sensor]); | 1956 | i2c_w_seq(gspca_dev, sensor_init[sd->sensor]); |
1825 | 1957 | ||
1826 | switch (sd->sensor) { | 1958 | switch (sd->sensor) { |
1959 | case SENSOR_ADCM1700: | ||
1960 | reg2 = 0x60; | ||
1961 | break; | ||
1827 | case SENSOR_OM6802: | 1962 | case SENSOR_OM6802: |
1828 | reg2 = 0x71; | 1963 | reg2 = 0x71; |
1829 | break; | 1964 | break; |
@@ -1842,17 +1977,28 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1842 | reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]); | 1977 | reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]); |
1843 | reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]); | 1978 | reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]); |
1844 | reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]); | 1979 | reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]); |
1845 | reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */ | 1980 | if (sd->sensor == SENSOR_ADCM1700) { |
1846 | reg_w1(gspca_dev, 0xd3, 0x50); | 1981 | reg_w1(gspca_dev, 0xd2, 0x3a); /* AE_H_SIZE = 116 */ |
1982 | reg_w1(gspca_dev, 0xd3, 0x30); /* AE_V_SIZE = 96 */ | ||
1983 | } else { | ||
1984 | reg_w1(gspca_dev, 0xd2, 0x6a); /* AE_H_SIZE = 212 */ | ||
1985 | reg_w1(gspca_dev, 0xd3, 0x50); /* AE_V_SIZE = 160 */ | ||
1986 | } | ||
1847 | reg_w1(gspca_dev, 0xc6, 0x00); | 1987 | reg_w1(gspca_dev, 0xc6, 0x00); |
1848 | reg_w1(gspca_dev, 0xc7, 0x00); | 1988 | reg_w1(gspca_dev, 0xc7, 0x00); |
1849 | reg_w1(gspca_dev, 0xc8, 0x50); | 1989 | if (sd->sensor == SENSOR_ADCM1700) { |
1850 | reg_w1(gspca_dev, 0xc9, 0x3c); | 1990 | reg_w1(gspca_dev, 0xc8, 0x2c); /* AW_H_STOP = 352 */ |
1991 | reg_w1(gspca_dev, 0xc9, 0x24); /* AW_V_STOP = 288 */ | ||
1992 | } else { | ||
1993 | reg_w1(gspca_dev, 0xc8, 0x50); /* AW_H_STOP = 640 */ | ||
1994 | reg_w1(gspca_dev, 0xc9, 0x3c); /* AW_V_STOP = 480 */ | ||
1995 | } | ||
1851 | reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]); | 1996 | reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]); |
1852 | switch (sd->sensor) { | 1997 | switch (sd->sensor) { |
1853 | case SENSOR_MT9V111: | 1998 | case SENSOR_MT9V111: |
1854 | reg17 = 0xe0; | 1999 | reg17 = 0xe0; |
1855 | break; | 2000 | break; |
2001 | case SENSOR_ADCM1700: | ||
1856 | case SENSOR_OV7630: | 2002 | case SENSOR_OV7630: |
1857 | reg17 = 0xe2; | 2003 | reg17 = 0xe2; |
1858 | break; | 2004 | break; |
@@ -1870,44 +2016,39 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1870 | break; | 2016 | break; |
1871 | } | 2017 | } |
1872 | reg_w1(gspca_dev, 0x17, reg17); | 2018 | reg_w1(gspca_dev, 0x17, reg17); |
1873 | /* set reg1 was here */ | 2019 | |
1874 | reg_w1(gspca_dev, 0x05, sn9c1xx[5]); /* red */ | 2020 | reg_w1(gspca_dev, 0x05, 0x00); /* red */ |
1875 | reg_w1(gspca_dev, 0x07, sn9c1xx[7]); /* green */ | 2021 | reg_w1(gspca_dev, 0x07, 0x00); /* green */ |
1876 | reg_w1(gspca_dev, 0x06, sn9c1xx[6]); /* blue */ | 2022 | reg_w1(gspca_dev, 0x06, 0x00); /* blue */ |
1877 | reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]); | 2023 | reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]); |
1878 | 2024 | ||
1879 | setgamma(gspca_dev); | 2025 | setgamma(gspca_dev); |
1880 | 2026 | ||
2027 | /*fixme: 8 times with all zeroes and 1 or 2 times with normal values */ | ||
1881 | for (i = 0; i < 8; i++) | 2028 | for (i = 0; i < 8; i++) |
1882 | reg_w(gspca_dev, 0x84, reg84, sizeof reg84); | 2029 | reg_w(gspca_dev, 0x84, reg84, sizeof reg84); |
1883 | switch (sd->sensor) { | 2030 | switch (sd->sensor) { |
2031 | case SENSOR_ADCM1700: | ||
2032 | case SENSOR_OV7660: | ||
2033 | case SENSOR_SP80708: | ||
2034 | reg_w1(gspca_dev, 0x9a, 0x05); | ||
2035 | break; | ||
1884 | case SENSOR_MT9V111: | 2036 | case SENSOR_MT9V111: |
1885 | reg_w1(gspca_dev, 0x9a, 0x07); | 2037 | reg_w1(gspca_dev, 0x9a, 0x07); |
1886 | reg_w1(gspca_dev, 0x99, 0x59); | ||
1887 | break; | ||
1888 | case SENSOR_OM6802: | ||
1889 | reg_w1(gspca_dev, 0x9a, 0x08); | ||
1890 | reg_w1(gspca_dev, 0x99, 0x10); | ||
1891 | break; | 2038 | break; |
1892 | case SENSOR_OV7648: | 2039 | case SENSOR_OV7648: |
1893 | reg_w1(gspca_dev, 0x9a, 0x0a); | 2040 | reg_w1(gspca_dev, 0x9a, 0x0a); |
1894 | reg_w1(gspca_dev, 0x99, 0x60); | ||
1895 | break; | ||
1896 | case SENSOR_OV7660: | ||
1897 | case SENSOR_SP80708: | ||
1898 | reg_w1(gspca_dev, 0x9a, 0x05); | ||
1899 | reg_w1(gspca_dev, 0x99, 0x59); | ||
1900 | break; | 2041 | break; |
1901 | default: | 2042 | default: |
1902 | reg_w1(gspca_dev, 0x9a, 0x08); | 2043 | reg_w1(gspca_dev, 0x9a, 0x08); |
1903 | reg_w1(gspca_dev, 0x99, 0x59); | ||
1904 | break; | 2044 | break; |
1905 | } | 2045 | } |
2046 | setsharpness(sd); | ||
1906 | 2047 | ||
1907 | reg_w(gspca_dev, 0x84, reg84, sizeof reg84); | 2048 | reg_w(gspca_dev, 0x84, reg84, sizeof reg84); |
1908 | reg_w1(gspca_dev, 0x05, sn9c1xx[5]); /* red */ | 2049 | reg_w1(gspca_dev, 0x05, 0x20); /* red */ |
1909 | reg_w1(gspca_dev, 0x07, sn9c1xx[7]); /* green */ | 2050 | reg_w1(gspca_dev, 0x07, 0x20); /* green */ |
1910 | reg_w1(gspca_dev, 0x06, sn9c1xx[6]); /* blue */ | 2051 | reg_w1(gspca_dev, 0x06, 0x20); /* blue */ |
1911 | 2052 | ||
1912 | init = NULL; | 2053 | init = NULL; |
1913 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; | 2054 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; |
@@ -1917,6 +2058,11 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1917 | reg1 = 0x06; /* 640x480: clk 24Mhz, video trf enable */ | 2058 | reg1 = 0x06; /* 640x480: clk 24Mhz, video trf enable */ |
1918 | reg17 = 0x61; /* 0x:20: enable sensor clock */ | 2059 | reg17 = 0x61; /* 0x:20: enable sensor clock */ |
1919 | switch (sd->sensor) { | 2060 | switch (sd->sensor) { |
2061 | case SENSOR_ADCM1700: | ||
2062 | init = adcm1700_sensor_param1; | ||
2063 | reg1 = 0x46; | ||
2064 | reg17 = 0xe2; | ||
2065 | break; | ||
1920 | case SENSOR_MO4000: | 2066 | case SENSOR_MO4000: |
1921 | if (mode) { | 2067 | if (mode) { |
1922 | /* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */ | 2068 | /* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */ |
@@ -1940,7 +2086,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1940 | reg17 = 0x64; /* 640 MCKSIZE */ | 2086 | reg17 = 0x64; /* 640 MCKSIZE */ |
1941 | break; | 2087 | break; |
1942 | case SENSOR_OV7630: | 2088 | case SENSOR_OV7630: |
1943 | setvflip(sd); | ||
1944 | reg17 = 0xe2; | 2089 | reg17 = 0xe2; |
1945 | reg1 = 0x44; | 2090 | reg1 = 0x44; |
1946 | break; | 2091 | break; |
@@ -1986,8 +2131,12 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1986 | } | 2131 | } |
1987 | 2132 | ||
1988 | reg_w(gspca_dev, 0xc0, C0, 6); | 2133 | reg_w(gspca_dev, 0xc0, C0, 6); |
1989 | reg_w(gspca_dev, 0xca, CA, 4); | 2134 | if (sd->sensor == SENSOR_ADCM1700) |
2135 | reg_w(gspca_dev, 0xca, CA_adcm1700, 4); | ||
2136 | else | ||
2137 | reg_w(gspca_dev, 0xca, CA, 4); | ||
1990 | switch (sd->sensor) { | 2138 | switch (sd->sensor) { |
2139 | case SENSOR_ADCM1700: | ||
1991 | case SENSOR_OV7630: | 2140 | case SENSOR_OV7630: |
1992 | case SENSOR_OV7648: | 2141 | case SENSOR_OV7648: |
1993 | case SENSOR_OV7660: | 2142 | case SENSOR_OV7660: |
@@ -2008,11 +2157,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2008 | reg_w1(gspca_dev, 0x17, reg17); | 2157 | reg_w1(gspca_dev, 0x17, reg17); |
2009 | reg_w1(gspca_dev, 0x01, reg1); | 2158 | reg_w1(gspca_dev, 0x01, reg1); |
2010 | 2159 | ||
2011 | switch (sd->sensor) { | 2160 | setvflip(sd); |
2012 | case SENSOR_OV7630: | ||
2013 | setvflip(sd); | ||
2014 | break; | ||
2015 | } | ||
2016 | setbrightness(gspca_dev); | 2161 | setbrightness(gspca_dev); |
2017 | setcontrast(gspca_dev); | 2162 | setcontrast(gspca_dev); |
2018 | setautogain(gspca_dev); | 2163 | setautogain(gspca_dev); |
@@ -2056,7 +2201,8 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
2056 | reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]); | 2201 | reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]); |
2057 | reg_w1(gspca_dev, 0x01, sn9c1xx[1]); | 2202 | reg_w1(gspca_dev, 0x01, sn9c1xx[1]); |
2058 | reg_w1(gspca_dev, 0x01, data); | 2203 | reg_w1(gspca_dev, 0x01, data); |
2059 | reg_w1(gspca_dev, 0xf1, 0x00); | 2204 | /* Don't disable sensor clock as that disables the button on the cam */ |
2205 | /* reg_w1(gspca_dev, 0xf1, 0x01); */ | ||
2060 | } | 2206 | } |
2061 | 2207 | ||
2062 | static void sd_stop0(struct gspca_dev *gspca_dev) | 2208 | static void sd_stop0(struct gspca_dev *gspca_dev) |
@@ -2288,6 +2434,24 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) | |||
2288 | return 0; | 2434 | return 0; |
2289 | } | 2435 | } |
2290 | 2436 | ||
2437 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val) | ||
2438 | { | ||
2439 | struct sd *sd = (struct sd *) gspca_dev; | ||
2440 | |||
2441 | sd->sharpness = val; | ||
2442 | if (gspca_dev->streaming) | ||
2443 | setsharpness(sd); | ||
2444 | return 0; | ||
2445 | } | ||
2446 | |||
2447 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val) | ||
2448 | { | ||
2449 | struct sd *sd = (struct sd *) gspca_dev; | ||
2450 | |||
2451 | *val = sd->sharpness; | ||
2452 | return 0; | ||
2453 | } | ||
2454 | |||
2291 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) | 2455 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val) |
2292 | { | 2456 | { |
2293 | struct sd *sd = (struct sd *) gspca_dev; | 2457 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -2391,6 +2555,25 @@ static int sd_querymenu(struct gspca_dev *gspca_dev, | |||
2391 | return -EINVAL; | 2555 | return -EINVAL; |
2392 | } | 2556 | } |
2393 | 2557 | ||
2558 | #ifdef CONFIG_INPUT | ||
2559 | static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, | ||
2560 | u8 *data, /* interrupt packet data */ | ||
2561 | int len) /* interrupt packet length */ | ||
2562 | { | ||
2563 | int ret = -EINVAL; | ||
2564 | |||
2565 | if (len == 1 && data[0] == 1) { | ||
2566 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); | ||
2567 | input_sync(gspca_dev->input_dev); | ||
2568 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); | ||
2569 | input_sync(gspca_dev->input_dev); | ||
2570 | ret = 0; | ||
2571 | } | ||
2572 | |||
2573 | return ret; | ||
2574 | } | ||
2575 | #endif | ||
2576 | |||
2394 | /* sub-driver description */ | 2577 | /* sub-driver description */ |
2395 | static const struct sd_desc sd_desc = { | 2578 | static const struct sd_desc sd_desc = { |
2396 | .name = MODULE_NAME, | 2579 | .name = MODULE_NAME, |
@@ -2406,6 +2589,9 @@ static const struct sd_desc sd_desc = { | |||
2406 | .get_jcomp = sd_get_jcomp, | 2589 | .get_jcomp = sd_get_jcomp, |
2407 | .set_jcomp = sd_set_jcomp, | 2590 | .set_jcomp = sd_set_jcomp, |
2408 | .querymenu = sd_querymenu, | 2591 | .querymenu = sd_querymenu, |
2592 | #ifdef CONFIG_INPUT | ||
2593 | .int_pkt_scan = sd_int_pkt_scan, | ||
2594 | #endif | ||
2409 | }; | 2595 | }; |
2410 | 2596 | ||
2411 | /* -- module initialisation -- */ | 2597 | /* -- module initialisation -- */ |
@@ -2472,6 +2658,7 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
2472 | /* {USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)}, *sn9c120b*/ | 2658 | /* {USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)}, *sn9c120b*/ |
2473 | {USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)}, /*sn9c120b*/ | 2659 | {USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)}, /*sn9c120b*/ |
2474 | {USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)}, /*sn9c120b*/ | 2660 | {USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)}, /*sn9c120b*/ |
2661 | {USB_DEVICE(0x0c45, 0x614a), BS(SN9C120, ADCM1700)}, /*sn9c120b*/ | ||
2475 | {} | 2662 | {} |
2476 | }; | 2663 | }; |
2477 | MODULE_DEVICE_TABLE(usb, device_table); | 2664 | MODULE_DEVICE_TABLE(usb, device_table); |
diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c index fe46868a87f2..b866c73c97db 100644 --- a/drivers/media/video/gspca/spca500.c +++ b/drivers/media/video/gspca/spca500.c | |||
@@ -68,7 +68,7 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | |||
68 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); | 68 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); |
69 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | 69 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); |
70 | 70 | ||
71 | static struct ctrl sd_ctrls[] = { | 71 | static const struct ctrl sd_ctrls[] = { |
72 | { | 72 | { |
73 | { | 73 | { |
74 | .id = V4L2_CID_BRIGHTNESS, | 74 | .id = V4L2_CID_BRIGHTNESS, |
@@ -1047,7 +1047,7 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev, | |||
1047 | } | 1047 | } |
1048 | 1048 | ||
1049 | /* sub-driver description */ | 1049 | /* sub-driver description */ |
1050 | static struct sd_desc sd_desc = { | 1050 | static const struct sd_desc sd_desc = { |
1051 | .name = MODULE_NAME, | 1051 | .name = MODULE_NAME, |
1052 | .ctrls = sd_ctrls, | 1052 | .ctrls = sd_ctrls, |
1053 | .nctrls = ARRAY_SIZE(sd_ctrls), | 1053 | .nctrls = ARRAY_SIZE(sd_ctrls), |
diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c index 6761a3048a98..c99333933e32 100644 --- a/drivers/media/video/gspca/spca501.c +++ b/drivers/media/video/gspca/spca501.c | |||
@@ -59,7 +59,7 @@ static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val); | |||
59 | static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val); | 59 | static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val); |
60 | static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val); | 60 | static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val); |
61 | 61 | ||
62 | static struct ctrl sd_ctrls[] = { | 62 | static const struct ctrl sd_ctrls[] = { |
63 | #define MY_BRIGHTNESS 0 | 63 | #define MY_BRIGHTNESS 0 |
64 | { | 64 | { |
65 | { | 65 | { |
diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c index 0f9232ff1281..c576eed73abe 100644 --- a/drivers/media/video/gspca/spca505.c +++ b/drivers/media/video/gspca/spca505.c | |||
@@ -42,7 +42,7 @@ struct sd { | |||
42 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | 42 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); |
43 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | 43 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); |
44 | 44 | ||
45 | static struct ctrl sd_ctrls[] = { | 45 | static const struct ctrl sd_ctrls[] = { |
46 | { | 46 | { |
47 | { | 47 | { |
48 | .id = V4L2_CID_BRIGHTNESS, | 48 | .id = V4L2_CID_BRIGHTNESS, |
diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c index 39257e4e074f..89fec4c500af 100644 --- a/drivers/media/video/gspca/spca506.c +++ b/drivers/media/video/gspca/spca506.c | |||
@@ -51,7 +51,7 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | |||
51 | static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val); | 51 | static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val); |
52 | static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val); | 52 | static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val); |
53 | 53 | ||
54 | static struct ctrl sd_ctrls[] = { | 54 | static const struct ctrl sd_ctrls[] = { |
55 | #define SD_BRIGHTNESS 0 | 55 | #define SD_BRIGHTNESS 0 |
56 | { | 56 | { |
57 | { | 57 | { |
@@ -673,7 +673,7 @@ static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val) | |||
673 | } | 673 | } |
674 | 674 | ||
675 | /* sub-driver description */ | 675 | /* sub-driver description */ |
676 | static struct sd_desc sd_desc = { | 676 | static const struct sd_desc sd_desc = { |
677 | .name = MODULE_NAME, | 677 | .name = MODULE_NAME, |
678 | .ctrls = sd_ctrls, | 678 | .ctrls = sd_ctrls, |
679 | .nctrls = ARRAY_SIZE(sd_ctrls), | 679 | .nctrls = ARRAY_SIZE(sd_ctrls), |
diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c index 4d8e6cf75d55..15b2eef8a3f6 100644 --- a/drivers/media/video/gspca/spca508.c +++ b/drivers/media/video/gspca/spca508.c | |||
@@ -45,7 +45,7 @@ struct sd { | |||
45 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | 45 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); |
46 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | 46 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); |
47 | 47 | ||
48 | static struct ctrl sd_ctrls[] = { | 48 | static const struct ctrl sd_ctrls[] = { |
49 | { | 49 | { |
50 | { | 50 | { |
51 | .id = V4L2_CID_BRIGHTNESS, | 51 | .id = V4L2_CID_BRIGHTNESS, |
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index 58c2f0039af1..dc7f2b0fbc79 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c | |||
@@ -922,7 +922,7 @@ static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) | |||
922 | } | 922 | } |
923 | 923 | ||
924 | /* control tables */ | 924 | /* control tables */ |
925 | static struct ctrl sd_ctrls_12a[] = { | 925 | static const struct ctrl sd_ctrls_12a[] = { |
926 | { | 926 | { |
927 | { | 927 | { |
928 | .id = V4L2_CID_HUE, | 928 | .id = V4L2_CID_HUE, |
@@ -964,7 +964,7 @@ static struct ctrl sd_ctrls_12a[] = { | |||
964 | }, | 964 | }, |
965 | }; | 965 | }; |
966 | 966 | ||
967 | static struct ctrl sd_ctrls_72a[] = { | 967 | static const struct ctrl sd_ctrls_72a[] = { |
968 | { | 968 | { |
969 | { | 969 | { |
970 | .id = V4L2_CID_HUE, | 970 | .id = V4L2_CID_HUE, |
diff --git a/drivers/media/video/gspca/sq905c.c b/drivers/media/video/gspca/sq905c.c index d70b156872d6..e64662052992 100644 --- a/drivers/media/video/gspca/sq905c.c +++ b/drivers/media/video/gspca/sq905c.c | |||
@@ -47,6 +47,7 @@ MODULE_LICENSE("GPL"); | |||
47 | 47 | ||
48 | /* Commands. These go in the "value" slot. */ | 48 | /* Commands. These go in the "value" slot. */ |
49 | #define SQ905C_CLEAR 0xa0 /* clear everything */ | 49 | #define SQ905C_CLEAR 0xa0 /* clear everything */ |
50 | #define SQ905C_GET_ID 0x14f4 /* Read version number */ | ||
50 | #define SQ905C_CAPTURE_LOW 0xa040 /* Starts capture at 160x120 */ | 51 | #define SQ905C_CAPTURE_LOW 0xa040 /* Starts capture at 160x120 */ |
51 | #define SQ905C_CAPTURE_MED 0x1440 /* Starts capture at 320x240 */ | 52 | #define SQ905C_CAPTURE_MED 0x1440 /* Starts capture at 320x240 */ |
52 | #define SQ905C_CAPTURE_HI 0x2840 /* Starts capture at 320x240 */ | 53 | #define SQ905C_CAPTURE_HI 0x2840 /* Starts capture at 320x240 */ |
@@ -101,6 +102,26 @@ static int sq905c_command(struct gspca_dev *gspca_dev, u16 command, u16 index) | |||
101 | return 0; | 102 | return 0; |
102 | } | 103 | } |
103 | 104 | ||
105 | static int sq905c_read(struct gspca_dev *gspca_dev, u16 command, u16 index, | ||
106 | int size) | ||
107 | { | ||
108 | int ret; | ||
109 | |||
110 | ret = usb_control_msg(gspca_dev->dev, | ||
111 | usb_rcvctrlpipe(gspca_dev->dev, 0), | ||
112 | USB_REQ_SYNCH_FRAME, /* request */ | ||
113 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
114 | command, index, gspca_dev->usb_buf, size, | ||
115 | SQ905C_CMD_TIMEOUT); | ||
116 | if (ret < 0) { | ||
117 | PDEBUG(D_ERR, "%s: usb_control_msg failed (%d)", | ||
118 | __func__, ret); | ||
119 | return ret; | ||
120 | } | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
104 | /* This function is called as a workqueue function and runs whenever the camera | 125 | /* This function is called as a workqueue function and runs whenever the camera |
105 | * is streaming data. Because it is a workqueue function it is allowed to sleep | 126 | * is streaming data. Because it is a workqueue function it is allowed to sleep |
106 | * so we can use synchronous USB calls. To avoid possible collisions with other | 127 | * so we can use synchronous USB calls. To avoid possible collisions with other |
@@ -183,13 +204,34 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
183 | { | 204 | { |
184 | struct cam *cam = &gspca_dev->cam; | 205 | struct cam *cam = &gspca_dev->cam; |
185 | struct sd *dev = (struct sd *) gspca_dev; | 206 | struct sd *dev = (struct sd *) gspca_dev; |
207 | int ret; | ||
186 | 208 | ||
187 | PDEBUG(D_PROBE, | 209 | PDEBUG(D_PROBE, |
188 | "SQ9050 camera detected" | 210 | "SQ9050 camera detected" |
189 | " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); | 211 | " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); |
212 | |||
213 | ret = sq905c_command(gspca_dev, SQ905C_GET_ID, 0); | ||
214 | if (ret < 0) { | ||
215 | PDEBUG(D_ERR, "Get version command failed"); | ||
216 | return ret; | ||
217 | } | ||
218 | |||
219 | ret = sq905c_read(gspca_dev, 0xf5, 0, 20); | ||
220 | if (ret < 0) { | ||
221 | PDEBUG(D_ERR, "Reading version command failed"); | ||
222 | return ret; | ||
223 | } | ||
224 | /* Note we leave out the usb id and the manufacturing date */ | ||
225 | PDEBUG(D_PROBE, | ||
226 | "SQ9050 ID string: %02x - %02x %02x %02x %02x %02x %02x", | ||
227 | gspca_dev->usb_buf[3], | ||
228 | gspca_dev->usb_buf[14], gspca_dev->usb_buf[15], | ||
229 | gspca_dev->usb_buf[16], gspca_dev->usb_buf[17], | ||
230 | gspca_dev->usb_buf[18], gspca_dev->usb_buf[19]); | ||
231 | |||
190 | cam->cam_mode = sq905c_mode; | 232 | cam->cam_mode = sq905c_mode; |
191 | cam->nmodes = 2; | 233 | cam->nmodes = 2; |
192 | if (id->idProduct == 0x9050) | 234 | if (gspca_dev->usb_buf[15] == 0) |
193 | cam->nmodes = 1; | 235 | cam->nmodes = 1; |
194 | /* We don't use the buffer gspca allocates so make it small. */ | 236 | /* We don't use the buffer gspca allocates so make it small. */ |
195 | cam->bulk_size = 32; | 237 | cam->bulk_size = 32; |
@@ -258,6 +300,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
258 | static const __devinitdata struct usb_device_id device_table[] = { | 300 | static const __devinitdata struct usb_device_id device_table[] = { |
259 | {USB_DEVICE(0x2770, 0x905c)}, | 301 | {USB_DEVICE(0x2770, 0x905c)}, |
260 | {USB_DEVICE(0x2770, 0x9050)}, | 302 | {USB_DEVICE(0x2770, 0x9050)}, |
303 | {USB_DEVICE(0x2770, 0x9052)}, | ||
261 | {USB_DEVICE(0x2770, 0x913d)}, | 304 | {USB_DEVICE(0x2770, 0x913d)}, |
262 | {} | 305 | {} |
263 | }; | 306 | }; |
diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c index 2e2935532d99..0fb534210a2c 100644 --- a/drivers/media/video/gspca/stk014.c +++ b/drivers/media/video/gspca/stk014.c | |||
@@ -53,7 +53,7 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | |||
53 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | 53 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); |
54 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | 54 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); |
55 | 55 | ||
56 | static struct ctrl sd_ctrls[] = { | 56 | static const struct ctrl sd_ctrls[] = { |
57 | { | 57 | { |
58 | { | 58 | { |
59 | .id = V4L2_CID_BRIGHTNESS, | 59 | .id = V4L2_CID_BRIGHTNESS, |
diff --git a/drivers/media/video/gspca/stv0680.c b/drivers/media/video/gspca/stv0680.c index 2a69d7ccb50d..e50dd7693f74 100644 --- a/drivers/media/video/gspca/stv0680.c +++ b/drivers/media/video/gspca/stv0680.c | |||
@@ -45,7 +45,7 @@ struct sd { | |||
45 | }; | 45 | }; |
46 | 46 | ||
47 | /* V4L2 controls supported by the driver */ | 47 | /* V4L2 controls supported by the driver */ |
48 | static struct ctrl sd_ctrls[] = { | 48 | static const struct ctrl sd_ctrls[] = { |
49 | }; | 49 | }; |
50 | 50 | ||
51 | static int stv_sndctrl(struct gspca_dev *gspca_dev, int set, u8 req, u16 val, | 51 | static int stv_sndctrl(struct gspca_dev *gspca_dev, int set, u8 req, u16 val, |
@@ -53,24 +53,28 @@ static int stv_sndctrl(struct gspca_dev *gspca_dev, int set, u8 req, u16 val, | |||
53 | { | 53 | { |
54 | int ret = -1; | 54 | int ret = -1; |
55 | u8 req_type = 0; | 55 | u8 req_type = 0; |
56 | unsigned int pipe = 0; | ||
56 | 57 | ||
57 | switch (set) { | 58 | switch (set) { |
58 | case 0: /* 0xc1 */ | 59 | case 0: /* 0xc1 */ |
59 | req_type = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; | 60 | req_type = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; |
61 | pipe = usb_rcvctrlpipe(gspca_dev->dev, 0); | ||
60 | break; | 62 | break; |
61 | case 1: /* 0x41 */ | 63 | case 1: /* 0x41 */ |
62 | req_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; | 64 | req_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; |
65 | pipe = usb_sndctrlpipe(gspca_dev->dev, 0); | ||
63 | break; | 66 | break; |
64 | case 2: /* 0x80 */ | 67 | case 2: /* 0x80 */ |
65 | req_type = USB_DIR_IN | USB_RECIP_DEVICE; | 68 | req_type = USB_DIR_IN | USB_RECIP_DEVICE; |
69 | pipe = usb_rcvctrlpipe(gspca_dev->dev, 0); | ||
66 | break; | 70 | break; |
67 | case 3: /* 0x40 */ | 71 | case 3: /* 0x40 */ |
68 | req_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; | 72 | req_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; |
73 | pipe = usb_sndctrlpipe(gspca_dev->dev, 0); | ||
69 | break; | 74 | break; |
70 | } | 75 | } |
71 | 76 | ||
72 | ret = usb_control_msg(gspca_dev->dev, | 77 | ret = usb_control_msg(gspca_dev->dev, pipe, |
73 | usb_rcvctrlpipe(gspca_dev->dev, 0), | ||
74 | req, req_type, | 78 | req, req_type, |
75 | val, 0, gspca_dev->usb_buf, size, 500); | 79 | val, 0, gspca_dev->usb_buf, size, 500); |
76 | 80 | ||
@@ -138,6 +142,10 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
138 | struct sd *sd = (struct sd *) gspca_dev; | 142 | struct sd *sd = (struct sd *) gspca_dev; |
139 | struct cam *cam = &gspca_dev->cam; | 143 | struct cam *cam = &gspca_dev->cam; |
140 | 144 | ||
145 | /* Give the camera some time to settle, otherwise initalization will | ||
146 | fail on hotplug, and yes it really needs a full second. */ | ||
147 | msleep(1000); | ||
148 | |||
141 | /* ping camera to be sure STV0680 is present */ | 149 | /* ping camera to be sure STV0680 is present */ |
142 | if (stv_sndctrl(gspca_dev, 0, 0x88, 0x5678, 0x02) != 0x02 || | 150 | if (stv_sndctrl(gspca_dev, 0, 0x88, 0x5678, 0x02) != 0x02 || |
143 | gspca_dev->usb_buf[0] != 0x56 || gspca_dev->usb_buf[1] != 0x78) { | 151 | gspca_dev->usb_buf[0] != 0x56 || gspca_dev->usb_buf[1] != 0x78) { |
@@ -169,6 +177,8 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
169 | PDEBUG(D_PROBE, "Camera supports CIF mode"); | 177 | PDEBUG(D_PROBE, "Camera supports CIF mode"); |
170 | if (gspca_dev->usb_buf[7] & 0x02) | 178 | if (gspca_dev->usb_buf[7] & 0x02) |
171 | PDEBUG(D_PROBE, "Camera supports VGA mode"); | 179 | PDEBUG(D_PROBE, "Camera supports VGA mode"); |
180 | if (gspca_dev->usb_buf[7] & 0x04) | ||
181 | PDEBUG(D_PROBE, "Camera supports QCIF mode"); | ||
172 | if (gspca_dev->usb_buf[7] & 0x08) | 182 | if (gspca_dev->usb_buf[7] & 0x08) |
173 | PDEBUG(D_PROBE, "Camera supports QVGA mode"); | 183 | PDEBUG(D_PROBE, "Camera supports QVGA mode"); |
174 | 184 | ||
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c index 5d0241bb1611..af73da34c83f 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx.c | |||
@@ -27,6 +27,7 @@ | |||
27 | * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web | 27 | * P/N 861040-0000: Sensor ST VV6410 ASIC STV0610 - QuickCam Web |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include <linux/input.h> | ||
30 | #include "stv06xx_sensor.h" | 31 | #include "stv06xx_sensor.h" |
31 | 32 | ||
32 | MODULE_AUTHOR("Erik Andrén"); | 33 | MODULE_AUTHOR("Erik Andrén"); |
@@ -219,6 +220,7 @@ static void stv06xx_dump_bridge(struct sd *sd) | |||
219 | info("Read 0x%x from address 0x%x", data, i); | 220 | info("Read 0x%x from address 0x%x", data, i); |
220 | } | 221 | } |
221 | 222 | ||
223 | info("Testing stv06xx bridge registers for writability"); | ||
222 | for (i = 0x1400; i < 0x160f; i++) { | 224 | for (i = 0x1400; i < 0x160f; i++) { |
223 | stv06xx_read_bridge(sd, i, &data); | 225 | stv06xx_read_bridge(sd, i, &data); |
224 | buf = data; | 226 | buf = data; |
@@ -229,7 +231,7 @@ static void stv06xx_dump_bridge(struct sd *sd) | |||
229 | info("Register 0x%x is read/write", i); | 231 | info("Register 0x%x is read/write", i); |
230 | else if (data != buf) | 232 | else if (data != buf) |
231 | info("Register 0x%x is read/write," | 233 | info("Register 0x%x is read/write," |
232 | "but only partially", i); | 234 | " but only partially", i); |
233 | else | 235 | else |
234 | info("Register 0x%x is read-only", i); | 236 | info("Register 0x%x is read-only", i); |
235 | 237 | ||
@@ -426,6 +428,29 @@ frame_data: | |||
426 | } | 428 | } |
427 | } | 429 | } |
428 | 430 | ||
431 | #ifdef CONFIG_INPUT | ||
432 | static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, | ||
433 | u8 *data, /* interrupt packet data */ | ||
434 | int len) /* interrupt packet length */ | ||
435 | { | ||
436 | int ret = -EINVAL; | ||
437 | |||
438 | if (len == 1 && data[0] == 0x80) { | ||
439 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); | ||
440 | input_sync(gspca_dev->input_dev); | ||
441 | ret = 0; | ||
442 | } | ||
443 | |||
444 | if (len == 1 && data[0] == 0x88) { | ||
445 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); | ||
446 | input_sync(gspca_dev->input_dev); | ||
447 | ret = 0; | ||
448 | } | ||
449 | |||
450 | return ret; | ||
451 | } | ||
452 | #endif | ||
453 | |||
429 | static int stv06xx_config(struct gspca_dev *gspca_dev, | 454 | static int stv06xx_config(struct gspca_dev *gspca_dev, |
430 | const struct usb_device_id *id); | 455 | const struct usb_device_id *id); |
431 | 456 | ||
@@ -436,7 +461,10 @@ static const struct sd_desc sd_desc = { | |||
436 | .init = stv06xx_init, | 461 | .init = stv06xx_init, |
437 | .start = stv06xx_start, | 462 | .start = stv06xx_start, |
438 | .stopN = stv06xx_stopN, | 463 | .stopN = stv06xx_stopN, |
439 | .pkt_scan = stv06xx_pkt_scan | 464 | .pkt_scan = stv06xx_pkt_scan, |
465 | #ifdef CONFIG_INPUT | ||
466 | .int_pkt_scan = sd_int_pkt_scan, | ||
467 | #endif | ||
440 | }; | 468 | }; |
441 | 469 | ||
442 | /* This function is called at probe time */ | 470 | /* This function is called at probe time */ |
diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index 306b7d75b4aa..0c786e00ebcf 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c | |||
@@ -67,7 +67,7 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | |||
67 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | 67 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); |
68 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | 68 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); |
69 | 69 | ||
70 | static struct ctrl sd_ctrls[] = { | 70 | static const struct ctrl sd_ctrls[] = { |
71 | { | 71 | { |
72 | { | 72 | { |
73 | .id = V4L2_CID_BRIGHTNESS, | 73 | .id = V4L2_CID_BRIGHTNESS, |
@@ -267,142 +267,6 @@ static const struct cmd spca504A_clicksmart420_open_data[] = { | |||
267 | {0x06, 0x0000, 0x0000}, | 267 | {0x06, 0x0000, 0x0000}, |
268 | {0x00, 0x0004, 0x2880}, | 268 | {0x00, 0x0004, 0x2880}, |
269 | {0x00, 0x0001, 0x2881}, | 269 | {0x00, 0x0001, 0x2881}, |
270 | /* look like setting a qTable */ | ||
271 | {0x00, 0x0006, 0x2800}, | ||
272 | {0x00, 0x0004, 0x2801}, | ||
273 | {0x00, 0x0004, 0x2802}, | ||
274 | {0x00, 0x0006, 0x2803}, | ||
275 | {0x00, 0x000a, 0x2804}, | ||
276 | {0x00, 0x0010, 0x2805}, | ||
277 | {0x00, 0x0014, 0x2806}, | ||
278 | {0x00, 0x0018, 0x2807}, | ||
279 | {0x00, 0x0005, 0x2808}, | ||
280 | {0x00, 0x0005, 0x2809}, | ||
281 | {0x00, 0x0006, 0x280a}, | ||
282 | {0x00, 0x0008, 0x280b}, | ||
283 | {0x00, 0x000a, 0x280c}, | ||
284 | {0x00, 0x0017, 0x280d}, | ||
285 | {0x00, 0x0018, 0x280e}, | ||
286 | {0x00, 0x0016, 0x280f}, | ||
287 | |||
288 | {0x00, 0x0006, 0x2810}, | ||
289 | {0x00, 0x0005, 0x2811}, | ||
290 | {0x00, 0x0006, 0x2812}, | ||
291 | {0x00, 0x000a, 0x2813}, | ||
292 | {0x00, 0x0010, 0x2814}, | ||
293 | {0x00, 0x0017, 0x2815}, | ||
294 | {0x00, 0x001c, 0x2816}, | ||
295 | {0x00, 0x0016, 0x2817}, | ||
296 | {0x00, 0x0006, 0x2818}, | ||
297 | {0x00, 0x0007, 0x2819}, | ||
298 | {0x00, 0x0009, 0x281a}, | ||
299 | {0x00, 0x000c, 0x281b}, | ||
300 | {0x00, 0x0014, 0x281c}, | ||
301 | {0x00, 0x0023, 0x281d}, | ||
302 | {0x00, 0x0020, 0x281e}, | ||
303 | {0x00, 0x0019, 0x281f}, | ||
304 | |||
305 | {0x00, 0x0007, 0x2820}, | ||
306 | {0x00, 0x0009, 0x2821}, | ||
307 | {0x00, 0x000f, 0x2822}, | ||
308 | {0x00, 0x0016, 0x2823}, | ||
309 | {0x00, 0x001b, 0x2824}, | ||
310 | {0x00, 0x002c, 0x2825}, | ||
311 | {0x00, 0x0029, 0x2826}, | ||
312 | {0x00, 0x001f, 0x2827}, | ||
313 | {0x00, 0x000a, 0x2828}, | ||
314 | {0x00, 0x000e, 0x2829}, | ||
315 | {0x00, 0x0016, 0x282a}, | ||
316 | {0x00, 0x001a, 0x282b}, | ||
317 | {0x00, 0x0020, 0x282c}, | ||
318 | {0x00, 0x002a, 0x282d}, | ||
319 | {0x00, 0x002d, 0x282e}, | ||
320 | {0x00, 0x0025, 0x282f}, | ||
321 | |||
322 | {0x00, 0x0014, 0x2830}, | ||
323 | {0x00, 0x001a, 0x2831}, | ||
324 | {0x00, 0x001f, 0x2832}, | ||
325 | {0x00, 0x0023, 0x2833}, | ||
326 | {0x00, 0x0029, 0x2834}, | ||
327 | {0x00, 0x0030, 0x2835}, | ||
328 | {0x00, 0x0030, 0x2836}, | ||
329 | {0x00, 0x0028, 0x2837}, | ||
330 | {0x00, 0x001d, 0x2838}, | ||
331 | {0x00, 0x0025, 0x2839}, | ||
332 | {0x00, 0x0026, 0x283a}, | ||
333 | {0x00, 0x0027, 0x283b}, | ||
334 | {0x00, 0x002d, 0x283c}, | ||
335 | {0x00, 0x0028, 0x283d}, | ||
336 | {0x00, 0x0029, 0x283e}, | ||
337 | {0x00, 0x0028, 0x283f}, | ||
338 | |||
339 | {0x00, 0x0007, 0x2840}, | ||
340 | {0x00, 0x0007, 0x2841}, | ||
341 | {0x00, 0x000a, 0x2842}, | ||
342 | {0x00, 0x0013, 0x2843}, | ||
343 | {0x00, 0x0028, 0x2844}, | ||
344 | {0x00, 0x0028, 0x2845}, | ||
345 | {0x00, 0x0028, 0x2846}, | ||
346 | {0x00, 0x0028, 0x2847}, | ||
347 | {0x00, 0x0007, 0x2848}, | ||
348 | {0x00, 0x0008, 0x2849}, | ||
349 | {0x00, 0x000a, 0x284a}, | ||
350 | {0x00, 0x001a, 0x284b}, | ||
351 | {0x00, 0x0028, 0x284c}, | ||
352 | {0x00, 0x0028, 0x284d}, | ||
353 | {0x00, 0x0028, 0x284e}, | ||
354 | {0x00, 0x0028, 0x284f}, | ||
355 | |||
356 | {0x00, 0x000a, 0x2850}, | ||
357 | {0x00, 0x000a, 0x2851}, | ||
358 | {0x00, 0x0016, 0x2852}, | ||
359 | {0x00, 0x0028, 0x2853}, | ||
360 | {0x00, 0x0028, 0x2854}, | ||
361 | {0x00, 0x0028, 0x2855}, | ||
362 | {0x00, 0x0028, 0x2856}, | ||
363 | {0x00, 0x0028, 0x2857}, | ||
364 | {0x00, 0x0013, 0x2858}, | ||
365 | {0x00, 0x001a, 0x2859}, | ||
366 | {0x00, 0x0028, 0x285a}, | ||
367 | {0x00, 0x0028, 0x285b}, | ||
368 | {0x00, 0x0028, 0x285c}, | ||
369 | {0x00, 0x0028, 0x285d}, | ||
370 | {0x00, 0x0028, 0x285e}, | ||
371 | {0x00, 0x0028, 0x285f}, | ||
372 | |||
373 | {0x00, 0x0028, 0x2860}, | ||
374 | {0x00, 0x0028, 0x2861}, | ||
375 | {0x00, 0x0028, 0x2862}, | ||
376 | {0x00, 0x0028, 0x2863}, | ||
377 | {0x00, 0x0028, 0x2864}, | ||
378 | {0x00, 0x0028, 0x2865}, | ||
379 | {0x00, 0x0028, 0x2866}, | ||
380 | {0x00, 0x0028, 0x2867}, | ||
381 | {0x00, 0x0028, 0x2868}, | ||
382 | {0x00, 0x0028, 0x2869}, | ||
383 | {0x00, 0x0028, 0x286a}, | ||
384 | {0x00, 0x0028, 0x286b}, | ||
385 | {0x00, 0x0028, 0x286c}, | ||
386 | {0x00, 0x0028, 0x286d}, | ||
387 | {0x00, 0x0028, 0x286e}, | ||
388 | {0x00, 0x0028, 0x286f}, | ||
389 | |||
390 | {0x00, 0x0028, 0x2870}, | ||
391 | {0x00, 0x0028, 0x2871}, | ||
392 | {0x00, 0x0028, 0x2872}, | ||
393 | {0x00, 0x0028, 0x2873}, | ||
394 | {0x00, 0x0028, 0x2874}, | ||
395 | {0x00, 0x0028, 0x2875}, | ||
396 | {0x00, 0x0028, 0x2876}, | ||
397 | {0x00, 0x0028, 0x2877}, | ||
398 | {0x00, 0x0028, 0x2878}, | ||
399 | {0x00, 0x0028, 0x2879}, | ||
400 | {0x00, 0x0028, 0x287a}, | ||
401 | {0x00, 0x0028, 0x287b}, | ||
402 | {0x00, 0x0028, 0x287c}, | ||
403 | {0x00, 0x0028, 0x287d}, | ||
404 | {0x00, 0x0028, 0x287e}, | ||
405 | {0x00, 0x0028, 0x287f}, | ||
406 | 270 | ||
407 | {0xa0, 0x0000, 0x0503}, | 271 | {0xa0, 0x0000, 0x0503}, |
408 | }; | 272 | }; |
@@ -622,6 +486,20 @@ static void spca504_acknowledged_command(struct gspca_dev *gspca_dev, | |||
622 | PDEBUG(D_FRAM, "after wait 0x%04x", notdone); | 486 | PDEBUG(D_FRAM, "after wait 0x%04x", notdone); |
623 | } | 487 | } |
624 | 488 | ||
489 | static void spca504_read_info(struct gspca_dev *gspca_dev) | ||
490 | { | ||
491 | int i; | ||
492 | u8 info[6]; | ||
493 | |||
494 | for (i = 0; i < 6; i++) | ||
495 | info[i] = reg_r_1(gspca_dev, i); | ||
496 | PDEBUG(D_STREAM, | ||
497 | "Read info: %d %d %d %d %d %d." | ||
498 | " Should be 1,0,2,2,0,0", | ||
499 | info[0], info[1], info[2], | ||
500 | info[3], info[4], info[5]); | ||
501 | } | ||
502 | |||
625 | static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev, | 503 | static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev, |
626 | u8 req, | 504 | u8 req, |
627 | u16 idx, u16 val, u16 endcode, u8 count) | 505 | u16 idx, u16 val, u16 endcode, u8 count) |
@@ -881,8 +759,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
881 | static int sd_init(struct gspca_dev *gspca_dev) | 759 | static int sd_init(struct gspca_dev *gspca_dev) |
882 | { | 760 | { |
883 | struct sd *sd = (struct sd *) gspca_dev; | 761 | struct sd *sd = (struct sd *) gspca_dev; |
884 | int i; | ||
885 | u8 info[6]; | ||
886 | 762 | ||
887 | switch (sd->bridge) { | 763 | switch (sd->bridge) { |
888 | case BRIDGE_SPCA504B: | 764 | case BRIDGE_SPCA504B: |
@@ -924,15 +800,8 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
924 | /* case BRIDGE_SPCA504: */ | 800 | /* case BRIDGE_SPCA504: */ |
925 | PDEBUG(D_STREAM, "Opening SPCA504"); | 801 | PDEBUG(D_STREAM, "Opening SPCA504"); |
926 | if (sd->subtype == AiptekMiniPenCam13) { | 802 | if (sd->subtype == AiptekMiniPenCam13) { |
927 | /*****************************/ | 803 | spca504_read_info(gspca_dev); |
928 | for (i = 0; i < 6; i++) | 804 | |
929 | info[i] = reg_r_1(gspca_dev, i); | ||
930 | PDEBUG(D_STREAM, | ||
931 | "Read info: %d %d %d %d %d %d." | ||
932 | " Should be 1,0,2,2,0,0", | ||
933 | info[0], info[1], info[2], | ||
934 | info[3], info[4], info[5]); | ||
935 | /* spca504a aiptek */ | ||
936 | /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */ | 805 | /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */ |
937 | spca504A_acknowledged_command(gspca_dev, 0x24, | 806 | spca504A_acknowledged_command(gspca_dev, 0x24, |
938 | 8, 3, 0x9e, 1); | 807 | 8, 3, 0x9e, 1); |
@@ -971,8 +840,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
971 | { | 840 | { |
972 | struct sd *sd = (struct sd *) gspca_dev; | 841 | struct sd *sd = (struct sd *) gspca_dev; |
973 | int enable; | 842 | int enable; |
974 | int i; | ||
975 | u8 info[6]; | ||
976 | 843 | ||
977 | /* create the JPEG header */ | 844 | /* create the JPEG header */ |
978 | sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); | 845 | sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); |
@@ -1008,14 +875,8 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1008 | break; | 875 | break; |
1009 | case BRIDGE_SPCA504: | 876 | case BRIDGE_SPCA504: |
1010 | if (sd->subtype == AiptekMiniPenCam13) { | 877 | if (sd->subtype == AiptekMiniPenCam13) { |
1011 | for (i = 0; i < 6; i++) | 878 | spca504_read_info(gspca_dev); |
1012 | info[i] = reg_r_1(gspca_dev, i); | 879 | |
1013 | PDEBUG(D_STREAM, | ||
1014 | "Read info: %d %d %d %d %d %d." | ||
1015 | " Should be 1,0,2,2,0,0", | ||
1016 | info[0], info[1], info[2], | ||
1017 | info[3], info[4], info[5]); | ||
1018 | /* spca504a aiptek */ | ||
1019 | /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */ | 880 | /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */ |
1020 | spca504A_acknowledged_command(gspca_dev, 0x24, | 881 | spca504A_acknowledged_command(gspca_dev, 0x24, |
1021 | 8, 3, 0x9e, 1); | 882 | 8, 3, 0x9e, 1); |
@@ -1026,13 +887,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1026 | 0, 0, 0x9d, 1); | 887 | 0, 0, 0x9d, 1); |
1027 | } else { | 888 | } else { |
1028 | spca504_acknowledged_command(gspca_dev, 0x24, 8, 3); | 889 | spca504_acknowledged_command(gspca_dev, 0x24, 8, 3); |
1029 | for (i = 0; i < 6; i++) | 890 | spca504_read_info(gspca_dev); |
1030 | info[i] = reg_r_1(gspca_dev, i); | ||
1031 | PDEBUG(D_STREAM, | ||
1032 | "Read info: %d %d %d %d %d %d." | ||
1033 | " Should be 1,0,2,2,0,0", | ||
1034 | info[0], info[1], info[2], | ||
1035 | info[3], info[4], info[5]); | ||
1036 | spca504_acknowledged_command(gspca_dev, 0x24, 8, 3); | 891 | spca504_acknowledged_command(gspca_dev, 0x24, 8, 3); |
1037 | spca504_acknowledged_command(gspca_dev, 0x24, 0, 0); | 892 | spca504_acknowledged_command(gspca_dev, 0x24, 0, 0); |
1038 | } | 893 | } |
@@ -1336,6 +1191,7 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
1336 | {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)}, | 1191 | {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)}, |
1337 | {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)}, | 1192 | {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)}, |
1338 | {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)}, | 1193 | {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)}, |
1194 | {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)}, | ||
1339 | {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)}, | 1195 | {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)}, |
1340 | {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)}, | 1196 | {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)}, |
1341 | {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)}, | 1197 | {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)}, |
diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index 55ef6a744427..668a7536af90 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c | |||
@@ -52,6 +52,7 @@ struct sd { | |||
52 | #define SENSOR_OM6802 0 | 52 | #define SENSOR_OM6802 0 |
53 | #define SENSOR_OTHER 1 | 53 | #define SENSOR_OTHER 1 |
54 | #define SENSOR_TAS5130A 2 | 54 | #define SENSOR_TAS5130A 2 |
55 | #define SENSOR_LT168G 3 /* must verify if this is the actual model */ | ||
55 | }; | 56 | }; |
56 | 57 | ||
57 | /* V4L2 controls supported by the driver */ | 58 | /* V4L2 controls supported by the driver */ |
@@ -78,7 +79,7 @@ static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val); | |||
78 | static int sd_querymenu(struct gspca_dev *gspca_dev, | 79 | static int sd_querymenu(struct gspca_dev *gspca_dev, |
79 | struct v4l2_querymenu *menu); | 80 | struct v4l2_querymenu *menu); |
80 | 81 | ||
81 | static struct ctrl sd_ctrls[] = { | 82 | static const struct ctrl sd_ctrls[] = { |
82 | { | 83 | { |
83 | { | 84 | { |
84 | .id = V4L2_CID_BRIGHTNESS, | 85 | .id = V4L2_CID_BRIGHTNESS, |
@@ -306,6 +307,17 @@ static const u8 n4_tas5130a[] = { | |||
306 | 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8, | 307 | 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8, |
307 | 0xc6, 0xda | 308 | 0xc6, 0xda |
308 | }; | 309 | }; |
310 | static const u8 n4_lt168g[] = { | ||
311 | 0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28, | ||
312 | 0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70, | ||
313 | 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3, | ||
314 | 0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20, | ||
315 | 0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68, | ||
316 | 0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40, | ||
317 | 0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0, | ||
318 | 0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c, | ||
319 | 0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80 | ||
320 | }; | ||
309 | 321 | ||
310 | static const struct additional_sensor_data sensor_data[] = { | 322 | static const struct additional_sensor_data sensor_data[] = { |
311 | { /* 0: OM6802 */ | 323 | { /* 0: OM6802 */ |
@@ -380,6 +392,23 @@ static const struct additional_sensor_data sensor_data[] = { | |||
380 | .stream = | 392 | .stream = |
381 | {0x0b, 0x04, 0x0a, 0x40}, | 393 | {0x0b, 0x04, 0x0a, 0x40}, |
382 | }, | 394 | }, |
395 | { /* 3: LT168G */ | ||
396 | .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00}, | ||
397 | .n4 = n4_lt168g, | ||
398 | .n4sz = sizeof n4_lt168g, | ||
399 | .reg80 = 0x7c, | ||
400 | .reg8e = 0xb3, | ||
401 | .nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00}, | ||
402 | .data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40, | ||
403 | 0xb0, 0xf4}, | ||
404 | .data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6, | ||
405 | 0xff}, | ||
406 | .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6, | ||
407 | 0xff}, | ||
408 | .data4 = {0x66, 0x41, 0xa8, 0xf0}, | ||
409 | .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b}, | ||
410 | .stream = {0x0b, 0x04, 0x0a, 0x28}, | ||
411 | }, | ||
383 | }; | 412 | }; |
384 | 413 | ||
385 | #define MAX_EFFECTS 7 | 414 | #define MAX_EFFECTS 7 |
@@ -716,6 +745,10 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
716 | PDEBUG(D_PROBE, "sensor tas5130a"); | 745 | PDEBUG(D_PROBE, "sensor tas5130a"); |
717 | sd->sensor = SENSOR_TAS5130A; | 746 | sd->sensor = SENSOR_TAS5130A; |
718 | break; | 747 | break; |
748 | case 0x0802: | ||
749 | PDEBUG(D_PROBE, "sensor lt168g"); | ||
750 | sd->sensor = SENSOR_LT168G; | ||
751 | break; | ||
719 | case 0x0803: | 752 | case 0x0803: |
720 | PDEBUG(D_PROBE, "sensor 'other'"); | 753 | PDEBUG(D_PROBE, "sensor 'other'"); |
721 | sd->sensor = SENSOR_OTHER; | 754 | sd->sensor = SENSOR_OTHER; |
@@ -758,6 +791,13 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
758 | reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3); | 791 | reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3); |
759 | reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz); | 792 | reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz); |
760 | 793 | ||
794 | if (sd->sensor == SENSOR_LT168G) { | ||
795 | test_byte = reg_r(gspca_dev, 0x80); | ||
796 | PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80, | ||
797 | test_byte); | ||
798 | reg_w(gspca_dev, 0x6c80); | ||
799 | } | ||
800 | |||
761 | reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1); | 801 | reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1); |
762 | reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2); | 802 | reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2); |
763 | reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3); | 803 | reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3); |
@@ -782,6 +822,13 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
782 | reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8); | 822 | reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8); |
783 | reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream); | 823 | reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream); |
784 | 824 | ||
825 | if (sd->sensor == SENSOR_LT168G) { | ||
826 | test_byte = reg_r(gspca_dev, 0x80); | ||
827 | PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80, | ||
828 | test_byte); | ||
829 | reg_w(gspca_dev, 0x6c80); | ||
830 | } | ||
831 | |||
785 | reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1); | 832 | reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1); |
786 | reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2); | 833 | reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2); |
787 | reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3); | 834 | reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3); |
@@ -888,6 +935,8 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
888 | case SENSOR_OM6802: | 935 | case SENSOR_OM6802: |
889 | om6802_sensor_init(gspca_dev); | 936 | om6802_sensor_init(gspca_dev); |
890 | break; | 937 | break; |
938 | case SENSOR_LT168G: | ||
939 | break; | ||
891 | case SENSOR_OTHER: | 940 | case SENSOR_OTHER: |
892 | break; | 941 | break; |
893 | default: | 942 | default: |
diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c index b74a3b6489c7..c7b6eb1e04d5 100644 --- a/drivers/media/video/gspca/tv8532.c +++ b/drivers/media/video/gspca/tv8532.c | |||
@@ -39,7 +39,7 @@ struct sd { | |||
39 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | 39 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); |
40 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | 40 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); |
41 | 41 | ||
42 | static struct ctrl sd_ctrls[] = { | 42 | static const struct ctrl sd_ctrls[] = { |
43 | { | 43 | { |
44 | { | 44 | { |
45 | .id = V4L2_CID_BRIGHTNESS, | 45 | .id = V4L2_CID_BRIGHTNESS, |
diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index 71921c878424..4989f9afb46e 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c | |||
@@ -32,10 +32,13 @@ MODULE_LICENSE("GPL"); | |||
32 | struct sd { | 32 | struct sd { |
33 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 33 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
34 | 34 | ||
35 | u8 brightness; | ||
36 | u8 contrast; | ||
37 | u8 colors; | ||
35 | u8 hflip; | 38 | u8 hflip; |
36 | u8 vflip; | 39 | u8 vflip; |
37 | u8 lightfreq; | 40 | u8 lightfreq; |
38 | u8 sharpness; | 41 | s8 sharpness; |
39 | 42 | ||
40 | u8 image_offset; | 43 | u8 image_offset; |
41 | 44 | ||
@@ -52,6 +55,7 @@ struct sd { | |||
52 | #define SENSOR_OV7670 6 | 55 | #define SENSOR_OV7670 6 |
53 | #define SENSOR_PO1200 7 | 56 | #define SENSOR_PO1200 7 |
54 | #define SENSOR_PO3130NC 8 | 57 | #define SENSOR_PO3130NC 8 |
58 | #define SENSOR_POxxxx 9 | ||
55 | u8 flags; | 59 | u8 flags; |
56 | #define FL_SAMSUNG 0x01 /* SamsungQ1 (2 sensors) */ | 60 | #define FL_SAMSUNG 0x01 /* SamsungQ1 (2 sensors) */ |
57 | #define FL_HFLIP 0x02 /* mirrored by default */ | 61 | #define FL_HFLIP 0x02 /* mirrored by default */ |
@@ -59,6 +63,12 @@ struct sd { | |||
59 | }; | 63 | }; |
60 | 64 | ||
61 | /* V4L2 controls supported by the driver */ | 65 | /* V4L2 controls supported by the driver */ |
66 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
67 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
68 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
69 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
70 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); | ||
71 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | ||
62 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); | 72 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); |
63 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); | 73 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); |
64 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); | 74 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); |
@@ -68,9 +78,54 @@ static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | |||
68 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); | 78 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); |
69 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | 79 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); |
70 | 80 | ||
71 | static struct ctrl sd_ctrls[] = { | 81 | static const struct ctrl sd_ctrls[] = { |
82 | #define BRIGHTNESS_IDX 0 | ||
83 | { | ||
84 | { | ||
85 | .id = V4L2_CID_BRIGHTNESS, | ||
86 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
87 | .name = "Brightness", | ||
88 | .minimum = 0, | ||
89 | .maximum = 255, | ||
90 | .step = 1, | ||
91 | #define BRIGHTNESS_DEF 128 | ||
92 | .default_value = BRIGHTNESS_DEF, | ||
93 | }, | ||
94 | .set = sd_setbrightness, | ||
95 | .get = sd_getbrightness, | ||
96 | }, | ||
97 | #define CONTRAST_IDX 1 | ||
98 | { | ||
99 | { | ||
100 | .id = V4L2_CID_CONTRAST, | ||
101 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
102 | .name = "Contrast", | ||
103 | .minimum = 0, | ||
104 | .maximum = 255, | ||
105 | .step = 1, | ||
106 | #define CONTRAST_DEF 127 | ||
107 | .default_value = CONTRAST_DEF, | ||
108 | }, | ||
109 | .set = sd_setcontrast, | ||
110 | .get = sd_getcontrast, | ||
111 | }, | ||
112 | #define COLORS_IDX 2 | ||
113 | { | ||
114 | { | ||
115 | .id = V4L2_CID_SATURATION, | ||
116 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
117 | .name = "Saturation", | ||
118 | .minimum = 1, | ||
119 | .maximum = 127, | ||
120 | .step = 1, | ||
121 | #define COLOR_DEF 63 | ||
122 | .default_value = COLOR_DEF, | ||
123 | }, | ||
124 | .set = sd_setcolors, | ||
125 | .get = sd_getcolors, | ||
126 | }, | ||
72 | /* next 2 controls work with some sensors only */ | 127 | /* next 2 controls work with some sensors only */ |
73 | #define HFLIP_IDX 0 | 128 | #define HFLIP_IDX 3 |
74 | { | 129 | { |
75 | { | 130 | { |
76 | .id = V4L2_CID_HFLIP, | 131 | .id = V4L2_CID_HFLIP, |
@@ -85,7 +140,7 @@ static struct ctrl sd_ctrls[] = { | |||
85 | .set = sd_sethflip, | 140 | .set = sd_sethflip, |
86 | .get = sd_gethflip, | 141 | .get = sd_gethflip, |
87 | }, | 142 | }, |
88 | #define VFLIP_IDX 1 | 143 | #define VFLIP_IDX 4 |
89 | { | 144 | { |
90 | { | 145 | { |
91 | .id = V4L2_CID_VFLIP, | 146 | .id = V4L2_CID_VFLIP, |
@@ -100,7 +155,7 @@ static struct ctrl sd_ctrls[] = { | |||
100 | .set = sd_setvflip, | 155 | .set = sd_setvflip, |
101 | .get = sd_getvflip, | 156 | .get = sd_getvflip, |
102 | }, | 157 | }, |
103 | #define LIGHTFREQ_IDX 2 | 158 | #define LIGHTFREQ_IDX 5 |
104 | { | 159 | { |
105 | { | 160 | { |
106 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | 161 | .id = V4L2_CID_POWER_LINE_FREQUENCY, |
@@ -115,17 +170,16 @@ static struct ctrl sd_ctrls[] = { | |||
115 | .set = sd_setfreq, | 170 | .set = sd_setfreq, |
116 | .get = sd_getfreq, | 171 | .get = sd_getfreq, |
117 | }, | 172 | }, |
118 | /* po1200 only */ | 173 | #define SHARPNESS_IDX 6 |
119 | #define SHARPNESS_IDX 3 | ||
120 | { | 174 | { |
121 | { | 175 | { |
122 | .id = V4L2_CID_SHARPNESS, | 176 | .id = V4L2_CID_SHARPNESS, |
123 | .type = V4L2_CTRL_TYPE_INTEGER, | 177 | .type = V4L2_CTRL_TYPE_INTEGER, |
124 | .name = "Sharpness", | 178 | .name = "Sharpness", |
125 | .minimum = 0, | 179 | .minimum = -1, |
126 | .maximum = 2, | 180 | .maximum = 2, |
127 | .step = 1, | 181 | .step = 1, |
128 | #define SHARPNESS_DEF 1 | 182 | #define SHARPNESS_DEF -1 |
129 | .default_value = SHARPNESS_DEF, | 183 | .default_value = SHARPNESS_DEF, |
130 | }, | 184 | }, |
131 | .set = sd_setsharpness, | 185 | .set = sd_setsharpness, |
@@ -133,6 +187,42 @@ static struct ctrl sd_ctrls[] = { | |||
133 | }, | 187 | }, |
134 | }; | 188 | }; |
135 | 189 | ||
190 | /* table of the disabled controls */ | ||
191 | static u32 ctrl_dis[] = { | ||
192 | /* SENSOR_HV7131R 0 */ | ||
193 | (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | ||
194 | | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX) | ||
195 | | (1 << SHARPNESS_IDX), | ||
196 | /* SENSOR_MI0360 1 */ | ||
197 | (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | ||
198 | | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX) | ||
199 | | (1 << SHARPNESS_IDX), | ||
200 | /* SENSOR_MI1310_SOC 2 */ | ||
201 | (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | ||
202 | | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX), | ||
203 | /* SENSOR_MI1320 3 */ | ||
204 | (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | ||
205 | | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX), | ||
206 | /* SENSOR_MI1320_SOC 4 */ | ||
207 | (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | ||
208 | | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX), | ||
209 | /* SENSOR_OV7660 5 */ | ||
210 | (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | ||
211 | | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX), | ||
212 | /* SENSOR_OV7670 6 */ | ||
213 | (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | ||
214 | | (1 << SHARPNESS_IDX), | ||
215 | /* SENSOR_PO1200 7 */ | ||
216 | (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | ||
217 | | (1 << LIGHTFREQ_IDX), | ||
218 | /* SENSOR_PO3130NC 8 */ | ||
219 | (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX) | ||
220 | | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX) | ||
221 | | (1 << SHARPNESS_IDX), | ||
222 | /* SENSOR_POxxxx 9 */ | ||
223 | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX), | ||
224 | }; | ||
225 | |||
136 | static const struct v4l2_pix_format vc0321_mode[] = { | 226 | static const struct v4l2_pix_format vc0321_mode[] = { |
137 | {320, 240, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, | 227 | {320, 240, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE, |
138 | .bytesperline = 320, | 228 | .bytesperline = 320, |
@@ -215,7 +305,7 @@ static const u8 mi0360_initVGA_JPG[][4] = { | |||
215 | {0xb3, 0x15, 0x00, 0xcc}, | 305 | {0xb3, 0x15, 0x00, 0xcc}, |
216 | {0xb3, 0x16, 0x02, 0xcc}, | 306 | {0xb3, 0x16, 0x02, 0xcc}, |
217 | {0xb3, 0x17, 0x7f, 0xcc}, | 307 | {0xb3, 0x17, 0x7f, 0xcc}, |
218 | {0xb3, 0x35, 0xdd, 0xcc}, | 308 | {0xb3, 0x35, 0xdd, 0xcc}, /* i2c add: 5d */ |
219 | {0xb3, 0x34, 0x02, 0xcc}, | 309 | {0xb3, 0x34, 0x02, 0xcc}, |
220 | {0xb3, 0x00, 0x25, 0xcc}, | 310 | {0xb3, 0x00, 0x25, 0xcc}, |
221 | {0xbc, 0x00, 0x71, 0xcc}, | 311 | {0xbc, 0x00, 0x71, 0xcc}, |
@@ -435,7 +525,7 @@ static const u8 mi1310_socinitVGA_JPG[][4] = { | |||
435 | {0xb3, 0x08, 0x01, 0xcc}, | 525 | {0xb3, 0x08, 0x01, 0xcc}, |
436 | {0xb3, 0x09, 0x0c, 0xcc}, | 526 | {0xb3, 0x09, 0x0c, 0xcc}, |
437 | {0xb3, 0x34, 0x02, 0xcc}, | 527 | {0xb3, 0x34, 0x02, 0xcc}, |
438 | {0xb3, 0x35, 0xdd, 0xcc}, | 528 | {0xb3, 0x35, 0xdd, 0xcc}, /* i2c add: 5d */ |
439 | {0xb3, 0x02, 0x00, 0xcc}, | 529 | {0xb3, 0x02, 0x00, 0xcc}, |
440 | {0xb3, 0x03, 0x0a, 0xcc}, | 530 | {0xb3, 0x03, 0x0a, 0xcc}, |
441 | {0xb3, 0x04, 0x05, 0xcc}, | 531 | {0xb3, 0x04, 0x05, 0xcc}, |
@@ -860,7 +950,8 @@ static const u8 mi1320_initVGA_data[][4] = { | |||
860 | {0xb0, 0x16, 0x03, 0xcc}, {0xb3, 0x05, 0x00, 0xcc}, | 950 | {0xb0, 0x16, 0x03, 0xcc}, {0xb3, 0x05, 0x00, 0xcc}, |
861 | {0xb3, 0x06, 0x00, 0xcc}, {0xb3, 0x08, 0x01, 0xcc}, | 951 | {0xb3, 0x06, 0x00, 0xcc}, {0xb3, 0x08, 0x01, 0xcc}, |
862 | {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x34, 0x02, 0xcc}, | 952 | {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x34, 0x02, 0xcc}, |
863 | {0xb3, 0x35, 0xc8, 0xcc}, {0xb3, 0x02, 0x00, 0xcc}, | 953 | {0xb3, 0x35, 0xc8, 0xcc}, /* i2c add: 48 */ |
954 | {0xb3, 0x02, 0x00, 0xcc}, | ||
864 | {0xb3, 0x03, 0x0a, 0xcc}, {0xb3, 0x04, 0x05, 0xcc}, | 955 | {0xb3, 0x03, 0x0a, 0xcc}, {0xb3, 0x04, 0x05, 0xcc}, |
865 | {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc}, | 956 | {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc}, |
866 | {0xb3, 0x22, 0x03, 0xcc}, {0xb3, 0x23, 0xc0, 0xcc}, | 957 | {0xb3, 0x22, 0x03, 0xcc}, {0xb3, 0x23, 0xc0, 0xcc}, |
@@ -901,7 +992,8 @@ static const u8 mi1320_initVGA_data[][4] = { | |||
901 | {0xc3, 0x01, 0x03, 0xbb}, {0xc4, 0x00, 0x04, 0xbb}, | 992 | {0xc3, 0x01, 0x03, 0xbb}, {0xc4, 0x00, 0x04, 0xbb}, |
902 | {0xf0, 0x00, 0x00, 0xbb}, {0x05, 0x01, 0x13, 0xbb}, | 993 | {0xf0, 0x00, 0x00, 0xbb}, {0x05, 0x01, 0x13, 0xbb}, |
903 | {0x06, 0x00, 0x11, 0xbb}, {0x07, 0x00, 0x85, 0xbb}, | 994 | {0x06, 0x00, 0x11, 0xbb}, {0x07, 0x00, 0x85, 0xbb}, |
904 | {0x08, 0x00, 0x27, 0xbb}, {0x20, 0x01, 0x03, 0xbb}, | 995 | {0x08, 0x00, 0x27, 0xbb}, |
996 | {0x20, 0x01, 0x00, 0xbb}, /* h/v flips - was 03 */ | ||
905 | {0x21, 0x80, 0x00, 0xbb}, {0x22, 0x0d, 0x0f, 0xbb}, | 997 | {0x21, 0x80, 0x00, 0xbb}, {0x22, 0x0d, 0x0f, 0xbb}, |
906 | {0x24, 0x80, 0x00, 0xbb}, {0x59, 0x00, 0xff, 0xbb}, | 998 | {0x24, 0x80, 0x00, 0xbb}, {0x59, 0x00, 0xff, 0xbb}, |
907 | {0xf0, 0x00, 0x02, 0xbb}, {0x39, 0x03, 0x0d, 0xbb}, | 999 | {0xf0, 0x00, 0x02, 0xbb}, {0x39, 0x03, 0x0d, 0xbb}, |
@@ -1012,7 +1104,7 @@ static const u8 mi1320_soc_InitVGA[][4] = { | |||
1012 | {0xb3, 0x08, 0x01, 0xcc}, | 1104 | {0xb3, 0x08, 0x01, 0xcc}, |
1013 | {0xb3, 0x09, 0x0c, 0xcc}, | 1105 | {0xb3, 0x09, 0x0c, 0xcc}, |
1014 | {0xb3, 0x34, 0x02, 0xcc}, | 1106 | {0xb3, 0x34, 0x02, 0xcc}, |
1015 | {0xb3, 0x35, 0xc8, 0xcc}, | 1107 | {0xb3, 0x35, 0xc8, 0xcc}, /* i2c add: 48 */ |
1016 | {0xb3, 0x02, 0x00, 0xcc}, | 1108 | {0xb3, 0x02, 0x00, 0xcc}, |
1017 | {0xb3, 0x03, 0x0a, 0xcc}, | 1109 | {0xb3, 0x03, 0x0a, 0xcc}, |
1018 | {0xb3, 0x04, 0x05, 0xcc}, | 1110 | {0xb3, 0x04, 0x05, 0xcc}, |
@@ -1359,7 +1451,8 @@ static const u8 po3130_initVGA_data[][4] = { | |||
1359 | {0xb3, 0x23, 0xe8, 0xcc}, {0xb8, 0x08, 0xe8, 0xcc}, | 1451 | {0xb3, 0x23, 0xe8, 0xcc}, {0xb8, 0x08, 0xe8, 0xcc}, |
1360 | {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc}, | 1452 | {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc}, |
1361 | {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc}, | 1453 | {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc}, |
1362 | {0xb3, 0x34, 0x01, 0xcc}, {0xb3, 0x35, 0xf6, 0xcc}, | 1454 | {0xb3, 0x34, 0x01, 0xcc}, |
1455 | {0xb3, 0x35, 0xf6, 0xcc}, /* i2c add: 76 */ | ||
1363 | {0xb3, 0x00, 0x27, 0xcc}, {0xbc, 0x00, 0x71, 0xcc}, | 1456 | {0xb3, 0x00, 0x27, 0xcc}, {0xbc, 0x00, 0x71, 0xcc}, |
1364 | {0xb8, 0x00, 0x21, 0xcc}, {0xb8, 0x27, 0x20, 0xcc}, | 1457 | {0xb8, 0x00, 0x21, 0xcc}, {0xb8, 0x27, 0x20, 0xcc}, |
1365 | {0xb8, 0x01, 0x79, 0xcc}, {0xb8, 0x81, 0x09, 0xcc}, | 1458 | {0xb8, 0x01, 0x79, 0xcc}, {0xb8, 0x81, 0x09, 0xcc}, |
@@ -1561,7 +1654,7 @@ static const u8 hv7131r_initVGA_data[][4] = { | |||
1561 | {0xb3, 0x16, 0x02, 0xcc}, | 1654 | {0xb3, 0x16, 0x02, 0xcc}, |
1562 | {0xb3, 0x17, 0x7f, 0xcc}, | 1655 | {0xb3, 0x17, 0x7f, 0xcc}, |
1563 | {0xb3, 0x34, 0x01, 0xcc}, | 1656 | {0xb3, 0x34, 0x01, 0xcc}, |
1564 | {0xb3, 0x35, 0x91, 0xcc}, | 1657 | {0xb3, 0x35, 0x91, 0xcc}, /* i2c add: 11 */ |
1565 | {0xb3, 0x00, 0x27, 0xcc}, | 1658 | {0xb3, 0x00, 0x27, 0xcc}, |
1566 | {0xbc, 0x00, 0x73, 0xcc}, | 1659 | {0xbc, 0x00, 0x73, 0xcc}, |
1567 | {0xb8, 0x00, 0x23, 0xcc}, | 1660 | {0xb8, 0x00, 0x23, 0xcc}, |
@@ -1747,7 +1840,8 @@ static const u8 ov7660_initVGA_data[][4] = { | |||
1747 | {0xb3, 0x23, 0xe0, 0xcc}, {0xb3, 0x1d, 0x01, 0xcc}, | 1840 | {0xb3, 0x23, 0xe0, 0xcc}, {0xb3, 0x1d, 0x01, 0xcc}, |
1748 | {0xb3, 0x1f, 0x02, 0xcc}, | 1841 | {0xb3, 0x1f, 0x02, 0xcc}, |
1749 | {0xb3, 0x34, 0x01, 0xcc}, | 1842 | {0xb3, 0x34, 0x01, 0xcc}, |
1750 | {0xb3, 0x35, 0xa1, 0xcc}, {0xb3, 0x00, 0x26, 0xcc}, | 1843 | {0xb3, 0x35, 0xa1, 0xcc}, /* i2c add: 21 */ |
1844 | {0xb3, 0x00, 0x26, 0xcc}, | ||
1751 | {0xb8, 0x00, 0x33, 0xcc}, /* 13 */ | 1845 | {0xb8, 0x00, 0x33, 0xcc}, /* 13 */ |
1752 | {0xb8, 0x01, 0x7d, 0xcc}, | 1846 | {0xb8, 0x01, 0x7d, 0xcc}, |
1753 | {0xbc, 0x00, 0x73, 0xcc}, {0xb8, 0x81, 0x09, 0xcc}, | 1847 | {0xbc, 0x00, 0x73, 0xcc}, {0xb8, 0x81, 0x09, 0xcc}, |
@@ -1883,7 +1977,8 @@ static const u8 ov7670_initVGA_JPG[][4] = { | |||
1883 | {0x00, 0x00, 0x10, 0xdd}, | 1977 | {0x00, 0x00, 0x10, 0xdd}, |
1884 | {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x10, 0xdd}, | 1978 | {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x10, 0xdd}, |
1885 | {0xb3, 0x00, 0x66, 0xcc}, {0xb3, 0x00, 0x67, 0xcc}, | 1979 | {0xb3, 0x00, 0x66, 0xcc}, {0xb3, 0x00, 0x67, 0xcc}, |
1886 | {0xb3, 0x35, 0xa1, 0xcc}, {0xb3, 0x34, 0x01, 0xcc}, | 1980 | {0xb3, 0x35, 0xa1, 0xcc}, /* i2c add: 21 */ |
1981 | {0xb3, 0x34, 0x01, 0xcc}, | ||
1887 | {0xb3, 0x05, 0x01, 0xcc}, {0xb3, 0x06, 0x01, 0xcc}, | 1982 | {0xb3, 0x05, 0x01, 0xcc}, {0xb3, 0x06, 0x01, 0xcc}, |
1888 | {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc}, | 1983 | {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc}, |
1889 | {0xb3, 0x02, 0x02, 0xcc}, {0xb3, 0x03, 0x1f, 0xcc}, | 1984 | {0xb3, 0x02, 0x02, 0xcc}, {0xb3, 0x03, 0x1f, 0xcc}, |
@@ -2181,7 +2276,7 @@ static const u8 po1200_initVGA_data[][4] = { | |||
2181 | {0xb0, 0x54, 0x13, 0xcc}, | 2276 | {0xb0, 0x54, 0x13, 0xcc}, |
2182 | {0xb3, 0x00, 0x67, 0xcc}, | 2277 | {0xb3, 0x00, 0x67, 0xcc}, |
2183 | {0xb3, 0x34, 0x01, 0xcc}, | 2278 | {0xb3, 0x34, 0x01, 0xcc}, |
2184 | {0xb3, 0x35, 0xdc, 0xcc}, | 2279 | {0xb3, 0x35, 0xdc, 0xcc}, /* i2c add: 5c */ |
2185 | {0x00, 0x03, 0x00, 0xaa}, | 2280 | {0x00, 0x03, 0x00, 0xaa}, |
2186 | {0x00, 0x12, 0x05, 0xaa}, | 2281 | {0x00, 0x12, 0x05, 0xaa}, |
2187 | {0x00, 0x13, 0x02, 0xaa}, | 2282 | {0x00, 0x13, 0x02, 0xaa}, |
@@ -2408,6 +2503,251 @@ static const u8 po1200_initVGA_data[][4] = { | |||
2408 | {0x00, 0xb6, 0x39, 0xaa}, | 2503 | {0x00, 0xb6, 0x39, 0xaa}, |
2409 | {0x00, 0xb7, 0x24, 0xaa}, | 2504 | {0x00, 0xb7, 0x24, 0xaa}, |
2410 | /*write 89 0400 1415*/ | 2505 | /*write 89 0400 1415*/ |
2506 | {} | ||
2507 | }; | ||
2508 | |||
2509 | static const u8 poxxxx_init_common[][4] = { | ||
2510 | {0xb3, 0x00, 0x04, 0xcc}, | ||
2511 | {0x00, 0x00, 0x10, 0xdd}, | ||
2512 | {0xb3, 0x00, 0x64, 0xcc}, | ||
2513 | {0x00, 0x00, 0x10, 0xdd}, | ||
2514 | {0xb3, 0x00, 0x65, 0xcc}, | ||
2515 | {0x00, 0x00, 0x10, 0xdd}, | ||
2516 | {0xb3, 0x00, 0x67, 0xcc}, | ||
2517 | {0xb0, 0x03, 0x09, 0xcc}, | ||
2518 | {0xb3, 0x05, 0x00, 0xcc}, | ||
2519 | {0xb3, 0x06, 0x00, 0xcc}, | ||
2520 | {0xb3, 0x5c, 0x01, 0xcc}, | ||
2521 | {0xb3, 0x08, 0x01, 0xcc}, | ||
2522 | {0xb3, 0x09, 0x0c, 0xcc}, | ||
2523 | {0xb3, 0x34, 0x01, 0xcc}, | ||
2524 | {0xb3, 0x35, 0xf6, 0xcc}, /* i2c add: 76 */ | ||
2525 | {0xb3, 0x02, 0xb0, 0xcc}, | ||
2526 | {0xb3, 0x03, 0x18, 0xcc}, | ||
2527 | {0xb3, 0x04, 0x15, 0xcc}, | ||
2528 | {0xb3, 0x20, 0x00, 0xcc}, | ||
2529 | {0xb3, 0x21, 0x00, 0xcc}, | ||
2530 | {0xb3, 0x22, 0x04, 0xcc}, | ||
2531 | {0xb3, 0x23, 0x00, 0xcc}, | ||
2532 | {0xb3, 0x14, 0x00, 0xcc}, | ||
2533 | {0xb3, 0x15, 0x00, 0xcc}, | ||
2534 | {0xb3, 0x16, 0x04, 0xcc}, | ||
2535 | {0xb3, 0x17, 0xff, 0xcc}, | ||
2536 | {0xb3, 0x2c, 0x03, 0xcc}, | ||
2537 | {0xb3, 0x2d, 0x56, 0xcc}, | ||
2538 | {0xb3, 0x2e, 0x02, 0xcc}, | ||
2539 | {0xb3, 0x2f, 0x0a, 0xcc}, | ||
2540 | {0xb3, 0x40, 0x00, 0xcc}, | ||
2541 | {0xb3, 0x41, 0x34, 0xcc}, | ||
2542 | {0xb3, 0x42, 0x01, 0xcc}, | ||
2543 | {0xb3, 0x43, 0xe0, 0xcc}, | ||
2544 | {0xbc, 0x00, 0x71, 0xcc}, | ||
2545 | {0xbc, 0x01, 0x01, 0xcc}, | ||
2546 | {0xb3, 0x01, 0x41, 0xcc}, | ||
2547 | {0xb3, 0x4d, 0x00, 0xcc}, | ||
2548 | {0x00, 0x0b, 0x2a, 0xaa}, | ||
2549 | {0x00, 0x0e, 0x03, 0xaa}, | ||
2550 | {0x00, 0x0f, 0xea, 0xaa}, | ||
2551 | {0x00, 0x12, 0x08, 0xaa}, | ||
2552 | {0x00, 0x1e, 0x06, 0xaa}, | ||
2553 | {0x00, 0x21, 0x00, 0xaa}, | ||
2554 | {0x00, 0x31, 0x1f, 0xaa}, | ||
2555 | {0x00, 0x33, 0x38, 0xaa}, | ||
2556 | {0x00, 0x36, 0xc0, 0xaa}, | ||
2557 | {0x00, 0x37, 0xc8, 0xaa}, | ||
2558 | {0x00, 0x3b, 0x36, 0xaa}, | ||
2559 | {0x00, 0x4b, 0xfe, 0xaa}, | ||
2560 | {0x00, 0x4d, 0x2e, 0xaa}, | ||
2561 | {0x00, 0x51, 0x1c, 0xaa}, | ||
2562 | {0x00, 0x52, 0x01, 0xaa}, | ||
2563 | {0x00, 0x55, 0x0a, 0xaa}, | ||
2564 | {0x00, 0x56, 0x0a, 0xaa}, | ||
2565 | {0x00, 0x57, 0x07, 0xaa}, | ||
2566 | {0x00, 0x58, 0x07, 0xaa}, | ||
2567 | {0x00, 0x59, 0x04, 0xaa}, | ||
2568 | {0x00, 0x70, 0x68, 0xaa}, | ||
2569 | {0x00, 0x71, 0x04, 0xaa}, | ||
2570 | {0x00, 0x72, 0x10, 0xaa}, | ||
2571 | {0x00, 0x80, 0x71, 0xaa}, | ||
2572 | {0x00, 0x81, 0x08, 0xaa}, | ||
2573 | {0x00, 0x82, 0x00, 0xaa}, | ||
2574 | {0x00, 0x83, 0x55, 0xaa}, | ||
2575 | {0x00, 0x84, 0x06, 0xaa}, | ||
2576 | {0x00, 0x85, 0x06, 0xaa}, | ||
2577 | {0x00, 0x8b, 0x25, 0xaa}, | ||
2578 | {0x00, 0x8c, 0x00, 0xaa}, | ||
2579 | {0x00, 0x8d, 0x86, 0xaa}, | ||
2580 | {0x00, 0x8e, 0x82, 0xaa}, | ||
2581 | {0x00, 0x8f, 0x2d, 0xaa}, | ||
2582 | {0x00, 0x90, 0x8b, 0xaa}, | ||
2583 | {0x00, 0x91, 0x81, 0xaa}, | ||
2584 | {0x00, 0x92, 0x81, 0xaa}, | ||
2585 | {0x00, 0x93, 0x23, 0xaa}, | ||
2586 | {0x00, 0xa3, 0x2a, 0xaa}, | ||
2587 | {0x00, 0xa4, 0x03, 0xaa}, | ||
2588 | {0x00, 0xa5, 0xea, 0xaa}, | ||
2589 | {0x00, 0xb0, 0x68, 0xaa}, | ||
2590 | {0x00, 0xbc, 0x04, 0xaa}, | ||
2591 | {0x00, 0xbe, 0x3b, 0xaa}, | ||
2592 | {0x00, 0x4e, 0x40, 0xaa}, | ||
2593 | {0x00, 0x06, 0x04, 0xaa}, | ||
2594 | {0x00, 0x07, 0x03, 0xaa}, | ||
2595 | {0x00, 0xcd, 0x18, 0xaa}, | ||
2596 | {0x00, 0x28, 0x03, 0xaa}, | ||
2597 | {0x00, 0x29, 0xef, 0xaa}, | ||
2598 | /* reinit on alt 2 (qvga) or alt7 (vga) */ | ||
2599 | {0xb3, 0x05, 0x00, 0xcc}, | ||
2600 | {0xb3, 0x06, 0x00, 0xcc}, | ||
2601 | {0xb8, 0x00, 0x01, 0xcc}, | ||
2602 | |||
2603 | {0x00, 0x1d, 0x85, 0xaa}, | ||
2604 | {0x00, 0x1e, 0xc6, 0xaa}, | ||
2605 | {0x00, 0x00, 0x40, 0xdd}, | ||
2606 | {0x00, 0x1d, 0x05, 0xaa}, | ||
2607 | |||
2608 | {0x00, 0xd6, 0x22, 0xaa}, /* gamma 0 */ | ||
2609 | {0x00, 0x73, 0x00, 0xaa}, | ||
2610 | {0x00, 0x74, 0x0a, 0xaa}, | ||
2611 | {0x00, 0x75, 0x16, 0xaa}, | ||
2612 | {0x00, 0x76, 0x25, 0xaa}, | ||
2613 | {0x00, 0x77, 0x34, 0xaa}, | ||
2614 | {0x00, 0x78, 0x49, 0xaa}, | ||
2615 | {0x00, 0x79, 0x5a, 0xaa}, | ||
2616 | {0x00, 0x7a, 0x7f, 0xaa}, | ||
2617 | {0x00, 0x7b, 0x9b, 0xaa}, | ||
2618 | {0x00, 0x7c, 0xba, 0xaa}, | ||
2619 | {0x00, 0x7d, 0xd4, 0xaa}, | ||
2620 | {0x00, 0x7e, 0xea, 0xaa}, | ||
2621 | |||
2622 | {0x00, 0xd6, 0x62, 0xaa}, /* gamma 1 */ | ||
2623 | {0x00, 0x73, 0x00, 0xaa}, | ||
2624 | {0x00, 0x74, 0x0a, 0xaa}, | ||
2625 | {0x00, 0x75, 0x16, 0xaa}, | ||
2626 | {0x00, 0x76, 0x25, 0xaa}, | ||
2627 | {0x00, 0x77, 0x34, 0xaa}, | ||
2628 | {0x00, 0x78, 0x49, 0xaa}, | ||
2629 | {0x00, 0x79, 0x5a, 0xaa}, | ||
2630 | {0x00, 0x7a, 0x7f, 0xaa}, | ||
2631 | {0x00, 0x7b, 0x9b, 0xaa}, | ||
2632 | {0x00, 0x7c, 0xba, 0xaa}, | ||
2633 | {0x00, 0x7d, 0xd4, 0xaa}, | ||
2634 | {0x00, 0x7e, 0xea, 0xaa}, | ||
2635 | |||
2636 | {0x00, 0xd6, 0xa2, 0xaa}, /* gamma 2 */ | ||
2637 | {0x00, 0x73, 0x00, 0xaa}, | ||
2638 | {0x00, 0x74, 0x0a, 0xaa}, | ||
2639 | {0x00, 0x75, 0x16, 0xaa}, | ||
2640 | {0x00, 0x76, 0x25, 0xaa}, | ||
2641 | {0x00, 0x77, 0x34, 0xaa}, | ||
2642 | {0x00, 0x78, 0x49, 0xaa}, | ||
2643 | {0x00, 0x79, 0x5a, 0xaa}, | ||
2644 | {0x00, 0x7a, 0x7f, 0xaa}, | ||
2645 | {0x00, 0x7b, 0x9b, 0xaa}, | ||
2646 | {0x00, 0x7c, 0xba, 0xaa}, | ||
2647 | {0x00, 0x7d, 0xd4, 0xaa}, | ||
2648 | {0x00, 0x7e, 0xea, 0xaa}, | ||
2649 | |||
2650 | {0x00, 0xaa, 0xff, 0xaa}, /* back light comp */ | ||
2651 | {0x00, 0xc4, 0x03, 0xaa}, | ||
2652 | {0x00, 0xc5, 0x19, 0xaa}, | ||
2653 | {0x00, 0xc6, 0x03, 0xaa}, | ||
2654 | {0x00, 0xc7, 0x91, 0xaa}, | ||
2655 | {0x00, 0xc8, 0x01, 0xaa}, | ||
2656 | {0x00, 0xc9, 0xdd, 0xaa}, | ||
2657 | {0x00, 0xca, 0x02, 0xaa}, | ||
2658 | {0x00, 0xcb, 0x37, 0xaa}, | ||
2659 | |||
2660 | /* read d1 */ | ||
2661 | {0x00, 0xd1, 0x3c, 0xaa}, | ||
2662 | {0x00, 0xb8, 0x28, 0xaa}, | ||
2663 | {0x00, 0xb9, 0x1e, 0xaa}, | ||
2664 | {0x00, 0xb6, 0x14, 0xaa}, | ||
2665 | {0x00, 0xb7, 0x0f, 0xaa}, | ||
2666 | {0x00, 0x5c, 0x10, 0xaa}, | ||
2667 | {0x00, 0x5d, 0x18, 0xaa}, | ||
2668 | {0x00, 0x5e, 0x24, 0xaa}, | ||
2669 | {0x00, 0x5f, 0x24, 0xaa}, | ||
2670 | {0x00, 0x86, 0x1a, 0xaa}, | ||
2671 | {0x00, 0x60, 0x00, 0xaa}, | ||
2672 | {0x00, 0x61, 0x1b, 0xaa}, | ||
2673 | {0x00, 0x62, 0x30, 0xaa}, | ||
2674 | {0x00, 0x63, 0x40, 0xaa}, | ||
2675 | {0x00, 0x87, 0x1a, 0xaa}, | ||
2676 | {0x00, 0x64, 0x00, 0xaa}, | ||
2677 | {0x00, 0x65, 0x08, 0xaa}, | ||
2678 | {0x00, 0x66, 0x10, 0xaa}, | ||
2679 | {0x00, 0x67, 0x20, 0xaa}, | ||
2680 | {0x00, 0x88, 0x10, 0xaa}, | ||
2681 | {0x00, 0x68, 0x00, 0xaa}, | ||
2682 | {0x00, 0x69, 0x08, 0xaa}, | ||
2683 | {0x00, 0x6a, 0x0f, 0xaa}, | ||
2684 | {0x00, 0x6b, 0x0f, 0xaa}, | ||
2685 | {0x00, 0x89, 0x07, 0xaa}, | ||
2686 | {0x00, 0xd5, 0x4c, 0xaa}, | ||
2687 | {0x00, 0x0a, 0x00, 0xaa}, | ||
2688 | {0x00, 0x0b, 0x2a, 0xaa}, | ||
2689 | {0x00, 0x0e, 0x03, 0xaa}, | ||
2690 | {0x00, 0x0f, 0xea, 0xaa}, | ||
2691 | {0x00, 0xa2, 0x00, 0xaa}, | ||
2692 | {0x00, 0xa3, 0x2a, 0xaa}, | ||
2693 | {0x00, 0xa4, 0x03, 0xaa}, | ||
2694 | {0x00, 0xa5, 0xea, 0xaa}, | ||
2695 | {} | ||
2696 | }; | ||
2697 | static const u8 poxxxx_initVGA[][4] = { | ||
2698 | {0x00, 0x20, 0x11, 0xaa}, | ||
2699 | {0x00, 0x33, 0x38, 0xaa}, | ||
2700 | {0x00, 0xbb, 0x0d, 0xaa}, | ||
2701 | {0xb3, 0x22, 0x01, 0xcc}, | ||
2702 | {0xb3, 0x23, 0xe0, 0xcc}, | ||
2703 | {0xb3, 0x16, 0x02, 0xcc}, | ||
2704 | {0xb3, 0x17, 0x7f, 0xcc}, | ||
2705 | {0xb3, 0x02, 0xb0, 0xcc}, | ||
2706 | {0xb3, 0x06, 0x00, 0xcc}, | ||
2707 | {0xb3, 0x5c, 0x01, 0xcc}, | ||
2708 | {0x00, 0x04, 0x06, 0xaa}, | ||
2709 | {0x00, 0x05, 0x3f, 0xaa}, | ||
2710 | {0x00, 0x04, 0x00, 0xdd}, /* delay 1s */ | ||
2711 | {} | ||
2712 | }; | ||
2713 | static const u8 poxxxx_initQVGA[][4] = { | ||
2714 | {0x00, 0x20, 0x33, 0xaa}, | ||
2715 | {0x00, 0x33, 0x38, 0xaa}, | ||
2716 | {0x00, 0xbb, 0x0d, 0xaa}, | ||
2717 | {0xb3, 0x22, 0x00, 0xcc}, | ||
2718 | {0xb3, 0x23, 0xf0, 0xcc}, | ||
2719 | {0xb3, 0x16, 0x01, 0xcc}, | ||
2720 | {0xb3, 0x17, 0x3f, 0xcc}, | ||
2721 | {0xb3, 0x02, 0xb0, 0xcc}, | ||
2722 | {0xb3, 0x06, 0x01, 0xcc}, | ||
2723 | {0xb3, 0x5c, 0x00, 0xcc}, | ||
2724 | {0x00, 0x04, 0x06, 0xaa}, | ||
2725 | {0x00, 0x05, 0x3f, 0xaa}, | ||
2726 | {0x00, 0x04, 0x00, 0xdd}, /* delay 1s */ | ||
2727 | {} | ||
2728 | }; | ||
2729 | static const u8 poxxxx_init_end_1[][4] = { | ||
2730 | {0x00, 0x47, 0x25, 0xaa}, | ||
2731 | {0x00, 0x48, 0x80, 0xaa}, | ||
2732 | {0x00, 0x49, 0x1f, 0xaa}, | ||
2733 | {0x00, 0x4a, 0x40, 0xaa}, | ||
2734 | {0x00, 0x44, 0x40, 0xaa}, | ||
2735 | {0x00, 0xab, 0x4a, 0xaa}, | ||
2736 | {0x00, 0xb1, 0x00, 0xaa}, | ||
2737 | {0x00, 0xb2, 0x04, 0xaa}, | ||
2738 | {0x00, 0xb3, 0x08, 0xaa}, | ||
2739 | {0x00, 0xb4, 0x0b, 0xaa}, | ||
2740 | {0x00, 0xb5, 0x0d, 0xaa}, | ||
2741 | {0x00, 0x59, 0x7e, 0xaa}, /* sharpness */ | ||
2742 | {0x00, 0x16, 0x00, 0xaa}, /* white balance */ | ||
2743 | {0x00, 0x18, 0x00, 0xaa}, | ||
2744 | {} | ||
2745 | }; | ||
2746 | static const u8 poxxxx_init_end_2[][4] = { | ||
2747 | {0x00, 0x1d, 0x85, 0xaa}, | ||
2748 | {0x00, 0x1e, 0x06, 0xaa}, | ||
2749 | {0x00, 0x1d, 0x05, 0xaa}, | ||
2750 | {} | ||
2411 | }; | 2751 | }; |
2412 | 2752 | ||
2413 | struct sensor_info { | 2753 | struct sensor_info { |
@@ -2420,33 +2760,89 @@ struct sensor_info { | |||
2420 | u8 op; | 2760 | u8 op; |
2421 | }; | 2761 | }; |
2422 | 2762 | ||
2423 | static const struct sensor_info sensor_info_data[] = { | 2763 | /* probe values */ |
2424 | /* sensorId, I2cAdd, IdAdd, VpId, m1, m2, op */ | 2764 | static const struct sensor_info vc0321_probe_data[] = { |
2765 | /* sensorId, I2cAdd, IdAdd, VpId, m1, m2, op */ | ||
2766 | /* 0 OV9640 */ | ||
2425 | {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05}, | 2767 | {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05}, |
2768 | /* 1 ICM108T (may respond on IdAdd == 0x83 - tested in vc032x_probe_sensor) */ | ||
2426 | {-1, 0x80 | 0x20, 0x82, 0x0000, 0x24, 0x25, 0x01}, | 2769 | {-1, 0x80 | 0x20, 0x82, 0x0000, 0x24, 0x25, 0x01}, |
2427 | /* (tested in vc032x_probe_sensor) */ | 2770 | /* 2 PO2130 (may detect PO3130NC - tested in vc032x_probe_sensor)*/ |
2428 | /* {-1, 0x80 | 0x20, 0x83, 0x0000, 0x24, 0x25, 0x01}, */ | 2771 | {-1, 0x80 | 0x76, 0x00, 0x0000, 0x24, 0x25, 0x01}, |
2429 | {SENSOR_PO3130NC, 0x80 | 0x76, 0x00, 0x3130, 0x24, 0x25, 0x01}, | 2772 | /* 3 MI1310 */ |
2773 | {-1, 0x80 | 0x5d, 0x00, 0x0000, 0x24, 0x25, 0x01}, | ||
2774 | /* 4 MI360 - tested in vc032x_probe_sensor */ | ||
2775 | /* {SENSOR_MI0360, 0x80 | 0x5d, 0x00, 0x8243, 0x24, 0x25, 0x01}, */ | ||
2776 | /* 5 7131R */ | ||
2777 | {SENSOR_HV7131R, 0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01}, | ||
2778 | /* 6 OV7649 */ | ||
2779 | {-1, 0x80 | 0x21, 0x0a, 0x0000, 0x21, 0x20, 0x05}, | ||
2780 | /* 7 PAS302BCW */ | ||
2781 | {-1, 0x80 | 0x40, 0x00, 0x0000, 0x20, 0x22, 0x05}, | ||
2782 | /* 8 OV7660 */ | ||
2783 | {SENSOR_OV7660, 0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05}, | ||
2784 | /* 9 PO3130NC - (tested in vc032x_probe_sensor) */ | ||
2785 | /* {SENSOR_PO3130NC, 0x80 | 0x76, 0x00, 0x3130, 0x24, 0x25, 0x01}, */ | ||
2786 | /* 10 PO1030KC */ | ||
2787 | {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01}, | ||
2788 | /* 11 MI1310_SOC */ | ||
2430 | {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01}, | 2789 | {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01}, |
2431 | /* (tested in vc032x_probe_sensor) */ | 2790 | /* 12 OV9650 */ |
2791 | {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05}, | ||
2792 | /* 13 S5K532 */ | ||
2793 | {-1, 0x80 | 0x11, 0x39, 0x0000, 0x24, 0x25, 0x01}, | ||
2794 | /* 14 MI360_SOC - ??? */ | ||
2795 | /* 15 PO1200N */ | ||
2796 | {SENSOR_PO1200, 0x80 | 0x5c, 0x00, 0x1200, 0x67, 0x67, 0x01}, | ||
2797 | /* 16 PO3030K */ | ||
2798 | {-1, 0x80 | 0x18, 0x00, 0x0000, 0x24, 0x25, 0x01}, | ||
2799 | /* 17 PO2030 */ | ||
2800 | {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01}, | ||
2801 | /* ?? */ | ||
2802 | {-1, 0x80 | 0x56, 0x01, 0x0000, 0x64, 0x67, 0x01}, | ||
2803 | {SENSOR_MI1320, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x65, 0x01}, | ||
2804 | }; | ||
2805 | static const struct sensor_info vc0323_probe_data[] = { | ||
2806 | /* sensorId, I2cAdd, IdAdd, VpId, m1, m2, op */ | ||
2807 | /* 0 OV9640 */ | ||
2808 | {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05}, | ||
2809 | /* 1 ICM108T (may respond on IdAdd == 0x83 - tested in vc032x_probe_sensor) */ | ||
2810 | {-1, 0x80 | 0x20, 0x82, 0x0000, 0x24, 0x25, 0x01}, | ||
2811 | /* 2 PO2130 (may detect PO3130NC - tested in vc032x_probe_sensor)*/ | ||
2812 | {-1, 0x80 | 0x76, 0x00, 0x0000, 0x24, 0x25, 0x01}, | ||
2813 | /* 3 MI1310 */ | ||
2814 | {-1, 0x80 | 0x5d, 0x00, 0x0000, 0x24, 0x25, 0x01}, | ||
2815 | /* 4 MI360 - tested in vc032x_probe_sensor */ | ||
2432 | /* {SENSOR_MI0360, 0x80 | 0x5d, 0x00, 0x8243, 0x24, 0x25, 0x01}, */ | 2816 | /* {SENSOR_MI0360, 0x80 | 0x5d, 0x00, 0x8243, 0x24, 0x25, 0x01}, */ |
2817 | /* 5 7131R */ | ||
2433 | {SENSOR_HV7131R, 0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01}, | 2818 | {SENSOR_HV7131R, 0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01}, |
2819 | /* 6 OV7649 */ | ||
2434 | {-1, 0x80 | 0x21, 0x0a, 0x0000, 0x21, 0x20, 0x05}, | 2820 | {-1, 0x80 | 0x21, 0x0a, 0x0000, 0x21, 0x20, 0x05}, |
2821 | /* 7 PAS302BCW */ | ||
2435 | {-1, 0x80 | 0x40, 0x00, 0x0000, 0x20, 0x22, 0x05}, | 2822 | {-1, 0x80 | 0x40, 0x00, 0x0000, 0x20, 0x22, 0x05}, |
2823 | /* 8 OV7660 */ | ||
2436 | {SENSOR_OV7660, 0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05}, | 2824 | {SENSOR_OV7660, 0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05}, |
2437 | /* {SENSOR_PO3130NC, 0x80 | 0x76, 0x00, 0x0000, 0x24, 0x25, 0x01}, */ | 2825 | /* 9 PO3130NC - (tested in vc032x_probe_sensor) */ |
2826 | /* {SENSOR_PO3130NC, 0x80 | 0x76, 0x00, 0x3130, 0x24, 0x25, 0x01}, */ | ||
2827 | /* 10 PO1030KC */ | ||
2438 | {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01}, | 2828 | {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01}, |
2439 | /* {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x0000, 0x24, 0x25, 0x01}, */ | 2829 | /* 11 MI1310_SOC */ |
2440 | /* {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05}, */ | 2830 | {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01}, |
2831 | /* 12 OV9650 */ | ||
2832 | {-1, 0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05}, | ||
2833 | /* 13 S5K532 */ | ||
2441 | {-1, 0x80 | 0x11, 0x39, 0x0000, 0x24, 0x25, 0x01}, | 2834 | {-1, 0x80 | 0x11, 0x39, 0x0000, 0x24, 0x25, 0x01}, |
2835 | /* 14 MI360_SOC - ??? */ | ||
2836 | /* 15 PO1200N */ | ||
2442 | {SENSOR_PO1200, 0x80 | 0x5c, 0x00, 0x1200, 0x67, 0x67, 0x01}, | 2837 | {SENSOR_PO1200, 0x80 | 0x5c, 0x00, 0x1200, 0x67, 0x67, 0x01}, |
2838 | /* 16 ?? */ | ||
2443 | {-1, 0x80 | 0x2d, 0x00, 0x0000, 0x65, 0x67, 0x01}, | 2839 | {-1, 0x80 | 0x2d, 0x00, 0x0000, 0x65, 0x67, 0x01}, |
2840 | /* 17 PO2030 */ | ||
2444 | {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01}, | 2841 | {-1, 0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01}, |
2842 | /* ?? */ | ||
2445 | {-1, 0x80 | 0x56, 0x01, 0x0000, 0x64, 0x67, 0x01}, | 2843 | {-1, 0x80 | 0x56, 0x01, 0x0000, 0x64, 0x67, 0x01}, |
2446 | {SENSOR_MI1320_SOC, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x67, 0x01}, | 2844 | {SENSOR_MI1320_SOC, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x67, 0x01}, |
2447 | /*fixme: previously detected?*/ | 2845 | /*fixme: not in the ms-win probe - may be found before? */ |
2448 | {SENSOR_MI1320, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x65, 0x01}, | ||
2449 | /*fixme: not in the ms-win probe - may be found before?*/ | ||
2450 | {SENSOR_OV7670, 0x80 | 0x21, 0x0a, 0x7673, 0x66, 0x67, 0x05}, | 2846 | {SENSOR_OV7670, 0x80 | 0x21, 0x0a, 0x7673, 0x66, 0x67, 0x05}, |
2451 | }; | 2847 | }; |
2452 | 2848 | ||
@@ -2520,7 +2916,7 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) | |||
2520 | { | 2916 | { |
2521 | struct sd *sd = (struct sd *) gspca_dev; | 2917 | struct sd *sd = (struct sd *) gspca_dev; |
2522 | struct usb_device *dev = gspca_dev->dev; | 2918 | struct usb_device *dev = gspca_dev->dev; |
2523 | int i; | 2919 | int i, n; |
2524 | u16 value; | 2920 | u16 value; |
2525 | const struct sensor_info *ptsensor_info; | 2921 | const struct sensor_info *ptsensor_info; |
2526 | 2922 | ||
@@ -2531,9 +2927,16 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) | |||
2531 | } | 2927 | } |
2532 | 2928 | ||
2533 | reg_r(gspca_dev, 0xa1, 0xbfcf, 1); | 2929 | reg_r(gspca_dev, 0xa1, 0xbfcf, 1); |
2534 | PDEBUG(D_PROBE, "check sensor header %02x", gspca_dev->usb_buf[0]); | 2930 | PDEBUG(D_PROBE, "vc032%d check sensor header %02x", |
2535 | for (i = 0; i < ARRAY_SIZE(sensor_info_data); i++) { | 2931 | sd->bridge == BRIDGE_VC0321 ? 1 : 3, gspca_dev->usb_buf[0]); |
2536 | ptsensor_info = &sensor_info_data[i]; | 2932 | if (sd->bridge == BRIDGE_VC0321) { |
2933 | ptsensor_info = vc0321_probe_data; | ||
2934 | n = ARRAY_SIZE(vc0321_probe_data); | ||
2935 | } else { | ||
2936 | ptsensor_info = vc0323_probe_data; | ||
2937 | n = ARRAY_SIZE(vc0323_probe_data); | ||
2938 | } | ||
2939 | for (i = 0; i < n; i++) { | ||
2537 | reg_w(dev, 0xa0, 0x02, 0xb334); | 2940 | reg_w(dev, 0xa0, 0x02, 0xb334); |
2538 | reg_w(dev, 0xa0, ptsensor_info->m1, 0xb300); | 2941 | reg_w(dev, 0xa0, ptsensor_info->m1, 0xb300); |
2539 | reg_w(dev, 0xa0, ptsensor_info->m2, 0xb300); | 2942 | reg_w(dev, 0xa0, ptsensor_info->m2, 0xb300); |
@@ -2551,13 +2954,15 @@ static int vc032x_probe_sensor(struct gspca_dev *gspca_dev) | |||
2551 | return ptsensor_info->sensorId; | 2954 | return ptsensor_info->sensorId; |
2552 | 2955 | ||
2553 | switch (value) { | 2956 | switch (value) { |
2957 | case 0x3130: | ||
2958 | return SENSOR_PO3130NC; | ||
2554 | case 0x7673: | 2959 | case 0x7673: |
2555 | return SENSOR_OV7670; | 2960 | return SENSOR_OV7670; |
2556 | case 0x8243: | 2961 | case 0x8243: |
2557 | return SENSOR_MI0360; | 2962 | return SENSOR_MI0360; |
2558 | } | 2963 | } |
2559 | /*fixme: should return here*/ | ||
2560 | } | 2964 | } |
2965 | ptsensor_info++; | ||
2561 | } | 2966 | } |
2562 | return -1; | 2967 | return -1; |
2563 | } | 2968 | } |
@@ -2619,7 +3024,7 @@ static void usb_exchange(struct gspca_dev *gspca_dev, | |||
2619 | i2c_write(gspca_dev, data[i][0], &data[i][1], 2); | 3024 | i2c_write(gspca_dev, data[i][0], &data[i][1], 2); |
2620 | break; | 3025 | break; |
2621 | case 0xdd: | 3026 | case 0xdd: |
2622 | msleep(data[i][2] + 10); | 3027 | msleep(data[i][1] * 256 + data[i][2] + 10); |
2623 | break; | 3028 | break; |
2624 | } | 3029 | } |
2625 | i++; | 3030 | i++; |
@@ -2646,12 +3051,17 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
2646 | 64, /* OV7670 6 */ | 3051 | 64, /* OV7670 6 */ |
2647 | 128, /* PO1200 7 */ | 3052 | 128, /* PO1200 7 */ |
2648 | 128, /* PO3130NC 8 */ | 3053 | 128, /* PO3130NC 8 */ |
3054 | 128, /* POxxxx 9 */ | ||
2649 | }; | 3055 | }; |
2650 | 3056 | ||
2651 | cam = &gspca_dev->cam; | 3057 | cam = &gspca_dev->cam; |
2652 | sd->bridge = id->driver_info >> 8; | 3058 | sd->bridge = id->driver_info >> 8; |
2653 | sd->flags = id->driver_info & 0xff; | 3059 | sd->flags = id->driver_info & 0xff; |
2654 | sensor = vc032x_probe_sensor(gspca_dev); | 3060 | if (id->idVendor == 0x046d && |
3061 | (id->idProduct == 0x0892 || id->idProduct == 0x0896)) | ||
3062 | sensor = SENSOR_POxxxx; | ||
3063 | else | ||
3064 | sensor = vc032x_probe_sensor(gspca_dev); | ||
2655 | switch (sensor) { | 3065 | switch (sensor) { |
2656 | case -1: | 3066 | case -1: |
2657 | PDEBUG(D_PROBE, "Unknown sensor..."); | 3067 | PDEBUG(D_PROBE, "Unknown sensor..."); |
@@ -2684,6 +3094,9 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
2684 | case SENSOR_PO3130NC: | 3094 | case SENSOR_PO3130NC: |
2685 | PDEBUG(D_PROBE, "Find Sensor PO3130NC"); | 3095 | PDEBUG(D_PROBE, "Find Sensor PO3130NC"); |
2686 | break; | 3096 | break; |
3097 | case SENSOR_POxxxx: | ||
3098 | PDEBUG(D_PROBE, "Sensor POxxxx"); | ||
3099 | break; | ||
2687 | } | 3100 | } |
2688 | sd->sensor = sensor; | 3101 | sd->sensor = sensor; |
2689 | 3102 | ||
@@ -2712,28 +3125,19 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
2712 | } | 3125 | } |
2713 | cam->npkt = npkt[sd->sensor]; | 3126 | cam->npkt = npkt[sd->sensor]; |
2714 | 3127 | ||
3128 | sd->brightness = BRIGHTNESS_DEF; | ||
3129 | sd->contrast = CONTRAST_DEF; | ||
3130 | sd->colors = COLOR_DEF; | ||
2715 | sd->hflip = HFLIP_DEF; | 3131 | sd->hflip = HFLIP_DEF; |
2716 | sd->vflip = VFLIP_DEF; | 3132 | sd->vflip = VFLIP_DEF; |
2717 | if (sd->sensor == SENSOR_OV7670) | ||
2718 | sd->flags |= FL_HFLIP | FL_VFLIP; | ||
2719 | sd->lightfreq = FREQ_DEF; | 3133 | sd->lightfreq = FREQ_DEF; |
2720 | if (sd->sensor != SENSOR_OV7670) | ||
2721 | gspca_dev->ctrl_dis = (1 << LIGHTFREQ_IDX); | ||
2722 | switch (sd->sensor) { | ||
2723 | case SENSOR_MI1310_SOC: | ||
2724 | case SENSOR_MI1320_SOC: | ||
2725 | case SENSOR_OV7660: | ||
2726 | case SENSOR_OV7670: | ||
2727 | case SENSOR_PO1200: | ||
2728 | break; | ||
2729 | default: | ||
2730 | gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | ||
2731 | | (1 << VFLIP_IDX); | ||
2732 | break; | ||
2733 | } | ||
2734 | |||
2735 | sd->sharpness = SHARPNESS_DEF; | 3134 | sd->sharpness = SHARPNESS_DEF; |
2736 | 3135 | ||
3136 | gspca_dev->ctrl_dis = ctrl_dis[sd->sensor]; | ||
3137 | |||
3138 | if (sd->sensor == SENSOR_OV7670) | ||
3139 | sd->flags |= FL_HFLIP | FL_VFLIP; | ||
3140 | |||
2737 | if (sd->bridge == BRIDGE_VC0321) { | 3141 | if (sd->bridge == BRIDGE_VC0321) { |
2738 | reg_r(gspca_dev, 0x8a, 0, 3); | 3142 | reg_r(gspca_dev, 0x8a, 0, 3); |
2739 | reg_w(dev, 0x87, 0x00, 0x0f0f); | 3143 | reg_w(dev, 0x87, 0x00, 0x0f0f); |
@@ -2747,10 +3151,55 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
2747 | /* this function is called at probe and resume time */ | 3151 | /* this function is called at probe and resume time */ |
2748 | static int sd_init(struct gspca_dev *gspca_dev) | 3152 | static int sd_init(struct gspca_dev *gspca_dev) |
2749 | { | 3153 | { |
3154 | struct sd *sd = (struct sd *) gspca_dev; | ||
3155 | |||
3156 | if (sd->sensor == SENSOR_POxxxx) { | ||
3157 | reg_r(gspca_dev, 0xa1, 0xb300, 1); | ||
3158 | if (gspca_dev->usb_buf[0] != 0) { | ||
3159 | reg_w(gspca_dev->dev, 0xa0, 0x26, 0xb300); | ||
3160 | reg_w(gspca_dev->dev, 0xa0, 0x04, 0xb300); | ||
3161 | reg_w(gspca_dev->dev, 0xa0, 0x00, 0xb300); | ||
3162 | } | ||
3163 | } | ||
2750 | return 0; | 3164 | return 0; |
2751 | } | 3165 | } |
2752 | 3166 | ||
2753 | /* some sensors only */ | 3167 | static void setbrightness(struct gspca_dev *gspca_dev) |
3168 | { | ||
3169 | struct sd *sd = (struct sd *) gspca_dev; | ||
3170 | u8 data; | ||
3171 | |||
3172 | if (gspca_dev->ctrl_dis & (1 << BRIGHTNESS_IDX)) | ||
3173 | return; | ||
3174 | data = sd->brightness; | ||
3175 | if (data >= 0x80) | ||
3176 | data &= 0x7f; | ||
3177 | else | ||
3178 | data = 0xff ^ data; | ||
3179 | i2c_write(gspca_dev, 0x98, &data, 1); | ||
3180 | } | ||
3181 | |||
3182 | static void setcontrast(struct gspca_dev *gspca_dev) | ||
3183 | { | ||
3184 | struct sd *sd = (struct sd *) gspca_dev; | ||
3185 | |||
3186 | if (gspca_dev->ctrl_dis & (1 << CONTRAST_IDX)) | ||
3187 | return; | ||
3188 | i2c_write(gspca_dev, 0x99, &sd->contrast, 1); | ||
3189 | } | ||
3190 | |||
3191 | static void setcolors(struct gspca_dev *gspca_dev) | ||
3192 | { | ||
3193 | struct sd *sd = (struct sd *) gspca_dev; | ||
3194 | u8 data; | ||
3195 | |||
3196 | if (gspca_dev->ctrl_dis & (1 << COLORS_IDX)) | ||
3197 | return; | ||
3198 | data = sd->colors - (sd->colors >> 3) - 1; | ||
3199 | i2c_write(gspca_dev, 0x94, &data, 1); | ||
3200 | i2c_write(gspca_dev, 0x95, &sd->colors, 1); | ||
3201 | } | ||
3202 | |||
2754 | static void sethvflip(struct gspca_dev *gspca_dev) | 3203 | static void sethvflip(struct gspca_dev *gspca_dev) |
2755 | { | 3204 | { |
2756 | struct sd *sd = (struct sd *) gspca_dev; | 3205 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -2764,6 +3213,7 @@ static void sethvflip(struct gspca_dev *gspca_dev) | |||
2764 | vflip = !vflip; | 3213 | vflip = !vflip; |
2765 | switch (sd->sensor) { | 3214 | switch (sd->sensor) { |
2766 | case SENSOR_MI1310_SOC: | 3215 | case SENSOR_MI1310_SOC: |
3216 | case SENSOR_MI1320: | ||
2767 | case SENSOR_MI1320_SOC: | 3217 | case SENSOR_MI1320_SOC: |
2768 | data[0] = data[1] = 0; /* select page 0 */ | 3218 | data[0] = data[1] = 0; /* select page 0 */ |
2769 | i2c_write(gspca_dev, 0xf0, data, 2); | 3219 | i2c_write(gspca_dev, 0xf0, data, 2); |
@@ -2801,18 +3251,29 @@ static void setlightfreq(struct gspca_dev *gspca_dev) | |||
2801 | usb_exchange(gspca_dev, ov7660_freq_tb[sd->lightfreq]); | 3251 | usb_exchange(gspca_dev, ov7660_freq_tb[sd->lightfreq]); |
2802 | } | 3252 | } |
2803 | 3253 | ||
2804 | /* po1200 only */ | ||
2805 | static void setsharpness(struct gspca_dev *gspca_dev) | 3254 | static void setsharpness(struct gspca_dev *gspca_dev) |
2806 | { | 3255 | { |
2807 | struct sd *sd = (struct sd *) gspca_dev; | 3256 | struct sd *sd = (struct sd *) gspca_dev; |
2808 | u8 data; | 3257 | u8 data; |
2809 | 3258 | ||
2810 | if (sd->sensor != SENSOR_PO1200) | 3259 | switch (sd->sensor) { |
2811 | return; | 3260 | case SENSOR_PO1200: |
2812 | data = 0; | 3261 | data = 0; |
2813 | i2c_write(gspca_dev, 0x03, &data, 1); | 3262 | i2c_write(gspca_dev, 0x03, &data, 1); |
2814 | data = 0xb5 + sd->sharpness * 3; | 3263 | if (sd->sharpness < 0) |
2815 | i2c_write(gspca_dev, 0x61, &data, 1); | 3264 | data = 0x6a; |
3265 | else | ||
3266 | data = 0xb5 + sd->sharpness * 3; | ||
3267 | i2c_write(gspca_dev, 0x61, &data, 1); | ||
3268 | break; | ||
3269 | case SENSOR_POxxxx: | ||
3270 | if (sd->sharpness < 0) | ||
3271 | data = 0x7e; /* def = max */ | ||
3272 | else | ||
3273 | data = 0x60 + sd->sharpness * 0x0f; | ||
3274 | i2c_write(gspca_dev, 0x59, &data, 1); | ||
3275 | break; | ||
3276 | } | ||
2816 | } | 3277 | } |
2817 | 3278 | ||
2818 | static int sd_start(struct gspca_dev *gspca_dev) | 3279 | static int sd_start(struct gspca_dev *gspca_dev) |
@@ -2922,12 +3383,27 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2922 | usb_exchange(gspca_dev, init); | 3383 | usb_exchange(gspca_dev, init); |
2923 | init = po3130_rundata; | 3384 | init = po3130_rundata; |
2924 | break; | 3385 | break; |
2925 | default: | 3386 | case SENSOR_PO1200: |
2926 | /* case SENSOR_PO1200: */ | ||
2927 | GammaT = po1200_gamma; | 3387 | GammaT = po1200_gamma; |
2928 | MatrixT = po1200_matrix; | 3388 | MatrixT = po1200_matrix; |
2929 | init = po1200_initVGA_data; | 3389 | init = po1200_initVGA_data; |
2930 | break; | 3390 | break; |
3391 | default: | ||
3392 | /* case SENSOR_POxxxx: */ | ||
3393 | usb_exchange(gspca_dev, poxxxx_init_common); | ||
3394 | if (mode) | ||
3395 | init = poxxxx_initQVGA; | ||
3396 | else | ||
3397 | init = poxxxx_initVGA; | ||
3398 | usb_exchange(gspca_dev, init); | ||
3399 | reg_r(gspca_dev, 0x8c, 0x0000, 3); | ||
3400 | reg_w(gspca_dev->dev, 0xa0, | ||
3401 | gspca_dev->usb_buf[2] & 1 ? 0 : 1, | ||
3402 | 0xb35c); | ||
3403 | msleep(300); | ||
3404 | /*fixme: i2c read 04 and 05*/ | ||
3405 | init = poxxxx_init_end_1; | ||
3406 | break; | ||
2931 | } | 3407 | } |
2932 | usb_exchange(gspca_dev, init); | 3408 | usb_exchange(gspca_dev, init); |
2933 | if (GammaT && MatrixT) { | 3409 | if (GammaT && MatrixT) { |
@@ -2936,7 +3412,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2936 | put_tab_to_reg(gspca_dev, GammaT, 17, 0xb86c); | 3412 | put_tab_to_reg(gspca_dev, GammaT, 17, 0xb86c); |
2937 | put_tab_to_reg(gspca_dev, MatrixT, 9, 0xb82c); | 3413 | put_tab_to_reg(gspca_dev, MatrixT, 9, 0xb82c); |
2938 | 3414 | ||
2939 | /* set the led on 0x0892 0x0896 */ | ||
2940 | switch (sd->sensor) { | 3415 | switch (sd->sensor) { |
2941 | case SENSOR_PO1200: | 3416 | case SENSOR_PO1200: |
2942 | case SENSOR_HV7131R: | 3417 | case SENSOR_HV7131R: |
@@ -2945,16 +3420,22 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2945 | case SENSOR_MI1310_SOC: | 3420 | case SENSOR_MI1310_SOC: |
2946 | reg_w(gspca_dev->dev, 0x89, 0x058c, 0x0000); | 3421 | reg_w(gspca_dev->dev, 0x89, 0x058c, 0x0000); |
2947 | break; | 3422 | break; |
2948 | default: | ||
2949 | if (!(sd->flags & FL_SAMSUNG)) | ||
2950 | reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff); | ||
2951 | break; | ||
2952 | } | 3423 | } |
2953 | msleep(100); | 3424 | msleep(100); |
2954 | setsharpness(gspca_dev); | 3425 | setsharpness(gspca_dev); |
2955 | sethvflip(gspca_dev); | 3426 | sethvflip(gspca_dev); |
2956 | setlightfreq(gspca_dev); | 3427 | setlightfreq(gspca_dev); |
2957 | } | 3428 | } |
3429 | if (sd->sensor == SENSOR_POxxxx) { | ||
3430 | setcolors(gspca_dev); | ||
3431 | setbrightness(gspca_dev); | ||
3432 | setcontrast(gspca_dev); | ||
3433 | |||
3434 | /* led on */ | ||
3435 | msleep(80); | ||
3436 | reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff); | ||
3437 | usb_exchange(gspca_dev, poxxxx_init_end_2); | ||
3438 | } | ||
2958 | return 0; | 3439 | return 0; |
2959 | } | 3440 | } |
2960 | 3441 | ||
@@ -2963,10 +3444,17 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
2963 | struct usb_device *dev = gspca_dev->dev; | 3444 | struct usb_device *dev = gspca_dev->dev; |
2964 | struct sd *sd = (struct sd *) gspca_dev; | 3445 | struct sd *sd = (struct sd *) gspca_dev; |
2965 | 3446 | ||
2966 | if (sd->sensor == SENSOR_MI1310_SOC) | 3447 | switch (sd->sensor) { |
3448 | case SENSOR_MI1310_SOC: | ||
2967 | reg_w(dev, 0x89, 0x058c, 0x00ff); | 3449 | reg_w(dev, 0x89, 0x058c, 0x00ff); |
2968 | else if (!(sd->flags & FL_SAMSUNG)) | 3450 | break; |
2969 | reg_w(dev, 0x89, 0xffff, 0xffff); | 3451 | case SENSOR_POxxxx: |
3452 | return; | ||
3453 | default: | ||
3454 | if (!(sd->flags & FL_SAMSUNG)) | ||
3455 | reg_w(dev, 0x89, 0xffff, 0xffff); | ||
3456 | break; | ||
3457 | } | ||
2970 | reg_w(dev, 0xa0, 0x01, 0xb301); | 3458 | reg_w(dev, 0xa0, 0x01, 0xb301); |
2971 | reg_w(dev, 0xa0, 0x09, 0xb003); | 3459 | reg_w(dev, 0xa0, 0x09, 0xb003); |
2972 | } | 3460 | } |
@@ -2984,6 +3472,12 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
2984 | reg_w(dev, 0x89, 0x058c, 0x00ff); | 3472 | reg_w(dev, 0x89, 0x058c, 0x00ff); |
2985 | else if (!(sd->flags & FL_SAMSUNG)) | 3473 | else if (!(sd->flags & FL_SAMSUNG)) |
2986 | reg_w(dev, 0x89, 0xffff, 0xffff); | 3474 | reg_w(dev, 0x89, 0xffff, 0xffff); |
3475 | |||
3476 | if (sd->sensor == SENSOR_POxxxx) { | ||
3477 | reg_w(dev, 0xa0, 0x26, 0xb300); | ||
3478 | reg_w(dev, 0xa0, 0x04, 0xb300); | ||
3479 | reg_w(dev, 0xa0, 0x00, 0xb300); | ||
3480 | } | ||
2987 | } | 3481 | } |
2988 | 3482 | ||
2989 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 3483 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
@@ -3020,6 +3514,60 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
3020 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | 3514 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
3021 | } | 3515 | } |
3022 | 3516 | ||
3517 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | ||
3518 | { | ||
3519 | struct sd *sd = (struct sd *) gspca_dev; | ||
3520 | |||
3521 | sd->brightness = val; | ||
3522 | if (gspca_dev->streaming) | ||
3523 | setbrightness(gspca_dev); | ||
3524 | return 0; | ||
3525 | } | ||
3526 | |||
3527 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
3528 | { | ||
3529 | struct sd *sd = (struct sd *) gspca_dev; | ||
3530 | |||
3531 | *val = sd->brightness; | ||
3532 | return 0; | ||
3533 | } | ||
3534 | |||
3535 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | ||
3536 | { | ||
3537 | struct sd *sd = (struct sd *) gspca_dev; | ||
3538 | |||
3539 | sd->contrast = val; | ||
3540 | if (gspca_dev->streaming) | ||
3541 | setcontrast(gspca_dev); | ||
3542 | return 0; | ||
3543 | } | ||
3544 | |||
3545 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | ||
3546 | { | ||
3547 | struct sd *sd = (struct sd *) gspca_dev; | ||
3548 | |||
3549 | *val = sd->contrast; | ||
3550 | return 0; | ||
3551 | } | ||
3552 | |||
3553 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) | ||
3554 | { | ||
3555 | struct sd *sd = (struct sd *) gspca_dev; | ||
3556 | |||
3557 | sd->colors = val; | ||
3558 | if (gspca_dev->streaming) | ||
3559 | setcolors(gspca_dev); | ||
3560 | return 0; | ||
3561 | } | ||
3562 | |||
3563 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) | ||
3564 | { | ||
3565 | struct sd *sd = (struct sd *) gspca_dev; | ||
3566 | |||
3567 | *val = sd->colors; | ||
3568 | return 0; | ||
3569 | } | ||
3570 | |||
3023 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) | 3571 | static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val) |
3024 | { | 3572 | { |
3025 | struct sd *sd = (struct sd *) gspca_dev; | 3573 | struct sd *sd = (struct sd *) gspca_dev; |
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 1a800fc1c00e..50986da3d912 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c | |||
@@ -1,9 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Z-Star/Vimicro zc301/zc302p/vc30x library | 2 | * Z-Star/Vimicro zc301/zc302p/vc30x library |
3 | * Copyright (C) 2004 2005 2006 Michel Xhaard | ||
4 | * mxhaard@magic.fr | ||
5 | * | 3 | * |
6 | * V4L2 by Jean-Francois Moine <http://moinejf.free.fr> | 4 | * Copyright (C) 2009-2010 Jean-Francois Moine <http://moinejf.free.fr> |
5 | * Copyright (C) 2004 2005 2006 Michel Xhaard mxhaard@magic.fr | ||
7 | * | 6 | * |
8 | * 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 |
9 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
@@ -22,10 +21,11 @@ | |||
22 | 21 | ||
23 | #define MODULE_NAME "zc3xx" | 22 | #define MODULE_NAME "zc3xx" |
24 | 23 | ||
24 | #include <linux/input.h> | ||
25 | #include "gspca.h" | 25 | #include "gspca.h" |
26 | #include "jpeg.h" | 26 | #include "jpeg.h" |
27 | 27 | ||
28 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>, " | 28 | MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, " |
29 | "Serge A. Suchkov <Serge.A.S@tochka.ru>"); | 29 | "Serge A. Suchkov <Serge.A.S@tochka.ru>"); |
30 | MODULE_DESCRIPTION("GSPCA ZC03xx/VC3xx USB Camera Driver"); | 30 | MODULE_DESCRIPTION("GSPCA ZC03xx/VC3xx USB Camera Driver"); |
31 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
@@ -39,18 +39,18 @@ static int force_sensor = -1; | |||
39 | struct sd { | 39 | struct sd { |
40 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 40 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
41 | 41 | ||
42 | __u8 brightness; | 42 | u8 brightness; |
43 | __u8 contrast; | 43 | u8 contrast; |
44 | __u8 gamma; | 44 | u8 gamma; |
45 | __u8 autogain; | 45 | u8 autogain; |
46 | __u8 lightfreq; | 46 | u8 lightfreq; |
47 | __u8 sharpness; | 47 | u8 sharpness; |
48 | u8 quality; /* image quality */ | 48 | u8 quality; /* image quality */ |
49 | #define QUALITY_MIN 40 | 49 | #define QUALITY_MIN 40 |
50 | #define QUALITY_MAX 60 | 50 | #define QUALITY_MAX 60 |
51 | #define QUALITY_DEF 50 | 51 | #define QUALITY_DEF 50 |
52 | 52 | ||
53 | signed char sensor; /* Type of image sensor chip */ | 53 | u8 sensor; /* Type of image sensor chip */ |
54 | /* !! values used in different tables */ | 54 | /* !! values used in different tables */ |
55 | #define SENSOR_ADCM2700 0 | 55 | #define SENSOR_ADCM2700 0 |
56 | #define SENSOR_CS2102 1 | 56 | #define SENSOR_CS2102 1 |
@@ -92,9 +92,8 @@ static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | |||
92 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); | 92 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); |
93 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | 93 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); |
94 | 94 | ||
95 | static struct ctrl sd_ctrls[] = { | 95 | static const struct ctrl sd_ctrls[] = { |
96 | #define BRIGHTNESS_IDX 0 | 96 | #define BRIGHTNESS_IDX 0 |
97 | #define SD_BRIGHTNESS 0 | ||
98 | { | 97 | { |
99 | { | 98 | { |
100 | .id = V4L2_CID_BRIGHTNESS, | 99 | .id = V4L2_CID_BRIGHTNESS, |
@@ -103,26 +102,26 @@ static struct ctrl sd_ctrls[] = { | |||
103 | .minimum = 0, | 102 | .minimum = 0, |
104 | .maximum = 255, | 103 | .maximum = 255, |
105 | .step = 1, | 104 | .step = 1, |
106 | .default_value = 128, | 105 | #define BRIGHTNESS_DEF 128 |
106 | .default_value = BRIGHTNESS_DEF, | ||
107 | }, | 107 | }, |
108 | .set = sd_setbrightness, | 108 | .set = sd_setbrightness, |
109 | .get = sd_getbrightness, | 109 | .get = sd_getbrightness, |
110 | }, | 110 | }, |
111 | #define SD_CONTRAST 1 | ||
112 | { | 111 | { |
113 | { | 112 | { |
114 | .id = V4L2_CID_CONTRAST, | 113 | .id = V4L2_CID_CONTRAST, |
115 | .type = V4L2_CTRL_TYPE_INTEGER, | 114 | .type = V4L2_CTRL_TYPE_INTEGER, |
116 | .name = "Contrast", | 115 | .name = "Contrast", |
117 | .minimum = 0, | 116 | .minimum = 0, |
118 | .maximum = 256, | 117 | .maximum = 255, |
119 | .step = 1, | 118 | .step = 1, |
120 | .default_value = 128, | 119 | #define CONTRAST_DEF 128 |
120 | .default_value = CONTRAST_DEF, | ||
121 | }, | 121 | }, |
122 | .set = sd_setcontrast, | 122 | .set = sd_setcontrast, |
123 | .get = sd_getcontrast, | 123 | .get = sd_getcontrast, |
124 | }, | 124 | }, |
125 | #define SD_GAMMA 2 | ||
126 | { | 125 | { |
127 | { | 126 | { |
128 | .id = V4L2_CID_GAMMA, | 127 | .id = V4L2_CID_GAMMA, |
@@ -136,7 +135,6 @@ static struct ctrl sd_ctrls[] = { | |||
136 | .set = sd_setgamma, | 135 | .set = sd_setgamma, |
137 | .get = sd_getgamma, | 136 | .get = sd_getgamma, |
138 | }, | 137 | }, |
139 | #define SD_AUTOGAIN 3 | ||
140 | { | 138 | { |
141 | { | 139 | { |
142 | .id = V4L2_CID_AUTOGAIN, | 140 | .id = V4L2_CID_AUTOGAIN, |
@@ -145,13 +143,13 @@ static struct ctrl sd_ctrls[] = { | |||
145 | .minimum = 0, | 143 | .minimum = 0, |
146 | .maximum = 1, | 144 | .maximum = 1, |
147 | .step = 1, | 145 | .step = 1, |
148 | .default_value = 1, | 146 | #define AUTOGAIN_DEF 1 |
147 | .default_value = AUTOGAIN_DEF, | ||
149 | }, | 148 | }, |
150 | .set = sd_setautogain, | 149 | .set = sd_setautogain, |
151 | .get = sd_getautogain, | 150 | .get = sd_getautogain, |
152 | }, | 151 | }, |
153 | #define LIGHTFREQ_IDX 4 | 152 | #define LIGHTFREQ_IDX 4 |
154 | #define SD_FREQ 4 | ||
155 | { | 153 | { |
156 | { | 154 | { |
157 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | 155 | .id = V4L2_CID_POWER_LINE_FREQUENCY, |
@@ -160,12 +158,12 @@ static struct ctrl sd_ctrls[] = { | |||
160 | .minimum = 0, | 158 | .minimum = 0, |
161 | .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ | 159 | .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ |
162 | .step = 1, | 160 | .step = 1, |
163 | .default_value = 1, | 161 | #define FREQ_DEF 0 |
162 | .default_value = FREQ_DEF, | ||
164 | }, | 163 | }, |
165 | .set = sd_setfreq, | 164 | .set = sd_setfreq, |
166 | .get = sd_getfreq, | 165 | .get = sd_getfreq, |
167 | }, | 166 | }, |
168 | #define SD_SHARPNESS 5 | ||
169 | { | 167 | { |
170 | { | 168 | { |
171 | .id = V4L2_CID_SHARPNESS, | 169 | .id = V4L2_CID_SHARPNESS, |
@@ -174,7 +172,8 @@ static struct ctrl sd_ctrls[] = { | |||
174 | .minimum = 0, | 172 | .minimum = 0, |
175 | .maximum = 3, | 173 | .maximum = 3, |
176 | .step = 1, | 174 | .step = 1, |
177 | .default_value = 2, | 175 | #define SHARPNESS_DEF 2 |
176 | .default_value = SHARPNESS_DEF, | ||
178 | }, | 177 | }, |
179 | .set = sd_setsharpness, | 178 | .set = sd_setsharpness, |
180 | .get = sd_getsharpness, | 179 | .get = sd_getsharpness, |
@@ -194,6 +193,19 @@ static const struct v4l2_pix_format vga_mode[] = { | |||
194 | .priv = 0}, | 193 | .priv = 0}, |
195 | }; | 194 | }; |
196 | 195 | ||
196 | static const struct v4l2_pix_format broken_vga_mode[] = { | ||
197 | {320, 232, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
198 | .bytesperline = 320, | ||
199 | .sizeimage = 320 * 232 * 4 / 8 + 590, | ||
200 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
201 | .priv = 1}, | ||
202 | {640, 472, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
203 | .bytesperline = 640, | ||
204 | .sizeimage = 640 * 472 * 3 / 8 + 590, | ||
205 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
206 | .priv = 0}, | ||
207 | }; | ||
208 | |||
197 | static const struct v4l2_pix_format sif_mode[] = { | 209 | static const struct v4l2_pix_format sif_mode[] = { |
198 | {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 210 | {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, |
199 | .bytesperline = 176, | 211 | .bytesperline = 176, |
@@ -209,9 +221,9 @@ static const struct v4l2_pix_format sif_mode[] = { | |||
209 | 221 | ||
210 | /* usb exchanges */ | 222 | /* usb exchanges */ |
211 | struct usb_action { | 223 | struct usb_action { |
212 | __u8 req; | 224 | u8 req; |
213 | __u8 val; | 225 | u8 val; |
214 | __u16 idx; | 226 | u16 idx; |
215 | }; | 227 | }; |
216 | 228 | ||
217 | static const struct usb_action adcm2700_Initial[] = { | 229 | static const struct usb_action adcm2700_Initial[] = { |
@@ -421,7 +433,7 @@ static const struct usb_action adcm2700_NoFliker[] = { | |||
421 | {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */ | 433 | {0xaa, 0xfe, 0x0010}, /* 00,fe,10,aa */ |
422 | {} | 434 | {} |
423 | }; | 435 | }; |
424 | static const struct usb_action cs2102_Initial[] = { /* 320x240 */ | 436 | static const struct usb_action cs2102_InitialScale[] = { /* 320x240 */ |
425 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 437 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
426 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, | 438 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, |
427 | {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, | 439 | {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, |
@@ -473,7 +485,7 @@ static const struct usb_action cs2102_Initial[] = { /* 320x240 */ | |||
473 | {} | 485 | {} |
474 | }; | 486 | }; |
475 | 487 | ||
476 | static const struct usb_action cs2102_InitialScale[] = { /* 640x480 */ | 488 | static const struct usb_action cs2102_Initial[] = { /* 640x480 */ |
477 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 489 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
478 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, | 490 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, |
479 | {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, | 491 | {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, |
@@ -524,7 +536,7 @@ static const struct usb_action cs2102_InitialScale[] = { /* 640x480 */ | |||
524 | {0xa0, 0x00, 0x01ad}, | 536 | {0xa0, 0x00, 0x01ad}, |
525 | {} | 537 | {} |
526 | }; | 538 | }; |
527 | static const struct usb_action cs2102_50HZ[] = { | 539 | static const struct usb_action cs2102_50HZScale[] = { |
528 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, | 540 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
529 | {0xaa, 0x23, 0x0001}, | 541 | {0xaa, 0x23, 0x0001}, |
530 | {0xaa, 0x24, 0x005f}, | 542 | {0xaa, 0x24, 0x005f}, |
@@ -546,7 +558,7 @@ static const struct usb_action cs2102_50HZ[] = { | |||
546 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, | 558 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, |
547 | {} | 559 | {} |
548 | }; | 560 | }; |
549 | static const struct usb_action cs2102_50HZScale[] = { | 561 | static const struct usb_action cs2102_50HZ[] = { |
550 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, | 562 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
551 | {0xaa, 0x23, 0x0000}, | 563 | {0xaa, 0x23, 0x0000}, |
552 | {0xaa, 0x24, 0x00af}, | 564 | {0xaa, 0x24, 0x00af}, |
@@ -568,7 +580,7 @@ static const struct usb_action cs2102_50HZScale[] = { | |||
568 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, | 580 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, |
569 | {} | 581 | {} |
570 | }; | 582 | }; |
571 | static const struct usb_action cs2102_60HZ[] = { | 583 | static const struct usb_action cs2102_60HZScale[] = { |
572 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, | 584 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
573 | {0xaa, 0x23, 0x0001}, | 585 | {0xaa, 0x23, 0x0001}, |
574 | {0xaa, 0x24, 0x0055}, | 586 | {0xaa, 0x24, 0x0055}, |
@@ -590,7 +602,7 @@ static const struct usb_action cs2102_60HZ[] = { | |||
590 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, | 602 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, |
591 | {} | 603 | {} |
592 | }; | 604 | }; |
593 | static const struct usb_action cs2102_60HZScale[] = { | 605 | static const struct usb_action cs2102_60HZ[] = { |
594 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, | 606 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
595 | {0xaa, 0x23, 0x0000}, | 607 | {0xaa, 0x23, 0x0000}, |
596 | {0xaa, 0x24, 0x00aa}, | 608 | {0xaa, 0x24, 0x00aa}, |
@@ -612,7 +624,7 @@ static const struct usb_action cs2102_60HZScale[] = { | |||
612 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, | 624 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, |
613 | {} | 625 | {} |
614 | }; | 626 | }; |
615 | static const struct usb_action cs2102_NoFliker[] = { | 627 | static const struct usb_action cs2102_NoFlikerScale[] = { |
616 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, | 628 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
617 | {0xaa, 0x23, 0x0001}, | 629 | {0xaa, 0x23, 0x0001}, |
618 | {0xaa, 0x24, 0x005f}, | 630 | {0xaa, 0x24, 0x005f}, |
@@ -634,7 +646,7 @@ static const struct usb_action cs2102_NoFliker[] = { | |||
634 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, | 646 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, |
635 | {} | 647 | {} |
636 | }; | 648 | }; |
637 | static const struct usb_action cs2102_NoFlikerScale[] = { | 649 | static const struct usb_action cs2102_NoFliker[] = { |
638 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, | 650 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, |
639 | {0xaa, 0x23, 0x0000}, | 651 | {0xaa, 0x23, 0x0000}, |
640 | {0xaa, 0x24, 0x00af}, | 652 | {0xaa, 0x24, 0x00af}, |
@@ -658,7 +670,7 @@ static const struct usb_action cs2102_NoFlikerScale[] = { | |||
658 | }; | 670 | }; |
659 | 671 | ||
660 | /* CS2102_KOCOM */ | 672 | /* CS2102_KOCOM */ |
661 | static const struct usb_action cs2102K_Initial[] = { | 673 | static const struct usb_action cs2102K_InitialScale[] = { |
662 | {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT}, | 674 | {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT}, |
663 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, | 675 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, |
664 | {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT}, | 676 | {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT}, |
@@ -917,7 +929,7 @@ static const struct usb_action cs2102K_Initial[] = { | |||
917 | {} | 929 | {} |
918 | }; | 930 | }; |
919 | 931 | ||
920 | static const struct usb_action cs2102K_InitialScale[] = { | 932 | static const struct usb_action cs2102K_Initial[] = { |
921 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 933 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
922 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, | 934 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, |
923 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, | 935 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, |
@@ -1495,7 +1507,7 @@ static const struct usb_action gc0305_NoFliker[] = { | |||
1495 | {} | 1507 | {} |
1496 | }; | 1508 | }; |
1497 | 1509 | ||
1498 | static const struct usb_action hdcs2020xb_Initial[] = { | 1510 | static const struct usb_action hdcs2020b_InitialScale[] = { |
1499 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 1511 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
1500 | {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT}, | 1512 | {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT}, |
1501 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* qtable 0x05 */ | 1513 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* qtable 0x05 */ |
@@ -1627,7 +1639,7 @@ static const struct usb_action hdcs2020xb_Initial[] = { | |||
1627 | {0xa0, 0x40, ZC3XX_R118_BGAIN}, | 1639 | {0xa0, 0x40, ZC3XX_R118_BGAIN}, |
1628 | {} | 1640 | {} |
1629 | }; | 1641 | }; |
1630 | static const struct usb_action hdcs2020xb_InitialScale[] = { | 1642 | static const struct usb_action hdcs2020b_Initial[] = { |
1631 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 1643 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
1632 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, | 1644 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, |
1633 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, | 1645 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, |
@@ -1819,7 +1831,7 @@ static const struct usb_action hdcs2020b_NoFliker[] = { | |||
1819 | {} | 1831 | {} |
1820 | }; | 1832 | }; |
1821 | 1833 | ||
1822 | static const struct usb_action hv7131bxx_Initial[] = { /* 320x240 */ | 1834 | static const struct usb_action hv7131b_InitialScale[] = { /* 320x240 */ |
1823 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 1835 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
1824 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, | 1836 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, |
1825 | {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, | 1837 | {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, |
@@ -1866,7 +1878,7 @@ static const struct usb_action hv7131bxx_Initial[] = { /* 320x240 */ | |||
1866 | {} | 1878 | {} |
1867 | }; | 1879 | }; |
1868 | 1880 | ||
1869 | static const struct usb_action hv7131bxx_InitialScale[] = { /* 640x480*/ | 1881 | static const struct usb_action hv7131b_Initial[] = { /* 640x480*/ |
1870 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 1882 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
1871 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, | 1883 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, |
1872 | {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, | 1884 | {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, |
@@ -2063,7 +2075,7 @@ static const struct usb_action hv7131b_NoFlikerScale[] = { /* 320x240 */ | |||
2063 | {} | 2075 | {} |
2064 | }; | 2076 | }; |
2065 | 2077 | ||
2066 | static const struct usb_action hv7131cxx_Initial[] = { | 2078 | static const struct usb_action hv7131r_InitialScale[] = { |
2067 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 2079 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
2068 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, | 2080 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, |
2069 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, | 2081 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, |
@@ -2157,7 +2169,7 @@ static const struct usb_action hv7131cxx_Initial[] = { | |||
2157 | {} | 2169 | {} |
2158 | }; | 2170 | }; |
2159 | 2171 | ||
2160 | static const struct usb_action hv7131cxx_InitialScale[] = { | 2172 | static const struct usb_action hv7131r_Initial[] = { |
2161 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 2173 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
2162 | 2174 | ||
2163 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* diff */ | 2175 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* diff */ |
@@ -2259,7 +2271,7 @@ static const struct usb_action hv7131cxx_InitialScale[] = { | |||
2259 | {} | 2271 | {} |
2260 | }; | 2272 | }; |
2261 | 2273 | ||
2262 | static const struct usb_action icm105axx_Initial[] = { | 2274 | static const struct usb_action icm105a_InitialScale[] = { |
2263 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 2275 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
2264 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, | 2276 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, |
2265 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, | 2277 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, |
@@ -2436,7 +2448,7 @@ static const struct usb_action icm105axx_Initial[] = { | |||
2436 | {} | 2448 | {} |
2437 | }; | 2449 | }; |
2438 | 2450 | ||
2439 | static const struct usb_action icm105axx_InitialScale[] = { | 2451 | static const struct usb_action icm105a_Initial[] = { |
2440 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 2452 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
2441 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, | 2453 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, |
2442 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, | 2454 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, |
@@ -2615,7 +2627,7 @@ static const struct usb_action icm105axx_InitialScale[] = { | |||
2615 | {0xa0, 0x40, ZC3XX_R118_BGAIN}, | 2627 | {0xa0, 0x40, ZC3XX_R118_BGAIN}, |
2616 | {} | 2628 | {} |
2617 | }; | 2629 | }; |
2618 | static const struct usb_action icm105a_50HZ[] = { | 2630 | static const struct usb_action icm105a_50HZScale[] = { |
2619 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | 2631 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ |
2620 | {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ | 2632 | {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ |
2621 | {0xaa, 0x0c, 0x0020}, /* 00,0c,20,aa */ | 2633 | {0xaa, 0x0c, 0x0020}, /* 00,0c,20,aa */ |
@@ -2646,7 +2658,7 @@ static const struct usb_action icm105a_50HZ[] = { | |||
2646 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ | 2658 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ |
2647 | {} | 2659 | {} |
2648 | }; | 2660 | }; |
2649 | static const struct usb_action icm105a_50HZScale[] = { | 2661 | static const struct usb_action icm105a_50HZ[] = { |
2650 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | 2662 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ |
2651 | {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ | 2663 | {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ |
2652 | {0xaa, 0x0c, 0x008c}, /* 00,0c,8c,aa */ | 2664 | {0xaa, 0x0c, 0x008c}, /* 00,0c,8c,aa */ |
@@ -2679,7 +2691,7 @@ static const struct usb_action icm105a_50HZScale[] = { | |||
2679 | {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */ | 2691 | {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */ |
2680 | {} | 2692 | {} |
2681 | }; | 2693 | }; |
2682 | static const struct usb_action icm105a_60HZ[] = { | 2694 | static const struct usb_action icm105a_60HZScale[] = { |
2683 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | 2695 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ |
2684 | {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ | 2696 | {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ |
2685 | {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */ | 2697 | {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */ |
@@ -2710,7 +2722,7 @@ static const struct usb_action icm105a_60HZ[] = { | |||
2710 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ | 2722 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ |
2711 | {} | 2723 | {} |
2712 | }; | 2724 | }; |
2713 | static const struct usb_action icm105a_60HZScale[] = { | 2725 | static const struct usb_action icm105a_60HZ[] = { |
2714 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | 2726 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ |
2715 | {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ | 2727 | {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ |
2716 | {0xaa, 0x0c, 0x0008}, /* 00,0c,08,aa */ | 2728 | {0xaa, 0x0c, 0x0008}, /* 00,0c,08,aa */ |
@@ -2743,7 +2755,7 @@ static const struct usb_action icm105a_60HZScale[] = { | |||
2743 | {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */ | 2755 | {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */ |
2744 | {} | 2756 | {} |
2745 | }; | 2757 | }; |
2746 | static const struct usb_action icm105a_NoFliker[] = { | 2758 | static const struct usb_action icm105a_NoFlikerScale[] = { |
2747 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | 2759 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ |
2748 | {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ | 2760 | {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ |
2749 | {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */ | 2761 | {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */ |
@@ -2774,7 +2786,7 @@ static const struct usb_action icm105a_NoFliker[] = { | |||
2774 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ | 2786 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */ |
2775 | {} | 2787 | {} |
2776 | }; | 2788 | }; |
2777 | static const struct usb_action icm105a_NoFlikerScale[] = { | 2789 | static const struct usb_action icm105a_NoFliker[] = { |
2778 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | 2790 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ |
2779 | {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ | 2791 | {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */ |
2780 | {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */ | 2792 | {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */ |
@@ -2808,7 +2820,7 @@ static const struct usb_action icm105a_NoFlikerScale[] = { | |||
2808 | {} | 2820 | {} |
2809 | }; | 2821 | }; |
2810 | 2822 | ||
2811 | static const struct usb_action MC501CB_InitialScale[] = { | 2823 | static const struct usb_action mc501cb_Initial[] = { |
2812 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ | 2824 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ |
2813 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc */ | 2825 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc */ |
2814 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ | 2826 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ |
@@ -2928,7 +2940,7 @@ static const struct usb_action MC501CB_InitialScale[] = { | |||
2928 | {} | 2940 | {} |
2929 | }; | 2941 | }; |
2930 | 2942 | ||
2931 | static const struct usb_action MC501CB_Initial[] = { /* 320x240 */ | 2943 | static const struct usb_action mc501cb_InitialScale[] = { /* 320x240 */ |
2932 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ | 2944 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ |
2933 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */ | 2945 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */ |
2934 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ | 2946 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ |
@@ -3047,7 +3059,7 @@ static const struct usb_action MC501CB_Initial[] = { /* 320x240 */ | |||
3047 | {} | 3059 | {} |
3048 | }; | 3060 | }; |
3049 | 3061 | ||
3050 | static const struct usb_action MC501CB_50HZ[] = { | 3062 | static const struct usb_action mc501cb_50HZScale[] = { |
3051 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ | 3063 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ |
3052 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ | 3064 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ |
3053 | {0xaa, 0x36, 0x001d}, /* 00,36,1D,aa */ | 3065 | {0xaa, 0x36, 0x001d}, /* 00,36,1D,aa */ |
@@ -3064,7 +3076,7 @@ static const struct usb_action MC501CB_50HZ[] = { | |||
3064 | {} | 3076 | {} |
3065 | }; | 3077 | }; |
3066 | 3078 | ||
3067 | static const struct usb_action MC501CB_50HZScale[] = { | 3079 | static const struct usb_action mc501cb_50HZ[] = { |
3068 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ | 3080 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ |
3069 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ | 3081 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ |
3070 | {0xaa, 0x36, 0x003a}, /* 00,36,3A,aa */ | 3082 | {0xaa, 0x36, 0x003a}, /* 00,36,3A,aa */ |
@@ -3081,7 +3093,7 @@ static const struct usb_action MC501CB_50HZScale[] = { | |||
3081 | {} | 3093 | {} |
3082 | }; | 3094 | }; |
3083 | 3095 | ||
3084 | static const struct usb_action MC501CB_60HZ[] = { | 3096 | static const struct usb_action mc501cb_60HZScale[] = { |
3085 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ | 3097 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ |
3086 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ | 3098 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ |
3087 | {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */ | 3099 | {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */ |
@@ -3098,7 +3110,7 @@ static const struct usb_action MC501CB_60HZ[] = { | |||
3098 | {} | 3110 | {} |
3099 | }; | 3111 | }; |
3100 | 3112 | ||
3101 | static const struct usb_action MC501CB_60HZScale[] = { | 3113 | static const struct usb_action mc501cb_60HZ[] = { |
3102 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ | 3114 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ |
3103 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ | 3115 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ |
3104 | {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */ | 3116 | {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */ |
@@ -3115,7 +3127,7 @@ static const struct usb_action MC501CB_60HZScale[] = { | |||
3115 | {} | 3127 | {} |
3116 | }; | 3128 | }; |
3117 | 3129 | ||
3118 | static const struct usb_action MC501CB_NoFliker[] = { | 3130 | static const struct usb_action mc501cb_NoFlikerScale[] = { |
3119 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ | 3131 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ |
3120 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ | 3132 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ |
3121 | {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */ | 3133 | {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */ |
@@ -3132,7 +3144,7 @@ static const struct usb_action MC501CB_NoFliker[] = { | |||
3132 | {} | 3144 | {} |
3133 | }; | 3145 | }; |
3134 | 3146 | ||
3135 | static const struct usb_action MC501CB_NoFlikerScale[] = { | 3147 | static const struct usb_action mc501cb_NoFliker[] = { |
3136 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ | 3148 | {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */ |
3137 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ | 3149 | {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */ |
3138 | {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */ | 3150 | {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */ |
@@ -3144,8 +3156,8 @@ static const struct usb_action MC501CB_NoFlikerScale[] = { | |||
3144 | {} | 3156 | {} |
3145 | }; | 3157 | }; |
3146 | 3158 | ||
3147 | /* from zs211.inf - HKR,%OV7620%,Initial - 640x480 */ | 3159 | /* from zs211.inf */ |
3148 | static const struct usb_action OV7620_mode0[] = { | 3160 | static const struct usb_action ov7620_Initial[] = { /* 640x480 */ |
3149 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ | 3161 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ |
3150 | {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, /* 00,02,40,cc */ | 3162 | {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, /* 00,02,40,cc */ |
3151 | {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */ | 3163 | {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */ |
@@ -3214,9 +3226,7 @@ static const struct usb_action OV7620_mode0[] = { | |||
3214 | {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,50,cc */ | 3226 | {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,50,cc */ |
3215 | {} | 3227 | {} |
3216 | }; | 3228 | }; |
3217 | 3229 | static const struct usb_action ov7620_InitialScale[] = { /* 320x240 */ | |
3218 | /* from zs211.inf - HKR,%OV7620%,InitialScale - 320x240 */ | ||
3219 | static const struct usb_action OV7620_mode1[] = { | ||
3220 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ | 3230 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ |
3221 | {0xa0, 0x50, ZC3XX_R002_CLOCKSELECT}, /* 00,02,50,cc */ | 3231 | {0xa0, 0x50, ZC3XX_R002_CLOCKSELECT}, /* 00,02,50,cc */ |
3222 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */ | 3232 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */ |
@@ -3287,9 +3297,7 @@ static const struct usb_action OV7620_mode1[] = { | |||
3287 | {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,50,cc */ | 3297 | {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,50,cc */ |
3288 | {} | 3298 | {} |
3289 | }; | 3299 | }; |
3290 | 3300 | static const struct usb_action ov7620_50HZ[] = { | |
3291 | /* from zs211.inf - HKR,%OV7620%\AE,50HZ */ | ||
3292 | static const struct usb_action OV7620_50HZ[] = { | ||
3293 | {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */ | 3301 | {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */ |
3294 | {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */ | 3302 | {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */ |
3295 | {0xaa, 0x2b, 0x0096}, /* 00,2b,96,aa */ | 3303 | {0xaa, 0x2b, 0x0096}, /* 00,2b,96,aa */ |
@@ -3307,9 +3315,7 @@ static const struct usb_action OV7620_50HZ[] = { | |||
3307 | if mode0 (640x480) */ | 3315 | if mode0 (640x480) */ |
3308 | {} | 3316 | {} |
3309 | }; | 3317 | }; |
3310 | 3318 | static const struct usb_action ov7620_60HZ[] = { | |
3311 | /* from zs211.inf - HKR,%OV7620%\AE,60HZ */ | ||
3312 | static const struct usb_action OV7620_60HZ[] = { | ||
3313 | {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */ | 3319 | {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */ |
3314 | /* (bug in zs211.inf) */ | 3320 | /* (bug in zs211.inf) */ |
3315 | {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */ | 3321 | {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */ |
@@ -3331,9 +3337,7 @@ static const struct usb_action OV7620_60HZ[] = { | |||
3331 | {0xa1, 0x01, 0x0037}, */ | 3337 | {0xa1, 0x01, 0x0037}, */ |
3332 | {} | 3338 | {} |
3333 | }; | 3339 | }; |
3334 | 3340 | static const struct usb_action ov7620_NoFliker[] = { | |
3335 | /* from zs211.inf - HKR,%OV7620%\AE,NoFliker */ | ||
3336 | static const struct usb_action OV7620_NoFliker[] = { | ||
3337 | {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */ | 3341 | {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */ |
3338 | /* (bug in zs211.inf) */ | 3342 | /* (bug in zs211.inf) */ |
3339 | {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */ | 3343 | {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */ |
@@ -3354,7 +3358,7 @@ static const struct usb_action OV7620_NoFliker[] = { | |||
3354 | {} | 3358 | {} |
3355 | }; | 3359 | }; |
3356 | 3360 | ||
3357 | static const struct usb_action ov7630c_Initial[] = { | 3361 | static const struct usb_action ov7630c_InitialScale[] = { |
3358 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 3362 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
3359 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, | 3363 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, |
3360 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 3364 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
@@ -3511,7 +3515,7 @@ static const struct usb_action ov7630c_Initial[] = { | |||
3511 | {} | 3515 | {} |
3512 | }; | 3516 | }; |
3513 | 3517 | ||
3514 | static const struct usb_action ov7630c_InitialScale[] = { | 3518 | static const struct usb_action ov7630c_Initial[] = { |
3515 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 3519 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
3516 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, | 3520 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, |
3517 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, | 3521 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, |
@@ -3682,7 +3686,7 @@ static const struct usb_action pas106b_Initial_com[] = { | |||
3682 | {} | 3686 | {} |
3683 | }; | 3687 | }; |
3684 | 3688 | ||
3685 | static const struct usb_action pas106b_Initial[] = { /* 176x144 */ | 3689 | static const struct usb_action pas106b_InitialScale[] = { /* 176x144 */ |
3686 | /* JPEG control */ | 3690 | /* JPEG control */ |
3687 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, | 3691 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, |
3688 | /* Sream and Sensor specific */ | 3692 | /* Sream and Sensor specific */ |
@@ -3800,7 +3804,7 @@ static const struct usb_action pas106b_Initial[] = { /* 176x144 */ | |||
3800 | {} | 3804 | {} |
3801 | }; | 3805 | }; |
3802 | 3806 | ||
3803 | static const struct usb_action pas106b_InitialScale[] = { /* 352x288 */ | 3807 | static const struct usb_action pas106b_Initial[] = { /* 352x288 */ |
3804 | /* JPEG control */ | 3808 | /* JPEG control */ |
3805 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, | 3809 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, |
3806 | /* Sream and Sensor specific */ | 3810 | /* Sream and Sensor specific */ |
@@ -3972,10 +3976,10 @@ static const struct usb_action pas106b_NoFliker[] = { | |||
3972 | {} | 3976 | {} |
3973 | }; | 3977 | }; |
3974 | 3978 | ||
3975 | /* from usbvm31b.inf */ | 3979 | /* from lvWIMv.inf 046d:08a2/:08aa 2007/06/03 */ |
3976 | static const struct usb_action pas202b_Initial[] = { /* 640x480 */ | 3980 | static const struct usb_action pas202b_Initial[] = { /* 640x480 */ |
3977 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ | 3981 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ |
3978 | {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */ | 3982 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, |
3979 | {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0e,cc */ | 3983 | {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0e,cc */ |
3980 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc */ | 3984 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc */ |
3981 | {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ | 3985 | {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ |
@@ -4000,7 +4004,7 @@ static const struct usb_action pas202b_Initial[] = { /* 640x480 */ | |||
4000 | {0xaa, 0x09, 0x0006}, /* 00,09,06,aa */ | 4004 | {0xaa, 0x09, 0x0006}, /* 00,09,06,aa */ |
4001 | {0xaa, 0x0a, 0x0001}, /* 00,0a,01,aa */ | 4005 | {0xaa, 0x0a, 0x0001}, /* 00,0a,01,aa */ |
4002 | {0xaa, 0x0b, 0x0001}, /* 00,0b,01,aa */ | 4006 | {0xaa, 0x0b, 0x0001}, /* 00,0b,01,aa */ |
4003 | {0xaa, 0x0c, 0x0008}, /* 00,0c,08,aa */ | 4007 | {0xaa, 0x0c, 0x0006}, |
4004 | {0xaa, 0x0d, 0x0000}, /* 00,0d,00,aa */ | 4008 | {0xaa, 0x0d, 0x0000}, /* 00,0d,00,aa */ |
4005 | {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */ | 4009 | {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */ |
4006 | {0xaa, 0x12, 0x0005}, /* 00,12,05,aa */ | 4010 | {0xaa, 0x12, 0x0005}, /* 00,12,05,aa */ |
@@ -4019,13 +4023,13 @@ static const struct usb_action pas202b_Initial[] = { /* 640x480 */ | |||
4019 | }; | 4023 | }; |
4020 | static const struct usb_action pas202b_InitialScale[] = { /* 320x240 */ | 4024 | static const struct usb_action pas202b_InitialScale[] = { /* 320x240 */ |
4021 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ | 4025 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ |
4022 | {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */ | 4026 | {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, |
4023 | {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0e,cc */ | 4027 | {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0e,cc */ |
4024 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */ | 4028 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */ |
4025 | {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ | 4029 | {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */ |
4026 | {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */ | 4030 | {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */ |
4027 | {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */ | 4031 | {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */ |
4028 | {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d0,cc */ | 4032 | {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, |
4029 | {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */ | 4033 | {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */ |
4030 | {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */ | 4034 | {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */ |
4031 | {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */ | 4035 | {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */ |
@@ -4035,7 +4039,7 @@ static const struct usb_action pas202b_InitialScale[] = { /* 320x240 */ | |||
4035 | {0xa0, 0x08, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,08,cc */ | 4039 | {0xa0, 0x08, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,08,cc */ |
4036 | {0xa0, 0x02, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,02,cc */ | 4040 | {0xa0, 0x02, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,02,cc */ |
4037 | {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */ | 4041 | {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */ |
4038 | {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,d8,cc */ | 4042 | {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, |
4039 | {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */ | 4043 | {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */ |
4040 | {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */ | 4044 | {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */ |
4041 | {0xaa, 0x02, 0x0002}, /* 00,02,02,aa */ | 4045 | {0xaa, 0x02, 0x0002}, /* 00,02,02,aa */ |
@@ -4044,7 +4048,7 @@ static const struct usb_action pas202b_InitialScale[] = { /* 320x240 */ | |||
4044 | {0xaa, 0x09, 0x0006}, /* 00,09,06,aa */ | 4048 | {0xaa, 0x09, 0x0006}, /* 00,09,06,aa */ |
4045 | {0xaa, 0x0a, 0x0001}, /* 00,0a,01,aa */ | 4049 | {0xaa, 0x0a, 0x0001}, /* 00,0a,01,aa */ |
4046 | {0xaa, 0x0b, 0x0001}, /* 00,0b,01,aa */ | 4050 | {0xaa, 0x0b, 0x0001}, /* 00,0b,01,aa */ |
4047 | {0xaa, 0x0c, 0x0008}, /* 00,0c,08,aa */ | 4051 | {0xaa, 0x0c, 0x0006}, |
4048 | {0xaa, 0x0d, 0x0000}, /* 00,0d,00,aa */ | 4052 | {0xaa, 0x0d, 0x0000}, /* 00,0d,00,aa */ |
4049 | {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */ | 4053 | {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */ |
4050 | {0xaa, 0x12, 0x0005}, /* 00,12,05,aa */ | 4054 | {0xaa, 0x12, 0x0005}, /* 00,12,05,aa */ |
@@ -4059,6 +4063,8 @@ static const struct usb_action pas202b_InitialScale[] = { /* 320x240 */ | |||
4059 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */ | 4063 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */ |
4060 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */ | 4064 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */ |
4061 | {0xa0, 0x70, ZC3XX_R18D_YTARGET}, /* 01,8d,70,cc */ | 4065 | {0xa0, 0x70, ZC3XX_R18D_YTARGET}, /* 01,8d,70,cc */ |
4066 | {0xa0, 0xff, ZC3XX_R097_WINYSTARTHIGH}, | ||
4067 | {0xa0, 0xfe, ZC3XX_R098_WINYSTARTLOW}, | ||
4062 | {} | 4068 | {} |
4063 | }; | 4069 | }; |
4064 | static const struct usb_action pas202b_50HZ[] = { | 4070 | static const struct usb_action pas202b_50HZ[] = { |
@@ -4066,22 +4072,22 @@ static const struct usb_action pas202b_50HZ[] = { | |||
4066 | {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ | 4072 | {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ |
4067 | {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ | 4073 | {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ |
4068 | {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */ | 4074 | {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */ |
4069 | {0xaa, 0x21, 0x0068}, /* 00,21,68,aa */ | 4075 | {0xaa, 0x21, 0x001b}, |
4070 | {0xaa, 0x03, 0x0044}, /* 00,03,44,aa */ | 4076 | {0xaa, 0x03, 0x0044}, /* 00,03,44,aa */ |
4071 | {0xaa, 0x04, 0x0009}, /* 00,04,09,aa */ | 4077 | {0xaa, 0x04, 0x0008}, |
4072 | {0xaa, 0x05, 0x0028}, /* 00,05,28,aa */ | 4078 | {0xaa, 0x05, 0x001b}, |
4073 | {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ | 4079 | {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ |
4074 | {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ | 4080 | {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ |
4075 | {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,14,cc */ | 4081 | {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF}, |
4076 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ | 4082 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ |
4077 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | 4083 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ |
4078 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */ | 4084 | {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, |
4079 | {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,d2,cc */ | 4085 | {0xa0, 0x1b, ZC3XX_R192_EXPOSURELIMITLOW}, |
4080 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | 4086 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ |
4081 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | 4087 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ |
4082 | {0xa0, 0x4d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,4d,cc */ | 4088 | {0xa0, 0x4d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,4d,cc */ |
4083 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | 4089 | {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, |
4084 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | 4090 | {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE}, |
4085 | {0xa0, 0x44, ZC3XX_R01D_HSYNC_0}, /* 00,1d,44,cc */ | 4091 | {0xa0, 0x44, ZC3XX_R01D_HSYNC_0}, /* 00,1d,44,cc */ |
4086 | {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */ | 4092 | {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */ |
4087 | {0xa0, 0xad, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ad,cc */ | 4093 | {0xa0, 0xad, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ad,cc */ |
@@ -4094,23 +4100,23 @@ static const struct usb_action pas202b_50HZScale[] = { | |||
4094 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | 4100 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ |
4095 | {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ | 4101 | {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ |
4096 | {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ | 4102 | {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ |
4097 | {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */ | 4103 | {0xaa, 0x20, 0x0004}, |
4098 | {0xaa, 0x21, 0x006c}, /* 00,21,6c,aa */ | 4104 | {0xaa, 0x21, 0x003d}, |
4099 | {0xaa, 0x03, 0x0041}, /* 00,03,41,aa */ | 4105 | {0xaa, 0x03, 0x0041}, /* 00,03,41,aa */ |
4100 | {0xaa, 0x04, 0x0009}, /* 00,04,09,aa */ | 4106 | {0xaa, 0x04, 0x0010}, |
4101 | {0xaa, 0x05, 0x002c}, /* 00,05,2c,aa */ | 4107 | {0xaa, 0x05, 0x003d}, |
4102 | {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ | 4108 | {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ |
4103 | {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ | 4109 | {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ |
4104 | {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,14,cc */ | 4110 | {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF}, |
4105 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ | 4111 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ |
4106 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | 4112 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ |
4107 | {0xa0, 0x0f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0f,cc */ | 4113 | {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, |
4108 | {0xa0, 0xbe, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,be,cc */ | 4114 | {0xa0, 0x3d, ZC3XX_R192_EXPOSURELIMITLOW}, |
4109 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | 4115 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ |
4110 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | 4116 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ |
4111 | {0xa0, 0x9b, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,9b,cc */ | 4117 | {0xa0, 0x9b, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,9b,cc */ |
4112 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | 4118 | {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, |
4113 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | 4119 | {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE}, |
4114 | {0xa0, 0x41, ZC3XX_R01D_HSYNC_0}, /* 00,1d,41,cc */ | 4120 | {0xa0, 0x41, ZC3XX_R01D_HSYNC_0}, /* 00,1d,41,cc */ |
4115 | {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */ | 4121 | {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */ |
4116 | {0xa0, 0xad, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ad,cc */ | 4122 | {0xa0, 0xad, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ad,cc */ |
@@ -4130,16 +4136,16 @@ static const struct usb_action pas202b_60HZ[] = { | |||
4130 | {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */ | 4136 | {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */ |
4131 | {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ | 4137 | {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ |
4132 | {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ | 4138 | {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ |
4133 | {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,14,cc */ | 4139 | {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF}, |
4134 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ | 4140 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ |
4135 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | 4141 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ |
4136 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */ | 4142 | {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, |
4137 | {0xa0, 0xc0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,c0,cc */ | 4143 | {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW}, |
4138 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | 4144 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ |
4139 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | 4145 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ |
4140 | {0xa0, 0x40, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,40,cc */ | 4146 | {0xa0, 0x40, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,40,cc */ |
4141 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | 4147 | {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, |
4142 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | 4148 | {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE}, |
4143 | {0xa0, 0x45, ZC3XX_R01D_HSYNC_0}, /* 00,1d,45,cc */ | 4149 | {0xa0, 0x45, ZC3XX_R01D_HSYNC_0}, /* 00,1d,45,cc */ |
4144 | {0xa0, 0x8e, ZC3XX_R01E_HSYNC_1}, /* 00,1e,8e,cc */ | 4150 | {0xa0, 0x8e, ZC3XX_R01E_HSYNC_1}, /* 00,1e,8e,cc */ |
4145 | {0xa0, 0xc1, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c1,cc */ | 4151 | {0xa0, 0xc1, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c1,cc */ |
@@ -4152,23 +4158,23 @@ static const struct usb_action pas202b_60HZScale[] = { | |||
4152 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | 4158 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ |
4153 | {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ | 4159 | {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ |
4154 | {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ | 4160 | {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ |
4155 | {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */ | 4161 | {0xaa, 0x20, 0x0004}, |
4156 | {0xaa, 0x21, 0x0004}, /* 00,21,04,aa */ | 4162 | {0xaa, 0x21, 0x0008}, |
4157 | {0xaa, 0x03, 0x0042}, /* 00,03,42,aa */ | 4163 | {0xaa, 0x03, 0x0042}, /* 00,03,42,aa */ |
4158 | {0xaa, 0x04, 0x0008}, /* 00,04,08,aa */ | 4164 | {0xaa, 0x04, 0x0010}, |
4159 | {0xaa, 0x05, 0x0004}, /* 00,05,04,aa */ | 4165 | {0xaa, 0x05, 0x0008}, |
4160 | {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ | 4166 | {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ |
4161 | {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ | 4167 | {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ |
4162 | {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,14,cc */ | 4168 | {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF}, |
4163 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ | 4169 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */ |
4164 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | 4170 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ |
4165 | {0xa0, 0x0f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0f,cc */ | 4171 | {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, |
4166 | {0xa0, 0x9f, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,9f,cc */ | 4172 | {0xa0, 0x08, ZC3XX_R192_EXPOSURELIMITLOW}, |
4167 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | 4173 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ |
4168 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | 4174 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ |
4169 | {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,81,cc */ | 4175 | {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,81,cc */ |
4170 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | 4176 | {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, |
4171 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | 4177 | {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE}, |
4172 | {0xa0, 0x42, ZC3XX_R01D_HSYNC_0}, /* 00,1d,42,cc */ | 4178 | {0xa0, 0x42, ZC3XX_R01D_HSYNC_0}, /* 00,1d,42,cc */ |
4173 | {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */ | 4179 | {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1}, /* 00,1e,6f,cc */ |
4174 | {0xa0, 0xaf, ZC3XX_R01F_HSYNC_2}, /* 00,1f,af,cc */ | 4180 | {0xa0, 0xaf, ZC3XX_R01F_HSYNC_2}, /* 00,1f,af,cc */ |
@@ -4182,22 +4188,22 @@ static const struct usb_action pas202b_NoFliker[] = { | |||
4182 | {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ | 4188 | {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ |
4183 | {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ | 4189 | {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ |
4184 | {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */ | 4190 | {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */ |
4185 | {0xaa, 0x21, 0x0020}, /* 00,21,20,aa */ | 4191 | {0xaa, 0x21, 0x0006}, |
4186 | {0xaa, 0x03, 0x0040}, /* 00,03,40,aa */ | 4192 | {0xaa, 0x03, 0x0040}, /* 00,03,40,aa */ |
4187 | {0xaa, 0x04, 0x0008}, /* 00,04,08,aa */ | 4193 | {0xaa, 0x04, 0x0008}, /* 00,04,08,aa */ |
4188 | {0xaa, 0x05, 0x0020}, /* 00,05,20,aa */ | 4194 | {0xaa, 0x05, 0x0006}, |
4189 | {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ | 4195 | {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ |
4190 | {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ | 4196 | {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ |
4191 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | 4197 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ |
4192 | {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */ | 4198 | {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, |
4193 | {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */ | 4199 | {0xa0, 0x06, ZC3XX_R192_EXPOSURELIMITLOW}, |
4194 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | 4200 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ |
4195 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | 4201 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ |
4196 | {0xa0, 0x02, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,02,cc */ | 4202 | {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW}, |
4197 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | 4203 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ |
4198 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | 4204 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ |
4199 | {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ | 4205 | {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ |
4200 | {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */ | 4206 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, |
4201 | {0xa0, 0x40, ZC3XX_R01D_HSYNC_0}, /* 00,1d,40,cc */ | 4207 | {0xa0, 0x40, ZC3XX_R01D_HSYNC_0}, /* 00,1d,40,cc */ |
4202 | {0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, /* 00,1e,60,cc */ | 4208 | {0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, /* 00,1e,60,cc */ |
4203 | {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */ | 4209 | {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */ |
@@ -4210,23 +4216,23 @@ static const struct usb_action pas202b_NoFlikerScale[] = { | |||
4210 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ | 4216 | {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */ |
4211 | {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ | 4217 | {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */ |
4212 | {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ | 4218 | {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */ |
4213 | {0xaa, 0x20, 0x0002}, /* 00,20,02,aa */ | 4219 | {0xaa, 0x20, 0x0004}, |
4214 | {0xaa, 0x21, 0x0010}, /* 00,21,10,aa */ | 4220 | {0xaa, 0x21, 0x000c}, |
4215 | {0xaa, 0x03, 0x0040}, /* 00,03,40,aa */ | 4221 | {0xaa, 0x03, 0x0040}, /* 00,03,40,aa */ |
4216 | {0xaa, 0x04, 0x0008}, /* 00,04,08,aa */ | 4222 | {0xaa, 0x04, 0x0010}, |
4217 | {0xaa, 0x05, 0x0010}, /* 00,05,10,aa */ | 4223 | {0xaa, 0x05, 0x000c}, |
4218 | {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ | 4224 | {0xaa, 0x0e, 0x0001}, /* 00,0e,01,aa */ |
4219 | {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ | 4225 | {0xaa, 0x0f, 0x0000}, /* 00,0f,00,aa */ |
4220 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ | 4226 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */ |
4221 | {0xa0, 0x0f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0f,cc */ | 4227 | {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, |
4222 | {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */ | 4228 | {0xa0, 0x0c, ZC3XX_R192_EXPOSURELIMITLOW}, |
4223 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ | 4229 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */ |
4224 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ | 4230 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */ |
4225 | {0xa0, 0x02, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,02,cc */ | 4231 | {0xa0, 0x02, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,02,cc */ |
4226 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ | 4232 | {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */ |
4227 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ | 4233 | {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */ |
4228 | {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ | 4234 | {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */ |
4229 | {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */ | 4235 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, |
4230 | {0xa0, 0x40, ZC3XX_R01D_HSYNC_0}, /* 00,1d,40,cc */ | 4236 | {0xa0, 0x40, ZC3XX_R01D_HSYNC_0}, /* 00,1d,40,cc */ |
4231 | {0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, /* 00,1e,60,cc */ | 4237 | {0xa0, 0x60, ZC3XX_R01E_HSYNC_1}, /* 00,1e,60,cc */ |
4232 | {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */ | 4238 | {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */ |
@@ -4713,8 +4719,8 @@ static const struct usb_action pb0330_NoFlikerScale[] = { | |||
4713 | {} | 4719 | {} |
4714 | }; | 4720 | }; |
4715 | 4721 | ||
4716 | /* from oem9.inf - HKR,%PO2030%,Initial - 640x480 - (close to CS2102) */ | 4722 | /* from oem9.inf */ |
4717 | static const struct usb_action PO2030_mode0[] = { | 4723 | static const struct usb_action po2030_Initial[] = { /* 640x480 */ |
4718 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ | 4724 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ |
4719 | {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT}, /* 00,02,04,cc */ | 4725 | {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT}, /* 00,02,04,cc */ |
4720 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ | 4726 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ |
@@ -4790,8 +4796,8 @@ static const struct usb_action PO2030_mode0[] = { | |||
4790 | {} | 4796 | {} |
4791 | }; | 4797 | }; |
4792 | 4798 | ||
4793 | /* from oem9.inf - HKR,%PO2030%,InitialScale - 320x240 */ | 4799 | /* from oem9.inf */ |
4794 | static const struct usb_action PO2030_mode1[] = { | 4800 | static const struct usb_action po2030_InitialScale[] = { /* 320x240 */ |
4795 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ | 4801 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */ |
4796 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */ | 4802 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */ |
4797 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ | 4803 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */ |
@@ -4867,7 +4873,7 @@ static const struct usb_action PO2030_mode1[] = { | |||
4867 | {} | 4873 | {} |
4868 | }; | 4874 | }; |
4869 | 4875 | ||
4870 | static const struct usb_action PO2030_50HZ[] = { | 4876 | static const struct usb_action po2030_50HZ[] = { |
4871 | {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */ | 4877 | {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */ |
4872 | {0xaa, 0x1a, 0x0001}, /* 00,1a,01,aa */ | 4878 | {0xaa, 0x1a, 0x0001}, /* 00,1a,01,aa */ |
4873 | {0xaa, 0x1b, 0x000a}, /* 00,1b,0a,aa */ | 4879 | {0xaa, 0x1b, 0x000a}, /* 00,1b,0a,aa */ |
@@ -4889,7 +4895,7 @@ static const struct usb_action PO2030_50HZ[] = { | |||
4889 | {} | 4895 | {} |
4890 | }; | 4896 | }; |
4891 | 4897 | ||
4892 | static const struct usb_action PO2030_60HZ[] = { | 4898 | static const struct usb_action po2030_60HZ[] = { |
4893 | {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */ | 4899 | {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */ |
4894 | {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */ | 4900 | {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */ |
4895 | {0xaa, 0x1b, 0x00de}, /* 00,1b,de,aa */ | 4901 | {0xaa, 0x1b, 0x00de}, /* 00,1b,de,aa */ |
@@ -4912,7 +4918,7 @@ static const struct usb_action PO2030_60HZ[] = { | |||
4912 | {} | 4918 | {} |
4913 | }; | 4919 | }; |
4914 | 4920 | ||
4915 | static const struct usb_action PO2030_NoFliker[] = { | 4921 | static const struct usb_action po2030_NoFliker[] = { |
4916 | {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */ | 4922 | {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */ |
4917 | {0xaa, 0x8d, 0x000d}, /* 00,8d,0d,aa */ | 4923 | {0xaa, 0x8d, 0x000d}, /* 00,8d,0d,aa */ |
4918 | {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */ | 4924 | {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */ |
@@ -4924,7 +4930,7 @@ static const struct usb_action PO2030_NoFliker[] = { | |||
4924 | }; | 4930 | }; |
4925 | 4931 | ||
4926 | /* TEST */ | 4932 | /* TEST */ |
4927 | static const struct usb_action tas5130CK_Initial[] = { | 4933 | static const struct usb_action tas5130cK_InitialScale[] = { |
4928 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 4934 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
4929 | {0xa0, 0x01, 0x003b}, | 4935 | {0xa0, 0x01, 0x003b}, |
4930 | {0xa0, 0x0e, 0x003a}, | 4936 | {0xa0, 0x0e, 0x003a}, |
@@ -5127,7 +5133,7 @@ static const struct usb_action tas5130CK_Initial[] = { | |||
5127 | {} | 5133 | {} |
5128 | }; | 5134 | }; |
5129 | 5135 | ||
5130 | static const struct usb_action tas5130CK_InitialScale[] = { | 5136 | static const struct usb_action tas5130cK_Initial[] = { |
5131 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, | 5137 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, |
5132 | {0xa0, 0x01, 0x003b}, | 5138 | {0xa0, 0x01, 0x003b}, |
5133 | {0xa0, 0x0e, 0x003a}, | 5139 | {0xa0, 0x0e, 0x003a}, |
@@ -5560,7 +5566,7 @@ static const struct usb_action tas5130cxx_NoFlikerScale[] = { | |||
5560 | {} | 5566 | {} |
5561 | }; | 5567 | }; |
5562 | 5568 | ||
5563 | static const struct usb_action tas5130c_vf0250_Initial[] = { | 5569 | static const struct usb_action tas5130c_vf0250_InitialScale[] = { |
5564 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */ | 5570 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */ |
5565 | {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */ | 5571 | {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */ |
5566 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */ | 5572 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */ |
@@ -5627,7 +5633,7 @@ static const struct usb_action tas5130c_vf0250_Initial[] = { | |||
5627 | {} | 5633 | {} |
5628 | }; | 5634 | }; |
5629 | 5635 | ||
5630 | static const struct usb_action tas5130c_vf0250_InitialScale[] = { | 5636 | static const struct usb_action tas5130c_vf0250_Initial[] = { |
5631 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */ | 5637 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */ |
5632 | {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */ | 5638 | {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */ |
5633 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */ | 5639 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */ |
@@ -5692,8 +5698,7 @@ static const struct usb_action tas5130c_vf0250_InitialScale[] = { | |||
5692 | {0xa0, 0x65, ZC3XX_R118_BGAIN}, /* 01,18,65,cc */ | 5698 | {0xa0, 0x65, ZC3XX_R118_BGAIN}, /* 01,18,65,cc */ |
5693 | {} | 5699 | {} |
5694 | }; | 5700 | }; |
5695 | /* "50HZ" light frequency banding filter */ | 5701 | static const struct usb_action tas5130c_vf0250_50HZScale[] = { |
5696 | static const struct usb_action tas5130c_vf0250_50HZ[] = { | ||
5697 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ | 5702 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ |
5698 | {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */ | 5703 | {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */ |
5699 | {0xaa, 0x84, 0x00aa}, /* 00,84,aa,aa */ | 5704 | {0xaa, 0x84, 0x00aa}, /* 00,84,aa,aa */ |
@@ -5717,8 +5722,7 @@ static const struct usb_action tas5130c_vf0250_50HZ[] = { | |||
5717 | {} | 5722 | {} |
5718 | }; | 5723 | }; |
5719 | 5724 | ||
5720 | /* "50HZScale" light frequency banding filter */ | 5725 | static const struct usb_action tas5130c_vf0250_50HZ[] = { |
5721 | static const struct usb_action tas5130c_vf0250_50HZScale[] = { | ||
5722 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ | 5726 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ |
5723 | {0xaa, 0x83, 0x0003}, /* 00,83,03,aa */ | 5727 | {0xaa, 0x83, 0x0003}, /* 00,83,03,aa */ |
5724 | {0xaa, 0x84, 0x0054}, /* 00,84,54,aa */ | 5728 | {0xaa, 0x84, 0x0054}, /* 00,84,54,aa */ |
@@ -5742,8 +5746,7 @@ static const struct usb_action tas5130c_vf0250_50HZScale[] = { | |||
5742 | {} | 5746 | {} |
5743 | }; | 5747 | }; |
5744 | 5748 | ||
5745 | /* "60HZ" light frequency banding filter */ | 5749 | static const struct usb_action tas5130c_vf0250_60HZScale[] = { |
5746 | static const struct usb_action tas5130c_vf0250_60HZ[] = { | ||
5747 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ | 5750 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ |
5748 | {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */ | 5751 | {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */ |
5749 | {0xaa, 0x84, 0x0062}, /* 00,84,62,aa */ | 5752 | {0xaa, 0x84, 0x0062}, /* 00,84,62,aa */ |
@@ -5767,8 +5770,7 @@ static const struct usb_action tas5130c_vf0250_60HZ[] = { | |||
5767 | {} | 5770 | {} |
5768 | }; | 5771 | }; |
5769 | 5772 | ||
5770 | /* "60HZScale" light frequency banding ilter */ | 5773 | static const struct usb_action tas5130c_vf0250_60HZ[] = { |
5771 | static const struct usb_action tas5130c_vf0250_60HZScale[] = { | ||
5772 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ | 5774 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ |
5773 | {0xaa, 0x83, 0x0002}, /* 00,83,02,aa */ | 5775 | {0xaa, 0x83, 0x0002}, /* 00,83,02,aa */ |
5774 | {0xaa, 0x84, 0x00c4}, /* 00,84,c4,aa */ | 5776 | {0xaa, 0x84, 0x00c4}, /* 00,84,c4,aa */ |
@@ -5792,8 +5794,7 @@ static const struct usb_action tas5130c_vf0250_60HZScale[] = { | |||
5792 | {} | 5794 | {} |
5793 | }; | 5795 | }; |
5794 | 5796 | ||
5795 | /* "NoFliker" light frequency banding flter */ | 5797 | static const struct usb_action tas5130c_vf0250_NoFlikerScale[] = { |
5796 | static const struct usb_action tas5130c_vf0250_NoFliker[] = { | ||
5797 | {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */ | 5798 | {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */ |
5798 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ | 5799 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ |
5799 | {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */ | 5800 | {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */ |
@@ -5815,8 +5816,7 @@ static const struct usb_action tas5130c_vf0250_NoFliker[] = { | |||
5815 | {} | 5816 | {} |
5816 | }; | 5817 | }; |
5817 | 5818 | ||
5818 | /* "NoFlikerScale" light frequency banding filter */ | 5819 | static const struct usb_action tas5130c_vf0250_NoFliker[] = { |
5819 | static const struct usb_action tas5130c_vf0250_NoFlikerScale[] = { | ||
5820 | {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */ | 5820 | {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */ |
5821 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ | 5821 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ |
5822 | {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */ | 5822 | {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */ |
@@ -5839,7 +5839,7 @@ static const struct usb_action tas5130c_vf0250_NoFlikerScale[] = { | |||
5839 | }; | 5839 | }; |
5840 | 5840 | ||
5841 | static u8 reg_r_i(struct gspca_dev *gspca_dev, | 5841 | static u8 reg_r_i(struct gspca_dev *gspca_dev, |
5842 | __u16 index) | 5842 | u16 index) |
5843 | { | 5843 | { |
5844 | usb_control_msg(gspca_dev->dev, | 5844 | usb_control_msg(gspca_dev->dev, |
5845 | usb_rcvctrlpipe(gspca_dev->dev, 0), | 5845 | usb_rcvctrlpipe(gspca_dev->dev, 0), |
@@ -5852,7 +5852,7 @@ static u8 reg_r_i(struct gspca_dev *gspca_dev, | |||
5852 | } | 5852 | } |
5853 | 5853 | ||
5854 | static u8 reg_r(struct gspca_dev *gspca_dev, | 5854 | static u8 reg_r(struct gspca_dev *gspca_dev, |
5855 | __u16 index) | 5855 | u16 index) |
5856 | { | 5856 | { |
5857 | u8 ret; | 5857 | u8 ret; |
5858 | 5858 | ||
@@ -5862,8 +5862,8 @@ static u8 reg_r(struct gspca_dev *gspca_dev, | |||
5862 | } | 5862 | } |
5863 | 5863 | ||
5864 | static void reg_w_i(struct usb_device *dev, | 5864 | static void reg_w_i(struct usb_device *dev, |
5865 | __u8 value, | 5865 | u8 value, |
5866 | __u16 index) | 5866 | u16 index) |
5867 | { | 5867 | { |
5868 | usb_control_msg(dev, | 5868 | usb_control_msg(dev, |
5869 | usb_sndctrlpipe(dev, 0), | 5869 | usb_sndctrlpipe(dev, 0), |
@@ -5874,18 +5874,18 @@ static void reg_w_i(struct usb_device *dev, | |||
5874 | } | 5874 | } |
5875 | 5875 | ||
5876 | static void reg_w(struct usb_device *dev, | 5876 | static void reg_w(struct usb_device *dev, |
5877 | __u8 value, | 5877 | u8 value, |
5878 | __u16 index) | 5878 | u16 index) |
5879 | { | 5879 | { |
5880 | PDEBUG(D_USBO, "reg w [%04x] = %02x", index, value); | 5880 | PDEBUG(D_USBO, "reg w [%04x] = %02x", index, value); |
5881 | reg_w_i(dev, value, index); | 5881 | reg_w_i(dev, value, index); |
5882 | } | 5882 | } |
5883 | 5883 | ||
5884 | static __u16 i2c_read(struct gspca_dev *gspca_dev, | 5884 | static u16 i2c_read(struct gspca_dev *gspca_dev, |
5885 | __u8 reg) | 5885 | u8 reg) |
5886 | { | 5886 | { |
5887 | __u8 retbyte; | 5887 | u8 retbyte; |
5888 | __u16 retval; | 5888 | u16 retval; |
5889 | 5889 | ||
5890 | reg_w_i(gspca_dev->dev, reg, 0x0092); | 5890 | reg_w_i(gspca_dev->dev, reg, 0x0092); |
5891 | reg_w_i(gspca_dev->dev, 0x02, 0x0090); /* <- read command */ | 5891 | reg_w_i(gspca_dev->dev, 0x02, 0x0090); /* <- read command */ |
@@ -5900,12 +5900,12 @@ static __u16 i2c_read(struct gspca_dev *gspca_dev, | |||
5900 | return retval; | 5900 | return retval; |
5901 | } | 5901 | } |
5902 | 5902 | ||
5903 | static __u8 i2c_write(struct gspca_dev *gspca_dev, | 5903 | static u8 i2c_write(struct gspca_dev *gspca_dev, |
5904 | __u8 reg, | 5904 | u8 reg, |
5905 | __u8 valL, | 5905 | u8 valL, |
5906 | __u8 valH) | 5906 | u8 valH) |
5907 | { | 5907 | { |
5908 | __u8 retbyte; | 5908 | u8 retbyte; |
5909 | 5909 | ||
5910 | reg_w_i(gspca_dev->dev, reg, 0x92); | 5910 | reg_w_i(gspca_dev->dev, reg, 0x92); |
5911 | reg_w_i(gspca_dev->dev, valL, 0x93); | 5911 | reg_w_i(gspca_dev->dev, valL, 0x93); |
@@ -5957,24 +5957,24 @@ static void setmatrix(struct gspca_dev *gspca_dev) | |||
5957 | { | 5957 | { |
5958 | struct sd *sd = (struct sd *) gspca_dev; | 5958 | struct sd *sd = (struct sd *) gspca_dev; |
5959 | int i; | 5959 | int i; |
5960 | const __u8 *matrix; | 5960 | const u8 *matrix; |
5961 | static const u8 adcm2700_matrix[9] = | 5961 | static const u8 adcm2700_matrix[9] = |
5962 | /* {0x66, 0xed, 0xed, 0xed, 0x66, 0xed, 0xed, 0xed, 0x66}; */ | 5962 | /* {0x66, 0xed, 0xed, 0xed, 0x66, 0xed, 0xed, 0xed, 0x66}; */ |
5963 | /*ms-win*/ | 5963 | /*ms-win*/ |
5964 | {0x74, 0xed, 0xed, 0xed, 0x74, 0xed, 0xed, 0xed, 0x74}; | 5964 | {0x74, 0xed, 0xed, 0xed, 0x74, 0xed, 0xed, 0xed, 0x74}; |
5965 | static const __u8 gc0305_matrix[9] = | 5965 | static const u8 gc0305_matrix[9] = |
5966 | {0x50, 0xf8, 0xf8, 0xf8, 0x50, 0xf8, 0xf8, 0xf8, 0x50}; | 5966 | {0x50, 0xf8, 0xf8, 0xf8, 0x50, 0xf8, 0xf8, 0xf8, 0x50}; |
5967 | static const __u8 ov7620_matrix[9] = | 5967 | static const u8 ov7620_matrix[9] = |
5968 | {0x58, 0xf4, 0xf4, 0xf4, 0x58, 0xf4, 0xf4, 0xf4, 0x58}; | 5968 | {0x58, 0xf4, 0xf4, 0xf4, 0x58, 0xf4, 0xf4, 0xf4, 0x58}; |
5969 | static const __u8 pas202b_matrix[9] = | 5969 | static const u8 pas202b_matrix[9] = |
5970 | {0x4c, 0xf5, 0xff, 0xf9, 0x51, 0xf5, 0xfb, 0xed, 0x5f}; | 5970 | {0x4c, 0xf5, 0xff, 0xf9, 0x51, 0xf5, 0xfb, 0xed, 0x5f}; |
5971 | static const __u8 po2030_matrix[9] = | 5971 | static const u8 po2030_matrix[9] = |
5972 | {0x60, 0xf0, 0xf0, 0xf0, 0x60, 0xf0, 0xf0, 0xf0, 0x60}; | 5972 | {0x60, 0xf0, 0xf0, 0xf0, 0x60, 0xf0, 0xf0, 0xf0, 0x60}; |
5973 | static const u8 tas5130c_matrix[9] = | 5973 | static const u8 tas5130c_matrix[9] = |
5974 | {0x68, 0xec, 0xec, 0xec, 0x68, 0xec, 0xec, 0xec, 0x68}; | 5974 | {0x68, 0xec, 0xec, 0xec, 0x68, 0xec, 0xec, 0xec, 0x68}; |
5975 | static const __u8 vf0250_matrix[9] = | 5975 | static const u8 vf0250_matrix[9] = |
5976 | {0x7b, 0xea, 0xea, 0xea, 0x7b, 0xea, 0xea, 0xea, 0x7b}; | 5976 | {0x7b, 0xea, 0xea, 0xea, 0x7b, 0xea, 0xea, 0xea, 0x7b}; |
5977 | static const __u8 *matrix_tb[SENSOR_MAX] = { | 5977 | static const u8 *matrix_tb[SENSOR_MAX] = { |
5978 | adcm2700_matrix, /* SENSOR_ADCM2700 0 */ | 5978 | adcm2700_matrix, /* SENSOR_ADCM2700 0 */ |
5979 | ov7620_matrix, /* SENSOR_CS2102 1 */ | 5979 | ov7620_matrix, /* SENSOR_CS2102 1 */ |
5980 | NULL, /* SENSOR_CS2102K 2 */ | 5980 | NULL, /* SENSOR_CS2102K 2 */ |
@@ -6006,11 +6006,12 @@ static void setmatrix(struct gspca_dev *gspca_dev) | |||
6006 | static void setbrightness(struct gspca_dev *gspca_dev) | 6006 | static void setbrightness(struct gspca_dev *gspca_dev) |
6007 | { | 6007 | { |
6008 | struct sd *sd = (struct sd *) gspca_dev; | 6008 | struct sd *sd = (struct sd *) gspca_dev; |
6009 | __u8 brightness; | 6009 | u8 brightness; |
6010 | 6010 | ||
6011 | switch (sd->sensor) { | 6011 | switch (sd->sensor) { |
6012 | case SENSOR_GC0305: | 6012 | case SENSOR_GC0305: |
6013 | case SENSOR_OV7620: | 6013 | case SENSOR_OV7620: |
6014 | case SENSOR_PAS202B: | ||
6014 | case SENSOR_PO2030: | 6015 | case SENSOR_PO2030: |
6015 | return; | 6016 | return; |
6016 | } | 6017 | } |
@@ -6034,7 +6035,7 @@ static void setsharpness(struct gspca_dev *gspca_dev) | |||
6034 | struct sd *sd = (struct sd *) gspca_dev; | 6035 | struct sd *sd = (struct sd *) gspca_dev; |
6035 | struct usb_device *dev = gspca_dev->dev; | 6036 | struct usb_device *dev = gspca_dev->dev; |
6036 | int sharpness; | 6037 | int sharpness; |
6037 | static const __u8 sharpness_tb[][2] = { | 6038 | static const u8 sharpness_tb[][2] = { |
6038 | {0x02, 0x03}, | 6039 | {0x02, 0x03}, |
6039 | {0x04, 0x07}, | 6040 | {0x04, 0x07}, |
6040 | {0x08, 0x0f}, | 6041 | {0x08, 0x0f}, |
@@ -6053,118 +6054,69 @@ static void setcontrast(struct gspca_dev *gspca_dev) | |||
6053 | { | 6054 | { |
6054 | struct sd *sd = (struct sd *) gspca_dev; | 6055 | struct sd *sd = (struct sd *) gspca_dev; |
6055 | struct usb_device *dev = gspca_dev->dev; | 6056 | struct usb_device *dev = gspca_dev->dev; |
6056 | const __u8 *Tgamma, *Tgradient; | 6057 | const u8 *Tgamma; |
6057 | int g, i, k; | 6058 | int g, i, k, adj, gp; |
6058 | static const __u8 kgamma_tb[16] = /* delta for contrast */ | 6059 | u8 gr[16]; |
6060 | static const u8 delta_tb[16] = /* delta for contrast */ | ||
6059 | {0x15, 0x0d, 0x0a, 0x09, 0x08, 0x08, 0x08, 0x08, | 6061 | {0x15, 0x0d, 0x0a, 0x09, 0x08, 0x08, 0x08, 0x08, |
6060 | 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}; | 6062 | 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}; |
6061 | static const __u8 kgrad_tb[16] = | 6063 | static const u8 gamma_tb[6][16] = { |
6062 | {0x1b, 0x06, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, | ||
6063 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x04}; | ||
6064 | static const __u8 Tgamma_1[16] = | ||
6065 | {0x00, 0x00, 0x03, 0x0d, 0x1b, 0x2e, 0x45, 0x5f, | 6064 | {0x00, 0x00, 0x03, 0x0d, 0x1b, 0x2e, 0x45, 0x5f, |
6066 | 0x79, 0x93, 0xab, 0xc1, 0xd4, 0xe5, 0xf3, 0xff}; | 6065 | 0x79, 0x93, 0xab, 0xc1, 0xd4, 0xe5, 0xf3, 0xff}, |
6067 | static const __u8 Tgradient_1[16] = | ||
6068 | {0x00, 0x01, 0x05, 0x0b, 0x10, 0x15, 0x18, 0x1a, | ||
6069 | 0x1a, 0x18, 0x16, 0x14, 0x12, 0x0f, 0x0d, 0x06}; | ||
6070 | static const __u8 Tgamma_2[16] = | ||
6071 | {0x01, 0x0c, 0x1f, 0x3a, 0x53, 0x6d, 0x85, 0x9c, | 6066 | {0x01, 0x0c, 0x1f, 0x3a, 0x53, 0x6d, 0x85, 0x9c, |
6072 | 0xb0, 0xc2, 0xd1, 0xde, 0xe9, 0xf2, 0xf9, 0xff}; | 6067 | 0xb0, 0xc2, 0xd1, 0xde, 0xe9, 0xf2, 0xf9, 0xff}, |
6073 | static const __u8 Tgradient_2[16] = | ||
6074 | {0x05, 0x0f, 0x16, 0x1a, 0x19, 0x19, 0x17, 0x15, | ||
6075 | 0x12, 0x10, 0x0e, 0x0b, 0x09, 0x08, 0x06, 0x03}; | ||
6076 | static const __u8 Tgamma_3[16] = | ||
6077 | {0x04, 0x16, 0x30, 0x4e, 0x68, 0x81, 0x98, 0xac, | 6068 | {0x04, 0x16, 0x30, 0x4e, 0x68, 0x81, 0x98, 0xac, |
6078 | 0xbe, 0xcd, 0xda, 0xe4, 0xed, 0xf5, 0xfb, 0xff}; | 6069 | 0xbe, 0xcd, 0xda, 0xe4, 0xed, 0xf5, 0xfb, 0xff}, |
6079 | static const __u8 Tgradient_3[16] = | ||
6080 | {0x0c, 0x16, 0x1b, 0x1c, 0x19, 0x18, 0x15, 0x12, | ||
6081 | 0x10, 0x0d, 0x0b, 0x09, 0x08, 0x06, 0x05, 0x03}; | ||
6082 | static const __u8 Tgamma_4[16] = | ||
6083 | {0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, | 6070 | {0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8, |
6084 | 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff}; | 6071 | 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff}, |
6085 | static const __u8 Tgradient_4[16] = | ||
6086 | {0x26, 0x22, 0x20, 0x1c, 0x16, 0x13, 0x10, 0x0d, | ||
6087 | 0x0b, 0x09, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02}; | ||
6088 | static const __u8 Tgamma_5[16] = | ||
6089 | {0x20, 0x4b, 0x6e, 0x8d, 0xa3, 0xb5, 0xc5, 0xd2, | 6072 | {0x20, 0x4b, 0x6e, 0x8d, 0xa3, 0xb5, 0xc5, 0xd2, |
6090 | 0xdc, 0xe5, 0xec, 0xf2, 0xf6, 0xfa, 0xfd, 0xff}; | 6073 | 0xdc, 0xe5, 0xec, 0xf2, 0xf6, 0xfa, 0xfd, 0xff}, |
6091 | static const __u8 Tgradient_5[16] = | ||
6092 | {0x37, 0x26, 0x20, 0x1a, 0x14, 0x10, 0x0e, 0x0b, | ||
6093 | 0x09, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x02}; | ||
6094 | static const __u8 Tgamma_6[16] = /* ?? was gamma 5 */ | ||
6095 | {0x24, 0x44, 0x64, 0x84, 0x9d, 0xb2, 0xc4, 0xd3, | 6074 | {0x24, 0x44, 0x64, 0x84, 0x9d, 0xb2, 0xc4, 0xd3, |
6096 | 0xe0, 0xeb, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff}; | 6075 | 0xe0, 0xeb, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff}, |
6097 | static const __u8 Tgradient_6[16] = | ||
6098 | {0x18, 0x20, 0x20, 0x1c, 0x16, 0x13, 0x10, 0x0e, | ||
6099 | 0x0b, 0x09, 0x07, 0x00, 0x00, 0x00, 0x00, 0x01}; | ||
6100 | static const __u8 *gamma_tb[] = { | ||
6101 | NULL, Tgamma_1, Tgamma_2, | ||
6102 | Tgamma_3, Tgamma_4, Tgamma_5, Tgamma_6 | ||
6103 | }; | 6076 | }; |
6104 | static const __u8 *gradient_tb[] = { | ||
6105 | NULL, Tgradient_1, Tgradient_2, | ||
6106 | Tgradient_3, Tgradient_4, Tgradient_5, Tgradient_6 | ||
6107 | }; | ||
6108 | #ifdef GSPCA_DEBUG | ||
6109 | __u8 v[16]; | ||
6110 | #endif | ||
6111 | 6077 | ||
6112 | Tgamma = gamma_tb[sd->gamma]; | 6078 | Tgamma = gamma_tb[sd->gamma - 1]; |
6113 | Tgradient = gradient_tb[sd->gamma]; | ||
6114 | 6079 | ||
6115 | k = (sd->contrast - 128) /* -128 / 128 */ | 6080 | k = ((int) sd->contrast - 128); /* -128 / 128 */ |
6116 | * Tgamma[0]; | 6081 | adj = 0; |
6117 | PDEBUG(D_CONF, "gamma:%d contrast:%d gamma coeff: %d/128", | 6082 | gp = 0; |
6118 | sd->gamma, sd->contrast, k); | ||
6119 | for (i = 0; i < 16; i++) { | 6083 | for (i = 0; i < 16; i++) { |
6120 | g = Tgamma[i] + kgamma_tb[i] * k / 128; | 6084 | g = Tgamma[i] - delta_tb[i] * k / 128 - adj / 2; |
6121 | if (g > 0xff) | 6085 | if (g > 0xff) |
6122 | g = 0xff; | 6086 | g = 0xff; |
6123 | else if (g <= 0) | 6087 | else if (g <= 0) |
6124 | g = 1; | 6088 | g = 1; |
6125 | reg_w(dev, g, 0x0120 + i); /* gamma */ | 6089 | reg_w(dev, g, 0x0120 + i); /* gamma */ |
6126 | #ifdef GSPCA_DEBUG | 6090 | if (k > 0) |
6127 | if (gspca_debug & D_CONF) | 6091 | adj--; |
6128 | v[i] = g; | 6092 | else |
6129 | #endif | 6093 | adj++; |
6130 | } | 6094 | |
6131 | PDEBUG(D_CONF, "tb: %02x %02x %02x %02x %02x %02x %02x %02x", | 6095 | if (i != 0) { |
6132 | v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]); | 6096 | if (gp == 0) |
6133 | PDEBUG(D_CONF, " %02x %02x %02x %02x %02x %02x %02x %02x", | 6097 | gr[i - 1] = 0; |
6134 | v[8], v[9], v[10], v[11], v[12], v[13], v[14], v[15]); | ||
6135 | for (i = 0; i < 16; i++) { | ||
6136 | g = Tgradient[i] - kgrad_tb[i] * k / 128; | ||
6137 | if (g > 0xff) | ||
6138 | g = 0xff; | ||
6139 | else if (g <= 0) { | ||
6140 | if (i != 15) | ||
6141 | g = 0; | ||
6142 | else | 6098 | else |
6143 | g = 1; | 6099 | gr[i - 1] = g - gp; |
6144 | } | 6100 | } |
6145 | reg_w(dev, g, 0x0130 + i); /* gradient */ | 6101 | gp = g; |
6146 | #ifdef GSPCA_DEBUG | ||
6147 | if (gspca_debug & D_CONF) | ||
6148 | v[i] = g; | ||
6149 | #endif | ||
6150 | } | 6102 | } |
6151 | PDEBUG(D_CONF, " %02x %02x %02x %02x %02x %02x %02x %02x", | 6103 | gr[15] = gr[14] / 2; |
6152 | v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]); | 6104 | for (i = 0; i < 16; i++) |
6153 | PDEBUG(D_CONF, " %02x %02x %02x %02x %02x %02x %02x %02x", | 6105 | reg_w(dev, gr[i], 0x0130 + i); /* gradient */ |
6154 | v[8], v[9], v[10], v[11], v[12], v[13], v[14], v[15]); | ||
6155 | } | 6106 | } |
6156 | 6107 | ||
6157 | static void setquality(struct gspca_dev *gspca_dev) | 6108 | static void setquality(struct gspca_dev *gspca_dev) |
6158 | { | 6109 | { |
6159 | struct sd *sd = (struct sd *) gspca_dev; | 6110 | struct sd *sd = (struct sd *) gspca_dev; |
6160 | struct usb_device *dev = gspca_dev->dev; | 6111 | struct usb_device *dev = gspca_dev->dev; |
6161 | __u8 frxt; | 6112 | u8 frxt; |
6162 | 6113 | ||
6163 | switch (sd->sensor) { | 6114 | switch (sd->sensor) { |
6164 | case SENSOR_ADCM2700: | 6115 | case SENSOR_ADCM2700: |
6165 | case SENSOR_GC0305: | 6116 | case SENSOR_GC0305: |
6166 | case SENSOR_HV7131B: | 6117 | case SENSOR_HV7131B: |
6167 | case SENSOR_OV7620: | 6118 | case SENSOR_OV7620: |
6119 | case SENSOR_PAS202B: | ||
6168 | case SENSOR_PO2030: | 6120 | case SENSOR_PO2030: |
6169 | return; | 6121 | return; |
6170 | } | 6122 | } |
@@ -6218,9 +6170,9 @@ static int setlightfreq(struct gspca_dev *gspca_dev) | |||
6218 | hdcs2020b_50HZ, hdcs2020b_50HZ, | 6170 | hdcs2020b_50HZ, hdcs2020b_50HZ, |
6219 | hdcs2020b_60HZ, hdcs2020b_60HZ}, | 6171 | hdcs2020b_60HZ, hdcs2020b_60HZ}, |
6220 | /* SENSOR_HV7131B 5 */ | 6172 | /* SENSOR_HV7131B 5 */ |
6221 | {hv7131b_NoFlikerScale, hv7131b_NoFliker, | 6173 | {hv7131b_NoFliker, hv7131b_NoFlikerScale, |
6222 | hv7131b_50HZScale, hv7131b_50HZ, | 6174 | hv7131b_50HZ, hv7131b_50HZScale, |
6223 | hv7131b_60HZScale, hv7131b_60HZ}, | 6175 | hv7131b_60HZ, hv7131b_60HZScale}, |
6224 | /* SENSOR_HV7131C 6 */ | 6176 | /* SENSOR_HV7131C 6 */ |
6225 | {NULL, NULL, | 6177 | {NULL, NULL, |
6226 | NULL, NULL, | 6178 | NULL, NULL, |
@@ -6230,17 +6182,17 @@ static int setlightfreq(struct gspca_dev *gspca_dev) | |||
6230 | icm105a_50HZ, icm105a_50HZScale, | 6182 | icm105a_50HZ, icm105a_50HZScale, |
6231 | icm105a_60HZ, icm105a_60HZScale}, | 6183 | icm105a_60HZ, icm105a_60HZScale}, |
6232 | /* SENSOR_MC501CB 8 */ | 6184 | /* SENSOR_MC501CB 8 */ |
6233 | {MC501CB_NoFliker, MC501CB_NoFlikerScale, | 6185 | {mc501cb_NoFliker, mc501cb_NoFlikerScale, |
6234 | MC501CB_50HZ, MC501CB_50HZScale, | 6186 | mc501cb_50HZ, mc501cb_50HZScale, |
6235 | MC501CB_60HZ, MC501CB_60HZScale}, | 6187 | mc501cb_60HZ, mc501cb_60HZScale}, |
6236 | /* SENSOR_MI0360SOC 9 */ | 6188 | /* SENSOR_MI0360SOC 9 */ |
6237 | {mi360soc_AENoFlikerScale, mi360soc_AENoFliker, | 6189 | {mi360soc_AENoFliker, mi360soc_AENoFlikerScale, |
6238 | mi360soc_AE50HZScale, mi360soc_AE50HZ, | 6190 | mi360soc_AE50HZ, mi360soc_AE50HZScale, |
6239 | mi360soc_AE60HZScale, mi360soc_AE60HZ}, | 6191 | mi360soc_AE60HZ, mi360soc_AE60HZScale}, |
6240 | /* SENSOR_OV7620 10 */ | 6192 | /* SENSOR_OV7620 10 */ |
6241 | {OV7620_NoFliker, OV7620_NoFliker, | 6193 | {ov7620_NoFliker, ov7620_NoFliker, |
6242 | OV7620_50HZ, OV7620_50HZ, | 6194 | ov7620_50HZ, ov7620_50HZ, |
6243 | OV7620_60HZ, OV7620_60HZ}, | 6195 | ov7620_60HZ, ov7620_60HZ}, |
6244 | /* SENSOR_OV7630C 11 */ | 6196 | /* SENSOR_OV7630C 11 */ |
6245 | {NULL, NULL, | 6197 | {NULL, NULL, |
6246 | NULL, NULL, | 6198 | NULL, NULL, |
@@ -6258,17 +6210,17 @@ static int setlightfreq(struct gspca_dev *gspca_dev) | |||
6258 | pb0330_50HZScale, pb0330_50HZ, | 6210 | pb0330_50HZScale, pb0330_50HZ, |
6259 | pb0330_60HZScale, pb0330_60HZ}, | 6211 | pb0330_60HZScale, pb0330_60HZ}, |
6260 | /* SENSOR_PO2030 15 */ | 6212 | /* SENSOR_PO2030 15 */ |
6261 | {PO2030_NoFliker, PO2030_NoFliker, | 6213 | {po2030_NoFliker, po2030_NoFliker, |
6262 | PO2030_50HZ, PO2030_50HZ, | 6214 | po2030_50HZ, po2030_50HZ, |
6263 | PO2030_60HZ, PO2030_60HZ}, | 6215 | po2030_60HZ, po2030_60HZ}, |
6264 | /* SENSOR_TAS5130CK 16 */ | 6216 | /* SENSOR_TAS5130CK 16 */ |
6265 | {tas5130cxx_NoFlikerScale, tas5130cxx_NoFliker, | 6217 | {tas5130cxx_NoFliker, tas5130cxx_NoFlikerScale, |
6266 | tas5130cxx_50HZScale, tas5130cxx_50HZ, | 6218 | tas5130cxx_50HZ, tas5130cxx_50HZScale, |
6267 | tas5130cxx_60HZScale, tas5130cxx_60HZ}, | 6219 | tas5130cxx_60HZ, tas5130cxx_60HZScale}, |
6268 | /* SENSOR_TAS5130CXX 17 */ | 6220 | /* SENSOR_TAS5130CXX 17 */ |
6269 | {tas5130cxx_NoFlikerScale, tas5130cxx_NoFliker, | 6221 | {tas5130cxx_NoFliker, tas5130cxx_NoFlikerScale, |
6270 | tas5130cxx_50HZScale, tas5130cxx_50HZ, | 6222 | tas5130cxx_50HZ, tas5130cxx_50HZScale, |
6271 | tas5130cxx_60HZScale, tas5130cxx_60HZ}, | 6223 | tas5130cxx_60HZ, tas5130cxx_60HZScale}, |
6272 | /* SENSOR_TAS5130C_VF0250 18 */ | 6224 | /* SENSOR_TAS5130C_VF0250 18 */ |
6273 | {tas5130c_vf0250_NoFliker, tas5130c_vf0250_NoFlikerScale, | 6225 | {tas5130c_vf0250_NoFliker, tas5130c_vf0250_NoFlikerScale, |
6274 | tas5130c_vf0250_50HZ, tas5130c_vf0250_50HZScale, | 6226 | tas5130c_vf0250_50HZ, tas5130c_vf0250_50HZScale, |
@@ -6277,9 +6229,9 @@ static int setlightfreq(struct gspca_dev *gspca_dev) | |||
6277 | 6229 | ||
6278 | i = sd->lightfreq * 2; | 6230 | i = sd->lightfreq * 2; |
6279 | mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; | 6231 | mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; |
6280 | if (!mode) | 6232 | if (mode) |
6281 | i++; /* 640x480 */ | 6233 | i++; /* 320x240 */ |
6282 | zc3_freq = freq_tb[(int) sd->sensor][i]; | 6234 | zc3_freq = freq_tb[sd->sensor][i]; |
6283 | if (zc3_freq != NULL) { | 6235 | if (zc3_freq != NULL) { |
6284 | usb_exchange(gspca_dev, zc3_freq); | 6236 | usb_exchange(gspca_dev, zc3_freq); |
6285 | switch (sd->sensor) { | 6237 | switch (sd->sensor) { |
@@ -6297,6 +6249,9 @@ static int setlightfreq(struct gspca_dev *gspca_dev) | |||
6297 | reg_w(gspca_dev->dev, 0x44, 0x0002); | 6249 | reg_w(gspca_dev->dev, 0x44, 0x0002); |
6298 | } | 6250 | } |
6299 | break; | 6251 | break; |
6252 | case SENSOR_PAS202B: | ||
6253 | reg_w(gspca_dev->dev, 0x00, 0x01a7); | ||
6254 | break; | ||
6300 | } | 6255 | } |
6301 | } | 6256 | } |
6302 | return 0; | 6257 | return 0; |
@@ -6305,7 +6260,7 @@ static int setlightfreq(struct gspca_dev *gspca_dev) | |||
6305 | static void setautogain(struct gspca_dev *gspca_dev) | 6260 | static void setautogain(struct gspca_dev *gspca_dev) |
6306 | { | 6261 | { |
6307 | struct sd *sd = (struct sd *) gspca_dev; | 6262 | struct sd *sd = (struct sd *) gspca_dev; |
6308 | __u8 autoval; | 6263 | u8 autoval; |
6309 | 6264 | ||
6310 | if (sd->autogain) | 6265 | if (sd->autogain) |
6311 | autoval = 0x42; | 6266 | autoval = 0x42; |
@@ -6333,6 +6288,12 @@ static void send_unknown(struct usb_device *dev, int sensor) | |||
6333 | reg_w(dev, 0x02, 0x003b); | 6288 | reg_w(dev, 0x02, 0x003b); |
6334 | reg_w(dev, 0x00, 0x0038); | 6289 | reg_w(dev, 0x00, 0x0038); |
6335 | break; | 6290 | break; |
6291 | case SENSOR_PAS202B: | ||
6292 | reg_w(dev, 0x03, 0x003b); | ||
6293 | reg_w(dev, 0x0c, 0x003a); | ||
6294 | reg_w(dev, 0x0b, 0x0039); | ||
6295 | reg_w(dev, 0x0b, 0x0038); | ||
6296 | break; | ||
6336 | } | 6297 | } |
6337 | } | 6298 | } |
6338 | 6299 | ||
@@ -6349,7 +6310,7 @@ static void start_2wr_probe(struct usb_device *dev, int sensor) | |||
6349 | 6310 | ||
6350 | static int sif_probe(struct gspca_dev *gspca_dev) | 6311 | static int sif_probe(struct gspca_dev *gspca_dev) |
6351 | { | 6312 | { |
6352 | __u16 checkword; | 6313 | u16 checkword; |
6353 | 6314 | ||
6354 | start_2wr_probe(gspca_dev->dev, 0x0f); /* PAS106 */ | 6315 | start_2wr_probe(gspca_dev->dev, 0x0f); /* PAS106 */ |
6355 | reg_w(gspca_dev->dev, 0x08, 0x008d); | 6316 | reg_w(gspca_dev->dev, 0x08, 0x008d); |
@@ -6392,6 +6353,7 @@ static int vga_2wr_probe(struct gspca_dev *gspca_dev) | |||
6392 | } | 6353 | } |
6393 | 6354 | ||
6394 | start_2wr_probe(dev, 0x08); /* HDCS2020 */ | 6355 | start_2wr_probe(dev, 0x08); /* HDCS2020 */ |
6356 | i2c_write(gspca_dev, 0x1c, 0x00, 0x00); | ||
6395 | i2c_write(gspca_dev, 0x15, 0xaa, 0x00); | 6357 | i2c_write(gspca_dev, 0x15, 0xaa, 0x00); |
6396 | retword = i2c_read(gspca_dev, 0x15); | 6358 | retword = i2c_read(gspca_dev, 0x15); |
6397 | if (retword != 0) | 6359 | if (retword != 0) |
@@ -6420,8 +6382,10 @@ static int vga_2wr_probe(struct gspca_dev *gspca_dev) | |||
6420 | i2c_write(gspca_dev, 0x03, 0xaa, 0x00); | 6382 | i2c_write(gspca_dev, 0x03, 0xaa, 0x00); |
6421 | msleep(50); | 6383 | msleep(50); |
6422 | retword = i2c_read(gspca_dev, 0x03); | 6384 | retword = i2c_read(gspca_dev, 0x03); |
6423 | if (retword != 0) | 6385 | if (retword != 0) { |
6386 | send_unknown(dev, SENSOR_PAS202B); | ||
6424 | return 0x0e; /* PAS202BCB */ | 6387 | return 0x0e; /* PAS202BCB */ |
6388 | } | ||
6425 | 6389 | ||
6426 | start_2wr_probe(dev, 0x02); /* TAS5130C */ | 6390 | start_2wr_probe(dev, 0x02); /* TAS5130C */ |
6427 | i2c_write(gspca_dev, 0x01, 0xaa, 0x00); | 6391 | i2c_write(gspca_dev, 0x01, 0xaa, 0x00); |
@@ -6457,8 +6421,8 @@ ov_check: | |||
6457 | } | 6421 | } |
6458 | 6422 | ||
6459 | struct sensor_by_chipset_revision { | 6423 | struct sensor_by_chipset_revision { |
6460 | __u16 revision; | 6424 | u16 revision; |
6461 | __u8 internal_sensor_id; | 6425 | u8 internal_sensor_id; |
6462 | }; | 6426 | }; |
6463 | static const struct sensor_by_chipset_revision chipset_revision_sensor[] = { | 6427 | static const struct sensor_by_chipset_revision chipset_revision_sensor[] = { |
6464 | {0xc000, 0x12}, /* TAS5130C */ | 6428 | {0xc000, 0x12}, /* TAS5130C */ |
@@ -6467,6 +6431,7 @@ static const struct sensor_by_chipset_revision chipset_revision_sensor[] = { | |||
6467 | {0x8001, 0x13}, | 6431 | {0x8001, 0x13}, |
6468 | {0x8000, 0x14}, /* CS2102K */ | 6432 | {0x8000, 0x14}, /* CS2102K */ |
6469 | {0x8400, 0x15}, /* TAS5130K */ | 6433 | {0x8400, 0x15}, /* TAS5130K */ |
6434 | {0xe400, 0x15}, | ||
6470 | }; | 6435 | }; |
6471 | 6436 | ||
6472 | static int vga_3wr_probe(struct gspca_dev *gspca_dev) | 6437 | static int vga_3wr_probe(struct gspca_dev *gspca_dev) |
@@ -6474,7 +6439,7 @@ static int vga_3wr_probe(struct gspca_dev *gspca_dev) | |||
6474 | struct sd *sd = (struct sd *) gspca_dev; | 6439 | struct sd *sd = (struct sd *) gspca_dev; |
6475 | struct usb_device *dev = gspca_dev->dev; | 6440 | struct usb_device *dev = gspca_dev->dev; |
6476 | int i; | 6441 | int i; |
6477 | __u8 retbyte; | 6442 | u8 retbyte; |
6478 | u16 retword; | 6443 | u16 retword; |
6479 | 6444 | ||
6480 | /*fixme: lack of 8b=b3 (11,12)-> 10, 8b=e0 (14,15,16)-> 12 found in gspcav1*/ | 6445 | /*fixme: lack of 8b=b3 (11,12)-> 10, 8b=e0 (14,15,16)-> 12 found in gspcav1*/ |
@@ -6622,8 +6587,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
6622 | struct sd *sd = (struct sd *) gspca_dev; | 6587 | struct sd *sd = (struct sd *) gspca_dev; |
6623 | struct cam *cam; | 6588 | struct cam *cam; |
6624 | int sensor; | 6589 | int sensor; |
6625 | int vga = 1; /* 1: vga, 0: sif */ | 6590 | static const u8 gamma[SENSOR_MAX] = { |
6626 | static const __u8 gamma[SENSOR_MAX] = { | ||
6627 | 4, /* SENSOR_ADCM2700 0 */ | 6591 | 4, /* SENSOR_ADCM2700 0 */ |
6628 | 4, /* SENSOR_CS2102 1 */ | 6592 | 4, /* SENSOR_CS2102 1 */ |
6629 | 5, /* SENSOR_CS2102K 2 */ | 6593 | 5, /* SENSOR_CS2102K 2 */ |
@@ -6644,9 +6608,30 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
6644 | 3, /* SENSOR_TAS5130CXX 17 */ | 6608 | 3, /* SENSOR_TAS5130CXX 17 */ |
6645 | 3, /* SENSOR_TAS5130C_VF0250 18 */ | 6609 | 3, /* SENSOR_TAS5130C_VF0250 18 */ |
6646 | }; | 6610 | }; |
6611 | static const u8 mode_tb[SENSOR_MAX] = { | ||
6612 | 2, /* SENSOR_ADCM2700 0 */ | ||
6613 | 1, /* SENSOR_CS2102 1 */ | ||
6614 | 1, /* SENSOR_CS2102K 2 */ | ||
6615 | 1, /* SENSOR_GC0305 3 */ | ||
6616 | 1, /* SENSOR_HDCS2020b 4 */ | ||
6617 | 1, /* SENSOR_HV7131B 5 */ | ||
6618 | 1, /* SENSOR_HV7131C 6 */ | ||
6619 | 1, /* SENSOR_ICM105A 7 */ | ||
6620 | 2, /* SENSOR_MC501CB 8 */ | ||
6621 | 1, /* SENSOR_MI0360SOC 9 */ | ||
6622 | 2, /* SENSOR_OV7620 10 */ | ||
6623 | 1, /* SENSOR_OV7630C 11 */ | ||
6624 | 0, /* SENSOR_PAS106 12 */ | ||
6625 | 1, /* SENSOR_PAS202B 13 */ | ||
6626 | 1, /* SENSOR_PB0330 14 */ | ||
6627 | 1, /* SENSOR_PO2030 15 */ | ||
6628 | 1, /* SENSOR_TAS5130CK 16 */ | ||
6629 | 1, /* SENSOR_TAS5130CXX 17 */ | ||
6630 | 1, /* SENSOR_TAS5130C_VF0250 18 */ | ||
6631 | }; | ||
6647 | 6632 | ||
6648 | /* define some sensors from the vendor/product */ | 6633 | /* define some sensors from the vendor/product */ |
6649 | sd->sharpness = 2; | 6634 | sd->sharpness = SHARPNESS_DEF; |
6650 | sd->sensor = id->driver_info; | 6635 | sd->sensor = id->driver_info; |
6651 | sensor = zcxx_probeSensor(gspca_dev); | 6636 | sensor = zcxx_probeSensor(gspca_dev); |
6652 | if (sensor >= 0) | 6637 | if (sensor >= 0) |
@@ -6671,8 +6656,21 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
6671 | } | 6656 | } |
6672 | break; | 6657 | break; |
6673 | case 0: | 6658 | case 0: |
6674 | PDEBUG(D_PROBE, "Find Sensor HV7131B"); | 6659 | /* check the sensor type */ |
6675 | sd->sensor = SENSOR_HV7131B; | 6660 | sensor = i2c_read(gspca_dev, 0x00); |
6661 | PDEBUG(D_PROBE, "Sensor hv7131 type %d", sensor); | ||
6662 | switch (sensor) { | ||
6663 | case 0: /* hv7131b */ | ||
6664 | case 1: /* hv7131e */ | ||
6665 | PDEBUG(D_PROBE, "Find Sensor HV7131B"); | ||
6666 | sd->sensor = SENSOR_HV7131B; | ||
6667 | break; | ||
6668 | default: | ||
6669 | /* case 2: * hv7131r */ | ||
6670 | PDEBUG(D_PROBE, "Find Sensor HV7131R(c)"); | ||
6671 | sd->sensor = SENSOR_HV7131C; | ||
6672 | break; | ||
6673 | } | ||
6676 | break; | 6674 | break; |
6677 | case 0x02: | 6675 | case 0x02: |
6678 | PDEBUG(D_PROBE, "Sensor TAS5130C"); | 6676 | PDEBUG(D_PROBE, "Sensor TAS5130C"); |
@@ -6699,12 +6697,11 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
6699 | case 0x0e: | 6697 | case 0x0e: |
6700 | PDEBUG(D_PROBE, "Find Sensor PAS202B"); | 6698 | PDEBUG(D_PROBE, "Find Sensor PAS202B"); |
6701 | sd->sensor = SENSOR_PAS202B; | 6699 | sd->sensor = SENSOR_PAS202B; |
6702 | sd->sharpness = 1; | 6700 | /* sd->sharpness = 1; */ |
6703 | break; | 6701 | break; |
6704 | case 0x0f: | 6702 | case 0x0f: |
6705 | PDEBUG(D_PROBE, "Find Sensor PAS106"); | 6703 | PDEBUG(D_PROBE, "Find Sensor PAS106"); |
6706 | sd->sensor = SENSOR_PAS106; | 6704 | sd->sensor = SENSOR_PAS106; |
6707 | vga = 0; /* SIF */ | ||
6708 | break; | 6705 | break; |
6709 | case 0x10: | 6706 | case 0x10: |
6710 | case 0x12: | 6707 | case 0x12: |
@@ -6770,31 +6767,38 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
6770 | if (sensor < 0x20) { | 6767 | if (sensor < 0x20) { |
6771 | if (sensor == -1 || sensor == 0x10 || sensor == 0x12) | 6768 | if (sensor == -1 || sensor == 0x10 || sensor == 0x12) |
6772 | reg_w(gspca_dev->dev, 0x02, 0x0010); | 6769 | reg_w(gspca_dev->dev, 0x02, 0x0010); |
6773 | else | ||
6774 | reg_w(gspca_dev->dev, sensor & 0x0f, 0x0010); | ||
6775 | reg_r(gspca_dev, 0x0010); | 6770 | reg_r(gspca_dev, 0x0010); |
6776 | } | 6771 | } |
6777 | 6772 | ||
6778 | cam = &gspca_dev->cam; | 6773 | cam = &gspca_dev->cam; |
6779 | /*fixme:test*/ | 6774 | /*fixme:test*/ |
6780 | gspca_dev->nbalt--; | 6775 | gspca_dev->nbalt--; |
6781 | if (vga) { | 6776 | switch (mode_tb[sd->sensor]) { |
6782 | cam->cam_mode = vga_mode; | 6777 | case 0: |
6783 | cam->nmodes = ARRAY_SIZE(vga_mode); | ||
6784 | } else { | ||
6785 | cam->cam_mode = sif_mode; | 6778 | cam->cam_mode = sif_mode; |
6786 | cam->nmodes = ARRAY_SIZE(sif_mode); | 6779 | cam->nmodes = ARRAY_SIZE(sif_mode); |
6780 | break; | ||
6781 | case 1: | ||
6782 | cam->cam_mode = vga_mode; | ||
6783 | cam->nmodes = ARRAY_SIZE(vga_mode); | ||
6784 | break; | ||
6785 | default: | ||
6786 | /* case 2: */ | ||
6787 | cam->cam_mode = broken_vga_mode; | ||
6788 | cam->nmodes = ARRAY_SIZE(broken_vga_mode); | ||
6789 | break; | ||
6787 | } | 6790 | } |
6788 | sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value; | 6791 | sd->brightness = BRIGHTNESS_DEF; |
6789 | sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value; | 6792 | sd->contrast = CONTRAST_DEF; |
6790 | sd->gamma = gamma[(int) sd->sensor]; | 6793 | sd->gamma = gamma[sd->sensor]; |
6791 | sd->autogain = sd_ctrls[SD_AUTOGAIN].qctrl.default_value; | 6794 | sd->autogain = AUTOGAIN_DEF; |
6792 | sd->lightfreq = sd_ctrls[SD_FREQ].qctrl.default_value; | 6795 | sd->lightfreq = FREQ_DEF; |
6793 | sd->quality = QUALITY_DEF; | 6796 | sd->quality = QUALITY_DEF; |
6794 | 6797 | ||
6795 | switch (sd->sensor) { | 6798 | switch (sd->sensor) { |
6796 | case SENSOR_GC0305: | 6799 | case SENSOR_GC0305: |
6797 | case SENSOR_OV7620: | 6800 | case SENSOR_OV7620: |
6801 | case SENSOR_PAS202B: | ||
6798 | case SENSOR_PO2030: | 6802 | case SENSOR_PO2030: |
6799 | gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX); | 6803 | gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX); |
6800 | break; | 6804 | break; |
@@ -6805,14 +6809,13 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
6805 | break; | 6809 | break; |
6806 | } | 6810 | } |
6807 | 6811 | ||
6808 | /* switch the led off */ | ||
6809 | reg_w(gspca_dev->dev, 0x01, 0x0000); | ||
6810 | return 0; | 6812 | return 0; |
6811 | } | 6813 | } |
6812 | 6814 | ||
6813 | /* this function is called at probe and resume time */ | 6815 | /* this function is called at probe and resume time */ |
6814 | static int sd_init(struct gspca_dev *gspca_dev) | 6816 | static int sd_init(struct gspca_dev *gspca_dev) |
6815 | { | 6817 | { |
6818 | /* switch off the led */ | ||
6816 | reg_w(gspca_dev->dev, 0x01, 0x0000); | 6819 | reg_w(gspca_dev->dev, 0x01, 0x0000); |
6817 | return 0; | 6820 | return 0; |
6818 | } | 6821 | } |
@@ -6821,28 +6824,27 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6821 | { | 6824 | { |
6822 | struct sd *sd = (struct sd *) gspca_dev; | 6825 | struct sd *sd = (struct sd *) gspca_dev; |
6823 | struct usb_device *dev = gspca_dev->dev; | 6826 | struct usb_device *dev = gspca_dev->dev; |
6824 | const struct usb_action *zc3_init; | ||
6825 | int mode; | 6827 | int mode; |
6826 | static const struct usb_action *init_tb[SENSOR_MAX][2] = { | 6828 | static const struct usb_action *init_tb[SENSOR_MAX][2] = { |
6827 | {adcm2700_Initial, adcm2700_InitialScale}, /* 0 */ | 6829 | {adcm2700_Initial, adcm2700_InitialScale}, /* 0 */ |
6828 | {cs2102_InitialScale, cs2102_Initial}, /* 1 */ | 6830 | {cs2102_Initial, cs2102_InitialScale}, /* 1 */ |
6829 | {cs2102K_InitialScale, cs2102K_Initial}, /* 2 */ | 6831 | {cs2102K_Initial, cs2102K_InitialScale}, /* 2 */ |
6830 | {gc0305_Initial, gc0305_InitialScale}, /* 3 */ | 6832 | {gc0305_Initial, gc0305_InitialScale}, /* 3 */ |
6831 | {hdcs2020xb_InitialScale, hdcs2020xb_Initial}, /* 4 */ | 6833 | {hdcs2020b_Initial, hdcs2020b_InitialScale}, /* 4 */ |
6832 | {hv7131bxx_InitialScale, hv7131bxx_Initial}, /* 5 */ | 6834 | {hv7131b_Initial, hv7131b_InitialScale}, /* 5 */ |
6833 | {hv7131cxx_InitialScale, hv7131cxx_Initial}, /* 6 */ | 6835 | {hv7131r_Initial, hv7131r_InitialScale}, /* 6 */ |
6834 | {icm105axx_InitialScale, icm105axx_Initial}, /* 7 */ | 6836 | {icm105a_Initial, icm105a_InitialScale}, /* 7 */ |
6835 | {MC501CB_InitialScale, MC501CB_Initial}, /* 8 */ | 6837 | {mc501cb_Initial, mc501cb_InitialScale}, /* 8 */ |
6836 | {mi0360soc_Initial, mi0360soc_InitialScale}, /* 9 */ | 6838 | {mi0360soc_Initial, mi0360soc_InitialScale}, /* 9 */ |
6837 | {OV7620_mode0, OV7620_mode1}, /* 10 */ | 6839 | {ov7620_Initial, ov7620_InitialScale}, /* 10 */ |
6838 | {ov7630c_InitialScale, ov7630c_Initial}, /* 11 */ | 6840 | {ov7630c_Initial, ov7630c_InitialScale}, /* 11 */ |
6839 | {pas106b_InitialScale, pas106b_Initial}, /* 12 */ | 6841 | {pas106b_Initial, pas106b_InitialScale}, /* 12 */ |
6840 | {pas202b_Initial, pas202b_InitialScale}, /* 13 */ | 6842 | {pas202b_Initial, pas202b_InitialScale}, /* 13 */ |
6841 | {pb0330_Initial, pb0330_InitialScale}, /* 14 */ | 6843 | {pb0330_Initial, pb0330_InitialScale}, /* 14 */ |
6842 | {PO2030_mode0, PO2030_mode1}, /* 15 */ | 6844 | {po2030_Initial, po2030_InitialScale}, /* 15 */ |
6843 | {tas5130CK_InitialScale, tas5130CK_Initial}, /* 16 */ | 6845 | {tas5130cK_Initial, tas5130cK_InitialScale}, /* 16 */ |
6844 | {tas5130cxx_Initial, tas5130cxx_InitialScale}, /* 17 */ | 6846 | {tas5130cxx_Initial, tas5130cxx_InitialScale}, /* 17 */ |
6845 | {tas5130c_vf0250_InitialScale, tas5130c_vf0250_Initial}, | 6847 | {tas5130c_vf0250_Initial, tas5130c_vf0250_InitialScale}, |
6846 | /* 18 */ | 6848 | /* 18 */ |
6847 | }; | 6849 | }; |
6848 | 6850 | ||
@@ -6854,8 +6856,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6854 | 0x21); /* JPEG 422 */ | 6856 | 0x21); /* JPEG 422 */ |
6855 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | 6857 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); |
6856 | 6858 | ||
6857 | mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; | 6859 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; |
6858 | zc3_init = init_tb[(int) sd->sensor][mode]; | ||
6859 | switch (sd->sensor) { | 6860 | switch (sd->sensor) { |
6860 | case SENSOR_HV7131C: | 6861 | case SENSOR_HV7131C: |
6861 | zcxx_probeSensor(gspca_dev); | 6862 | zcxx_probeSensor(gspca_dev); |
@@ -6864,7 +6865,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6864 | usb_exchange(gspca_dev, pas106b_Initial_com); | 6865 | usb_exchange(gspca_dev, pas106b_Initial_com); |
6865 | break; | 6866 | break; |
6866 | } | 6867 | } |
6867 | usb_exchange(gspca_dev, zc3_init); | 6868 | usb_exchange(gspca_dev, init_tb[sd->sensor][mode]); |
6868 | 6869 | ||
6869 | switch (sd->sensor) { | 6870 | switch (sd->sensor) { |
6870 | case SENSOR_ADCM2700: | 6871 | case SENSOR_ADCM2700: |
@@ -6883,6 +6884,11 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6883 | reg_w(dev, 0x02, 0x003b); | 6884 | reg_w(dev, 0x02, 0x003b); |
6884 | reg_w(dev, 0x00, 0x0038); | 6885 | reg_w(dev, 0x00, 0x0038); |
6885 | break; | 6886 | break; |
6887 | case SENSOR_PAS202B: | ||
6888 | reg_w(dev, 0x03, 0x003b); | ||
6889 | reg_w(dev, 0x0c, 0x003a); | ||
6890 | reg_w(dev, 0x0b, 0x0039); | ||
6891 | break; | ||
6886 | } | 6892 | } |
6887 | 6893 | ||
6888 | setmatrix(gspca_dev); | 6894 | setmatrix(gspca_dev); |
@@ -6961,13 +6967,13 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
6961 | switch (sd->sensor) { | 6967 | switch (sd->sensor) { |
6962 | case SENSOR_PO2030: | 6968 | case SENSOR_PO2030: |
6963 | msleep(50); | 6969 | msleep(50); |
6964 | reg_r(gspca_dev, 0x0008); | ||
6965 | reg_r(gspca_dev, 0x0007); | ||
6966 | /*fall thru*/ | ||
6967 | case SENSOR_PAS202B: | ||
6968 | reg_w(dev, 0x00, 0x0007); /* (from win traces) */ | 6970 | reg_w(dev, 0x00, 0x0007); /* (from win traces) */ |
6969 | reg_w(dev, 0x02, ZC3XX_R008_CLOCKSETTING); | 6971 | reg_w(dev, 0x02, ZC3XX_R008_CLOCKSETTING); |
6970 | break; | 6972 | break; |
6973 | case SENSOR_PAS202B: | ||
6974 | reg_w(dev, 0x32, 0x0007); /* (from win traces) */ | ||
6975 | reg_w(dev, 0x02, ZC3XX_R008_CLOCKSETTING); | ||
6976 | break; | ||
6971 | } | 6977 | } |
6972 | return 0; | 6978 | return 0; |
6973 | } | 6979 | } |
@@ -7165,6 +7171,22 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev, | |||
7165 | return 0; | 7171 | return 0; |
7166 | } | 7172 | } |
7167 | 7173 | ||
7174 | #ifdef CONFIG_INPUT | ||
7175 | static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, | ||
7176 | u8 *data, /* interrupt packet data */ | ||
7177 | int len) /* interrput packet length */ | ||
7178 | { | ||
7179 | if (len == 8 && data[4] == 1) { | ||
7180 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); | ||
7181 | input_sync(gspca_dev->input_dev); | ||
7182 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); | ||
7183 | input_sync(gspca_dev->input_dev); | ||
7184 | } | ||
7185 | |||
7186 | return 0; | ||
7187 | } | ||
7188 | #endif | ||
7189 | |||
7168 | static const struct sd_desc sd_desc = { | 7190 | static const struct sd_desc sd_desc = { |
7169 | .name = MODULE_NAME, | 7191 | .name = MODULE_NAME, |
7170 | .ctrls = sd_ctrls, | 7192 | .ctrls = sd_ctrls, |
@@ -7177,6 +7199,9 @@ static const struct sd_desc sd_desc = { | |||
7177 | .querymenu = sd_querymenu, | 7199 | .querymenu = sd_querymenu, |
7178 | .get_jcomp = sd_get_jcomp, | 7200 | .get_jcomp = sd_get_jcomp, |
7179 | .set_jcomp = sd_set_jcomp, | 7201 | .set_jcomp = sd_set_jcomp, |
7202 | #ifdef CONFIG_INPUT | ||
7203 | .int_pkt_scan = sd_int_pkt_scan, | ||
7204 | #endif | ||
7180 | }; | 7205 | }; |
7181 | 7206 | ||
7182 | static const __devinitdata struct usb_device_id device_table[] = { | 7207 | static const __devinitdata struct usb_device_id device_table[] = { |
diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c index 51f393d03a46..2fc9865fd486 100644 --- a/drivers/media/video/hdpvr/hdpvr-core.c +++ b/drivers/media/video/hdpvr/hdpvr-core.c | |||
@@ -39,12 +39,12 @@ int hdpvr_debug; | |||
39 | module_param(hdpvr_debug, int, S_IRUGO|S_IWUSR); | 39 | module_param(hdpvr_debug, int, S_IRUGO|S_IWUSR); |
40 | MODULE_PARM_DESC(hdpvr_debug, "enable debugging output"); | 40 | MODULE_PARM_DESC(hdpvr_debug, "enable debugging output"); |
41 | 41 | ||
42 | uint default_video_input = HDPVR_VIDEO_INPUTS; | 42 | static uint default_video_input = HDPVR_VIDEO_INPUTS; |
43 | module_param(default_video_input, uint, S_IRUGO|S_IWUSR); | 43 | module_param(default_video_input, uint, S_IRUGO|S_IWUSR); |
44 | MODULE_PARM_DESC(default_video_input, "default video input: 0=Component / " | 44 | MODULE_PARM_DESC(default_video_input, "default video input: 0=Component / " |
45 | "1=S-Video / 2=Composite"); | 45 | "1=S-Video / 2=Composite"); |
46 | 46 | ||
47 | uint default_audio_input = HDPVR_AUDIO_INPUTS; | 47 | static uint default_audio_input = HDPVR_AUDIO_INPUTS; |
48 | module_param(default_audio_input, uint, S_IRUGO|S_IWUSR); | 48 | module_param(default_audio_input, uint, S_IRUGO|S_IWUSR); |
49 | MODULE_PARM_DESC(default_audio_input, "default audio input: 0=RCA back / " | 49 | MODULE_PARM_DESC(default_audio_input, "default audio input: 0=RCA back / " |
50 | "1=RCA front / 2=S/PDIF"); | 50 | "1=RCA front / 2=S/PDIF"); |
@@ -59,6 +59,7 @@ static struct usb_device_id hdpvr_table[] = { | |||
59 | { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID) }, | 59 | { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID) }, |
60 | { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID1) }, | 60 | { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID1) }, |
61 | { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID2) }, | 61 | { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID2) }, |
62 | { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID3) }, | ||
62 | { } /* Terminating entry */ | 63 | { } /* Terminating entry */ |
63 | }; | 64 | }; |
64 | MODULE_DEVICE_TABLE(usb, hdpvr_table); | 65 | MODULE_DEVICE_TABLE(usb, hdpvr_table); |
diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c index fdd782039e9d..196f82de48f0 100644 --- a/drivers/media/video/hdpvr/hdpvr-video.c +++ b/drivers/media/video/hdpvr/hdpvr-video.c | |||
@@ -302,7 +302,8 @@ static int hdpvr_start_streaming(struct hdpvr_device *dev) | |||
302 | /* function expects dev->io_mutex to be hold by caller */ | 302 | /* function expects dev->io_mutex to be hold by caller */ |
303 | static int hdpvr_stop_streaming(struct hdpvr_device *dev) | 303 | static int hdpvr_stop_streaming(struct hdpvr_device *dev) |
304 | { | 304 | { |
305 | uint actual_length, c = 0; | 305 | int actual_length; |
306 | uint c = 0; | ||
306 | u8 *buf; | 307 | u8 *buf; |
307 | 308 | ||
308 | if (dev->status == STATUS_IDLE) | 309 | if (dev->status == STATUS_IDLE) |
@@ -572,7 +573,7 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
572 | struct hdpvr_device *dev = video_drvdata(file); | 573 | struct hdpvr_device *dev = video_drvdata(file); |
573 | 574 | ||
574 | strcpy(cap->driver, "hdpvr"); | 575 | strcpy(cap->driver, "hdpvr"); |
575 | strcpy(cap->card, "Haupauge HD PVR"); | 576 | strcpy(cap->card, "Hauppauge HD PVR"); |
576 | usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); | 577 | usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); |
577 | cap->version = HDPVR_VERSION; | 578 | cap->version = HDPVR_VERSION; |
578 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | | 579 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | |
diff --git a/drivers/media/video/hdpvr/hdpvr.h b/drivers/media/video/hdpvr/hdpvr.h index 1edd8759121e..49ae25d83d10 100644 --- a/drivers/media/video/hdpvr/hdpvr.h +++ b/drivers/media/video/hdpvr/hdpvr.h | |||
@@ -30,6 +30,7 @@ | |||
30 | #define HD_PVR_PRODUCT_ID 0x4900 | 30 | #define HD_PVR_PRODUCT_ID 0x4900 |
31 | #define HD_PVR_PRODUCT_ID1 0x4901 | 31 | #define HD_PVR_PRODUCT_ID1 0x4901 |
32 | #define HD_PVR_PRODUCT_ID2 0x4902 | 32 | #define HD_PVR_PRODUCT_ID2 0x4902 |
33 | #define HD_PVR_PRODUCT_ID3 0x4982 | ||
33 | 34 | ||
34 | #define UNSET (-1U) | 35 | #define UNSET (-1U) |
35 | 36 | ||
diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c index 60d992ee2589..e620a3a92f25 100644 --- a/drivers/media/video/hexium_gemini.c +++ b/drivers/media/video/hexium_gemini.c | |||
@@ -352,9 +352,13 @@ static struct saa7146_ext_vv vv_data; | |||
352 | static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) | 352 | static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) |
353 | { | 353 | { |
354 | struct hexium *hexium = (struct hexium *) dev->ext_priv; | 354 | struct hexium *hexium = (struct hexium *) dev->ext_priv; |
355 | int ret; | ||
355 | 356 | ||
356 | DEB_EE((".\n")); | 357 | DEB_EE((".\n")); |
357 | 358 | ||
359 | ret = saa7146_vv_devinit(dev); | ||
360 | if (ret) | ||
361 | return ret; | ||
358 | hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL); | 362 | hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL); |
359 | if (NULL == hexium) { | 363 | if (NULL == hexium) { |
360 | printk("hexium_gemini: not enough kernel memory in hexium_attach().\n"); | 364 | printk("hexium_gemini: not enough kernel memory in hexium_attach().\n"); |
@@ -400,9 +404,10 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d | |||
400 | vv_data.ops.vidioc_enum_input = vidioc_enum_input; | 404 | vv_data.ops.vidioc_enum_input = vidioc_enum_input; |
401 | vv_data.ops.vidioc_g_input = vidioc_g_input; | 405 | vv_data.ops.vidioc_g_input = vidioc_g_input; |
402 | vv_data.ops.vidioc_s_input = vidioc_s_input; | 406 | vv_data.ops.vidioc_s_input = vidioc_s_input; |
403 | if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium gemini", VFL_TYPE_GRABBER)) { | 407 | ret = saa7146_register_device(&hexium->video_dev, dev, "hexium gemini", VFL_TYPE_GRABBER); |
408 | if (ret < 0) { | ||
404 | printk("hexium_gemini: cannot register capture v4l2 device. skipping.\n"); | 409 | printk("hexium_gemini: cannot register capture v4l2 device. skipping.\n"); |
405 | return -1; | 410 | return ret; |
406 | } | 411 | } |
407 | 412 | ||
408 | printk("hexium_gemini: found 'hexium gemini' frame grabber-%d.\n", hexium_num); | 413 | printk("hexium_gemini: found 'hexium gemini' frame grabber-%d.\n", hexium_num); |
diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c index 938a1f8f880a..fe596a1c12a8 100644 --- a/drivers/media/video/hexium_orion.c +++ b/drivers/media/video/hexium_orion.c | |||
@@ -216,6 +216,10 @@ static int hexium_probe(struct saa7146_dev *dev) | |||
216 | return -EFAULT; | 216 | return -EFAULT; |
217 | } | 217 | } |
218 | 218 | ||
219 | err = saa7146_vv_devinit(dev); | ||
220 | if (err) | ||
221 | return err; | ||
222 | |||
219 | hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL); | 223 | hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL); |
220 | if (NULL == hexium) { | 224 | if (NULL == hexium) { |
221 | printk("hexium_orion: hexium_probe: not enough kernel memory.\n"); | 225 | printk("hexium_orion: hexium_probe: not enough kernel memory.\n"); |
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index b86e35386cee..da18d698e7f2 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c | |||
@@ -299,7 +299,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
299 | { | 299 | { |
300 | struct ir_scancode_table *ir_codes = NULL; | 300 | struct ir_scancode_table *ir_codes = NULL; |
301 | const char *name = NULL; | 301 | const char *name = NULL; |
302 | int ir_type = 0; | 302 | u64 ir_type = 0; |
303 | struct IR_i2c *ir; | 303 | struct IR_i2c *ir; |
304 | struct input_dev *input_dev; | 304 | struct input_dev *input_dev; |
305 | struct i2c_adapter *adap = client->adapter; | 305 | struct i2c_adapter *adap = client->adapter; |
@@ -331,6 +331,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
331 | ir_codes = &ir_codes_pv951_table; | 331 | ir_codes = &ir_codes_pv951_table; |
332 | break; | 332 | break; |
333 | case 0x18: | 333 | case 0x18: |
334 | case 0x1f: | ||
334 | case 0x1a: | 335 | case 0x1a: |
335 | name = "Hauppauge"; | 336 | name = "Hauppauge"; |
336 | ir->get_key = get_key_haup; | 337 | ir->get_key = get_key_haup; |
@@ -446,7 +447,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
446 | input_dev->name = ir->name; | 447 | input_dev->name = ir->name; |
447 | input_dev->phys = ir->phys; | 448 | input_dev->phys = ir->phys; |
448 | 449 | ||
449 | err = ir_input_register(ir->input, ir->ir_codes); | 450 | err = ir_input_register(ir->input, ir->ir_codes, NULL); |
450 | if (err) | 451 | if (err) |
451 | goto err_out_free; | 452 | goto err_out_free; |
452 | 453 | ||
diff --git a/drivers/media/video/ivtv/ivtv-cards.c b/drivers/media/video/ivtv/ivtv-cards.c index 79d0fe4990d6..ca1fd3227a93 100644 --- a/drivers/media/video/ivtv/ivtv-cards.c +++ b/drivers/media/video/ivtv/ivtv-cards.c | |||
@@ -1210,6 +1210,53 @@ static const struct ivtv_card ivtv_card_buffalo = { | |||
1210 | .i2c = &ivtv_i2c_std, | 1210 | .i2c = &ivtv_i2c_std, |
1211 | }; | 1211 | }; |
1212 | 1212 | ||
1213 | /* ------------------------------------------------------------------------- */ | ||
1214 | /* Sony Kikyou */ | ||
1215 | |||
1216 | static const struct ivtv_card_pci_info ivtv_pci_kikyou[] = { | ||
1217 | { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_SONY, 0x813d }, | ||
1218 | { 0, 0, 0 } | ||
1219 | }; | ||
1220 | |||
1221 | static const struct ivtv_card ivtv_card_kikyou = { | ||
1222 | .type = IVTV_CARD_KIKYOU, | ||
1223 | .name = "Sony VAIO Giga Pocket (ENX Kikyou)", | ||
1224 | .v4l2_capabilities = IVTV_CAP_ENCODER, | ||
1225 | .hw_video = IVTV_HW_SAA7115, | ||
1226 | .hw_audio = IVTV_HW_GPIO, | ||
1227 | .hw_audio_ctrl = IVTV_HW_GPIO, | ||
1228 | .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TUNER, | ||
1229 | .video_inputs = { | ||
1230 | { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE1 }, | ||
1231 | { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE1 }, | ||
1232 | { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO1 }, | ||
1233 | }, | ||
1234 | .audio_inputs = { | ||
1235 | { IVTV_CARD_INPUT_AUD_TUNER, IVTV_GPIO_TUNER }, | ||
1236 | { IVTV_CARD_INPUT_LINE_IN1, IVTV_GPIO_LINE_IN }, | ||
1237 | { IVTV_CARD_INPUT_LINE_IN2, IVTV_GPIO_LINE_IN }, | ||
1238 | }, | ||
1239 | .gpio_init = { .direction = 0x03e1, .initial_value = 0x0320 }, | ||
1240 | .gpio_audio_input = { .mask = 0x0060, | ||
1241 | .tuner = 0x0020, | ||
1242 | .linein = 0x0000, | ||
1243 | .radio = 0x0060 }, | ||
1244 | .gpio_audio_mute = { .mask = 0x0000, | ||
1245 | .mute = 0x0000 }, /* 0x200? Disable for now. */ | ||
1246 | .gpio_audio_mode = { .mask = 0x0080, | ||
1247 | .mono = 0x0000, | ||
1248 | .stereo = 0x0000, /* SAP */ | ||
1249 | .lang1 = 0x0080, | ||
1250 | .lang2 = 0x0000, | ||
1251 | .both = 0x0080 }, | ||
1252 | .tuners = { | ||
1253 | { .std = V4L2_STD_ALL, .tuner = TUNER_SONY_BTF_PXN01Z }, | ||
1254 | }, | ||
1255 | .pci_list = ivtv_pci_kikyou, | ||
1256 | .i2c = &ivtv_i2c_std, | ||
1257 | }; | ||
1258 | |||
1259 | |||
1213 | static const struct ivtv_card *ivtv_card_list[] = { | 1260 | static const struct ivtv_card *ivtv_card_list[] = { |
1214 | &ivtv_card_pvr250, | 1261 | &ivtv_card_pvr250, |
1215 | &ivtv_card_pvr350, | 1262 | &ivtv_card_pvr350, |
@@ -1238,6 +1285,7 @@ static const struct ivtv_card *ivtv_card_list[] = { | |||
1238 | &ivtv_card_aver_m104, | 1285 | &ivtv_card_aver_m104, |
1239 | &ivtv_card_buffalo, | 1286 | &ivtv_card_buffalo, |
1240 | &ivtv_card_aver_ultra1500mce, | 1287 | &ivtv_card_aver_ultra1500mce, |
1288 | &ivtv_card_kikyou, | ||
1241 | 1289 | ||
1242 | /* Variations of standard cards but with the same PCI IDs. | 1290 | /* Variations of standard cards but with the same PCI IDs. |
1243 | These cards must come last in this list. */ | 1291 | These cards must come last in this list. */ |
diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h index 6148827ec885..78eca992e1fd 100644 --- a/drivers/media/video/ivtv/ivtv-cards.h +++ b/drivers/media/video/ivtv/ivtv-cards.h | |||
@@ -51,7 +51,8 @@ | |||
51 | #define IVTV_CARD_AVER_M104 24 /* AverMedia M104 miniPCI card */ | 51 | #define IVTV_CARD_AVER_M104 24 /* AverMedia M104 miniPCI card */ |
52 | #define IVTV_CARD_BUFFALO_MV5L 25 /* Buffalo PC-MV5L/PCI card */ | 52 | #define IVTV_CARD_BUFFALO_MV5L 25 /* Buffalo PC-MV5L/PCI card */ |
53 | #define IVTV_CARD_AVER_ULTRA1500MCE 26 /* AVerMedia UltraTV 1500 MCE */ | 53 | #define IVTV_CARD_AVER_ULTRA1500MCE 26 /* AVerMedia UltraTV 1500 MCE */ |
54 | #define IVTV_CARD_LAST 26 | 54 | #define IVTV_CARD_KIKYOU 27 /* Sony VAIO Giga Pocket (ENX Kikyou) */ |
55 | #define IVTV_CARD_LAST 27 | ||
55 | 56 | ||
56 | /* Variants of existing cards but with the same PCI IDs. The driver | 57 | /* Variants of existing cards but with the same PCI IDs. The driver |
57 | detects these based on other device information. | 58 | detects these based on other device information. |
@@ -86,6 +87,7 @@ | |||
86 | #define IVTV_PCI_ID_MELCO 0x1154 | 87 | #define IVTV_PCI_ID_MELCO 0x1154 |
87 | #define IVTV_PCI_ID_GOTVIEW1 0xffac | 88 | #define IVTV_PCI_ID_GOTVIEW1 0xffac |
88 | #define IVTV_PCI_ID_GOTVIEW2 0xffad | 89 | #define IVTV_PCI_ID_GOTVIEW2 0xffad |
90 | #define IVTV_PCI_ID_SONY 0x104d | ||
89 | 91 | ||
90 | /* hardware flags, no gaps allowed */ | 92 | /* hardware flags, no gaps allowed */ |
91 | #define IVTV_HW_CX25840 (1 << 0) | 93 | #define IVTV_HW_CX25840 (1 << 0) |
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index 347c3344f56d..9a250548be4d 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c | |||
@@ -193,6 +193,7 @@ MODULE_PARM_DESC(cardtype, | |||
193 | "\t\t\t25 = AverMedia M104 (not yet working)\n" | 193 | "\t\t\t25 = AverMedia M104 (not yet working)\n" |
194 | "\t\t\t26 = Buffalo PC-MV5L/PCI\n" | 194 | "\t\t\t26 = Buffalo PC-MV5L/PCI\n" |
195 | "\t\t\t27 = AVerMedia UltraTV 1500 MCE\n" | 195 | "\t\t\t27 = AVerMedia UltraTV 1500 MCE\n" |
196 | "\t\t\t28 = Sony VAIO Giga Pocket (ENX Kikyou)\n" | ||
196 | "\t\t\t 0 = Autodetect (default)\n" | 197 | "\t\t\t 0 = Autodetect (default)\n" |
197 | "\t\t\t-1 = Ignore this card\n\t\t"); | 198 | "\t\t\t-1 = Ignore this card\n\t\t"); |
198 | MODULE_PARM_DESC(pal, "Set PAL standard: BGH, DK, I, M, N, Nc, 60"); | 199 | MODULE_PARM_DESC(pal, "Set PAL standard: BGH, DK, I, M, N, Nc, 60"); |
diff --git a/drivers/media/video/ivtv/ivtv-firmware.c b/drivers/media/video/ivtv/ivtv-firmware.c index c1b7ec475c27..a71e8ba306b0 100644 --- a/drivers/media/video/ivtv/ivtv-firmware.c +++ b/drivers/media/video/ivtv/ivtv-firmware.c | |||
@@ -258,7 +258,7 @@ void ivtv_init_mpeg_decoder(struct ivtv *itv) | |||
258 | IVTV_ERR("ivtv_init_mpeg_decoder failed to start playback\n"); | 258 | IVTV_ERR("ivtv_init_mpeg_decoder failed to start playback\n"); |
259 | return; | 259 | return; |
260 | } | 260 | } |
261 | ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, data); | 261 | ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, 2, data); |
262 | mem_offset = itv->dec_mem + data[1]; | 262 | mem_offset = itv->dec_mem + data[1]; |
263 | 263 | ||
264 | if ((readbytes = load_fw_direct(IVTV_DECODE_INIT_MPEG_FILENAME, | 264 | if ((readbytes = load_fw_direct(IVTV_DECODE_INIT_MPEG_FILENAME, |
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c index cd9db0bf33bf..12d36ca91d53 100644 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ b/drivers/media/video/ivtv/ivtv-irq.c | |||
@@ -562,7 +562,7 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv) | |||
562 | u32 data[CX2341X_MBOX_MAX_DATA]; | 562 | u32 data[CX2341X_MBOX_MAX_DATA]; |
563 | struct ivtv_stream *s; | 563 | struct ivtv_stream *s; |
564 | 564 | ||
565 | ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, data); | 565 | ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, 2, data); |
566 | IVTV_DEBUG_HI_IRQ("ENC DMA COMPLETE %x %d (%d)\n", data[0], data[1], itv->cur_dma_stream); | 566 | IVTV_DEBUG_HI_IRQ("ENC DMA COMPLETE %x %d (%d)\n", data[0], data[1], itv->cur_dma_stream); |
567 | 567 | ||
568 | del_timer(&itv->dma_timer); | 568 | del_timer(&itv->dma_timer); |
@@ -638,7 +638,7 @@ static void ivtv_irq_dma_err(struct ivtv *itv) | |||
638 | u32 data[CX2341X_MBOX_MAX_DATA]; | 638 | u32 data[CX2341X_MBOX_MAX_DATA]; |
639 | 639 | ||
640 | del_timer(&itv->dma_timer); | 640 | del_timer(&itv->dma_timer); |
641 | ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, data); | 641 | ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, 2, data); |
642 | IVTV_DEBUG_WARN("DMA ERROR %08x %08x %08x %d\n", data[0], data[1], | 642 | IVTV_DEBUG_WARN("DMA ERROR %08x %08x %08x %d\n", data[0], data[1], |
643 | read_reg(IVTV_REG_DMASTATUS), itv->cur_dma_stream); | 643 | read_reg(IVTV_REG_DMASTATUS), itv->cur_dma_stream); |
644 | write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS); | 644 | write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS); |
@@ -669,7 +669,7 @@ static void ivtv_irq_enc_start_cap(struct ivtv *itv) | |||
669 | struct ivtv_stream *s; | 669 | struct ivtv_stream *s; |
670 | 670 | ||
671 | /* Get DMA destination and size arguments from card */ | 671 | /* Get DMA destination and size arguments from card */ |
672 | ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA, data); | 672 | ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA, 7, data); |
673 | IVTV_DEBUG_HI_IRQ("ENC START CAP %d: %08x %08x\n", data[0], data[1], data[2]); | 673 | IVTV_DEBUG_HI_IRQ("ENC START CAP %d: %08x %08x\n", data[0], data[1], data[2]); |
674 | 674 | ||
675 | if (data[0] > 2 || data[1] == 0 || data[2] == 0) { | 675 | if (data[0] > 2 || data[1] == 0 || data[2] == 0) { |
@@ -713,9 +713,9 @@ static void ivtv_irq_dec_data_req(struct ivtv *itv) | |||
713 | struct ivtv_stream *s; | 713 | struct ivtv_stream *s; |
714 | 714 | ||
715 | /* YUV or MPG */ | 715 | /* YUV or MPG */ |
716 | ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, data); | ||
717 | 716 | ||
718 | if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) { | 717 | if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) { |
718 | ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, 2, data); | ||
719 | itv->dma_data_req_size = | 719 | itv->dma_data_req_size = |
720 | 1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31); | 720 | 1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31); |
721 | itv->dma_data_req_offset = data[1]; | 721 | itv->dma_data_req_offset = data[1]; |
@@ -724,6 +724,7 @@ static void ivtv_irq_dec_data_req(struct ivtv *itv) | |||
724 | s = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV]; | 724 | s = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV]; |
725 | } | 725 | } |
726 | else { | 726 | else { |
727 | ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, 3, data); | ||
727 | itv->dma_data_req_size = min_t(u32, data[2], 0x10000); | 728 | itv->dma_data_req_size = min_t(u32, data[2], 0x10000); |
728 | itv->dma_data_req_offset = data[1]; | 729 | itv->dma_data_req_offset = data[1]; |
729 | s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; | 730 | s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; |
@@ -940,9 +941,10 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id) | |||
940 | ivtv_dma_enc_start(s); | 941 | ivtv_dma_enc_start(s); |
941 | break; | 942 | break; |
942 | } | 943 | } |
943 | if (i == IVTV_MAX_STREAMS && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags)) { | 944 | |
945 | if (i == IVTV_MAX_STREAMS && | ||
946 | test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags)) | ||
944 | ivtv_udma_start(itv); | 947 | ivtv_udma_start(itv); |
945 | } | ||
946 | } | 948 | } |
947 | 949 | ||
948 | if ((combo & IVTV_IRQ_DMA) && !test_bit(IVTV_F_I_PIO, &itv->i_flags)) { | 950 | if ((combo & IVTV_IRQ_DMA) && !test_bit(IVTV_F_I_PIO, &itv->i_flags)) { |
diff --git a/drivers/media/video/ivtv/ivtv-mailbox.c b/drivers/media/video/ivtv/ivtv-mailbox.c index 1b5c0ac09a85..84577f6f41a2 100644 --- a/drivers/media/video/ivtv/ivtv-mailbox.c +++ b/drivers/media/video/ivtv/ivtv-mailbox.c | |||
@@ -369,10 +369,11 @@ int ivtv_vapi(struct ivtv *itv, int cmd, int args, ...) | |||
369 | } | 369 | } |
370 | 370 | ||
371 | /* This one is for stuff that can't sleep.. irq handlers, etc.. */ | 371 | /* This one is for stuff that can't sleep.. irq handlers, etc.. */ |
372 | void ivtv_api_get_data(struct ivtv_mailbox_data *mbdata, int mb, u32 data[]) | 372 | void ivtv_api_get_data(struct ivtv_mailbox_data *mbdata, int mb, |
373 | int argc, u32 data[]) | ||
373 | { | 374 | { |
375 | volatile u32 __iomem *p = mbdata->mbox[mb].data; | ||
374 | int i; | 376 | int i; |
375 | 377 | for (i = 0; i < argc; i++, p++) | |
376 | for (i = 0; i < CX2341X_MBOX_MAX_DATA; i++) | 378 | data[i] = readl(p); |
377 | data[i] = readl(&mbdata->mbox[mb].data[i]); | ||
378 | } | 379 | } |
diff --git a/drivers/media/video/ivtv/ivtv-mailbox.h b/drivers/media/video/ivtv/ivtv-mailbox.h index 6ef12091e3f3..8247662c928e 100644 --- a/drivers/media/video/ivtv/ivtv-mailbox.h +++ b/drivers/media/video/ivtv/ivtv-mailbox.h | |||
@@ -24,7 +24,8 @@ | |||
24 | #define IVTV_MBOX_DMA_END 8 | 24 | #define IVTV_MBOX_DMA_END 8 |
25 | #define IVTV_MBOX_DMA 9 | 25 | #define IVTV_MBOX_DMA 9 |
26 | 26 | ||
27 | void ivtv_api_get_data(struct ivtv_mailbox_data *mbox, int mb, u32 data[]); | 27 | void ivtv_api_get_data(struct ivtv_mailbox_data *mbdata, int mb, |
28 | int argc, u32 data[]); | ||
28 | int ivtv_api(struct ivtv *itv, int cmd, int args, u32 data[]); | 29 | int ivtv_api(struct ivtv *itv, int cmd, int args, u32 data[]); |
29 | int ivtv_vapi_result(struct ivtv *itv, u32 data[CX2341X_MBOX_MAX_DATA], int cmd, int args, ...); | 30 | int ivtv_vapi_result(struct ivtv *itv, u32 data[CX2341X_MBOX_MAX_DATA], int cmd, int args, ...); |
30 | int ivtv_vapi(struct ivtv *itv, int cmd, int args, ...); | 31 | int ivtv_vapi(struct ivtv *itv, int cmd, int args, ...); |
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index e12c6022373e..1f9387f6ca24 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c | |||
@@ -577,10 +577,14 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) | |||
577 | clear_bit(IVTV_F_I_EOS, &itv->i_flags); | 577 | clear_bit(IVTV_F_I_EOS, &itv->i_flags); |
578 | 578 | ||
579 | /* Initialize Digitizer for Capture */ | 579 | /* Initialize Digitizer for Capture */ |
580 | /* Avoid tinny audio problem - ensure audio clocks are going */ | ||
581 | v4l2_subdev_call(itv->sd_audio, audio, s_stream, 1); | ||
582 | /* Avoid unpredictable PCI bus hang - disable video clocks */ | ||
580 | v4l2_subdev_call(itv->sd_video, video, s_stream, 0); | 583 | v4l2_subdev_call(itv->sd_video, video, s_stream, 0); |
581 | ivtv_msleep_timeout(300, 1); | 584 | ivtv_msleep_timeout(150, 1); |
582 | ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0); | 585 | ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0); |
583 | v4l2_subdev_call(itv->sd_video, video, s_stream, 1); | 586 | v4l2_subdev_call(itv->sd_video, video, s_stream, 1); |
587 | ivtv_msleep_timeout(150, 1); | ||
584 | } | 588 | } |
585 | 589 | ||
586 | /* begin_capture */ | 590 | /* begin_capture */ |
diff --git a/drivers/media/video/ivtv/ivtv-udma.c b/drivers/media/video/ivtv/ivtv-udma.c index d07ad6c39024..1daf1dd65bf7 100644 --- a/drivers/media/video/ivtv/ivtv-udma.c +++ b/drivers/media/video/ivtv/ivtv-udma.c | |||
@@ -213,6 +213,7 @@ void ivtv_udma_start(struct ivtv *itv) | |||
213 | write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER); | 213 | write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER); |
214 | set_bit(IVTV_F_I_DMA, &itv->i_flags); | 214 | set_bit(IVTV_F_I_DMA, &itv->i_flags); |
215 | set_bit(IVTV_F_I_UDMA, &itv->i_flags); | 215 | set_bit(IVTV_F_I_UDMA, &itv->i_flags); |
216 | clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags); | ||
216 | } | 217 | } |
217 | 218 | ||
218 | void ivtv_udma_prepare(struct ivtv *itv) | 219 | void ivtv_udma_prepare(struct ivtv *itv) |
diff --git a/drivers/media/video/mt9t112.c b/drivers/media/video/mt9t112.c index fc4dd6045720..7438f8d775ba 100644 --- a/drivers/media/video/mt9t112.c +++ b/drivers/media/video/mt9t112.c | |||
@@ -514,7 +514,7 @@ static int mt9t112_init_pll(const struct i2c_client *client) | |||
514 | /* poll to verify out of standby. Must Poll this bit */ | 514 | /* poll to verify out of standby. Must Poll this bit */ |
515 | for (i = 0; i < 100; i++) { | 515 | for (i = 0; i < 100; i++) { |
516 | mt9t112_reg_read(data, client, 0x0018); | 516 | mt9t112_reg_read(data, client, 0x0018); |
517 | if (0x4000 & data) | 517 | if (!(0x4000 & data)) |
518 | break; | 518 | break; |
519 | 519 | ||
520 | mdelay(10); | 520 | mdelay(10); |
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index 91df7ec91fb6..1a34d2993e94 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c | |||
@@ -257,19 +257,18 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd, | |||
257 | static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) | 257 | static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) |
258 | { | 258 | { |
259 | struct soc_camera_link *icl = to_soc_camera_link(icd); | 259 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
260 | unsigned int width_flag; | 260 | unsigned int flags = SOCAM_MASTER | SOCAM_SLAVE | |
261 | SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING | | ||
262 | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW | | ||
263 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW | | ||
264 | SOCAM_DATA_ACTIVE_HIGH; | ||
261 | 265 | ||
262 | if (icl->query_bus_param) | 266 | if (icl->query_bus_param) |
263 | width_flag = icl->query_bus_param(icl) & | 267 | flags |= icl->query_bus_param(icl) & SOCAM_DATAWIDTH_MASK; |
264 | SOCAM_DATAWIDTH_MASK; | ||
265 | else | 268 | else |
266 | width_flag = SOCAM_DATAWIDTH_10; | 269 | flags |= SOCAM_DATAWIDTH_10; |
267 | 270 | ||
268 | return SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FALLING | | 271 | return soc_camera_apply_sensor_flags(icl, flags); |
269 | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW | | ||
270 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW | | ||
271 | SOCAM_DATA_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_SLAVE | | ||
272 | width_flag; | ||
273 | } | 272 | } |
274 | 273 | ||
275 | static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | 274 | static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) |
diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index c1fc6dc776f5..9f01f14e4aa2 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c | |||
@@ -169,7 +169,11 @@ static struct saa7146_extension extension; | |||
169 | static int mxb_probe(struct saa7146_dev *dev) | 169 | static int mxb_probe(struct saa7146_dev *dev) |
170 | { | 170 | { |
171 | struct mxb *mxb = NULL; | 171 | struct mxb *mxb = NULL; |
172 | int err; | ||
172 | 173 | ||
174 | err = saa7146_vv_devinit(dev); | ||
175 | if (err) | ||
176 | return err; | ||
173 | mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL); | 177 | mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL); |
174 | if (mxb == NULL) { | 178 | if (mxb == NULL) { |
175 | DEB_D(("not enough kernel memory.\n")); | 179 | DEB_D(("not enough kernel memory.\n")); |
@@ -294,7 +298,7 @@ static int mxb_init_done(struct saa7146_dev* dev) | |||
294 | /* select tuner-output on saa7111a */ | 298 | /* select tuner-output on saa7111a */ |
295 | i = 0; | 299 | i = 0; |
296 | saa7111a_call(mxb, video, s_routing, SAA7115_COMPOSITE0, | 300 | saa7111a_call(mxb, video, s_routing, SAA7115_COMPOSITE0, |
297 | SAA7111_FMT_CCIR | SAA7111_VBI_BYPASS, 0); | 301 | SAA7111_FMT_CCIR, 0); |
298 | 302 | ||
299 | /* select a tuner type */ | 303 | /* select a tuner type */ |
300 | tun_setup.mode_mask = T_ANALOG_TV; | 304 | tun_setup.mode_mask = T_ANALOG_TV; |
@@ -518,8 +522,8 @@ static int vidioc_s_input(struct file *file, void *fh, unsigned int input) | |||
518 | return err; | 522 | return err; |
519 | 523 | ||
520 | /* switch video in saa7111a */ | 524 | /* switch video in saa7111a */ |
521 | if (saa7111a_call(mxb, video, s_routing, i, 0, 0)) | 525 | if (saa7111a_call(mxb, video, s_routing, i, SAA7111_FMT_CCIR, 0)) |
522 | printk(KERN_ERR "VIDIOC_S_INPUT: could not address saa7111a #1.\n"); | 526 | printk(KERN_ERR "VIDIOC_S_INPUT: could not address saa7111a.\n"); |
523 | 527 | ||
524 | /* switch the audio-source only if necessary */ | 528 | /* switch the audio-source only if necessary */ |
525 | if (0 == mxb->cur_mute) | 529 | if (0 == mxb->cur_mute) |
diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c index 3a45e945a528..7f8ece30c77b 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/video/ov772x.c | |||
@@ -547,7 +547,6 @@ static const struct v4l2_queryctrl ov772x_controls[] = { | |||
547 | }, | 547 | }, |
548 | }; | 548 | }; |
549 | 549 | ||
550 | |||
551 | /* | 550 | /* |
552 | * general function | 551 | * general function |
553 | */ | 552 | */ |
@@ -634,7 +633,12 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) | |||
634 | struct soc_camera_link *icl = to_soc_camera_link(icd); | 633 | struct soc_camera_link *icl = to_soc_camera_link(icd); |
635 | unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | | 634 | unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | |
636 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | | 635 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | |
637 | SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth; | 636 | SOCAM_DATA_ACTIVE_HIGH; |
637 | |||
638 | if (priv->info->flags & OV772X_FLAG_8BIT) | ||
639 | flags |= SOCAM_DATAWIDTH_8; | ||
640 | else | ||
641 | flags |= SOCAM_DATAWIDTH_10; | ||
638 | 642 | ||
639 | return soc_camera_apply_sensor_flags(icl, flags); | 643 | return soc_camera_apply_sensor_flags(icl, flags); |
640 | } | 644 | } |
@@ -1040,15 +1044,6 @@ static int ov772x_video_probe(struct soc_camera_device *icd, | |||
1040 | return -ENODEV; | 1044 | return -ENODEV; |
1041 | 1045 | ||
1042 | /* | 1046 | /* |
1043 | * ov772x only use 8 or 10 bit bus width | ||
1044 | */ | ||
1045 | if (SOCAM_DATAWIDTH_10 != priv->info->buswidth && | ||
1046 | SOCAM_DATAWIDTH_8 != priv->info->buswidth) { | ||
1047 | dev_err(&client->dev, "bus width error\n"); | ||
1048 | return -ENODEV; | ||
1049 | } | ||
1050 | |||
1051 | /* | ||
1052 | * check and show product ID and manufacturer ID | 1047 | * check and show product ID and manufacturer ID |
1053 | */ | 1048 | */ |
1054 | pid = i2c_smbus_read_byte_data(client, PID); | 1049 | pid = i2c_smbus_read_byte_data(client, PID); |
@@ -1130,7 +1125,6 @@ static int ov772x_probe(struct i2c_client *client, | |||
1130 | const struct i2c_device_id *did) | 1125 | const struct i2c_device_id *did) |
1131 | { | 1126 | { |
1132 | struct ov772x_priv *priv; | 1127 | struct ov772x_priv *priv; |
1133 | struct ov772x_camera_info *info; | ||
1134 | struct soc_camera_device *icd = client->dev.platform_data; | 1128 | struct soc_camera_device *icd = client->dev.platform_data; |
1135 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 1129 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
1136 | struct soc_camera_link *icl; | 1130 | struct soc_camera_link *icl; |
@@ -1145,8 +1139,6 @@ static int ov772x_probe(struct i2c_client *client, | |||
1145 | if (!icl || !icl->priv) | 1139 | if (!icl || !icl->priv) |
1146 | return -EINVAL; | 1140 | return -EINVAL; |
1147 | 1141 | ||
1148 | info = icl->priv; | ||
1149 | |||
1150 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | 1142 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { |
1151 | dev_err(&adapter->dev, | 1143 | dev_err(&adapter->dev, |
1152 | "I2C-Adapter doesn't support " | 1144 | "I2C-Adapter doesn't support " |
@@ -1158,7 +1150,7 @@ static int ov772x_probe(struct i2c_client *client, | |||
1158 | if (!priv) | 1150 | if (!priv) |
1159 | return -ENOMEM; | 1151 | return -ENOMEM; |
1160 | 1152 | ||
1161 | priv->info = info; | 1153 | priv->info = icl->priv; |
1162 | 1154 | ||
1163 | v4l2_i2c_subdev_init(&priv->subdev, client, &ov772x_subdev_ops); | 1155 | v4l2_i2c_subdev_init(&priv->subdev, client, &ov772x_subdev_ops); |
1164 | 1156 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index de5485f506b1..cb4057bb07a0 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | |||
@@ -233,8 +233,9 @@ struct pvr2_hdw { | |||
233 | int state_encoder_waitok; /* Encoder pre-wait done */ | 233 | int state_encoder_waitok; /* Encoder pre-wait done */ |
234 | int state_encoder_runok; /* Encoder has run for >= .25 sec */ | 234 | int state_encoder_runok; /* Encoder has run for >= .25 sec */ |
235 | int state_decoder_run; /* Decoder is running */ | 235 | int state_decoder_run; /* Decoder is running */ |
236 | int state_decoder_ready; /* Decoder is stabilized & streamable */ | ||
236 | int state_usbstream_run; /* FX2 is streaming */ | 237 | int state_usbstream_run; /* FX2 is streaming */ |
237 | int state_decoder_quiescent; /* Decoder idle for > 50msec */ | 238 | int state_decoder_quiescent; /* Decoder idle for minimal interval */ |
238 | int state_pipeline_config; /* Pipeline is configured */ | 239 | int state_pipeline_config; /* Pipeline is configured */ |
239 | int state_pipeline_req; /* Somebody wants to stream */ | 240 | int state_pipeline_req; /* Somebody wants to stream */ |
240 | int state_pipeline_pause; /* Pipeline must be paused */ | 241 | int state_pipeline_pause; /* Pipeline must be paused */ |
@@ -255,9 +256,16 @@ struct pvr2_hdw { | |||
255 | void (*state_func)(void *); | 256 | void (*state_func)(void *); |
256 | void *state_data; | 257 | void *state_data; |
257 | 258 | ||
258 | /* Timer for measuring decoder settling time */ | 259 | /* Timer for measuring required decoder settling time before we're |
260 | allowed to fire it up again. */ | ||
259 | struct timer_list quiescent_timer; | 261 | struct timer_list quiescent_timer; |
260 | 262 | ||
263 | /* Timer for measuring decoder stabilization time, which is the | ||
264 | amount of time we need to let the decoder run before we can | ||
265 | trust its output (otherwise the encoder might see garbage and | ||
266 | then fail to start correctly). */ | ||
267 | struct timer_list decoder_stabilization_timer; | ||
268 | |||
261 | /* Timer for measuring encoder pre-wait time */ | 269 | /* Timer for measuring encoder pre-wait time */ |
262 | struct timer_list encoder_wait_timer; | 270 | struct timer_list encoder_wait_timer; |
263 | 271 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 1bbdab08fe0e..712b300f723f 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c | |||
@@ -48,11 +48,13 @@ | |||
48 | before we are allowed to start it running. */ | 48 | before we are allowed to start it running. */ |
49 | #define TIME_MSEC_DECODER_WAIT 50 | 49 | #define TIME_MSEC_DECODER_WAIT 50 |
50 | 50 | ||
51 | /* This defines a minimum interval that the decoder must be allowed to run | ||
52 | before we can safely begin using its streaming output. */ | ||
53 | #define TIME_MSEC_DECODER_STABILIZATION_WAIT 300 | ||
54 | |||
51 | /* This defines a minimum interval that the encoder must remain quiet | 55 | /* This defines a minimum interval that the encoder must remain quiet |
52 | before we are allowed to configure it. I had this originally set to | 56 | before we are allowed to configure it. */ |
53 | 50msec, but Martin Dauskardt <martin.dauskardt@gmx.de> reports that | 57 | #define TIME_MSEC_ENCODER_WAIT 50 |
54 | things work better when it's set to 100msec. */ | ||
55 | #define TIME_MSEC_ENCODER_WAIT 100 | ||
56 | 58 | ||
57 | /* This defines the minimum interval that the encoder must successfully run | 59 | /* This defines the minimum interval that the encoder must successfully run |
58 | before we consider that the encoder has run at least once since its | 60 | before we consider that the encoder has run at least once since its |
@@ -334,6 +336,7 @@ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw); | |||
334 | static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw); | 336 | static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw); |
335 | static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw); | 337 | static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw); |
336 | static void pvr2_hdw_quiescent_timeout(unsigned long); | 338 | static void pvr2_hdw_quiescent_timeout(unsigned long); |
339 | static void pvr2_hdw_decoder_stabilization_timeout(unsigned long); | ||
337 | static void pvr2_hdw_encoder_wait_timeout(unsigned long); | 340 | static void pvr2_hdw_encoder_wait_timeout(unsigned long); |
338 | static void pvr2_hdw_encoder_run_timeout(unsigned long); | 341 | static void pvr2_hdw_encoder_run_timeout(unsigned long); |
339 | static int pvr2_issue_simple_cmd(struct pvr2_hdw *,u32); | 342 | static int pvr2_issue_simple_cmd(struct pvr2_hdw *,u32); |
@@ -1705,6 +1708,7 @@ static int pvr2_decoder_enable(struct pvr2_hdw *hdw,int enablefl) | |||
1705 | pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 stream=%s", | 1708 | pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 stream=%s", |
1706 | (enablefl ? "on" : "off")); | 1709 | (enablefl ? "on" : "off")); |
1707 | v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_stream, enablefl); | 1710 | v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_stream, enablefl); |
1711 | v4l2_device_call_all(&hdw->v4l2_dev, 0, audio, s_stream, enablefl); | ||
1708 | if (hdw->decoder_client_id) { | 1712 | if (hdw->decoder_client_id) { |
1709 | /* We get here if the encoder has been noticed. Otherwise | 1713 | /* We get here if the encoder has been noticed. Otherwise |
1710 | we'll issue a warning to the user (which should | 1714 | we'll issue a warning to the user (which should |
@@ -2461,6 +2465,11 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, | |||
2461 | hdw->quiescent_timer.data = (unsigned long)hdw; | 2465 | hdw->quiescent_timer.data = (unsigned long)hdw; |
2462 | hdw->quiescent_timer.function = pvr2_hdw_quiescent_timeout; | 2466 | hdw->quiescent_timer.function = pvr2_hdw_quiescent_timeout; |
2463 | 2467 | ||
2468 | init_timer(&hdw->decoder_stabilization_timer); | ||
2469 | hdw->decoder_stabilization_timer.data = (unsigned long)hdw; | ||
2470 | hdw->decoder_stabilization_timer.function = | ||
2471 | pvr2_hdw_decoder_stabilization_timeout; | ||
2472 | |||
2464 | init_timer(&hdw->encoder_wait_timer); | 2473 | init_timer(&hdw->encoder_wait_timer); |
2465 | hdw->encoder_wait_timer.data = (unsigned long)hdw; | 2474 | hdw->encoder_wait_timer.data = (unsigned long)hdw; |
2466 | hdw->encoder_wait_timer.function = pvr2_hdw_encoder_wait_timeout; | 2475 | hdw->encoder_wait_timer.function = pvr2_hdw_encoder_wait_timeout; |
@@ -2674,6 +2683,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, | |||
2674 | fail: | 2683 | fail: |
2675 | if (hdw) { | 2684 | if (hdw) { |
2676 | del_timer_sync(&hdw->quiescent_timer); | 2685 | del_timer_sync(&hdw->quiescent_timer); |
2686 | del_timer_sync(&hdw->decoder_stabilization_timer); | ||
2677 | del_timer_sync(&hdw->encoder_run_timer); | 2687 | del_timer_sync(&hdw->encoder_run_timer); |
2678 | del_timer_sync(&hdw->encoder_wait_timer); | 2688 | del_timer_sync(&hdw->encoder_wait_timer); |
2679 | if (hdw->workqueue) { | 2689 | if (hdw->workqueue) { |
@@ -2741,6 +2751,7 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) | |||
2741 | hdw->workqueue = NULL; | 2751 | hdw->workqueue = NULL; |
2742 | } | 2752 | } |
2743 | del_timer_sync(&hdw->quiescent_timer); | 2753 | del_timer_sync(&hdw->quiescent_timer); |
2754 | del_timer_sync(&hdw->decoder_stabilization_timer); | ||
2744 | del_timer_sync(&hdw->encoder_run_timer); | 2755 | del_timer_sync(&hdw->encoder_run_timer); |
2745 | del_timer_sync(&hdw->encoder_wait_timer); | 2756 | del_timer_sync(&hdw->encoder_wait_timer); |
2746 | if (hdw->fw_buffer) { | 2757 | if (hdw->fw_buffer) { |
@@ -4452,7 +4463,7 @@ static int state_check_enable_encoder_run(struct pvr2_hdw *hdw) | |||
4452 | 4463 | ||
4453 | switch (hdw->pathway_state) { | 4464 | switch (hdw->pathway_state) { |
4454 | case PVR2_PATHWAY_ANALOG: | 4465 | case PVR2_PATHWAY_ANALOG: |
4455 | if (hdw->state_decoder_run) { | 4466 | if (hdw->state_decoder_run && hdw->state_decoder_ready) { |
4456 | /* In analog mode, if the decoder is running, then | 4467 | /* In analog mode, if the decoder is running, then |
4457 | run the encoder. */ | 4468 | run the encoder. */ |
4458 | return !0; | 4469 | return !0; |
@@ -4519,6 +4530,17 @@ static void pvr2_hdw_quiescent_timeout(unsigned long data) | |||
4519 | } | 4530 | } |
4520 | 4531 | ||
4521 | 4532 | ||
4533 | /* Timeout function for decoder stabilization timer. */ | ||
4534 | static void pvr2_hdw_decoder_stabilization_timeout(unsigned long data) | ||
4535 | { | ||
4536 | struct pvr2_hdw *hdw = (struct pvr2_hdw *)data; | ||
4537 | hdw->state_decoder_ready = !0; | ||
4538 | trace_stbit("state_decoder_ready", hdw->state_decoder_ready); | ||
4539 | hdw->state_stale = !0; | ||
4540 | queue_work(hdw->workqueue, &hdw->workpoll); | ||
4541 | } | ||
4542 | |||
4543 | |||
4522 | /* Timeout function for encoder wait timer. */ | 4544 | /* Timeout function for encoder wait timer. */ |
4523 | static void pvr2_hdw_encoder_wait_timeout(unsigned long data) | 4545 | static void pvr2_hdw_encoder_wait_timeout(unsigned long data) |
4524 | { | 4546 | { |
@@ -4557,8 +4579,13 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw) | |||
4557 | } | 4579 | } |
4558 | hdw->state_decoder_quiescent = 0; | 4580 | hdw->state_decoder_quiescent = 0; |
4559 | hdw->state_decoder_run = 0; | 4581 | hdw->state_decoder_run = 0; |
4560 | /* paranoia - solve race if timer just completed */ | 4582 | /* paranoia - solve race if timer(s) just completed */ |
4561 | del_timer_sync(&hdw->quiescent_timer); | 4583 | del_timer_sync(&hdw->quiescent_timer); |
4584 | /* Kill the stabilization timer, in case we're killing the | ||
4585 | encoder before the previous stabilization interval has | ||
4586 | been properly timed. */ | ||
4587 | del_timer_sync(&hdw->decoder_stabilization_timer); | ||
4588 | hdw->state_decoder_ready = 0; | ||
4562 | } else { | 4589 | } else { |
4563 | if (!hdw->state_decoder_quiescent) { | 4590 | if (!hdw->state_decoder_quiescent) { |
4564 | if (!timer_pending(&hdw->quiescent_timer)) { | 4591 | if (!timer_pending(&hdw->quiescent_timer)) { |
@@ -4596,10 +4623,21 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw) | |||
4596 | if (hdw->flag_decoder_missed) return 0; | 4623 | if (hdw->flag_decoder_missed) return 0; |
4597 | if (pvr2_decoder_enable(hdw,!0) < 0) return 0; | 4624 | if (pvr2_decoder_enable(hdw,!0) < 0) return 0; |
4598 | hdw->state_decoder_quiescent = 0; | 4625 | hdw->state_decoder_quiescent = 0; |
4626 | hdw->state_decoder_ready = 0; | ||
4599 | hdw->state_decoder_run = !0; | 4627 | hdw->state_decoder_run = !0; |
4628 | if (hdw->decoder_client_id == PVR2_CLIENT_ID_SAA7115) { | ||
4629 | hdw->decoder_stabilization_timer.expires = | ||
4630 | jiffies + | ||
4631 | (HZ * TIME_MSEC_DECODER_STABILIZATION_WAIT / | ||
4632 | 1000); | ||
4633 | add_timer(&hdw->decoder_stabilization_timer); | ||
4634 | } else { | ||
4635 | hdw->state_decoder_ready = !0; | ||
4636 | } | ||
4600 | } | 4637 | } |
4601 | trace_stbit("state_decoder_quiescent",hdw->state_decoder_quiescent); | 4638 | trace_stbit("state_decoder_quiescent",hdw->state_decoder_quiescent); |
4602 | trace_stbit("state_decoder_run",hdw->state_decoder_run); | 4639 | trace_stbit("state_decoder_run",hdw->state_decoder_run); |
4640 | trace_stbit("state_decoder_ready", hdw->state_decoder_ready); | ||
4603 | return !0; | 4641 | return !0; |
4604 | } | 4642 | } |
4605 | 4643 | ||
@@ -4797,7 +4835,8 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, | |||
4797 | buf,acnt, | 4835 | buf,acnt, |
4798 | "worker:%s%s%s%s%s%s%s", | 4836 | "worker:%s%s%s%s%s%s%s", |
4799 | (hdw->state_decoder_run ? | 4837 | (hdw->state_decoder_run ? |
4800 | " <decode:run>" : | 4838 | (hdw->state_decoder_ready ? |
4839 | "<decode:run>" : " <decode:start>") : | ||
4801 | (hdw->state_decoder_quiescent ? | 4840 | (hdw->state_decoder_quiescent ? |
4802 | "" : " <decode:stop>")), | 4841 | "" : " <decode:stop>")), |
4803 | (hdw->state_decoder_quiescent ? | 4842 | (hdw->state_decoder_quiescent ? |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index 56e70eae20c1..51d3009ab57f 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h | |||
@@ -306,6 +306,7 @@ struct pvr2_hdw_debug_info { | |||
306 | int state_encoder_ok; | 306 | int state_encoder_ok; |
307 | int state_encoder_run; | 307 | int state_encoder_run; |
308 | int state_decoder_run; | 308 | int state_decoder_run; |
309 | int state_decoder_ready; | ||
309 | int state_usbstream_run; | 310 | int state_usbstream_run; |
310 | int state_decoder_quiescent; | 311 | int state_decoder_quiescent; |
311 | int state_pipeline_config; | 312 | int state_pipeline_config; |
diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c index 50b415e07eda..f7f7e04cf485 100644 --- a/drivers/media/video/pwc/pwc-ctrl.c +++ b/drivers/media/video/pwc/pwc-ctrl.c | |||
@@ -753,7 +753,7 @@ int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value) | |||
753 | buf[0] = 0xff; /* fixed */ | 753 | buf[0] = 0xff; /* fixed */ |
754 | 754 | ||
755 | ret = send_control_msg(pdev, | 755 | ret = send_control_msg(pdev, |
756 | SET_LUM_CTL, SHUTTER_MODE_FORMATTER, &buf, sizeof(buf)); | 756 | SET_LUM_CTL, SHUTTER_MODE_FORMATTER, &buf, 1); |
757 | 757 | ||
758 | if (!mode && ret >= 0) { | 758 | if (!mode && ret >= 0) { |
759 | if (value < 0) | 759 | if (value < 0) |
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 294f860ce2b0..322ac4eecf0a 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c | |||
@@ -898,18 +898,8 @@ static void recalculate_fifo_timeout(struct pxa_camera_dev *pcdev, | |||
898 | 898 | ||
899 | static void pxa_camera_activate(struct pxa_camera_dev *pcdev) | 899 | static void pxa_camera_activate(struct pxa_camera_dev *pcdev) |
900 | { | 900 | { |
901 | struct pxacamera_platform_data *pdata = pcdev->pdata; | ||
902 | struct device *dev = pcdev->soc_host.v4l2_dev.dev; | ||
903 | u32 cicr4 = 0; | 901 | u32 cicr4 = 0; |
904 | 902 | ||
905 | dev_dbg(dev, "Registered platform device at %p data %p\n", | ||
906 | pcdev, pdata); | ||
907 | |||
908 | if (pdata && pdata->init) { | ||
909 | dev_dbg(dev, "%s: Init gpios\n", __func__); | ||
910 | pdata->init(dev); | ||
911 | } | ||
912 | |||
913 | /* disable all interrupts */ | 903 | /* disable all interrupts */ |
914 | __raw_writel(0x3ff, pcdev->base + CICR0); | 904 | __raw_writel(0x3ff, pcdev->base + CICR0); |
915 | 905 | ||
diff --git a/drivers/media/video/rj54n1cb0c.c b/drivers/media/video/rj54n1cb0c.c index 805226e0d9c1..9277194cd821 100644 --- a/drivers/media/video/rj54n1cb0c.c +++ b/drivers/media/video/rj54n1cb0c.c | |||
@@ -165,7 +165,7 @@ struct rj54n1_reg_val { | |||
165 | u8 val; | 165 | u8 val; |
166 | }; | 166 | }; |
167 | 167 | ||
168 | const static struct rj54n1_reg_val bank_4[] = { | 168 | static const struct rj54n1_reg_val bank_4[] = { |
169 | {0x417, 0}, | 169 | {0x417, 0}, |
170 | {0x42c, 0}, | 170 | {0x42c, 0}, |
171 | {0x42d, 0xf0}, | 171 | {0x42d, 0xf0}, |
@@ -186,7 +186,7 @@ const static struct rj54n1_reg_val bank_4[] = { | |||
186 | {0x4fe, 2}, | 186 | {0x4fe, 2}, |
187 | }; | 187 | }; |
188 | 188 | ||
189 | const static struct rj54n1_reg_val bank_5[] = { | 189 | static const struct rj54n1_reg_val bank_5[] = { |
190 | {0x514, 0}, | 190 | {0x514, 0}, |
191 | {0x516, 0}, | 191 | {0x516, 0}, |
192 | {0x518, 0}, | 192 | {0x518, 0}, |
@@ -207,7 +207,7 @@ const static struct rj54n1_reg_val bank_5[] = { | |||
207 | {0x5fe, 2}, | 207 | {0x5fe, 2}, |
208 | }; | 208 | }; |
209 | 209 | ||
210 | const static struct rj54n1_reg_val bank_7[] = { | 210 | static const struct rj54n1_reg_val bank_7[] = { |
211 | {0x70a, 0}, | 211 | {0x70a, 0}, |
212 | {0x714, 0xff}, | 212 | {0x714, 0xff}, |
213 | {0x715, 0xff}, | 213 | {0x715, 0xff}, |
@@ -215,7 +215,7 @@ const static struct rj54n1_reg_val bank_7[] = { | |||
215 | {0x7FE, 2}, | 215 | {0x7FE, 2}, |
216 | }; | 216 | }; |
217 | 217 | ||
218 | const static struct rj54n1_reg_val bank_8[] = { | 218 | static const struct rj54n1_reg_val bank_8[] = { |
219 | {0x800, 0x00}, | 219 | {0x800, 0x00}, |
220 | {0x801, 0x01}, | 220 | {0x801, 0x01}, |
221 | {0x802, 0x61}, | 221 | {0x802, 0x61}, |
@@ -403,12 +403,12 @@ const static struct rj54n1_reg_val bank_8[] = { | |||
403 | {0x8FE, 2}, | 403 | {0x8FE, 2}, |
404 | }; | 404 | }; |
405 | 405 | ||
406 | const static struct rj54n1_reg_val bank_10[] = { | 406 | static const struct rj54n1_reg_val bank_10[] = { |
407 | {0x10bf, 0x69} | 407 | {0x10bf, 0x69} |
408 | }; | 408 | }; |
409 | 409 | ||
410 | /* Clock dividers - these are default register values, divider = register + 1 */ | 410 | /* Clock dividers - these are default register values, divider = register + 1 */ |
411 | const static struct rj54n1_clock_div clk_div = { | 411 | static const struct rj54n1_clock_div clk_div = { |
412 | .ratio_tg = 3 /* default: 5 */, | 412 | .ratio_tg = 3 /* default: 5 */, |
413 | .ratio_t = 4 /* default: 1 */, | 413 | .ratio_t = 4 /* default: 1 */, |
414 | .ratio_r = 4 /* default: 0 */, | 414 | .ratio_r = 4 /* default: 0 */, |
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 44873a016c2c..c0a7f8a369f4 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c | |||
@@ -104,6 +104,10 @@ static int saa711x_has_reg(const int id, const u8 reg) | |||
104 | if (id == V4L2_IDENT_SAA7111) | 104 | if (id == V4L2_IDENT_SAA7111) |
105 | return reg < 0x20 && reg != 0x01 && reg != 0x0f && | 105 | return reg < 0x20 && reg != 0x01 && reg != 0x0f && |
106 | (reg < 0x13 || reg > 0x19) && reg != 0x1d && reg != 0x1e; | 106 | (reg < 0x13 || reg > 0x19) && reg != 0x1d && reg != 0x1e; |
107 | if (id == V4L2_IDENT_SAA7111A) | ||
108 | return reg < 0x20 && reg != 0x01 && reg != 0x0f && | ||
109 | reg != 0x14 && reg != 0x18 && reg != 0x19 && | ||
110 | reg != 0x1d && reg != 0x1e; | ||
107 | 111 | ||
108 | /* common for saa7113/4/5/8 */ | 112 | /* common for saa7113/4/5/8 */ |
109 | if (unlikely((reg >= 0x3b && reg <= 0x3f) || reg == 0x5c || reg == 0x5f || | 113 | if (unlikely((reg >= 0x3b && reg <= 0x3f) || reg == 0x5c || reg == 0x5f || |
@@ -954,8 +958,7 @@ static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std) | |||
954 | 011 NTSC N (3.58MHz) PAL M (3.58MHz) | 958 | 011 NTSC N (3.58MHz) PAL M (3.58MHz) |
955 | 100 reserved NTSC-Japan (3.58MHz) | 959 | 100 reserved NTSC-Japan (3.58MHz) |
956 | */ | 960 | */ |
957 | if (state->ident == V4L2_IDENT_SAA7111 || | 961 | if (state->ident <= V4L2_IDENT_SAA7113) { |
958 | state->ident == V4L2_IDENT_SAA7113) { | ||
959 | u8 reg = saa711x_read(sd, R_0E_CHROMA_CNTL_1) & 0x8f; | 962 | u8 reg = saa711x_read(sd, R_0E_CHROMA_CNTL_1) & 0x8f; |
960 | 963 | ||
961 | if (std == V4L2_STD_PAL_M) { | 964 | if (std == V4L2_STD_PAL_M) { |
@@ -1232,22 +1235,19 @@ static int saa711x_s_routing(struct v4l2_subdev *sd, | |||
1232 | u32 input, u32 output, u32 config) | 1235 | u32 input, u32 output, u32 config) |
1233 | { | 1236 | { |
1234 | struct saa711x_state *state = to_state(sd); | 1237 | struct saa711x_state *state = to_state(sd); |
1235 | u8 mask = (state->ident == V4L2_IDENT_SAA7111) ? 0xf8 : 0xf0; | 1238 | u8 mask = (state->ident <= V4L2_IDENT_SAA7111A) ? 0xf8 : 0xf0; |
1236 | 1239 | ||
1237 | v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n", | 1240 | v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n", |
1238 | input, output); | 1241 | input, output); |
1239 | 1242 | ||
1240 | /* saa7111/3 does not have these inputs */ | 1243 | /* saa7111/3 does not have these inputs */ |
1241 | if ((state->ident == V4L2_IDENT_SAA7113 || | 1244 | if (state->ident <= V4L2_IDENT_SAA7113 && |
1242 | state->ident == V4L2_IDENT_SAA7111) && | ||
1243 | (input == SAA7115_COMPOSITE4 || | 1245 | (input == SAA7115_COMPOSITE4 || |
1244 | input == SAA7115_COMPOSITE5)) { | 1246 | input == SAA7115_COMPOSITE5)) { |
1245 | return -EINVAL; | 1247 | return -EINVAL; |
1246 | } | 1248 | } |
1247 | if (input > SAA7115_SVIDEO3) | 1249 | if (input > SAA7115_SVIDEO3) |
1248 | return -EINVAL; | 1250 | return -EINVAL; |
1249 | if (output > SAA7115_IPORT_ON) | ||
1250 | return -EINVAL; | ||
1251 | if (state->input == input && state->output == output) | 1251 | if (state->input == input && state->output == output) |
1252 | return 0; | 1252 | return 0; |
1253 | v4l2_dbg(1, debug, sd, "now setting %s input %s output\n", | 1253 | v4l2_dbg(1, debug, sd, "now setting %s input %s output\n", |
@@ -1256,7 +1256,7 @@ static int saa711x_s_routing(struct v4l2_subdev *sd, | |||
1256 | state->input = input; | 1256 | state->input = input; |
1257 | 1257 | ||
1258 | /* saa7111 has slightly different input numbering */ | 1258 | /* saa7111 has slightly different input numbering */ |
1259 | if (state->ident == V4L2_IDENT_SAA7111) { | 1259 | if (state->ident <= V4L2_IDENT_SAA7111A) { |
1260 | if (input >= SAA7115_COMPOSITE4) | 1260 | if (input >= SAA7115_COMPOSITE4) |
1261 | input -= 2; | 1261 | input -= 2; |
1262 | /* saa7111 specific */ | 1262 | /* saa7111 specific */ |
@@ -1292,7 +1292,7 @@ static int saa711x_s_gpio(struct v4l2_subdev *sd, u32 val) | |||
1292 | { | 1292 | { |
1293 | struct saa711x_state *state = to_state(sd); | 1293 | struct saa711x_state *state = to_state(sd); |
1294 | 1294 | ||
1295 | if (state->ident != V4L2_IDENT_SAA7111) | 1295 | if (state->ident > V4L2_IDENT_SAA7111A) |
1296 | return -EINVAL; | 1296 | return -EINVAL; |
1297 | saa711x_write(sd, 0x11, (saa711x_read(sd, 0x11) & 0x7f) | | 1297 | saa711x_write(sd, 0x11, (saa711x_read(sd, 0x11) & 0x7f) | |
1298 | (val ? 0x80 : 0)); | 1298 | (val ? 0x80 : 0)); |
@@ -1596,6 +1596,10 @@ static int saa711x_probe(struct i2c_client *client, | |||
1596 | switch (chip_id) { | 1596 | switch (chip_id) { |
1597 | case '1': | 1597 | case '1': |
1598 | state->ident = V4L2_IDENT_SAA7111; | 1598 | state->ident = V4L2_IDENT_SAA7111; |
1599 | if (saa711x_read(sd, R_00_CHIP_VERSION) & 0xf0) { | ||
1600 | v4l_info(client, "saa7111a variant found\n"); | ||
1601 | state->ident = V4L2_IDENT_SAA7111A; | ||
1602 | } | ||
1599 | break; | 1603 | break; |
1600 | case '3': | 1604 | case '3': |
1601 | state->ident = V4L2_IDENT_SAA7113; | 1605 | state->ident = V4L2_IDENT_SAA7113; |
@@ -1612,7 +1616,7 @@ static int saa711x_probe(struct i2c_client *client, | |||
1612 | default: | 1616 | default: |
1613 | state->ident = V4L2_IDENT_SAA7111; | 1617 | state->ident = V4L2_IDENT_SAA7111; |
1614 | v4l2_info(sd, "WARNING: Chip is not known - Falling back to saa7111\n"); | 1618 | v4l2_info(sd, "WARNING: Chip is not known - Falling back to saa7111\n"); |
1615 | 1619 | break; | |
1616 | } | 1620 | } |
1617 | 1621 | ||
1618 | state->audclk_freq = 48000; | 1622 | state->audclk_freq = 48000; |
@@ -1623,6 +1627,7 @@ static int saa711x_probe(struct i2c_client *client, | |||
1623 | state->crystal_freq = SAA7115_FREQ_24_576_MHZ; | 1627 | state->crystal_freq = SAA7115_FREQ_24_576_MHZ; |
1624 | switch (state->ident) { | 1628 | switch (state->ident) { |
1625 | case V4L2_IDENT_SAA7111: | 1629 | case V4L2_IDENT_SAA7111: |
1630 | case V4L2_IDENT_SAA7111A: | ||
1626 | saa711x_writeregs(sd, saa7111_init); | 1631 | saa711x_writeregs(sd, saa7111_init); |
1627 | break; | 1632 | break; |
1628 | case V4L2_IDENT_SAA7113: | 1633 | case V4L2_IDENT_SAA7113: |
@@ -1632,7 +1637,7 @@ static int saa711x_probe(struct i2c_client *client, | |||
1632 | state->crystal_freq = SAA7115_FREQ_32_11_MHZ; | 1637 | state->crystal_freq = SAA7115_FREQ_32_11_MHZ; |
1633 | saa711x_writeregs(sd, saa7115_init_auto_input); | 1638 | saa711x_writeregs(sd, saa7115_init_auto_input); |
1634 | } | 1639 | } |
1635 | if (state->ident != V4L2_IDENT_SAA7111) | 1640 | if (state->ident > V4L2_IDENT_SAA7111A) |
1636 | saa711x_writeregs(sd, saa7115_init_misc); | 1641 | saa711x_writeregs(sd, saa7115_init_misc); |
1637 | saa711x_set_v4lstd(sd, V4L2_STD_NTSC); | 1642 | saa711x_set_v4lstd(sd, V4L2_STD_NTSC); |
1638 | 1643 | ||
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index 2fe7a701b954..250ef84cf5ca 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c | |||
@@ -181,7 +181,7 @@ static const struct i2c_reg_value saa7127_init_config_common[] = { | |||
181 | #define SAA7127_60HZ_DAC_CONTROL 0x15 | 181 | #define SAA7127_60HZ_DAC_CONTROL 0x15 |
182 | static const struct i2c_reg_value saa7127_init_config_60hz[] = { | 182 | static const struct i2c_reg_value saa7127_init_config_60hz[] = { |
183 | { SAA7127_REG_BURST_START, 0x19 }, | 183 | { SAA7127_REG_BURST_START, 0x19 }, |
184 | /* BURST_END is also used as a chip ID in saa7127_detect_client */ | 184 | /* BURST_END is also used as a chip ID in saa7127_probe */ |
185 | { SAA7127_REG_BURST_END, 0x1d }, | 185 | { SAA7127_REG_BURST_END, 0x1d }, |
186 | { SAA7127_REG_CHROMA_PHASE, 0xa3 }, | 186 | { SAA7127_REG_CHROMA_PHASE, 0xa3 }, |
187 | { SAA7127_REG_GAINU, 0x98 }, | 187 | { SAA7127_REG_GAINU, 0x98 }, |
@@ -200,10 +200,10 @@ static const struct i2c_reg_value saa7127_init_config_60hz[] = { | |||
200 | { 0, 0 } | 200 | { 0, 0 } |
201 | }; | 201 | }; |
202 | 202 | ||
203 | #define SAA7127_50HZ_DAC_CONTROL 0x02 | 203 | #define SAA7127_50HZ_PAL_DAC_CONTROL 0x02 |
204 | static struct i2c_reg_value saa7127_init_config_50hz[] = { | 204 | static struct i2c_reg_value saa7127_init_config_50hz_pal[] = { |
205 | { SAA7127_REG_BURST_START, 0x21 }, | 205 | { SAA7127_REG_BURST_START, 0x21 }, |
206 | /* BURST_END is also used as a chip ID in saa7127_detect_client */ | 206 | /* BURST_END is also used as a chip ID in saa7127_probe */ |
207 | { SAA7127_REG_BURST_END, 0x1d }, | 207 | { SAA7127_REG_BURST_END, 0x1d }, |
208 | { SAA7127_REG_CHROMA_PHASE, 0x3f }, | 208 | { SAA7127_REG_CHROMA_PHASE, 0x3f }, |
209 | { SAA7127_REG_GAINU, 0x7d }, | 209 | { SAA7127_REG_GAINU, 0x7d }, |
@@ -222,6 +222,28 @@ static struct i2c_reg_value saa7127_init_config_50hz[] = { | |||
222 | { 0, 0 } | 222 | { 0, 0 } |
223 | }; | 223 | }; |
224 | 224 | ||
225 | #define SAA7127_50HZ_SECAM_DAC_CONTROL 0x08 | ||
226 | static struct i2c_reg_value saa7127_init_config_50hz_secam[] = { | ||
227 | { SAA7127_REG_BURST_START, 0x21 }, | ||
228 | /* BURST_END is also used as a chip ID in saa7127_probe */ | ||
229 | { SAA7127_REG_BURST_END, 0x1d }, | ||
230 | { SAA7127_REG_CHROMA_PHASE, 0x3f }, | ||
231 | { SAA7127_REG_GAINU, 0x6a }, | ||
232 | { SAA7127_REG_GAINV, 0x81 }, | ||
233 | { SAA7127_REG_BLACK_LEVEL, 0x33 }, | ||
234 | { SAA7127_REG_BLANKING_LEVEL, 0x35 }, | ||
235 | { SAA7127_REG_VBI_BLANKING, 0x35 }, | ||
236 | { SAA7127_REG_DAC_CONTROL, 0x08 }, | ||
237 | { SAA7127_REG_BURST_AMP, 0x2f }, | ||
238 | { SAA7127_REG_SUBC3, 0xb2 }, | ||
239 | { SAA7127_REG_SUBC2, 0x3b }, | ||
240 | { SAA7127_REG_SUBC1, 0xa3 }, | ||
241 | { SAA7127_REG_SUBC0, 0x28 }, | ||
242 | { SAA7127_REG_MULTI, 0x90 }, | ||
243 | { SAA7127_REG_CLOSED_CAPTION, 0x00 }, | ||
244 | { 0, 0 } | ||
245 | }; | ||
246 | |||
225 | /* | 247 | /* |
226 | ********************************************************************** | 248 | ********************************************************************** |
227 | * | 249 | * |
@@ -463,10 +485,21 @@ static int saa7127_set_std(struct v4l2_subdev *sd, v4l2_std_id std) | |||
463 | v4l2_dbg(1, debug, sd, "Selecting 60 Hz video Standard\n"); | 485 | v4l2_dbg(1, debug, sd, "Selecting 60 Hz video Standard\n"); |
464 | inittab = saa7127_init_config_60hz; | 486 | inittab = saa7127_init_config_60hz; |
465 | state->reg_61 = SAA7127_60HZ_DAC_CONTROL; | 487 | state->reg_61 = SAA7127_60HZ_DAC_CONTROL; |
488 | |||
489 | } else if (state->ident == V4L2_IDENT_SAA7129 && | ||
490 | (std & V4L2_STD_SECAM) && | ||
491 | !(std & (V4L2_STD_625_50 & ~V4L2_STD_SECAM))) { | ||
492 | |||
493 | /* If and only if SECAM, with a SAA712[89] */ | ||
494 | v4l2_dbg(1, debug, sd, | ||
495 | "Selecting 50 Hz SECAM video Standard\n"); | ||
496 | inittab = saa7127_init_config_50hz_secam; | ||
497 | state->reg_61 = SAA7127_50HZ_SECAM_DAC_CONTROL; | ||
498 | |||
466 | } else { | 499 | } else { |
467 | v4l2_dbg(1, debug, sd, "Selecting 50 Hz video Standard\n"); | 500 | v4l2_dbg(1, debug, sd, "Selecting 50 Hz PAL video Standard\n"); |
468 | inittab = saa7127_init_config_50hz; | 501 | inittab = saa7127_init_config_50hz_pal; |
469 | state->reg_61 = SAA7127_50HZ_DAC_CONTROL; | 502 | state->reg_61 = SAA7127_50HZ_PAL_DAC_CONTROL; |
470 | } | 503 | } |
471 | 504 | ||
472 | /* Write Table */ | 505 | /* Write Table */ |
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 03f572708b85..297833fb3b4a 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c | |||
@@ -4160,7 +4160,7 @@ struct saa7134_board saa7134_boards[] = { | |||
4160 | .amux = LINE2, | 4160 | .amux = LINE2, |
4161 | }, | 4161 | }, |
4162 | }, | 4162 | }, |
4163 | [SAA7134_BOARD_BEHOLD_505RDS] = { | 4163 | [SAA7134_BOARD_BEHOLD_505RDS_MK5] = { |
4164 | /* Beholder Intl. Ltd. 2008 */ | 4164 | /* Beholder Intl. Ltd. 2008 */ |
4165 | /*Dmitry Belimov <d.belimov@gmail.com> */ | 4165 | /*Dmitry Belimov <d.belimov@gmail.com> */ |
4166 | .name = "Beholder BeholdTV 505 RDS", | 4166 | .name = "Beholder BeholdTV 505 RDS", |
@@ -5320,6 +5320,41 @@ struct saa7134_board saa7134_boards[] = { | |||
5320 | .vmux = 8, | 5320 | .vmux = 8, |
5321 | } }, | 5321 | } }, |
5322 | }, | 5322 | }, |
5323 | [SAA7134_BOARD_BEHOLD_505RDS_MK3] = { | ||
5324 | /* Beholder Intl. Ltd. 2008 */ | ||
5325 | /*Dmitry Belimov <d.belimov@gmail.com> */ | ||
5326 | .name = "Beholder BeholdTV 505 RDS", | ||
5327 | .audio_clock = 0x00200000, | ||
5328 | .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, | ||
5329 | .radio_type = UNSET, | ||
5330 | .tuner_addr = ADDR_UNSET, | ||
5331 | .radio_addr = ADDR_UNSET, | ||
5332 | .rds_addr = 0x10, | ||
5333 | .tda9887_conf = TDA9887_PRESENT, | ||
5334 | .gpiomask = 0x00008000, | ||
5335 | .inputs = {{ | ||
5336 | .name = name_tv, | ||
5337 | .vmux = 3, | ||
5338 | .amux = LINE2, | ||
5339 | .tv = 1, | ||
5340 | }, { | ||
5341 | .name = name_comp1, | ||
5342 | .vmux = 1, | ||
5343 | .amux = LINE1, | ||
5344 | }, { | ||
5345 | .name = name_svideo, | ||
5346 | .vmux = 8, | ||
5347 | .amux = LINE1, | ||
5348 | } }, | ||
5349 | .mute = { | ||
5350 | .name = name_mute, | ||
5351 | .amux = LINE1, | ||
5352 | }, | ||
5353 | .radio = { | ||
5354 | .name = name_radio, | ||
5355 | .amux = LINE2, | ||
5356 | }, | ||
5357 | }, | ||
5323 | 5358 | ||
5324 | }; | 5359 | }; |
5325 | 5360 | ||
@@ -6235,7 +6270,13 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
6235 | .device = PCI_DEVICE_ID_PHILIPS_SAA7130, | 6270 | .device = PCI_DEVICE_ID_PHILIPS_SAA7130, |
6236 | .subvendor = 0x0000, | 6271 | .subvendor = 0x0000, |
6237 | .subdevice = 0x505B, | 6272 | .subdevice = 0x505B, |
6238 | .driver_data = SAA7134_BOARD_BEHOLD_505RDS, | 6273 | .driver_data = SAA7134_BOARD_BEHOLD_505RDS_MK5, |
6274 | }, { | ||
6275 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
6276 | .device = PCI_DEVICE_ID_PHILIPS_SAA7130, | ||
6277 | .subvendor = 0x0000, | ||
6278 | .subdevice = 0x5051, | ||
6279 | .driver_data = SAA7134_BOARD_BEHOLD_505RDS_MK3, | ||
6239 | },{ | 6280 | },{ |
6240 | .vendor = PCI_VENDOR_ID_PHILIPS, | 6281 | .vendor = PCI_VENDOR_ID_PHILIPS, |
6241 | .device = PCI_DEVICE_ID_PHILIPS_SAA7130, | 6282 | .device = PCI_DEVICE_ID_PHILIPS_SAA7130, |
@@ -6792,7 +6833,8 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
6792 | case SAA7134_BOARD_BEHOLD_407FM: | 6833 | case SAA7134_BOARD_BEHOLD_407FM: |
6793 | case SAA7134_BOARD_BEHOLD_409: | 6834 | case SAA7134_BOARD_BEHOLD_409: |
6794 | case SAA7134_BOARD_BEHOLD_505FM: | 6835 | case SAA7134_BOARD_BEHOLD_505FM: |
6795 | case SAA7134_BOARD_BEHOLD_505RDS: | 6836 | case SAA7134_BOARD_BEHOLD_505RDS_MK5: |
6837 | case SAA7134_BOARD_BEHOLD_505RDS_MK3: | ||
6796 | case SAA7134_BOARD_BEHOLD_507_9FM: | 6838 | case SAA7134_BOARD_BEHOLD_507_9FM: |
6797 | case SAA7134_BOARD_BEHOLD_507RDS_MK3: | 6839 | case SAA7134_BOARD_BEHOLD_507RDS_MK3: |
6798 | case SAA7134_BOARD_BEHOLD_507RDS_MK5: | 6840 | case SAA7134_BOARD_BEHOLD_507RDS_MK5: |
@@ -6953,8 +6995,8 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
6953 | break; | 6995 | break; |
6954 | case SAA7134_BOARD_VIDEOMATE_S350: | 6996 | case SAA7134_BOARD_VIDEOMATE_S350: |
6955 | dev->has_remote = SAA7134_REMOTE_GPIO; | 6997 | dev->has_remote = SAA7134_REMOTE_GPIO; |
6956 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00008000, 0x00008000); | 6998 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x0000C000, 0x0000C000); |
6957 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00008000, 0x00008000); | 6999 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0000C000, 0x0000C000); |
6958 | break; | 7000 | break; |
6959 | } | 7001 | } |
6960 | return 0; | 7002 | return 0; |
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index f8e985989ca0..9499000f66b6 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -460,7 +460,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
460 | int polling = 0; | 460 | int polling = 0; |
461 | int rc5_gpio = 0; | 461 | int rc5_gpio = 0; |
462 | int nec_gpio = 0; | 462 | int nec_gpio = 0; |
463 | int ir_type = IR_TYPE_OTHER; | 463 | u64 ir_type = IR_TYPE_OTHER; |
464 | int err; | 464 | int err; |
465 | 465 | ||
466 | if (dev->has_remote != SAA7134_REMOTE_GPIO) | 466 | if (dev->has_remote != SAA7134_REMOTE_GPIO) |
@@ -568,7 +568,8 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
568 | case SAA7134_BOARD_BEHOLD_407FM: | 568 | case SAA7134_BOARD_BEHOLD_407FM: |
569 | case SAA7134_BOARD_BEHOLD_409: | 569 | case SAA7134_BOARD_BEHOLD_409: |
570 | case SAA7134_BOARD_BEHOLD_505FM: | 570 | case SAA7134_BOARD_BEHOLD_505FM: |
571 | case SAA7134_BOARD_BEHOLD_505RDS: | 571 | case SAA7134_BOARD_BEHOLD_505RDS_MK5: |
572 | case SAA7134_BOARD_BEHOLD_505RDS_MK3: | ||
572 | case SAA7134_BOARD_BEHOLD_507_9FM: | 573 | case SAA7134_BOARD_BEHOLD_507_9FM: |
573 | case SAA7134_BOARD_BEHOLD_507RDS_MK3: | 574 | case SAA7134_BOARD_BEHOLD_507RDS_MK3: |
574 | case SAA7134_BOARD_BEHOLD_507RDS_MK5: | 575 | case SAA7134_BOARD_BEHOLD_507RDS_MK5: |
@@ -728,7 +729,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
728 | dev->remote = ir; | 729 | dev->remote = ir; |
729 | saa7134_ir_start(dev, ir); | 730 | saa7134_ir_start(dev, ir); |
730 | 731 | ||
731 | err = ir_input_register(ir->dev, ir_codes); | 732 | err = ir_input_register(ir->dev, ir_codes, NULL); |
732 | if (err) | 733 | if (err) |
733 | goto err_out_stop; | 734 | goto err_out_stop; |
734 | 735 | ||
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index cb732640ac4a..31138d3e51bb 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c | |||
@@ -205,7 +205,7 @@ static struct saa7134_format formats[] = { | |||
205 | 205 | ||
206 | #define NORM_525_60 \ | 206 | #define NORM_525_60 \ |
207 | .h_start = 0, \ | 207 | .h_start = 0, \ |
208 | .h_stop = 703, \ | 208 | .h_stop = 719, \ |
209 | .video_v_start = 23, \ | 209 | .video_v_start = 23, \ |
210 | .video_v_stop = 262, \ | 210 | .video_v_stop = 262, \ |
211 | .vbi_v_start_0 = 10, \ | 211 | .vbi_v_start_0 = 10, \ |
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 53b7e0b8a2fb..bf130967ed17 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h | |||
@@ -282,7 +282,7 @@ struct saa7134_format { | |||
282 | #define SAA7134_BOARD_HAUPPAUGE_HVR1120 156 | 282 | #define SAA7134_BOARD_HAUPPAUGE_HVR1120 156 |
283 | #define SAA7134_BOARD_AVERMEDIA_STUDIO_507UA 157 | 283 | #define SAA7134_BOARD_AVERMEDIA_STUDIO_507UA 157 |
284 | #define SAA7134_BOARD_AVERMEDIA_CARDBUS_501 158 | 284 | #define SAA7134_BOARD_AVERMEDIA_CARDBUS_501 158 |
285 | #define SAA7134_BOARD_BEHOLD_505RDS 159 | 285 | #define SAA7134_BOARD_BEHOLD_505RDS_MK5 159 |
286 | #define SAA7134_BOARD_BEHOLD_507RDS_MK3 160 | 286 | #define SAA7134_BOARD_BEHOLD_507RDS_MK3 160 |
287 | #define SAA7134_BOARD_BEHOLD_507RDS_MK5 161 | 287 | #define SAA7134_BOARD_BEHOLD_507RDS_MK5 161 |
288 | #define SAA7134_BOARD_BEHOLD_607FM_MK5 162 | 288 | #define SAA7134_BOARD_BEHOLD_607FM_MK5 162 |
@@ -299,6 +299,7 @@ struct saa7134_format { | |||
299 | #define SAA7134_BOARD_ZOLID_HYBRID_PCI 173 | 299 | #define SAA7134_BOARD_ZOLID_HYBRID_PCI 173 |
300 | #define SAA7134_BOARD_ASUS_EUROPA_HYBRID 174 | 300 | #define SAA7134_BOARD_ASUS_EUROPA_HYBRID 174 |
301 | #define SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S 175 | 301 | #define SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S 175 |
302 | #define SAA7134_BOARD_BEHOLD_505RDS_MK3 176 | ||
302 | 303 | ||
303 | #define SAA7134_MAXBOARDS 32 | 304 | #define SAA7134_MAXBOARDS 32 |
304 | #define SAA7134_INPUT_MAX 8 | 305 | #define SAA7134_INPUT_MAX 8 |
diff --git a/drivers/media/video/saa7164/saa7164-api.c b/drivers/media/video/saa7164/saa7164-api.c index 6f094a96ac81..1d487c150340 100644 --- a/drivers/media/video/saa7164/saa7164-api.c +++ b/drivers/media/video/saa7164/saa7164-api.c | |||
@@ -523,7 +523,7 @@ int saa7164_api_i2c_write(struct saa7164_i2c *bus, u8 addr, u32 datalen, | |||
523 | } | 523 | } |
524 | 524 | ||
525 | reglen = saa7164_i2caddr_to_reglen(bus, addr); | 525 | reglen = saa7164_i2caddr_to_reglen(bus, addr); |
526 | if (unitid < 0) { | 526 | if (reglen < 0) { |
527 | printk(KERN_ERR | 527 | printk(KERN_ERR |
528 | "%s() error, cannot translate regaddr to reglen\n", | 528 | "%s() error, cannot translate regaddr to reglen\n", |
529 | __func__); | 529 | __func__); |
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index f09c7140d6b2..fb88c63188f3 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c | |||
@@ -1748,6 +1748,22 @@ static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q, | |||
1748 | icd); | 1748 | icd); |
1749 | } | 1749 | } |
1750 | 1750 | ||
1751 | static int sh_mobile_ceu_get_parm(struct soc_camera_device *icd, | ||
1752 | struct v4l2_streamparm *parm) | ||
1753 | { | ||
1754 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
1755 | |||
1756 | return v4l2_subdev_call(sd, video, g_parm, parm); | ||
1757 | } | ||
1758 | |||
1759 | static int sh_mobile_ceu_set_parm(struct soc_camera_device *icd, | ||
1760 | struct v4l2_streamparm *parm) | ||
1761 | { | ||
1762 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
1763 | |||
1764 | return v4l2_subdev_call(sd, video, s_parm, parm); | ||
1765 | } | ||
1766 | |||
1751 | static int sh_mobile_ceu_get_ctrl(struct soc_camera_device *icd, | 1767 | static int sh_mobile_ceu_get_ctrl(struct soc_camera_device *icd, |
1752 | struct v4l2_control *ctrl) | 1768 | struct v4l2_control *ctrl) |
1753 | { | 1769 | { |
@@ -1808,6 +1824,8 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = { | |||
1808 | .try_fmt = sh_mobile_ceu_try_fmt, | 1824 | .try_fmt = sh_mobile_ceu_try_fmt, |
1809 | .set_ctrl = sh_mobile_ceu_set_ctrl, | 1825 | .set_ctrl = sh_mobile_ceu_set_ctrl, |
1810 | .get_ctrl = sh_mobile_ceu_get_ctrl, | 1826 | .get_ctrl = sh_mobile_ceu_get_ctrl, |
1827 | .set_parm = sh_mobile_ceu_set_parm, | ||
1828 | .get_parm = sh_mobile_ceu_get_parm, | ||
1811 | .reqbufs = sh_mobile_ceu_reqbufs, | 1829 | .reqbufs = sh_mobile_ceu_reqbufs, |
1812 | .poll = sh_mobile_ceu_poll, | 1830 | .poll = sh_mobile_ceu_poll, |
1813 | .querycap = sh_mobile_ceu_querycap, | 1831 | .querycap = sh_mobile_ceu_querycap, |
diff --git a/drivers/media/video/sn9c102/Kconfig b/drivers/media/video/sn9c102/Kconfig index f71f272776de..6ebaf2940d06 100644 --- a/drivers/media/video/sn9c102/Kconfig +++ b/drivers/media/video/sn9c102/Kconfig | |||
@@ -1,7 +1,10 @@ | |||
1 | config USB_SN9C102 | 1 | config USB_SN9C102 |
2 | tristate "USB SN9C1xx PC Camera Controller support" | 2 | tristate "USB SN9C1xx PC Camera Controller support (DEPRECATED)" |
3 | depends on VIDEO_V4L2 | 3 | depends on VIDEO_V4L2 |
4 | ---help--- | 4 | ---help--- |
5 | This driver is DEPRECATED please use the gspca sonixb and | ||
6 | sonixj modules instead. | ||
7 | |||
5 | Say Y here if you want support for cameras based on SONiX SN9C101, | 8 | Say Y here if you want support for cameras based on SONiX SN9C101, |
6 | SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers. | 9 | SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers. |
7 | 10 | ||
diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h index 36ee43a9ee95..cc40d6ba9f22 100644 --- a/drivers/media/video/sn9c102/sn9c102_devtable.h +++ b/drivers/media/video/sn9c102/sn9c102_devtable.h | |||
@@ -45,20 +45,24 @@ static const struct usb_device_id sn9c102_id_table[] = { | |||
45 | { SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), }, | 45 | { SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), }, |
46 | #endif | 46 | #endif |
47 | { SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), }, | 47 | { SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), }, |
48 | #if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE | ||
48 | { SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), }, | 49 | { SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), }, |
49 | { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), }, | 50 | { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), }, |
50 | /* { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, OV6650 */ | 51 | /* { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, OV6650 */ |
52 | #endif | ||
51 | { SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), }, | 53 | { SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), }, |
52 | { SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), }, | 54 | { SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), }, |
53 | { SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), }, | 55 | { SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), }, |
56 | #if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE | ||
54 | { SN9C102_USB_DEVICE(0x0c45, 0x6028, BRIDGE_SN9C102), }, | 57 | { SN9C102_USB_DEVICE(0x0c45, 0x6028, BRIDGE_SN9C102), }, |
55 | { SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), }, | 58 | { SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), }, |
59 | #endif | ||
56 | { SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), }, | 60 | { SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), }, |
57 | { SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), }, | 61 | { SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), }, |
58 | #if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE | 62 | #if !defined CONFIG_USB_GSPCA && !defined CONFIG_USB_GSPCA_MODULE |
59 | { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), }, | 63 | { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), }, |
60 | #endif | ||
61 | /* { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, HV7131R */ | 64 | /* { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, HV7131R */ |
65 | #endif | ||
62 | { SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), }, | 66 | { SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), }, |
63 | { SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), }, | 67 | { SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), }, |
64 | /* SN9C103 */ | 68 | /* SN9C103 */ |
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 6b3fbcca7747..80f6bfa2632b 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c | |||
@@ -781,6 +781,32 @@ static int soc_camera_s_crop(struct file *file, void *fh, | |||
781 | return ret; | 781 | return ret; |
782 | } | 782 | } |
783 | 783 | ||
784 | static int soc_camera_g_parm(struct file *file, void *fh, | ||
785 | struct v4l2_streamparm *a) | ||
786 | { | ||
787 | struct soc_camera_file *icf = file->private_data; | ||
788 | struct soc_camera_device *icd = icf->icd; | ||
789 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
790 | |||
791 | if (ici->ops->get_parm) | ||
792 | return ici->ops->get_parm(icd, a); | ||
793 | |||
794 | return -ENOIOCTLCMD; | ||
795 | } | ||
796 | |||
797 | static int soc_camera_s_parm(struct file *file, void *fh, | ||
798 | struct v4l2_streamparm *a) | ||
799 | { | ||
800 | struct soc_camera_file *icf = file->private_data; | ||
801 | struct soc_camera_device *icd = icf->icd; | ||
802 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
803 | |||
804 | if (ici->ops->set_parm) | ||
805 | return ici->ops->set_parm(icd, a); | ||
806 | |||
807 | return -ENOIOCTLCMD; | ||
808 | } | ||
809 | |||
784 | static int soc_camera_g_chip_ident(struct file *file, void *fh, | 810 | static int soc_camera_g_chip_ident(struct file *file, void *fh, |
785 | struct v4l2_dbg_chip_ident *id) | 811 | struct v4l2_dbg_chip_ident *id) |
786 | { | 812 | { |
@@ -846,10 +872,8 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd, | |||
846 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 872 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
847 | struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id); | 873 | struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id); |
848 | struct v4l2_subdev *subdev; | 874 | struct v4l2_subdev *subdev; |
849 | int ret; | ||
850 | 875 | ||
851 | if (!adap) { | 876 | if (!adap) { |
852 | ret = -ENODEV; | ||
853 | dev_err(&icd->dev, "Cannot get I2C adapter #%d. No driver?\n", | 877 | dev_err(&icd->dev, "Cannot get I2C adapter #%d. No driver?\n", |
854 | icl->i2c_adapter_id); | 878 | icl->i2c_adapter_id); |
855 | goto ei2cga; | 879 | goto ei2cga; |
@@ -859,10 +883,8 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd, | |||
859 | 883 | ||
860 | subdev = v4l2_i2c_new_subdev_board(&ici->v4l2_dev, adap, | 884 | subdev = v4l2_i2c_new_subdev_board(&ici->v4l2_dev, adap, |
861 | icl->module_name, icl->board_info, NULL); | 885 | icl->module_name, icl->board_info, NULL); |
862 | if (!subdev) { | 886 | if (!subdev) |
863 | ret = -ENOMEM; | ||
864 | goto ei2cnd; | 887 | goto ei2cnd; |
865 | } | ||
866 | 888 | ||
867 | client = subdev->priv; | 889 | client = subdev->priv; |
868 | 890 | ||
@@ -873,7 +895,7 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd, | |||
873 | ei2cnd: | 895 | ei2cnd: |
874 | i2c_put_adapter(adap); | 896 | i2c_put_adapter(adap); |
875 | ei2cga: | 897 | ei2cga: |
876 | return ret; | 898 | return -ENODEV; |
877 | } | 899 | } |
878 | 900 | ||
879 | static void soc_camera_free_i2c(struct soc_camera_device *icd) | 901 | static void soc_camera_free_i2c(struct soc_camera_device *icd) |
@@ -1260,6 +1282,8 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = { | |||
1260 | .vidioc_cropcap = soc_camera_cropcap, | 1282 | .vidioc_cropcap = soc_camera_cropcap, |
1261 | .vidioc_g_crop = soc_camera_g_crop, | 1283 | .vidioc_g_crop = soc_camera_g_crop, |
1262 | .vidioc_s_crop = soc_camera_s_crop, | 1284 | .vidioc_s_crop = soc_camera_s_crop, |
1285 | .vidioc_g_parm = soc_camera_g_parm, | ||
1286 | .vidioc_s_parm = soc_camera_s_parm, | ||
1263 | .vidioc_g_chip_ident = soc_camera_g_chip_ident, | 1287 | .vidioc_g_chip_ident = soc_camera_g_chip_ident, |
1264 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 1288 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
1265 | .vidioc_g_register = soc_camera_g_register, | 1289 | .vidioc_g_register = soc_camera_g_register, |
diff --git a/drivers/media/video/soc_mediabus.c b/drivers/media/video/soc_mediabus.c index f8d5c87dc2aa..8b63b6545e76 100644 --- a/drivers/media/video/soc_mediabus.c +++ b/drivers/media/video/soc_mediabus.c | |||
@@ -24,91 +24,106 @@ static const struct soc_mbus_pixelfmt mbus_fmt[] = { | |||
24 | .bits_per_sample = 8, | 24 | .bits_per_sample = 8, |
25 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 25 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
26 | .order = SOC_MBUS_ORDER_LE, | 26 | .order = SOC_MBUS_ORDER_LE, |
27 | }, [MBUS_IDX(YVYU8_2X8_LE)] = { | 27 | }, |
28 | [MBUS_IDX(YVYU8_2X8_LE)] = { | ||
28 | .fourcc = V4L2_PIX_FMT_YVYU, | 29 | .fourcc = V4L2_PIX_FMT_YVYU, |
29 | .name = "YVYU", | 30 | .name = "YVYU", |
30 | .bits_per_sample = 8, | 31 | .bits_per_sample = 8, |
31 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 32 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
32 | .order = SOC_MBUS_ORDER_LE, | 33 | .order = SOC_MBUS_ORDER_LE, |
33 | }, [MBUS_IDX(YUYV8_2X8_BE)] = { | 34 | }, |
35 | [MBUS_IDX(YUYV8_2X8_BE)] = { | ||
34 | .fourcc = V4L2_PIX_FMT_UYVY, | 36 | .fourcc = V4L2_PIX_FMT_UYVY, |
35 | .name = "UYVY", | 37 | .name = "UYVY", |
36 | .bits_per_sample = 8, | 38 | .bits_per_sample = 8, |
37 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 39 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
38 | .order = SOC_MBUS_ORDER_LE, | 40 | .order = SOC_MBUS_ORDER_LE, |
39 | }, [MBUS_IDX(YVYU8_2X8_BE)] = { | 41 | }, |
42 | [MBUS_IDX(YVYU8_2X8_BE)] = { | ||
40 | .fourcc = V4L2_PIX_FMT_VYUY, | 43 | .fourcc = V4L2_PIX_FMT_VYUY, |
41 | .name = "VYUY", | 44 | .name = "VYUY", |
42 | .bits_per_sample = 8, | 45 | .bits_per_sample = 8, |
43 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 46 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
44 | .order = SOC_MBUS_ORDER_LE, | 47 | .order = SOC_MBUS_ORDER_LE, |
45 | }, [MBUS_IDX(RGB555_2X8_PADHI_LE)] = { | 48 | }, |
49 | [MBUS_IDX(RGB555_2X8_PADHI_LE)] = { | ||
46 | .fourcc = V4L2_PIX_FMT_RGB555, | 50 | .fourcc = V4L2_PIX_FMT_RGB555, |
47 | .name = "RGB555", | 51 | .name = "RGB555", |
48 | .bits_per_sample = 8, | 52 | .bits_per_sample = 8, |
49 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 53 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
50 | .order = SOC_MBUS_ORDER_LE, | 54 | .order = SOC_MBUS_ORDER_LE, |
51 | }, [MBUS_IDX(RGB555_2X8_PADHI_BE)] = { | 55 | }, |
56 | [MBUS_IDX(RGB555_2X8_PADHI_BE)] = { | ||
52 | .fourcc = V4L2_PIX_FMT_RGB555X, | 57 | .fourcc = V4L2_PIX_FMT_RGB555X, |
53 | .name = "RGB555X", | 58 | .name = "RGB555X", |
54 | .bits_per_sample = 8, | 59 | .bits_per_sample = 8, |
55 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 60 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
56 | .order = SOC_MBUS_ORDER_LE, | 61 | .order = SOC_MBUS_ORDER_LE, |
57 | }, [MBUS_IDX(RGB565_2X8_LE)] = { | 62 | }, |
63 | [MBUS_IDX(RGB565_2X8_LE)] = { | ||
58 | .fourcc = V4L2_PIX_FMT_RGB565, | 64 | .fourcc = V4L2_PIX_FMT_RGB565, |
59 | .name = "RGB565", | 65 | .name = "RGB565", |
60 | .bits_per_sample = 8, | 66 | .bits_per_sample = 8, |
61 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 67 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
62 | .order = SOC_MBUS_ORDER_LE, | 68 | .order = SOC_MBUS_ORDER_LE, |
63 | }, [MBUS_IDX(RGB565_2X8_BE)] = { | 69 | }, |
70 | [MBUS_IDX(RGB565_2X8_BE)] = { | ||
64 | .fourcc = V4L2_PIX_FMT_RGB565X, | 71 | .fourcc = V4L2_PIX_FMT_RGB565X, |
65 | .name = "RGB565X", | 72 | .name = "RGB565X", |
66 | .bits_per_sample = 8, | 73 | .bits_per_sample = 8, |
67 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 74 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
68 | .order = SOC_MBUS_ORDER_LE, | 75 | .order = SOC_MBUS_ORDER_LE, |
69 | }, [MBUS_IDX(SBGGR8_1X8)] = { | 76 | }, |
77 | [MBUS_IDX(SBGGR8_1X8)] = { | ||
70 | .fourcc = V4L2_PIX_FMT_SBGGR8, | 78 | .fourcc = V4L2_PIX_FMT_SBGGR8, |
71 | .name = "Bayer 8 BGGR", | 79 | .name = "Bayer 8 BGGR", |
72 | .bits_per_sample = 8, | 80 | .bits_per_sample = 8, |
73 | .packing = SOC_MBUS_PACKING_NONE, | 81 | .packing = SOC_MBUS_PACKING_NONE, |
74 | .order = SOC_MBUS_ORDER_LE, | 82 | .order = SOC_MBUS_ORDER_LE, |
75 | }, [MBUS_IDX(SBGGR10_1X10)] = { | 83 | }, |
84 | [MBUS_IDX(SBGGR10_1X10)] = { | ||
76 | .fourcc = V4L2_PIX_FMT_SBGGR10, | 85 | .fourcc = V4L2_PIX_FMT_SBGGR10, |
77 | .name = "Bayer 10 BGGR", | 86 | .name = "Bayer 10 BGGR", |
78 | .bits_per_sample = 10, | 87 | .bits_per_sample = 10, |
79 | .packing = SOC_MBUS_PACKING_EXTEND16, | 88 | .packing = SOC_MBUS_PACKING_EXTEND16, |
80 | .order = SOC_MBUS_ORDER_LE, | 89 | .order = SOC_MBUS_ORDER_LE, |
81 | }, [MBUS_IDX(GREY8_1X8)] = { | 90 | }, |
91 | [MBUS_IDX(GREY8_1X8)] = { | ||
82 | .fourcc = V4L2_PIX_FMT_GREY, | 92 | .fourcc = V4L2_PIX_FMT_GREY, |
83 | .name = "Grey", | 93 | .name = "Grey", |
84 | .bits_per_sample = 8, | 94 | .bits_per_sample = 8, |
85 | .packing = SOC_MBUS_PACKING_NONE, | 95 | .packing = SOC_MBUS_PACKING_NONE, |
86 | .order = SOC_MBUS_ORDER_LE, | 96 | .order = SOC_MBUS_ORDER_LE, |
87 | }, [MBUS_IDX(Y10_1X10)] = { | 97 | }, |
98 | [MBUS_IDX(Y10_1X10)] = { | ||
88 | .fourcc = V4L2_PIX_FMT_Y10, | 99 | .fourcc = V4L2_PIX_FMT_Y10, |
89 | .name = "Grey 10bit", | 100 | .name = "Grey 10bit", |
90 | .bits_per_sample = 10, | 101 | .bits_per_sample = 10, |
91 | .packing = SOC_MBUS_PACKING_EXTEND16, | 102 | .packing = SOC_MBUS_PACKING_EXTEND16, |
92 | .order = SOC_MBUS_ORDER_LE, | 103 | .order = SOC_MBUS_ORDER_LE, |
93 | }, [MBUS_IDX(SBGGR10_2X8_PADHI_LE)] = { | 104 | }, |
105 | [MBUS_IDX(SBGGR10_2X8_PADHI_LE)] = { | ||
94 | .fourcc = V4L2_PIX_FMT_SBGGR10, | 106 | .fourcc = V4L2_PIX_FMT_SBGGR10, |
95 | .name = "Bayer 10 BGGR", | 107 | .name = "Bayer 10 BGGR", |
96 | .bits_per_sample = 8, | 108 | .bits_per_sample = 8, |
97 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 109 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
98 | .order = SOC_MBUS_ORDER_LE, | 110 | .order = SOC_MBUS_ORDER_LE, |
99 | }, [MBUS_IDX(SBGGR10_2X8_PADLO_LE)] = { | 111 | }, |
112 | [MBUS_IDX(SBGGR10_2X8_PADLO_LE)] = { | ||
100 | .fourcc = V4L2_PIX_FMT_SBGGR10, | 113 | .fourcc = V4L2_PIX_FMT_SBGGR10, |
101 | .name = "Bayer 10 BGGR", | 114 | .name = "Bayer 10 BGGR", |
102 | .bits_per_sample = 8, | 115 | .bits_per_sample = 8, |
103 | .packing = SOC_MBUS_PACKING_2X8_PADLO, | 116 | .packing = SOC_MBUS_PACKING_2X8_PADLO, |
104 | .order = SOC_MBUS_ORDER_LE, | 117 | .order = SOC_MBUS_ORDER_LE, |
105 | }, [MBUS_IDX(SBGGR10_2X8_PADHI_BE)] = { | 118 | }, |
119 | [MBUS_IDX(SBGGR10_2X8_PADHI_BE)] = { | ||
106 | .fourcc = V4L2_PIX_FMT_SBGGR10, | 120 | .fourcc = V4L2_PIX_FMT_SBGGR10, |
107 | .name = "Bayer 10 BGGR", | 121 | .name = "Bayer 10 BGGR", |
108 | .bits_per_sample = 8, | 122 | .bits_per_sample = 8, |
109 | .packing = SOC_MBUS_PACKING_2X8_PADHI, | 123 | .packing = SOC_MBUS_PACKING_2X8_PADHI, |
110 | .order = SOC_MBUS_ORDER_BE, | 124 | .order = SOC_MBUS_ORDER_BE, |
111 | }, [MBUS_IDX(SBGGR10_2X8_PADLO_BE)] = { | 125 | }, |
126 | [MBUS_IDX(SBGGR10_2X8_PADLO_BE)] = { | ||
112 | .fourcc = V4L2_PIX_FMT_SBGGR10, | 127 | .fourcc = V4L2_PIX_FMT_SBGGR10, |
113 | .name = "Bayer 10 BGGR", | 128 | .name = "Bayer 10 BGGR", |
114 | .bits_per_sample = 8, | 129 | .bits_per_sample = 8, |
@@ -134,7 +149,8 @@ EXPORT_SYMBOL(soc_mbus_bytes_per_line); | |||
134 | const struct soc_mbus_pixelfmt *soc_mbus_get_fmtdesc( | 149 | const struct soc_mbus_pixelfmt *soc_mbus_get_fmtdesc( |
135 | enum v4l2_mbus_pixelcode code) | 150 | enum v4l2_mbus_pixelcode code) |
136 | { | 151 | { |
137 | if ((unsigned int)(code - V4L2_MBUS_FMT_FIXED) > ARRAY_SIZE(mbus_fmt)) | 152 | if (code - V4L2_MBUS_FMT_FIXED > ARRAY_SIZE(mbus_fmt) || |
153 | code <= V4L2_MBUS_FMT_FIXED) | ||
138 | return NULL; | 154 | return NULL; |
139 | return mbus_fmt + code - V4L2_MBUS_FMT_FIXED - 1; | 155 | return mbus_fmt + code - V4L2_MBUS_FMT_FIXED - 1; |
140 | } | 156 | } |
diff --git a/drivers/media/video/tlg2300/Kconfig b/drivers/media/video/tlg2300/Kconfig new file mode 100644 index 000000000000..2c29ec659b4e --- /dev/null +++ b/drivers/media/video/tlg2300/Kconfig | |||
@@ -0,0 +1,16 @@ | |||
1 | config VIDEO_TLG2300 | ||
2 | tristate "Telegent TLG2300 USB video capture support" | ||
3 | depends on VIDEO_DEV && I2C && INPUT && SND && DVB_CORE | ||
4 | select VIDEO_TUNER | ||
5 | select VIDEO_TVEEPROM | ||
6 | select VIDEO_IR | ||
7 | select VIDEOBUF_VMALLOC | ||
8 | select SND_PCM | ||
9 | select VIDEOBUF_DVB | ||
10 | |||
11 | ---help--- | ||
12 | This is a video4linux driver for Telegent tlg2300 based TV cards. | ||
13 | The driver supports V4L2, DVB-T and radio. | ||
14 | |||
15 | To compile this driver as a module, choose M here: the | ||
16 | module will be called poseidon | ||
diff --git a/drivers/media/video/tlg2300/Makefile b/drivers/media/video/tlg2300/Makefile new file mode 100644 index 000000000000..81bb7fdd1e3d --- /dev/null +++ b/drivers/media/video/tlg2300/Makefile | |||
@@ -0,0 +1,9 @@ | |||
1 | poseidon-objs := pd-video.o pd-alsa.o pd-dvb.o pd-radio.o pd-main.o | ||
2 | |||
3 | obj-$(CONFIG_VIDEO_TLG2300) += poseidon.o | ||
4 | |||
5 | EXTRA_CFLAGS += -Idrivers/media/video | ||
6 | EXTRA_CFLAGS += -Idrivers/media/common/tuners | ||
7 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core | ||
8 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends | ||
9 | |||
diff --git a/drivers/media/video/tlg2300/pd-alsa.c b/drivers/media/video/tlg2300/pd-alsa.c new file mode 100644 index 000000000000..6f42621ad478 --- /dev/null +++ b/drivers/media/video/tlg2300/pd-alsa.c | |||
@@ -0,0 +1,332 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/usb.h> | ||
3 | #include <linux/init.h> | ||
4 | #include <linux/sound.h> | ||
5 | #include <linux/spinlock.h> | ||
6 | #include <linux/soundcard.h> | ||
7 | #include <linux/slab.h> | ||
8 | #include <linux/vmalloc.h> | ||
9 | #include <linux/proc_fs.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <sound/core.h> | ||
12 | #include <sound/pcm.h> | ||
13 | #include <sound/pcm_params.h> | ||
14 | #include <sound/info.h> | ||
15 | #include <sound/initval.h> | ||
16 | #include <sound/control.h> | ||
17 | #include <media/v4l2-common.h> | ||
18 | #include "pd-common.h" | ||
19 | #include "vendorcmds.h" | ||
20 | |||
21 | static void complete_handler_audio(struct urb *urb); | ||
22 | #define AUDIO_EP (0x83) | ||
23 | #define AUDIO_BUF_SIZE (512) | ||
24 | #define PERIOD_SIZE (1024 * 8) | ||
25 | #define PERIOD_MIN (4) | ||
26 | #define PERIOD_MAX PERIOD_MIN | ||
27 | |||
28 | static struct snd_pcm_hardware snd_pd_hw_capture = { | ||
29 | .info = SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
30 | SNDRV_PCM_INFO_MMAP | | ||
31 | SNDRV_PCM_INFO_INTERLEAVED | | ||
32 | SNDRV_PCM_INFO_MMAP_VALID, | ||
33 | |||
34 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
35 | .rates = SNDRV_PCM_RATE_48000, | ||
36 | |||
37 | .rate_min = 48000, | ||
38 | .rate_max = 48000, | ||
39 | .channels_min = 2, | ||
40 | .channels_max = 2, | ||
41 | .buffer_bytes_max = PERIOD_SIZE * PERIOD_MIN, | ||
42 | .period_bytes_min = PERIOD_SIZE, | ||
43 | .period_bytes_max = PERIOD_SIZE, | ||
44 | .periods_min = PERIOD_MIN, | ||
45 | .periods_max = PERIOD_MAX, | ||
46 | /* | ||
47 | .buffer_bytes_max = 62720 * 8, | ||
48 | .period_bytes_min = 64, | ||
49 | .period_bytes_max = 12544, | ||
50 | .periods_min = 2, | ||
51 | .periods_max = 98 | ||
52 | */ | ||
53 | }; | ||
54 | |||
55 | static int snd_pd_capture_open(struct snd_pcm_substream *substream) | ||
56 | { | ||
57 | struct poseidon *p = snd_pcm_substream_chip(substream); | ||
58 | struct poseidon_audio *pa = &p->audio; | ||
59 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
60 | |||
61 | if (!p) | ||
62 | return -ENODEV; | ||
63 | pa->users++; | ||
64 | pa->card_close = 0; | ||
65 | pa->capture_pcm_substream = substream; | ||
66 | runtime->private_data = p; | ||
67 | |||
68 | runtime->hw = snd_pd_hw_capture; | ||
69 | snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | ||
70 | usb_autopm_get_interface(p->interface); | ||
71 | kref_get(&p->kref); | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | static int snd_pd_pcm_close(struct snd_pcm_substream *substream) | ||
76 | { | ||
77 | struct poseidon *p = snd_pcm_substream_chip(substream); | ||
78 | struct poseidon_audio *pa = &p->audio; | ||
79 | |||
80 | pa->users--; | ||
81 | pa->card_close = 1; | ||
82 | usb_autopm_put_interface(p->interface); | ||
83 | kref_put(&p->kref, poseidon_delete); | ||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static int snd_pd_hw_capture_params(struct snd_pcm_substream *substream, | ||
88 | struct snd_pcm_hw_params *hw_params) | ||
89 | { | ||
90 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
91 | unsigned int size; | ||
92 | |||
93 | size = params_buffer_bytes(hw_params); | ||
94 | if (runtime->dma_area) { | ||
95 | if (runtime->dma_bytes > size) | ||
96 | return 0; | ||
97 | vfree(runtime->dma_area); | ||
98 | } | ||
99 | runtime->dma_area = vmalloc(size); | ||
100 | if (!runtime->dma_area) | ||
101 | return -ENOMEM; | ||
102 | else | ||
103 | runtime->dma_bytes = size; | ||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static int audio_buf_free(struct poseidon *p) | ||
108 | { | ||
109 | struct poseidon_audio *pa = &p->audio; | ||
110 | int i; | ||
111 | |||
112 | for (i = 0; i < AUDIO_BUFS; i++) | ||
113 | if (pa->urb_array[i]) | ||
114 | usb_kill_urb(pa->urb_array[i]); | ||
115 | free_all_urb_generic(pa->urb_array, AUDIO_BUFS); | ||
116 | logpm(); | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static int snd_pd_hw_capture_free(struct snd_pcm_substream *substream) | ||
121 | { | ||
122 | struct poseidon *p = snd_pcm_substream_chip(substream); | ||
123 | |||
124 | logpm(); | ||
125 | audio_buf_free(p); | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static int snd_pd_prepare(struct snd_pcm_substream *substream) | ||
130 | { | ||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | #define AUDIO_TRAILER_SIZE (16) | ||
135 | static inline void handle_audio_data(struct urb *urb, int *period_elapsed) | ||
136 | { | ||
137 | struct poseidon_audio *pa = urb->context; | ||
138 | struct snd_pcm_runtime *runtime = pa->capture_pcm_substream->runtime; | ||
139 | |||
140 | int stride = runtime->frame_bits >> 3; | ||
141 | int len = urb->actual_length / stride; | ||
142 | unsigned char *cp = urb->transfer_buffer; | ||
143 | unsigned int oldptr = pa->rcv_position; | ||
144 | |||
145 | if (urb->actual_length == AUDIO_BUF_SIZE - 4) | ||
146 | len -= (AUDIO_TRAILER_SIZE / stride); | ||
147 | |||
148 | /* do the copy */ | ||
149 | if (oldptr + len >= runtime->buffer_size) { | ||
150 | unsigned int cnt = runtime->buffer_size - oldptr; | ||
151 | |||
152 | memcpy(runtime->dma_area + oldptr * stride, cp, cnt * stride); | ||
153 | memcpy(runtime->dma_area, (cp + cnt * stride), | ||
154 | (len * stride - cnt * stride)); | ||
155 | } else | ||
156 | memcpy(runtime->dma_area + oldptr * stride, cp, len * stride); | ||
157 | |||
158 | /* update the statas */ | ||
159 | snd_pcm_stream_lock(pa->capture_pcm_substream); | ||
160 | pa->rcv_position += len; | ||
161 | if (pa->rcv_position >= runtime->buffer_size) | ||
162 | pa->rcv_position -= runtime->buffer_size; | ||
163 | |||
164 | pa->copied_position += (len); | ||
165 | if (pa->copied_position >= runtime->period_size) { | ||
166 | pa->copied_position -= runtime->period_size; | ||
167 | *period_elapsed = 1; | ||
168 | } | ||
169 | snd_pcm_stream_unlock(pa->capture_pcm_substream); | ||
170 | } | ||
171 | |||
172 | static void complete_handler_audio(struct urb *urb) | ||
173 | { | ||
174 | struct poseidon_audio *pa = urb->context; | ||
175 | struct snd_pcm_substream *substream = pa->capture_pcm_substream; | ||
176 | int period_elapsed = 0; | ||
177 | int ret; | ||
178 | |||
179 | if (1 == pa->card_close || pa->capture_stream != STREAM_ON) | ||
180 | return; | ||
181 | |||
182 | if (urb->status != 0) { | ||
183 | /*if (urb->status == -ESHUTDOWN)*/ | ||
184 | return; | ||
185 | } | ||
186 | |||
187 | if (substream) { | ||
188 | if (urb->actual_length) { | ||
189 | handle_audio_data(urb, &period_elapsed); | ||
190 | if (period_elapsed) | ||
191 | snd_pcm_period_elapsed(substream); | ||
192 | } | ||
193 | } | ||
194 | |||
195 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
196 | if (ret < 0) | ||
197 | log("audio urb failed (errcod = %i)", ret); | ||
198 | return; | ||
199 | } | ||
200 | |||
201 | static int fire_audio_urb(struct poseidon *p) | ||
202 | { | ||
203 | int i, ret = 0; | ||
204 | struct poseidon_audio *pa = &p->audio; | ||
205 | |||
206 | alloc_bulk_urbs_generic(pa->urb_array, AUDIO_BUFS, | ||
207 | p->udev, AUDIO_EP, | ||
208 | AUDIO_BUF_SIZE, GFP_ATOMIC, | ||
209 | complete_handler_audio, pa); | ||
210 | |||
211 | for (i = 0; i < AUDIO_BUFS; i++) { | ||
212 | ret = usb_submit_urb(pa->urb_array[i], GFP_KERNEL); | ||
213 | if (ret) | ||
214 | log("urb err : %d", ret); | ||
215 | } | ||
216 | log(); | ||
217 | return ret; | ||
218 | } | ||
219 | |||
220 | static int snd_pd_capture_trigger(struct snd_pcm_substream *substream, int cmd) | ||
221 | { | ||
222 | struct poseidon *p = snd_pcm_substream_chip(substream); | ||
223 | struct poseidon_audio *pa = &p->audio; | ||
224 | |||
225 | if (debug_mode) | ||
226 | log("cmd %d, audio stat : %d\n", cmd, pa->capture_stream); | ||
227 | |||
228 | switch (cmd) { | ||
229 | case SNDRV_PCM_TRIGGER_RESUME: | ||
230 | case SNDRV_PCM_TRIGGER_START: | ||
231 | if (pa->capture_stream == STREAM_ON) | ||
232 | return 0; | ||
233 | |||
234 | pa->rcv_position = pa->copied_position = 0; | ||
235 | pa->capture_stream = STREAM_ON; | ||
236 | |||
237 | if (in_hibernation(p)) | ||
238 | return 0; | ||
239 | fire_audio_urb(p); | ||
240 | return 0; | ||
241 | |||
242 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
243 | pa->capture_stream = STREAM_SUSPEND; | ||
244 | return 0; | ||
245 | case SNDRV_PCM_TRIGGER_STOP: | ||
246 | pa->capture_stream = STREAM_OFF; | ||
247 | return 0; | ||
248 | default: | ||
249 | return -EINVAL; | ||
250 | } | ||
251 | } | ||
252 | |||
253 | static snd_pcm_uframes_t | ||
254 | snd_pd_capture_pointer(struct snd_pcm_substream *substream) | ||
255 | { | ||
256 | struct poseidon *p = snd_pcm_substream_chip(substream); | ||
257 | struct poseidon_audio *pa = &p->audio; | ||
258 | return pa->rcv_position; | ||
259 | } | ||
260 | |||
261 | static struct page *snd_pcm_pd_get_page(struct snd_pcm_substream *subs, | ||
262 | unsigned long offset) | ||
263 | { | ||
264 | void *pageptr = subs->runtime->dma_area + offset; | ||
265 | return vmalloc_to_page(pageptr); | ||
266 | } | ||
267 | |||
268 | static struct snd_pcm_ops pcm_capture_ops = { | ||
269 | .open = snd_pd_capture_open, | ||
270 | .close = snd_pd_pcm_close, | ||
271 | .ioctl = snd_pcm_lib_ioctl, | ||
272 | .hw_params = snd_pd_hw_capture_params, | ||
273 | .hw_free = snd_pd_hw_capture_free, | ||
274 | .prepare = snd_pd_prepare, | ||
275 | .trigger = snd_pd_capture_trigger, | ||
276 | .pointer = snd_pd_capture_pointer, | ||
277 | .page = snd_pcm_pd_get_page, | ||
278 | }; | ||
279 | |||
280 | #ifdef CONFIG_PM | ||
281 | int pm_alsa_suspend(struct poseidon *p) | ||
282 | { | ||
283 | logpm(p); | ||
284 | audio_buf_free(p); | ||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | int pm_alsa_resume(struct poseidon *p) | ||
289 | { | ||
290 | logpm(p); | ||
291 | fire_audio_urb(p); | ||
292 | return 0; | ||
293 | } | ||
294 | #endif | ||
295 | |||
296 | int poseidon_audio_init(struct poseidon *p) | ||
297 | { | ||
298 | struct poseidon_audio *pa = &p->audio; | ||
299 | struct snd_card *card; | ||
300 | struct snd_pcm *pcm; | ||
301 | int ret; | ||
302 | |||
303 | ret = snd_card_create(-1, "Telegent", THIS_MODULE, 0, &card); | ||
304 | if (ret != 0) | ||
305 | return ret; | ||
306 | |||
307 | ret = snd_pcm_new(card, "poseidon audio", 0, 0, 1, &pcm); | ||
308 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops); | ||
309 | pcm->info_flags = 0; | ||
310 | pcm->private_data = p; | ||
311 | strcpy(pcm->name, "poseidon audio capture"); | ||
312 | |||
313 | strcpy(card->driver, "ALSA driver"); | ||
314 | strcpy(card->shortname, "poseidon Audio"); | ||
315 | strcpy(card->longname, "poseidon ALSA Audio"); | ||
316 | |||
317 | if (snd_card_register(card)) { | ||
318 | snd_card_free(card); | ||
319 | return -ENOMEM; | ||
320 | } | ||
321 | pa->card = card; | ||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | int poseidon_audio_free(struct poseidon *p) | ||
326 | { | ||
327 | struct poseidon_audio *pa = &p->audio; | ||
328 | |||
329 | if (pa->card) | ||
330 | snd_card_free(pa->card); | ||
331 | return 0; | ||
332 | } | ||
diff --git a/drivers/media/video/tlg2300/pd-common.h b/drivers/media/video/tlg2300/pd-common.h new file mode 100644 index 000000000000..46066bdc73f9 --- /dev/null +++ b/drivers/media/video/tlg2300/pd-common.h | |||
@@ -0,0 +1,282 @@ | |||
1 | #ifndef PD_COMMON_H | ||
2 | #define PD_COMMON_H | ||
3 | |||
4 | #include <linux/version.h> | ||
5 | #include <linux/fs.h> | ||
6 | #include <linux/wait.h> | ||
7 | #include <linux/list.h> | ||
8 | #include <linux/videodev2.h> | ||
9 | #include <linux/semaphore.h> | ||
10 | #include <linux/usb.h> | ||
11 | #include <linux/poll.h> | ||
12 | #include <media/videobuf-vmalloc.h> | ||
13 | #include <media/v4l2-device.h> | ||
14 | |||
15 | #include "dvb_frontend.h" | ||
16 | #include "dvbdev.h" | ||
17 | #include "dvb_demux.h" | ||
18 | #include "dmxdev.h" | ||
19 | |||
20 | #define SBUF_NUM 8 | ||
21 | #define MAX_BUFFER_NUM 6 | ||
22 | #define PK_PER_URB 32 | ||
23 | #define ISO_PKT_SIZE 3072 | ||
24 | |||
25 | #define POSEIDON_STATE_NONE (0x0000) | ||
26 | #define POSEIDON_STATE_ANALOG (0x0001) | ||
27 | #define POSEIDON_STATE_FM (0x0002) | ||
28 | #define POSEIDON_STATE_DVBT (0x0004) | ||
29 | #define POSEIDON_STATE_VBI (0x0008) | ||
30 | #define POSEIDON_STATE_DISCONNECT (0x0080) | ||
31 | |||
32 | #define PM_SUSPEND_DELAY 3 | ||
33 | |||
34 | #define V4L_PAL_VBI_LINES 18 | ||
35 | #define V4L_NTSC_VBI_LINES 12 | ||
36 | #define V4L_PAL_VBI_FRAMESIZE (V4L_PAL_VBI_LINES * 1440 * 2) | ||
37 | #define V4L_NTSC_VBI_FRAMESIZE (V4L_NTSC_VBI_LINES * 1440 * 2) | ||
38 | |||
39 | #define TUNER_FREQ_MIN (45000000) | ||
40 | #define TUNER_FREQ_MAX (862000000) | ||
41 | |||
42 | struct vbi_data { | ||
43 | struct video_device *v_dev; | ||
44 | struct video_data *video; | ||
45 | struct front_face *front; | ||
46 | |||
47 | unsigned int copied; | ||
48 | unsigned int vbi_size; /* the whole size of two fields */ | ||
49 | int users; | ||
50 | }; | ||
51 | |||
52 | /* | ||
53 | * This is the running context of the video, it is useful for | ||
54 | * resume() | ||
55 | */ | ||
56 | struct running_context { | ||
57 | u32 freq; /* VIDIOC_S_FREQUENCY */ | ||
58 | int audio_idx; /* VIDIOC_S_TUNER */ | ||
59 | v4l2_std_id tvnormid; /* VIDIOC_S_STD */ | ||
60 | int sig_index; /* VIDIOC_S_INPUT */ | ||
61 | struct v4l2_pix_format pix; /* VIDIOC_S_FMT */ | ||
62 | }; | ||
63 | |||
64 | struct video_data { | ||
65 | /* v4l2 video device */ | ||
66 | struct video_device *v_dev; | ||
67 | |||
68 | /* the working context */ | ||
69 | struct running_context context; | ||
70 | |||
71 | /* for data copy */ | ||
72 | int field_count; | ||
73 | |||
74 | char *dst; | ||
75 | int lines_copied; | ||
76 | int prev_left; | ||
77 | |||
78 | int lines_per_field; | ||
79 | int lines_size; | ||
80 | |||
81 | /* for communication */ | ||
82 | u8 endpoint_addr; | ||
83 | struct urb *urb_array[SBUF_NUM]; | ||
84 | struct vbi_data *vbi; | ||
85 | struct poseidon *pd; | ||
86 | struct front_face *front; | ||
87 | |||
88 | int is_streaming; | ||
89 | int users; | ||
90 | |||
91 | /* for bubble handler */ | ||
92 | struct work_struct bubble_work; | ||
93 | }; | ||
94 | |||
95 | enum pcm_stream_state { | ||
96 | STREAM_OFF, | ||
97 | STREAM_ON, | ||
98 | STREAM_SUSPEND, | ||
99 | }; | ||
100 | |||
101 | #define AUDIO_BUFS (3) | ||
102 | #define CAPTURE_STREAM_EN 1 | ||
103 | struct poseidon_audio { | ||
104 | struct urb *urb_array[AUDIO_BUFS]; | ||
105 | unsigned int copied_position; | ||
106 | struct snd_pcm_substream *capture_pcm_substream; | ||
107 | |||
108 | unsigned int rcv_position; | ||
109 | struct snd_card *card; | ||
110 | int card_close; | ||
111 | |||
112 | int users; | ||
113 | int pm_state; | ||
114 | enum pcm_stream_state capture_stream; | ||
115 | }; | ||
116 | |||
117 | struct radio_data { | ||
118 | __u32 fm_freq; | ||
119 | int users; | ||
120 | unsigned int is_radio_streaming; | ||
121 | int pre_emphasis; | ||
122 | struct video_device *fm_dev; | ||
123 | }; | ||
124 | |||
125 | #define DVB_SBUF_NUM 4 | ||
126 | #define DVB_URB_BUF_SIZE 0x2000 | ||
127 | struct pd_dvb_adapter { | ||
128 | struct dvb_adapter dvb_adap; | ||
129 | struct dvb_frontend dvb_fe; | ||
130 | struct dmxdev dmxdev; | ||
131 | struct dvb_demux demux; | ||
132 | |||
133 | atomic_t users; | ||
134 | atomic_t active_feed; | ||
135 | |||
136 | /* data transfer */ | ||
137 | s32 is_streaming; | ||
138 | struct urb *urb_array[DVB_SBUF_NUM]; | ||
139 | struct poseidon *pd_device; | ||
140 | u8 ep_addr; | ||
141 | u8 reserved[3]; | ||
142 | |||
143 | /* data for power resume*/ | ||
144 | struct dvb_frontend_parameters fe_param; | ||
145 | |||
146 | /* for channel scanning */ | ||
147 | int prev_freq; | ||
148 | int bandwidth; | ||
149 | unsigned long last_jiffies; | ||
150 | }; | ||
151 | |||
152 | struct front_face { | ||
153 | /* use this field to distinguish VIDEO and VBI */ | ||
154 | enum v4l2_buf_type type; | ||
155 | |||
156 | /* for host */ | ||
157 | struct videobuf_queue q; | ||
158 | |||
159 | /* the bridge for host and device */ | ||
160 | struct videobuf_buffer *curr_frame; | ||
161 | |||
162 | /* for device */ | ||
163 | spinlock_t queue_lock; | ||
164 | struct list_head active; | ||
165 | struct poseidon *pd; | ||
166 | }; | ||
167 | |||
168 | struct poseidon { | ||
169 | struct list_head device_list; | ||
170 | |||
171 | struct mutex lock; | ||
172 | struct kref kref; | ||
173 | |||
174 | /* for V4L2 */ | ||
175 | struct v4l2_device v4l2_dev; | ||
176 | |||
177 | /* hardware info */ | ||
178 | struct usb_device *udev; | ||
179 | struct usb_interface *interface; | ||
180 | int cur_transfer_mode; | ||
181 | |||
182 | struct video_data video_data; /* video */ | ||
183 | struct vbi_data vbi_data; /* vbi */ | ||
184 | struct poseidon_audio audio; /* audio (alsa) */ | ||
185 | struct radio_data radio_data; /* FM */ | ||
186 | struct pd_dvb_adapter dvb_data; /* DVB */ | ||
187 | |||
188 | u32 state; | ||
189 | struct file *file_for_stream; /* the active stream*/ | ||
190 | |||
191 | #ifdef CONFIG_PM | ||
192 | int (*pm_suspend)(struct poseidon *); | ||
193 | int (*pm_resume)(struct poseidon *); | ||
194 | pm_message_t msg; | ||
195 | |||
196 | struct work_struct pm_work; | ||
197 | u8 portnum; | ||
198 | #endif | ||
199 | }; | ||
200 | |||
201 | struct poseidon_format { | ||
202 | char *name; | ||
203 | int fourcc; /* video4linux 2 */ | ||
204 | int depth; /* bit/pixel */ | ||
205 | int flags; | ||
206 | }; | ||
207 | |||
208 | struct poseidon_tvnorm { | ||
209 | v4l2_std_id v4l2_id; | ||
210 | char name[12]; | ||
211 | u32 tlg_tvnorm; | ||
212 | }; | ||
213 | |||
214 | /* video */ | ||
215 | int pd_video_init(struct poseidon *); | ||
216 | void pd_video_exit(struct poseidon *); | ||
217 | int stop_all_video_stream(struct poseidon *); | ||
218 | |||
219 | /* alsa audio */ | ||
220 | int poseidon_audio_init(struct poseidon *); | ||
221 | int poseidon_audio_free(struct poseidon *); | ||
222 | #ifdef CONFIG_PM | ||
223 | int pm_alsa_suspend(struct poseidon *); | ||
224 | int pm_alsa_resume(struct poseidon *); | ||
225 | #endif | ||
226 | |||
227 | /* dvb */ | ||
228 | int pd_dvb_usb_device_init(struct poseidon *); | ||
229 | void pd_dvb_usb_device_exit(struct poseidon *); | ||
230 | void pd_dvb_usb_device_cleanup(struct poseidon *); | ||
231 | int pd_dvb_get_adapter_num(struct pd_dvb_adapter *); | ||
232 | void dvb_stop_streaming(struct pd_dvb_adapter *); | ||
233 | |||
234 | /* FM */ | ||
235 | int poseidon_fm_init(struct poseidon *); | ||
236 | int poseidon_fm_exit(struct poseidon *); | ||
237 | struct video_device *vdev_init(struct poseidon *, struct video_device *); | ||
238 | |||
239 | /* vendor command ops */ | ||
240 | int send_set_req(struct poseidon*, u8, s32, s32*); | ||
241 | int send_get_req(struct poseidon*, u8, s32, void*, s32*, s32); | ||
242 | s32 set_tuner_mode(struct poseidon*, unsigned char); | ||
243 | |||
244 | /* bulk urb alloc/free */ | ||
245 | int alloc_bulk_urbs_generic(struct urb **urb_array, int num, | ||
246 | struct usb_device *udev, u8 ep_addr, | ||
247 | int buf_size, gfp_t gfp_flags, | ||
248 | usb_complete_t complete_fn, void *context); | ||
249 | void free_all_urb_generic(struct urb **urb_array, int num); | ||
250 | |||
251 | /* misc */ | ||
252 | void poseidon_delete(struct kref *kref); | ||
253 | void destroy_video_device(struct video_device **v_dev); | ||
254 | extern int debug_mode; | ||
255 | void set_debug_mode(struct video_device *vfd, int debug_mode); | ||
256 | |||
257 | #ifdef CONFIG_PM | ||
258 | #define in_hibernation(pd) (pd->msg.event == PM_EVENT_FREEZE) | ||
259 | #else | ||
260 | #define in_hibernation(pd) (0) | ||
261 | #endif | ||
262 | #define get_pm_count(p) (atomic_read(&(p)->interface->pm_usage_cnt)) | ||
263 | |||
264 | #define log(a, ...) printk(KERN_DEBUG "\t[ %s : %.3d ] "a"\n", \ | ||
265 | __func__, __LINE__, ## __VA_ARGS__) | ||
266 | |||
267 | /* for power management */ | ||
268 | #define logpm(pd) do {\ | ||
269 | if (debug_mode & 0x10)\ | ||
270 | log();\ | ||
271 | } while (0) | ||
272 | |||
273 | #define logs(f) do { \ | ||
274 | if ((debug_mode & 0x4) && \ | ||
275 | (f)->type == V4L2_BUF_TYPE_VBI_CAPTURE) \ | ||
276 | log("type : VBI");\ | ||
277 | \ | ||
278 | if ((debug_mode & 0x8) && \ | ||
279 | (f)->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) \ | ||
280 | log("type : VIDEO");\ | ||
281 | } while (0) | ||
282 | #endif | ||
diff --git a/drivers/media/video/tlg2300/pd-dvb.c b/drivers/media/video/tlg2300/pd-dvb.c new file mode 100644 index 000000000000..4133aee568bf --- /dev/null +++ b/drivers/media/video/tlg2300/pd-dvb.c | |||
@@ -0,0 +1,593 @@ | |||
1 | #include "pd-common.h" | ||
2 | #include <linux/kernel.h> | ||
3 | #include <linux/usb.h> | ||
4 | #include <linux/dvb/dmx.h> | ||
5 | #include <linux/delay.h> | ||
6 | |||
7 | #include "vendorcmds.h" | ||
8 | #include <linux/sched.h> | ||
9 | #include <asm/atomic.h> | ||
10 | |||
11 | static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb); | ||
12 | |||
13 | static int dvb_bandwidth[][2] = { | ||
14 | { TLG_BW_8, BANDWIDTH_8_MHZ }, | ||
15 | { TLG_BW_7, BANDWIDTH_7_MHZ }, | ||
16 | { TLG_BW_6, BANDWIDTH_6_MHZ } | ||
17 | }; | ||
18 | static int dvb_bandwidth_length = ARRAY_SIZE(dvb_bandwidth); | ||
19 | |||
20 | static s32 dvb_start_streaming(struct pd_dvb_adapter *pd_dvb); | ||
21 | static int poseidon_check_mode_dvbt(struct poseidon *pd) | ||
22 | { | ||
23 | s32 ret = 0, cmd_status = 0; | ||
24 | |||
25 | set_current_state(TASK_INTERRUPTIBLE); | ||
26 | schedule_timeout(HZ/4); | ||
27 | |||
28 | ret = usb_set_interface(pd->udev, 0, BULK_ALTERNATE_IFACE); | ||
29 | if (ret != 0) | ||
30 | return ret; | ||
31 | |||
32 | ret = set_tuner_mode(pd, TLG_MODE_CAPS_DVB_T); | ||
33 | if (ret) | ||
34 | return ret; | ||
35 | |||
36 | /* signal source */ | ||
37 | ret = send_set_req(pd, SGNL_SRC_SEL, TLG_SIG_SRC_ANTENNA, &cmd_status); | ||
38 | if (ret|cmd_status) | ||
39 | return ret; | ||
40 | |||
41 | return 0; | ||
42 | } | ||
43 | |||
44 | /* acquire : | ||
45 | * 1 == open | ||
46 | * 0 == release | ||
47 | */ | ||
48 | static int poseidon_ts_bus_ctrl(struct dvb_frontend *fe, int acquire) | ||
49 | { | ||
50 | struct poseidon *pd = fe->demodulator_priv; | ||
51 | struct pd_dvb_adapter *pd_dvb; | ||
52 | int ret = 0; | ||
53 | |||
54 | if (!pd) | ||
55 | return -ENODEV; | ||
56 | |||
57 | pd_dvb = container_of(fe, struct pd_dvb_adapter, dvb_fe); | ||
58 | if (acquire) { | ||
59 | mutex_lock(&pd->lock); | ||
60 | if (pd->state & POSEIDON_STATE_DISCONNECT) { | ||
61 | ret = -ENODEV; | ||
62 | goto open_out; | ||
63 | } | ||
64 | |||
65 | if (pd->state && !(pd->state & POSEIDON_STATE_DVBT)) { | ||
66 | ret = -EBUSY; | ||
67 | goto open_out; | ||
68 | } | ||
69 | |||
70 | usb_autopm_get_interface(pd->interface); | ||
71 | if (0 == pd->state) { | ||
72 | ret = poseidon_check_mode_dvbt(pd); | ||
73 | if (ret < 0) { | ||
74 | usb_autopm_put_interface(pd->interface); | ||
75 | goto open_out; | ||
76 | } | ||
77 | pd->state |= POSEIDON_STATE_DVBT; | ||
78 | pd_dvb->bandwidth = 0; | ||
79 | pd_dvb->prev_freq = 0; | ||
80 | } | ||
81 | atomic_inc(&pd_dvb->users); | ||
82 | kref_get(&pd->kref); | ||
83 | open_out: | ||
84 | mutex_unlock(&pd->lock); | ||
85 | } else { | ||
86 | dvb_stop_streaming(pd_dvb); | ||
87 | |||
88 | if (atomic_dec_and_test(&pd_dvb->users)) { | ||
89 | mutex_lock(&pd->lock); | ||
90 | pd->state &= ~POSEIDON_STATE_DVBT; | ||
91 | mutex_unlock(&pd->lock); | ||
92 | } | ||
93 | kref_put(&pd->kref, poseidon_delete); | ||
94 | usb_autopm_put_interface(pd->interface); | ||
95 | } | ||
96 | return ret; | ||
97 | } | ||
98 | |||
99 | static void poseidon_fe_release(struct dvb_frontend *fe) | ||
100 | { | ||
101 | struct poseidon *pd = fe->demodulator_priv; | ||
102 | |||
103 | #ifdef CONFIG_PM | ||
104 | pd->pm_suspend = NULL; | ||
105 | pd->pm_resume = NULL; | ||
106 | #endif | ||
107 | } | ||
108 | |||
109 | static s32 poseidon_fe_sleep(struct dvb_frontend *fe) | ||
110 | { | ||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | /* | ||
115 | * return true if we can satisfy the conditions, else return false. | ||
116 | */ | ||
117 | static bool check_scan_ok(__u32 freq, int bandwidth, | ||
118 | struct pd_dvb_adapter *adapter) | ||
119 | { | ||
120 | if (bandwidth < 0) | ||
121 | return false; | ||
122 | |||
123 | if (adapter->prev_freq == freq | ||
124 | && adapter->bandwidth == bandwidth) { | ||
125 | long nl = jiffies - adapter->last_jiffies; | ||
126 | unsigned int msec ; | ||
127 | |||
128 | msec = jiffies_to_msecs(abs(nl)); | ||
129 | return msec > 15000 ? true : false; | ||
130 | } | ||
131 | return true; | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * Check if the firmware delays too long for an invalid frequency. | ||
136 | */ | ||
137 | static int fw_delay_overflow(struct pd_dvb_adapter *adapter) | ||
138 | { | ||
139 | long nl = jiffies - adapter->last_jiffies; | ||
140 | unsigned int msec ; | ||
141 | |||
142 | msec = jiffies_to_msecs(abs(nl)); | ||
143 | return msec > 800 ? true : false; | ||
144 | } | ||
145 | |||
146 | static int poseidon_set_fe(struct dvb_frontend *fe, | ||
147 | struct dvb_frontend_parameters *fep) | ||
148 | { | ||
149 | s32 ret = 0, cmd_status = 0; | ||
150 | s32 i, bandwidth = -1; | ||
151 | struct poseidon *pd = fe->demodulator_priv; | ||
152 | struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; | ||
153 | |||
154 | if (in_hibernation(pd)) | ||
155 | return -EBUSY; | ||
156 | |||
157 | mutex_lock(&pd->lock); | ||
158 | for (i = 0; i < dvb_bandwidth_length; i++) | ||
159 | if (fep->u.ofdm.bandwidth == dvb_bandwidth[i][1]) | ||
160 | bandwidth = dvb_bandwidth[i][0]; | ||
161 | |||
162 | if (check_scan_ok(fep->frequency, bandwidth, pd_dvb)) { | ||
163 | ret = send_set_req(pd, TUNE_FREQ_SELECT, | ||
164 | fep->frequency / 1000, &cmd_status); | ||
165 | if (ret | cmd_status) { | ||
166 | log("error line"); | ||
167 | goto front_out; | ||
168 | } | ||
169 | |||
170 | ret = send_set_req(pd, DVBT_BANDW_SEL, | ||
171 | bandwidth, &cmd_status); | ||
172 | if (ret | cmd_status) { | ||
173 | log("error line"); | ||
174 | goto front_out; | ||
175 | } | ||
176 | |||
177 | ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status); | ||
178 | if (ret | cmd_status) { | ||
179 | log("error line"); | ||
180 | goto front_out; | ||
181 | } | ||
182 | |||
183 | /* save the context for future */ | ||
184 | memcpy(&pd_dvb->fe_param, fep, sizeof(*fep)); | ||
185 | pd_dvb->bandwidth = bandwidth; | ||
186 | pd_dvb->prev_freq = fep->frequency; | ||
187 | pd_dvb->last_jiffies = jiffies; | ||
188 | } | ||
189 | front_out: | ||
190 | mutex_unlock(&pd->lock); | ||
191 | return ret; | ||
192 | } | ||
193 | |||
194 | #ifdef CONFIG_PM | ||
195 | static int pm_dvb_suspend(struct poseidon *pd) | ||
196 | { | ||
197 | struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; | ||
198 | dvb_stop_streaming(pd_dvb); | ||
199 | dvb_urb_cleanup(pd_dvb); | ||
200 | msleep(500); | ||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static int pm_dvb_resume(struct poseidon *pd) | ||
205 | { | ||
206 | struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; | ||
207 | |||
208 | poseidon_check_mode_dvbt(pd); | ||
209 | msleep(300); | ||
210 | poseidon_set_fe(&pd_dvb->dvb_fe, &pd_dvb->fe_param); | ||
211 | |||
212 | dvb_start_streaming(pd_dvb); | ||
213 | return 0; | ||
214 | } | ||
215 | #endif | ||
216 | |||
217 | static s32 poseidon_fe_init(struct dvb_frontend *fe) | ||
218 | { | ||
219 | struct poseidon *pd = fe->demodulator_priv; | ||
220 | struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; | ||
221 | |||
222 | #ifdef CONFIG_PM | ||
223 | pd->pm_suspend = pm_dvb_suspend; | ||
224 | pd->pm_resume = pm_dvb_resume; | ||
225 | #endif | ||
226 | memset(&pd_dvb->fe_param, 0, | ||
227 | sizeof(struct dvb_frontend_parameters)); | ||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static int poseidon_get_fe(struct dvb_frontend *fe, | ||
232 | struct dvb_frontend_parameters *fep) | ||
233 | { | ||
234 | struct poseidon *pd = fe->demodulator_priv; | ||
235 | struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; | ||
236 | |||
237 | memcpy(fep, &pd_dvb->fe_param, sizeof(*fep)); | ||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | static int poseidon_fe_get_tune_settings(struct dvb_frontend *fe, | ||
242 | struct dvb_frontend_tune_settings *tune) | ||
243 | { | ||
244 | tune->min_delay_ms = 1000; | ||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | static int poseidon_read_status(struct dvb_frontend *fe, fe_status_t *stat) | ||
249 | { | ||
250 | struct poseidon *pd = fe->demodulator_priv; | ||
251 | s32 ret = -1, cmd_status; | ||
252 | struct tuner_dtv_sig_stat_s status = {}; | ||
253 | |||
254 | if (in_hibernation(pd)) | ||
255 | return -EBUSY; | ||
256 | mutex_lock(&pd->lock); | ||
257 | |||
258 | ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_DVB_T, | ||
259 | &status, &cmd_status, sizeof(status)); | ||
260 | if (ret | cmd_status) { | ||
261 | log("get tuner status error"); | ||
262 | goto out; | ||
263 | } | ||
264 | |||
265 | if (debug_mode) | ||
266 | log("P : %d, L %d, LB :%d", status.sig_present, | ||
267 | status.sig_locked, status.sig_lock_busy); | ||
268 | |||
269 | if (status.sig_lock_busy) { | ||
270 | goto out; | ||
271 | } else if (status.sig_present || status.sig_locked) { | ||
272 | *stat |= FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER | ||
273 | | FE_HAS_SYNC | FE_HAS_VITERBI; | ||
274 | } else { | ||
275 | if (fw_delay_overflow(&pd->dvb_data)) | ||
276 | *stat |= FE_TIMEDOUT; | ||
277 | } | ||
278 | out: | ||
279 | mutex_unlock(&pd->lock); | ||
280 | return ret; | ||
281 | } | ||
282 | |||
283 | static int poseidon_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
284 | { | ||
285 | struct poseidon *pd = fe->demodulator_priv; | ||
286 | struct tuner_ber_rate_s tlg_ber = {}; | ||
287 | s32 ret = -1, cmd_status; | ||
288 | |||
289 | mutex_lock(&pd->lock); | ||
290 | ret = send_get_req(pd, TUNER_BER_RATE, 0, | ||
291 | &tlg_ber, &cmd_status, sizeof(tlg_ber)); | ||
292 | if (ret | cmd_status) | ||
293 | goto out; | ||
294 | *ber = tlg_ber.ber_rate; | ||
295 | out: | ||
296 | mutex_unlock(&pd->lock); | ||
297 | return ret; | ||
298 | } | ||
299 | |||
300 | static s32 poseidon_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | ||
301 | { | ||
302 | struct poseidon *pd = fe->demodulator_priv; | ||
303 | struct tuner_dtv_sig_stat_s status = {}; | ||
304 | s32 ret = 0, cmd_status; | ||
305 | |||
306 | mutex_lock(&pd->lock); | ||
307 | ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_DVB_T, | ||
308 | &status, &cmd_status, sizeof(status)); | ||
309 | if (ret | cmd_status) | ||
310 | goto out; | ||
311 | if ((status.sig_present || status.sig_locked) && !status.sig_strength) | ||
312 | *strength = 0xFFFF; | ||
313 | else | ||
314 | *strength = status.sig_strength; | ||
315 | out: | ||
316 | mutex_unlock(&pd->lock); | ||
317 | return ret; | ||
318 | } | ||
319 | |||
320 | static int poseidon_read_snr(struct dvb_frontend *fe, u16 *snr) | ||
321 | { | ||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static int poseidon_read_unc_blocks(struct dvb_frontend *fe, u32 *unc) | ||
326 | { | ||
327 | *unc = 0; | ||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static struct dvb_frontend_ops poseidon_frontend_ops = { | ||
332 | .info = { | ||
333 | .name = "Poseidon DVB-T", | ||
334 | .type = FE_OFDM, | ||
335 | .frequency_min = 174000000, | ||
336 | .frequency_max = 862000000, | ||
337 | .frequency_stepsize = 62500,/* FIXME */ | ||
338 | .caps = FE_CAN_INVERSION_AUTO | | ||
339 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
340 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
341 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | | ||
342 | FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
343 | FE_CAN_GUARD_INTERVAL_AUTO | | ||
344 | FE_CAN_RECOVER | | ||
345 | FE_CAN_HIERARCHY_AUTO, | ||
346 | }, | ||
347 | |||
348 | .release = poseidon_fe_release, | ||
349 | |||
350 | .init = poseidon_fe_init, | ||
351 | .sleep = poseidon_fe_sleep, | ||
352 | |||
353 | .set_frontend = poseidon_set_fe, | ||
354 | .get_frontend = poseidon_get_fe, | ||
355 | .get_tune_settings = poseidon_fe_get_tune_settings, | ||
356 | |||
357 | .read_status = poseidon_read_status, | ||
358 | .read_ber = poseidon_read_ber, | ||
359 | .read_signal_strength = poseidon_read_signal_strength, | ||
360 | .read_snr = poseidon_read_snr, | ||
361 | .read_ucblocks = poseidon_read_unc_blocks, | ||
362 | |||
363 | .ts_bus_ctrl = poseidon_ts_bus_ctrl, | ||
364 | }; | ||
365 | |||
366 | static void dvb_urb_irq(struct urb *urb) | ||
367 | { | ||
368 | struct pd_dvb_adapter *pd_dvb = urb->context; | ||
369 | int len = urb->transfer_buffer_length; | ||
370 | struct dvb_demux *demux = &pd_dvb->demux; | ||
371 | s32 ret; | ||
372 | |||
373 | if (!pd_dvb->is_streaming || urb->status) { | ||
374 | if (urb->status == -EPROTO) | ||
375 | goto resend; | ||
376 | return; | ||
377 | } | ||
378 | |||
379 | if (urb->actual_length == len) | ||
380 | dvb_dmx_swfilter(demux, urb->transfer_buffer, len); | ||
381 | else if (urb->actual_length == len - 4) { | ||
382 | int offset; | ||
383 | u8 *buf = urb->transfer_buffer; | ||
384 | |||
385 | /* | ||
386 | * The packet size is 512, | ||
387 | * last packet contains 456 bytes tsp data | ||
388 | */ | ||
389 | for (offset = 456; offset < len; offset += 512) { | ||
390 | if (!strncmp(buf + offset, "DVHS", 4)) { | ||
391 | dvb_dmx_swfilter(demux, buf, offset); | ||
392 | if (len > offset + 52 + 4) { | ||
393 | /*16 bytes trailer + 36 bytes padding */ | ||
394 | buf += offset + 52; | ||
395 | len -= offset + 52 + 4; | ||
396 | dvb_dmx_swfilter(demux, buf, len); | ||
397 | } | ||
398 | break; | ||
399 | } | ||
400 | } | ||
401 | } | ||
402 | |||
403 | resend: | ||
404 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
405 | if (ret) | ||
406 | log(" usb_submit_urb failed: error %d", ret); | ||
407 | } | ||
408 | |||
409 | static int dvb_urb_init(struct pd_dvb_adapter *pd_dvb) | ||
410 | { | ||
411 | if (pd_dvb->urb_array[0]) | ||
412 | return 0; | ||
413 | |||
414 | alloc_bulk_urbs_generic(pd_dvb->urb_array, DVB_SBUF_NUM, | ||
415 | pd_dvb->pd_device->udev, pd_dvb->ep_addr, | ||
416 | DVB_URB_BUF_SIZE, GFP_KERNEL, | ||
417 | dvb_urb_irq, pd_dvb); | ||
418 | return 0; | ||
419 | } | ||
420 | |||
421 | static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb) | ||
422 | { | ||
423 | free_all_urb_generic(pd_dvb->urb_array, DVB_SBUF_NUM); | ||
424 | } | ||
425 | |||
426 | static s32 dvb_start_streaming(struct pd_dvb_adapter *pd_dvb) | ||
427 | { | ||
428 | struct poseidon *pd = pd_dvb->pd_device; | ||
429 | int ret = 0; | ||
430 | |||
431 | if (pd->state & POSEIDON_STATE_DISCONNECT) | ||
432 | return -ENODEV; | ||
433 | |||
434 | mutex_lock(&pd->lock); | ||
435 | if (!pd_dvb->is_streaming) { | ||
436 | s32 i, cmd_status = 0; | ||
437 | /* | ||
438 | * Once upon a time, there was a difficult bug lying here. | ||
439 | * ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status); | ||
440 | */ | ||
441 | |||
442 | ret = send_set_req(pd, PLAY_SERVICE, 1, &cmd_status); | ||
443 | if (ret | cmd_status) | ||
444 | goto out; | ||
445 | |||
446 | ret = dvb_urb_init(pd_dvb); | ||
447 | if (ret < 0) | ||
448 | goto out; | ||
449 | |||
450 | pd_dvb->is_streaming = 1; | ||
451 | for (i = 0; i < DVB_SBUF_NUM; i++) { | ||
452 | ret = usb_submit_urb(pd_dvb->urb_array[i], | ||
453 | GFP_KERNEL); | ||
454 | if (ret) { | ||
455 | log(" submit urb error %d", ret); | ||
456 | goto out; | ||
457 | } | ||
458 | } | ||
459 | } | ||
460 | out: | ||
461 | mutex_unlock(&pd->lock); | ||
462 | return ret; | ||
463 | } | ||
464 | |||
465 | void dvb_stop_streaming(struct pd_dvb_adapter *pd_dvb) | ||
466 | { | ||
467 | struct poseidon *pd = pd_dvb->pd_device; | ||
468 | |||
469 | mutex_lock(&pd->lock); | ||
470 | if (pd_dvb->is_streaming) { | ||
471 | s32 i, ret, cmd_status = 0; | ||
472 | |||
473 | pd_dvb->is_streaming = 0; | ||
474 | |||
475 | for (i = 0; i < DVB_SBUF_NUM; i++) | ||
476 | if (pd_dvb->urb_array[i]) | ||
477 | usb_kill_urb(pd_dvb->urb_array[i]); | ||
478 | |||
479 | ret = send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP, | ||
480 | &cmd_status); | ||
481 | if (ret | cmd_status) | ||
482 | log("error"); | ||
483 | } | ||
484 | mutex_unlock(&pd->lock); | ||
485 | } | ||
486 | |||
487 | static int pd_start_feed(struct dvb_demux_feed *feed) | ||
488 | { | ||
489 | struct pd_dvb_adapter *pd_dvb = feed->demux->priv; | ||
490 | int ret = 0; | ||
491 | |||
492 | if (!pd_dvb) | ||
493 | return -1; | ||
494 | if (atomic_inc_return(&pd_dvb->active_feed) == 1) | ||
495 | ret = dvb_start_streaming(pd_dvb); | ||
496 | return ret; | ||
497 | } | ||
498 | |||
499 | static int pd_stop_feed(struct dvb_demux_feed *feed) | ||
500 | { | ||
501 | struct pd_dvb_adapter *pd_dvb = feed->demux->priv; | ||
502 | |||
503 | if (!pd_dvb) | ||
504 | return -1; | ||
505 | if (atomic_dec_and_test(&pd_dvb->active_feed)) | ||
506 | dvb_stop_streaming(pd_dvb); | ||
507 | return 0; | ||
508 | } | ||
509 | |||
510 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
511 | int pd_dvb_usb_device_init(struct poseidon *pd) | ||
512 | { | ||
513 | struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; | ||
514 | struct dvb_demux *dvbdemux; | ||
515 | int ret = 0; | ||
516 | |||
517 | pd_dvb->ep_addr = 0x82; | ||
518 | atomic_set(&pd_dvb->users, 0); | ||
519 | atomic_set(&pd_dvb->active_feed, 0); | ||
520 | pd_dvb->pd_device = pd; | ||
521 | |||
522 | ret = dvb_register_adapter(&pd_dvb->dvb_adap, | ||
523 | "Poseidon dvbt adapter", | ||
524 | THIS_MODULE, | ||
525 | NULL /* for hibernation correctly*/, | ||
526 | adapter_nr); | ||
527 | if (ret < 0) | ||
528 | goto error1; | ||
529 | |||
530 | /* register frontend */ | ||
531 | pd_dvb->dvb_fe.demodulator_priv = pd; | ||
532 | memcpy(&pd_dvb->dvb_fe.ops, &poseidon_frontend_ops, | ||
533 | sizeof(struct dvb_frontend_ops)); | ||
534 | ret = dvb_register_frontend(&pd_dvb->dvb_adap, &pd_dvb->dvb_fe); | ||
535 | if (ret < 0) | ||
536 | goto error2; | ||
537 | |||
538 | /* register demux device */ | ||
539 | dvbdemux = &pd_dvb->demux; | ||
540 | dvbdemux->dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING; | ||
541 | dvbdemux->priv = pd_dvb; | ||
542 | dvbdemux->feednum = dvbdemux->filternum = 64; | ||
543 | dvbdemux->start_feed = pd_start_feed; | ||
544 | dvbdemux->stop_feed = pd_stop_feed; | ||
545 | dvbdemux->write_to_decoder = NULL; | ||
546 | |||
547 | ret = dvb_dmx_init(dvbdemux); | ||
548 | if (ret < 0) | ||
549 | goto error3; | ||
550 | |||
551 | pd_dvb->dmxdev.filternum = pd_dvb->demux.filternum; | ||
552 | pd_dvb->dmxdev.demux = &pd_dvb->demux.dmx; | ||
553 | pd_dvb->dmxdev.capabilities = 0; | ||
554 | |||
555 | ret = dvb_dmxdev_init(&pd_dvb->dmxdev, &pd_dvb->dvb_adap); | ||
556 | if (ret < 0) | ||
557 | goto error3; | ||
558 | return 0; | ||
559 | |||
560 | error3: | ||
561 | dvb_unregister_frontend(&pd_dvb->dvb_fe); | ||
562 | error2: | ||
563 | dvb_unregister_adapter(&pd_dvb->dvb_adap); | ||
564 | error1: | ||
565 | return ret; | ||
566 | } | ||
567 | |||
568 | void pd_dvb_usb_device_exit(struct poseidon *pd) | ||
569 | { | ||
570 | struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; | ||
571 | |||
572 | while (atomic_read(&pd_dvb->users) != 0 | ||
573 | || atomic_read(&pd_dvb->active_feed) != 0) { | ||
574 | set_current_state(TASK_INTERRUPTIBLE); | ||
575 | schedule_timeout(HZ); | ||
576 | } | ||
577 | dvb_dmxdev_release(&pd_dvb->dmxdev); | ||
578 | dvb_unregister_frontend(&pd_dvb->dvb_fe); | ||
579 | dvb_unregister_adapter(&pd_dvb->dvb_adap); | ||
580 | pd_dvb_usb_device_cleanup(pd); | ||
581 | } | ||
582 | |||
583 | void pd_dvb_usb_device_cleanup(struct poseidon *pd) | ||
584 | { | ||
585 | struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; | ||
586 | |||
587 | dvb_urb_cleanup(pd_dvb); | ||
588 | } | ||
589 | |||
590 | int pd_dvb_get_adapter_num(struct pd_dvb_adapter *pd_dvb) | ||
591 | { | ||
592 | return pd_dvb->dvb_adap.num; | ||
593 | } | ||
diff --git a/drivers/media/video/tlg2300/pd-main.c b/drivers/media/video/tlg2300/pd-main.c new file mode 100644 index 000000000000..2cf0ebf9f28b --- /dev/null +++ b/drivers/media/video/tlg2300/pd-main.c | |||
@@ -0,0 +1,539 @@ | |||
1 | /* | ||
2 | * device driver for Telegent tlg2300 based TV cards | ||
3 | * | ||
4 | * Author : | ||
5 | * Kang Yong <kangyong@telegent.com> | ||
6 | * Zhang Xiaobing <xbzhang@telegent.com> | ||
7 | * Huang Shijie <zyziii@telegent.com> or <shijie8@gmail.com> | ||
8 | * | ||
9 | * (c) 2009 Telegent Systems | ||
10 | * (c) 2010 Telegent Systems | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #include <linux/version.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/errno.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/kref.h> | ||
34 | #include <linux/suspend.h> | ||
35 | #include <linux/usb/quirks.h> | ||
36 | #include <linux/ctype.h> | ||
37 | #include <linux/string.h> | ||
38 | #include <linux/types.h> | ||
39 | #include <linux/firmware.h> | ||
40 | #include <linux/smp_lock.h> | ||
41 | |||
42 | #include "vendorcmds.h" | ||
43 | #include "pd-common.h" | ||
44 | |||
45 | #define VENDOR_ID 0x1B24 | ||
46 | #define PRODUCT_ID 0x4001 | ||
47 | static struct usb_device_id id_table[] = { | ||
48 | { USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID, PRODUCT_ID, 255, 1, 0) }, | ||
49 | { USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID, PRODUCT_ID, 255, 1, 1) }, | ||
50 | { }, | ||
51 | }; | ||
52 | MODULE_DEVICE_TABLE(usb, id_table); | ||
53 | |||
54 | int debug_mode; | ||
55 | module_param(debug_mode, int, 0644); | ||
56 | MODULE_PARM_DESC(debug_mode, "0 = disable, 1 = enable, 2 = verbose"); | ||
57 | |||
58 | const char *firmware_name = "tlg2300_firmware.bin"; | ||
59 | struct usb_driver poseidon_driver; | ||
60 | static LIST_HEAD(pd_device_list); | ||
61 | |||
62 | /* | ||
63 | * send set request to USB firmware. | ||
64 | */ | ||
65 | s32 send_set_req(struct poseidon *pd, u8 cmdid, s32 param, s32 *cmd_status) | ||
66 | { | ||
67 | s32 ret; | ||
68 | s8 data[32] = {}; | ||
69 | u16 lower_16, upper_16; | ||
70 | |||
71 | if (pd->state & POSEIDON_STATE_DISCONNECT) | ||
72 | return -ENODEV; | ||
73 | |||
74 | mdelay(30); | ||
75 | |||
76 | if (param == 0) { | ||
77 | upper_16 = lower_16 = 0; | ||
78 | } else { | ||
79 | /* send 32 bit param as two 16 bit param,little endian */ | ||
80 | lower_16 = (unsigned short)(param & 0xffff); | ||
81 | upper_16 = (unsigned short)((param >> 16) & 0xffff); | ||
82 | } | ||
83 | ret = usb_control_msg(pd->udev, | ||
84 | usb_rcvctrlpipe(pd->udev, 0), | ||
85 | REQ_SET_CMD | cmdid, | ||
86 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
87 | lower_16, | ||
88 | upper_16, | ||
89 | &data, | ||
90 | sizeof(*cmd_status), | ||
91 | USB_CTRL_GET_TIMEOUT); | ||
92 | |||
93 | if (!ret) { | ||
94 | return -ENXIO; | ||
95 | } else { | ||
96 | /* 1st 4 bytes into cmd_status */ | ||
97 | memcpy((char *)cmd_status, &(data[0]), sizeof(*cmd_status)); | ||
98 | } | ||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | /* | ||
103 | * send get request to Poseidon firmware. | ||
104 | */ | ||
105 | s32 send_get_req(struct poseidon *pd, u8 cmdid, s32 param, | ||
106 | void *buf, s32 *cmd_status, s32 datalen) | ||
107 | { | ||
108 | s32 ret; | ||
109 | s8 data[128] = {}; | ||
110 | u16 lower_16, upper_16; | ||
111 | |||
112 | if (pd->state & POSEIDON_STATE_DISCONNECT) | ||
113 | return -ENODEV; | ||
114 | |||
115 | mdelay(30); | ||
116 | if (param == 0) { | ||
117 | upper_16 = lower_16 = 0; | ||
118 | } else { | ||
119 | /*send 32 bit param as two 16 bit param, little endian */ | ||
120 | lower_16 = (unsigned short)(param & 0xffff); | ||
121 | upper_16 = (unsigned short)((param >> 16) & 0xffff); | ||
122 | } | ||
123 | ret = usb_control_msg(pd->udev, | ||
124 | usb_rcvctrlpipe(pd->udev, 0), | ||
125 | REQ_GET_CMD | cmdid, | ||
126 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
127 | lower_16, | ||
128 | upper_16, | ||
129 | &data, | ||
130 | (datalen + sizeof(*cmd_status)), | ||
131 | USB_CTRL_GET_TIMEOUT); | ||
132 | |||
133 | if (ret < 0) { | ||
134 | return -ENXIO; | ||
135 | } else { | ||
136 | /* 1st 4 bytes into cmd_status, remaining data into cmd_data */ | ||
137 | memcpy((char *)cmd_status, &data[0], sizeof(*cmd_status)); | ||
138 | memcpy((char *)buf, &data[sizeof(*cmd_status)], datalen); | ||
139 | } | ||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | static int pm_notifier_block(struct notifier_block *nb, | ||
144 | unsigned long event, void *dummy) | ||
145 | { | ||
146 | struct poseidon *pd = NULL; | ||
147 | struct list_head *node, *next; | ||
148 | |||
149 | switch (event) { | ||
150 | case PM_POST_HIBERNATION: | ||
151 | list_for_each_safe(node, next, &pd_device_list) { | ||
152 | struct usb_device *udev; | ||
153 | struct usb_interface *iface; | ||
154 | int rc = 0; | ||
155 | |||
156 | pd = container_of(node, struct poseidon, device_list); | ||
157 | udev = pd->udev; | ||
158 | iface = pd->interface; | ||
159 | |||
160 | /* It will cause the system to reload the firmware */ | ||
161 | rc = usb_lock_device_for_reset(udev, iface); | ||
162 | if (rc >= 0) { | ||
163 | usb_reset_device(udev); | ||
164 | usb_unlock_device(udev); | ||
165 | } | ||
166 | } | ||
167 | break; | ||
168 | default: | ||
169 | break; | ||
170 | } | ||
171 | log("event :%ld\n", event); | ||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | static struct notifier_block pm_notifer = { | ||
176 | .notifier_call = pm_notifier_block, | ||
177 | }; | ||
178 | |||
179 | int set_tuner_mode(struct poseidon *pd, unsigned char mode) | ||
180 | { | ||
181 | s32 ret, cmd_status; | ||
182 | |||
183 | if (pd->state & POSEIDON_STATE_DISCONNECT) | ||
184 | return -ENODEV; | ||
185 | |||
186 | ret = send_set_req(pd, TUNE_MODE_SELECT, mode, &cmd_status); | ||
187 | if (ret || cmd_status) | ||
188 | return -ENXIO; | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | void poseidon_delete(struct kref *kref) | ||
193 | { | ||
194 | struct poseidon *pd = container_of(kref, struct poseidon, kref); | ||
195 | |||
196 | if (!pd) | ||
197 | return; | ||
198 | list_del_init(&pd->device_list); | ||
199 | |||
200 | pd_dvb_usb_device_cleanup(pd); | ||
201 | /* clean_audio_data(&pd->audio_data);*/ | ||
202 | |||
203 | if (pd->udev) { | ||
204 | usb_put_dev(pd->udev); | ||
205 | pd->udev = NULL; | ||
206 | } | ||
207 | if (pd->interface) { | ||
208 | usb_put_intf(pd->interface); | ||
209 | pd->interface = NULL; | ||
210 | } | ||
211 | kfree(pd); | ||
212 | log(); | ||
213 | } | ||
214 | |||
215 | static int firmware_download(struct usb_device *udev) | ||
216 | { | ||
217 | int ret = 0, actual_length; | ||
218 | const struct firmware *fw = NULL; | ||
219 | void *fwbuf = NULL; | ||
220 | size_t fwlength = 0, offset; | ||
221 | size_t max_packet_size; | ||
222 | |||
223 | ret = request_firmware(&fw, firmware_name, &udev->dev); | ||
224 | if (ret) { | ||
225 | log("download err : %d", ret); | ||
226 | return ret; | ||
227 | } | ||
228 | |||
229 | fwlength = fw->size; | ||
230 | |||
231 | fwbuf = kzalloc(fwlength, GFP_KERNEL); | ||
232 | if (!fwbuf) { | ||
233 | ret = -ENOMEM; | ||
234 | goto out; | ||
235 | } | ||
236 | memcpy(fwbuf, fw->data, fwlength); | ||
237 | |||
238 | max_packet_size = udev->ep_out[0x1]->desc.wMaxPacketSize; | ||
239 | log("\t\t download size : %d", (int)max_packet_size); | ||
240 | |||
241 | for (offset = 0; offset < fwlength; offset += max_packet_size) { | ||
242 | actual_length = 0; | ||
243 | ret = usb_bulk_msg(udev, | ||
244 | usb_sndbulkpipe(udev, 0x01), /* ep 1 */ | ||
245 | fwbuf + offset, | ||
246 | min(max_packet_size, fwlength - offset), | ||
247 | &actual_length, | ||
248 | HZ * 10); | ||
249 | if (ret) | ||
250 | break; | ||
251 | } | ||
252 | kfree(fwbuf); | ||
253 | out: | ||
254 | release_firmware(fw); | ||
255 | return ret; | ||
256 | } | ||
257 | |||
258 | static inline struct poseidon *get_pd(struct usb_interface *intf) | ||
259 | { | ||
260 | return usb_get_intfdata(intf); | ||
261 | } | ||
262 | |||
263 | #ifdef CONFIG_PM | ||
264 | /* one-to-one map : poseidon{} <----> usb_device{}'s port */ | ||
265 | static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev) | ||
266 | { | ||
267 | pd->portnum = udev->portnum; | ||
268 | } | ||
269 | |||
270 | static inline int get_autopm_ref(struct poseidon *pd) | ||
271 | { | ||
272 | return pd->video_data.users + pd->vbi_data.users + pd->audio.users | ||
273 | + atomic_read(&pd->dvb_data.users) + pd->radio_data.users; | ||
274 | } | ||
275 | |||
276 | /* fixup something for poseidon */ | ||
277 | static inline struct poseidon *fixup(struct poseidon *pd) | ||
278 | { | ||
279 | int count; | ||
280 | |||
281 | /* old udev and interface have gone, so put back reference . */ | ||
282 | count = get_autopm_ref(pd); | ||
283 | log("count : %d, ref count : %d", count, get_pm_count(pd)); | ||
284 | while (count--) | ||
285 | usb_autopm_put_interface(pd->interface); | ||
286 | /*usb_autopm_set_interface(pd->interface); */ | ||
287 | |||
288 | usb_put_dev(pd->udev); | ||
289 | usb_put_intf(pd->interface); | ||
290 | log("event : %d\n", pd->msg.event); | ||
291 | return pd; | ||
292 | } | ||
293 | |||
294 | static struct poseidon *find_old_poseidon(struct usb_device *udev) | ||
295 | { | ||
296 | struct poseidon *pd; | ||
297 | |||
298 | list_for_each_entry(pd, &pd_device_list, device_list) { | ||
299 | if (pd->portnum == udev->portnum && in_hibernation(pd)) | ||
300 | return fixup(pd); | ||
301 | } | ||
302 | return NULL; | ||
303 | } | ||
304 | |||
305 | /* Is the card working now ? */ | ||
306 | static inline int is_working(struct poseidon *pd) | ||
307 | { | ||
308 | return get_pm_count(pd) > 0; | ||
309 | } | ||
310 | |||
311 | static int poseidon_suspend(struct usb_interface *intf, pm_message_t msg) | ||
312 | { | ||
313 | struct poseidon *pd = get_pd(intf); | ||
314 | |||
315 | if (!pd) | ||
316 | return 0; | ||
317 | if (!is_working(pd)) { | ||
318 | if (get_pm_count(pd) <= 0 && !in_hibernation(pd)) { | ||
319 | pd->msg.event = PM_EVENT_AUTO_SUSPEND; | ||
320 | pd->pm_resume = NULL; /* a good guard */ | ||
321 | printk(KERN_DEBUG "\n\t+ TLG2300 auto suspend +\n\n"); | ||
322 | } | ||
323 | return 0; | ||
324 | } | ||
325 | pd->msg = msg; /* save it here */ | ||
326 | logpm(pd); | ||
327 | return pd->pm_suspend ? pd->pm_suspend(pd) : 0; | ||
328 | } | ||
329 | |||
330 | static int poseidon_resume(struct usb_interface *intf) | ||
331 | { | ||
332 | struct poseidon *pd = get_pd(intf); | ||
333 | |||
334 | if (!pd) | ||
335 | return 0; | ||
336 | printk(KERN_DEBUG "\n\t ++ TLG2300 resume ++\n\n"); | ||
337 | |||
338 | if (!is_working(pd)) { | ||
339 | if (PM_EVENT_AUTO_SUSPEND == pd->msg.event) | ||
340 | pd->msg = PMSG_ON; | ||
341 | return 0; | ||
342 | } | ||
343 | if (in_hibernation(pd)) { | ||
344 | logpm(pd); | ||
345 | return 0; | ||
346 | } | ||
347 | logpm(pd); | ||
348 | return pd->pm_resume ? pd->pm_resume(pd) : 0; | ||
349 | } | ||
350 | |||
351 | static void hibernation_resume(struct work_struct *w) | ||
352 | { | ||
353 | struct poseidon *pd = container_of(w, struct poseidon, pm_work); | ||
354 | int count; | ||
355 | |||
356 | pd->msg.event = 0; /* clear it here */ | ||
357 | pd->state &= ~POSEIDON_STATE_DISCONNECT; | ||
358 | |||
359 | /* set the new interface's reference */ | ||
360 | count = get_autopm_ref(pd); | ||
361 | while (count--) | ||
362 | usb_autopm_get_interface(pd->interface); | ||
363 | |||
364 | /* resume the context */ | ||
365 | logpm(pd); | ||
366 | if (pd->pm_resume) | ||
367 | pd->pm_resume(pd); | ||
368 | } | ||
369 | #else /* CONFIG_PM is not enabled: */ | ||
370 | static inline struct poseidon *find_old_poseidon(struct usb_device *udev) | ||
371 | { | ||
372 | return NULL; | ||
373 | } | ||
374 | |||
375 | static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev) | ||
376 | { | ||
377 | } | ||
378 | #endif | ||
379 | |||
380 | static bool check_firmware(struct usb_device *udev, int *down_firmware) | ||
381 | { | ||
382 | void *buf; | ||
383 | int ret; | ||
384 | struct cmd_firmware_vers_s *cmd_firm; | ||
385 | |||
386 | buf = kzalloc(sizeof(*cmd_firm) + sizeof(u32), GFP_KERNEL); | ||
387 | if (!buf) | ||
388 | return -ENOMEM; | ||
389 | ret = usb_control_msg(udev, | ||
390 | usb_rcvctrlpipe(udev, 0), | ||
391 | REQ_GET_CMD | GET_FW_ID, | ||
392 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
393 | 0, | ||
394 | 0, | ||
395 | buf, | ||
396 | sizeof(*cmd_firm) + sizeof(u32), | ||
397 | USB_CTRL_GET_TIMEOUT); | ||
398 | kfree(buf); | ||
399 | |||
400 | if (ret < 0) { | ||
401 | *down_firmware = 1; | ||
402 | return firmware_download(udev); | ||
403 | } | ||
404 | return ret; | ||
405 | } | ||
406 | |||
407 | static int poseidon_probe(struct usb_interface *interface, | ||
408 | const struct usb_device_id *id) | ||
409 | { | ||
410 | struct usb_device *udev = interface_to_usbdev(interface); | ||
411 | struct poseidon *pd = NULL; | ||
412 | int ret = 0; | ||
413 | int new_one = 0; | ||
414 | |||
415 | /* download firmware */ | ||
416 | check_firmware(udev, &ret); | ||
417 | if (ret) | ||
418 | return 0; | ||
419 | |||
420 | /* Do I recovery from the hibernate ? */ | ||
421 | pd = find_old_poseidon(udev); | ||
422 | if (!pd) { | ||
423 | pd = kzalloc(sizeof(*pd), GFP_KERNEL); | ||
424 | if (!pd) | ||
425 | return -ENOMEM; | ||
426 | kref_init(&pd->kref); | ||
427 | set_map_flags(pd, udev); | ||
428 | new_one = 1; | ||
429 | } | ||
430 | |||
431 | pd->udev = usb_get_dev(udev); | ||
432 | pd->interface = usb_get_intf(interface); | ||
433 | usb_set_intfdata(interface, pd); | ||
434 | |||
435 | if (new_one) { | ||
436 | struct device *dev = &interface->dev; | ||
437 | |||
438 | logpm(pd); | ||
439 | mutex_init(&pd->lock); | ||
440 | |||
441 | /* register v4l2 device */ | ||
442 | snprintf(pd->v4l2_dev.name, sizeof(pd->v4l2_dev.name), "%s %s", | ||
443 | dev->driver->name, dev_name(dev)); | ||
444 | ret = v4l2_device_register(NULL, &pd->v4l2_dev); | ||
445 | |||
446 | /* register devices in directory /dev */ | ||
447 | ret = pd_video_init(pd); | ||
448 | poseidon_audio_init(pd); | ||
449 | poseidon_fm_init(pd); | ||
450 | pd_dvb_usb_device_init(pd); | ||
451 | |||
452 | INIT_LIST_HEAD(&pd->device_list); | ||
453 | list_add_tail(&pd->device_list, &pd_device_list); | ||
454 | } | ||
455 | |||
456 | device_init_wakeup(&udev->dev, 1); | ||
457 | #ifdef CONFIG_PM | ||
458 | pd->udev->autosuspend_disabled = 0; | ||
459 | pd->udev->autosuspend_delay = HZ * PM_SUSPEND_DELAY; | ||
460 | |||
461 | if (in_hibernation(pd)) { | ||
462 | INIT_WORK(&pd->pm_work, hibernation_resume); | ||
463 | schedule_work(&pd->pm_work); | ||
464 | } | ||
465 | #endif | ||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | static void poseidon_disconnect(struct usb_interface *interface) | ||
470 | { | ||
471 | struct poseidon *pd = get_pd(interface); | ||
472 | |||
473 | if (!pd) | ||
474 | return; | ||
475 | logpm(pd); | ||
476 | if (in_hibernation(pd)) | ||
477 | return; | ||
478 | |||
479 | mutex_lock(&pd->lock); | ||
480 | pd->state |= POSEIDON_STATE_DISCONNECT; | ||
481 | mutex_unlock(&pd->lock); | ||
482 | |||
483 | /* stop urb transferring */ | ||
484 | stop_all_video_stream(pd); | ||
485 | dvb_stop_streaming(&pd->dvb_data); | ||
486 | |||
487 | /*unregister v4l2 device */ | ||
488 | v4l2_device_unregister(&pd->v4l2_dev); | ||
489 | |||
490 | lock_kernel(); | ||
491 | { | ||
492 | pd_dvb_usb_device_exit(pd); | ||
493 | poseidon_fm_exit(pd); | ||
494 | |||
495 | poseidon_audio_free(pd); | ||
496 | pd_video_exit(pd); | ||
497 | } | ||
498 | unlock_kernel(); | ||
499 | |||
500 | usb_set_intfdata(interface, NULL); | ||
501 | kref_put(&pd->kref, poseidon_delete); | ||
502 | } | ||
503 | |||
504 | struct usb_driver poseidon_driver = { | ||
505 | .name = "poseidon", | ||
506 | .probe = poseidon_probe, | ||
507 | .disconnect = poseidon_disconnect, | ||
508 | .id_table = id_table, | ||
509 | #ifdef CONFIG_PM | ||
510 | .suspend = poseidon_suspend, | ||
511 | .resume = poseidon_resume, | ||
512 | #endif | ||
513 | .supports_autosuspend = 1, | ||
514 | }; | ||
515 | |||
516 | static int __init poseidon_init(void) | ||
517 | { | ||
518 | int ret; | ||
519 | |||
520 | ret = usb_register(&poseidon_driver); | ||
521 | if (ret) | ||
522 | return ret; | ||
523 | register_pm_notifier(&pm_notifer); | ||
524 | return ret; | ||
525 | } | ||
526 | |||
527 | static void __exit poseidon_exit(void) | ||
528 | { | ||
529 | log(); | ||
530 | unregister_pm_notifier(&pm_notifer); | ||
531 | usb_deregister(&poseidon_driver); | ||
532 | } | ||
533 | |||
534 | module_init(poseidon_init); | ||
535 | module_exit(poseidon_exit); | ||
536 | |||
537 | MODULE_AUTHOR("Telegent Systems"); | ||
538 | MODULE_DESCRIPTION("For tlg2300-based USB device "); | ||
539 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/tlg2300/pd-radio.c b/drivers/media/video/tlg2300/pd-radio.c new file mode 100644 index 000000000000..755766b15157 --- /dev/null +++ b/drivers/media/video/tlg2300/pd-radio.c | |||
@@ -0,0 +1,420 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <linux/list.h> | ||
3 | #include <linux/module.h> | ||
4 | #include <linux/kernel.h> | ||
5 | #include <linux/bitmap.h> | ||
6 | #include <linux/usb.h> | ||
7 | #include <linux/i2c.h> | ||
8 | #include <media/v4l2-dev.h> | ||
9 | #include <linux/version.h> | ||
10 | #include <linux/mm.h> | ||
11 | #include <linux/mutex.h> | ||
12 | #include <media/v4l2-ioctl.h> | ||
13 | #include <linux/sched.h> | ||
14 | |||
15 | #include "pd-common.h" | ||
16 | #include "vendorcmds.h" | ||
17 | |||
18 | static int set_frequency(struct poseidon *p, __u32 frequency); | ||
19 | static int poseidon_fm_close(struct file *filp); | ||
20 | static int poseidon_fm_open(struct file *filp); | ||
21 | |||
22 | #define TUNER_FREQ_MIN_FM 76000000 | ||
23 | #define TUNER_FREQ_MAX_FM 108000000 | ||
24 | |||
25 | #define MAX_PREEMPHASIS (V4L2_PREEMPHASIS_75_uS + 1) | ||
26 | static int preemphasis[MAX_PREEMPHASIS] = { | ||
27 | TLG_TUNE_ASTD_NONE, /* V4L2_PREEMPHASIS_DISABLED */ | ||
28 | TLG_TUNE_ASTD_FM_EUR, /* V4L2_PREEMPHASIS_50_uS */ | ||
29 | TLG_TUNE_ASTD_FM_US, /* V4L2_PREEMPHASIS_75_uS */ | ||
30 | }; | ||
31 | |||
32 | static int poseidon_check_mode_radio(struct poseidon *p) | ||
33 | { | ||
34 | int ret; | ||
35 | u32 status; | ||
36 | |||
37 | set_current_state(TASK_INTERRUPTIBLE); | ||
38 | schedule_timeout(HZ/2); | ||
39 | ret = usb_set_interface(p->udev, 0, BULK_ALTERNATE_IFACE); | ||
40 | if (ret < 0) | ||
41 | goto out; | ||
42 | |||
43 | ret = set_tuner_mode(p, TLG_MODE_FM_RADIO); | ||
44 | if (ret != 0) | ||
45 | goto out; | ||
46 | |||
47 | ret = send_set_req(p, SGNL_SRC_SEL, TLG_SIG_SRC_ANTENNA, &status); | ||
48 | ret = send_set_req(p, TUNER_AUD_ANA_STD, | ||
49 | p->radio_data.pre_emphasis, &status); | ||
50 | ret |= send_set_req(p, TUNER_AUD_MODE, | ||
51 | TLG_TUNE_TVAUDIO_MODE_STEREO, &status); | ||
52 | ret |= send_set_req(p, AUDIO_SAMPLE_RATE_SEL, | ||
53 | ATV_AUDIO_RATE_48K, &status); | ||
54 | ret |= send_set_req(p, TUNE_FREQ_SELECT, TUNER_FREQ_MIN_FM, &status); | ||
55 | out: | ||
56 | return ret; | ||
57 | } | ||
58 | |||
59 | #ifdef CONFIG_PM | ||
60 | static int pm_fm_suspend(struct poseidon *p) | ||
61 | { | ||
62 | logpm(p); | ||
63 | pm_alsa_suspend(p); | ||
64 | usb_set_interface(p->udev, 0, 0); | ||
65 | msleep(300); | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static int pm_fm_resume(struct poseidon *p) | ||
70 | { | ||
71 | logpm(p); | ||
72 | poseidon_check_mode_radio(p); | ||
73 | set_frequency(p, p->radio_data.fm_freq); | ||
74 | pm_alsa_resume(p); | ||
75 | return 0; | ||
76 | } | ||
77 | #endif | ||
78 | |||
79 | static int poseidon_fm_open(struct file *filp) | ||
80 | { | ||
81 | struct video_device *vfd = video_devdata(filp); | ||
82 | struct poseidon *p = video_get_drvdata(vfd); | ||
83 | int ret = 0; | ||
84 | |||
85 | if (!p) | ||
86 | return -1; | ||
87 | |||
88 | mutex_lock(&p->lock); | ||
89 | if (p->state & POSEIDON_STATE_DISCONNECT) { | ||
90 | ret = -ENODEV; | ||
91 | goto out; | ||
92 | } | ||
93 | |||
94 | if (p->state && !(p->state & POSEIDON_STATE_FM)) { | ||
95 | ret = -EBUSY; | ||
96 | goto out; | ||
97 | } | ||
98 | |||
99 | usb_autopm_get_interface(p->interface); | ||
100 | if (0 == p->state) { | ||
101 | /* default pre-emphasis */ | ||
102 | if (p->radio_data.pre_emphasis == 0) | ||
103 | p->radio_data.pre_emphasis = TLG_TUNE_ASTD_FM_EUR; | ||
104 | set_debug_mode(vfd, debug_mode); | ||
105 | |||
106 | ret = poseidon_check_mode_radio(p); | ||
107 | if (ret < 0) { | ||
108 | usb_autopm_put_interface(p->interface); | ||
109 | goto out; | ||
110 | } | ||
111 | p->state |= POSEIDON_STATE_FM; | ||
112 | } | ||
113 | p->radio_data.users++; | ||
114 | kref_get(&p->kref); | ||
115 | filp->private_data = p; | ||
116 | out: | ||
117 | mutex_unlock(&p->lock); | ||
118 | return ret; | ||
119 | } | ||
120 | |||
121 | static int poseidon_fm_close(struct file *filp) | ||
122 | { | ||
123 | struct poseidon *p = filp->private_data; | ||
124 | struct radio_data *fm = &p->radio_data; | ||
125 | uint32_t status; | ||
126 | |||
127 | mutex_lock(&p->lock); | ||
128 | fm->users--; | ||
129 | if (0 == fm->users) | ||
130 | p->state &= ~POSEIDON_STATE_FM; | ||
131 | |||
132 | if (fm->is_radio_streaming && filp == p->file_for_stream) { | ||
133 | fm->is_radio_streaming = 0; | ||
134 | send_set_req(p, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP, &status); | ||
135 | } | ||
136 | usb_autopm_put_interface(p->interface); | ||
137 | mutex_unlock(&p->lock); | ||
138 | |||
139 | kref_put(&p->kref, poseidon_delete); | ||
140 | filp->private_data = NULL; | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static int vidioc_querycap(struct file *file, void *priv, | ||
145 | struct v4l2_capability *v) | ||
146 | { | ||
147 | struct poseidon *p = file->private_data; | ||
148 | |||
149 | strlcpy(v->driver, "tele-radio", sizeof(v->driver)); | ||
150 | strlcpy(v->card, "Telegent Poseidon", sizeof(v->card)); | ||
151 | usb_make_path(p->udev, v->bus_info, sizeof(v->bus_info)); | ||
152 | v->version = KERNEL_VERSION(0, 0, 1); | ||
153 | v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; | ||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | static const struct v4l2_file_operations poseidon_fm_fops = { | ||
158 | .owner = THIS_MODULE, | ||
159 | .open = poseidon_fm_open, | ||
160 | .release = poseidon_fm_close, | ||
161 | .ioctl = video_ioctl2, | ||
162 | }; | ||
163 | |||
164 | int tlg_fm_vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt) | ||
165 | { | ||
166 | struct tuner_fm_sig_stat_s fm_stat = {}; | ||
167 | int ret, status, count = 5; | ||
168 | struct poseidon *p = file->private_data; | ||
169 | |||
170 | if (vt->index != 0) | ||
171 | return -EINVAL; | ||
172 | |||
173 | vt->type = V4L2_TUNER_RADIO; | ||
174 | vt->capability = V4L2_TUNER_CAP_STEREO; | ||
175 | vt->rangelow = TUNER_FREQ_MIN_FM / 62500; | ||
176 | vt->rangehigh = TUNER_FREQ_MAX_FM / 62500; | ||
177 | vt->rxsubchans = V4L2_TUNER_SUB_STEREO; | ||
178 | vt->audmode = V4L2_TUNER_MODE_STEREO; | ||
179 | vt->signal = 0; | ||
180 | vt->afc = 0; | ||
181 | |||
182 | mutex_lock(&p->lock); | ||
183 | ret = send_get_req(p, TUNER_STATUS, TLG_MODE_FM_RADIO, | ||
184 | &fm_stat, &status, sizeof(fm_stat)); | ||
185 | |||
186 | while (fm_stat.sig_lock_busy && count-- && !ret) { | ||
187 | set_current_state(TASK_INTERRUPTIBLE); | ||
188 | schedule_timeout(HZ); | ||
189 | |||
190 | ret = send_get_req(p, TUNER_STATUS, TLG_MODE_FM_RADIO, | ||
191 | &fm_stat, &status, sizeof(fm_stat)); | ||
192 | } | ||
193 | mutex_unlock(&p->lock); | ||
194 | |||
195 | if (ret || status) { | ||
196 | vt->signal = 0; | ||
197 | } else if ((fm_stat.sig_present || fm_stat.sig_locked) | ||
198 | && fm_stat.sig_strength == 0) { | ||
199 | vt->signal = 0xffff; | ||
200 | } else | ||
201 | vt->signal = (fm_stat.sig_strength * 255 / 10) << 8; | ||
202 | |||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | int fm_get_freq(struct file *file, void *priv, struct v4l2_frequency *argp) | ||
207 | { | ||
208 | struct poseidon *p = file->private_data; | ||
209 | |||
210 | argp->frequency = p->radio_data.fm_freq; | ||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static int set_frequency(struct poseidon *p, __u32 frequency) | ||
215 | { | ||
216 | __u32 freq ; | ||
217 | int ret, status; | ||
218 | |||
219 | mutex_lock(&p->lock); | ||
220 | |||
221 | ret = send_set_req(p, TUNER_AUD_ANA_STD, | ||
222 | p->radio_data.pre_emphasis, &status); | ||
223 | |||
224 | freq = (frequency * 125) * 500 / 1000;/* kHZ */ | ||
225 | if (freq < TUNER_FREQ_MIN_FM/1000 || freq > TUNER_FREQ_MAX_FM/1000) { | ||
226 | ret = -EINVAL; | ||
227 | goto error; | ||
228 | } | ||
229 | |||
230 | ret = send_set_req(p, TUNE_FREQ_SELECT, freq, &status); | ||
231 | if (ret < 0) | ||
232 | goto error ; | ||
233 | ret = send_set_req(p, TAKE_REQUEST, 0, &status); | ||
234 | |||
235 | set_current_state(TASK_INTERRUPTIBLE); | ||
236 | schedule_timeout(HZ/4); | ||
237 | if (!p->radio_data.is_radio_streaming) { | ||
238 | ret = send_set_req(p, TAKE_REQUEST, 0, &status); | ||
239 | ret = send_set_req(p, PLAY_SERVICE, | ||
240 | TLG_TUNE_PLAY_SVC_START, &status); | ||
241 | p->radio_data.is_radio_streaming = 1; | ||
242 | } | ||
243 | p->radio_data.fm_freq = frequency; | ||
244 | error: | ||
245 | mutex_unlock(&p->lock); | ||
246 | return ret; | ||
247 | } | ||
248 | |||
249 | int fm_set_freq(struct file *file, void *priv, struct v4l2_frequency *argp) | ||
250 | { | ||
251 | struct poseidon *p = file->private_data; | ||
252 | |||
253 | p->file_for_stream = file; | ||
254 | #ifdef CONFIG_PM | ||
255 | p->pm_suspend = pm_fm_suspend; | ||
256 | p->pm_resume = pm_fm_resume; | ||
257 | #endif | ||
258 | return set_frequency(p, argp->frequency); | ||
259 | } | ||
260 | |||
261 | int tlg_fm_vidioc_g_ctrl(struct file *file, void *priv, | ||
262 | struct v4l2_control *arg) | ||
263 | { | ||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | int tlg_fm_vidioc_g_exts_ctrl(struct file *file, void *fh, | ||
268 | struct v4l2_ext_controls *ctrls) | ||
269 | { | ||
270 | struct poseidon *p = file->private_data; | ||
271 | int i; | ||
272 | |||
273 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX) | ||
274 | return -EINVAL; | ||
275 | |||
276 | for (i = 0; i < ctrls->count; i++) { | ||
277 | struct v4l2_ext_control *ctrl = ctrls->controls + i; | ||
278 | |||
279 | if (ctrl->id != V4L2_CID_TUNE_PREEMPHASIS) | ||
280 | continue; | ||
281 | |||
282 | if (i < MAX_PREEMPHASIS) | ||
283 | ctrl->value = p->radio_data.pre_emphasis; | ||
284 | } | ||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | int tlg_fm_vidioc_s_exts_ctrl(struct file *file, void *fh, | ||
289 | struct v4l2_ext_controls *ctrls) | ||
290 | { | ||
291 | int i; | ||
292 | |||
293 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX) | ||
294 | return -EINVAL; | ||
295 | |||
296 | for (i = 0; i < ctrls->count; i++) { | ||
297 | struct v4l2_ext_control *ctrl = ctrls->controls + i; | ||
298 | |||
299 | if (ctrl->id != V4L2_CID_TUNE_PREEMPHASIS) | ||
300 | continue; | ||
301 | |||
302 | if (ctrl->value >= 0 && ctrl->value < MAX_PREEMPHASIS) { | ||
303 | struct poseidon *p = file->private_data; | ||
304 | int pre_emphasis = preemphasis[ctrl->value]; | ||
305 | u32 status; | ||
306 | |||
307 | send_set_req(p, TUNER_AUD_ANA_STD, | ||
308 | pre_emphasis, &status); | ||
309 | p->radio_data.pre_emphasis = pre_emphasis; | ||
310 | } | ||
311 | } | ||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | int tlg_fm_vidioc_s_ctrl(struct file *file, void *priv, | ||
316 | struct v4l2_control *ctrl) | ||
317 | { | ||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | int tlg_fm_vidioc_queryctrl(struct file *file, void *priv, | ||
322 | struct v4l2_queryctrl *ctrl) | ||
323 | { | ||
324 | if (!(ctrl->id & V4L2_CTRL_FLAG_NEXT_CTRL)) | ||
325 | return -EINVAL; | ||
326 | |||
327 | ctrl->id &= ~V4L2_CTRL_FLAG_NEXT_CTRL; | ||
328 | if (ctrl->id != V4L2_CID_TUNE_PREEMPHASIS) { | ||
329 | /* return the next supported control */ | ||
330 | ctrl->id = V4L2_CID_TUNE_PREEMPHASIS; | ||
331 | v4l2_ctrl_query_fill(ctrl, V4L2_PREEMPHASIS_DISABLED, | ||
332 | V4L2_PREEMPHASIS_75_uS, 1, | ||
333 | V4L2_PREEMPHASIS_50_uS); | ||
334 | ctrl->flags = V4L2_CTRL_FLAG_UPDATE; | ||
335 | return 0; | ||
336 | } | ||
337 | return -EINVAL; | ||
338 | } | ||
339 | |||
340 | int tlg_fm_vidioc_querymenu(struct file *file, void *fh, | ||
341 | struct v4l2_querymenu *qmenu) | ||
342 | { | ||
343 | return v4l2_ctrl_query_menu(qmenu, NULL, NULL); | ||
344 | } | ||
345 | |||
346 | static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *vt) | ||
347 | { | ||
348 | return vt->index > 0 ? -EINVAL : 0; | ||
349 | } | ||
350 | static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *va) | ||
351 | { | ||
352 | return (va->index != 0) ? -EINVAL : 0; | ||
353 | } | ||
354 | |||
355 | static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) | ||
356 | { | ||
357 | a->index = 0; | ||
358 | a->mode = 0; | ||
359 | a->capability = V4L2_AUDCAP_STEREO; | ||
360 | strcpy(a->name, "Radio"); | ||
361 | return 0; | ||
362 | } | ||
363 | |||
364 | static int vidioc_s_input(struct file *filp, void *priv, u32 i) | ||
365 | { | ||
366 | return (i != 0) ? -EINVAL : 0; | ||
367 | } | ||
368 | |||
369 | static int vidioc_g_input(struct file *filp, void *priv, u32 *i) | ||
370 | { | ||
371 | return (*i != 0) ? -EINVAL : 0; | ||
372 | } | ||
373 | |||
374 | static const struct v4l2_ioctl_ops poseidon_fm_ioctl_ops = { | ||
375 | .vidioc_querycap = vidioc_querycap, | ||
376 | .vidioc_g_audio = vidioc_g_audio, | ||
377 | .vidioc_s_audio = vidioc_s_audio, | ||
378 | .vidioc_g_input = vidioc_g_input, | ||
379 | .vidioc_s_input = vidioc_s_input, | ||
380 | .vidioc_queryctrl = tlg_fm_vidioc_queryctrl, | ||
381 | .vidioc_querymenu = tlg_fm_vidioc_querymenu, | ||
382 | .vidioc_g_ctrl = tlg_fm_vidioc_g_ctrl, | ||
383 | .vidioc_s_ctrl = tlg_fm_vidioc_s_ctrl, | ||
384 | .vidioc_s_ext_ctrls = tlg_fm_vidioc_s_exts_ctrl, | ||
385 | .vidioc_g_ext_ctrls = tlg_fm_vidioc_g_exts_ctrl, | ||
386 | .vidioc_s_tuner = vidioc_s_tuner, | ||
387 | .vidioc_g_tuner = tlg_fm_vidioc_g_tuner, | ||
388 | .vidioc_g_frequency = fm_get_freq, | ||
389 | .vidioc_s_frequency = fm_set_freq, | ||
390 | }; | ||
391 | |||
392 | static struct video_device poseidon_fm_template = { | ||
393 | .name = "Telegent-Radio", | ||
394 | .fops = &poseidon_fm_fops, | ||
395 | .minor = -1, | ||
396 | .release = video_device_release, | ||
397 | .ioctl_ops = &poseidon_fm_ioctl_ops, | ||
398 | }; | ||
399 | |||
400 | int poseidon_fm_init(struct poseidon *p) | ||
401 | { | ||
402 | struct video_device *fm_dev; | ||
403 | |||
404 | fm_dev = vdev_init(p, &poseidon_fm_template); | ||
405 | if (fm_dev == NULL) | ||
406 | return -1; | ||
407 | |||
408 | if (video_register_device(fm_dev, VFL_TYPE_RADIO, -1) < 0) { | ||
409 | video_device_release(fm_dev); | ||
410 | return -1; | ||
411 | } | ||
412 | p->radio_data.fm_dev = fm_dev; | ||
413 | return 0; | ||
414 | } | ||
415 | |||
416 | int poseidon_fm_exit(struct poseidon *p) | ||
417 | { | ||
418 | destroy_video_device(&p->radio_data.fm_dev); | ||
419 | return 0; | ||
420 | } | ||
diff --git a/drivers/media/video/tlg2300/pd-video.c b/drivers/media/video/tlg2300/pd-video.c new file mode 100644 index 000000000000..becfba6a3041 --- /dev/null +++ b/drivers/media/video/tlg2300/pd-video.c | |||
@@ -0,0 +1,1667 @@ | |||
1 | #include <linux/fs.h> | ||
2 | #include <linux/vmalloc.h> | ||
3 | #include <linux/videodev2.h> | ||
4 | #include <linux/usb.h> | ||
5 | #include <linux/mm.h> | ||
6 | #include <linux/sched.h> | ||
7 | |||
8 | #include <media/v4l2-ioctl.h> | ||
9 | #include <media/v4l2-dev.h> | ||
10 | |||
11 | #include "pd-common.h" | ||
12 | #include "vendorcmds.h" | ||
13 | |||
14 | static int pm_video_suspend(struct poseidon *pd); | ||
15 | static int pm_video_resume(struct poseidon *pd); | ||
16 | static void iso_bubble_handler(struct work_struct *w); | ||
17 | |||
18 | int usb_transfer_mode; | ||
19 | module_param(usb_transfer_mode, int, 0644); | ||
20 | MODULE_PARM_DESC(usb_transfer_mode, "0 = Bulk, 1 = Isochronous"); | ||
21 | |||
22 | static const struct poseidon_format poseidon_formats[] = { | ||
23 | { "YUV 422", V4L2_PIX_FMT_YUYV, 16, 0}, | ||
24 | { "RGB565", V4L2_PIX_FMT_RGB565, 16, 0}, | ||
25 | }; | ||
26 | |||
27 | static const struct poseidon_tvnorm poseidon_tvnorms[] = { | ||
28 | { V4L2_STD_PAL_D, "PAL-D", TLG_TUNE_VSTD_PAL_D }, | ||
29 | { V4L2_STD_PAL_B, "PAL-B", TLG_TUNE_VSTD_PAL_B }, | ||
30 | { V4L2_STD_PAL_G, "PAL-G", TLG_TUNE_VSTD_PAL_G }, | ||
31 | { V4L2_STD_PAL_H, "PAL-H", TLG_TUNE_VSTD_PAL_H }, | ||
32 | { V4L2_STD_PAL_I, "PAL-I", TLG_TUNE_VSTD_PAL_I }, | ||
33 | { V4L2_STD_PAL_M, "PAL-M", TLG_TUNE_VSTD_PAL_M }, | ||
34 | { V4L2_STD_PAL_N, "PAL-N", TLG_TUNE_VSTD_PAL_N_COMBO }, | ||
35 | { V4L2_STD_PAL_Nc, "PAL-Nc", TLG_TUNE_VSTD_PAL_N_COMBO }, | ||
36 | { V4L2_STD_NTSC_M, "NTSC-M", TLG_TUNE_VSTD_NTSC_M }, | ||
37 | { V4L2_STD_NTSC_M_JP, "NTSC-JP", TLG_TUNE_VSTD_NTSC_M_J }, | ||
38 | { V4L2_STD_SECAM_B, "SECAM-B", TLG_TUNE_VSTD_SECAM_B }, | ||
39 | { V4L2_STD_SECAM_D, "SECAM-D", TLG_TUNE_VSTD_SECAM_D }, | ||
40 | { V4L2_STD_SECAM_G, "SECAM-G", TLG_TUNE_VSTD_SECAM_G }, | ||
41 | { V4L2_STD_SECAM_H, "SECAM-H", TLG_TUNE_VSTD_SECAM_H }, | ||
42 | { V4L2_STD_SECAM_K, "SECAM-K", TLG_TUNE_VSTD_SECAM_K }, | ||
43 | { V4L2_STD_SECAM_K1, "SECAM-K1", TLG_TUNE_VSTD_SECAM_K1 }, | ||
44 | { V4L2_STD_SECAM_L, "SECAM-L", TLG_TUNE_VSTD_SECAM_L }, | ||
45 | { V4L2_STD_SECAM_LC, "SECAM-LC", TLG_TUNE_VSTD_SECAM_L1 }, | ||
46 | }; | ||
47 | static const unsigned int POSEIDON_TVNORMS = ARRAY_SIZE(poseidon_tvnorms); | ||
48 | |||
49 | struct pd_audio_mode { | ||
50 | u32 tlg_audio_mode; | ||
51 | u32 v4l2_audio_sub; | ||
52 | u32 v4l2_audio_mode; | ||
53 | }; | ||
54 | |||
55 | static const struct pd_audio_mode pd_audio_modes[] = { | ||
56 | { TLG_TUNE_TVAUDIO_MODE_MONO, V4L2_TUNER_SUB_MONO, | ||
57 | V4L2_TUNER_MODE_MONO }, | ||
58 | { TLG_TUNE_TVAUDIO_MODE_STEREO, V4L2_TUNER_SUB_STEREO, | ||
59 | V4L2_TUNER_MODE_STEREO }, | ||
60 | { TLG_TUNE_TVAUDIO_MODE_LANG_A, V4L2_TUNER_SUB_LANG1, | ||
61 | V4L2_TUNER_MODE_LANG1 }, | ||
62 | { TLG_TUNE_TVAUDIO_MODE_LANG_B, V4L2_TUNER_SUB_LANG2, | ||
63 | V4L2_TUNER_MODE_LANG2 }, | ||
64 | { TLG_TUNE_TVAUDIO_MODE_LANG_C, V4L2_TUNER_SUB_LANG1, | ||
65 | V4L2_TUNER_MODE_LANG1_LANG2 } | ||
66 | }; | ||
67 | static const unsigned int POSEIDON_AUDIOMODS = ARRAY_SIZE(pd_audio_modes); | ||
68 | |||
69 | struct pd_input { | ||
70 | char *name; | ||
71 | uint32_t tlg_src; | ||
72 | }; | ||
73 | |||
74 | static const struct pd_input pd_inputs[] = { | ||
75 | { "TV Antenna", TLG_SIG_SRC_ANTENNA }, | ||
76 | { "TV Cable", TLG_SIG_SRC_CABLE }, | ||
77 | { "TV SVideo", TLG_SIG_SRC_SVIDEO }, | ||
78 | { "TV Composite", TLG_SIG_SRC_COMPOSITE } | ||
79 | }; | ||
80 | static const unsigned int POSEIDON_INPUTS = ARRAY_SIZE(pd_inputs); | ||
81 | |||
82 | struct poseidon_control { | ||
83 | struct v4l2_queryctrl v4l2_ctrl; | ||
84 | enum cmd_custom_param_id vc_id; | ||
85 | }; | ||
86 | |||
87 | static struct poseidon_control controls[] = { | ||
88 | { | ||
89 | { V4L2_CID_BRIGHTNESS, V4L2_CTRL_TYPE_INTEGER, | ||
90 | "brightness", 0, 10000, 1, 100, 0, }, | ||
91 | CUST_PARM_ID_BRIGHTNESS_CTRL | ||
92 | }, { | ||
93 | { V4L2_CID_CONTRAST, V4L2_CTRL_TYPE_INTEGER, | ||
94 | "contrast", 0, 10000, 1, 100, 0, }, | ||
95 | CUST_PARM_ID_CONTRAST_CTRL, | ||
96 | }, { | ||
97 | { V4L2_CID_HUE, V4L2_CTRL_TYPE_INTEGER, | ||
98 | "hue", 0, 10000, 1, 100, 0, }, | ||
99 | CUST_PARM_ID_HUE_CTRL, | ||
100 | }, { | ||
101 | { V4L2_CID_SATURATION, V4L2_CTRL_TYPE_INTEGER, | ||
102 | "saturation", 0, 10000, 1, 100, 0, }, | ||
103 | CUST_PARM_ID_SATURATION_CTRL, | ||
104 | }, | ||
105 | }; | ||
106 | |||
107 | struct video_std_to_audio_std { | ||
108 | v4l2_std_id video_std; | ||
109 | int audio_std; | ||
110 | }; | ||
111 | |||
112 | static const struct video_std_to_audio_std video_to_audio_map[] = { | ||
113 | /* country : { 27, 32, 33, 34, 36, 44, 45, 46, 47, 48, 64, | ||
114 | 65, 86, 351, 352, 353, 354, 358, 372, 852, 972 } */ | ||
115 | { (V4L2_STD_PAL_I | V4L2_STD_PAL_B | V4L2_STD_PAL_D | | ||
116 | V4L2_STD_SECAM_L | V4L2_STD_SECAM_D), TLG_TUNE_ASTD_NICAM }, | ||
117 | |||
118 | /* country : { 1, 52, 54, 55, 886 } */ | ||
119 | {V4L2_STD_NTSC_M | V4L2_STD_PAL_N | V4L2_STD_PAL_M, TLG_TUNE_ASTD_BTSC}, | ||
120 | |||
121 | /* country : { 81 } */ | ||
122 | { V4L2_STD_NTSC_M_JP, TLG_TUNE_ASTD_EIAJ }, | ||
123 | |||
124 | /* other country : TLG_TUNE_ASTD_A2 */ | ||
125 | }; | ||
126 | static const unsigned int map_size = ARRAY_SIZE(video_to_audio_map); | ||
127 | |||
128 | static int get_audio_std(v4l2_std_id v4l2_std) | ||
129 | { | ||
130 | int i = 0; | ||
131 | |||
132 | for (; i < map_size; i++) { | ||
133 | if (v4l2_std & video_to_audio_map[i].video_std) | ||
134 | return video_to_audio_map[i].audio_std; | ||
135 | } | ||
136 | return TLG_TUNE_ASTD_A2; | ||
137 | } | ||
138 | |||
139 | static int vidioc_querycap(struct file *file, void *fh, | ||
140 | struct v4l2_capability *cap) | ||
141 | { | ||
142 | struct front_face *front = fh; | ||
143 | struct poseidon *p = front->pd; | ||
144 | |||
145 | logs(front); | ||
146 | |||
147 | strcpy(cap->driver, "tele-video"); | ||
148 | strcpy(cap->card, "Telegent Poseidon"); | ||
149 | usb_make_path(p->udev, cap->bus_info, sizeof(cap->bus_info)); | ||
150 | cap->version = KERNEL_VERSION(0, 0, 1); | ||
151 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | | ||
152 | V4L2_CAP_AUDIO | V4L2_CAP_STREAMING | | ||
153 | V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE; | ||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | /*====================================================================*/ | ||
158 | static void init_copy(struct video_data *video, bool index) | ||
159 | { | ||
160 | struct front_face *front = video->front; | ||
161 | |||
162 | video->field_count = index; | ||
163 | video->lines_copied = 0; | ||
164 | video->prev_left = 0 ; | ||
165 | video->dst = (char *)videobuf_to_vmalloc(front->curr_frame) | ||
166 | + index * video->lines_size; | ||
167 | video->vbi->copied = 0; /* set it here */ | ||
168 | } | ||
169 | |||
170 | static bool get_frame(struct front_face *front, int *need_init) | ||
171 | { | ||
172 | struct videobuf_buffer *vb = front->curr_frame; | ||
173 | |||
174 | if (vb) | ||
175 | return true; | ||
176 | |||
177 | spin_lock(&front->queue_lock); | ||
178 | if (!list_empty(&front->active)) { | ||
179 | vb = list_entry(front->active.next, | ||
180 | struct videobuf_buffer, queue); | ||
181 | if (need_init) | ||
182 | *need_init = 1; | ||
183 | front->curr_frame = vb; | ||
184 | list_del_init(&vb->queue); | ||
185 | } | ||
186 | spin_unlock(&front->queue_lock); | ||
187 | |||
188 | return !!vb; | ||
189 | } | ||
190 | |||
191 | /* check if the video's buffer is ready */ | ||
192 | static bool get_video_frame(struct front_face *front, struct video_data *video) | ||
193 | { | ||
194 | int need_init = 0; | ||
195 | bool ret = true; | ||
196 | |||
197 | ret = get_frame(front, &need_init); | ||
198 | if (ret && need_init) | ||
199 | init_copy(video, 0); | ||
200 | return ret; | ||
201 | } | ||
202 | |||
203 | static void submit_frame(struct front_face *front) | ||
204 | { | ||
205 | struct videobuf_buffer *vb = front->curr_frame; | ||
206 | |||
207 | if (vb == NULL) | ||
208 | return; | ||
209 | |||
210 | front->curr_frame = NULL; | ||
211 | vb->state = VIDEOBUF_DONE; | ||
212 | vb->field_count++; | ||
213 | do_gettimeofday(&vb->ts); | ||
214 | |||
215 | wake_up(&vb->done); | ||
216 | } | ||
217 | |||
218 | /* | ||
219 | * A frame is composed of two fields. If we receive all the two fields, | ||
220 | * call the submit_frame() to submit the whole frame to applications. | ||
221 | */ | ||
222 | static void end_field(struct video_data *video) | ||
223 | { | ||
224 | /* logs(video->front); */ | ||
225 | if (1 == video->field_count) | ||
226 | submit_frame(video->front); | ||
227 | else | ||
228 | init_copy(video, 1); | ||
229 | } | ||
230 | |||
231 | static void copy_video_data(struct video_data *video, char *src, | ||
232 | unsigned int count) | ||
233 | { | ||
234 | #define copy_data(len) \ | ||
235 | do { \ | ||
236 | if (++video->lines_copied > video->lines_per_field) \ | ||
237 | goto overflow; \ | ||
238 | memcpy(video->dst, src, len);\ | ||
239 | video->dst += len + video->lines_size; \ | ||
240 | src += len; \ | ||
241 | count -= len; \ | ||
242 | } while (0) | ||
243 | |||
244 | while (count && count >= video->lines_size) { | ||
245 | if (video->prev_left) { | ||
246 | copy_data(video->prev_left); | ||
247 | video->prev_left = 0; | ||
248 | continue; | ||
249 | } | ||
250 | copy_data(video->lines_size); | ||
251 | } | ||
252 | if (count && count < video->lines_size) { | ||
253 | memcpy(video->dst, src, count); | ||
254 | |||
255 | video->prev_left = video->lines_size - count; | ||
256 | video->dst += count; | ||
257 | } | ||
258 | return; | ||
259 | |||
260 | overflow: | ||
261 | end_field(video); | ||
262 | } | ||
263 | |||
264 | static void check_trailer(struct video_data *video, char *src, int count) | ||
265 | { | ||
266 | struct vbi_data *vbi = video->vbi; | ||
267 | int offset; /* trailer's offset */ | ||
268 | char *buf; | ||
269 | |||
270 | offset = (video->context.pix.sizeimage / 2 + vbi->vbi_size / 2) | ||
271 | - (vbi->copied + video->lines_size * video->lines_copied); | ||
272 | if (video->prev_left) | ||
273 | offset -= (video->lines_size - video->prev_left); | ||
274 | |||
275 | if (offset > count || offset <= 0) | ||
276 | goto short_package; | ||
277 | |||
278 | buf = src + offset; | ||
279 | |||
280 | /* trailer : (VFHS) + U32 + U32 + field_num */ | ||
281 | if (!strncmp(buf, "VFHS", 4)) { | ||
282 | int field_num = *((u32 *)(buf + 12)); | ||
283 | |||
284 | if ((field_num & 1) ^ video->field_count) { | ||
285 | init_copy(video, video->field_count); | ||
286 | return; | ||
287 | } | ||
288 | copy_video_data(video, src, offset); | ||
289 | } | ||
290 | short_package: | ||
291 | end_field(video); | ||
292 | } | ||
293 | |||
294 | /* ========== Check this more carefully! =========== */ | ||
295 | static inline void copy_vbi_data(struct vbi_data *vbi, | ||
296 | char *src, unsigned int count) | ||
297 | { | ||
298 | struct front_face *front = vbi->front; | ||
299 | |||
300 | if (front && get_frame(front, NULL)) { | ||
301 | char *buf = videobuf_to_vmalloc(front->curr_frame); | ||
302 | |||
303 | if (vbi->video->field_count) | ||
304 | buf += (vbi->vbi_size / 2); | ||
305 | memcpy(buf + vbi->copied, src, count); | ||
306 | } | ||
307 | vbi->copied += count; | ||
308 | } | ||
309 | |||
310 | /* | ||
311 | * Copy the normal data (VBI or VIDEO) without the trailer. | ||
312 | * VBI is not interlaced, while VIDEO is interlaced. | ||
313 | */ | ||
314 | static inline void copy_vbi_video_data(struct video_data *video, | ||
315 | char *src, unsigned int count) | ||
316 | { | ||
317 | struct vbi_data *vbi = video->vbi; | ||
318 | unsigned int vbi_delta = (vbi->vbi_size / 2) - vbi->copied; | ||
319 | |||
320 | if (vbi_delta >= count) { | ||
321 | copy_vbi_data(vbi, src, count); | ||
322 | } else { | ||
323 | if (vbi_delta) { | ||
324 | copy_vbi_data(vbi, src, vbi_delta); | ||
325 | |||
326 | /* we receive the two fields of the VBI*/ | ||
327 | if (vbi->front && video->field_count) | ||
328 | submit_frame(vbi->front); | ||
329 | } | ||
330 | copy_video_data(video, src + vbi_delta, count - vbi_delta); | ||
331 | } | ||
332 | } | ||
333 | |||
334 | static void urb_complete_bulk(struct urb *urb) | ||
335 | { | ||
336 | struct front_face *front = urb->context; | ||
337 | struct video_data *video = &front->pd->video_data; | ||
338 | char *src = (char *)urb->transfer_buffer; | ||
339 | int count = urb->actual_length; | ||
340 | int ret = 0; | ||
341 | |||
342 | if (!video->is_streaming || urb->status) { | ||
343 | if (urb->status == -EPROTO) | ||
344 | goto resend_it; | ||
345 | return; | ||
346 | } | ||
347 | if (!get_video_frame(front, video)) | ||
348 | goto resend_it; | ||
349 | |||
350 | if (count == urb->transfer_buffer_length) | ||
351 | copy_vbi_video_data(video, src, count); | ||
352 | else | ||
353 | check_trailer(video, src, count); | ||
354 | |||
355 | resend_it: | ||
356 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
357 | if (ret) | ||
358 | log(" submit failed: error %d", ret); | ||
359 | } | ||
360 | |||
361 | /************************* for ISO *********************/ | ||
362 | #define GET_SUCCESS (0) | ||
363 | #define GET_TRAILER (1) | ||
364 | #define GET_TOO_MUCH_BUBBLE (2) | ||
365 | #define GET_NONE (3) | ||
366 | static int get_chunk(int start, struct urb *urb, | ||
367 | int *head, int *tail, int *bubble_err) | ||
368 | { | ||
369 | struct usb_iso_packet_descriptor *pkt = NULL; | ||
370 | int ret = GET_SUCCESS; | ||
371 | |||
372 | for (*head = *tail = -1; start < urb->number_of_packets; start++) { | ||
373 | pkt = &urb->iso_frame_desc[start]; | ||
374 | |||
375 | /* handle the bubble of the Hub */ | ||
376 | if (-EOVERFLOW == pkt->status) { | ||
377 | if (++*bubble_err > urb->number_of_packets / 3) | ||
378 | return GET_TOO_MUCH_BUBBLE; | ||
379 | continue; | ||
380 | } | ||
381 | |||
382 | /* This is the gap */ | ||
383 | if (pkt->status || pkt->actual_length <= 0 | ||
384 | || pkt->actual_length > ISO_PKT_SIZE) { | ||
385 | if (*head != -1) | ||
386 | break; | ||
387 | continue; | ||
388 | } | ||
389 | |||
390 | /* a good isochronous packet */ | ||
391 | if (pkt->actual_length == ISO_PKT_SIZE) { | ||
392 | if (*head == -1) | ||
393 | *head = start; | ||
394 | *tail = start; | ||
395 | continue; | ||
396 | } | ||
397 | |||
398 | /* trailer is here */ | ||
399 | if (pkt->actual_length < ISO_PKT_SIZE) { | ||
400 | if (*head == -1) { | ||
401 | *head = start; | ||
402 | *tail = start; | ||
403 | return GET_TRAILER; | ||
404 | } | ||
405 | break; | ||
406 | } | ||
407 | } | ||
408 | |||
409 | if (*head == -1 && *tail == -1) | ||
410 | ret = GET_NONE; | ||
411 | return ret; | ||
412 | } | ||
413 | |||
414 | /* | ||
415 | * |__|------|___|-----|_______| | ||
416 | * ^ ^ | ||
417 | * | | | ||
418 | * gap gap | ||
419 | */ | ||
420 | static void urb_complete_iso(struct urb *urb) | ||
421 | { | ||
422 | struct front_face *front = urb->context; | ||
423 | struct video_data *video = &front->pd->video_data; | ||
424 | int bubble_err = 0, head = 0, tail = 0; | ||
425 | char *src = (char *)urb->transfer_buffer; | ||
426 | int ret = 0; | ||
427 | |||
428 | if (!video->is_streaming) | ||
429 | return; | ||
430 | |||
431 | do { | ||
432 | if (!get_video_frame(front, video)) | ||
433 | goto out; | ||
434 | |||
435 | switch (get_chunk(head, urb, &head, &tail, &bubble_err)) { | ||
436 | case GET_SUCCESS: | ||
437 | copy_vbi_video_data(video, src + (head * ISO_PKT_SIZE), | ||
438 | (tail - head + 1) * ISO_PKT_SIZE); | ||
439 | break; | ||
440 | case GET_TRAILER: | ||
441 | check_trailer(video, src + (head * ISO_PKT_SIZE), | ||
442 | ISO_PKT_SIZE); | ||
443 | break; | ||
444 | case GET_NONE: | ||
445 | goto out; | ||
446 | case GET_TOO_MUCH_BUBBLE: | ||
447 | log("\t We got too much bubble"); | ||
448 | schedule_work(&video->bubble_work); | ||
449 | return; | ||
450 | } | ||
451 | } while (head = tail + 1, head < urb->number_of_packets); | ||
452 | |||
453 | out: | ||
454 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
455 | if (ret) | ||
456 | log("usb_submit_urb err : %d", ret); | ||
457 | } | ||
458 | /*============================= [ end ] =====================*/ | ||
459 | |||
460 | static int prepare_iso_urb(struct video_data *video) | ||
461 | { | ||
462 | struct usb_device *udev = video->pd->udev; | ||
463 | int i; | ||
464 | |||
465 | if (video->urb_array[0]) | ||
466 | return 0; | ||
467 | |||
468 | for (i = 0; i < SBUF_NUM; i++) { | ||
469 | struct urb *urb; | ||
470 | void *mem; | ||
471 | int j; | ||
472 | |||
473 | urb = usb_alloc_urb(PK_PER_URB, GFP_KERNEL); | ||
474 | if (urb == NULL) | ||
475 | goto out; | ||
476 | |||
477 | video->urb_array[i] = urb; | ||
478 | mem = usb_buffer_alloc(udev, | ||
479 | ISO_PKT_SIZE * PK_PER_URB, | ||
480 | GFP_KERNEL, | ||
481 | &urb->transfer_dma); | ||
482 | |||
483 | urb->complete = urb_complete_iso; /* handler */ | ||
484 | urb->dev = udev; | ||
485 | urb->context = video->front; | ||
486 | urb->pipe = usb_rcvisocpipe(udev, | ||
487 | video->endpoint_addr); | ||
488 | urb->interval = 1; | ||
489 | urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; | ||
490 | urb->number_of_packets = PK_PER_URB; | ||
491 | urb->transfer_buffer = mem; | ||
492 | urb->transfer_buffer_length = PK_PER_URB * ISO_PKT_SIZE; | ||
493 | |||
494 | for (j = 0; j < PK_PER_URB; j++) { | ||
495 | urb->iso_frame_desc[j].offset = ISO_PKT_SIZE * j; | ||
496 | urb->iso_frame_desc[j].length = ISO_PKT_SIZE; | ||
497 | } | ||
498 | } | ||
499 | return 0; | ||
500 | out: | ||
501 | for (; i > 0; i--) | ||
502 | ; | ||
503 | return -ENOMEM; | ||
504 | } | ||
505 | |||
506 | /* return the succeeded number of the allocation */ | ||
507 | int alloc_bulk_urbs_generic(struct urb **urb_array, int num, | ||
508 | struct usb_device *udev, u8 ep_addr, | ||
509 | int buf_size, gfp_t gfp_flags, | ||
510 | usb_complete_t complete_fn, void *context) | ||
511 | { | ||
512 | struct urb *urb; | ||
513 | void *mem; | ||
514 | int i; | ||
515 | |||
516 | for (i = 0; i < num; i++) { | ||
517 | urb = usb_alloc_urb(0, gfp_flags); | ||
518 | if (urb == NULL) | ||
519 | return i; | ||
520 | |||
521 | mem = usb_buffer_alloc(udev, buf_size, gfp_flags, | ||
522 | &urb->transfer_dma); | ||
523 | if (mem == NULL) | ||
524 | return i; | ||
525 | |||
526 | usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, ep_addr), | ||
527 | mem, buf_size, complete_fn, context); | ||
528 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
529 | urb_array[i] = urb; | ||
530 | } | ||
531 | return i; | ||
532 | } | ||
533 | |||
534 | void free_all_urb_generic(struct urb **urb_array, int num) | ||
535 | { | ||
536 | int i; | ||
537 | struct urb *urb; | ||
538 | |||
539 | for (i = 0; i < num; i++) { | ||
540 | urb = urb_array[i]; | ||
541 | if (urb) { | ||
542 | usb_buffer_free(urb->dev, | ||
543 | urb->transfer_buffer_length, | ||
544 | urb->transfer_buffer, | ||
545 | urb->transfer_dma); | ||
546 | usb_free_urb(urb); | ||
547 | urb_array[i] = NULL; | ||
548 | } | ||
549 | } | ||
550 | } | ||
551 | |||
552 | static int prepare_bulk_urb(struct video_data *video) | ||
553 | { | ||
554 | if (video->urb_array[0]) | ||
555 | return 0; | ||
556 | |||
557 | alloc_bulk_urbs_generic(video->urb_array, SBUF_NUM, | ||
558 | video->pd->udev, video->endpoint_addr, | ||
559 | 0x2000, GFP_KERNEL, | ||
560 | urb_complete_bulk, video->front); | ||
561 | return 0; | ||
562 | } | ||
563 | |||
564 | /* free the URBs */ | ||
565 | static void free_all_urb(struct video_data *video) | ||
566 | { | ||
567 | free_all_urb_generic(video->urb_array, SBUF_NUM); | ||
568 | } | ||
569 | |||
570 | static void pd_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb) | ||
571 | { | ||
572 | videobuf_vmalloc_free(vb); | ||
573 | vb->state = VIDEOBUF_NEEDS_INIT; | ||
574 | } | ||
575 | |||
576 | static void pd_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) | ||
577 | { | ||
578 | struct front_face *front = q->priv_data; | ||
579 | vb->state = VIDEOBUF_QUEUED; | ||
580 | list_add_tail(&vb->queue, &front->active); | ||
581 | } | ||
582 | |||
583 | static int pd_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | ||
584 | enum v4l2_field field) | ||
585 | { | ||
586 | struct front_face *front = q->priv_data; | ||
587 | int rc; | ||
588 | |||
589 | switch (front->type) { | ||
590 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
591 | if (VIDEOBUF_NEEDS_INIT == vb->state) { | ||
592 | struct v4l2_pix_format *pix; | ||
593 | |||
594 | pix = &front->pd->video_data.context.pix; | ||
595 | vb->size = pix->sizeimage; /* real frame size */ | ||
596 | vb->width = pix->width; | ||
597 | vb->height = pix->height; | ||
598 | rc = videobuf_iolock(q, vb, NULL); | ||
599 | if (rc < 0) | ||
600 | return rc; | ||
601 | } | ||
602 | break; | ||
603 | case V4L2_BUF_TYPE_VBI_CAPTURE: | ||
604 | if (VIDEOBUF_NEEDS_INIT == vb->state) { | ||
605 | vb->size = front->pd->vbi_data.vbi_size; | ||
606 | rc = videobuf_iolock(q, vb, NULL); | ||
607 | if (rc < 0) | ||
608 | return rc; | ||
609 | } | ||
610 | break; | ||
611 | default: | ||
612 | return -EINVAL; | ||
613 | } | ||
614 | vb->field = field; | ||
615 | vb->state = VIDEOBUF_PREPARED; | ||
616 | return 0; | ||
617 | } | ||
618 | |||
619 | int fire_all_urb(struct video_data *video) | ||
620 | { | ||
621 | int i, ret; | ||
622 | |||
623 | video->is_streaming = 1; | ||
624 | |||
625 | for (i = 0; i < SBUF_NUM; i++) { | ||
626 | ret = usb_submit_urb(video->urb_array[i], GFP_KERNEL); | ||
627 | if (ret) | ||
628 | log("(%d) failed: error %d", i, ret); | ||
629 | } | ||
630 | return ret; | ||
631 | } | ||
632 | |||
633 | static int start_video_stream(struct poseidon *pd) | ||
634 | { | ||
635 | struct video_data *video = &pd->video_data; | ||
636 | s32 cmd_status; | ||
637 | |||
638 | send_set_req(pd, TAKE_REQUEST, 0, &cmd_status); | ||
639 | send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_START, &cmd_status); | ||
640 | |||
641 | if (pd->cur_transfer_mode) { | ||
642 | prepare_iso_urb(video); | ||
643 | INIT_WORK(&video->bubble_work, iso_bubble_handler); | ||
644 | } else { | ||
645 | /* The bulk mode does not need a bubble handler */ | ||
646 | prepare_bulk_urb(video); | ||
647 | } | ||
648 | fire_all_urb(video); | ||
649 | return 0; | ||
650 | } | ||
651 | |||
652 | static int pd_buf_setup(struct videobuf_queue *q, unsigned int *count, | ||
653 | unsigned int *size) | ||
654 | { | ||
655 | struct front_face *front = q->priv_data; | ||
656 | struct poseidon *pd = front->pd; | ||
657 | |||
658 | switch (front->type) { | ||
659 | default: | ||
660 | return -EINVAL; | ||
661 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { | ||
662 | struct video_data *video = &pd->video_data; | ||
663 | struct v4l2_pix_format *pix = &video->context.pix; | ||
664 | |||
665 | *size = PAGE_ALIGN(pix->sizeimage);/* page aligned frame size */ | ||
666 | if (*count < 4) | ||
667 | *count = 4; | ||
668 | if (1) { | ||
669 | /* same in different altersetting */ | ||
670 | video->endpoint_addr = 0x82; | ||
671 | video->vbi = &pd->vbi_data; | ||
672 | video->vbi->video = video; | ||
673 | video->pd = pd; | ||
674 | video->lines_per_field = pix->height / 2; | ||
675 | video->lines_size = pix->width * 2; | ||
676 | video->front = front; | ||
677 | } | ||
678 | return start_video_stream(pd); | ||
679 | } | ||
680 | |||
681 | case V4L2_BUF_TYPE_VBI_CAPTURE: { | ||
682 | struct vbi_data *vbi = &pd->vbi_data; | ||
683 | |||
684 | *size = PAGE_ALIGN(vbi->vbi_size); | ||
685 | log("size : %d", *size); | ||
686 | if (*count == 0) | ||
687 | *count = 4; | ||
688 | } | ||
689 | break; | ||
690 | } | ||
691 | return 0; | ||
692 | } | ||
693 | |||
694 | static struct videobuf_queue_ops pd_video_qops = { | ||
695 | .buf_setup = pd_buf_setup, | ||
696 | .buf_prepare = pd_buf_prepare, | ||
697 | .buf_queue = pd_buf_queue, | ||
698 | .buf_release = pd_buf_release, | ||
699 | }; | ||
700 | |||
701 | static int vidioc_enum_fmt(struct file *file, void *fh, | ||
702 | struct v4l2_fmtdesc *f) | ||
703 | { | ||
704 | if (ARRAY_SIZE(poseidon_formats) <= f->index) | ||
705 | return -EINVAL; | ||
706 | f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
707 | f->flags = 0; | ||
708 | f->pixelformat = poseidon_formats[f->index].fourcc; | ||
709 | strcpy(f->description, poseidon_formats[f->index].name); | ||
710 | return 0; | ||
711 | } | ||
712 | |||
713 | static int vidioc_g_fmt(struct file *file, void *fh, struct v4l2_format *f) | ||
714 | { | ||
715 | struct front_face *front = fh; | ||
716 | struct poseidon *pd = front->pd; | ||
717 | |||
718 | logs(front); | ||
719 | f->fmt.pix = pd->video_data.context.pix; | ||
720 | return 0; | ||
721 | } | ||
722 | |||
723 | static int vidioc_try_fmt(struct file *file, void *fh, | ||
724 | struct v4l2_format *f) | ||
725 | { | ||
726 | return 0; | ||
727 | } | ||
728 | |||
729 | /* | ||
730 | * VLC calls VIDIOC_S_STD before VIDIOC_S_FMT, while | ||
731 | * Mplayer calls them in the reverse order. | ||
732 | */ | ||
733 | static int pd_vidioc_s_fmt(struct poseidon *pd, struct v4l2_pix_format *pix) | ||
734 | { | ||
735 | struct video_data *video = &pd->video_data; | ||
736 | struct running_context *context = &video->context; | ||
737 | struct v4l2_pix_format *pix_def = &context->pix; | ||
738 | s32 ret = 0, cmd_status = 0, vid_resol; | ||
739 | |||
740 | /* set the pixel format to firmware */ | ||
741 | if (pix->pixelformat == V4L2_PIX_FMT_RGB565) { | ||
742 | vid_resol = TLG_TUNER_VID_FORMAT_RGB_565; | ||
743 | } else { | ||
744 | pix->pixelformat = V4L2_PIX_FMT_YUYV; | ||
745 | vid_resol = TLG_TUNER_VID_FORMAT_YUV; | ||
746 | } | ||
747 | ret = send_set_req(pd, VIDEO_STREAM_FMT_SEL, | ||
748 | vid_resol, &cmd_status); | ||
749 | |||
750 | /* set the resolution to firmware */ | ||
751 | vid_resol = TLG_TUNE_VID_RES_720; | ||
752 | switch (pix->width) { | ||
753 | case 704: | ||
754 | vid_resol = TLG_TUNE_VID_RES_704; | ||
755 | break; | ||
756 | default: | ||
757 | pix->width = 720; | ||
758 | case 720: | ||
759 | break; | ||
760 | } | ||
761 | ret |= send_set_req(pd, VIDEO_ROSOLU_SEL, | ||
762 | vid_resol, &cmd_status); | ||
763 | if (ret || cmd_status) { | ||
764 | mutex_unlock(&pd->lock); | ||
765 | return -EBUSY; | ||
766 | } | ||
767 | |||
768 | pix_def->pixelformat = pix->pixelformat; /* save it */ | ||
769 | pix->height = (context->tvnormid & V4L2_STD_525_60) ? 480 : 576; | ||
770 | |||
771 | /* Compare with the default setting */ | ||
772 | if ((pix_def->width != pix->width) | ||
773 | || (pix_def->height != pix->height)) { | ||
774 | pix_def->width = pix->width; | ||
775 | pix_def->height = pix->height; | ||
776 | pix_def->bytesperline = pix->width * 2; | ||
777 | pix_def->sizeimage = pix->width * pix->height * 2; | ||
778 | } | ||
779 | *pix = *pix_def; | ||
780 | |||
781 | return 0; | ||
782 | } | ||
783 | |||
784 | static int vidioc_s_fmt(struct file *file, void *fh, struct v4l2_format *f) | ||
785 | { | ||
786 | struct front_face *front = fh; | ||
787 | struct poseidon *pd = front->pd; | ||
788 | |||
789 | logs(front); | ||
790 | /* stop VBI here */ | ||
791 | if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type) | ||
792 | return -EINVAL; | ||
793 | |||
794 | mutex_lock(&pd->lock); | ||
795 | if (pd->file_for_stream == NULL) | ||
796 | pd->file_for_stream = file; | ||
797 | else if (file != pd->file_for_stream) { | ||
798 | mutex_unlock(&pd->lock); | ||
799 | return -EINVAL; | ||
800 | } | ||
801 | |||
802 | pd_vidioc_s_fmt(pd, &f->fmt.pix); | ||
803 | mutex_unlock(&pd->lock); | ||
804 | return 0; | ||
805 | } | ||
806 | |||
807 | static int vidioc_g_fmt_vbi(struct file *file, void *fh, | ||
808 | struct v4l2_format *v4l2_f) | ||
809 | { | ||
810 | struct front_face *front = fh; | ||
811 | struct poseidon *pd = front->pd; | ||
812 | struct v4l2_vbi_format *vbi_fmt = &v4l2_f->fmt.vbi; | ||
813 | |||
814 | vbi_fmt->samples_per_line = 720 * 2; | ||
815 | vbi_fmt->sampling_rate = 6750000 * 4; | ||
816 | vbi_fmt->sample_format = V4L2_PIX_FMT_GREY; | ||
817 | vbi_fmt->offset = 64 * 4; /*FIXME: why offset */ | ||
818 | if (pd->video_data.context.tvnormid & V4L2_STD_525_60) { | ||
819 | vbi_fmt->start[0] = 10; | ||
820 | vbi_fmt->start[1] = 264; | ||
821 | vbi_fmt->count[0] = V4L_NTSC_VBI_LINES; | ||
822 | vbi_fmt->count[1] = V4L_NTSC_VBI_LINES; | ||
823 | } else { | ||
824 | vbi_fmt->start[0] = 6; | ||
825 | vbi_fmt->start[1] = 314; | ||
826 | vbi_fmt->count[0] = V4L_PAL_VBI_LINES; | ||
827 | vbi_fmt->count[1] = V4L_PAL_VBI_LINES; | ||
828 | } | ||
829 | vbi_fmt->flags = V4L2_VBI_UNSYNC; | ||
830 | logs(front); | ||
831 | return 0; | ||
832 | } | ||
833 | |||
834 | static int set_std(struct poseidon *pd, v4l2_std_id *norm) | ||
835 | { | ||
836 | struct video_data *video = &pd->video_data; | ||
837 | struct vbi_data *vbi = &pd->vbi_data; | ||
838 | struct running_context *context; | ||
839 | struct v4l2_pix_format *pix; | ||
840 | s32 i, ret = 0, cmd_status, param; | ||
841 | int height; | ||
842 | |||
843 | for (i = 0; i < POSEIDON_TVNORMS; i++) { | ||
844 | if (*norm & poseidon_tvnorms[i].v4l2_id) { | ||
845 | param = poseidon_tvnorms[i].tlg_tvnorm; | ||
846 | log("name : %s", poseidon_tvnorms[i].name); | ||
847 | goto found; | ||
848 | } | ||
849 | } | ||
850 | return -EINVAL; | ||
851 | found: | ||
852 | mutex_lock(&pd->lock); | ||
853 | ret = send_set_req(pd, VIDEO_STD_SEL, param, &cmd_status); | ||
854 | if (ret || cmd_status) | ||
855 | goto out; | ||
856 | |||
857 | /* Set vbi size and check the height of the frame */ | ||
858 | context = &video->context; | ||
859 | context->tvnormid = poseidon_tvnorms[i].v4l2_id; | ||
860 | if (context->tvnormid & V4L2_STD_525_60) { | ||
861 | vbi->vbi_size = V4L_NTSC_VBI_FRAMESIZE; | ||
862 | height = 480; | ||
863 | } else { | ||
864 | vbi->vbi_size = V4L_PAL_VBI_FRAMESIZE; | ||
865 | height = 576; | ||
866 | } | ||
867 | |||
868 | pix = &context->pix; | ||
869 | if (pix->height != height) { | ||
870 | pix->height = height; | ||
871 | pix->sizeimage = pix->width * pix->height * 2; | ||
872 | } | ||
873 | |||
874 | out: | ||
875 | mutex_unlock(&pd->lock); | ||
876 | return ret; | ||
877 | } | ||
878 | |||
879 | int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *norm) | ||
880 | { | ||
881 | struct front_face *front = fh; | ||
882 | logs(front); | ||
883 | return set_std(front->pd, norm); | ||
884 | } | ||
885 | |||
886 | static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *in) | ||
887 | { | ||
888 | struct front_face *front = fh; | ||
889 | |||
890 | if (in->index < 0 || in->index >= POSEIDON_INPUTS) | ||
891 | return -EINVAL; | ||
892 | strcpy(in->name, pd_inputs[in->index].name); | ||
893 | in->type = V4L2_INPUT_TYPE_TUNER; | ||
894 | |||
895 | /* | ||
896 | * the audio input index mixed with this video input, | ||
897 | * Poseidon only have one audio/video, set to "0" | ||
898 | */ | ||
899 | in->audioset = 0; | ||
900 | in->tuner = 0; | ||
901 | in->std = V4L2_STD_ALL; | ||
902 | in->status = 0; | ||
903 | logs(front); | ||
904 | return 0; | ||
905 | } | ||
906 | |||
907 | static int vidioc_g_input(struct file *file, void *fh, unsigned int *i) | ||
908 | { | ||
909 | struct front_face *front = fh; | ||
910 | struct poseidon *pd = front->pd; | ||
911 | struct running_context *context = &pd->video_data.context; | ||
912 | |||
913 | logs(front); | ||
914 | *i = context->sig_index; | ||
915 | return 0; | ||
916 | } | ||
917 | |||
918 | /* We can support several inputs */ | ||
919 | static int vidioc_s_input(struct file *file, void *fh, unsigned int i) | ||
920 | { | ||
921 | struct front_face *front = fh; | ||
922 | struct poseidon *pd = front->pd; | ||
923 | s32 ret, cmd_status; | ||
924 | |||
925 | if (i < 0 || i >= POSEIDON_INPUTS) | ||
926 | return -EINVAL; | ||
927 | ret = send_set_req(pd, SGNL_SRC_SEL, | ||
928 | pd_inputs[i].tlg_src, &cmd_status); | ||
929 | if (ret) | ||
930 | return ret; | ||
931 | |||
932 | pd->video_data.context.sig_index = i; | ||
933 | return 0; | ||
934 | } | ||
935 | |||
936 | static struct poseidon_control *check_control_id(__u32 id) | ||
937 | { | ||
938 | struct poseidon_control *control = &controls[0]; | ||
939 | int array_size = ARRAY_SIZE(controls); | ||
940 | |||
941 | for (; control < &controls[array_size]; control++) | ||
942 | if (control->v4l2_ctrl.id == id) | ||
943 | return control; | ||
944 | return NULL; | ||
945 | } | ||
946 | |||
947 | static int vidioc_queryctrl(struct file *file, void *fh, | ||
948 | struct v4l2_queryctrl *a) | ||
949 | { | ||
950 | struct poseidon_control *control = NULL; | ||
951 | |||
952 | control = check_control_id(a->id); | ||
953 | if (!control) | ||
954 | return -EINVAL; | ||
955 | |||
956 | *a = control->v4l2_ctrl; | ||
957 | return 0; | ||
958 | } | ||
959 | |||
960 | static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *ctrl) | ||
961 | { | ||
962 | struct front_face *front = fh; | ||
963 | struct poseidon *pd = front->pd; | ||
964 | struct poseidon_control *control = NULL; | ||
965 | struct tuner_custom_parameter_s tuner_param; | ||
966 | s32 ret = 0, cmd_status; | ||
967 | |||
968 | control = check_control_id(ctrl->id); | ||
969 | if (!control) | ||
970 | return -EINVAL; | ||
971 | |||
972 | mutex_lock(&pd->lock); | ||
973 | ret = send_get_req(pd, TUNER_CUSTOM_PARAMETER, control->vc_id, | ||
974 | &tuner_param, &cmd_status, sizeof(tuner_param)); | ||
975 | mutex_unlock(&pd->lock); | ||
976 | |||
977 | if (ret || cmd_status) | ||
978 | return -1; | ||
979 | |||
980 | ctrl->value = tuner_param.param_value; | ||
981 | return 0; | ||
982 | } | ||
983 | |||
984 | static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *a) | ||
985 | { | ||
986 | struct tuner_custom_parameter_s param = {0}; | ||
987 | struct poseidon_control *control = NULL; | ||
988 | struct front_face *front = fh; | ||
989 | struct poseidon *pd = front->pd; | ||
990 | s32 ret = 0, cmd_status, params; | ||
991 | |||
992 | control = check_control_id(a->id); | ||
993 | if (!control) | ||
994 | return -EINVAL; | ||
995 | |||
996 | param.param_value = a->value; | ||
997 | param.param_id = control->vc_id; | ||
998 | params = *(s32 *)¶m; /* temp code */ | ||
999 | |||
1000 | mutex_lock(&pd->lock); | ||
1001 | ret = send_set_req(pd, TUNER_CUSTOM_PARAMETER, params, &cmd_status); | ||
1002 | ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status); | ||
1003 | mutex_unlock(&pd->lock); | ||
1004 | |||
1005 | set_current_state(TASK_INTERRUPTIBLE); | ||
1006 | schedule_timeout(HZ/4); | ||
1007 | return ret; | ||
1008 | } | ||
1009 | |||
1010 | /* Audio ioctls */ | ||
1011 | static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a) | ||
1012 | { | ||
1013 | if (0 != a->index) | ||
1014 | return -EINVAL; | ||
1015 | a->capability = V4L2_AUDCAP_STEREO; | ||
1016 | strcpy(a->name, "USB audio in"); | ||
1017 | /*Poseidon have no AVL function.*/ | ||
1018 | a->mode = 0; | ||
1019 | return 0; | ||
1020 | } | ||
1021 | |||
1022 | int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) | ||
1023 | { | ||
1024 | a->index = 0; | ||
1025 | a->capability = V4L2_AUDCAP_STEREO; | ||
1026 | strcpy(a->name, "USB audio in"); | ||
1027 | a->mode = 0; | ||
1028 | return 0; | ||
1029 | } | ||
1030 | |||
1031 | int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a) | ||
1032 | { | ||
1033 | return (0 == a->index) ? 0 : -EINVAL; | ||
1034 | } | ||
1035 | |||
1036 | /* Tuner ioctls */ | ||
1037 | static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *tuner) | ||
1038 | { | ||
1039 | struct front_face *front = fh; | ||
1040 | struct poseidon *pd = front->pd; | ||
1041 | struct tuner_atv_sig_stat_s atv_stat; | ||
1042 | s32 count = 5, ret, cmd_status; | ||
1043 | int index; | ||
1044 | |||
1045 | if (0 != tuner->index) | ||
1046 | return -EINVAL; | ||
1047 | |||
1048 | mutex_lock(&pd->lock); | ||
1049 | ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_ANALOG_TV, | ||
1050 | &atv_stat, &cmd_status, sizeof(atv_stat)); | ||
1051 | |||
1052 | while (atv_stat.sig_lock_busy && count-- && !ret) { | ||
1053 | set_current_state(TASK_INTERRUPTIBLE); | ||
1054 | schedule_timeout(HZ); | ||
1055 | |||
1056 | ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_ANALOG_TV, | ||
1057 | &atv_stat, &cmd_status, sizeof(atv_stat)); | ||
1058 | } | ||
1059 | mutex_unlock(&pd->lock); | ||
1060 | |||
1061 | if (debug_mode) | ||
1062 | log("P:%d,S:%d", atv_stat.sig_present, atv_stat.sig_strength); | ||
1063 | |||
1064 | if (ret || cmd_status) | ||
1065 | tuner->signal = 0; | ||
1066 | else if (atv_stat.sig_present && !atv_stat.sig_strength) | ||
1067 | tuner->signal = 0xFFFF; | ||
1068 | else | ||
1069 | tuner->signal = (atv_stat.sig_strength * 255 / 10) << 8; | ||
1070 | |||
1071 | strcpy(tuner->name, "Telegent Systems"); | ||
1072 | tuner->type = V4L2_TUNER_ANALOG_TV; | ||
1073 | tuner->rangelow = TUNER_FREQ_MIN / 62500; | ||
1074 | tuner->rangehigh = TUNER_FREQ_MAX / 62500; | ||
1075 | tuner->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | | ||
1076 | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; | ||
1077 | index = pd->video_data.context.audio_idx; | ||
1078 | tuner->rxsubchans = pd_audio_modes[index].v4l2_audio_sub; | ||
1079 | tuner->audmode = pd_audio_modes[index].v4l2_audio_mode; | ||
1080 | tuner->afc = 0; | ||
1081 | logs(front); | ||
1082 | return 0; | ||
1083 | } | ||
1084 | |||
1085 | static int pd_vidioc_s_tuner(struct poseidon *pd, int index) | ||
1086 | { | ||
1087 | s32 ret = 0, cmd_status, param, audiomode; | ||
1088 | |||
1089 | mutex_lock(&pd->lock); | ||
1090 | param = pd_audio_modes[index].tlg_audio_mode; | ||
1091 | ret = send_set_req(pd, TUNER_AUD_MODE, param, &cmd_status); | ||
1092 | audiomode = get_audio_std(pd->video_data.context.tvnormid); | ||
1093 | ret |= send_set_req(pd, TUNER_AUD_ANA_STD, audiomode, | ||
1094 | &cmd_status); | ||
1095 | if (!ret) | ||
1096 | pd->video_data.context.audio_idx = index; | ||
1097 | mutex_unlock(&pd->lock); | ||
1098 | return ret; | ||
1099 | } | ||
1100 | |||
1101 | static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *a) | ||
1102 | { | ||
1103 | struct front_face *front = fh; | ||
1104 | struct poseidon *pd = front->pd; | ||
1105 | int index; | ||
1106 | |||
1107 | if (0 != a->index) | ||
1108 | return -EINVAL; | ||
1109 | logs(front); | ||
1110 | for (index = 0; index < POSEIDON_AUDIOMODS; index++) | ||
1111 | if (a->audmode == pd_audio_modes[index].v4l2_audio_mode) | ||
1112 | return pd_vidioc_s_tuner(pd, index); | ||
1113 | return -EINVAL; | ||
1114 | } | ||
1115 | |||
1116 | static int vidioc_g_frequency(struct file *file, void *fh, | ||
1117 | struct v4l2_frequency *freq) | ||
1118 | { | ||
1119 | struct front_face *front = fh; | ||
1120 | struct poseidon *pd = front->pd; | ||
1121 | struct running_context *context = &pd->video_data.context; | ||
1122 | |||
1123 | if (0 != freq->tuner) | ||
1124 | return -EINVAL; | ||
1125 | freq->frequency = context->freq; | ||
1126 | freq->type = V4L2_TUNER_ANALOG_TV; | ||
1127 | return 0; | ||
1128 | } | ||
1129 | |||
1130 | static int set_frequency(struct poseidon *pd, __u32 frequency) | ||
1131 | { | ||
1132 | s32 ret = 0, param, cmd_status; | ||
1133 | struct running_context *context = &pd->video_data.context; | ||
1134 | |||
1135 | param = frequency * 62500 / 1000; | ||
1136 | if (param < TUNER_FREQ_MIN/1000 || param > TUNER_FREQ_MAX / 1000) | ||
1137 | return -EINVAL; | ||
1138 | |||
1139 | mutex_lock(&pd->lock); | ||
1140 | ret = send_set_req(pd, TUNE_FREQ_SELECT, param, &cmd_status); | ||
1141 | ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status); | ||
1142 | |||
1143 | msleep(250); /* wait for a while until the hardware is ready. */ | ||
1144 | context->freq = frequency; | ||
1145 | mutex_unlock(&pd->lock); | ||
1146 | return ret; | ||
1147 | } | ||
1148 | |||
1149 | static int vidioc_s_frequency(struct file *file, void *fh, | ||
1150 | struct v4l2_frequency *freq) | ||
1151 | { | ||
1152 | struct front_face *front = fh; | ||
1153 | struct poseidon *pd = front->pd; | ||
1154 | |||
1155 | logs(front); | ||
1156 | #ifdef CONFIG_PM | ||
1157 | pd->pm_suspend = pm_video_suspend; | ||
1158 | pd->pm_resume = pm_video_resume; | ||
1159 | #endif | ||
1160 | return set_frequency(pd, freq->frequency); | ||
1161 | } | ||
1162 | |||
1163 | static int vidioc_reqbufs(struct file *file, void *fh, | ||
1164 | struct v4l2_requestbuffers *b) | ||
1165 | { | ||
1166 | struct front_face *front = file->private_data; | ||
1167 | logs(front); | ||
1168 | return videobuf_reqbufs(&front->q, b); | ||
1169 | } | ||
1170 | |||
1171 | static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *b) | ||
1172 | { | ||
1173 | struct front_face *front = file->private_data; | ||
1174 | logs(front); | ||
1175 | return videobuf_querybuf(&front->q, b); | ||
1176 | } | ||
1177 | |||
1178 | static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *b) | ||
1179 | { | ||
1180 | struct front_face *front = file->private_data; | ||
1181 | return videobuf_qbuf(&front->q, b); | ||
1182 | } | ||
1183 | |||
1184 | static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b) | ||
1185 | { | ||
1186 | struct front_face *front = file->private_data; | ||
1187 | return videobuf_dqbuf(&front->q, b, file->f_flags & O_NONBLOCK); | ||
1188 | } | ||
1189 | |||
1190 | /* Just stop the URBs, do not free the URBs */ | ||
1191 | int usb_transfer_stop(struct video_data *video) | ||
1192 | { | ||
1193 | if (video->is_streaming) { | ||
1194 | int i; | ||
1195 | s32 cmd_status; | ||
1196 | struct poseidon *pd = video->pd; | ||
1197 | |||
1198 | video->is_streaming = 0; | ||
1199 | for (i = 0; i < SBUF_NUM; ++i) { | ||
1200 | if (video->urb_array[i]) | ||
1201 | usb_kill_urb(video->urb_array[i]); | ||
1202 | } | ||
1203 | |||
1204 | send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP, | ||
1205 | &cmd_status); | ||
1206 | } | ||
1207 | return 0; | ||
1208 | } | ||
1209 | |||
1210 | int stop_all_video_stream(struct poseidon *pd) | ||
1211 | { | ||
1212 | struct video_data *video = &pd->video_data; | ||
1213 | struct vbi_data *vbi = &pd->vbi_data; | ||
1214 | |||
1215 | mutex_lock(&pd->lock); | ||
1216 | if (video->is_streaming) { | ||
1217 | struct front_face *front = video->front; | ||
1218 | |||
1219 | /* stop the URBs */ | ||
1220 | usb_transfer_stop(video); | ||
1221 | free_all_urb(video); | ||
1222 | |||
1223 | /* stop the host side of VIDEO */ | ||
1224 | videobuf_stop(&front->q); | ||
1225 | videobuf_mmap_free(&front->q); | ||
1226 | |||
1227 | /* stop the host side of VBI */ | ||
1228 | front = vbi->front; | ||
1229 | if (front) { | ||
1230 | videobuf_stop(&front->q); | ||
1231 | videobuf_mmap_free(&front->q); | ||
1232 | } | ||
1233 | } | ||
1234 | mutex_unlock(&pd->lock); | ||
1235 | return 0; | ||
1236 | } | ||
1237 | |||
1238 | /* | ||
1239 | * The bubbles can seriously damage the video's quality, | ||
1240 | * though it occurs in very rare situation. | ||
1241 | */ | ||
1242 | static void iso_bubble_handler(struct work_struct *w) | ||
1243 | { | ||
1244 | struct video_data *video; | ||
1245 | struct poseidon *pd; | ||
1246 | |||
1247 | video = container_of(w, struct video_data, bubble_work); | ||
1248 | pd = video->pd; | ||
1249 | |||
1250 | mutex_lock(&pd->lock); | ||
1251 | usb_transfer_stop(video); | ||
1252 | msleep(500); | ||
1253 | start_video_stream(pd); | ||
1254 | mutex_unlock(&pd->lock); | ||
1255 | } | ||
1256 | |||
1257 | |||
1258 | static int vidioc_streamon(struct file *file, void *fh, | ||
1259 | enum v4l2_buf_type type) | ||
1260 | { | ||
1261 | struct front_face *front = fh; | ||
1262 | |||
1263 | logs(front); | ||
1264 | if (unlikely(type != front->type)) | ||
1265 | return -EINVAL; | ||
1266 | return videobuf_streamon(&front->q); | ||
1267 | } | ||
1268 | |||
1269 | static int vidioc_streamoff(struct file *file, void *fh, | ||
1270 | enum v4l2_buf_type type) | ||
1271 | { | ||
1272 | struct front_face *front = file->private_data; | ||
1273 | |||
1274 | logs(front); | ||
1275 | if (unlikely(type != front->type)) | ||
1276 | return -EINVAL; | ||
1277 | return videobuf_streamoff(&front->q); | ||
1278 | } | ||
1279 | |||
1280 | /* Set the firmware's default values : need altersetting */ | ||
1281 | static int pd_video_checkmode(struct poseidon *pd) | ||
1282 | { | ||
1283 | s32 ret = 0, cmd_status, audiomode; | ||
1284 | |||
1285 | set_current_state(TASK_INTERRUPTIBLE); | ||
1286 | schedule_timeout(HZ/2); | ||
1287 | |||
1288 | /* choose the altersetting */ | ||
1289 | ret = usb_set_interface(pd->udev, 0, | ||
1290 | (pd->cur_transfer_mode ? | ||
1291 | ISO_3K_BULK_ALTERNATE_IFACE : | ||
1292 | BULK_ALTERNATE_IFACE)); | ||
1293 | if (ret < 0) | ||
1294 | goto error; | ||
1295 | |||
1296 | /* set default parameters for PAL-D , with the VBI enabled*/ | ||
1297 | ret = set_tuner_mode(pd, TLG_MODE_ANALOG_TV); | ||
1298 | ret |= send_set_req(pd, SGNL_SRC_SEL, | ||
1299 | TLG_SIG_SRC_ANTENNA, &cmd_status); | ||
1300 | ret |= send_set_req(pd, VIDEO_STD_SEL, | ||
1301 | TLG_TUNE_VSTD_PAL_D, &cmd_status); | ||
1302 | ret |= send_set_req(pd, VIDEO_STREAM_FMT_SEL, | ||
1303 | TLG_TUNER_VID_FORMAT_YUV, &cmd_status); | ||
1304 | ret |= send_set_req(pd, VIDEO_ROSOLU_SEL, | ||
1305 | TLG_TUNE_VID_RES_720, &cmd_status); | ||
1306 | ret |= send_set_req(pd, TUNE_FREQ_SELECT, TUNER_FREQ_MIN, &cmd_status); | ||
1307 | ret |= send_set_req(pd, VBI_DATA_SEL, 1, &cmd_status);/* enable vbi */ | ||
1308 | |||
1309 | /* set the audio */ | ||
1310 | audiomode = get_audio_std(pd->video_data.context.tvnormid); | ||
1311 | ret |= send_set_req(pd, TUNER_AUD_ANA_STD, audiomode, &cmd_status); | ||
1312 | ret |= send_set_req(pd, TUNER_AUD_MODE, | ||
1313 | TLG_TUNE_TVAUDIO_MODE_STEREO, &cmd_status); | ||
1314 | ret |= send_set_req(pd, AUDIO_SAMPLE_RATE_SEL, | ||
1315 | ATV_AUDIO_RATE_48K, &cmd_status); | ||
1316 | error: | ||
1317 | return ret; | ||
1318 | } | ||
1319 | |||
1320 | #ifdef CONFIG_PM | ||
1321 | static int pm_video_suspend(struct poseidon *pd) | ||
1322 | { | ||
1323 | /* stop audio */ | ||
1324 | pm_alsa_suspend(pd); | ||
1325 | |||
1326 | /* stop and free all the URBs */ | ||
1327 | usb_transfer_stop(&pd->video_data); | ||
1328 | free_all_urb(&pd->video_data); | ||
1329 | |||
1330 | /* reset the interface */ | ||
1331 | usb_set_interface(pd->udev, 0, 0); | ||
1332 | msleep(300); | ||
1333 | return 0; | ||
1334 | } | ||
1335 | |||
1336 | static int restore_v4l2_context(struct poseidon *pd, | ||
1337 | struct running_context *context) | ||
1338 | { | ||
1339 | struct front_face *front = pd->video_data.front; | ||
1340 | |||
1341 | pd_video_checkmode(pd); | ||
1342 | |||
1343 | set_std(pd, &context->tvnormid); | ||
1344 | vidioc_s_input(NULL, front, context->sig_index); | ||
1345 | pd_vidioc_s_tuner(pd, context->audio_idx); | ||
1346 | pd_vidioc_s_fmt(pd, &context->pix); | ||
1347 | set_frequency(pd, context->freq); | ||
1348 | return 0; | ||
1349 | } | ||
1350 | |||
1351 | static int pm_video_resume(struct poseidon *pd) | ||
1352 | { | ||
1353 | struct video_data *video = &pd->video_data; | ||
1354 | |||
1355 | /* resume the video */ | ||
1356 | /* [1] restore the origin V4L2 parameters */ | ||
1357 | restore_v4l2_context(pd, &video->context); | ||
1358 | |||
1359 | /* [2] initiate video copy variables */ | ||
1360 | if (video->front->curr_frame) | ||
1361 | init_copy(video, 0); | ||
1362 | |||
1363 | /* [3] fire urbs */ | ||
1364 | start_video_stream(pd); | ||
1365 | |||
1366 | /* resume the audio */ | ||
1367 | pm_alsa_resume(pd); | ||
1368 | return 0; | ||
1369 | } | ||
1370 | #endif | ||
1371 | |||
1372 | void set_debug_mode(struct video_device *vfd, int debug_mode) | ||
1373 | { | ||
1374 | vfd->debug = 0; | ||
1375 | if (debug_mode & 0x1) | ||
1376 | vfd->debug = V4L2_DEBUG_IOCTL; | ||
1377 | if (debug_mode & 0x2) | ||
1378 | vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG; | ||
1379 | } | ||
1380 | |||
1381 | static void init_video_context(struct running_context *context) | ||
1382 | { | ||
1383 | context->sig_index = 0; | ||
1384 | context->audio_idx = 1; /* stereo */ | ||
1385 | context->tvnormid = V4L2_STD_PAL_D; | ||
1386 | context->pix = (struct v4l2_pix_format) { | ||
1387 | .width = 720, | ||
1388 | .height = 576, | ||
1389 | .pixelformat = V4L2_PIX_FMT_YUYV, | ||
1390 | .field = V4L2_FIELD_INTERLACED, | ||
1391 | .bytesperline = 720 * 2, | ||
1392 | .sizeimage = 720 * 576 * 2, | ||
1393 | .colorspace = V4L2_COLORSPACE_SMPTE170M, | ||
1394 | .priv = 0 | ||
1395 | }; | ||
1396 | } | ||
1397 | |||
1398 | static int pd_video_open(struct file *file) | ||
1399 | { | ||
1400 | struct video_device *vfd = video_devdata(file); | ||
1401 | struct poseidon *pd = video_get_drvdata(vfd); | ||
1402 | struct front_face *front = NULL; | ||
1403 | int ret = -ENOMEM; | ||
1404 | |||
1405 | mutex_lock(&pd->lock); | ||
1406 | usb_autopm_get_interface(pd->interface); | ||
1407 | |||
1408 | if (vfd->vfl_type == VFL_TYPE_GRABBER | ||
1409 | && !(pd->state & POSEIDON_STATE_ANALOG)) { | ||
1410 | front = kzalloc(sizeof(struct front_face), GFP_KERNEL); | ||
1411 | if (!front) | ||
1412 | goto out; | ||
1413 | |||
1414 | pd->cur_transfer_mode = usb_transfer_mode;/* bulk or iso */ | ||
1415 | init_video_context(&pd->video_data.context); | ||
1416 | |||
1417 | ret = pd_video_checkmode(pd); | ||
1418 | if (ret < 0) { | ||
1419 | kfree(front); | ||
1420 | ret = -1; | ||
1421 | goto out; | ||
1422 | } | ||
1423 | |||
1424 | pd->state |= POSEIDON_STATE_ANALOG; | ||
1425 | front->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1426 | pd->video_data.users++; | ||
1427 | set_debug_mode(vfd, debug_mode); | ||
1428 | |||
1429 | videobuf_queue_vmalloc_init(&front->q, &pd_video_qops, | ||
1430 | NULL, &front->queue_lock, | ||
1431 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
1432 | V4L2_FIELD_INTERLACED,/* video is interlacd */ | ||
1433 | sizeof(struct videobuf_buffer),/*it's enough*/ | ||
1434 | front); | ||
1435 | } else if (vfd->vfl_type == VFL_TYPE_VBI | ||
1436 | && !(pd->state & POSEIDON_STATE_VBI)) { | ||
1437 | front = kzalloc(sizeof(struct front_face), GFP_KERNEL); | ||
1438 | if (!front) | ||
1439 | goto out; | ||
1440 | |||
1441 | pd->state |= POSEIDON_STATE_VBI; | ||
1442 | front->type = V4L2_BUF_TYPE_VBI_CAPTURE; | ||
1443 | pd->vbi_data.front = front; | ||
1444 | pd->vbi_data.users++; | ||
1445 | |||
1446 | videobuf_queue_vmalloc_init(&front->q, &pd_video_qops, | ||
1447 | NULL, &front->queue_lock, | ||
1448 | V4L2_BUF_TYPE_VBI_CAPTURE, | ||
1449 | V4L2_FIELD_NONE, /* vbi is NONE mode */ | ||
1450 | sizeof(struct videobuf_buffer), | ||
1451 | front); | ||
1452 | } else { | ||
1453 | /* maybe add FM support here */ | ||
1454 | log("other "); | ||
1455 | ret = -EINVAL; | ||
1456 | goto out; | ||
1457 | } | ||
1458 | |||
1459 | front->pd = pd; | ||
1460 | front->curr_frame = NULL; | ||
1461 | INIT_LIST_HEAD(&front->active); | ||
1462 | spin_lock_init(&front->queue_lock); | ||
1463 | |||
1464 | file->private_data = front; | ||
1465 | kref_get(&pd->kref); | ||
1466 | |||
1467 | mutex_unlock(&pd->lock); | ||
1468 | return 0; | ||
1469 | out: | ||
1470 | usb_autopm_put_interface(pd->interface); | ||
1471 | mutex_unlock(&pd->lock); | ||
1472 | return ret; | ||
1473 | } | ||
1474 | |||
1475 | static int pd_video_release(struct file *file) | ||
1476 | { | ||
1477 | struct front_face *front = file->private_data; | ||
1478 | struct poseidon *pd = front->pd; | ||
1479 | s32 cmd_status = 0; | ||
1480 | |||
1481 | logs(front); | ||
1482 | mutex_lock(&pd->lock); | ||
1483 | |||
1484 | if (front->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { | ||
1485 | pd->state &= ~POSEIDON_STATE_ANALOG; | ||
1486 | |||
1487 | /* stop the device, and free the URBs */ | ||
1488 | usb_transfer_stop(&pd->video_data); | ||
1489 | free_all_urb(&pd->video_data); | ||
1490 | |||
1491 | /* stop the firmware */ | ||
1492 | send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP, | ||
1493 | &cmd_status); | ||
1494 | |||
1495 | pd->file_for_stream = NULL; | ||
1496 | pd->video_data.users--; | ||
1497 | } else if (front->type == V4L2_BUF_TYPE_VBI_CAPTURE) { | ||
1498 | pd->state &= ~POSEIDON_STATE_VBI; | ||
1499 | pd->vbi_data.front = NULL; | ||
1500 | pd->vbi_data.users--; | ||
1501 | } | ||
1502 | videobuf_stop(&front->q); | ||
1503 | videobuf_mmap_free(&front->q); | ||
1504 | |||
1505 | usb_autopm_put_interface(pd->interface); | ||
1506 | mutex_unlock(&pd->lock); | ||
1507 | |||
1508 | kfree(front); | ||
1509 | file->private_data = NULL; | ||
1510 | kref_put(&pd->kref, poseidon_delete); | ||
1511 | return 0; | ||
1512 | } | ||
1513 | |||
1514 | static int pd_video_mmap(struct file *file, struct vm_area_struct *vma) | ||
1515 | { | ||
1516 | struct front_face *front = file->private_data; | ||
1517 | return videobuf_mmap_mapper(&front->q, vma); | ||
1518 | } | ||
1519 | |||
1520 | unsigned int pd_video_poll(struct file *file, poll_table *table) | ||
1521 | { | ||
1522 | struct front_face *front = file->private_data; | ||
1523 | return videobuf_poll_stream(file, &front->q, table); | ||
1524 | } | ||
1525 | |||
1526 | ssize_t pd_video_read(struct file *file, char __user *buffer, | ||
1527 | size_t count, loff_t *ppos) | ||
1528 | { | ||
1529 | struct front_face *front = file->private_data; | ||
1530 | return videobuf_read_stream(&front->q, buffer, count, ppos, | ||
1531 | 0, file->f_flags & O_NONBLOCK); | ||
1532 | } | ||
1533 | |||
1534 | /* This struct works for both VIDEO and VBI */ | ||
1535 | static const struct v4l2_file_operations pd_video_fops = { | ||
1536 | .owner = THIS_MODULE, | ||
1537 | .open = pd_video_open, | ||
1538 | .release = pd_video_release, | ||
1539 | .read = pd_video_read, | ||
1540 | .poll = pd_video_poll, | ||
1541 | .mmap = pd_video_mmap, | ||
1542 | .ioctl = video_ioctl2, /* maybe changed in future */ | ||
1543 | }; | ||
1544 | |||
1545 | static const struct v4l2_ioctl_ops pd_video_ioctl_ops = { | ||
1546 | .vidioc_querycap = vidioc_querycap, | ||
1547 | |||
1548 | /* Video format */ | ||
1549 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt, | ||
1550 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt, | ||
1551 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt, | ||
1552 | .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi, /* VBI */ | ||
1553 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt, | ||
1554 | |||
1555 | /* Input */ | ||
1556 | .vidioc_g_input = vidioc_g_input, | ||
1557 | .vidioc_s_input = vidioc_s_input, | ||
1558 | .vidioc_enum_input = vidioc_enum_input, | ||
1559 | |||
1560 | /* Audio ioctls */ | ||
1561 | .vidioc_enumaudio = vidioc_enumaudio, | ||
1562 | .vidioc_g_audio = vidioc_g_audio, | ||
1563 | .vidioc_s_audio = vidioc_s_audio, | ||
1564 | |||
1565 | /* Tuner ioctls */ | ||
1566 | .vidioc_g_tuner = vidioc_g_tuner, | ||
1567 | .vidioc_s_tuner = vidioc_s_tuner, | ||
1568 | .vidioc_s_std = vidioc_s_std, | ||
1569 | .vidioc_g_frequency = vidioc_g_frequency, | ||
1570 | .vidioc_s_frequency = vidioc_s_frequency, | ||
1571 | |||
1572 | /* Buffer handlers */ | ||
1573 | .vidioc_reqbufs = vidioc_reqbufs, | ||
1574 | .vidioc_querybuf = vidioc_querybuf, | ||
1575 | .vidioc_qbuf = vidioc_qbuf, | ||
1576 | .vidioc_dqbuf = vidioc_dqbuf, | ||
1577 | |||
1578 | /* Stream on/off */ | ||
1579 | .vidioc_streamon = vidioc_streamon, | ||
1580 | .vidioc_streamoff = vidioc_streamoff, | ||
1581 | |||
1582 | /* Control handling */ | ||
1583 | .vidioc_queryctrl = vidioc_queryctrl, | ||
1584 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
1585 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
1586 | }; | ||
1587 | |||
1588 | static struct video_device pd_video_template = { | ||
1589 | .name = "Telegent-Video", | ||
1590 | .fops = &pd_video_fops, | ||
1591 | .minor = -1, | ||
1592 | .release = video_device_release, | ||
1593 | .tvnorms = V4L2_STD_ALL, | ||
1594 | .ioctl_ops = &pd_video_ioctl_ops, | ||
1595 | }; | ||
1596 | |||
1597 | struct video_device *vdev_init(struct poseidon *pd, struct video_device *tmp) | ||
1598 | { | ||
1599 | struct video_device *vfd; | ||
1600 | |||
1601 | vfd = video_device_alloc(); | ||
1602 | if (vfd == NULL) | ||
1603 | return NULL; | ||
1604 | *vfd = *tmp; | ||
1605 | vfd->minor = -1; | ||
1606 | vfd->v4l2_dev = &pd->v4l2_dev; | ||
1607 | /*vfd->parent = &(pd->udev->dev); */ | ||
1608 | vfd->release = video_device_release; | ||
1609 | video_set_drvdata(vfd, pd); | ||
1610 | return vfd; | ||
1611 | } | ||
1612 | |||
1613 | void destroy_video_device(struct video_device **v_dev) | ||
1614 | { | ||
1615 | struct video_device *dev = *v_dev; | ||
1616 | |||
1617 | if (dev == NULL) | ||
1618 | return; | ||
1619 | |||
1620 | if (video_is_registered(dev)) | ||
1621 | video_unregister_device(dev); | ||
1622 | else | ||
1623 | video_device_release(dev); | ||
1624 | *v_dev = NULL; | ||
1625 | } | ||
1626 | |||
1627 | void pd_video_exit(struct poseidon *pd) | ||
1628 | { | ||
1629 | struct video_data *video = &pd->video_data; | ||
1630 | struct vbi_data *vbi = &pd->vbi_data; | ||
1631 | |||
1632 | destroy_video_device(&video->v_dev); | ||
1633 | destroy_video_device(&vbi->v_dev); | ||
1634 | log(); | ||
1635 | } | ||
1636 | |||
1637 | int pd_video_init(struct poseidon *pd) | ||
1638 | { | ||
1639 | struct video_data *video = &pd->video_data; | ||
1640 | struct vbi_data *vbi = &pd->vbi_data; | ||
1641 | int ret = -ENOMEM; | ||
1642 | |||
1643 | video->v_dev = vdev_init(pd, &pd_video_template); | ||
1644 | if (video->v_dev == NULL) | ||
1645 | goto out; | ||
1646 | |||
1647 | ret = video_register_device(video->v_dev, VFL_TYPE_GRABBER, -1); | ||
1648 | if (ret != 0) | ||
1649 | goto out; | ||
1650 | |||
1651 | /* VBI uses the same template as video */ | ||
1652 | vbi->v_dev = vdev_init(pd, &pd_video_template); | ||
1653 | if (vbi->v_dev == NULL) { | ||
1654 | ret = -ENOMEM; | ||
1655 | goto out; | ||
1656 | } | ||
1657 | ret = video_register_device(vbi->v_dev, VFL_TYPE_VBI, -1); | ||
1658 | if (ret != 0) | ||
1659 | goto out; | ||
1660 | log("register VIDEO/VBI devices"); | ||
1661 | return 0; | ||
1662 | out: | ||
1663 | log("VIDEO/VBI devices register failed, : %d", ret); | ||
1664 | pd_video_exit(pd); | ||
1665 | return ret; | ||
1666 | } | ||
1667 | |||
diff --git a/drivers/media/video/tlg2300/vendorcmds.h b/drivers/media/video/tlg2300/vendorcmds.h new file mode 100644 index 000000000000..ba6f4ae3b2c2 --- /dev/null +++ b/drivers/media/video/tlg2300/vendorcmds.h | |||
@@ -0,0 +1,243 @@ | |||
1 | #ifndef VENDOR_CMD_H_ | ||
2 | #define VENDOR_CMD_H_ | ||
3 | |||
4 | #define BULK_ALTERNATE_IFACE (2) | ||
5 | #define ISO_3K_BULK_ALTERNATE_IFACE (1) | ||
6 | #define REQ_SET_CMD (0X00) | ||
7 | #define REQ_GET_CMD (0X80) | ||
8 | |||
9 | enum tlg__analog_audio_standard { | ||
10 | TLG_TUNE_ASTD_NONE = 0x00000000, | ||
11 | TLG_TUNE_ASTD_A2 = 0x00000001, | ||
12 | TLG_TUNE_ASTD_NICAM = 0x00000002, | ||
13 | TLG_TUNE_ASTD_EIAJ = 0x00000004, | ||
14 | TLG_TUNE_ASTD_BTSC = 0x00000008, | ||
15 | TLG_TUNE_ASTD_FM_US = 0x00000010, | ||
16 | TLG_TUNE_ASTD_FM_EUR = 0x00000020, | ||
17 | TLG_TUNE_ASTD_ALL = 0x0000003f | ||
18 | }; | ||
19 | |||
20 | /* | ||
21 | * identifiers for Custom Parameter messages. | ||
22 | * @typedef cmd_custom_param_id_t | ||
23 | */ | ||
24 | enum cmd_custom_param_id { | ||
25 | CUST_PARM_ID_NONE = 0x00, | ||
26 | CUST_PARM_ID_BRIGHTNESS_CTRL = 0x01, | ||
27 | CUST_PARM_ID_CONTRAST_CTRL = 0x02, | ||
28 | CUST_PARM_ID_HUE_CTRL = 0x03, | ||
29 | CUST_PARM_ID_SATURATION_CTRL = 0x04, | ||
30 | CUST_PARM_ID_AUDIO_SNR_THRESHOLD = 0x10, | ||
31 | CUST_PARM_ID_AUDIO_AGC_THRESHOLD = 0x11, | ||
32 | CUST_PARM_ID_MAX | ||
33 | }; | ||
34 | |||
35 | struct tuner_custom_parameter_s { | ||
36 | uint16_t param_id; /* Parameter identifier */ | ||
37 | uint16_t param_value; /* Parameter value */ | ||
38 | }; | ||
39 | |||
40 | struct tuner_ber_rate_s { | ||
41 | uint32_t ber_rate; /* BER sample rate in seconds */ | ||
42 | }; | ||
43 | |||
44 | struct tuner_atv_sig_stat_s { | ||
45 | uint32_t sig_present; | ||
46 | uint32_t sig_locked; | ||
47 | uint32_t sig_lock_busy; | ||
48 | uint32_t sig_strength; /* milliDb */ | ||
49 | uint32_t tv_audio_chan; /* mono/stereo/sap*/ | ||
50 | uint32_t mvision_stat; /* macrovision status */ | ||
51 | }; | ||
52 | |||
53 | struct tuner_dtv_sig_stat_s { | ||
54 | uint32_t sig_present; /* Boolean*/ | ||
55 | uint32_t sig_locked; /* Boolean */ | ||
56 | uint32_t sig_lock_busy; /* Boolean (Can this time-out?) */ | ||
57 | uint32_t sig_strength; /* milliDb*/ | ||
58 | }; | ||
59 | |||
60 | struct tuner_fm_sig_stat_s { | ||
61 | uint32_t sig_present; /* Boolean*/ | ||
62 | uint32_t sig_locked; /* Boolean */ | ||
63 | uint32_t sig_lock_busy; /* Boolean */ | ||
64 | uint32_t sig_stereo_mono;/* TBD*/ | ||
65 | uint32_t sig_strength; /* milliDb*/ | ||
66 | }; | ||
67 | |||
68 | enum _tag_tlg_tune_srv_cmd { | ||
69 | TLG_TUNE_PLAY_SVC_START = 1, | ||
70 | TLG_TUNE_PLAY_SVC_STOP | ||
71 | }; | ||
72 | |||
73 | enum _tag_tune_atv_audio_mode_caps { | ||
74 | TLG_TUNE_TVAUDIO_MODE_MONO = 0x00000001, | ||
75 | TLG_TUNE_TVAUDIO_MODE_STEREO = 0x00000002, | ||
76 | TLG_TUNE_TVAUDIO_MODE_LANG_A = 0x00000010,/* Primary language*/ | ||
77 | TLG_TUNE_TVAUDIO_MODE_LANG_B = 0x00000020,/* 2nd avail language*/ | ||
78 | TLG_TUNE_TVAUDIO_MODE_LANG_C = 0x00000040 | ||
79 | }; | ||
80 | |||
81 | |||
82 | enum _tag_tuner_atv_audio_rates { | ||
83 | ATV_AUDIO_RATE_NONE = 0x00,/* Audio not supported*/ | ||
84 | ATV_AUDIO_RATE_32K = 0x01,/* Audio rate = 32 KHz*/ | ||
85 | ATV_AUDIO_RATE_48K = 0x02, /* Audio rate = 48 KHz*/ | ||
86 | ATV_AUDIO_RATE_31_25K = 0x04 /* Audio rate = 31.25KHz */ | ||
87 | }; | ||
88 | |||
89 | enum _tag_tune_atv_vid_res_caps { | ||
90 | TLG_TUNE_VID_RES_NONE = 0x00000000, | ||
91 | TLG_TUNE_VID_RES_720 = 0x00000001, | ||
92 | TLG_TUNE_VID_RES_704 = 0x00000002, | ||
93 | TLG_TUNE_VID_RES_360 = 0x00000004 | ||
94 | }; | ||
95 | |||
96 | enum _tag_tuner_analog_video_format { | ||
97 | TLG_TUNER_VID_FORMAT_YUV = 0x00000001, | ||
98 | TLG_TUNER_VID_FORMAT_YCRCB = 0x00000002, | ||
99 | TLG_TUNER_VID_FORMAT_RGB_565 = 0x00000004, | ||
100 | }; | ||
101 | |||
102 | enum tlg_ext_audio_support { | ||
103 | TLG_EXT_AUDIO_NONE = 0x00,/* No external audio input supported */ | ||
104 | TLG_EXT_AUDIO_LR = 0x01/* LR external audio inputs supported*/ | ||
105 | }; | ||
106 | |||
107 | enum { | ||
108 | TLG_MODE_NONE = 0x00, /* No Mode specified*/ | ||
109 | TLG_MODE_ANALOG_TV = 0x01, /* Analog Television mode*/ | ||
110 | TLG_MODE_ANALOG_TV_UNCOMP = 0x01, /* Analog Television mode*/ | ||
111 | TLG_MODE_ANALOG_TV_COMP = 0x02, /* Analog TV mode (compressed)*/ | ||
112 | TLG_MODE_FM_RADIO = 0x04, /* FM Radio mode*/ | ||
113 | TLG_MODE_DVB_T = 0x08, /* Digital TV (DVB-T)*/ | ||
114 | }; | ||
115 | |||
116 | enum tlg_signal_sources_t { | ||
117 | TLG_SIG_SRC_NONE = 0x00,/* Signal source not specified */ | ||
118 | TLG_SIG_SRC_ANTENNA = 0x01,/* Signal src is: Antenna */ | ||
119 | TLG_SIG_SRC_CABLE = 0x02,/* Signal src is: Coax Cable*/ | ||
120 | TLG_SIG_SRC_SVIDEO = 0x04,/* Signal src is: S_VIDEO */ | ||
121 | TLG_SIG_SRC_COMPOSITE = 0x08 /* Signal src is: Composite Video */ | ||
122 | }; | ||
123 | |||
124 | enum tuner_analog_video_standard { | ||
125 | TLG_TUNE_VSTD_NONE = 0x00000000, | ||
126 | TLG_TUNE_VSTD_NTSC_M = 0x00000001, | ||
127 | TLG_TUNE_VSTD_NTSC_M_J = 0x00000002,/* Japan */ | ||
128 | TLG_TUNE_VSTD_PAL_B = 0x00000010, | ||
129 | TLG_TUNE_VSTD_PAL_D = 0x00000020, | ||
130 | TLG_TUNE_VSTD_PAL_G = 0x00000040, | ||
131 | TLG_TUNE_VSTD_PAL_H = 0x00000080, | ||
132 | TLG_TUNE_VSTD_PAL_I = 0x00000100, | ||
133 | TLG_TUNE_VSTD_PAL_M = 0x00000200, | ||
134 | TLG_TUNE_VSTD_PAL_N = 0x00000400, | ||
135 | TLG_TUNE_VSTD_SECAM_B = 0x00001000, | ||
136 | TLG_TUNE_VSTD_SECAM_D = 0x00002000, | ||
137 | TLG_TUNE_VSTD_SECAM_G = 0x00004000, | ||
138 | TLG_TUNE_VSTD_SECAM_H = 0x00008000, | ||
139 | TLG_TUNE_VSTD_SECAM_K = 0x00010000, | ||
140 | TLG_TUNE_VSTD_SECAM_K1 = 0x00020000, | ||
141 | TLG_TUNE_VSTD_SECAM_L = 0x00040000, | ||
142 | TLG_TUNE_VSTD_SECAM_L1 = 0x00080000, | ||
143 | TLG_TUNE_VSTD_PAL_N_COMBO = 0x00100000 | ||
144 | }; | ||
145 | |||
146 | enum tlg_mode_caps { | ||
147 | TLG_MODE_CAPS_NONE = 0x00, /* No Mode specified */ | ||
148 | TLG_MODE_CAPS_ANALOG_TV_UNCOMP = 0x01, /* Analog TV mode */ | ||
149 | TLG_MODE_CAPS_ANALOG_TV_COMP = 0x02, /* Analog TV (compressed)*/ | ||
150 | TLG_MODE_CAPS_FM_RADIO = 0x04, /* FM Radio mode */ | ||
151 | TLG_MODE_CAPS_DVB_T = 0x08, /* Digital TV (DVB-T) */ | ||
152 | }; | ||
153 | |||
154 | enum poseidon_vendor_cmds { | ||
155 | LAST_CMD_STAT = 0x00, | ||
156 | GET_CHIP_ID = 0x01, | ||
157 | GET_FW_ID = 0x02, | ||
158 | PRODUCT_CAPS = 0x03, | ||
159 | |||
160 | TUNE_MODE_CAP_ATV = 0x10, | ||
161 | TUNE_MODE_CAP_ATVCOMP = 0X10, | ||
162 | TUNE_MODE_CAP_DVBT = 0x10, | ||
163 | TUNE_MODE_CAP_FM = 0x10, | ||
164 | TUNE_MODE_SELECT = 0x11, | ||
165 | TUNE_FREQ_SELECT = 0x12, | ||
166 | SGNL_SRC_SEL = 0x13, | ||
167 | |||
168 | VIDEO_STD_SEL = 0x14, | ||
169 | VIDEO_STREAM_FMT_SEL = 0x15, | ||
170 | VIDEO_ROSOLU_AVAIL = 0x16, | ||
171 | VIDEO_ROSOLU_SEL = 0x17, | ||
172 | VIDEO_CONT_PROTECT = 0x20, | ||
173 | |||
174 | VCR_TIMING_MODSEL = 0x21, | ||
175 | EXT_AUDIO_CAP = 0x22, | ||
176 | EXT_AUDIO_SEL = 0x23, | ||
177 | TEST_PATTERN_SEL = 0x24, | ||
178 | VBI_DATA_SEL = 0x25, | ||
179 | AUDIO_SAMPLE_RATE_CAP = 0x28, | ||
180 | AUDIO_SAMPLE_RATE_SEL = 0x29, | ||
181 | TUNER_AUD_MODE = 0x2a, | ||
182 | TUNER_AUD_MODE_AVAIL = 0x2b, | ||
183 | TUNER_AUD_ANA_STD = 0x2c, | ||
184 | TUNER_CUSTOM_PARAMETER = 0x2f, | ||
185 | |||
186 | DVBT_TUNE_MODE_SEL = 0x30, | ||
187 | DVBT_BANDW_CAP = 0x31, | ||
188 | DVBT_BANDW_SEL = 0x32, | ||
189 | DVBT_GUARD_INTERV_CAP = 0x33, | ||
190 | DVBT_GUARD_INTERV_SEL = 0x34, | ||
191 | DVBT_MODULATION_CAP = 0x35, | ||
192 | DVBT_MODULATION_SEL = 0x36, | ||
193 | DVBT_INNER_FEC_RATE_CAP = 0x37, | ||
194 | DVBT_INNER_FEC_RATE_SEL = 0x38, | ||
195 | DVBT_TRANS_MODE_CAP = 0x39, | ||
196 | DVBT_TRANS_MODE_SEL = 0x3a, | ||
197 | DVBT_SEARCH_RANG = 0x3c, | ||
198 | |||
199 | TUNER_SETUP_ANALOG = 0x40, | ||
200 | TUNER_SETUP_DIGITAL = 0x41, | ||
201 | TUNER_SETUP_FM_RADIO = 0x42, | ||
202 | TAKE_REQUEST = 0x43, /* Take effect of the command */ | ||
203 | PLAY_SERVICE = 0x44, /* Play start or Play stop */ | ||
204 | TUNER_STATUS = 0x45, | ||
205 | TUNE_PROP_DVBT = 0x46, | ||
206 | ERR_RATE_STATS = 0x47, | ||
207 | TUNER_BER_RATE = 0x48, | ||
208 | |||
209 | SCAN_CAPS = 0x50, | ||
210 | SCAN_SETUP = 0x51, | ||
211 | SCAN_SERVICE = 0x52, | ||
212 | SCAN_STATS = 0x53, | ||
213 | |||
214 | PID_SET = 0x58, | ||
215 | PID_UNSET = 0x59, | ||
216 | PID_LIST = 0x5a, | ||
217 | |||
218 | IRD_CAP = 0x60, | ||
219 | IRD_MODE_SEL = 0x61, | ||
220 | IRD_SETUP = 0x62, | ||
221 | |||
222 | PTM_MODE_CAP = 0x70, | ||
223 | PTM_MODE_SEL = 0x71, | ||
224 | PTM_SERVICE = 0x72, | ||
225 | TUNER_REG_SCRIPT = 0x73, | ||
226 | CMD_CHIP_RST = 0x74, | ||
227 | }; | ||
228 | |||
229 | enum tlg_bw { | ||
230 | TLG_BW_5 = 5, | ||
231 | TLG_BW_6 = 6, | ||
232 | TLG_BW_7 = 7, | ||
233 | TLG_BW_8 = 8, | ||
234 | TLG_BW_12 = 12, | ||
235 | TLG_BW_15 = 15 | ||
236 | }; | ||
237 | |||
238 | struct cmd_firmware_vers_s { | ||
239 | uint8_t fw_rev_major; | ||
240 | uint8_t fw_rev_minor; | ||
241 | uint16_t fw_patch; | ||
242 | }; | ||
243 | #endif /* VENDOR_CMD_H_ */ | ||
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 5b3eaa16afd2..c4dab6cfd948 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c | |||
@@ -1078,6 +1078,7 @@ static int tuner_probe(struct i2c_client *client, | |||
1078 | 1078 | ||
1079 | goto register_client; | 1079 | goto register_client; |
1080 | } | 1080 | } |
1081 | kfree(t); | ||
1081 | return -ENODEV; | 1082 | return -ENODEV; |
1082 | case 0x42: | 1083 | case 0x42: |
1083 | case 0x43: | 1084 | case 0x43: |
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index d533ea57e7b1..0a877497b93f 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c | |||
@@ -680,10 +680,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, | |||
680 | tveeprom_info("Hauppauge model %d, rev %s, serial# %d\n", | 680 | tveeprom_info("Hauppauge model %d, rev %s, serial# %d\n", |
681 | tvee->model, tvee->rev_str, tvee->serial_number); | 681 | tvee->model, tvee->rev_str, tvee->serial_number); |
682 | if (tvee->has_MAC_address == 1) | 682 | if (tvee->has_MAC_address == 1) |
683 | tveeprom_info("MAC address is %02X-%02X-%02X-%02X-%02X-%02X\n", | 683 | tveeprom_info("MAC address is %pM\n", tvee->MAC_address); |
684 | tvee->MAC_address[0], tvee->MAC_address[1], | ||
685 | tvee->MAC_address[2], tvee->MAC_address[3], | ||
686 | tvee->MAC_address[4], tvee->MAC_address[5]); | ||
687 | tveeprom_info("tuner model is %s (idx %d, type %d)\n", | 684 | tveeprom_info("tuner model is %s (idx %d, type %d)\n", |
688 | t_name1, tuner1, tvee->tuner_type); | 685 | t_name1, tuner1, tvee->tuner_type); |
689 | tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n", | 686 | tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n", |
diff --git a/drivers/media/video/tvp7002.c b/drivers/media/video/tvp7002.c new file mode 100644 index 000000000000..5a878bca02d4 --- /dev/null +++ b/drivers/media/video/tvp7002.c | |||
@@ -0,0 +1,1187 @@ | |||
1 | /* Texas Instruments Triple 8-/10-BIT 165-/110-MSPS Video and Graphics | ||
2 | * Digitizer with Horizontal PLL registers | ||
3 | * | ||
4 | * Copyright (C) 2009 Texas Instruments Inc | ||
5 | * Author: Santiago Nunez-Corrales <santiago.nunez@ridgerun.com> | ||
6 | * | ||
7 | * This code is partially based upon the TVP5150 driver | ||
8 | * written by Mauro Carvalho Chehab (mchehab@infradead.org), | ||
9 | * the TVP514x driver written by Vaibhav Hiremath <hvaibhav@ti.com> | ||
10 | * and the TVP7002 driver in the TI LSP 2.10.00.14. Revisions by | ||
11 | * Muralidharan Karicheri and Snehaprabha Narnakaje (TI). | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | #include <linux/delay.h> | ||
28 | #include <linux/i2c.h> | ||
29 | #include <linux/videodev2.h> | ||
30 | #include <media/tvp7002.h> | ||
31 | #include <media/v4l2-device.h> | ||
32 | #include <media/v4l2-chip-ident.h> | ||
33 | #include <media/v4l2-common.h> | ||
34 | #include "tvp7002_reg.h" | ||
35 | |||
36 | MODULE_DESCRIPTION("TI TVP7002 Video and Graphics Digitizer driver"); | ||
37 | MODULE_AUTHOR("Santiago Nunez-Corrales <santiago.nunez@ridgerun.com>"); | ||
38 | MODULE_LICENSE("GPL"); | ||
39 | |||
40 | /* Module Name */ | ||
41 | #define TVP7002_MODULE_NAME "tvp7002" | ||
42 | |||
43 | /* I2C retry attempts */ | ||
44 | #define I2C_RETRY_COUNT (5) | ||
45 | |||
46 | /* End of registers */ | ||
47 | #define TVP7002_EOR 0x5c | ||
48 | |||
49 | /* Read write definition for registers */ | ||
50 | #define TVP7002_READ 0 | ||
51 | #define TVP7002_WRITE 1 | ||
52 | #define TVP7002_RESERVED 2 | ||
53 | |||
54 | /* Interlaced vs progressive mask and shift */ | ||
55 | #define TVP7002_IP_SHIFT 5 | ||
56 | #define TVP7002_INPR_MASK (0x01 << TVP7002_IP_SHIFT) | ||
57 | |||
58 | /* Shift for CPL and LPF registers */ | ||
59 | #define TVP7002_CL_SHIFT 8 | ||
60 | #define TVP7002_CL_MASK 0x0f | ||
61 | |||
62 | /* Debug functions */ | ||
63 | static int debug; | ||
64 | module_param(debug, bool, 0644); | ||
65 | MODULE_PARM_DESC(debug, "Debug level (0-2)"); | ||
66 | |||
67 | /* Structure for register values */ | ||
68 | struct i2c_reg_value { | ||
69 | u8 reg; | ||
70 | u8 value; | ||
71 | u8 type; | ||
72 | }; | ||
73 | |||
74 | /* | ||
75 | * Register default values (according to tvp7002 datasheet) | ||
76 | * In the case of read-only registers, the value (0xff) is | ||
77 | * never written. R/W functionality is controlled by the | ||
78 | * writable bit in the register struct definition. | ||
79 | */ | ||
80 | static const struct i2c_reg_value tvp7002_init_default[] = { | ||
81 | { TVP7002_CHIP_REV, 0xff, TVP7002_READ }, | ||
82 | { TVP7002_HPLL_FDBK_DIV_MSBS, 0x67, TVP7002_WRITE }, | ||
83 | { TVP7002_HPLL_FDBK_DIV_LSBS, 0x20, TVP7002_WRITE }, | ||
84 | { TVP7002_HPLL_CRTL, 0xa0, TVP7002_WRITE }, | ||
85 | { TVP7002_HPLL_PHASE_SEL, 0x80, TVP7002_WRITE }, | ||
86 | { TVP7002_CLAMP_START, 0x32, TVP7002_WRITE }, | ||
87 | { TVP7002_CLAMP_W, 0x20, TVP7002_WRITE }, | ||
88 | { TVP7002_HSYNC_OUT_W, 0x60, TVP7002_WRITE }, | ||
89 | { TVP7002_B_FINE_GAIN, 0x00, TVP7002_WRITE }, | ||
90 | { TVP7002_G_FINE_GAIN, 0x00, TVP7002_WRITE }, | ||
91 | { TVP7002_R_FINE_GAIN, 0x00, TVP7002_WRITE }, | ||
92 | { TVP7002_B_FINE_OFF_MSBS, 0x80, TVP7002_WRITE }, | ||
93 | { TVP7002_G_FINE_OFF_MSBS, 0x80, TVP7002_WRITE }, | ||
94 | { TVP7002_R_FINE_OFF_MSBS, 0x80, TVP7002_WRITE }, | ||
95 | { TVP7002_SYNC_CTL_1, 0x20, TVP7002_WRITE }, | ||
96 | { TVP7002_HPLL_AND_CLAMP_CTL, 0x2e, TVP7002_WRITE }, | ||
97 | { TVP7002_SYNC_ON_G_THRS, 0x5d, TVP7002_WRITE }, | ||
98 | { TVP7002_SYNC_SEPARATOR_THRS, 0x47, TVP7002_WRITE }, | ||
99 | { TVP7002_HPLL_PRE_COAST, 0x00, TVP7002_WRITE }, | ||
100 | { TVP7002_HPLL_POST_COAST, 0x00, TVP7002_WRITE }, | ||
101 | { TVP7002_SYNC_DETECT_STAT, 0xff, TVP7002_READ }, | ||
102 | { TVP7002_OUT_FORMATTER, 0x47, TVP7002_WRITE }, | ||
103 | { TVP7002_MISC_CTL_1, 0x01, TVP7002_WRITE }, | ||
104 | { TVP7002_MISC_CTL_2, 0x00, TVP7002_WRITE }, | ||
105 | { TVP7002_MISC_CTL_3, 0x01, TVP7002_WRITE }, | ||
106 | { TVP7002_IN_MUX_SEL_1, 0x00, TVP7002_WRITE }, | ||
107 | { TVP7002_IN_MUX_SEL_2, 0x67, TVP7002_WRITE }, | ||
108 | { TVP7002_B_AND_G_COARSE_GAIN, 0x77, TVP7002_WRITE }, | ||
109 | { TVP7002_R_COARSE_GAIN, 0x07, TVP7002_WRITE }, | ||
110 | { TVP7002_FINE_OFF_LSBS, 0x00, TVP7002_WRITE }, | ||
111 | { TVP7002_B_COARSE_OFF, 0x10, TVP7002_WRITE }, | ||
112 | { TVP7002_G_COARSE_OFF, 0x10, TVP7002_WRITE }, | ||
113 | { TVP7002_R_COARSE_OFF, 0x10, TVP7002_WRITE }, | ||
114 | { TVP7002_HSOUT_OUT_START, 0x08, TVP7002_WRITE }, | ||
115 | { TVP7002_MISC_CTL_4, 0x00, TVP7002_WRITE }, | ||
116 | { TVP7002_B_DGTL_ALC_OUT_LSBS, 0xff, TVP7002_READ }, | ||
117 | { TVP7002_G_DGTL_ALC_OUT_LSBS, 0xff, TVP7002_READ }, | ||
118 | { TVP7002_R_DGTL_ALC_OUT_LSBS, 0xff, TVP7002_READ }, | ||
119 | { TVP7002_AUTO_LVL_CTL_ENABLE, 0x80, TVP7002_WRITE }, | ||
120 | { TVP7002_DGTL_ALC_OUT_MSBS, 0xff, TVP7002_READ }, | ||
121 | { TVP7002_AUTO_LVL_CTL_FILTER, 0x53, TVP7002_WRITE }, | ||
122 | { 0x29, 0x08, TVP7002_RESERVED }, | ||
123 | { TVP7002_FINE_CLAMP_CTL, 0x07, TVP7002_WRITE }, | ||
124 | /* PWR_CTL is controlled only by the probe and reset functions */ | ||
125 | { TVP7002_PWR_CTL, 0x00, TVP7002_RESERVED }, | ||
126 | { TVP7002_ADC_SETUP, 0x50, TVP7002_WRITE }, | ||
127 | { TVP7002_COARSE_CLAMP_CTL, 0x00, TVP7002_WRITE }, | ||
128 | { TVP7002_SOG_CLAMP, 0x80, TVP7002_WRITE }, | ||
129 | { TVP7002_RGB_COARSE_CLAMP_CTL, 0x00, TVP7002_WRITE }, | ||
130 | { TVP7002_SOG_COARSE_CLAMP_CTL, 0x04, TVP7002_WRITE }, | ||
131 | { TVP7002_ALC_PLACEMENT, 0x5a, TVP7002_WRITE }, | ||
132 | { 0x32, 0x18, TVP7002_RESERVED }, | ||
133 | { 0x33, 0x60, TVP7002_RESERVED }, | ||
134 | { TVP7002_MVIS_STRIPPER_W, 0xff, TVP7002_RESERVED }, | ||
135 | { TVP7002_VSYNC_ALGN, 0x10, TVP7002_WRITE }, | ||
136 | { TVP7002_SYNC_BYPASS, 0x00, TVP7002_WRITE }, | ||
137 | { TVP7002_L_FRAME_STAT_LSBS, 0xff, TVP7002_READ }, | ||
138 | { TVP7002_L_FRAME_STAT_MSBS, 0xff, TVP7002_READ }, | ||
139 | { TVP7002_CLK_L_STAT_LSBS, 0xff, TVP7002_READ }, | ||
140 | { TVP7002_CLK_L_STAT_MSBS, 0xff, TVP7002_READ }, | ||
141 | { TVP7002_HSYNC_W, 0xff, TVP7002_READ }, | ||
142 | { TVP7002_VSYNC_W, 0xff, TVP7002_READ }, | ||
143 | { TVP7002_L_LENGTH_TOL, 0x03, TVP7002_WRITE }, | ||
144 | { 0x3e, 0x60, TVP7002_RESERVED }, | ||
145 | { TVP7002_VIDEO_BWTH_CTL, 0x01, TVP7002_WRITE }, | ||
146 | { TVP7002_AVID_START_PIXEL_LSBS, 0x01, TVP7002_WRITE }, | ||
147 | { TVP7002_AVID_START_PIXEL_MSBS, 0x2c, TVP7002_WRITE }, | ||
148 | { TVP7002_AVID_STOP_PIXEL_LSBS, 0x06, TVP7002_WRITE }, | ||
149 | { TVP7002_AVID_STOP_PIXEL_MSBS, 0x2c, TVP7002_WRITE }, | ||
150 | { TVP7002_VBLK_F_0_START_L_OFF, 0x05, TVP7002_WRITE }, | ||
151 | { TVP7002_VBLK_F_1_START_L_OFF, 0x00, TVP7002_WRITE }, | ||
152 | { TVP7002_VBLK_F_0_DURATION, 0x1e, TVP7002_WRITE }, | ||
153 | { TVP7002_VBLK_F_1_DURATION, 0x00, TVP7002_WRITE }, | ||
154 | { TVP7002_FBIT_F_0_START_L_OFF, 0x00, TVP7002_WRITE }, | ||
155 | { TVP7002_FBIT_F_1_START_L_OFF, 0x00, TVP7002_WRITE }, | ||
156 | { TVP7002_YUV_Y_G_COEF_LSBS, 0xe3, TVP7002_WRITE }, | ||
157 | { TVP7002_YUV_Y_G_COEF_MSBS, 0x16, TVP7002_WRITE }, | ||
158 | { TVP7002_YUV_Y_B_COEF_LSBS, 0x4f, TVP7002_WRITE }, | ||
159 | { TVP7002_YUV_Y_B_COEF_MSBS, 0x02, TVP7002_WRITE }, | ||
160 | { TVP7002_YUV_Y_R_COEF_LSBS, 0xce, TVP7002_WRITE }, | ||
161 | { TVP7002_YUV_Y_R_COEF_MSBS, 0x06, TVP7002_WRITE }, | ||
162 | { TVP7002_YUV_U_G_COEF_LSBS, 0xab, TVP7002_WRITE }, | ||
163 | { TVP7002_YUV_U_G_COEF_MSBS, 0xf3, TVP7002_WRITE }, | ||
164 | { TVP7002_YUV_U_B_COEF_LSBS, 0x00, TVP7002_WRITE }, | ||
165 | { TVP7002_YUV_U_B_COEF_MSBS, 0x10, TVP7002_WRITE }, | ||
166 | { TVP7002_YUV_U_R_COEF_LSBS, 0x55, TVP7002_WRITE }, | ||
167 | { TVP7002_YUV_U_R_COEF_MSBS, 0xfc, TVP7002_WRITE }, | ||
168 | { TVP7002_YUV_V_G_COEF_LSBS, 0x78, TVP7002_WRITE }, | ||
169 | { TVP7002_YUV_V_G_COEF_MSBS, 0xf1, TVP7002_WRITE }, | ||
170 | { TVP7002_YUV_V_B_COEF_LSBS, 0x88, TVP7002_WRITE }, | ||
171 | { TVP7002_YUV_V_B_COEF_MSBS, 0xfe, TVP7002_WRITE }, | ||
172 | { TVP7002_YUV_V_R_COEF_LSBS, 0x00, TVP7002_WRITE }, | ||
173 | { TVP7002_YUV_V_R_COEF_MSBS, 0x10, TVP7002_WRITE }, | ||
174 | /* This signals end of register values */ | ||
175 | { TVP7002_EOR, 0xff, TVP7002_RESERVED } | ||
176 | }; | ||
177 | |||
178 | /* Register parameters for 480P */ | ||
179 | static const struct i2c_reg_value tvp7002_parms_480P[] = { | ||
180 | { TVP7002_HPLL_FDBK_DIV_MSBS, 0x35, TVP7002_WRITE }, | ||
181 | { TVP7002_HPLL_FDBK_DIV_LSBS, 0x0a, TVP7002_WRITE }, | ||
182 | { TVP7002_HPLL_CRTL, 0x02, TVP7002_WRITE }, | ||
183 | { TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE }, | ||
184 | { TVP7002_AVID_START_PIXEL_LSBS, 0x91, TVP7002_WRITE }, | ||
185 | { TVP7002_AVID_START_PIXEL_MSBS, 0x00, TVP7002_WRITE }, | ||
186 | { TVP7002_AVID_STOP_PIXEL_LSBS, 0x0B, TVP7002_WRITE }, | ||
187 | { TVP7002_AVID_STOP_PIXEL_MSBS, 0x00, TVP7002_WRITE }, | ||
188 | { TVP7002_VBLK_F_0_START_L_OFF, 0x03, TVP7002_WRITE }, | ||
189 | { TVP7002_VBLK_F_1_START_L_OFF, 0x01, TVP7002_WRITE }, | ||
190 | { TVP7002_VBLK_F_0_DURATION, 0x13, TVP7002_WRITE }, | ||
191 | { TVP7002_VBLK_F_1_DURATION, 0x13, TVP7002_WRITE }, | ||
192 | { TVP7002_ALC_PLACEMENT, 0x18, TVP7002_WRITE }, | ||
193 | { TVP7002_CLAMP_START, 0x06, TVP7002_WRITE }, | ||
194 | { TVP7002_CLAMP_W, 0x10, TVP7002_WRITE }, | ||
195 | { TVP7002_HPLL_PRE_COAST, 0x03, TVP7002_WRITE }, | ||
196 | { TVP7002_HPLL_POST_COAST, 0x03, TVP7002_WRITE }, | ||
197 | { TVP7002_EOR, 0xff, TVP7002_RESERVED } | ||
198 | }; | ||
199 | |||
200 | /* Register parameters for 576P */ | ||
201 | static const struct i2c_reg_value tvp7002_parms_576P[] = { | ||
202 | { TVP7002_HPLL_FDBK_DIV_MSBS, 0x36, TVP7002_WRITE }, | ||
203 | { TVP7002_HPLL_FDBK_DIV_LSBS, 0x00, TVP7002_WRITE }, | ||
204 | { TVP7002_HPLL_CRTL, 0x18, TVP7002_WRITE }, | ||
205 | { TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE }, | ||
206 | { TVP7002_AVID_START_PIXEL_LSBS, 0x9B, TVP7002_WRITE }, | ||
207 | { TVP7002_AVID_START_PIXEL_MSBS, 0x00, TVP7002_WRITE }, | ||
208 | { TVP7002_AVID_STOP_PIXEL_LSBS, 0x0F, TVP7002_WRITE }, | ||
209 | { TVP7002_AVID_STOP_PIXEL_MSBS, 0x00, TVP7002_WRITE }, | ||
210 | { TVP7002_VBLK_F_0_START_L_OFF, 0x00, TVP7002_WRITE }, | ||
211 | { TVP7002_VBLK_F_1_START_L_OFF, 0x00, TVP7002_WRITE }, | ||
212 | { TVP7002_VBLK_F_0_DURATION, 0x2D, TVP7002_WRITE }, | ||
213 | { TVP7002_VBLK_F_1_DURATION, 0x00, TVP7002_WRITE }, | ||
214 | { TVP7002_ALC_PLACEMENT, 0x18, TVP7002_WRITE }, | ||
215 | { TVP7002_CLAMP_START, 0x06, TVP7002_WRITE }, | ||
216 | { TVP7002_CLAMP_W, 0x10, TVP7002_WRITE }, | ||
217 | { TVP7002_HPLL_PRE_COAST, 0x03, TVP7002_WRITE }, | ||
218 | { TVP7002_HPLL_POST_COAST, 0x03, TVP7002_WRITE }, | ||
219 | { TVP7002_EOR, 0xff, TVP7002_RESERVED } | ||
220 | }; | ||
221 | |||
222 | /* Register parameters for 1080I60 */ | ||
223 | static const struct i2c_reg_value tvp7002_parms_1080I60[] = { | ||
224 | { TVP7002_HPLL_FDBK_DIV_MSBS, 0x89, TVP7002_WRITE }, | ||
225 | { TVP7002_HPLL_FDBK_DIV_LSBS, 0x08, TVP7002_WRITE }, | ||
226 | { TVP7002_HPLL_CRTL, 0x98, TVP7002_WRITE }, | ||
227 | { TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE }, | ||
228 | { TVP7002_AVID_START_PIXEL_LSBS, 0x06, TVP7002_WRITE }, | ||
229 | { TVP7002_AVID_START_PIXEL_MSBS, 0x01, TVP7002_WRITE }, | ||
230 | { TVP7002_AVID_STOP_PIXEL_LSBS, 0x8a, TVP7002_WRITE }, | ||
231 | { TVP7002_AVID_STOP_PIXEL_MSBS, 0x08, TVP7002_WRITE }, | ||
232 | { TVP7002_VBLK_F_0_START_L_OFF, 0x02, TVP7002_WRITE }, | ||
233 | { TVP7002_VBLK_F_1_START_L_OFF, 0x02, TVP7002_WRITE }, | ||
234 | { TVP7002_VBLK_F_0_DURATION, 0x16, TVP7002_WRITE }, | ||
235 | { TVP7002_VBLK_F_1_DURATION, 0x17, TVP7002_WRITE }, | ||
236 | { TVP7002_ALC_PLACEMENT, 0x5a, TVP7002_WRITE }, | ||
237 | { TVP7002_CLAMP_START, 0x32, TVP7002_WRITE }, | ||
238 | { TVP7002_CLAMP_W, 0x20, TVP7002_WRITE }, | ||
239 | { TVP7002_HPLL_PRE_COAST, 0x01, TVP7002_WRITE }, | ||
240 | { TVP7002_HPLL_POST_COAST, 0x00, TVP7002_WRITE }, | ||
241 | { TVP7002_EOR, 0xff, TVP7002_RESERVED } | ||
242 | }; | ||
243 | |||
244 | /* Register parameters for 1080P60 */ | ||
245 | static const struct i2c_reg_value tvp7002_parms_1080P60[] = { | ||
246 | { TVP7002_HPLL_FDBK_DIV_MSBS, 0x89, TVP7002_WRITE }, | ||
247 | { TVP7002_HPLL_FDBK_DIV_LSBS, 0x08, TVP7002_WRITE }, | ||
248 | { TVP7002_HPLL_CRTL, 0xE0, TVP7002_WRITE }, | ||
249 | { TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE }, | ||
250 | { TVP7002_AVID_START_PIXEL_LSBS, 0x06, TVP7002_WRITE }, | ||
251 | { TVP7002_AVID_START_PIXEL_MSBS, 0x01, TVP7002_WRITE }, | ||
252 | { TVP7002_AVID_STOP_PIXEL_LSBS, 0x8a, TVP7002_WRITE }, | ||
253 | { TVP7002_AVID_STOP_PIXEL_MSBS, 0x08, TVP7002_WRITE }, | ||
254 | { TVP7002_VBLK_F_0_START_L_OFF, 0x02, TVP7002_WRITE }, | ||
255 | { TVP7002_VBLK_F_1_START_L_OFF, 0x02, TVP7002_WRITE }, | ||
256 | { TVP7002_VBLK_F_0_DURATION, 0x16, TVP7002_WRITE }, | ||
257 | { TVP7002_VBLK_F_1_DURATION, 0x17, TVP7002_WRITE }, | ||
258 | { TVP7002_ALC_PLACEMENT, 0x5a, TVP7002_WRITE }, | ||
259 | { TVP7002_CLAMP_START, 0x32, TVP7002_WRITE }, | ||
260 | { TVP7002_CLAMP_W, 0x20, TVP7002_WRITE }, | ||
261 | { TVP7002_HPLL_PRE_COAST, 0x01, TVP7002_WRITE }, | ||
262 | { TVP7002_HPLL_POST_COAST, 0x00, TVP7002_WRITE }, | ||
263 | { TVP7002_EOR, 0xff, TVP7002_RESERVED } | ||
264 | }; | ||
265 | |||
266 | /* Register parameters for 1080I50 */ | ||
267 | static const struct i2c_reg_value tvp7002_parms_1080I50[] = { | ||
268 | { TVP7002_HPLL_FDBK_DIV_MSBS, 0xa5, TVP7002_WRITE }, | ||
269 | { TVP7002_HPLL_FDBK_DIV_LSBS, 0x00, TVP7002_WRITE }, | ||
270 | { TVP7002_HPLL_CRTL, 0x98, TVP7002_WRITE }, | ||
271 | { TVP7002_HPLL_PHASE_SEL, 0x14, TVP7002_WRITE }, | ||
272 | { TVP7002_AVID_START_PIXEL_LSBS, 0x06, TVP7002_WRITE }, | ||
273 | { TVP7002_AVID_START_PIXEL_MSBS, 0x01, TVP7002_WRITE }, | ||
274 | { TVP7002_AVID_STOP_PIXEL_LSBS, 0x8a, TVP7002_WRITE }, | ||
275 | { TVP7002_AVID_STOP_PIXEL_MSBS, 0x08, TVP7002_WRITE }, | ||
276 | { TVP7002_VBLK_F_0_START_L_OFF, 0x02, TVP7002_WRITE }, | ||
277 | { TVP7002_VBLK_F_1_START_L_OFF, 0x02, TVP7002_WRITE }, | ||
278 | { TVP7002_VBLK_F_0_DURATION, 0x16, TVP7002_WRITE }, | ||
279 | { TVP7002_VBLK_F_1_DURATION, 0x17, TVP7002_WRITE }, | ||
280 | { TVP7002_ALC_PLACEMENT, 0x5a, TVP7002_WRITE }, | ||
281 | { TVP7002_CLAMP_START, 0x32, TVP7002_WRITE }, | ||
282 | { TVP7002_CLAMP_W, 0x20, TVP7002_WRITE }, | ||
283 | { TVP7002_HPLL_PRE_COAST, 0x01, TVP7002_WRITE }, | ||
284 | { TVP7002_HPLL_POST_COAST, 0x00, TVP7002_WRITE }, | ||
285 | { TVP7002_EOR, 0xff, TVP7002_RESERVED } | ||
286 | }; | ||
287 | |||
288 | /* Register parameters for 720P60 */ | ||
289 | static const struct i2c_reg_value tvp7002_parms_720P60[] = { | ||
290 | { TVP7002_HPLL_FDBK_DIV_MSBS, 0x67, TVP7002_WRITE }, | ||
291 | { TVP7002_HPLL_FDBK_DIV_LSBS, 0x02, TVP7002_WRITE }, | ||
292 | { TVP7002_HPLL_CRTL, 0xa0, TVP7002_WRITE }, | ||
293 | { TVP7002_HPLL_PHASE_SEL, 0x16, TVP7002_WRITE }, | ||
294 | { TVP7002_AVID_START_PIXEL_LSBS, 0x47, TVP7002_WRITE }, | ||
295 | { TVP7002_AVID_START_PIXEL_MSBS, 0x01, TVP7002_WRITE }, | ||
296 | { TVP7002_AVID_STOP_PIXEL_LSBS, 0x4B, TVP7002_WRITE }, | ||
297 | { TVP7002_AVID_STOP_PIXEL_MSBS, 0x06, TVP7002_WRITE }, | ||
298 | { TVP7002_VBLK_F_0_START_L_OFF, 0x05, TVP7002_WRITE }, | ||
299 | { TVP7002_VBLK_F_1_START_L_OFF, 0x00, TVP7002_WRITE }, | ||
300 | { TVP7002_VBLK_F_0_DURATION, 0x2D, TVP7002_WRITE }, | ||
301 | { TVP7002_VBLK_F_1_DURATION, 0x00, TVP7002_WRITE }, | ||
302 | { TVP7002_ALC_PLACEMENT, 0x5a, TVP7002_WRITE }, | ||
303 | { TVP7002_CLAMP_START, 0x32, TVP7002_WRITE }, | ||
304 | { TVP7002_CLAMP_W, 0x20, TVP7002_WRITE }, | ||
305 | { TVP7002_HPLL_PRE_COAST, 0x00, TVP7002_WRITE }, | ||
306 | { TVP7002_HPLL_POST_COAST, 0x00, TVP7002_WRITE }, | ||
307 | { TVP7002_EOR, 0xff, TVP7002_RESERVED } | ||
308 | }; | ||
309 | |||
310 | /* Register parameters for 720P50 */ | ||
311 | static const struct i2c_reg_value tvp7002_parms_720P50[] = { | ||
312 | { TVP7002_HPLL_FDBK_DIV_MSBS, 0x7b, TVP7002_WRITE }, | ||
313 | { TVP7002_HPLL_FDBK_DIV_LSBS, 0x0c, TVP7002_WRITE }, | ||
314 | { TVP7002_HPLL_CRTL, 0x98, TVP7002_WRITE }, | ||
315 | { TVP7002_HPLL_PHASE_SEL, 0x16, TVP7002_WRITE }, | ||
316 | { TVP7002_AVID_START_PIXEL_LSBS, 0x47, TVP7002_WRITE }, | ||
317 | { TVP7002_AVID_START_PIXEL_MSBS, 0x01, TVP7002_WRITE }, | ||
318 | { TVP7002_AVID_STOP_PIXEL_LSBS, 0x4B, TVP7002_WRITE }, | ||
319 | { TVP7002_AVID_STOP_PIXEL_MSBS, 0x06, TVP7002_WRITE }, | ||
320 | { TVP7002_VBLK_F_0_START_L_OFF, 0x05, TVP7002_WRITE }, | ||
321 | { TVP7002_VBLK_F_1_START_L_OFF, 0x00, TVP7002_WRITE }, | ||
322 | { TVP7002_VBLK_F_0_DURATION, 0x2D, TVP7002_WRITE }, | ||
323 | { TVP7002_VBLK_F_1_DURATION, 0x00, TVP7002_WRITE }, | ||
324 | { TVP7002_ALC_PLACEMENT, 0x5a, TVP7002_WRITE }, | ||
325 | { TVP7002_CLAMP_START, 0x32, TVP7002_WRITE }, | ||
326 | { TVP7002_CLAMP_W, 0x20, TVP7002_WRITE }, | ||
327 | { TVP7002_HPLL_PRE_COAST, 0x01, TVP7002_WRITE }, | ||
328 | { TVP7002_HPLL_POST_COAST, 0x00, TVP7002_WRITE }, | ||
329 | { TVP7002_EOR, 0xff, TVP7002_RESERVED } | ||
330 | }; | ||
331 | |||
332 | /* Struct list for available formats */ | ||
333 | static const struct v4l2_fmtdesc tvp7002_fmt_list[] = { | ||
334 | { | ||
335 | .index = 0, | ||
336 | .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
337 | .flags = 0, | ||
338 | .description = "8-bit UYVY 4:2:2 Format", | ||
339 | .pixelformat = V4L2_PIX_FMT_UYVY, | ||
340 | }, | ||
341 | }; | ||
342 | |||
343 | #define NUM_FORMATS ARRAY_SIZE(tvp7002_fmt_list) | ||
344 | |||
345 | /* Preset definition for handling device operation */ | ||
346 | struct tvp7002_preset_definition { | ||
347 | u32 preset; | ||
348 | const struct i2c_reg_value *p_settings; | ||
349 | enum v4l2_colorspace color_space; | ||
350 | enum v4l2_field scanmode; | ||
351 | u16 progressive; | ||
352 | u16 lines_per_frame; | ||
353 | u16 cpl_min; | ||
354 | u16 cpl_max; | ||
355 | }; | ||
356 | |||
357 | /* Struct list for digital video presets */ | ||
358 | static const struct tvp7002_preset_definition tvp7002_presets[] = { | ||
359 | { | ||
360 | V4L2_DV_720P60, | ||
361 | tvp7002_parms_720P60, | ||
362 | V4L2_COLORSPACE_REC709, | ||
363 | V4L2_FIELD_NONE, | ||
364 | 1, | ||
365 | 0x2EE, | ||
366 | 135, | ||
367 | 153 | ||
368 | }, | ||
369 | { | ||
370 | V4L2_DV_1080I60, | ||
371 | tvp7002_parms_1080I60, | ||
372 | V4L2_COLORSPACE_REC709, | ||
373 | V4L2_FIELD_INTERLACED, | ||
374 | 0, | ||
375 | 0x465, | ||
376 | 181, | ||
377 | 205 | ||
378 | }, | ||
379 | { | ||
380 | V4L2_DV_1080I50, | ||
381 | tvp7002_parms_1080I50, | ||
382 | V4L2_COLORSPACE_REC709, | ||
383 | V4L2_FIELD_INTERLACED, | ||
384 | 0, | ||
385 | 0x465, | ||
386 | 217, | ||
387 | 245 | ||
388 | }, | ||
389 | { | ||
390 | V4L2_DV_720P50, | ||
391 | tvp7002_parms_720P50, | ||
392 | V4L2_COLORSPACE_REC709, | ||
393 | V4L2_FIELD_NONE, | ||
394 | 1, | ||
395 | 0x2EE, | ||
396 | 163, | ||
397 | 183 | ||
398 | }, | ||
399 | { | ||
400 | V4L2_DV_1080P60, | ||
401 | tvp7002_parms_1080P60, | ||
402 | V4L2_COLORSPACE_REC709, | ||
403 | V4L2_FIELD_NONE, | ||
404 | 1, | ||
405 | 0x465, | ||
406 | 90, | ||
407 | 102 | ||
408 | }, | ||
409 | { | ||
410 | V4L2_DV_480P59_94, | ||
411 | tvp7002_parms_480P, | ||
412 | V4L2_COLORSPACE_SMPTE170M, | ||
413 | V4L2_FIELD_NONE, | ||
414 | 1, | ||
415 | 0x20D, | ||
416 | 0xffff, | ||
417 | 0xffff | ||
418 | }, | ||
419 | { | ||
420 | V4L2_DV_576P50, | ||
421 | tvp7002_parms_576P, | ||
422 | V4L2_COLORSPACE_SMPTE170M, | ||
423 | V4L2_FIELD_NONE, | ||
424 | 1, | ||
425 | 0x271, | ||
426 | 0xffff, | ||
427 | 0xffff | ||
428 | } | ||
429 | }; | ||
430 | |||
431 | #define NUM_PRESETS ARRAY_SIZE(tvp7002_presets) | ||
432 | |||
433 | /* Device definition */ | ||
434 | struct tvp7002 { | ||
435 | struct v4l2_subdev sd; | ||
436 | const struct tvp7002_config *pdata; | ||
437 | |||
438 | int ver; | ||
439 | int streaming; | ||
440 | |||
441 | struct v4l2_pix_format pix; | ||
442 | const struct tvp7002_preset_definition *current_preset; | ||
443 | u8 gain; | ||
444 | }; | ||
445 | |||
446 | /* | ||
447 | * to_tvp7002 - Obtain device handler TVP7002 | ||
448 | * @sd: ptr to v4l2_subdev struct | ||
449 | * | ||
450 | * Returns device handler tvp7002. | ||
451 | */ | ||
452 | static inline struct tvp7002 *to_tvp7002(struct v4l2_subdev *sd) | ||
453 | { | ||
454 | return container_of(sd, struct tvp7002, sd); | ||
455 | } | ||
456 | |||
457 | /* | ||
458 | * tvp7002_read - Read a value from a register in an TVP7002 | ||
459 | * @sd: ptr to v4l2_subdev struct | ||
460 | * @reg: TVP7002 register address | ||
461 | * @dst: pointer to 8-bit destination | ||
462 | * | ||
463 | * Returns value read if successful, or non-zero (-1) otherwise. | ||
464 | */ | ||
465 | static int tvp7002_read(struct v4l2_subdev *sd, u8 addr, u8 *dst) | ||
466 | { | ||
467 | struct i2c_client *c = v4l2_get_subdevdata(sd); | ||
468 | int retry; | ||
469 | int error; | ||
470 | |||
471 | for (retry = 0; retry < I2C_RETRY_COUNT; retry++) { | ||
472 | error = i2c_smbus_read_byte_data(c, addr); | ||
473 | |||
474 | if (error >= 0) { | ||
475 | *dst = (u8)error; | ||
476 | return 0; | ||
477 | } | ||
478 | |||
479 | msleep_interruptible(10); | ||
480 | } | ||
481 | v4l2_err(sd, "TVP7002 read error %d\n", error); | ||
482 | return error; | ||
483 | } | ||
484 | |||
485 | /* | ||
486 | * tvp7002_read_err() - Read a register value with error code | ||
487 | * @sd: pointer to standard V4L2 sub-device structure | ||
488 | * @reg: destination register | ||
489 | * @val: value to be read | ||
490 | * @error: pointer to error value | ||
491 | * | ||
492 | * Read a value in a register and save error value in pointer. | ||
493 | * Also update the register table if successful | ||
494 | */ | ||
495 | static inline void tvp7002_read_err(struct v4l2_subdev *sd, u8 reg, | ||
496 | u8 *dst, int *err) | ||
497 | { | ||
498 | if (!*err) | ||
499 | *err = tvp7002_read(sd, reg, dst); | ||
500 | } | ||
501 | |||
502 | /* | ||
503 | * tvp7002_write() - Write a value to a register in TVP7002 | ||
504 | * @sd: ptr to v4l2_subdev struct | ||
505 | * @addr: TVP7002 register address | ||
506 | * @value: value to be written to the register | ||
507 | * | ||
508 | * Write a value to a register in an TVP7002 decoder device. | ||
509 | * Returns zero if successful, or non-zero otherwise. | ||
510 | */ | ||
511 | static int tvp7002_write(struct v4l2_subdev *sd, u8 addr, u8 value) | ||
512 | { | ||
513 | struct i2c_client *c; | ||
514 | int retry; | ||
515 | int error; | ||
516 | |||
517 | c = v4l2_get_subdevdata(sd); | ||
518 | |||
519 | for (retry = 0; retry < I2C_RETRY_COUNT; retry++) { | ||
520 | error = i2c_smbus_write_byte_data(c, addr, value); | ||
521 | |||
522 | if (error >= 0) | ||
523 | return 0; | ||
524 | |||
525 | v4l2_warn(sd, "Write: retry ... %d\n", retry); | ||
526 | msleep_interruptible(10); | ||
527 | } | ||
528 | v4l2_err(sd, "TVP7002 write error %d\n", error); | ||
529 | return error; | ||
530 | } | ||
531 | |||
532 | /* | ||
533 | * tvp7002_write_err() - Write a register value with error code | ||
534 | * @sd: pointer to standard V4L2 sub-device structure | ||
535 | * @reg: destination register | ||
536 | * @val: value to be written | ||
537 | * @error: pointer to error value | ||
538 | * | ||
539 | * Write a value in a register and save error value in pointer. | ||
540 | * Also update the register table if successful | ||
541 | */ | ||
542 | static inline void tvp7002_write_err(struct v4l2_subdev *sd, u8 reg, | ||
543 | u8 val, int *err) | ||
544 | { | ||
545 | if (!*err) | ||
546 | *err = tvp7002_write(sd, reg, val); | ||
547 | } | ||
548 | |||
549 | /* | ||
550 | * tvp7002_g_chip_ident() - Get chip identification number | ||
551 | * @sd: ptr to v4l2_subdev struct | ||
552 | * @chip: ptr to v4l2_dbg_chip_ident struct | ||
553 | * | ||
554 | * Obtains the chip's identification number. | ||
555 | * Returns zero or -EINVAL if read operation fails. | ||
556 | */ | ||
557 | static int tvp7002_g_chip_ident(struct v4l2_subdev *sd, | ||
558 | struct v4l2_dbg_chip_ident *chip) | ||
559 | { | ||
560 | u8 rev; | ||
561 | int error; | ||
562 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
563 | |||
564 | error = tvp7002_read(sd, TVP7002_CHIP_REV, &rev); | ||
565 | |||
566 | if (error < 0) | ||
567 | return error; | ||
568 | |||
569 | return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TVP7002, rev); | ||
570 | } | ||
571 | |||
572 | /* | ||
573 | * tvp7002_write_inittab() - Write initialization values | ||
574 | * @sd: ptr to v4l2_subdev struct | ||
575 | * @regs: ptr to i2c_reg_value struct | ||
576 | * | ||
577 | * Write initialization values. | ||
578 | * Returns zero or -EINVAL if read operation fails. | ||
579 | */ | ||
580 | static int tvp7002_write_inittab(struct v4l2_subdev *sd, | ||
581 | const struct i2c_reg_value *regs) | ||
582 | { | ||
583 | int error = 0; | ||
584 | |||
585 | /* Initialize the first (defined) registers */ | ||
586 | while (TVP7002_EOR != regs->reg) { | ||
587 | if (TVP7002_WRITE == regs->type) | ||
588 | tvp7002_write_err(sd, regs->reg, regs->value, &error); | ||
589 | regs++; | ||
590 | } | ||
591 | |||
592 | return error; | ||
593 | } | ||
594 | |||
595 | /* | ||
596 | * tvp7002_s_dv_preset() - Set digital video preset | ||
597 | * @sd: ptr to v4l2_subdev struct | ||
598 | * @std: ptr to v4l2_dv_preset struct | ||
599 | * | ||
600 | * Set the digital video preset for a TVP7002 decoder device. | ||
601 | * Returns zero when successful or -EINVAL if register access fails. | ||
602 | */ | ||
603 | static int tvp7002_s_dv_preset(struct v4l2_subdev *sd, | ||
604 | struct v4l2_dv_preset *dv_preset) | ||
605 | { | ||
606 | struct tvp7002 *device = to_tvp7002(sd); | ||
607 | u32 preset; | ||
608 | int i; | ||
609 | |||
610 | for (i = 0; i < NUM_PRESETS; i++) { | ||
611 | preset = tvp7002_presets[i].preset; | ||
612 | if (preset == dv_preset->preset) { | ||
613 | device->current_preset = &tvp7002_presets[i]; | ||
614 | return tvp7002_write_inittab(sd, tvp7002_presets[i].p_settings); | ||
615 | } | ||
616 | } | ||
617 | |||
618 | return -EINVAL; | ||
619 | } | ||
620 | |||
621 | /* | ||
622 | * tvp7002_g_ctrl() - Get a control | ||
623 | * @sd: ptr to v4l2_subdev struct | ||
624 | * @ctrl: ptr to v4l2_control struct | ||
625 | * | ||
626 | * Get a control for a TVP7002 decoder device. | ||
627 | * Returns zero when successful or -EINVAL if register access fails. | ||
628 | */ | ||
629 | static int tvp7002_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
630 | { | ||
631 | struct tvp7002 *device = to_tvp7002(sd); | ||
632 | |||
633 | switch (ctrl->id) { | ||
634 | case V4L2_CID_GAIN: | ||
635 | ctrl->value = device->gain; | ||
636 | return 0; | ||
637 | default: | ||
638 | return -EINVAL; | ||
639 | } | ||
640 | } | ||
641 | |||
642 | /* | ||
643 | * tvp7002_s_ctrl() - Set a control | ||
644 | * @sd: ptr to v4l2_subdev struct | ||
645 | * @ctrl: ptr to v4l2_control struct | ||
646 | * | ||
647 | * Set a control in TVP7002 decoder device. | ||
648 | * Returns zero when successful or -EINVAL if register access fails. | ||
649 | */ | ||
650 | static int tvp7002_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | ||
651 | { | ||
652 | struct tvp7002 *device = to_tvp7002(sd); | ||
653 | int error = 0; | ||
654 | |||
655 | switch (ctrl->id) { | ||
656 | case V4L2_CID_GAIN: | ||
657 | tvp7002_write_err(sd, TVP7002_R_FINE_GAIN, | ||
658 | ctrl->value & 0xff, &error); | ||
659 | tvp7002_write_err(sd, TVP7002_G_FINE_GAIN, | ||
660 | ctrl->value & 0xff, &error); | ||
661 | tvp7002_write_err(sd, TVP7002_B_FINE_GAIN, | ||
662 | ctrl->value & 0xff, &error); | ||
663 | |||
664 | if (error < 0) | ||
665 | return error; | ||
666 | |||
667 | /* Set only after knowing there is no error */ | ||
668 | device->gain = ctrl->value & 0xff; | ||
669 | return 0; | ||
670 | default: | ||
671 | return -EINVAL; | ||
672 | } | ||
673 | } | ||
674 | |||
675 | /* | ||
676 | * tvp7002_queryctrl() - Query a control | ||
677 | * @sd: ptr to v4l2_subdev struct | ||
678 | * @ctrl: ptr to v4l2_queryctrl struct | ||
679 | * | ||
680 | * Query a control of a TVP7002 decoder device. | ||
681 | * Returns zero when successful or -EINVAL if register read fails. | ||
682 | */ | ||
683 | static int tvp7002_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) | ||
684 | { | ||
685 | switch (qc->id) { | ||
686 | case V4L2_CID_GAIN: | ||
687 | /* | ||
688 | * Gain is supported [0-255, default=0, step=1] | ||
689 | */ | ||
690 | return v4l2_ctrl_query_fill(qc, 0, 255, 1, 0); | ||
691 | default: | ||
692 | return -EINVAL; | ||
693 | } | ||
694 | } | ||
695 | |||
696 | /* | ||
697 | * tvp7002_try_fmt_cap() - V4L2 decoder interface handler for try_fmt | ||
698 | * @sd: pointer to standard V4L2 sub-device structure | ||
699 | * @f: pointer to standard V4L2 VIDIOC_TRY_FMT ioctl structure | ||
700 | * | ||
701 | * Implement the VIDIOC_TRY_FMT ioctl for the CAPTURE buffer type. This | ||
702 | * ioctl is used to negotiate the image capture size and pixel format | ||
703 | * without actually making it take effect. | ||
704 | */ | ||
705 | static int tvp7002_try_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f) | ||
706 | { | ||
707 | struct tvp7002 *device = to_tvp7002(sd); | ||
708 | struct v4l2_dv_enum_preset e_preset; | ||
709 | struct v4l2_pix_format *pix; | ||
710 | int error = 0; | ||
711 | |||
712 | pix = &f->fmt.pix; | ||
713 | |||
714 | /* Calculate height and width based on current standard */ | ||
715 | error = v4l_fill_dv_preset_info(device->current_preset->preset, &e_preset); | ||
716 | if (error) | ||
717 | return -EINVAL; | ||
718 | |||
719 | pix->width = e_preset.width; | ||
720 | pix->height = e_preset.height; | ||
721 | pix->pixelformat = V4L2_PIX_FMT_UYVY; | ||
722 | pix->field = device->current_preset->scanmode; | ||
723 | pix->bytesperline = pix->width * 2; | ||
724 | pix->sizeimage = pix->bytesperline * pix->height; | ||
725 | pix->colorspace = device->current_preset->color_space; | ||
726 | pix->priv = 0; | ||
727 | |||
728 | v4l2_dbg(1, debug, sd, "Try FMT: pixelformat - %s, bytesperline - %d" | ||
729 | "Width - %d, Height - %d", "8-bit UYVY 4:2:2 Format", | ||
730 | pix->bytesperline, pix->width, pix->height); | ||
731 | return error; | ||
732 | } | ||
733 | |||
734 | /* | ||
735 | * tvp7002_s_fmt() - V4L2 decoder interface handler for s_fmt | ||
736 | * @sd: pointer to standard V4L2 sub-device structure | ||
737 | * @f: pointer to standard V4L2 VIDIOC_S_FMT ioctl structure | ||
738 | * | ||
739 | * If the requested format is supported, configures the HW to use that | ||
740 | * format, returns error code if format not supported or HW can't be | ||
741 | * correctly configured. | ||
742 | */ | ||
743 | static int tvp7002_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | ||
744 | { | ||
745 | struct tvp7002 *decoder = to_tvp7002(sd); | ||
746 | int rval; | ||
747 | |||
748 | rval = tvp7002_try_fmt_cap(sd, f); | ||
749 | if (!rval) | ||
750 | decoder->pix = f->fmt.pix; | ||
751 | return rval; | ||
752 | } | ||
753 | |||
754 | /* | ||
755 | * tvp7002_g_fmt() - V4L2 decoder interface handler for tvp7002_g_fmt | ||
756 | * @sd: pointer to standard V4L2 sub-device structure | ||
757 | * @f: pointer to standard V4L2 v4l2_format structure | ||
758 | * | ||
759 | * Returns the decoder's current pixel format in the v4l2_format | ||
760 | * parameter. | ||
761 | */ | ||
762 | static int tvp7002_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | ||
763 | { | ||
764 | struct tvp7002 *decoder = to_tvp7002(sd); | ||
765 | |||
766 | f->fmt.pix = decoder->pix; | ||
767 | |||
768 | v4l2_dbg(1, debug, sd, "Current FMT: bytesperline - %d" | ||
769 | "Width - %d, Height - %d", | ||
770 | decoder->pix.bytesperline, | ||
771 | decoder->pix.width, decoder->pix.height); | ||
772 | return 0; | ||
773 | } | ||
774 | |||
775 | /* | ||
776 | * tvp7002_query_dv_preset() - query DV preset | ||
777 | * @sd: pointer to standard V4L2 sub-device structure | ||
778 | * @std_id: standard V4L2 v4l2_dv_preset | ||
779 | * | ||
780 | * Returns the current DV preset by TVP7002. If no active input is | ||
781 | * detected, returns -EINVAL | ||
782 | */ | ||
783 | static int tvp7002_query_dv_preset(struct v4l2_subdev *sd, | ||
784 | struct v4l2_dv_preset *qpreset) | ||
785 | { | ||
786 | const struct tvp7002_preset_definition *presets = tvp7002_presets; | ||
787 | struct v4l2_dv_enum_preset e_preset; | ||
788 | struct tvp7002 *device; | ||
789 | u8 progressive; | ||
790 | u32 lpfr; | ||
791 | u32 cpln; | ||
792 | int error = 0; | ||
793 | u8 lpf_lsb; | ||
794 | u8 lpf_msb; | ||
795 | u8 cpl_lsb; | ||
796 | u8 cpl_msb; | ||
797 | int index; | ||
798 | |||
799 | device = to_tvp7002(sd); | ||
800 | |||
801 | /* Read standards from device registers */ | ||
802 | tvp7002_read_err(sd, TVP7002_L_FRAME_STAT_LSBS, &lpf_lsb, &error); | ||
803 | tvp7002_read_err(sd, TVP7002_L_FRAME_STAT_MSBS, &lpf_msb, &error); | ||
804 | |||
805 | if (error < 0) | ||
806 | return error; | ||
807 | |||
808 | tvp7002_read_err(sd, TVP7002_CLK_L_STAT_LSBS, &cpl_lsb, &error); | ||
809 | tvp7002_read_err(sd, TVP7002_CLK_L_STAT_MSBS, &cpl_msb, &error); | ||
810 | |||
811 | if (error < 0) | ||
812 | return error; | ||
813 | |||
814 | /* Get lines per frame, clocks per line and interlaced/progresive */ | ||
815 | lpfr = lpf_lsb | ((TVP7002_CL_MASK & lpf_msb) << TVP7002_CL_SHIFT); | ||
816 | cpln = cpl_lsb | ((TVP7002_CL_MASK & cpl_msb) << TVP7002_CL_SHIFT); | ||
817 | progressive = (lpf_msb & TVP7002_INPR_MASK) >> TVP7002_IP_SHIFT; | ||
818 | |||
819 | /* Do checking of video modes */ | ||
820 | for (index = 0; index < NUM_PRESETS; index++, presets++) | ||
821 | if (lpfr == presets->lines_per_frame && | ||
822 | progressive == presets->progressive) { | ||
823 | if (presets->cpl_min == 0xffff) | ||
824 | break; | ||
825 | if (cpln >= presets->cpl_min && cpln <= presets->cpl_max) | ||
826 | break; | ||
827 | } | ||
828 | |||
829 | if (index == NUM_PRESETS) { | ||
830 | v4l2_err(sd, "querystd error, lpf = %x, cpl = %x\n", | ||
831 | lpfr, cpln); | ||
832 | return -EINVAL; | ||
833 | } | ||
834 | |||
835 | if (v4l_fill_dv_preset_info(presets->preset, &e_preset)) | ||
836 | return -EINVAL; | ||
837 | |||
838 | /* Set values in found preset */ | ||
839 | qpreset->preset = presets->preset; | ||
840 | |||
841 | /* Update lines per frame and clocks per line info */ | ||
842 | v4l2_dbg(1, debug, sd, "Current preset: %d %d", | ||
843 | e_preset.width, e_preset.height); | ||
844 | return 0; | ||
845 | } | ||
846 | |||
847 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
848 | /* | ||
849 | * tvp7002_g_register() - Get the value of a register | ||
850 | * @sd: ptr to v4l2_subdev struct | ||
851 | * @vreg: ptr to v4l2_dbg_register struct | ||
852 | * | ||
853 | * Get the value of a TVP7002 decoder device register. | ||
854 | * Returns zero when successful, -EINVAL if register read fails or | ||
855 | * access to I2C client fails, -EPERM if the call is not allowed | ||
856 | * by diabled CAP_SYS_ADMIN. | ||
857 | */ | ||
858 | static int tvp7002_g_register(struct v4l2_subdev *sd, | ||
859 | struct v4l2_dbg_register *reg) | ||
860 | { | ||
861 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
862 | u8 val; | ||
863 | int ret; | ||
864 | |||
865 | if (!v4l2_chip_match_i2c_client(client, ®->match)) | ||
866 | return -EINVAL; | ||
867 | if (!capable(CAP_SYS_ADMIN)) | ||
868 | return -EPERM; | ||
869 | |||
870 | ret = tvp7002_read(sd, reg->reg & 0xff, &val); | ||
871 | reg->val = val; | ||
872 | return ret; | ||
873 | } | ||
874 | |||
875 | /* | ||
876 | * tvp7002_s_register() - set a control | ||
877 | * @sd: ptr to v4l2_subdev struct | ||
878 | * @ctrl: ptr to v4l2_control struct | ||
879 | * | ||
880 | * Get the value of a TVP7002 decoder device register. | ||
881 | * Returns zero when successful, -EINVAL if register read fails or | ||
882 | * -EPERM if call not allowed. | ||
883 | */ | ||
884 | static int tvp7002_s_register(struct v4l2_subdev *sd, | ||
885 | struct v4l2_dbg_register *reg) | ||
886 | { | ||
887 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
888 | |||
889 | if (!v4l2_chip_match_i2c_client(client, ®->match)) | ||
890 | return -EINVAL; | ||
891 | if (!capable(CAP_SYS_ADMIN)) | ||
892 | return -EPERM; | ||
893 | |||
894 | return tvp7002_write(sd, reg->reg & 0xff, reg->val & 0xff); | ||
895 | } | ||
896 | #endif | ||
897 | |||
898 | /* | ||
899 | * tvp7002_enum_fmt() - Enum supported formats | ||
900 | * @sd: pointer to standard V4L2 sub-device structure | ||
901 | * @enable: pointer to format struct | ||
902 | * | ||
903 | * Enumerate supported formats. | ||
904 | */ | ||
905 | |||
906 | static int tvp7002_enum_fmt(struct v4l2_subdev *sd, | ||
907 | struct v4l2_fmtdesc *fmtdesc) | ||
908 | { | ||
909 | /* Check requested format index is within range */ | ||
910 | if (fmtdesc->index < 0 || fmtdesc->index >= NUM_FORMATS) | ||
911 | return -EINVAL; | ||
912 | *fmtdesc = tvp7002_fmt_list[fmtdesc->index]; | ||
913 | |||
914 | return 0; | ||
915 | } | ||
916 | |||
917 | /* | ||
918 | * tvp7002_s_stream() - V4L2 decoder i/f handler for s_stream | ||
919 | * @sd: pointer to standard V4L2 sub-device structure | ||
920 | * @enable: streaming enable or disable | ||
921 | * | ||
922 | * Sets streaming to enable or disable, if possible. | ||
923 | */ | ||
924 | static int tvp7002_s_stream(struct v4l2_subdev *sd, int enable) | ||
925 | { | ||
926 | struct tvp7002 *device = to_tvp7002(sd); | ||
927 | int error = 0; | ||
928 | |||
929 | if (device->streaming == enable) | ||
930 | return 0; | ||
931 | |||
932 | if (enable) { | ||
933 | /* Set output state on (low impedance means stream on) */ | ||
934 | error = tvp7002_write(sd, TVP7002_MISC_CTL_2, 0x00); | ||
935 | device->streaming = enable; | ||
936 | } else { | ||
937 | /* Set output state off (high impedance means stream off) */ | ||
938 | error = tvp7002_write(sd, TVP7002_MISC_CTL_2, 0x03); | ||
939 | if (error) | ||
940 | v4l2_dbg(1, debug, sd, "Unable to stop streaming\n"); | ||
941 | |||
942 | device->streaming = enable; | ||
943 | } | ||
944 | |||
945 | return error; | ||
946 | } | ||
947 | |||
948 | /* | ||
949 | * tvp7002_log_status() - Print information about register settings | ||
950 | * @sd: ptr to v4l2_subdev struct | ||
951 | * | ||
952 | * Log register values of a TVP7002 decoder device. | ||
953 | * Returns zero or -EINVAL if read operation fails. | ||
954 | */ | ||
955 | static int tvp7002_log_status(struct v4l2_subdev *sd) | ||
956 | { | ||
957 | const struct tvp7002_preset_definition *presets = tvp7002_presets; | ||
958 | struct tvp7002 *device = to_tvp7002(sd); | ||
959 | struct v4l2_dv_enum_preset e_preset; | ||
960 | struct v4l2_dv_preset detected; | ||
961 | int i; | ||
962 | |||
963 | detected.preset = V4L2_DV_INVALID; | ||
964 | /* Find my current standard*/ | ||
965 | tvp7002_query_dv_preset(sd, &detected); | ||
966 | |||
967 | /* Print standard related code values */ | ||
968 | for (i = 0; i < NUM_PRESETS; i++, presets++) | ||
969 | if (presets->preset == detected.preset) | ||
970 | break; | ||
971 | |||
972 | if (v4l_fill_dv_preset_info(device->current_preset->preset, &e_preset)) | ||
973 | return -EINVAL; | ||
974 | |||
975 | v4l2_info(sd, "Selected DV Preset: %s\n", e_preset.name); | ||
976 | v4l2_info(sd, " Pixels per line: %u\n", e_preset.width); | ||
977 | v4l2_info(sd, " Lines per frame: %u\n\n", e_preset.height); | ||
978 | if (i == NUM_PRESETS) { | ||
979 | v4l2_info(sd, "Detected DV Preset: None\n"); | ||
980 | } else { | ||
981 | if (v4l_fill_dv_preset_info(presets->preset, &e_preset)) | ||
982 | return -EINVAL; | ||
983 | v4l2_info(sd, "Detected DV Preset: %s\n", e_preset.name); | ||
984 | v4l2_info(sd, " Pixels per line: %u\n", e_preset.width); | ||
985 | v4l2_info(sd, " Lines per frame: %u\n\n", e_preset.height); | ||
986 | } | ||
987 | v4l2_info(sd, "Streaming enabled: %s\n", | ||
988 | device->streaming ? "yes" : "no"); | ||
989 | |||
990 | /* Print the current value of the gain control */ | ||
991 | v4l2_info(sd, "Gain: %u\n", device->gain); | ||
992 | |||
993 | return 0; | ||
994 | } | ||
995 | |||
996 | /* V4L2 core operation handlers */ | ||
997 | static const struct v4l2_subdev_core_ops tvp7002_core_ops = { | ||
998 | .g_chip_ident = tvp7002_g_chip_ident, | ||
999 | .log_status = tvp7002_log_status, | ||
1000 | .g_ctrl = tvp7002_g_ctrl, | ||
1001 | .s_ctrl = tvp7002_s_ctrl, | ||
1002 | .queryctrl = tvp7002_queryctrl, | ||
1003 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1004 | .g_register = tvp7002_g_register, | ||
1005 | .s_register = tvp7002_s_register, | ||
1006 | #endif | ||
1007 | }; | ||
1008 | |||
1009 | /* Specific video subsystem operation handlers */ | ||
1010 | static const struct v4l2_subdev_video_ops tvp7002_video_ops = { | ||
1011 | .s_dv_preset = tvp7002_s_dv_preset, | ||
1012 | .query_dv_preset = tvp7002_query_dv_preset, | ||
1013 | .s_stream = tvp7002_s_stream, | ||
1014 | .g_fmt = tvp7002_g_fmt, | ||
1015 | .s_fmt = tvp7002_s_fmt, | ||
1016 | .enum_fmt = tvp7002_enum_fmt, | ||
1017 | }; | ||
1018 | |||
1019 | /* V4L2 top level operation handlers */ | ||
1020 | static const struct v4l2_subdev_ops tvp7002_ops = { | ||
1021 | .core = &tvp7002_core_ops, | ||
1022 | .video = &tvp7002_video_ops, | ||
1023 | }; | ||
1024 | |||
1025 | static struct tvp7002 tvp7002_dev = { | ||
1026 | .streaming = 0, | ||
1027 | |||
1028 | .pix = { | ||
1029 | .width = 1280, | ||
1030 | .height = 720, | ||
1031 | .pixelformat = V4L2_PIX_FMT_UYVY, | ||
1032 | .field = V4L2_FIELD_NONE, | ||
1033 | .bytesperline = 1280 * 2, | ||
1034 | .sizeimage = 1280 * 2 * 720, | ||
1035 | .colorspace = V4L2_COLORSPACE_REC709, | ||
1036 | }, | ||
1037 | |||
1038 | .current_preset = tvp7002_presets, | ||
1039 | .gain = 0, | ||
1040 | }; | ||
1041 | |||
1042 | /* | ||
1043 | * tvp7002_probe - Probe a TVP7002 device | ||
1044 | * @sd: ptr to v4l2_subdev struct | ||
1045 | * @ctrl: ptr to i2c_device_id struct | ||
1046 | * | ||
1047 | * Initialize the TVP7002 device | ||
1048 | * Returns zero when successful, -EINVAL if register read fails or | ||
1049 | * -EIO if i2c access is not available. | ||
1050 | */ | ||
1051 | static int tvp7002_probe(struct i2c_client *c, const struct i2c_device_id *id) | ||
1052 | { | ||
1053 | struct v4l2_subdev *sd; | ||
1054 | struct tvp7002 *device; | ||
1055 | struct v4l2_dv_preset preset; | ||
1056 | int polarity_a; | ||
1057 | int polarity_b; | ||
1058 | u8 revision; | ||
1059 | |||
1060 | int error; | ||
1061 | |||
1062 | /* Check if the adapter supports the needed features */ | ||
1063 | if (!i2c_check_functionality(c->adapter, | ||
1064 | I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) | ||
1065 | return -EIO; | ||
1066 | |||
1067 | if (!c->dev.platform_data) { | ||
1068 | v4l_err(c, "No platform data!!\n"); | ||
1069 | return -ENODEV; | ||
1070 | } | ||
1071 | |||
1072 | device = kmalloc(sizeof(struct tvp7002), GFP_KERNEL); | ||
1073 | |||
1074 | if (!device) | ||
1075 | return -ENOMEM; | ||
1076 | |||
1077 | *device = tvp7002_dev; | ||
1078 | sd = &device->sd; | ||
1079 | device->pdata = c->dev.platform_data; | ||
1080 | |||
1081 | /* Tell v4l2 the device is ready */ | ||
1082 | v4l2_i2c_subdev_init(sd, c, &tvp7002_ops); | ||
1083 | v4l_info(c, "tvp7002 found @ 0x%02x (%s)\n", | ||
1084 | c->addr, c->adapter->name); | ||
1085 | |||
1086 | error = tvp7002_read(sd, TVP7002_CHIP_REV, &revision); | ||
1087 | if (error < 0) | ||
1088 | goto found_error; | ||
1089 | |||
1090 | /* Get revision number */ | ||
1091 | v4l2_info(sd, "Rev. %02x detected.\n", revision); | ||
1092 | if (revision != 0x02) | ||
1093 | v4l2_info(sd, "Unknown revision detected.\n"); | ||
1094 | |||
1095 | /* Initializes TVP7002 to its default values */ | ||
1096 | error = tvp7002_write_inittab(sd, tvp7002_init_default); | ||
1097 | |||
1098 | if (error < 0) | ||
1099 | goto found_error; | ||
1100 | |||
1101 | /* Set polarity information after registers have been set */ | ||
1102 | polarity_a = 0x20 | device->pdata->hs_polarity << 5 | ||
1103 | | device->pdata->vs_polarity << 2; | ||
1104 | error = tvp7002_write(sd, TVP7002_SYNC_CTL_1, polarity_a); | ||
1105 | if (error < 0) | ||
1106 | goto found_error; | ||
1107 | |||
1108 | polarity_b = 0x01 | device->pdata->fid_polarity << 2 | ||
1109 | | device->pdata->sog_polarity << 1 | ||
1110 | | device->pdata->clk_polarity; | ||
1111 | error = tvp7002_write(sd, TVP7002_MISC_CTL_3, polarity_b); | ||
1112 | if (error < 0) | ||
1113 | goto found_error; | ||
1114 | |||
1115 | /* Set registers according to default video mode */ | ||
1116 | preset.preset = device->current_preset->preset; | ||
1117 | error = tvp7002_s_dv_preset(sd, &preset); | ||
1118 | |||
1119 | found_error: | ||
1120 | if (error < 0) | ||
1121 | kfree(device); | ||
1122 | |||
1123 | return error; | ||
1124 | } | ||
1125 | |||
1126 | /* | ||
1127 | * tvp7002_remove - Remove TVP7002 device support | ||
1128 | * @c: ptr to i2c_client struct | ||
1129 | * | ||
1130 | * Reset the TVP7002 device | ||
1131 | * Returns zero. | ||
1132 | */ | ||
1133 | static int tvp7002_remove(struct i2c_client *c) | ||
1134 | { | ||
1135 | struct v4l2_subdev *sd = i2c_get_clientdata(c); | ||
1136 | struct tvp7002 *device = to_tvp7002(sd); | ||
1137 | |||
1138 | v4l2_dbg(1, debug, sd, "Removing tvp7002 adapter" | ||
1139 | "on address 0x%x\n", c->addr); | ||
1140 | |||
1141 | v4l2_device_unregister_subdev(sd); | ||
1142 | kfree(device); | ||
1143 | return 0; | ||
1144 | } | ||
1145 | |||
1146 | /* I2C Device ID table */ | ||
1147 | static const struct i2c_device_id tvp7002_id[] = { | ||
1148 | { "tvp7002", 0 }, | ||
1149 | { } | ||
1150 | }; | ||
1151 | MODULE_DEVICE_TABLE(i2c, tvp7002_id); | ||
1152 | |||
1153 | /* I2C driver data */ | ||
1154 | static struct i2c_driver tvp7002_driver = { | ||
1155 | .driver = { | ||
1156 | .owner = THIS_MODULE, | ||
1157 | .name = TVP7002_MODULE_NAME, | ||
1158 | }, | ||
1159 | .probe = tvp7002_probe, | ||
1160 | .remove = tvp7002_remove, | ||
1161 | .id_table = tvp7002_id, | ||
1162 | }; | ||
1163 | |||
1164 | /* | ||
1165 | * tvp7002_init - Initialize driver via I2C interface | ||
1166 | * | ||
1167 | * Register the TVP7002 driver. | ||
1168 | * Return 0 on success or error code on failure. | ||
1169 | */ | ||
1170 | static int __init tvp7002_init(void) | ||
1171 | { | ||
1172 | return i2c_add_driver(&tvp7002_driver); | ||
1173 | } | ||
1174 | |||
1175 | /* | ||
1176 | * tvp7002_exit - Remove driver via I2C interface | ||
1177 | * | ||
1178 | * Unregister the TVP7002 driver. | ||
1179 | * Returns nothing. | ||
1180 | */ | ||
1181 | static void __exit tvp7002_exit(void) | ||
1182 | { | ||
1183 | i2c_del_driver(&tvp7002_driver); | ||
1184 | } | ||
1185 | |||
1186 | module_init(tvp7002_init); | ||
1187 | module_exit(tvp7002_exit); | ||
diff --git a/drivers/media/video/tvp7002_reg.h b/drivers/media/video/tvp7002_reg.h new file mode 100644 index 000000000000..0e34ca9bccf3 --- /dev/null +++ b/drivers/media/video/tvp7002_reg.h | |||
@@ -0,0 +1,150 @@ | |||
1 | /* Texas Instruments Triple 8-/10-BIT 165-/110-MSPS Video and Graphics | ||
2 | * Digitizer with Horizontal PLL registers | ||
3 | * | ||
4 | * Copyright (C) 2009 Texas Instruments Inc | ||
5 | * Author: Santiago Nunez-Corrales <santiago.nunez@ridgerun.com> | ||
6 | * | ||
7 | * This code is partially based upon the TVP5150 driver | ||
8 | * written by Mauro Carvalho Chehab (mchehab@infradead.org), | ||
9 | * the TVP514x driver written by Vaibhav Hiremath <hvaibhav@ti.com> | ||
10 | * and the TVP7002 driver in the TI LSP 2.10.00.14 | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | /* Naming conventions | ||
28 | * ------------------ | ||
29 | * | ||
30 | * FDBK: Feedback | ||
31 | * DIV: Divider | ||
32 | * CTL: Control | ||
33 | * SEL: Select | ||
34 | * IN: Input | ||
35 | * OUT: Output | ||
36 | * R: Red | ||
37 | * G: Green | ||
38 | * B: Blue | ||
39 | * OFF: Offset | ||
40 | * THRS: Threshold | ||
41 | * DGTL: Digital | ||
42 | * LVL: Level | ||
43 | * PWR: Power | ||
44 | * MVIS: Macrovision | ||
45 | * W: Width | ||
46 | * H: Height | ||
47 | * ALGN: Alignment | ||
48 | * CLK: Clocks | ||
49 | * TOL: Tolerance | ||
50 | * BWTH: Bandwidth | ||
51 | * COEF: Coefficient | ||
52 | * STAT: Status | ||
53 | * AUTO: Automatic | ||
54 | * FLD: Field | ||
55 | * L: Line | ||
56 | */ | ||
57 | |||
58 | #define TVP7002_CHIP_REV 0x00 | ||
59 | #define TVP7002_HPLL_FDBK_DIV_MSBS 0x01 | ||
60 | #define TVP7002_HPLL_FDBK_DIV_LSBS 0x02 | ||
61 | #define TVP7002_HPLL_CRTL 0x03 | ||
62 | #define TVP7002_HPLL_PHASE_SEL 0x04 | ||
63 | #define TVP7002_CLAMP_START 0x05 | ||
64 | #define TVP7002_CLAMP_W 0x06 | ||
65 | #define TVP7002_HSYNC_OUT_W 0x07 | ||
66 | #define TVP7002_B_FINE_GAIN 0x08 | ||
67 | #define TVP7002_G_FINE_GAIN 0x09 | ||
68 | #define TVP7002_R_FINE_GAIN 0x0a | ||
69 | #define TVP7002_B_FINE_OFF_MSBS 0x0b | ||
70 | #define TVP7002_G_FINE_OFF_MSBS 0x0c | ||
71 | #define TVP7002_R_FINE_OFF_MSBS 0x0d | ||
72 | #define TVP7002_SYNC_CTL_1 0x0e | ||
73 | #define TVP7002_HPLL_AND_CLAMP_CTL 0x0f | ||
74 | #define TVP7002_SYNC_ON_G_THRS 0x10 | ||
75 | #define TVP7002_SYNC_SEPARATOR_THRS 0x11 | ||
76 | #define TVP7002_HPLL_PRE_COAST 0x12 | ||
77 | #define TVP7002_HPLL_POST_COAST 0x13 | ||
78 | #define TVP7002_SYNC_DETECT_STAT 0x14 | ||
79 | #define TVP7002_OUT_FORMATTER 0x15 | ||
80 | #define TVP7002_MISC_CTL_1 0x16 | ||
81 | #define TVP7002_MISC_CTL_2 0x17 | ||
82 | #define TVP7002_MISC_CTL_3 0x18 | ||
83 | #define TVP7002_IN_MUX_SEL_1 0x19 | ||
84 | #define TVP7002_IN_MUX_SEL_2 0x1a | ||
85 | #define TVP7002_B_AND_G_COARSE_GAIN 0x1b | ||
86 | #define TVP7002_R_COARSE_GAIN 0x1c | ||
87 | #define TVP7002_FINE_OFF_LSBS 0x1d | ||
88 | #define TVP7002_B_COARSE_OFF 0x1e | ||
89 | #define TVP7002_G_COARSE_OFF 0x1f | ||
90 | #define TVP7002_R_COARSE_OFF 0x20 | ||
91 | #define TVP7002_HSOUT_OUT_START 0x21 | ||
92 | #define TVP7002_MISC_CTL_4 0x22 | ||
93 | #define TVP7002_B_DGTL_ALC_OUT_LSBS 0x23 | ||
94 | #define TVP7002_G_DGTL_ALC_OUT_LSBS 0x24 | ||
95 | #define TVP7002_R_DGTL_ALC_OUT_LSBS 0x25 | ||
96 | #define TVP7002_AUTO_LVL_CTL_ENABLE 0x26 | ||
97 | #define TVP7002_DGTL_ALC_OUT_MSBS 0x27 | ||
98 | #define TVP7002_AUTO_LVL_CTL_FILTER 0x28 | ||
99 | /* Reserved 0x29*/ | ||
100 | #define TVP7002_FINE_CLAMP_CTL 0x2a | ||
101 | #define TVP7002_PWR_CTL 0x2b | ||
102 | #define TVP7002_ADC_SETUP 0x2c | ||
103 | #define TVP7002_COARSE_CLAMP_CTL 0x2d | ||
104 | #define TVP7002_SOG_CLAMP 0x2e | ||
105 | #define TVP7002_RGB_COARSE_CLAMP_CTL 0x2f | ||
106 | #define TVP7002_SOG_COARSE_CLAMP_CTL 0x30 | ||
107 | #define TVP7002_ALC_PLACEMENT 0x31 | ||
108 | /* Reserved 0x32 */ | ||
109 | /* Reserved 0x33 */ | ||
110 | #define TVP7002_MVIS_STRIPPER_W 0x34 | ||
111 | #define TVP7002_VSYNC_ALGN 0x35 | ||
112 | #define TVP7002_SYNC_BYPASS 0x36 | ||
113 | #define TVP7002_L_FRAME_STAT_LSBS 0x37 | ||
114 | #define TVP7002_L_FRAME_STAT_MSBS 0x38 | ||
115 | #define TVP7002_CLK_L_STAT_LSBS 0x39 | ||
116 | #define TVP7002_CLK_L_STAT_MSBS 0x3a | ||
117 | #define TVP7002_HSYNC_W 0x3b | ||
118 | #define TVP7002_VSYNC_W 0x3c | ||
119 | #define TVP7002_L_LENGTH_TOL 0x3d | ||
120 | /* Reserved 0x3e */ | ||
121 | #define TVP7002_VIDEO_BWTH_CTL 0x3f | ||
122 | #define TVP7002_AVID_START_PIXEL_LSBS 0x40 | ||
123 | #define TVP7002_AVID_START_PIXEL_MSBS 0x41 | ||
124 | #define TVP7002_AVID_STOP_PIXEL_LSBS 0x42 | ||
125 | #define TVP7002_AVID_STOP_PIXEL_MSBS 0x43 | ||
126 | #define TVP7002_VBLK_F_0_START_L_OFF 0x44 | ||
127 | #define TVP7002_VBLK_F_1_START_L_OFF 0x45 | ||
128 | #define TVP7002_VBLK_F_0_DURATION 0x46 | ||
129 | #define TVP7002_VBLK_F_1_DURATION 0x47 | ||
130 | #define TVP7002_FBIT_F_0_START_L_OFF 0x48 | ||
131 | #define TVP7002_FBIT_F_1_START_L_OFF 0x49 | ||
132 | #define TVP7002_YUV_Y_G_COEF_LSBS 0x4a | ||
133 | #define TVP7002_YUV_Y_G_COEF_MSBS 0x4b | ||
134 | #define TVP7002_YUV_Y_B_COEF_LSBS 0x4c | ||
135 | #define TVP7002_YUV_Y_B_COEF_MSBS 0x4d | ||
136 | #define TVP7002_YUV_Y_R_COEF_LSBS 0x4e | ||
137 | #define TVP7002_YUV_Y_R_COEF_MSBS 0x4f | ||
138 | #define TVP7002_YUV_U_G_COEF_LSBS 0x50 | ||
139 | #define TVP7002_YUV_U_G_COEF_MSBS 0x51 | ||
140 | #define TVP7002_YUV_U_B_COEF_LSBS 0x52 | ||
141 | #define TVP7002_YUV_U_B_COEF_MSBS 0x53 | ||
142 | #define TVP7002_YUV_U_R_COEF_LSBS 0x54 | ||
143 | #define TVP7002_YUV_U_R_COEF_MSBS 0x55 | ||
144 | #define TVP7002_YUV_V_G_COEF_LSBS 0x56 | ||
145 | #define TVP7002_YUV_V_G_COEF_MSBS 0x57 | ||
146 | #define TVP7002_YUV_V_B_COEF_LSBS 0x58 | ||
147 | #define TVP7002_YUV_V_B_COEF_MSBS 0x59 | ||
148 | #define TVP7002_YUV_V_R_COEF_LSBS 0x5a | ||
149 | #define TVP7002_YUV_V_R_COEF_MSBS 0x5b | ||
150 | |||
diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index 5b801a6e1eea..76be733eabfd 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c | |||
@@ -233,10 +233,10 @@ struct tw9910_hsync_ctrl { | |||
233 | }; | 233 | }; |
234 | 234 | ||
235 | struct tw9910_priv { | 235 | struct tw9910_priv { |
236 | struct v4l2_subdev subdev; | 236 | struct v4l2_subdev subdev; |
237 | struct tw9910_video_info *info; | 237 | struct tw9910_video_info *info; |
238 | const struct tw9910_scale_ctrl *scale; | 238 | const struct tw9910_scale_ctrl *scale; |
239 | u32 revision; | 239 | u32 revision; |
240 | }; | 240 | }; |
241 | 241 | ||
242 | static const struct tw9910_scale_ctrl tw9910_ntsc_scales[] = { | 242 | static const struct tw9910_scale_ctrl tw9910_ntsc_scales[] = { |
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 1054546db908..7c17ec63c5da 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c | |||
@@ -1487,7 +1487,7 @@ static int __devinit usbvision_register_video(struct usb_usbvision *usbvision) | |||
1487 | usbvision->vbi = usbvision_vdev_init(usbvision, | 1487 | usbvision->vbi = usbvision_vdev_init(usbvision, |
1488 | &usbvision_vbi_template, | 1488 | &usbvision_vbi_template, |
1489 | "USBVision VBI"); | 1489 | "USBVision VBI"); |
1490 | if (usbvision->vdev == NULL) { | 1490 | if (usbvision->vbi == NULL) { |
1491 | goto err_exit; | 1491 | goto err_exit; |
1492 | } | 1492 | } |
1493 | if (video_register_device(usbvision->vbi, | 1493 | if (video_register_device(usbvision->vbi, |
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index ec8ef8c5560a..3b2e7800d56f 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c | |||
@@ -23,9 +23,13 @@ | |||
23 | 23 | ||
24 | #include "uvcvideo.h" | 24 | #include "uvcvideo.h" |
25 | 25 | ||
26 | #define UVC_CTRL_NDATA 2 | ||
27 | #define UVC_CTRL_DATA_CURRENT 0 | 26 | #define UVC_CTRL_DATA_CURRENT 0 |
28 | #define UVC_CTRL_DATA_BACKUP 1 | 27 | #define UVC_CTRL_DATA_BACKUP 1 |
28 | #define UVC_CTRL_DATA_MIN 2 | ||
29 | #define UVC_CTRL_DATA_MAX 3 | ||
30 | #define UVC_CTRL_DATA_RES 4 | ||
31 | #define UVC_CTRL_DATA_DEF 5 | ||
32 | #define UVC_CTRL_DATA_LAST 6 | ||
29 | 33 | ||
30 | /* ------------------------------------------------------------------------ | 34 | /* ------------------------------------------------------------------------ |
31 | * Controls | 35 | * Controls |
@@ -755,6 +759,49 @@ struct uvc_control *uvc_find_control(struct uvc_video_chain *chain, | |||
755 | return ctrl; | 759 | return ctrl; |
756 | } | 760 | } |
757 | 761 | ||
762 | static int uvc_ctrl_populate_cache(struct uvc_video_chain *chain, | ||
763 | struct uvc_control *ctrl) | ||
764 | { | ||
765 | int ret; | ||
766 | |||
767 | if (ctrl->info->flags & UVC_CONTROL_GET_DEF) { | ||
768 | ret = uvc_query_ctrl(chain->dev, UVC_GET_DEF, ctrl->entity->id, | ||
769 | chain->dev->intfnum, ctrl->info->selector, | ||
770 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF), | ||
771 | ctrl->info->size); | ||
772 | if (ret < 0) | ||
773 | return ret; | ||
774 | } | ||
775 | |||
776 | if (ctrl->info->flags & UVC_CONTROL_GET_MIN) { | ||
777 | ret = uvc_query_ctrl(chain->dev, UVC_GET_MIN, ctrl->entity->id, | ||
778 | chain->dev->intfnum, ctrl->info->selector, | ||
779 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN), | ||
780 | ctrl->info->size); | ||
781 | if (ret < 0) | ||
782 | return ret; | ||
783 | } | ||
784 | if (ctrl->info->flags & UVC_CONTROL_GET_MAX) { | ||
785 | ret = uvc_query_ctrl(chain->dev, UVC_GET_MAX, ctrl->entity->id, | ||
786 | chain->dev->intfnum, ctrl->info->selector, | ||
787 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX), | ||
788 | ctrl->info->size); | ||
789 | if (ret < 0) | ||
790 | return ret; | ||
791 | } | ||
792 | if (ctrl->info->flags & UVC_CONTROL_GET_RES) { | ||
793 | ret = uvc_query_ctrl(chain->dev, UVC_GET_RES, ctrl->entity->id, | ||
794 | chain->dev->intfnum, ctrl->info->selector, | ||
795 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES), | ||
796 | ctrl->info->size); | ||
797 | if (ret < 0) | ||
798 | return ret; | ||
799 | } | ||
800 | |||
801 | ctrl->cached = 1; | ||
802 | return 0; | ||
803 | } | ||
804 | |||
758 | int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, | 805 | int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, |
759 | struct v4l2_queryctrl *v4l2_ctrl) | 806 | struct v4l2_queryctrl *v4l2_ctrl) |
760 | { | 807 | { |
@@ -762,17 +809,12 @@ int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, | |||
762 | struct uvc_control_mapping *mapping; | 809 | struct uvc_control_mapping *mapping; |
763 | struct uvc_menu_info *menu; | 810 | struct uvc_menu_info *menu; |
764 | unsigned int i; | 811 | unsigned int i; |
765 | __u8 *data; | ||
766 | int ret; | 812 | int ret; |
767 | 813 | ||
768 | ctrl = uvc_find_control(chain, v4l2_ctrl->id, &mapping); | 814 | ctrl = uvc_find_control(chain, v4l2_ctrl->id, &mapping); |
769 | if (ctrl == NULL) | 815 | if (ctrl == NULL) |
770 | return -EINVAL; | 816 | return -EINVAL; |
771 | 817 | ||
772 | data = kmalloc(ctrl->info->size, GFP_KERNEL); | ||
773 | if (data == NULL) | ||
774 | return -ENOMEM; | ||
775 | |||
776 | memset(v4l2_ctrl, 0, sizeof *v4l2_ctrl); | 818 | memset(v4l2_ctrl, 0, sizeof *v4l2_ctrl); |
777 | v4l2_ctrl->id = mapping->id; | 819 | v4l2_ctrl->id = mapping->id; |
778 | v4l2_ctrl->type = mapping->v4l2_type; | 820 | v4l2_ctrl->type = mapping->v4l2_type; |
@@ -782,14 +824,15 @@ int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, | |||
782 | if (!(ctrl->info->flags & UVC_CONTROL_SET_CUR)) | 824 | if (!(ctrl->info->flags & UVC_CONTROL_SET_CUR)) |
783 | v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; | 825 | v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
784 | 826 | ||
785 | if (ctrl->info->flags & UVC_CONTROL_GET_DEF) { | 827 | if (!ctrl->cached) { |
786 | ret = uvc_query_ctrl(chain->dev, UVC_GET_DEF, ctrl->entity->id, | 828 | ret = uvc_ctrl_populate_cache(chain, ctrl); |
787 | chain->dev->intfnum, ctrl->info->selector, | ||
788 | data, ctrl->info->size); | ||
789 | if (ret < 0) | 829 | if (ret < 0) |
790 | goto out; | 830 | return ret; |
791 | v4l2_ctrl->default_value = | 831 | } |
792 | mapping->get(mapping, UVC_GET_DEF, data); | 832 | |
833 | if (ctrl->info->flags & UVC_CONTROL_GET_DEF) { | ||
834 | v4l2_ctrl->default_value = mapping->get(mapping, UVC_GET_DEF, | ||
835 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF)); | ||
793 | } | 836 | } |
794 | 837 | ||
795 | switch (mapping->v4l2_type) { | 838 | switch (mapping->v4l2_type) { |
@@ -806,56 +849,37 @@ int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, | |||
806 | } | 849 | } |
807 | } | 850 | } |
808 | 851 | ||
809 | ret = 0; | 852 | return 0; |
810 | goto out; | ||
811 | 853 | ||
812 | case V4L2_CTRL_TYPE_BOOLEAN: | 854 | case V4L2_CTRL_TYPE_BOOLEAN: |
813 | v4l2_ctrl->minimum = 0; | 855 | v4l2_ctrl->minimum = 0; |
814 | v4l2_ctrl->maximum = 1; | 856 | v4l2_ctrl->maximum = 1; |
815 | v4l2_ctrl->step = 1; | 857 | v4l2_ctrl->step = 1; |
816 | ret = 0; | 858 | return 0; |
817 | goto out; | ||
818 | 859 | ||
819 | case V4L2_CTRL_TYPE_BUTTON: | 860 | case V4L2_CTRL_TYPE_BUTTON: |
820 | v4l2_ctrl->minimum = 0; | 861 | v4l2_ctrl->minimum = 0; |
821 | v4l2_ctrl->maximum = 0; | 862 | v4l2_ctrl->maximum = 0; |
822 | v4l2_ctrl->step = 0; | 863 | v4l2_ctrl->step = 0; |
823 | ret = 0; | 864 | return 0; |
824 | goto out; | ||
825 | 865 | ||
826 | default: | 866 | default: |
827 | break; | 867 | break; |
828 | } | 868 | } |
829 | 869 | ||
830 | if (ctrl->info->flags & UVC_CONTROL_GET_MIN) { | 870 | if (ctrl->info->flags & UVC_CONTROL_GET_MIN) |
831 | ret = uvc_query_ctrl(chain->dev, UVC_GET_MIN, ctrl->entity->id, | 871 | v4l2_ctrl->minimum = mapping->get(mapping, UVC_GET_MIN, |
832 | chain->dev->intfnum, ctrl->info->selector, | 872 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN)); |
833 | data, ctrl->info->size); | ||
834 | if (ret < 0) | ||
835 | goto out; | ||
836 | v4l2_ctrl->minimum = mapping->get(mapping, UVC_GET_MIN, data); | ||
837 | } | ||
838 | if (ctrl->info->flags & UVC_CONTROL_GET_MAX) { | ||
839 | ret = uvc_query_ctrl(chain->dev, UVC_GET_MAX, ctrl->entity->id, | ||
840 | chain->dev->intfnum, ctrl->info->selector, | ||
841 | data, ctrl->info->size); | ||
842 | if (ret < 0) | ||
843 | goto out; | ||
844 | v4l2_ctrl->maximum = mapping->get(mapping, UVC_GET_MAX, data); | ||
845 | } | ||
846 | if (ctrl->info->flags & UVC_CONTROL_GET_RES) { | ||
847 | ret = uvc_query_ctrl(chain->dev, UVC_GET_RES, ctrl->entity->id, | ||
848 | chain->dev->intfnum, ctrl->info->selector, | ||
849 | data, ctrl->info->size); | ||
850 | if (ret < 0) | ||
851 | goto out; | ||
852 | v4l2_ctrl->step = mapping->get(mapping, UVC_GET_RES, data); | ||
853 | } | ||
854 | 873 | ||
855 | ret = 0; | 874 | if (ctrl->info->flags & UVC_CONTROL_GET_MAX) |
856 | out: | 875 | v4l2_ctrl->maximum = mapping->get(mapping, UVC_GET_MAX, |
857 | kfree(data); | 876 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX)); |
858 | return ret; | 877 | |
878 | if (ctrl->info->flags & UVC_CONTROL_GET_RES) | ||
879 | v4l2_ctrl->step = mapping->get(mapping, UVC_GET_RES, | ||
880 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES)); | ||
881 | |||
882 | return 0; | ||
859 | } | 883 | } |
860 | 884 | ||
861 | 885 | ||
@@ -997,19 +1021,57 @@ int uvc_ctrl_set(struct uvc_video_chain *chain, | |||
997 | { | 1021 | { |
998 | struct uvc_control *ctrl; | 1022 | struct uvc_control *ctrl; |
999 | struct uvc_control_mapping *mapping; | 1023 | struct uvc_control_mapping *mapping; |
1000 | s32 value = xctrl->value; | 1024 | s32 value; |
1025 | u32 step; | ||
1026 | s32 min; | ||
1027 | s32 max; | ||
1001 | int ret; | 1028 | int ret; |
1002 | 1029 | ||
1003 | ctrl = uvc_find_control(chain, xctrl->id, &mapping); | 1030 | ctrl = uvc_find_control(chain, xctrl->id, &mapping); |
1004 | if (ctrl == NULL || (ctrl->info->flags & UVC_CONTROL_SET_CUR) == 0) | 1031 | if (ctrl == NULL || (ctrl->info->flags & UVC_CONTROL_SET_CUR) == 0) |
1005 | return -EINVAL; | 1032 | return -EINVAL; |
1006 | 1033 | ||
1007 | if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) { | 1034 | /* Clamp out of range values. */ |
1008 | if (value < 0 || value >= mapping->menu_count) | 1035 | switch (mapping->v4l2_type) { |
1009 | return -EINVAL; | 1036 | case V4L2_CTRL_TYPE_INTEGER: |
1010 | value = mapping->menu_info[value].value; | 1037 | if (!ctrl->cached) { |
1038 | ret = uvc_ctrl_populate_cache(chain, ctrl); | ||
1039 | if (ret < 0) | ||
1040 | return ret; | ||
1041 | } | ||
1042 | |||
1043 | min = mapping->get(mapping, UVC_GET_MIN, | ||
1044 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN)); | ||
1045 | max = mapping->get(mapping, UVC_GET_MAX, | ||
1046 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX)); | ||
1047 | step = mapping->get(mapping, UVC_GET_RES, | ||
1048 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES)); | ||
1049 | |||
1050 | xctrl->value = min + (xctrl->value - min + step/2) / step * step; | ||
1051 | xctrl->value = clamp(xctrl->value, min, max); | ||
1052 | value = xctrl->value; | ||
1053 | break; | ||
1054 | |||
1055 | case V4L2_CTRL_TYPE_BOOLEAN: | ||
1056 | xctrl->value = clamp(xctrl->value, 0, 1); | ||
1057 | value = xctrl->value; | ||
1058 | break; | ||
1059 | |||
1060 | case V4L2_CTRL_TYPE_MENU: | ||
1061 | if (xctrl->value < 0 || xctrl->value >= mapping->menu_count) | ||
1062 | return -ERANGE; | ||
1063 | value = mapping->menu_info[xctrl->value].value; | ||
1064 | break; | ||
1065 | |||
1066 | default: | ||
1067 | value = xctrl->value; | ||
1068 | break; | ||
1011 | } | 1069 | } |
1012 | 1070 | ||
1071 | /* If the mapping doesn't span the whole UVC control, the current value | ||
1072 | * needs to be loaded from the device to perform the read-modify-write | ||
1073 | * operation. | ||
1074 | */ | ||
1013 | if (!ctrl->loaded && (ctrl->info->size * 8) != mapping->size) { | 1075 | if (!ctrl->loaded && (ctrl->info->size * 8) != mapping->size) { |
1014 | if ((ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0) { | 1076 | if ((ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0) { |
1015 | memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), | 1077 | memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), |
@@ -1027,6 +1089,7 @@ int uvc_ctrl_set(struct uvc_video_chain *chain, | |||
1027 | ctrl->loaded = 1; | 1089 | ctrl->loaded = 1; |
1028 | } | 1090 | } |
1029 | 1091 | ||
1092 | /* Backup the current value in case we need to rollback later. */ | ||
1030 | if (!ctrl->dirty) { | 1093 | if (!ctrl->dirty) { |
1031 | memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), | 1094 | memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), |
1032 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), | 1095 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), |
@@ -1080,10 +1143,8 @@ int uvc_xu_ctrl_query(struct uvc_video_chain *chain, | |||
1080 | } | 1143 | } |
1081 | 1144 | ||
1082 | if (!found) { | 1145 | if (!found) { |
1083 | uvc_trace(UVC_TRACE_CONTROL, | 1146 | uvc_trace(UVC_TRACE_CONTROL, "Control %pUl/%u not found.\n", |
1084 | "Control " UVC_GUID_FORMAT "/%u not found.\n", | 1147 | entity->extension.guidExtensionCode, xctrl->selector); |
1085 | UVC_GUID_ARGS(entity->extension.guidExtensionCode), | ||
1086 | xctrl->selector); | ||
1087 | return -EINVAL; | 1148 | return -EINVAL; |
1088 | } | 1149 | } |
1089 | 1150 | ||
@@ -1159,9 +1220,9 @@ int uvc_ctrl_resume_device(struct uvc_device *dev) | |||
1159 | (ctrl->info->flags & UVC_CONTROL_RESTORE) == 0) | 1220 | (ctrl->info->flags & UVC_CONTROL_RESTORE) == 0) |
1160 | continue; | 1221 | continue; |
1161 | 1222 | ||
1162 | printk(KERN_INFO "restoring control " UVC_GUID_FORMAT | 1223 | printk(KERN_INFO "restoring control %pUl/%u/%u\n", |
1163 | "/%u/%u\n", UVC_GUID_ARGS(ctrl->info->entity), | 1224 | ctrl->info->entity, ctrl->info->index, |
1164 | ctrl->info->index, ctrl->info->selector); | 1225 | ctrl->info->selector); |
1165 | ctrl->dirty = 1; | 1226 | ctrl->dirty = 1; |
1166 | } | 1227 | } |
1167 | 1228 | ||
@@ -1215,47 +1276,43 @@ static void uvc_ctrl_add_ctrl(struct uvc_device *dev, | |||
1215 | ret = uvc_query_ctrl(dev, UVC_GET_LEN, ctrl->entity->id, | 1276 | ret = uvc_query_ctrl(dev, UVC_GET_LEN, ctrl->entity->id, |
1216 | dev->intfnum, info->selector, (__u8 *)&size, 2); | 1277 | dev->intfnum, info->selector, (__u8 *)&size, 2); |
1217 | if (ret < 0) { | 1278 | if (ret < 0) { |
1218 | uvc_trace(UVC_TRACE_CONTROL, "GET_LEN failed on " | 1279 | uvc_trace(UVC_TRACE_CONTROL, |
1219 | "control " UVC_GUID_FORMAT "/%u (%d).\n", | 1280 | "GET_LEN failed on control %pUl/%u (%d).\n", |
1220 | UVC_GUID_ARGS(info->entity), info->selector, | 1281 | info->entity, info->selector, ret); |
1221 | ret); | ||
1222 | return; | 1282 | return; |
1223 | } | 1283 | } |
1224 | 1284 | ||
1225 | if (info->size != le16_to_cpu(size)) { | 1285 | if (info->size != le16_to_cpu(size)) { |
1226 | uvc_trace(UVC_TRACE_CONTROL, "Control " UVC_GUID_FORMAT | 1286 | uvc_trace(UVC_TRACE_CONTROL, "Control %pUl/%u size " |
1227 | "/%u size doesn't match user supplied " | 1287 | "doesn't match user supplied value.\n", |
1228 | "value.\n", UVC_GUID_ARGS(info->entity), | 1288 | info->entity, info->selector); |
1229 | info->selector); | ||
1230 | return; | 1289 | return; |
1231 | } | 1290 | } |
1232 | 1291 | ||
1233 | ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id, | 1292 | ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id, |
1234 | dev->intfnum, info->selector, &inf, 1); | 1293 | dev->intfnum, info->selector, &inf, 1); |
1235 | if (ret < 0) { | 1294 | if (ret < 0) { |
1236 | uvc_trace(UVC_TRACE_CONTROL, "GET_INFO failed on " | 1295 | uvc_trace(UVC_TRACE_CONTROL, |
1237 | "control " UVC_GUID_FORMAT "/%u (%d).\n", | 1296 | "GET_INFO failed on control %pUl/%u (%d).\n", |
1238 | UVC_GUID_ARGS(info->entity), info->selector, | 1297 | info->entity, info->selector, ret); |
1239 | ret); | ||
1240 | return; | 1298 | return; |
1241 | } | 1299 | } |
1242 | 1300 | ||
1243 | flags = info->flags; | 1301 | flags = info->flags; |
1244 | if (((flags & UVC_CONTROL_GET_CUR) && !(inf & (1 << 0))) || | 1302 | if (((flags & UVC_CONTROL_GET_CUR) && !(inf & (1 << 0))) || |
1245 | ((flags & UVC_CONTROL_SET_CUR) && !(inf & (1 << 1)))) { | 1303 | ((flags & UVC_CONTROL_SET_CUR) && !(inf & (1 << 1)))) { |
1246 | uvc_trace(UVC_TRACE_CONTROL, "Control " | 1304 | uvc_trace(UVC_TRACE_CONTROL, "Control %pUl/%u flags " |
1247 | UVC_GUID_FORMAT "/%u flags don't match " | 1305 | "don't match supported operations.\n", |
1248 | "supported operations.\n", | 1306 | info->entity, info->selector); |
1249 | UVC_GUID_ARGS(info->entity), info->selector); | ||
1250 | return; | 1307 | return; |
1251 | } | 1308 | } |
1252 | } | 1309 | } |
1253 | 1310 | ||
1254 | ctrl->info = info; | 1311 | ctrl->info = info; |
1255 | ctrl->data = kmalloc(ctrl->info->size * UVC_CTRL_NDATA, GFP_KERNEL); | 1312 | ctrl->data = kmalloc(ctrl->info->size * UVC_CTRL_DATA_LAST, GFP_KERNEL); |
1256 | uvc_trace(UVC_TRACE_CONTROL, "Added control " UVC_GUID_FORMAT "/%u " | 1313 | uvc_trace(UVC_TRACE_CONTROL, "Added control %pUl/%u to device %s " |
1257 | "to device %s entity %u\n", UVC_GUID_ARGS(ctrl->info->entity), | 1314 | "entity %u\n", ctrl->info->entity, ctrl->info->selector, |
1258 | ctrl->info->selector, dev->udev->devpath, entity->id); | 1315 | dev->udev->devpath, entity->id); |
1259 | } | 1316 | } |
1260 | 1317 | ||
1261 | /* | 1318 | /* |
@@ -1281,17 +1338,16 @@ int uvc_ctrl_add_info(struct uvc_control_info *info) | |||
1281 | continue; | 1338 | continue; |
1282 | 1339 | ||
1283 | if (ctrl->selector == info->selector) { | 1340 | if (ctrl->selector == info->selector) { |
1284 | uvc_trace(UVC_TRACE_CONTROL, "Control " | 1341 | uvc_trace(UVC_TRACE_CONTROL, |
1285 | UVC_GUID_FORMAT "/%u is already defined.\n", | 1342 | "Control %pUl/%u is already defined.\n", |
1286 | UVC_GUID_ARGS(info->entity), info->selector); | 1343 | info->entity, info->selector); |
1287 | ret = -EEXIST; | 1344 | ret = -EEXIST; |
1288 | goto end; | 1345 | goto end; |
1289 | } | 1346 | } |
1290 | if (ctrl->index == info->index) { | 1347 | if (ctrl->index == info->index) { |
1291 | uvc_trace(UVC_TRACE_CONTROL, "Control " | 1348 | uvc_trace(UVC_TRACE_CONTROL, |
1292 | UVC_GUID_FORMAT "/%u would overwrite index " | 1349 | "Control %pUl/%u would overwrite index %d.\n", |
1293 | "%d.\n", UVC_GUID_ARGS(info->entity), | 1350 | info->entity, info->selector, info->index); |
1294 | info->selector, info->index); | ||
1295 | ret = -EEXIST; | 1351 | ret = -EEXIST; |
1296 | goto end; | 1352 | goto end; |
1297 | } | 1353 | } |
@@ -1332,10 +1388,9 @@ int uvc_ctrl_add_mapping(struct uvc_control_mapping *mapping) | |||
1332 | continue; | 1388 | continue; |
1333 | 1389 | ||
1334 | if (info->size * 8 < mapping->size + mapping->offset) { | 1390 | if (info->size * 8 < mapping->size + mapping->offset) { |
1335 | uvc_trace(UVC_TRACE_CONTROL, "Mapping '%s' would " | 1391 | uvc_trace(UVC_TRACE_CONTROL, |
1336 | "overflow control " UVC_GUID_FORMAT "/%u\n", | 1392 | "Mapping '%s' would overflow control %pUl/%u\n", |
1337 | mapping->name, UVC_GUID_ARGS(info->entity), | 1393 | mapping->name, info->entity, info->selector); |
1338 | info->selector); | ||
1339 | ret = -EOVERFLOW; | 1394 | ret = -EOVERFLOW; |
1340 | goto end; | 1395 | goto end; |
1341 | } | 1396 | } |
@@ -1354,9 +1409,9 @@ int uvc_ctrl_add_mapping(struct uvc_control_mapping *mapping) | |||
1354 | 1409 | ||
1355 | mapping->ctrl = info; | 1410 | mapping->ctrl = info; |
1356 | list_add_tail(&mapping->list, &info->mappings); | 1411 | list_add_tail(&mapping->list, &info->mappings); |
1357 | uvc_trace(UVC_TRACE_CONTROL, "Adding mapping %s to control " | 1412 | uvc_trace(UVC_TRACE_CONTROL, |
1358 | UVC_GUID_FORMAT "/%u.\n", mapping->name, | 1413 | "Adding mapping %s to control %pUl/%u.\n", |
1359 | UVC_GUID_ARGS(info->entity), info->selector); | 1414 | mapping->name, info->entity, info->selector); |
1360 | 1415 | ||
1361 | ret = 0; | 1416 | ret = 0; |
1362 | break; | 1417 | break; |
@@ -1378,6 +1433,7 @@ uvc_ctrl_prune_entity(struct uvc_device *dev, struct uvc_entity *entity) | |||
1378 | struct usb_device_id id; | 1433 | struct usb_device_id id; |
1379 | u8 index; | 1434 | u8 index; |
1380 | } blacklist[] = { | 1435 | } blacklist[] = { |
1436 | { { USB_DEVICE(0x13d3, 0x509b) }, 9 }, /* Gain */ | ||
1381 | { { USB_DEVICE(0x1c4f, 0x3000) }, 6 }, /* WB Temperature */ | 1437 | { { USB_DEVICE(0x1c4f, 0x3000) }, 6 }, /* WB Temperature */ |
1382 | { { USB_DEVICE(0x5986, 0x0241) }, 2 }, /* Hue */ | 1438 | { { USB_DEVICE(0x5986, 0x0241) }, 2 }, /* Hue */ |
1383 | }; | 1439 | }; |
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 391cccca7ffc..a814820a3f6e 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c | |||
@@ -43,8 +43,9 @@ | |||
43 | #define DRIVER_VERSION "v0.1.0" | 43 | #define DRIVER_VERSION "v0.1.0" |
44 | #endif | 44 | #endif |
45 | 45 | ||
46 | unsigned int uvc_clock_param = CLOCK_MONOTONIC; | ||
46 | unsigned int uvc_no_drop_param; | 47 | unsigned int uvc_no_drop_param; |
47 | static unsigned int uvc_quirks_param; | 48 | static unsigned int uvc_quirks_param = -1; |
48 | unsigned int uvc_trace_param; | 49 | unsigned int uvc_trace_param; |
49 | unsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT; | 50 | unsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT; |
50 | 51 | ||
@@ -59,6 +60,11 @@ static struct uvc_format_desc uvc_fmts[] = { | |||
59 | .fcc = V4L2_PIX_FMT_YUYV, | 60 | .fcc = V4L2_PIX_FMT_YUYV, |
60 | }, | 61 | }, |
61 | { | 62 | { |
63 | .name = "YUV 4:2:2 (YUYV)", | ||
64 | .guid = UVC_GUID_FORMAT_YUY2_ISIGHT, | ||
65 | .fcc = V4L2_PIX_FMT_YUYV, | ||
66 | }, | ||
67 | { | ||
62 | .name = "YUV 4:2:0 (NV12)", | 68 | .name = "YUV 4:2:0 (NV12)", |
63 | .guid = UVC_GUID_FORMAT_NV12, | 69 | .guid = UVC_GUID_FORMAT_NV12, |
64 | .fcc = V4L2_PIX_FMT_NV12, | 70 | .fcc = V4L2_PIX_FMT_NV12, |
@@ -309,11 +315,10 @@ static int uvc_parse_format(struct uvc_device *dev, | |||
309 | sizeof format->name); | 315 | sizeof format->name); |
310 | format->fcc = fmtdesc->fcc; | 316 | format->fcc = fmtdesc->fcc; |
311 | } else { | 317 | } else { |
312 | uvc_printk(KERN_INFO, "Unknown video format " | 318 | uvc_printk(KERN_INFO, "Unknown video format %pUl\n", |
313 | UVC_GUID_FORMAT "\n", | 319 | &buffer[5]); |
314 | UVC_GUID_ARGS(&buffer[5])); | 320 | snprintf(format->name, sizeof(format->name), "%pUl\n", |
315 | snprintf(format->name, sizeof format->name, | 321 | &buffer[5]); |
316 | UVC_GUID_FORMAT, UVC_GUID_ARGS(&buffer[5])); | ||
317 | format->fcc = 0; | 322 | format->fcc = 0; |
318 | } | 323 | } |
319 | 324 | ||
@@ -1750,7 +1755,8 @@ static int uvc_probe(struct usb_interface *intf, | |||
1750 | dev->udev = usb_get_dev(udev); | 1755 | dev->udev = usb_get_dev(udev); |
1751 | dev->intf = usb_get_intf(intf); | 1756 | dev->intf = usb_get_intf(intf); |
1752 | dev->intfnum = intf->cur_altsetting->desc.bInterfaceNumber; | 1757 | dev->intfnum = intf->cur_altsetting->desc.bInterfaceNumber; |
1753 | dev->quirks = id->driver_info | uvc_quirks_param; | 1758 | dev->quirks = (uvc_quirks_param == -1) |
1759 | ? id->driver_info : uvc_quirks_param; | ||
1754 | 1760 | ||
1755 | if (udev->product != NULL) | 1761 | if (udev->product != NULL) |
1756 | strlcpy(dev->name, udev->product, sizeof dev->name); | 1762 | strlcpy(dev->name, udev->product, sizeof dev->name); |
@@ -1773,9 +1779,9 @@ static int uvc_probe(struct usb_interface *intf, | |||
1773 | le16_to_cpu(udev->descriptor.idVendor), | 1779 | le16_to_cpu(udev->descriptor.idVendor), |
1774 | le16_to_cpu(udev->descriptor.idProduct)); | 1780 | le16_to_cpu(udev->descriptor.idProduct)); |
1775 | 1781 | ||
1776 | if (uvc_quirks_param != 0) { | 1782 | if (dev->quirks != id->driver_info) { |
1777 | uvc_printk(KERN_INFO, "Forcing device quirks 0x%x by module " | 1783 | uvc_printk(KERN_INFO, "Forcing device quirks to 0x%x by module " |
1778 | "parameter for testing purpose.\n", uvc_quirks_param); | 1784 | "parameter for testing purpose.\n", dev->quirks); |
1779 | uvc_printk(KERN_INFO, "Please report required quirks to the " | 1785 | uvc_printk(KERN_INFO, "Please report required quirks to the " |
1780 | "linux-uvc-devel mailing list.\n"); | 1786 | "linux-uvc-devel mailing list.\n"); |
1781 | } | 1787 | } |
@@ -1892,6 +1898,45 @@ static int uvc_reset_resume(struct usb_interface *intf) | |||
1892 | } | 1898 | } |
1893 | 1899 | ||
1894 | /* ------------------------------------------------------------------------ | 1900 | /* ------------------------------------------------------------------------ |
1901 | * Module parameters | ||
1902 | */ | ||
1903 | |||
1904 | static int uvc_clock_param_get(char *buffer, struct kernel_param *kp) | ||
1905 | { | ||
1906 | if (uvc_clock_param == CLOCK_MONOTONIC) | ||
1907 | return sprintf(buffer, "CLOCK_MONOTONIC"); | ||
1908 | else | ||
1909 | return sprintf(buffer, "CLOCK_REALTIME"); | ||
1910 | } | ||
1911 | |||
1912 | static int uvc_clock_param_set(const char *val, struct kernel_param *kp) | ||
1913 | { | ||
1914 | if (strncasecmp(val, "clock_", strlen("clock_")) == 0) | ||
1915 | val += strlen("clock_"); | ||
1916 | |||
1917 | if (strcasecmp(val, "monotonic") == 0) | ||
1918 | uvc_clock_param = CLOCK_MONOTONIC; | ||
1919 | else if (strcasecmp(val, "realtime") == 0) | ||
1920 | uvc_clock_param = CLOCK_REALTIME; | ||
1921 | else | ||
1922 | return -EINVAL; | ||
1923 | |||
1924 | return 0; | ||
1925 | } | ||
1926 | |||
1927 | module_param_call(clock, uvc_clock_param_set, uvc_clock_param_get, | ||
1928 | &uvc_clock_param, S_IRUGO|S_IWUSR); | ||
1929 | MODULE_PARM_DESC(clock, "Video buffers timestamp clock"); | ||
1930 | module_param_named(nodrop, uvc_no_drop_param, uint, S_IRUGO|S_IWUSR); | ||
1931 | MODULE_PARM_DESC(nodrop, "Don't drop incomplete frames"); | ||
1932 | module_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR); | ||
1933 | MODULE_PARM_DESC(quirks, "Forced device quirks"); | ||
1934 | module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR); | ||
1935 | MODULE_PARM_DESC(trace, "Trace level bitmask"); | ||
1936 | module_param_named(timeout, uvc_timeout_param, uint, S_IRUGO|S_IWUSR); | ||
1937 | MODULE_PARM_DESC(timeout, "Streaming control requests timeout"); | ||
1938 | |||
1939 | /* ------------------------------------------------------------------------ | ||
1895 | * Driver initialization and cleanup | 1940 | * Driver initialization and cleanup |
1896 | */ | 1941 | */ |
1897 | 1942 | ||
@@ -2197,15 +2242,6 @@ static void __exit uvc_cleanup(void) | |||
2197 | module_init(uvc_init); | 2242 | module_init(uvc_init); |
2198 | module_exit(uvc_cleanup); | 2243 | module_exit(uvc_cleanup); |
2199 | 2244 | ||
2200 | module_param_named(nodrop, uvc_no_drop_param, uint, S_IRUGO|S_IWUSR); | ||
2201 | MODULE_PARM_DESC(nodrop, "Don't drop incomplete frames"); | ||
2202 | module_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR); | ||
2203 | MODULE_PARM_DESC(quirks, "Forced device quirks"); | ||
2204 | module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR); | ||
2205 | MODULE_PARM_DESC(trace, "Trace level bitmask"); | ||
2206 | module_param_named(timeout, uvc_timeout_param, uint, S_IRUGO|S_IWUSR); | ||
2207 | MODULE_PARM_DESC(timeout, "Streaming control requests timeout"); | ||
2208 | |||
2209 | MODULE_AUTHOR(DRIVER_AUTHOR); | 2245 | MODULE_AUTHOR(DRIVER_AUTHOR); |
2210 | MODULE_DESCRIPTION(DRIVER_DESC); | 2246 | MODULE_DESCRIPTION(DRIVER_DESC); |
2211 | MODULE_LICENSE("GPL"); | 2247 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index ea11839cba4a..4a925a31b0e0 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c | |||
@@ -502,7 +502,6 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, | |||
502 | spin_unlock_irqrestore(&queue->irqlock, flags); | 502 | spin_unlock_irqrestore(&queue->irqlock, flags); |
503 | 503 | ||
504 | buf->buf.sequence = queue->sequence++; | 504 | buf->buf.sequence = queue->sequence++; |
505 | do_gettimeofday(&buf->buf.timestamp); | ||
506 | 505 | ||
507 | wake_up(&buf->wait); | 506 | wake_up(&buf->wait); |
508 | return nextbuf; | 507 | return nextbuf; |
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index 23239a4adefe..43152aa52227 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c | |||
@@ -539,7 +539,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
539 | xctrl.id = ctrl->id; | 539 | xctrl.id = ctrl->id; |
540 | xctrl.value = ctrl->value; | 540 | xctrl.value = ctrl->value; |
541 | 541 | ||
542 | uvc_ctrl_begin(chain); | 542 | ret = uvc_ctrl_begin(chain); |
543 | if (ret < 0) | 543 | if (ret < 0) |
544 | return ret; | 544 | return ret; |
545 | 545 | ||
@@ -549,6 +549,8 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
549 | return ret; | 549 | return ret; |
550 | } | 550 | } |
551 | ret = uvc_ctrl_commit(chain); | 551 | ret = uvc_ctrl_commit(chain); |
552 | if (ret == 0) | ||
553 | ctrl->value = xctrl.value; | ||
552 | break; | 554 | break; |
553 | } | 555 | } |
554 | 556 | ||
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 7dcf534a0cf3..6b0666be370f 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c | |||
@@ -410,6 +410,8 @@ static int uvc_video_decode_start(struct uvc_streaming *stream, | |||
410 | * when the EOF bit is set to force synchronisation on the next packet. | 410 | * when the EOF bit is set to force synchronisation on the next packet. |
411 | */ | 411 | */ |
412 | if (buf->state != UVC_BUF_STATE_ACTIVE) { | 412 | if (buf->state != UVC_BUF_STATE_ACTIVE) { |
413 | struct timespec ts; | ||
414 | |||
413 | if (fid == stream->last_fid) { | 415 | if (fid == stream->last_fid) { |
414 | uvc_trace(UVC_TRACE_FRAME, "Dropping payload (out of " | 416 | uvc_trace(UVC_TRACE_FRAME, "Dropping payload (out of " |
415 | "sync).\n"); | 417 | "sync).\n"); |
@@ -419,6 +421,14 @@ static int uvc_video_decode_start(struct uvc_streaming *stream, | |||
419 | return -ENODATA; | 421 | return -ENODATA; |
420 | } | 422 | } |
421 | 423 | ||
424 | if (uvc_clock_param == CLOCK_MONOTONIC) | ||
425 | ktime_get_ts(&ts); | ||
426 | else | ||
427 | ktime_get_real_ts(&ts); | ||
428 | |||
429 | buf->buf.timestamp.tv_sec = ts.tv_sec; | ||
430 | buf->buf.timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC; | ||
431 | |||
422 | /* TODO: Handle PTS and SCR. */ | 432 | /* TODO: Handle PTS and SCR. */ |
423 | buf->state = UVC_BUF_STATE_ACTIVE; | 433 | buf->state = UVC_BUF_STATE_ACTIVE; |
424 | } | 434 | } |
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index 2337585001ea..2bba059259e6 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h | |||
@@ -113,6 +113,9 @@ struct uvc_xu_control { | |||
113 | #define UVC_GUID_FORMAT_YUY2 \ | 113 | #define UVC_GUID_FORMAT_YUY2 \ |
114 | { 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00, \ | 114 | { 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00, \ |
115 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | 115 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} |
116 | #define UVC_GUID_FORMAT_YUY2_ISIGHT \ | ||
117 | { 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00, \ | ||
118 | 0x80, 0x00, 0x00, 0x00, 0x00, 0x38, 0x9b, 0x71} | ||
116 | #define UVC_GUID_FORMAT_NV12 \ | 119 | #define UVC_GUID_FORMAT_NV12 \ |
117 | { 'N', 'V', '1', '2', 0x00, 0x00, 0x10, 0x00, \ | 120 | { 'N', 'V', '1', '2', 0x00, 0x00, 0x10, 0x00, \ |
118 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | 121 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} |
@@ -149,7 +152,7 @@ struct uvc_xu_control { | |||
149 | #define UVC_MAX_STATUS_SIZE 16 | 152 | #define UVC_MAX_STATUS_SIZE 16 |
150 | 153 | ||
151 | #define UVC_CTRL_CONTROL_TIMEOUT 300 | 154 | #define UVC_CTRL_CONTROL_TIMEOUT 300 |
152 | #define UVC_CTRL_STREAMING_TIMEOUT 3000 | 155 | #define UVC_CTRL_STREAMING_TIMEOUT 5000 |
153 | 156 | ||
154 | /* Devices quirks */ | 157 | /* Devices quirks */ |
155 | #define UVC_QUIRK_STATUS_INTERVAL 0x00000001 | 158 | #define UVC_QUIRK_STATUS_INTERVAL 0x00000001 |
@@ -242,7 +245,8 @@ struct uvc_control { | |||
242 | uvc_control_info. */ | 245 | uvc_control_info. */ |
243 | __u8 dirty : 1, | 246 | __u8 dirty : 1, |
244 | loaded : 1, | 247 | loaded : 1, |
245 | modified : 1; | 248 | modified : 1, |
249 | cached : 1; | ||
246 | 250 | ||
247 | __u8 *data; | 251 | __u8 *data; |
248 | }; | 252 | }; |
@@ -533,6 +537,7 @@ struct uvc_driver { | |||
533 | #define UVC_WARN_MINMAX 0 | 537 | #define UVC_WARN_MINMAX 0 |
534 | #define UVC_WARN_PROBE_DEF 1 | 538 | #define UVC_WARN_PROBE_DEF 1 |
535 | 539 | ||
540 | extern unsigned int uvc_clock_param; | ||
536 | extern unsigned int uvc_no_drop_param; | 541 | extern unsigned int uvc_no_drop_param; |
537 | extern unsigned int uvc_trace_param; | 542 | extern unsigned int uvc_trace_param; |
538 | extern unsigned int uvc_timeout_param; | 543 | extern unsigned int uvc_timeout_param; |
@@ -552,16 +557,6 @@ extern unsigned int uvc_timeout_param; | |||
552 | #define uvc_printk(level, msg...) \ | 557 | #define uvc_printk(level, msg...) \ |
553 | printk(level "uvcvideo: " msg) | 558 | printk(level "uvcvideo: " msg) |
554 | 559 | ||
555 | #define UVC_GUID_FORMAT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-" \ | ||
556 | "%02x%02x%02x%02x%02x%02x" | ||
557 | #define UVC_GUID_ARGS(guid) \ | ||
558 | (guid)[3], (guid)[2], (guid)[1], (guid)[0], \ | ||
559 | (guid)[5], (guid)[4], \ | ||
560 | (guid)[7], (guid)[6], \ | ||
561 | (guid)[8], (guid)[9], \ | ||
562 | (guid)[10], (guid)[11], (guid)[12], \ | ||
563 | (guid)[13], (guid)[14], (guid)[15] | ||
564 | |||
565 | /* -------------------------------------------------------------------------- | 560 | /* -------------------------------------------------------------------------- |
566 | * Internal functions. | 561 | * Internal functions. |
567 | */ | 562 | */ |
diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c index c4150bd26337..f77f84bfe714 100644 --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c | |||
@@ -288,7 +288,7 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user | |||
288 | 288 | ||
289 | static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) | 289 | static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) |
290 | { | 290 | { |
291 | if (copy_to_user(&up->w, &kp->w, sizeof(up->w)) || | 291 | if (copy_to_user(&up->w, &kp->w, sizeof(kp->w)) || |
292 | put_user(kp->field, &up->field) || | 292 | put_user(kp->field, &up->field) || |
293 | put_user(kp->chromakey, &up->chromakey) || | 293 | put_user(kp->chromakey, &up->chromakey) || |
294 | put_user(kp->clipcount, &up->clipcount)) | 294 | put_user(kp->clipcount, &up->clipcount)) |
@@ -475,6 +475,9 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user | |||
475 | return -EFAULT; | 475 | return -EFAULT; |
476 | switch (kp->memory) { | 476 | switch (kp->memory) { |
477 | case V4L2_MEMORY_MMAP: | 477 | case V4L2_MEMORY_MMAP: |
478 | if (get_user(kp->length, &up->length) || | ||
479 | get_user(kp->m.offset, &up->m.offset)) | ||
480 | return -EFAULT; | ||
478 | break; | 481 | break; |
479 | case V4L2_MEMORY_USERPTR: | 482 | case V4L2_MEMORY_USERPTR: |
480 | { | 483 | { |
diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index fa78555b118b..fcd045e7a1c1 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c | |||
@@ -418,6 +418,8 @@ static void *__videobuf_alloc(size_t size) | |||
418 | struct videobuf_buffer *vb; | 418 | struct videobuf_buffer *vb; |
419 | 419 | ||
420 | vb = kzalloc(size+sizeof(*mem),GFP_KERNEL); | 420 | vb = kzalloc(size+sizeof(*mem),GFP_KERNEL); |
421 | if (!vb) | ||
422 | return vb; | ||
421 | 423 | ||
422 | mem = vb->priv = ((char *)vb)+size; | 424 | mem = vb->priv = ((char *)vb)+size; |
423 | mem->magic=MAGIC_SG_MEM; | 425 | mem->magic=MAGIC_SG_MEM; |
diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index d6e6a28fb6b8..136e09383c06 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c | |||
@@ -138,6 +138,8 @@ static void *__videobuf_alloc(size_t size) | |||
138 | struct videobuf_buffer *vb; | 138 | struct videobuf_buffer *vb; |
139 | 139 | ||
140 | vb = kzalloc(size+sizeof(*mem),GFP_KERNEL); | 140 | vb = kzalloc(size+sizeof(*mem),GFP_KERNEL); |
141 | if (!vb) | ||
142 | return vb; | ||
141 | 143 | ||
142 | mem = vb->priv = ((char *)vb)+size; | 144 | mem = vb->priv = ((char *)vb)+size; |
143 | mem->magic=MAGIC_VMAL_MEM; | 145 | mem->magic=MAGIC_VMAL_MEM; |
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 37632a064966..cdbe70385c12 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c | |||
@@ -1371,7 +1371,7 @@ static int __init vivi_create_instance(int inst) | |||
1371 | /* Now that everything is fine, let's add it to device list */ | 1371 | /* Now that everything is fine, let's add it to device list */ |
1372 | list_add_tail(&dev->vivi_devlist, &vivi_devlist); | 1372 | list_add_tail(&dev->vivi_devlist, &vivi_devlist); |
1373 | 1373 | ||
1374 | if (video_nr >= 0) | 1374 | if (video_nr != -1) |
1375 | video_nr++; | 1375 | video_nr++; |
1376 | 1376 | ||
1377 | dev->vfd = vfd; | 1377 | dev->vfd = vfd; |
diff --git a/drivers/media/video/zc0301/Kconfig b/drivers/media/video/zc0301/Kconfig index edb00293cd59..a7e610e0be9e 100644 --- a/drivers/media/video/zc0301/Kconfig +++ b/drivers/media/video/zc0301/Kconfig | |||
@@ -1,7 +1,11 @@ | |||
1 | config USB_ZC0301 | 1 | config USB_ZC0301 |
2 | tristate "USB ZC0301[P] Image Processor and Control Chip support" | 2 | tristate "USB ZC0301[P] webcam support (DEPRECATED)" |
3 | depends on VIDEO_V4L2 | 3 | depends on VIDEO_V4L2 |
4 | default n | ||
4 | ---help--- | 5 | ---help--- |
6 | This driver is DEPRECATED please use the gspca zc3xx module | ||
7 | instead. | ||
8 | |||
5 | Say Y here if you want support for cameras based on the ZC0301 or | 9 | Say Y here if you want support for cameras based on the ZC0301 or |
6 | ZC0301P Image Processors and Control Chips. | 10 | ZC0301P Image Processors and Control Chips. |
7 | 11 | ||
diff --git a/drivers/media/video/zoran/zoran_device.c b/drivers/media/video/zoran/zoran_device.c index f6c2fb4fc3b4..e6ad4b205611 100644 --- a/drivers/media/video/zoran/zoran_device.c +++ b/drivers/media/video/zoran/zoran_device.c | |||
@@ -1196,7 +1196,8 @@ zoran_reap_stat_com (struct zoran *zr) | |||
1196 | static void zoran_restart(struct zoran *zr) | 1196 | static void zoran_restart(struct zoran *zr) |
1197 | { | 1197 | { |
1198 | /* Now the stat_comm buffer is ready for restart */ | 1198 | /* Now the stat_comm buffer is ready for restart */ |
1199 | int status = 0, mode; | 1199 | unsigned int status = 0; |
1200 | int mode; | ||
1200 | 1201 | ||
1201 | if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) { | 1202 | if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) { |
1202 | decoder_call(zr, video, g_input_status, &status); | 1203 | decoder_call(zr, video, g_input_status, &status); |
@@ -1228,7 +1229,7 @@ error_handler (struct zoran *zr, | |||
1228 | u32 astat, | 1229 | u32 astat, |
1229 | u32 stat) | 1230 | u32 stat) |
1230 | { | 1231 | { |
1231 | int i, j; | 1232 | int i; |
1232 | 1233 | ||
1233 | /* This is JPEG error handling part */ | 1234 | /* This is JPEG error handling part */ |
1234 | if (zr->codec_mode != BUZ_MODE_MOTION_COMPRESS && | 1235 | if (zr->codec_mode != BUZ_MODE_MOTION_COMPRESS && |
@@ -1279,6 +1280,7 @@ error_handler (struct zoran *zr, | |||
1279 | /* Report error */ | 1280 | /* Report error */ |
1280 | if (zr36067_debug > 1 && zr->num_errors <= 8) { | 1281 | if (zr36067_debug > 1 && zr->num_errors <= 8) { |
1281 | long frame; | 1282 | long frame; |
1283 | int j; | ||
1282 | 1284 | ||
1283 | frame = zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME]; | 1285 | frame = zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME]; |
1284 | printk(KERN_ERR | 1286 | printk(KERN_ERR |
diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 2ddffed019ee..ec41303544e5 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c | |||
@@ -324,7 +324,7 @@ static int jpg_fbuffer_alloc(struct zoran_fh *fh) | |||
324 | /* Allocate fragment table for this buffer */ | 324 | /* Allocate fragment table for this buffer */ |
325 | 325 | ||
326 | mem = (void *)get_zeroed_page(GFP_KERNEL); | 326 | mem = (void *)get_zeroed_page(GFP_KERNEL); |
327 | if (mem == 0) { | 327 | if (!mem) { |
328 | dprintk(1, | 328 | dprintk(1, |
329 | KERN_ERR | 329 | KERN_ERR |
330 | "%s: %s - get_zeroed_page (frag_tab) failed for buffer %d\n", | 330 | "%s: %s - get_zeroed_page (frag_tab) failed for buffer %d\n", |
@@ -1444,7 +1444,7 @@ zoran_set_norm (struct zoran *zr, | |||
1444 | } | 1444 | } |
1445 | 1445 | ||
1446 | if (norm == V4L2_STD_ALL) { | 1446 | if (norm == V4L2_STD_ALL) { |
1447 | int status = 0; | 1447 | unsigned int status = 0; |
1448 | v4l2_std_id std = 0; | 1448 | v4l2_std_id std = 0; |
1449 | 1449 | ||
1450 | decoder_call(zr, video, querystd, &std); | 1450 | decoder_call(zr, video, querystd, &std); |
diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index f0eae83e3d89..3d4bac252902 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/video/zr364xx.c | |||
@@ -78,6 +78,7 @@ | |||
78 | #define METHOD0 0 | 78 | #define METHOD0 0 |
79 | #define METHOD1 1 | 79 | #define METHOD1 1 |
80 | #define METHOD2 2 | 80 | #define METHOD2 2 |
81 | #define METHOD3 3 | ||
81 | 82 | ||
82 | 83 | ||
83 | /* Module parameters */ | 84 | /* Module parameters */ |
@@ -114,7 +115,7 @@ static struct usb_device_id device_table[] = { | |||
114 | {USB_DEVICE(0x06d6, 0x003b), .driver_info = METHOD0 }, | 115 | {USB_DEVICE(0x06d6, 0x003b), .driver_info = METHOD0 }, |
115 | {USB_DEVICE(0x0a17, 0x004e), .driver_info = METHOD2 }, | 116 | {USB_DEVICE(0x0a17, 0x004e), .driver_info = METHOD2 }, |
116 | {USB_DEVICE(0x041e, 0x405d), .driver_info = METHOD2 }, | 117 | {USB_DEVICE(0x041e, 0x405d), .driver_info = METHOD2 }, |
117 | {USB_DEVICE(0x08ca, 0x2102), .driver_info = METHOD2 }, | 118 | {USB_DEVICE(0x08ca, 0x2102), .driver_info = METHOD3 }, |
118 | {USB_DEVICE(0x06d6, 0x003d), .driver_info = METHOD0 }, | 119 | {USB_DEVICE(0x06d6, 0x003d), .driver_info = METHOD0 }, |
119 | {} /* Terminating entry */ | 120 | {} /* Terminating entry */ |
120 | }; | 121 | }; |
@@ -302,7 +303,7 @@ static message m2[] = { | |||
302 | }; | 303 | }; |
303 | 304 | ||
304 | /* init table */ | 305 | /* init table */ |
305 | static message *init[3] = { m0, m1, m2 }; | 306 | static message *init[4] = { m0, m1, m2, m2 }; |
306 | 307 | ||
307 | 308 | ||
308 | /* JPEG static data in header (Huffman table, etc) */ | 309 | /* JPEG static data in header (Huffman table, etc) */ |
@@ -967,6 +968,22 @@ static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
967 | m0d1[0] = mode; | 968 | m0d1[0] = mode; |
968 | m1[2].value = 0xf000 + mode; | 969 | m1[2].value = 0xf000 + mode; |
969 | m2[1].value = 0xf000 + mode; | 970 | m2[1].value = 0xf000 + mode; |
971 | |||
972 | /* special case for METHOD3, the modes are different */ | ||
973 | if (cam->method == METHOD3) { | ||
974 | switch (mode) { | ||
975 | case 1: | ||
976 | m2[1].value = 0xf000 + 4; | ||
977 | break; | ||
978 | case 2: | ||
979 | m2[1].value = 0xf000 + 0; | ||
980 | break; | ||
981 | default: | ||
982 | m2[1].value = 0xf000 + 1; | ||
983 | break; | ||
984 | } | ||
985 | } | ||
986 | |||
970 | header2[437] = cam->height / 256; | 987 | header2[437] = cam->height / 256; |
971 | header2[438] = cam->height % 256; | 988 | header2[438] = cam->height % 256; |
972 | header2[439] = cam->width / 256; | 989 | header2[439] = cam->width / 256; |
@@ -1582,6 +1599,22 @@ static int zr364xx_probe(struct usb_interface *intf, | |||
1582 | m0d1[0] = mode; | 1599 | m0d1[0] = mode; |
1583 | m1[2].value = 0xf000 + mode; | 1600 | m1[2].value = 0xf000 + mode; |
1584 | m2[1].value = 0xf000 + mode; | 1601 | m2[1].value = 0xf000 + mode; |
1602 | |||
1603 | /* special case for METHOD3, the modes are different */ | ||
1604 | if (cam->method == METHOD3) { | ||
1605 | switch (mode) { | ||
1606 | case 1: | ||
1607 | m2[1].value = 0xf000 + 4; | ||
1608 | break; | ||
1609 | case 2: | ||
1610 | m2[1].value = 0xf000 + 0; | ||
1611 | break; | ||
1612 | default: | ||
1613 | m2[1].value = 0xf000 + 1; | ||
1614 | break; | ||
1615 | } | ||
1616 | } | ||
1617 | |||
1585 | header2[437] = cam->height / 256; | 1618 | header2[437] = cam->height / 256; |
1586 | header2[438] = cam->height % 256; | 1619 | header2[438] = cam->height % 256; |
1587 | header2[439] = cam->width / 256; | 1620 | header2[439] = cam->width / 256; |