[media] gspca - ov519: Add exposure and autogain controls for ov2610/2610ae
authorJean-François Moine <moinejf@free.fr>
Sun, 13 Mar 2011 19:36:49 +0000 (16:36 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 22 Mar 2011 07:54:49 +0000 (04:54 -0300)
Signed-off-by: Jean-François Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/gspca/ov519.c

index 42670ec7ef3b1d46c9c8006071493fee4724201d..fd1b6082c96daec8b4312ac67106bac4ad7b13ac 100644 (file)
@@ -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