aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2010-02-10 16:57:40 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-02-26 13:11:09 -0500
commit421763e7764e424dcb14ef17ef72ae1eb4ec79fe (patch)
treefac73d302b206dd437a5c44cb4e32c2191ac7692 /drivers
parent606f8428ca1c2fbc665f726b4f810b8d50b87954 (diff)
V4L/DVB: gspca_sonixb: pas106: fixup bright ctrl and add gain and exposure ctrls
Fixup brightness ctrl and add gain and exposure ctrls for PAS106B sensors, this allows enabling autogain (done), and makes the cam usable in low light conditions. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/gspca/sonixb.c101
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
411static const __u8 pas106_sensor_init[][8] = { 435static 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),
532SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60), 556SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60),
533SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, 557SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3,
534 F_GAIN, 0, 0x21), 558 F_GAIN, 0, 0x21),
535SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_SIF, NO_EXPO|NO_FREQ, 559SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_GAIN|F_SIF, NO_FREQ,
536 0), 560 0),
537SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, F_GAIN, 561SENS(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;
888err: 947err: