]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/commitdiff
drm/i915/icl: add basic support for the ICL clocks
authorPaulo Zanoni <paulo.r.zanoni@intel.com>
Fri, 27 Apr 2018 23:14:36 +0000 (16:14 -0700)
committerPaulo Zanoni <paulo.r.zanoni@intel.com>
Mon, 7 May 2018 23:42:47 +0000 (16:42 -0700)
This commit introduces the definitions for the ICL clocks and adds the
basic functions to the shared DPLL framework. It adds code for the
Enable and Disable sequences for some PLLs, but it does not have the
code to compute the actual PLL values, which are marked as TODO
comments and should be introduced as separate commits.

Special thanks to James Ausmus for investigating and fixing a bug with
the placement of icl_unmap_plls_to_ports() function.

v2:
 - Rebase around dpll_lock changes.
v3:
 - The spec now says what the timeouts should be.
 - Touch DPCLKA_CFGCR0_ICL at the appropriate time so we don't freeze
   the machine.
 - Checkpatch found a white space problem.
 - Small adjustments before upstreaming.
v4:
 - Move the ICL checks out of the *map_plls_to_ports() functions
  (James)
 - Add extra encoder check (James)
 - Call icl_unmap_plls_to_ports() later (James)
v5:
 - Rebase after the pll struct changes.
v6:
 - Properly make the unmap function based on encoders_post_disable()
   with regarding to checks and iterators.
 - Address checkpatch comment on "min = max = x()".

Cc: James Ausmus <james.ausmus@intel.com>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: James Ausmus <james.ausmus@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180427231436.9353-1-paulo.r.zanoni@intel.com
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dpll_mgr.c
drivers/gpu/drm/i915/intel_dpll_mgr.h
drivers/gpu/drm/i915/intel_drv.h

index 85911bc0b7036062242efb7045dbb45b0e1c8200..13e7b9e4a6e6ffa7f15aa4e9740df9ffd3b68737 100644 (file)
@@ -3368,6 +3368,28 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused)
                seq_printf(m, " fp0:     0x%08x\n", pll->state.hw_state.fp0);
                seq_printf(m, " fp1:     0x%08x\n", pll->state.hw_state.fp1);
                seq_printf(m, " wrpll:   0x%08x\n", pll->state.hw_state.wrpll);
+               seq_printf(m, " cfgcr0:  0x%08x\n", pll->state.hw_state.cfgcr0);
+               seq_printf(m, " cfgcr1:  0x%08x\n", pll->state.hw_state.cfgcr1);
+               seq_printf(m, " mg_refclkin_ctl:        0x%08x\n",
+                          pll->state.hw_state.mg_refclkin_ctl);
+               seq_printf(m, " mg_clktop2_coreclkctl1: 0x%08x\n",
+                          pll->state.hw_state.mg_clktop2_coreclkctl1);
+               seq_printf(m, " mg_clktop2_hsclkctl:    0x%08x\n",
+                          pll->state.hw_state.mg_clktop2_hsclkctl);
+               seq_printf(m, " mg_pll_div0:  0x%08x\n",
+                          pll->state.hw_state.mg_pll_div0);
+               seq_printf(m, " mg_pll_div1:  0x%08x\n",
+                          pll->state.hw_state.mg_pll_div1);
+               seq_printf(m, " mg_pll_lf:    0x%08x\n",
+                          pll->state.hw_state.mg_pll_lf);
+               seq_printf(m, " mg_pll_frac_lock: 0x%08x\n",
+                          pll->state.hw_state.mg_pll_frac_lock);
+               seq_printf(m, " mg_pll_ssc:   0x%08x\n",
+                          pll->state.hw_state.mg_pll_ssc);
+               seq_printf(m, " mg_pll_bias:  0x%08x\n",
+                          pll->state.hw_state.mg_pll_bias);
+               seq_printf(m, " mg_pll_tdc_coldst_bias: 0x%08x\n",
+                          pll->state.hw_state.mg_pll_tdc_coldst_bias);
        }
        drm_modeset_unlock_all(dev);
 
