All of lore.kernel.org
 help / color / mirror / Atom feed
From: Imre Deak <imre.deak@intel.com>
To: intel-gfx@lists.freedesktop.org
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Subject: [PATCH v3 19/23] drm/i915/icl: Reserve all required PLLs for TypeC ports
Date: Fri, 28 Jun 2019 17:36:31 +0300	[thread overview]
Message-ID: <20190628143635.22066-20-imre.deak@intel.com> (raw)
In-Reply-To: <20190628143635.22066-1-imre.deak@intel.com>

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ä <ville.syrjala@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c  |  11 +-
 drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 153 +++++++++++++-----
 drivers/gpu/drm/i915/display/intel_dpll_mgr.h |   9 ++
 drivers/gpu/drm/i915/intel_drv.h              |   9 ++
 4 files changed, 140 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index e38acb860fb1..77af43ac64fd 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -9958,6 +9958,7 @@ static void icelake_get_ddi_pll(struct drm_i915_private *dev_priv,
 				enum port port,
 				struct intel_crtc_state *pipe_config)
 {
+	enum icl_port_dpll_id port_dpll_id;
 	enum intel_dpll_id id;
 	u32 temp;
 
@@ -9965,22 +9966,28 @@ static void icelake_get_ddi_pll(struct drm_i915_private *dev_priv,
 		temp = I915_READ(DPCLKA_CFGCR0_ICL) &
 		       DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
 		id = temp >> DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port);
+		port_dpll_id = ICL_PORT_DPLL_DEFAULT;
 	} else if (intel_port_is_tc(dev_priv, port)) {
 		u32 clk_sel = I915_READ(DDI_CLK_SEL(port)) & DDI_CLK_SEL_MASK;
 
 		if (clk_sel == DDI_CLK_SEL_MG) {
 			id = icl_tc_port_to_pll_id(intel_port_to_tc(dev_priv,
 								    port));
+			port_dpll_id = ICL_PORT_DPLL_MG_PHY;
 		} else {
 			WARN_ON(clk_sel < DDI_CLK_SEL_TBT_162);
 			id = DPLL_ID_ICL_TBTPLL;
+			port_dpll_id = ICL_PORT_DPLL_DEFAULT;
 		}
 	} else {
 		WARN(1, "Invalid port %x\n", port);
 		return;
 	}
 
