On 28/04/2020 11:21, Neil Armstrong wrote:
> The Amlogic S805X/Y uses the same die as the S905X, but with more
> limited graphics capabilities.
> 
> This adds a soc version detection adding specific limitations on the HDMI
> mode selections.
> 
> Here, we limit to HDMI 1.3a max HDMI PHY clock frequency.
> 
> Changes sinces v1:
> - Moved frequency check in the vclk code, and also checks DMT modes
> 
> Signed-off-by: Neil Armstrong <narmstr...@baylibre.com>
> ---
>  drivers/gpu/drm/meson/meson_drv.c     | 29 ++++++++++++++++++++++++++-
>  drivers/gpu/drm/meson/meson_drv.h     |  6 ++++++
>  drivers/gpu/drm/meson/meson_dw_hdmi.c |  2 +-
>  drivers/gpu/drm/meson/meson_vclk.c    | 16 ++++++++++++++-
>  drivers/gpu/drm/meson/meson_vclk.h    |  3 ++-
>  5 files changed, 52 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/meson/meson_drv.c 
> b/drivers/gpu/drm/meson/meson_drv.c
> index 6f29fab79952..621f6de0f076 100644
> --- a/drivers/gpu/drm/meson/meson_drv.c
> +++ b/drivers/gpu/drm/meson/meson_drv.c
> @@ -11,6 +11,7 @@
>  #include <linux/component.h>
>  #include <linux/module.h>
>  #include <linux/of_graph.h>
> +#include <linux/sys_soc.h>
>  #include <linux/platform_device.h>
>  #include <linux/soc/amlogic/meson-canvas.h>
>  
> @@ -183,6 +184,24 @@ static void meson_remove_framebuffers(void)
>       kfree(ap);
>  }
>  
> +struct meson_drm_soc_attr {
> +     struct meson_drm_soc_limits limits;
> +     const struct soc_device_attribute *attrs;
> +};
> +
> +static const struct meson_drm_soc_attr meson_drm_soc_attrs[] = {
> +     /* S805X/S805Y HDMI PLL won't lock for HDMI PHY freq > 1,65GHz */
> +     {
> +             .limits = {
> +                     .max_hdmi_phy_freq = 1650000,
> +             },
> +             .attrs = (const struct soc_device_attribute []) {
> +                     { .soc_id = "GXL (S805*)", },
> +                     { /* sentinel */ },
> +             }
> +     },
> +};
> +
>  static int meson_drv_bind_master(struct device *dev, bool has_components)
>  {
>       struct platform_device *pdev = to_platform_device(dev);
> @@ -191,7 +210,7 @@ static int meson_drv_bind_master(struct device *dev, bool 
> has_components)
>       struct drm_device *drm;
>       struct resource *res;
>       void __iomem *regs;
> -     int ret;
> +     int ret, i;
>  
>       /* Checks if an output connector is available */
>       if (!meson_vpu_has_available_connectors(dev)) {
> @@ -281,6 +300,14 @@ static int meson_drv_bind_master(struct device *dev, 
> bool has_components)
>       if (ret)
>               goto free_drm;
>  
> +     /* Assign limits per soc revision/package */
> +     for (i = 0 ; i < ARRAY_SIZE(meson_drm_soc_attrs) ; ++i) {
> +             if (soc_device_match(meson_drm_soc_attrs[i].attrs)) {
> +                     priv->limits = &meson_drm_soc_attrs[i].limits;
> +                     break;
> +             }
> +     }
> +
>       /* Remove early framebuffers (ie. simplefb) */
>       meson_remove_framebuffers();
>  
> diff --git a/drivers/gpu/drm/meson/meson_drv.h 
> b/drivers/gpu/drm/meson/meson_drv.h
> index 04fdf3826643..5b23704a80d6 100644
> --- a/drivers/gpu/drm/meson/meson_drv.h
> +++ b/drivers/gpu/drm/meson/meson_drv.h
> @@ -30,6 +30,10 @@ struct meson_drm_match_data {
>       struct meson_afbcd_ops *afbcd_ops;
>  };
>  
> +struct meson_drm_soc_limits {
> +     unsigned int max_hdmi_phy_freq;
> +};
> +
>  struct meson_drm {
>       struct device *dev;
>       enum vpu_compatible compat;
> @@ -48,6 +52,8 @@ struct meson_drm {
>       struct drm_plane *primary_plane;
>       struct drm_plane *overlay_plane;
>  
> +     const struct meson_drm_soc_limits *limits;
> +
>       /* Components Data */
>       struct {
>               bool osd1_enabled;
> diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c 
> b/drivers/gpu/drm/meson/meson_dw_hdmi.c
> index e8c94915a4fc..5be963e9db05 100644
> --- a/drivers/gpu/drm/meson/meson_dw_hdmi.c
> +++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c
> @@ -695,7 +695,7 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
>       dev_dbg(connector->dev->dev, "%s: vclk:%d phy=%d venc=%d hdmi=%d\n",
>               __func__, phy_freq, vclk_freq, venc_freq, hdmi_freq);
>  
> -     return meson_vclk_vic_supported_freq(phy_freq, vclk_freq);
> +     return meson_vclk_vic_supported_freq(priv, phy_freq, vclk_freq);
>  }
>  
>  /* Encoder */
> diff --git a/drivers/gpu/drm/meson/meson_vclk.c 
> b/drivers/gpu/drm/meson/meson_vclk.c
> index fdf26dac9fa8..0eb86943a358 100644
> --- a/drivers/gpu/drm/meson/meson_vclk.c
> +++ b/drivers/gpu/drm/meson/meson_vclk.c
> @@ -725,6 +725,13 @@ meson_vclk_dmt_supported_freq(struct meson_drm *priv, 
> unsigned int freq)
>       /* In DMT mode, path after PLL is always /10 */
>       freq *= 10;
>  
> +     /* Check against soc revision/package limits */
> +     if (priv->limits) {
> +             if (priv->limits->max_hdmi_phy_freq &&
> +                 freq > priv->limits->max_hdmi_phy_freq)
> +                     return MODE_CLOCK_HIGH;
> +     }
> +
>       if (meson_hdmi_pll_find_params(priv, freq, &m, &frac, &od))
>               return MODE_OK;
>  
> @@ -762,7 +769,7 @@ static void meson_hdmi_pll_generic_set(struct meson_drm 
> *priv,
>  }
>  
>  enum drm_mode_status
> -meson_vclk_vic_supported_freq(unsigned int phy_freq,
> +meson_vclk_vic_supported_freq(struct meson_drm *priv, unsigned int phy_freq,
>                             unsigned int vclk_freq)
>  {
>       int i;
> @@ -770,6 +777,13 @@ meson_vclk_vic_supported_freq(unsigned int phy_freq,
>       DRM_DEBUG_DRIVER("phy_freq = %d vclk_freq = %d\n",
>                        phy_freq, vclk_freq);
>  
> +     /* Check against soc revision/package limits */
> +     if (priv->limits) {
> +             if (priv->limits->max_hdmi_phy_freq &&
> +                 phy_freq > priv->limits->max_hdmi_phy_freq)
> +                     return MODE_CLOCK_HIGH;
> +     }
> +
>       for (i = 0 ; params[i].pixel_freq ; ++i) {
>               DRM_DEBUG_DRIVER("i = %d pixel_freq = %d alt = %d\n",
>                                i, params[i].pixel_freq,
> diff --git a/drivers/gpu/drm/meson/meson_vclk.h 
> b/drivers/gpu/drm/meson/meson_vclk.h
> index aed0ab2efa71..60617aaf18dd 100644
> --- a/drivers/gpu/drm/meson/meson_vclk.h
> +++ b/drivers/gpu/drm/meson/meson_vclk.h
> @@ -25,7 +25,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 phy_freq, unsigned int vclk_freq);
> +meson_vclk_vic_supported_freq(struct meson_drm *priv, unsigned int phy_freq,
> +                           unsigned int vclk_freq);
>  
>  void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
>                     unsigned int phy_freq, unsigned int vclk_freq,
> 

Applied to drm-misc-next with commit log fixup
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to