aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/ov519.c
diff options
context:
space:
mode:
authorJean-Francois Moine <moinejf@free.fr>2008-09-03 16:12:15 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-09-03 17:37:33 -0400
commit4202f71ca1e52d73cab14f3695fdef6b6f010a0b (patch)
tree154100d56c2727bdf94e4deaefc0be7943794212 /drivers/media/video/gspca/ov519.c
parent1e89e2da48070da8ac221c37fea8fa82da127c34 (diff)
V4L/DVB (8819): gspca: Initialize the ov519 at open time and source cleanup.
Signed-off-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/gspca/ov519.c')
-rw-r--r--drivers/media/video/gspca/ov519.c1142
1 files changed, 596 insertions, 546 deletions
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
index c132f8d2cf05..4062aed24139 100644
--- a/drivers/media/video/gspca/ov519.c
+++ b/drivers/media/video/gspca/ov519.c
@@ -63,11 +63,10 @@ struct sd {
63#define SEN_OV6630 2 63#define SEN_OV6630 2
64#define SEN_OV7610 3 64#define SEN_OV7610 3
65#define SEN_OV7620 4 65#define SEN_OV7620 4
66#define SEN_OV7630 5 66#define SEN_OV7640 5
67#define SEN_OV7640 6 67#define SEN_OV7670 6
68#define SEN_OV7670 7 68#define SEN_OV76BE 7
69#define SEN_OV76BE 8 69#define SEN_OV8610 8
70#define SEN_OV8610 9
71 70
72}; 71};
73 72
@@ -293,6 +292,541 @@ static struct v4l2_pix_format sif_mode[] = {
293#define OV7670_REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */ 292#define OV7670_REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */
294#define OV7670_REG_BD60MAX 0xab /* 60hz banding step limit */ 293#define OV7670_REG_BD60MAX 0xab /* 60hz banding step limit */
295 294
295struct ov_regvals {
296 __u8 reg;
297 __u8 val;
298};
299struct ov_i2c_regvals {
300 __u8 reg;
301 __u8 val;
302};
303
304static const struct ov_i2c_regvals norm_6x20[] = {
305 { 0x12, 0x80 }, /* reset */
306 { 0x11, 0x01 },
307 { 0x03, 0x60 },
308 { 0x05, 0x7f }, /* For when autoadjust is off */
309 { 0x07, 0xa8 },
310 /* The ratio of 0x0c and 0x0d controls the white point */
311 { 0x0c, 0x24 },
312 { 0x0d, 0x24 },
313 { 0x0f, 0x15 }, /* COMS */
314 { 0x10, 0x75 }, /* AEC Exposure time */
315 { 0x12, 0x24 }, /* Enable AGC */
316 { 0x14, 0x04 },
317 /* 0x16: 0x06 helps frame stability with moving objects */
318 { 0x16, 0x06 },
319/* { 0x20, 0x30 }, * Aperture correction enable */
320 { 0x26, 0xb2 }, /* BLC enable */
321 /* 0x28: 0x05 Selects RGB format if RGB on */
322 { 0x28, 0x05 },
323 { 0x2a, 0x04 }, /* Disable framerate adjust */
324/* { 0x2b, 0xac }, * Framerate; Set 2a[7] first */
325 { 0x2d, 0x99 },
326 { 0x33, 0xa0 }, /* Color Processing Parameter */
327 { 0x34, 0xd2 }, /* Max A/D range */
328 { 0x38, 0x8b },
329 { 0x39, 0x40 },
330
331 { 0x3c, 0x39 }, /* Enable AEC mode changing */
332 { 0x3c, 0x3c }, /* Change AEC mode */
333 { 0x3c, 0x24 }, /* Disable AEC mode changing */
334
335 { 0x3d, 0x80 },
336 /* These next two registers (0x4a, 0x4b) are undocumented.
337 * They control the color balance */
338 { 0x4a, 0x80 },
339 { 0x4b, 0x80 },
340 { 0x4d, 0xd2 }, /* This reduces noise a bit */
341 { 0x4e, 0xc1 },
342 { 0x4f, 0x04 },
343/* Do 50-53 have any effect? */
344/* Toggle 0x12[2] off and on here? */
345};
346
347static const struct ov_i2c_regvals norm_6x30[] = {
348 { 0x12, 0x80 }, /* Reset */
349 { 0x00, 0x1f }, /* Gain */
350 { 0x01, 0x99 }, /* Blue gain */
351 { 0x02, 0x7c }, /* Red gain */
352 { 0x03, 0xc0 }, /* Saturation */
353 { 0x05, 0x0a }, /* Contrast */
354 { 0x06, 0x95 }, /* Brightness */
355 { 0x07, 0x2d }, /* Sharpness */
356 { 0x0c, 0x20 },
357 { 0x0d, 0x20 },
358 { 0x0e, 0x20 },
359 { 0x0f, 0x05 },
360 { 0x10, 0x9a },
361 { 0x11, 0x00 }, /* Pixel clock = fastest */
362 { 0x12, 0x24 }, /* Enable AGC and AWB */
363 { 0x13, 0x21 },
364 { 0x14, 0x80 },
365 { 0x15, 0x01 },
366 { 0x16, 0x03 },
367 { 0x17, 0x38 },
368 { 0x18, 0xea },
369 { 0x19, 0x04 },
370 { 0x1a, 0x93 },
371 { 0x1b, 0x00 },
372 { 0x1e, 0xc4 },
373 { 0x1f, 0x04 },
374 { 0x20, 0x20 },
375 { 0x21, 0x10 },
376 { 0x22, 0x88 },
377 { 0x23, 0xc0 }, /* Crystal circuit power level */
378 { 0x25, 0x9a }, /* Increase AEC black ratio */
379 { 0x26, 0xb2 }, /* BLC enable */
380 { 0x27, 0xa2 },
381 { 0x28, 0x00 },
382 { 0x29, 0x00 },
383 { 0x2a, 0x84 }, /* 60 Hz power */
384 { 0x2b, 0xa8 }, /* 60 Hz power */
385 { 0x2c, 0xa0 },
386 { 0x2d, 0x95 }, /* Enable auto-brightness */
387 { 0x2e, 0x88 },
388 { 0x33, 0x26 },
389 { 0x34, 0x03 },
390 { 0x36, 0x8f },
391 { 0x37, 0x80 },
392 { 0x38, 0x83 },
393 { 0x39, 0x80 },
394 { 0x3a, 0x0f },
395 { 0x3b, 0x3c },
396 { 0x3c, 0x1a },
397 { 0x3d, 0x80 },
398 { 0x3e, 0x80 },
399 { 0x3f, 0x0e },
400 { 0x40, 0x00 }, /* White bal */
401 { 0x41, 0x00 }, /* White bal */
402 { 0x42, 0x80 },
403 { 0x43, 0x3f }, /* White bal */
404 { 0x44, 0x80 },
405 { 0x45, 0x20 },
406 { 0x46, 0x20 },
407 { 0x47, 0x80 },
408 { 0x48, 0x7f },
409 { 0x49, 0x00 },
410 { 0x4a, 0x00 },
411 { 0x4b, 0x80 },
412 { 0x4c, 0xd0 },
413 { 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */
414 { 0x4e, 0x40 },
415 { 0x4f, 0x07 }, /* UV avg., col. killer: max */
416 { 0x50, 0xff },
417 { 0x54, 0x23 }, /* Max AGC gain: 18dB */
418 { 0x55, 0xff },
419 { 0x56, 0x12 },
420 { 0x57, 0x81 },
421 { 0x58, 0x75 },
422 { 0x59, 0x01 }, /* AGC dark current comp.: +1 */
423 { 0x5a, 0x2c },
424 { 0x5b, 0x0f }, /* AWB chrominance levels */
425 { 0x5c, 0x10 },
426 { 0x3d, 0x80 },
427 { 0x27, 0xa6 },
428 { 0x12, 0x20 }, /* Toggle AWB */
429 { 0x12, 0x24 },
430};
431
432/* Lawrence Glaister <lg@jfm.bc.ca> reports:
433 *
434 * Register 0x0f in the 7610 has the following effects:
435 *
436 * 0x85 (AEC method 1): Best overall, good contrast range
437 * 0x45 (AEC method 2): Very overexposed
438 * 0xa5 (spec sheet default): Ok, but the black level is
439 * shifted resulting in loss of contrast
440 * 0x05 (old driver setting): very overexposed, too much
441 * contrast
442 */
443static const struct ov_i2c_regvals norm_7610[] = {
444 { 0x10, 0xff },
445 { 0x16, 0x06 },
446 { 0x28, 0x24 },
447 { 0x2b, 0xac },
448 { 0x12, 0x00 },
449 { 0x38, 0x81 },
450 { 0x28, 0x24 }, /* 0c */
451 { 0x0f, 0x85 }, /* lg's setting */
452 { 0x15, 0x01 },
453 { 0x20, 0x1c },
454 { 0x23, 0x2a },
455 { 0x24, 0x10 },
456 { 0x25, 0x8a },
457 { 0x26, 0xa2 },
458 { 0x27, 0xc2 },
459 { 0x2a, 0x04 },
460 { 0x2c, 0xfe },
461 { 0x2d, 0x93 },
462 { 0x30, 0x71 },
463 { 0x31, 0x60 },
464 { 0x32, 0x26 },
465 { 0x33, 0x20 },
466 { 0x34, 0x48 },
467 { 0x12, 0x24 },
468 { 0x11, 0x01 },
469 { 0x0c, 0x24 },
470 { 0x0d, 0x24 },
471};
472
473static const struct ov_i2c_regvals norm_7620[] = {
474 { 0x00, 0x00 }, /* gain */
475 { 0x01, 0x80 }, /* blue gain */
476 { 0x02, 0x80 }, /* red gain */
477 { 0x03, 0xc0 }, /* OV7670_REG_VREF */
478 { 0x06, 0x60 },
479 { 0x07, 0x00 },
480 { 0x0c, 0x24 },
481 { 0x0c, 0x24 },
482 { 0x0d, 0x24 },
483 { 0x11, 0x01 },
484 { 0x12, 0x24 },
485 { 0x13, 0x01 },
486 { 0x14, 0x84 },
487 { 0x15, 0x01 },
488 { 0x16, 0x03 },
489 { 0x17, 0x2f },
490 { 0x18, 0xcf },
491 { 0x19, 0x06 },
492 { 0x1a, 0xf5 },
493 { 0x1b, 0x00 },
494 { 0x20, 0x18 },
495 { 0x21, 0x80 },
496 { 0x22, 0x80 },
497 { 0x23, 0x00 },
498 { 0x26, 0xa2 },
499 { 0x27, 0xea },
500 { 0x28, 0x20 },
501 { 0x29, 0x00 },
502 { 0x2a, 0x10 },
503 { 0x2b, 0x00 },
504 { 0x2c, 0x88 },
505 { 0x2d, 0x91 },
506 { 0x2e, 0x80 },
507 { 0x2f, 0x44 },
508 { 0x60, 0x27 },
509 { 0x61, 0x02 },
510 { 0x62, 0x5f },
511 { 0x63, 0xd5 },
512 { 0x64, 0x57 },
513 { 0x65, 0x83 },
514 { 0x66, 0x55 },
515 { 0x67, 0x92 },
516 { 0x68, 0xcf },
517 { 0x69, 0x76 },
518 { 0x6a, 0x22 },
519 { 0x6b, 0x00 },
520 { 0x6c, 0x02 },
521 { 0x6d, 0x44 },
522 { 0x6e, 0x80 },
523 { 0x6f, 0x1d },
524 { 0x70, 0x8b },
525 { 0x71, 0x00 },
526 { 0x72, 0x14 },
527 { 0x73, 0x54 },
528 { 0x74, 0x00 },
529 { 0x75, 0x8e },
530 { 0x76, 0x00 },
531 { 0x77, 0xff },
532 { 0x78, 0x80 },
533 { 0x79, 0x80 },
534 { 0x7a, 0x80 },
535 { 0x7b, 0xe2 },
536 { 0x7c, 0x00 },
537};
538
539/* 7640 and 7648. The defaults should be OK for most registers. */
540static const struct ov_i2c_regvals norm_7640[] = {
541 { 0x12, 0x80 },
542 { 0x12, 0x14 },
543};
544
545/* 7670. Defaults taken from OmniVision provided data,
546* as provided by Jonathan Corbet of OLPC */
547static const struct ov_i2c_regvals norm_7670[] = {
548 { OV7670_REG_COM7, OV7670_COM7_RESET },
549 { OV7670_REG_TSLB, 0x04 }, /* OV */
550 { OV7670_REG_COM7, OV7670_COM7_FMT_VGA }, /* VGA */
551 { OV7670_REG_CLKRC, 0x01 },
552/*
553 * Set the hardware window. These values from OV don't entirely
554 * make sense - hstop is less than hstart. But they work...
555 */
556 { OV7670_REG_HSTART, 0x13 },
557 { OV7670_REG_HSTOP, 0x01 },
558 { OV7670_REG_HREF, 0xb6 },
559 { OV7670_REG_VSTART, 0x02 },
560 { OV7670_REG_VSTOP, 0x7a },
561 { OV7670_REG_VREF, 0x0a },
562
563 { OV7670_REG_COM3, 0 },
564 { OV7670_REG_COM14, 0 },
565/* Mystery scaling numbers */
566 { 0x70, 0x3a },
567 { 0x71, 0x35 },
568 { 0x72, 0x11 },
569 { 0x73, 0xf0 },
570 { 0xa2, 0x02 },
571/* { OV7670_REG_COM10, 0x0 }, */
572
573/* Gamma curve values */
574 { 0x7a, 0x20 },
575 { 0x7b, 0x10 },
576 { 0x7c, 0x1e },
577 { 0x7d, 0x35 },
578 { 0x7e, 0x5a },
579 { 0x7f, 0x69 },
580 { 0x80, 0x76 },
581 { 0x81, 0x80 },
582 { 0x82, 0x88 },
583 { 0x83, 0x8f },
584 { 0x84, 0x96 },
585 { 0x85, 0xa3 },
586 { 0x86, 0xaf },
587 { 0x87, 0xc4 },
588 { 0x88, 0xd7 },
589 { 0x89, 0xe8 },
590
591/* AGC and AEC parameters. Note we start by disabling those features,
592 then turn them only after tweaking the values. */
593 { OV7670_REG_COM8, OV7670_COM8_FASTAEC
594 | OV7670_COM8_AECSTEP
595 | OV7670_COM8_BFILT },
596 { OV7670_REG_GAIN, 0 },
597 { OV7670_REG_AECH, 0 },
598 { OV7670_REG_COM4, 0x40 }, /* magic reserved bit */
599 { OV7670_REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
600 { OV7670_REG_BD50MAX, 0x05 },
601 { OV7670_REG_BD60MAX, 0x07 },
602 { OV7670_REG_AEW, 0x95 },
603 { OV7670_REG_AEB, 0x33 },
604 { OV7670_REG_VPT, 0xe3 },
605 { OV7670_REG_HAECC1, 0x78 },
606 { OV7670_REG_HAECC2, 0x68 },
607 { 0xa1, 0x03 }, /* magic */
608 { OV7670_REG_HAECC3, 0xd8 },
609 { OV7670_REG_HAECC4, 0xd8 },
610 { OV7670_REG_HAECC5, 0xf0 },
611 { OV7670_REG_HAECC6, 0x90 },
612 { OV7670_REG_HAECC7, 0x94 },
613 { OV7670_REG_COM8, OV7670_COM8_FASTAEC
614 | OV7670_COM8_AECSTEP
615 | OV7670_COM8_BFILT
616 | OV7670_COM8_AGC
617 | OV7670_COM8_AEC },
618
619/* Almost all of these are magic "reserved" values. */
620 { OV7670_REG_COM5, 0x61 },
621 { OV7670_REG_COM6, 0x4b },
622 { 0x16, 0x02 },
623 { OV7670_REG_MVFP, 0x07 },
624 { 0x21, 0x02 },
625 { 0x22, 0x91 },
626 { 0x29, 0x07 },
627 { 0x33, 0x0b },
628 { 0x35, 0x0b },
629 { 0x37, 0x1d },
630 { 0x38, 0x71 },
631 { 0x39, 0x2a },
632 { OV7670_REG_COM12, 0x78 },
633 { 0x4d, 0x40 },
634 { 0x4e, 0x20 },
635 { OV7670_REG_GFIX, 0 },
636 { 0x6b, 0x4a },
637 { 0x74, 0x10 },
638 { 0x8d, 0x4f },
639 { 0x8e, 0 },
640 { 0x8f, 0 },
641 { 0x90, 0 },
642 { 0x91, 0 },
643 { 0x96, 0 },
644 { 0x9a, 0 },
645 { 0xb0, 0x84 },
646 { 0xb1, 0x0c },
647 { 0xb2, 0x0e },
648 { 0xb3, 0x82 },
649 { 0xb8, 0x0a },
650
651/* More reserved magic, some of which tweaks white balance */
652 { 0x43, 0x0a },
653 { 0x44, 0xf0 },
654 { 0x45, 0x34 },
655 { 0x46, 0x58 },
656 { 0x47, 0x28 },
657 { 0x48, 0x3a },
658 { 0x59, 0x88 },
659 { 0x5a, 0x88 },
660 { 0x5b, 0x44 },
661 { 0x5c, 0x67 },
662 { 0x5d, 0x49 },
663 { 0x5e, 0x0e },
664 { 0x6c, 0x0a },
665 { 0x6d, 0x55 },
666 { 0x6e, 0x11 },
667 { 0x6f, 0x9f },
668 /* "9e for advance AWB" */
669 { 0x6a, 0x40 },
670 { OV7670_REG_BLUE, 0x40 },
671 { OV7670_REG_RED, 0x60 },
672 { OV7670_REG_COM8, OV7670_COM8_FASTAEC
673 | OV7670_COM8_AECSTEP
674 | OV7670_COM8_BFILT
675 | OV7670_COM8_AGC
676 | OV7670_COM8_AEC
677 | OV7670_COM8_AWB },
678
679/* Matrix coefficients */
680 { 0x4f, 0x80 },
681 { 0x50, 0x80 },
682 { 0x51, 0 },
683 { 0x52, 0x22 },
684 { 0x53, 0x5e },
685 { 0x54, 0x80 },
686 { 0x58, 0x9e },
687
688 { OV7670_REG_COM16, OV7670_COM16_AWBGAIN },
689 { OV7670_REG_EDGE, 0 },
690 { 0x75, 0x05 },
691 { 0x76, 0xe1 },
692 { 0x4c, 0 },
693 { 0x77, 0x01 },
694 { OV7670_REG_COM13, OV7670_COM13_GAMMA
695 | OV7670_COM13_UVSAT
696 | 2}, /* was 3 */
697 { 0x4b, 0x09 },
698 { 0xc9, 0x60 },
699 { OV7670_REG_COM16, 0x38 },
700 { 0x56, 0x40 },
701
702 { 0x34, 0x11 },
703 { OV7670_REG_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO },
704 { 0xa4, 0x88 },
705 { 0x96, 0 },
706 { 0x97, 0x30 },
707 { 0x98, 0x20 },
708 { 0x99, 0x30 },
709 { 0x9a, 0x84 },
710 { 0x9b, 0x29 },
711 { 0x9c, 0x03 },
712 { 0x9d, 0x4c },
713 { 0x9e, 0x3f },
714 { 0x78, 0x04 },
715
716/* Extra-weird stuff. Some sort of multiplexor register */
717 { 0x79, 0x01 },
718 { 0xc8, 0xf0 },
719 { 0x79, 0x0f },
720 { 0xc8, 0x00 },
721 { 0x79, 0x10 },
722 { 0xc8, 0x7e },
723 { 0x79, 0x0a },
724 { 0xc8, 0x80 },
725 { 0x79, 0x0b },
726 { 0xc8, 0x01 },
727 { 0x79, 0x0c },
728 { 0xc8, 0x0f },
729 { 0x79, 0x0d },
730 { 0xc8, 0x20 },
731 { 0x79, 0x09 },
732 { 0xc8, 0x80 },
733 { 0x79, 0x02 },
734 { 0xc8, 0xc0 },
735 { 0x79, 0x03 },
736 { 0xc8, 0x40 },
737 { 0x79, 0x05 },
738 { 0xc8, 0x30 },
739 { 0x79, 0x26 },
740};
741
742static const struct ov_i2c_regvals norm_8610[] = {
743 { 0x12, 0x80 },
744 { 0x00, 0x00 },
745 { 0x01, 0x80 },
746 { 0x02, 0x80 },
747 { 0x03, 0xc0 },
748 { 0x04, 0x30 },
749 { 0x05, 0x30 }, /* was 0x10, new from windrv 090403 */
750 { 0x06, 0x70 }, /* was 0x80, new from windrv 090403 */
751 { 0x0a, 0x86 },
752 { 0x0b, 0xb0 },
753 { 0x0c, 0x20 },
754 { 0x0d, 0x20 },
755 { 0x11, 0x01 },
756 { 0x12, 0x25 },
757 { 0x13, 0x01 },
758 { 0x14, 0x04 },
759 { 0x15, 0x01 }, /* Lin and Win think different about UV order */
760 { 0x16, 0x03 },
761 { 0x17, 0x38 }, /* was 0x2f, new from windrv 090403 */
762 { 0x18, 0xea }, /* was 0xcf, new from windrv 090403 */
763 { 0x19, 0x02 }, /* was 0x06, new from windrv 090403 */
764 { 0x1a, 0xf5 },
765 { 0x1b, 0x00 },
766 { 0x20, 0xd0 }, /* was 0x90, new from windrv 090403 */
767 { 0x23, 0xc0 }, /* was 0x00, new from windrv 090403 */
768 { 0x24, 0x30 }, /* was 0x1d, new from windrv 090403 */
769 { 0x25, 0x50 }, /* was 0x57, new from windrv 090403 */
770 { 0x26, 0xa2 },
771 { 0x27, 0xea },
772 { 0x28, 0x00 },
773 { 0x29, 0x00 },
774 { 0x2a, 0x80 },
775 { 0x2b, 0xc8 }, /* was 0xcc, new from windrv 090403 */
776 { 0x2c, 0xac },
777 { 0x2d, 0x45 }, /* was 0xd5, new from windrv 090403 */
778 { 0x2e, 0x80 },
779 { 0x2f, 0x14 }, /* was 0x01, new from windrv 090403 */
780 { 0x4c, 0x00 },
781 { 0x4d, 0x30 }, /* was 0x10, new from windrv 090403 */
782 { 0x60, 0x02 }, /* was 0x01, new from windrv 090403 */
783 { 0x61, 0x00 }, /* was 0x09, new from windrv 090403 */
784 { 0x62, 0x5f }, /* was 0xd7, new from windrv 090403 */
785 { 0x63, 0xff },
786 { 0x64, 0x53 }, /* new windrv 090403 says 0x57,
787 * maybe thats wrong */
788 { 0x65, 0x00 },
789 { 0x66, 0x55 },
790 { 0x67, 0xb0 },
791 { 0x68, 0xc0 }, /* was 0xaf, new from windrv 090403 */
792 { 0x69, 0x02 },
793 { 0x6a, 0x22 },
794 { 0x6b, 0x00 },
795 { 0x6c, 0x99 }, /* was 0x80, old windrv says 0x00, but
796 * deleting bit7 colors the first images red */
797 { 0x6d, 0x11 }, /* was 0x00, new from windrv 090403 */
798 { 0x6e, 0x11 }, /* was 0x00, new from windrv 090403 */
799 { 0x6f, 0x01 },
800 { 0x70, 0x8b },
801 { 0x71, 0x00 },
802 { 0x72, 0x14 },
803 { 0x73, 0x54 },
804 { 0x74, 0x00 },/* 0x60? - was 0x00, new from windrv 090403 */
805 { 0x75, 0x0e },
806 { 0x76, 0x02 }, /* was 0x02, new from windrv 090403 */
807 { 0x77, 0xff },
808 { 0x78, 0x80 },
809 { 0x79, 0x80 },
810 { 0x7a, 0x80 },
811 { 0x7b, 0x10 }, /* was 0x13, new from windrv 090403 */
812 { 0x7c, 0x00 },
813 { 0x7d, 0x08 }, /* was 0x09, new from windrv 090403 */
814 { 0x7e, 0x08 }, /* was 0xc0, new from windrv 090403 */
815 { 0x7f, 0xfb },
816 { 0x80, 0x28 },
817 { 0x81, 0x00 },
818 { 0x82, 0x23 },
819 { 0x83, 0x0b },
820 { 0x84, 0x00 },
821 { 0x85, 0x62 }, /* was 0x61, new from windrv 090403 */
822 { 0x86, 0xc9 },
823 { 0x87, 0x00 },
824 { 0x88, 0x00 },
825 { 0x89, 0x01 },
826 { 0x12, 0x20 },
827 { 0x12, 0x25 }, /* was 0x24, new from windrv 090403 */
828};
829
296static unsigned char ov7670_abs_to_sm(unsigned char v) 830static unsigned char ov7670_abs_to_sm(unsigned char v)
297{ 831{
298 if (v > 127) 832 if (v > 127)
@@ -537,18 +1071,10 @@ static int ov51x_set_slave_ids(struct sd *sd,
537 rc = reg_w(sd, R51x_I2C_W_SID, slave); 1071 rc = reg_w(sd, R51x_I2C_W_SID, slave);
538 if (rc < 0) 1072 if (rc < 0)
539 return rc; 1073 return rc;
1074 sd->primary_i2c_slave = slave;
540 return reg_w(sd, R51x_I2C_R_SID, slave + 1); 1075 return reg_w(sd, R51x_I2C_R_SID, slave + 1);
541} 1076}
542 1077
543struct ov_regvals {
544 __u8 reg;
545 __u8 val;
546};
547struct ov_i2c_regvals {
548 __u8 reg;
549 __u8 val;
550};
551
552static int write_regvals(struct sd *sd, 1078static int write_regvals(struct sd *sd,
553 const struct ov_regvals *regvals, 1079 const struct ov_regvals *regvals,
554 int n) 1080 int n)
@@ -591,101 +1117,9 @@ static int write_i2c_regvals(struct sd *sd,
591static int ov8xx0_configure(struct sd *sd) 1117static int ov8xx0_configure(struct sd *sd)
592{ 1118{
593 int rc; 1119 int rc;
594 static const struct ov_i2c_regvals norm_8610[] = {
595 { 0x12, 0x80 },
596 { 0x00, 0x00 },
597 { 0x01, 0x80 },
598 { 0x02, 0x80 },
599 { 0x03, 0xc0 },
600 { 0x04, 0x30 },
601 { 0x05, 0x30 }, /* was 0x10, new from windrv 090403 */
602 { 0x06, 0x70 }, /* was 0x80, new from windrv 090403 */
603 { 0x0a, 0x86 },
604 { 0x0b, 0xb0 },
605 { 0x0c, 0x20 },
606 { 0x0d, 0x20 },
607 { 0x11, 0x01 },
608 { 0x12, 0x25 },
609 { 0x13, 0x01 },
610 { 0x14, 0x04 },
611 { 0x15, 0x01 }, /* Lin and Win think different about UV order */
612 { 0x16, 0x03 },
613 { 0x17, 0x38 }, /* was 0x2f, new from windrv 090403 */
614 { 0x18, 0xea }, /* was 0xcf, new from windrv 090403 */
615 { 0x19, 0x02 }, /* was 0x06, new from windrv 090403 */
616 { 0x1a, 0xf5 },
617 { 0x1b, 0x00 },
618 { 0x20, 0xd0 }, /* was 0x90, new from windrv 090403 */
619 { 0x23, 0xc0 }, /* was 0x00, new from windrv 090403 */
620 { 0x24, 0x30 }, /* was 0x1d, new from windrv 090403 */
621 { 0x25, 0x50 }, /* was 0x57, new from windrv 090403 */
622 { 0x26, 0xa2 },
623 { 0x27, 0xea },
624 { 0x28, 0x00 },
625 { 0x29, 0x00 },
626 { 0x2a, 0x80 },
627 { 0x2b, 0xc8 }, /* was 0xcc, new from windrv 090403 */
628 { 0x2c, 0xac },
629 { 0x2d, 0x45 }, /* was 0xd5, new from windrv 090403 */
630 { 0x2e, 0x80 },
631 { 0x2f, 0x14 }, /* was 0x01, new from windrv 090403 */
632 { 0x4c, 0x00 },
633 { 0x4d, 0x30 }, /* was 0x10, new from windrv 090403 */
634 { 0x60, 0x02 }, /* was 0x01, new from windrv 090403 */
635 { 0x61, 0x00 }, /* was 0x09, new from windrv 090403 */
636 { 0x62, 0x5f }, /* was 0xd7, new from windrv 090403 */
637 { 0x63, 0xff },
638 { 0x64, 0x53 }, /* new windrv 090403 says 0x57,
639 * maybe thats wrong */
640 { 0x65, 0x00 },
641 { 0x66, 0x55 },
642 { 0x67, 0xb0 },
643 { 0x68, 0xc0 }, /* was 0xaf, new from windrv 090403 */
644 { 0x69, 0x02 },
645 { 0x6a, 0x22 },
646 { 0x6b, 0x00 },
647 { 0x6c, 0x99 }, /* was 0x80, old windrv says 0x00, but
648 deleting bit7 colors the first images red */
649 { 0x6d, 0x11 }, /* was 0x00, new from windrv 090403 */
650 { 0x6e, 0x11 }, /* was 0x00, new from windrv 090403 */
651 { 0x6f, 0x01 },
652 { 0x70, 0x8b },
653 { 0x71, 0x00 },
654 { 0x72, 0x14 },
655 { 0x73, 0x54 },
656 { 0x74, 0x00 },/* 0x60? - was 0x00, new from windrv 090403 */
657 { 0x75, 0x0e },
658 { 0x76, 0x02 }, /* was 0x02, new from windrv 090403 */
659 { 0x77, 0xff },
660 { 0x78, 0x80 },
661 { 0x79, 0x80 },
662 { 0x7a, 0x80 },
663 { 0x7b, 0x10 }, /* was 0x13, new from windrv 090403 */
664 { 0x7c, 0x00 },
665 { 0x7d, 0x08 }, /* was 0x09, new from windrv 090403 */
666 { 0x7e, 0x08 }, /* was 0xc0, new from windrv 090403 */
667 { 0x7f, 0xfb },
668 { 0x80, 0x28 },
669 { 0x81, 0x00 },
670 { 0x82, 0x23 },
671 { 0x83, 0x0b },
672 { 0x84, 0x00 },
673 { 0x85, 0x62 }, /* was 0x61, new from windrv 090403 */
674 { 0x86, 0xc9 },
675 { 0x87, 0x00 },
676 { 0x88, 0x00 },
677 { 0x89, 0x01 },
678 { 0x12, 0x20 },
679 { 0x12, 0x25 }, /* was 0x24, new from windrv 090403 */
680 };
681 1120
682 PDEBUG(D_PROBE, "starting ov8xx0 configuration"); 1121 PDEBUG(D_PROBE, "starting ov8xx0 configuration");
683 1122
684 if (init_ov_sensor(sd) < 0)
685 PDEBUG(D_ERR|D_PROBE, "Failed to read sensor ID");
686 else
687 PDEBUG(D_PROBE, "OV86x0 initialized");
688
689 /* Detect sensor (sub)type */ 1123 /* Detect sensor (sub)type */
690 rc = i2c_r(sd, OV7610_REG_COM_I); 1124 rc = i2c_r(sd, OV7610_REG_COM_I);
691 if (rc < 0) { 1125 if (rc < 0) {
@@ -698,9 +1132,6 @@ static int ov8xx0_configure(struct sd *sd)
698 PDEBUG(D_ERR, "Unknown image sensor version: %d", rc & 3); 1132 PDEBUG(D_ERR, "Unknown image sensor version: %d", rc & 3);
699 return -1; 1133 return -1;
700 } 1134 }
701 PDEBUG(D_PROBE, "Writing 8610 registers");
702 if (write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610)))
703 return -1;
704 1135
705 /* Set sensor-specific vars */ 1136 /* Set sensor-specific vars */
706/* sd->sif = 0; already done */ 1137/* sd->sif = 0; already done */
@@ -714,252 +1145,6 @@ static int ov7xx0_configure(struct sd *sd)
714{ 1145{
715 int rc, high, low; 1146 int rc, high, low;
716 1147
717 /* Lawrence Glaister <lg@jfm.bc.ca> reports:
718 *
719 * Register 0x0f in the 7610 has the following effects:
720 *
721 * 0x85 (AEC method 1): Best overall, good contrast range
722 * 0x45 (AEC method 2): Very overexposed
723 * 0xa5 (spec sheet default): Ok, but the black level is
724 * shifted resulting in loss of contrast
725 * 0x05 (old driver setting): very overexposed, too much
726 * contrast
727 */
728 static const struct ov_i2c_regvals norm_7610[] = {
729 { 0x10, 0xff },
730 { 0x16, 0x06 },
731 { 0x28, 0x24 },
732 { 0x2b, 0xac },
733 { 0x12, 0x00 },
734 { 0x38, 0x81 },
735 { 0x28, 0x24 }, /* 0c */
736 { 0x0f, 0x85 }, /* lg's setting */
737 { 0x15, 0x01 },
738 { 0x20, 0x1c },
739 { 0x23, 0x2a },
740 { 0x24, 0x10 },
741 { 0x25, 0x8a },
742 { 0x26, 0xa2 },
743 { 0x27, 0xc2 },
744 { 0x2a, 0x04 },
745 { 0x2c, 0xfe },
746 { 0x2d, 0x93 },
747 { 0x30, 0x71 },
748 { 0x31, 0x60 },
749 { 0x32, 0x26 },
750 { 0x33, 0x20 },
751 { 0x34, 0x48 },
752 { 0x12, 0x24 },
753 { 0x11, 0x01 },
754 { 0x0c, 0x24 },
755 { 0x0d, 0x24 },
756 };
757
758 static const struct ov_i2c_regvals norm_7620[] = {
759 { 0x00, 0x00 }, /* gain */
760 { 0x01, 0x80 }, /* blue gain */
761 { 0x02, 0x80 }, /* red gain */
762 { 0x03, 0xc0 }, /* OV7670_REG_VREF */
763 { 0x06, 0x60 },
764 { 0x07, 0x00 },
765 { 0x0c, 0x24 },
766 { 0x0c, 0x24 },
767 { 0x0d, 0x24 },
768 { 0x11, 0x01 },
769 { 0x12, 0x24 },
770 { 0x13, 0x01 },
771 { 0x14, 0x84 },
772 { 0x15, 0x01 },
773 { 0x16, 0x03 },
774 { 0x17, 0x2f },
775 { 0x18, 0xcf },
776 { 0x19, 0x06 },
777 { 0x1a, 0xf5 },
778 { 0x1b, 0x00 },
779 { 0x20, 0x18 },
780 { 0x21, 0x80 },
781 { 0x22, 0x80 },
782 { 0x23, 0x00 },
783 { 0x26, 0xa2 },
784 { 0x27, 0xea },
785 { 0x28, 0x20 },
786 { 0x29, 0x00 },
787 { 0x2a, 0x10 },
788 { 0x2b, 0x00 },
789 { 0x2c, 0x88 },
790 { 0x2d, 0x91 },
791 { 0x2e, 0x80 },
792 { 0x2f, 0x44 },
793 { 0x60, 0x27 },
794 { 0x61, 0x02 },
795 { 0x62, 0x5f },
796 { 0x63, 0xd5 },
797 { 0x64, 0x57 },
798 { 0x65, 0x83 },
799 { 0x66, 0x55 },
800 { 0x67, 0x92 },
801 { 0x68, 0xcf },
802 { 0x69, 0x76 },
803 { 0x6a, 0x22 },
804 { 0x6b, 0x00 },
805 { 0x6c, 0x02 },
806 { 0x6d, 0x44 },
807 { 0x6e, 0x80 },
808 { 0x6f, 0x1d },
809 { 0x70, 0x8b },
810 { 0x71, 0x00 },
811 { 0x72, 0x14 },
812 { 0x73, 0x54 },
813 { 0x74, 0x00 },
814 { 0x75, 0x8e },
815 { 0x76, 0x00 },
816 { 0x77, 0xff },
817 { 0x78, 0x80 },
818 { 0x79, 0x80 },
819 { 0x7a, 0x80 },
820 { 0x7b, 0xe2 },
821 { 0x7c, 0x00 },
822 };
823
824 /* 7640 and 7648. The defaults should be OK for most registers. */
825 static const struct ov_i2c_regvals norm_7640[] = {
826 { 0x12, 0x80 },
827 { 0x12, 0x14 },
828 };
829
830 /* 7670. Defaults taken from OmniVision provided data,
831 * as provided by Jonathan Corbet of OLPC */
832 static const struct ov_i2c_regvals norm_7670[] = {
833 { OV7670_REG_COM7, OV7670_COM7_RESET },
834 { OV7670_REG_TSLB, 0x04 }, /* OV */
835 { OV7670_REG_COM7, OV7670_COM7_FMT_VGA }, /* VGA */
836 { OV7670_REG_CLKRC, 0x01 },
837 /*
838 * Set the hardware window. These values from OV don't entirely
839 * make sense - hstop is less than hstart. But they work...
840 */
841 { OV7670_REG_HSTART, 0x13 }, { OV7670_REG_HSTOP, 0x01 },
842 { OV7670_REG_HREF, 0xb6 }, { OV7670_REG_VSTART, 0x02 },
843 { OV7670_REG_VSTOP, 0x7a }, { OV7670_REG_VREF, 0x0a },
844
845 { OV7670_REG_COM3, 0 }, { OV7670_REG_COM14, 0 },
846 /* Mystery scaling numbers */
847 { 0x70, 0x3a }, { 0x71, 0x35 },
848 { 0x72, 0x11 }, { 0x73, 0xf0 },
849 { 0xa2, 0x02 },
850/* { OV7670_REG_COM10, 0x0 }, */
851
852 /* Gamma curve values */
853 { 0x7a, 0x20 },
854 { 0x7b, 0x10 },
855 { 0x7c, 0x1e },
856 { 0x7d, 0x35 },
857 { 0x7e, 0x5a }, { 0x7f, 0x69 },
858 { 0x80, 0x76 }, { 0x81, 0x80 },
859 { 0x82, 0x88 }, { 0x83, 0x8f },
860 { 0x84, 0x96 }, { 0x85, 0xa3 },
861 { 0x86, 0xaf }, { 0x87, 0xc4 },
862 { 0x88, 0xd7 }, { 0x89, 0xe8 },
863
864 /* AGC and AEC parameters. Note we start by disabling those features,
865 then turn them only after tweaking the values. */
866 { OV7670_REG_COM8, OV7670_COM8_FASTAEC
867 | OV7670_COM8_AECSTEP
868 | OV7670_COM8_BFILT },
869 { OV7670_REG_GAIN, 0 }, { OV7670_REG_AECH, 0 },
870 { OV7670_REG_COM4, 0x40 }, /* magic reserved bit */
871 { OV7670_REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
872 { OV7670_REG_BD50MAX, 0x05 }, { OV7670_REG_BD60MAX, 0x07 },
873 { OV7670_REG_AEW, 0x95 }, { OV7670_REG_AEB, 0x33 },
874 { OV7670_REG_VPT, 0xe3 }, { OV7670_REG_HAECC1, 0x78 },
875 { OV7670_REG_HAECC2, 0x68 },
876 { 0xa1, 0x03 }, /* magic */
877 { OV7670_REG_HAECC3, 0xd8 }, { OV7670_REG_HAECC4, 0xd8 },
878 { OV7670_REG_HAECC5, 0xf0 }, { OV7670_REG_HAECC6, 0x90 },
879 { OV7670_REG_HAECC7, 0x94 },
880 { OV7670_REG_COM8, OV7670_COM8_FASTAEC
881 | OV7670_COM8_AECSTEP
882 | OV7670_COM8_BFILT
883 | OV7670_COM8_AGC
884 | OV7670_COM8_AEC },
885
886 /* Almost all of these are magic "reserved" values. */
887 { OV7670_REG_COM5, 0x61 }, { OV7670_REG_COM6, 0x4b },
888 { 0x16, 0x02 },
889 { OV7670_REG_MVFP, 0x07 },
890 { 0x21, 0x02 }, { 0x22, 0x91 },
891 { 0x29, 0x07 }, { 0x33, 0x0b },
892 { 0x35, 0x0b }, { 0x37, 0x1d },
893 { 0x38, 0x71 }, { 0x39, 0x2a },
894 { OV7670_REG_COM12, 0x78 }, { 0x4d, 0x40 },
895 { 0x4e, 0x20 }, { OV7670_REG_GFIX, 0 },
896 { 0x6b, 0x4a }, { 0x74, 0x10 },
897 { 0x8d, 0x4f }, { 0x8e, 0 },
898 { 0x8f, 0 }, { 0x90, 0 },
899 { 0x91, 0 }, { 0x96, 0 },
900 { 0x9a, 0 }, { 0xb0, 0x84 },
901 { 0xb1, 0x0c }, { 0xb2, 0x0e },
902 { 0xb3, 0x82 }, { 0xb8, 0x0a },
903
904 /* More reserved magic, some of which tweaks white balance */
905 { 0x43, 0x0a }, { 0x44, 0xf0 },
906 { 0x45, 0x34 }, { 0x46, 0x58 },
907 { 0x47, 0x28 }, { 0x48, 0x3a },
908 { 0x59, 0x88 }, { 0x5a, 0x88 },
909 { 0x5b, 0x44 }, { 0x5c, 0x67 },
910 { 0x5d, 0x49 }, { 0x5e, 0x0e },
911 { 0x6c, 0x0a }, { 0x6d, 0x55 },
912 { 0x6e, 0x11 }, { 0x6f, 0x9f },
913 /* "9e for advance AWB" */
914 { 0x6a, 0x40 }, { OV7670_REG_BLUE, 0x40 },
915 { OV7670_REG_RED, 0x60 },
916 { OV7670_REG_COM8, OV7670_COM8_FASTAEC
917 | OV7670_COM8_AECSTEP
918 | OV7670_COM8_BFILT
919 | OV7670_COM8_AGC
920 | OV7670_COM8_AEC
921 | OV7670_COM8_AWB },
922
923 /* Matrix coefficients */
924 { 0x4f, 0x80 }, { 0x50, 0x80 },
925 { 0x51, 0 }, { 0x52, 0x22 },
926 { 0x53, 0x5e }, { 0x54, 0x80 },
927 { 0x58, 0x9e },
928
929 { OV7670_REG_COM16, OV7670_COM16_AWBGAIN },
930 { OV7670_REG_EDGE, 0 },
931 { 0x75, 0x05 }, { 0x76, 0xe1 },
932 { 0x4c, 0 }, { 0x77, 0x01 },
933 { OV7670_REG_COM13, OV7670_COM13_GAMMA
934 | OV7670_COM13_UVSAT
935 | 2}, /* was 3 */
936 { 0x4b, 0x09 },
937 { 0xc9, 0x60 }, { OV7670_REG_COM16, 0x38 },
938 { 0x56, 0x40 },
939
940 { 0x34, 0x11 },
941 { OV7670_REG_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO },
942 { 0xa4, 0x88 }, { 0x96, 0 },
943 { 0x97, 0x30 }, { 0x98, 0x20 },
944 { 0x99, 0x30 }, { 0x9a, 0x84 },
945 { 0x9b, 0x29 }, { 0x9c, 0x03 },
946 { 0x9d, 0x4c }, { 0x9e, 0x3f },
947 { 0x78, 0x04 },
948
949 /* Extra-weird stuff. Some sort of multiplexor register */
950 { 0x79, 0x01 }, { 0xc8, 0xf0 },
951 { 0x79, 0x0f }, { 0xc8, 0x00 },
952 { 0x79, 0x10 }, { 0xc8, 0x7e },
953 { 0x79, 0x0a }, { 0xc8, 0x80 },
954 { 0x79, 0x0b }, { 0xc8, 0x01 },
955 { 0x79, 0x0c }, { 0xc8, 0x0f },
956 { 0x79, 0x0d }, { 0xc8, 0x20 },
957 { 0x79, 0x09 }, { 0xc8, 0x80 },
958 { 0x79, 0x02 }, { 0xc8, 0xc0 },
959 { 0x79, 0x03 }, { 0xc8, 0x40 },
960 { 0x79, 0x05 }, { 0xc8, 0x30 },
961 { 0x79, 0x26 },
962 };
963 1148
964 PDEBUG(D_PROBE, "starting OV7xx0 configuration"); 1149 PDEBUG(D_PROBE, "starting OV7xx0 configuration");
965 1150
@@ -1011,8 +1196,9 @@ static int ov7xx0_configure(struct sd *sd)
1011 switch (low) { 1196 switch (low) {
1012 case 0x30: 1197 case 0x30:
1013 PDEBUG(D_PROBE, "Sensor is an OV7630/OV7635"); 1198 PDEBUG(D_PROBE, "Sensor is an OV7630/OV7635");
1014 sd->sensor = SEN_OV7630; 1199 PDEBUG(D_ERR,
1015 break; 1200 "7630 is not supported by this driver");
1201 return -1;
1016 case 0x40: 1202 case 0x40:
1017 PDEBUG(D_PROBE, "Sensor is an OV7645"); 1203 PDEBUG(D_PROBE, "Sensor is an OV7645");
1018 sd->sensor = SEN_OV7640; /* FIXME */ 1204 sd->sensor = SEN_OV7640; /* FIXME */
@@ -1038,32 +1224,6 @@ static int ov7xx0_configure(struct sd *sd)
1038 return -1; 1224 return -1;
1039 } 1225 }
1040 1226
1041 switch (sd->sensor) {
1042 case SEN_OV7620:
1043 PDEBUG(D_PROBE, "Writing 7620 registers");
1044 if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620)))
1045 return -1;
1046 break;
1047 case SEN_OV7630:
1048 PDEBUG(D_ERR, "7630 is not supported by this driver version");
1049 return -1;
1050 case SEN_OV7640:
1051 PDEBUG(D_PROBE, "Writing 7640 registers");
1052 if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640)))
1053 return -1;
1054 break;
1055 case SEN_OV7670:
1056 PDEBUG(D_PROBE, "Writing 7670 registers");
1057 if (write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670)))
1058 return -1;
1059 break;
1060 default:
1061 PDEBUG(D_PROBE, "Writing 7610 registers");
1062 if (write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610)))
1063 return -1;
1064 break;
1065 }
1066
1067 /* Set sensor-specific vars */ 1227 /* Set sensor-specific vars */
1068/* sd->sif = 0; already done */ 1228/* sd->sif = 0; already done */
1069 return 0; 1229 return 0;
@@ -1073,141 +1233,7 @@ static int ov7xx0_configure(struct sd *sd)
1073static int ov6xx0_configure(struct sd *sd) 1233static int ov6xx0_configure(struct sd *sd)
1074{ 1234{
1075 int rc; 1235 int rc;
1076 static const struct ov_i2c_regvals norm_6x20[] = { 1236 PDEBUG(D_PROBE, "starting OV6xx0 configuration");
1077 { 0x12, 0x80 }, /* reset */
1078 { 0x11, 0x01 },
1079 { 0x03, 0x60 },
1080 { 0x05, 0x7f }, /* For when autoadjust is off */
1081 { 0x07, 0xa8 },
1082 /* The ratio of 0x0c and 0x0d controls the white point */
1083 { 0x0c, 0x24 },
1084 { 0x0d, 0x24 },
1085 { 0x0f, 0x15 }, /* COMS */
1086 { 0x10, 0x75 }, /* AEC Exposure time */
1087 { 0x12, 0x24 }, /* Enable AGC */
1088 { 0x14, 0x04 },
1089 /* 0x16: 0x06 helps frame stability with moving objects */
1090 { 0x16, 0x06 },
1091/* { 0x20, 0x30 }, * Aperture correction enable */
1092 { 0x26, 0xb2 }, /* BLC enable */
1093 /* 0x28: 0x05 Selects RGB format if RGB on */
1094 { 0x28, 0x05 },
1095 { 0x2a, 0x04 }, /* Disable framerate adjust */
1096/* { 0x2b, 0xac }, * Framerate; Set 2a[7] first */
1097 { 0x2d, 0x99 },
1098 { 0x33, 0xa0 }, /* Color Processing Parameter */
1099 { 0x34, 0xd2 }, /* Max A/D range */
1100 { 0x38, 0x8b },
1101 { 0x39, 0x40 },
1102
1103 { 0x3c, 0x39 }, /* Enable AEC mode changing */
1104 { 0x3c, 0x3c }, /* Change AEC mode */
1105 { 0x3c, 0x24 }, /* Disable AEC mode changing */
1106
1107 { 0x3d, 0x80 },
1108 /* These next two registers (0x4a, 0x4b) are undocumented.
1109 * They control the color balance */
1110 { 0x4a, 0x80 },
1111 { 0x4b, 0x80 },
1112 { 0x4d, 0xd2 }, /* This reduces noise a bit */
1113 { 0x4e, 0xc1 },
1114 { 0x4f, 0x04 },
1115/* Do 50-53 have any effect? */
1116/* Toggle 0x12[2] off and on here? */
1117 };
1118
1119 static const struct ov_i2c_regvals norm_6x30[] = {
1120 { 0x12, 0x80 }, /* Reset */
1121 { 0x00, 0x1f }, /* Gain */
1122 { 0x01, 0x99 }, /* Blue gain */
1123 { 0x02, 0x7c }, /* Red gain */
1124 { 0x03, 0xc0 }, /* Saturation */
1125 { 0x05, 0x0a }, /* Contrast */
1126 { 0x06, 0x95 }, /* Brightness */
1127 { 0x07, 0x2d }, /* Sharpness */
1128 { 0x0c, 0x20 },
1129 { 0x0d, 0x20 },
1130 { 0x0e, 0x20 },
1131 { 0x0f, 0x05 },
1132 { 0x10, 0x9a },
1133 { 0x11, 0x00 }, /* Pixel clock = fastest */
1134 { 0x12, 0x24 }, /* Enable AGC and AWB */
1135 { 0x13, 0x21 },
1136 { 0x14, 0x80 },
1137 { 0x15, 0x01 },
1138 { 0x16, 0x03 },
1139 { 0x17, 0x38 },
1140 { 0x18, 0xea },
1141 { 0x19, 0x04 },
1142 { 0x1a, 0x93 },
1143 { 0x1b, 0x00 },
1144 { 0x1e, 0xc4 },
1145 { 0x1f, 0x04 },
1146 { 0x20, 0x20 },
1147 { 0x21, 0x10 },
1148 { 0x22, 0x88 },
1149 { 0x23, 0xc0 }, /* Crystal circuit power level */
1150 { 0x25, 0x9a }, /* Increase AEC black ratio */
1151 { 0x26, 0xb2 }, /* BLC enable */
1152 { 0x27, 0xa2 },
1153 { 0x28, 0x00 },
1154 { 0x29, 0x00 },
1155 { 0x2a, 0x84 }, /* 60 Hz power */
1156 { 0x2b, 0xa8 }, /* 60 Hz power */
1157 { 0x2c, 0xa0 },
1158 { 0x2d, 0x95 }, /* Enable auto-brightness */
1159 { 0x2e, 0x88 },
1160 { 0x33, 0x26 },
1161 { 0x34, 0x03 },
1162 { 0x36, 0x8f },
1163 { 0x37, 0x80 },
1164 { 0x38, 0x83 },
1165 { 0x39, 0x80 },
1166 { 0x3a, 0x0f },
1167 { 0x3b, 0x3c },
1168 { 0x3c, 0x1a },
1169 { 0x3d, 0x80 },
1170 { 0x3e, 0x80 },
1171 { 0x3f, 0x0e },
1172 { 0x40, 0x00 }, /* White bal */
1173 { 0x41, 0x00 }, /* White bal */
1174 { 0x42, 0x80 },
1175 { 0x43, 0x3f }, /* White bal */
1176 { 0x44, 0x80 },
1177 { 0x45, 0x20 },
1178 { 0x46, 0x20 },
1179 { 0x47, 0x80 },
1180 { 0x48, 0x7f },
1181 { 0x49, 0x00 },
1182 { 0x4a, 0x00 },
1183 { 0x4b, 0x80 },
1184 { 0x4c, 0xd0 },
1185 { 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */
1186 { 0x4e, 0x40 },
1187 { 0x4f, 0x07 }, /* UV avg., col. killer: max */
1188 { 0x50, 0xff },
1189 { 0x54, 0x23 }, /* Max AGC gain: 18dB */
1190 { 0x55, 0xff },
1191 { 0x56, 0x12 },
1192 { 0x57, 0x81 },
1193 { 0x58, 0x75 },
1194 { 0x59, 0x01 }, /* AGC dark current comp.: +1 */
1195 { 0x5a, 0x2c },
1196 { 0x5b, 0x0f }, /* AWB chrominance levels */
1197 { 0x5c, 0x10 },
1198 { 0x3d, 0x80 },
1199 { 0x27, 0xa6 },
1200 { 0x12, 0x20 }, /* Toggle AWB */
1201 { 0x12, 0x24 },
1202 };
1203
1204 PDEBUG(D_PROBE, "starting sensor configuration");
1205
1206 if (init_ov_sensor(sd) < 0) {
1207 PDEBUG(D_ERR, "Failed to read sensor ID.");
1208 return -1;
1209 }
1210 PDEBUG(D_PROBE, "OV6xx0 sensor detected");
1211 1237
1212 /* Detect sensor (sub)type */ 1238 /* Detect sensor (sub)type */
1213 rc = i2c_r(sd, OV7610_REG_COM_I); 1239 rc = i2c_r(sd, OV7610_REG_COM_I);
@@ -1251,15 +1277,6 @@ static int ov6xx0_configure(struct sd *sd)
1251 /* Set sensor-specific vars */ 1277 /* Set sensor-specific vars */
1252 sd->sif = 1; 1278 sd->sif = 1;
1253 1279
1254 if (sd->sensor == SEN_OV6620) {
1255 PDEBUG(D_PROBE, "Writing 6x20 registers");
1256 if (write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20)))
1257 return -1;
1258 } else {
1259 PDEBUG(D_PROBE, "Writing 6x30 registers");
1260 if (write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30)))
1261 return -1;
1262 }
1263 return 0; 1280 return 0;
1264} 1281}
1265 1282
@@ -1298,22 +1315,31 @@ static int sd_config(struct gspca_dev *gspca_dev,
1298 ov51x_led_control(sd, 0); /* turn LED off */ 1315 ov51x_led_control(sd, 0); /* turn LED off */
1299 1316
1300 /* Test for 76xx */ 1317 /* Test for 76xx */
1301 sd->primary_i2c_slave = OV7xx0_SID;
1302 if (ov51x_set_slave_ids(sd, OV7xx0_SID) < 0) 1318 if (ov51x_set_slave_ids(sd, OV7xx0_SID) < 0)
1303 goto error; 1319 goto error;
1304 1320
1305 /* The OV519 must be more aggressive about sensor detection since 1321 /* The OV519 must be more aggressive about sensor detection since
1306 * I2C write will never fail if the sensor is not present. We have 1322 * I2C write will never fail if the sensor is not present. We have
1307 * to try to initialize the sensor to detect its presence */ 1323 * to try to initialize the sensor to detect its presence */
1308 if (init_ov_sensor(sd) < 0) { 1324 if (init_ov_sensor(sd) >= 0) {
1325 if (ov7xx0_configure(sd) < 0) {
1326 PDEBUG(D_ERR, "Failed to configure OV7xx0");
1327 goto error;
1328 }
1329 } else {
1330
1309 /* Test for 6xx0 */ 1331 /* Test for 6xx0 */
1310 sd->primary_i2c_slave = OV6xx0_SID;
1311 if (ov51x_set_slave_ids(sd, OV6xx0_SID) < 0) 1332 if (ov51x_set_slave_ids(sd, OV6xx0_SID) < 0)
1312 goto error; 1333 goto error;
1313 1334
1314 if (init_ov_sensor(sd) < 0) { 1335 if (init_ov_sensor(sd) >= 0) {
1336 if (ov6xx0_configure(sd) < 0) {
1337 PDEBUG(D_ERR, "Failed to configure OV6xx0");
1338 goto error;
1339 }
1340 } else {
1341
1315 /* Test for 8xx0 */ 1342 /* Test for 8xx0 */
1316 sd->primary_i2c_slave = OV8xx0_SID;
1317 if (ov51x_set_slave_ids(sd, OV8xx0_SID) < 0) 1343 if (ov51x_set_slave_ids(sd, OV8xx0_SID) < 0)
1318 goto error; 1344 goto error;
1319 1345
@@ -1321,24 +1347,13 @@ static int sd_config(struct gspca_dev *gspca_dev,
1321 PDEBUG(D_ERR, 1347 PDEBUG(D_ERR,
1322 "Can't determine sensor slave IDs"); 1348 "Can't determine sensor slave IDs");
1323 goto error; 1349 goto error;
1324 } else {
1325 if (ov8xx0_configure(sd) < 0) {
1326 PDEBUG(D_ERR,
1327 "Failed to configure OV8xx0 sensor");
1328 goto error;
1329 }
1330 } 1350 }
1331 } else { 1351 if (ov8xx0_configure(sd) < 0) {
1332 if (ov6xx0_configure(sd) < 0) { 1352 PDEBUG(D_ERR,
1333 PDEBUG(D_ERR, "Failed to configure OV6xx0"); 1353 "Failed to configure OV8xx0 sensor");
1334 goto error; 1354 goto error;
1335 } 1355 }
1336 } 1356 }
1337 } else {
1338 if (ov7xx0_configure(sd) < 0) {
1339 PDEBUG(D_ERR, "Failed to configure OV7xx0");
1340 goto error;
1341 }
1342 } 1357 }
1343 1358
1344 cam = &gspca_dev->cam; 1359 cam = &gspca_dev->cam;
@@ -1364,6 +1379,41 @@ error:
1364/* this function is called at open time */ 1379/* this function is called at open time */
1365static int sd_open(struct gspca_dev *gspca_dev) 1380static int sd_open(struct gspca_dev *gspca_dev)
1366{ 1381{
1382 struct sd *sd = (struct sd *) gspca_dev;
1383
1384 /* initialize the sensor */
1385 switch (sd->sensor) {
1386 case SEN_OV6620:
1387 if (write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20)))
1388 return -EIO;
1389 break;
1390 case SEN_OV6630:
1391 if (write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30)))
1392 return -EIO;
1393 break;
1394 default:
1395/* case SEN_OV7610: */
1396/* case SEN_OV76BE: */
1397 if (write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610)))
1398 return -EIO;
1399 break;
1400 case SEN_OV7620:
1401 if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620)))
1402 return -EIO;
1403 break;
1404 case SEN_OV7640:
1405 if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640)))
1406 return -EIO;
1407 break;
1408 case SEN_OV7670:
1409 if (write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670)))
1410 return -EIO;
1411 break;
1412 case SEN_OV8610:
1413 if (write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610)))
1414 return -EIO;
1415 break;
1416 }
1367 return 0; 1417 return 0;
1368} 1418}
1369 1419