drm/i915/gen11: Program ICL_DPCLKA_CFGCR0 according to PHY
authorMatt Roper <matthew.d.roper@intel.com>
Tue, 9 Jul 2019 18:39:31 +0000 (11:39 -0700)
committerMatt Roper <matthew.d.roper@intel.com>
Thu, 11 Jul 2019 01:22:26 +0000 (18:22 -0700)
Although the register name implies that it operates on DDI's,
DPCLKA_CFGCR0_ICL actually needs to be programmed according to the PHY
that's in use.  I.e., when using EHL's DDI-D on combo PHY A, the bits
described as "port A" in the bspec are what we need to set.  The bspec
clarifies:

        "[For EHL] DDID clock tied to DDIA clock, so DPCLKA_CFGCR0 DDIA
        Clock Select chooses the PLL for both DDIA and DDID and drives
        port A in all cases."

Also, since the CNL DPCLKA_CFGCR0 bit defines are still port-based, we
create separate ICL-specific defines that accept the PHY rather than
trying to share the same bit definitions between CNL and ICL.

v5: Make icl_dpclka_cfgcr0_clk_off() take phy rather than port.  When
    splitting the original patch the hunk to handle this wound up too
    late in the series.  (Sparse)

v6: Since we're already changing this code,
    s/DPCLKA_CFGCR0_ICL/ICL_DPCLKA_CFGCR0/ for consistency.  (Jose)

Bspec: 33148
Cc: José Roberto de Souza <jose.souza@intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: José Roberto de Souza <jose.souza@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190709183934.445-3-matthew.d.roper@intel.com
drivers/gpu/drm/i915/display/icl_dsi.c
drivers/gpu/drm/i915/display/intel_ddi.c
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/i915_reg.h

index 3cf95c34143cd4d6b2fd91567180ccf0bb339fa8..8f1324c2f5393e49ed588285dd5b83f5ba5a0446 100644 (file)
@@ -560,14 +560,16 @@ static void gen11_dsi_gate_clocks(struct intel_encoder *encoder)
        struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
        u32 tmp;
        enum port port;
+       enum phy phy;
 
        mutex_lock(&dev_priv->dpll_lock);
-       tmp = I915_READ(DPCLKA_CFGCR0_ICL);
+       tmp = I915_READ(ICL_DPCLKA_CFGCR0);
        for_each_dsi_port(port, intel_dsi->ports) {
-               tmp |= DPCLKA_CFGCR0_DDI_CLK_OFF(port);
+               phy = intel_port_to_phy(dev_priv, port);
+               tmp |= ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy);
        }
 
-       I915_WRITE(DPCLKA_CFGCR0_ICL, tmp);
+       I915_WRITE(ICL_DPCLKA_CFGCR0, tmp);
        mutex_unlock(&dev_priv->dpll_lock);
 }
 
@@ -577,14 +579,16 @@ static void gen11_dsi_ungate_clocks(struct intel_encoder *encoder)
        struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
        u32 tmp;
        enum port port;
+       enum phy phy;
 
        mutex_lock(&dev_priv->dpll_lock);
-       tmp = I915_READ(DPCLKA_CFGCR0_ICL);
+       tmp = I915_READ(ICL_DPCLKA_CFGCR0);
        for_each_dsi_port(port, intel_dsi->ports) {
-               tmp &= ~DPCLKA_CFGCR0_DDI_CLK_OFF(port);
+               phy = intel_port_to_phy(dev_priv, port);
+               tmp &= ~ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy);
        }
 
-       I915_WRITE(DPCLKA_CFGCR0_ICL, tmp);
+       I915_WRITE(ICL_DPCLKA_CFGCR0, tmp);
        mutex_unlock(&dev_priv->dpll_lock);
 }
 
@@ -595,23 +599,26 @@ static void gen11_dsi_map_pll(struct intel_encoder *encoder,
        struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
        struct intel_shared_dpll *pll = crtc_state->shared_dpll;
        enum port port;
+       enum phy phy;
        u32 val;
 
        mutex_lock(&dev_priv->dpll_lock);
 
-       val = I915_READ(DPCLKA_CFGCR0_ICL);
+       val = I915_READ(ICL_DPCLKA_CFGCR0);
        for_each_dsi_port(port, intel_dsi->ports) {
-               val &= ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
-               val |= DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, port);
+               phy = intel_port_to_phy(dev_priv, port);
+               val &= ~ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy);
+               val |= ICL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy);
        }
