1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#define MODULE_NAME "t613"
28
29#include "gspca.h"
30
31#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0)
32
33MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
34MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
35MODULE_LICENSE("GPL");
36
37struct sd {
38 struct gspca_dev gspca_dev;
39
40 u8 brightness;
41 u8 contrast;
42 u8 colors;
43 u8 autogain;
44 u8 gamma;
45 u8 sharpness;
46 u8 freq;
47 u8 whitebalance;
48 u8 mirror;
49 u8 effect;
50
51 u8 sensor;
52#define SENSOR_OM6802 0
53#define SENSOR_OTHER 1
54#define SENSOR_TAS5130A 2
55};
56
57
58static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
59static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
60static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
61static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
62static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
63static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
64static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
65static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
66static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
67static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
68static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
69static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
70static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
71static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
72static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
73static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
74static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val);
75static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val);
76static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
77static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
78static int sd_querymenu(struct gspca_dev *gspca_dev,
79 struct v4l2_querymenu *menu);
80
81static struct ctrl sd_ctrls[] = {
82 {
83 {
84 .id = V4L2_CID_BRIGHTNESS,
85 .type = V4L2_CTRL_TYPE_INTEGER,
86 .name = "Brightness",
87 .minimum = 0,
88 .maximum = 14,
89 .step = 1,
90#define BRIGHTNESS_DEF 8
91 .default_value = BRIGHTNESS_DEF,
92 },
93 .set = sd_setbrightness,
94 .get = sd_getbrightness,
95 },
96 {
97 {
98 .id = V4L2_CID_CONTRAST,
99 .type = V4L2_CTRL_TYPE_INTEGER,
100 .name = "Contrast",
101 .minimum = 0,
102 .maximum = 0x0d,
103 .step = 1,
104#define CONTRAST_DEF 0x07
105 .default_value = CONTRAST_DEF,
106 },
107 .set = sd_setcontrast,
108 .get = sd_getcontrast,
109 },
110 {
111 {
112 .id = V4L2_CID_SATURATION,
113 .type = V4L2_CTRL_TYPE_INTEGER,
114 .name = "Color",
115 .minimum = 0,
116 .maximum = 0x0f,
117 .step = 1,
118#define COLORS_DEF 0x05
119 .default_value = COLORS_DEF,
120 },
121 .set = sd_setcolors,
122 .get = sd_getcolors,
123 },
124#define GAMMA_MAX 16
125#define GAMMA_DEF 10
126 {
127 {
128 .id = V4L2_CID_GAMMA,
129 .type = V4L2_CTRL_TYPE_INTEGER,
130 .name = "Gamma",
131 .minimum = 0,
132 .maximum = GAMMA_MAX - 1,
133 .step = 1,
134 .default_value = GAMMA_DEF,
135 },
136 .set = sd_setgamma,
137 .get = sd_getgamma,
138 },
139 {
140 {
141 .id = V4L2_CID_GAIN,
142
143
144 .type = V4L2_CTRL_TYPE_INTEGER,
145 .name = "Low Light",
146 .minimum = 0,
147 .maximum = 1,
148 .step = 1,
149#define AUTOGAIN_DEF 0x01
150 .default_value = AUTOGAIN_DEF,
151 },
152 .set = sd_setlowlight,
153 .get = sd_getlowlight,
154 },
155 {
156 {
157 .id = V4L2_CID_HFLIP,
158 .type = V4L2_CTRL_TYPE_BOOLEAN,
159 .name = "Mirror Image",
160 .minimum = 0,
161 .maximum = 1,
162 .step = 1,
163#define MIRROR_DEF 0
164 .default_value = MIRROR_DEF,
165 },
166 .set = sd_setflip,
167 .get = sd_getflip
168 },
169 {
170 {
171 .id = V4L2_CID_POWER_LINE_FREQUENCY,
172 .type = V4L2_CTRL_TYPE_MENU,
173 .name = "Light Frequency Filter",
174 .minimum = 1,
175 .maximum = 2,
176 .step = 1,
177#define FREQ_DEF 1
178 .default_value = FREQ_DEF,
179 },
180 .set = sd_setfreq,
181 .get = sd_getfreq},
182
183 {
184 {
185 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
186 .type = V4L2_CTRL_TYPE_INTEGER,
187 .name = "White Balance",
188 .minimum = 0,
189 .maximum = 1,
190 .step = 1,
191#define WHITE_BALANCE_DEF 0
192 .default_value = WHITE_BALANCE_DEF,
193 },
194 .set = sd_setwhitebalance,
195 .get = sd_getwhitebalance
196 },
197 {
198 {
199 .id = V4L2_CID_SHARPNESS,
200 .type = V4L2_CTRL_TYPE_INTEGER,
201 .name = "Sharpness",
202 .minimum = 0,
203 .maximum = 15,
204 .step = 1,
205#define SHARPNESS_DEF 0x06
206 .default_value = SHARPNESS_DEF,
207 },
208 .set = sd_setsharpness,
209 .get = sd_getsharpness,
210 },
211 {
212 {
213 .id = V4L2_CID_EFFECTS,
214 .type = V4L2_CTRL_TYPE_MENU,
215 .name = "Webcam Effects",
216 .minimum = 0,
217 .maximum = 4,
218 .step = 1,
219#define EFFECTS_DEF 0
220 .default_value = EFFECTS_DEF,
221 },
222 .set = sd_seteffect,
223 .get = sd_geteffect
224 },
225};
226
227static char *effects_control[] = {
228 "Normal",
229 "Emboss",
230 "Monochrome",
231 "Sepia",
232 "Sketch",
233 "Sun Effect",
234 "Negative",
235};
236
237static const struct v4l2_pix_format vga_mode_t16[] = {
238 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
239 .bytesperline = 160,
240 .sizeimage = 160 * 120 * 4 / 8 + 590,
241 .colorspace = V4L2_COLORSPACE_JPEG,
242 .priv = 4},
243 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
244 .bytesperline = 176,
245 .sizeimage = 176 * 144 * 3 / 8 + 590,
246 .colorspace = V4L2_COLORSPACE_JPEG,
247 .priv = 3},
248 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
249 .bytesperline = 320,
250 .sizeimage = 320 * 240 * 3 / 8 + 590,
251 .colorspace = V4L2_COLORSPACE_JPEG,
252 .priv = 2},
253 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
254 .bytesperline = 352,
255 .sizeimage = 352 * 288 * 3 / 8 + 590,
256 .colorspace = V4L2_COLORSPACE_JPEG,
257 .priv = 1},
258 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
259 .bytesperline = 640,
260 .sizeimage = 640 * 480 * 3 / 8 + 590,
261 .colorspace = V4L2_COLORSPACE_JPEG,
262 .priv = 0},
263};
264
265
266struct additional_sensor_data {
267 const u8 n3[6];
268 const u8 *n4, n4sz;
269 const u8 reg80, reg8e;
270 const u8 nset8[6];
271 const u8 data1[10];
272 const u8 data2[9];
273 const u8 data3[9];
274 const u8 data4[4];
275 const u8 data5[6];
276 const u8 stream[4];
277};
278
279static const u8 n4_om6802[] = {
280 0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
281 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
282 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
283 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
284 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
285 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
286 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
287 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
288 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46
289};
290static const u8 n4_other[] = {
291 0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69,
292 0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68,
293 0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8,
294 0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8,
295 0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56,
296 0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5,
297 0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0,
298 0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00
299};
300static const u8 n4_tas5130a[] = {
301 0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20,
302 0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4,
303 0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10,
304 0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08,
305 0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a,
306 0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8,
307 0xc6, 0xda
308};
309
310static const struct additional_sensor_data sensor_data[] = {
311 {
312 .n3 =
313 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04},
314 .n4 = n4_om6802,
315 .n4sz = sizeof n4_om6802,
316 .reg80 = 0x3c,
317 .reg8e = 0x33,
318 .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
319 .data1 =
320 {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
321 0xb3, 0xfc},
322 .data2 =
323 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
324 0xff},
325 .data3 =
326 {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
327 0xff},
328 .data4 =
329 {0x66, 0xca, 0xa8, 0xf0},
330 .data5 =
331 {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
332 .stream =
333 {0x0b, 0x04, 0x0a, 0x78},
334 },
335 {
336 .n3 =
337 {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00},
338 .n4 = n4_other,
339 .n4sz = sizeof n4_other,
340 .reg80 = 0xac,
341 .reg8e = 0xb8,
342 .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00},
343 .data1 =
344 {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
345 0xe8, 0xfc},
346 .data2 =
347 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
348 0xd9},
349 .data3 =
350 {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
351 0xd9},
352 .data4 =
353 {0x66, 0x00, 0xa8, 0xa8},
354 .data5 =
355 {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
356 .stream =
357 {0x0b, 0x04, 0x0a, 0x00},
358 },
359 {
360 .n3 =
361 {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
362 .n4 = n4_tas5130a,
363 .n4sz = sizeof n4_tas5130a,
364 .reg80 = 0x3c,
365 .reg8e = 0xb4,
366 .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
367 .data1 =
368 {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
369 0xc8, 0xfc},
370 .data2 =
371 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
372 0xe0},
373 .data3 =
374 {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
375 0xe0},
376 .data4 =
377 {0x66, 0x00, 0xa8, 0xe8},
378 .data5 =
379 {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
380 .stream =
381 {0x0b, 0x04, 0x0a, 0x40},
382 },
383};
384
385#define MAX_EFFECTS 7
386
387
388static const u8 effects_table[MAX_EFFECTS][6] = {
389 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00},
390 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04},
391 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20},
392 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80},
393 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02},
394 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10},
395 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40},
396};
397
398static const u8 gamma_table[GAMMA_MAX][17] = {
399 {0x00, 0x3e, 0x69, 0x85, 0x95, 0xa1, 0xae, 0xb9,
400 0xc2, 0xcb, 0xd4, 0xdb, 0xe3, 0xea, 0xf1, 0xf8,
401 0xff},
402 {0x00, 0x33, 0x5a, 0x75, 0x85, 0x93, 0xa1, 0xad,
403 0xb7, 0xc2, 0xcb, 0xd4, 0xde, 0xe7, 0xf0, 0xf7,
404 0xff},
405 {0x00, 0x2f, 0x51, 0x6b, 0x7c, 0x8a, 0x99, 0xa6,
406 0xb1, 0xbc, 0xc6, 0xd0, 0xdb, 0xe4, 0xed, 0xf6,
407 0xff},
408 {0x00, 0x29, 0x48, 0x60, 0x72, 0x81, 0x90, 0x9e,
409 0xaa, 0xb5, 0xbf, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
410 0xff},
411 {0x00, 0x23, 0x3f, 0x55, 0x68, 0x77, 0x86, 0x95,
412 0xa2, 0xad, 0xb9, 0xc6, 0xd2, 0xde, 0xe9, 0xf4,
413 0xff},
414 {0x00, 0x1b, 0x33, 0x48, 0x59, 0x69, 0x79, 0x87,
415 0x96, 0xa3, 0xb1, 0xbe, 0xcc, 0xda, 0xe7, 0xf3,
416 0xff},
417 {0x00, 0x02, 0x10, 0x20, 0x32, 0x40, 0x57, 0x67,
418 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
419 0xff},
420 {0x00, 0x02, 0x14, 0x26, 0x38, 0x4a, 0x60, 0x70,
421 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
422 0xff},
423 {0x00, 0x10, 0x22, 0x35, 0x47, 0x5a, 0x69, 0x79,
424 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe0, 0xf0,
425 0xff},
426 {0x00, 0x10, 0x26, 0x40, 0x54, 0x65, 0x75, 0x84,
427 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd6, 0xe0, 0xf0,
428 0xff},
429 {0x00, 0x18, 0x2b, 0x44, 0x60, 0x70, 0x80, 0x8e,
430 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xd8, 0xe2, 0xf0,
431 0xff},
432 {0x00, 0x1a, 0x34, 0x52, 0x66, 0x7e, 0x8d, 0x9b,
433 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
434 0xff},
435 {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8,
436 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
437 0xff},
438 {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7,
439 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
440 0xff},
441 {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6,
442 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
443 0xff},
444 {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8,
445 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
446 0xff}
447};
448
449static const u8 tas5130a_sensor_init[][8] = {
450 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
451 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
452 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
453};
454
455static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
456
457
458static u8 reg_r(struct gspca_dev *gspca_dev,
459 u16 index)
460{
461 usb_control_msg(gspca_dev->dev,
462 usb_rcvctrlpipe(gspca_dev->dev, 0),
463 0,
464 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
465 0,
466 index,
467 gspca_dev->usb_buf, 1, 500);
468 return gspca_dev->usb_buf[0];
469}
470
471static void reg_w(struct gspca_dev *gspca_dev,
472 u16 index)
473{
474 usb_control_msg(gspca_dev->dev,
475 usb_sndctrlpipe(gspca_dev->dev, 0),
476 0,
477 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
478 0, index,
479 NULL, 0, 500);
480}
481
482static void reg_w_buf(struct gspca_dev *gspca_dev,
483 const u8 *buffer, u16 len)
484{
485 if (len <= USB_BUF_SZ) {
486 memcpy(gspca_dev->usb_buf, buffer, len);
487 usb_control_msg(gspca_dev->dev,
488 usb_sndctrlpipe(gspca_dev->dev, 0),
489 0,
490 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
491 0x01, 0,
492 gspca_dev->usb_buf, len, 500);
493 } else {
494 u8 *tmpbuf;
495
496 tmpbuf = kmalloc(len, GFP_KERNEL);
497 memcpy(tmpbuf, buffer, len);
498 usb_control_msg(gspca_dev->dev,
499 usb_sndctrlpipe(gspca_dev->dev, 0),
500 0,
501 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
502 0x01, 0,
503 tmpbuf, len, 500);
504 kfree(tmpbuf);
505 }
506}
507
508
509static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
510 u8 reg,
511 const u8 *buffer, u16 len)
512{
513 int i;
514 u8 *p, *tmpbuf;
515
516 if (len * 2 <= USB_BUF_SZ)
517 p = tmpbuf = gspca_dev->usb_buf;
518 else
519 p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
520 i = len;
521 while (--i >= 0) {
522 *p++ = reg++;
523 *p++ = *buffer++;
524 }
525 usb_control_msg(gspca_dev->dev,
526 usb_sndctrlpipe(gspca_dev->dev, 0),
527 0,
528 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
529 0x01, 0,
530 tmpbuf, len * 2, 500);
531 if (len * 2 > USB_BUF_SZ)
532 kfree(tmpbuf);
533}
534
535
536static void om6802_sensor_init(struct gspca_dev *gspca_dev)
537{
538 int i;
539 const u8 *p;
540 u8 byte;
541 u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
542 static const u8 sensor_init[] = {
543 0xdf, 0x6d,
544 0xdd, 0x18,
545 0x5a, 0xe0,
546 0x5c, 0x07,
547 0x5d, 0xb0,
548 0x5e, 0x1e,
549 0x60, 0x71,
550 0xef, 0x00,
551 0xe9, 0x00,
552 0xea, 0x00,
553 0x90, 0x24,
554 0x91, 0xb2,
555 0x82, 0x32,
556 0xfd, 0x41,
557 0x00
558 };
559
560 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
561 msleep(100);
562 i = 4;
563 while (--i > 0) {
564 byte = reg_r(gspca_dev, 0x0060);
565 if (!(byte & 0x01))
566 break;
567 msleep(100);
568 }
569 byte = reg_r(gspca_dev, 0x0063);
570 if (byte != 0x17) {
571 err("Bad sensor reset %02x", byte);
572
573 }
574
575 p = sensor_init;
576 while (*p != 0) {
577 val[1] = *p++;
578 val[3] = *p++;
579 if (*p == 0)
580 reg_w(gspca_dev, 0x3c80);
581 reg_w_buf(gspca_dev, val, sizeof val);
582 i = 4;
583 while (--i >= 0) {
584 msleep(15);
585 byte = reg_r(gspca_dev, 0x60);
586 if (!(byte & 0x01))
587 break;
588 }
589 }
590 msleep(15);
591 reg_w(gspca_dev, 0x3c80);
592}
593
594
595static int sd_config(struct gspca_dev *gspca_dev,
596 const struct usb_device_id *id)
597{
598 struct sd *sd = (struct sd *) gspca_dev;
599 struct cam *cam;
600
601 cam = &gspca_dev->cam;
602
603 cam->cam_mode = vga_mode_t16;
604 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
605
606 sd->brightness = BRIGHTNESS_DEF;
607 sd->contrast = CONTRAST_DEF;
608 sd->colors = COLORS_DEF;
609 sd->gamma = GAMMA_DEF;
610 sd->autogain = AUTOGAIN_DEF;
611 sd->mirror = MIRROR_DEF;
612 sd->freq = FREQ_DEF;
613 sd->whitebalance = WHITE_BALANCE_DEF;
614 sd->sharpness = SHARPNESS_DEF;
615 sd->effect = EFFECTS_DEF;
616 return 0;
617}
618
619static void setbrightness(struct gspca_dev *gspca_dev)
620{
621 struct sd *sd = (struct sd *) gspca_dev;
622 unsigned int brightness;
623 u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
624
625 brightness = sd->brightness;
626 if (brightness < 7) {
627 set6[1] = 0x26;
628 set6[3] = 0x70 - brightness * 0x10;
629 } else {
630 set6[3] = 0x00 + ((brightness - 7) * 0x10);
631 }
632
633 reg_w_buf(gspca_dev, set6, sizeof set6);
634}
635
636static void setcontrast(struct gspca_dev *gspca_dev)
637{
638 struct sd *sd = (struct sd *) gspca_dev;
639 unsigned int contrast = sd->contrast;
640 u16 reg_to_write;
641
642 if (contrast < 7)
643 reg_to_write = 0x8ea9 - contrast * 0x200;
644 else
645 reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
646
647 reg_w(gspca_dev, reg_to_write);
648}
649
650static void setcolors(struct gspca_dev *gspca_dev)
651{
652 struct sd *sd = (struct sd *) gspca_dev;
653 u16 reg_to_write;
654
655 reg_to_write = 0x80bb + sd->colors * 0x100;
656 reg_w(gspca_dev, reg_to_write);
657}
658
659static void setgamma(struct gspca_dev *gspca_dev)
660{
661 struct sd *sd = (struct sd *) gspca_dev;
662
663 PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
664 reg_w_ixbuf(gspca_dev, 0x90,
665 gamma_table[sd->gamma], sizeof gamma_table[0]);
666}
667
668static void setwhitebalance(struct gspca_dev *gspca_dev)
669{
670 struct sd *sd = (struct sd *) gspca_dev;
671
672 u8 white_balance[8] =
673 {0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38};
674
675 if (sd->whitebalance)
676 white_balance[7] = 0x3c;
677
678 reg_w_buf(gspca_dev, white_balance, sizeof white_balance);
679}
680
681static void setsharpness(struct gspca_dev *gspca_dev)
682{
683 struct sd *sd = (struct sd *) gspca_dev;
684 u16 reg_to_write;
685
686 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
687
688 reg_w(gspca_dev, reg_to_write);
689}
690
691
692static int sd_init(struct gspca_dev *gspca_dev)
693{
694
695
696
697
698 struct sd *sd = (struct sd *) gspca_dev;
699 const struct additional_sensor_data *sensor;
700 int i;
701 u16 sensor_id;
702 u8 test_byte = 0;
703
704 static const u8 read_indexs[] =
705 { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
706 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
707 static const u8 n1[] =
708 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
709 static const u8 n2[] =
710 {0x08, 0x00};
711
712 sensor_id = (reg_r(gspca_dev, 0x06) << 8)
713 | reg_r(gspca_dev, 0x07);
714 switch (sensor_id & 0xff0f) {
715 case 0x0801:
716 PDEBUG(D_PROBE, "sensor tas5130a");
717 sd->sensor = SENSOR_TAS5130A;
718 break;
719 case 0x0803:
720 PDEBUG(D_PROBE, "sensor 'other'");
721 sd->sensor = SENSOR_OTHER;
722 break;
723 case 0x0807:
724 PDEBUG(D_PROBE, "sensor om6802");
725 sd->sensor = SENSOR_OM6802;
726 break;
727 default:
728 PDEBUG(D_ERR|D_PROBE, "unknown sensor %04x", sensor_id);
729 return -EINVAL;
730 }
731
732 if (sd->sensor == SENSOR_OM6802) {
733 reg_w_buf(gspca_dev, n1, sizeof n1);
734 i = 5;
735 while (--i >= 0) {
736 reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
737 test_byte = reg_r(gspca_dev, 0x0063);
738 msleep(100);
739 if (test_byte == 0x17)
740 break;
741 }
742 if (i < 0) {
743 err("Bad sensor reset %02x", test_byte);
744 return -EIO;
745 }
746 reg_w_buf(gspca_dev, n2, sizeof n2);
747 }
748
749 i = 0;
750 while (read_indexs[i] != 0x00) {
751 test_byte = reg_r(gspca_dev, read_indexs[i]);
752 PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
753 test_byte);
754 i++;
755 }
756
757 sensor = &sensor_data[sd->sensor];
758 reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
759 reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
760
761 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
762 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
763 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
764
765 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
766 reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
767 reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
768
769 setbrightness(gspca_dev);
770 setcontrast(gspca_dev);
771 setgamma(gspca_dev);
772 setcolors(gspca_dev);
773 setsharpness(gspca_dev);
774 setwhitebalance(gspca_dev);
775
776 reg_w(gspca_dev, 0x2087);
777 reg_w(gspca_dev, 0x2088);
778 reg_w(gspca_dev, 0x2089);
779
780 reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4);
781 reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
782 reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
783 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
784
785 reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
786 reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
787 reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
788
789 return 0;
790}
791
792static void setflip(struct gspca_dev *gspca_dev)
793{
794 struct sd *sd = (struct sd *) gspca_dev;
795 u8 flipcmd[8] =
796 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
797
798 if (sd->mirror)
799 flipcmd[3] = 0x01;
800
801 reg_w_buf(gspca_dev, flipcmd, sizeof flipcmd);
802}
803
804static void seteffect(struct gspca_dev *gspca_dev)
805{
806 struct sd *sd = (struct sd *) gspca_dev;
807
808 reg_w_buf(gspca_dev, effects_table[sd->effect],
809 sizeof effects_table[0]);
810 if (sd->effect == 1 || sd->effect == 5) {
811 PDEBUG(D_CONF,
812 "This effect have been disabled for webcam \"safety\"");
813 return;
814 }
815
816 if (sd->effect == 1 || sd->effect == 4)
817 reg_w(gspca_dev, 0x4aa6);
818 else
819 reg_w(gspca_dev, 0xfaa6);
820}
821
822static void setlightfreq(struct gspca_dev *gspca_dev)
823{
824 struct sd *sd = (struct sd *) gspca_dev;
825 u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
826
827 if (sd->freq == 2)
828 freq[1] = 0x00;
829
830 reg_w_buf(gspca_dev, freq, sizeof freq);
831}
832
833
834
835static void poll_sensor(struct gspca_dev *gspca_dev)
836{
837 static const u8 poll1[] =
838 {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
839 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
840 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
841 0x60, 0x14};
842 static const u8 poll2[] =
843 {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
844 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
845 static const u8 poll3[] =
846 {0x87, 0x3f, 0x88, 0x20, 0x89, 0x2d};
847 static const u8 poll4[] =
848 {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
849 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
850 0xc2, 0x80, 0xc3, 0x10};
851
852 PDEBUG(D_STREAM, "[Sensor requires polling]");
853 reg_w_buf(gspca_dev, poll1, sizeof poll1);
854 reg_w_buf(gspca_dev, poll2, sizeof poll2);
855 reg_w_buf(gspca_dev, poll3, sizeof poll3);
856 reg_w_buf(gspca_dev, poll4, sizeof poll4);
857}
858
859static int sd_start(struct gspca_dev *gspca_dev)
860{
861 struct sd *sd = (struct sd *) gspca_dev;
862 const struct additional_sensor_data *sensor;
863 int i, mode;
864 u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
865 static const u8 t3[] =
866 { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
867
868 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
869 switch (mode) {
870 case 0:
871 break;
872 case 1:
873 t2[1] = 0x40;
874 break;
875 case 2:
876 t2[1] = 0x10;
877 break;
878 case 3:
879 t2[1] = 0x50;
880 break;
881 default:
882
883 t2[1] = 0x20;
884 break;
885 }
886
887 switch (sd->sensor) {
888 case SENSOR_OM6802:
889 om6802_sensor_init(gspca_dev);
890 break;
891 case SENSOR_OTHER:
892 break;
893 default:
894
895 i = 0;
896 for (;;) {
897 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
898 sizeof tas5130a_sensor_init[0]);
899 if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
900 break;
901 i++;
902 }
903 reg_w(gspca_dev, 0x3c80);
904
905 reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
906 sizeof tas5130a_sensor_init[0]);
907 reg_w(gspca_dev, 0x3c80);
908 break;
909 }
910 sensor = &sensor_data[sd->sensor];
911 reg_w_buf(gspca_dev, sensor->data4, sizeof sensor->data4);
912 reg_r(gspca_dev, 0x0012);
913 reg_w_buf(gspca_dev, t2, sizeof t2);
914 reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
915 reg_w(gspca_dev, 0x0013);
916 msleep(15);
917 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
918 reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
919
920 if (sd->sensor == SENSOR_OM6802)
921 poll_sensor(gspca_dev);
922
923 return 0;
924}
925
926static void sd_stopN(struct gspca_dev *gspca_dev)
927{
928 struct sd *sd = (struct sd *) gspca_dev;
929
930 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
931 sizeof sensor_data[sd->sensor].stream);
932 reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
933 sizeof sensor_data[sd->sensor].stream);
934 if (sd->sensor == SENSOR_OM6802) {
935 msleep(20);
936 reg_w(gspca_dev, 0x0309);
937 }
938}
939
940static void sd_pkt_scan(struct gspca_dev *gspca_dev,
941 struct gspca_frame *frame,
942 u8 *data,
943 int len)
944{
945 static u8 ffd9[] = { 0xff, 0xd9 };
946
947 if (data[0] == 0x5a) {
948
949
950
951 return;
952 }
953 data += 2;
954 len -= 2;
955 if (data[0] == 0xff && data[1] == 0xd8) {
956
957
958
959 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
960 ffd9, 2);
961 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
962 return;
963 }
964
965 if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
966
967
968 len -= 2;
969 }
970 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
971}
972
973static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
974{
975 struct sd *sd = (struct sd *) gspca_dev;
976
977 sd->brightness = val;
978 if (gspca_dev->streaming)
979 setbrightness(gspca_dev);
980 return 0;
981}
982
983static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
984{
985 struct sd *sd = (struct sd *) gspca_dev;
986
987 *val = sd->brightness;
988 return *val;
989}
990
991static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
992{
993 struct sd *sd = (struct sd *) gspca_dev;
994
995 sd->whitebalance = val;
996 if (gspca_dev->streaming)
997 setwhitebalance(gspca_dev);
998 return 0;
999}
1000
1001static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
1002{
1003 struct sd *sd = (struct sd *) gspca_dev;
1004
1005 *val = sd->whitebalance;
1006 return *val;
1007}
1008
1009static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
1010{
1011 struct sd *sd = (struct sd *) gspca_dev;
1012
1013 sd->mirror = val;
1014 if (gspca_dev->streaming)
1015 setflip(gspca_dev);
1016 return 0;
1017}
1018
1019static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
1020{
1021 struct sd *sd = (struct sd *) gspca_dev;
1022
1023 *val = sd->mirror;
1024 return *val;
1025}
1026
1027static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
1028{
1029 struct sd *sd = (struct sd *) gspca_dev;
1030
1031 sd->effect = val;
1032 if (gspca_dev->streaming)
1033 seteffect(gspca_dev);
1034 return 0;
1035}
1036
1037static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
1038{
1039 struct sd *sd = (struct sd *) gspca_dev;
1040
1041 *val = sd->effect;
1042 return *val;
1043}
1044
1045static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1046{
1047 struct sd *sd = (struct sd *) gspca_dev;
1048
1049 sd->contrast = val;
1050 if (gspca_dev->streaming)
1051 setcontrast(gspca_dev);
1052 return 0;
1053}
1054
1055static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1056{
1057 struct sd *sd = (struct sd *) gspca_dev;
1058
1059 *val = sd->contrast;
1060 return *val;
1061}
1062
1063static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1064{
1065 struct sd *sd = (struct sd *) gspca_dev;
1066
1067 sd->colors = val;
1068 if (gspca_dev->streaming)
1069 setcolors(gspca_dev);
1070 return 0;
1071}
1072
1073static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1074{
1075 struct sd *sd = (struct sd *) gspca_dev;
1076
1077 *val = sd->colors;
1078 return 0;
1079}
1080
1081static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
1082{
1083 struct sd *sd = (struct sd *) gspca_dev;
1084
1085 sd->gamma = val;
1086 if (gspca_dev->streaming)
1087 setgamma(gspca_dev);
1088 return 0;
1089}
1090
1091static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
1092{
1093 struct sd *sd = (struct sd *) gspca_dev;
1094
1095 *val = sd->gamma;
1096 return 0;
1097}
1098
1099static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1100{
1101 struct sd *sd = (struct sd *) gspca_dev;
1102
1103 sd->freq = val;
1104 if (gspca_dev->streaming)
1105 setlightfreq(gspca_dev);
1106 return 0;
1107}
1108
1109static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1110{
1111 struct sd *sd = (struct sd *) gspca_dev;
1112
1113 *val = sd->freq;
1114 return 0;
1115}
1116
1117static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1118{
1119 struct sd *sd = (struct sd *) gspca_dev;
1120
1121 sd->sharpness = val;
1122 if (gspca_dev->streaming)
1123 setsharpness(gspca_dev);
1124 return 0;
1125}
1126
1127static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1128{
1129 struct sd *sd = (struct sd *) gspca_dev;
1130
1131 *val = sd->sharpness;
1132 return 0;
1133}
1134
1135
1136static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
1137{
1138 struct sd *sd = (struct sd *) gspca_dev;
1139
1140 sd->autogain = val;
1141 if (val != 0)
1142 reg_w(gspca_dev, 0xf48e);
1143 else
1144 reg_w(gspca_dev, 0xb48e);
1145 return 0;
1146}
1147
1148static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
1149{
1150 struct sd *sd = (struct sd *) gspca_dev;
1151
1152 *val = sd->autogain;
1153 return 0;
1154}
1155
1156static int sd_querymenu(struct gspca_dev *gspca_dev,
1157 struct v4l2_querymenu *menu)
1158{
1159 switch (menu->id) {
1160 case V4L2_CID_POWER_LINE_FREQUENCY:
1161 switch (menu->index) {
1162 case 1:
1163 strcpy((char *) menu->name, "50 Hz");
1164 return 0;
1165 case 2:
1166 strcpy((char *) menu->name, "60 Hz");
1167 return 0;
1168 }
1169 break;
1170 case V4L2_CID_EFFECTS:
1171 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
1172 strncpy((char *) menu->name,
1173 effects_control[menu->index], 32);
1174 return 0;
1175 }
1176 break;
1177 }
1178 return -EINVAL;
1179}
1180
1181
1182static const struct sd_desc sd_desc = {
1183 .name = MODULE_NAME,
1184 .ctrls = sd_ctrls,
1185 .nctrls = ARRAY_SIZE(sd_ctrls),
1186 .config = sd_config,
1187 .init = sd_init,
1188 .start = sd_start,
1189 .stopN = sd_stopN,
1190 .pkt_scan = sd_pkt_scan,
1191 .querymenu = sd_querymenu,
1192};
1193
1194
1195static const __devinitdata struct usb_device_id device_table[] = {
1196 {USB_DEVICE(0x17a1, 0x0128)},
1197 {}
1198};
1199MODULE_DEVICE_TABLE(usb, device_table);
1200
1201
1202static int sd_probe(struct usb_interface *intf,
1203 const struct usb_device_id *id)
1204{
1205 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1206 THIS_MODULE);
1207}
1208
1209static struct usb_driver sd_driver = {
1210 .name = MODULE_NAME,
1211 .id_table = device_table,
1212 .probe = sd_probe,
1213 .disconnect = gspca_disconnect,
1214#ifdef CONFIG_PM
1215 .suspend = gspca_suspend,
1216 .resume = gspca_resume,
1217#endif
1218};
1219
1220
1221static int __init sd_mod_init(void)
1222{
1223 int ret;
1224 ret = usb_register(&sd_driver);
1225 if (ret < 0)
1226 return ret;
1227 PDEBUG(D_PROBE, "registered");
1228 return 0;
1229}
1230static void __exit sd_mod_exit(void)
1231{
1232 usb_deregister(&sd_driver);
1233 PDEBUG(D_PROBE, "deregistered");
1234}
1235
1236module_init(sd_mod_init);
1237module_exit(sd_mod_exit);
1238