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:
parent
3647fea840
commit
f4d520258d
@ -121,8 +121,8 @@ static struct ctrl sd_ctrls[] = {
|
|||||||
.id = V4L2_CID_EXPOSURE,
|
.id = V4L2_CID_EXPOSURE,
|
||||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||||
.name = "Exposure",
|
.name = "Exposure",
|
||||||
#define EXPOSURE_DEF 0
|
#define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
|
||||||
#define EXPOSURE_KNEE 176 /* 10 fps */
|
#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
|
||||||
.minimum = 0,
|
.minimum = 0,
|
||||||
.maximum = 255,
|
.maximum = 255,
|
||||||
.step = 1,
|
.step = 1,
|
||||||
@ -611,8 +611,6 @@ static void setgain(struct gspca_dev *gspca_dev)
|
|||||||
static void setexposure(struct gspca_dev *gspca_dev)
|
static void setexposure(struct gspca_dev *gspca_dev)
|
||||||
{
|
{
|
||||||
struct sd *sd = (struct sd *) 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) {
|
switch (sd->sensor) {
|
||||||
case SENSOR_TAS5110: {
|
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
|
/* register 19's high nibble contains the sn9c10x clock divider
|
||||||
The high nibble configures the no fps according to the
|
The high nibble configures the no fps according to the
|
||||||
formula: 60 / high_nibble. With a maximum of 30 fps */
|
formula: 60 / high_nibble. With a maximum of 30 fps */
|
||||||
reg = 60 / fps;
|
reg = 120 * sd->exposure / 1000;
|
||||||
if (reg > 15)
|
if (reg < 2)
|
||||||
|
reg = 2;
|
||||||
|
else if (reg > 15)
|
||||||
reg = 15;
|
reg = 15;
|
||||||
reg = (reg << 4) | 0x0b;
|
reg = (reg << 4) | 0x0b;
|
||||||
reg_w(gspca_dev, 0x19, ®, 1);
|
reg_w(gspca_dev, 0x19, ®, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SENSOR_OV6650: {
|
case SENSOR_OV6650: {
|
||||||
__u8 i2c[] = {0xa0, 0x60, 0x11, 0xc0, 0x00, 0x00, 0x00, 0x10};
|
/* The ov6650 has 2 registers which both influence exposure,
|
||||||
i2c[3] = 30 / fps - 1;
|
first there is register 11, whose low nibble sets the no fps
|
||||||
if (i2c[3] > 15)
|
according to: fps = 30 / (low_nibble + 1)
|
||||||
i2c[3] = 15;
|
|
||||||
i2c[3] |= 0xc0;
|
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)
|
if (i2c_w(gspca_dev, i2c) < 0)
|
||||||
PDEBUG(D_ERR, "i2c error exposure");
|
PDEBUG(D_ERR, "i2c error exposure");
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user