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 "spca500"
25
26#include "gspca.h"
27#include "jpeg.h"
28
29MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
30MODULE_DESCRIPTION("GSPCA/SPCA500 USB Camera Driver");
31MODULE_LICENSE("GPL");
32
33
34struct sd {
35 struct gspca_dev gspca_dev;
36
37 unsigned char brightness;
38 unsigned char contrast;
39 unsigned char colors;
40 u8 quality;
41#define QUALITY_MIN 70
42#define QUALITY_MAX 95
43#define QUALITY_DEF 85
44
45 char subtype;
46#define AgfaCl20 0
47#define AiptekPocketDV 1
48#define BenqDC1016 2
49#define CreativePCCam300 3
50#define DLinkDSC350 4
51#define Gsmartmini 5
52#define IntelPocketPCCamera 6
53#define KodakEZ200 7
54#define LogitechClickSmart310 8
55#define LogitechClickSmart510 9
56#define LogitechTraveler 10
57#define MustekGsmart300 11
58#define Optimedia 12
59#define PalmPixDC85 13
60#define ToptroIndus 14
61
62 u8 jpeg_hdr[JPEG_HDR_SZ];
63};
64
65
66static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
67static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
68static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
69static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
70static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
71static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
72
73static const struct ctrl sd_ctrls[] = {
74 {
75 {
76 .id = V4L2_CID_BRIGHTNESS,
77 .type = V4L2_CTRL_TYPE_INTEGER,
78 .name = "Brightness",
79 .minimum = 0,
80 .maximum = 255,
81 .step = 1,
82#define BRIGHTNESS_DEF 127
83 .default_value = BRIGHTNESS_DEF,
84 },
85 .set = sd_setbrightness,
86 .get = sd_getbrightness,
87 },
88 {
89 {
90 .id = V4L2_CID_CONTRAST,
91 .type = V4L2_CTRL_TYPE_INTEGER,
92 .name = "Contrast",
93 .minimum = 0,
94 .maximum = 63,
95 .step = 1,
96#define CONTRAST_DEF 31
97 .default_value = CONTRAST_DEF,
98 },
99 .set = sd_setcontrast,
100 .get = sd_getcontrast,
101 },
102 {
103 {
104 .id = V4L2_CID_SATURATION,
105 .type = V4L2_CTRL_TYPE_INTEGER,
106 .name = "Color",
107 .minimum = 0,
108 .maximum = 63,
109 .step = 1,
110#define COLOR_DEF 31
111 .default_value = COLOR_DEF,
112 },
113 .set = sd_setcolors,
114 .get = sd_getcolors,
115 },
116};
117
118static const struct v4l2_pix_format vga_mode[] = {
119 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
120 .bytesperline = 320,
121 .sizeimage = 320 * 240 * 3 / 8 + 590,
122 .colorspace = V4L2_COLORSPACE_JPEG,
123 .priv = 1},
124 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
125 .bytesperline = 640,
126 .sizeimage = 640 * 480 * 3 / 8 + 590,
127 .colorspace = V4L2_COLORSPACE_JPEG,
128 .priv = 0},
129};
130
131static const struct v4l2_pix_format sif_mode[] = {
132 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
133 .bytesperline = 176,
134 .sizeimage = 176 * 144 * 3 / 8 + 590,
135 .colorspace = V4L2_COLORSPACE_JPEG,
136 .priv = 1},
137 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
138 .bytesperline = 352,
139 .sizeimage = 352 * 288 * 3 / 8 + 590,
140 .colorspace = V4L2_COLORSPACE_JPEG,
141 .priv = 0},
142};
143
144
145#define SPCA500_OFFSET_PADDINGLB 2
146#define SPCA500_OFFSET_PADDINGHB 3
147#define SPCA500_OFFSET_MODE 4
148#define SPCA500_OFFSET_IMGWIDTH 5
149#define SPCA500_OFFSET_IMGHEIGHT 6
150#define SPCA500_OFFSET_IMGMODE 7
151#define SPCA500_OFFSET_QTBLINDEX 8
152#define SPCA500_OFFSET_FRAMSEQ 9
153#define SPCA500_OFFSET_CDSPINFO 10
154#define SPCA500_OFFSET_GPIO 11
155#define SPCA500_OFFSET_AUGPIO 12
156#define SPCA500_OFFSET_DATA 16
157
158
159static const __u16 spca500_visual_defaults[][3] = {
160 {0x00, 0x0003, 0x816b},
161
162
163
164
165 {0x00, 0x0000, 0x8167},
166 {0x00, 0x0020, 0x8168},
167 {0x00, 0x0003, 0x816b},
168
169
170
171
172 {0x00, 0x0000, 0x816a},
173 {0x00, 0x0020, 0x8169},
174 {0x00, 0x0050, 0x8157},
175 {0x00, 0x0030, 0x8158},
176 {0x00, 0x0028, 0x8159},
177 {0x00, 0x000a, 0x815a},
178 {0x00, 0x0001, 0x8202},
179 {0x0c, 0x0004, 0x0000},
180
181 {}
182};
183static const __u16 Clicksmart510_defaults[][3] = {
184 {0x00, 0x00, 0x8211},
185 {0x00, 0x01, 0x82c0},
186 {0x00, 0x10, 0x82cb},
187 {0x00, 0x0f, 0x800d},
188 {0x00, 0x82, 0x8225},
189 {0x00, 0x21, 0x8228},
190 {0x00, 0x00, 0x8203},
191 {0x00, 0x00, 0x8204},
192 {0x00, 0x08, 0x8205},
193 {0x00, 0xf8, 0x8206},
194 {0x00, 0x28, 0x8207},
195 {0x00, 0xa0, 0x8208},
196 {0x00, 0x08, 0x824a},
197 {0x00, 0x08, 0x8214},
198 {0x00, 0x80, 0x82c1},
199 {0x00, 0x00, 0x82c2},
200 {0x00, 0x00, 0x82ca},
201 {0x00, 0x80, 0x82c1},
202 {0x00, 0x04, 0x82c2},
203 {0x00, 0x00, 0x82ca},
204 {0x00, 0xfc, 0x8100},
205 {0x00, 0xfc, 0x8105},
206 {0x00, 0x30, 0x8101},
207 {0x00, 0x00, 0x8102},
208 {0x00, 0x00, 0x8103},
209 {0x00, 0x66, 0x8107},
210 {0x00, 0x00, 0x816b},
211 {0x00, 0x00, 0x8155},
212 {0x00, 0x01, 0x8156},
213 {0x00, 0x60, 0x8157},
214 {0x00, 0x40, 0x8158},
215 {0x00, 0x0a, 0x8159},
216 {0x00, 0x06, 0x815a},
217 {0x00, 0x00, 0x813f},
218 {0x00, 0x00, 0x8200},
219 {0x00, 0x19, 0x8201},
220 {0x00, 0x00, 0x82c1},
221 {0x00, 0xa0, 0x82c2},
222 {0x00, 0x00, 0x82ca},
223 {0x00, 0x00, 0x8117},
224 {0x00, 0x00, 0x8118},
225 {0x00, 0x65, 0x8119},
226 {0x00, 0x00, 0x811a},
227 {0x00, 0x00, 0x811b},
228 {0x00, 0x55, 0x811c},
229 {0x00, 0x65, 0x811d},
230 {0x00, 0x55, 0x811e},
231 {0x00, 0x16, 0x811f},
232 {0x00, 0x19, 0x8120},
233 {0x00, 0x80, 0x8103},
234 {0x00, 0x83, 0x816b},
235 {0x00, 0x25, 0x8168},
236 {0x00, 0x01, 0x820f},
237 {0x00, 0xff, 0x8115},
238 {0x00, 0x48, 0x8116},
239 {0x00, 0x50, 0x8151},
240 {0x00, 0x40, 0x8152},
241 {0x00, 0x78, 0x8153},
242 {0x00, 0x40, 0x8154},
243 {0x00, 0x00, 0x8167},
244 {0x00, 0x20, 0x8168},
245 {0x00, 0x00, 0x816a},
246 {0x00, 0x03, 0x816b},
247 {0x00, 0x20, 0x8169},
248 {0x00, 0x60, 0x8157},
249 {0x00, 0x00, 0x8190},
250 {0x00, 0x00, 0x81a1},
251 {0x00, 0x00, 0x81b2},
252 {0x00, 0x27, 0x8191},
253 {0x00, 0x27, 0x81a2},
254 {0x00, 0x27, 0x81b3},
255 {0x00, 0x4b, 0x8192},
256 {0x00, 0x4b, 0x81a3},
257 {0x00, 0x4b, 0x81b4},
258 {0x00, 0x66, 0x8193},
259 {0x00, 0x66, 0x81a4},
260 {0x00, 0x66, 0x81b5},
261 {0x00, 0x79, 0x8194},
262 {0x00, 0x79, 0x81a5},
263 {0x00, 0x79, 0x81b6},
264 {0x00, 0x8a, 0x8195},
265 {0x00, 0x8a, 0x81a6},
266 {0x00, 0x8a, 0x81b7},
267 {0x00, 0x9b, 0x8196},
268 {0x00, 0x9b, 0x81a7},
269 {0x00, 0x9b, 0x81b8},
270 {0x00, 0xa6, 0x8197},
271 {0x00, 0xa6, 0x81a8},
272 {0x00, 0xa6, 0x81b9},
273 {0x00, 0xb2, 0x8198},
274 {0x00, 0xb2, 0x81a9},
275 {0x00, 0xb2, 0x81ba},
276 {0x00, 0xbe, 0x8199},
277 {0x00, 0xbe, 0x81aa},
278 {0x00, 0xbe, 0x81bb},
279 {0x00, 0xc8, 0x819a},
280 {0x00, 0xc8, 0x81ab},
281 {0x00, 0xc8, 0x81bc},
282 {0x00, 0xd2, 0x819b},
283 {0x00, 0xd2, 0x81ac},
284 {0x00, 0xd2, 0x81bd},
285 {0x00, 0xdb, 0x819c},
286 {0x00, 0xdb, 0x81ad},
287 {0x00, 0xdb, 0x81be},
288 {0x00, 0xe4, 0x819d},
289 {0x00, 0xe4, 0x81ae},
290 {0x00, 0xe4, 0x81bf},
291 {0x00, 0xed, 0x819e},
292 {0x00, 0xed, 0x81af},
293 {0x00, 0xed, 0x81c0},
294 {0x00, 0xf7, 0x819f},
295 {0x00, 0xf7, 0x81b0},
296 {0x00, 0xf7, 0x81c1},
297 {0x00, 0xff, 0x81a0},
298 {0x00, 0xff, 0x81b1},
299 {0x00, 0xff, 0x81c2},
300 {0x00, 0x03, 0x8156},
301 {0x00, 0x00, 0x8211},
302 {0x00, 0x20, 0x8168},
303 {0x00, 0x01, 0x8202},
304 {0x00, 0x30, 0x8101},
305 {0x00, 0x00, 0x8111},
306 {0x00, 0x00, 0x8112},
307 {0x00, 0x00, 0x8113},
308 {0x00, 0x00, 0x8114},
309 {}
310};
311
312static const __u8 qtable_creative_pccam[2][64] = {
313 {
314 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
315 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
316 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
317 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
318 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
319 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
320 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
321 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
322 {
323 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
324 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
325 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
326 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
327 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
328 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
329 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
330 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
331};
332
333static const __u8 qtable_kodak_ez200[2][64] = {
334 {
335 0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06,
336 0x01, 0x01, 0x01, 0x02, 0x03, 0x06, 0x06, 0x06,
337 0x01, 0x01, 0x02, 0x02, 0x04, 0x06, 0x07, 0x06,
338 0x01, 0x02, 0x02, 0x03, 0x05, 0x09, 0x08, 0x06,
339 0x02, 0x02, 0x04, 0x06, 0x07, 0x0b, 0x0a, 0x08,
340 0x02, 0x04, 0x06, 0x06, 0x08, 0x0a, 0x0b, 0x09,
341 0x05, 0x06, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0a,
342 0x07, 0x09, 0x0a, 0x0a, 0x0b, 0x0a, 0x0a, 0x0a},
343 {
344 0x02, 0x02, 0x02, 0x05, 0x0a, 0x0a, 0x0a, 0x0a,
345 0x02, 0x02, 0x03, 0x07, 0x0a, 0x0a, 0x0a, 0x0a,
346 0x02, 0x03, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
347 0x05, 0x07, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
348 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
349 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
350 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
351 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a}
352};
353
354static const __u8 qtable_pocketdv[2][64] = {
355 {
356 0x06, 0x04, 0x04, 0x06, 0x0a, 0x10, 0x14, 0x18,
357 0x05, 0x05, 0x06, 0x08, 0x0a, 0x17, 0x18, 0x16,
358 0x06, 0x05, 0x06, 0x0a, 0x10, 0x17, 0x1c, 0x16,
359 0x06, 0x07, 0x09, 0x0c, 0x14, 0x23, 0x20, 0x19,
360 0x07, 0x09, 0x0f, 0x16, 0x1b, 0x2c, 0x29, 0x1f,
361 0x0a, 0x0e, 0x16, 0x1a, 0x20, 0x2a, 0x2d, 0x25,
362 0x14, 0x1a, 0x1f, 0x23, 0x29, 0x30, 0x30, 0x28,
363 0x1d, 0x25, 0x26, 0x27, 0x2d, 0x28, 0x29, 0x28,
364 },
365 {
366 0x07, 0x07, 0x0a, 0x13, 0x28, 0x28, 0x28, 0x28,
367 0x07, 0x08, 0x0a, 0x1a, 0x28, 0x28, 0x28, 0x28,
368 0x0a, 0x0a, 0x16, 0x28, 0x28, 0x28, 0x28, 0x28,
369 0x13, 0x1a, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
370 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
371 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
372 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
373 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28}
374};
375
376
377static void reg_r(struct gspca_dev *gspca_dev,
378 __u16 index,
379 __u16 length)
380{
381 usb_control_msg(gspca_dev->dev,
382 usb_rcvctrlpipe(gspca_dev->dev, 0),
383 0,
384 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
385 0,
386 index, gspca_dev->usb_buf, length, 500);
387}
388
389static int reg_w(struct gspca_dev *gspca_dev,
390 __u16 req, __u16 index, __u16 value)
391{
392 int ret;
393
394 PDEBUG(D_USBO, "reg write: [0x%02x] = 0x%02x", index, value);
395 ret = usb_control_msg(gspca_dev->dev,
396 usb_sndctrlpipe(gspca_dev->dev, 0),
397 req,
398 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
399 value, index, NULL, 0, 500);
400 if (ret < 0)
401 pr_err("reg write: error %d\n", ret);
402 return ret;
403}
404
405
406static int reg_r_12(struct gspca_dev *gspca_dev,
407 __u16 req,
408 __u16 index,
409 __u16 length)
410{
411 int ret;
412
413 gspca_dev->usb_buf[1] = 0;
414 ret = usb_control_msg(gspca_dev->dev,
415 usb_rcvctrlpipe(gspca_dev->dev, 0),
416 req,
417 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
418 0,
419 index,
420 gspca_dev->usb_buf, length,
421 500);
422 if (ret < 0) {
423 pr_err("reg_r_12 err %d\n", ret);
424 return ret;
425 }
426 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
427}
428
429
430
431
432
433
434static int reg_r_wait(struct gspca_dev *gspca_dev,
435 __u16 reg, __u16 index, __u16 value)
436{
437 int ret, cnt = 20;
438
439 while (--cnt > 0) {
440 ret = reg_r_12(gspca_dev, reg, index, 1);
441 if (ret == value)
442 return 0;
443 msleep(50);
444 }
445 return -EIO;
446}
447
448static int write_vector(struct gspca_dev *gspca_dev,
449 const __u16 data[][3])
450{
451 int ret, i = 0;
452
453 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
454 ret = reg_w(gspca_dev, data[i][0], data[i][2], data[i][1]);
455 if (ret < 0)
456 return ret;
457 i++;
458 }
459 return 0;
460}
461
462static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
463 unsigned int request,
464 unsigned int ybase,
465 unsigned int cbase,
466 const __u8 qtable[2][64])
467{
468 int i, err;
469
470
471 for (i = 0; i < 64; i++) {
472 err = reg_w(gspca_dev, request, ybase + i, qtable[0][i]);
473 if (err < 0)
474 return err;
475 }
476
477
478 for (i = 0; i < 64; i++) {
479 err = reg_w(gspca_dev, request, cbase + i, qtable[1][i]);
480 if (err < 0)
481 return err;
482 }
483 return 0;
484}
485
486static void spca500_ping310(struct gspca_dev *gspca_dev)
487{
488 reg_r(gspca_dev, 0x0d04, 2);
489 PDEBUG(D_STREAM, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x",
490 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
491}
492
493static void spca500_clksmart310_init(struct gspca_dev *gspca_dev)
494{
495 reg_r(gspca_dev, 0x0d05, 2);
496 PDEBUG(D_STREAM, "ClickSmart310 init 0x0d05 0x%02x 0x%02x",
497 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
498 reg_w(gspca_dev, 0x00, 0x8167, 0x5a);
499 spca500_ping310(gspca_dev);
500
501 reg_w(gspca_dev, 0x00, 0x8168, 0x22);
502 reg_w(gspca_dev, 0x00, 0x816a, 0xc0);
503 reg_w(gspca_dev, 0x00, 0x816b, 0x0b);
504 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
505 reg_w(gspca_dev, 0x00, 0x8157, 0x5b);
506 reg_w(gspca_dev, 0x00, 0x8158, 0x5b);
507 reg_w(gspca_dev, 0x00, 0x813f, 0x03);
508 reg_w(gspca_dev, 0x00, 0x8151, 0x4a);
509 reg_w(gspca_dev, 0x00, 0x8153, 0x78);
510 reg_w(gspca_dev, 0x00, 0x0d01, 0x04);
511
512 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
513 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
514 reg_w(gspca_dev, 0x00, 0x0d01, 0x02);
515}
516
517static void spca500_setmode(struct gspca_dev *gspca_dev,
518 __u8 xmult, __u8 ymult)
519{
520 int mode;
521
522
523 reg_w(gspca_dev, 0, 0x8001, xmult);
524
525
526 reg_w(gspca_dev, 0, 0x8002, ymult);
527
528
529 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
530 reg_w(gspca_dev, 0, 0x8003, mode << 4);
531}
532
533static int spca500_full_reset(struct gspca_dev *gspca_dev)
534{
535 int err;
536
537
538 err = reg_w(gspca_dev, 0xe0, 0x0001, 0x0000);
539 if (err < 0)
540 return err;
541
542
543 err = reg_r_wait(gspca_dev, 0x06, 0x0000, 0x0000);
544 if (err < 0)
545 return err;
546 err = reg_w(gspca_dev, 0xe0, 0x0000, 0x0000);
547 if (err < 0)
548 return err;
549 err = reg_r_wait(gspca_dev, 0x06, 0, 0);
550 if (err < 0) {
551 PDEBUG(D_ERR, "reg_r_wait() failed");
552 return err;
553 }
554
555 return 0;
556}
557
558
559
560
561
562
563
564static int spca500_synch310(struct gspca_dev *gspca_dev)
565{
566 if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0) < 0) {
567 PDEBUG(D_ERR, "Set packet size: set interface error");
568 goto error;
569 }
570 spca500_ping310(gspca_dev);
571
572 reg_r(gspca_dev, 0x0d00, 1);
573
574
575 PDEBUG(D_PACK, "ClickSmart310 sync alt: %d", gspca_dev->alt);
576
577
578 if (usb_set_interface(gspca_dev->dev,
579 gspca_dev->iface,
580 gspca_dev->alt) < 0) {
581 PDEBUG(D_ERR, "Set packet size: set interface error");
582 goto error;
583 }
584 return 0;
585error:
586 return -EBUSY;
587}
588
589static void spca500_reinit(struct gspca_dev *gspca_dev)
590{
591 int err;
592 __u8 Data;
593
594
595
596 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
597 reg_w(gspca_dev, 0x00, 0x0d03, 0x00);
598 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
599
600
601 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
602
603 err = spca50x_setup_qtable(gspca_dev, 0x00, 0x8800, 0x8840,
604 qtable_pocketdv);
605 if (err < 0)
606 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed on init");
607
608
609 reg_w(gspca_dev, 0x00, 0x8880, 2);
610
611 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
612
613 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
614
615 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
616
617 reg_w(gspca_dev, 0, 0x8003, 0x00);
618
619 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
620 msleep(2000);
621 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) {
622 reg_r(gspca_dev, 0x816b, 1);
623 Data = gspca_dev->usb_buf[0];
624 reg_w(gspca_dev, 0x00, 0x816b, Data);
625 }
626}
627
628
629static int sd_config(struct gspca_dev *gspca_dev,
630 const struct usb_device_id *id)
631{
632 struct sd *sd = (struct sd *) gspca_dev;
633 struct cam *cam;
634
635 cam = &gspca_dev->cam;
636 sd->subtype = id->driver_info;
637 if (sd->subtype != LogitechClickSmart310) {
638 cam->cam_mode = vga_mode;
639 cam->nmodes = ARRAY_SIZE(vga_mode);
640 } else {
641 cam->cam_mode = sif_mode;
642 cam->nmodes = ARRAY_SIZE(sif_mode);
643 }
644 sd->brightness = BRIGHTNESS_DEF;
645 sd->contrast = CONTRAST_DEF;
646 sd->colors = COLOR_DEF;
647 sd->quality = QUALITY_DEF;
648 return 0;
649}
650
651
652static int sd_init(struct gspca_dev *gspca_dev)
653{
654 struct sd *sd = (struct sd *) gspca_dev;
655
656
657 PDEBUG(D_STREAM, "SPCA500 init");
658 if (sd->subtype == LogitechClickSmart310)
659 spca500_clksmart310_init(gspca_dev);
660
661
662 PDEBUG(D_STREAM, "SPCA500 init done");
663 return 0;
664}
665
666static int sd_start(struct gspca_dev *gspca_dev)
667{
668 struct sd *sd = (struct sd *) gspca_dev;
669 int err;
670 __u8 Data;
671 __u8 xmult, ymult;
672
673
674 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
675 0x22);
676 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
677
678 if (sd->subtype == LogitechClickSmart310) {
679 xmult = 0x16;
680 ymult = 0x12;
681 } else {
682 xmult = 0x28;
683 ymult = 0x1e;
684 }
685
686
687 reg_r(gspca_dev, 0x8a04, 1);
688 PDEBUG(D_STREAM, "Spca500 Sensor Address 0x%02x",
689 gspca_dev->usb_buf[0]);
690 PDEBUG(D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x",
691 gspca_dev->curr_mode, xmult, ymult);
692
693
694 switch (sd->subtype) {
695 case LogitechClickSmart310:
696 spca500_setmode(gspca_dev, xmult, ymult);
697
698
699 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
700 reg_w(gspca_dev, 0x00, 0x8880, 3);
701 err = spca50x_setup_qtable(gspca_dev,
702 0x00, 0x8800, 0x8840,
703 qtable_creative_pccam);
704 if (err < 0)
705 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
706
707 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
708
709
710 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
711 msleep(500);
712 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
713 PDEBUG(D_ERR, "reg_r_wait() failed");
714
715 reg_r(gspca_dev, 0x816b, 1);
716 Data = gspca_dev->usb_buf[0];
717 reg_w(gspca_dev, 0x00, 0x816b, Data);
718
719 spca500_synch310(gspca_dev);
720
721 write_vector(gspca_dev, spca500_visual_defaults);
722 spca500_setmode(gspca_dev, xmult, ymult);
723
724 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
725 if (err < 0)
726 PDEBUG(D_ERR, "failed to enable drop packet");
727 reg_w(gspca_dev, 0x00, 0x8880, 3);
728 err = spca50x_setup_qtable(gspca_dev,
729 0x00, 0x8800, 0x8840,
730 qtable_creative_pccam);
731 if (err < 0)
732 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
733
734
735 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
736
737
738 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
739
740 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
741 PDEBUG(D_ERR, "reg_r_wait() failed");
742
743 reg_r(gspca_dev, 0x816b, 1);
744 Data = gspca_dev->usb_buf[0];
745 reg_w(gspca_dev, 0x00, 0x816b, Data);
746 break;
747 case CreativePCCam300:
748 case IntelPocketPCCamera:
749
750
751
752
753 err = spca500_full_reset(gspca_dev);
754 if (err < 0)
755 PDEBUG(D_ERR, "spca500_full_reset failed");
756
757
758 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
759 if (err < 0)
760 PDEBUG(D_ERR, "failed to enable drop packet");
761 reg_w(gspca_dev, 0x00, 0x8880, 3);
762 err = spca50x_setup_qtable(gspca_dev,
763 0x00, 0x8800, 0x8840,
764 qtable_creative_pccam);
765 if (err < 0)
766 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
767
768 spca500_setmode(gspca_dev, xmult, ymult);
769 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
770
771
772 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
773
774 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
775 PDEBUG(D_ERR, "reg_r_wait() failed");
776
777 reg_r(gspca_dev, 0x816b, 1);
778 Data = gspca_dev->usb_buf[0];
779 reg_w(gspca_dev, 0x00, 0x816b, Data);
780
781
782 break;
783 case KodakEZ200:
784
785
786 err = spca500_full_reset(gspca_dev);
787 if (err < 0)
788 PDEBUG(D_ERR, "spca500_full_reset failed");
789
790 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
791 reg_w(gspca_dev, 0x00, 0x8880, 0);
792 err = spca50x_setup_qtable(gspca_dev,
793 0x00, 0x8800, 0x8840,
794 qtable_kodak_ez200);
795 if (err < 0)
796 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
797 spca500_setmode(gspca_dev, xmult, ymult);
798
799 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
800
801
802 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
803
804 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
805 PDEBUG(D_ERR, "reg_r_wait() failed");
806
807 reg_r(gspca_dev, 0x816b, 1);
808 Data = gspca_dev->usb_buf[0];
809 reg_w(gspca_dev, 0x00, 0x816b, Data);
810
811
812 break;
813
814 case BenqDC1016:
815 case DLinkDSC350:
816 case AiptekPocketDV:
817 case Gsmartmini:
818 case MustekGsmart300:
819 case PalmPixDC85:
820 case Optimedia:
821 case ToptroIndus:
822 case AgfaCl20:
823 spca500_reinit(gspca_dev);
824 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
825
826 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
827
828 err = spca50x_setup_qtable(gspca_dev,
829 0x00, 0x8800, 0x8840, qtable_pocketdv);
830 if (err < 0)
831 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
832 reg_w(gspca_dev, 0x00, 0x8880, 2);
833
834
835 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
836
837 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
838
839 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
840
841 spca500_setmode(gspca_dev, xmult, ymult);
842
843 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
844
845 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
846
847 reg_r(gspca_dev, 0x816b, 1);
848 Data = gspca_dev->usb_buf[0];
849 reg_w(gspca_dev, 0x00, 0x816b, Data);
850 break;
851 case LogitechTraveler:
852 case LogitechClickSmart510:
853 reg_w(gspca_dev, 0x02, 0x00, 0x00);
854
855 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
856
857 err = spca50x_setup_qtable(gspca_dev,
858 0x00, 0x8800,
859 0x8840, qtable_creative_pccam);
860 if (err < 0)
861 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
862 reg_w(gspca_dev, 0x00, 0x8880, 3);
863 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
864
865 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
866
867 spca500_setmode(gspca_dev, xmult, ymult);
868
869
870 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
871 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
872
873 reg_r(gspca_dev, 0x816b, 1);
874 Data = gspca_dev->usb_buf[0];
875 reg_w(gspca_dev, 0x00, 0x816b, Data);
876 write_vector(gspca_dev, Clicksmart510_defaults);
877 break;
878 }
879 return 0;
880}
881
882static void sd_stopN(struct gspca_dev *gspca_dev)
883{
884 reg_w(gspca_dev, 0, 0x8003, 0x00);
885
886
887 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
888 reg_r(gspca_dev, 0x8000, 1);
889 PDEBUG(D_STREAM, "stop SPCA500 done reg8000: 0x%2x",
890 gspca_dev->usb_buf[0]);
891}
892
893static void sd_pkt_scan(struct gspca_dev *gspca_dev,
894 u8 *data,
895 int len)
896{
897 struct sd *sd = (struct sd *) gspca_dev;
898 int i;
899 static __u8 ffd9[] = {0xff, 0xd9};
900
901
902 if (data[0] == 0xff) {
903 if (data[1] != 0x01) {
904
905 return;
906 }
907 gspca_frame_add(gspca_dev, LAST_PACKET,
908 ffd9, 2);
909
910
911 gspca_frame_add(gspca_dev, FIRST_PACKET,
912 sd->jpeg_hdr, JPEG_HDR_SZ);
913
914 data += SPCA500_OFFSET_DATA;
915 len -= SPCA500_OFFSET_DATA;
916 } else {
917 data += 1;
918 len -= 1;
919 }
920
921
922 i = 0;
923 do {
924 if (data[i] == 0xff) {
925 gspca_frame_add(gspca_dev, INTER_PACKET,
926 data, i + 1);
927 len -= i;
928 data += i;
929 *data = 0x00;
930 i = 0;
931 }
932 i++;
933 } while (i < len);
934 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
935}
936
937static void setbrightness(struct gspca_dev *gspca_dev)
938{
939 struct sd *sd = (struct sd *) gspca_dev;
940
941 reg_w(gspca_dev, 0x00, 0x8167,
942 (__u8) (sd->brightness - 128));
943}
944
945static void setcontrast(struct gspca_dev *gspca_dev)
946{
947 struct sd *sd = (struct sd *) gspca_dev;
948
949 reg_w(gspca_dev, 0x00, 0x8168, sd->contrast);
950}
951
952static void setcolors(struct gspca_dev *gspca_dev)
953{
954 struct sd *sd = (struct sd *) gspca_dev;
955
956 reg_w(gspca_dev, 0x00, 0x8169, sd->colors);
957}
958
959static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
960{
961 struct sd *sd = (struct sd *) gspca_dev;
962
963 sd->brightness = val;
964 if (gspca_dev->streaming)
965 setbrightness(gspca_dev);
966 return 0;
967}
968
969static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
970{
971 struct sd *sd = (struct sd *) gspca_dev;
972
973 *val = sd->brightness;
974 return 0;
975}
976
977static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
978{
979 struct sd *sd = (struct sd *) gspca_dev;
980
981 sd->contrast = val;
982 if (gspca_dev->streaming)
983 setcontrast(gspca_dev);
984 return 0;
985}
986
987static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
988{
989 struct sd *sd = (struct sd *) gspca_dev;
990
991 *val = sd->contrast;
992 return 0;
993}
994
995static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
996{
997 struct sd *sd = (struct sd *) gspca_dev;
998
999 sd->colors = val;
1000 if (gspca_dev->streaming)
1001 setcolors(gspca_dev);
1002 return 0;
1003}
1004
1005static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1006{
1007 struct sd *sd = (struct sd *) gspca_dev;
1008
1009 *val = sd->colors;
1010 return 0;
1011}
1012
1013static int sd_set_jcomp(struct gspca_dev *gspca_dev,
1014 struct v4l2_jpegcompression *jcomp)
1015{
1016 struct sd *sd = (struct sd *) gspca_dev;
1017
1018 if (jcomp->quality < QUALITY_MIN)
1019 sd->quality = QUALITY_MIN;
1020 else if (jcomp->quality > QUALITY_MAX)
1021 sd->quality = QUALITY_MAX;
1022 else
1023 sd->quality = jcomp->quality;
1024 if (gspca_dev->streaming)
1025 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
1026 return 0;
1027}
1028
1029static int sd_get_jcomp(struct gspca_dev *gspca_dev,
1030 struct v4l2_jpegcompression *jcomp)
1031{
1032 struct sd *sd = (struct sd *) gspca_dev;
1033
1034 memset(jcomp, 0, sizeof *jcomp);
1035 jcomp->quality = sd->quality;
1036 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
1037 | V4L2_JPEG_MARKER_DQT;
1038 return 0;
1039}
1040
1041
1042static const struct sd_desc sd_desc = {
1043 .name = MODULE_NAME,
1044 .ctrls = sd_ctrls,
1045 .nctrls = ARRAY_SIZE(sd_ctrls),
1046 .config = sd_config,
1047 .init = sd_init,
1048 .start = sd_start,
1049 .stopN = sd_stopN,
1050 .pkt_scan = sd_pkt_scan,
1051 .get_jcomp = sd_get_jcomp,
1052 .set_jcomp = sd_set_jcomp,
1053};
1054
1055
1056static const struct usb_device_id device_table[] = {
1057 {USB_DEVICE(0x040a, 0x0300), .driver_info = KodakEZ200},
1058 {USB_DEVICE(0x041e, 0x400a), .driver_info = CreativePCCam300},
1059 {USB_DEVICE(0x046d, 0x0890), .driver_info = LogitechTraveler},
1060 {USB_DEVICE(0x046d, 0x0900), .driver_info = LogitechClickSmart310},
1061 {USB_DEVICE(0x046d, 0x0901), .driver_info = LogitechClickSmart510},
1062 {USB_DEVICE(0x04a5, 0x300c), .driver_info = BenqDC1016},
1063 {USB_DEVICE(0x04fc, 0x7333), .driver_info = PalmPixDC85},
1064 {USB_DEVICE(0x055f, 0xc200), .driver_info = MustekGsmart300},
1065 {USB_DEVICE(0x055f, 0xc220), .driver_info = Gsmartmini},
1066 {USB_DEVICE(0x06bd, 0x0404), .driver_info = AgfaCl20},
1067 {USB_DEVICE(0x06be, 0x0800), .driver_info = Optimedia},
1068 {USB_DEVICE(0x084d, 0x0003), .driver_info = DLinkDSC350},
1069 {USB_DEVICE(0x08ca, 0x0103), .driver_info = AiptekPocketDV},
1070 {USB_DEVICE(0x2899, 0x012c), .driver_info = ToptroIndus},
1071 {USB_DEVICE(0x8086, 0x0630), .driver_info = IntelPocketPCCamera},
1072 {}
1073};
1074MODULE_DEVICE_TABLE(usb, device_table);
1075
1076
1077static int sd_probe(struct usb_interface *intf,
1078 const struct usb_device_id *id)
1079{
1080 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1081 THIS_MODULE);
1082}
1083
1084static struct usb_driver sd_driver = {
1085 .name = MODULE_NAME,
1086 .id_table = device_table,
1087 .probe = sd_probe,
1088 .disconnect = gspca_disconnect,
1089#ifdef CONFIG_PM
1090 .suspend = gspca_suspend,
1091 .resume = gspca_resume,
1092#endif
1093};
1094
1095
1096static int __init sd_mod_init(void)
1097{
1098 return usb_register(&sd_driver);
1099}
1100static void __exit sd_mod_exit(void)
1101{
1102 usb_deregister(&sd_driver);
1103}
1104
1105module_init(sd_mod_init);
1106module_exit(sd_mod_exit);
1107