From a3c988ea068c94f39a2e6bd37e0faf1c2606a55d Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Tue, 8 Mar 2016 17:46:27 +0200 Subject: [PATCH] drm/i915: Make SKL/KBL DPLL0 managed by the shared dpll code Include DPLL0 in the managed dplls for SKL/KBL. While it has to be kept enabled because of it driving CDCLK, it is better to special case that inside the DPLL code than in the higher level. v2: Use INTEL_DPLL_ALWAYS_ON flag. (Ander) v3: Remove extremely paranoid WARN_ONs. (Maarten) Handle DPLL0 in skylake_get_ddi_pll() properly. (Ander) Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1457451987-17466-14-git-send-email-ander.conselvan.de.oliveira@intel.com --- drivers/gpu/drm/i915/intel_ddi.c | 21 ----- drivers/gpu/drm/i915/intel_display.c | 12 +-- drivers/gpu/drm/i915/intel_dp.c | 52 +---------- drivers/gpu/drm/i915/intel_dpll_mgr.c | 124 ++++++++++++++++++++------ drivers/gpu/drm/i915/intel_dpll_mgr.h | 7 +- 5 files changed, 105 insertions(+), 111 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 31f9aa0c2b51..91654ffc3a42 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1008,9 +1008,6 @@ skl_ddi_pll_select(struct intel_crtc *intel_crtc, { struct intel_shared_dpll *pll; - if (intel_encoder->type == INTEL_OUTPUT_EDP) - return true; - pll = intel_get_shared_dpll(intel_crtc, crtc_state, intel_encoder); if (pll == NULL) { DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", @@ -1570,24 +1567,6 @@ void intel_ddi_clk_select(struct intel_encoder *encoder, uint32_t dpll = pipe_config->ddi_pll_sel; uint32_t val; - /* - * DPLL0 is used for eDP and is the only "private" DPLL (as - * opposed to shared) on SKL - */ - if (encoder->type == INTEL_OUTPUT_EDP) { - WARN_ON(dpll != SKL_DPLL0); - - val = I915_READ(DPLL_CTRL1); - - val &= ~(DPLL_CTRL1_HDMI_MODE(dpll) | - DPLL_CTRL1_SSC(dpll) | - DPLL_CTRL1_LINK_RATE_MASK(dpll)); - val |= pipe_config->dpll_hw_state.ctrl1 << (dpll * 6); - - I915_WRITE(DPLL_CTRL1, val); - POSTING_READ(DPLL_CTRL1); - } - /* DDI -> PLL mapping */ val = I915_READ(DPLL_CTRL2); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 7e00ee51b2c9..28556a800804 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9771,21 +9771,15 @@ static void skylake_get_ddi_pll(struct drm_i915_private *dev_priv, struct intel_crtc_state *pipe_config) { enum intel_dpll_id id; - u32 temp, dpll_ctl1; + u32 temp; temp = I915_READ(DPLL_CTRL2) & DPLL_CTRL2_DDI_CLK_SEL_MASK(port); pipe_config->ddi_pll_sel = temp >> (port * 3 + 1); switch (pipe_config->ddi_pll_sel) { case SKL_DPLL0: - /* - * On SKL the eDP DPLL (DPLL0 as we don't use SSC) is not part - * of the shared DPLL framework and thus needs to be read out - * separately - */ - dpll_ctl1 = I915_READ(DPLL_CTRL1); - pipe_config->dpll_hw_state.ctrl1 = dpll_ctl1 & 0x3f; - return; + id = DPLL_ID_SKL_DPLL0; + break; case SKL_DPLL1: id = DPLL_ID_SKL_DPLL1; break; diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 4f0fad3cf138..13e1cc8936d8 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1237,52 +1237,6 @@ intel_dp_connector_unregister(struct intel_connector *intel_connector) intel_connector_unregister(intel_connector); } -static void -skl_edp_set_pll_config(struct intel_crtc_state *pipe_config) -{ - u32 ctrl1; - - memset(&pipe_config->dpll_hw_state, 0, - sizeof(pipe_config->dpll_hw_state)); - - pipe_config->ddi_pll_sel = SKL_DPLL0; - pipe_config->dpll_hw_state.cfgcr1 = 0; - pipe_config->dpll_hw_state.cfgcr2 = 0; - - ctrl1 = DPLL_CTRL1_OVERRIDE(SKL_DPLL0); - switch (pipe_config->port_clock / 2) { - case 81000: - ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, - SKL_DPLL0); - break; - case 135000: - ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, - SKL_DPLL0); - break; - case 270000: - ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, - SKL_DPLL0); - break; - case 162000: - ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, - SKL_DPLL0); - break; - /* TBD: For DP link rates 2.16 GHz and 4.32 GHz, VCO is 8640 which - results in CDCLK change. Need to handle the change of CDCLK by - disabling pipes and re-enabling them */ - case 108000: - ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, - SKL_DPLL0); - break; - case 216000: - ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, - SKL_DPLL0); - break; - - } - pipe_config->dpll_hw_state.ctrl1 = ctrl1; -} - static int intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates) { @@ -1640,11 +1594,7 @@ found: &pipe_config->dp_m2_n2); } - if ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) && is_edp(intel_dp)) - skl_edp_set_pll_config(pipe_config); - else if (IS_BROXTON(dev) || IS_HASWELL(dev) || IS_BROADWELL(dev)) - /* handled in ddi */; - else + if (!HAS_DDI(dev)) intel_dp_set_clock(encoder, pipe_config); return true; diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index a83af07e3570..4b636c47e8e3 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -785,7 +785,12 @@ struct skl_dpll_regs { }; /* this array is indexed by the *shared* pll id */ -static const struct skl_dpll_regs skl_dpll_regs[3] = { +static const struct skl_dpll_regs skl_dpll_regs[4] = { + { + /* DPLL 0 */ + .ctl = LCPLL1_CTL, + /* DPLL 0 doesn't support HDMI mode */ + }, { /* DPLL 1 */ .ctl = LCPLL2_CTL, @@ -806,24 +811,27 @@ static const struct skl_dpll_regs skl_dpll_regs[3] = { }, }; -static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll) +static void skl_ddi_pll_write_ctrl1(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) { uint32_t val; - unsigned int dpll; - const struct skl_dpll_regs *regs = skl_dpll_regs; - - /* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */ - dpll = pll->id + 1; val = I915_READ(DPLL_CTRL1); - val &= ~(DPLL_CTRL1_HDMI_MODE(dpll) | DPLL_CTRL1_SSC(dpll) | - DPLL_CTRL1_LINK_RATE_MASK(dpll)); - val |= pll->config.hw_state.ctrl1 << (dpll * 6); + val &= ~(DPLL_CTRL1_HDMI_MODE(pll->id) | DPLL_CTRL1_SSC(pll->id) | + DPLL_CTRL1_LINK_RATE_MASK(pll->id)); + val |= pll->config.hw_state.ctrl1 << (pll->id * 6); I915_WRITE(DPLL_CTRL1, val); POSTING_READ(DPLL_CTRL1); +} + +static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ + const struct skl_dpll_regs *regs = skl_dpll_regs; + + skl_ddi_pll_write_ctrl1(dev_priv, pll); I915_WRITE(regs[pll->id].cfgcr1, pll->config.hw_state.cfgcr1); I915_WRITE(regs[pll->id].cfgcr2, pll->config.hw_state.cfgcr2); @@ -834,8 +842,14 @@ static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv, I915_WRITE(regs[pll->id].ctl, I915_READ(regs[pll->id].ctl) | LCPLL_PLL_ENABLE); - if (wait_for(I915_READ(DPLL_STATUS) & DPLL_LOCK(dpll), 5)) - DRM_ERROR("DPLL %d not locked\n", dpll); + if (wait_for(I915_READ(DPLL_STATUS) & DPLL_LOCK(pll->id), 5)) + DRM_ERROR("DPLL %d not locked\n", pll->id); +} + +static void skl_ddi_dpll0_enable(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ + skl_ddi_pll_write_ctrl1(dev_priv, pll); } static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv, @@ -849,12 +863,16 @@ static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv, POSTING_READ(regs[pll->id].ctl); } +static void skl_ddi_dpll0_disable(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ +} + static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll, struct intel_dpll_hw_state *hw_state) { uint32_t val; - unsigned int dpll; const struct skl_dpll_regs *regs = skl_dpll_regs; bool ret; @@ -863,18 +881,15 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, ret = false; - /* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */ - dpll = pll->id + 1; - val = I915_READ(regs[pll->id].ctl); if (!(val & LCPLL_PLL_ENABLE)) goto out; val = I915_READ(DPLL_CTRL1); - hw_state->ctrl1 = (val >> (dpll * 6)) & 0x3f; + hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f; /* avoid reading back stale values if HDMI mode is not enabled */ - if (val & DPLL_CTRL1_HDMI_MODE(dpll)) { + if (val & DPLL_CTRL1_HDMI_MODE(pll->id)) { hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1); hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2); } @@ -886,6 +901,35 @@ out: return ret; } +static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll, + struct intel_dpll_hw_state *hw_state) +{ + uint32_t val; + const struct skl_dpll_regs *regs = skl_dpll_regs; + bool ret; + + if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) + return false; + + ret = false; + + /* DPLL0 is always enabled since it drives CDCLK */ + val = I915_READ(regs[pll->id].ctl); + if (WARN_ON(!(val & LCPLL_PLL_ENABLE))) + goto out; + + val = I915_READ(DPLL_CTRL1); + hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f; + + ret = true; + +out: + intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); + + return ret; +} + struct skl_wrpll_context { uint64_t min_deviation; /* current minimal deviation */ uint64_t central_freq; /* chosen central freq */ @@ -1165,7 +1209,8 @@ skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, DPLL_CFGCR2_PDIV(wrpll_params.pdiv) | wrpll_params.central_freq; } else if (encoder->type == INTEL_OUTPUT_DISPLAYPORT || - encoder->type == INTEL_OUTPUT_DP_MST) { + encoder->type == INTEL_OUTPUT_DP_MST || + encoder->type == INTEL_OUTPUT_EDP) { switch (crtc_state->port_clock / 2) { case 81000: ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0); @@ -1176,6 +1221,19 @@ skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, case 270000: ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0); break; + /* eDP 1.4 rates */ + case 162000: + ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, 0); + break; + /* TBD: For DP link rates 2.16 GHz and 4.32 GHz, VCO is 8640 which + results in CDCLK change. Need to handle the change of CDCLK by + disabling pipes and re-enabling them */ + case 108000: + ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, 0); + break; + case 216000: + ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, 0); + break; } cfgcr1 = cfgcr2 = 0; @@ -1190,13 +1248,18 @@ skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, crtc_state->dpll_hw_state.cfgcr1 = cfgcr1; crtc_state->dpll_hw_state.cfgcr2 = cfgcr2; - pll = intel_find_shared_dpll(crtc, crtc_state, - DPLL_ID_SKL_DPLL1, DPLL_ID_SKL_DPLL3); + if (encoder->type == INTEL_OUTPUT_EDP) + pll = intel_find_shared_dpll(crtc, crtc_state, + DPLL_ID_SKL_DPLL0, + DPLL_ID_SKL_DPLL0); + else + pll = intel_find_shared_dpll(crtc, crtc_state, + DPLL_ID_SKL_DPLL1, + DPLL_ID_SKL_DPLL3); if (!pll) return NULL; - /* shared DPLL id 0 is DPLL 1 */ - crtc_state->ddi_pll_sel = pll->id + 1; + crtc_state->ddi_pll_sel = pll->id; intel_reference_shared_dpll(pll, crtc_state); @@ -1209,6 +1272,12 @@ static const struct intel_shared_dpll_funcs skl_ddi_pll_funcs = { .get_hw_state = skl_ddi_pll_get_hw_state, }; +static const struct intel_shared_dpll_funcs skl_ddi_dpll0_funcs = { + .enable = skl_ddi_dpll0_enable, + .disable = skl_ddi_dpll0_disable, + .get_hw_state = skl_ddi_dpll0_get_hw_state, +}; + static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll) { @@ -1624,9 +1693,10 @@ static const struct intel_dpll_mgr hsw_pll_mgr = { }; static const struct dpll_info skl_plls[] = { - { "DPPL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs, 0 }, - { "DPPL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs, 0 }, - { "DPPL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs, 0 }, + { "DPLL 0", DPLL_ID_SKL_DPLL0, &skl_ddi_dpll0_funcs, INTEL_DPLL_ALWAYS_ON }, + { "DPPL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs, 0 }, + { "DPPL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs, 0 }, + { "DPPL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs, 0 }, { NULL, -1, NULL, }, }; diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h index adf4706b8e58..1d341472f8b0 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h @@ -54,9 +54,10 @@ enum intel_dpll_id { DPLL_ID_LCPLL_2700 = 5, /* skl */ - DPLL_ID_SKL_DPLL1 = 0, - DPLL_ID_SKL_DPLL2 = 1, - DPLL_ID_SKL_DPLL3 = 2, + DPLL_ID_SKL_DPLL0 = 0, + DPLL_ID_SKL_DPLL1 = 1, + DPLL_ID_SKL_DPLL2 = 2, + DPLL_ID_SKL_DPLL3 = 3, }; #define I915_NUM_PLLS 6 -- 2.39.5