summaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorJean-François Moine <moinejf@free.fr>2011-03-13 16:36:49 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-03-22 04:54:49 -0300
commit58c92d37e7d34433cfbc3989bec20e48fba0799e (patch)
tree4caccbda16d5f5dcceeb5a924c64f1359ad07650 /drivers/media/video
parent7d47b789ceb456d90a3ace522dbcb2a94d2693ca (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/media/video')
-rw-r--r--drivers/media/video/gspca/ov519.c120
1 files changed, 106 insertions, 14 deletions
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
index 42670ec7ef3..fd1b6082c96 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