-       I915_WRITE(DPCLKA_CFGCR0_ICL, val);
+       I915_WRITE(ICL_DPCLKA_CFGCR0, val);
 
        for_each_dsi_port(port, intel_dsi->ports) {
-               val &= ~DPCLKA_CFGCR0_DDI_CLK_OFF(port);
+               phy = intel_port_to_phy(dev_priv, port);
+               val &= ~ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy);
        }
-       I915_WRITE(DPCLKA_CFGCR0_ICL, val);
+       I915_WRITE(ICL_DPCLKA_CFGCR0, val);
 
-       POSTING_READ(DPCLKA_CFGCR0_ICL);
+       POSTING_READ(ICL_DPCLKA_CFGCR0);
 
        mutex_unlock(&dev_priv->dpll_lock);
 }
index ad638e7f27bbbd9756648bde780d27e5b037b011..e5b55b4928bbc1aa09302c57af76f1ceb76bdf40 100644 (file)
@@ -2729,12 +2729,13 @@ u32 ddi_signal_levels(struct intel_dp *intel_dp)
 
 static inline
 u32 icl_dpclka_cfgcr0_clk_off(struct drm_i915_private *dev_priv,
-                             enum port port)
+                             enum phy phy)
 {
-       if (intel_port_is_combophy(dev_priv, port)) {
-               return ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(port);
-       } else if (intel_port_is_tc(dev_priv, port)) {
-               enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
+       if (intel_phy_is_combo(dev_priv, phy)) {
+               return ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy);
+       } else if (intel_phy_is_tc(dev_priv, phy)) {
+               enum tc_port tc_port = intel_port_to_tc(dev_priv,
+                                                       (enum port)phy);
 
                return ICL_DPCLKA_CFGCR0_TC_CLK_OFF(tc_port);
        }
@@ -2747,23 +2748,33 @@ static void icl_map_plls_to_ports(struct intel_encoder *encoder,
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct intel_shared_dpll *pll = crtc_state->shared_dpll;
-       enum port port = encoder->port;
+       enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
        u32 val;
 
        mutex_lock(&dev_priv->dpll_lock);
 
-       val = I915_READ(DPCLKA_CFGCR0_ICL);
-       WARN_ON((val & icl_dpclka_cfgcr0_clk_off(dev_priv, port)) == 0);
+       val = I915_READ(ICL_DPCLKA_CFGCR0);
+       WARN_ON((val & icl_dpclka_cfgcr0_clk_off(dev_priv, phy)) == 0);
 
-       if (intel_port_is_combophy(dev_priv, port)) {
-               val &= ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
-               val |= DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, port);
-               I915_WRITE(DPCLKA_CFGCR0_ICL, val);
-               POSTING_READ(DPCLKA_CFGCR0_ICL);
+       if (intel_phy_is_combo(dev_priv, phy)) {
+               /*
+                * Even though this register references DDIs, note that we
+                * want to pass the PHY rather than the port (DDI).  For
+                * ICL, port=phy in all cases so it doesn't matter, but for
+                * EHL the bspec notes the following:
+                *
+                *   "DDID clock tied to DDIA clock, so DPCLKA_CFGCR0 DDIA
+                *   Clock Select chooses the PLL for both DDIA and DDID and
+                *   drives port A in all cases."
+                */
+               val &= ~ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy);
+               val |= ICL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy);
+               I915_WRITE(ICL_DPCLKA_CFGCR0, val);
+               POSTING_READ(ICL_DPCLKA_CFGCR0);
        }
 
-       val &= ~icl_dpclka_cfgcr0_clk_off(dev_priv, port);
-       I915_WRITE(DPCLKA_CFGCR0_ICL, val);
+       val &= ~icl_dpclka_cfgcr0_clk_off(dev_priv, phy);
+       I915_WRITE(ICL_DPCLKA_CFGCR0, val);
 
        mutex_unlock(&dev_priv->dpll_lock);
 }
