V4L/DVB (11693): gspca - stv06xx-vv6410: Add exposure ctrl
Add the possibility to control the exposure on the vv6410 sensor Signed-off-by: Erik Andrén <erik.andren@gmail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Родитель
1b844b5367
Коммит
1906d8d17e
|
@ -84,8 +84,22 @@ static const struct ctrl vv6410_ctrl[] = {
|
||||||
},
|
},
|
||||||
.set = vv6410_set_analog_gain,
|
.set = vv6410_set_analog_gain,
|
||||||
.get = vv6410_get_analog_gain
|
.get = vv6410_get_analog_gain
|
||||||
|
},
|
||||||
|
#define EXPOSURE_IDX 3
|
||||||
|
{
|
||||||
|
{
|
||||||
|
.id = V4L2_CID_EXPOSURE,
|
||||||
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||||
|
.name = "exposure",
|
||||||
|
.minimum = 0,
|
||||||
|
.maximum = 32768,
|
||||||
|
.step = 1,
|
||||||
|
.default_value = 20000
|
||||||
|
},
|
||||||
|
.set = vv6410_set_exposure,
|
||||||
|
.get = vv6410_get_exposure
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static int vv6410_probe(struct sd *sd)
|
static int vv6410_probe(struct sd *sd)
|
||||||
{
|
{
|
||||||
|
@ -121,6 +135,7 @@ static int vv6410_probe(struct sd *sd)
|
||||||
static int vv6410_init(struct sd *sd)
|
static int vv6410_init(struct sd *sd)
|
||||||
{
|
{
|
||||||
int err = 0, i;
|
int err = 0, i;
|
||||||
|
s32 *sensor_settings = sd->sensor_priv;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(stv_bridge_init); i++) {
|
for (i = 0; i < ARRAY_SIZE(stv_bridge_init); i++) {
|
||||||
/* if NULL then len contains single value */
|
/* if NULL then len contains single value */
|
||||||
|
@ -142,6 +157,11 @@ static int vv6410_init(struct sd *sd)
|
||||||
|
|
||||||
err = stv06xx_write_sensor_bytes(sd, (u8 *) vv6410_sensor_init,
|
err = stv06xx_write_sensor_bytes(sd, (u8 *) vv6410_sensor_init,
|
||||||
ARRAY_SIZE(vv6410_sensor_init));
|
ARRAY_SIZE(vv6410_sensor_init));
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = vv6410_set_exposure(&sd->gspca_dev,
|
||||||
|
sensor_settings[EXPOSURE_IDX]);
|
||||||
|
|
||||||
return (err < 0) ? err : 0;
|
return (err < 0) ? err : 0;
|
||||||
}
|
}
|
||||||
|
@ -318,3 +338,50 @@ static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val)
|
||||||
|
|
||||||
return (err < 0) ? err : 0;
|
return (err < 0) ? err : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int vv6410_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
|
||||||
|
{
|
||||||
|
struct sd *sd = (struct sd *) gspca_dev;
|
||||||
|
s32 *sensor_settings = sd->sensor_priv;
|
||||||
|
|
||||||
|
*val = sensor_settings[EXPOSURE_IDX];
|
||||||
|
|
||||||
|
PDEBUG(D_V4L2, "Read exposure %d", *val);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
struct sd *sd = (struct sd *) gspca_dev;
|
||||||
|
s32 *sensor_settings = sd->sensor_priv;
|
||||||
|
unsigned int fine, coarse;
|
||||||
|
|
||||||
|
sensor_settings[EXPOSURE_IDX] = val;
|
||||||
|
|
||||||
|
val = (val * val >> 14) + val / 4;
|
||||||
|
|
||||||
|
fine = val % VV6410_CIF_LINELENGTH;
|
||||||
|
coarse = min(512, val / VV6410_CIF_LINELENGTH);
|
||||||
|
|
||||||
|
PDEBUG(D_V4L2, "Set coarse exposure to %d, fine expsure to %d",
|
||||||
|
coarse, fine);
|
||||||
|
|
||||||
|
err = stv06xx_write_sensor(sd, VV6410_FINEH, fine >> 8);
|
||||||
|
if (err < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
err = stv06xx_write_sensor(sd, VV6410_FINEL, fine & 0xff);
|
||||||
|
if (err < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
err = stv06xx_write_sensor(sd, VV6410_COARSEH, coarse >> 8);
|
||||||
|
if (err < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
err = stv06xx_write_sensor(sd, VV6410_COARSEL, coarse & 0xff);
|
||||||
|
|
||||||
|
out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
|
@ -173,6 +173,8 @@
|
||||||
#define VV6410_SUBSAMPLE 0x01
|
#define VV6410_SUBSAMPLE 0x01
|
||||||
#define VV6410_CROP_TO_QVGA 0x02
|
#define VV6410_CROP_TO_QVGA 0x02
|
||||||
|
|
||||||
|
#define VV6410_CIF_LINELENGTH 415
|
||||||
|
|
||||||
static int vv6410_probe(struct sd *sd);
|
static int vv6410_probe(struct sd *sd);
|
||||||
static int vv6410_start(struct sd *sd);
|
static int vv6410_start(struct sd *sd);
|
||||||
static int vv6410_init(struct sd *sd);
|
static int vv6410_init(struct sd *sd);
|
||||||
|
@ -187,6 +189,8 @@ static int vv6410_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
|
||||||
static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
|
static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
|
||||||
static int vv6410_get_analog_gain(struct gspca_dev *gspca_dev, __s32 *val);
|
static int vv6410_get_analog_gain(struct gspca_dev *gspca_dev, __s32 *val);
|
||||||
static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val);
|
static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val);
|
||||||
|
static int vv6410_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
|
||||||
|
static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
|
||||||
|
|
||||||
const struct stv06xx_sensor stv06xx_sensor_vv6410 = {
|
const struct stv06xx_sensor stv06xx_sensor_vv6410 = {
|
||||||
.name = "ST VV6410",
|
.name = "ST VV6410",
|
||||||
|
|
Загрузка…
Ссылка в новой задаче