Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *      Connexant Cx11646 library
0004  *      Copyright (C) 2004 Michel Xhaard mxhaard@magic.fr
0005  *
0006  * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
0007  */
0008 
0009 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0010 
0011 #define MODULE_NAME "conex"
0012 
0013 #include "gspca.h"
0014 #define CONEX_CAM 1     /* special JPEG header */
0015 #include "jpeg.h"
0016 
0017 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
0018 MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver");
0019 MODULE_LICENSE("GPL");
0020 
0021 #define QUALITY 50
0022 
0023 /* specific webcam descriptor */
0024 struct sd {
0025     struct gspca_dev gspca_dev; /* !! must be the first item */
0026     struct v4l2_ctrl *brightness;
0027     struct v4l2_ctrl *contrast;
0028     struct v4l2_ctrl *sat;
0029 
0030     u8 jpeg_hdr[JPEG_HDR_SZ];
0031 };
0032 
0033 static const struct v4l2_pix_format vga_mode[] = {
0034     {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
0035         .bytesperline = 176,
0036         .sizeimage = 176 * 144 * 3 / 8 + 590,
0037         .colorspace = V4L2_COLORSPACE_JPEG,
0038         .priv = 3},
0039     {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
0040         .bytesperline = 320,
0041         .sizeimage = 320 * 240 * 3 / 8 + 590,
0042         .colorspace = V4L2_COLORSPACE_JPEG,
0043         .priv = 2},
0044     {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
0045         .bytesperline = 352,
0046         .sizeimage = 352 * 288 * 3 / 8 + 590,
0047         .colorspace = V4L2_COLORSPACE_JPEG,
0048         .priv = 1},
0049     {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
0050         .bytesperline = 640,
0051         .sizeimage = 640 * 480 * 3 / 8 + 590,
0052         .colorspace = V4L2_COLORSPACE_JPEG,
0053         .priv = 0},
0054 };
0055 
0056 /* the read bytes are found in gspca_dev->usb_buf */
0057 static void reg_r(struct gspca_dev *gspca_dev,
0058           __u16 index,
0059           __u16 len)
0060 {
0061     struct usb_device *dev = gspca_dev->dev;
0062 
0063     if (len > USB_BUF_SZ) {
0064         gspca_err(gspca_dev, "reg_r: buffer overflow\n");
0065         return;
0066     }
0067 
0068     usb_control_msg(dev,
0069             usb_rcvctrlpipe(dev, 0),
0070             0,
0071             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0072             0,
0073             index, gspca_dev->usb_buf, len,
0074             500);
0075     gspca_dbg(gspca_dev, D_USBI, "reg read [%02x] -> %02x ..\n",
0076           index, gspca_dev->usb_buf[0]);
0077 }
0078 
0079 /* the bytes to write are in gspca_dev->usb_buf */
0080 static void reg_w_val(struct gspca_dev *gspca_dev,
0081             __u16 index,
0082             __u8 val)
0083 {
0084     struct usb_device *dev = gspca_dev->dev;
0085 
0086     gspca_dev->usb_buf[0] = val;
0087     usb_control_msg(dev,
0088             usb_sndctrlpipe(dev, 0),
0089             0,
0090             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0091             0,
0092             index, gspca_dev->usb_buf, 1, 500);
0093 }
0094 
0095 static void reg_w(struct gspca_dev *gspca_dev,
0096           __u16 index,
0097           const __u8 *buffer,
0098           __u16 len)
0099 {
0100     struct usb_device *dev = gspca_dev->dev;
0101 
0102     if (len > USB_BUF_SZ) {
0103         gspca_err(gspca_dev, "reg_w: buffer overflow\n");
0104         return;
0105     }
0106     gspca_dbg(gspca_dev, D_USBO, "reg write [%02x] = %02x..\n",
0107           index, *buffer);
0108 
0109     memcpy(gspca_dev->usb_buf, buffer, len);
0110     usb_control_msg(dev,
0111             usb_sndctrlpipe(dev, 0),
0112             0,
0113             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0114             0,
0115             index, gspca_dev->usb_buf, len, 500);
0116 }
0117 
0118 static const __u8 cx_sensor_init[][4] = {
0119     {0x88, 0x11, 0x01, 0x01},
0120     {0x88, 0x12, 0x70, 0x01},
0121     {0x88, 0x0f, 0x00, 0x01},
0122     {0x88, 0x05, 0x01, 0x01},
0123     {}
0124 };
0125 
0126 static const __u8 cx11646_fw1[][3] = {
0127     {0x00, 0x02, 0x00},
0128     {0x01, 0x43, 0x00},
0129     {0x02, 0xA7, 0x00},
0130     {0x03, 0x8B, 0x01},
0131     {0x04, 0xE9, 0x02},
0132     {0x05, 0x08, 0x04},
0133     {0x06, 0x08, 0x05},
0134     {0x07, 0x07, 0x06},
0135     {0x08, 0xE7, 0x06},
0136     {0x09, 0xC6, 0x07},
0137     {0x0A, 0x86, 0x08},
0138     {0x0B, 0x46, 0x09},
0139     {0x0C, 0x05, 0x0A},
0140     {0x0D, 0xA5, 0x0A},
0141     {0x0E, 0x45, 0x0B},
0142     {0x0F, 0xE5, 0x0B},
0143     {0x10, 0x85, 0x0C},
0144     {0x11, 0x25, 0x0D},
0145     {0x12, 0xC4, 0x0D},
0146     {0x13, 0x45, 0x0E},
0147     {0x14, 0xE4, 0x0E},
0148     {0x15, 0x64, 0x0F},
0149     {0x16, 0xE4, 0x0F},
0150     {0x17, 0x64, 0x10},
0151     {0x18, 0xE4, 0x10},
0152     {0x19, 0x64, 0x11},
0153     {0x1A, 0xE4, 0x11},
0154     {0x1B, 0x64, 0x12},
0155     {0x1C, 0xE3, 0x12},
0156     {0x1D, 0x44, 0x13},
0157     {0x1E, 0xC3, 0x13},
0158     {0x1F, 0x24, 0x14},
0159     {0x20, 0xA3, 0x14},
0160     {0x21, 0x04, 0x15},
0161     {0x22, 0x83, 0x15},
0162     {0x23, 0xE3, 0x15},
0163     {0x24, 0x43, 0x16},
0164     {0x25, 0xA4, 0x16},
0165     {0x26, 0x23, 0x17},
0166     {0x27, 0x83, 0x17},
0167     {0x28, 0xE3, 0x17},
0168     {0x29, 0x43, 0x18},
0169     {0x2A, 0xA3, 0x18},
0170     {0x2B, 0x03, 0x19},
0171     {0x2C, 0x63, 0x19},
0172     {0x2D, 0xC3, 0x19},
0173     {0x2E, 0x22, 0x1A},
0174     {0x2F, 0x63, 0x1A},
0175     {0x30, 0xC3, 0x1A},
0176     {0x31, 0x23, 0x1B},
0177     {0x32, 0x83, 0x1B},
0178     {0x33, 0xE2, 0x1B},
0179     {0x34, 0x23, 0x1C},
0180     {0x35, 0x83, 0x1C},
0181     {0x36, 0xE2, 0x1C},
0182     {0x37, 0x23, 0x1D},
0183     {0x38, 0x83, 0x1D},
0184     {0x39, 0xE2, 0x1D},
0185     {0x3A, 0x23, 0x1E},
0186     {0x3B, 0x82, 0x1E},
0187     {0x3C, 0xC3, 0x1E},
0188     {0x3D, 0x22, 0x1F},
0189     {0x3E, 0x63, 0x1F},
0190     {0x3F, 0xC1, 0x1F},
0191     {}
0192 };
0193 static void cx11646_fw(struct gspca_dev*gspca_dev)
0194 {
0195     int i = 0;
0196 
0197     reg_w_val(gspca_dev, 0x006a, 0x02);
0198     while (cx11646_fw1[i][1]) {
0199         reg_w(gspca_dev, 0x006b, cx11646_fw1[i], 3);
0200         i++;
0201     }
0202     reg_w_val(gspca_dev, 0x006a, 0x00);
0203 }
0204 
0205 static const __u8 cxsensor[] = {
0206     0x88, 0x12, 0x70, 0x01,
0207     0x88, 0x0d, 0x02, 0x01,
0208     0x88, 0x0f, 0x00, 0x01,
0209     0x88, 0x03, 0x71, 0x01, 0x88, 0x04, 0x00, 0x01, /* 3 */
0210     0x88, 0x02, 0x10, 0x01,
0211     0x88, 0x00, 0xD4, 0x01, 0x88, 0x01, 0x01, 0x01, /* 5 */
0212     0x88, 0x0B, 0x00, 0x01,
0213     0x88, 0x0A, 0x0A, 0x01,
0214     0x88, 0x00, 0x08, 0x01, 0x88, 0x01, 0x00, 0x01, /* 8 */
0215     0x88, 0x05, 0x01, 0x01,
0216     0xA1, 0x18, 0x00, 0x01,
0217     0x00
0218 };
0219 
0220 static const __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff };
0221 static const __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff };
0222 static const __u8 reg10[] = { 0xb1, 0xb1 };
0223 static const __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e };    /* 640 */
0224 static const __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f };
0225     /* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */
0226 static const __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 };
0227                     /* 320{0x04,0x0c,0x05,0x0f}; //320 */
0228 static const __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 };    /* 176 */
0229 static const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff };
0230 
0231 static void cx_sensor(struct gspca_dev*gspca_dev)
0232 {
0233     int i = 0;
0234     int length;
0235     const __u8 *ptsensor = cxsensor;
0236 
0237     reg_w(gspca_dev, 0x0020, reg20, 8);
0238     reg_w(gspca_dev, 0x0028, reg28, 8);
0239     reg_w(gspca_dev, 0x0010, reg10, 2);
0240     reg_w_val(gspca_dev, 0x0092, 0x03);
0241 
0242     switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
0243     case 0:
0244         reg_w(gspca_dev, 0x0071, reg71a, 4);
0245         break;
0246     case 1:
0247         reg_w(gspca_dev, 0x0071, reg71b, 4);
0248         break;
0249     default:
0250 /*  case 2: */
0251         reg_w(gspca_dev, 0x0071, reg71c, 4);
0252         break;
0253     case 3:
0254         reg_w(gspca_dev, 0x0071, reg71d, 4);
0255         break;
0256     }
0257     reg_w(gspca_dev, 0x007b, reg7b, 6);
0258     reg_w_val(gspca_dev, 0x00f8, 0x00);
0259     reg_w(gspca_dev, 0x0010, reg10, 2);
0260     reg_w_val(gspca_dev, 0x0098, 0x41);
0261     for (i = 0; i < 11; i++) {
0262         if (i == 3 || i == 5 || i == 8)
0263             length = 8;
0264         else
0265             length = 4;
0266         reg_w(gspca_dev, 0x00e5, ptsensor, length);
0267         if (length == 4)
0268             reg_r(gspca_dev, 0x00e8, 1);
0269         else
0270             reg_r(gspca_dev, 0x00e8, length);
0271         ptsensor += length;
0272     }
0273     reg_r(gspca_dev, 0x00e7, 8);
0274 }
0275 
0276 static const __u8 cx_inits_176[] = {
0277     0x33, 0x81, 0xB0, 0x00, 0x90, 0x00, 0x0A, 0x03, /* 176x144 */
0278     0x00, 0x03, 0x03, 0x03, 0x1B, 0x05, 0x30, 0x03,
0279     0x65, 0x15, 0x18, 0x25, 0x03, 0x25, 0x08, 0x30,
0280     0x3B, 0x25, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
0281     0xDC, 0xFF, 0xEE, 0xFF, 0xC5, 0xFF, 0xBF, 0xFF,
0282     0xF7, 0xFF, 0x88, 0xFF, 0x66, 0x02, 0x28, 0x02,
0283     0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0284 };
0285 static const __u8 cx_inits_320[] = {
0286     0x7f, 0x7f, 0x40, 0x01, 0xf0, 0x00, 0x02, 0x01,
0287     0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x02, 0x01,
0288     0x65, 0x45, 0xfa, 0x4c, 0x2c, 0xdf, 0xb9, 0x81,
0289     0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0290     0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
0291     0xf5, 0xff, 0x6d, 0xff, 0xf6, 0x01, 0x43, 0x02,
0292     0xd3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0293 };
0294 static const __u8 cx_inits_352[] = {
0295     0x2e, 0x7c, 0x60, 0x01, 0x20, 0x01, 0x05, 0x03,
0296     0x00, 0x06, 0x03, 0x06, 0x1b, 0x10, 0x05, 0x3b,
0297     0x30, 0x25, 0x18, 0x25, 0x08, 0x30, 0x03, 0x25,
0298     0x3b, 0x30, 0x25, 0x1b, 0x10, 0x05, 0x00, 0x00,
0299     0xe3, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
0300     0xf5, 0xff, 0x6b, 0xff, 0xee, 0x01, 0x43, 0x02,
0301     0xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0302 };
0303 static const __u8 cx_inits_640[] = {
0304     0x7e, 0x7e, 0x80, 0x02, 0xe0, 0x01, 0x01, 0x01,
0305     0x00, 0x02, 0x01, 0x02, 0x10, 0x30, 0x01, 0x01,
0306     0x65, 0x45, 0xf7, 0x52, 0x2c, 0xdf, 0xb9, 0x81,
0307     0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0308     0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
0309     0xf6, 0xff, 0x7b, 0xff, 0x01, 0x02, 0x43, 0x02,
0310     0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0311 };
0312 
0313 static void cx11646_initsize(struct gspca_dev *gspca_dev)
0314 {
0315     const __u8 *cxinit;
0316     static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 };
0317     static const __u8 reg17[] =
0318             { 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 };
0319 
0320     switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
0321     case 0:
0322         cxinit = cx_inits_640;
0323         break;
0324     case 1:
0325         cxinit = cx_inits_352;
0326         break;
0327     default:
0328 /*  case 2: */
0329         cxinit = cx_inits_320;
0330         break;
0331     case 3:
0332         cxinit = cx_inits_176;
0333         break;
0334     }
0335     reg_w_val(gspca_dev, 0x009a, 0x01);
0336     reg_w_val(gspca_dev, 0x0010, 0x10);
0337     reg_w(gspca_dev, 0x0012, reg12, 5);
0338     reg_w(gspca_dev, 0x0017, reg17, 8);
0339     reg_w_val(gspca_dev, 0x00c0, 0x00);
0340     reg_w_val(gspca_dev, 0x00c1, 0x04);
0341     reg_w_val(gspca_dev, 0x00c2, 0x04);
0342 
0343     reg_w(gspca_dev, 0x0061, cxinit, 8);
0344     cxinit += 8;
0345     reg_w(gspca_dev, 0x00ca, cxinit, 8);
0346     cxinit += 8;
0347     reg_w(gspca_dev, 0x00d2, cxinit, 8);
0348     cxinit += 8;
0349     reg_w(gspca_dev, 0x00da, cxinit, 6);
0350     cxinit += 8;
0351     reg_w(gspca_dev, 0x0041, cxinit, 8);
0352     cxinit += 8;
0353     reg_w(gspca_dev, 0x0049, cxinit, 8);
0354     cxinit += 8;
0355     reg_w(gspca_dev, 0x0051, cxinit, 2);
0356 
0357     reg_r(gspca_dev, 0x0010, 1);
0358 }
0359 
0360 static const __u8 cx_jpeg_init[][8] = {
0361     {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x15},   /* 1 */
0362     {0x0f, 0x10, 0x12, 0x10, 0x0d, 0x15, 0x12, 0x11},
0363     {0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35, 0x22},
0364     {0x20, 0x1d, 0x1d, 0x20, 0x41, 0x2e, 0x31, 0x26},
0365     {0x35, 0x4d, 0x43, 0x51, 0x4f, 0x4b, 0x43, 0x4a},
0366     {0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A, 0x73},
0367     {0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73, 0x7D},
0368     {0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95, 0xA0},
0369     {0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83, 0x01},
0370     {0x15, 0x0F, 0x10, 0x12, 0x10, 0x0D, 0x15, 0x12},
0371     {0x11, 0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35},
0372     {0x22, 0x20, 0x1D, 0x1D, 0x20, 0x41, 0x2E, 0x31},
0373     {0x26, 0x35, 0x4D, 0x43, 0x51, 0x4F, 0x4B, 0x43},
0374     {0x4A, 0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A},
0375     {0x73, 0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73},
0376     {0x7D, 0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95},
0377     {0xA0, 0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83},
0378     {0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05},
0379     {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00},
0380     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02},
0381     {0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A},
0382     {0x0B, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01},
0383     {0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00},
0384     {0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05},
0385     {0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00},
0386     {0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05},
0387     {0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01},
0388     {0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21},
0389     {0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22},
0390     {0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23},
0391     {0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24},
0392     {0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17},
0393     {0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29},
0394     {0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A},
0395     {0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A},
0396     {0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A},
0397     {0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A},
0398     {0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A},
0399     {0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A},
0400     {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99},
0401     {0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8},
0402     {0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7},
0403     {0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6},
0404     {0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5},
0405     {0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3},
0406     {0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1},
0407     {0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9},
0408     {0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04},
0409     {0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01},
0410     {0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04},
0411     {0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07},
0412     {0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14},
0413     {0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33},
0414     {0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16},
0415     {0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19},
0416     {0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36},
0417     {0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46},
0418     {0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56},
0419     {0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66},
0420     {0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76},
0421     {0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85},
0422     {0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94},
0423     {0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3},
0424     {0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2},
0425     {0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA},
0426     {0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9},
0427     {0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8},
0428     {0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7},
0429     {0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6},
0430     {0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0x20, 0x00, 0x1F},
0431     {0x02, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00},
0432     {0x00, 0x00, 0x11, 0x00, 0x11, 0x22, 0x00, 0x22},
0433     {0x22, 0x11, 0x22, 0x22, 0x11, 0x33, 0x33, 0x11},
0434     {0x44, 0x66, 0x22, 0x55, 0x66, 0xFF, 0xDD, 0x00},
0435     {0x04, 0x00, 0x14, 0xFF, 0xC0, 0x00, 0x11, 0x08},
0436     {0x00, 0xF0, 0x01, 0x40, 0x03, 0x00, 0x21, 0x00},
0437     {0x01, 0x11, 0x01, 0x02, 0x11, 0x01, 0xFF, 0xDA},
0438     {0x00, 0x0C, 0x03, 0x00, 0x00, 0x01, 0x11, 0x02},
0439     {0x11, 0x00, 0x3F, 0x00, 0xFF, 0xD9, 0x00, 0x00}    /* 79 */
0440 };
0441 
0442 
0443 static const __u8 cxjpeg_640[][8] = {
0444     {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x10},   /* 1 */
0445     {0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d},
0446     {0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a},
0447     {0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d},
0448     {0x28, 0x3a, 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38},
0449     {0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57},
0450     {0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F},
0451     {0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79},
0452     {0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0x01},
0453     {0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E},
0454     {0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28},
0455     {0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25},
0456     {0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33},
0457     {0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44},
0458     {0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57},
0459     {0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71},
0460     {0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63},
0461     {0xFF, 0x20, 0x00, 0x1F, 0x00, 0x83, 0x00, 0x00},
0462     {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
0463     {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
0464     {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
0465     {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x28, 0xFF},
0466     {0xC0, 0x00, 0x11, 0x08, 0x01, 0xE0, 0x02, 0x80},
0467     {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
0468     {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
0469     {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
0470     {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}    /* 27 */
0471 };
0472 static const __u8 cxjpeg_352[][8] = {
0473     {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
0474     {0x09, 0x09, 0x0b, 0x09, 0x08, 0x0D, 0x0b, 0x0a},
0475     {0x0b, 0x0e, 0x0d, 0x0d, 0x0f, 0x13, 0x1f, 0x14},
0476     {0x13, 0x11, 0x11, 0x13, 0x26, 0x1b, 0x1d, 0x17},
0477     {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
0478     {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
0479     {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
0480     {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
0481     {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
0482     {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
0483     {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
0484     {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
0485     {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
0486     {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
0487     {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
0488     {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
0489     {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
0490     {0xFF, 0x20, 0x00, 0x1F, 0x01, 0x83, 0x00, 0x00},
0491     {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
0492     {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
0493     {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
0494     {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x16, 0xFF},
0495     {0xC0, 0x00, 0x11, 0x08, 0x01, 0x20, 0x01, 0x60},
0496     {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
0497     {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
0498     {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
0499     {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
0500 };
0501 static const __u8 cxjpeg_320[][8] = {
0502     {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x05},
0503     {0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04},
0504     {0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08},
0505     {0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, 0x09},
0506     {0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0f, 0x11},
0507     {0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14, 0x1A},
0508     {0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A, 0x1D},
0509     {0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22, 0x24},
0510     {0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E, 0x01},
0511     {0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04},
0512     {0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0C},
0513     {0x08, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0B, 0x0B},
0514     {0x09, 0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0F},
0515     {0x11, 0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14},
0516     {0x1A, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A},
0517     {0x1D, 0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22},
0518     {0x24, 0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E},
0519     {0xFF, 0x20, 0x00, 0x1F, 0x02, 0x0C, 0x00, 0x00},
0520     {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
0521     {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
0522     {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
0523     {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x14, 0xFF},
0524     {0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01, 0x40},
0525     {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
0526     {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
0527     {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
0528     {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}    /* 27 */
0529 };
0530 static const __u8 cxjpeg_176[][8] = {
0531     {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
0532     {0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B, 0x0A},
0533     {0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F, 0x14},
0534     {0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D, 0x17},
0535     {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
0536     {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
0537     {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
0538     {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
0539     {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
0540     {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
0541     {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
0542     {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
0543     {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
0544     {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
0545     {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
0546     {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
0547     {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
0548     {0xFF, 0x20, 0x00, 0x1F, 0x03, 0xA1, 0x00, 0x00},
0549     {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
0550     {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
0551     {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
0552     {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x0B, 0xFF},
0553     {0xC0, 0x00, 0x11, 0x08, 0x00, 0x90, 0x00, 0xB0},
0554     {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
0555     {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
0556     {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
0557     {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
0558 };
0559 /* 640 take with the zcx30x part */
0560 static const __u8 cxjpeg_qtable[][8] = {
0561     {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x08},
0562     {0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07},
0563     {0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, 0x0a},
0564     {0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13, 0x0f},
0565     {0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a, 0x1c},
0566     {0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22, 0x2c},
0567     {0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c, 0x30},
0568     {0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39, 0x3d},
0569     {0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32, 0x01},
0570     {0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0a},
0571     {0x0a, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32},
0572     {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
0573     {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
0574     {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
0575     {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
0576     {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
0577     {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
0578     {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}    /* 18 */
0579 };
0580 
0581 
0582 static void cx11646_jpegInit(struct gspca_dev*gspca_dev)
0583 {
0584     int i;
0585     int length;
0586 
0587     reg_w_val(gspca_dev, 0x00c0, 0x01);
0588     reg_w_val(gspca_dev, 0x00c3, 0x00);
0589     reg_w_val(gspca_dev, 0x00c0, 0x00);
0590     reg_r(gspca_dev, 0x0001, 1);
0591     length = 8;
0592     for (i = 0; i < 79; i++) {
0593         if (i == 78)
0594             length = 6;
0595         reg_w(gspca_dev, 0x0008, cx_jpeg_init[i], length);
0596     }
0597     reg_r(gspca_dev, 0x0002, 1);
0598     reg_w_val(gspca_dev, 0x0055, 0x14);
0599 }
0600 
0601 static const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 };
0602 static const __u8 regE5_8[] =
0603         { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
0604 static const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 };
0605 static const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 };
0606 static const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 };
0607 static const __u8 reg51[] = { 0x77, 0x03 };
0608 #define reg70 0x03
0609 
0610 static void cx11646_jpeg(struct gspca_dev*gspca_dev)
0611 {
0612     int i;
0613     int length;
0614     __u8 Reg55;
0615     int retry;
0616 
0617     reg_w_val(gspca_dev, 0x00c0, 0x01);
0618     reg_w_val(gspca_dev, 0x00c3, 0x00);
0619     reg_w_val(gspca_dev, 0x00c0, 0x00);
0620     reg_r(gspca_dev, 0x0001, 1);
0621     length = 8;
0622     switch (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv) {
0623     case 0:
0624         for (i = 0; i < 27; i++) {
0625             if (i == 26)
0626                 length = 2;
0627             reg_w(gspca_dev, 0x0008, cxjpeg_640[i], length);
0628         }
0629         Reg55 = 0x28;
0630         break;
0631     case 1:
0632         for (i = 0; i < 27; i++) {
0633             if (i == 26)
0634                 length = 2;
0635             reg_w(gspca_dev, 0x0008, cxjpeg_352[i], length);
0636         }
0637         Reg55 = 0x16;
0638         break;
0639     default:
0640 /*  case 2: */
0641         for (i = 0; i < 27; i++) {
0642             if (i == 26)
0643                 length = 2;
0644             reg_w(gspca_dev, 0x0008, cxjpeg_320[i], length);
0645         }
0646         Reg55 = 0x14;
0647         break;
0648     case 3:
0649         for (i = 0; i < 27; i++) {
0650             if (i == 26)
0651                 length = 2;
0652             reg_w(gspca_dev, 0x0008, cxjpeg_176[i], length);
0653         }
0654         Reg55 = 0x0B;
0655         break;
0656     }
0657 
0658     reg_r(gspca_dev, 0x0002, 1);
0659     reg_w_val(gspca_dev, 0x0055, Reg55);
0660     reg_r(gspca_dev, 0x0002, 1);
0661     reg_w(gspca_dev, 0x0010, reg10, 2);
0662     reg_w_val(gspca_dev, 0x0054, 0x02);
0663     reg_w_val(gspca_dev, 0x0054, 0x01);
0664     reg_w_val(gspca_dev, 0x0000, 0x94);
0665     reg_w_val(gspca_dev, 0x0053, 0xc0);
0666     reg_w_val(gspca_dev, 0x00fc, 0xe1);
0667     reg_w_val(gspca_dev, 0x0000, 0x00);
0668     /* wait for completion */
0669     retry = 50;
0670     do {
0671         reg_r(gspca_dev, 0x0002, 1);
0672                             /* 0x07 until 0x00 */
0673         if (gspca_dev->usb_buf[0] == 0x00)
0674             break;
0675         reg_w_val(gspca_dev, 0x0053, 0x00);
0676     } while (--retry);
0677     if (retry == 0)
0678         gspca_err(gspca_dev, "Damned Errors sending jpeg Table\n");
0679     /* send the qtable now */
0680     reg_r(gspca_dev, 0x0001, 1);        /* -> 0x18 */
0681     length = 8;
0682     for (i = 0; i < 18; i++) {
0683         if (i == 17)
0684             length = 2;
0685         reg_w(gspca_dev, 0x0008, cxjpeg_qtable[i], length);
0686 
0687     }
0688     reg_r(gspca_dev, 0x0002, 1);    /* 0x00 */
0689     reg_r(gspca_dev, 0x0053, 1);    /* 0x00 */
0690     reg_w_val(gspca_dev, 0x0054, 0x02);
0691     reg_w_val(gspca_dev, 0x0054, 0x01);
0692     reg_w_val(gspca_dev, 0x0000, 0x94);
0693     reg_w_val(gspca_dev, 0x0053, 0xc0);
0694 
0695     reg_r(gspca_dev, 0x0038, 1);        /* 0x40 */
0696     reg_r(gspca_dev, 0x0038, 1);        /* 0x40 */
0697     reg_r(gspca_dev, 0x001f, 1);        /* 0x38 */
0698     reg_w(gspca_dev, 0x0012, reg12, 5);
0699     reg_w(gspca_dev, 0x00e5, regE5_8, 8);
0700     reg_r(gspca_dev, 0x00e8, 8);
0701     reg_w(gspca_dev, 0x00e5, regE5a, 4);
0702     reg_r(gspca_dev, 0x00e8, 1);        /* 0x00 */
0703     reg_w_val(gspca_dev, 0x009a, 0x01);
0704     reg_w(gspca_dev, 0x00e5, regE5b, 4);
0705     reg_r(gspca_dev, 0x00e8, 1);        /* 0x00 */
0706     reg_w(gspca_dev, 0x00e5, regE5c, 4);
0707     reg_r(gspca_dev, 0x00e8, 1);        /* 0x00 */
0708 
0709     reg_w(gspca_dev, 0x0051, reg51, 2);
0710     reg_w(gspca_dev, 0x0010, reg10, 2);
0711     reg_w_val(gspca_dev, 0x0070, reg70);
0712 }
0713 
0714 static void cx11646_init1(struct gspca_dev *gspca_dev)
0715 {
0716     int i = 0;
0717 
0718     reg_w_val(gspca_dev, 0x0010, 0x00);
0719     reg_w_val(gspca_dev, 0x0053, 0x00);
0720     reg_w_val(gspca_dev, 0x0052, 0x00);
0721     reg_w_val(gspca_dev, 0x009b, 0x2f);
0722     reg_w_val(gspca_dev, 0x009c, 0x10);
0723     reg_r(gspca_dev, 0x0098, 1);
0724     reg_w_val(gspca_dev, 0x0098, 0x40);
0725     reg_r(gspca_dev, 0x0099, 1);
0726     reg_w_val(gspca_dev, 0x0099, 0x07);
0727     reg_w_val(gspca_dev, 0x0039, 0x40);
0728     reg_w_val(gspca_dev, 0x003c, 0xff);
0729     reg_w_val(gspca_dev, 0x003f, 0x1f);
0730     reg_w_val(gspca_dev, 0x003d, 0x40);
0731 /*  reg_w_val(gspca_dev, 0x003d, 0x60); */
0732     reg_r(gspca_dev, 0x0099, 1);            /* ->0x07 */
0733 
0734     while (cx_sensor_init[i][0]) {
0735         reg_w_val(gspca_dev, 0x00e5, cx_sensor_init[i][0]);
0736         reg_r(gspca_dev, 0x00e8, 1);        /* -> 0x00 */
0737         if (i == 1) {
0738             reg_w_val(gspca_dev, 0x00ed, 0x01);
0739             reg_r(gspca_dev, 0x00ed, 1);    /* -> 0x01 */
0740         }
0741         i++;
0742     }
0743     reg_w_val(gspca_dev, 0x00c3, 0x00);
0744 }
0745 
0746 /* this function is called at probe time */
0747 static int sd_config(struct gspca_dev *gspca_dev,
0748             const struct usb_device_id *id)
0749 {
0750     struct cam *cam;
0751 
0752     cam = &gspca_dev->cam;
0753     cam->cam_mode = vga_mode;
0754     cam->nmodes = ARRAY_SIZE(vga_mode);
0755     return 0;
0756 }
0757 
0758 /* this function is called at probe and resume time */
0759 static int sd_init(struct gspca_dev *gspca_dev)
0760 {
0761     cx11646_init1(gspca_dev);
0762     cx11646_initsize(gspca_dev);
0763     cx11646_fw(gspca_dev);
0764     cx_sensor(gspca_dev);
0765     cx11646_jpegInit(gspca_dev);
0766     return 0;
0767 }
0768 
0769 static int sd_start(struct gspca_dev *gspca_dev)
0770 {
0771     struct sd *sd = (struct sd *) gspca_dev;
0772 
0773     /* create the JPEG header */
0774     jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
0775             gspca_dev->pixfmt.width,
0776             0x22);      /* JPEG 411 */
0777     jpeg_set_qual(sd->jpeg_hdr, QUALITY);
0778 
0779     cx11646_initsize(gspca_dev);
0780     cx11646_fw(gspca_dev);
0781     cx_sensor(gspca_dev);
0782     cx11646_jpeg(gspca_dev);
0783     return 0;
0784 }
0785 
0786 /* called on streamoff with alt 0 and on disconnect */
0787 static void sd_stop0(struct gspca_dev *gspca_dev)
0788 {
0789     int retry = 50;
0790 
0791     if (!gspca_dev->present)
0792         return;
0793     reg_w_val(gspca_dev, 0x0000, 0x00);
0794     reg_r(gspca_dev, 0x0002, 1);
0795     reg_w_val(gspca_dev, 0x0053, 0x00);
0796 
0797     while (retry--) {
0798 /*      reg_r(gspca_dev, 0x0002, 1);*/
0799         reg_r(gspca_dev, 0x0053, 1);
0800         if (gspca_dev->usb_buf[0] == 0)
0801             break;
0802     }
0803     reg_w_val(gspca_dev, 0x0000, 0x00);
0804     reg_r(gspca_dev, 0x0002, 1);
0805 
0806     reg_w_val(gspca_dev, 0x0010, 0x00);
0807     reg_r(gspca_dev, 0x0033, 1);
0808     reg_w_val(gspca_dev, 0x00fc, 0xe0);
0809 }
0810 
0811 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
0812             u8 *data,           /* isoc packet */
0813             int len)            /* iso packet length */
0814 {
0815     struct sd *sd = (struct sd *) gspca_dev;
0816 
0817     if (data[0] == 0xff && data[1] == 0xd8) {
0818 
0819         /* start of frame */
0820         gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
0821 
0822         /* put the JPEG header in the new frame */
0823         gspca_frame_add(gspca_dev, FIRST_PACKET,
0824                 sd->jpeg_hdr, JPEG_HDR_SZ);
0825         data += 2;
0826         len -= 2;
0827     }
0828     gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
0829 }
0830 
0831 static void setbrightness(struct gspca_dev *gspca_dev, s32 val, s32 sat)
0832 {
0833     __u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
0834     __u8 reg51c[2];
0835 
0836     regE5cbx[2] = val;
0837     reg_w(gspca_dev, 0x00e5, regE5cbx, 8);
0838     reg_r(gspca_dev, 0x00e8, 8);
0839     reg_w(gspca_dev, 0x00e5, regE5c, 4);
0840     reg_r(gspca_dev, 0x00e8, 1);        /* 0x00 */
0841 
0842     reg51c[0] = 0x77;
0843     reg51c[1] = sat;
0844     reg_w(gspca_dev, 0x0051, reg51c, 2);
0845     reg_w(gspca_dev, 0x0010, reg10, 2);
0846     reg_w_val(gspca_dev, 0x0070, reg70);
0847 }
0848 
0849 static void setcontrast(struct gspca_dev *gspca_dev, s32 val, s32 sat)
0850 {
0851     __u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 };   /* seem MSB */
0852 /*  __u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01};     * LSB */
0853     __u8 reg51c[2];
0854 
0855     regE5acx[2] = val;
0856     reg_w(gspca_dev, 0x00e5, regE5acx, 4);
0857     reg_r(gspca_dev, 0x00e8, 1);        /* 0x00 */
0858     reg51c[0] = 0x77;
0859     reg51c[1] = sat;
0860     reg_w(gspca_dev, 0x0051, reg51c, 2);
0861     reg_w(gspca_dev, 0x0010, reg10, 2);
0862     reg_w_val(gspca_dev, 0x0070, reg70);
0863 }
0864 
0865 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
0866 {
0867     struct gspca_dev *gspca_dev =
0868         container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
0869     struct sd *sd = (struct sd *)gspca_dev;
0870 
0871     gspca_dev->usb_err = 0;
0872 
0873     if (!gspca_dev->streaming)
0874         return 0;
0875 
0876     switch (ctrl->id) {
0877     case V4L2_CID_BRIGHTNESS:
0878         setbrightness(gspca_dev, ctrl->val, sd->sat->cur.val);
0879         break;
0880     case V4L2_CID_CONTRAST:
0881         setcontrast(gspca_dev, ctrl->val, sd->sat->cur.val);
0882         break;
0883     case V4L2_CID_SATURATION:
0884         setbrightness(gspca_dev, sd->brightness->cur.val, ctrl->val);
0885         setcontrast(gspca_dev, sd->contrast->cur.val, ctrl->val);
0886         break;
0887     }
0888     return gspca_dev->usb_err;
0889 }
0890 
0891 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
0892     .s_ctrl = sd_s_ctrl,
0893 };
0894 
0895 static int sd_init_controls(struct gspca_dev *gspca_dev)
0896 {
0897     struct sd *sd = (struct sd *)gspca_dev;
0898     struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
0899 
0900     gspca_dev->vdev.ctrl_handler = hdl;
0901     v4l2_ctrl_handler_init(hdl, 3);
0902     sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0903             V4L2_CID_BRIGHTNESS, 0, 255, 1, 0xd4);
0904     sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0905             V4L2_CID_CONTRAST, 0x0a, 0x1f, 1, 0x0c);
0906     sd->sat = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
0907             V4L2_CID_SATURATION, 0, 7, 1, 3);
0908     if (hdl->error) {
0909         pr_err("Could not initialize controls\n");
0910         return hdl->error;
0911     }
0912     return 0;
0913 }
0914 
0915 /* sub-driver description */
0916 static const struct sd_desc sd_desc = {
0917     .name = MODULE_NAME,
0918     .config = sd_config,
0919     .init = sd_init,
0920     .init_controls = sd_init_controls,
0921     .start = sd_start,
0922     .stop0 = sd_stop0,
0923     .pkt_scan = sd_pkt_scan,
0924 };
0925 
0926 /* -- module initialisation -- */
0927 static const struct usb_device_id device_table[] = {
0928     {USB_DEVICE(0x0572, 0x0041)},
0929     {}
0930 };
0931 MODULE_DEVICE_TABLE(usb, device_table);
0932 
0933 /* -- device connect -- */
0934 static int sd_probe(struct usb_interface *intf,
0935             const struct usb_device_id *id)
0936 {
0937     return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
0938                 THIS_MODULE);
0939 }
0940 
0941 static struct usb_driver sd_driver = {
0942     .name = MODULE_NAME,
0943     .id_table = device_table,
0944     .probe = sd_probe,
0945     .disconnect = gspca_disconnect,
0946 #ifdef CONFIG_PM
0947     .suspend = gspca_suspend,
0948     .resume = gspca_resume,
0949     .reset_resume = gspca_resume,
0950 #endif
0951 };
0952 
0953 module_usb_driver(sd_driver);