diff options
author | Jean-Francois Moine <moinejf@free.fr> | 2010-01-07 03:18:16 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-02-26 13:10:35 -0500 |
commit | c52af79916028f9d15638519b54a80ed1c10bce5 (patch) | |
tree | f4e49161d702ca4bbf2fdc1e465ea79125685739 | |
parent | de2d1549c2083e45ed84c779b64acf438ba5bf7f (diff) |
V4L/DVB (13916): gspca - ov534/ov534_9: Split the ov534 subdriver.
The two sensors ov772x and ov965x have too much differences.
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | Documentation/video4linux/gspca.txt | 3 | ||||
-rw-r--r-- | drivers/media/video/gspca/Kconfig | 16 | ||||
-rw-r--r-- | drivers/media/video/gspca/Makefile | 2 | ||||
-rw-r--r-- | drivers/media/video/gspca/ov534.c | 1242 | ||||
-rw-r--r-- | drivers/media/video/gspca/ov534_9.c | 1477 |
5 files changed, 1597 insertions, 1143 deletions
diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index 7b603439509d..c6364faa15af 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt | |||
@@ -190,8 +190,7 @@ spca500 06bd:0404 Agfa CL20 | |||
190 | spca500 06be:0800 Optimedia | 190 | spca500 06be:0800 Optimedia |
191 | sunplus 06d6:0031 Trust 610 LCD PowerC@m Zoom | 191 | sunplus 06d6:0031 Trust 610 LCD PowerC@m Zoom |
192 | spca506 06e1:a190 ADS Instant VCD | 192 | spca506 06e1:a190 ADS Instant VCD |
193 | ov534 06f8:3002 Hercules Blog Webcam | 193 | ov534_9 06f8:3003 Hercules Dualpix HD Weblog |
194 | ov534 06f8:3003 Hercules Dualpix HD Weblog | ||
195 | sonixj 06f8:3004 Hercules Classic Silver | 194 | sonixj 06f8:3004 Hercules Classic Silver |
196 | sonixj 06f8:3008 Hercules Deluxe Optical Glass | 195 | sonixj 06f8:3008 Hercules Deluxe Optical Glass |
197 | pac7302 06f8:3009 Hercules Classic Link | 196 | pac7302 06f8:3009 Hercules Classic Link |
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index 824e95a3d889..561bab0874ce 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig | |||
@@ -95,15 +95,25 @@ config USB_GSPCA_OV519 | |||
95 | module will be called gspca_ov519. | 95 | module will be called gspca_ov519. |
96 | 96 | ||
97 | config USB_GSPCA_OV534 | 97 | config USB_GSPCA_OV534 |
98 | tristate "OV534 USB Camera Driver" | 98 | tristate "OV534 OV772x USB Camera Driver" |
99 | depends on VIDEO_V4L2 && USB_GSPCA | 99 | depends on VIDEO_V4L2 && USB_GSPCA |
100 | help | 100 | help |
101 | Say Y here if you want support for cameras based on the OV534 chip. | 101 | Say Y here if you want support for cameras based on the OV534 chip |
102 | (e.g. Sony Playstation EYE) | 102 | and sensor OV772x (e.g. Sony Playstation EYE) |
103 | 103 | ||
104 | To compile this driver as a module, choose M here: the | 104 | To compile this driver as a module, choose M here: the |
105 | module will be called gspca_ov534. | 105 | module will be called gspca_ov534. |
106 | 106 | ||
107 | config USB_GSPCA_OV534_9 | ||
108 | tristate "OV534 OV965x USB Camera Driver" | ||
109 | depends on VIDEO_V4L2 && USB_GSPCA | ||
110 | help | ||
111 | Say Y here if you want support for cameras based on the OV534 chip | ||
112 | and sensor OV965x (e.g. Hercules Dualpix) | ||
113 | |||
114 | To compile this driver as a module, choose M here: the | ||
115 | module will be called gspca_ov534_9. | ||
116 | |||
107 | config USB_GSPCA_PAC207 | 117 | config USB_GSPCA_PAC207 |
108 | tristate "Pixart PAC207 USB Camera Driver" | 118 | tristate "Pixart PAC207 USB Camera Driver" |
109 | depends on VIDEO_V4L2 && USB_GSPCA | 119 | depends on VIDEO_V4L2 && USB_GSPCA |
diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile index 82da9c3d204a..553753d5c5ea 100644 --- a/drivers/media/video/gspca/Makefile +++ b/drivers/media/video/gspca/Makefile | |||
@@ -8,6 +8,7 @@ obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o | |||
8 | obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o | 8 | obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o |
9 | obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o | 9 | obj-$(CONFIG_USB_GSPCA_OV519) += gspca_ov519.o |
10 | obj-$(CONFIG_USB_GSPCA_OV534) += gspca_ov534.o | 10 | obj-$(CONFIG_USB_GSPCA_OV534) += gspca_ov534.o |
11 | obj-$(CONFIG_USB_GSPCA_OV534_9) += gspca_ov534_9.o | ||
11 | obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o | 12 | obj-$(CONFIG_USB_GSPCA_PAC207) += gspca_pac207.o |
12 | obj-$(CONFIG_USB_GSPCA_PAC7302) += gspca_pac7302.o | 13 | obj-$(CONFIG_USB_GSPCA_PAC7302) += gspca_pac7302.o |
13 | obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o | 14 | obj-$(CONFIG_USB_GSPCA_PAC7311) += gspca_pac7311.o |
@@ -40,6 +41,7 @@ gspca_mars-objs := mars.o | |||
40 | gspca_mr97310a-objs := mr97310a.o | 41 | gspca_mr97310a-objs := mr97310a.o |
41 | gspca_ov519-objs := ov519.o | 42 | gspca_ov519-objs := ov519.o |
42 | gspca_ov534-objs := ov534.o | 43 | gspca_ov534-objs := ov534.o |
44 | gspca_ov534_9-objs := ov534_9.o | ||
43 | gspca_pac207-objs := pac207.o | 45 | gspca_pac207-objs := pac207.o |
44 | gspca_pac7302-objs := pac7302.o | 46 | gspca_pac7302-objs := pac7302.o |
45 | gspca_pac7311-objs := pac7311.o | 47 | gspca_pac7311-objs := pac7311.o |
diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index da55637d07e8..0878c09e2485 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * ov534 gspca driver | 2 | * ov534-ov772x gspca driver |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it> | 4 | * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it> |
5 | * Copyright (C) 2008 Jim Paris <jim@jtan.com> | 5 | * Copyright (C) 2008 Jim Paris <jim@jtan.com> |
@@ -68,12 +68,7 @@ struct sd { | |||
68 | s8 sharpness; | 68 | s8 sharpness; |
69 | u8 hflip; | 69 | u8 hflip; |
70 | u8 vflip; | 70 | u8 vflip; |
71 | u8 satur; | ||
72 | u8 lightfreq; | ||
73 | 71 | ||
74 | u8 sensor; | ||
75 | #define SENSOR_OV772X 0 | ||
76 | #define SENSOR_OV965X 1 | ||
77 | }; | 72 | }; |
78 | 73 | ||
79 | /* V4L2 controls supported by the driver */ | 74 | /* V4L2 controls supported by the driver */ |
@@ -101,12 +96,8 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | |||
101 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | 96 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); |
102 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | 97 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); |
103 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | 98 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); |
104 | static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val); | ||
105 | static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val); | ||
106 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | ||
107 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | ||
108 | 99 | ||
109 | static const struct ctrl sd_ctrls_ov772x[] = { | 100 | static const struct ctrl sd_ctrls[] = { |
110 | { /* 0 */ | 101 | { /* 0 */ |
111 | { | 102 | { |
112 | .id = V4L2_CID_BRIGHTNESS, | 103 | .id = V4L2_CID_BRIGHTNESS, |
@@ -115,8 +106,8 @@ static const struct ctrl sd_ctrls_ov772x[] = { | |||
115 | .minimum = 0, | 106 | .minimum = 0, |
116 | .maximum = 255, | 107 | .maximum = 255, |
117 | .step = 1, | 108 | .step = 1, |
118 | #define BRIGHTNESS_77_DEF 20 | 109 | #define BRIGHTNESS_DEF 20 |
119 | .default_value = BRIGHTNESS_77_DEF, | 110 | .default_value = BRIGHTNESS_DEF, |
120 | }, | 111 | }, |
121 | .set = sd_setbrightness, | 112 | .set = sd_setbrightness, |
122 | .get = sd_getbrightness, | 113 | .get = sd_getbrightness, |
@@ -129,8 +120,8 @@ static const struct ctrl sd_ctrls_ov772x[] = { | |||
129 | .minimum = 0, | 120 | .minimum = 0, |
130 | .maximum = 255, | 121 | .maximum = 255, |
131 | .step = 1, | 122 | .step = 1, |
132 | #define CONTRAST_77_DEF 37 | 123 | #define CONTRAST_DEF 37 |
133 | .default_value = CONTRAST_77_DEF, | 124 | .default_value = CONTRAST_DEF, |
134 | }, | 125 | }, |
135 | .set = sd_setcontrast, | 126 | .set = sd_setcontrast, |
136 | .get = sd_getcontrast, | 127 | .get = sd_getcontrast, |
@@ -157,8 +148,8 @@ static const struct ctrl sd_ctrls_ov772x[] = { | |||
157 | .minimum = 0, | 148 | .minimum = 0, |
158 | .maximum = 255, | 149 | .maximum = 255, |
159 | .step = 1, | 150 | .step = 1, |
160 | #define EXPO_77_DEF 120 | 151 | #define EXPO_DEF 120 |
161 | .default_value = EXPO_77_DEF, | 152 | .default_value = EXPO_DEF, |
162 | }, | 153 | }, |
163 | .set = sd_setexposure, | 154 | .set = sd_setexposure, |
164 | .get = sd_getexposure, | 155 | .get = sd_getexposure, |
@@ -213,13 +204,13 @@ static const struct ctrl sd_ctrls_ov772x[] = { | |||
213 | .minimum = 0, | 204 | .minimum = 0, |
214 | .maximum = 1, | 205 | .maximum = 1, |
215 | .step = 1, | 206 | .step = 1, |
216 | #define AUTOGAIN_77_DEF 0 | 207 | #define AUTOGAIN_DEF 0 |
217 | .default_value = AUTOGAIN_77_DEF, | 208 | .default_value = AUTOGAIN_DEF, |
218 | }, | 209 | }, |
219 | .set = sd_setautogain, | 210 | .set = sd_setautogain, |
220 | .get = sd_getautogain, | 211 | .get = sd_getautogain, |
221 | }, | 212 | }, |
222 | #define AWB_77_IDX 8 | 213 | #define AWB_IDX 8 |
223 | { /* 8 */ | 214 | { /* 8 */ |
224 | { | 215 | { |
225 | .id = V4L2_CID_AUTO_WHITE_BALANCE, | 216 | .id = V4L2_CID_AUTO_WHITE_BALANCE, |
@@ -242,8 +233,8 @@ static const struct ctrl sd_ctrls_ov772x[] = { | |||
242 | .minimum = 0, | 233 | .minimum = 0, |
243 | .maximum = 63, | 234 | .maximum = 63, |
244 | .step = 1, | 235 | .step = 1, |
245 | #define SHARPNESS_77_DEF 0 | 236 | #define SHARPNESS_DEF 0 |
246 | .default_value = SHARPNESS_77_DEF, | 237 | .default_value = SHARPNESS_DEF, |
247 | }, | 238 | }, |
248 | .set = sd_setsharpness, | 239 | .set = sd_setsharpness, |
249 | .get = sd_getsharpness, | 240 | .get = sd_getsharpness, |
@@ -277,107 +268,6 @@ static const struct ctrl sd_ctrls_ov772x[] = { | |||
277 | .get = sd_getvflip, | 268 | .get = sd_getvflip, |
278 | }, | 269 | }, |
279 | }; | 270 | }; |
280 | static const struct ctrl sd_ctrls_ov965x[] = { | ||
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 | }, | ||
380 | }; | ||
381 | 271 | ||
382 | static const struct v4l2_pix_format ov772x_mode[] = { | 272 | static const struct v4l2_pix_format ov772x_mode[] = { |
383 | {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, | 273 | {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE, |
@@ -392,35 +282,7 @@ static const struct v4l2_pix_format ov772x_mode[] = { | |||
392 | .priv = 0}, | 282 | .priv = 0}, |
393 | }; | 283 | }; |
394 | 284 | ||
395 | static const struct v4l2_pix_format ov965x_mode[] = { | 285 | static const u8 bridge_init[][2] = { |
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, | ||
400 | .priv = 4}, | ||
401 | {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
402 | .bytesperline = 640, | ||
403 | .sizeimage = 640 * 480 * 3 / 8 + 590, | ||
404 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
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, | ||
420 | .priv = 0}, | ||
421 | }; | ||
422 | |||
423 | static const u8 bridge_init_ov772x[][2] = { | ||
424 | { 0xc2, 0x0c }, | 286 | { 0xc2, 0x0c }, |
425 | { 0x88, 0xf8 }, | 287 | { 0x88, 0xf8 }, |
426 | { 0xc3, 0x69 }, | 288 | { 0xc3, 0x69 }, |
@@ -478,7 +340,7 @@ static const u8 bridge_init_ov772x[][2] = { | |||
478 | { 0xc1, 0x3c }, | 340 | { 0xc1, 0x3c }, |
479 | { 0xc2, 0x0c }, | 341 | { 0xc2, 0x0c }, |
480 | }; | 342 | }; |
481 | static const u8 sensor_init_ov772x[][2] = { | 343 | static const u8 sensor_init[][2] = { |
482 | { 0x12, 0x80 }, | 344 | { 0x12, 0x80 }, |
483 | { 0x11, 0x01 }, | 345 | { 0x11, 0x01 }, |
484 | /*fixme: better have a delay?*/ | 346 | /*fixme: better have a delay?*/ |
@@ -571,7 +433,7 @@ static const u8 sensor_init_ov772x[][2] = { | |||
571 | { 0x8e, 0x00 }, /* De-noise threshold */ | 433 | { 0x8e, 0x00 }, /* De-noise threshold */ |
572 | { 0x0c, 0xd0 } | 434 | { 0x0c, 0xd0 } |
573 | }; | 435 | }; |
574 | static const u8 bridge_start_ov772x_vga[][2] = { | 436 | static const u8 bridge_start_vga[][2] = { |
575 | {0x1c, 0x00}, | 437 | {0x1c, 0x00}, |
576 | {0x1d, 0x40}, | 438 | {0x1d, 0x40}, |
577 | {0x1d, 0x02}, | 439 | {0x1d, 0x02}, |
@@ -582,7 +444,7 @@ static const u8 bridge_start_ov772x_vga[][2] = { | |||
582 | {0xc0, 0x50}, | 444 | {0xc0, 0x50}, |
583 | {0xc1, 0x3c}, | 445 | {0xc1, 0x3c}, |
584 | }; | 446 | }; |
585 | static const u8 sensor_start_ov772x_vga[][2] = { | 447 | static const u8 sensor_start_vga[][2] = { |
586 | {0x12, 0x00}, | 448 | {0x12, 0x00}, |
587 | {0x17, 0x26}, | 449 | {0x17, 0x26}, |
588 | {0x18, 0xa0}, | 450 | {0x18, 0xa0}, |
@@ -592,7 +454,7 @@ static const u8 sensor_start_ov772x_vga[][2] = { | |||
592 | {0x2c, 0xf0}, | 454 | {0x2c, 0xf0}, |
593 | {0x65, 0x20}, | 455 | {0x65, 0x20}, |
594 | }; | 456 | }; |
595 | static const u8 bridge_start_ov772x_qvga[][2] = { | 457 | static const u8 bridge_start_qvga[][2] = { |
596 | {0x1c, 0x00}, | 458 | {0x1c, 0x00}, |
597 | {0x1d, 0x40}, | 459 | {0x1d, 0x40}, |
598 | {0x1d, 0x02}, | 460 | {0x1d, 0x02}, |
@@ -603,7 +465,7 @@ static const u8 bridge_start_ov772x_qvga[][2] = { | |||
603 | {0xc0, 0x28}, | 465 | {0xc0, 0x28}, |
604 | {0xc1, 0x1e}, | 466 | {0xc1, 0x1e}, |
605 | }; | 467 | }; |
606 | static const u8 sensor_start_ov772x_qvga[][2] = { | 468 | static const u8 sensor_start_qvga[][2] = { |
607 | {0x12, 0x40}, | 469 | {0x12, 0x40}, |
608 | {0x17, 0x3f}, | 470 | {0x17, 0x3f}, |
609 | {0x18, 0x50}, | 471 | {0x18, 0x50}, |
@@ -614,571 +476,6 @@ static const u8 sensor_start_ov772x_qvga[][2] = { | |||
614 | {0x65, 0x2f}, | 476 | {0x65, 0x2f}, |
615 | }; | 477 | }; |
616 | 478 | ||
617 | static 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 | |||
651 | static const u8 sensor_init_ov965x[][2] = { | ||
652 | {0x12, 0x80}, /* com7 - SSCB reset */ | ||
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 */ | ||
662 | {0x12, 0x02}, /* com7 - 15fps VGA YUYV */ | ||
663 | {0x13, 0xe7}, /* com8 - everything (AGC, AWB and AEC) */ | ||
664 | {0x14, 0x28}, /* com9 */ | ||
665 | {0x16, 0x24}, /* reg16 */ | ||
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 */ | ||
677 | {0x2a, 0x00}, /* exhch */ | ||
678 | {0x2b, 0x00}, /* exhcl */ | ||
679 | {0x2c, 0x08}, /* rbias */ | ||
680 | {0x32, 0xff}, /* href */ | ||
681 | {0x33, 0x00}, /* chlf */ | ||
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 */ | ||
689 | {0x3d, 0x99}, /* com13 */ | ||
690 | {0x3f, 0xc1}, /* edge */ | ||
691 | {0x40, 0xc0}, /* com15 */ | ||
692 | {0x41, 0x40}, /* com16 */ | ||
693 | {0x42, 0xc0}, /* com17 */ | ||
694 | {0x43, 0x0a}, /* rsvd */ | ||
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}, | ||
705 | {0x4f, 0x98}, /* matrix */ | ||
706 | {0x50, 0x98}, | ||
707 | {0x51, 0x00}, | ||
708 | {0x52, 0x28}, | ||
709 | {0x53, 0x70}, | ||
710 | {0x54, 0x98}, | ||
711 | {0x58, 0x1a}, /* matrix coef sign */ | ||
712 | {0x59, 0x85}, /* AWB control */ | ||
713 | {0x5a, 0xa9}, | ||
714 | {0x5b, 0x64}, | ||
715 | {0x5c, 0x84}, | ||
716 | {0x5d, 0x53}, | ||
717 | {0x5e, 0x0e}, | ||
718 | {0x5f, 0xf0}, /* AWB blue limit */ | ||
719 | {0x60, 0xf0}, /* AWB red limit */ | ||
720 | {0x61, 0xf0}, /* AWB green limit */ | ||
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}, | ||
732 | {0x70, 0x21}, /* dnsth */ | ||
733 | {0x71, 0x78}, | ||
734 | {0x72, 0x00}, /* poidx */ | ||
735 | {0x73, 0x01}, /* pckdv */ | ||
736 | {0x74, 0x3a}, /* xindx */ | ||
737 | {0x75, 0x35}, /* yindx */ | ||
738 | {0x76, 0x01}, | ||
739 | {0x77, 0x02}, | ||
740 | {0x7a, 0x12}, /* gamma curve */ | ||
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}, | ||
757 | {0x8c, 0x89}, /* com19 */ | ||
758 | {0x14, 0x28}, /* com9 */ | ||
759 | {0x90, 0x7d}, | ||
760 | {0x91, 0x7b}, | ||
761 | {0x9d, 0x03}, /* lcc6 */ | ||
762 | {0x9e, 0x04}, /* lcc7 */ | ||
763 | {0x9f, 0x7a}, | ||
764 | {0xa0, 0x79}, | ||
765 | {0xa1, 0x40}, /* aechm */ | ||
766 | {0xa4, 0x50}, /* com21 */ | ||
767 | {0xa5, 0x68}, /* com26 */ | ||
768 | {0xa6, 0x4a}, /* AWB green */ | ||
769 | {0xa8, 0xc1}, /* refa8 */ | ||
770 | {0xa9, 0xef}, /* refa9 */ | ||
771 | {0xaa, 0x92}, | ||
772 | {0xab, 0x04}, | ||
773 | {0xac, 0x80}, /* black level control */ | ||
774 | {0xad, 0x80}, | ||
775 | {0xae, 0x80}, | ||
776 | {0xaf, 0x80}, | ||
777 | {0xb2, 0xf2}, | ||
778 | {0xb3, 0x20}, | ||
779 | {0xb4, 0x20}, /* ctrlb4 */ | ||
780 | {0xb5, 0x00}, | ||
781 | {0xb6, 0xaf}, | ||
782 | {0xbb, 0xae}, | ||
783 | {0xbc, 0x7f}, /* ADC channel offsets */ | ||
784 | {0xdb, 0x7f}, | ||
785 | {0xbe, 0x7f}, | ||
786 | {0xbf, 0x7f}, | ||
787 | {0xc0, 0xe2}, | ||
788 | {0xc1, 0xc0}, | ||
789 | {0xc2, 0x01}, | ||
790 | {0xc3, 0x4e}, | ||
791 | {0xc6, 0x85}, | ||
792 | {0xc7, 0x80}, /* com24 */ | ||
793 | {0xc9, 0xe0}, | ||
794 | {0xca, 0xe8}, | ||
795 | {0xcb, 0xf0}, | ||
796 | {0xcc, 0xd8}, | ||
797 | {0xcd, 0xf1}, | ||
798 | {0x4f, 0x98}, /* matrix */ | ||
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 */ | ||
807 | |||
808 | {0xc5, 0x03}, /* 60 Hz banding filter */ | ||
809 | {0x6a, 0x02}, /* 50 Hz banding filter */ | ||
810 | |||
811 | {0x12, 0x62}, /* com7 - 30fps VGA YUV */ | ||
812 | {0x36, 0xfa}, /* aref3 */ | ||
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 | |||
833 | static 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}, | ||
851 | {0x55, 0x00}, | ||
852 | {0x57, 0x00}, | ||
853 | {0x5c, 0x00}, | ||
854 | {0x5a, 0xa0}, | ||
855 | {0x5b, 0x78}, | ||
856 | {0x35, 0x02}, | ||
857 | {0xd9, 0x10}, | ||
858 | {0x94, 0x11}, | ||
859 | }; | ||
860 | |||
861 | static 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 */ | ||
875 | {0x42, 0xc0}, /* com17 */ | ||
876 | {0x2d, 0x00}, | ||
877 | {0xff, 0x42}, /* read 42, write ff 00 */ | ||
878 | {0x42, 0xc1}, /* com17 */ | ||
879 | /* sharpness */ | ||
880 | {0x3f, 0x01}, | ||
881 | {0xff, 0x42}, /* read 42, write ff 00 */ | ||
882 | {0x42, 0xc1}, /* com17 */ | ||
883 | /* saturation */ | ||
884 | {0x4f, 0x98}, /* matrix */ | ||
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 */ | ||
893 | /* contrast */ | ||
894 | {0x56, 0x40}, | ||
895 | /* brightness */ | ||
896 | {0x55, 0x8f}, | ||
897 | /* expo */ | ||
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 | |||
903 | static const u8 sensor_start_ov965x_1_vga[][2] = { /* same for qvga */ | ||
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}, | ||
924 | }; | ||
925 | |||
926 | static 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}, | ||
946 | }; | ||
947 | |||
948 | static 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}, | ||
969 | }; | ||
970 | |||
971 | static 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}, | ||
992 | }; | ||
993 | |||
994 | static const u8 bridge_start_ov965x_qvga[][2] = { | ||
995 | {0x94, 0xaa}, | ||
996 | {0xf1, 0x60}, | ||
997 | {0xe5, 0x04}, | ||
998 | {0xc0, 0x50}, | ||
999 | {0xc1, 0x3c}, | ||
1000 | {0x8c, 0x00}, | ||
1001 | {0x8d, 0x1c}, | ||
1002 | {0x34, 0x05}, | ||
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}, | ||
1020 | }; | ||
1021 | |||
1022 | static const u8 bridge_start_ov965x_vga[][2] = { | ||
1023 | {0x94, 0xaa}, | ||
1024 | {0xf1, 0x60}, | ||
1025 | {0xe5, 0x04}, | ||
1026 | {0xc0, 0x50}, | ||
1027 | {0xc1, 0x3c}, | ||
1028 | {0x8c, 0x00}, | ||
1029 | {0x8d, 0x1c}, | ||
1030 | {0x34, 0x05}, | ||
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}, | ||
1047 | }; | ||
1048 | |||
1049 | static 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}, | ||
1058 | {0xc2, 0x4c}, | ||
1059 | {0xc3, 0xf9}, | ||
1060 | {0x50, 0x00}, | ||
1061 | {0x51, 0x40}, | ||
1062 | {0x52, 0x00}, | ||
1063 | {0x53, 0x00}, | ||
1064 | {0x54, 0x00}, | ||
1065 | {0x55, 0x88}, | ||
1066 | {0x57, 0x00}, | ||
1067 | {0x5c, 0x00}, | ||
1068 | {0x5a, 0xc8}, | ||
1069 | {0x5b, 0x96}, | ||
1070 | {0x35, 0x02}, | ||
1071 | {0xd9, 0x10}, | ||
1072 | {0xda, 0x00}, | ||
1073 | {0x94, 0x11}, | ||
1074 | }; | ||
1075 | |||
1076 | static 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}, | ||
1097 | {0x35, 0x02}, | ||
1098 | {0xd9, 0x10}, | ||
1099 | {0xda, 0x01}, | ||
1100 | {0x94, 0x11}, | ||
1101 | }; | ||
1102 | |||
1103 | static 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}, | ||
1118 | }; | ||
1119 | |||
1120 | static 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 */ | ||
1136 | }; | ||
1137 | |||
1138 | static const u8 sensor_start_ov965x_2_vga[][2] = { | ||
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 */ | ||
1152 | }; | ||
1153 | |||
1154 | static const u8 sensor_start_ov965x_2_svga[][2] = { /* same for xga */ | ||
1155 | {0x3b, 0xc4}, /* com11 - night mode 1/4 frame rate */ | ||
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 */ | ||
1162 | {0x6a, 0x0c}, /* 50 Hz banding filter */ | ||
1163 | {0xc5, 0x0f}, /* 60 Hz banding filter */ | ||
1164 | {0xa2, 0x4e}, /* bd50 */ | ||
1165 | {0xa3, 0x41}, /* bd60 */ | ||
1166 | }; | ||
1167 | |||
1168 | static 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 */ | ||
1180 | }; | ||
1181 | |||
1182 | static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val) | 479 | static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val) |
1183 | { | 480 | { |
1184 | struct usb_device *udev = gspca_dev->dev; | 481 | struct usb_device *udev = gspca_dev->dev; |
@@ -1360,14 +657,14 @@ static void set_frame_rate(struct gspca_dev *gspca_dev) | |||
1360 | PDEBUG(D_PROBE, "frame_rate: %d", r->fps); | 657 | PDEBUG(D_PROBE, "frame_rate: %d", r->fps); |
1361 | } | 658 | } |
1362 | 659 | ||
1363 | static void setbrightness_77(struct gspca_dev *gspca_dev) | 660 | static void setbrightness(struct gspca_dev *gspca_dev) |
1364 | { | 661 | { |
1365 | struct sd *sd = (struct sd *) gspca_dev; | 662 | struct sd *sd = (struct sd *) gspca_dev; |
1366 | 663 | ||
1367 | sccb_reg_write(gspca_dev, 0x9B, sd->brightness); | 664 | sccb_reg_write(gspca_dev, 0x9B, sd->brightness); |
1368 | } | 665 | } |
1369 | 666 | ||
1370 | static void setcontrast_77(struct gspca_dev *gspca_dev) | 667 | static void setcontrast(struct gspca_dev *gspca_dev) |
1371 | { | 668 | { |
1372 | struct sd *sd = (struct sd *) gspca_dev; | 669 | struct sd *sd = (struct sd *) gspca_dev; |
1373 | 670 | ||
@@ -1401,7 +698,7 @@ static void setgain(struct gspca_dev *gspca_dev) | |||
1401 | sccb_reg_write(gspca_dev, 0x00, val); | 698 | sccb_reg_write(gspca_dev, 0x00, val); |
1402 | } | 699 | } |
1403 | 700 | ||
1404 | static void setexposure_77(struct gspca_dev *gspca_dev) | 701 | static void setexposure(struct gspca_dev *gspca_dev) |
1405 | { | 702 | { |
1406 | struct sd *sd = (struct sd *) gspca_dev; | 703 | struct sd *sd = (struct sd *) gspca_dev; |
1407 | u8 val; | 704 | u8 val; |
@@ -1432,7 +729,7 @@ static void sethue(struct gspca_dev *gspca_dev) | |||
1432 | sccb_reg_write(gspca_dev, 0x01, sd->hue); | 729 | sccb_reg_write(gspca_dev, 0x01, sd->hue); |
1433 | } | 730 | } |
1434 | 731 | ||
1435 | static void setautogain_77(struct gspca_dev *gspca_dev) | 732 | static void setautogain(struct gspca_dev *gspca_dev) |
1436 | { | 733 | { |
1437 | struct sd *sd = (struct sd *) gspca_dev; | 734 | struct sd *sd = (struct sd *) gspca_dev; |
1438 | 735 | ||
@@ -1457,7 +754,7 @@ static void setawb(struct gspca_dev *gspca_dev) | |||
1457 | sccb_reg_write(gspca_dev, 0x63, 0xaa); /* AWB off */ | 754 | sccb_reg_write(gspca_dev, 0x63, 0xaa); /* AWB off */ |
1458 | } | 755 | } |
1459 | 756 | ||
1460 | static void setsharpness_77(struct gspca_dev *gspca_dev) | 757 | static void setsharpness(struct gspca_dev *gspca_dev) |
1461 | { | 758 | { |
1462 | struct sd *sd = (struct sd *) gspca_dev; | 759 | struct sd *sd = (struct sd *) gspca_dev; |
1463 | u8 val; | 760 | u8 val; |
@@ -1491,132 +788,6 @@ static void setvflip(struct gspca_dev *gspca_dev) | |||
1491 | sccb_reg_read(gspca_dev, 0x0c) & 0x7f); | 788 | sccb_reg_read(gspca_dev, 0x0c) & 0x7f); |
1492 | } | 789 | } |
1493 | 790 | ||
1494 | /* ov965x specific controls */ | ||
1495 | static 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 | |||
1509 | static 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 | |||
1517 | static 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 | |||
1533 | static void setsharpness_96(struct gspca_dev *gspca_dev) | ||
1534 | { | ||
1535 | struct sd *sd = (struct sd *) gspca_dev; | ||
1536 | s8 val; | ||
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 | |||
1555 | static 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 | |||
1571 | static 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 | |||
1598 | static 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 | |||
1620 | /* this function is called at probe time */ | 791 | /* this function is called at probe time */ |
1621 | static int sd_config(struct gspca_dev *gspca_dev, | 792 | static int sd_config(struct gspca_dev *gspca_dev, |
1622 | const struct usb_device_id *id) | 793 | const struct usb_device_id *id) |
@@ -1624,77 +795,49 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1624 | struct sd *sd = (struct sd *) gspca_dev; | 795 | struct sd *sd = (struct sd *) gspca_dev; |
1625 | struct cam *cam; | 796 | struct cam *cam; |
1626 | 797 | ||
1627 | sd->sensor = id->driver_info; | ||
1628 | |||
1629 | cam = &gspca_dev->cam; | 798 | cam = &gspca_dev->cam; |
1630 | 799 | ||
1631 | if (sd->sensor == SENSOR_OV772X) { | 800 | cam->cam_mode = ov772x_mode; |
1632 | cam->cam_mode = ov772x_mode; | 801 | cam->nmodes = ARRAY_SIZE(ov772x_mode); |
1633 | cam->nmodes = ARRAY_SIZE(ov772x_mode); | ||
1634 | 802 | ||
1635 | cam->bulk = 1; | 803 | cam->bulk = 1; |
1636 | cam->bulk_size = 16384; | 804 | cam->bulk_size = 16384; |
1637 | cam->bulk_nurbs = 2; | 805 | cam->bulk_nurbs = 2; |
1638 | } else { /* ov965x */ | ||
1639 | cam->cam_mode = ov965x_mode; | ||
1640 | cam->nmodes = ARRAY_SIZE(ov965x_mode); | ||
1641 | } | ||
1642 | 806 | ||
1643 | sd->frame_rate = 30; | 807 | sd->frame_rate = 30; |
1644 | 808 | ||
1645 | if (sd->sensor == SENSOR_OV772X) { | 809 | sd->brightness = BRIGHTNESS_DEF; |
1646 | sd->brightness = BRIGHTNESS_77_DEF; | 810 | sd->contrast = CONTRAST_DEF; |
1647 | sd->contrast = CONTRAST_77_DEF; | 811 | sd->gain = GAIN_DEF; |
1648 | sd->gain = GAIN_DEF; | 812 | sd->exposure = EXPO_DEF; |
1649 | sd->exposure = EXPO_77_DEF; | 813 | sd->redblc = RED_BALANCE_DEF; |
1650 | sd->redblc = RED_BALANCE_DEF; | 814 | sd->blueblc = BLUE_BALANCE_DEF; |
1651 | sd->blueblc = BLUE_BALANCE_DEF; | 815 | sd->hue = HUE_DEF; |
1652 | sd->hue = HUE_DEF; | 816 | #if AUTOGAIN_DEF != 0 |
1653 | #if AUTOGAIN_77_DEF != 0 | 817 | sd->autogain = AUTOGAIN_DEF; |
1654 | sd->autogain = AUTOGAIN_77_DEF; | ||
1655 | #else | 818 | #else |
1656 | gspca_dev->ctrl_inac |= (1 << AWB_77_IDX); | 819 | gspca_dev->ctrl_inac |= (1 << AWB_IDX); |
1657 | #endif | 820 | #endif |
1658 | #if AWB_DEF != 0 | 821 | #if AWB_DEF != 0 |
1659 | sd->awb = AWB_DEF | 822 | sd->awb = AWB_DEF |
1660 | #endif | 823 | #endif |
1661 | #if SHARPNESS_77_DEF != 0 | 824 | #if SHARPNESS_DEF != 0 |
1662 | sd->sharpness = SHARPNESS_77_DEF; | 825 | sd->sharpness = SHARPNESS_DEF; |
1663 | #endif | 826 | #endif |
1664 | #if HFLIP_DEF != 0 | 827 | #if HFLIP_DEF != 0 |
1665 | sd->hflip = HFLIP_DEF; | 828 | sd->hflip = HFLIP_DEF; |
1666 | #endif | 829 | #endif |
1667 | #if VFLIP_DEF != 0 | 830 | #if VFLIP_DEF != 0 |
1668 | sd->vflip = VFLIP_DEF; | 831 | 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 | 832 | #endif |
1680 | #if SHARPNESS_96_DEF != 0 | 833 | |
1681 | sd->sharpness = SHARPNESS_96_DEF; | ||
1682 | #endif | ||
1683 | sd->satur = SATUR_DEF; | ||
1684 | sd->lightfreq = FREQ_DEF; | ||
1685 | } | ||
1686 | return 0; | 834 | return 0; |
1687 | } | 835 | } |
1688 | 836 | ||
1689 | /* this function is called at probe and resume time */ | 837 | /* this function is called at probe and resume time */ |
1690 | static int sd_init(struct gspca_dev *gspca_dev) | 838 | static int sd_init(struct gspca_dev *gspca_dev) |
1691 | { | 839 | { |
1692 | struct sd *sd = (struct sd *) gspca_dev; | ||
1693 | u16 sensor_id; | 840 | u16 sensor_id; |
1694 | static const u8 sensor_addr[2] = { | ||
1695 | 0x42, /* 0 SENSOR_OV772X */ | ||
1696 | 0x60, /* 1 SENSOR_OV965X */ | ||
1697 | }; | ||
1698 | 841 | ||
1699 | /* reset bridge */ | 842 | /* reset bridge */ |
1700 | ov534_reg_write(gspca_dev, 0xe7, 0x3a); | 843 | ov534_reg_write(gspca_dev, 0xe7, 0x3a); |
@@ -1702,8 +845,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1702 | msleep(100); | 845 | msleep(100); |
1703 | 846 | ||
1704 | /* initialize the sensor address */ | 847 | /* initialize the sensor address */ |
1705 | ov534_reg_write(gspca_dev, OV534_REG_ADDRESS, | 848 | ov534_reg_write(gspca_dev, OV534_REG_ADDRESS, 0x42); |
1706 | sensor_addr[sd->sensor]); | ||
1707 | 849 | ||
1708 | /* reset sensor */ | 850 | /* reset sensor */ |
1709 | sccb_reg_write(gspca_dev, 0x12, 0x80); | 851 | sccb_reg_write(gspca_dev, 0x12, 0x80); |
@@ -1717,64 +859,46 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1717 | PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id); | 859 | PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id); |
1718 | 860 | ||
1719 | /* initialize */ | 861 | /* initialize */ |
1720 | switch (sd->sensor) { | 862 | reg_w_array(gspca_dev, bridge_init, |
1721 | case SENSOR_OV772X: | 863 | ARRAY_SIZE(bridge_init)); |
1722 | reg_w_array(gspca_dev, bridge_init_ov772x, | 864 | ov534_set_led(gspca_dev, 1); |
1723 | ARRAY_SIZE(bridge_init_ov772x)); | 865 | sccb_w_array(gspca_dev, sensor_init, |
1724 | ov534_set_led(gspca_dev, 1); | 866 | ARRAY_SIZE(sensor_init)); |
1725 | sccb_w_array(gspca_dev, sensor_init_ov772x, | 867 | ov534_reg_write(gspca_dev, 0xe0, 0x09); |
1726 | ARRAY_SIZE(sensor_init_ov772x)); | 868 | ov534_set_led(gspca_dev, 0); |
1727 | ov534_reg_write(gspca_dev, 0xe0, 0x09); | 869 | set_frame_rate(gspca_dev); |
1728 | ov534_set_led(gspca_dev, 0); | ||
1729 | set_frame_rate(gspca_dev); | ||
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 | } | ||
1746 | 870 | ||
1747 | return 0; | 871 | return 0; |
1748 | } | 872 | } |
1749 | 873 | ||
1750 | static int sd_start_ov772x(struct gspca_dev *gspca_dev) | 874 | static int sd_start(struct gspca_dev *gspca_dev) |
1751 | { | 875 | { |
1752 | int mode; | 876 | int mode; |
1753 | 877 | ||
1754 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; | 878 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; |
1755 | if (mode != 0) { /* 320x240 */ | 879 | if (mode != 0) { /* 320x240 */ |
1756 | reg_w_array(gspca_dev, bridge_start_ov772x_qvga, | 880 | reg_w_array(gspca_dev, bridge_start_qvga, |
1757 | ARRAY_SIZE(bridge_start_ov772x_qvga)); | 881 | ARRAY_SIZE(bridge_start_qvga)); |
1758 | sccb_w_array(gspca_dev, sensor_start_ov772x_qvga, | 882 | sccb_w_array(gspca_dev, sensor_start_qvga, |
1759 | ARRAY_SIZE(sensor_start_ov772x_qvga)); | 883 | ARRAY_SIZE(sensor_start_qvga)); |
1760 | } else { /* 640x480 */ | 884 | } else { /* 640x480 */ |
1761 | reg_w_array(gspca_dev, bridge_start_ov772x_vga, | 885 | reg_w_array(gspca_dev, bridge_start_vga, |
1762 | ARRAY_SIZE(bridge_start_ov772x_vga)); | 886 | ARRAY_SIZE(bridge_start_vga)); |
1763 | sccb_w_array(gspca_dev, sensor_start_ov772x_vga, | 887 | sccb_w_array(gspca_dev, sensor_start_vga, |
1764 | ARRAY_SIZE(sensor_start_ov772x_vga)); | 888 | ARRAY_SIZE(sensor_start_vga)); |
1765 | } | 889 | } |
1766 | set_frame_rate(gspca_dev); | 890 | set_frame_rate(gspca_dev); |
1767 | 891 | ||
1768 | setautogain_77(gspca_dev); | 892 | setautogain(gspca_dev); |
1769 | setawb(gspca_dev); | 893 | setawb(gspca_dev); |
1770 | setgain(gspca_dev); | 894 | setgain(gspca_dev); |
1771 | setredblc(gspca_dev); | 895 | setredblc(gspca_dev); |
1772 | setblueblc(gspca_dev); | 896 | setblueblc(gspca_dev); |
1773 | sethue(gspca_dev); | 897 | sethue(gspca_dev); |
1774 | setexposure_77(gspca_dev); | 898 | setexposure(gspca_dev); |
1775 | setbrightness_77(gspca_dev); | 899 | setbrightness(gspca_dev); |
1776 | setcontrast_77(gspca_dev); | 900 | setcontrast(gspca_dev); |
1777 | setsharpness_77(gspca_dev); | 901 | setsharpness(gspca_dev); |
1778 | setvflip(gspca_dev); | 902 | setvflip(gspca_dev); |
1779 | sethflip(gspca_dev); | 903 | sethflip(gspca_dev); |
1780 | 904 | ||
@@ -1783,81 +907,12 @@ static int sd_start_ov772x(struct gspca_dev *gspca_dev) | |||
1783 | return 0; | 907 | return 0; |
1784 | } | 908 | } |
1785 | 909 | ||
1786 | static int sd_start_ov965x(struct gspca_dev *gspca_dev) | 910 | static void sd_stopN(struct gspca_dev *gspca_dev) |
1787 | { | ||
1788 | int mode; | ||
1789 | |||
1790 | mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; | ||
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)); | ||
1796 | reg_w_array(gspca_dev, bridge_start_ov965x_qvga, | ||
1797 | ARRAY_SIZE(bridge_start_ov965x_qvga)); | ||
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)); | ||
1804 | reg_w_array(gspca_dev, bridge_start_ov965x_vga, | ||
1805 | ARRAY_SIZE(bridge_start_ov965x_vga)); | ||
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; | ||
1833 | } | ||
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 | |||
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 | |||
1848 | static void sd_stopN_ov772x(struct gspca_dev *gspca_dev) | ||
1849 | { | 911 | { |
1850 | ov534_reg_write(gspca_dev, 0xe0, 0x09); | 912 | ov534_reg_write(gspca_dev, 0xe0, 0x09); |
1851 | ov534_set_led(gspca_dev, 0); | 913 | ov534_set_led(gspca_dev, 0); |
1852 | } | 914 | } |
1853 | 915 | ||
1854 | static 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); | ||
1859 | } | ||
1860 | |||
1861 | /* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */ | 916 | /* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */ |
1862 | #define UVC_STREAM_EOH (1 << 7) | 917 | #define UVC_STREAM_EOH (1 << 7) |
1863 | #define UVC_STREAM_ERR (1 << 6) | 918 | #define UVC_STREAM_ERR (1 << 6) |
@@ -1875,11 +930,9 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
1875 | __u32 this_pts; | 930 | __u32 this_pts; |
1876 | u16 this_fid; | 931 | u16 this_fid; |
1877 | int remaining_len = len; | 932 | int remaining_len = len; |
1878 | int payload_len; | ||
1879 | 933 | ||
1880 | payload_len = gspca_dev->cam.bulk ? 2048 : 2040; | ||
1881 | do { | 934 | do { |
1882 | len = min(remaining_len, payload_len); | 935 | len = min(remaining_len, 2048); |
1883 | 936 | ||
1884 | /* Payloads are prefixed with a UVC-style header. We | 937 | /* Payloads are prefixed with a UVC-style header. We |
1885 | consider a frame to start when the FID toggles, or the PTS | 938 | consider a frame to start when the FID toggles, or the PTS |
@@ -1918,7 +971,17 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
1918 | data + 12, len - 12); | 971 | data + 12, len - 12); |
1919 | /* If this packet is marked as EOF, end the frame */ | 972 | /* If this packet is marked as EOF, end the frame */ |
1920 | } else if (data[1] & UVC_STREAM_EOF) { | 973 | } else if (data[1] & UVC_STREAM_EOF) { |
974 | struct gspca_frame *frame; | ||
975 | |||
1921 | sd->last_pts = 0; | 976 | sd->last_pts = 0; |
977 | frame = gspca_get_i_frame(gspca_dev); | ||
978 | if (frame == NULL) | ||
979 | goto discard; | ||
980 | if (frame->data_end - frame->data != | ||
981 | gspca_dev->width * gspca_dev->height * 2) { | ||
982 | PDEBUG(D_PACK, "short frame"); | ||
983 | goto discard; | ||
984 | } | ||
1922 | gspca_frame_add(gspca_dev, LAST_PACKET, | 985 | gspca_frame_add(gspca_dev, LAST_PACKET, |
1923 | data + 12, len - 12); | 986 | data + 12, len - 12); |
1924 | } else { | 987 | } else { |
@@ -1965,12 +1028,8 @@ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) | |||
1965 | struct sd *sd = (struct sd *) gspca_dev; | 1028 | struct sd *sd = (struct sd *) gspca_dev; |
1966 | 1029 | ||
1967 | sd->exposure = val; | 1030 | sd->exposure = val; |
1968 | if (gspca_dev->streaming) { | 1031 | if (gspca_dev->streaming) |
1969 | if (sd->sensor == SENSOR_OV772X) | 1032 | setexposure(gspca_dev); |
1970 | setexposure_77(gspca_dev); | ||
1971 | else | ||
1972 | setexposure_96(gspca_dev); | ||
1973 | } | ||
1974 | return 0; | 1033 | return 0; |
1975 | } | 1034 | } |
1976 | 1035 | ||
@@ -1987,12 +1046,8 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | |||
1987 | struct sd *sd = (struct sd *) gspca_dev; | 1046 | struct sd *sd = (struct sd *) gspca_dev; |
1988 | 1047 | ||
1989 | sd->brightness = val; | 1048 | sd->brightness = val; |
1990 | if (gspca_dev->streaming) { | 1049 | if (gspca_dev->streaming) |
1991 | if (sd->sensor == SENSOR_OV772X) | 1050 | setbrightness(gspca_dev); |
1992 | setbrightness_77(gspca_dev); | ||
1993 | else | ||
1994 | setbrightness_96(gspca_dev); | ||
1995 | } | ||
1996 | return 0; | 1051 | return 0; |
1997 | } | 1052 | } |
1998 | 1053 | ||
@@ -2009,12 +1064,8 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | |||
2009 | struct sd *sd = (struct sd *) gspca_dev; | 1064 | struct sd *sd = (struct sd *) gspca_dev; |
2010 | 1065 | ||
2011 | sd->contrast = val; | 1066 | sd->contrast = val; |
2012 | if (gspca_dev->streaming) { | 1067 | if (gspca_dev->streaming) |
2013 | if (sd->sensor == SENSOR_OV772X) | 1068 | setcontrast(gspca_dev); |
2014 | setcontrast_77(gspca_dev); | ||
2015 | else | ||
2016 | setcontrast_96(gspca_dev); | ||
2017 | } | ||
2018 | return 0; | 1069 | return 0; |
2019 | } | 1070 | } |
2020 | 1071 | ||
@@ -2026,41 +1077,6 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | |||
2026 | return 0; | 1077 | return 0; |
2027 | } | 1078 | } |
2028 | 1079 | ||
2029 | static 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 | |||
2039 | static 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 | } | ||
2046 | static 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 | |||
2056 | static 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 | |||
2064 | static int sd_setredblc(struct gspca_dev *gspca_dev, __s32 val) | 1080 | static int sd_setredblc(struct gspca_dev *gspca_dev, __s32 val) |
2065 | { | 1081 | { |
2066 | struct sd *sd = (struct sd *) gspca_dev; | 1082 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -2122,22 +1138,14 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | |||
2122 | sd->autogain = val; | 1138 | sd->autogain = val; |
2123 | 1139 | ||
2124 | if (gspca_dev->streaming) { | 1140 | if (gspca_dev->streaming) { |
2125 | if (sd->sensor == SENSOR_OV772X) { | 1141 | |
2126 | 1142 | /* the auto white balance control works only | |
2127 | /* the auto white balance control works only | 1143 | * when auto gain is set */ |
2128 | * when auto gain is set */ | 1144 | if (val) |
2129 | if (val) | 1145 | gspca_dev->ctrl_inac &= ~(1 << AWB_IDX); |
2130 | gspca_dev->ctrl_inac &= ~(1 << AWB_77_IDX); | 1146 | else |
2131 | else | 1147 | gspca_dev->ctrl_inac |= (1 << AWB_IDX); |
2132 | gspca_dev->ctrl_inac |= (1 << AWB_77_IDX); | 1148 | setautogain(gspca_dev); |
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 | } | 1149 | } |
2142 | return 0; | 1150 | return 0; |
2143 | } | 1151 | } |
@@ -2173,12 +1181,8 @@ static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val) | |||
2173 | struct sd *sd = (struct sd *) gspca_dev; | 1181 | struct sd *sd = (struct sd *) gspca_dev; |
2174 | 1182 | ||
2175 | sd->sharpness = val; | 1183 | sd->sharpness = val; |
2176 | if (gspca_dev->streaming) { | 1184 | if (gspca_dev->streaming) |
2177 | if (sd->sensor == SENSOR_OV772X) | 1185 | setsharpness(gspca_dev); |
2178 | setsharpness_77(gspca_dev); | ||
2179 | else | ||
2180 | setsharpness_96(gspca_dev); | ||
2181 | } | ||
2182 | return 0; | 1186 | return 0; |
2183 | } | 1187 | } |
2184 | 1188 | ||
@@ -2257,7 +1261,7 @@ static int sd_set_streamparm(struct gspca_dev *gspca_dev, | |||
2257 | 1261 | ||
2258 | /* Set requested framerate */ | 1262 | /* Set requested framerate */ |
2259 | sd->frame_rate = tpf->denominator / tpf->numerator; | 1263 | sd->frame_rate = tpf->denominator / tpf->numerator; |
2260 | if (gspca_dev->streaming && sd->sensor == SENSOR_OV772X) | 1264 | if (gspca_dev->streaming) |
2261 | set_frame_rate(gspca_dev); | 1265 | set_frame_rate(gspca_dev); |
2262 | 1266 | ||
2263 | /* Return the actual framerate */ | 1267 | /* Return the actual framerate */ |
@@ -2267,57 +1271,23 @@ static int sd_set_streamparm(struct gspca_dev *gspca_dev, | |||
2267 | return 0; | 1271 | return 0; |
2268 | } | 1272 | } |
2269 | 1273 | ||
2270 | static 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 | |||
2291 | /* sub-driver description */ | 1274 | /* sub-driver description */ |
2292 | static const struct sd_desc sd_desc_ov772x = { | 1275 | static const struct sd_desc sd_desc = { |
2293 | .name = MODULE_NAME, | 1276 | .name = MODULE_NAME, |
2294 | .ctrls = sd_ctrls_ov772x, | 1277 | .ctrls = sd_ctrls, |
2295 | .nctrls = ARRAY_SIZE(sd_ctrls_ov772x), | 1278 | .nctrls = ARRAY_SIZE(sd_ctrls), |
2296 | .config = sd_config, | 1279 | .config = sd_config, |
2297 | .init = sd_init, | 1280 | .init = sd_init, |
2298 | .start = sd_start_ov772x, | 1281 | .start = sd_start, |
2299 | .stopN = sd_stopN_ov772x, | 1282 | .stopN = sd_stopN, |
2300 | .pkt_scan = sd_pkt_scan, | 1283 | .pkt_scan = sd_pkt_scan, |
2301 | .get_streamparm = sd_get_streamparm, | 1284 | .get_streamparm = sd_get_streamparm, |
2302 | .set_streamparm = sd_set_streamparm, | 1285 | .set_streamparm = sd_set_streamparm, |
2303 | }; | 1286 | }; |
2304 | 1287 | ||
2305 | static 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, | ||
2313 | .pkt_scan = sd_pkt_scan, | ||
2314 | .querymenu = sd_querymenu, | ||
2315 | }; | ||
2316 | |||
2317 | /* -- module initialisation -- */ | 1288 | /* -- module initialisation -- */ |
2318 | static const __devinitdata struct usb_device_id device_table[] = { | 1289 | static const __devinitdata struct usb_device_id device_table[] = { |
2319 | {USB_DEVICE(0x06f8, 0x3003), .driver_info = SENSOR_OV965X}, | 1290 | {USB_DEVICE(0x1415, 0x2000)}, |
2320 | {USB_DEVICE(0x1415, 0x2000), .driver_info = SENSOR_OV772X}, | ||
2321 | {} | 1291 | {} |
2322 | }; | 1292 | }; |
2323 | 1293 | ||
@@ -2326,11 +1296,7 @@ MODULE_DEVICE_TABLE(usb, device_table); | |||
2326 | /* -- device connect -- */ | 1296 | /* -- device connect -- */ |
2327 | static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id) | 1297 | static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id) |
2328 | { | 1298 | { |
2329 | return gspca_dev_probe(intf, id, | 1299 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), |
2330 | id->driver_info == SENSOR_OV772X | ||
2331 | ? &sd_desc_ov772x | ||
2332 | : &sd_desc_ov965x, | ||
2333 | sizeof(struct sd), | ||
2334 | THIS_MODULE); | 1300 | THIS_MODULE); |
2335 | } | 1301 | } |
2336 | 1302 | ||
diff --git a/drivers/media/video/gspca/ov534_9.c b/drivers/media/video/gspca/ov534_9.c new file mode 100644 index 000000000000..464b7f50827d --- /dev/null +++ b/drivers/media/video/gspca/ov534_9.c | |||
@@ -0,0 +1,1477 @@ | |||
1 | /* | ||
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 | |||
44 | MODULE_AUTHOR("Jean-Francois Moine <moinejf@free.fr>"); | ||
45 | MODULE_DESCRIPTION("GSPCA/OV534_9 USB Camera Driver"); | ||
46 | MODULE_LICENSE("GPL"); | ||
47 | |||
48 | /* specific webcam descriptor */ | ||
49 | struct 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 */ | ||
64 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
65 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
66 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
67 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
68 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
69 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | ||
70 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | ||
71 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
72 | static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val); | ||
73 | static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val); | ||
74 | static int sd_setsatur(struct gspca_dev *gspca_dev, __s32 val); | ||
75 | static int sd_getsatur(struct gspca_dev *gspca_dev, __s32 *val); | ||
76 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | ||
77 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | ||
78 | |||
79 | static 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 | |||
181 | static 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 | |||
209 | static 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 | |||
243 | static 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 | |||
425 | static 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 | |||
453 | static 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 | |||
495 | static 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 | |||
518 | static 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 | |||
540 | static 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 | |||
563 | static 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 | |||
586 | static 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 | |||
614 | static 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 | |||
641 | static 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 | |||
668 | static 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 | |||
695 | static 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 | |||
712 | static 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 | |||
730 | static 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 | |||
746 | static 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 | |||
760 | static 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 | |||
774 | static 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) { | ||
788 | PDEBUG(D_ERR, "reg_w failed %d", ret); | ||
789 | gspca_dev->usb_err = ret; | ||
790 | } | ||
791 | } | ||
792 | |||
793 | static 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 | |||
799 | static 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) { | ||
813 | PDEBUG(D_ERR, "reg_r err %d", ret); | ||
814 | gspca_dev->usb_err = ret; | ||
815 | } | ||
816 | return gspca_dev->usb_buf[0]; | ||
817 | } | ||
818 | |||
819 | static 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 | |||
843 | static 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)) | ||
851 | PDEBUG(D_ERR, "sccb_write failed"); | ||
852 | } | ||
853 | |||
854 | static 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)) | ||
859 | PDEBUG(D_ERR, "sccb_read failed 1"); | ||
860 | |||
861 | reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2); | ||
862 | if (!sccb_check_status(gspca_dev)) | ||
863 | PDEBUG(D_ERR, "sccb_read failed 2"); | ||
864 | |||
865 | return reg_r(gspca_dev, OV534_REG_READ); | ||
866 | } | ||
867 | |||
868 | /* output a bridge sequence (reg - val) */ | ||
869 | static 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) */ | ||
879 | static 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)? */ | ||
895 | static 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 | |||
920 | static 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 | |||
934 | static 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 | |||
942 | static 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 | |||
958 | static 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 | |||
976 | static 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 | |||
998 | static 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 | |||
1026 | static 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 */ | ||
1049 | static 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 */ | ||
1079 | static 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 | |||
1116 | return 0; | ||
1117 | } | ||
1118 | |||
1119 | static 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); | ||
1175 | return 0; | ||
1176 | } | ||
1177 | |||
1178 | static 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 | |||
1195 | static 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 | |||
1256 | discard: | ||
1257 | /* Discard data until a new frame starts. */ | ||
1258 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
1259 | |||
1260 | scan_next: | ||
1261 | remaining_len -= len; | ||
1262 | data += len; | ||
1263 | } while (remaining_len > 0); | ||
1264 | } | ||
1265 | |||
1266 | /* controls */ | ||
1267 | static 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); | ||
1274 | return 0; | ||
1275 | } | ||
1276 | |||
1277 | static 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 | |||
1285 | static 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); | ||
1292 | return 0; | ||
1293 | } | ||
1294 | |||
1295 | static 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 | |||
1303 | static 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 | } | ||
1316 | return 0; | ||
1317 | } | ||
1318 | |||
1319 | static 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 | |||
1327 | static 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); | ||
1334 | return 0; | ||
1335 | } | ||
1336 | |||
1337 | static 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 | |||
1345 | static 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); | ||
1352 | return 0; | ||
1353 | } | ||
1354 | |||
1355 | static 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 | |||
1363 | static 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); | ||
1370 | return 0; | ||
1371 | } | ||
1372 | |||
1373 | static 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 | } | ||
1380 | static 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); | ||
1387 | return 0; | ||
1388 | } | ||
1389 | |||
1390 | static 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 | |||
1398 | static 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 */ | ||
1420 | static 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 -- */ | ||
1433 | static const __devinitdata struct usb_device_id device_table[] = { | ||
1434 | {USB_DEVICE(0x06f8, 0x3003)}, | ||
1435 | {} | ||
1436 | }; | ||
1437 | |||
1438 | MODULE_DEVICE_TABLE(usb, device_table); | ||
1439 | |||
1440 | /* -- device connect -- */ | ||
1441 | static 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 | |||
1447 | static 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 -- */ | ||
1459 | static int __init sd_mod_init(void) | ||
1460 | { | ||
1461 | int ret; | ||
1462 | |||
1463 | ret = usb_register(&sd_driver); | ||
1464 | if (ret < 0) | ||
1465 | return ret; | ||
1466 | PDEBUG(D_PROBE, "registered"); | ||
1467 | return 0; | ||
1468 | } | ||
1469 | |||
1470 | static void __exit sd_mod_exit(void) | ||
1471 | { | ||
1472 | usb_deregister(&sd_driver); | ||
1473 | PDEBUG(D_PROBE, "deregistered"); | ||
1474 | } | ||
1475 | |||
1476 | module_init(sd_mod_init); | ||
1477 | module_exit(sd_mod_exit); | ||