From 58c92d37e7d34433cfbc3989bec20e48fba0799e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jean-Fran=C3=A7ois=20Moine?= Date: Sun, 13 Mar 2011 16:36:49 -0300 Subject: [PATCH] [media] gspca - ov519: Add exposure and autogain controls for ov2610/2610ae MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jean-François Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov519.c | 120 +++++++++++++++++++++++++++++++++----- 1 file changed, 106 insertions(+), 14 deletions(-) diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 42670ec..fd1b608 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 * Copyright (C) 2009 Hans de Goede * * 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 -- 2.7.4