diff options
author | Olivier Lorin <o.lorin@laposte.net> | 2009-10-15 03:20:54 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-12-05 15:40:50 -0500 |
commit | fdd1dd1d246e14dacd8fb0bf842828b03bed2481 (patch) | |
tree | 23c63e895e965d869300dde37c3269d8d8b4ed58 | |
parent | be9904bdde05137085af1df98de98a49ddce9ad8 (diff) |
V4L/DVB (13196): gspca - gl860: add flip/mirror for OV2640
- add flip/mirror support for OV2640
- fix for backlight value range
- fix for red-blue inversion hue mode with V4L1 applications
Signed-off-by: Olivier Lorin <o.lorin@laposte.net>
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/gspca/gl860/gl860-ov2640.c | 99 |
1 files changed, 41 insertions, 58 deletions
diff --git a/drivers/media/video/gspca/gl860/gl860-ov2640.c b/drivers/media/video/gspca/gl860/gl860-ov2640.c index e0837432d394..768cac5cd72b 100644 --- a/drivers/media/video/gspca/gl860/gl860-ov2640.c +++ b/drivers/media/video/gspca/gl860/gl860-ov2640.c | |||
@@ -20,8 +20,12 @@ | |||
20 | #include "gl860.h" | 20 | #include "gl860.h" |
21 | 21 | ||
22 | static u8 dat_init1[] = "\x00\x41\x07\x6a\x06\x61\x0d\x6a" "\x10\x10\xc1\x01"; | 22 | static u8 dat_init1[] = "\x00\x41\x07\x6a\x06\x61\x0d\x6a" "\x10\x10\xc1\x01"; |
23 | static u8 dat_init2[] = {0x61}; /* expected */ | 23 | |
24 | static u8 dat_init3[] = {0x51}; /* expected */ | 24 | static u8 c61[] = {0x61}; /* expected */ |
25 | static u8 c51[] = {0x51}; /* expected */ | ||
26 | static u8 c50[] = {0x50}; /* expected */ | ||
27 | static u8 c28[] = {0x28}; /* expected */ | ||
28 | static u8 ca8[] = {0xa8}; /* expected */ | ||
25 | 29 | ||
26 | static u8 dat_post[] = | 30 | static u8 dat_post[] = |
27 | "\x00\x41\x07\x6a\x06\xef\x0d\x6a" "\x10\x10\xc1\x01"; | 31 | "\x00\x41\x07\x6a\x06\xef\x0d\x6a" "\x10\x10\xc1\x01"; |
@@ -31,10 +35,6 @@ static u8 dat_800[] = "\xd0\x01\xd1\x10\xd2\x58\xd3\x02\xd4\x18\xd5\x21"; | |||
31 | static u8 dat_1280[] = "\xd0\x01\xd1\x18\xd2\xc0\xd3\x02\xd4\x28\xd5\x01"; | 35 | static u8 dat_1280[] = "\xd0\x01\xd1\x18\xd2\xc0\xd3\x02\xd4\x28\xd5\x01"; |
32 | static u8 dat_1600[] = "\xd0\x01\xd1\x20\xd2\xb0\xd3\x02\xd4\x30\xd5\x41"; | 36 | static u8 dat_1600[] = "\xd0\x01\xd1\x20\xd2\xb0\xd3\x02\xd4\x30\xd5\x41"; |
33 | 37 | ||
34 | static u8 c50[] = {0x50}; /* expected */ | ||
35 | static u8 c28[] = {0x28}; /* expected */ | ||
36 | static u8 ca8[] = {0xa8}; /* expected */ | ||
37 | |||
38 | static struct validx tbl_init_at_startup[] = { | 38 | static struct validx tbl_init_at_startup[] = { |
39 | {0x0000, 0x0000}, {0x0010, 0x0010}, {0x0008, 0x00c0}, {0x0001, 0x00c1}, | 39 | {0x0000, 0x0000}, {0x0010, 0x0010}, {0x0008, 0x00c0}, {0x0001, 0x00c1}, |
40 | {0x0001, 0x00c2}, {0x0020, 0x0006}, {0x006a, 0x000d}, | 40 | {0x0001, 0x00c2}, {0x0020, 0x0006}, {0x006a, 0x000d}, |
@@ -107,36 +107,6 @@ static struct validx tbl_sensor_settings_common2[] = { | |||
107 | {0x6001, 0x00ff}, {0x6038, 0x000c}, | 107 | {0x6001, 0x00ff}, {0x6038, 0x000c}, |
108 | {10, 0xffff}, | 108 | {10, 0xffff}, |
109 | {0x6000, 0x0011}, | 109 | {0x6000, 0x0011}, |
110 | /* backlight=31/64 */ | ||
111 | {0x6001, 0x00ff}, {0x603e, 0x0024}, {0x6034, 0x0025}, | ||
112 | /* bright=0/256 */ | ||
113 | {0x6000, 0x00ff}, {0x6009, 0x007c}, {0x6000, 0x007d}, | ||
114 | /* wbal=64/128 */ | ||
115 | {0x6000, 0x00ff}, {0x6003, 0x007c}, {0x6040, 0x007d}, | ||
116 | /* cntr=0/256 */ | ||
117 | {0x6000, 0x00ff}, {0x6007, 0x007c}, {0x6000, 0x007d}, | ||
118 | /* sat=128/256 */ | ||
119 | {0x6000, 0x00ff}, {0x6001, 0x007c}, {0x6080, 0x007d}, | ||
120 | /* sharpness=0/32 */ | ||
121 | {0x6000, 0x00ff}, {0x6001, 0x0092}, {0x60c0, 0x0093}, | ||
122 | /* hue=0/256 */ | ||
123 | {0x6000, 0x00ff}, {0x6002, 0x007c}, {0x6000, 0x007d}, | ||
124 | /* gam=32/64 */ | ||
125 | {0x6000, 0x00ff}, {0x6008, 0x007c}, {0x6020, 0x007d}, | ||
126 | /* image right up */ | ||
127 | {0xffff, 0xffff}, | ||
128 | {15, 0xffff}, | ||
129 | {0x6001, 0x00ff}, {0x6000, 0x8004}, | ||
130 | {0xffff, 0xffff}, | ||
131 | {0x60a8, 0x0004}, | ||
132 | {15, 0xffff}, | ||
133 | {0x6001, 0x00ff}, {0x6000, 0x8004}, | ||
134 | {0xffff, 0xffff}, | ||
135 | {0x60f8, 0x0004}, | ||
136 | /* image right up */ | ||
137 | {0xffff, 0xffff}, | ||
138 | /* backlight=31/64 */ | ||
139 | {0x6001, 0x00ff}, {0x603e, 0x0024}, {0x6034, 0x0025}, | ||
140 | }; | 110 | }; |
141 | 111 | ||
142 | static struct validx tbl_640[] = { | 112 | static struct validx tbl_640[] = { |
@@ -222,17 +192,19 @@ void ov2640_init_settings(struct gspca_dev *gspca_dev) | |||
222 | sd->vcur.hue = 0; | 192 | sd->vcur.hue = 0; |
223 | sd->vcur.saturation = 128; | 193 | sd->vcur.saturation = 128; |
224 | sd->vcur.whitebal = 64; | 194 | sd->vcur.whitebal = 64; |
195 | sd->vcur.mirror = 0; | ||
196 | sd->vcur.flip = 0; | ||
225 | 197 | ||
226 | sd->vmax.backlight = 64; | 198 | sd->vmax.backlight = 64; |
227 | sd->vmax.brightness = 255; | 199 | sd->vmax.brightness = 255; |
228 | sd->vmax.sharpness = 31; | 200 | sd->vmax.sharpness = 31; |
229 | sd->vmax.contrast = 255; | 201 | sd->vmax.contrast = 255; |
230 | sd->vmax.gamma = 64; | 202 | sd->vmax.gamma = 64; |
231 | sd->vmax.hue = 255 + 1; | 203 | sd->vmax.hue = 254 + 2; |
232 | sd->vmax.saturation = 255; | 204 | sd->vmax.saturation = 255; |
233 | sd->vmax.whitebal = 128; | 205 | sd->vmax.whitebal = 128; |
234 | sd->vmax.mirror = 0; | 206 | sd->vmax.mirror = 1; |
235 | sd->vmax.flip = 0; | 207 | sd->vmax.flip = 1; |
236 | sd->vmax.AC50Hz = 0; | 208 | sd->vmax.AC50Hz = 0; |
237 | 209 | ||
238 | sd->dev_camera_settings = ov2640_camera_settings; | 210 | sd->dev_camera_settings = ov2640_camera_settings; |
@@ -258,11 +230,11 @@ static int ov2640_init_at_startup(struct gspca_dev *gspca_dev) | |||
258 | 230 | ||
259 | common(gspca_dev); | 231 | common(gspca_dev); |
260 | 232 | ||
261 | ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0006, 1, dat_init2); | 233 | ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0006, 1, c61); |
262 | 234 | ||
263 | ctrl_out(gspca_dev, 0x40, 1, 0x00ef, 0x0006, 0, NULL); | 235 | ctrl_out(gspca_dev, 0x40, 1, 0x00ef, 0x0006, 0, NULL); |
264 | 236 | ||
265 | ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, dat_init3); | 237 | ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, c51); |
266 | 238 | ||
267 | ctrl_out(gspca_dev, 0x40, 1, 0x0051, 0x0000, 0, NULL); | 239 | ctrl_out(gspca_dev, 0x40, 1, 0x0051, 0x0000, 0, NULL); |
268 | /* ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL); */ | 240 | /* ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL); */ |
@@ -284,6 +256,8 @@ static int ov2640_init_pre_alt(struct gspca_dev *gspca_dev) | |||
284 | sd->vold.gamma = -1; | 256 | sd->vold.gamma = -1; |
285 | sd->vold.hue = -1; | 257 | sd->vold.hue = -1; |
286 | sd->vold.whitebal = -1; | 258 | sd->vold.whitebal = -1; |
259 | sd->vold.mirror = -1; | ||
260 | sd->vold.flip = -1; | ||
287 | 261 | ||
288 | ov2640_init_post_alt(gspca_dev); | 262 | ov2640_init_post_alt(gspca_dev); |
289 | 263 | ||
@@ -346,18 +320,6 @@ static int ov2640_init_post_alt(struct gspca_dev *gspca_dev) | |||
346 | 320 | ||
347 | n = fetch_validx(gspca_dev, tbl_sensor_settings_common2, | 321 | n = fetch_validx(gspca_dev, tbl_sensor_settings_common2, |
348 | ARRAY_SIZE(tbl_sensor_settings_common2)); | 322 | ARRAY_SIZE(tbl_sensor_settings_common2)); |
349 | ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, c50); | ||
350 | keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common2, | ||
351 | ARRAY_SIZE(tbl_sensor_settings_common2), n); | ||
352 | ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, c28); | ||
353 | keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common2, | ||
354 | ARRAY_SIZE(tbl_sensor_settings_common2), n); | ||
355 | ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, ca8); | ||
356 | keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common2, | ||
357 | ARRAY_SIZE(tbl_sensor_settings_common2), n); | ||
358 | ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, c50); | ||
359 | keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common2, | ||
360 | ARRAY_SIZE(tbl_sensor_settings_common2), n); | ||
361 | 323 | ||
362 | ov2640_camera_settings(gspca_dev); | 324 | ov2640_camera_settings(gspca_dev); |
363 | 325 | ||
@@ -394,6 +356,8 @@ static int ov2640_camera_settings(struct gspca_dev *gspca_dev) | |||
394 | s32 sat = sd->vcur.saturation; | 356 | s32 sat = sd->vcur.saturation; |
395 | s32 hue = sd->vcur.hue; | 357 | s32 hue = sd->vcur.hue; |
396 | s32 wbal = sd->vcur.whitebal; | 358 | s32 wbal = sd->vcur.whitebal; |
359 | s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) == 0); | ||
360 | s32 flip = (((sd->vcur.flip > 0) ^ sd->mirrorMask) == 0); | ||
397 | 361 | ||
398 | if (backlight != sd->vold.backlight) { | 362 | if (backlight != sd->vold.backlight) { |
399 | /* No sd->vold.backlight=backlight; (to be done again later) */ | 363 | /* No sd->vold.backlight=backlight; (to be done again later) */ |
@@ -402,9 +366,9 @@ static int ov2640_camera_settings(struct gspca_dev *gspca_dev) | |||
402 | 366 | ||
403 | ctrl_out(gspca_dev, 0x40, 1, 0x6001 , 0x00ff, | 367 | ctrl_out(gspca_dev, 0x40, 1, 0x6001 , 0x00ff, |
404 | 0, NULL); | 368 | 0, NULL); |
405 | ctrl_out(gspca_dev, 0x40, 1, 0x601f + backlight , 0x0024, | 369 | ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight , 0x0024, |
406 | 0, NULL); | 370 | 0, NULL); |
407 | ctrl_out(gspca_dev, 0x40, 1, 0x601f + backlight - 10, 0x0025, | 371 | ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight - 10, 0x0025, |
408 | 0, NULL); | 372 | 0, NULL); |
409 | } | 373 | } |
410 | 374 | ||
@@ -467,7 +431,7 @@ static int ov2640_camera_settings(struct gspca_dev *gspca_dev) | |||
467 | ctrl_out(gspca_dev, 0x40, 1, 0x6002 , 0x007c, 0, NULL); | 431 | ctrl_out(gspca_dev, 0x40, 1, 0x6002 , 0x007c, 0, NULL); |
468 | ctrl_out(gspca_dev, 0x40, 1, 0x6000 + hue * (hue < 255), 0x007d, | 432 | ctrl_out(gspca_dev, 0x40, 1, 0x6000 + hue * (hue < 255), 0x007d, |
469 | 0, NULL); | 433 | 0, NULL); |
470 | if (hue >= sd->vmax.hue) | 434 | if (hue >= 255) |
471 | sd->swapRB = 1; | 435 | sd->swapRB = 1; |
472 | else | 436 | else |
473 | sd->swapRB = 0; | 437 | sd->swapRB = 0; |
@@ -483,14 +447,33 @@ static int ov2640_camera_settings(struct gspca_dev *gspca_dev) | |||
483 | ctrl_out(gspca_dev, 0x40, 1, 0x6000 + gam, 0x007d, 0, NULL); | 447 | ctrl_out(gspca_dev, 0x40, 1, 0x6000 + gam, 0x007d, 0, NULL); |
484 | } | 448 | } |
485 | 449 | ||
450 | if (mirror != sd->vold.mirror || flip != sd->vold.flip) { | ||
451 | sd->vold.mirror = mirror; | ||
452 | sd->vold.flip = flip; | ||
453 | |||
454 | mirror = 0x80 * mirror; | ||
455 | ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL); | ||
456 | ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x8004, 0, NULL); | ||
457 | ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, c28); | ||
458 | ctrl_out(gspca_dev, 0x40, 1, 0x6028 + mirror, 0x0004, 0, NULL); | ||
459 | |||
460 | flip = 0x50 * flip + mirror; | ||
461 | ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL); | ||
462 | ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x8004, 0, NULL); | ||
463 | ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, ca8); | ||
464 | ctrl_out(gspca_dev, 0x40, 1, 0x6028 + flip, 0x0004, 0, NULL); | ||
465 | |||
466 | ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, c50); | ||
467 | } | ||
468 | |||
486 | if (backlight != sd->vold.backlight) { | 469 | if (backlight != sd->vold.backlight) { |
487 | sd->vold.backlight = backlight; | 470 | sd->vold.backlight = backlight; |
488 | 471 | ||
489 | ctrl_out(gspca_dev, 0x40, 1, 0x6001 , 0x00ff, | 472 | ctrl_out(gspca_dev, 0x40, 1, 0x6001 , 0x00ff, |
490 | 0, NULL); | 473 | 0, NULL); |
491 | ctrl_out(gspca_dev, 0x40, 1, 0x601f + backlight , 0x0024, | 474 | ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight , 0x0024, |
492 | 0, NULL); | 475 | 0, NULL); |
493 | ctrl_out(gspca_dev, 0x40, 1, 0x601f + backlight - 10, 0x0025, | 476 | ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight - 10, 0x0025, |
494 | 0, NULL); | 477 | 0, NULL); |
495 | } | 478 | } |
496 | 479 | ||