index 8225d223f4523a05af8af7cbea4ee17bd815600f..b98ac0541f190271b71bbd9cdd7b6c690419bf2a 100644 (file)
@@ -1052,6 +1052,25 @@ static uint32_t hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)
        }
 }
 
+static uint32_t icl_pll_to_ddi_pll_sel(struct intel_encoder *encoder,
+                                      const struct intel_shared_dpll *pll)
+{
+       const enum intel_dpll_id id = pll->info->id;
+
+       switch (id) {
+       default:
+               MISSING_CASE(id);
+       case DPLL_ID_ICL_DPLL0:
+       case DPLL_ID_ICL_DPLL1:
+               return DDI_CLK_SEL_NONE;
+       case DPLL_ID_ICL_MGPLL1:
+       case DPLL_ID_ICL_MGPLL2:
+       case DPLL_ID_ICL_MGPLL3:
+       case DPLL_ID_ICL_MGPLL4:
+               return DDI_CLK_SEL_MG;
+       }
+}
+
 /* Starting with Haswell, different DDI ports can work in FDI mode for
  * connection to the PCH-located connectors. For this, it is necessary to train
  * both the DDI port and PCH receiver for the desired DDI buffer settings.
@@ -2421,6 +2440,69 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp)
        return DDI_BUF_TRANS_SELECT(level);
 }
 
+void icl_map_plls_to_ports(struct drm_crtc *crtc,
+                          struct intel_crtc_state *crtc_state,
+                          struct drm_atomic_state *old_state)
+{
+       struct intel_shared_dpll *pll = crtc_state->shared_dpll;
+       struct drm_i915_private *dev_priv = to_i915(crtc->dev);
+       struct drm_connector_state *conn_state;
+       struct drm_connector *conn;
+       int i;
+
+       for_each_new_connector_in_state(old_state, conn, conn_state, i) {
+               struct intel_encoder *encoder =
+                       to_intel_encoder(conn_state->best_encoder);
+               enum port port = encoder->port;
+               uint32_t val;
+
+               if (conn_state->crtc != crtc)
+                       continue;
+
+               mutex_lock(&dev_priv->dpll_lock);
+
+               val = I915_READ(DPCLKA_CFGCR0_ICL);
+               WARN_ON((val & DPCLKA_CFGCR0_DDI_CLK_OFF(port)) == 0);
+
+               if (port == PORT_A || port == PORT_B) {
+                       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);
+               }
+
+               val &= ~DPCLKA_CFGCR0_DDI_CLK_OFF(port);
+               I915_WRITE(DPCLKA_CFGCR0_ICL, val);
+
+               mutex_unlock(&dev_priv->dpll_lock);
+       }
+}
+
+void icl_unmap_plls_to_ports(struct drm_crtc *crtc,
+                            struct intel_crtc_state *crtc_state,
+                            struct drm_atomic_state *old_state)
+{
+       struct drm_i915_private *dev_priv = to_i915(crtc->dev);
+       struct drm_connector_state *old_conn_state;
+       struct drm_connector *conn;
+       int i;
+
+       for_each_old_connector_in_state(old_state, conn, old_conn_state, i) {
+               struct intel_encoder *encoder =
+                       to_intel_encoder(old_conn_state->best_encoder);
+               enum port port = encoder->port;
+
+               if (old_conn_state->crtc != crtc)
+                       continue;
+
+               mutex_lock(&dev_priv->dpll_lock);
+               I915_WRITE(DPCLKA_CFGCR0_ICL,
+                          I915_READ(DPCLKA_CFGCR0_ICL) |
+                          DPCLKA_CFGCR0_DDI_CLK_OFF(port));
+               mutex_unlock(&dev_priv->dpll_lock);
+       }
+}
+
 static void intel_ddi_clk_select(struct intel_encoder *encoder,
                                 const struct intel_shared_dpll *pll)
 {
@@ -2433,7 +2515,11 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder,
 
        mutex_lock(&dev_priv->dpll_lock);
 
-       if (IS_CANNONLAKE(dev_priv)) {
+       if (IS_ICELAKE(dev_priv)) {
+               if (port >= PORT_C)
+                       I915_WRITE(DDI_CLK_SEL(port),
+                                  icl_pll_to_ddi_pll_sel(encoder, pll));
+       } else if (IS_CANNONLAKE(dev_priv)) {
                /* Configure DPCLKA_CFGCR0 to map the DPLL to the DDI. */
                val = I915_READ(DPCLKA_CFGCR0);
                val &= ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
