linux/drivers/media/usb/gspca/conex.c
<<
>>
Prefs
   1/*
   2 *              Connexant Cx11646 library
   3 *              Copyright (C) 2004 Michel Xhaard mxhaard@magic.fr
   4 *
   5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20 */
  21
  22#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  23
  24#define MODULE_NAME "conex"
  25
  26#include "gspca.h"
  27#define CONEX_CAM 1             /* special JPEG header */
  28#include "jpeg.h"
  29
  30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
  31MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver");
  32MODULE_LICENSE("GPL");
  33
  34#define QUALITY 50
  35
  36/* specific webcam descriptor */
  37struct sd {
  38        struct gspca_dev gspca_dev;     /* !! must be the first item */
  39        struct v4l2_ctrl *brightness;
  40        struct v4l2_ctrl *contrast;
  41        struct v4l2_ctrl *sat;
  42
  43        u8 jpeg_hdr[JPEG_HDR_SZ];
  44};
  45
  46static const struct v4l2_pix_format vga_mode[] = {
  47        {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  48                .bytesperline = 176,
  49                .sizeimage = 176 * 144 * 3 / 8 + 590,
  50                .colorspace = V4L2_COLORSPACE_JPEG,
  51                .priv = 3},
  52        {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  53                .bytesperline = 320,
  54                .sizeimage = 320 * 240 * 3 / 8 + 590,
  55                .colorspace = V4L2_COLORSPACE_JPEG,
  56                .priv = 2},
  57        {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  58                .bytesperline = 352,
  59                .sizeimage = 352 * 288 * 3 / 8 + 590,
  60                .colorspace = V4L2_COLORSPACE_JPEG,
  61                .priv = 1},
  62        {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  63                .bytesperline = 640,
  64                .sizeimage = 640 * 480 * 3 / 8 + 590,
  65                .colorspace = V4L2_COLORSPACE_JPEG,
  66                .priv = 0},
  67};
  68
  69/* the read bytes are found in gspca_dev->usb_buf */
  70static void reg_r(struct gspca_dev *gspca_dev,
  71                  __u16 index,
  72                  __u16 len)
  73{
  74        struct usb_device *dev = gspca_dev->dev;
  75
  76        if (len > USB_BUF_SZ) {
  77                PERR("reg_r: buffer overflow\n");
  78                return;
  79        }
  80
  81        usb_control_msg(dev,
  82                        usb_rcvctrlpipe(dev, 0),
  83                        0,
  84                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  85                        0,
  86                        index, gspca_dev->usb_buf, len,
  87                        500);
  88        PDEBUG(D_USBI, "reg read [%02x] -> %02x ..",
  89                        index, gspca_dev->usb_buf[0]);
  90}
  91
  92/* the bytes to write are in gspca_dev->usb_buf */
  93static void reg_w_val(struct gspca_dev *gspca_dev,
  94                        __u16 index,
  95                        __u8 val)
  96{
  97        struct usb_device *dev = gspca_dev->dev;
  98
  99        gspca_dev->usb_buf[0] = val;
 100        usb_control_msg(dev,
 101                        usb_sndctrlpipe(dev, 0),
 102                        0,
 103                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 104                        0,
 105                        index, gspca_dev->usb_buf, 1, 500);
 106}
 107
 108static void reg_w(struct gspca_dev *gspca_dev,
 109                  __u16 index,
 110                  const __u8 *buffer,
 111                  __u16 len)
 112{
 113        struct usb_device *dev = gspca_dev->dev;
 114
 115        if (len > USB_BUF_SZ) {
 116                PERR("reg_w: buffer overflow\n");
 117                return;
 118        }
 119        PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
 120
 121        memcpy(gspca_dev->usb_buf, buffer, len);
 122        usb_control_msg(dev,
 123                        usb_sndctrlpipe(dev, 0),
 124                        0,
 125                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 126                        0,
 127                        index, gspca_dev->usb_buf, len, 500);
 128}
 129
 130static const __u8 cx_sensor_init[][4] = {
 131        {0x88, 0x11, 0x01, 0x01},
 132        {0x88, 0x12, 0x70, 0x01},
 133        {0x88, 0x0f, 0x00, 0x01},
 134        {0x88, 0x05, 0x01, 0x01},
 135        {}
 136};
 137
 138static const __u8 cx11646_fw1[][3] = {
 139        {0x00, 0x02, 0x00},
 140        {0x01, 0x43, 0x00},
 141        {0x02, 0xA7, 0x00},
 142        {0x03, 0x8B, 0x01},
 143        {0x04, 0xE9, 0x02},
 144        {0x05, 0x08, 0x04},
 145        {0x06, 0x08, 0x05},
 146        {0x07, 0x07, 0x06},
 147        {0x08, 0xE7, 0x06},
 148        {0x09, 0xC6, 0x07},
 149        {0x0A, 0x86, 0x08},
 150        {0x0B, 0x46, 0x09},
 151        {0x0C, 0x05, 0x0A},
 152        {0x0D, 0xA5, 0x0A},
 153        {0x0E, 0x45, 0x0B},
 154        {0x0F, 0xE5, 0x0B},
 155        {0x10, 0x85, 0x0C},
 156        {0x11, 0x25, 0x0D},
 157        {0x12, 0xC4, 0x0D},
 158        {0x13, 0x45, 0x0E},
 159        {0x14, 0xE4, 0x0E},
 160        {0x15, 0x64, 0x0F},
 161        {0x16, 0xE4, 0x0F},
 162        {0x17, 0x64, 0x10},
 163        {0x18, 0xE4, 0x10},
 164        {0x19, 0x64, 0x11},
 165        {0x1A, 0xE4, 0x11},
 166        {0x1B, 0x64, 0x12},
 167        {0x1C, 0xE3, 0x12},
 168        {0x1D, 0x44, 0x13},
 169        {0x1E, 0xC3, 0x13},
 170        {0x1F, 0x24, 0x14},
 171        {0x20, 0xA3, 0x14},
 172        {0x21, 0x04, 0x15},
 173        {0x22, 0x83, 0x15},
 174        {0x23, 0xE3, 0x15},
 175        {0x24, 0x43, 0x16},
 176        {0x25, 0xA4, 0x16},
 177        {0x26, 0x23, 0x17},
 178        {0x27, 0x83, 0x17},
 179        {0x28, 0xE3, 0x17},
 180        {0x29, 0x43, 0x18},
 181        {0x2A, 0xA3, 0x18},
 182        {0x2B, 0x03, 0x19},
 183        {0x2C, 0x63, 0x19},
 184        {0x2D, 0xC3, 0x19},
 185        {0x2E, 0x22, 0x1A},
 186        {0x2F, 0x63, 0x1A},
 187        {0x30, 0xC3, 0x1A},
 188        {0x31, 0x23, 0x1B},
 189        {0x32, 0x83, 0x1B},
 190        {0x33, 0xE2, 0x1B},
 191        {0x34, 0x23, 0x1C},
 192        {0x35, 0x83, 0x1C},
 193        {0x36, 0xE2, 0x1C},
 194        {0x37, 0x23, 0x1D},
 195        {0x38, 0x83, 0x1D},
 196        {0x39, 0xE2, 0x1D},
 197        {0x3A, 0x23, 0x1E},
 198        {0x3B, 0x82, 0x1E},
 199        {0x3C, 0xC3, 0x1E},
 200        {0x3D, 0x22, 0x1F},
 201        {0x3E, 0x63, 0x1F},
 202        {0x3F, 0xC1, 0x1F},
 203        {}
 204};
 205static void cx11646_fw(struct gspca_dev*gspca_dev)
 206{
 207        int i = 0;
 208
 209        reg_w_val(gspca_dev, 0x006a, 0x02);
 210        while (cx11646_fw1[i][1]) {
 211                reg_w(gspca_dev, 0x006b, cx11646_fw1[i], 3);
 212                i++;
 213        }
 214        reg_w_val(gspca_dev, 0x006a, 0x00);
 215}
 216
 217static const __u8 cxsensor[] = {
 218        0x88, 0x12, 0x70, 0x01,
 219        0x88, 0x0d, 0x02, 0x01,
 220        0x88, 0x0f, 0x00, 0x01,
 221        0x88, 0x03, 0x71, 0x01, 0x88, 0x04, 0x00, 0x01, /* 3 */
 222        0x88, 0x02, 0x10, 0x01,
 223        0x88, 0x00, 0xD4, 0x01, 0x88, 0x01, 0x01, 0x01, /* 5 */
 224        0x88, 0x0B, 0x00, 0x01,
 225        0x88, 0x0A, 0x0A, 0x01,
 226        0x88, 0x00, 0x08, 0x01, 0x88, 0x01, 0x00, 0x01, /* 8 */
 227        0x88, 0x05, 0x01, 0x01,
 228        0xA1, 0x18, 0x00, 0x01,
 229        0x00
 230};
 231
 232static const __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff };
 233static const __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff };
 234static const __u8 reg10[] = { 0xb1, 0xb1 };
 235static const __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e };        /* 640 */
 236static const __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f };
 237        /* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */
 238static const __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 };
 239                                        /* 320{0x04,0x0c,0x05,0x0f}; //320 */
 240static const __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 };        /* 176 */
 241static const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff };
 242
 243static void cx_sensor(struct gspca_dev*gspca_dev)
 244{
 245        int i = 0;
 246        int length;
 247        const __u8 *ptsensor = cxsensor;
 248
 249        reg_w(gspca_dev, 0x0020, reg20, 8);
 250        reg_w(gspca_dev, 0x0028, reg28, 8);
 251        reg_w(gspca_dev, 0x0010, reg10, 2);
 252        reg_w_val(gspca_dev, 0x0092, 0x03);
 253
 254        switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
 255        case 0:
 256                reg_w(gspca_dev, 0x0071, reg71a, 4);
 257                break;
 258        case 1:
 259                reg_w(gspca_dev, 0x0071, reg71b, 4);
 260                break;
 261        default:
 262/*      case 2: */
 263                reg_w(gspca_dev, 0x0071, reg71c, 4);
 264                break;
 265        case 3:
 266                reg_w(gspca_dev, 0x0071, reg71d, 4);
 267                break;
 268        }
 269        reg_w(gspca_dev, 0x007b, reg7b, 6);
 270        reg_w_val(gspca_dev, 0x00f8, 0x00);
 271        reg_w(gspca_dev, 0x0010, reg10, 2);
 272        reg_w_val(gspca_dev, 0x0098, 0x41);
 273        for (i = 0; i < 11; i++) {
 274                if (i == 3 || i == 5 || i == 8)
 275                        length = 8;
 276                else
 277                        length = 4;
 278                reg_w(gspca_dev, 0x00e5, ptsensor, length);
 279                if (length == 4)
 280                        reg_r(gspca_dev, 0x00e8, 1);
 281                else
 282                        reg_r(gspca_dev, 0x00e8, length);
 283                ptsensor += length;
 284        }
 285        reg_r(gspca_dev, 0x00e7, 8);
 286}
 287
 288static const __u8 cx_inits_176[] = {
 289        0x33, 0x81, 0xB0, 0x00, 0x90, 0x00, 0x0A, 0x03, /* 176x144 */
 290        0x00, 0x03, 0x03, 0x03, 0x1B, 0x05, 0x30, 0x03,
 291        0x65, 0x15, 0x18, 0x25, 0x03, 0x25, 0x08, 0x30,
 292        0x3B, 0x25, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
 293        0xDC, 0xFF, 0xEE, 0xFF, 0xC5, 0xFF, 0xBF, 0xFF,
 294        0xF7, 0xFF, 0x88, 0xFF, 0x66, 0x02, 0x28, 0x02,
 295        0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 296};
 297static const __u8 cx_inits_320[] = {
 298        0x7f, 0x7f, 0x40, 0x01, 0xf0, 0x00, 0x02, 0x01,
 299        0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x02, 0x01,
 300        0x65, 0x45, 0xfa, 0x4c, 0x2c, 0xdf, 0xb9, 0x81,
 301        0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
 302        0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
 303        0xf5, 0xff, 0x6d, 0xff, 0xf6, 0x01, 0x43, 0x02,
 304        0xd3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 305};
 306static const __u8 cx_inits_352[] = {
 307        0x2e, 0x7c, 0x60, 0x01, 0x20, 0x01, 0x05, 0x03,
 308        0x00, 0x06, 0x03, 0x06, 0x1b, 0x10, 0x05, 0x3b,
 309        0x30, 0x25, 0x18, 0x25, 0x08, 0x30, 0x03, 0x25,
 310        0x3b, 0x30, 0x25, 0x1b, 0x10, 0x05, 0x00, 0x00,
 311        0xe3, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
 312        0xf5, 0xff, 0x6b, 0xff, 0xee, 0x01, 0x43, 0x02,
 313        0xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 314};
 315static const __u8 cx_inits_640[] = {
 316        0x7e, 0x7e, 0x80, 0x02, 0xe0, 0x01, 0x01, 0x01,
 317        0x00, 0x02, 0x01, 0x02, 0x10, 0x30, 0x01, 0x01,
 318        0x65, 0x45, 0xf7, 0x52, 0x2c, 0xdf, 0xb9, 0x81,
 319        0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
 320        0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
 321        0xf6, 0xff, 0x7b, 0xff, 0x01, 0x02, 0x43, 0x02,
 322        0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 323};
 324
 325static void cx11646_initsize(struct gspca_dev *gspca_dev)
 326{
 327        const __u8 *cxinit;
 328        static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 };
 329        static const __u8 reg17[] =
 330                        { 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 };
 331
 332        switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
 333        case 0:
 334                cxinit = cx_inits_640;
 335                break;
 336        case 1:
 337                cxinit = cx_inits_352;
 338                break;
 339        default:
 340/*      case 2: */
 341                cxinit = cx_inits_320;
 342                break;
 343        case 3:
 344                cxinit = cx_inits_176;
 345                break;
 346        }
 347        reg_w_val(gspca_dev, 0x009a, 0x01);
 348        reg_w_val(gspca_dev, 0x0010, 0x10);
 349        reg_w(gspca_dev, 0x0012, reg12, 5);
 350        reg_w(gspca_dev, 0x0017, reg17, 8);
 351        reg_w_val(gspca_dev, 0x00c0, 0x00);
 352        reg_w_val(gspca_dev, 0x00c1, 0x04);
 353        reg_w_val(gspca_dev, 0x00c2, 0x04);
 354
 355        reg_w(gspca_dev, 0x0061, cxinit, 8);
 356        cxinit += 8;
 357        reg_w(gspca_dev, 0x00ca, cxinit, 8);
 358        cxinit += 8;
 359        reg_w(gspca_dev, 0x00d2, cxinit, 8);
 360        cxinit += 8;
 361        reg_w(gspca_dev, 0x00da, cxinit, 6);
 362        cxinit += 8;
 363        reg_w(gspca_dev, 0x0041, cxinit, 8);
 364        cxinit += 8;
 365        reg_w(gspca_dev, 0x0049, cxinit, 8);
 366        cxinit += 8;
 367        reg_w(gspca_dev, 0x0051, cxinit, 2);
 368
 369        reg_r(gspca_dev, 0x0010, 1);
 370}
 371
 372static const __u8 cx_jpeg_init[][8] = {
 373        {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x15},       /* 1 */
 374        {0x0f, 0x10, 0x12, 0x10, 0x0d, 0x15, 0x12, 0x11},
 375        {0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35, 0x22},
 376        {0x20, 0x1d, 0x1d, 0x20, 0x41, 0x2e, 0x31, 0x26},
 377        {0x35, 0x4d, 0x43, 0x51, 0x4f, 0x4b, 0x43, 0x4a},
 378        {0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A, 0x73},
 379        {0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73, 0x7D},
 380        {0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95, 0xA0},
 381        {0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83, 0x01},
 382        {0x15, 0x0F, 0x10, 0x12, 0x10, 0x0D, 0x15, 0x12},
 383        {0x11, 0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35},
 384        {0x22, 0x20, 0x1D, 0x1D, 0x20, 0x41, 0x2E, 0x31},
 385        {0x26, 0x35, 0x4D, 0x43, 0x51, 0x4F, 0x4B, 0x43},
 386        {0x4A, 0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A},
 387        {0x73, 0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73},
 388        {0x7D, 0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95},
 389        {0xA0, 0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83},
 390        {0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05},
 391        {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00},
 392        {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02},
 393        {0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A},
 394        {0x0B, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01},
 395        {0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00},
 396        {0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05},
 397        {0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00},
 398        {0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05},
 399        {0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01},
 400        {0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21},
 401        {0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22},
 402        {0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23},
 403        {0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24},
 404        {0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17},
 405        {0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29},
 406        {0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A},
 407        {0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A},
 408        {0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A},
 409        {0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A},
 410        {0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A},
 411        {0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A},
 412        {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99},
 413        {0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8},
 414        {0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7},
 415        {0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6},
 416        {0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5},
 417        {0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3},
 418        {0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1},
 419        {0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9},
 420        {0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04},
 421        {0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01},
 422        {0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04},
 423        {0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07},
 424        {0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14},
 425        {0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33},
 426        {0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16},
 427        {0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19},
 428        {0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36},
 429        {0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46},
 430        {0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56},
 431        {0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66},
 432        {0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76},
 433        {0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85},
 434        {0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94},
 435        {0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3},
 436        {0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2},
 437        {0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA},
 438        {0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9},
 439        {0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8},
 440        {0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7},
 441        {0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6},
 442        {0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0x20, 0x00, 0x1F},
 443        {0x02, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00},
 444        {0x00, 0x00, 0x11, 0x00, 0x11, 0x22, 0x00, 0x22},
 445        {0x22, 0x11, 0x22, 0x22, 0x11, 0x33, 0x33, 0x11},
 446        {0x44, 0x66, 0x22, 0x55, 0x66, 0xFF, 0xDD, 0x00},
 447        {0x04, 0x00, 0x14, 0xFF, 0xC0, 0x00, 0x11, 0x08},
 448        {0x00, 0xF0, 0x01, 0x40, 0x03, 0x00, 0x21, 0x00},
 449        {0x01, 0x11, 0x01, 0x02, 0x11, 0x01, 0xFF, 0xDA},
 450        {0x00, 0x0C, 0x03, 0x00, 0x00, 0x01, 0x11, 0x02},
 451        {0x11, 0x00, 0x3F, 0x00, 0xFF, 0xD9, 0x00, 0x00}        /* 79 */
 452};
 453
 454
 455static const __u8 cxjpeg_640[][8] = {
 456        {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x10},       /* 1 */
 457        {0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d},
 458        {0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a},
 459        {0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d},
 460        {0x28, 0x3a, 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38},
 461        {0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57},
 462        {0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F},
 463        {0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79},
 464        {0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0x01},
 465        {0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E},
 466        {0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28},
 467        {0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25},
 468        {0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33},
 469        {0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44},
 470        {0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57},
 471        {0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71},
 472        {0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63},
 473        {0xFF, 0x20, 0x00, 0x1F, 0x00, 0x83, 0x00, 0x00},
 474        {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
 475        {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
 476        {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
 477        {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x28, 0xFF},
 478        {0xC0, 0x00, 0x11, 0x08, 0x01, 0xE0, 0x02, 0x80},
 479        {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
 480        {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
 481        {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
 482        {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}        /* 27 */
 483};
 484static const __u8 cxjpeg_352[][8] = {
 485        {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
 486        {0x09, 0x09, 0x0b, 0x09, 0x08, 0x0D, 0x0b, 0x0a},
 487        {0x0b, 0x0e, 0x0d, 0x0d, 0x0f, 0x13, 0x1f, 0x14},
 488        {0x13, 0x11, 0x11, 0x13, 0x26, 0x1b, 0x1d, 0x17},
 489        {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
 490        {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
 491        {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
 492        {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
 493        {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
 494        {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
 495        {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
 496        {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
 497        {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
 498        {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
 499        {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
 500        {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
 501        {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
 502        {0xFF, 0x20, 0x00, 0x1F, 0x01, 0x83, 0x00, 0x00},
 503        {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
 504        {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
 505        {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
 506        {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x16, 0xFF},
 507        {0xC0, 0x00, 0x11, 0x08, 0x01, 0x20, 0x01, 0x60},
 508        {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
 509        {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
 510        {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
 511        {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
 512};
 513static const __u8 cxjpeg_320[][8] = {
 514        {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x05},
 515        {0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04},
 516        {0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08},
 517        {0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, 0x09},
 518        {0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0f, 0x11},
 519        {0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14, 0x1A},
 520        {0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A, 0x1D},
 521        {0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22, 0x24},
 522        {0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E, 0x01},
 523        {0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04},
 524        {0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0C},
 525        {0x08, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0B, 0x0B},
 526        {0x09, 0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0F},
 527        {0x11, 0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14},
 528        {0x1A, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A},
 529        {0x1D, 0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22},
 530        {0x24, 0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E},
 531        {0xFF, 0x20, 0x00, 0x1F, 0x02, 0x0C, 0x00, 0x00},
 532        {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
 533        {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
 534        {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
 535        {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x14, 0xFF},
 536        {0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01, 0x40},
 537        {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
 538        {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
 539        {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
 540        {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}        /* 27 */
 541};
 542static const __u8 cxjpeg_176[][8] = {
 543        {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
 544        {0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B, 0x0A},
 545        {0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F, 0x14},
 546        {0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D, 0x17},
 547        {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
 548        {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
 549        {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
 550        {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
 551        {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
 552        {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
 553        {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
 554        {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
 555        {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
 556        {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
 557        {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
 558        {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
 559        {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
 560        {0xFF, 0x20, 0x00, 0x1F, 0x03, 0xA1, 0x00, 0x00},
 561        {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
 562        {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
 563        {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
 564        {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x0B, 0xFF},
 565        {0xC0, 0x00, 0x11, 0x08, 0x00, 0x90, 0x00, 0xB0},
 566        {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
 567        {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
 568        {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
 569        {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
 570};
 571/* 640 take with the zcx30x part */
 572static const __u8 cxjpeg_qtable[][8] = {
 573        {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x08},
 574        {0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07},
 575        {0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, 0x0a},
 576        {0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13, 0x0f},
 577        {0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a, 0x1c},
 578        {0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22, 0x2c},
 579        {0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c, 0x30},
 580        {0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39, 0x3d},
 581        {0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32, 0x01},
 582        {0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0a},
 583        {0x0a, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32},
 584        {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
 585        {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
 586        {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
 587        {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
 588        {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
 589        {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
 590        {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}        /* 18 */
 591};
 592
 593
 594static void cx11646_jpegInit(struct gspca_dev*gspca_dev)
 595{
 596        int i;
 597        int length;
 598
 599        reg_w_val(gspca_dev, 0x00c0, 0x01);
 600        reg_w_val(gspca_dev, 0x00c3, 0x00);
 601        reg_w_val(gspca_dev, 0x00c0, 0x00);
 602        reg_r(gspca_dev, 0x0001, 1);
 603        length = 8;
 604        for (i = 0; i < 79; i++) {
 605                if (i == 78)
 606                        length = 6;
 607                reg_w(gspca_dev, 0x0008, cx_jpeg_init[i], length);
 608        }
 609        reg_r(gspca_dev, 0x0002, 1);
 610        reg_w_val(gspca_dev, 0x0055, 0x14);
 611}
 612
 613static const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 };
 614static const __u8 regE5_8[] =
 615                { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
 616static const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 };
 617static const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 };
 618static const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 };
 619static const __u8 reg51[] = { 0x77, 0x03 };
 620#define reg70 0x03
 621
 622static void cx11646_jpeg(struct gspca_dev*gspca_dev)
 623{
 624        int i;
 625        int length;
 626        __u8 Reg55;
 627        int retry;
 628
 629        reg_w_val(gspca_dev, 0x00c0, 0x01);
 630        reg_w_val(gspca_dev, 0x00c3, 0x00);
 631        reg_w_val(gspca_dev, 0x00c0, 0x00);
 632        reg_r(gspca_dev, 0x0001, 1);
 633        length = 8;
 634        switch (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv) {
 635        case 0:
 636                for (i = 0; i < 27; i++) {
 637                        if (i == 26)
 638                                length = 2;
 639                        reg_w(gspca_dev, 0x0008, cxjpeg_640[i], length);
 640                }
 641                Reg55 = 0x28;
 642                break;
 643        case 1:
 644                for (i = 0; i < 27; i++) {
 645                        if (i == 26)
 646                                length = 2;
 647                        reg_w(gspca_dev, 0x0008, cxjpeg_352[i], length);
 648                }
 649                Reg55 = 0x16;
 650                break;
 651        default:
 652/*      case 2: */
 653                for (i = 0; i < 27; i++) {
 654                        if (i == 26)
 655                                length = 2;
 656                        reg_w(gspca_dev, 0x0008, cxjpeg_320[i], length);
 657                }
 658                Reg55 = 0x14;
 659                break;
 660        case 3:
 661                for (i = 0; i < 27; i++) {
 662                        if (i == 26)
 663                                length = 2;
 664                        reg_w(gspca_dev, 0x0008, cxjpeg_176[i], length);
 665                }
 666                Reg55 = 0x0B;
 667                break;
 668        }
 669
 670        reg_r(gspca_dev, 0x0002, 1);
 671        reg_w_val(gspca_dev, 0x0055, Reg55);
 672        reg_r(gspca_dev, 0x0002, 1);
 673        reg_w(gspca_dev, 0x0010, reg10, 2);
 674        reg_w_val(gspca_dev, 0x0054, 0x02);
 675        reg_w_val(gspca_dev, 0x0054, 0x01);
 676        reg_w_val(gspca_dev, 0x0000, 0x94);
 677        reg_w_val(gspca_dev, 0x0053, 0xc0);
 678        reg_w_val(gspca_dev, 0x00fc, 0xe1);
 679        reg_w_val(gspca_dev, 0x0000, 0x00);
 680        /* wait for completion */
 681        retry = 50;
 682        do {
 683                reg_r(gspca_dev, 0x0002, 1);
 684                                                        /* 0x07 until 0x00 */
 685                if (gspca_dev->usb_buf[0] == 0x00)
 686                        break;
 687                reg_w_val(gspca_dev, 0x0053, 0x00);
 688        } while (--retry);
 689        if (retry == 0)
 690                PERR("Damned Errors sending jpeg Table");
 691        /* send the qtable now */
 692        reg_r(gspca_dev, 0x0001, 1);            /* -> 0x18 */
 693        length = 8;
 694        for (i = 0; i < 18; i++) {
 695                if (i == 17)
 696                        length = 2;
 697                reg_w(gspca_dev, 0x0008, cxjpeg_qtable[i], length);
 698
 699        }
 700        reg_r(gspca_dev, 0x0002, 1);    /* 0x00 */
 701        reg_r(gspca_dev, 0x0053, 1);    /* 0x00 */
 702        reg_w_val(gspca_dev, 0x0054, 0x02);
 703        reg_w_val(gspca_dev, 0x0054, 0x01);
 704        reg_w_val(gspca_dev, 0x0000, 0x94);
 705        reg_w_val(gspca_dev, 0x0053, 0xc0);
 706
 707        reg_r(gspca_dev, 0x0038, 1);            /* 0x40 */
 708        reg_r(gspca_dev, 0x0038, 1);            /* 0x40 */
 709        reg_r(gspca_dev, 0x001f, 1);            /* 0x38 */
 710        reg_w(gspca_dev, 0x0012, reg12, 5);
 711        reg_w(gspca_dev, 0x00e5, regE5_8, 8);
 712        reg_r(gspca_dev, 0x00e8, 8);
 713        reg_w(gspca_dev, 0x00e5, regE5a, 4);
 714        reg_r(gspca_dev, 0x00e8, 1);            /* 0x00 */
 715        reg_w_val(gspca_dev, 0x009a, 0x01);
 716        reg_w(gspca_dev, 0x00e5, regE5b, 4);
 717        reg_r(gspca_dev, 0x00e8, 1);            /* 0x00 */
 718        reg_w(gspca_dev, 0x00e5, regE5c, 4);
 719        reg_r(gspca_dev, 0x00e8, 1);            /* 0x00 */
 720
 721        reg_w(gspca_dev, 0x0051, reg51, 2);
 722        reg_w(gspca_dev, 0x0010, reg10, 2);
 723        reg_w_val(gspca_dev, 0x0070, reg70);
 724}
 725
 726static void cx11646_init1(struct gspca_dev *gspca_dev)
 727{
 728        int i = 0;
 729
 730        reg_w_val(gspca_dev, 0x0010, 0x00);
 731        reg_w_val(gspca_dev, 0x0053, 0x00);
 732        reg_w_val(gspca_dev, 0x0052, 0x00);
 733        reg_w_val(gspca_dev, 0x009b, 0x2f);
 734        reg_w_val(gspca_dev, 0x009c, 0x10);
 735        reg_r(gspca_dev, 0x0098, 1);
 736        reg_w_val(gspca_dev, 0x0098, 0x40);
 737        reg_r(gspca_dev, 0x0099, 1);
 738        reg_w_val(gspca_dev, 0x0099, 0x07);
 739        reg_w_val(gspca_dev, 0x0039, 0x40);
 740        reg_w_val(gspca_dev, 0x003c, 0xff);
 741        reg_w_val(gspca_dev, 0x003f, 0x1f);
 742        reg_w_val(gspca_dev, 0x003d, 0x40);
 743/*      reg_w_val(gspca_dev, 0x003d, 0x60); */
 744        reg_r(gspca_dev, 0x0099, 1);                    /* ->0x07 */
 745
 746        while (cx_sensor_init[i][0]) {
 747                reg_w_val(gspca_dev, 0x00e5, cx_sensor_init[i][0]);
 748                reg_r(gspca_dev, 0x00e8, 1);            /* -> 0x00 */
 749                if (i == 1) {
 750                        reg_w_val(gspca_dev, 0x00ed, 0x01);
 751                        reg_r(gspca_dev, 0x00ed, 1);    /* -> 0x01 */
 752                }
 753                i++;
 754        }
 755        reg_w_val(gspca_dev, 0x00c3, 0x00);
 756}
 757
 758/* this function is called at probe time */
 759static int sd_config(struct gspca_dev *gspca_dev,
 760                        const struct usb_device_id *id)
 761{
 762        struct cam *cam;
 763
 764        cam = &gspca_dev->cam;
 765        cam->cam_mode = vga_mode;
 766        cam->nmodes = ARRAY_SIZE(vga_mode);
 767        return 0;
 768}
 769
 770/* this function is called at probe and resume time */
 771static int sd_init(struct gspca_dev *gspca_dev)
 772{
 773        cx11646_init1(gspca_dev);
 774        cx11646_initsize(gspca_dev);
 775        cx11646_fw(gspca_dev);
 776        cx_sensor(gspca_dev);
 777        cx11646_jpegInit(gspca_dev);
 778        return 0;
 779}
 780
 781static int sd_start(struct gspca_dev *gspca_dev)
 782{
 783        struct sd *sd = (struct sd *) gspca_dev;
 784
 785        /* create the JPEG header */
 786        jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
 787                        gspca_dev->pixfmt.width,
 788                        0x22);          /* JPEG 411 */
 789        jpeg_set_qual(sd->jpeg_hdr, QUALITY);
 790
 791        cx11646_initsize(gspca_dev);
 792        cx11646_fw(gspca_dev);
 793        cx_sensor(gspca_dev);
 794        cx11646_jpeg(gspca_dev);
 795        return 0;
 796}
 797
 798/* called on streamoff with alt 0 and on disconnect */
 799static void sd_stop0(struct gspca_dev *gspca_dev)
 800{
 801        int retry = 50;
 802
 803        if (!gspca_dev->present)
 804                return;
 805        reg_w_val(gspca_dev, 0x0000, 0x00);
 806        reg_r(gspca_dev, 0x0002, 1);
 807        reg_w_val(gspca_dev, 0x0053, 0x00);
 808
 809        while (retry--) {
 810/*              reg_r(gspca_dev, 0x0002, 1);*/
 811                reg_r(gspca_dev, 0x0053, 1);
 812                if (gspca_dev->usb_buf[0] == 0)
 813                        break;
 814        }
 815        reg_w_val(gspca_dev, 0x0000, 0x00);
 816        reg_r(gspca_dev, 0x0002, 1);
 817
 818        reg_w_val(gspca_dev, 0x0010, 0x00);
 819        reg_r(gspca_dev, 0x0033, 1);
 820        reg_w_val(gspca_dev, 0x00fc, 0xe0);
 821}
 822
 823static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 824                        u8 *data,                       /* isoc packet */
 825                        int len)                        /* iso packet length */
 826{
 827        struct sd *sd = (struct sd *) gspca_dev;
 828
 829        if (data[0] == 0xff && data[1] == 0xd8) {
 830
 831                /* start of frame */
 832                gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
 833
 834                /* put the JPEG header in the new frame */
 835                gspca_frame_add(gspca_dev, FIRST_PACKET,
 836                                sd->jpeg_hdr, JPEG_HDR_SZ);
 837                data += 2;
 838                len -= 2;
 839        }
 840        gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
 841}
 842
 843static void setbrightness(struct gspca_dev *gspca_dev, s32 val, s32 sat)
 844{
 845        __u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
 846        __u8 reg51c[2];
 847
 848        regE5cbx[2] = val;
 849        reg_w(gspca_dev, 0x00e5, regE5cbx, 8);
 850        reg_r(gspca_dev, 0x00e8, 8);
 851        reg_w(gspca_dev, 0x00e5, regE5c, 4);
 852        reg_r(gspca_dev, 0x00e8, 1);            /* 0x00 */
 853
 854        reg51c[0] = 0x77;
 855        reg51c[1] = sat;
 856        reg_w(gspca_dev, 0x0051, reg51c, 2);
 857        reg_w(gspca_dev, 0x0010, reg10, 2);
 858        reg_w_val(gspca_dev, 0x0070, reg70);
 859}
 860
 861static void setcontrast(struct gspca_dev *gspca_dev, s32 val, s32 sat)
 862{
 863        __u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 };   /* seem MSB */
 864/*      __u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01};     * LSB */
 865        __u8 reg51c[2];
 866
 867        regE5acx[2] = val;
 868        reg_w(gspca_dev, 0x00e5, regE5acx, 4);
 869        reg_r(gspca_dev, 0x00e8, 1);            /* 0x00 */
 870        reg51c[0] = 0x77;
 871        reg51c[1] = sat;
 872        reg_w(gspca_dev, 0x0051, reg51c, 2);
 873        reg_w(gspca_dev, 0x0010, reg10, 2);
 874        reg_w_val(gspca_dev, 0x0070, reg70);
 875}
 876
 877static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
 878{
 879        struct gspca_dev *gspca_dev =
 880                container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
 881        struct sd *sd = (struct sd *)gspca_dev;
 882
 883        gspca_dev->usb_err = 0;
 884
 885        if (!gspca_dev->streaming)
 886                return 0;
 887
 888        switch (ctrl->id) {
 889        case V4L2_CID_BRIGHTNESS:
 890                setbrightness(gspca_dev, ctrl->val, sd->sat->cur.val);
 891                break;
 892        case V4L2_CID_CONTRAST:
 893                setcontrast(gspca_dev, ctrl->val, sd->sat->cur.val);
 894                break;
 895        case V4L2_CID_SATURATION:
 896                setbrightness(gspca_dev, sd->brightness->cur.val, ctrl->val);
 897                setcontrast(gspca_dev, sd->contrast->cur.val, ctrl->val);
 898                break;
 899        }
 900        return gspca_dev->usb_err;
 901}
 902
 903static const struct v4l2_ctrl_ops sd_ctrl_ops = {
 904        .s_ctrl = sd_s_ctrl,
 905};
 906
 907static int sd_init_controls(struct gspca_dev *gspca_dev)
 908{
 909        struct sd *sd = (struct sd *)gspca_dev;
 910        struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
 911
 912        gspca_dev->vdev.ctrl_handler = hdl;
 913        v4l2_ctrl_handler_init(hdl, 3);
 914        sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 915                        V4L2_CID_BRIGHTNESS, 0, 255, 1, 0xd4);
 916        sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 917                        V4L2_CID_CONTRAST, 0x0a, 0x1f, 1, 0x0c);
 918        sd->sat = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 919                        V4L2_CID_SATURATION, 0, 7, 1, 3);
 920        if (hdl->error) {
 921                pr_err("Could not initialize controls\n");
 922                return hdl->error;
 923        }
 924        return 0;
 925}
 926
 927/* sub-driver description */
 928static const struct sd_desc sd_desc = {
 929        .name = MODULE_NAME,
 930        .config = sd_config,
 931        .init = sd_init,
 932        .init_controls = sd_init_controls,
 933        .start = sd_start,
 934        .stop0 = sd_stop0,
 935        .pkt_scan = sd_pkt_scan,
 936};
 937
 938/* -- module initialisation -- */
 939static const struct usb_device_id device_table[] = {
 940        {USB_DEVICE(0x0572, 0x0041)},
 941        {}
 942};
 943MODULE_DEVICE_TABLE(usb, device_table);
 944
 945/* -- device connect -- */
 946static int sd_probe(struct usb_interface *intf,
 947                        const struct usb_device_id *id)
 948{
 949        return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
 950                                THIS_MODULE);
 951}
 952
 953static struct usb_driver sd_driver = {
 954        .name = MODULE_NAME,
 955        .id_table = device_table,
 956        .probe = sd_probe,
 957        .disconnect = gspca_disconnect,
 958#ifdef CONFIG_PM
 959        .suspend = gspca_suspend,
 960        .resume = gspca_resume,
 961        .reset_resume = gspca_resume,
 962#endif
 963};
 964
 965module_usb_driver(sd_driver);
 966