diff options
author | Jean-François Moine <moinejf@free.fr> | 2010-06-24 04:02:57 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-08-02 13:52:02 -0400 |
commit | a68f723cef2c97c30e84c39a847c0c5feff5f0d5 (patch) | |
tree | 3faf3d01c45f94e848de58b7bea79282a248e5b2 /drivers/media | |
parent | 7d716a36c349bad75e13352d11211c3ae556e92f (diff) |
V4L/DVB: gspca - sq930x: New sensor mt9v111
Signed-off-by: Jean-François Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/gspca/sq930x.c | 392 |
1 files changed, 323 insertions, 69 deletions
diff --git a/drivers/media/video/gspca/sq930x.c b/drivers/media/video/gspca/sq930x.c index dd24127d5168..01954701d813 100644 --- a/drivers/media/video/gspca/sq930x.c +++ b/drivers/media/video/gspca/sq930x.c | |||
@@ -51,8 +51,11 @@ struct sd { | |||
51 | u8 sensor; | 51 | u8 sensor; |
52 | enum { | 52 | enum { |
53 | SENSOR_ICX098BQ, | 53 | SENSOR_ICX098BQ, |
54 | SENSOR_MI0360, | ||
55 | SENSOR_LZ24BP, | 54 | SENSOR_LZ24BP, |
55 | SENSOR_MI0360, | ||
56 | SENSOR_MT9V111, | ||
57 | SENSOR_OV7660, | ||
58 | SENSOR_OV9630, | ||
56 | } sensors; | 59 | } sensors; |
57 | u8 type; | 60 | u8 type; |
58 | #define Generic 0 | 61 | #define Generic 0 |
@@ -295,10 +298,55 @@ static const struct i2c_write_cmd mi0360_start_4[] = { | |||
295 | {0x05, 0x03f5}, /* horiz blanking */ | 298 | {0x05, 0x03f5}, /* horiz blanking */ |
296 | }; | 299 | }; |
297 | 300 | ||
301 | static const struct i2c_write_cmd mt9v111_init_0[] = { | ||
302 | {0x01, 0x0001}, | ||
303 | {0x06, 0x300c}, | ||
304 | {0x08, 0xcc00}, | ||
305 | {0x01, 0x0004}, | ||
306 | }; | ||
307 | static const struct i2c_write_cmd mt9v111_init_1[] = { | ||
308 | {0x03, 0x01e5}, | ||
309 | {0x04, 0x0285}, | ||
310 | }; | ||
311 | static const struct i2c_write_cmd mt9v111_init_2[] = { | ||
312 | {0x30, 0x7800}, | ||
313 | {0x31, 0x0000}, | ||
314 | {0x07, 0x3002}, | ||
315 | {0x35, 0x0020}, | ||
316 | {0x2b, 0x0020}, | ||
317 | {0x2c, 0x0020}, | ||
318 | {0x2d, 0x0020}, | ||
319 | {0x2e, 0x0020}, | ||
320 | }; | ||
321 | static const struct ucbus_write_cmd mt9v111_start_1[] = { | ||
322 | {0xf5f0, 0x11}, {0xf5f1, 0x96}, {0xf5f2, 0x80}, {0xf5f3, 0x80}, | ||
323 | {0xf5f4, 0xaa}, | ||
324 | {0xf5f0, 0x51}, {0xf5f1, 0x96}, {0xf5f2, 0x80}, {0xf5f3, 0x80}, | ||
325 | {0xf5f4, 0xaa}, | ||
326 | {0xf5fa, 0x00}, {0xf5f6, 0x0a}, {0xf5f7, 0x0a}, {0xf5f8, 0x0a}, | ||
327 | {0xf5f9, 0x0a} | ||
328 | }; | ||
329 | static const struct i2c_write_cmd mt9v111_init_3[] = { | ||
330 | {0x62, 0x0405}, | ||
331 | }; | ||
332 | static const struct i2c_write_cmd mt9v111_init_4[] = { | ||
333 | {0x05, 0x00ce}, | ||
334 | }; | ||
335 | |||
336 | static const struct ucbus_write_cmd ov7660_start_0[] = { | ||
337 | {0x0354, 0x00}, {0x03fa, 0x00}, {0xf332, 0x00}, {0xf333, 0xc0}, | ||
338 | {0xf334, 0x39}, {0xf335, 0xe7}, {0xf33f, 0x03} | ||
339 | }; | ||
340 | |||
341 | static const struct ucbus_write_cmd ov9630_start_0[] = { | ||
342 | {0x0354, 0x00}, {0x03fa, 0x00}, {0xf332, 0x00}, {0xf333, 0x00}, | ||
343 | {0xf334, 0x3e}, {0xf335, 0xf8}, {0xf33f, 0x03} | ||
344 | }; | ||
345 | |||
298 | static const struct cap_s { | 346 | static const struct cap_s { |
299 | u8 cc_sizeid; | 347 | u8 cc_sizeid; |
300 | u8 cc_bytes[32]; | 348 | u8 cc_bytes[32]; |
301 | } capconfig[3][3] = { | 349 | } capconfig[4][3] = { |
302 | [SENSOR_ICX098BQ] = { | 350 | [SENSOR_ICX098BQ] = { |
303 | {0, /* JPEG, 160x120 */ | 351 | {0, /* JPEG, 160x120 */ |
304 | {0x01, 0x1f, 0x20, 0x0e, 0x00, 0x9f, 0x02, 0xee, | 352 | {0x01, 0x1f, 0x20, 0x0e, 0x00, 0x9f, 0x02, 0xee, |
@@ -351,6 +399,101 @@ static const struct cap_s { | |||
351 | 0x07, 0xe1, 0x01, 0xe1, 0x01, 0x3f, 0x01, 0x3f, | 399 | 0x07, 0xe1, 0x01, 0xe1, 0x01, 0x3f, 0x01, 0x3f, |
352 | 0x01, 0x3f, 0x01, 0x05, 0x80, 0x02, 0xe0, 0x01} }, | 400 | 0x01, 0x3f, 0x01, 0x05, 0x80, 0x02, 0xe0, 0x01} }, |
353 | }, | 401 | }, |
402 | [SENSOR_MT9V111] = { | ||
403 | {0, /* JPEG, 160x120 */ | ||
404 | {0x05, 0x3d, 0x20, 0x0b, 0x00, 0xbd, 0x02, 0x0b, | ||
405 | 0x02, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, | ||
406 | 0x02, 0x01, 0x01, 0x01, 0x01, 0x9f, 0x00, 0x9f, | ||
407 | 0x00, 0x9f, 0x01, 0x05, 0xa0, 0x00, 0x80, 0x00} }, | ||
408 | {2, /* JPEG, 320x240 */ | ||
409 | {0x01, 0x02, 0x20, 0x03, 0x20, 0x82, 0x02, 0xe3, | ||
410 | 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, | ||
411 | 0x02, 0xdf, 0x01, 0x00, 0x00, 0x3f, 0x01, 0x3f, | ||
412 | 0x01, 0x00, 0x00, 0x05, 0x40, 0x01, 0xf0, 0x00} }, | ||
413 | {4, /* JPEG, 640x480 */ | ||
414 | {0x01, 0x02, 0x20, 0x03, 0x20, 0x82, 0x02, 0xe3, | ||
415 | 0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8, | ||
416 | 0x07, 0xe1, 0x01, 0xe1, 0x01, 0x3f, 0x01, 0x3f, | ||
417 | 0x01, 0x3f, 0x01, 0x05, 0x80, 0x02, 0xe0, 0x01} }, | ||
418 | }, | ||
419 | }; | ||
420 | |||
421 | struct sensor_s { | ||
422 | const char *name; | ||
423 | u8 i2c_addr; | ||
424 | u8 i2c_dum; | ||
425 | u8 gpio[5]; | ||
426 | u8 cmd_len; | ||
427 | const struct ucbus_write_cmd *cmd; | ||
428 | }; | ||
429 | |||
430 | static const struct sensor_s sensor_tb[] = { | ||
431 | [SENSOR_ICX098BQ] = { | ||
432 | "icx098bp", | ||
433 | 0x00, 0x00, | ||
434 | {0, | ||
435 | SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL, | ||
436 | SQ930_GPIO_DFL_I2C_SDA, | ||
437 | 0, | ||
438 | SQ930_GPIO_RSTBAR | ||
439 | }, | ||
440 | 8, icx098bq_start_0 | ||
441 | }, | ||
442 | [SENSOR_LZ24BP] = { | ||
443 | "lz24bp", | ||
444 | 0x00, 0x00, | ||
445 | {0, | ||
446 | SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL, | ||
447 | SQ930_GPIO_DFL_I2C_SDA, | ||
448 | 0, | ||
449 | SQ930_GPIO_RSTBAR | ||
450 | }, | ||
451 | 8, lz24bp_start_0 | ||
452 | }, | ||
453 | [SENSOR_MI0360] = { | ||
454 | "mi0360", | ||
455 | 0x5d, 0x80, | ||
456 | {SQ930_GPIO_RSTBAR, | ||
457 | SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL, | ||
458 | SQ930_GPIO_DFL_I2C_SDA, | ||
459 | 0, | ||
460 | 0 | ||
461 | }, | ||
462 | 7, mi0360_start_0 | ||
463 | }, | ||
464 | [SENSOR_MT9V111] = { | ||
465 | "mt9v111", | ||
466 | 0x5c, 0x7f, | ||
467 | {SQ930_GPIO_RSTBAR, | ||
468 | SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL, | ||
469 | SQ930_GPIO_DFL_I2C_SDA, | ||
470 | 0, | ||
471 | 0 | ||
472 | }, | ||
473 | 7, mi0360_start_0 | ||
474 | }, | ||
475 | [SENSOR_OV7660] = { | ||
476 | "ov7660", | ||
477 | 0x21, 0x00, | ||
478 | {0, | ||
479 | SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL, | ||
480 | SQ930_GPIO_DFL_I2C_SDA, | ||
481 | 0, | ||
482 | SQ930_GPIO_RSTBAR | ||
483 | }, | ||
484 | 7, ov7660_start_0 | ||
485 | }, | ||
486 | [SENSOR_OV9630] = { | ||
487 | "ov9630", | ||
488 | 0x30, 0x00, | ||
489 | {0, | ||
490 | SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL, | ||
491 | SQ930_GPIO_DFL_I2C_SDA, | ||
492 | 0, | ||
493 | SQ930_GPIO_RSTBAR | ||
494 | }, | ||
495 | 7, ov9630_start_0 | ||
496 | }, | ||
354 | }; | 497 | }; |
355 | 498 | ||
356 | static void reg_r(struct gspca_dev *gspca_dev, | 499 | static void reg_r(struct gspca_dev *gspca_dev, |
@@ -415,10 +558,12 @@ static void reg_wb(struct gspca_dev *gspca_dev, u16 value, u16 index, | |||
415 | } | 558 | } |
416 | } | 559 | } |
417 | 560 | ||
418 | static void i2c_write(struct gspca_dev *gspca_dev, | 561 | static void i2c_write(struct sd *sd, |
419 | const struct i2c_write_cmd *cmd, | 562 | const struct i2c_write_cmd *cmd, |
420 | int ncmds) | 563 | int ncmds) |
421 | { | 564 | { |
565 | struct gspca_dev *gspca_dev = &sd->gspca_dev; | ||
566 | const struct sensor_s *sensor; | ||
422 | u16 val, idx; | 567 | u16 val, idx; |
423 | u8 *buf; | 568 | u8 *buf; |
424 | int ret; | 569 | int ret; |
@@ -426,18 +571,20 @@ static void i2c_write(struct gspca_dev *gspca_dev, | |||
426 | if (gspca_dev->usb_err < 0) | 571 | if (gspca_dev->usb_err < 0) |
427 | return; | 572 | return; |
428 | 573 | ||
429 | val = (0x5d << 8) | SQ930_CTRL_I2C_IO; /* 0x5d = mi0360 i2c addr */ | 574 | sensor = &sensor_tb[sd->sensor]; |
575 | |||
576 | val = (sensor->i2c_addr << 8) | SQ930_CTRL_I2C_IO; | ||
430 | idx = (cmd->val & 0xff00) | cmd->reg; | 577 | idx = (cmd->val & 0xff00) | cmd->reg; |
431 | 578 | ||
432 | buf = gspca_dev->usb_buf; | 579 | buf = gspca_dev->usb_buf; |
433 | *buf++ = 0x80; | 580 | *buf++ = sensor->i2c_dum; |
434 | *buf++ = cmd->val; | 581 | *buf++ = cmd->val; |
435 | 582 | ||
436 | while (--ncmds > 0) { | 583 | while (--ncmds > 0) { |
437 | cmd++; | 584 | cmd++; |
438 | *buf++ = cmd->reg; | 585 | *buf++ = cmd->reg; |
439 | *buf++ = cmd->val >> 8; | 586 | *buf++ = cmd->val >> 8; |
440 | *buf++ = 0x80; | 587 | *buf++ = sensor->i2c_dum; |
441 | *buf++ = cmd->val; | 588 | *buf++ = cmd->val; |
442 | } | 589 | } |
443 | 590 | ||
@@ -538,7 +685,17 @@ static void gpio_set(struct sd *sd, u16 val, u16 mask) | |||
538 | } | 685 | } |
539 | } | 686 | } |
540 | 687 | ||
541 | static void global_init(struct sd *sd, int first_time) | 688 | static void gpio_init(struct sd *sd, |
689 | const u8 *gpio) | ||
690 | { | ||
691 | gpio_set(sd, *gpio++, 0x000f); | ||
692 | gpio_set(sd, *gpio++, 0x000f); | ||
693 | gpio_set(sd, *gpio++, 0x000f); | ||
694 | gpio_set(sd, *gpio++, 0x000f); | ||
695 | gpio_set(sd, *gpio, 0x000f); | ||
696 | } | ||
697 | |||
698 | static void bridge_init(struct sd *sd) | ||
542 | { | 699 | { |
543 | static const struct ucbus_write_cmd clkfreq_cmd = { | 700 | static const struct ucbus_write_cmd clkfreq_cmd = { |
544 | 0xf031, 0 /* SQ930_CLKFREQ_60MHZ */ | 701 | 0xf031, 0 /* SQ930_CLKFREQ_60MHZ */ |
@@ -547,19 +704,81 @@ static void global_init(struct sd *sd, int first_time) | |||
547 | ucbus_write(&sd->gspca_dev, &clkfreq_cmd, 1, 1); | 704 | ucbus_write(&sd->gspca_dev, &clkfreq_cmd, 1, 1); |
548 | 705 | ||
549 | gpio_set(sd, SQ930_GPIO_POWER, 0xff00); | 706 | gpio_set(sd, SQ930_GPIO_POWER, 0xff00); |
707 | } | ||
708 | |||
709 | static void cmos_probe(struct gspca_dev *gspca_dev) | ||
710 | { | ||
711 | struct sd *sd = (struct sd *) gspca_dev; | ||
712 | int i; | ||
713 | const struct sensor_s *sensor; | ||
714 | static const u8 probe_order[] = { | ||
715 | /* SENSOR_LZ24BP, (tested as ccd) */ | ||
716 | SENSOR_OV9630, | ||
717 | SENSOR_MI0360, | ||
718 | SENSOR_OV7660, | ||
719 | SENSOR_MT9V111, | ||
720 | }; | ||
721 | |||
722 | for (i = 0; i < ARRAY_SIZE(probe_order); i++) { | ||
723 | sensor = &sensor_tb[probe_order[i]]; | ||
724 | ucbus_write(&sd->gspca_dev, sensor->cmd, sensor->cmd_len, 8); | ||
725 | gpio_init(sd, sensor->gpio); | ||
726 | msleep(100); | ||
727 | reg_r(gspca_dev, (sensor->i2c_addr << 8) | 0x001c, 1); | ||
728 | msleep(100); | ||
729 | if (gspca_dev->usb_buf[0] != 0) | ||
730 | break; | ||
731 | } | ||
732 | if (i >= ARRAY_SIZE(probe_order)) | ||
733 | PDEBUG(D_PROBE, "Unknown sensor"); | ||
734 | else | ||
735 | sd->sensor = probe_order[i]; | ||
736 | } | ||
737 | |||
738 | static void mt9v111_init(struct gspca_dev *gspca_dev) | ||
739 | { | ||
740 | int i, nwait; | ||
741 | static const u8 cmd_001b[] = { | ||
742 | 0x00, 0x3b, 0xf6, 0x01, 0x03, 0x02, 0x00, 0x00, | ||
743 | 0x00, 0x00, 0x00 | ||
744 | }; | ||
745 | static const u8 cmd_011b[][7] = { | ||
746 | {0x10, 0x01, 0x66, 0x08, 0x00, 0x00, 0x00}, | ||
747 | {0x01, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x00}, | ||
748 | {0x20, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00}, | ||
749 | {0x02, 0x01, 0xae, 0x01, 0x00, 0x00, 0x00}, | ||
750 | }; | ||
751 | |||
752 | reg_wb(gspca_dev, 0x001b, 0x0000, cmd_001b, sizeof cmd_001b); | ||
753 | for (i = 0; i < ARRAY_SIZE(cmd_011b); i++) { | ||
754 | reg_wb(gspca_dev, 0x001b, 0x0000, cmd_011b[i], | ||
755 | ARRAY_SIZE(cmd_011b[0])); | ||
756 | msleep(400); | ||
757 | nwait = 20; | ||
758 | for (;;) { | ||
759 | reg_r(gspca_dev, 0x031b, 1); | ||
760 | if (gspca_dev->usb_buf[0] == 0 | ||
761 | || gspca_dev->usb_err != 0) | ||
762 | break; | ||
763 | if (--nwait < 0) { | ||
764 | PDEBUG(D_PROBE, "mt9v111_init timeout"); | ||
765 | gspca_dev->usb_err = -ETIME; | ||
766 | return; | ||
767 | } | ||
768 | msleep(50); | ||
769 | } | ||
770 | } | ||
771 | } | ||
772 | |||
773 | static void global_init(struct sd *sd, int first_time) | ||
774 | { | ||
550 | switch (sd->sensor) { | 775 | switch (sd->sensor) { |
551 | case SENSOR_ICX098BQ: | 776 | case SENSOR_ICX098BQ: |
552 | if (first_time) | 777 | if (first_time) |
553 | ucbus_write(&sd->gspca_dev, | 778 | ucbus_write(&sd->gspca_dev, |
554 | icx098bq_start_0, | 779 | icx098bq_start_0, |
555 | 8, 8); | 780 | 8, 8); |
556 | gpio_set(sd, 0, 0x00ff); | 781 | gpio_init(sd, sensor_tb[sd->sensor].gpio); |
557 | gpio_set(sd, SQ930_GPIO_DFL_I2C_SCL | SQ930_GPIO_DFL_I2C_SDA, | ||
558 | SQ930_GPIO_DFL_I2C_SCL | SQ930_GPIO_DFL_I2C_SDA); | ||
559 | gpio_set(sd, 0, SQ930_GPIO_DFL_I2C_SCL); | ||
560 | gpio_set(sd, 0, SQ930_GPIO_DFL_I2C_SDA); | ||
561 | gpio_set(sd, SQ930_GPIO_RSTBAR, | ||
562 | SQ930_GPIO_RSTBAR); | ||
563 | break; | 782 | break; |
564 | case SENSOR_LZ24BP: | 783 | case SENSOR_LZ24BP: |
565 | if (sd->type != Creative_live_motion) | 784 | if (sd->type != Creative_live_motion) |
@@ -571,34 +790,24 @@ static void global_init(struct sd *sd, int first_time) | |||
571 | ucbus_write(&sd->gspca_dev, | 790 | ucbus_write(&sd->gspca_dev, |
572 | lz24bp_start_0, | 791 | lz24bp_start_0, |
573 | 8, 8); | 792 | 8, 8); |
574 | gpio_set(sd, 0, 0x0001); /* no change */ | 793 | gpio_init(sd, sensor_tb[sd->sensor].gpio); |
575 | gpio_set(sd, SQ930_GPIO_DFL_I2C_SCL | SQ930_GPIO_DFL_I2C_SDA, | ||
576 | SQ930_GPIO_DFL_I2C_SCL | SQ930_GPIO_DFL_I2C_SDA); | ||
577 | gpio_set(sd, 0, SQ930_GPIO_DFL_I2C_SCL); | ||
578 | gpio_set(sd, 0, SQ930_GPIO_DFL_I2C_SDA); | ||
579 | gpio_set(sd, SQ930_GPIO_RSTBAR, | ||
580 | SQ930_GPIO_RSTBAR); | ||
581 | break; | 794 | break; |
582 | default: | 795 | case SENSOR_MI0360: |
583 | /* case SENSOR_MI0360: */ | 796 | if (first_time) |
584 | if (first_time) { | ||
585 | ucbus_write(&sd->gspca_dev, | 797 | ucbus_write(&sd->gspca_dev, |
586 | mi0360_start_0, | 798 | mi0360_start_0, |
587 | ARRAY_SIZE(mi0360_start_0), | 799 | ARRAY_SIZE(mi0360_start_0), |
588 | 8); | 800 | 8); |
589 | gpio_set(sd, SQ930_GPIO_RSTBAR, 0x00ff); | 801 | gpio_init(sd, sensor_tb[sd->sensor].gpio); |
590 | } else { | ||
591 | gpio_set(sd, SQ930_GPIO_EXTRA2 | SQ930_GPIO_RSTBAR, | ||
592 | 0x00ff); | ||
593 | } | ||
594 | gpio_set(sd, SQ930_GPIO_DFL_I2C_SCL | SQ930_GPIO_DFL_I2C_SDA, | ||
595 | SQ930_GPIO_RSTBAR | | ||
596 | SQ930_GPIO_DFL_I2C_SCL | SQ930_GPIO_DFL_I2C_SDA); | ||
597 | gpio_set(sd, 0, SQ930_GPIO_DFL_I2C_SCL); | ||
598 | gpio_set(sd, 0, SQ930_GPIO_DFL_I2C_SDA); | ||
599 | gpio_set(sd, 0, SQ930_GPIO_DFL_I2C_SDA); | ||
600 | gpio_set(sd, SQ930_GPIO_EXTRA2, SQ930_GPIO_EXTRA2); | 802 | gpio_set(sd, SQ930_GPIO_EXTRA2, SQ930_GPIO_EXTRA2); |
601 | break; | 803 | break; |
804 | default: | ||
805 | /* case SENSOR_MT9V111: */ | ||
806 | if (first_time) | ||
807 | mt9v111_init(&sd->gspca_dev); | ||
808 | else | ||
809 | gpio_init(sd, sensor_tb[sd->sensor].gpio); | ||
810 | break; | ||
602 | } | 811 | } |
603 | } | 812 | } |
604 | 813 | ||
@@ -616,30 +825,17 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
616 | { | 825 | { |
617 | struct sd *sd = (struct sd *) gspca_dev; | 826 | struct sd *sd = (struct sd *) gspca_dev; |
618 | int i, integclks, intstartclk, frameclks, min_frclk; | 827 | int i, integclks, intstartclk, frameclks, min_frclk; |
828 | const struct sensor_s *sensor; | ||
619 | u16 cmd; | 829 | u16 cmd; |
620 | u8 buf[15]; | 830 | u8 buf[15]; |
621 | 831 | ||
622 | integclks = sd->expo; | 832 | integclks = sd->expo; |
623 | i = 0; | 833 | i = 0; |
624 | cmd = SQ930_CTRL_SET_EXPOSURE; | 834 | cmd = SQ930_CTRL_SET_EXPOSURE; |
625 | if (sd->sensor == SENSOR_MI0360) { | 835 | |
626 | cmd |= 0x0100; | 836 | switch (sd->sensor) { |
627 | buf[i++] = 0x5d; /* i2c_slave_addr */ | 837 | case SENSOR_ICX098BQ: /* ccd */ |
628 | buf[i++] = 0x08; /* 2 * ni2c */ | 838 | case SENSOR_LZ24BP: |
629 | buf[i++] = 0x09; /* reg = shutter width */ | ||
630 | buf[i++] = integclks >> 8; /* val H */ | ||
631 | buf[i++] = 0x80; | ||
632 | buf[i++] = integclks; /* val L */ | ||
633 | buf[i++] = 0x35; /* reg = global gain */ | ||
634 | buf[i++] = 0x00; /* val H */ | ||
635 | buf[i++] = 0x80; | ||
636 | buf[i++] = sd->gain; /* val L */ | ||
637 | buf[i++] = 0x00; | ||
638 | buf[i++] = 0x00; | ||
639 | buf[i++] = 0x00; | ||
640 | buf[i++] = 0x00; | ||
641 | buf[i++] = 0x83; | ||
642 | } else { | ||
643 | min_frclk = sd->sensor == SENSOR_ICX098BQ ? 0x210 : 0x26f; | 839 | min_frclk = sd->sensor == SENSOR_ICX098BQ ? 0x210 : 0x26f; |
644 | if (integclks >= min_frclk) { | 840 | if (integclks >= min_frclk) { |
645 | intstartclk = 0; | 841 | intstartclk = 0; |
@@ -653,6 +849,28 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
653 | buf[i++] = frameclks >> 8; | 849 | buf[i++] = frameclks >> 8; |
654 | buf[i++] = frameclks; | 850 | buf[i++] = frameclks; |
655 | buf[i++] = sd->gain; | 851 | buf[i++] = sd->gain; |
852 | break; | ||
853 | default: /* cmos */ | ||
854 | /* case SENSOR_MI0360: */ | ||
855 | /* case SENSOR_MT9V111: */ | ||
856 | cmd |= 0x0100; | ||
857 | sensor = &sensor_tb[sd->sensor]; | ||
858 | buf[i++] = sensor->i2c_addr; /* i2c_slave_addr */ | ||
859 | buf[i++] = 0x08; /* 2 * ni2c */ | ||
860 | buf[i++] = 0x09; /* reg = shutter width */ | ||
861 | buf[i++] = integclks >> 8; /* val H */ | ||
862 | buf[i++] = sensor->i2c_dum; | ||
863 | buf[i++] = integclks; /* val L */ | ||
864 | buf[i++] = 0x35; /* reg = global gain */ | ||
865 | buf[i++] = 0x00; /* val H */ | ||
866 | buf[i++] = sensor->i2c_dum; | ||
867 | buf[i++] = sd->gain; /* val L */ | ||
868 | buf[i++] = 0x00; | ||
869 | buf[i++] = 0x00; | ||
870 | buf[i++] = 0x00; | ||
871 | buf[i++] = 0x00; | ||
872 | buf[i++] = 0x83; | ||
873 | break; | ||
656 | } | 874 | } |
657 | reg_wb(gspca_dev, cmd, 0, buf, i); | 875 | reg_wb(gspca_dev, cmd, 0, buf, i); |
658 | } | 876 | } |
@@ -688,8 +906,10 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
688 | 906 | ||
689 | sd->gpio[0] = sd->gpio[1] = 0xff; /* force gpio rewrite */ | 907 | sd->gpio[0] = sd->gpio[1] = 0xff; /* force gpio rewrite */ |
690 | 908 | ||
909 | /*fixme: is this needed for icx098bp and mi0360? | ||
691 | if (sd->sensor != SENSOR_LZ24BP) | 910 | if (sd->sensor != SENSOR_LZ24BP) |
692 | reg_w(gspca_dev, SQ930_CTRL_RESET, 0x0000); | 911 | reg_w(gspca_dev, SQ930_CTRL_RESET, 0x0000); |
912 | */ | ||
693 | 913 | ||
694 | reg_r(gspca_dev, SQ930_CTRL_GET_DEV_INFO, 8); | 914 | reg_r(gspca_dev, SQ930_CTRL_GET_DEV_INFO, 8); |
695 | /* it returns: | 915 | /* it returns: |
@@ -706,7 +926,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
706 | * 2: 06 / 07 / 12 = mode webcam? firmware?? | 926 | * 2: 06 / 07 / 12 = mode webcam? firmware?? |
707 | * 3: 93 chip = 930b (930b or 930c) | 927 | * 3: 93 chip = 930b (930b or 930c) |
708 | * 4: 0b | 928 | * 4: 0b |
709 | * 5: f6 = cdd (icx098bq, lz24bp) / fe = cmos (i2c) (mi0360, ov9630) | 929 | * 5: f6 = cdd (icx098bq, lz24bp) / fe or de = cmos (i2c) (other sensors) |
710 | * 6: c8 / c9 / ca / cf = mode webcam?, sensor? webcam? | 930 | * 6: c8 / c9 / ca / cf = mode webcam?, sensor? webcam? |
711 | * 7: 00 | 931 | * 7: 00 |
712 | */ | 932 | */ |
@@ -720,14 +940,22 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
720 | gspca_dev->usb_buf[6], | 940 | gspca_dev->usb_buf[6], |
721 | gspca_dev->usb_buf[7]); | 941 | gspca_dev->usb_buf[7]); |
722 | 942 | ||
723 | /*fixme: no sensor probe - special case for icam tracer */ | 943 | bridge_init(sd); |
724 | if (gspca_dev->usb_buf[5] == 0xf6 | 944 | |
725 | && sd->sensor == SENSOR_MI0360) { | 945 | if (sd->sensor == SENSOR_MI0360) { |
726 | sd->sensor = SENSOR_ICX098BQ; | 946 | |
727 | gspca_dev->cam.cam_mode = &vga_mode[1]; /* only 320x240 */ | 947 | /* no sensor probe for icam tracer */ |
728 | gspca_dev->cam.nmodes = 1; | 948 | if (gspca_dev->usb_buf[5] == 0xf6) { /* if CMOS */ |
949 | sd->sensor = SENSOR_ICX098BQ; | ||
950 | gspca_dev->cam.cam_mode = &vga_mode[1]; | ||
951 | gspca_dev->cam.nmodes = 1; /* only 320x240 */ | ||
952 | } else { | ||
953 | cmos_probe(gspca_dev); | ||
954 | } | ||
729 | } | 955 | } |
730 | 956 | ||
957 | PDEBUG(D_PROBE, "Sensor %s", sensor_tb[sd->sensor].name); | ||
958 | |||
731 | global_init(sd, 1); | 959 | global_init(sd, 1); |
732 | return gspca_dev->usb_err; | 960 | return gspca_dev->usb_err; |
733 | } | 961 | } |
@@ -799,6 +1027,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
799 | 0x21); /* JPEG 422 */ | 1027 | 0x21); /* JPEG 422 */ |
800 | sd_jpeg_set_qual(sd->jpeg_hdr, sd->quality); | 1028 | sd_jpeg_set_qual(sd->jpeg_hdr, sd->quality); |
801 | 1029 | ||
1030 | bridge_init(sd); | ||
802 | global_init(sd, 0); | 1031 | global_init(sd, 0); |
803 | msleep(100); | 1032 | msleep(100); |
804 | 1033 | ||
@@ -845,23 +1074,22 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
845 | lz24bp_ppl(sd, mode == 2 ? 0x0564 : 0x0310); | 1074 | lz24bp_ppl(sd, mode == 2 ? 0x0564 : 0x0310); |
846 | msleep(10); | 1075 | msleep(10); |
847 | break; | 1076 | break; |
848 | default: | 1077 | case SENSOR_MI0360: |
849 | /* case SENSOR_MI0360: */ | ||
850 | ucbus_write(gspca_dev, mi0360_start_0, | 1078 | ucbus_write(gspca_dev, mi0360_start_0, |
851 | ARRAY_SIZE(mi0360_start_0), | 1079 | ARRAY_SIZE(mi0360_start_0), |
852 | 8); | 1080 | 8); |
853 | i2c_write(gspca_dev, mi0360_init_23, | 1081 | i2c_write(sd, mi0360_init_23, |
854 | ARRAY_SIZE(mi0360_init_23)); | 1082 | ARRAY_SIZE(mi0360_init_23)); |
855 | i2c_write(gspca_dev, mi0360_init_24, | 1083 | i2c_write(sd, mi0360_init_24, |
856 | ARRAY_SIZE(mi0360_init_24)); | 1084 | ARRAY_SIZE(mi0360_init_24)); |
857 | i2c_write(gspca_dev, mi0360_init_25, | 1085 | i2c_write(sd, mi0360_init_25, |
858 | ARRAY_SIZE(mi0360_init_25)); | 1086 | ARRAY_SIZE(mi0360_init_25)); |
859 | ucbus_write(gspca_dev, mi0360_start_1, | 1087 | ucbus_write(gspca_dev, mi0360_start_1, |
860 | ARRAY_SIZE(mi0360_start_1), | 1088 | ARRAY_SIZE(mi0360_start_1), |
861 | 5); | 1089 | 5); |
862 | i2c_write(gspca_dev, mi0360_start_2, | 1090 | i2c_write(sd, mi0360_start_2, |
863 | ARRAY_SIZE(mi0360_start_2)); | 1091 | ARRAY_SIZE(mi0360_start_2)); |
864 | i2c_write(gspca_dev, mi0360_start_3, | 1092 | i2c_write(sd, mi0360_start_3, |
865 | ARRAY_SIZE(mi0360_start_3)); | 1093 | ARRAY_SIZE(mi0360_start_3)); |
866 | 1094 | ||
867 | /* 1st start */ | 1095 | /* 1st start */ |
@@ -869,9 +1097,28 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
869 | msleep(60); | 1097 | msleep(60); |
870 | reg_w(gspca_dev, SQ930_CTRL_CAP_STOP, 0x0000); | 1098 | reg_w(gspca_dev, SQ930_CTRL_CAP_STOP, 0x0000); |
871 | 1099 | ||
872 | i2c_write(gspca_dev, | 1100 | i2c_write(sd, |
873 | mi0360_start_4, ARRAY_SIZE(mi0360_start_4)); | 1101 | mi0360_start_4, ARRAY_SIZE(mi0360_start_4)); |
874 | break; | 1102 | break; |
1103 | default: | ||
1104 | /* case SENSOR_MT9V111: */ | ||
1105 | ucbus_write(gspca_dev, mi0360_start_0, | ||
1106 | ARRAY_SIZE(mi0360_start_0), | ||
1107 | 8); | ||
1108 | i2c_write(sd, mt9v111_init_0, | ||
1109 | ARRAY_SIZE(mt9v111_init_0)); | ||
1110 | i2c_write(sd, mt9v111_init_1, | ||
1111 | ARRAY_SIZE(mt9v111_init_1)); | ||
1112 | i2c_write(sd, mt9v111_init_2, | ||
1113 | ARRAY_SIZE(mt9v111_init_2)); | ||
1114 | ucbus_write(gspca_dev, mt9v111_start_1, | ||
1115 | ARRAY_SIZE(mt9v111_start_1), | ||
1116 | 8); | ||
1117 | i2c_write(sd, mt9v111_init_3, | ||
1118 | ARRAY_SIZE(mt9v111_init_3)); | ||
1119 | i2c_write(sd, mt9v111_init_4, | ||
1120 | ARRAY_SIZE(mt9v111_init_4)); | ||
1121 | break; | ||
875 | } | 1122 | } |
876 | 1123 | ||
877 | send_start(gspca_dev); | 1124 | send_start(gspca_dev); |
@@ -880,6 +1127,9 @@ out: | |||
880 | 1127 | ||
881 | sd->eof_len = 0; /* init packet scan */ | 1128 | sd->eof_len = 0; /* init packet scan */ |
882 | 1129 | ||
1130 | if (sd->sensor == SENSOR_MT9V111) | ||
1131 | gpio_set(sd, SQ930_GPIO_DFL_LED, SQ930_GPIO_DFL_LED); | ||
1132 | |||
883 | sd->do_ctrl = 1; /* set the exposure */ | 1133 | sd->do_ctrl = 1; /* set the exposure */ |
884 | 1134 | ||
885 | return gspca_dev->usb_err; | 1135 | return gspca_dev->usb_err; |
@@ -887,6 +1137,10 @@ out: | |||
887 | 1137 | ||
888 | static void sd_stopN(struct gspca_dev *gspca_dev) | 1138 | static void sd_stopN(struct gspca_dev *gspca_dev) |
889 | { | 1139 | { |
1140 | struct sd *sd = (struct sd *) gspca_dev; | ||
1141 | |||
1142 | if (sd->sensor == SENSOR_MT9V111) | ||
1143 | gpio_set(sd, 0, SQ930_GPIO_DFL_LED); | ||
890 | send_stop(gspca_dev); | 1144 | send_stop(gspca_dev); |
891 | } | 1145 | } |
892 | 1146 | ||
@@ -1101,7 +1355,7 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
1101 | {USB_DEVICE(0x041e, 0x403c), ST(LZ24BP, 0)}, | 1355 | {USB_DEVICE(0x041e, 0x403c), ST(LZ24BP, 0)}, |
1102 | {USB_DEVICE(0x041e, 0x403d), ST(LZ24BP, 0)}, | 1356 | {USB_DEVICE(0x041e, 0x403d), ST(LZ24BP, 0)}, |
1103 | {USB_DEVICE(0x041e, 0x4041), ST(LZ24BP, Creative_live_motion)}, | 1357 | {USB_DEVICE(0x041e, 0x4041), ST(LZ24BP, Creative_live_motion)}, |
1104 | {USB_DEVICE(0x2770, 0x930b), ST(MI0360, 0)}, /* or ICX098BQ */ | 1358 | {USB_DEVICE(0x2770, 0x930b), ST(MI0360, 0)}, |
1105 | {USB_DEVICE(0x2770, 0x930c), ST(MI0360, 0)}, | 1359 | {USB_DEVICE(0x2770, 0x930c), ST(MI0360, 0)}, |
1106 | {} | 1360 | {} |
1107 | }; | 1361 | }; |