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