aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/tvp7002.c
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2012-05-15 07:07:24 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-05-20 07:30:09 -0400
commiteb8305b159f34abf9ac1349d61b4cf47578b13ab (patch)
tree767a7070ad44f5cdac0f3ec74fb177e81378971d /drivers/media/video/tvp7002.c
parentf00dc30422d442c6cfbbab3c6e93fe6cb6681621 (diff)
[media] tvp7002: add support for the new dv timings API
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Reviewed-by: Mauro Carvalho Chehab <mchehab@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/tvp7002.c')
-rw-r--r--drivers/media/video/tvp7002.c102
1 files changed, 89 insertions, 13 deletions
diff --git a/drivers/media/video/tvp7002.c b/drivers/media/video/tvp7002.c
index 408b65e782e5..fb6a5b57eb83 100644
--- a/drivers/media/video/tvp7002.c
+++ b/drivers/media/video/tvp7002.c
@@ -29,6 +29,7 @@
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/videodev2.h> 30#include <linux/videodev2.h>
31#include <linux/module.h> 31#include <linux/module.h>
32#include <linux/v4l2-dv-timings.h>
32#include <media/tvp7002.h> 33#include <media/tvp7002.h>
33#include <media/v4l2-device.h> 34#include <media/v4l2-device.h>
34#include <media/v4l2-chip-ident.h> 35#include <media/v4l2-chip-ident.h>
@@ -328,6 +329,7 @@ static const struct i2c_reg_value tvp7002_parms_720P50[] = {
328/* Preset definition for handling device operation */ 329/* Preset definition for handling device operation */
329struct tvp7002_preset_definition { 330struct tvp7002_preset_definition {
330 u32 preset; 331 u32 preset;
332 struct v4l2_dv_timings timings;
331 const struct i2c_reg_value *p_settings; 333 const struct i2c_reg_value *p_settings;
332 enum v4l2_colorspace color_space; 334 enum v4l2_colorspace color_space;
333 enum v4l2_field scanmode; 335 enum v4l2_field scanmode;
@@ -341,6 +343,7 @@ struct tvp7002_preset_definition {
341static const struct tvp7002_preset_definition tvp7002_presets[] = { 343static const struct tvp7002_preset_definition tvp7002_presets[] = {
342 { 344 {
343 V4L2_DV_720P60, 345 V4L2_DV_720P60,
346 V4L2_DV_BT_CEA_1280X720P60,
344 tvp7002_parms_720P60, 347 tvp7002_parms_720P60,
345 V4L2_COLORSPACE_REC709, 348 V4L2_COLORSPACE_REC709,
346 V4L2_FIELD_NONE, 349 V4L2_FIELD_NONE,
@@ -351,6 +354,7 @@ static const struct tvp7002_preset_definition tvp7002_presets[] = {
351 }, 354 },
352 { 355 {
353 V4L2_DV_1080I60, 356 V4L2_DV_1080I60,
357 V4L2_DV_BT_CEA_1920X1080I60,
354 tvp7002_parms_1080I60, 358 tvp7002_parms_1080I60,
355 V4L2_COLORSPACE_REC709, 359 V4L2_COLORSPACE_REC709,
356 V4L2_FIELD_INTERLACED, 360 V4L2_FIELD_INTERLACED,
@@ -361,6 +365,7 @@ static const struct tvp7002_preset_definition tvp7002_presets[] = {
361 }, 365 },
362 { 366 {
363 V4L2_DV_1080I50, 367 V4L2_DV_1080I50,
368 V4L2_DV_BT_CEA_1920X1080I50,
364 tvp7002_parms_1080I50, 369 tvp7002_parms_1080I50,
365 V4L2_COLORSPACE_REC709, 370 V4L2_COLORSPACE_REC709,
366 V4L2_FIELD_INTERLACED, 371 V4L2_FIELD_INTERLACED,
@@ -371,6 +376,7 @@ static const struct tvp7002_preset_definition tvp7002_presets[] = {
371 }, 376 },
372 { 377 {
373 V4L2_DV_720P50, 378 V4L2_DV_720P50,
379 V4L2_DV_BT_CEA_1280X720P50,
374 tvp7002_parms_720P50, 380 tvp7002_parms_720P50,
375 V4L2_COLORSPACE_REC709, 381 V4L2_COLORSPACE_REC709,
376 V4L2_FIELD_NONE, 382 V4L2_FIELD_NONE,
@@ -381,6 +387,7 @@ static const struct tvp7002_preset_definition tvp7002_presets[] = {
381 }, 387 },
382 { 388 {
383 V4L2_DV_1080P60, 389 V4L2_DV_1080P60,
390 V4L2_DV_BT_CEA_1920X1080P60,
384 tvp7002_parms_1080P60, 391 tvp7002_parms_1080P60,
385 V4L2_COLORSPACE_REC709, 392 V4L2_COLORSPACE_REC709,
386 V4L2_FIELD_NONE, 393 V4L2_FIELD_NONE,
@@ -391,6 +398,7 @@ static const struct tvp7002_preset_definition tvp7002_presets[] = {
391 }, 398 },
392 { 399 {
393 V4L2_DV_480P59_94, 400 V4L2_DV_480P59_94,
401 V4L2_DV_BT_CEA_720X480P59_94,
394 tvp7002_parms_480P, 402 tvp7002_parms_480P,
395 V4L2_COLORSPACE_SMPTE170M, 403 V4L2_COLORSPACE_SMPTE170M,
396 V4L2_FIELD_NONE, 404 V4L2_FIELD_NONE,
@@ -401,6 +409,7 @@ static const struct tvp7002_preset_definition tvp7002_presets[] = {
401 }, 409 },
402 { 410 {
403 V4L2_DV_576P50, 411 V4L2_DV_576P50,
412 V4L2_DV_BT_CEA_720X576P50,
404 tvp7002_parms_576P, 413 tvp7002_parms_576P,
405 V4L2_COLORSPACE_SMPTE170M, 414 V4L2_COLORSPACE_SMPTE170M,
406 V4L2_FIELD_NONE, 415 V4L2_FIELD_NONE,
@@ -605,6 +614,35 @@ static int tvp7002_s_dv_preset(struct v4l2_subdev *sd,
605 return -EINVAL; 614 return -EINVAL;
606} 615}
607 616
617static int tvp7002_s_dv_timings(struct v4l2_subdev *sd,
618 struct v4l2_dv_timings *dv_timings)
619{
620 struct tvp7002 *device = to_tvp7002(sd);
621 const struct v4l2_bt_timings *bt = &dv_timings->bt;
622 int i;
623
624 if (dv_timings->type != V4L2_DV_BT_656_1120)
625 return -EINVAL;
626 for (i = 0; i < NUM_PRESETS; i++) {
627 const struct v4l2_bt_timings *t = &tvp7002_presets[i].timings.bt;
628
629 if (!memcmp(bt, t, &bt->standards - &bt->width)) {
630 device->current_preset = &tvp7002_presets[i];
631 return tvp7002_write_inittab(sd, tvp7002_presets[i].p_settings);
632 }
633 }
634 return -EINVAL;
635}
636
637static int tvp7002_g_dv_timings(struct v4l2_subdev *sd,
638 struct v4l2_dv_timings *dv_timings)
639{
640 struct tvp7002 *device = to_tvp7002(sd);
641
642 *dv_timings = device->current_preset->timings;
643 return 0;
644}
645
608/* 646/*
609 * tvp7002_s_ctrl() - Set a control 647 * tvp7002_s_ctrl() - Set a control
610 * @ctrl: ptr to v4l2_ctrl struct 648 * @ctrl: ptr to v4l2_ctrl struct
@@ -666,8 +704,7 @@ static int tvp7002_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f
666 * Returns the current DV preset by TVP7002. If no active input is 704 * Returns the current DV preset by TVP7002. If no active input is
667 * detected, returns -EINVAL 705 * detected, returns -EINVAL
668 */ 706 */
669static int tvp7002_query_dv_preset(struct v4l2_subdev *sd, 707static int tvp7002_query_dv(struct v4l2_subdev *sd, int *index)
670 struct v4l2_dv_preset *qpreset)
671{ 708{
672 const struct tvp7002_preset_definition *presets = tvp7002_presets; 709 const struct tvp7002_preset_definition *presets = tvp7002_presets;
673 u8 progressive; 710 u8 progressive;
@@ -678,10 +715,9 @@ static int tvp7002_query_dv_preset(struct v4l2_subdev *sd,
678 u8 lpf_msb; 715 u8 lpf_msb;
679 u8 cpl_lsb; 716 u8 cpl_lsb;
680 u8 cpl_msb; 717 u8 cpl_msb;
681 int index;
682 718
683 /* Return invalid preset if no active input is detected */ 719 /* Return invalid index if no active input is detected */
684 qpreset->preset = V4L2_DV_INVALID; 720 *index = NUM_PRESETS;
685 721
686 /* Read standards from device registers */ 722 /* Read standards from device registers */
687 tvp7002_read_err(sd, TVP7002_L_FRAME_STAT_LSBS, &lpf_lsb, &error); 723 tvp7002_read_err(sd, TVP7002_L_FRAME_STAT_LSBS, &lpf_lsb, &error);
@@ -702,8 +738,8 @@ static int tvp7002_query_dv_preset(struct v4l2_subdev *sd,
702 progressive = (lpf_msb & TVP7002_INPR_MASK) >> TVP7002_IP_SHIFT; 738 progressive = (lpf_msb & TVP7002_INPR_MASK) >> TVP7002_IP_SHIFT;
703 739
704 /* Do checking of video modes */ 740 /* Do checking of video modes */
705 for (index = 0; index < NUM_PRESETS; index++, presets++) 741 for (*index = 0; *index < NUM_PRESETS; (*index)++, presets++)
706 if (lpfr == presets->lines_per_frame && 742 if (lpfr == presets->lines_per_frame &&
707 progressive == presets->progressive) { 743 progressive == presets->progressive) {
708 if (presets->cpl_min == 0xffff) 744 if (presets->cpl_min == 0xffff)
709 break; 745 break;
@@ -711,17 +747,42 @@ static int tvp7002_query_dv_preset(struct v4l2_subdev *sd,
711 break; 747 break;
712 } 748 }
713 749
714 if (index == NUM_PRESETS) { 750 if (*index == NUM_PRESETS) {
715 v4l2_dbg(1, debug, sd, "detection failed: lpf = %x, cpl = %x\n", 751 v4l2_dbg(1, debug, sd, "detection failed: lpf = %x, cpl = %x\n",
716 lpfr, cpln); 752 lpfr, cpln);
717 return 0; 753 return -ENOLINK;
718 } 754 }
719 755
720 /* Set values in found preset */
721 qpreset->preset = presets->preset;
722
723 /* Update lines per frame and clocks per line info */ 756 /* Update lines per frame and clocks per line info */
724 v4l2_dbg(1, debug, sd, "detected preset: %d\n", presets->preset); 757 v4l2_dbg(1, debug, sd, "detected preset: %d\n", *index);
758 return 0;
759}
760
761static int tvp7002_query_dv_preset(struct v4l2_subdev *sd,
762 struct v4l2_dv_preset *qpreset)
763{
764 int index;
765 int err = tvp7002_query_dv(sd, &index);
766
767 if (err || index == NUM_PRESETS) {
768 qpreset->preset = V4L2_DV_INVALID;
769 if (err == -ENOLINK)
770 err = 0;
771 return err;
772 }
773 qpreset->preset = tvp7002_presets[index].preset;
774 return 0;
775}
776
777static int tvp7002_query_dv_timings(struct v4l2_subdev *sd,
778 struct v4l2_dv_timings *timings)
779{
780 int index;
781 int err = tvp7002_query_dv(sd, &index);
782
783 if (err)
784 return err;
785 *timings = tvp7002_presets[index].timings;
725 return 0; 786 return 0;
726} 787}
727 788
@@ -891,6 +952,17 @@ static int tvp7002_enum_dv_presets(struct v4l2_subdev *sd,
891 return v4l_fill_dv_preset_info(tvp7002_presets[preset->index].preset, preset); 952 return v4l_fill_dv_preset_info(tvp7002_presets[preset->index].preset, preset);
892} 953}
893 954
955static int tvp7002_enum_dv_timings(struct v4l2_subdev *sd,
956 struct v4l2_enum_dv_timings *timings)
957{
958 /* Check requested format index is within range */
959 if (timings->index >= NUM_PRESETS)
960 return -EINVAL;
961
962 timings->timings = tvp7002_presets[timings->index].timings;
963 return 0;
964}
965
894static const struct v4l2_ctrl_ops tvp7002_ctrl_ops = { 966static const struct v4l2_ctrl_ops tvp7002_ctrl_ops = {
895 .s_ctrl = tvp7002_s_ctrl, 967 .s_ctrl = tvp7002_s_ctrl,
896}; 968};
@@ -917,6 +989,10 @@ static const struct v4l2_subdev_video_ops tvp7002_video_ops = {
917 .enum_dv_presets = tvp7002_enum_dv_presets, 989 .enum_dv_presets = tvp7002_enum_dv_presets,
918 .s_dv_preset = tvp7002_s_dv_preset, 990 .s_dv_preset = tvp7002_s_dv_preset,
919 .query_dv_preset = tvp7002_query_dv_preset, 991 .query_dv_preset = tvp7002_query_dv_preset,
992 .g_dv_timings = tvp7002_g_dv_timings,
993 .s_dv_timings = tvp7002_s_dv_timings,
994 .enum_dv_timings = tvp7002_enum_dv_timings,
995 .query_dv_timings = tvp7002_query_dv_timings,
920 .s_stream = tvp7002_s_stream, 996 .s_stream = tvp7002_s_stream,
921 .g_mbus_fmt = tvp7002_mbus_fmt, 997 .g_mbus_fmt = tvp7002_mbus_fmt,
922 .try_mbus_fmt = tvp7002_mbus_fmt, 998 .try_mbus_fmt = tvp7002_mbus_fmt,