On 11/6/20 1:00 PM, Lucas De Marchi wrote:
> DG1 uses 2 registers for the ddi clock mapping, with PHY A and B using
> DPCLKA_CFGCR0 and PHY C and D using DPCLKA1_CFGCR0. Hide this behind a
> single macro that chooses the correct register according to the phy
> being accessed, use the correct bitfields for each pll/phy and implement
> separate functions for DG1 since it doesn't share much with ICL/TGL
> anymore.
> 
> The previous values were correct for PHY A and B since they were using
> the same register as before and the bitfields were matching.
> 
> v2: Add comment and try to simplify DG1_DPCLKA* macros by reusing
> previous ones
> v3:
>   - Fix DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK() after wrong macro reuse
>   - Move phy -> id map to a separate macro (Aditya)
>   - Remove DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK where not required
>     (Aditya)
>   - Use drm_WARN_ON
> 
> Cc: José Roberto de Souza <jose.so...@intel.com>
> Cc: Clinton Taylor <clinton.a.tay...@intel.com>
> Cc: Matt Roper <matthew.d.ro...@intel.com>
> Cc: Aditya Swarup <aditya.swa...@intel.com>
> Signed-off-by: Lucas De Marchi <lucas.demar...@intel.com>

LGTM!
Reviewed-by: Aditya Swarup <aditya.swa...@intel.com>

