From e9b7e1422d409bb7d3423b8d1e59865227083669 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 28 Jun 2019 17:36:16 +0300 Subject: drm/i915: Sanitize the terminology used for TypeC port modes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The TypeC port mode can switch dynamically, to reflect that better call the port's mode as 'mode' rather than 'type'. While at it: - s/TC_PORT_TBT/TC_PORT_TBT_ALT/ and s/TC_PORT_TYPEC/TC_PORT_DP_ALT/. 'TYPEC' is ambiguous, TBT_ALT and DP_ALT better match the reality. - Remove the 'unknown' TypeC port mode. The mode is always known, it's the TBT-alt/safe mode after HW reset and after disconnecting the PHY. Simplify the tc_port/tc_type checks accordingly. - Don't WARN if the port mode changes, that can happen normally. No functional changes. Cc: Animesh Manna Cc: Paulo Zanoni Cc: Anusha Srivatsa Cc: José Roberto de Souza Cc: Rodrigo Vivi Signed-off-by: Imre Deak Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20190628143635.22066-5-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/display/intel_dpll_mgr.c') diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 2d4e7b9a7b9d..bf66261c8bf0 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -2817,7 +2817,7 @@ icl_get_dpll(struct intel_crtc_state *crtc_state, intel_dig_port = enc_to_dig_port(&encoder->base); } - if (intel_dig_port->tc_type == TC_PORT_TBT) { + if (intel_dig_port->tc_mode == TC_PORT_TBT_ALT) { min = DPLL_ID_ICL_TBTPLL; max = min; ret = icl_calc_dpll_state(crtc_state, encoder); -- cgit v1.2.3 From 866955fa452e1f3d2164bd731d71348d4978e8bc Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 28 Jun 2019 17:36:28 +0300 Subject: drm/i915: Sanitize the shared DPLL reserve/release interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For consistency s/intel_get_shared_dpll()/intel_reserve_shared_dplls()/ to better match intel_release_shared_dplls(). Also, pass to the reserve/release and get_dplls/put_dplls hooks the intel_atomic_state and CRTC object, that way these functions can look up the old or new state as needed. Also release the PLLs from the atomic state via a new put_dplls->intel_unreference_shared_dpll() call chain for better symmetry with the reservation via the get_dplls->intel_reference_shared_dpll() call chain. Since nothing uses the PLL returned by intel_reserve_shared_dplls(), make it return only a bool. While at it also clarify the reserve/release function docbook headers making it clear that multiple DPLLs will be reserved/released and whether the new or old atomic CRTC state is affected. This refactoring is also a preparation for a follow-up change that needs to reserve multiple DPLLs. Kudos to Ville for the idea to pass intel_atomic_state around, to make things clearer locally where an object's old/new atomic state is required. No functional changes. v2: - Fix checkpatch issue: typo in code comment. v3: - Rebase on drm-tip. Cc: Ville Syrjälä Cc: Daniel Vetter Cc: Maarten Lankhorst Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20190628143635.22066-17-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 221 ++++++++++++++++---------- 1 file changed, 139 insertions(+), 82 deletions(-) (limited to 'drivers/gpu/drm/i915/display/intel_dpll_mgr.c') diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index bf66261c8bf0..3fbc975851fa 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -36,9 +36,10 @@ * This file provides an abstraction over display PLLs. The function * intel_shared_dpll_init() initializes the PLLs for the given platform. The * users of a PLL are tracked and that tracking is integrated with the atomic - * modest interface. During an atomic operation, a PLL can be requested for a - * given CRTC and encoder configuration by calling intel_get_shared_dpll() and - * a previously used PLL can be released with intel_release_shared_dpll(). + * modset interface. During an atomic operation, required PLLs can be reserved + * for a given CRTC and encoder configuration by calling + * intel_reserve_shared_dplls() and previously reserved PLLs can be released + * with intel_release_shared_dplls(). * Changes to the users are first staged in the atomic state, and then made * effective by calling intel_shared_dpll_swap_state() during the atomic * commit phase. @@ -309,6 +310,28 @@ intel_reference_shared_dpll(struct intel_shared_dpll *pll, shared_dpll[id].crtc_mask |= 1 << crtc->pipe; } +static void intel_unreference_shared_dpll(struct intel_atomic_state *state, + const struct intel_crtc *crtc, + const struct intel_shared_dpll *pll) +{ + struct intel_shared_dpll_state *shared_dpll; + + shared_dpll = intel_atomic_get_shared_dpll_state(&state->base); + shared_dpll[pll->info->id].crtc_mask &= ~(1 << crtc->pipe); +} + +static void intel_put_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc) +{ + struct intel_crtc_state *crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + + if (!crtc_state->shared_dpll) + return; + + intel_unreference_shared_dpll(state, crtc, crtc_state->shared_dpll); +} + /** * intel_shared_dpll_swap_state - make atomic DPLL configuration effective * @state: atomic state @@ -421,11 +444,12 @@ static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv, udelay(200); } -static struct intel_shared_dpll * -ibx_get_dpll(struct intel_crtc_state *crtc_state, - struct intel_encoder *encoder) +static bool ibx_get_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_shared_dpll *pll; enum intel_dpll_id i; @@ -445,12 +469,12 @@ ibx_get_dpll(struct intel_crtc_state *crtc_state, } if (!pll) - return NULL; + return false; /* reference the pll */ intel_reference_shared_dpll(pll, crtc_state); - return pll; + return true; } static void ibx_dump_hw_state(struct drm_i915_private *dev_priv, @@ -821,10 +845,12 @@ hsw_ddi_dp_get_dpll(struct intel_crtc_state *crtc_state) return pll; } -static struct intel_shared_dpll * -hsw_get_dpll(struct intel_crtc_state *crtc_state, - struct intel_encoder *encoder) +static bool hsw_get_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) { + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); struct intel_shared_dpll *pll; memset(&crtc_state->dpll_hw_state, 0, @@ -836,7 +862,7 @@ hsw_get_dpll(struct intel_crtc_state *crtc_state, pll = hsw_ddi_dp_get_dpll(crtc_state); } else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG)) { if (WARN_ON(crtc_state->port_clock / 2 != 135000)) - return NULL; + return false; crtc_state->dpll_hw_state.spll = SPLL_PLL_ENABLE | SPLL_FREQ_1350MHz | SPLL_REF_MUXED_SSC; @@ -844,15 +870,15 @@ hsw_get_dpll(struct intel_crtc_state *crtc_state, pll = intel_find_shared_dpll(crtc_state, DPLL_ID_SPLL, DPLL_ID_SPLL); } else { - return NULL; + return false; } if (!pll) - return NULL; + return false; intel_reference_shared_dpll(pll, crtc_state); - return pll; + return true; } static void hsw_dump_hw_state(struct drm_i915_private *dev_priv, @@ -1385,10 +1411,12 @@ skl_ddi_dp_set_dpll_hw_state(struct intel_crtc_state *crtc_state) return true; } -static struct intel_shared_dpll * -skl_get_dpll(struct intel_crtc_state *crtc_state, - struct intel_encoder *encoder) +static bool skl_get_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) { + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); struct intel_shared_dpll *pll; bool bret; @@ -1396,16 +1424,16 @@ skl_get_dpll(struct intel_crtc_state *crtc_state, bret = skl_ddi_hdmi_pll_dividers(crtc_state); if (!bret) { DRM_DEBUG_KMS("Could not get HDMI pll dividers.\n"); - return NULL; + return false; } } else if (intel_crtc_has_dp_encoder(crtc_state)) { bret = skl_ddi_dp_set_dpll_hw_state(crtc_state); if (!bret) { DRM_DEBUG_KMS("Could not set DP dpll HW state.\n"); - return NULL; + return false; } } else { - return NULL; + return false; } if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) @@ -1417,11 +1445,11 @@ skl_get_dpll(struct intel_crtc_state *crtc_state, DPLL_ID_SKL_DPLL1, DPLL_ID_SKL_DPLL3); if (!pll) - return NULL; + return false; intel_reference_shared_dpll(pll, crtc_state); - return pll; + return true; } static void skl_dump_hw_state(struct drm_i915_private *dev_priv, @@ -1827,22 +1855,23 @@ bxt_ddi_hdmi_set_dpll_hw_state(struct intel_crtc_state *crtc_state) return bxt_ddi_set_dpll_hw_state(crtc_state, &clk_div); } -static struct intel_shared_dpll * -bxt_get_dpll(struct intel_crtc_state *crtc_state, - struct intel_encoder *encoder) +static bool bxt_get_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_shared_dpll *pll; enum intel_dpll_id id; if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) && !bxt_ddi_hdmi_set_dpll_hw_state(crtc_state)) - return NULL; + return false; if (intel_crtc_has_dp_encoder(crtc_state) && !bxt_ddi_dp_set_dpll_hw_state(crtc_state)) - return NULL; + return false; /* 1:1 mapping between ports and PLLs */ id = (enum intel_dpll_id) encoder->port; @@ -1853,7 +1882,7 @@ bxt_get_dpll(struct intel_crtc_state *crtc_state, intel_reference_shared_dpll(pll, crtc_state); - return pll; + return true; } static void bxt_dump_hw_state(struct drm_i915_private *dev_priv, @@ -1884,8 +1913,11 @@ static const struct intel_shared_dpll_funcs bxt_ddi_pll_funcs = { struct intel_dpll_mgr { const struct dpll_info *dpll_info; - struct intel_shared_dpll *(*get_dpll)(struct intel_crtc_state *crtc_state, - struct intel_encoder *encoder); + bool (*get_dplls)(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder); + void (*put_dplls)(struct intel_atomic_state *state, + struct intel_crtc *crtc); void (*dump_hw_state)(struct drm_i915_private *dev_priv, const struct intel_dpll_hw_state *hw_state); @@ -1899,7 +1931,8 @@ static const struct dpll_info pch_plls[] = { static const struct intel_dpll_mgr pch_pll_mgr = { .dpll_info = pch_plls, - .get_dpll = ibx_get_dpll, + .get_dplls = ibx_get_dpll, + .put_dplls = intel_put_dpll, .dump_hw_state = ibx_dump_hw_state, }; @@ -1915,7 +1948,8 @@ static const struct dpll_info hsw_plls[] = { static const struct intel_dpll_mgr hsw_pll_mgr = { .dpll_info = hsw_plls, - .get_dpll = hsw_get_dpll, + .get_dplls = hsw_get_dpll, + .put_dplls = intel_put_dpll, .dump_hw_state = hsw_dump_hw_state, }; @@ -1929,7 +1963,8 @@ static const struct dpll_info skl_plls[] = { static const struct intel_dpll_mgr skl_pll_mgr = { .dpll_info = skl_plls, - .get_dpll = skl_get_dpll, + .get_dplls = skl_get_dpll, + .put_dplls = intel_put_dpll, .dump_hw_state = skl_dump_hw_state, }; @@ -1942,7 +1977,8 @@ static const struct dpll_info bxt_plls[] = { static const struct intel_dpll_mgr bxt_pll_mgr = { .dpll_info = bxt_plls, - .get_dpll = bxt_get_dpll, + .get_dplls = bxt_get_dpll, + .put_dplls = intel_put_dpll, .dump_hw_state = bxt_dump_hw_state, }; @@ -2332,10 +2368,12 @@ cnl_ddi_dp_set_dpll_hw_state(struct intel_crtc_state *crtc_state) return true; } -static struct intel_shared_dpll * -cnl_get_dpll(struct intel_crtc_state *crtc_state, - struct intel_encoder *encoder) +static bool cnl_get_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) { + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); struct intel_shared_dpll *pll; bool bret; @@ -2343,18 +2381,18 @@ cnl_get_dpll(struct intel_crtc_state *crtc_state, bret = cnl_ddi_hdmi_pll_dividers(crtc_state); if (!bret) { DRM_DEBUG_KMS("Could not get HDMI pll dividers.\n"); - return NULL; + return false; } } else if (intel_crtc_has_dp_encoder(crtc_state)) { bret = cnl_ddi_dp_set_dpll_hw_state(crtc_state); if (!bret) { DRM_DEBUG_KMS("Could not set DP dpll HW state.\n"); - return NULL; + return false; } } else { DRM_DEBUG_KMS("Skip DPLL setup for output_types 0x%x\n", crtc_state->output_types); - return NULL; + return false; } pll = intel_find_shared_dpll(crtc_state, @@ -2362,12 +2400,12 @@ cnl_get_dpll(struct intel_crtc_state *crtc_state, DPLL_ID_SKL_DPLL2); if (!pll) { DRM_DEBUG_KMS("No PLL selected\n"); - return NULL; + return false; } intel_reference_shared_dpll(pll, crtc_state); - return pll; + return true; } static void cnl_dump_hw_state(struct drm_i915_private *dev_priv, @@ -2394,7 +2432,8 @@ static const struct dpll_info cnl_plls[] = { static const struct intel_dpll_mgr cnl_pll_mgr = { .dpll_info = cnl_plls, - .get_dpll = cnl_get_dpll, + .get_dplls = cnl_get_dpll, + .put_dplls = intel_put_dpll, .dump_hw_state = cnl_dump_hw_state, }; @@ -2792,11 +2831,13 @@ static bool icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state) return true; } -static struct intel_shared_dpll * -icl_get_dpll(struct intel_crtc_state *crtc_state, - struct intel_encoder *encoder) +static bool icl_get_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(state->base.dev); + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); struct intel_digital_port *intel_dig_port; struct intel_shared_dpll *pll; enum port port = encoder->port; @@ -2831,24 +2872,24 @@ icl_get_dpll(struct intel_crtc_state *crtc_state, } } else { MISSING_CASE(port); - return NULL; + return false; } if (!ret) { DRM_DEBUG_KMS("Could not calculate PLL state.\n"); - return NULL; + return false; } pll = intel_find_shared_dpll(crtc_state, min, max); if (!pll) { DRM_DEBUG_KMS("No PLL selected\n"); - return NULL; + return false; } intel_reference_shared_dpll(pll, crtc_state); - return pll; + return true; } static bool mg_pll_get_hw_state(struct drm_i915_private *dev_priv, @@ -3223,7 +3264,8 @@ static const struct dpll_info icl_plls[] = { static const struct intel_dpll_mgr icl_pll_mgr = { .dpll_info = icl_plls, - .get_dpll = icl_get_dpll, + .get_dplls = icl_get_dplls, + .put_dplls = intel_put_dpll, .dump_hw_state = icl_dump_hw_state, }; @@ -3235,7 +3277,8 @@ static const struct dpll_info ehl_plls[] = { static const struct intel_dpll_mgr ehl_pll_mgr = { .dpll_info = ehl_plls, - .get_dpll = icl_get_dpll, + .get_dplls = icl_get_dplls, + .put_dplls = intel_put_dpll, .dump_hw_state = icl_dump_hw_state, }; @@ -3287,50 +3330,64 @@ void intel_shared_dpll_init(struct drm_device *dev) } /** - * intel_get_shared_dpll - get a shared DPLL for CRTC and encoder combination - * @crtc_state: atomic state for the crtc + * intel_reserve_shared_dplls - reserve DPLLs for CRTC and encoder combination + * @state: atomic state + * @crtc: CRTC to reserve DPLLs for * @encoder: encoder * - * Find an appropriate DPLL for the given CRTC and encoder combination. A - * reference from the @crtc_state to the returned pll is registered in the - * atomic state. That configuration is made effective by calling - * intel_shared_dpll_swap_state(). The reference should be released by calling - * intel_release_shared_dpll(). + * This function reserves all required DPLLs for the given CRTC and encoder + * combination in the current atomic commit @state and the new @crtc atomic + * state. + * + * The new configuration in the atomic commit @state is made effective by + * calling intel_shared_dpll_swap_state(). + * + * The reserved DPLLs should be released by calling + * intel_release_shared_dplls(). * * Returns: - * A shared DPLL to be used by @crtc_state and @encoder. + * True if all required DPLLs were successfully reserved. */ -struct intel_shared_dpll * -intel_get_shared_dpll(struct intel_crtc_state *crtc_state, - struct intel_encoder *encoder) +bool intel_reserve_shared_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) { - struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + struct drm_i915_private *dev_priv = to_i915(state->base.dev); const struct intel_dpll_mgr *dpll_mgr = dev_priv->dpll_mgr; if (WARN_ON(!dpll_mgr)) - return NULL; + return false; - return dpll_mgr->get_dpll(crtc_state, encoder); + return dpll_mgr->get_dplls(state, crtc, encoder); } /** - * intel_release_shared_dpll - end use of DPLL by CRTC in atomic state - * @dpll: dpll in use by @crtc - * @crtc: crtc + * intel_release_shared_dplls - end use of DPLLs by CRTC in atomic state * @state: atomic state + * @crtc: crtc from which the DPLLs are to be released * - * This function releases the reference from @crtc to @dpll from the - * atomic @state. The new configuration is made effective by calling - * intel_shared_dpll_swap_state(). + * This function releases all DPLLs reserved by intel_reserve_shared_dplls() + * from the current atomic commit @state and the old @crtc atomic state. + * + * The new configuration in the atomic commit @state is made effective by + * calling intel_shared_dpll_swap_state(). */ -void intel_release_shared_dpll(struct intel_shared_dpll *dpll, - struct intel_crtc *crtc, - struct drm_atomic_state *state) +void intel_release_shared_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct intel_shared_dpll_state *shared_dpll_state; + struct drm_i915_private *dev_priv = to_i915(state->base.dev); + const struct intel_dpll_mgr *dpll_mgr = dev_priv->dpll_mgr; + + /* + * FIXME: this function is called for every platform having a + * compute_clock hook, even though the platform doesn't yet support + * the shared DPLL framework and intel_reserve_shared_dplls() is not + * called on those. + */ + if (!dpll_mgr) + return; - shared_dpll_state = intel_atomic_get_shared_dpll_state(state); - shared_dpll_state[dpll->info->id].crtc_mask &= ~(1 << crtc->pipe); + dpll_mgr->put_dplls(state, crtc); } /** -- cgit v1.2.3 From 01b24f50b67f49e40172c58d5e8034630f776110 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 28 Jun 2019 17:36:29 +0300 Subject: drm/i915: Sanitize the shared DPLL find/reference interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass the PLL HW state to the PLL find/reference functions making it clearer what is their input. Also pass to these the atomic state and the CRTC object instead of the CRTC state, since they don't require the latter. Move setting the PLL in the crtc_state to the get_dpll() hook, which is the more logical place for this, where the related PLL HW state was also set. This refactoring is also a preparation for a follow-up patch that will have to find/reference multiple PLLs. No functional changes. Cc: Ville Syrjälä Cc: Daniel Vetter Cc: Maarten Lankhorst Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20190628143635.22066-18-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 107 +++++++++++++++++--------- 1 file changed, 70 insertions(+), 37 deletions(-) (limited to 'drivers/gpu/drm/i915/display/intel_dpll_mgr.c') diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 3fbc975851fa..14bbab45836d 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -244,17 +244,18 @@ out: } static struct intel_shared_dpll * -intel_find_shared_dpll(struct intel_crtc_state *crtc_state, +intel_find_shared_dpll(struct intel_atomic_state *state, + const struct intel_crtc *crtc, + const struct intel_dpll_hw_state *pll_state, enum intel_dpll_id range_min, enum intel_dpll_id range_max) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_shared_dpll *pll, *unused_pll = NULL; struct intel_shared_dpll_state *shared_dpll; enum intel_dpll_id i; - shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state); + shared_dpll = intel_atomic_get_shared_dpll_state(&state->base); for (i = range_min; i <= range_max; i++) { pll = &dev_priv->shared_dplls[i]; @@ -266,9 +267,9 @@ intel_find_shared_dpll(struct intel_crtc_state *crtc_state, continue; } - if (memcmp(&crtc_state->dpll_hw_state, + if (memcmp(pll_state, &shared_dpll[i].hw_state, - sizeof(crtc_state->dpll_hw_state)) == 0) { + sizeof(*pll_state)) == 0) { DRM_DEBUG_KMS("[CRTC:%d:%s] sharing existing %s (crtc mask 0x%08x, active %x)\n", crtc->base.base.id, crtc->base.name, pll->info->name, @@ -290,20 +291,19 @@ intel_find_shared_dpll(struct intel_crtc_state *crtc_state, } static void -intel_reference_shared_dpll(struct intel_shared_dpll *pll, - struct intel_crtc_state *crtc_state) +intel_reference_shared_dpll(struct intel_atomic_state *state, + const struct intel_crtc *crtc, + const struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *pll_state) { struct intel_shared_dpll_state *shared_dpll; - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); const enum intel_dpll_id id = pll->info->id; - shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state); + shared_dpll = intel_atomic_get_shared_dpll_state(&state->base); if (shared_dpll[id].crtc_mask == 0) - shared_dpll[id].hw_state = - crtc_state->dpll_hw_state; + shared_dpll[id].hw_state = *pll_state; - crtc_state->shared_dpll = pll; DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->info->name, pipe_name(crtc->pipe)); @@ -463,7 +463,8 @@ static bool ibx_get_dpll(struct intel_atomic_state *state, crtc->base.base.id, crtc->base.name, pll->info->name); } else { - pll = intel_find_shared_dpll(crtc_state, + pll = intel_find_shared_dpll(state, crtc, + &crtc_state->dpll_hw_state, DPLL_ID_PCH_PLL_A, DPLL_ID_PCH_PLL_B); } @@ -472,7 +473,10 @@ static bool ibx_get_dpll(struct intel_atomic_state *state, return false; /* reference the pll */ - intel_reference_shared_dpll(pll, crtc_state); + intel_reference_shared_dpll(state, crtc, + pll, &crtc_state->dpll_hw_state); + + crtc_state->shared_dpll = pll; return true; } @@ -791,8 +795,12 @@ hsw_ddi_calculate_wrpll(int clock /* in Hz */, *r2_out = best.r2; } -static struct intel_shared_dpll *hsw_ddi_hdmi_get_dpll(struct intel_crtc_state *crtc_state) +static struct intel_shared_dpll * +hsw_ddi_hdmi_get_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc) { + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); struct intel_shared_dpll *pll; u32 val; unsigned int p, n2, r2; @@ -805,7 +813,8 @@ static struct intel_shared_dpll *hsw_ddi_hdmi_get_dpll(struct intel_crtc_state * crtc_state->dpll_hw_state.wrpll = val; - pll = intel_find_shared_dpll(crtc_state, + pll = intel_find_shared_dpll(state, crtc, + &crtc_state->dpll_hw_state, DPLL_ID_WRPLL1, DPLL_ID_WRPLL2); if (!pll) @@ -857,7 +866,7 @@ static bool hsw_get_dpll(struct intel_atomic_state *state, sizeof(crtc_state->dpll_hw_state)); if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) { - pll = hsw_ddi_hdmi_get_dpll(crtc_state); + pll = hsw_ddi_hdmi_get_dpll(state, crtc); } else if (intel_crtc_has_dp_encoder(crtc_state)) { pll = hsw_ddi_dp_get_dpll(crtc_state); } else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG)) { @@ -867,7 +876,8 @@ static bool hsw_get_dpll(struct intel_atomic_state *state, crtc_state->dpll_hw_state.spll = SPLL_PLL_ENABLE | SPLL_FREQ_1350MHz | SPLL_REF_MUXED_SSC; - pll = intel_find_shared_dpll(crtc_state, + pll = intel_find_shared_dpll(state, crtc, + &crtc_state->dpll_hw_state, DPLL_ID_SPLL, DPLL_ID_SPLL); } else { return false; @@ -876,7 +886,10 @@ static bool hsw_get_dpll(struct intel_atomic_state *state, if (!pll) return false; - intel_reference_shared_dpll(pll, crtc_state); + intel_reference_shared_dpll(state, crtc, + pll, &crtc_state->dpll_hw_state); + + crtc_state->shared_dpll = pll; return true; } @@ -1437,17 +1450,22 @@ static bool skl_get_dpll(struct intel_atomic_state *state, } if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) - pll = intel_find_shared_dpll(crtc_state, + pll = intel_find_shared_dpll(state, crtc, + &crtc_state->dpll_hw_state, DPLL_ID_SKL_DPLL0, DPLL_ID_SKL_DPLL0); else - pll = intel_find_shared_dpll(crtc_state, + pll = intel_find_shared_dpll(state, crtc, + &crtc_state->dpll_hw_state, DPLL_ID_SKL_DPLL1, DPLL_ID_SKL_DPLL3); if (!pll) return false; - intel_reference_shared_dpll(pll, crtc_state); + intel_reference_shared_dpll(state, crtc, + pll, &crtc_state->dpll_hw_state); + + crtc_state->shared_dpll = pll; return true; } @@ -1880,7 +1898,10 @@ static bool bxt_get_dpll(struct intel_atomic_state *state, DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n", crtc->base.base.id, crtc->base.name, pll->info->name); - intel_reference_shared_dpll(pll, crtc_state); + intel_reference_shared_dpll(state, crtc, + pll, &crtc_state->dpll_hw_state); + + crtc_state->shared_dpll = pll; return true; } @@ -2395,7 +2416,8 @@ static bool cnl_get_dpll(struct intel_atomic_state *state, return false; } - pll = intel_find_shared_dpll(crtc_state, + pll = intel_find_shared_dpll(state, crtc, + &crtc_state->dpll_hw_state, DPLL_ID_SKL_DPLL0, DPLL_ID_SKL_DPLL2); if (!pll) { @@ -2403,7 +2425,10 @@ static bool cnl_get_dpll(struct intel_atomic_state *state, return false; } - intel_reference_shared_dpll(pll, crtc_state); + intel_reference_shared_dpll(state, crtc, + pll, &crtc_state->dpll_hw_state); + + crtc_state->shared_dpll = pll; return true; } @@ -2545,7 +2570,8 @@ static bool icl_calc_tbt_pll(struct intel_crtc_state *crtc_state, } static bool icl_calc_dpll_state(struct intel_crtc_state *crtc_state, - struct intel_encoder *encoder) + struct intel_encoder *encoder, + struct intel_dpll_hw_state *pll_state) { struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); u32 cfgcr0, cfgcr1; @@ -2572,11 +2598,10 @@ static bool icl_calc_dpll_state(struct intel_crtc_state *crtc_state, DPLL_CFGCR1_PDIV(pll_params.pdiv) | DPLL_CFGCR1_CENTRAL_FREQ_8400; - memset(&crtc_state->dpll_hw_state, 0, - sizeof(crtc_state->dpll_hw_state)); + memset(pll_state, 0, sizeof(*pll_state)); - crtc_state->dpll_hw_state.cfgcr0 = cfgcr0; - crtc_state->dpll_hw_state.cfgcr1 = cfgcr1; + pll_state->cfgcr0 = cfgcr0; + pll_state->cfgcr1 = cfgcr1; return true; } @@ -2666,10 +2691,10 @@ static bool icl_mg_pll_find_divisors(int clock_khz, bool is_dp, bool use_ssc, * The specification for this function uses real numbers, so the math had to be * adapted to integer-only calculation, that's why it looks so different. */ -static bool icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state) +static bool icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state, + struct intel_dpll_hw_state *pll_state) { struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); - struct intel_dpll_hw_state *pll_state = &crtc_state->dpll_hw_state; int refclk_khz = dev_priv->cdclk.hw.ref; int clock = crtc_state->port_clock; u32 dco_khz, m1div, m2div_int, m2div_rem, m2div_frac; @@ -2847,7 +2872,8 @@ static bool icl_get_dplls(struct intel_atomic_state *state, if (intel_port_is_combophy(dev_priv, port)) { min = DPLL_ID_ICL_DPLL0; max = DPLL_ID_ICL_DPLL1; - ret = icl_calc_dpll_state(crtc_state, encoder); + ret = icl_calc_dpll_state(crtc_state, encoder, + &crtc_state->dpll_hw_state); } else if (intel_port_is_tc(dev_priv, port)) { if (encoder->type == INTEL_OUTPUT_DP_MST) { struct intel_dp_mst_encoder *mst_encoder; @@ -2861,14 +2887,16 @@ static bool icl_get_dplls(struct intel_atomic_state *state, if (intel_dig_port->tc_mode == TC_PORT_TBT_ALT) { min = DPLL_ID_ICL_TBTPLL; max = min; - ret = icl_calc_dpll_state(crtc_state, encoder); + ret = icl_calc_dpll_state(crtc_state, encoder, + &crtc_state->dpll_hw_state); } else { enum tc_port tc_port; tc_port = intel_port_to_tc(dev_priv, port); min = icl_tc_port_to_pll_id(tc_port); max = min; - ret = icl_calc_mg_pll_state(crtc_state); + ret = icl_calc_mg_pll_state(crtc_state, + &crtc_state->dpll_hw_state); } } else { MISSING_CASE(port); @@ -2881,13 +2909,18 @@ static bool icl_get_dplls(struct intel_atomic_state *state, } - pll = intel_find_shared_dpll(crtc_state, min, max); + pll = intel_find_shared_dpll(state, crtc, + &crtc_state->dpll_hw_state, + min, max); if (!pll) { DRM_DEBUG_KMS("No PLL selected\n"); return false; } - intel_reference_shared_dpll(pll, crtc_state); + intel_reference_shared_dpll(state, crtc, + pll, &crtc_state->dpll_hw_state); + + crtc_state->shared_dpll = pll; return true; } -- cgit v1.2.3 From 726ca99666dba067ac8fad32bed9d3efcfc57f9d Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 28 Jun 2019 17:36:30 +0300 Subject: drm/i915/icl: Split getting the DPLLs to port type specific functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For clarity factor out the combo PHY and TypeC PHY specific code from icl_get_dplls() into their own functions. No functional changes. Cc: Ville Syrjälä Cc: Daniel Vetter Cc: Maarten Lankhorst Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20190628143635.22066-19-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 100 +++++++++++++++++--------- 1 file changed, 66 insertions(+), 34 deletions(-) (limited to 'drivers/gpu/drm/i915/display/intel_dpll_mgr.c') diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 14bbab45836d..85c38eed93a8 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -2856,51 +2856,66 @@ static bool icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state, return true; } -static bool icl_get_dplls(struct intel_atomic_state *state, - struct intel_crtc *crtc, - struct intel_encoder *encoder) +static bool icl_get_combo_phy_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) +{ + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + struct intel_shared_dpll *pll; + + if (!icl_calc_dpll_state(crtc_state, encoder, + &crtc_state->dpll_hw_state)) { + DRM_DEBUG_KMS("Could not calculate combo PHY PLL state.\n"); + + return false; + } + + pll = intel_find_shared_dpll(state, crtc, &crtc_state->dpll_hw_state, + DPLL_ID_ICL_DPLL0, + DPLL_ID_ICL_DPLL1); + if (!pll) { + DRM_DEBUG_KMS("No combo PHY PLL found for port %c\n", + port_name(encoder->port)); + return false; + } + + intel_reference_shared_dpll(state, crtc, + pll, &crtc_state->dpll_hw_state); + + crtc_state->shared_dpll = pll; + + return true; +} + +static bool icl_get_tc_phy_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - struct intel_digital_port *intel_dig_port; + enum tc_port tc_port = intel_port_to_tc(dev_priv, encoder->port); + struct intel_digital_port *dig_port; struct intel_shared_dpll *pll; - enum port port = encoder->port; enum intel_dpll_id min, max; bool ret; - if (intel_port_is_combophy(dev_priv, port)) { - min = DPLL_ID_ICL_DPLL0; - max = DPLL_ID_ICL_DPLL1; + if (encoder->type == INTEL_OUTPUT_DP_MST) + dig_port = enc_to_mst(&encoder->base)->primary; + else + dig_port = enc_to_dig_port(&encoder->base); + + if (dig_port->tc_mode == TC_PORT_TBT_ALT) { + min = DPLL_ID_ICL_TBTPLL; + max = min; ret = icl_calc_dpll_state(crtc_state, encoder, &crtc_state->dpll_hw_state); - } else if (intel_port_is_tc(dev_priv, port)) { - if (encoder->type == INTEL_OUTPUT_DP_MST) { - struct intel_dp_mst_encoder *mst_encoder; - - mst_encoder = enc_to_mst(&encoder->base); - intel_dig_port = mst_encoder->primary; - } else { - intel_dig_port = enc_to_dig_port(&encoder->base); - } - - if (intel_dig_port->tc_mode == TC_PORT_TBT_ALT) { - min = DPLL_ID_ICL_TBTPLL; - max = min; - ret = icl_calc_dpll_state(crtc_state, encoder, - &crtc_state->dpll_hw_state); - } else { - enum tc_port tc_port; - - tc_port = intel_port_to_tc(dev_priv, port); - min = icl_tc_port_to_pll_id(tc_port); - max = min; - ret = icl_calc_mg_pll_state(crtc_state, - &crtc_state->dpll_hw_state); - } } else { - MISSING_CASE(port); - return false; + min = icl_tc_port_to_pll_id(tc_port); + max = min; + ret = icl_calc_mg_pll_state(crtc_state, + &crtc_state->dpll_hw_state); } if (!ret) { @@ -2925,6 +2940,23 @@ static bool icl_get_dplls(struct intel_atomic_state *state, return true; } +static bool icl_get_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = to_i915(state->base.dev); + enum port port = encoder->port; + + if (intel_port_is_combophy(dev_priv, port)) + return icl_get_combo_phy_dpll(state, crtc, encoder); + else if (intel_port_is_tc(dev_priv, port)) + return icl_get_tc_phy_dplls(state, crtc, encoder); + + MISSING_CASE(port); + + return false; +} + static bool mg_pll_get_hw_state(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll, struct intel_dpll_hw_state *hw_state) -- cgit v1.2.3 From eea72c4c2161269a9046184607b71c5cfaabe477 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 28 Jun 2019 17:36:31 +0300 Subject: drm/i915/icl: Reserve all required PLLs for TypeC ports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When enabling a TypeC port we need to reserve all the required PLLs for it, the TBT PLL for TBT-alt and the MG PHY PLL for DP-alt/legacy sinks. We can select the proper PLL for the current port mode from the reserved PLLs only once we selected and locked down the port mode for the whole duration of the port's active state. Resetting and locking down the port mode can in turn happen only during the modeset commit phase once we disabled the given port and the PLL it used. To support the above reserve-and-select PLL semantic we store the reserved PLLs along with their HW state in the CRTC state and provide a way to select the active PLL from these. The selected PLL along with its HW state will be pointed at by crtc_state->shared_dpll/dpll_hw_state as in the case of other port types. Besides reserving all required PLLs no functional changes. v2: - Fix releasing the ICL PLLs, not clearing the PLLs from the old crtc_state. - Init port_dpll to ICL_PORT_DPLL_DEFAULT closer to where port_dpll is used for symmetry with the corresponding ICL_PORT_DPLL_MG_PHY init. (Ville) v3: - Add FIXME: for clearing the ICL port PLLs from the new crtc state. Cc: Ville Syrjälä Cc: Daniel Vetter Cc: Maarten Lankhorst Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20190628143635.22066-20-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 153 +++++++++++++++++++------- 1 file changed, 112 insertions(+), 41 deletions(-) (limited to 'drivers/gpu/drm/i915/display/intel_dpll_mgr.c') diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 85c38eed93a8..bdc7150dbfac 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -2856,34 +2856,79 @@ static bool icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state, return true; } +/** + * icl_set_active_port_dpll - select the active port DPLL for a given CRTC + * @crtc_state: state for the CRTC to select the DPLL for + * @port_dpll_id: the active @port_dpll_id to select + * + * Select the given @port_dpll_id instance from the DPLLs reserved for the + * CRTC. + */ +void icl_set_active_port_dpll(struct intel_crtc_state *crtc_state, + enum icl_port_dpll_id port_dpll_id) +{ + struct icl_port_dpll *port_dpll = + &crtc_state->icl_port_dplls[port_dpll_id]; + + crtc_state->shared_dpll = port_dpll->pll; + crtc_state->dpll_hw_state = port_dpll->hw_state; +} + +static void icl_update_active_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) +{ + struct intel_crtc_state *crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + struct intel_digital_port *primary_port; + enum icl_port_dpll_id port_dpll_id; + + primary_port = encoder->type == INTEL_OUTPUT_DP_MST ? + enc_to_mst(&encoder->base)->primary : + enc_to_dig_port(&encoder->base); + + switch (primary_port->tc_mode) { + case TC_PORT_TBT_ALT: + port_dpll_id = ICL_PORT_DPLL_DEFAULT; + break; + case TC_PORT_DP_ALT: + case TC_PORT_LEGACY: + port_dpll_id = ICL_PORT_DPLL_MG_PHY; + break; + } + + icl_set_active_port_dpll(crtc_state, port_dpll_id); +} + static bool icl_get_combo_phy_dpll(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_encoder *encoder) { struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - struct intel_shared_dpll *pll; + struct icl_port_dpll *port_dpll = + &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; - if (!icl_calc_dpll_state(crtc_state, encoder, - &crtc_state->dpll_hw_state)) { + if (!icl_calc_dpll_state(crtc_state, encoder, &port_dpll->hw_state)) { DRM_DEBUG_KMS("Could not calculate combo PHY PLL state.\n"); return false; } - pll = intel_find_shared_dpll(state, crtc, &crtc_state->dpll_hw_state, - DPLL_ID_ICL_DPLL0, - DPLL_ID_ICL_DPLL1); - if (!pll) { + port_dpll->pll = intel_find_shared_dpll(state, crtc, + &port_dpll->hw_state, + DPLL_ID_ICL_DPLL0, + DPLL_ID_ICL_DPLL1); + if (!port_dpll->pll) { DRM_DEBUG_KMS("No combo PHY PLL found for port %c\n", port_name(encoder->port)); return false; } intel_reference_shared_dpll(state, crtc, - pll, &crtc_state->dpll_hw_state); + port_dpll->pll, &port_dpll->hw_state); - crtc_state->shared_dpll = pll; + icl_update_active_dpll(state, crtc, encoder); return true; } @@ -2895,49 +2940,55 @@ static bool icl_get_tc_phy_dplls(struct intel_atomic_state *state, struct drm_i915_private *dev_priv = to_i915(state->base.dev); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - enum tc_port tc_port = intel_port_to_tc(dev_priv, encoder->port); - struct intel_digital_port *dig_port; - struct intel_shared_dpll *pll; - enum intel_dpll_id min, max; - bool ret; - - if (encoder->type == INTEL_OUTPUT_DP_MST) - dig_port = enc_to_mst(&encoder->base)->primary; - else - dig_port = enc_to_dig_port(&encoder->base); + struct icl_port_dpll *port_dpll; + enum intel_dpll_id dpll_id; - if (dig_port->tc_mode == TC_PORT_TBT_ALT) { - min = DPLL_ID_ICL_TBTPLL; - max = min; - ret = icl_calc_dpll_state(crtc_state, encoder, - &crtc_state->dpll_hw_state); - } else { - min = icl_tc_port_to_pll_id(tc_port); - max = min; - ret = icl_calc_mg_pll_state(crtc_state, - &crtc_state->dpll_hw_state); + port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; + if (!icl_calc_dpll_state(crtc_state, encoder, &port_dpll->hw_state)) { + DRM_DEBUG_KMS("Could not calculate TBT PLL state.\n"); + return false; } - if (!ret) { - DRM_DEBUG_KMS("Could not calculate PLL state.\n"); + port_dpll->pll = intel_find_shared_dpll(state, crtc, + &port_dpll->hw_state, + DPLL_ID_ICL_TBTPLL, + DPLL_ID_ICL_TBTPLL); + if (!port_dpll->pll) { + DRM_DEBUG_KMS("No TBT-ALT PLL found\n"); return false; } + intel_reference_shared_dpll(state, crtc, + port_dpll->pll, &port_dpll->hw_state); - pll = intel_find_shared_dpll(state, crtc, - &crtc_state->dpll_hw_state, - min, max); - if (!pll) { - DRM_DEBUG_KMS("No PLL selected\n"); - return false; + port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_MG_PHY]; + if (!icl_calc_mg_pll_state(crtc_state, &port_dpll->hw_state)) { + DRM_DEBUG_KMS("Could not calculate MG PHY PLL state.\n"); + goto err_unreference_tbt_pll; } + dpll_id = icl_tc_port_to_pll_id(intel_port_to_tc(dev_priv, + encoder->port)); + port_dpll->pll = intel_find_shared_dpll(state, crtc, + &port_dpll->hw_state, + dpll_id, + dpll_id); + if (!port_dpll->pll) { + DRM_DEBUG_KMS("No MG PHY PLL found\n"); + goto err_unreference_tbt_pll; + } intel_reference_shared_dpll(state, crtc, - pll, &crtc_state->dpll_hw_state); + port_dpll->pll, &port_dpll->hw_state); - crtc_state->shared_dpll = pll; + icl_update_active_dpll(state, crtc, encoder); return true; + +err_unreference_tbt_pll: + port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; + intel_unreference_shared_dpll(state, crtc, port_dpll->pll); + + return false; } static bool icl_get_dplls(struct intel_atomic_state *state, @@ -2957,6 +3008,26 @@ static bool icl_get_dplls(struct intel_atomic_state *state, return false; } +static void icl_put_dplls(struct intel_atomic_state *state, + struct intel_crtc *crtc) +{ + struct intel_crtc_state *crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + enum icl_port_dpll_id id; + + for (id = ICL_PORT_DPLL_DEFAULT; id < ICL_PORT_DPLL_COUNT; id++) { + struct icl_port_dpll *port_dpll = + &crtc_state->icl_port_dplls[id]; + + if (!port_dpll->pll) + continue; + + intel_unreference_shared_dpll(state, crtc, port_dpll->pll); + + /* FIXME: Clear the icl_port_dplls from the new crtc state */ + } +} + static bool mg_pll_get_hw_state(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll, struct intel_dpll_hw_state *hw_state) @@ -3330,7 +3401,7 @@ static const struct dpll_info icl_plls[] = { static const struct intel_dpll_mgr icl_pll_mgr = { .dpll_info = icl_plls, .get_dplls = icl_get_dplls, - .put_dplls = intel_put_dpll, + .put_dplls = icl_put_dplls, .dump_hw_state = icl_dump_hw_state, }; @@ -3343,7 +3414,7 @@ static const struct dpll_info ehl_plls[] = { static const struct intel_dpll_mgr ehl_pll_mgr = { .dpll_info = ehl_plls, .get_dplls = icl_get_dplls, - .put_dplls = intel_put_dpll, + .put_dplls = icl_put_dplls, .dump_hw_state = icl_dump_hw_state, }; -- cgit v1.2.3 From 24a7bfe0c2d7aec06956d48808cdfe2756f618ad Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 28 Jun 2019 17:36:32 +0300 Subject: drm/i915: Keep the TypeC port mode fixed when the port is active MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The TypeC port mode needs to stay fixed whenever the port is active. Do that by introducing a tc_link_refcount to account for active ports, avoiding changing the port mode if a reference is held. During the modeset commit phase we also have to reset the port mode and update the active PLL reflecting the new port mode. We can do this only once the port and its old PLL has been already disabled. Add the new encoder update_prepare/complete hooks that are called around the whole enabling sequence. The TypeC specific hooks of these will reset the port mode, update the active PLL if the port will be active and ensure that the port mode will stay fixed for the duration of the whole enabling sequence by holding a tc_link_refcount. During the port enabling, the pre_pll_enable/post_pll_disable hooks will take/release a tc_link_refcount to ensure the port mode stays fixed while the port is active. Changing the port mode should also be avoided during connector detection and AUX transfers if the port is active, we'll do that by checking the port's tc_link_refcount. When resetting the port mode we also have to take into account the maximum lanes provided by the FIA. It's guaranteed to be 4 in TBT-alt and legacy modes, but there may be less lanes available in DP-alt mode, in which case we have to fall back to TBT-alt mode. While at it also update icl_tc_phy_connect()'s code comment, reflecting the current way of switching the port mode. v2: - Add the update_prepare/complete hooks to the encoder instead of the connector. (Ville) - Simplify intel_connector_needs_modeset() by removing redundant if. (Ville) v3: - Fix sparse warning, marking static functions as such. v4: - Rebase on drm-tip. Cc: Ville Syrjälä Cc: Daniel Vetter Cc: Maarten Lankhorst Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20190628143635.22066-21-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 28 ++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/display/intel_dpll_mgr.c') diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index bdc7150dbfac..76a2c879efc2 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -1939,7 +1939,9 @@ struct intel_dpll_mgr { struct intel_encoder *encoder); void (*put_dplls)(struct intel_atomic_state *state, struct intel_crtc *crtc); - + void (*update_active_dpll)(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder); void (*dump_hw_state)(struct drm_i915_private *dev_priv, const struct intel_dpll_hw_state *hw_state); }; @@ -3402,6 +3404,7 @@ static const struct intel_dpll_mgr icl_pll_mgr = { .dpll_info = icl_plls, .get_dplls = icl_get_dplls, .put_dplls = icl_put_dplls, + .update_active_dpll = icl_update_active_dpll, .dump_hw_state = icl_dump_hw_state, }; @@ -3526,6 +3529,29 @@ void intel_release_shared_dplls(struct intel_atomic_state *state, dpll_mgr->put_dplls(state, crtc); } +/** + * intel_update_active_dpll - update the active DPLL for a CRTC/encoder + * @state: atomic state + * @crtc: the CRTC for which to update the active DPLL + * @encoder: encoder determining the type of port DPLL + * + * Update the active DPLL for the given @crtc/@encoder in @crtc's atomic state, + * from the port DPLLs reserved previously by intel_reserve_shared_dplls(). The + * DPLL selected will be based on the current mode of the encoder's port. + */ +void intel_update_active_dpll(struct intel_atomic_state *state, + struct intel_crtc *crtc, + struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + const struct intel_dpll_mgr *dpll_mgr = dev_priv->dpll_mgr; + + if (WARN_ON(!dpll_mgr)) + return; + + dpll_mgr->update_active_dpll(state, crtc, encoder); +} + /** * intel_shared_dpll_dump_hw_state - write hw_state to dmesg * @dev_priv: i915 drm device -- cgit v1.2.3 From 8e9ecb3e1e3366559cd4ed5ab698c391f8236a37 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 2 Jul 2019 15:09:50 +0100 Subject: drm/i915/display: Handle lost primary_port across suspend icl-dsi is dying on suspend/resume at RIP: 0010:icl_update_active_dpll+0x2c/0xa0 [i915] which appears due to the loss of the time primary_port across suspend. Protect against the potential NULL dereference by assuming ICL_PORT_DPLL_DEFAULT unless the port is actively specified otherwise. Fixes: 24a7bfe0c2d7 ("drm/i915: Keep the TypeC port mode fixed when the port is active") Signed-off-by: Chris Wilson Reviewed-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20190702140950.7069-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/i915/display/intel_dpll_mgr.c') diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 76a2c879efc2..f953971e7c3b 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -2883,21 +2883,16 @@ static void icl_update_active_dpll(struct intel_atomic_state *state, struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); struct intel_digital_port *primary_port; - enum icl_port_dpll_id port_dpll_id; + enum icl_port_dpll_id port_dpll_id = ICL_PORT_DPLL_DEFAULT; primary_port = encoder->type == INTEL_OUTPUT_DP_MST ? enc_to_mst(&encoder->base)->primary : enc_to_dig_port(&encoder->base); - switch (primary_port->tc_mode) { - case TC_PORT_TBT_ALT: - port_dpll_id = ICL_PORT_DPLL_DEFAULT; - break; - case TC_PORT_DP_ALT: - case TC_PORT_LEGACY: + if (primary_port && + (primary_port->tc_mode == TC_PORT_DP_ALT || + primary_port->tc_mode == TC_PORT_LEGACY)) port_dpll_id = ICL_PORT_DPLL_MG_PHY; - break; - } icl_set_active_port_dpll(crtc_state, port_dpll_id); } -- cgit v1.2.3 From eef037ea02809afd4d21e204acf27d3bd1525829 Mon Sep 17 00:00:00 2001 From: Vivek Kasireddy Date: Wed, 3 Jul 2019 16:03:53 -0700 Subject: drm/i915/ehl: Add support for DPLL4 (v10) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds support for DPLL4 on EHL that include the following restrictions: - DPLL4 cannot be used with DDIA (combo port A internal eDP usage). DPLL4 can be used with other DDIs, including DDID (combo port A external usage). - DPLL4 cannot be enabled when DC5 or DC6 are enabled. - The DPLL4 enable, lock, power enabled, and power state are connected to the MGPLL1_ENABLE register. v2: (suggestions from Bob Paauwe) - Rework ehl_get_dpll() function to call intel_find_shared_dpll() and iterate twice: once for Combo plls and once for MG plls. - Use MG pll funcs for DPLL4 instead of creating new ones and modify mg_pll_enable to include the restrictions for EHL. v3: Fix compilation error v4: (suggestions from Lucas and Ville) - Treat DPLL4 as a combo phy PLL and not as MG PLL - Disable DC states when this DPLL is being enabled - Reuse icl_get_dpll instead of creating a separate one for EHL v5: (suggestion from Ville) - Refcount the DC OFF power domains during the enabling and disabling of this DPLL. v6: rebase v7: (suggestion from Imre) - Add a new power domain instead of iterating over the domains assoicated with DC OFF power well. v8: (Ville and Imre) - Rename POWER_DOMAIN_DPLL4 TO POWER_DOMAIN_DPLL_DC_OFF - Grab a reference in intel_modeset_setup_hw_state() if this DPLL was already enabled perhaps by BIOS. - Check for the port type instead of the encoder v9: (Ville) - Move the block of code that grabs a reference to the power domain POWER_DOMAIN_DPLL_DC_OFF to intel_modeset_readout_hw_state() to ensure that there is a reference present before this DPLL might get disabled. v10: rebase Cc: José Roberto de Souza Cc: Ville Syrjälä Cc: Matt Roper Cc: Imre Deak Signed-off-by: Vivek Kasireddy Reviewed-by: José Roberto de Souza Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20190703230353.24059-1-vivek.kasireddy@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 47 ++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915/display/intel_dpll_mgr.c') diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index f953971e7c3b..67cfe836286e 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -2905,6 +2905,9 @@ static bool icl_get_combo_phy_dpll(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, crtc); struct icl_port_dpll *port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum port port = encoder->port; + bool has_dpll4 = false; if (!icl_calc_dpll_state(crtc_state, encoder, &port_dpll->hw_state)) { DRM_DEBUG_KMS("Could not calculate combo PHY PLL state.\n"); @@ -2912,10 +2915,14 @@ static bool icl_get_combo_phy_dpll(struct intel_atomic_state *state, return false; } + if (IS_ELKHARTLAKE(dev_priv) && port != PORT_A) + has_dpll4 = true; + port_dpll->pll = intel_find_shared_dpll(state, crtc, &port_dpll->hw_state, DPLL_ID_ICL_DPLL0, - DPLL_ID_ICL_DPLL1); + has_dpll4 ? DPLL_ID_EHL_DPLL4 + : DPLL_ID_ICL_DPLL1); if (!port_dpll->pll) { DRM_DEBUG_KMS("No combo PHY PLL found for port %c\n", port_name(encoder->port)); @@ -3119,8 +3126,14 @@ static bool combo_pll_get_hw_state(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll, struct intel_dpll_hw_state *hw_state) { - return icl_pll_get_hw_state(dev_priv, pll, hw_state, - CNL_DPLL_ENABLE(pll->info->id)); + i915_reg_t enable_reg = CNL_DPLL_ENABLE(pll->info->id); + + if (IS_ELKHARTLAKE(dev_priv) && + pll->info->id == DPLL_ID_EHL_DPLL4) { + enable_reg = MG_PLL_ENABLE(0); + } + + return icl_pll_get_hw_state(dev_priv, pll, hw_state, enable_reg); } static bool tbt_pll_get_hw_state(struct drm_i915_private *dev_priv, @@ -3231,6 +3244,19 @@ static void combo_pll_enable(struct drm_i915_private *dev_priv, { i915_reg_t enable_reg = CNL_DPLL_ENABLE(pll->info->id); + if (IS_ELKHARTLAKE(dev_priv) && + pll->info->id == DPLL_ID_EHL_DPLL4) { + enable_reg = MG_PLL_ENABLE(0); + + /* + * We need to disable DC states when this DPLL is enabled. + * This can be done by taking a reference on DPLL4 power + * domain. + */ + pll->wakeref = intel_display_power_get(dev_priv, + POWER_DOMAIN_DPLL_DC_OFF); + } + icl_pll_power_enable(dev_priv, pll, enable_reg); icl_dpll_write(dev_priv, pll); @@ -3326,7 +3352,19 @@ static void icl_pll_disable(struct drm_i915_private *dev_priv, static void combo_pll_disable(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll) { - icl_pll_disable(dev_priv, pll, CNL_DPLL_ENABLE(pll->info->id)); + i915_reg_t enable_reg = CNL_DPLL_ENABLE(pll->info->id); + + if (IS_ELKHARTLAKE(dev_priv) && + pll->info->id == DPLL_ID_EHL_DPLL4) { + enable_reg = MG_PLL_ENABLE(0); + icl_pll_disable(dev_priv, pll, enable_reg); + + intel_display_power_put(dev_priv, POWER_DOMAIN_DPLL_DC_OFF, + pll->wakeref); + return; + } + + icl_pll_disable(dev_priv, pll, enable_reg); } static void tbt_pll_disable(struct drm_i915_private *dev_priv, @@ -3406,6 +3444,7 @@ static const struct intel_dpll_mgr icl_pll_mgr = { static const struct dpll_info ehl_plls[] = { { "DPLL 0", &combo_pll_funcs, DPLL_ID_ICL_DPLL0, 0 }, { "DPLL 1", &combo_pll_funcs, DPLL_ID_ICL_DPLL1, 0 }, + { "DPLL 4", &combo_pll_funcs, DPLL_ID_EHL_DPLL4, 0 }, { }, }; -- cgit v1.2.3 From 5c28e3a567fed9c22cb79f01294b1aaefee344fd Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 8 Jul 2019 17:07:34 +0300 Subject: drm/i915: Clear the shared PLL from the put_dplls() hook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For symmetry with the get_dplls() hook which sets the shared_dpll pointer clear the same pointer from the put_dplls() hook. While at it also constify the old crtc state. v2: - Constify the old crtc state. (Ville) Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20190708140735.20198-1-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/i915/display/intel_dpll_mgr.c') diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 67cfe836286e..5c18f9012062 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -323,13 +323,17 @@ static void intel_unreference_shared_dpll(struct intel_atomic_state *state, static void intel_put_dpll(struct intel_atomic_state *state, struct intel_crtc *crtc) { - struct intel_crtc_state *crtc_state = + const struct intel_crtc_state *old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); + struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + + new_crtc_state->shared_dpll = NULL; - if (!crtc_state->shared_dpll) + if (!old_crtc_state->shared_dpll) return; - intel_unreference_shared_dpll(state, crtc, crtc_state->shared_dpll); + intel_unreference_shared_dpll(state, crtc, old_crtc_state->shared_dpll); } /** @@ -3015,13 +3019,17 @@ static bool icl_get_dplls(struct intel_atomic_state *state, static void icl_put_dplls(struct intel_atomic_state *state, struct intel_crtc *crtc) { - struct intel_crtc_state *crtc_state = + const struct intel_crtc_state *old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); + struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); enum icl_port_dpll_id id; + new_crtc_state->shared_dpll = NULL; + for (id = ICL_PORT_DPLL_DEFAULT; id < ICL_PORT_DPLL_COUNT; id++) { - struct icl_port_dpll *port_dpll = - &crtc_state->icl_port_dplls[id]; + const struct icl_port_dpll *port_dpll = + &old_crtc_state->icl_port_dplls[id]; if (!port_dpll->pll) continue; -- cgit v1.2.3 From f7ddc80ecb0e19e2c706747d1540b7699b4198d3 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 8 Jul 2019 17:07:35 +0300 Subject: drm/i915/icl: Clear the shared port PLLs from the new crtc state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For consistency clear the icl_port_dplls from the new crtc state, when releasing the DPLLs from the old crtc state. Leaving them set could result in releasing the same PLLs multiple times from the same CRTC state incorrectly (if the same CRTC was first used for a TypeC port then for a combo PHY port). Leaving the stale pointers behind happens not to cause a problem atm (since the incorrect releasing will be a NOP), but we need to fix that for consistency. Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20190708140735.20198-2-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915/display/intel_dpll_mgr.c') diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 5c18f9012062..30d7500eb66c 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -3028,15 +3028,17 @@ static void icl_put_dplls(struct intel_atomic_state *state, new_crtc_state->shared_dpll = NULL; for (id = ICL_PORT_DPLL_DEFAULT; id < ICL_PORT_DPLL_COUNT; id++) { - const struct icl_port_dpll *port_dpll = + const struct icl_port_dpll *old_port_dpll = &old_crtc_state->icl_port_dplls[id]; + struct icl_port_dpll *new_port_dpll = + &new_crtc_state->icl_port_dplls[id]; - if (!port_dpll->pll) - continue; + new_port_dpll->pll = NULL; - intel_unreference_shared_dpll(state, crtc, port_dpll->pll); + if (!old_port_dpll->pll) + continue; - /* FIXME: Clear the icl_port_dplls from the new crtc state */ + intel_unreference_shared_dpll(state, crtc, old_port_dpll->pll); } } -- cgit v1.2.3 From d8fe2ab6bb283dd9b511ea9bea52874fafd3de61 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 9 Jul 2019 11:39:33 -0700 Subject: drm/i915: Transition port type checks to phy checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Transition the remaining uses of intel_port_is_* over to the equivalent intel_phy_is_* functions and drop the port functions. v5: Fix a call in a debug function that's only called when CONFIG_DRM_I915_DEBUG_RUNTIME_PM is on. (CI) Cc: José Roberto de Souza Cc: Lucas De Marchi Signed-off-by: Matt Roper Reviewed-by: Ville Syrjälä Reviewed-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20190709183934.445-5-matthew.d.roper@intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915/display/intel_dpll_mgr.c') diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 30d7500eb66c..fc6f3c52629a 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -2584,7 +2584,8 @@ static bool icl_calc_dpll_state(struct intel_crtc_state *crtc_state, struct skl_wrpll_params pll_params = { 0 }; bool ret; - if (intel_port_is_tc(dev_priv, encoder->port)) + if (intel_phy_is_tc(dev_priv, intel_port_to_phy(dev_priv, + encoder->port))) ret = icl_calc_tbt_pll(crtc_state, &pll_params); else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) || intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) @@ -3004,14 +3005,14 @@ static bool icl_get_dplls(struct intel_atomic_state *state, struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); - enum port port = encoder->port; + enum phy phy = intel_port_to_phy(dev_priv, encoder->port); - if (intel_port_is_combophy(dev_priv, port)) + if (intel_phy_is_combo(dev_priv, phy)) return icl_get_combo_phy_dpll(state, crtc, encoder); - else if (intel_port_i