@@ -2471,14 +2557,18 @@ static void intel_ddi_clk_disable(struct intel_encoder *encoder)
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        enum port port = encoder->port;
 
-       if (IS_CANNONLAKE(dev_priv))
+       if (IS_ICELAKE(dev_priv)) {
+               if (port >= PORT_C)
+                       I915_WRITE(DDI_CLK_SEL(port), DDI_CLK_SEL_NONE);
+       } else if (IS_CANNONLAKE(dev_priv)) {
                I915_WRITE(DPCLKA_CFGCR0, I915_READ(DPCLKA_CFGCR0) |
                           DPCLKA_CFGCR0_DDI_CLK_OFF(port));
-       else if (IS_GEN9_BC(dev_priv))
+       } else if (IS_GEN9_BC(dev_priv)) {
                I915_WRITE(DPLL_CTRL2, I915_READ(DPLL_CTRL2) |
                           DPLL_CTRL2_DDI_CLK_OFF(port));
-       else if (INTEL_GEN(dev_priv) < 9)
+       } else if (INTEL_GEN(dev_priv) < 9) {
                I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
+       }
 }
 
 static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
index 3fd249c05e4eba34507ceaa3d53658bdf714339a..cdfe0951d1713e67a471050d9b7bae636ce02d21 100644 (file)
@@ -5559,6 +5559,9 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
        if (intel_crtc->config->shared_dpll)
                intel_enable_shared_dpll(intel_crtc);
 
+       if (INTEL_GEN(dev_priv) >= 11)
+               icl_map_plls_to_ports(crtc, pipe_config, old_state);
+
        if (intel_crtc_has_dp_encoder(intel_crtc->config))
                intel_dp_set_m_n(intel_crtc, M1_N1);
 
@@ -5756,6 +5759,9 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state,
                intel_ddi_disable_pipe_clock(intel_crtc->config);
 
        intel_encoders_post_disable(crtc, old_crtc_state, old_state);
+
+       if (INTEL_GEN(dev_priv) >= 11)
+               icl_unmap_plls_to_ports(crtc, old_crtc_state, old_state);
 }
 
 static void i9xx_pfit_enable(struct intel_crtc *crtc)
@@ -11386,6 +11392,16 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
        PIPE_CONF_CHECK_X(dpll_hw_state.pll9);
        PIPE_CONF_CHECK_X(dpll_hw_state.pll10);
        PIPE_CONF_CHECK_X(dpll_hw_state.pcsdw12);
+       PIPE_CONF_CHECK_X(dpll_hw_state.mg_refclkin_ctl);
+       PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_coreclkctl1);
+       PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_hsclkctl);
+       PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div0);
+       PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div1);
+       PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_lf);
+       PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_frac_lock);
+       PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_ssc);
+       PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_bias);
+       PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_tdc_coldst_bias);
 
        PIPE_CONF_CHECK_X(dsi_pll.ctrl);
        PIPE_CONF_CHECK_X(dsi_pll.div);
index d5e114e9660bb5424f4160cec46c823d07733246..14f5414ceab22eae59d4484236080e69b3b79281 100644 (file)
@@ -2399,6 +2399,315 @@ static const struct intel_dpll_mgr cnl_pll_mgr = {
        .dump_hw_state = cnl_dump_hw_state,
 };
 
