diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2012-05-14 08:45:06 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-07-30 17:23:18 -0400 |
commit | 3e0ed00903e1904112108135c18b1918386457aa (patch) | |
tree | 8582dfd80f67308bd03eab808bb1d606ec8a3c0b /drivers/media/video/gspca | |
parent | 1bdee422cd9edea43a86f37a4ceb0081de6bd0bc (diff) |
[media] gspca-mr97310a: convert to the control framework
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
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/mr97310a.c | 438 |
1 files changed, 133 insertions, 305 deletions
diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index d73e5bd3dbf7..3ede41b67468 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c | |||
@@ -67,6 +67,7 @@ | |||
67 | #define MR97310A_CS_GAIN_MAX 0x7ff | 67 | #define MR97310A_CS_GAIN_MAX 0x7ff |
68 | #define MR97310A_CS_GAIN_DEFAULT 0x110 | 68 | #define MR97310A_CS_GAIN_DEFAULT 0x110 |
69 | 69 | ||
70 | #define MR97310A_CID_CLOCKDIV (V4L2_CTRL_CLASS_USER + 0x1000) | ||
70 | #define MR97310A_MIN_CLOCKDIV_MIN 3 | 71 | #define MR97310A_MIN_CLOCKDIV_MIN 3 |
71 | #define MR97310A_MIN_CLOCKDIV_MAX 8 | 72 | #define MR97310A_MIN_CLOCKDIV_MAX 8 |
72 | #define MR97310A_MIN_CLOCKDIV_DEFAULT 3 | 73 | #define MR97310A_MIN_CLOCKDIV_DEFAULT 3 |
@@ -84,17 +85,15 @@ MODULE_PARM_DESC(force_sensor_type, "Force sensor type (-1 (auto), 0 or 1)"); | |||
84 | /* specific webcam descriptor */ | 85 | /* specific webcam descriptor */ |
85 | struct sd { | 86 | struct sd { |
86 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 87 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
88 | struct { /* exposure/min_clockdiv control cluster */ | ||
89 | struct v4l2_ctrl *exposure; | ||
90 | struct v4l2_ctrl *min_clockdiv; | ||
91 | }; | ||
87 | u8 sof_read; | 92 | u8 sof_read; |
88 | u8 cam_type; /* 0 is CIF and 1 is VGA */ | 93 | u8 cam_type; /* 0 is CIF and 1 is VGA */ |
89 | u8 sensor_type; /* We use 0 and 1 here, too. */ | 94 | u8 sensor_type; /* We use 0 and 1 here, too. */ |
90 | u8 do_lcd_stop; | 95 | u8 do_lcd_stop; |
91 | u8 adj_colors; | 96 | u8 adj_colors; |
92 | |||
93 | int brightness; | ||
94 | u16 exposure; | ||
95 | u32 gain; | ||
96 | u8 contrast; | ||
97 | u8 min_clockdiv; | ||
98 | }; | 97 | }; |
99 | 98 | ||
100 | struct sensor_w_data { | 99 | struct sensor_w_data { |
@@ -105,132 +104,6 @@ struct sensor_w_data { | |||
105 | }; | 104 | }; |
106 | 105 | ||
107 | static void sd_stopN(struct gspca_dev *gspca_dev); | 106 | static void sd_stopN(struct gspca_dev *gspca_dev); |
108 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
109 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
110 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | ||
111 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
112 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
113 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
114 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); | ||
115 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | ||
116 | static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val); | ||
117 | static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val); | ||
118 | static void setbrightness(struct gspca_dev *gspca_dev); | ||
119 | static void setexposure(struct gspca_dev *gspca_dev); | ||
120 | static void setgain(struct gspca_dev *gspca_dev); | ||
121 | static void setcontrast(struct gspca_dev *gspca_dev); | ||
122 | |||
123 | /* V4L2 controls supported by the driver */ | ||
124 | static const struct ctrl sd_ctrls[] = { | ||
125 | /* Separate brightness control description for Argus QuickClix as it has | ||
126 | * different limits from the other mr97310a cameras, and separate gain | ||
127 | * control for Sakar CyberPix camera. */ | ||
128 | { | ||
129 | #define NORM_BRIGHTNESS_IDX 0 | ||
130 | { | ||
131 | .id = V4L2_CID_BRIGHTNESS, | ||
132 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
133 | .name = "Brightness", | ||
134 | .minimum = -254, | ||
135 | .maximum = 255, | ||
136 | .step = 1, | ||
137 | .default_value = MR97310A_BRIGHTNESS_DEFAULT, | ||
138 | .flags = 0, | ||
139 | }, | ||
140 | .set = sd_setbrightness, | ||
141 | .get = sd_getbrightness, | ||
142 | }, | ||
143 | { | ||
144 | #define ARGUS_QC_BRIGHTNESS_IDX 1 | ||
145 | { | ||
146 | .id = V4L2_CID_BRIGHTNESS, | ||
147 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
148 | .name = "Brightness", | ||
149 | .minimum = 0, | ||
150 | .maximum = 15, | ||
151 | .step = 1, | ||
152 | .default_value = MR97310A_BRIGHTNESS_DEFAULT, | ||
153 | .flags = 0, | ||
154 | }, | ||
155 | .set = sd_setbrightness, | ||
156 | .get = sd_getbrightness, | ||
157 | }, | ||
158 | { | ||
159 | #define EXPOSURE_IDX 2 | ||
160 | { | ||
161 | .id = V4L2_CID_EXPOSURE, | ||
162 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
163 | .name = "Exposure", | ||
164 | .minimum = MR97310A_EXPOSURE_MIN, | ||
165 | .maximum = MR97310A_EXPOSURE_MAX, | ||
166 | .step = 1, | ||
167 | .default_value = MR97310A_EXPOSURE_DEFAULT, | ||
168 | .flags = 0, | ||
169 | }, | ||
170 | .set = sd_setexposure, | ||
171 | .get = sd_getexposure, | ||
172 | }, | ||
173 | { | ||
174 | #define GAIN_IDX 3 | ||
175 | { | ||
176 | .id = V4L2_CID_GAIN, | ||
177 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
178 | .name = "Gain", | ||
179 | .minimum = MR97310A_GAIN_MIN, | ||
180 | .maximum = MR97310A_GAIN_MAX, | ||
181 | .step = 1, | ||
182 | .default_value = MR97310A_GAIN_DEFAULT, | ||
183 | .flags = 0, | ||
184 | }, | ||
185 | .set = sd_setgain, | ||
186 | .get = sd_getgain, | ||
187 | }, | ||
188 | { | ||
189 | #define SAKAR_CS_GAIN_IDX 4 | ||
190 | { | ||
191 | .id = V4L2_CID_GAIN, | ||
192 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
193 | .name = "Gain", | ||
194 | .minimum = MR97310A_CS_GAIN_MIN, | ||
195 | .maximum = MR97310A_CS_GAIN_MAX, | ||
196 | .step = 1, | ||
197 | .default_value = MR97310A_CS_GAIN_DEFAULT, | ||
198 | .flags = 0, | ||
199 | }, | ||
200 | .set = sd_setgain, | ||
201 | .get = sd_getgain, | ||
202 | }, | ||
203 | { | ||
204 | #define CONTRAST_IDX 5 | ||
205 | { | ||
206 | .id = V4L2_CID_CONTRAST, | ||
207 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
208 | .name = "Contrast", | ||
209 | .minimum = MR97310A_CONTRAST_MIN, | ||
210 | .maximum = MR97310A_CONTRAST_MAX, | ||
211 | .step = 1, | ||
212 | .default_value = MR97310A_CONTRAST_DEFAULT, | ||
213 | .flags = 0, | ||
214 | }, | ||
215 | .set = sd_setcontrast, | ||
216 | .get = sd_getcontrast, | ||
217 | }, | ||
218 | { | ||
219 | #define MIN_CLOCKDIV_IDX 6 | ||
220 | { | ||
221 | .id = V4L2_CID_PRIVATE_BASE, | ||
222 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
223 | .name = "Minimum Clock Divider", | ||
224 | .minimum = MR97310A_MIN_CLOCKDIV_MIN, | ||
225 | .maximum = MR97310A_MIN_CLOCKDIV_MAX, | ||
226 | .step = 1, | ||
227 | .default_value = MR97310A_MIN_CLOCKDIV_DEFAULT, | ||
228 | .flags = 0, | ||
229 | }, | ||
230 | .set = sd_setmin_clockdiv, | ||
231 | .get = sd_getmin_clockdiv, | ||
232 | }, | ||
233 | }; | ||
234 | 107 | ||
235 | static const struct v4l2_pix_format vga_mode[] = { | 108 | static const struct v4l2_pix_format vga_mode[] = { |
236 | {160, 120, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE, | 109 | {160, 120, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE, |
@@ -481,7 +354,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
481 | { | 354 | { |
482 | struct sd *sd = (struct sd *) gspca_dev; | 355 | struct sd *sd = (struct sd *) gspca_dev; |
483 | struct cam *cam; | 356 | struct cam *cam; |
484 | int gain_default = MR97310A_GAIN_DEFAULT; | ||
485 | int err_code; | 357 | int err_code; |
486 | 358 | ||
487 | cam = &gspca_dev->cam; | 359 | cam = &gspca_dev->cam; |
@@ -615,52 +487,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
615 | sd->sensor_type); | 487 | sd->sensor_type); |
616 | } | 488 | } |
617 | 489 | ||
618 | /* Setup controls depending on camera type */ | ||
619 | if (sd->cam_type == CAM_TYPE_CIF) { | ||
620 | /* No brightness for sensor_type 0 */ | ||
621 | if (sd->sensor_type == 0) | ||
622 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | | ||
623 | (1 << ARGUS_QC_BRIGHTNESS_IDX) | | ||
624 | (1 << CONTRAST_IDX) | | ||
625 | (1 << SAKAR_CS_GAIN_IDX); | ||
626 | else | ||
627 | gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) | | ||
628 | (1 << CONTRAST_IDX) | | ||
629 | (1 << SAKAR_CS_GAIN_IDX) | | ||
630 | (1 << MIN_CLOCKDIV_IDX); | ||
631 | } else { | ||
632 | /* All controls need to be disabled if VGA sensor_type is 0 */ | ||
633 | if (sd->sensor_type == 0) | ||
634 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | | ||
635 | (1 << ARGUS_QC_BRIGHTNESS_IDX) | | ||
636 | (1 << EXPOSURE_IDX) | | ||
637 | (1 << GAIN_IDX) | | ||
638 | (1 << CONTRAST_IDX) | | ||
639 | (1 << SAKAR_CS_GAIN_IDX) | | ||
640 | (1 << MIN_CLOCKDIV_IDX); | ||
641 | else if (sd->sensor_type == 2) { | ||
642 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | | ||
643 | (1 << ARGUS_QC_BRIGHTNESS_IDX) | | ||
644 | (1 << GAIN_IDX) | | ||
645 | (1 << MIN_CLOCKDIV_IDX); | ||
646 | gain_default = MR97310A_CS_GAIN_DEFAULT; | ||
647 | } else if (sd->do_lcd_stop) | ||
648 | /* Argus QuickClix has different brightness limits */ | ||
649 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | | ||
650 | (1 << CONTRAST_IDX) | | ||
651 | (1 << SAKAR_CS_GAIN_IDX); | ||
652 | else | ||
653 | gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) | | ||
654 | (1 << CONTRAST_IDX) | | ||
655 | (1 << SAKAR_CS_GAIN_IDX); | ||
656 | } | ||
657 | |||
658 | sd->brightness = MR97310A_BRIGHTNESS_DEFAULT; | ||
659 | sd->exposure = MR97310A_EXPOSURE_DEFAULT; | ||
660 | sd->gain = gain_default; | ||
661 | sd->contrast = MR97310A_CONTRAST_DEFAULT; | ||
662 | sd->min_clockdiv = MR97310A_MIN_CLOCKDIV_DEFAULT; | ||
663 | |||
664 | return 0; | 490 | return 0; |
665 | } | 491 | } |
666 | 492 | ||
@@ -952,11 +778,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
952 | if (err_code < 0) | 778 | if (err_code < 0) |
953 | return err_code; | 779 | return err_code; |
954 | 780 | ||
955 | setbrightness(gspca_dev); | ||
956 | setcontrast(gspca_dev); | ||
957 | setexposure(gspca_dev); | ||
958 | setgain(gspca_dev); | ||
959 | |||
960 | return isoc_enable(gspca_dev); | 781 | return isoc_enable(gspca_dev); |
961 | } | 782 | } |
962 | 783 | ||
@@ -971,37 +792,25 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
971 | lcd_stop(gspca_dev); | 792 | lcd_stop(gspca_dev); |
972 | } | 793 | } |
973 | 794 | ||
974 | static void setbrightness(struct gspca_dev *gspca_dev) | 795 | static void setbrightness(struct gspca_dev *gspca_dev, s32 val) |
975 | { | 796 | { |
976 | struct sd *sd = (struct sd *) gspca_dev; | 797 | struct sd *sd = (struct sd *) gspca_dev; |
977 | u8 val; | ||
978 | u8 sign_reg = 7; /* This reg and the next one used on CIF cams. */ | 798 | u8 sign_reg = 7; /* This reg and the next one used on CIF cams. */ |
979 | u8 value_reg = 8; /* VGA cams seem to use regs 0x0b and 0x0c */ | 799 | u8 value_reg = 8; /* VGA cams seem to use regs 0x0b and 0x0c */ |
980 | static const u8 quick_clix_table[] = | 800 | static const u8 quick_clix_table[] = |
981 | /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */ | 801 | /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */ |
982 | { 0, 4, 8, 12, 1, 2, 3, 5, 6, 9, 7, 10, 13, 11, 14, 15}; | 802 | { 0, 4, 8, 12, 1, 2, 3, 5, 6, 9, 7, 10, 13, 11, 14, 15}; |
983 | /* | ||
984 | * This control is disabled for CIF type 1 and VGA type 0 cameras. | ||
985 | * It does not quite act linearly for the Argus QuickClix camera, | ||
986 | * but it does control brightness. The values are 0 - 15 only, and | ||
987 | * the table above makes them act consecutively. | ||
988 | */ | ||
989 | if ((gspca_dev->ctrl_dis & (1 << NORM_BRIGHTNESS_IDX)) && | ||
990 | (gspca_dev->ctrl_dis & (1 << ARGUS_QC_BRIGHTNESS_IDX))) | ||
991 | return; | ||
992 | |||
993 | if (sd->cam_type == CAM_TYPE_VGA) { | 803 | if (sd->cam_type == CAM_TYPE_VGA) { |
994 | sign_reg += 4; | 804 | sign_reg += 4; |
995 | value_reg += 4; | 805 | value_reg += 4; |
996 | } | 806 | } |
997 | 807 | ||
998 | /* Note register 7 is also seen as 0x8x or 0xCx in some dumps */ | 808 | /* Note register 7 is also seen as 0x8x or 0xCx in some dumps */ |
999 | if (sd->brightness > 0) { | 809 | if (val > 0) { |
1000 | sensor_write1(gspca_dev, sign_reg, 0x00); | 810 | sensor_write1(gspca_dev, sign_reg, 0x00); |
1001 | val = sd->brightness; | ||
1002 | } else { | 811 | } else { |
1003 | sensor_write1(gspca_dev, sign_reg, 0x01); | 812 | sensor_write1(gspca_dev, sign_reg, 0x01); |
1004 | val = (257 - sd->brightness); | 813 | val = 257 - val; |
1005 | } | 814 | } |
1006 | /* Use lookup table for funky Argus QuickClix brightness */ | 815 | /* Use lookup table for funky Argus QuickClix brightness */ |
1007 | if (sd->do_lcd_stop) | 816 | if (sd->do_lcd_stop) |
@@ -1010,23 +819,20 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
1010 | sensor_write1(gspca_dev, value_reg, val); | 819 | sensor_write1(gspca_dev, value_reg, val); |
1011 | } | 820 | } |
1012 | 821 | ||
1013 | static void setexposure(struct gspca_dev *gspca_dev) | 822 | static void setexposure(struct gspca_dev *gspca_dev, s32 expo, s32 min_clockdiv) |
1014 | { | 823 | { |
1015 | struct sd *sd = (struct sd *) gspca_dev; | 824 | struct sd *sd = (struct sd *) gspca_dev; |
1016 | int exposure = MR97310A_EXPOSURE_DEFAULT; | 825 | int exposure = MR97310A_EXPOSURE_DEFAULT; |
1017 | u8 buf[2]; | 826 | u8 buf[2]; |
1018 | 827 | ||
1019 | if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX)) | ||
1020 | return; | ||
1021 | |||
1022 | if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) { | 828 | if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) { |
1023 | /* This cam does not like exposure settings < 300, | 829 | /* This cam does not like exposure settings < 300, |
1024 | so scale 0 - 4095 to 300 - 4095 */ | 830 | so scale 0 - 4095 to 300 - 4095 */ |
1025 | exposure = (sd->exposure * 9267) / 10000 + 300; | 831 | exposure = (expo * 9267) / 10000 + 300; |
1026 | sensor_write1(gspca_dev, 3, exposure >> 4); | 832 | sensor_write1(gspca_dev, 3, exposure >> 4); |
1027 | sensor_write1(gspca_dev, 4, exposure & 0x0f); | 833 | sensor_write1(gspca_dev, 4, exposure & 0x0f); |
1028 | } else if (sd->sensor_type == 2) { | 834 | } else if (sd->sensor_type == 2) { |
1029 | exposure = sd->exposure; | 835 | exposure = expo; |
1030 | exposure >>= 3; | 836 | exposure >>= 3; |
1031 | sensor_write1(gspca_dev, 3, exposure >> 8); | 837 | sensor_write1(gspca_dev, 3, exposure >> 8); |
1032 | sensor_write1(gspca_dev, 4, exposure & 0xff); | 838 | sensor_write1(gspca_dev, 4, exposure & 0xff); |
@@ -1038,11 +844,11 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
1038 | 844 | ||
1039 | Note our 0 - 4095 exposure is mapped to 0 - 511 | 845 | Note our 0 - 4095 exposure is mapped to 0 - 511 |
1040 | milliseconds exposure time */ | 846 | milliseconds exposure time */ |
1041 | u8 clockdiv = (60 * sd->exposure + 7999) / 8000; | 847 | u8 clockdiv = (60 * expo + 7999) / 8000; |
1042 | 848 | ||
1043 | /* Limit framerate to not exceed usb bandwidth */ | 849 | /* Limit framerate to not exceed usb bandwidth */ |
1044 | if (clockdiv < sd->min_clockdiv && gspca_dev->width >= 320) | 850 | if (clockdiv < min_clockdiv && gspca_dev->width >= 320) |
1045 | clockdiv = sd->min_clockdiv; | 851 | clockdiv = min_clockdiv; |
1046 | else if (clockdiv < 2) | 852 | else if (clockdiv < 2) |
1047 | clockdiv = 2; | 853 | clockdiv = 2; |
1048 | 854 | ||
@@ -1051,7 +857,7 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
1051 | 857 | ||
1052 | /* Frame exposure time in ms = 1000 * clockdiv / 60 -> | 858 | /* Frame exposure time in ms = 1000 * clockdiv / 60 -> |
1053 | exposure = (sd->exposure / 8) * 511 / (1000 * clockdiv / 60) */ | 859 | exposure = (sd->exposure / 8) * 511 / (1000 * clockdiv / 60) */ |
1054 | exposure = (60 * 511 * sd->exposure) / (8000 * clockdiv); | 860 | exposure = (60 * 511 * expo) / (8000 * clockdiv); |
1055 | if (exposure > 511) | 861 | if (exposure > 511) |
1056 | exposure = 511; | 862 | exposure = 511; |
1057 | 863 | ||
@@ -1065,125 +871,148 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
1065 | } | 871 | } |
1066 | } | 872 | } |
1067 | 873 | ||
1068 | static void setgain(struct gspca_dev *gspca_dev) | 874 | static void setgain(struct gspca_dev *gspca_dev, s32 val) |
1069 | { | 875 | { |
1070 | struct sd *sd = (struct sd *) gspca_dev; | 876 | struct sd *sd = (struct sd *) gspca_dev; |
1071 | u8 gainreg; | 877 | u8 gainreg; |
1072 | 878 | ||
1073 | if ((gspca_dev->ctrl_dis & (1 << GAIN_IDX)) && | ||
1074 | (gspca_dev->ctrl_dis & (1 << SAKAR_CS_GAIN_IDX))) | ||
1075 | return; | ||
1076 | |||
1077 | if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) | 879 | if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) |
1078 | sensor_write1(gspca_dev, 0x0e, sd->gain); | 880 | sensor_write1(gspca_dev, 0x0e, val); |
1079 | else if (sd->cam_type == CAM_TYPE_VGA && sd->sensor_type == 2) | 881 | else if (sd->cam_type == CAM_TYPE_VGA && sd->sensor_type == 2) |
1080 | for (gainreg = 0x0a; gainreg < 0x11; gainreg += 2) { | 882 | for (gainreg = 0x0a; gainreg < 0x11; gainreg += 2) { |
1081 | sensor_write1(gspca_dev, gainreg, sd->gain >> 8); | 883 | sensor_write1(gspca_dev, gainreg, val >> 8); |
1082 | sensor_write1(gspca_dev, gainreg + 1, sd->gain & 0xff); | 884 | sensor_write1(gspca_dev, gainreg + 1, val & 0xff); |
1083 | } | 885 | } |
1084 | else | 886 | else |
1085 | sensor_write1(gspca_dev, 0x10, sd->gain); | 887 | sensor_write1(gspca_dev, 0x10, val); |
1086 | } | ||
1087 | |||
1088 | static void setcontrast(struct gspca_dev *gspca_dev) | ||
1089 | { | ||
1090 | struct sd *sd = (struct sd *) gspca_dev; | ||
1091 | |||
1092 | if (gspca_dev->ctrl_dis & (1 << CONTRAST_IDX)) | ||
1093 | return; | ||
1094 | |||
1095 | sensor_write1(gspca_dev, 0x1c, sd->contrast); | ||
1096 | } | ||
1097 | |||
1098 | |||
1099 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | ||
1100 | { | ||
1101 | struct sd *sd = (struct sd *) gspca_dev; | ||
1102 | |||
1103 | sd->brightness = val; | ||
1104 | if (gspca_dev->streaming) | ||
1105 | setbrightness(gspca_dev); | ||
1106 | return 0; | ||
1107 | } | ||
1108 | |||
1109 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
1110 | { | ||
1111 | struct sd *sd = (struct sd *) gspca_dev; | ||
1112 | |||
1113 | *val = sd->brightness; | ||
1114 | return 0; | ||
1115 | } | ||
1116 | |||
1117 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) | ||
1118 | { | ||
1119 | struct sd *sd = (struct sd *) gspca_dev; | ||
1120 | |||
1121 | sd->exposure = val; | ||
1122 | if (gspca_dev->streaming) | ||
1123 | setexposure(gspca_dev); | ||
1124 | return 0; | ||
1125 | } | 888 | } |
1126 | 889 | ||
1127 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) | 890 | static void setcontrast(struct gspca_dev *gspca_dev, s32 val) |
1128 | { | 891 | { |
1129 | struct sd *sd = (struct sd *) gspca_dev; | 892 | sensor_write1(gspca_dev, 0x1c, val); |
1130 | |||
1131 | *val = sd->exposure; | ||
1132 | return 0; | ||
1133 | } | 893 | } |
1134 | 894 | ||
1135 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) | 895 | static int sd_s_ctrl(struct v4l2_ctrl *ctrl) |
1136 | { | 896 | { |
1137 | struct sd *sd = (struct sd *) gspca_dev; | 897 | struct gspca_dev *gspca_dev = |
898 | container_of(ctrl->handler, struct gspca_dev, ctrl_handler); | ||
899 | struct sd *sd = (struct sd *)gspca_dev; | ||
1138 | 900 | ||
1139 | sd->gain = val; | 901 | gspca_dev->usb_err = 0; |
1140 | if (gspca_dev->streaming) | ||
1141 | setgain(gspca_dev); | ||
1142 | return 0; | ||
1143 | } | ||
1144 | 902 | ||
1145 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) | 903 | if (!gspca_dev->streaming) |
1146 | { | 904 | return 0; |
1147 | struct sd *sd = (struct sd *) gspca_dev; | ||
1148 | |||
1149 | *val = sd->gain; | ||
1150 | return 0; | ||
1151 | } | ||
1152 | 905 | ||
1153 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | 906 | switch (ctrl->id) { |
1154 | { | 907 | case V4L2_CID_BRIGHTNESS: |
1155 | struct sd *sd = (struct sd *) gspca_dev; | 908 | setbrightness(gspca_dev, ctrl->val); |
1156 | 909 | break; | |
1157 | sd->contrast = val; | 910 | case V4L2_CID_CONTRAST: |
1158 | if (gspca_dev->streaming) | 911 | setcontrast(gspca_dev, ctrl->val); |
1159 | setcontrast(gspca_dev); | 912 | break; |
1160 | return 0; | 913 | case V4L2_CID_EXPOSURE: |
914 | setexposure(gspca_dev, sd->exposure->val, | ||
915 | sd->min_clockdiv ? sd->min_clockdiv->val : 0); | ||
916 | break; | ||
917 | case V4L2_CID_GAIN: | ||
918 | setgain(gspca_dev, ctrl->val); | ||
919 | break; | ||
920 | } | ||
921 | return gspca_dev->usb_err; | ||
1161 | } | 922 | } |
1162 | 923 | ||
924 | static const struct v4l2_ctrl_ops sd_ctrl_ops = { | ||
925 | .s_ctrl = sd_s_ctrl, | ||
926 | }; | ||
1163 | 927 | ||
1164 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | 928 | static int sd_init_controls(struct gspca_dev *gspca_dev) |
1165 | { | ||
1166 | struct sd *sd = (struct sd *) gspca_dev; | ||
1167 | |||
1168 | *val = sd->contrast; | ||
1169 | return 0; | ||
1170 | } | ||
1171 | |||
1172 | static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val) | ||
1173 | { | 929 | { |
1174 | struct sd *sd = (struct sd *) gspca_dev; | 930 | struct sd *sd = (struct sd *)gspca_dev; |
931 | struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; | ||
932 | static const struct v4l2_ctrl_config clockdiv = { | ||
933 | .ops = &sd_ctrl_ops, | ||
934 | .id = MR97310A_CID_CLOCKDIV, | ||
935 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
936 | .name = "Minimum Clock Divider", | ||
937 | .min = MR97310A_MIN_CLOCKDIV_MIN, | ||
938 | .max = MR97310A_MIN_CLOCKDIV_MAX, | ||
939 | .step = 1, | ||
940 | .def = MR97310A_MIN_CLOCKDIV_DEFAULT, | ||
941 | }; | ||
942 | bool has_brightness = false; | ||
943 | bool has_argus_brightness = false; | ||
944 | bool has_contrast = false; | ||
945 | bool has_gain = false; | ||
946 | bool has_cs_gain = false; | ||
947 | bool has_exposure = false; | ||
948 | bool has_clockdiv = false; | ||
1175 | 949 | ||
1176 | sd->min_clockdiv = val; | 950 | gspca_dev->vdev.ctrl_handler = hdl; |
1177 | if (gspca_dev->streaming) | 951 | v4l2_ctrl_handler_init(hdl, 4); |
1178 | setexposure(gspca_dev); | ||
1179 | return 0; | ||
1180 | } | ||
1181 | 952 | ||
1182 | static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val) | 953 | /* Setup controls depending on camera type */ |
1183 | { | 954 | if (sd->cam_type == CAM_TYPE_CIF) { |
1184 | struct sd *sd = (struct sd *) gspca_dev; | 955 | /* No brightness for sensor_type 0 */ |
956 | if (sd->sensor_type == 0) | ||
957 | has_exposure = has_gain = has_clockdiv = true; | ||
958 | else | ||
959 | has_exposure = has_gain = has_brightness = true; | ||
960 | } else { | ||
961 | /* All controls need to be disabled if VGA sensor_type is 0 */ | ||
962 | if (sd->sensor_type == 0) | ||
963 | ; /* no controls! */ | ||
964 | else if (sd->sensor_type == 2) | ||
965 | has_exposure = has_cs_gain = has_contrast = true; | ||
966 | else if (sd->do_lcd_stop) | ||
967 | has_exposure = has_gain = has_argus_brightness = | ||
968 | has_clockdiv = true; | ||
969 | else | ||
970 | has_exposure = has_gain = has_brightness = | ||
971 | has_clockdiv = true; | ||
972 | } | ||
1185 | 973 | ||
1186 | *val = sd->min_clockdiv; | 974 | /* Separate brightness control description for Argus QuickClix as it has |
975 | * different limits from the other mr97310a cameras, and separate gain | ||
976 | * control for Sakar CyberPix camera. */ | ||
977 | /* | ||
978 | * This control is disabled for CIF type 1 and VGA type 0 cameras. | ||
979 | * It does not quite act linearly for the Argus QuickClix camera, | ||
980 | * but it does control brightness. The values are 0 - 15 only, and | ||
981 | * the table above makes them act consecutively. | ||
982 | */ | ||
983 | if (has_brightness) | ||
984 | v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
985 | V4L2_CID_BRIGHTNESS, -254, 255, 1, | ||
986 | MR97310A_BRIGHTNESS_DEFAULT); | ||
987 | else if (has_argus_brightness) | ||
988 | v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
989 | V4L2_CID_BRIGHTNESS, 0, 15, 1, | ||
990 | MR97310A_BRIGHTNESS_DEFAULT); | ||
991 | if (has_contrast) | ||
992 | v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
993 | V4L2_CID_CONTRAST, MR97310A_CONTRAST_MIN, | ||
994 | MR97310A_CONTRAST_MAX, 1, MR97310A_CONTRAST_DEFAULT); | ||
995 | if (has_gain) | ||
996 | v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
997 | V4L2_CID_GAIN, MR97310A_GAIN_MIN, MR97310A_GAIN_MAX, | ||
998 | 1, MR97310A_GAIN_DEFAULT); | ||
999 | else if (has_cs_gain) | ||
1000 | v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_GAIN, | ||
1001 | MR97310A_CS_GAIN_MIN, MR97310A_CS_GAIN_MAX, | ||
1002 | 1, MR97310A_CS_GAIN_DEFAULT); | ||
1003 | if (has_exposure) | ||
1004 | sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
1005 | V4L2_CID_EXPOSURE, MR97310A_EXPOSURE_MIN, | ||
1006 | MR97310A_EXPOSURE_MAX, 1, MR97310A_EXPOSURE_DEFAULT); | ||
1007 | if (has_clockdiv) | ||
1008 | sd->min_clockdiv = v4l2_ctrl_new_custom(hdl, &clockdiv, NULL); | ||
1009 | |||
1010 | if (hdl->error) { | ||
1011 | pr_err("Could not initialize controls\n"); | ||
1012 | return hdl->error; | ||
1013 | } | ||
1014 | if (has_exposure && has_clockdiv) | ||
1015 | v4l2_ctrl_cluster(2, &sd->exposure); | ||
1187 | return 0; | 1016 | return 0; |
1188 | } | 1017 | } |
1189 | 1018 | ||
@@ -1221,10 +1050,9 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
1221 | /* sub-driver description */ | 1050 | /* sub-driver description */ |
1222 | static const struct sd_desc sd_desc = { | 1051 | static const struct sd_desc sd_desc = { |
1223 | .name = MODULE_NAME, | 1052 | .name = MODULE_NAME, |
1224 | .ctrls = sd_ctrls, | ||
1225 | .nctrls = ARRAY_SIZE(sd_ctrls), | ||
1226 | .config = sd_config, | 1053 | .config = sd_config, |
1227 | .init = sd_init, | 1054 | .init = sd_init, |
1055 | .init_controls = sd_init_controls, | ||
1228 | .start = sd_start, | 1056 | .start = sd_start, |
1229 | .stopN = sd_stopN, | 1057 | .stopN = sd_stopN, |
1230 | .pkt_scan = sd_pkt_scan, | 1058 | .pkt_scan = sd_pkt_scan, |