From patchwork Tue Nov 6 10:54:35 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Neil Armstrong X-Patchwork-Id: 10670069 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A486014BD for ; Tue, 6 Nov 2018 10:55:07 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 91C7628B40 for ; Tue, 6 Nov 2018 10:55:07 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 847262A339; Tue, 6 Nov 2018 10:55:07 +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=-3.6 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_LOW autolearn=ham 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 AE9EB28B40 for ; Tue, 6 Nov 2018 10:55:06 +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=qGuT6EokyF2ycON3PUQUEYeE1pfdVaWWbsd/4oi0ghE=; b=Aoy 2iIcCRsxshCqwX+xrflcou7mfN7ESuCuWruVIwRABuUV6vfSpZGkm8agT63C4f4KrWsV9l9lcUXgc a7BIjekoE5LxTd0+bGqCYR850kgh1bzAOa0JpMYt+an1/bkviXUB+fwG2iiXLRLhB/nTAfgE8uX3G 3A9Fc5SdY8Rzy3BJMMB524dgw4oC3+dQ6F80BHUUybIZZCuVGtCab/9720dXzkP2mDQlMz5/Z7QLR wygCsLth6sm5jpbo4jshxC7A9VXHnhZUoibw17CoyuqlD3N0PYzYAN9x0/NGqbo7u2BzUqX2j022T /IRJe7Rzmadk1eYdpZnKD5eNr9cSQIw==; 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 1gJz0d-0006Mz-1O; Tue, 06 Nov 2018 10:54:59 +0000 Received: from mail-wr1-x441.google.com ([2a00:1450:4864:20::441]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1gJz0W-00068k-AK for linux-arm-kernel@lists.infradead.org; Tue, 06 Nov 2018 10:54:54 +0000 Received: by mail-wr1-x441.google.com with SMTP id j26-v6so12953725wre.1 for ; Tue, 06 Nov 2018 02:54:41 -0800 (PST) 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=4GUprm9HmbWPoDJRU2zuoLJ8O3xIDWpcOXQKbm06s7Y=; b=klECkeKvIejdZFcg5RmGjvdaKXtw4HEJHWFX0AxJ0OnxqIRe6QH+gd/NLgbjQEXYDo JFsZ7LdHwhAl5Sgs5DIn2vSygabO/xWD7MMtUAY1vCmmmhc2xcAkGqAyImLCtPL4SFvh /5oqOVUF6mEEe2JA3jgcehtDEHkfomWizo0aDEYPhvcVi56rGObxfSmvtAfz8weR5wLQ NSZJjngveq0BbD1Oeod8rFHHmXQdRO/LtQrk/fUPK3nM5uioia/uojfBITXlmmMmblG/ bKmhbdPnxi84mNtyYDkpECrwaEFO/DTQzKkeYXDBRJ7h9VT21Ptj06hCsQxZ0iJriRl3 IB7w== 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=4GUprm9HmbWPoDJRU2zuoLJ8O3xIDWpcOXQKbm06s7Y=; b=pElDf8gvyQzQlORdELaZ1E9Vz7+3Wyug1gc3NtXYFQAX5vUGY/JvIG/BZdCKY75z3/ 6v/9eQBdl/pSPa9IEsiKja4cTQgpU8lDISPpWa+Kop5Qn8hJSUaYc0Qm2RoDKotTgDcX FSlxLZn/9P2ccwpIGWKkf3SYkvqdh2coGVUen3FUR/OcId9kBccPLS89HvESnPlOfSVl v1wWRynHOS+f7O7ZFNobTc7/wWD+I0ejCKpzozq0MyruK3uBFI3T10SirBZmiMZFjD51 h4hbtTGnoKRMGCZ3LbuHd1pBVvOP+K+jFbBXwi+wJy+q9mfGXNHDyivsZVDOPq+RMwgs s60g== X-Gm-Message-State: AGRZ1gKWh6XNjq7Ck+ZbSDxs1zipKChVGjKYmPnVN6RRtVRURUYhq8Jc kvRHiKzcoY+Unk2sSbg7RysguQ== X-Google-Smtp-Source: AJdET5c9o2Q8/t3T3B9Bn7Ln57+p3tKSHUUv8GAxwKwnEq0xw6NuhQC1qzCJ0ILHRYxgWGm1O9uH5w== X-Received: by 2002:a5d:4e4e:: with SMTP id r14-v6mr23334565wrt.326.1541501680374; Tue, 06 Nov 2018 02:54:40 -0800 (PST) Received: from bender.baylibre.local ([90.63.244.31]) by smtp.gmail.com with ESMTPSA id b204-v6sm641147wmh.0.2018.11.06.02.54.39 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 06 Nov 2018 02:54:39 -0800 (PST) From: Neil Armstrong To: dri-devel@lists.freedesktop.org Subject: [PATCH] drm/meson: Add support for VIC alternate timings Date: Tue, 6 Nov 2018 11:54:35 +0100 Message-Id: <1541501675-3928-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-20181106_025452_468343_6B5E0547 X-CRM114-Status: GOOD ( 18.93 ) 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, 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 change is an attempt to handle the alternate clock for the CEA mode. 60Hz vs. 59.94Hz, 30Hz vs 29.97Hz or 24Hz vs 23.97Hz on the Amlogic Meson SoC DRM Driver pixel clock generation. The actual clock generation will be moved to the Common Clock framework once all the video clock are handled by the Amlogic Meson SoC clock driver, then these alternate timings will be handled in the same time in a cleaner fashion. Signed-off-by: Neil Armstrong Reviewed-by: Maxime Jourdan --- drivers/gpu/drm/meson/meson_dw_hdmi.c | 12 +--- drivers/gpu/drm/meson/meson_vclk.c | 127 +++++++++++++++++++++++----------- drivers/gpu/drm/meson/meson_vclk.h | 2 + 3 files changed, 89 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c index df7247c..d8c5cc3 100644 --- a/drivers/gpu/drm/meson/meson_dw_hdmi.c +++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c @@ -594,17 +594,7 @@ dw_hdmi_mode_valid(struct drm_connector *connector, dev_dbg(connector->dev->dev, "%s: vclk:%d venc=%d hdmi=%d\n", __func__, vclk_freq, venc_freq, hdmi_freq); - /* Finally filter by configurable vclk frequencies for VIC modes */ - switch (vclk_freq) { - case 54000: - case 74250: - case 148500: - case 297000: - case 594000: - return MODE_OK; - } - - return MODE_CLOCK_RANGE; + return meson_vclk_vic_supported_freq(vclk_freq); } /* Encoder */ diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c index ae54732..5accceb 100644 --- a/drivers/gpu/drm/meson/meson_vclk.c +++ b/drivers/gpu/drm/meson/meson_vclk.c @@ -117,6 +117,8 @@ #define HDMI_PLL_RESET BIT(28) #define HDMI_PLL_LOCK BIT(31) +#define FREQ_1000_1001(_freq) DIV_ROUND_CLOSEST(_freq * 1000, 1001) + /* VID PLL Dividers */ enum { VID_PLL_DIV_1 = 0, @@ -323,7 +325,7 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv) enum { /* PLL O1 O2 O3 VP DV EN TX */ /* 4320 /4 /4 /1 /5 /1 => /2 /2 */ - MESON_VCLK_HDMI_ENCI_54000 = 1, + MESON_VCLK_HDMI_ENCI_54000 = 0, /* 4320 /4 /4 /1 /5 /1 => /1 /2 */ MESON_VCLK_HDMI_DDR_54000, /* 2970 /4 /1 /1 /5 /1 => /1 /2 */ @@ -339,6 +341,7 @@ enum { }; struct meson_vclk_params { + unsigned int pixel_freq; unsigned int pll_base_freq; unsigned int pll_od1; unsigned int pll_od2; @@ -347,6 +350,7 @@ struct meson_vclk_params { unsigned int vclk_div; } params[] = { [MESON_VCLK_HDMI_ENCI_54000] = { + .pixel_freq = 54000, .pll_base_freq = 4320000, .pll_od1 = 4, .pll_od2 = 4, @@ -355,6 +359,7 @@ struct meson_vclk_params { .vclk_div = 1, }, [MESON_VCLK_HDMI_DDR_54000] = { + .pixel_freq = 54000, .pll_base_freq = 4320000, .pll_od1 = 4, .pll_od2 = 4, @@ -363,6 +368,7 @@ struct meson_vclk_params { .vclk_div = 1, }, [MESON_VCLK_HDMI_DDR_148500] = { + .pixel_freq = 148500, .pll_base_freq = 2970000, .pll_od1 = 4, .pll_od2 = 1, @@ -371,6 +377,7 @@ struct meson_vclk_params { .vclk_div = 1, }, [MESON_VCLK_HDMI_74250] = { + .pixel_freq = 74250, .pll_base_freq = 2970000, .pll_od1 = 2, .pll_od2 = 2, @@ -379,6 +386,7 @@ struct meson_vclk_params { .vclk_div = 1, }, [MESON_VCLK_HDMI_148500] = { + .pixel_freq = 148500, .pll_base_freq = 2970000, .pll_od1 = 1, .pll_od2 = 2, @@ -387,6 +395,7 @@ struct meson_vclk_params { .vclk_div = 1, }, [MESON_VCLK_HDMI_297000] = { + .pixel_freq = 297000, .pll_base_freq = 2970000, .pll_od1 = 1, .pll_od2 = 1, @@ -395,6 +404,7 @@ struct meson_vclk_params { .vclk_div = 2, }, [MESON_VCLK_HDMI_594000] = { + .pixel_freq = 594000, .pll_base_freq = 5940000, .pll_od1 = 1, .pll_od2 = 1, @@ -402,6 +412,7 @@ struct meson_vclk_params { .vid_pll_div = VID_PLL_DIV_5, .vclk_div = 1, }, + { /* sentinel */ }, }; static inline unsigned int pll_od_to_reg(unsigned int od) @@ -626,12 +637,37 @@ static void meson_hdmi_pll_generic_set(struct meson_drm *priv, pll_freq); } +enum drm_mode_status +meson_vclk_vic_supported_freq(unsigned int freq) +{ + int i; + + DRM_DEBUG_DRIVER("freq = %d\n", freq); + + for (i = 0 ; params[i].pixel_freq ; ++i) { + DRM_DEBUG_DRIVER("i = %d pixel_freq = %d alt = %d\n", + i, params[i].pixel_freq, + FREQ_1000_1001(params[i].pixel_freq)); + /* Match strict frequency */ + if (freq == params[i].pixel_freq) + return MODE_OK; + /* Match 1000/1001 variant */ + if (freq == FREQ_1000_1001(params[i].pixel_freq)) + return MODE_OK; + } + + return MODE_CLOCK_RANGE; +} +EXPORT_SYMBOL_GPL(meson_vclk_vic_supported_freq); + static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq, unsigned int od1, unsigned int od2, unsigned int od3, unsigned int vid_pll_div, unsigned int vclk_div, unsigned int hdmi_tx_div, unsigned int venc_div, - bool hdmi_use_enci) + bool hdmi_use_enci, bool vic_alternate_clock) { + unsigned int m, frac; + /* Set HDMI-TX sys clock */ regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, CTS_HDMI_SYS_SEL_MASK, 0); @@ -646,34 +682,38 @@ static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq, } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) { switch (pll_base_freq) { case 2970000: - meson_hdmi_pll_set_params(priv, 0x3d, 0xe00, - od1, od2, od3); + m = 0x3d; + frac = vic_alternate_clock ? 0xd02 : 0xe00; break; case 4320000: - meson_hdmi_pll_set_params(priv, 0x5a, 0, - od1, od2, od3); + m = vic_alternate_clock ? 0x59 : 0x5a; + frac = vic_alternate_clock ? 0xe8f : 0; break; case 5940000: - meson_hdmi_pll_set_params(priv, 0x7b, 0xc00, - od1, od2, od3); + m = 0x7b; + frac = vic_alternate_clock ? 0xa05 : 0xc00; break; } + + meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3); } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") || meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) { switch (pll_base_freq) { case 2970000: - meson_hdmi_pll_set_params(priv, 0x7b, 0x300, - od1, od2, od3); + m = 0x7b; + frac = vic_alternate_clock ? 0x281 : 0x300; break; case 4320000: - meson_hdmi_pll_set_params(priv, 0xb4, 0, - od1, od2, od3); + m = vic_alternate_clock ? 0xb3 : 0xb4; + frac = vic_alternate_clock ? 0x347 : 0; break; case 5940000: - meson_hdmi_pll_set_params(priv, 0xf7, 0x200, - od1, od2, od3); + m = 0xf7; + frac = vic_alternate_clock ? 0x102 : 0x200; break; } + + meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3); } /* Setup vid_pll divider */ @@ -826,6 +866,7 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target, unsigned int vclk_freq, unsigned int venc_freq, unsigned int dac_freq, bool hdmi_use_enci) { + bool vic_alternate_clock = false; unsigned int freq; unsigned int hdmi_tx_div; unsigned int venc_div; @@ -843,7 +884,7 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target, * - encp encoder */ meson_vclk_set(priv, vclk_freq * 10, 0, 0, 0, - VID_PLL_DIV_5, 2, 1, 1, false); + VID_PLL_DIV_5, 2, 1, 1, false, false); return; } @@ -863,31 +904,35 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target, return; } - switch (vclk_freq) { - case 54000: - if (hdmi_use_enci) - freq = MESON_VCLK_HDMI_ENCI_54000; - else - freq = MESON_VCLK_HDMI_DDR_54000; - break; - case 74250: - freq = MESON_VCLK_HDMI_74250; - break; - case 148500: - if (dac_freq != 148500) - freq = MESON_VCLK_HDMI_DDR_148500; - else - freq = MESON_VCLK_HDMI_148500; - break; - case 297000: - freq = MESON_VCLK_HDMI_297000; - break; - case 594000: - freq = MESON_VCLK_HDMI_594000; - break; - default: - pr_err("Fatal Error, invalid HDMI vclk freq %d\n", - vclk_freq); + for (freq = 0 ; params[freq].pixel_freq ; ++freq) { + if (vclk_freq == params[freq].pixel_freq || + vclk_freq == FREQ_1000_1001(params[freq].pixel_freq)) { + if (vclk_freq != params[freq].pixel_freq) + vic_alternate_clock = true; + else + vic_alternate_clock = false; + + if (freq == MESON_VCLK_HDMI_ENCI_54000 && + !hdmi_use_enci) + continue; + + if (freq == MESON_VCLK_HDMI_DDR_54000 && + hdmi_use_enci) + continue; + + if (freq == MESON_VCLK_HDMI_DDR_148500 && + dac_freq == vclk_freq) + continue; + + if (freq == MESON_VCLK_HDMI_148500 && + dac_freq != vclk_freq) + continue; + break; + } + } + + if (!params[freq].pixel_freq) { + pr_err("Fatal Error, invalid HDMI vclk freq %d\n", vclk_freq); return; } @@ -895,6 +940,6 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target, params[freq].pll_od1, params[freq].pll_od2, params[freq].pll_od3, params[freq].vid_pll_div, params[freq].vclk_div, hdmi_tx_div, venc_div, - hdmi_use_enci); + hdmi_use_enci, vic_alternate_clock); } EXPORT_SYMBOL_GPL(meson_vclk_setup); diff --git a/drivers/gpu/drm/meson/meson_vclk.h b/drivers/gpu/drm/meson/meson_vclk.h index 869fa3a..4bd8752 100644 --- a/drivers/gpu/drm/meson/meson_vclk.h +++ b/drivers/gpu/drm/meson/meson_vclk.h @@ -32,6 +32,8 @@ enum { enum drm_mode_status meson_vclk_dmt_supported_freq(struct meson_drm *priv, unsigned int freq); +enum drm_mode_status +meson_vclk_vic_supported_freq(unsigned int freq); void meson_vclk_setup(struct meson_drm *priv, unsigned int target, unsigned int vclk_freq, unsigned int venc_freq,