V4L/DVB: gspca - sonixj: Add sensor soi768
authorJean-François Moine <moinejf@free.fr>
Sun, 25 Apr 2010 17:45:43 +0000 (14:45 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Wed, 19 May 2010 15:58:15 +0000 (12:58 -0300)
The webcams 0c45:613e may contain the sensors ov7630 or soi768.
A sensor probe is done at init time when the sensor is declared ov7630.

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

index 19ae4f5..bb923ef 100644 (file)
@@ -80,6 +80,7 @@ enum {
        SENSOR_OV7660,
        SENSOR_PO1030,
        SENSOR_PO2030N,
+       SENSOR_SOI768,
        SENSOR_SP80708,
 } sensors;
        u8 i2c_addr;
@@ -330,6 +331,10 @@ static const __u32 ctrl_dis[] = {
                        (1 << INFRARED_IDX) |
                        (1 << VFLIP_IDX) |
                        (1 << FREQ_IDX),
+[SENSOR_SOI768] =      (1 << AUTOGAIN_IDX) |
+                       (1 << INFRARED_IDX) |
+                       (1 << VFLIP_IDX) |
+                       (1 << FREQ_IDX),
 
 [SENSOR_SP80708] =     (1 << AUTOGAIN_IDX) |
                        (1 << INFRARED_IDX) |
@@ -495,6 +500,17 @@ static const u8 sn_po2030n[0x1c] = {
        0x07,   0x00,   0x00,   0x00
 };
 
+static const u8 sn_soi768[0x1c] = {
+/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
+       0x00,   0x21,   0x40,   0x00,   0x1a,   0x00,   0x00,   0x00,
+/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
+       0x81,   0x21,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
+/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
+       0x03,   0x00,   0x00,   0x01,   0x08,   0x28,   0x1e,   0x00,
+/*     reg18   reg19   reg1a   reg1b */
+       0x07,   0x00,   0x00,   0x00
+};
+
 static const u8 sn_sp80708[0x1c] = {
 /*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
        0x00,   0x63,   0x60,   0x00,   0x1a,   0x20,   0x20,   0x20,
@@ -520,7 +536,8 @@ static const u8 *sn_tb[] = {
 [SENSOR_OV7660] =      sn_ov7660,
 [SENSOR_PO1030] =      sn_po1030,
 [SENSOR_PO2030N] =     sn_po2030n,
-[SENSOR_SP80708] =     sn_sp80708
+[SENSOR_SOI768] =      sn_soi768,
+[SENSOR_SP80708] =     sn_sp80708,
 };
 
 /* default gamma table */
@@ -1173,6 +1190,37 @@ static const u8 po2030n_sensor_param1[][8] = {
        {}
 };
 
+static const u8 soi768_sensor_init[][8] = {
+       {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */
+       {0xdd, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 96ms */
+       {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x13, 0x80, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x19, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {}
+};
+static const u8 soi768_sensor_param1[][8] = {
+       {0xa1, 0x21, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xb1, 0x21, 0x01, 0x7f, 0x7f, 0x00, 0x00, 0x10},
+/* */
+/*     {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, */
+/*     {0xa1, 0x21, 0x2d, 0x25, 0x00, 0x00, 0x00, 0x10}, */
+       {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
+/*     {0xb1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, */
+       {0xa1, 0x21, 0x02, 0x8d, 0x00, 0x00, 0x00, 0x10},
+/* the next sequence should be used for auto gain */
+       {0xa1, 0x21, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10},
+                       /* global gain ? : 07 - change with 0x15 at the end */
+       {0xa1, 0x21, 0x10, 0x3f, 0x00, 0x00, 0x00, 0x10}, /* ???? : 063f */
+       {0xa1, 0x21, 0x04, 0x06, 0x00, 0x00, 0x00, 0x10},
+       {0xb1, 0x21, 0x2d, 0x00, 0x02, 0x00, 0x00, 0x10},
+                       /* exposure ? : 0200 - change with 0x1e at the end */
+       {}
+};
+
 static const u8 sp80708_sensor_init[][8] = {
        {0xa1, 0x18, 0x06, 0xf9, 0x00, 0x00, 0x00, 0x10},
        {0xa1, 0x18, 0x09, 0x1f, 0x00, 0x00, 0x00, 0x10},
@@ -1271,6 +1319,7 @@ static const u8 (*sensor_init[])[8] = {
 [SENSOR_OV7660] =      ov7660_sensor_init,
 [SENSOR_PO1030] =      po1030_sensor_init,
 [SENSOR_PO2030N] =     po2030n_sensor_init,
+[SENSOR_SOI768] =      soi768_sensor_init,
 [SENSOR_SP80708] =     sp80708_sensor_init,
 };
 
@@ -1495,6 +1544,30 @@ static void mi0360_probe(struct gspca_dev *gspca_dev)
        }
 }
 
+static void ov7630_probe(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u16 val;
+
+       /* check ov76xx */
+       reg_w1(gspca_dev, 0x17, 0x62);
+       reg_w1(gspca_dev, 0x01, 0x08);
+       sd->i2c_addr = 0x21;
+       i2c_r(gspca_dev, 0x0a, 2);
+       val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
+       reg_w1(gspca_dev, 0x01, 0x29);
+       reg_w1(gspca_dev, 0x17, 0x42);
+       if (val == 0x7628) {                    /* soi768 */
+               sd->sensor = SENSOR_SOI768;
+/*fixme: only valid for 0c45:613e?*/
+               gspca_dev->cam.input_flags =
+                               V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP;
+               PDEBUG(D_PROBE, "Sensor soi768");
+               return;
+       }
+       PDEBUG(D_PROBE, "Sensor ov%04x", val);
+}
+
 static void ov7648_probe(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
@@ -1591,6 +1664,7 @@ static void bridge_init(struct gspca_dev *gspca_dev,
        case SENSOR_OV7660:
        case SENSOR_PO1030:
        case SENSOR_PO2030N:
+       case SENSOR_SOI768:
        case SENSOR_SP80708:
                reg9a = reg9a_spec;
                break;
@@ -1656,6 +1730,7 @@ static void bridge_init(struct gspca_dev *gspca_dev,
                reg_w1(gspca_dev, 0x01, 0x42);
                break;
        case SENSOR_PO1030:
+       case SENSOR_SOI768:
                reg_w1(gspca_dev, 0x01, 0x61);
                reg_w1(gspca_dev, 0x17, 0x20);
                reg_w1(gspca_dev, 0x01, 0x60);
@@ -1771,6 +1846,9 @@ static int sd_init(struct gspca_dev *gspca_dev)
                case SENSOR_MI0360:
                        mi0360_probe(gspca_dev);
                        break;
+               case SENSOR_OV7630:
+                       ov7630_probe(gspca_dev);
+                       break;
                case SENSOR_OV7648:
                        ov7648_probe(gspca_dev);
                        break;
@@ -2280,6 +2358,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
                reg17 = 0x20;
                break;
        case SENSOR_OV7660:
+       case SENSOR_SOI768:
                reg17 = 0xa0;
                break;
        case SENSOR_PO1030:
@@ -2317,6 +2396,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
                reg_w1(gspca_dev, 0x9a, 0x0a);
                break;
        case SENSOR_PO2030N:
+       case SENSOR_SOI768:
                reg_w1(gspca_dev, 0x9a, 0x06);
                break;
        default:
@@ -2403,6 +2483,11 @@ static int sd_start(struct gspca_dev *gspca_dev)
                reg1 = 0x46;
                reg17 = 0xa2;
                break;
+       case SENSOR_SOI768:
+               init = soi768_sensor_param1;
+               reg1 = 0x44;
+               reg17 = 0xa2;
+               break;
        default:
 /*     case SENSOR_SP80708: */
                init = sp80708_sensor_param1;
@@ -2425,6 +2510,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
        switch (sd->sensor) {
        case SENSOR_ADCM1700:
        case SENSOR_GC0307:
+       case SENSOR_SOI768:
                reg_w(gspca_dev, 0xca, CA_adcm1700, 4);
                break;
        case SENSOR_PO2030N:
@@ -2439,6 +2525,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
        case SENSOR_OV7630:
        case SENSOR_OV7648:
        case SENSOR_OV7660:
+       case SENSOR_SOI768:
                reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
                break;
        case SENSOR_GC0307:
@@ -2480,6 +2567,8 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
                { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
        static const u8 stopov7648[] =
                { 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 };
+       static const u8 stopsoi768[] =
+               { 0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10 };
        u8 data;
        const u8 *sn9c1xx;
 
@@ -2504,6 +2593,10 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
        case SENSOR_PO1030:
                data = 0x29;
                break;
+       case SENSOR_SOI768:
+               i2c_w8(gspca_dev, stopsoi768);
+               data = 0x29;
+               break;
        }
        sn9c1xx = sn_tb[sd->sensor];
        reg_w1(gspca_dev, 0x01, sn9c1xx[1]);