-	pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id);
+	pipe_config->icl_port_dplls[port_dpll_id].pll =
+		intel_get_shared_dpll_by_id(dev_priv, id);
+
+	icl_set_active_port_dpll(pipe_config, port_dpll_id);
 }
 
 static void bxt_get_ddi_pll(struct drm_i915_private *dev_priv,
@@ -12119,6 +12126,8 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
 	saved_state->scaler_state = crtc_state->scaler_state;
 	saved_state->shared_dpll = crtc_state->shared_dpll;
 	saved_state->dpll_hw_state = crtc_state->dpll_hw_state;
+	memcpy(saved_state->icl_port_dplls, crtc_state->icl_port_dplls,
+	       sizeof(saved_state->icl_port_dplls));
 	saved_state->crc_enabled = crtc_state->crc_enabled;
 	if (IS_G4X(dev_priv) ||
 	    IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
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,
 };
 
diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h
index 16ddab138574..579f2ceafba3 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h
+++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h
@@ -141,6 +141,13 @@ enum intel_dpll_id {
 };
 #define I915_NUM_PLLS 7
 
+enum icl_port_dpll_id {
+	ICL_PORT_DPLL_DEFAULT,
+	ICL_PORT_DPLL_MG_PHY,
+
+	ICL_PORT_DPLL_COUNT,
+};
+
 struct intel_dpll_hw_state {
 	/* i9xx, pch plls */
 	u32 dpll;
@@ -337,6 +344,8 @@ bool intel_reserve_shared_dplls(struct intel_atomic_state *state,
 				struct intel_encoder *encoder);
 void intel_release_shared_dplls(struct intel_atomic_state *state,
 				struct intel_crtc *crtc);
+void icl_set_active_port_dpll(struct intel_crtc_state *crtc_state,
+			      enum icl_port_dpll_id port_dpll_id);
 void intel_prepare_shared_dpll(const struct intel_crtc_state *crtc_state);
 void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state);
 void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d9e7d011ed4a..12a102e239c5 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -812,6 +812,15 @@ struct intel_crtc_state {
 	/* Actual register state of the dpll, for shared dpll cross-checking. */
 	struct intel_dpll_hw_state dpll_hw_state;
 
+	/*
+	 * ICL reserved DPLLs for the CRTC/port. The active PLL is selected by
+	 * setting shared_dpll and dpll_hw_state to one of these reserved ones.
+	 */
+	struct icl_port_dpll {
+		struct intel_shared_dpll *pll;
+		struct intel_dpll_hw_state hw_state;
+	} icl_port_dplls[ICL_PORT_DPLL_COUNT];
+
 	/* DSI PLL registers */
 	struct {
 		u32 ctrl, div;
-- 
2.17.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

  parent reply	other threads:[~2019-06-28 14:37 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-06-28 14:36 [PATCH v3 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
2019-06-28 14:36 ` [PATCH v3 01/23] drm/i915/icl: Add support to read out the TBT PLL HW state Imre Deak
2019-06-28 14:36 ` [PATCH v3 02/23] drm/i915: Tune down WARNs about TBT AUX power well enabling Imre Deak
2019-06-28 14:36 ` [PATCH v3 03/23] drm/i915: Move the TypeC port handling code to a separate file Imre Deak
2019-06-28 14:36 ` [PATCH v3 04/23] drm/i915: Sanitize the terminology used for TypeC port modes Imre Deak
2019-06-28 14:36 ` [PATCH v3 05/23] drm/i915: Don't enable the DDI-IO power in the TypeC TBT-alt mode Imre Deak
2019-06-28 14:36 ` [PATCH v3 06/23] drm/i915: Fix the TBT AUX power well enabling Imre Deak
2019-06-28 14:36 ` [PATCH v3 07/23] drm/i915: Use the correct AUX power domain in TypeC TBT-alt mode Imre Deak
2019-06-28 14:36 ` [PATCH v3 08/23] drm/i915: Unify the TypeC port notation in debug/error messages Imre Deak
2019-06-28 14:36 ` [PATCH v3 09/23] drm/i915: Factor out common parts from TypeC port handling functions Imre Deak
2019-06-28 14:36 ` [PATCH v3 10/23] drm/i915: Wait for TypeC PHY complete flag to clear in safe mode Imre Deak
2019-06-28 14:36 ` [PATCH v3 11/23] drm/i915: Handle the TCCOLD power-down event Imre Deak
2019-06-28 14:36 ` [PATCH v3 12/23] drm/i915: Sanitize the TypeC connect/detect sequences Imre Deak
2019-06-28 14:36 ` [PATCH v3 13/23] drm/i915: Fix the TypeC port mode sanitization during loading/resume Imre Deak
2019-06-28 14:36 ` [PATCH v3 14/23] drm/i915: Keep the TypeC port mode fixed for detect/AUX transfers Imre Deak
2019-06-28 14:36 ` [PATCH v3 15/23] drm/i915: Sanitize the TypeC FIA lane configuration decoding Imre Deak
2019-06-28 14:36 ` [PATCH v3 16/23] drm/i915: Sanitize the shared DPLL reserve/release interface Imre Deak
2019-06-28 14:36 ` [PATCH v3 17/23] drm/i915: Sanitize the shared DPLL find/reference interface Imre Deak
2019-06-28 14:36 ` [PATCH v3 18/23] drm/i915/icl: Split getting the DPLLs to port type specific functions Imre Deak
2019-06-28 14:36 ` Imre Deak [this message]
2019-06-28 14:36 ` [PATCH v3 20/23] drm/i915: Keep the TypeC port mode fixed when the port is active Imre Deak
2019-06-28 14:36 ` [PATCH v3 21/23] drm/i915: Add state verification for the TypeC port mode Imre Deak
2019-06-28 14:36 ` [PATCH v3 22/23] drm/i915: Remove unneeded disconnect in TypeC legacy " Imre Deak
2019-06-28 14:36 ` [PATCH v3 23/23] drm/i915: WARN about invalid lane reversal in TBT-alt/DP-alt modes Imre Deak
2019-06-28 14:54 ` ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Fix TypeC port mode switching (rev8) Patchwork
2019-06-28 15:02 ` ✗ Fi.CI.SPARSE: " Patchwork
2019-06-28 19:04 ` ✓ Fi.CI.BAT: success " Patchwork
2019-06-29  7:03 ` ✓ Fi.CI.IGT: " Patchwork
2019-07-01 13:34   ` Imre Deak

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190628143635.22066-20-imre.deak@intel.com \
    --to=imre.deak@intel.com \
    --cc=daniel.vetter@ffwll.ch \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.