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