From patchwork Tue Dec 18 14:12:42 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rahul Sharma X-Patchwork-Id: 1892401 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork2.kernel.org (Postfix) with ESMTP id A8032DF23A for ; Tue, 18 Dec 2012 14:48:14 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id B0997E6294 for ; Tue, 18 Dec 2012 06:48:14 -0800 (PST) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mailout1.samsung.com (mailout1.samsung.com [203.254.224.24]) by gabe.freedesktop.org (Postfix) with ESMTP id F2003E6223 for ; Tue, 18 Dec 2012 05:51:12 -0800 (PST) Received: from epcpsbgm2.samsung.com (epcpsbgm2 [203.254.230.27]) by mailout1.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MF80067HBT5UON0@mailout1.samsung.com> for dri-devel@lists.freedesktop.org; Tue, 18 Dec 2012 22:51:12 +0900 (KST) Received: from epcpsbgm2.samsung.com ( [172.20.52.123]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id 3F.9F.12699.EC470D05; Tue, 18 Dec 2012 22:51:10 +0900 (KST) X-AuditID: cbfee61b-b7f616d00000319b-00-50d074ceaa18 Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id BE.9F.12699.EC470D05; Tue, 18 Dec 2012 22:51:10 +0900 (KST) Received: from localhost.localdomain ([107.108.73.106]) by mmp1.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0MF8000A2BRD3R10@mmp1.samsung.com> for dri-devel@lists.freedesktop.org; Tue, 18 Dec 2012 22:51:10 +0900 (KST) From: Rahul Sharma To: dri-devel@lists.freedesktop.org Subject: [PATCH 1/2] drm/exynos: hdmi: add support for extra permissable resolutions Date: Tue, 18 Dec 2012 19:42:42 +0530 Message-id: <1355839963-28091-2-git-send-email-rahul.sharma@samsung.com> X-Mailer: git-send-email 1.7.0.4 In-reply-to: <1355839963-28091-1-git-send-email-rahul.sharma@samsung.com> References: <1355839963-28091-1-git-send-email-rahul.sharma@samsung.com> DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrHLMWRmVeSWpSXmKPExsWyRsSkWvdcyYUAgyN/rCyufH3P5sDocb/7 OFMAYxSXTUpqTmZZapG+XQJXxtdNy5gL1m9iqvj2OKKB8cBPxi5GDg4JAROJM0ckuhg5gUwx iQv31rN1MXJxCAksZZRo2nGcESJhIrGpt5sVIrGIUWLt3I+MEM5qJonzk86AVbEJ6ErMPvgM zBYRUJb4O3EVWBGzQBujRN/+zewgCWGBMIn+1ZuZQWwWAVWJNTfXgcV5BTwkGrZuglqnING6 7BBYnFPAU+Lx304mEFsIqObfp+1QvQIS3yYfYoF4QVZi0wFmkF0SAtfZJE62n2GDmCMpcXDF DZYJjMILGBlWMYqmFiQXFCel5xrpFSfmFpfmpesl5+duYgQG4ul/z6R3MK5qsDjEKMDBqMTD +zP+fIAQa2JZcWXuIUYJDmYlEd43cRcChHhTEiurUovy44tKc1KLDzH6AF0ykVlKNDkfGCV5 JfGGxibmpsamlkZGZqamOISVxHmbPVIChATSE0tSs1NTC1KLYMYxcXBKNTB25kzW4HNZdUXf U8P7nwzbK5mQiIBp30I8l+oxhtqsCHmXuCEvlfXbzQkLw/tZclbq/VW+e+bOtqVGhm5eRXaT Ck9q+9oeiedtcoueO4VX33PHra0JOZwuZ/o6lXf9vRHLnC507vSrUFmz80kq8kqFEcudYjaJ cT6/aib8zUSKeYdh/PXQHiWW4oxEQy3mouJEAE7XbalxAgAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFupjkeLIzCtJLcpLzFFi42I5/e+xgO65kgsBBsv+SFtc+fqezYHR4373 caYAxqgGRpuM1MSU1CKF1Lzk/JTMvHRbJe/geOd4UzMDQ11DSwtzJYW8xNxUWyUXnwBdt8wc oLFKCmWJOaVAoYDE4mIlfTtME0JD3HQtYBojdH1DguB6jAzQQMIaxoyvm5YxF6zfxFTx7XFE A+OBn4xdjJwcEgImEpt6u1khbDGJC/fWs3UxcnEICSxilFg79yMjhLOaSeL8pDNgHWwCuhKz Dz4Ds0UElCX+TlwFVsQs0MYo0bd/MztIQlggTKJ/9WZmEJtFQFVizc11YHFeAQ+Jhq2boFYr SLQuOwQW5xTwlHj8t5MJxBYCqvn3aTvzBEbeBYwMqxhFUwuSC4qT0nON9IoTc4tL89L1kvNz NzGCA/2Z9A7GVQ0WhxgFOBiVeHh/xp8PEGJNLCuuzD3EKMHBrCTC+ybuQoAQb0piZVVqUX58 UWlOavEhRh+gqyYyS4km5wOjMK8k3tDYxNzU2NTSxMLEzBKHsJI4b7NHSoCQQHpiSWp2ampB ahHMOCYOTqkGxgkyPeavPv9ljVu3dCPjpNMHOtMCb703k5zCVfl528aNFivX/5nOMfP66kMc E7uVJD/5yB2ZHiwYysnbn3BZa6lkgvN7Sc1ETv8imxc73RP/bT3+85L8Pvd6L9XUe+fP514u e8GVrCEwZerdLB+Vn4qfxUyYchNvmWz6zPa57GP44jMyUz8FMimxFGckGmoxFxUnAgBUJfFQ oQIAAA== X-CFilter-Loop: Reflected X-Mailman-Approved-At: Tue, 18 Dec 2012 06:46:08 -0800 Cc: kgene.kim@samsung.com, seanpaul@google.com, sw0312.kim@samsung.com, joshi@samsung.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Program the core and timing generator registers using the timing data provided in drm_display_mode instead of using hardcoded configurations. This allows us to support more standard resolutions like 640x480, 720x576 and 1680x1050. Additional PHY configs has been added to support extra refresh rates. It also reduces the duplication of the timing data. Signed-off-by: Rahul Sharma Signed-off-by: Sean Paul Signed-off-by: Shirish S Signed-off-by: Akshay Saraswat --- drivers/gpu/drm/exynos/exynos_hdmi.c | 1004 ++++++++++++---------------------- 1 files changed, 354 insertions(+), 650 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 68936e6..9afabe8 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -49,6 +49,8 @@ #define MAX_WIDTH 1920 #define MAX_HEIGHT 1080 #define get_hdmi_context(dev) platform_get_drvdata(to_platform_device(dev)) +#define hdmi_v14_mode_found(c, w, h) (((hdmi_v14_find_phy_conf(c) >= 0) && \ + (hdmi_v14_find_mode(w, h) >= 0)) ? 0 : (-EINVAL)) /* AVI header and aspect ratio */ #define HDMI_AVI_VERSION 0x02 @@ -88,6 +90,73 @@ struct hdmi_resources { int regul_count; }; +struct hdmi_tg_regs { + u8 cmd[1]; + u8 h_fsz[2]; + u8 hact_st[2]; + u8 hact_sz[2]; + u8 v_fsz[2]; + u8 vsync[2]; + u8 vsync2[2]; + u8 vact_st[2]; + u8 vact_sz[2]; + u8 field_chg[2]; + u8 vact_st2[2]; + u8 vact_st3[2]; + u8 vact_st4[2]; + u8 vsync_top_hdmi[2]; + u8 vsync_bot_hdmi[2]; + u8 field_top_hdmi[2]; + u8 field_bot_hdmi[2]; + u8 tg_3d[1]; +}; + +struct hdmi_core_regs { + u8 h_blank[2]; + u8 v2_blank[2]; + u8 v1_blank[2]; + u8 v_line[2]; + u8 h_line[2]; + u8 hsync_pol[1]; + u8 vsync_pol[1]; + u8 int_pro_mode[1]; + u8 v_blank_f0[2]; + u8 v_blank_f1[2]; + u8 h_sync_start[2]; + u8 h_sync_end[2]; + u8 v_sync_line_bef_2[2]; + u8 v_sync_line_bef_1[2]; + u8 v_sync_line_aft_2[2]; + u8 v_sync_line_aft_1[2]; + u8 v_sync_line_aft_pxl_2[2]; + u8 v_sync_line_aft_pxl_1[2]; + u8 v_blank_f2[2]; /* for 3D mode */ + u8 v_blank_f3[2]; /* for 3D mode */ + u8 v_blank_f4[2]; /* for 3D mode */ + u8 v_blank_f5[2]; /* for 3D mode */ + u8 v_sync_line_aft_3[2]; + u8 v_sync_line_aft_4[2]; + u8 v_sync_line_aft_5[2]; + u8 v_sync_line_aft_6[2]; + u8 v_sync_line_aft_pxl_3[2]; + u8 v_sync_line_aft_pxl_4[2]; + u8 v_sync_line_aft_pxl_5[2]; + u8 v_sync_line_aft_pxl_6[2]; + u8 vact_space_1[2]; + u8 vact_space_2[2]; + u8 vact_space_3[2]; + u8 vact_space_4[2]; + u8 vact_space_5[2]; + u8 vact_space_6[2]; +}; + +struct hdmi_v14_conf { + int pixel_clock; + struct hdmi_core_regs core; + struct hdmi_tg_regs tg; + int cea_video_id; +}; + struct hdmi_context { struct device *dev; struct drm_device *drm_dev; @@ -106,6 +175,7 @@ struct hdmi_context { /* current hdmiphy conf index */ int cur_conf; + struct hdmi_v14_conf mode_conf; struct hdmi_resources res; @@ -394,584 +464,91 @@ static const struct hdmi_v13_conf hdmi_v13_confs[] = { }; /* HDMI Version 1.4 */ -static const u8 hdmiphy_conf27_027[32] = { - 0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08, - 0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80, - 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, - 0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, -}; - -static const u8 hdmiphy_conf74_176[32] = { - 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x5b, 0xef, 0x08, - 0x81, 0xa0, 0xb9, 0xd8, 0x45, 0xa0, 0xac, 0x80, - 0x5a, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, - 0x54, 0xa6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00, -}; - -static const u8 hdmiphy_conf74_25[32] = { - 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08, - 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80, - 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, - 0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00, -}; - -static const u8 hdmiphy_conf148_5[32] = { - 0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08, - 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80, - 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, - 0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00, -}; - -struct hdmi_tg_regs { - u8 cmd; - u8 h_fsz_l; - u8 h_fsz_h; - u8 hact_st_l; - u8 hact_st_h; - u8 hact_sz_l; - u8 hact_sz_h; - u8 v_fsz_l; - u8 v_fsz_h; - u8 vsync_l; - u8 vsync_h; - u8 vsync2_l; - u8 vsync2_h; - u8 vact_st_l; - u8 vact_st_h; - u8 vact_sz_l; - u8 vact_sz_h; - u8 field_chg_l; - u8 field_chg_h; - u8 vact_st2_l; - u8 vact_st2_h; - u8 vact_st3_l; - u8 vact_st3_h; - u8 vact_st4_l; - u8 vact_st4_h; - u8 vsync_top_hdmi_l; - u8 vsync_top_hdmi_h; - u8 vsync_bot_hdmi_l; - u8 vsync_bot_hdmi_h; - u8 field_top_hdmi_l; - u8 field_top_hdmi_h; - u8 field_bot_hdmi_l; - u8 field_bot_hdmi_h; - u8 tg_3d; -}; - -struct hdmi_core_regs { - u8 h_blank[2]; - u8 v2_blank[2]; - u8 v1_blank[2]; - u8 v_line[2]; - u8 h_line[2]; - u8 hsync_pol[1]; - u8 vsync_pol[1]; - u8 int_pro_mode[1]; - u8 v_blank_f0[2]; - u8 v_blank_f1[2]; - u8 h_sync_start[2]; - u8 h_sync_end[2]; - u8 v_sync_line_bef_2[2]; - u8 v_sync_line_bef_1[2]; - u8 v_sync_line_aft_2[2]; - u8 v_sync_line_aft_1[2]; - u8 v_sync_line_aft_pxl_2[2]; - u8 v_sync_line_aft_pxl_1[2]; - u8 v_blank_f2[2]; /* for 3D mode */ - u8 v_blank_f3[2]; /* for 3D mode */ - u8 v_blank_f4[2]; /* for 3D mode */ - u8 v_blank_f5[2]; /* for 3D mode */ - u8 v_sync_line_aft_3[2]; - u8 v_sync_line_aft_4[2]; - u8 v_sync_line_aft_5[2]; - u8 v_sync_line_aft_6[2]; - u8 v_sync_line_aft_pxl_3[2]; - u8 v_sync_line_aft_pxl_4[2]; - u8 v_sync_line_aft_pxl_5[2]; - u8 v_sync_line_aft_pxl_6[2]; - u8 vact_space_1[2]; - u8 vact_space_2[2]; - u8 vact_space_3[2]; - u8 vact_space_4[2]; - u8 vact_space_5[2]; - u8 vact_space_6[2]; -}; - -struct hdmi_preset_conf { - struct hdmi_core_regs core; - struct hdmi_tg_regs tg; -}; - -struct hdmi_conf { - int width; - int height; - int vrefresh; - bool interlace; - int cea_video_id; - const u8 *hdmiphy_data; - const struct hdmi_preset_conf *conf; -}; - -static const struct hdmi_preset_conf hdmi_conf_480p60 = { - .core = { - .h_blank = {0x8a, 0x00}, - .v2_blank = {0x0d, 0x02}, - .v1_blank = {0x2d, 0x00}, - .v_line = {0x0d, 0x02}, - .h_line = {0x5a, 0x03}, - .hsync_pol = {0x01}, - .vsync_pol = {0x01}, - .int_pro_mode = {0x00}, - .v_blank_f0 = {0xff, 0xff}, - .v_blank_f1 = {0xff, 0xff}, - .h_sync_start = {0x0e, 0x00}, - .h_sync_end = {0x4c, 0x00}, - .v_sync_line_bef_2 = {0x0f, 0x00}, - .v_sync_line_bef_1 = {0x09, 0x00}, - .v_sync_line_aft_2 = {0xff, 0xff}, - .v_sync_line_aft_1 = {0xff, 0xff}, - .v_sync_line_aft_pxl_2 = {0xff, 0xff}, - .v_sync_line_aft_pxl_1 = {0xff, 0xff}, - .v_blank_f2 = {0xff, 0xff}, - .v_blank_f3 = {0xff, 0xff}, - .v_blank_f4 = {0xff, 0xff}, - .v_blank_f5 = {0xff, 0xff}, - .v_sync_line_aft_3 = {0xff, 0xff}, - .v_sync_line_aft_4 = {0xff, 0xff}, - .v_sync_line_aft_5 = {0xff, 0xff}, - .v_sync_line_aft_6 = {0xff, 0xff}, - .v_sync_line_aft_pxl_3 = {0xff, 0xff}, - .v_sync_line_aft_pxl_4 = {0xff, 0xff}, - .v_sync_line_aft_pxl_5 = {0xff, 0xff}, - .v_sync_line_aft_pxl_6 = {0xff, 0xff}, - .vact_space_1 = {0xff, 0xff}, - .vact_space_2 = {0xff, 0xff}, - .vact_space_3 = {0xff, 0xff}, - .vact_space_4 = {0xff, 0xff}, - .vact_space_5 = {0xff, 0xff}, - .vact_space_6 = {0xff, 0xff}, - /* other don't care */ - }, - .tg = { - 0x00, /* cmd */ - 0x5a, 0x03, /* h_fsz */ - 0x8a, 0x00, 0xd0, 0x02, /* hact */ - 0x0d, 0x02, /* v_fsz */ - 0x01, 0x00, 0x33, 0x02, /* vsync */ - 0x2d, 0x00, 0xe0, 0x01, /* vact */ - 0x33, 0x02, /* field_chg */ - 0x48, 0x02, /* vact_st2 */ - 0x00, 0x00, /* vact_st3 */ - 0x00, 0x00, /* vact_st4 */ - 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ - 0x01, 0x00, 0x33, 0x02, /* field top/bot */ - 0x00, /* 3d FP */ - }, -}; - -static const struct hdmi_preset_conf hdmi_conf_720p50 = { - .core = { - .h_blank = {0xbc, 0x02}, - .v2_blank = {0xee, 0x02}, - .v1_blank = {0x1e, 0x00}, - .v_line = {0xee, 0x02}, - .h_line = {0xbc, 0x07}, - .hsync_pol = {0x00}, - .vsync_pol = {0x00}, - .int_pro_mode = {0x00}, - .v_blank_f0 = {0xff, 0xff}, - .v_blank_f1 = {0xff, 0xff}, - .h_sync_start = {0xb6, 0x01}, - .h_sync_end = {0xde, 0x01}, - .v_sync_line_bef_2 = {0x0a, 0x00}, - .v_sync_line_bef_1 = {0x05, 0x00}, - .v_sync_line_aft_2 = {0xff, 0xff}, - .v_sync_line_aft_1 = {0xff, 0xff}, - .v_sync_line_aft_pxl_2 = {0xff, 0xff}, - .v_sync_line_aft_pxl_1 = {0xff, 0xff}, - .v_blank_f2 = {0xff, 0xff}, - .v_blank_f3 = {0xff, 0xff}, - .v_blank_f4 = {0xff, 0xff}, - .v_blank_f5 = {0xff, 0xff}, - .v_sync_line_aft_3 = {0xff, 0xff}, - .v_sync_line_aft_4 = {0xff, 0xff}, - .v_sync_line_aft_5 = {0xff, 0xff}, - .v_sync_line_aft_6 = {0xff, 0xff}, - .v_sync_line_aft_pxl_3 = {0xff, 0xff}, - .v_sync_line_aft_pxl_4 = {0xff, 0xff}, - .v_sync_line_aft_pxl_5 = {0xff, 0xff}, - .v_sync_line_aft_pxl_6 = {0xff, 0xff}, - .vact_space_1 = {0xff, 0xff}, - .vact_space_2 = {0xff, 0xff}, - .vact_space_3 = {0xff, 0xff}, - .vact_space_4 = {0xff, 0xff}, - .vact_space_5 = {0xff, 0xff}, - .vact_space_6 = {0xff, 0xff}, - /* other don't care */ - }, - .tg = { - 0x00, /* cmd */ - 0xbc, 0x07, /* h_fsz */ - 0xbc, 0x02, 0x00, 0x05, /* hact */ - 0xee, 0x02, /* v_fsz */ - 0x01, 0x00, 0x33, 0x02, /* vsync */ - 0x1e, 0x00, 0xd0, 0x02, /* vact */ - 0x33, 0x02, /* field_chg */ - 0x48, 0x02, /* vact_st2 */ - 0x00, 0x00, /* vact_st3 */ - 0x00, 0x00, /* vact_st4 */ - 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ - 0x01, 0x00, 0x33, 0x02, /* field top/bot */ - 0x00, /* 3d FP */ - }, -}; - -static const struct hdmi_preset_conf hdmi_conf_720p60 = { - .core = { - .h_blank = {0x72, 0x01}, - .v2_blank = {0xee, 0x02}, - .v1_blank = {0x1e, 0x00}, - .v_line = {0xee, 0x02}, - .h_line = {0x72, 0x06}, - .hsync_pol = {0x00}, - .vsync_pol = {0x00}, - .int_pro_mode = {0x00}, - .v_blank_f0 = {0xff, 0xff}, - .v_blank_f1 = {0xff, 0xff}, - .h_sync_start = {0x6c, 0x00}, - .h_sync_end = {0x94, 0x00}, - .v_sync_line_bef_2 = {0x0a, 0x00}, - .v_sync_line_bef_1 = {0x05, 0x00}, - .v_sync_line_aft_2 = {0xff, 0xff}, - .v_sync_line_aft_1 = {0xff, 0xff}, - .v_sync_line_aft_pxl_2 = {0xff, 0xff}, - .v_sync_line_aft_pxl_1 = {0xff, 0xff}, - .v_blank_f2 = {0xff, 0xff}, - .v_blank_f3 = {0xff, 0xff}, - .v_blank_f4 = {0xff, 0xff}, - .v_blank_f5 = {0xff, 0xff}, - .v_sync_line_aft_3 = {0xff, 0xff}, - .v_sync_line_aft_4 = {0xff, 0xff}, - .v_sync_line_aft_5 = {0xff, 0xff}, - .v_sync_line_aft_6 = {0xff, 0xff}, - .v_sync_line_aft_pxl_3 = {0xff, 0xff}, - .v_sync_line_aft_pxl_4 = {0xff, 0xff}, - .v_sync_line_aft_pxl_5 = {0xff, 0xff}, - .v_sync_line_aft_pxl_6 = {0xff, 0xff}, - .vact_space_1 = {0xff, 0xff}, - .vact_space_2 = {0xff, 0xff}, - .vact_space_3 = {0xff, 0xff}, - .vact_space_4 = {0xff, 0xff}, - .vact_space_5 = {0xff, 0xff}, - .vact_space_6 = {0xff, 0xff}, - /* other don't care */ - }, - .tg = { - 0x00, /* cmd */ - 0x72, 0x06, /* h_fsz */ - 0x72, 0x01, 0x00, 0x05, /* hact */ - 0xee, 0x02, /* v_fsz */ - 0x01, 0x00, 0x33, 0x02, /* vsync */ - 0x1e, 0x00, 0xd0, 0x02, /* vact */ - 0x33, 0x02, /* field_chg */ - 0x48, 0x02, /* vact_st2 */ - 0x00, 0x00, /* vact_st3 */ - 0x00, 0x00, /* vact_st4 */ - 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ - 0x01, 0x00, 0x33, 0x02, /* field top/bot */ - 0x00, /* 3d FP */ - }, +struct hdmiphy_config { + int pixel_clock; + u8 conf[32]; }; -static const struct hdmi_preset_conf hdmi_conf_1080i50 = { - .core = { - .h_blank = {0xd0, 0x02}, - .v2_blank = {0x32, 0x02}, - .v1_blank = {0x16, 0x00}, - .v_line = {0x65, 0x04}, - .h_line = {0x50, 0x0a}, - .hsync_pol = {0x00}, - .vsync_pol = {0x00}, - .int_pro_mode = {0x01}, - .v_blank_f0 = {0x49, 0x02}, - .v_blank_f1 = {0x65, 0x04}, - .h_sync_start = {0x0e, 0x02}, - .h_sync_end = {0x3a, 0x02}, - .v_sync_line_bef_2 = {0x07, 0x00}, - .v_sync_line_bef_1 = {0x02, 0x00}, - .v_sync_line_aft_2 = {0x39, 0x02}, - .v_sync_line_aft_1 = {0x34, 0x02}, - .v_sync_line_aft_pxl_2 = {0x38, 0x07}, - .v_sync_line_aft_pxl_1 = {0x38, 0x07}, - .v_blank_f2 = {0xff, 0xff}, - .v_blank_f3 = {0xff, 0xff}, - .v_blank_f4 = {0xff, 0xff}, - .v_blank_f5 = {0xff, 0xff}, - .v_sync_line_aft_3 = {0xff, 0xff}, - .v_sync_line_aft_4 = {0xff, 0xff}, - .v_sync_line_aft_5 = {0xff, 0xff}, - .v_sync_line_aft_6 = {0xff, 0xff}, - .v_sync_line_aft_pxl_3 = {0xff, 0xff}, - .v_sync_line_aft_pxl_4 = {0xff, 0xff}, - .v_sync_line_aft_pxl_5 = {0xff, 0xff}, - .v_sync_line_aft_pxl_6 = {0xff, 0xff}, - .vact_space_1 = {0xff, 0xff}, - .vact_space_2 = {0xff, 0xff}, - .vact_space_3 = {0xff, 0xff}, - .vact_space_4 = {0xff, 0xff}, - .vact_space_5 = {0xff, 0xff}, - .vact_space_6 = {0xff, 0xff}, - /* other don't care */ - }, - .tg = { - 0x00, /* cmd */ - 0x50, 0x0a, /* h_fsz */ - 0xd0, 0x02, 0x80, 0x07, /* hact */ - 0x65, 0x04, /* v_fsz */ - 0x01, 0x00, 0x33, 0x02, /* vsync */ - 0x16, 0x00, 0x1c, 0x02, /* vact */ - 0x33, 0x02, /* field_chg */ - 0x49, 0x02, /* vact_st2 */ - 0x00, 0x00, /* vact_st3 */ - 0x00, 0x00, /* vact_st4 */ - 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */ - 0x01, 0x00, 0x33, 0x02, /* field top/bot */ - 0x00, /* 3d FP */ +/* list of all required phy config settings */ +static const struct hdmiphy_config hdmiphy_v14_configs[] = { + { + .pixel_clock = 25200000, + .conf = { + 0x01, 0x51, 0x2A, 0x75, 0x40, 0x01, 0x00, 0x08, + 0x82, 0x80, 0xfc, 0xd8, 0x45, 0xa0, 0xac, 0x80, + 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, + 0x54, 0xf4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80, + }, }, -}; - -static const struct hdmi_preset_conf hdmi_conf_1080i60 = { - .core = { - .h_blank = {0x18, 0x01}, - .v2_blank = {0x32, 0x02}, - .v1_blank = {0x16, 0x00}, - .v_line = {0x65, 0x04}, - .h_line = {0x98, 0x08}, - .hsync_pol = {0x00}, - .vsync_pol = {0x00}, - .int_pro_mode = {0x01}, - .v_blank_f0 = {0x49, 0x02}, - .v_blank_f1 = {0x65, 0x04}, - .h_sync_start = {0x56, 0x00}, - .h_sync_end = {0x82, 0x00}, - .v_sync_line_bef_2 = {0x07, 0x00}, - .v_sync_line_bef_1 = {0x02, 0x00}, - .v_sync_line_aft_2 = {0x39, 0x02}, - .v_sync_line_aft_1 = {0x34, 0x02}, - .v_sync_line_aft_pxl_2 = {0xa4, 0x04}, - .v_sync_line_aft_pxl_1 = {0xa4, 0x04}, - .v_blank_f2 = {0xff, 0xff}, - .v_blank_f3 = {0xff, 0xff}, - .v_blank_f4 = {0xff, 0xff}, - .v_blank_f5 = {0xff, 0xff}, - .v_sync_line_aft_3 = {0xff, 0xff}, - .v_sync_line_aft_4 = {0xff, 0xff}, - .v_sync_line_aft_5 = {0xff, 0xff}, - .v_sync_line_aft_6 = {0xff, 0xff}, - .v_sync_line_aft_pxl_3 = {0xff, 0xff}, - .v_sync_line_aft_pxl_4 = {0xff, 0xff}, - .v_sync_line_aft_pxl_5 = {0xff, 0xff}, - .v_sync_line_aft_pxl_6 = {0xff, 0xff}, - .vact_space_1 = {0xff, 0xff}, - .vact_space_2 = {0xff, 0xff}, - .vact_space_3 = {0xff, 0xff}, - .vact_space_4 = {0xff, 0xff}, - .vact_space_5 = {0xff, 0xff}, - .vact_space_6 = {0xff, 0xff}, - /* other don't care */ + { + .pixel_clock = 27000000, + .conf = { + 0x01, 0xd1, 0x22, 0x51, 0x40, 0x08, 0xfc, 0x20, + 0x98, 0xa0, 0xcb, 0xd8, 0x45, 0xa0, 0xac, 0x80, + 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, + 0x54, 0xe4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80, + }, }, - .tg = { - 0x00, /* cmd */ - 0x98, 0x08, /* h_fsz */ - 0x18, 0x01, 0x80, 0x07, /* hact */ - 0x65, 0x04, /* v_fsz */ - 0x01, 0x00, 0x33, 0x02, /* vsync */ - 0x16, 0x00, 0x1c, 0x02, /* vact */ - 0x33, 0x02, /* field_chg */ - 0x49, 0x02, /* vact_st2 */ - 0x00, 0x00, /* vact_st3 */ - 0x00, 0x00, /* vact_st4 */ - 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */ - 0x01, 0x00, 0x33, 0x02, /* field top/bot */ - 0x00, /* 3d FP */ + { + .pixel_clock = 36000000, + .conf = { + 0x01, 0x51, 0x2d, 0x55, 0x40, 0x01, 0x00, 0x08, + 0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80, + 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, + 0x54, 0xab, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80, + }, }, -}; - -static const struct hdmi_preset_conf hdmi_conf_1080p30 = { - .core = { - .h_blank = {0x18, 0x01}, - .v2_blank = {0x65, 0x04}, - .v1_blank = {0x2d, 0x00}, - .v_line = {0x65, 0x04}, - .h_line = {0x98, 0x08}, - .hsync_pol = {0x00}, - .vsync_pol = {0x00}, - .int_pro_mode = {0x00}, - .v_blank_f0 = {0xff, 0xff}, - .v_blank_f1 = {0xff, 0xff}, - .h_sync_start = {0x56, 0x00}, - .h_sync_end = {0x82, 0x00}, - .v_sync_line_bef_2 = {0x09, 0x00}, - .v_sync_line_bef_1 = {0x04, 0x00}, - .v_sync_line_aft_2 = {0xff, 0xff}, - .v_sync_line_aft_1 = {0xff, 0xff}, - .v_sync_line_aft_pxl_2 = {0xff, 0xff}, - .v_sync_line_aft_pxl_1 = {0xff, 0xff}, - .v_blank_f2 = {0xff, 0xff}, - .v_blank_f3 = {0xff, 0xff}, - .v_blank_f4 = {0xff, 0xff}, - .v_blank_f5 = {0xff, 0xff}, - .v_sync_line_aft_3 = {0xff, 0xff}, - .v_sync_line_aft_4 = {0xff, 0xff}, - .v_sync_line_aft_5 = {0xff, 0xff}, - .v_sync_line_aft_6 = {0xff, 0xff}, - .v_sync_line_aft_pxl_3 = {0xff, 0xff}, - .v_sync_line_aft_pxl_4 = {0xff, 0xff}, - .v_sync_line_aft_pxl_5 = {0xff, 0xff}, - .v_sync_line_aft_pxl_6 = {0xff, 0xff}, - .vact_space_1 = {0xff, 0xff}, - .vact_space_2 = {0xff, 0xff}, - .vact_space_3 = {0xff, 0xff}, - .vact_space_4 = {0xff, 0xff}, - .vact_space_5 = {0xff, 0xff}, - .vact_space_6 = {0xff, 0xff}, - /* other don't care */ + { + .pixel_clock = 74250000, + .conf = { + 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08, + 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80, + 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, + 0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00, + }, }, - .tg = { - 0x00, /* cmd */ - 0x98, 0x08, /* h_fsz */ - 0x18, 0x01, 0x80, 0x07, /* hact */ - 0x65, 0x04, /* v_fsz */ - 0x01, 0x00, 0x33, 0x02, /* vsync */ - 0x2d, 0x00, 0x38, 0x04, /* vact */ - 0x33, 0x02, /* field_chg */ - 0x48, 0x02, /* vact_st2 */ - 0x00, 0x00, /* vact_st3 */ - 0x00, 0x00, /* vact_st4 */ - 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ - 0x01, 0x00, 0x33, 0x02, /* field top/bot */ - 0x00, /* 3d FP */ + { + .pixel_clock = 108000000, + .conf = { + 0x01, 0x51, 0x2d, 0x15, 0x40, 0x01, 0x00, 0x08, + 0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80, + 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, + 0x54, 0xc7, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80, + }, }, -}; - -static const struct hdmi_preset_conf hdmi_conf_1080p50 = { - .core = { - .h_blank = {0xd0, 0x02}, - .v2_blank = {0x65, 0x04}, - .v1_blank = {0x2d, 0x00}, - .v_line = {0x65, 0x04}, - .h_line = {0x50, 0x0a}, - .hsync_pol = {0x00}, - .vsync_pol = {0x00}, - .int_pro_mode = {0x00}, - .v_blank_f0 = {0xff, 0xff}, - .v_blank_f1 = {0xff, 0xff}, - .h_sync_start = {0x0e, 0x02}, - .h_sync_end = {0x3a, 0x02}, - .v_sync_line_bef_2 = {0x09, 0x00}, - .v_sync_line_bef_1 = {0x04, 0x00}, - .v_sync_line_aft_2 = {0xff, 0xff}, - .v_sync_line_aft_1 = {0xff, 0xff}, - .v_sync_line_aft_pxl_2 = {0xff, 0xff}, - .v_sync_line_aft_pxl_1 = {0xff, 0xff}, - .v_blank_f2 = {0xff, 0xff}, - .v_blank_f3 = {0xff, 0xff}, - .v_blank_f4 = {0xff, 0xff}, - .v_blank_f5 = {0xff, 0xff}, - .v_sync_line_aft_3 = {0xff, 0xff}, - .v_sync_line_aft_4 = {0xff, 0xff}, - .v_sync_line_aft_5 = {0xff, 0xff}, - .v_sync_line_aft_6 = {0xff, 0xff}, - .v_sync_line_aft_pxl_3 = {0xff, 0xff}, - .v_sync_line_aft_pxl_4 = {0xff, 0xff}, - .v_sync_line_aft_pxl_5 = {0xff, 0xff}, - .v_sync_line_aft_pxl_6 = {0xff, 0xff}, - .vact_space_1 = {0xff, 0xff}, - .vact_space_2 = {0xff, 0xff}, - .vact_space_3 = {0xff, 0xff}, - .vact_space_4 = {0xff, 0xff}, - .vact_space_5 = {0xff, 0xff}, - .vact_space_6 = {0xff, 0xff}, - /* other don't care */ + { + .pixel_clock = 146250000, + .conf = { + 0x01, 0xd1, 0x3d, 0x15, 0x40, 0x18, 0xfd, 0x08, + 0x83, 0xa0, 0x6e, 0xd9, 0x45, 0xa0, 0xac, 0x80, + 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, + 0x54, 0x50, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80, + }, }, - .tg = { - 0x00, /* cmd */ - 0x50, 0x0a, /* h_fsz */ - 0xd0, 0x02, 0x80, 0x07, /* hact */ - 0x65, 0x04, /* v_fsz */ - 0x01, 0x00, 0x33, 0x02, /* vsync */ - 0x2d, 0x00, 0x38, 0x04, /* vact */ - 0x33, 0x02, /* field_chg */ - 0x48, 0x02, /* vact_st2 */ - 0x00, 0x00, /* vact_st3 */ - 0x00, 0x00, /* vact_st4 */ - 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ - 0x01, 0x00, 0x33, 0x02, /* field top/bot */ - 0x00, /* 3d FP */ + { + .pixel_clock = 148500000, + .conf = { + 0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08, + 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80, + 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, + 0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00, + }, }, }; -static const struct hdmi_preset_conf hdmi_conf_1080p60 = { - .core = { - .h_blank = {0x18, 0x01}, - .v2_blank = {0x65, 0x04}, - .v1_blank = {0x2d, 0x00}, - .v_line = {0x65, 0x04}, - .h_line = {0x98, 0x08}, - .hsync_pol = {0x00}, - .vsync_pol = {0x00}, - .int_pro_mode = {0x00}, - .v_blank_f0 = {0xff, 0xff}, - .v_blank_f1 = {0xff, 0xff}, - .h_sync_start = {0x56, 0x00}, - .h_sync_end = {0x82, 0x00}, - .v_sync_line_bef_2 = {0x09, 0x00}, - .v_sync_line_bef_1 = {0x04, 0x00}, - .v_sync_line_aft_2 = {0xff, 0xff}, - .v_sync_line_aft_1 = {0xff, 0xff}, - .v_sync_line_aft_pxl_2 = {0xff, 0xff}, - .v_sync_line_aft_pxl_1 = {0xff, 0xff}, - .v_blank_f2 = {0xff, 0xff}, - .v_blank_f3 = {0xff, 0xff}, - .v_blank_f4 = {0xff, 0xff}, - .v_blank_f5 = {0xff, 0xff}, - .v_sync_line_aft_3 = {0xff, 0xff}, - .v_sync_line_aft_4 = {0xff, 0xff}, - .v_sync_line_aft_5 = {0xff, 0xff}, - .v_sync_line_aft_6 = {0xff, 0xff}, - .v_sync_line_aft_pxl_3 = {0xff, 0xff}, - .v_sync_line_aft_pxl_4 = {0xff, 0xff}, - .v_sync_line_aft_pxl_5 = {0xff, 0xff}, - .v_sync_line_aft_pxl_6 = {0xff, 0xff}, - /* other don't care */ - }, - .tg = { - 0x00, /* cmd */ - 0x98, 0x08, /* h_fsz */ - 0x18, 0x01, 0x80, 0x07, /* hact */ - 0x65, 0x04, /* v_fsz */ - 0x01, 0x00, 0x33, 0x02, /* vsync */ - 0x2d, 0x00, 0x38, 0x04, /* vact */ - 0x33, 0x02, /* field_chg */ - 0x48, 0x02, /* vact_st2 */ - 0x00, 0x00, /* vact_st3 */ - 0x00, 0x00, /* vact_st4 */ - 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ - 0x01, 0x00, 0x33, 0x02, /* field top/bot */ - 0x00, /* 3d FP */ - }, +struct hdmi_modes { + int width; + int height; }; -static const struct hdmi_conf hdmi_confs[] = { - { 720, 480, 60, false, 3, hdmiphy_conf27_027, &hdmi_conf_480p60 }, - { 1280, 720, 50, false, 19, hdmiphy_conf74_25, &hdmi_conf_720p50 }, - { 1280, 720, 60, false, 4, hdmiphy_conf74_25, &hdmi_conf_720p60 }, - { 1920, 1080, 50, true, 20, hdmiphy_conf74_25, &hdmi_conf_1080i50 }, - { 1920, 1080, 60, true, 5, hdmiphy_conf74_25, &hdmi_conf_1080i60 }, - { 1920, 1080, 30, false, 34, hdmiphy_conf74_176, &hdmi_conf_1080p30 }, - { 1920, 1080, 50, false, 31, hdmiphy_conf148_5, &hdmi_conf_1080p50 }, - { 1920, 1080, 60, false, 16, hdmiphy_conf148_5, &hdmi_conf_1080p60 }, +/* list of resolutions which be successfully rendered. */ +static const struct hdmi_modes hdmi_v14_modes[] = { + { 640, 480 }, + { 720, 480 }, + { 720, 576 }, + { 1280, 720 }, + { 1680, 1050 }, + { 1920, 1080 }, }; struct hdmi_infoframe { @@ -1277,31 +854,6 @@ static int hdmi_v13_conf_index(struct drm_display_mode *mode) return -EINVAL; } -static int hdmi_v14_conf_index(struct drm_display_mode *mode) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(hdmi_confs); ++i) - if (hdmi_confs[i].width == mode->hdisplay && - hdmi_confs[i].height == mode->vdisplay && - hdmi_confs[i].vrefresh == mode->vrefresh && - hdmi_confs[i].interlace == - ((mode->flags & DRM_MODE_FLAG_INTERLACE) ? - true : false)) - return i; - - return -EINVAL; -} - -static int hdmi_conf_index(struct hdmi_context *hdata, - struct drm_display_mode *mode) -{ - if (hdata->type == HDMI_TYPE13) - return hdmi_v13_conf_index(mode); - - return hdmi_v14_conf_index(mode); -} - static u8 hdmi_chksum(struct hdmi_context *hdata, u32 start, u8 len, u32 hdr_sum) { @@ -1359,7 +911,7 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata, if (hdata->type == HDMI_TYPE13) vic = hdmi_v13_confs[hdata->cur_conf].cea_video_id; else - vic = hdmi_confs[hdata->cur_conf].cea_video_id; + vic = hdata->mode_conf.cea_video_id; hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), vic); @@ -1441,27 +993,46 @@ static int hdmi_v13_check_timing(struct fb_videomode *check_timing) return -EINVAL; } -static int hdmi_v14_check_timing(struct fb_videomode *check_timing) +static int hdmi_v14_find_phy_conf(int pixel_clock) { int i; - DRM_DEBUG_KMS("valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n", + for (i = 0; i < ARRAY_SIZE(hdmiphy_v14_configs); i++) { + if (hdmiphy_v14_configs[i].pixel_clock == pixel_clock) + return i; + } + + DRM_DEBUG_KMS("Could not find phy config for %d\n", pixel_clock); + return -EINVAL; +} + +static int hdmi_v14_find_mode(u32 width, u32 height) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(hdmi_v14_modes); i++) { + if (hdmi_v14_modes[i].width == width && + hdmi_v14_modes[i].height == height) + return i; + } + + DRM_DEBUG_KMS("Could not find hdmi mode (%dx%d)\n", width, height); + return -EINVAL; +} + +static int hdmi_v14_check_timing(struct fb_videomode *check_timing) +{ + int ret; + + DRM_DEBUG_KMS("valid mode: xres=%d, yres=%d, refresh=%d, intl=%d\n", check_timing->xres, check_timing->yres, check_timing->refresh, (check_timing->vmode & FB_VMODE_INTERLACED) ? true : false); - for (i = 0; i < ARRAY_SIZE(hdmi_confs); i++) - if (hdmi_confs[i].width == check_timing->xres && - hdmi_confs[i].height == check_timing->yres && - hdmi_confs[i].vrefresh == check_timing->refresh && - hdmi_confs[i].interlace == - ((check_timing->vmode & FB_VMODE_INTERLACED) ? - true : false)) - return 0; - - /* TODO */ + ret = hdmi_v14_mode_found(check_timing->pixclock, + check_timing->xres, check_timing->yres); - return -EINVAL; + return ret; } static int hdmi_check_timing(void *ctx, void *timing) @@ -1802,9 +1373,8 @@ static void hdmi_v13_timing_apply(struct hdmi_context *hdata) static void hdmi_v14_timing_apply(struct hdmi_context *hdata) { - const struct hdmi_preset_conf *conf = hdmi_confs[hdata->cur_conf].conf; - const struct hdmi_core_regs *core = &conf->core; - const struct hdmi_tg_regs *tg = &conf->tg; + struct hdmi_core_regs *core = &hdata->mode_conf.core; + struct hdmi_tg_regs *tg = &hdata->mode_conf.tg; int tries; /* setting core registers */ @@ -1907,39 +1477,39 @@ static void hdmi_v14_timing_apply(struct hdmi_context *hdata) hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_1, core->vact_space_6[1]); /* Timing generator registers */ - hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l); - hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h); - hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l); - hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h); - hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l); - hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h); - hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l); - hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h); - hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l); - hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_L, tg->vact_st3_l); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_H, tg->vact_st3_h); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_L, tg->vact_st4_l); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_H, tg->vact_st4_h); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h); - hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l); - hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h); - hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l); - hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h); - hdmi_reg_writeb(hdata, HDMI_TG_3D, tg->tg_3d); + hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz[0]); + hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz[1]); + hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st[0]); + hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st[1]); + hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz[0]); + hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz[1]); + hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz[0]); + hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz[1]); + hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync[0]); + hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync[1]); + hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2[0]); + hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2[1]); + hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st[0]); + hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st[1]); + hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz[0]); + hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz[1]); + hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg[0]); + hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg[1]); + hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2[0]); + hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2[1]); + hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_L, tg->vact_st3[0]); + hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_H, tg->vact_st3[1]); + hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_L, tg->vact_st4[0]); + hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_H, tg->vact_st4[1]); + hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi[0]); + hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi[1]); + hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi[0]); + hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi[1]); + hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi[0]); + hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi[1]); + hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi[0]); + hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi[1]); + hdmi_reg_writeb(hdata, HDMI_TG_3D, tg->tg_3d[0]); /* waiting for HDMIPHY's PLL to get to steady state */ for (tries = 100; tries; --tries) { @@ -2036,10 +1606,17 @@ static void hdmiphy_conf_apply(struct hdmi_context *hdata) } /* pixel clock */ - if (hdata->type == HDMI_TYPE13) + if (hdata->type == HDMI_TYPE13) { hdmiphy_data = hdmi_v13_confs[hdata->cur_conf].hdmiphy_data; - else - hdmiphy_data = hdmi_confs[hdata->cur_conf].hdmiphy_data; + } else { + i = hdmi_v14_find_phy_conf(hdata->mode_conf.pixel_clock); + if (i < 0) { + DRM_ERROR("failed to find hdmiphy conf\n"); + return; + } + + hdmiphy_data = hdmiphy_v14_configs[i].conf; + } memcpy(buffer, hdmiphy_data, 32); ret = i2c_master_send(hdata->hdmiphy_port, buffer, 32); @@ -2107,7 +1684,9 @@ static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector, if (hdata->type == HDMI_TYPE13) index = hdmi_v13_conf_index(adjusted_mode); else - index = hdmi_v14_conf_index(adjusted_mode); + index = hdmi_v14_mode_found(adjusted_mode->clock * 1000, + adjusted_mode->hdisplay, + adjusted_mode->vdisplay); /* just return if user desired mode exists. */ if (index >= 0) @@ -2121,7 +1700,9 @@ static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector, if (hdata->type == HDMI_TYPE13) index = hdmi_v13_conf_index(m); else - index = hdmi_v14_conf_index(m); + index = hdmi_v14_mode_found(adjusted_mode->clock * 1000, + adjusted_mode->hdisplay, + adjusted_mode->vdisplay); if (index >= 0) { struct drm_mode_object base; @@ -2130,6 +1711,9 @@ static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector, DRM_INFO("desired mode doesn't exist so\n"); DRM_INFO("use the most suitable mode among modes.\n"); + DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n", + m->hdisplay, m->vdisplay, m->vrefresh); + /* preserve display mode header while copying. */ head = adjusted_mode->head; base = adjusted_mode->base; @@ -2141,6 +1725,122 @@ static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector, } } +static void hdmi_set_reg(u8 *reg_pair, int num_bytes, u32 value) +{ + int i; + BUG_ON(num_bytes > 4); + for (i = 0; i < num_bytes; i++) + reg_pair[i] = (value >> (8 * i)) & 0xff; +} + +static void hdmi_v14_mode_set(struct hdmi_context *hdata, + struct drm_display_mode *m) +{ + struct hdmi_core_regs *core = &hdata->mode_conf.core; + struct hdmi_tg_regs *tg = &hdata->mode_conf.tg; + + hdata->mode_conf.cea_video_id = drm_match_cea_mode(m); + + hdata->mode_conf.pixel_clock = m->clock * 1000; + hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay); + hdmi_set_reg(core->v_line, 2, m->vtotal); + hdmi_set_reg(core->h_line, 2, m->htotal); + hdmi_set_reg(core->hsync_pol, 1, + (m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0); + hdmi_set_reg(core->vsync_pol, 1, + (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0); + hdmi_set_reg(core->int_pro_mode, 1, + (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0); + + /* + * Quirk requirement for exynos 5 HDMI IP design, + * 2 pixels less than the actual calculation for hsync_start + * and end. + */ + + /* Following values & calculations differ for different type of modes */ + if (m->flags & DRM_MODE_FLAG_INTERLACE) { + /* Interlaced Mode */ + hdmi_set_reg(core->v_sync_line_bef_2, 2, + (m->vsync_end - m->vdisplay) / 2); + hdmi_set_reg(core->v_sync_line_bef_1, 2, + (m->vsync_start - m->vdisplay) / 2); + hdmi_set_reg(core->v2_blank, 2, m->vtotal / 2); + hdmi_set_reg(core->v1_blank, 2, (m->vtotal - m->vdisplay) / 2); + hdmi_set_reg(core->v_blank_f0, 2, (m->vtotal + + ((m->vsync_end - m->vsync_start) * 4) + 5) / 2); + hdmi_set_reg(core->v_blank_f1, 2, m->vtotal); + hdmi_set_reg(core->v_sync_line_aft_2, 2, (m->vtotal / 2) + 7); + hdmi_set_reg(core->v_sync_line_aft_1, 2, (m->vtotal / 2) + 2); + hdmi_set_reg(core->v_sync_line_aft_pxl_2, 2, + (m->htotal / 2) + (m->hsync_start - m->hdisplay)); + hdmi_set_reg(core->v_sync_line_aft_pxl_1, 2, + (m->htotal / 2) + (m->hsync_start - m->hdisplay)); + hdmi_set_reg(tg->vact_st, 2, (m->vtotal - m->vdisplay) / 2); + hdmi_set_reg(tg->vact_sz, 2, m->vdisplay / 2); + hdmi_set_reg(tg->vact_st2, 2, 0x249);/* Reset value + 1*/ + hdmi_set_reg(tg->vact_st3, 2, 0x0); + hdmi_set_reg(tg->vact_st4, 2, 0x0); + } else { + /* Progressive Mode */ + hdmi_set_reg(core->v_sync_line_bef_2, 2, + m->vsync_end - m->vdisplay); + hdmi_set_reg(core->v_sync_line_bef_1, 2, + m->vsync_start - m->vdisplay); + hdmi_set_reg(core->v2_blank, 2, m->vtotal); + hdmi_set_reg(core->v1_blank, 2, m->vtotal - m->vdisplay); + hdmi_set_reg(core->v_blank_f0, 2, 0xffff); + hdmi_set_reg(core->v_blank_f1, 2, 0xffff); + hdmi_set_reg(core->v_sync_line_aft_2, 2, 0xffff); + hdmi_set_reg(core->v_sync_line_aft_1, 2, 0xffff); + hdmi_set_reg(core->v_sync_line_aft_pxl_2, 2, 0xffff); + hdmi_set_reg(core->v_sync_line_aft_pxl_1, 2, 0xffff); + hdmi_set_reg(tg->vact_st, 2, m->vtotal - m->vdisplay); + hdmi_set_reg(tg->vact_sz, 2, m->vdisplay); + hdmi_set_reg(tg->vact_st2, 2, 0x248); /* Reset value */ + hdmi_set_reg(tg->vact_st3, 2, 0x47b); /* Reset value */ + hdmi_set_reg(tg->vact_st4, 2, 0x6ae); /* Reset value */ + } + + /* Following values & calculations are same irrespective of mode type */ + hdmi_set_reg(core->h_sync_start, 2, m->hsync_start - m->hdisplay - 2); + hdmi_set_reg(core->h_sync_end, 2, m->hsync_end - m->hdisplay - 2); + hdmi_set_reg(core->vact_space_1, 2, 0xffff); + hdmi_set_reg(core->vact_space_2, 2, 0xffff); + hdmi_set_reg(core->vact_space_3, 2, 0xffff); + hdmi_set_reg(core->vact_space_4, 2, 0xffff); + hdmi_set_reg(core->vact_space_5, 2, 0xffff); + hdmi_set_reg(core->vact_space_6, 2, 0xffff); + hdmi_set_reg(core->v_blank_f2, 2, 0xffff); + hdmi_set_reg(core->v_blank_f3, 2, 0xffff); + hdmi_set_reg(core->v_blank_f4, 2, 0xffff); + hdmi_set_reg(core->v_blank_f5, 2, 0xffff); + hdmi_set_reg(core->v_sync_line_aft_3, 2, 0xffff); + hdmi_set_reg(core->v_sync_line_aft_4, 2, 0xffff); + hdmi_set_reg(core->v_sync_line_aft_5, 2, 0xffff); + hdmi_set_reg(core->v_sync_line_aft_6, 2, 0xffff); + hdmi_set_reg(core->v_sync_line_aft_pxl_3, 2, 0xffff); + hdmi_set_reg(core->v_sync_line_aft_pxl_4, 2, 0xffff); + hdmi_set_reg(core->v_sync_line_aft_pxl_5, 2, 0xffff); + hdmi_set_reg(core->v_sync_line_aft_pxl_6, 2, 0xffff); + + /* Timing generator registers */ + hdmi_set_reg(tg->cmd, 1, 0x0); + hdmi_set_reg(tg->h_fsz, 2, m->htotal); + hdmi_set_reg(tg->hact_st, 2, m->htotal - m->hdisplay); + hdmi_set_reg(tg->hact_sz, 2, m->hdisplay); + hdmi_set_reg(tg->v_fsz, 2, m->vtotal); + hdmi_set_reg(tg->vsync, 2, 0x1); + hdmi_set_reg(tg->vsync2, 2, 0x233); /* Reset value */ + hdmi_set_reg(tg->field_chg, 2, 0x233); /* Reset value */ + hdmi_set_reg(tg->vsync_top_hdmi, 2, 0x1); /* Reset value */ + hdmi_set_reg(tg->vsync_bot_hdmi, 2, 0x233); /* Reset value */ + hdmi_set_reg(tg->field_top_hdmi, 2, 0x1); /* Reset value */ + hdmi_set_reg(tg->field_bot_hdmi, 2, 0x233); /* Reset value */ + hdmi_set_reg(tg->tg_3d, 1, 0x0); + +} + static void hdmi_mode_set(void *ctx, void *mode) { struct hdmi_context *hdata = ctx; @@ -2148,11 +1848,15 @@ static void hdmi_mode_set(void *ctx, void *mode) DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - conf_idx = hdmi_conf_index(hdata, mode); - if (conf_idx >= 0) - hdata->cur_conf = conf_idx; - else - DRM_DEBUG_KMS("not supported mode\n"); + if (hdata->type == HDMI_TYPE13) { + conf_idx = hdmi_v13_conf_index(mode); + if (conf_idx >= 0) + hdata->cur_conf = conf_idx; + else + DRM_DEBUG_KMS("not supported mode\n"); + } else { + hdmi_v14_mode_set(hdata, mode); + } } static void hdmi_get_max_resol(void *ctx, unsigned int *width,