From patchwork Sat Feb 16 09:28:12 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Verkuil X-Patchwork-Id: 2151311 Return-Path: X-Original-To: patchwork-linux-media@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id 5F2A3DF2A1 for ; Sat, 16 Feb 2013 09:29:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753001Ab3BPJ3I (ORCPT ); Sat, 16 Feb 2013 04:29:08 -0500 Received: from smtp-vbr12.xs4all.nl ([194.109.24.32]:3000 "EHLO smtp-vbr12.xs4all.nl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752949Ab3BPJ25 (ORCPT ); Sat, 16 Feb 2013 04:28:57 -0500 Received: from alastor.dyndns.org (166.80-203-20.nextgentel.com [80.203.20.166] (may be forged)) (authenticated bits=0) by smtp-vbr12.xs4all.nl (8.13.8/8.13.8) with ESMTP id r1G9SfwI067372 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); Sat, 16 Feb 2013 10:28:42 +0100 (CET) (envelope-from hverkuil@xs4all.nl) Received: from durdane.fritz.box (marune.xs4all.nl [80.101.105.217]) (Authenticated sender: hans) by alastor.dyndns.org (Postfix) with ESMTPSA id AADD011E016D; Sat, 16 Feb 2013 10:28:33 +0100 (CET) From: Hans Verkuil To: linux-media@vger.kernel.org Cc: Prabhakar Lad , Tomasz Stanislawski , Kyungmin Park , Scott Jiang , Hans Verkuil Subject: [RFC PATCH 09/18] s5p-tv: add dv_timings support for hdmi. Date: Sat, 16 Feb 2013 10:28:12 +0100 Message-Id: <92ae3c7595637957ef1894921b9a451ffd458d16.1361006882.git.hans.verkuil@cisco.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1361006901-16103-1-git-send-email-hverkuil@xs4all.nl> References: <1361006901-16103-1-git-send-email-hverkuil@xs4all.nl> In-Reply-To: References: X-Virus-Scanned: by XS4ALL Virus Scanner Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org From: Hans Verkuil This just adds dv_timings support without modifying existing dv_preset support. Signed-off-by: Hans Verkuil Cc: Tomasz Stanislawski Cc: Kyungmin Park --- drivers/media/platform/s5p-tv/hdmi_drv.c | 92 +++++++++++++++++++++++++----- 1 file changed, 79 insertions(+), 13 deletions(-) diff --git a/drivers/media/platform/s5p-tv/hdmi_drv.c b/drivers/media/platform/s5p-tv/hdmi_drv.c index 8de1b3d..716d0e4 100644 --- a/drivers/media/platform/s5p-tv/hdmi_drv.c +++ b/drivers/media/platform/s5p-tv/hdmi_drv.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -93,6 +94,8 @@ struct hdmi_device { int cur_conf_dirty; /** current preset */ u32 cur_preset; + /** current timings */ + struct v4l2_dv_timings cur_timings; /** other resources */ struct hdmi_resources res; }; @@ -477,19 +480,21 @@ static const struct hdmi_timings hdmi_timings_1080p50 = { static const struct { u32 preset; - const struct hdmi_timings *timings; + bool reduced_fps; + const struct v4l2_dv_timings dv_timings; + const struct hdmi_timings *hdmi_timings; } hdmi_timings[] = { - { V4L2_DV_480P59_94, &hdmi_timings_480p }, - { V4L2_DV_576P50, &hdmi_timings_576p50 }, - { V4L2_DV_720P50, &hdmi_timings_720p50 }, - { V4L2_DV_720P59_94, &hdmi_timings_720p60 }, - { V4L2_DV_720P60, &hdmi_timings_720p60 }, - { V4L2_DV_1080P24, &hdmi_timings_1080p24 }, - { V4L2_DV_1080P30, &hdmi_timings_1080p60 }, - { V4L2_DV_1080P50, &hdmi_timings_1080p50 }, - { V4L2_DV_1080I50, &hdmi_timings_1080i50 }, - { V4L2_DV_1080I60, &hdmi_timings_1080i60 }, - { V4L2_DV_1080P60, &hdmi_timings_1080p60 }, + { V4L2_DV_480P59_94, false, V4L2_DV_BT_CEA_720X480P59_94, &hdmi_timings_480p }, + { V4L2_DV_576P50, false, V4L2_DV_BT_CEA_720X576P50, &hdmi_timings_576p50 }, + { V4L2_DV_720P50, false, V4L2_DV_BT_CEA_1280X720P50, &hdmi_timings_720p50 }, + { V4L2_DV_720P59_94, true, V4L2_DV_BT_CEA_1280X720P60, &hdmi_timings_720p60 }, + { V4L2_DV_720P60, false, V4L2_DV_BT_CEA_1280X720P60, &hdmi_timings_720p60 }, + { V4L2_DV_1080P24, false, V4L2_DV_BT_CEA_1920X1080P24, &hdmi_timings_1080p24 }, + { V4L2_DV_1080P30, false, V4L2_DV_BT_CEA_1920X1080P30, &hdmi_timings_1080p60 }, + { V4L2_DV_1080P50, false, V4L2_DV_BT_CEA_1920X1080P50, &hdmi_timings_1080p50 }, + { V4L2_DV_1080I50, false, V4L2_DV_BT_CEA_1920X1080I50, &hdmi_timings_1080i50 }, + { V4L2_DV_1080I60, false, V4L2_DV_BT_CEA_1920X1080I60, &hdmi_timings_1080i60 }, + { V4L2_DV_1080P60, false, V4L2_DV_BT_CEA_1920X1080P60, &hdmi_timings_1080p60 }, }; static const struct hdmi_timings *hdmi_preset2timings(u32 preset) @@ -498,7 +503,7 @@ static const struct hdmi_timings *hdmi_preset2timings(u32 preset) for (i = 0; i < ARRAY_SIZE(hdmi_timings); ++i) if (hdmi_timings[i].preset == preset) - return hdmi_timings[i].timings; + return hdmi_timings[i].hdmi_timings; return NULL; } @@ -647,6 +652,36 @@ static int hdmi_g_dv_preset(struct v4l2_subdev *sd, return 0; } +static int hdmi_s_dv_timings(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings) +{ + struct hdmi_device *hdev = sd_to_hdmi_dev(sd); + struct device *dev = hdev->dev; + int i; + + for (i = 0; i < ARRAY_SIZE(hdmi_timings); i++) + if (v4l_match_dv_timings(&hdmi_timings[i].dv_timings, + timings, 0)) + break; + if (i == ARRAY_SIZE(hdmi_timings)) { + dev_err(dev, "timings not supported\n"); + return -EINVAL; + } + hdev->cur_conf = hdmi_timings[i].hdmi_timings; + hdev->cur_conf_dirty = 1; + hdev->cur_timings = *timings; + if (!hdmi_timings[i].reduced_fps) + hdev->cur_timings.bt.flags &= ~V4L2_DV_FL_CAN_REDUCE_FPS; + return 0; +} + +static int hdmi_g_dv_timings(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings) +{ + *timings = sd_to_hdmi_dev(sd)->cur_timings; + return 0; +} + static int hdmi_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt) { @@ -679,6 +714,33 @@ static int hdmi_enum_dv_presets(struct v4l2_subdev *sd, preset); } +static int hdmi_enum_dv_timings(struct v4l2_subdev *sd, + struct v4l2_enum_dv_timings *timings) +{ + if (timings->index >= ARRAY_SIZE(hdmi_timings)) + return -EINVAL; + timings->timings = hdmi_timings[timings->index].dv_timings; + if (!hdmi_timings[timings->index].reduced_fps) + timings->timings.bt.flags &= ~V4L2_DV_FL_CAN_REDUCE_FPS; + return 0; +} + +static int hdmi_dv_timings_cap(struct v4l2_subdev *sd, + struct v4l2_dv_timings_cap *cap) +{ + cap->type = V4L2_DV_BT_656_1120; + cap->bt.min_width = 640; + cap->bt.max_width = 1920; + cap->bt.min_height = 480; + cap->bt.max_height = 1080; + cap->bt.min_pixelclock = 27000000; + cap->bt.max_pixelclock = 148500000; + cap->bt.standards = V4L2_DV_BT_STD_CEA861; + cap->bt.capabilities = V4L2_DV_BT_CAP_INTERLACED | + V4L2_DV_BT_CAP_PROGRESSIVE; + return 0; +} + static const struct v4l2_subdev_core_ops hdmi_sd_core_ops = { .s_power = hdmi_s_power, }; @@ -687,6 +749,10 @@ static const struct v4l2_subdev_video_ops hdmi_sd_video_ops = { .s_dv_preset = hdmi_s_dv_preset, .g_dv_preset = hdmi_g_dv_preset, .enum_dv_presets = hdmi_enum_dv_presets, + .s_dv_timings = hdmi_s_dv_timings, + .g_dv_timings = hdmi_g_dv_timings, + .enum_dv_timings = hdmi_enum_dv_timings, + .dv_timings_cap = hdmi_dv_timings_cap, .g_mbus_fmt = hdmi_g_mbus_fmt, .s_stream = hdmi_s_stream, };