[PATCH 09/11] drm/meson: Add G12A Video Clock setup
Jerome Brunet
jbrunet at baylibre.com
Tue Apr 9 08:46:56 UTC 2019
On Mon, 2019-03-25 at 15:18 +0100, Neil Armstrong wrote:
> While switching to the Common Clock Framework is still Work In Progress,
> this patch adds the corresponding G12A HDMI PLL setup to be on-par
> with the other SoCs support.
>
> The G12A has only a single tweak about the high frequency setup,
> where the HDMI PLL needs a specific setup to handle correctly the
> 5.94GHz DCO frequency.
>
> Apart that, it handle correctly all the other HDMI frequencies
> and can achieve even better DMT clock frequency precision with
> the larger fractional dividier width.
>
> Signed-off-by: Neil Armstrong <narmstrong at baylibre.com>
> ---
> drivers/gpu/drm/meson/meson_vclk.c | 119 ++++++++++++++++++++++++++---
> 1 file changed, 108 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c
> index c15a5a5df633..b39034745444 100644
> --- a/drivers/gpu/drm/meson/meson_vclk.c
> +++ b/drivers/gpu/drm/meson/meson_vclk.c
> @@ -113,9 +113,12 @@
> #define HHI_HDMI_PLL_CNTL4 0x32C /* 0xcb offset in data sheet */
> #define HHI_HDMI_PLL_CNTL5 0x330 /* 0xcc offset in data sheet */
> #define HHI_HDMI_PLL_CNTL6 0x334 /* 0xcd offset in data sheet */
> +#define HHI_HDMI_PLL_CNTL7 0x338 /* 0xce offset in data sheet */
>
> #define HDMI_PLL_RESET BIT(28)
> +#define HDMI_PLL_RESET_G12A BIT(29)
> #define HDMI_PLL_LOCK BIT(31)
> +#define HDMI_PLL_LOCK_G12A (3 << 30)
GENMASK(31, 30) ?
>
> #define FREQ_1000_1001(_freq) DIV_ROUND_CLOSEST(_freq * 1000, 1001)
>
> @@ -257,6 +260,10 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
> 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, 0x4800023d);
> +
> + /* 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, "amlogic,meson-gxm-vpu") ||
> meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
> regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4000027b);
> @@ -271,11 +278,26 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
> 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);
> + /* 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, "amlogic,meson-g12a-vpu")) {
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x1a0504f7);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00010000);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x00000000);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x6a28dc00);
> + 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, 0x56540000);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x3a0504f7);
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x1a0504f7);
> +
> + /* Poll for lock bit */
> + regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
> + ((val & HDMI_PLL_LOCK_G12A) == HDMI_PLL_LOCK_G12A),
> + 10, 0);
> + }
>
> /* Disable VCLK2 */
> regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, 0);
> @@ -288,8 +310,13 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
> VCLK2_DIV_MASK, (55 - 1));
>
> /* select vid_pll for vclk2 */
> - regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
> - VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
> + if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
> + 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);
>
> @@ -476,32 +503,80 @@ void meson_hdmi_pll_set_params(struct meson_drm *priv, unsigned int m,
> /* 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, "amlogic,meson-g12a-vpu")) {
> + regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x0b3a0400 | m);
> +
> + /* Enable and reset */
> + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
> + 0x3 << 28, 0x3 << 28);
Could you use define of the enable and reset bit instead of 0x3 << 28 ?
> +
> + 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) {
> + 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);
> + } 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);
> + }
> +
> + 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);
> }
>
> if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
> regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
> 3 << 16, pll_od_to_reg(od1) << 16);
> else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
> - meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
> + meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
> regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
> 3 << 21, pll_od_to_reg(od1) << 21);
> + else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
> + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
> + 3 << 16, pll_od_to_reg(od1) << 16);
>
> if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
> regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
> 3 << 22, pll_od_to_reg(od2) << 22);
> else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
> - meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
> + meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
> regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
> 3 << 23, pll_od_to_reg(od2) << 23);
> + else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
> + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
> + 3 << 18, pll_od_to_reg(od2) << 18);
>
> if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
> regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
> 3 << 18, pll_od_to_reg(od3) << 18);
> else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
> - meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
> + meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
> regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
> 3 << 19, pll_od_to_reg(od3) << 19);
> -
> + else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
> + regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
> + 3 << 20, pll_od_to_reg(od3) << 20);
Could you remove the constants above and define the shift and mask of the ODs
?
> }
>
> #define XTAL_FREQ 24000
> @@ -518,6 +593,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
>
> static unsigned int meson_hdmi_pll_get_frac(struct meson_drm *priv,
> unsigned int m,
> @@ -534,6 +610,9 @@ static unsigned int meson_hdmi_pll_get_frac(struct meson_drm *priv,
> parent_freq *= 2;
> }
>
> + if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
> + frac_max = HDMI_FRAC_MAX_G12A;
> +
> /* We can have a perfect match !*/
> if (pll_freq / m == parent_freq &&
> pll_freq % m == 0)
> @@ -559,7 +638,8 @@ static bool meson_hdmi_pll_validate_params(struct meson_drm *priv,
> if (frac >= HDMI_FRAC_MAX_GXBB)
> return false;
> } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
> - meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
> + meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu") ||
> + meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
> /* Empiric supported min/max dividers */
> if (m < 106 || m > 247)
> return false;
> @@ -713,6 +793,23 @@ 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, "amlogic,meson-g12a-vpu")) {
> + 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);
> }
>
More information about the dri-devel
mailing list