1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23
24#define MODULE_NAME "sunplus"
25
26#include "gspca.h"
27#include "jpeg.h"
28
29MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
30MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
31MODULE_LICENSE("GPL");
32
33
34struct sd {
35 struct gspca_dev gspca_dev;
36
37 s8 brightness;
38 u8 contrast;
39 u8 colors;
40 u8 autogain;
41 u8 quality;
42#define QUALITY_MIN 70
43#define QUALITY_MAX 95
44#define QUALITY_DEF 85
45
46 u8 bridge;
47#define BRIDGE_SPCA504 0
48#define BRIDGE_SPCA504B 1
49#define BRIDGE_SPCA504C 2
50#define BRIDGE_SPCA533 3
51#define BRIDGE_SPCA536 4
52 u8 subtype;
53#define AiptekMiniPenCam13 1
54#define LogitechClickSmart420 2
55#define LogitechClickSmart820 3
56#define MegapixV4 4
57#define MegaImageVI 5
58
59 u8 jpeg_hdr[JPEG_HDR_SZ];
60};
61
62
63static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
64static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
65static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
66static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
67static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
69static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
70static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
71
72static const struct ctrl sd_ctrls[] = {
73 {
74 {
75 .id = V4L2_CID_BRIGHTNESS,
76 .type = V4L2_CTRL_TYPE_INTEGER,
77 .name = "Brightness",
78 .minimum = -128,
79 .maximum = 127,
80 .step = 1,
81#define BRIGHTNESS_DEF 0
82 .default_value = BRIGHTNESS_DEF,
83 },
84 .set = sd_setbrightness,
85 .get = sd_getbrightness,
86 },
87 {
88 {
89 .id = V4L2_CID_CONTRAST,
90 .type = V4L2_CTRL_TYPE_INTEGER,
91 .name = "Contrast",
92 .minimum = 0,
93 .maximum = 0xff,
94 .step = 1,
95#define CONTRAST_DEF 0x20
96 .default_value = CONTRAST_DEF,
97 },
98 .set = sd_setcontrast,
99 .get = sd_getcontrast,
100 },
101 {
102 {
103 .id = V4L2_CID_SATURATION,
104 .type = V4L2_CTRL_TYPE_INTEGER,
105 .name = "Color",
106 .minimum = 0,
107 .maximum = 0xff,
108 .step = 1,
109#define COLOR_DEF 0x1a
110 .default_value = COLOR_DEF,
111 },
112 .set = sd_setcolors,
113 .get = sd_getcolors,
114 },
115 {
116 {
117 .id = V4L2_CID_AUTOGAIN,
118 .type = V4L2_CTRL_TYPE_BOOLEAN,
119 .name = "Auto Gain",
120 .minimum = 0,
121 .maximum = 1,
122 .step = 1,
123#define AUTOGAIN_DEF 1
124 .default_value = AUTOGAIN_DEF,
125 },
126 .set = sd_setautogain,
127 .get = sd_getautogain,
128 },
129};
130
131static const struct v4l2_pix_format vga_mode[] = {
132 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
133 .bytesperline = 320,
134 .sizeimage = 320 * 240 * 3 / 8 + 590,
135 .colorspace = V4L2_COLORSPACE_JPEG,
136 .priv = 2},
137 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
138 .bytesperline = 640,
139 .sizeimage = 640 * 480 * 3 / 8 + 590,
140 .colorspace = V4L2_COLORSPACE_JPEG,
141 .priv = 1},
142};
143
144static const struct v4l2_pix_format custom_mode[] = {
145 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
146 .bytesperline = 320,
147 .sizeimage = 320 * 240 * 3 / 8 + 590,
148 .colorspace = V4L2_COLORSPACE_JPEG,
149 .priv = 2},
150 {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
151 .bytesperline = 464,
152 .sizeimage = 464 * 480 * 3 / 8 + 590,
153 .colorspace = V4L2_COLORSPACE_JPEG,
154 .priv = 1},
155};
156
157static const struct v4l2_pix_format vga_mode2[] = {
158 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
159 .bytesperline = 176,
160 .sizeimage = 176 * 144 * 3 / 8 + 590,
161 .colorspace = V4L2_COLORSPACE_JPEG,
162 .priv = 4},
163 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
164 .bytesperline = 320,
165 .sizeimage = 320 * 240 * 3 / 8 + 590,
166 .colorspace = V4L2_COLORSPACE_JPEG,
167 .priv = 3},
168 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
169 .bytesperline = 352,
170 .sizeimage = 352 * 288 * 3 / 8 + 590,
171 .colorspace = V4L2_COLORSPACE_JPEG,
172 .priv = 2},
173 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
174 .bytesperline = 640,
175 .sizeimage = 640 * 480 * 3 / 8 + 590,
176 .colorspace = V4L2_COLORSPACE_JPEG,
177 .priv = 1},
178};
179
180#define SPCA50X_OFFSET_DATA 10
181#define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
182#define SPCA504_PCCAM600_OFFSET_COMPRESS 4
183#define SPCA504_PCCAM600_OFFSET_MODE 5
184#define SPCA504_PCCAM600_OFFSET_DATA 14
185
186#define SPCA533_OFFSET_DATA 16
187#define SPCA533_OFFSET_FRAMSEQ 15
188
189#define SPCA536_OFFSET_DATA 4
190#define SPCA536_OFFSET_FRAMSEQ 1
191
192struct cmd {
193 u8 req;
194 u16 val;
195 u16 idx;
196};
197
198
199static const struct cmd spca504_pccam600_init_data[] = {
200
201 {0x00, 0x0000, 0x2000},
202 {0x00, 0x0013, 0x2301},
203 {0x00, 0x0003, 0x2000},
204 {0x00, 0x0001, 0x21ac},
205 {0x00, 0x0001, 0x21a6},
206 {0x00, 0x0000, 0x21a7},
207 {0x00, 0x0020, 0x21a8},
208 {0x00, 0x0001, 0x21ac},
209 {0x00, 0x0000, 0x21ad},
210 {0x00, 0x001a, 0x21ae},
211 {0x00, 0x0002, 0x21a3},
212 {0x30, 0x0154, 0x0008},
213 {0x30, 0x0004, 0x0006},
214 {0x30, 0x0258, 0x0009},
215 {0x30, 0x0004, 0x0000},
216 {0x30, 0x0093, 0x0004},
217 {0x30, 0x0066, 0x0005},
218 {0x00, 0x0000, 0x2000},
219 {0x00, 0x0013, 0x2301},
220 {0x00, 0x0003, 0x2000},
221 {0x00, 0x0013, 0x2301},
222 {0x00, 0x0003, 0x2000},
223};
224
225
226
227
228static const struct cmd spca504_pccam600_open_data[] = {
229 {0x00, 0x0001, 0x2501},
230 {0x20, 0x0500, 0x0001},
231 {0x00, 0x0003, 0x2880},
232 {0x00, 0x0001, 0x2881},
233};
234
235
236static const struct cmd spca504A_clicksmart420_init_data[] = {
237
238 {0x00, 0x0000, 0x2000},
239 {0x00, 0x0013, 0x2301},
240 {0x00, 0x0003, 0x2000},
241 {0x00, 0x0001, 0x21ac},
242 {0x00, 0x0001, 0x21a6},
243 {0x00, 0x0000, 0x21a7},
244 {0x00, 0x0020, 0x21a8},
245 {0x00, 0x0001, 0x21ac},
246 {0x00, 0x0000, 0x21ad},
247 {0x00, 0x001a, 0x21ae},
248 {0x00, 0x0002, 0x21a3},
249 {0x30, 0x0004, 0x000a},
250 {0xb0, 0x0001, 0x0000},
251
252 {0xa1, 0x0080, 0x0001},
253 {0x30, 0x0049, 0x0000},
254 {0x30, 0x0060, 0x0005},
255 {0x0c, 0x0004, 0x0000},
256 {0x00, 0x0000, 0x0000},
257 {0x00, 0x0000, 0x2000},
258 {0x00, 0x0013, 0x2301},
259 {0x00, 0x0003, 0x2000},
260};
261
262
263static const struct cmd spca504A_clicksmart420_open_data[] = {
264 {0x00, 0x0001, 0x2501},
265 {0x20, 0x0502, 0x0000},
266 {0x06, 0x0000, 0x0000},
267 {0x00, 0x0004, 0x2880},
268 {0x00, 0x0001, 0x2881},
269
270 {0xa0, 0x0000, 0x0503},
271};
272
273static const u8 qtable_creative_pccam[2][64] = {
274 {
275 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
276 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
277 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
278 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
279 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
280 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
281 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
282 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
283 {
284 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
285 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
286 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
287 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
288 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
289 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
290 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
291 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
292};
293
294
295
296
297
298static const u8 qtable_spca504_default[2][64] = {
299 {
300 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
301 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
302 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
303 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
304 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
305 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
306 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
307 0x16, 0x1c, 0x1d, 0x1d, 0x1d , 0x1e, 0x1f, 0x1e,
308 },
309 {
310 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
311 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
312 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
313 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
314 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
315 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
316 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
317 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
318};
319
320
321static void reg_r(struct gspca_dev *gspca_dev,
322 u8 req,
323 u16 index,
324 u16 len)
325{
326 int ret;
327
328#ifdef GSPCA_DEBUG
329 if (len > USB_BUF_SZ) {
330 pr_err("reg_r: buffer overflow\n");
331 return;
332 }
333#endif
334 if (gspca_dev->usb_err < 0)
335 return;
336 ret = usb_control_msg(gspca_dev->dev,
337 usb_rcvctrlpipe(gspca_dev->dev, 0),
338 req,
339 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
340 0,
341 index,
342 len ? gspca_dev->usb_buf : NULL, len,
343 500);
344 if (ret < 0) {
345 pr_err("reg_r err %d\n", ret);
346 gspca_dev->usb_err = ret;
347 }
348}
349
350
351static void reg_w_1(struct gspca_dev *gspca_dev,
352 u8 req,
353 u16 value,
354 u16 index,
355 u16 byte)
356{
357 int ret;
358
359 if (gspca_dev->usb_err < 0)
360 return;
361 gspca_dev->usb_buf[0] = byte;
362 ret = usb_control_msg(gspca_dev->dev,
363 usb_sndctrlpipe(gspca_dev->dev, 0),
364 req,
365 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
366 value, index,
367 gspca_dev->usb_buf, 1,
368 500);
369 if (ret < 0) {
370 pr_err("reg_w_1 err %d\n", ret);
371 gspca_dev->usb_err = ret;
372 }
373}
374
375
376static void reg_w_riv(struct gspca_dev *gspca_dev,
377 u8 req, u16 index, u16 value)
378{
379 struct usb_device *dev = gspca_dev->dev;
380 int ret;
381
382 if (gspca_dev->usb_err < 0)
383 return;
384 ret = usb_control_msg(dev,
385 usb_sndctrlpipe(dev, 0),
386 req,
387 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
388 value, index, NULL, 0, 500);
389 if (ret < 0) {
390 pr_err("reg_w_riv err %d\n", ret);
391 gspca_dev->usb_err = ret;
392 return;
393 }
394 PDEBUG(D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x",
395 req, index, value);
396}
397
398static void write_vector(struct gspca_dev *gspca_dev,
399 const struct cmd *data, int ncmds)
400{
401 while (--ncmds >= 0) {
402 reg_w_riv(gspca_dev, data->req, data->idx, data->val);
403 data++;
404 }
405}
406
407static void setup_qtable(struct gspca_dev *gspca_dev,
408 const u8 qtable[2][64])
409{
410 int i;
411
412
413 for (i = 0; i < 64; i++)
414 reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]);
415
416
417 for (i = 0; i < 64; i++)
418 reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]);
419}
420
421static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
422 u8 req, u16 idx, u16 val)
423{
424 reg_w_riv(gspca_dev, req, idx, val);
425 reg_r(gspca_dev, 0x01, 0x0001, 1);
426 PDEBUG(D_FRAM, "before wait 0x%04x", gspca_dev->usb_buf[0]);
427 reg_w_riv(gspca_dev, req, idx, val);
428
429 msleep(200);
430 reg_r(gspca_dev, 0x01, 0x0001, 1);
431 PDEBUG(D_FRAM, "after wait 0x%04x", gspca_dev->usb_buf[0]);
432}
433
434#ifdef GSPCA_DEBUG
435static void spca504_read_info(struct gspca_dev *gspca_dev)
436{
437 int i;
438 u8 info[6];
439
440 for (i = 0; i < 6; i++) {
441 reg_r(gspca_dev, 0, i, 1);
442 info[i] = gspca_dev->usb_buf[0];
443 }
444 PDEBUG(D_STREAM,
445 "Read info: %d %d %d %d %d %d."
446 " Should be 1,0,2,2,0,0",
447 info[0], info[1], info[2],
448 info[3], info[4], info[5]);
449}
450#endif
451
452static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
453 u8 req,
454 u16 idx, u16 val, u8 endcode, u8 count)
455{
456 u16 status;
457
458 reg_w_riv(gspca_dev, req, idx, val);
459 reg_r(gspca_dev, 0x01, 0x0001, 1);
460 if (gspca_dev->usb_err < 0)
461 return;
462 PDEBUG(D_FRAM, "Status 0x%02x Need 0x%02x",
463 gspca_dev->usb_buf[0], endcode);
464 if (!count)
465 return;
466 count = 200;
467 while (--count > 0) {
468 msleep(10);
469
470
471 reg_r(gspca_dev, 0x01, 0x0001, 1);
472 status = gspca_dev->usb_buf[0];
473 if (status == endcode) {
474 PDEBUG(D_FRAM, "status 0x%04x after wait %d",
475 status, 200 - count);
476 break;
477 }
478 }
479}
480
481static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
482{
483 int count = 10;
484
485 while (--count > 0) {
486 reg_r(gspca_dev, 0x21, 0, 1);
487 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
488 break;
489 msleep(10);
490 }
491}
492
493static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
494{
495 int count = 50;
496
497 while (--count > 0) {
498 reg_r(gspca_dev, 0x21, 1, 1);
499 if (gspca_dev->usb_buf[0] != 0) {
500 reg_w_1(gspca_dev, 0x21, 0, 1, 0);
501 reg_r(gspca_dev, 0x21, 1, 1);
502 spca504B_PollingDataReady(gspca_dev);
503 break;
504 }
505 msleep(10);
506 }
507}
508
509#ifdef GSPCA_DEBUG
510static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
511{
512 u8 *data;
513
514 data = gspca_dev->usb_buf;
515 reg_r(gspca_dev, 0x20, 0, 5);
516 PDEBUG(D_STREAM, "FirmWare: %d %d %d %d %d",
517 data[0], data[1], data[2], data[3], data[4]);
518 reg_r(gspca_dev, 0x23, 0, 64);
519 reg_r(gspca_dev, 0x23, 1, 64);
520}
521#endif
522
523static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
524{
525 struct sd *sd = (struct sd *) gspca_dev;
526 u8 Size;
527
528 Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
529 switch (sd->bridge) {
530 case BRIDGE_SPCA533:
531 reg_w_riv(gspca_dev, 0x31, 0, 0);
532 spca504B_WaitCmdStatus(gspca_dev);
533 spca504B_PollingDataReady(gspca_dev);
534#ifdef GSPCA_DEBUG
535 spca50x_GetFirmware(gspca_dev);
536#endif
537 reg_w_1(gspca_dev, 0x24, 0, 8, 2);
538 reg_r(gspca_dev, 0x24, 8, 1);
539
540 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
541 reg_r(gspca_dev, 0x25, 4, 1);
542 spca504B_PollingDataReady(gspca_dev);
543
544
545 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
546 spca504B_WaitCmdStatus(gspca_dev);
547 spca504B_PollingDataReady(gspca_dev);
548 break;
549 default:
550
551
552 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
553 reg_r(gspca_dev, 0x25, 4, 1);
554 reg_w_1(gspca_dev, 0x27, 0, 0, 6);
555 reg_r(gspca_dev, 0x27, 0, 1);
556 spca504B_PollingDataReady(gspca_dev);
557 break;
558 case BRIDGE_SPCA504:
559 Size += 3;
560 if (sd->subtype == AiptekMiniPenCam13) {
561
562 spca504A_acknowledged_command(gspca_dev,
563 0x08, Size, 0,
564 0x80 | (Size & 0x0f), 1);
565 spca504A_acknowledged_command(gspca_dev,
566 1, 3, 0, 0x9f, 0);
567 } else {
568 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
569 }
570 break;
571 case BRIDGE_SPCA504C:
572
573 reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
574 reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
575 break;
576 }
577}
578
579static void spca504_wait_status(struct gspca_dev *gspca_dev)
580{
581 int cnt;
582
583 cnt = 256;
584 while (--cnt > 0) {
585
586 reg_r(gspca_dev, 0x06, 0x00, 1);
587 if (gspca_dev->usb_buf[0] == 0)
588 return;
589 msleep(10);
590 }
591}
592
593static void spca504B_setQtable(struct gspca_dev *gspca_dev)
594{
595 reg_w_1(gspca_dev, 0x26, 0, 0, 3);
596 reg_r(gspca_dev, 0x26, 0, 1);
597 spca504B_PollingDataReady(gspca_dev);
598}
599
600static void setbrightness(struct gspca_dev *gspca_dev)
601{
602 struct sd *sd = (struct sd *) gspca_dev;
603 u16 reg;
604
605 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
606 reg_w_riv(gspca_dev, 0x00, reg, sd->brightness);
607}
608
609static void setcontrast(struct gspca_dev *gspca_dev)
610{
611 struct sd *sd = (struct sd *) gspca_dev;
612 u16 reg;
613
614 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
615 reg_w_riv(gspca_dev, 0x00, reg, sd->contrast);
616}
617
618static void setcolors(struct gspca_dev *gspca_dev)
619{
620 struct sd *sd = (struct sd *) gspca_dev;
621 u16 reg;
622
623 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
624 reg_w_riv(gspca_dev, 0x00, reg, sd->colors);
625}
626
627static void init_ctl_reg(struct gspca_dev *gspca_dev)
628{
629 struct sd *sd = (struct sd *) gspca_dev;
630 int pollreg = 1;
631
632 setbrightness(gspca_dev);
633 setcontrast(gspca_dev);
634 setcolors(gspca_dev);
635
636 switch (sd->bridge) {
637 case BRIDGE_SPCA504:
638 case BRIDGE_SPCA504C:
639 pollreg = 0;
640
641 default:
642
643
644 reg_w_riv(gspca_dev, 0, 0x21ad, 0x00);
645 reg_w_riv(gspca_dev, 0, 0x21ac, 0x01);
646 reg_w_riv(gspca_dev, 0, 0x21a3, 0x00);
647 break;
648 case BRIDGE_SPCA536:
649 reg_w_riv(gspca_dev, 0, 0x20f5, 0x40);
650 reg_w_riv(gspca_dev, 0, 0x20f4, 0x01);
651 reg_w_riv(gspca_dev, 0, 0x2089, 0x00);
652 break;
653 }
654 if (pollreg)
655 spca504B_PollingDataReady(gspca_dev);
656}
657
658
659static int sd_config(struct gspca_dev *gspca_dev,
660 const struct usb_device_id *id)
661{
662 struct sd *sd = (struct sd *) gspca_dev;
663 struct cam *cam;
664
665 cam = &gspca_dev->cam;
666
667 sd->bridge = id->driver_info >> 8;
668 sd->subtype = id->driver_info;
669
670 if (sd->subtype == AiptekMiniPenCam13) {
671
672
673
674 reg_r(gspca_dev, 0x20, 0, 1);
675 switch (gspca_dev->usb_buf[0]) {
676 case 1:
677 break;
678 case 2:
679 sd->bridge = BRIDGE_SPCA504B;
680 sd->subtype = 0;
681 break;
682 default:
683 return -ENODEV;
684 }
685 }
686
687 switch (sd->bridge) {
688 default:
689
690
691
692 cam->cam_mode = vga_mode;
693 cam->nmodes = ARRAY_SIZE(vga_mode);
694 break;
695 case BRIDGE_SPCA533:
696 cam->cam_mode = custom_mode;
697 if (sd->subtype == MegaImageVI)
698 cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
699 else
700 cam->nmodes = ARRAY_SIZE(custom_mode);
701 break;
702 case BRIDGE_SPCA504C:
703 cam->cam_mode = vga_mode2;
704 cam->nmodes = ARRAY_SIZE(vga_mode2);
705 break;
706 }
707 sd->brightness = BRIGHTNESS_DEF;
708 sd->contrast = CONTRAST_DEF;
709 sd->colors = COLOR_DEF;
710 sd->autogain = AUTOGAIN_DEF;
711 sd->quality = QUALITY_DEF;
712 return 0;
713}
714
715
716static int sd_init(struct gspca_dev *gspca_dev)
717{
718 struct sd *sd = (struct sd *) gspca_dev;
719
720 switch (sd->bridge) {
721 case BRIDGE_SPCA504B:
722 reg_w_riv(gspca_dev, 0x1d, 0x00, 0);
723 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01);
724 reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00);
725 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00);
726 reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13);
727 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00);
728
729 case BRIDGE_SPCA533:
730 spca504B_PollingDataReady(gspca_dev);
731#ifdef GSPCA_DEBUG
732 spca50x_GetFirmware(gspca_dev);
733#endif
734 break;
735 case BRIDGE_SPCA536:
736#ifdef GSPCA_DEBUG
737 spca50x_GetFirmware(gspca_dev);
738#endif
739 reg_r(gspca_dev, 0x00, 0x5002, 1);
740 reg_w_1(gspca_dev, 0x24, 0, 0, 0);
741 reg_r(gspca_dev, 0x24, 0, 1);
742 spca504B_PollingDataReady(gspca_dev);
743 reg_w_riv(gspca_dev, 0x34, 0, 0);
744 spca504B_WaitCmdStatus(gspca_dev);
745 break;
746 case BRIDGE_SPCA504C:
747 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
748 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000);
749 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001);
750 spca504_wait_status(gspca_dev);
751 if (sd->subtype == LogitechClickSmart420)
752 write_vector(gspca_dev,
753 spca504A_clicksmart420_open_data,
754 ARRAY_SIZE(spca504A_clicksmart420_open_data));
755 else
756 write_vector(gspca_dev, spca504_pccam600_open_data,
757 ARRAY_SIZE(spca504_pccam600_open_data));
758 setup_qtable(gspca_dev, qtable_creative_pccam);
759 break;
760 default:
761
762 PDEBUG(D_STREAM, "Opening SPCA504");
763 if (sd->subtype == AiptekMiniPenCam13) {
764#ifdef GSPCA_DEBUG
765 spca504_read_info(gspca_dev);
766#endif
767
768
769 spca504A_acknowledged_command(gspca_dev, 0x24,
770 8, 3, 0x9e, 1);
771
772 spca504A_acknowledged_command(gspca_dev, 0x24,
773 8, 3, 0x9e, 0);
774
775 spca504A_acknowledged_command(gspca_dev, 0x24,
776 0, 0, 0x9d, 1);
777
778
779 spca504A_acknowledged_command(gspca_dev, 0x08,
780 6, 0, 0x86, 1);
781
782
783
784
785
786
787 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
788
789 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
790 spca504A_acknowledged_command(gspca_dev, 0x01,
791 0x0f, 0, 0xff, 0);
792 }
793
794 reg_w_riv(gspca_dev, 0, 0x2000, 0);
795 reg_w_riv(gspca_dev, 0, 0x2883, 1);
796 setup_qtable(gspca_dev, qtable_spca504_default);
797 break;
798 }
799 return gspca_dev->usb_err;
800}
801
802static int sd_start(struct gspca_dev *gspca_dev)
803{
804 struct sd *sd = (struct sd *) gspca_dev;
805 int enable;
806
807
808 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
809 0x22);
810 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
811
812 if (sd->bridge == BRIDGE_SPCA504B)
813 spca504B_setQtable(gspca_dev);
814 spca504B_SetSizeType(gspca_dev);
815 switch (sd->bridge) {
816 default:
817
818
819
820 switch (sd->subtype) {
821 case MegapixV4:
822 case LogitechClickSmart820:
823 case MegaImageVI:
824 reg_w_riv(gspca_dev, 0xf0, 0, 0);
825 spca504B_WaitCmdStatus(gspca_dev);
826 reg_r(gspca_dev, 0xf0, 4, 0);
827 spca504B_WaitCmdStatus(gspca_dev);
828 break;
829 default:
830 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
831 spca504B_WaitCmdStatus(gspca_dev);
832 spca504B_PollingDataReady(gspca_dev);
833 break;
834 }
835 break;
836 case BRIDGE_SPCA504:
837 if (sd->subtype == AiptekMiniPenCam13) {
838#ifdef GSPCA_DEBUG
839 spca504_read_info(gspca_dev);
840#endif
841
842
843 spca504A_acknowledged_command(gspca_dev, 0x24,
844 8, 3, 0x9e, 1);
845
846 spca504A_acknowledged_command(gspca_dev, 0x24,
847 8, 3, 0x9e, 0);
848 spca504A_acknowledged_command(gspca_dev, 0x24,
849 0, 0, 0x9d, 1);
850 } else {
851 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
852#ifdef GSPCA_DEBUG
853 spca504_read_info(gspca_dev);
854#endif
855 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
856 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
857 }
858 spca504B_SetSizeType(gspca_dev);
859 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
860
861 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
862 break;
863 case BRIDGE_SPCA504C:
864 if (sd->subtype == LogitechClickSmart420) {
865 write_vector(gspca_dev,
866 spca504A_clicksmart420_init_data,
867 ARRAY_SIZE(spca504A_clicksmart420_init_data));
868 } else {
869 write_vector(gspca_dev, spca504_pccam600_init_data,
870 ARRAY_SIZE(spca504_pccam600_init_data));
871 }
872 enable = (sd->autogain ? 0x04 : 0x01);
873 reg_w_riv(gspca_dev, 0x0c, 0x0000, enable);
874
875 reg_w_riv(gspca_dev, 0xb0, 0x0000, enable);
876
877
878
879 reg_w_riv(gspca_dev, 0x30, 0x0001, 800);
880 reg_w_riv(gspca_dev, 0x30, 0x0002, 1600);
881 spca504B_SetSizeType(gspca_dev);
882 break;
883 }
884 init_ctl_reg(gspca_dev);
885 return gspca_dev->usb_err;
886}
887
888static void sd_stopN(struct gspca_dev *gspca_dev)
889{
890 struct sd *sd = (struct sd *) gspca_dev;
891
892 switch (sd->bridge) {
893 default:
894
895
896
897 reg_w_riv(gspca_dev, 0x31, 0, 0);
898 spca504B_WaitCmdStatus(gspca_dev);
899 spca504B_PollingDataReady(gspca_dev);
900 break;
901 case BRIDGE_SPCA504:
902 case BRIDGE_SPCA504C:
903 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000);
904
905 if (sd->subtype == AiptekMiniPenCam13) {
906
907
908
909 spca504A_acknowledged_command(gspca_dev, 0x24,
910 0x00, 0x00, 0x9d, 1);
911 spca504A_acknowledged_command(gspca_dev, 0x01,
912 0x0f, 0x00, 0xff, 1);
913 } else {
914 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
915 reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000);
916 }
917 break;
918 }
919}
920
921static void sd_pkt_scan(struct gspca_dev *gspca_dev,
922 u8 *data,
923 int len)
924{
925 struct sd *sd = (struct sd *) gspca_dev;
926 int i, sof = 0;
927 static u8 ffd9[] = {0xff, 0xd9};
928
929
930 switch (sd->bridge) {
931 case BRIDGE_SPCA533:
932 if (data[0] == 0xff) {
933 if (data[1] != 0x01) {
934
935 return;
936 }
937 sof = 1;
938 data += SPCA533_OFFSET_DATA;
939 len -= SPCA533_OFFSET_DATA;
940 } else {
941 data += 1;
942 len -= 1;
943 }
944 break;
945 case BRIDGE_SPCA536:
946 if (data[0] == 0xff) {
947 sof = 1;
948 data += SPCA536_OFFSET_DATA;
949 len -= SPCA536_OFFSET_DATA;
950 } else {
951 data += 2;
952 len -= 2;
953 }
954 break;
955 default:
956
957
958 switch (data[0]) {
959 case 0xfe:
960 sof = 1;
961 data += SPCA50X_OFFSET_DATA;
962 len -= SPCA50X_OFFSET_DATA;
963 break;
964 case 0xff:
965
966 return;
967 default:
968 data += 1;
969 len -= 1;
970 break;
971 }
972 break;
973 case BRIDGE_SPCA504C:
974 switch (data[0]) {
975 case 0xfe:
976 sof = 1;
977 data += SPCA504_PCCAM600_OFFSET_DATA;
978 len -= SPCA504_PCCAM600_OFFSET_DATA;
979 break;
980 case 0xff:
981
982 return;
983 default:
984 data += 1;
985 len -= 1;
986 break;
987 }
988 break;
989 }
990 if (sof) {
991 gspca_frame_add(gspca_dev, LAST_PACKET,
992 ffd9, 2);
993
994
995 gspca_frame_add(gspca_dev, FIRST_PACKET,
996 sd->jpeg_hdr, JPEG_HDR_SZ);
997 }
998
999
1000 i = 0;
1001 do {
1002 if (data[i] == 0xff) {
1003 gspca_frame_add(gspca_dev, INTER_PACKET,
1004 data, i + 1);
1005 len -= i;
1006 data += i;
1007 *data = 0x00;
1008 i = 0;
1009 }
1010 i++;
1011 } while (i < len);
1012 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1013}
1014
1015static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1016{
1017 struct sd *sd = (struct sd *) gspca_dev;
1018
1019 sd->brightness = val;
1020 if (gspca_dev->streaming)
1021 setbrightness(gspca_dev);
1022 return gspca_dev->usb_err;
1023}
1024
1025static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1026{
1027 struct sd *sd = (struct sd *) gspca_dev;
1028
1029 *val = sd->brightness;
1030 return 0;
1031}
1032
1033static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1034{
1035 struct sd *sd = (struct sd *) gspca_dev;
1036
1037 sd->contrast = val;
1038 if (gspca_dev->streaming)
1039 setcontrast(gspca_dev);
1040 return gspca_dev->usb_err;
1041}
1042
1043static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1044{
1045 struct sd *sd = (struct sd *) gspca_dev;
1046
1047 *val = sd->contrast;
1048 return 0;
1049}
1050
1051static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1052{
1053 struct sd *sd = (struct sd *) gspca_dev;
1054
1055 sd->colors = val;
1056 if (gspca_dev->streaming)
1057 setcolors(gspca_dev);
1058 return gspca_dev->usb_err;
1059}
1060
1061static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1062{
1063 struct sd *sd = (struct sd *) gspca_dev;
1064
1065 *val = sd->colors;
1066 return 0;
1067}
1068
1069static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1070{
1071 struct sd *sd = (struct sd *) gspca_dev;
1072
1073 sd->autogain = val;
1074 return 0;
1075}
1076
1077static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1078{
1079 struct sd *sd = (struct sd *) gspca_dev;
1080
1081 *val = sd->autogain;
1082 return 0;
1083}
1084
1085static int sd_set_jcomp(struct gspca_dev *gspca_dev,
1086 struct v4l2_jpegcompression *jcomp)
1087{
1088 struct sd *sd = (struct sd *) gspca_dev;
1089
1090 if (jcomp->quality < QUALITY_MIN)
1091 sd->quality = QUALITY_MIN;
1092 else if (jcomp->quality > QUALITY_MAX)
1093 sd->quality = QUALITY_MAX;
1094 else
1095 sd->quality = jcomp->quality;
1096 if (gspca_dev->streaming)
1097 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
1098 return gspca_dev->usb_err;
1099}
1100
1101static int sd_get_jcomp(struct gspca_dev *gspca_dev,
1102 struct v4l2_jpegcompression *jcomp)
1103{
1104 struct sd *sd = (struct sd *) gspca_dev;
1105
1106 memset(jcomp, 0, sizeof *jcomp);
1107 jcomp->quality = sd->quality;
1108 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
1109 | V4L2_JPEG_MARKER_DQT;
1110 return 0;
1111}
1112
1113
1114static const struct sd_desc sd_desc = {
1115 .name = MODULE_NAME,
1116 .ctrls = sd_ctrls,
1117 .nctrls = ARRAY_SIZE(sd_ctrls),
1118 .config = sd_config,
1119 .init = sd_init,
1120 .start = sd_start,
1121 .stopN = sd_stopN,
1122 .pkt_scan = sd_pkt_scan,
1123 .get_jcomp = sd_get_jcomp,
1124 .set_jcomp = sd_set_jcomp,
1125};
1126
1127
1128#define BS(bridge, subtype) \
1129 .driver_info = (BRIDGE_ ## bridge << 8) \
1130 | (subtype)
1131static const struct usb_device_id device_table[] = {
1132 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
1133 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
1134 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
1135 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
1136 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
1137 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
1138 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
1139 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
1140 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
1141 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
1142 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
1143 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
1144 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
1145 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
1146 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
1147 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
1148 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
1149 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
1150 {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)},
1151 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
1152 {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
1153 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1154 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1155 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1156 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1157 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1158 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1159 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1160 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1161 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1162 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1163 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1164 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1165 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1166 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1167 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1168 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1169 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
1170 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1171 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1172 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1173 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1174 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1175 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1176 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1177 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1178 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1179 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1180 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1181 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1182 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1183 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1184 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1185 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1186 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1187 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1188 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1189 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1190 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
1191 {}
1192};
1193MODULE_DEVICE_TABLE(usb, device_table);
1194
1195
1196static int sd_probe(struct usb_interface *intf,
1197 const struct usb_device_id *id)
1198{
1199 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1200 THIS_MODULE);
1201}
1202
1203static struct usb_driver sd_driver = {
1204 .name = MODULE_NAME,
1205 .id_table = device_table,
1206 .probe = sd_probe,
1207 .disconnect = gspca_disconnect,
1208#ifdef CONFIG_PM
1209 .suspend = gspca_suspend,
1210 .resume = gspca_resume,
1211#endif
1212};
1213
1214
1215static int __init sd_mod_init(void)
1216{
1217 return usb_register(&sd_driver);
1218}
1219static void __exit sd_mod_exit(void)
1220{
1221 usb_deregister(&sd_driver);
1222}
1223
1224module_init(sd_mod_init);
1225module_exit(sd_mod_exit);
1226