Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Hans Verkuil and committed by
Mauro Carvalho Chehab
ceed52d6 a75b9be1

+63 -112
+61 -106
drivers/media/video/adv7343.c
··· 29 29 #include <media/adv7343.h> 30 30 #include <media/v4l2-device.h> 31 31 #include <media/v4l2-chip-ident.h> 32 + #include <media/v4l2-ctrls.h> 32 33 33 34 #include "adv7343_regs.h" 34 35 ··· 42 41 43 42 struct adv7343_state { 44 43 struct v4l2_subdev sd; 44 + struct v4l2_ctrl_handler hdl; 45 45 u8 reg00; 46 46 u8 reg01; 47 47 u8 reg02; 48 48 u8 reg35; 49 49 u8 reg80; 50 50 u8 reg82; 51 - int bright; 52 - int hue; 53 - int gain; 54 51 u32 output; 55 52 v4l2_std_id std; 56 53 }; ··· 56 57 static inline struct adv7343_state *to_state(struct v4l2_subdev *sd) 57 58 { 58 59 return container_of(sd, struct adv7343_state, sd); 60 + } 61 + 62 + static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) 63 + { 64 + return &container_of(ctrl->handler, struct adv7343_state, hdl)->sd; 59 65 } 60 66 61 67 static inline int adv7343_write(struct v4l2_subdev *sd, u8 reg, u8 value) ··· 272 268 return 0; 273 269 } 274 270 275 - static int adv7343_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) 271 + static int adv7343_s_ctrl(struct v4l2_ctrl *ctrl) 276 272 { 277 - switch (qc->id) { 278 - case V4L2_CID_BRIGHTNESS: 279 - return v4l2_ctrl_query_fill(qc, ADV7343_BRIGHTNESS_MIN, 280 - ADV7343_BRIGHTNESS_MAX, 1, 281 - ADV7343_BRIGHTNESS_DEF); 282 - case V4L2_CID_HUE: 283 - return v4l2_ctrl_query_fill(qc, ADV7343_HUE_MIN, 284 - ADV7343_HUE_MAX, 1 , 285 - ADV7343_HUE_DEF); 286 - case V4L2_CID_GAIN: 287 - return v4l2_ctrl_query_fill(qc, ADV7343_GAIN_MIN, 288 - ADV7343_GAIN_MAX, 1, 289 - ADV7343_GAIN_DEF); 290 - default: 291 - break; 292 - } 293 - 294 - return 0; 295 - } 296 - 297 - static int adv7343_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 298 - { 299 - struct adv7343_state *state = to_state(sd); 300 - int err = 0; 273 + struct v4l2_subdev *sd = to_sd(ctrl); 301 274 302 275 switch (ctrl->id) { 303 276 case V4L2_CID_BRIGHTNESS: 304 - if (ctrl->value < ADV7343_BRIGHTNESS_MIN || 305 - ctrl->value > ADV7343_BRIGHTNESS_MAX) { 306 - v4l2_dbg(1, debug, sd, 307 - "invalid brightness settings %d\n", 308 - ctrl->value); 309 - return -ERANGE; 310 - } 311 - 312 - state->bright = ctrl->value; 313 - err = adv7343_write(sd, ADV7343_SD_BRIGHTNESS_WSS, 314 - state->bright); 315 - break; 277 + return adv7343_write(sd, ADV7343_SD_BRIGHTNESS_WSS, 278 + ctrl->val); 316 279 317 280 case V4L2_CID_HUE: 318 - if (ctrl->value < ADV7343_HUE_MIN || 319 - ctrl->value > ADV7343_HUE_MAX) { 320 - v4l2_dbg(1, debug, sd, "invalid hue settings %d\n", 321 - ctrl->value); 322 - return -ERANGE; 323 - } 324 - 325 - state->hue = ctrl->value; 326 - err = adv7343_write(sd, ADV7343_SD_HUE_REG, state->hue); 327 - break; 281 + return adv7343_write(sd, ADV7343_SD_HUE_REG, ctrl->val); 328 282 329 283 case V4L2_CID_GAIN: 330 - if (ctrl->value < ADV7343_GAIN_MIN || 331 - ctrl->value > ADV7343_GAIN_MAX) { 332 - v4l2_dbg(1, debug, sd, "invalid gain settings %d\n", 333 - ctrl->value); 334 - return -ERANGE; 335 - } 336 - 337 - if ((ctrl->value > POSITIVE_GAIN_MAX) && 338 - (ctrl->value < NEGATIVE_GAIN_MIN)) { 339 - v4l2_dbg(1, debug, sd, 340 - "gain settings not within the specified range\n"); 341 - return -ERANGE; 342 - } 343 - 344 - state->gain = ctrl->value; 345 - err = adv7343_write(sd, ADV7343_DAC2_OUTPUT_LEVEL, state->gain); 346 - break; 347 - 348 - default: 349 - return -EINVAL; 284 + return adv7343_write(sd, ADV7343_DAC2_OUTPUT_LEVEL, ctrl->val); 350 285 } 351 - 352 - if (err < 0) 353 - v4l2_err(sd, "Failed to set the encoder controls\n"); 354 - 355 - return err; 356 - } 357 - 358 - static int adv7343_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 359 - { 360 - struct adv7343_state *state = to_state(sd); 361 - 362 - switch (ctrl->id) { 363 - case V4L2_CID_BRIGHTNESS: 364 - ctrl->value = state->bright; 365 - break; 366 - 367 - case V4L2_CID_HUE: 368 - ctrl->value = state->hue; 369 - break; 370 - 371 - case V4L2_CID_GAIN: 372 - ctrl->value = state->gain; 373 - break; 374 - 375 - default: 376 - return -EINVAL; 377 - } 378 - 379 - return 0; 286 + return -EINVAL; 380 287 } 381 288 382 289 static int adv7343_g_chip_ident(struct v4l2_subdev *sd, ··· 298 383 return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7343, 0); 299 384 } 300 385 386 + static const struct v4l2_ctrl_ops adv7343_ctrl_ops = { 387 + .s_ctrl = adv7343_s_ctrl, 388 + }; 389 + 301 390 static const struct v4l2_subdev_core_ops adv7343_core_ops = { 302 - .log_status = adv7343_log_status, 303 - .g_chip_ident = adv7343_g_chip_ident, 304 - .g_ctrl = adv7343_g_ctrl, 305 - .s_ctrl = adv7343_s_ctrl, 306 - .queryctrl = adv7343_queryctrl, 391 + .log_status = adv7343_log_status, 392 + .g_chip_ident = adv7343_g_chip_ident, 393 + .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, 394 + .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, 395 + .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, 396 + .g_ctrl = v4l2_subdev_g_ctrl, 397 + .s_ctrl = v4l2_subdev_s_ctrl, 398 + .queryctrl = v4l2_subdev_queryctrl, 399 + .querymenu = v4l2_subdev_querymenu, 307 400 }; 308 401 309 402 static int adv7343_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) ··· 391 468 const struct i2c_device_id *id) 392 469 { 393 470 struct adv7343_state *state; 471 + int err; 394 472 395 473 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 396 474 return -ENODEV; ··· 414 490 state->std = V4L2_STD_NTSC; 415 491 416 492 v4l2_i2c_subdev_init(&state->sd, client, &adv7343_ops); 417 - return adv7343_initialize(&state->sd); 493 + 494 + v4l2_ctrl_handler_init(&state->hdl, 2); 495 + v4l2_ctrl_new_std(&state->hdl, &adv7343_ctrl_ops, 496 + V4L2_CID_BRIGHTNESS, ADV7343_BRIGHTNESS_MIN, 497 + ADV7343_BRIGHTNESS_MAX, 1, 498 + ADV7343_BRIGHTNESS_DEF); 499 + v4l2_ctrl_new_std(&state->hdl, &adv7343_ctrl_ops, 500 + V4L2_CID_HUE, ADV7343_HUE_MIN, 501 + ADV7343_HUE_MAX, 1, 502 + ADV7343_HUE_DEF); 503 + v4l2_ctrl_new_std(&state->hdl, &adv7343_ctrl_ops, 504 + V4L2_CID_GAIN, ADV7343_GAIN_MIN, 505 + ADV7343_GAIN_MAX, 1, 506 + ADV7343_GAIN_DEF); 507 + state->sd.ctrl_handler = &state->hdl; 508 + if (state->hdl.error) { 509 + int err = state->hdl.error; 510 + 511 + v4l2_ctrl_handler_free(&state->hdl); 512 + kfree(state); 513 + return err; 514 + } 515 + v4l2_ctrl_handler_setup(&state->hdl); 516 + 517 + err = adv7343_initialize(&state->sd); 518 + if (err) { 519 + v4l2_ctrl_handler_free(&state->hdl); 520 + kfree(state); 521 + } 522 + return err; 418 523 } 419 524 420 525 static int adv7343_remove(struct i2c_client *client) 421 526 { 422 527 struct v4l2_subdev *sd = i2c_get_clientdata(client); 528 + struct adv7343_state *state = to_state(sd); 423 529 424 530 v4l2_device_unregister_subdev(sd); 425 - kfree(to_state(sd)); 531 + v4l2_ctrl_handler_free(&state->hdl); 532 + kfree(state); 426 533 427 534 return 0; 428 535 }
+2 -6
drivers/media/video/adv7343_regs.h
··· 102 102 103 103 /* Bit masks for DAC output levels */ 104 104 #define DAC_OUTPUT_LEVEL_MASK (0xFF) 105 - #define POSITIVE_GAIN_MAX (0x40) 106 - #define POSITIVE_GAIN_MIN (0x00) 107 - #define NEGATIVE_GAIN_MAX (0xFF) 108 - #define NEGATIVE_GAIN_MIN (0xC0) 109 105 110 106 /* Bit masks for soft reset register */ 111 107 #define SOFT_RESET (0x02) ··· 174 178 #define ADV7343_HUE_MAX (255) 175 179 #define ADV7343_HUE_MIN (0) 176 180 #define ADV7343_HUE_DEF (127) 177 - #define ADV7343_GAIN_MAX (255) 178 - #define ADV7343_GAIN_MIN (0) 181 + #define ADV7343_GAIN_MAX (64) 182 + #define ADV7343_GAIN_MIN (-64) 179 183 #define ADV7343_GAIN_DEF (0) 180 184 181 185 #endif