drivers/tty/serial/8250_pci.c: fix warning
[linux-2.6/next.git] / drivers / media / video / gspca / sunplus.c
blobb089c0d3ee9f96dc7b2de6f770105efe35db1503
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},
251 {0xa1, 0x0080, 0x0001},
252 {0x30, 0x0049, 0x0000},
253 {0x30, 0x0060, 0x0005},
254 {0x0c, 0x0004, 0x0000},
255 {0x00, 0x0000, 0x0000},
256 {0x00, 0x0000, 0x2000},
257 {0x00, 0x0013, 0x2301},
258 {0x00, 0x0003, 0x2000},
259 {0x00, 0x0000, 0x2000},
263 /* clicksmart 420 open data ? */
264 static const struct cmd spca504A_clicksmart420_open_data[] = {
265 {0x00, 0x0001, 0x2501},
266 {0x20, 0x0502, 0x0000},
267 {0x06, 0x0000, 0x0000},
268 {0x00, 0x0004, 0x2880},
269 {0x00, 0x0001, 0x2881},
271 {0xa0, 0x0000, 0x0503},
274 static const u8 qtable_creative_pccam[2][64] = {
275 { /* Q-table Y-components */
276 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
277 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
278 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
279 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
280 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
281 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
282 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
283 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
284 { /* Q-table C-components */
285 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
286 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
287 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
288 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
289 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
290 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
291 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
292 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
295 /* FIXME: This Q-table is identical to the Creative PC-CAM one,
296 * except for one byte. Possibly a typo?
297 * NWG: 18/05/2003.
299 static const u8 qtable_spca504_default[2][64] = {
300 { /* Q-table Y-components */
301 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
302 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
303 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
304 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
305 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
306 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
307 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
308 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
310 { /* Q-table C-components */
311 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
312 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
313 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
314 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
315 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
316 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
317 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
318 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
321 /* read <len> bytes to gspca_dev->usb_buf */
322 static void reg_r(struct gspca_dev *gspca_dev,
323 u8 req,
324 u16 index,
325 u16 len)
327 int ret;
329 #ifdef GSPCA_DEBUG
330 if (len > USB_BUF_SZ) {
331 err("reg_r: buffer overflow");
332 return;
334 #endif
335 if (gspca_dev->usb_err < 0)
336 return;
337 ret = usb_control_msg(gspca_dev->dev,
338 usb_rcvctrlpipe(gspca_dev->dev, 0),
339 req,
340 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
341 0, /* value */
342 index,
343 len ? gspca_dev->usb_buf : NULL, len,
344 500);
345 if (ret < 0) {
346 err("reg_r err %d", ret);
347 gspca_dev->usb_err = ret;
351 /* write one byte */
352 static void reg_w_1(struct gspca_dev *gspca_dev,
353 u8 req,
354 u16 value,
355 u16 index,
356 u16 byte)
358 int ret;
360 if (gspca_dev->usb_err < 0)
361 return;
362 gspca_dev->usb_buf[0] = byte;
363 ret = usb_control_msg(gspca_dev->dev,
364 usb_sndctrlpipe(gspca_dev->dev, 0),
365 req,
366 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
367 value, index,
368 gspca_dev->usb_buf, 1,
369 500);
370 if (ret < 0) {
371 err("reg_w_1 err %d", ret);
372 gspca_dev->usb_err = ret;
376 /* write req / index / value */
377 static void reg_w_riv(struct gspca_dev *gspca_dev,
378 u8 req, u16 index, u16 value)
380 struct usb_device *dev = gspca_dev->dev;
381 int ret;
383 if (gspca_dev->usb_err < 0)
384 return;
385 ret = usb_control_msg(dev,
386 usb_sndctrlpipe(dev, 0),
387 req,
388 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
389 value, index, NULL, 0, 500);
390 if (ret < 0) {
391 err("reg_w_riv err %d", ret);
392 gspca_dev->usb_err = ret;
393 return;
395 PDEBUG(D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x",
396 req, index, value);
399 static void write_vector(struct gspca_dev *gspca_dev,
400 const struct cmd *data, int ncmds)
402 while (--ncmds >= 0) {
403 reg_w_riv(gspca_dev, data->req, data->idx, data->val);
404 data++;
408 static void setup_qtable(struct gspca_dev *gspca_dev,
409 const u8 qtable[2][64])
411 int i;
413 /* loop over y components */
414 for (i = 0; i < 64; i++)
415 reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]);
417 /* loop over c components */
418 for (i = 0; i < 64; i++)
419 reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]);
422 static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
423 u8 req, u16 idx, u16 val)
425 reg_w_riv(gspca_dev, req, idx, val);
426 reg_r(gspca_dev, 0x01, 0x0001, 1);
427 PDEBUG(D_FRAM, "before wait 0x%04x", gspca_dev->usb_buf[0]);
428 reg_w_riv(gspca_dev, req, idx, val);
430 msleep(200);
431 reg_r(gspca_dev, 0x01, 0x0001, 1);
432 PDEBUG(D_FRAM, "after wait 0x%04x", gspca_dev->usb_buf[0]);
435 #ifdef GSPCA_DEBUG
436 static void spca504_read_info(struct gspca_dev *gspca_dev)
438 int i;
439 u8 info[6];
441 for (i = 0; i < 6; i++) {
442 reg_r(gspca_dev, 0, i, 1);
443 info[i] = gspca_dev->usb_buf[0];
445 PDEBUG(D_STREAM,
446 "Read info: %d %d %d %d %d %d."
447 " Should be 1,0,2,2,0,0",
448 info[0], info[1], info[2],
449 info[3], info[4], info[5]);
451 #endif
453 static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
454 u8 req,
455 u16 idx, u16 val, u8 endcode, u8 count)
457 u16 status;
459 reg_w_riv(gspca_dev, req, idx, val);
460 reg_r(gspca_dev, 0x01, 0x0001, 1);
461 if (gspca_dev->usb_err < 0)
462 return;
463 PDEBUG(D_FRAM, "Status 0x%02x Need 0x%02x",
464 gspca_dev->usb_buf[0], endcode);
465 if (!count)
466 return;
467 count = 200;
468 while (--count > 0) {
469 msleep(10);
470 /* gsmart mini2 write a each wait setting 1 ms is enough */
471 /* reg_w_riv(gspca_dev, req, idx, val); */
472 reg_r(gspca_dev, 0x01, 0x0001, 1);
473 status = gspca_dev->usb_buf[0];
474 if (status == endcode) {
475 PDEBUG(D_FRAM, "status 0x%04x after wait %d",
476 status, 200 - count);
477 break;
482 static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
484 int count = 10;
486 while (--count > 0) {
487 reg_r(gspca_dev, 0x21, 0, 1);
488 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
489 break;
490 msleep(10);
494 static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
496 int count = 50;
498 while (--count > 0) {
499 reg_r(gspca_dev, 0x21, 1, 1);
500 if (gspca_dev->usb_buf[0] != 0) {
501 reg_w_1(gspca_dev, 0x21, 0, 1, 0);
502 reg_r(gspca_dev, 0x21, 1, 1);
503 spca504B_PollingDataReady(gspca_dev);
504 break;
506 msleep(10);
510 #ifdef GSPCA_DEBUG
511 static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
513 u8 *data;
515 data = gspca_dev->usb_buf;
516 reg_r(gspca_dev, 0x20, 0, 5);
517 PDEBUG(D_STREAM, "FirmWare: %d %d %d %d %d",
518 data[0], data[1], data[2], data[3], data[4]);
519 reg_r(gspca_dev, 0x23, 0, 64);
520 reg_r(gspca_dev, 0x23, 1, 64);
522 #endif
524 static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
526 struct sd *sd = (struct sd *) gspca_dev;
527 u8 Size;
529 Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
530 switch (sd->bridge) {
531 case BRIDGE_SPCA533:
532 reg_w_riv(gspca_dev, 0x31, 0, 0);
533 spca504B_WaitCmdStatus(gspca_dev);
534 spca504B_PollingDataReady(gspca_dev);
535 #ifdef GSPCA_DEBUG
536 spca50x_GetFirmware(gspca_dev);
537 #endif
538 reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */
539 reg_r(gspca_dev, 0x24, 8, 1);
541 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
542 reg_r(gspca_dev, 0x25, 4, 1); /* size */
543 spca504B_PollingDataReady(gspca_dev);
545 /* Init the cam width height with some values get on init ? */
546 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
547 spca504B_WaitCmdStatus(gspca_dev);
548 spca504B_PollingDataReady(gspca_dev);
549 break;
550 default:
551 /* case BRIDGE_SPCA504B: */
552 /* case BRIDGE_SPCA536: */
553 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
554 reg_r(gspca_dev, 0x25, 4, 1); /* size */
555 reg_w_1(gspca_dev, 0x27, 0, 0, 6);
556 reg_r(gspca_dev, 0x27, 0, 1); /* type */
557 spca504B_PollingDataReady(gspca_dev);
558 break;
559 case BRIDGE_SPCA504:
560 Size += 3;
561 if (sd->subtype == AiptekMiniPenCam13) {
562 /* spca504a aiptek */
563 spca504A_acknowledged_command(gspca_dev,
564 0x08, Size, 0,
565 0x80 | (Size & 0x0f), 1);
566 spca504A_acknowledged_command(gspca_dev,
567 1, 3, 0, 0x9f, 0);
568 } else {
569 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
571 break;
572 case BRIDGE_SPCA504C:
573 /* capture mode */
574 reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
575 reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
576 break;
580 static void spca504_wait_status(struct gspca_dev *gspca_dev)
582 int cnt;
584 cnt = 256;
585 while (--cnt > 0) {
586 /* With this we get the status, when return 0 it's all ok */
587 reg_r(gspca_dev, 0x06, 0x00, 1);
588 if (gspca_dev->usb_buf[0] == 0)
589 return;
590 msleep(10);
594 static void spca504B_setQtable(struct gspca_dev *gspca_dev)
596 reg_w_1(gspca_dev, 0x26, 0, 0, 3);
597 reg_r(gspca_dev, 0x26, 0, 1);
598 spca504B_PollingDataReady(gspca_dev);
601 static void setbrightness(struct gspca_dev *gspca_dev)
603 struct sd *sd = (struct sd *) gspca_dev;
604 u16 reg;
606 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
607 reg_w_riv(gspca_dev, 0x00, reg, sd->brightness);
610 static void setcontrast(struct gspca_dev *gspca_dev)
612 struct sd *sd = (struct sd *) gspca_dev;
613 u16 reg;
615 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
616 reg_w_riv(gspca_dev, 0x00, reg, sd->contrast);
619 static void setcolors(struct gspca_dev *gspca_dev)
621 struct sd *sd = (struct sd *) gspca_dev;
622 u16 reg;
624 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
625 reg_w_riv(gspca_dev, 0x00, reg, sd->colors);
628 static void init_ctl_reg(struct gspca_dev *gspca_dev)
630 struct sd *sd = (struct sd *) gspca_dev;
631 int pollreg = 1;
633 setbrightness(gspca_dev);
634 setcontrast(gspca_dev);
635 setcolors(gspca_dev);
637 switch (sd->bridge) {
638 case BRIDGE_SPCA504:
639 case BRIDGE_SPCA504C:
640 pollreg = 0;
641 /* fall thru */
642 default:
643 /* case BRIDGE_SPCA533: */
644 /* case BRIDGE_SPCA504B: */
645 reg_w_riv(gspca_dev, 0, 0x21ad, 0x00); /* hue */
646 reg_w_riv(gspca_dev, 0, 0x21ac, 0x01); /* sat/hue */
647 reg_w_riv(gspca_dev, 0, 0x21a3, 0x00); /* gamma */
648 break;
649 case BRIDGE_SPCA536:
650 reg_w_riv(gspca_dev, 0, 0x20f5, 0x40);
651 reg_w_riv(gspca_dev, 0, 0x20f4, 0x01);
652 reg_w_riv(gspca_dev, 0, 0x2089, 0x00);
653 break;
655 if (pollreg)
656 spca504B_PollingDataReady(gspca_dev);
659 /* this function is called at probe time */
660 static int sd_config(struct gspca_dev *gspca_dev,
661 const struct usb_device_id *id)
663 struct sd *sd = (struct sd *) gspca_dev;
664 struct cam *cam;
666 cam = &gspca_dev->cam;
668 sd->bridge = id->driver_info >> 8;
669 sd->subtype = id->driver_info;
671 if (sd->subtype == AiptekMiniPenCam13) {
673 /* try to get the firmware as some cam answer 2.0.1.2.2
674 * and should be a spca504b then overwrite that setting */
675 reg_r(gspca_dev, 0x20, 0, 1);
676 switch (gspca_dev->usb_buf[0]) {
677 case 1:
678 break; /* (right bridge/subtype) */
679 case 2:
680 sd->bridge = BRIDGE_SPCA504B;
681 sd->subtype = 0;
682 break;
683 default:
684 return -ENODEV;
688 switch (sd->bridge) {
689 default:
690 /* case BRIDGE_SPCA504B: */
691 /* case BRIDGE_SPCA504: */
692 /* case BRIDGE_SPCA536: */
693 cam->cam_mode = vga_mode;
694 cam->nmodes = ARRAY_SIZE(vga_mode);
695 break;
696 case BRIDGE_SPCA533:
697 cam->cam_mode = custom_mode;
698 if (sd->subtype == MegaImageVI) /* 320x240 only */
699 cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
700 else
701 cam->nmodes = ARRAY_SIZE(custom_mode);
702 break;
703 case BRIDGE_SPCA504C:
704 cam->cam_mode = vga_mode2;
705 cam->nmodes = ARRAY_SIZE(vga_mode2);
706 break;
708 sd->brightness = BRIGHTNESS_DEF;
709 sd->contrast = CONTRAST_DEF;
710 sd->colors = COLOR_DEF;
711 sd->autogain = AUTOGAIN_DEF;
712 sd->quality = QUALITY_DEF;
713 return 0;
716 /* this function is called at probe and resume time */
717 static int sd_init(struct gspca_dev *gspca_dev)
719 struct sd *sd = (struct sd *) gspca_dev;
721 switch (sd->bridge) {
722 case BRIDGE_SPCA504B:
723 reg_w_riv(gspca_dev, 0x1d, 0x00, 0);
724 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01);
725 reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00);
726 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00);
727 reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13);
728 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00);
729 /* fall thru */
730 case BRIDGE_SPCA533:
731 spca504B_PollingDataReady(gspca_dev);
732 #ifdef GSPCA_DEBUG
733 spca50x_GetFirmware(gspca_dev);
734 #endif
735 break;
736 case BRIDGE_SPCA536:
737 #ifdef GSPCA_DEBUG
738 spca50x_GetFirmware(gspca_dev);
739 #endif
740 reg_r(gspca_dev, 0x00, 0x5002, 1);
741 reg_w_1(gspca_dev, 0x24, 0, 0, 0);
742 reg_r(gspca_dev, 0x24, 0, 1);
743 spca504B_PollingDataReady(gspca_dev);
744 reg_w_riv(gspca_dev, 0x34, 0, 0);
745 spca504B_WaitCmdStatus(gspca_dev);
746 break;
747 case BRIDGE_SPCA504C: /* pccam600 */
748 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
749 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000);
750 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001); /* reset */
751 spca504_wait_status(gspca_dev);
752 if (sd->subtype == LogitechClickSmart420)
753 write_vector(gspca_dev,
754 spca504A_clicksmart420_open_data,
755 ARRAY_SIZE(spca504A_clicksmart420_open_data));
756 else
757 write_vector(gspca_dev, spca504_pccam600_open_data,
758 ARRAY_SIZE(spca504_pccam600_open_data));
759 setup_qtable(gspca_dev, qtable_creative_pccam);
760 break;
761 default:
762 /* case BRIDGE_SPCA504: */
763 PDEBUG(D_STREAM, "Opening SPCA504");
764 if (sd->subtype == AiptekMiniPenCam13) {
765 #ifdef GSPCA_DEBUG
766 spca504_read_info(gspca_dev);
767 #endif
769 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
770 spca504A_acknowledged_command(gspca_dev, 0x24,
771 8, 3, 0x9e, 1);
772 /* Twice sequential need status 0xff->0x9e->0x9d */
773 spca504A_acknowledged_command(gspca_dev, 0x24,
774 8, 3, 0x9e, 0);
776 spca504A_acknowledged_command(gspca_dev, 0x24,
777 0, 0, 0x9d, 1);
778 /******************************/
779 /* spca504a aiptek */
780 spca504A_acknowledged_command(gspca_dev, 0x08,
781 6, 0, 0x86, 1);
782 /* reg_write (dev, 0, 0x2000, 0); */
783 /* reg_write (dev, 0, 0x2883, 1); */
784 /* spca504A_acknowledged_command (gspca_dev, 0x08,
785 6, 0, 0x86, 1); */
786 /* spca504A_acknowledged_command (gspca_dev, 0x24,
787 0, 0, 0x9D, 1); */
788 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
789 /* L92 sno1t.txt */
790 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
791 spca504A_acknowledged_command(gspca_dev, 0x01,
792 0x0f, 0, 0xff, 0);
794 /* setup qtable */
795 reg_w_riv(gspca_dev, 0, 0x2000, 0);
796 reg_w_riv(gspca_dev, 0, 0x2883, 1);
797 setup_qtable(gspca_dev, qtable_spca504_default);
798 break;
800 return gspca_dev->usb_err;
803 static int sd_start(struct gspca_dev *gspca_dev)
805 struct sd *sd = (struct sd *) gspca_dev;
806 int enable;
808 /* create the JPEG header */
809 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
810 0x22); /* JPEG 411 */
811 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
813 if (sd->bridge == BRIDGE_SPCA504B)
814 spca504B_setQtable(gspca_dev);
815 spca504B_SetSizeType(gspca_dev);
816 switch (sd->bridge) {
817 default:
818 /* case BRIDGE_SPCA504B: */
819 /* case BRIDGE_SPCA533: */
820 /* case BRIDGE_SPCA536: */
821 switch (sd->subtype) {
822 case MegapixV4:
823 case LogitechClickSmart820:
824 case MegaImageVI:
825 reg_w_riv(gspca_dev, 0xf0, 0, 0);
826 spca504B_WaitCmdStatus(gspca_dev);
827 reg_r(gspca_dev, 0xf0, 4, 0);
828 spca504B_WaitCmdStatus(gspca_dev);
829 break;
830 default:
831 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
832 spca504B_WaitCmdStatus(gspca_dev);
833 spca504B_PollingDataReady(gspca_dev);
834 break;
836 break;
837 case BRIDGE_SPCA504:
838 if (sd->subtype == AiptekMiniPenCam13) {
839 #ifdef GSPCA_DEBUG
840 spca504_read_info(gspca_dev);
841 #endif
843 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
844 spca504A_acknowledged_command(gspca_dev, 0x24,
845 8, 3, 0x9e, 1);
846 /* Twice sequential need status 0xff->0x9e->0x9d */
847 spca504A_acknowledged_command(gspca_dev, 0x24,
848 8, 3, 0x9e, 0);
849 spca504A_acknowledged_command(gspca_dev, 0x24,
850 0, 0, 0x9d, 1);
851 } else {
852 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
853 #ifdef GSPCA_DEBUG
854 spca504_read_info(gspca_dev);
855 #endif
856 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
857 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
859 spca504B_SetSizeType(gspca_dev);
860 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
861 /* L92 sno1t.txt */
862 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
863 break;
864 case BRIDGE_SPCA504C:
865 if (sd->subtype == LogitechClickSmart420) {
866 write_vector(gspca_dev,
867 spca504A_clicksmart420_init_data,
868 ARRAY_SIZE(spca504A_clicksmart420_init_data));
869 } else {
870 write_vector(gspca_dev, spca504_pccam600_init_data,
871 ARRAY_SIZE(spca504_pccam600_init_data));
873 enable = (sd->autogain ? 0x04 : 0x01);
874 reg_w_riv(gspca_dev, 0x0c, 0x0000, enable);
875 /* auto exposure */
876 reg_w_riv(gspca_dev, 0xb0, 0x0000, enable);
877 /* auto whiteness */
879 /* set default exposure compensation and whiteness balance */
880 reg_w_riv(gspca_dev, 0x30, 0x0001, 800); /* ~ 20 fps */
881 reg_w_riv(gspca_dev, 0x30, 0x0002, 1600);
882 spca504B_SetSizeType(gspca_dev);
883 break;
885 init_ctl_reg(gspca_dev);
886 return gspca_dev->usb_err;
889 static void sd_stopN(struct gspca_dev *gspca_dev)
891 struct sd *sd = (struct sd *) gspca_dev;
893 switch (sd->bridge) {
894 default:
895 /* case BRIDGE_SPCA533: */
896 /* case BRIDGE_SPCA536: */
897 /* case BRIDGE_SPCA504B: */
898 reg_w_riv(gspca_dev, 0x31, 0, 0);
899 spca504B_WaitCmdStatus(gspca_dev);
900 spca504B_PollingDataReady(gspca_dev);
901 break;
902 case BRIDGE_SPCA504:
903 case BRIDGE_SPCA504C:
904 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000);
906 if (sd->subtype == AiptekMiniPenCam13) {
907 /* spca504a aiptek */
908 /* spca504A_acknowledged_command(gspca_dev, 0x08,
909 6, 0, 0x86, 1); */
910 spca504A_acknowledged_command(gspca_dev, 0x24,
911 0x00, 0x00, 0x9d, 1);
912 spca504A_acknowledged_command(gspca_dev, 0x01,
913 0x0f, 0x00, 0xff, 1);
914 } else {
915 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
916 reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000);
918 break;
922 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
923 u8 *data, /* isoc packet */
924 int len) /* iso packet length */
926 struct sd *sd = (struct sd *) gspca_dev;
927 int i, sof = 0;
928 static u8 ffd9[] = {0xff, 0xd9};
930 /* frames are jpeg 4.1.1 without 0xff escape */
931 switch (sd->bridge) {
932 case BRIDGE_SPCA533:
933 if (data[0] == 0xff) {
934 if (data[1] != 0x01) { /* drop packet */
935 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
936 return;
938 sof = 1;
939 data += SPCA533_OFFSET_DATA;
940 len -= SPCA533_OFFSET_DATA;
941 } else {
942 data += 1;
943 len -= 1;
945 break;
946 case BRIDGE_SPCA536:
947 if (data[0] == 0xff) {
948 sof = 1;
949 data += SPCA536_OFFSET_DATA;
950 len -= SPCA536_OFFSET_DATA;
951 } else {
952 data += 2;
953 len -= 2;
955 break;
956 default:
957 /* case BRIDGE_SPCA504: */
958 /* case BRIDGE_SPCA504B: */
959 switch (data[0]) {
960 case 0xfe: /* start of frame */
961 sof = 1;
962 data += SPCA50X_OFFSET_DATA;
963 len -= SPCA50X_OFFSET_DATA;
964 break;
965 case 0xff: /* drop packet */
966 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
967 return;
968 default:
969 data += 1;
970 len -= 1;
971 break;
973 break;
974 case BRIDGE_SPCA504C:
975 switch (data[0]) {
976 case 0xfe: /* start of frame */
977 sof = 1;
978 data += SPCA504_PCCAM600_OFFSET_DATA;
979 len -= SPCA504_PCCAM600_OFFSET_DATA;
980 break;
981 case 0xff: /* drop packet */
982 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
983 return;
984 default:
985 data += 1;
986 len -= 1;
987 break;
989 break;
991 if (sof) { /* start of frame */
992 gspca_frame_add(gspca_dev, LAST_PACKET,
993 ffd9, 2);
995 /* put the JPEG header in the new frame */
996 gspca_frame_add(gspca_dev, FIRST_PACKET,
997 sd->jpeg_hdr, JPEG_HDR_SZ);
1000 /* add 0x00 after 0xff */
1001 i = 0;
1002 do {
1003 if (data[i] == 0xff) {
1004 gspca_frame_add(gspca_dev, INTER_PACKET,
1005 data, i + 1);
1006 len -= i;
1007 data += i;
1008 *data = 0x00;
1009 i = 0;
1011 i++;
1012 } while (i < len);
1013 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1016 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1018 struct sd *sd = (struct sd *) gspca_dev;
1020 sd->brightness = val;
1021 if (gspca_dev->streaming)
1022 setbrightness(gspca_dev);
1023 return gspca_dev->usb_err;
1026 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1028 struct sd *sd = (struct sd *) gspca_dev;
1030 *val = sd->brightness;
1031 return 0;
1034 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1036 struct sd *sd = (struct sd *) gspca_dev;
1038 sd->contrast = val;
1039 if (gspca_dev->streaming)
1040 setcontrast(gspca_dev);
1041 return gspca_dev->usb_err;
1044 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1046 struct sd *sd = (struct sd *) gspca_dev;
1048 *val = sd->contrast;
1049 return 0;
1052 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1054 struct sd *sd = (struct sd *) gspca_dev;
1056 sd->colors = val;
1057 if (gspca_dev->streaming)
1058 setcolors(gspca_dev);
1059 return gspca_dev->usb_err;
1062 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1064 struct sd *sd = (struct sd *) gspca_dev;
1066 *val = sd->colors;
1067 return 0;
1070 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1072 struct sd *sd = (struct sd *) gspca_dev;
1074 sd->autogain = val;
1075 return 0;
1078 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1080 struct sd *sd = (struct sd *) gspca_dev;
1082 *val = sd->autogain;
1083 return 0;
1086 static int sd_set_jcomp(struct gspca_dev *gspca_dev,
1087 struct v4l2_jpegcompression *jcomp)
1089 struct sd *sd = (struct sd *) gspca_dev;
1091 if (jcomp->quality < QUALITY_MIN)
1092 sd->quality = QUALITY_MIN;
1093 else if (jcomp->quality > QUALITY_MAX)
1094 sd->quality = QUALITY_MAX;
1095 else
1096 sd->quality = jcomp->quality;
1097 if (gspca_dev->streaming)
1098 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
1099 return gspca_dev->usb_err;
1102 static int sd_get_jcomp(struct gspca_dev *gspca_dev,
1103 struct v4l2_jpegcompression *jcomp)
1105 struct sd *sd = (struct sd *) gspca_dev;
1107 memset(jcomp, 0, sizeof *jcomp);
1108 jcomp->quality = sd->quality;
1109 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
1110 | V4L2_JPEG_MARKER_DQT;
1111 return 0;
1114 /* sub-driver description */
1115 static const struct sd_desc sd_desc = {
1116 .name = MODULE_NAME,
1117 .ctrls = sd_ctrls,
1118 .nctrls = ARRAY_SIZE(sd_ctrls),
1119 .config = sd_config,
1120 .init = sd_init,
1121 .start = sd_start,
1122 .stopN = sd_stopN,
1123 .pkt_scan = sd_pkt_scan,
1124 .get_jcomp = sd_get_jcomp,
1125 .set_jcomp = sd_set_jcomp,
1128 /* -- module initialisation -- */
1129 #define BS(bridge, subtype) \
1130 .driver_info = (BRIDGE_ ## bridge << 8) \
1131 | (subtype)
1132 static const struct usb_device_id device_table[] = {
1133 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
1134 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
1135 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
1136 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
1137 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
1138 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
1139 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
1140 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
1141 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
1142 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
1143 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
1144 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
1145 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
1146 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
1147 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
1148 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
1149 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
1150 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
1151 {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)},
1152 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
1153 {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
1154 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1155 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1156 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1157 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1158 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1159 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1160 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1161 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1162 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1163 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1164 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1165 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1166 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1167 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1168 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1169 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1170 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
1171 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1172 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1173 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1174 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1175 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1176 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1177 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1178 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1179 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1180 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1181 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1182 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1183 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1184 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1185 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1186 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1187 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1188 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1189 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1190 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1191 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
1194 MODULE_DEVICE_TABLE(usb, device_table);
1196 /* -- device connect -- */
1197 static int sd_probe(struct usb_interface *intf,
1198 const struct usb_device_id *id)
1200 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1201 THIS_MODULE);
1204 static struct usb_driver sd_driver = {
1205 .name = MODULE_NAME,
1206 .id_table = device_table,
1207 .probe = sd_probe,
1208 .disconnect = gspca_disconnect,
1209 #ifdef CONFIG_PM
1210 .suspend = gspca_suspend,
1211 .resume = gspca_resume,
1212 #endif
1215 /* -- module insert / remove -- */
1216 static int __init sd_mod_init(void)
1218 return usb_register(&sd_driver);
1220 static void __exit sd_mod_exit(void)
1222 usb_deregister(&sd_driver);
1225 module_init(sd_mod_init);
1226 module_exit(sd_mod_exit);