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