V4L/DVB (13869): gspca - sn9c20x: Cleanup code.
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / media / video / gspca / ov534.c
CommitLineData
fbb4c6d2 1/*
2ce949ec 2 * ov534 gspca driver
189d92af 3 *
fbb4c6d2 4 * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it>
0f7a50b2 5 * Copyright (C) 2008 Jim Paris <jim@jtan.com>
2ce949ec 6 * Copyright (C) 2009 Jean-Francois Moine http://moinejf.free.fr
fbb4c6d2
AO
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 *
189d92af 12 * PS3 Eye camera enhanced by Richard Kaswy http://kaswy.free.fr
b014f94b
JFM
13 * PS3 Eye camera, brightness, contrast, hue, AWB control added
14 * by Max Thrun <bear24rw@gmail.com>
189d92af 15 *
fbb4c6d2
AO
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 */
30
31#define MODULE_NAME "ov534"
32
33#include "gspca.h"
34
2ce949ec 35#define OV534_REG_ADDRESS 0xf1 /* sensor address */
fbb4c6d2
AO
36#define OV534_REG_SUBADDR 0xf2
37#define OV534_REG_WRITE 0xf3
38#define OV534_REG_READ 0xf4
39#define OV534_REG_OPERATION 0xf5
40#define OV534_REG_STATUS 0xf6
41
42#define OV534_OP_WRITE_3 0x37
43#define OV534_OP_WRITE_2 0x33
44#define OV534_OP_READ_2 0xf9
45
46#define CTRL_TIMEOUT 500
47
48MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
49MODULE_DESCRIPTION("GSPCA/OV534 USB Camera Driver");
50MODULE_LICENSE("GPL");
51
fbb4c6d2
AO
52/* specific webcam descriptor */
53struct sd {
54 struct gspca_dev gspca_dev; /* !! must be the first item */
8c252050 55 __u32 last_pts;
84fbdf87
JFM
56 u16 last_fid;
57 u8 frame_rate;
b014f94b
JFM
58
59 u8 brightness;
60 u8 contrast;
189d92af
JFM
61 u8 gain;
62 u8 exposure;
63 u8 redblc;
64 u8 blueblc;
b014f94b 65 u8 hue;
189d92af 66 u8 autogain;
b014f94b 67 u8 awb;
c22c4a20 68 s8 sharpness;
189d92af
JFM
69 u8 hflip;
70 u8 vflip;
c22c4a20
JFM
71 u8 satur;
72 u8 lightfreq;
2ce949ec
JFM
73
74 u8 sensor;
75#define SENSOR_OV772X 0
76#define SENSOR_OV965X 1
fbb4c6d2
AO
77};
78
79/* V4L2 controls supported by the driver */
189d92af
JFM
80static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
81static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
82static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
83static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
84static int sd_setredblc(struct gspca_dev *gspca_dev, __s32 val);
85static int sd_getredblc(struct gspca_dev *gspca_dev, __s32 *val);
86static int sd_setblueblc(struct gspca_dev *gspca_dev, __s32 val);
87static int sd_getblueblc(struct gspca_dev *gspca_dev, __s32 *val);
88static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
89static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
90static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
91static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
92static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
93static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
94static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
95static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
b014f94b
JFM
96static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val);
97static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val);
98static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val);
99static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val);
100static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
101static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
102static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
103static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
c22c4a20
JFM
104static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val);
105static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val);
106static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
107static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
189d92af 108
7e64dc4c 109static const struct ctrl sd_ctrls_ov772x[] = {
2d19a2c1 110 { /* 0 */
b014f94b
JFM
111 {
112 .id = V4L2_CID_BRIGHTNESS,
113 .type = V4L2_CTRL_TYPE_INTEGER,
114 .name = "Brightness",
115 .minimum = 0,
116 .maximum = 255,
117 .step = 1,
c22c4a20
JFM
118#define BRIGHTNESS_77_DEF 20
119 .default_value = BRIGHTNESS_77_DEF,
b014f94b
JFM
120 },
121 .set = sd_setbrightness,
122 .get = sd_getbrightness,
123 },
2d19a2c1 124 { /* 1 */
b014f94b
JFM
125 {
126 .id = V4L2_CID_CONTRAST,
127 .type = V4L2_CTRL_TYPE_INTEGER,
128 .name = "Contrast",
129 .minimum = 0,
130 .maximum = 255,
131 .step = 1,
c22c4a20
JFM
132#define CONTRAST_77_DEF 37
133 .default_value = CONTRAST_77_DEF,
b014f94b
JFM
134 },
135 .set = sd_setcontrast,
136 .get = sd_getcontrast,
137 },
2d19a2c1 138 { /* 2 */
189d92af
JFM
139 {
140 .id = V4L2_CID_GAIN,
141 .type = V4L2_CTRL_TYPE_INTEGER,
142 .name = "Main Gain",
143 .minimum = 0,
144 .maximum = 63,
145 .step = 1,
146#define GAIN_DEF 20
147 .default_value = GAIN_DEF,
148 },
149 .set = sd_setgain,
150 .get = sd_getgain,
151 },
2d19a2c1 152 { /* 3 */
189d92af
JFM
153 {
154 .id = V4L2_CID_EXPOSURE,
155 .type = V4L2_CTRL_TYPE_INTEGER,
156 .name = "Exposure",
157 .minimum = 0,
158 .maximum = 255,
159 .step = 1,
c22c4a20
JFM
160#define EXPO_77_DEF 120
161 .default_value = EXPO_77_DEF,
189d92af
JFM
162 },
163 .set = sd_setexposure,
164 .get = sd_getexposure,
165 },
2d19a2c1 166 { /* 4 */
189d92af
JFM
167 {
168 .id = V4L2_CID_RED_BALANCE,
169 .type = V4L2_CTRL_TYPE_INTEGER,
170 .name = "Red Balance",
171 .minimum = 0,
172 .maximum = 255,
173 .step = 1,
174#define RED_BALANCE_DEF 128
175 .default_value = RED_BALANCE_DEF,
176 },
177 .set = sd_setredblc,
178 .get = sd_getredblc,
179 },
2d19a2c1 180 { /* 5 */
189d92af
JFM
181 {
182 .id = V4L2_CID_BLUE_BALANCE,
183 .type = V4L2_CTRL_TYPE_INTEGER,
184 .name = "Blue Balance",
185 .minimum = 0,
186 .maximum = 255,
187 .step = 1,
188#define BLUE_BALANCE_DEF 128
189 .default_value = BLUE_BALANCE_DEF,
190 },
191 .set = sd_setblueblc,
192 .get = sd_getblueblc,
193 },
2d19a2c1 194 { /* 6 */
b014f94b
JFM
195 {
196 .id = V4L2_CID_HUE,
197 .type = V4L2_CTRL_TYPE_INTEGER,
198 .name = "Hue",
199 .minimum = 0,
200 .maximum = 255,
201 .step = 1,
202#define HUE_DEF 143
203 .default_value = HUE_DEF,
204 },
205 .set = sd_sethue,
206 .get = sd_gethue,
207 },
2d19a2c1 208 { /* 7 */
189d92af
JFM
209 {
210 .id = V4L2_CID_AUTOGAIN,
211 .type = V4L2_CTRL_TYPE_BOOLEAN,
212 .name = "Autogain",
213 .minimum = 0,
214 .maximum = 1,
215 .step = 1,
c22c4a20
JFM
216#define AUTOGAIN_77_DEF 0
217 .default_value = AUTOGAIN_77_DEF,
189d92af
JFM
218 },
219 .set = sd_setautogain,
220 .get = sd_getautogain,
221 },
c22c4a20 222#define AWB_77_IDX 8
2d19a2c1 223 { /* 8 */
b014f94b
JFM
224 {
225 .id = V4L2_CID_AUTO_WHITE_BALANCE,
226 .type = V4L2_CTRL_TYPE_BOOLEAN,
227 .name = "Auto White Balance",
228 .minimum = 0,
229 .maximum = 1,
230 .step = 1,
231#define AWB_DEF 0
232 .default_value = AWB_DEF,
233 },
234 .set = sd_setawb,
235 .get = sd_getawb,
236 },
2d19a2c1 237 { /* 9 */
189d92af
JFM
238 {
239 .id = V4L2_CID_SHARPNESS,
240 .type = V4L2_CTRL_TYPE_INTEGER,
241 .name = "Sharpness",
242 .minimum = 0,
243 .maximum = 63,
244 .step = 1,
c22c4a20
JFM
245#define SHARPNESS_77_DEF 0
246 .default_value = SHARPNESS_77_DEF,
189d92af
JFM
247 },
248 .set = sd_setsharpness,
249 .get = sd_getsharpness,
250 },
2d19a2c1 251 { /* 10 */
189d92af
JFM
252 {
253 .id = V4L2_CID_HFLIP,
254 .type = V4L2_CTRL_TYPE_BOOLEAN,
255 .name = "HFlip",
256 .minimum = 0,
257 .maximum = 1,
258 .step = 1,
259#define HFLIP_DEF 0
260 .default_value = HFLIP_DEF,
261 },
262 .set = sd_sethflip,
263 .get = sd_gethflip,
264 },
2d19a2c1 265 { /* 11 */
189d92af
JFM
266 {
267 .id = V4L2_CID_VFLIP,
268 .type = V4L2_CTRL_TYPE_BOOLEAN,
269 .name = "VFlip",
270 .minimum = 0,
271 .maximum = 1,
272 .step = 1,
273#define VFLIP_DEF 0
274 .default_value = VFLIP_DEF,
275 },
276 .set = sd_setvflip,
277 .get = sd_getvflip,
278 },
279};
7e64dc4c 280static const struct ctrl sd_ctrls_ov965x[] = {
c22c4a20
JFM
281 { /* 0 */
282 {
283 .id = V4L2_CID_BRIGHTNESS,
284 .type = V4L2_CTRL_TYPE_INTEGER,
285 .name = "Brightness",
286 .minimum = 0,
287 .maximum = 15,
288 .step = 1,
289#define BRIGHTNESS_96_DEF 7
290 .default_value = BRIGHTNESS_96_DEF,
291 },
292 .set = sd_setbrightness,
293 .get = sd_getbrightness,
294 },
295 { /* 1 */
296 {
297 .id = V4L2_CID_CONTRAST,
298 .type = V4L2_CTRL_TYPE_INTEGER,
299 .name = "Contrast",
300 .minimum = 0,
301 .maximum = 15,
302 .step = 1,
303#define CONTRAST_96_DEF 3
304 .default_value = CONTRAST_96_DEF,
305 },
306 .set = sd_setcontrast,
307 .get = sd_getcontrast,
308 },
309 { /* 2 */
310 {
311 .id = V4L2_CID_AUTOGAIN,
312 .type = V4L2_CTRL_TYPE_BOOLEAN,
313 .name = "Autogain",
314 .minimum = 0,
315 .maximum = 1,
316 .step = 1,
317#define AUTOGAIN_96_DEF 1
318 .default_value = AUTOGAIN_96_DEF,
319 },
320 .set = sd_setautogain,
321 .get = sd_getautogain,
322 },
323#define EXPO_96_IDX 3
324 { /* 3 */
325 {
326 .id = V4L2_CID_EXPOSURE,
327 .type = V4L2_CTRL_TYPE_INTEGER,
328 .name = "Exposure",
329 .minimum = 0,
330 .maximum = 3,
331 .step = 1,
332#define EXPO_96_DEF 0
333 .default_value = EXPO_96_DEF,
334 },
335 .set = sd_setexposure,
336 .get = sd_getexposure,
337 },
338 { /* 4 */
339 {
340 .id = V4L2_CID_SHARPNESS,
341 .type = V4L2_CTRL_TYPE_INTEGER,
342 .name = "Sharpness",
343 .minimum = -1, /* -1 = auto */
344 .maximum = 4,
345 .step = 1,
346#define SHARPNESS_96_DEF -1
347 .default_value = SHARPNESS_96_DEF,
348 },
349 .set = sd_setsharpness,
350 .get = sd_getsharpness,
351 },
352 { /* 5 */
353 {
354 .id = V4L2_CID_SATURATION,
355 .type = V4L2_CTRL_TYPE_INTEGER,
356 .name = "Saturation",
357 .minimum = 0,
358 .maximum = 4,
359 .step = 1,
360#define SATUR_DEF 2
361 .default_value = SATUR_DEF,
362 },
363 .set = sd_setsatur,
364 .get = sd_getsatur,
365 },
366 {
367 {
368 .id = V4L2_CID_POWER_LINE_FREQUENCY,
369 .type = V4L2_CTRL_TYPE_MENU,
370 .name = "Light frequency filter",
371 .minimum = 0,
372 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
373 .step = 1,
374#define FREQ_DEF 0
375 .default_value = FREQ_DEF,
376 },
377 .set = sd_setfreq,
378 .get = sd_getfreq,
379 },
fbb4c6d2
AO
380};
381
569691a5 382static const struct v4l2_pix_format ov772x_mode[] = {
189d92af
JFM
383 {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
384 .bytesperline = 320 * 2,
385 .sizeimage = 320 * 240 * 2,
b014f94b 386 .colorspace = V4L2_COLORSPACE_SRGB,
189d92af 387 .priv = 1},
fbb4c6d2
AO
388 {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
389 .bytesperline = 640 * 2,
390 .sizeimage = 640 * 480 * 2,
191d0e7f
JFM
391 .colorspace = V4L2_COLORSPACE_SRGB,
392 .priv = 0},
393};
394
569691a5 395static const struct v4l2_pix_format ov965x_mode[] = {
191d0e7f
JFM
396 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
397 .bytesperline = 320,
398 .sizeimage = 320 * 240 * 3 / 8 + 590,
399 .colorspace = V4L2_COLORSPACE_JPEG,
569691a5 400 .priv = 4},
191d0e7f
JFM
401 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
402 .bytesperline = 640,
403 .sizeimage = 640 * 480 * 3 / 8 + 590,
fbb4c6d2 404 .colorspace = V4L2_COLORSPACE_JPEG,
569691a5
JFM
405 .priv = 3},
406 {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
407 .bytesperline = 800,
408 .sizeimage = 800 * 600 * 3 / 8 + 590,
409 .colorspace = V4L2_COLORSPACE_JPEG,
410 .priv = 2},
411 {1024, 768, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
412 .bytesperline = 1024,
413 .sizeimage = 1024 * 768 * 3 / 8 + 590,
414 .colorspace = V4L2_COLORSPACE_JPEG,
415 .priv = 1},
416 {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
417 .bytesperline = 1280,
418 .sizeimage = 1280 * 1024 * 3 / 8 + 590,
419 .colorspace = V4L2_COLORSPACE_JPEG,
fbb4c6d2
AO
420 .priv = 0},
421};
c22c4a20 422
189d92af 423static const u8 bridge_init_ov772x[][2] = {
47dfd21f
JP
424 { 0xc2, 0x0c },
425 { 0x88, 0xf8 },
426 { 0xc3, 0x69 },
427 { 0x89, 0xff },
428 { 0x76, 0x03 },
429 { 0x92, 0x01 },
430 { 0x93, 0x18 },
431 { 0x94, 0x10 },
432 { 0x95, 0x10 },
433 { 0xe2, 0x00 },
434 { 0xe7, 0x3e },
435
47dfd21f
JP
436 { 0x96, 0x00 },
437
438 { 0x97, 0x20 },
439 { 0x97, 0x20 },
440 { 0x97, 0x20 },
441 { 0x97, 0x0a },
442 { 0x97, 0x3f },
443 { 0x97, 0x4a },
444 { 0x97, 0x20 },
445 { 0x97, 0x15 },
446 { 0x97, 0x0b },
447
448 { 0x8e, 0x40 },
449 { 0x1f, 0x81 },
450 { 0x34, 0x05 },
451 { 0xe3, 0x04 },
452 { 0x88, 0x00 },
453 { 0x89, 0x00 },
454 { 0x76, 0x00 },
455 { 0xe7, 0x2e },
456 { 0x31, 0xf9 },
457 { 0x25, 0x42 },
458 { 0x21, 0xf0 },
459
460 { 0x1c, 0x00 },
461 { 0x1d, 0x40 },
0f7a50b2
JP
462 { 0x1d, 0x02 }, /* payload size 0x0200 * 4 = 2048 bytes */
463 { 0x1d, 0x00 }, /* payload size */
189d92af 464
5ea9c4de
JP
465 { 0x1d, 0x02 }, /* frame size 0x025800 * 4 = 614400 */
466 { 0x1d, 0x58 }, /* frame size */
467 { 0x1d, 0x00 }, /* frame size */
47dfd21f 468
c06eb619
JP
469 { 0x1c, 0x0a },
470 { 0x1d, 0x08 }, /* turn on UVC header */
471 { 0x1d, 0x0e }, /* .. */
472
47dfd21f
JP
473 { 0x8d, 0x1c },
474 { 0x8e, 0x80 },
475 { 0xe5, 0x04 },
476
477 { 0xc0, 0x50 },
478 { 0xc1, 0x3c },
479 { 0xc2, 0x0c },
480};
189d92af 481static const u8 sensor_init_ov772x[][2] = {
47dfd21f
JP
482 { 0x12, 0x80 },
483 { 0x11, 0x01 },
189d92af
JFM
484/*fixme: better have a delay?*/
485 { 0x11, 0x01 },
486 { 0x11, 0x01 },
487 { 0x11, 0x01 },
488 { 0x11, 0x01 },
489 { 0x11, 0x01 },
490 { 0x11, 0x01 },
491 { 0x11, 0x01 },
492 { 0x11, 0x01 },
493 { 0x11, 0x01 },
494 { 0x11, 0x01 },
47dfd21f
JP
495
496 { 0x3d, 0x03 },
497 { 0x17, 0x26 },
498 { 0x18, 0xa0 },
499 { 0x19, 0x07 },
500 { 0x1a, 0xf0 },
501 { 0x32, 0x00 },
502 { 0x29, 0xa0 },
503 { 0x2c, 0xf0 },
504 { 0x65, 0x20 },
505 { 0x11, 0x01 },
506 { 0x42, 0x7f },
b014f94b 507 { 0x63, 0xaa }, /* AWB - was e0 */
47dfd21f
JP
508 { 0x64, 0xff },
509 { 0x66, 0x00 },
b014f94b 510 { 0x13, 0xf0 }, /* com8 */
47dfd21f
JP
511 { 0x0d, 0x41 },
512 { 0x0f, 0xc5 },
513 { 0x14, 0x11 },
514
515 { 0x22, 0x7f },
516 { 0x23, 0x03 },
517 { 0x24, 0x40 },
518 { 0x25, 0x30 },
519 { 0x26, 0xa1 },
520 { 0x2a, 0x00 },
521 { 0x2b, 0x00 },
522 { 0x6b, 0xaa },
b014f94b 523 { 0x13, 0xff }, /* AWB */
47dfd21f
JP
524
525 { 0x90, 0x05 },
526 { 0x91, 0x01 },
527 { 0x92, 0x03 },
528 { 0x93, 0x00 },
529 { 0x94, 0x60 },
530 { 0x95, 0x3c },
531 { 0x96, 0x24 },
532 { 0x97, 0x1e },
533 { 0x98, 0x62 },
534 { 0x99, 0x80 },
535 { 0x9a, 0x1e },
536 { 0x9b, 0x08 },
537 { 0x9c, 0x20 },
538 { 0x9e, 0x81 },
539
540 { 0xa6, 0x04 },
541 { 0x7e, 0x0c },
542 { 0x7f, 0x16 },
543 { 0x80, 0x2a },
544 { 0x81, 0x4e },
545 { 0x82, 0x61 },
546 { 0x83, 0x6f },
547 { 0x84, 0x7b },
548 { 0x85, 0x86 },
549 { 0x86, 0x8e },
550 { 0x87, 0x97 },
551 { 0x88, 0xa4 },
552 { 0x89, 0xaf },
553 { 0x8a, 0xc5 },
554 { 0x8b, 0xd7 },
555 { 0x8c, 0xe8 },
556 { 0x8d, 0x20 },
557
558 { 0x0c, 0x90 },
559
560 { 0x2b, 0x00 },
561 { 0x22, 0x7f },
562 { 0x23, 0x03 },
563 { 0x11, 0x01 },
564 { 0x0c, 0xd0 },
565 { 0x64, 0xff },
566 { 0x0d, 0x41 },
567
568 { 0x14, 0x41 },
569 { 0x0e, 0xcd },
570 { 0xac, 0xbf },
b014f94b 571 { 0x8e, 0x00 }, /* De-noise threshold */
47dfd21f
JP
572 { 0x0c, 0xd0 }
573};
189d92af
JFM
574static const u8 bridge_start_ov772x_vga[][2] = {
575 {0x1c, 0x00},
576 {0x1d, 0x40},
577 {0x1d, 0x02},
578 {0x1d, 0x00},
579 {0x1d, 0x02},
580 {0x1d, 0x58},
581 {0x1d, 0x00},
582 {0xc0, 0x50},
583 {0xc1, 0x3c},
584};
585static const u8 sensor_start_ov772x_vga[][2] = {
586 {0x12, 0x00},
587 {0x17, 0x26},
588 {0x18, 0xa0},
589 {0x19, 0x07},
590 {0x1a, 0xf0},
591 {0x29, 0xa0},
592 {0x2c, 0xf0},
b014f94b 593 {0x65, 0x20},
189d92af
JFM
594};
595static const u8 bridge_start_ov772x_qvga[][2] = {
596 {0x1c, 0x00},
597 {0x1d, 0x40},
598 {0x1d, 0x02},
599 {0x1d, 0x00},
600 {0x1d, 0x01},
601 {0x1d, 0x4b},
602 {0x1d, 0x00},
603 {0xc0, 0x28},
604 {0xc1, 0x1e},
605};
606static const u8 sensor_start_ov772x_qvga[][2] = {
607 {0x12, 0x40},
608 {0x17, 0x3f},
609 {0x18, 0x50},
610 {0x19, 0x03},
611 {0x1a, 0x78},
612 {0x29, 0x50},
613 {0x2c, 0x78},
b014f94b 614 {0x65, 0x2f},
189d92af 615};
fbb4c6d2 616
2ce949ec
JFM
617static const u8 bridge_init_ov965x[][2] = {
618 {0x88, 0xf8},
619 {0x89, 0xff},
620 {0x76, 0x03},
621 {0x92, 0x03},
622 {0x95, 0x10},
623 {0xe2, 0x00},
624 {0xe7, 0x3e},
625 {0x8d, 0x1c},
626 {0x8e, 0x00},
627 {0x8f, 0x00},
628 {0x1f, 0x00},
629 {0xc3, 0xf9},
630 {0x89, 0xff},
631 {0x88, 0xf8},
632 {0x76, 0x03},
633 {0x92, 0x01},
634 {0x93, 0x18},
635 {0x1c, 0x0a},
636 {0x1d, 0x48},
637 {0xc0, 0x50},
638 {0xc1, 0x3c},
639 {0x34, 0x05},
640 {0xc2, 0x0c},
641 {0xc3, 0xf9},
642 {0x34, 0x05},
643 {0xe7, 0x2e},
644 {0x31, 0xf9},
645 {0x35, 0x02},
646 {0xd9, 0x10},
647 {0x25, 0x42},
648 {0x94, 0x11},
649};
650
651static const u8 sensor_init_ov965x[][2] = {
191d0e7f 652 {0x12, 0x80}, /* com7 - SSCB reset */
2ce949ec
JFM
653 {0x00, 0x00}, /* gain */
654 {0x01, 0x80}, /* blue */
655 {0x02, 0x80}, /* red */
656 {0x03, 0x1b}, /* vref */
657 {0x04, 0x03}, /* com1 - exposure low bits */
658 {0x0b, 0x57}, /* ver */
659 {0x0e, 0x61}, /* com5 */
660 {0x0f, 0x42}, /* com6 */
661 {0x11, 0x00}, /* clkrc */
191d0e7f 662 {0x12, 0x02}, /* com7 - 15fps VGA YUYV */
2ce949ec
JFM
663 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
664 {0x14, 0x28}, /* com9 */
191d0e7f 665 {0x16, 0x24}, /* reg16 */
2ce949ec
JFM
666 {0x17, 0x1d}, /* hstart*/
667 {0x18, 0xbd}, /* hstop */
668 {0x19, 0x01}, /* vstrt */
669 {0x1a, 0x81}, /* vstop*/
670 {0x1e, 0x04}, /* mvfp */
671 {0x24, 0x3c}, /* aew */
672 {0x25, 0x36}, /* aeb */
673 {0x26, 0x71}, /* vpt */
674 {0x27, 0x08}, /* bbias */
675 {0x28, 0x08}, /* gbbias */
676 {0x29, 0x15}, /* gr com */
191d0e7f
JFM
677 {0x2a, 0x00}, /* exhch */
678 {0x2b, 0x00}, /* exhcl */
2ce949ec
JFM
679 {0x2c, 0x08}, /* rbias */
680 {0x32, 0xff}, /* href */
681 {0x33, 0x00}, /* chlf */
191d0e7f
JFM
682 {0x34, 0x3f}, /* aref1 */
683 {0x35, 0x00}, /* aref2 */
684 {0x36, 0xf8}, /* aref3 */
685 {0x38, 0x72}, /* adc2 */
686 {0x39, 0x57}, /* aref4 */
687 {0x3a, 0x80}, /* tslb - yuyv */
688 {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
2ce949ec 689 {0x3d, 0x99}, /* com13 */
191d0e7f 690 {0x3f, 0xc1}, /* edge */
2ce949ec
JFM
691 {0x40, 0xc0}, /* com15 */
692 {0x41, 0x40}, /* com16 */
191d0e7f
JFM
693 {0x42, 0xc0}, /* com17 */
694 {0x43, 0x0a}, /* rsvd */
2ce949ec
JFM
695 {0x44, 0xf0},
696 {0x45, 0x46},
697 {0x46, 0x62},
698 {0x47, 0x2a},
699 {0x48, 0x3c},
700 {0x4a, 0xfc},
701 {0x4b, 0xfc},
702 {0x4c, 0x7f},
703 {0x4d, 0x7f},
704 {0x4e, 0x7f},
191d0e7f 705 {0x4f, 0x98}, /* matrix */
2ce949ec
JFM
706 {0x50, 0x98},
707 {0x51, 0x00},
708 {0x52, 0x28},
709 {0x53, 0x70},
710 {0x54, 0x98},
191d0e7f
JFM
711 {0x58, 0x1a}, /* matrix coef sign */
712 {0x59, 0x85}, /* AWB control */
2ce949ec
JFM
713 {0x5a, 0xa9},
714 {0x5b, 0x64},
715 {0x5c, 0x84},
716 {0x5d, 0x53},
717 {0x5e, 0x0e},
191d0e7f
JFM
718 {0x5f, 0xf0}, /* AWB blue limit */
719 {0x60, 0xf0}, /* AWB red limit */
720 {0x61, 0xf0}, /* AWB green limit */
2ce949ec
JFM
721 {0x62, 0x00}, /* lcc1 */
722 {0x63, 0x00}, /* lcc2 */
723 {0x64, 0x02}, /* lcc3 */
724 {0x65, 0x16}, /* lcc4 */
725 {0x66, 0x01}, /* lcc5 */
726 {0x69, 0x02}, /* hv */
727 {0x6b, 0x5a}, /* dbvl */
728 {0x6c, 0x04},
729 {0x6d, 0x55},
730 {0x6e, 0x00},
731 {0x6f, 0x9d},
191d0e7f 732 {0x70, 0x21}, /* dnsth */
2ce949ec 733 {0x71, 0x78},
191d0e7f
JFM
734 {0x72, 0x00}, /* poidx */
735 {0x73, 0x01}, /* pckdv */
736 {0x74, 0x3a}, /* xindx */
737 {0x75, 0x35}, /* yindx */
2ce949ec
JFM
738 {0x76, 0x01},
739 {0x77, 0x02},
191d0e7f 740 {0x7a, 0x12}, /* gamma curve */
2ce949ec
JFM
741 {0x7b, 0x08},
742 {0x7c, 0x16},
743 {0x7d, 0x30},
744 {0x7e, 0x5e},
745 {0x7f, 0x72},
746 {0x80, 0x82},
747 {0x81, 0x8e},
748 {0x82, 0x9a},
749 {0x83, 0xa4},
750 {0x84, 0xac},
751 {0x85, 0xb8},
752 {0x86, 0xc3},
753 {0x87, 0xd6},
754 {0x88, 0xe6},
755 {0x89, 0xf2},
756 {0x8a, 0x03},
191d0e7f 757 {0x8c, 0x89}, /* com19 */
2ce949ec
JFM
758 {0x14, 0x28}, /* com9 */
759 {0x90, 0x7d},
760 {0x91, 0x7b},
191d0e7f
JFM
761 {0x9d, 0x03}, /* lcc6 */
762 {0x9e, 0x04}, /* lcc7 */
2ce949ec
JFM
763 {0x9f, 0x7a},
764 {0xa0, 0x79},
765 {0xa1, 0x40}, /* aechm */
191d0e7f 766 {0xa4, 0x50}, /* com21 */
2ce949ec 767 {0xa5, 0x68}, /* com26 */
191d0e7f
JFM
768 {0xa6, 0x4a}, /* AWB green */
769 {0xa8, 0xc1}, /* refa8 */
770 {0xa9, 0xef}, /* refa9 */
2ce949ec
JFM
771 {0xaa, 0x92},
772 {0xab, 0x04},
191d0e7f 773 {0xac, 0x80}, /* black level control */
2ce949ec
JFM
774 {0xad, 0x80},
775 {0xae, 0x80},
776 {0xaf, 0x80},
777 {0xb2, 0xf2},
778 {0xb3, 0x20},
191d0e7f 779 {0xb4, 0x20}, /* ctrlb4 */
2ce949ec
JFM
780 {0xb5, 0x00},
781 {0xb6, 0xaf},
782 {0xbb, 0xae},
191d0e7f 783 {0xbc, 0x7f}, /* ADC channel offsets */
2ce949ec
JFM
784 {0xdb, 0x7f},
785 {0xbe, 0x7f},
786 {0xbf, 0x7f},
787 {0xc0, 0xe2},
788 {0xc1, 0xc0},
789 {0xc2, 0x01},
790 {0xc3, 0x4e},
791 {0xc6, 0x85},
191d0e7f 792 {0xc7, 0x80}, /* com24 */
2ce949ec
JFM
793 {0xc9, 0xe0},
794 {0xca, 0xe8},
795 {0xcb, 0xf0},
796 {0xcc, 0xd8},
797 {0xcd, 0xf1},
c22c4a20 798 {0x4f, 0x98}, /* matrix */
2ce949ec
JFM
799 {0x50, 0x98},
800 {0x51, 0x00},
801 {0x52, 0x28},
802 {0x53, 0x70},
803 {0x54, 0x98},
804 {0x58, 0x1a},
805 {0xff, 0x41}, /* read 41, write ff 00 */
806 {0x41, 0x40}, /* com16 */
c22c4a20 807
191d0e7f
JFM
808 {0xc5, 0x03}, /* 60 Hz banding filter */
809 {0x6a, 0x02}, /* 50 Hz banding filter */
2ce949ec 810
191d0e7f
JFM
811 {0x12, 0x62}, /* com7 - 30fps VGA YUV */
812 {0x36, 0xfa}, /* aref3 */
2ce949ec
JFM
813 {0x69, 0x0a}, /* hv */
814 {0x8c, 0x89}, /* com22 */
815 {0x14, 0x28}, /* com9 */
816 {0x3e, 0x0c},
817 {0x41, 0x40}, /* com16 */
818 {0x72, 0x00},
819 {0x73, 0x00},
820 {0x74, 0x3a},
821 {0x75, 0x35},
822 {0x76, 0x01},
823 {0xc7, 0x80},
824 {0x03, 0x12}, /* vref */
825 {0x17, 0x16}, /* hstart */
826 {0x18, 0x02}, /* hstop */
827 {0x19, 0x01}, /* vstrt */
828 {0x1a, 0x3d}, /* vstop */
829 {0x32, 0xff}, /* href */
830 {0xc0, 0xaa},
831};
832
833static const u8 bridge_init_ov965x_2[][2] = {
834 {0x94, 0xaa},
835 {0xf1, 0x60},
836 {0xe5, 0x04},
837 {0xc0, 0x50},
838 {0xc1, 0x3c},
839 {0x8c, 0x00},
840 {0x8d, 0x1c},
841 {0x34, 0x05},
842
843 {0xc2, 0x0c},
844 {0xc3, 0xf9},
845 {0xda, 0x01},
846 {0x50, 0x00},
847 {0x51, 0xa0},
848 {0x52, 0x3c},
849 {0x53, 0x00},
850 {0x54, 0x00},
c22c4a20
JFM
851 {0x55, 0x00},
852 {0x57, 0x00},
2ce949ec
JFM
853 {0x5c, 0x00},
854 {0x5a, 0xa0},
855 {0x5b, 0x78},
856 {0x35, 0x02},
857 {0xd9, 0x10},
858 {0x94, 0x11},
859};
860
861static const u8 sensor_init_ov965x_2[][2] = {
862 {0x3b, 0xc4},
863 {0x1e, 0x04}, /* mvfp */
864 {0x13, 0xe0}, /* com8 */
865 {0x00, 0x00}, /* gain */
866 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
867 {0x11, 0x03}, /* clkrc */
868 {0x6b, 0x5a}, /* dblv */
869 {0x6a, 0x05},
870 {0xc5, 0x07},
871 {0xa2, 0x4b},
872 {0xa3, 0x3e},
873 {0x2d, 0x00},
874 {0xff, 0x42}, /* read 42, write ff 00 */
c22c4a20 875 {0x42, 0xc0}, /* com17 */
2ce949ec
JFM
876 {0x2d, 0x00},
877 {0xff, 0x42}, /* read 42, write ff 00 */
c22c4a20
JFM
878 {0x42, 0xc1}, /* com17 */
879/* sharpness */
2ce949ec
JFM
880 {0x3f, 0x01},
881 {0xff, 0x42}, /* read 42, write ff 00 */
c22c4a20
JFM
882 {0x42, 0xc1}, /* com17 */
883/* saturation */
884 {0x4f, 0x98}, /* matrix */
2ce949ec
JFM
885 {0x50, 0x98},
886 {0x51, 0x00},
887 {0x52, 0x28},
888 {0x53, 0x70},
889 {0x54, 0x98},
890 {0x58, 0x1a},
891 {0xff, 0x41}, /* read 41, write ff 00 */
892 {0x41, 0x40}, /* com16 */
c22c4a20 893/* contrast */
2ce949ec 894 {0x56, 0x40},
c22c4a20 895/* brightness */
2ce949ec 896 {0x55, 0x8f},
c22c4a20 897/* expo */
2ce949ec
JFM
898 {0x10, 0x25}, /* aech - exposure high bits */
899 {0xff, 0x13}, /* read 13, write ff 00 */
900 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
901};
902
569691a5 903static const u8 sensor_start_ov965x_1_vga[][2] = { /* same for qvga */
191d0e7f
JFM
904 {0x12, 0x62}, /* com7 - 30fps VGA YUV */
905 {0x36, 0xfa}, /* aref3 */
906 {0x69, 0x0a}, /* hv */
907 {0x8c, 0x89}, /* com22 */
908 {0x14, 0x28}, /* com9 */
909 {0x3e, 0x0c}, /* com14 */
910 {0x41, 0x40}, /* com16 */
911 {0x72, 0x00},
912 {0x73, 0x00},
913 {0x74, 0x3a},
914 {0x75, 0x35},
915 {0x76, 0x01},
916 {0xc7, 0x80}, /* com24 */
917 {0x03, 0x12}, /* vref */
918 {0x17, 0x16}, /* hstart */
919 {0x18, 0x02}, /* hstop */
920 {0x19, 0x01}, /* vstrt */
921 {0x1a, 0x3d}, /* vstop */
922 {0x32, 0xff}, /* href */
923 {0xc0, 0xaa},
191d0e7f
JFM
924};
925
569691a5
JFM
926static const u8 sensor_start_ov965x_1_svga[][2] = {
927 {0x12, 0x02}, /* com7 - YUYV - VGA 15 full resolution */
928 {0x36, 0xf8}, /* aref3 */
929 {0x69, 0x02}, /* hv */
930 {0x8c, 0x0d}, /* com22 */
931 {0x3e, 0x0c}, /* com14 */
932 {0x41, 0x40}, /* com16 */
933 {0x72, 0x00},
934 {0x73, 0x01},
935 {0x74, 0x3a},
936 {0x75, 0x35},
937 {0x76, 0x01},
938 {0xc7, 0x80}, /* com24 */
939 {0x03, 0x1b}, /* vref */
940 {0x17, 0x1d}, /* hstart */
941 {0x18, 0xbd}, /* hstop */
942 {0x19, 0x01}, /* vstrt */
943 {0x1a, 0x81}, /* vstop */
944 {0x32, 0xff}, /* href */
945 {0xc0, 0xe2},
569691a5
JFM
946};
947
948static const u8 sensor_start_ov965x_1_xga[][2] = {
949 {0x12, 0x02}, /* com7 */
950 {0x36, 0xf8}, /* aref3 */
951 {0x69, 0x02}, /* hv */
952 {0x8c, 0x89}, /* com22 */
953 {0x14, 0x28}, /* com9 */
954 {0x3e, 0x0c}, /* com14 */
955 {0x41, 0x40}, /* com16 */
956 {0x72, 0x00},
957 {0x73, 0x01},
958 {0x74, 0x3a},
959 {0x75, 0x35},
960 {0x76, 0x01},
961 {0xc7, 0x80}, /* com24 */
962 {0x03, 0x1b}, /* vref */
963 {0x17, 0x1d}, /* hstart */
964 {0x18, 0xbd}, /* hstop */
965 {0x19, 0x01}, /* vstrt */
966 {0x1a, 0x81}, /* vstop */
967 {0x32, 0xff}, /* href */
968 {0xc0, 0xe2},
569691a5
JFM
969};
970
971static const u8 sensor_start_ov965x_1_sxga[][2] = {
972 {0x12, 0x02}, /* com7 */
973 {0x36, 0xf8}, /* aref3 */
974 {0x69, 0x02}, /* hv */
975 {0x8c, 0x89}, /* com22 */
976 {0x14, 0x28}, /* com9 */
977 {0x3e, 0x0c}, /* com14 */
978 {0x41, 0x40}, /* com16 */
979 {0x72, 0x00},
980 {0x73, 0x01},
981 {0x74, 0x3a},
982 {0x75, 0x35},
983 {0x76, 0x01},
984 {0xc7, 0x80}, /* com24 */
985 {0x03, 0x1b}, /* vref */
986 {0x17, 0x1d}, /* hstart */
987 {0x18, 0x02}, /* hstop */
988 {0x19, 0x01}, /* vstrt */
989 {0x1a, 0x81}, /* vstop */
990 {0x32, 0xff}, /* href */
991 {0xc0, 0xe2},
569691a5
JFM
992};
993
994static const u8 bridge_start_ov965x_qvga[][2] = {
191d0e7f
JFM
995 {0x94, 0xaa},
996 {0xf1, 0x60},
997 {0xe5, 0x04},
998 {0xc0, 0x50},
999 {0xc1, 0x3c},
1000 {0x8c, 0x00},
1001 {0x8d, 0x1c},
1002 {0x34, 0x05},
569691a5
JFM
1003
1004 {0xc2, 0x4c},
1005 {0xc3, 0xf9},
1006 {0xda, 0x00},
1007 {0x50, 0x00},
1008 {0x51, 0xa0},
1009 {0x52, 0x78},
1010 {0x53, 0x00},
1011 {0x54, 0x00},
1012 {0x55, 0x00},
1013 {0x57, 0x00},
1014 {0x5c, 0x00},
1015 {0x5a, 0x50},
1016 {0x5b, 0x3c},
1017 {0x35, 0x02},
1018 {0xd9, 0x10},
1019 {0x94, 0x11},
191d0e7f
JFM
1020};
1021
1022static const u8 bridge_start_ov965x_vga[][2] = {
569691a5
JFM
1023 {0x94, 0xaa},
1024 {0xf1, 0x60},
1025 {0xe5, 0x04},
1026 {0xc0, 0x50},
1027 {0xc1, 0x3c},
1028 {0x8c, 0x00},
1029 {0x8d, 0x1c},
1030 {0x34, 0x05},
191d0e7f
JFM
1031 {0xc2, 0x0c},
1032 {0xc3, 0xf9},
1033 {0xda, 0x01},
1034 {0x50, 0x00},
1035 {0x51, 0xa0},
1036 {0x52, 0x3c},
1037 {0x53, 0x00},
1038 {0x54, 0x00},
1039 {0x55, 0x00},
1040 {0x57, 0x00},
1041 {0x5c, 0x00},
1042 {0x5a, 0xa0},
1043 {0x5b, 0x78},
1044 {0x35, 0x02},
1045 {0xd9, 0x10},
1046 {0x94, 0x11},
191d0e7f
JFM
1047};
1048
569691a5
JFM
1049static const u8 bridge_start_ov965x_svga[][2] = {
1050 {0x94, 0xaa},
1051 {0xf1, 0x60},
1052 {0xe5, 0x04},
1053 {0xc0, 0xa0},
1054 {0xc1, 0x80},
1055 {0x8c, 0x00},
1056 {0x8d, 0x1c},
1057 {0x34, 0x05},
2ce949ec
JFM
1058 {0xc2, 0x4c},
1059 {0xc3, 0xf9},
1060 {0x50, 0x00},
569691a5
JFM
1061 {0x51, 0x40},
1062 {0x52, 0x00},
2ce949ec
JFM
1063 {0x53, 0x00},
1064 {0x54, 0x00},
569691a5 1065 {0x55, 0x88},
2ce949ec
JFM
1066 {0x57, 0x00},
1067 {0x5c, 0x00},
569691a5
JFM
1068 {0x5a, 0xc8},
1069 {0x5b, 0x96},
1070 {0x35, 0x02},
1071 {0xd9, 0x10},
1072 {0xda, 0x00},
1073 {0x94, 0x11},
569691a5
JFM
1074};
1075
1076static const u8 bridge_start_ov965x_xga[][2] = {
1077 {0x94, 0xaa},
1078 {0xf1, 0x60},
1079 {0xe5, 0x04},
1080 {0xc0, 0xa0},
1081 {0xc1, 0x80},
1082 {0x8c, 0x00},
1083 {0x8d, 0x1c},
1084 {0x34, 0x05},
1085 {0xc2, 0x4c},
1086 {0xc3, 0xf9},
1087 {0x50, 0x00},
1088 {0x51, 0x40},
1089 {0x52, 0x00},
1090 {0x53, 0x00},
1091 {0x54, 0x00},
1092 {0x55, 0x88},
1093 {0x57, 0x00},
1094 {0x5c, 0x01},
1095 {0x5a, 0x00},
1096 {0x5b, 0xc0},
191d0e7f
JFM
1097 {0x35, 0x02},
1098 {0xd9, 0x10},
569691a5 1099 {0xda, 0x01},
2ce949ec
JFM
1100 {0x94, 0x11},
1101};
1102
569691a5
JFM
1103static const u8 bridge_start_ov965x_sxga[][2] = {
1104 {0x94, 0xaa},
1105 {0xf1, 0x60},
1106 {0xe5, 0x04},
1107 {0xc0, 0xa0},
1108 {0xc1, 0x80},
1109 {0x8c, 0x00},
1110 {0x8d, 0x1c},
1111 {0x34, 0x05},
1112 {0xc2, 0x0c},
1113 {0xc3, 0xf9},
1114 {0xda, 0x00},
1115 {0x35, 0x02},
1116 {0xd9, 0x10},
1117 {0x94, 0x11},
569691a5
JFM
1118};
1119
1120static const u8 sensor_start_ov965x_2_qvga[][2] = {
1121 {0x3b, 0xe4}, /* com11 - night mode 1/4 frame rate */
1122 {0x1e, 0x04}, /* mvfp */
1123 {0x13, 0xe0}, /* com8 */
1124 {0x00, 0x00},
1125 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
1126 {0x11, 0x01}, /* clkrc */
1127 {0x6b, 0x5a}, /* dblv */
1128 {0x6a, 0x02}, /* 50 Hz banding filter */
1129 {0xc5, 0x03}, /* 60 Hz banding filter */
1130 {0xa2, 0x96}, /* bd50 */
1131 {0xa3, 0x7d}, /* bd60 */
1132
1133 {0xff, 0x13}, /* read 13, write ff 00 */
1134 {0x13, 0xe7},
1135 {0x3a, 0x80}, /* tslb - yuyv */
569691a5
JFM
1136};
1137
1138static const u8 sensor_start_ov965x_2_vga[][2] = {
191d0e7f
JFM
1139 {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
1140 {0x1e, 0x04}, /* mvfp */
1141 {0x13, 0xe0}, /* com8 */
1142 {0x00, 0x00},
1143 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
1144 {0x11, 0x03}, /* clkrc */
1145 {0x6b, 0x5a}, /* dblv */
1146 {0x6a, 0x05}, /* 50 Hz banding filter */
1147 {0xc5, 0x07}, /* 60 Hz banding filter */
1148 {0xa2, 0x4b}, /* bd50 */
1149 {0xa3, 0x3e}, /* bd60 */
1150
1151 {0x2d, 0x00}, /* advfl */
191d0e7f
JFM
1152};
1153
569691a5
JFM
1154static const u8 sensor_start_ov965x_2_svga[][2] = { /* same for xga */
1155 {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
2ce949ec
JFM
1156 {0x1e, 0x04}, /* mvfp */
1157 {0x13, 0xe0}, /* com8 */
1158 {0x00, 0x00},
1159 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
1160 {0x11, 0x01}, /* clkrc */
1161 {0x6b, 0x5a}, /* dblv */
569691a5
JFM
1162 {0x6a, 0x0c}, /* 50 Hz banding filter */
1163 {0xc5, 0x0f}, /* 60 Hz banding filter */
1164 {0xa2, 0x4e}, /* bd50 */
1165 {0xa3, 0x41}, /* bd60 */
569691a5 1166};
191d0e7f 1167
569691a5
JFM
1168static const u8 sensor_start_ov965x_2_sxga[][2] = {
1169 {0x13, 0xe0}, /* com8 */
1170 {0x00, 0x00},
1171 {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */
1172 {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */
1173 {0x1e, 0x04}, /* mvfp */
1174 {0x11, 0x01}, /* clkrc */
1175 {0x6b, 0x5a}, /* dblv */
1176 {0x6a, 0x0c}, /* 50 Hz banding filter */
1177 {0xc5, 0x0f}, /* 60 Hz banding filter */
1178 {0xa2, 0x4e}, /* bd50 */
1179 {0xa3, 0x41}, /* bd60 */
2ce949ec
JFM
1180};
1181
2ce949ec
JFM
1182static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val)
1183{
1184 struct usb_device *udev = gspca_dev->dev;
1185 int ret;
1186
1187 PDEBUG(D_USBO, "reg=0x%04x, val=0%02x", reg, val);
1188 gspca_dev->usb_buf[0] = val;
1189 ret = usb_control_msg(udev,
1190 usb_sndctrlpipe(udev, 0),
1191 0x01,
1192 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1193 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
1194 if (ret < 0)
1195 PDEBUG(D_ERR, "write failed");
1196}
1197
1198static u8 ov534_reg_read(struct gspca_dev *gspca_dev, u16 reg)
1199{
1200 struct usb_device *udev = gspca_dev->dev;
1201 int ret;
1202
1203 ret = usb_control_msg(udev,
1204 usb_rcvctrlpipe(udev, 0),
1205 0x01,
1206 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1207 0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
1208 PDEBUG(D_USBI, "reg=0x%04x, data=0x%02x", reg, gspca_dev->usb_buf[0]);
1209 if (ret < 0)
1210 PDEBUG(D_ERR, "read failed");
1211 return gspca_dev->usb_buf[0];
1212}
1213
1214/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7.
1215 * (direction and output)? */
1216static void ov534_set_led(struct gspca_dev *gspca_dev, int status)
1217{
1218 u8 data;
1219
1220 PDEBUG(D_CONF, "led status: %d", status);
1221
1222 data = ov534_reg_read(gspca_dev, 0x21);
1223 data |= 0x80;
1224 ov534_reg_write(gspca_dev, 0x21, data);
1225
1226 data = ov534_reg_read(gspca_dev, 0x23);
1227 if (status)
1228 data |= 0x80;
1229 else
1230 data &= ~0x80;
1231
1232 ov534_reg_write(gspca_dev, 0x23, data);
1233
1234 if (!status) {
1235 data = ov534_reg_read(gspca_dev, 0x21);
1236 data &= ~0x80;
1237 ov534_reg_write(gspca_dev, 0x21, data);
1238 }
1239}
1240
1241static int sccb_check_status(struct gspca_dev *gspca_dev)
1242{
1243 u8 data;
1244 int i;
1245
1246 for (i = 0; i < 5; i++) {
1247 data = ov534_reg_read(gspca_dev, OV534_REG_STATUS);
1248
1249 switch (data) {
1250 case 0x00:
1251 return 1;
1252 case 0x04:
1253 return 0;
1254 case 0x03:
1255 break;
1256 default:
1257 PDEBUG(D_ERR, "sccb status 0x%02x, attempt %d/5",
1258 data, i + 1);
1259 }
1260 }
1261 return 0;
1262}
1263
1264static void sccb_reg_write(struct gspca_dev *gspca_dev, u8 reg, u8 val)
1265{
1266 PDEBUG(D_USBO, "reg: 0x%02x, val: 0x%02x", reg, val);
1267 ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg);
1268 ov534_reg_write(gspca_dev, OV534_REG_WRITE, val);
1269 ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
1270
1271 if (!sccb_check_status(gspca_dev))
1272 PDEBUG(D_ERR, "sccb_reg_write failed");
1273}
1274
1275static u8 sccb_reg_read(struct gspca_dev *gspca_dev, u16 reg)
1276{
1277 ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg);
1278 ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
1279 if (!sccb_check_status(gspca_dev))
1280 PDEBUG(D_ERR, "sccb_reg_read failed 1");
1281
1282 ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
1283 if (!sccb_check_status(gspca_dev))
1284 PDEBUG(D_ERR, "sccb_reg_read failed 2");
1285
1286 return ov534_reg_read(gspca_dev, OV534_REG_READ);
1287}
1288
1289/* output a bridge sequence (reg - val) */
1290static void reg_w_array(struct gspca_dev *gspca_dev,
1291 const u8 (*data)[2], int len)
1292{
1293 while (--len >= 0) {
1294 ov534_reg_write(gspca_dev, (*data)[0], (*data)[1]);
1295 data++;
1296 }
1297}
1298
1299/* output a sensor sequence (reg - val) */
1300static void sccb_w_array(struct gspca_dev *gspca_dev,
1301 const u8 (*data)[2], int len)
1302{
1303 while (--len >= 0) {
1304 if ((*data)[0] != 0xff) {
1305 sccb_reg_write(gspca_dev, (*data)[0], (*data)[1]);
1306 } else {
1307 sccb_reg_read(gspca_dev, (*data)[1]);
1308 sccb_reg_write(gspca_dev, 0xff, 0x00);
1309 }
1310 data++;
1311 }
1312}
1313
69f1fe28
JFM
1314/* ov772x specific controls */
1315static void set_frame_rate(struct gspca_dev *gspca_dev)
11d9f25d
JP
1316{
1317 struct sd *sd = (struct sd *) gspca_dev;
189d92af
JFM
1318 int i;
1319 struct rate_s {
1320 u8 fps;
1321 u8 r11;
1322 u8 r0d;
1323 u8 re5;
1324 };
1325 const struct rate_s *r;
1326 static const struct rate_s rate_0[] = { /* 640x480 */
1327 {60, 0x01, 0xc1, 0x04},
1328 {50, 0x01, 0x41, 0x02},
1329 {40, 0x02, 0xc1, 0x04},
1330 {30, 0x04, 0x81, 0x02},
1331 {15, 0x03, 0x41, 0x04},
1332 };
1333 static const struct rate_s rate_1[] = { /* 320x240 */
1334 {125, 0x02, 0x81, 0x02},
1335 {100, 0x02, 0xc1, 0x04},
1336 {75, 0x03, 0xc1, 0x04},
1337 {60, 0x04, 0xc1, 0x04},
1338 {50, 0x02, 0x41, 0x04},
1339 {40, 0x03, 0x41, 0x04},
1340 {30, 0x04, 0x41, 0x04},
1341 };
1342
1343 if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv == 0) {
1344 r = rate_0;
1345 i = ARRAY_SIZE(rate_0);
1346 } else {
1347 r = rate_1;
1348 i = ARRAY_SIZE(rate_1);
1349 }
1350 while (--i > 0) {
1351 if (sd->frame_rate >= r->fps)
1352 break;
1353 r++;
1354 }
1355
1356 sccb_reg_write(gspca_dev, 0x11, r->r11);
1357 sccb_reg_write(gspca_dev, 0x0d, r->r0d);
1358 ov534_reg_write(gspca_dev, 0xe5, r->re5);
1359
1360 PDEBUG(D_PROBE, "frame_rate: %d", r->fps);
1361}
1362
c22c4a20 1363static void setbrightness_77(struct gspca_dev *gspca_dev)
b014f94b
JFM
1364{
1365 struct sd *sd = (struct sd *) gspca_dev;
1366
1367 sccb_reg_write(gspca_dev, 0x9B, sd->brightness);
1368}
1369
c22c4a20 1370static void setcontrast_77(struct gspca_dev *gspca_dev)
b014f94b
JFM
1371{
1372 struct sd *sd = (struct sd *) gspca_dev;
1373
1374 sccb_reg_write(gspca_dev, 0x9C, sd->contrast);
1375}
1376
189d92af
JFM
1377static void setgain(struct gspca_dev *gspca_dev)
1378{
1379 struct sd *sd = (struct sd *) gspca_dev;
1380 u8 val;
11d9f25d 1381
189d92af
JFM
1382 val = sd->gain;
1383 switch (val & 0x30) {
1384 case 0x00:
1385 val &= 0x0f;
11d9f25d 1386 break;
189d92af
JFM
1387 case 0x10:
1388 val &= 0x0f;
1389 val |= 0x30;
11d9f25d 1390 break;
189d92af
JFM
1391 case 0x20:
1392 val &= 0x0f;
1393 val |= 0x70;
11d9f25d 1394 break;
189d92af
JFM
1395 default:
1396/* case 0x30: */
1397 val &= 0x0f;
1398 val |= 0xf0;
11d9f25d
JP
1399 break;
1400 }
189d92af
JFM
1401 sccb_reg_write(gspca_dev, 0x00, val);
1402}
1403
c22c4a20 1404static void setexposure_77(struct gspca_dev *gspca_dev)
189d92af
JFM
1405{
1406 struct sd *sd = (struct sd *) gspca_dev;
1407 u8 val;
1408
1409 val = sd->exposure;
1410 sccb_reg_write(gspca_dev, 0x08, val >> 7);
1411 sccb_reg_write(gspca_dev, 0x10, val << 1);
1412}
1413
1414static void setredblc(struct gspca_dev *gspca_dev)
1415{
1416 struct sd *sd = (struct sd *) gspca_dev;
11d9f25d 1417
189d92af
JFM
1418 sccb_reg_write(gspca_dev, 0x43, sd->redblc);
1419}
1420
1421static void setblueblc(struct gspca_dev *gspca_dev)
1422{
1423 struct sd *sd = (struct sd *) gspca_dev;
1424
1425 sccb_reg_write(gspca_dev, 0x42, sd->blueblc);
1426}
1427
b014f94b
JFM
1428static void sethue(struct gspca_dev *gspca_dev)
1429{
1430 struct sd *sd = (struct sd *) gspca_dev;
1431
1432 sccb_reg_write(gspca_dev, 0x01, sd->hue);
1433}
1434
c22c4a20 1435static void setautogain_77(struct gspca_dev *gspca_dev)
189d92af
JFM
1436{
1437 struct sd *sd = (struct sd *) gspca_dev;
1438
1439 if (sd->autogain) {
1440 sccb_reg_write(gspca_dev, 0x13, 0xf7); /* AGC,AEC,AWB ON */
1441 sccb_reg_write(gspca_dev, 0x64,
1442 sccb_reg_read(gspca_dev, 0x64) | 0x03);
1443 } else {
1444 sccb_reg_write(gspca_dev, 0x13, 0xf0); /* AGC,AEC,AWB OFF */
1445 sccb_reg_write(gspca_dev, 0x64,
1446 sccb_reg_read(gspca_dev, 0x64) & 0xfc);
1447 }
1448}
1449
b014f94b
JFM
1450static void setawb(struct gspca_dev *gspca_dev)
1451{
1452 struct sd *sd = (struct sd *) gspca_dev;
1453
1454 if (sd->awb)
1455 sccb_reg_write(gspca_dev, 0x63, 0xe0); /* AWB on */
1456 else
1457 sccb_reg_write(gspca_dev, 0x63, 0xaa); /* AWB off */
1458}
1459
c22c4a20 1460static void setsharpness_77(struct gspca_dev *gspca_dev)
189d92af
JFM
1461{
1462 struct sd *sd = (struct sd *) gspca_dev;
1463 u8 val;
1464
1465 val = sd->sharpness;
1466 sccb_reg_write(gspca_dev, 0x91, val); /* vga noise */
1467 sccb_reg_write(gspca_dev, 0x8e, val); /* qvga noise */
1468}
1469
1470static void sethflip(struct gspca_dev *gspca_dev)
1471{
1472 struct sd *sd = (struct sd *) gspca_dev;
1473
1474 if (sd->hflip == 0)
1475 sccb_reg_write(gspca_dev, 0x0c,
1476 sccb_reg_read(gspca_dev, 0x0c) | 0x40);
1477 else
1478 sccb_reg_write(gspca_dev, 0x0c,
1479 sccb_reg_read(gspca_dev, 0x0c) & 0xbf);
1480}
1481
1482static void setvflip(struct gspca_dev *gspca_dev)
1483{
1484 struct sd *sd = (struct sd *) gspca_dev;
1485
1486 if (sd->vflip == 0)
1487 sccb_reg_write(gspca_dev, 0x0c,
1488 sccb_reg_read(gspca_dev, 0x0c) | 0x80);
1489 else
1490 sccb_reg_write(gspca_dev, 0x0c,
1491 sccb_reg_read(gspca_dev, 0x0c) & 0x7f);
11d9f25d 1492}
fbb4c6d2 1493
c22c4a20
JFM
1494/* ov965x specific controls */
1495static void setbrightness_96(struct gspca_dev *gspca_dev)
1496{
1497 struct sd *sd = (struct sd *) gspca_dev;
1498 u8 val;
1499
1500 val = sd->brightness;
1501 if (val < 8)
1502 val = 15 - val; /* f .. 8 */
1503 else
1504 val = val - 8; /* 0 .. 7 */
1505 sccb_reg_write(gspca_dev, 0x55, /* brtn - brightness adjustment */
1506 0x0f | (val << 4));
1507}
1508
1509static void setcontrast_96(struct gspca_dev *gspca_dev)
1510{
1511 struct sd *sd = (struct sd *) gspca_dev;
1512
1513 sccb_reg_write(gspca_dev, 0x56, /* cnst1 - contrast 1 ctrl coeff */
1514 sd->contrast << 4);
1515}
1516
1517static void setexposure_96(struct gspca_dev *gspca_dev)
1518{
1519 struct sd *sd = (struct sd *) gspca_dev;
1520 u8 val;
1521 static const u8 expo[4] = {0x00, 0x25, 0x38, 0x5e};
1522
1523 sccb_reg_write(gspca_dev, 0x10, /* aec[9:2] */
1524 expo[sd->exposure]);
1525 val = sccb_reg_read(gspca_dev, 0x13); /* com8 */
1526 sccb_reg_write(gspca_dev, 0xff, 0x00);
1527 sccb_reg_write(gspca_dev, 0x13, val);
1528 val = sccb_reg_read(gspca_dev, 0xa1); /* aech */
1529 sccb_reg_write(gspca_dev, 0xff, 0x00);
1530 sccb_reg_write(gspca_dev, 0xa1, val & 0xe0); /* aec[15:10] = 0 */
1531}
1532
1533static void setsharpness_96(struct gspca_dev *gspca_dev)
1534{
1535 struct sd *sd = (struct sd *) gspca_dev;
bc41797a 1536 s8 val;
c22c4a20
JFM
1537
1538 val = sd->sharpness;
1539 if (val < 0) { /* auto */
1540 val = sccb_reg_read(gspca_dev, 0x42); /* com17 */
1541 sccb_reg_write(gspca_dev, 0xff, 0x00);
1542 sccb_reg_write(gspca_dev, 0x42, val | 0x40);
1543 /* Edge enhancement strength auto adjust */
1544 return;
1545 }
1546 if (val != 0)
1547 val = 1 << (val - 1);
1548 sccb_reg_write(gspca_dev, 0x3f, /* edge - edge enhance. factor */
1549 val);
1550 val = sccb_reg_read(gspca_dev, 0x42); /* com17 */
1551 sccb_reg_write(gspca_dev, 0xff, 0x00);
1552 sccb_reg_write(gspca_dev, 0x42, val & 0xbf);
1553}
1554
1555static void setautogain_96(struct gspca_dev *gspca_dev)
1556{
1557 struct sd *sd = (struct sd *) gspca_dev;
1558 u8 val;
1559
1560/*fixme: should adjust agc/awb/aec by different controls */
1561 val = sd->autogain;
1562 val = sccb_reg_read(gspca_dev, 0x13); /* com8 */
1563 sccb_reg_write(gspca_dev, 0xff, 0x00);
1564 if (sd->autogain)
1565 val |= 0x05; /* agc & aec */
1566 else
1567 val &= 0xfa;
1568 sccb_reg_write(gspca_dev, 0x13, val);
1569}
1570
1571static void setsatur(struct gspca_dev *gspca_dev)
1572{
1573 struct sd *sd = (struct sd *) gspca_dev;
1574 u8 val1, val2, val3;
1575 static const u8 matrix[5][2] = {
1576 {0x14, 0x38},
1577 {0x1e, 0x54},
1578 {0x28, 0x70},
1579 {0x32, 0x8c},
1580 {0x48, 0x90}
1581 };
1582
1583 val1 = matrix[sd->satur][0];
1584 val2 = matrix[sd->satur][1];
1585 val3 = val1 + val2;
1586 sccb_reg_write(gspca_dev, 0x4f, val3); /* matrix coeff */
1587 sccb_reg_write(gspca_dev, 0x50, val3);
1588 sccb_reg_write(gspca_dev, 0x51, 0x00);
1589 sccb_reg_write(gspca_dev, 0x52, val1);
1590 sccb_reg_write(gspca_dev, 0x53, val2);
1591 sccb_reg_write(gspca_dev, 0x54, val3);
1592 sccb_reg_write(gspca_dev, 0x58, 0x1a); /* mtxs - coeff signs */
1593 val1 = sccb_reg_read(gspca_dev, 0x41); /* com16 */
1594 sccb_reg_write(gspca_dev, 0xff, 0x00);
1595 sccb_reg_write(gspca_dev, 0x41, val1);
1596}
1597
1598static void setfreq(struct gspca_dev *gspca_dev)
1599{
1600 struct sd *sd = (struct sd *) gspca_dev;
1601 u8 val;
1602
1603 val = sccb_reg_read(gspca_dev, 0x13); /* com8 */
1604 sccb_reg_write(gspca_dev, 0xff, 0x00);
1605 if (sd->lightfreq == 0) {
1606 sccb_reg_write(gspca_dev, 0x13, val & 0xdf);
1607 return;
1608 }
1609 sccb_reg_write(gspca_dev, 0x13, val | 0x20);
1610
1611 val = sccb_reg_read(gspca_dev, 0x42); /* com17 */
1612 sccb_reg_write(gspca_dev, 0xff, 0x00);
1613 if (sd->lightfreq == 1)
1614 val |= 0x01;
1615 else
1616 val &= 0xfe;
1617 sccb_reg_write(gspca_dev, 0x42, val);
1618}
1619
fbb4c6d2
AO
1620/* this function is called at probe time */
1621static int sd_config(struct gspca_dev *gspca_dev,
1622 const struct usb_device_id *id)
1623{
2ce949ec 1624 struct sd *sd = (struct sd *) gspca_dev;
fbb4c6d2
AO
1625 struct cam *cam;
1626
2ce949ec
JFM
1627 sd->sensor = id->driver_info;
1628
fbb4c6d2
AO
1629 cam = &gspca_dev->cam;
1630
6929dc6b 1631 if (sd->sensor == SENSOR_OV772X) {
569691a5
JFM
1632 cam->cam_mode = ov772x_mode;
1633 cam->nmodes = ARRAY_SIZE(ov772x_mode);
191d0e7f 1634
6929dc6b
JFM
1635 cam->bulk = 1;
1636 cam->bulk_size = 16384;
1637 cam->bulk_nurbs = 2;
191d0e7f 1638 } else { /* ov965x */
569691a5
JFM
1639 cam->cam_mode = ov965x_mode;
1640 cam->nmodes = ARRAY_SIZE(ov965x_mode);
6929dc6b 1641 }
fbb4c6d2 1642
189d92af 1643 sd->frame_rate = 30;
b014f94b 1644
c22c4a20
JFM
1645 if (sd->sensor == SENSOR_OV772X) {
1646 sd->brightness = BRIGHTNESS_77_DEF;
1647 sd->contrast = CONTRAST_77_DEF;
1648 sd->gain = GAIN_DEF;
1649 sd->exposure = EXPO_77_DEF;
1650 sd->redblc = RED_BALANCE_DEF;
1651 sd->blueblc = BLUE_BALANCE_DEF;
1652 sd->hue = HUE_DEF;
1653#if AUTOGAIN_77_DEF != 0
1654 sd->autogain = AUTOGAIN_77_DEF;
2d19a2c1 1655#else
c22c4a20 1656 gspca_dev->ctrl_inac |= (1 << AWB_77_IDX);
b014f94b
JFM
1657#endif
1658#if AWB_DEF != 0
c22c4a20
JFM
1659 sd->awb = AWB_DEF
1660#endif
1661#if SHARPNESS_77_DEF != 0
1662 sd->sharpness = SHARPNESS_77_DEF;
b014f94b 1663#endif
189d92af 1664#if HFLIP_DEF != 0
c22c4a20 1665 sd->hflip = HFLIP_DEF;
189d92af
JFM
1666#endif
1667#if VFLIP_DEF != 0
c22c4a20
JFM
1668 sd->vflip = VFLIP_DEF;
1669#endif
1670 } else {
1671 sd->brightness = BRIGHTNESS_96_DEF;
1672 sd->contrast = CONTRAST_96_DEF;
1673#if AUTOGAIN_96_DEF != 0
1674 sd->autogain = AUTOGAIN_96_DEF;
1675 gspca_dev->ctrl_inac |= (1 << EXPO_96_IDX);
1676#endif
1677#if EXPO_96_DEF != 0
1678 sd->exposure = EXPO_96_DEF;
1679#endif
1680#if SHARPNESS_96_DEF != 0
1681 sd->sharpness = SHARPNESS_96_DEF;
189d92af 1682#endif
c22c4a20
JFM
1683 sd->satur = SATUR_DEF;
1684 sd->lightfreq = FREQ_DEF;
1685 }
fbb4c6d2
AO
1686 return 0;
1687}
1688
1689/* this function is called at probe and resume time */
1690static int sd_init(struct gspca_dev *gspca_dev)
1691{
2ce949ec
JFM
1692 struct sd *sd = (struct sd *) gspca_dev;
1693 u16 sensor_id;
1694 static const u8 sensor_addr[2] = {
1695 0x42, /* 0 SENSOR_OV772X */
1696 0x60, /* 1 SENSOR_OV965X */
1697 };
1698
1699 /* reset bridge */
1700 ov534_reg_write(gspca_dev, 0xe7, 0x3a);
1701 ov534_reg_write(gspca_dev, 0xe0, 0x08);
1702 msleep(100);
1703
1704 /* initialize the sensor address */
1705 ov534_reg_write(gspca_dev, OV534_REG_ADDRESS,
1706 sensor_addr[sd->sensor]);
1707
1708 /* reset sensor */
1709 sccb_reg_write(gspca_dev, 0x12, 0x80);
1710 msleep(10);
1711
1712 /* probe the sensor */
1713 sccb_reg_read(gspca_dev, 0x0a);
1714 sensor_id = sccb_reg_read(gspca_dev, 0x0a) << 8;
1715 sccb_reg_read(gspca_dev, 0x0b);
1716 sensor_id |= sccb_reg_read(gspca_dev, 0x0b);
1717 PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id);
1718
1719 /* initialize */
1720 switch (sd->sensor) {
1721 case SENSOR_OV772X:
189d92af
JFM
1722 reg_w_array(gspca_dev, bridge_init_ov772x,
1723 ARRAY_SIZE(bridge_init_ov772x));
2ce949ec 1724 ov534_set_led(gspca_dev, 1);
189d92af
JFM
1725 sccb_w_array(gspca_dev, sensor_init_ov772x,
1726 ARRAY_SIZE(sensor_init_ov772x));
2ce949ec
JFM
1727 ov534_reg_write(gspca_dev, 0xe0, 0x09);
1728 ov534_set_led(gspca_dev, 0);
69f1fe28 1729 set_frame_rate(gspca_dev);
2ce949ec
JFM
1730 break;
1731 default:
1732/* case SENSOR_OV965X: */
1733 reg_w_array(gspca_dev, bridge_init_ov965x,
1734 ARRAY_SIZE(bridge_init_ov965x));
1735 sccb_w_array(gspca_dev, sensor_init_ov965x,
1736 ARRAY_SIZE(sensor_init_ov965x));
1737 reg_w_array(gspca_dev, bridge_init_ov965x_2,
1738 ARRAY_SIZE(bridge_init_ov965x_2));
1739 sccb_w_array(gspca_dev, sensor_init_ov965x_2,
1740 ARRAY_SIZE(sensor_init_ov965x_2));
1741 ov534_reg_write(gspca_dev, 0xe0, 0x00);
1742 ov534_reg_write(gspca_dev, 0xe0, 0x01);
1743 ov534_set_led(gspca_dev, 0);
1744 ov534_reg_write(gspca_dev, 0xe0, 0x00);
1745 }
fbb4c6d2
AO
1746
1747 return 0;
1748}
1749
189d92af 1750static int sd_start_ov772x(struct gspca_dev *gspca_dev)
fbb4c6d2 1751{
191d0e7f 1752 int mode;
fbb4c6d2 1753
189d92af
JFM
1754 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
1755 if (mode != 0) { /* 320x240 */
1756 reg_w_array(gspca_dev, bridge_start_ov772x_qvga,
1757 ARRAY_SIZE(bridge_start_ov772x_qvga));
1758 sccb_w_array(gspca_dev, sensor_start_ov772x_qvga,
1759 ARRAY_SIZE(sensor_start_ov772x_qvga));
1760 } else { /* 640x480 */
1761 reg_w_array(gspca_dev, bridge_start_ov772x_vga,
1762 ARRAY_SIZE(bridge_start_ov772x_vga));
1763 sccb_w_array(gspca_dev, sensor_start_ov772x_vga,
1764 ARRAY_SIZE(sensor_start_ov772x_vga));
2ce949ec 1765 }
69f1fe28 1766 set_frame_rate(gspca_dev);
189d92af 1767
c22c4a20 1768 setautogain_77(gspca_dev);
b014f94b 1769 setawb(gspca_dev);
189d92af
JFM
1770 setgain(gspca_dev);
1771 setredblc(gspca_dev);
1772 setblueblc(gspca_dev);
b014f94b 1773 sethue(gspca_dev);
c22c4a20
JFM
1774 setexposure_77(gspca_dev);
1775 setbrightness_77(gspca_dev);
1776 setcontrast_77(gspca_dev);
1777 setsharpness_77(gspca_dev);
189d92af
JFM
1778 setvflip(gspca_dev);
1779 sethflip(gspca_dev);
1780
1781 ov534_set_led(gspca_dev, 1);
1782 ov534_reg_write(gspca_dev, 0xe0, 0x00);
fbb4c6d2
AO
1783 return 0;
1784}
1785
189d92af 1786static int sd_start_ov965x(struct gspca_dev *gspca_dev)
fbb4c6d2 1787{
189d92af 1788 int mode;
2ce949ec 1789
189d92af 1790 mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
569691a5
JFM
1791 switch (mode) {
1792 default:
1793/* case 4: * 320x240 */
1794 sccb_w_array(gspca_dev, sensor_start_ov965x_1_vga,
1795 ARRAY_SIZE(sensor_start_ov965x_1_vga));
c76e6f11
JFM
1796 reg_w_array(gspca_dev, bridge_start_ov965x_qvga,
1797 ARRAY_SIZE(bridge_start_ov965x_qvga));
569691a5
JFM
1798 sccb_w_array(gspca_dev, sensor_start_ov965x_2_qvga,
1799 ARRAY_SIZE(sensor_start_ov965x_2_qvga));
1800 break;
1801 case 3: /* 640x480 */
1802 sccb_w_array(gspca_dev, sensor_start_ov965x_1_vga,
1803 ARRAY_SIZE(sensor_start_ov965x_1_vga));
189d92af
JFM
1804 reg_w_array(gspca_dev, bridge_start_ov965x_vga,
1805 ARRAY_SIZE(bridge_start_ov965x_vga));
569691a5
JFM
1806 sccb_w_array(gspca_dev, sensor_start_ov965x_2_vga,
1807 ARRAY_SIZE(sensor_start_ov965x_2_vga));
1808 break;
1809 case 2: /* 800x600 */
1810 sccb_w_array(gspca_dev, sensor_start_ov965x_1_svga,
1811 ARRAY_SIZE(sensor_start_ov965x_1_svga));
1812 reg_w_array(gspca_dev, bridge_start_ov965x_svga,
1813 ARRAY_SIZE(bridge_start_ov965x_svga));
1814 sccb_w_array(gspca_dev, sensor_start_ov965x_2_svga,
1815 ARRAY_SIZE(sensor_start_ov965x_2_svga));
1816 break;
1817 case 1: /* 1024x768 */
1818 sccb_w_array(gspca_dev, sensor_start_ov965x_1_xga,
1819 ARRAY_SIZE(sensor_start_ov965x_1_xga));
1820 reg_w_array(gspca_dev, bridge_start_ov965x_xga,
1821 ARRAY_SIZE(bridge_start_ov965x_xga));
1822 sccb_w_array(gspca_dev, sensor_start_ov965x_2_svga,
1823 ARRAY_SIZE(sensor_start_ov965x_2_svga));
1824 break;
1825 case 0: /* 1280x1024 */
1826 sccb_w_array(gspca_dev, sensor_start_ov965x_1_sxga,
1827 ARRAY_SIZE(sensor_start_ov965x_1_sxga));
1828 reg_w_array(gspca_dev, bridge_start_ov965x_sxga,
1829 ARRAY_SIZE(bridge_start_ov965x_sxga));
1830 sccb_w_array(gspca_dev, sensor_start_ov965x_2_sxga,
1831 ARRAY_SIZE(sensor_start_ov965x_2_sxga));
1832 break;
2ce949ec 1833 }
c22c4a20
JFM
1834 setfreq(gspca_dev);
1835 setautogain_96(gspca_dev);
1836 setbrightness_96(gspca_dev);
1837 setcontrast_96(gspca_dev);
1838 setexposure_96(gspca_dev);
1839 setsharpness_96(gspca_dev);
1840 setsatur(gspca_dev);
1841
189d92af
JFM
1842 ov534_reg_write(gspca_dev, 0xe0, 0x00);
1843 ov534_reg_write(gspca_dev, 0xe0, 0x00);
1844 ov534_set_led(gspca_dev, 1);
1845 return 0;
1846}
1847
1848static void sd_stopN_ov772x(struct gspca_dev *gspca_dev)
1849{
1850 ov534_reg_write(gspca_dev, 0xe0, 0x09);
1851 ov534_set_led(gspca_dev, 0);
1852}
1853
1854static void sd_stopN_ov965x(struct gspca_dev *gspca_dev)
1855{
1856 ov534_reg_write(gspca_dev, 0xe0, 0x01);
1857 ov534_set_led(gspca_dev, 0);
1858 ov534_reg_write(gspca_dev, 0xe0, 0x00);
fbb4c6d2
AO
1859}
1860
fb139224
JP
1861/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
1862#define UVC_STREAM_EOH (1 << 7)
1863#define UVC_STREAM_ERR (1 << 6)
1864#define UVC_STREAM_STI (1 << 5)
1865#define UVC_STREAM_RES (1 << 4)
1866#define UVC_STREAM_SCR (1 << 3)
1867#define UVC_STREAM_PTS (1 << 2)
1868#define UVC_STREAM_EOF (1 << 1)
1869#define UVC_STREAM_FID (1 << 0)
1870
76dd272b
JFM
1871static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1872 u8 *data, int len)
fbb4c6d2 1873{
8c252050 1874 struct sd *sd = (struct sd *) gspca_dev;
fb139224 1875 __u32 this_pts;
84fbdf87 1876 u16 this_fid;
0f7a50b2 1877 int remaining_len = len;
c874f3aa 1878 int payload_len;
0f7a50b2 1879
c874f3aa 1880 payload_len = gspca_dev->cam.bulk ? 2048 : 2040;
84fbdf87 1881 do {
c874f3aa 1882 len = min(remaining_len, payload_len);
fb139224 1883
84fbdf87
JFM
1884 /* Payloads are prefixed with a UVC-style header. We
1885 consider a frame to start when the FID toggles, or the PTS
1886 changes. A frame ends when EOF is set, and we've received
1887 the correct number of bytes. */
fb139224 1888
84fbdf87
JFM
1889 /* Verify UVC header. Header length is always 12 */
1890 if (data[0] != 12 || len < 12) {
1891 PDEBUG(D_PACK, "bad header");
1892 goto discard;
1893 }
fb139224 1894
84fbdf87
JFM
1895 /* Check errors */
1896 if (data[1] & UVC_STREAM_ERR) {
1897 PDEBUG(D_PACK, "payload error");
1898 goto discard;
1899 }
fb139224 1900
84fbdf87
JFM
1901 /* Extract PTS and FID */
1902 if (!(data[1] & UVC_STREAM_PTS)) {
1903 PDEBUG(D_PACK, "PTS not present");
fb139224
JP
1904 goto discard;
1905 }
84fbdf87
JFM
1906 this_pts = (data[5] << 24) | (data[4] << 16)
1907 | (data[3] << 8) | data[2];
1908 this_fid = (data[1] & UVC_STREAM_FID) ? 1 : 0;
fb139224 1909
84fbdf87
JFM
1910 /* If PTS or FID has changed, start a new frame. */
1911 if (this_pts != sd->last_pts || this_fid != sd->last_fid) {
ed47119f 1912 if (gspca_dev->last_packet_type == INTER_PACKET)
76dd272b
JFM
1913 gspca_frame_add(gspca_dev, LAST_PACKET,
1914 NULL, 0);
84fbdf87
JFM
1915 sd->last_pts = this_pts;
1916 sd->last_fid = this_fid;
76dd272b 1917 gspca_frame_add(gspca_dev, FIRST_PACKET,
84fbdf87 1918 data + 12, len - 12);
84fbdf87 1919 /* If this packet is marked as EOF, end the frame */
ed47119f 1920 } else if (data[1] & UVC_STREAM_EOF) {
84fbdf87 1921 sd->last_pts = 0;
76dd272b
JFM
1922 gspca_frame_add(gspca_dev, LAST_PACKET,
1923 data + 12, len - 12);
ed47119f
JFM
1924 } else {
1925
1926 /* Add the data from this payload */
76dd272b
JFM
1927 gspca_frame_add(gspca_dev, INTER_PACKET,
1928 data + 12, len - 12);
3481c198 1929 }
fb139224 1930
84fbdf87
JFM
1931 /* Done this payload */
1932 goto scan_next;
fb139224
JP
1933
1934discard:
84fbdf87 1935 /* Discard data until a new frame starts. */
76dd272b 1936 gspca_dev->last_packet_type = DISCARD_PACKET;
84fbdf87
JFM
1937
1938scan_next:
1939 remaining_len -= len;
1940 data += len;
1941 } while (remaining_len > 0);
fbb4c6d2
AO
1942}
1943
c22c4a20 1944/* controls */
189d92af
JFM
1945static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
1946{
1947 struct sd *sd = (struct sd *) gspca_dev;
1948
1949 sd->gain = val;
1950 if (gspca_dev->streaming)
1951 setgain(gspca_dev);
1952 return 0;
1953}
1954
1955static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1956{
1957 struct sd *sd = (struct sd *) gspca_dev;
1958
1959 *val = sd->gain;
1960 return 0;
1961}
1962
1963static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1964{
1965 struct sd *sd = (struct sd *) gspca_dev;
1966
1967 sd->exposure = val;
c22c4a20
JFM
1968 if (gspca_dev->streaming) {
1969 if (sd->sensor == SENSOR_OV772X)
1970 setexposure_77(gspca_dev);
1971 else
1972 setexposure_96(gspca_dev);
1973 }
189d92af
JFM
1974 return 0;
1975}
1976
1977static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1978{
1979 struct sd *sd = (struct sd *) gspca_dev;
1980
1981 *val = sd->exposure;
1982 return 0;
1983}
1984
b014f94b
JFM
1985static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1986{
1987 struct sd *sd = (struct sd *) gspca_dev;
1988
1989 sd->brightness = val;
c22c4a20
JFM
1990 if (gspca_dev->streaming) {
1991 if (sd->sensor == SENSOR_OV772X)
1992 setbrightness_77(gspca_dev);
1993 else
1994 setbrightness_96(gspca_dev);
1995 }
b014f94b
JFM
1996 return 0;
1997}
1998
1999static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
2000{
2001 struct sd *sd = (struct sd *) gspca_dev;
2002
2003 *val = sd->brightness;
2004 return 0;
2005}
2006
2007static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
2008{
2009 struct sd *sd = (struct sd *) gspca_dev;
2010
2011 sd->contrast = val;
c22c4a20
JFM
2012 if (gspca_dev->streaming) {
2013 if (sd->sensor == SENSOR_OV772X)
2014 setcontrast_77(gspca_dev);
2015 else
2016 setcontrast_96(gspca_dev);
2017 }
b014f94b
JFM
2018 return 0;
2019}
2020
2021static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
2022{
2023 struct sd *sd = (struct sd *) gspca_dev;
2024
2025 *val = sd->contrast;
2026 return 0;
2027}
2028
c22c4a20
JFM
2029static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val)
2030{
2031 struct sd *sd = (struct sd *) gspca_dev;
2032
2033 sd->satur = val;
2034 if (gspca_dev->streaming)
2035 setsatur(gspca_dev);
2036 return 0;
2037}
2038
2039static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val)
2040{
2041 struct sd *sd = (struct sd *) gspca_dev;
2042
2043 *val = sd->satur;
2044 return 0;
2045}
2046static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
2047{
2048 struct sd *sd = (struct sd *) gspca_dev;
2049
2050 sd->lightfreq = val;
2051 if (gspca_dev->streaming)
2052 setfreq(gspca_dev);
2053 return 0;
2054}
2055
2056static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
2057{
2058 struct sd *sd = (struct sd *) gspca_dev;
2059
2060 *val = sd->lightfreq;
2061 return 0;
2062}
2063
189d92af
JFM
2064static int sd_setredblc(struct gspca_dev *gspca_dev, __s32 val)
2065{
2066 struct sd *sd = (struct sd *) gspca_dev;
2067
2068 sd->redblc = val;
2069 if (gspca_dev->streaming)
2070 setredblc(gspca_dev);
2071 return 0;
2072}
2073
2074static int sd_getredblc(struct gspca_dev *gspca_dev, __s32 *val)
2075{
2076 struct sd *sd = (struct sd *) gspca_dev;
2077
2078 *val = sd->redblc;
2079 return 0;
2080}
2081
2082static int sd_setblueblc(struct gspca_dev *gspca_dev, __s32 val)
2083{
2084 struct sd *sd = (struct sd *) gspca_dev;
2085
2086 sd->blueblc = val;
2087 if (gspca_dev->streaming)
2088 setblueblc(gspca_dev);
2089 return 0;
2090}
2091
2092static int sd_getblueblc(struct gspca_dev *gspca_dev, __s32 *val)
2093{
2094 struct sd *sd = (struct sd *) gspca_dev;
2095
2096 *val = sd->blueblc;
2097 return 0;
2098}
2099
b014f94b
JFM
2100static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val)
2101{
2102 struct sd *sd = (struct sd *) gspca_dev;
2103
2104 sd->hue = val;
2105 if (gspca_dev->streaming)
2106 sethue(gspca_dev);
2107 return 0;
2108}
2109
2110static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val)
2111{
2112 struct sd *sd = (struct sd *) gspca_dev;
2113
2114 *val = sd->hue;
2115 return 0;
2116}
2117
189d92af
JFM
2118static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
2119{
2120 struct sd *sd = (struct sd *) gspca_dev;
2121
2122 sd->autogain = val;
2d19a2c1 2123
c22c4a20
JFM
2124 if (gspca_dev->streaming) {
2125 if (sd->sensor == SENSOR_OV772X) {
2d19a2c1 2126
c22c4a20
JFM
2127 /* the auto white balance control works only
2128 * when auto gain is set */
2129 if (val)
2130 gspca_dev->ctrl_inac &= ~(1 << AWB_77_IDX);
2131 else
2132 gspca_dev->ctrl_inac |= (1 << AWB_77_IDX);
2133 setautogain_77(gspca_dev);
2134 } else {
2135 if (val)
2136 gspca_dev->ctrl_inac |= (1 << EXPO_96_IDX);
2137 else
2138 gspca_dev->ctrl_inac &= ~(1 << EXPO_96_IDX);
2139 setautogain_96(gspca_dev);
2140 }
2141 }
189d92af
JFM
2142 return 0;
2143}
2144
2145static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
2146{
2147 struct sd *sd = (struct sd *) gspca_dev;
2148
2149 *val = sd->autogain;
2150 return 0;
2151}
2152
b014f94b
JFM
2153static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val)
2154{
2155 struct sd *sd = (struct sd *) gspca_dev;
2156
2157 sd->awb = val;
2158 if (gspca_dev->streaming)
2159 setawb(gspca_dev);
2160 return 0;
2161}
2162
2163static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val)
2164{
2165 struct sd *sd = (struct sd *) gspca_dev;
2166
2167 *val = sd->awb;
2168 return 0;
2169}
2170
189d92af
JFM
2171static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
2172{
2173 struct sd *sd = (struct sd *) gspca_dev;
2174
2175 sd->sharpness = val;
c22c4a20
JFM
2176 if (gspca_dev->streaming) {
2177 if (sd->sensor == SENSOR_OV772X)
2178 setsharpness_77(gspca_dev);
2179 else
2180 setsharpness_96(gspca_dev);
2181 }
189d92af
JFM
2182 return 0;
2183}
2184
2185static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
2186{
2187 struct sd *sd = (struct sd *) gspca_dev;
2188
2189 *val = sd->sharpness;
2190 return 0;
2191}
2192
2193static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
2194{
2195 struct sd *sd = (struct sd *) gspca_dev;
2196
2197 sd->hflip = val;
2198 if (gspca_dev->streaming)
2199 sethflip(gspca_dev);
2200 return 0;
2201}
2202
2203static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
2204{
2205 struct sd *sd = (struct sd *) gspca_dev;
2206
2207 *val = sd->hflip;
2208 return 0;
2209}
2210
2211static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
2212{
2213 struct sd *sd = (struct sd *) gspca_dev;
2214
2215 sd->vflip = val;
2216 if (gspca_dev->streaming)
2217 setvflip(gspca_dev);
2218 return 0;
2219}
2220
2221static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
2222{
2223 struct sd *sd = (struct sd *) gspca_dev;
2224
2225 *val = sd->vflip;
2226 return 0;
2227}
2228
11d9f25d 2229/* get stream parameters (framerate) */
5c1a15a1
JFM
2230static int sd_get_streamparm(struct gspca_dev *gspca_dev,
2231 struct v4l2_streamparm *parm)
11d9f25d
JP
2232{
2233 struct v4l2_captureparm *cp = &parm->parm.capture;
2234 struct v4l2_fract *tpf = &cp->timeperframe;
2235 struct sd *sd = (struct sd *) gspca_dev;
2236
2237 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2238 return -EINVAL;
2239
2240 cp->capability |= V4L2_CAP_TIMEPERFRAME;
2241 tpf->numerator = 1;
2242 tpf->denominator = sd->frame_rate;
2243
2244 return 0;
2245}
2246
2247/* set stream parameters (framerate) */
5c1a15a1
JFM
2248static int sd_set_streamparm(struct gspca_dev *gspca_dev,
2249 struct v4l2_streamparm *parm)
11d9f25d
JP
2250{
2251 struct v4l2_captureparm *cp = &parm->parm.capture;
2252 struct v4l2_fract *tpf = &cp->timeperframe;
2253 struct sd *sd = (struct sd *) gspca_dev;
2254
2255 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2256 return -EINVAL;
2257
2258 /* Set requested framerate */
2259 sd->frame_rate = tpf->denominator / tpf->numerator;
69f1fe28
JFM
2260 if (gspca_dev->streaming && sd->sensor == SENSOR_OV772X)
2261 set_frame_rate(gspca_dev);
11d9f25d
JP
2262
2263 /* Return the actual framerate */
2264 tpf->numerator = 1;
2265 tpf->denominator = sd->frame_rate;
2266
2267 return 0;
2268}
2269
c22c4a20
JFM
2270static int sd_querymenu(struct gspca_dev *gspca_dev,
2271 struct v4l2_querymenu *menu)
2272{
2273 switch (menu->id) {
2274 case V4L2_CID_POWER_LINE_FREQUENCY:
2275 switch (menu->index) {
2276 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
2277 strcpy((char *) menu->name, "NoFliker");
2278 return 0;
2279 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
2280 strcpy((char *) menu->name, "50 Hz");
2281 return 0;
2282 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
2283 strcpy((char *) menu->name, "60 Hz");
2284 return 0;
2285 }
2286 break;
2287 }
2288 return -EINVAL;
2289}
2290
fbb4c6d2 2291/* sub-driver description */
189d92af 2292static const struct sd_desc sd_desc_ov772x = {
fbb4c6d2 2293 .name = MODULE_NAME,
189d92af
JFM
2294 .ctrls = sd_ctrls_ov772x,
2295 .nctrls = ARRAY_SIZE(sd_ctrls_ov772x),
fbb4c6d2
AO
2296 .config = sd_config,
2297 .init = sd_init,
189d92af
JFM
2298 .start = sd_start_ov772x,
2299 .stopN = sd_stopN_ov772x,
2300 .pkt_scan = sd_pkt_scan,
2301 .get_streamparm = sd_get_streamparm,
2302 .set_streamparm = sd_set_streamparm,
2303};
2304
2305static const struct sd_desc sd_desc_ov965x = {
2306 .name = MODULE_NAME,
2307 .ctrls = sd_ctrls_ov965x,
2308 .nctrls = ARRAY_SIZE(sd_ctrls_ov965x),
2309 .config = sd_config,
2310 .init = sd_init,
2311 .start = sd_start_ov965x,
2312 .stopN = sd_stopN_ov965x,
fbb4c6d2 2313 .pkt_scan = sd_pkt_scan,
c22c4a20 2314 .querymenu = sd_querymenu,
fbb4c6d2
AO
2315};
2316
2317/* -- module initialisation -- */
2318static const __devinitdata struct usb_device_id device_table[] = {
2ce949ec
JFM
2319 {USB_DEVICE(0x06f8, 0x3003), .driver_info = SENSOR_OV965X},
2320 {USB_DEVICE(0x1415, 0x2000), .driver_info = SENSOR_OV772X},
fbb4c6d2
AO
2321 {}
2322};
2323
2324MODULE_DEVICE_TABLE(usb, device_table);
2325
2326/* -- device connect -- */
2327static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id)
2328{
189d92af
JFM
2329 return gspca_dev_probe(intf, id,
2330 id->driver_info == SENSOR_OV772X
2331 ? &sd_desc_ov772x
2332 : &sd_desc_ov965x,
2333 sizeof(struct sd),
2334 THIS_MODULE);
fbb4c6d2
AO
2335}
2336
2337static struct usb_driver sd_driver = {
2338 .name = MODULE_NAME,
2339 .id_table = device_table,
2340 .probe = sd_probe,
2341 .disconnect = gspca_disconnect,
2342#ifdef CONFIG_PM
2343 .suspend = gspca_suspend,
2344 .resume = gspca_resume,
2345#endif
2346};
2347
2348/* -- module insert / remove -- */
2349static int __init sd_mod_init(void)
2350{
f69e9529 2351 int ret;
189d92af 2352
f69e9529
AK
2353 ret = usb_register(&sd_driver);
2354 if (ret < 0)
e6b14849 2355 return ret;
fbb4c6d2
AO
2356 PDEBUG(D_PROBE, "registered");
2357 return 0;
2358}
2359
2360static void __exit sd_mod_exit(void)
2361{
2362 usb_deregister(&sd_driver);
2363 PDEBUG(D_PROBE, "deregistered");
2364}
2365
2366module_init(sd_mod_init);
2367module_exit(sd_mod_exit);