All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/23] drm/i915: Fix TypeC port mode switching
@ 2019-06-04 14:58 Imre Deak
  2019-06-04 14:58 ` [PATCH 01/23] drm/i915/icl: Add support to read out the TBT PLL HW state Imre Deak
                   ` (30 more replies)
  0 siblings, 31 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-04 14:58 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni, Daniel Vetter, Lucas De Marchi

Atm we switch the TypeC port mode upon receiving an HPD interrupt.
That's unsafe since the port could be active (after a modeset) or there
could be other users that depend on the port mode to stay fixed. To make
the mode switching robust add a TypeC port mode refcounting reflecting
the active state of the port and locking for any other users of it
(connector detection/AUX transfers).

The port mode will be reset if needed, whenever the TypeC lock is taken
and the port is inactive. During a modeset resetting the port and
selecting the proper PLL for the new mode must happen during the atomic
commit phase, after the port and its PLL got disabled. For that we need
to reserve both the TBT and MG PHY PLLs for the port and select the
correct one after the port mode got reset/locked down for the duration
of the port's active state.

The patchset has a few refactorings getting to the state described above
gradually, so that reviewing the actual changes is somewhat easier. I
also pushed the whole lot to [1].

The patchset also has a few fixes mostly related to the TBT-alt mode.

[1] https://github.com/ideak/linux/commits/typec-mode-switch

Cc: Manasi Navare <manasi.d.navare@intel.com>
Cc: José Roberto de Souza <jose.souza@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Animesh Manna <animesh.manna@intel.com>
Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Lucas De Marchi <lucas.demarchi@intel.com>
Cc: Anusha Srivatsa <anusha.srivatsa@intel.com>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>

Imre Deak (23):
  drm/i915/icl: Add support to read out the TBT PLL HW state
  drm/i915: Tune down WARNs about TBT AUX power well enabling
  drm/i915: Move the TypeC port handling code to a separate file
  drm/i915: Sanitize the terminology used for TypeC port modes
  drm/i915: Don't enable the DDI-IO power in the TypeC TBT-alt mode
  drm/i915: Fix the TBT AUX power well enabling
  drm/i915: Use the correct AUX power domain in TypeC TBT-alt mode
  drm/i915: Unify the TypeC port notation in debug/error messages
  drm/i915: Factor out common parts from TypeC port handling functions
  drm/i915: Wait for TypeC PHY complete flag to clear in safe mode
  drm/i915: Handle the TCCOLD power-down event
  drm/i915: Sanitize the TypeC connect/detect sequences
  drm/i915: Fix the TypeC port mode sanitization during loading/resume
  drm/i915: Keep the TypeC port mode fixed for detect/AUX transfers
  drm/i915: Sanitize the TypeC FIA lane configuration decoding
  drm/i915: Sanitize the shared DPLL reserve/release interface
  drm/i915: Sanitize the shared DPLL find/reference interface
  drm/i915/icl: Split getting the DPLLs to port type specific functions
  drm/i915/icl: Reserve all required PLLs for TypeC ports
  drm/i915: Keep the TypeC port mode fixed when the port is active
  drm/i915: Add state verification for the TypeC port mode
  drm/i915: Remove unneeded disconnect in TypeC legacy port mode
  drm/i915: WARN about invalid lane reversal in TBT-alt/DP-alt modes

 drivers/gpu/drm/i915/Makefile              |   3 +-
 drivers/gpu/drm/i915/Makefile.header-test  |   1 +
 drivers/gpu/drm/i915/intel_ddi.c           | 123 ++---
 drivers/gpu/drm/i915/intel_ddi.h           |   7 +
 drivers/gpu/drm/i915/intel_display.c       | 160 ++++++-
 drivers/gpu/drm/i915/intel_display.h       |   7 +-
 drivers/gpu/drm/i915/intel_display_power.c | 111 ++++-
 drivers/gpu/drm/i915/intel_dp.c            | 243 +---------
 drivers/gpu/drm/i915/intel_dp.h            |   2 -
 drivers/gpu/drm/i915/intel_dp_mst.c        |   6 +
 drivers/gpu/drm/i915/intel_dp_mst.h        |   8 +-
 drivers/gpu/drm/i915/intel_dpll_mgr.c      | 524 +++++++++++++++------
 drivers/gpu/drm/i915/intel_dpll_mgr.h      |  25 +-
 drivers/gpu/drm/i915/intel_drv.h           |  21 +-
 drivers/gpu/drm/i915/intel_hdmi.c          |   7 +
 drivers/gpu/drm/i915/intel_tc.c            | 469 ++++++++++++++++++
 drivers/gpu/drm/i915/intel_tc.h            |  27 ++
 17 files changed, 1272 insertions(+), 472 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/intel_tc.c
 create mode 100644 drivers/gpu/drm/i915/intel_tc.h

-- 
2.17.1

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

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [PATCH 01/23] drm/i915/icl: Add support to read out the TBT PLL HW state
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
@ 2019-06-04 14:58 ` Imre Deak
  2019-06-07 17:36   ` Souza, Jose
  2019-06-04 14:58 ` [PATCH 02/23] drm/i915: Tune down WARNs about TBT AUX power well enabling Imre Deak
                   ` (29 subsequent siblings)
  30 siblings, 1 reply; 79+ messages in thread
From: Imre Deak @ 2019-06-04 14:58 UTC (permalink / raw)
  To: intel-gfx; +Cc: Lucas De Marchi, Paulo Zanoni

Add support to read out the TBT PLL HW state.

Cc: Vandita Kulkarni <vandita.kulkarni@intel.com>
Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
Cc: Lucas De Marchi <lucas.demarchi@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index fc47ed0247c5..26474788b7b2 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -9859,13 +9859,20 @@ static void icelake_get_ddi_pll(struct drm_i915_private *dev_priv,
 	enum intel_dpll_id id;
 	u32 temp;
 
-	/* TODO: TBT pll not implemented. */
 	if (intel_port_is_combophy(dev_priv, port)) {
 		temp = I915_READ(DPCLKA_CFGCR0_ICL) &
 		       DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
 		id = temp >> DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port);
 	} else if (intel_port_is_tc(dev_priv, port)) {
-		id = icl_tc_port_to_pll_id(intel_port_to_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));
+		} else {
+			WARN_ON(clk_sel < DDI_CLK_SEL_TBT_162);
+			id = DPLL_ID_ICL_TBTPLL;
+		}
 	} else {
 		WARN(1, "Invalid port %x\n", port);
 		return;
-- 
2.17.1

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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 02/23] drm/i915: Tune down WARNs about TBT AUX power well enabling
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
  2019-06-04 14:58 ` [PATCH 01/23] drm/i915/icl: Add support to read out the TBT PLL HW state Imre Deak
@ 2019-06-04 14:58 ` Imre Deak
  2019-06-07 17:50   ` Souza, Jose
  2019-06-04 14:58 ` [PATCH 03/23] drm/i915: Move the TypeC port handling code to a separate file Imre Deak
                   ` (28 subsequent siblings)
  30 siblings, 1 reply; 79+ messages in thread
From: Imre Deak @ 2019-06-04 14:58 UTC (permalink / raw)
  To: intel-gfx

The HW completion flag for the TBT AUX power well enabling/disabling
gets stuck if the firmware tears down the TBT DP tunnel before the
completion.

We shouldn't complain about the timeout, since it's expected to happen
and doesn't cause further issues. We suppress the disabling timeout
already, do the same for enabling.

Cc: José Roberto de Souza <jose.souza@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_display_power.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display_power.c b/drivers/gpu/drm/i915/intel_display_power.c
index 278a7edc94f5..249a5fa55df6 100644
--- a/drivers/gpu/drm/i915/intel_display_power.c
+++ b/drivers/gpu/drm/i915/intel_display_power.c
@@ -268,11 +268,16 @@ static void hsw_wait_for_power_well_enable(struct drm_i915_private *dev_priv,
 	int pw_idx = power_well->desc->hsw.idx;
 
 	/* Timeout for PW1:10 us, AUX:not specified, other PWs:20 us. */
-	WARN_ON(intel_wait_for_register(&dev_priv->uncore,
-					regs->driver,
-					HSW_PWR_WELL_CTL_STATE(pw_idx),
-					HSW_PWR_WELL_CTL_STATE(pw_idx),
-					1));
+	if (intel_wait_for_register(&dev_priv->uncore,
+				    regs->driver,
+				    HSW_PWR_WELL_CTL_STATE(pw_idx),
+				    HSW_PWR_WELL_CTL_STATE(pw_idx),
+				    1)) {
+		DRM_DEBUG_KMS("%s forced off\n", power_well->desc->name);
+
+		/* An AUX timeout is expected if the TBT DP tunnel is down. */
+		WARN_ON(!power_well->desc->hsw.is_tc_tbt);
+	}
 }
 
 static u32 hsw_power_well_requesters(struct drm_i915_private *dev_priv,
-- 
2.17.1

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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 03/23] drm/i915: Move the TypeC port handling code to a separate file
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
  2019-06-04 14:58 ` [PATCH 01/23] drm/i915/icl: Add support to read out the TBT PLL HW state Imre Deak
  2019-06-04 14:58 ` [PATCH 02/23] drm/i915: Tune down WARNs about TBT AUX power well enabling Imre Deak
@ 2019-06-04 14:58 ` Imre Deak
  2019-06-06  8:42   ` Jani Nikula
  2019-06-07 17:56   ` Souza, Jose
  2019-06-04 14:58 ` [PATCH 04/23] drm/i915: Sanitize the terminology used for TypeC port modes Imre Deak
                   ` (27 subsequent siblings)
  30 siblings, 2 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-04 14:58 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

Move the TypeC port handling functions to a new file for clarity.

While at it:
- s/icl_tc_port_connected()/intel_tc_port_connected()/
  icl_tc_phy_disconnect(), will be unexported later.

- s/intel_dp_get_fia_supported_lane_count()/intel_tc_port_fia_max_lane_count()/
  It's used for HDMI legacy mode too.

- Simplify function interfaces by passing only dig_port to them.

No functional changes.

Cc: Animesh Manna <animesh.manna@intel.com>
Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
Cc: José Roberto de Souza <jose.souza@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/Makefile             |   3 +-
 drivers/gpu/drm/i915/Makefile.header-test |   1 +
 drivers/gpu/drm/i915/intel_ddi.c          |   6 +-
 drivers/gpu/drm/i915/intel_dp.c           | 227 +--------------------
 drivers/gpu/drm/i915/intel_dp.h           |   2 -
 drivers/gpu/drm/i915/intel_tc.c           | 230 ++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_tc.h           |  13 ++
 7 files changed, 252 insertions(+), 230 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/intel_tc.c
 create mode 100644 drivers/gpu/drm/i915/intel_tc.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index c0a7b2994077..74c4d11d83eb 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -171,7 +171,8 @@ i915-y += intel_audio.o \
 	  intel_psr.o \
 	  intel_quirks.o \
 	  intel_sideband.o \
-	  intel_sprite.o
+	  intel_sprite.o \
+	  intel_tc.o
 i915-$(CONFIG_ACPI)		+= intel_acpi.o intel_opregion.o
 i915-$(CONFIG_DRM_FBDEV_EMULATION)	+= intel_fbdev.o
 
diff --git a/drivers/gpu/drm/i915/Makefile.header-test b/drivers/gpu/drm/i915/Makefile.header-test
index 6ef3b647ac65..e80e8e45b09c 100644
--- a/drivers/gpu/drm/i915/Makefile.header-test
+++ b/drivers/gpu/drm/i915/Makefile.header-test
@@ -58,6 +58,7 @@ header_test := \
 	intel_sdvo.h \
 	intel_sideband.h \
 	intel_sprite.h \
+	intel_tc.h \
 	intel_tv.h \
 	intel_uncore.h \
 	intel_vdsc.h \
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 350eaf54f01f..5a1c98438375 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -45,6 +45,7 @@
 #include "intel_lspcon.h"
 #include "intel_panel.h"
 #include "intel_psr.h"
+#include "intel_tc.h"
 #include "intel_vdsc.h"
 
 struct ddi_buf_trans {
@@ -3904,7 +3905,6 @@ static int intel_ddi_compute_config(struct intel_encoder *encoder,
 static void intel_ddi_encoder_suspend(struct intel_encoder *encoder)
 {
 	struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
-	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
 
 	intel_dp_encoder_suspend(encoder);
 
@@ -3914,7 +3914,7 @@ static void intel_ddi_encoder_suspend(struct intel_encoder *encoder)
 	 * even if the sink has disappeared while being suspended.
 	 */
 	if (dig_port->tc_legacy_port)
-		icl_tc_phy_disconnect(i915, dig_port);
+		icl_tc_phy_disconnect(dig_port);
 }
 
 static void intel_ddi_encoder_reset(struct drm_encoder *drm_encoder)
@@ -3936,7 +3936,7 @@ static void intel_ddi_encoder_destroy(struct drm_encoder *encoder)
 	intel_dp_encoder_flush_work(encoder);
 
 	if (intel_port_is_tc(i915, dig_port->base.port))
-		icl_tc_phy_disconnect(i915, dig_port);
+		icl_tc_phy_disconnect(dig_port);
 
 	drm_encoder_cleanup(encoder);
 	kfree(dig_port);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 24b56b2a76c8..b69310bd9914 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -62,6 +62,7 @@
 #include "intel_panel.h"
 #include "intel_psr.h"
 #include "intel_sideband.h"
+#include "intel_tc.h"
 #include "intel_vdsc.h"
 
 #define DP_DPRX_ESI_LEN 14
@@ -211,46 +212,13 @@ static int intel_dp_max_common_rate(struct intel_dp *intel_dp)
 	return intel_dp->common_rates[intel_dp->num_common_rates - 1];
 }
 
-static int intel_dp_get_fia_supported_lane_count(struct intel_dp *intel_dp)
-{
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
-	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
-	intel_wakeref_t wakeref;
-	u32 lane_info;
-
-	if (tc_port == PORT_TC_NONE || dig_port->tc_type != TC_PORT_TYPEC)
-		return 4;
-
-	lane_info = 0;
-	with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref)
-		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
-			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
-				DP_LANE_ASSIGNMENT_SHIFT(tc_port);
-
-	switch (lane_info) {
-	default:
-		MISSING_CASE(lane_info);
-	case 1:
-	case 2:
-	case 4:
-	case 8:
-		return 1;
-	case 3:
-	case 12:
-		return 2;
-	case 15:
-		return 4;
-	}
-}
-
 /* Theoretical max between source and sink */
 static int intel_dp_max_common_lane_count(struct intel_dp *intel_dp)
 {
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 	int source_max = intel_dig_port->max_lanes;
 	int sink_max = drm_dp_max_lane_count(intel_dp->dpcd);
-	int fia_max = intel_dp_get_fia_supported_lane_count(intel_dp);
+	int fia_max = intel_tc_port_fia_max_lane_count(intel_dig_port);
 
 	return min3(source_max, sink_max, fia_max);
 }
@@ -5231,195 +5199,6 @@ static bool icl_combo_port_connected(struct drm_i915_private *dev_priv,
 	return I915_READ(SDEISR) & SDE_DDI_HOTPLUG_ICP(port);
 }
 
-static const char *tc_type_name(enum tc_port_type type)
-{
-	static const char * const names[] = {
-		[TC_PORT_UNKNOWN] = "unknown",
-		[TC_PORT_LEGACY] = "legacy",
-		[TC_PORT_TYPEC] = "typec",
-		[TC_PORT_TBT] = "tbt",
-	};
-
-	if (WARN_ON(type >= ARRAY_SIZE(names)))
-		type = TC_PORT_UNKNOWN;
-
-	return names[type];
-}
-
-static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
-				    struct intel_digital_port *intel_dig_port,
-				    bool is_legacy, bool is_typec, bool is_tbt)
-{
-	enum port port = intel_dig_port->base.port;
-	enum tc_port_type old_type = intel_dig_port->tc_type;
-
-	WARN_ON(is_legacy + is_typec + is_tbt != 1);
-
-	if (is_legacy)
-		intel_dig_port->tc_type = TC_PORT_LEGACY;
-	else if (is_typec)
-		intel_dig_port->tc_type = TC_PORT_TYPEC;
-	else if (is_tbt)
-		intel_dig_port->tc_type = TC_PORT_TBT;
-	else
-		return;
-
-	/* Types are not supposed to be changed at runtime. */
-	WARN_ON(old_type != TC_PORT_UNKNOWN &&
-		old_type != intel_dig_port->tc_type);
-
-	if (old_type != intel_dig_port->tc_type)
-		DRM_DEBUG_KMS("Port %c has TC type %s\n", port_name(port),
-			      tc_type_name(intel_dig_port->tc_type));
-}
-
-/*
- * This function implements the first part of the Connect Flow described by our
- * specification, Gen11 TypeC Programming chapter. The rest of the flow (reading
- * lanes, EDID, etc) is done as needed in the typical places.
- *
- * Unlike the other ports, type-C ports are not available to use as soon as we
- * get a hotplug. The type-C PHYs can be shared between multiple controllers:
- * display, USB, etc. As a result, handshaking through FIA is required around
- * connect and disconnect to cleanly transfer ownership with the controller and
- * set the type-C power state.
- *
- * We could opt to only do the connect flow when we actually try to use the AUX
- * channels or do a modeset, then immediately run the disconnect flow after
- * usage, but there are some implications on this for a dynamic environment:
- * things may go away or change behind our backs. So for now our driver is
- * always trying to acquire ownership of the controller as soon as it gets an
- * interrupt (or polls state and sees a port is connected) and only gives it
- * back when it sees a disconnect. Implementation of a more fine-grained model
- * will require a lot of coordination with user space and thorough testing for
- * the extra possible cases.
- */
-static bool icl_tc_phy_connect(struct drm_i915_private *dev_priv,
-			       struct intel_digital_port *dig_port)
-{
-	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
-	u32 val;
-
-	if (dig_port->tc_type != TC_PORT_LEGACY &&
-	    dig_port->tc_type != TC_PORT_TYPEC)
-		return true;
-
-	val = I915_READ(PORT_TX_DFLEXDPPMS);
-	if (!(val & DP_PHY_MODE_STATUS_COMPLETED(tc_port))) {
-		DRM_DEBUG_KMS("DP PHY for TC port %d not ready\n", tc_port);
-		WARN_ON(dig_port->tc_legacy_port);
-		return false;
-	}
-
-	/*
-	 * This function may be called many times in a row without an HPD event
-	 * in between, so try to avoid the write when we can.
-	 */
-	val = I915_READ(PORT_TX_DFLEXDPCSSS);
-	if (!(val & DP_PHY_MODE_STATUS_NOT_SAFE(tc_port))) {
-		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
-		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
-	}
-
-	/*
-	 * Now we have to re-check the live state, in case the port recently
-	 * became disconnected. Not necessary for legacy mode.
-	 */
-	if (dig_port->tc_type == TC_PORT_TYPEC &&
-	    !(I915_READ(PORT_TX_DFLEXDPSP) & TC_LIVE_STATE_TC(tc_port))) {
-		DRM_DEBUG_KMS("TC PHY %d sudden disconnect.\n", tc_port);
-		icl_tc_phy_disconnect(dev_priv, dig_port);
-		return false;
-	}
-
-	return true;
-}
-
-/*
- * See the comment at the connect function. This implements the Disconnect
- * Flow.
- */
-void icl_tc_phy_disconnect(struct drm_i915_private *dev_priv,
-			   struct intel_digital_port *dig_port)
-{
-	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
-
-	if (dig_port->tc_type == TC_PORT_UNKNOWN)
-		return;
-
-	/*
-	 * TBT disconnection flow is read the live status, what was done in
-	 * caller.
-	 */
-	if (dig_port->tc_type == TC_PORT_TYPEC ||
-	    dig_port->tc_type == TC_PORT_LEGACY) {
-		u32 val;
-
-		val = I915_READ(PORT_TX_DFLEXDPCSSS);
-		val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
-		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
-	}
-
-	DRM_DEBUG_KMS("Port %c TC type %s disconnected\n",
-		      port_name(dig_port->base.port),
-		      tc_type_name(dig_port->tc_type));
-
-	dig_port->tc_type = TC_PORT_UNKNOWN;
-}
-
-/*
- * The type-C ports are different because even when they are connected, they may
- * not be available/usable by the graphics driver: see the comment on
- * icl_tc_phy_connect(). So in our driver instead of adding the additional
- * concept of "usable" and make everything check for "connected and usable" we
- * define a port as "connected" when it is not only connected, but also when it
- * is usable by the rest of the driver. That maintains the old assumption that
- * connected ports are usable, and avoids exposing to the users objects they
- * can't really use.
- */
-static bool icl_tc_port_connected(struct drm_i915_private *dev_priv,
-				  struct intel_digital_port *intel_dig_port)
-{
-	enum port port = intel_dig_port->base.port;
-	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
-	bool is_legacy, is_typec, is_tbt;
-	u32 dpsp;
-
-	/*
-	 * Complain if we got a legacy port HPD, but VBT didn't mark the port as
-	 * legacy. Treat the port as legacy from now on.
-	 */
-	if (!intel_dig_port->tc_legacy_port &&
-	    I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port)) {
-		DRM_ERROR("VBT incorrectly claims port %c is not TypeC legacy\n",
-			  port_name(port));
-		intel_dig_port->tc_legacy_port = true;
-	}
-	is_legacy = intel_dig_port->tc_legacy_port;
-
-	/*
-	 * The spec says we shouldn't be using the ISR bits for detecting
-	 * between TC and TBT. We should use DFLEXDPSP.
-	 */
-	dpsp = I915_READ(PORT_TX_DFLEXDPSP);
-	is_typec = dpsp & TC_LIVE_STATE_TC(tc_port);
-	is_tbt = dpsp & TC_LIVE_STATE_TBT(tc_port);
-
-	if (!is_legacy && !is_typec && !is_tbt) {
-		icl_tc_phy_disconnect(dev_priv, intel_dig_port);
-
-		return false;
-	}
-
-	icl_update_tc_port_type(dev_priv, intel_dig_port, is_legacy, is_typec,
-				is_tbt);
-
-	if (!icl_tc_phy_connect(dev_priv, intel_dig_port))
-		return false;
-
-	return true;
-}
-
 static bool icl_digital_port_connected(struct intel_encoder *encoder)
 {
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
@@ -5428,7 +5207,7 @@ static bool icl_digital_port_connected(struct intel_encoder *encoder)
 	if (intel_port_is_combophy(dev_priv, encoder->port))
 		return icl_combo_port_connected(dev_priv, dig_port);
 	else if (intel_port_is_tc(dev_priv, encoder->port))
-		return icl_tc_port_connected(dev_priv, dig_port);
+		return intel_tc_port_connected(dig_port);
 	else
 		MISSING_CASE(encoder->hpd_pin);
 
diff --git a/drivers/gpu/drm/i915/intel_dp.h b/drivers/gpu/drm/i915/intel_dp.h
index da70b1a41c83..657bbb1f5ed0 100644
--- a/drivers/gpu/drm/i915/intel_dp.h
+++ b/drivers/gpu/drm/i915/intel_dp.h
@@ -112,8 +112,6 @@ bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp);
 int intel_dp_link_required(int pixel_clock, int bpp);
 int intel_dp_max_data_rate(int max_link_clock, int max_lanes);
 bool intel_digital_port_connected(struct intel_encoder *encoder);
-void icl_tc_phy_disconnect(struct drm_i915_private *dev_priv,
-			   struct intel_digital_port *dig_port);
 
 static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
 {
diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
new file mode 100644
index 000000000000..7a1b5870945f
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_tc.c
@@ -0,0 +1,230 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2019 Intel Corporation
+ */
+#include "intel_display.h"
+#include "i915_drv.h"
+#include "intel_tc.h"
+
+static const char *tc_type_name(enum tc_port_type type)
+{
+	static const char * const names[] = {
+		[TC_PORT_UNKNOWN] = "unknown",
+		[TC_PORT_LEGACY] = "legacy",
+		[TC_PORT_TYPEC] = "typec",
+		[TC_PORT_TBT] = "tbt",
+	};
+
+	if (WARN_ON(type >= ARRAY_SIZE(names)))
+		type = TC_PORT_UNKNOWN;
+
+	return names[type];
+}
+
+int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
+{
+	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
+	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
+	intel_wakeref_t wakeref;
+	u32 lane_info;
+
+	if (tc_port == PORT_TC_NONE || dig_port->tc_type != TC_PORT_TYPEC)
+		return 4;
+
+	lane_info = 0;
+	with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref)
+		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
+			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
+				DP_LANE_ASSIGNMENT_SHIFT(tc_port);
+
+	switch (lane_info) {
+	default:
+		MISSING_CASE(lane_info);
+	case 1:
+	case 2:
+	case 4:
+	case 8:
+		return 1;
+	case 3:
+	case 12:
+		return 2;
+	case 15:
+		return 4;
+	}
+}
+
+/*
+ * This function implements the first part of the Connect Flow described by our
+ * specification, Gen11 TypeC Programming chapter. The rest of the flow (reading
+ * lanes, EDID, etc) is done as needed in the typical places.
+ *
+ * Unlike the other ports, type-C ports are not available to use as soon as we
+ * get a hotplug. The type-C PHYs can be shared between multiple controllers:
+ * display, USB, etc. As a result, handshaking through FIA is required around
+ * connect and disconnect to cleanly transfer ownership with the controller and
+ * set the type-C power state.
+ *
+ * We could opt to only do the connect flow when we actually try to use the AUX
+ * channels or do a modeset, then immediately run the disconnect flow after
+ * usage, but there are some implications on this for a dynamic environment:
+ * things may go away or change behind our backs. So for now our driver is
+ * always trying to acquire ownership of the controller as soon as it gets an
+ * interrupt (or polls state and sees a port is connected) and only gives it
+ * back when it sees a disconnect. Implementation of a more fine-grained model
+ * will require a lot of coordination with user space and thorough testing for
+ * the extra possible cases.
+ */
+static bool icl_tc_phy_connect(struct intel_digital_port *dig_port)
+{
+	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
+	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
+	u32 val;
+
+	if (dig_port->tc_type != TC_PORT_LEGACY &&
+	    dig_port->tc_type != TC_PORT_TYPEC)
+		return true;
+
+	val = I915_READ(PORT_TX_DFLEXDPPMS);
+	if (!(val & DP_PHY_MODE_STATUS_COMPLETED(tc_port))) {
+		DRM_DEBUG_KMS("DP PHY for TC port %d not ready\n", tc_port);
+		WARN_ON(dig_port->tc_legacy_port);
+		return false;
+	}
+
+	/*
+	 * This function may be called many times in a row without an HPD event
+	 * in between, so try to avoid the write when we can.
+	 */
+	val = I915_READ(PORT_TX_DFLEXDPCSSS);
+	if (!(val & DP_PHY_MODE_STATUS_NOT_SAFE(tc_port))) {
+		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
+		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
+	}
+
+	/*
+	 * Now we have to re-check the live state, in case the port recently
+	 * became disconnected. Not necessary for legacy mode.
+	 */
+	if (dig_port->tc_type == TC_PORT_TYPEC &&
+	    !(I915_READ(PORT_TX_DFLEXDPSP) & TC_LIVE_STATE_TC(tc_port))) {
+		DRM_DEBUG_KMS("TC PHY %d sudden disconnect.\n", tc_port);
+		icl_tc_phy_disconnect(dig_port);
+		return false;
+	}
+
+	return true;
+}
+
+/*
+ * See the comment at the connect function. This implements the Disconnect
+ * Flow.
+ */
+void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
+{
+	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
+	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
+
+	if (dig_port->tc_type == TC_PORT_UNKNOWN)
+		return;
+
+	/*
+	 * TBT disconnection flow is read the live status, what was done in
+	 * caller.
+	 */
+	if (dig_port->tc_type == TC_PORT_TYPEC ||
+	    dig_port->tc_type == TC_PORT_LEGACY) {
+		u32 val;
+
+		val = I915_READ(PORT_TX_DFLEXDPCSSS);
+		val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
+		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
+	}
+
+	DRM_DEBUG_KMS("Port %c TC type %s disconnected\n",
+		      port_name(dig_port->base.port),
+		      tc_type_name(dig_port->tc_type));
+
+	dig_port->tc_type = TC_PORT_UNKNOWN;
+}
+
+static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
+				    struct intel_digital_port *intel_dig_port,
+				    bool is_legacy, bool is_typec, bool is_tbt)
+{
+	enum port port = intel_dig_port->base.port;
+	enum tc_port_type old_type = intel_dig_port->tc_type;
+
+	WARN_ON(is_legacy + is_typec + is_tbt != 1);
+
+	if (is_legacy)
+		intel_dig_port->tc_type = TC_PORT_LEGACY;
+	else if (is_typec)
+		intel_dig_port->tc_type = TC_PORT_TYPEC;
+	else if (is_tbt)
+		intel_dig_port->tc_type = TC_PORT_TBT;
+	else
+		return;
+
+	/* Types are not supposed to be changed at runtime. */
+	WARN_ON(old_type != TC_PORT_UNKNOWN &&
+		old_type != intel_dig_port->tc_type);
+
+	if (old_type != intel_dig_port->tc_type)
+		DRM_DEBUG_KMS("Port %c has TC type %s\n", port_name(port),
+			      tc_type_name(intel_dig_port->tc_type));
+}
+
+
+/*
+ * The type-C ports are different because even when they are connected, they may
+ * not be available/usable by the graphics driver: see the comment on
+ * icl_tc_phy_connect(). So in our driver instead of adding the additional
+ * concept of "usable" and make everything check for "connected and usable" we
+ * define a port as "connected" when it is not only connected, but also when it
+ * is usable by the rest of the driver. That maintains the old assumption that
+ * connected ports are usable, and avoids exposing to the users objects they
+ * can't really use.
+ */
+bool intel_tc_port_connected(struct intel_digital_port *dig_port)
+{
+	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
+	enum port port = dig_port->base.port;
+	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
+	bool is_legacy, is_typec, is_tbt;
+	u32 dpsp;
+
+	/*
+	 * Complain if we got a legacy port HPD, but VBT didn't mark the port as
+	 * legacy. Treat the port as legacy from now on.
+	 */
+	if (!dig_port->tc_legacy_port &&
+	    I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port)) {
+		DRM_ERROR("VBT incorrectly claims port %c is not TypeC legacy\n",
+			  port_name(port));
+		dig_port->tc_legacy_port = true;
+	}
+	is_legacy = dig_port->tc_legacy_port;
+
+	/*
+	 * The spec says we shouldn't be using the ISR bits for detecting
+	 * between TC and TBT. We should use DFLEXDPSP.
+	 */
+	dpsp = I915_READ(PORT_TX_DFLEXDPSP);
+	is_typec = dpsp & TC_LIVE_STATE_TC(tc_port);
+	is_tbt = dpsp & TC_LIVE_STATE_TBT(tc_port);
+
+	if (!is_legacy && !is_typec && !is_tbt) {
+		icl_tc_phy_disconnect(dig_port);
+
+		return false;
+	}
+
+	icl_update_tc_port_type(dev_priv, dig_port, is_legacy, is_typec,
+				is_tbt);
+
+	if (!icl_tc_phy_connect(dig_port))
+		return false;
+
+	return true;
+}
+
diff --git a/drivers/gpu/drm/i915/intel_tc.h b/drivers/gpu/drm/i915/intel_tc.h
new file mode 100644
index 000000000000..94c62ac4a162
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_tc.h
@@ -0,0 +1,13 @@
+#ifndef __INTEL_TC_H__
+#define __INTEL_TC_H__
+
+#include <linux/types.h>
+
+struct intel_digital_port;
+
+void icl_tc_phy_disconnect(struct intel_digital_port *dig_port);
+
+bool intel_tc_port_connected(struct intel_digital_port *dig_port);
+int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port);
+
+#endif /* __INTEL_TC_H__ */
-- 
2.17.1

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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 04/23] drm/i915: Sanitize the terminology used for TypeC port modes
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (2 preceding siblings ...)
  2019-06-04 14:58 ` [PATCH 03/23] drm/i915: Move the TypeC port handling code to a separate file Imre Deak
@ 2019-06-04 14:58 ` Imre Deak
  2019-06-07 19:15   ` Souza, Jose
  2019-06-10 23:21   ` Lucas De Marchi
  2019-06-04 14:58 ` [PATCH 05/23] drm/i915: Don't enable the DDI-IO power in the TypeC TBT-alt mode Imre Deak
                   ` (26 subsequent siblings)
  30 siblings, 2 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-04 14:58 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

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 <animesh.manna@intel.com>
Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
Cc: Anusha Srivatsa <anusha.srivatsa@intel.com>
Cc: José Roberto de Souza <jose.souza@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c      | 11 +++---
 drivers/gpu/drm/i915/intel_display.h  |  7 ++--
 drivers/gpu/drm/i915/intel_dp.c       |  2 +-
 drivers/gpu/drm/i915/intel_dpll_mgr.c |  2 +-
 drivers/gpu/drm/i915/intel_drv.h      |  2 +-
 drivers/gpu/drm/i915/intel_tc.c       | 48 +++++++++++----------------
 6 files changed, 31 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 5a1c98438375..a3574f14a3d0 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -2986,14 +2986,14 @@ static void icl_program_mg_dp_mode(struct intel_digital_port *intel_dig_port)
 	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
 	u32 ln0, ln1, lane_info;
 
-	if (tc_port == PORT_TC_NONE || intel_dig_port->tc_type == TC_PORT_TBT)
+	if (intel_dig_port->tc_mode == TC_PORT_TBT_ALT)
 		return;
 
 	ln0 = I915_READ(MG_DP_MODE(0, port));
 	ln1 = I915_READ(MG_DP_MODE(1, port));
 
-	switch (intel_dig_port->tc_type) {
-	case TC_PORT_TYPEC:
+	switch (intel_dig_port->tc_mode) {
+	case TC_PORT_DP_ALT:
 		ln0 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
 		ln1 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
 
@@ -3036,7 +3036,7 @@ static void icl_program_mg_dp_mode(struct intel_digital_port *intel_dig_port)
 		break;
 
 	default:
-		MISSING_CASE(intel_dig_port->tc_type);
+		MISSING_CASE(intel_dig_port->tc_mode);
 		return;
 	}
 
@@ -3630,8 +3630,7 @@ intel_ddi_pre_pll_enable(struct intel_encoder *encoder,
 	 * Program the lane count for static/dynamic connections on Type-C ports.
 	 * Skip this step for TBT.
 	 */
-	if (dig_port->tc_type == TC_PORT_UNKNOWN ||
-	    dig_port->tc_type == TC_PORT_TBT)
+	if (dig_port->tc_mode == TC_PORT_TBT_ALT)
 		return;
 
 	intel_ddi_set_fia_lane_count(encoder, crtc_state, port);
diff --git a/drivers/gpu/drm/i915/intel_display.h b/drivers/gpu/drm/i915/intel_display.h
index ee6b8194a459..d296556ed82e 100644
--- a/drivers/gpu/drm/i915/intel_display.h
+++ b/drivers/gpu/drm/i915/intel_display.h
@@ -189,10 +189,9 @@ enum tc_port {
 	I915_MAX_TC_PORTS
 };
 
-enum tc_port_type {
-	TC_PORT_UNKNOWN = 0,
-	TC_PORT_TYPEC,
-	TC_PORT_TBT,
+enum tc_port_mode {
+	TC_PORT_TBT_ALT,
+	TC_PORT_DP_ALT,
 	TC_PORT_LEGACY,
 };
 
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index b69310bd9914..e1e27662aa6d 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1175,7 +1175,7 @@ static u32 skl_get_aux_send_ctl(struct intel_dp *intel_dp,
 	      DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(32) |
 	      DP_AUX_CH_CTL_SYNC_PULSE_SKL(32);
 
-	if (intel_dig_port->tc_type == TC_PORT_TBT)
+	if (intel_dig_port->tc_mode == TC_PORT_TBT_ALT)
 		ret |= DP_AUX_CH_CTL_TBT_IO;
 
 	return ret;
diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
index 69787f259677..f4787650a0d3 100644
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/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);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 0dcc03592d6e..30cd49dbd0d8 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1225,7 +1225,7 @@ struct intel_digital_port {
 	enum aux_ch aux_ch;
 	enum intel_display_power_domain ddi_io_power_domain;
 	bool tc_legacy_port:1;
-	enum tc_port_type tc_type;
+	enum tc_port_mode tc_mode;
 
 	void (*write_infoframe)(struct intel_encoder *encoder,
 				const struct intel_crtc_state *crtc_state,
diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
index 7a1b5870945f..a3057c44bec6 100644
--- a/drivers/gpu/drm/i915/intel_tc.c
+++ b/drivers/gpu/drm/i915/intel_tc.c
@@ -6,19 +6,18 @@
 #include "i915_drv.h"
 #include "intel_tc.h"
 
-static const char *tc_type_name(enum tc_port_type type)
+static const char *tc_port_mode_name(enum tc_port_mode mode)
 {
 	static const char * const names[] = {
-		[TC_PORT_UNKNOWN] = "unknown",
+		[TC_PORT_TBT_ALT] = "tbt-alt",
+		[TC_PORT_DP_ALT] = "dp-alt",
 		[TC_PORT_LEGACY] = "legacy",
-		[TC_PORT_TYPEC] = "typec",
-		[TC_PORT_TBT] = "tbt",
 	};
 
-	if (WARN_ON(type >= ARRAY_SIZE(names)))
-		type = TC_PORT_UNKNOWN;
+	if (WARN_ON(mode >= ARRAY_SIZE(names)))
+		mode = TC_PORT_TBT_ALT;
 
-	return names[type];
+	return names[mode];
 }
 
 int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
@@ -28,7 +27,7 @@ int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
 	intel_wakeref_t wakeref;
 	u32 lane_info;
 
-	if (tc_port == PORT_TC_NONE || dig_port->tc_type != TC_PORT_TYPEC)
+	if (dig_port->tc_mode != TC_PORT_DP_ALT)
 		return 4;
 
 	lane_info = 0;
@@ -80,8 +79,8 @@ static bool icl_tc_phy_connect(struct intel_digital_port *dig_port)
 	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
 	u32 val;
 
-	if (dig_port->tc_type != TC_PORT_LEGACY &&
-	    dig_port->tc_type != TC_PORT_TYPEC)
+	if (dig_port->tc_mode != TC_PORT_LEGACY &&
+	    dig_port->tc_mode != TC_PORT_DP_ALT)
 		return true;
 
 	val = I915_READ(PORT_TX_DFLEXDPPMS);
@@ -105,7 +104,7 @@ static bool icl_tc_phy_connect(struct intel_digital_port *dig_port)
 	 * Now we have to re-check the live state, in case the port recently
 	 * became disconnected. Not necessary for legacy mode.
 	 */
-	if (dig_port->tc_type == TC_PORT_TYPEC &&
+	if (dig_port->tc_mode == TC_PORT_DP_ALT &&
 	    !(I915_READ(PORT_TX_DFLEXDPSP) & TC_LIVE_STATE_TC(tc_port))) {
 		DRM_DEBUG_KMS("TC PHY %d sudden disconnect.\n", tc_port);
 		icl_tc_phy_disconnect(dig_port);
@@ -124,15 +123,12 @@ void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
 	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
 	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
 
-	if (dig_port->tc_type == TC_PORT_UNKNOWN)
-		return;
-
 	/*
 	 * TBT disconnection flow is read the live status, what was done in
 	 * caller.
 	 */
-	if (dig_port->tc_type == TC_PORT_TYPEC ||
-	    dig_port->tc_type == TC_PORT_LEGACY) {
+	if (dig_port->tc_mode == TC_PORT_DP_ALT ||
+	    dig_port->tc_mode == TC_PORT_LEGACY) {
 		u32 val;
 
 		val = I915_READ(PORT_TX_DFLEXDPCSSS);
@@ -142,9 +138,9 @@ void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
 
 	DRM_DEBUG_KMS("Port %c TC type %s disconnected\n",
 		      port_name(dig_port->base.port),
-		      tc_type_name(dig_port->tc_type));
+		      tc_port_mode_name(dig_port->tc_mode));
 
-	dig_port->tc_type = TC_PORT_UNKNOWN;
+	dig_port->tc_mode = TC_PORT_TBT_ALT;
 }
 
 static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
@@ -152,26 +148,22 @@ static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
 				    bool is_legacy, bool is_typec, bool is_tbt)
 {
 	enum port port = intel_dig_port->base.port;
-	enum tc_port_type old_type = intel_dig_port->tc_type;
+	enum tc_port_mode old_mode = intel_dig_port->tc_mode;
 
 	WARN_ON(is_legacy + is_typec + is_tbt != 1);
 
 	if (is_legacy)
-		intel_dig_port->tc_type = TC_PORT_LEGACY;
+		intel_dig_port->tc_mode = TC_PORT_LEGACY;
 	else if (is_typec)
-		intel_dig_port->tc_type = TC_PORT_TYPEC;
+		intel_dig_port->tc_mode = TC_PORT_DP_ALT;
 	else if (is_tbt)
-		intel_dig_port->tc_type = TC_PORT_TBT;
+		intel_dig_port->tc_mode = TC_PORT_TBT_ALT;
 	else
 		return;
 
-	/* Types are not supposed to be changed at runtime. */
-	WARN_ON(old_type != TC_PORT_UNKNOWN &&
-		old_type != intel_dig_port->tc_type);
-
-	if (old_type != intel_dig_port->tc_type)
+	if (old_mode != intel_dig_port->tc_mode)
 		DRM_DEBUG_KMS("Port %c has TC type %s\n", port_name(port),
-			      tc_type_name(intel_dig_port->tc_type));
+			      tc_port_mode_name(intel_dig_port->tc_mode));
 }
 
 
-- 
2.17.1

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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 05/23] drm/i915: Don't enable the DDI-IO power in the TypeC TBT-alt mode
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (3 preceding siblings ...)
  2019-06-04 14:58 ` [PATCH 04/23] drm/i915: Sanitize the terminology used for TypeC port modes Imre Deak
@ 2019-06-04 14:58 ` Imre Deak
  2019-06-07 19:23   ` Souza, Jose
  2019-06-04 14:58 ` [PATCH 06/23] drm/i915: Fix the TBT AUX power well enabling Imre Deak
                   ` (25 subsequent siblings)
  30 siblings, 1 reply; 79+ messages in thread
From: Imre Deak @ 2019-06-04 14:58 UTC (permalink / raw)
  To: intel-gfx

According to the spec we should not enable the DDI-IO power domain if
the TypeC port is in the TBT-alt mode, so do that only in the other
TypeC modes or for non-TypeC ports.

Cc: Manasi Navare <manasi.d.navare@intel.com>
Cc: Anusha Srivatsa <anusha.srivatsa@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index a3574f14a3d0..8f223d48d562 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -3111,7 +3111,10 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
 
 	intel_ddi_clk_select(encoder, crtc_state);
 
-	intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain);
+	if (!intel_port_is_tc(dev_priv, port) ||
+	    dig_port->tc_mode != TC_PORT_TBT_ALT)
+		intel_display_power_get(dev_priv,
+					dig_port->ddi_io_power_domain);
 
 	icl_program_mg_dp_mode(dig_port);
 	icl_disable_phy_clock_gating(dig_port);
@@ -3293,8 +3296,10 @@ static void intel_ddi_post_disable_dp(struct intel_encoder *encoder,
 	intel_edp_panel_vdd_on(intel_dp);
 	intel_edp_panel_off(intel_dp);
 
-	intel_display_power_put_unchecked(dev_priv,
-					  dig_port->ddi_io_power_domain);
+	if (!intel_port_is_tc(dev_priv, encoder->port) ||
+	    dig_port->tc_mode != TC_PORT_TBT_ALT)
+		intel_display_power_put_unchecked(dev_priv,
+						  dig_port->ddi_io_power_domain);
 
 	intel_ddi_clk_disable(encoder);
 }
-- 
2.17.1

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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 06/23] drm/i915: Fix the TBT AUX power well enabling
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (4 preceding siblings ...)
  2019-06-04 14:58 ` [PATCH 05/23] drm/i915: Don't enable the DDI-IO power in the TypeC TBT-alt mode Imre Deak
@ 2019-06-04 14:58 ` Imre Deak
  2019-06-07 19:58   ` Souza, Jose
  2019-06-04 14:58 ` [PATCH 07/23] drm/i915: Use the correct AUX power domain in TypeC TBT-alt mode Imre Deak
                   ` (24 subsequent siblings)
  30 siblings, 1 reply; 79+ messages in thread
From: Imre Deak @ 2019-06-04 14:58 UTC (permalink / raw)
  To: intel-gfx

Fix the mapping from a TBT AUX power well index to the DP_AUX_CH_CTL
register.

Fixes: c7375d9542f1 ("drm/i915: Configure AUX_CH_CTL when enabling the AUX power domain")
Cc: José Roberto de Souza <jose.souza@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_display_power.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display_power.c b/drivers/gpu/drm/i915/intel_display_power.c
index 249a5fa55df6..14cf04bf0bf4 100644
--- a/drivers/gpu/drm/i915/intel_display_power.c
+++ b/drivers/gpu/drm/i915/intel_display_power.c
@@ -442,16 +442,23 @@ icl_combo_phy_aux_power_well_disable(struct drm_i915_private *dev_priv,
 #define ICL_AUX_PW_TO_CH(pw_idx)	\
 	((pw_idx) - ICL_PW_CTL_IDX_AUX_A + AUX_CH_A)
 
+#define ICL_TBT_AUX_PW_TO_CH(pw_idx)	\
+	((pw_idx) - ICL_PW_CTL_IDX_AUX_TBT1 + AUX_CH_C)
+
 static void
 icl_tc_phy_aux_power_well_enable(struct drm_i915_private *dev_priv,
 				 struct i915_power_well *power_well)
 {
-	enum aux_ch aux_ch = ICL_AUX_PW_TO_CH(power_well->desc->hsw.idx);
+	int pw_idx = power_well->desc->hsw.idx;
+	bool is_tbt = power_well->desc->hsw.is_tc_tbt;
+	enum aux_ch aux_ch;
 	u32 val;
 
+	aux_ch = is_tbt ? ICL_TBT_AUX_PW_TO_CH(pw_idx) :
+			  ICL_AUX_PW_TO_CH(pw_idx);
 	val = I915_READ(DP_AUX_CH_CTL(aux_ch));
 	val &= ~DP_AUX_CH_CTL_TBT_IO;
-	if (power_well->desc->hsw.is_tc_tbt)
+	if (is_tbt)
 		val |= DP_AUX_CH_CTL_TBT_IO;
 	I915_WRITE(DP_AUX_CH_CTL(aux_ch), val);
 
-- 
2.17.1

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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 07/23] drm/i915: Use the correct AUX power domain in TypeC TBT-alt mode
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (5 preceding siblings ...)
  2019-06-04 14:58 ` [PATCH 06/23] drm/i915: Fix the TBT AUX power well enabling Imre Deak
@ 2019-06-04 14:58 ` Imre Deak
  2019-06-07 20:02   ` Souza, Jose
  2019-06-04 14:58 ` [PATCH 08/23] drm/i915: Unify the TypeC port notation in debug/error messages Imre Deak
                   ` (23 subsequent siblings)
  30 siblings, 1 reply; 79+ messages in thread
From: Imre Deak @ 2019-06-04 14:58 UTC (permalink / raw)
  To: intel-gfx

In the TypeC TBT-alt port mode we must use the TBT AUX power domain,
fix that.

Cc: Manasi Navare <manasi.d.navare@intel.com>
Cc: Anusha Srivatsa <anusha.srivatsa@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 26474788b7b2..0e425a6eebf3 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6609,6 +6609,25 @@ enum intel_display_power_domain intel_port_to_power_domain(enum port port)
 enum intel_display_power_domain
 intel_aux_power_domain(struct intel_digital_port *dig_port)
 {
+	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
+
+	if (intel_port_is_tc(dev_priv, dig_port->base.port) &&
+	    dig_port->tc_mode == TC_PORT_TBT_ALT) {
+		switch (dig_port->aux_ch) {
+		case AUX_CH_C:
+			return POWER_DOMAIN_AUX_TBT1;
+		case AUX_CH_D:
+			return POWER_DOMAIN_AUX_TBT2;
+		case AUX_CH_E:
+			return POWER_DOMAIN_AUX_TBT3;
+		case AUX_CH_F:
+			return POWER_DOMAIN_AUX_TBT4;
+		default:
+			MISSING_CASE(dig_port->aux_ch);
+			return POWER_DOMAIN_AUX_TBT1;
+		}
+	}
+
 	switch (dig_port->aux_ch) {
 	case AUX_CH_A:
 		return POWER_DOMAIN_AUX_A;
-- 
2.17.1

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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 08/23] drm/i915: Unify the TypeC port notation in debug/error messages
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (6 preceding siblings ...)
  2019-06-04 14:58 ` [PATCH 07/23] drm/i915: Use the correct AUX power domain in TypeC TBT-alt mode Imre Deak
@ 2019-06-04 14:58 ` Imre Deak
  2019-06-07 20:21   ` Souza, Jose
  2019-06-04 14:58 ` [PATCH 09/23] drm/i915: Factor out common parts from TypeC port handling functions Imre Deak
                   ` (22 subsequent siblings)
  30 siblings, 1 reply; 79+ messages in thread
From: Imre Deak @ 2019-06-04 14:58 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

Unify the TypeC port notation in log messages, so that it matches the
spec. For instance the first ICL TypeC port will read as 'Port C/TC#1'.

Cc: José Roberto de Souza <jose.souza@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_tc.c | 41 +++++++++++++++++++++++++++------
 1 file changed, 34 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
index a3057c44bec6..07488235b67a 100644
--- a/drivers/gpu/drm/i915/intel_tc.c
+++ b/drivers/gpu/drm/i915/intel_tc.c
@@ -6,6 +6,29 @@
 #include "i915_drv.h"
 #include "intel_tc.h"
 
+static enum port intel_tc_port_to_port(struct drm_i915_private *dev_priv,
+				       enum tc_port tc_port)
+{
+	return tc_port + PORT_C;
+}
+
+static const char *tc_port_name(struct drm_i915_private *dev_priv,
+				enum tc_port tc_port)
+{
+	static char port_names[I915_MAX_TC_PORTS][8];
+
+	if (WARN_ON(INTEL_GEN(dev_priv) < 11 ||
+	    (unsigned int)tc_port >= I915_MAX_TC_PORTS))
+		tc_port = PORT_TC1;
+
+	snprintf(&port_names[tc_port][0], sizeof(port_names[tc_port]),
+		 "%c/TC#%d",
+		 port_name(intel_tc_port_to_port(dev_priv, tc_port)),
+		 tc_port + 1);
+
+	return port_names[tc_port];
+}
+
 static const char *tc_port_mode_name(enum tc_port_mode mode)
 {
 	static const char * const names[] = {
@@ -85,7 +108,8 @@ static bool icl_tc_phy_connect(struct intel_digital_port *dig_port)
 
 	val = I915_READ(PORT_TX_DFLEXDPPMS);
 	if (!(val & DP_PHY_MODE_STATUS_COMPLETED(tc_port))) {
-		DRM_DEBUG_KMS("DP PHY for TC port %d not ready\n", tc_port);
+		DRM_DEBUG_KMS("Port %s: PHY not ready\n",
+			      tc_port_name(dev_priv, tc_port));
 		WARN_ON(dig_port->tc_legacy_port);
 		return false;
 	}
@@ -106,7 +130,8 @@ static bool icl_tc_phy_connect(struct intel_digital_port *dig_port)
 	 */
 	if (dig_port->tc_mode == TC_PORT_DP_ALT &&
 	    !(I915_READ(PORT_TX_DFLEXDPSP) & TC_LIVE_STATE_TC(tc_port))) {
-		DRM_DEBUG_KMS("TC PHY %d sudden disconnect.\n", tc_port);
+		DRM_DEBUG_KMS("Port %s: PHY sudden disconnect\n",
+			      tc_port_name(dev_priv, tc_port));
 		icl_tc_phy_disconnect(dig_port);
 		return false;
 	}
@@ -136,8 +161,8 @@ void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
 		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
 	}
 
-	DRM_DEBUG_KMS("Port %c TC type %s disconnected\n",
-		      port_name(dig_port->base.port),
+	DRM_DEBUG_KMS("Port %s: mode %s disconnected\n",
+		      tc_port_name(dev_priv, tc_port),
 		      tc_port_mode_name(dig_port->tc_mode));
 
 	dig_port->tc_mode = TC_PORT_TBT_ALT;
@@ -162,7 +187,9 @@ static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
 		return;
 
 	if (old_mode != intel_dig_port->tc_mode)
-		DRM_DEBUG_KMS("Port %c has TC type %s\n", port_name(port),
+		DRM_DEBUG_KMS("Port %s: port has mode %s\n",
+			      tc_port_name(dev_priv,
+					   intel_port_to_tc(dev_priv, port)),
 			      tc_port_mode_name(intel_dig_port->tc_mode));
 }
 
@@ -191,8 +218,8 @@ bool intel_tc_port_connected(struct intel_digital_port *dig_port)
 	 */
 	if (!dig_port->tc_legacy_port &&
 	    I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port)) {
-		DRM_ERROR("VBT incorrectly claims port %c is not TypeC legacy\n",
-			  port_name(port));
+		DRM_ERROR("Port %s: VBT incorrectly claims port is not TypeC legacy\n",
+			  tc_port_name(dev_priv, tc_port));
 		dig_port->tc_legacy_port = true;
 	}
 	is_legacy = dig_port->tc_legacy_port;
-- 
2.17.1

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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 09/23] drm/i915: Factor out common parts from TypeC port handling functions
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (7 preceding siblings ...)
  2019-06-04 14:58 ` [PATCH 08/23] drm/i915: Unify the TypeC port notation in debug/error messages Imre Deak
@ 2019-06-04 14:58 ` Imre Deak
  2019-06-06  8:47   ` Jani Nikula
                     ` (2 more replies)
  2019-06-04 14:58 ` [PATCH 10/23] drm/i915: Wait for TypeC PHY complete flag to clear in safe mode Imre Deak
                   ` (21 subsequent siblings)
  30 siblings, 3 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-04 14:58 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

Factor out helpers reading/parsing the TypeC specific registers, making
current users of them clearer and letting us use them later.

While at it also:
- Simplify icl_tc_phy_connect() with an early return in legacy mode.
- Simplify the live status check using one bitmask for all HPD bits.
- Remove a micro-optimisation of the repeated safe-mode clearing.
- Make sure we fix the legacy port flag in all cases.

Except for the last two, no functional changes.

Cc: José Roberto de Souza <jose.souza@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c |   5 +-
 drivers/gpu/drm/i915/intel_tc.c  | 166 +++++++++++++++++++------------
 drivers/gpu/drm/i915/intel_tc.h  |   1 +
 3 files changed, 103 insertions(+), 69 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 8f223d48d562..d236839bee19 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -2983,7 +2983,6 @@ static void icl_program_mg_dp_mode(struct intel_digital_port *intel_dig_port)
 {
 	struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
 	enum port port = intel_dig_port->base.port;
-	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
 	u32 ln0, ln1, lane_info;
 
 	if (intel_dig_port->tc_mode == TC_PORT_TBT_ALT)
@@ -2997,9 +2996,7 @@ static void icl_program_mg_dp_mode(struct intel_digital_port *intel_dig_port)
 		ln0 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
 		ln1 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
 
-		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
-			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
-			    DP_LANE_ASSIGNMENT_SHIFT(tc_port);
+		lane_info = intel_tc_port_get_lane_info(intel_dig_port);
 
 		switch (lane_info) {
 		case 0x1:
diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
index 07488235b67a..3fdcfa2bbaee 100644
--- a/drivers/gpu/drm/i915/intel_tc.c
+++ b/drivers/gpu/drm/i915/intel_tc.c
@@ -43,10 +43,19 @@ static const char *tc_port_mode_name(enum tc_port_mode mode)
 	return names[mode];
 }
 
-int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
+u32 intel_tc_port_get_lane_info(struct intel_digital_port *dig_port)
 {
 	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
 	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
+	u32 lane_info = I915_READ(PORT_TX_DFLEXDPSP);
+
+	return (lane_info & DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
+	       DP_LANE_ASSIGNMENT_SHIFT(tc_port);
+}
+
+int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
+{
+	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
 	intel_wakeref_t wakeref;
 	u32 lane_info;
 
@@ -55,9 +64,7 @@ int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
 
 	lane_info = 0;
 	with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref)
-		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
-			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
-				DP_LANE_ASSIGNMENT_SHIFT(tc_port);
+		lane_info = intel_tc_port_get_lane_info(dig_port);
 
 	switch (lane_info) {
 	default:
@@ -75,6 +82,69 @@ int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
 	}
 }
 
+static void tc_port_fixup_legacy_flag(struct intel_digital_port *dig_port,
+				      u32 live_status_mask)
+{
+	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
+	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
+	u32 valid_hpd_mask = dig_port->tc_legacy_port ? BIT(TC_PORT_LEGACY) :
+							~BIT(TC_PORT_LEGACY);
+
+	if (!(live_status_mask & ~valid_hpd_mask))
+		return;
+
+	/* If live status mismatches the VBT flag, trust the live status. */
+	DRM_ERROR("Port %s: live status %08x mismatches the legacy port flag, fix flag\n",
+		  tc_port_name(dev_priv, tc_port), live_status_mask);
+
+	dig_port->tc_legacy_port = !dig_port->tc_legacy_port;
+}
+
+static u32 tc_port_live_status_mask(struct intel_digital_port *dig_port)
+{
+	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
+	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
+	u32 val = I915_READ(PORT_TX_DFLEXDPSP);
+	u32 mask = 0;
+
+	if (val & TC_LIVE_STATE_TBT(tc_port))
+		mask |= BIT(TC_PORT_TBT_ALT);
+	if (val & TC_LIVE_STATE_TC(tc_port))
+		mask |= BIT(TC_PORT_DP_ALT);
+
+	if (I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port))
+		mask |= BIT(TC_PORT_LEGACY);
+
+	/* The sink can be connected only in a single mode. */
+	if (!WARN_ON(hweight32(mask) > 1))
+		tc_port_fixup_legacy_flag(dig_port, mask);
+
+	return mask;
+}
+
+static bool icl_tc_phy_status_complete(struct intel_digital_port *dig_port)
+{
+	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
+	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
+
+	return I915_READ(PORT_TX_DFLEXDPPMS) &
+	       DP_PHY_MODE_STATUS_COMPLETED(tc_port);
+}
+
+static void icl_tc_phy_set_safe_mode(struct intel_digital_port *dig_port,
+				     bool enable)
+{
+	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
+	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
+	u32 val = I915_READ(PORT_TX_DFLEXDPCSSS);
+
+	val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
+	if (!enable)
+		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
+
+	I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
+}
+
 /*
  * This function implements the first part of the Connect Flow described by our
  * specification, Gen11 TypeC Programming chapter. The rest of the flow (reading
@@ -100,36 +170,31 @@ static bool icl_tc_phy_connect(struct intel_digital_port *dig_port)
 {
 	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
 	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
-	u32 val;
+	u32 live_status_mask;
 
 	if (dig_port->tc_mode != TC_PORT_LEGACY &&
 	    dig_port->tc_mode != TC_PORT_DP_ALT)
 		return true;
 
-	val = I915_READ(PORT_TX_DFLEXDPPMS);
-	if (!(val & DP_PHY_MODE_STATUS_COMPLETED(tc_port))) {
+	if (!icl_tc_phy_status_complete(dig_port)) {
 		DRM_DEBUG_KMS("Port %s: PHY not ready\n",
 			      tc_port_name(dev_priv, tc_port));
 		WARN_ON(dig_port->tc_legacy_port);
 		return false;
 	}
 
-	/*
-	 * This function may be called many times in a row without an HPD event
-	 * in between, so try to avoid the write when we can.
-	 */
-	val = I915_READ(PORT_TX_DFLEXDPCSSS);
-	if (!(val & DP_PHY_MODE_STATUS_NOT_SAFE(tc_port))) {
-		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
-		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
-	}
+	icl_tc_phy_set_safe_mode(dig_port, false);
+
+	if (dig_port->tc_mode == TC_PORT_LEGACY)
+		return true;
+
+	live_status_mask = tc_port_live_status_mask(dig_port);
 
 	/*
 	 * Now we have to re-check the live state, in case the port recently
 	 * became disconnected. Not necessary for legacy mode.
 	 */
-	if (dig_port->tc_mode == TC_PORT_DP_ALT &&
-	    !(I915_READ(PORT_TX_DFLEXDPSP) & TC_LIVE_STATE_TC(tc_port))) {
+	if (!(live_status_mask & BIT(TC_PORT_DP_ALT))) {
 		DRM_DEBUG_KMS("Port %s: PHY sudden disconnect\n",
 			      tc_port_name(dev_priv, tc_port));
 		icl_tc_phy_disconnect(dig_port);
@@ -148,44 +213,36 @@ void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
 	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
 	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
 
-	/*
-	 * TBT disconnection flow is read the live status, what was done in
-	 * caller.
-	 */
-	if (dig_port->tc_mode == TC_PORT_DP_ALT ||
-	    dig_port->tc_mode == TC_PORT_LEGACY) {
-		u32 val;
-
-		val = I915_READ(PORT_TX_DFLEXDPCSSS);
-		val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
-		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
+	switch (dig_port->tc_mode) {
+	case TC_PORT_LEGACY:
+	case TC_PORT_DP_ALT:
+		icl_tc_phy_set_safe_mode(dig_port, true);
+		dig_port->tc_mode = TC_PORT_TBT_ALT;
+		break;
+	case TC_PORT_TBT_ALT:
+		/* Nothing to do, we stay in TBT-alt mode */
+		break;
+	default:
+		MISSING_CASE(dig_port->tc_mode);
 	}
 
 	DRM_DEBUG_KMS("Port %s: mode %s disconnected\n",
 		      tc_port_name(dev_priv, tc_port),
 		      tc_port_mode_name(dig_port->tc_mode));
-
-	dig_port->tc_mode = TC_PORT_TBT_ALT;
 }
 
 static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
 				    struct intel_digital_port *intel_dig_port,
-				    bool is_legacy, bool is_typec, bool is_tbt)
+				    u32 live_status_mask)
 {
 	enum port port = intel_dig_port->base.port;
 	enum tc_port_mode old_mode = intel_dig_port->tc_mode;
 
-	WARN_ON(is_legacy + is_typec + is_tbt != 1);
-
-	if (is_legacy)
-		intel_dig_port->tc_mode = TC_PORT_LEGACY;
-	else if (is_typec)
-		intel_dig_port->tc_mode = TC_PORT_DP_ALT;
-	else if (is_tbt)
-		intel_dig_port->tc_mode = TC_PORT_TBT_ALT;
-	else
+	if (!live_status_mask)
 		return;
 
+	intel_dig_port->tc_mode = fls(live_status_mask) - 1;
+
 	if (old_mode != intel_dig_port->tc_mode)
 		DRM_DEBUG_KMS("Port %s: port has mode %s\n",
 			      tc_port_name(dev_priv,
@@ -207,40 +264,19 @@ static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
 bool intel_tc_port_connected(struct intel_digital_port *dig_port)
 {
 	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
-	enum port port = dig_port->base.port;
-	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
-	bool is_legacy, is_typec, is_tbt;
-	u32 dpsp;
-
-	/*
-	 * Complain if we got a legacy port HPD, but VBT didn't mark the port as
-	 * legacy. Treat the port as legacy from now on.
-	 */
-	if (!dig_port->tc_legacy_port &&
-	    I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port)) {
-		DRM_ERROR("Port %s: VBT incorrectly claims port is not TypeC legacy\n",
-			  tc_port_name(dev_priv, tc_port));
-		dig_port->tc_legacy_port = true;
-	}
-	is_legacy = dig_port->tc_legacy_port;
+	u32 live_status_mask = tc_port_live_status_mask(dig_port);
 
 	/*
 	 * The spec says we shouldn't be using the ISR bits for detecting
 	 * between TC and TBT. We should use DFLEXDPSP.
 	 */
-	dpsp = I915_READ(PORT_TX_DFLEXDPSP);
-	is_typec = dpsp & TC_LIVE_STATE_TC(tc_port);
-	is_tbt = dpsp & TC_LIVE_STATE_TBT(tc_port);
-
-	if (!is_legacy && !is_typec && !is_tbt) {
+	if (!live_status_mask && !dig_port->tc_legacy_port) {
 		icl_tc_phy_disconnect(dig_port);
 
 		return false;
 	}
 
-	icl_update_tc_port_type(dev_priv, dig_port, is_legacy, is_typec,
-				is_tbt);
-
+	icl_update_tc_port_type(dev_priv, dig_port, live_status_mask);
 	if (!icl_tc_phy_connect(dig_port))
 		return false;
 
diff --git a/drivers/gpu/drm/i915/intel_tc.h b/drivers/gpu/drm/i915/intel_tc.h
index 94c62ac4a162..e937f5326959 100644
--- a/drivers/gpu/drm/i915/intel_tc.h
+++ b/drivers/gpu/drm/i915/intel_tc.h
@@ -8,6 +8,7 @@ struct intel_digital_port;
 void icl_tc_phy_disconnect(struct intel_digital_port *dig_port);
 
 bool intel_tc_port_connected(struct intel_digital_port *dig_port);
+u32 intel_tc_port_get_lane_info(struct intel_digital_port *dig_port);
 int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port);
 
 #endif /* __INTEL_TC_H__ */
-- 
2.17.1

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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 10/23] drm/i915: Wait for TypeC PHY complete flag to clear in safe mode
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (8 preceding siblings ...)
  2019-06-04 14:58 ` [PATCH 09/23] drm/i915: Factor out common parts from TypeC port handling functions Imre Deak
@ 2019-06-04 14:58 ` Imre Deak
  2019-06-07 21:32   ` Souza, Jose
  2019-06-04 14:58 ` [PATCH 11/23] drm/i915: Handle the TCCOLD power-down event Imre Deak
                   ` (20 subsequent siblings)
  30 siblings, 1 reply; 79+ messages in thread
From: Imre Deak @ 2019-06-04 14:58 UTC (permalink / raw)
  To: intel-gfx

The PHY satus complete flag normally clears when disconnecting the PHY
in DP-alt mode (achieved by switching to safe mode), so wait for the
flag to clear.

Cc: José Roberto de Souza <jose.souza@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_tc.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
index 3fdcfa2bbaee..84e0c06877ec 100644
--- a/drivers/gpu/drm/i915/intel_tc.c
+++ b/drivers/gpu/drm/i915/intel_tc.c
@@ -143,6 +143,10 @@ static void icl_tc_phy_set_safe_mode(struct intel_digital_port *dig_port,
 		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
 
 	I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
+
+	if (enable && wait_for(!icl_tc_phy_status_complete(dig_port), 10))
+		DRM_DEBUG_DRIVER("Port %s: PHY complete clear timed out\n",
+				 tc_port_name(dev_priv, tc_port));
 }
 
 /*
-- 
2.17.1

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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 11/23] drm/i915: Handle the TCCOLD power-down event
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (9 preceding siblings ...)
  2019-06-04 14:58 ` [PATCH 10/23] drm/i915: Wait for TypeC PHY complete flag to clear in safe mode Imre Deak
@ 2019-06-04 14:58 ` Imre Deak
  2019-06-07 21:41   ` Souza, Jose
  2019-06-04 14:58 ` [PATCH 12/23] drm/i915: Sanitize the TypeC connect/detect sequences Imre Deak
                   ` (19 subsequent siblings)
  30 siblings, 1 reply; 79+ messages in thread
From: Imre Deak @ 2019-06-04 14:58 UTC (permalink / raw)
  To: intel-gfx

Based on a recent BSpec update (Index/21750) we must handle the TCCOLD
event associated with the DP-alt mode. We can detect this event by
reading an invalid all-1s value from FIA registers.

After detecting TCCOLD we will:
- fall back to TBT-alt mode when attempting to switch to DP-alt mode
- conclude that nothing is connected during live status detection
- WARN when already in unsafe mode, since then TCCOLD is unexpected

Cc: José Roberto de Souza <jose.souza@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_tc.c | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
index 84e0c06877ec..d91381c0e87d 100644
--- a/drivers/gpu/drm/i915/intel_tc.c
+++ b/drivers/gpu/drm/i915/intel_tc.c
@@ -49,6 +49,8 @@ u32 intel_tc_port_get_lane_info(struct intel_digital_port *dig_port)
 	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
 	u32 lane_info = I915_READ(PORT_TX_DFLEXDPSP);
 
+	WARN_ON(lane_info == -1);
+
 	return (lane_info & DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
 	       DP_LANE_ASSIGNMENT_SHIFT(tc_port);
 }
@@ -107,6 +109,12 @@ static u32 tc_port_live_status_mask(struct intel_digital_port *dig_port)
 	u32 val = I915_READ(PORT_TX_DFLEXDPSP);
 	u32 mask = 0;
 
+	if (val == -1) {
+		DRM_DEBUG_DRIVER("Port %s: PHY in TCCOLD, nothing connected\n",
+				 tc_port_name(dev_priv, tc_port));
+		return mask;
+	}
+
 	if (val & TC_LIVE_STATE_TBT(tc_port))
 		mask |= BIT(TC_PORT_TBT_ALT);
 	if (val & TC_LIVE_STATE_TC(tc_port))
@@ -131,13 +139,21 @@ static bool icl_tc_phy_status_complete(struct intel_digital_port *dig_port)
 	       DP_PHY_MODE_STATUS_COMPLETED(tc_port);
 }
 
-static void icl_tc_phy_set_safe_mode(struct intel_digital_port *dig_port,
+static bool icl_tc_phy_set_safe_mode(struct intel_digital_port *dig_port,
 				     bool enable)
 {
 	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
 	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
 	u32 val = I915_READ(PORT_TX_DFLEXDPCSSS);
 
+	if (val == -1) {
+		DRM_DEBUG_DRIVER("Port %s: PHY in TCCOLD, can't set safe-mode to %s\n",
+				 tc_port_name(dev_priv, tc_port),
+				 enableddisabled(enable));
+
+		return false;
+	}
+
 	val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
 	if (!enable)
 		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
@@ -147,6 +163,8 @@ static void icl_tc_phy_set_safe_mode(struct intel_digital_port *dig_port,
 	if (enable && wait_for(!icl_tc_phy_status_complete(dig_port), 10))
 		DRM_DEBUG_DRIVER("Port %s: PHY complete clear timed out\n",
 				 tc_port_name(dev_priv, tc_port));
+
+	return true;
 }
 
 /*
@@ -187,7 +205,8 @@ static bool icl_tc_phy_connect(struct intel_digital_port *dig_port)
 		return false;
 	}
 
-	icl_tc_phy_set_safe_mode(dig_port, false);
+	if (!icl_tc_phy_set_safe_mode(dig_port, false))
+		return false;
 
 	if (dig_port->tc_mode == TC_PORT_LEGACY)
 		return true;
-- 
2.17.1

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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 12/23] drm/i915: Sanitize the TypeC connect/detect sequences
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (10 preceding siblings ...)
  2019-06-04 14:58 ` [PATCH 11/23] drm/i915: Handle the TCCOLD power-down event Imre Deak
@ 2019-06-04 14:58 ` Imre Deak
  2019-06-07 22:15   ` Souza, Jose
  2019-06-04 14:58 ` [PATCH 13/23] drm/i915: Fix the TypeC port mode sanitization during loading/resume Imre Deak
                   ` (18 subsequent siblings)
  30 siblings, 1 reply; 79+ messages in thread
From: Imre Deak @ 2019-06-04 14:58 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

Make the order during detection more consistent: first reset the TypeC
port mode if needed (adding new helpers for this), then detect any
connected sink.

To check if a port mode reset is needed determine first the target port
mode based on the live status if a sink is already connected or the
PHY status complete flag otherwise.

Add a WARN in legacy mode if unexpectedly we can't set the unsafe mode
or if the FIA doesn't provide the 4 lanes required.

Cc: José Roberto de Souza <jose.souza@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_tc.c | 104 +++++++++++++++-----------------
 1 file changed, 50 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
index d91381c0e87d..9832e2ddb92e 100644
--- a/drivers/gpu/drm/i915/intel_tc.c
+++ b/drivers/gpu/drm/i915/intel_tc.c
@@ -188,43 +188,46 @@ static bool icl_tc_phy_set_safe_mode(struct intel_digital_port *dig_port,
  * will require a lot of coordination with user space and thorough testing for
  * the extra possible cases.
  */
-static bool icl_tc_phy_connect(struct intel_digital_port *dig_port)
+static void icl_tc_phy_connect(struct intel_digital_port *dig_port)
 {
 	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
 	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
-	u32 live_status_mask;
-
-	if (dig_port->tc_mode != TC_PORT_LEGACY &&
-	    dig_port->tc_mode != TC_PORT_DP_ALT)
-		return true;
 
 	if (!icl_tc_phy_status_complete(dig_port)) {
 		DRM_DEBUG_KMS("Port %s: PHY not ready\n",
 			      tc_port_name(dev_priv, tc_port));
-		WARN_ON(dig_port->tc_legacy_port);
-		return false;
+		goto out_set_tbt_alt_mode;
 	}
 
-	if (!icl_tc_phy_set_safe_mode(dig_port, false))
-		return false;
+	if (!icl_tc_phy_set_safe_mode(dig_port, false) &&
+	    !WARN_ON(dig_port->tc_legacy_port))
+		goto out_set_tbt_alt_mode;
 
-	if (dig_port->tc_mode == TC_PORT_LEGACY)
-		return true;
+	if (dig_port->tc_legacy_port) {
+		WARN_ON(intel_tc_port_fia_max_lane_count(dig_port) != 4);
+		dig_port->tc_mode = TC_PORT_LEGACY;
 
-	live_status_mask = tc_port_live_status_mask(dig_port);
+		return;
+	}
 
 	/*
 	 * Now we have to re-check the live state, in case the port recently
 	 * became disconnected. Not necessary for legacy mode.
 	 */
-	if (!(live_status_mask & BIT(TC_PORT_DP_ALT))) {
+	if (!(tc_port_live_status_mask(dig_port) & BIT(TC_PORT_DP_ALT))) {
 		DRM_DEBUG_KMS("Port %s: PHY sudden disconnect\n",
 			      tc_port_name(dev_priv, tc_port));
-		icl_tc_phy_disconnect(dig_port);
-		return false;
+		goto out_set_safe_mode;
 	}
 
-	return true;
+	dig_port->tc_mode = TC_PORT_DP_ALT;
+
+	return;
+
+out_set_safe_mode:
+	icl_tc_phy_set_safe_mode(dig_port, true);
+out_set_tbt_alt_mode:
+	dig_port->tc_mode = TC_PORT_TBT_ALT;
 }
 
 /*
@@ -233,9 +236,6 @@ static bool icl_tc_phy_connect(struct intel_digital_port *dig_port)
  */
 void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
 {
-	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
-	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
-
 	switch (dig_port->tc_mode) {
 	case TC_PORT_LEGACY:
 	case TC_PORT_DP_ALT:
@@ -248,31 +248,41 @@ void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
 	default:
 		MISSING_CASE(dig_port->tc_mode);
 	}
-
-	DRM_DEBUG_KMS("Port %s: mode %s disconnected\n",
-		      tc_port_name(dev_priv, tc_port),
-		      tc_port_mode_name(dig_port->tc_mode));
 }
 
-static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
-				    struct intel_digital_port *intel_dig_port,
-				    u32 live_status_mask)
+static enum tc_port_mode
+intel_tc_port_get_target_mode(struct intel_digital_port *dig_port)
 {
-	enum port port = intel_dig_port->base.port;
-	enum tc_port_mode old_mode = intel_dig_port->tc_mode;
+	u32 live_status_mask = tc_port_live_status_mask(dig_port);
 
-	if (!live_status_mask)
-		return;
+	if (live_status_mask)
+		return fls(live_status_mask) - 1;
+
+	return icl_tc_phy_status_complete(dig_port) &&
+	       dig_port->tc_legacy_port ? TC_PORT_LEGACY :
+					  TC_PORT_TBT_ALT;
+}
 
-	intel_dig_port->tc_mode = fls(live_status_mask) - 1;
+static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port)
+{
+	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
+	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
+	enum tc_port_mode old_tc_mode = dig_port->tc_mode;
 
-	if (old_mode != intel_dig_port->tc_mode)
-		DRM_DEBUG_KMS("Port %s: port has mode %s\n",
-			      tc_port_name(dev_priv,
-					   intel_port_to_tc(dev_priv, port)),
-			      tc_port_mode_name(intel_dig_port->tc_mode));
+	icl_tc_phy_disconnect(dig_port);
+	icl_tc_phy_connect(dig_port);
+
+	DRM_DEBUG_KMS("Port %s: TC port mode reset (%s -> %s)\n",
+		      tc_port_name(dev_priv, tc_port),
+		      tc_port_mode_name(old_tc_mode),
+		      tc_port_mode_name(dig_port->tc_mode));
 }
 
+static bool
+intel_tc_port_needs_reset(struct intel_digital_port *dig_port)
+{
+	return intel_tc_port_get_target_mode(dig_port) != dig_port->tc_mode;
+}
 
 /*
  * The type-C ports are different because even when they are connected, they may
@@ -286,23 +296,9 @@ static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
  */
 bool intel_tc_port_connected(struct intel_digital_port *dig_port)
 {
-	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
-	u32 live_status_mask = tc_port_live_status_mask(dig_port);
+	if (intel_tc_port_needs_reset(dig_port))
+		intel_tc_port_reset_mode(dig_port);
 
-	/*
-	 * The spec says we shouldn't be using the ISR bits for detecting
-	 * between TC and TBT. We should use DFLEXDPSP.
-	 */
-	if (!live_status_mask && !dig_port->tc_legacy_port) {
-		icl_tc_phy_disconnect(dig_port);
-
-		return false;
-	}
-
-	icl_update_tc_port_type(dev_priv, dig_port, live_status_mask);
-	if (!icl_tc_phy_connect(dig_port))
-		return false;
-
-	return true;
+	return tc_port_live_status_mask(dig_port) & BIT(dig_port->tc_mode);
 }
 
-- 
2.17.1

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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 13/23] drm/i915: Fix the TypeC port mode sanitization during loading/resume
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (11 preceding siblings ...)
  2019-06-04 14:58 ` [PATCH 12/23] drm/i915: Sanitize the TypeC connect/detect sequences Imre Deak
@ 2019-06-04 14:58 ` Imre Deak
  2019-06-07 22:39   ` Souza, Jose
  2019-06-04 14:58 ` [PATCH 14/23] drm/i915: Keep the TypeC port mode fixed for detect/AUX transfers Imre Deak
                   ` (17 subsequent siblings)
  30 siblings, 1 reply; 79+ messages in thread
From: Imre Deak @ 2019-06-04 14:58 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

For using the correct AUX power domains we have to sanitize the TypeC
port mode early, so move that before encoder sanitization. To do this
properly read out the actual port mode instead of just relying on the
VBT legacy port flag (which can be incorrect).

We also verify that the PHY is connected as expected if the port is
active. In case the port is inactive we connect the PHY in case of a
legacy port - as we did so far. The PHY will be connected during
detection for DP-alt mode - as it was done so far. For TBT-alt mode
nothing needs to be done to connect the PHY.

Cc: José Roberto de Souza <jose.souza@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c     | 16 +-----
 drivers/gpu/drm/i915/intel_display.c | 10 ++++
 drivers/gpu/drm/i915/intel_dp_mst.h  |  8 ++-
 drivers/gpu/drm/i915/intel_tc.c      | 83 ++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_tc.h      |  2 +
 5 files changed, 103 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index d236839bee19..2bc3b4f2c9a5 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -3918,17 +3918,6 @@ static void intel_ddi_encoder_suspend(struct intel_encoder *encoder)
 		icl_tc_phy_disconnect(dig_port);
 }
 
-static void intel_ddi_encoder_reset(struct drm_encoder *drm_encoder)
-{
-	struct intel_digital_port *dig_port = enc_to_dig_port(drm_encoder);
-	struct drm_i915_private *i915 = to_i915(drm_encoder->dev);
-
-	if (intel_port_is_tc(i915, dig_port->base.port))
-		intel_digital_port_connected(&dig_port->base);
-
-	intel_dp_encoder_reset(drm_encoder);
-}
-
 static void intel_ddi_encoder_destroy(struct drm_encoder *encoder)
 {
 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
@@ -3944,7 +3933,7 @@ static void intel_ddi_encoder_destroy(struct drm_encoder *encoder)
 }
 
 static const struct drm_encoder_funcs intel_ddi_funcs = {
-	.reset = intel_ddi_encoder_reset,
+	.reset = intel_dp_encoder_reset,
 	.destroy = intel_ddi_encoder_destroy,
 };
 
@@ -4309,9 +4298,6 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
 
 	intel_infoframe_init(intel_dig_port);
 
-	if (intel_port_is_tc(dev_priv, port))
-		intel_digital_port_connected(intel_encoder);
-
 	return;
 
 err:
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 0e425a6eebf3..91d18cd0371c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -75,6 +75,7 @@
 #include "intel_sdvo.h"
 #include "intel_sideband.h"
 #include "intel_sprite.h"
+#include "intel_tc.h"
 #include "intel_tv.h"
 #include "intel_vdsc.h"
 
@@ -16683,6 +16684,15 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
 	intel_modeset_readout_hw_state(dev);
 
 	/* HW state is read out, now we need to sanitize this mess. */
+
+	/* Sanitize the TypeC port mode upfront, encoders depend on this */
+	for_each_intel_encoder(dev, encoder) {
+		/* We need to sanitize only the MST primary port. */
+		if (encoder->type != INTEL_OUTPUT_DP_MST &&
+		    intel_port_is_tc(dev_priv, encoder->port))
+			intel_tc_port_sanitize(enc_to_dig_port(&encoder->base));
+	}
+
 	get_encoder_power_domains(dev_priv);
 
 	if (HAS_PCH_IBX(dev_priv))
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.h b/drivers/gpu/drm/i915/intel_dp_mst.h
index 1470c6e0514b..6754c211205a 100644
--- a/drivers/gpu/drm/i915/intel_dp_mst.h
+++ b/drivers/gpu/drm/i915/intel_dp_mst.h
@@ -6,9 +6,15 @@
 #ifndef __INTEL_DP_MST_H__
 #define __INTEL_DP_MST_H__
 
-struct intel_digital_port;
+#include "intel_drv.h"
 
 int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id);
 void intel_dp_mst_encoder_cleanup(struct intel_digital_port *intel_dig_port);
+static inline int
+intel_dp_mst_encoder_active_links(struct intel_digital_port *intel_dig_port)
+{
+	return intel_dig_port->dp.active_mst_links;
+}
+
 
 #endif /* __INTEL_DP_MST_H__ */
diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
index 9832e2ddb92e..9ebf25d7931c 100644
--- a/drivers/gpu/drm/i915/intel_tc.c
+++ b/drivers/gpu/drm/i915/intel_tc.c
@@ -3,6 +3,7 @@
  * Copyright © 2019 Intel Corporation
  */
 #include "intel_display.h"
+#include "intel_dp_mst.h"
 #include "i915_drv.h"
 #include "intel_tc.h"
 
@@ -167,6 +168,15 @@ static bool icl_tc_phy_set_safe_mode(struct intel_digital_port *dig_port,
 	return true;
 }
 
+static bool icl_tc_phy_is_in_safe_mode(struct intel_digital_port *dig_port)
+{
+	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
+	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
+
+	return !(I915_READ(PORT_TX_DFLEXDPCSSS) &
+		 DP_PHY_MODE_STATUS_NOT_SAFE(tc_port));
+}
+
 /*
  * This function implements the first part of the Connect Flow described by our
  * specification, Gen11 TypeC Programming chapter. The rest of the flow (reading
@@ -250,6 +260,49 @@ void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
 	}
 }
 
+static bool icl_tc_phy_is_connected(struct intel_digital_port *dig_port)
+{
+	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
+	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
+
+	if (!icl_tc_phy_status_complete(dig_port)) {
+		DRM_DEBUG_KMS("Port %s: PHY status not complete\n",
+			      tc_port_name(dev_priv, tc_port));
+		return dig_port->tc_mode == TC_PORT_TBT_ALT;
+	}
+
+	if (icl_tc_phy_is_in_safe_mode(dig_port)) {
+		DRM_DEBUG_KMS("Port %s: PHY still in safe mode\n",
+			      tc_port_name(dev_priv, tc_port));
+
+		return false;
+	}
+
+	return dig_port->tc_mode == TC_PORT_DP_ALT ||
+	       dig_port->tc_mode == TC_PORT_LEGACY;
+}
+
+static enum tc_port_mode
+intel_tc_port_get_current_mode(struct intel_digital_port *dig_port)
+{
+	u32 live_status_mask = tc_port_live_status_mask(dig_port);
+	bool in_safe_mode = icl_tc_phy_is_in_safe_mode(dig_port);
+	enum tc_port_mode mode;
+
+	if (in_safe_mode || WARN_ON(!icl_tc_phy_status_complete(dig_port)))
+		return TC_PORT_TBT_ALT;
+
+	mode = dig_port->tc_legacy_port ? TC_PORT_LEGACY : TC_PORT_DP_ALT;
+	if (live_status_mask) {
+		enum tc_port_mode live_mode = fls(live_status_mask) - 1;
+
+		if (!WARN_ON(live_mode == TC_PORT_TBT_ALT))
+			mode = live_mode;
+	}
+
+	return mode;
+}
+
 static enum tc_port_mode
 intel_tc_port_get_target_mode(struct intel_digital_port *dig_port)
 {
@@ -278,6 +331,36 @@ static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port)
 		      tc_port_mode_name(dig_port->tc_mode));
 }
 
+void intel_tc_port_sanitize(struct intel_digital_port *dig_port)
+{
+	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
+	struct intel_encoder *encoder = &dig_port->base;
+	enum tc_port tc_port = intel_port_to_tc(dev_priv, encoder->port);
+	int active_links = 0;
+
+	dig_port->tc_mode = intel_tc_port_get_current_mode(dig_port);
+	if (dig_port->dp.is_mst)
+		active_links = intel_dp_mst_encoder_active_links(dig_port);
+	else if (encoder->base.crtc)
+		active_links = to_intel_crtc(encoder->base.crtc)->active;
+
+	if (active_links) {
+		if (!icl_tc_phy_is_connected(dig_port))
+			DRM_DEBUG_DRIVER("Port %s: PHY disconnected with %d active link(s)\n",
+					 tc_port_name(dev_priv, tc_port),
+					 active_links);
+		goto out;
+	}
+
+	if (dig_port->tc_legacy_port)
+		icl_tc_phy_connect(dig_port);
+
+out:
+	DRM_DEBUG_DRIVER("Port %s: sanitize mode (%s)\n",
+			 tc_port_name(dev_priv, tc_port),
+			 tc_port_mode_name(dig_port->tc_mode));
+}
+
 static bool
 intel_tc_port_needs_reset(struct intel_digital_port *dig_port)
 {
diff --git a/drivers/gpu/drm/i915/intel_tc.h b/drivers/gpu/drm/i915/intel_tc.h
index e937f5326959..10f0f0d81ee4 100644
--- a/drivers/gpu/drm/i915/intel_tc.h
+++ b/drivers/gpu/drm/i915/intel_tc.h
@@ -11,4 +11,6 @@ bool intel_tc_port_connected(struct intel_digital_port *dig_port);
 u32 intel_tc_port_get_lane_info(struct intel_digital_port *dig_port);
 int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port);
 
+void intel_tc_port_sanitize(struct intel_digital_port *dig_port);
+
 #endif /* __INTEL_TC_H__ */
-- 
2.17.1

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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 14/23] drm/i915: Keep the TypeC port mode fixed for detect/AUX transfers
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (12 preceding siblings ...)
  2019-06-04 14:58 ` [PATCH 13/23] drm/i915: Fix the TypeC port mode sanitization during loading/resume Imre Deak
@ 2019-06-04 14:58 ` Imre Deak
  2019-06-04 14:58 ` [PATCH 15/23] drm/i915: Sanitize the TypeC FIA lane configuration decoding Imre Deak
                   ` (16 subsequent siblings)
  30 siblings, 0 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-04 14:58 UTC (permalink / raw)
  To: intel-gfx; +Cc: Paulo Zanoni

We must keep the TypeC port mode fixed for the duration of the connector
detection and each AUX transfers. Add a new TypeC lock holding it around
these two sequences. For consistency also hold the lock during the port
mode sanitization.

Whenever resetting the port mode (only during the detection for now) the
port's AUX power domain must be disabled already. Flush the async power
domain disabling work to ensure this.

A follow-up patch will make the port mode changing more robust by
postponing the change for active ports.

Cc: José Roberto de Souza <jose.souza@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c |  9 ++++++---
 drivers/gpu/drm/i915/intel_dp.c  |  7 +++++++
 drivers/gpu/drm/i915/intel_drv.h |  1 +
 drivers/gpu/drm/i915/intel_tc.c  | 34 +++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_tc.h  |  4 ++++
 5 files changed, 51 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 2bc3b4f2c9a5..ad2f7bb2f50b 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -4235,9 +4235,12 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
 	intel_dig_port->max_lanes = intel_ddi_max_lanes(intel_dig_port);
 	intel_dig_port->aux_ch = intel_bios_port_aux_ch(dev_priv, port);
 
-	intel_dig_port->tc_legacy_port = intel_port_is_tc(dev_priv, port) &&
-					 !port_info->supports_typec_usb &&
-					 !port_info->supports_tbt;
+	if (intel_port_is_tc(dev_priv, port)) {
+		bool is_legacy = !port_info->supports_typec_usb &&
+				 !port_info->supports_tbt;
+
+		intel_tc_port_init(intel_dig_port, is_legacy);
+	}
 
 	switch (port) {
 	case PORT_A:
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index e1e27662aa6d..b984410f41a4 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1190,6 +1190,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 	struct drm_i915_private *dev_priv =
 			to_i915(intel_dig_port->base.base.dev);
+	bool is_tc_port = intel_port_is_tc(dev_priv, intel_dig_port->base.port);
 	i915_reg_t ch_ctl, ch_data[5];
 	u32 aux_clock_divider;
 	enum intel_display_power_domain aux_domain =
@@ -1205,6 +1206,9 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
 	for (i = 0; i < ARRAY_SIZE(ch_data); i++)
 		ch_data[i] = intel_dp->aux_ch_data_reg(intel_dp, i);
 
+	if (is_tc_port)
+		intel_tc_port_lock(intel_dig_port);
+
 	aux_wakeref = intel_display_power_get(dev_priv, aux_domain);
 	pps_wakeref = pps_lock(intel_dp);
 
@@ -1355,6 +1359,9 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
 	pps_unlock(intel_dp, pps_wakeref);
 	intel_display_power_put_async(dev_priv, aux_domain, aux_wakeref);
 
+	if (is_tc_port)
+		intel_tc_port_unlock(intel_dig_port);
+
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 30cd49dbd0d8..18d292dd0d9c 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1224,6 +1224,7 @@ struct intel_digital_port {
 	/* Used for DP and ICL+ TypeC/DP and TypeC/HDMI ports. */
 	enum aux_ch aux_ch;
 	enum intel_display_power_domain ddi_io_power_domain;
+	struct mutex tc_lock;
 	bool tc_legacy_port:1;
 	enum tc_port_mode tc_mode;
 
diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
index 9ebf25d7931c..fc0341dc50c5 100644
--- a/drivers/gpu/drm/i915/intel_tc.c
+++ b/drivers/gpu/drm/i915/intel_tc.c
@@ -322,6 +322,8 @@ static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port)
 	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
 	enum tc_port_mode old_tc_mode = dig_port->tc_mode;
 
+	intel_display_power_flush_work(dev_priv);
+
 	icl_tc_phy_disconnect(dig_port);
 	icl_tc_phy_connect(dig_port);
 
@@ -338,6 +340,8 @@ void intel_tc_port_sanitize(struct intel_digital_port *dig_port)
 	enum tc_port tc_port = intel_port_to_tc(dev_priv, encoder->port);
 	int active_links = 0;
 
+	mutex_lock(&dig_port->tc_lock);
+
 	dig_port->tc_mode = intel_tc_port_get_current_mode(dig_port);
 	if (dig_port->dp.is_mst)
 		active_links = intel_dp_mst_encoder_active_links(dig_port);
@@ -359,6 +363,8 @@ void intel_tc_port_sanitize(struct intel_digital_port *dig_port)
 	DRM_DEBUG_DRIVER("Port %s: sanitize mode (%s)\n",
 			 tc_port_name(dev_priv, tc_port),
 			 tc_port_mode_name(dig_port->tc_mode));
+
+	mutex_unlock(&dig_port->tc_lock);
 }
 
 static bool
@@ -379,9 +385,35 @@ intel_tc_port_needs_reset(struct intel_digital_port *dig_port)
  */
 bool intel_tc_port_connected(struct intel_digital_port *dig_port)
 {
+	bool is_connected;
+
+	mutex_lock(&dig_port->tc_lock);
+
 	if (intel_tc_port_needs_reset(dig_port))
 		intel_tc_port_reset_mode(dig_port);
 
-	return tc_port_live_status_mask(dig_port) & BIT(dig_port->tc_mode);
+	is_connected = tc_port_live_status_mask(dig_port) &
+		       BIT(dig_port->tc_mode);
+
+	mutex_unlock(&dig_port->tc_lock);
+
+	return is_connected;
 }
 
+void intel_tc_port_lock(struct intel_digital_port *dig_port)
+{
+	mutex_lock(&dig_port->tc_lock);
+	/* TODO: reset the TypeC port mode if needed */
+}
+
+void intel_tc_port_unlock(struct intel_digital_port *dig_port)
+{
+	mutex_unlock(&dig_port->tc_lock);
+}
+
+void
+intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy)
+{
+	mutex_init(&dig_port->tc_lock);
+	dig_port->tc_legacy_port = is_legacy;
+}
diff --git a/drivers/gpu/drm/i915/intel_tc.h b/drivers/gpu/drm/i915/intel_tc.h
index 10f0f0d81ee4..91c6e7459cc9 100644
--- a/drivers/gpu/drm/i915/intel_tc.h
+++ b/drivers/gpu/drm/i915/intel_tc.h
@@ -12,5 +12,9 @@ u32 intel_tc_port_get_lane_info(struct intel_digital_port *dig_port);
 int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port);
 
 void intel_tc_port_sanitize(struct intel_digital_port *dig_port);
+void intel_tc_port_lock(struct intel_digital_port *dig_port);
+void intel_tc_port_unlock(struct intel_digital_port *dig_port);
+
+void intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy);
 
 #endif /* __INTEL_TC_H__ */
-- 
2.17.1

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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 15/23] drm/i915: Sanitize the TypeC FIA lane configuration decoding
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (13 preceding siblings ...)
  2019-06-04 14:58 ` [PATCH 14/23] drm/i915: Keep the TypeC port mode fixed for detect/AUX transfers Imre Deak
@ 2019-06-04 14:58 ` Imre Deak
  2019-06-07 22:49   ` Souza, Jose
  2019-06-18 16:39   ` Ville Syrjälä
  2019-06-04 14:58 ` [PATCH 16/23] drm/i915: Sanitize the shared DPLL reserve/release interface Imre Deak
                   ` (15 subsequent siblings)
  30 siblings, 2 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-04 14:58 UTC (permalink / raw)
  To: intel-gfx

Use hex numbers, since that makes more sense when decoding a bit pattern.

No functional change.

Suggested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Animesh Manna <animesh.manna@intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_tc.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
index fc0341dc50c5..4b2f525bc2a6 100644
--- a/drivers/gpu/drm/i915/intel_tc.c
+++ b/drivers/gpu/drm/i915/intel_tc.c
@@ -72,15 +72,16 @@ int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
 	switch (lane_info) {
 	default:
 		MISSING_CASE(lane_info);
-	case 1:
-	case 2:
-	case 4:
-	case 8:
+		/* fall-through */
+	case 0x1:
+	case 0x2:
+	case 0x4:
+	case 0x8:
 		return 1;
-	case 3:
-	case 12:
+	case 0x3:
+	case 0xc:
 		return 2;
-	case 15:
+	case 0xf:
 		return 4;
 	}
 }
-- 
2.17.1

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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 16/23] drm/i915: Sanitize the shared DPLL reserve/release interface
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (14 preceding siblings ...)
  2019-06-04 14:58 ` [PATCH 15/23] drm/i915: Sanitize the TypeC FIA lane configuration decoding Imre Deak
@ 2019-06-04 14:58 ` Imre Deak
  2019-06-04 14:58 ` [PATCH 17/23] drm/i915: Sanitize the shared DPLL find/reference interface Imre Deak
                   ` (14 subsequent siblings)
  30 siblings, 0 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-04 14:58 UTC (permalink / raw)
  To: intel-gfx; +Cc: Daniel Vetter

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.

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>
---
 drivers/gpu/drm/i915/intel_display.c  |  19 +--
 drivers/gpu/drm/i915/intel_dpll_mgr.c | 221 ++++++++++++++++----------
 drivers/gpu/drm/i915/intel_dpll_mgr.h |  13 +-
 3 files changed, 153 insertions(+), 100 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 91d18cd0371c..d86fceacf199 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -9425,6 +9425,8 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc,
 				       struct intel_crtc_state *crtc_state)
 {
 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	struct intel_atomic_state *state =
+		to_intel_atomic_state(crtc_state->base.state);
 	const struct intel_limit *limit;
 	int refclk = 120000;
 
@@ -9466,7 +9468,7 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc,
 
 	ironlake_compute_dpll(crtc, crtc_state, NULL);
 
-	if (!intel_get_shared_dpll(crtc_state, NULL)) {
+	if (!intel_reserve_shared_dplls(state, crtc, NULL)) {
 		DRM_DEBUG_KMS("failed to find PLL for pipe %c\n",
 			      pipe_name(crtc->pipe));
 		return -EINVAL;
@@ -9846,7 +9848,7 @@ static int haswell_crtc_compute_clock(struct intel_crtc *crtc,
 		struct intel_encoder *encoder =
 			intel_get_crtc_new_encoder(state, crtc_state);
 
-		if (!intel_get_shared_dpll(crtc_state, encoder)) {
+		if (!intel_reserve_shared_dplls(state, crtc, encoder)) {
 			DRM_DEBUG_KMS("failed to find PLL for pipe %c\n",
 				      pipe_name(crtc->pipe));
 			return -EINVAL;
@@ -13121,27 +13123,20 @@ static void update_scanline_offset(const struct intel_crtc_state *crtc_state)
 static void intel_modeset_clear_plls(struct intel_atomic_state *state)
 {
 	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
-	struct intel_crtc_state *old_crtc_state, *new_crtc_state;
+	struct intel_crtc_state *new_crtc_state;
 	struct intel_crtc *crtc;
 	int i;
 
 	if (!dev_priv->display.crtc_compute_clock)
 		return;
 
-	for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
-					    new_crtc_state, i) {
-		struct intel_shared_dpll *old_dpll =
-			old_crtc_state->shared_dpll;
-
+	for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
 		if (!needs_modeset(&new_crtc_state->base))
 			continue;
 
 		new_crtc_state->shared_dpll = NULL;
 
-		if (!old_dpll)
-			continue;
-
-		intel_release_shared_dpll(old_dpll, crtc, &state->base);
+		intel_release_shared_dplls(state, crtc);
 	}
 }
 
diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
index f4787650a0d3..34638a681f37 100644
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/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_PLL_FREQ_1350MHz | SPLL_PLL_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 succesfully 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);
 }
 
 /**
diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h
index b5dd9c7ad772..6ffdcc06ad23 100644
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.h
+++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h
@@ -39,6 +39,7 @@
 struct drm_atomic_state;
 struct drm_device;
 struct drm_i915_private;
+struct intel_atomic_state;
 struct intel_crtc;
 struct intel_crtc_state;
 struct intel_encoder;
@@ -195,7 +196,7 @@ struct intel_dpll_hw_state {
  * future state which would be applied by an atomic mode set (stored in
  * a struct &intel_atomic_state).
  *
- * See also intel_get_shared_dpll() and intel_release_shared_dpll().
+ * See also intel_reserve_shared_dplls() and intel_release_shared_dplls().
  */
 struct intel_shared_dpll_state {
 	/**
@@ -331,11 +332,11 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv,
 			bool state);
 #define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true)
 #define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false)
-struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc_state *state,
-						struct intel_encoder *encoder);
-void intel_release_shared_dpll(struct intel_shared_dpll *dpll,
-			       struct intel_crtc *crtc,
-			       struct drm_atomic_state *state);
+bool intel_reserve_shared_dplls(struct intel_atomic_state *state,
+				struct intel_crtc *crtc,
+				struct intel_encoder *encoder);
+void intel_release_shared_dplls(struct intel_atomic_state *state,
+				struct intel_crtc *crtc);
 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);
-- 
2.17.1

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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 17/23] drm/i915: Sanitize the shared DPLL find/reference interface
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (15 preceding siblings ...)
  2019-06-04 14:58 ` [PATCH 16/23] drm/i915: Sanitize the shared DPLL reserve/release interface Imre Deak
@ 2019-06-04 14:58 ` Imre Deak
  2019-06-04 14:58 ` [PATCH 18/23] drm/i915/icl: Split getting the DPLLs to port type specific functions Imre Deak
                   ` (13 subsequent siblings)
  30 siblings, 0 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-04 14:58 UTC (permalink / raw)
  To: intel-gfx; +Cc: Daniel Vetter

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ä <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>
---
 drivers/gpu/drm/i915/intel_dpll_mgr.c | 107 +++++++++++++++++---------
 1 file changed, 70 insertions(+), 37 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
index 34638a681f37..9e8dc025d8f7 100644
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c
@@ -244,17 +244,18 @@ void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state)
 }
 
 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_PLL_FREQ_1350MHz | SPLL_PLL_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;
 }
-- 
2.17.1

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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 18/23] drm/i915/icl: Split getting the DPLLs to port type specific functions
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (16 preceding siblings ...)
  2019-06-04 14:58 ` [PATCH 17/23] drm/i915: Sanitize the shared DPLL find/reference interface Imre Deak
@ 2019-06-04 14:58 ` Imre Deak
  2019-06-04 14:58 ` [PATCH 19/23] drm/i915/icl: Reserve all required PLLs for TypeC ports Imre Deak
                   ` (12 subsequent siblings)
  30 siblings, 0 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-04 14:58 UTC (permalink / raw)
  To: intel-gfx; +Cc: Daniel Vetter

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ä <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>
---
 drivers/gpu/drm/i915/intel_dpll_mgr.c | 100 +++++++++++++++++---------
 1 file changed, 66 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
index 9e8dc025d8f7..d2ca2c676f03 100644
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/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)
-- 
2.17.1

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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 19/23] drm/i915/icl: Reserve all required PLLs for TypeC ports
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (17 preceding siblings ...)
  2019-06-04 14:58 ` [PATCH 18/23] drm/i915/icl: Split getting the DPLLs to port type specific functions Imre Deak
@ 2019-06-04 14:58 ` Imre Deak
  2019-06-07 17:41   ` [PATCH v2 " Imre Deak
  2019-06-04 14:58 ` [PATCH 20/23] drm/i915: Keep the TypeC port mode fixed when the port is active Imre Deak
                   ` (11 subsequent siblings)
  30 siblings, 1 reply; 79+ messages in thread
From: Imre Deak @ 2019-06-04 14:58 UTC (permalink / raw)
  To: intel-gfx; +Cc: Daniel Vetter

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.

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>
---
 drivers/gpu/drm/i915/intel_display.c  |  11 +-
 drivers/gpu/drm/i915/intel_dpll_mgr.c | 152 +++++++++++++++++++-------
 drivers/gpu/drm/i915/intel_dpll_mgr.h |   9 ++
 drivers/gpu/drm/i915/intel_drv.h      |   9 ++
 4 files changed, 139 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index d86fceacf199..f86b5b848cbc 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -9878,6 +9878,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;
 
@@ -9885,22 +9886,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,
@@ -12037,6 +12044,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/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
index d2ca2c676f03..ce08a2eee55f 100644
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/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 =
+		&crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT];
+	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);
+	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,25 @@ 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);
+		port_dpll->pll = NULL;
+	}
+}
+
 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 +3400,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 +3413,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/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h
index 6ffdcc06ad23..3bea81bde343 100644
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.h
+++ b/drivers/gpu/drm/i915/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 18d292dd0d9c..c61955c41976 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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 20/23] drm/i915: Keep the TypeC port mode fixed when the port is active
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (18 preceding siblings ...)
  2019-06-04 14:58 ` [PATCH 19/23] drm/i915/icl: Reserve all required PLLs for TypeC ports Imre Deak
@ 2019-06-04 14:58 ` Imre Deak
  2019-06-19 12:58   ` Ville Syrjälä
  2019-06-04 14:58 ` [PATCH 21/23] drm/i915: Add state verification for the TypeC port mode Imre Deak
                   ` (10 subsequent siblings)
  30 siblings, 1 reply; 79+ messages in thread
From: Imre Deak @ 2019-06-04 14:58 UTC (permalink / raw)
  To: intel-gfx; +Cc: Daniel Vetter

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
connector_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.

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>
---
 drivers/gpu/drm/i915/intel_ddi.c      | 46 +++++++++++--
 drivers/gpu/drm/i915/intel_ddi.h      |  7 ++
 drivers/gpu/drm/i915/intel_display.c  | 90 +++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_dp.c       |  7 ++
 drivers/gpu/drm/i915/intel_dp_mst.c   |  6 ++
 drivers/gpu/drm/i915/intel_dpll_mgr.c | 28 +++++++-
 drivers/gpu/drm/i915/intel_dpll_mgr.h |  3 +
 drivers/gpu/drm/i915/intel_drv.h      |  9 +++
 drivers/gpu/drm/i915/intel_hdmi.c     |  7 ++
 drivers/gpu/drm/i915/intel_tc.c       | 93 ++++++++++++++++++++-------
 drivers/gpu/drm/i915/intel_tc.h       |  3 +
 11 files changed, 269 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index ad2f7bb2f50b..138950941246 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -3610,6 +3610,38 @@ static void intel_ddi_set_fia_lane_count(struct intel_encoder *encoder,
 	I915_WRITE(PORT_TX_DFLEXDPMLE1, val);
 }
 
+void
+intel_ddi_connector_update_prepare(struct intel_atomic_state *state,
+				   struct intel_connector *connector)
+{
+	struct drm_connector_state *conn_state =
+		drm_atomic_get_new_connector_state(&state->base,
+						   &connector->base);
+	struct intel_crtc *crtc = conn_state->crtc ?
+		to_intel_crtc(conn_state->crtc) : NULL;
+	struct intel_crtc_state *crtc_state =
+		crtc ? intel_atomic_get_new_crtc_state(state, crtc) : NULL;
+	struct intel_digital_port *primary_port =
+		intel_connector_primary_digital_port(connector);
+	int required_lanes = crtc_state ? crtc_state->lane_count : 1;
+
+	WARN_ON(crtc && crtc->active);
+
+	intel_tc_port_get_link(primary_port, required_lanes);
+	if (crtc_state && crtc_state->base.active)
+		intel_update_active_dpll(state, crtc, &primary_port->base);
+}
+
+void
+intel_ddi_connector_update_complete(struct intel_atomic_state *state,
+				    struct intel_connector *connector)
+{
+	struct intel_digital_port *primary_port =
+		intel_connector_primary_digital_port(connector);
+
+	intel_tc_port_put_link(primary_port);
+}
+
 static void
 intel_ddi_pre_pll_enable(struct intel_encoder *encoder,
 			 const struct intel_crtc_state *crtc_state,
@@ -3617,10 +3649,13 @@ intel_ddi_pre_pll_enable(struct intel_encoder *encoder,
 {
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
+	bool is_tc_port = intel_port_is_tc(dev_priv, encoder->port);
 	enum port port = encoder->port;
 
-	if (intel_crtc_has_dp_encoder(crtc_state) ||
-	    intel_port_is_tc(dev_priv, encoder->port))
+	if (is_tc_port)
+		intel_tc_port_get_link(dig_port, crtc_state->lane_count);
+
+	if (intel_crtc_has_dp_encoder(crtc_state) || is_tc_port)
 		intel_display_power_get(dev_priv,
 					intel_ddi_main_link_aux_domain(dig_port));
 
@@ -3645,11 +3680,14 @@ intel_ddi_post_pll_disable(struct intel_encoder *encoder,
 {
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
+	bool is_tc_port = intel_port_is_tc(dev_priv, encoder->port);
 
-	if (intel_crtc_has_dp_encoder(crtc_state) ||
-	    intel_port_is_tc(dev_priv, encoder->port))
+	if (intel_crtc_has_dp_encoder(crtc_state) || is_tc_port)
 		intel_display_power_put_unchecked(dev_priv,
 						  intel_ddi_main_link_aux_domain(dig_port));
+
+	if (is_tc_port)
+		intel_tc_port_put_link(dig_port);
 }
 
 void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
diff --git a/drivers/gpu/drm/i915/intel_ddi.h b/drivers/gpu/drm/i915/intel_ddi.h
index 9cf69175942e..1559d1fbf7bd 100644
--- a/drivers/gpu/drm/i915/intel_ddi.h
+++ b/drivers/gpu/drm/i915/intel_ddi.h
@@ -12,6 +12,7 @@
 
 struct drm_connector_state;
 struct drm_i915_private;
+struct intel_atomic_state;
 struct intel_connector;
 struct intel_crtc;
 struct intel_crtc_state;
@@ -35,6 +36,12 @@ void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp);
 bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector);
 void intel_ddi_get_config(struct intel_encoder *encoder,
 			  struct intel_crtc_state *pipe_config);
+void
+intel_ddi_connector_update_prepare(struct intel_atomic_state *state,
+				   struct intel_connector *connector);
+void
+intel_ddi_connector_update_complete(struct intel_atomic_state *state,
+				    struct intel_connector *connector);
 void intel_ddi_set_vc_payload_alloc(const struct intel_crtc_state *crtc_state,
 				    bool state);
 void intel_ddi_compute_min_voltage_level(struct drm_i915_private *dev_priv,
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f86b5b848cbc..2c65587d1622 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -520,6 +520,20 @@ needs_modeset(const struct drm_crtc_state *state)
 	return drm_atomic_crtc_needs_modeset(state);
 }
 
+static bool
+intel_connector_needs_modeset(struct intel_atomic_state *state,
+			      const struct drm_connector_state *old_conn_state,
+			      const struct drm_connector_state *new_conn_state)
+{
+	if (new_conn_state->crtc != old_conn_state->crtc ||
+	    (new_conn_state->crtc &&
+	     needs_modeset(drm_atomic_get_new_crtc_state(&state->base,
+							 new_conn_state->crtc))))
+		return true;
+
+	return false;
+}
+
 /*
  * Platform specific helpers to calculate the port PLL loopback- (clock.m),
  * and post-divider (clock.p) values, pre- (clock.vco) and post-divided fast
@@ -6032,6 +6046,52 @@ static void intel_crtc_disable_planes(struct intel_atomic_state *state,
 	intel_frontbuffer_flip(dev_priv, fb_bits);
 }
 
+static void intel_connectors_update_prepare(struct intel_atomic_state *state)
+{
+	struct drm_connector_state *old_conn_state;
+	struct drm_connector_state *new_conn_state;
+	struct drm_connector *conn;
+	int i;
+
+	for_each_oldnew_connector_in_state(&state->base, conn,
+					   old_conn_state, new_conn_state, i) {
+		struct intel_connector *connector = to_intel_connector(conn);
+
+		if (!connector->update_prepare)
+			continue;
+
+		if (!intel_connector_needs_modeset(state,
+						   old_conn_state,
+						   new_conn_state))
+			continue;
+
+		connector->update_prepare(state, connector);
+	}
+}
+
+static void intel_connectors_update_complete(struct intel_atomic_state *state)
+{
+	struct drm_connector_state *old_conn_state;
+	struct drm_connector_state *new_conn_state;
+	struct drm_connector *conn;
+	int i;
+
+	for_each_oldnew_connector_in_state(&state->base, conn,
+					   old_conn_state, new_conn_state, i) {
+		struct intel_connector *connector = to_intel_connector(conn);
+
+		if (!connector->update_complete)
+			continue;
+
+		if (!intel_connector_needs_modeset(state,
+						   old_conn_state,
+						   new_conn_state))
+			continue;
+
+		connector->update_complete(state, connector);
+	}
+}
+
 static void intel_encoders_pre_pll_enable(struct drm_crtc *crtc,
 					  struct intel_crtc_state *crtc_state,
 					  struct drm_atomic_state *old_state)
@@ -6556,6 +6616,28 @@ static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state)
 	I915_WRITE(BCLRPAT(crtc->pipe), 0);
 }
 
+/*
+ * intel_connector_primary_digital_port - get the primary port for a connector
+ * @connector: connector for which to return the port
+ *
+ * Returns the primary digital port for a DP MST, the single digital port for
+ * DP SST and HDMI and NULL for all other connector types.
+ */
+struct intel_digital_port *
+intel_connector_primary_digital_port(struct intel_connector *connector)
+{
+	struct intel_encoder *encoder;
+
+	if (connector->mst_port)
+		return dp_to_dig_port(connector->mst_port);
+
+	encoder = intel_attached_encoder(&connector->base);
+	if (WARN_ON(!encoder))
+		return NULL;
+
+	return enc_to_dig_port(&encoder->base);
+}
+
 bool intel_port_is_combophy(struct drm_i915_private *dev_priv, enum port port)
 {
 	if (port == PORT_NONE)
@@ -13805,14 +13887,20 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
 		}
 	}
 
+	if (intel_state->modeset)
+		intel_connectors_update_prepare(intel_state);
+
 	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
 	dev_priv->display.update_crtcs(state);
 
-	if (intel_state->modeset)
+	if (intel_state->modeset) {
+		intel_connectors_update_complete(intel_state);
+
 		intel_set_cdclk_post_plane_update(dev_priv,
 						  &intel_state->cdclk.actual,
 						  &dev_priv->cdclk.actual,
 						  intel_state->cdclk.pipe);
+	}
 
 	/* FIXME: We should call drm_atomic_helper_commit_hw_done() here
 	 * already, but still need the state for the delayed optimization. To
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index b984410f41a4..2f63476e3cf2 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -7195,6 +7195,13 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	else
 		intel_connector->get_hw_state = intel_connector_get_hw_state;
 
+	if (intel_port_is_tc(dev_priv, intel_encoder->port)) {
+		intel_connector->update_prepare =
+			intel_ddi_connector_update_prepare;
+		intel_connector->update_complete =
+			intel_ddi_connector_update_complete;
+	}
+
 	/* init MST on ports that can support it */
 	if (HAS_DP_MST(dev_priv) && !intel_dp_is_edp(intel_dp) &&
 	    (port == PORT_B || port == PORT_C ||
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
index 0caf645fbbb8..9d5b048b9c96 100644
--- a/drivers/gpu/drm/i915/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/intel_dp_mst.c
@@ -505,6 +505,12 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
 	if (!intel_connector)
 		return NULL;
 
+	if (intel_port_is_tc(dev_priv, intel_dig_port->base.port)) {
+		intel_connector->update_prepare =
+			intel_ddi_connector_update_prepare;
+		intel_connector->update_complete =
+			intel_ddi_connector_update_complete;
+	}
 	intel_connector->get_hw_state = intel_dp_mst_get_hw_state;
 	intel_connector->mst_port = intel_dp;
 	intel_connector->port = port;
diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
index ce08a2eee55f..ce397b69b1d6 100644
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/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);
 };
@@ -3401,6 +3403,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,
 };
 
@@ -3525,6 +3528,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
diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h
index 3bea81bde343..5817faa129d5 100644
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.h
+++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h
@@ -346,6 +346,9 @@ 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_update_active_dpll(struct intel_atomic_state *state,
+			      struct intel_crtc *crtc,
+			      struct intel_encoder *encoder);
 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 c61955c41976..b96656f1b8d4 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -375,6 +375,11 @@ struct intel_connector {
 	 * and active (i.e. dpms ON state). */
 	bool (*get_hw_state)(struct intel_connector *);
 
+	void (*update_prepare)(struct intel_atomic_state *state,
+			       struct intel_connector *connector);
+	void (*update_complete)(struct intel_atomic_state *state,
+				struct intel_connector *connector);
+
 	/* Panel info for eDP and LVDS */
 	struct intel_panel panel;
 
@@ -1234,6 +1239,8 @@ struct intel_digital_port {
 	enum aux_ch aux_ch;
 	enum intel_display_power_domain ddi_io_power_domain;
 	struct mutex tc_lock;
+	intel_wakeref_t tc_lock_wakeref;
+	int tc_link_refcount;
 	bool tc_legacy_port:1;
 	enum tc_port_mode tc_mode;
 
@@ -1485,6 +1492,8 @@ void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv);
 void intel_encoder_destroy(struct drm_encoder *encoder);
 struct drm_display_mode *
 intel_encoder_current_mode(struct intel_encoder *encoder);
+struct intel_digital_port *
+intel_connector_primary_digital_port(struct intel_connector *connector);
 bool intel_port_is_combophy(struct drm_i915_private *dev_priv, enum port port);
 bool intel_port_is_tc(struct drm_i915_private *dev_priv, enum port port);
 enum tc_port intel_port_to_tc(struct drm_i915_private *dev_priv,
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 097bfa504ece..89f09e27b741 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -3092,6 +3092,13 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
 	else
 		intel_connector->get_hw_state = intel_connector_get_hw_state;
 
+	if (intel_port_is_tc(dev_priv, intel_encoder->port)) {
+		intel_connector->update_prepare =
+			intel_ddi_connector_update_prepare;
+		intel_connector->update_complete =
+			intel_ddi_connector_update_complete;
+	}
+
 	intel_hdmi_add_properties(intel_hdmi, connector);
 
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
index 4b2f525bc2a6..e79f6ceb26f3 100644
--- a/drivers/gpu/drm/i915/intel_tc.c
+++ b/drivers/gpu/drm/i915/intel_tc.c
@@ -188,21 +188,13 @@ static bool icl_tc_phy_is_in_safe_mode(struct intel_digital_port *dig_port)
  * display, USB, etc. As a result, handshaking through FIA is required around
  * connect and disconnect to cleanly transfer ownership with the controller and
  * set the type-C power state.
- *
- * We could opt to only do the connect flow when we actually try to use the AUX
- * channels or do a modeset, then immediately run the disconnect flow after
- * usage, but there are some implications on this for a dynamic environment:
- * things may go away or change behind our backs. So for now our driver is
- * always trying to acquire ownership of the controller as soon as it gets an
- * interrupt (or polls state and sees a port is connected) and only gives it
- * back when it sees a disconnect. Implementation of a more fine-grained model
- * will require a lot of coordination with user space and thorough testing for
- * the extra possible cases.
  */
-static void icl_tc_phy_connect(struct intel_digital_port *dig_port)
+static void icl_tc_phy_connect(struct intel_digital_port *dig_port,
+			       int required_lanes)
 {
 	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
 	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
+	int max_lanes;
 
 	if (!icl_tc_phy_status_complete(dig_port)) {
 		DRM_DEBUG_KMS("Port %s: PHY not ready\n",
@@ -214,8 +206,9 @@ static void icl_tc_phy_connect(struct intel_digital_port *dig_port)
 	    !WARN_ON(dig_port->tc_legacy_port))
 		goto out_set_tbt_alt_mode;
 
+	max_lanes = intel_tc_port_fia_max_lane_count(dig_port);
 	if (dig_port->tc_legacy_port) {
-		WARN_ON(intel_tc_port_fia_max_lane_count(dig_port) != 4);
+		WARN_ON(max_lanes != 4);
 		dig_port->tc_mode = TC_PORT_LEGACY;
 
 		return;
@@ -231,6 +224,13 @@ static void icl_tc_phy_connect(struct intel_digital_port *dig_port)
 		goto out_set_safe_mode;
 	}
 
+	if (max_lanes < required_lanes) {
+		DRM_DEBUG_KMS("Port %s: PHY max lanes %d < required lanes %d\n",
+			      tc_port_name(dev_priv, tc_port),
+			      max_lanes, required_lanes);
+		goto out_set_safe_mode;
+	}
+
 	dig_port->tc_mode = TC_PORT_DP_ALT;
 
 	return;
@@ -317,7 +317,8 @@ intel_tc_port_get_target_mode(struct intel_digital_port *dig_port)
 					  TC_PORT_TBT_ALT;
 }
 
-static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port)
+static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port,
+				     int required_lanes)
 {
 	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
 	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
@@ -326,7 +327,7 @@ static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port)
 	intel_display_power_flush_work(dev_priv);
 
 	icl_tc_phy_disconnect(dig_port);
-	icl_tc_phy_connect(dig_port);
+	icl_tc_phy_connect(dig_port, required_lanes);
 
 	DRM_DEBUG_KMS("Port %s: TC port mode reset (%s -> %s)\n",
 		      tc_port_name(dev_priv, tc_port),
@@ -334,6 +335,14 @@ static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port)
 		      tc_port_mode_name(dig_port->tc_mode));
 }
 
+static void
+intel_tc_port_link_init_refcount(struct intel_digital_port *dig_port,
+				 int refcount)
+{
+	WARN_ON(dig_port->tc_link_refcount);
+	dig_port->tc_link_refcount = refcount;
+}
+
 void intel_tc_port_sanitize(struct intel_digital_port *dig_port)
 {
 	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
@@ -354,11 +363,13 @@ void intel_tc_port_sanitize(struct intel_digital_port *dig_port)
 			DRM_DEBUG_DRIVER("Port %s: PHY disconnected with %d active link(s)\n",
 					 tc_port_name(dev_priv, tc_port),
 					 active_links);
+		intel_tc_port_link_init_refcount(dig_port, active_links);
+
 		goto out;
 	}
 
 	if (dig_port->tc_legacy_port)
-		icl_tc_phy_connect(dig_port);
+		icl_tc_phy_connect(dig_port, 1);
 
 out:
 	DRM_DEBUG_DRIVER("Port %s: sanitize mode (%s)\n",
@@ -388,27 +399,60 @@ bool intel_tc_port_connected(struct intel_digital_port *dig_port)
 {
 	bool is_connected;
 
-	mutex_lock(&dig_port->tc_lock);
-
-	if (intel_tc_port_needs_reset(dig_port))
-		intel_tc_port_reset_mode(dig_port);
-
+	intel_tc_port_lock(dig_port);
 	is_connected = tc_port_live_status_mask(dig_port) &
 		       BIT(dig_port->tc_mode);
-
-	mutex_unlock(&dig_port->tc_lock);
+	intel_tc_port_unlock(dig_port);
 
 	return is_connected;
 }
 
-void intel_tc_port_lock(struct intel_digital_port *dig_port)
+static void __intel_tc_port_lock(struct intel_digital_port *dig_port,
+				 int required_lanes)
 {
+	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
+	intel_wakeref_t wakeref;
+
+	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_DISPLAY_CORE);
+
 	mutex_lock(&dig_port->tc_lock);
-	/* TODO: reset the TypeC port mode if needed */
+
+	if (!dig_port->tc_link_refcount &&
+	    intel_tc_port_needs_reset(dig_port))
+		intel_tc_port_reset_mode(dig_port, required_lanes);
+
+	WARN_ON(dig_port->tc_lock_wakeref);
+	dig_port->tc_lock_wakeref = wakeref;
+}
+
+void intel_tc_port_lock(struct intel_digital_port *dig_port)
+{
+	__intel_tc_port_lock(dig_port, 1);
 }
 
 void intel_tc_port_unlock(struct intel_digital_port *dig_port)
 {
+	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
+	intel_wakeref_t wakeref = fetch_and_zero(&dig_port->tc_lock_wakeref);
+
+	mutex_unlock(&dig_port->tc_lock);
+
+	intel_display_power_put_async(dev_priv, POWER_DOMAIN_DISPLAY_CORE,
+				      wakeref);
+}
+
+void intel_tc_port_get_link(struct intel_digital_port *dig_port,
+			    int required_lanes)
+{
+	__intel_tc_port_lock(dig_port, required_lanes);
+	dig_port->tc_link_refcount++;
+	intel_tc_port_unlock(dig_port);
+}
+
+void intel_tc_port_put_link(struct intel_digital_port *dig_port)
+{
+	mutex_lock(&dig_port->tc_lock);
+	dig_port->tc_link_refcount--;
 	mutex_unlock(&dig_port->tc_lock);
 }
 
@@ -417,4 +461,5 @@ intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy)
 {
 	mutex_init(&dig_port->tc_lock);
 	dig_port->tc_legacy_port = is_legacy;
+	dig_port->tc_link_refcount = 0;
 }
diff --git a/drivers/gpu/drm/i915/intel_tc.h b/drivers/gpu/drm/i915/intel_tc.h
index 91c6e7459cc9..c1870acf6516 100644
--- a/drivers/gpu/drm/i915/intel_tc.h
+++ b/drivers/gpu/drm/i915/intel_tc.h
@@ -14,6 +14,9 @@ int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port);
 void intel_tc_port_sanitize(struct intel_digital_port *dig_port);
 void intel_tc_port_lock(struct intel_digital_port *dig_port);
 void intel_tc_port_unlock(struct intel_digital_port *dig_port);
+void intel_tc_port_get_link(struct intel_digital_port *dig_port,
+			    int required_lanes);
+void intel_tc_port_put_link(struct intel_digital_port *dig_port);
 
 void intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy);
 
-- 
2.17.1

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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 21/23] drm/i915: Add state verification for the TypeC port mode
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (19 preceding siblings ...)
  2019-06-04 14:58 ` [PATCH 20/23] drm/i915: Keep the TypeC port mode fixed when the port is active Imre Deak
@ 2019-06-04 14:58 ` Imre Deak
  2019-06-04 14:58 ` [PATCH 22/23] drm/i915: Remove unneeded disconnect in TypeC legacy " Imre Deak
                   ` (9 subsequent siblings)
  30 siblings, 0 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-04 14:58 UTC (permalink / raw)
  To: intel-gfx

Add state verification for the TypeC port mode wrt. the port's AUX power
well enabling/disabling. Also check the correctness of changing the port
mode:
- When enabling/disabling the AUX power well for a TypeC port we must hold
  already the TypeC port lock.
- When changing the TypeC port mode the port's AUX power domain must be
  disabled.

Cc: José Roberto de Souza <jose.souza@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_display_power.c | 99 ++++++++++++++++++++--
 drivers/gpu/drm/i915/intel_tc.c            |  2 +
 drivers/gpu/drm/i915/intel_tc.h            | 10 ++-
 3 files changed, 102 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display_power.c b/drivers/gpu/drm/i915/intel_display_power.c
index 14cf04bf0bf4..3ee6fd03d112 100644
--- a/drivers/gpu/drm/i915/intel_display_power.c
+++ b/drivers/gpu/drm/i915/intel_display_power.c
@@ -16,6 +16,7 @@
 #include "intel_drv.h"
 #include "intel_hotplug.h"
 #include "intel_sideband.h"
+#include "intel_tc.h"
 
 bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
 					 enum i915_power_well_id power_well_id);
@@ -445,26 +446,110 @@ icl_combo_phy_aux_power_well_disable(struct drm_i915_private *dev_priv,
 #define ICL_TBT_AUX_PW_TO_CH(pw_idx)	\
 	((pw_idx) - ICL_PW_CTL_IDX_AUX_TBT1 + AUX_CH_C)
 
+static enum aux_ch icl_tc_phy_aux_ch(struct drm_i915_private *dev_priv,
+				     struct i915_power_well *power_well)
+{
+	int pw_idx = power_well->desc->hsw.idx;
+
+	return power_well->desc->hsw.is_tc_tbt ? ICL_TBT_AUX_PW_TO_CH(pw_idx) :
+						 ICL_AUX_PW_TO_CH(pw_idx);
+}
+
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
+
+static u64 async_put_domains_mask(struct i915_power_domains *power_domains);
+
+static int power_well_async_ref_count(struct drm_i915_private *dev_priv,
+				      struct i915_power_well *power_well)
+{
+	enum intel_display_power_domain domain;
+	u64 async_domains = async_put_domains_mask(&dev_priv->power_domains);
+	int refs = 0;
+
+	for_each_power_domain(domain, power_well->desc->domains)
+		refs += !!(async_domains & BIT_ULL(domain));
+
+	WARN_ON(refs > power_well->count);
+
+	return refs;
+}
+
+static void icl_tc_port_assert_ref_held(struct drm_i915_private *dev_priv,
+					struct i915_power_well *power_well)
+{
+	enum aux_ch aux_ch = icl_tc_phy_aux_ch(dev_priv, power_well);
+	struct intel_digital_port *dig_port = NULL;
+	struct intel_encoder *encoder;
+
+	/* Bypass the check if all references are released asynchronously */
+	if (power_well_async_ref_count(dev_priv, power_well) ==
+	    power_well->count)
+		return;
+
+	aux_ch = icl_tc_phy_aux_ch(dev_priv, power_well);
+
+	for_each_intel_encoder(&dev_priv->drm, encoder) {
+		if (!intel_port_is_tc(dev_priv, encoder->port))
+			continue;
+
+		/* We'll check the MST primary port */
+		if (encoder->type == INTEL_OUTPUT_DP_MST)
+			continue;
+
+		dig_port = enc_to_dig_port(&encoder->base);
+		if (WARN_ON(!dig_port))
+			continue;
+
+		if (dig_port->aux_ch != aux_ch) {
+			dig_port = NULL;
+			continue;
+		}
+
+		break;
+	}
+
+	if (WARN_ON(!dig_port))
+		return;
+
+	WARN_ON(!intel_tc_port_ref_held(dig_port));
+}
+
+#else
+
+static void icl_tc_port_assert_ref_held(struct drm_i915_private *dev_priv,
+					struct i915_power_well *power_well)
+{
+}
+
+#endif
+
 static void
 icl_tc_phy_aux_power_well_enable(struct drm_i915_private *dev_priv,
 				 struct i915_power_well *power_well)
 {
-	int pw_idx = power_well->desc->hsw.idx;
-	bool is_tbt = power_well->desc->hsw.is_tc_tbt;
-	enum aux_ch aux_ch;
+	enum aux_ch aux_ch = icl_tc_phy_aux_ch(dev_priv, power_well);
 	u32 val;
 
-	aux_ch = is_tbt ? ICL_TBT_AUX_PW_TO_CH(pw_idx) :
-			  ICL_AUX_PW_TO_CH(pw_idx);
+	icl_tc_port_assert_ref_held(dev_priv, power_well);
+
 	val = I915_READ(DP_AUX_CH_CTL(aux_ch));
 	val &= ~DP_AUX_CH_CTL_TBT_IO;
-	if (is_tbt)
+	if (power_well->desc->hsw.is_tc_tbt)
 		val |= DP_AUX_CH_CTL_TBT_IO;
 	I915_WRITE(DP_AUX_CH_CTL(aux_ch), val);
 
 	hsw_power_well_enable(dev_priv, power_well);
 }
 
+static void
+icl_tc_phy_aux_power_well_disable(struct drm_i915_private *dev_priv,
+				  struct i915_power_well *power_well)
+{
+	icl_tc_port_assert_ref_held(dev_priv, power_well);
+
+	hsw_power_well_disable(dev_priv, power_well);
+}
+
 /*
  * We should only use the power well if we explicitly asked the hardware to
  * enable it, so check if it's enabled and also check if we've requested it to
@@ -3114,7 +3199,7 @@ static const struct i915_power_well_ops icl_combo_phy_aux_power_well_ops = {
 static const struct i915_power_well_ops icl_tc_phy_aux_power_well_ops = {
 	.sync_hw = hsw_power_well_sync_hw,
 	.enable = icl_tc_phy_aux_power_well_enable,
-	.disable = hsw_power_well_disable,
+	.disable = icl_tc_phy_aux_power_well_disable,
 	.is_enabled = hsw_power_well_enabled,
 };
 
diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
index e79f6ceb26f3..d807127ad5f1 100644
--- a/drivers/gpu/drm/i915/intel_tc.c
+++ b/drivers/gpu/drm/i915/intel_tc.c
@@ -325,6 +325,8 @@ static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port,
 	enum tc_port_mode old_tc_mode = dig_port->tc_mode;
 
 	intel_display_power_flush_work(dev_priv);
+	WARN_ON(intel_display_power_is_enabled(dev_priv,
+					       intel_aux_power_domain(dig_port)));
 
 	icl_tc_phy_disconnect(dig_port);
 	icl_tc_phy_connect(dig_port, required_lanes);
diff --git a/drivers/gpu/drm/i915/intel_tc.h b/drivers/gpu/drm/i915/intel_tc.h
index c1870acf6516..568844e1846f 100644
--- a/drivers/gpu/drm/i915/intel_tc.h
+++ b/drivers/gpu/drm/i915/intel_tc.h
@@ -2,8 +2,8 @@
 #define __INTEL_TC_H__
 
 #include <linux/types.h>
-
-struct intel_digital_port;
+#include <linux/mutex.h>
+#include "intel_drv.h"
 
 void icl_tc_phy_disconnect(struct intel_digital_port *dig_port);
 
@@ -18,6 +18,12 @@ void intel_tc_port_get_link(struct intel_digital_port *dig_port,
 			    int required_lanes);
 void intel_tc_port_put_link(struct intel_digital_port *dig_port);
 
+static inline int intel_tc_port_ref_held(struct intel_digital_port *dig_port)
+{
+	return mutex_is_locked(&dig_port->tc_lock) ||
+	       dig_port->tc_link_refcount;
+}
+
 void intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy);
 
 #endif /* __INTEL_TC_H__ */
-- 
2.17.1

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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 22/23] drm/i915: Remove unneeded disconnect in TypeC legacy port mode
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (20 preceding siblings ...)
  2019-06-04 14:58 ` [PATCH 21/23] drm/i915: Add state verification for the TypeC port mode Imre Deak
@ 2019-06-04 14:58 ` Imre Deak
  2019-06-08  0:18   ` Souza, Jose
  2019-06-04 14:58 ` [PATCH 23/23] drm/i915: WARN about invalid lane reversal in TBT-alt/DP-alt modes Imre Deak
                   ` (8 subsequent siblings)
  30 siblings, 1 reply; 79+ messages in thread
From: Imre Deak @ 2019-06-04 14:58 UTC (permalink / raw)
  To: intel-gfx

Disconnecting the TypeC PHY when the port is in legacy mode is not
necessary:
- BSpec doesn't specify a disconnect sequence for legacy mode.
- The use of the PHY is dedicated for the display in legacy mode.
- We keep the PHY always connected during runtime as well in legacy
  mode.

We disconnect the PHY when needed during a disabling modeset for the
port, so we can also remove the disconnect call from the destroy hook.

Cc: José Roberto de Souza <jose.souza@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c | 21 +--------------------
 drivers/gpu/drm/i915/intel_tc.c  |  4 +++-
 drivers/gpu/drm/i915/intel_tc.h  |  2 --
 3 files changed, 4 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 138950941246..9c198f1a3a91 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -3941,31 +3941,12 @@ static int intel_ddi_compute_config(struct intel_encoder *encoder,
 	return 0;
 }
 
-static void intel_ddi_encoder_suspend(struct intel_encoder *encoder)
-{
-	struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
-
-	intel_dp_encoder_suspend(encoder);
-
-	/*
-	 * TODO: disconnect also from USB DP alternate mode once we have a
-	 * way to handle the modeset restore in that mode during resume
-	 * even if the sink has disappeared while being suspended.
-	 */
-	if (dig_port->tc_legacy_port)
-		icl_tc_phy_disconnect(dig_port);
-}
-
 static void intel_ddi_encoder_destroy(struct drm_encoder *encoder)
 {
 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
-	struct drm_i915_private *i915 = to_i915(encoder->dev);
 
 	intel_dp_encoder_flush_work(encoder);
 
-	if (intel_port_is_tc(i915, dig_port->base.port))
-		icl_tc_phy_disconnect(dig_port);
-
 	drm_encoder_cleanup(encoder);
 	kfree(dig_port);
 }
@@ -4254,7 +4235,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
 	intel_encoder->update_pipe = intel_ddi_update_pipe;
 	intel_encoder->get_hw_state = intel_ddi_get_hw_state;
 	intel_encoder->get_config = intel_ddi_get_config;
-	intel_encoder->suspend = intel_ddi_encoder_suspend;
+	intel_encoder->suspend = intel_dp_encoder_suspend;
 	intel_encoder->get_power_domains = intel_ddi_get_power_domains;
 	intel_encoder->type = INTEL_OUTPUT_DDI;
 	intel_encoder->power_domain = intel_port_to_power_domain(port);
diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
index d807127ad5f1..29a59ce7f073 100644
--- a/drivers/gpu/drm/i915/intel_tc.c
+++ b/drivers/gpu/drm/i915/intel_tc.c
@@ -245,10 +245,12 @@ static void icl_tc_phy_connect(struct intel_digital_port *dig_port,
  * See the comment at the connect function. This implements the Disconnect
  * Flow.
  */
-void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
+static void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
 {
 	switch (dig_port->tc_mode) {
 	case TC_PORT_LEGACY:
+		/* Nothing to do, we never disconnect from legacy mode */
+		break;
 	case TC_PORT_DP_ALT:
 		icl_tc_phy_set_safe_mode(dig_port, true);
 		dig_port->tc_mode = TC_PORT_TBT_ALT;
diff --git a/drivers/gpu/drm/i915/intel_tc.h b/drivers/gpu/drm/i915/intel_tc.h
index 568844e1846f..6d7e813c082b 100644
--- a/drivers/gpu/drm/i915/intel_tc.h
+++ b/drivers/gpu/drm/i915/intel_tc.h
@@ -5,8 +5,6 @@
 #include <linux/mutex.h>
 #include "intel_drv.h"
 
-void icl_tc_phy_disconnect(struct intel_digital_port *dig_port);
-
 bool intel_tc_port_connected(struct intel_digital_port *dig_port);
 u32 intel_tc_port_get_lane_info(struct intel_digital_port *dig_port);
 int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port);
-- 
2.17.1

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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* [PATCH 23/23] drm/i915: WARN about invalid lane reversal in TBT-alt/DP-alt modes
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (21 preceding siblings ...)
  2019-06-04 14:58 ` [PATCH 22/23] drm/i915: Remove unneeded disconnect in TypeC legacy " Imre Deak
@ 2019-06-04 14:58 ` Imre Deak
  2019-06-08  0:13   ` Souza, Jose
  2019-06-04 17:30 ` ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Fix TypeC port mode switching Patchwork
                   ` (7 subsequent siblings)
  30 siblings, 1 reply; 79+ messages in thread
From: Imre Deak @ 2019-06-04 14:58 UTC (permalink / raw)
  To: intel-gfx

Lane reversal happens only in the FIA module for TBT-alt/DP-alt mode, so
WARN if lane reversal is attempted at a different level. See the
BSpec DDI_BUF_CTL register description.

Cc: Manasi Navare <manasi.d.navare@intel.com>
Cc: José Roberto de Souza <jose.souza@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 9c198f1a3a91..5f535f17d7b3 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -3591,6 +3591,8 @@ static void intel_ddi_set_fia_lane_count(struct intel_encoder *encoder,
 	u32 val = I915_READ(PORT_TX_DFLEXDPMLE1);
 	bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL;
 
+	WARN_ON(lane_reversal && dig_port->tc_mode != TC_PORT_LEGACY);
+
 	val &= ~DFLEXDPMLE1_DPMLETC_MASK(tc_port);
 	switch (pipe_config->lane_count) {
 	case 1:
-- 
2.17.1

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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Fix TypeC port mode switching
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (22 preceding siblings ...)
  2019-06-04 14:58 ` [PATCH 23/23] drm/i915: WARN about invalid lane reversal in TBT-alt/DP-alt modes Imre Deak
@ 2019-06-04 17:30 ` Patchwork
  2019-06-04 17:39 ` ✗ Fi.CI.SPARSE: " Patchwork
                   ` (6 subsequent siblings)
  30 siblings, 0 replies; 79+ messages in thread
From: Patchwork @ 2019-06-04 17:30 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Fix TypeC port mode switching
URL   : https://patchwork.freedesktop.org/series/61590/
State : warning

== Summary ==

$ dim checkpatch origin/drm-tip
14db34664cf1 drm/i915/icl: Add support to read out the TBT PLL HW state
90cdad322f0f drm/i915: Tune down WARNs about TBT AUX power well enabling
ee8152f95440 drm/i915: Move the TypeC port handling code to a separate file
-:16: WARNING:COMMIT_LOG_LONG_LINE: Possible unwrapped commit description (prefer a maximum 75 chars per line)
#16: 
- s/intel_dp_get_fia_supported_lane_count()/intel_tc_port_fia_max_lane_count()/

-:371: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#371: 
new file mode 100644

-:552: CHECK:LINE_SPACING: Please don't use multiple blank lines
#552: FILE: drivers/gpu/drm/i915/intel_tc.c:177:
+
+

-:612: WARNING:SPDX_LICENSE_TAG: Missing or malformed SPDX-License-Identifier tag in line 1
#612: FILE: drivers/gpu/drm/i915/intel_tc.h:1:
+#ifndef __INTEL_TC_H__

total: 0 errors, 3 warnings, 1 checks, 554 lines checked
fa3cd0d9851c drm/i915: Sanitize the terminology used for TypeC port modes
2c6f803c95c9 drm/i915: Don't enable the DDI-IO power in the TypeC TBT-alt mode
b98f89ef27e8 drm/i915: Fix the TBT AUX power well enabling
de2d578fdfab drm/i915: Use the correct AUX power domain in TypeC TBT-alt mode
4b3efd91dc32 drm/i915: Unify the TypeC port notation in debug/error messages
-:38: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#38: FILE: drivers/gpu/drm/i915/intel_tc.c:21:
+	if (WARN_ON(INTEL_GEN(dev_priv) < 11 ||
+	    (unsigned int)tc_port >= I915_MAX_TC_PORTS))

total: 0 errors, 0 warnings, 1 checks, 77 lines checked
bc3a3c77a3f5 drm/i915: Factor out common parts from TypeC port handling functions
ebb66c60f3cf drm/i915: Wait for TypeC PHY complete flag to clear in safe mode
58c036477acb drm/i915: Handle the TCCOLD power-down event
95125fafe1ec drm/i915: Sanitize the TypeC connect/detect sequences
dfbe290320f4 drm/i915: Fix the TypeC port mode sanitization during loading/resume
224419d6882e drm/i915: Keep the TypeC port mode fixed for detect/AUX transfers
-:88: CHECK:UNCOMMENTED_DEFINITION: struct mutex definition without comment
#88: FILE: drivers/gpu/drm/i915/intel_drv.h:1227:
+	struct mutex tc_lock;

total: 0 errors, 0 warnings, 1 checks, 116 lines checked
c42d11cbf62e drm/i915: Sanitize the TypeC FIA lane configuration decoding
919f648b1dc1 drm/i915: Sanitize the shared DPLL reserve/release interface
-:527: WARNING:TYPO_SPELLING: 'succesfully' may be misspelled - perhaps 'successfully'?
#527: FILE: drivers/gpu/drm/i915/intel_dpll_mgr.c:3349:
+ * True if all required DPLLs were succesfully reserved.

total: 0 errors, 1 warnings, 0 checks, 542 lines checked
cb7a3ff173c9 drm/i915: Sanitize the shared DPLL find/reference interface
38fef1eb02de drm/i915/icl: Split getting the DPLLs to port type specific functions
4653a4e49ccc drm/i915/icl: Reserve all required PLLs for TypeC ports
97faef600998 drm/i915: Keep the TypeC port mode fixed when the port is active
94663bce7d66 drm/i915: Add state verification for the TypeC port mode
cbe3469c83b3 drm/i915: Remove unneeded disconnect in TypeC legacy port mode
ead9432bec38 drm/i915: WARN about invalid lane reversal in TBT-alt/DP-alt modes

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

^ permalink raw reply	[flat|nested] 79+ messages in thread

* ✗ Fi.CI.SPARSE: warning for drm/i915: Fix TypeC port mode switching
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (23 preceding siblings ...)
  2019-06-04 17:30 ` ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Fix TypeC port mode switching Patchwork
@ 2019-06-04 17:39 ` Patchwork
  2019-06-05  5:24 ` ✓ Fi.CI.BAT: success " Patchwork
                   ` (5 subsequent siblings)
  30 siblings, 0 replies; 79+ messages in thread
From: Patchwork @ 2019-06-04 17:39 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Fix TypeC port mode switching
URL   : https://patchwork.freedesktop.org/series/61590/
State : warning

== Summary ==

$ dim sparse origin/drm-tip
Sparse version: v0.5.2
Commit: drm/i915/icl: Add support to read out the TBT PLL HW state
Okay!

Commit: drm/i915: Tune down WARNs about TBT AUX power well enabling
Okay!

Commit: drm/i915: Move the TypeC port handling code to a separate file
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+./include/uapi/linux/perf_event.h:147:56: warning: cast truncates bits from constant value (8000000000000000 becomes 0)

Commit: drm/i915: Sanitize the terminology used for TypeC port modes
Okay!

Commit: drm/i915: Don't enable the DDI-IO power in the TypeC TBT-alt mode
Okay!

Commit: drm/i915: Fix the TBT AUX power well enabling
Okay!

Commit: drm/i915: Use the correct AUX power domain in TypeC TBT-alt mode
Okay!

Commit: drm/i915: Unify the TypeC port notation in debug/error messages
Okay!

Commit: drm/i915: Factor out common parts from TypeC port handling functions
Okay!

Commit: drm/i915: Wait for TypeC PHY complete flag to clear in safe mode
Okay!

Commit: drm/i915: Handle the TCCOLD power-down event
Okay!

Commit: drm/i915: Sanitize the TypeC connect/detect sequences
Okay!

Commit: drm/i915: Fix the TypeC port mode sanitization during loading/resume
+./include/uapi/linux/perf_event.h:147:56: warning: cast truncates bits from constant value (8000000000000000 becomes 0)

Commit: drm/i915: Keep the TypeC port mode fixed for detect/AUX transfers
Okay!

Commit: drm/i915: Sanitize the TypeC FIA lane configuration decoding
Okay!

Commit: drm/i915: Sanitize the shared DPLL reserve/release interface
Okay!

Commit: drm/i915: Sanitize the shared DPLL find/reference interface
Okay!

Commit: drm/i915/icl: Split getting the DPLLs to port type specific functions
Okay!

Commit: drm/i915/icl: Reserve all required PLLs for TypeC ports
Okay!

Commit: drm/i915: Keep the TypeC port mode fixed when the port is active
Okay!

Commit: drm/i915: Add state verification for the TypeC port mode
+./include/uapi/linux/perf_event.h:147:56: warning: cast truncates bits from constant value (8000000000000000 becomes 0)

Commit: drm/i915: Remove unneeded disconnect in TypeC legacy port mode
Okay!

Commit: drm/i915: WARN about invalid lane reversal in TBT-alt/DP-alt modes
Okay!

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

^ permalink raw reply	[flat|nested] 79+ messages in thread

* ✓ Fi.CI.BAT: success for drm/i915: Fix TypeC port mode switching
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (24 preceding siblings ...)
  2019-06-04 17:39 ` ✗ Fi.CI.SPARSE: " Patchwork
@ 2019-06-05  5:24 ` Patchwork
  2019-06-05 16:36 ` ✓ Fi.CI.IGT: " Patchwork
                   ` (4 subsequent siblings)
  30 siblings, 0 replies; 79+ messages in thread
From: Patchwork @ 2019-06-05  5:24 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Fix TypeC port mode switching
URL   : https://patchwork.freedesktop.org/series/61590/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_6187 -> Patchwork_13170
====================================================

Summary
-------

  **WARNING**

  Minor unknown changes coming with Patchwork_13170 need to be verified
  manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in Patchwork_13170, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_13170:

### IGT changes ###

#### Warnings ####

  * igt@i915_module_load@reload:
    - fi-icl-u2:          [DMESG-WARN][1] ([fdo#110595]) -> [DMESG-WARN][2] +2 similar issues
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/fi-icl-u2/igt@i915_module_load@reload.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/fi-icl-u2/igt@i915_module_load@reload.html

  
Known issues
------------

  Here are the changes found in Patchwork_13170 that come from known issues:

### IGT changes ###

#### Possible fixes ####

  * igt@kms_cursor_legacy@basic-flip-after-cursor-varying-size:
    - fi-icl-u3:          [DMESG-WARN][3] ([fdo#107724]) -> [PASS][4] +1 similar issue
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/fi-icl-u3/igt@kms_cursor_legacy@basic-flip-after-cursor-varying-size.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/fi-icl-u3/igt@kms_cursor_legacy@basic-flip-after-cursor-varying-size.html

  * igt@kms_pipe_crc_basic@suspend-read-crc-pipe-a:
    - fi-blb-e6850:       [INCOMPLETE][5] ([fdo#107718]) -> [PASS][6]
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/fi-blb-e6850/igt@kms_pipe_crc_basic@suspend-read-crc-pipe-a.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/fi-blb-e6850/igt@kms_pipe_crc_basic@suspend-read-crc-pipe-a.html

  
#### Warnings ####

  * igt@kms_frontbuffer_tracking@basic:
    - fi-icl-u3:          [FAIL][7] ([fdo#103167]) -> [DMESG-FAIL][8] ([fdo#103167] / [fdo#107724])
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/fi-icl-u3/igt@kms_frontbuffer_tracking@basic.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/fi-icl-u3/igt@kms_frontbuffer_tracking@basic.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#103167]: https://bugs.freedesktop.org/show_bug.cgi?id=103167
  [fdo#107718]: https://bugs.freedesktop.org/show_bug.cgi?id=107718
  [fdo#107724]: https://bugs.freedesktop.org/show_bug.cgi?id=107724
  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#110595]: https://bugs.freedesktop.org/show_bug.cgi?id=110595
  [fdo#110829]: https://bugs.freedesktop.org/show_bug.cgi?id=110829


Participating hosts (54 -> 46)
------------------------------

  Missing    (8): fi-ilk-m540 fi-hsw-4200u fi-byt-squawks fi-bsw-cyan fi-ctg-p8600 fi-kbl-7560u fi-byt-clapper fi-bdw-samus 


Build changes
-------------

  * Linux: CI_DRM_6187 -> Patchwork_13170

  CI_DRM_6187: 201dda6b2f7138214cdba69211c7504ce7b8b96e @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_5037: a98c9cd50aa48933217ca41055279ccb1680d25b @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  Patchwork_13170: ead9432bec38eac0430752d4b5b100c59fe7cfff @ git://anongit.freedesktop.org/gfx-ci/linux


== Linux commits ==

ead9432bec38 drm/i915: WARN about invalid lane reversal in TBT-alt/DP-alt modes
cbe3469c83b3 drm/i915: Remove unneeded disconnect in TypeC legacy port mode
94663bce7d66 drm/i915: Add state verification for the TypeC port mode
97faef600998 drm/i915: Keep the TypeC port mode fixed when the port is active
4653a4e49ccc drm/i915/icl: Reserve all required PLLs for TypeC ports
38fef1eb02de drm/i915/icl: Split getting the DPLLs to port type specific functions
cb7a3ff173c9 drm/i915: Sanitize the shared DPLL find/reference interface
919f648b1dc1 drm/i915: Sanitize the shared DPLL reserve/release interface
c42d11cbf62e drm/i915: Sanitize the TypeC FIA lane configuration decoding
224419d6882e drm/i915: Keep the TypeC port mode fixed for detect/AUX transfers
dfbe290320f4 drm/i915: Fix the TypeC port mode sanitization during loading/resume
95125fafe1ec drm/i915: Sanitize the TypeC connect/detect sequences
58c036477acb drm/i915: Handle the TCCOLD power-down event
ebb66c60f3cf drm/i915: Wait for TypeC PHY complete flag to clear in safe mode
bc3a3c77a3f5 drm/i915: Factor out common parts from TypeC port handling functions
4b3efd91dc32 drm/i915: Unify the TypeC port notation in debug/error messages
de2d578fdfab drm/i915: Use the correct AUX power domain in TypeC TBT-alt mode
b98f89ef27e8 drm/i915: Fix the TBT AUX power well enabling
2c6f803c95c9 drm/i915: Don't enable the DDI-IO power in the TypeC TBT-alt mode
fa3cd0d9851c drm/i915: Sanitize the terminology used for TypeC port modes
ee8152f95440 drm/i915: Move the TypeC port handling code to a separate file
90cdad322f0f drm/i915: Tune down WARNs about TBT AUX power well enabling
14db34664cf1 drm/i915/icl: Add support to read out the TBT PLL HW state

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* ✓ Fi.CI.IGT: success for drm/i915: Fix TypeC port mode switching
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (25 preceding siblings ...)
  2019-06-05  5:24 ` ✓ Fi.CI.BAT: success " Patchwork
@ 2019-06-05 16:36 ` Patchwork
  2019-06-07 17:59 ` ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Fix TypeC port mode switching (rev2) Patchwork
                   ` (3 subsequent siblings)
  30 siblings, 0 replies; 79+ messages in thread
From: Patchwork @ 2019-06-05 16:36 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Fix TypeC port mode switching
URL   : https://patchwork.freedesktop.org/series/61590/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_6187_full -> Patchwork_13170_full
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  

Known issues
------------

  Here are the changes found in Patchwork_13170_full that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_eio@reset-stress:
    - shard-snb:          [PASS][1] -> ([FAIL][2], [PASS][3]) ([fdo#109661])
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-snb6/igt@gem_eio@reset-stress.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-snb7/igt@gem_eio@reset-stress.html
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-snb4/igt@gem_eio@reset-stress.html

  * igt@gem_eio@unwedge-stress:
    - shard-snb:          [PASS][4] -> [FAIL][5] ([fdo#109661])
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-snb2/igt@gem_eio@unwedge-stress.html
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-snb2/igt@gem_eio@unwedge-stress.html

  * igt@i915_pm_rpm@gem-execbuf:
    - shard-iclb:         [PASS][6] -> [INCOMPLETE][7] ([fdo#107713] / [fdo#108840])
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-iclb4/igt@i915_pm_rpm@gem-execbuf.html
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-iclb7/igt@i915_pm_rpm@gem-execbuf.html

  * igt@i915_suspend@debugfs-reader:
    - shard-skl:          [PASS][8] -> ([PASS][9], [INCOMPLETE][10]) ([fdo#104108]) +1 similar issue
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-skl8/igt@i915_suspend@debugfs-reader.html
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-skl4/igt@i915_suspend@debugfs-reader.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-skl3/igt@i915_suspend@debugfs-reader.html

  * igt@kms_cursor_crc@pipe-b-cursor-suspend:
    - shard-apl:          [PASS][11] -> ([PASS][12], [DMESG-WARN][13]) ([fdo#108566]) +3 similar issues
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-apl2/igt@kms_cursor_crc@pipe-b-cursor-suspend.html
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-apl8/igt@kms_cursor_crc@pipe-b-cursor-suspend.html
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-apl7/igt@kms_cursor_crc@pipe-b-cursor-suspend.html

  * igt@kms_dp_dsc@basic-dsc-enable-edp:
    - shard-iclb:         [PASS][14] -> [SKIP][15] ([fdo#109349])
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-iclb2/igt@kms_dp_dsc@basic-dsc-enable-edp.html
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-iclb8/igt@kms_dp_dsc@basic-dsc-enable-edp.html

  * igt@kms_flip@2x-flip-vs-expired-vblank:
    - shard-glk:          [PASS][16] -> ([FAIL][17], [PASS][18]) ([fdo#105363])
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-glk9/igt@kms_flip@2x-flip-vs-expired-vblank.html
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-glk4/igt@kms_flip@2x-flip-vs-expired-vblank.html
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-glk1/igt@kms_flip@2x-flip-vs-expired-vblank.html

  * igt@kms_flip@2x-modeset-vs-vblank-race-interruptible:
    - shard-glk:          [PASS][19] -> ([FAIL][20], [PASS][21]) ([fdo#103060])
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-glk3/igt@kms_flip@2x-modeset-vs-vblank-race-interruptible.html
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-glk8/igt@kms_flip@2x-modeset-vs-vblank-race-interruptible.html
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-glk6/igt@kms_flip@2x-modeset-vs-vblank-race-interruptible.html

  * igt@kms_flip@2x-plain-flip-fb-recreate-interruptible:
    - shard-glk:          [PASS][22] -> [FAIL][23] ([fdo#100368])
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-glk2/igt@kms_flip@2x-plain-flip-fb-recreate-interruptible.html
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-glk1/igt@kms_flip@2x-plain-flip-fb-recreate-interruptible.html

  * igt@kms_flip@flip-vs-expired-vblank-interruptible:
    - shard-glk:          [PASS][24] -> ([FAIL][25], [PASS][26]) ([fdo#102887] / [fdo#105363])
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-glk4/igt@kms_flip@flip-vs-expired-vblank-interruptible.html
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-glk2/igt@kms_flip@flip-vs-expired-vblank-interruptible.html
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-glk5/igt@kms_flip@flip-vs-expired-vblank-interruptible.html

  * igt@kms_flip_tiling@flip-to-x-tiled:
    - shard-iclb:         [PASS][27] -> [FAIL][28] ([fdo#108134])
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-iclb6/igt@kms_flip_tiling@flip-to-x-tiled.html
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-iclb3/igt@kms_flip_tiling@flip-to-x-tiled.html

  * igt@kms_frontbuffer_tracking@fbc-2p-primscrn-cur-indfb-draw-render:
    - shard-hsw:          [PASS][29] -> [SKIP][30] ([fdo#109271]) +41 similar issues
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-hsw1/igt@kms_frontbuffer_tracking@fbc-2p-primscrn-cur-indfb-draw-render.html
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-hsw1/igt@kms_frontbuffer_tracking@fbc-2p-primscrn-cur-indfb-draw-render.html

  * igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-cur-indfb-draw-render:
    - shard-iclb:         [PASS][31] -> [FAIL][32] ([fdo#103167]) +3 similar issues
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-iclb8/igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-cur-indfb-draw-render.html
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-iclb7/igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-cur-indfb-draw-render.html

  * igt@kms_plane_alpha_blend@pipe-c-coverage-7efc:
    - shard-skl:          [PASS][33] -> ([PASS][34], [FAIL][35]) ([fdo#108145] / [fdo#110403])
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-skl2/igt@kms_plane_alpha_blend@pipe-c-coverage-7efc.html
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-skl10/igt@kms_plane_alpha_blend@pipe-c-coverage-7efc.html
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-skl2/igt@kms_plane_alpha_blend@pipe-c-coverage-7efc.html

  * igt@kms_plane_lowres@pipe-a-tiling-x:
    - shard-iclb:         [PASS][36] -> [FAIL][37] ([fdo#103166])
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-iclb1/igt@kms_plane_lowres@pipe-a-tiling-x.html
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-iclb6/igt@kms_plane_lowres@pipe-a-tiling-x.html

  * igt@kms_psr@psr2_primary_mmap_cpu:
    - shard-iclb:         [PASS][38] -> [SKIP][39] ([fdo#109441]) +2 similar issues
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-iclb2/igt@kms_psr@psr2_primary_mmap_cpu.html
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-iclb5/igt@kms_psr@psr2_primary_mmap_cpu.html

  * igt@kms_setmode@basic:
    - shard-apl:          [PASS][40] -> [FAIL][41] ([fdo#99912])
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-apl3/igt@kms_setmode@basic.html
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-apl2/igt@kms_setmode@basic.html
    - shard-kbl:          [PASS][42] -> ([PASS][43], [FAIL][44]) ([fdo#99912])
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-kbl1/igt@kms_setmode@basic.html
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-kbl6/igt@kms_setmode@basic.html
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-kbl2/igt@kms_setmode@basic.html

  
#### Possible fixes ####

  * igt@gem_ctx_isolation@vecs0-s3:
    - shard-apl:          [DMESG-WARN][45] ([fdo#108566]) -> ([PASS][46], [PASS][47]) +1 similar issue
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-apl2/igt@gem_ctx_isolation@vecs0-s3.html
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-apl1/igt@gem_ctx_isolation@vecs0-s3.html
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-apl3/igt@gem_ctx_isolation@vecs0-s3.html

  * igt@gem_softpin@noreloc-s3:
    - shard-skl:          [INCOMPLETE][48] ([fdo#104108]) -> ([PASS][49], [PASS][50])
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-skl5/igt@gem_softpin@noreloc-s3.html
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-skl5/igt@gem_softpin@noreloc-s3.html
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-skl8/igt@gem_softpin@noreloc-s3.html

  * igt@kms_cursor_legacy@2x-long-cursor-vs-flip-atomic:
    - shard-hsw:          [FAIL][51] ([fdo#105767]) -> [PASS][52]
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-hsw4/igt@kms_cursor_legacy@2x-long-cursor-vs-flip-atomic.html
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-hsw2/igt@kms_cursor_legacy@2x-long-cursor-vs-flip-atomic.html

  * igt@kms_draw_crc@draw-method-xrgb2101010-blt-untiled:
    - shard-snb:          [SKIP][53] ([fdo#109271]) -> ([PASS][54], [PASS][55])
   [53]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-snb7/igt@kms_draw_crc@draw-method-xrgb2101010-blt-untiled.html
   [54]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-snb5/igt@kms_draw_crc@draw-method-xrgb2101010-blt-untiled.html
   [55]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-snb4/igt@kms_draw_crc@draw-method-xrgb2101010-blt-untiled.html

  * igt@kms_flip@2x-flip-vs-wf_vblank-interruptible:
    - shard-hsw:          [SKIP][56] ([fdo#109271]) -> [PASS][57] +1 similar issue
   [56]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-hsw1/igt@kms_flip@2x-flip-vs-wf_vblank-interruptible.html
   [57]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-hsw4/igt@kms_flip@2x-flip-vs-wf_vblank-interruptible.html

  * igt@kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-blt:
    - shard-iclb:         [FAIL][58] ([fdo#103167]) -> [PASS][59] +6 similar issues
   [58]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-iclb4/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-blt.html
   [59]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-iclb7/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-blt.html

  * igt@kms_frontbuffer_tracking@fbc-suspend:
    - shard-apl:          [DMESG-WARN][60] ([fdo#108566]) -> [PASS][61]
   [60]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-apl1/igt@kms_frontbuffer_tracking@fbc-suspend.html
   [61]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-apl6/igt@kms_frontbuffer_tracking@fbc-suspend.html

  * igt@kms_frontbuffer_tracking@fbcpsr-suspend:
    - shard-skl:          [INCOMPLETE][62] ([fdo#104108] / [fdo#106978]) -> ([PASS][63], [PASS][64])
   [62]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-skl6/igt@kms_frontbuffer_tracking@fbcpsr-suspend.html
   [63]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-skl7/igt@kms_frontbuffer_tracking@fbcpsr-suspend.html
   [64]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-skl3/igt@kms_frontbuffer_tracking@fbcpsr-suspend.html

  * igt@kms_psr@psr2_cursor_render:
    - shard-iclb:         [SKIP][65] ([fdo#109441]) -> [PASS][66] +2 similar issues
   [65]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-iclb3/igt@kms_psr@psr2_cursor_render.html
   [66]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-iclb2/igt@kms_psr@psr2_cursor_render.html

  * igt@perf@blocking:
    - shard-skl:          [FAIL][67] ([fdo#110728]) -> ([PASS][68], [PASS][69])
   [67]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-skl8/igt@perf@blocking.html
   [68]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-skl1/igt@perf@blocking.html
   [69]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-skl4/igt@perf@blocking.html

  * igt@prime_self_import@export-vs-gem_close-race:
    - shard-hsw:          [INCOMPLETE][70] ([fdo#103540]) -> [PASS][71] +1 similar issue
   [70]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-hsw2/igt@prime_self_import@export-vs-gem_close-race.html
   [71]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-hsw8/igt@prime_self_import@export-vs-gem_close-race.html

  
#### Warnings ####

  * igt@gem_mmap_gtt@forked-big-copy-xy:
    - shard-iclb:         [TIMEOUT][72] ([fdo#109673]) -> [INCOMPLETE][73] ([fdo#107713] / [fdo#109100])
   [72]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-iclb6/igt@gem_mmap_gtt@forked-big-copy-xy.html
   [73]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-iclb1/igt@gem_mmap_gtt@forked-big-copy-xy.html

  * igt@kms_flip@flip-vs-expired-vblank-interruptible:
    - shard-skl:          [FAIL][74] ([fdo#105363]) -> ([PASS][75], [FAIL][76]) ([fdo#105363])
   [74]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-skl6/igt@kms_flip@flip-vs-expired-vblank-interruptible.html
   [75]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-skl7/igt@kms_flip@flip-vs-expired-vblank-interruptible.html
   [76]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-skl10/igt@kms_flip@flip-vs-expired-vblank-interruptible.html

  * igt@kms_flip@flip-vs-suspend-interruptible:
    - shard-apl:          [DMESG-WARN][77] ([fdo#108566]) -> ([DMESG-WARN][78], [PASS][79]) ([fdo#108566]) +1 similar issue
   [77]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-apl7/igt@kms_flip@flip-vs-suspend-interruptible.html
   [78]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-apl4/igt@kms_flip@flip-vs-suspend-interruptible.html
   [79]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-apl7/igt@kms_flip@flip-vs-suspend-interruptible.html

  * igt@kms_plane_alpha_blend@pipe-c-constant-alpha-min:
    - shard-skl:          [FAIL][80] ([fdo#108145]) -> ([FAIL][81], [PASS][82]) ([fdo#108145]) +1 similar issue
   [80]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6187/shard-skl10/igt@kms_plane_alpha_blend@pipe-c-constant-alpha-min.html
   [81]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-skl6/igt@kms_plane_alpha_blend@pipe-c-constant-alpha-min.html
   [82]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/shard-skl9/igt@kms_plane_alpha_blend@pipe-c-constant-alpha-min.html

  
  [fdo#100368]: https://bugs.freedesktop.org/show_bug.cgi?id=100368
  [fdo#102887]: https://bugs.freedesktop.org/show_bug.cgi?id=102887
  [fdo#103060]: https://bugs.freedesktop.org/show_bug.cgi?id=103060
  [fdo#103166]: https://bugs.freedesktop.org/show_bug.cgi?id=103166
  [fdo#103167]: https://bugs.freedesktop.org/show_bug.cgi?id=103167
  [fdo#103540]: https://bugs.freedesktop.org/show_bug.cgi?id=103540
  [fdo#104108]: https://bugs.freedesktop.org/show_bug.cgi?id=104108
  [fdo#105363]: https://bugs.freedesktop.org/show_bug.cgi?id=105363
  [fdo#105767]: https://bugs.freedesktop.org/show_bug.cgi?id=105767
  [fdo#106978]: https://bugs.freedesktop.org/show_bug.cgi?id=106978
  [fdo#107713]: https://bugs.freedesktop.org/show_bug.cgi?id=107713
  [fdo#108134]: https://bugs.freedesktop.org/show_bug.cgi?id=108134
  [fdo#108145]: https://bugs.freedesktop.org/show_bug.cgi?id=108145
  [fdo#108566]: https://bugs.freedesktop.org/show_bug.cgi?id=108566
  [fdo#108840]: https://bugs.freedesktop.org/show_bug.cgi?id=108840
  [fdo#109100]: https://bugs.freedesktop.org/show_bug.cgi?id=109100
  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#109349]: https://bugs.freedesktop.org/show_bug.cgi?id=109349
  [fdo#109441]: https://bugs.freedesktop.org/show_bug.cgi?id=109441
  [fdo#109661]: https://bugs.freedesktop.org/show_bug.cgi?id=109661
  [fdo#109673]: https://bugs.freedesktop.org/show_bug.cgi?id=109673
  [fdo#110403]: https://bugs.freedesktop.org/show_bug.cgi?id=110403
  [fdo#110728]: https://bugs.freedesktop.org/show_bug.cgi?id=110728
  [fdo#99912]: https://bugs.freedesktop.org/show_bug.cgi?id=99912


Participating hosts (10 -> 10)
------------------------------

  No changes in participating hosts


Build changes
-------------

  * Linux: CI_DRM_6187 -> Patchwork_13170

  CI_DRM_6187: 201dda6b2f7138214cdba69211c7504ce7b8b96e @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_5037: a98c9cd50aa48933217ca41055279ccb1680d25b @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  Patchwork_13170: ead9432bec38eac0430752d4b5b100c59fe7cfff @ git://anongit.freedesktop.org/gfx-ci/linux
  piglit_4509: fdc5a4ca11124ab8413c7988896eec4c97336694 @ git://anongit.freedesktop.org/piglit

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13170/
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 03/23] drm/i915: Move the TypeC port handling code to a separate file
  2019-06-04 14:58 ` [PATCH 03/23] drm/i915: Move the TypeC port handling code to a separate file Imre Deak
@ 2019-06-06  8:42   ` Jani Nikula
  2019-06-06  8:43     ` Jani Nikula
                       ` (2 more replies)
  2019-06-07 17:56   ` Souza, Jose
  1 sibling, 3 replies; 79+ messages in thread
From: Jani Nikula @ 2019-06-06  8:42 UTC (permalink / raw)
  To: Imre Deak, intel-gfx; +Cc: Paulo Zanoni

On Tue, 04 Jun 2019, Imre Deak <imre.deak@intel.com> wrote:
> Move the TypeC port handling functions to a new file for clarity.
>
> While at it:
> - s/icl_tc_port_connected()/intel_tc_port_connected()/
>   icl_tc_phy_disconnect(), will be unexported later.
>
> - s/intel_dp_get_fia_supported_lane_count()/intel_tc_port_fia_max_lane_count()/
>   It's used for HDMI legacy mode too.
>
> - Simplify function interfaces by passing only dig_port to them.
>
> No functional changes.

Some nitpicks below.

BR,
Jani.


>
> Cc: Animesh Manna <animesh.manna@intel.com>
> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Cc: José Roberto de Souza <jose.souza@intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/Makefile             |   3 +-
>  drivers/gpu/drm/i915/Makefile.header-test |   1 +
>  drivers/gpu/drm/i915/intel_ddi.c          |   6 +-
>  drivers/gpu/drm/i915/intel_dp.c           | 227 +--------------------
>  drivers/gpu/drm/i915/intel_dp.h           |   2 -
>  drivers/gpu/drm/i915/intel_tc.c           | 230 ++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_tc.h           |  13 ++
>  7 files changed, 252 insertions(+), 230 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/intel_tc.c
>  create mode 100644 drivers/gpu/drm/i915/intel_tc.h
>
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index c0a7b2994077..74c4d11d83eb 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -171,7 +171,8 @@ i915-y += intel_audio.o \
>  	  intel_psr.o \
>  	  intel_quirks.o \
>  	  intel_sideband.o \
> -	  intel_sprite.o
> +	  intel_sprite.o \
> +	  intel_tc.o
>  i915-$(CONFIG_ACPI)		+= intel_acpi.o intel_opregion.o
>  i915-$(CONFIG_DRM_FBDEV_EMULATION)	+= intel_fbdev.o
>  
> diff --git a/drivers/gpu/drm/i915/Makefile.header-test b/drivers/gpu/drm/i915/Makefile.header-test
> index 6ef3b647ac65..e80e8e45b09c 100644
> --- a/drivers/gpu/drm/i915/Makefile.header-test
> +++ b/drivers/gpu/drm/i915/Makefile.header-test
> @@ -58,6 +58,7 @@ header_test := \
>  	intel_sdvo.h \
>  	intel_sideband.h \
>  	intel_sprite.h \
> +	intel_tc.h \
>  	intel_tv.h \
>  	intel_uncore.h \
>  	intel_vdsc.h \
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index 350eaf54f01f..5a1c98438375 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -45,6 +45,7 @@
>  #include "intel_lspcon.h"
>  #include "intel_panel.h"
>  #include "intel_psr.h"
> +#include "intel_tc.h"
>  #include "intel_vdsc.h"
>  
>  struct ddi_buf_trans {
> @@ -3904,7 +3905,6 @@ static int intel_ddi_compute_config(struct intel_encoder *encoder,
>  static void intel_ddi_encoder_suspend(struct intel_encoder *encoder)
>  {
>  	struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
> -	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
>  
>  	intel_dp_encoder_suspend(encoder);
>  
> @@ -3914,7 +3914,7 @@ static void intel_ddi_encoder_suspend(struct intel_encoder *encoder)
>  	 * even if the sink has disappeared while being suspended.
>  	 */
>  	if (dig_port->tc_legacy_port)
> -		icl_tc_phy_disconnect(i915, dig_port);
> +		icl_tc_phy_disconnect(dig_port);
>  }
>  
>  static void intel_ddi_encoder_reset(struct drm_encoder *drm_encoder)
> @@ -3936,7 +3936,7 @@ static void intel_ddi_encoder_destroy(struct drm_encoder *encoder)
>  	intel_dp_encoder_flush_work(encoder);
>  
>  	if (intel_port_is_tc(i915, dig_port->base.port))
> -		icl_tc_phy_disconnect(i915, dig_port);
> +		icl_tc_phy_disconnect(dig_port);
>  
>  	drm_encoder_cleanup(encoder);
>  	kfree(dig_port);
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 24b56b2a76c8..b69310bd9914 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -62,6 +62,7 @@
>  #include "intel_panel.h"
>  #include "intel_psr.h"
>  #include "intel_sideband.h"
> +#include "intel_tc.h"
>  #include "intel_vdsc.h"
>  
>  #define DP_DPRX_ESI_LEN 14
> @@ -211,46 +212,13 @@ static int intel_dp_max_common_rate(struct intel_dp *intel_dp)
>  	return intel_dp->common_rates[intel_dp->num_common_rates - 1];
>  }
>  
> -static int intel_dp_get_fia_supported_lane_count(struct intel_dp *intel_dp)
> -{
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> -	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> -	intel_wakeref_t wakeref;
> -	u32 lane_info;
> -
> -	if (tc_port == PORT_TC_NONE || dig_port->tc_type != TC_PORT_TYPEC)
> -		return 4;
> -
> -	lane_info = 0;
> -	with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref)
> -		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
> -			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
> -				DP_LANE_ASSIGNMENT_SHIFT(tc_port);
> -
> -	switch (lane_info) {
> -	default:
> -		MISSING_CASE(lane_info);
> -	case 1:
> -	case 2:
> -	case 4:
> -	case 8:
> -		return 1;
> -	case 3:
> -	case 12:
> -		return 2;
> -	case 15:
> -		return 4;
> -	}
> -}
> -
>  /* Theoretical max between source and sink */
>  static int intel_dp_max_common_lane_count(struct intel_dp *intel_dp)
>  {
>  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
>  	int source_max = intel_dig_port->max_lanes;
>  	int sink_max = drm_dp_max_lane_count(intel_dp->dpcd);
> -	int fia_max = intel_dp_get_fia_supported_lane_count(intel_dp);
> +	int fia_max = intel_tc_port_fia_max_lane_count(intel_dig_port);
>  
>  	return min3(source_max, sink_max, fia_max);
>  }
> @@ -5231,195 +5199,6 @@ static bool icl_combo_port_connected(struct drm_i915_private *dev_priv,
>  	return I915_READ(SDEISR) & SDE_DDI_HOTPLUG_ICP(port);
>  }
>  
> -static const char *tc_type_name(enum tc_port_type type)
> -{
> -	static const char * const names[] = {
> -		[TC_PORT_UNKNOWN] = "unknown",
> -		[TC_PORT_LEGACY] = "legacy",
> -		[TC_PORT_TYPEC] = "typec",
> -		[TC_PORT_TBT] = "tbt",
> -	};
> -
> -	if (WARN_ON(type >= ARRAY_SIZE(names)))
> -		type = TC_PORT_UNKNOWN;
> -
> -	return names[type];
> -}
> -
> -static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
> -				    struct intel_digital_port *intel_dig_port,
> -				    bool is_legacy, bool is_typec, bool is_tbt)
> -{
> -	enum port port = intel_dig_port->base.port;
> -	enum tc_port_type old_type = intel_dig_port->tc_type;
> -
> -	WARN_ON(is_legacy + is_typec + is_tbt != 1);
> -
> -	if (is_legacy)
> -		intel_dig_port->tc_type = TC_PORT_LEGACY;
> -	else if (is_typec)
> -		intel_dig_port->tc_type = TC_PORT_TYPEC;
> -	else if (is_tbt)
> -		intel_dig_port->tc_type = TC_PORT_TBT;
> -	else
> -		return;
> -
> -	/* Types are not supposed to be changed at runtime. */
> -	WARN_ON(old_type != TC_PORT_UNKNOWN &&
> -		old_type != intel_dig_port->tc_type);
> -
> -	if (old_type != intel_dig_port->tc_type)
> -		DRM_DEBUG_KMS("Port %c has TC type %s\n", port_name(port),
> -			      tc_type_name(intel_dig_port->tc_type));
> -}
> -
> -/*
> - * This function implements the first part of the Connect Flow described by our
> - * specification, Gen11 TypeC Programming chapter. The rest of the flow (reading
> - * lanes, EDID, etc) is done as needed in the typical places.
> - *
> - * Unlike the other ports, type-C ports are not available to use as soon as we
> - * get a hotplug. The type-C PHYs can be shared between multiple controllers:
> - * display, USB, etc. As a result, handshaking through FIA is required around
> - * connect and disconnect to cleanly transfer ownership with the controller and
> - * set the type-C power state.
> - *
> - * We could opt to only do the connect flow when we actually try to use the AUX
> - * channels or do a modeset, then immediately run the disconnect flow after
> - * usage, but there are some implications on this for a dynamic environment:
> - * things may go away or change behind our backs. So for now our driver is
> - * always trying to acquire ownership of the controller as soon as it gets an
> - * interrupt (or polls state and sees a port is connected) and only gives it
> - * back when it sees a disconnect. Implementation of a more fine-grained model
> - * will require a lot of coordination with user space and thorough testing for
> - * the extra possible cases.
> - */
> -static bool icl_tc_phy_connect(struct drm_i915_private *dev_priv,
> -			       struct intel_digital_port *dig_port)
> -{
> -	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> -	u32 val;
> -
> -	if (dig_port->tc_type != TC_PORT_LEGACY &&
> -	    dig_port->tc_type != TC_PORT_TYPEC)
> -		return true;
> -
> -	val = I915_READ(PORT_TX_DFLEXDPPMS);
> -	if (!(val & DP_PHY_MODE_STATUS_COMPLETED(tc_port))) {
> -		DRM_DEBUG_KMS("DP PHY for TC port %d not ready\n", tc_port);
> -		WARN_ON(dig_port->tc_legacy_port);
> -		return false;
> -	}
> -
> -	/*
> -	 * This function may be called many times in a row without an HPD event
> -	 * in between, so try to avoid the write when we can.
> -	 */
> -	val = I915_READ(PORT_TX_DFLEXDPCSSS);
> -	if (!(val & DP_PHY_MODE_STATUS_NOT_SAFE(tc_port))) {
> -		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> -		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> -	}
> -
> -	/*
> -	 * Now we have to re-check the live state, in case the port recently
> -	 * became disconnected. Not necessary for legacy mode.
> -	 */
> -	if (dig_port->tc_type == TC_PORT_TYPEC &&
> -	    !(I915_READ(PORT_TX_DFLEXDPSP) & TC_LIVE_STATE_TC(tc_port))) {
> -		DRM_DEBUG_KMS("TC PHY %d sudden disconnect.\n", tc_port);
> -		icl_tc_phy_disconnect(dev_priv, dig_port);
> -		return false;
> -	}
> -
> -	return true;
> -}
> -
> -/*
> - * See the comment at the connect function. This implements the Disconnect
> - * Flow.
> - */
> -void icl_tc_phy_disconnect(struct drm_i915_private *dev_priv,
> -			   struct intel_digital_port *dig_port)
> -{
> -	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> -
> -	if (dig_port->tc_type == TC_PORT_UNKNOWN)
> -		return;
> -
> -	/*
> -	 * TBT disconnection flow is read the live status, what was done in
> -	 * caller.
> -	 */
> -	if (dig_port->tc_type == TC_PORT_TYPEC ||
> -	    dig_port->tc_type == TC_PORT_LEGACY) {
> -		u32 val;
> -
> -		val = I915_READ(PORT_TX_DFLEXDPCSSS);
> -		val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> -		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> -	}
> -
> -	DRM_DEBUG_KMS("Port %c TC type %s disconnected\n",
> -		      port_name(dig_port->base.port),
> -		      tc_type_name(dig_port->tc_type));
> -
> -	dig_port->tc_type = TC_PORT_UNKNOWN;
> -}
> -
> -/*
> - * The type-C ports are different because even when they are connected, they may
> - * not be available/usable by the graphics driver: see the comment on
> - * icl_tc_phy_connect(). So in our driver instead of adding the additional
> - * concept of "usable" and make everything check for "connected and usable" we
> - * define a port as "connected" when it is not only connected, but also when it
> - * is usable by the rest of the driver. That maintains the old assumption that
> - * connected ports are usable, and avoids exposing to the users objects they
> - * can't really use.
> - */
> -static bool icl_tc_port_connected(struct drm_i915_private *dev_priv,
> -				  struct intel_digital_port *intel_dig_port)
> -{
> -	enum port port = intel_dig_port->base.port;
> -	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
> -	bool is_legacy, is_typec, is_tbt;
> -	u32 dpsp;
> -
> -	/*
> -	 * Complain if we got a legacy port HPD, but VBT didn't mark the port as
> -	 * legacy. Treat the port as legacy from now on.
> -	 */
> -	if (!intel_dig_port->tc_legacy_port &&
> -	    I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port)) {
> -		DRM_ERROR("VBT incorrectly claims port %c is not TypeC legacy\n",
> -			  port_name(port));
> -		intel_dig_port->tc_legacy_port = true;
> -	}
> -	is_legacy = intel_dig_port->tc_legacy_port;
> -
> -	/*
> -	 * The spec says we shouldn't be using the ISR bits for detecting
> -	 * between TC and TBT. We should use DFLEXDPSP.
> -	 */
> -	dpsp = I915_READ(PORT_TX_DFLEXDPSP);
> -	is_typec = dpsp & TC_LIVE_STATE_TC(tc_port);
> -	is_tbt = dpsp & TC_LIVE_STATE_TBT(tc_port);
> -
> -	if (!is_legacy && !is_typec && !is_tbt) {
> -		icl_tc_phy_disconnect(dev_priv, intel_dig_port);
> -
> -		return false;
> -	}
> -
> -	icl_update_tc_port_type(dev_priv, intel_dig_port, is_legacy, is_typec,
> -				is_tbt);
> -
> -	if (!icl_tc_phy_connect(dev_priv, intel_dig_port))
> -		return false;
> -
> -	return true;
> -}
> -
>  static bool icl_digital_port_connected(struct intel_encoder *encoder)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> @@ -5428,7 +5207,7 @@ static bool icl_digital_port_connected(struct intel_encoder *encoder)
>  	if (intel_port_is_combophy(dev_priv, encoder->port))
>  		return icl_combo_port_connected(dev_priv, dig_port);
>  	else if (intel_port_is_tc(dev_priv, encoder->port))
> -		return icl_tc_port_connected(dev_priv, dig_port);
> +		return intel_tc_port_connected(dig_port);
>  	else
>  		MISSING_CASE(encoder->hpd_pin);
>  
> diff --git a/drivers/gpu/drm/i915/intel_dp.h b/drivers/gpu/drm/i915/intel_dp.h
> index da70b1a41c83..657bbb1f5ed0 100644
> --- a/drivers/gpu/drm/i915/intel_dp.h
> +++ b/drivers/gpu/drm/i915/intel_dp.h
> @@ -112,8 +112,6 @@ bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp);
>  int intel_dp_link_required(int pixel_clock, int bpp);
>  int intel_dp_max_data_rate(int max_link_clock, int max_lanes);
>  bool intel_digital_port_connected(struct intel_encoder *encoder);
> -void icl_tc_phy_disconnect(struct drm_i915_private *dev_priv,
> -			   struct intel_digital_port *dig_port);
>  
>  static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
>  {
> diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
> new file mode 100644
> index 000000000000..7a1b5870945f
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/intel_tc.c
> @@ -0,0 +1,230 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2019 Intel Corporation
> + */

From the Nitpicks Department, please add a blank line here.

> +#include "intel_display.h"
> +#include "i915_drv.h"
> +#include "intel_tc.h"

And sort the includes.

> +
> +static const char *tc_type_name(enum tc_port_type type)
> +{
> +	static const char * const names[] = {
> +		[TC_PORT_UNKNOWN] = "unknown",
> +		[TC_PORT_LEGACY] = "legacy",
> +		[TC_PORT_TYPEC] = "typec",
> +		[TC_PORT_TBT] = "tbt",
> +	};
> +
> +	if (WARN_ON(type >= ARRAY_SIZE(names)))
> +		type = TC_PORT_UNKNOWN;
> +
> +	return names[type];
> +}
> +
> +int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> +	intel_wakeref_t wakeref;
> +	u32 lane_info;
> +
> +	if (tc_port == PORT_TC_NONE || dig_port->tc_type != TC_PORT_TYPEC)
> +		return 4;
> +
> +	lane_info = 0;
> +	with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref)
> +		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
> +			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
> +				DP_LANE_ASSIGNMENT_SHIFT(tc_port);
> +
> +	switch (lane_info) {
> +	default:
> +		MISSING_CASE(lane_info);
> +	case 1:
> +	case 2:
> +	case 4:
> +	case 8:
> +		return 1;
> +	case 3:
> +	case 12:
> +		return 2;
> +	case 15:
> +		return 4;
> +	}
> +}
> +
> +/*
> + * This function implements the first part of the Connect Flow described by our
> + * specification, Gen11 TypeC Programming chapter. The rest of the flow (reading
> + * lanes, EDID, etc) is done as needed in the typical places.
> + *
> + * Unlike the other ports, type-C ports are not available to use as soon as we
> + * get a hotplug. The type-C PHYs can be shared between multiple controllers:
> + * display, USB, etc. As a result, handshaking through FIA is required around
> + * connect and disconnect to cleanly transfer ownership with the controller and
> + * set the type-C power state.
> + *
> + * We could opt to only do the connect flow when we actually try to use the AUX
> + * channels or do a modeset, then immediately run the disconnect flow after
> + * usage, but there are some implications on this for a dynamic environment:
> + * things may go away or change behind our backs. So for now our driver is
> + * always trying to acquire ownership of the controller as soon as it gets an
> + * interrupt (or polls state and sees a port is connected) and only gives it
> + * back when it sees a disconnect. Implementation of a more fine-grained model
> + * will require a lot of coordination with user space and thorough testing for
> + * the extra possible cases.
> + */
> +static bool icl_tc_phy_connect(struct intel_digital_port *dig_port)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> +	u32 val;
> +
> +	if (dig_port->tc_type != TC_PORT_LEGACY &&
> +	    dig_port->tc_type != TC_PORT_TYPEC)
> +		return true;
> +
> +	val = I915_READ(PORT_TX_DFLEXDPPMS);
> +	if (!(val & DP_PHY_MODE_STATUS_COMPLETED(tc_port))) {
> +		DRM_DEBUG_KMS("DP PHY for TC port %d not ready\n", tc_port);
> +		WARN_ON(dig_port->tc_legacy_port);
> +		return false;
> +	}
> +
> +	/*
> +	 * This function may be called many times in a row without an HPD event
> +	 * in between, so try to avoid the write when we can.
> +	 */
> +	val = I915_READ(PORT_TX_DFLEXDPCSSS);
> +	if (!(val & DP_PHY_MODE_STATUS_NOT_SAFE(tc_port))) {
> +		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> +		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> +	}
> +
> +	/*
> +	 * Now we have to re-check the live state, in case the port recently
> +	 * became disconnected. Not necessary for legacy mode.
> +	 */
> +	if (dig_port->tc_type == TC_PORT_TYPEC &&
> +	    !(I915_READ(PORT_TX_DFLEXDPSP) & TC_LIVE_STATE_TC(tc_port))) {
> +		DRM_DEBUG_KMS("TC PHY %d sudden disconnect.\n", tc_port);
> +		icl_tc_phy_disconnect(dig_port);
> +		return false;
> +	}
> +
> +	return true;
> +}
> +
> +/*
> + * See the comment at the connect function. This implements the Disconnect
> + * Flow.
> + */
> +void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> +
> +	if (dig_port->tc_type == TC_PORT_UNKNOWN)
> +		return;
> +
> +	/*
> +	 * TBT disconnection flow is read the live status, what was done in
> +	 * caller.
> +	 */
> +	if (dig_port->tc_type == TC_PORT_TYPEC ||
> +	    dig_port->tc_type == TC_PORT_LEGACY) {
> +		u32 val;
> +
> +		val = I915_READ(PORT_TX_DFLEXDPCSSS);
> +		val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> +		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> +	}
> +
> +	DRM_DEBUG_KMS("Port %c TC type %s disconnected\n",
> +		      port_name(dig_port->base.port),
> +		      tc_type_name(dig_port->tc_type));
> +
> +	dig_port->tc_type = TC_PORT_UNKNOWN;
> +}
> +
> +static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
> +				    struct intel_digital_port *intel_dig_port,
> +				    bool is_legacy, bool is_typec, bool is_tbt)
> +{
> +	enum port port = intel_dig_port->base.port;
> +	enum tc_port_type old_type = intel_dig_port->tc_type;
> +
> +	WARN_ON(is_legacy + is_typec + is_tbt != 1);
> +
> +	if (is_legacy)
> +		intel_dig_port->tc_type = TC_PORT_LEGACY;
> +	else if (is_typec)
> +		intel_dig_port->tc_type = TC_PORT_TYPEC;
> +	else if (is_tbt)
> +		intel_dig_port->tc_type = TC_PORT_TBT;
> +	else
> +		return;
> +
> +	/* Types are not supposed to be changed at runtime. */
> +	WARN_ON(old_type != TC_PORT_UNKNOWN &&
> +		old_type != intel_dig_port->tc_type);
> +
> +	if (old_type != intel_dig_port->tc_type)
> +		DRM_DEBUG_KMS("Port %c has TC type %s\n", port_name(port),
> +			      tc_type_name(intel_dig_port->tc_type));
> +}
> +
> +
> +/*
> + * The type-C ports are different because even when they are connected, they may
> + * not be available/usable by the graphics driver: see the comment on
> + * icl_tc_phy_connect(). So in our driver instead of adding the additional
> + * concept of "usable" and make everything check for "connected and usable" we
> + * define a port as "connected" when it is not only connected, but also when it
> + * is usable by the rest of the driver. That maintains the old assumption that
> + * connected ports are usable, and avoids exposing to the users objects they
> + * can't really use.
> + */
> +bool intel_tc_port_connected(struct intel_digital_port *dig_port)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> +	enum port port = dig_port->base.port;
> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
> +	bool is_legacy, is_typec, is_tbt;
> +	u32 dpsp;
> +
> +	/*
> +	 * Complain if we got a legacy port HPD, but VBT didn't mark the port as
> +	 * legacy. Treat the port as legacy from now on.
> +	 */
> +	if (!dig_port->tc_legacy_port &&
> +	    I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port)) {
> +		DRM_ERROR("VBT incorrectly claims port %c is not TypeC legacy\n",
> +			  port_name(port));
> +		dig_port->tc_legacy_port = true;
> +	}
> +	is_legacy = dig_port->tc_legacy_port;
> +
> +	/*
> +	 * The spec says we shouldn't be using the ISR bits for detecting
> +	 * between TC and TBT. We should use DFLEXDPSP.
> +	 */
> +	dpsp = I915_READ(PORT_TX_DFLEXDPSP);
> +	is_typec = dpsp & TC_LIVE_STATE_TC(tc_port);
> +	is_tbt = dpsp & TC_LIVE_STATE_TBT(tc_port);
> +
> +	if (!is_legacy && !is_typec && !is_tbt) {
> +		icl_tc_phy_disconnect(dig_port);
> +
> +		return false;
> +	}
> +
> +	icl_update_tc_port_type(dev_priv, dig_port, is_legacy, is_typec,
> +				is_tbt);
> +
> +	if (!icl_tc_phy_connect(dig_port))
> +		return false;
> +
> +	return true;
> +}
> +
> diff --git a/drivers/gpu/drm/i915/intel_tc.h b/drivers/gpu/drm/i915/intel_tc.h
> new file mode 100644
> index 000000000000..94c62ac4a162
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/intel_tc.h
> @@ -0,0 +1,13 @@

SPDX header here please.

> +#ifndef __INTEL_TC_H__
> +#define __INTEL_TC_H__
> +
> +#include <linux/types.h>
> +
> +struct intel_digital_port;
> +
> +void icl_tc_phy_disconnect(struct intel_digital_port *dig_port);

I'd like to see this named intel_tc_* in the future.

BR,
Jani.


> +
> +bool intel_tc_port_connected(struct intel_digital_port *dig_port);
> +int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port);
> +
> +#endif /* __INTEL_TC_H__ */

-- 
Jani Nikula, Intel Open Source Graphics Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 03/23] drm/i915: Move the TypeC port handling code to a separate file
  2019-06-06  8:42   ` Jani Nikula
@ 2019-06-06  8:43     ` Jani Nikula
  2019-06-06  9:09     ` Imre Deak
  2019-06-10 22:57     ` Lucas De Marchi
  2 siblings, 0 replies; 79+ messages in thread
From: Jani Nikula @ 2019-06-06  8:43 UTC (permalink / raw)
  To: Imre Deak, intel-gfx; +Cc: Paulo Zanoni

On Thu, 06 Jun 2019, Jani Nikula <jani.nikula@linux.intel.com> wrote:
> On Tue, 04 Jun 2019, Imre Deak <imre.deak@intel.com> wrote:
>> Move the TypeC port handling functions to a new file for clarity.
>>
>> While at it:
>> - s/icl_tc_port_connected()/intel_tc_port_connected()/
>>   icl_tc_phy_disconnect(), will be unexported later.
>>
>> - s/intel_dp_get_fia_supported_lane_count()/intel_tc_port_fia_max_lane_count()/
>>   It's used for HDMI legacy mode too.
>>
>> - Simplify function interfaces by passing only dig_port to them.
>>
>> No functional changes.
>
> Some nitpicks below.

Forgot,

Acked-by: Jani Nikula <jani.nikula@intel.com>

on the idea.

>
> BR,
> Jani.
>
>
>>
>> Cc: Animesh Manna <animesh.manna@intel.com>
>> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
>> Cc: José Roberto de Souza <jose.souza@intel.com>
>> Signed-off-by: Imre Deak <imre.deak@intel.com>
>> ---
>>  drivers/gpu/drm/i915/Makefile             |   3 +-
>>  drivers/gpu/drm/i915/Makefile.header-test |   1 +
>>  drivers/gpu/drm/i915/intel_ddi.c          |   6 +-
>>  drivers/gpu/drm/i915/intel_dp.c           | 227 +--------------------
>>  drivers/gpu/drm/i915/intel_dp.h           |   2 -
>>  drivers/gpu/drm/i915/intel_tc.c           | 230 ++++++++++++++++++++++
>>  drivers/gpu/drm/i915/intel_tc.h           |  13 ++
>>  7 files changed, 252 insertions(+), 230 deletions(-)
>>  create mode 100644 drivers/gpu/drm/i915/intel_tc.c
>>  create mode 100644 drivers/gpu/drm/i915/intel_tc.h
>>
>> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
>> index c0a7b2994077..74c4d11d83eb 100644
>> --- a/drivers/gpu/drm/i915/Makefile
>> +++ b/drivers/gpu/drm/i915/Makefile
>> @@ -171,7 +171,8 @@ i915-y += intel_audio.o \
>>  	  intel_psr.o \
>>  	  intel_quirks.o \
>>  	  intel_sideband.o \
>> -	  intel_sprite.o
>> +	  intel_sprite.o \
>> +	  intel_tc.o
>>  i915-$(CONFIG_ACPI)		+= intel_acpi.o intel_opregion.o
>>  i915-$(CONFIG_DRM_FBDEV_EMULATION)	+= intel_fbdev.o
>>  
>> diff --git a/drivers/gpu/drm/i915/Makefile.header-test b/drivers/gpu/drm/i915/Makefile.header-test
>> index 6ef3b647ac65..e80e8e45b09c 100644
>> --- a/drivers/gpu/drm/i915/Makefile.header-test
>> +++ b/drivers/gpu/drm/i915/Makefile.header-test
>> @@ -58,6 +58,7 @@ header_test := \
>>  	intel_sdvo.h \
>>  	intel_sideband.h \
>>  	intel_sprite.h \
>> +	intel_tc.h \
>>  	intel_tv.h \
>>  	intel_uncore.h \
>>  	intel_vdsc.h \
>> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
>> index 350eaf54f01f..5a1c98438375 100644
>> --- a/drivers/gpu/drm/i915/intel_ddi.c
>> +++ b/drivers/gpu/drm/i915/intel_ddi.c
>> @@ -45,6 +45,7 @@
>>  #include "intel_lspcon.h"
>>  #include "intel_panel.h"
>>  #include "intel_psr.h"
>> +#include "intel_tc.h"
>>  #include "intel_vdsc.h"
>>  
>>  struct ddi_buf_trans {
>> @@ -3904,7 +3905,6 @@ static int intel_ddi_compute_config(struct intel_encoder *encoder,
>>  static void intel_ddi_encoder_suspend(struct intel_encoder *encoder)
>>  {
>>  	struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
>> -	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
>>  
>>  	intel_dp_encoder_suspend(encoder);
>>  
>> @@ -3914,7 +3914,7 @@ static void intel_ddi_encoder_suspend(struct intel_encoder *encoder)
>>  	 * even if the sink has disappeared while being suspended.
>>  	 */
>>  	if (dig_port->tc_legacy_port)
>> -		icl_tc_phy_disconnect(i915, dig_port);
>> +		icl_tc_phy_disconnect(dig_port);
>>  }
>>  
>>  static void intel_ddi_encoder_reset(struct drm_encoder *drm_encoder)
>> @@ -3936,7 +3936,7 @@ static void intel_ddi_encoder_destroy(struct drm_encoder *encoder)
>>  	intel_dp_encoder_flush_work(encoder);
>>  
>>  	if (intel_port_is_tc(i915, dig_port->base.port))
>> -		icl_tc_phy_disconnect(i915, dig_port);
>> +		icl_tc_phy_disconnect(dig_port);
>>  
>>  	drm_encoder_cleanup(encoder);
>>  	kfree(dig_port);
>> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>> index 24b56b2a76c8..b69310bd9914 100644
>> --- a/drivers/gpu/drm/i915/intel_dp.c
>> +++ b/drivers/gpu/drm/i915/intel_dp.c
>> @@ -62,6 +62,7 @@
>>  #include "intel_panel.h"
>>  #include "intel_psr.h"
>>  #include "intel_sideband.h"
>> +#include "intel_tc.h"
>>  #include "intel_vdsc.h"
>>  
>>  #define DP_DPRX_ESI_LEN 14
>> @@ -211,46 +212,13 @@ static int intel_dp_max_common_rate(struct intel_dp *intel_dp)
>>  	return intel_dp->common_rates[intel_dp->num_common_rates - 1];
>>  }
>>  
>> -static int intel_dp_get_fia_supported_lane_count(struct intel_dp *intel_dp)
>> -{
>> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
>> -	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
>> -	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
>> -	intel_wakeref_t wakeref;
>> -	u32 lane_info;
>> -
>> -	if (tc_port == PORT_TC_NONE || dig_port->tc_type != TC_PORT_TYPEC)
>> -		return 4;
>> -
>> -	lane_info = 0;
>> -	with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref)
>> -		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
>> -			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
>> -				DP_LANE_ASSIGNMENT_SHIFT(tc_port);
>> -
>> -	switch (lane_info) {
>> -	default:
>> -		MISSING_CASE(lane_info);
>> -	case 1:
>> -	case 2:
>> -	case 4:
>> -	case 8:
>> -		return 1;
>> -	case 3:
>> -	case 12:
>> -		return 2;
>> -	case 15:
>> -		return 4;
>> -	}
>> -}
>> -
>>  /* Theoretical max between source and sink */
>>  static int intel_dp_max_common_lane_count(struct intel_dp *intel_dp)
>>  {
>>  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
>>  	int source_max = intel_dig_port->max_lanes;
>>  	int sink_max = drm_dp_max_lane_count(intel_dp->dpcd);
>> -	int fia_max = intel_dp_get_fia_supported_lane_count(intel_dp);
>> +	int fia_max = intel_tc_port_fia_max_lane_count(intel_dig_port);
>>  
>>  	return min3(source_max, sink_max, fia_max);
>>  }
>> @@ -5231,195 +5199,6 @@ static bool icl_combo_port_connected(struct drm_i915_private *dev_priv,
>>  	return I915_READ(SDEISR) & SDE_DDI_HOTPLUG_ICP(port);
>>  }
>>  
>> -static const char *tc_type_name(enum tc_port_type type)
>> -{
>> -	static const char * const names[] = {
>> -		[TC_PORT_UNKNOWN] = "unknown",
>> -		[TC_PORT_LEGACY] = "legacy",
>> -		[TC_PORT_TYPEC] = "typec",
>> -		[TC_PORT_TBT] = "tbt",
>> -	};
>> -
>> -	if (WARN_ON(type >= ARRAY_SIZE(names)))
>> -		type = TC_PORT_UNKNOWN;
>> -
>> -	return names[type];
>> -}
>> -
>> -static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
>> -				    struct intel_digital_port *intel_dig_port,
>> -				    bool is_legacy, bool is_typec, bool is_tbt)
>> -{
>> -	enum port port = intel_dig_port->base.port;
>> -	enum tc_port_type old_type = intel_dig_port->tc_type;
>> -
>> -	WARN_ON(is_legacy + is_typec + is_tbt != 1);
>> -
>> -	if (is_legacy)
>> -		intel_dig_port->tc_type = TC_PORT_LEGACY;
>> -	else if (is_typec)
>> -		intel_dig_port->tc_type = TC_PORT_TYPEC;
>> -	else if (is_tbt)
>> -		intel_dig_port->tc_type = TC_PORT_TBT;
>> -	else
>> -		return;
>> -
>> -	/* Types are not supposed to be changed at runtime. */
>> -	WARN_ON(old_type != TC_PORT_UNKNOWN &&
>> -		old_type != intel_dig_port->tc_type);
>> -
>> -	if (old_type != intel_dig_port->tc_type)
>> -		DRM_DEBUG_KMS("Port %c has TC type %s\n", port_name(port),
>> -			      tc_type_name(intel_dig_port->tc_type));
>> -}
>> -
>> -/*
>> - * This function implements the first part of the Connect Flow described by our
>> - * specification, Gen11 TypeC Programming chapter. The rest of the flow (reading
>> - * lanes, EDID, etc) is done as needed in the typical places.
>> - *
>> - * Unlike the other ports, type-C ports are not available to use as soon as we
>> - * get a hotplug. The type-C PHYs can be shared between multiple controllers:
>> - * display, USB, etc. As a result, handshaking through FIA is required around
>> - * connect and disconnect to cleanly transfer ownership with the controller and
>> - * set the type-C power state.
>> - *
>> - * We could opt to only do the connect flow when we actually try to use the AUX
>> - * channels or do a modeset, then immediately run the disconnect flow after
>> - * usage, but there are some implications on this for a dynamic environment:
>> - * things may go away or change behind our backs. So for now our driver is
>> - * always trying to acquire ownership of the controller as soon as it gets an
>> - * interrupt (or polls state and sees a port is connected) and only gives it
>> - * back when it sees a disconnect. Implementation of a more fine-grained model
>> - * will require a lot of coordination with user space and thorough testing for
>> - * the extra possible cases.
>> - */
>> -static bool icl_tc_phy_connect(struct drm_i915_private *dev_priv,
>> -			       struct intel_digital_port *dig_port)
>> -{
>> -	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
>> -	u32 val;
>> -
>> -	if (dig_port->tc_type != TC_PORT_LEGACY &&
>> -	    dig_port->tc_type != TC_PORT_TYPEC)
>> -		return true;
>> -
>> -	val = I915_READ(PORT_TX_DFLEXDPPMS);
>> -	if (!(val & DP_PHY_MODE_STATUS_COMPLETED(tc_port))) {
>> -		DRM_DEBUG_KMS("DP PHY for TC port %d not ready\n", tc_port);
>> -		WARN_ON(dig_port->tc_legacy_port);
>> -		return false;
>> -	}
>> -
>> -	/*
>> -	 * This function may be called many times in a row without an HPD event
>> -	 * in between, so try to avoid the write when we can.
>> -	 */
>> -	val = I915_READ(PORT_TX_DFLEXDPCSSS);
>> -	if (!(val & DP_PHY_MODE_STATUS_NOT_SAFE(tc_port))) {
>> -		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
>> -		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
>> -	}
>> -
>> -	/*
>> -	 * Now we have to re-check the live state, in case the port recently
>> -	 * became disconnected. Not necessary for legacy mode.
>> -	 */
>> -	if (dig_port->tc_type == TC_PORT_TYPEC &&
>> -	    !(I915_READ(PORT_TX_DFLEXDPSP) & TC_LIVE_STATE_TC(tc_port))) {
>> -		DRM_DEBUG_KMS("TC PHY %d sudden disconnect.\n", tc_port);
>> -		icl_tc_phy_disconnect(dev_priv, dig_port);
>> -		return false;
>> -	}
>> -
>> -	return true;
>> -}
>> -
>> -/*
>> - * See the comment at the connect function. This implements the Disconnect
>> - * Flow.
>> - */
>> -void icl_tc_phy_disconnect(struct drm_i915_private *dev_priv,
>> -			   struct intel_digital_port *dig_port)
>> -{
>> -	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
>> -
>> -	if (dig_port->tc_type == TC_PORT_UNKNOWN)
>> -		return;
>> -
>> -	/*
>> -	 * TBT disconnection flow is read the live status, what was done in
>> -	 * caller.
>> -	 */
>> -	if (dig_port->tc_type == TC_PORT_TYPEC ||
>> -	    dig_port->tc_type == TC_PORT_LEGACY) {
>> -		u32 val;
>> -
>> -		val = I915_READ(PORT_TX_DFLEXDPCSSS);
>> -		val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
>> -		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
>> -	}
>> -
>> -	DRM_DEBUG_KMS("Port %c TC type %s disconnected\n",
>> -		      port_name(dig_port->base.port),
>> -		      tc_type_name(dig_port->tc_type));
>> -
>> -	dig_port->tc_type = TC_PORT_UNKNOWN;
>> -}
>> -
>> -/*
>> - * The type-C ports are different because even when they are connected, they may
>> - * not be available/usable by the graphics driver: see the comment on
>> - * icl_tc_phy_connect(). So in our driver instead of adding the additional
>> - * concept of "usable" and make everything check for "connected and usable" we
>> - * define a port as "connected" when it is not only connected, but also when it
>> - * is usable by the rest of the driver. That maintains the old assumption that
>> - * connected ports are usable, and avoids exposing to the users objects they
>> - * can't really use.
>> - */
>> -static bool icl_tc_port_connected(struct drm_i915_private *dev_priv,
>> -				  struct intel_digital_port *intel_dig_port)
>> -{
>> -	enum port port = intel_dig_port->base.port;
>> -	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
>> -	bool is_legacy, is_typec, is_tbt;
>> -	u32 dpsp;
>> -
>> -	/*
>> -	 * Complain if we got a legacy port HPD, but VBT didn't mark the port as
>> -	 * legacy. Treat the port as legacy from now on.
>> -	 */
>> -	if (!intel_dig_port->tc_legacy_port &&
>> -	    I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port)) {
>> -		DRM_ERROR("VBT incorrectly claims port %c is not TypeC legacy\n",
>> -			  port_name(port));
>> -		intel_dig_port->tc_legacy_port = true;
>> -	}
>> -	is_legacy = intel_dig_port->tc_legacy_port;
>> -
>> -	/*
>> -	 * The spec says we shouldn't be using the ISR bits for detecting
>> -	 * between TC and TBT. We should use DFLEXDPSP.
>> -	 */
>> -	dpsp = I915_READ(PORT_TX_DFLEXDPSP);
>> -	is_typec = dpsp & TC_LIVE_STATE_TC(tc_port);
>> -	is_tbt = dpsp & TC_LIVE_STATE_TBT(tc_port);
>> -
>> -	if (!is_legacy && !is_typec && !is_tbt) {
>> -		icl_tc_phy_disconnect(dev_priv, intel_dig_port);
>> -
>> -		return false;
>> -	}
>> -
>> -	icl_update_tc_port_type(dev_priv, intel_dig_port, is_legacy, is_typec,
>> -				is_tbt);
>> -
>> -	if (!icl_tc_phy_connect(dev_priv, intel_dig_port))
>> -		return false;
>> -
>> -	return true;
>> -}
>> -
>>  static bool icl_digital_port_connected(struct intel_encoder *encoder)
>>  {
>>  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>> @@ -5428,7 +5207,7 @@ static bool icl_digital_port_connected(struct intel_encoder *encoder)
>>  	if (intel_port_is_combophy(dev_priv, encoder->port))
>>  		return icl_combo_port_connected(dev_priv, dig_port);
>>  	else if (intel_port_is_tc(dev_priv, encoder->port))
>> -		return icl_tc_port_connected(dev_priv, dig_port);
>> +		return intel_tc_port_connected(dig_port);
>>  	else
>>  		MISSING_CASE(encoder->hpd_pin);
>>  
>> diff --git a/drivers/gpu/drm/i915/intel_dp.h b/drivers/gpu/drm/i915/intel_dp.h
>> index da70b1a41c83..657bbb1f5ed0 100644
>> --- a/drivers/gpu/drm/i915/intel_dp.h
>> +++ b/drivers/gpu/drm/i915/intel_dp.h
>> @@ -112,8 +112,6 @@ bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp);
>>  int intel_dp_link_required(int pixel_clock, int bpp);
>>  int intel_dp_max_data_rate(int max_link_clock, int max_lanes);
>>  bool intel_digital_port_connected(struct intel_encoder *encoder);
>> -void icl_tc_phy_disconnect(struct drm_i915_private *dev_priv,
>> -			   struct intel_digital_port *dig_port);
>>  
>>  static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
>>  {
>> diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
>> new file mode 100644
>> index 000000000000..7a1b5870945f
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/intel_tc.c
>> @@ -0,0 +1,230 @@
>> +// SPDX-License-Identifier: MIT
>> +/*
>> + * Copyright © 2019 Intel Corporation
>> + */
>
> From the Nitpicks Department, please add a blank line here.
>
>> +#include "intel_display.h"
>> +#include "i915_drv.h"
>> +#include "intel_tc.h"
>
> And sort the includes.
>
>> +
>> +static const char *tc_type_name(enum tc_port_type type)
>> +{
>> +	static const char * const names[] = {
>> +		[TC_PORT_UNKNOWN] = "unknown",
>> +		[TC_PORT_LEGACY] = "legacy",
>> +		[TC_PORT_TYPEC] = "typec",
>> +		[TC_PORT_TBT] = "tbt",
>> +	};
>> +
>> +	if (WARN_ON(type >= ARRAY_SIZE(names)))
>> +		type = TC_PORT_UNKNOWN;
>> +
>> +	return names[type];
>> +}
>> +
>> +int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
>> +{
>> +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
>> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
>> +	intel_wakeref_t wakeref;
>> +	u32 lane_info;
>> +
>> +	if (tc_port == PORT_TC_NONE || dig_port->tc_type != TC_PORT_TYPEC)
>> +		return 4;
>> +
>> +	lane_info = 0;
>> +	with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref)
>> +		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
>> +			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
>> +				DP_LANE_ASSIGNMENT_SHIFT(tc_port);
>> +
>> +	switch (lane_info) {
>> +	default:
>> +		MISSING_CASE(lane_info);
>> +	case 1:
>> +	case 2:
>> +	case 4:
>> +	case 8:
>> +		return 1;
>> +	case 3:
>> +	case 12:
>> +		return 2;
>> +	case 15:
>> +		return 4;
>> +	}
>> +}
>> +
>> +/*
>> + * This function implements the first part of the Connect Flow described by our
>> + * specification, Gen11 TypeC Programming chapter. The rest of the flow (reading
>> + * lanes, EDID, etc) is done as needed in the typical places.
>> + *
>> + * Unlike the other ports, type-C ports are not available to use as soon as we
>> + * get a hotplug. The type-C PHYs can be shared between multiple controllers:
>> + * display, USB, etc. As a result, handshaking through FIA is required around
>> + * connect and disconnect to cleanly transfer ownership with the controller and
>> + * set the type-C power state.
>> + *
>> + * We could opt to only do the connect flow when we actually try to use the AUX
>> + * channels or do a modeset, then immediately run the disconnect flow after
>> + * usage, but there are some implications on this for a dynamic environment:
>> + * things may go away or change behind our backs. So for now our driver is
>> + * always trying to acquire ownership of the controller as soon as it gets an
>> + * interrupt (or polls state and sees a port is connected) and only gives it
>> + * back when it sees a disconnect. Implementation of a more fine-grained model
>> + * will require a lot of coordination with user space and thorough testing for
>> + * the extra possible cases.
>> + */
>> +static bool icl_tc_phy_connect(struct intel_digital_port *dig_port)
>> +{
>> +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
>> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
>> +	u32 val;
>> +
>> +	if (dig_port->tc_type != TC_PORT_LEGACY &&
>> +	    dig_port->tc_type != TC_PORT_TYPEC)
>> +		return true;
>> +
>> +	val = I915_READ(PORT_TX_DFLEXDPPMS);
>> +	if (!(val & DP_PHY_MODE_STATUS_COMPLETED(tc_port))) {
>> +		DRM_DEBUG_KMS("DP PHY for TC port %d not ready\n", tc_port);
>> +		WARN_ON(dig_port->tc_legacy_port);
>> +		return false;
>> +	}
>> +
>> +	/*
>> +	 * This function may be called many times in a row without an HPD event
>> +	 * in between, so try to avoid the write when we can.
>> +	 */
>> +	val = I915_READ(PORT_TX_DFLEXDPCSSS);
>> +	if (!(val & DP_PHY_MODE_STATUS_NOT_SAFE(tc_port))) {
>> +		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
>> +		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
>> +	}
>> +
>> +	/*
>> +	 * Now we have to re-check the live state, in case the port recently
>> +	 * became disconnected. Not necessary for legacy mode.
>> +	 */
>> +	if (dig_port->tc_type == TC_PORT_TYPEC &&
>> +	    !(I915_READ(PORT_TX_DFLEXDPSP) & TC_LIVE_STATE_TC(tc_port))) {
>> +		DRM_DEBUG_KMS("TC PHY %d sudden disconnect.\n", tc_port);
>> +		icl_tc_phy_disconnect(dig_port);
>> +		return false;
>> +	}
>> +
>> +	return true;
>> +}
>> +
>> +/*
>> + * See the comment at the connect function. This implements the Disconnect
>> + * Flow.
>> + */
>> +void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
>> +{
>> +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
>> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
>> +
>> +	if (dig_port->tc_type == TC_PORT_UNKNOWN)
>> +		return;
>> +
>> +	/*
>> +	 * TBT disconnection flow is read the live status, what was done in
>> +	 * caller.
>> +	 */
>> +	if (dig_port->tc_type == TC_PORT_TYPEC ||
>> +	    dig_port->tc_type == TC_PORT_LEGACY) {
>> +		u32 val;
>> +
>> +		val = I915_READ(PORT_TX_DFLEXDPCSSS);
>> +		val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
>> +		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
>> +	}
>> +
>> +	DRM_DEBUG_KMS("Port %c TC type %s disconnected\n",
>> +		      port_name(dig_port->base.port),
>> +		      tc_type_name(dig_port->tc_type));
>> +
>> +	dig_port->tc_type = TC_PORT_UNKNOWN;
>> +}
>> +
>> +static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
>> +				    struct intel_digital_port *intel_dig_port,
>> +				    bool is_legacy, bool is_typec, bool is_tbt)
>> +{
>> +	enum port port = intel_dig_port->base.port;
>> +	enum tc_port_type old_type = intel_dig_port->tc_type;
>> +
>> +	WARN_ON(is_legacy + is_typec + is_tbt != 1);
>> +
>> +	if (is_legacy)
>> +		intel_dig_port->tc_type = TC_PORT_LEGACY;
>> +	else if (is_typec)
>> +		intel_dig_port->tc_type = TC_PORT_TYPEC;
>> +	else if (is_tbt)
>> +		intel_dig_port->tc_type = TC_PORT_TBT;
>> +	else
>> +		return;
>> +
>> +	/* Types are not supposed to be changed at runtime. */
>> +	WARN_ON(old_type != TC_PORT_UNKNOWN &&
>> +		old_type != intel_dig_port->tc_type);
>> +
>> +	if (old_type != intel_dig_port->tc_type)
>> +		DRM_DEBUG_KMS("Port %c has TC type %s\n", port_name(port),
>> +			      tc_type_name(intel_dig_port->tc_type));
>> +}
>> +
>> +
>> +/*
>> + * The type-C ports are different because even when they are connected, they may
>> + * not be available/usable by the graphics driver: see the comment on
>> + * icl_tc_phy_connect(). So in our driver instead of adding the additional
>> + * concept of "usable" and make everything check for "connected and usable" we
>> + * define a port as "connected" when it is not only connected, but also when it
>> + * is usable by the rest of the driver. That maintains the old assumption that
>> + * connected ports are usable, and avoids exposing to the users objects they
>> + * can't really use.
>> + */
>> +bool intel_tc_port_connected(struct intel_digital_port *dig_port)
>> +{
>> +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
>> +	enum port port = dig_port->base.port;
>> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
>> +	bool is_legacy, is_typec, is_tbt;
>> +	u32 dpsp;
>> +
>> +	/*
>> +	 * Complain if we got a legacy port HPD, but VBT didn't mark the port as
>> +	 * legacy. Treat the port as legacy from now on.
>> +	 */
>> +	if (!dig_port->tc_legacy_port &&
>> +	    I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port)) {
>> +		DRM_ERROR("VBT incorrectly claims port %c is not TypeC legacy\n",
>> +			  port_name(port));
>> +		dig_port->tc_legacy_port = true;
>> +	}
>> +	is_legacy = dig_port->tc_legacy_port;
>> +
>> +	/*
>> +	 * The spec says we shouldn't be using the ISR bits for detecting
>> +	 * between TC and TBT. We should use DFLEXDPSP.
>> +	 */
>> +	dpsp = I915_READ(PORT_TX_DFLEXDPSP);
>> +	is_typec = dpsp & TC_LIVE_STATE_TC(tc_port);
>> +	is_tbt = dpsp & TC_LIVE_STATE_TBT(tc_port);
>> +
>> +	if (!is_legacy && !is_typec && !is_tbt) {
>> +		icl_tc_phy_disconnect(dig_port);
>> +
>> +		return false;
>> +	}
>> +
>> +	icl_update_tc_port_type(dev_priv, dig_port, is_legacy, is_typec,
>> +				is_tbt);
>> +
>> +	if (!icl_tc_phy_connect(dig_port))
>> +		return false;
>> +
>> +	return true;
>> +}
>> +
>> diff --git a/drivers/gpu/drm/i915/intel_tc.h b/drivers/gpu/drm/i915/intel_tc.h
>> new file mode 100644
>> index 000000000000..94c62ac4a162
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/intel_tc.h
>> @@ -0,0 +1,13 @@
>
> SPDX header here please.
>
>> +#ifndef __INTEL_TC_H__
>> +#define __INTEL_TC_H__
>> +
>> +#include <linux/types.h>
>> +
>> +struct intel_digital_port;
>> +
>> +void icl_tc_phy_disconnect(struct intel_digital_port *dig_port);
>
> I'd like to see this named intel_tc_* in the future.
>
> BR,
> Jani.
>
>
>> +
>> +bool intel_tc_port_connected(struct intel_digital_port *dig_port);
>> +int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port);
>> +
>> +#endif /* __INTEL_TC_H__ */

-- 
Jani Nikula, Intel Open Source Graphics Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 09/23] drm/i915: Factor out common parts from TypeC port handling functions
  2019-06-04 14:58 ` [PATCH 09/23] drm/i915: Factor out common parts from TypeC port handling functions Imre Deak
@ 2019-06-06  8:47   ` Jani Nikula
  2019-06-06  9:19     ` Imre Deak
  2019-06-07 21:22   ` Souza, Jose
  2019-06-18 16:33   ` Ville Syrjälä
  2 siblings, 1 reply; 79+ messages in thread
From: Jani Nikula @ 2019-06-06  8:47 UTC (permalink / raw)
  To: Imre Deak, intel-gfx; +Cc: Paulo Zanoni

On Tue, 04 Jun 2019, Imre Deak <imre.deak@intel.com> wrote:
> Factor out helpers reading/parsing the TypeC specific registers, making
> current users of them clearer and letting us use them later.
>
> While at it also:
> - Simplify icl_tc_phy_connect() with an early return in legacy mode.
> - Simplify the live status check using one bitmask for all HPD bits.
> - Remove a micro-optimisation of the repeated safe-mode clearing.
> - Make sure we fix the legacy port flag in all cases.
>
> Except for the last two, no functional changes.
>
> Cc: José Roberto de Souza <jose.souza@intel.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_ddi.c |   5 +-
>  drivers/gpu/drm/i915/intel_tc.c  | 166 +++++++++++++++++++------------
>  drivers/gpu/drm/i915/intel_tc.h  |   1 +
>  3 files changed, 103 insertions(+), 69 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index 8f223d48d562..d236839bee19 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -2983,7 +2983,6 @@ static void icl_program_mg_dp_mode(struct intel_digital_port *intel_dig_port)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
>  	enum port port = intel_dig_port->base.port;
> -	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
>  	u32 ln0, ln1, lane_info;
>  
>  	if (intel_dig_port->tc_mode == TC_PORT_TBT_ALT)
> @@ -2997,9 +2996,7 @@ static void icl_program_mg_dp_mode(struct intel_digital_port *intel_dig_port)
>  		ln0 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
>  		ln1 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
>  
> -		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
> -			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
> -			    DP_LANE_ASSIGNMENT_SHIFT(tc_port);
> +		lane_info = intel_tc_port_get_lane_info(intel_dig_port);
>  
>  		switch (lane_info) {
>  		case 0x1:
> diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
> index 07488235b67a..3fdcfa2bbaee 100644
> --- a/drivers/gpu/drm/i915/intel_tc.c
> +++ b/drivers/gpu/drm/i915/intel_tc.c
> @@ -43,10 +43,19 @@ static const char *tc_port_mode_name(enum tc_port_mode mode)
>  	return names[mode];
>  }
>  
> -int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
> +u32 intel_tc_port_get_lane_info(struct intel_digital_port *dig_port)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
>  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> +	u32 lane_info = I915_READ(PORT_TX_DFLEXDPSP);

Please don't do register reads in declarations. Ditto below.

> +
> +	return (lane_info & DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
> +	       DP_LANE_ASSIGNMENT_SHIFT(tc_port);
> +}
> +
> +int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
>  	intel_wakeref_t wakeref;
>  	u32 lane_info;
>  
> @@ -55,9 +64,7 @@ int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
>  
>  	lane_info = 0;
>  	with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref)
> -		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
> -			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
> -				DP_LANE_ASSIGNMENT_SHIFT(tc_port);
> +		lane_info = intel_tc_port_get_lane_info(dig_port);
>  
>  	switch (lane_info) {
>  	default:
> @@ -75,6 +82,69 @@ int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
>  	}
>  }
>  
> +static void tc_port_fixup_legacy_flag(struct intel_digital_port *dig_port,
> +				      u32 live_status_mask)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> +	u32 valid_hpd_mask = dig_port->tc_legacy_port ? BIT(TC_PORT_LEGACY) :
> +							~BIT(TC_PORT_LEGACY);
> +
> +	if (!(live_status_mask & ~valid_hpd_mask))
> +		return;
> +
> +	/* If live status mismatches the VBT flag, trust the live status. */
> +	DRM_ERROR("Port %s: live status %08x mismatches the legacy port flag, fix flag\n",
> +		  tc_port_name(dev_priv, tc_port), live_status_mask);
> +
> +	dig_port->tc_legacy_port = !dig_port->tc_legacy_port;
> +}
> +
> +static u32 tc_port_live_status_mask(struct intel_digital_port *dig_port)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> +	u32 val = I915_READ(PORT_TX_DFLEXDPSP);
> +	u32 mask = 0;
> +
> +	if (val & TC_LIVE_STATE_TBT(tc_port))
> +		mask |= BIT(TC_PORT_TBT_ALT);
> +	if (val & TC_LIVE_STATE_TC(tc_port))
> +		mask |= BIT(TC_PORT_DP_ALT);
> +
> +	if (I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port))
> +		mask |= BIT(TC_PORT_LEGACY);
> +
> +	/* The sink can be connected only in a single mode. */
> +	if (!WARN_ON(hweight32(mask) > 1))
> +		tc_port_fixup_legacy_flag(dig_port, mask);
> +
> +	return mask;
> +}
> +
> +static bool icl_tc_phy_status_complete(struct intel_digital_port *dig_port)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> +
> +	return I915_READ(PORT_TX_DFLEXDPPMS) &
> +	       DP_PHY_MODE_STATUS_COMPLETED(tc_port);
> +}
> +
> +static void icl_tc_phy_set_safe_mode(struct intel_digital_port *dig_port,
> +				     bool enable)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> +	u32 val = I915_READ(PORT_TX_DFLEXDPCSSS);
> +
> +	val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> +	if (!enable)
> +		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> +
> +	I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> +}
> +
>  /*
>   * This function implements the first part of the Connect Flow described by our
>   * specification, Gen11 TypeC Programming chapter. The rest of the flow (reading
> @@ -100,36 +170,31 @@ static bool icl_tc_phy_connect(struct intel_digital_port *dig_port)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
>  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> -	u32 val;
> +	u32 live_status_mask;
>  
>  	if (dig_port->tc_mode != TC_PORT_LEGACY &&
>  	    dig_port->tc_mode != TC_PORT_DP_ALT)
>  		return true;
>  
> -	val = I915_READ(PORT_TX_DFLEXDPPMS);
> -	if (!(val & DP_PHY_MODE_STATUS_COMPLETED(tc_port))) {
> +	if (!icl_tc_phy_status_complete(dig_port)) {
>  		DRM_DEBUG_KMS("Port %s: PHY not ready\n",
>  			      tc_port_name(dev_priv, tc_port));
>  		WARN_ON(dig_port->tc_legacy_port);
>  		return false;
>  	}
>  
> -	/*
> -	 * This function may be called many times in a row without an HPD event
> -	 * in between, so try to avoid the write when we can.
> -	 */
> -	val = I915_READ(PORT_TX_DFLEXDPCSSS);
> -	if (!(val & DP_PHY_MODE_STATUS_NOT_SAFE(tc_port))) {
> -		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> -		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> -	}
> +	icl_tc_phy_set_safe_mode(dig_port, false);
> +
> +	if (dig_port->tc_mode == TC_PORT_LEGACY)
> +		return true;
> +
> +	live_status_mask = tc_port_live_status_mask(dig_port);
>  
>  	/*
>  	 * Now we have to re-check the live state, in case the port recently
>  	 * became disconnected. Not necessary for legacy mode.
>  	 */
> -	if (dig_port->tc_mode == TC_PORT_DP_ALT &&
> -	    !(I915_READ(PORT_TX_DFLEXDPSP) & TC_LIVE_STATE_TC(tc_port))) {
> +	if (!(live_status_mask & BIT(TC_PORT_DP_ALT))) {
>  		DRM_DEBUG_KMS("Port %s: PHY sudden disconnect\n",
>  			      tc_port_name(dev_priv, tc_port));
>  		icl_tc_phy_disconnect(dig_port);
> @@ -148,44 +213,36 @@ void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
>  	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
>  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
>  
> -	/*
> -	 * TBT disconnection flow is read the live status, what was done in
> -	 * caller.
> -	 */
> -	if (dig_port->tc_mode == TC_PORT_DP_ALT ||
> -	    dig_port->tc_mode == TC_PORT_LEGACY) {
> -		u32 val;
> -
> -		val = I915_READ(PORT_TX_DFLEXDPCSSS);
> -		val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> -		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> +	switch (dig_port->tc_mode) {
> +	case TC_PORT_LEGACY:
> +	case TC_PORT_DP_ALT:
> +		icl_tc_phy_set_safe_mode(dig_port, true);
> +		dig_port->tc_mode = TC_PORT_TBT_ALT;
> +		break;
> +	case TC_PORT_TBT_ALT:
> +		/* Nothing to do, we stay in TBT-alt mode */
> +		break;
> +	default:
> +		MISSING_CASE(dig_port->tc_mode);
>  	}
>  
>  	DRM_DEBUG_KMS("Port %s: mode %s disconnected\n",
>  		      tc_port_name(dev_priv, tc_port),
>  		      tc_port_mode_name(dig_port->tc_mode));
> -
> -	dig_port->tc_mode = TC_PORT_TBT_ALT;
>  }
>  
>  static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
>  				    struct intel_digital_port *intel_dig_port,
> -				    bool is_legacy, bool is_typec, bool is_tbt)
> +				    u32 live_status_mask)
>  {
>  	enum port port = intel_dig_port->base.port;
>  	enum tc_port_mode old_mode = intel_dig_port->tc_mode;
>  
> -	WARN_ON(is_legacy + is_typec + is_tbt != 1);
> -
> -	if (is_legacy)
> -		intel_dig_port->tc_mode = TC_PORT_LEGACY;
> -	else if (is_typec)
> -		intel_dig_port->tc_mode = TC_PORT_DP_ALT;
> -	else if (is_tbt)
> -		intel_dig_port->tc_mode = TC_PORT_TBT_ALT;
> -	else
> +	if (!live_status_mask)
>  		return;
>  
> +	intel_dig_port->tc_mode = fls(live_status_mask) - 1;
> +
>  	if (old_mode != intel_dig_port->tc_mode)
>  		DRM_DEBUG_KMS("Port %s: port has mode %s\n",
>  			      tc_port_name(dev_priv,
> @@ -207,40 +264,19 @@ static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
>  bool intel_tc_port_connected(struct intel_digital_port *dig_port)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> -	enum port port = dig_port->base.port;
> -	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
> -	bool is_legacy, is_typec, is_tbt;
> -	u32 dpsp;
> -
> -	/*
> -	 * Complain if we got a legacy port HPD, but VBT didn't mark the port as
> -	 * legacy. Treat the port as legacy from now on.
> -	 */
> -	if (!dig_port->tc_legacy_port &&
> -	    I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port)) {
> -		DRM_ERROR("Port %s: VBT incorrectly claims port is not TypeC legacy\n",
> -			  tc_port_name(dev_priv, tc_port));
> -		dig_port->tc_legacy_port = true;
> -	}
> -	is_legacy = dig_port->tc_legacy_port;
> +	u32 live_status_mask = tc_port_live_status_mask(dig_port);
>  
>  	/*
>  	 * The spec says we shouldn't be using the ISR bits for detecting
>  	 * between TC and TBT. We should use DFLEXDPSP.
>  	 */
> -	dpsp = I915_READ(PORT_TX_DFLEXDPSP);
> -	is_typec = dpsp & TC_LIVE_STATE_TC(tc_port);
> -	is_tbt = dpsp & TC_LIVE_STATE_TBT(tc_port);
> -
> -	if (!is_legacy && !is_typec && !is_tbt) {
> +	if (!live_status_mask && !dig_port->tc_legacy_port) {
>  		icl_tc_phy_disconnect(dig_port);
>  
>  		return false;
>  	}
>  
> -	icl_update_tc_port_type(dev_priv, dig_port, is_legacy, is_typec,
> -				is_tbt);
> -
> +	icl_update_tc_port_type(dev_priv, dig_port, live_status_mask);
>  	if (!icl_tc_phy_connect(dig_port))
>  		return false;
>  
> diff --git a/drivers/gpu/drm/i915/intel_tc.h b/drivers/gpu/drm/i915/intel_tc.h
> index 94c62ac4a162..e937f5326959 100644
> --- a/drivers/gpu/drm/i915/intel_tc.h
> +++ b/drivers/gpu/drm/i915/intel_tc.h
> @@ -8,6 +8,7 @@ struct intel_digital_port;
>  void icl_tc_phy_disconnect(struct intel_digital_port *dig_port);
>  
>  bool intel_tc_port_connected(struct intel_digital_port *dig_port);
> +u32 intel_tc_port_get_lane_info(struct intel_digital_port *dig_port);
>  int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port);
>  
>  #endif /* __INTEL_TC_H__ */

-- 
Jani Nikula, Intel Open Source Graphics Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 03/23] drm/i915: Move the TypeC port handling code to a separate file
  2019-06-06  8:42   ` Jani Nikula
  2019-06-06  8:43     ` Jani Nikula
@ 2019-06-06  9:09     ` Imre Deak
  2019-06-10 22:57     ` Lucas De Marchi
  2 siblings, 0 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-06  9:09 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx, Paulo Zanoni

On Thu, Jun 06, 2019 at 11:42:46AM +0300, Jani Nikula wrote:
> On Tue, 04 Jun 2019, Imre Deak <imre.deak@intel.com> wrote:
> > Move the TypeC port handling functions to a new file for clarity.
> >
> > While at it:
> > - s/icl_tc_port_connected()/intel_tc_port_connected()/
> >   icl_tc_phy_disconnect(), will be unexported later.
> >
> > - s/intel_dp_get_fia_supported_lane_count()/intel_tc_port_fia_max_lane_count()/
> >   It's used for HDMI legacy mode too.
> >
> > - Simplify function interfaces by passing only dig_port to them.
> >
> > No functional changes.
> 
> Some nitpicks below.
> 
> BR,
> Jani.
> 
> 
> >
> > Cc: Animesh Manna <animesh.manna@intel.com>
> > Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > Cc: José Roberto de Souza <jose.souza@intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/Makefile             |   3 +-
> >  drivers/gpu/drm/i915/Makefile.header-test |   1 +
> >  drivers/gpu/drm/i915/intel_ddi.c          |   6 +-
> >  drivers/gpu/drm/i915/intel_dp.c           | 227 +--------------------
> >  drivers/gpu/drm/i915/intel_dp.h           |   2 -
> >  drivers/gpu/drm/i915/intel_tc.c           | 230 ++++++++++++++++++++++
> >  drivers/gpu/drm/i915/intel_tc.h           |  13 ++
> >  7 files changed, 252 insertions(+), 230 deletions(-)
> >  create mode 100644 drivers/gpu/drm/i915/intel_tc.c
> >  create mode 100644 drivers/gpu/drm/i915/intel_tc.h
> >
> > diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> > index c0a7b2994077..74c4d11d83eb 100644
> > --- a/drivers/gpu/drm/i915/Makefile
> > +++ b/drivers/gpu/drm/i915/Makefile
> > @@ -171,7 +171,8 @@ i915-y += intel_audio.o \
> >  	  intel_psr.o \
> >  	  intel_quirks.o \
> >  	  intel_sideband.o \
> > -	  intel_sprite.o
> > +	  intel_sprite.o \
> > +	  intel_tc.o
> >  i915-$(CONFIG_ACPI)		+= intel_acpi.o intel_opregion.o
> >  i915-$(CONFIG_DRM_FBDEV_EMULATION)	+= intel_fbdev.o
> >  
> > diff --git a/drivers/gpu/drm/i915/Makefile.header-test b/drivers/gpu/drm/i915/Makefile.header-test
> > index 6ef3b647ac65..e80e8e45b09c 100644
> > --- a/drivers/gpu/drm/i915/Makefile.header-test
> > +++ b/drivers/gpu/drm/i915/Makefile.header-test
> > @@ -58,6 +58,7 @@ header_test := \
> >  	intel_sdvo.h \
> >  	intel_sideband.h \
> >  	intel_sprite.h \
> > +	intel_tc.h \
> >  	intel_tv.h \
> >  	intel_uncore.h \
> >  	intel_vdsc.h \
> > diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> > index 350eaf54f01f..5a1c98438375 100644
> > --- a/drivers/gpu/drm/i915/intel_ddi.c
> > +++ b/drivers/gpu/drm/i915/intel_ddi.c
> > @@ -45,6 +45,7 @@
> >  #include "intel_lspcon.h"
> >  #include "intel_panel.h"
> >  #include "intel_psr.h"
> > +#include "intel_tc.h"
> >  #include "intel_vdsc.h"
> >  
> >  struct ddi_buf_trans {
> > @@ -3904,7 +3905,6 @@ static int intel_ddi_compute_config(struct intel_encoder *encoder,
> >  static void intel_ddi_encoder_suspend(struct intel_encoder *encoder)
> >  {
> >  	struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
> > -	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> >  
> >  	intel_dp_encoder_suspend(encoder);
> >  
> > @@ -3914,7 +3914,7 @@ static void intel_ddi_encoder_suspend(struct intel_encoder *encoder)
> >  	 * even if the sink has disappeared while being suspended.
> >  	 */
> >  	if (dig_port->tc_legacy_port)
> > -		icl_tc_phy_disconnect(i915, dig_port);
> > +		icl_tc_phy_disconnect(dig_port);
> >  }
> >  
> >  static void intel_ddi_encoder_reset(struct drm_encoder *drm_encoder)
> > @@ -3936,7 +3936,7 @@ static void intel_ddi_encoder_destroy(struct drm_encoder *encoder)
> >  	intel_dp_encoder_flush_work(encoder);
> >  
> >  	if (intel_port_is_tc(i915, dig_port->base.port))
> > -		icl_tc_phy_disconnect(i915, dig_port);
> > +		icl_tc_phy_disconnect(dig_port);
> >  
> >  	drm_encoder_cleanup(encoder);
> >  	kfree(dig_port);
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 24b56b2a76c8..b69310bd9914 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -62,6 +62,7 @@
> >  #include "intel_panel.h"
> >  #include "intel_psr.h"
> >  #include "intel_sideband.h"
> > +#include "intel_tc.h"
> >  #include "intel_vdsc.h"
> >  
> >  #define DP_DPRX_ESI_LEN 14
> > @@ -211,46 +212,13 @@ static int intel_dp_max_common_rate(struct intel_dp *intel_dp)
> >  	return intel_dp->common_rates[intel_dp->num_common_rates - 1];
> >  }
> >  
> > -static int intel_dp_get_fia_supported_lane_count(struct intel_dp *intel_dp)
> > -{
> > -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> > -	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> > -	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> > -	intel_wakeref_t wakeref;
> > -	u32 lane_info;
> > -
> > -	if (tc_port == PORT_TC_NONE || dig_port->tc_type != TC_PORT_TYPEC)
> > -		return 4;
> > -
> > -	lane_info = 0;
> > -	with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref)
> > -		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
> > -			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
> > -				DP_LANE_ASSIGNMENT_SHIFT(tc_port);
> > -
> > -	switch (lane_info) {
> > -	default:
> > -		MISSING_CASE(lane_info);
> > -	case 1:
> > -	case 2:
> > -	case 4:
> > -	case 8:
> > -		return 1;
> > -	case 3:
> > -	case 12:
> > -		return 2;
> > -	case 15:
> > -		return 4;
> > -	}
> > -}
> > -
> >  /* Theoretical max between source and sink */
> >  static int intel_dp_max_common_lane_count(struct intel_dp *intel_dp)
> >  {
> >  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> >  	int source_max = intel_dig_port->max_lanes;
> >  	int sink_max = drm_dp_max_lane_count(intel_dp->dpcd);
> > -	int fia_max = intel_dp_get_fia_supported_lane_count(intel_dp);
> > +	int fia_max = intel_tc_port_fia_max_lane_count(intel_dig_port);
> >  
> >  	return min3(source_max, sink_max, fia_max);
> >  }
> > @@ -5231,195 +5199,6 @@ static bool icl_combo_port_connected(struct drm_i915_private *dev_priv,
> >  	return I915_READ(SDEISR) & SDE_DDI_HOTPLUG_ICP(port);
> >  }
> >  
> > -static const char *tc_type_name(enum tc_port_type type)
> > -{
> > -	static const char * const names[] = {
> > -		[TC_PORT_UNKNOWN] = "unknown",
> > -		[TC_PORT_LEGACY] = "legacy",
> > -		[TC_PORT_TYPEC] = "typec",
> > -		[TC_PORT_TBT] = "tbt",
> > -	};
> > -
> > -	if (WARN_ON(type >= ARRAY_SIZE(names)))
> > -		type = TC_PORT_UNKNOWN;
> > -
> > -	return names[type];
> > -}
> > -
> > -static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
> > -				    struct intel_digital_port *intel_dig_port,
> > -				    bool is_legacy, bool is_typec, bool is_tbt)
> > -{
> > -	enum port port = intel_dig_port->base.port;
> > -	enum tc_port_type old_type = intel_dig_port->tc_type;
> > -
> > -	WARN_ON(is_legacy + is_typec + is_tbt != 1);
> > -
> > -	if (is_legacy)
> > -		intel_dig_port->tc_type = TC_PORT_LEGACY;
> > -	else if (is_typec)
> > -		intel_dig_port->tc_type = TC_PORT_TYPEC;
> > -	else if (is_tbt)
> > -		intel_dig_port->tc_type = TC_PORT_TBT;
> > -	else
> > -		return;
> > -
> > -	/* Types are not supposed to be changed at runtime. */
> > -	WARN_ON(old_type != TC_PORT_UNKNOWN &&
> > -		old_type != intel_dig_port->tc_type);
> > -
> > -	if (old_type != intel_dig_port->tc_type)
> > -		DRM_DEBUG_KMS("Port %c has TC type %s\n", port_name(port),
> > -			      tc_type_name(intel_dig_port->tc_type));
> > -}
> > -
> > -/*
> > - * This function implements the first part of the Connect Flow described by our
> > - * specification, Gen11 TypeC Programming chapter. The rest of the flow (reading
> > - * lanes, EDID, etc) is done as needed in the typical places.
> > - *
> > - * Unlike the other ports, type-C ports are not available to use as soon as we
> > - * get a hotplug. The type-C PHYs can be shared between multiple controllers:
> > - * display, USB, etc. As a result, handshaking through FIA is required around
> > - * connect and disconnect to cleanly transfer ownership with the controller and
> > - * set the type-C power state.
> > - *
> > - * We could opt to only do the connect flow when we actually try to use the AUX
> > - * channels or do a modeset, then immediately run the disconnect flow after
> > - * usage, but there are some implications on this for a dynamic environment:
> > - * things may go away or change behind our backs. So for now our driver is
> > - * always trying to acquire ownership of the controller as soon as it gets an
> > - * interrupt (or polls state and sees a port is connected) and only gives it
> > - * back when it sees a disconnect. Implementation of a more fine-grained model
> > - * will require a lot of coordination with user space and thorough testing for
> > - * the extra possible cases.
> > - */
> > -static bool icl_tc_phy_connect(struct drm_i915_private *dev_priv,
> > -			       struct intel_digital_port *dig_port)
> > -{
> > -	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> > -	u32 val;
> > -
> > -	if (dig_port->tc_type != TC_PORT_LEGACY &&
> > -	    dig_port->tc_type != TC_PORT_TYPEC)
> > -		return true;
> > -
> > -	val = I915_READ(PORT_TX_DFLEXDPPMS);
> > -	if (!(val & DP_PHY_MODE_STATUS_COMPLETED(tc_port))) {
> > -		DRM_DEBUG_KMS("DP PHY for TC port %d not ready\n", tc_port);
> > -		WARN_ON(dig_port->tc_legacy_port);
> > -		return false;
> > -	}
> > -
> > -	/*
> > -	 * This function may be called many times in a row without an HPD event
> > -	 * in between, so try to avoid the write when we can.
> > -	 */
> > -	val = I915_READ(PORT_TX_DFLEXDPCSSS);
> > -	if (!(val & DP_PHY_MODE_STATUS_NOT_SAFE(tc_port))) {
> > -		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> > -		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> > -	}
> > -
> > -	/*
> > -	 * Now we have to re-check the live state, in case the port recently
> > -	 * became disconnected. Not necessary for legacy mode.
> > -	 */
> > -	if (dig_port->tc_type == TC_PORT_TYPEC &&
> > -	    !(I915_READ(PORT_TX_DFLEXDPSP) & TC_LIVE_STATE_TC(tc_port))) {
> > -		DRM_DEBUG_KMS("TC PHY %d sudden disconnect.\n", tc_port);
> > -		icl_tc_phy_disconnect(dev_priv, dig_port);
> > -		return false;
> > -	}
> > -
> > -	return true;
> > -}
> > -
> > -/*
> > - * See the comment at the connect function. This implements the Disconnect
> > - * Flow.
> > - */
> > -void icl_tc_phy_disconnect(struct drm_i915_private *dev_priv,
> > -			   struct intel_digital_port *dig_port)
> > -{
> > -	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> > -
> > -	if (dig_port->tc_type == TC_PORT_UNKNOWN)
> > -		return;
> > -
> > -	/*
> > -	 * TBT disconnection flow is read the live status, what was done in
> > -	 * caller.
> > -	 */
> > -	if (dig_port->tc_type == TC_PORT_TYPEC ||
> > -	    dig_port->tc_type == TC_PORT_LEGACY) {
> > -		u32 val;
> > -
> > -		val = I915_READ(PORT_TX_DFLEXDPCSSS);
> > -		val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> > -		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> > -	}
> > -
> > -	DRM_DEBUG_KMS("Port %c TC type %s disconnected\n",
> > -		      port_name(dig_port->base.port),
> > -		      tc_type_name(dig_port->tc_type));
> > -
> > -	dig_port->tc_type = TC_PORT_UNKNOWN;
> > -}
> > -
> > -/*
> > - * The type-C ports are different because even when they are connected, they may
> > - * not be available/usable by the graphics driver: see the comment on
> > - * icl_tc_phy_connect(). So in our driver instead of adding the additional
> > - * concept of "usable" and make everything check for "connected and usable" we
> > - * define a port as "connected" when it is not only connected, but also when it
> > - * is usable by the rest of the driver. That maintains the old assumption that
> > - * connected ports are usable, and avoids exposing to the users objects they
> > - * can't really use.
> > - */
> > -static bool icl_tc_port_connected(struct drm_i915_private *dev_priv,
> > -				  struct intel_digital_port *intel_dig_port)
> > -{
> > -	enum port port = intel_dig_port->base.port;
> > -	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
> > -	bool is_legacy, is_typec, is_tbt;
> > -	u32 dpsp;
> > -
> > -	/*
> > -	 * Complain if we got a legacy port HPD, but VBT didn't mark the port as
> > -	 * legacy. Treat the port as legacy from now on.
> > -	 */
> > -	if (!intel_dig_port->tc_legacy_port &&
> > -	    I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port)) {
> > -		DRM_ERROR("VBT incorrectly claims port %c is not TypeC legacy\n",
> > -			  port_name(port));
> > -		intel_dig_port->tc_legacy_port = true;
> > -	}
> > -	is_legacy = intel_dig_port->tc_legacy_port;
> > -
> > -	/*
> > -	 * The spec says we shouldn't be using the ISR bits for detecting
> > -	 * between TC and TBT. We should use DFLEXDPSP.
> > -	 */
> > -	dpsp = I915_READ(PORT_TX_DFLEXDPSP);
> > -	is_typec = dpsp & TC_LIVE_STATE_TC(tc_port);
> > -	is_tbt = dpsp & TC_LIVE_STATE_TBT(tc_port);
> > -
> > -	if (!is_legacy && !is_typec && !is_tbt) {
> > -		icl_tc_phy_disconnect(dev_priv, intel_dig_port);
> > -
> > -		return false;
> > -	}
> > -
> > -	icl_update_tc_port_type(dev_priv, intel_dig_port, is_legacy, is_typec,
> > -				is_tbt);
> > -
> > -	if (!icl_tc_phy_connect(dev_priv, intel_dig_port))
> > -		return false;
> > -
> > -	return true;
> > -}
> > -
> >  static bool icl_digital_port_connected(struct intel_encoder *encoder)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> > @@ -5428,7 +5207,7 @@ static bool icl_digital_port_connected(struct intel_encoder *encoder)
> >  	if (intel_port_is_combophy(dev_priv, encoder->port))
> >  		return icl_combo_port_connected(dev_priv, dig_port);
> >  	else if (intel_port_is_tc(dev_priv, encoder->port))
> > -		return icl_tc_port_connected(dev_priv, dig_port);
> > +		return intel_tc_port_connected(dig_port);
> >  	else
> >  		MISSING_CASE(encoder->hpd_pin);
> >  
> > diff --git a/drivers/gpu/drm/i915/intel_dp.h b/drivers/gpu/drm/i915/intel_dp.h
> > index da70b1a41c83..657bbb1f5ed0 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.h
> > +++ b/drivers/gpu/drm/i915/intel_dp.h
> > @@ -112,8 +112,6 @@ bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp);
> >  int intel_dp_link_required(int pixel_clock, int bpp);
> >  int intel_dp_max_data_rate(int max_link_clock, int max_lanes);
> >  bool intel_digital_port_connected(struct intel_encoder *encoder);
> > -void icl_tc_phy_disconnect(struct drm_i915_private *dev_priv,
> > -			   struct intel_digital_port *dig_port);
> >  
> >  static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
> >  {
> > diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
> > new file mode 100644
> > index 000000000000..7a1b5870945f
> > --- /dev/null
> > +++ b/drivers/gpu/drm/i915/intel_tc.c
> > @@ -0,0 +1,230 @@
> > +// SPDX-License-Identifier: MIT
> > +/*
> > + * Copyright © 2019 Intel Corporation
> > + */
> 
> From the Nitpicks Department, please add a blank line here.

Ok.

> 
> > +#include "intel_display.h"
> > +#include "i915_drv.h"
> > +#include "intel_tc.h"
> 
> And sort the includes.

Ok, forgot that here..

> 
> > +
> > +static const char *tc_type_name(enum tc_port_type type)
> > +{
> > +	static const char * const names[] = {
> > +		[TC_PORT_UNKNOWN] = "unknown",
> > +		[TC_PORT_LEGACY] = "legacy",
> > +		[TC_PORT_TYPEC] = "typec",
> > +		[TC_PORT_TBT] = "tbt",
> > +	};
> > +
> > +	if (WARN_ON(type >= ARRAY_SIZE(names)))
> > +		type = TC_PORT_UNKNOWN;
> > +
> > +	return names[type];
> > +}
> > +
> > +int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> > +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> > +	intel_wakeref_t wakeref;
> > +	u32 lane_info;
> > +
> > +	if (tc_port == PORT_TC_NONE || dig_port->tc_type != TC_PORT_TYPEC)
> > +		return 4;
> > +
> > +	lane_info = 0;
> > +	with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref)
> > +		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
> > +			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
> > +				DP_LANE_ASSIGNMENT_SHIFT(tc_port);
> > +
> > +	switch (lane_info) {
> > +	default:
> > +		MISSING_CASE(lane_info);
> > +	case 1:
> > +	case 2:
> > +	case 4:
> > +	case 8:
> > +		return 1;
> > +	case 3:
> > +	case 12:
> > +		return 2;
> > +	case 15:
> > +		return 4;
> > +	}
> > +}
> > +
> > +/*
> > + * This function implements the first part of the Connect Flow described by our
> > + * specification, Gen11 TypeC Programming chapter. The rest of the flow (reading
> > + * lanes, EDID, etc) is done as needed in the typical places.
> > + *
> > + * Unlike the other ports, type-C ports are not available to use as soon as we
> > + * get a hotplug. The type-C PHYs can be shared between multiple controllers:
> > + * display, USB, etc. As a result, handshaking through FIA is required around
> > + * connect and disconnect to cleanly transfer ownership with the controller and
> > + * set the type-C power state.
> > + *
> > + * We could opt to only do the connect flow when we actually try to use the AUX
> > + * channels or do a modeset, then immediately run the disconnect flow after
> > + * usage, but there are some implications on this for a dynamic environment:
> > + * things may go away or change behind our backs. So for now our driver is
> > + * always trying to acquire ownership of the controller as soon as it gets an
> > + * interrupt (or polls state and sees a port is connected) and only gives it
> > + * back when it sees a disconnect. Implementation of a more fine-grained model
> > + * will require a lot of coordination with user space and thorough testing for
> > + * the extra possible cases.
> > + */
> > +static bool icl_tc_phy_connect(struct intel_digital_port *dig_port)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> > +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> > +	u32 val;
> > +
> > +	if (dig_port->tc_type != TC_PORT_LEGACY &&
> > +	    dig_port->tc_type != TC_PORT_TYPEC)
> > +		return true;
> > +
> > +	val = I915_READ(PORT_TX_DFLEXDPPMS);
> > +	if (!(val & DP_PHY_MODE_STATUS_COMPLETED(tc_port))) {
> > +		DRM_DEBUG_KMS("DP PHY for TC port %d not ready\n", tc_port);
> > +		WARN_ON(dig_port->tc_legacy_port);
> > +		return false;
> > +	}
> > +
> > +	/*
> > +	 * This function may be called many times in a row without an HPD event
> > +	 * in between, so try to avoid the write when we can.
> > +	 */
> > +	val = I915_READ(PORT_TX_DFLEXDPCSSS);
> > +	if (!(val & DP_PHY_MODE_STATUS_NOT_SAFE(tc_port))) {
> > +		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> > +		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> > +	}
> > +
> > +	/*
> > +	 * Now we have to re-check the live state, in case the port recently
> > +	 * became disconnected. Not necessary for legacy mode.
> > +	 */
> > +	if (dig_port->tc_type == TC_PORT_TYPEC &&
> > +	    !(I915_READ(PORT_TX_DFLEXDPSP) & TC_LIVE_STATE_TC(tc_port))) {
> > +		DRM_DEBUG_KMS("TC PHY %d sudden disconnect.\n", tc_port);
> > +		icl_tc_phy_disconnect(dig_port);
> > +		return false;
> > +	}
> > +
> > +	return true;
> > +}
> > +
> > +/*
> > + * See the comment at the connect function. This implements the Disconnect
> > + * Flow.
> > + */
> > +void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> > +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> > +
> > +	if (dig_port->tc_type == TC_PORT_UNKNOWN)
> > +		return;
> > +
> > +	/*
> > +	 * TBT disconnection flow is read the live status, what was done in
> > +	 * caller.
> > +	 */
> > +	if (dig_port->tc_type == TC_PORT_TYPEC ||
> > +	    dig_port->tc_type == TC_PORT_LEGACY) {
> > +		u32 val;
> > +
> > +		val = I915_READ(PORT_TX_DFLEXDPCSSS);
> > +		val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> > +		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> > +	}
> > +
> > +	DRM_DEBUG_KMS("Port %c TC type %s disconnected\n",
> > +		      port_name(dig_port->base.port),
> > +		      tc_type_name(dig_port->tc_type));
> > +
> > +	dig_port->tc_type = TC_PORT_UNKNOWN;
> > +}
> > +
> > +static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
> > +				    struct intel_digital_port *intel_dig_port,
> > +				    bool is_legacy, bool is_typec, bool is_tbt)
> > +{
> > +	enum port port = intel_dig_port->base.port;
> > +	enum tc_port_type old_type = intel_dig_port->tc_type;
> > +
> > +	WARN_ON(is_legacy + is_typec + is_tbt != 1);
> > +
> > +	if (is_legacy)
> > +		intel_dig_port->tc_type = TC_PORT_LEGACY;
> > +	else if (is_typec)
> > +		intel_dig_port->tc_type = TC_PORT_TYPEC;
> > +	else if (is_tbt)
> > +		intel_dig_port->tc_type = TC_PORT_TBT;
> > +	else
> > +		return;
> > +
> > +	/* Types are not supposed to be changed at runtime. */
> > +	WARN_ON(old_type != TC_PORT_UNKNOWN &&
> > +		old_type != intel_dig_port->tc_type);
> > +
> > +	if (old_type != intel_dig_port->tc_type)
> > +		DRM_DEBUG_KMS("Port %c has TC type %s\n", port_name(port),
> > +			      tc_type_name(intel_dig_port->tc_type));
> > +}
> > +
> > +
> > +/*
> > + * The type-C ports are different because even when they are connected, they may
> > + * not be available/usable by the graphics driver: see the comment on
> > + * icl_tc_phy_connect(). So in our driver instead of adding the additional
> > + * concept of "usable" and make everything check for "connected and usable" we
> > + * define a port as "connected" when it is not only connected, but also when it
> > + * is usable by the rest of the driver. That maintains the old assumption that
> > + * connected ports are usable, and avoids exposing to the users objects they
> > + * can't really use.
> > + */
> > +bool intel_tc_port_connected(struct intel_digital_port *dig_port)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> > +	enum port port = dig_port->base.port;
> > +	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
> > +	bool is_legacy, is_typec, is_tbt;
> > +	u32 dpsp;
> > +
> > +	/*
> > +	 * Complain if we got a legacy port HPD, but VBT didn't mark the port as
> > +	 * legacy. Treat the port as legacy from now on.
> > +	 */
> > +	if (!dig_port->tc_legacy_port &&
> > +	    I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port)) {
> > +		DRM_ERROR("VBT incorrectly claims port %c is not TypeC legacy\n",
> > +			  port_name(port));
> > +		dig_port->tc_legacy_port = true;
> > +	}
> > +	is_legacy = dig_port->tc_legacy_port;
> > +
> > +	/*
> > +	 * The spec says we shouldn't be using the ISR bits for detecting
> > +	 * between TC and TBT. We should use DFLEXDPSP.
> > +	 */
> > +	dpsp = I915_READ(PORT_TX_DFLEXDPSP);
> > +	is_typec = dpsp & TC_LIVE_STATE_TC(tc_port);
> > +	is_tbt = dpsp & TC_LIVE_STATE_TBT(tc_port);
> > +
> > +	if (!is_legacy && !is_typec && !is_tbt) {
> > +		icl_tc_phy_disconnect(dig_port);
> > +
> > +		return false;
> > +	}
> > +
> > +	icl_update_tc_port_type(dev_priv, dig_port, is_legacy, is_typec,
> > +				is_tbt);
> > +
> > +	if (!icl_tc_phy_connect(dig_port))
> > +		return false;
> > +
> > +	return true;
> > +}
> > +
> > diff --git a/drivers/gpu/drm/i915/intel_tc.h b/drivers/gpu/drm/i915/intel_tc.h
> > new file mode 100644
> > index 000000000000..94c62ac4a162
> > --- /dev/null
> > +++ b/drivers/gpu/drm/i915/intel_tc.h
> > @@ -0,0 +1,13 @@
> 
> SPDX header here please.

Ok, added that like:
https://github.com/ideak/linux/blob/2dee09f687ba/drivers/gpu/drm/i915/intel_tc.h#L2

> 
> > +#ifndef __INTEL_TC_H__
> > +#define __INTEL_TC_H__
> > +
> > +#include <linux/types.h>
> > +
> > +struct intel_digital_port;
> > +
> > +void icl_tc_phy_disconnect(struct intel_digital_port *dig_port);
> 
> I'd like to see this named intel_tc_* in the future.

Yep, thought about that rule, which is good, but I kept this one
as-is, since later in this patchset it will get unexported.

> 
> BR,
> Jani.
> 
> 
> > +
> > +bool intel_tc_port_connected(struct intel_digital_port *dig_port);
> > +int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port);
> > +
> > +#endif /* __INTEL_TC_H__ */
> 
> -- 
> Jani Nikula, Intel Open Source Graphics Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 09/23] drm/i915: Factor out common parts from TypeC port handling functions
  2019-06-06  8:47   ` Jani Nikula
@ 2019-06-06  9:19     ` Imre Deak
  0 siblings, 0 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-06  9:19 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx, Paulo Zanoni

On Thu, Jun 06, 2019 at 11:47:20AM +0300, Jani Nikula wrote:
> On Tue, 04 Jun 2019, Imre Deak <imre.deak@intel.com> wrote:
> > Factor out helpers reading/parsing the TypeC specific registers, making
> > current users of them clearer and letting us use them later.
> >
> > While at it also:
> > - Simplify icl_tc_phy_connect() with an early return in legacy mode.
> > - Simplify the live status check using one bitmask for all HPD bits.
> > - Remove a micro-optimisation of the repeated safe-mode clearing.
> > - Make sure we fix the legacy port flag in all cases.
> >
> > Except for the last two, no functional changes.
> >
> > Cc: José Roberto de Souza <jose.souza@intel.com>
> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_ddi.c |   5 +-
> >  drivers/gpu/drm/i915/intel_tc.c  | 166 +++++++++++++++++++------------
> >  drivers/gpu/drm/i915/intel_tc.h  |   1 +
> >  3 files changed, 103 insertions(+), 69 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> > index 8f223d48d562..d236839bee19 100644
> > --- a/drivers/gpu/drm/i915/intel_ddi.c
> > +++ b/drivers/gpu/drm/i915/intel_ddi.c
> > @@ -2983,7 +2983,6 @@ static void icl_program_mg_dp_mode(struct intel_digital_port *intel_dig_port)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
> >  	enum port port = intel_dig_port->base.port;
> > -	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
> >  	u32 ln0, ln1, lane_info;
> >  
> >  	if (intel_dig_port->tc_mode == TC_PORT_TBT_ALT)
> > @@ -2997,9 +2996,7 @@ static void icl_program_mg_dp_mode(struct intel_digital_port *intel_dig_port)
> >  		ln0 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
> >  		ln1 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
> >  
> > -		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
> > -			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
> > -			    DP_LANE_ASSIGNMENT_SHIFT(tc_port);
> > +		lane_info = intel_tc_port_get_lane_info(intel_dig_port);
> >  
> >  		switch (lane_info) {
> >  		case 0x1:
> > diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
> > index 07488235b67a..3fdcfa2bbaee 100644
> > --- a/drivers/gpu/drm/i915/intel_tc.c
> > +++ b/drivers/gpu/drm/i915/intel_tc.c
> > @@ -43,10 +43,19 @@ static const char *tc_port_mode_name(enum tc_port_mode mode)
> >  	return names[mode];
> >  }
> >  
> > -int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
> > +u32 intel_tc_port_get_lane_info(struct intel_digital_port *dig_port)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> >  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> > +	u32 lane_info = I915_READ(PORT_TX_DFLEXDPSP);
> 
> Please don't do register reads in declarations. Ditto below.

Ok.

> 
> > +
> > +	return (lane_info & DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
> > +	       DP_LANE_ASSIGNMENT_SHIFT(tc_port);
> > +}
> > +
> > +int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> >  	intel_wakeref_t wakeref;
> >  	u32 lane_info;
> >  
> > @@ -55,9 +64,7 @@ int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
> >  
> >  	lane_info = 0;
> >  	with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref)
> > -		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
> > -			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
> > -				DP_LANE_ASSIGNMENT_SHIFT(tc_port);
> > +		lane_info = intel_tc_port_get_lane_info(dig_port);
> >  
> >  	switch (lane_info) {
> >  	default:
> > @@ -75,6 +82,69 @@ int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
> >  	}
> >  }
> >  
> > +static void tc_port_fixup_legacy_flag(struct intel_digital_port *dig_port,
> > +				      u32 live_status_mask)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> > +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> > +	u32 valid_hpd_mask = dig_port->tc_legacy_port ? BIT(TC_PORT_LEGACY) :
> > +							~BIT(TC_PORT_LEGACY);
> > +
> > +	if (!(live_status_mask & ~valid_hpd_mask))
> > +		return;
> > +
> > +	/* If live status mismatches the VBT flag, trust the live status. */
> > +	DRM_ERROR("Port %s: live status %08x mismatches the legacy port flag, fix flag\n",
> > +		  tc_port_name(dev_priv, tc_port), live_status_mask);
> > +
> > +	dig_port->tc_legacy_port = !dig_port->tc_legacy_port;
> > +}
> > +
> > +static u32 tc_port_live_status_mask(struct intel_digital_port *dig_port)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> > +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> > +	u32 val = I915_READ(PORT_TX_DFLEXDPSP);
> > +	u32 mask = 0;
> > +
> > +	if (val & TC_LIVE_STATE_TBT(tc_port))
> > +		mask |= BIT(TC_PORT_TBT_ALT);
> > +	if (val & TC_LIVE_STATE_TC(tc_port))
> > +		mask |= BIT(TC_PORT_DP_ALT);
> > +
> > +	if (I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port))
> > +		mask |= BIT(TC_PORT_LEGACY);
> > +
> > +	/* The sink can be connected only in a single mode. */
> > +	if (!WARN_ON(hweight32(mask) > 1))
> > +		tc_port_fixup_legacy_flag(dig_port, mask);
> > +
> > +	return mask;
> > +}
> > +
> > +static bool icl_tc_phy_status_complete(struct intel_digital_port *dig_port)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> > +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> > +
> > +	return I915_READ(PORT_TX_DFLEXDPPMS) &
> > +	       DP_PHY_MODE_STATUS_COMPLETED(tc_port);
> > +}
> > +
> > +static void icl_tc_phy_set_safe_mode(struct intel_digital_port *dig_port,
> > +				     bool enable)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> > +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> > +	u32 val = I915_READ(PORT_TX_DFLEXDPCSSS);
> > +
> > +	val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> > +	if (!enable)
> > +		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> > +
> > +	I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> > +}
> > +
> >  /*
> >   * This function implements the first part of the Connect Flow described by our
> >   * specification, Gen11 TypeC Programming chapter. The rest of the flow (reading
> > @@ -100,36 +170,31 @@ static bool icl_tc_phy_connect(struct intel_digital_port *dig_port)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> >  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> > -	u32 val;
> > +	u32 live_status_mask;
> >  
> >  	if (dig_port->tc_mode != TC_PORT_LEGACY &&
> >  	    dig_port->tc_mode != TC_PORT_DP_ALT)
> >  		return true;
> >  
> > -	val = I915_READ(PORT_TX_DFLEXDPPMS);
> > -	if (!(val & DP_PHY_MODE_STATUS_COMPLETED(tc_port))) {
> > +	if (!icl_tc_phy_status_complete(dig_port)) {
> >  		DRM_DEBUG_KMS("Port %s: PHY not ready\n",
> >  			      tc_port_name(dev_priv, tc_port));
> >  		WARN_ON(dig_port->tc_legacy_port);
> >  		return false;
> >  	}
> >  
> > -	/*
> > -	 * This function may be called many times in a row without an HPD event
> > -	 * in between, so try to avoid the write when we can.
> > -	 */
> > -	val = I915_READ(PORT_TX_DFLEXDPCSSS);
> > -	if (!(val & DP_PHY_MODE_STATUS_NOT_SAFE(tc_port))) {
> > -		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> > -		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> > -	}
> > +	icl_tc_phy_set_safe_mode(dig_port, false);
> > +
> > +	if (dig_port->tc_mode == TC_PORT_LEGACY)
> > +		return true;
> > +
> > +	live_status_mask = tc_port_live_status_mask(dig_port);
> >  
> >  	/*
> >  	 * Now we have to re-check the live state, in case the port recently
> >  	 * became disconnected. Not necessary for legacy mode.
> >  	 */
> > -	if (dig_port->tc_mode == TC_PORT_DP_ALT &&
> > -	    !(I915_READ(PORT_TX_DFLEXDPSP) & TC_LIVE_STATE_TC(tc_port))) {
> > +	if (!(live_status_mask & BIT(TC_PORT_DP_ALT))) {
> >  		DRM_DEBUG_KMS("Port %s: PHY sudden disconnect\n",
> >  			      tc_port_name(dev_priv, tc_port));
> >  		icl_tc_phy_disconnect(dig_port);
> > @@ -148,44 +213,36 @@ void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
> >  	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> >  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> >  
> > -	/*
> > -	 * TBT disconnection flow is read the live status, what was done in
> > -	 * caller.
> > -	 */
> > -	if (dig_port->tc_mode == TC_PORT_DP_ALT ||
> > -	    dig_port->tc_mode == TC_PORT_LEGACY) {
> > -		u32 val;
> > -
> > -		val = I915_READ(PORT_TX_DFLEXDPCSSS);
> > -		val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> > -		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> > +	switch (dig_port->tc_mode) {
> > +	case TC_PORT_LEGACY:
> > +	case TC_PORT_DP_ALT:
> > +		icl_tc_phy_set_safe_mode(dig_port, true);
> > +		dig_port->tc_mode = TC_PORT_TBT_ALT;
> > +		break;
> > +	case TC_PORT_TBT_ALT:
> > +		/* Nothing to do, we stay in TBT-alt mode */
> > +		break;
> > +	default:
> > +		MISSING_CASE(dig_port->tc_mode);
> >  	}
> >  
> >  	DRM_DEBUG_KMS("Port %s: mode %s disconnected\n",
> >  		      tc_port_name(dev_priv, tc_port),
> >  		      tc_port_mode_name(dig_port->tc_mode));
> > -
> > -	dig_port->tc_mode = TC_PORT_TBT_ALT;
> >  }
> >  
> >  static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
> >  				    struct intel_digital_port *intel_dig_port,
> > -				    bool is_legacy, bool is_typec, bool is_tbt)
> > +				    u32 live_status_mask)
> >  {
> >  	enum port port = intel_dig_port->base.port;
> >  	enum tc_port_mode old_mode = intel_dig_port->tc_mode;
> >  
> > -	WARN_ON(is_legacy + is_typec + is_tbt != 1);
> > -
> > -	if (is_legacy)
> > -		intel_dig_port->tc_mode = TC_PORT_LEGACY;
> > -	else if (is_typec)
> > -		intel_dig_port->tc_mode = TC_PORT_DP_ALT;
> > -	else if (is_tbt)
> > -		intel_dig_port->tc_mode = TC_PORT_TBT_ALT;
> > -	else
> > +	if (!live_status_mask)
> >  		return;
> >  
> > +	intel_dig_port->tc_mode = fls(live_status_mask) - 1;
> > +
> >  	if (old_mode != intel_dig_port->tc_mode)
> >  		DRM_DEBUG_KMS("Port %s: port has mode %s\n",
> >  			      tc_port_name(dev_priv,
> > @@ -207,40 +264,19 @@ static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
> >  bool intel_tc_port_connected(struct intel_digital_port *dig_port)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> > -	enum port port = dig_port->base.port;
> > -	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
> > -	bool is_legacy, is_typec, is_tbt;
> > -	u32 dpsp;
> > -
> > -	/*
> > -	 * Complain if we got a legacy port HPD, but VBT didn't mark the port as
> > -	 * legacy. Treat the port as legacy from now on.
> > -	 */
> > -	if (!dig_port->tc_legacy_port &&
> > -	    I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port)) {
> > -		DRM_ERROR("Port %s: VBT incorrectly claims port is not TypeC legacy\n",
> > -			  tc_port_name(dev_priv, tc_port));
> > -		dig_port->tc_legacy_port = true;
> > -	}
> > -	is_legacy = dig_port->tc_legacy_port;
> > +	u32 live_status_mask = tc_port_live_status_mask(dig_port);
> >  
> >  	/*
> >  	 * The spec says we shouldn't be using the ISR bits for detecting
> >  	 * between TC and TBT. We should use DFLEXDPSP.
> >  	 */
> > -	dpsp = I915_READ(PORT_TX_DFLEXDPSP);
> > -	is_typec = dpsp & TC_LIVE_STATE_TC(tc_port);
> > -	is_tbt = dpsp & TC_LIVE_STATE_TBT(tc_port);
> > -
> > -	if (!is_legacy && !is_typec && !is_tbt) {
> > +	if (!live_status_mask && !dig_port->tc_legacy_port) {
> >  		icl_tc_phy_disconnect(dig_port);
> >  
> >  		return false;
> >  	}
> >  
> > -	icl_update_tc_port_type(dev_priv, dig_port, is_legacy, is_typec,
> > -				is_tbt);
> > -
> > +	icl_update_tc_port_type(dev_priv, dig_port, live_status_mask);
> >  	if (!icl_tc_phy_connect(dig_port))
> >  		return false;
> >  
> > diff --git a/drivers/gpu/drm/i915/intel_tc.h b/drivers/gpu/drm/i915/intel_tc.h
> > index 94c62ac4a162..e937f5326959 100644
> > --- a/drivers/gpu/drm/i915/intel_tc.h
> > +++ b/drivers/gpu/drm/i915/intel_tc.h
> > @@ -8,6 +8,7 @@ struct intel_digital_port;
> >  void icl_tc_phy_disconnect(struct intel_digital_port *dig_port);
> >  
> >  bool intel_tc_port_connected(struct intel_digital_port *dig_port);
> > +u32 intel_tc_port_get_lane_info(struct intel_digital_port *dig_port);
> >  int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port);
> >  
> >  #endif /* __INTEL_TC_H__ */
> 
> -- 
> Jani Nikula, Intel Open Source Graphics Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 01/23] drm/i915/icl: Add support to read out the TBT PLL HW state
  2019-06-04 14:58 ` [PATCH 01/23] drm/i915/icl: Add support to read out the TBT PLL HW state Imre Deak
@ 2019-06-07 17:36   ` Souza, Jose
  0 siblings, 0 replies; 79+ messages in thread
From: Souza, Jose @ 2019-06-07 17:36 UTC (permalink / raw)
  To: intel-gfx, Deak, Imre; +Cc: De Marchi, Lucas, Zanoni, Paulo R

On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> Add support to read out the TBT PLL HW state.

Reviewed-by: José Roberto de Souza <jose.souza@intel.com>

> 
> Cc: Vandita Kulkarni <vandita.kulkarni@intel.com>
> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Cc: Lucas De Marchi <lucas.demarchi@intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 11 +++++++++--
>  1 file changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c
> b/drivers/gpu/drm/i915/intel_display.c
> index fc47ed0247c5..26474788b7b2 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -9859,13 +9859,20 @@ static void icelake_get_ddi_pll(struct
> drm_i915_private *dev_priv,
>  	enum intel_dpll_id id;
>  	u32 temp;
>  
> -	/* TODO: TBT pll not implemented. */
>  	if (intel_port_is_combophy(dev_priv, port)) {
>  		temp = I915_READ(DPCLKA_CFGCR0_ICL) &
>  		       DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
>  		id = temp >> DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port);
>  	} else if (intel_port_is_tc(dev_priv, port)) {
> -		id = icl_tc_port_to_pll_id(intel_port_to_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,
> +								    por
> t));
> +		} else {
> +			WARN_ON(clk_sel < DDI_CLK_SEL_TBT_162);
> +			id = DPLL_ID_ICL_TBTPLL;
> +		}
>  	} else {
>  		WARN(1, "Invalid port %x\n", port);
>  		return;
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [PATCH v2 19/23] drm/i915/icl: Reserve all required PLLs for TypeC ports
  2019-06-04 14:58 ` [PATCH 19/23] drm/i915/icl: Reserve all required PLLs for TypeC ports Imre Deak
@ 2019-06-07 17:41   ` Imre Deak
  2019-06-18 17:25     ` Ville Syrjälä
  0 siblings, 1 reply; 79+ messages in thread
From: Imre Deak @ 2019-06-07 17:41 UTC (permalink / raw)
  To: intel-gfx; +Cc: Daniel Vetter

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.

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>
---
 drivers/gpu/drm/i915/intel_display.c  |  11 +-
 drivers/gpu/drm/i915/intel_dpll_mgr.c | 151 +++++++++++++++++++-------
 drivers/gpu/drm/i915/intel_dpll_mgr.h |   9 ++
 drivers/gpu/drm/i915/intel_drv.h      |   9 ++
 4 files changed, 138 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 7381fb2e1240..006be3c3f1bd 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -9880,6 +9880,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;
 
@@ -9887,22 +9888,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,
@@ -12041,6 +12048,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/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
index 8ac293db43a5..17441d5f990e 100644
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/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 =
+		&crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT];
+	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);
+	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,24 @@ 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);
+	}
+}
+
 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 +3399,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 +3412,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/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h
index 6ffdcc06ad23..3bea81bde343 100644
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.h
+++ b/drivers/gpu/drm/i915/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 f9b6f63ebbfe..7f1dcb8d8a28 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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

* Re: [PATCH 02/23] drm/i915: Tune down WARNs about TBT AUX power well enabling
  2019-06-04 14:58 ` [PATCH 02/23] drm/i915: Tune down WARNs about TBT AUX power well enabling Imre Deak
@ 2019-06-07 17:50   ` Souza, Jose
  2019-06-08 13:33     ` Imre Deak
  0 siblings, 1 reply; 79+ messages in thread
From: Souza, Jose @ 2019-06-07 17:50 UTC (permalink / raw)
  To: intel-gfx, Deak, Imre

On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> The HW completion flag for the TBT AUX power well enabling/disabling
> gets stuck if the firmware tears down the TBT DP tunnel before the
> completion.
> 
> We shouldn't complain about the timeout, since it's expected to
> happen
> and doesn't cause further issues. We suppress the disabling timeout
> already, do the same for enabling.

This was documented in spec?

> 
> Cc: José Roberto de Souza <jose.souza@intel.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display_power.c | 15 ++++++++++-----
>  1 file changed, 10 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display_power.c
> b/drivers/gpu/drm/i915/intel_display_power.c
> index 278a7edc94f5..249a5fa55df6 100644
> --- a/drivers/gpu/drm/i915/intel_display_power.c
> +++ b/drivers/gpu/drm/i915/intel_display_power.c
> @@ -268,11 +268,16 @@ static void
> hsw_wait_for_power_well_enable(struct drm_i915_private *dev_priv,
>  	int pw_idx = power_well->desc->hsw.idx;
>  
>  	/* Timeout for PW1:10 us, AUX:not specified, other PWs:20 us.
> */
> -	WARN_ON(intel_wait_for_register(&dev_priv->uncore,
> -					regs->driver,
> -					HSW_PWR_WELL_CTL_STATE(pw_idx),
> -					HSW_PWR_WELL_CTL_STATE(pw_idx),
> -					1));
> +	if (intel_wait_for_register(&dev_priv->uncore,
> +				    regs->driver,
> +				    HSW_PWR_WELL_CTL_STATE(pw_idx),
> +				    HSW_PWR_WELL_CTL_STATE(pw_idx),
> +				    1)) {
> +		DRM_DEBUG_KMS("%s forced off\n", power_well->desc-
> >name);

Maybe "%s power well enable timeout"?
Anyways we can fix that latter.

Reviewed-by: José Roberto de Souza <jose.souza@intel.com>

> +
> +		/* An AUX timeout is expected if the TBT DP tunnel is
> down. */
> +		WARN_ON(!power_well->desc->hsw.is_tc_tbt);
> +	}
>  }
>  
>  static u32 hsw_power_well_requesters(struct drm_i915_private
> *dev_priv,
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 03/23] drm/i915: Move the TypeC port handling code to a separate file
  2019-06-04 14:58 ` [PATCH 03/23] drm/i915: Move the TypeC port handling code to a separate file Imre Deak
  2019-06-06  8:42   ` Jani Nikula
@ 2019-06-07 17:56   ` Souza, Jose
  1 sibling, 0 replies; 79+ messages in thread
From: Souza, Jose @ 2019-06-07 17:56 UTC (permalink / raw)
  To: intel-gfx, Deak, Imre; +Cc: Zanoni, Paulo R

On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> Move the TypeC port handling functions to a new file for clarity.
> 
> While at it:
> - s/icl_tc_port_connected()/intel_tc_port_connected()/
>   icl_tc_phy_disconnect(), will be unexported later.
> 
> -
> s/intel_dp_get_fia_supported_lane_count()/intel_tc_port_fia_max_lane_
> count()/
>   It's used for HDMI legacy mode too.
> 
> - Simplify function interfaces by passing only dig_port to them.
> 
> No functional changes.

Nice.

Reviewed-by: José Roberto de Souza <jose.souza@intel.com>

> 
> Cc: Animesh Manna <animesh.manna@intel.com>
> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Cc: José Roberto de Souza <jose.souza@intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/Makefile             |   3 +-
>  drivers/gpu/drm/i915/Makefile.header-test |   1 +
>  drivers/gpu/drm/i915/intel_ddi.c          |   6 +-
>  drivers/gpu/drm/i915/intel_dp.c           | 227 +-------------------
> -
>  drivers/gpu/drm/i915/intel_dp.h           |   2 -
>  drivers/gpu/drm/i915/intel_tc.c           | 230
> ++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_tc.h           |  13 ++
>  7 files changed, 252 insertions(+), 230 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/intel_tc.c
>  create mode 100644 drivers/gpu/drm/i915/intel_tc.h
> 
> diff --git a/drivers/gpu/drm/i915/Makefile
> b/drivers/gpu/drm/i915/Makefile
> index c0a7b2994077..74c4d11d83eb 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -171,7 +171,8 @@ i915-y += intel_audio.o \
>  	  intel_psr.o \
>  	  intel_quirks.o \
>  	  intel_sideband.o \
> -	  intel_sprite.o
> +	  intel_sprite.o \
> +	  intel_tc.o
>  i915-$(CONFIG_ACPI)		+= intel_acpi.o intel_opregion.o
>  i915-$(CONFIG_DRM_FBDEV_EMULATION)	+= intel_fbdev.o
>  
> diff --git a/drivers/gpu/drm/i915/Makefile.header-test
> b/drivers/gpu/drm/i915/Makefile.header-test
> index 6ef3b647ac65..e80e8e45b09c 100644
> --- a/drivers/gpu/drm/i915/Makefile.header-test
> +++ b/drivers/gpu/drm/i915/Makefile.header-test
> @@ -58,6 +58,7 @@ header_test := \
>  	intel_sdvo.h \
>  	intel_sideband.h \
>  	intel_sprite.h \
> +	intel_tc.h \
>  	intel_tv.h \
>  	intel_uncore.h \
>  	intel_vdsc.h \
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c
> b/drivers/gpu/drm/i915/intel_ddi.c
> index 350eaf54f01f..5a1c98438375 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -45,6 +45,7 @@
>  #include "intel_lspcon.h"
>  #include "intel_panel.h"
>  #include "intel_psr.h"
> +#include "intel_tc.h"
>  #include "intel_vdsc.h"
>  
>  struct ddi_buf_trans {
> @@ -3904,7 +3905,6 @@ static int intel_ddi_compute_config(struct
> intel_encoder *encoder,
>  static void intel_ddi_encoder_suspend(struct intel_encoder *encoder)
>  {
>  	struct intel_digital_port *dig_port = enc_to_dig_port(&encoder-
> >base);
> -	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
>  
>  	intel_dp_encoder_suspend(encoder);
>  
> @@ -3914,7 +3914,7 @@ static void intel_ddi_encoder_suspend(struct
> intel_encoder *encoder)
>  	 * even if the sink has disappeared while being suspended.
>  	 */
>  	if (dig_port->tc_legacy_port)
> -		icl_tc_phy_disconnect(i915, dig_port);
> +		icl_tc_phy_disconnect(dig_port);
>  }
>  
>  static void intel_ddi_encoder_reset(struct drm_encoder *drm_encoder)
> @@ -3936,7 +3936,7 @@ static void intel_ddi_encoder_destroy(struct
> drm_encoder *encoder)
>  	intel_dp_encoder_flush_work(encoder);
>  
>  	if (intel_port_is_tc(i915, dig_port->base.port))
> -		icl_tc_phy_disconnect(i915, dig_port);
> +		icl_tc_phy_disconnect(dig_port);
>  
>  	drm_encoder_cleanup(encoder);
>  	kfree(dig_port);
> diff --git a/drivers/gpu/drm/i915/intel_dp.c
> b/drivers/gpu/drm/i915/intel_dp.c
> index 24b56b2a76c8..b69310bd9914 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -62,6 +62,7 @@
>  #include "intel_panel.h"
>  #include "intel_psr.h"
>  #include "intel_sideband.h"
> +#include "intel_tc.h"
>  #include "intel_vdsc.h"
>  
>  #define DP_DPRX_ESI_LEN 14
> @@ -211,46 +212,13 @@ static int intel_dp_max_common_rate(struct
> intel_dp *intel_dp)
>  	return intel_dp->common_rates[intel_dp->num_common_rates - 1];
>  }
>  
> -static int intel_dp_get_fia_supported_lane_count(struct intel_dp
> *intel_dp)
> -{
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	struct drm_i915_private *dev_priv = to_i915(dig_port-
> >base.base.dev);
> -	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> >base.port);
> -	intel_wakeref_t wakeref;
> -	u32 lane_info;
> -
> -	if (tc_port == PORT_TC_NONE || dig_port->tc_type !=
> TC_PORT_TYPEC)
> -		return 4;
> -
> -	lane_info = 0;
> -	with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE,
> wakeref)
> -		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
> -			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
> -				DP_LANE_ASSIGNMENT_SHIFT(tc_port);
> -
> -	switch (lane_info) {
> -	default:
> -		MISSING_CASE(lane_info);
> -	case 1:
> -	case 2:
> -	case 4:
> -	case 8:
> -		return 1;
> -	case 3:
> -	case 12:
> -		return 2;
> -	case 15:
> -		return 4;
> -	}
> -}
> -
>  /* Theoretical max between source and sink */
>  static int intel_dp_max_common_lane_count(struct intel_dp *intel_dp)
>  {
>  	struct intel_digital_port *intel_dig_port =
> dp_to_dig_port(intel_dp);
>  	int source_max = intel_dig_port->max_lanes;
>  	int sink_max = drm_dp_max_lane_count(intel_dp->dpcd);
> -	int fia_max = intel_dp_get_fia_supported_lane_count(intel_dp);
> +	int fia_max = intel_tc_port_fia_max_lane_count(intel_dig_port);
>  
>  	return min3(source_max, sink_max, fia_max);
>  }
> @@ -5231,195 +5199,6 @@ static bool icl_combo_port_connected(struct
> drm_i915_private *dev_priv,
>  	return I915_READ(SDEISR) & SDE_DDI_HOTPLUG_ICP(port);
>  }
>  
> -static const char *tc_type_name(enum tc_port_type type)
> -{
> -	static const char * const names[] = {
> -		[TC_PORT_UNKNOWN] = "unknown",
> -		[TC_PORT_LEGACY] = "legacy",
> -		[TC_PORT_TYPEC] = "typec",
> -		[TC_PORT_TBT] = "tbt",
> -	};
> -
> -	if (WARN_ON(type >= ARRAY_SIZE(names)))
> -		type = TC_PORT_UNKNOWN;
> -
> -	return names[type];
> -}
> -
> -static void icl_update_tc_port_type(struct drm_i915_private
> *dev_priv,
> -				    struct intel_digital_port
> *intel_dig_port,
> -				    bool is_legacy, bool is_typec, bool
> is_tbt)
> -{
> -	enum port port = intel_dig_port->base.port;
> -	enum tc_port_type old_type = intel_dig_port->tc_type;
> -
> -	WARN_ON(is_legacy + is_typec + is_tbt != 1);
> -
> -	if (is_legacy)
> -		intel_dig_port->tc_type = TC_PORT_LEGACY;
> -	else if (is_typec)
> -		intel_dig_port->tc_type = TC_PORT_TYPEC;
> -	else if (is_tbt)
> -		intel_dig_port->tc_type = TC_PORT_TBT;
> -	else
> -		return;
> -
> -	/* Types are not supposed to be changed at runtime. */
> -	WARN_ON(old_type != TC_PORT_UNKNOWN &&
> -		old_type != intel_dig_port->tc_type);
> -
> -	if (old_type != intel_dig_port->tc_type)
> -		DRM_DEBUG_KMS("Port %c has TC type %s\n",
> port_name(port),
> -			      tc_type_name(intel_dig_port->tc_type));
> -}
> -
> -/*
> - * This function implements the first part of the Connect Flow
> described by our
> - * specification, Gen11 TypeC Programming chapter. The rest of the
> flow (reading
> - * lanes, EDID, etc) is done as needed in the typical places.
> - *
> - * Unlike the other ports, type-C ports are not available to use as
> soon as we
> - * get a hotplug. The type-C PHYs can be shared between multiple
> controllers:
> - * display, USB, etc. As a result, handshaking through FIA is
> required around
> - * connect and disconnect to cleanly transfer ownership with the
> controller and
> - * set the type-C power state.
> - *
> - * We could opt to only do the connect flow when we actually try to
> use the AUX
> - * channels or do a modeset, then immediately run the disconnect
> flow after
> - * usage, but there are some implications on this for a dynamic
> environment:
> - * things may go away or change behind our backs. So for now our
> driver is
> - * always trying to acquire ownership of the controller as soon as
> it gets an
> - * interrupt (or polls state and sees a port is connected) and only
> gives it
> - * back when it sees a disconnect. Implementation of a more fine-
> grained model
> - * will require a lot of coordination with user space and thorough
> testing for
> - * the extra possible cases.
> - */
> -static bool icl_tc_phy_connect(struct drm_i915_private *dev_priv,
> -			       struct intel_digital_port *dig_port)
> -{
> -	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> >base.port);
> -	u32 val;
> -
> -	if (dig_port->tc_type != TC_PORT_LEGACY &&
> -	    dig_port->tc_type != TC_PORT_TYPEC)
> -		return true;
> -
> -	val = I915_READ(PORT_TX_DFLEXDPPMS);
> -	if (!(val & DP_PHY_MODE_STATUS_COMPLETED(tc_port))) {
> -		DRM_DEBUG_KMS("DP PHY for TC port %d not ready\n",
> tc_port);
> -		WARN_ON(dig_port->tc_legacy_port);
> -		return false;
> -	}
> -
> -	/*
> -	 * This function may be called many times in a row without an
> HPD event
> -	 * in between, so try to avoid the write when we can.
> -	 */
> -	val = I915_READ(PORT_TX_DFLEXDPCSSS);
> -	if (!(val & DP_PHY_MODE_STATUS_NOT_SAFE(tc_port))) {
> -		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> -		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> -	}
> -
> -	/*
> -	 * Now we have to re-check the live state, in case the port
> recently
> -	 * became disconnected. Not necessary for legacy mode.
> -	 */
> -	if (dig_port->tc_type == TC_PORT_TYPEC &&
> -	    !(I915_READ(PORT_TX_DFLEXDPSP) &
> TC_LIVE_STATE_TC(tc_port))) {
> -		DRM_DEBUG_KMS("TC PHY %d sudden disconnect.\n",
> tc_port);
> -		icl_tc_phy_disconnect(dev_priv, dig_port);
> -		return false;
> -	}
> -
> -	return true;
> -}
> -
> -/*
> - * See the comment at the connect function. This implements the
> Disconnect
> - * Flow.
> - */
> -void icl_tc_phy_disconnect(struct drm_i915_private *dev_priv,
> -			   struct intel_digital_port *dig_port)
> -{
> -	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> >base.port);
> -
> -	if (dig_port->tc_type == TC_PORT_UNKNOWN)
> -		return;
> -
> -	/*
> -	 * TBT disconnection flow is read the live status, what was
> done in
> -	 * caller.
> -	 */
> -	if (dig_port->tc_type == TC_PORT_TYPEC ||
> -	    dig_port->tc_type == TC_PORT_LEGACY) {
> -		u32 val;
> -
> -		val = I915_READ(PORT_TX_DFLEXDPCSSS);
> -		val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> -		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> -	}
> -
> -	DRM_DEBUG_KMS("Port %c TC type %s disconnected\n",
> -		      port_name(dig_port->base.port),
> -		      tc_type_name(dig_port->tc_type));
> -
> -	dig_port->tc_type = TC_PORT_UNKNOWN;
> -}
> -
> -/*
> - * The type-C ports are different because even when they are
> connected, they may
> - * not be available/usable by the graphics driver: see the comment
> on
> - * icl_tc_phy_connect(). So in our driver instead of adding the
> additional
> - * concept of "usable" and make everything check for "connected and
> usable" we
> - * define a port as "connected" when it is not only connected, but
> also when it
> - * is usable by the rest of the driver. That maintains the old
> assumption that
> - * connected ports are usable, and avoids exposing to the users
> objects they
> - * can't really use.
> - */
> -static bool icl_tc_port_connected(struct drm_i915_private *dev_priv,
> -				  struct intel_digital_port
> *intel_dig_port)
> -{
> -	enum port port = intel_dig_port->base.port;
> -	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
> -	bool is_legacy, is_typec, is_tbt;
> -	u32 dpsp;
> -
> -	/*
> -	 * Complain if we got a legacy port HPD, but VBT didn't mark
> the port as
> -	 * legacy. Treat the port as legacy from now on.
> -	 */
> -	if (!intel_dig_port->tc_legacy_port &&
> -	    I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port)) {
> -		DRM_ERROR("VBT incorrectly claims port %c is not TypeC
> legacy\n",
> -			  port_name(port));
> -		intel_dig_port->tc_legacy_port = true;
> -	}
> -	is_legacy = intel_dig_port->tc_legacy_port;
> -
> -	/*
> -	 * The spec says we shouldn't be using the ISR bits for
> detecting
> -	 * between TC and TBT. We should use DFLEXDPSP.
> -	 */
> -	dpsp = I915_READ(PORT_TX_DFLEXDPSP);
> -	is_typec = dpsp & TC_LIVE_STATE_TC(tc_port);
> -	is_tbt = dpsp & TC_LIVE_STATE_TBT(tc_port);
> -
> -	if (!is_legacy && !is_typec && !is_tbt) {
> -		icl_tc_phy_disconnect(dev_priv, intel_dig_port);
> -
> -		return false;
> -	}
> -
> -	icl_update_tc_port_type(dev_priv, intel_dig_port, is_legacy,
> is_typec,
> -				is_tbt);
> -
> -	if (!icl_tc_phy_connect(dev_priv, intel_dig_port))
> -		return false;
> -
> -	return true;
> -}
> -
>  static bool icl_digital_port_connected(struct intel_encoder
> *encoder)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> @@ -5428,7 +5207,7 @@ static bool icl_digital_port_connected(struct
> intel_encoder *encoder)
>  	if (intel_port_is_combophy(dev_priv, encoder->port))
>  		return icl_combo_port_connected(dev_priv, dig_port);
>  	else if (intel_port_is_tc(dev_priv, encoder->port))
> -		return icl_tc_port_connected(dev_priv, dig_port);
> +		return intel_tc_port_connected(dig_port);
>  	else
>  		MISSING_CASE(encoder->hpd_pin);
>  
> diff --git a/drivers/gpu/drm/i915/intel_dp.h
> b/drivers/gpu/drm/i915/intel_dp.h
> index da70b1a41c83..657bbb1f5ed0 100644
> --- a/drivers/gpu/drm/i915/intel_dp.h
> +++ b/drivers/gpu/drm/i915/intel_dp.h
> @@ -112,8 +112,6 @@ bool intel_dp_get_colorimetry_status(struct
> intel_dp *intel_dp);
>  int intel_dp_link_required(int pixel_clock, int bpp);
>  int intel_dp_max_data_rate(int max_link_clock, int max_lanes);
>  bool intel_digital_port_connected(struct intel_encoder *encoder);
> -void icl_tc_phy_disconnect(struct drm_i915_private *dev_priv,
> -			   struct intel_digital_port *dig_port);
>  
>  static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
>  {
> diff --git a/drivers/gpu/drm/i915/intel_tc.c
> b/drivers/gpu/drm/i915/intel_tc.c
> new file mode 100644
> index 000000000000..7a1b5870945f
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/intel_tc.c
> @@ -0,0 +1,230 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2019 Intel Corporation
> + */
> +#include "intel_display.h"
> +#include "i915_drv.h"
> +#include "intel_tc.h"
> +
> +static const char *tc_type_name(enum tc_port_type type)
> +{
> +	static const char * const names[] = {
> +		[TC_PORT_UNKNOWN] = "unknown",
> +		[TC_PORT_LEGACY] = "legacy",
> +		[TC_PORT_TYPEC] = "typec",
> +		[TC_PORT_TBT] = "tbt",
> +	};
> +
> +	if (WARN_ON(type >= ARRAY_SIZE(names)))
> +		type = TC_PORT_UNKNOWN;
> +
> +	return names[type];
> +}
> +
> +int intel_tc_port_fia_max_lane_count(struct intel_digital_port
> *dig_port)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port-
> >base.base.dev);
> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> >base.port);
> +	intel_wakeref_t wakeref;
> +	u32 lane_info;
> +
> +	if (tc_port == PORT_TC_NONE || dig_port->tc_type !=
> TC_PORT_TYPEC)
> +		return 4;
> +
> +	lane_info = 0;
> +	with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE,
> wakeref)
> +		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
> +			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
> +				DP_LANE_ASSIGNMENT_SHIFT(tc_port);
> +
> +	switch (lane_info) {
> +	default:
> +		MISSING_CASE(lane_info);
> +	case 1:
> +	case 2:
> +	case 4:
> +	case 8:
> +		return 1;
> +	case 3:
> +	case 12:
> +		return 2;
> +	case 15:
> +		return 4;
> +	}
> +}
> +
> +/*
> + * This function implements the first part of the Connect Flow
> described by our
> + * specification, Gen11 TypeC Programming chapter. The rest of the
> flow (reading
> + * lanes, EDID, etc) is done as needed in the typical places.
> + *
> + * Unlike the other ports, type-C ports are not available to use as
> soon as we
> + * get a hotplug. The type-C PHYs can be shared between multiple
> controllers:
> + * display, USB, etc. As a result, handshaking through FIA is
> required around
> + * connect and disconnect to cleanly transfer ownership with the
> controller and
> + * set the type-C power state.
> + *
> + * We could opt to only do the connect flow when we actually try to
> use the AUX
> + * channels or do a modeset, then immediately run the disconnect
> flow after
> + * usage, but there are some implications on this for a dynamic
> environment:
> + * things may go away or change behind our backs. So for now our
> driver is
> + * always trying to acquire ownership of the controller as soon as
> it gets an
> + * interrupt (or polls state and sees a port is connected) and only
> gives it
> + * back when it sees a disconnect. Implementation of a more fine-
> grained model
> + * will require a lot of coordination with user space and thorough
> testing for
> + * the extra possible cases.
> + */
> +static bool icl_tc_phy_connect(struct intel_digital_port *dig_port)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port-
> >base.base.dev);
> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> >base.port);
> +	u32 val;
> +
> +	if (dig_port->tc_type != TC_PORT_LEGACY &&
> +	    dig_port->tc_type != TC_PORT_TYPEC)
> +		return true;
> +
> +	val = I915_READ(PORT_TX_DFLEXDPPMS);
> +	if (!(val & DP_PHY_MODE_STATUS_COMPLETED(tc_port))) {
> +		DRM_DEBUG_KMS("DP PHY for TC port %d not ready\n",
> tc_port);
> +		WARN_ON(dig_port->tc_legacy_port);
> +		return false;
> +	}
> +
> +	/*
> +	 * This function may be called many times in a row without an
> HPD event
> +	 * in between, so try to avoid the write when we can.
> +	 */
> +	val = I915_READ(PORT_TX_DFLEXDPCSSS);
> +	if (!(val & DP_PHY_MODE_STATUS_NOT_SAFE(tc_port))) {
> +		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> +		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> +	}
> +
> +	/*
> +	 * Now we have to re-check the live state, in case the port
> recently
> +	 * became disconnected. Not necessary for legacy mode.
> +	 */
> +	if (dig_port->tc_type == TC_PORT_TYPEC &&
> +	    !(I915_READ(PORT_TX_DFLEXDPSP) &
> TC_LIVE_STATE_TC(tc_port))) {
> +		DRM_DEBUG_KMS("TC PHY %d sudden disconnect.\n",
> tc_port);
> +		icl_tc_phy_disconnect(dig_port);
> +		return false;
> +	}
> +
> +	return true;
> +}
> +
> +/*
> + * See the comment at the connect function. This implements the
> Disconnect
> + * Flow.
> + */
> +void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port-
> >base.base.dev);
> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> >base.port);
> +
> +	if (dig_port->tc_type == TC_PORT_UNKNOWN)
> +		return;
> +
> +	/*
> +	 * TBT disconnection flow is read the live status, what was
> done in
> +	 * caller.
> +	 */
> +	if (dig_port->tc_type == TC_PORT_TYPEC ||
> +	    dig_port->tc_type == TC_PORT_LEGACY) {
> +		u32 val;
> +
> +		val = I915_READ(PORT_TX_DFLEXDPCSSS);
> +		val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> +		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> +	}
> +
> +	DRM_DEBUG_KMS("Port %c TC type %s disconnected\n",
> +		      port_name(dig_port->base.port),
> +		      tc_type_name(dig_port->tc_type));
> +
> +	dig_port->tc_type = TC_PORT_UNKNOWN;
> +}
> +
> +static void icl_update_tc_port_type(struct drm_i915_private
> *dev_priv,
> +				    struct intel_digital_port
> *intel_dig_port,
> +				    bool is_legacy, bool is_typec, bool
> is_tbt)
> +{
> +	enum port port = intel_dig_port->base.port;
> +	enum tc_port_type old_type = intel_dig_port->tc_type;
> +
> +	WARN_ON(is_legacy + is_typec + is_tbt != 1);
> +
> +	if (is_legacy)
> +		intel_dig_port->tc_type = TC_PORT_LEGACY;
> +	else if (is_typec)
> +		intel_dig_port->tc_type = TC_PORT_TYPEC;
> +	else if (is_tbt)
> +		intel_dig_port->tc_type = TC_PORT_TBT;
> +	else
> +		return;
> +
> +	/* Types are not supposed to be changed at runtime. */
> +	WARN_ON(old_type != TC_PORT_UNKNOWN &&
> +		old_type != intel_dig_port->tc_type);
> +
> +	if (old_type != intel_dig_port->tc_type)
> +		DRM_DEBUG_KMS("Port %c has TC type %s\n",
> port_name(port),
> +			      tc_type_name(intel_dig_port->tc_type));
> +}
> +
> +
> +/*
> + * The type-C ports are different because even when they are
> connected, they may
> + * not be available/usable by the graphics driver: see the comment
> on
> + * icl_tc_phy_connect(). So in our driver instead of adding the
> additional
> + * concept of "usable" and make everything check for "connected and
> usable" we
> + * define a port as "connected" when it is not only connected, but
> also when it
> + * is usable by the rest of the driver. That maintains the old
> assumption that
> + * connected ports are usable, and avoids exposing to the users
> objects they
> + * can't really use.
> + */
> +bool intel_tc_port_connected(struct intel_digital_port *dig_port)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port-
> >base.base.dev);
> +	enum port port = dig_port->base.port;
> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
> +	bool is_legacy, is_typec, is_tbt;
> +	u32 dpsp;
> +
> +	/*
> +	 * Complain if we got a legacy port HPD, but VBT didn't mark
> the port as
> +	 * legacy. Treat the port as legacy from now on.
> +	 */
> +	if (!dig_port->tc_legacy_port &&
> +	    I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port)) {
> +		DRM_ERROR("VBT incorrectly claims port %c is not TypeC
> legacy\n",
> +			  port_name(port));
> +		dig_port->tc_legacy_port = true;
> +	}
> +	is_legacy = dig_port->tc_legacy_port;
> +
> +	/*
> +	 * The spec says we shouldn't be using the ISR bits for
> detecting
> +	 * between TC and TBT. We should use DFLEXDPSP.
> +	 */
> +	dpsp = I915_READ(PORT_TX_DFLEXDPSP);
> +	is_typec = dpsp & TC_LIVE_STATE_TC(tc_port);
> +	is_tbt = dpsp & TC_LIVE_STATE_TBT(tc_port);
> +
> +	if (!is_legacy && !is_typec && !is_tbt) {
> +		icl_tc_phy_disconnect(dig_port);
> +
> +		return false;
> +	}
> +
> +	icl_update_tc_port_type(dev_priv, dig_port, is_legacy,
> is_typec,
> +				is_tbt);
> +
> +	if (!icl_tc_phy_connect(dig_port))
> +		return false;
> +
> +	return true;
> +}
> +
> diff --git a/drivers/gpu/drm/i915/intel_tc.h
> b/drivers/gpu/drm/i915/intel_tc.h
> new file mode 100644
> index 000000000000..94c62ac4a162
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/intel_tc.h
> @@ -0,0 +1,13 @@
> +#ifndef __INTEL_TC_H__
> +#define __INTEL_TC_H__
> +
> +#include <linux/types.h>
> +
> +struct intel_digital_port;
> +
> +void icl_tc_phy_disconnect(struct intel_digital_port *dig_port);
> +
> +bool intel_tc_port_connected(struct intel_digital_port *dig_port);
> +int intel_tc_port_fia_max_lane_count(struct intel_digital_port
> *dig_port);
> +
> +#endif /* __INTEL_TC_H__ */
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Fix TypeC port mode switching (rev2)
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (26 preceding siblings ...)
  2019-06-05 16:36 ` ✓ Fi.CI.IGT: " Patchwork
@ 2019-06-07 17:59 ` Patchwork
  2019-06-07 18:07 ` ✗ Fi.CI.SPARSE: " Patchwork
                   ` (2 subsequent siblings)
  30 siblings, 0 replies; 79+ messages in thread
From: Patchwork @ 2019-06-07 17:59 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Fix TypeC port mode switching (rev2)
URL   : https://patchwork.freedesktop.org/series/61590/
State : warning

== Summary ==

$ dim checkpatch origin/drm-tip
429dfd1e1b32 drm/i915/icl: Add support to read out the TBT PLL HW state
8ceef23351d2 drm/i915: Tune down WARNs about TBT AUX power well enabling
44c9b3647fd4 drm/i915: Move the TypeC port handling code to a separate file
-:16: WARNING:COMMIT_LOG_LONG_LINE: Possible unwrapped commit description (prefer a maximum 75 chars per line)
#16: 
- s/intel_dp_get_fia_supported_lane_count()/intel_tc_port_fia_max_lane_count()/

-:372: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#372: 
new file mode 100644

-:553: CHECK:LINE_SPACING: Please don't use multiple blank lines
#553: FILE: drivers/gpu/drm/i915/intel_tc.c:177:
+
+

-:613: WARNING:SPDX_LICENSE_TAG: Missing or malformed SPDX-License-Identifier tag in line 1
#613: FILE: drivers/gpu/drm/i915/intel_tc.h:1:
+#ifndef __INTEL_TC_H__

total: 0 errors, 3 warnings, 1 checks, 554 lines checked
b9b7113c4067 drm/i915: Sanitize the terminology used for TypeC port modes
23b0fde5d329 drm/i915: Don't enable the DDI-IO power in the TypeC TBT-alt mode
8a0532a98f99 drm/i915: Fix the TBT AUX power well enabling
28ab588e258d drm/i915: Use the correct AUX power domain in TypeC TBT-alt mode
378d871080dc drm/i915: Unify the TypeC port notation in debug/error messages
-:38: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#38: FILE: drivers/gpu/drm/i915/intel_tc.c:21:
+	if (WARN_ON(INTEL_GEN(dev_priv) < 11 ||
+	    (unsigned int)tc_port >= I915_MAX_TC_PORTS))

total: 0 errors, 0 warnings, 1 checks, 77 lines checked
54ac7475d3aa drm/i915: Factor out common parts from TypeC port handling functions
1f8594a207f9 drm/i915: Wait for TypeC PHY complete flag to clear in safe mode
928ee9c6465d drm/i915: Handle the TCCOLD power-down event
1bff7d4d3fc4 drm/i915: Sanitize the TypeC connect/detect sequences
04156e7cf332 drm/i915: Fix the TypeC port mode sanitization during loading/resume
fd3f8157be20 drm/i915: Keep the TypeC port mode fixed for detect/AUX transfers
-:88: CHECK:UNCOMMENTED_DEFINITION: struct mutex definition without comment
#88: FILE: drivers/gpu/drm/i915/intel_drv.h:1227:
+	struct mutex tc_lock;

total: 0 errors, 0 warnings, 1 checks, 116 lines checked
e967e51d9a88 drm/i915: Sanitize the TypeC FIA lane configuration decoding
a98e18237ea4 drm/i915: Sanitize the shared DPLL reserve/release interface
-:527: WARNING:TYPO_SPELLING: 'succesfully' may be misspelled - perhaps 'successfully'?
#527: FILE: drivers/gpu/drm/i915/intel_dpll_mgr.c:3349:
+ * True if all required DPLLs were succesfully reserved.

total: 0 errors, 1 warnings, 0 checks, 542 lines checked
dbead30653b4 drm/i915: Sanitize the shared DPLL find/reference interface
406a41584fe0 drm/i915/icl: Split getting the DPLLs to port type specific functions
54d3b6ccdf51 drm/i915/icl: Reserve all required PLLs for TypeC ports
74d8ead2747d drm/i915: Keep the TypeC port mode fixed when the port is active
e8c117e05e35 drm/i915: Add state verification for the TypeC port mode
5294dc95eff6 drm/i915: Remove unneeded disconnect in TypeC legacy port mode
e8990683c8c6 drm/i915: WARN about invalid lane reversal in TBT-alt/DP-alt modes

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

^ permalink raw reply	[flat|nested] 79+ messages in thread

* ✗ Fi.CI.SPARSE: warning for drm/i915: Fix TypeC port mode switching (rev2)
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (27 preceding siblings ...)
  2019-06-07 17:59 ` ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Fix TypeC port mode switching (rev2) Patchwork
@ 2019-06-07 18:07 ` Patchwork
  2019-06-07 18:34 ` ✓ Fi.CI.BAT: success " Patchwork
  2019-06-10 12:34 ` ✓ Fi.CI.IGT: " Patchwork
  30 siblings, 0 replies; 79+ messages in thread
From: Patchwork @ 2019-06-07 18:07 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Fix TypeC port mode switching (rev2)
URL   : https://patchwork.freedesktop.org/series/61590/
State : warning

== Summary ==

$ dim sparse origin/drm-tip
Sparse version: v0.5.2
Commit: drm/i915/icl: Add support to read out the TBT PLL HW state
Okay!

Commit: drm/i915: Tune down WARNs about TBT AUX power well enabling
Okay!

Commit: drm/i915: Move the TypeC port handling code to a separate file
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
-O:drivers/gpu/drm/i915/intel_dp.c:255:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/intel_dp.c:223:16: warning: expression using sizeof(void)
+./include/uapi/linux/perf_event.h:147:56: warning: cast truncates bits from constant value (8000000000000000 becomes 0)

Commit: drm/i915: Sanitize the terminology used for TypeC port modes
Okay!

Commit: drm/i915: Don't enable the DDI-IO power in the TypeC TBT-alt mode
Okay!

Commit: drm/i915: Fix the TBT AUX power well enabling
Okay!

Commit: drm/i915: Use the correct AUX power domain in TypeC TBT-alt mode
Okay!

Commit: drm/i915: Unify the TypeC port notation in debug/error messages
Okay!

Commit: drm/i915: Factor out common parts from TypeC port handling functions
Okay!

Commit: drm/i915: Wait for TypeC PHY complete flag to clear in safe mode
Okay!

Commit: drm/i915: Handle the TCCOLD power-down event
Okay!

Commit: drm/i915: Sanitize the TypeC connect/detect sequences
Okay!

Commit: drm/i915: Fix the TypeC port mode sanitization during loading/resume
+./include/uapi/linux/perf_event.h:147:56: warning: cast truncates bits from constant value (8000000000000000 becomes 0)

Commit: drm/i915: Keep the TypeC port mode fixed for detect/AUX transfers
Okay!

Commit: drm/i915: Sanitize the TypeC FIA lane configuration decoding
Okay!

Commit: drm/i915: Sanitize the shared DPLL reserve/release interface
Okay!

Commit: drm/i915: Sanitize the shared DPLL find/reference interface
Okay!

Commit: drm/i915/icl: Split getting the DPLLs to port type specific functions
Okay!

Commit: drm/i915/icl: Reserve all required PLLs for TypeC ports
Okay!

Commit: drm/i915: Keep the TypeC port mode fixed when the port is active
Okay!

Commit: drm/i915: Add state verification for the TypeC port mode
+./include/uapi/linux/perf_event.h:147:56: warning: cast truncates bits from constant value (8000000000000000 becomes 0)

Commit: drm/i915: Remove unneeded disconnect in TypeC legacy port mode
Okay!

Commit: drm/i915: WARN about invalid lane reversal in TBT-alt/DP-alt modes
Okay!

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

^ permalink raw reply	[flat|nested] 79+ messages in thread

* ✓ Fi.CI.BAT: success for drm/i915: Fix TypeC port mode switching (rev2)
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (28 preceding siblings ...)
  2019-06-07 18:07 ` ✗ Fi.CI.SPARSE: " Patchwork
@ 2019-06-07 18:34 ` Patchwork
  2019-06-10 12:34 ` ✓ Fi.CI.IGT: " Patchwork
  30 siblings, 0 replies; 79+ messages in thread
From: Patchwork @ 2019-06-07 18:34 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Fix TypeC port mode switching (rev2)
URL   : https://patchwork.freedesktop.org/series/61590/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_6221 -> Patchwork_13209
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/

Known issues
------------

  Here are the changes found in Patchwork_13209 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_exec_suspend@basic-s3:
    - fi-icl-u3:          [PASS][1] -> [DMESG-WARN][2] ([fdo#107724]) +1 similar issue
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/fi-icl-u3/igt@gem_exec_suspend@basic-s3.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/fi-icl-u3/igt@gem_exec_suspend@basic-s3.html
    - fi-icl-dsi:         [PASS][3] -> [INCOMPLETE][4] ([fdo#107713])
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/fi-icl-dsi/igt@gem_exec_suspend@basic-s3.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/fi-icl-dsi/igt@gem_exec_suspend@basic-s3.html

  * igt@kms_chamelium@dp-crc-fast:
    - fi-cml-u2:          [PASS][5] -> [FAIL][6] ([fdo#110627])
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/fi-cml-u2/igt@kms_chamelium@dp-crc-fast.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/fi-cml-u2/igt@kms_chamelium@dp-crc-fast.html

  
#### Possible fixes ####

  * igt@gem_ctx_switch@basic-default:
    - {fi-icl-guc}:       [INCOMPLETE][7] ([fdo#107713] / [fdo#108569]) -> [PASS][8]
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/fi-icl-guc/igt@gem_ctx_switch@basic-default.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/fi-icl-guc/igt@gem_ctx_switch@basic-default.html

  * igt@kms_cursor_legacy@basic-flip-before-cursor-varying-size:
    - fi-icl-u3:          [DMESG-WARN][9] ([fdo#107724]) -> [PASS][10] +1 similar issue
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/fi-icl-u3/igt@kms_cursor_legacy@basic-flip-before-cursor-varying-size.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/fi-icl-u3/igt@kms_cursor_legacy@basic-flip-before-cursor-varying-size.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#107713]: https://bugs.freedesktop.org/show_bug.cgi?id=107713
  [fdo#107724]: https://bugs.freedesktop.org/show_bug.cgi?id=107724
  [fdo#108569]: https://bugs.freedesktop.org/show_bug.cgi?id=108569
  [fdo#110627]: https://bugs.freedesktop.org/show_bug.cgi?id=110627


Participating hosts (54 -> 39)
------------------------------

  Missing    (15): fi-ilk-m540 fi-skl-gvtdvm fi-hsw-4200u fi-bdw-gvtdvm fi-byt-squawks fi-icl-u2 fi-bwr-2160 fi-ilk-650 fi-kbl-7500u fi-bsw-cyan fi-kbl-guc fi-skl-lmem fi-kbl-7560u fi-byt-clapper fi-bdw-samus 


Build changes
-------------

  * Linux: CI_DRM_6221 -> Patchwork_13209

  CI_DRM_6221: 3f71d971d89a60348dbb11c40459aeb9d69c18f9 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_5048: 1a34b94f1ce07ac5978fe7893a17e8732d467868 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  Patchwork_13209: e8990683c8c6a9ebc1026ae3f272e8b87f4f5f5c @ git://anongit.freedesktop.org/gfx-ci/linux


== Linux commits ==

e8990683c8c6 drm/i915: WARN about invalid lane reversal in TBT-alt/DP-alt modes
5294dc95eff6 drm/i915: Remove unneeded disconnect in TypeC legacy port mode
e8c117e05e35 drm/i915: Add state verification for the TypeC port mode
74d8ead2747d drm/i915: Keep the TypeC port mode fixed when the port is active
54d3b6ccdf51 drm/i915/icl: Reserve all required PLLs for TypeC ports
406a41584fe0 drm/i915/icl: Split getting the DPLLs to port type specific functions
dbead30653b4 drm/i915: Sanitize the shared DPLL find/reference interface
a98e18237ea4 drm/i915: Sanitize the shared DPLL reserve/release interface
e967e51d9a88 drm/i915: Sanitize the TypeC FIA lane configuration decoding
fd3f8157be20 drm/i915: Keep the TypeC port mode fixed for detect/AUX transfers
04156e7cf332 drm/i915: Fix the TypeC port mode sanitization during loading/resume
1bff7d4d3fc4 drm/i915: Sanitize the TypeC connect/detect sequences
928ee9c6465d drm/i915: Handle the TCCOLD power-down event
1f8594a207f9 drm/i915: Wait for TypeC PHY complete flag to clear in safe mode
54ac7475d3aa drm/i915: Factor out common parts from TypeC port handling functions
378d871080dc drm/i915: Unify the TypeC port notation in debug/error messages
28ab588e258d drm/i915: Use the correct AUX power domain in TypeC TBT-alt mode
8a0532a98f99 drm/i915: Fix the TBT AUX power well enabling
23b0fde5d329 drm/i915: Don't enable the DDI-IO power in the TypeC TBT-alt mode
b9b7113c4067 drm/i915: Sanitize the terminology used for TypeC port modes
44c9b3647fd4 drm/i915: Move the TypeC port handling code to a separate file
8ceef23351d2 drm/i915: Tune down WARNs about TBT AUX power well enabling
429dfd1e1b32 drm/i915/icl: Add support to read out the TBT PLL HW state

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 04/23] drm/i915: Sanitize the terminology used for TypeC port modes
  2019-06-04 14:58 ` [PATCH 04/23] drm/i915: Sanitize the terminology used for TypeC port modes Imre Deak
@ 2019-06-07 19:15   ` Souza, Jose
  2019-06-08 13:43     ` Imre Deak
  2019-06-10 23:21   ` Lucas De Marchi
  1 sibling, 1 reply; 79+ messages in thread
From: Souza, Jose @ 2019-06-07 19:15 UTC (permalink / raw)
  To: intel-gfx, Deak, Imre; +Cc: Zanoni, Paulo R

On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> 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.

There is, the default tc_mode value now is TC_PORT_TBT_ALT instead of
TC_PORT_UNKNOWN.

With the change above:
Reviewed-by: José Roberto de Souza <
jose.souza@intel.com>

Also consider split this patch in two.


> 
> Cc: Animesh Manna <animesh.manna@intel.com>
> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Cc: Anusha Srivatsa <anusha.srivatsa@intel.com>
> Cc: José Roberto de Souza <jose.souza@intel.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_ddi.c      | 11 +++---
>  drivers/gpu/drm/i915/intel_display.h  |  7 ++--
>  drivers/gpu/drm/i915/intel_dp.c       |  2 +-
>  drivers/gpu/drm/i915/intel_dpll_mgr.c |  2 +-
>  drivers/gpu/drm/i915/intel_drv.h      |  2 +-
>  drivers/gpu/drm/i915/intel_tc.c       | 48 +++++++++++------------
> ----
>  6 files changed, 31 insertions(+), 41 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c
> b/drivers/gpu/drm/i915/intel_ddi.c
> index 5a1c98438375..a3574f14a3d0 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -2986,14 +2986,14 @@ static void icl_program_mg_dp_mode(struct
> intel_digital_port *intel_dig_port)
>  	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
>  	u32 ln0, ln1, lane_info;
>  
> -	if (tc_port == PORT_TC_NONE || intel_dig_port->tc_type ==
> TC_PORT_TBT)
> +	if (intel_dig_port->tc_mode == TC_PORT_TBT_ALT)
>  		return;
>  
>  	ln0 = I915_READ(MG_DP_MODE(0, port));
>  	ln1 = I915_READ(MG_DP_MODE(1, port));
>  
> -	switch (intel_dig_port->tc_type) {
> -	case TC_PORT_TYPEC:
> +	switch (intel_dig_port->tc_mode) {
> +	case TC_PORT_DP_ALT:
>  		ln0 &= ~(MG_DP_MODE_CFG_DP_X1_MODE |
> MG_DP_MODE_CFG_DP_X2_MODE);
>  		ln1 &= ~(MG_DP_MODE_CFG_DP_X1_MODE |
> MG_DP_MODE_CFG_DP_X2_MODE);
>  
> @@ -3036,7 +3036,7 @@ static void icl_program_mg_dp_mode(struct
> intel_digital_port *intel_dig_port)
>  		break;
>  
>  	default:
> -		MISSING_CASE(intel_dig_port->tc_type);
> +		MISSING_CASE(intel_dig_port->tc_mode);
>  		return;
>  	}
>  
> @@ -3630,8 +3630,7 @@ intel_ddi_pre_pll_enable(struct intel_encoder
> *encoder,
>  	 * Program the lane count for static/dynamic connections on
> Type-C ports.
>  	 * Skip this step for TBT.
>  	 */
> -	if (dig_port->tc_type == TC_PORT_UNKNOWN ||
> -	    dig_port->tc_type == TC_PORT_TBT)
> +	if (dig_port->tc_mode == TC_PORT_TBT_ALT)
>  		return;
>  
>  	intel_ddi_set_fia_lane_count(encoder, crtc_state, port);
> diff --git a/drivers/gpu/drm/i915/intel_display.h
> b/drivers/gpu/drm/i915/intel_display.h
> index ee6b8194a459..d296556ed82e 100644
> --- a/drivers/gpu/drm/i915/intel_display.h
> +++ b/drivers/gpu/drm/i915/intel_display.h
> @@ -189,10 +189,9 @@ enum tc_port {
>  	I915_MAX_TC_PORTS
>  };
>  
> -enum tc_port_type {
> -	TC_PORT_UNKNOWN = 0,
> -	TC_PORT_TYPEC,
> -	TC_PORT_TBT,
> +enum tc_port_mode {
> +	TC_PORT_TBT_ALT,
> +	TC_PORT_DP_ALT,
>  	TC_PORT_LEGACY,
>  };
>  
> diff --git a/drivers/gpu/drm/i915/intel_dp.c
> b/drivers/gpu/drm/i915/intel_dp.c
> index b69310bd9914..e1e27662aa6d 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1175,7 +1175,7 @@ static u32 skl_get_aux_send_ctl(struct intel_dp
> *intel_dp,
>  	      DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(32) |
>  	      DP_AUX_CH_CTL_SYNC_PULSE_SKL(32);
>  
> -	if (intel_dig_port->tc_type == TC_PORT_TBT)
> +	if (intel_dig_port->tc_mode == TC_PORT_TBT_ALT)
>  		ret |= DP_AUX_CH_CTL_TBT_IO;
>  
>  	return ret;
> diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c
> b/drivers/gpu/drm/i915/intel_dpll_mgr.c
> index 69787f259677..f4787650a0d3 100644
> --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
> +++ b/drivers/gpu/drm/i915/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);
> diff --git a/drivers/gpu/drm/i915/intel_drv.h
> b/drivers/gpu/drm/i915/intel_drv.h
> index 0dcc03592d6e..30cd49dbd0d8 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1225,7 +1225,7 @@ struct intel_digital_port {
>  	enum aux_ch aux_ch;
>  	enum intel_display_power_domain ddi_io_power_domain;
>  	bool tc_legacy_port:1;
> -	enum tc_port_type tc_type;
> +	enum tc_port_mode tc_mode;
>  
>  	void (*write_infoframe)(struct intel_encoder *encoder,
>  				const struct intel_crtc_state
> *crtc_state,
> diff --git a/drivers/gpu/drm/i915/intel_tc.c
> b/drivers/gpu/drm/i915/intel_tc.c
> index 7a1b5870945f..a3057c44bec6 100644
> --- a/drivers/gpu/drm/i915/intel_tc.c
> +++ b/drivers/gpu/drm/i915/intel_tc.c
> @@ -6,19 +6,18 @@
>  #include "i915_drv.h"
>  #include "intel_tc.h"
>  
> -static const char *tc_type_name(enum tc_port_type type)
> +static const char *tc_port_mode_name(enum tc_port_mode mode)
>  {
>  	static const char * const names[] = {
> -		[TC_PORT_UNKNOWN] = "unknown",
> +		[TC_PORT_TBT_ALT] = "tbt-alt",
> +		[TC_PORT_DP_ALT] = "dp-alt",
>  		[TC_PORT_LEGACY] = "legacy",
> -		[TC_PORT_TYPEC] = "typec",
> -		[TC_PORT_TBT] = "tbt",
>  	};
>  
> -	if (WARN_ON(type >= ARRAY_SIZE(names)))
> -		type = TC_PORT_UNKNOWN;
> +	if (WARN_ON(mode >= ARRAY_SIZE(names)))
> +		mode = TC_PORT_TBT_ALT;
>  
> -	return names[type];
> +	return names[mode];
>  }
>  
>  int intel_tc_port_fia_max_lane_count(struct intel_digital_port
> *dig_port)
> @@ -28,7 +27,7 @@ int intel_tc_port_fia_max_lane_count(struct
> intel_digital_port *dig_port)
>  	intel_wakeref_t wakeref;
>  	u32 lane_info;
>  
> -	if (tc_port == PORT_TC_NONE || dig_port->tc_type !=
> TC_PORT_TYPEC)
> +	if (dig_port->tc_mode != TC_PORT_DP_ALT)
>  		return 4;
>  
>  	lane_info = 0;
> @@ -80,8 +79,8 @@ static bool icl_tc_phy_connect(struct
> intel_digital_port *dig_port)
>  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> >base.port);
>  	u32 val;
>  
> -	if (dig_port->tc_type != TC_PORT_LEGACY &&
> -	    dig_port->tc_type != TC_PORT_TYPEC)
> +	if (dig_port->tc_mode != TC_PORT_LEGACY &&
> +	    dig_port->tc_mode != TC_PORT_DP_ALT)
>  		return true;
>  
>  	val = I915_READ(PORT_TX_DFLEXDPPMS);
> @@ -105,7 +104,7 @@ static bool icl_tc_phy_connect(struct
> intel_digital_port *dig_port)
>  	 * Now we have to re-check the live state, in case the port
> recently
>  	 * became disconnected. Not necessary for legacy mode.
>  	 */
> -	if (dig_port->tc_type == TC_PORT_TYPEC &&
> +	if (dig_port->tc_mode == TC_PORT_DP_ALT &&
>  	    !(I915_READ(PORT_TX_DFLEXDPSP) &
> TC_LIVE_STATE_TC(tc_port))) {
>  		DRM_DEBUG_KMS("TC PHY %d sudden disconnect.\n",
> tc_port);
>  		icl_tc_phy_disconnect(dig_port);
> @@ -124,15 +123,12 @@ void icl_tc_phy_disconnect(struct
> intel_digital_port *dig_port)
>  	struct drm_i915_private *dev_priv = to_i915(dig_port-
> >base.base.dev);
>  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> >base.port);
>  
> -	if (dig_port->tc_type == TC_PORT_UNKNOWN)
> -		return;
> -
>  	/*
>  	 * TBT disconnection flow is read the live status, what was
> done in
>  	 * caller.
>  	 */
> -	if (dig_port->tc_type == TC_PORT_TYPEC ||
> -	    dig_port->tc_type == TC_PORT_LEGACY) {
> +	if (dig_port->tc_mode == TC_PORT_DP_ALT ||
> +	    dig_port->tc_mode == TC_PORT_LEGACY) {
>  		u32 val;
>  
>  		val = I915_READ(PORT_TX_DFLEXDPCSSS);
> @@ -142,9 +138,9 @@ void icl_tc_phy_disconnect(struct
> intel_digital_port *dig_port)
>  
>  	DRM_DEBUG_KMS("Port %c TC type %s disconnected\n",
>  		      port_name(dig_port->base.port),
> -		      tc_type_name(dig_port->tc_type));
> +		      tc_port_mode_name(dig_port->tc_mode));
>  
> -	dig_port->tc_type = TC_PORT_UNKNOWN;
> +	dig_port->tc_mode = TC_PORT_TBT_ALT;
>  }
>  
>  static void icl_update_tc_port_type(struct drm_i915_private
> *dev_priv,
> @@ -152,26 +148,22 @@ static void icl_update_tc_port_type(struct
> drm_i915_private *dev_priv,
>  				    bool is_legacy, bool is_typec, bool
> is_tbt)
>  {
>  	enum port port = intel_dig_port->base.port;
> -	enum tc_port_type old_type = intel_dig_port->tc_type;
> +	enum tc_port_mode old_mode = intel_dig_port->tc_mode;
>  
>  	WARN_ON(is_legacy + is_typec + is_tbt != 1);
>  
>  	if (is_legacy)
> -		intel_dig_port->tc_type = TC_PORT_LEGACY;
> +		intel_dig_port->tc_mode = TC_PORT_LEGACY;
>  	else if (is_typec)
> -		intel_dig_port->tc_type = TC_PORT_TYPEC;
> +		intel_dig_port->tc_mode = TC_PORT_DP_ALT;
>  	else if (is_tbt)
> -		intel_dig_port->tc_type = TC_PORT_TBT;
> +		intel_dig_port->tc_mode = TC_PORT_TBT_ALT;
>  	else
>  		return;
>  
> -	/* Types are not supposed to be changed at runtime. */
> -	WARN_ON(old_type != TC_PORT_UNKNOWN &&
> -		old_type != intel_dig_port->tc_type);
> -
> -	if (old_type != intel_dig_port->tc_type)
> +	if (old_mode != intel_dig_port->tc_mode)
>  		DRM_DEBUG_KMS("Port %c has TC type %s\n",
> port_name(port),
> -			      tc_type_name(intel_dig_port->tc_type));
> +			      tc_port_mode_name(intel_dig_port-
> >tc_mode));
>  }
>  
>  
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 05/23] drm/i915: Don't enable the DDI-IO power in the TypeC TBT-alt mode
  2019-06-04 14:58 ` [PATCH 05/23] drm/i915: Don't enable the DDI-IO power in the TypeC TBT-alt mode Imre Deak
@ 2019-06-07 19:23   ` Souza, Jose
  0 siblings, 0 replies; 79+ messages in thread
From: Souza, Jose @ 2019-06-07 19:23 UTC (permalink / raw)
  To: intel-gfx, Deak, Imre

On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> According to the spec we should not enable the DDI-IO power domain if
> the TypeC port is in the TBT-alt mode, so do that only in the other
> TypeC modes or for non-TypeC ports.

With:
BSpec: 22243

Reviewed-by: José Roberto de Souza <jose.souza@intel.com>

> 
> Cc: Manasi Navare <manasi.d.navare@intel.com>
> Cc: Anusha Srivatsa <anusha.srivatsa@intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_ddi.c | 11 ++++++++---
>  1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c
> b/drivers/gpu/drm/i915/intel_ddi.c
> index a3574f14a3d0..8f223d48d562 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -3111,7 +3111,10 @@ static void intel_ddi_pre_enable_dp(struct
> intel_encoder *encoder,
>  
>  	intel_ddi_clk_select(encoder, crtc_state);
>  
> -	intel_display_power_get(dev_priv, dig_port-
> >ddi_io_power_domain);
> +	if (!intel_port_is_tc(dev_priv, port) ||
> +	    dig_port->tc_mode != TC_PORT_TBT_ALT)
> +		intel_display_power_get(dev_priv,
> +					dig_port->ddi_io_power_domain);
>  
>  	icl_program_mg_dp_mode(dig_port);
>  	icl_disable_phy_clock_gating(dig_port);
> @@ -3293,8 +3296,10 @@ static void intel_ddi_post_disable_dp(struct
> intel_encoder *encoder,
>  	intel_edp_panel_vdd_on(intel_dp);
>  	intel_edp_panel_off(intel_dp);
>  
> -	intel_display_power_put_unchecked(dev_priv,
> -					  dig_port-
> >ddi_io_power_domain);
> +	if (!intel_port_is_tc(dev_priv, encoder->port) ||
> +	    dig_port->tc_mode != TC_PORT_TBT_ALT)
> +		intel_display_power_put_unchecked(dev_priv,
> +						  dig_port-
> >ddi_io_power_domain);
>  
>  	intel_ddi_clk_disable(encoder);
>  }
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 06/23] drm/i915: Fix the TBT AUX power well enabling
  2019-06-04 14:58 ` [PATCH 06/23] drm/i915: Fix the TBT AUX power well enabling Imre Deak
@ 2019-06-07 19:58   ` Souza, Jose
  2019-06-08 13:55     ` Imre Deak
  0 siblings, 1 reply; 79+ messages in thread
From: Souza, Jose @ 2019-06-07 19:58 UTC (permalink / raw)
  To: intel-gfx, Deak, Imre

On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> Fix the mapping from a TBT AUX power well index to the DP_AUX_CH_CTL
> register.
> 
> Fixes: c7375d9542f1 ("drm/i915: Configure AUX_CH_CTL when enabling
> the AUX power domain")
> Cc: José Roberto de Souza <jose.souza@intel.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display_power.c | 11 +++++++++--
>  1 file changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display_power.c
> b/drivers/gpu/drm/i915/intel_display_power.c
> index 249a5fa55df6..14cf04bf0bf4 100644
> --- a/drivers/gpu/drm/i915/intel_display_power.c
> +++ b/drivers/gpu/drm/i915/intel_display_power.c
> @@ -442,16 +442,23 @@ icl_combo_phy_aux_power_well_disable(struct
> drm_i915_private *dev_priv,
>  #define ICL_AUX_PW_TO_CH(pw_idx)	\
>  	((pw_idx) - ICL_PW_CTL_IDX_AUX_A + AUX_CH_A)
>  
> +#define ICL_TBT_AUX_PW_TO_CH(pw_idx)	\
> +	((pw_idx) - ICL_PW_CTL_IDX_AUX_TBT1 + AUX_CH_C)
> +
>  static void
>  icl_tc_phy_aux_power_well_enable(struct drm_i915_private *dev_priv,
>  				 struct i915_power_well *power_well)
>  {
> -	enum aux_ch aux_ch = ICL_AUX_PW_TO_CH(power_well->desc-
> >hsw.idx);
> +	int pw_idx = power_well->desc->hsw.idx;
> +	bool is_tbt = power_well->desc->hsw.is_tc_tbt;
> +	enum aux_ch aux_ch;
>  	u32 val;
>  
> +	aux_ch = is_tbt ? ICL_TBT_AUX_PW_TO_CH(pw_idx) :
> +			  ICL_AUX_PW_TO_CH(pw_idx);

Matches

Reviewed-by: José Roberto de Souza <jose.souza@intel.com>

>  	val = I915_READ(DP_AUX_CH_CTL(aux_ch));
>  	val &= ~DP_AUX_CH_CTL_TBT_IO;
> -	if (power_well->desc->hsw.is_tc_tbt)
> +	if (is_tbt)
>  		val |= DP_AUX_CH_CTL_TBT_IO;

So this register needs to be set before the aux transaction?

>  	I915_WRITE(DP_AUX_CH_CTL(aux_ch), val);
>  
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 07/23] drm/i915: Use the correct AUX power domain in TypeC TBT-alt mode
  2019-06-04 14:58 ` [PATCH 07/23] drm/i915: Use the correct AUX power domain in TypeC TBT-alt mode Imre Deak
@ 2019-06-07 20:02   ` Souza, Jose
  0 siblings, 0 replies; 79+ messages in thread
From: Souza, Jose @ 2019-06-07 20:02 UTC (permalink / raw)
  To: intel-gfx, Deak, Imre

On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> In the TypeC TBT-alt port mode we must use the TBT AUX power domain,
> fix that.
> 
> Cc: Manasi Navare <manasi.d.navare@intel.com>
> Cc: Anusha Srivatsa <anusha.srivatsa@intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c
> b/drivers/gpu/drm/i915/intel_display.c
> index 26474788b7b2..0e425a6eebf3 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6609,6 +6609,25 @@ enum intel_display_power_domain
> intel_port_to_power_domain(enum port port)
>  enum intel_display_power_domain
>  intel_aux_power_domain(struct intel_digital_port *dig_port)
>  {
> +	struct drm_i915_private *dev_priv = to_i915(dig_port-
> >base.base.dev);
> +
> +	if (intel_port_is_tc(dev_priv, dig_port->base.port) &&
> +	    dig_port->tc_mode == TC_PORT_TBT_ALT) {
> +		switch (dig_port->aux_ch) {
> +		case AUX_CH_C:
> +			return POWER_DOMAIN_AUX_TBT1;
> +		case AUX_CH_D:
> +			return POWER_DOMAIN_AUX_TBT2;
> +		case AUX_CH_E:
> +			return POWER_DOMAIN_AUX_TBT3;
> +		case AUX_CH_F:
> +			return POWER_DOMAIN_AUX_TBT4;
> +		default:
> +			MISSING_CASE(dig_port->aux_ch);
> +			return POWER_DOMAIN_AUX_TBT1;
> +		}
> +	}


I would go by:
return dig_port->aux_ch - AUX_CH_C + POWER_DOMAIN_AUX_TBT1;

but that works too.

Reviewed-by: José Roberto de Souza <jose.souza@intel.com>

> +
>  	switch (dig_port->aux_ch) {
>  	case AUX_CH_A:
>  		return POWER_DOMAIN_AUX_A;
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 08/23] drm/i915: Unify the TypeC port notation in debug/error messages
  2019-06-04 14:58 ` [PATCH 08/23] drm/i915: Unify the TypeC port notation in debug/error messages Imre Deak
@ 2019-06-07 20:21   ` Souza, Jose
  2019-06-07 20:42     ` Imre Deak
  0 siblings, 1 reply; 79+ messages in thread
From: Souza, Jose @ 2019-06-07 20:21 UTC (permalink / raw)
  To: intel-gfx, Deak, Imre; +Cc: Zanoni, Paulo R

On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> Unify the TypeC port notation in log messages, so that it matches the
> spec. For instance the first ICL TypeC port will read as 'Port
> C/TC#1'.
> 
> Cc: José Roberto de Souza <jose.souza@intel.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_tc.c | 41 +++++++++++++++++++++++++++--
> ----
>  1 file changed, 34 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_tc.c
> b/drivers/gpu/drm/i915/intel_tc.c
> index a3057c44bec6..07488235b67a 100644
> --- a/drivers/gpu/drm/i915/intel_tc.c
> +++ b/drivers/gpu/drm/i915/intel_tc.c
> @@ -6,6 +6,29 @@
>  #include "i915_drv.h"
>  #include "intel_tc.h"
>  
> +static enum port intel_tc_port_to_port(struct drm_i915_private
> *dev_priv,
> +				       enum tc_port tc_port)
> +{
> +	return tc_port + PORT_C;
> +}
> +
> +static const char *tc_port_name(struct drm_i915_private *dev_priv,
> +				enum tc_port tc_port)
> +{
> +	static char port_names[I915_MAX_TC_PORTS][8];
> +
> +	if (WARN_ON(INTEL_GEN(dev_priv) < 11 ||
> +	    (unsigned int)tc_port >= I915_MAX_TC_PORTS))
> +		tc_port = PORT_TC1;

Why no WARN_ON on the tc_port >= I915_MAX_TC_PORTS?

> +
> +	snprintf(&port_names[tc_port][0], sizeof(port_names[tc_port]),
> +		 "%c/TC#%d",
> +		 port_name(intel_tc_port_to_port(dev_priv, tc_port)),
> +		 tc_port + 1);

Maybe do it only once for each port?

if (port_names[tc_port][0])
	return port_names[tc_port];

snprintf(&port_names[tc_port], sizeof....

Other the above:

Reviewed-by: José Roberto de Souza <jose.souza@intel.com>

> +
> +	return port_names[tc_port];
> +}
> +
>  static const char *tc_port_mode_name(enum tc_port_mode mode)
>  {
>  	static const char * const names[] = {
> @@ -85,7 +108,8 @@ static bool icl_tc_phy_connect(struct
> intel_digital_port *dig_port)
>  
>  	val = I915_READ(PORT_TX_DFLEXDPPMS);
>  	if (!(val & DP_PHY_MODE_STATUS_COMPLETED(tc_port))) {
> -		DRM_DEBUG_KMS("DP PHY for TC port %d not ready\n",
> tc_port);
> +		DRM_DEBUG_KMS("Port %s: PHY not ready\n",
> +			      tc_port_name(dev_priv, tc_port));
>  		WARN_ON(dig_port->tc_legacy_port);
>  		return false;
>  	}
> @@ -106,7 +130,8 @@ static bool icl_tc_phy_connect(struct
> intel_digital_port *dig_port)
>  	 */
>  	if (dig_port->tc_mode == TC_PORT_DP_ALT &&
>  	    !(I915_READ(PORT_TX_DFLEXDPSP) &
> TC_LIVE_STATE_TC(tc_port))) {
> -		DRM_DEBUG_KMS("TC PHY %d sudden disconnect.\n",
> tc_port);
> +		DRM_DEBUG_KMS("Port %s: PHY sudden disconnect\n",
> +			      tc_port_name(dev_priv, tc_port));
>  		icl_tc_phy_disconnect(dig_port);
>  		return false;
>  	}
> @@ -136,8 +161,8 @@ void icl_tc_phy_disconnect(struct
> intel_digital_port *dig_port)
>  		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
>  	}
>  
> -	DRM_DEBUG_KMS("Port %c TC type %s disconnected\n",
> -		      port_name(dig_port->base.port),
> +	DRM_DEBUG_KMS("Port %s: mode %s disconnected\n",
> +		      tc_port_name(dev_priv, tc_port),
>  		      tc_port_mode_name(dig_port->tc_mode));
>  
>  	dig_port->tc_mode = TC_PORT_TBT_ALT;
> @@ -162,7 +187,9 @@ static void icl_update_tc_port_type(struct
> drm_i915_private *dev_priv,
>  		return;
>  
>  	if (old_mode != intel_dig_port->tc_mode)
> -		DRM_DEBUG_KMS("Port %c has TC type %s\n",
> port_name(port),
> +		DRM_DEBUG_KMS("Port %s: port has mode %s\n",
> +			      tc_port_name(dev_priv,
> +					   intel_port_to_tc(dev_priv,
> port)),
>  			      tc_port_mode_name(intel_dig_port-
> >tc_mode));
>  }
>  
> @@ -191,8 +218,8 @@ bool intel_tc_port_connected(struct
> intel_digital_port *dig_port)
>  	 */
>  	if (!dig_port->tc_legacy_port &&
>  	    I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port)) {
> -		DRM_ERROR("VBT incorrectly claims port %c is not TypeC
> legacy\n",
> -			  port_name(port));
> +		DRM_ERROR("Port %s: VBT incorrectly claims port is not
> TypeC legacy\n",
> +			  tc_port_name(dev_priv, tc_port));
>  		dig_port->tc_legacy_port = true;
>  	}
>  	is_legacy = dig_port->tc_legacy_port;
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 08/23] drm/i915: Unify the TypeC port notation in debug/error messages
  2019-06-07 20:21   ` Souza, Jose
@ 2019-06-07 20:42     ` Imre Deak
  2019-06-07 20:45       ` Souza, Jose
  2019-06-07 20:46       ` Imre Deak
  0 siblings, 2 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-07 20:42 UTC (permalink / raw)
  To: Souza, Jose; +Cc: intel-gfx, Zanoni, Paulo R

On Fri, Jun 07, 2019 at 11:21:51PM +0300, Souza, Jose wrote:
> On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> > Unify the TypeC port notation in log messages, so that it matches the
> > spec. For instance the first ICL TypeC port will read as 'Port
> > C/TC#1'.
> > 
> > Cc: José Roberto de Souza <jose.souza@intel.com>
> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_tc.c | 41 +++++++++++++++++++++++++++--
> > ----
> >  1 file changed, 34 insertions(+), 7 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_tc.c
> > b/drivers/gpu/drm/i915/intel_tc.c
> > index a3057c44bec6..07488235b67a 100644
> > --- a/drivers/gpu/drm/i915/intel_tc.c
> > +++ b/drivers/gpu/drm/i915/intel_tc.c
> > @@ -6,6 +6,29 @@
> >  #include "i915_drv.h"
> >  #include "intel_tc.h"
> >  
> > +static enum port intel_tc_port_to_port(struct drm_i915_private
> > *dev_priv,
> > +				       enum tc_port tc_port)
> > +{
> > +	return tc_port + PORT_C;
> > +}
> > +
> > +static const char *tc_port_name(struct drm_i915_private *dev_priv,
> > +				enum tc_port tc_port)
> > +{
> > +	static char port_names[I915_MAX_TC_PORTS][8];
> > +
> > +	if (WARN_ON(INTEL_GEN(dev_priv) < 11 ||
> > +	    (unsigned int)tc_port >= I915_MAX_TC_PORTS))
> > +		tc_port = PORT_TC1;
> 
> Why no WARN_ON on the tc_port >= I915_MAX_TC_PORTS?

Hm, do you mean a seaparate WARN_ON()?

> 
> > +
> > +	snprintf(&port_names[tc_port][0], sizeof(port_names[tc_port]),
> > +		 "%c/TC#%d",
> > +		 port_name(intel_tc_port_to_port(dev_priv, tc_port)),
> > +		 tc_port + 1);
> 
> Maybe do it only once for each port?
> 
> if (port_names[tc_port][0])
> 	return port_names[tc_port];

I thought why not keep it as simple as possible (not really performance
critical), but your version makes it clearer to the reader what the
logic is (static array), so can change it.

> 
> snprintf(&port_names[tc_port], sizeof....
> 
> Other the above:
> 
> Reviewed-by: José Roberto de Souza <jose.souza@intel.com>
> 
> > +
> > +	return port_names[tc_port];
> > +}
> > +
> >  static const char *tc_port_mode_name(enum tc_port_mode mode)
> >  {
> >  	static const char * const names[] = {
> > @@ -85,7 +108,8 @@ static bool icl_tc_phy_connect(struct
> > intel_digital_port *dig_port)
> >  
> >  	val = I915_READ(PORT_TX_DFLEXDPPMS);
> >  	if (!(val & DP_PHY_MODE_STATUS_COMPLETED(tc_port))) {
> > -		DRM_DEBUG_KMS("DP PHY for TC port %d not ready\n",
> > tc_port);
> > +		DRM_DEBUG_KMS("Port %s: PHY not ready\n",
> > +			      tc_port_name(dev_priv, tc_port));
> >  		WARN_ON(dig_port->tc_legacy_port);
> >  		return false;
> >  	}
> > @@ -106,7 +130,8 @@ static bool icl_tc_phy_connect(struct
> > intel_digital_port *dig_port)
> >  	 */
> >  	if (dig_port->tc_mode == TC_PORT_DP_ALT &&
> >  	    !(I915_READ(PORT_TX_DFLEXDPSP) &
> > TC_LIVE_STATE_TC(tc_port))) {
> > -		DRM_DEBUG_KMS("TC PHY %d sudden disconnect.\n",
> > tc_port);
> > +		DRM_DEBUG_KMS("Port %s: PHY sudden disconnect\n",
> > +			      tc_port_name(dev_priv, tc_port));
> >  		icl_tc_phy_disconnect(dig_port);
> >  		return false;
> >  	}
> > @@ -136,8 +161,8 @@ void icl_tc_phy_disconnect(struct
> > intel_digital_port *dig_port)
> >  		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> >  	}
> >  
> > -	DRM_DEBUG_KMS("Port %c TC type %s disconnected\n",
> > -		      port_name(dig_port->base.port),
> > +	DRM_DEBUG_KMS("Port %s: mode %s disconnected\n",
> > +		      tc_port_name(dev_priv, tc_port),
> >  		      tc_port_mode_name(dig_port->tc_mode));
> >  
> >  	dig_port->tc_mode = TC_PORT_TBT_ALT;
> > @@ -162,7 +187,9 @@ static void icl_update_tc_port_type(struct
> > drm_i915_private *dev_priv,
> >  		return;
> >  
> >  	if (old_mode != intel_dig_port->tc_mode)
> > -		DRM_DEBUG_KMS("Port %c has TC type %s\n",
> > port_name(port),
> > +		DRM_DEBUG_KMS("Port %s: port has mode %s\n",
> > +			      tc_port_name(dev_priv,
> > +					   intel_port_to_tc(dev_priv,
> > port)),
> >  			      tc_port_mode_name(intel_dig_port-
> > >tc_mode));
> >  }
> >  
> > @@ -191,8 +218,8 @@ bool intel_tc_port_connected(struct
> > intel_digital_port *dig_port)
> >  	 */
> >  	if (!dig_port->tc_legacy_port &&
> >  	    I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port)) {
> > -		DRM_ERROR("VBT incorrectly claims port %c is not TypeC
> > legacy\n",
> > -			  port_name(port));
> > +		DRM_ERROR("Port %s: VBT incorrectly claims port is not
> > TypeC legacy\n",
> > +			  tc_port_name(dev_priv, tc_port));
> >  		dig_port->tc_legacy_port = true;
> >  	}
> >  	is_legacy = dig_port->tc_legacy_port;
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 08/23] drm/i915: Unify the TypeC port notation in debug/error messages
  2019-06-07 20:42     ` Imre Deak
@ 2019-06-07 20:45       ` Souza, Jose
  2019-06-07 20:46       ` Imre Deak
  1 sibling, 0 replies; 79+ messages in thread
From: Souza, Jose @ 2019-06-07 20:45 UTC (permalink / raw)
  To: Deak, Imre; +Cc: intel-gfx, Zanoni, Paulo R

On Fri, 2019-06-07 at 23:42 +0300, Imre Deak wrote:
> On Fri, Jun 07, 2019 at 11:21:51PM +0300, Souza, Jose wrote:
> > On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> > > Unify the TypeC port notation in log messages, so that it matches
> > > the
> > > spec. For instance the first ICL TypeC port will read as 'Port
> > > C/TC#1'.
> > > 
> > > Cc: José Roberto de Souza <jose.souza@intel.com>
> > > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > > Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/intel_tc.c | 41
> > > +++++++++++++++++++++++++++--
> > > ----
> > >  1 file changed, 34 insertions(+), 7 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/intel_tc.c
> > > b/drivers/gpu/drm/i915/intel_tc.c
> > > index a3057c44bec6..07488235b67a 100644
> > > --- a/drivers/gpu/drm/i915/intel_tc.c
> > > +++ b/drivers/gpu/drm/i915/intel_tc.c
> > > @@ -6,6 +6,29 @@
> > >  #include "i915_drv.h"
> > >  #include "intel_tc.h"
> > >  
> > > +static enum port intel_tc_port_to_port(struct drm_i915_private
> > > *dev_priv,
> > > +				       enum tc_port tc_port)
> > > +{
> > > +	return tc_port + PORT_C;
> > > +}
> > > +
> > > +static const char *tc_port_name(struct drm_i915_private
> > > *dev_priv,
> > > +				enum tc_port tc_port)
> > > +{
> > > +	static char port_names[I915_MAX_TC_PORTS][8];
> > > +
> > > +	if (WARN_ON(INTEL_GEN(dev_priv) < 11 ||
> > > +	    (unsigned int)tc_port >= I915_MAX_TC_PORTS))
> > > +		tc_port = PORT_TC1;
> > 
> > Why no WARN_ON on the tc_port >= I915_MAX_TC_PORTS?
> 
> Hm, do you mean a seaparate WARN_ON()?

Oh I misread the parentheses, it is right.

> 
> > > +
> > > +	snprintf(&port_names[tc_port][0], sizeof(port_names[tc_port]),
> > > +		 "%c/TC#%d",
> > > +		 port_name(intel_tc_port_to_port(dev_priv, tc_port)),
> > > +		 tc_port + 1);
> > 
> > Maybe do it only once for each port?
> > 
> > if (port_names[tc_port][0])
> > 	return port_names[tc_port];
> 
> I thought why not keep it as simple as possible (not really
> performance
> critical), but your version makes it clearer to the reader what the
> logic is (static array), so can change it.
> 
> > snprintf(&port_names[tc_port], sizeof....
> > 
> > Other the above:
> > 
> > Reviewed-by: José Roberto de Souza <jose.souza@intel.com>
> > 
> > > +
> > > +	return port_names[tc_port];
> > > +}
> > > +
> > >  static const char *tc_port_mode_name(enum tc_port_mode mode)
> > >  {
> > >  	static const char * const names[] = {
> > > @@ -85,7 +108,8 @@ static bool icl_tc_phy_connect(struct
> > > intel_digital_port *dig_port)
> > >  
> > >  	val = I915_READ(PORT_TX_DFLEXDPPMS);
> > >  	if (!(val & DP_PHY_MODE_STATUS_COMPLETED(tc_port))) {
> > > -		DRM_DEBUG_KMS("DP PHY for TC port %d not ready\n",
> > > tc_port);
> > > +		DRM_DEBUG_KMS("Port %s: PHY not ready\n",
> > > +			      tc_port_name(dev_priv, tc_port));
> > >  		WARN_ON(dig_port->tc_legacy_port);
> > >  		return false;
> > >  	}
> > > @@ -106,7 +130,8 @@ static bool icl_tc_phy_connect(struct
> > > intel_digital_port *dig_port)
> > >  	 */
> > >  	if (dig_port->tc_mode == TC_PORT_DP_ALT &&
> > >  	    !(I915_READ(PORT_TX_DFLEXDPSP) &
> > > TC_LIVE_STATE_TC(tc_port))) {
> > > -		DRM_DEBUG_KMS("TC PHY %d sudden disconnect.\n",
> > > tc_port);
> > > +		DRM_DEBUG_KMS("Port %s: PHY sudden disconnect\n",
> > > +			      tc_port_name(dev_priv, tc_port));
> > >  		icl_tc_phy_disconnect(dig_port);
> > >  		return false;
> > >  	}
> > > @@ -136,8 +161,8 @@ void icl_tc_phy_disconnect(struct
> > > intel_digital_port *dig_port)
> > >  		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> > >  	}
> > >  
> > > -	DRM_DEBUG_KMS("Port %c TC type %s disconnected\n",
> > > -		      port_name(dig_port->base.port),
> > > +	DRM_DEBUG_KMS("Port %s: mode %s disconnected\n",
> > > +		      tc_port_name(dev_priv, tc_port),
> > >  		      tc_port_mode_name(dig_port->tc_mode));
> > >  
> > >  	dig_port->tc_mode = TC_PORT_TBT_ALT;
> > > @@ -162,7 +187,9 @@ static void icl_update_tc_port_type(struct
> > > drm_i915_private *dev_priv,
> > >  		return;
> > >  
> > >  	if (old_mode != intel_dig_port->tc_mode)
> > > -		DRM_DEBUG_KMS("Port %c has TC type %s\n",
> > > port_name(port),
> > > +		DRM_DEBUG_KMS("Port %s: port has mode %s\n",
> > > +			      tc_port_name(dev_priv,
> > > +					   intel_port_to_tc(dev_priv,
> > > port)),
> > >  			      tc_port_mode_name(intel_dig_port-
> > > > tc_mode));
> > >  }
> > >  
> > > @@ -191,8 +218,8 @@ bool intel_tc_port_connected(struct
> > > intel_digital_port *dig_port)
> > >  	 */
> > >  	if (!dig_port->tc_legacy_port &&
> > >  	    I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port)) {
> > > -		DRM_ERROR("VBT incorrectly claims port %c is not TypeC
> > > legacy\n",
> > > -			  port_name(port));
> > > +		DRM_ERROR("Port %s: VBT incorrectly claims port is not
> > > TypeC legacy\n",
> > > +			  tc_port_name(dev_priv, tc_port));
> > >  		dig_port->tc_legacy_port = true;
> > >  	}
> > >  	is_legacy = dig_port->tc_legacy_port;
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 08/23] drm/i915: Unify the TypeC port notation in debug/error messages
  2019-06-07 20:42     ` Imre Deak
  2019-06-07 20:45       ` Souza, Jose
@ 2019-06-07 20:46       ` Imre Deak
  1 sibling, 0 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-07 20:46 UTC (permalink / raw)
  To: Souza, Jose; +Cc: intel-gfx, Zanoni, Paulo R

On Fri, Jun 07, 2019 at 11:42:31PM +0300, Imre Deak wrote:
> On Fri, Jun 07, 2019 at 11:21:51PM +0300, Souza, Jose wrote:
> > On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> > > Unify the TypeC port notation in log messages, so that it matches the
> > > spec. For instance the first ICL TypeC port will read as 'Port
> > > C/TC#1'.
> > > 
> > > Cc: José Roberto de Souza <jose.souza@intel.com>
> > > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > > Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/intel_tc.c | 41 +++++++++++++++++++++++++++--
> > > ----
> > >  1 file changed, 34 insertions(+), 7 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/intel_tc.c
> > > b/drivers/gpu/drm/i915/intel_tc.c
> > > index a3057c44bec6..07488235b67a 100644
> > > --- a/drivers/gpu/drm/i915/intel_tc.c
> > > +++ b/drivers/gpu/drm/i915/intel_tc.c
> > > @@ -6,6 +6,29 @@
> > >  #include "i915_drv.h"
> > >  #include "intel_tc.h"
> > >  
> > > +static enum port intel_tc_port_to_port(struct drm_i915_private
> > > *dev_priv,
> > > +				       enum tc_port tc_port)
> > > +{
> > > +	return tc_port + PORT_C;
> > > +}
> > > +
> > > +static const char *tc_port_name(struct drm_i915_private *dev_priv,
> > > +				enum tc_port tc_port)
> > > +{
> > > +	static char port_names[I915_MAX_TC_PORTS][8];
> > > +
> > > +	if (WARN_ON(INTEL_GEN(dev_priv) < 11 ||
> > > +	    (unsigned int)tc_port >= I915_MAX_TC_PORTS))
> > > +		tc_port = PORT_TC1;
> > 
> > Why no WARN_ON on the tc_port >= I915_MAX_TC_PORTS?
> 
> Hm, do you mean a seaparate WARN_ON()?

Well, at least it's misindented, I can fix that.

> 
> > 
> > > +
> > > +	snprintf(&port_names[tc_port][0], sizeof(port_names[tc_port]),
> > > +		 "%c/TC#%d",
> > > +		 port_name(intel_tc_port_to_port(dev_priv, tc_port)),
> > > +		 tc_port + 1);
> > 
> > Maybe do it only once for each port?
> > 
> > if (port_names[tc_port][0])
> > 	return port_names[tc_port];
> 
> I thought why not keep it as simple as possible (not really performance
> critical), but your version makes it clearer to the reader what the
> logic is (static array), so can change it.
> 
> > 
> > snprintf(&port_names[tc_port], sizeof....
> > 
> > Other the above:
> > 
> > Reviewed-by: José Roberto de Souza <jose.souza@intel.com>
> > 
> > > +
> > > +	return port_names[tc_port];
> > > +}
> > > +
> > >  static const char *tc_port_mode_name(enum tc_port_mode mode)
> > >  {
> > >  	static const char * const names[] = {
> > > @@ -85,7 +108,8 @@ static bool icl_tc_phy_connect(struct
> > > intel_digital_port *dig_port)
> > >  
> > >  	val = I915_READ(PORT_TX_DFLEXDPPMS);
> > >  	if (!(val & DP_PHY_MODE_STATUS_COMPLETED(tc_port))) {
> > > -		DRM_DEBUG_KMS("DP PHY for TC port %d not ready\n",
> > > tc_port);
> > > +		DRM_DEBUG_KMS("Port %s: PHY not ready\n",
> > > +			      tc_port_name(dev_priv, tc_port));
> > >  		WARN_ON(dig_port->tc_legacy_port);
> > >  		return false;
> > >  	}
> > > @@ -106,7 +130,8 @@ static bool icl_tc_phy_connect(struct
> > > intel_digital_port *dig_port)
> > >  	 */
> > >  	if (dig_port->tc_mode == TC_PORT_DP_ALT &&
> > >  	    !(I915_READ(PORT_TX_DFLEXDPSP) &
> > > TC_LIVE_STATE_TC(tc_port))) {
> > > -		DRM_DEBUG_KMS("TC PHY %d sudden disconnect.\n",
> > > tc_port);
> > > +		DRM_DEBUG_KMS("Port %s: PHY sudden disconnect\n",
> > > +			      tc_port_name(dev_priv, tc_port));
> > >  		icl_tc_phy_disconnect(dig_port);
> > >  		return false;
> > >  	}
> > > @@ -136,8 +161,8 @@ void icl_tc_phy_disconnect(struct
> > > intel_digital_port *dig_port)
> > >  		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> > >  	}
> > >  
> > > -	DRM_DEBUG_KMS("Port %c TC type %s disconnected\n",
> > > -		      port_name(dig_port->base.port),
> > > +	DRM_DEBUG_KMS("Port %s: mode %s disconnected\n",
> > > +		      tc_port_name(dev_priv, tc_port),
> > >  		      tc_port_mode_name(dig_port->tc_mode));
> > >  
> > >  	dig_port->tc_mode = TC_PORT_TBT_ALT;
> > > @@ -162,7 +187,9 @@ static void icl_update_tc_port_type(struct
> > > drm_i915_private *dev_priv,
> > >  		return;
> > >  
> > >  	if (old_mode != intel_dig_port->tc_mode)
> > > -		DRM_DEBUG_KMS("Port %c has TC type %s\n",
> > > port_name(port),
> > > +		DRM_DEBUG_KMS("Port %s: port has mode %s\n",
> > > +			      tc_port_name(dev_priv,
> > > +					   intel_port_to_tc(dev_priv,
> > > port)),
> > >  			      tc_port_mode_name(intel_dig_port-
> > > >tc_mode));
> > >  }
> > >  
> > > @@ -191,8 +218,8 @@ bool intel_tc_port_connected(struct
> > > intel_digital_port *dig_port)
> > >  	 */
> > >  	if (!dig_port->tc_legacy_port &&
> > >  	    I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port)) {
> > > -		DRM_ERROR("VBT incorrectly claims port %c is not TypeC
> > > legacy\n",
> > > -			  port_name(port));
> > > +		DRM_ERROR("Port %s: VBT incorrectly claims port is not
> > > TypeC legacy\n",
> > > +			  tc_port_name(dev_priv, tc_port));
> > >  		dig_port->tc_legacy_port = true;
> > >  	}
> > >  	is_legacy = dig_port->tc_legacy_port;
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 09/23] drm/i915: Factor out common parts from TypeC port handling functions
  2019-06-04 14:58 ` [PATCH 09/23] drm/i915: Factor out common parts from TypeC port handling functions Imre Deak
  2019-06-06  8:47   ` Jani Nikula
@ 2019-06-07 21:22   ` Souza, Jose
  2019-06-08 17:23     ` Imre Deak
  2019-06-18 16:33   ` Ville Syrjälä
  2 siblings, 1 reply; 79+ messages in thread
From: Souza, Jose @ 2019-06-07 21:22 UTC (permalink / raw)
  To: intel-gfx, Deak, Imre; +Cc: Zanoni, Paulo R

On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> Factor out helpers reading/parsing the TypeC specific registers,
> making
> current users of them clearer and letting us use them later.
> 
> While at it also:
> - Simplify icl_tc_phy_connect() with an early return in legacy mode.
> - Simplify the live status check using one bitmask for all HPD bits.
> - Remove a micro-optimisation of the repeated safe-mode clearing.
> - Make sure we fix the legacy port flag in all cases.
> 
> Except for the last two, no functional changes.
> 
> Cc: José Roberto de Souza <jose.souza@intel.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_ddi.c |   5 +-
>  drivers/gpu/drm/i915/intel_tc.c  | 166 +++++++++++++++++++--------
> ----
>  drivers/gpu/drm/i915/intel_tc.h  |   1 +
>  3 files changed, 103 insertions(+), 69 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c
> b/drivers/gpu/drm/i915/intel_ddi.c
> index 8f223d48d562..d236839bee19 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -2983,7 +2983,6 @@ static void icl_program_mg_dp_mode(struct
> intel_digital_port *intel_dig_port)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(intel_dig_port-
> >base.base.dev);
>  	enum port port = intel_dig_port->base.port;
> -	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
>  	u32 ln0, ln1, lane_info;
>  
>  	if (intel_dig_port->tc_mode == TC_PORT_TBT_ALT)
> @@ -2997,9 +2996,7 @@ static void icl_program_mg_dp_mode(struct
> intel_digital_port *intel_dig_port)
>  		ln0 &= ~(MG_DP_MODE_CFG_DP_X1_MODE |
> MG_DP_MODE_CFG_DP_X2_MODE);
>  		ln1 &= ~(MG_DP_MODE_CFG_DP_X1_MODE |
> MG_DP_MODE_CFG_DP_X2_MODE);
>  
> -		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
> -			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
> -			    DP_LANE_ASSIGNMENT_SHIFT(tc_port);
> +		lane_info =
> intel_tc_port_get_lane_info(intel_dig_port);
>  
>  		switch (lane_info) {
>  		case 0x1:
> diff --git a/drivers/gpu/drm/i915/intel_tc.c
> b/drivers/gpu/drm/i915/intel_tc.c
> index 07488235b67a..3fdcfa2bbaee 100644
> --- a/drivers/gpu/drm/i915/intel_tc.c
> +++ b/drivers/gpu/drm/i915/intel_tc.c
> @@ -43,10 +43,19 @@ static const char *tc_port_mode_name(enum
> tc_port_mode mode)
>  	return names[mode];
>  }
>  
> -int intel_tc_port_fia_max_lane_count(struct intel_digital_port
> *dig_port)
> +u32 intel_tc_port_get_lane_info(struct intel_digital_port *dig_port)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dig_port-
> >base.base.dev);
>  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> >base.port);
> +	u32 lane_info = I915_READ(PORT_TX_DFLEXDPSP);
> +
> +	return (lane_info & DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
> +	       DP_LANE_ASSIGNMENT_SHIFT(tc_port);
> +}
> +
> +int intel_tc_port_fia_max_lane_count(struct intel_digital_port
> *dig_port)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port-
> >base.base.dev);
>  	intel_wakeref_t wakeref;
>  	u32 lane_info;
>  
> @@ -55,9 +64,7 @@ int intel_tc_port_fia_max_lane_count(struct
> intel_digital_port *dig_port)
>  
>  	lane_info = 0;
>  	with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE,
> wakeref)
> -		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
> -			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
> -				DP_LANE_ASSIGNMENT_SHIFT(tc_port);
> +		lane_info = intel_tc_port_get_lane_info(dig_port);
>  
>  	switch (lane_info) {
>  	default:
> @@ -75,6 +82,69 @@ int intel_tc_port_fia_max_lane_count(struct
> intel_digital_port *dig_port)
>  	}
>  }
>  
> +static void tc_port_fixup_legacy_flag(struct intel_digital_port
> *dig_port,
> +				      u32 live_status_mask)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port-
> >base.base.dev);
> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> >base.port);
> +	u32 valid_hpd_mask = dig_port->tc_legacy_port ?
> BIT(TC_PORT_LEGACY) :
> +							~BIT(TC_PORT_LE
> GACY);
> +
> +	if (!(live_status_mask & ~valid_hpd_mask))
> +		return;
> +
> +	/* If live status mismatches the VBT flag, trust the live
> status. */
> +	DRM_ERROR("Port %s: live status %08x mismatches the legacy port
> flag, fix flag\n",
> +		  tc_port_name(dev_priv, tc_port), live_status_mask);
> +
> +	dig_port->tc_legacy_port = !dig_port->tc_legacy_port;
> +}
> +
> +static u32 tc_port_live_status_mask(struct intel_digital_port
> *dig_port)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port-
> >base.base.dev);
> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> >base.port);
> +	u32 val = I915_READ(PORT_TX_DFLEXDPSP);
> +	u32 mask = 0;
> +
> +	if (val & TC_LIVE_STATE_TBT(tc_port))
> +		mask |= BIT(TC_PORT_TBT_ALT);
> +	if (val & TC_LIVE_STATE_TC(tc_port))
> +		mask |= BIT(TC_PORT_DP_ALT);
> +
> +	if (I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port))
> +		mask |= BIT(TC_PORT_LEGACY);
> +
> +	/* The sink can be connected only in a single mode. */
> +	if (!WARN_ON(hweight32(mask) > 1))
> +		tc_port_fixup_legacy_flag(dig_port, mask);

The mask should be updated after the fixup

> +
> +	return mask;
> +}
> +
> +static bool icl_tc_phy_status_complete(struct intel_digital_port
> *dig_port)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port-
> >base.base.dev);
> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> >base.port);
> +
> +	return I915_READ(PORT_TX_DFLEXDPPMS) &
> +	       DP_PHY_MODE_STATUS_COMPLETED(tc_port);
> +}
> +
> +static void icl_tc_phy_set_safe_mode(struct intel_digital_port
> *dig_port,
> +				     bool enable)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port-
> >base.base.dev);
> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> >base.port);
> +	u32 val = I915_READ(PORT_TX_DFLEXDPCSSS);
> +
> +	val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> +	if (!enable)
> +		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);

Why complete remove the optimizations?
You could do:

old_val = val = I915_READ(PORT_TX_DFLEXDPCSSS);
val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);

if (!enable)

	val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);


if (val != old_val)
	I915_WRITE(PORT_TX_DFLEXDPCSSS, val);

> +
> +	I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> +}
> +
>  /*
>   * This function implements the first part of the Connect Flow
> described by our
>   * specification, Gen11 TypeC Programming chapter. The rest of the
> flow (reading
> @@ -100,36 +170,31 @@ static bool icl_tc_phy_connect(struct
> intel_digital_port *dig_port)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dig_port-
> >base.base.dev);
>  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> >base.port);
> -	u32 val;
> +	u32 live_status_mask;
>  
>  	if (dig_port->tc_mode != TC_PORT_LEGACY &&
>  	    dig_port->tc_mode != TC_PORT_DP_ALT)
>  		return true;
>  
> -	val = I915_READ(PORT_TX_DFLEXDPPMS);
> -	if (!(val & DP_PHY_MODE_STATUS_COMPLETED(tc_port))) {
> +	if (!icl_tc_phy_status_complete(dig_port)) {
>  		DRM_DEBUG_KMS("Port %s: PHY not ready\n",
>  			      tc_port_name(dev_priv, tc_port));
>  		WARN_ON(dig_port->tc_legacy_port);
>  		return false;
>  	}
>  
> -	/*
> -	 * This function may be called many times in a row without an
> HPD event
> -	 * in between, so try to avoid the write when we can.
> -	 */
> -	val = I915_READ(PORT_TX_DFLEXDPCSSS);
> -	if (!(val & DP_PHY_MODE_STATUS_NOT_SAFE(tc_port))) {
> -		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> -		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> -	}
> +	icl_tc_phy_set_safe_mode(dig_port, false);
> +
> +	if (dig_port->tc_mode == TC_PORT_LEGACY)
> +		return true;
> +
> +	live_status_mask = tc_port_live_status_mask(dig_port);
>  
>  	/*
>  	 * Now we have to re-check the live state, in case the port
> recently
>  	 * became disconnected. Not necessary for legacy mode.
>  	 */
> -	if (dig_port->tc_mode == TC_PORT_DP_ALT &&
> -	    !(I915_READ(PORT_TX_DFLEXDPSP) &
> TC_LIVE_STATE_TC(tc_port))) {
> +	if (!(live_status_mask & BIT(TC_PORT_DP_ALT))) {

When live status is TC_PORT_TBT_ALT it will cause the "sudden
disconnect" to be printed each time although icl_tc_phy_disconnect()
will do nothing for TBT.

>  		DRM_DEBUG_KMS("Port %s: PHY sudden disconnect\n",
>  			      tc_port_name(dev_priv, tc_port));
>  		icl_tc_phy_disconnect(dig_port);
> @@ -148,44 +213,36 @@ void icl_tc_phy_disconnect(struct
> intel_digital_port *dig_port)
>  	struct drm_i915_private *dev_priv = to_i915(dig_port-
> >base.base.dev);
>  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> >base.port);
>  
> -	/*
> -	 * TBT disconnection flow is read the live status, what was
> done in
> -	 * caller.
> -	 */
> -	if (dig_port->tc_mode == TC_PORT_DP_ALT ||
> -	    dig_port->tc_mode == TC_PORT_LEGACY) {
> -		u32 val;
> -
> -		val = I915_READ(PORT_TX_DFLEXDPCSSS);
> -		val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> -		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> +	switch (dig_port->tc_mode) {
> +	case TC_PORT_LEGACY:
> +	case TC_PORT_DP_ALT:
> +		icl_tc_phy_set_safe_mode(dig_port, true);
> +		dig_port->tc_mode = TC_PORT_TBT_ALT;
> +		break;
> +	case TC_PORT_TBT_ALT:
> +		/* Nothing to do, we stay in TBT-alt mode */
> +		break;
> +	default:
> +		MISSING_CASE(dig_port->tc_mode);
>  	}
>  
>  	DRM_DEBUG_KMS("Port %s: mode %s disconnected\n",
>  		      tc_port_name(dev_priv, tc_port),
>  		      tc_port_mode_name(dig_port->tc_mode));
> -
> -	dig_port->tc_mode = TC_PORT_TBT_ALT;
>  }
>  
>  static void icl_update_tc_port_type(struct drm_i915_private
> *dev_priv,
>  				    struct intel_digital_port
> *intel_dig_port,
> -				    bool is_legacy, bool is_typec, bool
> is_tbt)
> +				    u32 live_status_mask)
>  {
>  	enum port port = intel_dig_port->base.port;
>  	enum tc_port_mode old_mode = intel_dig_port->tc_mode;
>  
> -	WARN_ON(is_legacy + is_typec + is_tbt != 1);
> -
> -	if (is_legacy)
> -		intel_dig_port->tc_mode = TC_PORT_LEGACY;
> -	else if (is_typec)
> -		intel_dig_port->tc_mode = TC_PORT_DP_ALT;
> -	else if (is_tbt)
> -		intel_dig_port->tc_mode = TC_PORT_TBT_ALT;
> -	else
> +	if (!live_status_mask)
>  		return;
>  
> +	intel_dig_port->tc_mode = fls(live_status_mask) - 1;
> +
>  	if (old_mode != intel_dig_port->tc_mode)
>  		DRM_DEBUG_KMS("Port %s: port has mode %s\n",
>  			      tc_port_name(dev_priv,
> @@ -207,40 +264,19 @@ static void icl_update_tc_port_type(struct
> drm_i915_private *dev_priv,
>  bool intel_tc_port_connected(struct intel_digital_port *dig_port)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dig_port-
> >base.base.dev);
> -	enum port port = dig_port->base.port;
> -	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
> -	bool is_legacy, is_typec, is_tbt;
> -	u32 dpsp;
> -
> -	/*
> -	 * Complain if we got a legacy port HPD, but VBT didn't mark
> the port as
> -	 * legacy. Treat the port as legacy from now on.
> -	 */
> -	if (!dig_port->tc_legacy_port &&
> -	    I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port)) {
> -		DRM_ERROR("Port %s: VBT incorrectly claims port is not
> TypeC legacy\n",
> -			  tc_port_name(dev_priv, tc_port));
> -		dig_port->tc_legacy_port = true;
> -	}
> -	is_legacy = dig_port->tc_legacy_port;
> +	u32 live_status_mask = tc_port_live_status_mask(dig_port);
>  
>  	/*
>  	 * The spec says we shouldn't be using the ISR bits for
> detecting
>  	 * between TC and TBT. We should use DFLEXDPSP.
>  	 */
> -	dpsp = I915_READ(PORT_TX_DFLEXDPSP);
> -	is_typec = dpsp & TC_LIVE_STATE_TC(tc_port);
> -	is_tbt = dpsp & TC_LIVE_STATE_TBT(tc_port);
> -
> -	if (!is_legacy && !is_typec && !is_tbt) {
> +	if (!live_status_mask && !dig_port->tc_legacy_port) {

So now it will keep legacy port as unsafe even when disconnected.
Maybe worth mention in commit message.

>  		icl_tc_phy_disconnect(dig_port);
>  
>  		return false;
>  	}
>  
> -	icl_update_tc_port_type(dev_priv, dig_port, is_legacy,
> is_typec,
> -				is_tbt);
> -
> +	icl_update_tc_port_type(dev_priv, dig_port, live_status_mask);
>  	if (!icl_tc_phy_connect(dig_port))
>  		return false;
>  
> diff --git a/drivers/gpu/drm/i915/intel_tc.h
> b/drivers/gpu/drm/i915/intel_tc.h
> index 94c62ac4a162..e937f5326959 100644
> --- a/drivers/gpu/drm/i915/intel_tc.h
> +++ b/drivers/gpu/drm/i915/intel_tc.h
> @@ -8,6 +8,7 @@ struct intel_digital_port;
>  void icl_tc_phy_disconnect(struct intel_digital_port *dig_port);
>  
>  bool intel_tc_port_connected(struct intel_digital_port *dig_port);
> +u32 intel_tc_port_get_lane_info(struct intel_digital_port
> *dig_port);
>  int intel_tc_port_fia_max_lane_count(struct intel_digital_port
> *dig_port);
>  
>  #endif /* __INTEL_TC_H__ */
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 10/23] drm/i915: Wait for TypeC PHY complete flag to clear in safe mode
  2019-06-04 14:58 ` [PATCH 10/23] drm/i915: Wait for TypeC PHY complete flag to clear in safe mode Imre Deak
@ 2019-06-07 21:32   ` Souza, Jose
  0 siblings, 0 replies; 79+ messages in thread
From: Souza, Jose @ 2019-06-07 21:32 UTC (permalink / raw)
  To: intel-gfx, Deak, Imre

On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> The PHY satus complete flag normally clears when disconnecting the 

s/satus/status

> PHY
> in DP-alt mode (achieved by switching to safe mode), so wait for the
> flag to clear.
> 
> Cc: José Roberto de Souza <jose.souza@intel.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_tc.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_tc.c
> b/drivers/gpu/drm/i915/intel_tc.c
> index 3fdcfa2bbaee..84e0c06877ec 100644
> --- a/drivers/gpu/drm/i915/intel_tc.c
> +++ b/drivers/gpu/drm/i915/intel_tc.c
> @@ -143,6 +143,10 @@ static void icl_tc_phy_set_safe_mode(struct
> intel_digital_port *dig_port,
>  		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
>  
>  	I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> +
> +	if (enable && wait_for(!icl_tc_phy_status_complete(dig_port),
> 10))
> +		DRM_DEBUG_DRIVER("Port %s: PHY complete clear timed
> out\n",
> +				 tc_port_name(dev_priv, tc_port));

No mention in spec that we need to do that but it should not harm.

Reviewed-by: José Roberto de Souza <jose.souza@intel.com>

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

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 11/23] drm/i915: Handle the TCCOLD power-down event
  2019-06-04 14:58 ` [PATCH 11/23] drm/i915: Handle the TCCOLD power-down event Imre Deak
@ 2019-06-07 21:41   ` Souza, Jose
  2019-06-08 17:31     ` Imre Deak
  0 siblings, 1 reply; 79+ messages in thread
From: Souza, Jose @ 2019-06-07 21:41 UTC (permalink / raw)
  To: intel-gfx, Deak, Imre

On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> Based on a recent BSpec update (Index/21750) we must handle the
> TCCOLD
> event associated with the DP-alt mode. We can detect this event by
> reading an invalid all-1s value from FIA registers.
> 
> After detecting TCCOLD we will:
> - fall back to TBT-alt mode when attempting to switch to DP-alt mode
> - conclude that nothing is connected during live status detection
> - WARN when already in unsafe mode, since then TCCOLD is unexpected
> 
> Cc: José Roberto de Souza <jose.souza@intel.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_tc.c | 23 +++++++++++++++++++++--
>  1 file changed, 21 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_tc.c
> b/drivers/gpu/drm/i915/intel_tc.c
> index 84e0c06877ec..d91381c0e87d 100644
> --- a/drivers/gpu/drm/i915/intel_tc.c
> +++ b/drivers/gpu/drm/i915/intel_tc.c
> @@ -49,6 +49,8 @@ u32 intel_tc_port_get_lane_info(struct
> intel_digital_port *dig_port)
>  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> >base.port);
>  	u32 lane_info = I915_READ(PORT_TX_DFLEXDPSP);
>  
> +	WARN_ON(lane_info == -1);

I would use 0xFFFFFFFF, it could cause a warning in some
compiler(comparing a signed with a unsigned).

Other than that:
Reviewed-by: José Roberto de Souza <jose.souza@intel.com>


> +
>  	return (lane_info & DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
>  	       DP_LANE_ASSIGNMENT_SHIFT(tc_port);
>  }
> @@ -107,6 +109,12 @@ static u32 tc_port_live_status_mask(struct
> intel_digital_port *dig_port)
>  	u32 val = I915_READ(PORT_TX_DFLEXDPSP);
>  	u32 mask = 0;
>  
> +	if (val == -1) {
> +		DRM_DEBUG_DRIVER("Port %s: PHY in TCCOLD, nothing
> connected\n",
> +				 tc_port_name(dev_priv, tc_port));
> +		return mask;
> +	}
> +
>  	if (val & TC_LIVE_STATE_TBT(tc_port))
>  		mask |= BIT(TC_PORT_TBT_ALT);
>  	if (val & TC_LIVE_STATE_TC(tc_port))
> @@ -131,13 +139,21 @@ static bool icl_tc_phy_status_complete(struct
> intel_digital_port *dig_port)
>  	       DP_PHY_MODE_STATUS_COMPLETED(tc_port);
>  }
>  
> -static void icl_tc_phy_set_safe_mode(struct intel_digital_port
> *dig_port,
> +static bool icl_tc_phy_set_safe_mode(struct intel_digital_port
> *dig_port,
>  				     bool enable)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dig_port-
> >base.base.dev);
>  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> >base.port);
>  	u32 val = I915_READ(PORT_TX_DFLEXDPCSSS);
>  
> +	if (val == -1) {
> +		DRM_DEBUG_DRIVER("Port %s: PHY in TCCOLD, can't set
> safe-mode to %s\n",
> +				 tc_port_name(dev_priv, tc_port),
> +				 enableddisabled(enable));
> +
> +		return false;
> +	}
> +
>  	val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
>  	if (!enable)
>  		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> @@ -147,6 +163,8 @@ static void icl_tc_phy_set_safe_mode(struct
> intel_digital_port *dig_port,
>  	if (enable && wait_for(!icl_tc_phy_status_complete(dig_port),
> 10))
>  		DRM_DEBUG_DRIVER("Port %s: PHY complete clear timed
> out\n",
>  				 tc_port_name(dev_priv, tc_port));
> +
> +	return true;
>  }
>  
>  /*
> @@ -187,7 +205,8 @@ static bool icl_tc_phy_connect(struct
> intel_digital_port *dig_port)
>  		return false;
>  	}
>  
> -	icl_tc_phy_set_safe_mode(dig_port, false);
> +	if (!icl_tc_phy_set_safe_mode(dig_port, false))
> +		return false;
>  
>  	if (dig_port->tc_mode == TC_PORT_LEGACY)
>  		return true;
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 12/23] drm/i915: Sanitize the TypeC connect/detect sequences
  2019-06-04 14:58 ` [PATCH 12/23] drm/i915: Sanitize the TypeC connect/detect sequences Imre Deak
@ 2019-06-07 22:15   ` Souza, Jose
  2019-06-08 17:40     ` Imre Deak
  0 siblings, 1 reply; 79+ messages in thread
From: Souza, Jose @ 2019-06-07 22:15 UTC (permalink / raw)
  To: intel-gfx, Deak, Imre; +Cc: Zanoni, Paulo R

On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> Make the order during detection more consistent: first reset the
> TypeC
> port mode if needed (adding new helpers for this), then detect any
> connected sink.
> 
> To check if a port mode reset is needed determine first the target
> port
> mode based on the live status if a sink is already connected or the
> PHY status complete flag otherwise.
> 
> Add a WARN in legacy mode if unexpectedly we can't set the unsafe
> mode
> or if the FIA doesn't provide the 4 lanes required.
> 
> Cc: José Roberto de Souza <jose.souza@intel.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_tc.c | 104 +++++++++++++++---------------
> --
>  1 file changed, 50 insertions(+), 54 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_tc.c
> b/drivers/gpu/drm/i915/intel_tc.c
> index d91381c0e87d..9832e2ddb92e 100644
> --- a/drivers/gpu/drm/i915/intel_tc.c
> +++ b/drivers/gpu/drm/i915/intel_tc.c
> @@ -188,43 +188,46 @@ static bool icl_tc_phy_set_safe_mode(struct
> intel_digital_port *dig_port,
>   * will require a lot of coordination with user space and thorough
> testing for
>   * the extra possible cases.
>   */
> -static bool icl_tc_phy_connect(struct intel_digital_port *dig_port)
> +static void icl_tc_phy_connect(struct intel_digital_port *dig_port)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dig_port-
> >base.base.dev);
>  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> >base.port);
> -	u32 live_status_mask;
> -
> -	if (dig_port->tc_mode != TC_PORT_LEGACY &&
> -	    dig_port->tc_mode != TC_PORT_DP_ALT)
> -		return true;
>  
>  	if (!icl_tc_phy_status_complete(dig_port)) {
>  		DRM_DEBUG_KMS("Port %s: PHY not ready\n",
>  			      tc_port_name(dev_priv, tc_port));
> -		WARN_ON(dig_port->tc_legacy_port);
> -		return false;
> +		goto out_set_tbt_alt_mode;
>  	}
>  
> -	if (!icl_tc_phy_set_safe_mode(dig_port, false))
> -		return false;
> +	if (!icl_tc_phy_set_safe_mode(dig_port, false) &&
> +	    !WARN_ON(dig_port->tc_legacy_port))
> +		goto out_set_tbt_alt_mode;
>  
> -	if (dig_port->tc_mode == TC_PORT_LEGACY)
> -		return true;
> +	if (dig_port->tc_legacy_port) {
> +		WARN_ON(intel_tc_port_fia_max_lane_count(dig_port) !=
> 4);
> +		dig_port->tc_mode = TC_PORT_LEGACY;
>  
> -	live_status_mask = tc_port_live_status_mask(dig_port);
> +		return;
> +	}
>  
>  	/*
>  	 * Now we have to re-check the live state, in case the port
> recently
>  	 * became disconnected. Not necessary for legacy mode.
>  	 */
> -	if (!(live_status_mask & BIT(TC_PORT_DP_ALT))) {
> +	if (!(tc_port_live_status_mask(dig_port) &
> BIT(TC_PORT_DP_ALT))) {
>  		DRM_DEBUG_KMS("Port %s: PHY sudden disconnect\n",
>  			      tc_port_name(dev_priv, tc_port));
> -		icl_tc_phy_disconnect(dig_port);
> -		return false;
> +		goto out_set_safe_mode;
>  	}
>  
> -	return true;
> +	dig_port->tc_mode = TC_PORT_DP_ALT;
> +
> +	return;
> +
> +out_set_safe_mode:
> +	icl_tc_phy_set_safe_mode(dig_port, true);
> +out_set_tbt_alt_mode:
> +	dig_port->tc_mode = TC_PORT_TBT_ALT;
>  }
>  
>  /*
> @@ -233,9 +236,6 @@ static bool icl_tc_phy_connect(struct
> intel_digital_port *dig_port)
>   */
>  void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
>  {
> -	struct drm_i915_private *dev_priv = to_i915(dig_port-
> >base.base.dev);
> -	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> >base.port);
> -
>  	switch (dig_port->tc_mode) {
>  	case TC_PORT_LEGACY:
>  	case TC_PORT_DP_ALT:
> @@ -248,31 +248,41 @@ void icl_tc_phy_disconnect(struct
> intel_digital_port *dig_port)
>  	default:
>  		MISSING_CASE(dig_port->tc_mode);
>  	}
> -
> -	DRM_DEBUG_KMS("Port %s: mode %s disconnected\n",
> -		      tc_port_name(dev_priv, tc_port),
> -		      tc_port_mode_name(dig_port->tc_mode));
>  }
>  
> -static void icl_update_tc_port_type(struct drm_i915_private
> *dev_priv,
> -				    struct intel_digital_port
> *intel_dig_port,
> -				    u32 live_status_mask)
> +static enum tc_port_mode
> +intel_tc_port_get_target_mode(struct intel_digital_port *dig_port)
>  {
> -	enum port port = intel_dig_port->base.port;
> -	enum tc_port_mode old_mode = intel_dig_port->tc_mode;
> +	u32 live_status_mask = tc_port_live_status_mask(dig_port);
>  
> -	if (!live_status_mask)
> -		return;
> +	if (live_status_mask)
> +		return fls(live_status_mask) - 1;
> +
> +	return icl_tc_phy_status_complete(dig_port) &&
> +	       dig_port->tc_legacy_port ? TC_PORT_LEGACY :
> +					  TC_PORT_TBT_ALT;

This will return 0 or 1, never TC_PORT_LEGACY(2) because of the "&&".


-TOOMANYREFACTORS
Staring to love again huge patches :P

> +}
>  
> -	intel_dig_port->tc_mode = fls(live_status_mask) - 1;
> +static void intel_tc_port_reset_mode(struct intel_digital_port
> *dig_port)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port-
> >base.base.dev);
> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> >base.port);
> +	enum tc_port_mode old_tc_mode = dig_port->tc_mode;
>  
> -	if (old_mode != intel_dig_port->tc_mode)
> -		DRM_DEBUG_KMS("Port %s: port has mode %s\n",
> -			      tc_port_name(dev_priv,
> -					   intel_port_to_tc(dev_priv,
> port)),
> -			      tc_port_mode_name(intel_dig_port-
> >tc_mode));
> +	icl_tc_phy_disconnect(dig_port);
> +	icl_tc_phy_connect(dig_port);
> +
> +	DRM_DEBUG_KMS("Port %s: TC port mode reset (%s -> %s)\n",
> +		      tc_port_name(dev_priv, tc_port),
> +		      tc_port_mode_name(old_tc_mode),
> +		      tc_port_mode_name(dig_port->tc_mode));
>  }
>  
> +static bool
> +intel_tc_port_needs_reset(struct intel_digital_port *dig_port)
> +{
> +	return intel_tc_port_get_target_mode(dig_port) != dig_port-
> >tc_mode;
> +}
>  
>  /*
>   * The type-C ports are different because even when they are
> connected, they may
> @@ -286,23 +296,9 @@ static void icl_update_tc_port_type(struct
> drm_i915_private *dev_priv,
>   */
>  bool intel_tc_port_connected(struct intel_digital_port *dig_port)
>  {
> -	struct drm_i915_private *dev_priv = to_i915(dig_port-
> >base.base.dev);
> -	u32 live_status_mask = tc_port_live_status_mask(dig_port);
> +	if (intel_tc_port_needs_reset(dig_port))
> +		intel_tc_port_reset_mode(dig_port);
>  
> -	/*
> -	 * The spec says we shouldn't be using the ISR bits for
> detecting
> -	 * between TC and TBT. We should use DFLEXDPSP.
> -	 */
> -	if (!live_status_mask && !dig_port->tc_legacy_port) {
> -		icl_tc_phy_disconnect(dig_port);
> -
> -		return false;
> -	}
> -
> -	icl_update_tc_port_type(dev_priv, dig_port, live_status_mask);
> -	if (!icl_tc_phy_connect(dig_port))
> -		return false;
> -
> -	return true;
> +	return tc_port_live_status_mask(dig_port) & BIT(dig_port-
> >tc_mode);
>  }
>  
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 13/23] drm/i915: Fix the TypeC port mode sanitization during loading/resume
  2019-06-04 14:58 ` [PATCH 13/23] drm/i915: Fix the TypeC port mode sanitization during loading/resume Imre Deak
@ 2019-06-07 22:39   ` Souza, Jose
  2019-06-08 17:50     ` Imre Deak
  0 siblings, 1 reply; 79+ messages in thread
From: Souza, Jose @ 2019-06-07 22:39 UTC (permalink / raw)
  To: intel-gfx, Deak, Imre; +Cc: Zanoni, Paulo R

On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> For using the correct AUX power domains we have to sanitize the TypeC
> port mode early, so move that before encoder sanitization. To do this
> properly read out the actual port mode instead of just relying on the
> VBT legacy port flag (which can be incorrect).
> 
> We also verify that the PHY is connected as expected if the port is
> active. In case the port is inactive we connect the PHY in case of a
> legacy port - as we did so far. The PHY will be connected during
> detection for DP-alt mode - as it was done so far. For TBT-alt mode
> nothing needs to be done to connect the PHY.
> 
> Cc: José Roberto de Souza <jose.souza@intel.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_ddi.c     | 16 +-----
>  drivers/gpu/drm/i915/intel_display.c | 10 ++++
>  drivers/gpu/drm/i915/intel_dp_mst.h  |  8 ++-
>  drivers/gpu/drm/i915/intel_tc.c      | 83
> ++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_tc.h      |  2 +
>  5 files changed, 103 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c
> b/drivers/gpu/drm/i915/intel_ddi.c
> index d236839bee19..2bc3b4f2c9a5 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -3918,17 +3918,6 @@ static void intel_ddi_encoder_suspend(struct
> intel_encoder *encoder)
>  		icl_tc_phy_disconnect(dig_port);
>  }
>  
> -static void intel_ddi_encoder_reset(struct drm_encoder *drm_encoder)
> -{
> -	struct intel_digital_port *dig_port =
> enc_to_dig_port(drm_encoder);
> -	struct drm_i915_private *i915 = to_i915(drm_encoder->dev);
> -
> -	if (intel_port_is_tc(i915, dig_port->base.port))
> -		intel_digital_port_connected(&dig_port->base);
> -
> -	intel_dp_encoder_reset(drm_encoder);
> -}
> -
>  static void intel_ddi_encoder_destroy(struct drm_encoder *encoder)
>  {
>  	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
> @@ -3944,7 +3933,7 @@ static void intel_ddi_encoder_destroy(struct
> drm_encoder *encoder)
>  }
>  
>  static const struct drm_encoder_funcs intel_ddi_funcs = {
> -	.reset = intel_ddi_encoder_reset,
> +	.reset = intel_dp_encoder_reset,
>  	.destroy = intel_ddi_encoder_destroy,
>  };
>  
> @@ -4309,9 +4298,6 @@ void intel_ddi_init(struct drm_i915_private
> *dev_priv, enum port port)
>  
>  	intel_infoframe_init(intel_dig_port);
>  
> -	if (intel_port_is_tc(dev_priv, port))
> -		intel_digital_port_connected(intel_encoder);
> -
>  	return;
>  
>  err:
> diff --git a/drivers/gpu/drm/i915/intel_display.c
> b/drivers/gpu/drm/i915/intel_display.c
> index 0e425a6eebf3..91d18cd0371c 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -75,6 +75,7 @@
>  #include "intel_sdvo.h"
>  #include "intel_sideband.h"
>  #include "intel_sprite.h"
> +#include "intel_tc.h"
>  #include "intel_tv.h"
>  #include "intel_vdsc.h"
>  
> @@ -16683,6 +16684,15 @@ intel_modeset_setup_hw_state(struct
> drm_device *dev,
>  	intel_modeset_readout_hw_state(dev);
>  
>  	/* HW state is read out, now we need to sanitize this mess. */
> +
> +	/* Sanitize the TypeC port mode upfront, encoders depend on
> this */
> +	for_each_intel_encoder(dev, encoder) {
> +		/* We need to sanitize only the MST primary port. */
> +		if (encoder->type != INTEL_OUTPUT_DP_MST &&
> +		    intel_port_is_tc(dev_priv, encoder->port))
> +			intel_tc_port_sanitize(enc_to_dig_port(&encoder
> ->base));
> +	}
> +
>  	get_encoder_power_domains(dev_priv);
>  
>  	if (HAS_PCH_IBX(dev_priv))
> diff --git a/drivers/gpu/drm/i915/intel_dp_mst.h
> b/drivers/gpu/drm/i915/intel_dp_mst.h
> index 1470c6e0514b..6754c211205a 100644
> --- a/drivers/gpu/drm/i915/intel_dp_mst.h
> +++ b/drivers/gpu/drm/i915/intel_dp_mst.h
> @@ -6,9 +6,15 @@
>  #ifndef __INTEL_DP_MST_H__
>  #define __INTEL_DP_MST_H__
>  
> -struct intel_digital_port;
> +#include "intel_drv.h"
>  
>  int intel_dp_mst_encoder_init(struct intel_digital_port
> *intel_dig_port, int conn_id);
>  void intel_dp_mst_encoder_cleanup(struct intel_digital_port
> *intel_dig_port);
> +static inline int
> +intel_dp_mst_encoder_active_links(struct intel_digital_port
> *intel_dig_port)
> +{
> +	return intel_dig_port->dp.active_mst_links;
> +}
> +
>  
>  #endif /* __INTEL_DP_MST_H__ */
> diff --git a/drivers/gpu/drm/i915/intel_tc.c
> b/drivers/gpu/drm/i915/intel_tc.c
> index 9832e2ddb92e..9ebf25d7931c 100644
> --- a/drivers/gpu/drm/i915/intel_tc.c
> +++ b/drivers/gpu/drm/i915/intel_tc.c
> @@ -3,6 +3,7 @@
>   * Copyright © 2019 Intel Corporation
>   */
>  #include "intel_display.h"
> +#include "intel_dp_mst.h"
>  #include "i915_drv.h"
>  #include "intel_tc.h"
>  
> @@ -167,6 +168,15 @@ static bool icl_tc_phy_set_safe_mode(struct
> intel_digital_port *dig_port,
>  	return true;
>  }
>  
> +static bool icl_tc_phy_is_in_safe_mode(struct intel_digital_port
> *dig_port)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port-
> >base.base.dev);
> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> >base.port);
> +
> +	return !(I915_READ(PORT_TX_DFLEXDPCSSS) &
> +		 DP_PHY_MODE_STATUS_NOT_SAFE(tc_port));
> +}
> +
>  /*
>   * This function implements the first part of the Connect Flow
> described by our
>   * specification, Gen11 TypeC Programming chapter. The rest of the
> flow (reading
> @@ -250,6 +260,49 @@ void icl_tc_phy_disconnect(struct
> intel_digital_port *dig_port)
>  	}
>  }
>  
> +static bool icl_tc_phy_is_connected(struct intel_digital_port
> *dig_port)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port-
> >base.base.dev);
> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> >base.port);
> +
> +	if (!icl_tc_phy_status_complete(dig_port)) {
> +		DRM_DEBUG_KMS("Port %s: PHY status not complete\n",
> +			      tc_port_name(dev_priv, tc_port));
> +		return dig_port->tc_mode == TC_PORT_TBT_ALT;
> +	}
> +
> +	if (icl_tc_phy_is_in_safe_mode(dig_port)) {
> +		DRM_DEBUG_KMS("Port %s: PHY still in safe mode\n",
> +			      tc_port_name(dev_priv, tc_port));
> +
> +		return false;
> +	}
> +
> +	return dig_port->tc_mode == TC_PORT_DP_ALT ||
> +	       dig_port->tc_mode == TC_PORT_LEGACY;
> +}
> +
> +static enum tc_port_mode
> +intel_tc_port_get_current_mode(struct intel_digital_port *dig_port)
> +{
> +	u32 live_status_mask = tc_port_live_status_mask(dig_port);
> +	bool in_safe_mode = icl_tc_phy_is_in_safe_mode(dig_port);
> +	enum tc_port_mode mode;
> +
> +	if (in_safe_mode ||
> WARN_ON(!icl_tc_phy_status_complete(dig_port)))
> +		return TC_PORT_TBT_ALT;
> +
> +	mode = dig_port->tc_legacy_port ? TC_PORT_LEGACY :
> TC_PORT_DP_ALT;
> +	if (live_status_mask) {
> +		enum tc_port_mode live_mode = fls(live_status_mask) -
> 1;
> +
> +		if (!WARN_ON(live_mode == TC_PORT_TBT_ALT))
> +			mode = live_mode;
> +	}
> +
> +	return mode;
> +}
> +
>  static enum tc_port_mode
>  intel_tc_port_get_target_mode(struct intel_digital_port *dig_port)
>  {
> @@ -278,6 +331,36 @@ static void intel_tc_port_reset_mode(struct
> intel_digital_port *dig_port)
>  		      tc_port_mode_name(dig_port->tc_mode));
>  }
>  
> +void intel_tc_port_sanitize(struct intel_digital_port *dig_port)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port-
> >base.base.dev);
> +	struct intel_encoder *encoder = &dig_port->base;
> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, encoder-
> >port);
> +	int active_links = 0;
> +
> +	dig_port->tc_mode = intel_tc_port_get_current_mode(dig_port);
> +	if (dig_port->dp.is_mst)
> +		active_links =
> intel_dp_mst_encoder_active_links(dig_port);
> +	else if (encoder->base.crtc)
> +		active_links = to_intel_crtc(encoder->base.crtc)-
> >active;
> +
> +	if (active_links) {
> +		if (!icl_tc_phy_is_connected(dig_port))
> +			DRM_DEBUG_DRIVER("Port %s: PHY disconnected
> with %d active link(s)\n",
> +					 tc_port_name(dev_priv,
> tc_port),
> +					 active_links);
> +		goto out;

And then probe sequences will take care of call
intel_digital_port_connected() to reset TC state. 

> +	}
> +
> +	if (dig_port->tc_legacy_port)
> +		icl_tc_phy_connect(dig_port);
> +
> +out:
> +	DRM_DEBUG_DRIVER("Port %s: sanitize mode (%s)\n",
> +			 tc_port_name(dev_priv, tc_port),
> +			 tc_port_mode_name(dig_port->tc_mode));

Should be:

DRM_DEBUG_DRIVER()

I guess I missed this on previous patches too.


With that:
Reviewed-by: José Roberto de Souza <jose.souza@intel.com>


> +}
> +
>  static bool
>  intel_tc_port_needs_reset(struct intel_digital_port *dig_port)
>  {
> diff --git a/drivers/gpu/drm/i915/intel_tc.h
> b/drivers/gpu/drm/i915/intel_tc.h
> index e937f5326959..10f0f0d81ee4 100644
> --- a/drivers/gpu/drm/i915/intel_tc.h
> +++ b/drivers/gpu/drm/i915/intel_tc.h
> @@ -11,4 +11,6 @@ bool intel_tc_port_connected(struct
> intel_digital_port *dig_port);
>  u32 intel_tc_port_get_lane_info(struct intel_digital_port
> *dig_port);
>  int intel_tc_port_fia_max_lane_count(struct intel_digital_port
> *dig_port);
>  
> +void intel_tc_port_sanitize(struct intel_digital_port *dig_port);
> +
>  #endif /* __INTEL_TC_H__ */
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 15/23] drm/i915: Sanitize the TypeC FIA lane configuration decoding
  2019-06-04 14:58 ` [PATCH 15/23] drm/i915: Sanitize the TypeC FIA lane configuration decoding Imre Deak
@ 2019-06-07 22:49   ` Souza, Jose
  2019-06-18 16:39   ` Ville Syrjälä
  1 sibling, 0 replies; 79+ messages in thread
From: Souza, Jose @ 2019-06-07 22:49 UTC (permalink / raw)
  To: intel-gfx, Deak, Imre

On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> Use hex numbers, since that makes more sense when decoding a bit
> pattern.
> 
> No functional change.

Reviewed-by: José Roberto de Souza <jose.souza@intel.com>

> 
> Suggested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Animesh Manna <animesh.manna@intel.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_tc.c | 15 ++++++++-------
>  1 file changed, 8 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_tc.c
> b/drivers/gpu/drm/i915/intel_tc.c
> index fc0341dc50c5..4b2f525bc2a6 100644
> --- a/drivers/gpu/drm/i915/intel_tc.c
> +++ b/drivers/gpu/drm/i915/intel_tc.c
> @@ -72,15 +72,16 @@ int intel_tc_port_fia_max_lane_count(struct
> intel_digital_port *dig_port)
>  	switch (lane_info) {
>  	default:
>  		MISSING_CASE(lane_info);
> -	case 1:
> -	case 2:
> -	case 4:
> -	case 8:
> +		/* fall-through */
> +	case 0x1:
> +	case 0x2:
> +	case 0x4:
> +	case 0x8:
>  		return 1;
> -	case 3:
> -	case 12:
> +	case 0x3:
> +	case 0xc:
>  		return 2;
> -	case 15:
> +	case 0xf:
>  		return 4;
>  	}
>  }
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 23/23] drm/i915: WARN about invalid lane reversal in TBT-alt/DP-alt modes
  2019-06-04 14:58 ` [PATCH 23/23] drm/i915: WARN about invalid lane reversal in TBT-alt/DP-alt modes Imre Deak
@ 2019-06-08  0:13   ` Souza, Jose
  2019-06-08  0:25     ` Souza, Jose
  0 siblings, 1 reply; 79+ messages in thread
From: Souza, Jose @ 2019-06-08  0:13 UTC (permalink / raw)
  To: intel-gfx, Deak, Imre

On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> Lane reversal happens only in the FIA module for TBT-alt/DP-alt mode,
> so
> WARN if lane reversal is attempted at a different level. See the
> BSpec DDI_BUF_CTL register description.

Reviewed-by: José Roberto de Souza <jose.souza@intel.com>

> 
> Cc: Manasi Navare <manasi.d.navare@intel.com>
> Cc: José Roberto de Souza <jose.souza@intel.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_ddi.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c
> b/drivers/gpu/drm/i915/intel_ddi.c
> index 9c198f1a3a91..5f535f17d7b3 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -3591,6 +3591,8 @@ static void intel_ddi_set_fia_lane_count(struct
> intel_encoder *encoder,
>  	u32 val = I915_READ(PORT_TX_DFLEXDPMLE1);
>  	bool lane_reversal = dig_port->saved_port_bits &
> DDI_BUF_PORT_REVERSAL;
>  
> +	WARN_ON(lane_reversal && dig_port->tc_mode != TC_PORT_LEGACY);
> +
>  	val &= ~DFLEXDPMLE1_DPMLETC_MASK(tc_port);
>  	switch (pipe_config->lane_count) {
>  	case 1:
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 22/23] drm/i915: Remove unneeded disconnect in TypeC legacy port mode
  2019-06-04 14:58 ` [PATCH 22/23] drm/i915: Remove unneeded disconnect in TypeC legacy " Imre Deak
@ 2019-06-08  0:18   ` Souza, Jose
  0 siblings, 0 replies; 79+ messages in thread
From: Souza, Jose @ 2019-06-08  0:18 UTC (permalink / raw)
  To: intel-gfx, Deak, Imre

On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> Disconnecting the TypeC PHY when the port is in legacy mode is not
> necessary:
> - BSpec doesn't specify a disconnect sequence for legacy mode.
> - The use of the PHY is dedicated for the display in legacy mode.
> - We keep the PHY always connected during runtime as well in legacy
>   mode.
> 
> We disconnect the PHY when needed during a disabling modeset for the
> port, so we can also remove the disconnect call from the destroy
> hook.
> 

Reviewed-by: José Roberto de Souza <jose.souza@intel.com>

> Cc: José Roberto de Souza <jose.souza@intel.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_ddi.c | 21 +--------------------
>  drivers/gpu/drm/i915/intel_tc.c  |  4 +++-
>  drivers/gpu/drm/i915/intel_tc.h  |  2 --
>  3 files changed, 4 insertions(+), 23 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c
> b/drivers/gpu/drm/i915/intel_ddi.c
> index 138950941246..9c198f1a3a91 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -3941,31 +3941,12 @@ static int intel_ddi_compute_config(struct
> intel_encoder *encoder,
>  	return 0;
>  }
>  
> -static void intel_ddi_encoder_suspend(struct intel_encoder *encoder)
> -{
> -	struct intel_digital_port *dig_port = enc_to_dig_port(&encoder-
> >base);
> -
> -	intel_dp_encoder_suspend(encoder);
> -
> -	/*
> -	 * TODO: disconnect also from USB DP alternate mode once we
> have a
> -	 * way to handle the modeset restore in that mode during resume
> -	 * even if the sink has disappeared while being suspended.
> -	 */
> -	if (dig_port->tc_legacy_port)
> -		icl_tc_phy_disconnect(dig_port);
> -}
> -
>  static void intel_ddi_encoder_destroy(struct drm_encoder *encoder)
>  {
>  	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
> -	struct drm_i915_private *i915 = to_i915(encoder->dev);
>  
>  	intel_dp_encoder_flush_work(encoder);
>  
> -	if (intel_port_is_tc(i915, dig_port->base.port))
> -		icl_tc_phy_disconnect(dig_port);
> -
>  	drm_encoder_cleanup(encoder);
>  	kfree(dig_port);
>  }
> @@ -4254,7 +4235,7 @@ void intel_ddi_init(struct drm_i915_private
> *dev_priv, enum port port)
>  	intel_encoder->update_pipe = intel_ddi_update_pipe;
>  	intel_encoder->get_hw_state = intel_ddi_get_hw_state;
>  	intel_encoder->get_config = intel_ddi_get_config;
> -	intel_encoder->suspend = intel_ddi_encoder_suspend;
> +	intel_encoder->suspend = intel_dp_encoder_suspend;
>  	intel_encoder->get_power_domains = intel_ddi_get_power_domains;
>  	intel_encoder->type = INTEL_OUTPUT_DDI;
>  	intel_encoder->power_domain = intel_port_to_power_domain(port);
> diff --git a/drivers/gpu/drm/i915/intel_tc.c
> b/drivers/gpu/drm/i915/intel_tc.c
> index d807127ad5f1..29a59ce7f073 100644
> --- a/drivers/gpu/drm/i915/intel_tc.c
> +++ b/drivers/gpu/drm/i915/intel_tc.c
> @@ -245,10 +245,12 @@ static void icl_tc_phy_connect(struct
> intel_digital_port *dig_port,
>   * See the comment at the connect function. This implements the
> Disconnect
>   * Flow.
>   */
> -void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
> +static void icl_tc_phy_disconnect(struct intel_digital_port
> *dig_port)
>  {
>  	switch (dig_port->tc_mode) {
>  	case TC_PORT_LEGACY:
> +		/* Nothing to do, we never disconnect from legacy mode
> */
> +		break;
>  	case TC_PORT_DP_ALT:
>  		icl_tc_phy_set_safe_mode(dig_port, true);
>  		dig_port->tc_mode = TC_PORT_TBT_ALT;
> diff --git a/drivers/gpu/drm/i915/intel_tc.h
> b/drivers/gpu/drm/i915/intel_tc.h
> index 568844e1846f..6d7e813c082b 100644
> --- a/drivers/gpu/drm/i915/intel_tc.h
> +++ b/drivers/gpu/drm/i915/intel_tc.h
> @@ -5,8 +5,6 @@
>  #include <linux/mutex.h>
>  #include "intel_drv.h"
>  
> -void icl_tc_phy_disconnect(struct intel_digital_port *dig_port);
> -
>  bool intel_tc_port_connected(struct intel_digital_port *dig_port);
>  u32 intel_tc_port_get_lane_info(struct intel_digital_port
> *dig_port);
>  int intel_tc_port_fia_max_lane_count(struct intel_digital_port
> *dig_port);
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 23/23] drm/i915: WARN about invalid lane reversal in TBT-alt/DP-alt modes
  2019-06-08  0:13   ` Souza, Jose
@ 2019-06-08  0:25     ` Souza, Jose
  0 siblings, 0 replies; 79+ messages in thread
From: Souza, Jose @ 2019-06-08  0:25 UTC (permalink / raw)
  To: intel-gfx, Deak, Imre

On Fri, 2019-06-07 at 17:13 -0700, José Roberto de Souza wrote:
> On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> > Lane reversal happens only in the FIA module for TBT-alt/DP-alt
> > mode,
> > so
> > WARN if lane reversal is attempted at a different level. See the
> > BSpec DDI_BUF_CTL register description.
> 
> Reviewed-by: José Roberto de Souza <jose.souza@intel.com>

Hi Imre

Going to review the renaming after wednesday if no one does, please go
ahead and push the ones reviewed.

> 
> > Cc: Manasi Navare <manasi.d.navare@intel.com>
> > Cc: José Roberto de Souza <jose.souza@intel.com>
> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_ddi.c | 2 ++
> >  1 file changed, 2 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_ddi.c
> > b/drivers/gpu/drm/i915/intel_ddi.c
> > index 9c198f1a3a91..5f535f17d7b3 100644
> > --- a/drivers/gpu/drm/i915/intel_ddi.c
> > +++ b/drivers/gpu/drm/i915/intel_ddi.c
> > @@ -3591,6 +3591,8 @@ static void
> > intel_ddi_set_fia_lane_count(struct
> > intel_encoder *encoder,
> >  	u32 val = I915_READ(PORT_TX_DFLEXDPMLE1);
> >  	bool lane_reversal = dig_port->saved_port_bits &
> > DDI_BUF_PORT_REVERSAL;
> >  
> > +	WARN_ON(lane_reversal && dig_port->tc_mode != TC_PORT_LEGACY);
> > +
> >  	val &= ~DFLEXDPMLE1_DPMLETC_MASK(tc_port);
> >  	switch (pipe_config->lane_count) {
> >  	case 1:
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 02/23] drm/i915: Tune down WARNs about TBT AUX power well enabling
  2019-06-07 17:50   ` Souza, Jose
@ 2019-06-08 13:33     ` Imre Deak
  0 siblings, 0 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-08 13:33 UTC (permalink / raw)
  To: Souza, Jose; +Cc: intel-gfx

On Fri, Jun 07, 2019 at 08:50:34PM +0300, Souza, Jose wrote:
> On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> > The HW completion flag for the TBT AUX power well enabling/disabling
> > gets stuck if the firmware tears down the TBT DP tunnel before the
> > completion.
> > 
> > We shouldn't complain about the timeout, since it's expected to
> > happen
> > and doesn't cause further issues. We suppress the disabling timeout
> > already, do the same for enabling.
> 
> This was documented in spec?
> 
> > 
> > Cc: José Roberto de Souza <jose.souza@intel.com>
> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_display_power.c | 15 ++++++++++-----
> >  1 file changed, 10 insertions(+), 5 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_display_power.c
> > b/drivers/gpu/drm/i915/intel_display_power.c
> > index 278a7edc94f5..249a5fa55df6 100644
> > --- a/drivers/gpu/drm/i915/intel_display_power.c
> > +++ b/drivers/gpu/drm/i915/intel_display_power.c
> > @@ -268,11 +268,16 @@ static void
> > hsw_wait_for_power_well_enable(struct drm_i915_private *dev_priv,
> >  	int pw_idx = power_well->desc->hsw.idx;
> >  
> >  	/* Timeout for PW1:10 us, AUX:not specified, other PWs:20 us.
> > */
> > -	WARN_ON(intel_wait_for_register(&dev_priv->uncore,
> > -					regs->driver,
> > -					HSW_PWR_WELL_CTL_STATE(pw_idx),
> > -					HSW_PWR_WELL_CTL_STATE(pw_idx),
> > -					1));
> > +	if (intel_wait_for_register(&dev_priv->uncore,
> > +				    regs->driver,
> > +				    HSW_PWR_WELL_CTL_STATE(pw_idx),
> > +				    HSW_PWR_WELL_CTL_STATE(pw_idx),
> > +				    1)) {
> > +		DRM_DEBUG_KMS("%s forced off\n", power_well->desc-
> > >name);
> 
> Maybe "%s power well enable timeout"?

Yep, makes sense, will change this.

> Anyways we can fix that latter.
> 
> Reviewed-by: José Roberto de Souza <jose.souza@intel.com>
> 
> > +
> > +		/* An AUX timeout is expected if the TBT DP tunnel is
> > down. */
> > +		WARN_ON(!power_well->desc->hsw.is_tc_tbt);
> > +	}
> >  }
> >  
> >  static u32 hsw_power_well_requesters(struct drm_i915_private
> > *dev_priv,
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 04/23] drm/i915: Sanitize the terminology used for TypeC port modes
  2019-06-07 19:15   ` Souza, Jose
@ 2019-06-08 13:43     ` Imre Deak
  0 siblings, 0 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-08 13:43 UTC (permalink / raw)
  To: Souza, Jose; +Cc: Zanoni, Paulo R, intel-gfx

On Fri, Jun 07, 2019 at 10:15:12PM +0300, Souza, Jose wrote:
> On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> > 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.
> 
> There is, the default tc_mode value now is TC_PORT_TBT_ALT instead of
> TC_PORT_UNKNOWN.

That doesn't change the functionality. Before the change the two modes
were treated the same way; that fact motivated the change to remove
TC_PORT_UNKNOWN and just use TC_PORT_TBT_ALT instead, which I tried to
explain in the commit log.

> 
> With the change above:
> Reviewed-by: José Roberto de Souza <jose.souza@intel.com>
> 
> Also consider split this patch in two.

Makes sense to keep it as-is, based on keeping the
functionality as described above?

> > 
> > Cc: Animesh Manna <animesh.manna@intel.com>
> > Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > Cc: Anusha Srivatsa <anusha.srivatsa@intel.com>
> > Cc: José Roberto de Souza <jose.souza@intel.com>
> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_ddi.c      | 11 +++---
> >  drivers/gpu/drm/i915/intel_display.h  |  7 ++--
> >  drivers/gpu/drm/i915/intel_dp.c       |  2 +-
> >  drivers/gpu/drm/i915/intel_dpll_mgr.c |  2 +-
> >  drivers/gpu/drm/i915/intel_drv.h      |  2 +-
> >  drivers/gpu/drm/i915/intel_tc.c       | 48 +++++++++++------------
> > ----
> >  6 files changed, 31 insertions(+), 41 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_ddi.c
> > b/drivers/gpu/drm/i915/intel_ddi.c
> > index 5a1c98438375..a3574f14a3d0 100644
> > --- a/drivers/gpu/drm/i915/intel_ddi.c
> > +++ b/drivers/gpu/drm/i915/intel_ddi.c
> > @@ -2986,14 +2986,14 @@ static void icl_program_mg_dp_mode(struct
> > intel_digital_port *intel_dig_port)
> >  	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
> >  	u32 ln0, ln1, lane_info;
> >  
> > -	if (tc_port == PORT_TC_NONE || intel_dig_port->tc_type ==
> > TC_PORT_TBT)
> > +	if (intel_dig_port->tc_mode == TC_PORT_TBT_ALT)
> >  		return;
> >  
> >  	ln0 = I915_READ(MG_DP_MODE(0, port));
> >  	ln1 = I915_READ(MG_DP_MODE(1, port));
> >  
> > -	switch (intel_dig_port->tc_type) {
> > -	case TC_PORT_TYPEC:
> > +	switch (intel_dig_port->tc_mode) {
> > +	case TC_PORT_DP_ALT:
> >  		ln0 &= ~(MG_DP_MODE_CFG_DP_X1_MODE |
> > MG_DP_MODE_CFG_DP_X2_MODE);
> >  		ln1 &= ~(MG_DP_MODE_CFG_DP_X1_MODE |
> > MG_DP_MODE_CFG_DP_X2_MODE);
> >  
> > @@ -3036,7 +3036,7 @@ static void icl_program_mg_dp_mode(struct
> > intel_digital_port *intel_dig_port)
> >  		break;
> >  
> >  	default:
> > -		MISSING_CASE(intel_dig_port->tc_type);
> > +		MISSING_CASE(intel_dig_port->tc_mode);
> >  		return;
> >  	}
> >  
> > @@ -3630,8 +3630,7 @@ intel_ddi_pre_pll_enable(struct intel_encoder
> > *encoder,
> >  	 * Program the lane count for static/dynamic connections on
> > Type-C ports.
> >  	 * Skip this step for TBT.
> >  	 */
> > -	if (dig_port->tc_type == TC_PORT_UNKNOWN ||
> > -	    dig_port->tc_type == TC_PORT_TBT)
> > +	if (dig_port->tc_mode == TC_PORT_TBT_ALT)
> >  		return;
> >  
> >  	intel_ddi_set_fia_lane_count(encoder, crtc_state, port);
> > diff --git a/drivers/gpu/drm/i915/intel_display.h
> > b/drivers/gpu/drm/i915/intel_display.h
> > index ee6b8194a459..d296556ed82e 100644
> > --- a/drivers/gpu/drm/i915/intel_display.h
> > +++ b/drivers/gpu/drm/i915/intel_display.h
> > @@ -189,10 +189,9 @@ enum tc_port {
> >  	I915_MAX_TC_PORTS
> >  };
> >  
> > -enum tc_port_type {
> > -	TC_PORT_UNKNOWN = 0,
> > -	TC_PORT_TYPEC,
> > -	TC_PORT_TBT,
> > +enum tc_port_mode {
> > +	TC_PORT_TBT_ALT,
> > +	TC_PORT_DP_ALT,
> >  	TC_PORT_LEGACY,
> >  };
> >  
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c
> > b/drivers/gpu/drm/i915/intel_dp.c
> > index b69310bd9914..e1e27662aa6d 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -1175,7 +1175,7 @@ static u32 skl_get_aux_send_ctl(struct intel_dp
> > *intel_dp,
> >  	      DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(32) |
> >  	      DP_AUX_CH_CTL_SYNC_PULSE_SKL(32);
> >  
> > -	if (intel_dig_port->tc_type == TC_PORT_TBT)
> > +	if (intel_dig_port->tc_mode == TC_PORT_TBT_ALT)
> >  		ret |= DP_AUX_CH_CTL_TBT_IO;
> >  
> >  	return ret;
> > diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c
> > b/drivers/gpu/drm/i915/intel_dpll_mgr.c
> > index 69787f259677..f4787650a0d3 100644
> > --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
> > +++ b/drivers/gpu/drm/i915/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);
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h
> > b/drivers/gpu/drm/i915/intel_drv.h
> > index 0dcc03592d6e..30cd49dbd0d8 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -1225,7 +1225,7 @@ struct intel_digital_port {
> >  	enum aux_ch aux_ch;
> >  	enum intel_display_power_domain ddi_io_power_domain;
> >  	bool tc_legacy_port:1;
> > -	enum tc_port_type tc_type;
> > +	enum tc_port_mode tc_mode;
> >  
> >  	void (*write_infoframe)(struct intel_encoder *encoder,
> >  				const struct intel_crtc_state
> > *crtc_state,
> > diff --git a/drivers/gpu/drm/i915/intel_tc.c
> > b/drivers/gpu/drm/i915/intel_tc.c
> > index 7a1b5870945f..a3057c44bec6 100644
> > --- a/drivers/gpu/drm/i915/intel_tc.c
> > +++ b/drivers/gpu/drm/i915/intel_tc.c
> > @@ -6,19 +6,18 @@
> >  #include "i915_drv.h"
> >  #include "intel_tc.h"
> >  
> > -static const char *tc_type_name(enum tc_port_type type)
> > +static const char *tc_port_mode_name(enum tc_port_mode mode)
> >  {
> >  	static const char * const names[] = {
> > -		[TC_PORT_UNKNOWN] = "unknown",
> > +		[TC_PORT_TBT_ALT] = "tbt-alt",
> > +		[TC_PORT_DP_ALT] = "dp-alt",
> >  		[TC_PORT_LEGACY] = "legacy",
> > -		[TC_PORT_TYPEC] = "typec",
> > -		[TC_PORT_TBT] = "tbt",
> >  	};
> >  
> > -	if (WARN_ON(type >= ARRAY_SIZE(names)))
> > -		type = TC_PORT_UNKNOWN;
> > +	if (WARN_ON(mode >= ARRAY_SIZE(names)))
> > +		mode = TC_PORT_TBT_ALT;
> >  
> > -	return names[type];
> > +	return names[mode];
> >  }
> >  
> >  int intel_tc_port_fia_max_lane_count(struct intel_digital_port
> > *dig_port)
> > @@ -28,7 +27,7 @@ int intel_tc_port_fia_max_lane_count(struct
> > intel_digital_port *dig_port)
> >  	intel_wakeref_t wakeref;
> >  	u32 lane_info;
> >  
> > -	if (tc_port == PORT_TC_NONE || dig_port->tc_type !=
> > TC_PORT_TYPEC)
> > +	if (dig_port->tc_mode != TC_PORT_DP_ALT)
> >  		return 4;
> >  
> >  	lane_info = 0;
> > @@ -80,8 +79,8 @@ static bool icl_tc_phy_connect(struct
> > intel_digital_port *dig_port)
> >  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> > >base.port);
> >  	u32 val;
> >  
> > -	if (dig_port->tc_type != TC_PORT_LEGACY &&
> > -	    dig_port->tc_type != TC_PORT_TYPEC)
> > +	if (dig_port->tc_mode != TC_PORT_LEGACY &&
> > +	    dig_port->tc_mode != TC_PORT_DP_ALT)
> >  		return true;
> >  
> >  	val = I915_READ(PORT_TX_DFLEXDPPMS);
> > @@ -105,7 +104,7 @@ static bool icl_tc_phy_connect(struct
> > intel_digital_port *dig_port)
> >  	 * Now we have to re-check the live state, in case the port
> > recently
> >  	 * became disconnected. Not necessary for legacy mode.
> >  	 */
> > -	if (dig_port->tc_type == TC_PORT_TYPEC &&
> > +	if (dig_port->tc_mode == TC_PORT_DP_ALT &&
> >  	    !(I915_READ(PORT_TX_DFLEXDPSP) &
> > TC_LIVE_STATE_TC(tc_port))) {
> >  		DRM_DEBUG_KMS("TC PHY %d sudden disconnect.\n",
> > tc_port);
> >  		icl_tc_phy_disconnect(dig_port);
> > @@ -124,15 +123,12 @@ void icl_tc_phy_disconnect(struct
> > intel_digital_port *dig_port)
> >  	struct drm_i915_private *dev_priv = to_i915(dig_port-
> > >base.base.dev);
> >  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> > >base.port);
> >  
> > -	if (dig_port->tc_type == TC_PORT_UNKNOWN)
> > -		return;
> > -
> >  	/*
> >  	 * TBT disconnection flow is read the live status, what was
> > done in
> >  	 * caller.
> >  	 */
> > -	if (dig_port->tc_type == TC_PORT_TYPEC ||
> > -	    dig_port->tc_type == TC_PORT_LEGACY) {
> > +	if (dig_port->tc_mode == TC_PORT_DP_ALT ||
> > +	    dig_port->tc_mode == TC_PORT_LEGACY) {
> >  		u32 val;
> >  
> >  		val = I915_READ(PORT_TX_DFLEXDPCSSS);
> > @@ -142,9 +138,9 @@ void icl_tc_phy_disconnect(struct
> > intel_digital_port *dig_port)
> >  
> >  	DRM_DEBUG_KMS("Port %c TC type %s disconnected\n",
> >  		      port_name(dig_port->base.port),
> > -		      tc_type_name(dig_port->tc_type));
> > +		      tc_port_mode_name(dig_port->tc_mode));
> >  
> > -	dig_port->tc_type = TC_PORT_UNKNOWN;
> > +	dig_port->tc_mode = TC_PORT_TBT_ALT;
> >  }
> >  
> >  static void icl_update_tc_port_type(struct drm_i915_private
> > *dev_priv,
> > @@ -152,26 +148,22 @@ static void icl_update_tc_port_type(struct
> > drm_i915_private *dev_priv,
> >  				    bool is_legacy, bool is_typec, bool
> > is_tbt)
> >  {
> >  	enum port port = intel_dig_port->base.port;
> > -	enum tc_port_type old_type = intel_dig_port->tc_type;
> > +	enum tc_port_mode old_mode = intel_dig_port->tc_mode;
> >  
> >  	WARN_ON(is_legacy + is_typec + is_tbt != 1);
> >  
> >  	if (is_legacy)
> > -		intel_dig_port->tc_type = TC_PORT_LEGACY;
> > +		intel_dig_port->tc_mode = TC_PORT_LEGACY;
> >  	else if (is_typec)
> > -		intel_dig_port->tc_type = TC_PORT_TYPEC;
> > +		intel_dig_port->tc_mode = TC_PORT_DP_ALT;
> >  	else if (is_tbt)
> > -		intel_dig_port->tc_type = TC_PORT_TBT;
> > +		intel_dig_port->tc_mode = TC_PORT_TBT_ALT;
> >  	else
> >  		return;
> >  
> > -	/* Types are not supposed to be changed at runtime. */
> > -	WARN_ON(old_type != TC_PORT_UNKNOWN &&
> > -		old_type != intel_dig_port->tc_type);
> > -
> > -	if (old_type != intel_dig_port->tc_type)
> > +	if (old_mode != intel_dig_port->tc_mode)
> >  		DRM_DEBUG_KMS("Port %c has TC type %s\n",
> > port_name(port),
> > -			      tc_type_name(intel_dig_port->tc_type));
> > +			      tc_port_mode_name(intel_dig_port-
> > >tc_mode));
> >  }
> >  
> >  
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 06/23] drm/i915: Fix the TBT AUX power well enabling
  2019-06-07 19:58   ` Souza, Jose
@ 2019-06-08 13:55     ` Imre Deak
  0 siblings, 0 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-08 13:55 UTC (permalink / raw)
  To: Souza, Jose; +Cc: intel-gfx

On Fri, Jun 07, 2019 at 10:58:41PM +0300, Souza, Jose wrote:
> On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> > Fix the mapping from a TBT AUX power well index to the DP_AUX_CH_CTL
> > register.
> > 
> > Fixes: c7375d9542f1 ("drm/i915: Configure AUX_CH_CTL when enabling
> > the AUX power domain")
> > Cc: José Roberto de Souza <jose.souza@intel.com>
> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_display_power.c | 11 +++++++++--
> >  1 file changed, 9 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_display_power.c
> > b/drivers/gpu/drm/i915/intel_display_power.c
> > index 249a5fa55df6..14cf04bf0bf4 100644
> > --- a/drivers/gpu/drm/i915/intel_display_power.c
> > +++ b/drivers/gpu/drm/i915/intel_display_power.c
> > @@ -442,16 +442,23 @@ icl_combo_phy_aux_power_well_disable(struct
> > drm_i915_private *dev_priv,
> >  #define ICL_AUX_PW_TO_CH(pw_idx)	\
> >  	((pw_idx) - ICL_PW_CTL_IDX_AUX_A + AUX_CH_A)
> >  
> > +#define ICL_TBT_AUX_PW_TO_CH(pw_idx)	\
> > +	((pw_idx) - ICL_PW_CTL_IDX_AUX_TBT1 + AUX_CH_C)
> > +
> >  static void
> >  icl_tc_phy_aux_power_well_enable(struct drm_i915_private *dev_priv,
> >  				 struct i915_power_well *power_well)
> >  {
> > -	enum aux_ch aux_ch = ICL_AUX_PW_TO_CH(power_well->desc-
> > >hsw.idx);
> > +	int pw_idx = power_well->desc->hsw.idx;
> > +	bool is_tbt = power_well->desc->hsw.is_tc_tbt;
> > +	enum aux_ch aux_ch;
> >  	u32 val;
> >  
> > +	aux_ch = is_tbt ? ICL_TBT_AUX_PW_TO_CH(pw_idx) :
> > +			  ICL_AUX_PW_TO_CH(pw_idx);
> 
> Matches
> 
> Reviewed-by: José Roberto de Souza <jose.souza@intel.com>
> 
> >  	val = I915_READ(DP_AUX_CH_CTL(aux_ch));
> >  	val &= ~DP_AUX_CH_CTL_TBT_IO;
> > -	if (power_well->desc->hsw.is_tc_tbt)
> > +	if (is_tbt)
> >  		val |= DP_AUX_CH_CTL_TBT_IO;
> 
> So this register needs to be set before the aux transaction?

Not only, based on bspec TypeC Programming (Index/21750) it needs to be
set as part of the connect sequence; so whenever you need to enable this
power well.

> 
> >  	I915_WRITE(DP_AUX_CH_CTL(aux_ch), val);
> >  
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 09/23] drm/i915: Factor out common parts from TypeC port handling functions
  2019-06-07 21:22   ` Souza, Jose
@ 2019-06-08 17:23     ` Imre Deak
  0 siblings, 0 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-08 17:23 UTC (permalink / raw)
  To: Souza, Jose; +Cc: intel-gfx, Zanoni, Paulo R

On Sat, Jun 08, 2019 at 12:22:46AM +0300, Souza, Jose wrote:
> On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> > Factor out helpers reading/parsing the TypeC specific registers,
> > making
> > current users of them clearer and letting us use them later.
> > 
> > While at it also:
> > - Simplify icl_tc_phy_connect() with an early return in legacy mode.
> > - Simplify the live status check using one bitmask for all HPD bits.
> > - Remove a micro-optimisation of the repeated safe-mode clearing.
> > - Make sure we fix the legacy port flag in all cases.
> > 
> > Except for the last two, no functional changes.
> > 
> > Cc: José Roberto de Souza <jose.souza@intel.com>
> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_ddi.c |   5 +-
> >  drivers/gpu/drm/i915/intel_tc.c  | 166 +++++++++++++++++++--------
> > ----
> >  drivers/gpu/drm/i915/intel_tc.h  |   1 +
> >  3 files changed, 103 insertions(+), 69 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_ddi.c
> > b/drivers/gpu/drm/i915/intel_ddi.c
> > index 8f223d48d562..d236839bee19 100644
> > --- a/drivers/gpu/drm/i915/intel_ddi.c
> > +++ b/drivers/gpu/drm/i915/intel_ddi.c
> > @@ -2983,7 +2983,6 @@ static void icl_program_mg_dp_mode(struct
> > intel_digital_port *intel_dig_port)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(intel_dig_port-
> > >base.base.dev);
> >  	enum port port = intel_dig_port->base.port;
> > -	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
> >  	u32 ln0, ln1, lane_info;
> >  
> >  	if (intel_dig_port->tc_mode == TC_PORT_TBT_ALT)
> > @@ -2997,9 +2996,7 @@ static void icl_program_mg_dp_mode(struct
> > intel_digital_port *intel_dig_port)
> >  		ln0 &= ~(MG_DP_MODE_CFG_DP_X1_MODE |
> > MG_DP_MODE_CFG_DP_X2_MODE);
> >  		ln1 &= ~(MG_DP_MODE_CFG_DP_X1_MODE |
> > MG_DP_MODE_CFG_DP_X2_MODE);
> >  
> > -		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
> > -			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
> > -			    DP_LANE_ASSIGNMENT_SHIFT(tc_port);
> > +		lane_info =
> > intel_tc_port_get_lane_info(intel_dig_port);
> >  
> >  		switch (lane_info) {
> >  		case 0x1:
> > diff --git a/drivers/gpu/drm/i915/intel_tc.c
> > b/drivers/gpu/drm/i915/intel_tc.c
> > index 07488235b67a..3fdcfa2bbaee 100644
> > --- a/drivers/gpu/drm/i915/intel_tc.c
> > +++ b/drivers/gpu/drm/i915/intel_tc.c
> > @@ -43,10 +43,19 @@ static const char *tc_port_mode_name(enum
> > tc_port_mode mode)
> >  	return names[mode];
> >  }
> >  
> > -int intel_tc_port_fia_max_lane_count(struct intel_digital_port
> > *dig_port)
> > +u32 intel_tc_port_get_lane_info(struct intel_digital_port *dig_port)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(dig_port-
> > >base.base.dev);
> >  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> > >base.port);
> > +	u32 lane_info = I915_READ(PORT_TX_DFLEXDPSP);
> > +
> > +	return (lane_info & DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
> > +	       DP_LANE_ASSIGNMENT_SHIFT(tc_port);
> > +}
> > +
> > +int intel_tc_port_fia_max_lane_count(struct intel_digital_port
> > *dig_port)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(dig_port-
> > >base.base.dev);
> >  	intel_wakeref_t wakeref;
> >  	u32 lane_info;
> >  
> > @@ -55,9 +64,7 @@ int intel_tc_port_fia_max_lane_count(struct
> > intel_digital_port *dig_port)
> >  
> >  	lane_info = 0;
> >  	with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE,
> > wakeref)
> > -		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
> > -			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
> > -				DP_LANE_ASSIGNMENT_SHIFT(tc_port);
> > +		lane_info = intel_tc_port_get_lane_info(dig_port);
> >  
> >  	switch (lane_info) {
> >  	default:
> > @@ -75,6 +82,69 @@ int intel_tc_port_fia_max_lane_count(struct
> > intel_digital_port *dig_port)
> >  	}
> >  }
> >  
> > +static void tc_port_fixup_legacy_flag(struct intel_digital_port
> > *dig_port,
> > +				      u32 live_status_mask)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(dig_port-
> > >base.base.dev);
> > +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> > >base.port);
> > +	u32 valid_hpd_mask = dig_port->tc_legacy_port ?
> > BIT(TC_PORT_LEGACY) :
> > +							~BIT(TC_PORT_LE
> > GACY);
> > +
> > +	if (!(live_status_mask & ~valid_hpd_mask))
> > +		return;
> > +
> > +	/* If live status mismatches the VBT flag, trust the live
> > status. */
> > +	DRM_ERROR("Port %s: live status %08x mismatches the legacy port
> > flag, fix flag\n",
> > +		  tc_port_name(dev_priv, tc_port), live_status_mask);
> > +
> > +	dig_port->tc_legacy_port = !dig_port->tc_legacy_port;
> > +}
> > +
> > +static u32 tc_port_live_status_mask(struct intel_digital_port
> > *dig_port)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(dig_port-
> > >base.base.dev);
> > +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> > >base.port);
> > +	u32 val = I915_READ(PORT_TX_DFLEXDPSP);
> > +	u32 mask = 0;
> > +
> > +	if (val & TC_LIVE_STATE_TBT(tc_port))
> > +		mask |= BIT(TC_PORT_TBT_ALT);
> > +	if (val & TC_LIVE_STATE_TC(tc_port))
> > +		mask |= BIT(TC_PORT_DP_ALT);
> > +
> > +	if (I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port))
> > +		mask |= BIT(TC_PORT_LEGACY);
> > +
> > +	/* The sink can be connected only in a single mode. */
> > +	if (!WARN_ON(hweight32(mask) > 1))
> > +		tc_port_fixup_legacy_flag(dig_port, mask);
> 
> The mask should be updated after the fixup

tc_port_fixup_legacy_flag() will only fix dig_port->tc_legacy_port based
on the mask, but mask itself will remain the same. (We trust the live
status based mask what is the HW's opinion about what kind of sink got
connected.)

If hweight32(mask)>1 we can't really do anything, it'd be some HW issue
which we haven't seen so far and that's handled anyway whenever
converting the mask to tc_mode by a priority scheme
(tc_mode=fls(mask)-1).

> 
> > +
> > +	return mask;
> > +}
> > +
> > +static bool icl_tc_phy_status_complete(struct intel_digital_port
> > *dig_port)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(dig_port-
> > >base.base.dev);
> > +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> > >base.port);
> > +
> > +	return I915_READ(PORT_TX_DFLEXDPPMS) &
> > +	       DP_PHY_MODE_STATUS_COMPLETED(tc_port);
> > +}
> > +
> > +static void icl_tc_phy_set_safe_mode(struct intel_digital_port
> > *dig_port,
> > +				     bool enable)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(dig_port-
> > >base.base.dev);
> > +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> > >base.port);
> > +	u32 val = I915_READ(PORT_TX_DFLEXDPCSSS);
> > +
> > +	val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> > +	if (!enable)
> > +		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> 
> Why complete remove the optimizations?
> You could do:
> 
> old_val = val = I915_READ(PORT_TX_DFLEXDPCSSS);
> val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> 
> if (!enable)
> 	val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> 
> if (val != old_val)
> 	I915_WRITE(PORT_TX_DFLEXDPCSSS, val);

You could optimize register writes where there is a requirement for it,
but there isn't any need for that here.

> > +
> > +	I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> > +}
> > +
> >  /*
> >   * This function implements the first part of the Connect Flow
> > described by our
> >   * specification, Gen11 TypeC Programming chapter. The rest of the
> > flow (reading
> > @@ -100,36 +170,31 @@ static bool icl_tc_phy_connect(struct
> > intel_digital_port *dig_port)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(dig_port-
> > >base.base.dev);
> >  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> > >base.port);
> > -	u32 val;
> > +	u32 live_status_mask;
> >  
> >  	if (dig_port->tc_mode != TC_PORT_LEGACY &&
> >  	    dig_port->tc_mode != TC_PORT_DP_ALT)
> >  		return true;
> >  
> > -	val = I915_READ(PORT_TX_DFLEXDPPMS);
> > -	if (!(val & DP_PHY_MODE_STATUS_COMPLETED(tc_port))) {
> > +	if (!icl_tc_phy_status_complete(dig_port)) {
> >  		DRM_DEBUG_KMS("Port %s: PHY not ready\n",
> >  			      tc_port_name(dev_priv, tc_port));
> >  		WARN_ON(dig_port->tc_legacy_port);
> >  		return false;
> >  	}
> >  
> > -	/*
> > -	 * This function may be called many times in a row without an
> > HPD event
> > -	 * in between, so try to avoid the write when we can.
> > -	 */
> > -	val = I915_READ(PORT_TX_DFLEXDPCSSS);
> > -	if (!(val & DP_PHY_MODE_STATUS_NOT_SAFE(tc_port))) {
> > -		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> > -		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> > -	}
> > +	icl_tc_phy_set_safe_mode(dig_port, false);
> > +
> > +	if (dig_port->tc_mode == TC_PORT_LEGACY)
> > +		return true;
> > +
> > +	live_status_mask = tc_port_live_status_mask(dig_port);
> >  
> >  	/*
> >  	 * Now we have to re-check the live state, in case the port
> > recently
> >  	 * became disconnected. Not necessary for legacy mode.
> >  	 */
> > -	if (dig_port->tc_mode == TC_PORT_DP_ALT &&
> > -	    !(I915_READ(PORT_TX_DFLEXDPSP) &
> > TC_LIVE_STATE_TC(tc_port))) {
> > +	if (!(live_status_mask & BIT(TC_PORT_DP_ALT))) {
> 
> When live status is TC_PORT_TBT_ALT it will cause the "sudden
> disconnect" to be printed each time

That can't really happen. There was first a DP-alt HPD, after which
icl_update_tc_port_type() set tc_mode = TC_PORT_DP_ALT. The only reason
for this live status check is to detect a quick unplug of the DP-alt
sink (as required by BSpec), after which live status will be 0 here.

> although icl_tc_phy_disconnect() will do nothing for TBT.

We'll have here tc_mode = TC_PORT_DP_ALT, in which case
icl_tc_phy_disconnect() will have to switch back to safe mode (since
above we switched to unsafe mode already).

Note that there is no change in behaviour here wrt. the current code.

> 
> >  		DRM_DEBUG_KMS("Port %s: PHY sudden disconnect\n",
> >  			      tc_port_name(dev_priv, tc_port));
> >  		icl_tc_phy_disconnect(dig_port);
> > @@ -148,44 +213,36 @@ void icl_tc_phy_disconnect(struct
> > intel_digital_port *dig_port)
> >  	struct drm_i915_private *dev_priv = to_i915(dig_port-
> > >base.base.dev);
> >  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> > >base.port);
> >  
> > -	/*
> > -	 * TBT disconnection flow is read the live status, what was
> > done in
> > -	 * caller.
> > -	 */
> > -	if (dig_port->tc_mode == TC_PORT_DP_ALT ||
> > -	    dig_port->tc_mode == TC_PORT_LEGACY) {
> > -		u32 val;
> > -
> > -		val = I915_READ(PORT_TX_DFLEXDPCSSS);
> > -		val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> > -		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
> > +	switch (dig_port->tc_mode) {
> > +	case TC_PORT_LEGACY:
> > +	case TC_PORT_DP_ALT:
> > +		icl_tc_phy_set_safe_mode(dig_port, true);
> > +		dig_port->tc_mode = TC_PORT_TBT_ALT;
> > +		break;
> > +	case TC_PORT_TBT_ALT:
> > +		/* Nothing to do, we stay in TBT-alt mode */
> > +		break;
> > +	default:
> > +		MISSING_CASE(dig_port->tc_mode);
> >  	}
> >  
> >  	DRM_DEBUG_KMS("Port %s: mode %s disconnected\n",
> >  		      tc_port_name(dev_priv, tc_port),
> >  		      tc_port_mode_name(dig_port->tc_mode));
> > -
> > -	dig_port->tc_mode = TC_PORT_TBT_ALT;
> >  }
> >  
> >  static void icl_update_tc_port_type(struct drm_i915_private
> > *dev_priv,
> >  				    struct intel_digital_port
> > *intel_dig_port,
> > -				    bool is_legacy, bool is_typec, bool
> > is_tbt)
> > +				    u32 live_status_mask)
> >  {
> >  	enum port port = intel_dig_port->base.port;
> >  	enum tc_port_mode old_mode = intel_dig_port->tc_mode;
> >  
> > -	WARN_ON(is_legacy + is_typec + is_tbt != 1);
> > -
> > -	if (is_legacy)
> > -		intel_dig_port->tc_mode = TC_PORT_LEGACY;
> > -	else if (is_typec)
> > -		intel_dig_port->tc_mode = TC_PORT_DP_ALT;
> > -	else if (is_tbt)
> > -		intel_dig_port->tc_mode = TC_PORT_TBT_ALT;
> > -	else
> > +	if (!live_status_mask)
> >  		return;
> >  
> > +	intel_dig_port->tc_mode = fls(live_status_mask) - 1;
> > +
> >  	if (old_mode != intel_dig_port->tc_mode)
> >  		DRM_DEBUG_KMS("Port %s: port has mode %s\n",
> >  			      tc_port_name(dev_priv,
> > @@ -207,40 +264,19 @@ static void icl_update_tc_port_type(struct
> > drm_i915_private *dev_priv,
> >  bool intel_tc_port_connected(struct intel_digital_port *dig_port)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(dig_port-
> > >base.base.dev);
> > -	enum port port = dig_port->base.port;
> > -	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
> > -	bool is_legacy, is_typec, is_tbt;
> > -	u32 dpsp;
> > -
> > -	/*
> > -	 * Complain if we got a legacy port HPD, but VBT didn't mark
> > the port as
> > -	 * legacy. Treat the port as legacy from now on.
> > -	 */
> > -	if (!dig_port->tc_legacy_port &&
> > -	    I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port)) {
> > -		DRM_ERROR("Port %s: VBT incorrectly claims port is not
> > TypeC legacy\n",
> > -			  tc_port_name(dev_priv, tc_port));
> > -		dig_port->tc_legacy_port = true;
> > -	}
> > -	is_legacy = dig_port->tc_legacy_port;
> > +	u32 live_status_mask = tc_port_live_status_mask(dig_port);
> >  
> >  	/*
> >  	 * The spec says we shouldn't be using the ISR bits for
> > detecting
> >  	 * between TC and TBT. We should use DFLEXDPSP.
> >  	 */
> > -	dpsp = I915_READ(PORT_TX_DFLEXDPSP);
> > -	is_typec = dpsp & TC_LIVE_STATE_TC(tc_port);
> > -	is_tbt = dpsp & TC_LIVE_STATE_TBT(tc_port);
> > -
> > -	if (!is_legacy && !is_typec && !is_tbt) {
> > +	if (!live_status_mask && !dig_port->tc_legacy_port) {
> 
> So now it will keep legacy port as unsafe even when disconnected.
> Maybe worth mention in commit message.

That is how it was also before, since above we had

	is_legacy = dig_port->tc_legacy_port

So no change in behaviour.

> 
> >  		icl_tc_phy_disconnect(dig_port);
> >  
> >  		return false;
> >  	}
> >  
> > -	icl_update_tc_port_type(dev_priv, dig_port, is_legacy,
> > is_typec,
> > -				is_tbt);
> > -
> > +	icl_update_tc_port_type(dev_priv, dig_port, live_status_mask);
> >  	if (!icl_tc_phy_connect(dig_port))
> >  		return false;
> >  
> > diff --git a/drivers/gpu/drm/i915/intel_tc.h
> > b/drivers/gpu/drm/i915/intel_tc.h
> > index 94c62ac4a162..e937f5326959 100644
> > --- a/drivers/gpu/drm/i915/intel_tc.h
> > +++ b/drivers/gpu/drm/i915/intel_tc.h
> > @@ -8,6 +8,7 @@ struct intel_digital_port;
> >  void icl_tc_phy_disconnect(struct intel_digital_port *dig_port);
> >  
> >  bool intel_tc_port_connected(struct intel_digital_port *dig_port);
> > +u32 intel_tc_port_get_lane_info(struct intel_digital_port
> > *dig_port);
> >  int intel_tc_port_fia_max_lane_count(struct intel_digital_port
> > *dig_port);
> >  
> >  #endif /* __INTEL_TC_H__ */
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 11/23] drm/i915: Handle the TCCOLD power-down event
  2019-06-07 21:41   ` Souza, Jose
@ 2019-06-08 17:31     ` Imre Deak
  0 siblings, 0 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-08 17:31 UTC (permalink / raw)
  To: Souza, Jose; +Cc: intel-gfx

On Sat, Jun 08, 2019 at 12:41:10AM +0300, Souza, Jose wrote:
> On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> > Based on a recent BSpec update (Index/21750) we must handle the
> > TCCOLD
> > event associated with the DP-alt mode. We can detect this event by
> > reading an invalid all-1s value from FIA registers.
> > 
> > After detecting TCCOLD we will:
> > - fall back to TBT-alt mode when attempting to switch to DP-alt mode
> > - conclude that nothing is connected during live status detection
> > - WARN when already in unsafe mode, since then TCCOLD is unexpected
> > 
> > Cc: José Roberto de Souza <jose.souza@intel.com>
> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_tc.c | 23 +++++++++++++++++++++--
> >  1 file changed, 21 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_tc.c
> > b/drivers/gpu/drm/i915/intel_tc.c
> > index 84e0c06877ec..d91381c0e87d 100644
> > --- a/drivers/gpu/drm/i915/intel_tc.c
> > +++ b/drivers/gpu/drm/i915/intel_tc.c
> > @@ -49,6 +49,8 @@ u32 intel_tc_port_get_lane_info(struct
> > intel_digital_port *dig_port)
> >  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> > >base.port);
> >  	u32 lane_info = I915_READ(PORT_TX_DFLEXDPSP);
> >  
> > +	WARN_ON(lane_info == -1);
> 
> I would use 0xFFFFFFFF, it could cause a warning in some
> compiler(comparing a signed with a unsigned).

Shouldn't cause any compiler warnings, since there is a conversion of
the types to a common type first, which is unsigned int in this case.
That's according to the C standard, so should be fine and it's a short
way to write an all-1s value, whatever is on the other side (u32 now,
but could be for instance u64).

> 
> Other than that:
> Reviewed-by: José Roberto de Souza <jose.souza@intel.com>
> 
> 
> > +
> >  	return (lane_info & DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
> >  	       DP_LANE_ASSIGNMENT_SHIFT(tc_port);
> >  }
> > @@ -107,6 +109,12 @@ static u32 tc_port_live_status_mask(struct
> > intel_digital_port *dig_port)
> >  	u32 val = I915_READ(PORT_TX_DFLEXDPSP);
> >  	u32 mask = 0;
> >  
> > +	if (val == -1) {
> > +		DRM_DEBUG_DRIVER("Port %s: PHY in TCCOLD, nothing
> > connected\n",
> > +				 tc_port_name(dev_priv, tc_port));
> > +		return mask;
> > +	}
> > +
> >  	if (val & TC_LIVE_STATE_TBT(tc_port))
> >  		mask |= BIT(TC_PORT_TBT_ALT);
> >  	if (val & TC_LIVE_STATE_TC(tc_port))
> > @@ -131,13 +139,21 @@ static bool icl_tc_phy_status_complete(struct
> > intel_digital_port *dig_port)
> >  	       DP_PHY_MODE_STATUS_COMPLETED(tc_port);
> >  }
> >  
> > -static void icl_tc_phy_set_safe_mode(struct intel_digital_port
> > *dig_port,
> > +static bool icl_tc_phy_set_safe_mode(struct intel_digital_port
> > *dig_port,
> >  				     bool enable)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(dig_port-
> > >base.base.dev);
> >  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> > >base.port);
> >  	u32 val = I915_READ(PORT_TX_DFLEXDPCSSS);
> >  
> > +	if (val == -1) {
> > +		DRM_DEBUG_DRIVER("Port %s: PHY in TCCOLD, can't set
> > safe-mode to %s\n",
> > +				 tc_port_name(dev_priv, tc_port),
> > +				 enableddisabled(enable));
> > +
> > +		return false;
> > +	}
> > +
> >  	val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> >  	if (!enable)
> >  		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
> > @@ -147,6 +163,8 @@ static void icl_tc_phy_set_safe_mode(struct
> > intel_digital_port *dig_port,
> >  	if (enable && wait_for(!icl_tc_phy_status_complete(dig_port),
> > 10))
> >  		DRM_DEBUG_DRIVER("Port %s: PHY complete clear timed
> > out\n",
> >  				 tc_port_name(dev_priv, tc_port));
> > +
> > +	return true;
> >  }
> >  
> >  /*
> > @@ -187,7 +205,8 @@ static bool icl_tc_phy_connect(struct
> > intel_digital_port *dig_port)
> >  		return false;
> >  	}
> >  
> > -	icl_tc_phy_set_safe_mode(dig_port, false);
> > +	if (!icl_tc_phy_set_safe_mode(dig_port, false))
> > +		return false;
> >  
> >  	if (dig_port->tc_mode == TC_PORT_LEGACY)
> >  		return true;
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 12/23] drm/i915: Sanitize the TypeC connect/detect sequences
  2019-06-07 22:15   ` Souza, Jose
@ 2019-06-08 17:40     ` Imre Deak
  0 siblings, 0 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-08 17:40 UTC (permalink / raw)
  To: Souza, Jose; +Cc: intel-gfx, Zanoni, Paulo R

On Sat, Jun 08, 2019 at 01:15:44AM +0300, Souza, Jose wrote:
> On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> > Make the order during detection more consistent: first reset the
> > TypeC
> > port mode if needed (adding new helpers for this), then detect any
> > connected sink.
> > 
> > To check if a port mode reset is needed determine first the target
> > port
> > mode based on the live status if a sink is already connected or the
> > PHY status complete flag otherwise.
> > 
> > Add a WARN in legacy mode if unexpectedly we can't set the unsafe
> > mode
> > or if the FIA doesn't provide the 4 lanes required.
> > 
> > Cc: José Roberto de Souza <jose.souza@intel.com>
> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_tc.c | 104 +++++++++++++++---------------
> > --
> >  1 file changed, 50 insertions(+), 54 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_tc.c
> > b/drivers/gpu/drm/i915/intel_tc.c
> > index d91381c0e87d..9832e2ddb92e 100644
> > --- a/drivers/gpu/drm/i915/intel_tc.c
> > +++ b/drivers/gpu/drm/i915/intel_tc.c
> > @@ -188,43 +188,46 @@ static bool icl_tc_phy_set_safe_mode(struct
> > intel_digital_port *dig_port,
> >   * will require a lot of coordination with user space and thorough
> > testing for
> >   * the extra possible cases.
> >   */
> > -static bool icl_tc_phy_connect(struct intel_digital_port *dig_port)
> > +static void icl_tc_phy_connect(struct intel_digital_port *dig_port)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(dig_port-
> > >base.base.dev);
> >  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> > >base.port);
> > -	u32 live_status_mask;
> > -
> > -	if (dig_port->tc_mode != TC_PORT_LEGACY &&
> > -	    dig_port->tc_mode != TC_PORT_DP_ALT)
> > -		return true;
> >  
> >  	if (!icl_tc_phy_status_complete(dig_port)) {
> >  		DRM_DEBUG_KMS("Port %s: PHY not ready\n",
> >  			      tc_port_name(dev_priv, tc_port));
> > -		WARN_ON(dig_port->tc_legacy_port);
> > -		return false;
> > +		goto out_set_tbt_alt_mode;
> >  	}
> >  
> > -	if (!icl_tc_phy_set_safe_mode(dig_port, false))
> > -		return false;
> > +	if (!icl_tc_phy_set_safe_mode(dig_port, false) &&
> > +	    !WARN_ON(dig_port->tc_legacy_port))
> > +		goto out_set_tbt_alt_mode;
> >  
> > -	if (dig_port->tc_mode == TC_PORT_LEGACY)
> > -		return true;
> > +	if (dig_port->tc_legacy_port) {
> > +		WARN_ON(intel_tc_port_fia_max_lane_count(dig_port) !=
> > 4);
> > +		dig_port->tc_mode = TC_PORT_LEGACY;
> >  
> > -	live_status_mask = tc_port_live_status_mask(dig_port);
> > +		return;
> > +	}
> >  
> >  	/*
> >  	 * Now we have to re-check the live state, in case the port
> > recently
> >  	 * became disconnected. Not necessary for legacy mode.
> >  	 */
> > -	if (!(live_status_mask & BIT(TC_PORT_DP_ALT))) {
> > +	if (!(tc_port_live_status_mask(dig_port) &
> > BIT(TC_PORT_DP_ALT))) {
> >  		DRM_DEBUG_KMS("Port %s: PHY sudden disconnect\n",
> >  			      tc_port_name(dev_priv, tc_port));
> > -		icl_tc_phy_disconnect(dig_port);
> > -		return false;
> > +		goto out_set_safe_mode;
> >  	}
> >  
> > -	return true;
> > +	dig_port->tc_mode = TC_PORT_DP_ALT;
> > +
> > +	return;
> > +
> > +out_set_safe_mode:
> > +	icl_tc_phy_set_safe_mode(dig_port, true);
> > +out_set_tbt_alt_mode:
> > +	dig_port->tc_mode = TC_PORT_TBT_ALT;
> >  }
> >  
> >  /*
> > @@ -233,9 +236,6 @@ static bool icl_tc_phy_connect(struct
> > intel_digital_port *dig_port)
> >   */
> >  void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
> >  {
> > -	struct drm_i915_private *dev_priv = to_i915(dig_port-
> > >base.base.dev);
> > -	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> > >base.port);
> > -
> >  	switch (dig_port->tc_mode) {
> >  	case TC_PORT_LEGACY:
> >  	case TC_PORT_DP_ALT:
> > @@ -248,31 +248,41 @@ void icl_tc_phy_disconnect(struct
> > intel_digital_port *dig_port)
> >  	default:
> >  		MISSING_CASE(dig_port->tc_mode);
> >  	}
> > -
> > -	DRM_DEBUG_KMS("Port %s: mode %s disconnected\n",
> > -		      tc_port_name(dev_priv, tc_port),
> > -		      tc_port_mode_name(dig_port->tc_mode));
> >  }
> >  
> > -static void icl_update_tc_port_type(struct drm_i915_private
> > *dev_priv,
> > -				    struct intel_digital_port
> > *intel_dig_port,
> > -				    u32 live_status_mask)
> > +static enum tc_port_mode
> > +intel_tc_port_get_target_mode(struct intel_digital_port *dig_port)
> >  {
> > -	enum port port = intel_dig_port->base.port;
> > -	enum tc_port_mode old_mode = intel_dig_port->tc_mode;
> > +	u32 live_status_mask = tc_port_live_status_mask(dig_port);
> >  
> > -	if (!live_status_mask)
> > -		return;
> > +	if (live_status_mask)
> > +		return fls(live_status_mask) - 1;
> > +
> > +	return icl_tc_phy_status_complete(dig_port) &&
> > +	       dig_port->tc_legacy_port ? TC_PORT_LEGACY :
> > +					  TC_PORT_TBT_ALT;
> 
> This will return 0 or 1, never TC_PORT_LEGACY(2) because of the "&&".

Nope, C operators precedence is first "&&" then "?:". Should be fine.

> -TOOMANYREFACTORS
> Staring to love again huge patches :P

Well all the previous refactorings should be easier to review, since
they don't change the functionality.

The hope was that the refactoring patches make the review of this one
- with functionality changes - easier to review.

> 
> > +}
> >  
> > -	intel_dig_port->tc_mode = fls(live_status_mask) - 1;
> > +static void intel_tc_port_reset_mode(struct intel_digital_port
> > *dig_port)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(dig_port-
> > >base.base.dev);
> > +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> > >base.port);
> > +	enum tc_port_mode old_tc_mode = dig_port->tc_mode;
> >  
> > -	if (old_mode != intel_dig_port->tc_mode)
> > -		DRM_DEBUG_KMS("Port %s: port has mode %s\n",
> > -			      tc_port_name(dev_priv,
> > -					   intel_port_to_tc(dev_priv,
> > port)),
> > -			      tc_port_mode_name(intel_dig_port-
> > >tc_mode));
> > +	icl_tc_phy_disconnect(dig_port);
> > +	icl_tc_phy_connect(dig_port);
> > +
> > +	DRM_DEBUG_KMS("Port %s: TC port mode reset (%s -> %s)\n",
> > +		      tc_port_name(dev_priv, tc_port),
> > +		      tc_port_mode_name(old_tc_mode),
> > +		      tc_port_mode_name(dig_port->tc_mode));
> >  }
> >  
> > +static bool
> > +intel_tc_port_needs_reset(struct intel_digital_port *dig_port)
> > +{
> > +	return intel_tc_port_get_target_mode(dig_port) != dig_port-
> > >tc_mode;
> > +}
> >  
> >  /*
> >   * The type-C ports are different because even when they are
> > connected, they may
> > @@ -286,23 +296,9 @@ static void icl_update_tc_port_type(struct
> > drm_i915_private *dev_priv,
> >   */
> >  bool intel_tc_port_connected(struct intel_digital_port *dig_port)
> >  {
> > -	struct drm_i915_private *dev_priv = to_i915(dig_port-
> > >base.base.dev);
> > -	u32 live_status_mask = tc_port_live_status_mask(dig_port);
> > +	if (intel_tc_port_needs_reset(dig_port))
> > +		intel_tc_port_reset_mode(dig_port);
> >  
> > -	/*
> > -	 * The spec says we shouldn't be using the ISR bits for
> > detecting
> > -	 * between TC and TBT. We should use DFLEXDPSP.
> > -	 */
> > -	if (!live_status_mask && !dig_port->tc_legacy_port) {
> > -		icl_tc_phy_disconnect(dig_port);
> > -
> > -		return false;
> > -	}
> > -
> > -	icl_update_tc_port_type(dev_priv, dig_port, live_status_mask);
> > -	if (!icl_tc_phy_connect(dig_port))
> > -		return false;
> > -
> > -	return true;
> > +	return tc_port_live_status_mask(dig_port) & BIT(dig_port-
> > >tc_mode);
> >  }
> >  
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 13/23] drm/i915: Fix the TypeC port mode sanitization during loading/resume
  2019-06-07 22:39   ` Souza, Jose
@ 2019-06-08 17:50     ` Imre Deak
  0 siblings, 0 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-08 17:50 UTC (permalink / raw)
  To: Souza, Jose; +Cc: intel-gfx, Zanoni, Paulo R

On Sat, Jun 08, 2019 at 01:39:36AM +0300, Souza, Jose wrote:
> On Tue, 2019-06-04 at 17:58 +0300, Imre Deak wrote:
> > For using the correct AUX power domains we have to sanitize the TypeC
> > port mode early, so move that before encoder sanitization. To do this
> > properly read out the actual port mode instead of just relying on the
> > VBT legacy port flag (which can be incorrect).
> > 
> > We also verify that the PHY is connected as expected if the port is
> > active. In case the port is inactive we connect the PHY in case of a
> > legacy port - as we did so far. The PHY will be connected during
> > detection for DP-alt mode - as it was done so far. For TBT-alt mode
> > nothing needs to be done to connect the PHY.
> > 
> > Cc: José Roberto de Souza <jose.souza@intel.com>
> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_ddi.c     | 16 +-----
> >  drivers/gpu/drm/i915/intel_display.c | 10 ++++
> >  drivers/gpu/drm/i915/intel_dp_mst.h  |  8 ++-
> >  drivers/gpu/drm/i915/intel_tc.c      | 83
> > ++++++++++++++++++++++++++++
> >  drivers/gpu/drm/i915/intel_tc.h      |  2 +
> >  5 files changed, 103 insertions(+), 16 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_ddi.c
> > b/drivers/gpu/drm/i915/intel_ddi.c
> > index d236839bee19..2bc3b4f2c9a5 100644
> > --- a/drivers/gpu/drm/i915/intel_ddi.c
> > +++ b/drivers/gpu/drm/i915/intel_ddi.c
> > @@ -3918,17 +3918,6 @@ static void intel_ddi_encoder_suspend(struct
> > intel_encoder *encoder)
> >  		icl_tc_phy_disconnect(dig_port);
> >  }
> >  
> > -static void intel_ddi_encoder_reset(struct drm_encoder *drm_encoder)
> > -{
> > -	struct intel_digital_port *dig_port =
> > enc_to_dig_port(drm_encoder);
> > -	struct drm_i915_private *i915 = to_i915(drm_encoder->dev);
> > -
> > -	if (intel_port_is_tc(i915, dig_port->base.port))
> > -		intel_digital_port_connected(&dig_port->base);
> > -
> > -	intel_dp_encoder_reset(drm_encoder);
> > -}
> > -
> >  static void intel_ddi_encoder_destroy(struct drm_encoder *encoder)
> >  {
> >  	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
> > @@ -3944,7 +3933,7 @@ static void intel_ddi_encoder_destroy(struct
> > drm_encoder *encoder)
> >  }
> >  
> >  static const struct drm_encoder_funcs intel_ddi_funcs = {
> > -	.reset = intel_ddi_encoder_reset,
> > +	.reset = intel_dp_encoder_reset,
> >  	.destroy = intel_ddi_encoder_destroy,
> >  };
> >  
> > @@ -4309,9 +4298,6 @@ void intel_ddi_init(struct drm_i915_private
> > *dev_priv, enum port port)
> >  
> >  	intel_infoframe_init(intel_dig_port);
> >  
> > -	if (intel_port_is_tc(dev_priv, port))
> > -		intel_digital_port_connected(intel_encoder);
> > -
> >  	return;
> >  
> >  err:
> > diff --git a/drivers/gpu/drm/i915/intel_display.c
> > b/drivers/gpu/drm/i915/intel_display.c
> > index 0e425a6eebf3..91d18cd0371c 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -75,6 +75,7 @@
> >  #include "intel_sdvo.h"
> >  #include "intel_sideband.h"
> >  #include "intel_sprite.h"
> > +#include "intel_tc.h"
> >  #include "intel_tv.h"
> >  #include "intel_vdsc.h"
> >  
> > @@ -16683,6 +16684,15 @@ intel_modeset_setup_hw_state(struct
> > drm_device *dev,
> >  	intel_modeset_readout_hw_state(dev);
> >  
> >  	/* HW state is read out, now we need to sanitize this mess. */
> > +
> > +	/* Sanitize the TypeC port mode upfront, encoders depend on
> > this */
> > +	for_each_intel_encoder(dev, encoder) {
> > +		/* We need to sanitize only the MST primary port. */
> > +		if (encoder->type != INTEL_OUTPUT_DP_MST &&
> > +		    intel_port_is_tc(dev_priv, encoder->port))
> > +			intel_tc_port_sanitize(enc_to_dig_port(&encoder
> > ->base));
> > +	}
> > +
> >  	get_encoder_power_domains(dev_priv);
> >  
> >  	if (HAS_PCH_IBX(dev_priv))
> > diff --git a/drivers/gpu/drm/i915/intel_dp_mst.h
> > b/drivers/gpu/drm/i915/intel_dp_mst.h
> > index 1470c6e0514b..6754c211205a 100644
> > --- a/drivers/gpu/drm/i915/intel_dp_mst.h
> > +++ b/drivers/gpu/drm/i915/intel_dp_mst.h
> > @@ -6,9 +6,15 @@
> >  #ifndef __INTEL_DP_MST_H__
> >  #define __INTEL_DP_MST_H__
> >  
> > -struct intel_digital_port;
> > +#include "intel_drv.h"
> >  
> >  int intel_dp_mst_encoder_init(struct intel_digital_port
> > *intel_dig_port, int conn_id);
> >  void intel_dp_mst_encoder_cleanup(struct intel_digital_port
> > *intel_dig_port);
> > +static inline int
> > +intel_dp_mst_encoder_active_links(struct intel_digital_port
> > *intel_dig_port)
> > +{
> > +	return intel_dig_port->dp.active_mst_links;
> > +}
> > +
> >  
> >  #endif /* __INTEL_DP_MST_H__ */
> > diff --git a/drivers/gpu/drm/i915/intel_tc.c
> > b/drivers/gpu/drm/i915/intel_tc.c
> > index 9832e2ddb92e..9ebf25d7931c 100644
> > --- a/drivers/gpu/drm/i915/intel_tc.c
> > +++ b/drivers/gpu/drm/i915/intel_tc.c
> > @@ -3,6 +3,7 @@
> >   * Copyright © 2019 Intel Corporation
> >   */
> >  #include "intel_display.h"
> > +#include "intel_dp_mst.h"
> >  #include "i915_drv.h"
> >  #include "intel_tc.h"
> >  
> > @@ -167,6 +168,15 @@ static bool icl_tc_phy_set_safe_mode(struct
> > intel_digital_port *dig_port,
> >  	return true;
> >  }
> >  
> > +static bool icl_tc_phy_is_in_safe_mode(struct intel_digital_port
> > *dig_port)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(dig_port-
> > >base.base.dev);
> > +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> > >base.port);
> > +
> > +	return !(I915_READ(PORT_TX_DFLEXDPCSSS) &
> > +		 DP_PHY_MODE_STATUS_NOT_SAFE(tc_port));
> > +}
> > +
> >  /*
> >   * This function implements the first part of the Connect Flow
> > described by our
> >   * specification, Gen11 TypeC Programming chapter. The rest of the
> > flow (reading
> > @@ -250,6 +260,49 @@ void icl_tc_phy_disconnect(struct
> > intel_digital_port *dig_port)
> >  	}
> >  }
> >  
> > +static bool icl_tc_phy_is_connected(struct intel_digital_port
> > *dig_port)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(dig_port-
> > >base.base.dev);
> > +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port-
> > >base.port);
> > +
> > +	if (!icl_tc_phy_status_complete(dig_port)) {
> > +		DRM_DEBUG_KMS("Port %s: PHY status not complete\n",
> > +			      tc_port_name(dev_priv, tc_port));
> > +		return dig_port->tc_mode == TC_PORT_TBT_ALT;
> > +	}
> > +
> > +	if (icl_tc_phy_is_in_safe_mode(dig_port)) {
> > +		DRM_DEBUG_KMS("Port %s: PHY still in safe mode\n",
> > +			      tc_port_name(dev_priv, tc_port));
> > +
> > +		return false;
> > +	}
> > +
> > +	return dig_port->tc_mode == TC_PORT_DP_ALT ||
> > +	       dig_port->tc_mode == TC_PORT_LEGACY;
> > +}
> > +
> > +static enum tc_port_mode
> > +intel_tc_port_get_current_mode(struct intel_digital_port *dig_port)
> > +{
> > +	u32 live_status_mask = tc_port_live_status_mask(dig_port);
> > +	bool in_safe_mode = icl_tc_phy_is_in_safe_mode(dig_port);
> > +	enum tc_port_mode mode;
> > +
> > +	if (in_safe_mode ||
> > WARN_ON(!icl_tc_phy_status_complete(dig_port)))
> > +		return TC_PORT_TBT_ALT;
> > +
> > +	mode = dig_port->tc_legacy_port ? TC_PORT_LEGACY :
> > TC_PORT_DP_ALT;
> > +	if (live_status_mask) {
> > +		enum tc_port_mode live_mode = fls(live_status_mask) -
> > 1;
> > +
> > +		if (!WARN_ON(live_mode == TC_PORT_TBT_ALT))
> > +			mode = live_mode;
> > +	}
> > +
> > +	return mode;
> > +}
> > +
> >  static enum tc_port_mode
> >  intel_tc_port_get_target_mode(struct intel_digital_port *dig_port)
> >  {
> > @@ -278,6 +331,36 @@ static void intel_tc_port_reset_mode(struct
> > intel_digital_port *dig_port)
> >  		      tc_port_mode_name(dig_port->tc_mode));
> >  }
> >  
> > +void intel_tc_port_sanitize(struct intel_digital_port *dig_port)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(dig_port-
> > >base.base.dev);
> > +	struct intel_encoder *encoder = &dig_port->base;
> > +	enum tc_port tc_port = intel_port_to_tc(dev_priv, encoder-
> > >port);
> > +	int active_links = 0;
> > +
> > +	dig_port->tc_mode = intel_tc_port_get_current_mode(dig_port);
> > +	if (dig_port->dp.is_mst)
> > +		active_links =
> > intel_dp_mst_encoder_active_links(dig_port);
> > +	else if (encoder->base.crtc)
> > +		active_links = to_intel_crtc(encoder->base.crtc)-
> > >active;
> > +
> > +	if (active_links) {
> > +		if (!icl_tc_phy_is_connected(dig_port))
> > +			DRM_DEBUG_DRIVER("Port %s: PHY disconnected
> > with %d active link(s)\n",
> > +					 tc_port_name(dev_priv,
> > tc_port),
> > +					 active_links);
> > +		goto out;
> 
> And then probe sequences will take care of call
> intel_digital_port_connected() to reset TC state. 

Right, once the active mode (we detected here) gets disabled, since
before that you can't reset the mode. Btw, we'll also check if a mode
reset is needed before AUX transfers (if the port is not active).

> 
> > +	}
> > +
> > +	if (dig_port->tc_legacy_port)
> > +		icl_tc_phy_connect(dig_port);
> > +
> > +out:
> > +	DRM_DEBUG_DRIVER("Port %s: sanitize mode (%s)\n",
> > +			 tc_port_name(dev_priv, tc_port),
> > +			 tc_port_mode_name(dig_port->tc_mode));
> 
> Should be:
> 
> DRM_DEBUG_DRIVER()
> 
> I guess I missed this on previous patches too.

Ah right, DRM_DEBUG_KMS().

> 
> 
> With that:
> Reviewed-by: José Roberto de Souza <jose.souza@intel.com>
> 
> 
> > +}
> > +
> >  static bool
> >  intel_tc_port_needs_reset(struct intel_digital_port *dig_port)
> >  {
> > diff --git a/drivers/gpu/drm/i915/intel_tc.h
> > b/drivers/gpu/drm/i915/intel_tc.h
> > index e937f5326959..10f0f0d81ee4 100644
> > --- a/drivers/gpu/drm/i915/intel_tc.h
> > +++ b/drivers/gpu/drm/i915/intel_tc.h
> > @@ -11,4 +11,6 @@ bool intel_tc_port_connected(struct
> > intel_digital_port *dig_port);
> >  u32 intel_tc_port_get_lane_info(struct intel_digital_port
> > *dig_port);
> >  int intel_tc_port_fia_max_lane_count(struct intel_digital_port
> > *dig_port);
> >  
> > +void intel_tc_port_sanitize(struct intel_digital_port *dig_port);
> > +
> >  #endif /* __INTEL_TC_H__ */
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* ✓ Fi.CI.IGT: success for drm/i915: Fix TypeC port mode switching (rev2)
  2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
                   ` (29 preceding siblings ...)
  2019-06-07 18:34 ` ✓ Fi.CI.BAT: success " Patchwork
@ 2019-06-10 12:34 ` Patchwork
  30 siblings, 0 replies; 79+ messages in thread
From: Patchwork @ 2019-06-10 12:34 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Fix TypeC port mode switching (rev2)
URL   : https://patchwork.freedesktop.org/series/61590/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_6221_full -> Patchwork_13209_full
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  

Known issues
------------

  Here are the changes found in Patchwork_13209_full that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_ctx_engines@execute-one:
    - shard-snb:          [PASS][1] -> [DMESG-WARN][2] ([fdo#110869])
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-snb2/igt@gem_ctx_engines@execute-one.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-snb2/igt@gem_ctx_engines@execute-one.html

  * igt@gem_tiled_swapping@non-threaded:
    - shard-glk:          [PASS][3] -> [DMESG-WARN][4] ([fdo#108686])
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-glk6/igt@gem_tiled_swapping@non-threaded.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-glk5/igt@gem_tiled_swapping@non-threaded.html

  * igt@i915_suspend@fence-restore-untiled:
    - shard-skl:          [PASS][5] -> [INCOMPLETE][6] ([fdo#104108])
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-skl6/igt@i915_suspend@fence-restore-untiled.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-skl7/igt@i915_suspend@fence-restore-untiled.html

  * igt@kms_cursor_legacy@all-pipes-torture-bo:
    - shard-iclb:         [PASS][7] -> [INCOMPLETE][8] ([fdo#107713])
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-iclb6/igt@kms_cursor_legacy@all-pipes-torture-bo.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-iclb7/igt@kms_cursor_legacy@all-pipes-torture-bo.html

  * igt@kms_flip@flip-vs-suspend-interruptible:
    - shard-iclb:         [PASS][9] -> [INCOMPLETE][10] ([fdo#107713] / [fdo#109507])
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-iclb3/igt@kms_flip@flip-vs-suspend-interruptible.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-iclb3/igt@kms_flip@flip-vs-suspend-interruptible.html
    - shard-skl:          [PASS][11] -> [INCOMPLETE][12] ([fdo#109507])
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-skl6/igt@kms_flip@flip-vs-suspend-interruptible.html
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-skl7/igt@kms_flip@flip-vs-suspend-interruptible.html

  * igt@kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-render:
    - shard-iclb:         [PASS][13] -> [FAIL][14] ([fdo#103167]) +4 similar issues
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-iclb4/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-render.html
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-iclb4/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-render.html

  * igt@kms_pipe_crc_basic@suspend-read-crc-pipe-c:
    - shard-kbl:          [PASS][15] -> [DMESG-WARN][16] ([fdo#108566]) +2 similar issues
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-kbl4/igt@kms_pipe_crc_basic@suspend-read-crc-pipe-c.html
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-kbl6/igt@kms_pipe_crc_basic@suspend-read-crc-pipe-c.html

  * igt@kms_plane@plane-panning-bottom-right-suspend-pipe-c-planes:
    - shard-apl:          [PASS][17] -> [DMESG-WARN][18] ([fdo#108566]) +5 similar issues
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-apl3/igt@kms_plane@plane-panning-bottom-right-suspend-pipe-c-planes.html
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-apl7/igt@kms_plane@plane-panning-bottom-right-suspend-pipe-c-planes.html

  * igt@kms_plane_alpha_blend@pipe-b-coverage-7efc:
    - shard-skl:          [PASS][19] -> [FAIL][20] ([fdo#108145] / [fdo#110403])
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-skl7/igt@kms_plane_alpha_blend@pipe-b-coverage-7efc.html
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-skl1/igt@kms_plane_alpha_blend@pipe-b-coverage-7efc.html

  * igt@kms_plane_alpha_blend@pipe-c-constant-alpha-min:
    - shard-skl:          [PASS][21] -> [FAIL][22] ([fdo#108145]) +1 similar issue
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-skl5/igt@kms_plane_alpha_blend@pipe-c-constant-alpha-min.html
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-skl9/igt@kms_plane_alpha_blend@pipe-c-constant-alpha-min.html

  * igt@kms_plane_lowres@pipe-a-tiling-y:
    - shard-iclb:         [PASS][23] -> [FAIL][24] ([fdo#103166])
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-iclb7/igt@kms_plane_lowres@pipe-a-tiling-y.html
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-iclb5/igt@kms_plane_lowres@pipe-a-tiling-y.html

  * igt@kms_setmode@basic:
    - shard-kbl:          [PASS][25] -> [FAIL][26] ([fdo#99912])
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-kbl2/igt@kms_setmode@basic.html
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-kbl4/igt@kms_setmode@basic.html

  
#### Possible fixes ####

  * igt@gem_ctx_engines@execute-one:
    - shard-glk:          [DMESG-WARN][27] ([fdo#110869]) -> [PASS][28]
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-glk5/igt@gem_ctx_engines@execute-one.html
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-glk7/igt@gem_ctx_engines@execute-one.html

  * igt@gem_ctx_isolation@bcs0-s3:
    - shard-kbl:          [DMESG-WARN][29] ([fdo#108566]) -> [PASS][30]
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-kbl6/igt@gem_ctx_isolation@bcs0-s3.html
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-kbl1/igt@gem_ctx_isolation@bcs0-s3.html

  * igt@gem_fence_thrash@bo-write-verify-threaded-none:
    - shard-iclb:         [INCOMPLETE][31] ([fdo#107713]) -> [PASS][32]
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-iclb7/igt@gem_fence_thrash@bo-write-verify-threaded-none.html
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-iclb5/igt@gem_fence_thrash@bo-write-verify-threaded-none.html

  * igt@i915_suspend@debugfs-reader:
    - shard-apl:          [DMESG-WARN][33] ([fdo#108566]) -> [PASS][34] +6 similar issues
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-apl7/igt@i915_suspend@debugfs-reader.html
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-apl5/igt@i915_suspend@debugfs-reader.html

  * igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size:
    - shard-skl:          [FAIL][35] ([fdo#102670]) -> [PASS][36]
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-skl4/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size.html
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-skl10/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size.html

  * igt@kms_draw_crc@draw-method-xrgb2101010-pwrite-ytiled:
    - shard-skl:          [FAIL][37] ([fdo#103184] / [fdo#103232]) -> [PASS][38]
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-skl6/igt@kms_draw_crc@draw-method-xrgb2101010-pwrite-ytiled.html
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-skl9/igt@kms_draw_crc@draw-method-xrgb2101010-pwrite-ytiled.html

  * igt@kms_flip@flip-vs-suspend:
    - shard-skl:          [INCOMPLETE][39] ([fdo#109507]) -> [PASS][40]
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-skl1/igt@kms_flip@flip-vs-suspend.html
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-skl4/igt@kms_flip@flip-vs-suspend.html

  * igt@kms_frontbuffer_tracking@fbc-rgb565-draw-pwrite:
    - shard-iclb:         [FAIL][41] ([fdo#103167]) -> [PASS][42] +4 similar issues
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-iclb5/igt@kms_frontbuffer_tracking@fbc-rgb565-draw-pwrite.html
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-iclb8/igt@kms_frontbuffer_tracking@fbc-rgb565-draw-pwrite.html

  * igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-spr-indfb-draw-blt:
    - shard-iclb:         [INCOMPLETE][43] ([fdo#106978] / [fdo#107713]) -> [PASS][44]
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-iclb1/igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-spr-indfb-draw-blt.html
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-iclb7/igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-spr-indfb-draw-blt.html

  * igt@kms_plane_alpha_blend@pipe-a-constant-alpha-min:
    - shard-skl:          [FAIL][45] ([fdo#108145]) -> [PASS][46]
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-skl6/igt@kms_plane_alpha_blend@pipe-a-constant-alpha-min.html
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-skl9/igt@kms_plane_alpha_blend@pipe-a-constant-alpha-min.html

  * igt@kms_plane_alpha_blend@pipe-c-coverage-7efc:
    - shard-skl:          [FAIL][47] ([fdo#108145] / [fdo#110403]) -> [PASS][48]
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-skl6/igt@kms_plane_alpha_blend@pipe-c-coverage-7efc.html
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-skl7/igt@kms_plane_alpha_blend@pipe-c-coverage-7efc.html

  
#### Warnings ####

  * igt@gem_mmap_gtt@forked-big-copy-odd:
    - shard-iclb:         [TIMEOUT][49] ([fdo#109673]) -> [INCOMPLETE][50] ([fdo#107713] / [fdo#109100])
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-iclb4/igt@gem_mmap_gtt@forked-big-copy-odd.html
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-iclb6/igt@gem_mmap_gtt@forked-big-copy-odd.html

  * igt@kms_frontbuffer_tracking@fbcpsr-tilingchange:
    - shard-skl:          [FAIL][51] ([fdo#103167]) -> [FAIL][52] ([fdo#108040])
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_6221/shard-skl1/igt@kms_frontbuffer_tracking@fbcpsr-tilingchange.html
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/shard-skl7/igt@kms_frontbuffer_tracking@fbcpsr-tilingchange.html

  
  [fdo#102670]: https://bugs.freedesktop.org/show_bug.cgi?id=102670
  [fdo#103166]: https://bugs.freedesktop.org/show_bug.cgi?id=103166
  [fdo#103167]: https://bugs.freedesktop.org/show_bug.cgi?id=103167
  [fdo#103184]: https://bugs.freedesktop.org/show_bug.cgi?id=103184
  [fdo#103232]: https://bugs.freedesktop.org/show_bug.cgi?id=103232
  [fdo#104108]: https://bugs.freedesktop.org/show_bug.cgi?id=104108
  [fdo#106978]: https://bugs.freedesktop.org/show_bug.cgi?id=106978
  [fdo#107713]: https://bugs.freedesktop.org/show_bug.cgi?id=107713
  [fdo#108040]: https://bugs.freedesktop.org/show_bug.cgi?id=108040
  [fdo#108145]: https://bugs.freedesktop.org/show_bug.cgi?id=108145
  [fdo#108566]: https://bugs.freedesktop.org/show_bug.cgi?id=108566
  [fdo#108686]: https://bugs.freedesktop.org/show_bug.cgi?id=108686
  [fdo#109100]: https://bugs.freedesktop.org/show_bug.cgi?id=109100
  [fdo#109507]: https://bugs.freedesktop.org/show_bug.cgi?id=109507
  [fdo#109673]: https://bugs.freedesktop.org/show_bug.cgi?id=109673
  [fdo#110403]: https://bugs.freedesktop.org/show_bug.cgi?id=110403
  [fdo#110869]: https://bugs.freedesktop.org/show_bug.cgi?id=110869
  [fdo#99912]: https://bugs.freedesktop.org/show_bug.cgi?id=99912


Participating hosts (9 -> 9)
------------------------------

  No changes in participating hosts


Build changes
-------------

  * Linux: CI_DRM_6221 -> Patchwork_13209

  CI_DRM_6221: 3f71d971d89a60348dbb11c40459aeb9d69c18f9 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_5048: 1a34b94f1ce07ac5978fe7893a17e8732d467868 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  Patchwork_13209: e8990683c8c6a9ebc1026ae3f272e8b87f4f5f5c @ git://anongit.freedesktop.org/gfx-ci/linux
  piglit_4509: fdc5a4ca11124ab8413c7988896eec4c97336694 @ git://anongit.freedesktop.org/piglit

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_13209/
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 03/23] drm/i915: Move the TypeC port handling code to a separate file
  2019-06-06  8:42   ` Jani Nikula
  2019-06-06  8:43     ` Jani Nikula
  2019-06-06  9:09     ` Imre Deak
@ 2019-06-10 22:57     ` Lucas De Marchi
  2019-06-11 10:01       ` Jani Nikula
  2 siblings, 1 reply; 79+ messages in thread
From: Lucas De Marchi @ 2019-06-10 22:57 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx, Paulo Zanoni

On Thu, Jun 06, 2019 at 11:42:46AM +0300, Jani Nikula wrote:
>On Tue, 04 Jun 2019, Imre Deak <imre.deak@intel.com> wrote:
>> Move the TypeC port handling functions to a new file for clarity.
>>
>> While at it:
>> - s/icl_tc_port_connected()/intel_tc_port_connected()/
>>   icl_tc_phy_disconnect(), will be unexported later.
>>
>> - s/intel_dp_get_fia_supported_lane_count()/intel_tc_port_fia_max_lane_count()/
>>   It's used for HDMI legacy mode too.
>>
>> - Simplify function interfaces by passing only dig_port to them.
>>
>> No functional changes.
>
>Some nitpicks below.
>
>BR,
>Jani.
>
>
>>
>> Cc: Animesh Manna <animesh.manna@intel.com>
>> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
>> Cc: José Roberto de Souza <jose.souza@intel.com>
>> Signed-off-by: Imre Deak <imre.deak@intel.com>
>> ---
>>  drivers/gpu/drm/i915/Makefile             |   3 +-
>>  drivers/gpu/drm/i915/Makefile.header-test |   1 +
>>  drivers/gpu/drm/i915/intel_ddi.c          |   6 +-
>>  drivers/gpu/drm/i915/intel_dp.c           | 227 +--------------------
>>  drivers/gpu/drm/i915/intel_dp.h           |   2 -
>>  drivers/gpu/drm/i915/intel_tc.c           | 230 ++++++++++++++++++++++
>>  drivers/gpu/drm/i915/intel_tc.h           |  13 ++
>>  7 files changed, 252 insertions(+), 230 deletions(-)
>>  create mode 100644 drivers/gpu/drm/i915/intel_tc.c
>>  create mode 100644 drivers/gpu/drm/i915/intel_tc.h
>>
>> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
>> index c0a7b2994077..74c4d11d83eb 100644
>> --- a/drivers/gpu/drm/i915/Makefile
>> +++ b/drivers/gpu/drm/i915/Makefile
>> @@ -171,7 +171,8 @@ i915-y += intel_audio.o \
>>  	  intel_psr.o \
>>  	  intel_quirks.o \
>>  	  intel_sideband.o \
>> -	  intel_sprite.o
>> +	  intel_sprite.o \
>> +	  intel_tc.o
>>  i915-$(CONFIG_ACPI)		+= intel_acpi.o intel_opregion.o
>>  i915-$(CONFIG_DRM_FBDEV_EMULATION)	+= intel_fbdev.o
>>
>> diff --git a/drivers/gpu/drm/i915/Makefile.header-test b/drivers/gpu/drm/i915/Makefile.header-test
>> index 6ef3b647ac65..e80e8e45b09c 100644
>> --- a/drivers/gpu/drm/i915/Makefile.header-test
>> +++ b/drivers/gpu/drm/i915/Makefile.header-test
>> @@ -58,6 +58,7 @@ header_test := \
>>  	intel_sdvo.h \
>>  	intel_sideband.h \
>>  	intel_sprite.h \
>> +	intel_tc.h \
>>  	intel_tv.h \
>>  	intel_uncore.h \
>>  	intel_vdsc.h \
>> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
>> index 350eaf54f01f..5a1c98438375 100644
>> --- a/drivers/gpu/drm/i915/intel_ddi.c
>> +++ b/drivers/gpu/drm/i915/intel_ddi.c
>> @@ -45,6 +45,7 @@
>>  #include "intel_lspcon.h"
>>  #include "intel_panel.h"
>>  #include "intel_psr.h"
>> +#include "intel_tc.h"
>>  #include "intel_vdsc.h"
>>
>>  struct ddi_buf_trans {
>> @@ -3904,7 +3905,6 @@ static int intel_ddi_compute_config(struct intel_encoder *encoder,
>>  static void intel_ddi_encoder_suspend(struct intel_encoder *encoder)
>>  {
>>  	struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
>> -	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
>>
>>  	intel_dp_encoder_suspend(encoder);
>>
>> @@ -3914,7 +3914,7 @@ static void intel_ddi_encoder_suspend(struct intel_encoder *encoder)
>>  	 * even if the sink has disappeared while being suspended.
>>  	 */
>>  	if (dig_port->tc_legacy_port)
>> -		icl_tc_phy_disconnect(i915, dig_port);
>> +		icl_tc_phy_disconnect(dig_port);
>>  }
>>
>>  static void intel_ddi_encoder_reset(struct drm_encoder *drm_encoder)
>> @@ -3936,7 +3936,7 @@ static void intel_ddi_encoder_destroy(struct drm_encoder *encoder)
>>  	intel_dp_encoder_flush_work(encoder);
>>
>>  	if (intel_port_is_tc(i915, dig_port->base.port))
>> -		icl_tc_phy_disconnect(i915, dig_port);
>> +		icl_tc_phy_disconnect(dig_port);
>>
>>  	drm_encoder_cleanup(encoder);
>>  	kfree(dig_port);
>> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>> index 24b56b2a76c8..b69310bd9914 100644
>> --- a/drivers/gpu/drm/i915/intel_dp.c
>> +++ b/drivers/gpu/drm/i915/intel_dp.c
>> @@ -62,6 +62,7 @@
>>  #include "intel_panel.h"
>>  #include "intel_psr.h"
>>  #include "intel_sideband.h"
>> +#include "intel_tc.h"
>>  #include "intel_vdsc.h"
>>
>>  #define DP_DPRX_ESI_LEN 14
>> @@ -211,46 +212,13 @@ static int intel_dp_max_common_rate(struct intel_dp *intel_dp)
>>  	return intel_dp->common_rates[intel_dp->num_common_rates - 1];
>>  }
>>
>> -static int intel_dp_get_fia_supported_lane_count(struct intel_dp *intel_dp)
>> -{
>> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
>> -	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
>> -	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
>> -	intel_wakeref_t wakeref;
>> -	u32 lane_info;
>> -
>> -	if (tc_port == PORT_TC_NONE || dig_port->tc_type != TC_PORT_TYPEC)
>> -		return 4;
>> -
>> -	lane_info = 0;
>> -	with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref)
>> -		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
>> -			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
>> -				DP_LANE_ASSIGNMENT_SHIFT(tc_port);
>> -
>> -	switch (lane_info) {
>> -	default:
>> -		MISSING_CASE(lane_info);
>> -	case 1:
>> -	case 2:
>> -	case 4:
>> -	case 8:
>> -		return 1;
>> -	case 3:
>> -	case 12:
>> -		return 2;
>> -	case 15:
>> -		return 4;
>> -	}
>> -}
>> -
>>  /* Theoretical max between source and sink */
>>  static int intel_dp_max_common_lane_count(struct intel_dp *intel_dp)
>>  {
>>  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
>>  	int source_max = intel_dig_port->max_lanes;
>>  	int sink_max = drm_dp_max_lane_count(intel_dp->dpcd);
>> -	int fia_max = intel_dp_get_fia_supported_lane_count(intel_dp);
>> +	int fia_max = intel_tc_port_fia_max_lane_count(intel_dig_port);
>>
>>  	return min3(source_max, sink_max, fia_max);
>>  }
>> @@ -5231,195 +5199,6 @@ static bool icl_combo_port_connected(struct drm_i915_private *dev_priv,
>>  	return I915_READ(SDEISR) & SDE_DDI_HOTPLUG_ICP(port);
>>  }
>>
>> -static const char *tc_type_name(enum tc_port_type type)
>> -{
>> -	static const char * const names[] = {
>> -		[TC_PORT_UNKNOWN] = "unknown",
>> -		[TC_PORT_LEGACY] = "legacy",
>> -		[TC_PORT_TYPEC] = "typec",
>> -		[TC_PORT_TBT] = "tbt",
>> -	};
>> -
>> -	if (WARN_ON(type >= ARRAY_SIZE(names)))
>> -		type = TC_PORT_UNKNOWN;
>> -
>> -	return names[type];
>> -}
>> -
>> -static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
>> -				    struct intel_digital_port *intel_dig_port,
>> -				    bool is_legacy, bool is_typec, bool is_tbt)
>> -{
>> -	enum port port = intel_dig_port->base.port;
>> -	enum tc_port_type old_type = intel_dig_port->tc_type;
>> -
>> -	WARN_ON(is_legacy + is_typec + is_tbt != 1);
>> -
>> -	if (is_legacy)
>> -		intel_dig_port->tc_type = TC_PORT_LEGACY;
>> -	else if (is_typec)
>> -		intel_dig_port->tc_type = TC_PORT_TYPEC;
>> -	else if (is_tbt)
>> -		intel_dig_port->tc_type = TC_PORT_TBT;
>> -	else
>> -		return;
>> -
>> -	/* Types are not supposed to be changed at runtime. */
>> -	WARN_ON(old_type != TC_PORT_UNKNOWN &&
>> -		old_type != intel_dig_port->tc_type);
>> -
>> -	if (old_type != intel_dig_port->tc_type)
>> -		DRM_DEBUG_KMS("Port %c has TC type %s\n", port_name(port),
>> -			      tc_type_name(intel_dig_port->tc_type));
>> -}
>> -
>> -/*
>> - * This function implements the first part of the Connect Flow described by our
>> - * specification, Gen11 TypeC Programming chapter. The rest of the flow (reading
>> - * lanes, EDID, etc) is done as needed in the typical places.
>> - *
>> - * Unlike the other ports, type-C ports are not available to use as soon as we
>> - * get a hotplug. The type-C PHYs can be shared between multiple controllers:
>> - * display, USB, etc. As a result, handshaking through FIA is required around
>> - * connect and disconnect to cleanly transfer ownership with the controller and
>> - * set the type-C power state.
>> - *
>> - * We could opt to only do the connect flow when we actually try to use the AUX
>> - * channels or do a modeset, then immediately run the disconnect flow after
>> - * usage, but there are some implications on this for a dynamic environment:
>> - * things may go away or change behind our backs. So for now our driver is
>> - * always trying to acquire ownership of the controller as soon as it gets an
>> - * interrupt (or polls state and sees a port is connected) and only gives it
>> - * back when it sees a disconnect. Implementation of a more fine-grained model
>> - * will require a lot of coordination with user space and thorough testing for
>> - * the extra possible cases.
>> - */
>> -static bool icl_tc_phy_connect(struct drm_i915_private *dev_priv,
>> -			       struct intel_digital_port *dig_port)
>> -{
>> -	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
>> -	u32 val;
>> -
>> -	if (dig_port->tc_type != TC_PORT_LEGACY &&
>> -	    dig_port->tc_type != TC_PORT_TYPEC)
>> -		return true;
>> -
>> -	val = I915_READ(PORT_TX_DFLEXDPPMS);
>> -	if (!(val & DP_PHY_MODE_STATUS_COMPLETED(tc_port))) {
>> -		DRM_DEBUG_KMS("DP PHY for TC port %d not ready\n", tc_port);
>> -		WARN_ON(dig_port->tc_legacy_port);
>> -		return false;
>> -	}
>> -
>> -	/*
>> -	 * This function may be called many times in a row without an HPD event
>> -	 * in between, so try to avoid the write when we can.
>> -	 */
>> -	val = I915_READ(PORT_TX_DFLEXDPCSSS);
>> -	if (!(val & DP_PHY_MODE_STATUS_NOT_SAFE(tc_port))) {
>> -		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
>> -		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
>> -	}
>> -
>> -	/*
>> -	 * Now we have to re-check the live state, in case the port recently
>> -	 * became disconnected. Not necessary for legacy mode.
>> -	 */
>> -	if (dig_port->tc_type == TC_PORT_TYPEC &&
>> -	    !(I915_READ(PORT_TX_DFLEXDPSP) & TC_LIVE_STATE_TC(tc_port))) {
>> -		DRM_DEBUG_KMS("TC PHY %d sudden disconnect.\n", tc_port);
>> -		icl_tc_phy_disconnect(dev_priv, dig_port);
>> -		return false;
>> -	}
>> -
>> -	return true;
>> -}
>> -
>> -/*
>> - * See the comment at the connect function. This implements the Disconnect
>> - * Flow.
>> - */
>> -void icl_tc_phy_disconnect(struct drm_i915_private *dev_priv,
>> -			   struct intel_digital_port *dig_port)
>> -{
>> -	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
>> -
>> -	if (dig_port->tc_type == TC_PORT_UNKNOWN)
>> -		return;
>> -
>> -	/*
>> -	 * TBT disconnection flow is read the live status, what was done in
>> -	 * caller.
>> -	 */
>> -	if (dig_port->tc_type == TC_PORT_TYPEC ||
>> -	    dig_port->tc_type == TC_PORT_LEGACY) {
>> -		u32 val;
>> -
>> -		val = I915_READ(PORT_TX_DFLEXDPCSSS);
>> -		val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
>> -		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
>> -	}
>> -
>> -	DRM_DEBUG_KMS("Port %c TC type %s disconnected\n",
>> -		      port_name(dig_port->base.port),
>> -		      tc_type_name(dig_port->tc_type));
>> -
>> -	dig_port->tc_type = TC_PORT_UNKNOWN;
>> -}
>> -
>> -/*
>> - * The type-C ports are different because even when they are connected, they may
>> - * not be available/usable by the graphics driver: see the comment on
>> - * icl_tc_phy_connect(). So in our driver instead of adding the additional
>> - * concept of "usable" and make everything check for "connected and usable" we
>> - * define a port as "connected" when it is not only connected, but also when it
>> - * is usable by the rest of the driver. That maintains the old assumption that
>> - * connected ports are usable, and avoids exposing to the users objects they
>> - * can't really use.
>> - */
>> -static bool icl_tc_port_connected(struct drm_i915_private *dev_priv,
>> -				  struct intel_digital_port *intel_dig_port)
>> -{
>> -	enum port port = intel_dig_port->base.port;
>> -	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
>> -	bool is_legacy, is_typec, is_tbt;
>> -	u32 dpsp;
>> -
>> -	/*
>> -	 * Complain if we got a legacy port HPD, but VBT didn't mark the port as
>> -	 * legacy. Treat the port as legacy from now on.
>> -	 */
>> -	if (!intel_dig_port->tc_legacy_port &&
>> -	    I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port)) {
>> -		DRM_ERROR("VBT incorrectly claims port %c is not TypeC legacy\n",
>> -			  port_name(port));
>> -		intel_dig_port->tc_legacy_port = true;
>> -	}
>> -	is_legacy = intel_dig_port->tc_legacy_port;
>> -
>> -	/*
>> -	 * The spec says we shouldn't be using the ISR bits for detecting
>> -	 * between TC and TBT. We should use DFLEXDPSP.
>> -	 */
>> -	dpsp = I915_READ(PORT_TX_DFLEXDPSP);
>> -	is_typec = dpsp & TC_LIVE_STATE_TC(tc_port);
>> -	is_tbt = dpsp & TC_LIVE_STATE_TBT(tc_port);
>> -
>> -	if (!is_legacy && !is_typec && !is_tbt) {
>> -		icl_tc_phy_disconnect(dev_priv, intel_dig_port);
>> -
>> -		return false;
>> -	}
>> -
>> -	icl_update_tc_port_type(dev_priv, intel_dig_port, is_legacy, is_typec,
>> -				is_tbt);
>> -
>> -	if (!icl_tc_phy_connect(dev_priv, intel_dig_port))
>> -		return false;
>> -
>> -	return true;
>> -}
>> -
>>  static bool icl_digital_port_connected(struct intel_encoder *encoder)
>>  {
>>  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>> @@ -5428,7 +5207,7 @@ static bool icl_digital_port_connected(struct intel_encoder *encoder)
>>  	if (intel_port_is_combophy(dev_priv, encoder->port))
>>  		return icl_combo_port_connected(dev_priv, dig_port);
>>  	else if (intel_port_is_tc(dev_priv, encoder->port))
>> -		return icl_tc_port_connected(dev_priv, dig_port);
>> +		return intel_tc_port_connected(dig_port);
>>  	else
>>  		MISSING_CASE(encoder->hpd_pin);
>>
>> diff --git a/drivers/gpu/drm/i915/intel_dp.h b/drivers/gpu/drm/i915/intel_dp.h
>> index da70b1a41c83..657bbb1f5ed0 100644
>> --- a/drivers/gpu/drm/i915/intel_dp.h
>> +++ b/drivers/gpu/drm/i915/intel_dp.h
>> @@ -112,8 +112,6 @@ bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp);
>>  int intel_dp_link_required(int pixel_clock, int bpp);
>>  int intel_dp_max_data_rate(int max_link_clock, int max_lanes);
>>  bool intel_digital_port_connected(struct intel_encoder *encoder);
>> -void icl_tc_phy_disconnect(struct drm_i915_private *dev_priv,
>> -			   struct intel_digital_port *dig_port);
>>
>>  static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
>>  {
>> diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
>> new file mode 100644
>> index 000000000000..7a1b5870945f
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/intel_tc.c
>> @@ -0,0 +1,230 @@
>> +// SPDX-License-Identifier: MIT
>> +/*
>> + * Copyright © 2019 Intel Corporation
>> + */
>
>From the Nitpicks Department, please add a blank line here.
>
>> +#include "intel_display.h"
>> +#include "i915_drv.h"
>> +#include "intel_tc.h"
>
>And sort the includes.

humn... In some other projects I use the convention of always having the
correspondent header to be included first and the rest sorted. Here it
would be like:

#include "intel_tc.h"

#include "intel_display.h"
#include "intel_drv.h"

This way we guarantee that intel_tc.h header is self-contained: anything
it needs, it includes or declares.  If we adopted such convention I don't
see why we would still need Makefile.header-test for example.

Lucas De Marchi

>
>> +
>> +static const char *tc_type_name(enum tc_port_type type)
>> +{
>> +	static const char * const names[] = {
>> +		[TC_PORT_UNKNOWN] = "unknown",
>> +		[TC_PORT_LEGACY] = "legacy",
>> +		[TC_PORT_TYPEC] = "typec",
>> +		[TC_PORT_TBT] = "tbt",
>> +	};
>> +
>> +	if (WARN_ON(type >= ARRAY_SIZE(names)))
>> +		type = TC_PORT_UNKNOWN;
>> +
>> +	return names[type];
>> +}
>> +
>> +int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
>> +{
>> +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
>> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
>> +	intel_wakeref_t wakeref;
>> +	u32 lane_info;
>> +
>> +	if (tc_port == PORT_TC_NONE || dig_port->tc_type != TC_PORT_TYPEC)
>> +		return 4;
>> +
>> +	lane_info = 0;
>> +	with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref)
>> +		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
>> +			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
>> +				DP_LANE_ASSIGNMENT_SHIFT(tc_port);
>> +
>> +	switch (lane_info) {
>> +	default:
>> +		MISSING_CASE(lane_info);
>> +	case 1:
>> +	case 2:
>> +	case 4:
>> +	case 8:
>> +		return 1;
>> +	case 3:
>> +	case 12:
>> +		return 2;
>> +	case 15:
>> +		return 4;
>> +	}
>> +}
>> +
>> +/*
>> + * This function implements the first part of the Connect Flow described by our
>> + * specification, Gen11 TypeC Programming chapter. The rest of the flow (reading
>> + * lanes, EDID, etc) is done as needed in the typical places.
>> + *
>> + * Unlike the other ports, type-C ports are not available to use as soon as we
>> + * get a hotplug. The type-C PHYs can be shared between multiple controllers:
>> + * display, USB, etc. As a result, handshaking through FIA is required around
>> + * connect and disconnect to cleanly transfer ownership with the controller and
>> + * set the type-C power state.
>> + *
>> + * We could opt to only do the connect flow when we actually try to use the AUX
>> + * channels or do a modeset, then immediately run the disconnect flow after
>> + * usage, but there are some implications on this for a dynamic environment:
>> + * things may go away or change behind our backs. So for now our driver is
>> + * always trying to acquire ownership of the controller as soon as it gets an
>> + * interrupt (or polls state and sees a port is connected) and only gives it
>> + * back when it sees a disconnect. Implementation of a more fine-grained model
>> + * will require a lot of coordination with user space and thorough testing for
>> + * the extra possible cases.
>> + */
>> +static bool icl_tc_phy_connect(struct intel_digital_port *dig_port)
>> +{
>> +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
>> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
>> +	u32 val;
>> +
>> +	if (dig_port->tc_type != TC_PORT_LEGACY &&
>> +	    dig_port->tc_type != TC_PORT_TYPEC)
>> +		return true;
>> +
>> +	val = I915_READ(PORT_TX_DFLEXDPPMS);
>> +	if (!(val & DP_PHY_MODE_STATUS_COMPLETED(tc_port))) {
>> +		DRM_DEBUG_KMS("DP PHY for TC port %d not ready\n", tc_port);
>> +		WARN_ON(dig_port->tc_legacy_port);
>> +		return false;
>> +	}
>> +
>> +	/*
>> +	 * This function may be called many times in a row without an HPD event
>> +	 * in between, so try to avoid the write when we can.
>> +	 */
>> +	val = I915_READ(PORT_TX_DFLEXDPCSSS);
>> +	if (!(val & DP_PHY_MODE_STATUS_NOT_SAFE(tc_port))) {
>> +		val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
>> +		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
>> +	}
>> +
>> +	/*
>> +	 * Now we have to re-check the live state, in case the port recently
>> +	 * became disconnected. Not necessary for legacy mode.
>> +	 */
>> +	if (dig_port->tc_type == TC_PORT_TYPEC &&
>> +	    !(I915_READ(PORT_TX_DFLEXDPSP) & TC_LIVE_STATE_TC(tc_port))) {
>> +		DRM_DEBUG_KMS("TC PHY %d sudden disconnect.\n", tc_port);
>> +		icl_tc_phy_disconnect(dig_port);
>> +		return false;
>> +	}
>> +
>> +	return true;
>> +}
>> +
>> +/*
>> + * See the comment at the connect function. This implements the Disconnect
>> + * Flow.
>> + */
>> +void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
>> +{
>> +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
>> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
>> +
>> +	if (dig_port->tc_type == TC_PORT_UNKNOWN)
>> +		return;
>> +
>> +	/*
>> +	 * TBT disconnection flow is read the live status, what was done in
>> +	 * caller.
>> +	 */
>> +	if (dig_port->tc_type == TC_PORT_TYPEC ||
>> +	    dig_port->tc_type == TC_PORT_LEGACY) {
>> +		u32 val;
>> +
>> +		val = I915_READ(PORT_TX_DFLEXDPCSSS);
>> +		val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
>> +		I915_WRITE(PORT_TX_DFLEXDPCSSS, val);
>> +	}
>> +
>> +	DRM_DEBUG_KMS("Port %c TC type %s disconnected\n",
>> +		      port_name(dig_port->base.port),
>> +		      tc_type_name(dig_port->tc_type));
>> +
>> +	dig_port->tc_type = TC_PORT_UNKNOWN;
>> +}
>> +
>> +static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
>> +				    struct intel_digital_port *intel_dig_port,
>> +				    bool is_legacy, bool is_typec, bool is_tbt)
>> +{
>> +	enum port port = intel_dig_port->base.port;
>> +	enum tc_port_type old_type = intel_dig_port->tc_type;
>> +
>> +	WARN_ON(is_legacy + is_typec + is_tbt != 1);
>> +
>> +	if (is_legacy)
>> +		intel_dig_port->tc_type = TC_PORT_LEGACY;
>> +	else if (is_typec)
>> +		intel_dig_port->tc_type = TC_PORT_TYPEC;
>> +	else if (is_tbt)
>> +		intel_dig_port->tc_type = TC_PORT_TBT;
>> +	else
>> +		return;
>> +
>> +	/* Types are not supposed to be changed at runtime. */
>> +	WARN_ON(old_type != TC_PORT_UNKNOWN &&
>> +		old_type != intel_dig_port->tc_type);
>> +
>> +	if (old_type != intel_dig_port->tc_type)
>> +		DRM_DEBUG_KMS("Port %c has TC type %s\n", port_name(port),
>> +			      tc_type_name(intel_dig_port->tc_type));
>> +}
>> +
>> +
>> +/*
>> + * The type-C ports are different because even when they are connected, they may
>> + * not be available/usable by the graphics driver: see the comment on
>> + * icl_tc_phy_connect(). So in our driver instead of adding the additional
>> + * concept of "usable" and make everything check for "connected and usable" we
>> + * define a port as "connected" when it is not only connected, but also when it
>> + * is usable by the rest of the driver. That maintains the old assumption that
>> + * connected ports are usable, and avoids exposing to the users objects they
>> + * can't really use.
>> + */
>> +bool intel_tc_port_connected(struct intel_digital_port *dig_port)
>> +{
>> +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
>> +	enum port port = dig_port->base.port;
>> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
>> +	bool is_legacy, is_typec, is_tbt;
>> +	u32 dpsp;
>> +
>> +	/*
>> +	 * Complain if we got a legacy port HPD, but VBT didn't mark the port as
>> +	 * legacy. Treat the port as legacy from now on.
>> +	 */
>> +	if (!dig_port->tc_legacy_port &&
>> +	    I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port)) {
>> +		DRM_ERROR("VBT incorrectly claims port %c is not TypeC legacy\n",
>> +			  port_name(port));
>> +		dig_port->tc_legacy_port = true;
>> +	}
>> +	is_legacy = dig_port->tc_legacy_port;
>> +
>> +	/*
>> +	 * The spec says we shouldn't be using the ISR bits for detecting
>> +	 * between TC and TBT. We should use DFLEXDPSP.
>> +	 */
>> +	dpsp = I915_READ(PORT_TX_DFLEXDPSP);
>> +	is_typec = dpsp & TC_LIVE_STATE_TC(tc_port);
>> +	is_tbt = dpsp & TC_LIVE_STATE_TBT(tc_port);
>> +
>> +	if (!is_legacy && !is_typec && !is_tbt) {
>> +		icl_tc_phy_disconnect(dig_port);
>> +
>> +		return false;
>> +	}
>> +
>> +	icl_update_tc_port_type(dev_priv, dig_port, is_legacy, is_typec,
>> +				is_tbt);
>> +
>> +	if (!icl_tc_phy_connect(dig_port))
>> +		return false;
>> +
>> +	return true;
>> +}
>> +
>> diff --git a/drivers/gpu/drm/i915/intel_tc.h b/drivers/gpu/drm/i915/intel_tc.h
>> new file mode 100644
>> index 000000000000..94c62ac4a162
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/intel_tc.h
>> @@ -0,0 +1,13 @@
>
>SPDX header here please.
>
>> +#ifndef __INTEL_TC_H__
>> +#define __INTEL_TC_H__
>> +
>> +#include <linux/types.h>
>> +
>> +struct intel_digital_port;
>> +
>> +void icl_tc_phy_disconnect(struct intel_digital_port *dig_port);
>
>I'd like to see this named intel_tc_* in the future.
>
>BR,
>Jani.
>
>
>> +
>> +bool intel_tc_port_connected(struct intel_digital_port *dig_port);
>> +int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port);
>> +
>> +#endif /* __INTEL_TC_H__ */
>
>-- 
>Jani Nikula, Intel Open Source Graphics Center
>_______________________________________________
>Intel-gfx mailing list
>Intel-gfx@lists.freedesktop.org
>https://lists.freedesktop.org/mailman/listinfo/intel-gfx
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 04/23] drm/i915: Sanitize the terminology used for TypeC port modes
  2019-06-04 14:58 ` [PATCH 04/23] drm/i915: Sanitize the terminology used for TypeC port modes Imre Deak
  2019-06-07 19:15   ` Souza, Jose
@ 2019-06-10 23:21   ` Lucas De Marchi
  2019-06-11 11:19     ` Imre Deak
  1 sibling, 1 reply; 79+ messages in thread
From: Lucas De Marchi @ 2019-06-10 23:21 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx, Paulo Zanoni

On Tue, Jun 04, 2019 at 05:58:07PM +0300, Imre Deak wrote:
>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.

\o/

>
>- 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.

I think the unknown was there to cover the first time we set the type
(aka mode). Since we don't do this during initialization and only when
updating the connected state, we needed that to protect some functions.

>
>- Don't WARN if the port mode changes, that can happen normally.
>
>No functional changes.
>
>Cc: Animesh Manna <animesh.manna@intel.com>
>Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
>Cc: Anusha Srivatsa <anusha.srivatsa@intel.com>
>Cc: José Roberto de Souza <jose.souza@intel.com>
>Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
>Signed-off-by: Imre Deak <imre.deak@intel.com>
>---
> drivers/gpu/drm/i915/intel_ddi.c      | 11 +++---
> drivers/gpu/drm/i915/intel_display.h  |  7 ++--
> drivers/gpu/drm/i915/intel_dp.c       |  2 +-
> drivers/gpu/drm/i915/intel_dpll_mgr.c |  2 +-
> drivers/gpu/drm/i915/intel_drv.h      |  2 +-
> drivers/gpu/drm/i915/intel_tc.c       | 48 +++++++++++----------------
> 6 files changed, 31 insertions(+), 41 deletions(-)
>
>diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
>index 5a1c98438375..a3574f14a3d0 100644
>--- a/drivers/gpu/drm/i915/intel_ddi.c
>+++ b/drivers/gpu/drm/i915/intel_ddi.c
>@@ -2986,14 +2986,14 @@ static void icl_program_mg_dp_mode(struct intel_digital_port *intel_dig_port)
> 	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
> 	u32 ln0, ln1, lane_info;
>
>-	if (tc_port == PORT_TC_NONE || intel_dig_port->tc_type == TC_PORT_TBT)
>+	if (intel_dig_port->tc_mode == TC_PORT_TBT_ALT)
> 		return;
>
> 	ln0 = I915_READ(MG_DP_MODE(0, port));
> 	ln1 = I915_READ(MG_DP_MODE(1, port));
>
>-	switch (intel_dig_port->tc_type) {
>-	case TC_PORT_TYPEC:
>+	switch (intel_dig_port->tc_mode) {
>+	case TC_PORT_DP_ALT:
> 		ln0 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
> 		ln1 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
>
>@@ -3036,7 +3036,7 @@ static void icl_program_mg_dp_mode(struct intel_digital_port *intel_dig_port)
> 		break;
>
> 	default:
>-		MISSING_CASE(intel_dig_port->tc_type);
>+		MISSING_CASE(intel_dig_port->tc_mode);
> 		return;
> 	}
>
>@@ -3630,8 +3630,7 @@ intel_ddi_pre_pll_enable(struct intel_encoder *encoder,
> 	 * Program the lane count for static/dynamic connections on Type-C ports.
> 	 * Skip this step for TBT.
> 	 */
>-	if (dig_port->tc_type == TC_PORT_UNKNOWN ||
>-	    dig_port->tc_type == TC_PORT_TBT)
>+	if (dig_port->tc_mode == TC_PORT_TBT_ALT)
> 		return;
>
> 	intel_ddi_set_fia_lane_count(encoder, crtc_state, port);
>diff --git a/drivers/gpu/drm/i915/intel_display.h b/drivers/gpu/drm/i915/intel_display.h
>index ee6b8194a459..d296556ed82e 100644
>--- a/drivers/gpu/drm/i915/intel_display.h
>+++ b/drivers/gpu/drm/i915/intel_display.h
>@@ -189,10 +189,9 @@ enum tc_port {
> 	I915_MAX_TC_PORTS
> };
>
>-enum tc_port_type {
>-	TC_PORT_UNKNOWN = 0,
>-	TC_PORT_TYPEC,
>-	TC_PORT_TBT,
>+enum tc_port_mode {
>+	TC_PORT_TBT_ALT,
>+	TC_PORT_DP_ALT,
> 	TC_PORT_LEGACY,
> };
>
>diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>index b69310bd9914..e1e27662aa6d 100644
>--- a/drivers/gpu/drm/i915/intel_dp.c
>+++ b/drivers/gpu/drm/i915/intel_dp.c
>@@ -1175,7 +1175,7 @@ static u32 skl_get_aux_send_ctl(struct intel_dp *intel_dp,
> 	      DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(32) |
> 	      DP_AUX_CH_CTL_SYNC_PULSE_SKL(32);
>
>-	if (intel_dig_port->tc_type == TC_PORT_TBT)
>+	if (intel_dig_port->tc_mode == TC_PORT_TBT_ALT)
> 		ret |= DP_AUX_CH_CTL_TBT_IO;
>
> 	return ret;
>diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
>index 69787f259677..f4787650a0d3 100644
>--- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
>+++ b/drivers/gpu/drm/i915/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);
>diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>index 0dcc03592d6e..30cd49dbd0d8 100644
>--- a/drivers/gpu/drm/i915/intel_drv.h
>+++ b/drivers/gpu/drm/i915/intel_drv.h
>@@ -1225,7 +1225,7 @@ struct intel_digital_port {
> 	enum aux_ch aux_ch;
> 	enum intel_display_power_domain ddi_io_power_domain;
> 	bool tc_legacy_port:1;

not related, but why do we add a hole in the struct on purpose?!?

>-	enum tc_port_type tc_type;
>+	enum tc_port_mode tc_mode;
>
> 	void (*write_infoframe)(struct intel_encoder *encoder,
> 				const struct intel_crtc_state *crtc_state,
>diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
>index 7a1b5870945f..a3057c44bec6 100644
>--- a/drivers/gpu/drm/i915/intel_tc.c
>+++ b/drivers/gpu/drm/i915/intel_tc.c
>@@ -6,19 +6,18 @@
> #include "i915_drv.h"
> #include "intel_tc.h"
>
>-static const char *tc_type_name(enum tc_port_type type)
>+static const char *tc_port_mode_name(enum tc_port_mode mode)
> {
> 	static const char * const names[] = {
>-		[TC_PORT_UNKNOWN] = "unknown",
>+		[TC_PORT_TBT_ALT] = "tbt-alt",
>+		[TC_PORT_DP_ALT] = "dp-alt",
> 		[TC_PORT_LEGACY] = "legacy",
>-		[TC_PORT_TYPEC] = "typec",
>-		[TC_PORT_TBT] = "tbt",
> 	};
>
>-	if (WARN_ON(type >= ARRAY_SIZE(names)))
>-		type = TC_PORT_UNKNOWN;
>+	if (WARN_ON(mode >= ARRAY_SIZE(names)))
>+		mode = TC_PORT_TBT_ALT;
>
>-	return names[type];
>+	return names[mode];
> }
>
> int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
>@@ -28,7 +27,7 @@ int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
> 	intel_wakeref_t wakeref;
> 	u32 lane_info;
>
>-	if (tc_port == PORT_TC_NONE || dig_port->tc_type != TC_PORT_TYPEC)
>+	if (dig_port->tc_mode != TC_PORT_DP_ALT)
> 		return 4;
>
> 	lane_info = 0;
>@@ -80,8 +79,8 @@ static bool icl_tc_phy_connect(struct intel_digital_port *dig_port)
> 	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> 	u32 val;
>
>-	if (dig_port->tc_type != TC_PORT_LEGACY &&
>-	    dig_port->tc_type != TC_PORT_TYPEC)
>+	if (dig_port->tc_mode != TC_PORT_LEGACY &&
>+	    dig_port->tc_mode != TC_PORT_DP_ALT)
> 		return true;
>
> 	val = I915_READ(PORT_TX_DFLEXDPPMS);
>@@ -105,7 +104,7 @@ static bool icl_tc_phy_connect(struct intel_digital_port *dig_port)
> 	 * Now we have to re-check the live state, in case the port recently
> 	 * became disconnected. Not necessary for legacy mode.
> 	 */
>-	if (dig_port->tc_type == TC_PORT_TYPEC &&
>+	if (dig_port->tc_mode == TC_PORT_DP_ALT &&
> 	    !(I915_READ(PORT_TX_DFLEXDPSP) & TC_LIVE_STATE_TC(tc_port))) {
> 		DRM_DEBUG_KMS("TC PHY %d sudden disconnect.\n", tc_port);
> 		icl_tc_phy_disconnect(dig_port);
>@@ -124,15 +123,12 @@ void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
> 	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> 	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
>
>-	if (dig_port->tc_type == TC_PORT_UNKNOWN)
>-		return;
>-
> 	/*
> 	 * TBT disconnection flow is read the live status, what was done in
> 	 * caller.
> 	 */
>-	if (dig_port->tc_type == TC_PORT_TYPEC ||
>-	    dig_port->tc_type == TC_PORT_LEGACY) {
>+	if (dig_port->tc_mode == TC_PORT_DP_ALT ||
>+	    dig_port->tc_mode == TC_PORT_LEGACY) {
> 		u32 val;
>
> 		val = I915_READ(PORT_TX_DFLEXDPCSSS);
>@@ -142,9 +138,9 @@ void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
>
> 	DRM_DEBUG_KMS("Port %c TC type %s disconnected\n",
> 		      port_name(dig_port->base.port),
>-		      tc_type_name(dig_port->tc_type));
>+		      tc_port_mode_name(dig_port->tc_mode));
>
>-	dig_port->tc_type = TC_PORT_UNKNOWN;
>+	dig_port->tc_mode = TC_PORT_TBT_ALT;

humn... if this is what the hw has after reset, then I think it covers
my concern above.


Reviewed-by: Lucas De Marchi <lucas.demarchi@intel.com>

Lucas De Marchi

> }
>
> static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
>@@ -152,26 +148,22 @@ static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
> 				    bool is_legacy, bool is_typec, bool is_tbt)
> {
> 	enum port port = intel_dig_port->base.port;
>-	enum tc_port_type old_type = intel_dig_port->tc_type;
>+	enum tc_port_mode old_mode = intel_dig_port->tc_mode;
>
> 	WARN_ON(is_legacy + is_typec + is_tbt != 1);
>
> 	if (is_legacy)
>-		intel_dig_port->tc_type = TC_PORT_LEGACY;
>+		intel_dig_port->tc_mode = TC_PORT_LEGACY;
> 	else if (is_typec)
>-		intel_dig_port->tc_type = TC_PORT_TYPEC;
>+		intel_dig_port->tc_mode = TC_PORT_DP_ALT;
> 	else if (is_tbt)
>-		intel_dig_port->tc_type = TC_PORT_TBT;
>+		intel_dig_port->tc_mode = TC_PORT_TBT_ALT;
> 	else
> 		return;
>
>-	/* Types are not supposed to be changed at runtime. */
>-	WARN_ON(old_type != TC_PORT_UNKNOWN &&
>-		old_type != intel_dig_port->tc_type);
>-
>-	if (old_type != intel_dig_port->tc_type)
>+	if (old_mode != intel_dig_port->tc_mode)
> 		DRM_DEBUG_KMS("Port %c has TC type %s\n", port_name(port),
>-			      tc_type_name(intel_dig_port->tc_type));
>+			      tc_port_mode_name(intel_dig_port->tc_mode));
> }
>
>
>-- 
>2.17.1
>
>_______________________________________________
>Intel-gfx mailing list
>Intel-gfx@lists.freedesktop.org
>https://lists.freedesktop.org/mailman/listinfo/intel-gfx
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 03/23] drm/i915: Move the TypeC port handling code to a separate file
  2019-06-10 22:57     ` Lucas De Marchi
@ 2019-06-11 10:01       ` Jani Nikula
  0 siblings, 0 replies; 79+ messages in thread
From: Jani Nikula @ 2019-06-11 10:01 UTC (permalink / raw)
  To: Lucas De Marchi; +Cc: intel-gfx, Paulo Zanoni

On Mon, 10 Jun 2019, Lucas De Marchi <lucas.de.marchi@gmail.com> wrote:
> On Thu, Jun 06, 2019 at 11:42:46AM +0300, Jani Nikula wrote:
>>On Tue, 04 Jun 2019, Imre Deak <imre.deak@intel.com> wrote:
>>From the Nitpicks Department, please add a blank line here.
>>
>>> +#include "intel_display.h"
>>> +#include "i915_drv.h"
>>> +#include "intel_tc.h"
>>
>>And sort the includes.
>
> humn... In some other projects I use the convention of always having the
> correspondent header to be included first and the rest sorted. Here it
> would be like:
>
> #include "intel_tc.h"
>
> #include "intel_display.h"
> #include "intel_drv.h"
>
> This way we guarantee that intel_tc.h header is self-contained: anything
> it needs, it includes or declares.  If we adopted such convention I don't
> see why we would still need Makefile.header-test for example.

I think the long standing convention is to have <asm>, <linux>, and
<drm> headers included before "local" headers.

Eventually the version of header tests that I've submitted to kbuild
upstream will obsolete the Makefile.header-test files, and I expect us
to have simply

header-test-y := $(notdir $(wildcard $(src)/*.h))

in there, testing everything.

BR,
Jani.


-- 
Jani Nikula, Intel Open Source Graphics Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 04/23] drm/i915: Sanitize the terminology used for TypeC port modes
  2019-06-10 23:21   ` Lucas De Marchi
@ 2019-06-11 11:19     ` Imre Deak
  0 siblings, 0 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-11 11:19 UTC (permalink / raw)
  To: Lucas De Marchi; +Cc: intel-gfx, Paulo Zanoni

On Mon, Jun 10, 2019 at 04:21:30PM -0700, Lucas De Marchi wrote:
> On Tue, Jun 04, 2019 at 05:58:07PM +0300, Imre Deak wrote:
> > 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.
> 
> \o/
> 
> > 
> > - 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.
> 
> I think the unknown was there to cover the first time we set the type
> (aka mode). Since we don't do this during initialization and only when
> updating the connected state, we needed that to protect some functions.

Ok, but the mode is still known even before updating the connected state
(that is probing), we just have to make sure that we read out the HW
state (which is what this mode is) early enough. At least selecting the
proper AUX power well (DP-Alt or TBT-Alt AUX) depends on this.

That HW readout happens already now via the intel_ddi_init() function.

> > 
> > - Don't WARN if the port mode changes, that can happen normally.
> > 
> > No functional changes.
> > 
> > Cc: Animesh Manna <animesh.manna@intel.com>
> > Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > Cc: Anusha Srivatsa <anusha.srivatsa@intel.com>
> > Cc: José Roberto de Souza <jose.souza@intel.com>
> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> > drivers/gpu/drm/i915/intel_ddi.c      | 11 +++---
> > drivers/gpu/drm/i915/intel_display.h  |  7 ++--
> > drivers/gpu/drm/i915/intel_dp.c       |  2 +-
> > drivers/gpu/drm/i915/intel_dpll_mgr.c |  2 +-
> > drivers/gpu/drm/i915/intel_drv.h      |  2 +-
> > drivers/gpu/drm/i915/intel_tc.c       | 48 +++++++++++----------------
> > 6 files changed, 31 insertions(+), 41 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> > index 5a1c98438375..a3574f14a3d0 100644
> > --- a/drivers/gpu/drm/i915/intel_ddi.c
> > +++ b/drivers/gpu/drm/i915/intel_ddi.c
> > @@ -2986,14 +2986,14 @@ static void icl_program_mg_dp_mode(struct intel_digital_port *intel_dig_port)
> > 	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
> > 	u32 ln0, ln1, lane_info;
> > 
> > -	if (tc_port == PORT_TC_NONE || intel_dig_port->tc_type == TC_PORT_TBT)
> > +	if (intel_dig_port->tc_mode == TC_PORT_TBT_ALT)
> > 		return;
> > 
> > 	ln0 = I915_READ(MG_DP_MODE(0, port));
> > 	ln1 = I915_READ(MG_DP_MODE(1, port));
> > 
> > -	switch (intel_dig_port->tc_type) {
> > -	case TC_PORT_TYPEC:
> > +	switch (intel_dig_port->tc_mode) {
> > +	case TC_PORT_DP_ALT:
> > 		ln0 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
> > 		ln1 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
> > 
> > @@ -3036,7 +3036,7 @@ static void icl_program_mg_dp_mode(struct intel_digital_port *intel_dig_port)
> > 		break;
> > 
> > 	default:
> > -		MISSING_CASE(intel_dig_port->tc_type);
> > +		MISSING_CASE(intel_dig_port->tc_mode);
> > 		return;
> > 	}
> > 
> > @@ -3630,8 +3630,7 @@ intel_ddi_pre_pll_enable(struct intel_encoder *encoder,
> > 	 * Program the lane count for static/dynamic connections on Type-C ports.
> > 	 * Skip this step for TBT.
> > 	 */
> > -	if (dig_port->tc_type == TC_PORT_UNKNOWN ||
> > -	    dig_port->tc_type == TC_PORT_TBT)
> > +	if (dig_port->tc_mode == TC_PORT_TBT_ALT)
> > 		return;
> > 
> > 	intel_ddi_set_fia_lane_count(encoder, crtc_state, port);
> > diff --git a/drivers/gpu/drm/i915/intel_display.h b/drivers/gpu/drm/i915/intel_display.h
> > index ee6b8194a459..d296556ed82e 100644
> > --- a/drivers/gpu/drm/i915/intel_display.h
> > +++ b/drivers/gpu/drm/i915/intel_display.h
> > @@ -189,10 +189,9 @@ enum tc_port {
> > 	I915_MAX_TC_PORTS
> > };
> > 
> > -enum tc_port_type {
> > -	TC_PORT_UNKNOWN = 0,
> > -	TC_PORT_TYPEC,
> > -	TC_PORT_TBT,
> > +enum tc_port_mode {
> > +	TC_PORT_TBT_ALT,
> > +	TC_PORT_DP_ALT,
> > 	TC_PORT_LEGACY,
> > };
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index b69310bd9914..e1e27662aa6d 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -1175,7 +1175,7 @@ static u32 skl_get_aux_send_ctl(struct intel_dp *intel_dp,
> > 	      DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(32) |
> > 	      DP_AUX_CH_CTL_SYNC_PULSE_SKL(32);
> > 
> > -	if (intel_dig_port->tc_type == TC_PORT_TBT)
> > +	if (intel_dig_port->tc_mode == TC_PORT_TBT_ALT)
> > 		ret |= DP_AUX_CH_CTL_TBT_IO;
> > 
> > 	return ret;
> > diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
> > index 69787f259677..f4787650a0d3 100644
> > --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
> > +++ b/drivers/gpu/drm/i915/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);
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 0dcc03592d6e..30cd49dbd0d8 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -1225,7 +1225,7 @@ struct intel_digital_port {
> > 	enum aux_ch aux_ch;
> > 	enum intel_display_power_domain ddi_io_power_domain;
> > 	bool tc_legacy_port:1;
> 
> not related, but why do we add a hole in the struct on purpose?!?

The purpose was to group all the TypeC related fields at one spot. We
could save some space gathering all the bools in this struct
(release_cl2_override, tc_legacy_port) into a bool bitfield.

> 
> > -	enum tc_port_type tc_type;
> > +	enum tc_port_mode tc_mode;
> > 
> > 	void (*write_infoframe)(struct intel_encoder *encoder,
> > 				const struct intel_crtc_state *crtc_state,
> > diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
> > index 7a1b5870945f..a3057c44bec6 100644
> > --- a/drivers/gpu/drm/i915/intel_tc.c
> > +++ b/drivers/gpu/drm/i915/intel_tc.c
> > @@ -6,19 +6,18 @@
> > #include "i915_drv.h"
> > #include "intel_tc.h"
> > 
> > -static const char *tc_type_name(enum tc_port_type type)
> > +static const char *tc_port_mode_name(enum tc_port_mode mode)
> > {
> > 	static const char * const names[] = {
> > -		[TC_PORT_UNKNOWN] = "unknown",
> > +		[TC_PORT_TBT_ALT] = "tbt-alt",
> > +		[TC_PORT_DP_ALT] = "dp-alt",
> > 		[TC_PORT_LEGACY] = "legacy",
> > -		[TC_PORT_TYPEC] = "typec",
> > -		[TC_PORT_TBT] = "tbt",
> > 	};
> > 
> > -	if (WARN_ON(type >= ARRAY_SIZE(names)))
> > -		type = TC_PORT_UNKNOWN;
> > +	if (WARN_ON(mode >= ARRAY_SIZE(names)))
> > +		mode = TC_PORT_TBT_ALT;
> > 
> > -	return names[type];
> > +	return names[mode];
> > }
> > 
> > int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
> > @@ -28,7 +27,7 @@ int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
> > 	intel_wakeref_t wakeref;
> > 	u32 lane_info;
> > 
> > -	if (tc_port == PORT_TC_NONE || dig_port->tc_type != TC_PORT_TYPEC)
> > +	if (dig_port->tc_mode != TC_PORT_DP_ALT)
> > 		return 4;
> > 
> > 	lane_info = 0;
> > @@ -80,8 +79,8 @@ static bool icl_tc_phy_connect(struct intel_digital_port *dig_port)
> > 	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> > 	u32 val;
> > 
> > -	if (dig_port->tc_type != TC_PORT_LEGACY &&
> > -	    dig_port->tc_type != TC_PORT_TYPEC)
> > +	if (dig_port->tc_mode != TC_PORT_LEGACY &&
> > +	    dig_port->tc_mode != TC_PORT_DP_ALT)
> > 		return true;
> > 
> > 	val = I915_READ(PORT_TX_DFLEXDPPMS);
> > @@ -105,7 +104,7 @@ static bool icl_tc_phy_connect(struct intel_digital_port *dig_port)
> > 	 * Now we have to re-check the live state, in case the port recently
> > 	 * became disconnected. Not necessary for legacy mode.
> > 	 */
> > -	if (dig_port->tc_type == TC_PORT_TYPEC &&
> > +	if (dig_port->tc_mode == TC_PORT_DP_ALT &&
> > 	    !(I915_READ(PORT_TX_DFLEXDPSP) & TC_LIVE_STATE_TC(tc_port))) {
> > 		DRM_DEBUG_KMS("TC PHY %d sudden disconnect.\n", tc_port);
> > 		icl_tc_phy_disconnect(dig_port);
> > @@ -124,15 +123,12 @@ void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
> > 	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> > 	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> > 
> > -	if (dig_port->tc_type == TC_PORT_UNKNOWN)
> > -		return;
> > -
> > 	/*
> > 	 * TBT disconnection flow is read the live status, what was done in
> > 	 * caller.
> > 	 */
> > -	if (dig_port->tc_type == TC_PORT_TYPEC ||
> > -	    dig_port->tc_type == TC_PORT_LEGACY) {
> > +	if (dig_port->tc_mode == TC_PORT_DP_ALT ||
> > +	    dig_port->tc_mode == TC_PORT_LEGACY) {
> > 		u32 val;
> > 
> > 		val = I915_READ(PORT_TX_DFLEXDPCSSS);
> > @@ -142,9 +138,9 @@ void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
> > 
> > 	DRM_DEBUG_KMS("Port %c TC type %s disconnected\n",
> > 		      port_name(dig_port->base.port),
> > -		      tc_type_name(dig_port->tc_type));
> > +		      tc_port_mode_name(dig_port->tc_mode));
> > 
> > -	dig_port->tc_type = TC_PORT_UNKNOWN;
> > +	dig_port->tc_mode = TC_PORT_TBT_ALT;
> 
> humn... if this is what the hw has after reset,

Yes, IOW if we'd only connect/disconnect a TBT-Alt sink we wouldn't have
to do anything to connect/disconnect the PHY (icl_tc_phy_connect() /
icl_tc_phy_disconnect() would both become NOPs). That's unlike if we'd
had only a DP-Alt/legacy sink where we have the TypeC specific
programming steps to connect/disconnect the PHY.

> then I think it covers my concern above.


> Reviewed-by: Lucas De Marchi <lucas.demarchi@intel.com>
> 
> Lucas De Marchi
> 
> > }
> > 
> > static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
> > @@ -152,26 +148,22 @@ static void icl_update_tc_port_type(struct drm_i915_private *dev_priv,
> > 				    bool is_legacy, bool is_typec, bool is_tbt)
> > {
> > 	enum port port = intel_dig_port->base.port;
> > -	enum tc_port_type old_type = intel_dig_port->tc_type;
> > +	enum tc_port_mode old_mode = intel_dig_port->tc_mode;
> > 
> > 	WARN_ON(is_legacy + is_typec + is_tbt != 1);
> > 
> > 	if (is_legacy)
> > -		intel_dig_port->tc_type = TC_PORT_LEGACY;
> > +		intel_dig_port->tc_mode = TC_PORT_LEGACY;
> > 	else if (is_typec)
> > -		intel_dig_port->tc_type = TC_PORT_TYPEC;
> > +		intel_dig_port->tc_mode = TC_PORT_DP_ALT;
> > 	else if (is_tbt)
> > -		intel_dig_port->tc_type = TC_PORT_TBT;
> > +		intel_dig_port->tc_mode = TC_PORT_TBT_ALT;
> > 	else
> > 		return;
> > 
> > -	/* Types are not supposed to be changed at runtime. */
> > -	WARN_ON(old_type != TC_PORT_UNKNOWN &&
> > -		old_type != intel_dig_port->tc_type);
> > -
> > -	if (old_type != intel_dig_port->tc_type)
> > +	if (old_mode != intel_dig_port->tc_mode)
> > 		DRM_DEBUG_KMS("Port %c has TC type %s\n", port_name(port),
> > -			      tc_type_name(intel_dig_port->tc_type));
> > +			      tc_port_mode_name(intel_dig_port->tc_mode));
> > }
> > 
> > 
> > -- 
> > 2.17.1
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 09/23] drm/i915: Factor out common parts from TypeC port handling functions
  2019-06-04 14:58 ` [PATCH 09/23] drm/i915: Factor out common parts from TypeC port handling functions Imre Deak
  2019-06-06  8:47   ` Jani Nikula
  2019-06-07 21:22   ` Souza, Jose
@ 2019-06-18 16:33   ` Ville Syrjälä
  2019-06-18 16:44     ` Imre Deak
  2 siblings, 1 reply; 79+ messages in thread
From: Ville Syrjälä @ 2019-06-18 16:33 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx, Paulo Zanoni

On Tue, Jun 04, 2019 at 05:58:12PM +0300, Imre Deak wrote:
> Factor out helpers reading/parsing the TypeC specific registers, making
> current users of them clearer and letting us use them later.
> 
> While at it also:
> - Simplify icl_tc_phy_connect() with an early return in legacy mode.
> - Simplify the live status check using one bitmask for all HPD bits.
> - Remove a micro-optimisation of the repeated safe-mode clearing.
> - Make sure we fix the legacy port flag in all cases.
> 
> Except for the last two, no functional changes.
> 
> Cc: José Roberto de Souza <jose.souza@intel.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_ddi.c |   5 +-
>  drivers/gpu/drm/i915/intel_tc.c  | 166 +++++++++++++++++++------------
>  drivers/gpu/drm/i915/intel_tc.h  |   1 +
>  3 files changed, 103 insertions(+), 69 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index 8f223d48d562..d236839bee19 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -2983,7 +2983,6 @@ static void icl_program_mg_dp_mode(struct intel_digital_port *intel_dig_port)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
>  	enum port port = intel_dig_port->base.port;
> -	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
>  	u32 ln0, ln1, lane_info;
>  
>  	if (intel_dig_port->tc_mode == TC_PORT_TBT_ALT)
> @@ -2997,9 +2996,7 @@ static void icl_program_mg_dp_mode(struct intel_digital_port *intel_dig_port)
>  		ln0 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
>  		ln1 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
>  
> -		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
> -			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
> -			    DP_LANE_ASSIGNMENT_SHIFT(tc_port);
> +		lane_info = intel_tc_port_get_lane_info(intel_dig_port);
>  
>  		switch (lane_info) {
>  		case 0x1:
> diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
> index 07488235b67a..3fdcfa2bbaee 100644
> --- a/drivers/gpu/drm/i915/intel_tc.c
> +++ b/drivers/gpu/drm/i915/intel_tc.c
> @@ -43,10 +43,19 @@ static const char *tc_port_mode_name(enum tc_port_mode mode)
>  	return names[mode];
>  }
>  
> -int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
> +u32 intel_tc_port_get_lane_info(struct intel_digital_port *dig_port)

get_lane_mask() or something?

>  {
>  	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
>  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> +	u32 lane_info = I915_READ(PORT_TX_DFLEXDPSP);
> +
> +	return (lane_info & DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
> +	       DP_LANE_ASSIGNMENT_SHIFT(tc_port);
> +}
> +
> +int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
>  	intel_wakeref_t wakeref;
>  	u32 lane_info;
>  
> @@ -55,9 +64,7 @@ int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
>  
>  	lane_info = 0;
>  	with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref)
> -		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
> -			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
> -				DP_LANE_ASSIGNMENT_SHIFT(tc_port);
> +		lane_info = intel_tc_port_get_lane_info(dig_port);
>  
>  	switch (lane_info) {
>  	default:
> @@ -75,6 +82,69 @@ int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
>  	}
>  }
>  
> +static void tc_port_fixup_legacy_flag(struct intel_digital_port *dig_port,
> +				      u32 live_status_mask)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> +	u32 valid_hpd_mask = dig_port->tc_legacy_port ? BIT(TC_PORT_LEGACY) :
> +							~BIT(TC_PORT_LEGACY);
> +
> +	if (!(live_status_mask & ~valid_hpd_mask))
> +		return;

A bit too many nots for me to follow. I guess what it's doing is
checking if any of the other bits are set, and if so it assumes the
mode was misdeclared in vbt? 

Actually, won't this end up ping-ponging back and forth if the
hw really reports both legacy and non-legacy bits as set?

> +
> +	/* If live status mismatches the VBT flag, trust the live status. */
> +	DRM_ERROR("Port %s: live status %08x mismatches the legacy port flag, fix flag\n",
> +		  tc_port_name(dev_priv, tc_port), live_status_mask);
> +
> +	dig_port->tc_legacy_port = !dig_port->tc_legacy_port;
> +}
> +

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

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 15/23] drm/i915: Sanitize the TypeC FIA lane configuration decoding
  2019-06-04 14:58 ` [PATCH 15/23] drm/i915: Sanitize the TypeC FIA lane configuration decoding Imre Deak
  2019-06-07 22:49   ` Souza, Jose
@ 2019-06-18 16:39   ` Ville Syrjälä
  2019-06-18 16:46     ` Imre Deak
  1 sibling, 1 reply; 79+ messages in thread
From: Ville Syrjälä @ 2019-06-18 16:39 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Jun 04, 2019 at 05:58:18PM +0300, Imre Deak wrote:
> Use hex numbers, since that makes more sense when decoding a bit pattern.
> 
> No functional change.
> 
> Suggested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Animesh Manna <animesh.manna@intel.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_tc.c | 15 ++++++++-------
>  1 file changed, 8 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
> index fc0341dc50c5..4b2f525bc2a6 100644
> --- a/drivers/gpu/drm/i915/intel_tc.c
> +++ b/drivers/gpu/drm/i915/intel_tc.c
> @@ -72,15 +72,16 @@ int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
>  	switch (lane_info) {
>  	default:
>  		MISSING_CASE(lane_info);
> -	case 1:
> -	case 2:
> -	case 4:
> -	case 8:
> +		/* fall-through */
> +	case 0x1:
> +	case 0x2:
> +	case 0x4:
> +	case 0x8:
>  		return 1;
> -	case 3:
> -	case 12:
> +	case 0x3:
> +	case 0xc:
>  		return 2;
> -	case 15:
> +	case 0xf:
>  		return 4;
>  	}

Still looks like a hand rolled hweight() to me ;)

>  }
> -- 
> 2.17.1

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

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 09/23] drm/i915: Factor out common parts from TypeC port handling functions
  2019-06-18 16:33   ` Ville Syrjälä
@ 2019-06-18 16:44     ` Imre Deak
  0 siblings, 0 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-18 16:44 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, Paulo Zanoni

On Tue, Jun 18, 2019 at 07:33:13PM +0300, Ville Syrjälä wrote:
> On Tue, Jun 04, 2019 at 05:58:12PM +0300, Imre Deak wrote:
> > Factor out helpers reading/parsing the TypeC specific registers, making
> > current users of them clearer and letting us use them later.
> > 
> > While at it also:
> > - Simplify icl_tc_phy_connect() with an early return in legacy mode.
> > - Simplify the live status check using one bitmask for all HPD bits.
> > - Remove a micro-optimisation of the repeated safe-mode clearing.
> > - Make sure we fix the legacy port flag in all cases.
> > 
> > Except for the last two, no functional changes.
> > 
> > Cc: José Roberto de Souza <jose.souza@intel.com>
> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_ddi.c |   5 +-
> >  drivers/gpu/drm/i915/intel_tc.c  | 166 +++++++++++++++++++------------
> >  drivers/gpu/drm/i915/intel_tc.h  |   1 +
> >  3 files changed, 103 insertions(+), 69 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> > index 8f223d48d562..d236839bee19 100644
> > --- a/drivers/gpu/drm/i915/intel_ddi.c
> > +++ b/drivers/gpu/drm/i915/intel_ddi.c
> > @@ -2983,7 +2983,6 @@ static void icl_program_mg_dp_mode(struct intel_digital_port *intel_dig_port)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
> >  	enum port port = intel_dig_port->base.port;
> > -	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
> >  	u32 ln0, ln1, lane_info;
> >  
> >  	if (intel_dig_port->tc_mode == TC_PORT_TBT_ALT)
> > @@ -2997,9 +2996,7 @@ static void icl_program_mg_dp_mode(struct intel_digital_port *intel_dig_port)
> >  		ln0 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
> >  		ln1 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
> >  
> > -		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
> > -			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
> > -			    DP_LANE_ASSIGNMENT_SHIFT(tc_port);
> > +		lane_info = intel_tc_port_get_lane_info(intel_dig_port);
> >  
> >  		switch (lane_info) {
> >  		case 0x1:
> > diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
> > index 07488235b67a..3fdcfa2bbaee 100644
> > --- a/drivers/gpu/drm/i915/intel_tc.c
> > +++ b/drivers/gpu/drm/i915/intel_tc.c
> > @@ -43,10 +43,19 @@ static const char *tc_port_mode_name(enum tc_port_mode mode)
> >  	return names[mode];
> >  }
> >  
> > -int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
> > +u32 intel_tc_port_get_lane_info(struct intel_digital_port *dig_port)
> 
> get_lane_mask() or something?

Ok.

> 
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> >  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> > +	u32 lane_info = I915_READ(PORT_TX_DFLEXDPSP);
> > +
> > +	return (lane_info & DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
> > +	       DP_LANE_ASSIGNMENT_SHIFT(tc_port);
> > +}
> > +
> > +int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> >  	intel_wakeref_t wakeref;
> >  	u32 lane_info;
> >  
> > @@ -55,9 +64,7 @@ int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
> >  
> >  	lane_info = 0;
> >  	with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref)
> > -		lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
> > -			     DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
> > -				DP_LANE_ASSIGNMENT_SHIFT(tc_port);
> > +		lane_info = intel_tc_port_get_lane_info(dig_port);
> >  
> >  	switch (lane_info) {
> >  	default:
> > @@ -75,6 +82,69 @@ int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
> >  	}
> >  }
> >  
> > +static void tc_port_fixup_legacy_flag(struct intel_digital_port *dig_port,
> > +				      u32 live_status_mask)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> > +	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> > +	u32 valid_hpd_mask = dig_port->tc_legacy_port ? BIT(TC_PORT_LEGACY) :
> > +							~BIT(TC_PORT_LEGACY);
> > +
> > +	if (!(live_status_mask & ~valid_hpd_mask))
> > +		return;
> 
> A bit too many nots for me to follow. I guess what it's doing is
> checking if any of the other bits are set, and if so it assumes the
> mode was misdeclared in vbt? 

Yes.

> 
> Actually, won't this end up ping-ponging back and forth if the
> hw really reports both legacy and non-legacy bits as set?

If you mean multiple HPD bits being set by HW, we won't call this
function to fix up the flag.

> 
> > +
> > +	/* If live status mismatches the VBT flag, trust the live status. */
> > +	DRM_ERROR("Port %s: live status %08x mismatches the legacy port flag, fix flag\n",
> > +		  tc_port_name(dev_priv, tc_port), live_status_mask);
> > +
> > +	dig_port->tc_legacy_port = !dig_port->tc_legacy_port;
> > +}
> > +
> 
> -- 
> Ville Syrjälä
> Intel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 15/23] drm/i915: Sanitize the TypeC FIA lane configuration decoding
  2019-06-18 16:39   ` Ville Syrjälä
@ 2019-06-18 16:46     ` Imre Deak
  0 siblings, 0 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-18 16:46 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Tue, Jun 18, 2019 at 07:39:09PM +0300, Ville Syrjälä wrote:
> On Tue, Jun 04, 2019 at 05:58:18PM +0300, Imre Deak wrote:
> > Use hex numbers, since that makes more sense when decoding a bit pattern.
> > 
> > No functional change.
> > 
> > Suggested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Cc: Animesh Manna <animesh.manna@intel.com>
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_tc.c | 15 ++++++++-------
> >  1 file changed, 8 insertions(+), 7 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
> > index fc0341dc50c5..4b2f525bc2a6 100644
> > --- a/drivers/gpu/drm/i915/intel_tc.c
> > +++ b/drivers/gpu/drm/i915/intel_tc.c
> > @@ -72,15 +72,16 @@ int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
> >  	switch (lane_info) {
> >  	default:
> >  		MISSING_CASE(lane_info);
> > -	case 1:
> > -	case 2:
> > -	case 4:
> > -	case 8:
> > +		/* fall-through */
> > +	case 0x1:
> > +	case 0x2:
> > +	case 0x4:
> > +	case 0x8:
> >  		return 1;
> > -	case 3:
> > -	case 12:
> > +	case 0x3:
> > +	case 0xc:
> >  		return 2;
> > -	case 15:
> > +	case 0xf:
> >  		return 4;
> >  	}
> 
> Still looks like a hand rolled hweight() to me ;)

Thought about that, but then we'd miss undefined encodings.

> 
> >  }
> > -- 
> > 2.17.1
> 
> -- 
> Ville Syrjälä
> Intel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH v2 19/23] drm/i915/icl: Reserve all required PLLs for TypeC ports
  2019-06-07 17:41   ` [PATCH v2 " Imre Deak
@ 2019-06-18 17:25     ` Ville Syrjälä
  2019-06-18 18:02       ` Imre Deak
  0 siblings, 1 reply; 79+ messages in thread
From: Ville Syrjälä @ 2019-06-18 17:25 UTC (permalink / raw)
  To: Imre Deak; +Cc: Daniel Vetter, intel-gfx

On Fri, Jun 07, 2019 at 08:41:29PM +0300, Imre Deak wrote:
> 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.
> 
> 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>
> ---
>  drivers/gpu/drm/i915/intel_display.c  |  11 +-
>  drivers/gpu/drm/i915/intel_dpll_mgr.c | 151 +++++++++++++++++++-------
>  drivers/gpu/drm/i915/intel_dpll_mgr.h |   9 ++
>  drivers/gpu/drm/i915/intel_drv.h      |   9 ++
>  4 files changed, 138 insertions(+), 42 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 7381fb2e1240..006be3c3f1bd 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -9880,6 +9880,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;
>  
> @@ -9887,22 +9888,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,
> @@ -12041,6 +12048,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/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
> index 8ac293db43a5..17441d5f990e 100644
> --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
> +++ b/drivers/gpu/drm/i915/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 =
> +		&crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT];

I would move that initialization next to the code so that the
tbt vs. mg cases look more like twins.

> +	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);
> +	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,24 @@ 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);
> +	}
> +}
> +
>  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 +3399,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 +3412,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/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h
> index 6ffdcc06ad23..3bea81bde343 100644
> --- a/drivers/gpu/drm/i915/intel_dpll_mgr.h
> +++ b/drivers/gpu/drm/i915/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 f9b6f63ebbfe..7f1dcb8d8a28 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;

I was pondering if we should use this array on non-icl too.
Would avoid having three instances of this state embedded in
our crtc state. But I don't know how big the struct is so not
sure if it's worth it. 

Anyways, something to think about for a future optimization.

> +	} icl_port_dplls[ICL_PORT_DPLL_COUNT];
> +
>  	/* DSI PLL registers */
>  	struct {
>  		u32 ctrl, div;
> -- 
> 2.17.1

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

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH v2 19/23] drm/i915/icl: Reserve all required PLLs for TypeC ports
  2019-06-18 17:25     ` Ville Syrjälä
@ 2019-06-18 18:02       ` Imre Deak
  0 siblings, 0 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-18 18:02 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Daniel Vetter, intel-gfx

On Tue, Jun 18, 2019 at 08:25:52PM +0300, Ville Syrjälä wrote:
> On Fri, Jun 07, 2019 at 08:41:29PM +0300, Imre Deak wrote:
> > 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.
> > 
> > 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>
> > ---
> >  drivers/gpu/drm/i915/intel_display.c  |  11 +-
> >  drivers/gpu/drm/i915/intel_dpll_mgr.c | 151 +++++++++++++++++++-------
> >  drivers/gpu/drm/i915/intel_dpll_mgr.h |   9 ++
> >  drivers/gpu/drm/i915/intel_drv.h      |   9 ++
> >  4 files changed, 138 insertions(+), 42 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 7381fb2e1240..006be3c3f1bd 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -9880,6 +9880,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;
> >  
> > @@ -9887,22 +9888,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,
> > @@ -12041,6 +12048,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/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
> > index 8ac293db43a5..17441d5f990e 100644
> > --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
> > +++ b/drivers/gpu/drm/i915/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 =
> > +		&crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT];
> 
> I would move that initialization next to the code so that the
> tbt vs. mg cases look more like twins.

Ok.

> 
> > +	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);
> > +	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,24 @@ 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);
> > +	}
> > +}
> > +
> >  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 +3399,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 +3412,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/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h
> > index 6ffdcc06ad23..3bea81bde343 100644
> > --- a/drivers/gpu/drm/i915/intel_dpll_mgr.h
> > +++ b/drivers/gpu/drm/i915/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 f9b6f63ebbfe..7f1dcb8d8a28 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;
> 
> I was pondering if we should use this array on non-icl too.
> Would avoid having three instances of this state embedded in
> our crtc state. But I don't know how big the struct is so not
> sure if it's worth it. 
> 
> Anyways, something to think about for a future optimization.

Yep, would be good to make it more generic, expressing it also better
that hw_state is pll's state.

I suppose that would be instead of the above

	struct intel_port_dpll {
		struct intel_shared_dpll *pll;
		struct intel_dpll_hw_state hw_state;
	} port_dplls[PORT_DPLL_COUNT];

	struct intel_port_dpll *active_dpll;

removing also intel_crtc_state::dpll_hw_state and shared_dpll.

I chickened out of doing that too now, affecting many platforms, but
would be worth doing as a follow-up.

> 
> > +	} icl_port_dplls[ICL_PORT_DPLL_COUNT];
> > +
> >  	/* DSI PLL registers */
> >  	struct {
> >  		u32 ctrl, div;
> > -- 
> > 2.17.1
> 
> -- 
> Ville Syrjälä
> Intel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 20/23] drm/i915: Keep the TypeC port mode fixed when the port is active
  2019-06-04 14:58 ` [PATCH 20/23] drm/i915: Keep the TypeC port mode fixed when the port is active Imre Deak
@ 2019-06-19 12:58   ` Ville Syrjälä
  2019-06-19 16:08     ` Imre Deak
  0 siblings, 1 reply; 79+ messages in thread
From: Ville Syrjälä @ 2019-06-19 12:58 UTC (permalink / raw)
  To: Imre Deak; +Cc: Daniel Vetter, intel-gfx

On Tue, Jun 04, 2019 at 05:58:23PM +0300, Imre Deak wrote:
> 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
> connector_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.
> 
> 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>
> ---
>  drivers/gpu/drm/i915/intel_ddi.c      | 46 +++++++++++--
>  drivers/gpu/drm/i915/intel_ddi.h      |  7 ++
>  drivers/gpu/drm/i915/intel_display.c  | 90 +++++++++++++++++++++++++-
>  drivers/gpu/drm/i915/intel_dp.c       |  7 ++
>  drivers/gpu/drm/i915/intel_dp_mst.c   |  6 ++
>  drivers/gpu/drm/i915/intel_dpll_mgr.c | 28 +++++++-
>  drivers/gpu/drm/i915/intel_dpll_mgr.h |  3 +
>  drivers/gpu/drm/i915/intel_drv.h      |  9 +++
>  drivers/gpu/drm/i915/intel_hdmi.c     |  7 ++
>  drivers/gpu/drm/i915/intel_tc.c       | 93 ++++++++++++++++++++-------
>  drivers/gpu/drm/i915/intel_tc.h       |  3 +
>  11 files changed, 269 insertions(+), 30 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index ad2f7bb2f50b..138950941246 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -3610,6 +3610,38 @@ static void intel_ddi_set_fia_lane_count(struct intel_encoder *encoder,
>  	I915_WRITE(PORT_TX_DFLEXDPMLE1, val);
>  }
>  
> +void
> +intel_ddi_connector_update_prepare(struct intel_atomic_state *state,
> +				   struct intel_connector *connector)
> +{
> +	struct drm_connector_state *conn_state =
> +		drm_atomic_get_new_connector_state(&state->base,
> +						   &connector->base);
> +	struct intel_crtc *crtc = conn_state->crtc ?
> +		to_intel_crtc(conn_state->crtc) : NULL;
> +	struct intel_crtc_state *crtc_state =
> +		crtc ? intel_atomic_get_new_crtc_state(state, crtc) : NULL;
> +	struct intel_digital_port *primary_port =
> +		intel_connector_primary_digital_port(connector);
> +	int required_lanes = crtc_state ? crtc_state->lane_count : 1;
> +
> +	WARN_ON(crtc && crtc->active);
> +
> +	intel_tc_port_get_link(primary_port, required_lanes);
> +	if (crtc_state && crtc_state->base.active)
> +		intel_update_active_dpll(state, crtc, &primary_port->base);
> +}

Having this as a connector hook feels a bit strange. I guess moving it
to encoder level would feel more in line with the rest of the hooks, and
would avoid having that intel_connector_primary_digital_port() thing
because then the mst code could just pass in the right thing itself.
Hmm. Or maybe that wouldn't actually work because of
intel_connector->encoder being wonky on MST :(

Although if we just put the hooks on the main encoder and not on the
MST ones it could maybe work. Would still need
intel_connector_primary_digital_port() to dig out the encoder though.

Not sure.

> +
> +void
> +intel_ddi_connector_update_complete(struct intel_atomic_state *state,
> +				    struct intel_connector *connector)
> +{
> +	struct intel_digital_port *primary_port =
> +		intel_connector_primary_digital_port(connector);
> +
> +	intel_tc_port_put_link(primary_port);
> +}
> +
>  static void
>  intel_ddi_pre_pll_enable(struct intel_encoder *encoder,
>  			 const struct intel_crtc_state *crtc_state,
> @@ -3617,10 +3649,13 @@ intel_ddi_pre_pll_enable(struct intel_encoder *encoder,
>  {
>  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>  	struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
> +	bool is_tc_port = intel_port_is_tc(dev_priv, encoder->port);
>  	enum port port = encoder->port;
>  
> -	if (intel_crtc_has_dp_encoder(crtc_state) ||
> -	    intel_port_is_tc(dev_priv, encoder->port))
> +	if (is_tc_port)
> +		intel_tc_port_get_link(dig_port, crtc_state->lane_count);
> +
> +	if (intel_crtc_has_dp_encoder(crtc_state) || is_tc_port)
>  		intel_display_power_get(dev_priv,
>  					intel_ddi_main_link_aux_domain(dig_port));
>  
> @@ -3645,11 +3680,14 @@ intel_ddi_post_pll_disable(struct intel_encoder *encoder,
>  {
>  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>  	struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
> +	bool is_tc_port = intel_port_is_tc(dev_priv, encoder->port);
>  
> -	if (intel_crtc_has_dp_encoder(crtc_state) ||
> -	    intel_port_is_tc(dev_priv, encoder->port))
> +	if (intel_crtc_has_dp_encoder(crtc_state) || is_tc_port)
>  		intel_display_power_put_unchecked(dev_priv,
>  						  intel_ddi_main_link_aux_domain(dig_port));
> +
> +	if (is_tc_port)
> +		intel_tc_port_put_link(dig_port);
>  }
>  
>  void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
> diff --git a/drivers/gpu/drm/i915/intel_ddi.h b/drivers/gpu/drm/i915/intel_ddi.h
> index 9cf69175942e..1559d1fbf7bd 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.h
> +++ b/drivers/gpu/drm/i915/intel_ddi.h
> @@ -12,6 +12,7 @@
>  
>  struct drm_connector_state;
>  struct drm_i915_private;
> +struct intel_atomic_state;
>  struct intel_connector;
>  struct intel_crtc;
>  struct intel_crtc_state;
> @@ -35,6 +36,12 @@ void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp);
>  bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector);
>  void intel_ddi_get_config(struct intel_encoder *encoder,
>  			  struct intel_crtc_state *pipe_config);
> +void
> +intel_ddi_connector_update_prepare(struct intel_atomic_state *state,
> +				   struct intel_connector *connector);
> +void
> +intel_ddi_connector_update_complete(struct intel_atomic_state *state,
> +				    struct intel_connector *connector);
>  void intel_ddi_set_vc_payload_alloc(const struct intel_crtc_state *crtc_state,
>  				    bool state);
>  void intel_ddi_compute_min_voltage_level(struct drm_i915_private *dev_priv,
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index f86b5b848cbc..2c65587d1622 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -520,6 +520,20 @@ needs_modeset(const struct drm_crtc_state *state)
>  	return drm_atomic_crtc_needs_modeset(state);
>  }
>  
> +static bool
> +intel_connector_needs_modeset(struct intel_atomic_state *state,
> +			      const struct drm_connector_state *old_conn_state,
> +			      const struct drm_connector_state *new_conn_state)
> +{
> +	if (new_conn_state->crtc != old_conn_state->crtc ||
> +	    (new_conn_state->crtc &&
> +	     needs_modeset(drm_atomic_get_new_crtc_state(&state->base,
> +							 new_conn_state->crtc))))
> +		return true;
> +
> +	return false;

Pointless if statement. Or is there more coming here?

> +}
> +
>  /*
>   * Platform specific helpers to calculate the port PLL loopback- (clock.m),
>   * and post-divider (clock.p) values, pre- (clock.vco) and post-divided fast
> @@ -6032,6 +6046,52 @@ static void intel_crtc_disable_planes(struct intel_atomic_state *state,
>  	intel_frontbuffer_flip(dev_priv, fb_bits);
>  }
>  
> +static void intel_connectors_update_prepare(struct intel_atomic_state *state)
> +{
> +	struct drm_connector_state *old_conn_state;
> +	struct drm_connector_state *new_conn_state;
> +	struct drm_connector *conn;
> +	int i;
> +
> +	for_each_oldnew_connector_in_state(&state->base, conn,
> +					   old_conn_state, new_conn_state, i) {
> +		struct intel_connector *connector = to_intel_connector(conn);
> +
> +		if (!connector->update_prepare)
> +			continue;
> +
> +		if (!intel_connector_needs_modeset(state,
> +						   old_conn_state,
> +						   new_conn_state))
> +			continue;
> +
> +		connector->update_prepare(state, connector);
> +	}
> +}
> +
> +static void intel_connectors_update_complete(struct intel_atomic_state *state)
> +{
> +	struct drm_connector_state *old_conn_state;
> +	struct drm_connector_state *new_conn_state;
> +	struct drm_connector *conn;
> +	int i;
> +
> +	for_each_oldnew_connector_in_state(&state->base, conn,
> +					   old_conn_state, new_conn_state, i) {
> +		struct intel_connector *connector = to_intel_connector(conn);
> +
> +		if (!connector->update_complete)
> +			continue;
> +
> +		if (!intel_connector_needs_modeset(state,
> +						   old_conn_state,
> +						   new_conn_state))
> +			continue;
> +
> +		connector->update_complete(state, connector);
> +	}
> +}
> +
>  static void intel_encoders_pre_pll_enable(struct drm_crtc *crtc,
>  					  struct intel_crtc_state *crtc_state,
>  					  struct drm_atomic_state *old_state)
> @@ -6556,6 +6616,28 @@ static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state)
>  	I915_WRITE(BCLRPAT(crtc->pipe), 0);
>  }
>  
> +/*
> + * intel_connector_primary_digital_port - get the primary port for a connector
> + * @connector: connector for which to return the port
> + *
> + * Returns the primary digital port for a DP MST, the single digital port for
> + * DP SST and HDMI and NULL for all other connector types.
> + */
> +struct intel_digital_port *
> +intel_connector_primary_digital_port(struct intel_connector *connector)
> +{
> +	struct intel_encoder *encoder;
> +
> +	if (connector->mst_port)
> +		return dp_to_dig_port(connector->mst_port);
> +
> +	encoder = intel_attached_encoder(&connector->base);
> +	if (WARN_ON(!encoder))
> +		return NULL;
> +
> +	return enc_to_dig_port(&encoder->base);
> +}
> +
>  bool intel_port_is_combophy(struct drm_i915_private *dev_priv, enum port port)
>  {
>  	if (port == PORT_NONE)
> @@ -13805,14 +13887,20 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
>  		}
>  	}
>  
> +	if (intel_state->modeset)
> +		intel_connectors_update_prepare(intel_state);
> +
>  	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
>  	dev_priv->display.update_crtcs(state);
>  
> -	if (intel_state->modeset)
> +	if (intel_state->modeset) {
> +		intel_connectors_update_complete(intel_state);
> +
>  		intel_set_cdclk_post_plane_update(dev_priv,
>  						  &intel_state->cdclk.actual,
>  						  &dev_priv->cdclk.actual,
>  						  intel_state->cdclk.pipe);
> +	}
>  
>  	/* FIXME: We should call drm_atomic_helper_commit_hw_done() here
>  	 * already, but still need the state for the delayed optimization. To
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index b984410f41a4..2f63476e3cf2 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -7195,6 +7195,13 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
>  	else
>  		intel_connector->get_hw_state = intel_connector_get_hw_state;
>  
> +	if (intel_port_is_tc(dev_priv, intel_encoder->port)) {
> +		intel_connector->update_prepare =
> +			intel_ddi_connector_update_prepare;
> +		intel_connector->update_complete =
> +			intel_ddi_connector_update_complete;
> +	}
> +
>  	/* init MST on ports that can support it */
>  	if (HAS_DP_MST(dev_priv) && !intel_dp_is_edp(intel_dp) &&
>  	    (port == PORT_B || port == PORT_C ||
> diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
> index 0caf645fbbb8..9d5b048b9c96 100644
> --- a/drivers/gpu/drm/i915/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/intel_dp_mst.c
> @@ -505,6 +505,12 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
>  	if (!intel_connector)
>  		return NULL;
>  
> +	if (intel_port_is_tc(dev_priv, intel_dig_port->base.port)) {
> +		intel_connector->update_prepare =
> +			intel_ddi_connector_update_prepare;
> +		intel_connector->update_complete =
> +			intel_ddi_connector_update_complete;
> +	}
>  	intel_connector->get_hw_state = intel_dp_mst_get_hw_state;
>  	intel_connector->mst_port = intel_dp;
>  	intel_connector->port = port;
> diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
> index ce08a2eee55f..ce397b69b1d6 100644
> --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
> +++ b/drivers/gpu/drm/i915/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);
>  };
> @@ -3401,6 +3403,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,
>  };
>  
> @@ -3525,6 +3528,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
> diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h
> index 3bea81bde343..5817faa129d5 100644
> --- a/drivers/gpu/drm/i915/intel_dpll_mgr.h
> +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h
> @@ -346,6 +346,9 @@ 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_update_active_dpll(struct intel_atomic_state *state,
> +			      struct intel_crtc *crtc,
> +			      struct intel_encoder *encoder);
>  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 c61955c41976..b96656f1b8d4 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -375,6 +375,11 @@ struct intel_connector {
>  	 * and active (i.e. dpms ON state). */
>  	bool (*get_hw_state)(struct intel_connector *);
>  
> +	void (*update_prepare)(struct intel_atomic_state *state,
> +			       struct intel_connector *connector);
> +	void (*update_complete)(struct intel_atomic_state *state,
> +				struct intel_connector *connector);
> +
>  	/* Panel info for eDP and LVDS */
>  	struct intel_panel panel;
>  
> @@ -1234,6 +1239,8 @@ struct intel_digital_port {
>  	enum aux_ch aux_ch;
>  	enum intel_display_power_domain ddi_io_power_domain;
>  	struct mutex tc_lock;
> +	intel_wakeref_t tc_lock_wakeref;
> +	int tc_link_refcount;
>  	bool tc_legacy_port:1;
>  	enum tc_port_mode tc_mode;
>  
> @@ -1485,6 +1492,8 @@ void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv);
>  void intel_encoder_destroy(struct drm_encoder *encoder);
>  struct drm_display_mode *
>  intel_encoder_current_mode(struct intel_encoder *encoder);
> +struct intel_digital_port *
> +intel_connector_primary_digital_port(struct intel_connector *connector);
>  bool intel_port_is_combophy(struct drm_i915_private *dev_priv, enum port port);
>  bool intel_port_is_tc(struct drm_i915_private *dev_priv, enum port port);
>  enum tc_port intel_port_to_tc(struct drm_i915_private *dev_priv,
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index 097bfa504ece..89f09e27b741 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -3092,6 +3092,13 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
>  	else
>  		intel_connector->get_hw_state = intel_connector_get_hw_state;
>  
> +	if (intel_port_is_tc(dev_priv, intel_encoder->port)) {
> +		intel_connector->update_prepare =
> +			intel_ddi_connector_update_prepare;
> +		intel_connector->update_complete =
> +			intel_ddi_connector_update_complete;
> +	}
> +
>  	intel_hdmi_add_properties(intel_hdmi, connector);
>  
>  	intel_connector_attach_encoder(intel_connector, intel_encoder);
> diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
> index 4b2f525bc2a6..e79f6ceb26f3 100644
> --- a/drivers/gpu/drm/i915/intel_tc.c
> +++ b/drivers/gpu/drm/i915/intel_tc.c
> @@ -188,21 +188,13 @@ static bool icl_tc_phy_is_in_safe_mode(struct intel_digital_port *dig_port)
>   * display, USB, etc. As a result, handshaking through FIA is required around
>   * connect and disconnect to cleanly transfer ownership with the controller and
>   * set the type-C power state.
> - *
> - * We could opt to only do the connect flow when we actually try to use the AUX
> - * channels or do a modeset, then immediately run the disconnect flow after
> - * usage, but there are some implications on this for a dynamic environment:
> - * things may go away or change behind our backs. So for now our driver is
> - * always trying to acquire ownership of the controller as soon as it gets an
> - * interrupt (or polls state and sees a port is connected) and only gives it
> - * back when it sees a disconnect. Implementation of a more fine-grained model
> - * will require a lot of coordination with user space and thorough testing for
> - * the extra possible cases.
>   */
> -static void icl_tc_phy_connect(struct intel_digital_port *dig_port)
> +static void icl_tc_phy_connect(struct intel_digital_port *dig_port,
> +			       int required_lanes)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
>  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> +	int max_lanes;
>  
>  	if (!icl_tc_phy_status_complete(dig_port)) {
>  		DRM_DEBUG_KMS("Port %s: PHY not ready\n",
> @@ -214,8 +206,9 @@ static void icl_tc_phy_connect(struct intel_digital_port *dig_port)
>  	    !WARN_ON(dig_port->tc_legacy_port))
>  		goto out_set_tbt_alt_mode;
>  
> +	max_lanes = intel_tc_port_fia_max_lane_count(dig_port);
>  	if (dig_port->tc_legacy_port) {
> -		WARN_ON(intel_tc_port_fia_max_lane_count(dig_port) != 4);
> +		WARN_ON(max_lanes != 4);
>  		dig_port->tc_mode = TC_PORT_LEGACY;
>  
>  		return;
> @@ -231,6 +224,13 @@ static void icl_tc_phy_connect(struct intel_digital_port *dig_port)
>  		goto out_set_safe_mode;
>  	}
>  
> +	if (max_lanes < required_lanes) {
> +		DRM_DEBUG_KMS("Port %s: PHY max lanes %d < required lanes %d\n",
> +			      tc_port_name(dev_priv, tc_port),
> +			      max_lanes, required_lanes);
> +		goto out_set_safe_mode;
> +	}
> +
>  	dig_port->tc_mode = TC_PORT_DP_ALT;
>  
>  	return;
> @@ -317,7 +317,8 @@ intel_tc_port_get_target_mode(struct intel_digital_port *dig_port)
>  					  TC_PORT_TBT_ALT;
>  }
>  
> -static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port)
> +static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port,
> +				     int required_lanes)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
>  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> @@ -326,7 +327,7 @@ static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port)
>  	intel_display_power_flush_work(dev_priv);
>  
>  	icl_tc_phy_disconnect(dig_port);
> -	icl_tc_phy_connect(dig_port);
> +	icl_tc_phy_connect(dig_port, required_lanes);
>  
>  	DRM_DEBUG_KMS("Port %s: TC port mode reset (%s -> %s)\n",
>  		      tc_port_name(dev_priv, tc_port),
> @@ -334,6 +335,14 @@ static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port)
>  		      tc_port_mode_name(dig_port->tc_mode));
>  }
>  
> +static void
> +intel_tc_port_link_init_refcount(struct intel_digital_port *dig_port,
> +				 int refcount)
> +{
> +	WARN_ON(dig_port->tc_link_refcount);
> +	dig_port->tc_link_refcount = refcount;
> +}
> +
>  void intel_tc_port_sanitize(struct intel_digital_port *dig_port)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> @@ -354,11 +363,13 @@ void intel_tc_port_sanitize(struct intel_digital_port *dig_port)
>  			DRM_DEBUG_DRIVER("Port %s: PHY disconnected with %d active link(s)\n",
>  					 tc_port_name(dev_priv, tc_port),
>  					 active_links);
> +		intel_tc_port_link_init_refcount(dig_port, active_links);
> +
>  		goto out;
>  	}
>  
>  	if (dig_port->tc_legacy_port)
> -		icl_tc_phy_connect(dig_port);
> +		icl_tc_phy_connect(dig_port, 1);
>  
>  out:
>  	DRM_DEBUG_DRIVER("Port %s: sanitize mode (%s)\n",
> @@ -388,27 +399,60 @@ bool intel_tc_port_connected(struct intel_digital_port *dig_port)
>  {
>  	bool is_connected;
>  
> -	mutex_lock(&dig_port->tc_lock);
> -
> -	if (intel_tc_port_needs_reset(dig_port))
> -		intel_tc_port_reset_mode(dig_port);
> -
> +	intel_tc_port_lock(dig_port);
>  	is_connected = tc_port_live_status_mask(dig_port) &
>  		       BIT(dig_port->tc_mode);
> -
> -	mutex_unlock(&dig_port->tc_lock);
> +	intel_tc_port_unlock(dig_port);
>  
>  	return is_connected;
>  }
>  
> -void intel_tc_port_lock(struct intel_digital_port *dig_port)
> +static void __intel_tc_port_lock(struct intel_digital_port *dig_port,
> +				 int required_lanes)
>  {
> +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> +	intel_wakeref_t wakeref;
> +
> +	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_DISPLAY_CORE);
> +
>  	mutex_lock(&dig_port->tc_lock);
> -	/* TODO: reset the TypeC port mode if needed */
> +
> +	if (!dig_port->tc_link_refcount &&
> +	    intel_tc_port_needs_reset(dig_port))
> +		intel_tc_port_reset_mode(dig_port, required_lanes);
> +
> +	WARN_ON(dig_port->tc_lock_wakeref);
> +	dig_port->tc_lock_wakeref = wakeref;
> +}
> +
> +void intel_tc_port_lock(struct intel_digital_port *dig_port)
> +{
> +	__intel_tc_port_lock(dig_port, 1);
>  }
>  
>  void intel_tc_port_unlock(struct intel_digital_port *dig_port)
>  {
> +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> +	intel_wakeref_t wakeref = fetch_and_zero(&dig_port->tc_lock_wakeref);
> +
> +	mutex_unlock(&dig_port->tc_lock);
> +
> +	intel_display_power_put_async(dev_priv, POWER_DOMAIN_DISPLAY_CORE,
> +				      wakeref);
> +}
> +
> +void intel_tc_port_get_link(struct intel_digital_port *dig_port,
> +			    int required_lanes)
> +{
> +	__intel_tc_port_lock(dig_port, required_lanes);
> +	dig_port->tc_link_refcount++;
> +	intel_tc_port_unlock(dig_port);
> +}
> +
> +void intel_tc_port_put_link(struct intel_digital_port *dig_port)
> +{
> +	mutex_lock(&dig_port->tc_lock);
> +	dig_port->tc_link_refcount--;
>  	mutex_unlock(&dig_port->tc_lock);
>  }
>  
> @@ -417,4 +461,5 @@ intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy)
>  {
>  	mutex_init(&dig_port->tc_lock);
>  	dig_port->tc_legacy_port = is_legacy;
> +	dig_port->tc_link_refcount = 0;
>  }
> diff --git a/drivers/gpu/drm/i915/intel_tc.h b/drivers/gpu/drm/i915/intel_tc.h
> index 91c6e7459cc9..c1870acf6516 100644
> --- a/drivers/gpu/drm/i915/intel_tc.h
> +++ b/drivers/gpu/drm/i915/intel_tc.h
> @@ -14,6 +14,9 @@ int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port);
>  void intel_tc_port_sanitize(struct intel_digital_port *dig_port);
>  void intel_tc_port_lock(struct intel_digital_port *dig_port);
>  void intel_tc_port_unlock(struct intel_digital_port *dig_port);
> +void intel_tc_port_get_link(struct intel_digital_port *dig_port,
> +			    int required_lanes);
> +void intel_tc_port_put_link(struct intel_digital_port *dig_port);
>  
>  void intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy);
>  
> -- 
> 2.17.1

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

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH 20/23] drm/i915: Keep the TypeC port mode fixed when the port is active
  2019-06-19 12:58   ` Ville Syrjälä
@ 2019-06-19 16:08     ` Imre Deak
  0 siblings, 0 replies; 79+ messages in thread
From: Imre Deak @ 2019-06-19 16:08 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Daniel Vetter, intel-gfx

On Wed, Jun 19, 2019 at 03:58:46PM +0300, Ville Syrjälä wrote:
> On Tue, Jun 04, 2019 at 05:58:23PM +0300, Imre Deak wrote:
> > 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
> > connector_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.
> > 
> > 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>
> > ---
> >  drivers/gpu/drm/i915/intel_ddi.c      | 46 +++++++++++--
> >  drivers/gpu/drm/i915/intel_ddi.h      |  7 ++
> >  drivers/gpu/drm/i915/intel_display.c  | 90 +++++++++++++++++++++++++-
> >  drivers/gpu/drm/i915/intel_dp.c       |  7 ++
> >  drivers/gpu/drm/i915/intel_dp_mst.c   |  6 ++
> >  drivers/gpu/drm/i915/intel_dpll_mgr.c | 28 +++++++-
> >  drivers/gpu/drm/i915/intel_dpll_mgr.h |  3 +
> >  drivers/gpu/drm/i915/intel_drv.h      |  9 +++
> >  drivers/gpu/drm/i915/intel_hdmi.c     |  7 ++
> >  drivers/gpu/drm/i915/intel_tc.c       | 93 ++++++++++++++++++++-------
> >  drivers/gpu/drm/i915/intel_tc.h       |  3 +
> >  11 files changed, 269 insertions(+), 30 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> > index ad2f7bb2f50b..138950941246 100644
> > --- a/drivers/gpu/drm/i915/intel_ddi.c
> > +++ b/drivers/gpu/drm/i915/intel_ddi.c
> > @@ -3610,6 +3610,38 @@ static void intel_ddi_set_fia_lane_count(struct intel_encoder *encoder,
> >  	I915_WRITE(PORT_TX_DFLEXDPMLE1, val);
> >  }
> >  
> > +void
> > +intel_ddi_connector_update_prepare(struct intel_atomic_state *state,
> > +				   struct intel_connector *connector)
> > +{
> > +	struct drm_connector_state *conn_state =
> > +		drm_atomic_get_new_connector_state(&state->base,
> > +						   &connector->base);
> > +	struct intel_crtc *crtc = conn_state->crtc ?
> > +		to_intel_crtc(conn_state->crtc) : NULL;
> > +	struct intel_crtc_state *crtc_state =
> > +		crtc ? intel_atomic_get_new_crtc_state(state, crtc) : NULL;
> > +	struct intel_digital_port *primary_port =
> > +		intel_connector_primary_digital_port(connector);
> > +	int required_lanes = crtc_state ? crtc_state->lane_count : 1;
> > +
> > +	WARN_ON(crtc && crtc->active);
> > +
> > +	intel_tc_port_get_link(primary_port, required_lanes);
> > +	if (crtc_state && crtc_state->base.active)
> > +		intel_update_active_dpll(state, crtc, &primary_port->base);
> > +}
> 
> Having this as a connector hook feels a bit strange. I guess moving it
> to encoder level would feel more in line with the rest of the hooks, and
> would avoid having that intel_connector_primary_digital_port() thing
> because then the mst code could just pass in the right thing itself.
> Hmm. Or maybe that wouldn't actually work because of
> intel_connector->encoder being wonky on MST :(

Yep, it took a while to wrap my mind around the tracking of the MST
connector->encoder mapping. The only certainty here is that we have a
fixed encoder for all non-MST connectors and the primary encoder for MST
connectors. Things would simplify a lot even by keeping the above hooks
connector specific, but adding separate MST versions of them to deal
with the connector->primary encoder mapping, which would remove the need
for intel_connector_primary_digital_port().

I see now though, that it makes more sense to add these hooks to the
encoder, which also simplifies things a lot, so I chose that instead. 

> 
> Although if we just put the hooks on the main encoder and not on the
> MST ones it could maybe work. Would still need
> intel_connector_primary_digital_port() to dig out the encoder though.

Yep, this turned out to be simplifying things a lot (by adding a new
intel_connector_primary_encoder() helper instead):
https://github.com/ideak/linux/commit/49dc011132

This way it's enough to assign the hooks to the common DDI encoder,
instead of assigning them to each type of connectors used with a DDI
encoder.

Will post a v2 patchset with all the comments addressed after some
testing, an updated version is at:
https://github.com/ideak/linux/commits/typec-mode-switch

> 
> Not sure.
> 
> > +
> > +void
> > +intel_ddi_connector_update_complete(struct intel_atomic_state *state,
> > +				    struct intel_connector *connector)
> > +{
> > +	struct intel_digital_port *primary_port =
> > +		intel_connector_primary_digital_port(connector);
> > +
> > +	intel_tc_port_put_link(primary_port);
> > +}
> > +
> >  static void
> >  intel_ddi_pre_pll_enable(struct intel_encoder *encoder,
> >  			 const struct intel_crtc_state *crtc_state,
> > @@ -3617,10 +3649,13 @@ intel_ddi_pre_pll_enable(struct intel_encoder *encoder,
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> >  	struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
> > +	bool is_tc_port = intel_port_is_tc(dev_priv, encoder->port);
> >  	enum port port = encoder->port;
> >  
> > -	if (intel_crtc_has_dp_encoder(crtc_state) ||
> > -	    intel_port_is_tc(dev_priv, encoder->port))
> > +	if (is_tc_port)
> > +		intel_tc_port_get_link(dig_port, crtc_state->lane_count);
> > +
> > +	if (intel_crtc_has_dp_encoder(crtc_state) || is_tc_port)
> >  		intel_display_power_get(dev_priv,
> >  					intel_ddi_main_link_aux_domain(dig_port));
> >  
> > @@ -3645,11 +3680,14 @@ intel_ddi_post_pll_disable(struct intel_encoder *encoder,
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> >  	struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
> > +	bool is_tc_port = intel_port_is_tc(dev_priv, encoder->port);
> >  
> > -	if (intel_crtc_has_dp_encoder(crtc_state) ||
> > -	    intel_port_is_tc(dev_priv, encoder->port))
> > +	if (intel_crtc_has_dp_encoder(crtc_state) || is_tc_port)
> >  		intel_display_power_put_unchecked(dev_priv,
> >  						  intel_ddi_main_link_aux_domain(dig_port));
> > +
> > +	if (is_tc_port)
> > +		intel_tc_port_put_link(dig_port);
> >  }
> >  
> >  void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
> > diff --git a/drivers/gpu/drm/i915/intel_ddi.h b/drivers/gpu/drm/i915/intel_ddi.h
> > index 9cf69175942e..1559d1fbf7bd 100644
> > --- a/drivers/gpu/drm/i915/intel_ddi.h
> > +++ b/drivers/gpu/drm/i915/intel_ddi.h
> > @@ -12,6 +12,7 @@
> >  
> >  struct drm_connector_state;
> >  struct drm_i915_private;
> > +struct intel_atomic_state;
> >  struct intel_connector;
> >  struct intel_crtc;
> >  struct intel_crtc_state;
> > @@ -35,6 +36,12 @@ void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp);
> >  bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector);
> >  void intel_ddi_get_config(struct intel_encoder *encoder,
> >  			  struct intel_crtc_state *pipe_config);
> > +void
> > +intel_ddi_connector_update_prepare(struct intel_atomic_state *state,
> > +				   struct intel_connector *connector);
> > +void
> > +intel_ddi_connector_update_complete(struct intel_atomic_state *state,
> > +				    struct intel_connector *connector);
> >  void intel_ddi_set_vc_payload_alloc(const struct intel_crtc_state *crtc_state,
> >  				    bool state);
> >  void intel_ddi_compute_min_voltage_level(struct drm_i915_private *dev_priv,
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index f86b5b848cbc..2c65587d1622 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -520,6 +520,20 @@ needs_modeset(const struct drm_crtc_state *state)
> >  	return drm_atomic_crtc_needs_modeset(state);
> >  }
> >  
> > +static bool
> > +intel_connector_needs_modeset(struct intel_atomic_state *state,
> > +			      const struct drm_connector_state *old_conn_state,
> > +			      const struct drm_connector_state *new_conn_state)
> > +{
> > +	if (new_conn_state->crtc != old_conn_state->crtc ||
> > +	    (new_conn_state->crtc &&
> > +	     needs_modeset(drm_atomic_get_new_crtc_state(&state->base,
> > +							 new_conn_state->crtc))))
> > +		return true;
> > +
> > +	return false;
> 
> Pointless if statement. Or is there more coming here?

Nope, it can be simplified.

> 
> > +}
> > +
> >  /*
> >   * Platform specific helpers to calculate the port PLL loopback- (clock.m),
> >   * and post-divider (clock.p) values, pre- (clock.vco) and post-divided fast
> > @@ -6032,6 +6046,52 @@ static void intel_crtc_disable_planes(struct intel_atomic_state *state,
> >  	intel_frontbuffer_flip(dev_priv, fb_bits);
> >  }
> >  
> > +static void intel_connectors_update_prepare(struct intel_atomic_state *state)
> > +{
> > +	struct drm_connector_state *old_conn_state;
> > +	struct drm_connector_state *new_conn_state;
> > +	struct drm_connector *conn;
> > +	int i;
> > +
> > +	for_each_oldnew_connector_in_state(&state->base, conn,
> > +					   old_conn_state, new_conn_state, i) {
> > +		struct intel_connector *connector = to_intel_connector(conn);
> > +
> > +		if (!connector->update_prepare)
> > +			continue;
> > +
> > +		if (!intel_connector_needs_modeset(state,
> > +						   old_conn_state,
> > +						   new_conn_state))
> > +			continue;
> > +
> > +		connector->update_prepare(state, connector);
> > +	}
> > +}
> > +
> > +static void intel_connectors_update_complete(struct intel_atomic_state *state)
> > +{
> > +	struct drm_connector_state *old_conn_state;
> > +	struct drm_connector_state *new_conn_state;
> > +	struct drm_connector *conn;
> > +	int i;
> > +
> > +	for_each_oldnew_connector_in_state(&state->base, conn,
> > +					   old_conn_state, new_conn_state, i) {
> > +		struct intel_connector *connector = to_intel_connector(conn);
> > +
> > +		if (!connector->update_complete)
> > +			continue;
> > +
> > +		if (!intel_connector_needs_modeset(state,
> > +						   old_conn_state,
> > +						   new_conn_state))
> > +			continue;
> > +
> > +		connector->update_complete(state, connector);
> > +	}
> > +}
> > +
> >  static void intel_encoders_pre_pll_enable(struct drm_crtc *crtc,
> >  					  struct intel_crtc_state *crtc_state,
> >  					  struct drm_atomic_state *old_state)
> > @@ -6556,6 +6616,28 @@ static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state)
> >  	I915_WRITE(BCLRPAT(crtc->pipe), 0);
> >  }
> >  
> > +/*
> > + * intel_connector_primary_digital_port - get the primary port for a connector
> > + * @connector: connector for which to return the port
> > + *
> > + * Returns the primary digital port for a DP MST, the single digital port for
> > + * DP SST and HDMI and NULL for all other connector types.
> > + */
> > +struct intel_digital_port *
> > +intel_connector_primary_digital_port(struct intel_connector *connector)
> > +{
> > +	struct intel_encoder *encoder;
> > +
> > +	if (connector->mst_port)
> > +		return dp_to_dig_port(connector->mst_port);
> > +
> > +	encoder = intel_attached_encoder(&connector->base);
> > +	if (WARN_ON(!encoder))
> > +		return NULL;
> > +
> > +	return enc_to_dig_port(&encoder->base);
> > +}
> > +
> >  bool intel_port_is_combophy(struct drm_i915_private *dev_priv, enum port port)
> >  {
> >  	if (port == PORT_NONE)
> > @@ -13805,14 +13887,20 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
> >  		}
> >  	}
> >  
> > +	if (intel_state->modeset)
> > +		intel_connectors_update_prepare(intel_state);
> > +
> >  	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
> >  	dev_priv->display.update_crtcs(state);
> >  
> > -	if (intel_state->modeset)
> > +	if (intel_state->modeset) {
> > +		intel_connectors_update_complete(intel_state);
> > +
> >  		intel_set_cdclk_post_plane_update(dev_priv,
> >  						  &intel_state->cdclk.actual,
> >  						  &dev_priv->cdclk.actual,
> >  						  intel_state->cdclk.pipe);
> > +	}
> >  
> >  	/* FIXME: We should call drm_atomic_helper_commit_hw_done() here
> >  	 * already, but still need the state for the delayed optimization. To
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index b984410f41a4..2f63476e3cf2 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -7195,6 +7195,13 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
> >  	else
> >  		intel_connector->get_hw_state = intel_connector_get_hw_state;
> >  
> > +	if (intel_port_is_tc(dev_priv, intel_encoder->port)) {
> > +		intel_connector->update_prepare =
> > +			intel_ddi_connector_update_prepare;
> > +		intel_connector->update_complete =
> > +			intel_ddi_connector_update_complete;
> > +	}
> > +
> >  	/* init MST on ports that can support it */
> >  	if (HAS_DP_MST(dev_priv) && !intel_dp_is_edp(intel_dp) &&
> >  	    (port == PORT_B || port == PORT_C ||
> > diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
> > index 0caf645fbbb8..9d5b048b9c96 100644
> > --- a/drivers/gpu/drm/i915/intel_dp_mst.c
> > +++ b/drivers/gpu/drm/i915/intel_dp_mst.c
> > @@ -505,6 +505,12 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
> >  	if (!intel_connector)
> >  		return NULL;
> >  
> > +	if (intel_port_is_tc(dev_priv, intel_dig_port->base.port)) {
> > +		intel_connector->update_prepare =
> > +			intel_ddi_connector_update_prepare;
> > +		intel_connector->update_complete =
> > +			intel_ddi_connector_update_complete;
> > +	}
> >  	intel_connector->get_hw_state = intel_dp_mst_get_hw_state;
> >  	intel_connector->mst_port = intel_dp;
> >  	intel_connector->port = port;
> > diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
> > index ce08a2eee55f..ce397b69b1d6 100644
> > --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
> > +++ b/drivers/gpu/drm/i915/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);
> >  };
> > @@ -3401,6 +3403,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,
> >  };
> >  
> > @@ -3525,6 +3528,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
> > diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h
> > index 3bea81bde343..5817faa129d5 100644
> > --- a/drivers/gpu/drm/i915/intel_dpll_mgr.h
> > +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h
> > @@ -346,6 +346,9 @@ 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_update_active_dpll(struct intel_atomic_state *state,
> > +			      struct intel_crtc *crtc,
> > +			      struct intel_encoder *encoder);
> >  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 c61955c41976..b96656f1b8d4 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -375,6 +375,11 @@ struct intel_connector {
> >  	 * and active (i.e. dpms ON state). */
> >  	bool (*get_hw_state)(struct intel_connector *);
> >  
> > +	void (*update_prepare)(struct intel_atomic_state *state,
> > +			       struct intel_connector *connector);
> > +	void (*update_complete)(struct intel_atomic_state *state,
> > +				struct intel_connector *connector);
> > +
> >  	/* Panel info for eDP and LVDS */
> >  	struct intel_panel panel;
> >  
> > @@ -1234,6 +1239,8 @@ struct intel_digital_port {
> >  	enum aux_ch aux_ch;
> >  	enum intel_display_power_domain ddi_io_power_domain;
> >  	struct mutex tc_lock;
> > +	intel_wakeref_t tc_lock_wakeref;
> > +	int tc_link_refcount;
> >  	bool tc_legacy_port:1;
> >  	enum tc_port_mode tc_mode;
> >  
> > @@ -1485,6 +1492,8 @@ void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv);
> >  void intel_encoder_destroy(struct drm_encoder *encoder);
> >  struct drm_display_mode *
> >  intel_encoder_current_mode(struct intel_encoder *encoder);
> > +struct intel_digital_port *
> > +intel_connector_primary_digital_port(struct intel_connector *connector);
> >  bool intel_port_is_combophy(struct drm_i915_private *dev_priv, enum port port);
> >  bool intel_port_is_tc(struct drm_i915_private *dev_priv, enum port port);
> >  enum tc_port intel_port_to_tc(struct drm_i915_private *dev_priv,
> > diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> > index 097bfa504ece..89f09e27b741 100644
> > --- a/drivers/gpu/drm/i915/intel_hdmi.c
> > +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> > @@ -3092,6 +3092,13 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
> >  	else
> >  		intel_connector->get_hw_state = intel_connector_get_hw_state;
> >  
> > +	if (intel_port_is_tc(dev_priv, intel_encoder->port)) {
> > +		intel_connector->update_prepare =
> > +			intel_ddi_connector_update_prepare;
> > +		intel_connector->update_complete =
> > +			intel_ddi_connector_update_complete;
> > +	}
> > +
> >  	intel_hdmi_add_properties(intel_hdmi, connector);
> >  
> >  	intel_connector_attach_encoder(intel_connector, intel_encoder);
> > diff --git a/drivers/gpu/drm/i915/intel_tc.c b/drivers/gpu/drm/i915/intel_tc.c
> > index 4b2f525bc2a6..e79f6ceb26f3 100644
> > --- a/drivers/gpu/drm/i915/intel_tc.c
> > +++ b/drivers/gpu/drm/i915/intel_tc.c
> > @@ -188,21 +188,13 @@ static bool icl_tc_phy_is_in_safe_mode(struct intel_digital_port *dig_port)
> >   * display, USB, etc. As a result, handshaking through FIA is required around
> >   * connect and disconnect to cleanly transfer ownership with the controller and
> >   * set the type-C power state.
> > - *
> > - * We could opt to only do the connect flow when we actually try to use the AUX
> > - * channels or do a modeset, then immediately run the disconnect flow after
> > - * usage, but there are some implications on this for a dynamic environment:
> > - * things may go away or change behind our backs. So for now our driver is
> > - * always trying to acquire ownership of the controller as soon as it gets an
> > - * interrupt (or polls state and sees a port is connected) and only gives it
> > - * back when it sees a disconnect. Implementation of a more fine-grained model
> > - * will require a lot of coordination with user space and thorough testing for
> > - * the extra possible cases.
> >   */
> > -static void icl_tc_phy_connect(struct intel_digital_port *dig_port)
> > +static void icl_tc_phy_connect(struct intel_digital_port *dig_port,
> > +			       int required_lanes)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> >  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> > +	int max_lanes;
> >  
> >  	if (!icl_tc_phy_status_complete(dig_port)) {
> >  		DRM_DEBUG_KMS("Port %s: PHY not ready\n",
> > @@ -214,8 +206,9 @@ static void icl_tc_phy_connect(struct intel_digital_port *dig_port)
> >  	    !WARN_ON(dig_port->tc_legacy_port))
> >  		goto out_set_tbt_alt_mode;
> >  
> > +	max_lanes = intel_tc_port_fia_max_lane_count(dig_port);
> >  	if (dig_port->tc_legacy_port) {
> > -		WARN_ON(intel_tc_port_fia_max_lane_count(dig_port) != 4);
> > +		WARN_ON(max_lanes != 4);
> >  		dig_port->tc_mode = TC_PORT_LEGACY;
> >  
> >  		return;
> > @@ -231,6 +224,13 @@ static void icl_tc_phy_connect(struct intel_digital_port *dig_port)
> >  		goto out_set_safe_mode;
> >  	}
> >  
> > +	if (max_lanes < required_lanes) {
> > +		DRM_DEBUG_KMS("Port %s: PHY max lanes %d < required lanes %d\n",
> > +			      tc_port_name(dev_priv, tc_port),
> > +			      max_lanes, required_lanes);
> > +		goto out_set_safe_mode;
> > +	}
> > +
> >  	dig_port->tc_mode = TC_PORT_DP_ALT;
> >  
> >  	return;
> > @@ -317,7 +317,8 @@ intel_tc_port_get_target_mode(struct intel_digital_port *dig_port)
> >  					  TC_PORT_TBT_ALT;
> >  }
> >  
> > -static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port)
> > +static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port,
> > +				     int required_lanes)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> >  	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
> > @@ -326,7 +327,7 @@ static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port)
> >  	intel_display_power_flush_work(dev_priv);
> >  
> >  	icl_tc_phy_disconnect(dig_port);
> > -	icl_tc_phy_connect(dig_port);
> > +	icl_tc_phy_connect(dig_port, required_lanes);
> >  
> >  	DRM_DEBUG_KMS("Port %s: TC port mode reset (%s -> %s)\n",
> >  		      tc_port_name(dev_priv, tc_port),
> > @@ -334,6 +335,14 @@ static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port)
> >  		      tc_port_mode_name(dig_port->tc_mode));
> >  }
> >  
> > +static void
> > +intel_tc_port_link_init_refcount(struct intel_digital_port *dig_port,
> > +				 int refcount)
> > +{
> > +	WARN_ON(dig_port->tc_link_refcount);
> > +	dig_port->tc_link_refcount = refcount;
> > +}
> > +
> >  void intel_tc_port_sanitize(struct intel_digital_port *dig_port)
> >  {
> >  	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> > @@ -354,11 +363,13 @@ void intel_tc_port_sanitize(struct intel_digital_port *dig_port)
> >  			DRM_DEBUG_DRIVER("Port %s: PHY disconnected with %d active link(s)\n",
> >  					 tc_port_name(dev_priv, tc_port),
> >  					 active_links);
> > +		intel_tc_port_link_init_refcount(dig_port, active_links);
> > +
> >  		goto out;
> >  	}
> >  
> >  	if (dig_port->tc_legacy_port)
> > -		icl_tc_phy_connect(dig_port);
> > +		icl_tc_phy_connect(dig_port, 1);
> >  
> >  out:
> >  	DRM_DEBUG_DRIVER("Port %s: sanitize mode (%s)\n",
> > @@ -388,27 +399,60 @@ bool intel_tc_port_connected(struct intel_digital_port *dig_port)
> >  {
> >  	bool is_connected;
> >  
> > -	mutex_lock(&dig_port->tc_lock);
> > -
> > -	if (intel_tc_port_needs_reset(dig_port))
> > -		intel_tc_port_reset_mode(dig_port);
> > -
> > +	intel_tc_port_lock(dig_port);
> >  	is_connected = tc_port_live_status_mask(dig_port) &
> >  		       BIT(dig_port->tc_mode);
> > -
> > -	mutex_unlock(&dig_port->tc_lock);
> > +	intel_tc_port_unlock(dig_port);
> >  
> >  	return is_connected;
> >  }
> >  
> > -void intel_tc_port_lock(struct intel_digital_port *dig_port)
> > +static void __intel_tc_port_lock(struct intel_digital_port *dig_port,
> > +				 int required_lanes)
> >  {
> > +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> > +	intel_wakeref_t wakeref;
> > +
> > +	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_DISPLAY_CORE);
> > +
> >  	mutex_lock(&dig_port->tc_lock);
> > -	/* TODO: reset the TypeC port mode if needed */
> > +
> > +	if (!dig_port->tc_link_refcount &&
> > +	    intel_tc_port_needs_reset(dig_port))
> > +		intel_tc_port_reset_mode(dig_port, required_lanes);
> > +
> > +	WARN_ON(dig_port->tc_lock_wakeref);
> > +	dig_port->tc_lock_wakeref = wakeref;
> > +}
> > +
> > +void intel_tc_port_lock(struct intel_digital_port *dig_port)
> > +{
> > +	__intel_tc_port_lock(dig_port, 1);
> >  }
> >  
> >  void intel_tc_port_unlock(struct intel_digital_port *dig_port)
> >  {
> > +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> > +	intel_wakeref_t wakeref = fetch_and_zero(&dig_port->tc_lock_wakeref);
> > +
> > +	mutex_unlock(&dig_port->tc_lock);
> > +
> > +	intel_display_power_put_async(dev_priv, POWER_DOMAIN_DISPLAY_CORE,
> > +				      wakeref);
> > +}
> > +
> > +void intel_tc_port_get_link(struct intel_digital_port *dig_port,
> > +			    int required_lanes)
> > +{
> > +	__intel_tc_port_lock(dig_port, required_lanes);
> > +	dig_port->tc_link_refcount++;
> > +	intel_tc_port_unlock(dig_port);
> > +}
> > +
> > +void intel_tc_port_put_link(struct intel_digital_port *dig_port)
> > +{
> > +	mutex_lock(&dig_port->tc_lock);
> > +	dig_port->tc_link_refcount--;
> >  	mutex_unlock(&dig_port->tc_lock);
> >  }
> >  
> > @@ -417,4 +461,5 @@ intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy)
> >  {
> >  	mutex_init(&dig_port->tc_lock);
> >  	dig_port->tc_legacy_port = is_legacy;
> > +	dig_port->tc_link_refcount = 0;
> >  }
> > diff --git a/drivers/gpu/drm/i915/intel_tc.h b/drivers/gpu/drm/i915/intel_tc.h
> > index 91c6e7459cc9..c1870acf6516 100644
> > --- a/drivers/gpu/drm/i915/intel_tc.h
> > +++ b/drivers/gpu/drm/i915/intel_tc.h
> > @@ -14,6 +14,9 @@ int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port);
> >  void intel_tc_port_sanitize(struct intel_digital_port *dig_port);
> >  void intel_tc_port_lock(struct intel_digital_port *dig_port);
> >  void intel_tc_port_unlock(struct intel_digital_port *dig_port);
> > +void intel_tc_port_get_link(struct intel_digital_port *dig_port,
> > +			    int required_lanes);
> > +void intel_tc_port_put_link(struct intel_digital_port *dig_port);
> >  
> >  void intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy);
> >  
> > -- 
> > 2.17.1
> 
> -- 
> Ville Syrjälä
> Intel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [PATCH v2 19/23] drm/i915/icl: Reserve all required PLLs for TypeC ports
  2019-06-20 14:05 ` [PATCH v2 19/23] drm/i915/icl: Reserve all required PLLs for TypeC ports Imre Deak
@ 2019-06-25 13:58   ` Ville Syrjälä
  0 siblings, 0 replies; 79+ messages in thread
From: Ville Syrjälä @ 2019-06-25 13:58 UTC (permalink / raw)
  To: Imre Deak; +Cc: Daniel Vetter, intel-gfx

On Thu, Jun 20, 2019 at 05:05:56PM +0300, Imre Deak wrote:
> 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)
> 
> 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 | 151 +++++++++++++-----
>  drivers/gpu/drm/i915/display/intel_dpll_mgr.h |   9 ++
>  drivers/gpu/drm/i915/intel_drv.h              |   9 ++
>  4 files changed, 138 insertions(+), 42 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 688137524179..93e3f568d7db 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..a996a3fad48c 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,24 @@ 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);
> +	}
> +}
> +
>  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 +3399,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 +3412,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

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

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [PATCH v2 19/23] drm/i915/icl: Reserve all required PLLs for TypeC ports
  2019-06-20 14:05 [PATCH v2 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
@ 2019-06-20 14:05 ` Imre Deak
  2019-06-25 13:58   ` Ville Syrjälä
  0 siblings, 1 reply; 79+ messages in thread
From: Imre Deak @ 2019-06-20 14:05 UTC (permalink / raw)
  To: intel-gfx; +Cc: Daniel Vetter

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)

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>
---
 drivers/gpu/drm/i915/display/intel_display.c  |  11 +-
 drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 151 +++++++++++++-----
 drivers/gpu/drm/i915/display/intel_dpll_mgr.h |   9 ++
 drivers/gpu/drm/i915/intel_drv.h              |   9 ++
 4 files changed, 138 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 688137524179..93e3f568d7db 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..a996a3fad48c 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,24 @@ 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);
+	}
+}
+
 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 +3399,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 +3412,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

^ permalink raw reply related	[flat|nested] 79+ messages in thread

end of thread, other threads:[~2019-06-25 13:58 UTC | newest]

Thread overview: 79+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-04 14:58 [PATCH 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
2019-06-04 14:58 ` [PATCH 01/23] drm/i915/icl: Add support to read out the TBT PLL HW state Imre Deak
2019-06-07 17:36   ` Souza, Jose
2019-06-04 14:58 ` [PATCH 02/23] drm/i915: Tune down WARNs about TBT AUX power well enabling Imre Deak
2019-06-07 17:50   ` Souza, Jose
2019-06-08 13:33     ` Imre Deak
2019-06-04 14:58 ` [PATCH 03/23] drm/i915: Move the TypeC port handling code to a separate file Imre Deak
2019-06-06  8:42   ` Jani Nikula
2019-06-06  8:43     ` Jani Nikula
2019-06-06  9:09     ` Imre Deak
2019-06-10 22:57     ` Lucas De Marchi
2019-06-11 10:01       ` Jani Nikula
2019-06-07 17:56   ` Souza, Jose
2019-06-04 14:58 ` [PATCH 04/23] drm/i915: Sanitize the terminology used for TypeC port modes Imre Deak
2019-06-07 19:15   ` Souza, Jose
2019-06-08 13:43     ` Imre Deak
2019-06-10 23:21   ` Lucas De Marchi
2019-06-11 11:19     ` Imre Deak
2019-06-04 14:58 ` [PATCH 05/23] drm/i915: Don't enable the DDI-IO power in the TypeC TBT-alt mode Imre Deak
2019-06-07 19:23   ` Souza, Jose
2019-06-04 14:58 ` [PATCH 06/23] drm/i915: Fix the TBT AUX power well enabling Imre Deak
2019-06-07 19:58   ` Souza, Jose
2019-06-08 13:55     ` Imre Deak
2019-06-04 14:58 ` [PATCH 07/23] drm/i915: Use the correct AUX power domain in TypeC TBT-alt mode Imre Deak
2019-06-07 20:02   ` Souza, Jose
2019-06-04 14:58 ` [PATCH 08/23] drm/i915: Unify the TypeC port notation in debug/error messages Imre Deak
2019-06-07 20:21   ` Souza, Jose
2019-06-07 20:42     ` Imre Deak
2019-06-07 20:45       ` Souza, Jose
2019-06-07 20:46       ` Imre Deak
2019-06-04 14:58 ` [PATCH 09/23] drm/i915: Factor out common parts from TypeC port handling functions Imre Deak
2019-06-06  8:47   ` Jani Nikula
2019-06-06  9:19     ` Imre Deak
2019-06-07 21:22   ` Souza, Jose
2019-06-08 17:23     ` Imre Deak
2019-06-18 16:33   ` Ville Syrjälä
2019-06-18 16:44     ` Imre Deak
2019-06-04 14:58 ` [PATCH 10/23] drm/i915: Wait for TypeC PHY complete flag to clear in safe mode Imre Deak
2019-06-07 21:32   ` Souza, Jose
2019-06-04 14:58 ` [PATCH 11/23] drm/i915: Handle the TCCOLD power-down event Imre Deak
2019-06-07 21:41   ` Souza, Jose
2019-06-08 17:31     ` Imre Deak
2019-06-04 14:58 ` [PATCH 12/23] drm/i915: Sanitize the TypeC connect/detect sequences Imre Deak
2019-06-07 22:15   ` Souza, Jose
2019-06-08 17:40     ` Imre Deak
2019-06-04 14:58 ` [PATCH 13/23] drm/i915: Fix the TypeC port mode sanitization during loading/resume Imre Deak
2019-06-07 22:39   ` Souza, Jose
2019-06-08 17:50     ` Imre Deak
2019-06-04 14:58 ` [PATCH 14/23] drm/i915: Keep the TypeC port mode fixed for detect/AUX transfers Imre Deak
2019-06-04 14:58 ` [PATCH 15/23] drm/i915: Sanitize the TypeC FIA lane configuration decoding Imre Deak
2019-06-07 22:49   ` Souza, Jose
2019-06-18 16:39   ` Ville Syrjälä
2019-06-18 16:46     ` Imre Deak
2019-06-04 14:58 ` [PATCH 16/23] drm/i915: Sanitize the shared DPLL reserve/release interface Imre Deak
2019-06-04 14:58 ` [PATCH 17/23] drm/i915: Sanitize the shared DPLL find/reference interface Imre Deak
2019-06-04 14:58 ` [PATCH 18/23] drm/i915/icl: Split getting the DPLLs to port type specific functions Imre Deak
2019-06-04 14:58 ` [PATCH 19/23] drm/i915/icl: Reserve all required PLLs for TypeC ports Imre Deak
2019-06-07 17:41   ` [PATCH v2 " Imre Deak
2019-06-18 17:25     ` Ville Syrjälä
2019-06-18 18:02       ` Imre Deak
2019-06-04 14:58 ` [PATCH 20/23] drm/i915: Keep the TypeC port mode fixed when the port is active Imre Deak
2019-06-19 12:58   ` Ville Syrjälä
2019-06-19 16:08     ` Imre Deak
2019-06-04 14:58 ` [PATCH 21/23] drm/i915: Add state verification for the TypeC port mode Imre Deak
2019-06-04 14:58 ` [PATCH 22/23] drm/i915: Remove unneeded disconnect in TypeC legacy " Imre Deak
2019-06-08  0:18   ` Souza, Jose
2019-06-04 14:58 ` [PATCH 23/23] drm/i915: WARN about invalid lane reversal in TBT-alt/DP-alt modes Imre Deak
2019-06-08  0:13   ` Souza, Jose
2019-06-08  0:25     ` Souza, Jose
2019-06-04 17:30 ` ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Fix TypeC port mode switching Patchwork
2019-06-04 17:39 ` ✗ Fi.CI.SPARSE: " Patchwork
2019-06-05  5:24 ` ✓ Fi.CI.BAT: success " Patchwork
2019-06-05 16:36 ` ✓ Fi.CI.IGT: " Patchwork
2019-06-07 17:59 ` ✗ Fi.CI.CHECKPATCH: warning for drm/i915: Fix TypeC port mode switching (rev2) Patchwork
2019-06-07 18:07 ` ✗ Fi.CI.SPARSE: " Patchwork
2019-06-07 18:34 ` ✓ Fi.CI.BAT: success " Patchwork
2019-06-10 12:34 ` ✓ Fi.CI.IGT: " Patchwork
2019-06-20 14:05 [PATCH v2 00/23] drm/i915: Fix TypeC port mode switching Imre Deak
2019-06-20 14:05 ` [PATCH v2 19/23] drm/i915/icl: Reserve all required PLLs for TypeC ports Imre Deak
2019-06-25 13:58   ` Ville Syrjälä

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.