[media] gspca - zc3xx: Add exposure control for sensor hv7131r
authorJean-François Moine <moinejf@free.fr>
Tue, 22 Mar 2011 09:47:56 +0000 (06:47 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 22 Mar 2011 19:38:27 +0000 (16:38 -0300)
Signed-off-by: Jean-François Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/gspca/zc3xx.c

index 6dcb1cf11b5cf3b644f100f8bc325c769cc14832..fa164e861cde9b1107cd829db39666f4e2b21b9d 100644 (file)
@@ -39,6 +39,7 @@ static int force_sensor = -1;
 enum e_ctrl {
        BRIGHTNESS,
        CONTRAST,
+       EXPOSURE,
        GAMMA,
        AUTOGAIN,
        LIGHTFREQ,
@@ -46,6 +47,8 @@ enum e_ctrl {
        NCTRLS          /* number of controls */
 };
 
+#define AUTOGAIN_DEF 1
+
 /* specific webcam descriptor */
 struct sd {
        struct gspca_dev gspca_dev;     /* !! must be the first item */
@@ -92,7 +95,8 @@ enum sensors {
 
 /* V4L2 controls supported by the driver */
 static void setcontrast(struct gspca_dev *gspca_dev);
-static void setautogain(struct gspca_dev *gspca_dev);
+static void setexposure(struct gspca_dev *gspca_dev);
+static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
 static void setlightfreq(struct gspca_dev *gspca_dev);
 static void setsharpness(struct gspca_dev *gspca_dev);
 
@@ -121,6 +125,18 @@ static const struct ctrl sd_ctrls[NCTRLS] = {
            },
            .set_control = setcontrast
        },
+[EXPOSURE] = {
+           {
+               .id      = V4L2_CID_EXPOSURE,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Exposure",
+               .minimum = 0x30d,
+               .maximum        = 0x493e,
+               .step           = 1,
+               .default_value  = 0x927
+           },
+           .set_control = setexposure
+       },
 [GAMMA] = {
            {
                .id      = V4L2_CID_GAMMA,
@@ -141,9 +157,10 @@ static const struct ctrl sd_ctrls[NCTRLS] = {
                .minimum = 0,
                .maximum = 1,
                .step    = 1,
-               .default_value = 1,
+               .default_value = AUTOGAIN_DEF,
+               .flags   = V4L2_CTRL_FLAG_UPDATE
            },
-           .set_control = setautogain
+           .set = sd_setautogain
        },
 [LIGHTFREQ] = {
            {
@@ -5926,6 +5943,26 @@ static void setcontrast(struct gspca_dev *gspca_dev)
                reg_w(gspca_dev, gr[i], 0x0130 + i);    /* gradient */
 }
 
+static void getexposure(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->ctrls[EXPOSURE].val = (i2c_read(gspca_dev, 0x25) << 9)
+               | (i2c_read(gspca_dev, 0x26) << 1)
+               | (i2c_read(gspca_dev, 0x27) >> 7);
+}
+
+static void setexposure(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int val;
+
+       val = sd->ctrls[EXPOSURE].val;
+       i2c_write(gspca_dev, 0x25, val >> 9, 0x00);
+       i2c_write(gspca_dev, 0x26, val >> 1, 0x00);
+       i2c_write(gspca_dev, 0x27, val << 7, 0x00);
+}
+
 static void setquality(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
@@ -6623,10 +6660,19 @@ static int sd_init(struct gspca_dev *gspca_dev)
        sd->ctrls[GAMMA].def = gamma[sd->sensor];
 
        switch (sd->sensor) {
+       case SENSOR_HV7131R:
+               break;
        case SENSOR_OV7630C:
-               gspca_dev->ctrl_dis = (1 << LIGHTFREQ);
+               gspca_dev->ctrl_dis = (1 << LIGHTFREQ) | (1 << EXPOSURE);
+               break;
+       default:
+               gspca_dev->ctrl_dis = (1 << EXPOSURE);
                break;
        }
+#if AUTOGAIN_DEF
+       if (sd->ctrls[AUTOGAIN].val)
+               gspca_dev->ctrl_inac = (1 << EXPOSURE);
+#endif
 
        /* switch off the led */
        reg_w(gspca_dev, 0x01, 0x0000);
@@ -6772,9 +6818,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
                reg_w(gspca_dev, 0x40, 0x0117);
                break;
        case SENSOR_HV7131R:
-               i2c_write(gspca_dev, 0x25, 0x04, 0x00); /* exposure */
-               i2c_write(gspca_dev, 0x26, 0x93, 0x00);
-               i2c_write(gspca_dev, 0x27, 0xe0, 0x00);
+               if (!sd->ctrls[AUTOGAIN].val)
+                       setexposure(gspca_dev);
                reg_w(gspca_dev, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN);
                break;
        case SENSOR_GC0305:
@@ -6852,6 +6897,23 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
        gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
 }
 
+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);
+               if (gspca_dev->streaming)
+                       getexposure(gspca_dev);
+       }
+       if (gspca_dev->streaming)
+               setautogain(gspca_dev);
+       return gspca_dev->usb_err;
+}
+
 static int sd_querymenu(struct gspca_dev *gspca_dev,
                        struct v4l2_querymenu *menu)
 {