diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2013-03-04 07:29:33 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-03-23 09:59:06 -0400 |
commit | 5efb54b2b7bf685f5d2efdf468418e26a74554f2 (patch) | |
tree | 15f71e20d57af91258f86cae17bee76e2d473c2d | |
parent | 8cf2f7ad9749980a455d61b5664ccb553c12fd0e (diff) |
[media] s5p-tv: add dv_timings support for hdmi
This just adds dv_timings support without modifying existing dv_preset
support.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Tested-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Acked-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/platform/s5p-tv/hdmi_drv.c | 94 |
1 files changed, 81 insertions, 13 deletions
diff --git a/drivers/media/platform/s5p-tv/hdmi_drv.c b/drivers/media/platform/s5p-tv/hdmi_drv.c index 8de1b3dce459..c78f54cd5df9 100644 --- a/drivers/media/platform/s5p-tv/hdmi_drv.c +++ b/drivers/media/platform/s5p-tv/hdmi_drv.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/pm_runtime.h> | 31 | #include <linux/pm_runtime.h> |
32 | #include <linux/clk.h> | 32 | #include <linux/clk.h> |
33 | #include <linux/regulator/consumer.h> | 33 | #include <linux/regulator/consumer.h> |
34 | #include <linux/v4l2-dv-timings.h> | ||
34 | 35 | ||
35 | #include <media/s5p_hdmi.h> | 36 | #include <media/s5p_hdmi.h> |
36 | #include <media/v4l2-common.h> | 37 | #include <media/v4l2-common.h> |
@@ -93,6 +94,8 @@ struct hdmi_device { | |||
93 | int cur_conf_dirty; | 94 | int cur_conf_dirty; |
94 | /** current preset */ | 95 | /** current preset */ |
95 | u32 cur_preset; | 96 | u32 cur_preset; |
97 | /** current timings */ | ||
98 | struct v4l2_dv_timings cur_timings; | ||
96 | /** other resources */ | 99 | /** other resources */ |
97 | struct hdmi_resources res; | 100 | struct hdmi_resources res; |
98 | }; | 101 | }; |
@@ -477,19 +480,21 @@ static const struct hdmi_timings hdmi_timings_1080p50 = { | |||
477 | 480 | ||
478 | static const struct { | 481 | static const struct { |
479 | u32 preset; | 482 | u32 preset; |
480 | const struct hdmi_timings *timings; | 483 | bool reduced_fps; |
484 | const struct v4l2_dv_timings dv_timings; | ||
485 | const struct hdmi_timings *hdmi_timings; | ||
481 | } hdmi_timings[] = { | 486 | } hdmi_timings[] = { |
482 | { V4L2_DV_480P59_94, &hdmi_timings_480p }, | 487 | { V4L2_DV_480P59_94, false, V4L2_DV_BT_CEA_720X480P59_94, &hdmi_timings_480p }, |
483 | { V4L2_DV_576P50, &hdmi_timings_576p50 }, | 488 | { V4L2_DV_576P50, false, V4L2_DV_BT_CEA_720X576P50, &hdmi_timings_576p50 }, |
484 | { V4L2_DV_720P50, &hdmi_timings_720p50 }, | 489 | { V4L2_DV_720P50, false, V4L2_DV_BT_CEA_1280X720P50, &hdmi_timings_720p50 }, |
485 | { V4L2_DV_720P59_94, &hdmi_timings_720p60 }, | 490 | { V4L2_DV_720P59_94, true, V4L2_DV_BT_CEA_1280X720P60, &hdmi_timings_720p60 }, |
486 | { V4L2_DV_720P60, &hdmi_timings_720p60 }, | 491 | { V4L2_DV_720P60, false, V4L2_DV_BT_CEA_1280X720P60, &hdmi_timings_720p60 }, |
487 | { V4L2_DV_1080P24, &hdmi_timings_1080p24 }, | 492 | { V4L2_DV_1080P24, false, V4L2_DV_BT_CEA_1920X1080P24, &hdmi_timings_1080p24 }, |
488 | { V4L2_DV_1080P30, &hdmi_timings_1080p60 }, | 493 | { V4L2_DV_1080P30, false, V4L2_DV_BT_CEA_1920X1080P30, &hdmi_timings_1080p60 }, |
489 | { V4L2_DV_1080P50, &hdmi_timings_1080p50 }, | 494 | { V4L2_DV_1080P50, false, V4L2_DV_BT_CEA_1920X1080P50, &hdmi_timings_1080p50 }, |
490 | { V4L2_DV_1080I50, &hdmi_timings_1080i50 }, | 495 | { V4L2_DV_1080I50, false, V4L2_DV_BT_CEA_1920X1080I50, &hdmi_timings_1080i50 }, |
491 | { V4L2_DV_1080I60, &hdmi_timings_1080i60 }, | 496 | { V4L2_DV_1080I60, false, V4L2_DV_BT_CEA_1920X1080I60, &hdmi_timings_1080i60 }, |
492 | { V4L2_DV_1080P60, &hdmi_timings_1080p60 }, | 497 | { V4L2_DV_1080P60, false, V4L2_DV_BT_CEA_1920X1080P60, &hdmi_timings_1080p60 }, |
493 | }; | 498 | }; |
494 | 499 | ||
495 | static const struct hdmi_timings *hdmi_preset2timings(u32 preset) | 500 | static const struct hdmi_timings *hdmi_preset2timings(u32 preset) |
@@ -498,7 +503,7 @@ static const struct hdmi_timings *hdmi_preset2timings(u32 preset) | |||
498 | 503 | ||
499 | for (i = 0; i < ARRAY_SIZE(hdmi_timings); ++i) | 504 | for (i = 0; i < ARRAY_SIZE(hdmi_timings); ++i) |
500 | if (hdmi_timings[i].preset == preset) | 505 | if (hdmi_timings[i].preset == preset) |
501 | return hdmi_timings[i].timings; | 506 | return hdmi_timings[i].hdmi_timings; |
502 | return NULL; | 507 | return NULL; |
503 | } | 508 | } |
504 | 509 | ||
@@ -647,6 +652,36 @@ static int hdmi_g_dv_preset(struct v4l2_subdev *sd, | |||
647 | return 0; | 652 | return 0; |
648 | } | 653 | } |
649 | 654 | ||
655 | static int hdmi_s_dv_timings(struct v4l2_subdev *sd, | ||
656 | struct v4l2_dv_timings *timings) | ||
657 | { | ||
658 | struct hdmi_device *hdev = sd_to_hdmi_dev(sd); | ||
659 | struct device *dev = hdev->dev; | ||
660 | int i; | ||
661 | |||
662 | for (i = 0; i < ARRAY_SIZE(hdmi_timings); i++) | ||
663 | if (v4l_match_dv_timings(&hdmi_timings[i].dv_timings, | ||
664 | timings, 0)) | ||
665 | break; | ||
666 | if (i == ARRAY_SIZE(hdmi_timings)) { | ||
667 | dev_err(dev, "timings not supported\n"); | ||
668 | return -EINVAL; | ||
669 | } | ||
670 | hdev->cur_conf = hdmi_timings[i].hdmi_timings; | ||
671 | hdev->cur_conf_dirty = 1; | ||
672 | hdev->cur_timings = *timings; | ||
673 | if (!hdmi_timings[i].reduced_fps) | ||
674 | hdev->cur_timings.bt.flags &= ~V4L2_DV_FL_CAN_REDUCE_FPS; | ||
675 | return 0; | ||
676 | } | ||
677 | |||
678 | static int hdmi_g_dv_timings(struct v4l2_subdev *sd, | ||
679 | struct v4l2_dv_timings *timings) | ||
680 | { | ||
681 | *timings = sd_to_hdmi_dev(sd)->cur_timings; | ||
682 | return 0; | ||
683 | } | ||
684 | |||
650 | static int hdmi_g_mbus_fmt(struct v4l2_subdev *sd, | 685 | static int hdmi_g_mbus_fmt(struct v4l2_subdev *sd, |
651 | struct v4l2_mbus_framefmt *fmt) | 686 | struct v4l2_mbus_framefmt *fmt) |
652 | { | 687 | { |
@@ -679,6 +714,35 @@ static int hdmi_enum_dv_presets(struct v4l2_subdev *sd, | |||
679 | preset); | 714 | preset); |
680 | } | 715 | } |
681 | 716 | ||
717 | static int hdmi_enum_dv_timings(struct v4l2_subdev *sd, | ||
718 | struct v4l2_enum_dv_timings *timings) | ||
719 | { | ||
720 | if (timings->index >= ARRAY_SIZE(hdmi_timings)) | ||
721 | return -EINVAL; | ||
722 | timings->timings = hdmi_timings[timings->index].dv_timings; | ||
723 | if (!hdmi_timings[timings->index].reduced_fps) | ||
724 | timings->timings.bt.flags &= ~V4L2_DV_FL_CAN_REDUCE_FPS; | ||
725 | return 0; | ||
726 | } | ||
727 | |||
728 | static int hdmi_dv_timings_cap(struct v4l2_subdev *sd, | ||
729 | struct v4l2_dv_timings_cap *cap) | ||
730 | { | ||
731 | struct hdmi_device *hdev = sd_to_hdmi_dev(sd); | ||
732 | |||
733 | /* Let the phy fill in the pixelclock range */ | ||
734 | v4l2_subdev_call(hdev->phy_sd, video, dv_timings_cap, cap); | ||
735 | cap->type = V4L2_DV_BT_656_1120; | ||
736 | cap->bt.min_width = 720; | ||
737 | cap->bt.max_width = 1920; | ||
738 | cap->bt.min_height = 480; | ||
739 | cap->bt.max_height = 1080; | ||
740 | cap->bt.standards = V4L2_DV_BT_STD_CEA861; | ||
741 | cap->bt.capabilities = V4L2_DV_BT_CAP_INTERLACED | | ||
742 | V4L2_DV_BT_CAP_PROGRESSIVE; | ||
743 | return 0; | ||
744 | } | ||
745 | |||
682 | static const struct v4l2_subdev_core_ops hdmi_sd_core_ops = { | 746 | static const struct v4l2_subdev_core_ops hdmi_sd_core_ops = { |
683 | .s_power = hdmi_s_power, | 747 | .s_power = hdmi_s_power, |
684 | }; | 748 | }; |
@@ -687,6 +751,10 @@ static const struct v4l2_subdev_video_ops hdmi_sd_video_ops = { | |||
687 | .s_dv_preset = hdmi_s_dv_preset, | 751 | .s_dv_preset = hdmi_s_dv_preset, |
688 | .g_dv_preset = hdmi_g_dv_preset, | 752 | .g_dv_preset = hdmi_g_dv_preset, |
689 | .enum_dv_presets = hdmi_enum_dv_presets, | 753 | .enum_dv_presets = hdmi_enum_dv_presets, |
754 | .s_dv_timings = hdmi_s_dv_timings, | ||
755 | .g_dv_timings = hdmi_g_dv_timings, | ||
756 | .enum_dv_timings = hdmi_enum_dv_timings, | ||
757 | .dv_timings_cap = hdmi_dv_timings_cap, | ||
690 | .g_mbus_fmt = hdmi_g_mbus_fmt, | 758 | .g_mbus_fmt = hdmi_g_mbus_fmt, |
691 | .s_stream = hdmi_s_stream, | 759 | .s_stream = hdmi_s_stream, |
692 | }; | 760 | }; |