aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/adv7180.c235
1 files changed, 84 insertions, 151 deletions
diff --git a/drivers/media/video/adv7180.c b/drivers/media/video/adv7180.c
index 174bffacf117..45ecf8db1eae 100644
--- a/drivers/media/video/adv7180.c
+++ b/drivers/media/video/adv7180.c
@@ -26,11 +26,10 @@
26#include <media/v4l2-ioctl.h> 26#include <media/v4l2-ioctl.h>
27#include <linux/videodev2.h> 27#include <linux/videodev2.h>
28#include <media/v4l2-device.h> 28#include <media/v4l2-device.h>
29#include <media/v4l2-ctrls.h>
29#include <media/v4l2-chip-ident.h> 30#include <media/v4l2-chip-ident.h>
30#include <linux/mutex.h> 31#include <linux/mutex.h>
31 32
32#define DRIVER_NAME "adv7180"
33
34#define ADV7180_INPUT_CONTROL_REG 0x00 33#define ADV7180_INPUT_CONTROL_REG 0x00
35#define ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM 0x00 34#define ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM 0x00
36#define ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM_PED 0x10 35#define ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM_PED 0x10
@@ -55,21 +54,21 @@
55 54
56#define ADV7180_AUTODETECT_ENABLE_REG 0x07 55#define ADV7180_AUTODETECT_ENABLE_REG 0x07
57#define ADV7180_AUTODETECT_DEFAULT 0x7f 56#define ADV7180_AUTODETECT_DEFAULT 0x7f
58 57/* Contrast */
59#define ADV7180_CON_REG 0x08 /*Unsigned */ 58#define ADV7180_CON_REG 0x08 /*Unsigned */
60#define CON_REG_MIN 0 59#define ADV7180_CON_MIN 0
61#define CON_REG_DEF 128 60#define ADV7180_CON_DEF 128
62#define CON_REG_MAX 255 61#define ADV7180_CON_MAX 255
63 62/* Brightness*/
64#define ADV7180_BRI_REG 0x0a /*Signed */ 63#define ADV7180_BRI_REG 0x0a /*Signed */
65#define BRI_REG_MIN -128 64#define ADV7180_BRI_MIN -128
66#define BRI_REG_DEF 0 65#define ADV7180_BRI_DEF 0
67#define BRI_REG_MAX 127 66#define ADV7180_BRI_MAX 127
68 67/* Hue */
69#define ADV7180_HUE_REG 0x0b /*Signed, inverted */ 68#define ADV7180_HUE_REG 0x0b /*Signed, inverted */
70#define HUE_REG_MIN -127 69#define ADV7180_HUE_MIN -127
71#define HUE_REG_DEF 0 70#define ADV7180_HUE_DEF 0
72#define HUE_REG_MAX 128 71#define ADV7180_HUE_MAX 128
73 72
74#define ADV7180_ADI_CTRL_REG 0x0e 73#define ADV7180_ADI_CTRL_REG 0x0e
75#define ADV7180_ADI_CTRL_IRQ_SPACE 0x20 74#define ADV7180_ADI_CTRL_IRQ_SPACE 0x20
@@ -98,12 +97,12 @@
98#define ADV7180_ICONF1_ACTIVE_LOW 0x01 97#define ADV7180_ICONF1_ACTIVE_LOW 0x01
99#define ADV7180_ICONF1_PSYNC_ONLY 0x10 98#define ADV7180_ICONF1_PSYNC_ONLY 0x10
100#define ADV7180_ICONF1_ACTIVE_TO_CLR 0xC0 99#define ADV7180_ICONF1_ACTIVE_TO_CLR 0xC0
101 100/* Saturation */
102#define ADV7180_SD_SAT_CB_REG 0xe3 /*Unsigned */ 101#define ADV7180_SD_SAT_CB_REG 0xe3 /*Unsigned */
103#define ADV7180_SD_SAT_CR_REG 0xe4 /*Unsigned */ 102#define ADV7180_SD_SAT_CR_REG 0xe4 /*Unsigned */
104#define SAT_REG_MIN 0 103#define ADV7180_SAT_MIN 0
105#define SAT_REG_DEF 128 104#define ADV7180_SAT_DEF 128
106#define SAT_REG_MAX 255 105#define ADV7180_SAT_MAX 255
107 106
108#define ADV7180_IRQ1_LOCK 0x01 107#define ADV7180_IRQ1_LOCK 0x01
109#define ADV7180_IRQ1_UNLOCK 0x02 108#define ADV7180_IRQ1_UNLOCK 0x02
@@ -121,18 +120,18 @@
121#define ADV7180_NTSC_V_BIT_END_MANUAL_NVEND 0x4F 120#define ADV7180_NTSC_V_BIT_END_MANUAL_NVEND 0x4F
122 121
123struct adv7180_state { 122struct adv7180_state {
123 struct v4l2_ctrl_handler ctrl_hdl;
124 struct v4l2_subdev sd; 124 struct v4l2_subdev sd;
125 struct work_struct work; 125 struct work_struct work;
126 struct mutex mutex; /* mutual excl. when accessing chip */ 126 struct mutex mutex; /* mutual excl. when accessing chip */
127 int irq; 127 int irq;
128 v4l2_std_id curr_norm; 128 v4l2_std_id curr_norm;
129 bool autodetect; 129 bool autodetect;
130 s8 brightness;
131 s16 hue;
132 u8 contrast;
133 u8 saturation;
134 u8 input; 130 u8 input;
135}; 131};
132#define to_adv7180_sd(_ctrl) (&container_of(_ctrl->handler, \
133 struct adv7180_state, \
134 ctrl_hdl)->sd)
136 135
137static v4l2_std_id adv7180_std_to_v4l2(u8 status1) 136static v4l2_std_id adv7180_std_to_v4l2(u8 status1)
138{ 137{
@@ -237,7 +236,7 @@ static int adv7180_s_routing(struct v4l2_subdev *sd, u32 input,
237 if (ret) 236 if (ret)
238 return ret; 237 return ret;
239 238
240 /*We cannot discriminate between LQFP and 40-pin LFCSP, so accept 239 /* We cannot discriminate between LQFP and 40-pin LFCSP, so accept
241 * all inputs and let the card driver take care of validation 240 * all inputs and let the card driver take care of validation
242 */ 241 */
243 if ((input & ADV7180_INPUT_CONTROL_INSEL_MASK) != input) 242 if ((input & ADV7180_INPUT_CONTROL_INSEL_MASK) != input)
@@ -316,117 +315,39 @@ out:
316 return ret; 315 return ret;
317} 316}
318 317
319static int adv7180_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) 318static int adv7180_s_ctrl(struct v4l2_ctrl *ctrl)
320{
321 switch (qc->id) {
322 case V4L2_CID_BRIGHTNESS:
323 return v4l2_ctrl_query_fill(qc, BRI_REG_MIN, BRI_REG_MAX,
324 1, BRI_REG_DEF);
325 case V4L2_CID_HUE:
326 return v4l2_ctrl_query_fill(qc, HUE_REG_MIN, HUE_REG_MAX,
327 1, HUE_REG_DEF);
328 case V4L2_CID_CONTRAST:
329 return v4l2_ctrl_query_fill(qc, CON_REG_MIN, CON_REG_MAX,
330 1, CON_REG_DEF);
331 case V4L2_CID_SATURATION:
332 return v4l2_ctrl_query_fill(qc, SAT_REG_MIN, SAT_REG_MAX,
333 1, SAT_REG_DEF);
334 default:
335 break;
336 }
337
338 return -EINVAL;
339}
340
341static int adv7180_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
342{
343 struct adv7180_state *state = to_state(sd);
344 int ret = mutex_lock_interruptible(&state->mutex);
345 if (ret)
346 return ret;
347
348 switch (ctrl->id) {
349 case V4L2_CID_BRIGHTNESS:
350 ctrl->value = state->brightness;
351 break;
352 case V4L2_CID_HUE:
353 ctrl->value = state->hue;
354 break;
355 case V4L2_CID_CONTRAST:
356 ctrl->value = state->contrast;
357 break;
358 case V4L2_CID_SATURATION:
359 ctrl->value = state->saturation;
360 break;
361 default:
362 ret = -EINVAL;
363 }
364
365 mutex_unlock(&state->mutex);
366 return ret;
367}
368
369static int adv7180_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
370{ 319{
320 struct v4l2_subdev *sd = to_adv7180_sd(ctrl);
371 struct adv7180_state *state = to_state(sd); 321 struct adv7180_state *state = to_state(sd);
372 struct i2c_client *client = v4l2_get_subdevdata(sd); 322 struct i2c_client *client = v4l2_get_subdevdata(sd);
373 int ret = mutex_lock_interruptible(&state->mutex); 323 int ret = mutex_lock_interruptible(&state->mutex);
324 int val;
325
374 if (ret) 326 if (ret)
375 return ret; 327 return ret;
376 328 val = ctrl->val;
377 switch (ctrl->id) { 329 switch (ctrl->id) {
378 case V4L2_CID_BRIGHTNESS: 330 case V4L2_CID_BRIGHTNESS:
379 if ((ctrl->value > BRI_REG_MAX) 331 ret = i2c_smbus_write_byte_data(client, ADV7180_BRI_REG, val);
380 || (ctrl->value < BRI_REG_MIN)) {
381 ret = -ERANGE;
382 break;
383 }
384 state->brightness = ctrl->value;
385 ret = i2c_smbus_write_byte_data(client,
386 ADV7180_BRI_REG,
387 state->brightness);
388 break; 332 break;
389 case V4L2_CID_HUE: 333 case V4L2_CID_HUE:
390 if ((ctrl->value > HUE_REG_MAX)
391 || (ctrl->value < HUE_REG_MIN)) {
392 ret = -ERANGE;
393 break;
394 }
395 state->hue = ctrl->value;
396 /*Hue is inverted according to HSL chart */ 334 /*Hue is inverted according to HSL chart */
397 ret = i2c_smbus_write_byte_data(client, 335 ret = i2c_smbus_write_byte_data(client, ADV7180_HUE_REG, -val);
398 ADV7180_HUE_REG, -state->hue);
399 break; 336 break;
400 case V4L2_CID_CONTRAST: 337 case V4L2_CID_CONTRAST:
401 if ((ctrl->value > CON_REG_MAX) 338 ret = i2c_smbus_write_byte_data(client, ADV7180_CON_REG, val);
402 || (ctrl->value < CON_REG_MIN)) {
403 ret = -ERANGE;
404 break;
405 }
406 state->contrast = ctrl->value;
407 ret = i2c_smbus_write_byte_data(client,
408 ADV7180_CON_REG,
409 state->contrast);
410 break; 339 break;
411 case V4L2_CID_SATURATION: 340 case V4L2_CID_SATURATION:
412 if ((ctrl->value > SAT_REG_MAX)
413 || (ctrl->value < SAT_REG_MIN)) {
414 ret = -ERANGE;
415 break;
416 }
417 /* 341 /*
418 *This could be V4L2_CID_BLUE_BALANCE/V4L2_CID_RED_BALANCE 342 *This could be V4L2_CID_BLUE_BALANCE/V4L2_CID_RED_BALANCE
419 *Let's not confuse the user, everybody understands saturation 343 *Let's not confuse the user, everybody understands saturation
420 */ 344 */
421 state->saturation = ctrl->value; 345 ret = i2c_smbus_write_byte_data(client, ADV7180_SD_SAT_CB_REG,
422 ret = i2c_smbus_write_byte_data(client, 346 val);
423 ADV7180_SD_SAT_CB_REG,
424 state->saturation);
425 if (ret < 0) 347 if (ret < 0)
426 break; 348 break;
427 ret = i2c_smbus_write_byte_data(client, 349 ret = i2c_smbus_write_byte_data(client, ADV7180_SD_SAT_CR_REG,
428 ADV7180_SD_SAT_CR_REG, 350 val);
429 state->saturation);
430 break; 351 break;
431 default: 352 default:
432 ret = -EINVAL; 353 ret = -EINVAL;
@@ -436,6 +357,42 @@ static int adv7180_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
436 return ret; 357 return ret;
437} 358}
438 359
360static const struct v4l2_ctrl_ops adv7180_ctrl_ops = {
361 .s_ctrl = adv7180_s_ctrl,
362};
363
364static int adv7180_init_controls(struct adv7180_state *state)
365{
366 v4l2_ctrl_handler_init(&state->ctrl_hdl, 4);
367
368 v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops,
369 V4L2_CID_BRIGHTNESS, ADV7180_BRI_MIN,
370 ADV7180_BRI_MAX, 1, ADV7180_BRI_DEF);
371 v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops,
372 V4L2_CID_CONTRAST, ADV7180_CON_MIN,
373 ADV7180_CON_MAX, 1, ADV7180_CON_DEF);
374 v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops,
375 V4L2_CID_SATURATION, ADV7180_SAT_MIN,
376 ADV7180_SAT_MAX, 1, ADV7180_SAT_DEF);
377 v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops,
378 V4L2_CID_HUE, ADV7180_HUE_MIN,
379 ADV7180_HUE_MAX, 1, ADV7180_HUE_DEF);
380 state->sd.ctrl_handler = &state->ctrl_hdl;
381 if (state->ctrl_hdl.error) {
382 int err = state->ctrl_hdl.error;
383
384 v4l2_ctrl_handler_free(&state->ctrl_hdl);
385 return err;
386 }
387 v4l2_ctrl_handler_setup(&state->ctrl_hdl);
388
389 return 0;
390}
391static void adv7180_exit_controls(struct adv7180_state *state)
392{
393 v4l2_ctrl_handler_free(&state->ctrl_hdl);
394}
395
439static const struct v4l2_subdev_video_ops adv7180_video_ops = { 396static const struct v4l2_subdev_video_ops adv7180_video_ops = {
440 .querystd = adv7180_querystd, 397 .querystd = adv7180_querystd,
441 .g_input_status = adv7180_g_input_status, 398 .g_input_status = adv7180_g_input_status,
@@ -445,9 +402,9 @@ static const struct v4l2_subdev_video_ops adv7180_video_ops = {
445static const struct v4l2_subdev_core_ops adv7180_core_ops = { 402static const struct v4l2_subdev_core_ops adv7180_core_ops = {
446 .g_chip_ident = adv7180_g_chip_ident, 403 .g_chip_ident = adv7180_g_chip_ident,
447 .s_std = adv7180_s_std, 404 .s_std = adv7180_s_std,
448 .queryctrl = adv7180_queryctrl, 405 .queryctrl = v4l2_subdev_queryctrl,
449 .g_ctrl = adv7180_g_ctrl, 406 .g_ctrl = v4l2_subdev_g_ctrl,
450 .s_ctrl = adv7180_s_ctrl, 407 .s_ctrl = v4l2_subdev_s_ctrl,
451}; 408};
452 409
453static const struct v4l2_subdev_ops adv7180_ops = { 410static const struct v4l2_subdev_ops adv7180_ops = {
@@ -539,7 +496,7 @@ static int init_device(struct i2c_client *client, struct adv7180_state *state)
539 496
540 /* register for interrupts */ 497 /* register for interrupts */
541 if (state->irq > 0) { 498 if (state->irq > 0) {
542 ret = request_irq(state->irq, adv7180_irq, 0, DRIVER_NAME, 499 ret = request_irq(state->irq, adv7180_irq, 0, KBUILD_MODNAME,
543 state); 500 state);
544 if (ret) 501 if (ret)
545 return ret; 502 return ret;
@@ -580,31 +537,6 @@ static int init_device(struct i2c_client *client, struct adv7180_state *state)
580 return ret; 537 return ret;
581 } 538 }
582 539
583 /*Set default value for controls */
584 ret = i2c_smbus_write_byte_data(client, ADV7180_BRI_REG,
585 state->brightness);
586 if (ret < 0)
587 return ret;
588
589 ret = i2c_smbus_write_byte_data(client, ADV7180_HUE_REG, state->hue);
590 if (ret < 0)
591 return ret;
592
593 ret = i2c_smbus_write_byte_data(client, ADV7180_CON_REG,
594 state->contrast);
595 if (ret < 0)
596 return ret;
597
598 ret = i2c_smbus_write_byte_data(client, ADV7180_SD_SAT_CB_REG,
599 state->saturation);
600 if (ret < 0)
601 return ret;
602
603 ret = i2c_smbus_write_byte_data(client, ADV7180_SD_SAT_CR_REG,
604 state->saturation);
605 if (ret < 0)
606 return ret;
607
608 return 0; 540 return 0;
609} 541}
610 542
@@ -632,25 +564,26 @@ static __devinit int adv7180_probe(struct i2c_client *client,
632 INIT_WORK(&state->work, adv7180_work); 564 INIT_WORK(&state->work, adv7180_work);
633 mutex_init(&state->mutex); 565 mutex_init(&state->mutex);
634 state->autodetect = true; 566 state->autodetect = true;
635 state->brightness = BRI_REG_DEF;
636 state->hue = HUE_REG_DEF;
637 state->contrast = CON_REG_DEF;
638 state->saturation = SAT_REG_DEF;
639 state->input = 0; 567 state->input = 0;
640 sd = &state->sd; 568 sd = &state->sd;
641 v4l2_i2c_subdev_init(sd, client, &adv7180_ops); 569 v4l2_i2c_subdev_init(sd, client, &adv7180_ops);
642 570
643 ret = init_device(client, state); 571 ret = adv7180_init_controls(state);
644 if (0 != ret) 572 if (ret)
645 goto err_unreg_subdev; 573 goto err_unreg_subdev;
574 ret = init_device(client, state);
575 if (ret)
576 goto err_free_ctrl;
646 return 0; 577 return 0;
647 578
579err_free_ctrl:
580 adv7180_exit_controls(state);
648err_unreg_subdev: 581err_unreg_subdev:
649 mutex_destroy(&state->mutex); 582 mutex_destroy(&state->mutex);
650 v4l2_device_unregister_subdev(sd); 583 v4l2_device_unregister_subdev(sd);
651 kfree(state); 584 kfree(state);
652err: 585err:
653 printk(KERN_ERR DRIVER_NAME ": Failed to probe: %d\n", ret); 586 printk(KERN_ERR KBUILD_MODNAME ": Failed to probe: %d\n", ret);
654 return ret; 587 return ret;
655} 588}
656 589
@@ -678,7 +611,7 @@ static __devexit int adv7180_remove(struct i2c_client *client)
678} 611}
679 612
680static const struct i2c_device_id adv7180_id[] = { 613static const struct i2c_device_id adv7180_id[] = {
681 {DRIVER_NAME, 0}, 614 {KBUILD_MODNAME, 0},
682 {}, 615 {},
683}; 616};
684 617
@@ -716,7 +649,7 @@ MODULE_DEVICE_TABLE(i2c, adv7180_id);
716static struct i2c_driver adv7180_driver = { 649static struct i2c_driver adv7180_driver = {
717 .driver = { 650 .driver = {
718 .owner = THIS_MODULE, 651 .owner = THIS_MODULE,
719 .name = DRIVER_NAME, 652 .name = KBUILD_MODNAME,
720 }, 653 },
721 .probe = adv7180_probe, 654 .probe = adv7180_probe,
722 .remove = __devexit_p(adv7180_remove), 655 .remove = __devexit_p(adv7180_remove),