V4L/DVB: gspca - vc032x: Add more controls for poxxxx
authorJean-François Moine <moinejf@free.fr>
Mon, 26 Jul 2010 10:53:57 +0000 (07:53 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 9 Aug 2010 02:42:53 +0000 (23:42 -0300)
The added controls are exposure, gain, autogain and backlight compensation.

Signed-off-by: Jean-François Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/gspca/vc032x.c

index 031266a..d450a95 100644 (file)
@@ -39,6 +39,10 @@ struct sd {
        u8 vflip;
        u8 lightfreq;
        s8 sharpness;
+       u16 exposure;
+       u8 gain;
+       u8 autogain;
+       u8 backlight;
 
        u8 image_offset;
 
@@ -77,6 +81,14 @@ static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
 static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
 static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setbacklight(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getbacklight(struct gspca_dev *gspca_dev, __s32 *val);
 
 static const struct ctrl sd_ctrls[] = {
 #define BRIGHTNESS_IDX 0
@@ -185,6 +197,66 @@ static const struct ctrl sd_ctrls[] = {
         .set = sd_setsharpness,
         .get = sd_getsharpness,
         },
+#define GAIN_IDX 7
+       {
+           {
+               .id      = V4L2_CID_GAIN,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Gain",
+               .minimum = 0,
+               .maximum = 78,
+               .step    = 1,
+#define GAIN_DEF 0
+               .default_value = GAIN_DEF,
+           },
+           .set = sd_setgain,
+           .get = sd_getgain,
+       },
+#define EXPOSURE_IDX 8
+       {
+               {
+                       .id = V4L2_CID_EXPOSURE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "Exposure",
+#define EXPOSURE_DEF 450
+                       .minimum = 0,
+                       .maximum = 4095,
+                       .step = 1,
+                       .default_value = EXPOSURE_DEF,
+               },
+               .set = sd_setexposure,
+               .get = sd_getexposure,
+       },
+#define AUTOGAIN_IDX 9
+       {
+               {
+                       .id = V4L2_CID_AUTOGAIN,
+                       .type = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name = "Automatic Gain and Exposure",
+                       .minimum = 0,
+                       .maximum = 1,
+                       .step = 1,
+#define AUTOGAIN_DEF 1
+                       .default_value = AUTOGAIN_DEF,
+               },
+               .set = sd_setautogain,
+               .get = sd_getautogain,
+       },
+#define BACKLIGHT_IDX 10
+       {
+               {
+                       .id = V4L2_CID_BACKLIGHT_COMPENSATION,
+                       .type = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name = "Backlight Compensation",
+                       .minimum = 0,
+                       .maximum = 15,
+                       .step = 1,
+#define BACKLIGHT_DEF 15
+                       .default_value = BACKLIGHT_DEF,
+               },
+               .set = sd_setbacklight,
+               .get = sd_getbacklight,
+       },
 };
 
 /* table of the disabled controls */
@@ -192,33 +264,51 @@ static u32 ctrl_dis[] = {
 /* SENSOR_HV7131R 0 */
        (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
                | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX)
-               | (1 << SHARPNESS_IDX),
+               | (1 << SHARPNESS_IDX)
+               | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
+               | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
 /* SENSOR_MI0360 1 */
        (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
                | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX)
-               | (1 << SHARPNESS_IDX),
+               | (1 << SHARPNESS_IDX)
+               | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
+               | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
 /* SENSOR_MI1310_SOC 2 */
        (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
-               | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX),
+               | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX)
+               | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
+               | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
 /* SENSOR_MI1320 3 */
        (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
-               | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX),
+               | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX)
+               | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
+               | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
 /* SENSOR_MI1320_SOC 4 */
        (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
-               | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX),
+               | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX)
+               | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
+               | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
 /* SENSOR_OV7660 5 */
        (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
-               | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX),
+               | (1 << LIGHTFREQ_IDX) | (1 << SHARPNESS_IDX)
+               | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
+               | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
 /* SENSOR_OV7670 6 */
        (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
-               | (1 << SHARPNESS_IDX),
+               | (1 << SHARPNESS_IDX)
+               | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
+               | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
 /* SENSOR_PO1200 7 */
        (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
-               | (1 << LIGHTFREQ_IDX),
+               | (1 << LIGHTFREQ_IDX)
+               | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
+               | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
 /* SENSOR_PO3130NC 8 */
        (1 << BRIGHTNESS_IDX) | (1 << CONTRAST_IDX) | (1 << COLORS_IDX)
                | (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX)
-               | (1 << SHARPNESS_IDX),
+               | (1 << SHARPNESS_IDX)
+               | (1 << GAIN_IDX) | (1 << EXPOSURE_IDX)
+               | (1 << AUTOGAIN_IDX) | (1 << BACKLIGHT_IDX),
 /* SENSOR_POxxxx 9 */
        (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << LIGHTFREQ_IDX),
 };
@@ -2825,7 +2915,9 @@ static const u8 poxxxx_init_common[][4] = {
        {0x00, 0x1e, 0xc6, 0xaa},
        {0x00, 0x00, 0x40, 0xdd},
        {0x00, 0x1d, 0x05, 0xaa},
-
+       {}
+};
+static const u8 poxxxx_gamma[][4] = {
        {0x00, 0xd6, 0x22, 0xaa},       /* gamma 0 */
        {0x00, 0x73, 0x00, 0xaa},
        {0x00, 0x74, 0x0a, 0xaa},
@@ -2867,19 +2959,9 @@ static const u8 poxxxx_init_common[][4] = {
        {0x00, 0x7c, 0xba, 0xaa},
        {0x00, 0x7d, 0xd4, 0xaa},
        {0x00, 0x7e, 0xea, 0xaa},
-
-       {0x00, 0xaa, 0xff, 0xaa},       /* back light comp */
-       {0x00, 0xc4, 0x03, 0xaa},
-       {0x00, 0xc5, 0x19, 0xaa},
-       {0x00, 0xc6, 0x03, 0xaa},
-       {0x00, 0xc7, 0x91, 0xaa},
-       {0x00, 0xc8, 0x01, 0xaa},
-       {0x00, 0xc9, 0xdd, 0xaa},
-       {0x00, 0xca, 0x02, 0xaa},
-       {0x00, 0xcb, 0x37, 0xaa},
-
-/* read d1 */
-       {0x00, 0xd1, 0x3c, 0xaa},
+       {}
+};
+static const u8 poxxxx_init_start_3[][4] = {
        {0x00, 0xb8, 0x28, 0xaa},
        {0x00, 0xb9, 0x1e, 0xaa},
        {0x00, 0xb6, 0x14, 0xaa},
@@ -2959,9 +3041,6 @@ static const u8 poxxxx_init_end_1[][4] = {
        {0x00, 0xb3, 0x08, 0xaa},
        {0x00, 0xb4, 0x0b, 0xaa},
        {0x00, 0xb5, 0x0d, 0xaa},
-       {0x00, 0x59, 0x7e, 0xaa},       /* sharpness */
-       {0x00, 0x16, 0x00, 0xaa},       /* white balance */
-       {0x00, 0x18, 0x00, 0xaa},
        {}
 };
 static const u8 poxxxx_init_end_2[][4] = {
@@ -3409,6 +3488,10 @@ static int sd_config(struct gspca_dev *gspca_dev,
        sd->vflip = VFLIP_DEF;
        sd->lightfreq = FREQ_DEF;
        sd->sharpness = SHARPNESS_DEF;
+       sd->gain = GAIN_DEF;
+       sd->exposure = EXPOSURE_DEF;
+       sd->autogain = AUTOGAIN_DEF;
+       sd->backlight = BACKLIGHT_DEF;
 
        gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];
 
@@ -3551,6 +3634,82 @@ static void setsharpness(struct gspca_dev *gspca_dev)
                break;
        }
 }
+static void setgain(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (gspca_dev->ctrl_dis & (1 << GAIN_IDX))
+               return;
+       i2c_write(gspca_dev, 0x15, &sd->gain, 1);
+}
+
+static void setexposure(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 data;
+
+       if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX))
+               return;
+       data = sd->exposure >> 8;
+       i2c_write(gspca_dev, 0x1a, &data, 1);
+       data = sd->exposure;
+       i2c_write(gspca_dev, 0x1b, &data, 1);
+}
+
+static void setautogain(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       static const u8 data[2] = {0x28, 0x3c};
+
+       if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
+               return;
+       i2c_write(gspca_dev, 0xd1, &data[sd->autogain], 1);
+}
+
+static void setgamma(struct gspca_dev *gspca_dev)
+{
+/*fixme:to do */
+       usb_exchange(gspca_dev, poxxxx_gamma);
+}
+
+static void setbacklight(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u16 v;
+       u8 data;
+
+       data = (sd->backlight << 4) | 0x0f;
+       i2c_write(gspca_dev, 0xaa, &data, 1);
+       v = 613 + 12 * sd->backlight;
+       data = v >> 8;
+       i2c_write(gspca_dev, 0xc4, &data, 1);
+       data = v;
+       i2c_write(gspca_dev, 0xc5, &data, 1);
+       v = 1093 - 12 * sd->backlight;
+       data = v >> 8;
+       i2c_write(gspca_dev, 0xc6, &data, 1);
+       data = v;
+       i2c_write(gspca_dev, 0xc7, &data, 1);
+       v = 342 + 9 * sd->backlight;
+       data = v >> 8;
+       i2c_write(gspca_dev, 0xc8, &data, 1);
+       data = v;
+       i2c_write(gspca_dev, 0xc9, &data, 1);
+       v = 702 - 9 * sd->backlight;
+       data = v >> 8;
+       i2c_write(gspca_dev, 0xca, &data, 1);
+       data = v;
+       i2c_write(gspca_dev, 0xcb, &data, 1);
+}
+
+static void setwb(struct gspca_dev *gspca_dev)
+{
+/*fixme:to do - valid when reg d1 = 0x1c - (reg16 + reg15 = 0xa3)*/
+       static const u8 data[2] = {0x00, 0x00};
+
+       i2c_write(gspca_dev, 0x16, &data[0], 1);
+       i2c_write(gspca_dev, 0x18, &data[1], 1);
+}
 
 static int sd_start(struct gspca_dev *gspca_dev)
 {
@@ -3662,6 +3821,16 @@ static int sd_start(struct gspca_dev *gspca_dev)
        default:
 /*     case SENSOR_POxxxx: */
                usb_exchange(gspca_dev, poxxxx_init_common);
+               setgamma(gspca_dev);
+               setbacklight(gspca_dev);
+               setbrightness(gspca_dev);
+               setcontrast(gspca_dev);
+               setcolors(gspca_dev);
+               setsharpness(gspca_dev);
+               setautogain(gspca_dev);
+               setexposure(gspca_dev);
+               setgain(gspca_dev);
+               usb_exchange(gspca_dev, poxxxx_init_start_3);
                if (mode)
                        init = poxxxx_initQVGA;
                else
@@ -3693,7 +3862,6 @@ static int sd_start(struct gspca_dev *gspca_dev)
                        break;
                }
                msleep(100);
-               setsharpness(gspca_dev);
                sethvflip(gspca_dev);
                setlightfreq(gspca_dev);
        }
