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