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