@@ -2771,14 +2782,14 @@ static void icl_map_plls_to_ports(struct intel_encoder *encoder,
 static void icl_unmap_plls_to_ports(struct intel_encoder *encoder)
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
-       enum port port = encoder->port;
+       enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
        u32 val;
 
        mutex_lock(&dev_priv->dpll_lock);
 
-       val = I915_READ(DPCLKA_CFGCR0_ICL);
-       val |= icl_dpclka_cfgcr0_clk_off(dev_priv, port);
-       I915_WRITE(DPCLKA_CFGCR0_ICL, val);
+       val = I915_READ(ICL_DPCLKA_CFGCR0);
+       val |= icl_dpclka_cfgcr0_clk_off(dev_priv, phy);
+       I915_WRITE(ICL_DPCLKA_CFGCR0, val);
 
        mutex_unlock(&dev_priv->dpll_lock);
 }
@@ -2836,11 +2847,13 @@ void icl_sanitize_encoder_pll_mapping(struct intel_encoder *encoder)
                ddi_clk_needed = false;
        }
 
-       val = I915_READ(DPCLKA_CFGCR0_ICL);
+       val = I915_READ(ICL_DPCLKA_CFGCR0);
        for_each_port_masked(port, port_mask) {
+               enum phy phy = intel_port_to_phy(dev_priv, port);
+
                bool ddi_clk_ungated = !(val &
                                         icl_dpclka_cfgcr0_clk_off(dev_priv,
-                                                                  port));
+                                                                  phy));
 
                if (ddi_clk_needed == ddi_clk_ungated)
                        continue;
@@ -2852,10 +2865,10 @@ void icl_sanitize_encoder_pll_mapping(struct intel_encoder *encoder)
                if (WARN_ON(ddi_clk_needed))
                        continue;
 
-               DRM_NOTE("Port %c is disabled/in DSI mode with an ungated DDI clock, gate it\n",
-                        port_name(port));
-               val |= icl_dpclka_cfgcr0_clk_off(dev_priv, port);
-               I915_WRITE(DPCLKA_CFGCR0_ICL, val);
+               DRM_NOTE("PHY %c is disabled/in DSI mode with an ungated DDI clock, gate it\n",
+                        phy_name(port));
+               val |= icl_dpclka_cfgcr0_clk_off(dev_priv, phy);
+               I915_WRITE(ICL_DPCLKA_CFGCR0, val);
        }
 }
 
index 43caee6d3c2feda1e77d6be46fff4feb6f4c7908..44c79f8bd028d9977c0376f2c016a268a47e6467 100644 (file)
@@ -10096,7 +10096,7 @@ static void icelake_get_ddi_pll(struct drm_i915_private *dev_priv,
        u32 temp;
 
        if (intel_port_is_combophy(dev_priv, port)) {
-               temp = I915_READ(DPCLKA_CFGCR0_ICL) &
+               temp = I915_READ(ICL_DPCLKA_CFGCR0) &
                       DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
                id = temp >> DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port);
                port_dpll_id = ICL_PORT_DPLL_DEFAULT;
index 5898f59e3dd7aa35799bdc51ec981e1e913855ab..d3fc575a94db5f1136c4554dce3e9960c545b7df 100644 (file)
@@ -9697,17 +9697,21 @@ enum skl_power_gate {
  * CNL Clocks
  */
 #define DPCLKA_CFGCR0                          _MMIO(0x6C200)
-#define DPCLKA_CFGCR0_ICL                      _MMIO(0x164280)
 #define  DPCLKA_CFGCR0_DDI_CLK_OFF(port)       (1 << ((port) ==  PORT_F ? 23 : \
                                                      (port) + 10))
-#define  ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(port)   (1 << ((port) + 10))
-#define  ICL_DPCLKA_CFGCR0_TC_CLK_OFF(tc_port) (1 << ((tc_port) == PORT_TC4 ? \
-                                                     21 : (tc_port) + 12))
 #define  DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port) ((port) == PORT_F ? 21 : \
                                                (port) * 2)
 #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))
 
+#define ICL_DPCLKA_CFGCR0                      _MMIO(0x164280)
+#define  ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)    (1 << _PICK(phy, 10, 11, 24))
+#define  ICL_DPCLKA_CFGCR0_TC_CLK_OFF(tc_port) (1 << ((tc_port) == PORT_TC4 ? \
+                                                     21 : (tc_port) + 12))
+#define  ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy)      ((phy) * 2)
+#define  ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy)       (3 << ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy))
+#define  ICL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll, phy)       ((pll) << ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy))
+
 /* CNL PLL */
 #define DPLL0_ENABLE           0x46010
 #define DPLL1_ENABLE           0x46014