diff options
author | Hans de Goede <hdegoede@redhat.com> | 2012-05-15 03:23:55 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-07-30 17:17:56 -0400 |
commit | 9153ac3ba4bccfdccb43e765cf1cf9bd9e65e657 (patch) | |
tree | a86e648eccf3c6ed9f06fd9d9727ade85345f4b4 /drivers/media/video/gspca | |
parent | 4848ea77e0e8131fe928a11e15dc2d5c47862bb5 (diff) |
[media] gscpa_sonixb: Convert to the control framework
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/gspca')
-rw-r--r-- | drivers/media/video/gspca/sonixb.c | 454 |
1 files changed, 200 insertions, 254 deletions
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index 65fa4f2fb0b2..1bfe5f8947b7 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c | |||
@@ -56,26 +56,16 @@ MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>"); | |||
56 | MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver"); | 56 | MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver"); |
57 | MODULE_LICENSE("GPL"); | 57 | MODULE_LICENSE("GPL"); |
58 | 58 | ||
59 | /* controls */ | ||
60 | enum e_ctrl { | ||
61 | BRIGHTNESS, | ||
62 | GAIN, | ||
63 | EXPOSURE, | ||
64 | AUTOGAIN, | ||
65 | FREQ, | ||
66 | NCTRLS /* number of controls */ | ||
67 | }; | ||
68 | |||
69 | /* specific webcam descriptor */ | 59 | /* specific webcam descriptor */ |
70 | struct sd { | 60 | struct sd { |
71 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 61 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
72 | 62 | ||
73 | struct gspca_ctrl ctrls[NCTRLS]; | 63 | struct v4l2_ctrl *brightness; |
64 | struct v4l2_ctrl *plfreq; | ||
74 | 65 | ||
75 | atomic_t avg_lum; | 66 | atomic_t avg_lum; |
76 | int prev_avg_lum; | 67 | int prev_avg_lum; |
77 | int exp_too_low_cnt; | 68 | int exposure_knee; |
78 | int exp_too_high_cnt; | ||
79 | int header_read; | 69 | int header_read; |
80 | u8 header[12]; /* Header without sof marker */ | 70 | u8 header[12]; /* Header without sof marker */ |
81 | 71 | ||
@@ -107,24 +97,16 @@ struct sensor_data { | |||
107 | sensor_init_t *sensor_init; | 97 | sensor_init_t *sensor_init; |
108 | int sensor_init_size; | 98 | int sensor_init_size; |
109 | int flags; | 99 | int flags; |
110 | unsigned ctrl_dis; | ||
111 | __u8 sensor_addr; | 100 | __u8 sensor_addr; |
112 | }; | 101 | }; |
113 | 102 | ||
114 | /* sensor_data flags */ | 103 | /* sensor_data flags */ |
115 | #define F_GAIN 0x01 /* has gain */ | 104 | #define F_SIF 0x01 /* sif or vga */ |
116 | #define F_SIF 0x02 /* sif or vga */ | ||
117 | #define F_COARSE_EXPO 0x04 /* exposure control is coarse */ | ||
118 | 105 | ||
119 | /* priv field of struct v4l2_pix_format flags (do not use low nibble!) */ | 106 | /* priv field of struct v4l2_pix_format flags (do not use low nibble!) */ |
120 | #define MODE_RAW 0x10 /* raw bayer mode */ | 107 | #define MODE_RAW 0x10 /* raw bayer mode */ |
121 | #define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */ | 108 | #define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */ |
122 | 109 | ||
123 | /* ctrl_dis helper macros */ | ||
124 | #define NO_EXPO ((1 << EXPOSURE) | (1 << AUTOGAIN)) | ||
125 | #define NO_FREQ (1 << FREQ) | ||
126 | #define NO_BRIGHTNESS (1 << BRIGHTNESS) | ||
127 | |||
128 | #define COMP 0xc7 /* 0x87 //0x07 */ | 110 | #define COMP 0xc7 /* 0x87 //0x07 */ |
129 | #define COMP1 0xc9 /* 0x89 //0x09 */ | 111 | #define COMP1 0xc9 /* 0x89 //0x09 */ |
130 | 112 | ||
@@ -133,12 +115,12 @@ struct sensor_data { | |||
133 | 115 | ||
134 | #define SYS_CLK 0x04 | 116 | #define SYS_CLK 0x04 |
135 | 117 | ||
136 | #define SENS(bridge, sensor, _flags, _ctrl_dis, _sensor_addr) \ | 118 | #define SENS(bridge, sensor, _flags, _sensor_addr) \ |
137 | { \ | 119 | { \ |
138 | .bridge_init = bridge, \ | 120 | .bridge_init = bridge, \ |
139 | .sensor_init = sensor, \ | 121 | .sensor_init = sensor, \ |
140 | .sensor_init_size = sizeof(sensor), \ | 122 | .sensor_init_size = sizeof(sensor), \ |
141 | .flags = _flags, .ctrl_dis = _ctrl_dis, .sensor_addr = _sensor_addr \ | 123 | .flags = _flags, .sensor_addr = _sensor_addr \ |
142 | } | 124 | } |
143 | 125 | ||
144 | /* We calculate the autogain at the end of the transfer of a frame, at this | 126 | /* We calculate the autogain at the end of the transfer of a frame, at this |
@@ -147,87 +129,6 @@ struct sensor_data { | |||
147 | the new settings to come into effect before doing any other adjustments. */ | 129 | the new settings to come into effect before doing any other adjustments. */ |
148 | #define AUTOGAIN_IGNORE_FRAMES 1 | 130 | #define AUTOGAIN_IGNORE_FRAMES 1 |
149 | 131 | ||
150 | /* V4L2 controls supported by the driver */ | ||
151 | static void setbrightness(struct gspca_dev *gspca_dev); | ||
152 | static void setgain(struct gspca_dev *gspca_dev); | ||
153 | static void setexposure(struct gspca_dev *gspca_dev); | ||
154 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
155 | static void setfreq(struct gspca_dev *gspca_dev); | ||
156 | |||
157 | static const struct ctrl sd_ctrls[NCTRLS] = { | ||
158 | [BRIGHTNESS] = { | ||
159 | { | ||
160 | .id = V4L2_CID_BRIGHTNESS, | ||
161 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
162 | .name = "Brightness", | ||
163 | .minimum = 0, | ||
164 | .maximum = 255, | ||
165 | .step = 1, | ||
166 | .default_value = 127, | ||
167 | }, | ||
168 | .set_control = setbrightness | ||
169 | }, | ||
170 | [GAIN] = { | ||
171 | { | ||
172 | .id = V4L2_CID_GAIN, | ||
173 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
174 | .name = "Gain", | ||
175 | .minimum = 0, | ||
176 | .maximum = 255, | ||
177 | .step = 1, | ||
178 | #define GAIN_KNEE 230 | ||
179 | .default_value = 127, | ||
180 | }, | ||
181 | .set_control = setgain | ||
182 | }, | ||
183 | [EXPOSURE] = { | ||
184 | { | ||
185 | .id = V4L2_CID_EXPOSURE, | ||
186 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
187 | .name = "Exposure", | ||
188 | .minimum = 0, | ||
189 | .maximum = 1023, | ||
190 | .step = 1, | ||
191 | .default_value = 66, | ||
192 | /* 33 ms / 30 fps (except on PASXXX) */ | ||
193 | #define EXPOSURE_KNEE 200 /* 100 ms / 10 fps (except on PASXXX) */ | ||
194 | .flags = 0, | ||
195 | }, | ||
196 | .set_control = setexposure | ||
197 | }, | ||
198 | /* for coarse exposure */ | ||
199 | #define COARSE_EXPOSURE_MIN 2 | ||
200 | #define COARSE_EXPOSURE_MAX 15 | ||
201 | #define COARSE_EXPOSURE_DEF 2 /* 30 fps */ | ||
202 | [AUTOGAIN] = { | ||
203 | { | ||
204 | .id = V4L2_CID_AUTOGAIN, | ||
205 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
206 | .name = "Automatic Gain (and Exposure)", | ||
207 | .minimum = 0, | ||
208 | .maximum = 1, | ||
209 | .step = 1, | ||
210 | #define AUTOGAIN_DEF 1 | ||
211 | .default_value = AUTOGAIN_DEF, | ||
212 | .flags = V4L2_CTRL_FLAG_UPDATE | ||
213 | }, | ||
214 | .set = sd_setautogain, | ||
215 | }, | ||
216 | [FREQ] = { | ||
217 | { | ||
218 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | ||
219 | .type = V4L2_CTRL_TYPE_MENU, | ||
220 | .name = "Light frequency filter", | ||
221 | .minimum = 0, | ||
222 | .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ | ||
223 | .step = 1, | ||
224 | #define FREQ_DEF 0 | ||
225 | .default_value = FREQ_DEF, | ||
226 | }, | ||
227 | .set_control = setfreq | ||
228 | }, | ||
229 | }; | ||
230 | |||
231 | static const struct v4l2_pix_format vga_mode[] = { | 132 | static const struct v4l2_pix_format vga_mode[] = { |
232 | {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | 133 | {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, |
233 | .bytesperline = 160, | 134 | .bytesperline = 160, |
@@ -532,18 +433,15 @@ static const __u8 tas5130_sensor_init[][8] = { | |||
532 | }; | 433 | }; |
533 | 434 | ||
534 | static const struct sensor_data sensor_data[] = { | 435 | static const struct sensor_data sensor_data[] = { |
535 | SENS(initHv7131d, hv7131d_sensor_init, F_GAIN, NO_BRIGHTNESS|NO_FREQ, 0), | 436 | SENS(initHv7131d, hv7131d_sensor_init, 0, 0), |
536 | SENS(initHv7131r, hv7131r_sensor_init, 0, NO_BRIGHTNESS|NO_EXPO|NO_FREQ, 0), | 437 | SENS(initHv7131r, hv7131r_sensor_init, 0, 0), |
537 | SENS(initOv6650, ov6650_sensor_init, F_GAIN|F_SIF, 0, 0x60), | 438 | SENS(initOv6650, ov6650_sensor_init, F_SIF, 0x60), |
538 | SENS(initOv7630, ov7630_sensor_init, F_GAIN, 0, 0x21), | 439 | SENS(initOv7630, ov7630_sensor_init, 0, 0x21), |
539 | SENS(initPas106, pas106_sensor_init, F_GAIN|F_SIF, NO_FREQ, 0), | 440 | SENS(initPas106, pas106_sensor_init, F_SIF, 0), |
540 | SENS(initPas202, pas202_sensor_init, F_GAIN, NO_FREQ, 0), | 441 | SENS(initPas202, pas202_sensor_init, 0, 0), |
541 | SENS(initTas5110c, tas5110c_sensor_init, F_GAIN|F_SIF|F_COARSE_EXPO, | 442 | SENS(initTas5110c, tas5110c_sensor_init, F_SIF, 0), |
542 | NO_BRIGHTNESS|NO_FREQ, 0), | 443 | SENS(initTas5110d, tas5110d_sensor_init, F_SIF, 0), |
543 | SENS(initTas5110d, tas5110d_sensor_init, F_GAIN|F_SIF|F_COARSE_EXPO, | 444 | SENS(initTas5130, tas5130_sensor_init, 0, 0), |
544 | NO_BRIGHTNESS|NO_FREQ, 0), | ||
545 | SENS(initTas5130, tas5130_sensor_init, F_GAIN, | ||
546 | NO_BRIGHTNESS|NO_EXPO|NO_FREQ, 0), | ||
547 | }; | 445 | }; |
548 | 446 | ||
549 | /* get one byte in gspca_dev->usb_buf */ | 447 | /* get one byte in gspca_dev->usb_buf */ |
@@ -652,7 +550,7 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
652 | 550 | ||
653 | /* change reg 0x06 */ | 551 | /* change reg 0x06 */ |
654 | i2cOV[1] = sensor_data[sd->sensor].sensor_addr; | 552 | i2cOV[1] = sensor_data[sd->sensor].sensor_addr; |
655 | i2cOV[3] = sd->ctrls[BRIGHTNESS].val; | 553 | i2cOV[3] = sd->brightness->val; |
656 | i2c_w(gspca_dev, i2cOV); | 554 | i2c_w(gspca_dev, i2cOV); |
657 | break; | 555 | break; |
658 | } | 556 | } |
@@ -669,13 +567,13 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
669 | i2cpdoit[2] = 0x13; | 567 | i2cpdoit[2] = 0x13; |
670 | } | 568 | } |
671 | 569 | ||
672 | if (sd->ctrls[BRIGHTNESS].val < 127) { | 570 | if (sd->brightness->val < 127) { |
673 | /* change reg 0x0b, signreg */ | 571 | /* change reg 0x0b, signreg */ |
674 | i2cpbright[3] = 0x01; | 572 | i2cpbright[3] = 0x01; |
675 | /* set reg 0x0c, offset */ | 573 | /* set reg 0x0c, offset */ |
676 | i2cpbright[4] = 127 - sd->ctrls[BRIGHTNESS].val; | 574 | i2cpbright[4] = 127 - sd->brightness->val; |
677 | } else | 575 | } else |
678 | i2cpbright[4] = sd->ctrls[BRIGHTNESS].val - 127; | 576 | i2cpbright[4] = sd->brightness->val - 127; |
679 | 577 | ||
680 | i2c_w(gspca_dev, i2cpbright); | 578 | i2c_w(gspca_dev, i2cpbright); |
681 | i2c_w(gspca_dev, i2cpdoit); | 579 | i2c_w(gspca_dev, i2cpdoit); |
@@ -686,19 +584,19 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
686 | } | 584 | } |
687 | } | 585 | } |
688 | 586 | ||
689 | static void setsensorgain(struct gspca_dev *gspca_dev) | 587 | static void setgain(struct gspca_dev *gspca_dev) |
690 | { | 588 | { |
691 | struct sd *sd = (struct sd *) gspca_dev; | 589 | struct sd *sd = (struct sd *) gspca_dev; |
692 | u8 gain = sd->ctrls[GAIN].val; | 590 | u8 gain = gspca_dev->gain->val; |
693 | 591 | ||
694 | switch (sd->sensor) { | 592 | switch (sd->sensor) { |
695 | case SENSOR_HV7131D: { | 593 | case SENSOR_HV7131D: { |
696 | __u8 i2c[] = | 594 | __u8 i2c[] = |
697 | {0xc0, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x17}; | 595 | {0xc0, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x17}; |
698 | 596 | ||
699 | i2c[3] = 0x3f - (gain / 4); | 597 | i2c[3] = 0x3f - gain; |
700 | i2c[4] = 0x3f - (gain / 4); | 598 | i2c[4] = 0x3f - gain; |
701 | i2c[5] = 0x3f - (gain / 4); | 599 | i2c[5] = 0x3f - gain; |
702 | 600 | ||
703 | i2c_w(gspca_dev, i2c); | 601 | i2c_w(gspca_dev, i2c); |
704 | break; | 602 | break; |
@@ -729,13 +627,11 @@ static void setsensorgain(struct gspca_dev *gspca_dev) | |||
729 | break; | 627 | break; |
730 | } | 628 | } |
731 | case SENSOR_OV6650: | 629 | case SENSOR_OV6650: |
732 | gain >>= 1; | ||
733 | /* fall thru */ | ||
734 | case SENSOR_OV7630: { | 630 | case SENSOR_OV7630: { |
735 | __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; | 631 | __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; |
736 | 632 | ||
737 | i2c[1] = sensor_data[sd->sensor].sensor_addr; | 633 | i2c[1] = sensor_data[sd->sensor].sensor_addr; |
738 | i2c[3] = gain >> 2; | 634 | i2c[3] = gain; |
739 | i2c_w(gspca_dev, i2c); | 635 | i2c_w(gspca_dev, i2c); |
740 | break; | 636 | break; |
741 | } | 637 | } |
@@ -756,11 +652,11 @@ static void setsensorgain(struct gspca_dev *gspca_dev) | |||
756 | i2cpdoit[2] = 0x13; | 652 | i2cpdoit[2] = 0x13; |
757 | } | 653 | } |
758 | 654 | ||
759 | i2cpgain[3] = gain >> 3; | 655 | i2cpgain[3] = gain; |
760 | i2cpcolorgain[3] = gain >> 4; | 656 | i2cpcolorgain[3] = gain >> 1; |
761 | i2cpcolorgain[4] = gain >> 4; | 657 | i2cpcolorgain[4] = gain >> 1; |
762 | i2cpcolorgain[5] = gain >> 4; | 658 | i2cpcolorgain[5] = gain >> 1; |
763 | i2cpcolorgain[6] = gain >> 4; | 659 | i2cpcolorgain[6] = gain >> 1; |
764 | 660 | ||
765 | i2c_w(gspca_dev, i2cpgain); | 661 | i2c_w(gspca_dev, i2cpgain); |
766 | i2c_w(gspca_dev, i2cpcolorgain); | 662 | i2c_w(gspca_dev, i2cpcolorgain); |
@@ -768,33 +664,15 @@ static void setsensorgain(struct gspca_dev *gspca_dev) | |||
768 | break; | 664 | break; |
769 | } | 665 | } |
770 | default: | 666 | default: |
771 | break; | 667 | if (sd->bridge == BRIDGE_103) { |
772 | } | 668 | u8 buf[3] = { gain, gain, gain }; /* R, G, B */ |
773 | } | 669 | reg_w(gspca_dev, 0x05, buf, 3); |
774 | 670 | } else { | |
775 | static void setgain(struct gspca_dev *gspca_dev) | 671 | u8 buf[2]; |
776 | { | 672 | buf[0] = gain << 4 | gain; /* Red and blue */ |
777 | struct sd *sd = (struct sd *) gspca_dev; | 673 | buf[1] = gain; /* Green */ |
778 | __u8 gain; | 674 | reg_w(gspca_dev, 0x10, buf, 2); |
779 | __u8 buf[3] = { 0, 0, 0 }; | 675 | } |
780 | |||
781 | if (sensor_data[sd->sensor].flags & F_GAIN) { | ||
782 | /* Use the sensor gain to do the actual gain */ | ||
783 | setsensorgain(gspca_dev); | ||
784 | return; | ||
785 | } | ||
786 | |||
787 | if (sd->bridge == BRIDGE_103) { | ||
788 | gain = sd->ctrls[GAIN].val >> 1; | ||
789 | buf[0] = gain; /* Red */ | ||
790 | buf[1] = gain; /* Green */ | ||
791 | buf[2] = gain; /* Blue */ | ||
792 | reg_w(gspca_dev, 0x05, buf, 3); | ||
793 | } else { | ||
794 | gain = sd->ctrls[GAIN].val >> 4; | ||
795 | buf[0] = gain << 4 | gain; /* Red and blue */ | ||
796 | buf[1] = gain; /* Green */ | ||
797 | reg_w(gspca_dev, 0x10, buf, 2); | ||
798 | } | 676 | } |
799 | } | 677 | } |
800 | 678 | ||
@@ -807,13 +685,7 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
807 | /* Note the datasheet wrongly says line mode exposure uses reg | 685 | /* Note the datasheet wrongly says line mode exposure uses reg |
808 | 0x26 and 0x27, testing has shown 0x25 + 0x26 */ | 686 | 0x26 and 0x27, testing has shown 0x25 + 0x26 */ |
809 | __u8 i2c[] = {0xc0, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x17}; | 687 | __u8 i2c[] = {0xc0, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x17}; |
810 | /* The HV7131D's exposure goes from 0 - 65535, we scale our | 688 | u16 reg = gspca_dev->exposure->val; |
811 | exposure of 0-1023 to 0-6138. There are 2 reasons for this: | ||
812 | 1) This puts our exposure knee of 200 at approx the point | ||
813 | where the framerate starts dropping | ||
814 | 2) At 6138 the framerate has already dropped to 2 fps, | ||
815 | going any lower makes little sense */ | ||
816 | u16 reg = sd->ctrls[EXPOSURE].val * 6; | ||
817 | 689 | ||
818 | i2c[3] = reg >> 8; | 690 | i2c[3] = reg >> 8; |
819 | i2c[4] = reg & 0xff; | 691 | i2c[4] = reg & 0xff; |
@@ -825,7 +697,7 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
825 | /* register 19's high nibble contains the sn9c10x clock divider | 697 | /* register 19's high nibble contains the sn9c10x clock divider |
826 | The high nibble configures the no fps according to the | 698 | The high nibble configures the no fps according to the |
827 | formula: 60 / high_nibble. With a maximum of 30 fps */ | 699 | formula: 60 / high_nibble. With a maximum of 30 fps */ |
828 | u8 reg = sd->ctrls[EXPOSURE].val; | 700 | u8 reg = gspca_dev->exposure->val; |
829 | 701 | ||
830 | reg = (reg << 4) | 0x0b; | 702 | reg = (reg << 4) | 0x0b; |
831 | reg_w(gspca_dev, 0x19, ®, 1); | 703 | reg_w(gspca_dev, 0x19, ®, 1); |
@@ -862,7 +734,7 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
862 | } else | 734 | } else |
863 | reg10_max = 0x41; | 735 | reg10_max = 0x41; |
864 | 736 | ||
865 | reg11 = (15 * sd->ctrls[EXPOSURE].val + 999) / 1000; | 737 | reg11 = (15 * gspca_dev->exposure->val + 999) / 1000; |
866 | if (reg11 < 1) | 738 | if (reg11 < 1) |
867 | reg11 = 1; | 739 | reg11 = 1; |
868 | else if (reg11 > 16) | 740 | else if (reg11 > 16) |
@@ -875,16 +747,16 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
875 | reg11 = 4; | 747 | reg11 = 4; |
876 | 748 | ||
877 | /* frame exposure time in ms = 1000 * reg11 / 30 -> | 749 | /* frame exposure time in ms = 1000 * reg11 / 30 -> |
878 | reg10 = (sd->ctrls[EXPOSURE].val / 2) * reg10_max | 750 | reg10 = (gspca_dev->exposure->val / 2) * reg10_max |
879 | / (1000 * reg11 / 30) */ | 751 | / (1000 * reg11 / 30) */ |
880 | reg10 = (sd->ctrls[EXPOSURE].val * 15 * reg10_max) | 752 | reg10 = (gspca_dev->exposure->val * 15 * reg10_max) |
881 | / (1000 * reg11); | 753 | / (1000 * reg11); |
882 | 754 | ||
883 | /* Don't allow this to get below 10 when using autogain, the | 755 | /* Don't allow this to get below 10 when using autogain, the |
884 | steps become very large (relatively) when below 10 causing | 756 | steps become very large (relatively) when below 10 causing |
885 | the image to oscilate from much too dark, to much too bright | 757 | the image to oscilate from much too dark, to much too bright |
886 | and back again. */ | 758 | and back again. */ |
887 | if (sd->ctrls[AUTOGAIN].val && reg10 < 10) | 759 | if (gspca_dev->autogain->val && reg10 < 10) |
888 | reg10 = 10; | 760 | reg10 = 10; |
889 | else if (reg10 > reg10_max) | 761 | else if (reg10 > reg10_max) |
890 | reg10 = reg10_max; | 762 | reg10 = reg10_max; |
@@ -922,15 +794,15 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
922 | frame exposure times (like we are doing with the ov chips), | 794 | frame exposure times (like we are doing with the ov chips), |
923 | as that sometimes leads to jumps in the exposure control, | 795 | as that sometimes leads to jumps in the exposure control, |
924 | which are bad for auto exposure. */ | 796 | which are bad for auto exposure. */ |
925 | if (sd->ctrls[EXPOSURE].val < 200) { | 797 | if (gspca_dev->exposure->val < 200) { |
926 | i2cpexpo[3] = 255 - (sd->ctrls[EXPOSURE].val * 255) | 798 | i2cpexpo[3] = 255 - (gspca_dev->exposure->val * 255) |
927 | / 200; | 799 | / 200; |
928 | framerate_ctrl = 500; | 800 | framerate_ctrl = 500; |
929 | } else { | 801 | } else { |
930 | /* The PAS202's exposure control goes from 0 - 4095, | 802 | /* The PAS202's exposure control goes from 0 - 4095, |
931 | but anything below 500 causes vsync issues, so scale | 803 | but anything below 500 causes vsync issues, so scale |
932 | our 200-1023 to 500-4095 */ | 804 | our 200-1023 to 500-4095 */ |
933 | framerate_ctrl = (sd->ctrls[EXPOSURE].val - 200) | 805 | framerate_ctrl = (gspca_dev->exposure->val - 200) |
934 | * 1000 / 229 + 500; | 806 | * 1000 / 229 + 500; |
935 | } | 807 | } |
936 | 808 | ||
@@ -952,14 +824,14 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
952 | 824 | ||
953 | /* For values below 150 use partial frame exposure, above | 825 | /* For values below 150 use partial frame exposure, above |
954 | that use framerate ctrl */ | 826 | that use framerate ctrl */ |
955 | if (sd->ctrls[EXPOSURE].val < 150) { | 827 | if (gspca_dev->exposure->val < 150) { |
956 | i2cpexpo[3] = 150 - sd->ctrls[EXPOSURE].val; | 828 | i2cpexpo[3] = 150 - gspca_dev->exposure->val; |
957 | framerate_ctrl = 300; | 829 | framerate_ctrl = 300; |
958 | } else { | 830 | } else { |
959 | /* The PAS106's exposure control goes from 0 - 4095, | 831 | /* The PAS106's exposure control goes from 0 - 4095, |
960 | but anything below 300 causes vsync issues, so scale | 832 | but anything below 300 causes vsync issues, so scale |
961 | our 150-1023 to 300-4095 */ | 833 | our 150-1023 to 300-4095 */ |
962 | framerate_ctrl = (sd->ctrls[EXPOSURE].val - 150) | 834 | framerate_ctrl = (gspca_dev->exposure->val - 150) |
963 | * 1000 / 230 + 300; | 835 | * 1000 / 230 + 300; |
964 | } | 836 | } |
965 | 837 | ||
@@ -985,7 +857,7 @@ static void setfreq(struct gspca_dev *gspca_dev) | |||
985 | 0x2b register, see ov6630 datasheet. | 857 | 0x2b register, see ov6630 datasheet. |
986 | 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */ | 858 | 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */ |
987 | __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}; | 859 | __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}; |
988 | switch (sd->ctrls[FREQ].val) { | 860 | switch (sd->plfreq->val) { |
989 | default: | 861 | default: |
990 | /* case 0: * no filter*/ | 862 | /* case 0: * no filter*/ |
991 | /* case 2: * 60 hz */ | 863 | /* case 2: * 60 hz */ |
@@ -1001,18 +873,13 @@ static void setfreq(struct gspca_dev *gspca_dev) | |||
1001 | } | 873 | } |
1002 | } | 874 | } |
1003 | 875 | ||
1004 | #define WANT_REGULAR_AUTOGAIN | ||
1005 | #define WANT_COARSE_EXPO_AUTOGAIN | ||
1006 | #include "autogain_functions.h" | ||
1007 | |||
1008 | static void do_autogain(struct gspca_dev *gspca_dev) | 876 | static void do_autogain(struct gspca_dev *gspca_dev) |
1009 | { | 877 | { |
1010 | int deadzone, desired_avg_lum, result; | ||
1011 | struct sd *sd = (struct sd *) gspca_dev; | 878 | struct sd *sd = (struct sd *) gspca_dev; |
1012 | int avg_lum = atomic_read(&sd->avg_lum); | 879 | int deadzone, desired_avg_lum, avg_lum; |
1013 | 880 | ||
1014 | if ((gspca_dev->ctrl_dis & (1 << AUTOGAIN)) || | 881 | avg_lum = atomic_read(&sd->avg_lum); |
1015 | avg_lum == -1 || !sd->ctrls[AUTOGAIN].val) | 882 | if (avg_lum == -1) |
1016 | return; | 883 | return; |
1017 | 884 | ||
1018 | if (sd->autogain_ignore_frames > 0) { | 885 | if (sd->autogain_ignore_frames > 0) { |
@@ -1031,22 +898,18 @@ static void do_autogain(struct gspca_dev *gspca_dev) | |||
1031 | desired_avg_lum = 13000; | 898 | desired_avg_lum = 13000; |
1032 | } | 899 | } |
1033 | 900 | ||
1034 | if (sensor_data[sd->sensor].flags & F_COARSE_EXPO) | 901 | if (sd->brightness) |
1035 | result = coarse_grained_expo_autogain(gspca_dev, avg_lum, | 902 | desired_avg_lum = sd->brightness->val * desired_avg_lum / 127; |
1036 | sd->ctrls[BRIGHTNESS].val | 903 | |
1037 | * desired_avg_lum / 127, | 904 | if (gspca_dev->exposure->maximum < 500) { |
1038 | deadzone); | 905 | if (gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum, |
1039 | else | 906 | desired_avg_lum, deadzone)) |
1040 | result = auto_gain_n_exposure(gspca_dev, avg_lum, | 907 | sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES; |
1041 | sd->ctrls[BRIGHTNESS].val | 908 | } else { |
1042 | * desired_avg_lum / 127, | 909 | int gain_knee = gspca_dev->gain->maximum * 9 / 10; |
1043 | deadzone, GAIN_KNEE, EXPOSURE_KNEE); | 910 | if (gspca_expo_autogain(gspca_dev, avg_lum, desired_avg_lum, |
1044 | 911 | deadzone, gain_knee, sd->exposure_knee)) | |
1045 | if (result) { | 912 | sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES; |
1046 | PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d", | ||
1047 | (int) sd->ctrls[GAIN].val, | ||
1048 | (int) sd->ctrls[EXPOSURE].val); | ||
1049 | sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES; | ||
1050 | } | 913 | } |
1051 | } | 914 | } |
1052 | 915 | ||
@@ -1065,14 +928,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1065 | sd->sensor = id->driver_info >> 8; | 928 | sd->sensor = id->driver_info >> 8; |
1066 | sd->bridge = id->driver_info & 0xff; | 929 | sd->bridge = id->driver_info & 0xff; |
1067 | 930 | ||
1068 | gspca_dev->ctrl_dis = sensor_data[sd->sensor].ctrl_dis; | ||
1069 | #if AUTOGAIN_DEF | ||
1070 | if (!(gspca_dev->ctrl_dis & (1 << AUTOGAIN))) | ||
1071 | gspca_dev->ctrl_inac = (1 << GAIN) | (1 << EXPOSURE); | ||
1072 | #endif | ||
1073 | |||
1074 | cam = &gspca_dev->cam; | 931 | cam = &gspca_dev->cam; |
1075 | cam->ctrls = sd->ctrls; | ||
1076 | if (!(sensor_data[sd->sensor].flags & F_SIF)) { | 932 | if (!(sensor_data[sd->sensor].flags & F_SIF)) { |
1077 | cam->cam_mode = vga_mode; | 933 | cam->cam_mode = vga_mode; |
1078 | cam->nmodes = ARRAY_SIZE(vga_mode); | 934 | cam->nmodes = ARRAY_SIZE(vga_mode); |
@@ -1088,22 +944,144 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1088 | /* this function is called at probe and resume time */ | 944 | /* this function is called at probe and resume time */ |
1089 | static int sd_init(struct gspca_dev *gspca_dev) | 945 | static int sd_init(struct gspca_dev *gspca_dev) |
1090 | { | 946 | { |
1091 | struct sd *sd = (struct sd *) gspca_dev; | ||
1092 | const __u8 stop = 0x09; /* Disable stream turn of LED */ | 947 | const __u8 stop = 0x09; /* Disable stream turn of LED */ |
1093 | 948 | ||
1094 | if (sensor_data[sd->sensor].flags & F_COARSE_EXPO) { | 949 | reg_w(gspca_dev, 0x01, &stop, 1); |
1095 | sd->ctrls[EXPOSURE].min = COARSE_EXPOSURE_MIN; | 950 | |
1096 | sd->ctrls[EXPOSURE].max = COARSE_EXPOSURE_MAX; | 951 | return gspca_dev->usb_err; |
1097 | sd->ctrls[EXPOSURE].def = COARSE_EXPOSURE_DEF; | 952 | } |
1098 | if (sd->ctrls[EXPOSURE].val > COARSE_EXPOSURE_MAX) | 953 | |
1099 | sd->ctrls[EXPOSURE].val = COARSE_EXPOSURE_DEF; | 954 | static int sd_s_ctrl(struct v4l2_ctrl *ctrl) |
955 | { | ||
956 | struct gspca_dev *gspca_dev = | ||
957 | container_of(ctrl->handler, struct gspca_dev, ctrl_handler); | ||
958 | struct sd *sd = (struct sd *)gspca_dev; | ||
959 | |||
960 | gspca_dev->usb_err = 0; | ||
961 | |||
962 | if (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) { | ||
963 | /* when switching to autogain set defaults to make sure | ||
964 | we are on a valid point of the autogain gain / | ||
965 | exposure knee graph, and give this change time to | ||
966 | take effect before doing autogain. */ | ||
967 | gspca_dev->gain->val = gspca_dev->gain->default_value; | ||
968 | gspca_dev->exposure->val = gspca_dev->exposure->default_value; | ||
969 | sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES; | ||
1100 | } | 970 | } |
1101 | 971 | ||
1102 | reg_w(gspca_dev, 0x01, &stop, 1); | 972 | if (!gspca_dev->streaming) |
973 | return 0; | ||
1103 | 974 | ||
975 | switch (ctrl->id) { | ||
976 | case V4L2_CID_BRIGHTNESS: | ||
977 | setbrightness(gspca_dev); | ||
978 | break; | ||
979 | case V4L2_CID_AUTOGAIN: | ||
980 | if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val)) | ||
981 | setexposure(gspca_dev); | ||
982 | if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val)) | ||
983 | setgain(gspca_dev); | ||
984 | break; | ||
985 | case V4L2_CID_POWER_LINE_FREQUENCY: | ||
986 | setfreq(gspca_dev); | ||
987 | break; | ||
988 | default: | ||
989 | return -EINVAL; | ||
990 | } | ||
1104 | return gspca_dev->usb_err; | 991 | return gspca_dev->usb_err; |
1105 | } | 992 | } |
1106 | 993 | ||
994 | static const struct v4l2_ctrl_ops sd_ctrl_ops = { | ||
995 | .s_ctrl = sd_s_ctrl, | ||
996 | }; | ||
997 | |||
998 | /* this function is called at probe time */ | ||
999 | static int sd_init_controls(struct gspca_dev *gspca_dev) | ||
1000 | { | ||
1001 | struct sd *sd = (struct sd *) gspca_dev; | ||
1002 | struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; | ||
1003 | |||
1004 | gspca_dev->vdev.ctrl_handler = hdl; | ||
1005 | v4l2_ctrl_handler_init(hdl, 5); | ||
1006 | |||
1007 | if (sd->sensor == SENSOR_OV6650 || sd->sensor == SENSOR_OV7630 || | ||
1008 | sd->sensor == SENSOR_PAS106 || sd->sensor == SENSOR_PAS202) | ||
1009 | sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
1010 | V4L2_CID_BRIGHTNESS, 0, 255, 1, 127); | ||
1011 | |||
1012 | /* Gain range is sensor dependent */ | ||
1013 | switch (sd->sensor) { | ||
1014 | case SENSOR_OV6650: | ||
1015 | case SENSOR_PAS106: | ||
1016 | case SENSOR_PAS202: | ||
1017 | gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
1018 | V4L2_CID_GAIN, 0, 31, 1, 15); | ||
1019 | break; | ||
1020 | case SENSOR_HV7131D: | ||
1021 | case SENSOR_OV7630: | ||
1022 | gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
1023 | V4L2_CID_GAIN, 0, 63, 1, 31); | ||
1024 | break; | ||
1025 | case SENSOR_TAS5110C: | ||
1026 | case SENSOR_TAS5110D: | ||
1027 | case SENSOR_TAS5130CXX: | ||
1028 | gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
1029 | V4L2_CID_GAIN, 0, 255, 1, 127); | ||
1030 | break; | ||
1031 | default: | ||
1032 | if (sd->bridge == BRIDGE_103) { | ||
1033 | gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
1034 | V4L2_CID_GAIN, 0, 127, 1, 63); | ||
1035 | } else { | ||
1036 | gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
1037 | V4L2_CID_GAIN, 0, 15, 1, 7); | ||
1038 | } | ||
1039 | } | ||
1040 | |||
1041 | /* Exposure range is sensor dependent, and not all have exposure */ | ||
1042 | switch (sd->sensor) { | ||
1043 | case SENSOR_HV7131D: | ||
1044 | gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
1045 | V4L2_CID_EXPOSURE, 0, 8191, 1, 482); | ||
1046 | sd->exposure_knee = 964; | ||
1047 | break; | ||
1048 | case SENSOR_OV6650: | ||
1049 | case SENSOR_OV7630: | ||
1050 | case SENSOR_PAS106: | ||
1051 | case SENSOR_PAS202: | ||
1052 | gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
1053 | V4L2_CID_EXPOSURE, 0, 1023, 1, 66); | ||
1054 | sd->exposure_knee = 200; | ||
1055 | break; | ||
1056 | case SENSOR_TAS5110C: | ||
1057 | case SENSOR_TAS5110D: | ||
1058 | gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
1059 | V4L2_CID_EXPOSURE, 2, 15, 1, 2); | ||
1060 | break; | ||
1061 | } | ||
1062 | |||
1063 | if (gspca_dev->exposure) { | ||
1064 | gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
1065 | V4L2_CID_AUTOGAIN, 0, 1, 1, 1); | ||
1066 | } | ||
1067 | |||
1068 | if (sd->sensor == SENSOR_OV6650 || sd->sensor == SENSOR_OV7630) | ||
1069 | sd->plfreq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops, | ||
1070 | V4L2_CID_POWER_LINE_FREQUENCY, | ||
1071 | V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, | ||
1072 | V4L2_CID_POWER_LINE_FREQUENCY_DISABLED); | ||
1073 | |||
1074 | if (hdl->error) { | ||
1075 | pr_err("Could not initialize controls\n"); | ||
1076 | return hdl->error; | ||
1077 | } | ||
1078 | |||
1079 | if (gspca_dev->autogain) | ||
1080 | v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false); | ||
1081 | |||
1082 | return 0; | ||
1083 | } | ||
1084 | |||
1107 | /* -- start the camera -- */ | 1085 | /* -- start the camera -- */ |
1108 | static int sd_start(struct gspca_dev *gspca_dev) | 1086 | static int sd_start(struct gspca_dev *gspca_dev) |
1109 | { | 1087 | { |
@@ -1243,8 +1221,8 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1243 | 1221 | ||
1244 | sd->frames_to_drop = 0; | 1222 | sd->frames_to_drop = 0; |
1245 | sd->autogain_ignore_frames = 0; | 1223 | sd->autogain_ignore_frames = 0; |
1246 | sd->exp_too_high_cnt = 0; | 1224 | gspca_dev->exp_too_high_cnt = 0; |
1247 | sd->exp_too_low_cnt = 0; | 1225 | gspca_dev->exp_too_low_cnt = 0; |
1248 | atomic_set(&sd->avg_lum, -1); | 1226 | atomic_set(&sd->avg_lum, -1); |
1249 | return gspca_dev->usb_err; | 1227 | return gspca_dev->usb_err; |
1250 | } | 1228 | } |
@@ -1388,37 +1366,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
1388 | } | 1366 | } |
1389 | } | 1367 | } |
1390 | 1368 | ||
1391 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | ||
1392 | { | ||
1393 | struct sd *sd = (struct sd *) gspca_dev; | ||
1394 | |||
1395 | sd->ctrls[AUTOGAIN].val = val; | ||
1396 | sd->exp_too_high_cnt = 0; | ||
1397 | sd->exp_too_low_cnt = 0; | ||
1398 | |||
1399 | /* when switching to autogain set defaults to make sure | ||
1400 | we are on a valid point of the autogain gain / | ||
1401 | exposure knee graph, and give this change time to | ||
1402 | take effect before doing autogain. */ | ||
1403 | if (sd->ctrls[AUTOGAIN].val | ||
1404 | && !(sensor_data[sd->sensor].flags & F_COARSE_EXPO)) { | ||
1405 | sd->ctrls[EXPOSURE].val = sd->ctrls[EXPOSURE].def; | ||
1406 | sd->ctrls[GAIN].val = sd->ctrls[GAIN].def; | ||
1407 | if (gspca_dev->streaming) { | ||
1408 | sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES; | ||
1409 | setexposure(gspca_dev); | ||
1410 | setgain(gspca_dev); | ||
1411 | } | ||
1412 | } | ||
1413 | |||
1414 | if (sd->ctrls[AUTOGAIN].val) | ||
1415 | gspca_dev->ctrl_inac = (1 << GAIN) | (1 << EXPOSURE); | ||
1416 | else | ||
1417 | gspca_dev->ctrl_inac = 0; | ||
1418 | |||
1419 | return 0; | ||
1420 | } | ||
1421 | |||
1422 | static int sd_querymenu(struct gspca_dev *gspca_dev, | 1369 | static int sd_querymenu(struct gspca_dev *gspca_dev, |
1423 | struct v4l2_querymenu *menu) | 1370 | struct v4l2_querymenu *menu) |
1424 | { | 1371 | { |
@@ -1462,10 +1409,9 @@ static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, | |||
1462 | /* sub-driver description */ | 1409 | /* sub-driver description */ |
1463 | static const struct sd_desc sd_desc = { | 1410 | static const struct sd_desc sd_desc = { |
1464 | .name = MODULE_NAME, | 1411 | .name = MODULE_NAME, |
1465 | .ctrls = sd_ctrls, | ||
1466 | .nctrls = ARRAY_SIZE(sd_ctrls), | ||
1467 | .config = sd_config, | 1412 | .config = sd_config, |
1468 | .init = sd_init, | 1413 | .init = sd_init, |
1414 | .init_controls = sd_init_controls, | ||
1469 | .start = sd_start, | 1415 | .start = sd_start, |
1470 | .stopN = sd_stopN, | 1416 | .stopN = sd_stopN, |
1471 | .pkt_scan = sd_pkt_scan, | 1417 | .pkt_scan = sd_pkt_scan, |