aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/bt8xx/bttv-cards.c92
-rw-r--r--drivers/media/video/bt8xx/bttv-driver.c1
-rw-r--r--drivers/media/video/bt8xx/bttv.h1
-rw-r--r--drivers/media/video/cx23885/cx23885-417.c4
-rw-r--r--drivers/media/video/em28xx/em28xx-cards.c134
-rw-r--r--drivers/media/video/em28xx/em28xx-core.c22
-rw-r--r--drivers/media/video/em28xx/em28xx-dvb.c62
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c16
-rw-r--r--drivers/media/video/em28xx/em28xx.h31
-rw-r--r--drivers/media/video/gspca/Kconfig16
-rw-r--r--drivers/media/video/gspca/Makefile2
-rw-r--r--drivers/media/video/gspca/conex.c2
-rw-r--r--drivers/media/video/gspca/gspca.c73
-rw-r--r--drivers/media/video/gspca/gspca.h9
-rw-r--r--drivers/media/video/gspca/m5602/m5602_s5k4aa.c6
-rw-r--r--drivers/media/video/gspca/mars.c2
-rw-r--r--drivers/media/video/gspca/sn9c20x.c2434
-rw-r--r--drivers/media/video/gspca/sonixj.c4
-rw-r--r--drivers/media/video/gspca/spca500.c2
-rw-r--r--drivers/media/video/gspca/stk014.c2
-rw-r--r--drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c16
-rw-r--r--drivers/media/video/gspca/sunplus.c2
-rw-r--r--drivers/media/video/gspca/zc3xx.c2
-rw-r--r--drivers/media/video/mt9v011.c69
24 files changed, 2872 insertions, 132 deletions
diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c
index fdb4adff3d28..ca6558c394be 100644
--- a/drivers/media/video/bt8xx/bttv-cards.c
+++ b/drivers/media/video/bt8xx/bttv-cards.c
@@ -3324,8 +3324,6 @@ void __devinit bttv_init_card1(struct bttv *btv)
3324/* initialization part two -- after registering i2c bus */ 3324/* initialization part two -- after registering i2c bus */
3325void __devinit bttv_init_card2(struct bttv *btv) 3325void __devinit bttv_init_card2(struct bttv *btv)
3326{ 3326{
3327 int addr=ADDR_UNSET;
3328
3329 btv->tuner_type = UNSET; 3327 btv->tuner_type = UNSET;
3330 3328
3331 if (BTTV_BOARD_UNKNOWN == btv->c.type) { 3329 if (BTTV_BOARD_UNKNOWN == btv->c.type) {
@@ -3470,9 +3468,6 @@ void __devinit bttv_init_card2(struct bttv *btv)
3470 btv->pll.pll_current = -1; 3468 btv->pll.pll_current = -1;
3471 3469
3472 /* tuner configuration (from card list / autodetect / insmod option) */ 3470 /* tuner configuration (from card list / autodetect / insmod option) */
3473 if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr)
3474 addr = bttv_tvcards[btv->c.type].tuner_addr;
3475
3476 if (UNSET != bttv_tvcards[btv->c.type].tuner_type) 3471 if (UNSET != bttv_tvcards[btv->c.type].tuner_type)
3477 if (UNSET == btv->tuner_type) 3472 if (UNSET == btv->tuner_type)
3478 btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type; 3473 btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type;
@@ -3496,40 +3491,6 @@ void __devinit bttv_init_card2(struct bttv *btv)
3496 if (UNSET == btv->tuner_type) 3491 if (UNSET == btv->tuner_type)
3497 btv->tuner_type = TUNER_ABSENT; 3492 btv->tuner_type = TUNER_ABSENT;
3498 3493
3499 if (btv->tuner_type != TUNER_ABSENT) {
3500 struct tuner_setup tun_setup;
3501
3502 /* Load tuner module before issuing tuner config call! */
3503 if (bttv_tvcards[btv->c.type].has_radio)
3504 v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev,
3505 &btv->c.i2c_adap, "tuner", "tuner",
3506 v4l2_i2c_tuner_addrs(ADDRS_RADIO));
3507 v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev,
3508 &btv->c.i2c_adap, "tuner", "tuner",
3509 v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
3510 v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev,
3511 &btv->c.i2c_adap, "tuner", "tuner",
3512 v4l2_i2c_tuner_addrs(ADDRS_TV_WITH_DEMOD));
3513
3514 tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV;
3515 tun_setup.type = btv->tuner_type;
3516 tun_setup.addr = addr;
3517
3518 if (bttv_tvcards[btv->c.type].has_radio)
3519 tun_setup.mode_mask |= T_RADIO;
3520
3521 bttv_call_all(btv, tuner, s_type_addr, &tun_setup);
3522 }
3523
3524 if (btv->tda9887_conf) {
3525 struct v4l2_priv_tun_config tda9887_cfg;
3526
3527 tda9887_cfg.tuner = TUNER_TDA9887;
3528 tda9887_cfg.priv = &btv->tda9887_conf;
3529
3530 bttv_call_all(btv, tuner, s_config, &tda9887_cfg);
3531 }
3532
3533 btv->dig = bttv_tvcards[btv->c.type].has_dig_in ? 3494 btv->dig = bttv_tvcards[btv->c.type].has_dig_in ?
3534 bttv_tvcards[btv->c.type].video_inputs - 1 : UNSET; 3495 bttv_tvcards[btv->c.type].video_inputs - 1 : UNSET;
3535 btv->svhs = bttv_tvcards[btv->c.type].svhs == NO_SVHS ? 3496 btv->svhs = bttv_tvcards[btv->c.type].svhs == NO_SVHS ?
@@ -3540,15 +3501,15 @@ void __devinit bttv_init_card2(struct bttv *btv)
3540 btv->has_remote = remote[btv->c.nr]; 3501 btv->has_remote = remote[btv->c.nr];
3541 3502
3542 if (bttv_tvcards[btv->c.type].has_radio) 3503 if (bttv_tvcards[btv->c.type].has_radio)
3543 btv->has_radio=1; 3504 btv->has_radio = 1;
3544 if (bttv_tvcards[btv->c.type].has_remote) 3505 if (bttv_tvcards[btv->c.type].has_remote)
3545 btv->has_remote=1; 3506 btv->has_remote = 1;
3546 if (!bttv_tvcards[btv->c.type].no_gpioirq) 3507 if (!bttv_tvcards[btv->c.type].no_gpioirq)
3547 btv->gpioirq=1; 3508 btv->gpioirq = 1;
3548 if (bttv_tvcards[btv->c.type].volume_gpio) 3509 if (bttv_tvcards[btv->c.type].volume_gpio)
3549 btv->volume_gpio=bttv_tvcards[btv->c.type].volume_gpio; 3510 btv->volume_gpio = bttv_tvcards[btv->c.type].volume_gpio;
3550 if (bttv_tvcards[btv->c.type].audio_mode_gpio) 3511 if (bttv_tvcards[btv->c.type].audio_mode_gpio)
3551 btv->audio_mode_gpio=bttv_tvcards[btv->c.type].audio_mode_gpio; 3512 btv->audio_mode_gpio = bttv_tvcards[btv->c.type].audio_mode_gpio;
3552 3513
3553 if (btv->tuner_type == TUNER_ABSENT) 3514 if (btv->tuner_type == TUNER_ABSENT)
3554 return; /* no tuner or related drivers to load */ 3515 return; /* no tuner or related drivers to load */
@@ -3666,6 +3627,49 @@ no_audio:
3666} 3627}
3667 3628
3668 3629
3630/* initialize the tuner */
3631void __devinit bttv_init_tuner(struct bttv *btv)
3632{
3633 int addr = ADDR_UNSET;
3634
3635 if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr)
3636 addr = bttv_tvcards[btv->c.type].tuner_addr;
3637
3638 if (btv->tuner_type != TUNER_ABSENT) {
3639 struct tuner_setup tun_setup;
3640
3641 /* Load tuner module before issuing tuner config call! */
3642 if (bttv_tvcards[btv->c.type].has_radio)
3643 v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev,
3644 &btv->c.i2c_adap, "tuner", "tuner",
3645 v4l2_i2c_tuner_addrs(ADDRS_RADIO));
3646 v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev,
3647 &btv->c.i2c_adap, "tuner", "tuner",
3648 v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
3649 v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev,
3650 &btv->c.i2c_adap, "tuner", "tuner",
3651 v4l2_i2c_tuner_addrs(ADDRS_TV_WITH_DEMOD));
3652
3653 tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV;
3654 tun_setup.type = btv->tuner_type;
3655 tun_setup.addr = addr;
3656
3657 if (bttv_tvcards[btv->c.type].has_radio)
3658 tun_setup.mode_mask |= T_RADIO;
3659
3660 bttv_call_all(btv, tuner, s_type_addr, &tun_setup);
3661 }
3662
3663 if (btv->tda9887_conf) {
3664 struct v4l2_priv_tun_config tda9887_cfg;
3665
3666 tda9887_cfg.tuner = TUNER_TDA9887;
3667 tda9887_cfg.priv = &btv->tda9887_conf;
3668
3669 bttv_call_all(btv, tuner, s_config, &tda9887_cfg);
3670 }
3671}
3672
3669/* ----------------------------------------------------------------------- */ 3673/* ----------------------------------------------------------------------- */
3670 3674
3671static void modtec_eeprom(struct bttv *btv) 3675static void modtec_eeprom(struct bttv *btv)
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index d147d29bb0d3..8cc6dd28d6a7 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -4419,6 +4419,7 @@ static int __devinit bttv_probe(struct pci_dev *dev,
4419 4419
4420 /* some card-specific stuff (needs working i2c) */ 4420 /* some card-specific stuff (needs working i2c) */
4421 bttv_init_card2(btv); 4421 bttv_init_card2(btv);
4422 bttv_init_tuner(btv);
4422 init_irqreg(btv); 4423 init_irqreg(btv);
4423 4424
4424 /* register video4linux + input */ 4425 /* register video4linux + input */
diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h
index 3d36daf206f3..3ec2402c6b4a 100644
--- a/drivers/media/video/bt8xx/bttv.h
+++ b/drivers/media/video/bt8xx/bttv.h
@@ -283,6 +283,7 @@ extern struct tvcard bttv_tvcards[];
283extern void bttv_idcard(struct bttv *btv); 283extern void bttv_idcard(struct bttv *btv);
284extern void bttv_init_card1(struct bttv *btv); 284extern void bttv_init_card1(struct bttv *btv);
285extern void bttv_init_card2(struct bttv *btv); 285extern void bttv_init_card2(struct bttv *btv);
286extern void bttv_init_tuner(struct bttv *btv);
286 287
287/* card-specific funtions */ 288/* card-specific funtions */
288extern void tea5757_set_freq(struct bttv *btv, unsigned short freq); 289extern void tea5757_set_freq(struct bttv *btv, unsigned short freq);
diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c
index 428f0c45e6b7..e0cf21e0b1bf 100644
--- a/drivers/media/video/cx23885/cx23885-417.c
+++ b/drivers/media/video/cx23885/cx23885-417.c
@@ -58,7 +58,8 @@ MODULE_PARM_DESC(v4l_debug, "enable V4L debug messages");
58 58
59#define dprintk(level, fmt, arg...)\ 59#define dprintk(level, fmt, arg...)\
60 do { if (v4l_debug >= level) \ 60 do { if (v4l_debug >= level) \
61 printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg);\ 61 printk(KERN_DEBUG "%s: " fmt, \
62 (dev) ? dev->name : "cx23885[?]", ## arg); \
62 } while (0) 63 } while (0)
63 64
64static struct cx23885_tvnorm cx23885_tvnorms[] = { 65static struct cx23885_tvnorm cx23885_tvnorms[] = {
@@ -1677,6 +1678,7 @@ static struct v4l2_file_operations mpeg_fops = {
1677 .read = mpeg_read, 1678 .read = mpeg_read,
1678 .poll = mpeg_poll, 1679 .poll = mpeg_poll,
1679 .mmap = mpeg_mmap, 1680 .mmap = mpeg_mmap,
1681 .ioctl = video_ioctl2,
1680}; 1682};
1681 1683
1682static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { 1684static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index ebd24a25fb85..320f1f60276e 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -58,8 +58,6 @@ static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
58module_param_array(card, int, NULL, 0444); 58module_param_array(card, int, NULL, 0444);
59MODULE_PARM_DESC(card, "card type"); 59MODULE_PARM_DESC(card, "card type");
60 60
61#define MT9V011_VERSION 0x8243
62
63/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */ 61/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS */
64static unsigned long em28xx_devused; 62static unsigned long em28xx_devused;
65 63
@@ -159,6 +157,20 @@ static struct em28xx_reg_seq evga_indtube_digital[] = {
159 { -1, -1, -1, -1}, 157 { -1, -1, -1, -1},
160}; 158};
161 159
160/* Pinnacle Hybrid Pro eb1a:2881 */
161static struct em28xx_reg_seq pinnacle_hybrid_pro_analog[] = {
162 {EM28XX_R08_GPIO, 0xfd, ~EM_GPIO_4, 10},
163 { -1, -1, -1, -1},
164};
165
166static struct em28xx_reg_seq pinnacle_hybrid_pro_digital[] = {
167 {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10},
168 {EM2880_R04_GPO, 0x04, 0xff, 100},/* zl10353 reset */
169 {EM2880_R04_GPO, 0x0c, 0xff, 1},
170 { -1, -1, -1, -1},
171};
172
173
162/* Callback for the most boards */ 174/* Callback for the most boards */
163static struct em28xx_reg_seq default_tuner_gpio[] = { 175static struct em28xx_reg_seq default_tuner_gpio[] = {
164 {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, 176 {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10},
@@ -205,13 +217,15 @@ static struct em28xx_reg_seq silvercrest_reg_seq[] = {
205 */ 217 */
206struct em28xx_board em28xx_boards[] = { 218struct em28xx_board em28xx_boards[] = {
207 [EM2750_BOARD_UNKNOWN] = { 219 [EM2750_BOARD_UNKNOWN] = {
208 .name = "Unknown EM2750/EM2751 webcam grabber", 220 .name = "EM2710/EM2750/EM2751 webcam grabber",
209 .xclk = EM28XX_XCLK_FREQUENCY_48MHZ, 221 .xclk = EM28XX_XCLK_FREQUENCY_48MHZ,
210 .tuner_type = TUNER_ABSENT, /* This is a webcam */ 222 .tuner_type = TUNER_ABSENT,
223 .is_webcam = 1,
211 .input = { { 224 .input = { {
212 .type = EM28XX_VMUX_COMPOSITE1, 225 .type = EM28XX_VMUX_COMPOSITE1,
213 .vmux = 0, 226 .vmux = 0,
214 .amux = EM28XX_AMUX_VIDEO, 227 .amux = EM28XX_AMUX_VIDEO,
228 .gpio = silvercrest_reg_seq,
215 } }, 229 } },
216 }, 230 },
217 [EM2800_BOARD_UNKNOWN] = { 231 [EM2800_BOARD_UNKNOWN] = {
@@ -233,13 +247,15 @@ struct em28xx_board em28xx_boards[] = {
233 [EM2820_BOARD_UNKNOWN] = { 247 [EM2820_BOARD_UNKNOWN] = {
234 .name = "Unknown EM2750/28xx video grabber", 248 .name = "Unknown EM2750/28xx video grabber",
235 .tuner_type = TUNER_ABSENT, 249 .tuner_type = TUNER_ABSENT,
250 .is_webcam = 1, /* To enable sensor probe */
236 }, 251 },
237 [EM2750_BOARD_DLCW_130] = { 252 [EM2750_BOARD_DLCW_130] = {
238 /* Beijing Huaqi Information Digital Technology Co., Ltd */ 253 /* Beijing Huaqi Information Digital Technology Co., Ltd */
239 .name = "Huaqi DLCW-130", 254 .name = "Huaqi DLCW-130",
240 .valid = EM28XX_BOARD_NOT_VALIDATED, 255 .valid = EM28XX_BOARD_NOT_VALIDATED,
241 .xclk = EM28XX_XCLK_FREQUENCY_48MHZ, 256 .xclk = EM28XX_XCLK_FREQUENCY_48MHZ,
242 .tuner_type = TUNER_ABSENT, /* This is a webcam */ 257 .tuner_type = TUNER_ABSENT,
258 .is_webcam = 1,
243 .input = { { 259 .input = { {
244 .type = EM28XX_VMUX_COMPOSITE1, 260 .type = EM28XX_VMUX_COMPOSITE1,
245 .vmux = 0, 261 .vmux = 0,
@@ -440,7 +456,8 @@ struct em28xx_board em28xx_boards[] = {
440 [EM2820_BOARD_VIDEOLOGY_20K14XUSB] = { 456 [EM2820_BOARD_VIDEOLOGY_20K14XUSB] = {
441 .name = "Videology 20K14XUSB USB2.0", 457 .name = "Videology 20K14XUSB USB2.0",
442 .valid = EM28XX_BOARD_NOT_VALIDATED, 458 .valid = EM28XX_BOARD_NOT_VALIDATED,
443 .tuner_type = TUNER_ABSENT, /* This is a webcam */ 459 .tuner_type = TUNER_ABSENT,
460 .is_webcam = 1,
444 .input = { { 461 .input = { {
445 .type = EM28XX_VMUX_COMPOSITE1, 462 .type = EM28XX_VMUX_COMPOSITE1,
446 .vmux = 0, 463 .vmux = 0,
@@ -450,8 +467,7 @@ struct em28xx_board em28xx_boards[] = {
450 [EM2820_BOARD_SILVERCREST_WEBCAM] = { 467 [EM2820_BOARD_SILVERCREST_WEBCAM] = {
451 .name = "Silvercrest Webcam 1.3mpix", 468 .name = "Silvercrest Webcam 1.3mpix",
452 .tuner_type = TUNER_ABSENT, 469 .tuner_type = TUNER_ABSENT,
453 .is_27xx = 1, 470 .is_webcam = 1,
454 .decoder = EM28XX_MT9V011,
455 .input = { { 471 .input = { {
456 .type = EM28XX_VMUX_COMPOSITE1, 472 .type = EM28XX_VMUX_COMPOSITE1,
457 .vmux = 0, 473 .vmux = 0,
@@ -500,7 +516,8 @@ struct em28xx_board em28xx_boards[] = {
500 /* Beijing Huaqi Information Digital Technology Co., Ltd */ 516 /* Beijing Huaqi Information Digital Technology Co., Ltd */
501 .name = "NetGMBH Cam", 517 .name = "NetGMBH Cam",
502 .valid = EM28XX_BOARD_NOT_VALIDATED, 518 .valid = EM28XX_BOARD_NOT_VALIDATED,
503 .tuner_type = TUNER_ABSENT, /* This is a webcam */ 519 .tuner_type = TUNER_ABSENT,
520 .is_webcam = 1,
504 .input = { { 521 .input = { {
505 .type = EM28XX_VMUX_COMPOSITE1, 522 .type = EM28XX_VMUX_COMPOSITE1,
506 .vmux = 0, 523 .vmux = 0,
@@ -1250,25 +1267,26 @@ struct em28xx_board em28xx_boards[] = {
1250 }, 1267 },
1251 [EM2881_BOARD_PINNACLE_HYBRID_PRO] = { 1268 [EM2881_BOARD_PINNACLE_HYBRID_PRO] = {
1252 .name = "Pinnacle Hybrid Pro", 1269 .name = "Pinnacle Hybrid Pro",
1253 .valid = EM28XX_BOARD_NOT_VALIDATED,
1254 .tuner_type = TUNER_XC2028, 1270 .tuner_type = TUNER_XC2028,
1255 .tuner_gpio = default_tuner_gpio, 1271 .tuner_gpio = default_tuner_gpio,
1256 .decoder = EM28XX_TVP5150, 1272 .decoder = EM28XX_TVP5150,
1273 .has_dvb = 1,
1274 .dvb_gpio = pinnacle_hybrid_pro_digital,
1257 .input = { { 1275 .input = { {
1258 .type = EM28XX_VMUX_TELEVISION, 1276 .type = EM28XX_VMUX_TELEVISION,
1259 .vmux = TVP5150_COMPOSITE0, 1277 .vmux = TVP5150_COMPOSITE0,
1260 .amux = EM28XX_AMUX_VIDEO, 1278 .amux = EM28XX_AMUX_VIDEO,
1261 .gpio = default_analog, 1279 .gpio = pinnacle_hybrid_pro_analog,
1262 }, { 1280 }, {
1263 .type = EM28XX_VMUX_COMPOSITE1, 1281 .type = EM28XX_VMUX_COMPOSITE1,
1264 .vmux = TVP5150_COMPOSITE1, 1282 .vmux = TVP5150_COMPOSITE1,
1265 .amux = EM28XX_AMUX_LINE_IN, 1283 .amux = EM28XX_AMUX_LINE_IN,
1266 .gpio = default_analog, 1284 .gpio = pinnacle_hybrid_pro_analog,
1267 }, { 1285 }, {
1268 .type = EM28XX_VMUX_SVIDEO, 1286 .type = EM28XX_VMUX_SVIDEO,
1269 .vmux = TVP5150_SVIDEO, 1287 .vmux = TVP5150_SVIDEO,
1270 .amux = EM28XX_AMUX_LINE_IN, 1288 .amux = EM28XX_AMUX_LINE_IN,
1271 .gpio = default_analog, 1289 .gpio = pinnacle_hybrid_pro_analog,
1272 } }, 1290 } },
1273 }, 1291 },
1274 [EM2882_BOARD_PINNACLE_HYBRID_PRO] = { 1292 [EM2882_BOARD_PINNACLE_HYBRID_PRO] = {
@@ -1638,6 +1656,7 @@ static struct em28xx_hash_table em28xx_eeprom_hash[] = {
1638 {0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028}, 1656 {0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028},
1639 {0x9567eb1a, EM2880_BOARD_EMPIRE_DUAL_TV, TUNER_XC2028}, 1657 {0x9567eb1a, EM2880_BOARD_EMPIRE_DUAL_TV, TUNER_XC2028},
1640 {0xcee44a99, EM2882_BOARD_EVGA_INDTUBE, TUNER_XC2028}, 1658 {0xcee44a99, EM2882_BOARD_EVGA_INDTUBE, TUNER_XC2028},
1659 {0xb8846b20, EM2881_BOARD_PINNACLE_HYBRID_PRO, TUNER_XC2028},
1641}; 1660};
1642 1661
1643/* I2C devicelist hash table for devices with generic USB IDs */ 1662/* I2C devicelist hash table for devices with generic USB IDs */
@@ -1704,6 +1723,32 @@ static inline void em28xx_set_model(struct em28xx *dev)
1704 EM28XX_I2C_FREQ_100_KHZ; 1723 EM28XX_I2C_FREQ_100_KHZ;
1705} 1724}
1706 1725
1726/* FIXME: Should be replaced by a proper mt9m001 driver */
1727static int em28xx_initialize_mt9m001(struct em28xx *dev)
1728{
1729 int i;
1730 unsigned char regs[][3] = {
1731 { 0x0d, 0x00, 0x01, },
1732 { 0x0d, 0x00, 0x00, },
1733 { 0x04, 0x05, 0x00, }, /* hres = 1280 */
1734 { 0x03, 0x04, 0x00, }, /* vres = 1024 */
1735 { 0x20, 0x11, 0x00, },
1736 { 0x06, 0x00, 0x10, },
1737 { 0x2b, 0x00, 0x24, },
1738 { 0x2e, 0x00, 0x24, },
1739 { 0x35, 0x00, 0x24, },
1740 { 0x2d, 0x00, 0x20, },
1741 { 0x2c, 0x00, 0x20, },
1742 { 0x09, 0x0a, 0xd4, },
1743 { 0x35, 0x00, 0x57, },
1744 };
1745
1746 for (i = 0; i < ARRAY_SIZE(regs); i++)
1747 i2c_master_send(&dev->i2c_client, &regs[i][0], 3);
1748
1749 return 0;
1750}
1751
1707/* HINT method: webcam I2C chips 1752/* HINT method: webcam I2C chips
1708 * 1753 *
1709 * This method work for webcams with Micron sensors 1754 * This method work for webcams with Micron sensors
@@ -1716,9 +1761,6 @@ static int em28xx_hint_sensor(struct em28xx *dev)
1716 __be16 version_be; 1761 __be16 version_be;
1717 u16 version; 1762 u16 version;
1718 1763
1719 if (dev->model != EM2820_BOARD_UNKNOWN)
1720 return 0;
1721
1722 dev->i2c_client.addr = 0xba >> 1; 1764 dev->i2c_client.addr = 0xba >> 1;
1723 cmd = 0; 1765 cmd = 0;
1724 i2c_master_send(&dev->i2c_client, &cmd, 1); 1766 i2c_master_send(&dev->i2c_client, &cmd, 1);
@@ -1729,16 +1771,38 @@ static int em28xx_hint_sensor(struct em28xx *dev)
1729 version = be16_to_cpu(version_be); 1771 version = be16_to_cpu(version_be);
1730 1772
1731 switch (version) { 1773 switch (version) {
1732 case MT9V011_VERSION: 1774 case 0x8243: /* mt9v011 640x480 1.3 Mpix sensor */
1733 dev->model = EM2820_BOARD_SILVERCREST_WEBCAM; 1775 dev->model = EM2820_BOARD_SILVERCREST_WEBCAM;
1734 sensor_name = "mt9v011"; 1776 sensor_name = "mt9v011";
1777 dev->em28xx_sensor = EM28XX_MT9V011;
1778 dev->sensor_xres = 640;
1779 dev->sensor_yres = 480;
1780 dev->sensor_xtal = 6300000;
1781
1782 /* probably means GRGB 16 bit bayer */
1783 dev->vinmode = 0x0d;
1784 dev->vinctl = 0x00;
1785
1786 break;
1787 case 0x8431:
1788 dev->model = EM2750_BOARD_UNKNOWN;
1789 sensor_name = "mt9m001";
1790 dev->em28xx_sensor = EM28XX_MT9M001;
1791 em28xx_initialize_mt9m001(dev);
1792 dev->sensor_xres = 1280;
1793 dev->sensor_yres = 1024;
1794
1795 /* probably means BGGR 16 bit bayer */
1796 dev->vinmode = 0x0c;
1797 dev->vinctl = 0x00;
1798
1735 break; 1799 break;
1736 default: 1800 default:
1737 printk("Unknown Sensor 0x%04x\n", be16_to_cpu(version)); 1801 printk("Unknown Micron Sensor 0x%04x\n", be16_to_cpu(version));
1738 return -EINVAL; 1802 return -EINVAL;
1739 } 1803 }
1740 1804
1741 em28xx_errdev("Sensor is %s, assuming that webcam is %s\n", 1805 em28xx_errdev("Sensor is %s, using model %s entry.\n",
1742 sensor_name, em28xx_boards[dev->model].name); 1806 sensor_name, em28xx_boards[dev->model].name);
1743 1807
1744 return 0; 1808 return 0;
@@ -1772,10 +1836,7 @@ void em28xx_pre_card_setup(struct em28xx *dev)
1772 em28xx_info("chip ID is em2750\n"); 1836 em28xx_info("chip ID is em2750\n");
1773 break; 1837 break;
1774 case CHIP_ID_EM2820: 1838 case CHIP_ID_EM2820:
1775 if (dev->board.is_27xx) 1839 em28xx_info("chip ID is em2710 or em2820\n");
1776 em28xx_info("chip is em2710\n");
1777 else
1778 em28xx_info("chip ID is em2820\n");
1779 break; 1840 break;
1780 case CHIP_ID_EM2840: 1841 case CHIP_ID_EM2840:
1781 em28xx_info("chip ID is em2840\n"); 1842 em28xx_info("chip ID is em2840\n");
@@ -1929,6 +1990,7 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
1929 ctl->demod = XC3028_FE_ZARLINK456; 1990 ctl->demod = XC3028_FE_ZARLINK456;
1930 break; 1991 break;
1931 case EM2880_BOARD_TERRATEC_HYBRID_XS: 1992 case EM2880_BOARD_TERRATEC_HYBRID_XS:
1993 case EM2881_BOARD_PINNACLE_HYBRID_PRO:
1932 ctl->demod = XC3028_FE_ZARLINK456; 1994 ctl->demod = XC3028_FE_ZARLINK456;
1933 break; 1995 break;
1934 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: 1996 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
@@ -2225,6 +2287,7 @@ void em28xx_card_setup(struct em28xx *dev)
2225 em28xx_set_mode() in em28xx_pre_card_setup() was a no-op, 2287 em28xx_set_mode() in em28xx_pre_card_setup() was a no-op,
2226 so make the call now so the analog GPIOs are set properly 2288 so make the call now so the analog GPIOs are set properly
2227 before probing the i2c bus. */ 2289 before probing the i2c bus. */
2290 em28xx_gpio_set(dev, dev->board.tuner_gpio);
2228 em28xx_set_mode(dev, EM28XX_ANALOG_MODE); 2291 em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
2229 break; 2292 break;
2230 case EM2820_BOARD_SILVERCREST_WEBCAM: 2293 case EM2820_BOARD_SILVERCREST_WEBCAM:
@@ -2262,9 +2325,14 @@ void em28xx_card_setup(struct em28xx *dev)
2262 v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, 2325 v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap,
2263 "tvp5150", "tvp5150", tvp5150_addrs); 2326 "tvp5150", "tvp5150", tvp5150_addrs);
2264 2327
2265 if (dev->board.decoder == EM28XX_MT9V011) 2328 if (dev->em28xx_sensor == EM28XX_MT9V011) {
2266 v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap, 2329 struct v4l2_subdev *sd;
2267 "mt9v011", "mt9v011", mt9v011_addrs); 2330
2331 sd = v4l2_i2c_new_probed_subdev(&dev->v4l2_dev,
2332 &dev->i2c_adap, "mt9v011", "mt9v011", mt9v011_addrs);
2333 v4l2_subdev_call(sd, core, s_config, 0, &dev->sensor_xtal);
2334 }
2335
2268 2336
2269 if (dev->board.adecoder == EM28XX_TVAUDIO) 2337 if (dev->board.adecoder == EM28XX_TVAUDIO)
2270 v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap, 2338 v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
@@ -2410,7 +2478,19 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
2410 return errCode; 2478 return errCode;
2411 } 2479 }
2412 2480
2413 em28xx_hint_sensor(dev); 2481 /*
2482 * Default format, used for tvp5150 or saa711x output formats
2483 */
2484 dev->vinmode = 0x10;
2485 dev->vinctl = 0x11;
2486
2487 /*
2488 * If the device can be a webcam, seek for a sensor.
2489 * If sensor is not found, then it isn't a webcam.
2490 */
2491 if (dev->board.is_webcam)
2492 if (em28xx_hint_sensor(dev) < 0)
2493 dev->board.is_webcam = 0;
2414 2494
2415 /* Do board specific init and eeprom reading */ 2495 /* Do board specific init and eeprom reading */
2416 em28xx_card_setup(dev); 2496 em28xx_card_setup(dev);
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index 079ab4d563a6..5b78e199abd1 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -648,28 +648,17 @@ int em28xx_capture_start(struct em28xx *dev, int start)
648int em28xx_set_outfmt(struct em28xx *dev) 648int em28xx_set_outfmt(struct em28xx *dev)
649{ 649{
650 int ret; 650 int ret;
651 int vinmode, vinctl, outfmt;
652
653 outfmt = dev->format->reg;
654
655 if (dev->board.is_27xx) {
656 vinmode = 0x0d;
657 vinctl = 0x00;
658 } else {
659 vinmode = 0x10;
660 vinctl = 0x11;
661 }
662 651
663 ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT, 652 ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT,
664 outfmt | 0x20, 0xff); 653 dev->format->reg | 0x20, 0xff);
665 if (ret < 0) 654 if (ret < 0)
666 return ret; 655 return ret;
667 656
668 ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, vinmode); 657 ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, dev->vinmode);
669 if (ret < 0) 658 if (ret < 0)
670 return ret; 659 return ret;
671 660
672 return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctl); 661 return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, dev->vinctl);
673} 662}
674 663
675static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, 664static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
@@ -707,10 +696,7 @@ static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
707 u8 mode; 696 u8 mode;
708 /* the em2800 scaler only supports scaling down to 50% */ 697 /* the em2800 scaler only supports scaling down to 50% */
709 698
710 if (dev->board.is_27xx) { 699 if (dev->board.is_em2800) {
711 /* FIXME: Don't use the scaler yet */
712 mode = 0;
713 } else if (dev->board.is_em2800) {
714 mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00); 700 mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
715 } else { 701 } else {
716 u8 buf[2]; 702 u8 buf[2];
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c
index 3da97c32b8fa..cf0ac7f2a30d 100644
--- a/drivers/media/video/em28xx/em28xx-dvb.c
+++ b/drivers/media/video/em28xx/em28xx-dvb.c
@@ -31,6 +31,8 @@
31#include "lgdt330x.h" 31#include "lgdt330x.h"
32#include "zl10353.h" 32#include "zl10353.h"
33#include "s5h1409.h" 33#include "s5h1409.h"
34#include "mt352.h"
35#include "mt352_priv.h" /* FIXME */
34 36
35MODULE_DESCRIPTION("driver for em28xx based DVB cards"); 37MODULE_DESCRIPTION("driver for em28xx based DVB cards");
36MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); 38MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
@@ -243,7 +245,7 @@ static struct s5h1409_config em28xx_s5h1409_with_xc3028 = {
243 .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK 245 .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK
244}; 246};
245 247
246static struct zl10353_config em28xx_terratec_xs_zl10353_xc3028 = { 248static struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = {
247 .demod_address = (0x1e >> 1), 249 .demod_address = (0x1e >> 1),
248 .no_tuner = 1, 250 .no_tuner = 1,
249 .disable_i2c_gate_ctrl = 1, 251 .disable_i2c_gate_ctrl = 1,
@@ -258,6 +260,41 @@ static struct drx397xD_config em28xx_drx397xD_with_xc3028 = {
258}; 260};
259#endif 261#endif
260 262
263static int mt352_terratec_xs_init(struct dvb_frontend *fe)
264{
265 /* Values extracted from a USB trace of the Terratec Windows driver */
266 static u8 clock_config[] = { CLOCK_CTL, 0x38, 0x2c };
267 static u8 reset[] = { RESET, 0x80 };
268 static u8 adc_ctl_1_cfg[] = { ADC_CTL_1, 0x40 };
269 static u8 agc_cfg[] = { AGC_TARGET, 0x28, 0xa0 };
270 static u8 input_freq_cfg[] = { INPUT_FREQ_1, 0x31, 0xb8 };
271 static u8 rs_err_cfg[] = { RS_ERR_PER_1, 0x00, 0x4d };
272 static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
273 static u8 trl_nom_cfg[] = { TRL_NOMINAL_RATE_1, 0x64, 0x00 };
274 static u8 tps_given_cfg[] = { TPS_GIVEN_1, 0x40, 0x80, 0x50 };
275 static u8 tuner_go[] = { TUNER_GO, 0x01};
276
277 mt352_write(fe, clock_config, sizeof(clock_config));
278 udelay(200);
279 mt352_write(fe, reset, sizeof(reset));
280 mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
281 mt352_write(fe, agc_cfg, sizeof(agc_cfg));
282 mt352_write(fe, input_freq_cfg, sizeof(input_freq_cfg));
283 mt352_write(fe, rs_err_cfg, sizeof(rs_err_cfg));
284 mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
285 mt352_write(fe, trl_nom_cfg, sizeof(trl_nom_cfg));
286 mt352_write(fe, tps_given_cfg, sizeof(tps_given_cfg));
287 mt352_write(fe, tuner_go, sizeof(tuner_go));
288 return 0;
289}
290
291static struct mt352_config terratec_xs_mt352_cfg = {
292 .demod_address = (0x1e >> 1),
293 .no_tuner = 1,
294 .if2 = 45600,
295 .demod_init = mt352_terratec_xs_init,
296};
297
261/* ------------------------------------------------------------------ */ 298/* ------------------------------------------------------------------ */
262 299
263static int attach_xc3028(u8 addr, struct em28xx *dev) 300static int attach_xc3028(u8 addr, struct em28xx *dev)
@@ -440,7 +477,6 @@ static int dvb_init(struct em28xx *dev)
440 goto out_free; 477 goto out_free;
441 } 478 }
442 break; 479 break;
443 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
444 case EM2880_BOARD_KWORLD_DVB_310U: 480 case EM2880_BOARD_KWORLD_DVB_310U:
445 case EM2880_BOARD_EMPIRE_DUAL_TV: 481 case EM2880_BOARD_EMPIRE_DUAL_TV:
446 dvb->frontend = dvb_attach(zl10353_attach, 482 dvb->frontend = dvb_attach(zl10353_attach,
@@ -451,20 +487,28 @@ static int dvb_init(struct em28xx *dev)
451 goto out_free; 487 goto out_free;
452 } 488 }
453 break; 489 break;
490 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
491 dvb->frontend = dvb_attach(zl10353_attach,
492 &em28xx_zl10353_xc3028_no_i2c_gate,
493 &dev->i2c_adap);
494 if (attach_xc3028(0x61, dev) < 0) {
495 result = -EINVAL;
496 goto out_free;
497 }
498 break;
454 case EM2880_BOARD_TERRATEC_HYBRID_XS: 499 case EM2880_BOARD_TERRATEC_HYBRID_XS:
500 case EM2881_BOARD_PINNACLE_HYBRID_PRO:
455 dvb->frontend = dvb_attach(zl10353_attach, 501 dvb->frontend = dvb_attach(zl10353_attach,
456 &em28xx_terratec_xs_zl10353_xc3028, 502 &em28xx_zl10353_xc3028_no_i2c_gate,
457 &dev->i2c_adap); 503 &dev->i2c_adap);
458 if (dvb->frontend == NULL) { 504 if (dvb->frontend == NULL) {
459 /* This board could have either a zl10353 or a mt352. 505 /* This board could have either a zl10353 or a mt352.
460 If the chip id isn't for zl10353, try mt352 */ 506 If the chip id isn't for zl10353, try mt352 */
461 507 dvb->frontend = dvb_attach(mt352_attach,
462 /* FIXME: make support for mt352 work */ 508 &terratec_xs_mt352_cfg,
463 printk(KERN_ERR "version of this board with mt352 not " 509 &dev->i2c_adap);
464 "currently supported\n");
465 result = -EINVAL;
466 goto out_free;
467 } 510 }
511
468 if (attach_xc3028(0x61, dev) < 0) { 512 if (attach_xc3028(0x61, dev) < 0) {
469 result = -EINVAL; 513 result = -EINVAL;
470 goto out_free; 514 goto out_free;
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 14316c912179..ff37b4c15f44 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -657,8 +657,8 @@ static void get_scale(struct em28xx *dev,
657 unsigned int width, unsigned int height, 657 unsigned int width, unsigned int height,
658 unsigned int *hscale, unsigned int *vscale) 658 unsigned int *hscale, unsigned int *vscale)
659{ 659{
660 unsigned int maxw = norm_maxw(dev); 660 unsigned int maxw = norm_maxw(dev);
661 unsigned int maxh = norm_maxh(dev); 661 unsigned int maxh = norm_maxh(dev);
662 662
663 *hscale = (((unsigned long)maxw) << 12) / width - 4096L; 663 *hscale = (((unsigned long)maxw) << 12) / width - 4096L;
664 if (*hscale >= 0x4000) 664 if (*hscale >= 0x4000)
@@ -726,11 +726,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
726 return -EINVAL; 726 return -EINVAL;
727 } 727 }
728 728
729 if (dev->board.is_27xx) { 729 if (dev->board.is_em2800) {
730 /* FIXME: This is the only supported fmt */
731 width = 640;
732 height = 480;
733 } else if (dev->board.is_em2800) {
734 /* the em2800 can only scale down to 50% */ 730 /* the em2800 can only scale down to 50% */
735 height = height > (3 * maxh / 4) ? maxh : maxh / 2; 731 height = height > (3 * maxh / 4) ? maxh : maxh / 2;
736 width = width > (3 * maxw / 4) ? maxw : maxw / 2; 732 width = width > (3 * maxw / 4) ? maxw : maxw / 2;
@@ -767,12 +763,6 @@ static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc,
767{ 763{
768 struct em28xx_fmt *fmt; 764 struct em28xx_fmt *fmt;
769 765
770 /* FIXME: This is the only supported fmt */
771 if (dev->board.is_27xx) {
772 width = 640;
773 height = 480;
774 }
775
776 fmt = format_by_fourcc(fourcc); 766 fmt = format_by_fourcc(fourcc);
777 if (!fmt) 767 if (!fmt)
778 return -EINVAL; 768 return -EINVAL;
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index d90fef463764..45bd513f62dc 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -358,10 +358,15 @@ struct em28xx_input {
358#define INPUT(nr) (&em28xx_boards[dev->model].input[nr]) 358#define INPUT(nr) (&em28xx_boards[dev->model].input[nr])
359 359
360enum em28xx_decoder { 360enum em28xx_decoder {
361 EM28XX_NODECODER, 361 EM28XX_NODECODER = 0,
362 EM28XX_TVP5150, 362 EM28XX_TVP5150,
363 EM28XX_SAA711X, 363 EM28XX_SAA711X,
364};
365
366enum em28xx_sensor {
367 EM28XX_NOSENSOR = 0,
364 EM28XX_MT9V011, 368 EM28XX_MT9V011,
369 EM28XX_MT9M001,
365}; 370};
366 371
367enum em28xx_adecoder { 372enum em28xx_adecoder {
@@ -390,7 +395,7 @@ struct em28xx_board {
390 unsigned int max_range_640_480:1; 395 unsigned int max_range_640_480:1;
391 unsigned int has_dvb:1; 396 unsigned int has_dvb:1;
392 unsigned int has_snapshot_button:1; 397 unsigned int has_snapshot_button:1;
393 unsigned int is_27xx:1; 398 unsigned int is_webcam:1;
394 unsigned int valid:1; 399 unsigned int valid:1;
395 400
396 unsigned char xclk, i2c_speed; 401 unsigned char xclk, i2c_speed;
@@ -474,6 +479,14 @@ struct em28xx {
474 struct v4l2_device v4l2_dev; 479 struct v4l2_device v4l2_dev;
475 struct em28xx_board board; 480 struct em28xx_board board;
476 481
482 /* Webcam specific fields */
483 enum em28xx_sensor em28xx_sensor;
484 int sensor_xres, sensor_yres;
485 int sensor_xtal;
486
487 /* Vinmode/Vinctl used at the driver */
488 int vinmode, vinctl;
489
477 unsigned int stream_on:1; /* Locks streams */ 490 unsigned int stream_on:1; /* Locks streams */
478 unsigned int has_audio_class:1; 491 unsigned int has_audio_class:1;
479 unsigned int has_alsa_audio:1; 492 unsigned int has_alsa_audio:1;
@@ -754,17 +767,23 @@ static inline int em28xx_gamma_set(struct em28xx *dev, s32 val)
754/*FIXME: maxw should be dependent of alt mode */ 767/*FIXME: maxw should be dependent of alt mode */
755static inline unsigned int norm_maxw(struct em28xx *dev) 768static inline unsigned int norm_maxw(struct em28xx *dev)
756{ 769{
770 if (dev->board.is_webcam)
771 return dev->sensor_xres;
772
757 if (dev->board.max_range_640_480) 773 if (dev->board.max_range_640_480)
758 return 640; 774 return 640;
759 else 775
760 return 720; 776 return 720;
761} 777}
762 778
763static inline unsigned int norm_maxh(struct em28xx *dev) 779static inline unsigned int norm_maxh(struct em28xx *dev)
764{ 780{
781 if (dev->board.is_webcam)
782 return dev->sensor_yres;
783
765 if (dev->board.max_range_640_480) 784 if (dev->board.max_range_640_480)
766 return 480; 785 return 480;
767 else 786
768 return (dev->norm & V4L2_STD_625_50) ? 576 : 480; 787 return (dev->norm & V4L2_STD_625_50) ? 576 : 480;
769} 788}
770#endif 789#endif
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig
index 578dc4ffc965..34f46f2bc040 100644
--- a/drivers/media/video/gspca/Kconfig
+++ b/drivers/media/video/gspca/Kconfig
@@ -102,6 +102,22 @@ config USB_GSPCA_PAC7311
102 To compile this driver as a module, choose M here: the 102 To compile this driver as a module, choose M here: the
103 module will be called gspca_pac7311. 103 module will be called gspca_pac7311.
104 104
105config USB_GSPCA_SN9C20X
106 tristate "SN9C20X USB Camera Driver"
107 depends on VIDEO_V4L2 && USB_GSPCA
108 help
109 Say Y here if you want support for cameras based on the
110 sn9c20x chips (SN9C201 and SN9C202).
111
112 To compile this driver as a module, choose M here: the
113 module will be called gspca_sn9c20x.
114
115config USB_GSPCA_SN9C20X_EVDEV
116 bool "Enable evdev support"
117 depends on USB_GSPCA_SN9C20X
118 ---help---
119 Say Y here in order to enable evdev support for sn9c20x webcam button.
120
105config USB_GSPCA_SONIXB 121config USB_GSPCA_SONIXB
106 tristate "SONIX Bayer USB Camera Driver" 122 tristate "SONIX Bayer USB Camera Driver"
107 depends on VIDEO_V4L2 && USB_GSPCA 123 depends on VIDEO_V4L2 && USB_GSPCA
diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile
index 8a6643e8eb96..f6d3b86e9ad5 100644
--- a/drivers/media/video/gspca/Makefile
+++ b/drivers/media/video/gspca/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o
8obj-$(CONFIG_USB_GSPCA_OV534) += gspca_ov534.o 8obj-$(CONFIG_USB_GSPCA_OV534) += gspca_ov534.o
9obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o 9obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o
10obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o 10obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o
11obj-$(CONFIG_USB_GSPCA_SN9C20X) += gspca_sn9c20x.o
11obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o 12obj-$(CONFIG_USB_GSPCA_SONIXB) += gspca_sonixb.o
12obj-$(CONFIG_USB_GSPCA_SONIXJ) += gspca_sonixj.o 13obj-$(CONFIG_USB_GSPCA_SONIXJ) += gspca_sonixj.o
13obj-$(CONFIG_USB_GSPCA_SPCA500) += gspca_spca500.o 14obj-$(CONFIG_USB_GSPCA_SPCA500) += gspca_spca500.o
@@ -35,6 +36,7 @@ gspca_ov519-objs := ov519.o
35gspca_ov534-objs := ov534.o 36gspca_ov534-objs := ov534.o
36gspca_pac207-objs := pac207.o 37gspca_pac207-objs := pac207.o
37gspca_pac7311-objs := pac7311.o 38gspca_pac7311-objs := pac7311.o
39gspca_sn9c20x-objs := sn9c20x.o
38gspca_sonixb-objs := sonixb.o 40gspca_sonixb-objs := sonixb.o
39gspca_sonixj-objs := sonixj.o 41gspca_sonixj-objs := sonixj.o
40gspca_spca500-objs := spca500.o 42gspca_spca500-objs := spca500.o
diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c
index 219cfa6fb877..8d48ea1742c2 100644
--- a/drivers/media/video/gspca/conex.c
+++ b/drivers/media/video/gspca/conex.c
@@ -846,6 +846,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
846 846
847 /* create the JPEG header */ 847 /* create the JPEG header */
848 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); 848 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
849 if (!sd->jpeg_hdr)
850 return -ENOMEM;
849 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, 851 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
850 0x22); /* JPEG 411 */ 852 0x22); /* JPEG 411 */
851 jpeg_set_qual(sd->jpeg_hdr, sd->quality); 853 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index 1e89600986c8..b8561dfb6c8c 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -727,6 +727,74 @@ static int gspca_get_mode(struct gspca_dev *gspca_dev,
727 return -EINVAL; 727 return -EINVAL;
728} 728}
729 729
730#ifdef CONFIG_VIDEO_ADV_DEBUG
731static int vidioc_g_register(struct file *file, void *priv,
732 struct v4l2_dbg_register *reg)
733{
734 int ret;
735 struct gspca_dev *gspca_dev = priv;
736
737 if (!gspca_dev->sd_desc->get_chip_ident)
738 return -EINVAL;
739
740 if (!gspca_dev->sd_desc->get_register)
741 return -EINVAL;
742
743 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
744 return -ERESTARTSYS;
745 if (gspca_dev->present)
746 ret = gspca_dev->sd_desc->get_register(gspca_dev, reg);
747 else
748 ret = -ENODEV;
749 mutex_unlock(&gspca_dev->usb_lock);
750
751 return ret;
752}
753
754static int vidioc_s_register(struct file *file, void *priv,
755 struct v4l2_dbg_register *reg)
756{
757 int ret;
758 struct gspca_dev *gspca_dev = priv;
759
760 if (!gspca_dev->sd_desc->get_chip_ident)
761 return -EINVAL;
762
763 if (!gspca_dev->sd_desc->set_register)
764 return -EINVAL;
765
766 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
767 return -ERESTARTSYS;
768 if (gspca_dev->present)
769 ret = gspca_dev->sd_desc->set_register(gspca_dev, reg);
770 else
771 ret = -ENODEV;
772 mutex_unlock(&gspca_dev->usb_lock);
773
774 return ret;
775}
776#endif
777
778static int vidioc_g_chip_ident(struct file *file, void *priv,
779 struct v4l2_dbg_chip_ident *chip)
780{
781 int ret;
782 struct gspca_dev *gspca_dev = priv;
783
784 if (!gspca_dev->sd_desc->get_chip_ident)
785 return -EINVAL;
786
787 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
788 return -ERESTARTSYS;
789 if (gspca_dev->present)
790 ret = gspca_dev->sd_desc->get_chip_ident(gspca_dev, chip);
791 else
792 ret = -ENODEV;
793 mutex_unlock(&gspca_dev->usb_lock);
794
795 return ret;
796}
797
730static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, 798static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
731 struct v4l2_fmtdesc *fmtdesc) 799 struct v4l2_fmtdesc *fmtdesc)
732{ 800{
@@ -1883,6 +1951,11 @@ static const struct v4l2_ioctl_ops dev_ioctl_ops = {
1883 .vidioc_s_parm = vidioc_s_parm, 1951 .vidioc_s_parm = vidioc_s_parm,
1884 .vidioc_s_std = vidioc_s_std, 1952 .vidioc_s_std = vidioc_s_std,
1885 .vidioc_enum_framesizes = vidioc_enum_framesizes, 1953 .vidioc_enum_framesizes = vidioc_enum_framesizes,
1954#ifdef CONFIG_VIDEO_ADV_DEBUG
1955 .vidioc_g_register = vidioc_g_register,
1956 .vidioc_s_register = vidioc_s_register,
1957#endif
1958 .vidioc_g_chip_ident = vidioc_g_chip_ident,
1886#ifdef CONFIG_VIDEO_V4L1_COMPAT 1959#ifdef CONFIG_VIDEO_V4L1_COMPAT
1887 .vidiocgmbuf = vidiocgmbuf, 1960 .vidiocgmbuf = vidiocgmbuf,
1888#endif 1961#endif
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h
index bd1faff88644..46c4effdfcd5 100644
--- a/drivers/media/video/gspca/gspca.h
+++ b/drivers/media/video/gspca/gspca.h
@@ -69,6 +69,10 @@ typedef void (*cam_v_op) (struct gspca_dev *);
69typedef int (*cam_cf_op) (struct gspca_dev *, const struct usb_device_id *); 69typedef int (*cam_cf_op) (struct gspca_dev *, const struct usb_device_id *);
70typedef int (*cam_jpg_op) (struct gspca_dev *, 70typedef int (*cam_jpg_op) (struct gspca_dev *,
71 struct v4l2_jpegcompression *); 71 struct v4l2_jpegcompression *);
72typedef int (*cam_reg_op) (struct gspca_dev *,
73 struct v4l2_dbg_register *);
74typedef int (*cam_ident_op) (struct gspca_dev *,
75 struct v4l2_dbg_chip_ident *);
72typedef int (*cam_streamparm_op) (struct gspca_dev *, 76typedef int (*cam_streamparm_op) (struct gspca_dev *,
73 struct v4l2_streamparm *); 77 struct v4l2_streamparm *);
74typedef int (*cam_qmnu_op) (struct gspca_dev *, 78typedef int (*cam_qmnu_op) (struct gspca_dev *,
@@ -105,6 +109,11 @@ struct sd_desc {
105 cam_qmnu_op querymenu; 109 cam_qmnu_op querymenu;
106 cam_streamparm_op get_streamparm; 110 cam_streamparm_op get_streamparm;
107 cam_streamparm_op set_streamparm; 111 cam_streamparm_op set_streamparm;
112#ifdef CONFIG_VIDEO_ADV_DEBUG
113 cam_reg_op set_register;
114 cam_reg_op get_register;
115#endif
116 cam_ident_op get_chip_ident;
108}; 117};
109 118
110/* packet types when moving from iso buf to frame buf */ 119/* packet types when moving from iso buf to frame buf */
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
index 191bcd718979..0163903d1c0f 100644
--- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
+++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
@@ -476,9 +476,6 @@ static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
476 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); 476 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
477 if (err < 0) 477 if (err < 0)
478 return err; 478 return err;
479 err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
480 if (err < 0)
481 return err;
482 479
483 err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1); 480 err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
484 if (err < 0) 481 if (err < 0)
@@ -524,9 +521,6 @@ static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
524 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1); 521 err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
525 if (err < 0) 522 if (err < 0)
526 return err; 523 return err;
527 err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
528 if (err < 0)
529 return err;
530 524
531 err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1); 525 err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
532 if (err < 0) 526 if (err < 0)
diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c
index 75e8d14e4ac7..de769caf013d 100644
--- a/drivers/media/video/gspca/mars.c
+++ b/drivers/media/video/gspca/mars.c
@@ -201,6 +201,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
201 201
202 /* create the JPEG header */ 202 /* create the JPEG header */
203 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); 203 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
204 if (!sd->jpeg_hdr)
205 return -ENOMEM;
204 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, 206 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
205 0x21); /* JPEG 422 */ 207 0x21); /* JPEG 422 */
206 jpeg_set_qual(sd->jpeg_hdr, sd->quality); 208 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c
new file mode 100644
index 000000000000..fcfbbd329b4c
--- /dev/null
+++ b/drivers/media/video/gspca/sn9c20x.c
@@ -0,0 +1,2434 @@
1/*
2 * Sonix sn9c201 sn9c202 library
3 * Copyright (C) 2008-2009 microdia project <microdia@googlegroups.com>
4 * Copyright (C) 2009 Brian Johnson <brijohn@gmail.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 * 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#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV
22#include <linux/kthread.h>
23#include <linux/freezer.h>
24#include <linux/usb/input.h>
25#include <linux/input.h>
26#endif
27
28#include "gspca.h"
29#include "jpeg.h"
30
31#include <media/v4l2-chip-ident.h>
32
33MODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, "
34 "microdia project <microdia@googlegroups.com>");
35MODULE_DESCRIPTION("GSPCA/SN9C20X USB Camera Driver");
36MODULE_LICENSE("GPL");
37
38#define MODULE_NAME "sn9c20x"
39
40#define MODE_RAW 0x10
41#define MODE_JPEG 0x20
42#define MODE_SXGA 0x80
43
44#define SENSOR_OV9650 0
45#define SENSOR_OV9655 1
46#define SENSOR_SOI968 2
47#define SENSOR_OV7660 3
48#define SENSOR_OV7670 4
49#define SENSOR_MT9V011 5
50#define SENSOR_MT9V111 6
51#define SENSOR_MT9V112 7
52#define SENSOR_MT9M001 8
53#define SENSOR_MT9M111 9
54#define SENSOR_HV7131R 10
55#define SENSOR_MT9VPRB 20
56
57/* specific webcam descriptor */
58struct sd {
59 struct gspca_dev gspca_dev;
60
61#define MIN_AVG_LUM 80
62#define MAX_AVG_LUM 130
63 atomic_t avg_lum;
64 u8 old_step;
65 u8 older_step;
66 u8 exposure_step;
67
68 u8 brightness;
69 u8 contrast;
70 u8 saturation;
71 s16 hue;
72 u8 gamma;
73 u8 red;
74 u8 blue;
75
76 u8 hflip;
77 u8 vflip;
78 u8 gain;
79 u16 exposure;
80 u8 auto_exposure;
81
82 u8 i2c_addr;
83 u8 sensor;
84 u8 hstart;
85 u8 vstart;
86
87 u8 *jpeg_hdr;
88 u8 quality;
89
90#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV
91 struct input_dev *input_dev;
92 u8 input_gpio;
93 struct task_struct *input_task;
94#endif
95};
96
97static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val);
98static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val);
99static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val);
100static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val);
101static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val);
102static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val);
103static int sd_sethue(struct gspca_dev *gspca_dev, s32 val);
104static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val);
105static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val);
106static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val);
107static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val);
108static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val);
109static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val);
110static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val);
111static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val);
112static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val);
113static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val);
114static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val);
115static int sd_setgain(struct gspca_dev *gspca_dev, s32 val);
116static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val);
117static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val);
118static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val);
119static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val);
120static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val);
121
122static struct ctrl sd_ctrls[] = {
123 {
124#define BRIGHTNESS_IDX 0
125 {
126 .id = V4L2_CID_BRIGHTNESS,
127 .type = V4L2_CTRL_TYPE_INTEGER,
128 .name = "Brightness",
129 .minimum = 0,
130 .maximum = 0xff,
131 .step = 1,
132#define BRIGHTNESS_DEFAULT 0x7f
133 .default_value = BRIGHTNESS_DEFAULT,
134 },
135 .set = sd_setbrightness,
136 .get = sd_getbrightness,
137 },
138 {
139#define CONTRAST_IDX 1
140 {
141 .id = V4L2_CID_CONTRAST,
142 .type = V4L2_CTRL_TYPE_INTEGER,
143 .name = "Contrast",
144 .minimum = 0,
145 .maximum = 0xff,
146 .step = 1,
147#define CONTRAST_DEFAULT 0x7f
148 .default_value = CONTRAST_DEFAULT,
149 },
150 .set = sd_setcontrast,
151 .get = sd_getcontrast,
152 },
153 {
154#define SATURATION_IDX 2
155 {
156 .id = V4L2_CID_SATURATION,
157 .type = V4L2_CTRL_TYPE_INTEGER,
158 .name = "Saturation",
159 .minimum = 0,
160 .maximum = 0xff,
161 .step = 1,
162#define SATURATION_DEFAULT 0x7f
163 .default_value = SATURATION_DEFAULT,
164 },
165 .set = sd_setsaturation,
166 .get = sd_getsaturation,
167 },
168 {
169#define HUE_IDX 3
170 {
171 .id = V4L2_CID_HUE,
172 .type = V4L2_CTRL_TYPE_INTEGER,
173 .name = "Hue",
174 .minimum = -180,
175 .maximum = 180,
176 .step = 1,
177#define HUE_DEFAULT 0
178 .default_value = HUE_DEFAULT,
179 },
180 .set = sd_sethue,
181 .get = sd_gethue,
182 },
183 {
184#define GAMMA_IDX 4
185 {
186 .id = V4L2_CID_GAMMA,
187 .type = V4L2_CTRL_TYPE_INTEGER,
188 .name = "Gamma",
189 .minimum = 0,
190 .maximum = 0xff,
191 .step = 1,
192#define GAMMA_DEFAULT 0x10
193 .default_value = GAMMA_DEFAULT,
194 },
195 .set = sd_setgamma,
196 .get = sd_getgamma,
197 },
198 {
199#define BLUE_IDX 5
200 {
201 .id = V4L2_CID_BLUE_BALANCE,
202 .type = V4L2_CTRL_TYPE_INTEGER,
203 .name = "Blue Balance",
204 .minimum = 0,
205 .maximum = 0x7f,
206 .step = 1,
207#define BLUE_DEFAULT 0x28
208 .default_value = BLUE_DEFAULT,
209 },
210 .set = sd_setbluebalance,
211 .get = sd_getbluebalance,
212 },
213 {
214#define RED_IDX 6
215 {
216 .id = V4L2_CID_RED_BALANCE,
217 .type = V4L2_CTRL_TYPE_INTEGER,
218 .name = "Red Balance",
219 .minimum = 0,
220 .maximum = 0x7f,
221 .step = 1,
222#define RED_DEFAULT 0x28
223 .default_value = RED_DEFAULT,
224 },
225 .set = sd_setredbalance,
226 .get = sd_getredbalance,
227 },
228 {
229#define HFLIP_IDX 7
230 {
231 .id = V4L2_CID_HFLIP,
232 .type = V4L2_CTRL_TYPE_BOOLEAN,
233 .name = "Horizontal Flip",
234 .minimum = 0,
235 .maximum = 1,
236 .step = 1,
237#define HFLIP_DEFAULT 0
238 .default_value = HFLIP_DEFAULT,
239 },
240 .set = sd_sethflip,
241 .get = sd_gethflip,
242 },
243 {
244#define VFLIP_IDX 8
245 {
246 .id = V4L2_CID_VFLIP,
247 .type = V4L2_CTRL_TYPE_BOOLEAN,
248 .name = "Vertical Flip",
249 .minimum = 0,
250 .maximum = 1,
251 .step = 1,
252#define VFLIP_DEFAULT 0
253 .default_value = VFLIP_DEFAULT,
254 },
255 .set = sd_setvflip,
256 .get = sd_getvflip,
257 },
258 {
259#define EXPOSURE_IDX 9
260 {
261 .id = V4L2_CID_EXPOSURE,
262 .type = V4L2_CTRL_TYPE_INTEGER,
263 .name = "Exposure",
264 .minimum = 0,
265 .maximum = 0x1780,
266 .step = 1,
267#define EXPOSURE_DEFAULT 0x33
268 .default_value = EXPOSURE_DEFAULT,
269 },
270 .set = sd_setexposure,
271 .get = sd_getexposure,
272 },
273 {
274#define GAIN_IDX 10
275 {
276 .id = V4L2_CID_GAIN,
277 .type = V4L2_CTRL_TYPE_INTEGER,
278 .name = "Gain",
279 .minimum = 0,
280 .maximum = 28,
281 .step = 1,
282#define GAIN_DEFAULT 0x00
283 .default_value = GAIN_DEFAULT,
284 },
285 .set = sd_setgain,
286 .get = sd_getgain,
287 },
288 {
289#define AUTOGAIN_IDX 11
290 {
291 .id = V4L2_CID_AUTOGAIN,
292 .type = V4L2_CTRL_TYPE_BOOLEAN,
293 .name = "Auto Exposure",
294 .minimum = 0,
295 .maximum = 1,
296 .step = 1,
297#define AUTO_EXPOSURE_DEFAULT 1
298 .default_value = AUTO_EXPOSURE_DEFAULT,
299 },
300 .set = sd_setautoexposure,
301 .get = sd_getautoexposure,
302 },
303};
304
305static const struct v4l2_pix_format vga_mode[] = {
306 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
307 .bytesperline = 240,
308 .sizeimage = 240 * 120,
309 .colorspace = V4L2_COLORSPACE_JPEG,
310 .priv = 0 | MODE_JPEG},
311 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
312 .bytesperline = 160,
313 .sizeimage = 160 * 120,
314 .colorspace = V4L2_COLORSPACE_SRGB,
315 .priv = 0 | MODE_RAW},
316 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
317 .bytesperline = 240,
318 .sizeimage = 240 * 120,
319 .colorspace = V4L2_COLORSPACE_SRGB,
320 .priv = 0},
321 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
322 .bytesperline = 480,
323 .sizeimage = 480 * 240 ,
324 .colorspace = V4L2_COLORSPACE_JPEG,
325 .priv = 1 | MODE_JPEG},
326 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
327 .bytesperline = 320,
328 .sizeimage = 320 * 240 ,
329 .colorspace = V4L2_COLORSPACE_SRGB,
330 .priv = 1 | MODE_RAW},
331 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
332 .bytesperline = 480,
333 .sizeimage = 480 * 240 ,
334 .colorspace = V4L2_COLORSPACE_SRGB,
335 .priv = 1},
336 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
337 .bytesperline = 960,
338 .sizeimage = 960 * 480,
339 .colorspace = V4L2_COLORSPACE_JPEG,
340 .priv = 2 | MODE_JPEG},
341 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
342 .bytesperline = 640,
343 .sizeimage = 640 * 480,
344 .colorspace = V4L2_COLORSPACE_SRGB,
345 .priv = 2 | MODE_RAW},
346 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
347 .bytesperline = 960,
348 .sizeimage = 960 * 480,
349 .colorspace = V4L2_COLORSPACE_SRGB,
350 .priv = 2},
351};
352
353static const struct v4l2_pix_format sxga_mode[] = {
354 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
355 .bytesperline = 240,
356 .sizeimage = 240 * 120,
357 .colorspace = V4L2_COLORSPACE_JPEG,
358 .priv = 0 | MODE_JPEG},
359 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
360 .bytesperline = 160,
361 .sizeimage = 160 * 120,
362 .colorspace = V4L2_COLORSPACE_SRGB,
363 .priv = 0 | MODE_RAW},
364 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
365 .bytesperline = 240,
366 .sizeimage = 240 * 120,
367 .colorspace = V4L2_COLORSPACE_SRGB,
368 .priv = 0},
369 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
370 .bytesperline = 480,
371 .sizeimage = 480 * 240 ,
372 .colorspace = V4L2_COLORSPACE_JPEG,
373 .priv = 1 | MODE_JPEG},
374 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
375 .bytesperline = 320,
376 .sizeimage = 320 * 240 ,
377 .colorspace = V4L2_COLORSPACE_SRGB,
378 .priv = 1 | MODE_RAW},
379 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
380 .bytesperline = 480,
381 .sizeimage = 480 * 240 ,
382 .colorspace = V4L2_COLORSPACE_SRGB,
383 .priv = 1},
384 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
385 .bytesperline = 960,
386 .sizeimage = 960 * 480,
387 .colorspace = V4L2_COLORSPACE_JPEG,
388 .priv = 2 | MODE_JPEG},
389 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
390 .bytesperline = 640,
391 .sizeimage = 640 * 480,
392 .colorspace = V4L2_COLORSPACE_SRGB,
393 .priv = 2 | MODE_RAW},
394 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
395 .bytesperline = 960,
396 .sizeimage = 960 * 480,
397 .colorspace = V4L2_COLORSPACE_SRGB,
398 .priv = 2},
399 {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
400 .bytesperline = 1280,
401 .sizeimage = (1280 * 1024) + 64,
402 .colorspace = V4L2_COLORSPACE_SRGB,
403 .priv = 3 | MODE_RAW | MODE_SXGA},
404};
405
406static const int hsv_red_x[] = {
407 41, 44, 46, 48, 50, 52, 54, 56,
408 58, 60, 62, 64, 66, 68, 70, 72,
409 74, 76, 78, 80, 81, 83, 85, 87,
410 88, 90, 92, 93, 95, 97, 98, 100,
411 101, 102, 104, 105, 107, 108, 109, 110,
412 112, 113, 114, 115, 116, 117, 118, 119,
413 120, 121, 122, 123, 123, 124, 125, 125,
414 126, 127, 127, 128, 128, 129, 129, 129,
415 130, 130, 130, 130, 131, 131, 131, 131,
416 131, 131, 131, 131, 130, 130, 130, 130,
417 129, 129, 129, 128, 128, 127, 127, 126,
418 125, 125, 124, 123, 122, 122, 121, 120,
419 119, 118, 117, 116, 115, 114, 112, 111,
420 110, 109, 107, 106, 105, 103, 102, 101,
421 99, 98, 96, 94, 93, 91, 90, 88,
422 86, 84, 83, 81, 79, 77, 75, 74,
423 72, 70, 68, 66, 64, 62, 60, 58,
424 56, 54, 52, 49, 47, 45, 43, 41,
425 39, 36, 34, 32, 30, 28, 25, 23,
426 21, 19, 16, 14, 12, 9, 7, 5,
427 3, 0, -1, -3, -6, -8, -10, -12,
428 -15, -17, -19, -22, -24, -26, -28, -30,
429 -33, -35, -37, -39, -41, -44, -46, -48,
430 -50, -52, -54, -56, -58, -60, -62, -64,
431 -66, -68, -70, -72, -74, -76, -78, -80,
432 -81, -83, -85, -87, -88, -90, -92, -93,
433 -95, -97, -98, -100, -101, -102, -104, -105,
434 -107, -108, -109, -110, -112, -113, -114, -115,
435 -116, -117, -118, -119, -120, -121, -122, -123,
436 -123, -124, -125, -125, -126, -127, -127, -128,
437 -128, -128, -128, -128, -128, -128, -128, -128,
438 -128, -128, -128, -128, -128, -128, -128, -128,
439 -128, -128, -128, -128, -128, -128, -128, -128,
440 -128, -127, -127, -126, -125, -125, -124, -123,
441 -122, -122, -121, -120, -119, -118, -117, -116,
442 -115, -114, -112, -111, -110, -109, -107, -106,
443 -105, -103, -102, -101, -99, -98, -96, -94,
444 -93, -91, -90, -88, -86, -84, -83, -81,
445 -79, -77, -75, -74, -72, -70, -68, -66,
446 -64, -62, -60, -58, -56, -54, -52, -49,
447 -47, -45, -43, -41, -39, -36, -34, -32,
448 -30, -28, -25, -23, -21, -19, -16, -14,
449 -12, -9, -7, -5, -3, 0, 1, 3,
450 6, 8, 10, 12, 15, 17, 19, 22,
451 24, 26, 28, 30, 33, 35, 37, 39, 41
452};
453
454static const int hsv_red_y[] = {
455 82, 80, 78, 76, 74, 73, 71, 69,
456 67, 65, 63, 61, 58, 56, 54, 52,
457 50, 48, 46, 44, 41, 39, 37, 35,
458 32, 30, 28, 26, 23, 21, 19, 16,
459 14, 12, 10, 7, 5, 3, 0, -1,
460 -3, -6, -8, -10, -13, -15, -17, -19,
461 -22, -24, -26, -29, -31, -33, -35, -38,
462 -40, -42, -44, -46, -48, -51, -53, -55,
463 -57, -59, -61, -63, -65, -67, -69, -71,
464 -73, -75, -77, -79, -81, -82, -84, -86,
465 -88, -89, -91, -93, -94, -96, -98, -99,
466 -101, -102, -104, -105, -106, -108, -109, -110,
467 -112, -113, -114, -115, -116, -117, -119, -120,
468 -120, -121, -122, -123, -124, -125, -126, -126,
469 -127, -128, -128, -128, -128, -128, -128, -128,
470 -128, -128, -128, -128, -128, -128, -128, -128,
471 -128, -128, -128, -128, -128, -128, -128, -128,
472 -128, -128, -128, -128, -128, -128, -128, -128,
473 -127, -127, -126, -125, -125, -124, -123, -122,
474 -121, -120, -119, -118, -117, -116, -115, -114,
475 -113, -111, -110, -109, -107, -106, -105, -103,
476 -102, -100, -99, -97, -96, -94, -92, -91,
477 -89, -87, -85, -84, -82, -80, -78, -76,
478 -74, -73, -71, -69, -67, -65, -63, -61,
479 -58, -56, -54, -52, -50, -48, -46, -44,
480 -41, -39, -37, -35, -32, -30, -28, -26,
481 -23, -21, -19, -16, -14, -12, -10, -7,
482 -5, -3, 0, 1, 3, 6, 8, 10,
483 13, 15, 17, 19, 22, 24, 26, 29,
484 31, 33, 35, 38, 40, 42, 44, 46,
485 48, 51, 53, 55, 57, 59, 61, 63,
486 65, 67, 69, 71, 73, 75, 77, 79,
487 81, 82, 84, 86, 88, 89, 91, 93,
488 94, 96, 98, 99, 101, 102, 104, 105,
489 106, 108, 109, 110, 112, 113, 114, 115,
490 116, 117, 119, 120, 120, 121, 122, 123,
491 124, 125, 126, 126, 127, 128, 128, 129,
492 129, 130, 130, 131, 131, 131, 131, 132,
493 132, 132, 132, 132, 132, 132, 132, 132,
494 132, 132, 132, 131, 131, 131, 130, 130,
495 130, 129, 129, 128, 127, 127, 126, 125,
496 125, 124, 123, 122, 121, 120, 119, 118,
497 117, 116, 115, 114, 113, 111, 110, 109,
498 107, 106, 105, 103, 102, 100, 99, 97,
499 96, 94, 92, 91, 89, 87, 85, 84, 82
500};
501
502static const int hsv_green_x[] = {
503 -124, -124, -125, -125, -125, -125, -125, -125,
504 -125, -126, -126, -125, -125, -125, -125, -125,
505 -125, -124, -124, -124, -123, -123, -122, -122,
506 -121, -121, -120, -120, -119, -118, -117, -117,
507 -116, -115, -114, -113, -112, -111, -110, -109,
508 -108, -107, -105, -104, -103, -102, -100, -99,
509 -98, -96, -95, -93, -92, -91, -89, -87,
510 -86, -84, -83, -81, -79, -77, -76, -74,
511 -72, -70, -69, -67, -65, -63, -61, -59,
512 -57, -55, -53, -51, -49, -47, -45, -43,
513 -41, -39, -37, -35, -33, -30, -28, -26,
514 -24, -22, -20, -18, -15, -13, -11, -9,
515 -7, -4, -2, 0, 1, 3, 6, 8,
516 10, 12, 14, 17, 19, 21, 23, 25,
517 27, 29, 32, 34, 36, 38, 40, 42,
518 44, 46, 48, 50, 52, 54, 56, 58,
519 60, 62, 64, 66, 68, 70, 71, 73,
520 75, 77, 78, 80, 82, 83, 85, 87,
521 88, 90, 91, 93, 94, 96, 97, 98,
522 100, 101, 102, 104, 105, 106, 107, 108,
523 109, 111, 112, 113, 113, 114, 115, 116,
524 117, 118, 118, 119, 120, 120, 121, 122,
525 122, 123, 123, 124, 124, 124, 125, 125,
526 125, 125, 125, 125, 125, 126, 126, 125,
527 125, 125, 125, 125, 125, 124, 124, 124,
528 123, 123, 122, 122, 121, 121, 120, 120,
529 119, 118, 117, 117, 116, 115, 114, 113,
530 112, 111, 110, 109, 108, 107, 105, 104,
531 103, 102, 100, 99, 98, 96, 95, 93,
532 92, 91, 89, 87, 86, 84, 83, 81,
533 79, 77, 76, 74, 72, 70, 69, 67,
534 65, 63, 61, 59, 57, 55, 53, 51,
535 49, 47, 45, 43, 41, 39, 37, 35,
536 33, 30, 28, 26, 24, 22, 20, 18,
537 15, 13, 11, 9, 7, 4, 2, 0,
538 -1, -3, -6, -8, -10, -12, -14, -17,
539 -19, -21, -23, -25, -27, -29, -32, -34,
540 -36, -38, -40, -42, -44, -46, -48, -50,
541 -52, -54, -56, -58, -60, -62, -64, -66,
542 -68, -70, -71, -73, -75, -77, -78, -80,
543 -82, -83, -85, -87, -88, -90, -91, -93,
544 -94, -96, -97, -98, -100, -101, -102, -104,
545 -105, -106, -107, -108, -109, -111, -112, -113,
546 -113, -114, -115, -116, -117, -118, -118, -119,
547 -120, -120, -121, -122, -122, -123, -123, -124, -124
548};
549
550static const int hsv_green_y[] = {
551 -100, -99, -98, -97, -95, -94, -93, -91,
552 -90, -89, -87, -86, -84, -83, -81, -80,
553 -78, -76, -75, -73, -71, -70, -68, -66,
554 -64, -63, -61, -59, -57, -55, -53, -51,
555 -49, -48, -46, -44, -42, -40, -38, -36,
556 -34, -32, -30, -27, -25, -23, -21, -19,
557 -17, -15, -13, -11, -9, -7, -4, -2,
558 0, 1, 3, 5, 7, 9, 11, 14,
559 16, 18, 20, 22, 24, 26, 28, 30,
560 32, 34, 36, 38, 40, 42, 44, 46,
561 48, 50, 52, 54, 56, 58, 59, 61,
562 63, 65, 67, 68, 70, 72, 74, 75,
563 77, 78, 80, 82, 83, 85, 86, 88,
564 89, 90, 92, 93, 95, 96, 97, 98,
565 100, 101, 102, 103, 104, 105, 106, 107,
566 108, 109, 110, 111, 112, 112, 113, 114,
567 115, 115, 116, 116, 117, 117, 118, 118,
568 119, 119, 119, 120, 120, 120, 120, 120,
569 121, 121, 121, 121, 121, 121, 120, 120,
570 120, 120, 120, 119, 119, 119, 118, 118,
571 117, 117, 116, 116, 115, 114, 114, 113,
572 112, 111, 111, 110, 109, 108, 107, 106,
573 105, 104, 103, 102, 100, 99, 98, 97,
574 95, 94, 93, 91, 90, 89, 87, 86,
575 84, 83, 81, 80, 78, 76, 75, 73,
576 71, 70, 68, 66, 64, 63, 61, 59,
577 57, 55, 53, 51, 49, 48, 46, 44,
578 42, 40, 38, 36, 34, 32, 30, 27,
579 25, 23, 21, 19, 17, 15, 13, 11,
580 9, 7, 4, 2, 0, -1, -3, -5,
581 -7, -9, -11, -14, -16, -18, -20, -22,
582 -24, -26, -28, -30, -32, -34, -36, -38,
583 -40, -42, -44, -46, -48, -50, -52, -54,
584 -56, -58, -59, -61, -63, -65, -67, -68,
585 -70, -72, -74, -75, -77, -78, -80, -82,
586 -83, -85, -86, -88, -89, -90, -92, -93,
587 -95, -96, -97, -98, -100, -101, -102, -103,
588 -104, -105, -106, -107, -108, -109, -110, -111,
589 -112, -112, -113, -114, -115, -115, -116, -116,
590 -117, -117, -118, -118, -119, -119, -119, -120,
591 -120, -120, -120, -120, -121, -121, -121, -121,
592 -121, -121, -120, -120, -120, -120, -120, -119,
593 -119, -119, -118, -118, -117, -117, -116, -116,
594 -115, -114, -114, -113, -112, -111, -111, -110,
595 -109, -108, -107, -106, -105, -104, -103, -102, -100
596};
597
598static const int hsv_blue_x[] = {
599 112, 113, 114, 114, 115, 116, 117, 117,
600 118, 118, 119, 119, 120, 120, 120, 121,
601 121, 121, 122, 122, 122, 122, 122, 122,
602 122, 122, 122, 122, 122, 122, 121, 121,
603 121, 120, 120, 120, 119, 119, 118, 118,
604 117, 116, 116, 115, 114, 113, 113, 112,
605 111, 110, 109, 108, 107, 106, 105, 104,
606 103, 102, 100, 99, 98, 97, 95, 94,
607 93, 91, 90, 88, 87, 85, 84, 82,
608 80, 79, 77, 76, 74, 72, 70, 69,
609 67, 65, 63, 61, 60, 58, 56, 54,
610 52, 50, 48, 46, 44, 42, 40, 38,
611 36, 34, 32, 30, 28, 26, 24, 22,
612 19, 17, 15, 13, 11, 9, 7, 5,
613 2, 0, -1, -3, -5, -7, -9, -12,
614 -14, -16, -18, -20, -22, -24, -26, -28,
615 -31, -33, -35, -37, -39, -41, -43, -45,
616 -47, -49, -51, -53, -54, -56, -58, -60,
617 -62, -64, -66, -67, -69, -71, -73, -74,
618 -76, -78, -79, -81, -83, -84, -86, -87,
619 -89, -90, -92, -93, -94, -96, -97, -98,
620 -99, -101, -102, -103, -104, -105, -106, -107,
621 -108, -109, -110, -111, -112, -113, -114, -114,
622 -115, -116, -117, -117, -118, -118, -119, -119,
623 -120, -120, -120, -121, -121, -121, -122, -122,
624 -122, -122, -122, -122, -122, -122, -122, -122,
625 -122, -122, -121, -121, -121, -120, -120, -120,
626 -119, -119, -118, -118, -117, -116, -116, -115,
627 -114, -113, -113, -112, -111, -110, -109, -108,
628 -107, -106, -105, -104, -103, -102, -100, -99,
629 -98, -97, -95, -94, -93, -91, -90, -88,
630 -87, -85, -84, -82, -80, -79, -77, -76,
631 -74, -72, -70, -69, -67, -65, -63, -61,
632 -60, -58, -56, -54, -52, -50, -48, -46,
633 -44, -42, -40, -38, -36, -34, -32, -30,
634 -28, -26, -24, -22, -19, -17, -15, -13,
635 -11, -9, -7, -5, -2, 0, 1, 3,
636 5, 7, 9, 12, 14, 16, 18, 20,
637 22, 24, 26, 28, 31, 33, 35, 37,
638 39, 41, 43, 45, 47, 49, 51, 53,
639 54, 56, 58, 60, 62, 64, 66, 67,
640 69, 71, 73, 74, 76, 78, 79, 81,
641 83, 84, 86, 87, 89, 90, 92, 93,
642 94, 96, 97, 98, 99, 101, 102, 103,
643 104, 105, 106, 107, 108, 109, 110, 111, 112
644};
645
646static const int hsv_blue_y[] = {
647 -11, -13, -15, -17, -19, -21, -23, -25,
648 -27, -29, -31, -33, -35, -37, -39, -41,
649 -43, -45, -46, -48, -50, -52, -54, -55,
650 -57, -59, -61, -62, -64, -66, -67, -69,
651 -71, -72, -74, -75, -77, -78, -80, -81,
652 -83, -84, -86, -87, -88, -90, -91, -92,
653 -93, -95, -96, -97, -98, -99, -100, -101,
654 -102, -103, -104, -105, -106, -106, -107, -108,
655 -109, -109, -110, -111, -111, -112, -112, -113,
656 -113, -114, -114, -114, -115, -115, -115, -115,
657 -116, -116, -116, -116, -116, -116, -116, -116,
658 -116, -115, -115, -115, -115, -114, -114, -114,
659 -113, -113, -112, -112, -111, -111, -110, -110,
660 -109, -108, -108, -107, -106, -105, -104, -103,
661 -102, -101, -100, -99, -98, -97, -96, -95,
662 -94, -93, -91, -90, -89, -88, -86, -85,
663 -84, -82, -81, -79, -78, -76, -75, -73,
664 -71, -70, -68, -67, -65, -63, -62, -60,
665 -58, -56, -55, -53, -51, -49, -47, -45,
666 -44, -42, -40, -38, -36, -34, -32, -30,
667 -28, -26, -24, -22, -20, -18, -16, -14,
668 -12, -10, -8, -6, -4, -2, 0, 1,
669 3, 5, 7, 9, 11, 13, 15, 17,
670 19, 21, 23, 25, 27, 29, 31, 33,
671 35, 37, 39, 41, 43, 45, 46, 48,
672 50, 52, 54, 55, 57, 59, 61, 62,
673 64, 66, 67, 69, 71, 72, 74, 75,
674 77, 78, 80, 81, 83, 84, 86, 87,
675 88, 90, 91, 92, 93, 95, 96, 97,
676 98, 99, 100, 101, 102, 103, 104, 105,
677 106, 106, 107, 108, 109, 109, 110, 111,
678 111, 112, 112, 113, 113, 114, 114, 114,
679 115, 115, 115, 115, 116, 116, 116, 116,
680 116, 116, 116, 116, 116, 115, 115, 115,
681 115, 114, 114, 114, 113, 113, 112, 112,
682 111, 111, 110, 110, 109, 108, 108, 107,
683 106, 105, 104, 103, 102, 101, 100, 99,
684 98, 97, 96, 95, 94, 93, 91, 90,
685 89, 88, 86, 85, 84, 82, 81, 79,
686 78, 76, 75, 73, 71, 70, 68, 67,
687 65, 63, 62, 60, 58, 56, 55, 53,
688 51, 49, 47, 45, 44, 42, 40, 38,
689 36, 34, 32, 30, 28, 26, 24, 22,
690 20, 18, 16, 14, 12, 10, 8, 6,
691 4, 2, 0, -1, -3, -5, -7, -9, -11
692};
693
694static u16 i2c_ident[] = {
695 V4L2_IDENT_OV9650,
696 V4L2_IDENT_OV9655,
697 V4L2_IDENT_SOI968,
698 V4L2_IDENT_OV7660,
699 V4L2_IDENT_OV7670,
700 V4L2_IDENT_MT9V011,
701 V4L2_IDENT_MT9V111,
702 V4L2_IDENT_MT9V112,
703 V4L2_IDENT_MT9M001C12ST,
704 V4L2_IDENT_MT9M111,
705 V4L2_IDENT_HV7131R,
706};
707
708static u16 bridge_init[][2] = {
709 {0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c},
710 {0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40},
711 {0x1068, 0x30}, {0x1069, 0x20}, {0x106a, 0x10},
712 {0x106b, 0x08}, {0x1188, 0x87}, {0x11a1, 0x00},
713 {0x11a2, 0x00}, {0x11a3, 0x6a}, {0x11a4, 0x50},
714 {0x11ab, 0x00}, {0x11ac, 0x00}, {0x11ad, 0x50},
715 {0x11ae, 0x3c}, {0x118a, 0x04}, {0x0395, 0x04},
716 {0x11b8, 0x3a}, {0x118b, 0x0e}, {0x10f7, 0x05},
717 {0x10f8, 0x14}, {0x10fa, 0xff}, {0x10f9, 0x00},
718 {0x11ba, 0x0a}, {0x11a5, 0x2d}, {0x11a6, 0x2d},
719 {0x11a7, 0x3a}, {0x11a8, 0x05}, {0x11a9, 0x04},
720 {0x11aa, 0x3f}, {0x11af, 0x28}, {0x11b0, 0xd8},
721 {0x11b1, 0x14}, {0x11b2, 0xec}, {0x11b3, 0x32},
722 {0x11b4, 0xdd}, {0x11b5, 0x32}, {0x11b6, 0xdd},
723 {0x10e0, 0x2c}, {0x11bc, 0x40}, {0x11bd, 0x01},
724 {0x11be, 0xf0}, {0x11bf, 0x00}, {0x118c, 0x1f},
725 {0x118d, 0x1f}, {0x118e, 0x1f}, {0x118f, 0x1f},
726 {0x1180, 0x01}, {0x1181, 0x00}, {0x1182, 0x01},
727 {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80}
728};
729
730/* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */
731static u8 ov_gain[] = {
732 0x00 /* 1x */, 0x04 /* 1.25x */, 0x08 /* 1.5x */, 0x0c /* 1.75x */,
733 0x10 /* 2x */, 0x12 /* 2.25x */, 0x14 /* 2.5x */, 0x16 /* 2.75x */,
734 0x18 /* 3x */, 0x1a /* 3.25x */, 0x1c /* 3.5x */, 0x1e /* 3.75x */,
735 0x30 /* 4x */, 0x31 /* 4.25x */, 0x32 /* 4.5x */, 0x33 /* 4.75x */,
736 0x34 /* 5x */, 0x35 /* 5.25x */, 0x36 /* 5.5x */, 0x37 /* 5.75x */,
737 0x38 /* 6x */, 0x39 /* 6.25x */, 0x3a /* 6.5x */, 0x3b /* 6.75x */,
738 0x3c /* 7x */, 0x3d /* 7.25x */, 0x3e /* 7.5x */, 0x3f /* 7.75x */,
739 0x70 /* 8x */
740};
741
742/* Gain = (bit[8] + 1) * (bit[7] + 1) * (bit[6:0] * 0.03125) */
743static u16 micron1_gain[] = {
744 /* 1x 1.25x 1.5x 1.75x */
745 0x0020, 0x0028, 0x0030, 0x0038,
746 /* 2x 2.25x 2.5x 2.75x */
747 0x00a0, 0x00a4, 0x00a8, 0x00ac,
748 /* 3x 3.25x 3.5x 3.75x */
749 0x00b0, 0x00b4, 0x00b8, 0x00bc,
750 /* 4x 4.25x 4.5x 4.75x */
751 0x00c0, 0x00c4, 0x00c8, 0x00cc,
752 /* 5x 5.25x 5.5x 5.75x */
753 0x00d0, 0x00d4, 0x00d8, 0x00dc,
754 /* 6x 6.25x 6.5x 6.75x */
755 0x00e0, 0x00e4, 0x00e8, 0x00ec,
756 /* 7x 7.25x 7.5x 7.75x */
757 0x00f0, 0x00f4, 0x00f8, 0x00fc,
758 /* 8x */
759 0x01c0
760};
761
762/* mt9m001 sensor uses a different gain formula then other micron sensors */
763/* Gain = (bit[6] + 1) * (bit[5-0] * 0.125) */
764static u16 micron2_gain[] = {
765 /* 1x 1.25x 1.5x 1.75x */
766 0x0008, 0x000a, 0x000c, 0x000e,
767 /* 2x 2.25x 2.5x 2.75x */
768 0x0010, 0x0012, 0x0014, 0x0016,
769 /* 3x 3.25x 3.5x 3.75x */
770 0x0018, 0x001a, 0x001c, 0x001e,
771 /* 4x 4.25x 4.5x 4.75x */
772 0x0020, 0x0051, 0x0052, 0x0053,
773 /* 5x 5.25x 5.5x 5.75x */
774 0x0054, 0x0055, 0x0056, 0x0057,
775 /* 6x 6.25x 6.5x 6.75x */
776 0x0058, 0x0059, 0x005a, 0x005b,
777 /* 7x 7.25x 7.5x 7.75x */
778 0x005c, 0x005d, 0x005e, 0x005f,
779 /* 8x */
780 0x0060
781};
782
783/* Gain = .5 + bit[7:0] / 16 */
784static u8 hv7131r_gain[] = {
785 0x08 /* 1x */, 0x0c /* 1.25x */, 0x10 /* 1.5x */, 0x14 /* 1.75x */,
786 0x18 /* 2x */, 0x1c /* 2.25x */, 0x20 /* 2.5x */, 0x24 /* 2.75x */,
787 0x28 /* 3x */, 0x2c /* 3.25x */, 0x30 /* 3.5x */, 0x34 /* 3.75x */,
788 0x38 /* 4x */, 0x3c /* 4.25x */, 0x40 /* 4.5x */, 0x44 /* 4.75x */,
789 0x48 /* 5x */, 0x4c /* 5.25x */, 0x50 /* 5.5x */, 0x54 /* 5.75x */,
790 0x58 /* 6x */, 0x5c /* 6.25x */, 0x60 /* 6.5x */, 0x64 /* 6.75x */,
791 0x68 /* 7x */, 0x6c /* 7.25x */, 0x70 /* 7.5x */, 0x74 /* 7.75x */,
792 0x78 /* 8x */
793};
794
795static u8 soi968_init[][2] = {
796 {0x12, 0x80}, {0x0c, 0x00}, {0x0f, 0x1f},
797 {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00},
798 {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c},
799 {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff},
800 {0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20},
801 {0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e},
802 {0x13, 0x8a}, {0x12, 0x40}, {0x17, 0x13},
803 {0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79},
804 {0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40},
805 {0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32},
806 {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80},
807};
808
809static u8 ov7660_init[][2] = {
810 {0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3},
811 {0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40},
812 {0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a},
813 {0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43},
814 {0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0xf6},
815 {0x2e, 0x0b}, {0x01, 0x78}, {0x02, 0x50},
816};
817
818static u8 ov7670_init[][2] = {
819 {0x12, 0x80}, {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01},
820 {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00},
821 {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0},
822 {0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00},
823 {0x0d, 0x40}, {0x14, 0x28}, {0xa5, 0x05}, {0xab, 0x07},
824 {0x24, 0x95}, {0x25, 0x33}, {0x26, 0xe3}, {0x9f, 0x75},
825 {0xa0, 0x65}, {0xa1, 0x0b}, {0xa6, 0xd8}, {0xa7, 0xd8},
826 {0xa8, 0xf0}, {0xa9, 0x90}, {0xaa, 0x94}, {0x13, 0xe5},
827 {0x0e, 0x61}, {0x0f, 0x4b}, {0x16, 0x02}, {0x1e, 0x27},
828 {0x21, 0x02}, {0x22, 0x91}, {0x29, 0x07}, {0x33, 0x0b},
829 {0x35, 0x0b}, {0x37, 0x1d}, {0x38, 0x71}, {0x39, 0x2a},
830 {0x3c, 0x78}, {0x4d, 0x40}, {0x4e, 0x20}, {0x69, 0x00},
831 {0x74, 0x19}, {0x8d, 0x4f}, {0x8e, 0x00}, {0x8f, 0x00},
832 {0x90, 0x00}, {0x91, 0x00}, {0x96, 0x00}, {0x9a, 0x80},
833 {0xb0, 0x84}, {0xb1, 0x0c}, {0xb2, 0x0e}, {0xb3, 0x82},
834 {0xb8, 0x0a}, {0x43, 0x0a}, {0x44, 0xf0}, {0x45, 0x20},
835 {0x46, 0x7d}, {0x47, 0x29}, {0x48, 0x4a}, {0x59, 0x8c},
836 {0x5a, 0xa5}, {0x5b, 0xde}, {0x5c, 0x96}, {0x5d, 0x66},
837 {0x5e, 0x10}, {0x6c, 0x0a}, {0x6d, 0x55}, {0x6e, 0x11},
838 {0x6f, 0x9e}, {0x6a, 0x40}, {0x01, 0x40}, {0x02, 0x40},
839 {0x13, 0xe7}, {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x02},
840 {0x52, 0x1d}, {0x53, 0x56}, {0x54, 0x73}, {0x55, 0x0a},
841 {0x56, 0x55}, {0x57, 0x80}, {0x58, 0x9e}, {0x41, 0x08},
842 {0x3f, 0x02}, {0x75, 0x03}, {0x76, 0x63}, {0x4c, 0x04},
843 {0x77, 0x06}, {0x3d, 0x02}, {0x4b, 0x09}, {0xc9, 0x30},
844 {0x41, 0x08}, {0x56, 0x48}, {0x34, 0x11}, {0xa4, 0x88},
845 {0x96, 0x00}, {0x97, 0x30}, {0x98, 0x20}, {0x99, 0x30},
846 {0x9a, 0x84}, {0x9b, 0x29}, {0x9c, 0x03}, {0x9d, 0x99},
847 {0x9e, 0x7f}, {0x78, 0x04}, {0x79, 0x01}, {0xc8, 0xf0},
848 {0x79, 0x0f}, {0xc8, 0x00}, {0x79, 0x10}, {0xc8, 0x7e},
849 {0x79, 0x0a}, {0xc8, 0x80}, {0x79, 0x0b}, {0xc8, 0x01},
850 {0x79, 0x0c}, {0xc8, 0x0f}, {0x79, 0x0d}, {0xc8, 0x20},
851 {0x79, 0x09}, {0xc8, 0x80}, {0x79, 0x02}, {0xc8, 0xc0},
852 {0x79, 0x03}, {0xc8, 0x40}, {0x79, 0x05}, {0xc8, 0x30},
853 {0x79, 0x26}, {0x62, 0x20}, {0x63, 0x00}, {0x64, 0x06},
854 {0x65, 0x00}, {0x66, 0x05}, {0x94, 0x05}, {0x95, 0x0a},
855 {0x17, 0x13}, {0x18, 0x01}, {0x19, 0x02}, {0x1a, 0x7a},
856 {0x46, 0x59}, {0x47, 0x30}, {0x58, 0x9a}, {0x59, 0x84},
857 {0x5a, 0x91}, {0x5b, 0x57}, {0x5c, 0x75}, {0x5d, 0x6d},
858 {0x5e, 0x13}, {0x64, 0x07}, {0x94, 0x07}, {0x95, 0x0d},
859 {0xa6, 0xdf}, {0xa7, 0xdf}, {0x48, 0x4d}, {0x51, 0x00},
860 {0x6b, 0x0a}, {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00},
861 {0x92, 0x00}, {0x93, 0x00}, {0x55, 0x0a}, {0x56, 0x60},
862 {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d},
863 {0x53, 0x56}, {0x54, 0x73}, {0x58, 0x9a}, {0x4f, 0x6e},
864 {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, {0x53, 0x56},
865 {0x54, 0x73}, {0x58, 0x9a}, {0x3f, 0x01}, {0x7b, 0x03},
866 {0x7c, 0x09}, {0x7d, 0x16}, {0x7e, 0x38}, {0x7f, 0x47},
867 {0x80, 0x53}, {0x81, 0x5e}, {0x82, 0x6a}, {0x83, 0x74},
868 {0x84, 0x80}, {0x85, 0x8c}, {0x86, 0x9b}, {0x87, 0xb2},
869 {0x88, 0xcc}, {0x89, 0xe5}, {0x7a, 0x24}, {0x3b, 0x00},
870 {0x9f, 0x76}, {0xa0, 0x65}, {0x13, 0xe2}, {0x6b, 0x0a},
871 {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00},
872 {0x93, 0x00},
873};
874
875static u8 ov9650_init[][2] = {
876 {0x12, 0x80}, {0x00, 0x00}, {0x01, 0x78},
877 {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03},
878 {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00},
879 {0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00},
880 {0x0e, 0xa0}, {0x0f, 0x52}, {0x10, 0x7c},
881 {0x11, 0x80}, {0x12, 0x45}, {0x13, 0xc2},
882 {0x14, 0x2e}, {0x15, 0x00}, {0x16, 0x07},
883 {0x17, 0x24}, {0x18, 0xc5}, {0x19, 0x00},
884 {0x1a, 0x3c}, {0x1b, 0x00}, {0x1e, 0x04},
885 {0x1f, 0x00}, {0x24, 0x78}, {0x25, 0x68},
886 {0x26, 0xd4}, {0x27, 0x80}, {0x28, 0x80},
887 {0x29, 0x30}, {0x2a, 0x00}, {0x2b, 0x00},
888 {0x2c, 0x80}, {0x2d, 0x00}, {0x2e, 0x00},
889 {0x2f, 0x00}, {0x30, 0x08}, {0x31, 0x30},
890 {0x32, 0x84}, {0x33, 0xe2}, {0x34, 0xbf},
891 {0x35, 0x81}, {0x36, 0xf9}, {0x37, 0x00},
892 {0x38, 0x93}, {0x39, 0x50}, {0x3a, 0x01},
893 {0x3b, 0x01}, {0x3c, 0x73}, {0x3d, 0x19},
894 {0x3e, 0x0b}, {0x3f, 0x80}, {0x40, 0xc1},
895 {0x41, 0x00}, {0x42, 0x08}, {0x67, 0x80},
896 {0x68, 0x80}, {0x69, 0x40}, {0x6a, 0x00},
897 {0x6b, 0x0a}, {0x8b, 0x06}, {0x8c, 0x20},
898 {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0xdf},
899 {0x92, 0x00}, {0x93, 0x00}, {0x94, 0x88},
900 {0x95, 0x88}, {0x96, 0x04}, {0xa1, 0x00},
901 {0xa5, 0x80}, {0xa8, 0x80}, {0xa9, 0xb8},
902 {0xaa, 0x92}, {0xab, 0x0a},
903};
904
905static u8 ov9655_init[][2] = {
906 {0x12, 0x80}, {0x12, 0x01}, {0x0d, 0x00}, {0x0e, 0x61},
907 {0x11, 0x80}, {0x13, 0xba}, {0x14, 0x2e}, {0x16, 0x24},
908 {0x1e, 0x04}, {0x1e, 0x04}, {0x1e, 0x04}, {0x27, 0x08},
909 {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x32, 0xbf},
910 {0x34, 0x3d}, {0x35, 0x00}, {0x36, 0xf8}, {0x38, 0x12},
911 {0x39, 0x57}, {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c},
912 {0x3d, 0x19}, {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40},
913 {0x42, 0x80}, {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a},
914 {0x48, 0x3c}, {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc},
915 {0x4d, 0xdc}, {0x4e, 0xdc}, {0x69, 0x02}, {0x6c, 0x04},
916 {0x6f, 0x9e}, {0x70, 0x05}, {0x71, 0x78}, {0x77, 0x02},
917 {0x8a, 0x23}, {0x8c, 0x0d}, {0x90, 0x7e}, {0x91, 0x7c},
918 {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68}, {0xa6, 0x60},
919 {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92}, {0xab, 0x04},
920 {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80}, {0xaf, 0x80},
921 {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00}, {0xb6, 0xaf},
922 {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44}, {0xbe, 0x3b},
923 {0xbf, 0x3a}, {0xc0, 0xe2}, {0xc1, 0xc8}, {0xc2, 0x01},
924 {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0},
925 {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x12, 0x61},
926 {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a},
927 {0x03, 0x12}, {0x17, 0x14}, {0x18, 0x00}, {0x19, 0x01},
928 {0x1a, 0x3d}, {0x32, 0xbf}, {0x11, 0x80}, {0x2a, 0x10},
929 {0x2b, 0x0a}, {0x92, 0x00}, {0x93, 0x00}, {0x1e, 0x04},
930 {0x1e, 0x04}, {0x10, 0x7c}, {0x04, 0x03}, {0xa1, 0x00},
931 {0x2d, 0x00}, {0x2e, 0x00}, {0x00, 0x00}, {0x01, 0x80},
932 {0x02, 0x80}, {0x12, 0x61}, {0x36, 0xfa}, {0x8c, 0x8d},
933 {0xc0, 0xaa}, {0x69, 0x0a}, {0x03, 0x12}, {0x17, 0x14},
934 {0x18, 0x00}, {0x19, 0x01}, {0x1a, 0x3d}, {0x32, 0xbf},
935 {0x11, 0x80}, {0x2a, 0x10}, {0x2b, 0x0a}, {0x92, 0x00},
936 {0x93, 0x00}, {0x04, 0x01}, {0x10, 0x1f}, {0xa1, 0x00},
937 {0x00, 0x0a}, {0xa1, 0x00}, {0x10, 0x5d}, {0x04, 0x03},
938 {0x00, 0x01}, {0xa1, 0x00}, {0x10, 0x7c}, {0x04, 0x03},
939 {0x00, 0x03}, {0x00, 0x0a}, {0x00, 0x10}, {0x00, 0x13},
940};
941
942static u16 mt9v112_init[][2] = {
943 {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020},
944 {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b},
945 {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001},
946 {0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a},
947 {0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58},
948 {0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001},
949 {0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020},
950 {0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020},
951 {0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020},
952 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
953 {0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2},
954 {0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
955 {0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020},
956 {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
957 {0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae},
958 {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae},
959};
960
961static u16 mt9v111_init[][2] = {
962 {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000},
963 {0x01, 0x0001}, {0x02, 0x0016}, {0x03, 0x01e1},
964 {0x04, 0x0281}, {0x05, 0x0004}, {0x07, 0x3002},
965 {0x21, 0x0000}, {0x25, 0x4024}, {0x26, 0xff03},
966 {0x27, 0xff10}, {0x2b, 0x7828}, {0x2c, 0xb43c},
967 {0x2d, 0xf0a0}, {0x2e, 0x0c64}, {0x2f, 0x0064},
968 {0x67, 0x4010}, {0x06, 0x301e}, {0x08, 0x0480},
969 {0x01, 0x0004}, {0x02, 0x0016}, {0x03, 0x01e6},
970 {0x04, 0x0286}, {0x05, 0x0004}, {0x06, 0x0000},
971 {0x07, 0x3002}, {0x08, 0x0008}, {0x0c, 0x0000},
972 {0x0d, 0x0000}, {0x0e, 0x0000}, {0x0f, 0x0000},
973 {0x10, 0x0000}, {0x11, 0x0000}, {0x12, 0x00b0},
974 {0x13, 0x007c}, {0x14, 0x0000}, {0x15, 0x0000},
975 {0x16, 0x0000}, {0x17, 0x0000}, {0x18, 0x0000},
976 {0x19, 0x0000}, {0x1a, 0x0000}, {0x1b, 0x0000},
977 {0x1c, 0x0000}, {0x1d, 0x0000}, {0x30, 0x0000},
978 {0x30, 0x0005}, {0x31, 0x0000}, {0x02, 0x0016},
979 {0x03, 0x01e1}, {0x04, 0x0281}, {0x05, 0x0004},
980 {0x06, 0x0000}, {0x07, 0x3002}, {0x06, 0x002d},
981 {0x05, 0x0004}, {0x09, 0x0064}, {0x2b, 0x00a0},
982 {0x2c, 0x00a0}, {0x2d, 0x00a0}, {0x2e, 0x00a0},
983 {0x02, 0x0016}, {0x03, 0x01e1}, {0x04, 0x0281},
984 {0x05, 0x0004}, {0x06, 0x002d}, {0x07, 0x3002},
985 {0x0e, 0x0008}, {0x06, 0x002d}, {0x05, 0x0004},
986};
987
988static u16 mt9v011_init[][2] = {
989 {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000},
990 {0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1},
991 {0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006},
992 {0x0d, 0x0002}, {0x0a, 0x0000}, {0x0b, 0x0000},
993 {0x0c, 0x0000}, {0x0d, 0x0000}, {0x0e, 0x0000},
994 {0x0f, 0x0000}, {0x10, 0x0000}, {0x11, 0x0000},
995 {0x12, 0x0000}, {0x13, 0x0000}, {0x14, 0x0000},
996 {0x15, 0x0000}, {0x16, 0x0000}, {0x17, 0x0000},
997 {0x18, 0x0000}, {0x19, 0x0000}, {0x1a, 0x0000},
998 {0x1b, 0x0000}, {0x1c, 0x0000}, {0x1d, 0x0000},
999 {0x32, 0x0000}, {0x20, 0x1101}, {0x21, 0x0000},
1000 {0x22, 0x0000}, {0x23, 0x0000}, {0x24, 0x0000},
1001 {0x25, 0x0000}, {0x26, 0x0000}, {0x27, 0x0024},
1002 {0x2f, 0xf7b0}, {0x30, 0x0005}, {0x31, 0x0000},
1003 {0x32, 0x0000}, {0x33, 0x0000}, {0x34, 0x0100},
1004 {0x3d, 0x068f}, {0x40, 0x01e0}, {0x41, 0x00d1},
1005 {0x44, 0x0082}, {0x5a, 0x0000}, {0x5b, 0x0000},
1006 {0x5c, 0x0000}, {0x5d, 0x0000}, {0x5e, 0x0000},
1007 {0x5f, 0xa31d}, {0x62, 0x0611}, {0x0a, 0x0000},
1008 {0x06, 0x0029}, {0x05, 0x0009}, {0x20, 0x1101},
1009 {0x20, 0x1101}, {0x09, 0x0064}, {0x07, 0x0003},
1010 {0x2b, 0x0033}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
1011 {0x2e, 0x0033}, {0x07, 0x0002}, {0x06, 0x0000},
1012 {0x06, 0x0029}, {0x05, 0x0009},
1013};
1014
1015static u16 mt9m001_init[][2] = {
1016 {0x0d, 0x0001}, {0x0d, 0x0000}, {0x01, 0x000e},
1017 {0x02, 0x0014}, {0x03, 0x03c1}, {0x04, 0x0501},
1018 {0x05, 0x0083}, {0x06, 0x0006}, {0x0d, 0x0002},
1019 {0x0a, 0x0000}, {0x0c, 0x0000}, {0x11, 0x0000},
1020 {0x1e, 0x8000}, {0x5f, 0x8904}, {0x60, 0x0000},
1021 {0x61, 0x0000}, {0x62, 0x0498}, {0x63, 0x0000},
1022 {0x64, 0x0000}, {0x20, 0x111d}, {0x06, 0x00f2},
1023 {0x05, 0x0013}, {0x09, 0x10f2}, {0x07, 0x0003},
1024 {0x2b, 0x002a}, {0x2d, 0x002a}, {0x2c, 0x002a},
1025 {0x2e, 0x0029}, {0x07, 0x0002},
1026};
1027
1028static u16 mt9m111_init[][2] = {
1029 {0xf0, 0x0000}, {0x0d, 0x0008}, {0x0d, 0x0009},
1030 {0x0d, 0x0008}, {0xf0, 0x0001}, {0x3a, 0x4300},
1031 {0x9b, 0x4300}, {0xa1, 0x0280}, {0xa4, 0x0200},
1032 {0x06, 0x308e}, {0xf0, 0x0000},
1033};
1034
1035static u8 hv7131r_init[][2] = {
1036 {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08},
1037 {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0},
1038 {0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08},
1039 {0x01, 0x08}, {0x01, 0x08}, {0x25, 0x07},
1040 {0x26, 0xc3}, {0x27, 0x50}, {0x30, 0x62},
1041 {0x31, 0x10}, {0x32, 0x06}, {0x33, 0x10},
1042 {0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00},
1043 {0x23, 0x09}, {0x01, 0x08},
1044};
1045
1046int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
1047{
1048 struct usb_device *dev = gspca_dev->dev;
1049 int result;
1050 result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
1051 0x00,
1052 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1053 reg,
1054 0x00,
1055 gspca_dev->usb_buf,
1056 length,
1057 500);
1058 if (unlikely(result < 0 || result != length)) {
1059 err("Read register failed 0x%02X", reg);
1060 return -EIO;
1061 }
1062 return 0;
1063}
1064
1065int reg_w(struct gspca_dev *gspca_dev, u16 reg, const u8 *buffer, int length)
1066{
1067 struct usb_device *dev = gspca_dev->dev;
1068 int result;
1069 memcpy(gspca_dev->usb_buf, buffer, length);
1070 result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
1071 0x08,
1072 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
1073 reg,
1074 0x00,
1075 gspca_dev->usb_buf,
1076 length,
1077 500);
1078 if (unlikely(result < 0 || result != length)) {
1079 err("Write register failed index 0x%02X", reg);
1080 return -EIO;
1081 }
1082 return 0;
1083}
1084
1085int reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value)
1086{
1087 u8 data[1] = {value};
1088 return reg_w(gspca_dev, reg, data, 1);
1089}
1090
1091int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
1092{
1093 int i;
1094 reg_w(gspca_dev, 0x10c0, buffer, 8);
1095 for (i = 0; i < 5; i++) {
1096 reg_r(gspca_dev, 0x10c0, 1);
1097 if (gspca_dev->usb_buf[0] & 0x04) {
1098 if (gspca_dev->usb_buf[0] & 0x08)
1099 return -1;
1100 return 0;
1101 }
1102 msleep(1);
1103 }
1104 return -1;
1105}
1106
1107int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
1108{
1109 struct sd *sd = (struct sd *) gspca_dev;
1110
1111 u8 row[8];
1112
1113 /*
1114 * from the point of view of the bridge, the length
1115 * includes the address
1116 */
1117 row[0] = 0x81 | (2 << 4);
1118 row[1] = sd->i2c_addr;
1119 row[2] = reg;
1120 row[3] = val;
1121 row[4] = 0x00;
1122 row[5] = 0x00;
1123 row[6] = 0x00;
1124 row[7] = 0x10;
1125
1126 return i2c_w(gspca_dev, row);
1127}
1128
1129int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
1130{
1131 struct sd *sd = (struct sd *) gspca_dev;
1132 u8 row[8];
1133
1134 /*
1135 * from the point of view of the bridge, the length
1136 * includes the address
1137 */
1138 row[0] = 0x81 | (3 << 4);
1139 row[1] = sd->i2c_addr;
1140 row[2] = reg;
1141 row[3] = (val >> 8) & 0xff;
1142 row[4] = val & 0xff;
1143 row[5] = 0x00;
1144 row[6] = 0x00;
1145 row[7] = 0x10;
1146
1147 return i2c_w(gspca_dev, row);
1148}
1149
1150int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
1151{
1152 struct sd *sd = (struct sd *) gspca_dev;
1153 u8 row[8];
1154
1155 row[0] = 0x81 | 0x10;
1156 row[1] = sd->i2c_addr;
1157 row[2] = reg;
1158 row[3] = 0;
1159 row[4] = 0;
1160 row[5] = 0;
1161 row[6] = 0;
1162 row[7] = 0x10;
1163 reg_w(gspca_dev, 0x10c0, row, 8);
1164 msleep(1);
1165 row[0] = 0x81 | (2 << 4) | 0x02;
1166 row[2] = 0;
1167 reg_w(gspca_dev, 0x10c0, row, 8);
1168 msleep(1);
1169 reg_r(gspca_dev, 0x10c2, 5);
1170 *val = gspca_dev->usb_buf[3];
1171 return 0;
1172}
1173
1174int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
1175{
1176 struct sd *sd = (struct sd *) gspca_dev;
1177 u8 row[8];
1178
1179 row[0] = 0x81 | 0x10;
1180 row[1] = sd->i2c_addr;
1181 row[2] = reg;
1182 row[3] = 0;
1183 row[4] = 0;
1184 row[5] = 0;
1185 row[6] = 0;
1186 row[7] = 0x10;
1187 reg_w(gspca_dev, 0x10c0, row, 8);
1188 msleep(1);
1189 row[0] = 0x81 | (3 << 4) | 0x02;
1190 row[2] = 0;
1191 reg_w(gspca_dev, 0x10c0, row, 8);
1192 msleep(1);
1193 reg_r(gspca_dev, 0x10c2, 5);
1194 *val = (gspca_dev->usb_buf[2] << 8) | gspca_dev->usb_buf[3];
1195 return 0;
1196}
1197
1198static int ov9650_init_sensor(struct gspca_dev *gspca_dev)
1199{
1200 int i;
1201 struct sd *sd = (struct sd *) gspca_dev;
1202
1203 for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) {
1204 if (i2c_w1(gspca_dev, ov9650_init[i][0],
1205 ov9650_init[i][1]) < 0) {
1206 err("OV9650 sensor initialization failed");
1207 return -ENODEV;
1208 }
1209 }
1210 sd->hstart = 1;
1211 sd->vstart = 7;
1212 return 0;
1213}
1214
1215static int ov9655_init_sensor(struct gspca_dev *gspca_dev)
1216{
1217 int i;
1218 struct sd *sd = (struct sd *) gspca_dev;
1219
1220 for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) {
1221 if (i2c_w1(gspca_dev, ov9655_init[i][0],
1222 ov9655_init[i][1]) < 0) {
1223 err("OV9655 sensor initialization failed");
1224 return -ENODEV;
1225 }
1226 }
1227 /* disable hflip and vflip */
1228 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
1229 sd->hstart = 0;
1230 sd->vstart = 7;
1231 return 0;
1232}
1233
1234static int soi968_init_sensor(struct gspca_dev *gspca_dev)
1235{
1236 int i;
1237 struct sd *sd = (struct sd *) gspca_dev;
1238
1239 for (i = 0; i < ARRAY_SIZE(soi968_init); i++) {
1240 if (i2c_w1(gspca_dev, soi968_init[i][0],
1241 soi968_init[i][1]) < 0) {
1242 err("SOI968 sensor initialization failed");
1243 return -ENODEV;
1244 }
1245 }
1246 /* disable hflip and vflip */
1247 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
1248 sd->hstart = 60;
1249 sd->vstart = 11;
1250 return 0;
1251}
1252
1253static int ov7660_init_sensor(struct gspca_dev *gspca_dev)
1254{
1255 int i;
1256 struct sd *sd = (struct sd *) gspca_dev;
1257
1258 for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) {
1259 if (i2c_w1(gspca_dev, ov7660_init[i][0],
1260 ov7660_init[i][1]) < 0) {
1261 err("OV7660 sensor initialization failed");
1262 return -ENODEV;
1263 }
1264 }
1265 /* disable hflip and vflip */
1266 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
1267 sd->hstart = 1;
1268 sd->vstart = 1;
1269 return 0;
1270}
1271
1272static int ov7670_init_sensor(struct gspca_dev *gspca_dev)
1273{
1274 int i;
1275 struct sd *sd = (struct sd *) gspca_dev;
1276
1277 for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) {
1278 if (i2c_w1(gspca_dev, ov7670_init[i][0],
1279 ov7670_init[i][1]) < 0) {
1280 err("OV7670 sensor initialization failed");
1281 return -ENODEV;
1282 }
1283 }
1284 /* disable hflip and vflip */
1285 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
1286 sd->hstart = 0;
1287 sd->vstart = 1;
1288 return 0;
1289}
1290
1291static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
1292{
1293 struct sd *sd = (struct sd *) gspca_dev;
1294 int i;
1295 u16 value;
1296 int ret;
1297
1298 sd->i2c_addr = 0x5d;
1299 ret = i2c_r2(gspca_dev, 0xff, &value);
1300 if ((ret == 0) && (value == 0x8243)) {
1301 for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) {
1302 if (i2c_w2(gspca_dev, mt9v011_init[i][0],
1303 mt9v011_init[i][1]) < 0) {
1304 err("MT9V011 sensor initialization failed");
1305 return -ENODEV;
1306 }
1307 }
1308 sd->hstart = 2;
1309 sd->vstart = 2;
1310 sd->sensor = SENSOR_MT9V011;
1311 info("MT9V011 sensor detected");
1312 return 0;
1313 }
1314
1315 sd->i2c_addr = 0x5c;
1316 i2c_w2(gspca_dev, 0x01, 0x0004);
1317 ret = i2c_r2(gspca_dev, 0xff, &value);
1318 if ((ret == 0) && (value == 0x823a)) {
1319 for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) {
1320 if (i2c_w2(gspca_dev, mt9v111_init[i][0],
1321 mt9v111_init[i][1]) < 0) {
1322 err("MT9V111 sensor initialization failed");
1323 return -ENODEV;
1324 }
1325 }
1326 sd->hstart = 2;
1327 sd->vstart = 2;
1328 sd->sensor = SENSOR_MT9V111;
1329 info("MT9V111 sensor detected");
1330 return 0;
1331 }
1332
1333 sd->i2c_addr = 0x5d;
1334 ret = i2c_w2(gspca_dev, 0xf0, 0x0000);
1335 if (ret < 0) {
1336 sd->i2c_addr = 0x48;
1337 i2c_w2(gspca_dev, 0xf0, 0x0000);
1338 }
1339 ret = i2c_r2(gspca_dev, 0x00, &value);
1340 if ((ret == 0) && (value == 0x1229)) {
1341 for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) {
1342 if (i2c_w2(gspca_dev, mt9v112_init[i][0],
1343 mt9v112_init[i][1]) < 0) {
1344 err("MT9V112 sensor initialization failed");
1345 return -ENODEV;
1346 }
1347 }
1348 sd->hstart = 6;
1349 sd->vstart = 2;
1350 sd->sensor = SENSOR_MT9V112;
1351 info("MT9V112 sensor detected");
1352 return 0;
1353 }
1354
1355 return -ENODEV;
1356}
1357
1358static int mt9m111_init_sensor(struct gspca_dev *gspca_dev)
1359{
1360 struct sd *sd = (struct sd *) gspca_dev;
1361 int i;
1362 for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) {
1363 if (i2c_w2(gspca_dev, mt9m111_init[i][0],
1364 mt9m111_init[i][1]) < 0) {
1365 err("MT9M111 sensor initialization failed");
1366 return -ENODEV;
1367 }
1368 }
1369 sd->hstart = 0;
1370 sd->vstart = 2;
1371 return 0;
1372}
1373
1374static int mt9m001_init_sensor(struct gspca_dev *gspca_dev)
1375{
1376 struct sd *sd = (struct sd *) gspca_dev;
1377 int i;
1378 for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) {
1379 if (i2c_w2(gspca_dev, mt9m001_init[i][0],
1380 mt9m001_init[i][1]) < 0) {
1381 err("MT9M001 sensor initialization failed");
1382 return -ENODEV;
1383 }
1384 }
1385 /* disable hflip and vflip */
1386 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
1387 sd->hstart = 2;
1388 sd->vstart = 2;
1389 return 0;
1390}
1391
1392static int hv7131r_init_sensor(struct gspca_dev *gspca_dev)
1393{
1394 int i;
1395 struct sd *sd = (struct sd *) gspca_dev;
1396
1397 for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) {
1398 if (i2c_w1(gspca_dev, hv7131r_init[i][0],
1399 hv7131r_init[i][1]) < 0) {
1400 err("HV7131R Sensor initialization failed");
1401 return -ENODEV;
1402 }
1403 }
1404 sd->hstart = 0;
1405 sd->vstart = 1;
1406 return 0;
1407}
1408
1409#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV
1410static int input_kthread(void *data)
1411{
1412 struct gspca_dev *gspca_dev = (struct gspca_dev *)data;
1413 struct sd *sd = (struct sd *) gspca_dev;
1414
1415 DECLARE_WAIT_QUEUE_HEAD(wait);
1416 set_freezable();
1417 for (;;) {
1418 if (kthread_should_stop())
1419 break;
1420
1421 if (reg_r(gspca_dev, 0x1005, 1) < 0)
1422 continue;
1423
1424 input_report_key(sd->input_dev,
1425 KEY_CAMERA,
1426 gspca_dev->usb_buf[0] & sd->input_gpio);
1427 input_sync(sd->input_dev);
1428
1429 wait_event_freezable_timeout(wait,
1430 kthread_should_stop(),
1431 msecs_to_jiffies(100));
1432 }
1433 return 0;
1434}
1435
1436
1437static int sn9c20x_input_init(struct gspca_dev *gspca_dev)
1438{
1439 struct sd *sd = (struct sd *) gspca_dev;
1440 if (sd->input_gpio == 0)
1441 return 0;
1442
1443 sd->input_dev = input_allocate_device();
1444 if (!sd->input_dev)
1445 return -ENOMEM;
1446
1447 sd->input_dev->name = "SN9C20X Webcam";
1448
1449 sd->input_dev->phys = kasprintf(GFP_KERNEL, "usb-%s-%s",
1450 gspca_dev->dev->bus->bus_name,
1451 gspca_dev->dev->devpath);
1452
1453 if (!sd->input_dev->phys)
1454 return -ENOMEM;
1455
1456 usb_to_input_id(gspca_dev->dev, &sd->input_dev->id);
1457 sd->input_dev->dev.parent = &gspca_dev->dev->dev;
1458
1459 set_bit(EV_KEY, sd->input_dev->evbit);
1460 set_bit(KEY_CAMERA, sd->input_dev->keybit);
1461
1462 if (input_register_device(sd->input_dev))
1463 return -EINVAL;
1464
1465 sd->input_task = kthread_run(input_kthread, gspca_dev, "sn9c20x/%d",
1466 gspca_dev->vdev.minor);
1467
1468 if (IS_ERR(sd->input_task))
1469 return -EINVAL;
1470
1471 return 0;
1472}
1473
1474static void sn9c20x_input_cleanup(struct gspca_dev *gspca_dev)
1475{
1476 struct sd *sd = (struct sd *) gspca_dev;
1477 if (sd->input_task != NULL && !IS_ERR(sd->input_task))
1478 kthread_stop(sd->input_task);
1479
1480 if (sd->input_dev != NULL) {
1481 input_unregister_device(sd->input_dev);
1482 kfree(sd->input_dev->phys);
1483 input_free_device(sd->input_dev);
1484 sd->input_dev = NULL;
1485 }
1486}
1487#endif
1488
1489static int set_cmatrix(struct gspca_dev *gspca_dev)
1490{
1491 struct sd *sd = (struct sd *) gspca_dev;
1492 s32 hue_coord, hue_index = 180 + sd->hue;
1493 u8 cmatrix[21];
1494 memset(cmatrix, 0, 21);
1495
1496 cmatrix[2] = (sd->contrast * 0x25 / 0x100) + 0x26;
1497 cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
1498 cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
1499 cmatrix[18] = sd->brightness - 0x80;
1500
1501 hue_coord = (hsv_red_x[hue_index] * sd->saturation) >> 8;
1502 cmatrix[6] = (unsigned char)(hue_coord & 0xff);
1503 cmatrix[7] = (unsigned char)((hue_coord >> 8) & 0x0f);
1504
1505 hue_coord = (hsv_red_y[hue_index] * sd->saturation) >> 8;
1506 cmatrix[8] = (unsigned char)(hue_coord & 0xff);
1507 cmatrix[9] = (unsigned char)((hue_coord >> 8) & 0x0f);
1508
1509 hue_coord = (hsv_green_x[hue_index] * sd->saturation) >> 8;
1510 cmatrix[10] = (unsigned char)(hue_coord & 0xff);
1511 cmatrix[11] = (unsigned char)((hue_coord >> 8) & 0x0f);
1512
1513 hue_coord = (hsv_green_y[hue_index] * sd->saturation) >> 8;
1514 cmatrix[12] = (unsigned char)(hue_coord & 0xff);
1515 cmatrix[13] = (unsigned char)((hue_coord >> 8) & 0x0f);
1516
1517 hue_coord = (hsv_blue_x[hue_index] * sd->saturation) >> 8;
1518 cmatrix[14] = (unsigned char)(hue_coord & 0xff);
1519 cmatrix[15] = (unsigned char)((hue_coord >> 8) & 0x0f);
1520
1521 hue_coord = (hsv_blue_y[hue_index] * sd->saturation) >> 8;
1522 cmatrix[16] = (unsigned char)(hue_coord & 0xff);
1523 cmatrix[17] = (unsigned char)((hue_coord >> 8) & 0x0f);
1524
1525 return reg_w(gspca_dev, 0x10e1, cmatrix, 21);
1526}
1527
1528static int set_gamma(struct gspca_dev *gspca_dev)
1529{
1530 struct sd *sd = (struct sd *) gspca_dev;
1531 u8 gamma[17];
1532 u8 gval = sd->gamma * 0xb8 / 0x100;
1533
1534
1535 gamma[0] = 0x0a;
1536 gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8);
1537 gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8);
1538 gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8);
1539 gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8);
1540 gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8);
1541 gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8);
1542 gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8);
1543 gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8);
1544 gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8);
1545 gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8);
1546 gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8);
1547 gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8);
1548 gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8);
1549 gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8);
1550 gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8);
1551 gamma[16] = 0xf5;
1552
1553 return reg_w(gspca_dev, 0x1190, gamma, 17);
1554}
1555
1556static int set_redblue(struct gspca_dev *gspca_dev)
1557{
1558 struct sd *sd = (struct sd *) gspca_dev;
1559 reg_w1(gspca_dev, 0x118c, sd->red);
1560 reg_w1(gspca_dev, 0x118f, sd->blue);
1561 return 0;
1562}
1563
1564static int set_hvflip(struct gspca_dev *gspca_dev)
1565{
1566 u8 value, tslb;
1567 u16 value2;
1568 struct sd *sd = (struct sd *) gspca_dev;
1569 switch (sd->sensor) {
1570 case SENSOR_OV9650:
1571 i2c_r1(gspca_dev, 0x1e, &value);
1572 value &= ~0x30;
1573 tslb = 0x01;
1574 if (sd->hflip)
1575 value |= 0x20;
1576 if (sd->vflip) {
1577 value |= 0x10;
1578 tslb = 0x49;
1579 }
1580 i2c_w1(gspca_dev, 0x1e, value);
1581 i2c_w1(gspca_dev, 0x3a, tslb);
1582 break;
1583 case SENSOR_MT9V111:
1584 case SENSOR_MT9V011:
1585 i2c_r2(gspca_dev, 0x20, &value2);
1586 value2 &= ~0xc0a0;
1587 if (sd->hflip)
1588 value2 |= 0x8080;
1589 if (sd->vflip)
1590 value2 |= 0x4020;
1591 i2c_w2(gspca_dev, 0x20, value2);
1592 break;
1593 case SENSOR_MT9M111:
1594 case SENSOR_MT9V112:
1595 i2c_r2(gspca_dev, 0x20, &value2);
1596 value2 &= ~0x0003;
1597 if (sd->hflip)
1598 value2 |= 0x0002;
1599 if (sd->vflip)
1600 value2 |= 0x0001;
1601 i2c_w2(gspca_dev, 0x20, value2);
1602 break;
1603 case SENSOR_HV7131R:
1604 i2c_r1(gspca_dev, 0x01, &value);
1605 value &= ~0x03;
1606 if (sd->vflip)
1607 value |= 0x01;
1608 if (sd->hflip)
1609 value |= 0x02;
1610 i2c_w1(gspca_dev, 0x01, value);
1611 break;
1612 }
1613 return 0;
1614}
1615
1616static int set_exposure(struct gspca_dev *gspca_dev)
1617{
1618 struct sd *sd = (struct sd *) gspca_dev;
1619 u8 exp[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e};
1620 switch (sd->sensor) {
1621 case SENSOR_OV7660:
1622 case SENSOR_OV7670:
1623 case SENSOR_SOI968:
1624 case SENSOR_OV9655:
1625 case SENSOR_OV9650:
1626 exp[0] |= (3 << 4);
1627 exp[2] = 0x2d;
1628 exp[3] = sd->exposure & 0xff;
1629 exp[4] = sd->exposure >> 8;
1630 break;
1631 case SENSOR_MT9M001:
1632 case SENSOR_MT9M111:
1633 case SENSOR_MT9V112:
1634 case SENSOR_MT9V111:
1635 case SENSOR_MT9V011:
1636 exp[0] |= (3 << 4);
1637 exp[2] = 0x09;
1638 exp[3] = sd->exposure >> 8;
1639 exp[4] = sd->exposure & 0xff;
1640 break;
1641 case SENSOR_HV7131R:
1642 exp[0] |= (4 << 4);
1643 exp[2] = 0x25;
1644 exp[3] = ((sd->exposure * 0xffffff) / 0xffff) >> 16;
1645 exp[4] = ((sd->exposure * 0xffffff) / 0xffff) >> 8;
1646 exp[5] = ((sd->exposure * 0xffffff) / 0xffff) & 0xff;
1647 break;
1648 }
1649 i2c_w(gspca_dev, exp);
1650 return 0;
1651}
1652
1653static int set_gain(struct gspca_dev *gspca_dev)
1654{
1655 struct sd *sd = (struct sd *) gspca_dev;
1656 u8 gain[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d};
1657 switch (sd->sensor) {
1658 case SENSOR_OV7660:
1659 case SENSOR_OV7670:
1660 case SENSOR_SOI968:
1661 case SENSOR_OV9655:
1662 case SENSOR_OV9650:
1663 gain[0] |= (2 << 4);
1664 gain[3] = ov_gain[sd->gain];
1665 break;
1666 case SENSOR_MT9V011:
1667 case SENSOR_MT9V111:
1668 gain[0] |= (3 << 4);
1669 gain[2] = 0x35;
1670 gain[3] = micron1_gain[sd->gain] >> 8;
1671 gain[4] = micron1_gain[sd->gain] & 0xff;
1672 break;
1673 case SENSOR_MT9V112:
1674 case SENSOR_MT9M111:
1675 gain[0] |= (3 << 4);
1676 gain[2] = 0x2f;
1677 gain[3] = micron1_gain[sd->gain] >> 8;
1678 gain[4] = micron1_gain[sd->gain] & 0xff;
1679 break;
1680 case SENSOR_MT9M001:
1681 gain[0] |= (3 << 4);
1682 gain[2] = 0x2f;
1683 gain[3] = micron2_gain[sd->gain] >> 8;
1684 gain[4] = micron2_gain[sd->gain] & 0xff;
1685 break;
1686 case SENSOR_HV7131R:
1687 gain[0] |= (2 << 4);
1688 gain[2] = 0x30;
1689 gain[3] = hv7131r_gain[sd->gain];
1690 break;
1691 }
1692 i2c_w(gspca_dev, gain);
1693 return 0;
1694}
1695
1696static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val)
1697{
1698 struct sd *sd = (struct sd *) gspca_dev;
1699
1700 sd->brightness = val;
1701 if (gspca_dev->streaming)
1702 return set_cmatrix(gspca_dev);
1703 return 0;
1704}
1705
1706static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val)
1707{
1708 struct sd *sd = (struct sd *) gspca_dev;
1709 *val = sd->brightness;
1710 return 0;
1711}
1712
1713
1714static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val)
1715{
1716 struct sd *sd = (struct sd *) gspca_dev;
1717
1718 sd->contrast = val;
1719 if (gspca_dev->streaming)
1720 return set_cmatrix(gspca_dev);
1721 return 0;
1722}
1723
1724static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val)
1725{
1726 struct sd *sd = (struct sd *) gspca_dev;
1727 *val = sd->contrast;
1728 return 0;
1729}
1730
1731static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val)
1732{
1733 struct sd *sd = (struct sd *) gspca_dev;
1734
1735 sd->saturation = val;
1736 if (gspca_dev->streaming)
1737 return set_cmatrix(gspca_dev);
1738 return 0;
1739}
1740
1741static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val)
1742{
1743 struct sd *sd = (struct sd *) gspca_dev;
1744 *val = sd->saturation;
1745 return 0;
1746}
1747
1748static int sd_sethue(struct gspca_dev *gspca_dev, s32 val)
1749{
1750 struct sd *sd = (struct sd *) gspca_dev;
1751
1752 sd->hue = val;
1753 if (gspca_dev->streaming)
1754 return set_cmatrix(gspca_dev);
1755 return 0;
1756}
1757
1758static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val)
1759{
1760 struct sd *sd = (struct sd *) gspca_dev;
1761 *val = sd->hue;
1762 return 0;
1763}
1764
1765static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val)
1766{
1767 struct sd *sd = (struct sd *) gspca_dev;
1768
1769 sd->gamma = val;
1770 if (gspca_dev->streaming)
1771 return set_gamma(gspca_dev);
1772 return 0;
1773}
1774
1775static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val)
1776{
1777 struct sd *sd = (struct sd *) gspca_dev;
1778 *val = sd->gamma;
1779 return 0;
1780}
1781
1782static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val)
1783{
1784 struct sd *sd = (struct sd *) gspca_dev;
1785
1786 sd->red = val;
1787 if (gspca_dev->streaming)
1788 return set_redblue(gspca_dev);
1789 return 0;
1790}
1791
1792static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val)
1793{
1794 struct sd *sd = (struct sd *) gspca_dev;
1795 *val = sd->red;
1796 return 0;
1797}
1798
1799static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val)
1800{
1801 struct sd *sd = (struct sd *) gspca_dev;
1802
1803 sd->blue = val;
1804 if (gspca_dev->streaming)
1805 return set_redblue(gspca_dev);
1806 return 0;
1807}
1808
1809static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val)
1810{
1811 struct sd *sd = (struct sd *) gspca_dev;
1812 *val = sd->blue;
1813 return 0;
1814}
1815
1816static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val)
1817{
1818 struct sd *sd = (struct sd *) gspca_dev;
1819
1820 sd->hflip = val;
1821 if (gspca_dev->streaming)
1822 return set_hvflip(gspca_dev);
1823 return 0;
1824}
1825
1826static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val)
1827{
1828 struct sd *sd = (struct sd *) gspca_dev;
1829 *val = sd->hflip;
1830 return 0;
1831}
1832
1833static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val)
1834{
1835 struct sd *sd = (struct sd *) gspca_dev;
1836
1837 sd->vflip = val;
1838 if (gspca_dev->streaming)
1839 return set_hvflip(gspca_dev);
1840 return 0;
1841}
1842
1843static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val)
1844{
1845 struct sd *sd = (struct sd *) gspca_dev;
1846 *val = sd->vflip;
1847 return 0;
1848}
1849
1850static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val)
1851{
1852 struct sd *sd = (struct sd *) gspca_dev;
1853
1854 sd->exposure = val;
1855 if (gspca_dev->streaming)
1856 return set_exposure(gspca_dev);
1857 return 0;
1858}
1859
1860static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val)
1861{
1862 struct sd *sd = (struct sd *) gspca_dev;
1863 *val = sd->exposure;
1864 return 0;
1865}
1866
1867static int sd_setgain(struct gspca_dev *gspca_dev, s32 val)
1868{
1869 struct sd *sd = (struct sd *) gspca_dev;
1870
1871 sd->gain = val;
1872 if (gspca_dev->streaming)
1873 return set_gain(gspca_dev);
1874 return 0;
1875}
1876
1877static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val)
1878{
1879 struct sd *sd = (struct sd *) gspca_dev;
1880 *val = sd->gain;
1881 return 0;
1882}
1883
1884static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val)
1885{
1886 struct sd *sd = (struct sd *) gspca_dev;
1887 sd->auto_exposure = val;
1888 return 0;
1889}
1890
1891static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val)
1892{
1893 struct sd *sd = (struct sd *) gspca_dev;
1894 *val = sd->auto_exposure;
1895 return 0;
1896}
1897
1898#ifdef CONFIG_VIDEO_ADV_DEBUG
1899static int sd_dbg_g_register(struct gspca_dev *gspca_dev,
1900 struct v4l2_dbg_register *reg)
1901{
1902 struct sd *sd = (struct sd *) gspca_dev;
1903 switch (reg->match.type) {
1904 case V4L2_CHIP_MATCH_HOST:
1905 if (reg->match.addr != 0)
1906 return -EINVAL;
1907 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1908 return -EINVAL;
1909 if (reg_r(gspca_dev, reg->reg, 1) < 0)
1910 return -EINVAL;
1911 reg->val = gspca_dev->usb_buf[0];
1912 return 0;
1913 case V4L2_CHIP_MATCH_I2C_ADDR:
1914 if (reg->match.addr != sd->i2c_addr)
1915 return -EINVAL;
1916 if (sd->sensor >= SENSOR_MT9V011 &&
1917 sd->sensor <= SENSOR_MT9M111) {
1918 if (i2c_r2(gspca_dev, reg->reg, (u16 *)&reg->val) < 0)
1919 return -EINVAL;
1920 } else {
1921 if (i2c_r1(gspca_dev, reg->reg, (u8 *)&reg->val) < 0)
1922 return -EINVAL;
1923 }
1924 return 0;
1925 }
1926 return -EINVAL;
1927}
1928
1929static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1930 struct v4l2_dbg_register *reg)
1931{
1932 struct sd *sd = (struct sd *) gspca_dev;
1933 switch (reg->match.type) {
1934 case V4L2_CHIP_MATCH_HOST:
1935 if (reg->match.addr != 0)
1936 return -EINVAL;
1937 if (reg->reg < 0x1000 || reg->reg > 0x11ff)
1938 return -EINVAL;
1939 if (reg_w1(gspca_dev, reg->reg, reg->val) < 0)
1940 return -EINVAL;
1941 return 0;
1942 case V4L2_CHIP_MATCH_I2C_ADDR:
1943 if (reg->match.addr != sd->i2c_addr)
1944 return -EINVAL;
1945 if (sd->sensor >= SENSOR_MT9V011 &&
1946 sd->sensor <= SENSOR_MT9M111) {
1947 if (i2c_w2(gspca_dev, reg->reg, reg->val) < 0)
1948 return -EINVAL;
1949 } else {
1950 if (i2c_w1(gspca_dev, reg->reg, reg->val) < 0)
1951 return -EINVAL;
1952 }
1953 return 0;
1954 }
1955 return -EINVAL;
1956}
1957#endif
1958
1959static int sd_chip_ident(struct gspca_dev *gspca_dev,
1960 struct v4l2_dbg_chip_ident *chip)
1961{
1962 struct sd *sd = (struct sd *) gspca_dev;
1963
1964 switch (chip->match.type) {
1965 case V4L2_CHIP_MATCH_HOST:
1966 if (chip->match.addr != 0)
1967 return -EINVAL;
1968 chip->revision = 0;
1969 chip->ident = V4L2_IDENT_SN9C20X;
1970 return 0;
1971 case V4L2_CHIP_MATCH_I2C_ADDR:
1972 if (chip->match.addr != sd->i2c_addr)
1973 return -EINVAL;
1974 chip->revision = 0;
1975 chip->ident = i2c_ident[sd->sensor];
1976 return 0;
1977 }
1978 return -EINVAL;
1979}
1980
1981static int sd_config(struct gspca_dev *gspca_dev,
1982 const struct usb_device_id *id)
1983{
1984 struct sd *sd = (struct sd *) gspca_dev;
1985 struct cam *cam;
1986
1987 cam = &gspca_dev->cam;
1988
1989 sd->sensor = (id->driver_info >> 8) & 0xff;
1990 sd->i2c_addr = id->driver_info & 0xff;
1991
1992 switch (sd->sensor) {
1993 case SENSOR_OV9650:
1994 cam->cam_mode = sxga_mode;
1995 cam->nmodes = ARRAY_SIZE(sxga_mode);
1996 break;
1997 default:
1998 cam->cam_mode = vga_mode;
1999 cam->nmodes = ARRAY_SIZE(vga_mode);
2000 }
2001
2002 sd->old_step = 0;
2003 sd->older_step = 0;
2004 sd->exposure_step = 16;
2005
2006 sd->brightness = BRIGHTNESS_DEFAULT;
2007 sd->contrast = CONTRAST_DEFAULT;
2008 sd->saturation = SATURATION_DEFAULT;
2009 sd->hue = HUE_DEFAULT;
2010 sd->gamma = GAMMA_DEFAULT;
2011 sd->red = RED_DEFAULT;
2012 sd->blue = BLUE_DEFAULT;
2013
2014 sd->hflip = HFLIP_DEFAULT;
2015 sd->vflip = VFLIP_DEFAULT;
2016 sd->exposure = EXPOSURE_DEFAULT;
2017 sd->gain = GAIN_DEFAULT;
2018 sd->auto_exposure = AUTO_EXPOSURE_DEFAULT;
2019
2020 sd->quality = 95;
2021
2022#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV
2023 sd->input_gpio = (id->driver_info >> 16) & 0xff;
2024 if (sn9c20x_input_init(gspca_dev) < 0)
2025 return -ENODEV;
2026#endif
2027 return 0;
2028}
2029
2030static int sd_init(struct gspca_dev *gspca_dev)
2031{
2032 struct sd *sd = (struct sd *) gspca_dev;
2033 int i;
2034 u8 value;
2035 u8 i2c_init[9] =
2036 {0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
2037
2038 for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
2039 value = bridge_init[i][1];
2040 if (reg_w(gspca_dev, bridge_init[i][0], &value, 1) < 0) {
2041 err("Device initialization failed");
2042 return -ENODEV;
2043 }
2044 }
2045
2046 if (reg_w(gspca_dev, 0x10c0, i2c_init, 9) < 0) {
2047 err("Device initialization failed");
2048 return -ENODEV;
2049 }
2050
2051 switch (sd->sensor) {
2052 case SENSOR_OV9650:
2053 if (ov9650_init_sensor(gspca_dev) < 0)
2054 return -ENODEV;
2055 info("OV9650 sensor detected");
2056 break;
2057 case SENSOR_OV9655:
2058 if (ov9655_init_sensor(gspca_dev) < 0)
2059 return -ENODEV;
2060 info("OV9655 sensor detected");
2061 break;
2062 case SENSOR_SOI968:
2063 if (soi968_init_sensor(gspca_dev) < 0)
2064 return -ENODEV;
2065 info("SOI968 sensor detected");
2066 break;
2067 case SENSOR_OV7660:
2068 if (ov7660_init_sensor(gspca_dev) < 0)
2069 return -ENODEV;
2070 info("OV7660 sensor detected");
2071 break;
2072 case SENSOR_OV7670:
2073 if (ov7670_init_sensor(gspca_dev) < 0)
2074 return -ENODEV;
2075 info("OV7670 sensor detected");
2076 break;
2077 case SENSOR_MT9VPRB:
2078 if (mt9v_init_sensor(gspca_dev) < 0)
2079 return -ENODEV;
2080 break;
2081 case SENSOR_MT9M111:
2082 if (mt9m111_init_sensor(gspca_dev) < 0)
2083 return -ENODEV;
2084 info("MT9M111 sensor detected");
2085 break;
2086 case SENSOR_MT9M001:
2087 if (mt9m001_init_sensor(gspca_dev) < 0)
2088 return -ENODEV;
2089 info("MT9M001 sensor detected");
2090 break;
2091 case SENSOR_HV7131R:
2092 if (hv7131r_init_sensor(gspca_dev) < 0)
2093 return -ENODEV;
2094 info("HV7131R sensor detected");
2095 break;
2096 default:
2097 info("Unsupported Sensor");
2098 return -ENODEV;
2099 }
2100
2101 return 0;
2102}
2103
2104static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
2105{
2106 struct sd *sd = (struct sd *) gspca_dev;
2107 u8 value;
2108 switch (sd->sensor) {
2109 case SENSOR_OV9650:
2110 if (mode & MODE_SXGA) {
2111 i2c_w1(gspca_dev, 0x17, 0x1b);
2112 i2c_w1(gspca_dev, 0x18, 0xbc);
2113 i2c_w1(gspca_dev, 0x19, 0x01);
2114 i2c_w1(gspca_dev, 0x1a, 0x82);
2115 i2c_r1(gspca_dev, 0x12, &value);
2116 i2c_w1(gspca_dev, 0x12, value & 0x07);
2117 } else {
2118 i2c_w1(gspca_dev, 0x17, 0x24);
2119 i2c_w1(gspca_dev, 0x18, 0xc5);
2120 i2c_w1(gspca_dev, 0x19, 0x00);
2121 i2c_w1(gspca_dev, 0x1a, 0x3c);
2122 i2c_r1(gspca_dev, 0x12, &value);
2123 i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
2124 }
2125 break;
2126 }
2127}
2128
2129#define HW_WIN(mode, hstart, vstart) \
2130((const u8 []){hstart & 0xff, hstart >> 8, \
2131vstart & 0xff, vstart >> 8, \
2132(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
2133(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
2134
2135#define CLR_WIN(width, height) \
2136((const u8 [])\
2137{0, width >> 2, 0, height >> 1,\
2138((width >> 10) & 0x01) | ((height >> 8) & 0x6)})
2139
2140static int sd_start(struct gspca_dev *gspca_dev)
2141{
2142 struct sd *sd = (struct sd *) gspca_dev;
2143 int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
2144 int width = gspca_dev->width;
2145 int height = gspca_dev->height;
2146 u8 fmt, scale = 0;
2147
2148 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
2149 if (sd->jpeg_hdr == NULL)
2150 return -ENOMEM;
2151
2152 jpeg_define(sd->jpeg_hdr, height, width,
2153 0x21);
2154 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
2155
2156 if (mode & MODE_RAW)
2157 fmt = 0x2d;
2158 else if (mode & MODE_JPEG)
2159 fmt = 0x2c;
2160 else
2161 fmt = 0x2f;
2162
2163 switch (mode & 0x0f) {
2164 case 3:
2165 scale = 0xc0;
2166 info("Set 1280x1024");
2167 break;
2168 case 2:
2169 scale = 0x80;
2170 info("Set 640x480");
2171 break;
2172 case 1:
2173 scale = 0x90;
2174 info("Set 320x240");
2175 break;
2176 case 0:
2177 scale = 0xa0;
2178 info("Set 160x120");
2179 break;
2180 }
2181
2182 configure_sensor_output(gspca_dev, mode);
2183 reg_w(gspca_dev, 0x1100, sd->jpeg_hdr + JPEG_QT0_OFFSET, 64);
2184 reg_w(gspca_dev, 0x1140, sd->jpeg_hdr + JPEG_QT1_OFFSET, 64);
2185 reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5);
2186 reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6);
2187 reg_w1(gspca_dev, 0x1189, scale);
2188 reg_w1(gspca_dev, 0x10e0, fmt);
2189
2190 set_cmatrix(gspca_dev);
2191 set_gamma(gspca_dev);
2192 set_redblue(gspca_dev);
2193 set_gain(gspca_dev);
2194 set_exposure(gspca_dev);
2195 set_hvflip(gspca_dev);
2196
2197 reg_r(gspca_dev, 0x1061, 1);
2198 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] | 0x02);
2199 return 0;
2200}
2201
2202static void sd_stopN(struct gspca_dev *gspca_dev)
2203{
2204 reg_r(gspca_dev, 0x1061, 1);
2205 reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02);
2206}
2207
2208static void sd_stop0(struct gspca_dev *gspca_dev)
2209{
2210 struct sd *sd = (struct sd *) gspca_dev;
2211 kfree(sd->jpeg_hdr);
2212}
2213
2214static void do_autoexposure(struct gspca_dev *gspca_dev)
2215{
2216 struct sd *sd = (struct sd *) gspca_dev;
2217 int avg_lum, new_exp;
2218
2219 if (!sd->auto_exposure)
2220 return;
2221
2222 avg_lum = atomic_read(&sd->avg_lum);
2223
2224 /*
2225 * some hardcoded values are present
2226 * like those for maximal/minimal exposure
2227 * and exposure steps
2228 */
2229 if (avg_lum < MIN_AVG_LUM) {
2230 if (sd->exposure > 0x1770)
2231 return;
2232
2233 new_exp = sd->exposure + sd->exposure_step;
2234 if (new_exp > 0x1770)
2235 new_exp = 0x1770;
2236 if (new_exp < 0x10)
2237 new_exp = 0x10;
2238 sd->exposure = new_exp;
2239 set_exposure(gspca_dev);
2240
2241 sd->older_step = sd->old_step;
2242 sd->old_step = 1;
2243
2244 if (sd->old_step ^ sd->older_step)
2245 sd->exposure_step /= 2;
2246 else
2247 sd->exposure_step += 2;
2248 }
2249 if (avg_lum > MAX_AVG_LUM) {
2250 if (sd->exposure < 0x10)
2251 return;
2252 new_exp = sd->exposure - sd->exposure_step;
2253 if (new_exp > 0x1700)
2254 new_exp = 0x1770;
2255 if (new_exp < 0x10)
2256 new_exp = 0x10;
2257 sd->exposure = new_exp;
2258 set_exposure(gspca_dev);
2259 sd->older_step = sd->old_step;
2260 sd->old_step = 0;
2261
2262 if (sd->old_step ^ sd->older_step)
2263 sd->exposure_step /= 2;
2264 else
2265 sd->exposure_step += 2;
2266 }
2267}
2268
2269static void sd_pkt_scan(struct gspca_dev *gspca_dev,
2270 struct gspca_frame *frame, /* target */
2271 u8 *data, /* isoc packet */
2272 int len) /* iso packet length */
2273{
2274 struct sd *sd = (struct sd *) gspca_dev;
2275 int avg_lum;
2276 static unsigned char frame_header[] =
2277 {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
2278 if (len == 64 && memcmp(data, frame_header, 6) == 0) {
2279 avg_lum = ((data[35] >> 2) & 3) |
2280 (data[20] << 2) |
2281 (data[19] << 10);
2282 avg_lum += ((data[35] >> 4) & 3) |
2283 (data[22] << 2) |
2284 (data[21] << 10);
2285 avg_lum += ((data[35] >> 6) & 3) |
2286 (data[24] << 2) |
2287 (data[23] << 10);
2288 avg_lum += (data[36] & 3) |
2289 (data[26] << 2) |
2290 (data[25] << 10);
2291 avg_lum += ((data[36] >> 2) & 3) |
2292 (data[28] << 2) |
2293 (data[27] << 10);
2294 avg_lum += ((data[36] >> 4) & 3) |
2295 (data[30] << 2) |
2296 (data[29] << 10);
2297 avg_lum += ((data[36] >> 6) & 3) |
2298 (data[32] << 2) |
2299 (data[31] << 10);
2300 avg_lum += ((data[44] >> 4) & 3) |
2301 (data[34] << 2) |
2302 (data[33] << 10);
2303 avg_lum >>= 9;
2304 atomic_set(&sd->avg_lum, avg_lum);
2305 gspca_frame_add(gspca_dev, LAST_PACKET,
2306 frame, data, len);
2307 return;
2308 }
2309 if (gspca_dev->last_packet_type == LAST_PACKET) {
2310 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv
2311 & MODE_JPEG) {
2312 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
2313 sd->jpeg_hdr, JPEG_HDR_SZ);
2314 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
2315 data, len);
2316 } else {
2317 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
2318 data, len);
2319 }
2320 } else {
2321 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
2322 }
2323}
2324
2325/* sub-driver description */
2326static const struct sd_desc sd_desc = {
2327 .name = MODULE_NAME,
2328 .ctrls = sd_ctrls,
2329 .nctrls = ARRAY_SIZE(sd_ctrls),
2330 .config = sd_config,
2331 .init = sd_init,
2332 .start = sd_start,
2333 .stopN = sd_stopN,
2334 .stop0 = sd_stop0,
2335 .pkt_scan = sd_pkt_scan,
2336 .dq_callback = do_autoexposure,
2337#ifdef CONFIG_VIDEO_ADV_DEBUG
2338 .set_register = sd_dbg_s_register,
2339 .get_register = sd_dbg_g_register,
2340#endif
2341 .get_chip_ident = sd_chip_ident,
2342};
2343
2344#define SN9C20X(sensor, i2c_addr, button_mask) \
2345 .driver_info = (button_mask << 16) \
2346 | (SENSOR_ ## sensor << 8) \
2347 | (i2c_addr)
2348
2349static const __devinitdata struct usb_device_id device_table[] = {
2350 {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)},
2351 {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)},
2352 {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)},
2353 {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, 0x10)},
2354 {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30, 0)},
2355 {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)},
2356 {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)},
2357 {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)},
2358 {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)},
2359 {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, 0)},
2360 {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)},
2361 {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)},
2362 {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)},
2363 {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)},
2364 {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)},
2365 {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)},
2366 {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
2367 {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
2368 {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
2369 {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, 0)},
2370 {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, 0)},
2371 {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
2372 {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
2373 {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
2374 {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)},
2375 {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)},
2376 {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)},
2377 {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)},
2378 {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)},
2379 {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)},
2380 {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)},
2381 {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)},
2382 {}
2383};
2384MODULE_DEVICE_TABLE(usb, device_table);
2385
2386/* -- device connect -- */
2387static int sd_probe(struct usb_interface *intf,
2388 const struct usb_device_id *id)
2389{
2390 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2391 THIS_MODULE);
2392}
2393
2394static void sd_disconnect(struct usb_interface *intf)
2395{
2396#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV
2397 struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
2398
2399 sn9c20x_input_cleanup(gspca_dev);
2400#endif
2401
2402 gspca_disconnect(intf);
2403}
2404
2405static struct usb_driver sd_driver = {
2406 .name = MODULE_NAME,
2407 .id_table = device_table,
2408 .probe = sd_probe,
2409 .disconnect = sd_disconnect,
2410#ifdef CONFIG_PM
2411 .suspend = gspca_suspend,
2412 .resume = gspca_resume,
2413 .reset_resume = gspca_resume,
2414#endif
2415};
2416
2417/* -- module insert / remove -- */
2418static int __init sd_mod_init(void)
2419{
2420 int ret;
2421 ret = usb_register(&sd_driver);
2422 if (ret < 0)
2423 return ret;
2424 info("registered");
2425 return 0;
2426}
2427static void __exit sd_mod_exit(void)
2428{
2429 usb_deregister(&sd_driver);
2430 info("deregistered");
2431}
2432
2433module_init(sd_mod_init);
2434module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c
index 0d02f41fa7d0..d6332ab80669 100644
--- a/drivers/media/video/gspca/sonixj.c
+++ b/drivers/media/video/gspca/sonixj.c
@@ -1634,6 +1634,8 @@ static void setfreq(struct gspca_dev *gspca_dev)
1634{ 1634{
1635 struct sd *sd = (struct sd *) gspca_dev; 1635 struct sd *sd = (struct sd *) gspca_dev;
1636 1636
1637 if (gspca_dev->ctrl_dis & (1 << FREQ_IDX))
1638 return;
1637 if (sd->sensor == SENSOR_OV7660) { 1639 if (sd->sensor == SENSOR_OV7660) {
1638 switch (sd->freq) { 1640 switch (sd->freq) {
1639 case 0: /* Banding filter disabled */ 1641 case 0: /* Banding filter disabled */
@@ -1735,6 +1737,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
1735 1737
1736 /* create the JPEG header */ 1738 /* create the JPEG header */
1737 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); 1739 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
1740 if (!sd->jpeg_hdr)
1741 return -ENOMEM;
1738 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, 1742 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
1739 0x21); /* JPEG 422 */ 1743 0x21); /* JPEG 422 */
1740 jpeg_set_qual(sd->jpeg_hdr, sd->quality); 1744 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c
index 8806b2ff82be..fab7ef85a6c1 100644
--- a/drivers/media/video/gspca/spca500.c
+++ b/drivers/media/video/gspca/spca500.c
@@ -670,6 +670,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
670 670
671 /* create the JPEG header */ 671 /* create the JPEG header */
672 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); 672 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
673 if (!sd->jpeg_hdr)
674 return -ENOMEM;
673 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, 675 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
674 0x22); /* JPEG 411 */ 676 0x22); /* JPEG 411 */
675 jpeg_set_qual(sd->jpeg_hdr, sd->quality); 677 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c
index f25be20cf1a6..47628964801e 100644
--- a/drivers/media/video/gspca/stk014.c
+++ b/drivers/media/video/gspca/stk014.c
@@ -333,6 +333,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
333 333
334 /* create the JPEG header */ 334 /* create the JPEG header */
335 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); 335 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
336 if (!sd->jpeg_hdr)
337 return -ENOMEM;
336 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, 338 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
337 0x22); /* JPEG 411 */ 339 0x22); /* JPEG 411 */
338 jpeg_set_qual(sd->jpeg_hdr, sd->quality); 340 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
index 3039ec208f3a..e5024c8496ef 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
@@ -64,7 +64,7 @@ static struct v4l2_pix_format hdcs1x00_mode[] = {
64 { 64 {
65 HDCS_1X00_DEF_WIDTH, 65 HDCS_1X00_DEF_WIDTH,
66 HDCS_1X00_DEF_HEIGHT, 66 HDCS_1X00_DEF_HEIGHT,
67 V4L2_PIX_FMT_SBGGR8, 67 V4L2_PIX_FMT_SGRBG8,
68 V4L2_FIELD_NONE, 68 V4L2_FIELD_NONE,
69 .sizeimage = 69 .sizeimage =
70 HDCS_1X00_DEF_WIDTH * HDCS_1X00_DEF_HEIGHT, 70 HDCS_1X00_DEF_WIDTH * HDCS_1X00_DEF_HEIGHT,
@@ -80,7 +80,7 @@ static struct v4l2_pix_format hdcs1020_mode[] = {
80 { 80 {
81 HDCS_1020_DEF_WIDTH, 81 HDCS_1020_DEF_WIDTH,
82 HDCS_1020_DEF_HEIGHT, 82 HDCS_1020_DEF_HEIGHT,
83 V4L2_PIX_FMT_SBGGR8, 83 V4L2_PIX_FMT_SGRBG8,
84 V4L2_FIELD_NONE, 84 V4L2_FIELD_NONE,
85 .sizeimage = 85 .sizeimage =
86 HDCS_1020_DEF_WIDTH * HDCS_1020_DEF_HEIGHT, 86 HDCS_1020_DEF_WIDTH * HDCS_1020_DEF_HEIGHT,
@@ -131,9 +131,11 @@ static int hdcs_reg_write_seq(struct sd *sd, u8 reg, u8 *vals, u8 len)
131 (reg + len > 0xff))) 131 (reg + len > 0xff)))
132 return -EINVAL; 132 return -EINVAL;
133 133
134 for (i = 0; i < len; i++, reg++) { 134 for (i = 0; i < len; i++) {
135 regs[2*i] = reg; 135 regs[2 * i] = reg;
136 regs[2*i+1] = vals[i]; 136 regs[2 * i + 1] = vals[i];
137 /* All addresses are shifted left one bit as bit 0 toggles r/w */
138 reg += 2;
137 } 139 }
138 140
139 return stv06xx_write_sensor_bytes(sd, regs, len); 141 return stv06xx_write_sensor_bytes(sd, regs, len);
@@ -174,7 +176,9 @@ static int hdcs_set_state(struct sd *sd, enum hdcs_power_state state)
174 } 176 }
175 177
176 ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), val); 178 ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), val);
177 if (ret < 0) 179
180 /* Update the state if the write succeeded */
181 if (!ret)
178 hdcs->state = state; 182 hdcs->state = state;
179 183
180 return ret; 184 return ret;
diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c
index 9623f294bdac..5127bbf9dd26 100644
--- a/drivers/media/video/gspca/sunplus.c
+++ b/drivers/media/video/gspca/sunplus.c
@@ -973,6 +973,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
973 973
974 /* create the JPEG header */ 974 /* create the JPEG header */
975 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); 975 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
976 if (!sd->jpeg_hdr)
977 return -ENOMEM;
976 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, 978 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
977 0x22); /* JPEG 411 */ 979 0x22); /* JPEG 411 */
978 jpeg_set_qual(sd->jpeg_hdr, sd->quality); 980 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c
index 08422d315e68..3d2756f7874a 100644
--- a/drivers/media/video/gspca/zc3xx.c
+++ b/drivers/media/video/gspca/zc3xx.c
@@ -7243,6 +7243,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
7243 7243
7244 /* create the JPEG header */ 7244 /* create the JPEG header */
7245 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL); 7245 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
7246 if (!sd->jpeg_hdr)
7247 return -ENOMEM;
7246 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, 7248 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
7247 0x21); /* JPEG 422 */ 7249 0x21); /* JPEG 422 */
7248 jpeg_set_qual(sd->jpeg_hdr, sd->quality); 7250 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
diff --git a/drivers/media/video/mt9v011.c b/drivers/media/video/mt9v011.c
index 1fe8fc9183a7..b2260de645f0 100644
--- a/drivers/media/video/mt9v011.c
+++ b/drivers/media/video/mt9v011.c
@@ -8,6 +8,7 @@
8#include <linux/i2c.h> 8#include <linux/i2c.h>
9#include <linux/videodev2.h> 9#include <linux/videodev2.h>
10#include <linux/delay.h> 10#include <linux/delay.h>
11#include <asm/div64.h>
11#include <media/v4l2-device.h> 12#include <media/v4l2-device.h>
12#include "mt9v011.h" 13#include "mt9v011.h"
13#include <media/v4l2-i2c-drv.h> 14#include <media/v4l2-i2c-drv.h>
@@ -57,6 +58,7 @@ static struct v4l2_queryctrl mt9v011_qctrl[] = {
57struct mt9v011 { 58struct mt9v011 {
58 struct v4l2_subdev sd; 59 struct v4l2_subdev sd;
59 unsigned width, height; 60 unsigned width, height;
61 unsigned xtal;
60 62
61 u16 global_gain, red_bal, blue_bal; 63 u16 global_gain, red_bal, blue_bal;
62}; 64};
@@ -131,7 +133,7 @@ static const struct i2c_reg_value mt9v011_init_default[] = {
131 { R1E_MT9V011_DIGITAL_ZOOM, 0x0000 }, 133 { R1E_MT9V011_DIGITAL_ZOOM, 0x0000 },
132 { R20_MT9V011_READ_MODE, 0x1000 }, 134 { R20_MT9V011_READ_MODE, 0x1000 },
133 135
134 { R07_MT9V011_OUT_CTRL, 0x000a }, /* chip enable */ 136 { R07_MT9V011_OUT_CTRL, 0x0002 }, /* chip enable */
135}; 137};
136 138
137static void set_balance(struct v4l2_subdev *sd) 139static void set_balance(struct v4l2_subdev *sd)
@@ -154,6 +156,31 @@ static void set_balance(struct v4l2_subdev *sd)
154 mt9v011_write(sd, R2D_MT9V011_RED_GAIN, red_gain); 156 mt9v011_write(sd, R2D_MT9V011_RED_GAIN, red_gain);
155} 157}
156 158
159static void calc_fps(struct v4l2_subdev *sd)
160{
161 struct mt9v011 *core = to_mt9v011(sd);
162 unsigned height, width, hblank, vblank, speed;
163 unsigned row_time, t_time;
164 u64 frames_per_ms;
165 unsigned tmp;
166
167 height = mt9v011_read(sd, R03_MT9V011_HEIGHT);
168 width = mt9v011_read(sd, R04_MT9V011_WIDTH);
169 hblank = mt9v011_read(sd, R05_MT9V011_HBLANK);
170 vblank = mt9v011_read(sd, R06_MT9V011_VBLANK);
171 speed = mt9v011_read(sd, R0A_MT9V011_CLK_SPEED);
172
173 row_time = (width + 113 + hblank) * (speed + 2);
174 t_time = row_time * (height + vblank + 1);
175
176 frames_per_ms = core->xtal * 1000l;
177 do_div(frames_per_ms, t_time);
178 tmp = frames_per_ms;
179
180 v4l2_dbg(1, debug, sd, "Programmed to %u.%03u fps (%d pixel clcks)\n",
181 tmp / 1000, tmp % 1000, t_time);
182}
183
157static void set_res(struct v4l2_subdev *sd) 184static void set_res(struct v4l2_subdev *sd)
158{ 185{
159 struct mt9v011 *core = to_mt9v011(sd); 186 struct mt9v011 *core = to_mt9v011(sd);
@@ -175,10 +202,12 @@ static void set_res(struct v4l2_subdev *sd)
175 mt9v011_write(sd, R04_MT9V011_WIDTH, core->width); 202 mt9v011_write(sd, R04_MT9V011_WIDTH, core->width);
176 mt9v011_write(sd, R05_MT9V011_HBLANK, 771 - core->width); 203 mt9v011_write(sd, R05_MT9V011_HBLANK, 771 - core->width);
177 204
178 vstart = 8 + (640 - core->height) / 2; 205 vstart = 8 + (480 - core->height) / 2;
179 mt9v011_write(sd, R01_MT9V011_ROWSTART, vstart); 206 mt9v011_write(sd, R01_MT9V011_ROWSTART, vstart);
180 mt9v011_write(sd, R03_MT9V011_HEIGHT, core->height); 207 mt9v011_write(sd, R03_MT9V011_HEIGHT, core->height);
181 mt9v011_write(sd, R06_MT9V011_VBLANK, 508 - core->height); 208 mt9v011_write(sd, R06_MT9V011_VBLANK, 508 - core->height);
209
210 calc_fps(sd);
182}; 211};
183 212
184static int mt9v011_reset(struct v4l2_subdev *sd, u32 val) 213static int mt9v011_reset(struct v4l2_subdev *sd, u32 val)
@@ -215,6 +244,23 @@ static int mt9v011_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
215 return -EINVAL; 244 return -EINVAL;
216} 245}
217 246
247static int mt9v011_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
248{
249 int i;
250
251 v4l2_dbg(1, debug, sd, "queryctrl called\n");
252
253 for (i = 0; i < ARRAY_SIZE(mt9v011_qctrl); i++)
254 if (qc->id && qc->id == mt9v011_qctrl[i].id) {
255 memcpy(qc, &(mt9v011_qctrl[i]),
256 sizeof(*qc));
257 return 0;
258 }
259
260 return -EINVAL;
261}
262
263
218static int mt9v011_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 264static int mt9v011_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
219{ 265{
220 struct mt9v011 *core = to_mt9v011(sd); 266 struct mt9v011 *core = to_mt9v011(sd);
@@ -294,6 +340,22 @@ static int mt9v011_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
294 return 0; 340 return 0;
295} 341}
296 342
343static int mt9v011_s_config(struct v4l2_subdev *sd, int dumb, void *data)
344{
345 struct mt9v011 *core = to_mt9v011(sd);
346 unsigned *xtal = data;
347
348 v4l2_dbg(1, debug, sd, "s_config called\n");
349
350 if (xtal) {
351 core->xtal = *xtal;
352 v4l2_dbg(1, debug, sd, "xtal set to %d.%03d MHz\n",
353 *xtal / 1000000, (*xtal / 1000) % 1000);
354 }
355
356 return 0;
357}
358
297 359
298#ifdef CONFIG_VIDEO_ADV_DEBUG 360#ifdef CONFIG_VIDEO_ADV_DEBUG
299static int mt9v011_g_register(struct v4l2_subdev *sd, 361static int mt9v011_g_register(struct v4l2_subdev *sd,
@@ -338,9 +400,11 @@ static int mt9v011_g_chip_ident(struct v4l2_subdev *sd,
338} 400}
339 401
340static const struct v4l2_subdev_core_ops mt9v011_core_ops = { 402static const struct v4l2_subdev_core_ops mt9v011_core_ops = {
403 .queryctrl = mt9v011_queryctrl,
341 .g_ctrl = mt9v011_g_ctrl, 404 .g_ctrl = mt9v011_g_ctrl,
342 .s_ctrl = mt9v011_s_ctrl, 405 .s_ctrl = mt9v011_s_ctrl,
343 .reset = mt9v011_reset, 406 .reset = mt9v011_reset,
407 .s_config = mt9v011_s_config,
344 .g_chip_ident = mt9v011_g_chip_ident, 408 .g_chip_ident = mt9v011_g_chip_ident,
345#ifdef CONFIG_VIDEO_ADV_DEBUG 409#ifdef CONFIG_VIDEO_ADV_DEBUG
346 .g_register = mt9v011_g_register, 410 .g_register = mt9v011_g_register,
@@ -395,6 +459,7 @@ static int mt9v011_probe(struct i2c_client *c,
395 core->global_gain = 0x0024; 459 core->global_gain = 0x0024;
396 core->width = 640; 460 core->width = 640;
397 core->height = 480; 461 core->height = 480;
462 core->xtal = 27000000; /* Hz */
398 463
399 v4l_info(c, "chip found @ 0x%02x (%s)\n", 464 v4l_info(c, "chip found @ 0x%02x (%s)\n",
400 c->addr << 1, c->adapter->name); 465 c->addr << 1, c->adapter->name);