blob: e831f0d280ea7bf268084a93393435679283dcfa [file] [log] [blame]
Jean-Francois Moinec52af792010-01-07 05:18:16 -03001/*
2 * ov534-ov965x gspca driver
3 *
4 * Copyright (C) 2009-2010 Jean-Francois Moine http://moinejf.free.fr
5 * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it>
6 * Copyright (C) 2008 Jim Paris <jim@jtan.com>
7 *
8 * Based on a prototype written by Mark Ferrell <majortrips@gmail.com>
9 * USB protocol reverse engineered by Jim Paris <jim@jtan.com>
10 * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27#define MODULE_NAME "ov534_9"
28
29#include "gspca.h"
30
31#define OV534_REG_ADDRESS 0xf1 /* sensor address */
32#define OV534_REG_SUBADDR 0xf2
33#define OV534_REG_WRITE 0xf3
34#define OV534_REG_READ 0xf4
35#define OV534_REG_OPERATION 0xf5
36#define OV534_REG_STATUS 0xf6
37
38#define OV534_OP_WRITE_3 0x37
39#define OV534_OP_WRITE_2 0x33
40#define OV534_OP_READ_2 0xf9
41
42#define CTRL_TIMEOUT 500
43
44MODULE_AUTHOR("Jean-Francois Moine <moinejf@free.fr>");
45MODULE_DESCRIPTION("GSPCA/OV534_9 USB Camera Driver");
46MODULE_LICENSE("GPL");
47
48/* specific webcam descriptor */
49struct sd {
50 struct gspca_dev gspca_dev; /* !! must be the first item */
51 __u32 last_pts;
52 u8 last_fid;
53
54 u8 brightness;
55 u8 contrast;
56 u8 autogain;
57 u8 exposure;
58 s8 sharpness;
59 u8 satur;
60 u8 freq;
61};
62
63/* V4L2 controls supported by the driver */
64static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
65static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
66static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
67static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
68static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
69static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
70static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
71static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
72static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
73static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
74static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val);
75static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val);
76static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
77static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
78
79static const struct ctrl sd_ctrls[] = {
80 { /* 0 */
81 {
82 .id = V4L2_CID_BRIGHTNESS,
83 .type = V4L2_CTRL_TYPE_INTEGER,
84 .name = "Brightness",
85 .minimum = 0,
86 .maximum = 15,
87 .step = 1,
88#define BRIGHTNESS_DEF 7
89 .default_value = BRIGHTNESS_DEF,
90 },
91 .set = sd_setbrightness,
92 .get = sd_getbrightness,
93 },
94 { /* 1 */
95 {
96 .id = V4L2_CID_CONTRAST,
97 .type = V4L2_CTRL_TYPE_INTEGER,
98 .name = "Contrast",
99 .minimum = 0,
100 .maximum = 15,
101 .step = 1,
102#define CONTRAST_DEF 3
103 .default_value = CONTRAST_DEF,
104 },
105 .set = sd_setcontrast,
106 .get = sd_getcontrast,
107 },
108 { /* 2 */
109 {
110 .id = V4L2_CID_AUTOGAIN,
111 .type = V4L2_CTRL_TYPE_BOOLEAN,
112 .name = "Autogain",
113 .minimum = 0,
114 .maximum = 1,
115 .step = 1,
116#define AUTOGAIN_DEF 1
117 .default_value = AUTOGAIN_DEF,
118 },
119 .set = sd_setautogain,
120 .get = sd_getautogain,
121 },
122#define EXPO_IDX 3
123 { /* 3 */
124 {
125 .id = V4L2_CID_EXPOSURE,
126 .type = V4L2_CTRL_TYPE_INTEGER,
127 .name = "Exposure",
128 .minimum = 0,
129 .maximum = 3,
130 .step = 1,
131#define EXPO_DEF 0
132 .default_value = EXPO_DEF,
133 },
134 .set = sd_setexposure,
135 .get = sd_getexposure,
136 },
137 { /* 4 */
138 {
139 .id = V4L2_CID_SHARPNESS,
140 .type = V4L2_CTRL_TYPE_INTEGER,
141 .name = "Sharpness",
142 .minimum = -1, /* -1 = auto */
143 .maximum = 4,
144 .step = 1,
145#define SHARPNESS_DEF -1
146 .default_value = SHARPNESS_DEF,
147 },
148 .set = sd_setsharpness,
149 .get = sd_getsharpness,
150 },
151 { /* 5 */
152 {
153 .id = V4L2_CID_SATURATION,
154 .type = V4L2_CTRL_TYPE_INTEGER,
155 .name = "Saturation",
156 .minimum = 0,
157 .maximum = 4,
158 .step = 1,
159#define SATUR_DEF 2
160 .default_value = SATUR_DEF,
161 },
162 .set = sd_setsatur,
163 .get = sd_getsatur,
164 },
165 {
166 {
167 .id = V4L2_CID_POWER_LINE_FREQUENCY,
168 .type = V4L2_CTRL_TYPE_MENU,
169 .name = "Light frequency filter",
170 .minimum = 0,
171 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
172 .step = 1,
173#define FREQ_DEF 0
174 .default_value = FREQ_DEF,
175 },
176 .set = sd_setfreq,
177 .get = sd_getfreq,
178 },
179};
180
181static const struct v4l2_pix_format ov965x_mode[] = {
182#define QVGA_MODE 0
183 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
184 .bytesperline = 320,
185 .sizeimage = 320 * 240 * 3 / 8 + 590,
186 .colorspace = V4L2_COLORSPACE_JPEG},
187#define VGA_MODE 1
188 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
189 .bytesperline = 640,
190 .sizeimage = 640 * 480 * 3 / 8 + 590,
191 .colorspace = V4L2_COLORSPACE_JPEG},
192#define SVGA_MODE 2
193 {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
194 .bytesperline = 800,
195 .sizeimage = 800 * 600 * 3 / 8 + 590,
196 .colorspace = V4L2_COLORSPACE_JPEG},
197#define XGA_MODE 3
198 {1024, 768, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
199 .bytesperline = 1024,
200 .sizeimage = 1024 * 768 * 3 / 8 + 590,
201 .colorspace = V4L2_COLORSPACE_JPEG},
202#define SXGA_MODE 4
203 {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
204 .bytesperline = 1280,
205 .sizeimage = 1280 * 1024 * 3 / 8 + 590,
206 .colorspace = V4L2_COLORSPACE_JPEG},
207};
208
209static const u8 bridge_init[][2] = {
210 {0x88, 0xf8},
211 {0x89, 0xff},
212 {0x76, 0x03},
213 {0x92, 0x03},
214 {0x95, 0x10},
215 {0xe2, 0x00},
216 {0xe7, 0x3e},
217 {0x8d, 0x1c},
218 {0x8e, 0x00},
219 {0x8f, 0x00},
220 {0x1f, 0x00},
221 {0xc3, 0xf9},
222 {0x89, 0xff},
223 {0x88, 0xf8},
224 {0x76, 0x03},
225 {0x92, 0x01},
226 {0x93, 0x18},
227 {0x1c, 0x0a},
228 {0x1d, 0x48},
229 {0xc0, 0x50},
230 {0xc1, 0x3c},
231 {0x34, 0x05},
232 {0xc2, 0x0c},
233 {0xc3, 0xf9},
234 {0x34, 0x05},
235 {0xe7, 0x2e},
236 {0x31, 0xf9},
237 {0x35, 0x02},
238 {0xd9, 0x10},
239 {0x25, 0x42},
240 {0x94, 0x11},
241};
242
243static const u8 sensor_init[][2] = {
244 {0x12, 0x80}, /* com7 - SSCB reset */
245 {0x00, 0x00}, /* gain */
246 {0x01, 0x80}, /* blue */
247 {0x02, 0x80}, /* red */
248 {0x03, 0x1b}, /* vref */
249 {0x04, 0x03}, /* com1 - exposure low bits */
250 {0x0b, 0x57}, /* ver */
251 {0x0e, 0x61}, /* com5 */
252 {0x0f, 0x42}, /* com6 */
253 {0x11, 0x00}, /* clkrc */
254 {0x12, 0x02}, /* com7 - 15fps VGA YUYV */
255 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
256 {0x14, 0x28}, /* com9 */
257 {0x16, 0x24}, /* reg16 */
258 {0x17, 0x1d}, /* hstart*/
259 {0x18, 0xbd}, /* hstop */
260 {0x19, 0x01}, /* vstrt */
261 {0x1a, 0x81}, /* vstop*/
262 {0x1e, 0x04}, /* mvfp */
263 {0x24, 0x3c}, /* aew */
264 {0x25, 0x36}, /* aeb */
265 {0x26, 0x71}, /* vpt */
266 {0x27, 0x08}, /* bbias */
267 {0x28, 0x08}, /* gbbias */
268 {0x29, 0x15}, /* gr com */
269 {0x2a, 0x00}, /* exhch */
270 {0x2b, 0x00}, /* exhcl */
271 {0x2c, 0x08}, /* rbias */
272 {0x32, 0xff}, /* href */
273 {0x33, 0x00}, /* chlf */
274 {0x34, 0x3f}, /* aref1 */
275 {0x35, 0x00}, /* aref2 */
276 {0x36, 0xf8}, /* aref3 */
277 {0x38, 0x72}, /* adc2 */
278 {0x39, 0x57}, /* aref4 */
279 {0x3a, 0x80}, /* tslb - yuyv */
280 {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
281 {0x3d, 0x99}, /* com13 */
282 {0x3f, 0xc1}, /* edge */
283 {0x40, 0xc0}, /* com15 */
284 {0x41, 0x40}, /* com16 */
285 {0x42, 0xc0}, /* com17 */
286 {0x43, 0x0a}, /* rsvd */
287 {0x44, 0xf0},
288 {0x45, 0x46},
289 {0x46, 0x62},
290 {0x47, 0x2a},
291 {0x48, 0x3c},
292 {0x4a, 0xfc},
293 {0x4b, 0xfc},
294 {0x4c, 0x7f},
295 {0x4d, 0x7f},
296 {0x4e, 0x7f},
297 {0x4f, 0x98}, /* matrix */
298 {0x50, 0x98},
299 {0x51, 0x00},
300 {0x52, 0x28},
301 {0x53, 0x70},
302 {0x54, 0x98},
303 {0x58, 0x1a}, /* matrix coef sign */
304 {0x59, 0x85}, /* AWB control */
305 {0x5a, 0xa9},
306 {0x5b, 0x64},
307 {0x5c, 0x84},
308 {0x5d, 0x53},
309 {0x5e, 0x0e},
310 {0x5f, 0xf0}, /* AWB blue limit */
311 {0x60, 0xf0}, /* AWB red limit */
312 {0x61, 0xf0}, /* AWB green limit */
313 {0x62, 0x00}, /* lcc1 */
314 {0x63, 0x00}, /* lcc2 */
315 {0x64, 0x02}, /* lcc3 */
316 {0x65, 0x16}, /* lcc4 */
317 {0x66, 0x01}, /* lcc5 */
318 {0x69, 0x02}, /* hv */
319 {0x6b, 0x5a}, /* dbvl */
320 {0x6c, 0x04},
321 {0x6d, 0x55},
322 {0x6e, 0x00},
323 {0x6f, 0x9d},
324 {0x70, 0x21}, /* dnsth */
325 {0x71, 0x78},
326 {0x72, 0x00}, /* poidx */
327 {0x73, 0x01}, /* pckdv */
328 {0x74, 0x3a}, /* xindx */
329 {0x75, 0x35}, /* yindx */
330 {0x76, 0x01},
331 {0x77, 0x02},
332 {0x7a, 0x12}, /* gamma curve */
333 {0x7b, 0x08},
334 {0x7c, 0x16},
335 {0x7d, 0x30},
336 {0x7e, 0x5e},
337 {0x7f, 0x72},
338 {0x80, 0x82},
339 {0x81, 0x8e},
340 {0x82, 0x9a},
341 {0x83, 0xa4},
342 {0x84, 0xac},
343 {0x85, 0xb8},
344 {0x86, 0xc3},
345 {0x87, 0xd6},
346 {0x88, 0xe6},
347 {0x89, 0xf2},
348 {0x8a, 0x03},
349 {0x8c, 0x89}, /* com19 */
350 {0x14, 0x28}, /* com9 */
351 {0x90, 0x7d},
352 {0x91, 0x7b},
353 {0x9d, 0x03}, /* lcc6 */
354 {0x9e, 0x04}, /* lcc7 */
355 {0x9f, 0x7a},
356 {0xa0, 0x79},
357 {0xa1, 0x40}, /* aechm */
358 {0xa4, 0x50}, /* com21 */
359 {0xa5, 0x68}, /* com26 */
360 {0xa6, 0x4a}, /* AWB green */
361 {0xa8, 0xc1}, /* refa8 */
362 {0xa9, 0xef}, /* refa9 */
363 {0xaa, 0x92},
364 {0xab, 0x04},
365 {0xac, 0x80}, /* black level control */
366 {0xad, 0x80},
367 {0xae, 0x80},
368 {0xaf, 0x80},
369 {0xb2, 0xf2},
370 {0xb3, 0x20},
371 {0xb4, 0x20}, /* ctrlb4 */
372 {0xb5, 0x00},
373 {0xb6, 0xaf},
374 {0xbb, 0xae},
375 {0xbc, 0x7f}, /* ADC channel offsets */
376 {0xdb, 0x7f},
377 {0xbe, 0x7f},
378 {0xbf, 0x7f},
379 {0xc0, 0xe2},
380 {0xc1, 0xc0},
381 {0xc2, 0x01},
382 {0xc3, 0x4e},
383 {0xc6, 0x85},
384 {0xc7, 0x80}, /* com24 */
385 {0xc9, 0xe0},
386 {0xca, 0xe8},
387 {0xcb, 0xf0},
388 {0xcc, 0xd8},
389 {0xcd, 0xf1},
390 {0x4f, 0x98}, /* matrix */
391 {0x50, 0x98},
392 {0x51, 0x00},
393 {0x52, 0x28},
394 {0x53, 0x70},
395 {0x54, 0x98},
396 {0x58, 0x1a},
397 {0xff, 0x41}, /* read 41, write ff 00 */
398 {0x41, 0x40}, /* com16 */
399
400 {0xc5, 0x03}, /* 60 Hz banding filter */
401 {0x6a, 0x02}, /* 50 Hz banding filter */
402
403 {0x12, 0x62}, /* com7 - 30fps VGA YUV */
404 {0x36, 0xfa}, /* aref3 */
405 {0x69, 0x0a}, /* hv */
406 {0x8c, 0x89}, /* com22 */
407 {0x14, 0x28}, /* com9 */
408 {0x3e, 0x0c},
409 {0x41, 0x40}, /* com16 */
410 {0x72, 0x00},
411 {0x73, 0x00},
412 {0x74, 0x3a},
413 {0x75, 0x35},
414 {0x76, 0x01},
415 {0xc7, 0x80},
416 {0x03, 0x12}, /* vref */
417 {0x17, 0x16}, /* hstart */
418 {0x18, 0x02}, /* hstop */
419 {0x19, 0x01}, /* vstrt */
420 {0x1a, 0x3d}, /* vstop */
421 {0x32, 0xff}, /* href */
422 {0xc0, 0xaa},
423};
424
425static const u8 bridge_init_2[][2] = {
426 {0x94, 0xaa},
427 {0xf1, 0x60},
428 {0xe5, 0x04},
429 {0xc0, 0x50},
430 {0xc1, 0x3c},
431 {0x8c, 0x00},
432 {0x8d, 0x1c},
433 {0x34, 0x05},
434
435 {0xc2, 0x0c},
436 {0xc3, 0xf9},
437 {0xda, 0x01},
438 {0x50, 0x00},
439 {0x51, 0xa0},
440 {0x52, 0x3c},
441 {0x53, 0x00},
442 {0x54, 0x00},
443 {0x55, 0x00},
444 {0x57, 0x00},
445 {0x5c, 0x00},
446 {0x5a, 0xa0},
447 {0x5b, 0x78},
448 {0x35, 0x02},
449 {0xd9, 0x10},
450 {0x94, 0x11},
451};
452
453static const u8 sensor_init_2[][2] = {
454 {0x3b, 0xc4},
455 {0x1e, 0x04}, /* mvfp */
456 {0x13, 0xe0}, /* com8 */
457 {0x00, 0x00}, /* gain */
458 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
459 {0x11, 0x03}, /* clkrc */
460 {0x6b, 0x5a}, /* dblv */
461 {0x6a, 0x05},
462 {0xc5, 0x07},
463 {0xa2, 0x4b},
464 {0xa3, 0x3e},
465 {0x2d, 0x00},
466 {0xff, 0x42}, /* read 42, write ff 00 */
467 {0x42, 0xc0}, /* com17 */
468 {0x2d, 0x00},
469 {0xff, 0x42}, /* read 42, write ff 00 */
470 {0x42, 0xc1}, /* com17 */
471/* sharpness */
472 {0x3f, 0x01},
473 {0xff, 0x42}, /* read 42, write ff 00 */
474 {0x42, 0xc1}, /* com17 */
475/* saturation */
476 {0x4f, 0x98}, /* matrix */
477 {0x50, 0x98},
478 {0x51, 0x00},
479 {0x52, 0x28},
480 {0x53, 0x70},
481 {0x54, 0x98},
482 {0x58, 0x1a},
483 {0xff, 0x41}, /* read 41, write ff 00 */
484 {0x41, 0x40}, /* com16 */
485/* contrast */
486 {0x56, 0x40},
487/* brightness */
488 {0x55, 0x8f},
489/* expo */
490 {0x10, 0x25}, /* aech - exposure high bits */
491 {0xff, 0x13}, /* read 13, write ff 00 */
492 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
493};
494
495static const u8 sensor_start_1_vga[][2] = { /* same for qvga */
496 {0x12, 0x62}, /* com7 - 30fps VGA YUV */
497 {0x36, 0xfa}, /* aref3 */
498 {0x69, 0x0a}, /* hv */
499 {0x8c, 0x89}, /* com22 */
500 {0x14, 0x28}, /* com9 */
501 {0x3e, 0x0c}, /* com14 */
502 {0x41, 0x40}, /* com16 */
503 {0x72, 0x00},
504 {0x73, 0x00},
505 {0x74, 0x3a},
506 {0x75, 0x35},
507 {0x76, 0x01},
508 {0xc7, 0x80}, /* com24 */
509 {0x03, 0x12}, /* vref */
510 {0x17, 0x16}, /* hstart */
511 {0x18, 0x02}, /* hstop */
512 {0x19, 0x01}, /* vstrt */
513 {0x1a, 0x3d}, /* vstop */
514 {0x32, 0xff}, /* href */
515 {0xc0, 0xaa},
516};
517
518static const u8 sensor_start_1_svga[][2] = {
519 {0x12, 0x02}, /* com7 - YUYV - VGA 15 full resolution */
520 {0x36, 0xf8}, /* aref3 */
521 {0x69, 0x02}, /* hv */
522 {0x8c, 0x0d}, /* com22 */
523 {0x3e, 0x0c}, /* com14 */
524 {0x41, 0x40}, /* com16 */
525 {0x72, 0x00},
526 {0x73, 0x01},
527 {0x74, 0x3a},
528 {0x75, 0x35},
529 {0x76, 0x01},
530 {0xc7, 0x80}, /* com24 */
531 {0x03, 0x1b}, /* vref */
532 {0x17, 0x1d}, /* hstart */
533 {0x18, 0xbd}, /* hstop */
534 {0x19, 0x01}, /* vstrt */
535 {0x1a, 0x81}, /* vstop */
536 {0x32, 0xff}, /* href */
537 {0xc0, 0xe2},
538};
539
540static const u8 sensor_start_1_xga[][2] = {
541 {0x12, 0x02}, /* com7 */
542 {0x36, 0xf8}, /* aref3 */
543 {0x69, 0x02}, /* hv */
544 {0x8c, 0x89}, /* com22 */
545 {0x14, 0x28}, /* com9 */
546 {0x3e, 0x0c}, /* com14 */
547 {0x41, 0x40}, /* com16 */
548 {0x72, 0x00},
549 {0x73, 0x01},
550 {0x74, 0x3a},
551 {0x75, 0x35},
552 {0x76, 0x01},
553 {0xc7, 0x80}, /* com24 */
554 {0x03, 0x1b}, /* vref */
555 {0x17, 0x1d}, /* hstart */
556 {0x18, 0xbd}, /* hstop */
557 {0x19, 0x01}, /* vstrt */
558 {0x1a, 0x81}, /* vstop */
559 {0x32, 0xff}, /* href */
560 {0xc0, 0xe2},
561};
562
563static const u8 sensor_start_1_sxga[][2] = {
564 {0x12, 0x02}, /* com7 */
565 {0x36, 0xf8}, /* aref3 */
566 {0x69, 0x02}, /* hv */
567 {0x8c, 0x89}, /* com22 */
568 {0x14, 0x28}, /* com9 */
569 {0x3e, 0x0c}, /* com14 */
570 {0x41, 0x40}, /* com16 */
571 {0x72, 0x00},
572 {0x73, 0x01},
573 {0x74, 0x3a},
574 {0x75, 0x35},
575 {0x76, 0x01},
576 {0xc7, 0x80}, /* com24 */
577 {0x03, 0x1b}, /* vref */
578 {0x17, 0x1d}, /* hstart */
579 {0x18, 0x02}, /* hstop */
580 {0x19, 0x01}, /* vstrt */
581 {0x1a, 0x81}, /* vstop */
582 {0x32, 0xff}, /* href */
583 {0xc0, 0xe2},
584};
585
586static const u8 bridge_start_qvga[][2] = {
587 {0x94, 0xaa},
588 {0xf1, 0x60},
589 {0xe5, 0x04},
590 {0xc0, 0x50},
591 {0xc1, 0x3c},
592 {0x8c, 0x00},
593 {0x8d, 0x1c},
594 {0x34, 0x05},
595
596 {0xc2, 0x4c},
597 {0xc3, 0xf9},
598 {0xda, 0x00},
599 {0x50, 0x00},
600 {0x51, 0xa0},
601 {0x52, 0x78},
602 {0x53, 0x00},
603 {0x54, 0x00},
604 {0x55, 0x00},
605 {0x57, 0x00},
606 {0x5c, 0x00},
607 {0x5a, 0x50},
608 {0x5b, 0x3c},
609 {0x35, 0x02},
610 {0xd9, 0x10},
611 {0x94, 0x11},
612};
613
614static const u8 bridge_start_vga[][2] = {
615 {0x94, 0xaa},
616 {0xf1, 0x60},
617 {0xe5, 0x04},
618 {0xc0, 0x50},
619 {0xc1, 0x3c},
620 {0x8c, 0x00},
621 {0x8d, 0x1c},
622 {0x34, 0x05},
623 {0xc2, 0x0c},
624 {0xc3, 0xf9},
625 {0xda, 0x01},
626 {0x50, 0x00},
627 {0x51, 0xa0},
628 {0x52, 0x3c},
629 {0x53, 0x00},
630 {0x54, 0x00},
631 {0x55, 0x00},
632 {0x57, 0x00},
633 {0x5c, 0x00},
634 {0x5a, 0xa0},
635 {0x5b, 0x78},
636 {0x35, 0x02},
637 {0xd9, 0x10},
638 {0x94, 0x11},
639};
640
641static const u8 bridge_start_svga[][2] = {
642 {0x94, 0xaa},
643 {0xf1, 0x60},
644 {0xe5, 0x04},
645 {0xc0, 0xa0},
646 {0xc1, 0x80},
647 {0x8c, 0x00},
648 {0x8d, 0x1c},
649 {0x34, 0x05},
650 {0xc2, 0x4c},
651 {0xc3, 0xf9},
652 {0x50, 0x00},
653 {0x51, 0x40},
654 {0x52, 0x00},
655 {0x53, 0x00},
656 {0x54, 0x00},
657 {0x55, 0x88},
658 {0x57, 0x00},
659 {0x5c, 0x00},
660 {0x5a, 0xc8},
661 {0x5b, 0x96},
662 {0x35, 0x02},
663 {0xd9, 0x10},
664 {0xda, 0x00},
665 {0x94, 0x11},
666};
667
668static const u8 bridge_start_xga[][2] = {
669 {0x94, 0xaa},
670 {0xf1, 0x60},
671 {0xe5, 0x04},
672 {0xc0, 0xa0},
673 {0xc1, 0x80},
674 {0x8c, 0x00},
675 {0x8d, 0x1c},
676 {0x34, 0x05},
677 {0xc2, 0x4c},
678 {0xc3, 0xf9},
679 {0x50, 0x00},
680 {0x51, 0x40},
681 {0x52, 0x00},
682 {0x53, 0x00},
683 {0x54, 0x00},
684 {0x55, 0x88},
685 {0x57, 0x00},
686 {0x5c, 0x01},
687 {0x5a, 0x00},
688 {0x5b, 0xc0},
689 {0x35, 0x02},
690 {0xd9, 0x10},
691 {0xda, 0x01},
692 {0x94, 0x11},
693};
694
695static const u8 bridge_start_sxga[][2] = {
696 {0x94, 0xaa},
697 {0xf1, 0x60},
698 {0xe5, 0x04},
699 {0xc0, 0xa0},
700 {0xc1, 0x80},
701 {0x8c, 0x00},
702 {0x8d, 0x1c},
703 {0x34, 0x05},
704 {0xc2, 0x0c},
705 {0xc3, 0xf9},
706 {0xda, 0x00},
707 {0x35, 0x02},
708 {0xd9, 0x10},
709 {0x94, 0x11},
710};
711
712static const u8 sensor_start_2_qvga[][2] = {
713 {0x3b, 0xe4}, /* com11 - night mode 1/4 frame rate */
714 {0x1e, 0x04}, /* mvfp */
715 {0x13, 0xe0}, /* com8 */
716 {0x00, 0x00},
717 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
718 {0x11, 0x01}, /* clkrc */
719 {0x6b, 0x5a}, /* dblv */
720 {0x6a, 0x02}, /* 50 Hz banding filter */
721 {0xc5, 0x03}, /* 60 Hz banding filter */
722 {0xa2, 0x96}, /* bd50 */
723 {0xa3, 0x7d}, /* bd60 */
724
725 {0xff, 0x13}, /* read 13, write ff 00 */
726 {0x13, 0xe7},
727 {0x3a, 0x80}, /* tslb - yuyv */
728};
729
730static const u8 sensor_start_2_vga[][2] = {
731 {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
732 {0x1e, 0x04}, /* mvfp */
733 {0x13, 0xe0}, /* com8 */
734 {0x00, 0x00},
735 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
736 {0x11, 0x03}, /* clkrc */
737 {0x6b, 0x5a}, /* dblv */
738 {0x6a, 0x05}, /* 50 Hz banding filter */
739 {0xc5, 0x07}, /* 60 Hz banding filter */
740 {0xa2, 0x4b}, /* bd50 */
741 {0xa3, 0x3e}, /* bd60 */
742
743 {0x2d, 0x00}, /* advfl */
744};
745
746static const u8 sensor_start_2_svga[][2] = { /* same for xga */
747 {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
748 {0x1e, 0x04}, /* mvfp */
749 {0x13, 0xe0}, /* com8 */
750 {0x00, 0x00},
751 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
752 {0x11, 0x01}, /* clkrc */
753 {0x6b, 0x5a}, /* dblv */
754 {0x6a, 0x0c}, /* 50 Hz banding filter */
755 {0xc5, 0x0f}, /* 60 Hz banding filter */
756 {0xa2, 0x4e}, /* bd50 */
757 {0xa3, 0x41}, /* bd60 */
758};
759
760static const u8 sensor_start_2_sxga[][2] = {
761 {0x13, 0xe0}, /* com8 */
762 {0x00, 0x00},
763 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
764 {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
765 {0x1e, 0x04}, /* mvfp */
766 {0x11, 0x01}, /* clkrc */
767 {0x6b, 0x5a}, /* dblv */
768 {0x6a, 0x0c}, /* 50 Hz banding filter */
769 {0xc5, 0x0f}, /* 60 Hz banding filter */
770 {0xa2, 0x4e}, /* bd50 */
771 {0xa3, 0x41}, /* bd60 */
772};
773
774static void reg_w_i(struct gspca_dev *gspca_dev, u16 reg, u8 val)
775{
776 struct usb_device *udev = gspca_dev->dev;
777 int ret;
778
779 if (gspca_dev->usb_err < 0)
780 return;
781 gspca_dev->usb_buf[0] = val;
782 ret = usb_control_msg(udev,
783 usb_sndctrlpipe(udev, 0),
784 0x01,
785 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
786 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
787 if (ret < 0) {
Jean-François Moine0b656322010-09-13 05:19:58 -0300788 err("reg_w failed %d", ret);
Jean-Francois Moinec52af792010-01-07 05:18:16 -0300789 gspca_dev->usb_err = ret;
790 }
791}
792
793static void reg_w(struct gspca_dev *gspca_dev, u16 reg, u8 val)
794{
795 PDEBUG(D_USBO, "reg_w [%04x] = %02x", reg, val);
796 reg_w_i(gspca_dev, reg, val);
797}
798
799static u8 reg_r(struct gspca_dev *gspca_dev, u16 reg)
800{
801 struct usb_device *udev = gspca_dev->dev;
802 int ret;
803
804 if (gspca_dev->usb_err < 0)
805 return 0;
806 ret = usb_control_msg(udev,
807 usb_rcvctrlpipe(udev, 0),
808 0x01,
809 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
810 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
811 PDEBUG(D_USBI, "reg_r [%04x] -> %02x", reg, gspca_dev->usb_buf[0]);
812 if (ret < 0) {
Jean-François Moine0b656322010-09-13 05:19:58 -0300813 err("reg_r err %d", ret);
Jean-Francois Moinec52af792010-01-07 05:18:16 -0300814 gspca_dev->usb_err = ret;
815 }
816 return gspca_dev->usb_buf[0];
817}
818
819static int sccb_check_status(struct gspca_dev *gspca_dev)
820{
821 u8 data;
822 int i;
823
824 for (i = 0; i < 5; i++) {
825 data = reg_r(gspca_dev, OV534_REG_STATUS);
826
827 switch (data) {
828 case 0x00:
829 return 1;
830 case 0x04:
831 return 0;
832 case 0x03:
833 break;
834 default:
835 PDEBUG(D_USBI|D_USBO,
836 "sccb status 0x%02x, attempt %d/5",
837 data, i + 1);
838 }
839 }
840 return 0;
841}
842
843static void sccb_write(struct gspca_dev *gspca_dev, u8 reg, u8 val)
844{
845 PDEBUG(D_USBO, "sccb_write [%02x] = %02x", reg, val);
846 reg_w_i(gspca_dev, OV534_REG_SUBADDR, reg);
847 reg_w_i(gspca_dev, OV534_REG_WRITE, val);
848 reg_w_i(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
849
850 if (!sccb_check_status(gspca_dev))
Jean-François Moine0b656322010-09-13 05:19:58 -0300851 err("sccb_write failed");
Jean-Francois Moinec52af792010-01-07 05:18:16 -0300852}
853
854static u8 sccb_read(struct gspca_dev *gspca_dev, u16 reg)
855{
856 reg_w(gspca_dev, OV534_REG_SUBADDR, reg);
857 reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
858 if (!sccb_check_status(gspca_dev))
Jean-François Moine0b656322010-09-13 05:19:58 -0300859 err("sccb_read failed 1");
Jean-Francois Moinec52af792010-01-07 05:18:16 -0300860
861 reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
862 if (!sccb_check_status(gspca_dev))
Jean-François Moine0b656322010-09-13 05:19:58 -0300863 err("sccb_read failed 2");
Jean-Francois Moinec52af792010-01-07 05:18:16 -0300864
865 return reg_r(gspca_dev, OV534_REG_READ);
866}
867
868/* output a bridge sequence (reg - val) */
869static void reg_w_array(struct gspca_dev *gspca_dev,
870 const u8 (*data)[2], int len)
871{
872 while (--len >= 0) {
873 reg_w(gspca_dev, (*data)[0], (*data)[1]);
874 data++;
875 }
876}
877
878/* output a sensor sequence (reg - val) */
879static void sccb_w_array(struct gspca_dev *gspca_dev,
880 const u8 (*data)[2], int len)
881{
882 while (--len >= 0) {
883 if ((*data)[0] != 0xff) {
884 sccb_write(gspca_dev, (*data)[0], (*data)[1]);
885 } else {
886 sccb_read(gspca_dev, (*data)[1]);
887 sccb_write(gspca_dev, 0xff, 0x00);
888 }
889 data++;
890 }
891}
892
893/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7.
894 * (direction and output)? */
895static void set_led(struct gspca_dev *gspca_dev, int status)
896{
897 u8 data;
898
899 PDEBUG(D_CONF, "led status: %d", status);
900
901 data = reg_r(gspca_dev, 0x21);
902 data |= 0x80;
903 reg_w(gspca_dev, 0x21, data);
904
905 data = reg_r(gspca_dev, 0x23);
906 if (status)
907 data |= 0x80;
908 else
909 data &= ~0x80;
910
911 reg_w(gspca_dev, 0x23, data);
912
913 if (!status) {
914 data = reg_r(gspca_dev, 0x21);
915 data &= ~0x80;
916 reg_w(gspca_dev, 0x21, data);
917 }
918}
919
920static void setbrightness(struct gspca_dev *gspca_dev)
921{
922 struct sd *sd = (struct sd *) gspca_dev;
923 u8 val;
924
925 val = sd->brightness;
926 if (val < 8)
927 val = 15 - val; /* f .. 8 */
928 else
929 val = val - 8; /* 0 .. 7 */
930 sccb_write(gspca_dev, 0x55, /* brtn - brightness adjustment */
931 0x0f | (val << 4));
932}
933
934static void setcontrast(struct gspca_dev *gspca_dev)
935{
936 struct sd *sd = (struct sd *) gspca_dev;
937
938 sccb_write(gspca_dev, 0x56, /* cnst1 - contrast 1 ctrl coeff */
939 sd->contrast << 4);
940}
941
942static void setautogain(struct gspca_dev *gspca_dev)
943{
944 struct sd *sd = (struct sd *) gspca_dev;
945 u8 val;
946
947/*fixme: should adjust agc/awb/aec by different controls */
948 val = sd->autogain;
949 val = sccb_read(gspca_dev, 0x13); /* com8 */
950 sccb_write(gspca_dev, 0xff, 0x00);
951 if (sd->autogain)
952 val |= 0x05; /* agc & aec */
953 else
954 val &= 0xfa;
955 sccb_write(gspca_dev, 0x13, val);
956}
957
958static void setexposure(struct gspca_dev *gspca_dev)
959{
960 struct sd *sd = (struct sd *) gspca_dev;
961 u8 val;
962 static const u8 expo[4] = {0x00, 0x25, 0x38, 0x5e};
963
964 sccb_write(gspca_dev, 0x10, /* aec[9:2] */
965 expo[sd->exposure]);
966
967 val = sccb_read(gspca_dev, 0x13); /* com8 */
968 sccb_write(gspca_dev, 0xff, 0x00);
969 sccb_write(gspca_dev, 0x13, val);
970
971 val = sccb_read(gspca_dev, 0xa1); /* aech */
972 sccb_write(gspca_dev, 0xff, 0x00);
973 sccb_write(gspca_dev, 0xa1, val & 0xe0); /* aec[15:10] = 0 */
974}
975
976static void setsharpness(struct gspca_dev *gspca_dev)
977{
978 struct sd *sd = (struct sd *) gspca_dev;
979 s8 val;
980
981 val = sd->sharpness;
982 if (val < 0) { /* auto */
983 val = sccb_read(gspca_dev, 0x42); /* com17 */
984 sccb_write(gspca_dev, 0xff, 0x00);
985 sccb_write(gspca_dev, 0x42, val | 0x40);
986 /* Edge enhancement strength auto adjust */
987 return;
988 }
989 if (val != 0)
990 val = 1 << (val - 1);
991 sccb_write(gspca_dev, 0x3f, /* edge - edge enhance. factor */
992 val);
993 val = sccb_read(gspca_dev, 0x42); /* com17 */
994 sccb_write(gspca_dev, 0xff, 0x00);
995 sccb_write(gspca_dev, 0x42, val & 0xbf);
996}
997
998static void setsatur(struct gspca_dev *gspca_dev)
999{
1000 struct sd *sd = (struct sd *) gspca_dev;
1001 u8 val1, val2, val3;
1002 static const u8 matrix[5][2] = {
1003 {0x14, 0x38},
1004 {0x1e, 0x54},
1005 {0x28, 0x70},
1006 {0x32, 0x8c},
1007 {0x48, 0x90}
1008 };
1009
1010 val1 = matrix[sd->satur][0];
1011 val2 = matrix[sd->satur][1];
1012 val3 = val1 + val2;
1013 sccb_write(gspca_dev, 0x4f, val3); /* matrix coeff */
1014 sccb_write(gspca_dev, 0x50, val3);
1015 sccb_write(gspca_dev, 0x51, 0x00);
1016 sccb_write(gspca_dev, 0x52, val1);
1017 sccb_write(gspca_dev, 0x53, val2);
1018 sccb_write(gspca_dev, 0x54, val3);
1019 sccb_write(gspca_dev, 0x58, 0x1a); /* mtxs - coeff signs */
1020
1021 val1 = sccb_read(gspca_dev, 0x41); /* com16 */
1022 sccb_write(gspca_dev, 0xff, 0x00);
1023 sccb_write(gspca_dev, 0x41, val1);
1024}
1025
1026static void setfreq(struct gspca_dev *gspca_dev)
1027{
1028 struct sd *sd = (struct sd *) gspca_dev;
1029 u8 val;
1030
1031 val = sccb_read(gspca_dev, 0x13); /* com8 */
1032 sccb_write(gspca_dev, 0xff, 0x00);
1033 if (sd->freq == 0) {
1034 sccb_write(gspca_dev, 0x13, val & 0xdf);
1035 return;
1036 }
1037 sccb_write(gspca_dev, 0x13, val | 0x20);
1038
1039 val = sccb_read(gspca_dev, 0x42); /* com17 */
1040 sccb_write(gspca_dev, 0xff, 0x00);
1041 if (sd->freq == 1)
1042 val |= 0x01;
1043 else
1044 val &= 0xfe;
1045 sccb_write(gspca_dev, 0x42, val);
1046}
1047
1048/* this function is called at probe time */
1049static int sd_config(struct gspca_dev *gspca_dev,
1050 const struct usb_device_id *id)
1051{
1052 struct sd *sd = (struct sd *) gspca_dev;
1053 struct cam *cam;
1054
1055 cam = &gspca_dev->cam;
1056
1057 cam->cam_mode = ov965x_mode;
1058 cam->nmodes = ARRAY_SIZE(ov965x_mode);
1059
1060 sd->brightness = BRIGHTNESS_DEF;
1061 sd->contrast = CONTRAST_DEF;
1062#if AUTOGAIN_DEF != 0
1063 sd->autogain = AUTOGAIN_DEF;
1064 gspca_dev->ctrl_inac |= (1 << EXPO_IDX);
1065#endif
1066#if EXPO_DEF != 0
1067 sd->exposure = EXPO_DEF;
1068#endif
1069#if SHARPNESS_DEF != 0
1070 sd->sharpness = SHARPNESS_DEF;
1071#endif
1072 sd->satur = SATUR_DEF;
1073 sd->freq = FREQ_DEF;
1074
1075 return 0;
1076}
1077
1078/* this function is called at probe and resume time */
1079static int sd_init(struct gspca_dev *gspca_dev)
1080{
1081 u16 sensor_id;
1082
1083 /* reset bridge */
1084 reg_w(gspca_dev, 0xe7, 0x3a);
1085 reg_w(gspca_dev, 0xe0, 0x08);
1086 msleep(100);
1087
1088 /* initialize the sensor address */
1089 reg_w(gspca_dev, OV534_REG_ADDRESS, 0x60);
1090
1091 /* reset sensor */
1092 sccb_write(gspca_dev, 0x12, 0x80);
1093 msleep(10);
1094
1095 /* probe the sensor */
1096 sccb_read(gspca_dev, 0x0a);
1097 sensor_id = sccb_read(gspca_dev, 0x0a) << 8;
1098 sccb_read(gspca_dev, 0x0b);
1099 sensor_id |= sccb_read(gspca_dev, 0x0b);
1100 PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id);
1101
1102 /* initialize */
1103 reg_w_array(gspca_dev, bridge_init,
1104 ARRAY_SIZE(bridge_init));
1105 sccb_w_array(gspca_dev, sensor_init,
1106 ARRAY_SIZE(sensor_init));
1107 reg_w_array(gspca_dev, bridge_init_2,
1108 ARRAY_SIZE(bridge_init_2));
1109 sccb_w_array(gspca_dev, sensor_init_2,
1110 ARRAY_SIZE(sensor_init_2));
1111 reg_w(gspca_dev, 0xe0, 0x00);
1112 reg_w(gspca_dev, 0xe0, 0x01);
1113 set_led(gspca_dev, 0);
1114 reg_w(gspca_dev, 0xe0, 0x00);
1115
Jean-Francois Moine4b27d072010-01-13 15:40:36 -03001116 return gspca_dev->usb_err;
Jean-Francois Moinec52af792010-01-07 05:18:16 -03001117}
1118
1119static int sd_start(struct gspca_dev *gspca_dev)
1120{
1121 switch (gspca_dev->curr_mode) {
1122 case QVGA_MODE: /* 320x240 */
1123 sccb_w_array(gspca_dev, sensor_start_1_vga,
1124 ARRAY_SIZE(sensor_start_1_vga));
1125 reg_w_array(gspca_dev, bridge_start_qvga,
1126 ARRAY_SIZE(bridge_start_qvga));
1127 sccb_w_array(gspca_dev, sensor_start_2_qvga,
1128 ARRAY_SIZE(sensor_start_2_qvga));
1129 break;
1130 case VGA_MODE: /* 640x480 */
1131 sccb_w_array(gspca_dev, sensor_start_1_vga,
1132 ARRAY_SIZE(sensor_start_1_vga));
1133 reg_w_array(gspca_dev, bridge_start_vga,
1134 ARRAY_SIZE(bridge_start_vga));
1135 sccb_w_array(gspca_dev, sensor_start_2_vga,
1136 ARRAY_SIZE(sensor_start_2_vga));
1137 break;
1138 case SVGA_MODE: /* 800x600 */
1139 sccb_w_array(gspca_dev, sensor_start_1_svga,
1140 ARRAY_SIZE(sensor_start_1_svga));
1141 reg_w_array(gspca_dev, bridge_start_svga,
1142 ARRAY_SIZE(bridge_start_svga));
1143 sccb_w_array(gspca_dev, sensor_start_2_svga,
1144 ARRAY_SIZE(sensor_start_2_svga));
1145 break;
1146 case XGA_MODE: /* 1024x768 */
1147 sccb_w_array(gspca_dev, sensor_start_1_xga,
1148 ARRAY_SIZE(sensor_start_1_xga));
1149 reg_w_array(gspca_dev, bridge_start_xga,
1150 ARRAY_SIZE(bridge_start_xga));
1151 sccb_w_array(gspca_dev, sensor_start_2_svga,
1152 ARRAY_SIZE(sensor_start_2_svga));
1153 break;
1154 default:
1155/* case SXGA_MODE: * 1280x1024 */
1156 sccb_w_array(gspca_dev, sensor_start_1_sxga,
1157 ARRAY_SIZE(sensor_start_1_sxga));
1158 reg_w_array(gspca_dev, bridge_start_sxga,
1159 ARRAY_SIZE(bridge_start_sxga));
1160 sccb_w_array(gspca_dev, sensor_start_2_sxga,
1161 ARRAY_SIZE(sensor_start_2_sxga));
1162 break;
1163 }
1164 setfreq(gspca_dev);
1165 setautogain(gspca_dev);
1166 setbrightness(gspca_dev);
1167 setcontrast(gspca_dev);
1168 setexposure(gspca_dev);
1169 setsharpness(gspca_dev);
1170 setsatur(gspca_dev);
1171
1172 reg_w(gspca_dev, 0xe0, 0x00);
1173 reg_w(gspca_dev, 0xe0, 0x00);
1174 set_led(gspca_dev, 1);
Jean-Francois Moine4b27d072010-01-13 15:40:36 -03001175 return gspca_dev->usb_err;
Jean-Francois Moinec52af792010-01-07 05:18:16 -03001176}
1177
1178static void sd_stopN(struct gspca_dev *gspca_dev)
1179{
1180 reg_w(gspca_dev, 0xe0, 0x01);
1181 set_led(gspca_dev, 0);
1182 reg_w(gspca_dev, 0xe0, 0x00);
1183}
1184
1185/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
1186#define UVC_STREAM_EOH (1 << 7)
1187#define UVC_STREAM_ERR (1 << 6)
1188#define UVC_STREAM_STI (1 << 5)
1189#define UVC_STREAM_RES (1 << 4)
1190#define UVC_STREAM_SCR (1 << 3)
1191#define UVC_STREAM_PTS (1 << 2)
1192#define UVC_STREAM_EOF (1 << 1)
1193#define UVC_STREAM_FID (1 << 0)
1194
1195static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1196 u8 *data, int len)
1197{
1198 struct sd *sd = (struct sd *) gspca_dev;
1199 __u32 this_pts;
1200 u8 this_fid;
1201 int remaining_len = len;
1202
1203 do {
1204 len = min(remaining_len, 2040);
1205
1206 /* Payloads are prefixed with a UVC-style header. We
1207 consider a frame to start when the FID toggles, or the PTS
1208 changes. A frame ends when EOF is set, and we've received
1209 the correct number of bytes. */
1210
1211 /* Verify UVC header. Header length is always 12 */
1212 if (data[0] != 12 || len < 12) {
1213 PDEBUG(D_PACK, "bad header");
1214 goto discard;
1215 }
1216
1217 /* Check errors */
1218 if (data[1] & UVC_STREAM_ERR) {
1219 PDEBUG(D_PACK, "payload error");
1220 goto discard;
1221 }
1222
1223 /* Extract PTS and FID */
1224 if (!(data[1] & UVC_STREAM_PTS)) {
1225 PDEBUG(D_PACK, "PTS not present");
1226 goto discard;
1227 }
1228 this_pts = (data[5] << 24) | (data[4] << 16)
1229 | (data[3] << 8) | data[2];
1230 this_fid = data[1] & UVC_STREAM_FID;
1231
1232 /* If PTS or FID has changed, start a new frame. */
1233 if (this_pts != sd->last_pts || this_fid != sd->last_fid) {
1234 if (gspca_dev->last_packet_type == INTER_PACKET)
1235 gspca_frame_add(gspca_dev, LAST_PACKET,
1236 NULL, 0);
1237 sd->last_pts = this_pts;
1238 sd->last_fid = this_fid;
1239 gspca_frame_add(gspca_dev, FIRST_PACKET,
1240 data + 12, len - 12);
1241 /* If this packet is marked as EOF, end the frame */
1242 } else if (data[1] & UVC_STREAM_EOF) {
1243 sd->last_pts = 0;
1244 gspca_frame_add(gspca_dev, LAST_PACKET,
1245 data + 12, len - 12);
1246 } else {
1247
1248 /* Add the data from this payload */
1249 gspca_frame_add(gspca_dev, INTER_PACKET,
1250 data + 12, len - 12);
1251 }
1252
1253 /* Done this payload */
1254 goto scan_next;
1255
1256discard:
1257 /* Discard data until a new frame starts. */
1258 gspca_dev->last_packet_type = DISCARD_PACKET;
1259
1260scan_next:
1261 remaining_len -= len;
1262 data += len;
1263 } while (remaining_len > 0);
1264}
1265
1266/* controls */
1267static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1268{
1269 struct sd *sd = (struct sd *) gspca_dev;
1270
1271 sd->brightness = val;
1272 if (gspca_dev->streaming)
1273 setbrightness(gspca_dev);
Jean-Francois Moine4b27d072010-01-13 15:40:36 -03001274 return gspca_dev->usb_err;
Jean-Francois Moinec52af792010-01-07 05:18:16 -03001275}
1276
1277static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1278{
1279 struct sd *sd = (struct sd *) gspca_dev;
1280
1281 *val = sd->brightness;
1282 return 0;
1283}
1284
1285static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1286{
1287 struct sd *sd = (struct sd *) gspca_dev;
1288
1289 sd->contrast = val;
1290 if (gspca_dev->streaming)
1291 setcontrast(gspca_dev);
Jean-Francois Moine4b27d072010-01-13 15:40:36 -03001292 return gspca_dev->usb_err;
Jean-Francois Moinec52af792010-01-07 05:18:16 -03001293}
1294
1295static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1296{
1297 struct sd *sd = (struct sd *) gspca_dev;
1298
1299 *val = sd->contrast;
1300 return 0;
1301}
1302
1303static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1304{
1305 struct sd *sd = (struct sd *) gspca_dev;
1306
1307 sd->autogain = val;
1308
1309 if (gspca_dev->streaming) {
1310 if (val)
1311 gspca_dev->ctrl_inac |= (1 << EXPO_IDX);
1312 else
1313 gspca_dev->ctrl_inac &= ~(1 << EXPO_IDX);
1314 setautogain(gspca_dev);
1315 }
Jean-Francois Moine4b27d072010-01-13 15:40:36 -03001316 return gspca_dev->usb_err;
Jean-Francois Moinec52af792010-01-07 05:18:16 -03001317}
1318
1319static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1320{
1321 struct sd *sd = (struct sd *) gspca_dev;
1322
1323 *val = sd->autogain;
1324 return 0;
1325}
1326
1327static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1328{
1329 struct sd *sd = (struct sd *) gspca_dev;
1330
1331 sd->exposure = val;
1332 if (gspca_dev->streaming)
1333 setexposure(gspca_dev);
Jean-Francois Moine4b27d072010-01-13 15:40:36 -03001334 return gspca_dev->usb_err;
Jean-Francois Moinec52af792010-01-07 05:18:16 -03001335}
1336
1337static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1338{
1339 struct sd *sd = (struct sd *) gspca_dev;
1340
1341 *val = sd->exposure;
1342 return 0;
1343}
1344
1345static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
1346{
1347 struct sd *sd = (struct sd *) gspca_dev;
1348
1349 sd->sharpness = val;
1350 if (gspca_dev->streaming)
1351 setsharpness(gspca_dev);
Jean-Francois Moine4b27d072010-01-13 15:40:36 -03001352 return gspca_dev->usb_err;
Jean-Francois Moinec52af792010-01-07 05:18:16 -03001353}
1354
1355static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
1356{
1357 struct sd *sd = (struct sd *) gspca_dev;
1358
1359 *val = sd->sharpness;
1360 return 0;
1361}
1362
1363static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val)
1364{
1365 struct sd *sd = (struct sd *) gspca_dev;
1366
1367 sd->satur = val;
1368 if (gspca_dev->streaming)
1369 setsatur(gspca_dev);
Jean-Francois Moine4b27d072010-01-13 15:40:36 -03001370 return gspca_dev->usb_err;
Jean-Francois Moinec52af792010-01-07 05:18:16 -03001371}
1372
1373static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val)
1374{
1375 struct sd *sd = (struct sd *) gspca_dev;
1376
1377 *val = sd->satur;
1378 return 0;
1379}
1380static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1381{
1382 struct sd *sd = (struct sd *) gspca_dev;
1383
1384 sd->freq = val;
1385 if (gspca_dev->streaming)
1386 setfreq(gspca_dev);
Jean-Francois Moine4b27d072010-01-13 15:40:36 -03001387 return gspca_dev->usb_err;
Jean-Francois Moinec52af792010-01-07 05:18:16 -03001388}
1389
1390static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1391{
1392 struct sd *sd = (struct sd *) gspca_dev;
1393
1394 *val = sd->freq;
1395 return 0;
1396}
1397
1398static int sd_querymenu(struct gspca_dev *gspca_dev,
1399 struct v4l2_querymenu *menu)
1400{
1401 switch (menu->id) {
1402 case V4L2_CID_POWER_LINE_FREQUENCY:
1403 switch (menu->index) {
1404 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1405 strcpy((char *) menu->name, "NoFliker");
1406 return 0;
1407 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1408 strcpy((char *) menu->name, "50 Hz");
1409 return 0;
1410 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1411 strcpy((char *) menu->name, "60 Hz");
1412 return 0;
1413 }
1414 break;
1415 }
1416 return -EINVAL;
1417}
1418
1419/* sub-driver description */
1420static const struct sd_desc sd_desc = {
1421 .name = MODULE_NAME,
1422 .ctrls = sd_ctrls,
1423 .nctrls = ARRAY_SIZE(sd_ctrls),
1424 .config = sd_config,
1425 .init = sd_init,
1426 .start = sd_start,
1427 .stopN = sd_stopN,
1428 .pkt_scan = sd_pkt_scan,
1429 .querymenu = sd_querymenu,
1430};
1431
1432/* -- module initialisation -- */
1433static const __devinitdata struct usb_device_id device_table[] = {
1434 {USB_DEVICE(0x06f8, 0x3003)},
1435 {}
1436};
1437
1438MODULE_DEVICE_TABLE(usb, device_table);
1439
1440/* -- device connect -- */
1441static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id)
1442{
1443 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1444 THIS_MODULE);
1445}
1446
1447static struct usb_driver sd_driver = {
1448 .name = MODULE_NAME,
1449 .id_table = device_table,
1450 .probe = sd_probe,
1451 .disconnect = gspca_disconnect,
1452#ifdef CONFIG_PM
1453 .suspend = gspca_suspend,
1454 .resume = gspca_resume,
1455#endif
1456};
1457
1458/* -- module insert / remove -- */
1459static int __init sd_mod_init(void)
1460{
Jean-François Moine54826432010-09-13 04:53:03 -03001461 return usb_register(&sd_driver);
Jean-Francois Moinec52af792010-01-07 05:18:16 -03001462}
1463
1464static void __exit sd_mod_exit(void)
1465{
1466 usb_deregister(&sd_driver);
Jean-Francois Moinec52af792010-01-07 05:18:16 -03001467}
1468
1469module_init(sd_mod_init);
1470module_exit(sd_mod_exit);