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, 8)
28 static const char version[] = "2.1.8";
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 reg_r(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 reg_w(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 /* write req / index / value */
484 static int reg_w_riv(struct usb_device *dev,
485 __u16 req, __u16 index, __u16 value)
489 ret = usb_control_msg(dev,
490 usb_sndctrlpipe(dev, 0),
492 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
493 value, index, NULL, 0, 500);
494 PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d",
495 req, index, value, ret);
497 PDEBUG(D_ERR, "reg write: error %d", ret);
502 static int reg_r_1(struct gspca_dev *gspca_dev,
503 __u16 value) /* wValue */
507 ret = usb_control_msg(gspca_dev->dev,
508 usb_rcvctrlpipe(gspca_dev->dev, 0),
510 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
513 gspca_dev->usb_buf, 1,
516 PDEBUG(D_ERR, "reg_r_1 err %d", ret);
519 return gspca_dev->usb_buf[0];
522 /* read 1 or 2 bytes - returns < 0 if error */
523 static int reg_r_12(struct gspca_dev *gspca_dev,
524 __u16 req, /* bRequest */
525 __u16 index, /* wIndex */
526 __u16 length) /* wLength (1 or 2 only) */
530 gspca_dev->usb_buf[1] = 0;
531 ret = usb_control_msg(gspca_dev->dev,
532 usb_rcvctrlpipe(gspca_dev->dev, 0),
534 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
537 gspca_dev->usb_buf, length,
540 PDEBUG(D_ERR, "reg_read err %d", ret);
543 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_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_w_riv(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_w_riv(dev, request, ybase + i, qtable[0][i]);
581 /* loop over c components */
582 for (i = 0; i < 64; i++) {
583 err = reg_w_riv(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_w_riv(dev, req, idx, val);
597 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
598 reg_w_riv(dev, req, idx, val);
600 PDEBUG(D_FRAM, "before wait 0x%x", notdone);
603 notdone = reg_r_12(gspca_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_w_riv(dev, req, idx, val);
616 status = reg_r_12(gspca_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_w_riv(dev, req, idx, val); */
626 status = reg_r_12(gspca_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 gspca_dev *gspca_dev)
639 while (--count > 0) {
640 reg_r(gspca_dev->dev, 0x21, 0, gspca_dev->usb_buf, 1);
641 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
645 return gspca_dev->usb_buf[0];
648 static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
650 struct usb_device *dev = gspca_dev->dev;
653 while (--count > 0) {
654 reg_r(dev, 0x21, 1, gspca_dev->usb_buf, 1);
655 if (gspca_dev->usb_buf[0] != 0) {
656 gspca_dev->usb_buf[0] = 0;
657 reg_w(dev, 0x21, 0, 1, gspca_dev->usb_buf, 1);
658 reg_r(dev, 0x21, 1, gspca_dev->usb_buf, 1);
659 spca504B_PollingDataReady(gspca_dev);
666 static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
668 struct usb_device *dev = gspca_dev->dev;
671 data = kmalloc(64, GFP_KERNEL);
672 reg_r(dev, 0x20, 0, data, 5);
673 PDEBUG(D_STREAM, "FirmWare : %d %d %d %d %d ",
674 data[0], data[1], data[2], data[3], data[4]);
675 reg_r(dev, 0x23, 0, data, 64);
676 reg_r(dev, 0x23, 1, data, 64);
680 static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
682 struct sd *sd = (struct sd *) gspca_dev;
683 struct usb_device *dev = gspca_dev->dev;
688 Size = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
690 switch (sd->bridge) {
692 reg_w(dev, 0x31, 0, 0, NULL, 0);
693 spca504B_WaitCmdStatus(gspca_dev);
694 rc = spca504B_PollingDataReady(gspca_dev);
695 spca50x_GetFirmware(gspca_dev);
696 gspca_dev->usb_buf[0] = 2; /* type */
697 reg_w(dev, 0x24, 0, 8, gspca_dev->usb_buf, 1);
698 reg_r(dev, 0x24, 8, gspca_dev->usb_buf, 1);
700 gspca_dev->usb_buf[0] = Size;
701 reg_w(dev, 0x25, 0, 4, gspca_dev->usb_buf, 1);
702 reg_r(dev, 0x25, 4, gspca_dev->usb_buf, 1); /* size */
703 rc = spca504B_PollingDataReady(gspca_dev);
705 /* Init the cam width height with some values get on init ? */
706 reg_w(dev, 0x31, 0, 4, NULL, 0);
707 spca504B_WaitCmdStatus(gspca_dev);
708 rc = spca504B_PollingDataReady(gspca_dev);
711 /* case BRIDGE_SPCA504B: */
712 /* case BRIDGE_SPCA536: */
713 gspca_dev->usb_buf[0] = Size;
714 reg_w(dev, 0x25, 0, 4, gspca_dev->usb_buf, 1);
715 reg_r(dev, 0x25, 4, gspca_dev->usb_buf, 1); /* size */
717 gspca_dev->usb_buf[0] = Type;
718 reg_w(dev, 0x27, 0, 0, gspca_dev->usb_buf, 1);
719 reg_r(dev, 0x27, 0, gspca_dev->usb_buf, 1); /* type */
720 rc = spca504B_PollingDataReady(gspca_dev);
724 if (sd->subtype == AiptekMiniPenCam13) {
725 /* spca504a aiptek */
726 spca504A_acknowledged_command(gspca_dev,
728 0x80 | (Size & 0x0f), 1);
729 spca504A_acknowledged_command(gspca_dev,
732 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
735 case BRIDGE_SPCA504C:
737 reg_w_riv(dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
738 reg_w_riv(dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
743 static void spca504_wait_status(struct gspca_dev *gspca_dev)
749 /* With this we get the status, when return 0 it's all ok */
750 if (reg_r_12(gspca_dev, 0x06, 0x00, 1) == 0)
756 static void spca504B_setQtable(struct gspca_dev *gspca_dev)
758 struct usb_device *dev = gspca_dev->dev;
760 gspca_dev->usb_buf[0] = 3;
761 reg_w(dev, 0x26, 0, 0, gspca_dev->usb_buf, 1);
762 reg_r(dev, 0x26, 0, gspca_dev->usb_buf, 1);
763 spca504B_PollingDataReady(gspca_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 reg_w(dev, 0, 0, 0x21a7, NULL, 0); /* brightness */
781 reg_w(dev, 0, 0x20, 0x21a8, NULL, 0); /* contrast */
782 reg_w(dev, 0, 0, 0x21ad, NULL, 0); /* hue */
783 reg_w(dev, 0, 1, 0x21ac, NULL, 0); /* sat/hue */
784 reg_w(dev, 0, 0x20, 0x21ae, NULL, 0); /* saturation */
785 reg_w(dev, 0, 0, 0x21a3, NULL, 0); /* gamma */
788 reg_w(dev, 0, 0, 0x20f0, NULL, 0);
789 reg_w(dev, 0, 0x21, 0x20f1, NULL, 0);
790 reg_w(dev, 0, 0x40, 0x20f5, NULL, 0);
791 reg_w(dev, 0, 1, 0x20f4, NULL, 0);
792 reg_w(dev, 0, 0x40, 0x20f6, NULL, 0);
793 reg_w(dev, 0, 0, 0x2089, NULL, 0);
797 spca504B_PollingDataReady(gspca_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 0x0461: /* MicroInnovation */
831 /* switch (product) { */
833 sd->bridge = BRIDGE_SPCA533;
837 case 0x046d: /* Logitech Labtec */
840 sd->subtype = LogitechClickSmart820;
841 sd->bridge = BRIDGE_SPCA533;
844 sd->subtype = LogitechClickSmart420;
845 sd->bridge = BRIDGE_SPCA504C;
849 case 0x0471: /* Philips */
850 /* switch (product) { */
852 sd->bridge = BRIDGE_SPCA504B;
856 case 0x04a5: /* Benq */
859 sd->bridge = BRIDGE_SPCA504B;
863 sd->bridge = BRIDGE_SPCA533;
867 case 0x04f1: /* JVC */
868 /* switch (product) { */
870 sd->bridge = BRIDGE_SPCA504B;
874 case 0x04fc: /* SunPlus */
877 sd->bridge = BRIDGE_SPCA504B;
880 /* try to get the firmware as some cam answer 2.0.1.2.2
881 * and should be a spca504b then overwrite that setting */
882 reg_r(dev, 0x20, 0, gspca_dev->usb_buf, 1);
883 fw = gspca_dev->usb_buf[0];
885 sd->subtype = AiptekMiniPenCam13;
886 sd->bridge = BRIDGE_SPCA504;
887 } else if (fw == 2) {
888 sd->bridge = BRIDGE_SPCA504B;
893 sd->bridge = BRIDGE_SPCA504B;
896 sd->bridge = BRIDGE_SPCA533;
899 sd->bridge = BRIDGE_SPCA536;
902 sd->bridge = BRIDGE_SPCA504B;
906 case 0x052b: /* ?? Megapix */
907 /* switch (product) { */
909 sd->subtype = MegapixV4;
910 sd->bridge = BRIDGE_SPCA533;
914 case 0x0546: /* Polaroid */
917 sd->bridge = BRIDGE_SPCA533;
921 sd->bridge = BRIDGE_SPCA504B;
925 case 0x055f: /* Mustek cameras */
928 sd->bridge = BRIDGE_SPCA536;
932 sd->bridge = BRIDGE_SPCA533;
935 sd->bridge = BRIDGE_SPCA536;
938 sd->bridge = BRIDGE_SPCA504;
942 sd->bridge = BRIDGE_SPCA533;
945 sd->bridge = BRIDGE_SPCA504;
951 sd->bridge = BRIDGE_SPCA533;
955 case 0x05da: /* Digital Dream cameras */
956 /* switch (product) { */
958 sd->bridge = BRIDGE_SPCA504B;
962 case 0x06d6: /* Trust */
963 /* switch (product) { */
965 sd->bridge = BRIDGE_SPCA533; /* SPCA533A */
969 case 0x0733: /* Rebadged ViewQuest (Intel) and ViewQuest cameras */
975 sd->bridge = BRIDGE_SPCA533;
979 sd->bridge = BRIDGE_SPCA536;
983 case 0x08ca: /* Aiptek */
987 sd->bridge = BRIDGE_SPCA533;
990 sd->bridge = BRIDGE_SPCA504B;
993 sd->bridge = BRIDGE_SPCA533;
997 sd->bridge = BRIDGE_SPCA504B;
1001 sd->bridge = BRIDGE_SPCA533;
1004 sd->bridge = BRIDGE_SPCA536;
1007 sd->bridge = BRIDGE_SPCA533;
1012 sd->bridge = BRIDGE_SPCA536;
1016 case 0x0d64: /* SunPlus */
1017 /* switch (product) { */
1019 sd->bridge = BRIDGE_SPCA536;
1025 cam = &gspca_dev->cam;
1026 cam->dev_name = (char *) id->driver_info;
1029 switch (sd->bridge) {
1031 /* case BRIDGE_SPCA504B: */
1032 /* case BRIDGE_SPCA504: */
1033 /* case BRIDGE_SPCA536: */
1034 cam->cam_mode = vga_mode;
1035 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
1037 case BRIDGE_SPCA533:
1038 cam->cam_mode = custom_mode;
1039 cam->nmodes = sizeof custom_mode / sizeof custom_mode[0];
1041 case BRIDGE_SPCA504C:
1042 cam->cam_mode = vga_mode2;
1043 cam->nmodes = sizeof vga_mode2 / sizeof vga_mode2[0];
1046 sd->qindex = 5; /* set the quantization table */
1047 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
1048 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
1049 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
1053 /* this function is called at open time */
1054 static int sd_open(struct gspca_dev *gspca_dev)
1056 struct sd *sd = (struct sd *) gspca_dev;
1057 struct usb_device *dev = gspca_dev->dev;
1063 switch (sd->bridge) {
1064 case BRIDGE_SPCA504B:
1065 reg_w(dev, 0x1d, 0, 0, NULL, 0);
1066 reg_w(dev, 0, 1, 0x2306, NULL, 0);
1067 reg_w(dev, 0, 0, 0x0d04, NULL, 0);
1068 reg_w(dev, 0, 0, 0x2000, NULL, 0);
1069 reg_w(dev, 0, 0x13, 0x2301, NULL, 0);
1070 reg_w(dev, 0, 0, 0x2306, NULL, 0);
1072 case BRIDGE_SPCA533:
1073 rc = spca504B_PollingDataReady(gspca_dev);
1074 spca50x_GetFirmware(gspca_dev);
1076 case BRIDGE_SPCA536:
1077 spca50x_GetFirmware(gspca_dev);
1078 reg_r(dev, 0x00, 0x5002, gspca_dev->usb_buf, 1);
1079 gspca_dev->usb_buf[0] = 0;
1080 reg_w(dev, 0x24, 0, 0, gspca_dev->usb_buf, 1);
1081 reg_r(dev, 0x24, 0, gspca_dev->usb_buf, 1);
1082 rc = spca504B_PollingDataReady(gspca_dev);
1083 reg_w(dev, 0x34, 0, 0, NULL, 0);
1084 spca504B_WaitCmdStatus(gspca_dev);
1086 case BRIDGE_SPCA504C: /* pccam600 */
1087 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
1088 reg_w_riv(dev, 0xe0, 0x0000, 0x0000);
1089 reg_w_riv(dev, 0xe0, 0x0000, 0x0001); /* reset */
1090 spca504_wait_status(gspca_dev);
1091 if (sd->subtype == LogitechClickSmart420)
1092 write_vector(gspca_dev,
1093 spca504A_clicksmart420_open_data);
1095 write_vector(gspca_dev, spca504_pccam600_open_data);
1096 err_code = spca50x_setup_qtable(gspca_dev,
1098 0x2840, qtable_creative_pccam);
1100 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed");
1105 /* case BRIDGE_SPCA504: */
1106 PDEBUG(D_STREAM, "Opening SPCA504");
1107 if (sd->subtype == AiptekMiniPenCam13) {
1108 /*****************************/
1109 for (i = 0; i < 6; i++)
1110 info[i] = reg_r_1(gspca_dev, i);
1112 "Read info: %d %d %d %d %d %d."
1113 " Should be 1,0,2,2,0,0",
1114 info[0], info[1], info[2],
1115 info[3], info[4], info[5]);
1116 /* spca504a aiptek */
1117 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1118 spca504A_acknowledged_command(gspca_dev, 0x24,
1120 /* Twice sequencial need status 0xff->0x9e->0x9d */
1121 spca504A_acknowledged_command(gspca_dev, 0x24,
1124 spca504A_acknowledged_command(gspca_dev, 0x24,
1126 /******************************/
1127 /* spca504a aiptek */
1128 spca504A_acknowledged_command(gspca_dev, 0x08,
1130 /* reg_write (dev, 0, 0x2000, 0); */
1131 /* reg_write (dev, 0, 0x2883, 1); */
1132 /* spca504A_acknowledged_command (gspca_dev, 0x08,
1134 /* spca504A_acknowledged_command (gspca_dev, 0x24,
1136 reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */
1137 reg_w_riv(dev, 0x0, 0x2310, 0x05);
1138 spca504A_acknowledged_command(gspca_dev, 0x01,
1142 reg_w_riv(dev, 0, 0x2000, 0);
1143 reg_w_riv(dev, 0, 0x2883, 1);
1144 err_code = spca50x_setup_qtable(gspca_dev,
1147 qtable_spca504_default);
1149 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
1157 static void sd_start(struct gspca_dev *gspca_dev)
1159 struct sd *sd = (struct sd *) gspca_dev;
1160 struct usb_device *dev = gspca_dev->dev;
1166 if (sd->bridge == BRIDGE_SPCA504B)
1167 spca504B_setQtable(gspca_dev);
1168 spca504B_SetSizeType(gspca_dev);
1169 switch (sd->bridge) {
1171 /* case BRIDGE_SPCA504B: */
1172 /* case BRIDGE_SPCA533: */
1173 /* case BRIDGE_SPCA536: */
1174 if (sd->subtype == MegapixV4 ||
1175 sd->subtype == LogitechClickSmart820) {
1176 reg_w(dev, 0xf0, 0, 0, NULL, 0);
1177 spca504B_WaitCmdStatus(gspca_dev);
1178 reg_r(dev, 0xf0, 4, NULL, 0);
1179 spca504B_WaitCmdStatus(gspca_dev);
1181 reg_w(dev, 0x31, 0, 4, NULL, 0);
1182 spca504B_WaitCmdStatus(gspca_dev);
1183 rc = spca504B_PollingDataReady(gspca_dev);
1186 case BRIDGE_SPCA504:
1187 if (sd->subtype == AiptekMiniPenCam13) {
1188 for (i = 0; i < 6; i++)
1189 info[i] = reg_r_1(gspca_dev, i);
1191 "Read info: %d %d %d %d %d %d."
1192 " Should be 1,0,2,2,0,0",
1193 info[0], info[1], info[2],
1194 info[3], info[4], info[5]);
1195 /* spca504a aiptek */
1196 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1197 spca504A_acknowledged_command(gspca_dev, 0x24,
1199 /* Twice sequencial need status 0xff->0x9e->0x9d */
1200 spca504A_acknowledged_command(gspca_dev, 0x24,
1202 spca504A_acknowledged_command(gspca_dev, 0x24,
1205 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1206 for (i = 0; i < 6; i++)
1207 info[i] = reg_r_1(gspca_dev, i);
1209 "Read info: %d %d %d %d %d %d."
1210 " Should be 1,0,2,2,0,0",
1211 info[0], info[1], info[2],
1212 info[3], info[4], info[5]);
1213 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1214 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1216 spca504B_SetSizeType(gspca_dev);
1217 reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */
1218 reg_w_riv(dev, 0x0, 0x2310, 0x05);
1220 case BRIDGE_SPCA504C:
1221 if (sd->subtype == LogitechClickSmart420) {
1222 write_vector(gspca_dev,
1223 spca504A_clicksmart420_init_data);
1225 write_vector(gspca_dev, spca504_pccam600_init_data);
1227 enable = (sd->autogain ? 0x04 : 0x01);
1228 reg_w_riv(dev, 0x0c, 0x0000, enable); /* auto exposure */
1229 reg_w_riv(dev, 0xb0, 0x0000, enable); /* auto whiteness */
1231 /* set default exposure compensation and whiteness balance */
1232 reg_w_riv(dev, 0x30, 0x0001, 800); /* ~ 20 fps */
1233 reg_w_riv(dev, 0x30, 0x0002, 1600);
1234 spca504B_SetSizeType(gspca_dev);
1237 sp5xx_initContBrigHueRegisters(gspca_dev);
1240 static void sd_stopN(struct gspca_dev *gspca_dev)
1242 struct sd *sd = (struct sd *) gspca_dev;
1243 struct usb_device *dev = gspca_dev->dev;
1245 switch (sd->bridge) {
1247 /* case BRIDGE_SPCA533: */
1248 /* case BRIDGE_SPCA536: */
1249 /* case BRIDGE_SPCA504B: */
1250 reg_w(dev, 0x31, 0, 0, NULL, 0);
1251 spca504B_WaitCmdStatus(gspca_dev);
1252 spca504B_PollingDataReady(gspca_dev);
1254 case BRIDGE_SPCA504:
1255 case BRIDGE_SPCA504C:
1256 reg_w_riv(dev, 0x00, 0x2000, 0x0000);
1258 if (sd->subtype == AiptekMiniPenCam13) {
1259 /* spca504a aiptek */
1260 /* spca504A_acknowledged_command(gspca_dev, 0x08,
1262 spca504A_acknowledged_command(gspca_dev, 0x24,
1263 0x00, 0x00, 0x9d, 1);
1264 spca504A_acknowledged_command(gspca_dev, 0x01,
1265 0x0f, 0x00, 0xff, 1);
1267 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1268 reg_w_riv(dev, 0x01, 0x000f, 0x00);
1274 static void sd_stop0(struct gspca_dev *gspca_dev)
1278 static void sd_close(struct gspca_dev *gspca_dev)
1282 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1283 struct gspca_frame *frame, /* target */
1284 __u8 *data, /* isoc packet */
1285 int len) /* iso packet length */
1287 struct sd *sd = (struct sd *) gspca_dev;
1289 unsigned char *s, *d;
1290 static unsigned char ffd9[] = {0xff, 0xd9};
1292 /* frames are jpeg 4.1.1 without 0xff escape */
1293 switch (sd->bridge) {
1294 case BRIDGE_SPCA533:
1295 if (data[0] == 0xff) {
1296 if (data[1] != 0x01) { /* drop packet */
1297 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1301 data += SPCA533_OFFSET_DATA;
1302 len -= SPCA533_OFFSET_DATA;
1308 case BRIDGE_SPCA536:
1309 if (data[0] == 0xff) {
1311 data += SPCA536_OFFSET_DATA;
1312 len -= SPCA536_OFFSET_DATA;
1319 /* case BRIDGE_SPCA504: */
1320 /* case BRIDGE_SPCA504B: */
1322 case 0xfe: /* start of frame */
1324 data += SPCA50X_OFFSET_DATA;
1325 len -= SPCA50X_OFFSET_DATA;
1327 case 0xff: /* drop packet */
1328 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1336 case BRIDGE_SPCA504C:
1338 case 0xfe: /* start of frame */
1340 data += SPCA504_PCCAM600_OFFSET_DATA;
1341 len -= SPCA504_PCCAM600_OFFSET_DATA;
1343 case 0xff: /* drop packet */
1344 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
1353 if (sof) { /* start of frame */
1354 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1357 /* put the JPEG header in the new frame */
1358 jpeg_put_header(gspca_dev, frame,
1359 ((struct sd *) gspca_dev)->qindex,
1363 /* add 0x00 after 0xff */
1364 for (i = len; --i >= 0; )
1365 if (data[i] == 0xff)
1367 if (i < 0) { /* no 0xff */
1368 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1373 for (i = 0; i < len; i++) {
1378 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1379 sd->packet, d - sd->packet);
1382 static void setbrightness(struct gspca_dev *gspca_dev)
1384 struct sd *sd = (struct sd *) gspca_dev;
1385 struct usb_device *dev = gspca_dev->dev;
1387 switch (sd->bridge) {
1389 /* case BRIDGE_SPCA533: */
1390 /* case BRIDGE_SPCA504B: */
1391 /* case BRIDGE_SPCA504: */
1392 /* case BRIDGE_SPCA504C: */
1393 reg_w_riv(dev, 0x0, 0x21a7, sd->brightness);
1395 case BRIDGE_SPCA536:
1396 reg_w_riv(dev, 0x0, 0x20f0, sd->brightness);
1401 static void getbrightness(struct gspca_dev *gspca_dev)
1403 struct sd *sd = (struct sd *) gspca_dev;
1404 __u16 brightness = 0;
1406 switch (sd->bridge) {
1408 /* case BRIDGE_SPCA533: */
1409 /* case BRIDGE_SPCA504B: */
1410 /* case BRIDGE_SPCA504: */
1411 /* case BRIDGE_SPCA504C: */
1412 brightness = reg_r_12(gspca_dev, 0x00, 0x21a7, 2);
1414 case BRIDGE_SPCA536:
1415 brightness = reg_r_12(gspca_dev, 0x00, 0x20f0, 2);
1418 sd->brightness = ((brightness & 0xff) - 128) % 255;
1421 static void setcontrast(struct gspca_dev *gspca_dev)
1423 struct sd *sd = (struct sd *) gspca_dev;
1424 struct usb_device *dev = gspca_dev->dev;
1426 switch (sd->bridge) {
1428 /* case BRIDGE_SPCA533: */
1429 /* case BRIDGE_SPCA504B: */
1430 /* case BRIDGE_SPCA504: */
1431 /* case BRIDGE_SPCA504C: */
1432 reg_w_riv(dev, 0x0, 0x21a8, sd->contrast);
1434 case BRIDGE_SPCA536:
1435 reg_w_riv(dev, 0x0, 0x20f1, sd->contrast);
1440 static void getcontrast(struct gspca_dev *gspca_dev)
1442 struct sd *sd = (struct sd *) gspca_dev;
1444 switch (sd->bridge) {
1446 /* case BRIDGE_SPCA533: */
1447 /* case BRIDGE_SPCA504B: */
1448 /* case BRIDGE_SPCA504: */
1449 /* case BRIDGE_SPCA504C: */
1450 sd->contrast = reg_r_12(gspca_dev, 0x00, 0x21a8, 2);
1452 case BRIDGE_SPCA536:
1453 sd->contrast = reg_r_12(gspca_dev, 0x00, 0x20f1, 2);
1458 static void setcolors(struct gspca_dev *gspca_dev)
1460 struct sd *sd = (struct sd *) gspca_dev;
1461 struct usb_device *dev = gspca_dev->dev;
1463 switch (sd->bridge) {
1465 /* case BRIDGE_SPCA533: */
1466 /* case BRIDGE_SPCA504B: */
1467 /* case BRIDGE_SPCA504: */
1468 /* case BRIDGE_SPCA504C: */
1469 reg_w_riv(dev, 0x0, 0x21ae, sd->colors);
1471 case BRIDGE_SPCA536:
1472 reg_w_riv(dev, 0x0, 0x20f6, sd->colors);
1477 static void getcolors(struct gspca_dev *gspca_dev)
1479 struct sd *sd = (struct sd *) gspca_dev;
1481 switch (sd->bridge) {
1483 /* case BRIDGE_SPCA533: */
1484 /* case BRIDGE_SPCA504B: */
1485 /* case BRIDGE_SPCA504: */
1486 /* case BRIDGE_SPCA504C: */
1487 sd->colors = reg_r_12(gspca_dev, 0x00, 0x21ae, 2) >> 1;
1489 case BRIDGE_SPCA536:
1490 sd->colors = reg_r_12(gspca_dev, 0x00, 0x20f6, 2) >> 1;
1495 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1497 struct sd *sd = (struct sd *) gspca_dev;
1499 sd->brightness = val;
1500 if (gspca_dev->streaming)
1501 setbrightness(gspca_dev);
1505 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1507 struct sd *sd = (struct sd *) gspca_dev;
1509 getbrightness(gspca_dev);
1510 *val = sd->brightness;
1514 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1516 struct sd *sd = (struct sd *) gspca_dev;
1519 if (gspca_dev->streaming)
1520 setcontrast(gspca_dev);
1524 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1526 struct sd *sd = (struct sd *) gspca_dev;
1528 getcontrast(gspca_dev);
1529 *val = sd->contrast;
1533 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1535 struct sd *sd = (struct sd *) gspca_dev;
1538 if (gspca_dev->streaming)
1539 setcolors(gspca_dev);
1543 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1545 struct sd *sd = (struct sd *) gspca_dev;
1547 getcolors(gspca_dev);
1552 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1554 struct sd *sd = (struct sd *) gspca_dev;
1560 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1562 struct sd *sd = (struct sd *) gspca_dev;
1564 *val = sd->autogain;
1568 /* sub-driver description */
1569 static const struct sd_desc sd_desc = {
1570 .name = MODULE_NAME,
1572 .nctrls = ARRAY_SIZE(sd_ctrls),
1573 .config = sd_config,
1579 .pkt_scan = sd_pkt_scan,
1582 /* -- module initialisation -- */
1583 #define DVNM(name) .driver_info = (kernel_ulong_t) name
1584 static const __devinitdata struct usb_device_id device_table[] = {
1585 {USB_DEVICE(0x041e, 0x400b), DVNM("Creative PC-CAM 600")},
1586 {USB_DEVICE(0x041e, 0x4012), DVNM("PC-Cam350")},
1587 {USB_DEVICE(0x041e, 0x4013), DVNM("Creative Pccam750")},
1588 {USB_DEVICE(0x0458, 0x7006), DVNM("Genius Dsc 1.3 Smart")},
1589 {USB_DEVICE(0x0461, 0x0821), DVNM("Fujifilm MV-1")},
1590 {USB_DEVICE(0x046d, 0x0905), DVNM("Logitech ClickSmart 820")},
1591 {USB_DEVICE(0x046d, 0x0960), DVNM("Logitech ClickSmart 420")},
1592 {USB_DEVICE(0x0471, 0x0322), DVNM("Philips DMVC1300K")},
1593 {USB_DEVICE(0x04a5, 0x3003), DVNM("Benq DC 1300")},
1594 {USB_DEVICE(0x04a5, 0x3008), DVNM("Benq DC 1500")},
1595 {USB_DEVICE(0x04a5, 0x300a), DVNM("Benq DC3410")},
1596 {USB_DEVICE(0x04f1, 0x1001), DVNM("JVC GC A50")},
1597 {USB_DEVICE(0x04fc, 0x500c), DVNM("Sunplus CA500C")},
1598 {USB_DEVICE(0x04fc, 0x504a), DVNM("Aiptek Mini PenCam 1.3")},
1599 {USB_DEVICE(0x04fc, 0x504b), DVNM("Maxell MaxPocket LE 1.3")},
1600 {USB_DEVICE(0x04fc, 0x5330), DVNM("Digitrex 2110")},
1601 {USB_DEVICE(0x04fc, 0x5360), DVNM("Sunplus Generic")},
1602 {USB_DEVICE(0x04fc, 0xffff), DVNM("Pure DigitalDakota")},
1603 {USB_DEVICE(0x052b, 0x1513), DVNM("Megapix V4")},
1604 {USB_DEVICE(0x0546, 0x3155), DVNM("Polaroid PDC3070")},
1605 {USB_DEVICE(0x0546, 0x3191), DVNM("Polaroid Ion 80")},
1606 {USB_DEVICE(0x0546, 0x3273), DVNM("Polaroid PDC2030")},
1607 {USB_DEVICE(0x055f, 0xc211), DVNM("Kowa Bs888e Microcamera")},
1608 {USB_DEVICE(0x055f, 0xc230), DVNM("Mustek Digicam 330K")},
1609 {USB_DEVICE(0x055f, 0xc232), DVNM("Mustek MDC3500")},
1610 {USB_DEVICE(0x055f, 0xc360), DVNM("Mustek DV4000 Mpeg4 ")},
1611 {USB_DEVICE(0x055f, 0xc420), DVNM("Mustek gSmart Mini 2")},
1612 {USB_DEVICE(0x055f, 0xc430), DVNM("Mustek Gsmart LCD 2")},
1613 {USB_DEVICE(0x055f, 0xc440), DVNM("Mustek DV 3000")},
1614 {USB_DEVICE(0x055f, 0xc520), DVNM("Mustek gSmart Mini 3")},
1615 {USB_DEVICE(0x055f, 0xc530), DVNM("Mustek Gsmart LCD 3")},
1616 {USB_DEVICE(0x055f, 0xc540), DVNM("Gsmart D30")},
1617 {USB_DEVICE(0x055f, 0xc630), DVNM("Mustek MDC4000")},
1618 {USB_DEVICE(0x055f, 0xc650), DVNM("Mustek MDC5500Z")},
1619 {USB_DEVICE(0x05da, 0x1018), DVNM("Digital Dream Enigma 1.3")},
1620 {USB_DEVICE(0x06d6, 0x0031), DVNM("Trust 610 LCD PowerC@m Zoom")},
1621 {USB_DEVICE(0x0733, 0x1311), DVNM("Digital Dream Epsilon 1.3")},
1622 {USB_DEVICE(0x0733, 0x1314), DVNM("Mercury 2.1MEG Deluxe Classic Cam")},
1623 {USB_DEVICE(0x0733, 0x2211), DVNM("Jenoptik jdc 21 LCD")},
1624 {USB_DEVICE(0x0733, 0x2221), DVNM("Mercury Digital Pro 3.1p")},
1625 {USB_DEVICE(0x0733, 0x3261), DVNM("Concord 3045 spca536a")},
1626 {USB_DEVICE(0x0733, 0x3281), DVNM("Cyberpix S550V")},
1627 {USB_DEVICE(0x08ca, 0x0104), DVNM("Aiptek PocketDVII 1.3")},
1628 {USB_DEVICE(0x08ca, 0x0106), DVNM("Aiptek Pocket DV3100+")},
1629 {USB_DEVICE(0x08ca, 0x2008), DVNM("Aiptek Mini PenCam 2 M")},
1630 {USB_DEVICE(0x08ca, 0x2010), DVNM("Aiptek PocketCam 3M")},
1631 {USB_DEVICE(0x08ca, 0x2016), DVNM("Aiptek PocketCam 2 Mega")},
1632 {USB_DEVICE(0x08ca, 0x2018), DVNM("Aiptek Pencam SD 2M")},
1633 {USB_DEVICE(0x08ca, 0x2020), DVNM("Aiptek Slim 3000F")},
1634 {USB_DEVICE(0x08ca, 0x2022), DVNM("Aiptek Slim 3200")},
1635 {USB_DEVICE(0x08ca, 0x2024), DVNM("Aiptek DV3500 Mpeg4 ")},
1636 {USB_DEVICE(0x08ca, 0x2028), DVNM("Aiptek PocketCam4M")},
1637 {USB_DEVICE(0x08ca, 0x2040), DVNM("Aiptek PocketDV4100M")},
1638 {USB_DEVICE(0x08ca, 0x2042), DVNM("Aiptek PocketDV5100")},
1639 {USB_DEVICE(0x08ca, 0x2060), DVNM("Aiptek PocketDV5300")},
1640 {USB_DEVICE(0x0d64, 0x0303), DVNM("Sunplus FashionCam DXG")},
1643 MODULE_DEVICE_TABLE(usb, device_table);
1645 /* -- device connect -- */
1646 static int sd_probe(struct usb_interface *intf,
1647 const struct usb_device_id *id)
1649 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1653 static struct usb_driver sd_driver = {
1654 .name = MODULE_NAME,
1655 .id_table = device_table,
1657 .disconnect = gspca_disconnect,
1660 /* -- module insert / remove -- */
1661 static int __init sd_mod_init(void)
1663 if (usb_register(&sd_driver) < 0)
1665 PDEBUG(D_PROBE, "v%s registered", version);
1668 static void __exit sd_mod_exit(void)
1670 usb_deregister(&sd_driver);
1671 PDEBUG(D_PROBE, "deregistered");
1674 module_init(sd_mod_init);
1675 module_exit(sd_mod_exit);