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 if (len > USB_BUF_SZ) {
255 PERR("reg_r: buffer overflow\n");
256 return;
257 }
258 if (gspca_dev->usb_err < 0)
259 return;
260 ret = usb_control_msg(gspca_dev->dev,
261 usb_rcvctrlpipe(gspca_dev->dev, 0),
262 req,
263 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
264 0,
265 index,
266 len ? gspca_dev->usb_buf : NULL, len,
267 500);
268 if (ret < 0) {
269 pr_err("reg_r err %d\n", ret);
270 gspca_dev->usb_err = ret;
271 }
272}
273
274
275static void reg_w_1(struct gspca_dev *gspca_dev,
276 u8 req,
277 u16 value,
278 u16 index,
279 u16 byte)
280{
281 int ret;
282
283 if (gspca_dev->usb_err < 0)
284 return;
285 gspca_dev->usb_buf[0] = byte;
286 ret = usb_control_msg(gspca_dev->dev,
287 usb_sndctrlpipe(gspca_dev->dev, 0),
288 req,
289 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
290 value, index,
291 gspca_dev->usb_buf, 1,
292 500);
293 if (ret < 0) {
294 pr_err("reg_w_1 err %d\n", ret);
295 gspca_dev->usb_err = ret;
296 }
297}
298
299
300static void reg_w_riv(struct gspca_dev *gspca_dev,
301 u8 req, u16 index, u16 value)
302{
303 struct usb_device *dev = gspca_dev->dev;
304 int ret;
305
306 if (gspca_dev->usb_err < 0)
307 return;
308 ret = usb_control_msg(dev,
309 usb_sndctrlpipe(dev, 0),
310 req,
311 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
312 value, index, NULL, 0, 500);
313 if (ret < 0) {
314 pr_err("reg_w_riv err %d\n", ret);
315 gspca_dev->usb_err = ret;
316 return;
317 }
318 PDEBUG(D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x",
319 req, index, value);
320}
321
322static void write_vector(struct gspca_dev *gspca_dev,
323 const struct cmd *data, int ncmds)
324{
325 while (--ncmds >= 0) {
326 reg_w_riv(gspca_dev, data->req, data->idx, data->val);
327 data++;
328 }
329}
330
331static void setup_qtable(struct gspca_dev *gspca_dev,
332 const u8 qtable[2][64])
333{
334 int i;
335
336
337 for (i = 0; i < 64; i++)
338 reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]);
339
340
341 for (i = 0; i < 64; i++)
342 reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]);
343}
344
345static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
346 u8 req, u16 idx, u16 val)
347{
348 reg_w_riv(gspca_dev, req, idx, val);
349 reg_r(gspca_dev, 0x01, 0x0001, 1);
350 PDEBUG(D_FRAM, "before wait 0x%04x", gspca_dev->usb_buf[0]);
351 reg_w_riv(gspca_dev, req, idx, val);
352
353 msleep(200);
354 reg_r(gspca_dev, 0x01, 0x0001, 1);
355 PDEBUG(D_FRAM, "after wait 0x%04x", gspca_dev->usb_buf[0]);
356}
357
358static void spca504_read_info(struct gspca_dev *gspca_dev)
359{
360 int i;
361 u8 info[6];
362
363 if (gspca_debug < D_STREAM)
364 return;
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
377static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
378 u8 req,
379 u16 idx, u16 val, u8 endcode, u8 count)
380{
381 u16 status;
382
383 reg_w_riv(gspca_dev, req, idx, val);
384 reg_r(gspca_dev, 0x01, 0x0001, 1);
385 if (gspca_dev->usb_err < 0)
386 return;
387 PDEBUG(D_FRAM, "Status 0x%02x Need 0x%02x",
388 gspca_dev->usb_buf[0], endcode);
389 if (!count)
390 return;
391 count = 200;
392 while (--count > 0) {
393 msleep(10);
394
395
396 reg_r(gspca_dev, 0x01, 0x0001, 1);
397 status = gspca_dev->usb_buf[0];
398 if (status == endcode) {
399 PDEBUG(D_FRAM, "status 0x%04x after wait %d",
400 status, 200 - count);
401 break;
402 }
403 }
404}
405
406static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
407{
408 int count = 10;
409
410 while (--count > 0) {
411 reg_r(gspca_dev, 0x21, 0, 1);
412 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
413 break;
414 msleep(10);
415 }
416}
417
418static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
419{
420 int count = 50;
421
422 while (--count > 0) {
423 reg_r(gspca_dev, 0x21, 1, 1);
424 if (gspca_dev->usb_buf[0] != 0) {
425 reg_w_1(gspca_dev, 0x21, 0, 1, 0);
426 reg_r(gspca_dev, 0x21, 1, 1);
427 spca504B_PollingDataReady(gspca_dev);
428 break;
429 }
430 msleep(10);
431 }
432}
433
434static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
435{
436 u8 *data;
437
438 if (gspca_debug < D_STREAM)
439 return;
440
441 data = gspca_dev->usb_buf;
442 reg_r(gspca_dev, 0x20, 0, 5);
443 PDEBUG(D_STREAM, "FirmWare: %d %d %d %d %d",
444 data[0], data[1], data[2], data[3], data[4]);
445 reg_r(gspca_dev, 0x23, 0, 64);
446 reg_r(gspca_dev, 0x23, 1, 64);
447}
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 spca50x_GetFirmware(gspca_dev);
461
462 reg_w_1(gspca_dev, 0x24, 0, 8, 2);
463 reg_r(gspca_dev, 0x24, 8, 1);
464
465 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
466 reg_r(gspca_dev, 0x25, 4, 1);
467 spca504B_PollingDataReady(gspca_dev);
468
469
470 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
471 spca504B_WaitCmdStatus(gspca_dev);
472 spca504B_PollingDataReady(gspca_dev);
473 break;
474 default:
475
476
477 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
478 reg_r(gspca_dev, 0x25, 4, 1);
479 reg_w_1(gspca_dev, 0x27, 0, 0, 6);
480 reg_r(gspca_dev, 0x27, 0, 1);
481 spca504B_PollingDataReady(gspca_dev);
482 break;
483 case BRIDGE_SPCA504:
484 Size += 3;
485 if (sd->subtype == AiptekMiniPenCam13) {
486
487 spca504A_acknowledged_command(gspca_dev,
488 0x08, Size, 0,
489 0x80 | (Size & 0x0f), 1);
490 spca504A_acknowledged_command(gspca_dev,
491 1, 3, 0, 0x9f, 0);
492 } else {
493 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
494 }
495 break;
496 case BRIDGE_SPCA504C:
497
498 reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
499 reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
500 break;
501 }
502}
503
504static void spca504_wait_status(struct gspca_dev *gspca_dev)
505{
506 int cnt;
507
508 cnt = 256;
509 while (--cnt > 0) {
510
511 reg_r(gspca_dev, 0x06, 0x00, 1);
512 if (gspca_dev->usb_buf[0] == 0)
513 return;
514 msleep(10);
515 }
516}
517
518static void spca504B_setQtable(struct gspca_dev *gspca_dev)
519{
520 reg_w_1(gspca_dev, 0x26, 0, 0, 3);
521 reg_r(gspca_dev, 0x26, 0, 1);
522 spca504B_PollingDataReady(gspca_dev);
523}
524
525static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
526{
527 struct sd *sd = (struct sd *) gspca_dev;
528 u16 reg;
529
530 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
531 reg_w_riv(gspca_dev, 0x00, reg, val);
532}
533
534static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
535{
536 struct sd *sd = (struct sd *) gspca_dev;
537 u16 reg;
538
539 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
540 reg_w_riv(gspca_dev, 0x00, reg, val);
541}
542
543static void setcolors(struct gspca_dev *gspca_dev, s32 val)
544{
545 struct sd *sd = (struct sd *) gspca_dev;
546 u16 reg;
547
548 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
549 reg_w_riv(gspca_dev, 0x00, reg, val);
550}
551
552static void init_ctl_reg(struct gspca_dev *gspca_dev)
553{
554 struct sd *sd = (struct sd *) gspca_dev;
555 int pollreg = 1;
556
557 switch (sd->bridge) {
558 case BRIDGE_SPCA504:
559 case BRIDGE_SPCA504C:
560 pollreg = 0;
561
562 default:
563
564
565 reg_w_riv(gspca_dev, 0, 0x21ad, 0x00);
566 reg_w_riv(gspca_dev, 0, 0x21ac, 0x01);
567 reg_w_riv(gspca_dev, 0, 0x21a3, 0x00);
568 break;
569 case BRIDGE_SPCA536:
570 reg_w_riv(gspca_dev, 0, 0x20f5, 0x40);
571 reg_w_riv(gspca_dev, 0, 0x20f4, 0x01);
572 reg_w_riv(gspca_dev, 0, 0x2089, 0x00);
573 break;
574 }
575 if (pollreg)
576 spca504B_PollingDataReady(gspca_dev);
577}
578
579
580static int sd_config(struct gspca_dev *gspca_dev,
581 const struct usb_device_id *id)
582{
583 struct sd *sd = (struct sd *) gspca_dev;
584 struct cam *cam;
585
586 cam = &gspca_dev->cam;
587
588 sd->bridge = id->driver_info >> 8;
589 sd->subtype = id->driver_info;
590
591 if (sd->subtype == AiptekMiniPenCam13) {
592
593
594
595 reg_r(gspca_dev, 0x20, 0, 1);
596 switch (gspca_dev->usb_buf[0]) {
597 case 1:
598 break;
599 case 2:
600 sd->bridge = BRIDGE_SPCA504B;
601 sd->subtype = 0;
602 break;
603 default:
604 return -ENODEV;
605 }
606 }
607
608 switch (sd->bridge) {
609 default:
610
611
612
613 cam->cam_mode = vga_mode;
614 cam->nmodes = ARRAY_SIZE(vga_mode);
615 break;
616 case BRIDGE_SPCA533:
617 cam->cam_mode = custom_mode;
618 if (sd->subtype == MegaImageVI)
619 cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
620 else
621 cam->nmodes = ARRAY_SIZE(custom_mode);
622 break;
623 case BRIDGE_SPCA504C:
624 cam->cam_mode = vga_mode2;
625 cam->nmodes = ARRAY_SIZE(vga_mode2);
626 break;
627 }
628 return 0;
629}
630
631
632static int sd_init(struct gspca_dev *gspca_dev)
633{
634 struct sd *sd = (struct sd *) gspca_dev;
635
636 switch (sd->bridge) {
637 case BRIDGE_SPCA504B:
638 reg_w_riv(gspca_dev, 0x1d, 0x00, 0);
639 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01);
640 reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00);
641 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00);
642 reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13);
643 reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00);
644
645 case BRIDGE_SPCA533:
646 spca504B_PollingDataReady(gspca_dev);
647 spca50x_GetFirmware(gspca_dev);
648 break;
649 case BRIDGE_SPCA536:
650 spca50x_GetFirmware(gspca_dev);
651 reg_r(gspca_dev, 0x00, 0x5002, 1);
652 reg_w_1(gspca_dev, 0x24, 0, 0, 0);
653 reg_r(gspca_dev, 0x24, 0, 1);
654 spca504B_PollingDataReady(gspca_dev);
655 reg_w_riv(gspca_dev, 0x34, 0, 0);
656 spca504B_WaitCmdStatus(gspca_dev);
657 break;
658 case BRIDGE_SPCA504C:
659 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
660 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000);
661 reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001);
662 spca504_wait_status(gspca_dev);
663 if (sd->subtype == LogitechClickSmart420)
664 write_vector(gspca_dev,
665 spca504A_clicksmart420_open_data,
666 ARRAY_SIZE(spca504A_clicksmart420_open_data));
667 else
668 write_vector(gspca_dev, spca504_pccam600_open_data,
669 ARRAY_SIZE(spca504_pccam600_open_data));
670 setup_qtable(gspca_dev, qtable_creative_pccam);
671 break;
672 default:
673
674 PDEBUG(D_STREAM, "Opening SPCA504");
675 if (sd->subtype == AiptekMiniPenCam13) {
676 spca504_read_info(gspca_dev);
677
678
679 spca504A_acknowledged_command(gspca_dev, 0x24,
680 8, 3, 0x9e, 1);
681
682 spca504A_acknowledged_command(gspca_dev, 0x24,
683 8, 3, 0x9e, 0);
684
685 spca504A_acknowledged_command(gspca_dev, 0x24,
686 0, 0, 0x9d, 1);
687
688
689 spca504A_acknowledged_command(gspca_dev, 0x08,
690 6, 0, 0x86, 1);
691
692
693
694
695
696
697 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
698
699 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
700 spca504A_acknowledged_command(gspca_dev, 0x01,
701 0x0f, 0, 0xff, 0);
702 }
703
704 reg_w_riv(gspca_dev, 0, 0x2000, 0);
705 reg_w_riv(gspca_dev, 0, 0x2883, 1);
706 setup_qtable(gspca_dev, qtable_spca504_default);
707 break;
708 }
709 return gspca_dev->usb_err;
710}
711
712static int sd_start(struct gspca_dev *gspca_dev)
713{
714 struct sd *sd = (struct sd *) gspca_dev;
715 int enable;
716
717
718 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
719 0x22);
720 jpeg_set_qual(sd->jpeg_hdr, QUALITY);
721
722 if (sd->bridge == BRIDGE_SPCA504B)
723 spca504B_setQtable(gspca_dev);
724 spca504B_SetSizeType(gspca_dev);
725 switch (sd->bridge) {
726 default:
727
728
729
730 switch (sd->subtype) {
731 case MegapixV4:
732 case LogitechClickSmart820:
733 case MegaImageVI:
734 reg_w_riv(gspca_dev, 0xf0, 0, 0);
735 spca504B_WaitCmdStatus(gspca_dev);
736 reg_r(gspca_dev, 0xf0, 4, 0);
737 spca504B_WaitCmdStatus(gspca_dev);
738 break;
739 default:
740 reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
741 spca504B_WaitCmdStatus(gspca_dev);
742 spca504B_PollingDataReady(gspca_dev);
743 break;
744 }
745 break;
746 case BRIDGE_SPCA504:
747 if (sd->subtype == AiptekMiniPenCam13) {
748 spca504_read_info(gspca_dev);
749
750
751 spca504A_acknowledged_command(gspca_dev, 0x24,
752 8, 3, 0x9e, 1);
753
754 spca504A_acknowledged_command(gspca_dev, 0x24,
755 8, 3, 0x9e, 0);
756 spca504A_acknowledged_command(gspca_dev, 0x24,
757 0, 0, 0x9d, 1);
758 } else {
759 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
760 spca504_read_info(gspca_dev);
761 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
762 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
763 }
764 spca504B_SetSizeType(gspca_dev);
765 reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
766
767 reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
768 break;
769 case BRIDGE_SPCA504C:
770 if (sd->subtype == LogitechClickSmart420) {
771 write_vector(gspca_dev,
772 spca504A_clicksmart420_init_data,
773 ARRAY_SIZE(spca504A_clicksmart420_init_data));
774 } else {
775 write_vector(gspca_dev, spca504_pccam600_init_data,
776 ARRAY_SIZE(spca504_pccam600_init_data));
777 }
778 enable = (sd->autogain ? 0x04 : 0x01);
779 reg_w_riv(gspca_dev, 0x0c, 0x0000, enable);
780
781 reg_w_riv(gspca_dev, 0xb0, 0x0000, enable);
782
783
784
785 reg_w_riv(gspca_dev, 0x30, 0x0001, 800);
786 reg_w_riv(gspca_dev, 0x30, 0x0002, 1600);
787 spca504B_SetSizeType(gspca_dev);
788 break;
789 }
790 init_ctl_reg(gspca_dev);
791 return gspca_dev->usb_err;
792}
793
794static void sd_stopN(struct gspca_dev *gspca_dev)
795{
796 struct sd *sd = (struct sd *) gspca_dev;
797
798 switch (sd->bridge) {
799 default:
800
801
802
803 reg_w_riv(gspca_dev, 0x31, 0, 0);
804 spca504B_WaitCmdStatus(gspca_dev);
805 spca504B_PollingDataReady(gspca_dev);
806 break;
807 case BRIDGE_SPCA504:
808 case BRIDGE_SPCA504C:
809 reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000);
810
811 if (sd->subtype == AiptekMiniPenCam13) {
812
813
814
815 spca504A_acknowledged_command(gspca_dev, 0x24,
816 0x00, 0x00, 0x9d, 1);
817 spca504A_acknowledged_command(gspca_dev, 0x01,
818 0x0f, 0x00, 0xff, 1);
819 } else {
820 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
821 reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000);
822 }
823 break;
824 }
825}
826
827static void sd_pkt_scan(struct gspca_dev *gspca_dev,
828 u8 *data,
829 int len)
830{
831 struct sd *sd = (struct sd *) gspca_dev;
832 int i, sof = 0;
833 static u8 ffd9[] = {0xff, 0xd9};
834
835
836 switch (sd->bridge) {
837 case BRIDGE_SPCA533:
838 if (data[0] == 0xff) {
839 if (data[1] != 0x01) {
840
841 return;
842 }
843 sof = 1;
844 data += SPCA533_OFFSET_DATA;
845 len -= SPCA533_OFFSET_DATA;
846 } else {
847 data += 1;
848 len -= 1;
849 }
850 break;
851 case BRIDGE_SPCA536:
852 if (data[0] == 0xff) {
853 sof = 1;
854 data += SPCA536_OFFSET_DATA;
855 len -= SPCA536_OFFSET_DATA;
856 } else {
857 data += 2;
858 len -= 2;
859 }
860 break;
861 default:
862
863
864 switch (data[0]) {
865 case 0xfe:
866 sof = 1;
867 data += SPCA50X_OFFSET_DATA;
868 len -= SPCA50X_OFFSET_DATA;
869 break;
870 case 0xff:
871
872 return;
873 default:
874 data += 1;
875 len -= 1;
876 break;
877 }
878 break;
879 case BRIDGE_SPCA504C:
880 switch (data[0]) {
881 case 0xfe:
882 sof = 1;
883 data += SPCA504_PCCAM600_OFFSET_DATA;
884 len -= SPCA504_PCCAM600_OFFSET_DATA;
885 break;
886 case 0xff:
887
888 return;
889 default:
890 data += 1;
891 len -= 1;
892 break;
893 }
894 break;
895 }
896 if (sof) {
897 gspca_frame_add(gspca_dev, LAST_PACKET,
898 ffd9, 2);
899
900
901 gspca_frame_add(gspca_dev, FIRST_PACKET,
902 sd->jpeg_hdr, JPEG_HDR_SZ);
903 }
904
905
906 i = 0;
907 do {
908 if (data[i] == 0xff) {
909 gspca_frame_add(gspca_dev, INTER_PACKET,
910 data, i + 1);
911 len -= i;
912 data += i;
913 *data = 0x00;
914 i = 0;
915 }
916 i++;
917 } while (i < len);
918 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
919}
920
921static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
922{
923 struct gspca_dev *gspca_dev =
924 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
925 struct sd *sd = (struct sd *)gspca_dev;
926
927 gspca_dev->usb_err = 0;
928
929 if (!gspca_dev->streaming)
930 return 0;
931
932 switch (ctrl->id) {
933 case V4L2_CID_BRIGHTNESS:
934 setbrightness(gspca_dev, ctrl->val);
935 break;
936 case V4L2_CID_CONTRAST:
937 setcontrast(gspca_dev, ctrl->val);
938 break;
939 case V4L2_CID_SATURATION:
940 setcolors(gspca_dev, ctrl->val);
941 break;
942 case V4L2_CID_AUTOGAIN:
943 sd->autogain = ctrl->val;
944 break;
945 }
946 return gspca_dev->usb_err;
947}
948
949static const struct v4l2_ctrl_ops sd_ctrl_ops = {
950 .s_ctrl = sd_s_ctrl,
951};
952
953static int sd_init_controls(struct gspca_dev *gspca_dev)
954{
955 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
956
957 gspca_dev->vdev.ctrl_handler = hdl;
958 v4l2_ctrl_handler_init(hdl, 4);
959 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
960 V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
961 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
962 V4L2_CID_CONTRAST, 0, 255, 1, 0x20);
963 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
964 V4L2_CID_SATURATION, 0, 255, 1, 0x1a);
965 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
966 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
967
968 if (hdl->error) {
969 pr_err("Could not initialize controls\n");
970 return hdl->error;
971 }
972 return 0;
973}
974
975
976static const struct sd_desc sd_desc = {
977 .name = MODULE_NAME,
978 .config = sd_config,
979 .init = sd_init,
980 .init_controls = sd_init_controls,
981 .start = sd_start,
982 .stopN = sd_stopN,
983 .pkt_scan = sd_pkt_scan,
984};
985
986
987#define BS(bridge, subtype) \
988 .driver_info = (BRIDGE_ ## bridge << 8) \
989 | (subtype)
990static const struct usb_device_id device_table[] = {
991 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
992 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
993 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
994 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
995 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
996 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
997 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
998 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
999 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
1000 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
1001 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
1002 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
1003 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
1004 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
1005 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
1006 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
1007 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
1008 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
1009 {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)},
1010 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
1011 {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
1012 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1013 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1014 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1015 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1016 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1017 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1018 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1019 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1020 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1021 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1022 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1023 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1024 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1025 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1026 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1027 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1028 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
1029 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1030 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1031 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1032 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1033 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1034 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1035 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1036 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1037 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1038 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1039 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1040 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1041 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1042 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1043 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1044 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1045 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1046 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1047 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1048 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1049 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
1050 {}
1051};
1052MODULE_DEVICE_TABLE(usb, device_table);
1053
1054
1055static int sd_probe(struct usb_interface *intf,
1056 const struct usb_device_id *id)
1057{
1058 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1059 THIS_MODULE);
1060}
1061
1062static struct usb_driver sd_driver = {
1063 .name = MODULE_NAME,
1064 .id_table = device_table,
1065 .probe = sd_probe,
1066 .disconnect = gspca_disconnect,
1067#ifdef CONFIG_PM
1068 .suspend = gspca_suspend,
1069 .resume = gspca_resume,
1070 .reset_resume = gspca_resume,
1071#endif
1072};
1073
1074module_usb_driver(sd_driver);
1075