aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2012-05-14 05:30:06 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-07-30 17:22:26 -0400
commitbfaab899e7c8ded57afe93ebed234b3688d9a898 (patch)
tree9067ef2398465c51593217e545b87832b088cd4a /drivers
parent8792015ec58be8059cdb9ff86e3639481a4be4fb (diff)
[media] gspca-jeilinj: 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')
-rw-r--r--drivers/media/video/gspca/jeilinj.c218
1 files changed, 90 insertions, 128 deletions
diff --git a/drivers/media/video/gspca/jeilinj.c b/drivers/media/video/gspca/jeilinj.c
index 5ab3f7e12760..51016db2fc62 100644
--- a/drivers/media/video/gspca/jeilinj.c
+++ b/drivers/media/video/gspca/jeilinj.c
@@ -54,21 +54,13 @@ enum {
54#define CAMQUALITY_MIN 0 /* highest cam quality */ 54#define CAMQUALITY_MIN 0 /* highest cam quality */
55#define CAMQUALITY_MAX 97 /* lowest cam quality */ 55#define CAMQUALITY_MAX 97 /* lowest cam quality */
56 56
57enum e_ctrl {
58 LIGHTFREQ,
59 AUTOGAIN,
60 RED,
61 GREEN,
62 BLUE,
63 NCTRLS /* number of controls */
64};
65
66/* Structure to hold all of our device specific stuff */ 57/* Structure to hold all of our device specific stuff */
67struct sd { 58struct sd {
68 struct gspca_dev gspca_dev; /* !! must be the first item */ 59 struct gspca_dev gspca_dev; /* !! must be the first item */
69 struct gspca_ctrl ctrls[NCTRLS];
70 int blocks_left; 60 int blocks_left;
71 const struct v4l2_pix_format *cap_mode; 61 const struct v4l2_pix_format *cap_mode;
62 struct v4l2_ctrl *freq;
63 struct v4l2_ctrl *jpegqual;
72 /* Driver stuff */ 64 /* Driver stuff */
73 u8 type; 65 u8 type;
74 u8 quality; /* image quality */ 66 u8 quality; /* image quality */
@@ -139,23 +131,21 @@ static void jlj_read1(struct gspca_dev *gspca_dev, unsigned char response)
139 } 131 }
140} 132}
141 133
142static void setfreq(struct gspca_dev *gspca_dev) 134static void setfreq(struct gspca_dev *gspca_dev, s32 val)
143{ 135{
144 struct sd *sd = (struct sd *) gspca_dev;
145 u8 freq_commands[][2] = { 136 u8 freq_commands[][2] = {
146 {0x71, 0x80}, 137 {0x71, 0x80},
147 {0x70, 0x07} 138 {0x70, 0x07}
148 }; 139 };
149 140
150 freq_commands[0][1] |= (sd->ctrls[LIGHTFREQ].val >> 1); 141 freq_commands[0][1] |= val >> 1;
151 142
152 jlj_write2(gspca_dev, freq_commands[0]); 143 jlj_write2(gspca_dev, freq_commands[0]);
153 jlj_write2(gspca_dev, freq_commands[1]); 144 jlj_write2(gspca_dev, freq_commands[1]);
154} 145}
155 146
156static void setcamquality(struct gspca_dev *gspca_dev) 147static void setcamquality(struct gspca_dev *gspca_dev, s32 val)
157{ 148{
158 struct sd *sd = (struct sd *) gspca_dev;
159 u8 quality_commands[][2] = { 149 u8 quality_commands[][2] = {
160 {0x71, 0x1E}, 150 {0x71, 0x1E},
161 {0x70, 0x06} 151 {0x70, 0x06}
@@ -163,7 +153,7 @@ static void setcamquality(struct gspca_dev *gspca_dev)
163 u8 camquality; 153 u8 camquality;
164 154
165 /* adapt camera quality from jpeg quality */ 155 /* adapt camera quality from jpeg quality */
166 camquality = ((QUALITY_MAX - sd->quality) * CAMQUALITY_MAX) 156 camquality = ((QUALITY_MAX - val) * CAMQUALITY_MAX)
167 / (QUALITY_MAX - QUALITY_MIN); 157 / (QUALITY_MAX - QUALITY_MIN);
168 quality_commands[0][1] += camquality; 158 quality_commands[0][1] += camquality;
169 159
@@ -171,130 +161,58 @@ static void setcamquality(struct gspca_dev *gspca_dev)
171 jlj_write2(gspca_dev, quality_commands[1]); 161 jlj_write2(gspca_dev, quality_commands[1]);
172} 162}
173 163
174static void setautogain(struct gspca_dev *gspca_dev) 164static void setautogain(struct gspca_dev *gspca_dev, s32 val)
175{ 165{
176 struct sd *sd = (struct sd *) gspca_dev;
177 u8 autogain_commands[][2] = { 166 u8 autogain_commands[][2] = {
178 {0x94, 0x02}, 167 {0x94, 0x02},
179 {0xcf, 0x00} 168 {0xcf, 0x00}
180 }; 169 };
181 170
182 autogain_commands[1][1] = (sd->ctrls[AUTOGAIN].val << 4); 171 autogain_commands[1][1] = val << 4;
183 172
184 jlj_write2(gspca_dev, autogain_commands[0]); 173 jlj_write2(gspca_dev, autogain_commands[0]);
185 jlj_write2(gspca_dev, autogain_commands[1]); 174 jlj_write2(gspca_dev, autogain_commands[1]);
186} 175}
187 176
188static void setred(struct gspca_dev *gspca_dev) 177static void setred(struct gspca_dev *gspca_dev, s32 val)
189{ 178{
190 struct sd *sd = (struct sd *) gspca_dev;
191 u8 setred_commands[][2] = { 179 u8 setred_commands[][2] = {
192 {0x94, 0x02}, 180 {0x94, 0x02},
193 {0xe6, 0x00} 181 {0xe6, 0x00}
194 }; 182 };
195 183
196 setred_commands[1][1] = sd->ctrls[RED].val; 184 setred_commands[1][1] = val;
197 185
198 jlj_write2(gspca_dev, setred_commands[0]); 186 jlj_write2(gspca_dev, setred_commands[0]);
199 jlj_write2(gspca_dev, setred_commands[1]); 187 jlj_write2(gspca_dev, setred_commands[1]);
200} 188}
201 189
202static void setgreen(struct gspca_dev *gspca_dev) 190static void setgreen(struct gspca_dev *gspca_dev, s32 val)
203{ 191{
204 struct sd *sd = (struct sd *) gspca_dev;
205 u8 setgreen_commands[][2] = { 192 u8 setgreen_commands[][2] = {
206 {0x94, 0x02}, 193 {0x94, 0x02},
207 {0xe7, 0x00} 194 {0xe7, 0x00}
208 }; 195 };
209 196
210 setgreen_commands[1][1] = sd->ctrls[GREEN].val; 197 setgreen_commands[1][1] = val;
211 198
212 jlj_write2(gspca_dev, setgreen_commands[0]); 199 jlj_write2(gspca_dev, setgreen_commands[0]);
213 jlj_write2(gspca_dev, setgreen_commands[1]); 200 jlj_write2(gspca_dev, setgreen_commands[1]);
214} 201}
215 202
216static void setblue(struct gspca_dev *gspca_dev) 203static void setblue(struct gspca_dev *gspca_dev, s32 val)
217{ 204{
218 struct sd *sd = (struct sd *) gspca_dev;
219 u8 setblue_commands[][2] = { 205 u8 setblue_commands[][2] = {
220 {0x94, 0x02}, 206 {0x94, 0x02},
221 {0xe9, 0x00} 207 {0xe9, 0x00}
222 }; 208 };
223 209
224 setblue_commands[1][1] = sd->ctrls[BLUE].val; 210 setblue_commands[1][1] = val;
225 211
226 jlj_write2(gspca_dev, setblue_commands[0]); 212 jlj_write2(gspca_dev, setblue_commands[0]);
227 jlj_write2(gspca_dev, setblue_commands[1]); 213 jlj_write2(gspca_dev, setblue_commands[1]);
228} 214}
229 215
230static const struct ctrl sd_ctrls[NCTRLS] = {
231[LIGHTFREQ] = {
232 {
233 .id = V4L2_CID_POWER_LINE_FREQUENCY,
234 .type = V4L2_CTRL_TYPE_MENU,
235 .name = "Light frequency filter",
236 .minimum = V4L2_CID_POWER_LINE_FREQUENCY_DISABLED, /* 1 */
237 .maximum = V4L2_CID_POWER_LINE_FREQUENCY_60HZ, /* 2 */
238 .step = 1,
239 .default_value = V4L2_CID_POWER_LINE_FREQUENCY_60HZ,
240 },
241 .set_control = setfreq
242 },
243[AUTOGAIN] = {
244 {
245 .id = V4L2_CID_AUTOGAIN,
246 .type = V4L2_CTRL_TYPE_INTEGER,
247 .name = "Automatic Gain (and Exposure)",
248 .minimum = 0,
249 .maximum = 3,
250 .step = 1,
251#define AUTOGAIN_DEF 0
252 .default_value = AUTOGAIN_DEF,
253 },
254 .set_control = setautogain
255 },
256[RED] = {
257 {
258 .id = V4L2_CID_RED_BALANCE,
259 .type = V4L2_CTRL_TYPE_INTEGER,
260 .name = "red balance",
261 .minimum = 0,
262 .maximum = 3,
263 .step = 1,
264#define RED_BALANCE_DEF 2
265 .default_value = RED_BALANCE_DEF,
266 },
267 .set_control = setred
268 },
269
270[GREEN] = {
271 {
272 .id = V4L2_CID_GAIN,
273 .type = V4L2_CTRL_TYPE_INTEGER,
274 .name = "green balance",
275 .minimum = 0,
276 .maximum = 3,
277 .step = 1,
278#define GREEN_BALANCE_DEF 2
279 .default_value = GREEN_BALANCE_DEF,
280 },
281 .set_control = setgreen
282 },
283[BLUE] = {
284 {
285 .id = V4L2_CID_BLUE_BALANCE,
286 .type = V4L2_CTRL_TYPE_INTEGER,
287 .name = "blue balance",
288 .minimum = 0,
289 .maximum = 3,
290 .step = 1,
291#define BLUE_BALANCE_DEF 2
292 .default_value = BLUE_BALANCE_DEF,
293 },
294 .set_control = setblue
295 },
296};
297
298static int jlj_start(struct gspca_dev *gspca_dev) 216static int jlj_start(struct gspca_dev *gspca_dev)
299{ 217{
300 int i; 218 int i;
@@ -344,9 +262,9 @@ static int jlj_start(struct gspca_dev *gspca_dev)
344 if (start_commands[i].ack_wanted) 262 if (start_commands[i].ack_wanted)
345 jlj_read1(gspca_dev, response); 263 jlj_read1(gspca_dev, response);
346 } 264 }
347 setcamquality(gspca_dev); 265 setcamquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual));
348 msleep(2); 266 msleep(2);
349 setfreq(gspca_dev); 267 setfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->freq));
350 if (gspca_dev->usb_err < 0) 268 if (gspca_dev->usb_err < 0)
351 PDEBUG(D_ERR, "Start streaming command failed"); 269 PDEBUG(D_ERR, "Start streaming command failed");
352 return gspca_dev->usb_err; 270 return gspca_dev->usb_err;
@@ -403,7 +321,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
403 struct sd *dev = (struct sd *) gspca_dev; 321 struct sd *dev = (struct sd *) gspca_dev;
404 322
405 dev->type = id->driver_info; 323 dev->type = id->driver_info;
406 gspca_dev->cam.ctrls = dev->ctrls;
407 dev->quality = QUALITY_DEF; 324 dev->quality = QUALITY_DEF;
408 325
409 cam->cam_mode = jlj_mode; 326 cam->cam_mode = jlj_mode;
@@ -479,25 +396,81 @@ static const struct usb_device_id device_table[] = {
479 396
480MODULE_DEVICE_TABLE(usb, device_table); 397MODULE_DEVICE_TABLE(usb, device_table);
481 398
482static int sd_querymenu(struct gspca_dev *gspca_dev, 399static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
483 struct v4l2_querymenu *menu)
484{ 400{
485 switch (menu->id) { 401 struct gspca_dev *gspca_dev =
402 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
403 struct sd *sd = (struct sd *)gspca_dev;
404
405 gspca_dev->usb_err = 0;
406
407 if (!gspca_dev->streaming)
408 return 0;
409
410 switch (ctrl->id) {
486 case V4L2_CID_POWER_LINE_FREQUENCY: 411 case V4L2_CID_POWER_LINE_FREQUENCY:
487 switch (menu->index) { 412 setfreq(gspca_dev, ctrl->val);
488 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */ 413 break;
489 strcpy((char *) menu->name, "disable"); 414 case V4L2_CID_RED_BALANCE:
490 return 0; 415 setred(gspca_dev, ctrl->val);
491 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ 416 break;
492 strcpy((char *) menu->name, "50 Hz"); 417 case V4L2_CID_GAIN:
493 return 0; 418 setgreen(gspca_dev, ctrl->val);
494 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ 419 break;
495 strcpy((char *) menu->name, "60 Hz"); 420 case V4L2_CID_BLUE_BALANCE:
496 return 0; 421 setblue(gspca_dev, ctrl->val);
497 } 422 break;
423 case V4L2_CID_AUTOGAIN:
424 setautogain(gspca_dev, ctrl->val);
425 break;
426 case V4L2_CID_JPEG_COMPRESSION_QUALITY:
427 jpeg_set_qual(sd->jpeg_hdr, ctrl->val);
428 setcamquality(gspca_dev, ctrl->val);
498 break; 429 break;
499 } 430 }
500 return -EINVAL; 431 return gspca_dev->usb_err;
432}
433
434static const struct v4l2_ctrl_ops sd_ctrl_ops = {
435 .s_ctrl = sd_s_ctrl,
436};
437
438static int sd_init_controls(struct gspca_dev *gspca_dev)
439{
440 struct sd *sd = (struct sd *)gspca_dev;
441 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
442 static const struct v4l2_ctrl_config custom_autogain = {
443 .ops = &sd_ctrl_ops,
444 .id = V4L2_CID_AUTOGAIN,
445 .type = V4L2_CTRL_TYPE_INTEGER,
446 .name = "Automatic Gain (and Exposure)",
447 .max = 3,
448 .step = 1,
449 .def = 0,
450 };
451
452 gspca_dev->vdev.ctrl_handler = hdl;
453 v4l2_ctrl_handler_init(hdl, 6);
454 sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
455 V4L2_CID_POWER_LINE_FREQUENCY,
456 V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 1,
457 V4L2_CID_POWER_LINE_FREQUENCY_60HZ);
458 v4l2_ctrl_new_custom(hdl, &custom_autogain, NULL);
459 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
460 V4L2_CID_RED_BALANCE, 0, 3, 1, 2);
461 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
462 V4L2_CID_GAIN, 0, 3, 1, 2);
463 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
464 V4L2_CID_BLUE_BALANCE, 0, 3, 1, 2);
465 sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
466 V4L2_CID_JPEG_COMPRESSION_QUALITY,
467 QUALITY_MIN, QUALITY_MAX, 1, QUALITY_DEF);
468
469 if (hdl->error) {
470 pr_err("Could not initialize controls\n");
471 return hdl->error;
472 }
473 return 0;
501} 474}
502 475
503static int sd_set_jcomp(struct gspca_dev *gspca_dev, 476static int sd_set_jcomp(struct gspca_dev *gspca_dev,
@@ -505,16 +478,7 @@ static int sd_set_jcomp(struct gspca_dev *gspca_dev,
505{ 478{
506 struct sd *sd = (struct sd *) gspca_dev; 479 struct sd *sd = (struct sd *) gspca_dev;
507 480
508 if (jcomp->quality < QUALITY_MIN) 481 v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);
509 sd->quality = QUALITY_MIN;
510 else if (jcomp->quality > QUALITY_MAX)
511 sd->quality = QUALITY_MAX;
512 else
513 sd->quality = jcomp->quality;
514 if (gspca_dev->streaming) {
515 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
516 setcamquality(gspca_dev);
517 }
518 return 0; 482 return 0;
519} 483}
520 484
@@ -524,7 +488,7 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev,
524 struct sd *sd = (struct sd *) gspca_dev; 488 struct sd *sd = (struct sd *) gspca_dev;
525 489
526 memset(jcomp, 0, sizeof *jcomp); 490 memset(jcomp, 0, sizeof *jcomp);
527 jcomp->quality = sd->quality; 491 jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
528 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT 492 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
529 | V4L2_JPEG_MARKER_DQT; 493 | V4L2_JPEG_MARKER_DQT;
530 return 0; 494 return 0;
@@ -546,12 +510,10 @@ static const struct sd_desc sd_desc_sportscam_dv15 = {
546 .name = MODULE_NAME, 510 .name = MODULE_NAME,
547 .config = sd_config, 511 .config = sd_config,
548 .init = sd_init, 512 .init = sd_init,
513 .init_controls = sd_init_controls,
549 .start = sd_start, 514 .start = sd_start,
550 .stopN = sd_stopN, 515 .stopN = sd_stopN,
551 .pkt_scan = sd_pkt_scan, 516 .pkt_scan = sd_pkt_scan,
552 .ctrls = sd_ctrls,
553 .nctrls = ARRAY_SIZE(sd_ctrls),
554 .querymenu = sd_querymenu,
555 .get_jcomp = sd_get_jcomp, 517 .get_jcomp = sd_get_jcomp,
556 .set_jcomp = sd_set_jcomp, 518 .set_jcomp = sd_set_jcomp,
557}; 519};