aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2012-05-06 08:28:29 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-05-14 08:36:34 -0400
commit63069da1c8ef0abcdb74b0ea1c461d23fb9181d9 (patch)
treeecf1cf5509b31c0e5df3aaae8107dca1d506518d
parentc06ba2804a50076cc0c5a4d65466a37b8eaa4455 (diff)
[media] gcpca_sn9c20x: Convert to the control framework
HdG: Small fix: don't register some controls for sensors which don't have an implementation for them. 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>
-rw-r--r--drivers/media/video/gspca/sn9c20x.c495
1 files changed, 212 insertions, 283 deletions
diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c
index 5285a519c1f3..f35f1a0d1caf 100644
--- a/drivers/media/video/gspca/sn9c20x.c
+++ b/drivers/media/video/gspca/sn9c20x.c
@@ -66,28 +66,32 @@ MODULE_LICENSE("GPL");
66#define LED_REVERSE 0x2 /* some cameras unset gpio to turn on leds */ 66#define LED_REVERSE 0x2 /* some cameras unset gpio to turn on leds */
67#define FLIP_DETECT 0x4 67#define FLIP_DETECT 0x4
68 68
69enum e_ctrl {
70 BRIGHTNESS,
71 CONTRAST,
72 SATURATION,
73 HUE,
74 GAMMA,
75 BLUE,
76 RED,
77 VFLIP,
78 HFLIP,
79 EXPOSURE,
80 GAIN,
81 AUTOGAIN,
82 QUALITY,
83 NCTRLS /* number of controls */
84};
85
86/* specific webcam descriptor */ 69/* specific webcam descriptor */
87struct sd { 70struct sd {
88 struct gspca_dev gspca_dev; 71 struct gspca_dev gspca_dev;
89 72
90 struct gspca_ctrl ctrls[NCTRLS]; 73 struct v4l2_ctrl_handler ctrl_handler;
74 struct { /* color control cluster */
75 struct v4l2_ctrl *brightness;
76 struct v4l2_ctrl *contrast;
77 struct v4l2_ctrl *saturation;
78 struct v4l2_ctrl *hue;
79 };
80 struct { /* blue/red balance control cluster */
81 struct v4l2_ctrl *blue;
82 struct v4l2_ctrl *red;
83 };
84 struct { /* h/vflip control cluster */
85 struct v4l2_ctrl *hflip;
86 struct v4l2_ctrl *vflip;
87 };
88 struct v4l2_ctrl *gamma;
89 struct { /* autogain and exposure or gain control cluster */
90 struct v4l2_ctrl *autogain;
91 struct v4l2_ctrl *exposure;
92 struct v4l2_ctrl *gain;
93 };
94 struct v4l2_ctrl *jpegqual;
91 95
92 struct work_struct work; 96 struct work_struct work;
93 struct workqueue_struct *work_thread; 97 struct workqueue_struct *work_thread;
@@ -167,175 +171,6 @@ static const struct dmi_system_id flip_dmi_table[] = {
167 {} 171 {}
168}; 172};
169 173
170static void set_cmatrix(struct gspca_dev *gspca_dev);
171static void set_gamma(struct gspca_dev *gspca_dev);
172static void set_redblue(struct gspca_dev *gspca_dev);
173static void set_hvflip(struct gspca_dev *gspca_dev);
174static void set_exposure(struct gspca_dev *gspca_dev);
175static void set_gain(struct gspca_dev *gspca_dev);
176static void set_quality(struct gspca_dev *gspca_dev);
177
178static const struct ctrl sd_ctrls[NCTRLS] = {
179[BRIGHTNESS] = {
180 {
181 .id = V4L2_CID_BRIGHTNESS,
182 .type = V4L2_CTRL_TYPE_INTEGER,
183 .name = "Brightness",
184 .minimum = 0,
185 .maximum = 0xff,
186 .step = 1,
187 .default_value = 0x7f
188 },
189 .set_control = set_cmatrix
190 },
191[CONTRAST] = {
192 {
193 .id = V4L2_CID_CONTRAST,
194 .type = V4L2_CTRL_TYPE_INTEGER,
195 .name = "Contrast",
196 .minimum = 0,
197 .maximum = 0xff,
198 .step = 1,
199 .default_value = 0x7f
200 },
201 .set_control = set_cmatrix
202 },
203[SATURATION] = {
204 {
205 .id = V4L2_CID_SATURATION,
206 .type = V4L2_CTRL_TYPE_INTEGER,
207 .name = "Saturation",
208 .minimum = 0,
209 .maximum = 0xff,
210 .step = 1,
211 .default_value = 0x7f
212 },
213 .set_control = set_cmatrix
214 },
215[HUE] = {
216 {
217 .id = V4L2_CID_HUE,
218 .type = V4L2_CTRL_TYPE_INTEGER,
219 .name = "Hue",
220 .minimum = -180,
221 .maximum = 180,
222 .step = 1,
223 .default_value = 0
224 },
225 .set_control = set_cmatrix
226 },
227[GAMMA] = {
228 {
229 .id = V4L2_CID_GAMMA,
230 .type = V4L2_CTRL_TYPE_INTEGER,
231 .name = "Gamma",
232 .minimum = 0,
233 .maximum = 0xff,
234 .step = 1,
235 .default_value = 0x10
236 },
237 .set_control = set_gamma
238 },
239[BLUE] = {
240 {
241 .id = V4L2_CID_BLUE_BALANCE,
242 .type = V4L2_CTRL_TYPE_INTEGER,
243 .name = "Blue Balance",
244 .minimum = 0,
245 .maximum = 0x7f,
246 .step = 1,
247 .default_value = 0x28
248 },
249 .set_control = set_redblue
250 },
251[RED] = {
252 {
253 .id = V4L2_CID_RED_BALANCE,
254 .type = V4L2_CTRL_TYPE_INTEGER,
255 .name = "Red Balance",
256 .minimum = 0,
257 .maximum = 0x7f,
258 .step = 1,
259 .default_value = 0x28
260 },
261 .set_control = set_redblue
262 },
263[HFLIP] = {
264 {
265 .id = V4L2_CID_HFLIP,
266 .type = V4L2_CTRL_TYPE_BOOLEAN,
267 .name = "Horizontal Flip",
268 .minimum = 0,
269 .maximum = 1,
270 .step = 1,
271 .default_value = 0,
272 },
273 .set_control = set_hvflip
274 },
275[VFLIP] = {
276 {
277 .id = V4L2_CID_VFLIP,
278 .type = V4L2_CTRL_TYPE_BOOLEAN,
279 .name = "Vertical Flip",
280 .minimum = 0,
281 .maximum = 1,
282 .step = 1,
283 .default_value = 0,
284 },
285 .set_control = set_hvflip
286 },
287[EXPOSURE] = {
288 {
289 .id = V4L2_CID_EXPOSURE,
290 .type = V4L2_CTRL_TYPE_INTEGER,
291 .name = "Exposure",
292 .minimum = 0,
293 .maximum = 0x1780,
294 .step = 1,
295 .default_value = 0x33,
296 },
297 .set_control = set_exposure
298 },
299[GAIN] = {
300 {
301 .id = V4L2_CID_GAIN,
302 .type = V4L2_CTRL_TYPE_INTEGER,
303 .name = "Gain",
304 .minimum = 0,
305 .maximum = 28,
306 .step = 1,
307 .default_value = 0,
308 },
309 .set_control = set_gain
310 },
311[AUTOGAIN] = {
312 {
313 .id = V4L2_CID_AUTOGAIN,
314 .type = V4L2_CTRL_TYPE_BOOLEAN,
315 .name = "Auto Exposure",
316 .minimum = 0,
317 .maximum = 1,
318 .step = 1,
319 .default_value = 1,
320 },
321 },
322[QUALITY] = {
323 {
324 .id = V4L2_CID_JPEG_COMPRESSION_QUALITY,
325 .type = V4L2_CTRL_TYPE_INTEGER,
326 .name = "Compression Quality",
327#define QUALITY_MIN 50
328#define QUALITY_MAX 90
329#define QUALITY_DEF 80
330 .minimum = QUALITY_MIN,
331 .maximum = QUALITY_MAX,
332 .step = 1,
333 .default_value = QUALITY_DEF,
334 },
335 .set_control = set_quality
336 },
337};
338
339static const struct v4l2_pix_format vga_mode[] = { 174static const struct v4l2_pix_format vga_mode[] = {
340 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 175 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
341 .bytesperline = 160, 176 .bytesperline = 160,
@@ -1296,8 +1131,6 @@ static void ov9655_init_sensor(struct gspca_dev *gspca_dev)
1296 if (gspca_dev->usb_err < 0) 1131 if (gspca_dev->usb_err < 0)
1297 pr_err("OV9655 sensor initialization failed\n"); 1132 pr_err("OV9655 sensor initialization failed\n");
1298 1133
1299 /* disable hflip and vflip */
1300 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
1301 sd->hstart = 1; 1134 sd->hstart = 1;
1302 sd->vstart = 2; 1135 sd->vstart = 2;
1303} 1136}
@@ -1312,9 +1145,6 @@ static void soi968_init_sensor(struct gspca_dev *gspca_dev)
1312 if (gspca_dev->usb_err < 0) 1145 if (gspca_dev->usb_err < 0)
1313 pr_err("SOI968 sensor initialization failed\n"); 1146 pr_err("SOI968 sensor initialization failed\n");
1314 1147
1315 /* disable hflip and vflip */
1316 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP)
1317 | (1 << EXPOSURE);
1318 sd->hstart = 60; 1148 sd->hstart = 60;
1319 sd->vstart = 11; 1149 sd->vstart = 11;
1320} 1150}
@@ -1342,8 +1172,6 @@ static void ov7670_init_sensor(struct gspca_dev *gspca_dev)
1342 if (gspca_dev->usb_err < 0) 1172 if (gspca_dev->usb_err < 0)
1343 pr_err("OV7670 sensor initialization failed\n"); 1173 pr_err("OV7670 sensor initialization failed\n");
1344 1174
1345 /* disable hflip and vflip */
1346 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
1347 sd->hstart = 0; 1175 sd->hstart = 0;
1348 sd->vstart = 1; 1176 sd->vstart = 1;
1349} 1177}
@@ -1380,9 +1208,6 @@ static void mt9v_init_sensor(struct gspca_dev *gspca_dev)
1380 pr_err("MT9V111 sensor initialization failed\n"); 1208 pr_err("MT9V111 sensor initialization failed\n");
1381 return; 1209 return;
1382 } 1210 }
1383 gspca_dev->ctrl_dis = (1 << EXPOSURE)
1384 | (1 << AUTOGAIN)
1385 | (1 << GAIN);
1386 sd->hstart = 2; 1211 sd->hstart = 2;
1387 sd->vstart = 2; 1212 sd->vstart = 2;
1388 sd->sensor = SENSOR_MT9V111; 1213 sd->sensor = SENSOR_MT9V111;
@@ -1424,8 +1249,6 @@ static void mt9m112_init_sensor(struct gspca_dev *gspca_dev)
1424 if (gspca_dev->usb_err < 0) 1249 if (gspca_dev->usb_err < 0)
1425 pr_err("MT9M112 sensor initialization failed\n"); 1250 pr_err("MT9M112 sensor initialization failed\n");
1426 1251
1427 gspca_dev->ctrl_dis = (1 << EXPOSURE) | (1 << AUTOGAIN)
1428 | (1 << GAIN);
1429 sd->hstart = 0; 1252 sd->hstart = 0;
1430 sd->vstart = 2; 1253 sd->vstart = 2;
1431} 1254}
@@ -1438,8 +1261,6 @@ static void mt9m111_init_sensor(struct gspca_dev *gspca_dev)
1438 if (gspca_dev->usb_err < 0) 1261 if (gspca_dev->usb_err < 0)
1439 pr_err("MT9M111 sensor initialization failed\n"); 1262 pr_err("MT9M111 sensor initialization failed\n");
1440 1263
1441 gspca_dev->ctrl_dis = (1 << EXPOSURE) | (1 << AUTOGAIN)
1442 | (1 << GAIN);
1443 sd->hstart = 0; 1264 sd->hstart = 0;
1444 sd->vstart = 2; 1265 sd->vstart = 2;
1445} 1266}
@@ -1472,8 +1293,6 @@ static void mt9m001_init_sensor(struct gspca_dev *gspca_dev)
1472 if (gspca_dev->usb_err < 0) 1293 if (gspca_dev->usb_err < 0)
1473 pr_err("MT9M001 sensor initialization failed\n"); 1294 pr_err("MT9M001 sensor initialization failed\n");
1474 1295
1475 /* disable hflip and vflip */
1476 gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
1477 sd->hstart = 1; 1296 sd->hstart = 1;
1478 sd->vstart = 1; 1297 sd->vstart = 1;
1479} 1298}
@@ -1490,20 +1309,18 @@ static void hv7131r_init_sensor(struct gspca_dev *gspca_dev)
1490 sd->vstart = 1; 1309 sd->vstart = 1;
1491} 1310}
1492 1311
1493static void set_cmatrix(struct gspca_dev *gspca_dev) 1312static void set_cmatrix(struct gspca_dev *gspca_dev,
1313 s32 brightness, s32 contrast, s32 satur, s32 hue)
1494{ 1314{
1495 struct sd *sd = (struct sd *) gspca_dev; 1315 s32 hue_coord, hue_index = 180 + hue;
1496 int satur;
1497 s32 hue_coord, hue_index = 180 + sd->ctrls[HUE].val;
1498 u8 cmatrix[21]; 1316 u8 cmatrix[21];
1499 1317
1500 memset(cmatrix, 0, sizeof cmatrix); 1318 memset(cmatrix, 0, sizeof cmatrix);
1501 cmatrix[2] = (sd->ctrls[CONTRAST].val * 0x25 / 0x100) + 0x26; 1319 cmatrix[2] = (contrast * 0x25 / 0x100) + 0x26;
1502 cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25; 1320 cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
1503 cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25; 1321 cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
1504 cmatrix[18] = sd->ctrls[BRIGHTNESS].val - 0x80; 1322 cmatrix[18] = brightness - 0x80;
1505 1323
1506 satur = sd->ctrls[SATURATION].val;
1507 hue_coord = (hsv_red_x[hue_index] * satur) >> 8; 1324 hue_coord = (hsv_red_x[hue_index] * satur) >> 8;
1508 cmatrix[6] = hue_coord; 1325 cmatrix[6] = hue_coord;
1509 cmatrix[7] = (hue_coord >> 8) & 0x0f; 1326 cmatrix[7] = (hue_coord >> 8) & 0x0f;
@@ -1531,11 +1348,10 @@ static void set_cmatrix(struct gspca_dev *gspca_dev)
1531 reg_w(gspca_dev, 0x10e1, cmatrix, 21); 1348 reg_w(gspca_dev, 0x10e1, cmatrix, 21);
1532} 1349}
1533 1350
1534static void set_gamma(struct gspca_dev *gspca_dev) 1351static void set_gamma(struct gspca_dev *gspca_dev, s32 val)
1535{ 1352{
1536 struct sd *sd = (struct sd *) gspca_dev;
1537 u8 gamma[17]; 1353 u8 gamma[17];
1538 u8 gval = sd->ctrls[GAMMA].val * 0xb8 / 0x100; 1354 u8 gval = val * 0xb8 / 0x100;
1539 1355
1540 gamma[0] = 0x0a; 1356 gamma[0] = 0x0a;
1541 gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8); 1357 gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8);
@@ -1558,26 +1374,21 @@ static void set_gamma(struct gspca_dev *gspca_dev)
1558 reg_w(gspca_dev, 0x1190, gamma, 17); 1374 reg_w(gspca_dev, 0x1190, gamma, 17);
1559} 1375}
1560 1376
1561static void set_redblue(struct gspca_dev *gspca_dev) 1377static void set_redblue(struct gspca_dev *gspca_dev, s32 blue, s32 red)
1562{ 1378{
1563 struct sd *sd = (struct sd *) gspca_dev; 1379 reg_w1(gspca_dev, 0x118c, red);
1564 1380 reg_w1(gspca_dev, 0x118f, blue);
1565 reg_w1(gspca_dev, 0x118c, sd->ctrls[RED].val);
1566 reg_w1(gspca_dev, 0x118f, sd->ctrls[BLUE].val);
1567} 1381}
1568 1382
1569static void set_hvflip(struct gspca_dev *gspca_dev) 1383static void set_hvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip)
1570{ 1384{
1571 u8 value, tslb, hflip, vflip; 1385 u8 value, tslb;
1572 u16 value2; 1386 u16 value2;
1573 struct sd *sd = (struct sd *) gspca_dev; 1387 struct sd *sd = (struct sd *) gspca_dev;
1574 1388
1575 if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) { 1389 if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) {
1576 hflip = !sd->ctrls[HFLIP].val; 1390 hflip = !hflip;
1577 vflip = !sd->ctrls[VFLIP].val; 1391 vflip = !vflip;
1578 } else {
1579 hflip = sd->ctrls[HFLIP].val;
1580 vflip = sd->ctrls[VFLIP].val;
1581 } 1392 }
1582 1393
1583 switch (sd->sensor) { 1394 switch (sd->sensor) {
@@ -1640,17 +1451,16 @@ static void set_hvflip(struct gspca_dev *gspca_dev)
1640 } 1451 }
1641} 1452}
1642 1453
1643static void set_exposure(struct gspca_dev *gspca_dev) 1454static void set_exposure(struct gspca_dev *gspca_dev, s32 expo)
1644{ 1455{
1645 struct sd *sd = (struct sd *) gspca_dev; 1456 struct sd *sd = (struct sd *) gspca_dev;
1646 u8 exp[8] = {sd->i2c_intf, sd->i2c_addr, 1457 u8 exp[8] = {sd->i2c_intf, sd->i2c_addr,
1647 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; 1458 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
1648 int expo, expo2; 1459 int expo2;
1649 1460
1650 if (gspca_dev->streaming) 1461 if (gspca_dev->streaming)
1651 exp[7] = 0x1e; 1462 exp[7] = 0x1e;
1652 1463
1653 expo = sd->ctrls[EXPOSURE].val;
1654 switch (sd->sensor) { 1464 switch (sd->sensor) {
1655 case SENSOR_OV7660: 1465 case SENSOR_OV7660:
1656 case SENSOR_OV7670: 1466 case SENSOR_OV7670:
@@ -1697,17 +1507,15 @@ static void set_exposure(struct gspca_dev *gspca_dev)
1697 i2c_w(gspca_dev, exp); 1507 i2c_w(gspca_dev, exp);
1698} 1508}
1699 1509
1700static void set_gain(struct gspca_dev *gspca_dev) 1510static void set_gain(struct gspca_dev *gspca_dev, s32 g)
1701{ 1511{
1702 struct sd *sd = (struct sd *) gspca_dev; 1512 struct sd *sd = (struct sd *) gspca_dev;
1703 u8 gain[8] = {sd->i2c_intf, sd->i2c_addr, 1513 u8 gain[8] = {sd->i2c_intf, sd->i2c_addr,
1704 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; 1514 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
1705 int g;
1706 1515
1707 if (gspca_dev->streaming) 1516 if (gspca_dev->streaming)
1708 gain[7] = 0x15; /* or 1d ? */ 1517 gain[7] = 0x15; /* or 1d ? */
1709 1518
1710 g = sd->ctrls[GAIN].val;
1711 switch (sd->sensor) { 1519 switch (sd->sensor) {
1712 case SENSOR_OV7660: 1520 case SENSOR_OV7660:
1713 case SENSOR_OV7670: 1521 case SENSOR_OV7670:
@@ -1746,11 +1554,11 @@ static void set_gain(struct gspca_dev *gspca_dev)
1746 i2c_w(gspca_dev, gain); 1554 i2c_w(gspca_dev, gain);
1747} 1555}
1748 1556
1749static void set_quality(struct gspca_dev *gspca_dev) 1557static void set_quality(struct gspca_dev *gspca_dev, s32 val)
1750{ 1558{
1751 struct sd *sd = (struct sd *) gspca_dev; 1559 struct sd *sd = (struct sd *) gspca_dev;
1752 1560
1753 jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val); 1561 jpeg_set_qual(sd->jpeg_hdr, val);
1754 reg_w1(gspca_dev, 0x1061, 0x01); /* stop transfer */ 1562 reg_w1(gspca_dev, 0x1061, 0x01); /* stop transfer */
1755 reg_w1(gspca_dev, 0x10e0, sd->fmt | 0x20); /* write QTAB */ 1563 reg_w1(gspca_dev, 0x10e0, sd->fmt | 0x20); /* write QTAB */
1756 reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64); 1564 reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
@@ -1879,13 +1687,132 @@ static int sd_config(struct gspca_dev *gspca_dev,
1879 sd->older_step = 0; 1687 sd->older_step = 0;
1880 sd->exposure_step = 16; 1688 sd->exposure_step = 16;
1881 1689
1882 gspca_dev->cam.ctrls = sd->ctrls;
1883
1884 INIT_WORK(&sd->work, qual_upd); 1690 INIT_WORK(&sd->work, qual_upd);
1885 1691
1886 return 0; 1692 return 0;
1887} 1693}
1888 1694
1695static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
1696{
1697 struct sd *sd = container_of(ctrl->handler, struct sd, ctrl_handler);
1698 struct gspca_dev *gspca_dev = &sd->gspca_dev;
1699
1700 gspca_dev->usb_err = 0;
1701
1702 if (!gspca_dev->streaming)
1703 return 0;
1704
1705 switch (ctrl->id) {
1706 /* color control cluster */
1707 case V4L2_CID_BRIGHTNESS:
1708 set_cmatrix(&sd->gspca_dev, sd->brightness->val,
1709 sd->contrast->val, sd->saturation->val, sd->hue->val);
1710 break;
1711 case V4L2_CID_GAMMA:
1712 set_gamma(&sd->gspca_dev, ctrl->val);
1713 break;
1714 /* blue/red balance cluster */
1715 case V4L2_CID_BLUE_BALANCE:
1716 set_redblue(&sd->gspca_dev, sd->blue->val, sd->red->val);
1717 break;
1718 /* h/vflip cluster */
1719 case V4L2_CID_HFLIP:
1720 set_hvflip(&sd->gspca_dev, sd->hflip->val, sd->vflip->val);
1721 break;
1722 /* standalone exposure control */
1723 case V4L2_CID_EXPOSURE:
1724 set_exposure(&sd->gspca_dev, ctrl->val);
1725 break;
1726 /* standalone gain control */
1727 case V4L2_CID_GAIN:
1728 set_gain(&sd->gspca_dev, ctrl->val);
1729 break;
1730 /* autogain + exposure or gain control cluster */
1731 case V4L2_CID_AUTOGAIN:
1732 if (sd->sensor == SENSOR_SOI968)
1733 set_gain(&sd->gspca_dev, sd->gain->val);
1734 else
1735 set_exposure(&sd->gspca_dev, sd->exposure->val);
1736 break;
1737 case V4L2_CID_JPEG_COMPRESSION_QUALITY:
1738 set_quality(&sd->gspca_dev, ctrl->val);
1739 break;
1740 }
1741 return gspca_dev->usb_err;
1742}
1743
1744static const struct v4l2_ctrl_ops sd_ctrl_ops = {
1745 .s_ctrl = sd_s_ctrl,
1746};
1747
1748static int sd_init_controls(struct gspca_dev *gspca_dev)
1749{
1750 struct sd *sd = (struct sd *) gspca_dev;
1751 struct v4l2_ctrl_handler *hdl = &sd->ctrl_handler;
1752
1753 gspca_dev->vdev.ctrl_handler = hdl;
1754 v4l2_ctrl_handler_init(hdl, 13);
1755
1756 sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1757 V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
1758 sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1759 V4L2_CID_CONTRAST, 0, 255, 1, 127);
1760 sd->saturation = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1761 V4L2_CID_SATURATION, 0, 255, 1, 127);
1762 sd->hue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1763 V4L2_CID_HUE, -180, 180, 1, 0);
1764 v4l2_ctrl_cluster(4, &sd->brightness);
1765
1766 sd->gamma = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1767 V4L2_CID_GAMMA, 0, 255, 1, 0x10);
1768
1769 sd->blue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1770 V4L2_CID_BLUE_BALANCE, 0, 127, 1, 0x28);
1771 sd->red = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1772 V4L2_CID_RED_BALANCE, 0, 127, 1, 0x28);
1773 v4l2_ctrl_cluster(2, &sd->blue);
1774
1775 if (sd->sensor != SENSOR_OV9655 && sd->sensor != SENSOR_SOI968 &&
1776 sd->sensor != SENSOR_OV7670 && sd->sensor != SENSOR_MT9M001 &&
1777 sd->sensor != SENSOR_MT9VPRB) {
1778 sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1779 V4L2_CID_HFLIP, 0, 1, 1, 0);
1780 sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1781 V4L2_CID_VFLIP, 0, 1, 1, 0);
1782 v4l2_ctrl_cluster(2, &sd->hflip);
1783 }
1784
1785 if (sd->sensor != SENSOR_SOI968 && sd->sensor != SENSOR_MT9VPRB &&
1786 sd->sensor != SENSOR_MT9M112 && sd->sensor != SENSOR_MT9M111 &&
1787 sd->sensor != SENSOR_MT9V111)
1788 sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1789 V4L2_CID_EXPOSURE, 0, 0x1780, 1, 0x33);
1790
1791 if (sd->sensor != SENSOR_MT9VPRB && sd->sensor != SENSOR_MT9M112 &&
1792 sd->sensor != SENSOR_MT9M111 && sd->sensor != SENSOR_MT9V111) {
1793 sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1794 V4L2_CID_GAIN, 0, 28, 1, 0);
1795 sd->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1796 V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
1797 if (sd->sensor == SENSOR_SOI968)
1798 /* this sensor doesn't have the exposure control and
1799 autogain is clustered with gain instead. This works
1800 because sd->exposure == NULL. */
1801 v4l2_ctrl_auto_cluster(3, &sd->autogain, 0, false);
1802 else
1803 /* Otherwise autogain is clustered with exposure. */
1804 v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, false);
1805 }
1806
1807 sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1808 V4L2_CID_JPEG_COMPRESSION_QUALITY, 50, 90, 1, 80);
1809 if (hdl->error) {
1810 pr_err("Could not initialize controls\n");
1811 return hdl->error;
1812 }
1813 return 0;
1814}
1815
1889static int sd_init(struct gspca_dev *gspca_dev) 1816static int sd_init(struct gspca_dev *gspca_dev)
1890{ 1817{
1891 struct sd *sd = (struct sd *) gspca_dev; 1818 struct sd *sd = (struct sd *) gspca_dev;
@@ -1978,7 +1905,6 @@ static int sd_init(struct gspca_dev *gspca_dev)
1978 pr_err("Unsupported sensor\n"); 1905 pr_err("Unsupported sensor\n");
1979 gspca_dev->usb_err = -ENODEV; 1906 gspca_dev->usb_err = -ENODEV;
1980 } 1907 }
1981
1982 return gspca_dev->usb_err; 1908 return gspca_dev->usb_err;
1983} 1909}
1984 1910
@@ -2096,7 +2022,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
2096 2022
2097 jpeg_define(sd->jpeg_hdr, height, width, 2023 jpeg_define(sd->jpeg_hdr, height, width,
2098 0x21); 2024 0x21);
2099 jpeg_set_qual(sd->jpeg_hdr, sd->ctrls[QUALITY].val); 2025 jpeg_set_qual(sd->jpeg_hdr, v4l2_ctrl_g_ctrl(sd->jpegqual));
2100 2026
2101 if (mode & MODE_RAW) 2027 if (mode & MODE_RAW)
2102 fmt = 0x2d; 2028 fmt = 0x2d;
@@ -2133,12 +2059,17 @@ static int sd_start(struct gspca_dev *gspca_dev)
2133 reg_w1(gspca_dev, 0x1189, scale); 2059 reg_w1(gspca_dev, 0x1189, scale);
2134 reg_w1(gspca_dev, 0x10e0, fmt); 2060 reg_w1(gspca_dev, 0x10e0, fmt);
2135 2061
2136 set_cmatrix(gspca_dev); 2062 set_cmatrix(gspca_dev, v4l2_ctrl_g_ctrl(sd->brightness),
2137 set_gamma(gspca_dev); 2063 v4l2_ctrl_g_ctrl(sd->contrast),
2138 set_redblue(gspca_dev); 2064 v4l2_ctrl_g_ctrl(sd->saturation),
2139 set_gain(gspca_dev); 2065 v4l2_ctrl_g_ctrl(sd->hue));
2140 set_exposure(gspca_dev); 2066 set_gamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma));
2141 set_hvflip(gspca_dev); 2067 set_redblue(gspca_dev, v4l2_ctrl_g_ctrl(sd->blue),
2068 v4l2_ctrl_g_ctrl(sd->red));
2069 set_gain(gspca_dev, v4l2_ctrl_g_ctrl(sd->gain));
2070 set_exposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure));
2071 set_hvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip),
2072 v4l2_ctrl_g_ctrl(sd->vflip));
2142 2073
2143 reg_w1(gspca_dev, 0x1007, 0x20); 2074 reg_w1(gspca_dev, 0x1007, 0x20);
2144 reg_w1(gspca_dev, 0x1061, 0x03); 2075 reg_w1(gspca_dev, 0x1061, 0x03);
@@ -2177,6 +2108,9 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
2177static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum) 2108static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum)
2178{ 2109{
2179 struct sd *sd = (struct sd *) gspca_dev; 2110 struct sd *sd = (struct sd *) gspca_dev;
2111 s32 cur_exp = v4l2_ctrl_g_ctrl(sd->exposure);
2112 s32 max = sd->exposure->maximum - sd->exposure_step;
2113 s32 min = sd->exposure->minimum + sd->exposure_step;
2180 s16 new_exp; 2114 s16 new_exp;
2181 2115
2182 /* 2116 /*
@@ -2185,16 +2119,15 @@ static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum)
2185 * and exposure steps 2119 * and exposure steps
2186 */ 2120 */
2187 if (avg_lum < MIN_AVG_LUM) { 2121 if (avg_lum < MIN_AVG_LUM) {
2188 if (sd->ctrls[EXPOSURE].val > 0x1770) 2122 if (cur_exp > max)
2189 return; 2123 return;
2190 2124
2191 new_exp = sd->ctrls[EXPOSURE].val + sd->exposure_step; 2125 new_exp = cur_exp + sd->exposure_step;
2192 if (new_exp > 0x1770) 2126 if (new_exp > max)
2193 new_exp = 0x1770; 2127 new_exp = max;
2194 if (new_exp < 0x10) 2128 if (new_exp < min)
2195 new_exp = 0x10; 2129 new_exp = min;
2196 sd->ctrls[EXPOSURE].val = new_exp; 2130 v4l2_ctrl_s_ctrl(sd->exposure, new_exp);
2197 set_exposure(gspca_dev);
2198 2131
2199 sd->older_step = sd->old_step; 2132 sd->older_step = sd->old_step;
2200 sd->old_step = 1; 2133 sd->old_step = 1;
@@ -2205,15 +2138,14 @@ static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum)
2205 sd->exposure_step += 2; 2138 sd->exposure_step += 2;
2206 } 2139 }
2207 if (avg_lum > MAX_AVG_LUM) { 2140 if (avg_lum > MAX_AVG_LUM) {
2208 if (sd->ctrls[EXPOSURE].val < 0x10) 2141 if (cur_exp < min)
2209 return; 2142 return;
2210 new_exp = sd->ctrls[EXPOSURE].val - sd->exposure_step; 2143 new_exp = cur_exp - sd->exposure_step;
2211 if (new_exp > 0x1700) 2144 if (new_exp > max)
2212 new_exp = 0x1770; 2145 new_exp = max;
2213 if (new_exp < 0x10) 2146 if (new_exp < min)
2214 new_exp = 0x10; 2147 new_exp = min;
2215 sd->ctrls[EXPOSURE].val = new_exp; 2148 v4l2_ctrl_s_ctrl(sd->exposure, new_exp);
2216 set_exposure(gspca_dev);
2217 sd->older_step = sd->old_step; 2149 sd->older_step = sd->old_step;
2218 sd->old_step = 0; 2150 sd->old_step = 0;
2219 2151
@@ -2227,19 +2159,12 @@ static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum)
2227static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum) 2159static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum)
2228{ 2160{
2229 struct sd *sd = (struct sd *) gspca_dev; 2161 struct sd *sd = (struct sd *) gspca_dev;
2162 s32 cur_gain = v4l2_ctrl_g_ctrl(sd->gain);
2230 2163
2231 if (avg_lum < MIN_AVG_LUM) { 2164 if (avg_lum < MIN_AVG_LUM && cur_gain < sd->gain->maximum)
2232 if (sd->ctrls[GAIN].val + 1 <= 28) { 2165 v4l2_ctrl_s_ctrl(sd->gain, cur_gain + 1);
2233 sd->ctrls[GAIN].val++; 2166 if (avg_lum > MAX_AVG_LUM && cur_gain > sd->gain->minimum)
2234 set_gain(gspca_dev); 2167 v4l2_ctrl_s_ctrl(sd->gain, cur_gain - 1);
2235 }
2236 }
2237 if (avg_lum > MAX_AVG_LUM) {
2238 if (sd->ctrls[GAIN].val > 0) {
2239 sd->ctrls[GAIN].val--;
2240 set_gain(gspca_dev);
2241 }
2242 }
2243} 2168}
2244 2169
2245static void sd_dqcallback(struct gspca_dev *gspca_dev) 2170static void sd_dqcallback(struct gspca_dev *gspca_dev)
@@ -2247,7 +2172,7 @@ static void sd_dqcallback(struct gspca_dev *gspca_dev)
2247 struct sd *sd = (struct sd *) gspca_dev; 2172 struct sd *sd = (struct sd *) gspca_dev;
2248 int avg_lum; 2173 int avg_lum;
2249 2174
2250 if (!sd->ctrls[AUTOGAIN].val) 2175 if (!v4l2_ctrl_g_ctrl(sd->autogain))
2251 return; 2176 return;
2252 2177
2253 avg_lum = atomic_read(&sd->avg_lum); 2178 avg_lum = atomic_read(&sd->avg_lum);
@@ -2263,10 +2188,11 @@ static void qual_upd(struct work_struct *work)
2263{ 2188{
2264 struct sd *sd = container_of(work, struct sd, work); 2189 struct sd *sd = container_of(work, struct sd, work);
2265 struct gspca_dev *gspca_dev = &sd->gspca_dev; 2190 struct gspca_dev *gspca_dev = &sd->gspca_dev;
2191 s32 qual = v4l2_ctrl_g_ctrl(sd->jpegqual);
2266 2192
2267 mutex_lock(&gspca_dev->usb_lock); 2193 mutex_lock(&gspca_dev->usb_lock);
2268 PDEBUG(D_STREAM, "qual_upd %d%%", sd->ctrls[QUALITY].val); 2194 PDEBUG(D_STREAM, "qual_upd %d%%", qual);
2269 set_quality(gspca_dev); 2195 set_quality(gspca_dev, qual);
2270 mutex_unlock(&gspca_dev->usb_lock); 2196 mutex_unlock(&gspca_dev->usb_lock);
2271} 2197}
2272 2198
@@ -2315,14 +2241,18 @@ static void transfer_check(struct gspca_dev *gspca_dev,
2315 if (new_qual != 0) { 2241 if (new_qual != 0) {
2316 sd->nchg += new_qual; 2242 sd->nchg += new_qual;
2317 if (sd->nchg < -6 || sd->nchg >= 12) { 2243 if (sd->nchg < -6 || sd->nchg >= 12) {
2244 /* Note: we are in interrupt context, so we can't
2245 use v4l2_ctrl_g/s_ctrl here. Access the value
2246 directly instead. */
2247 s32 curqual = sd->jpegqual->cur.val;
2318 sd->nchg = 0; 2248 sd->nchg = 0;
2319 new_qual += sd->ctrls[QUALITY].val; 2249 new_qual += curqual;
2320 if (new_qual < QUALITY_MIN) 2250 if (new_qual < sd->jpegqual->minimum)
2321 new_qual = QUALITY_MIN; 2251 new_qual = sd->jpegqual->minimum;
2322 else if (new_qual > QUALITY_MAX) 2252 else if (new_qual > sd->jpegqual->maximum)
2323 new_qual = QUALITY_MAX; 2253 new_qual = sd->jpegqual->maximum;
2324 if (new_qual != sd->ctrls[QUALITY].val) { 2254 if (new_qual != curqual) {
2325 sd->ctrls[QUALITY].val = new_qual; 2255 sd->jpegqual->cur.val = new_qual;
2326 queue_work(sd->work_thread, &sd->work); 2256 queue_work(sd->work_thread, &sd->work);
2327 } 2257 }
2328 } 2258 }
@@ -2402,10 +2332,9 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
2402/* sub-driver description */ 2332/* sub-driver description */
2403static const struct sd_desc sd_desc = { 2333static const struct sd_desc sd_desc = {
2404 .name = KBUILD_MODNAME, 2334 .name = KBUILD_MODNAME,
2405 .ctrls = sd_ctrls,
2406 .nctrls = ARRAY_SIZE(sd_ctrls),
2407 .config = sd_config, 2335 .config = sd_config,
2408 .init = sd_init, 2336 .init = sd_init,
2337 .init_controls = sd_init_controls,
2409 .isoc_init = sd_isoc_init, 2338 .isoc_init = sd_isoc_init,
2410 .start = sd_start, 2339 .start = sd_start,
2411 .stopN = sd_stopN, 2340 .stopN = sd_stopN,