diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2012-05-16 07:38:34 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-07-30 17:31:45 -0400 |
commit | 74dec797143ea2624f829758ef2fb92f7c470a2d (patch) | |
tree | 3f68e223b5a5d6fd5da3c0ea03cb2cf4cb0e5fd0 | |
parent | df0df1accaf5a5a36901ad4019dd22b59ab8974d (diff) |
[media] stk014: 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>
-rw-r--r-- | drivers/media/video/gspca/stk014.c | 194 |
1 files changed, 76 insertions, 118 deletions
diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c index 4ae7cc8f463a..247365c2a519 100644 --- a/drivers/media/video/gspca/stk014.c +++ b/drivers/media/video/gspca/stk014.c | |||
@@ -29,22 +29,11 @@ MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>"); | |||
29 | MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver"); | 29 | MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver"); |
30 | MODULE_LICENSE("GPL"); | 30 | MODULE_LICENSE("GPL"); |
31 | 31 | ||
32 | /* controls */ | ||
33 | enum e_ctrl { | ||
34 | BRIGHTNESS, | ||
35 | CONTRAST, | ||
36 | COLORS, | ||
37 | LIGHTFREQ, | ||
38 | NCTRLS /* number of controls */ | ||
39 | }; | ||
40 | |||
41 | /* specific webcam descriptor */ | 32 | /* specific webcam descriptor */ |
42 | struct sd { | 33 | struct sd { |
43 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 34 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
44 | 35 | ||
45 | struct gspca_ctrl ctrls[NCTRLS]; | 36 | struct v4l2_ctrl *jpegqual; |
46 | |||
47 | u8 quality; | ||
48 | #define QUALITY_MIN 70 | 37 | #define QUALITY_MIN 70 |
49 | #define QUALITY_MAX 95 | 38 | #define QUALITY_MAX 95 |
50 | #define QUALITY_DEF 88 | 39 | #define QUALITY_DEF 88 |
@@ -52,63 +41,6 @@ struct sd { | |||
52 | u8 jpeg_hdr[JPEG_HDR_SZ]; | 41 | u8 jpeg_hdr[JPEG_HDR_SZ]; |
53 | }; | 42 | }; |
54 | 43 | ||
55 | /* V4L2 controls supported by the driver */ | ||
56 | static void setbrightness(struct gspca_dev *gspca_dev); | ||
57 | static void setcontrast(struct gspca_dev *gspca_dev); | ||
58 | static void setcolors(struct gspca_dev *gspca_dev); | ||
59 | static void setlightfreq(struct gspca_dev *gspca_dev); | ||
60 | |||
61 | static const struct ctrl sd_ctrls[NCTRLS] = { | ||
62 | [BRIGHTNESS] = { | ||
63 | { | ||
64 | .id = V4L2_CID_BRIGHTNESS, | ||
65 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
66 | .name = "Brightness", | ||
67 | .minimum = 0, | ||
68 | .maximum = 255, | ||
69 | .step = 1, | ||
70 | .default_value = 127, | ||
71 | }, | ||
72 | .set_control = setbrightness | ||
73 | }, | ||
74 | [CONTRAST] = { | ||
75 | { | ||
76 | .id = V4L2_CID_CONTRAST, | ||
77 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
78 | .name = "Contrast", | ||
79 | .minimum = 0, | ||
80 | .maximum = 255, | ||
81 | .step = 1, | ||
82 | .default_value = 127, | ||
83 | }, | ||
84 | .set_control = setcontrast | ||
85 | }, | ||
86 | [COLORS] = { | ||
87 | { | ||
88 | .id = V4L2_CID_SATURATION, | ||
89 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
90 | .name = "Color", | ||
91 | .minimum = 0, | ||
92 | .maximum = 255, | ||
93 | .step = 1, | ||
94 | .default_value = 127, | ||
95 | }, | ||
96 | .set_control = setcolors | ||
97 | }, | ||
98 | [LIGHTFREQ] = { | ||
99 | { | ||
100 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | ||
101 | .type = V4L2_CTRL_TYPE_MENU, | ||
102 | .name = "Light frequency filter", | ||
103 | .minimum = 1, | ||
104 | .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ | ||
105 | .step = 1, | ||
106 | .default_value = 1, | ||
107 | }, | ||
108 | .set_control = setlightfreq | ||
109 | }, | ||
110 | }; | ||
111 | |||
112 | static const struct v4l2_pix_format vga_mode[] = { | 44 | static const struct v4l2_pix_format vga_mode[] = { |
113 | {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 45 | {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, |
114 | .bytesperline = 320, | 46 | .bytesperline = 320, |
@@ -255,41 +187,36 @@ static void set_par(struct gspca_dev *gspca_dev, | |||
255 | snd_val(gspca_dev, 0x003f08, parval); | 187 | snd_val(gspca_dev, 0x003f08, parval); |
256 | } | 188 | } |
257 | 189 | ||
258 | static void setbrightness(struct gspca_dev *gspca_dev) | 190 | static void setbrightness(struct gspca_dev *gspca_dev, s32 val) |
259 | { | 191 | { |
260 | struct sd *sd = (struct sd *) gspca_dev; | ||
261 | int parval; | 192 | int parval; |
262 | 193 | ||
263 | parval = 0x06000000 /* whiteness */ | 194 | parval = 0x06000000 /* whiteness */ |
264 | + (sd->ctrls[BRIGHTNESS].val << 16); | 195 | + (val << 16); |
265 | set_par(gspca_dev, parval); | 196 | set_par(gspca_dev, parval); |
266 | } | 197 | } |
267 | 198 | ||
268 | static void setcontrast(struct gspca_dev *gspca_dev) | 199 | static void setcontrast(struct gspca_dev *gspca_dev, s32 val) |
269 | { | 200 | { |
270 | struct sd *sd = (struct sd *) gspca_dev; | ||
271 | int parval; | 201 | int parval; |
272 | 202 | ||
273 | parval = 0x07000000 /* contrast */ | 203 | parval = 0x07000000 /* contrast */ |
274 | + (sd->ctrls[CONTRAST].val << 16); | 204 | + (val << 16); |
275 | set_par(gspca_dev, parval); | 205 | set_par(gspca_dev, parval); |
276 | } | 206 | } |
277 | 207 | ||
278 | static void setcolors(struct gspca_dev *gspca_dev) | 208 | static void setcolors(struct gspca_dev *gspca_dev, s32 val) |
279 | { | 209 | { |
280 | struct sd *sd = (struct sd *) gspca_dev; | ||
281 | int parval; | 210 | int parval; |
282 | 211 | ||
283 | parval = 0x08000000 /* saturation */ | 212 | parval = 0x08000000 /* saturation */ |
284 | + (sd->ctrls[COLORS].val << 16); | 213 | + (val << 16); |
285 | set_par(gspca_dev, parval); | 214 | set_par(gspca_dev, parval); |
286 | } | 215 | } |
287 | 216 | ||
288 | static void setlightfreq(struct gspca_dev *gspca_dev) | 217 | static void setlightfreq(struct gspca_dev *gspca_dev, s32 val) |
289 | { | 218 | { |
290 | struct sd *sd = (struct sd *) gspca_dev; | 219 | set_par(gspca_dev, val == 1 |
291 | |||
292 | set_par(gspca_dev, sd->ctrls[LIGHTFREQ].val == 1 | ||
293 | ? 0x33640000 /* 50 Hz */ | 220 | ? 0x33640000 /* 50 Hz */ |
294 | : 0x33780000); /* 60 Hz */ | 221 | : 0x33780000); /* 60 Hz */ |
295 | } | 222 | } |
@@ -298,12 +225,8 @@ static void setlightfreq(struct gspca_dev *gspca_dev) | |||
298 | static int sd_config(struct gspca_dev *gspca_dev, | 225 | static int sd_config(struct gspca_dev *gspca_dev, |
299 | const struct usb_device_id *id) | 226 | const struct usb_device_id *id) |
300 | { | 227 | { |
301 | struct sd *sd = (struct sd *) gspca_dev; | ||
302 | |||
303 | gspca_dev->cam.cam_mode = vga_mode; | 228 | gspca_dev->cam.cam_mode = vga_mode; |
304 | gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode); | 229 | gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode); |
305 | gspca_dev->cam.ctrls = sd->ctrls; | ||
306 | sd->quality = QUALITY_DEF; | ||
307 | return 0; | 230 | return 0; |
308 | } | 231 | } |
309 | 232 | ||
@@ -333,7 +256,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
333 | /* create the JPEG header */ | 256 | /* create the JPEG header */ |
334 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, | 257 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, |
335 | 0x22); /* JPEG 411 */ | 258 | 0x22); /* JPEG 411 */ |
336 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | ||
337 | 259 | ||
338 | /* work on alternate 1 */ | 260 | /* work on alternate 1 */ |
339 | usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); | 261 | usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1); |
@@ -365,14 +287,11 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
365 | reg_w(gspca_dev, 0x0640, 0); | 287 | reg_w(gspca_dev, 0x0640, 0); |
366 | reg_w(gspca_dev, 0x0650, 0); | 288 | reg_w(gspca_dev, 0x0650, 0); |
367 | reg_w(gspca_dev, 0x0660, 0); | 289 | reg_w(gspca_dev, 0x0660, 0); |
368 | setbrightness(gspca_dev); /* whiteness */ | 290 | v4l2_ctrl_handler_setup(&gspca_dev->ctrl_handler); |
369 | setcontrast(gspca_dev); /* contrast */ | ||
370 | setcolors(gspca_dev); /* saturation */ | ||
371 | set_par(gspca_dev, 0x09800000); /* Red ? */ | 291 | set_par(gspca_dev, 0x09800000); /* Red ? */ |
372 | set_par(gspca_dev, 0x0a800000); /* Green ? */ | 292 | set_par(gspca_dev, 0x0a800000); /* Green ? */ |
373 | set_par(gspca_dev, 0x0b800000); /* Blue ? */ | 293 | set_par(gspca_dev, 0x0b800000); /* Blue ? */ |
374 | set_par(gspca_dev, 0x0d030000); /* Gamma ? */ | 294 | set_par(gspca_dev, 0x0d030000); /* Gamma ? */ |
375 | setlightfreq(gspca_dev); | ||
376 | 295 | ||
377 | /* start the video flow */ | 296 | /* start the video flow */ |
378 | set_par(gspca_dev, 0x01000000); | 297 | set_par(gspca_dev, 0x01000000); |
@@ -435,34 +354,12 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
435 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | 354 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
436 | } | 355 | } |
437 | 356 | ||
438 | static int sd_querymenu(struct gspca_dev *gspca_dev, | ||
439 | struct v4l2_querymenu *menu) | ||
440 | { | ||
441 | static const char *freq_nm[3] = {"NoFliker", "50 Hz", "60 Hz"}; | ||
442 | |||
443 | switch (menu->id) { | ||
444 | case V4L2_CID_POWER_LINE_FREQUENCY: | ||
445 | if ((unsigned) menu->index >= ARRAY_SIZE(freq_nm)) | ||
446 | break; | ||
447 | strcpy((char *) menu->name, freq_nm[menu->index]); | ||
448 | return 0; | ||
449 | } | ||
450 | return -EINVAL; | ||
451 | } | ||
452 | |||
453 | static int sd_set_jcomp(struct gspca_dev *gspca_dev, | 357 | static int sd_set_jcomp(struct gspca_dev *gspca_dev, |
454 | struct v4l2_jpegcompression *jcomp) | 358 | struct v4l2_jpegcompression *jcomp) |
455 | { | 359 | { |
456 | struct sd *sd = (struct sd *) gspca_dev; | 360 | struct sd *sd = (struct sd *) gspca_dev; |
457 | 361 | ||
458 | if (jcomp->quality < QUALITY_MIN) | 362 | v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality); |
459 | sd->quality = QUALITY_MIN; | ||
460 | else if (jcomp->quality > QUALITY_MAX) | ||
461 | sd->quality = QUALITY_MAX; | ||
462 | else | ||
463 | sd->quality = jcomp->quality; | ||
464 | if (gspca_dev->streaming) | ||
465 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | ||
466 | return gspca_dev->usb_err; | 363 | return gspca_dev->usb_err; |
467 | } | 364 | } |
468 | 365 | ||
@@ -472,23 +369,84 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev, | |||
472 | struct sd *sd = (struct sd *) gspca_dev; | 369 | struct sd *sd = (struct sd *) gspca_dev; |
473 | 370 | ||
474 | memset(jcomp, 0, sizeof *jcomp); | 371 | memset(jcomp, 0, sizeof *jcomp); |
475 | jcomp->quality = sd->quality; | 372 | jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual); |
476 | jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT | 373 | jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT |
477 | | V4L2_JPEG_MARKER_DQT; | 374 | | V4L2_JPEG_MARKER_DQT; |
478 | return 0; | 375 | return 0; |
479 | } | 376 | } |
480 | 377 | ||
378 | static int sd_s_ctrl(struct v4l2_ctrl *ctrl) | ||
379 | { | ||
380 | struct gspca_dev *gspca_dev = | ||
381 | container_of(ctrl->handler, struct gspca_dev, ctrl_handler); | ||
382 | struct sd *sd = (struct sd *)gspca_dev; | ||
383 | |||
384 | gspca_dev->usb_err = 0; | ||
385 | |||
386 | if (!gspca_dev->streaming) | ||
387 | return 0; | ||
388 | |||
389 | switch (ctrl->id) { | ||
390 | case V4L2_CID_BRIGHTNESS: | ||
391 | setbrightness(gspca_dev, ctrl->val); | ||
392 | break; | ||
393 | case V4L2_CID_CONTRAST: | ||
394 | setcontrast(gspca_dev, ctrl->val); | ||
395 | break; | ||
396 | case V4L2_CID_SATURATION: | ||
397 | setcolors(gspca_dev, ctrl->val); | ||
398 | break; | ||
399 | case V4L2_CID_POWER_LINE_FREQUENCY: | ||
400 | setlightfreq(gspca_dev, ctrl->val); | ||
401 | break; | ||
402 | case V4L2_CID_JPEG_COMPRESSION_QUALITY: | ||
403 | jpeg_set_qual(sd->jpeg_hdr, ctrl->val); | ||
404 | break; | ||
405 | } | ||
406 | return gspca_dev->usb_err; | ||
407 | } | ||
408 | |||
409 | static const struct v4l2_ctrl_ops sd_ctrl_ops = { | ||
410 | .s_ctrl = sd_s_ctrl, | ||
411 | }; | ||
412 | |||
413 | static int sd_init_controls(struct gspca_dev *gspca_dev) | ||
414 | { | ||
415 | struct sd *sd = (struct sd *)gspca_dev; | ||
416 | struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; | ||
417 | |||
418 | gspca_dev->vdev.ctrl_handler = hdl; | ||
419 | v4l2_ctrl_handler_init(hdl, 5); | ||
420 | v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
421 | V4L2_CID_BRIGHTNESS, 0, 255, 1, 127); | ||
422 | v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
423 | V4L2_CID_CONTRAST, 0, 255, 1, 127); | ||
424 | v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
425 | V4L2_CID_SATURATION, 0, 255, 1, 127); | ||
426 | v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops, | ||
427 | V4L2_CID_POWER_LINE_FREQUENCY, | ||
428 | V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 1, | ||
429 | V4L2_CID_POWER_LINE_FREQUENCY_50HZ); | ||
430 | sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
431 | V4L2_CID_JPEG_COMPRESSION_QUALITY, | ||
432 | QUALITY_MIN, QUALITY_MAX, 1, QUALITY_DEF); | ||
433 | |||
434 | if (hdl->error) { | ||
435 | pr_err("Could not initialize controls\n"); | ||
436 | return hdl->error; | ||
437 | } | ||
438 | return 0; | ||
439 | } | ||
440 | |||
481 | /* sub-driver description */ | 441 | /* sub-driver description */ |
482 | static const struct sd_desc sd_desc = { | 442 | static const struct sd_desc sd_desc = { |
483 | .name = MODULE_NAME, | 443 | .name = MODULE_NAME, |
484 | .ctrls = sd_ctrls, | ||
485 | .nctrls = NCTRLS, | ||
486 | .config = sd_config, | 444 | .config = sd_config, |
487 | .init = sd_init, | 445 | .init = sd_init, |
446 | .init_controls = sd_init_controls, | ||
488 | .start = sd_start, | 447 | .start = sd_start, |
489 | .stopN = sd_stopN, | 448 | .stopN = sd_stopN, |
490 | .pkt_scan = sd_pkt_scan, | 449 | .pkt_scan = sd_pkt_scan, |
491 | .querymenu = sd_querymenu, | ||
492 | .get_jcomp = sd_get_jcomp, | 450 | .get_jcomp = sd_get_jcomp, |
493 | .set_jcomp = sd_set_jcomp, | 451 | .set_jcomp = sd_set_jcomp, |
494 | }; | 452 | }; |