Linux 2.6.34-rc3
[pohmelfs.git] / drivers / media / video / gspca / sunplus.c
blob0c786e00ebcf39e758bb60f29f73f82f826fadc4
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;
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 PDEBUG(D_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 PDEBUG(D_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 PDEBUG(D_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 /* read 1 byte */
400 static u8 reg_r_1(struct gspca_dev *gspca_dev,
401 u16 value) /* wValue */
403 int ret;
405 if (gspca_dev->usb_err < 0)
406 return 0;
407 ret = usb_control_msg(gspca_dev->dev,
408 usb_rcvctrlpipe(gspca_dev->dev, 0),
409 0x20, /* request */
410 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
411 value,
412 0, /* index */
413 gspca_dev->usb_buf, 1,
414 500); /* timeout */
415 if (ret < 0) {
416 PDEBUG(D_ERR, "reg_r_1 err %d", ret);
417 gspca_dev->usb_err = ret;
418 return 0;
420 return gspca_dev->usb_buf[0];
423 /* read 1 or 2 bytes */
424 static u16 reg_r_12(struct gspca_dev *gspca_dev,
425 u8 req, /* bRequest */
426 u16 index, /* wIndex */
427 u16 length) /* wLength (1 or 2 only) */
429 int ret;
431 if (gspca_dev->usb_err < 0)
432 return 0;
433 gspca_dev->usb_buf[1] = 0;
434 ret = usb_control_msg(gspca_dev->dev,
435 usb_rcvctrlpipe(gspca_dev->dev, 0),
436 req,
437 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
438 0, /* value */
439 index,
440 gspca_dev->usb_buf, length,
441 500);
442 if (ret < 0) {
443 PDEBUG(D_ERR, "reg_r_12 err %d", ret);
444 gspca_dev->usb_err = ret;
445 return 0;
447 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
450 static void write_vector(struct gspca_dev *gspca_dev,
451 const struct cmd *data, int ncmds)
453 while (--ncmds >= 0) {
454 reg_w_riv(gspca_dev, data->req, data->idx, data->val);
455 data++;
459 static void setup_qtable(struct gspca_dev *gspca_dev,
460 const u8 qtable[2][64])
462 int i;
464 /* loop over y components */
465 for (i = 0; i < 64; i++)
466 reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]);
468 /* loop over c components */
469 for (i = 0; i < 64; i++)
470 reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]);
473 static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
474 u8 req, u16 idx, u16 val)
476 u16 notdone;
478 reg_w_riv(gspca_dev, req, idx, val);
479 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
480 reg_w_riv(gspca_dev, req, idx, val);
482 PDEBUG(D_FRAM, "before wait 0x%04x", notdone);
484 msleep(200);
485 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
486 PDEBUG(D_FRAM, "after wait 0x%04x", notdone);
489 static void spca504_read_info(struct gspca_dev *gspca_dev)
491 int i;
492 u8 info[6];
494 for (i = 0; i < 6; i++)
495 info[i] = reg_r_1(gspca_dev, i);
496 PDEBUG(D_STREAM,
497 "Read info: %d %d %d %d %d %d."
498 " Should be 1,0,2,2,0,0",
499 info[0], info[1], info[2],
500 info[3], info[4], info[5]);
503 static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
504 u8 req,
505 u16 idx, u16 val, u16 endcode, u8 count)
507 u16 status;
509 reg_w_riv(gspca_dev, req, idx, val);
510 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
511 if (gspca_dev->usb_err < 0)
512 return;
513 PDEBUG(D_FRAM, "Status 0x%04x Need 0x%04x", status, endcode);
514 if (!count)
515 return;
516 count = 200;
517 while (--count > 0) {
518 msleep(10);
519 /* gsmart mini2 write a each wait setting 1 ms is enough */
520 /* reg_w_riv(gspca_dev, req, idx, val); */
521 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
522 if (status == endcode) {
523 PDEBUG(D_FRAM, "status 0x%04x after wait %d",
524 status, 200 - count);
525 break;
530 static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
532 int count = 10;
534 while (--count > 0) {
535 reg_r(gspca_dev, 0x21, 0, 1);
536 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
537 break;
538 msleep(10);
542 static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
544 int count = 50;
546 while (--count > 0) {
547 reg_r(gspca_dev, 0x21, 1, 1);
548 if (gspca_dev->usb_buf[0] != 0) {
549 reg_w_1(gspca_dev, 0x21, 0, 1, 0);
550 reg_r(gspca_dev, 0x21, 1, 1);
551 spca504B_PollingDataReady(gspca_dev);
552 break;
554 msleep(10);
558 static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
560 u8 *data;
562 data = gspca_dev->usb_buf;
563 reg_r(gspca_dev, 0x20, 0, 5);
564 PDEBUG(D_STREAM, "FirmWare : %d %d %d %d %d ",
565 data[0], data[1], data[2], data[3], data[4]);
566 reg_r(gspca_dev, 0x23, 0, 64);
567 reg_r(gspca_dev, 0x23, 1, 64);
570 static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
572 struct sd *sd = (struct sd *) gspca_dev;
573 u8 Size;
575 Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
576 switch (sd->bridge) {
577 case BRIDGE_SPCA533:
578 reg_w_riv(gspca_dev, 0x31, 0, 0);
579 spca504B_WaitCmdStatus(gspca_dev);
580 spca504B_PollingDataReady(gspca_dev);
581 spca50x_GetFirmware(gspca_dev);
582 reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */
583 reg_r(gspca_dev, 0x24, 8, 1);
585 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
586 reg_r(gspca_dev, 0x25, 4, 1); /* size */
587 spca504B_PollingDataReady(gspca_dev);
589 /* Init the cam width height with some values get on init ? */
590 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
591 spca504B_WaitCmdStatus(gspca_dev);
592 spca504B_PollingDataReady(gspca_dev);
593 break;
594 default:
595 /* case BRIDGE_SPCA504B: */
596 /* case BRIDGE_SPCA536: */
597 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
598 reg_r(gspca_dev, 0x25, 4, 1); /* size */
599 reg_w_1(gspca_dev, 0x27, 0, 0, 6);
600 reg_r(gspca_dev, 0x27, 0, 1); /* type */
601 spca504B_PollingDataReady(gspca_dev);
602 break;
603 case BRIDGE_SPCA504:
604 Size += 3;
605 if (sd->subtype == AiptekMiniPenCam13) {
606 /* spca504a aiptek */
607 spca504A_acknowledged_command(gspca_dev,
608 0x08, Size, 0,
609 0x80 | (Size & 0x0f), 1);
610 spca504A_acknowledged_command(gspca_dev,
611 1, 3, 0, 0x9f, 0);
612 } else {
613 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
615 break;
616 case BRIDGE_SPCA504C:
617 /* capture mode */
618 reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
619 reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
620 break;
624 static void spca504_wait_status(struct gspca_dev *gspca_dev)
626 int cnt;
628 cnt = 256;
629 while (--cnt > 0) {
630 /* With this we get the status, when return 0 it's all ok */
631 if (reg_r_12(gspca_dev, 0x06, 0x00, 1) == 0)
632 return;
633 msleep(10);
637 static void spca504B_setQtable(struct gspca_dev *gspca_dev)
639 reg_w_1(gspca_dev, 0x26, 0, 0, 3);
640 reg_r(gspca_dev, 0x26, 0, 1);
641 spca504B_PollingDataReady(gspca_dev);
644 static void setbrightness(struct gspca_dev *gspca_dev)
646 struct sd *sd = (struct sd *) gspca_dev;
647 u16 reg;
649 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
650 reg_w_riv(gspca_dev, 0x00, reg, sd->brightness);
653 static void setcontrast(struct gspca_dev *gspca_dev)
655 struct sd *sd = (struct sd *) gspca_dev;
656 u16 reg;
658 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
659 reg_w_riv(gspca_dev, 0x00, reg, sd->contrast);
662 static void setcolors(struct gspca_dev *gspca_dev)
664 struct sd *sd = (struct sd *) gspca_dev;
665 u16 reg;
667 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
668 reg_w_riv(gspca_dev, 0x00, reg, sd->colors);
671 static void init_ctl_reg(struct gspca_dev *gspca_dev)
673 struct sd *sd = (struct sd *) gspca_dev;
674 int pollreg = 1;
676 setbrightness(gspca_dev);
677 setcontrast(gspca_dev);
678 setcolors(gspca_dev);
680 switch (sd->bridge) {
681 case BRIDGE_SPCA504:
682 case BRIDGE_SPCA504C:
683 pollreg = 0;
684 /* fall thru */
685 default:
686 /* case BRIDGE_SPCA533: */
687 /* case BRIDGE_SPCA504B: */
688 reg_w_riv(gspca_dev, 0, 0x21ad, 0x00); /* hue */
689 reg_w_riv(gspca_dev, 0, 0x21ac, 0x01); /* sat/hue */
690 reg_w_riv(gspca_dev, 0, 0x21a3, 0x00); /* gamma */
691 break;
692 case BRIDGE_SPCA536:
693 reg_w_riv(gspca_dev, 0, 0x20f5, 0x40);
694 reg_w_riv(gspca_dev, 0, 0x20f4, 0x01);
695 reg_w_riv(gspca_dev, 0, 0x2089, 0x00);
696 break;
698 if (pollreg)
699 spca504B_PollingDataReady(gspca_dev);
702 /* this function is called at probe time */
703 static int sd_config(struct gspca_dev *gspca_dev,
704 const struct usb_device_id *id)
706 struct sd *sd = (struct sd *) gspca_dev;
707 struct cam *cam;
709 cam = &gspca_dev->cam;
711 sd->bridge = id->driver_info >> 8;
712 sd->subtype = id->driver_info;
714 if (sd->subtype == AiptekMiniPenCam13) {
715 /* try to get the firmware as some cam answer 2.0.1.2.2
716 * and should be a spca504b then overwrite that setting */
717 reg_r(gspca_dev, 0x20, 0, 1);
718 switch (gspca_dev->usb_buf[0]) {
719 case 1:
720 break; /* (right bridge/subtype) */
721 case 2:
722 sd->bridge = BRIDGE_SPCA504B;
723 sd->subtype = 0;
724 break;
725 default:
726 return -ENODEV;
730 switch (sd->bridge) {
731 default:
732 /* case BRIDGE_SPCA504B: */
733 /* case BRIDGE_SPCA504: */
734 /* case BRIDGE_SPCA536: */
735 cam->cam_mode = vga_mode;
736 cam->nmodes =ARRAY_SIZE(vga_mode);
737 break;
738 case BRIDGE_SPCA533:
739 cam->cam_mode = custom_mode;
740 if (sd->subtype == MegaImageVI) /* 320x240 only */
741 cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
742 else
743 cam->nmodes = ARRAY_SIZE(custom_mode);
744 break;
745 case BRIDGE_SPCA504C:
746 cam->cam_mode = vga_mode2;
747 cam->nmodes = ARRAY_SIZE(vga_mode2);
748 break;
750 sd->brightness = BRIGHTNESS_DEF;
751 sd->contrast = CONTRAST_DEF;
752 sd->colors = COLOR_DEF;
753 sd->autogain = AUTOGAIN_DEF;
754 sd->quality = QUALITY_DEF;
755 return 0;
758 /* this function is called at probe and resume time */
759 static int sd_init(struct gspca_dev *gspca_dev)
761 struct sd *sd = (struct sd *) gspca_dev;
763 switch (sd->bridge) {
764 case BRIDGE_SPCA504B:
765 reg_w_riv(gspca_dev, 0x1d, 0x00, 0);
766 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01);
767 reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00);
768 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00);
769 reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13);
770 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00);
771 /* fall thru */
772 case BRIDGE_SPCA533:
773 spca504B_PollingDataReady(gspca_dev);
774 spca50x_GetFirmware(gspca_dev);
775 break;
776 case BRIDGE_SPCA536:
777 spca50x_GetFirmware(gspca_dev);
778 reg_r(gspca_dev, 0x00, 0x5002, 1);
779 reg_w_1(gspca_dev, 0x24, 0, 0, 0);
780 reg_r(gspca_dev, 0x24, 0, 1);
781 spca504B_PollingDataReady(gspca_dev);
782 reg_w_riv(gspca_dev, 0x34, 0, 0);
783 spca504B_WaitCmdStatus(gspca_dev);
784 break;
785 case BRIDGE_SPCA504C: /* pccam600 */
786 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
787 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000);
788 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001); /* reset */
789 spca504_wait_status(gspca_dev);
790 if (sd->subtype == LogitechClickSmart420)
791 write_vector(gspca_dev,
792 spca504A_clicksmart420_open_data,
793 ARRAY_SIZE(spca504A_clicksmart420_open_data));
794 else
795 write_vector(gspca_dev, spca504_pccam600_open_data,
796 ARRAY_SIZE(spca504_pccam600_open_data));
797 setup_qtable(gspca_dev, qtable_creative_pccam);
798 break;
799 default:
800 /* case BRIDGE_SPCA504: */
801 PDEBUG(D_STREAM, "Opening SPCA504");
802 if (sd->subtype == AiptekMiniPenCam13) {
803 spca504_read_info(gspca_dev);
805 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
806 spca504A_acknowledged_command(gspca_dev, 0x24,
807 8, 3, 0x9e, 1);
808 /* Twice sequencial need status 0xff->0x9e->0x9d */
809 spca504A_acknowledged_command(gspca_dev, 0x24,
810 8, 3, 0x9e, 0);
812 spca504A_acknowledged_command(gspca_dev, 0x24,
813 0, 0, 0x9d, 1);
814 /******************************/
815 /* spca504a aiptek */
816 spca504A_acknowledged_command(gspca_dev, 0x08,
817 6, 0, 0x86, 1);
818 /* reg_write (dev, 0, 0x2000, 0); */
819 /* reg_write (dev, 0, 0x2883, 1); */
820 /* spca504A_acknowledged_command (gspca_dev, 0x08,
821 6, 0, 0x86, 1); */
822 /* spca504A_acknowledged_command (gspca_dev, 0x24,
823 0, 0, 0x9D, 1); */
824 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
825 /* L92 sno1t.txt */
826 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
827 spca504A_acknowledged_command(gspca_dev, 0x01,
828 0x0f, 0, 0xff, 0);
830 /* setup qtable */
831 reg_w_riv(gspca_dev, 0, 0x2000, 0);
832 reg_w_riv(gspca_dev, 0, 0x2883, 1);
833 setup_qtable(gspca_dev, qtable_spca504_default);
834 break;
836 return gspca_dev->usb_err;
839 static int sd_start(struct gspca_dev *gspca_dev)
841 struct sd *sd = (struct sd *) gspca_dev;
842 int enable;
844 /* create the JPEG header */
845 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
846 if (!sd->jpeg_hdr)
847 return -ENOMEM;
848 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
849 0x22); /* JPEG 411 */
850 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
852 if (sd->bridge == BRIDGE_SPCA504B)
853 spca504B_setQtable(gspca_dev);
854 spca504B_SetSizeType(gspca_dev);
855 switch (sd->bridge) {
856 default:
857 /* case BRIDGE_SPCA504B: */
858 /* case BRIDGE_SPCA533: */
859 /* case BRIDGE_SPCA536: */
860 switch (sd->subtype) {
861 case MegapixV4:
862 case LogitechClickSmart820:
863 case MegaImageVI:
864 reg_w_riv(gspca_dev, 0xf0, 0, 0);
865 spca504B_WaitCmdStatus(gspca_dev);
866 reg_r(gspca_dev, 0xf0, 4, 0);
867 spca504B_WaitCmdStatus(gspca_dev);
868 break;
869 default:
870 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
871 spca504B_WaitCmdStatus(gspca_dev);
872 spca504B_PollingDataReady(gspca_dev);
873 break;
875 break;
876 case BRIDGE_SPCA504:
877 if (sd->subtype == AiptekMiniPenCam13) {
878 spca504_read_info(gspca_dev);
880 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
881 spca504A_acknowledged_command(gspca_dev, 0x24,
882 8, 3, 0x9e, 1);
883 /* Twice sequencial need status 0xff->0x9e->0x9d */
884 spca504A_acknowledged_command(gspca_dev, 0x24,
885 8, 3, 0x9e, 0);
886 spca504A_acknowledged_command(gspca_dev, 0x24,
887 0, 0, 0x9d, 1);
888 } else {
889 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
890 spca504_read_info(gspca_dev);
891 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
892 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
894 spca504B_SetSizeType(gspca_dev);
895 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
896 /* L92 sno1t.txt */
897 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
898 break;
899 case BRIDGE_SPCA504C:
900 if (sd->subtype == LogitechClickSmart420) {
901 write_vector(gspca_dev,
902 spca504A_clicksmart420_init_data,
903 ARRAY_SIZE(spca504A_clicksmart420_init_data));
904 } else {
905 write_vector(gspca_dev, spca504_pccam600_init_data,
906 ARRAY_SIZE(spca504_pccam600_init_data));
908 enable = (sd->autogain ? 0x04 : 0x01);
909 reg_w_riv(gspca_dev, 0x0c, 0x0000, enable);
910 /* auto exposure */
911 reg_w_riv(gspca_dev, 0xb0, 0x0000, enable);
912 /* auto whiteness */
914 /* set default exposure compensation and whiteness balance */
915 reg_w_riv(gspca_dev, 0x30, 0x0001, 800); /* ~ 20 fps */
916 reg_w_riv(gspca_dev, 0x30, 0x0002, 1600);
917 spca504B_SetSizeType(gspca_dev);
918 break;
920 init_ctl_reg(gspca_dev);
921 return gspca_dev->usb_err;
924 static void sd_stopN(struct gspca_dev *gspca_dev)
926 struct sd *sd = (struct sd *) gspca_dev;
928 switch (sd->bridge) {
929 default:
930 /* case BRIDGE_SPCA533: */
931 /* case BRIDGE_SPCA536: */
932 /* case BRIDGE_SPCA504B: */
933 reg_w_riv(gspca_dev, 0x31, 0, 0);
934 spca504B_WaitCmdStatus(gspca_dev);
935 spca504B_PollingDataReady(gspca_dev);
936 break;
937 case BRIDGE_SPCA504:
938 case BRIDGE_SPCA504C:
939 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000);
941 if (sd->subtype == AiptekMiniPenCam13) {
942 /* spca504a aiptek */
943 /* spca504A_acknowledged_command(gspca_dev, 0x08,
944 6, 0, 0x86, 1); */
945 spca504A_acknowledged_command(gspca_dev, 0x24,
946 0x00, 0x00, 0x9d, 1);
947 spca504A_acknowledged_command(gspca_dev, 0x01,
948 0x0f, 0x00, 0xff, 1);
949 } else {
950 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
951 reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000);
953 break;
957 static void sd_stop0(struct gspca_dev *gspca_dev)
959 struct sd *sd = (struct sd *) gspca_dev;
961 kfree(sd->jpeg_hdr);
964 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
965 u8 *data, /* isoc packet */
966 int len) /* iso packet length */
968 struct sd *sd = (struct sd *) gspca_dev;
969 int i, sof = 0;
970 static u8 ffd9[] = {0xff, 0xd9};
972 /* frames are jpeg 4.1.1 without 0xff escape */
973 switch (sd->bridge) {
974 case BRIDGE_SPCA533:
975 if (data[0] == 0xff) {
976 if (data[1] != 0x01) { /* drop packet */
977 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
978 return;
980 sof = 1;
981 data += SPCA533_OFFSET_DATA;
982 len -= SPCA533_OFFSET_DATA;
983 } else {
984 data += 1;
985 len -= 1;
987 break;
988 case BRIDGE_SPCA536:
989 if (data[0] == 0xff) {
990 sof = 1;
991 data += SPCA536_OFFSET_DATA;
992 len -= SPCA536_OFFSET_DATA;
993 } else {
994 data += 2;
995 len -= 2;
997 break;
998 default:
999 /* case BRIDGE_SPCA504: */
1000 /* case BRIDGE_SPCA504B: */
1001 switch (data[0]) {
1002 case 0xfe: /* start of frame */
1003 sof = 1;
1004 data += SPCA50X_OFFSET_DATA;
1005 len -= SPCA50X_OFFSET_DATA;
1006 break;
1007 case 0xff: /* drop packet */
1008 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1009 return;
1010 default:
1011 data += 1;
1012 len -= 1;
1013 break;
1015 break;
1016 case BRIDGE_SPCA504C:
1017 switch (data[0]) {
1018 case 0xfe: /* start of frame */
1019 sof = 1;
1020 data += SPCA504_PCCAM600_OFFSET_DATA;
1021 len -= SPCA504_PCCAM600_OFFSET_DATA;
1022 break;
1023 case 0xff: /* drop packet */
1024 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1025 return;
1026 default:
1027 data += 1;
1028 len -= 1;
1029 break;
1031 break;
1033 if (sof) { /* start of frame */
1034 gspca_frame_add(gspca_dev, LAST_PACKET,
1035 ffd9, 2);
1037 /* put the JPEG header in the new frame */
1038 gspca_frame_add(gspca_dev, FIRST_PACKET,
1039 sd->jpeg_hdr, JPEG_HDR_SZ);
1042 /* add 0x00 after 0xff */
1043 i = 0;
1044 do {
1045 if (data[i] == 0xff) {
1046 gspca_frame_add(gspca_dev, INTER_PACKET,
1047 data, i + 1);
1048 len -= i;
1049 data += i;
1050 *data = 0x00;
1051 i = 0;
1053 i++;
1054 } while (i < len);
1055 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1058 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1060 struct sd *sd = (struct sd *) gspca_dev;
1062 sd->brightness = val;
1063 if (gspca_dev->streaming)
1064 setbrightness(gspca_dev);
1065 return gspca_dev->usb_err;
1068 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1070 struct sd *sd = (struct sd *) gspca_dev;
1072 *val = sd->brightness;
1073 return 0;
1076 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1078 struct sd *sd = (struct sd *) gspca_dev;
1080 sd->contrast = val;
1081 if (gspca_dev->streaming)
1082 setcontrast(gspca_dev);
1083 return gspca_dev->usb_err;
1086 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1088 struct sd *sd = (struct sd *) gspca_dev;
1090 *val = sd->contrast;
1091 return 0;
1094 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1096 struct sd *sd = (struct sd *) gspca_dev;
1098 sd->colors = val;
1099 if (gspca_dev->streaming)
1100 setcolors(gspca_dev);
1101 return gspca_dev->usb_err;
1104 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1106 struct sd *sd = (struct sd *) gspca_dev;
1108 *val = sd->colors;
1109 return 0;
1112 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1114 struct sd *sd = (struct sd *) gspca_dev;
1116 sd->autogain = val;
1117 return 0;
1120 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1122 struct sd *sd = (struct sd *) gspca_dev;
1124 *val = sd->autogain;
1125 return 0;
1128 static int sd_set_jcomp(struct gspca_dev *gspca_dev,
1129 struct v4l2_jpegcompression *jcomp)
1131 struct sd *sd = (struct sd *) gspca_dev;
1133 if (jcomp->quality < QUALITY_MIN)
1134 sd->quality = QUALITY_MIN;
1135 else if (jcomp->quality > QUALITY_MAX)
1136 sd->quality = QUALITY_MAX;
1137 else
1138 sd->quality = jcomp->quality;
1139 if (gspca_dev->streaming)
1140 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
1141 return gspca_dev->usb_err;
1144 static int sd_get_jcomp(struct gspca_dev *gspca_dev,
1145 struct v4l2_jpegcompression *jcomp)
1147 struct sd *sd = (struct sd *) gspca_dev;
1149 memset(jcomp, 0, sizeof *jcomp);
1150 jcomp->quality = sd->quality;
1151 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
1152 | V4L2_JPEG_MARKER_DQT;
1153 return 0;
1156 /* sub-driver description */
1157 static const struct sd_desc sd_desc = {
1158 .name = MODULE_NAME,
1159 .ctrls = sd_ctrls,
1160 .nctrls = ARRAY_SIZE(sd_ctrls),
1161 .config = sd_config,
1162 .init = sd_init,
1163 .start = sd_start,
1164 .stopN = sd_stopN,
1165 .stop0 = sd_stop0,
1166 .pkt_scan = sd_pkt_scan,
1167 .get_jcomp = sd_get_jcomp,
1168 .set_jcomp = sd_set_jcomp,
1171 /* -- module initialisation -- */
1172 #define BS(bridge, subtype) \
1173 .driver_info = (BRIDGE_ ## bridge << 8) \
1174 | (subtype)
1175 static const __devinitdata struct usb_device_id device_table[] = {
1176 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
1177 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
1178 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
1179 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
1180 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
1181 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
1182 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
1183 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
1184 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
1185 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
1186 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
1187 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
1188 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
1189 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
1190 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
1191 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
1192 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
1193 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
1194 {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)},
1195 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
1196 {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
1197 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1198 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1199 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1200 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1201 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1202 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1203 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1204 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1205 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1206 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1207 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1208 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1209 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1210 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1211 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1212 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1213 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
1214 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1215 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1216 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1217 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1218 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1219 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1220 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1221 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1222 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1223 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1224 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1225 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1226 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1227 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1228 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1229 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1230 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1231 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1232 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1233 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1234 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
1237 MODULE_DEVICE_TABLE(usb, device_table);
1239 /* -- device connect -- */
1240 static int sd_probe(struct usb_interface *intf,
1241 const struct usb_device_id *id)
1243 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1244 THIS_MODULE);
1247 static struct usb_driver sd_driver = {
1248 .name = MODULE_NAME,
1249 .id_table = device_table,
1250 .probe = sd_probe,
1251 .disconnect = gspca_disconnect,
1252 #ifdef CONFIG_PM
1253 .suspend = gspca_suspend,
1254 .resume = gspca_resume,
1255 #endif
1258 /* -- module insert / remove -- */
1259 static int __init sd_mod_init(void)
1261 int ret;
1262 ret = usb_register(&sd_driver);
1263 if (ret < 0)
1264 return ret;
1265 PDEBUG(D_PROBE, "registered");
1266 return 0;
1268 static void __exit sd_mod_exit(void)
1270 usb_deregister(&sd_driver);
1271 PDEBUG(D_PROBE, "deregistered");
1274 module_init(sd_mod_init);
1275 module_exit(sd_mod_exit);