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