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 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28 MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
29 MODULE_LICENSE("GPL");
31 /* specific webcam descriptor */
33 struct gspca_dev gspca_dev; /* !! must be the first item */
35 __u8 packet[ISO_MAX_SIZE + 128];
36 /* !! no more than 128 ff in an ISO packet */
38 unsigned char brightness;
39 unsigned char contrast;
41 unsigned char autogain;
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
51 #define AiptekMiniPenCam13 1
52 #define LogitechClickSmart420 2
53 #define LogitechClickSmart820 3
57 /* V4L2 controls supported by the driver */
58 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
59 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
60 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
61 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
62 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
63 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
64 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
65 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
67 static struct ctrl sd_ctrls[] = {
68 #define SD_BRIGHTNESS 0
71 .id = V4L2_CID_BRIGHTNESS,
72 .type = V4L2_CTRL_TYPE_INTEGER,
79 .set = sd_setbrightness,
80 .get = sd_getbrightness,
85 .id = V4L2_CID_CONTRAST,
86 .type = V4L2_CTRL_TYPE_INTEGER,
91 .default_value = 0x20,
93 .set = sd_setcontrast,
94 .get = sd_getcontrast,
99 .id = V4L2_CID_SATURATION,
100 .type = V4L2_CTRL_TYPE_INTEGER,
105 .default_value = 0x1a,
110 #define SD_AUTOGAIN 3
113 .id = V4L2_CID_AUTOGAIN,
114 .type = V4L2_CTRL_TYPE_BOOLEAN,
121 .set = sd_setautogain,
122 .get = sd_getautogain,
126 static struct v4l2_pix_format vga_mode[] = {
127 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
129 .sizeimage = 320 * 240 * 3 / 8 + 590,
130 .colorspace = V4L2_COLORSPACE_JPEG,
132 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
134 .sizeimage = 640 * 480 * 3 / 8 + 590,
135 .colorspace = V4L2_COLORSPACE_JPEG,
139 static struct v4l2_pix_format custom_mode[] = {
140 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
142 .sizeimage = 320 * 240 * 3 / 8 + 590,
143 .colorspace = V4L2_COLORSPACE_JPEG,
145 {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
147 .sizeimage = 464 * 480 * 3 / 8 + 590,
148 .colorspace = V4L2_COLORSPACE_JPEG,
152 static struct v4l2_pix_format vga_mode2[] = {
153 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
155 .sizeimage = 176 * 144 * 3 / 8 + 590,
156 .colorspace = V4L2_COLORSPACE_JPEG,
158 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
160 .sizeimage = 320 * 240 * 3 / 8 + 590,
161 .colorspace = V4L2_COLORSPACE_JPEG,
163 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
165 .sizeimage = 352 * 288 * 3 / 8 + 590,
166 .colorspace = V4L2_COLORSPACE_JPEG,
168 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
170 .sizeimage = 640 * 480 * 3 / 8 + 590,
171 .colorspace = V4L2_COLORSPACE_JPEG,
175 #define SPCA50X_OFFSET_DATA 10
176 #define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
177 #define SPCA504_PCCAM600_OFFSET_COMPRESS 4
178 #define SPCA504_PCCAM600_OFFSET_MODE 5
179 #define SPCA504_PCCAM600_OFFSET_DATA 14
180 /* Frame packet header offsets for the spca533 */
181 #define SPCA533_OFFSET_DATA 16
182 #define SPCA533_OFFSET_FRAMSEQ 15
183 /* Frame packet header offsets for the spca536 */
184 #define SPCA536_OFFSET_DATA 4
185 #define SPCA536_OFFSET_FRAMSEQ 1
187 /* Initialisation data for the Creative PC-CAM 600 */
188 static const __u16 spca504_pccam600_init_data[][3] = {
189 /* {0xa0, 0x0000, 0x0503}, * capture mode */
190 {0x00, 0x0000, 0x2000},
191 {0x00, 0x0013, 0x2301},
192 {0x00, 0x0003, 0x2000},
193 {0x00, 0x0001, 0x21ac},
194 {0x00, 0x0001, 0x21a6},
195 {0x00, 0x0000, 0x21a7}, /* brightness */
196 {0x00, 0x0020, 0x21a8}, /* contrast */
197 {0x00, 0x0001, 0x21ac}, /* sat/hue */
198 {0x00, 0x0000, 0x21ad}, /* hue */
199 {0x00, 0x001a, 0x21ae}, /* saturation */
200 {0x00, 0x0002, 0x21a3}, /* gamma */
201 {0x30, 0x0154, 0x0008},
202 {0x30, 0x0004, 0x0006},
203 {0x30, 0x0258, 0x0009},
204 {0x30, 0x0004, 0x0000},
205 {0x30, 0x0093, 0x0004},
206 {0x30, 0x0066, 0x0005},
207 {0x00, 0x0000, 0x2000},
208 {0x00, 0x0013, 0x2301},
209 {0x00, 0x0003, 0x2000},
210 {0x00, 0x0013, 0x2301},
211 {0x00, 0x0003, 0x2000},
215 /* Creative PC-CAM 600 specific open data, sent before using the
216 * generic initialisation data from spca504_open_data.
218 static const __u16 spca504_pccam600_open_data[][3] = {
219 {0x00, 0x0001, 0x2501},
220 {0x20, 0x0500, 0x0001}, /* snapshot mode */
221 {0x00, 0x0003, 0x2880},
222 {0x00, 0x0001, 0x2881},
226 /* Initialisation data for the logitech clicksmart 420 */
227 static const __u16 spca504A_clicksmart420_init_data[][3] = {
228 /* {0xa0, 0x0000, 0x0503}, * capture mode */
229 {0x00, 0x0000, 0x2000},
230 {0x00, 0x0013, 0x2301},
231 {0x00, 0x0003, 0x2000},
232 {0x00, 0x0001, 0x21ac},
233 {0x00, 0x0001, 0x21a6},
234 {0x00, 0x0000, 0x21a7}, /* brightness */
235 {0x00, 0x0020, 0x21a8}, /* contrast */
236 {0x00, 0x0001, 0x21ac}, /* sat/hue */
237 {0x00, 0x0000, 0x21ad}, /* hue */
238 {0x00, 0x001a, 0x21ae}, /* saturation */
239 {0x00, 0x0002, 0x21a3}, /* gamma */
240 {0x30, 0x0004, 0x000a},
241 {0xb0, 0x0001, 0x0000},
244 {0x0a1, 0x0080, 0x0001},
245 {0x30, 0x0049, 0x0000},
246 {0x30, 0x0060, 0x0005},
247 {0x0c, 0x0004, 0x0000},
248 {0x00, 0x0000, 0x0000},
249 {0x00, 0x0000, 0x2000},
250 {0x00, 0x0013, 0x2301},
251 {0x00, 0x0003, 0x2000},
252 {0x00, 0x0000, 0x2000},
257 /* clicksmart 420 open data ? */
258 static const __u16 spca504A_clicksmart420_open_data[][3] = {
259 {0x00, 0x0001, 0x2501},
260 {0x20, 0x0502, 0x0000},
261 {0x06, 0x0000, 0x0000},
262 {0x00, 0x0004, 0x2880},
263 {0x00, 0x0001, 0x2881},
264 /* look like setting a qTable */
265 {0x00, 0x0006, 0x2800},
266 {0x00, 0x0004, 0x2801},
267 {0x00, 0x0004, 0x2802},
268 {0x00, 0x0006, 0x2803},
269 {0x00, 0x000a, 0x2804},
270 {0x00, 0x0010, 0x2805},
271 {0x00, 0x0014, 0x2806},
272 {0x00, 0x0018, 0x2807},
273 {0x00, 0x0005, 0x2808},
274 {0x00, 0x0005, 0x2809},
275 {0x00, 0x0006, 0x280a},
276 {0x00, 0x0008, 0x280b},
277 {0x00, 0x000a, 0x280c},
278 {0x00, 0x0017, 0x280d},
279 {0x00, 0x0018, 0x280e},
280 {0x00, 0x0016, 0x280f},
282 {0x00, 0x0006, 0x2810},
283 {0x00, 0x0005, 0x2811},
284 {0x00, 0x0006, 0x2812},
285 {0x00, 0x000a, 0x2813},
286 {0x00, 0x0010, 0x2814},
287 {0x00, 0x0017, 0x2815},
288 {0x00, 0x001c, 0x2816},
289 {0x00, 0x0016, 0x2817},
290 {0x00, 0x0006, 0x2818},
291 {0x00, 0x0007, 0x2819},
292 {0x00, 0x0009, 0x281a},
293 {0x00, 0x000c, 0x281b},
294 {0x00, 0x0014, 0x281c},
295 {0x00, 0x0023, 0x281d},
296 {0x00, 0x0020, 0x281e},
297 {0x00, 0x0019, 0x281f},
299 {0x00, 0x0007, 0x2820},
300 {0x00, 0x0009, 0x2821},
301 {0x00, 0x000f, 0x2822},
302 {0x00, 0x0016, 0x2823},
303 {0x00, 0x001b, 0x2824},
304 {0x00, 0x002c, 0x2825},
305 {0x00, 0x0029, 0x2826},
306 {0x00, 0x001f, 0x2827},
307 {0x00, 0x000a, 0x2828},
308 {0x00, 0x000e, 0x2829},
309 {0x00, 0x0016, 0x282a},
310 {0x00, 0x001a, 0x282b},
311 {0x00, 0x0020, 0x282c},
312 {0x00, 0x002a, 0x282d},
313 {0x00, 0x002d, 0x282e},
314 {0x00, 0x0025, 0x282f},
316 {0x00, 0x0014, 0x2830},
317 {0x00, 0x001a, 0x2831},
318 {0x00, 0x001f, 0x2832},
319 {0x00, 0x0023, 0x2833},
320 {0x00, 0x0029, 0x2834},
321 {0x00, 0x0030, 0x2835},
322 {0x00, 0x0030, 0x2836},
323 {0x00, 0x0028, 0x2837},
324 {0x00, 0x001d, 0x2838},
325 {0x00, 0x0025, 0x2839},
326 {0x00, 0x0026, 0x283a},
327 {0x00, 0x0027, 0x283b},
328 {0x00, 0x002d, 0x283c},
329 {0x00, 0x0028, 0x283d},
330 {0x00, 0x0029, 0x283e},
331 {0x00, 0x0028, 0x283f},
333 {0x00, 0x0007, 0x2840},
334 {0x00, 0x0007, 0x2841},
335 {0x00, 0x000a, 0x2842},
336 {0x00, 0x0013, 0x2843},
337 {0x00, 0x0028, 0x2844},
338 {0x00, 0x0028, 0x2845},
339 {0x00, 0x0028, 0x2846},
340 {0x00, 0x0028, 0x2847},
341 {0x00, 0x0007, 0x2848},
342 {0x00, 0x0008, 0x2849},
343 {0x00, 0x000a, 0x284a},
344 {0x00, 0x001a, 0x284b},
345 {0x00, 0x0028, 0x284c},
346 {0x00, 0x0028, 0x284d},
347 {0x00, 0x0028, 0x284e},
348 {0x00, 0x0028, 0x284f},
350 {0x00, 0x000a, 0x2850},
351 {0x00, 0x000a, 0x2851},
352 {0x00, 0x0016, 0x2852},
353 {0x00, 0x0028, 0x2853},
354 {0x00, 0x0028, 0x2854},
355 {0x00, 0x0028, 0x2855},
356 {0x00, 0x0028, 0x2856},
357 {0x00, 0x0028, 0x2857},
358 {0x00, 0x0013, 0x2858},
359 {0x00, 0x001a, 0x2859},
360 {0x00, 0x0028, 0x285a},
361 {0x00, 0x0028, 0x285b},
362 {0x00, 0x0028, 0x285c},
363 {0x00, 0x0028, 0x285d},
364 {0x00, 0x0028, 0x285e},
365 {0x00, 0x0028, 0x285f},
367 {0x00, 0x0028, 0x2860},
368 {0x00, 0x0028, 0x2861},
369 {0x00, 0x0028, 0x2862},
370 {0x00, 0x0028, 0x2863},
371 {0x00, 0x0028, 0x2864},
372 {0x00, 0x0028, 0x2865},
373 {0x00, 0x0028, 0x2866},
374 {0x00, 0x0028, 0x2867},
375 {0x00, 0x0028, 0x2868},
376 {0x00, 0x0028, 0x2869},
377 {0x00, 0x0028, 0x286a},
378 {0x00, 0x0028, 0x286b},
379 {0x00, 0x0028, 0x286c},
380 {0x00, 0x0028, 0x286d},
381 {0x00, 0x0028, 0x286e},
382 {0x00, 0x0028, 0x286f},
384 {0x00, 0x0028, 0x2870},
385 {0x00, 0x0028, 0x2871},
386 {0x00, 0x0028, 0x2872},
387 {0x00, 0x0028, 0x2873},
388 {0x00, 0x0028, 0x2874},
389 {0x00, 0x0028, 0x2875},
390 {0x00, 0x0028, 0x2876},
391 {0x00, 0x0028, 0x2877},
392 {0x00, 0x0028, 0x2878},
393 {0x00, 0x0028, 0x2879},
394 {0x00, 0x0028, 0x287a},
395 {0x00, 0x0028, 0x287b},
396 {0x00, 0x0028, 0x287c},
397 {0x00, 0x0028, 0x287d},
398 {0x00, 0x0028, 0x287e},
399 {0x00, 0x0028, 0x287f},
401 {0xa0, 0x0000, 0x0503},
405 static const __u8 qtable_creative_pccam[2][64] = {
406 { /* Q-table Y-components */
407 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
408 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
409 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
410 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
411 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
412 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
413 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
414 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
415 { /* Q-table C-components */
416 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
417 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
418 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
419 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
420 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
421 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
422 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
423 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
426 /* FIXME: This Q-table is identical to the Creative PC-CAM one,
427 * except for one byte. Possibly a typo?
430 static const __u8 qtable_spca504_default[2][64] = {
431 { /* Q-table Y-components */
432 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
433 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
434 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
435 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
436 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
437 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
438 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
439 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
441 { /* Q-table C-components */
442 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
443 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
444 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
445 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
446 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
447 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
448 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
449 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
452 static void reg_r(struct usb_device *dev,
455 __u8 *buffer, __u16 length)
458 usb_rcvctrlpipe(dev, 0),
460 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
462 index, buffer, length,
466 static void reg_w(struct usb_device *dev,
470 __u8 *buffer, __u16 length)
473 usb_sndctrlpipe(dev, 0),
475 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
476 value, index, buffer, length,
480 /* write req / index / value */
481 static int reg_w_riv(struct usb_device *dev,
482 __u16 req, __u16 index, __u16 value)
486 ret = usb_control_msg(dev,
487 usb_sndctrlpipe(dev, 0),
489 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
490 value, index, NULL, 0, 500);
491 PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d",
492 req, index, value, ret);
494 PDEBUG(D_ERR, "reg write: error %d", ret);
499 static int reg_r_1(struct gspca_dev *gspca_dev,
500 __u16 value) /* wValue */
504 ret = usb_control_msg(gspca_dev->dev,
505 usb_rcvctrlpipe(gspca_dev->dev, 0),
507 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
510 gspca_dev->usb_buf, 1,
513 PDEBUG(D_ERR, "reg_r_1 err %d", ret);
516 return gspca_dev->usb_buf[0];
519 /* read 1 or 2 bytes - returns < 0 if error */
520 static int reg_r_12(struct gspca_dev *gspca_dev,
521 __u16 req, /* bRequest */
522 __u16 index, /* wIndex */
523 __u16 length) /* wLength (1 or 2 only) */
527 gspca_dev->usb_buf[1] = 0;
528 ret = usb_control_msg(gspca_dev->dev,
529 usb_rcvctrlpipe(gspca_dev->dev, 0),
531 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
534 gspca_dev->usb_buf, length,
537 PDEBUG(D_ERR, "reg_read err %d", ret);
540 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
543 static int write_vector(struct gspca_dev *gspca_dev,
544 const __u16 data[][3])
546 struct usb_device *dev = gspca_dev->dev;
549 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
550 ret = reg_w_riv(dev, data[i][0], data[i][2], data[i][1]);
553 "Register write failed for 0x%x,0x%x,0x%x",
554 data[i][0], data[i][1], data[i][2]);
562 static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
563 unsigned int request,
566 const __u8 qtable[2][64])
568 struct usb_device *dev = gspca_dev->dev;
571 /* loop over y components */
572 for (i = 0; i < 64; i++) {
573 err = reg_w_riv(dev, request, ybase + i, qtable[0][i]);
578 /* loop over c components */
579 for (i = 0; i < 64; i++) {
580 err = reg_w_riv(dev, request, cbase + i, qtable[1][i]);
587 static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
588 __u16 req, __u16 idx, __u16 val)
590 struct usb_device *dev = gspca_dev->dev;
593 reg_w_riv(dev, req, idx, val);
594 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
595 reg_w_riv(dev, req, idx, val);
597 PDEBUG(D_FRAM, "before wait 0x%x", notdone);
600 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
601 PDEBUG(D_FRAM, "after wait 0x%x", notdone);
604 static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
606 __u16 idx, __u16 val, __u8 stat, __u8 count)
608 struct usb_device *dev = gspca_dev->dev;
612 reg_w_riv(dev, req, idx, val);
613 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
615 PDEBUG(D_FRAM, "Status 0x%x Need 0x%x", status, stat);
619 while (--count > 0) {
621 /* gsmart mini2 write a each wait setting 1 ms is enought */
622 /* reg_w_riv(dev, req, idx, val); */
623 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
624 if (status == endcode) {
625 PDEBUG(D_FRAM, "status 0x%x after wait 0x%x",
626 status, 200 - count);
632 static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
636 while (--count > 0) {
637 reg_r(gspca_dev->dev, 0x21, 0, gspca_dev->usb_buf, 1);
638 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
642 return gspca_dev->usb_buf[0];
645 static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
647 struct usb_device *dev = gspca_dev->dev;
650 while (--count > 0) {
651 reg_r(dev, 0x21, 1, gspca_dev->usb_buf, 1);
652 if (gspca_dev->usb_buf[0] != 0) {
653 gspca_dev->usb_buf[0] = 0;
654 reg_w(dev, 0x21, 0, 1, gspca_dev->usb_buf, 1);
655 reg_r(dev, 0x21, 1, gspca_dev->usb_buf, 1);
656 spca504B_PollingDataReady(gspca_dev);
663 static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
665 struct usb_device *dev = gspca_dev->dev;
668 data = kmalloc(64, GFP_KERNEL);
669 reg_r(dev, 0x20, 0, data, 5);
670 PDEBUG(D_STREAM, "FirmWare : %d %d %d %d %d ",
671 data[0], data[1], data[2], data[3], data[4]);
672 reg_r(dev, 0x23, 0, data, 64);
673 reg_r(dev, 0x23, 1, data, 64);
677 static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
679 struct sd *sd = (struct sd *) gspca_dev;
680 struct usb_device *dev = gspca_dev->dev;
685 Size = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
687 switch (sd->bridge) {
689 reg_w(dev, 0x31, 0, 0, NULL, 0);
690 spca504B_WaitCmdStatus(gspca_dev);
691 rc = spca504B_PollingDataReady(gspca_dev);
692 spca50x_GetFirmware(gspca_dev);
693 gspca_dev->usb_buf[0] = 2; /* type */
694 reg_w(dev, 0x24, 0, 8, gspca_dev->usb_buf, 1);
695 reg_r(dev, 0x24, 8, gspca_dev->usb_buf, 1);
697 gspca_dev->usb_buf[0] = Size;
698 reg_w(dev, 0x25, 0, 4, gspca_dev->usb_buf, 1);
699 reg_r(dev, 0x25, 4, gspca_dev->usb_buf, 1); /* size */
700 rc = spca504B_PollingDataReady(gspca_dev);
702 /* Init the cam width height with some values get on init ? */
703 reg_w(dev, 0x31, 0, 4, NULL, 0);
704 spca504B_WaitCmdStatus(gspca_dev);
705 rc = spca504B_PollingDataReady(gspca_dev);
708 /* case BRIDGE_SPCA504B: */
709 /* case BRIDGE_SPCA536: */
710 gspca_dev->usb_buf[0] = Size;
711 reg_w(dev, 0x25, 0, 4, gspca_dev->usb_buf, 1);
712 reg_r(dev, 0x25, 4, gspca_dev->usb_buf, 1); /* size */
714 gspca_dev->usb_buf[0] = Type;
715 reg_w(dev, 0x27, 0, 0, gspca_dev->usb_buf, 1);
716 reg_r(dev, 0x27, 0, gspca_dev->usb_buf, 1); /* type */
717 rc = spca504B_PollingDataReady(gspca_dev);
721 if (sd->subtype == AiptekMiniPenCam13) {
722 /* spca504a aiptek */
723 spca504A_acknowledged_command(gspca_dev,
725 0x80 | (Size & 0x0f), 1);
726 spca504A_acknowledged_command(gspca_dev,
729 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
732 case BRIDGE_SPCA504C:
734 reg_w_riv(dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
735 reg_w_riv(dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
740 static void spca504_wait_status(struct gspca_dev *gspca_dev)
746 /* With this we get the status, when return 0 it's all ok */
747 if (reg_r_12(gspca_dev, 0x06, 0x00, 1) == 0)
753 static void spca504B_setQtable(struct gspca_dev *gspca_dev)
755 struct usb_device *dev = gspca_dev->dev;
757 gspca_dev->usb_buf[0] = 3;
758 reg_w(dev, 0x26, 0, 0, gspca_dev->usb_buf, 1);
759 reg_r(dev, 0x26, 0, gspca_dev->usb_buf, 1);
760 spca504B_PollingDataReady(gspca_dev);
763 static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev)
765 struct sd *sd = (struct sd *) gspca_dev;
766 struct usb_device *dev = gspca_dev->dev;
769 switch (sd->bridge) {
771 case BRIDGE_SPCA504C:
775 /* case BRIDGE_SPCA533: */
776 /* case BRIDGE_SPCA504B: */
777 reg_w(dev, 0, 0, 0x21a7, NULL, 0); /* brightness */
778 reg_w(dev, 0, 0x20, 0x21a8, NULL, 0); /* contrast */
779 reg_w(dev, 0, 0, 0x21ad, NULL, 0); /* hue */
780 reg_w(dev, 0, 1, 0x21ac, NULL, 0); /* sat/hue */
781 reg_w(dev, 0, 0x20, 0x21ae, NULL, 0); /* saturation */
782 reg_w(dev, 0, 0, 0x21a3, NULL, 0); /* gamma */
785 reg_w(dev, 0, 0, 0x20f0, NULL, 0);
786 reg_w(dev, 0, 0x21, 0x20f1, NULL, 0);
787 reg_w(dev, 0, 0x40, 0x20f5, NULL, 0);
788 reg_w(dev, 0, 1, 0x20f4, NULL, 0);
789 reg_w(dev, 0, 0x40, 0x20f6, NULL, 0);
790 reg_w(dev, 0, 0, 0x2089, NULL, 0);
794 spca504B_PollingDataReady(gspca_dev);
797 /* this function is called at probe time */
798 static int sd_config(struct gspca_dev *gspca_dev,
799 const struct usb_device_id *id)
801 struct sd *sd = (struct sd *) gspca_dev;
802 struct usb_device *dev = gspca_dev->dev;
808 vendor = id->idVendor;
809 product = id->idProduct;
811 case 0x041e: /* Creative cameras */
812 /* switch (product) { */
816 /* sd->bridge = BRIDGE_SPCA504C; */
820 case 0x0458: /* Genius KYE cameras */
821 /* switch (product) { */
823 sd->bridge = BRIDGE_SPCA504B;
827 case 0x0461: /* MicroInnovation */
828 /* switch (product) { */
830 sd->bridge = BRIDGE_SPCA533;
834 case 0x046d: /* Logitech Labtec */
837 sd->subtype = LogitechClickSmart820;
838 sd->bridge = BRIDGE_SPCA533;
841 sd->subtype = LogitechClickSmart420;
842 sd->bridge = BRIDGE_SPCA504C;
846 case 0x0471: /* Philips */
847 /* switch (product) { */
849 sd->bridge = BRIDGE_SPCA504B;
853 case 0x04a5: /* Benq */
856 sd->bridge = BRIDGE_SPCA504B;
860 sd->bridge = BRIDGE_SPCA533;
864 case 0x04f1: /* JVC */
865 /* switch (product) { */
867 sd->bridge = BRIDGE_SPCA504B;
871 case 0x04fc: /* SunPlus */
874 sd->bridge = BRIDGE_SPCA504B;
877 /* try to get the firmware as some cam answer 2.0.1.2.2
878 * and should be a spca504b then overwrite that setting */
879 reg_r(dev, 0x20, 0, gspca_dev->usb_buf, 1);
880 fw = gspca_dev->usb_buf[0];
882 sd->subtype = AiptekMiniPenCam13;
883 sd->bridge = BRIDGE_SPCA504;
884 } else if (fw == 2) {
885 sd->bridge = BRIDGE_SPCA504B;
890 sd->bridge = BRIDGE_SPCA504B;
893 sd->bridge = BRIDGE_SPCA533;
896 sd->bridge = BRIDGE_SPCA536;
899 sd->bridge = BRIDGE_SPCA504B;
903 case 0x052b: /* ?? Megapix */
904 /* switch (product) { */
906 sd->subtype = MegapixV4;
907 sd->bridge = BRIDGE_SPCA533;
911 case 0x0546: /* Polaroid */
914 sd->bridge = BRIDGE_SPCA533;
918 sd->bridge = BRIDGE_SPCA504B;
922 case 0x055f: /* Mustek cameras */
925 sd->bridge = BRIDGE_SPCA536;
929 sd->bridge = BRIDGE_SPCA533;
932 sd->bridge = BRIDGE_SPCA536;
935 sd->bridge = BRIDGE_SPCA504;
939 sd->bridge = BRIDGE_SPCA533;
942 sd->bridge = BRIDGE_SPCA504;
948 sd->bridge = BRIDGE_SPCA533;
952 case 0x05da: /* Digital Dream cameras */
953 /* switch (product) { */
955 sd->bridge = BRIDGE_SPCA504B;
959 case 0x06d6: /* Trust */
960 /* switch (product) { */
962 sd->bridge = BRIDGE_SPCA533; /* SPCA533A */
966 case 0x0733: /* Rebadged ViewQuest (Intel) and ViewQuest cameras */
972 sd->bridge = BRIDGE_SPCA533;
976 sd->bridge = BRIDGE_SPCA536;
980 case 0x08ca: /* Aiptek */
984 sd->bridge = BRIDGE_SPCA533;
987 sd->bridge = BRIDGE_SPCA504B;
990 sd->bridge = BRIDGE_SPCA533;
994 sd->bridge = BRIDGE_SPCA504B;
998 sd->bridge = BRIDGE_SPCA533;
1001 sd->bridge = BRIDGE_SPCA536;
1004 sd->bridge = BRIDGE_SPCA533;
1010 sd->bridge = BRIDGE_SPCA536;
1014 case 0x0d64: /* SunPlus */
1015 /* switch (product) { */
1017 sd->bridge = BRIDGE_SPCA536;
1023 cam = &gspca_dev->cam;
1024 cam->dev_name = (char *) id->driver_info;
1027 switch (sd->bridge) {
1029 /* case BRIDGE_SPCA504B: */
1030 /* case BRIDGE_SPCA504: */
1031 /* case BRIDGE_SPCA536: */
1032 cam->cam_mode = vga_mode;
1033 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
1035 case BRIDGE_SPCA533:
1036 cam->cam_mode = custom_mode;
1037 cam->nmodes = sizeof custom_mode / sizeof custom_mode[0];
1039 case BRIDGE_SPCA504C:
1040 cam->cam_mode = vga_mode2;
1041 cam->nmodes = sizeof vga_mode2 / sizeof vga_mode2[0];
1044 sd->qindex = 5; /* set the quantization table */
1045 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
1046 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
1047 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
1051 /* this function is called at open time */
1052 static int sd_open(struct gspca_dev *gspca_dev)
1054 struct sd *sd = (struct sd *) gspca_dev;
1055 struct usb_device *dev = gspca_dev->dev;
1061 switch (sd->bridge) {
1062 case BRIDGE_SPCA504B:
1063 reg_w(dev, 0x1d, 0, 0, NULL, 0);
1064 reg_w(dev, 0, 1, 0x2306, NULL, 0);
1065 reg_w(dev, 0, 0, 0x0d04, NULL, 0);
1066 reg_w(dev, 0, 0, 0x2000, NULL, 0);
1067 reg_w(dev, 0, 0x13, 0x2301, NULL, 0);
1068 reg_w(dev, 0, 0, 0x2306, NULL, 0);
1070 case BRIDGE_SPCA533:
1071 rc = spca504B_PollingDataReady(gspca_dev);
1072 spca50x_GetFirmware(gspca_dev);
1074 case BRIDGE_SPCA536:
1075 spca50x_GetFirmware(gspca_dev);
1076 reg_r(dev, 0x00, 0x5002, gspca_dev->usb_buf, 1);
1077 gspca_dev->usb_buf[0] = 0;
1078 reg_w(dev, 0x24, 0, 0, gspca_dev->usb_buf, 1);
1079 reg_r(dev, 0x24, 0, gspca_dev->usb_buf, 1);
1080 rc = spca504B_PollingDataReady(gspca_dev);
1081 reg_w(dev, 0x34, 0, 0, NULL, 0);
1082 spca504B_WaitCmdStatus(gspca_dev);
1084 case BRIDGE_SPCA504C: /* pccam600 */
1085 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
1086 reg_w_riv(dev, 0xe0, 0x0000, 0x0000);
1087 reg_w_riv(dev, 0xe0, 0x0000, 0x0001); /* reset */
1088 spca504_wait_status(gspca_dev);
1089 if (sd->subtype == LogitechClickSmart420)
1090 write_vector(gspca_dev,
1091 spca504A_clicksmart420_open_data);
1093 write_vector(gspca_dev, spca504_pccam600_open_data);
1094 err_code = spca50x_setup_qtable(gspca_dev,
1096 0x2840, qtable_creative_pccam);
1098 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed");
1103 /* case BRIDGE_SPCA504: */
1104 PDEBUG(D_STREAM, "Opening SPCA504");
1105 if (sd->subtype == AiptekMiniPenCam13) {
1106 /*****************************/
1107 for (i = 0; i < 6; i++)
1108 info[i] = reg_r_1(gspca_dev, i);
1110 "Read info: %d %d %d %d %d %d."
1111 " Should be 1,0,2,2,0,0",
1112 info[0], info[1], info[2],
1113 info[3], info[4], info[5]);
1114 /* spca504a aiptek */
1115 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1116 spca504A_acknowledged_command(gspca_dev, 0x24,
1118 /* Twice sequencial need status 0xff->0x9e->0x9d */
1119 spca504A_acknowledged_command(gspca_dev, 0x24,
1122 spca504A_acknowledged_command(gspca_dev, 0x24,
1124 /******************************/
1125 /* spca504a aiptek */
1126 spca504A_acknowledged_command(gspca_dev, 0x08,
1128 /* reg_write (dev, 0, 0x2000, 0); */
1129 /* reg_write (dev, 0, 0x2883, 1); */
1130 /* spca504A_acknowledged_command (gspca_dev, 0x08,
1132 /* spca504A_acknowledged_command (gspca_dev, 0x24,
1134 reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */
1135 reg_w_riv(dev, 0x0, 0x2310, 0x05);
1136 spca504A_acknowledged_command(gspca_dev, 0x01,
1140 reg_w_riv(dev, 0, 0x2000, 0);
1141 reg_w_riv(dev, 0, 0x2883, 1);
1142 err_code = spca50x_setup_qtable(gspca_dev,
1145 qtable_spca504_default);
1147 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
1155 static void sd_start(struct gspca_dev *gspca_dev)
1157 struct sd *sd = (struct sd *) gspca_dev;
1158 struct usb_device *dev = gspca_dev->dev;
1164 if (sd->bridge == BRIDGE_SPCA504B)
1165 spca504B_setQtable(gspca_dev);
1166 spca504B_SetSizeType(gspca_dev);
1167 switch (sd->bridge) {
1169 /* case BRIDGE_SPCA504B: */
1170 /* case BRIDGE_SPCA533: */
1171 /* case BRIDGE_SPCA536: */
1172 if (sd->subtype == MegapixV4 ||
1173 sd->subtype == LogitechClickSmart820) {
1174 reg_w(dev, 0xf0, 0, 0, NULL, 0);
1175 spca504B_WaitCmdStatus(gspca_dev);
1176 reg_r(dev, 0xf0, 4, NULL, 0);
1177 spca504B_WaitCmdStatus(gspca_dev);
1179 reg_w(dev, 0x31, 0, 4, NULL, 0);
1180 spca504B_WaitCmdStatus(gspca_dev);
1181 rc = spca504B_PollingDataReady(gspca_dev);
1184 case BRIDGE_SPCA504:
1185 if (sd->subtype == AiptekMiniPenCam13) {
1186 for (i = 0; i < 6; i++)
1187 info[i] = reg_r_1(gspca_dev, i);
1189 "Read info: %d %d %d %d %d %d."
1190 " Should be 1,0,2,2,0,0",
1191 info[0], info[1], info[2],
1192 info[3], info[4], info[5]);
1193 /* spca504a aiptek */
1194 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1195 spca504A_acknowledged_command(gspca_dev, 0x24,
1197 /* Twice sequencial need status 0xff->0x9e->0x9d */
1198 spca504A_acknowledged_command(gspca_dev, 0x24,
1200 spca504A_acknowledged_command(gspca_dev, 0x24,
1203 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1204 for (i = 0; i < 6; i++)
1205 info[i] = reg_r_1(gspca_dev, i);
1207 "Read info: %d %d %d %d %d %d."
1208 " Should be 1,0,2,2,0,0",
1209 info[0], info[1], info[2],
1210 info[3], info[4], info[5]);
1211 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1212 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1214 spca504B_SetSizeType(gspca_dev);
1215 reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */
1216 reg_w_riv(dev, 0x0, 0x2310, 0x05);
1218 case BRIDGE_SPCA504C:
1219 if (sd->subtype == LogitechClickSmart420) {
1220 write_vector(gspca_dev,
1221 spca504A_clicksmart420_init_data);
1223 write_vector(gspca_dev, spca504_pccam600_init_data);
1225 enable = (sd->autogain ? 0x04 : 0x01);
1226 reg_w_riv(dev, 0x0c, 0x0000, enable); /* auto exposure */
1227 reg_w_riv(dev, 0xb0, 0x0000, enable); /* auto whiteness */
1229 /* set default exposure compensation and whiteness balance */
1230 reg_w_riv(dev, 0x30, 0x0001, 800); /* ~ 20 fps */
1231 reg_w_riv(dev, 0x30, 0x0002, 1600);
1232 spca504B_SetSizeType(gspca_dev);
1235 sp5xx_initContBrigHueRegisters(gspca_dev);
1238 static void sd_stopN(struct gspca_dev *gspca_dev)
1240 struct sd *sd = (struct sd *) gspca_dev;
1241 struct usb_device *dev = gspca_dev->dev;
1243 switch (sd->bridge) {
1245 /* case BRIDGE_SPCA533: */
1246 /* case BRIDGE_SPCA536: */
1247 /* case BRIDGE_SPCA504B: */
1248 reg_w(dev, 0x31, 0, 0, NULL, 0);
1249 spca504B_WaitCmdStatus(gspca_dev);
1250 spca504B_PollingDataReady(gspca_dev);
1252 case BRIDGE_SPCA504:
1253 case BRIDGE_SPCA504C:
1254 reg_w_riv(dev, 0x00, 0x2000, 0x0000);
1256 if (sd->subtype == AiptekMiniPenCam13) {
1257 /* spca504a aiptek */
1258 /* spca504A_acknowledged_command(gspca_dev, 0x08,
1260 spca504A_acknowledged_command(gspca_dev, 0x24,
1261 0x00, 0x00, 0x9d, 1);
1262 spca504A_acknowledged_command(gspca_dev, 0x01,
1263 0x0f, 0x00, 0xff, 1);
1265 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1266 reg_w_riv(dev, 0x01, 0x000f, 0x00);
1272 static void sd_stop0(struct gspca_dev *gspca_dev)
1276 static void sd_close(struct gspca_dev *gspca_dev)
1280 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1281 struct gspca_frame *frame, /* target */
1282 __u8 *data, /* isoc packet */
1283 int len) /* iso packet length */
1285 struct sd *sd = (struct sd *) gspca_dev;
1287 unsigned char *s, *d;
1288 static unsigned char ffd9[] = {0xff, 0xd9};
1290 /* frames are jpeg 4.1.1 without 0xff escape */
1291 switch (sd->bridge) {
1292 case BRIDGE_SPCA533:
1293 if (data[0] == 0xff) {
1294 if (data[1] != 0x01) { /* drop packet */
1295 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1299 data += SPCA533_OFFSET_DATA;
1300 len -= SPCA533_OFFSET_DATA;
1306 case BRIDGE_SPCA536:
1307 if (data[0] == 0xff) {
1309 data += SPCA536_OFFSET_DATA;
1310 len -= SPCA536_OFFSET_DATA;
1317 /* case BRIDGE_SPCA504: */
1318 /* case BRIDGE_SPCA504B: */
1320 case 0xfe: /* start of frame */
1322 data += SPCA50X_OFFSET_DATA;
1323 len -= SPCA50X_OFFSET_DATA;
1325 case 0xff: /* drop packet */
1326 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1334 case BRIDGE_SPCA504C:
1336 case 0xfe: /* start of frame */
1338 data += SPCA504_PCCAM600_OFFSET_DATA;
1339 len -= SPCA504_PCCAM600_OFFSET_DATA;
1341 case 0xff: /* drop packet */
1342 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1351 if (sof) { /* start of frame */
1352 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1355 /* put the JPEG header in the new frame */
1356 jpeg_put_header(gspca_dev, frame,
1357 ((struct sd *) gspca_dev)->qindex,
1361 /* add 0x00 after 0xff */
1362 for (i = len; --i >= 0; )
1363 if (data[i] == 0xff)
1365 if (i < 0) { /* no 0xff */
1366 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1371 for (i = 0; i < len; i++) {
1376 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1377 sd->packet, d - sd->packet);
1380 static void setbrightness(struct gspca_dev *gspca_dev)
1382 struct sd *sd = (struct sd *) gspca_dev;
1383 struct usb_device *dev = gspca_dev->dev;
1385 switch (sd->bridge) {
1387 /* case BRIDGE_SPCA533: */
1388 /* case BRIDGE_SPCA504B: */
1389 /* case BRIDGE_SPCA504: */
1390 /* case BRIDGE_SPCA504C: */
1391 reg_w_riv(dev, 0x0, 0x21a7, sd->brightness);
1393 case BRIDGE_SPCA536:
1394 reg_w_riv(dev, 0x0, 0x20f0, sd->brightness);
1399 static void getbrightness(struct gspca_dev *gspca_dev)
1401 struct sd *sd = (struct sd *) gspca_dev;
1402 __u16 brightness = 0;
1404 switch (sd->bridge) {
1406 /* case BRIDGE_SPCA533: */
1407 /* case BRIDGE_SPCA504B: */
1408 /* case BRIDGE_SPCA504: */
1409 /* case BRIDGE_SPCA504C: */
1410 brightness = reg_r_12(gspca_dev, 0x00, 0x21a7, 2);
1412 case BRIDGE_SPCA536:
1413 brightness = reg_r_12(gspca_dev, 0x00, 0x20f0, 2);
1416 sd->brightness = ((brightness & 0xff) - 128) % 255;
1419 static void setcontrast(struct gspca_dev *gspca_dev)
1421 struct sd *sd = (struct sd *) gspca_dev;
1422 struct usb_device *dev = gspca_dev->dev;
1424 switch (sd->bridge) {
1426 /* case BRIDGE_SPCA533: */
1427 /* case BRIDGE_SPCA504B: */
1428 /* case BRIDGE_SPCA504: */
1429 /* case BRIDGE_SPCA504C: */
1430 reg_w_riv(dev, 0x0, 0x21a8, sd->contrast);
1432 case BRIDGE_SPCA536:
1433 reg_w_riv(dev, 0x0, 0x20f1, sd->contrast);
1438 static void getcontrast(struct gspca_dev *gspca_dev)
1440 struct sd *sd = (struct sd *) gspca_dev;
1442 switch (sd->bridge) {
1444 /* case BRIDGE_SPCA533: */
1445 /* case BRIDGE_SPCA504B: */
1446 /* case BRIDGE_SPCA504: */
1447 /* case BRIDGE_SPCA504C: */
1448 sd->contrast = reg_r_12(gspca_dev, 0x00, 0x21a8, 2);
1450 case BRIDGE_SPCA536:
1451 sd->contrast = reg_r_12(gspca_dev, 0x00, 0x20f1, 2);
1456 static void setcolors(struct gspca_dev *gspca_dev)
1458 struct sd *sd = (struct sd *) gspca_dev;
1459 struct usb_device *dev = gspca_dev->dev;
1461 switch (sd->bridge) {
1463 /* case BRIDGE_SPCA533: */
1464 /* case BRIDGE_SPCA504B: */
1465 /* case BRIDGE_SPCA504: */
1466 /* case BRIDGE_SPCA504C: */
1467 reg_w_riv(dev, 0x0, 0x21ae, sd->colors);
1469 case BRIDGE_SPCA536:
1470 reg_w_riv(dev, 0x0, 0x20f6, sd->colors);
1475 static void getcolors(struct gspca_dev *gspca_dev)
1477 struct sd *sd = (struct sd *) gspca_dev;
1479 switch (sd->bridge) {
1481 /* case BRIDGE_SPCA533: */
1482 /* case BRIDGE_SPCA504B: */
1483 /* case BRIDGE_SPCA504: */
1484 /* case BRIDGE_SPCA504C: */
1485 sd->colors = reg_r_12(gspca_dev, 0x00, 0x21ae, 2) >> 1;
1487 case BRIDGE_SPCA536:
1488 sd->colors = reg_r_12(gspca_dev, 0x00, 0x20f6, 2) >> 1;
1493 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1495 struct sd *sd = (struct sd *) gspca_dev;
1497 sd->brightness = val;
1498 if (gspca_dev->streaming)
1499 setbrightness(gspca_dev);
1503 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1505 struct sd *sd = (struct sd *) gspca_dev;
1507 getbrightness(gspca_dev);
1508 *val = sd->brightness;
1512 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1514 struct sd *sd = (struct sd *) gspca_dev;
1517 if (gspca_dev->streaming)
1518 setcontrast(gspca_dev);
1522 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1524 struct sd *sd = (struct sd *) gspca_dev;
1526 getcontrast(gspca_dev);
1527 *val = sd->contrast;
1531 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1533 struct sd *sd = (struct sd *) gspca_dev;
1536 if (gspca_dev->streaming)
1537 setcolors(gspca_dev);
1541 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1543 struct sd *sd = (struct sd *) gspca_dev;
1545 getcolors(gspca_dev);
1550 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1552 struct sd *sd = (struct sd *) gspca_dev;
1558 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1560 struct sd *sd = (struct sd *) gspca_dev;
1562 *val = sd->autogain;
1566 /* sub-driver description */
1567 static const struct sd_desc sd_desc = {
1568 .name = MODULE_NAME,
1570 .nctrls = ARRAY_SIZE(sd_ctrls),
1571 .config = sd_config,
1577 .pkt_scan = sd_pkt_scan,
1580 /* -- module initialisation -- */
1581 #define DVNM(name) .driver_info = (kernel_ulong_t) name
1582 static const __devinitdata struct usb_device_id device_table[] = {
1583 {USB_DEVICE(0x041e, 0x400b), DVNM("Creative PC-CAM 600")},
1584 {USB_DEVICE(0x041e, 0x4012), DVNM("PC-Cam350")},
1585 {USB_DEVICE(0x041e, 0x4013), DVNM("Creative Pccam750")},
1586 {USB_DEVICE(0x0458, 0x7006), DVNM("Genius Dsc 1.3 Smart")},
1587 {USB_DEVICE(0x0461, 0x0821), DVNM("Fujifilm MV-1")},
1588 {USB_DEVICE(0x046d, 0x0905), DVNM("Logitech ClickSmart 820")},
1589 {USB_DEVICE(0x046d, 0x0960), DVNM("Logitech ClickSmart 420")},
1590 {USB_DEVICE(0x0471, 0x0322), DVNM("Philips DMVC1300K")},
1591 {USB_DEVICE(0x04a5, 0x3003), DVNM("Benq DC 1300")},
1592 {USB_DEVICE(0x04a5, 0x3008), DVNM("Benq DC 1500")},
1593 {USB_DEVICE(0x04a5, 0x300a), DVNM("Benq DC3410")},
1594 {USB_DEVICE(0x04f1, 0x1001), DVNM("JVC GC A50")},
1595 {USB_DEVICE(0x04fc, 0x500c), DVNM("Sunplus CA500C")},
1596 {USB_DEVICE(0x04fc, 0x504a), DVNM("Aiptek Mini PenCam 1.3")},
1597 {USB_DEVICE(0x04fc, 0x504b), DVNM("Maxell MaxPocket LE 1.3")},
1598 {USB_DEVICE(0x04fc, 0x5330), DVNM("Digitrex 2110")},
1599 {USB_DEVICE(0x04fc, 0x5360), DVNM("Sunplus Generic")},
1600 {USB_DEVICE(0x04fc, 0xffff), DVNM("Pure DigitalDakota")},
1601 {USB_DEVICE(0x052b, 0x1513), DVNM("Megapix V4")},
1602 {USB_DEVICE(0x0546, 0x3155), DVNM("Polaroid PDC3070")},
1603 {USB_DEVICE(0x0546, 0x3191), DVNM("Polaroid Ion 80")},
1604 {USB_DEVICE(0x0546, 0x3273), DVNM("Polaroid PDC2030")},
1605 {USB_DEVICE(0x055f, 0xc211), DVNM("Kowa Bs888e Microcamera")},
1606 {USB_DEVICE(0x055f, 0xc230), DVNM("Mustek Digicam 330K")},
1607 {USB_DEVICE(0x055f, 0xc232), DVNM("Mustek MDC3500")},
1608 {USB_DEVICE(0x055f, 0xc360), DVNM("Mustek DV4000 Mpeg4 ")},
1609 {USB_DEVICE(0x055f, 0xc420), DVNM("Mustek gSmart Mini 2")},
1610 {USB_DEVICE(0x055f, 0xc430), DVNM("Mustek Gsmart LCD 2")},
1611 {USB_DEVICE(0x055f, 0xc440), DVNM("Mustek DV 3000")},
1612 {USB_DEVICE(0x055f, 0xc520), DVNM("Mustek gSmart Mini 3")},
1613 {USB_DEVICE(0x055f, 0xc530), DVNM("Mustek Gsmart LCD 3")},
1614 {USB_DEVICE(0x055f, 0xc540), DVNM("Gsmart D30")},
1615 {USB_DEVICE(0x055f, 0xc630), DVNM("Mustek MDC4000")},
1616 {USB_DEVICE(0x055f, 0xc650), DVNM("Mustek MDC5500Z")},
1617 {USB_DEVICE(0x05da, 0x1018), DVNM("Digital Dream Enigma 1.3")},
1618 {USB_DEVICE(0x06d6, 0x0031), DVNM("Trust 610 LCD PowerC@m Zoom")},
1619 {USB_DEVICE(0x0733, 0x1311), DVNM("Digital Dream Epsilon 1.3")},
1620 {USB_DEVICE(0x0733, 0x1314), DVNM("Mercury 2.1MEG Deluxe Classic Cam")},
1621 {USB_DEVICE(0x0733, 0x2211), DVNM("Jenoptik jdc 21 LCD")},
1622 {USB_DEVICE(0x0733, 0x2221), DVNM("Mercury Digital Pro 3.1p")},
1623 {USB_DEVICE(0x0733, 0x3261), DVNM("Concord 3045 spca536a")},
1624 {USB_DEVICE(0x0733, 0x3281), DVNM("Cyberpix S550V")},
1625 {USB_DEVICE(0x08ca, 0x0104), DVNM("Aiptek PocketDVII 1.3")},
1626 {USB_DEVICE(0x08ca, 0x0106), DVNM("Aiptek Pocket DV3100+")},
1627 {USB_DEVICE(0x08ca, 0x2008), DVNM("Aiptek Mini PenCam 2 M")},
1628 {USB_DEVICE(0x08ca, 0x2010), DVNM("Aiptek PocketCam 3M")},
1629 {USB_DEVICE(0x08ca, 0x2016), DVNM("Aiptek PocketCam 2 Mega")},
1630 {USB_DEVICE(0x08ca, 0x2018), DVNM("Aiptek Pencam SD 2M")},
1631 {USB_DEVICE(0x08ca, 0x2020), DVNM("Aiptek Slim 3000F")},
1632 {USB_DEVICE(0x08ca, 0x2022), DVNM("Aiptek Slim 3200")},
1633 {USB_DEVICE(0x08ca, 0x2024), DVNM("Aiptek DV3500 Mpeg4 ")},
1634 {USB_DEVICE(0x08ca, 0x2028), DVNM("Aiptek PocketCam4M")},
1635 {USB_DEVICE(0x08ca, 0x2040), DVNM("Aiptek PocketDV4100M")},
1636 {USB_DEVICE(0x08ca, 0x2042), DVNM("Aiptek PocketDV5100")},
1637 {USB_DEVICE(0x08ca, 0x2050), DVNM("Medion MD 41437")},
1638 {USB_DEVICE(0x08ca, 0x2060), DVNM("Aiptek PocketDV5300")},
1639 {USB_DEVICE(0x0d64, 0x0303), DVNM("Sunplus FashionCam DXG")},
1642 MODULE_DEVICE_TABLE(usb, device_table);
1644 /* -- device connect -- */
1645 static int sd_probe(struct usb_interface *intf,
1646 const struct usb_device_id *id)
1648 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1652 static struct usb_driver sd_driver = {
1653 .name = MODULE_NAME,
1654 .id_table = device_table,
1656 .disconnect = gspca_disconnect,
1659 /* -- module insert / remove -- */
1660 static int __init sd_mod_init(void)
1662 if (usb_register(&sd_driver) < 0)
1664 PDEBUG(D_PROBE, "registered");
1667 static void __exit sd_mod_exit(void)
1669 usb_deregister(&sd_driver);
1670 PDEBUG(D_PROBE, "deregistered");
1673 module_init(sd_mod_init);
1674 module_exit(sd_mod_exit);