+static bool icl_calc_dpll_state(struct intel_crtc_state *crtc_state,
+                               struct intel_encoder *encoder, int clock,
+                               struct intel_dpll_hw_state *pll_state)
+{
+       /* TODO */
+       return true;
+}
+
+static enum port icl_mg_pll_id_to_port(enum intel_dpll_id id)
+{
+       return id - DPLL_ID_ICL_MGPLL1 + PORT_C;
+}
+
+static enum intel_dpll_id icl_port_to_mg_pll_id(enum port port)
+{
+       return port - PORT_C + DPLL_ID_ICL_MGPLL1;
+}
+
+static bool icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state,
+                                 struct intel_encoder *encoder, int clock,
+                                 struct intel_dpll_hw_state *pll_state)
+{
+       /* TODO */
+       return true;
+}
+
+static struct intel_shared_dpll *
+icl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
+            struct intel_encoder *encoder)
+{
+       struct intel_shared_dpll *pll;
+       struct intel_dpll_hw_state pll_state = {};
+       enum port port = encoder->port;
+       enum intel_dpll_id min, max;
+       int clock = crtc_state->port_clock;
+       bool ret;
+
+       switch (port) {
+       case PORT_A:
+       case PORT_B:
+               min = DPLL_ID_ICL_DPLL0;
+               max = DPLL_ID_ICL_DPLL1;
+               ret = icl_calc_dpll_state(crtc_state, encoder, clock,
+                                         &pll_state);
+               break;
+       case PORT_C:
+       case PORT_D:
+       case PORT_E:
+       case PORT_F:
+               min = icl_port_to_mg_pll_id(port);
+               max = min;
+               ret = icl_calc_mg_pll_state(crtc_state, encoder, clock,
+                                           &pll_state);
+               break;
+       default:
+               MISSING_CASE(port);
+               return NULL;
+       }
+
+       if (!ret) {
+               DRM_DEBUG_KMS("Could not calculate PLL state.\n");
+               return NULL;
+       }
+
+       crtc_state->dpll_hw_state = pll_state;
+
+       pll = intel_find_shared_dpll(crtc, crtc_state, min, max);
+       if (!pll) {
+               DRM_DEBUG_KMS("No PLL selected\n");
+               return NULL;
+       }
+
+       intel_reference_shared_dpll(pll, crtc_state);
+
+       return pll;
+}
+
+static i915_reg_t icl_pll_id_to_enable_reg(enum intel_dpll_id id)
+{
+       switch (id) {
+       default:
+               MISSING_CASE(id);
+       case DPLL_ID_ICL_DPLL0:
+       case DPLL_ID_ICL_DPLL1:
+               return CNL_DPLL_ENABLE(id);
+       case DPLL_ID_ICL_MGPLL1:
+       case DPLL_ID_ICL_MGPLL2:
+       case DPLL_ID_ICL_MGPLL3:
+       case DPLL_ID_ICL_MGPLL4:
+               return MG_PLL_ENABLE(icl_mg_pll_id_to_port(id));
+       }
+}
+
+static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv,
+                                struct intel_shared_dpll *pll,
+                                struct intel_dpll_hw_state *hw_state)
+{
+       const enum intel_dpll_id id = pll->info->id;
+       uint32_t val;
+       enum port port;
+       bool ret = false;
+
+       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+               return false;
+
+       val = I915_READ(icl_pll_id_to_enable_reg(id));
+       if (!(val & PLL_ENABLE))
+               goto out;
+
+       switch (id) {
+       case DPLL_ID_ICL_DPLL0:
+       case DPLL_ID_ICL_DPLL1:
+               hw_state->cfgcr0 = I915_READ(ICL_DPLL_CFGCR0(id));
+               hw_state->cfgcr1 = I915_READ(ICL_DPLL_CFGCR1(id));
+               break;
+       case DPLL_ID_ICL_MGPLL1:
+       case DPLL_ID_ICL_MGPLL2:
+       case DPLL_ID_ICL_MGPLL3:
+       case DPLL_ID_ICL_MGPLL4:
+               port = icl_mg_pll_id_to_port(id);
+               hw_state->mg_refclkin_ctl = I915_READ(MG_REFCLKIN_CTL(port));
+               hw_state->mg_clktop2_coreclkctl1 =
+                       I915_READ(MG_CLKTOP2_CORECLKCTL1(port));
+               hw_state->mg_clktop2_hsclkctl =
+                       I915_READ(MG_CLKTOP2_HSCLKCTL(port));
+               hw_state->mg_pll_div0 = I915_READ(MG_PLL_DIV0(port));
+               hw_state->mg_pll_div1 = I915_READ(MG_PLL_DIV1(port));
+               hw_state->mg_pll_lf = I915_READ(MG_PLL_LF(port));
+               hw_state->mg_pll_frac_lock = I915_READ(MG_PLL_FRAC_LOCK(port));
+               hw_state->mg_pll_ssc = I915_READ(MG_PLL_SSC(port));
+               hw_state->mg_pll_bias = I915_READ(MG_PLL_BIAS(port));
+               hw_state->mg_pll_tdc_coldst_bias =
+                       I915_READ(MG_PLL_TDC_COLDST_BIAS(port));
+               break;
+       default:
+               MISSING_CASE(id);
+       }
+
+       ret = true;
+out:
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+       return ret;
+}
+
+static void icl_dpll_write(struct drm_i915_private *dev_priv,
+                          struct intel_shared_dpll *pll)
+{
+       struct intel_dpll_hw_state *hw_state = &pll->state.hw_state;
+       const enum intel_dpll_id id = pll->info->id;
+
+       I915_WRITE(ICL_DPLL_CFGCR0(id), hw_state->cfgcr0);
+       I915_WRITE(ICL_DPLL_CFGCR1(id), hw_state->cfgcr1);
+       POSTING_READ(ICL_DPLL_CFGCR1(id));
+}
+
+static void icl_mg_pll_write(struct drm_i915_private *dev_priv,
+                            struct intel_shared_dpll *pll)
+{
+       struct intel_dpll_hw_state *hw_state = &pll->state.hw_state;
+       enum port port = icl_mg_pll_id_to_port(pll->info->id);
+
+       I915_WRITE(MG_REFCLKIN_CTL(port), hw_state->mg_refclkin_ctl);
+       I915_WRITE(MG_CLKTOP2_CORECLKCTL1(port),
+                  hw_state->mg_clktop2_coreclkctl1);
+       I915_WRITE(MG_CLKTOP2_HSCLKCTL(port), hw_state->mg_clktop2_hsclkctl);
+       I915_WRITE(MG_PLL_DIV0(port), hw_state->mg_pll_div0);
+       I915_WRITE(MG_PLL_DIV1(port), hw_state->mg_pll_div1);
+       I915_WRITE(MG_PLL_LF(port), hw_state->mg_pll_lf);
+       I915_WRITE(MG_PLL_FRAC_LOCK(port), hw_state->mg_pll_frac_lock);
+       I915_WRITE(MG_PLL_SSC(port), hw_state->mg_pll_ssc);
+       I915_WRITE(MG_PLL_BIAS(port), hw_state->mg_pll_bias);
+       I915_WRITE(MG_PLL_TDC_COLDST_BIAS(port),
+                  hw_state->mg_pll_tdc_coldst_bias);
+       POSTING_READ(MG_PLL_TDC_COLDST_BIAS(port));
+}
+
+static void icl_pll_enable(struct drm_i915_private *dev_priv,
+                          struct intel_shared_dpll *pll)
+{
+       const enum intel_dpll_id id = pll->info->id;
+       i915_reg_t enable_reg = icl_pll_id_to_enable_reg(id);
+       uint32_t val;
+
+       val = I915_READ(enable_reg);
+       val |= PLL_POWER_ENABLE;
+       I915_WRITE(enable_reg, val);
+
+       /*
+        * The spec says we need to "wait" but it also says it should be
+        * immediate.
+        */
+       if (intel_wait_for_register(dev_priv, enable_reg, PLL_POWER_STATE,
+                                   PLL_POWER_STATE, 1))
+               DRM_ERROR("PLL %d Power not enabled\n", id);
+
+       switch (id) {
+       case DPLL_ID_ICL_DPLL0:
+       case DPLL_ID_ICL_DPLL1:
+               icl_dpll_write(dev_priv, pll);
+               break;
+       case DPLL_ID_ICL_MGPLL1:
+       case DPLL_ID_ICL_MGPLL2:
+       case DPLL_ID_ICL_MGPLL3:
+       case DPLL_ID_ICL_MGPLL4:
+               icl_mg_pll_write(dev_priv, pll);
+               break;
+       default:
+               MISSING_CASE(id);
+       }
+
+       /*
+        * DVFS pre sequence would be here, but in our driver the cdclk code
+        * paths should already be setting the appropriate voltage, hence we do
+        * nothign here.
+        */
+
+       val = I915_READ(enable_reg);
+       val |= PLL_ENABLE;
+       I915_WRITE(enable_reg, val);
+
+       if (intel_wait_for_register(dev_priv, enable_reg, PLL_LOCK, PLL_LOCK,
+                                   1)) /* 600us actually. */
+               DRM_ERROR("PLL %d not locked\n", id);
+
+       /* DVFS post sequence would be here. See the comment above. */
+}
+
+static void icl_pll_disable(struct drm_i915_private *dev_priv,
+                           struct intel_shared_dpll *pll)
+{
+       const enum intel_dpll_id id = pll->info->id;
+       i915_reg_t enable_reg = icl_pll_id_to_enable_reg(id);
+       uint32_t val;
+
+       /* The first steps are done by intel_ddi_post_disable(). */
+
+       /*
+        * DVFS pre sequence would be here, but in our driver the cdclk code
+        * paths should already be setting the appropriate voltage, hence we do
+        * nothign here.
+        */
+
+       val = I915_READ(enable_reg);
+       val &= ~PLL_ENABLE;
+       I915_WRITE(enable_reg, val);
+
+       /* Timeout is actually 1us. */
+       if (intel_wait_for_register(dev_priv, enable_reg, PLL_LOCK, 0, 1))
+               DRM_ERROR("PLL %d locked\n", id);
+
+       /* DVFS post sequence would be here. See the comment above. */
+
+       val = I915_READ(enable_reg);
+       val &= ~PLL_POWER_ENABLE;
+       I915_WRITE(enable_reg, val);
+
+       /*
+        * The spec says we need to "wait" but it also says it should be
+        * immediate.
+        */
+       if (intel_wait_for_register(dev_priv, enable_reg, PLL_POWER_STATE, 0,
+                                   1))
+               DRM_ERROR("PLL %d Power not disabled\n", id);
+}
+
+static void icl_dump_hw_state(struct drm_i915_private *dev_priv,
+                             struct intel_dpll_hw_state *hw_state)
+{
+       DRM_DEBUG_KMS("dpll_hw_state: cfgcr0: 0x%x, cfgcr1: 0x%x, "
+                     "mg_refclkin_ctl: 0x%x, hg_clktop2_coreclkctl1: 0x%x, "
+                     "mg_clktop2_hsclkctl: 0x%x, mg_pll_div0: 0x%x, "
+                     "mg_pll_div2: 0x%x, mg_pll_lf: 0x%x, "
+                     "mg_pll_frac_lock: 0x%x, mg_pll_ssc: 0x%x, "
+                     "mg_pll_bias: 0x%x, mg_pll_tdc_coldst_bias: 0x%x\n",
+                     hw_state->cfgcr0, hw_state->cfgcr1,
+                     hw_state->mg_refclkin_ctl,
+                     hw_state->mg_clktop2_coreclkctl1,
+                     hw_state->mg_clktop2_hsclkctl,
+                     hw_state->mg_pll_div0,
+                     hw_state->mg_pll_div1,
+                     hw_state->mg_pll_lf,
+                     hw_state->mg_pll_frac_lock,
+                     hw_state->mg_pll_ssc,
+                     hw_state->mg_pll_bias,
+                     hw_state->mg_pll_tdc_coldst_bias);
+}
+
+static const struct intel_shared_dpll_funcs icl_pll_funcs = {
+       .enable = icl_pll_enable,
+       .disable = icl_pll_disable,
+       .get_hw_state = icl_pll_get_hw_state,
+};
+
+static const struct dpll_info icl_plls[] = {
+       { "DPLL 0",   &icl_pll_funcs, DPLL_ID_ICL_DPLL0,  0 },
+       { "DPLL 1",   &icl_pll_funcs, DPLL_ID_ICL_DPLL1,  0 },
+       { "MG PLL 1", &icl_pll_funcs, DPLL_ID_ICL_MGPLL1, 0 },
+       { "MG PLL 2", &icl_pll_funcs, DPLL_ID_ICL_MGPLL2, 0 },
+       { "MG PLL 3", &icl_pll_funcs, DPLL_ID_ICL_MGPLL3, 0 },
+       { "MG PLL 4", &icl_pll_funcs, DPLL_ID_ICL_MGPLL4, 0 },
+       { },
+};
+
+static const struct intel_dpll_mgr icl_pll_mgr = {
+       .dpll_info = icl_plls,
+       .get_dpll = icl_get_dpll,
+       .dump_hw_state = icl_dump_hw_state,
+};
+
 /**
  * intel_shared_dpll_init - Initialize shared DPLLs
  * @dev: drm device
@@ -2412,7 +2721,9 @@ void intel_shared_dpll_init(struct drm_device *dev)
        const struct dpll_info *dpll_info;
        int i;
 
-       if (IS_CANNONLAKE(dev_priv))
+       if (IS_ICELAKE(dev_priv))
+               dpll_mgr = &icl_pll_mgr;
+       else if (IS_CANNONLAKE(dev_priv))
                dpll_mgr = &cnl_pll_mgr;
        else if (IS_GEN9_BC(dev_priv))
                dpll_mgr = &skl_pll_mgr;
index 4febfaa90bdead46db5b7da7fc6b1398e937cd4d..7a0cd564a9ee1f9f562a61882922fac13be62285 100644 (file)
@@ -103,6 +103,32 @@ enum intel_dpll_id {
         * @DPLL_ID_SKL_DPLL3: SKL and later DPLL3
         */
        DPLL_ID_SKL_DPLL3 = 3,
