diff options
author | Hans de Goede <j.w.r.degoede@hhs.nl> | 2008-07-15 08:36:42 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-07-20 06:26:37 -0400 |
commit | f4d520258d229f093bec6937ec3d632eb95600b4 (patch) | |
tree | c21109bccf8b742fc715a281994cb8c8caf65ba8 /drivers/media | |
parent | 3647fea840c94c04f35215cb75b48613c0af310e (diff) |
V4L/DVB (8357): gspca: Perfect exposure for sn9c10x, sensor ov6650.
Signed-off-by: Hans de Goede <j.w.r.degoede@hhs.nl>
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/gspca/sonixb.c | 54 |
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) | |||
611 | static void setexposure(struct gspca_dev *gspca_dev) | 611 | static 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, ®, 1); | 628 | reg_w(gspca_dev, 0x19, ®, 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; |