aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca
diff options
context:
space:
mode:
authorHans de Goede <j.w.r.degoede@hhs.nl>2008-07-16 14:29:11 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-07-20 06:27:19 -0400
commita975a5279e39b5bc104cc8329d25a36a25136ad9 (patch)
treec7b40ddea02a4c972e773975df479fb53ec01204 /drivers/media/video/gspca
parent66f358211d4f8bf1a43e3aef9565c5c1454f73b3 (diff)
V4L/DVB (8366): gspca: Better code for ov6650 and ov7630.
sonixb: Common code between ov6650 and ov7630. Fix brightness oscillation with ov6650 sensor. Signed-off-by: Hans de Goede <j.w.r.degoede@hhs.nl> Signed-off-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/gspca')
-rw-r--r--drivers/media/video/gspca/sonixb.c91
1 files changed, 34 insertions, 57 deletions
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c
index 51435e3dbb1..4625a464a54 100644
--- a/drivers/media/video/gspca/sonixb.c
+++ b/drivers/media/video/gspca/sonixb.c
@@ -48,7 +48,6 @@ struct sd {
48 48
49 unsigned char fr_h_sz; /* size of frame header */ 49 unsigned char fr_h_sz; /* size of frame header */
50 char sensor; /* Type of image sensor chip */ 50 char sensor; /* Type of image sensor chip */
51 char sensor_has_gain;
52#define SENSOR_HV7131R 0 51#define SENSOR_HV7131R 0
53#define SENSOR_OV6650 1 52#define SENSOR_OV6650 1
54#define SENSOR_OV7630 2 53#define SENSOR_OV7630 2
@@ -57,6 +56,8 @@ struct sd {
57#define SENSOR_PAS202 5 56#define SENSOR_PAS202 5
58#define SENSOR_TAS5110 6 57#define SENSOR_TAS5110 6
59#define SENSOR_TAS5130CXX 7 58#define SENSOR_TAS5130CXX 7
59 char sensor_has_gain;
60 __u8 sensor_addr;
60}; 61};
61 62
62#define COMP2 0x8f 63#define COMP2 0x8f
@@ -495,21 +496,14 @@ static void setbrightness(struct gspca_dev *gspca_dev)
495 __u8 value; 496 __u8 value;
496 497
497 switch (sd->sensor) { 498 switch (sd->sensor) {
498 case SENSOR_OV6650: { 499 case SENSOR_OV6650:
499 __u8 i2cOV6650[] =
500 {0xa0, 0x60, 0x06, 0x11, 0x99, 0x04, 0x94, 0x15};
501
502 i2cOV6650[3] = sd->brightness;
503 if (i2c_w(gspca_dev, i2cOV6650) < 0)
504 goto err;
505 break;
506 }
507 case SENSOR_OV7630_3: 500 case SENSOR_OV7630_3:
508 case SENSOR_OV7630: { 501 case SENSOR_OV7630: {
509 __u8 i2cOV[] = 502 __u8 i2cOV[] =
510 {0xa0, 0x21, 0x06, 0x36, 0xbd, 0x06, 0xf6, 0x16}; 503 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
511 504
512 /* change reg 0x06 */ 505 /* change reg 0x06 */
506 i2cOV[1] = sd->sensor_addr;
513 i2cOV[3] = sd->brightness; 507 i2cOV[3] = sd->brightness;
514 if (i2c_w(gspca_dev, i2cOV) < 0) 508 if (i2c_w(gspca_dev, i2cOV) < 0)
515 goto err; 509 goto err;
@@ -579,6 +573,7 @@ err:
579static void setsensorgain(struct gspca_dev *gspca_dev) 573static void setsensorgain(struct gspca_dev *gspca_dev)
580{ 574{
581 struct sd *sd = (struct sd *) gspca_dev; 575 struct sd *sd = (struct sd *) gspca_dev;
576 unsigned char gain = sd->gain;
582 577
583 switch (sd->sensor) { 578 switch (sd->sensor) {
584 579
@@ -586,23 +581,20 @@ static void setsensorgain(struct gspca_dev *gspca_dev)
586 __u8 i2c[] = 581 __u8 i2c[] =
587 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10}; 582 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
588 583
589 i2c[4] = 255 - sd->gain; 584 i2c[4] = 255 - gain;
590 if (i2c_w(gspca_dev, i2c) < 0) 585 if (i2c_w(gspca_dev, i2c) < 0)
591 goto err; 586 goto err;
592 break; 587 break;
593 } 588 }
594 case SENSOR_OV6650: {
595 __u8 i2c[] = {0xa0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
596 589
597 i2c[3] = sd->gain >> 3; 590 case SENSOR_OV6650:
598 if (i2c_w(gspca_dev, i2c) < 0) 591 gain >>= 1;
599 goto err; 592 /* fall thru */
600 break;
601 }
602 case SENSOR_OV7630_3: { 593 case SENSOR_OV7630_3: {
603 __u8 i2c[] = {0xa0, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; 594 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
604 595
605 i2c[3] = sd->gain >> 2; 596 i2c[1] = sd->sensor_addr;
597 i2c[3] = gain >> 2;
606 if (i2c_w(gspca_dev, i2c) < 0) 598 if (i2c_w(gspca_dev, i2c) < 0)
607 goto err; 599 goto err;
608 break; 600 break;
@@ -652,9 +644,10 @@ static void setexposure(struct gspca_dev *gspca_dev)
652 reg_w(gspca_dev, 0x19, &reg, 1); 644 reg_w(gspca_dev, 0x19, &reg, 1);
653 break; 645 break;
654 } 646 }
655 case SENSOR_OV6650: { 647 case SENSOR_OV6650:
656 /* The ov6650 has 2 registers which both influence exposure, 648 case SENSOR_OV7630_3: {
657 first there is register 11, whose low nibble sets the no fps 649 /* The ov6650 / ov7630 have 2 registers which both influence
650 exposure, register 11, whose low nibble sets the nr off fps
658 according to: fps = 30 / (low_nibble + 1) 651 according to: fps = 30 / (low_nibble + 1)
659 652
660 The fps configures the maximum exposure setting, but it is 653 The fps configures the maximum exposure setting, but it is
@@ -667,15 +660,15 @@ static void setexposure(struct gspca_dev *gspca_dev)
667 The code maps our 0 - 510 ms exposure ctrl to these 2 660 The code maps our 0 - 510 ms exposure ctrl to these 2
668 registers, trying to keep fps as high as possible. 661 registers, trying to keep fps as high as possible.
669 */ 662 */
670 __u8 i2c[] = {0xb0, 0x60, 0x10, 0x00, 0xc0, 0x00, 0x00, 0x10}; 663 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0xc0, 0x00, 0x00, 0x10};
671 int reg10, reg11; 664 int reg10, reg11;
672 /* ov6645 datasheet says reg10_max is 9a, but that uses 665 /* ov6645 datasheet says reg10_max is 9a, but that uses
673 tline * 2 * reg10 as formula for calculating texpo, the 666 tline * 2 * reg10 as formula for calculating texpo, the
674 ov6650 probably uses the same formula as the 7730 which uses 667 ov6650 probably uses the same formula as the 7730 which uses
675 tline * 4 * reg10, which explains why the reg10max we've 668 tline * 4 * reg10, which explains why the reg10max we've
676 found experimentally for the ov6650 is exactly half that of 669 found experimentally for the ov6650 is exactly half that of
677 the ov6645. */ 670 the ov6645. The ov7630 datasheet says the max is 0x41. */
678 const int reg10_max = 0x4d; 671 const int reg10_max = (sd->sensor == SENSOR_OV6650)? 0x4d:0x41;
679 672
680 reg11 = (60 * sd->exposure + 999) / 1000; 673 reg11 = (60 * sd->exposure + 999) / 1000;
681 if (reg11 < 1) 674 if (reg11 < 1)
@@ -686,40 +679,18 @@ static void setexposure(struct gspca_dev *gspca_dev)
686 /* frame exposure time in ms = 1000 * reg11 / 30 -> 679 /* frame exposure time in ms = 1000 * reg11 / 30 ->
687 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */ 680 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
688 reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11); 681 reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
689 if (reg10 < 1) /* 0 is a valid value, but is very _black_ */
690 reg10 = 1;
691 else if (reg10 > reg10_max)
692 reg10 = reg10_max;
693 682
694 /* Write reg 10 and reg11 low nibble */ 683 /* Don't allow this to get below 10 when using autogain, the
695 i2c[3] = reg10; 684 steps become very large (relatively) when below 10 causing
696 i2c[4] |= reg11 - 1; 685 the image to oscilate from much too dark, to much too bright
697 if (i2c_w(gspca_dev, i2c) < 0) 686 and back again. */
698 PDEBUG(D_ERR, "i2c error exposure"); 687 if (sd->autogain && reg10 < 10)
699 break; 688 reg10 = 10;
700 }
701 case SENSOR_OV7630_3: {
702 __u8 i2c[] = {0xb0, 0x21, 0x10, 0x00, 0xc0, 0x00, 0x00, 0x10};
703 int reg10, reg11;
704 /* No clear idea why, but setting reg10 above this value
705 results in no change */
706 const int reg10_max = 0x4d;
707
708 reg11 = (60 * sd->exposure + 999) / 1000;
709 if (reg11 < 1)
710 reg11 = 1;
711 else if (reg11 > 16)
712 reg11 = 16;
713
714 /* frame exposure time in ms = 1000 * reg11 / 30 ->
715 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
716 reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
717 if (reg10 < 1) /* 0 is a valid value, but is very _black_ */
718 reg10 = 1;
719 else if (reg10 > reg10_max) 689 else if (reg10 > reg10_max)
720 reg10 = reg10_max; 690 reg10 = reg10_max;
721 691
722 /* Write reg 10 and reg11 low nibble */ 692 /* Write reg 10 and reg11 low nibble */
693 i2c[1] = sd->sensor_addr;
723 i2c[3] = reg10; 694 i2c[3] = reg10;
724 i2c[4] |= reg11 - 1; 695 i2c[4] |= reg11 - 1;
725 if (i2c_w(gspca_dev, i2c) < 0) 696 if (i2c_w(gspca_dev, i2c) < 0)
@@ -770,8 +741,11 @@ static void do_autogain(struct gspca_dev *gspca_dev)
770 sd->autogain_ignore_frames--; 741 sd->autogain_ignore_frames--;
771 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, 742 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
772 sd->brightness * DESIRED_AVG_LUM / 127, 743 sd->brightness * DESIRED_AVG_LUM / 127,
773 AUTOGAIN_DEADZONE, GAIN_KNEE, EXPOSURE_KNEE)) 744 AUTOGAIN_DEADZONE, GAIN_KNEE, EXPOSURE_KNEE)) {
745 PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d\n",
746 (int)sd->gain, (int)sd->exposure);
774 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES; 747 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
748 }
775} 749}
776 750
777/* this function is called at probe time */ 751/* this function is called at probe time */
@@ -814,6 +788,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
814 case 0x6011: /* SN9C101 - SN9C101G */ 788 case 0x6011: /* SN9C101 - SN9C101G */
815 sd->sensor = SENSOR_OV6650; 789 sd->sensor = SENSOR_OV6650;
816 sd->sensor_has_gain = 1; 790 sd->sensor_has_gain = 1;
791 sd->sensor_addr = 0x60;
817 sd->sd_desc.nctrls = 4; 792 sd->sd_desc.nctrls = 4;
818 sd->sd_desc.dq_callback = do_autogain; 793 sd->sd_desc.dq_callback = do_autogain;
819 sif = 1; 794 sif = 1;
@@ -822,9 +797,11 @@ static int sd_config(struct gspca_dev *gspca_dev,
822 case 0x602c: /* SN9C102 */ 797 case 0x602c: /* SN9C102 */
823 case 0x602e: /* SN9C102 */ 798 case 0x602e: /* SN9C102 */
824 sd->sensor = SENSOR_OV7630; 799 sd->sensor = SENSOR_OV7630;
800 sd->sensor_addr = 0x21;
825 break; 801 break;
826 case 0x60b0: /* SN9C103 */ 802 case 0x60b0: /* SN9C103 */
827 sd->sensor = SENSOR_OV7630_3; 803 sd->sensor = SENSOR_OV7630_3;
804 sd->sensor_addr = 0x21;
828 sd->fr_h_sz = 18; /* size of frame header */ 805 sd->fr_h_sz = 18; /* size of frame header */
829 sd->sensor_has_gain = 1; 806 sd->sensor_has_gain = 1;
830 sd->sd_desc.nctrls = 4; 807 sd->sd_desc.nctrls = 4;