aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorHans de Goede <j.w.r.degoede@hhs.nl>2008-07-22 06:09:33 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-07-26 11:54:09 -0400
commit6af492e56648e786e0dfb84d538fb7f9ecc02504 (patch)
tree97afb529021a0ed188a09bac6e98077ddea34f1d /drivers/media/video
parentc5e0bd1a982ee449b3598600f85895dc3bc8c13f (diff)
V4L/DVB (8455): gspca_sonixb sn9c103 + ov7630 autoexposure and cleanup
Andoni Zubimendi has been doing some testing with his sn9c103 cam with ov7630 sensor, and with this patch the exposure setting and autoexposure now work. This patch also removes some special cases in the shared ov6650 / ov7630 code which now are handled the same for both sensors and it adds a new special case which stops us from changing the hsync / vsync polarity settings from their default on the ov7630 (which we were doing as a side-effect of using the ov6650 exposure code for the ov7630). Last this patch removes the superficial difference between the OV7630 and OV7630_3 sensors. Signed-off-by: Andoni Zubimendi <andoni.zubimendi@gmail.com> Signed-off-by: Hans de Goede <j.w.r.degoede@hhs.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/gspca/sonixb.c174
1 files changed, 82 insertions, 92 deletions
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c
index f6bef896d3a5..4f9c9ecb06e8 100644
--- a/drivers/media/video/gspca/sonixb.c
+++ b/drivers/media/video/gspca/sonixb.c
@@ -41,6 +41,7 @@ struct sd {
41 unsigned char brightness; 41 unsigned char brightness;
42 unsigned char autogain; 42 unsigned char autogain;
43 unsigned char autogain_ignore_frames; 43 unsigned char autogain_ignore_frames;
44 unsigned char frames_to_drop;
44 unsigned char freq; /* light freq filter setting */ 45 unsigned char freq; /* light freq filter setting */
45 unsigned char saturation; 46 unsigned char saturation;
46 unsigned char hue; 47 unsigned char hue;
@@ -51,13 +52,13 @@ struct sd {
51#define SENSOR_HV7131R 0 52#define SENSOR_HV7131R 0
52#define SENSOR_OV6650 1 53#define SENSOR_OV6650 1
53#define SENSOR_OV7630 2 54#define SENSOR_OV7630 2
54#define SENSOR_OV7630_3 3 55#define SENSOR_PAS106 3
55#define SENSOR_PAS106 4 56#define SENSOR_PAS202 4
56#define SENSOR_PAS202 5 57#define SENSOR_TAS5110 5
57#define SENSOR_TAS5110 6 58#define SENSOR_TAS5130CXX 6
58#define SENSOR_TAS5130CXX 7
59 char sensor_has_gain; 59 char sensor_has_gain;
60 __u8 sensor_addr; 60 __u8 sensor_addr;
61 __u8 reg11;
61}; 62};
62 63
63#define COMP2 0x8f 64#define COMP2 0x8f
@@ -318,7 +319,7 @@ static const __u8 initOv7630_3[] = {
318 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */ 319 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
319 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff /* r29 .. r30 */ 320 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff /* r29 .. r30 */
320}; 321};
321static const __u8 ov7630_sensor_init_com[][8] = { 322static const __u8 ov7630_sensor_init[][8] = {
322 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, 323 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
323 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10}, 324 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
324/* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */ 325/* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
@@ -339,17 +340,6 @@ static const __u8 ov7630_sensor_init_com[][8] = {
339 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10}, 340 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
340 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10}, 341 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
341}; 342};
342static const __u8 ov7630_sensor_init[][8] = {
343 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 200ms */
344 {0xa0, 0x21, 0x11, 0x01, 0xbd, 0x06, 0xf6, 0x10}, /* jfm */
345 {0xa0, 0x21, 0x10, 0x57, 0xbd, 0x06, 0xf6, 0x16},
346 {0xa0, 0x21, 0x76, 0x02, 0xbd, 0x06, 0xf6, 0x16},
347 {0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15}, /* gain */
348};
349static const __u8 ov7630_sensor_init_3[][8] = {
350 {0xa0, 0x21, 0x2a, 0xa0, 0x00, 0x00, 0x00, 0x10},
351 {0xa0, 0x21, 0x2a, 0x80, 0x00, 0x00, 0x00, 0x10},
352};
353 343
354static const __u8 initPas106[] = { 344static const __u8 initPas106[] = {
355 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00, 345 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
@@ -539,7 +529,6 @@ static void setbrightness(struct gspca_dev *gspca_dev)
539 529
540 switch (sd->sensor) { 530 switch (sd->sensor) {
541 case SENSOR_OV6650: 531 case SENSOR_OV6650:
542 case SENSOR_OV7630_3:
543 case SENSOR_OV7630: { 532 case SENSOR_OV7630: {
544 __u8 i2cOV[] = 533 __u8 i2cOV[] =
545 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}; 534 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
@@ -632,7 +621,7 @@ static void setsensorgain(struct gspca_dev *gspca_dev)
632 case SENSOR_OV6650: 621 case SENSOR_OV6650:
633 gain >>= 1; 622 gain >>= 1;
634 /* fall thru */ 623 /* fall thru */
635 case SENSOR_OV7630_3: { 624 case SENSOR_OV7630: {
636 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; 625 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
637 626
638 i2c[1] = sd->sensor_addr; 627 i2c[1] = sd->sensor_addr;
@@ -687,7 +676,7 @@ static void setexposure(struct gspca_dev *gspca_dev)
687 break; 676 break;
688 } 677 }
689 case SENSOR_OV6650: 678 case SENSOR_OV6650:
690 case SENSOR_OV7630_3: { 679 case SENSOR_OV7630: {
691 /* The ov6650 / ov7630 have 2 registers which both influence 680 /* The ov6650 / ov7630 have 2 registers which both influence
692 exposure, register 11, whose low nibble sets the nr off fps 681 exposure, register 11, whose low nibble sets the nr off fps
693 according to: fps = 30 / (low_nibble + 1) 682 according to: fps = 30 / (low_nibble + 1)
@@ -702,16 +691,20 @@ static void setexposure(struct gspca_dev *gspca_dev)
702 The code maps our 0 - 510 ms exposure ctrl to these 2 691 The code maps our 0 - 510 ms exposure ctrl to these 2
703 registers, trying to keep fps as high as possible. 692 registers, trying to keep fps as high as possible.
704 */ 693 */
705 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0xc0, 0x00, 0x00, 0x10}; 694 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10};
706 int reg10, reg11; 695 int reg10, reg11, reg10_max;
696
707 /* ov6645 datasheet says reg10_max is 9a, but that uses 697 /* ov6645 datasheet says reg10_max is 9a, but that uses
708 tline * 2 * reg10 as formula for calculating texpo, the 698 tline * 2 * reg10 as formula for calculating texpo, the
709 ov6650 probably uses the same formula as the 7730 which uses 699 ov6650 probably uses the same formula as the 7730 which uses
710 tline * 4 * reg10, which explains why the reg10max we've 700 tline * 4 * reg10, which explains why the reg10max we've
711 found experimentally for the ov6650 is exactly half that of 701 found experimentally for the ov6650 is exactly half that of
712 the ov6645. The ov7630 datasheet says the max is 0x41. */ 702 the ov6645. The ov7630 datasheet says the max is 0x41. */
713 const int reg10_max = (sd->sensor == SENSOR_OV6650) 703 if (sd->sensor == SENSOR_OV6650) {
714 ? 0x4d : 0x41; 704 reg10_max = 0x4d;
705 i2c[4] = 0xc0; /* OV6650 needs non default vsync pol */
706 } else
707 reg10_max = 0x41;
715 708
716 reg11 = (60 * sd->exposure + 999) / 1000; 709 reg11 = (60 * sd->exposure + 999) / 1000;
717 if (reg11 < 1) 710 if (reg11 < 1)
@@ -732,20 +725,23 @@ static void setexposure(struct gspca_dev *gspca_dev)
732 else if (reg10 > reg10_max) 725 else if (reg10 > reg10_max)
733 reg10 = reg10_max; 726 reg10 = reg10_max;
734 727
728 /* In 640x480, if the reg11 has less than 3, the image is
729 unstable (not enough bandwidth). */
730 if (gspca_dev->width == 640 && reg11 < 3)
731 reg11 = 3;
732
735 /* Write reg 10 and reg11 low nibble */ 733 /* Write reg 10 and reg11 low nibble */
736 i2c[1] = sd->sensor_addr; 734 i2c[1] = sd->sensor_addr;
737 i2c[3] = reg10; 735 i2c[3] = reg10;
738 i2c[4] |= reg11 - 1; 736 i2c[4] |= reg11 - 1;
739 if (sd->sensor == SENSOR_OV7630_3) { 737
740 __u8 reg76 = reg10 & 0x03; 738 /* If register 11 didn't change, don't change it */
741 __u8 i2c_reg76[] = {0xa0, 0x21, 0x76, 0x00, 739 if (sd->reg11 == reg11 )
742 0x00, 0x00, 0x00, 0x10}; 740 i2c[0] = 0xa0;
743 reg10 >>= 2; 741
744 i2c_reg76[3] = reg76; 742 if (i2c_w(gspca_dev, i2c) == 0)
745 if (i2c_w(gspca_dev, i2c_reg76) < 0) 743 sd->reg11 = reg11;
746 PDEBUG(D_ERR, "i2c error exposure"); 744 else
747 }
748 if (i2c_w(gspca_dev, i2c) < 0)
749 PDEBUG(D_ERR, "i2c error exposure"); 745 PDEBUG(D_ERR, "i2c error exposure");
750 break; 746 break;
751 } 747 }
@@ -758,11 +754,11 @@ static void setfreq(struct gspca_dev *gspca_dev)
758 754
759 switch (sd->sensor) { 755 switch (sd->sensor) {
760 case SENSOR_OV6650: 756 case SENSOR_OV6650:
761 case SENSOR_OV7630_3: { 757 case SENSOR_OV7630: {
762 /* Framerate adjust register for artificial light 50 hz flicker 758 /* Framerate adjust register for artificial light 50 hz flicker
763 compensation, identical to ov6630 0x2b register, see ov6630 759 compensation, for the ov6650 this is identical to ov6630
764 datasheet. 760 0x2b register, see ov6630 datasheet.
765 0x4f -> (30 fps -> 25 fps), 0x00 -> no adjustment */ 761 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
766 __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}; 762 __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
767 switch (sd->freq) { 763 switch (sd->freq) {
768 default: 764 default:
@@ -789,7 +785,6 @@ static void setsaturation(struct gspca_dev *gspca_dev)
789 785
790 switch (sd->sensor) { 786 switch (sd->sensor) {
791/* case SENSOR_OV6650: */ 787/* case SENSOR_OV6650: */
792 case SENSOR_OV7630_3:
793 case SENSOR_OV7630: { 788 case SENSOR_OV7630: {
794 __u8 i2c[] = {0xa0, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10}; 789 __u8 i2c[] = {0xa0, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10};
795 i2c[1] = sd->sensor_addr; 790 i2c[1] = sd->sensor_addr;
@@ -810,7 +805,6 @@ static void sethue(struct gspca_dev *gspca_dev)
810 805
811 switch (sd->sensor) { 806 switch (sd->sensor) {
812/* case SENSOR_OV6650: */ 807/* case SENSOR_OV6650: */
813 case SENSOR_OV7630_3:
814 case SENSOR_OV7630: { 808 case SENSOR_OV7630: {
815 __u8 i2c[] = {0xa0, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10}; 809 __u8 i2c[] = {0xa0, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10};
816 i2c[1] = sd->sensor_addr; 810 i2c[1] = sd->sensor_addr;
@@ -830,7 +824,6 @@ static void setcontrast(struct gspca_dev *gspca_dev)
830 824
831 switch (sd->sensor) { 825 switch (sd->sensor) {
832/* case SENSOR_OV6650: */ 826/* case SENSOR_OV6650: */
833 case SENSOR_OV7630_3:
834 case SENSOR_OV7630: { 827 case SENSOR_OV7630: {
835 __u8 i2c[] = {0xa0, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10}; 828 __u8 i2c[] = {0xa0, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10};
836 i2c[1] = sd->sensor_addr; 829 i2c[1] = sd->sensor_addr;
@@ -880,8 +873,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
880 873
881 sd->fr_h_sz = 12; /* default size of the frame header */ 874 sd->fr_h_sz = 12; /* default size of the frame header */
882 sd->sd_desc.nctrls = 2; /* default nb of ctrls */ 875 sd->sd_desc.nctrls = 2; /* default nb of ctrls */
883 sd->autogain = AUTOGAIN_DEF; /* default is autogain active */
884
885 product = id->idProduct; 876 product = id->idProduct;
886/* switch (id->idVendor) { */ 877/* switch (id->idVendor) { */
887/* case 0x0c45: * Sonix */ 878/* case 0x0c45: * Sonix */
@@ -912,17 +903,14 @@ static int sd_config(struct gspca_dev *gspca_dev,
912 case 0x6019: /* SN9C101 */ 903 case 0x6019: /* SN9C101 */
913 case 0x602c: /* SN9C102 */ 904 case 0x602c: /* SN9C102 */
914 case 0x602e: /* SN9C102 */ 905 case 0x602e: /* SN9C102 */
915 sd->sensor = SENSOR_OV7630;
916 sd->sensor_addr = 0x21;
917 break;
918 case 0x60b0: /* SN9C103 */ 906 case 0x60b0: /* SN9C103 */
919 sd->sensor = SENSOR_OV7630_3; 907 sd->sensor = SENSOR_OV7630;
920 sd->sensor_addr = 0x21; 908 sd->sensor_addr = 0x21;
921 sd->fr_h_sz = 18; /* size of frame header */
922 sd->sensor_has_gain = 1; 909 sd->sensor_has_gain = 1;
923 sd->sd_desc.nctrls = 8; 910 sd->sd_desc.nctrls = 5;
924 sd->sd_desc.dq_callback = do_autogain; 911 sd->sd_desc.dq_callback = do_autogain;
925 sd->autogain = 0; 912 if (product == 0x60b0)
913 sd->fr_h_sz = 18; /* size of frame header */
926 break; 914 break;
927 case 0x6024: /* SN9C102 */ 915 case 0x6024: /* SN9C102 */
928 case 0x6025: /* SN9C102 */ 916 case 0x6025: /* SN9C102 */
@@ -948,7 +936,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
948 if (!sif) { 936 if (!sif) {
949 cam->cam_mode = vga_mode; 937 cam->cam_mode = vga_mode;
950 cam->nmodes = ARRAY_SIZE(vga_mode); 938 cam->nmodes = ARRAY_SIZE(vga_mode);
951 if (sd->sensor == SENSOR_OV7630_3) { 939 if (product == 0x60b0) { /* SN9C103 with OV7630 */
952 /* We only have 320x240 & 640x480 */ 940 /* We only have 320x240 & 640x480 */
953 cam->cam_mode++; 941 cam->cam_mode++;
954 cam->nmodes--; 942 cam->nmodes--;
@@ -960,12 +948,15 @@ static int sd_config(struct gspca_dev *gspca_dev,
960 sd->brightness = BRIGHTNESS_DEF; 948 sd->brightness = BRIGHTNESS_DEF;
961 sd->gain = GAIN_DEF; 949 sd->gain = GAIN_DEF;
962 sd->exposure = EXPOSURE_DEF; 950 sd->exposure = EXPOSURE_DEF;
951 sd->autogain = AUTOGAIN_DEF;
963 sd->freq = FREQ_DEF; 952 sd->freq = FREQ_DEF;
964 sd->contrast = CONTRAST_DEF; 953 sd->contrast = CONTRAST_DEF;
965 sd->saturation = SATURATION_DEF; 954 sd->saturation = SATURATION_DEF;
966 sd->hue = HUE_DEF; 955 sd->hue = HUE_DEF;
967 if (sd->sensor == SENSOR_OV7630_3) /* jfm: from win trace */ 956
957 if (product == 0x60b0) /* SN9C103 with OV7630 */
968 reg_w(gspca_dev, 0x01, probe_ov7630, sizeof probe_ov7630); 958 reg_w(gspca_dev, 0x01, probe_ov7630, sizeof probe_ov7630);
959
969 return 0; 960 return 0;
970} 961}
971 962
@@ -999,7 +990,7 @@ static void pas106_i2cinit(struct gspca_dev *gspca_dev)
999static void sd_start(struct gspca_dev *gspca_dev) 990static void sd_start(struct gspca_dev *gspca_dev)
1000{ 991{
1001 struct sd *sd = (struct sd *) gspca_dev; 992 struct sd *sd = (struct sd *) gspca_dev;
1002 int mode, l; 993 int mode, l = 0x1f;
1003 const __u8 *sn9c10x; 994 const __u8 *sn9c10x;
1004 __u8 reg01, reg17; 995 __u8 reg01, reg17;
1005 __u8 reg17_19[3]; 996 __u8 reg17_19[3];
@@ -1019,13 +1010,11 @@ static void sd_start(struct gspca_dev *gspca_dev)
1019 reg17_19[2] = 0x20; 1010 reg17_19[2] = 0x20;
1020 break; 1011 break;
1021 case SENSOR_OV7630: 1012 case SENSOR_OV7630:
1022 sn9c10x = initOv7630; 1013 if (sd->fr_h_sz == 18) { /* SN9C103 */
1023 reg17_19[0] = 0x68; 1014 sn9c10x = initOv7630_3;
1024 reg17_19[1] = (mode << 4) | COMP2; 1015 l = sizeof initOv7630_3;
1025 reg17_19[2] = MCK_INIT1; 1016 } else
1026 break; 1017 sn9c10x = initOv7630;
1027 case SENSOR_OV7630_3:
1028 sn9c10x = initOv7630_3;
1029 reg17_19[0] = 0x68; 1018 reg17_19[0] = 0x68;
1030 reg17_19[1] = (mode << 4) | COMP2; 1019 reg17_19[1] = (mode << 4) | COMP2;
1031 reg17_19[2] = MCK_INIT1; 1020 reg17_19[2] = MCK_INIT1;
@@ -1056,30 +1045,22 @@ static void sd_start(struct gspca_dev *gspca_dev)
1056 reg17_19[2] = mode ? 0x23 : 0x43; 1045 reg17_19[2] = mode ? 0x23 : 0x43;
1057 break; 1046 break;
1058 } 1047 }
1059 switch (sd->sensor) { 1048
1060 case SENSOR_OV7630: 1049 /* Special case for SN9C101/2 with OV 7630 */
1050 /* HDG: is this really necessary we overwrite the values immediately
1051 afterwards with the ones from the template ?? */
1052 if (sd->sensor == SENSOR_OV7630 && sd->fr_h_sz == 12) {
1061 reg01 = 0x06; 1053 reg01 = 0x06;
1062 reg17 = 0x29; 1054 reg17 = 0x29;
1063 l = sizeof initOv7630; 1055 } else {
1064 break;
1065 case SENSOR_OV7630_3:
1066 reg01 = 0x44;
1067 reg17 = 0x68;
1068 l = sizeof initOv7630_3;
1069 break;
1070 default:
1071 reg01 = sn9c10x[0]; 1056 reg01 = sn9c10x[0];
1072 reg17 = sn9c10x[0x17 - 1]; 1057 reg17 = sn9c10x[0x17 - 1];
1073 l = 0x1f;
1074 break;
1075 } 1058 }
1076 1059
1077 /* reg 0x01 bit 2 video transfert on */ 1060 /* reg 0x01 bit 2 video transfert on */
1078 reg_w(gspca_dev, 0x01, &reg01, 1); 1061 reg_w(gspca_dev, 0x01, &reg01, 1);
1079 /* reg 0x17 SensorClk enable inv Clk 0x60 */ 1062 /* reg 0x17 SensorClk enable inv Clk 0x60 */
1080 reg_w(gspca_dev, 0x17, &reg17, 1); 1063 reg_w(gspca_dev, 0x17, &reg17, 1);
1081/*fixme: for ov7630 102
1082 reg_w(gspca_dev, 0x01, {0x06, sn9c10x[1]}, 2); */
1083 /* Set the registers from the template */ 1064 /* Set the registers from the template */
1084 reg_w_big(gspca_dev, 0x01, sn9c10x, l); 1065 reg_w_big(gspca_dev, 0x01, sn9c10x, l);
1085 switch (sd->sensor) { 1066 switch (sd->sensor) {
@@ -1092,17 +1073,13 @@ static void sd_start(struct gspca_dev *gspca_dev)
1092 sizeof ov6650_sensor_init); 1073 sizeof ov6650_sensor_init);
1093 break; 1074 break;
1094 case SENSOR_OV7630: 1075 case SENSOR_OV7630:
1095 i2c_w_vector(gspca_dev, ov7630_sensor_init_com,
1096 sizeof ov7630_sensor_init_com);
1097 msleep(200);
1098 i2c_w_vector(gspca_dev, ov7630_sensor_init, 1076 i2c_w_vector(gspca_dev, ov7630_sensor_init,
1099 sizeof ov7630_sensor_init); 1077 sizeof ov7630_sensor_init);
1100 break; 1078 if (sd->fr_h_sz == 18) { /* SN9C103 */
1101 case SENSOR_OV7630_3: 1079 const __u8 i2c[] = { 0xa0, 0x21, 0x13, 0x80, 0x00,
1102 i2c_w_vector(gspca_dev, ov7630_sensor_init_com, 1080 0x00, 0x00, 0x10 };
1103 sizeof ov7630_sensor_init_com); 1081 i2c_w(gspca_dev, i2c);
1104 msleep(200); 1082 }
1105 i2c_w(gspca_dev, ov7630_sensor_init_3[mode]);
1106 break; 1083 break;
1107 case SENSOR_PAS106: 1084 case SENSOR_PAS106:
1108 pas106_i2cinit(gspca_dev); 1085 pas106_i2cinit(gspca_dev);
@@ -1142,6 +1119,8 @@ static void sd_start(struct gspca_dev *gspca_dev)
1142 reg_w(gspca_dev, 0x18, &reg17_19[1], 2); 1119 reg_w(gspca_dev, 0x18, &reg17_19[1], 2);
1143 msleep(20); 1120 msleep(20);
1144 1121
1122 sd->reg11 = -1;
1123
1145 setgain(gspca_dev); 1124 setgain(gspca_dev);
1146 setbrightness(gspca_dev); 1125 setbrightness(gspca_dev);
1147 setexposure(gspca_dev); 1126 setexposure(gspca_dev);
@@ -1150,6 +1129,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
1150 sethue(gspca_dev); 1129 sethue(gspca_dev);
1151 setcontrast(gspca_dev); 1130 setcontrast(gspca_dev);
1152 1131
1132 sd->frames_to_drop = 0;
1153 sd->autogain_ignore_frames = 0; 1133 sd->autogain_ignore_frames = 0;
1154 atomic_set(&sd->avg_lum, -1); 1134 atomic_set(&sd->avg_lum, -1);
1155} 1135}
@@ -1195,21 +1175,31 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1195 && data[3 + i] == 0xc4 1175 && data[3 + i] == 0xc4
1196 && data[4 + i] == 0xc4 1176 && data[4 + i] == 0xc4
1197 && data[5 + i] == 0x96) { /* start of frame */ 1177 && data[5 + i] == 0x96) { /* start of frame */
1198 frame = gspca_frame_add(gspca_dev, LAST_PACKET, 1178 int lum = -1;
1199 frame, data, 0); 1179 int pkt_type = LAST_PACKET;
1180
1200 if (len - i < sd->fr_h_sz) { 1181 if (len - i < sd->fr_h_sz) {
1201 atomic_set(&sd->avg_lum, -1);
1202 PDEBUG(D_STREAM, "packet too short to" 1182 PDEBUG(D_STREAM, "packet too short to"
1203 " get avg brightness"); 1183 " get avg brightness");
1204 } else if (sd->fr_h_sz == 12) { 1184 } else if (sd->fr_h_sz == 12) {
1205 atomic_set(&sd->avg_lum, 1185 lum = data[i + 8] + (data[i + 9] << 8);
1206 data[i + 8] +
1207 (data[i + 9] << 8));
1208 } else { 1186 } else {
1209 atomic_set(&sd->avg_lum, 1187 lum = data[i + 9] +
1210 data[i + 9] + 1188 (data[i + 10] << 8);
1211 (data[i + 10] << 8));
1212 } 1189 }
1190 if (lum == 0) {
1191 lum = -1;
1192 sd->frames_to_drop = 2;
1193 }
1194 atomic_set(&sd->avg_lum, lum);
1195
1196 if (sd->frames_to_drop) {
1197 sd->frames_to_drop--;
1198 pkt_type = DISCARD_PACKET;
1199 }
1200
1201 frame = gspca_frame_add(gspca_dev, pkt_type,
1202 frame, data, 0);
1213 data += i + sd->fr_h_sz; 1203 data += i + sd->fr_h_sz;
1214 len -= i + sd->fr_h_sz; 1204 len -= i + sd->fr_h_sz;
1215 gspca_frame_add(gspca_dev, FIRST_PACKET, 1205 gspca_frame_add(gspca_dev, FIRST_PACKET,