diff options
author | Hans de Goede <j.w.r.degoede@hhs.nl> | 2008-07-16 14:29:11 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-07-20 06:27:19 -0400 |
commit | a975a5279e39b5bc104cc8329d25a36a25136ad9 (patch) | |
tree | c7b40ddea02a4c972e773975df479fb53ec01204 /drivers | |
parent | 66f358211d4f8bf1a43e3aef9565c5c1454f73b3 (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')
-rw-r--r-- | drivers/media/video/gspca/sonixb.c | 91 |
1 files changed, 34 insertions, 57 deletions
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 51435e3dbb10..4625a464a547 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: | |||
579 | static void setsensorgain(struct gspca_dev *gspca_dev) | 573 | static 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, ®, 1); | 644 | reg_w(gspca_dev, 0x19, ®, 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; |