diff options
author | Jean-François Moine | 2011-03-13 16:36:49 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab | 2011-03-22 04:54:49 -0300 |
commit | 58c92d37e7d34433cfbc3989bec20e48fba0799e (patch) | |
tree | 4caccbda16d5f5dcceeb5a924c64f1359ad07650 /drivers | |
parent | 7d47b789ceb456d90a3ace522dbcb2a94d2693ca (diff) |
[media] gspca - ov519: Add exposure and autogain controls for ov2610/2610ae
Signed-off-by: Jean-François Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/video/gspca/ov519.c | 120 |
1 files changed, 106 insertions, 14 deletions
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 42670ec7ef3b..fd1b6082c96d 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -1,7 +1,7 @@ /** * OV519 driver * - * Copyright (C) 2008 Jean-Francois Moine (http://moinejf.free.fr) + * Copyright (C) 2008-2011 Jean-François Moine <moinejf@free.fr> * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com> * * This module is adapted from the ov51x-jpeg package, which itself @@ -61,10 +61,12 @@ static int i2c_detect_tries = 10; enum e_ctrl { BRIGHTNESS, CONTRAST, + EXPOSURE, COLORS, HFLIP, VFLIP, AUTOBRIGHT, + AUTOGAIN, FREQ, NCTRL /* number of controls */ }; @@ -142,9 +144,11 @@ enum sensors { /* V4L2 controls supported by the driver */ static void setbrightness(struct gspca_dev *gspca_dev); static void setcontrast(struct gspca_dev *gspca_dev); +static void setexposure(struct gspca_dev *gspca_dev); static void setcolors(struct gspca_dev *gspca_dev); static void sethvflip(struct gspca_dev *gspca_dev); static void setautobright(struct gspca_dev *gspca_dev); +static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); static void setfreq(struct gspca_dev *gspca_dev); static void setfreq_i(struct sd *sd); @@ -173,6 +177,18 @@ static const struct ctrl sd_ctrls[] = { }, .set_control = setcontrast, }, +[EXPOSURE] = { + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Exposure", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = 127, + }, + .set_control = setexposure, + }, [COLORS] = { { .id = V4L2_CID_SATURATION, @@ -222,6 +238,19 @@ static const struct ctrl sd_ctrls[] = { }, .set_control = setautobright, }, +[AUTOGAIN] = { + { + .id = V4L2_CID_AUTOGAIN, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Auto Gain", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + .flags = V4L2_CTRL_FLAG_UPDATE + }, + .set = sd_setautogain, + }, [FREQ] = { { .id = V4L2_CID_POWER_LINE_FREQUENCY, @@ -238,50 +267,78 @@ static const struct ctrl sd_ctrls[] = { /* table of the disabled controls */ static const unsigned ctrl_dis[] = { -[SEN_OV2610] = (1 << NCTRL) - 1, /* no control */ +[SEN_OV2610] = ((1 << NCTRL) - 1) /* no control */ + ^ ((1 << EXPOSURE) /* but exposure */ + | (1 << AUTOGAIN)), /* and autogain */ -[SEN_OV2610AE] = (1 << NCTRL) - 1, /* no control */ +[SEN_OV2610AE] = ((1 << NCTRL) - 1) /* no control */ + ^ ((1 << EXPOSURE) /* but exposure */ + | (1 << AUTOGAIN)), /* and autogain */ [SEN_OV3610] = (1 << NCTRL) - 1, /* no control */ [SEN_OV6620] = (1 << HFLIP) | - (1 << VFLIP), + (1 << VFLIP) | + (1 << EXPOSURE) | + (1 << AUTOGAIN), [SEN_OV6630] = (1 << HFLIP) | - (1 << VFLIP), + (1 << VFLIP) | + (1 << EXPOSURE) | + (1 << AUTOGAIN), [SEN_OV66308AF] = (1 << HFLIP) | - (1 << VFLIP), + (1 << VFLIP) | + (1 << EXPOSURE) | + (1 << AUTOGAIN), [SEN_OV7610] = (1 << HFLIP) | - (1 << VFLIP), + (1 << VFLIP) | + (1 << EXPOSURE) | + (1 << AUTOGAIN), [SEN_OV7620] = (1 << HFLIP) | - (1 << VFLIP), + (1 << VFLIP) | + (1 << EXPOSURE) | + (1 << AUTOGAIN), [SEN_OV7620AE] = (1 << HFLIP) | - (1 << VFLIP), + (1 << VFLIP) | + (1 << EXPOSURE) | + (1 << AUTOGAIN), [SEN_OV7640] = (1 << HFLIP) | (1 << VFLIP) | (1 << AUTOBRIGHT) | - (1 << CONTRAST), + (1 << CONTRAST) | + (1 << EXPOSURE) | + (1 << AUTOGAIN), [SEN_OV7648] = (1 << HFLIP) | (1 << VFLIP) | (1 << AUTOBRIGHT) | - (1 << CONTRAST), + (1 << CONTRAST) | + (1 << EXPOSURE) | + (1 << AUTOGAIN), -[SEN_OV7660] = (1 << AUTOBRIGHT), +[SEN_OV7660] = (1 << AUTOBRIGHT) | + (1 << EXPOSURE) | + (1 << AUTOGAIN), [SEN_OV7670] = (1 << COLORS) | - (1 << AUTOBRIGHT), + (1 << AUTOBRIGHT) | + (1 << EXPOSURE) | + (1 << AUTOGAIN), [SEN_OV76BE] = (1 << HFLIP) | - (1 << VFLIP), + (1 << VFLIP) | + (1 << EXPOSURE) | + (1 << AUTOGAIN), [SEN_OV8610] = (1 << HFLIP) | (1 << VFLIP) | + (1 << EXPOSURE) | + (1 << AUTOGAIN) | (1 << FREQ), }; @@ -3201,6 +3258,13 @@ static void ov519_set_fr(struct sd *sd) ov518_i2c_w(sd, OV7670_R11_CLKRC, clock); } +static void setautogain(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + i2c_w_mask(sd, 0x13, sd->ctrls[AUTOGAIN].val ? 0x05 : 0x00, 0x05); +} + /* this function is called at probe time */ static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) @@ -4189,12 +4253,16 @@ static int sd_start(struct gspca_dev *gspca_dev) setcontrast(gspca_dev); if (!(sd->gspca_dev.ctrl_dis & (1 << BRIGHTNESS))) setbrightness(gspca_dev); + if (!(sd->gspca_dev.ctrl_dis & (1 << EXPOSURE))) + setexposure(gspca_dev); if (!(sd->gspca_dev.ctrl_dis & (1 << COLORS))) setcolors(gspca_dev); if (!(sd->gspca_dev.ctrl_dis & ((1 << HFLIP) | (1 << VFLIP)))) sethvflip(gspca_dev); if (!(sd->gspca_dev.ctrl_dis & (1 << AUTOBRIGHT))) setautobright(gspca_dev); + if (!(sd->gspca_dev.ctrl_dis & (1 << AUTOGAIN))) + setautogain(gspca_dev); if (!(sd->gspca_dev.ctrl_dis & (1 << FREQ))) setfreq_i(sd); @@ -4608,6 +4676,14 @@ static void setcontrast(struct gspca_dev *gspca_dev) } } +static void setexposure(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *) gspca_dev; + + if (!sd->ctrls[AUTOGAIN].val) + i2c_w(sd, 0x10, sd->ctrls[EXPOSURE].val); +} + static void setcolors(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; @@ -4666,6 +4742,22 @@ static void setautobright(struct gspca_dev *gspca_dev) i2c_w_mask(sd, 0x2d, sd->ctrls[AUTOBRIGHT].val ? 0x10 : 0x00, 0x10); } +static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) +{ + struct sd *sd = (struct sd *) gspca_dev; + + sd->ctrls[AUTOGAIN].val = val; + if (val) { + gspca_dev->ctrl_inac |= (1 << EXPOSURE); + } else { + gspca_dev->ctrl_inac &= ~(1 << EXPOSURE); + sd->ctrls[EXPOSURE].val = i2c_r(sd, 0x10); + } + if (gspca_dev->streaming) + setautogain(gspca_dev); + return gspca_dev->usb_err; +} + static void setfreq_i(struct sd *sd) { if (sd->sensor == SEN_OV7660 |