@@ -3704,14 +3872,10 @@ static int sd_start(struct gspca_dev *gspca_dev)
                reg_w(gspca_dev, 0xa0, 0x0000, 0xbfff);
                break;
        case SENSOR_POxxxx:
-               setcolors(gspca_dev);
-               setbrightness(gspca_dev);
-               setcontrast(gspca_dev);
-
-               /* led on */
-               msleep(80);
-               reg_w(gspca_dev, 0x89, 0xffff, 0xfdff);
                usb_exchange(gspca_dev, poxxxx_init_end_2);
+               setwb(gspca_dev);
+               msleep(80);             /* led on */
+               reg_w(gspca_dev, 0x89, 0xffff, 0xfdff);
                break;
        }
        return gspca_dev->usb_err;
@@ -3911,6 +4075,80 @@ static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
        return 0;
 }
 
+static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->gain = val;
+       if (gspca_dev->streaming)
+               setgain(gspca_dev);
+       return gspca_dev->usb_err;
+}
+
+static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       *val = sd->gain;
+       return 0;
+}
+
+static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->exposure = val;
+       if (gspca_dev->streaming)
+               setexposure(gspca_dev);
+       return gspca_dev->usb_err;
+}
+
+static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       *val = sd->exposure;
+       return 0;
+}
+
+static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->autogain = val;
+       if (gspca_dev->streaming)
+               setautogain(gspca_dev);
+
+       return gspca_dev->usb_err;
+}
+
+static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       *val = sd->autogain;
+       return 0;
+}
+
+static int sd_setbacklight(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->backlight = val;
+       if (gspca_dev->streaming)
+               setbacklight(gspca_dev);
+
+       return gspca_dev->usb_err;
+}
+
+static int sd_getbacklight(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       *val = sd->backlight;
+       return 0;
+}
+
 static int sd_querymenu(struct gspca_dev *gspca_dev,
                        struct v4l2_querymenu *menu)
 {