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
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"
27 #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 5)
28 static const char version[] = "2.1.5";
30 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31 MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
32 MODULE_LICENSE("GPL");
34 /* specific webcam descriptor */
36 struct gspca_dev gspca_dev; /* !! must be the first item */
38 __u8 packet[ISO_MAX_SIZE + 128];
39 /* !! no more than 128 ff in an ISO packet */
41 unsigned char brightness;
42 unsigned char contrast;
44 unsigned char autogain;
48 #define BRIDGE_SPCA504 0
49 #define BRIDGE_SPCA504B 1
50 #define BRIDGE_SPCA504C 2
51 #define BRIDGE_SPCA533 3
52 #define BRIDGE_SPCA536 4
54 #define AiptekMiniPenCam13 1
55 #define LogitechClickSmart420 2
56 #define LogitechClickSmart820 3
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 struct ctrl sd_ctrls[] = {
71 #define SD_BRIGHTNESS 0
74 .id = V4L2_CID_BRIGHTNESS,
75 .type = V4L2_CTRL_TYPE_INTEGER,
82 .set = sd_setbrightness,
83 .get = sd_getbrightness,
88 .id = V4L2_CID_CONTRAST,
89 .type = V4L2_CTRL_TYPE_INTEGER,
94 .default_value = 0x20,
96 .set = sd_setcontrast,
97 .get = sd_getcontrast,
102 .id = V4L2_CID_SATURATION,
103 .type = V4L2_CTRL_TYPE_INTEGER,
108 .default_value = 0x1a,
113 #define SD_AUTOGAIN 3
116 .id = V4L2_CID_AUTOGAIN,
117 .type = V4L2_CTRL_TYPE_BOOLEAN,
124 .set = sd_setautogain,
125 .get = sd_getautogain,
129 static struct v4l2_pix_format vga_mode[] = {
130 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
132 .sizeimage = 320 * 240 * 3 / 8 + 590,
133 .colorspace = V4L2_COLORSPACE_JPEG,
135 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
137 .sizeimage = 640 * 480 * 3 / 8 + 590,
138 .colorspace = V4L2_COLORSPACE_JPEG,
142 static struct v4l2_pix_format custom_mode[] = {
143 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
145 .sizeimage = 320 * 240 * 3 / 8 + 590,
146 .colorspace = V4L2_COLORSPACE_JPEG,
148 {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
150 .sizeimage = 464 * 480 * 3 / 8 + 590,
151 .colorspace = V4L2_COLORSPACE_JPEG,
155 static struct v4l2_pix_format vga_mode2[] = {
156 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
158 .sizeimage = 176 * 144 * 3 / 8 + 590,
159 .colorspace = V4L2_COLORSPACE_JPEG,
161 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
163 .sizeimage = 320 * 240 * 3 / 8 + 590,
164 .colorspace = V4L2_COLORSPACE_JPEG,
166 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
168 .sizeimage = 352 * 288 * 3 / 8 + 590,
169 .colorspace = V4L2_COLORSPACE_JPEG,
171 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
173 .sizeimage = 640 * 480 * 3 / 8 + 590,
174 .colorspace = V4L2_COLORSPACE_JPEG,
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 /* Initialisation data for the Creative PC-CAM 600 */
191 static const __u16 spca504_pccam600_init_data[][3] = {
192 /* {0xa0, 0x0000, 0x0503}, * capture mode */
193 {0x00, 0x0000, 0x2000},
194 {0x00, 0x0013, 0x2301},
195 {0x00, 0x0003, 0x2000},
196 {0x00, 0x0001, 0x21ac},
197 {0x00, 0x0001, 0x21a6},
198 {0x00, 0x0000, 0x21a7}, /* brightness */
199 {0x00, 0x0020, 0x21a8}, /* contrast */
200 {0x00, 0x0001, 0x21ac}, /* sat/hue */
201 {0x00, 0x0000, 0x21ad}, /* hue */
202 {0x00, 0x001a, 0x21ae}, /* saturation */
203 {0x00, 0x0002, 0x21a3}, /* gamma */
204 {0x30, 0x0154, 0x0008},
205 {0x30, 0x0004, 0x0006},
206 {0x30, 0x0258, 0x0009},
207 {0x30, 0x0004, 0x0000},
208 {0x30, 0x0093, 0x0004},
209 {0x30, 0x0066, 0x0005},
210 {0x00, 0x0000, 0x2000},
211 {0x00, 0x0013, 0x2301},
212 {0x00, 0x0003, 0x2000},
213 {0x00, 0x0013, 0x2301},
214 {0x00, 0x0003, 0x2000},
218 /* Creative PC-CAM 600 specific open data, sent before using the
219 * generic initialisation data from spca504_open_data.
221 static const __u16 spca504_pccam600_open_data[][3] = {
222 {0x00, 0x0001, 0x2501},
223 {0x20, 0x0500, 0x0001}, /* snapshot mode */
224 {0x00, 0x0003, 0x2880},
225 {0x00, 0x0001, 0x2881},
229 /* Initialisation data for the logitech clicksmart 420 */
230 static const __u16 spca504A_clicksmart420_init_data[][3] = {
231 /* {0xa0, 0x0000, 0x0503}, * capture mode */
232 {0x00, 0x0000, 0x2000},
233 {0x00, 0x0013, 0x2301},
234 {0x00, 0x0003, 0x2000},
235 {0x00, 0x0001, 0x21ac},
236 {0x00, 0x0001, 0x21a6},
237 {0x00, 0x0000, 0x21a7}, /* brightness */
238 {0x00, 0x0020, 0x21a8}, /* contrast */
239 {0x00, 0x0001, 0x21ac}, /* sat/hue */
240 {0x00, 0x0000, 0x21ad}, /* hue */
241 {0x00, 0x001a, 0x21ae}, /* saturation */
242 {0x00, 0x0002, 0x21a3}, /* gamma */
243 {0x30, 0x0004, 0x000a},
244 {0xb0, 0x0001, 0x0000},
247 {0x0a1, 0x0080, 0x0001},
248 {0x30, 0x0049, 0x0000},
249 {0x30, 0x0060, 0x0005},
250 {0x0c, 0x0004, 0x0000},
251 {0x00, 0x0000, 0x0000},
252 {0x00, 0x0000, 0x2000},
253 {0x00, 0x0013, 0x2301},
254 {0x00, 0x0003, 0x2000},
255 {0x00, 0x0000, 0x2000},
260 /* clicksmart 420 open data ? */
261 static const __u16 spca504A_clicksmart420_open_data[][3] = {
262 {0x00, 0x0001, 0x2501},
263 {0x20, 0x0502, 0x0000},
264 {0x06, 0x0000, 0x0000},
265 {0x00, 0x0004, 0x2880},
266 {0x00, 0x0001, 0x2881},
267 /* look like setting a qTable */
268 {0x00, 0x0006, 0x2800},
269 {0x00, 0x0004, 0x2801},
270 {0x00, 0x0004, 0x2802},
271 {0x00, 0x0006, 0x2803},
272 {0x00, 0x000a, 0x2804},
273 {0x00, 0x0010, 0x2805},
274 {0x00, 0x0014, 0x2806},
275 {0x00, 0x0018, 0x2807},
276 {0x00, 0x0005, 0x2808},
277 {0x00, 0x0005, 0x2809},
278 {0x00, 0x0006, 0x280a},
279 {0x00, 0x0008, 0x280b},
280 {0x00, 0x000a, 0x280c},
281 {0x00, 0x0017, 0x280d},
282 {0x00, 0x0018, 0x280e},
283 {0x00, 0x0016, 0x280f},
285 {0x00, 0x0006, 0x2810},
286 {0x00, 0x0005, 0x2811},
287 {0x00, 0x0006, 0x2812},
288 {0x00, 0x000a, 0x2813},
289 {0x00, 0x0010, 0x2814},
290 {0x00, 0x0017, 0x2815},
291 {0x00, 0x001c, 0x2816},
292 {0x00, 0x0016, 0x2817},
293 {0x00, 0x0006, 0x2818},
294 {0x00, 0x0007, 0x2819},
295 {0x00, 0x0009, 0x281a},
296 {0x00, 0x000c, 0x281b},
297 {0x00, 0x0014, 0x281c},
298 {0x00, 0x0023, 0x281d},
299 {0x00, 0x0020, 0x281e},
300 {0x00, 0x0019, 0x281f},
302 {0x00, 0x0007, 0x2820},
303 {0x00, 0x0009, 0x2821},
304 {0x00, 0x000f, 0x2822},
305 {0x00, 0x0016, 0x2823},
306 {0x00, 0x001b, 0x2824},
307 {0x00, 0x002c, 0x2825},
308 {0x00, 0x0029, 0x2826},
309 {0x00, 0x001f, 0x2827},
310 {0x00, 0x000a, 0x2828},
311 {0x00, 0x000e, 0x2829},
312 {0x00, 0x0016, 0x282a},
313 {0x00, 0x001a, 0x282b},
314 {0x00, 0x0020, 0x282c},
315 {0x00, 0x002a, 0x282d},
316 {0x00, 0x002d, 0x282e},
317 {0x00, 0x0025, 0x282f},
319 {0x00, 0x0014, 0x2830},
320 {0x00, 0x001a, 0x2831},
321 {0x00, 0x001f, 0x2832},
322 {0x00, 0x0023, 0x2833},
323 {0x00, 0x0029, 0x2834},
324 {0x00, 0x0030, 0x2835},
325 {0x00, 0x0030, 0x2836},
326 {0x00, 0x0028, 0x2837},
327 {0x00, 0x001d, 0x2838},
328 {0x00, 0x0025, 0x2839},
329 {0x00, 0x0026, 0x283a},
330 {0x00, 0x0027, 0x283b},
331 {0x00, 0x002d, 0x283c},
332 {0x00, 0x0028, 0x283d},
333 {0x00, 0x0029, 0x283e},
334 {0x00, 0x0028, 0x283f},
336 {0x00, 0x0007, 0x2840},
337 {0x00, 0x0007, 0x2841},
338 {0x00, 0x000a, 0x2842},
339 {0x00, 0x0013, 0x2843},
340 {0x00, 0x0028, 0x2844},
341 {0x00, 0x0028, 0x2845},
342 {0x00, 0x0028, 0x2846},
343 {0x00, 0x0028, 0x2847},
344 {0x00, 0x0007, 0x2848},
345 {0x00, 0x0008, 0x2849},
346 {0x00, 0x000a, 0x284a},
347 {0x00, 0x001a, 0x284b},
348 {0x00, 0x0028, 0x284c},
349 {0x00, 0x0028, 0x284d},
350 {0x00, 0x0028, 0x284e},
351 {0x00, 0x0028, 0x284f},
353 {0x00, 0x000a, 0x2850},
354 {0x00, 0x000a, 0x2851},
355 {0x00, 0x0016, 0x2852},
356 {0x00, 0x0028, 0x2853},
357 {0x00, 0x0028, 0x2854},
358 {0x00, 0x0028, 0x2855},
359 {0x00, 0x0028, 0x2856},
360 {0x00, 0x0028, 0x2857},
361 {0x00, 0x0013, 0x2858},
362 {0x00, 0x001a, 0x2859},
363 {0x00, 0x0028, 0x285a},
364 {0x00, 0x0028, 0x285b},
365 {0x00, 0x0028, 0x285c},
366 {0x00, 0x0028, 0x285d},
367 {0x00, 0x0028, 0x285e},
368 {0x00, 0x0028, 0x285f},
370 {0x00, 0x0028, 0x2860},
371 {0x00, 0x0028, 0x2861},
372 {0x00, 0x0028, 0x2862},
373 {0x00, 0x0028, 0x2863},
374 {0x00, 0x0028, 0x2864},
375 {0x00, 0x0028, 0x2865},
376 {0x00, 0x0028, 0x2866},
377 {0x00, 0x0028, 0x2867},
378 {0x00, 0x0028, 0x2868},
379 {0x00, 0x0028, 0x2869},
380 {0x00, 0x0028, 0x286a},
381 {0x00, 0x0028, 0x286b},
382 {0x00, 0x0028, 0x286c},
383 {0x00, 0x0028, 0x286d},
384 {0x00, 0x0028, 0x286e},
385 {0x00, 0x0028, 0x286f},
387 {0x00, 0x0028, 0x2870},
388 {0x00, 0x0028, 0x2871},
389 {0x00, 0x0028, 0x2872},
390 {0x00, 0x0028, 0x2873},
391 {0x00, 0x0028, 0x2874},
392 {0x00, 0x0028, 0x2875},
393 {0x00, 0x0028, 0x2876},
394 {0x00, 0x0028, 0x2877},
395 {0x00, 0x0028, 0x2878},
396 {0x00, 0x0028, 0x2879},
397 {0x00, 0x0028, 0x287a},
398 {0x00, 0x0028, 0x287b},
399 {0x00, 0x0028, 0x287c},
400 {0x00, 0x0028, 0x287d},
401 {0x00, 0x0028, 0x287e},
402 {0x00, 0x0028, 0x287f},
404 {0xa0, 0x0000, 0x0503},
408 static const __u8 qtable_creative_pccam[2][64] = {
409 { /* Q-table Y-components */
410 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
411 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
412 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
413 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
414 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
415 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
416 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
417 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
418 { /* Q-table C-components */
419 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
420 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
421 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
422 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
423 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
424 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
425 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
426 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
429 /* FIXME: This Q-table is identical to the Creative PC-CAM one,
430 * except for one byte. Possibly a typo?
433 static const __u8 qtable_spca504_default[2][64] = {
434 { /* Q-table Y-components */
435 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
436 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
437 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
438 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
439 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
440 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
441 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
442 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
444 { /* Q-table C-components */
445 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
446 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
447 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
448 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
449 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
450 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
451 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
452 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
455 static void spca5xxRegRead(struct usb_device *dev,
458 __u8 *buffer, __u16 length)
461 usb_rcvctrlpipe(dev, 0),
463 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
465 index, buffer, length,
469 static void spca5xxRegWrite(struct usb_device *dev,
473 __u8 *buffer, __u16 length)
476 usb_sndctrlpipe(dev, 0),
478 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
479 value, index, buffer, length,
483 static int reg_write(struct usb_device *dev,
484 __u16 req, __u16 index, __u16 value)
488 ret = usb_control_msg(dev,
489 usb_sndctrlpipe(dev, 0),
491 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
492 value, index, NULL, 0, 500);
493 PDEBUG(D_PACK, "reg write: 0x%02x,0x%02x:0x%02x, 0x%x",
494 req, index, value, ret);
496 PDEBUG(D_ERR, "reg write: error %d", ret);
500 static int reg_read_info(struct usb_device *dev,
501 __u16 value) /* wValue */
506 ret = usb_control_msg(dev,
507 usb_rcvctrlpipe(dev, 0),
509 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
515 PDEBUG(D_ERR, "reg_read_info err %d", ret);
521 /* returns: negative is error, pos or zero is data */
522 static int reg_read(struct usb_device *dev,
523 __u16 req, /* bRequest */
524 __u16 index, /* wIndex */
525 __u16 length) /* wLength (1 or 2 only) */
531 ret = usb_control_msg(dev,
532 usb_rcvctrlpipe(dev, 0),
534 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
540 PDEBUG(D_ERR, "reg_read err %d", ret);
543 return (buf[1] << 8) + buf[0];
546 static int write_vector(struct gspca_dev *gspca_dev,
547 const __u16 data[][3])
549 struct usb_device *dev = gspca_dev->dev;
552 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
553 ret = reg_write(dev, data[i][0], data[i][2], data[i][1]);
556 "Register write failed for 0x%x,0x%x,0x%x",
557 data[i][0], data[i][1], data[i][2]);
565 static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
566 unsigned int request,
569 const __u8 qtable[2][64])
571 struct usb_device *dev = gspca_dev->dev;
574 /* loop over y components */
575 for (i = 0; i < 64; i++) {
576 err = reg_write(dev, request, ybase + i, qtable[0][i]);
581 /* loop over c components */
582 for (i = 0; i < 64; i++) {
583 err = reg_write(dev, request, cbase + i, qtable[1][i]);
590 static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
591 __u16 req, __u16 idx, __u16 val)
593 struct usb_device *dev = gspca_dev->dev;
596 reg_write(dev, req, idx, val);
597 notdone = reg_read(dev, 0x01, 0x0001, 1);
598 reg_write(dev, req, idx, val);
600 PDEBUG(D_FRAM, "before wait 0x%x", notdone);
603 notdone = reg_read(dev, 0x01, 0x0001, 1);
604 PDEBUG(D_FRAM, "after wait 0x%x", notdone);
607 static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
609 __u16 idx, __u16 val, __u8 stat, __u8 count)
611 struct usb_device *dev = gspca_dev->dev;
615 reg_write(dev, req, idx, val);
616 status = reg_read(dev, 0x01, 0x0001, 1);
618 PDEBUG(D_FRAM, "Status 0x%x Need 0x%x", status, stat);
622 while (--count > 0) {
624 /* gsmart mini2 write a each wait setting 1 ms is enought */
625 /* reg_write(dev, req, idx, val); */
626 status = reg_read(dev, 0x01, 0x0001, 1);
627 if (status == endcode) {
628 PDEBUG(D_FRAM, "status 0x%x after wait 0x%x",
629 status, 200 - count);
635 static int spca504B_PollingDataReady(struct usb_device *dev)
640 while (--count > 0) {
641 spca5xxRegRead(dev, 0x21, 0, &DataReady, 1);
642 if ((DataReady & 0x01) == 0)
649 static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
651 struct usb_device *dev = gspca_dev->dev;
655 while (--count > 0) {
656 spca5xxRegRead(dev, 0x21, 1, &DataReady, 1);
660 spca5xxRegWrite(dev, 0x21, 0, 1, &DataReady, 1);
661 spca5xxRegRead(dev, 0x21, 1, &DataReady, 1);
662 spca504B_PollingDataReady(dev);
669 static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
671 struct usb_device *dev = gspca_dev->dev;
673 __u8 ProductInfo[64];
675 spca5xxRegRead(dev, 0x20, 0, FW, 5);
676 PDEBUG(D_STREAM, "FirmWare : %d %d %d %d %d ",
677 FW[0], FW[1], FW[2], FW[3], FW[4]);
678 spca5xxRegRead(dev, 0x23, 0, ProductInfo, 64);
679 spca5xxRegRead(dev, 0x23, 1, ProductInfo, 64);
682 static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
684 struct sd *sd = (struct sd *) gspca_dev;
685 struct usb_device *dev = gspca_dev->dev;
690 Size = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
692 switch (sd->bridge) {
694 spca5xxRegWrite(dev, 0x31, 0, 0, NULL, 0);
695 spca504B_WaitCmdStatus(gspca_dev);
696 rc = spca504B_PollingDataReady(dev);
697 spca50x_GetFirmware(gspca_dev);
699 spca5xxRegWrite(dev, 0x24, 0, 8, &Type, 1);
700 spca5xxRegRead(dev, 0x24, 8, &Type, 1);
702 spca5xxRegWrite(dev, 0x25, 0, 4, &Size, 1);
703 spca5xxRegRead(dev, 0x25, 4, &Size, 1);
704 rc = spca504B_PollingDataReady(dev);
706 /* Init the cam width height with some values get on init ? */
707 spca5xxRegWrite(dev, 0x31, 0, 4, NULL, 0);
708 spca504B_WaitCmdStatus(gspca_dev);
709 rc = spca504B_PollingDataReady(dev);
712 /* case BRIDGE_SPCA504B: */
713 /* case BRIDGE_SPCA536: */
715 spca5xxRegWrite(dev, 0x25, 0, 4, &Size, 1);
716 spca5xxRegRead(dev, 0x25, 4, &Size, 1);
717 spca5xxRegWrite(dev, 0x27, 0, 0, &Type, 1);
718 spca5xxRegRead(dev, 0x27, 0, &Type, 1);
719 rc = spca504B_PollingDataReady(dev);
723 if (sd->subtype == AiptekMiniPenCam13) {
724 /* spca504a aiptek */
725 spca504A_acknowledged_command(gspca_dev,
727 0x80 | (Size & 0x0f), 1);
728 spca504A_acknowledged_command(gspca_dev,
731 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
734 case BRIDGE_SPCA504C:
736 reg_write(dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x0);
737 reg_write(dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
742 static void spca504_wait_status(struct gspca_dev *gspca_dev)
744 struct usb_device *dev = gspca_dev->dev;
749 /* With this we get the status, when return 0 it's all ok */
750 if (reg_read(dev, 0x06, 0x00, 1) == 0)
756 static void spca504B_setQtable(struct gspca_dev *gspca_dev)
758 struct usb_device *dev = gspca_dev->dev;
761 spca5xxRegWrite(dev, 0x26, 0, 0, &Data, 1);
762 spca5xxRegRead(dev, 0x26, 0, &Data, 1);
763 spca504B_PollingDataReady(dev);
766 static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev)
768 struct sd *sd = (struct sd *) gspca_dev;
769 struct usb_device *dev = gspca_dev->dev;
772 switch (sd->bridge) {
774 case BRIDGE_SPCA504C:
778 /* case BRIDGE_SPCA533: */
779 /* case BRIDGE_SPCA504B: */
780 spca5xxRegWrite(dev, 0, 0, 0x21a7, NULL, 0); /* brightness */
781 spca5xxRegWrite(dev, 0, 0x20, 0x21a8, NULL, 0); /* contrast */
782 spca5xxRegWrite(dev, 0, 0, 0x21ad, NULL, 0); /* hue */
783 spca5xxRegWrite(dev, 0, 1, 0x21ac, NULL, 0); /* sat/hue */
784 spca5xxRegWrite(dev, 0, 0x20, 0x21ae, NULL, 0); /* saturation */
785 spca5xxRegWrite(dev, 0, 0, 0x21a3, NULL, 0); /* gamma */
788 spca5xxRegWrite(dev, 0, 0, 0x20f0, NULL, 0);
789 spca5xxRegWrite(dev, 0, 0x21, 0x20f1, NULL, 0);
790 spca5xxRegWrite(dev, 0, 0x40, 0x20f5, NULL, 0);
791 spca5xxRegWrite(dev, 0, 1, 0x20f4, NULL, 0);
792 spca5xxRegWrite(dev, 0, 0x40, 0x20f6, NULL, 0);
793 spca5xxRegWrite(dev, 0, 0, 0x2089, NULL, 0);
797 spca504B_PollingDataReady(dev);
800 /* this function is called at probe time */
801 static int sd_config(struct gspca_dev *gspca_dev,
802 const struct usb_device_id *id)
804 struct sd *sd = (struct sd *) gspca_dev;
805 struct usb_device *dev = gspca_dev->dev;
811 vendor = id->idVendor;
812 product = id->idProduct;
814 case 0x041e: /* Creative cameras */
815 /* switch (product) { */
819 /* sd->bridge = BRIDGE_SPCA504C; */
823 case 0x0458: /* Genius KYE cameras */
824 /* switch (product) { */
826 sd->bridge = BRIDGE_SPCA504B;
830 case 0x046d: /* Logitech Labtec */
833 sd->subtype = LogitechClickSmart820;
834 sd->bridge = BRIDGE_SPCA533;
837 sd->subtype = LogitechClickSmart420;
838 sd->bridge = BRIDGE_SPCA504C;
842 case 0x0471: /* Philips */
843 /* switch (product) { */
845 sd->bridge = BRIDGE_SPCA504B;
849 case 0x04a5: /* Benq */
852 sd->bridge = BRIDGE_SPCA504B;
856 sd->bridge = BRIDGE_SPCA533;
860 case 0x04f1: /* JVC */
861 /* switch (product) { */
863 sd->bridge = BRIDGE_SPCA504B;
867 case 0x04fc: /* SunPlus */
870 sd->bridge = BRIDGE_SPCA504B;
873 /* try to get the firmware as some cam answer 2.0.1.2.2
874 * and should be a spca504b then overwrite that setting */
875 spca5xxRegRead(dev, 0x20, 0, &fw, 1);
877 sd->subtype = AiptekMiniPenCam13;
878 sd->bridge = BRIDGE_SPCA504;
879 } else if (fw == 2) {
880 sd->bridge = BRIDGE_SPCA504B;
885 sd->bridge = BRIDGE_SPCA504B;
888 sd->bridge = BRIDGE_SPCA533;
891 sd->bridge = BRIDGE_SPCA536;
894 sd->bridge = BRIDGE_SPCA504B;
898 case 0x052b: /* ?? Megapix */
899 /* switch (product) { */
901 sd->subtype = MegapixV4;
902 sd->bridge = BRIDGE_SPCA533;
906 case 0x0546: /* Polaroid */
909 sd->bridge = BRIDGE_SPCA533;
913 sd->bridge = BRIDGE_SPCA504B;
917 case 0x055f: /* Mustek cameras */
920 sd->bridge = BRIDGE_SPCA536;
924 sd->bridge = BRIDGE_SPCA533;
927 sd->bridge = BRIDGE_SPCA536;
930 sd->bridge = BRIDGE_SPCA504;
934 sd->bridge = BRIDGE_SPCA533;
937 sd->bridge = BRIDGE_SPCA504;
943 sd->bridge = BRIDGE_SPCA533;
947 case 0x05da: /* Digital Dream cameras */
948 /* switch (product) { */
950 sd->bridge = BRIDGE_SPCA504B;
954 case 0x06d6: /* Trust */
955 /* switch (product) { */
957 sd->bridge = BRIDGE_SPCA533; /* SPCA533A */
961 case 0x0733: /* Rebadged ViewQuest (Intel) and ViewQuest cameras */
967 sd->bridge = BRIDGE_SPCA533;
971 sd->bridge = BRIDGE_SPCA536;
975 case 0x08ca: /* Aiptek */
979 sd->bridge = BRIDGE_SPCA533;
982 sd->bridge = BRIDGE_SPCA504B;
985 sd->bridge = BRIDGE_SPCA533;
989 sd->bridge = BRIDGE_SPCA504B;
993 sd->bridge = BRIDGE_SPCA533;
996 sd->bridge = BRIDGE_SPCA536;
999 sd->bridge = BRIDGE_SPCA533;
1004 sd->bridge = BRIDGE_SPCA536;
1008 case 0x0d64: /* SunPlus */
1009 /* switch (product) { */
1011 sd->bridge = BRIDGE_SPCA536;
1017 cam = &gspca_dev->cam;
1018 cam->dev_name = (char *) id->driver_info;
1021 switch (sd->bridge) {
1023 /* case BRIDGE_SPCA504B: */
1024 /* case BRIDGE_SPCA504: */
1025 /* case BRIDGE_SPCA536: */
1026 cam->cam_mode = vga_mode;
1027 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
1029 case BRIDGE_SPCA533:
1030 cam->cam_mode = custom_mode;
1031 cam->nmodes = sizeof custom_mode / sizeof custom_mode[0];
1033 case BRIDGE_SPCA504C:
1034 cam->cam_mode = vga_mode2;
1035 cam->nmodes = sizeof vga_mode2 / sizeof vga_mode2[0];
1038 sd->qindex = 5; /* set the quantization table */
1039 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
1040 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
1041 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
1045 /* this function is called at open time */
1046 static int sd_open(struct gspca_dev *gspca_dev)
1048 struct sd *sd = (struct sd *) gspca_dev;
1049 struct usb_device *dev = gspca_dev->dev;
1056 switch (sd->bridge) {
1057 case BRIDGE_SPCA504B:
1058 spca5xxRegWrite(dev, 0x1d, 0, 0, NULL, 0);
1059 spca5xxRegWrite(dev, 0, 1, 0x2306, NULL, 0);
1060 spca5xxRegWrite(dev, 0, 0, 0x0d04, NULL, 0);
1061 spca5xxRegWrite(dev, 0, 0, 0x2000, NULL, 0);
1062 spca5xxRegWrite(dev, 0, 0x13, 0x2301, NULL, 0);
1063 spca5xxRegWrite(dev, 0, 0, 0x2306, NULL, 0);
1065 case BRIDGE_SPCA533:
1066 rc = spca504B_PollingDataReady(dev);
1067 spca50x_GetFirmware(gspca_dev);
1069 case BRIDGE_SPCA536:
1070 spca50x_GetFirmware(gspca_dev);
1071 spca5xxRegRead(dev, 0x00, 0x5002, &Data, 1);
1073 spca5xxRegWrite(dev, 0x24, 0, 0, &Data, 1);
1074 spca5xxRegRead(dev, 0x24, 0, &Data, 1);
1075 rc = spca504B_PollingDataReady(dev);
1076 spca5xxRegWrite(dev, 0x34, 0, 0, NULL, 0);
1077 spca504B_WaitCmdStatus(gspca_dev);
1079 case BRIDGE_SPCA504C: /* pccam600 */
1080 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
1081 reg_write(dev, 0xe0, 0x0000, 0x0000);
1082 reg_write(dev, 0xe0, 0x0000, 0x0001); /* reset */
1083 spca504_wait_status(gspca_dev);
1084 if (sd->subtype == LogitechClickSmart420)
1085 write_vector(gspca_dev,
1086 spca504A_clicksmart420_open_data);
1088 write_vector(gspca_dev, spca504_pccam600_open_data);
1089 err_code = spca50x_setup_qtable(gspca_dev,
1091 0x2840, qtable_creative_pccam);
1093 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed");
1098 /* case BRIDGE_SPCA504: */
1099 PDEBUG(D_STREAM, "Opening SPCA504");
1100 if (sd->subtype == AiptekMiniPenCam13) {
1101 /*****************************/
1102 for (i = 0; i < 6; i++)
1103 info[i] = reg_read_info(dev, i);
1105 "Read info: %d %d %d %d %d %d."
1106 " Should be 1,0,2,2,0,0",
1107 info[0], info[1], info[2],
1108 info[3], info[4], info[5]);
1109 /* spca504a aiptek */
1110 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1111 spca504A_acknowledged_command(gspca_dev, 0x24,
1113 /* Twice sequencial need status 0xff->0x9e->0x9d */
1114 spca504A_acknowledged_command(gspca_dev, 0x24,
1117 spca504A_acknowledged_command(gspca_dev, 0x24,
1119 /******************************/
1120 /* spca504a aiptek */
1121 spca504A_acknowledged_command(gspca_dev, 0x08,
1123 /* reg_write (dev, 0, 0x2000, 0); */
1124 /* reg_write (dev, 0, 0x2883, 1); */
1125 /* spca504A_acknowledged_command (gspca_dev, 0x08,
1127 /* spca504A_acknowledged_command (gspca_dev, 0x24,
1129 reg_write(dev, 0x0, 0x270c, 0x5); /* L92 sno1t.txt */
1130 reg_write(dev, 0x0, 0x2310, 0x5);
1131 spca504A_acknowledged_command(gspca_dev, 0x01,
1135 reg_write(dev, 0, 0x2000, 0);
1136 reg_write(dev, 0, 0x2883, 1);
1137 err_code = spca50x_setup_qtable(gspca_dev,
1140 qtable_spca504_default);
1142 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
1150 static void sd_start(struct gspca_dev *gspca_dev)
1152 struct sd *sd = (struct sd *) gspca_dev;
1153 struct usb_device *dev = gspca_dev->dev;
1159 if (sd->bridge == BRIDGE_SPCA504B)
1160 spca504B_setQtable(gspca_dev);
1161 spca504B_SetSizeType(gspca_dev);
1162 switch (sd->bridge) {
1164 /* case BRIDGE_SPCA504B: */
1165 /* case BRIDGE_SPCA533: */
1166 /* case BRIDGE_SPCA536: */
1167 if (sd->subtype == MegapixV4 ||
1168 sd->subtype == LogitechClickSmart820) {
1169 spca5xxRegWrite(dev, 0xf0, 0, 0, NULL, 0);
1170 spca504B_WaitCmdStatus(gspca_dev);
1171 spca5xxRegRead(dev, 0xf0, 4, NULL, 0);
1172 spca504B_WaitCmdStatus(gspca_dev);
1174 spca5xxRegWrite(dev, 0x31, 0, 4, NULL, 0);
1175 spca504B_WaitCmdStatus(gspca_dev);
1176 rc = spca504B_PollingDataReady(dev);
1179 case BRIDGE_SPCA504:
1180 if (sd->subtype == AiptekMiniPenCam13) {
1181 for (i = 0; i < 6; i++)
1182 info[i] = reg_read_info(dev, i);
1184 "Read info: %d %d %d %d %d %d."
1185 " Should be 1,0,2,2,0,0",
1186 info[0], info[1], info[2],
1187 info[3], info[4], info[5]);
1188 /* spca504a aiptek */
1189 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1190 spca504A_acknowledged_command(gspca_dev, 0x24,
1192 /* Twice sequencial need status 0xff->0x9e->0x9d */
1193 spca504A_acknowledged_command(gspca_dev, 0x24,
1195 spca504A_acknowledged_command(gspca_dev, 0x24,
1198 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1199 for (i = 0; i < 6; i++)
1200 info[i] = reg_read_info(dev, i);
1202 "Read info: %d %d %d %d %d %d."
1203 " Should be 1,0,2,2,0,0",
1204 info[0], info[1], info[2],
1205 info[3], info[4], info[5]);
1206 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1207 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1209 spca504B_SetSizeType(gspca_dev);
1210 reg_write(dev, 0x0, 0x270c, 0x5); /* L92 sno1t.txt */
1211 reg_write(dev, 0x0, 0x2310, 0x5);
1213 case BRIDGE_SPCA504C:
1214 if (sd->subtype == LogitechClickSmart420) {
1215 write_vector(gspca_dev,
1216 spca504A_clicksmart420_init_data);
1218 write_vector(gspca_dev, spca504_pccam600_init_data);
1220 enable = (sd->autogain ? 0x4 : 0x1);
1221 reg_write(dev, 0x0c, 0x0000, enable); /* auto exposure */
1222 reg_write(dev, 0xb0, 0x0000, enable); /* auto whiteness */
1224 /* set default exposure compensation and whiteness balance */
1225 reg_write(dev, 0x30, 0x0001, 800); /* ~ 20 fps */
1226 reg_write(dev, 0x30, 0x0002, 1600);
1227 spca504B_SetSizeType(gspca_dev);
1230 sp5xx_initContBrigHueRegisters(gspca_dev);
1233 static void sd_stopN(struct gspca_dev *gspca_dev)
1235 struct sd *sd = (struct sd *) gspca_dev;
1236 struct usb_device *dev = gspca_dev->dev;
1238 switch (sd->bridge) {
1240 /* case BRIDGE_SPCA533: */
1241 /* case BRIDGE_SPCA536: */
1242 /* case BRIDGE_SPCA504B: */
1243 spca5xxRegWrite(dev, 0x31, 0, 0, NULL, 0);
1244 spca504B_WaitCmdStatus(gspca_dev);
1245 spca504B_PollingDataReady(dev);
1247 case BRIDGE_SPCA504:
1248 case BRIDGE_SPCA504C:
1249 reg_write(dev, 0x00, 0x2000, 0x0000);
1251 if (sd->subtype == AiptekMiniPenCam13) {
1252 /* spca504a aiptek */
1253 /* spca504A_acknowledged_command(gspca_dev, 0x08,
1255 spca504A_acknowledged_command(gspca_dev, 0x24,
1256 0x00, 0x00, 0x9d, 1);
1257 spca504A_acknowledged_command(gspca_dev, 0x01,
1258 0x0f, 0x00, 0xff, 1);
1260 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1261 reg_write(dev, 0x01, 0x000f, 0x0);
1267 static void sd_stop0(struct gspca_dev *gspca_dev)
1271 static void sd_close(struct gspca_dev *gspca_dev)
1275 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1276 struct gspca_frame *frame, /* target */
1277 __u8 *data, /* isoc packet */
1278 int len) /* iso packet length */
1280 struct sd *sd = (struct sd *) gspca_dev;
1282 unsigned char *s, *d;
1283 static unsigned char ffd9[] = {0xff, 0xd9};
1285 /* frames are jpeg 4.1.1 without 0xff escape */
1286 switch (sd->bridge) {
1287 case BRIDGE_SPCA533:
1288 if (data[0] == 0xff) {
1289 if (data[1] != 0x01) { /* drop packet */
1290 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1294 data += SPCA533_OFFSET_DATA;
1295 len -= SPCA533_OFFSET_DATA;
1301 case BRIDGE_SPCA536:
1302 if (data[0] == 0xff) {
1304 data += SPCA536_OFFSET_DATA;
1305 len -= SPCA536_OFFSET_DATA;
1312 /* case BRIDGE_SPCA504: */
1313 /* case BRIDGE_SPCA504B: */
1315 case 0xfe: /* start of frame */
1317 data += SPCA50X_OFFSET_DATA;
1318 len -= SPCA50X_OFFSET_DATA;
1320 case 0xff: /* drop packet */
1321 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1329 case BRIDGE_SPCA504C:
1331 case 0xfe: /* start of frame */
1333 data += SPCA504_PCCAM600_OFFSET_DATA;
1334 len -= SPCA504_PCCAM600_OFFSET_DATA;
1336 case 0xff: /* drop packet */
1337 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1346 if (sof) { /* start of frame */
1347 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1350 /* put the JPEG header in the new frame */
1351 jpeg_put_header(gspca_dev, frame,
1352 ((struct sd *) gspca_dev)->qindex,
1356 /* add 0x00 after 0xff */
1357 for (i = len; --i >= 0; )
1358 if (data[i] == 0xff)
1360 if (i < 0) { /* no 0xff */
1361 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1366 for (i = 0; i < len; i++) {
1371 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1372 sd->packet, d - sd->packet);
1375 static void setbrightness(struct gspca_dev *gspca_dev)
1377 struct sd *sd = (struct sd *) gspca_dev;
1378 struct usb_device *dev = gspca_dev->dev;
1380 switch (sd->bridge) {
1382 /* case BRIDGE_SPCA533: */
1383 /* case BRIDGE_SPCA504B: */
1384 /* case BRIDGE_SPCA504: */
1385 /* case BRIDGE_SPCA504C: */
1386 reg_write(dev, 0x0, 0x21a7, sd->brightness);
1388 case BRIDGE_SPCA536:
1389 reg_write(dev, 0x0, 0x20f0, sd->brightness);
1394 static void getbrightness(struct gspca_dev *gspca_dev)
1396 struct sd *sd = (struct sd *) gspca_dev;
1397 struct usb_device *dev = gspca_dev->dev;
1398 __u16 brightness = 0;
1400 switch (sd->bridge) {
1402 /* case BRIDGE_SPCA533: */
1403 /* case BRIDGE_SPCA504B: */
1404 /* case BRIDGE_SPCA504: */
1405 /* case BRIDGE_SPCA504C: */
1406 brightness = reg_read(dev, 0x0, 0x21a7, 2);
1408 case BRIDGE_SPCA536:
1409 brightness = reg_read(dev, 0x0, 0x20f0, 2);
1412 sd->brightness = ((brightness & 0xff) - 128) % 255;
1415 static void setcontrast(struct gspca_dev *gspca_dev)
1417 struct sd *sd = (struct sd *) gspca_dev;
1418 struct usb_device *dev = gspca_dev->dev;
1420 switch (sd->bridge) {
1422 /* case BRIDGE_SPCA533: */
1423 /* case BRIDGE_SPCA504B: */
1424 /* case BRIDGE_SPCA504: */
1425 /* case BRIDGE_SPCA504C: */
1426 reg_write(dev, 0x0, 0x21a8, sd->contrast);
1428 case BRIDGE_SPCA536:
1429 reg_write(dev, 0x0, 0x20f1, sd->contrast);
1434 static void getcontrast(struct gspca_dev *gspca_dev)
1436 struct sd *sd = (struct sd *) gspca_dev;
1437 struct usb_device *dev = gspca_dev->dev;
1439 switch (sd->bridge) {
1441 /* case BRIDGE_SPCA533: */
1442 /* case BRIDGE_SPCA504B: */
1443 /* case BRIDGE_SPCA504: */
1444 /* case BRIDGE_SPCA504C: */
1445 sd->contrast = reg_read(dev, 0x0, 0x21a8, 2);
1447 case BRIDGE_SPCA536:
1448 sd->contrast = reg_read(dev, 0x0, 0x20f1, 2);
1453 static void setcolors(struct gspca_dev *gspca_dev)
1455 struct sd *sd = (struct sd *) gspca_dev;
1456 struct usb_device *dev = gspca_dev->dev;
1458 switch (sd->bridge) {
1460 /* case BRIDGE_SPCA533: */
1461 /* case BRIDGE_SPCA504B: */
1462 /* case BRIDGE_SPCA504: */
1463 /* case BRIDGE_SPCA504C: */
1464 reg_write(dev, 0x0, 0x21ae, sd->colors);
1466 case BRIDGE_SPCA536:
1467 reg_write(dev, 0x0, 0x20f6, sd->colors);
1472 static void getcolors(struct gspca_dev *gspca_dev)
1474 struct sd *sd = (struct sd *) gspca_dev;
1475 struct usb_device *dev = gspca_dev->dev;
1477 switch (sd->bridge) {
1479 /* case BRIDGE_SPCA533: */
1480 /* case BRIDGE_SPCA504B: */
1481 /* case BRIDGE_SPCA504: */
1482 /* case BRIDGE_SPCA504C: */
1483 sd->colors = reg_read(dev, 0x0, 0x21ae, 2) >> 1;
1485 case BRIDGE_SPCA536:
1486 sd->colors = reg_read(dev, 0x0, 0x20f6, 2) >> 1;
1491 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1493 struct sd *sd = (struct sd *) gspca_dev;
1495 sd->brightness = val;
1496 if (gspca_dev->streaming)
1497 setbrightness(gspca_dev);
1501 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1503 struct sd *sd = (struct sd *) gspca_dev;
1505 getbrightness(gspca_dev);
1506 *val = sd->brightness;
1510 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1512 struct sd *sd = (struct sd *) gspca_dev;
1515 if (gspca_dev->streaming)
1516 setcontrast(gspca_dev);
1520 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1522 struct sd *sd = (struct sd *) gspca_dev;
1524 getcontrast(gspca_dev);
1525 *val = sd->contrast;
1529 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1531 struct sd *sd = (struct sd *) gspca_dev;
1534 if (gspca_dev->streaming)
1535 setcolors(gspca_dev);
1539 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1541 struct sd *sd = (struct sd *) gspca_dev;
1543 getcolors(gspca_dev);
1548 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1550 struct sd *sd = (struct sd *) gspca_dev;
1556 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1558 struct sd *sd = (struct sd *) gspca_dev;
1560 *val = sd->autogain;
1564 /* sub-driver description */
1565 static const struct sd_desc sd_desc = {
1566 .name = MODULE_NAME,
1568 .nctrls = ARRAY_SIZE(sd_ctrls),
1569 .config = sd_config,
1575 .pkt_scan = sd_pkt_scan,
1578 /* -- module initialisation -- */
1579 #define DVNM(name) .driver_info = (kernel_ulong_t) name
1580 static const __devinitdata struct usb_device_id device_table[] = {
1581 {USB_DEVICE(0x041e, 0x400b), DVNM("Creative PC-CAM 600")},
1582 {USB_DEVICE(0x041e, 0x4012), DVNM("PC-Cam350")},
1583 {USB_DEVICE(0x041e, 0x4013), DVNM("Creative Pccam750")},
1584 {USB_DEVICE(0x0458, 0x7006), DVNM("Genius Dsc 1.3 Smart")},
1585 {USB_DEVICE(0x046d, 0x0905), DVNM("Logitech ClickSmart 820")},
1586 {USB_DEVICE(0x046d, 0x0960), DVNM("Logitech ClickSmart 420")},
1587 {USB_DEVICE(0x0471, 0x0322), DVNM("Philips DMVC1300K")},
1588 {USB_DEVICE(0x04a5, 0x3003), DVNM("Benq DC 1300")},
1589 {USB_DEVICE(0x04a5, 0x3008), DVNM("Benq DC 1500")},
1590 {USB_DEVICE(0x04a5, 0x300a), DVNM("Benq DC3410")},
1591 {USB_DEVICE(0x04f1, 0x1001), DVNM("JVC GC A50")},
1592 {USB_DEVICE(0x04fc, 0x500c), DVNM("Sunplus CA500C")},
1593 {USB_DEVICE(0x04fc, 0x504a), DVNM("Aiptek Mini PenCam 1.3")},
1594 {USB_DEVICE(0x04fc, 0x504b), DVNM("Maxell MaxPocket LE 1.3")},
1595 {USB_DEVICE(0x04fc, 0x5330), DVNM("Digitrex 2110")},
1596 {USB_DEVICE(0x04fc, 0x5360), DVNM("Sunplus Generic")},
1597 {USB_DEVICE(0x04fc, 0xffff), DVNM("Pure DigitalDakota")},
1598 {USB_DEVICE(0x052b, 0x1513), DVNM("Megapix V4")},
1599 {USB_DEVICE(0x0546, 0x3155), DVNM("Polaroid PDC3070")},
1600 {USB_DEVICE(0x0546, 0x3191), DVNM("Polaroid Ion 80")},
1601 {USB_DEVICE(0x0546, 0x3273), DVNM("Polaroid PDC2030")},
1602 {USB_DEVICE(0x055f, 0xc211), DVNM("Kowa Bs888e Microcamera")},
1603 {USB_DEVICE(0x055f, 0xc230), DVNM("Mustek Digicam 330K")},
1604 {USB_DEVICE(0x055f, 0xc232), DVNM("Mustek MDC3500")},
1605 {USB_DEVICE(0x055f, 0xc360), DVNM("Mustek DV4000 Mpeg4 ")},
1606 {USB_DEVICE(0x055f, 0xc420), DVNM("Mustek gSmart Mini 2")},
1607 {USB_DEVICE(0x055f, 0xc430), DVNM("Mustek Gsmart LCD 2")},
1608 {USB_DEVICE(0x055f, 0xc440), DVNM("Mustek DV 3000")},
1609 {USB_DEVICE(0x055f, 0xc520), DVNM("Mustek gSmart Mini 3")},
1610 {USB_DEVICE(0x055f, 0xc530), DVNM("Mustek Gsmart LCD 3")},
1611 {USB_DEVICE(0x055f, 0xc540), DVNM("Gsmart D30")},
1612 {USB_DEVICE(0x055f, 0xc630), DVNM("Mustek MDC4000")},
1613 {USB_DEVICE(0x055f, 0xc650), DVNM("Mustek MDC5500Z")},
1614 {USB_DEVICE(0x05da, 0x1018), DVNM("Digital Dream Enigma 1.3")},
1615 {USB_DEVICE(0x06d6, 0x0031), DVNM("Trust 610 LCD PowerC@m Zoom")},
1616 {USB_DEVICE(0x0733, 0x1311), DVNM("Digital Dream Epsilon 1.3")},
1617 {USB_DEVICE(0x0733, 0x1314), DVNM("Mercury 2.1MEG Deluxe Classic Cam")},
1618 {USB_DEVICE(0x0733, 0x2211), DVNM("Jenoptik jdc 21 LCD")},
1619 {USB_DEVICE(0x0733, 0x2221), DVNM("Mercury Digital Pro 3.1p")},
1620 {USB_DEVICE(0x0733, 0x3261), DVNM("Concord 3045 spca536a")},
1621 {USB_DEVICE(0x0733, 0x3281), DVNM("Cyberpix S550V")},
1622 {USB_DEVICE(0x08ca, 0x0104), DVNM("Aiptek PocketDVII 1.3")},
1623 {USB_DEVICE(0x08ca, 0x0106), DVNM("Aiptek Pocket DV3100+")},
1624 {USB_DEVICE(0x08ca, 0x2008), DVNM("Aiptek Mini PenCam 2 M")},
1625 {USB_DEVICE(0x08ca, 0x2010), DVNM("Aiptek PocketCam 3M")},
1626 {USB_DEVICE(0x08ca, 0x2016), DVNM("Aiptek PocketCam 2 Mega")},
1627 {USB_DEVICE(0x08ca, 0x2018), DVNM("Aiptek Pencam SD 2M")},
1628 {USB_DEVICE(0x08ca, 0x2020), DVNM("Aiptek Slim 3000F")},
1629 {USB_DEVICE(0x08ca, 0x2022), DVNM("Aiptek Slim 3200")},
1630 {USB_DEVICE(0x08ca, 0x2024), DVNM("Aiptek DV3500 Mpeg4 ")},
1631 {USB_DEVICE(0x08ca, 0x2028), DVNM("Aiptek PocketCam4M")},
1632 {USB_DEVICE(0x08ca, 0x2040), DVNM("Aiptek PocketDV4100M")},
1633 {USB_DEVICE(0x08ca, 0x2042), DVNM("Aiptek PocketDV5100")},
1634 {USB_DEVICE(0x08ca, 0x2060), DVNM("Aiptek PocketDV5300")},
1635 {USB_DEVICE(0x0d64, 0x0303), DVNM("Sunplus FashionCam DXG")},
1638 MODULE_DEVICE_TABLE(usb, device_table);
1640 /* -- device connect -- */
1641 static int sd_probe(struct usb_interface *intf,
1642 const struct usb_device_id *id)
1644 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1648 static struct usb_driver sd_driver = {
1649 .name = MODULE_NAME,
1650 .id_table = device_table,
1652 .disconnect = gspca_disconnect,
1655 /* -- module insert / remove -- */
1656 static int __init sd_mod_init(void)
1658 if (usb_register(&sd_driver) < 0)
1660 PDEBUG(D_PROBE, "v%s registered", version);
1663 static void __exit sd_mod_exit(void)
1665 usb_deregister(&sd_driver);
1666 PDEBUG(D_PROBE, "deregistered");
1669 module_init(sd_mod_init);
1670 module_exit(sd_mod_exit);