> ---
>  drivers/gpu/drm/i915/display/intel_ddi.c     | 91 +++++++++++++++++++-
>  drivers/gpu/drm/i915/display/intel_display.c | 24 +++++-
>  drivers/gpu/drm/i915/i915_reg.h              | 24 ++++++
>  3 files changed, 135 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
> b/drivers/gpu/drm/i915/display/intel_ddi.c
> index 19b16517a502..36a4a1f4d775 100644
> --- a/drivers/gpu/drm/i915/display/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
> @@ -2970,6 +2970,40 @@ static u32 icl_dpclka_cfgcr0_clk_off(struct 
> drm_i915_private *dev_priv,
>       return 0;
>  }
>  
> +static void dg1_map_plls_to_ports(struct intel_encoder *encoder,
> +                               const struct intel_crtc_state *crtc_state)
> +{
> +     struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> +     struct intel_shared_dpll *pll = crtc_state->shared_dpll;
> +     enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
> +     u32 val;
> +
> +     /*
> +      * If we fail this, something went very wrong: first 2 PLLs should be
> +      * used by first 2 phys and last 2 PLLs by last phys
> +      */
> +     if (drm_WARN_ON(&dev_priv->drm,
> +                     (pll->info->id < DPLL_ID_DG1_DPLL2 && phy >= PHY_C) ||
> +                     (pll->info->id >= DPLL_ID_DG1_DPLL2 && phy < PHY_C)))
> +             return;
> +
> +     mutex_lock(&dev_priv->dpll.lock);
> +
> +     val = intel_de_read(dev_priv, DG1_DPCLKA_CFGCR0(phy));
> +     drm_WARN_ON(&dev_priv->drm,
> +                 (val & DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)) == 0);
> +
> +     val &= ~DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy);
> +     val |= DG1_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy);
> +     intel_de_write(dev_priv, DG1_DPCLKA_CFGCR0(phy), val);
> +     intel_de_posting_read(dev_priv, DG1_DPCLKA_CFGCR0(phy));
> +
> +     val &= ~DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy);
> +     intel_de_write(dev_priv, DG1_DPCLKA_CFGCR0(phy), val);
> +
> +     mutex_unlock(&dev_priv->dpll.lock);
> +}
> +
>  static void icl_map_plls_to_ports(struct intel_encoder *encoder,
>                                 const struct intel_crtc_state *crtc_state)
>  {
> @@ -3017,6 +3051,19 @@ static void icl_map_plls_to_ports(struct intel_encoder 
> *encoder,
>       mutex_unlock(&dev_priv->dpll.lock);
>  }
>  
> +static void dg1_unmap_plls_to_ports(struct intel_encoder *encoder)
> +{
> +     struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> +     enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
> +
> +     mutex_lock(&dev_priv->dpll.lock);
> +
> +     intel_de_rmw(dev_priv, DG1_DPCLKA_CFGCR0(phy), 0,
> +                  DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
> +
> +     mutex_unlock(&dev_priv->dpll.lock);
> +}
> +
>  static void icl_unmap_plls_to_ports(struct intel_encoder *encoder)
>  {
>       struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> @@ -3032,6 +3079,37 @@ static void icl_unmap_plls_to_ports(struct 
> intel_encoder *encoder)
>       mutex_unlock(&dev_priv->dpll.lock);
>  }
>  
> +static void dg1_sanitize_port_clk_off(struct drm_i915_private *dev_priv,
> +                                   u32 port_mask, bool ddi_clk_needed)
> +{
> +     enum port port;
> +     u32 val;
> +
> +     for_each_port_masked(port, port_mask) {
> +             enum phy phy = intel_port_to_phy(dev_priv, port);
> +             bool ddi_clk_off;
> +
> +             val = intel_de_read(dev_priv, DG1_DPCLKA_CFGCR0(phy));
> +             ddi_clk_off = val & DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy);
> +
> +             if (ddi_clk_needed == !ddi_clk_off)
> +                     continue;
> +
> +             /*
> +              * Punt on the case now where clock is gated, but it would
> +              * be needed by the port. Something else is really broken then.
> +              */
> +             if (drm_WARN_ON(&dev_priv->drm, ddi_clk_needed))
> +                     continue;
> +
> +             drm_notice(&dev_priv->drm,
> +                        "PHY %c is disabled with an ungated DDI clock, gate 
> it\n",
> +                        phy_name(phy));
> +             val |= DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy);
> +             intel_de_write(dev_priv, DG1_DPCLKA_CFGCR0(phy), val);
> +     }
> +}
> +
>  static void icl_sanitize_port_clk_off(struct drm_i915_private *dev_priv,
>                                     u32 port_mask, bool ddi_clk_needed)
>  {
> @@ -3114,7 +3192,10 @@ void icl_sanitize_encoder_pll_mapping(struct 
> intel_encoder *encoder)
>               ddi_clk_needed = false;
>       }
>  
> -     icl_sanitize_port_clk_off(dev_priv, port_mask, ddi_clk_needed);
> +     if (IS_DG1(dev_priv))
> +             dg1_sanitize_port_clk_off(dev_priv, port_mask, ddi_clk_needed);
> +     else
> +             icl_sanitize_port_clk_off(dev_priv, port_mask, ddi_clk_needed);
>  }
>  
>  static void intel_ddi_clk_select(struct intel_encoder *encoder,
> @@ -3666,7 +3747,9 @@ static void intel_ddi_pre_enable(struct 
> intel_atomic_state *state,
>  
>       drm_WARN_ON(&dev_priv->drm, crtc_state->has_pch_encoder);
>  
> -     if (INTEL_GEN(dev_priv) >= 11)
> +     if (IS_DG1(dev_priv))
> +             dg1_map_plls_to_ports(encoder, crtc_state);
> +     else if (INTEL_GEN(dev_priv) >= 11)
>               icl_map_plls_to_ports(encoder, crtc_state);
>  
>       intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
> @@ -3848,7 +3931,9 @@ static void intel_ddi_post_disable(struct 
> intel_atomic_state *state,
>               intel_ddi_post_disable_dp(state, encoder, old_crtc_state,
>                                         old_conn_state);
>  
> -     if (INTEL_GEN(dev_priv) >= 11)
> +     if (IS_DG1(dev_priv))
> +             dg1_unmap_plls_to_ports(encoder);
> +     else if (INTEL_GEN(dev_priv) >= 11)
>               icl_unmap_plls_to_ports(encoder);
>  
>       if (intel_crtc_has_dp_encoder(old_crtc_state) || is_tc_port)
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
> b/drivers/gpu/drm/i915/display/intel_display.c
> index 6faca1e739c8..2729c852c668 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -11003,6 +11003,26 @@ static int hsw_crtc_compute_clock(struct intel_crtc 
> *crtc,
>       return 0;
>  }
>  
> +static void dg1_get_ddi_pll(struct drm_i915_private *dev_priv, enum port 
> port,
> +                         struct intel_crtc_state *pipe_config)
> +{
> +     enum icl_port_dpll_id port_dpll_id = ICL_PORT_DPLL_DEFAULT;
> +     enum phy phy = intel_port_to_phy(dev_priv, port);
> +     enum intel_dpll_id id;
> +     u32 clk_sel;
> +
> +     clk_sel = intel_de_read(dev_priv, DG1_DPCLKA_CFGCR0(phy)) & 
> DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy);
> +     id = DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_DPLL_MAP(clk_sel, phy);
> +
> +     if (WARN_ON(id > DPLL_ID_DG1_DPLL3))
> +             return;
> +
> +     pipe_config->icl_port_dplls[port_dpll_id].pll =
> +             intel_get_shared_dpll_by_id(dev_priv, id);
> +
> +     icl_set_active_port_dpll(pipe_config, port_dpll_id);
> +}
> +
>  static void cnl_get_ddi_pll(struct drm_i915_private *dev_priv, enum port 
> port,
>                           struct intel_crtc_state *pipe_config)
>  {
> @@ -11311,7 +11331,9 @@ static void hsw_get_ddi_port_state(struct intel_crtc 
> *crtc,
>                       port = TRANS_DDI_FUNC_CTL_VAL_TO_PORT(tmp);
>       }
>  
> -     if (INTEL_GEN(dev_priv) >= 11)
> +     if (IS_DG1(dev_priv))
> +             dg1_get_ddi_pll(dev_priv, port, pipe_config);
> +     else if (INTEL_GEN(dev_priv) >= 11)
>               icl_get_ddi_pll(dev_priv, port, pipe_config);
>       else if (IS_CANNONLAKE(dev_priv))
>               cnl_get_ddi_pll(dev_priv, port, pipe_config);
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index bb0656875697..39664ba553ec 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -230,12 +230,14 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
>  #define _TRANS(tran, a, b)           _PICK_EVEN(tran, a, b)
>  #define _PORT(port, a, b)            _PICK_EVEN(port, a, b)
>  #define _PLL(pll, a, b)                      _PICK_EVEN(pll, a, b)
> +#define _PHY(phy, a, b)                      _PICK_EVEN(phy, a, b)
>  
>  #define _MMIO_PIPE(pipe, a, b)               _MMIO(_PIPE(pipe, a, b))
>  #define _MMIO_PLANE(plane, a, b)     _MMIO(_PLANE(plane, a, b))
>  #define _MMIO_TRANS(tran, a, b)              _MMIO(_TRANS(tran, a, b))
>  #define _MMIO_PORT(port, a, b)               _MMIO(_PORT(port, a, b))
>  #define _MMIO_PLL(pll, a, b)         _MMIO(_PLL(pll, a, b))
> +#define _MMIO_PHY(phy, a, b)         _MMIO(_PHY(phy, a, b))
>  
>  #define _PHY3(phy, ...)                      _PICK(phy, __VA_ARGS__)
>  
> @@ -10300,6 +10302,7 @@ enum skl_power_gate {
>  #define  DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port)        (3 << 
> DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port))
>  #define  DPCLKA_CFGCR0_DDI_CLK_SEL(pll, port)        ((pll) << 
> DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port))
>  
> +/* ICL Clocks */
>  #define ICL_DPCLKA_CFGCR0                    _MMIO(0x164280)
>  #define  ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)  (1 << _PICK(phy, 10, 11, 24))
>  #define  RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)  REG_BIT((phy) + 10)
> @@ -10315,6 +10318,27 @@ enum skl_power_gate {
>  #define  RKL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll, phy) \
>       ((pll) << RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy))
>  
> +/*
> + * DG1 Clocks
> + * First registers controls the first A and B, while the second register
> + * controls the phy C and D. The bits on these registers are the
> + * same, but refer to different phys
> + */
> +#define _DG1_DPCLKA_CFGCR0                           0x164280
> +#define _DG1_DPCLKA1_CFGCR0                          0x16C280
> +#define _DG1_DPCLKA_PHY_IDX(phy)                     ((phy) % 2)
> +#define _DG1_DPCLKA_PLL_IDX(pll)                     ((pll) % 2)
> +#define _DG1_PHY_DPLL_MAP(phy)                               ((phy) >= PHY_C 
> ? DPLL_ID_DG1_DPLL2 : DPLL_ID_DG1_DPLL0)
> +#define DG1_DPCLKA_CFGCR0(phy)                               _MMIO_PHY((phy) 
> / 2, \
> +                                                               
> _DG1_DPCLKA_CFGCR0, \
> +                                                               
> _DG1_DPCLKA1_CFGCR0)
> +#define   DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)         
> REG_BIT(_DG1_DPCLKA_PHY_IDX(phy) + 10)
> +#define   DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy)   
> (_DG1_DPCLKA_PHY_IDX(phy) * 2)
> +#define   DG1_DPCLKA_CFGCR0_DDI_CLK_SEL(pll, phy)    
> (_DG1_DPCLKA_PLL_IDX(pll) << DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy))
> +#define   DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy)    (0x3 << 
> DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy))
> +#define   DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_DPLL_MAP(clk_sel, phy) \
> +     (((clk_sel) >> DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy)) + 
> _DG1_PHY_DPLL_MAP(phy))
> +
>  /* CNL PLL */
>  #define DPLL0_ENABLE         0x46010
>  #define DPLL1_ENABLE         0x46014
> 

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to