On Wed, Mar 28, 2018 at 02:57:58PM -0700, Paulo Zanoni wrote: > 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. > > Cc: James Ausmus <james.ausmus@xxxxxxxxx> > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@xxxxxxxxx> > --- > drivers/gpu/drm/i915/i915_debugfs.c | 22 +++ > drivers/gpu/drm/i915/intel_ddi.c | 98 ++++++++++- > drivers/gpu/drm/i915/intel_display.c | 16 ++ > drivers/gpu/drm/i915/intel_dpll_mgr.c | 312 +++++++++++++++++++++++++++++++++- > drivers/gpu/drm/i915/intel_dpll_mgr.h | 41 +++++ > drivers/gpu/drm/i915/intel_drv.h | 6 + > 6 files changed, 490 insertions(+), 5 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c > index ff90577da450..43a805c39b0a 100644 > --- a/drivers/gpu/drm/i915/i915_debugfs.c > +++ b/drivers/gpu/drm/i915/i915_debugfs.c > @@ -3296,6 +3296,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); > > diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c > index a6672a9abd85..10223ffcceab 100644 > --- a/drivers/gpu/drm/i915/intel_ddi.c > +++ b/drivers/gpu/drm/i915/intel_ddi.c > @@ -1013,6 +1013,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. > @@ -2234,6 +2253,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; Just realized that we have the same potential NULL encoder problem here in map, too - not just unmap, which I missed previously. > + 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 *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; Access of encoder->port needs to be after the encoder NULL check, otherwise the NULL check is pointless :) > + > + if (!encoder || 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) > { > @@ -2246,7 +2328,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); > @@ -2284,14 +2370,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, > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c > index 8b18729bc4d3..64e7943164d5 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -5508,6 +5508,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); > > @@ -5705,6 +5708,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) > @@ -11324,6 +11330,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); > diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c > index d5e114e9660b..470de6a33ca0 100644 > --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c > +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c > @@ -2399,6 +2399,314 @@ 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 = max = icl_port_to_mg_pll_id(port); > + 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 +2720,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; > diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h > index 4febfaa90bde..7a0cd564a9ee 100644 > --- a/drivers/gpu/drm/i915/intel_dpll_mgr.h > +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h > @@ -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; > }; > > /** > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h > index d1452fd2a58d..d77306950676 100644 > --- a/drivers/gpu/drm/i915/intel_drv.h > +++ b/drivers/gpu/drm/i915/intel_drv.h > @@ -1393,6 +1393,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); > -- > 2.14.3 > _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx