linux/drivers/media/usb/gspca/sunplus.c
<<
>>
Prefs
   1/*
   2 *              Sunplus spca504(abc) spca533 spca536 library
   3 *              Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
   4 *
   5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 * GNU General Public License for more details.
  16 */
  17
  18#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  19
  20#define MODULE_NAME "sunplus"
  21
  22#include "gspca.h"
  23#include "jpeg.h"
  24
  25MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
  26MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
  27MODULE_LICENSE("GPL");
  28
  29#define QUALITY 85
  30
  31/* specific webcam descriptor */
  32struct sd {
  33        struct gspca_dev gspca_dev;     /* !! must be the first item */
  34
  35        bool autogain;
  36
  37        u8 bridge;
  38#define BRIDGE_SPCA504 0
  39#define BRIDGE_SPCA504B 1
  40#define BRIDGE_SPCA504C 2
  41#define BRIDGE_SPCA533 3
  42#define BRIDGE_SPCA536 4
  43        u8 subtype;
  44#define AiptekMiniPenCam13 1
  45#define LogitechClickSmart420 2
  46#define LogitechClickSmart820 3
  47#define MegapixV4 4
  48#define MegaImageVI 5
  49
  50        u8 jpeg_hdr[JPEG_HDR_SZ];
  51};
  52
  53static const struct v4l2_pix_format vga_mode[] = {
  54        {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  55                .bytesperline = 320,
  56                .sizeimage = 320 * 240 * 3 / 8 + 590,
  57                .colorspace = V4L2_COLORSPACE_JPEG,
  58                .priv = 2},
  59        {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  60                .bytesperline = 640,
  61                .sizeimage = 640 * 480 * 3 / 8 + 590,
  62                .colorspace = V4L2_COLORSPACE_JPEG,
  63                .priv = 1},
  64};
  65
  66static const struct v4l2_pix_format custom_mode[] = {
  67        {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  68                .bytesperline = 320,
  69                .sizeimage = 320 * 240 * 3 / 8 + 590,
  70                .colorspace = V4L2_COLORSPACE_JPEG,
  71                .priv = 2},
  72        {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  73                .bytesperline = 464,
  74                .sizeimage = 464 * 480 * 3 / 8 + 590,
  75                .colorspace = V4L2_COLORSPACE_JPEG,
  76                .priv = 1},
  77};
  78
  79static const struct v4l2_pix_format vga_mode2[] = {
  80        {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  81                .bytesperline = 176,
  82                .sizeimage = 176 * 144 * 3 / 8 + 590,
  83                .colorspace = V4L2_COLORSPACE_JPEG,
  84                .priv = 4},
  85        {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  86                .bytesperline = 320,
  87                .sizeimage = 320 * 240 * 3 / 8 + 590,
  88                .colorspace = V4L2_COLORSPACE_JPEG,
  89                .priv = 3},
  90        {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  91                .bytesperline = 352,
  92                .sizeimage = 352 * 288 * 3 / 8 + 590,
  93                .colorspace = V4L2_COLORSPACE_JPEG,
  94                .priv = 2},
  95        {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  96                .bytesperline = 640,
  97                .sizeimage = 640 * 480 * 3 / 8 + 590,
  98                .colorspace = V4L2_COLORSPACE_JPEG,
  99                .priv = 1},
 100};
 101
 102#define SPCA50X_OFFSET_DATA 10
 103#define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
 104#define SPCA504_PCCAM600_OFFSET_COMPRESS 4
 105#define SPCA504_PCCAM600_OFFSET_MODE     5
 106#define SPCA504_PCCAM600_OFFSET_DATA     14
 107 /* Frame packet header offsets for the spca533 */
 108#define SPCA533_OFFSET_DATA     16
 109#define SPCA533_OFFSET_FRAMSEQ  15
 110/* Frame packet header offsets for the spca536 */
 111#define SPCA536_OFFSET_DATA     4
 112#define SPCA536_OFFSET_FRAMSEQ  1
 113
 114struct cmd {
 115        u8 req;
 116        u16 val;
 117        u16 idx;
 118};
 119
 120/* Initialisation data for the Creative PC-CAM 600 */
 121static const struct cmd spca504_pccam600_init_data[] = {
 122/*      {0xa0, 0x0000, 0x0503},  * capture mode */
 123        {0x00, 0x0000, 0x2000},
 124        {0x00, 0x0013, 0x2301},
 125        {0x00, 0x0003, 0x2000},
 126        {0x00, 0x0001, 0x21ac},
 127        {0x00, 0x0001, 0x21a6},
 128        {0x00, 0x0000, 0x21a7}, /* brightness */
 129        {0x00, 0x0020, 0x21a8}, /* contrast */
 130        {0x00, 0x0001, 0x21ac}, /* sat/hue */
 131        {0x00, 0x0000, 0x21ad}, /* hue */
 132        {0x00, 0x001a, 0x21ae}, /* saturation */
 133        {0x00, 0x0002, 0x21a3}, /* gamma */
 134        {0x30, 0x0154, 0x0008},
 135        {0x30, 0x0004, 0x0006},
 136        {0x30, 0x0258, 0x0009},
 137        {0x30, 0x0004, 0x0000},
 138        {0x30, 0x0093, 0x0004},
 139        {0x30, 0x0066, 0x0005},
 140        {0x00, 0x0000, 0x2000},
 141        {0x00, 0x0013, 0x2301},
 142        {0x00, 0x0003, 0x2000},
 143        {0x00, 0x0013, 0x2301},
 144        {0x00, 0x0003, 0x2000},
 145};
 146
 147/* Creative PC-CAM 600 specific open data, sent before using the
 148 * generic initialisation data from spca504_open_data.
 149 */
 150static const struct cmd spca504_pccam600_open_data[] = {
 151        {0x00, 0x0001, 0x2501},
 152        {0x20, 0x0500, 0x0001}, /* snapshot mode */
 153        {0x00, 0x0003, 0x2880},
 154        {0x00, 0x0001, 0x2881},
 155};
 156
 157/* Initialisation data for the logitech clicksmart 420 */
 158static const struct cmd spca504A_clicksmart420_init_data[] = {
 159/*      {0xa0, 0x0000, 0x0503},  * capture mode */
 160        {0x00, 0x0000, 0x2000},
 161        {0x00, 0x0013, 0x2301},
 162        {0x00, 0x0003, 0x2000},
 163        {0x00, 0x0001, 0x21ac},
 164        {0x00, 0x0001, 0x21a6},
 165        {0x00, 0x0000, 0x21a7}, /* brightness */
 166        {0x00, 0x0020, 0x21a8}, /* contrast */
 167        {0x00, 0x0001, 0x21ac}, /* sat/hue */
 168        {0x00, 0x0000, 0x21ad}, /* hue */
 169        {0x00, 0x001a, 0x21ae}, /* saturation */
 170        {0x00, 0x0002, 0x21a3}, /* gamma */
 171        {0x30, 0x0004, 0x000a},
 172        {0xb0, 0x0001, 0x0000},
 173
 174        {0xa1, 0x0080, 0x0001},
 175        {0x30, 0x0049, 0x0000},
 176        {0x30, 0x0060, 0x0005},
 177        {0x0c, 0x0004, 0x0000},
 178        {0x00, 0x0000, 0x0000},
 179        {0x00, 0x0000, 0x2000},
 180        {0x00, 0x0013, 0x2301},
 181        {0x00, 0x0003, 0x2000},
 182};
 183
 184/* clicksmart 420 open data ? */
 185static const struct cmd spca504A_clicksmart420_open_data[] = {
 186        {0x00, 0x0001, 0x2501},
 187        {0x20, 0x0502, 0x0000},
 188        {0x06, 0x0000, 0x0000},
 189        {0x00, 0x0004, 0x2880},
 190        {0x00, 0x0001, 0x2881},
 191
 192        {0xa0, 0x0000, 0x0503},
 193};
 194
 195static const u8 qtable_creative_pccam[2][64] = {
 196        {                               /* Q-table Y-components */
 197         0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
 198         0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
 199         0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
 200         0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
 201         0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
 202         0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
 203         0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
 204         0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
 205        {                               /* Q-table C-components */
 206         0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
 207         0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
 208         0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 209         0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 210         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 211         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 212         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 213         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
 214};
 215
 216/* FIXME: This Q-table is identical to the Creative PC-CAM one,
 217 *              except for one byte. Possibly a typo?
 218 *              NWG: 18/05/2003.
 219 */
 220static const u8 qtable_spca504_default[2][64] = {
 221        {                               /* Q-table Y-components */
 222         0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
 223         0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
 224         0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
 225         0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
 226         0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
 227         0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
 228         0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
 229         0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
 230         },
 231        {                               /* Q-table C-components */
 232         0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
 233         0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
 234         0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 235         0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 236         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 237         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 238         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
 239         0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
 240};
 241
 242/* read <len> bytes to gspca_dev->usb_buf */
 243static void reg_r(struct gspca_dev *gspca_dev,
 244                  u8 req,
 245                  u16 index,
 246                  u16 len)
 247{
 248        int ret;
 249
 250        if (len > USB_BUF_SZ) {
 251                PERR("reg_r: buffer overflow\n");
 252                return;
 253        }
 254        if (gspca_dev->usb_err < 0)
 255                return;
 256        ret = usb_control_msg(gspca_dev->dev,
 257                        usb_rcvctrlpipe(gspca_dev->dev, 0),
 258                        req,
 259                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 260                        0,              /* value */
 261                        index,
 262                        len ? gspca_dev->usb_buf : NULL, len,
 263                        500);
 264        if (ret < 0) {
 265                pr_err("reg_r err %d\n", ret);
 266                gspca_dev->usb_err = ret;
 267        }
 268}
 269
 270/* write one byte */
 271static void reg_w_1(struct gspca_dev *gspca_dev,
 272                   u8 req,
 273                   u16 value,
 274                   u16 index,
 275                   u16 byte)
 276{
 277        int ret;
 278
 279        if (gspca_dev->usb_err < 0)
 280                return;
 281        gspca_dev->usb_buf[0] = byte;
 282        ret = usb_control_msg(gspca_dev->dev,
 283                        usb_sndctrlpipe(gspca_dev->dev, 0),
 284                        req,
 285                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 286                        value, index,
 287                        gspca_dev->usb_buf, 1,
 288                        500);
 289        if (ret < 0) {
 290                pr_err("reg_w_1 err %d\n", ret);
 291                gspca_dev->usb_err = ret;
 292        }
 293}
 294
 295/* write req / index / value */
 296static void reg_w_riv(struct gspca_dev *gspca_dev,
 297                     u8 req, u16 index, u16 value)
 298{
 299        struct usb_device *dev = gspca_dev->dev;
 300        int ret;
 301
 302        if (gspca_dev->usb_err < 0)
 303                return;
 304        ret = usb_control_msg(dev,
 305                        usb_sndctrlpipe(dev, 0),
 306                        req,
 307                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 308                        value, index, NULL, 0, 500);
 309        if (ret < 0) {
 310                pr_err("reg_w_riv err %d\n", ret);
 311                gspca_dev->usb_err = ret;
 312                return;
 313        }
 314        PDEBUG(D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x",
 315                req, index, value);
 316}
 317
 318static void write_vector(struct gspca_dev *gspca_dev,
 319                        const struct cmd *data, int ncmds)
 320{
 321        while (--ncmds >= 0) {
 322                reg_w_riv(gspca_dev, data->req, data->idx, data->val);
 323                data++;
 324        }
 325}
 326
 327static void setup_qtable(struct gspca_dev *gspca_dev,
 328                        const u8 qtable[2][64])
 329{
 330        int i;
 331
 332        /* loop over y components */
 333        for (i = 0; i < 64; i++)
 334                reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]);
 335
 336        /* loop over c components */
 337        for (i = 0; i < 64; i++)
 338                reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]);
 339}
 340
 341static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
 342                             u8 req, u16 idx, u16 val)
 343{
 344        reg_w_riv(gspca_dev, req, idx, val);
 345        reg_r(gspca_dev, 0x01, 0x0001, 1);
 346        PDEBUG(D_FRAM, "before wait 0x%04x", gspca_dev->usb_buf[0]);
 347        reg_w_riv(gspca_dev, req, idx, val);
 348
 349        msleep(200);
 350        reg_r(gspca_dev, 0x01, 0x0001, 1);
 351        PDEBUG(D_FRAM, "after wait 0x%04x", gspca_dev->usb_buf[0]);
 352}
 353
 354static void spca504_read_info(struct gspca_dev *gspca_dev)
 355{
 356        int i;
 357        u8 info[6];
 358
 359        if (gspca_debug < D_STREAM)
 360                return;
 361
 362        for (i = 0; i < 6; i++) {
 363                reg_r(gspca_dev, 0, i, 1);
 364                info[i] = gspca_dev->usb_buf[0];
 365        }
 366        PDEBUG(D_STREAM,
 367                "Read info: %d %d %d %d %d %d. Should be 1,0,2,2,0,0",
 368                info[0], info[1], info[2],
 369                info[3], info[4], info[5]);
 370}
 371
 372static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
 373                        u8 req,
 374                        u16 idx, u16 val, u8 endcode, u8 count)
 375{
 376        u16 status;
 377
 378        reg_w_riv(gspca_dev, req, idx, val);
 379        reg_r(gspca_dev, 0x01, 0x0001, 1);
 380        if (gspca_dev->usb_err < 0)
 381                return;
 382        PDEBUG(D_FRAM, "Status 0x%02x Need 0x%02x",
 383                        gspca_dev->usb_buf[0], endcode);
 384        if (!count)
 385                return;
 386        count = 200;
 387        while (--count > 0) {
 388                msleep(10);
 389                /* gsmart mini2 write a each wait setting 1 ms is enough */
 390/*              reg_w_riv(gspca_dev, req, idx, val); */
 391                reg_r(gspca_dev, 0x01, 0x0001, 1);
 392                status = gspca_dev->usb_buf[0];
 393                if (status == endcode) {
 394                        PDEBUG(D_FRAM, "status 0x%04x after wait %d",
 395                                status, 200 - count);
 396                                break;
 397                }
 398        }
 399}
 400
 401static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
 402{
 403        int count = 10;
 404
 405        while (--count > 0) {
 406                reg_r(gspca_dev, 0x21, 0, 1);
 407                if ((gspca_dev->usb_buf[0] & 0x01) == 0)
 408                        break;
 409                msleep(10);
 410        }
 411}
 412
 413static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
 414{
 415        int count = 50;
 416
 417        while (--count > 0) {
 418                reg_r(gspca_dev, 0x21, 1, 1);
 419                if (gspca_dev->usb_buf[0] != 0) {
 420                        reg_w_1(gspca_dev, 0x21, 0, 1, 0);
 421                        reg_r(gspca_dev, 0x21, 1, 1);
 422                        spca504B_PollingDataReady(gspca_dev);
 423                        break;
 424                }
 425                msleep(10);
 426        }
 427}
 428
 429static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
 430{
 431        u8 *data;
 432
 433        if (gspca_debug < D_STREAM)
 434                return;
 435
 436        data = gspca_dev->usb_buf;
 437        reg_r(gspca_dev, 0x20, 0, 5);
 438        PDEBUG(D_STREAM, "FirmWare: %d %d %d %d %d",
 439                data[0], data[1], data[2], data[3], data[4]);
 440        reg_r(gspca_dev, 0x23, 0, 64);
 441        reg_r(gspca_dev, 0x23, 1, 64);
 442}
 443
 444static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
 445{
 446        struct sd *sd = (struct sd *) gspca_dev;
 447        u8 Size;
 448
 449        Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
 450        switch (sd->bridge) {
 451        case BRIDGE_SPCA533:
 452                reg_w_riv(gspca_dev, 0x31, 0, 0);
 453                spca504B_WaitCmdStatus(gspca_dev);
 454                spca504B_PollingDataReady(gspca_dev);
 455                spca50x_GetFirmware(gspca_dev);
 456
 457                reg_w_1(gspca_dev, 0x24, 0, 8, 2);              /* type */
 458                reg_r(gspca_dev, 0x24, 8, 1);
 459
 460                reg_w_1(gspca_dev, 0x25, 0, 4, Size);
 461                reg_r(gspca_dev, 0x25, 4, 1);                   /* size */
 462                spca504B_PollingDataReady(gspca_dev);
 463
 464                /* Init the cam width height with some values get on init ? */
 465                reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
 466                spca504B_WaitCmdStatus(gspca_dev);
 467                spca504B_PollingDataReady(gspca_dev);
 468                break;
 469        default:
 470/* case BRIDGE_SPCA504B: */
 471/* case BRIDGE_SPCA536: */
 472                reg_w_1(gspca_dev, 0x25, 0, 4, Size);
 473                reg_r(gspca_dev, 0x25, 4, 1);                   /* size */
 474                reg_w_1(gspca_dev, 0x27, 0, 0, 6);
 475                reg_r(gspca_dev, 0x27, 0, 1);                   /* type */
 476                spca504B_PollingDataReady(gspca_dev);
 477                break;
 478        case BRIDGE_SPCA504:
 479                Size += 3;
 480                if (sd->subtype == AiptekMiniPenCam13) {
 481                        /* spca504a aiptek */
 482                        spca504A_acknowledged_command(gspca_dev,
 483                                                0x08, Size, 0,
 484                                                0x80 | (Size & 0x0f), 1);
 485                        spca504A_acknowledged_command(gspca_dev,
 486                                                        1, 3, 0, 0x9f, 0);
 487                } else {
 488                        spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
 489                }
 490                break;
 491        case BRIDGE_SPCA504C:
 492                /* capture mode */
 493                reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
 494                reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
 495                break;
 496        }
 497}
 498
 499static void spca504_wait_status(struct gspca_dev *gspca_dev)
 500{
 501        int cnt;
 502
 503        cnt = 256;
 504        while (--cnt > 0) {
 505                /* With this we get the status, when return 0 it's all ok */
 506                reg_r(gspca_dev, 0x06, 0x00, 1);
 507                if (gspca_dev->usb_buf[0] == 0)
 508                        return;
 509                msleep(10);
 510        }
 511}
 512
 513static void spca504B_setQtable(struct gspca_dev *gspca_dev)
 514{
 515        reg_w_1(gspca_dev, 0x26, 0, 0, 3);
 516        reg_r(gspca_dev, 0x26, 0, 1);
 517        spca504B_PollingDataReady(gspca_dev);
 518}
 519
 520static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
 521{
 522        struct sd *sd = (struct sd *) gspca_dev;
 523        u16 reg;
 524
 525        reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
 526        reg_w_riv(gspca_dev, 0x00, reg, val);
 527}
 528
 529static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
 530{
 531        struct sd *sd = (struct sd *) gspca_dev;
 532        u16 reg;
 533
 534        reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
 535        reg_w_riv(gspca_dev, 0x00, reg, val);
 536}
 537
 538static void setcolors(struct gspca_dev *gspca_dev, s32 val)
 539{
 540        struct sd *sd = (struct sd *) gspca_dev;
 541        u16 reg;
 542
 543        reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
 544        reg_w_riv(gspca_dev, 0x00, reg, val);
 545}
 546
 547static void init_ctl_reg(struct gspca_dev *gspca_dev)
 548{
 549        struct sd *sd = (struct sd *) gspca_dev;
 550        int pollreg = 1;
 551
 552        switch (sd->bridge) {
 553        case BRIDGE_SPCA504:
 554        case BRIDGE_SPCA504C:
 555                pollreg = 0;
 556                /* fall thru */
 557        default:
 558/*      case BRIDGE_SPCA533: */
 559/*      case BRIDGE_SPCA504B: */
 560                reg_w_riv(gspca_dev, 0, 0x21ad, 0x00);  /* hue */
 561                reg_w_riv(gspca_dev, 0, 0x21ac, 0x01);  /* sat/hue */
 562                reg_w_riv(gspca_dev, 0, 0x21a3, 0x00);  /* gamma */
 563                break;
 564        case BRIDGE_SPCA536:
 565                reg_w_riv(gspca_dev, 0, 0x20f5, 0x40);
 566                reg_w_riv(gspca_dev, 0, 0x20f4, 0x01);
 567                reg_w_riv(gspca_dev, 0, 0x2089, 0x00);
 568                break;
 569        }
 570        if (pollreg)
 571                spca504B_PollingDataReady(gspca_dev);
 572}
 573
 574/* this function is called at probe time */
 575static int sd_config(struct gspca_dev *gspca_dev,
 576                        const struct usb_device_id *id)
 577{
 578        struct sd *sd = (struct sd *) gspca_dev;
 579        struct cam *cam;
 580
 581        cam = &gspca_dev->cam;
 582
 583        sd->bridge = id->driver_info >> 8;
 584        sd->subtype = id->driver_info;
 585
 586        if (sd->subtype == AiptekMiniPenCam13) {
 587
 588                /* try to get the firmware as some cam answer 2.0.1.2.2
 589                 * and should be a spca504b then overwrite that setting */
 590                reg_r(gspca_dev, 0x20, 0, 1);
 591                switch (gspca_dev->usb_buf[0]) {
 592                case 1:
 593                        break;          /* (right bridge/subtype) */
 594                case 2:
 595                        sd->bridge = BRIDGE_SPCA504B;
 596                        sd->subtype = 0;
 597                        break;
 598                default:
 599                        return -ENODEV;
 600                }
 601        }
 602
 603        switch (sd->bridge) {
 604        default:
 605/*      case BRIDGE_SPCA504B: */
 606/*      case BRIDGE_SPCA504: */
 607/*      case BRIDGE_SPCA536: */
 608                cam->cam_mode = vga_mode;
 609                cam->nmodes = ARRAY_SIZE(vga_mode);
 610                break;
 611        case BRIDGE_SPCA533:
 612                cam->cam_mode = custom_mode;
 613                if (sd->subtype == MegaImageVI)         /* 320x240 only */
 614                        cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
 615                else
 616                        cam->nmodes = ARRAY_SIZE(custom_mode);
 617                break;
 618        case BRIDGE_SPCA504C:
 619                cam->cam_mode = vga_mode2;
 620                cam->nmodes = ARRAY_SIZE(vga_mode2);
 621                break;
 622        }
 623        return 0;
 624}
 625
 626/* this function is called at probe and resume time */
 627static int sd_init(struct gspca_dev *gspca_dev)
 628{
 629        struct sd *sd = (struct sd *) gspca_dev;
 630
 631        switch (sd->bridge) {
 632        case BRIDGE_SPCA504B:
 633                reg_w_riv(gspca_dev, 0x1d, 0x00, 0);
 634                reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01);
 635                reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00);
 636                reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00);
 637                reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13);
 638                reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00);
 639                /* fall thru */
 640        case BRIDGE_SPCA533:
 641                spca504B_PollingDataReady(gspca_dev);
 642                spca50x_GetFirmware(gspca_dev);
 643                break;
 644        case BRIDGE_SPCA536:
 645                spca50x_GetFirmware(gspca_dev);
 646                reg_r(gspca_dev, 0x00, 0x5002, 1);
 647                reg_w_1(gspca_dev, 0x24, 0, 0, 0);
 648                reg_r(gspca_dev, 0x24, 0, 1);
 649                spca504B_PollingDataReady(gspca_dev);
 650                reg_w_riv(gspca_dev, 0x34, 0, 0);
 651                spca504B_WaitCmdStatus(gspca_dev);
 652                break;
 653        case BRIDGE_SPCA504C:   /* pccam600 */
 654                PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
 655                reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000);
 656                reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001);     /* reset */
 657                spca504_wait_status(gspca_dev);
 658                if (sd->subtype == LogitechClickSmart420)
 659                        write_vector(gspca_dev,
 660                                spca504A_clicksmart420_open_data,
 661                                ARRAY_SIZE(spca504A_clicksmart420_open_data));
 662                else
 663                        write_vector(gspca_dev, spca504_pccam600_open_data,
 664                                ARRAY_SIZE(spca504_pccam600_open_data));
 665                setup_qtable(gspca_dev, qtable_creative_pccam);
 666                break;
 667        default:
 668/*      case BRIDGE_SPCA504: */
 669                PDEBUG(D_STREAM, "Opening SPCA504");
 670                if (sd->subtype == AiptekMiniPenCam13) {
 671                        spca504_read_info(gspca_dev);
 672
 673                        /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
 674                        spca504A_acknowledged_command(gspca_dev, 0x24,
 675                                                        8, 3, 0x9e, 1);
 676                        /* Twice sequential need status 0xff->0x9e->0x9d */
 677                        spca504A_acknowledged_command(gspca_dev, 0x24,
 678                                                        8, 3, 0x9e, 0);
 679
 680                        spca504A_acknowledged_command(gspca_dev, 0x24,
 681                                                        0, 0, 0x9d, 1);
 682                        /******************************/
 683                        /* spca504a aiptek */
 684                        spca504A_acknowledged_command(gspca_dev, 0x08,
 685                                                        6, 0, 0x86, 1);
 686/*                      reg_write (dev, 0, 0x2000, 0); */
 687/*                      reg_write (dev, 0, 0x2883, 1); */
 688/*                      spca504A_acknowledged_command (gspca_dev, 0x08,
 689                                                        6, 0, 0x86, 1); */
 690/*                      spca504A_acknowledged_command (gspca_dev, 0x24,
 691                                                        0, 0, 0x9D, 1); */
 692                        reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
 693                                                        /* L92 sno1t.txt */
 694                        reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
 695                        spca504A_acknowledged_command(gspca_dev, 0x01,
 696                                                        0x0f, 0, 0xff, 0);
 697                }
 698                /* setup qtable */
 699                reg_w_riv(gspca_dev, 0, 0x2000, 0);
 700                reg_w_riv(gspca_dev, 0, 0x2883, 1);
 701                setup_qtable(gspca_dev, qtable_spca504_default);
 702                break;
 703        }
 704        return gspca_dev->usb_err;
 705}
 706
 707static int sd_start(struct gspca_dev *gspca_dev)
 708{
 709        struct sd *sd = (struct sd *) gspca_dev;
 710        int enable;
 711
 712        /* create the JPEG header */
 713        jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
 714                        gspca_dev->pixfmt.width,
 715                        0x22);          /* JPEG 411 */
 716        jpeg_set_qual(sd->jpeg_hdr, QUALITY);
 717
 718        if (sd->bridge == BRIDGE_SPCA504B)
 719                spca504B_setQtable(gspca_dev);
 720        spca504B_SetSizeType(gspca_dev);
 721        switch (sd->bridge) {
 722        default:
 723/*      case BRIDGE_SPCA504B: */
 724/*      case BRIDGE_SPCA533: */
 725/*      case BRIDGE_SPCA536: */
 726                switch (sd->subtype) {
 727                case MegapixV4:
 728                case LogitechClickSmart820:
 729                case MegaImageVI:
 730                        reg_w_riv(gspca_dev, 0xf0, 0, 0);
 731                        spca504B_WaitCmdStatus(gspca_dev);
 732                        reg_r(gspca_dev, 0xf0, 4, 0);
 733                        spca504B_WaitCmdStatus(gspca_dev);
 734                        break;
 735                default:
 736                        reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
 737                        spca504B_WaitCmdStatus(gspca_dev);
 738                        spca504B_PollingDataReady(gspca_dev);
 739                        break;
 740                }
 741                break;
 742        case BRIDGE_SPCA504:
 743                if (sd->subtype == AiptekMiniPenCam13) {
 744                        spca504_read_info(gspca_dev);
 745
 746                        /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
 747                        spca504A_acknowledged_command(gspca_dev, 0x24,
 748                                                        8, 3, 0x9e, 1);
 749                        /* Twice sequential need status 0xff->0x9e->0x9d */
 750                        spca504A_acknowledged_command(gspca_dev, 0x24,
 751                                                        8, 3, 0x9e, 0);
 752                        spca504A_acknowledged_command(gspca_dev, 0x24,
 753                                                        0, 0, 0x9d, 1);
 754                } else {
 755                        spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
 756                        spca504_read_info(gspca_dev);
 757                        spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
 758                        spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
 759                }
 760                spca504B_SetSizeType(gspca_dev);
 761                reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
 762                                                        /* L92 sno1t.txt */
 763                reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
 764                break;
 765        case BRIDGE_SPCA504C:
 766                if (sd->subtype == LogitechClickSmart420) {
 767                        write_vector(gspca_dev,
 768                                spca504A_clicksmart420_init_data,
 769                                ARRAY_SIZE(spca504A_clicksmart420_init_data));
 770                } else {
 771                        write_vector(gspca_dev, spca504_pccam600_init_data,
 772                                ARRAY_SIZE(spca504_pccam600_init_data));
 773                }
 774                enable = (sd->autogain ? 0x04 : 0x01);
 775                reg_w_riv(gspca_dev, 0x0c, 0x0000, enable);
 776                                                        /* auto exposure */
 777                reg_w_riv(gspca_dev, 0xb0, 0x0000, enable);
 778                                                        /* auto whiteness */
 779
 780                /* set default exposure compensation and whiteness balance */
 781                reg_w_riv(gspca_dev, 0x30, 0x0001, 800);        /* ~ 20 fps */
 782                reg_w_riv(gspca_dev, 0x30, 0x0002, 1600);
 783                spca504B_SetSizeType(gspca_dev);
 784                break;
 785        }
 786        init_ctl_reg(gspca_dev);
 787        return gspca_dev->usb_err;
 788}
 789
 790static void sd_stopN(struct gspca_dev *gspca_dev)
 791{
 792        struct sd *sd = (struct sd *) gspca_dev;
 793
 794        switch (sd->bridge) {
 795        default:
 796/*      case BRIDGE_SPCA533: */
 797/*      case BRIDGE_SPCA536: */
 798/*      case BRIDGE_SPCA504B: */
 799                reg_w_riv(gspca_dev, 0x31, 0, 0);
 800                spca504B_WaitCmdStatus(gspca_dev);
 801                spca504B_PollingDataReady(gspca_dev);
 802                break;
 803        case BRIDGE_SPCA504:
 804        case BRIDGE_SPCA504C:
 805                reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000);
 806
 807                if (sd->subtype == AiptekMiniPenCam13) {
 808                        /* spca504a aiptek */
 809/*                      spca504A_acknowledged_command(gspca_dev, 0x08,
 810                                                         6, 0, 0x86, 1); */
 811                        spca504A_acknowledged_command(gspca_dev, 0x24,
 812                                                        0x00, 0x00, 0x9d, 1);
 813                        spca504A_acknowledged_command(gspca_dev, 0x01,
 814                                                        0x0f, 0x00, 0xff, 1);
 815                } else {
 816                        spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
 817                        reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000);
 818                }
 819                break;
 820        }
 821}
 822
 823static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 824                        u8 *data,                       /* isoc packet */
 825                        int len)                        /* iso packet length */
 826{
 827        struct sd *sd = (struct sd *) gspca_dev;
 828        int i, sof = 0;
 829        static u8 ffd9[] = {0xff, 0xd9};
 830
 831/* frames are jpeg 4.1.1 without 0xff escape */
 832        switch (sd->bridge) {
 833        case BRIDGE_SPCA533:
 834                if (data[0] == 0xff) {
 835                        if (data[1] != 0x01) {  /* drop packet */
 836/*                              gspca_dev->last_packet_type = DISCARD_PACKET; */
 837                                return;
 838                        }
 839                        sof = 1;
 840                        data += SPCA533_OFFSET_DATA;
 841                        len -= SPCA533_OFFSET_DATA;
 842                } else {
 843                        data += 1;
 844                        len -= 1;
 845                }
 846                break;
 847        case BRIDGE_SPCA536:
 848                if (data[0] == 0xff) {
 849                        sof = 1;
 850                        data += SPCA536_OFFSET_DATA;
 851                        len -= SPCA536_OFFSET_DATA;
 852                } else {
 853                        data += 2;
 854                        len -= 2;
 855                }
 856                break;
 857        default:
 858/*      case BRIDGE_SPCA504: */
 859/*      case BRIDGE_SPCA504B: */
 860                switch (data[0]) {
 861                case 0xfe:                      /* start of frame */
 862                        sof = 1;
 863                        data += SPCA50X_OFFSET_DATA;
 864                        len -= SPCA50X_OFFSET_DATA;
 865                        break;
 866                case 0xff:                      /* drop packet */
 867/*                      gspca_dev->last_packet_type = DISCARD_PACKET; */
 868                        return;
 869                default:
 870                        data += 1;
 871                        len -= 1;
 872                        break;
 873                }
 874                break;
 875        case BRIDGE_SPCA504C:
 876                switch (data[0]) {
 877                case 0xfe:                      /* start of frame */
 878                        sof = 1;
 879                        data += SPCA504_PCCAM600_OFFSET_DATA;
 880                        len -= SPCA504_PCCAM600_OFFSET_DATA;
 881                        break;
 882                case 0xff:                      /* drop packet */
 883/*                      gspca_dev->last_packet_type = DISCARD_PACKET; */
 884                        return;
 885                default:
 886                        data += 1;
 887                        len -= 1;
 888                        break;
 889                }
 890                break;
 891        }
 892        if (sof) {              /* start of frame */
 893                gspca_frame_add(gspca_dev, LAST_PACKET,
 894                                ffd9, 2);
 895
 896                /* put the JPEG header in the new frame */
 897                gspca_frame_add(gspca_dev, FIRST_PACKET,
 898                        sd->jpeg_hdr, JPEG_HDR_SZ);
 899        }
 900
 901        /* add 0x00 after 0xff */
 902        i = 0;
 903        do {
 904                if (data[i] == 0xff) {
 905                        gspca_frame_add(gspca_dev, INTER_PACKET,
 906                                        data, i + 1);
 907                        len -= i;
 908                        data += i;
 909                        *data = 0x00;
 910                        i = 0;
 911                }
 912                i++;
 913        } while (i < len);
 914        gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
 915}
 916
 917static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
 918{
 919        struct gspca_dev *gspca_dev =
 920                container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
 921        struct sd *sd = (struct sd *)gspca_dev;
 922
 923        gspca_dev->usb_err = 0;
 924
 925        if (!gspca_dev->streaming)
 926                return 0;
 927
 928        switch (ctrl->id) {
 929        case V4L2_CID_BRIGHTNESS:
 930                setbrightness(gspca_dev, ctrl->val);
 931                break;
 932        case V4L2_CID_CONTRAST:
 933                setcontrast(gspca_dev, ctrl->val);
 934                break;
 935        case V4L2_CID_SATURATION:
 936                setcolors(gspca_dev, ctrl->val);
 937                break;
 938        case V4L2_CID_AUTOGAIN:
 939                sd->autogain = ctrl->val;
 940                break;
 941        }
 942        return gspca_dev->usb_err;
 943}
 944
 945static const struct v4l2_ctrl_ops sd_ctrl_ops = {
 946        .s_ctrl = sd_s_ctrl,
 947};
 948
 949static int sd_init_controls(struct gspca_dev *gspca_dev)
 950{
 951        struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
 952
 953        gspca_dev->vdev.ctrl_handler = hdl;
 954        v4l2_ctrl_handler_init(hdl, 4);
 955        v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 956                        V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
 957        v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 958                        V4L2_CID_CONTRAST, 0, 255, 1, 0x20);
 959        v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 960                        V4L2_CID_SATURATION, 0, 255, 1, 0x1a);
 961        v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
 962                        V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
 963
 964        if (hdl->error) {
 965                pr_err("Could not initialize controls\n");
 966                return hdl->error;
 967        }
 968        return 0;
 969}
 970
 971/* sub-driver description */
 972static const struct sd_desc sd_desc = {
 973        .name = MODULE_NAME,
 974        .config = sd_config,
 975        .init = sd_init,
 976        .init_controls = sd_init_controls,
 977        .start = sd_start,
 978        .stopN = sd_stopN,
 979        .pkt_scan = sd_pkt_scan,
 980};
 981
 982/* -- module initialisation -- */
 983#define BS(bridge, subtype) \
 984        .driver_info = (BRIDGE_ ## bridge << 8) \
 985                        | (subtype)
 986static const struct usb_device_id device_table[] = {
 987        {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
 988        {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
 989        {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
 990        {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
 991        {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
 992        {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
 993        {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
 994        {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
 995        {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
 996        {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
 997        {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
 998        {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
 999        {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
1000        {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
1001        {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
1002        {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
1003        {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
1004        {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
1005        {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)},
1006        {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
1007        {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
1008        {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1009        {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1010        {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1011        {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1012        {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1013        {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1014        {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1015        {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1016        {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1017        {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1018        {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1019        {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1020        {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1021        {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1022        {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1023        {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1024        {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
1025        {USB_DEVICE(0x06d6, 0x0041), BS(SPCA504B, 0)},
1026        {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1027        {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1028        {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1029        {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1030        {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1031        {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1032        {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1033        {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1034        {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1035        {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1036        {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1037        {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1038        {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1039        {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1040        {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1041        {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1042        {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1043        {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1044        {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1045        {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1046        {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
1047        {}
1048};
1049MODULE_DEVICE_TABLE(usb, device_table);
1050
1051/* -- device connect -- */
1052static int sd_probe(struct usb_interface *intf,
1053                        const struct usb_device_id *id)
1054{
1055        return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1056                                THIS_MODULE);
1057}
1058
1059static struct usb_driver sd_driver = {
1060        .name = MODULE_NAME,
1061        .id_table = device_table,
1062        .probe = sd_probe,
1063        .disconnect = gspca_disconnect,
1064#ifdef CONFIG_PM
1065        .suspend = gspca_suspend,
1066        .resume = gspca_resume,
1067        .reset_resume = gspca_resume,
1068#endif
1069};
1070
1071module_usb_driver(sd_driver);
1072