[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250110-drm-s4-v1-9-cbc2d5edaae8@amlogic.com>
Date: Fri, 10 Jan 2025 13:39:59 +0800
From: Ao Xu via B4 Relay <devnull+ao.xu.amlogic.com@...nel.org>
To: Neil Armstrong <neil.armstrong@...aro.org>,
Maarten Lankhorst <maarten.lankhorst@...ux.intel.com>,
Maxime Ripard <mripard@...nel.org>, Thomas Zimmermann <tzimmermann@...e.de>,
David Airlie <airlied@...il.com>, Simona Vetter <simona@...ll.ch>,
Rob Herring <robh@...nel.org>, Krzysztof Kozlowski <krzk+dt@...nel.org>,
Conor Dooley <conor+dt@...nel.org>, Kevin Hilman <khilman@...libre.com>,
Jerome Brunet <jbrunet@...libre.com>,
Martin Blumenstingl <martin.blumenstingl@...glemail.com>
Cc: dri-devel@...ts.freedesktop.org, linux-amlogic@...ts.infradead.org,
devicetree@...r.kernel.org, linux-arm-kernel@...ts.infradead.org,
linux-kernel@...r.kernel.org, Ao Xu <ao.xu@...ogic.com>
Subject: [PATCH 09/11] drm: meson: add vpu clk setting for S4
From: Ao Xu <ao.xu@...ogic.com>
The S4-series splits the HIU into `sys_ctrl`, `pwr_ctrl`, and `clk_ctrl`.
Introduce VPU clock settings specific to the Amlogic S4 SoC,
which differ from the configurations used for G12.
Signed-off-by: Ao Xu <ao.xu@...ogic.com>
---
drivers/gpu/drm/meson/meson_vclk.c | 1018 +++++++++++++++++++++++++-----------
1 file changed, 720 insertions(+), 298 deletions(-)
diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c
index 2a942dc6a6dc23561ec26a54139b27acf8009ccb..b2707af2a5283874936658d2749cecb4ef86beb5 100644
--- a/drivers/gpu/drm/meson/meson_vclk.c
+++ b/drivers/gpu/drm/meson/meson_vclk.c
@@ -87,8 +87,11 @@
#define CTS_VDAC_EN BIT(4)
#define HDMI_TX_PIXEL_EN BIT(5)
#define HHI_HDMI_CLK_CNTL 0x1cc /* 0x73 offset in data sheet */
-#define HDMI_TX_PIXEL_SEL_MASK (0xf << 16)
+#define HDMI_TX_PIXEL_SEL_MASK GENMASK(19, 16)
#define HDMI_TX_PIXEL_SEL_SHIFT 16
+
+#define HDMI_TX_FE_SEL_MASK GENMASK(23, 20)
+#define HDMI_TX_FE_SEL_SHIFT 20
#define CTS_HDMI_SYS_SEL_MASK (0x7 << 9)
#define CTS_HDMI_SYS_DIV_MASK (0x7f)
#define CTS_HDMI_SYS_EN BIT(8)
@@ -110,6 +113,30 @@
#define HDMI_PLL_LOCK BIT(31)
#define HDMI_PLL_LOCK_G12A (3 << 30)
+/* ANA Registers */
+/* REG_BASE: REGISTER_BASE_ADDR = 0xfe000000 */
+#define CLKCTRL_VID_CLK_CTRL 0x0c0 /* 0x30 offset in data sheet */
+#define CLKCTRL_VID_CLK_CTRL2 0x0c4 /* 0x31 offset in data sheet */
+#define CLKCTRL_VID_CLK_DIV 0x0c8 /* 0x32 offset in data sheet */
+#define CLKCTRL_VIID_CLK_DIV 0x0cc /* 0x33 offset in data sheet */
+#define CLKCTRL_VIID_CLK_CTRL 0x0d0 /* 0x34 offset in data sheet */
+
+#define CLKCTRL_VID_PLL_CLK_DIV 0x0e4 /* 0x39 offset in data sheet */
+#define CLKCTRL_HDMI_CLK_CTRL 0x0e0 /* 0x38 */
+
+/* REG_BASE: REGISTER_BASE_ADDR = 0xfe008000 */
+#define ANACTRL_HDMIPLL_CTRL0 0x1c0 /* 0x70 offset in data sheet */
+#define ANACTRL_HDMIPLL_CTRL1 0x1c4 /* 0x71 offset in data sheet */
+#define ANACTRL_HDMIPLL_CTRL2 0x1c8 /* 0x72 offset in data sheet */
+#define ANACTRL_HDMIPLL_CTRL3 0x1cc /* 0x73 offset in data sheet */
+#define ANACTRL_HDMIPLL_CTRL4 0x1d0 /* 0x74 offset in data sheet */
+#define ANACTRL_HDMIPLL_CTRL5 0x1d4 /* 0x75 offset in data sheet */
+#define ANACTRL_HDMIPLL_CTRL6 0x1d8 /* 0x76 offset in data sheet */
+#define ANACTRL_HDMIPLL_STS 0x1dc /* 0x77 offset in data sheet */
+#define ANACTRL_HDMIPLL_VLOCK 0x1e4 /* 0x79 offset in data sheet */
+#define HDMI_PLL_RESET_S4 BIT(29)
+#define HDMI_PLL_LOCK_S4 (3 << 30)
+
#define FREQ_1000_1001(_freq) DIV_ROUND_CLOSEST(_freq * 1000, 1001)
/* VID PLL Dividers */
@@ -137,8 +164,13 @@ static void meson_vid_pll_set(struct meson_drm *priv, unsigned int div)
unsigned int shift_sel = 0;
/* Disable vid_pll output clock */
- regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_EN, 0);
- regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_PRESET, 0);
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_S4)) {
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_PLL_CLK_DIV, VID_PLL_EN, 0);
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_PLL_CLK_DIV, VID_PLL_PRESET, 0);
+ } else {
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_EN, 0);
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_PRESET, 0);
+ }
switch (div) {
case VID_PLL_DIV_2:
@@ -199,37 +231,71 @@ static void meson_vid_pll_set(struct meson_drm *priv, unsigned int div)
break;
}
- if (div == VID_PLL_DIV_1)
- /* Enable vid_pll bypass to HDMI pll */
- regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
- VID_PLL_BYPASS, VID_PLL_BYPASS);
- else {
- /* Disable Bypass */
- regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
- VID_PLL_BYPASS, 0);
- /* Clear sel */
- regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
- 3 << 16, 0);
- regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
- VID_PLL_PRESET, 0);
- regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
- 0x7fff, 0);
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_S4)) {
+ if (div == VID_PLL_DIV_1) {
+ /* Enable vid_pll bypass to HDMI pll */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_PLL_CLK_DIV,
+ VID_PLL_BYPASS, VID_PLL_BYPASS);
+ } else {
+ /* Disable Bypass */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_PLL_CLK_DIV,
+ VID_PLL_BYPASS, 0);
+ /* Clear sel */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_PLL_CLK_DIV,
+ 3 << 16, 0);
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_PLL_CLK_DIV,
+ VID_PLL_PRESET, 0);
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_PLL_CLK_DIV,
+ 0x7fff, 0);
+
+ /* Setup sel and val */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_PLL_CLK_DIV,
+ 3 << 16, shift_sel << 16);
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_PLL_CLK_DIV,
+ VID_PLL_PRESET, VID_PLL_PRESET);
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_PLL_CLK_DIV,
+ 0x7fff, shift_val);
+
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_PLL_CLK_DIV,
+ VID_PLL_PRESET, 0);
+ }
- /* Setup sel and val */
- regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
- 3 << 16, shift_sel << 16);
- regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
- VID_PLL_PRESET, VID_PLL_PRESET);
- regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
- 0x7fff, shift_val);
+ /* Enable the vid_pll output clock */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_PLL_CLK_DIV,
+ VID_PLL_EN, VID_PLL_EN);
+ } else {
+ if (div == VID_PLL_DIV_1) {
+ /* Enable vid_pll bypass to HDMI pll */
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
+ VID_PLL_BYPASS, VID_PLL_BYPASS);
+ } else {
+ /* Disable Bypass */
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
+ VID_PLL_BYPASS, 0);
+ /* Clear sel */
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
+ 3 << 16, 0);
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
+ VID_PLL_PRESET, 0);
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
+ 0x7fff, 0);
+
+ /* Setup sel and val */
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
+ 3 << 16, shift_sel << 16);
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
+ VID_PLL_PRESET, VID_PLL_PRESET);
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
+ 0x7fff, shift_val);
+
+ regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
+ VID_PLL_PRESET, 0);
+ }
+ /* Enable the vid_pll output clock */
regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
- VID_PLL_PRESET, 0);
+ VID_PLL_EN, VID_PLL_EN);
}
-
- /* Enable the vid_pll output clock */
- regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
- VID_PLL_EN, VID_PLL_EN);
}
/*
@@ -287,56 +353,117 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
((val & HDMI_PLL_LOCK_G12A) == HDMI_PLL_LOCK_G12A),
10, 0);
+ } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_S4)) {
+ regmap_write(priv->hhi, ANACTRL_HDMIPLL_CTRL0, 0x3b01047b);
+ regmap_write(priv->hhi, ANACTRL_HDMIPLL_CTRL1, 0x00018000);
+ regmap_write(priv->hhi, ANACTRL_HDMIPLL_CTRL2, 0x00000000);
+ regmap_write(priv->hhi, ANACTRL_HDMIPLL_CTRL3, 0x0a691c00);
+ regmap_write(priv->hhi, ANACTRL_HDMIPLL_CTRL4, 0x33771290);
+ regmap_write(priv->hhi, ANACTRL_HDMIPLL_CTRL5, 0x39270000);
+ regmap_write(priv->hhi, ANACTRL_HDMIPLL_CTRL6, 0x50540000);
+ regmap_write(priv->hhi, ANACTRL_HDMIPLL_CTRL0, 0x1b01047b);
+
+ /* Poll for lock bit */
+ regmap_read_poll_timeout(priv->hhi, ANACTRL_HDMIPLL_CTRL0, val,
+ ((val & HDMI_PLL_LOCK) == HDMI_PLL_LOCK),
+ 10, 0);
}
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_S4)) {
+ /* Disable VCLK2 */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VIID_CLK_CTRL, VCLK2_EN, 0);
- /* Disable VCLK2 */
- regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, 0);
+ /* Setup vid_pll to /1 */
+ meson_vid_pll_set(priv, VID_PLL_DIV_1);
- /* Setup vid_pll to /1 */
- meson_vid_pll_set(priv, VID_PLL_DIV_1);
+ /* Setup the VCLK2 divider value to achieve 27MHz */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VIID_CLK_DIV,
+ VCLK2_DIV_MASK, (55 - 1));
- /* Setup the VCLK2 divider value to achieve 27MHz */
- regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV,
- VCLK2_DIV_MASK, (55 - 1));
+ /* select vid_pll for vclk2 */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VIID_CLK_CTRL,
+ VCLK2_SEL_MASK, (0 << VCLK2_SEL_SHIFT));
- /* select vid_pll for vclk2 */
- if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+ /* enable vclk2 gate */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VIID_CLK_CTRL, VCLK2_EN, VCLK2_EN);
+
+ /* select vclk_div1 for enci */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_DIV,
+ CTS_ENCI_SEL_MASK, (8 << CTS_ENCI_SEL_SHIFT));
+ /* select vclk_div1 for vdac */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VIID_CLK_DIV,
+ CTS_VDAC_SEL_MASK, (8 << CTS_VDAC_SEL_SHIFT));
+
+ /* release vclk2_div_reset and enable vclk2_div */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VIID_CLK_DIV,
+ VCLK2_DIV_EN | VCLK2_DIV_RESET, VCLK2_DIV_EN);
+
+ /* enable vclk2_div1 gate */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VIID_CLK_CTRL,
+ VCLK2_DIV1_EN, VCLK2_DIV1_EN);
+
+ /* reset vclk2 */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VIID_CLK_CTRL,
+ VCLK2_SOFT_RESET, VCLK2_SOFT_RESET);
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VIID_CLK_CTRL,
+ VCLK2_SOFT_RESET, 0);
+
+ /* enable enci_clk */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_CTRL2,
+ CTS_ENCI_EN, CTS_ENCI_EN);
+ /* enable vdac_clk */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_CTRL2,
+ CTS_VDAC_EN, CTS_VDAC_EN);
+
+ } else {
+ /* Disable VCLK2 */
+ regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, 0);
+
+ /* Setup vid_pll to /1 */
+ meson_vid_pll_set(priv, VID_PLL_DIV_1);
+
+ /* Setup the VCLK2 divider value to achieve 27MHz */
+ regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV,
+ VCLK2_DIV_MASK, (55 - 1));
+
+ /* select vid_pll for vclk2 */
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+ regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
+ VCLK2_SEL_MASK, (0 << VCLK2_SEL_SHIFT));
+ else
+ regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
+ VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
+
+ /* enable vclk2 gate */
+ regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, VCLK2_EN);
+
+ /* select vclk_div1 for enci */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
+ CTS_ENCI_SEL_MASK, (8 << CTS_ENCI_SEL_SHIFT));
+ /* select vclk_div1 for vdac */
+ regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV,
+ CTS_VDAC_SEL_MASK, (8 << CTS_VDAC_SEL_SHIFT));
+
+ /* release vclk2_div_reset and enable vclk2_div */
+ regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV,
+ VCLK2_DIV_EN | VCLK2_DIV_RESET, VCLK2_DIV_EN);
+
+ /* enable vclk2_div1 gate */
regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
- VCLK2_SEL_MASK, (0 << VCLK2_SEL_SHIFT));
- else
+ VCLK2_DIV1_EN, VCLK2_DIV1_EN);
+
+ /* reset vclk2 */
+ regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
+ VCLK2_SOFT_RESET, VCLK2_SOFT_RESET);
regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
- VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
-
- /* enable vclk2 gate */
- regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, VCLK2_EN);
-
- /* select vclk_div1 for enci */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
- CTS_ENCI_SEL_MASK, (8 << CTS_ENCI_SEL_SHIFT));
- /* select vclk_div1 for vdac */
- regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV,
- CTS_VDAC_SEL_MASK, (8 << CTS_VDAC_SEL_SHIFT));
-
- /* release vclk2_div_reset and enable vclk2_div */
- regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV,
- VCLK2_DIV_EN | VCLK2_DIV_RESET, VCLK2_DIV_EN);
-
- /* enable vclk2_div1 gate */
- regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
- VCLK2_DIV1_EN, VCLK2_DIV1_EN);
-
- /* reset vclk2 */
- regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
- VCLK2_SOFT_RESET, VCLK2_SOFT_RESET);
- regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
- VCLK2_SOFT_RESET, 0);
-
- /* enable enci_clk */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
- CTS_ENCI_EN, CTS_ENCI_EN);
- /* enable vdac_clk */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
- CTS_VDAC_EN, CTS_VDAC_EN);
+ VCLK2_SOFT_RESET, 0);
+
+ /* enable enci_clk */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
+ CTS_ENCI_EN, CTS_ENCI_EN);
+ /* enable vdac_clk */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
+ CTS_VDAC_EN, CTS_VDAC_EN);
+ }
}
enum {
@@ -357,6 +484,8 @@ enum {
MESON_VCLK_HDMI_594000,
/* 2970 /1 /1 /1 /5 /1 => /1 /2 */
MESON_VCLK_HDMI_594000_YUV420,
+/* 4320 /4 /4 /1 /5 /1 => /2 /2 */
+ MESON_VCLK_HDMI_27000,
};
struct meson_vclk_params {
@@ -467,6 +596,18 @@ struct meson_vclk_params {
.vid_pll_div = VID_PLL_DIV_5,
.vclk_div = 1,
},
+ [MESON_VCLK_HDMI_27000] = {
+ .pll_freq = 4320000,
+ .phy_freq = 270000,
+ .vclk_freq = 54000,
+ .venc_freq = 27000,
+ .pixel_freq = 27000,
+ .pll_od1 = 4,
+ .pll_od2 = 4,
+ .pll_od3 = 1,
+ .vid_pll_div = VID_PLL_DIV_5,
+ .vclk_div = 1,
+ },
{ /* sentinel */ },
};
@@ -487,136 +628,226 @@ static inline unsigned int pll_od_to_reg(unsigned int od)
return 0;
}
-static void meson_hdmi_pll_set_params(struct meson_drm *priv, unsigned int m,
+static void gxbb_pll_set_params(struct meson_drm *priv, unsigned int m,
unsigned int frac, unsigned int od1,
unsigned int od2, unsigned int od3)
{
unsigned int val;
- if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
- regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x58000200 | m);
- if (frac)
- regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2,
- 0x00004000 | frac);
- else
- 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);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x58000200 | m);
+ if (frac)
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2,
+ 0x00004000 | frac);
+ else
+ 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);
+
+ /* Enable and unreset */
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
+ 0x7 << 28, HHI_HDMI_PLL_CNTL_EN);
+
+ /* Poll for lock bit */
+ regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
+ val, (val & HDMI_PLL_LOCK), 10, 0);
+
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
+ 3 << 16, pll_od_to_reg(od1) << 16);
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
+ 3 << 22, pll_od_to_reg(od2) << 22);
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
+ 3 << 18, pll_od_to_reg(od3) << 18);
+}
- /* Enable and unreset */
- regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
- 0x7 << 28, HHI_HDMI_PLL_CNTL_EN);
+static void gxm_pll_set_params(struct meson_drm *priv, unsigned int m,
+ unsigned int frac, unsigned int od1,
+ unsigned int od2, unsigned int od3)
+{
+ unsigned int val;
- /* Poll for lock bit */
- regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
- val, (val & HDMI_PLL_LOCK), 10, 0);
- } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
- meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
- regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x40000200 | m);
- regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb000 | frac);
- 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);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x40000200 | m);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb000 | frac);
+ 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);
- /* Reset PLL */
- regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
- HDMI_PLL_RESET, HDMI_PLL_RESET);
- regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
- HDMI_PLL_RESET, 0);
+ /* Reset PLL */
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
+ HDMI_PLL_RESET, HDMI_PLL_RESET);
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
+ HDMI_PLL_RESET, 0);
- /* Poll for lock bit */
- regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
- (val & HDMI_PLL_LOCK), 10, 0);
- } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
- regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x0b3a0400 | m);
+ /* Poll for lock bit */
+ regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
+ (val & HDMI_PLL_LOCK), 10, 0);
- /* Enable and reset */
- /* TODO: add specific macro for g12a here */
- regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
- 0x3 << 28, 0x3 << 28);
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
+ 3 << 21, pll_od_to_reg(od1) << 21);
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
+ 3 << 23, pll_od_to_reg(od2) << 23);
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
+ 3 << 19, pll_od_to_reg(od3) << 19);
+}
- regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, frac);
- regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x00000000);
+static void g12a_pll_set_params(struct meson_drm *priv, unsigned int m,
+ unsigned int frac, unsigned int od1,
+ unsigned int od2, unsigned int od3)
+{
+ unsigned int val;
+
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x0b3a0400 | m);
+
+ /* Enable and reset */
+ /* TODO: add specific macro for g12a here */
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
+ 0x3 << 28, 0x3 << 28);
- /* G12A HDMI PLL Needs specific parameters for 5.4GHz */
- if (m >= 0xf7) {
- if (frac < 0x10000) {
- regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4,
- 0x6a685c00);
- regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5,
- 0x11551293);
- } else {
- regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4,
- 0xea68dc00);
- regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5,
- 0x65771290);
- }
- regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39272000);
- regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x55540000);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, frac);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x00000000);
+
+ /* G12A HDMI PLL Needs specific parameters for 5.4GHz */
+ if (m >= 0xf7) {
+ if (frac < 0x10000) {
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4,
+ 0x6a685c00);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5,
+ 0x11551293);
} else {
- regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0a691c00);
- regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x33771290);
- regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39270000);
- regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x50540000);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4,
+ 0xea68dc00);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5,
+ 0x65771290);
}
-
- do {
- /* Reset PLL */
- regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
- HDMI_PLL_RESET_G12A, HDMI_PLL_RESET_G12A);
-
- /* UN-Reset PLL */
- regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
- HDMI_PLL_RESET_G12A, 0);
-
- /* Poll for lock bits */
- if (!regmap_read_poll_timeout(priv->hhi,
- HHI_HDMI_PLL_CNTL, val,
- ((val & HDMI_PLL_LOCK_G12A)
- == HDMI_PLL_LOCK_G12A),
- 10, 100))
- break;
- } while(1);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39272000);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x55540000);
+ } else {
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0a691c00);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x33771290);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39270000);
+ regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x50540000);
}
- if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
- regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
- 3 << 16, pll_od_to_reg(od1) << 16);
- else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
- meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
- regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
- 3 << 21, pll_od_to_reg(od1) << 21);
- else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+ do {
+ /* Reset PLL */
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
- 3 << 16, pll_od_to_reg(od1) << 16);
+ HDMI_PLL_RESET_G12A, HDMI_PLL_RESET_G12A);
- if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
- regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
- 3 << 22, pll_od_to_reg(od2) << 22);
- else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
- meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
- regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
- 3 << 23, pll_od_to_reg(od2) << 23);
- else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+ /* UN-Reset PLL */
regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
- 3 << 18, pll_od_to_reg(od2) << 18);
+ HDMI_PLL_RESET_G12A, 0);
+
+ /* Poll for lock bits */
+ if (!regmap_read_poll_timeout(priv->hhi,
+ HHI_HDMI_PLL_CNTL, val,
+ ((val & HDMI_PLL_LOCK_G12A)
+ == HDMI_PLL_LOCK_G12A),
+ 10, 100))
+ break;
+ } while (1);
- if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
- regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
- 3 << 18, pll_od_to_reg(od3) << 18);
- else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
- meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
- regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
- 3 << 19, pll_od_to_reg(od3) << 19);
- else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
- regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
+ 3 << 16, pll_od_to_reg(od1) << 16);
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
+ 3 << 18, pll_od_to_reg(od2) << 18);
+ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
+ 3 << 20, pll_od_to_reg(od3) << 20);
+}
+
+static void s4_pll_set_params(struct meson_drm *priv, unsigned int m,
+ unsigned int frac, unsigned int od1,
+ unsigned int od2, unsigned int od3)
+{
+ unsigned int val;
+
+ DRM_DEBUG_DRIVER("%s: m = %d, frac = %d, od1 = %d, od2 = %d, od3 = %d\n",
+ __func__, m, frac, od1, od2, od3);
+
+ regmap_write(priv->hhi, ANACTRL_HDMIPLL_CTRL0, 0x0b3a0400 | m);
+
+ /* Enable and reset */
+ /* TODO: add specific macro for g12a here */
+ regmap_update_bits(priv->hhi, ANACTRL_HDMIPLL_CTRL0,
+ 0x3 << 28, 0x3 << 28);
+
+ regmap_write(priv->hhi, ANACTRL_HDMIPLL_CTRL1, frac);
+ regmap_write(priv->hhi, ANACTRL_HDMIPLL_CTRL2, 0x00000000);
+
+ /* S4 HDMI PLL Needs specific parameters for 5.4GHz */
+ if (m >= 0xf7) {
+ if (frac < 0x10000) {
+ regmap_write(priv->hhi, ANACTRL_HDMIPLL_CTRL3,
+ 0x6a685c00);
+ regmap_write(priv->hhi, ANACTRL_HDMIPLL_CTRL4,
+ 0x11551293);
+ } else {
+ regmap_write(priv->hhi, ANACTRL_HDMIPLL_CTRL3,
+ 0x6a685c00);
+ regmap_write(priv->hhi, ANACTRL_HDMIPLL_CTRL4,
+ 0x44331290);
+ }
+ regmap_write(priv->hhi, ANACTRL_HDMIPLL_CTRL5, 0x39272008);
+ regmap_write(priv->hhi, ANACTRL_HDMIPLL_CTRL6, 0x56540000);
+ } else {
+ regmap_write(priv->hhi, ANACTRL_HDMIPLL_CTRL3, 0x6a68dc00);
+ regmap_write(priv->hhi, ANACTRL_HDMIPLL_CTRL4, 0x65771290);
+ regmap_write(priv->hhi, ANACTRL_HDMIPLL_CTRL5, 0x39272008);
+ regmap_write(priv->hhi, ANACTRL_HDMIPLL_CTRL6, 0x56540000);
+ }
+
+ do {
+ //todo, need confir rst and lock bit
+ /* Reset PLL */
+ regmap_update_bits(priv->hhi, ANACTRL_HDMIPLL_CTRL0,
+ HDMI_PLL_RESET_S4, HDMI_PLL_RESET_S4);
+
+ /* UN-Reset PLL */
+ regmap_update_bits(priv->hhi, ANACTRL_HDMIPLL_CTRL0,
+ HDMI_PLL_RESET_S4, 0);
+
+ /* Poll for lock bits */
+ if (!regmap_read_poll_timeout(priv->hhi,
+ ANACTRL_HDMIPLL_CTRL0, val,
+ ((val & HDMI_PLL_LOCK_S4)
+ == HDMI_PLL_LOCK_S4),
+ 10, 100))
+ break;
+ } while (1);
+
+ regmap_update_bits(priv->hhi, ANACTRL_HDMIPLL_CTRL0,
+ 3 << 16, pll_od_to_reg(od1) << 16);
+ regmap_update_bits(priv->hhi, ANACTRL_HDMIPLL_CTRL0,
+ 3 << 18, pll_od_to_reg(od2) << 18);
+ regmap_update_bits(priv->hhi, ANACTRL_HDMIPLL_CTRL0,
3 << 20, pll_od_to_reg(od3) << 20);
}
+static void meson_hdmi_pll_set_params(struct meson_drm *priv, unsigned int m,
+ unsigned int frac, unsigned int od1,
+ unsigned int od2, unsigned int od3)
+{
+ switch (priv->compat) {
+ case VPU_COMPATIBLE_GXBB:
+ gxbb_pll_set_params(priv, m, frac, od1, od2, od3);
+ break;
+ case VPU_COMPATIBLE_GXM:
+ case VPU_COMPATIBLE_GXL:
+ gxm_pll_set_params(priv, m, frac, od1, od2, od3);
+ break;
+ case VPU_COMPATIBLE_G12A:
+ g12a_pll_set_params(priv, m, frac, od1, od2, od3);
+ break;
+ case VPU_COMPATIBLE_S4:
+ s4_pll_set_params(priv, m, frac, od1, od2, od3);
+ break;
+ default:
+ break;
+ }
+}
+
#define XTAL_FREQ 24000
static unsigned int meson_hdmi_pll_get_m(struct meson_drm *priv,
@@ -632,6 +863,7 @@ static unsigned int meson_hdmi_pll_get_m(struct meson_drm *priv,
#define HDMI_FRAC_MAX_GXBB 4096
#define HDMI_FRAC_MAX_GXL 1024
#define HDMI_FRAC_MAX_G12A 131072
+#define HDMI_FRAC_MAX_S4 131072
static unsigned int meson_hdmi_pll_get_frac(struct meson_drm *priv,
unsigned int m,
@@ -651,6 +883,9 @@ static unsigned int meson_hdmi_pll_get_frac(struct meson_drm *priv,
if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
frac_max = HDMI_FRAC_MAX_G12A;
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_S4))
+ frac_max = HDMI_FRAC_MAX_S4;
+
/* We can have a perfect match !*/
if (pll_freq / m == parent_freq &&
pll_freq % m == 0)
@@ -688,6 +923,12 @@ static bool meson_hdmi_pll_validate_params(struct meson_drm *priv,
return false;
if (frac >= HDMI_FRAC_MAX_G12A)
return false;
+ } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_S4)) {
+ /* Empiric supported min/max dividers */
+ if (m < 106 || m > 247)
+ return false;
+ if (frac >= HDMI_FRAC_MAX_S4)
+ return false;
}
return true;
@@ -813,14 +1054,22 @@ static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
{
unsigned int m = 0, frac = 0;
- /* Set HDMI-TX sys clock */
- regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
- CTS_HDMI_SYS_SEL_MASK, 0);
- regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
- CTS_HDMI_SYS_DIV_MASK, 0);
- regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
- CTS_HDMI_SYS_EN, CTS_HDMI_SYS_EN);
-
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_S4)) {
+ regmap_update_bits(priv->clkctrl, CLKCTRL_HDMI_CLK_CTRL,
+ CTS_HDMI_SYS_SEL_MASK, 0);
+ regmap_update_bits(priv->clkctrl, CLKCTRL_HDMI_CLK_CTRL,
+ CTS_HDMI_SYS_DIV_MASK, 0);
+ regmap_update_bits(priv->clkctrl, CLKCTRL_HDMI_CLK_CTRL,
+ CTS_HDMI_SYS_EN, CTS_HDMI_SYS_EN);
+ } else {
+ /* Set HDMI-TX sys clock */
+ regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
+ CTS_HDMI_SYS_SEL_MASK, 0);
+ regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
+ CTS_HDMI_SYS_DIV_MASK, 0);
+ regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
+ CTS_HDMI_SYS_EN, CTS_HDMI_SYS_EN);
+ }
/* Set HDMI PLL rate */
if (!od1 && !od2 && !od3) {
meson_hdmi_pll_generic_set(priv, pll_base_freq);
@@ -875,6 +1124,22 @@ static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
break;
}
+ meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
+ } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_S4)) {
+ switch (pll_base_freq) {
+ case 2970000:
+ m = 0x7b;
+ frac = vic_alternate_clock ? 0x140b4 : 0x18000;
+ break;
+ case 4320000:
+ m = vic_alternate_clock ? 0xb3 : 0xb4;
+ frac = vic_alternate_clock ? 0x1a3ee : 0;
+ break;
+ case 5940000:
+ m = 0xf7;
+ frac = vic_alternate_clock ? 0x8148 : 0x10000;
+ break;
+ }
meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
}
@@ -882,146 +1147,303 @@ static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
meson_vid_pll_set(priv, vid_pll_div);
/* Set VCLK div */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
- VCLK_SEL_MASK, 0);
- regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
- VCLK_DIV_MASK, vclk_div - 1);
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_S4)) {
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_CTRL,
+ VCLK_SEL_MASK, 0);
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_DIV,
+ VCLK_DIV_MASK, vclk_div - 1);
+ } else {
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
+ VCLK_SEL_MASK, 0);
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
+ VCLK_DIV_MASK, vclk_div - 1);
+ }
/* Set HDMI-TX source */
switch (hdmi_tx_div) {
case 1:
- /* enable vclk_div1 gate */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
- VCLK_DIV1_EN, VCLK_DIV1_EN);
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_S4)) {
+ /* enable vclk_div1 gate */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_CTRL,
+ VCLK_DIV1_EN, VCLK_DIV1_EN);
+
+ /* select vclk_div1 for HDMI-TX */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_HDMI_CLK_CTRL,
+ HDMI_TX_PIXEL_SEL_MASK, 0);
+ regmap_update_bits(priv->clkctrl, CLKCTRL_HDMI_CLK_CTRL,
+ HDMI_TX_FE_SEL_MASK, 0);
+ } else {
+ /* enable vclk_div1 gate */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
+ VCLK_DIV1_EN, VCLK_DIV1_EN);
- /* select vclk_div1 for HDMI-TX */
- regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
- HDMI_TX_PIXEL_SEL_MASK, 0);
+ /* select vclk_div1 for HDMI-TX */
+ regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
+ HDMI_TX_PIXEL_SEL_MASK, 0);
+ }
break;
case 2:
- /* enable vclk_div2 gate */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
- VCLK_DIV2_EN, VCLK_DIV2_EN);
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_S4)) {
+ /* enable vclk_div2 gate */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_CTRL,
+ VCLK_DIV2_EN, VCLK_DIV2_EN);
+
+ /* select vclk_div2 for HDMI-TX */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_HDMI_CLK_CTRL,
+ HDMI_TX_PIXEL_SEL_MASK, 1 << HDMI_TX_PIXEL_SEL_SHIFT);
+ regmap_update_bits(priv->clkctrl, CLKCTRL_HDMI_CLK_CTRL,
+ HDMI_TX_FE_SEL_MASK, 1 << HDMI_TX_FE_SEL_SHIFT);
+ } else {
+ /* enable vclk_div2 gate */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
+ VCLK_DIV2_EN, VCLK_DIV2_EN);
- /* select vclk_div2 for HDMI-TX */
- regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
- HDMI_TX_PIXEL_SEL_MASK, 1 << HDMI_TX_PIXEL_SEL_SHIFT);
+ /* select vclk_div2 for HDMI-TX */
+ regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
+ HDMI_TX_PIXEL_SEL_MASK, 1 << HDMI_TX_PIXEL_SEL_SHIFT);
+ }
break;
case 4:
- /* enable vclk_div4 gate */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
- VCLK_DIV4_EN, VCLK_DIV4_EN);
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_S4)) {
+ /* enable vclk_div4 gate */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_CTRL,
+ VCLK_DIV4_EN, VCLK_DIV4_EN);
+
+ /* select vclk_div4 for HDMI-TX */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_HDMI_CLK_CTRL,
+ HDMI_TX_PIXEL_SEL_MASK, 2 << HDMI_TX_PIXEL_SEL_SHIFT);
+ regmap_update_bits(priv->clkctrl, CLKCTRL_HDMI_CLK_CTRL,
+ HDMI_TX_FE_SEL_MASK, 2 << HDMI_TX_FE_SEL_SHIFT);
+ } else {
+ /* enable vclk_div4 gate */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
+ VCLK_DIV4_EN, VCLK_DIV4_EN);
- /* select vclk_div4 for HDMI-TX */
- regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
- HDMI_TX_PIXEL_SEL_MASK, 2 << HDMI_TX_PIXEL_SEL_SHIFT);
+ /* select vclk_div4 for HDMI-TX */
+ regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
+ HDMI_TX_PIXEL_SEL_MASK, 2 << HDMI_TX_PIXEL_SEL_SHIFT);
+ }
break;
case 6:
- /* enable vclk_div6 gate */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
- VCLK_DIV6_EN, VCLK_DIV6_EN);
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_S4)) {
+ /* enable vclk_div6 gate */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_CTRL,
+ VCLK_DIV6_EN, VCLK_DIV6_EN);
+
+ /* select vclk_div6 for HDMI-TX */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_HDMI_CLK_CTRL,
+ HDMI_TX_PIXEL_SEL_MASK, 3 << HDMI_TX_PIXEL_SEL_SHIFT);
+ regmap_update_bits(priv->clkctrl, CLKCTRL_HDMI_CLK_CTRL,
+ HDMI_TX_FE_SEL_MASK, 3 << HDMI_TX_FE_SEL_SHIFT);
+ } else {
+ /* enable vclk_div6 gate */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
+ VCLK_DIV6_EN, VCLK_DIV6_EN);
- /* select vclk_div6 for HDMI-TX */
- regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
- HDMI_TX_PIXEL_SEL_MASK, 3 << HDMI_TX_PIXEL_SEL_SHIFT);
+ /* select vclk_div6 for HDMI-TX */
+ regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
+ HDMI_TX_PIXEL_SEL_MASK, 3 << HDMI_TX_PIXEL_SEL_SHIFT);
+ }
break;
case 12:
- /* enable vclk_div12 gate */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
- VCLK_DIV12_EN, VCLK_DIV12_EN);
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_S4)) {
+ /* enable vclk_div12 gate */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_CTRL,
+ VCLK_DIV12_EN, VCLK_DIV12_EN);
+
+ /* select vclk_div12 for HDMI-TX */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_HDMI_CLK_CTRL,
+ HDMI_TX_PIXEL_SEL_MASK, 4 << HDMI_TX_PIXEL_SEL_SHIFT);
+ regmap_update_bits(priv->clkctrl, CLKCTRL_HDMI_CLK_CTRL,
+ HDMI_TX_FE_SEL_MASK, 4 << HDMI_TX_FE_SEL_SHIFT);
+ } else {
+ /* enable vclk_div12 gate */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
+ VCLK_DIV12_EN, VCLK_DIV12_EN);
- /* select vclk_div12 for HDMI-TX */
- regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
- HDMI_TX_PIXEL_SEL_MASK, 4 << HDMI_TX_PIXEL_SEL_SHIFT);
+ /* select vclk_div12 for HDMI-TX */
+ regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
+ HDMI_TX_PIXEL_SEL_MASK, 4 << HDMI_TX_PIXEL_SEL_SHIFT);
+ }
break;
}
- regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_S4))
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_CTRL2,
+ HDMI_TX_PIXEL_EN, HDMI_TX_PIXEL_EN);
+ else
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
HDMI_TX_PIXEL_EN, HDMI_TX_PIXEL_EN);
/* Set ENCI/ENCP Source */
- switch (venc_div) {
- case 1:
- /* enable vclk_div1 gate */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
- VCLK_DIV1_EN, VCLK_DIV1_EN);
-
- if (hdmi_use_enci)
- /* select vclk_div1 for enci */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
- CTS_ENCI_SEL_MASK, 0);
- else
- /* select vclk_div1 for encp */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
- CTS_ENCP_SEL_MASK, 0);
- break;
- case 2:
- /* enable vclk_div2 gate */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
- VCLK_DIV2_EN, VCLK_DIV2_EN);
-
- if (hdmi_use_enci)
- /* select vclk_div2 for enci */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
- CTS_ENCI_SEL_MASK, 1 << CTS_ENCI_SEL_SHIFT);
- else
- /* select vclk_div2 for encp */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
- CTS_ENCP_SEL_MASK, 1 << CTS_ENCP_SEL_SHIFT);
- break;
- case 4:
- /* enable vclk_div4 gate */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
- VCLK_DIV4_EN, VCLK_DIV4_EN);
+ if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_S4)) {
+ switch (venc_div) {
+ case 1:
+ /* enable vclk_div1 gate */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_CTRL,
+ VCLK_DIV1_EN, VCLK_DIV1_EN);
+
+ if (hdmi_use_enci)
+ /* select vclk_div1 for enci */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_DIV,
+ CTS_ENCI_SEL_MASK, 0);
+ else
+ /* select vclk_div1 for encp */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_DIV,
+ CTS_ENCP_SEL_MASK, 0);
+ break;
+ case 2:
+ /* enable vclk_div2 gate */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_CTRL,
+ VCLK_DIV2_EN, VCLK_DIV2_EN);
+
+ if (hdmi_use_enci)
+ /* select vclk_div2 for enci */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_DIV,
+ CTS_ENCI_SEL_MASK, 1 << CTS_ENCI_SEL_SHIFT);
+ else
+ /* select vclk_div2 for encp */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_DIV,
+ CTS_ENCP_SEL_MASK, 1 << CTS_ENCP_SEL_SHIFT);
+ break;
+ case 4:
+ /* enable vclk_div4 gate */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_CTRL,
+ VCLK_DIV4_EN, VCLK_DIV4_EN);
+
+ if (hdmi_use_enci)
+ /* select vclk_div4 for enci */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_DIV,
+ CTS_ENCI_SEL_MASK, 2 << CTS_ENCI_SEL_SHIFT);
+ else
+ /* select vclk_div4 for encp */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_DIV,
+ CTS_ENCP_SEL_MASK, 2 << CTS_ENCP_SEL_SHIFT);
+ break;
+ case 6:
+ /* enable vclk_div6 gate */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_CTRL,
+ VCLK_DIV6_EN, VCLK_DIV6_EN);
+
+ if (hdmi_use_enci)
+ /* select vclk_div6 for enci */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_DIV,
+ CTS_ENCI_SEL_MASK, 3 << CTS_ENCI_SEL_SHIFT);
+ else
+ /* select vclk_div6 for encp */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_DIV,
+ CTS_ENCP_SEL_MASK, 3 << CTS_ENCP_SEL_SHIFT);
+ break;
+ case 12:
+ /* enable vclk_div12 gate */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_CTRL,
+ VCLK_DIV12_EN, VCLK_DIV12_EN);
+
+ if (hdmi_use_enci)
+ /* select vclk_div12 for enci */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_DIV,
+ CTS_ENCI_SEL_MASK, 4 << CTS_ENCI_SEL_SHIFT);
+ else
+ /* select vclk_div12 for encp */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_DIV,
+ CTS_ENCP_SEL_MASK, 4 << CTS_ENCP_SEL_SHIFT);
+ break;
+ }
if (hdmi_use_enci)
- /* select vclk_div4 for enci */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
- CTS_ENCI_SEL_MASK, 2 << CTS_ENCI_SEL_SHIFT);
+ /* Enable ENCI clock gate */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_CTRL2,
+ CTS_ENCI_EN, CTS_ENCI_EN);
else
- /* select vclk_div4 for encp */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
- CTS_ENCP_SEL_MASK, 2 << CTS_ENCP_SEL_SHIFT);
- break;
- case 6:
- /* enable vclk_div6 gate */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
- VCLK_DIV6_EN, VCLK_DIV6_EN);
+ /* Enable ENCP clock gate */
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_CTRL2,
+ CTS_ENCP_EN, CTS_ENCP_EN);
+
+ regmap_update_bits(priv->clkctrl, CLKCTRL_VID_CLK_CTRL, VCLK_EN, VCLK_EN);
+ } else {
+ switch (venc_div) {
+ case 1:
+ /* enable vclk_div1 gate */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
+ VCLK_DIV1_EN, VCLK_DIV1_EN);
+
+ if (hdmi_use_enci)
+ /* select vclk_div1 for enci */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
+ CTS_ENCI_SEL_MASK, 0);
+ else
+ /* select vclk_div1 for encp */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
+ CTS_ENCP_SEL_MASK, 0);
+ break;
+ case 2:
+ /* enable vclk_div2 gate */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
+ VCLK_DIV2_EN, VCLK_DIV2_EN);
+
+ if (hdmi_use_enci)
+ /* select vclk_div2 for enci */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
+ CTS_ENCI_SEL_MASK, 1 << CTS_ENCI_SEL_SHIFT);
+ else
+ /* select vclk_div2 for encp */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
+ CTS_ENCP_SEL_MASK, 1 << CTS_ENCP_SEL_SHIFT);
+ break;
+ case 4:
+ /* enable vclk_div4 gate */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
+ VCLK_DIV4_EN, VCLK_DIV4_EN);
+
+ if (hdmi_use_enci)
+ /* select vclk_div4 for enci */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
+ CTS_ENCI_SEL_MASK, 2 << CTS_ENCI_SEL_SHIFT);
+ else
+ /* select vclk_div4 for encp */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
+ CTS_ENCP_SEL_MASK, 2 << CTS_ENCP_SEL_SHIFT);
+ break;
+ case 6:
+ /* enable vclk_div6 gate */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
+ VCLK_DIV6_EN, VCLK_DIV6_EN);
+
+ if (hdmi_use_enci)
+ /* select vclk_div6 for enci */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
+ CTS_ENCI_SEL_MASK, 3 << CTS_ENCI_SEL_SHIFT);
+ else
+ /* select vclk_div6 for encp */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
+ CTS_ENCP_SEL_MASK, 3 << CTS_ENCP_SEL_SHIFT);
+ break;
+ case 12:
+ /* enable vclk_div12 gate */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
+ VCLK_DIV12_EN, VCLK_DIV12_EN);
+
+ if (hdmi_use_enci)
+ /* select vclk_div12 for enci */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
+ CTS_ENCI_SEL_MASK, 4 << CTS_ENCI_SEL_SHIFT);
+ else
+ /* select vclk_div12 for encp */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
+ CTS_ENCP_SEL_MASK, 4 << CTS_ENCP_SEL_SHIFT);
+ break;
+ }
if (hdmi_use_enci)
- /* select vclk_div6 for enci */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
- CTS_ENCI_SEL_MASK, 3 << CTS_ENCI_SEL_SHIFT);
+ /* Enable ENCI clock gate */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
+ CTS_ENCI_EN, CTS_ENCI_EN);
else
- /* select vclk_div6 for encp */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
- CTS_ENCP_SEL_MASK, 3 << CTS_ENCP_SEL_SHIFT);
- break;
- case 12:
- /* enable vclk_div12 gate */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
- VCLK_DIV12_EN, VCLK_DIV12_EN);
+ /* Enable ENCP clock gate */
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
+ CTS_ENCP_EN, CTS_ENCP_EN);
- if (hdmi_use_enci)
- /* select vclk_div12 for enci */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
- CTS_ENCI_SEL_MASK, 4 << CTS_ENCI_SEL_SHIFT);
- else
- /* select vclk_div12 for encp */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
- CTS_ENCP_SEL_MASK, 4 << CTS_ENCP_SEL_SHIFT);
- break;
+ regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL, VCLK_EN, VCLK_EN);
}
-
- if (hdmi_use_enci)
- /* Enable ENCI clock gate */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
- CTS_ENCI_EN, CTS_ENCI_EN);
- else
- /* Enable ENCP clock gate */
- regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
- CTS_ENCP_EN, CTS_ENCP_EN);
-
- regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL, VCLK_EN, VCLK_EN);
}
void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
--
2.43.0
Powered by blists - more mailing lists