+
+
+       /**
+        * @DPLL_ID_ICL_DPLL0: ICL combo PHY DPLL0
+        */
+       DPLL_ID_ICL_DPLL0 = 0,
+       /**
+        * @DPLL_ID_ICL_DPLL1: ICL combo PHY DPLL1
+        */
+       DPLL_ID_ICL_DPLL1 = 1,
+       /**
+        * @DPLL_ID_ICL_MGPLL1: ICL MG PLL 1 port 1 (C)
+        */
+       DPLL_ID_ICL_MGPLL1 = 2,
+       /**
+        * @DPLL_ID_ICL_MGPLL2: ICL MG PLL 1 port 2 (D)
+        */
+       DPLL_ID_ICL_MGPLL2 = 3,
+       /**
+        * @DPLL_ID_ICL_MGPLL3: ICL MG PLL 1 port 3 (E)
+        */
+       DPLL_ID_ICL_MGPLL3 = 4,
+       /**
+        * @DPLL_ID_ICL_MGPLL4: ICL MG PLL 1 port 4 (F)
+        */
+       DPLL_ID_ICL_MGPLL4 = 5,
 };
 #define I915_NUM_PLLS 6
 
@@ -135,6 +161,21 @@ struct intel_dpll_hw_state {
        /* bxt */
        uint32_t ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10,
                 pcsdw12;
+
+       /*
+        * ICL uses the following, already defined:
+        * uint32_t cfgcr0, cfgcr1;
+        */
+       uint32_t mg_refclkin_ctl;
+       uint32_t mg_clktop2_coreclkctl1;
+       uint32_t mg_clktop2_hsclkctl;
+       uint32_t mg_pll_div0;
+       uint32_t mg_pll_div1;
+       uint32_t mg_pll_lf;
+       uint32_t mg_pll_frac_lock;
+       uint32_t mg_pll_ssc;
+       uint32_t mg_pll_bias;
+       uint32_t mg_pll_tdc_coldst_bias;
 };
 
 /**
index 11a1932cde6e30c061cba2485533118045b37d07..52337f487ebc8170b273114eb7ac4fa3e79d9cef 100644 (file)
@@ -1409,6 +1409,12 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp);
 u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder);
 int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder,
                                     bool enable);
+void icl_map_plls_to_ports(struct drm_crtc *crtc,
+                          struct intel_crtc_state *crtc_state,
+                          struct drm_atomic_state *old_state);
+void icl_unmap_plls_to_ports(struct drm_crtc *crtc,
+                            struct intel_crtc_state *crtc_state,
+                            struct drm_atomic_state *old_state);
 
 unsigned int intel_fb_align_height(const struct drm_framebuffer *fb,
                                   int plane, unsigned int height);