V4L/DVB (9843): gspca: Change the colors and add the red and blue controls in sonixj.
authorJean-Francois Moine <moinejf@free.fr>
Wed, 26 Nov 2008 07:46:15 +0000 (04:46 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 30 Dec 2008 11:38:48 +0000 (09:38 -0200)
The colors control (saturation) acted as color balance.

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

index 83564e0..5049769 100644 (file)
@@ -41,6 +41,8 @@ struct sd {
        unsigned char contrast;
        unsigned char colors;
        unsigned char autogain;
+       __u8 blue;
+       __u8 red;
        __u8 vflip;                     /* ov7630 only */
        __u8 infrared;                  /* mi0360 only */
 
@@ -72,6 +74,10 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getred_balance(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_setvflip(struct gspca_dev *gspca_dev, __s32 val);
@@ -116,7 +122,7 @@ static struct ctrl sd_ctrls[] = {
                .type    = V4L2_CTRL_TYPE_INTEGER,
                .name    = "Color",
                .minimum = 0,
-               .maximum = 64,
+               .maximum = 40,
                .step    = 1,
 #define COLOR_DEF 32
                .default_value = COLOR_DEF,
@@ -124,7 +130,35 @@ static struct ctrl sd_ctrls[] = {
            .set = sd_setcolors,
            .get = sd_getcolors,
        },
-#define AUTOGAIN_IDX 3
+       {
+           {
+               .id      = V4L2_CID_BLUE_BALANCE,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Blue Balance",
+               .minimum = 24,
+               .maximum = 40,
+               .step    = 1,
+#define BLUE_BALANCE_DEF 32
+               .default_value = BLUE_BALANCE_DEF,
+           },
+           .set = sd_setblue_balance,
+           .get = sd_getblue_balance,
+       },
+       {
+           {
+               .id      = V4L2_CID_RED_BALANCE,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Red Balance",
+               .minimum = 24,
+               .maximum = 40,
+               .step    = 1,
+#define RED_BALANCE_DEF 32
+               .default_value = RED_BALANCE_DEF,
+           },
+           .set = sd_setred_balance,
+           .get = sd_getred_balance,
+       },
+#define AUTOGAIN_IDX 5
        {
            {
                .id      = V4L2_CID_AUTOGAIN,
@@ -140,7 +174,7 @@ static struct ctrl sd_ctrls[] = {
            .get = sd_getautogain,
        },
 /* ov7630 only */
-#define VFLIP_IDX 4
+#define VFLIP_IDX 6
        {
            {
                .id      = V4L2_CID_VFLIP,
@@ -156,7 +190,7 @@ static struct ctrl sd_ctrls[] = {
            .get = sd_getvflip,
        },
 /* mi0360 only */
-#define INFRARED_IDX 5
+#define INFRARED_IDX 7
        {
            {
                .id      = V4L2_CID_INFRARED,
@@ -981,6 +1015,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
        sd->brightness = BRIGHTNESS_DEF;
        sd->contrast = CONTRAST_DEF;
        sd->colors = COLOR_DEF;
+       sd->blue = BLUE_BALANCE_DEF;
+       sd->red = RED_BALANCE_DEF;
        sd->autogain = AUTOGAIN_DEF;
        sd->ag_cnt = -1;
        sd->vflip = VFLIP_DEF;
@@ -1170,18 +1206,27 @@ static void setcontrast(struct gspca_dev *gspca_dev)
 static void setcolors(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
-       __u8 blue, red;
-
-       if (sd->colors >= 32) {
-               red = 32 + (sd->colors - 32) / 2;
-               blue = 64 - sd->colors;
-       } else {
-               red = sd->colors;
-               blue = 32 + (32 - sd->colors) / 2;
+       int i, v;
+       __u8 rega0[12];                 /* U & V gains */
+       static __s16 uv[6] = {          /* same as reg84 in signed decimal */
+               -24, -38, 64,           /* UR UG UB */
+                62, -51, -9            /* VR VG VB */
+       };
+       for (i = 0; i < 6; i++) {
+               v = uv[i] * sd->colors / COLOR_DEF;
+               rega0[i * 2] = v;
+               rega0[i * 2 + 1] = (v >> 8) & 0x0f;
        }
-       reg_w1(gspca_dev, 0x05, red);
+       reg_w(gspca_dev, 0x84, rega0, sizeof rega0);
+}
+
+static void setredblue(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       reg_w1(gspca_dev, 0x05, sd->red);
 /*     reg_w1(gspca_dev, 0x07, 32); */
-       reg_w1(gspca_dev, 0x06, blue);
+       reg_w1(gspca_dev, 0x06, sd->blue);
 }
 
 static void setautogain(struct gspca_dev *gspca_dev)
@@ -1259,9 +1304,9 @@ static int sd_start(struct gspca_dev *gspca_dev)
        }
        reg_w1(gspca_dev, 0x17, reg17);
 /* set reg1 was here */
-       reg_w1(gspca_dev, 0x05, sn9c1xx[5]);
-       reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
-       reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
+       reg_w1(gspca_dev, 0x05, sn9c1xx[5]);    /* red */
+       reg_w1(gspca_dev, 0x07, sn9c1xx[7]);    /* green */
+       reg_w1(gspca_dev, 0x06, sn9c1xx[6]);    /* blue */
        reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
        reg_w(gspca_dev, 0x20, gamma_def, sizeof gamma_def);
        for (i = 0; i < 8; i++)
@@ -1462,7 +1507,7 @@ static void do_autogain(struct gspca_dev *gspca_dev)
                                expotimes = 0;
                        sd->exposure = setexposure(gspca_dev,
                                                   (unsigned int) expotimes);
-                       setcolors(gspca_dev);
+                       setredblue(gspca_dev);
                        break;
                }
        }
@@ -1565,6 +1610,42 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
        return 0;
 }
 
+static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->blue = val;
+       if (gspca_dev->streaming)
+               setredblue(gspca_dev);
+       return 0;
+}
+
+static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       *val = sd->blue;
+       return 0;
+}
+
+static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->red = val;
+       if (gspca_dev->streaming)
+               setredblue(gspca_dev);
+       return 0;
+}
+
+static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       *val = sd->red;
+       return 0;
+}
+
 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
 {
        struct sd *sd = (struct sd *) gspca_dev;