diff options
Diffstat (limited to 'drivers/media/video')
-rw-r--r-- | drivers/media/video/gspca/sonixb.c | 101 |
1 files changed, 80 insertions, 21 deletions
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 81a7dd6a7240..43a7721d669c 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c | |||
@@ -188,8 +188,8 @@ static const struct ctrl sd_ctrls[] = { | |||
188 | .id = V4L2_CID_EXPOSURE, | 188 | .id = V4L2_CID_EXPOSURE, |
189 | .type = V4L2_CTRL_TYPE_INTEGER, | 189 | .type = V4L2_CTRL_TYPE_INTEGER, |
190 | .name = "Exposure", | 190 | .name = "Exposure", |
191 | #define EXPOSURE_DEF 66 /* 33 ms / 30 fps (except on PAS202) */ | 191 | #define EXPOSURE_DEF 66 /* 33 ms / 30 fps (except on PASXXX) */ |
192 | #define EXPOSURE_KNEE 200 /* 100 ms / 10 fps (except on PAS202) */ | 192 | #define EXPOSURE_KNEE 200 /* 100 ms / 10 fps (except on PASXXX) */ |
193 | .minimum = 0, | 193 | .minimum = 0, |
194 | .maximum = 1023, | 194 | .maximum = 1023, |
195 | .step = 1, | 195 | .step = 1, |
@@ -408,6 +408,30 @@ static const __u8 initPas106[] = { | |||
408 | 0x18, 0x10, 0x02, 0x02, 0x09, 0x07 | 408 | 0x18, 0x10, 0x02, 0x02, 0x09, 0x07 |
409 | }; | 409 | }; |
410 | /* compression 0x86 mckinit1 0x2b */ | 410 | /* compression 0x86 mckinit1 0x2b */ |
411 | |||
412 | /* "Known" PAS106B registers: | ||
413 | 0x02 clock divider | ||
414 | 0x03 Variable framerate bits 4-11 | ||
415 | 0x04 Var framerate bits 0-3, one must leave the 4 msb's at 0 !! | ||
416 | The variable framerate control must never be set lower then 300, | ||
417 | which sets the framerate at 90 / reg02, otherwise vsync is lost. | ||
418 | 0x05 Shutter Time Line Offset, this can be used as an exposure control: | ||
419 | 0 = use full frame time, 255 = no exposure at all | ||
420 | Note this may never be larger then "var-framerate control" / 2 - 2. | ||
421 | When var-framerate control is < 514, no exposure is reached at the max | ||
422 | allowed value for the framerate control value, rather then at 255. | ||
423 | 0x06 Shutter Time Pixel Offset, like reg05 this influences exposure, but | ||
424 | only a very little bit, leave at 0xcd | ||
425 | 0x07 offset sign bit (bit0 1 > negative offset) | ||
426 | 0x08 offset | ||
427 | 0x09 Blue Gain | ||
428 | 0x0a Green1 Gain | ||
429 | 0x0b Green2 Gain | ||
430 | 0x0c Red Gain | ||
431 | 0x0e Global gain | ||
432 | 0x13 Write 1 to commit settings to sensor | ||
433 | */ | ||
434 | |||
411 | static const __u8 pas106_sensor_init[][8] = { | 435 | static const __u8 pas106_sensor_init[][8] = { |
412 | /* Pixel Clock Divider 6 */ | 436 | /* Pixel Clock Divider 6 */ |
413 | { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 }, | 437 | { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 }, |
@@ -532,7 +556,7 @@ SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0), | |||
532 | SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60), | 556 | SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60), |
533 | SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, | 557 | SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, |
534 | F_GAIN, 0, 0x21), | 558 | F_GAIN, 0, 0x21), |
535 | SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_SIF, NO_EXPO|NO_FREQ, | 559 | SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_GAIN|F_SIF, NO_FREQ, |
536 | 0), | 560 | 0), |
537 | SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, F_GAIN, | 561 | SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, F_GAIN, |
538 | NO_FREQ, 0), | 562 | NO_FREQ, 0), |
@@ -628,26 +652,19 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
628 | goto err; | 652 | goto err; |
629 | break; | 653 | break; |
630 | } | 654 | } |
631 | case SENSOR_PAS106: { | 655 | case SENSOR_PAS106: |
632 | __u8 i2c1[] = | ||
633 | {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14}; | ||
634 | |||
635 | i2c1[3] = sd->brightness >> 3; | ||
636 | i2c1[2] = 0x0e; | ||
637 | if (i2c_w(gspca_dev, i2c1) < 0) | ||
638 | goto err; | ||
639 | i2c1[3] = 0x01; | ||
640 | i2c1[2] = 0x13; | ||
641 | if (i2c_w(gspca_dev, i2c1) < 0) | ||
642 | goto err; | ||
643 | break; | ||
644 | } | ||
645 | case SENSOR_PAS202: { | 656 | case SENSOR_PAS202: { |
646 | __u8 i2cpbright[] = | 657 | __u8 i2cpbright[] = |
647 | {0xb0, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x16}; | 658 | {0xb0, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x16}; |
648 | const __u8 i2cpdoit[] = | 659 | __u8 i2cpdoit[] = |
649 | {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16}; | 660 | {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16}; |
650 | 661 | ||
662 | /* PAS106 uses reg 7 and 8 instead of b and c */ | ||
663 | if (sd->sensor == SENSOR_PAS106) { | ||
664 | i2cpbright[2] = 7; | ||
665 | i2cpdoit[2] = 0x13; | ||
666 | } | ||
667 | |||
651 | if (sd->brightness < 127) { | 668 | if (sd->brightness < 127) { |
652 | /* change reg 0x0b, signreg */ | 669 | /* change reg 0x0b, signreg */ |
653 | i2cpbright[3] = 0x01; | 670 | i2cpbright[3] = 0x01; |
@@ -709,18 +726,28 @@ static void setsensorgain(struct gspca_dev *gspca_dev) | |||
709 | goto err; | 726 | goto err; |
710 | break; | 727 | break; |
711 | } | 728 | } |
729 | case SENSOR_PAS106: | ||
712 | case SENSOR_PAS202: { | 730 | case SENSOR_PAS202: { |
713 | __u8 i2cpgain[] = | 731 | __u8 i2cpgain[] = |
714 | {0xa0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x63, 0x15}; | 732 | {0xa0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x15}; |
715 | __u8 i2cpcolorgain[] = | 733 | __u8 i2cpcolorgain[] = |
716 | {0xc0, 0x40, 0x07, 0x00, 0x00, 0x00, 0x00, 0x15}; | 734 | {0xc0, 0x40, 0x07, 0x00, 0x00, 0x00, 0x00, 0x15}; |
717 | const __u8 i2cpdoit[] = | 735 | __u8 i2cpdoit[] = |
718 | {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x63, 0x16}; | 736 | {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16}; |
737 | |||
738 | /* PAS106 uses different regs (and has split green gains) */ | ||
739 | if (sd->sensor == SENSOR_PAS106) { | ||
740 | i2cpgain[2] = 0x0e; | ||
741 | i2cpcolorgain[0] = 0xd0; | ||
742 | i2cpcolorgain[2] = 0x09; | ||
743 | i2cpdoit[2] = 0x13; | ||
744 | } | ||
719 | 745 | ||
720 | i2cpgain[3] = sd->gain >> 3; | 746 | i2cpgain[3] = sd->gain >> 3; |
721 | i2cpcolorgain[3] = sd->gain >> 4; | 747 | i2cpcolorgain[3] = sd->gain >> 4; |
722 | i2cpcolorgain[4] = sd->gain >> 4; | 748 | i2cpcolorgain[4] = sd->gain >> 4; |
723 | i2cpcolorgain[5] = sd->gain >> 4; | 749 | i2cpcolorgain[5] = sd->gain >> 4; |
750 | i2cpcolorgain[6] = sd->gain >> 4; | ||
724 | 751 | ||
725 | if (i2c_w(gspca_dev, i2cpgain) < 0) | 752 | if (i2c_w(gspca_dev, i2cpgain) < 0) |
726 | goto err; | 753 | goto err; |
@@ -883,6 +910,38 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
883 | goto err; | 910 | goto err; |
884 | break; | 911 | break; |
885 | } | 912 | } |
913 | case SENSOR_PAS106: { | ||
914 | __u8 i2cpframerate[] = | ||
915 | {0xb1, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x14}; | ||
916 | __u8 i2cpexpo[] = | ||
917 | {0xa1, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x14}; | ||
918 | const __u8 i2cpdoit[] = | ||
919 | {0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14}; | ||
920 | int framerate_ctrl; | ||
921 | |||
922 | /* For values below 150 use partial frame exposure, above | ||
923 | that use framerate ctrl */ | ||
924 | if (sd->exposure < 150) { | ||
925 | i2cpexpo[3] = 150 - sd->exposure; | ||
926 | framerate_ctrl = 300; | ||
927 | } else { | ||
928 | /* The PAS106's exposure control goes from 0 - 4095, | ||
929 | but anything below 300 causes vsync issues, so scale | ||
930 | our 150-1023 to 300-4095 */ | ||
931 | framerate_ctrl = (sd->exposure - 150) * 1000 / 230 + | ||
932 | 300; | ||
933 | } | ||
934 | |||
935 | i2cpframerate[3] = framerate_ctrl >> 4; | ||
936 | i2cpframerate[4] = framerate_ctrl & 0x0f; | ||
937 | if (i2c_w(gspca_dev, i2cpframerate) < 0) | ||
938 | goto err; | ||
939 | if (i2c_w(gspca_dev, i2cpexpo) < 0) | ||
940 | goto err; | ||
941 | if (i2c_w(gspca_dev, i2cpdoit) < 0) | ||
942 | goto err; | ||
943 | break; | ||
944 | } | ||
886 | } | 945 | } |
887 | return; | 946 | return; |
888 | err: | 947 | err: |