]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/media/video/gspca/sonixj.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable
[linux-2.6-omap-h63xx.git] / drivers / media / video / gspca / sonixj.c
index 83564e09eeea3be19723bff60ce6e355f23b6f04..3373b8d9d2a88fa92c8ec40feb5d4d207d9b17ab 100644 (file)
@@ -37,24 +37,26 @@ struct sd {
        atomic_t avg_lum;
        unsigned int exposure;
 
-       unsigned short brightness;
-       unsigned char contrast;
-       unsigned char colors;
-       unsigned char autogain;
+       __u16 brightness;
+       __u8 contrast;
+       __u8 colors;
+       __u8 autogain;
+       __u8 blue;
+       __u8 red;
        __u8 vflip;                     /* ov7630 only */
        __u8 infrared;                  /* mi0360 only */
 
-       signed char ag_cnt;
+       __s8 ag_cnt;
 #define AG_CNT_START 13
 
-       char qindex;
-       unsigned char bridge;
+       __u8 qindex;
+       __u8 bridge;
 #define BRIDGE_SN9C102P 0
 #define BRIDGE_SN9C105 1
 #define BRIDGE_SN9C110 2
 #define BRIDGE_SN9C120 3
 #define BRIDGE_SN9C325 4
-       char sensor;                    /* Type of image sensor chip */
+       __u8 sensor;                    /* Type of image sensor chip */
 #define SENSOR_HV7131R 0
 #define SENSOR_MI0360 1
 #define SENSOR_MO4000 2
@@ -62,7 +64,7 @@ struct sd {
 #define SENSOR_OV7630 4
 #define SENSOR_OV7648 5
 #define SENSOR_OV7660 6
-       unsigned char i2c_base;
+       __u8 i2c_base;
 };
 
 /* V4L2 controls supported by the driver */
@@ -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,
@@ -173,7 +207,25 @@ static struct ctrl sd_ctrls[] = {
        },
 };
 
-static struct v4l2_pix_format vga_mode[] = {
+/* table of the disabled controls */
+static __u32 ctrl_dis[] = {
+       (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
+                                               /* SENSOR_HV7131R 0 */
+       (1 << VFLIP_IDX),
+                                               /* SENSOR_MI0360 1 */
+       (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
+                                               /* SENSOR_MO4000 2 */
+       (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
+                                               /* SENSOR_OM6802 3 */
+       (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX),
+                                               /* SENSOR_OV7630 4 */
+       (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
+                                               /* SENSOR_OV7648 5 */
+       (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
+                                               /* SENSOR_OV7660 6 */
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
        {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
                .bytesperline = 160,
                .sizeimage = 160 * 120 * 4 / 8 + 590,
@@ -767,8 +819,6 @@ static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
 
 static int probesensor(struct gspca_dev *gspca_dev)
 {
-       struct sd *sd = (struct sd *) gspca_dev;
-
        i2c_w1(gspca_dev, 0x02, 0);                     /* sensor wakeup */
        msleep(10);
        reg_w1(gspca_dev, 0x02, 0x66);                  /* Gpio on */
@@ -780,8 +830,7 @@ static int probesensor(struct gspca_dev *gspca_dev)
            && gspca_dev->usb_buf[3] == 0x00
            && gspca_dev->usb_buf[4] == 0x00) {
                PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
-               sd->sensor = SENSOR_HV7131R;
-               return SENSOR_HV7131R;
+               return 0;
        }
        PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
                gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
@@ -981,22 +1030,14 @@ 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;
        sd->infrared = INFRARED_DEF;
 
-       switch (sd->sensor) {
-       case SENSOR_OV7630:
-       case SENSOR_OV7648:
-       case SENSOR_OV7660:
-               gspca_dev->ctrl_dis = (1 << AUTOGAIN_IDX);
-               break;
-       }
-       if (sd->sensor != SENSOR_OV7630)
-               gspca_dev->ctrl_dis |= (1 << VFLIP_IDX);
-       if (sd->sensor != SENSOR_MI0360)
-               gspca_dev->ctrl_dis |= (1 << INFRARED_IDX);
+       gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];
        return 0;
 }
 
@@ -1004,7 +1045,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
 static int sd_init(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
-/*     const __u8 *sn9c1xx; */
        __u8 regGpio[] = { 0x29, 0x74 };
        __u8 regF1;
 
@@ -1158,30 +1198,42 @@ static void setcontrast(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        __u8 k2;
-       __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
+       __u8 contrast[6];
 
        k2 = sd->contrast * 0x30 / (CONTRAST_MAX + 1) + 0x10;   /* 10..40 */
        contrast[0] = (k2 + 1) / 2;             /* red */
+       contrast[1] = 0;
        contrast[2] = k2;                       /* green */
+       contrast[3] = 0;
        contrast[4] = (k2 + 1) / 5;             /* blue */
-       reg_w(gspca_dev, 0x84, contrast, 6);
+       contrast[5] = 0;
+       reg_w(gspca_dev, 0x84, contrast, sizeof contrast);
 }
 
 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 reg8a[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;
+               reg8a[i * 2] = v;
+               reg8a[i * 2 + 1] = (v >> 8) & 0x0f;
        }
-       reg_w1(gspca_dev, 0x05, red);
+       reg_w(gspca_dev, 0x8a, reg8a, sizeof reg8a);
+}
+
+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 +1311,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++)
@@ -1320,27 +1372,19 @@ static int sd_start(struct gspca_dev *gspca_dev)
                ov7648_InitSensor(gspca_dev);
                reg17 = 0x21;
 /*             reg1 = 0x42;             * 42 - 46? */
-/*             if (mode)
-                       ;                * 320x2...
-               else
-                       ;                * 640x... */
                break;
        default:
 /*     case SENSOR_OV7660: */
                ov7660_InitSensor(gspca_dev);
-               if (mode) {
-/*                     reg17 = 0x21;    * 320 */
-/*                     reg1 = 0x44; */
-/*                     reg1 = 0x46;    (done) */
-               } else {                        /* 640 */
-                       if (sd->bridge == BRIDGE_SN9C120) {
+               if (sd->bridge == BRIDGE_SN9C120) {
+                       if (mode) {             /* 320x240 - 160x120 */
                                reg17 = 0xa2;
                                reg1 = 0x44;    /* 48 Mhz, video trf eneble */
-                       } else {
-                               reg17 = 0x22;
-                               reg1 = 0x06;    /* 24 Mhz, video trf eneble
-                                                * inverse power down */
                        }
+               } else {
+                       reg17 = 0x22;
+                       reg1 = 0x06;    /* 24 Mhz, video trf eneble
+                                        * inverse power down */
                }
                break;
        }
@@ -1462,7 +1506,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 +1609,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;
@@ -1649,6 +1729,7 @@ static const __devinitdata struct usb_device_id device_table[] = {
 #endif
        {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
        {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
+       {USB_DEVICE(0x06f8, 0x3004), BSI(SN9C105, OV7660, 0x21)},
        {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
 /* bw600.inf:
        {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */