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>
This commit is contained in:
Hans de Goede 2008-07-15 09:36:42 -03:00 committed by Mauro Carvalho Chehab
parent 3647fea840
commit f4d520258d

View File

@ -121,8 +121,8 @@ static struct ctrl sd_ctrls[] = {
.id = V4L2_CID_EXPOSURE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Exposure",
#define EXPOSURE_DEF 0
#define EXPOSURE_KNEE 176 /* 10 fps */
#define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
.minimum = 0,
.maximum = 255,
.step = 1,
@ -611,8 +611,6 @@ static void setgain(struct gspca_dev *gspca_dev)
static void setexposure(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
/* translate 0 - 255 to a number of fps in a 30 - 1 scale */
int fps = 30 - sd->exposure * 29 / 255;
switch (sd->sensor) {
case SENSOR_TAS5110: {
@ -621,19 +619,53 @@ static void setexposure(struct gspca_dev *gspca_dev)
/* register 19's high nibble contains the sn9c10x clock divider
The high nibble configures the no fps according to the
formula: 60 / high_nibble. With a maximum of 30 fps */
reg = 60 / fps;
if (reg > 15)
reg = 120 * sd->exposure / 1000;
if (reg < 2)
reg = 2;
else if (reg > 15)
reg = 15;
reg = (reg << 4) | 0x0b;
reg_w(gspca_dev, 0x19, &reg, 1);
break;
}
case SENSOR_OV6650: {
__u8 i2c[] = {0xa0, 0x60, 0x11, 0xc0, 0x00, 0x00, 0x00, 0x10};
i2c[3] = 30 / fps - 1;
if (i2c[3] > 15)
i2c[3] = 15;
i2c[3] |= 0xc0;
/* The ov6650 has 2 registers which both influence exposure,
first there is register 11, whose low nibble sets the no fps
according to: fps = 30 / (low_nibble + 1)
The fps configures the maximum exposure setting, but it is
possible to use less exposure then what the fps maximum
allows by setting register 10. register 10 configures the
actual exposure as quotient of the full exposure, with 0
being no exposure at all (not very usefull) and reg10_max
being max exposure possible at that framerate.
The code maps our 0 - 510 ms exposure ctrl to these 2
registers, trying to keep fps as high as possible.
*/
__u8 i2c[] = {0xb0, 0x60, 0x10, 0x00, 0xc0, 0x00, 0x00, 0x10};
int reg10, reg11;
/* No clear idea why, but setting reg10 above this value
results in no change */
const int reg10_max = 0x4d;
reg11 = (60 * sd->exposure + 999) / 1000;
if (reg11 < 1)
reg11 = 1;
else if (reg11 > 16)
reg11 = 16;
/* frame exposure time in ms = 1000 * reg11 / 30 ->
reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
if (reg10 < 1) /* 0 is a valid value, but is very _black_ */
reg10 = 1;
else if (reg10 > reg10_max)
reg10 = reg10_max;
/* Write reg 10 and reg11 low nibble */
i2c[3] = reg10;
i2c[4] |= reg11 - 1;
if (i2c_w(gspca_dev, i2c) < 0)
PDEBUG(D_ERR, "i2c error exposure");
break;