aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2012-05-06 08:28:31 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-05-14 08:38:56 -0400
commit98684298f9ed89554cdaa4afe2554fca8276d1e9 (patch)
treeed5d660a42b3cf758217445fb25aca40ded1e45a
parentd67a1adaea29da942291145fa3964a453e017274 (diff)
[media] gspca_mars: 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/mars.c292
1 files changed, 126 insertions, 166 deletions
diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c
index b0231465afae..2950347b8265 100644
--- a/drivers/media/video/gspca/mars.c
+++ b/drivers/media/video/gspca/mars.c
@@ -30,22 +30,20 @@ MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
30MODULE_DESCRIPTION("GSPCA/Mars USB Camera Driver"); 30MODULE_DESCRIPTION("GSPCA/Mars USB Camera Driver");
31MODULE_LICENSE("GPL"); 31MODULE_LICENSE("GPL");
32 32
33/* controls */
34enum e_ctrl {
35 BRIGHTNESS,
36 COLORS,
37 GAMMA,
38 SHARPNESS,
39 ILLUM_TOP,
40 ILLUM_BOT,
41 NCTRLS /* number of controls */
42};
43
44/* specific webcam descriptor */ 33/* specific webcam descriptor */
45struct sd { 34struct sd {
46 struct gspca_dev gspca_dev; /* !! must be the first item */ 35 struct gspca_dev gspca_dev; /* !! must be the first item */
47 36
48 struct gspca_ctrl ctrls[NCTRLS]; 37 struct v4l2_ctrl_handler ctrl_handler;
38 struct v4l2_ctrl *brightness;
39 struct v4l2_ctrl *saturation;
40 struct v4l2_ctrl *sharpness;
41 struct v4l2_ctrl *gamma;
42 struct { /* illuminator control cluster */
43 struct v4l2_ctrl *illum_top;
44 struct v4l2_ctrl *illum_bottom;
45 };
46 struct v4l2_ctrl *jpegqual;
49 47
50 u8 quality; 48 u8 quality;
51#define QUALITY_MIN 40 49#define QUALITY_MIN 40
@@ -56,89 +54,10 @@ struct sd {
56}; 54};
57 55
58/* V4L2 controls supported by the driver */ 56/* V4L2 controls supported by the driver */
59static void setbrightness(struct gspca_dev *gspca_dev); 57static void setbrightness(struct gspca_dev *gspca_dev, s32 val);
60static void setcolors(struct gspca_dev *gspca_dev); 58static void setcolors(struct gspca_dev *gspca_dev, s32 val);
61static void setgamma(struct gspca_dev *gspca_dev); 59static void setgamma(struct gspca_dev *gspca_dev, s32 val);
62static void setsharpness(struct gspca_dev *gspca_dev); 60static void setsharpness(struct gspca_dev *gspca_dev, s32 val);
63static int sd_setilluminator1(struct gspca_dev *gspca_dev, __s32 val);
64static int sd_setilluminator2(struct gspca_dev *gspca_dev, __s32 val);
65
66static const struct ctrl sd_ctrls[NCTRLS] = {
67[BRIGHTNESS] = {
68 {
69 .id = V4L2_CID_BRIGHTNESS,
70 .type = V4L2_CTRL_TYPE_INTEGER,
71 .name = "Brightness",
72 .minimum = 0,
73 .maximum = 30,
74 .step = 1,
75 .default_value = 15,
76 },
77 .set_control = setbrightness
78 },
79[COLORS] = {
80 {
81 .id = V4L2_CID_SATURATION,
82 .type = V4L2_CTRL_TYPE_INTEGER,
83 .name = "Color",
84 .minimum = 1,
85 .maximum = 255,
86 .step = 1,
87 .default_value = 200,
88 },
89 .set_control = setcolors
90 },
91[GAMMA] = {
92 {
93 .id = V4L2_CID_GAMMA,
94 .type = V4L2_CTRL_TYPE_INTEGER,
95 .name = "Gamma",
96 .minimum = 0,
97 .maximum = 3,
98 .step = 1,
99 .default_value = 1,
100 },
101 .set_control = setgamma
102 },
103[SHARPNESS] = {
104 {
105 .id = V4L2_CID_SHARPNESS,
106 .type = V4L2_CTRL_TYPE_INTEGER,
107 .name = "Sharpness",
108 .minimum = 0,
109 .maximum = 2,
110 .step = 1,
111 .default_value = 1,
112 },
113 .set_control = setsharpness
114 },
115[ILLUM_TOP] = {
116 {
117 .id = V4L2_CID_ILLUMINATORS_1,
118 .type = V4L2_CTRL_TYPE_BOOLEAN,
119 .name = "Top illuminator",
120 .minimum = 0,
121 .maximum = 1,
122 .step = 1,
123 .default_value = 0,
124 .flags = V4L2_CTRL_FLAG_UPDATE,
125 },
126 .set = sd_setilluminator1
127 },
128[ILLUM_BOT] = {
129 {
130 .id = V4L2_CID_ILLUMINATORS_2,
131 .type = V4L2_CTRL_TYPE_BOOLEAN,
132 .name = "Bottom illuminator",
133 .minimum = 0,
134 .maximum = 1,
135 .step = 1,
136 .default_value = 0,
137 .flags = V4L2_CTRL_FLAG_UPDATE,
138 },
139 .set = sd_setilluminator2
140 },
141};
142 61
143static const struct v4l2_pix_format vga_mode[] = { 62static const struct v4l2_pix_format vga_mode[] = {
144 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 63 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
@@ -198,59 +117,129 @@ static void mi_w(struct gspca_dev *gspca_dev,
198 reg_w(gspca_dev, 4); 117 reg_w(gspca_dev, 4);
199} 118}
200 119
201static void setbrightness(struct gspca_dev *gspca_dev) 120static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
202{ 121{
203 struct sd *sd = (struct sd *) gspca_dev;
204
205 gspca_dev->usb_buf[0] = 0x61; 122 gspca_dev->usb_buf[0] = 0x61;
206 gspca_dev->usb_buf[1] = sd->ctrls[BRIGHTNESS].val; 123 gspca_dev->usb_buf[1] = val;
207 reg_w(gspca_dev, 2); 124 reg_w(gspca_dev, 2);
208} 125}
209 126
210static void setcolors(struct gspca_dev *gspca_dev) 127static void setcolors(struct gspca_dev *gspca_dev, s32 val)
211{ 128{
212 struct sd *sd = (struct sd *) gspca_dev;
213 s16 val;
214
215 val = sd->ctrls[COLORS].val;
216 gspca_dev->usb_buf[0] = 0x5f; 129 gspca_dev->usb_buf[0] = 0x5f;
217 gspca_dev->usb_buf[1] = val << 3; 130 gspca_dev->usb_buf[1] = val << 3;
218 gspca_dev->usb_buf[2] = ((val >> 2) & 0xf8) | 0x04; 131 gspca_dev->usb_buf[2] = ((val >> 2) & 0xf8) | 0x04;
219 reg_w(gspca_dev, 3); 132 reg_w(gspca_dev, 3);
220} 133}
221 134
222static void setgamma(struct gspca_dev *gspca_dev) 135static void setgamma(struct gspca_dev *gspca_dev, s32 val)
223{ 136{
224 struct sd *sd = (struct sd *) gspca_dev;
225
226 gspca_dev->usb_buf[0] = 0x06; 137 gspca_dev->usb_buf[0] = 0x06;
227 gspca_dev->usb_buf[1] = sd->ctrls[GAMMA].val * 0x40; 138 gspca_dev->usb_buf[1] = val * 0x40;
228 reg_w(gspca_dev, 2); 139 reg_w(gspca_dev, 2);
229} 140}
230 141
231static void setsharpness(struct gspca_dev *gspca_dev) 142static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
232{ 143{
233 struct sd *sd = (struct sd *) gspca_dev;
234
235 gspca_dev->usb_buf[0] = 0x67; 144 gspca_dev->usb_buf[0] = 0x67;
236 gspca_dev->usb_buf[1] = sd->ctrls[SHARPNESS].val * 4 + 3; 145 gspca_dev->usb_buf[1] = val * 4 + 3;
237 reg_w(gspca_dev, 2); 146 reg_w(gspca_dev, 2);
238} 147}
239 148
240static void setilluminators(struct gspca_dev *gspca_dev) 149static void setilluminators(struct gspca_dev *gspca_dev, bool top, bool bottom)
241{ 150{
242 struct sd *sd = (struct sd *) gspca_dev; 151 /* both are off if not streaming */
243
244 gspca_dev->usb_buf[0] = 0x22; 152 gspca_dev->usb_buf[0] = 0x22;
245 if (sd->ctrls[ILLUM_TOP].val) 153 if (top)
246 gspca_dev->usb_buf[1] = 0x76; 154 gspca_dev->usb_buf[1] = 0x76;
247 else if (sd->ctrls[ILLUM_BOT].val) 155 else if (bottom)
248 gspca_dev->usb_buf[1] = 0x7a; 156 gspca_dev->usb_buf[1] = 0x7a;
249 else 157 else
250 gspca_dev->usb_buf[1] = 0x7e; 158 gspca_dev->usb_buf[1] = 0x7e;
251 reg_w(gspca_dev, 2); 159 reg_w(gspca_dev, 2);
252} 160}
253 161
162static int mars_s_ctrl(struct v4l2_ctrl *ctrl)
163{
164 struct sd *sd = container_of(ctrl->handler, struct sd, ctrl_handler);
165 struct gspca_dev *gspca_dev = &sd->gspca_dev;
166
167 gspca_dev->usb_err = 0;
168
169 if (ctrl->id == V4L2_CID_ILLUMINATORS_1) {
170 /* only one can be on at a time */
171 if (ctrl->is_new && ctrl->val)
172 sd->illum_bottom->val = 0;
173 if (sd->illum_bottom->is_new && sd->illum_bottom->val)
174 sd->illum_top->val = 0;
175 }
176
177 if (!gspca_dev->streaming)
178 return 0;
179
180 switch (ctrl->id) {
181 case V4L2_CID_BRIGHTNESS:
182 setbrightness(&sd->gspca_dev, ctrl->val);
183 break;
184 case V4L2_CID_SATURATION:
185 setcolors(&sd->gspca_dev, ctrl->val);
186 break;
187 case V4L2_CID_GAMMA:
188 setgamma(&sd->gspca_dev, ctrl->val);
189 break;
190 case V4L2_CID_ILLUMINATORS_1:
191 setilluminators(&sd->gspca_dev, sd->illum_top->val,
192 sd->illum_bottom->val);
193 break;
194 case V4L2_CID_SHARPNESS:
195 setsharpness(&sd->gspca_dev, ctrl->val);
196 break;
197 case V4L2_CID_JPEG_COMPRESSION_QUALITY:
198 jpeg_set_qual(sd->jpeg_hdr, ctrl->val);
199 break;
200 default:
201 return -EINVAL;
202 }
203 return gspca_dev->usb_err;
204}
205
206static const struct v4l2_ctrl_ops mars_ctrl_ops = {
207 .s_ctrl = mars_s_ctrl,
208};
209
210/* this function is called at probe time */
211static int sd_init_controls(struct gspca_dev *gspca_dev)
212{
213 struct sd *sd = (struct sd *) gspca_dev;
214 struct v4l2_ctrl_handler *hdl = &sd->ctrl_handler;
215
216 gspca_dev->vdev.ctrl_handler = hdl;
217 v4l2_ctrl_handler_init(hdl, 7);
218 sd->brightness = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
219 V4L2_CID_BRIGHTNESS, 0, 30, 1, 15);
220 sd->saturation = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
221 V4L2_CID_SATURATION, 0, 255, 1, 200);
222 sd->gamma = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
223 V4L2_CID_GAMMA, 0, 3, 1, 1);
224 sd->sharpness = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
225 V4L2_CID_SHARPNESS, 0, 2, 1, 1);
226 sd->illum_top = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
227 V4L2_CID_ILLUMINATORS_1, 0, 1, 1, 0);
228 sd->illum_top->flags |= V4L2_CTRL_FLAG_UPDATE;
229 sd->illum_bottom = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
230 V4L2_CID_ILLUMINATORS_2, 0, 1, 1, 0);
231 sd->illum_bottom->flags |= V4L2_CTRL_FLAG_UPDATE;
232 sd->jpegqual = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
233 V4L2_CID_JPEG_COMPRESSION_QUALITY,
234 QUALITY_MIN, QUALITY_MAX, 1, QUALITY_DEF);
235 if (hdl->error) {
236 pr_err("Could not initialize controls\n");
237 return hdl->error;
238 }
239 v4l2_ctrl_cluster(2, &sd->illum_top);
240 return 0;
241}
242
254/* this function is called at probe time */ 243/* this function is called at probe time */
255static int sd_config(struct gspca_dev *gspca_dev, 244static int sd_config(struct gspca_dev *gspca_dev,
256 const struct usb_device_id *id) 245 const struct usb_device_id *id)
@@ -261,7 +250,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
261 cam = &gspca_dev->cam; 250 cam = &gspca_dev->cam;
262 cam->cam_mode = vga_mode; 251 cam->cam_mode = vga_mode;
263 cam->nmodes = ARRAY_SIZE(vga_mode); 252 cam->nmodes = ARRAY_SIZE(vga_mode);
264 cam->ctrls = sd->ctrls;
265 sd->quality = QUALITY_DEF; 253 sd->quality = QUALITY_DEF;
266 return 0; 254 return 0;
267} 255}
@@ -269,7 +257,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
269/* this function is called at probe and resume time */ 257/* this function is called at probe and resume time */
270static int sd_init(struct gspca_dev *gspca_dev) 258static int sd_init(struct gspca_dev *gspca_dev)
271{ 259{
272 gspca_dev->ctrl_inac = (1 << ILLUM_TOP) | (1 << ILLUM_BOT);
273 return 0; 260 return 0;
274} 261}
275 262
@@ -282,7 +269,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
282 /* create the JPEG header */ 269 /* create the JPEG header */
283 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, 270 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
284 0x21); /* JPEG 422 */ 271 0x21); /* JPEG 422 */
285 jpeg_set_qual(sd->jpeg_hdr, sd->quality); 272 jpeg_set_qual(sd->jpeg_hdr, v4l2_ctrl_g_ctrl(sd->jpegqual));
286 273
287 data = gspca_dev->usb_buf; 274 data = gspca_dev->usb_buf;
288 275
@@ -301,7 +288,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
301 data[5] = 0x30; /* reg 4, MI, PAS5101 : 288 data[5] = 0x30; /* reg 4, MI, PAS5101 :
302 * 0x30 for 24mhz , 0x28 for 12mhz */ 289 * 0x30 for 24mhz , 0x28 for 12mhz */
303 data[6] = 0x02; /* reg 5, H start - was 0x04 */ 290 data[6] = 0x02; /* reg 5, H start - was 0x04 */
304 data[7] = sd->ctrls[GAMMA].val * 0x40; /* reg 0x06: gamma */ 291 data[7] = v4l2_ctrl_g_ctrl(sd->gamma) * 0x40; /* reg 0x06: gamma */
305 data[8] = 0x01; /* reg 7, V start - was 0x03 */ 292 data[8] = 0x01; /* reg 7, V start - was 0x03 */
306/* if (h_size == 320 ) */ 293/* if (h_size == 320 ) */
307/* data[9]= 0x56; * reg 8, 24MHz, 2:1 scale down */ 294/* data[9]= 0x56; * reg 8, 24MHz, 2:1 scale down */
@@ -333,16 +320,16 @@ static int sd_start(struct gspca_dev *gspca_dev)
333 /* reg 0x5f/0x60 (LE) = saturation */ 320 /* reg 0x5f/0x60 (LE) = saturation */
334 /* h (60): xxxx x100 321 /* h (60): xxxx x100
335 * l (5f): xxxx x000 */ 322 * l (5f): xxxx x000 */
336 data[2] = sd->ctrls[COLORS].val << 3; 323 data[2] = v4l2_ctrl_g_ctrl(sd->saturation) << 3;
337 data[3] = ((sd->ctrls[COLORS].val >> 2) & 0xf8) | 0x04; 324 data[3] = ((v4l2_ctrl_g_ctrl(sd->saturation) >> 2) & 0xf8) | 0x04;
338 data[4] = sd->ctrls[BRIGHTNESS].val; /* reg 0x61 = brightness */ 325 data[4] = v4l2_ctrl_g_ctrl(sd->brightness); /* reg 0x61 = brightness */
339 data[5] = 0x00; 326 data[5] = 0x00;
340 327
341 reg_w(gspca_dev, 6); 328 reg_w(gspca_dev, 6);
342 329
343 data[0] = 0x67; 330 data[0] = 0x67;
344/*jfm: from win trace*/ 331/*jfm: from win trace*/
345 data[1] = sd->ctrls[SHARPNESS].val * 4 + 3; 332 data[1] = v4l2_ctrl_g_ctrl(sd->sharpness) * 4 + 3;
346 data[2] = 0x14; 333 data[2] = 0x14;
347 reg_w(gspca_dev, 3); 334 reg_w(gspca_dev, 3);
348 335
@@ -365,7 +352,9 @@ static int sd_start(struct gspca_dev *gspca_dev)
365 data[1] = 0x4d; /* ISOC transferring enable... */ 352 data[1] = 0x4d; /* ISOC transferring enable... */
366 reg_w(gspca_dev, 2); 353 reg_w(gspca_dev, 2);
367 354
368 gspca_dev->ctrl_inac = 0; /* activate the illuminator controls */ 355 setilluminators(gspca_dev, v4l2_ctrl_g_ctrl(sd->illum_top),
356 v4l2_ctrl_g_ctrl(sd->illum_bottom));
357
369 return gspca_dev->usb_err; 358 return gspca_dev->usb_err;
370} 359}
371 360
@@ -373,11 +362,9 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
373{ 362{
374 struct sd *sd = (struct sd *) gspca_dev; 363 struct sd *sd = (struct sd *) gspca_dev;
375 364
376 gspca_dev->ctrl_inac = (1 << ILLUM_TOP) | (1 << ILLUM_BOT); 365 if (v4l2_ctrl_g_ctrl(sd->illum_top) ||
377 if (sd->ctrls[ILLUM_TOP].val || sd->ctrls[ILLUM_BOT].val) { 366 v4l2_ctrl_g_ctrl(sd->illum_bottom)) {
378 sd->ctrls[ILLUM_TOP].val = 0; 367 setilluminators(gspca_dev, false, false);
379 sd->ctrls[ILLUM_BOT].val = 0;
380 setilluminators(gspca_dev);
381 msleep(20); 368 msleep(20);
382 } 369 }
383 370
@@ -424,43 +411,16 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
424 gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 411 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
425} 412}
426 413
427static int sd_setilluminator1(struct gspca_dev *gspca_dev, __s32 val)
428{
429 struct sd *sd = (struct sd *) gspca_dev;
430
431 /* only one illuminator may be on */
432 sd->ctrls[ILLUM_TOP].val = val;
433 if (val)
434 sd->ctrls[ILLUM_BOT].val = 0;
435 setilluminators(gspca_dev);
436 return gspca_dev->usb_err;
437}
438
439static int sd_setilluminator2(struct gspca_dev *gspca_dev, __s32 val)
440{
441 struct sd *sd = (struct sd *) gspca_dev;
442
443 /* only one illuminator may be on */
444 sd->ctrls[ILLUM_BOT].val = val;
445 if (val)
446 sd->ctrls[ILLUM_TOP].val = 0;
447 setilluminators(gspca_dev);
448 return gspca_dev->usb_err;
449}
450
451static int sd_set_jcomp(struct gspca_dev *gspca_dev, 414static int sd_set_jcomp(struct gspca_dev *gspca_dev,
452 struct v4l2_jpegcompression *jcomp) 415 struct v4l2_jpegcompression *jcomp)
453{ 416{
454 struct sd *sd = (struct sd *) gspca_dev; 417 struct sd *sd = (struct sd *) gspca_dev;
418 int ret;
455 419
456 if (jcomp->quality < QUALITY_MIN) 420 ret = v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);
457 sd->quality = QUALITY_MIN; 421 if (ret)
458 else if (jcomp->quality > QUALITY_MAX) 422 return ret;
459 sd->quality = QUALITY_MAX; 423 jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
460 else
461 sd->quality = jcomp->quality;
462 if (gspca_dev->streaming)
463 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
464 return 0; 424 return 0;
465} 425}
466 426
@@ -470,7 +430,7 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev,
470 struct sd *sd = (struct sd *) gspca_dev; 430 struct sd *sd = (struct sd *) gspca_dev;
471 431
472 memset(jcomp, 0, sizeof *jcomp); 432 memset(jcomp, 0, sizeof *jcomp);
473 jcomp->quality = sd->quality; 433 jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
474 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT 434 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
475 | V4L2_JPEG_MARKER_DQT; 435 | V4L2_JPEG_MARKER_DQT;
476 return 0; 436 return 0;
@@ -479,10 +439,9 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev,
479/* sub-driver description */ 439/* sub-driver description */
480static const struct sd_desc sd_desc = { 440static const struct sd_desc sd_desc = {
481 .name = MODULE_NAME, 441 .name = MODULE_NAME,
482 .ctrls = sd_ctrls,
483 .nctrls = NCTRLS,
484 .config = sd_config, 442 .config = sd_config,
485 .init = sd_init, 443 .init = sd_init,
444 .init_controls = sd_init_controls,
486 .start = sd_start, 445 .start = sd_start,
487 .stopN = sd_stopN, 446 .stopN = sd_stopN,
488 .pkt_scan = sd_pkt_scan, 447 .pkt_scan = sd_pkt_scan,
@@ -513,6 +472,7 @@ static struct usb_driver sd_driver = {
513#ifdef CONFIG_PM 472#ifdef CONFIG_PM
514 .suspend = gspca_suspend, 473 .suspend = gspca_suspend,
515 .resume = gspca_resume, 474 .resume = gspca_resume,
475 .reset_resume = gspca_resume,
516#endif 476#endif
517}; 477};
518 478