aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/adv7343.c
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2010-12-12 06:19:16 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-03-21 19:31:49 -0400
commitceed52d67e1cf7866fa96514525c615554a0e44e (patch)
tree4e3324dbb011f531c393cd1a172009970f8120e7 /drivers/media/video/adv7343.c
parenta75b9be1c2fb52dee765d35f29031dd788d522eb (diff)
[media] adv7343: use control framework
Also fixed a memory leak in the probe function if an error occurred. The gain control range was also fixed (a proper range from -64 to 64). Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/adv7343.c')
-rw-r--r--drivers/media/video/adv7343.c167
1 files changed, 61 insertions, 106 deletions
diff --git a/drivers/media/video/adv7343.c b/drivers/media/video/adv7343.c
index 41b2930d0ce..021fab23070 100644
--- a/drivers/media/video/adv7343.c
+++ b/drivers/media/video/adv7343.c
@@ -29,6 +29,7 @@
29#include <media/adv7343.h> 29#include <media/adv7343.h>
30#include <media/v4l2-device.h> 30#include <media/v4l2-device.h>
31#include <media/v4l2-chip-ident.h> 31#include <media/v4l2-chip-ident.h>
32#include <media/v4l2-ctrls.h>
32 33
33#include "adv7343_regs.h" 34#include "adv7343_regs.h"
34 35
@@ -41,15 +42,13 @@ MODULE_PARM_DESC(debug, "Debug level 0-1");
41 42
42struct adv7343_state { 43struct adv7343_state {
43 struct v4l2_subdev sd; 44 struct v4l2_subdev sd;
45 struct v4l2_ctrl_handler hdl;
44 u8 reg00; 46 u8 reg00;
45 u8 reg01; 47 u8 reg01;
46 u8 reg02; 48 u8 reg02;
47 u8 reg35; 49 u8 reg35;
48 u8 reg80; 50 u8 reg80;
49 u8 reg82; 51 u8 reg82;
50 int bright;
51 int hue;
52 int gain;
53 u32 output; 52 u32 output;
54 v4l2_std_id std; 53 v4l2_std_id std;
55}; 54};
@@ -59,6 +58,11 @@ static inline struct adv7343_state *to_state(struct v4l2_subdev *sd)
59 return container_of(sd, struct adv7343_state, sd); 58 return container_of(sd, struct adv7343_state, sd);
60} 59}
61 60
61static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
62{
63 return &container_of(ctrl->handler, struct adv7343_state, hdl)->sd;
64}
65
62static inline int adv7343_write(struct v4l2_subdev *sd, u8 reg, u8 value) 66static inline int adv7343_write(struct v4l2_subdev *sd, u8 reg, u8 value)
63{ 67{
64 struct i2c_client *client = v4l2_get_subdevdata(sd); 68 struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -268,111 +272,22 @@ static int adv7343_log_status(struct v4l2_subdev *sd)
268 return 0; 272 return 0;
269} 273}
270 274
271static int adv7343_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) 275static int adv7343_s_ctrl(struct v4l2_ctrl *ctrl)
272{
273 switch (qc->id) {
274 case V4L2_CID_BRIGHTNESS:
275 return v4l2_ctrl_query_fill(qc, ADV7343_BRIGHTNESS_MIN,
276 ADV7343_BRIGHTNESS_MAX, 1,
277 ADV7343_BRIGHTNESS_DEF);
278 case V4L2_CID_HUE:
279 return v4l2_ctrl_query_fill(qc, ADV7343_HUE_MIN,
280 ADV7343_HUE_MAX, 1 ,
281 ADV7343_HUE_DEF);
282 case V4L2_CID_GAIN:
283 return v4l2_ctrl_query_fill(qc, ADV7343_GAIN_MIN,
284 ADV7343_GAIN_MAX, 1,
285 ADV7343_GAIN_DEF);
286 default:
287 break;
288 }
289
290 return 0;
291}
292
293static int adv7343_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
294{
295 struct adv7343_state *state = to_state(sd);
296 int err = 0;
297
298 switch (ctrl->id) {
299 case V4L2_CID_BRIGHTNESS:
300 if (ctrl->value < ADV7343_BRIGHTNESS_MIN ||
301 ctrl->value > ADV7343_BRIGHTNESS_MAX) {
302 v4l2_dbg(1, debug, sd,
303 "invalid brightness settings %d\n",
304 ctrl->value);
305 return -ERANGE;
306 }
307
308 state->bright = ctrl->value;
309 err = adv7343_write(sd, ADV7343_SD_BRIGHTNESS_WSS,
310 state->bright);
311 break;
312
313 case V4L2_CID_HUE:
314 if (ctrl->value < ADV7343_HUE_MIN ||
315 ctrl->value > ADV7343_HUE_MAX) {
316 v4l2_dbg(1, debug, sd, "invalid hue settings %d\n",
317 ctrl->value);
318 return -ERANGE;
319 }
320
321 state->hue = ctrl->value;
322 err = adv7343_write(sd, ADV7343_SD_HUE_REG, state->hue);
323 break;
324
325 case V4L2_CID_GAIN:
326 if (ctrl->value < ADV7343_GAIN_MIN ||
327 ctrl->value > ADV7343_GAIN_MAX) {
328 v4l2_dbg(1, debug, sd, "invalid gain settings %d\n",
329 ctrl->value);
330 return -ERANGE;
331 }
332
333 if ((ctrl->value > POSITIVE_GAIN_MAX) &&
334 (ctrl->value < NEGATIVE_GAIN_MIN)) {
335 v4l2_dbg(1, debug, sd,
336 "gain settings not within the specified range\n");
337 return -ERANGE;
338 }
339
340 state->gain = ctrl->value;
341 err = adv7343_write(sd, ADV7343_DAC2_OUTPUT_LEVEL, state->gain);
342 break;
343
344 default:
345 return -EINVAL;
346 }
347
348 if (err < 0)
349 v4l2_err(sd, "Failed to set the encoder controls\n");
350
351 return err;
352}
353
354static int adv7343_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
355{ 276{
356 struct adv7343_state *state = to_state(sd); 277 struct v4l2_subdev *sd = to_sd(ctrl);
357 278
358 switch (ctrl->id) { 279 switch (ctrl->id) {
359 case V4L2_CID_BRIGHTNESS: 280 case V4L2_CID_BRIGHTNESS:
360 ctrl->value = state->bright; 281 return adv7343_write(sd, ADV7343_SD_BRIGHTNESS_WSS,
361 break; 282 ctrl->val);
362 283
363 case V4L2_CID_HUE: 284 case V4L2_CID_HUE:
364 ctrl->value = state->hue; 285 return adv7343_write(sd, ADV7343_SD_HUE_REG, ctrl->val);
365 break;
366 286
367 case V4L2_CID_GAIN: 287 case V4L2_CID_GAIN:
368 ctrl->value = state->gain; 288 return adv7343_write(sd, ADV7343_DAC2_OUTPUT_LEVEL, ctrl->val);
369 break;
370
371 default:
372 return -EINVAL;
373 } 289 }
374 290 return -EINVAL;
375 return 0;
376} 291}
377 292
378static int adv7343_g_chip_ident(struct v4l2_subdev *sd, 293static int adv7343_g_chip_ident(struct v4l2_subdev *sd,
@@ -383,12 +298,20 @@ static int adv7343_g_chip_ident(struct v4l2_subdev *sd,
383 return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7343, 0); 298 return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7343, 0);
384} 299}
385 300
301static const struct v4l2_ctrl_ops adv7343_ctrl_ops = {
302 .s_ctrl = adv7343_s_ctrl,
303};
304
386static const struct v4l2_subdev_core_ops adv7343_core_ops = { 305static const struct v4l2_subdev_core_ops adv7343_core_ops = {
387 .log_status = adv7343_log_status, 306 .log_status = adv7343_log_status,
388 .g_chip_ident = adv7343_g_chip_ident, 307 .g_chip_ident = adv7343_g_chip_ident,
389 .g_ctrl = adv7343_g_ctrl, 308 .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
390 .s_ctrl = adv7343_s_ctrl, 309 .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
391 .queryctrl = adv7343_queryctrl, 310 .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
311 .g_ctrl = v4l2_subdev_g_ctrl,
312 .s_ctrl = v4l2_subdev_s_ctrl,
313 .queryctrl = v4l2_subdev_queryctrl,
314 .querymenu = v4l2_subdev_querymenu,
392}; 315};
393 316
394static int adv7343_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) 317static int adv7343_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
@@ -468,6 +391,7 @@ static int adv7343_probe(struct i2c_client *client,
468 const struct i2c_device_id *id) 391 const struct i2c_device_id *id)
469{ 392{
470 struct adv7343_state *state; 393 struct adv7343_state *state;
394 int err;
471 395
472 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 396 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
473 return -ENODEV; 397 return -ENODEV;
@@ -490,15 +414,46 @@ static int adv7343_probe(struct i2c_client *client,
490 state->std = V4L2_STD_NTSC; 414 state->std = V4L2_STD_NTSC;
491 415
492 v4l2_i2c_subdev_init(&state->sd, client, &adv7343_ops); 416 v4l2_i2c_subdev_init(&state->sd, client, &adv7343_ops);
493 return adv7343_initialize(&state->sd); 417
418 v4l2_ctrl_handler_init(&state->hdl, 2);
419 v4l2_ctrl_new_std(&state->hdl, &adv7343_ctrl_ops,
420 V4L2_CID_BRIGHTNESS, ADV7343_BRIGHTNESS_MIN,
421 ADV7343_BRIGHTNESS_MAX, 1,
422 ADV7343_BRIGHTNESS_DEF);
423 v4l2_ctrl_new_std(&state->hdl, &adv7343_ctrl_ops,
424 V4L2_CID_HUE, ADV7343_HUE_MIN,
425 ADV7343_HUE_MAX, 1,
426 ADV7343_HUE_DEF);
427 v4l2_ctrl_new_std(&state->hdl, &adv7343_ctrl_ops,
428 V4L2_CID_GAIN, ADV7343_GAIN_MIN,
429 ADV7343_GAIN_MAX, 1,
430 ADV7343_GAIN_DEF);
431 state->sd.ctrl_handler = &state->hdl;
432 if (state->hdl.error) {
433 int err = state->hdl.error;
434
435 v4l2_ctrl_handler_free(&state->hdl);
436 kfree(state);
437 return err;
438 }
439 v4l2_ctrl_handler_setup(&state->hdl);
440
441 err = adv7343_initialize(&state->sd);
442 if (err) {
443 v4l2_ctrl_handler_free(&state->hdl);
444 kfree(state);
445 }
446 return err;
494} 447}
495 448
496static int adv7343_remove(struct i2c_client *client) 449static int adv7343_remove(struct i2c_client *client)
497{ 450{
498 struct v4l2_subdev *sd = i2c_get_clientdata(client); 451 struct v4l2_subdev *sd = i2c_get_clientdata(client);
452 struct adv7343_state *state = to_state(sd);
499 453
500 v4l2_device_unregister_subdev(sd); 454 v4l2_device_unregister_subdev(sd);
501 kfree(to_state(sd)); 455 v4l2_ctrl_handler_free(&state->hdl);
456 kfree(state);
502 457
503 return 0; 458 return 0;
504} 459}