aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2012-05-14 08:45:06 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-07-30 17:23:18 -0400
commit3e0ed00903e1904112108135c18b1918386457aa (patch)
tree8582dfd80f67308bd03eab808bb1d606ec8a3c0b /drivers/media/video/gspca
parent1bdee422cd9edea43a86f37a4ceb0081de6bd0bc (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.c438
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 */
85struct sd { 86struct 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
100struct sensor_w_data { 99struct sensor_w_data {
@@ -105,132 +104,6 @@ struct sensor_w_data {
105}; 104};
106 105
107static void sd_stopN(struct gspca_dev *gspca_dev); 106static void sd_stopN(struct gspca_dev *gspca_dev);
108static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
109static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
110static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
111static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
112static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
113static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
114static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
115static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
116static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val);
117static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val);
118static void setbrightness(struct gspca_dev *gspca_dev);
119static void setexposure(struct gspca_dev *gspca_dev);
120static void setgain(struct gspca_dev *gspca_dev);
121static void setcontrast(struct gspca_dev *gspca_dev);
122
123/* V4L2 controls supported by the driver */
124static 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
235static const struct v4l2_pix_format vga_mode[] = { 108static 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
974static void setbrightness(struct gspca_dev *gspca_dev) 795static 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
1013static void setexposure(struct gspca_dev *gspca_dev) 822static 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
1068static void setgain(struct gspca_dev *gspca_dev) 874static 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
1088static 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
1099static 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
1109static 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
1117static 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
1127static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) 890static 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
1135static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) 895static 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
1145static 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
1153static 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
924static const struct v4l2_ctrl_ops sd_ctrl_ops = {
925 .s_ctrl = sd_s_ctrl,
926};
1163 927
1164static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) 928static 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
1172static 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
1182static 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 */
1222static const struct sd_desc sd_desc = { 1051static 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,