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