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>
This commit is contained in:
Hans de Goede 2010-02-10 18:57:40 -03:00 committed by Mauro Carvalho Chehab
parent 606f8428ca
commit 421763e776

View File

@ -188,8 +188,8 @@ static const struct ctrl sd_ctrls[] = {
.id = V4L2_CID_EXPOSURE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Exposure",
#define EXPOSURE_DEF 66 /* 33 ms / 30 fps (except on PAS202) */
#define EXPOSURE_KNEE 200 /* 100 ms / 10 fps (except on PAS202) */
#define EXPOSURE_DEF 66 /* 33 ms / 30 fps (except on PASXXX) */
#define EXPOSURE_KNEE 200 /* 100 ms / 10 fps (except on PASXXX) */
.minimum = 0,
.maximum = 1023,
.step = 1,
@ -408,6 +408,30 @@ static const __u8 initPas106[] = {
0x18, 0x10, 0x02, 0x02, 0x09, 0x07
};
/* compression 0x86 mckinit1 0x2b */
/* "Known" PAS106B registers:
0x02 clock divider
0x03 Variable framerate bits 4-11
0x04 Var framerate bits 0-3, one must leave the 4 msb's at 0 !!
The variable framerate control must never be set lower then 300,
which sets the framerate at 90 / reg02, otherwise vsync is lost.
0x05 Shutter Time Line Offset, this can be used as an exposure control:
0 = use full frame time, 255 = no exposure at all
Note this may never be larger then "var-framerate control" / 2 - 2.
When var-framerate control is < 514, no exposure is reached at the max
allowed value for the framerate control value, rather then at 255.
0x06 Shutter Time Pixel Offset, like reg05 this influences exposure, but
only a very little bit, leave at 0xcd
0x07 offset sign bit (bit0 1 > negative offset)
0x08 offset
0x09 Blue Gain
0x0a Green1 Gain
0x0b Green2 Gain
0x0c Red Gain
0x0e Global gain
0x13 Write 1 to commit settings to sensor
*/
static const __u8 pas106_sensor_init[][8] = {
/* Pixel Clock Divider 6 */
{ 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),
SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60),
SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3,
F_GAIN, 0, 0x21),
SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_SIF, NO_EXPO|NO_FREQ,
SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_GAIN|F_SIF, NO_FREQ,
0),
SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, F_GAIN,
NO_FREQ, 0),
@ -628,26 +652,19 @@ static void setbrightness(struct gspca_dev *gspca_dev)
goto err;
break;
}
case SENSOR_PAS106: {
__u8 i2c1[] =
{0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
i2c1[3] = sd->brightness >> 3;
i2c1[2] = 0x0e;
if (i2c_w(gspca_dev, i2c1) < 0)
goto err;
i2c1[3] = 0x01;
i2c1[2] = 0x13;
if (i2c_w(gspca_dev, i2c1) < 0)
goto err;
break;
}
case SENSOR_PAS106:
case SENSOR_PAS202: {
__u8 i2cpbright[] =
{0xb0, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x16};
const __u8 i2cpdoit[] =
__u8 i2cpdoit[] =
{0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
/* PAS106 uses reg 7 and 8 instead of b and c */
if (sd->sensor == SENSOR_PAS106) {
i2cpbright[2] = 7;
i2cpdoit[2] = 0x13;
}
if (sd->brightness < 127) {
/* change reg 0x0b, signreg */
i2cpbright[3] = 0x01;
@ -709,18 +726,28 @@ static void setsensorgain(struct gspca_dev *gspca_dev)
goto err;
break;
}
case SENSOR_PAS106:
case SENSOR_PAS202: {
__u8 i2cpgain[] =
{0xa0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x63, 0x15};
{0xa0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x15};
__u8 i2cpcolorgain[] =
{0xc0, 0x40, 0x07, 0x00, 0x00, 0x00, 0x00, 0x15};
const __u8 i2cpdoit[] =
{0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x63, 0x16};
__u8 i2cpdoit[] =
{0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
/* PAS106 uses different regs (and has split green gains) */
if (sd->sensor == SENSOR_PAS106) {
i2cpgain[2] = 0x0e;
i2cpcolorgain[0] = 0xd0;
i2cpcolorgain[2] = 0x09;
i2cpdoit[2] = 0x13;
}
i2cpgain[3] = sd->gain >> 3;
i2cpcolorgain[3] = sd->gain >> 4;
i2cpcolorgain[4] = sd->gain >> 4;
i2cpcolorgain[5] = sd->gain >> 4;
i2cpcolorgain[6] = sd->gain >> 4;
if (i2c_w(gspca_dev, i2cpgain) < 0)
goto err;
@ -883,6 +910,38 @@ static void setexposure(struct gspca_dev *gspca_dev)
goto err;
break;
}
case SENSOR_PAS106: {
__u8 i2cpframerate[] =
{0xb1, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x14};
__u8 i2cpexpo[] =
{0xa1, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x14};
const __u8 i2cpdoit[] =
{0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14};
int framerate_ctrl;
/* For values below 150 use partial frame exposure, above
that use framerate ctrl */
if (sd->exposure < 150) {
i2cpexpo[3] = 150 - sd->exposure;
framerate_ctrl = 300;
} else {
/* The PAS106's exposure control goes from 0 - 4095,
but anything below 300 causes vsync issues, so scale
our 150-1023 to 300-4095 */
framerate_ctrl = (sd->exposure - 150) * 1000 / 230 +
300;
}
i2cpframerate[3] = framerate_ctrl >> 4;
i2cpframerate[4] = framerate_ctrl & 0x0f;
if (i2c_w(gspca_dev, i2cpframerate) < 0)
goto err;
if (i2c_w(gspca_dev, i2cpexpo) < 0)
goto err;
if (i2c_w(gspca_dev, i2cpdoit) < 0)
goto err;
break;
}
}
return;
err: