V4L/DVB (13872): gspca - sonixj: Add sensor adcm1700 and webcam 0c45:614a.
authorJean-Francois Moine <moinejf@free.fr>
Sun, 20 Dec 2009 15:31:28 +0000 (12:31 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Fri, 26 Feb 2010 18:10:27 +0000 (15:10 -0300)
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Documentation/video4linux/gspca.txt
drivers/media/video/gspca/sonixj.c

index d389619..7b60343 100644 (file)
@@ -304,6 +304,7 @@ sonixj              0c45:613b       Surfer SN-206
 sonixj         0c45:613c       Sonix Pccam168
 sonixj         0c45:6143       Sonix Pccam168
 sonixj         0c45:6148       Digitus DA-70811/ZSMC USB PC Camera ZS211/Microdia
+sonixj         0c45:614a       Frontech E-Ccam (JIL-2225)
 sn9c20x                0c45:6240       PC Camera (SN9C201 + MT9M001)
 sn9c20x                0c45:6242       PC Camera (SN9C201 + MT9M111)
 sn9c20x                0c45:6248       PC Camera (SN9C201 + OV9655)
index 0bd36a0..1f21c6a 100644 (file)
@@ -64,16 +64,17 @@ struct sd {
 #define BRIDGE_SN9C110 2
 #define BRIDGE_SN9C120 3
        u8 sensor;                      /* Type of image sensor chip */
-#define SENSOR_HV7131R 0
-#define SENSOR_MI0360 1
-#define SENSOR_MO4000 2
-#define SENSOR_MT9V111 3
-#define SENSOR_OM6802 4
-#define SENSOR_OV7630 5
-#define SENSOR_OV7648 6
-#define SENSOR_OV7660 7
-#define SENSOR_PO1030 8
-#define SENSOR_SP80708 9
+#define SENSOR_ADCM1700 0
+#define SENSOR_HV7131R 1
+#define SENSOR_MI0360 2
+#define SENSOR_MO4000 3
+#define SENSOR_MT9V111 4
+#define SENSOR_OM6802 5
+#define SENSOR_OV7630 6
+#define SENSOR_OV7648 7
+#define SENSOR_OV7660 8
+#define SENSOR_PO1030 9
+#define SENSOR_SP80708 10
        u8 i2c_addr;
 
        u8 *jpeg_hdr;
@@ -261,28 +262,37 @@ static struct ctrl sd_ctrls[] = {
 
 /* table of the disabled controls */
 static __u32 ctrl_dis[] = {
+       (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX) |
+       (1 << AUTOGAIN_IDX) | (1 << BRIGHTNESS_IDX), /* SENSOR_ADCM1700 0 */
        (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX),
-                                               /* SENSOR_HV7131R 0 */
+                                               /* SENSOR_HV7131R 1 */
        (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX),
-                                               /* SENSOR_MI0360 1 */
+                                               /* SENSOR_MI0360 2 */
        (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX),
-                                               /* SENSOR_MO4000 2 */
+                                               /* SENSOR_MO4000 3 */
        (1 << VFLIP_IDX) | (1 << FREQ_IDX),
-                                               /* SENSOR_MT9V111 3 */
+                                               /* SENSOR_MT9V111 4 */
        (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX),
-                                               /* SENSOR_OM6802 4 */
+                                               /* SENSOR_OM6802 5 */
        (1 << INFRARED_IDX),
-                                               /* SENSOR_OV7630 5 */
+                                               /* SENSOR_OV7630 6 */
        (1 << INFRARED_IDX),
-                                               /* SENSOR_OV7648 6 */
+                                               /* SENSOR_OV7648 7 */
        (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
-                                               /* SENSOR_OV7660 7 */
+                                               /* SENSOR_OV7660 8 */
        (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) |
-                             (1 << FREQ_IDX),  /* SENSOR_PO1030 8 */
+                             (1 << FREQ_IDX),  /* SENSOR_PO1030 9 */
        (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) |
-                             (1 << FREQ_IDX),  /* SENSOR_SP80708 9 */
+                             (1 << FREQ_IDX),  /* SENSOR_SP80708 10 */
 };
 
+static const struct v4l2_pix_format cif_mode[] = {
+       {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288 * 4 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 0},
+};
 static const struct v4l2_pix_format vga_mode[] = {
        {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
                .bytesperline = 160,
@@ -302,6 +312,17 @@ static const struct v4l2_pix_format vga_mode[] = {
                .priv = 0},
 };
 
+static const u8 sn_adcm1700[0x1c] = {
+/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
+       0x00,   0x42,   0x60,   0x00,   0x1a,   0x20,   0x20,   0x20,
+/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
+       0x80,   0x51,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
+/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
+       0x03,   0x00,   0x05,   0x01,   0x05,   0x16,   0x12,   0x42,
+/*     reg18   reg19   reg1a   reg1b */
+       0x06,   0x00,   0x00,   0x00
+};
+
 /*Data from sn9c102p+hv7131r */
 static const u8 sn_hv7131[0x1c] = {
 /*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
@@ -415,6 +436,7 @@ static const u8 sn_sp80708[0x1c] = {
 
 /* sequence specific to the sensors - !! index = SENSOR_xxx */
 static const u8 *sn_tb[] = {
+       sn_adcm1700,
        sn_hv7131,
        sn_mi0360,
        sn_mo4000,
@@ -432,6 +454,11 @@ static const u8 gamma_def[17] = {
        0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
        0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
 };
+/* gamma for sensor ADCM1700 */
+static const u8 gamma_spec_0[17] = {
+       0x0f, 0x39, 0x5a, 0x74, 0x86, 0x95, 0xa6, 0xb4,
+       0xbd, 0xc4, 0xcc, 0xd4, 0xd5, 0xde, 0xe4, 0xed, 0xf5
+};
 /* gamma for sensors HV7131R and MT9V111 */
 static const u8 gamma_spec_1[17] = {
        0x08, 0x3a, 0x52, 0x65, 0x75, 0x83, 0x91, 0x9d,
@@ -450,6 +477,38 @@ static const u8 reg84[] = {
        0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f,     /* VR VG VB */
        0x00, 0x00, 0x00                        /* YUV offsets */
 };
+static const u8 adcm1700_sensor_init[][8] = {
+       {0xa0, 0x51, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xb0, 0x51, 0x04, 0x08, 0x00, 0x00, 0x00, 0x10},
+       {0xdd, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+       {0xb0, 0x51, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xdd, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+       {0xb0, 0x51, 0x0c, 0xe0, 0x2e, 0x00, 0x00, 0x10},
+       {0xb0, 0x51, 0x10, 0x02, 0x02, 0x00, 0x00, 0x10},
+       {0xb0, 0x51, 0x14, 0x0e, 0x0e, 0x00, 0x00, 0x10},
+       {0xb0, 0x51, 0x1c, 0x00, 0x80, 0x00, 0x00, 0x10},
+       {0xb0, 0x51, 0x20, 0x01, 0x00, 0x00, 0x00, 0x10},
+       {0xdd, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+       {0xb0, 0x51, 0x04, 0x04, 0x00, 0x00, 0x00, 0x10},
+       {0xdd, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+       {0xb0, 0x51, 0x04, 0x01, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
+       {0xb0, 0x51, 0x14, 0x01, 0x00, 0x00, 0x00, 0x10},
+       {0xb0, 0x51, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {}
+};
+static const u8 adcm1700_sensor_param1[][8] = {
+       {0xb0, 0x51, 0x26, 0xf9, 0x01, 0x00, 0x00, 0x10},
+       {0xd0, 0x51, 0x1e, 0x8e, 0x8e, 0x8e, 0x8e, 0x10},
+
+       {0xa0, 0x51, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x10},
+       {0xb0, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
+       {0xb0, 0x51, 0x32, 0x00, 0x72, 0x00, 0x00, 0x10},
+       {0xd0, 0x51, 0x1e, 0x8e, 0x91, 0x91, 0x8e, 0x10},
+
+       {}
+};
 static const u8 hv7131r_sensor_init[][8] = {
        {0xc1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
        {0xb1, 0x11, 0x34, 0x17, 0x7f, 0x00, 0x00, 0x10},
@@ -986,17 +1045,18 @@ static const u8 sp80708_sensor_param1[][8] = {
        {}
 };
 
-static const u8 (*sensor_init[10])[8] = {
-       hv7131r_sensor_init,    /* HV7131R 0 */
-       mi0360_sensor_init,     /* MI0360 1 */
-       mo4000_sensor_init,     /* MO4000 2 */
-       mt9v111_sensor_init,    /* MT9V111 3 */
-       om6802_sensor_init,     /* OM6802 4 */
-       ov7630_sensor_init,     /* OV7630 5 */
-       ov7648_sensor_init,     /* OV7648 6 */
-       ov7660_sensor_init,     /* OV7660 7 */
-       po1030_sensor_init,     /* PO1030 8 */
-       sp80708_sensor_init,    /* SP80708 9 */
+static const u8 (*sensor_init[11])[8] = {
+       adcm1700_sensor_init,   /* ADCM1700 0 */
+       hv7131r_sensor_init,    /* HV7131R 1 */
+       mi0360_sensor_init,     /* MI0360 2 */
+       mo4000_sensor_init,     /* MO4000 3 */
+       mt9v111_sensor_init,    /* MT9V111 4 */
+       om6802_sensor_init,     /* OM6802 5 */
+       ov7630_sensor_init,     /* OV7630 6 */
+       ov7648_sensor_init,     /* OV7648 7 */
+       ov7660_sensor_init,     /* OV7660 8 */
+       po1030_sensor_init,     /* PO1030 9 */
+       sp80708_sensor_init,    /* SP80708 10 */
 };
 
 /* read <len> bytes to gspca_dev->usb_buf */
@@ -1064,6 +1124,7 @@ static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
 
        PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
        switch (sd->sensor) {
+       case SENSOR_ADCM1700:
        case SENSOR_OM6802:             /* i2c command = a0 (100 kHz) */
                gspca_dev->usb_buf[0] = 0x80 | (2 << 4);
                break;
@@ -1110,6 +1171,7 @@ static void i2c_r(struct gspca_dev *gspca_dev, u8 reg, int len)
        u8 mode[8];
 
        switch (sd->sensor) {
+       case SENSOR_ADCM1700:
        case SENSOR_OM6802:             /* i2c command = 90 (100 kHz) */
                mode[0] = 0x80 | 0x10;
                break;
@@ -1284,6 +1346,12 @@ static void bridge_init(struct gspca_dev *gspca_dev,
        reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
 
        switch (sd->sensor) {
+       case SENSOR_ADCM1700:
+               reg_w1(gspca_dev, 0x01, 0x42);
+               reg_w1(gspca_dev, 0x17, 0x62);
+               reg_w1(gspca_dev, 0x01, 0x42);
+               reg_w1(gspca_dev, 0x01, 0x42);
+               break;
        case SENSOR_MT9V111:
                reg_w1(gspca_dev, 0x01, 0x61);
                reg_w1(gspca_dev, 0x17, 0x61);
@@ -1358,8 +1426,13 @@ static int sd_config(struct gspca_dev *gspca_dev,
        struct cam *cam;
 
        cam = &gspca_dev->cam;
-       cam->cam_mode = vga_mode;
-       cam->nmodes = ARRAY_SIZE(vga_mode);
+       if (sd->sensor == SENSOR_ADCM1700) {
+               cam->cam_mode = cif_mode;
+               cam->nmodes = ARRAY_SIZE(cif_mode);
+       } else {
+               cam->cam_mode = vga_mode;
+               cam->nmodes = ARRAY_SIZE(vga_mode);
+       }
        cam->npkt = 24;                 /* 24 packets per ISOC message */
 
        sd->bridge = id->driver_info >> 16;
@@ -1543,6 +1616,8 @@ static void setbrightness(struct gspca_dev *gspca_dev)
 
        k2 = ((int) sd->brightness - 0x8000) >> 10;
        switch (sd->sensor) {
+       case SENSOR_ADCM1700:
+               return;
        case SENSOR_HV7131R:
                expo = sd->brightness << 4;
                if (expo > 0x002dc6c0)
@@ -1625,6 +1700,9 @@ static void setgamma(struct gspca_dev *gspca_dev)
        };
 
        switch (sd->sensor) {
+       case SENSOR_ADCM1700:
+               gamma_base = gamma_spec_0;
+               break;
        case SENSOR_HV7131R:
        case SENSOR_MT9V111:
                gamma_base = gamma_spec_1;
@@ -1804,6 +1882,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
        int mode;
        static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
        static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
+       static const u8 CA_adcm1700[] =
+                               { 0x14, 0xec, 0x0a, 0xf6 };
        static const u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd };      /* MI0360 */
        static const u8 CE_ov76xx[] =
                                { 0x32, 0xdd, 0x32, 0xdd };
@@ -1824,6 +1904,9 @@ static int sd_start(struct gspca_dev *gspca_dev)
        i2c_w_seq(gspca_dev, sensor_init[sd->sensor]);
 
        switch (sd->sensor) {
+       case SENSOR_ADCM1700:
+               reg2 = 0x60;
+               break;
        case SENSOR_OM6802:
                reg2 = 0x71;
                break;
@@ -1842,17 +1925,28 @@ static int sd_start(struct gspca_dev *gspca_dev)
        reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
        reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
        reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
-       reg_w1(gspca_dev, 0xd2, 0x6a);          /* DC29 */
-       reg_w1(gspca_dev, 0xd3, 0x50);
+       if (sd->sensor == SENSOR_ADCM1700) {
+               reg_w1(gspca_dev, 0xd2, 0x3a);          /* DC29 */
+               reg_w1(gspca_dev, 0xd3, 0x30);
+       } else {
+               reg_w1(gspca_dev, 0xd2, 0x6a);          /* DC29 */
+               reg_w1(gspca_dev, 0xd3, 0x50);
+       }
        reg_w1(gspca_dev, 0xc6, 0x00);
        reg_w1(gspca_dev, 0xc7, 0x00);
-       reg_w1(gspca_dev, 0xc8, 0x50);
-       reg_w1(gspca_dev, 0xc9, 0x3c);
+       if (sd->sensor == SENSOR_ADCM1700) {
+               reg_w1(gspca_dev, 0xc8, 0x2c);
+               reg_w1(gspca_dev, 0xc9, 0x24);
+       } else {
+               reg_w1(gspca_dev, 0xc8, 0x50);
+               reg_w1(gspca_dev, 0xc9, 0x3c);
+       }
        reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
        switch (sd->sensor) {
        case SENSOR_MT9V111:
                reg17 = 0xe0;
                break;
+       case SENSOR_ADCM1700:
        case SENSOR_OV7630:
                reg17 = 0xe2;
                break;
@@ -1881,6 +1975,10 @@ static int sd_start(struct gspca_dev *gspca_dev)
        for (i = 0; i < 8; i++)
                reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
        switch (sd->sensor) {
+       case SENSOR_ADCM1700:
+               reg_w1(gspca_dev, 0x9a, 0x05);
+               reg_w1(gspca_dev, 0x99, 0x60);
+               break;
        case SENSOR_MT9V111:
                reg_w1(gspca_dev, 0x9a, 0x07);
                reg_w1(gspca_dev, 0x99, 0x59);
@@ -1917,6 +2015,11 @@ static int sd_start(struct gspca_dev *gspca_dev)
                reg1 = 0x06;    /* 640x480: clk 24Mhz, video trf enable */
        reg17 = 0x61;           /* 0x:20: enable sensor clock */
        switch (sd->sensor) {
+       case SENSOR_ADCM1700:
+               init = adcm1700_sensor_param1;
+               reg1 = 0x46;
+               reg17 = 0xe2;
+               break;
        case SENSOR_MO4000:
                if (mode) {
 /*                     reg1 = 0x46;     * 320 clk 48Mhz 60fp/s */
@@ -1986,8 +2089,12 @@ static int sd_start(struct gspca_dev *gspca_dev)
        }
 
        reg_w(gspca_dev, 0xc0, C0, 6);
-       reg_w(gspca_dev, 0xca, CA, 4);
+       if (sd->sensor == SENSOR_ADCM1700)
+               reg_w(gspca_dev, 0xca, CA_adcm1700, 4);
+       else
+               reg_w(gspca_dev, 0xca, CA, 4);
        switch (sd->sensor) {
+       case SENSOR_ADCM1700:
        case SENSOR_OV7630:
        case SENSOR_OV7648:
        case SENSOR_OV7660:
@@ -2472,6 +2579,7 @@ static const __devinitdata struct usb_device_id device_table[] = {
 /*     {USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)},      *sn9c120b*/
        {USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)},     /*sn9c120b*/
        {USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)},      /*sn9c120b*/
+       {USB_DEVICE(0x0c45, 0x614a), BS(SN9C120, ADCM1700)},    /*sn9c120b*/
        {}
 };
 MODULE_DEVICE_TABLE(usb, device_table);