]> err.no Git - linux-2.6/blobdiff - drivers/media/video/gspca/sonixb.c
V4L/DVB (8374): gspca: No conflict of 0c45:6011 with the sn9c102 driver.
[linux-2.6] / drivers / media / video / gspca / sonixb.c
index 045ed6b7d053f54fea63d0c6be93b735f21414cc..dbeebe8625c59189021660462d4326c73f820715 100644 (file)
@@ -24,8 +24,8 @@
 
 #include "gspca.h"
 
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 1, 7)
-static const char version[] = "2.1.7";
+#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 1, 8)
+static const char version[] = "2.1.8";
 
 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
 MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
@@ -45,6 +45,9 @@ struct sd {
        unsigned char autogain;
        unsigned char autogain_ignore_frames;
        unsigned char freq;             /* light freq filter setting */
+       unsigned char saturation;
+       unsigned char hue;
+       unsigned char contrast;
 
        unsigned char fr_h_sz;          /* size of frame header */
        char sensor;                    /* Type of image sensor chip */
@@ -89,6 +92,12 @@ 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_setfreq(struct gspca_dev *gspca_dev, __s32 val);
 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
 
 static struct ctrl sd_ctrls[] = {
        {
@@ -165,6 +174,48 @@ static struct ctrl sd_ctrls[] = {
                .set = sd_setfreq,
                .get = sd_getfreq,
        },
+       {
+               {
+                       .id      = V4L2_CID_SATURATION,
+                       .type    = V4L2_CTRL_TYPE_INTEGER,
+                       .name    = "Saturation",
+                       .minimum = 0,
+                       .maximum = 255,
+                       .step    = 1,
+#define SATURATION_DEF 127
+                       .default_value = SATURATION_DEF,
+               },
+               .set = sd_setsaturation,
+               .get = sd_getsaturation,
+       },
+       {
+               {
+                       .id      = V4L2_CID_HUE,
+                       .type    = V4L2_CTRL_TYPE_INTEGER,
+                       .name    = "Hue",
+                       .minimum = 0,
+                       .maximum = 255,
+                       .step    = 1,
+#define HUE_DEF 127
+                       .default_value = HUE_DEF,
+               },
+               .set = sd_sethue,
+               .get = sd_gethue,
+       },
+       {
+               {
+                       .id      = V4L2_CID_CONTRAST,
+                       .type    = V4L2_CTRL_TYPE_INTEGER,
+                       .name    = "Contrast",
+                       .minimum = 0,
+                       .maximum = 255,
+                       .step    = 1,
+#define CONTRAST_DEF 127
+                       .default_value = CONTRAST_DEF,
+               },
+               .set = sd_setcontrast,
+               .get = sd_getcontrast,
+       },
 };
 
 static struct v4l2_pix_format vga_mode[] = {
@@ -238,8 +289,15 @@ static const __u8 ov6650_sensor_init[][8] =
        {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
        {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
        {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
-       /* Disable autobright ? */
-       {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10},
+       /* Enable rgb brightness control */
+       {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
+       /* HDG: Note windows uses the line below, which sets both register 0x60
+          and 0x61 I believe these registers of the ov6650 are identical as
+          those of the ov7630, because if this is true the windows settings
+          add a bit additional red gain and a lot additional blue gain, which
+          matches my findings that the windows settings make blue much too
+          blue and red a little too red.
+       {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
        /* Some more unknown stuff */
        {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
        {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
@@ -655,7 +713,8 @@ static void setexposure(struct gspca_dev *gspca_dev)
                   tline * 4 * reg10, which explains why the reg10max we've
                   found experimentally for the ov6650 is exactly half that of
                   the ov6645. The ov7630 datasheet says the max is 0x41. */
-               const int reg10_max = (sd->sensor == SENSOR_OV6650)? 0x4d:0x41;
+               const int reg10_max = (sd->sensor == SENSOR_OV6650)
+                               ? 0x4d : 0x41;
 
                reg11 = (60 * sd->exposure + 999) / 1000;
                if (reg11 < 1)
@@ -715,7 +774,8 @@ static void setfreq(struct gspca_dev *gspca_dev)
                        i2c[3] = 0;
                        break;
                case 1:                 /* 50 hz */
-                       i2c[3] = (sd->sensor == SENSOR_OV6650)? 0x4f:0x8a;
+                       i2c[3] = (sd->sensor == SENSOR_OV6650)
+                                       ? 0x4f : 0x8a;
                        break;
                }
                i2c[1] = sd->sensor_addr;
@@ -726,6 +786,68 @@ static void setfreq(struct gspca_dev *gspca_dev)
        }
 }
 
+static void setsaturation(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       switch (sd->sensor) {
+/*     case SENSOR_OV6650: */
+       case SENSOR_OV7630_3:
+       case SENSOR_OV7630: {
+               __u8 i2c[] = {0xa0, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10};
+               i2c[1] = sd->sensor_addr;
+               i2c[3] = sd->saturation & 0xf0;
+               if (i2c_w(gspca_dev, i2c) < 0)
+                       PDEBUG(D_ERR, "i2c error setsaturation");
+               else
+                       PDEBUG(D_CONF, "saturation set to: %d",
+                               (int)sd->saturation);
+               break;
+           }
+       }
+}
+
+static void sethue(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       switch (sd->sensor) {
+/*     case SENSOR_OV6650: */
+       case SENSOR_OV7630_3:
+       case SENSOR_OV7630: {
+               __u8 i2c[] = {0xa0, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10};
+               i2c[1] = sd->sensor_addr;
+               i2c[3] = 0x20 | (sd->hue >> 3);
+               if (i2c_w(gspca_dev, i2c) < 0)
+                       PDEBUG(D_ERR, "i2c error setsaturation");
+               else
+                       PDEBUG(D_CONF, "hue set to: %d", (int)sd->hue);
+               break;
+           }
+       }
+}
+
+static void setcontrast(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       switch (sd->sensor) {
+/*     case SENSOR_OV6650: */
+       case SENSOR_OV7630_3:
+       case SENSOR_OV7630: {
+               __u8 i2c[] = {0xa0, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10};
+               i2c[1] = sd->sensor_addr;
+               i2c[3] = 0x20 | (sd->contrast >> 3);
+               if (i2c_w(gspca_dev, i2c) < 0)
+                       PDEBUG(D_ERR, "i2c error setcontrast");
+               else
+                       PDEBUG(D_CONF, "contrast set to: %d",
+                               (int)sd->contrast);
+               break;
+           }
+       }
+}
+
 
 static void do_autogain(struct gspca_dev *gspca_dev)
 {
@@ -762,7 +884,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
        sd->fr_h_sz = 12;               /* default size of the frame header */
        sd->sd_desc.nctrls = 2;         /* default nb of ctrls */
        sd->autogain = AUTOGAIN_DEF;    /* default is autogain active */
-       sd->freq = FREQ_DEF;
 
        product = id->idProduct;
 /*     switch (id->idVendor) { */
@@ -787,7 +908,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
                        sd->sensor = SENSOR_OV6650;
                        sd->sensor_has_gain = 1;
                        sd->sensor_addr = 0x60;
-                       sd->sd_desc.nctrls = 4;
+                       sd->sd_desc.nctrls = 5;
                        sd->sd_desc.dq_callback = do_autogain;
                        sif = 1;
                        break;
@@ -802,7 +923,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
                        sd->sensor_addr = 0x21;
                        sd->fr_h_sz = 18;       /* size of frame header */
                        sd->sensor_has_gain = 1;
-                       sd->sd_desc.nctrls = 5;
+                       sd->sd_desc.nctrls = 8;
                        sd->sd_desc.dq_callback = do_autogain;
                        sd->autogain = 0;
                        break;
@@ -842,6 +963,10 @@ static int sd_config(struct gspca_dev *gspca_dev,
        sd->brightness = BRIGHTNESS_DEF;
        sd->gain = GAIN_DEF;
        sd->exposure = EXPOSURE_DEF;
+       sd->freq = FREQ_DEF;
+       sd->contrast = CONTRAST_DEF;
+       sd->saturation = SATURATION_DEF;
+       sd->hue = HUE_DEF;
        if (sd->sensor == SENSOR_OV7630_3)      /* jfm: from win trace */
                reg_w(gspca_dev, 0x01, probe_ov7630, sizeof probe_ov7630);
        return 0;
@@ -938,7 +1063,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
        case SENSOR_OV7630:
                reg01 = 0x06;
                reg17 = 0x29;
-               l = 0x10;
+               l = sizeof initOv7630;
                break;
        case SENSOR_OV7630_3:
                reg01 = 0x44;
@@ -1024,6 +1149,9 @@ static void sd_start(struct gspca_dev *gspca_dev)
        setbrightness(gspca_dev);
        setexposure(gspca_dev);
        setfreq(gspca_dev);
+       setsaturation(gspca_dev);
+       sethue(gspca_dev);
+       setcontrast(gspca_dev);
 
        sd->autogain_ignore_frames = 0;
        atomic_set(&sd->avg_lum, -1);
@@ -1199,6 +1327,60 @@ static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
        return 0;
 }
 
+static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->saturation = val;
+       if (gspca_dev->streaming)
+               setsaturation(gspca_dev);
+       return 0;
+}
+
+static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       *val = sd->saturation;
+       return 0;
+}
+
+static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->hue = val;
+       if (gspca_dev->streaming)
+               sethue(gspca_dev);
+       return 0;
+}
+
+static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       *val = sd->hue;
+       return 0;
+}
+
+static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->contrast = val;
+       if (gspca_dev->streaming)
+               setcontrast(gspca_dev);
+       return 0;
+}
+
+static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       *val = sd->contrast;
+       return 0;
+}
+
 static int sd_querymenu(struct gspca_dev *gspca_dev,
                        struct v4l2_querymenu *menu)
 {
@@ -1244,7 +1426,9 @@ static __devinitdata struct usb_device_id device_table[] = {
        {USB_DEVICE(0x0c45, 0x6007), DVNM("Sonix sn9c101 + Tas5110D")},
        {USB_DEVICE(0x0c45, 0x6009), DVNM("spcaCam@120")},
        {USB_DEVICE(0x0c45, 0x600d), DVNM("spcaCam@120")},
+#endif
        {USB_DEVICE(0x0c45, 0x6011), DVNM("MAX Webcam Microdia")},
+#ifndef CONFIG_USB_SN9C102
        {USB_DEVICE(0x0c45, 0x6019), DVNM("Generic Sonix OV7630")},
        {USB_DEVICE(0x0c45, 0x6024), DVNM("Generic Sonix Tas5130c")},
        {USB_DEVICE(0x0c45, 0x6025), DVNM("Xcam Shanga")},