aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/gspca/sonixb.c54
1 files changed, 43 insertions, 11 deletions
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c
index c0ce21fe85f7..7303df0dc16b 100644
--- a/drivers/media/video/gspca/sonixb.c
+++ b/drivers/media/video/gspca/sonixb.c
@@ -121,8 +121,8 @@ static struct ctrl sd_ctrls[] = {
121 .id = V4L2_CID_EXPOSURE, 121 .id = V4L2_CID_EXPOSURE,
122 .type = V4L2_CTRL_TYPE_INTEGER, 122 .type = V4L2_CTRL_TYPE_INTEGER,
123 .name = "Exposure", 123 .name = "Exposure",
124#define EXPOSURE_DEF 0 124#define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
125#define EXPOSURE_KNEE 176 /* 10 fps */ 125#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
126 .minimum = 0, 126 .minimum = 0,
127 .maximum = 255, 127 .maximum = 255,
128 .step = 1, 128 .step = 1,
@@ -611,8 +611,6 @@ static void setgain(struct gspca_dev *gspca_dev)
611static void setexposure(struct gspca_dev *gspca_dev) 611static void setexposure(struct gspca_dev *gspca_dev)
612{ 612{
613 struct sd *sd = (struct sd *) gspca_dev; 613 struct sd *sd = (struct sd *) gspca_dev;
614 /* translate 0 - 255 to a number of fps in a 30 - 1 scale */
615 int fps = 30 - sd->exposure * 29 / 255;
616 614
617 switch (sd->sensor) { 615 switch (sd->sensor) {
618 case SENSOR_TAS5110: { 616 case SENSOR_TAS5110: {
@@ -621,19 +619,53 @@ static void setexposure(struct gspca_dev *gspca_dev)
621 /* register 19's high nibble contains the sn9c10x clock divider 619 /* register 19's high nibble contains the sn9c10x clock divider
622 The high nibble configures the no fps according to the 620 The high nibble configures the no fps according to the
623 formula: 60 / high_nibble. With a maximum of 30 fps */ 621 formula: 60 / high_nibble. With a maximum of 30 fps */
624 reg = 60 / fps; 622 reg = 120 * sd->exposure / 1000;
625 if (reg > 15) 623 if (reg < 2)
624 reg = 2;
625 else if (reg > 15)
626 reg = 15; 626 reg = 15;
627 reg = (reg << 4) | 0x0b; 627 reg = (reg << 4) | 0x0b;
628 reg_w(gspca_dev, 0x19, &reg, 1); 628 reg_w(gspca_dev, 0x19, &reg, 1);
629 break; 629 break;
630 } 630 }
631 case SENSOR_OV6650: { 631 case SENSOR_OV6650: {
632 __u8 i2c[] = {0xa0, 0x60, 0x11, 0xc0, 0x00, 0x00, 0x00, 0x10}; 632 /* The ov6650 has 2 registers which both influence exposure,
633 i2c[3] = 30 / fps - 1; 633 first there is register 11, whose low nibble sets the no fps
634 if (i2c[3] > 15) 634 according to: fps = 30 / (low_nibble + 1)
635 i2c[3] = 15; 635
636 i2c[3] |= 0xc0; 636 The fps configures the maximum exposure setting, but it is
637 possible to use less exposure then what the fps maximum
638 allows by setting register 10. register 10 configures the
639 actual exposure as quotient of the full exposure, with 0
640 being no exposure at all (not very usefull) and reg10_max
641 being max exposure possible at that framerate.
642
643 The code maps our 0 - 510 ms exposure ctrl to these 2
644 registers, trying to keep fps as high as possible.
645 */
646 __u8 i2c[] = {0xb0, 0x60, 0x10, 0x00, 0xc0, 0x00, 0x00, 0x10};
647 int reg10, reg11;
648 /* No clear idea why, but setting reg10 above this value
649 results in no change */
650 const int reg10_max = 0x4d;
651
652 reg11 = (60 * sd->exposure + 999) / 1000;
653 if (reg11 < 1)
654 reg11 = 1;
655 else if (reg11 > 16)
656 reg11 = 16;
657
658 /* frame exposure time in ms = 1000 * reg11 / 30 ->
659 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
660 reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
661 if (reg10 < 1) /* 0 is a valid value, but is very _black_ */
662 reg10 = 1;
663 else if (reg10 > reg10_max)
664 reg10 = reg10_max;
665
666 /* Write reg 10 and reg11 low nibble */
667 i2c[3] = reg10;
668 i2c[4] |= reg11 - 1;
637 if (i2c_w(gspca_dev, i2c) < 0) 669 if (i2c_w(gspca_dev, i2c) < 0)
638 PDEBUG(D_ERR, "i2c error exposure"); 670 PDEBUG(D_ERR, "i2c error exposure");
639 break; 671 break;