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