From patchwork Tue Mar 13 10:07:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Neil Armstrong X-Patchwork-Id: 10278093 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id CB49C602C2 for ; Tue, 13 Mar 2018 10:08:17 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B9A1828834 for ; Tue, 13 Mar 2018 10:08:17 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AE5EB28849; Tue, 13 Mar 2018 10:08:17 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id A442E28834 for ; Tue, 13 Mar 2018 10:08:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: References:List-Owner; bh=jcLM0VR105Jy8bOWPz8eyDtwFwkRL1xFEEKxpw0Jeoc=; b=JdZ ctlAfQ9g0ft6/j5/oFOLBcMqixyY6rpInb8Frw1ABLCuyKa5NWMQac+HxjT7UYHnZ2aoAz+O6mABt Dudp/xMEeMk/WkcBf3xQlpfv20McstcwkDCJJ5rhD0yN6KraKZsid8hFai2/9bvGKDlY+mokMHdi2 3wWYeXyEgCFO+sLgd4pYsq7z86DXWVQ5YUILIRh/UIZ5n011KZHJAkIX5cMONNkaTE9cIaGoIfmxD amocCjcqi0+/s4d/yjLsZN4l14dwkRBSNiCGEe7Xo5Q899S2MnFK9z8LM3tPDVGWnZi0K8oViDkwt f+pz3sYw8TvnouAfIMbKBjurzvumfXA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1evgqp-0003Ok-VL; Tue, 13 Mar 2018 10:08:11 +0000 Received: from mail-wr0-x242.google.com ([2a00:1450:400c:c0c::242]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1evgqj-0003MQ-Dw for linux-arm-kernel@lists.infradead.org; Tue, 13 Mar 2018 10:08:09 +0000 Received: by mail-wr0-x242.google.com with SMTP id h2so13554987wre.12 for ; Tue, 13 Mar 2018 03:07:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id; bh=aqwzBwk4npoJrbAT1OppAS8QzhXdoOsrnQESPNg1hEw=; b=fBDeySyGdOGaU4LyI2R9CPF7C2KktjvfDreCob4bGiTag42U1Qa+Fi89yryi8bCe8d Lq0jZT28yeMZpedbUegjKF1jFUOdHAAc/EItNMT1ArkVFgpigDjGEsqynprW01rxbE5R Zwd3iIpKx3NZw172HkabdbH7AZ6S3buQY1SFjtabTiDw6hBb4m/92ZJBlK18Didgqpx5 CpzZMMtY/cfQZ3SioVQZ9uhND1dvBfCS366O7sdrbvKGjyIo6wnPeJ4Ud0UvT0GYiikb uk4we0cNZLLai+AgNJLUE/GMKrf1ratCTHeDBkLsnuUO77KuwAF4EE3/nZYD5/zcZkt7 MBog== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=aqwzBwk4npoJrbAT1OppAS8QzhXdoOsrnQESPNg1hEw=; b=lFtnpeCykxRKO+1/zT1qBtfuXKB1qAbBLG6Ncpa631OyOMriOxIGn/adb1MGrvLORI EqyXbOrpFs12u1IROx9pb7A4dBAOk3AQyw5YKfB7WnFRheDqXGPRqHApbg817Th6shtu q1CX0aJqZphrh1xUAcWQ/gId7WgN78MeGUAZ+/xDLlvQw5aRfrFvKUESnQDzt8pcnP3g 5F8PNgfOt5Y3+xE4BetFXV/iLejkPy3sLZvPlNEdWvsqA0uckywLCGEb42vP/diw6cgh Ik+mjHjrNACRyGkXTLraGACyyRnX7or6Z6wBc17202z1HgVWLh3TxyQTC/CHC7y2IwsU Ny1Q== X-Gm-Message-State: AElRT7FzdIp3WVtKiOW79HI9h+NrC3C1MvsZjzoEr65Z6UExOLcOV/UH 7qZC/ZXX/51t1iAxO4ntmlUw3w== X-Google-Smtp-Source: AG47ELsdlTGxwMHpxaTx6HND59+yZVVAI9vNiJFLWPLmaPWjYkJdL3NxFwWdZzA/S1Nuh2p8MVtehQ== X-Received: by 10.28.237.21 with SMTP id l21mr234146wmh.12.1520935673226; Tue, 13 Mar 2018 03:07:53 -0700 (PDT) Received: from bender.baylibre.local ([90.63.244.31]) by smtp.gmail.com with ESMTPSA id s78sm16453497wrc.93.2018.03.13.03.07.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 13 Mar 2018 03:07:52 -0700 (PDT) From: Neil Armstrong To: airlied@linux.ie Subject: [PATCH] drm/meson: Add support for DMT modes on HDMI Date: Tue, 13 Mar 2018 11:07:50 +0100 Message-Id: <1520935670-14187-1-git-send-email-narmstrong@baylibre.com> X-Mailer: git-send-email 2.7.4 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180313_030805_593850_FDE535A0 X-CRM114-Status: GOOD ( 18.33 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-amlogic@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, dri-devel@lists.freedesktop.org, Neil Armstrong MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds support for DMT display modes over HDMI. The modes timings configurations are from the Amlogic Vendor linux tree and tested over multiples monitors. Previously only a selected number of CEA modes were supported. Only these following modes are supported with these changes: - 640x480@60Hz - 800x600@60Hz - 1024x768@60Hz - 1152x864@75Hz - 1280x1024@60Hz - 1600x1200@60Hz - 1920x1080@60Hz The associated code to handle the clock rates is also added. Signed-off-by: Neil Armstrong Acked-by: Jerome Brunet --- Changes since v1: - Fixed a regression on HDMI vic validation drivers/gpu/drm/meson/meson_dw_hdmi.c | 22 +-- drivers/gpu/drm/meson/meson_vclk.c | 219 ++++++++++++++++++++- drivers/gpu/drm/meson/meson_venc.c | 347 +++++++++++++++++++++++++++++++++- drivers/gpu/drm/meson/meson_venc.h | 1 + 4 files changed, 570 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c index 17de3af..9d70ed6 100644 --- a/drivers/gpu/drm/meson/meson_dw_hdmi.c +++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c @@ -537,7 +537,6 @@ static irqreturn_t dw_hdmi_top_thread_irq(int irq, void *dev_id) return IRQ_HANDLED; } -/* TOFIX Enable support for non-vic modes */ static enum drm_mode_status dw_hdmi_mode_valid(struct drm_connector *connector, const struct drm_display_mode *mode) @@ -554,12 +553,12 @@ dw_hdmi_mode_valid(struct drm_connector *connector, mode->vdisplay, mode->vsync_start, mode->vsync_end, mode->vtotal, mode->type, mode->flags); - /* For now, only accept VIC modes */ - if (!vic) - return MODE_BAD; - - /* For now, filter by supported VIC modes */ - if (!meson_venc_hdmi_supported_vic(vic)) + /* Check against non-VIC supported modes */ + if (!vic) { + if (!meson_venc_hdmi_supported_mode(mode)) + return MODE_BAD; + /* Check against supported VIC modes */ + } else if (!meson_venc_hdmi_supported_vic(vic)) return MODE_BAD; vclk_freq = mode->clock; @@ -585,9 +584,14 @@ dw_hdmi_mode_valid(struct drm_connector *connector, /* Finally filter by configurable vclk frequencies */ switch (vclk_freq) { + case 25175: + case 40000: case 54000: + case 65000: case 74250: + case 108000: case 148500: + case 162000: case 297000: case 594000: return MODE_OK; @@ -652,10 +656,6 @@ static void meson_venc_hdmi_encoder_mode_set(struct drm_encoder *encoder, DRM_DEBUG_DRIVER("%d:\"%s\" vic %d\n", mode->base.id, mode->name, vic); - /* Should have been filtered */ - if (!vic) - return; - /* VENC + VENC-DVI Mode setup */ meson_venc_hdmi_mode_set(priv, vic, mode); diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c index 4767704..f051122 100644 --- a/drivers/gpu/drm/meson/meson_vclk.c +++ b/drivers/gpu/drm/meson/meson_vclk.c @@ -328,14 +328,24 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv) #define MESON_VCLK_HDMI_DDR_54000 2 /* 2970 /4 /1 /1 /5 /1 => /1 /2 */ #define MESON_VCLK_HDMI_DDR_148500 3 +/* 4028 /4 /4 /1 /5 /2 => /1 /1 */ +#define MESON_VCLK_HDMI_25175 4 +/* 3200 /4 /2 /1 /5 /2 => /1 /1 */ +#define MESON_VCLK_HDMI_40000 5 +/* 5200 /4 /2 /1 /5 /2 => /1 /1 */ +#define MESON_VCLK_HDMI_65000 6 /* 2970 /2 /2 /2 /5 /1 => /1 /1 */ -#define MESON_VCLK_HDMI_74250 4 +#define MESON_VCLK_HDMI_74250 7 +/* 4320 /4 /1 /1 /5 /2 => /1 /1 */ +#define MESON_VCLK_HDMI_108000 8 /* 2970 /1 /2 /2 /5 /1 => /1 /1 */ -#define MESON_VCLK_HDMI_148500 5 +#define MESON_VCLK_HDMI_148500 9 +/* 3240 /2 /1 /1 /5 /2 => /1 /1 */ +#define MESON_VCLK_HDMI_162000 10 /* 2970 /1 /1 /1 /5 /2 => /1 /1 */ -#define MESON_VCLK_HDMI_297000 6 +#define MESON_VCLK_HDMI_297000 11 /* 5940 /1 /1 /2 /5 /1 => /1 /1 */ -#define MESON_VCLK_HDMI_594000 7 +#define MESON_VCLK_HDMI_594000 12 struct meson_vclk_params { unsigned int pll_base_freq; @@ -401,6 +411,46 @@ struct meson_vclk_params { .vid_pll_div = VID_PLL_DIV_5, .vclk_div = 1, }, + [MESON_VCLK_HDMI_25175] = { + .pll_base_freq = 4028000, + .pll_od1 = 4, + .pll_od2 = 4, + .pll_od3 = 1, + .vid_pll_div = VID_PLL_DIV_5, + .vclk_div = 2, + }, + [MESON_VCLK_HDMI_40000] = { + .pll_base_freq = 3200000, + .pll_od1 = 4, + .pll_od2 = 2, + .pll_od3 = 1, + .vid_pll_div = VID_PLL_DIV_5, + .vclk_div = 2, + }, + [MESON_VCLK_HDMI_65000] = { + .pll_base_freq = 5200000, + .pll_od1 = 4, + .pll_od2 = 2, + .pll_od3 = 1, + .vid_pll_div = VID_PLL_DIV_5, + .vclk_div = 2, + }, + [MESON_VCLK_HDMI_108000] = { + .pll_base_freq = 4320000, + .pll_od1 = 4, + .pll_od2 = 1, + .pll_od3 = 1, + .vid_pll_div = VID_PLL_DIV_5, + .vclk_div = 2, + }, + [MESON_VCLK_HDMI_162000] = { + .pll_base_freq = 3240000, + .pll_od1 = 2, + .pll_od2 = 1, + .pll_od3 = 1, + .vid_pll_div = VID_PLL_DIV_5, + .vclk_div = 2, + }, }; static inline unsigned int pll_od_to_reg(unsigned int od) @@ -451,6 +501,90 @@ void meson_hdmi_pll_set(struct meson_drm *priv, 0xFFFF, 0x4e00); break; + case 3200000: + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x58000242); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55); + + /* unreset */ + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL, + BIT(28), 0); + + /* Poll for lock bit */ + regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, + val, (val & HDMI_PLL_LOCK), 10, 0); + + /* div_frac */ + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2, + 0xFFFF, 0x4aab); + break; + + case 3240000: + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x58000243); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55); + + /* unreset */ + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL, + BIT(28), 0); + + /* Poll for lock bit */ + regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, + val, (val & HDMI_PLL_LOCK), 10, 0); + + /* div_frac */ + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2, + 0xFFFF, 0x4800); + break; + + case 3865000: + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x58000250); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55); + + /* unreset */ + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL, + BIT(28), 0); + + /* Poll for lock bit */ + regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, + val, (val & HDMI_PLL_LOCK), 10, 0); + + /* div_frac */ + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2, + 0xFFFF, 0x4855); + break; + + case 4028000: + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x58000253); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55); + + /* unreset */ + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL, + BIT(28), 0); + + /* Poll for lock bit */ + regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, + val, (val & HDMI_PLL_LOCK), 10, 0); + + /* div_frac */ + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2, + 0xFFFF, 0x4eab); + break; + case 4320000: regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800025a); regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000); @@ -485,6 +619,23 @@ void meson_hdmi_pll_set(struct meson_drm *priv, regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val, (val & HDMI_PLL_LOCK), 10, 0); break; + + case 5200000: + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800026c); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00000000); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x135c5091); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55); + + /* unreset */ + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL, + BIT(28), 0); + + /* Poll for lock bit */ + regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, + val, (val & HDMI_PLL_LOCK), 10, 0); + break; }; } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") || meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) { @@ -498,6 +649,42 @@ void meson_hdmi_pll_set(struct meson_drm *priv, regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500); break; + case 3200000: + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x40000285); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb155); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500); + break; + + case 3240000: + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x40000287); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb000); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500); + break; + + case 3865000: + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002a1); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb02b); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500); + break; + + case 4028000: + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002a7); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb355); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500); + break; + case 4320000: regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002b4); regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb000); @@ -516,6 +703,15 @@ void meson_hdmi_pll_set(struct meson_drm *priv, regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500); break; + case 5200000: + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x400002d8); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb2ab); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729); + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500); + break; + }; /* Reset PLL */ @@ -590,15 +786,30 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target, else freq = MESON_VCLK_HDMI_DDR_54000; break; + case 25175: + freq = MESON_VCLK_HDMI_25175; + break; + case 40000: + freq = MESON_VCLK_HDMI_40000; + break; + case 65000: + freq = MESON_VCLK_HDMI_65000; + break; case 74250: freq = MESON_VCLK_HDMI_74250; break; + case 108000: + freq = MESON_VCLK_HDMI_108000; + break; case 148500: if (dac_freq != 148500) freq = MESON_VCLK_HDMI_DDR_148500; else freq = MESON_VCLK_HDMI_148500; break; + case 162000: + freq = MESON_VCLK_HDMI_162000; + break; case 297000: freq = MESON_VCLK_HDMI_297000; break; diff --git a/drivers/gpu/drm/meson/meson_venc.c b/drivers/gpu/drm/meson/meson_venc.c index 9509017..6e27013 100644 --- a/drivers/gpu/drm/meson/meson_venc.c +++ b/drivers/gpu/drm/meson/meson_venc.c @@ -697,6 +697,314 @@ union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p60 = { }, }; +union meson_hdmi_venc_mode meson_hdmi_encp_mode_640x480_60 = { + .encp = { + .dvi_settings = 0x21, + .video_mode = 0x4040, + .video_mode_adv = 0x18, + /* video_prog_mode */ + /* video_sync_mode */ + /* video_yc_dly */ + /* video_rgb_ctrl */ + /* video_filt_ctrl */ + /* video_ofld_voav_ofst */ + /* yfp1_htime */ + /* yfp2_htime */ + .max_pxcnt = 0x31f, + /* hspuls_begin */ + /* hspuls_end */ + /* hspuls_switch */ + /* vspuls_begin */ + /* vspuls_end */ + /* vspuls_bline */ + /* vspuls_eline */ + .havon_begin = 0x90, + .havon_end = 0x30f, + .vavon_bline = 0x23, + .vavon_eline = 0x202, + /* eqpuls_begin */ + /* eqpuls_end */ + /* eqpuls_bline */ + /* eqpuls_eline */ + .hso_begin = 0, + .hso_end = 0x60, + .vso_begin = 0x1e, + .vso_end = 0x32, + .vso_bline = 0, + .vso_eline = 2, + .vso_eline_present = true, + /* sy_val */ + /* sy2_val */ + .max_lncnt = 0x20c, + }, +}; + +union meson_hdmi_venc_mode meson_hdmi_encp_mode_800x600_60 = { + .encp = { + .dvi_settings = 0x21, + .video_mode = 0x4040, + .video_mode_adv = 0x18, + /* video_prog_mode */ + /* video_sync_mode */ + /* video_yc_dly */ + /* video_rgb_ctrl */ + /* video_filt_ctrl */ + /* video_ofld_voav_ofst */ + /* yfp1_htime */ + /* yfp2_htime */ + .max_pxcnt = 0x41f, + /* hspuls_begin */ + /* hspuls_end */ + /* hspuls_switch */ + /* vspuls_begin */ + /* vspuls_end */ + /* vspuls_bline */ + /* vspuls_eline */ + .havon_begin = 0xD8, + .havon_end = 0x3f7, + .vavon_bline = 0x1b, + .vavon_eline = 0x272, + /* eqpuls_begin */ + /* eqpuls_end */ + /* eqpuls_bline */ + /* eqpuls_eline */ + .hso_begin = 0, + .hso_end = 0x80, + .vso_begin = 0x1e, + .vso_end = 0x32, + .vso_bline = 0, + .vso_eline = 4, + .vso_eline_present = true, + /* sy_val */ + /* sy2_val */ + .max_lncnt = 0x273, + }, +}; + +union meson_hdmi_venc_mode meson_hdmi_encp_mode_1024x768_60 = { + .encp = { + .dvi_settings = 0x21, + .video_mode = 0x4040, + .video_mode_adv = 0x18, + /* video_prog_mode */ + /* video_sync_mode */ + /* video_yc_dly */ + /* video_rgb_ctrl */ + /* video_filt_ctrl */ + /* video_ofld_voav_ofst */ + /* yfp1_htime */ + /* yfp2_htime */ + .max_pxcnt = 1343, + /* hspuls_begin */ + /* hspuls_end */ + /* hspuls_switch */ + /* vspuls_begin */ + /* vspuls_end */ + /* vspuls_bline */ + /* vspuls_eline */ + .havon_begin = 296, + .havon_end = 1319, + .vavon_bline = 35, + .vavon_eline = 802, + /* eqpuls_begin */ + /* eqpuls_end */ + /* eqpuls_bline */ + /* eqpuls_eline */ + .hso_begin = 0, + .hso_end = 136, + .vso_begin = 30, + .vso_end = 50, + .vso_bline = 0, + .vso_eline = 6, + .vso_eline_present = true, + /* sy_val */ + /* sy2_val */ + .max_lncnt = 805, + }, +}; + +union meson_hdmi_venc_mode meson_hdmi_encp_mode_1152x864_75 = { + .encp = { + .dvi_settings = 0x21, + .video_mode = 0x4040, + .video_mode_adv = 0x18, + /* video_prog_mode */ + /* video_sync_mode */ + /* video_yc_dly */ + /* video_rgb_ctrl */ + /* video_filt_ctrl */ + /* video_ofld_voav_ofst */ + /* yfp1_htime */ + /* yfp2_htime */ + .max_pxcnt = 0x63f, + /* hspuls_begin */ + /* hspuls_end */ + /* hspuls_switch */ + /* vspuls_begin */ + /* vspuls_end */ + /* vspuls_bline */ + /* vspuls_eline */ + .havon_begin = 0x180, + .havon_end = 0x5ff, + .vavon_bline = 0x23, + .vavon_eline = 0x382, + /* eqpuls_begin */ + /* eqpuls_end */ + /* eqpuls_bline */ + /* eqpuls_eline */ + .hso_begin = 0, + .hso_end = 0x80, + .vso_begin = 0x1e, + .vso_end = 0x32, + .vso_bline = 0, + .vso_eline = 3, + .vso_eline_present = true, + /* sy_val */ + /* sy2_val */ + .max_lncnt = 0x383, + }, +}; + +union meson_hdmi_venc_mode meson_hdmi_encp_mode_1280x1024_60 = { + .encp = { + .dvi_settings = 0x21, + .video_mode = 0x4040, + .video_mode_adv = 0x18, + /* video_prog_mode */ + /* video_sync_mode */ + /* video_yc_dly */ + /* video_rgb_ctrl */ + /* video_filt_ctrl */ + /* video_ofld_voav_ofst */ + /* yfp1_htime */ + /* yfp2_htime */ + .max_pxcnt = 0x697, + /* hspuls_begin */ + /* hspuls_end */ + /* hspuls_switch */ + /* vspuls_begin */ + /* vspuls_end */ + /* vspuls_bline */ + /* vspuls_eline */ + .havon_begin = 0x168, + .havon_end = 0x667, + .vavon_bline = 0x29, + .vavon_eline = 0x428, + /* eqpuls_begin */ + /* eqpuls_end */ + /* eqpuls_bline */ + /* eqpuls_eline */ + .hso_begin = 0, + .hso_end = 0x70, + .vso_begin = 0x1e, + .vso_end = 0x32, + .vso_bline = 0, + .vso_eline = 3, + .vso_eline_present = true, + /* sy_val */ + /* sy2_val */ + .max_lncnt = 0x429, + }, +}; + +union meson_hdmi_venc_mode meson_hdmi_encp_mode_1600x1200_60 = { + .encp = { + .dvi_settings = 0x21, + .video_mode = 0x4040, + .video_mode_adv = 0x18, + /* video_prog_mode */ + /* video_sync_mode */ + /* video_yc_dly */ + /* video_rgb_ctrl */ + /* video_filt_ctrl */ + /* video_ofld_voav_ofst */ + /* yfp1_htime */ + /* yfp2_htime */ + .max_pxcnt = 0x86f, + /* hspuls_begin */ + /* hspuls_end */ + /* hspuls_switch */ + /* vspuls_begin */ + /* vspuls_end */ + /* vspuls_bline */ + /* vspuls_eline */ + .havon_begin = 0x1f0, + .havon_end = 0x82f, + .vavon_bline = 0x31, + .vavon_eline = 0x4e0, + /* eqpuls_begin */ + /* eqpuls_end */ + /* eqpuls_bline */ + /* eqpuls_eline */ + .hso_begin = 0, + .hso_end = 0xc0, + .vso_begin = 0x1e, + .vso_end = 0x32, + .vso_bline = 0, + .vso_eline = 3, + .vso_eline_present = true, + /* sy_val */ + /* sy2_val */ + .max_lncnt = 0x4e1, + }, +}; + +struct meson_hdmi_venc_dmt_mode { + struct drm_display_mode drm_mode; + union meson_hdmi_venc_mode *mode; +} meson_hdmi_venc_dmt_modes[] = { + /* 640x480@60Hz */ + { + { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656, + 752, 800, 0, 480, 490, 492, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, + &meson_hdmi_encp_mode_640x480_60, + }, + /* 800x600@60Hz */ + { + { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840, + 968, 1056, 0, 600, 601, 605, 628, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + &meson_hdmi_encp_mode_800x600_60, + }, + /* 1024x768@60Hz */ + { + { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, + 1048, 1184, 1344, 0, 768, 771, 777, 806, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, + &meson_hdmi_encp_mode_1024x768_60, + }, + /* 1152x864@75Hz */ + { + { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, + 1216, 1344, 1600, 0, 864, 865, 868, 900, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + &meson_hdmi_encp_mode_1152x864_75, + }, + /* 1280x1024@60Hz */ + { + { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280, + 1328, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + &meson_hdmi_encp_mode_1280x1024_60, + }, + /* 1600x1200@60Hz */ + { + { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600, + 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + &meson_hdmi_encp_mode_1600x1200_60, + }, + /* 1920x1080@60Hz */ + { + { DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, + 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, + &meson_hdmi_encp_mode_1080p60 + }, + { }, /* sentinel */ +}; + struct meson_hdmi_venc_vic_mode { unsigned int vic; union meson_hdmi_venc_mode *mode; @@ -736,6 +1044,20 @@ static unsigned long modulo(unsigned long a, unsigned long b) return a; } +bool meson_venc_hdmi_supported_mode(const struct drm_display_mode *mode) +{ + struct meson_hdmi_venc_dmt_mode *vmode = meson_hdmi_venc_dmt_modes; + + while (vmode->mode) { + if (drm_mode_equal(&vmode->drm_mode, mode)) + return true; + vmode++; + } + + return false; +} +EXPORT_SYMBOL_GPL(meson_venc_hdmi_supported_mode); + bool meson_venc_hdmi_supported_vic(int vic) { struct meson_hdmi_venc_vic_mode *vmode = meson_hdmi_venc_vic_modes; @@ -750,6 +1072,20 @@ bool meson_venc_hdmi_supported_vic(int vic) } EXPORT_SYMBOL_GPL(meson_venc_hdmi_supported_vic); +static union meson_hdmi_venc_mode +*meson_venc_hdmi_get_dmt_vmode(const struct drm_display_mode *mode) +{ + struct meson_hdmi_venc_dmt_mode *vmode = meson_hdmi_venc_dmt_modes; + + while (vmode->mode) { + if (drm_mode_equal(&vmode->drm_mode, mode)) + return vmode->mode; + vmode++; + } + + return NULL; +} + static union meson_hdmi_venc_mode *meson_venc_hdmi_get_vic_vmode(int vic) { struct meson_hdmi_venc_vic_mode *vmode = meson_hdmi_venc_vic_modes; @@ -811,10 +1147,13 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic, unsigned int sof_lines; unsigned int vsync_lines; - vmode = meson_venc_hdmi_get_vic_vmode(vic); + if (meson_venc_hdmi_supported_vic(vic)) + vmode = meson_venc_hdmi_get_vic_vmode(vic); + else + vmode = meson_venc_hdmi_get_dmt_vmode(mode); if (!vmode) { - dev_err(priv->dev, "%s: Fatal Error, unsupported vic %d\n", - __func__, vic); + dev_err(priv->dev, "%s: Fatal Error, unsupported mode " + DRM_MODE_FMT "\n", __func__, DRM_MODE_ARG(mode)); return; } @@ -864,7 +1203,7 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic, hsync_pixels_venc *= 2; /* Disable VDACs */ - writel_bits_relaxed(0x1f, 0x1f, + writel_bits_relaxed(0xff, 0xff, priv->io_base + _REG(VENC_VDAC_SETTING)); writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN)); diff --git a/drivers/gpu/drm/meson/meson_venc.h b/drivers/gpu/drm/meson/meson_venc.h index a1b96e8..7c18a36 100644 --- a/drivers/gpu/drm/meson/meson_venc.h +++ b/drivers/gpu/drm/meson/meson_venc.h @@ -58,6 +58,7 @@ struct meson_cvbs_enci_mode { }; /* HDMI Clock parameters */ +bool meson_venc_hdmi_supported_mode(const struct drm_display_mode *mode); bool meson_venc_hdmi_supported_vic(int vic); bool meson_venc_hdmi_venc_repeat(int vic);