Merge remote-tracking branch 'moduleh/module.h-split'
[linux-2.6/next.git] / drivers / media / video / gspca / sunplus.c
blob6ec232902183ebb7b2dc4c7afe93010b9c1cd791
1 /*
2 * Sunplus spca504(abc) spca533 spca536 library
3 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
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.
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.
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
22 #define MODULE_NAME "sunplus"
24 #include "gspca.h"
25 #include "jpeg.h"
27 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28 MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
29 MODULE_LICENSE("GPL");
31 /* specific webcam descriptor */
32 struct sd {
33 struct gspca_dev gspca_dev; /* !! must be the first item */
35 s8 brightness;
36 u8 contrast;
37 u8 colors;
38 u8 autogain;
39 u8 quality;
40 #define QUALITY_MIN 70
41 #define QUALITY_MAX 95
42 #define QUALITY_DEF 85
44 u8 bridge;
45 #define BRIDGE_SPCA504 0
46 #define BRIDGE_SPCA504B 1
47 #define BRIDGE_SPCA504C 2
48 #define BRIDGE_SPCA533 3
49 #define BRIDGE_SPCA536 4
50 u8 subtype;
51 #define AiptekMiniPenCam13 1
52 #define LogitechClickSmart420 2
53 #define LogitechClickSmart820 3
54 #define MegapixV4 4
55 #define MegaImageVI 5
57 u8 jpeg_hdr[JPEG_HDR_SZ];
60 /* V4L2 controls supported by the driver */
61 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
62 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
63 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
64 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
65 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
66 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
67 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
68 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
70 static const struct ctrl sd_ctrls[] = {
73 .id = V4L2_CID_BRIGHTNESS,
74 .type = V4L2_CTRL_TYPE_INTEGER,
75 .name = "Brightness",
76 .minimum = -128,
77 .maximum = 127,
78 .step = 1,
79 #define BRIGHTNESS_DEF 0
80 .default_value = BRIGHTNESS_DEF,
82 .set = sd_setbrightness,
83 .get = sd_getbrightness,
87 .id = V4L2_CID_CONTRAST,
88 .type = V4L2_CTRL_TYPE_INTEGER,
89 .name = "Contrast",
90 .minimum = 0,
91 .maximum = 0xff,
92 .step = 1,
93 #define CONTRAST_DEF 0x20
94 .default_value = CONTRAST_DEF,
96 .set = sd_setcontrast,
97 .get = sd_getcontrast,
101 .id = V4L2_CID_SATURATION,
102 .type = V4L2_CTRL_TYPE_INTEGER,
103 .name = "Color",
104 .minimum = 0,
105 .maximum = 0xff,
106 .step = 1,
107 #define COLOR_DEF 0x1a
108 .default_value = COLOR_DEF,
110 .set = sd_setcolors,
111 .get = sd_getcolors,
115 .id = V4L2_CID_AUTOGAIN,
116 .type = V4L2_CTRL_TYPE_BOOLEAN,
117 .name = "Auto Gain",
118 .minimum = 0,
119 .maximum = 1,
120 .step = 1,
121 #define AUTOGAIN_DEF 1
122 .default_value = AUTOGAIN_DEF,
124 .set = sd_setautogain,
125 .get = sd_getautogain,
129 static const struct v4l2_pix_format vga_mode[] = {
130 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
131 .bytesperline = 320,
132 .sizeimage = 320 * 240 * 3 / 8 + 590,
133 .colorspace = V4L2_COLORSPACE_JPEG,
134 .priv = 2},
135 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
136 .bytesperline = 640,
137 .sizeimage = 640 * 480 * 3 / 8 + 590,
138 .colorspace = V4L2_COLORSPACE_JPEG,
139 .priv = 1},
142 static const struct v4l2_pix_format custom_mode[] = {
143 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
144 .bytesperline = 320,
145 .sizeimage = 320 * 240 * 3 / 8 + 590,
146 .colorspace = V4L2_COLORSPACE_JPEG,
147 .priv = 2},
148 {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
149 .bytesperline = 464,
150 .sizeimage = 464 * 480 * 3 / 8 + 590,
151 .colorspace = V4L2_COLORSPACE_JPEG,
152 .priv = 1},
155 static const struct v4l2_pix_format vga_mode2[] = {
156 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
157 .bytesperline = 176,
158 .sizeimage = 176 * 144 * 3 / 8 + 590,
159 .colorspace = V4L2_COLORSPACE_JPEG,
160 .priv = 4},
161 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
162 .bytesperline = 320,
163 .sizeimage = 320 * 240 * 3 / 8 + 590,
164 .colorspace = V4L2_COLORSPACE_JPEG,
165 .priv = 3},
166 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
167 .bytesperline = 352,
168 .sizeimage = 352 * 288 * 3 / 8 + 590,
169 .colorspace = V4L2_COLORSPACE_JPEG,
170 .priv = 2},
171 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
172 .bytesperline = 640,
173 .sizeimage = 640 * 480 * 3 / 8 + 590,
174 .colorspace = V4L2_COLORSPACE_JPEG,
175 .priv = 1},
178 #define SPCA50X_OFFSET_DATA 10
179 #define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
180 #define SPCA504_PCCAM600_OFFSET_COMPRESS 4
181 #define SPCA504_PCCAM600_OFFSET_MODE 5
182 #define SPCA504_PCCAM600_OFFSET_DATA 14
183 /* Frame packet header offsets for the spca533 */
184 #define SPCA533_OFFSET_DATA 16
185 #define SPCA533_OFFSET_FRAMSEQ 15
186 /* Frame packet header offsets for the spca536 */
187 #define SPCA536_OFFSET_DATA 4
188 #define SPCA536_OFFSET_FRAMSEQ 1
190 struct cmd {
191 u8 req;
192 u16 val;
193 u16 idx;
196 /* Initialisation data for the Creative PC-CAM 600 */
197 static const struct cmd spca504_pccam600_init_data[] = {
198 /* {0xa0, 0x0000, 0x0503}, * capture mode */
199 {0x00, 0x0000, 0x2000},
200 {0x00, 0x0013, 0x2301},
201 {0x00, 0x0003, 0x2000},
202 {0x00, 0x0001, 0x21ac},
203 {0x00, 0x0001, 0x21a6},
204 {0x00, 0x0000, 0x21a7}, /* brightness */
205 {0x00, 0x0020, 0x21a8}, /* contrast */
206 {0x00, 0x0001, 0x21ac}, /* sat/hue */
207 {0x00, 0x0000, 0x21ad}, /* hue */
208 {0x00, 0x001a, 0x21ae}, /* saturation */
209 {0x00, 0x0002, 0x21a3}, /* gamma */
210 {0x30, 0x0154, 0x0008},
211 {0x30, 0x0004, 0x0006},
212 {0x30, 0x0258, 0x0009},
213 {0x30, 0x0004, 0x0000},
214 {0x30, 0x0093, 0x0004},
215 {0x30, 0x0066, 0x0005},
216 {0x00, 0x0000, 0x2000},
217 {0x00, 0x0013, 0x2301},
218 {0x00, 0x0003, 0x2000},
219 {0x00, 0x0013, 0x2301},
220 {0x00, 0x0003, 0x2000},
223 /* Creative PC-CAM 600 specific open data, sent before using the
224 * generic initialisation data from spca504_open_data.
226 static const struct cmd spca504_pccam600_open_data[] = {
227 {0x00, 0x0001, 0x2501},
228 {0x20, 0x0500, 0x0001}, /* snapshot mode */
229 {0x00, 0x0003, 0x2880},
230 {0x00, 0x0001, 0x2881},
233 /* Initialisation data for the logitech clicksmart 420 */
234 static const struct cmd spca504A_clicksmart420_init_data[] = {
235 /* {0xa0, 0x0000, 0x0503}, * capture mode */
236 {0x00, 0x0000, 0x2000},
237 {0x00, 0x0013, 0x2301},
238 {0x00, 0x0003, 0x2000},
239 {0x00, 0x0001, 0x21ac},
240 {0x00, 0x0001, 0x21a6},
241 {0x00, 0x0000, 0x21a7}, /* brightness */
242 {0x00, 0x0020, 0x21a8}, /* contrast */
243 {0x00, 0x0001, 0x21ac}, /* sat/hue */
244 {0x00, 0x0000, 0x21ad}, /* hue */
245 {0x00, 0x001a, 0x21ae}, /* saturation */
246 {0x00, 0x0002, 0x21a3}, /* gamma */
247 {0x30, 0x0004, 0x000a},
248 {0xb0, 0x0001, 0x0000},
250 {0xa1, 0x0080, 0x0001},
251 {0x30, 0x0049, 0x0000},
252 {0x30, 0x0060, 0x0005},
253 {0x0c, 0x0004, 0x0000},
254 {0x00, 0x0000, 0x0000},
255 {0x00, 0x0000, 0x2000},
256 {0x00, 0x0013, 0x2301},
257 {0x00, 0x0003, 0x2000},
260 /* clicksmart 420 open data ? */
261 static const struct cmd spca504A_clicksmart420_open_data[] = {
262 {0x00, 0x0001, 0x2501},
263 {0x20, 0x0502, 0x0000},
264 {0x06, 0x0000, 0x0000},
265 {0x00, 0x0004, 0x2880},
266 {0x00, 0x0001, 0x2881},
268 {0xa0, 0x0000, 0x0503},
271 static const u8 qtable_creative_pccam[2][64] = {
272 { /* Q-table Y-components */
273 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
274 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
275 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
276 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
277 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
278 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
279 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
280 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
281 { /* Q-table C-components */
282 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
283 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
284 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
285 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
286 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
287 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
288 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
289 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
292 /* FIXME: This Q-table is identical to the Creative PC-CAM one,
293 * except for one byte. Possibly a typo?
294 * NWG: 18/05/2003.
296 static const u8 qtable_spca504_default[2][64] = {
297 { /* Q-table Y-components */
298 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
299 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
300 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
301 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
302 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
303 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
304 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
305 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
307 { /* Q-table C-components */
308 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
309 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
310 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
311 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
312 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
313 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
314 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
315 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
318 /* read <len> bytes to gspca_dev->usb_buf */
319 static void reg_r(struct gspca_dev *gspca_dev,
320 u8 req,
321 u16 index,
322 u16 len)
324 int ret;
326 #ifdef GSPCA_DEBUG
327 if (len > USB_BUF_SZ) {
328 err("reg_r: buffer overflow");
329 return;
331 #endif
332 if (gspca_dev->usb_err < 0)
333 return;
334 ret = usb_control_msg(gspca_dev->dev,
335 usb_rcvctrlpipe(gspca_dev->dev, 0),
336 req,
337 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
338 0, /* value */
339 index,
340 len ? gspca_dev->usb_buf : NULL, len,
341 500);
342 if (ret < 0) {
343 err("reg_r err %d", ret);
344 gspca_dev->usb_err = ret;
348 /* write one byte */
349 static void reg_w_1(struct gspca_dev *gspca_dev,
350 u8 req,
351 u16 value,
352 u16 index,
353 u16 byte)
355 int ret;
357 if (gspca_dev->usb_err < 0)
358 return;
359 gspca_dev->usb_buf[0] = byte;
360 ret = usb_control_msg(gspca_dev->dev,
361 usb_sndctrlpipe(gspca_dev->dev, 0),
362 req,
363 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
364 value, index,
365 gspca_dev->usb_buf, 1,
366 500);
367 if (ret < 0) {
368 err("reg_w_1 err %d", ret);
369 gspca_dev->usb_err = ret;
373 /* write req / index / value */
374 static void reg_w_riv(struct gspca_dev *gspca_dev,
375 u8 req, u16 index, u16 value)
377 struct usb_device *dev = gspca_dev->dev;
378 int ret;
380 if (gspca_dev->usb_err < 0)
381 return;
382 ret = usb_control_msg(dev,
383 usb_sndctrlpipe(dev, 0),
384 req,
385 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
386 value, index, NULL, 0, 500);
387 if (ret < 0) {
388 err("reg_w_riv err %d", ret);
389 gspca_dev->usb_err = ret;
390 return;
392 PDEBUG(D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x",
393 req, index, value);
396 static void write_vector(struct gspca_dev *gspca_dev,
397 const struct cmd *data, int ncmds)
399 while (--ncmds >= 0) {
400 reg_w_riv(gspca_dev, data->req, data->idx, data->val);
401 data++;
405 static void setup_qtable(struct gspca_dev *gspca_dev,
406 const u8 qtable[2][64])
408 int i;
410 /* loop over y components */
411 for (i = 0; i < 64; i++)
412 reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]);
414 /* loop over c components */
415 for (i = 0; i < 64; i++)
416 reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]);
419 static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
420 u8 req, u16 idx, u16 val)
422 reg_w_riv(gspca_dev, req, idx, val);
423 reg_r(gspca_dev, 0x01, 0x0001, 1);
424 PDEBUG(D_FRAM, "before wait 0x%04x", gspca_dev->usb_buf[0]);
425 reg_w_riv(gspca_dev, req, idx, val);
427 msleep(200);
428 reg_r(gspca_dev, 0x01, 0x0001, 1);
429 PDEBUG(D_FRAM, "after wait 0x%04x", gspca_dev->usb_buf[0]);
432 #ifdef GSPCA_DEBUG
433 static void spca504_read_info(struct gspca_dev *gspca_dev)
435 int i;
436 u8 info[6];
438 for (i = 0; i < 6; i++) {
439 reg_r(gspca_dev, 0, i, 1);
440 info[i] = gspca_dev->usb_buf[0];
442 PDEBUG(D_STREAM,
443 "Read info: %d %d %d %d %d %d."
444 " Should be 1,0,2,2,0,0",
445 info[0], info[1], info[2],
446 info[3], info[4], info[5]);
448 #endif
450 static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
451 u8 req,
452 u16 idx, u16 val, u8 endcode, u8 count)
454 u16 status;
456 reg_w_riv(gspca_dev, req, idx, val);
457 reg_r(gspca_dev, 0x01, 0x0001, 1);
458 if (gspca_dev->usb_err < 0)
459 return;
460 PDEBUG(D_FRAM, "Status 0x%02x Need 0x%02x",
461 gspca_dev->usb_buf[0], endcode);
462 if (!count)
463 return;
464 count = 200;
465 while (--count > 0) {
466 msleep(10);
467 /* gsmart mini2 write a each wait setting 1 ms is enough */
468 /* reg_w_riv(gspca_dev, req, idx, val); */
469 reg_r(gspca_dev, 0x01, 0x0001, 1);
470 status = gspca_dev->usb_buf[0];
471 if (status == endcode) {
472 PDEBUG(D_FRAM, "status 0x%04x after wait %d",
473 status, 200 - count);
474 break;
479 static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
481 int count = 10;
483 while (--count > 0) {
484 reg_r(gspca_dev, 0x21, 0, 1);
485 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
486 break;
487 msleep(10);
491 static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
493 int count = 50;
495 while (--count > 0) {
496 reg_r(gspca_dev, 0x21, 1, 1);
497 if (gspca_dev->usb_buf[0] != 0) {
498 reg_w_1(gspca_dev, 0x21, 0, 1, 0);
499 reg_r(gspca_dev, 0x21, 1, 1);
500 spca504B_PollingDataReady(gspca_dev);
501 break;
503 msleep(10);
507 #ifdef GSPCA_DEBUG
508 static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
510 u8 *data;
512 data = gspca_dev->usb_buf;
513 reg_r(gspca_dev, 0x20, 0, 5);
514 PDEBUG(D_STREAM, "FirmWare: %d %d %d %d %d",
515 data[0], data[1], data[2], data[3], data[4]);
516 reg_r(gspca_dev, 0x23, 0, 64);
517 reg_r(gspca_dev, 0x23, 1, 64);
519 #endif
521 static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
523 struct sd *sd = (struct sd *) gspca_dev;
524 u8 Size;
526 Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
527 switch (sd->bridge) {
528 case BRIDGE_SPCA533:
529 reg_w_riv(gspca_dev, 0x31, 0, 0);
530 spca504B_WaitCmdStatus(gspca_dev);
531 spca504B_PollingDataReady(gspca_dev);
532 #ifdef GSPCA_DEBUG
533 spca50x_GetFirmware(gspca_dev);
534 #endif
535 reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */
536 reg_r(gspca_dev, 0x24, 8, 1);
538 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
539 reg_r(gspca_dev, 0x25, 4, 1); /* size */
540 spca504B_PollingDataReady(gspca_dev);
542 /* Init the cam width height with some values get on init ? */
543 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
544 spca504B_WaitCmdStatus(gspca_dev);
545 spca504B_PollingDataReady(gspca_dev);
546 break;
547 default:
548 /* case BRIDGE_SPCA504B: */
549 /* case BRIDGE_SPCA536: */
550 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
551 reg_r(gspca_dev, 0x25, 4, 1); /* size */
552 reg_w_1(gspca_dev, 0x27, 0, 0, 6);
553 reg_r(gspca_dev, 0x27, 0, 1); /* type */
554 spca504B_PollingDataReady(gspca_dev);
555 break;
556 case BRIDGE_SPCA504:
557 Size += 3;
558 if (sd->subtype == AiptekMiniPenCam13) {
559 /* spca504a aiptek */
560 spca504A_acknowledged_command(gspca_dev,
561 0x08, Size, 0,
562 0x80 | (Size & 0x0f), 1);
563 spca504A_acknowledged_command(gspca_dev,
564 1, 3, 0, 0x9f, 0);
565 } else {
566 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
568 break;
569 case BRIDGE_SPCA504C:
570 /* capture mode */
571 reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
572 reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
573 break;
577 static void spca504_wait_status(struct gspca_dev *gspca_dev)
579 int cnt;
581 cnt = 256;
582 while (--cnt > 0) {
583 /* With this we get the status, when return 0 it's all ok */
584 reg_r(gspca_dev, 0x06, 0x00, 1);
585 if (gspca_dev->usb_buf[0] == 0)
586 return;
587 msleep(10);
591 static void spca504B_setQtable(struct gspca_dev *gspca_dev)
593 reg_w_1(gspca_dev, 0x26, 0, 0, 3);
594 reg_r(gspca_dev, 0x26, 0, 1);
595 spca504B_PollingDataReady(gspca_dev);
598 static void setbrightness(struct gspca_dev *gspca_dev)
600 struct sd *sd = (struct sd *) gspca_dev;
601 u16 reg;
603 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
604 reg_w_riv(gspca_dev, 0x00, reg, sd->brightness);
607 static void setcontrast(struct gspca_dev *gspca_dev)
609 struct sd *sd = (struct sd *) gspca_dev;
610 u16 reg;
612 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
613 reg_w_riv(gspca_dev, 0x00, reg, sd->contrast);
616 static void setcolors(struct gspca_dev *gspca_dev)
618 struct sd *sd = (struct sd *) gspca_dev;
619 u16 reg;
621 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
622 reg_w_riv(gspca_dev, 0x00, reg, sd->colors);
625 static void init_ctl_reg(struct gspca_dev *gspca_dev)
627 struct sd *sd = (struct sd *) gspca_dev;
628 int pollreg = 1;
630 setbrightness(gspca_dev);
631 setcontrast(gspca_dev);
632 setcolors(gspca_dev);
634 switch (sd->bridge) {
635 case BRIDGE_SPCA504:
636 case BRIDGE_SPCA504C:
637 pollreg = 0;
638 /* fall thru */
639 default:
640 /* case BRIDGE_SPCA533: */
641 /* case BRIDGE_SPCA504B: */
642 reg_w_riv(gspca_dev, 0, 0x21ad, 0x00); /* hue */
643 reg_w_riv(gspca_dev, 0, 0x21ac, 0x01); /* sat/hue */
644 reg_w_riv(gspca_dev, 0, 0x21a3, 0x00); /* gamma */
645 break;
646 case BRIDGE_SPCA536:
647 reg_w_riv(gspca_dev, 0, 0x20f5, 0x40);
648 reg_w_riv(gspca_dev, 0, 0x20f4, 0x01);
649 reg_w_riv(gspca_dev, 0, 0x2089, 0x00);
650 break;
652 if (pollreg)
653 spca504B_PollingDataReady(gspca_dev);
656 /* this function is called at probe time */
657 static int sd_config(struct gspca_dev *gspca_dev,
658 const struct usb_device_id *id)
660 struct sd *sd = (struct sd *) gspca_dev;
661 struct cam *cam;
663 cam = &gspca_dev->cam;
665 sd->bridge = id->driver_info >> 8;
666 sd->subtype = id->driver_info;
668 if (sd->subtype == AiptekMiniPenCam13) {
670 /* try to get the firmware as some cam answer 2.0.1.2.2
671 * and should be a spca504b then overwrite that setting */
672 reg_r(gspca_dev, 0x20, 0, 1);
673 switch (gspca_dev->usb_buf[0]) {
674 case 1:
675 break; /* (right bridge/subtype) */
676 case 2:
677 sd->bridge = BRIDGE_SPCA504B;
678 sd->subtype = 0;
679 break;
680 default:
681 return -ENODEV;
685 switch (sd->bridge) {
686 default:
687 /* case BRIDGE_SPCA504B: */
688 /* case BRIDGE_SPCA504: */
689 /* case BRIDGE_SPCA536: */
690 cam->cam_mode = vga_mode;
691 cam->nmodes = ARRAY_SIZE(vga_mode);
692 break;
693 case BRIDGE_SPCA533:
694 cam->cam_mode = custom_mode;
695 if (sd->subtype == MegaImageVI) /* 320x240 only */
696 cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
697 else
698 cam->nmodes = ARRAY_SIZE(custom_mode);
699 break;
700 case BRIDGE_SPCA504C:
701 cam->cam_mode = vga_mode2;
702 cam->nmodes = ARRAY_SIZE(vga_mode2);
703 break;
705 sd->brightness = BRIGHTNESS_DEF;
706 sd->contrast = CONTRAST_DEF;
707 sd->colors = COLOR_DEF;
708 sd->autogain = AUTOGAIN_DEF;
709 sd->quality = QUALITY_DEF;
710 return 0;
713 /* this function is called at probe and resume time */
714 static int sd_init(struct gspca_dev *gspca_dev)
716 struct sd *sd = (struct sd *) gspca_dev;
718 switch (sd->bridge) {
719 case BRIDGE_SPCA504B:
720 reg_w_riv(gspca_dev, 0x1d, 0x00, 0);
721 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01);
722 reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00);
723 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00);
724 reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13);
725 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00);
726 /* fall thru */
727 case BRIDGE_SPCA533:
728 spca504B_PollingDataReady(gspca_dev);
729 #ifdef GSPCA_DEBUG
730 spca50x_GetFirmware(gspca_dev);
731 #endif
732 break;
733 case BRIDGE_SPCA536:
734 #ifdef GSPCA_DEBUG
735 spca50x_GetFirmware(gspca_dev);
736 #endif
737 reg_r(gspca_dev, 0x00, 0x5002, 1);
738 reg_w_1(gspca_dev, 0x24, 0, 0, 0);
739 reg_r(gspca_dev, 0x24, 0, 1);
740 spca504B_PollingDataReady(gspca_dev);
741 reg_w_riv(gspca_dev, 0x34, 0, 0);
742 spca504B_WaitCmdStatus(gspca_dev);
743 break;
744 case BRIDGE_SPCA504C: /* pccam600 */
745 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
746 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000);
747 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001); /* reset */
748 spca504_wait_status(gspca_dev);
749 if (sd->subtype == LogitechClickSmart420)
750 write_vector(gspca_dev,
751 spca504A_clicksmart420_open_data,
752 ARRAY_SIZE(spca504A_clicksmart420_open_data));
753 else
754 write_vector(gspca_dev, spca504_pccam600_open_data,
755 ARRAY_SIZE(spca504_pccam600_open_data));
756 setup_qtable(gspca_dev, qtable_creative_pccam);
757 break;
758 default:
759 /* case BRIDGE_SPCA504: */
760 PDEBUG(D_STREAM, "Opening SPCA504");
761 if (sd->subtype == AiptekMiniPenCam13) {
762 #ifdef GSPCA_DEBUG
763 spca504_read_info(gspca_dev);
764 #endif
766 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
767 spca504A_acknowledged_command(gspca_dev, 0x24,
768 8, 3, 0x9e, 1);
769 /* Twice sequential need status 0xff->0x9e->0x9d */
770 spca504A_acknowledged_command(gspca_dev, 0x24,
771 8, 3, 0x9e, 0);
773 spca504A_acknowledged_command(gspca_dev, 0x24,
774 0, 0, 0x9d, 1);
775 /******************************/
776 /* spca504a aiptek */
777 spca504A_acknowledged_command(gspca_dev, 0x08,
778 6, 0, 0x86, 1);
779 /* reg_write (dev, 0, 0x2000, 0); */
780 /* reg_write (dev, 0, 0x2883, 1); */
781 /* spca504A_acknowledged_command (gspca_dev, 0x08,
782 6, 0, 0x86, 1); */
783 /* spca504A_acknowledged_command (gspca_dev, 0x24,
784 0, 0, 0x9D, 1); */
785 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
786 /* L92 sno1t.txt */
787 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
788 spca504A_acknowledged_command(gspca_dev, 0x01,
789 0x0f, 0, 0xff, 0);
791 /* setup qtable */
792 reg_w_riv(gspca_dev, 0, 0x2000, 0);
793 reg_w_riv(gspca_dev, 0, 0x2883, 1);
794 setup_qtable(gspca_dev, qtable_spca504_default);
795 break;
797 return gspca_dev->usb_err;
800 static int sd_start(struct gspca_dev *gspca_dev)
802 struct sd *sd = (struct sd *) gspca_dev;
803 int enable;
805 /* create the JPEG header */
806 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
807 0x22); /* JPEG 411 */
808 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
810 if (sd->bridge == BRIDGE_SPCA504B)
811 spca504B_setQtable(gspca_dev);
812 spca504B_SetSizeType(gspca_dev);
813 switch (sd->bridge) {
814 default:
815 /* case BRIDGE_SPCA504B: */
816 /* case BRIDGE_SPCA533: */
817 /* case BRIDGE_SPCA536: */
818 switch (sd->subtype) {
819 case MegapixV4:
820 case LogitechClickSmart820:
821 case MegaImageVI:
822 reg_w_riv(gspca_dev, 0xf0, 0, 0);
823 spca504B_WaitCmdStatus(gspca_dev);
824 reg_r(gspca_dev, 0xf0, 4, 0);
825 spca504B_WaitCmdStatus(gspca_dev);
826 break;
827 default:
828 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
829 spca504B_WaitCmdStatus(gspca_dev);
830 spca504B_PollingDataReady(gspca_dev);
831 break;
833 break;
834 case BRIDGE_SPCA504:
835 if (sd->subtype == AiptekMiniPenCam13) {
836 #ifdef GSPCA_DEBUG
837 spca504_read_info(gspca_dev);
838 #endif
840 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
841 spca504A_acknowledged_command(gspca_dev, 0x24,
842 8, 3, 0x9e, 1);
843 /* Twice sequential need status 0xff->0x9e->0x9d */
844 spca504A_acknowledged_command(gspca_dev, 0x24,
845 8, 3, 0x9e, 0);
846 spca504A_acknowledged_command(gspca_dev, 0x24,
847 0, 0, 0x9d, 1);
848 } else {
849 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
850 #ifdef GSPCA_DEBUG
851 spca504_read_info(gspca_dev);
852 #endif
853 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
854 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
856 spca504B_SetSizeType(gspca_dev);
857 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
858 /* L92 sno1t.txt */
859 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
860 break;
861 case BRIDGE_SPCA504C:
862 if (sd->subtype == LogitechClickSmart420) {
863 write_vector(gspca_dev,
864 spca504A_clicksmart420_init_data,
865 ARRAY_SIZE(spca504A_clicksmart420_init_data));
866 } else {
867 write_vector(gspca_dev, spca504_pccam600_init_data,
868 ARRAY_SIZE(spca504_pccam600_init_data));
870 enable = (sd->autogain ? 0x04 : 0x01);
871 reg_w_riv(gspca_dev, 0x0c, 0x0000, enable);
872 /* auto exposure */
873 reg_w_riv(gspca_dev, 0xb0, 0x0000, enable);
874 /* auto whiteness */
876 /* set default exposure compensation and whiteness balance */
877 reg_w_riv(gspca_dev, 0x30, 0x0001, 800); /* ~ 20 fps */
878 reg_w_riv(gspca_dev, 0x30, 0x0002, 1600);
879 spca504B_SetSizeType(gspca_dev);
880 break;
882 init_ctl_reg(gspca_dev);
883 return gspca_dev->usb_err;
886 static void sd_stopN(struct gspca_dev *gspca_dev)
888 struct sd *sd = (struct sd *) gspca_dev;
890 switch (sd->bridge) {
891 default:
892 /* case BRIDGE_SPCA533: */
893 /* case BRIDGE_SPCA536: */
894 /* case BRIDGE_SPCA504B: */
895 reg_w_riv(gspca_dev, 0x31, 0, 0);
896 spca504B_WaitCmdStatus(gspca_dev);
897 spca504B_PollingDataReady(gspca_dev);
898 break;
899 case BRIDGE_SPCA504:
900 case BRIDGE_SPCA504C:
901 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000);
903 if (sd->subtype == AiptekMiniPenCam13) {
904 /* spca504a aiptek */
905 /* spca504A_acknowledged_command(gspca_dev, 0x08,
906 6, 0, 0x86, 1); */
907 spca504A_acknowledged_command(gspca_dev, 0x24,
908 0x00, 0x00, 0x9d, 1);
909 spca504A_acknowledged_command(gspca_dev, 0x01,
910 0x0f, 0x00, 0xff, 1);
911 } else {
912 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
913 reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000);
915 break;
919 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
920 u8 *data, /* isoc packet */
921 int len) /* iso packet length */
923 struct sd *sd = (struct sd *) gspca_dev;
924 int i, sof = 0;
925 static u8 ffd9[] = {0xff, 0xd9};
927 /* frames are jpeg 4.1.1 without 0xff escape */
928 switch (sd->bridge) {
929 case BRIDGE_SPCA533:
930 if (data[0] == 0xff) {
931 if (data[1] != 0x01) { /* drop packet */
932 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
933 return;
935 sof = 1;
936 data += SPCA533_OFFSET_DATA;
937 len -= SPCA533_OFFSET_DATA;
938 } else {
939 data += 1;
940 len -= 1;
942 break;
943 case BRIDGE_SPCA536:
944 if (data[0] == 0xff) {
945 sof = 1;
946 data += SPCA536_OFFSET_DATA;
947 len -= SPCA536_OFFSET_DATA;
948 } else {
949 data += 2;
950 len -= 2;
952 break;
953 default:
954 /* case BRIDGE_SPCA504: */
955 /* case BRIDGE_SPCA504B: */
956 switch (data[0]) {
957 case 0xfe: /* start of frame */
958 sof = 1;
959 data += SPCA50X_OFFSET_DATA;
960 len -= SPCA50X_OFFSET_DATA;
961 break;
962 case 0xff: /* drop packet */
963 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
964 return;
965 default:
966 data += 1;
967 len -= 1;
968 break;
970 break;
971 case BRIDGE_SPCA504C:
972 switch (data[0]) {
973 case 0xfe: /* start of frame */
974 sof = 1;
975 data += SPCA504_PCCAM600_OFFSET_DATA;
976 len -= SPCA504_PCCAM600_OFFSET_DATA;
977 break;
978 case 0xff: /* drop packet */
979 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
980 return;
981 default:
982 data += 1;
983 len -= 1;
984 break;
986 break;
988 if (sof) { /* start of frame */
989 gspca_frame_add(gspca_dev, LAST_PACKET,
990 ffd9, 2);
992 /* put the JPEG header in the new frame */
993 gspca_frame_add(gspca_dev, FIRST_PACKET,
994 sd->jpeg_hdr, JPEG_HDR_SZ);
997 /* add 0x00 after 0xff */
998 i = 0;
999 do {
1000 if (data[i] == 0xff) {
1001 gspca_frame_add(gspca_dev, INTER_PACKET,
1002 data, i + 1);
1003 len -= i;
1004 data += i;
1005 *data = 0x00;
1006 i = 0;
1008 i++;
1009 } while (i < len);
1010 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1013 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1015 struct sd *sd = (struct sd *) gspca_dev;
1017 sd->brightness = val;
1018 if (gspca_dev->streaming)
1019 setbrightness(gspca_dev);
1020 return gspca_dev->usb_err;
1023 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1025 struct sd *sd = (struct sd *) gspca_dev;
1027 *val = sd->brightness;
1028 return 0;
1031 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1033 struct sd *sd = (struct sd *) gspca_dev;
1035 sd->contrast = val;
1036 if (gspca_dev->streaming)
1037 setcontrast(gspca_dev);
1038 return gspca_dev->usb_err;
1041 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1043 struct sd *sd = (struct sd *) gspca_dev;
1045 *val = sd->contrast;
1046 return 0;
1049 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1051 struct sd *sd = (struct sd *) gspca_dev;
1053 sd->colors = val;
1054 if (gspca_dev->streaming)
1055 setcolors(gspca_dev);
1056 return gspca_dev->usb_err;
1059 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1061 struct sd *sd = (struct sd *) gspca_dev;
1063 *val = sd->colors;
1064 return 0;
1067 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1069 struct sd *sd = (struct sd *) gspca_dev;
1071 sd->autogain = val;
1072 return 0;
1075 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1077 struct sd *sd = (struct sd *) gspca_dev;
1079 *val = sd->autogain;
1080 return 0;
1083 static int sd_set_jcomp(struct gspca_dev *gspca_dev,
1084 struct v4l2_jpegcompression *jcomp)
1086 struct sd *sd = (struct sd *) gspca_dev;
1088 if (jcomp->quality < QUALITY_MIN)
1089 sd->quality = QUALITY_MIN;
1090 else if (jcomp->quality > QUALITY_MAX)
1091 sd->quality = QUALITY_MAX;
1092 else
1093 sd->quality = jcomp->quality;
1094 if (gspca_dev->streaming)
1095 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
1096 return gspca_dev->usb_err;
1099 static int sd_get_jcomp(struct gspca_dev *gspca_dev,
1100 struct v4l2_jpegcompression *jcomp)
1102 struct sd *sd = (struct sd *) gspca_dev;
1104 memset(jcomp, 0, sizeof *jcomp);
1105 jcomp->quality = sd->quality;
1106 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
1107 | V4L2_JPEG_MARKER_DQT;
1108 return 0;
1111 /* sub-driver description */
1112 static const struct sd_desc sd_desc = {
1113 .name = MODULE_NAME,
1114 .ctrls = sd_ctrls,
1115 .nctrls = ARRAY_SIZE(sd_ctrls),
1116 .config = sd_config,
1117 .init = sd_init,
1118 .start = sd_start,
1119 .stopN = sd_stopN,
1120 .pkt_scan = sd_pkt_scan,
1121 .get_jcomp = sd_get_jcomp,
1122 .set_jcomp = sd_set_jcomp,
1125 /* -- module initialisation -- */
1126 #define BS(bridge, subtype) \
1127 .driver_info = (BRIDGE_ ## bridge << 8) \
1128 | (subtype)
1129 static const struct usb_device_id device_table[] = {
1130 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
1131 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
1132 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
1133 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
1134 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
1135 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
1136 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
1137 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
1138 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
1139 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
1140 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
1141 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
1142 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
1143 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
1144 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
1145 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
1146 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
1147 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
1148 {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)},
1149 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
1150 {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
1151 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1152 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1153 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1154 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1155 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1156 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1157 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1158 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1159 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1160 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1161 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1162 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1163 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1164 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1165 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1166 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1167 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
1168 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1169 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1170 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1171 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1172 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1173 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1174 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1175 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1176 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1177 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1178 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1179 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1180 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1181 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1182 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1183 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1184 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1185 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1186 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1187 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1188 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
1191 MODULE_DEVICE_TABLE(usb, device_table);
1193 /* -- device connect -- */
1194 static int sd_probe(struct usb_interface *intf,
1195 const struct usb_device_id *id)
1197 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1198 THIS_MODULE);
1201 static struct usb_driver sd_driver = {
1202 .name = MODULE_NAME,
1203 .id_table = device_table,
1204 .probe = sd_probe,
1205 .disconnect = gspca_disconnect,
1206 #ifdef CONFIG_PM
1207 .suspend = gspca_suspend,
1208 .resume = gspca_resume,
1209 #endif
1212 /* -- module insert / remove -- */
1213 static int __init sd_mod_init(void)
1215 return usb_register(&sd_driver);
1217 static void __exit sd_mod_exit(void)
1219 usb_deregister(&sd_driver);
1222 module_init(sd_mod_init);
1223 module_exit(sd_mod_exit);