diff options
author | Jean-François Moine <moinejf@free.fr> | 2010-12-28 05:35:27 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-12-29 05:17:21 -0500 |
commit | 71e84ea7f082eb02df6ef40f55d2c4a998f6e1df (patch) | |
tree | edc34673c011101d2aea32fed146e954e43fa3ae /drivers/media | |
parent | 7e5f9059a807ce9b7a12b2402f5aeae9557c8049 (diff) |
[media] gspca - stv06xx/st6422: Use the new video control mechanism
Signed-off-by: Jean-François Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/gspca/stv06xx/stv06xx_st6422.c | 272 | ||||
-rw-r--r-- | drivers/media/video/gspca/stv06xx/stv06xx_st6422.h | 10 |
2 files changed, 118 insertions, 164 deletions
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c index 42f3a1e41188..8a456de4970a 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c | |||
@@ -28,6 +28,20 @@ | |||
28 | 28 | ||
29 | #include "stv06xx_st6422.h" | 29 | #include "stv06xx_st6422.h" |
30 | 30 | ||
31 | /* controls */ | ||
32 | enum e_ctrl { | ||
33 | BRIGHTNESS, | ||
34 | CONTRAST, | ||
35 | GAIN, | ||
36 | EXPOSURE, | ||
37 | NCTRLS /* number of controls */ | ||
38 | }; | ||
39 | |||
40 | /* sensor settings */ | ||
41 | struct st6422_settings { | ||
42 | struct gspca_ctrl ctrls[NCTRLS]; | ||
43 | }; | ||
44 | |||
31 | static struct v4l2_pix_format st6422_mode[] = { | 45 | static struct v4l2_pix_format st6422_mode[] = { |
32 | /* Note we actually get 124 lines of data, of which we skip the 4st | 46 | /* Note we actually get 124 lines of data, of which we skip the 4st |
33 | 4 as they are garbage */ | 47 | 4 as they are garbage */ |
@@ -57,9 +71,14 @@ static struct v4l2_pix_format st6422_mode[] = { | |||
57 | }, | 71 | }, |
58 | }; | 72 | }; |
59 | 73 | ||
60 | static const struct ctrl st6422_ctrl[] = { | 74 | /* V4L2 controls supported by the driver */ |
61 | #define BRIGHTNESS_IDX 0 | 75 | static void st6422_set_brightness(struct gspca_dev *gspca_dev); |
62 | { | 76 | static void st6422_set_contrast(struct gspca_dev *gspca_dev); |
77 | static void st6422_set_gain(struct gspca_dev *gspca_dev); | ||
78 | static void st6422_set_exposure(struct gspca_dev *gspca_dev); | ||
79 | |||
80 | static const struct ctrl st6422_ctrl[NCTRLS] = { | ||
81 | [BRIGHTNESS] = { | ||
63 | { | 82 | { |
64 | .id = V4L2_CID_BRIGHTNESS, | 83 | .id = V4L2_CID_BRIGHTNESS, |
65 | .type = V4L2_CTRL_TYPE_INTEGER, | 84 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -69,11 +88,9 @@ static const struct ctrl st6422_ctrl[] = { | |||
69 | .step = 1, | 88 | .step = 1, |
70 | .default_value = 3 | 89 | .default_value = 3 |
71 | }, | 90 | }, |
72 | .set = st6422_set_brightness, | 91 | .set_control = st6422_set_brightness |
73 | .get = st6422_get_brightness | ||
74 | }, | 92 | }, |
75 | #define CONTRAST_IDX 1 | 93 | [CONTRAST] = { |
76 | { | ||
77 | { | 94 | { |
78 | .id = V4L2_CID_CONTRAST, | 95 | .id = V4L2_CID_CONTRAST, |
79 | .type = V4L2_CTRL_TYPE_INTEGER, | 96 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -83,11 +100,9 @@ static const struct ctrl st6422_ctrl[] = { | |||
83 | .step = 1, | 100 | .step = 1, |
84 | .default_value = 11 | 101 | .default_value = 11 |
85 | }, | 102 | }, |
86 | .set = st6422_set_contrast, | 103 | .set_control = st6422_set_contrast |
87 | .get = st6422_get_contrast | ||
88 | }, | 104 | }, |
89 | #define GAIN_IDX 2 | 105 | [GAIN] = { |
90 | { | ||
91 | { | 106 | { |
92 | .id = V4L2_CID_GAIN, | 107 | .id = V4L2_CID_GAIN, |
93 | .type = V4L2_CTRL_TYPE_INTEGER, | 108 | .type = V4L2_CTRL_TYPE_INTEGER, |
@@ -97,49 +112,43 @@ static const struct ctrl st6422_ctrl[] = { | |||
97 | .step = 1, | 112 | .step = 1, |
98 | .default_value = 64 | 113 | .default_value = 64 |
99 | }, | 114 | }, |
100 | .set = st6422_set_gain, | 115 | .set_control = st6422_set_gain |
101 | .get = st6422_get_gain | ||
102 | }, | 116 | }, |
103 | #define EXPOSURE_IDX 3 | 117 | [EXPOSURE] = { |
104 | { | ||
105 | { | 118 | { |
106 | .id = V4L2_CID_EXPOSURE, | 119 | .id = V4L2_CID_EXPOSURE, |
107 | .type = V4L2_CTRL_TYPE_INTEGER, | 120 | .type = V4L2_CTRL_TYPE_INTEGER, |
108 | .name = "Exposure", | 121 | .name = "Exposure", |
109 | .minimum = 0, | 122 | .minimum = 0, |
110 | .maximum = 1023, | 123 | #define EXPOSURE_MAX 1023 |
124 | .maximum = EXPOSURE_MAX, | ||
111 | .step = 1, | 125 | .step = 1, |
112 | .default_value = 256 | 126 | .default_value = 256 |
113 | }, | 127 | }, |
114 | .set = st6422_set_exposure, | 128 | .set_control = st6422_set_exposure |
115 | .get = st6422_get_exposure | ||
116 | }, | 129 | }, |
117 | }; | 130 | }; |
118 | 131 | ||
119 | static int st6422_probe(struct sd *sd) | 132 | static int st6422_probe(struct sd *sd) |
120 | { | 133 | { |
121 | int i; | 134 | struct st6422_settings *sensor_settings; |
122 | s32 *sensor_settings; | ||
123 | 135 | ||
124 | if (sd->bridge != BRIDGE_ST6422) | 136 | if (sd->bridge != BRIDGE_ST6422) |
125 | return -ENODEV; | 137 | return -ENODEV; |
126 | 138 | ||
127 | info("st6422 sensor detected"); | 139 | info("st6422 sensor detected"); |
128 | 140 | ||
129 | sensor_settings = kmalloc(ARRAY_SIZE(st6422_ctrl) * sizeof(s32), | 141 | sensor_settings = kmalloc(sizeof *sensor_settings, GFP_KERNEL); |
130 | GFP_KERNEL); | ||
131 | if (!sensor_settings) | 142 | if (!sensor_settings) |
132 | return -ENOMEM; | 143 | return -ENOMEM; |
133 | 144 | ||
134 | sd->gspca_dev.cam.cam_mode = st6422_mode; | 145 | sd->gspca_dev.cam.cam_mode = st6422_mode; |
135 | sd->gspca_dev.cam.nmodes = ARRAY_SIZE(st6422_mode); | 146 | sd->gspca_dev.cam.nmodes = ARRAY_SIZE(st6422_mode); |
147 | sd->gspca_dev.cam.ctrls = sensor_settings->ctrls; | ||
136 | sd->desc.ctrls = st6422_ctrl; | 148 | sd->desc.ctrls = st6422_ctrl; |
137 | sd->desc.nctrls = ARRAY_SIZE(st6422_ctrl); | 149 | sd->desc.nctrls = ARRAY_SIZE(st6422_ctrl); |
138 | sd->sensor_priv = sensor_settings; | 150 | sd->sensor_priv = sensor_settings; |
139 | 151 | ||
140 | for (i = 0; i < sd->desc.nctrls; i++) | ||
141 | sensor_settings[i] = st6422_ctrl[i].qctrl.default_value; | ||
142 | |||
143 | return 0; | 152 | return 0; |
144 | } | 153 | } |
145 | 154 | ||
@@ -234,77 +243,92 @@ static void st6422_disconnect(struct sd *sd) | |||
234 | kfree(sd->sensor_priv); | 243 | kfree(sd->sensor_priv); |
235 | } | 244 | } |
236 | 245 | ||
237 | static int st6422_start(struct sd *sd) | 246 | static int setbrightness(struct sd *sd) |
247 | { | ||
248 | struct st6422_settings *sensor_settings = sd->sensor_priv; | ||
249 | |||
250 | /* val goes from 0 -> 31 */ | ||
251 | return stv06xx_write_bridge(sd, 0x1432, | ||
252 | sensor_settings->ctrls[BRIGHTNESS].val); | ||
253 | } | ||
254 | |||
255 | static int setcontrast(struct sd *sd) | ||
256 | { | ||
257 | struct st6422_settings *sensor_settings = sd->sensor_priv; | ||
258 | |||
259 | /* Val goes from 0 -> 15 */ | ||
260 | return stv06xx_write_bridge(sd, 0x143a, | ||
261 | sensor_settings->ctrls[CONTRAST].val | 0xf0); | ||
262 | } | ||
263 | |||
264 | static int setgain(struct sd *sd) | ||
238 | { | 265 | { |
266 | struct st6422_settings *sensor_settings = sd->sensor_priv; | ||
267 | u8 gain; | ||
239 | int err; | 268 | int err; |
240 | struct cam *cam = &sd->gspca_dev.cam; | ||
241 | s32 *sensor_settings = sd->sensor_priv; | ||
242 | 269 | ||
243 | if (cam->cam_mode[sd->gspca_dev.curr_mode].priv) | 270 | gain = sensor_settings->ctrls[GAIN].val; |
244 | err = stv06xx_write_bridge(sd, 0x1505, 0x0f); | ||
245 | else | ||
246 | err = stv06xx_write_bridge(sd, 0x1505, 0x02); | ||
247 | if (err < 0) | ||
248 | return err; | ||
249 | 271 | ||
250 | err = st6422_set_brightness(&sd->gspca_dev, | 272 | /* Set red, green, blue, gain */ |
251 | sensor_settings[BRIGHTNESS_IDX]); | 273 | err = stv06xx_write_bridge(sd, 0x0509, gain); |
252 | if (err < 0) | 274 | if (err < 0) |
253 | return err; | 275 | return err; |
254 | 276 | ||
255 | err = st6422_set_contrast(&sd->gspca_dev, | 277 | err = stv06xx_write_bridge(sd, 0x050a, gain); |
256 | sensor_settings[CONTRAST_IDX]); | ||
257 | if (err < 0) | 278 | if (err < 0) |
258 | return err; | 279 | return err; |
259 | 280 | ||
260 | err = st6422_set_exposure(&sd->gspca_dev, | 281 | err = stv06xx_write_bridge(sd, 0x050b, gain); |
261 | sensor_settings[EXPOSURE_IDX]); | ||
262 | if (err < 0) | 282 | if (err < 0) |
263 | return err; | 283 | return err; |
264 | 284 | ||
265 | err = st6422_set_gain(&sd->gspca_dev, | 285 | /* 2 mystery writes */ |
266 | sensor_settings[GAIN_IDX]); | 286 | err = stv06xx_write_bridge(sd, 0x050c, 0x2a); |
267 | if (err < 0) | 287 | if (err < 0) |
268 | return err; | 288 | return err; |
269 | 289 | ||
270 | PDEBUG(D_STREAM, "Starting stream"); | 290 | return stv06xx_write_bridge(sd, 0x050d, 0x01); |
271 | |||
272 | return 0; | ||
273 | } | 291 | } |
274 | 292 | ||
275 | static int st6422_stop(struct sd *sd) | 293 | static int setexposure(struct sd *sd) |
276 | { | 294 | { |
277 | PDEBUG(D_STREAM, "Halting stream"); | 295 | struct st6422_settings *sensor_settings = sd->sensor_priv; |
278 | 296 | u16 expo; | |
279 | return 0; | 297 | int err; |
280 | } | ||
281 | |||
282 | static int st6422_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
283 | { | ||
284 | struct sd *sd = (struct sd *) gspca_dev; | ||
285 | s32 *sensor_settings = sd->sensor_priv; | ||
286 | |||
287 | *val = sensor_settings[BRIGHTNESS_IDX]; | ||
288 | 298 | ||
289 | PDEBUG(D_V4L2, "Read brightness %d", *val); | 299 | expo = sensor_settings->ctrls[EXPOSURE].val; |
300 | err = stv06xx_write_bridge(sd, 0x143d, expo & 0xff); | ||
301 | if (err < 0) | ||
302 | return err; | ||
290 | 303 | ||
291 | return 0; | 304 | return stv06xx_write_bridge(sd, 0x143e, expo >> 8); |
292 | } | 305 | } |
293 | 306 | ||
294 | static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val) | 307 | static int st6422_start(struct sd *sd) |
295 | { | 308 | { |
296 | int err; | 309 | int err; |
297 | struct sd *sd = (struct sd *) gspca_dev; | 310 | struct cam *cam = &sd->gspca_dev.cam; |
298 | s32 *sensor_settings = sd->sensor_priv; | ||
299 | 311 | ||
300 | sensor_settings[BRIGHTNESS_IDX] = val; | 312 | if (cam->cam_mode[sd->gspca_dev.curr_mode].priv) |
313 | err = stv06xx_write_bridge(sd, 0x1505, 0x0f); | ||
314 | else | ||
315 | err = stv06xx_write_bridge(sd, 0x1505, 0x02); | ||
316 | if (err < 0) | ||
317 | return err; | ||
301 | 318 | ||
302 | if (!gspca_dev->streaming) | 319 | err = setbrightness(sd); |
303 | return 0; | 320 | if (err < 0) |
321 | return err; | ||
304 | 322 | ||
305 | /* val goes from 0 -> 31 */ | 323 | err = setcontrast(sd); |
306 | PDEBUG(D_V4L2, "Set brightness to %d", val); | 324 | if (err < 0) |
307 | err = stv06xx_write_bridge(sd, 0x1432, val); | 325 | return err; |
326 | |||
327 | err = setexposure(sd); | ||
328 | if (err < 0) | ||
329 | return err; | ||
330 | |||
331 | err = setgain(sd); | ||
308 | if (err < 0) | 332 | if (err < 0) |
309 | return err; | 333 | return err; |
310 | 334 | ||
@@ -313,125 +337,65 @@ static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val) | |||
313 | return (err < 0) ? err : 0; | 337 | return (err < 0) ? err : 0; |
314 | } | 338 | } |
315 | 339 | ||
316 | static int st6422_get_contrast(struct gspca_dev *gspca_dev, __s32 *val) | 340 | static int st6422_stop(struct sd *sd) |
317 | { | 341 | { |
318 | struct sd *sd = (struct sd *) gspca_dev; | 342 | PDEBUG(D_STREAM, "Halting stream"); |
319 | s32 *sensor_settings = sd->sensor_priv; | ||
320 | |||
321 | *val = sensor_settings[CONTRAST_IDX]; | ||
322 | |||
323 | PDEBUG(D_V4L2, "Read contrast %d", *val); | ||
324 | 343 | ||
325 | return 0; | 344 | return 0; |
326 | } | 345 | } |
327 | 346 | ||
328 | static int st6422_set_contrast(struct gspca_dev *gspca_dev, __s32 val) | 347 | static void st6422_set_brightness(struct gspca_dev *gspca_dev) |
329 | { | 348 | { |
330 | int err; | 349 | int err; |
331 | struct sd *sd = (struct sd *) gspca_dev; | 350 | struct sd *sd = (struct sd *) gspca_dev; |
332 | s32 *sensor_settings = sd->sensor_priv; | ||
333 | |||
334 | sensor_settings[CONTRAST_IDX] = val; | ||
335 | 351 | ||
336 | if (!gspca_dev->streaming) | 352 | err = setbrightness(sd); |
337 | return 0; | ||
338 | |||
339 | /* Val goes from 0 -> 15 */ | ||
340 | PDEBUG(D_V4L2, "Set contrast to %d\n", val); | ||
341 | err = stv06xx_write_bridge(sd, 0x143a, 0xf0 | val); | ||
342 | if (err < 0) | ||
343 | return err; | ||
344 | 353 | ||
345 | /* commit settings */ | 354 | /* commit settings */ |
346 | err = stv06xx_write_bridge(sd, 0x143f, 0x01); | 355 | if (err >= 0) |
347 | return (err < 0) ? err : 0; | 356 | err = stv06xx_write_bridge(sd, 0x143f, 0x01); |
348 | } | ||
349 | |||
350 | static int st6422_get_gain(struct gspca_dev *gspca_dev, __s32 *val) | ||
351 | { | ||
352 | struct sd *sd = (struct sd *) gspca_dev; | ||
353 | s32 *sensor_settings = sd->sensor_priv; | ||
354 | |||
355 | *val = sensor_settings[GAIN_IDX]; | ||
356 | 357 | ||
357 | PDEBUG(D_V4L2, "Read gain %d", *val); | 358 | gspca_dev->usb_err = err; |
358 | |||
359 | return 0; | ||
360 | } | 359 | } |
361 | 360 | ||
362 | static int st6422_set_gain(struct gspca_dev *gspca_dev, __s32 val) | 361 | static void st6422_set_contrast(struct gspca_dev *gspca_dev) |
363 | { | 362 | { |
364 | int err; | 363 | int err; |
365 | struct sd *sd = (struct sd *) gspca_dev; | 364 | struct sd *sd = (struct sd *) gspca_dev; |
366 | s32 *sensor_settings = sd->sensor_priv; | ||
367 | 365 | ||
368 | sensor_settings[GAIN_IDX] = val; | 366 | err = setcontrast(sd); |
369 | |||
370 | if (!gspca_dev->streaming) | ||
371 | return 0; | ||
372 | |||
373 | PDEBUG(D_V4L2, "Set gain to %d", val); | ||
374 | |||
375 | /* Set red, green, blue, gain */ | ||
376 | err = stv06xx_write_bridge(sd, 0x0509, val); | ||
377 | if (err < 0) | ||
378 | return err; | ||
379 | |||
380 | err = stv06xx_write_bridge(sd, 0x050a, val); | ||
381 | if (err < 0) | ||
382 | return err; | ||
383 | |||
384 | err = stv06xx_write_bridge(sd, 0x050b, val); | ||
385 | if (err < 0) | ||
386 | return err; | ||
387 | |||
388 | /* 2 mystery writes */ | ||
389 | err = stv06xx_write_bridge(sd, 0x050c, 0x2a); | ||
390 | if (err < 0) | ||
391 | return err; | ||
392 | |||
393 | err = stv06xx_write_bridge(sd, 0x050d, 0x01); | ||
394 | if (err < 0) | ||
395 | return err; | ||
396 | 367 | ||
397 | /* commit settings */ | 368 | /* commit settings */ |
398 | err = stv06xx_write_bridge(sd, 0x143f, 0x01); | 369 | if (err >= 0) |
399 | return (err < 0) ? err : 0; | 370 | err = stv06xx_write_bridge(sd, 0x143f, 0x01); |
371 | |||
372 | gspca_dev->usb_err = err; | ||
400 | } | 373 | } |
401 | 374 | ||
402 | static int st6422_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) | 375 | static void st6422_set_gain(struct gspca_dev *gspca_dev) |
403 | { | 376 | { |
377 | int err; | ||
404 | struct sd *sd = (struct sd *) gspca_dev; | 378 | struct sd *sd = (struct sd *) gspca_dev; |
405 | s32 *sensor_settings = sd->sensor_priv; | ||
406 | 379 | ||
407 | *val = sensor_settings[EXPOSURE_IDX]; | 380 | err = setgain(sd); |
408 | 381 | ||
409 | PDEBUG(D_V4L2, "Read exposure %d", *val); | 382 | /* commit settings */ |
383 | if (err >= 0) | ||
384 | err = stv06xx_write_bridge(sd, 0x143f, 0x01); | ||
410 | 385 | ||
411 | return 0; | 386 | gspca_dev->usb_err = err; |
412 | } | 387 | } |
413 | 388 | ||
414 | static int st6422_set_exposure(struct gspca_dev *gspca_dev, __s32 val) | 389 | static void st6422_set_exposure(struct gspca_dev *gspca_dev) |
415 | { | 390 | { |
416 | int err; | 391 | int err; |
417 | struct sd *sd = (struct sd *) gspca_dev; | 392 | struct sd *sd = (struct sd *) gspca_dev; |
418 | s32 *sensor_settings = sd->sensor_priv; | ||
419 | |||
420 | sensor_settings[EXPOSURE_IDX] = val; | ||
421 | |||
422 | if (!gspca_dev->streaming) | ||
423 | return 0; | ||
424 | |||
425 | PDEBUG(D_V4L2, "Set exposure to %d\n", val); | ||
426 | err = stv06xx_write_bridge(sd, 0x143d, val & 0xff); | ||
427 | if (err < 0) | ||
428 | return err; | ||
429 | 393 | ||
430 | err = stv06xx_write_bridge(sd, 0x143e, val >> 8); | 394 | err = setexposure(sd); |
431 | if (err < 0) | ||
432 | return err; | ||
433 | 395 | ||
434 | /* commit settings */ | 396 | /* commit settings */ |
435 | err = stv06xx_write_bridge(sd, 0x143f, 0x01); | 397 | if (err >= 0) |
436 | return (err < 0) ? err : 0; | 398 | err = stv06xx_write_bridge(sd, 0x143f, 0x01); |
399 | |||
400 | gspca_dev->usb_err = err; | ||
437 | } | 401 | } |
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h index 12608aebe50b..d7498e06432b 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h | |||
@@ -37,16 +37,6 @@ static int st6422_init(struct sd *sd); | |||
37 | static int st6422_stop(struct sd *sd); | 37 | static int st6422_stop(struct sd *sd); |
38 | static void st6422_disconnect(struct sd *sd); | 38 | static void st6422_disconnect(struct sd *sd); |
39 | 39 | ||
40 | /* V4L2 controls supported by the driver */ | ||
41 | static int st6422_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
42 | static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val); | ||
43 | static int st6422_get_contrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
44 | static int st6422_set_contrast(struct gspca_dev *gspca_dev, __s32 val); | ||
45 | static int st6422_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
46 | static int st6422_set_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
47 | static int st6422_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
48 | static int st6422_set_exposure(struct gspca_dev *gspca_dev, __s32 val); | ||
49 | |||
50 | const struct stv06xx_sensor stv06xx_sensor_st6422 = { | 40 | const struct stv06xx_sensor stv06xx_sensor_st6422 = { |
51 | .name = "ST6422", | 41 | .name = "ST6422", |
52 | /* No known way to lower framerate in case of less bandwidth */ | 42 | /* No known way to lower framerate in case of less bandwidth */ |