All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/6] drm/i915: Add support for LTTPR non-transparent link training mode
@ 2020-09-24 18:47 ` Imre Deak
  0 siblings, 0 replies; 19+ messages in thread
From: Imre Deak @ 2020-09-24 18:47 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

This patchset is v2 of [1], addressing the comments from Ville and an
issue in the last patch with the per-PHY capability readout (needs to be
done after switching to non-transparent mode).

[1] https://patchwork.freedesktop.org/series/81968/

Cc: dri-devel@lists.freedesktop.org
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>

Imre Deak (6):
  drm/i915: Fix DP link training pattern mask
  drm/i915: Simplify the link training functions
  drm/i915: Factor out a helper to disable the DPCD training pattern
  drm/dp: Add LTTPR helpers
  drm/i915: Switch to LTTPR transparent mode link training
  drm/i915: Switch to LTTPR non-transparent mode link training

 drivers/gpu/drm/drm_dp_helper.c               | 244 ++++++++-
 drivers/gpu/drm/i915/display/intel_ddi.c      |   3 +-
 .../drm/i915/display/intel_display_types.h    |   2 +
 drivers/gpu/drm/i915/display/intel_dp.c       |  46 +-
 drivers/gpu/drm/i915/display/intel_dp.h       |   3 -
 .../drm/i915/display/intel_dp_link_training.c | 486 +++++++++++++++---
 .../drm/i915/display/intel_dp_link_training.h |  13 +-
 include/drm/drm_dp_helper.h                   |  62 +++
 8 files changed, 750 insertions(+), 109 deletions(-)

-- 
2.25.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [Intel-gfx] [PATCH v2 0/6] drm/i915: Add support for LTTPR non-transparent link training mode
@ 2020-09-24 18:47 ` Imre Deak
  0 siblings, 0 replies; 19+ messages in thread
From: Imre Deak @ 2020-09-24 18:47 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

This patchset is v2 of [1], addressing the comments from Ville and an
issue in the last patch with the per-PHY capability readout (needs to be
done after switching to non-transparent mode).

[1] https://patchwork.freedesktop.org/series/81968/

Cc: dri-devel@lists.freedesktop.org
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>

Imre Deak (6):
  drm/i915: Fix DP link training pattern mask
  drm/i915: Simplify the link training functions
  drm/i915: Factor out a helper to disable the DPCD training pattern
  drm/dp: Add LTTPR helpers
  drm/i915: Switch to LTTPR transparent mode link training
  drm/i915: Switch to LTTPR non-transparent mode link training

 drivers/gpu/drm/drm_dp_helper.c               | 244 ++++++++-
 drivers/gpu/drm/i915/display/intel_ddi.c      |   3 +-
 .../drm/i915/display/intel_display_types.h    |   2 +
 drivers/gpu/drm/i915/display/intel_dp.c       |  46 +-
 drivers/gpu/drm/i915/display/intel_dp.h       |   3 -
 .../drm/i915/display/intel_dp_link_training.c | 486 +++++++++++++++---
 .../drm/i915/display/intel_dp_link_training.h |  13 +-
 include/drm/drm_dp_helper.h                   |  62 +++
 8 files changed, 750 insertions(+), 109 deletions(-)

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

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

* [Intel-gfx] [PATCH v2 1/6] drm/i915: Fix DP link training pattern mask
  2020-09-24 18:47 ` [Intel-gfx] " Imre Deak
  (?)
@ 2020-09-24 18:48 ` Imre Deak
  -1 siblings, 0 replies; 19+ messages in thread
From: Imre Deak @ 2020-09-24 18:48 UTC (permalink / raw)
  To: intel-gfx

An LTTPR can be trained with training pattern 4 even if the DPCD
revision is < 1.4, but drm_dp_training_pattern_mask() would change
pattern 4 to pattern 3 on those DPCD revisions.

Since intel_dp_training_pattern() makes already sure that the proper
training pattern is used, all that needs to be masked out is the
scrambling disable flag, which is or'd to the mask later based on the
training pattern.

v2:
- Use a helper instead of open-coding the masking. (Ville)

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_ddi.c              |  3 +--
 drivers/gpu/drm/i915/display/intel_dp.c               | 10 +++++-----
 drivers/gpu/drm/i915/display/intel_dp_link_training.c |  2 +-
 drivers/gpu/drm/i915/display/intel_dp_link_training.h |  6 ++++++
 4 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index 4d06178cd76c..edeee1d8471c 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -4158,13 +4158,12 @@ static void intel_ddi_set_link_train(struct intel_dp *intel_dp,
 				     u8 dp_train_pat)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	u8 train_pat_mask = drm_dp_training_pattern_mask(intel_dp->dpcd);
 	u32 temp;
 
 	temp = intel_de_read(dev_priv, intel_dp->regs.dp_tp_ctl);
 
 	temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
-	switch (dp_train_pat & train_pat_mask) {
+	switch (intel_dp_training_pattern_symbol(dp_train_pat)) {
 	case DP_TRAINING_PATTERN_DISABLE:
 		temp |= DP_TP_CTL_LINK_TRAIN_NORMAL;
 		break;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index bf1e9cf1c0f3..bba9669e0e57 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -3778,7 +3778,7 @@ cpt_set_link_train(struct intel_dp *intel_dp,
 
 	*DP &= ~DP_LINK_TRAIN_MASK_CPT;
 
-	switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
+	switch (intel_dp_training_pattern_symbol(dp_train_pat)) {
 	case DP_TRAINING_PATTERN_DISABLE:
 		*DP |= DP_LINK_TRAIN_OFF_CPT;
 		break;
@@ -3808,7 +3808,7 @@ g4x_set_link_train(struct intel_dp *intel_dp,
 
 	*DP &= ~DP_LINK_TRAIN_MASK;
 
-	switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
+	switch (intel_dp_training_pattern_symbol(dp_train_pat)) {
 	case DP_TRAINING_PATTERN_DISABLE:
 		*DP |= DP_LINK_TRAIN_OFF;
 		break;
@@ -4498,12 +4498,12 @@ intel_dp_program_link_training_pattern(struct intel_dp *intel_dp,
 				       u8 dp_train_pat)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	u8 train_pat_mask = drm_dp_training_pattern_mask(intel_dp->dpcd);
 
-	if (dp_train_pat & train_pat_mask)
+	if ((intel_dp_training_pattern_symbol(dp_train_pat)) !=
+	    DP_TRAINING_PATTERN_DISABLE)
 		drm_dbg_kms(&dev_priv->drm,
 			    "Using DP training pattern TPS%d\n",
-			    dp_train_pat & train_pat_mask);
+			    intel_dp_training_pattern_symbol(dp_train_pat));
 
 	intel_dp->set_link_train(intel_dp, dp_train_pat);
 }
diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
index f2c8b56be9ea..0e1472b1f868 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
@@ -96,7 +96,7 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
 	intel_dp_program_link_training_pattern(intel_dp, dp_train_pat);
 
 	buf[0] = dp_train_pat;
-	if ((dp_train_pat & DP_TRAINING_PATTERN_MASK) ==
+	if (intel_dp_training_pattern_symbol(dp_train_pat) ==
 	    DP_TRAINING_PATTERN_DISABLE) {
 		/* don't write DP_TRAINING_LANEx_SET on disable */
 		len = 1;
diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.h b/drivers/gpu/drm/i915/display/intel_dp_link_training.h
index 01f1dabbb060..518d834dbc98 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.h
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.h
@@ -15,4 +15,10 @@ void intel_dp_get_adjust_train(struct intel_dp *intel_dp,
 void intel_dp_start_link_train(struct intel_dp *intel_dp);
 void intel_dp_stop_link_train(struct intel_dp *intel_dp);
 
+/* Get the TPSx symbol type of the value programmed to DP_TRAINING_PATTERN_SET */
+static inline u8 intel_dp_training_pattern_symbol(u8 pattern)
+{
+	return pattern & ~DP_LINK_SCRAMBLING_DISABLE;
+}
+
 #endif /* __INTEL_DP_LINK_TRAINING_H__ */
-- 
2.25.1

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

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

* [Intel-gfx] [PATCH v2 2/6] drm/i915: Simplify the link training functions
  2020-09-24 18:47 ` [Intel-gfx] " Imre Deak
  (?)
  (?)
@ 2020-09-24 18:48 ` Imre Deak
  -1 siblings, 0 replies; 19+ messages in thread
From: Imre Deak @ 2020-09-24 18:48 UTC (permalink / raw)
  To: intel-gfx

Split the prepare, link training, fallback-handling steps into their own
functions for clarity and as a preparation for the upcoming LTTPR
changes.

While at it also:
- Unexport and inline intel_dp_set_idle_link_train(), which is used at a
  single place.
- Add some documentation to functions that are exported or that can use
  a better description about which part of the LT sequence they
  implement.

v2: (Ville)
- Unexport/inline intel_dp_set_idle_link_train()
- Make the documentation of
  intel_dp_prepare_link_train()/intel_dp_stop_link_train() more accurate
  wrt. HW specific details.

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c       |  6 --
 drivers/gpu/drm/i915/display/intel_dp.h       |  1 -
 .../drm/i915/display/intel_dp_link_training.c | 90 ++++++++++++++-----
 3 files changed, 70 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index bba9669e0e57..b21f42193a11 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4508,12 +4508,6 @@ intel_dp_program_link_training_pattern(struct intel_dp *intel_dp,
 	intel_dp->set_link_train(intel_dp, dp_train_pat);
 }
 
-void intel_dp_set_idle_link_train(struct intel_dp *intel_dp)
-{
-	if (intel_dp->set_idle_link_train)
-		intel_dp->set_idle_link_train(intel_dp);
-}
-
 static void
 intel_dp_link_down(struct intel_encoder *encoder,
 		   const struct intel_crtc_state *old_crtc_state)
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index 08a1c0aa8b94..ca8319d6c63c 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -95,7 +95,6 @@ intel_dp_program_link_training_pattern(struct intel_dp *intel_dp,
 				       u8 dp_train_pat);
 void
 intel_dp_set_signal_levels(struct intel_dp *intel_dp);
-void intel_dp_set_idle_link_train(struct intel_dp *intel_dp);
 void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
 			   u8 *link_bw, u8 *rate_select);
 bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp);
diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
index 0e1472b1f868..78b0f165fadd 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
@@ -146,14 +146,13 @@ static bool intel_dp_link_max_vswing_reached(struct intel_dp *intel_dp)
 	return true;
 }
 
-/* Enable corresponding port and start training pattern 1 */
-static bool
-intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
+/*
+ * Prepare link training by configuring the link parameters. On DDI platforms
+ * also enable the port here.
+ */
+static void intel_dp_prepare_link_train(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
-	u8 voltage;
-	int voltage_tries, cr_tries, max_cr_tries;
-	bool max_vswing_reached = false;
 	u8 link_config[2];
 	u8 link_bw, rate_select;
 
@@ -187,6 +186,16 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
 	drm_dp_dpcd_write(&intel_dp->aux, DP_DOWNSPREAD_CTRL, link_config, 2);
 
 	intel_dp->DP |= DP_PORT_EN;
+}
+
+/* Perform the link training clock recovery phase using training pattern 1. */
+static bool
+intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+	u8 voltage;
+	int voltage_tries, cr_tries, max_cr_tries;
+	bool max_vswing_reached = false;
 
 	/* clock recovery */
 	if (!intel_dp_reset_link_train(intel_dp,
@@ -309,6 +318,10 @@ static u32 intel_dp_training_pattern(struct intel_dp *intel_dp)
 	return DP_TRAINING_PATTERN_2;
 }
 
+/*
+ * Perform the link training channel equalization phase using one of training
+ * pattern 2, 3 or 4 depending on the source and sink capabilities.
+ */
 static bool
 intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
 {
@@ -373,12 +386,27 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
 			    "Channel equalization failed 5 times\n");
 	}
 
-	intel_dp_set_idle_link_train(intel_dp);
+	if (intel_dp->set_idle_link_train)
+		intel_dp->set_idle_link_train(intel_dp);
 
 	return channel_eq;
-
 }
 
+/**
+ * intel_dp_stop_link_train - stop link training
+ * @intel_dp: DP struct
+ *
+ * Stop the link training of the @intel_dp port, disabling the test pattern
+ * symbol generation on the port and disabling the training pattern in
+ * the sink's DPCD.
+ *
+ * What symbols are output on the port after this point is
+ * platform specific: On DDI/VLV/CHV platforms it will be the idle pattern
+ * with the pipe being disabled, on older platforms it's HW specific if/how an
+ * idle pattern is generated, as the pipe is already enabled here for those.
+ *
+ * This function must be called after intel_dp_start_link_train().
+ */
 void intel_dp_stop_link_train(struct intel_dp *intel_dp)
 {
 	intel_dp->link_trained = true;
@@ -387,30 +415,37 @@ void intel_dp_stop_link_train(struct intel_dp *intel_dp)
 				DP_TRAINING_PATTERN_DISABLE);
 }
 
-void
-intel_dp_start_link_train(struct intel_dp *intel_dp)
+static bool
+intel_dp_link_train(struct intel_dp *intel_dp)
 {
 	struct intel_connector *intel_connector = intel_dp->attached_connector;
+	bool ret = false;
+
+	intel_dp_prepare_link_train(intel_dp);
 
 	if (!intel_dp_link_training_clock_recovery(intel_dp))
-		goto failure_handling;
+		goto out;
+
 	if (!intel_dp_link_training_channel_equalization(intel_dp))
-		goto failure_handling;
+		goto out;
 
-	drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
-		    "[CONNECTOR:%d:%s] Link Training Passed at Link Rate = %d, Lane count = %d",
-		    intel_connector->base.base.id,
-		    intel_connector->base.name,
-		    intel_dp->link_rate, intel_dp->lane_count);
-	return;
+	ret = true;
 
- failure_handling:
+out:
 	drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
-		    "[CONNECTOR:%d:%s] Link Training failed at link rate = %d, lane count = %d",
+		    "[CONNECTOR:%d:%s] Link Training %s at Link Rate = %d, Lane count = %d",
 		    intel_connector->base.base.id,
 		    intel_connector->base.name,
+		    ret ? "passed" : "failed",
 		    intel_dp->link_rate, intel_dp->lane_count);
 
+	return ret;
+}
+
+static void intel_dp_schedule_fallback_link_training(struct intel_dp *intel_dp)
+{
+	struct intel_connector *intel_connector = intel_dp->attached_connector;
+
 	if (intel_dp->hobl_active) {
 		drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
 			    "Link Training failed with HOBL active, not enabling it from now on");
@@ -424,3 +459,18 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
 	/* Schedule a Hotplug Uevent to userspace to start modeset */
 	schedule_work(&intel_connector->modeset_retry_work);
 }
+
+/**
+ * intel_dp_start_link_train - start link training
+ * @intel_dp: DP struct
+ *
+ * Start the link training of the @intel_dp port, scheduling a fallback
+ * retraining with reduced link rate/lane parameters if the link training
+ * fails.
+ * After calling this function intel_dp_stop_link_train() must be called.
+ */
+void intel_dp_start_link_train(struct intel_dp *intel_dp)
+{
+	if (!intel_dp_link_train(intel_dp))
+		intel_dp_schedule_fallback_link_training(intel_dp);
+}
-- 
2.25.1

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

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

* [Intel-gfx] [PATCH v2 3/6] drm/i915: Factor out a helper to disable the DPCD training pattern
  2020-09-24 18:47 ` [Intel-gfx] " Imre Deak
                   ` (2 preceding siblings ...)
  (?)
@ 2020-09-24 18:48 ` Imre Deak
  2020-09-24 18:57   ` Ville Syrjälä
  -1 siblings, 1 reply; 19+ messages in thread
From: Imre Deak @ 2020-09-24 18:48 UTC (permalink / raw)
  To: intel-gfx

To prepare for a follow-up LTTPR change factor out a helper to disable
the training pattern in DPCD. We'll need to do this for each LTTPR
(without programming the port to output the idle pattern) when training
in LTTPR non-transparent mode.

While at it also move the disable-link-training logic from
intel_dp_set_link_train() to intel_dp_stop_link_train(), since the
latter is the only user of this.

v2:
- Move the disable-link-training logic to intel_dp_stop_link_train()
  (Ville)

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 .../drm/i915/display/intel_dp_link_training.c | 32 +++++++++----------
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
index 78b0f165fadd..38d4553670a1 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
@@ -91,25 +91,17 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
 			u8 dp_train_pat)
 {
 	u8 buf[sizeof(intel_dp->train_set) + 1];
-	int ret, len;
+	int len;
 
 	intel_dp_program_link_training_pattern(intel_dp, dp_train_pat);
 
 	buf[0] = dp_train_pat;
-	if (intel_dp_training_pattern_symbol(dp_train_pat) ==
-	    DP_TRAINING_PATTERN_DISABLE) {
-		/* don't write DP_TRAINING_LANEx_SET on disable */
-		len = 1;
-	} else {
-		/* DP_TRAINING_LANEx_SET follow DP_TRAINING_PATTERN_SET */
-		memcpy(buf + 1, intel_dp->train_set, intel_dp->lane_count);
-		len = intel_dp->lane_count + 1;
-	}
+	/* DP_TRAINING_LANEx_SET follow DP_TRAINING_PATTERN_SET */
+	memcpy(buf + 1, intel_dp->train_set, intel_dp->lane_count);
+	len = intel_dp->lane_count + 1;
 
-	ret = drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_PATTERN_SET,
-				buf, len);
-
-	return ret == len;
+	return drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_PATTERN_SET,
+				 buf, len) == len;
 }
 
 static bool
@@ -392,6 +384,13 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
 	return channel_eq;
 }
 
+static bool intel_dp_disable_dpcd_training_pattern(struct intel_dp *intel_dp)
+{
+	u8 val = DP_TRAINING_PATTERN_DISABLE;
+
+	return drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_PATTERN_SET, &val, 1) == 1;
+}
+
 /**
  * intel_dp_stop_link_train - stop link training
  * @intel_dp: DP struct
@@ -411,8 +410,9 @@ void intel_dp_stop_link_train(struct intel_dp *intel_dp)
 {
 	intel_dp->link_trained = true;
 
-	intel_dp_set_link_train(intel_dp,
-				DP_TRAINING_PATTERN_DISABLE);
+	intel_dp_program_link_training_pattern(intel_dp,
+					       DP_TRAINING_PATTERN_DISABLE);
+	intel_dp_disable_dpcd_training_pattern(intel_dp);
 }
 
 static bool
-- 
2.25.1

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

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

* [PATCH v2 4/6] drm/dp: Add LTTPR helpers
  2020-09-24 18:47 ` [Intel-gfx] " Imre Deak
@ 2020-09-24 18:48   ` Imre Deak
  -1 siblings, 0 replies; 19+ messages in thread
From: Imre Deak @ 2020-09-24 18:48 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

Add the helpers and register definitions needed to read out the common
and per-PHY LTTPR capabilities and perform link training in the LTTPR
non-transparent mode.

v2:
- Add drm_dp_dpcd_read_phy_link_status() and DP_PHY_LTTPR() here instead
  of adding these to i915. (Ville)

Cc: dri-devel@lists.freedesktop.org
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/drm_dp_helper.c | 244 +++++++++++++++++++++++++++++++-
 include/drm/drm_dp_helper.h     |  62 ++++++++
 2 files changed, 302 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 478dd51f738d..6014c858b06b 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -150,11 +150,8 @@ void drm_dp_link_train_clock_recovery_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
 }
 EXPORT_SYMBOL(drm_dp_link_train_clock_recovery_delay);
 
-void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
+static void __drm_dp_link_train_channel_eq_delay(unsigned long rd_interval)
 {
-	unsigned long rd_interval = dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
-					 DP_TRAINING_AUX_RD_MASK;
-
 	if (rd_interval > 4)
 		DRM_DEBUG_KMS("AUX interval %lu, out of range (max 4)\n",
 			      rd_interval);
@@ -166,8 +163,35 @@ void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
 
 	usleep_range(rd_interval, rd_interval * 2);
 }
+
+void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
+{
+	__drm_dp_link_train_channel_eq_delay(dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
+					     DP_TRAINING_AUX_RD_MASK);
+}
 EXPORT_SYMBOL(drm_dp_link_train_channel_eq_delay);
 
+void drm_dp_lttpr_link_train_clock_recovery_delay(void)
+{
+	usleep_range(100, 200);
+}
+EXPORT_SYMBOL(drm_dp_lttpr_link_train_clock_recovery_delay);
+
+static u8 dp_lttpr_phy_cap(const u8 phy_cap[DP_LTTPR_PHY_CAP_SIZE], int r)
+{
+	return phy_cap[r - DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1];
+}
+
+void drm_dp_lttpr_link_train_channel_eq_delay(const u8 phy_cap[DP_LTTPR_PHY_CAP_SIZE])
+{
+	u8 interval = dp_lttpr_phy_cap(phy_cap,
+				       DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1) &
+		      DP_TRAINING_AUX_RD_MASK;
+
+	__drm_dp_link_train_channel_eq_delay(interval);
+}
+EXPORT_SYMBOL(drm_dp_lttpr_link_train_channel_eq_delay);
+
 u8 drm_dp_link_rate_to_bw_code(int link_rate)
 {
 	/* Spec says link_bw = link_rate / 0.27Gbps */
@@ -363,6 +387,71 @@ int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
 }
 EXPORT_SYMBOL(drm_dp_dpcd_read_link_status);
 
+/**
+ * drm_dp_dpcd_read_phy_link_status - get the link status information for a DP PHY
+ * @aux: DisplayPort AUX channel
+ * @dp_phy: the DP PHY to get the link status for
+ * @link_status: buffer to return the status in
+ *
+ * Fetch the AUX DPCD registers for the DPRX or an LTTPR PHY link status. The
+ * layout of the returned @link_status matches the DPCD register layout of the
+ * DPRX PHY link status.
+ *
+ * Returns 0 if the information was read successfully or a negative error code
+ * on failure.
+ */
+int drm_dp_dpcd_read_phy_link_status(struct drm_dp_aux *aux,
+				     enum drm_dp_phy dp_phy,
+				     u8 link_status[DP_LINK_STATUS_SIZE])
+{
+	u8 lttpr_status[DP_LINK_STATUS_SIZE - 1];
+	int ret;
+
+	if (dp_phy == DP_PHY_DPRX) {
+		ret = drm_dp_dpcd_read(aux,
+				       DP_LANE0_1_STATUS,
+				       link_status,
+				       DP_LINK_STATUS_SIZE);
+
+		if (ret < 0)
+			return ret;
+
+		WARN_ON(ret != DP_LINK_STATUS_SIZE);
+
+		return 0;
+	}
+
+	ret = drm_dp_dpcd_read(aux,
+			       DP_LANE0_1_STATUS_PHY_REPEATER(dp_phy),
+			       lttpr_status,
+			       sizeof(lttpr_status));
+
+	if (ret < 0)
+		return ret;
+
+	WARN_ON(ret != sizeof(lttpr_status));
+
+#define link_reg(reg)	link_status[(reg) - DP_LANE0_1_STATUS]
+#define lttpr_reg(reg)	lttpr_status[(reg) - DP_LANE0_1_STATUS_PHY_REPEATER1]
+
+	/* Convert the LTTPR to the sink PHY link status layout */
+	link_reg(DP_LANE0_1_STATUS) = lttpr_reg(DP_LANE0_1_STATUS_PHY_REPEATER1);
+	link_reg(DP_LANE2_3_STATUS) = lttpr_reg(DP_LANE2_3_STATUS_PHY_REPEATER1);
+	link_reg(DP_LANE_ALIGN_STATUS_UPDATED) =
+		lttpr_reg(DP_LANE_ALIGN_STATUS_UPDATED_PHY_REPEATER1);
+	link_reg(DP_SINK_STATUS) = 0;
+	link_reg(DP_ADJUST_REQUEST_LANE0_1) =
+		lttpr_reg(DP_ADJUST_REQUEST_LANE0_1_PHY_REPEATER1);
+	link_reg(DP_ADJUST_REQUEST_LANE2_3) =
+		lttpr_reg(DP_ADJUST_REQUEST_LANE2_3_PHY_REPEATER1);
+
+#undef link_reg
+#undef lttpr_reg
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_dp_dpcd_read_phy_link_status);
+
 static bool is_edid_digital_input_dp(const struct edid *edid)
 {
 	return edid && edid->revision >= 4 &&
@@ -2098,6 +2187,153 @@ int drm_dp_dsc_sink_supported_input_bpcs(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_S
 }
 EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs);
 
+/**
+ * drm_dp_read_lttpr_common_caps - read the LTTPR common capabilities
+ * @aux: DisplayPort AUX channel
+ * @caps: buffer to return the capability info in
+ *
+ * Read capabilities common to all LTTPRs.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int drm_dp_read_lttpr_common_caps(struct drm_dp_aux *aux,
+				  u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
+{
+	int ret;
+
+	ret = drm_dp_dpcd_read(aux,
+			       DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
+			       caps, DP_LTTPR_COMMON_CAP_SIZE);
+	if (ret < 0)
+		return ret;
+
+	WARN_ON(ret != DP_LTTPR_COMMON_CAP_SIZE);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_dp_read_lttpr_common_caps);
+
+/**
+ * drm_dp_read_lttpr_phy_caps - read the capabilities for a given LTTPR PHY
+ * @aux: DisplayPort AUX channel
+ * @dp_phy: LTTPR PHY to read the capabilities for
+ * @caps: buffer to return the capability info in
+ *
+ * Read the capabilities for the given LTTPR PHY.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int drm_dp_read_lttpr_phy_caps(struct drm_dp_aux *aux,
+			       enum drm_dp_phy dp_phy,
+			       u8 caps[DP_LTTPR_PHY_CAP_SIZE])
+{
+	int ret;
+
+	ret = drm_dp_dpcd_read(aux,
+			       DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER(dp_phy),
+			       caps, DP_LTTPR_PHY_CAP_SIZE);
+	if (ret < 0)
+		return ret;
+
+	WARN_ON(ret != DP_LTTPR_PHY_CAP_SIZE);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_dp_read_lttpr_phy_caps);
+
+static u8 dp_lttpr_common_cap(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE], int r)
+{
+	return caps[r - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
+}
+
+/**
+ * drm_dp_lttpr_count - get the number of detected LTTPRs
+ * @caps: LTTPR common capabilities
+ *
+ * Get the number of detected LTTPRs from the LTTPR common capabilities info.
+ *
+ * Returns:
+ *   -ERANGE if more than supported number (8) of LTTPRs are detected
+ *   -EINVAL if the DP_PHY_REPEATER_CNT register contains an invalid value
+ *   otherwise the number of detected LTTPRs
+ */
+int drm_dp_lttpr_count(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
+{
+	u8 count = dp_lttpr_common_cap(caps, DP_PHY_REPEATER_CNT);
+
+	switch (hweight8(count)) {
+	case 0:
+		return 0;
+	case 1:
+		return 8 - ilog2(count);
+	case 8:
+		return -ERANGE;
+	default:
+		return -EINVAL;
+	}
+}
+EXPORT_SYMBOL(drm_dp_lttpr_count);
+
+/**
+ * drm_dp_lttpr_max_link_rate - get the maximum link rate supported by all LTTPRs
+ * @caps: LTTPR common capabilities
+ *
+ * Returns the maximum link rate supported by all detected LTTPRs.
+ */
+int drm_dp_lttpr_max_link_rate(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
+{
+	u8 rate = dp_lttpr_common_cap(caps, DP_MAX_LINK_RATE_PHY_REPEATER);
+
+	return drm_dp_bw_code_to_link_rate(rate);
+}
+EXPORT_SYMBOL(drm_dp_lttpr_max_link_rate);
+
+/**
+ * drm_dp_lttpr_max_lane_count - get the maximum lane count supported by all LTTPRs
+ * @caps: LTTPR common capabilities
+ *
+ * Returns the maximum lane count supported by all detected LTTPRs.
+ */
+int drm_dp_lttpr_max_lane_count(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
+{
+	u8 max_lanes = dp_lttpr_common_cap(caps, DP_MAX_LANE_COUNT_PHY_REPEATER);
+
+	return max_lanes & DP_MAX_LANE_COUNT_MASK;
+}
+EXPORT_SYMBOL(drm_dp_lttpr_max_lane_count);
+
+/**
+ * drm_dp_lttpr_voltage_swing_level_3_supported - check for LTTPR vswing3 support
+ * @caps: LTTPR PHY capabilities
+ *
+ * Returns true if the @caps for an LTTPR TX PHY indicate support for
+ * voltage swing level 3.
+ */
+bool
+drm_dp_lttpr_voltage_swing_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE])
+{
+	u8 txcap = dp_lttpr_phy_cap(caps, DP_TRANSMITTER_CAPABILITY_PHY_REPEATER1);
+
+	return txcap & DP_VOLTAGE_SWING_LEVEL_3_SUPPORTED;
+}
+EXPORT_SYMBOL(drm_dp_lttpr_voltage_swing_level_3_supported);
+
+/**
+ * drm_dp_lttpr_pre_emphasis_level_3_supported - check for LTTPR preemph3 support
+ * @caps: LTTPR PHY capabilities
+ *
+ * Returns true if the @caps for an LTTPR TX PHY indicate support for
+ * pre-emphasis level 3.
+ */
+bool
+drm_dp_lttpr_pre_emphasis_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE])
+{
+	u8 txcap = dp_lttpr_phy_cap(caps, DP_TRANSMITTER_CAPABILITY_PHY_REPEATER1);
+
+	return txcap & DP_PRE_EMPHASIS_LEVEL_3_SUPPORTED;
+}
+EXPORT_SYMBOL(drm_dp_lttpr_pre_emphasis_level_3_supported);
+
 /**
  * drm_dp_get_phy_test_pattern() - get the requested pattern from the sink.
  * @aux: DisplayPort AUX channel
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index e144b4b9d79a..42b6ab14920a 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -1118,15 +1118,58 @@ struct drm_device;
 #define DP_MAX_LANE_COUNT_PHY_REPEATER			    0xf0004 /* 1.4a */
 #define DP_Repeater_FEC_CAPABILITY			    0xf0004 /* 1.4 */
 #define DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT		    0xf0005 /* 1.4a */
+
+enum drm_dp_phy {
+	DP_PHY_DPRX,
+
+	DP_PHY_LTTPR1,
+	DP_PHY_LTTPR2,
+	DP_PHY_LTTPR3,
+	DP_PHY_LTTPR4,
+	DP_PHY_LTTPR5,
+	DP_PHY_LTTPR6,
+	DP_PHY_LTTPR7,
+	DP_PHY_LTTPR8,
+
+	DP_MAX_LTTPR_COUNT = DP_PHY_LTTPR8,
+};
+
+#define DP_PHY_LTTPR(i)					    (DP_PHY_LTTPR1 + (i))
+
+#define __DP_LTTPR1_BASE				    0xf0010 /* 1.3 */
+#define __DP_LTTPR2_BASE				    0xf0060 /* 1.3 */
+#define DP_LTTPR_BASE(dp_phy) \
+	(__DP_LTTPR1_BASE + (__DP_LTTPR2_BASE - __DP_LTTPR1_BASE) * \
+		((dp_phy) - DP_PHY_LTTPR1))
+
+#define DP_LTTPR_REG(dp_phy, lttpr1_reg) \
+	(DP_LTTPR_BASE(dp_phy) - DP_LTTPR_BASE(DP_PHY_LTTPR1) + (lttpr1_reg))
+
 #define DP_TRAINING_PATTERN_SET_PHY_REPEATER1		    0xf0010 /* 1.3 */
+#define DP_TRAINING_PATTERN_SET_PHY_REPEATER(dp_phy) \
+	DP_LTTPR_REG(dp_phy, DP_TRAINING_PATTERN_SET_PHY_REPEATER1)
+
 #define DP_TRAINING_LANE0_SET_PHY_REPEATER1		    0xf0011 /* 1.3 */
+#define DP_TRAINING_LANE0_SET_PHY_REPEATER(dp_phy) \
+	DP_LTTPR_REG(dp_phy, DP_TRAINING_LANE0_SET_PHY_REPEATER1)
+
 #define DP_TRAINING_LANE1_SET_PHY_REPEATER1		    0xf0012 /* 1.3 */
 #define DP_TRAINING_LANE2_SET_PHY_REPEATER1		    0xf0013 /* 1.3 */
 #define DP_TRAINING_LANE3_SET_PHY_REPEATER1		    0xf0014 /* 1.3 */
 #define DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1	    0xf0020 /* 1.4a */
+#define DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER(dp_phy)	\
+	DP_LTTPR_REG(dp_phy, DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1)
+
 #define DP_TRANSMITTER_CAPABILITY_PHY_REPEATER1		    0xf0021 /* 1.4a */
+# define DP_VOLTAGE_SWING_LEVEL_3_SUPPORTED		    BIT(0)
+# define DP_PRE_EMPHASIS_LEVEL_3_SUPPORTED		    BIT(1)
+
 #define DP_LANE0_1_STATUS_PHY_REPEATER1			    0xf0030 /* 1.3 */
+#define DP_LANE0_1_STATUS_PHY_REPEATER(dp_phy) \
+	DP_LTTPR_REG(dp_phy, DP_LANE0_1_STATUS_PHY_REPEATER1)
+
 #define DP_LANE2_3_STATUS_PHY_REPEATER1			    0xf0031 /* 1.3 */
+
 #define DP_LANE_ALIGN_STATUS_UPDATED_PHY_REPEATER1	    0xf0032 /* 1.3 */
 #define DP_ADJUST_REQUEST_LANE0_1_PHY_REPEATER1		    0xf0033 /* 1.3 */
 #define DP_ADJUST_REQUEST_LANE2_3_PHY_REPEATER1		    0xf0034 /* 1.3 */
@@ -1236,9 +1279,13 @@ u8 drm_dp_get_adjust_request_post_cursor(const u8 link_status[DP_LINK_STATUS_SIZ
 #define DP_DSC_RECEIVER_CAP_SIZE        0xf
 #define EDP_PSR_RECEIVER_CAP_SIZE	2
 #define EDP_DISPLAY_CTL_CAP_SIZE	3
+#define DP_LTTPR_COMMON_CAP_SIZE	8
+#define DP_LTTPR_PHY_CAP_SIZE		3
 
 void drm_dp_link_train_clock_recovery_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]);
+void drm_dp_lttpr_link_train_clock_recovery_delay(void);
 void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]);
+void drm_dp_lttpr_link_train_channel_eq_delay(const u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
 
 u8 drm_dp_link_rate_to_bw_code(int link_rate);
 int drm_dp_bw_code_to_link_rate(u8 link_bw);
@@ -1697,6 +1744,10 @@ int drm_dp_read_dpcd_caps(struct drm_dp_aux *aux,
 int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
 				 u8 status[DP_LINK_STATUS_SIZE]);
 
+int drm_dp_dpcd_read_phy_link_status(struct drm_dp_aux *aux,
+				     enum drm_dp_phy dp_phy,
+				     u8 link_status[DP_LINK_STATUS_SIZE]);
+
 bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux,
 				    u8 real_edid_checksum);
 
@@ -1746,6 +1797,17 @@ bool drm_dp_read_sink_count_cap(struct drm_connector *connector,
 				const struct drm_dp_desc *desc);
 int drm_dp_read_sink_count(struct drm_dp_aux *aux);
 
+int drm_dp_read_lttpr_common_caps(struct drm_dp_aux *aux,
+				  u8 caps[DP_LTTPR_COMMON_CAP_SIZE]);
+int drm_dp_read_lttpr_phy_caps(struct drm_dp_aux *aux,
+			       enum drm_dp_phy dp_phy,
+			       u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
+int drm_dp_lttpr_count(const u8 cap[DP_LTTPR_COMMON_CAP_SIZE]);
+int drm_dp_lttpr_max_link_rate(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE]);
+int drm_dp_lttpr_max_lane_count(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE]);
+bool drm_dp_lttpr_voltage_swing_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
+bool drm_dp_lttpr_pre_emphasis_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
+
 void drm_dp_remote_aux_init(struct drm_dp_aux *aux);
 void drm_dp_aux_init(struct drm_dp_aux *aux);
 int drm_dp_aux_register(struct drm_dp_aux *aux);
-- 
2.25.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [Intel-gfx] [PATCH v2 4/6] drm/dp: Add LTTPR helpers
@ 2020-09-24 18:48   ` Imre Deak
  0 siblings, 0 replies; 19+ messages in thread
From: Imre Deak @ 2020-09-24 18:48 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

Add the helpers and register definitions needed to read out the common
and per-PHY LTTPR capabilities and perform link training in the LTTPR
non-transparent mode.

v2:
- Add drm_dp_dpcd_read_phy_link_status() and DP_PHY_LTTPR() here instead
  of adding these to i915. (Ville)

Cc: dri-devel@lists.freedesktop.org
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/drm_dp_helper.c | 244 +++++++++++++++++++++++++++++++-
 include/drm/drm_dp_helper.h     |  62 ++++++++
 2 files changed, 302 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 478dd51f738d..6014c858b06b 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -150,11 +150,8 @@ void drm_dp_link_train_clock_recovery_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
 }
 EXPORT_SYMBOL(drm_dp_link_train_clock_recovery_delay);
 
-void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
+static void __drm_dp_link_train_channel_eq_delay(unsigned long rd_interval)
 {
-	unsigned long rd_interval = dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
-					 DP_TRAINING_AUX_RD_MASK;
-
 	if (rd_interval > 4)
 		DRM_DEBUG_KMS("AUX interval %lu, out of range (max 4)\n",
 			      rd_interval);
@@ -166,8 +163,35 @@ void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
 
 	usleep_range(rd_interval, rd_interval * 2);
 }
+
+void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
+{
+	__drm_dp_link_train_channel_eq_delay(dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
+					     DP_TRAINING_AUX_RD_MASK);
+}
 EXPORT_SYMBOL(drm_dp_link_train_channel_eq_delay);
 
+void drm_dp_lttpr_link_train_clock_recovery_delay(void)
+{
+	usleep_range(100, 200);
+}
+EXPORT_SYMBOL(drm_dp_lttpr_link_train_clock_recovery_delay);
+
+static u8 dp_lttpr_phy_cap(const u8 phy_cap[DP_LTTPR_PHY_CAP_SIZE], int r)
+{
+	return phy_cap[r - DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1];
+}
+
+void drm_dp_lttpr_link_train_channel_eq_delay(const u8 phy_cap[DP_LTTPR_PHY_CAP_SIZE])
+{
+	u8 interval = dp_lttpr_phy_cap(phy_cap,
+				       DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1) &
+		      DP_TRAINING_AUX_RD_MASK;
+
+	__drm_dp_link_train_channel_eq_delay(interval);
+}
+EXPORT_SYMBOL(drm_dp_lttpr_link_train_channel_eq_delay);
+
 u8 drm_dp_link_rate_to_bw_code(int link_rate)
 {
 	/* Spec says link_bw = link_rate / 0.27Gbps */
@@ -363,6 +387,71 @@ int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
 }
 EXPORT_SYMBOL(drm_dp_dpcd_read_link_status);
 
+/**
+ * drm_dp_dpcd_read_phy_link_status - get the link status information for a DP PHY
+ * @aux: DisplayPort AUX channel
+ * @dp_phy: the DP PHY to get the link status for
+ * @link_status: buffer to return the status in
+ *
+ * Fetch the AUX DPCD registers for the DPRX or an LTTPR PHY link status. The
+ * layout of the returned @link_status matches the DPCD register layout of the
+ * DPRX PHY link status.
+ *
+ * Returns 0 if the information was read successfully or a negative error code
+ * on failure.
+ */
+int drm_dp_dpcd_read_phy_link_status(struct drm_dp_aux *aux,
+				     enum drm_dp_phy dp_phy,
+				     u8 link_status[DP_LINK_STATUS_SIZE])
+{
+	u8 lttpr_status[DP_LINK_STATUS_SIZE - 1];
+	int ret;
+
+	if (dp_phy == DP_PHY_DPRX) {
+		ret = drm_dp_dpcd_read(aux,
+				       DP_LANE0_1_STATUS,
+				       link_status,
+				       DP_LINK_STATUS_SIZE);
+
+		if (ret < 0)
+			return ret;
+
+		WARN_ON(ret != DP_LINK_STATUS_SIZE);
+
+		return 0;
+	}
+
+	ret = drm_dp_dpcd_read(aux,
+			       DP_LANE0_1_STATUS_PHY_REPEATER(dp_phy),
+			       lttpr_status,
+			       sizeof(lttpr_status));
+
+	if (ret < 0)
+		return ret;
+
+	WARN_ON(ret != sizeof(lttpr_status));
+
+#define link_reg(reg)	link_status[(reg) - DP_LANE0_1_STATUS]
+#define lttpr_reg(reg)	lttpr_status[(reg) - DP_LANE0_1_STATUS_PHY_REPEATER1]
+
+	/* Convert the LTTPR to the sink PHY link status layout */
+	link_reg(DP_LANE0_1_STATUS) = lttpr_reg(DP_LANE0_1_STATUS_PHY_REPEATER1);
+	link_reg(DP_LANE2_3_STATUS) = lttpr_reg(DP_LANE2_3_STATUS_PHY_REPEATER1);
+	link_reg(DP_LANE_ALIGN_STATUS_UPDATED) =
+		lttpr_reg(DP_LANE_ALIGN_STATUS_UPDATED_PHY_REPEATER1);
+	link_reg(DP_SINK_STATUS) = 0;
+	link_reg(DP_ADJUST_REQUEST_LANE0_1) =
+		lttpr_reg(DP_ADJUST_REQUEST_LANE0_1_PHY_REPEATER1);
+	link_reg(DP_ADJUST_REQUEST_LANE2_3) =
+		lttpr_reg(DP_ADJUST_REQUEST_LANE2_3_PHY_REPEATER1);
+
+#undef link_reg
+#undef lttpr_reg
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_dp_dpcd_read_phy_link_status);
+
 static bool is_edid_digital_input_dp(const struct edid *edid)
 {
 	return edid && edid->revision >= 4 &&
@@ -2098,6 +2187,153 @@ int drm_dp_dsc_sink_supported_input_bpcs(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_S
 }
 EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs);
 
+/**
+ * drm_dp_read_lttpr_common_caps - read the LTTPR common capabilities
+ * @aux: DisplayPort AUX channel
+ * @caps: buffer to return the capability info in
+ *
+ * Read capabilities common to all LTTPRs.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int drm_dp_read_lttpr_common_caps(struct drm_dp_aux *aux,
+				  u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
+{
+	int ret;
+
+	ret = drm_dp_dpcd_read(aux,
+			       DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
+			       caps, DP_LTTPR_COMMON_CAP_SIZE);
+	if (ret < 0)
+		return ret;
+
+	WARN_ON(ret != DP_LTTPR_COMMON_CAP_SIZE);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_dp_read_lttpr_common_caps);
+
+/**
+ * drm_dp_read_lttpr_phy_caps - read the capabilities for a given LTTPR PHY
+ * @aux: DisplayPort AUX channel
+ * @dp_phy: LTTPR PHY to read the capabilities for
+ * @caps: buffer to return the capability info in
+ *
+ * Read the capabilities for the given LTTPR PHY.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int drm_dp_read_lttpr_phy_caps(struct drm_dp_aux *aux,
+			       enum drm_dp_phy dp_phy,
+			       u8 caps[DP_LTTPR_PHY_CAP_SIZE])
+{
+	int ret;
+
+	ret = drm_dp_dpcd_read(aux,
+			       DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER(dp_phy),
+			       caps, DP_LTTPR_PHY_CAP_SIZE);
+	if (ret < 0)
+		return ret;
+
+	WARN_ON(ret != DP_LTTPR_PHY_CAP_SIZE);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_dp_read_lttpr_phy_caps);
+
+static u8 dp_lttpr_common_cap(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE], int r)
+{
+	return caps[r - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
+}
+
+/**
+ * drm_dp_lttpr_count - get the number of detected LTTPRs
+ * @caps: LTTPR common capabilities
+ *
+ * Get the number of detected LTTPRs from the LTTPR common capabilities info.
+ *
+ * Returns:
+ *   -ERANGE if more than supported number (8) of LTTPRs are detected
+ *   -EINVAL if the DP_PHY_REPEATER_CNT register contains an invalid value
+ *   otherwise the number of detected LTTPRs
+ */
+int drm_dp_lttpr_count(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
+{
+	u8 count = dp_lttpr_common_cap(caps, DP_PHY_REPEATER_CNT);
+
+	switch (hweight8(count)) {
+	case 0:
+		return 0;
+	case 1:
+		return 8 - ilog2(count);
+	case 8:
+		return -ERANGE;
+	default:
+		return -EINVAL;
+	}
+}
+EXPORT_SYMBOL(drm_dp_lttpr_count);
+
+/**
+ * drm_dp_lttpr_max_link_rate - get the maximum link rate supported by all LTTPRs
+ * @caps: LTTPR common capabilities
+ *
+ * Returns the maximum link rate supported by all detected LTTPRs.
+ */
+int drm_dp_lttpr_max_link_rate(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
+{
+	u8 rate = dp_lttpr_common_cap(caps, DP_MAX_LINK_RATE_PHY_REPEATER);
+
+	return drm_dp_bw_code_to_link_rate(rate);
+}
+EXPORT_SYMBOL(drm_dp_lttpr_max_link_rate);
+
+/**
+ * drm_dp_lttpr_max_lane_count - get the maximum lane count supported by all LTTPRs
+ * @caps: LTTPR common capabilities
+ *
+ * Returns the maximum lane count supported by all detected LTTPRs.
+ */
+int drm_dp_lttpr_max_lane_count(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
+{
+	u8 max_lanes = dp_lttpr_common_cap(caps, DP_MAX_LANE_COUNT_PHY_REPEATER);
+
+	return max_lanes & DP_MAX_LANE_COUNT_MASK;
+}
+EXPORT_SYMBOL(drm_dp_lttpr_max_lane_count);
+
+/**
+ * drm_dp_lttpr_voltage_swing_level_3_supported - check for LTTPR vswing3 support
+ * @caps: LTTPR PHY capabilities
+ *
+ * Returns true if the @caps for an LTTPR TX PHY indicate support for
+ * voltage swing level 3.
+ */
+bool
+drm_dp_lttpr_voltage_swing_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE])
+{
+	u8 txcap = dp_lttpr_phy_cap(caps, DP_TRANSMITTER_CAPABILITY_PHY_REPEATER1);
+
+	return txcap & DP_VOLTAGE_SWING_LEVEL_3_SUPPORTED;
+}
+EXPORT_SYMBOL(drm_dp_lttpr_voltage_swing_level_3_supported);
+
+/**
+ * drm_dp_lttpr_pre_emphasis_level_3_supported - check for LTTPR preemph3 support
+ * @caps: LTTPR PHY capabilities
+ *
+ * Returns true if the @caps for an LTTPR TX PHY indicate support for
+ * pre-emphasis level 3.
+ */
+bool
+drm_dp_lttpr_pre_emphasis_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE])
+{
+	u8 txcap = dp_lttpr_phy_cap(caps, DP_TRANSMITTER_CAPABILITY_PHY_REPEATER1);
+
+	return txcap & DP_PRE_EMPHASIS_LEVEL_3_SUPPORTED;
+}
+EXPORT_SYMBOL(drm_dp_lttpr_pre_emphasis_level_3_supported);
+
 /**
  * drm_dp_get_phy_test_pattern() - get the requested pattern from the sink.
  * @aux: DisplayPort AUX channel
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index e144b4b9d79a..42b6ab14920a 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -1118,15 +1118,58 @@ struct drm_device;
 #define DP_MAX_LANE_COUNT_PHY_REPEATER			    0xf0004 /* 1.4a */
 #define DP_Repeater_FEC_CAPABILITY			    0xf0004 /* 1.4 */
 #define DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT		    0xf0005 /* 1.4a */
+
+enum drm_dp_phy {
+	DP_PHY_DPRX,
+
+	DP_PHY_LTTPR1,
+	DP_PHY_LTTPR2,
+	DP_PHY_LTTPR3,
+	DP_PHY_LTTPR4,
+	DP_PHY_LTTPR5,
+	DP_PHY_LTTPR6,
+	DP_PHY_LTTPR7,
+	DP_PHY_LTTPR8,
+
+	DP_MAX_LTTPR_COUNT = DP_PHY_LTTPR8,
+};
+
+#define DP_PHY_LTTPR(i)					    (DP_PHY_LTTPR1 + (i))
+
+#define __DP_LTTPR1_BASE				    0xf0010 /* 1.3 */
+#define __DP_LTTPR2_BASE				    0xf0060 /* 1.3 */
+#define DP_LTTPR_BASE(dp_phy) \
+	(__DP_LTTPR1_BASE + (__DP_LTTPR2_BASE - __DP_LTTPR1_BASE) * \
+		((dp_phy) - DP_PHY_LTTPR1))
+
+#define DP_LTTPR_REG(dp_phy, lttpr1_reg) \
+	(DP_LTTPR_BASE(dp_phy) - DP_LTTPR_BASE(DP_PHY_LTTPR1) + (lttpr1_reg))
+
 #define DP_TRAINING_PATTERN_SET_PHY_REPEATER1		    0xf0010 /* 1.3 */
+#define DP_TRAINING_PATTERN_SET_PHY_REPEATER(dp_phy) \
+	DP_LTTPR_REG(dp_phy, DP_TRAINING_PATTERN_SET_PHY_REPEATER1)
+
 #define DP_TRAINING_LANE0_SET_PHY_REPEATER1		    0xf0011 /* 1.3 */
+#define DP_TRAINING_LANE0_SET_PHY_REPEATER(dp_phy) \
+	DP_LTTPR_REG(dp_phy, DP_TRAINING_LANE0_SET_PHY_REPEATER1)
+
 #define DP_TRAINING_LANE1_SET_PHY_REPEATER1		    0xf0012 /* 1.3 */
 #define DP_TRAINING_LANE2_SET_PHY_REPEATER1		    0xf0013 /* 1.3 */
 #define DP_TRAINING_LANE3_SET_PHY_REPEATER1		    0xf0014 /* 1.3 */
 #define DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1	    0xf0020 /* 1.4a */
+#define DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER(dp_phy)	\
+	DP_LTTPR_REG(dp_phy, DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1)
+
 #define DP_TRANSMITTER_CAPABILITY_PHY_REPEATER1		    0xf0021 /* 1.4a */
+# define DP_VOLTAGE_SWING_LEVEL_3_SUPPORTED		    BIT(0)
+# define DP_PRE_EMPHASIS_LEVEL_3_SUPPORTED		    BIT(1)
+
 #define DP_LANE0_1_STATUS_PHY_REPEATER1			    0xf0030 /* 1.3 */
+#define DP_LANE0_1_STATUS_PHY_REPEATER(dp_phy) \
+	DP_LTTPR_REG(dp_phy, DP_LANE0_1_STATUS_PHY_REPEATER1)
+
 #define DP_LANE2_3_STATUS_PHY_REPEATER1			    0xf0031 /* 1.3 */
+
 #define DP_LANE_ALIGN_STATUS_UPDATED_PHY_REPEATER1	    0xf0032 /* 1.3 */
 #define DP_ADJUST_REQUEST_LANE0_1_PHY_REPEATER1		    0xf0033 /* 1.3 */
 #define DP_ADJUST_REQUEST_LANE2_3_PHY_REPEATER1		    0xf0034 /* 1.3 */
@@ -1236,9 +1279,13 @@ u8 drm_dp_get_adjust_request_post_cursor(const u8 link_status[DP_LINK_STATUS_SIZ
 #define DP_DSC_RECEIVER_CAP_SIZE        0xf
 #define EDP_PSR_RECEIVER_CAP_SIZE	2
 #define EDP_DISPLAY_CTL_CAP_SIZE	3
+#define DP_LTTPR_COMMON_CAP_SIZE	8
+#define DP_LTTPR_PHY_CAP_SIZE		3
 
 void drm_dp_link_train_clock_recovery_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]);
+void drm_dp_lttpr_link_train_clock_recovery_delay(void);
 void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]);
+void drm_dp_lttpr_link_train_channel_eq_delay(const u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
 
 u8 drm_dp_link_rate_to_bw_code(int link_rate);
 int drm_dp_bw_code_to_link_rate(u8 link_bw);
@@ -1697,6 +1744,10 @@ int drm_dp_read_dpcd_caps(struct drm_dp_aux *aux,
 int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
 				 u8 status[DP_LINK_STATUS_SIZE]);
 
+int drm_dp_dpcd_read_phy_link_status(struct drm_dp_aux *aux,
+				     enum drm_dp_phy dp_phy,
+				     u8 link_status[DP_LINK_STATUS_SIZE]);
+
 bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux,
 				    u8 real_edid_checksum);
 
@@ -1746,6 +1797,17 @@ bool drm_dp_read_sink_count_cap(struct drm_connector *connector,
 				const struct drm_dp_desc *desc);
 int drm_dp_read_sink_count(struct drm_dp_aux *aux);
 
+int drm_dp_read_lttpr_common_caps(struct drm_dp_aux *aux,
+				  u8 caps[DP_LTTPR_COMMON_CAP_SIZE]);
+int drm_dp_read_lttpr_phy_caps(struct drm_dp_aux *aux,
+			       enum drm_dp_phy dp_phy,
+			       u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
+int drm_dp_lttpr_count(const u8 cap[DP_LTTPR_COMMON_CAP_SIZE]);
+int drm_dp_lttpr_max_link_rate(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE]);
+int drm_dp_lttpr_max_lane_count(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE]);
+bool drm_dp_lttpr_voltage_swing_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
+bool drm_dp_lttpr_pre_emphasis_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
+
 void drm_dp_remote_aux_init(struct drm_dp_aux *aux);
 void drm_dp_aux_init(struct drm_dp_aux *aux);
 int drm_dp_aux_register(struct drm_dp_aux *aux);
-- 
2.25.1

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

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

* [Intel-gfx] [PATCH v2 5/6] drm/i915: Switch to LTTPR transparent mode link training
  2020-09-24 18:47 ` [Intel-gfx] " Imre Deak
                   ` (4 preceding siblings ...)
  (?)
@ 2020-09-24 18:48 ` Imre Deak
  2020-09-25 16:03   ` Ville Syrjälä
  -1 siblings, 1 reply; 19+ messages in thread
From: Imre Deak @ 2020-09-24 18:48 UTC (permalink / raw)
  To: intel-gfx

By default LTTPRs should be in transparent link training mode,
nevertheless in this patch we switch to this default mode explicitly.

The DP Standard recommends this, supposedly because an LTTPR may be left
in the non-transparent mode (by BIOS, previous kernel, or after reset
due to a firmware bug). I haven't seen this happening, but let's follow
the DP Standard.

v2:
- Add a code comment about the explicit disabling of non-transparent
  mode.

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 .../drm/i915/display/intel_display_types.h    |  1 +
 drivers/gpu/drm/i915/display/intel_dp.c       |  3 ++
 .../drm/i915/display/intel_dp_link_training.c | 52 +++++++++++++++++++
 .../drm/i915/display/intel_dp_link_training.h |  2 +
 4 files changed, 58 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 3d4bf9b6a0a2..b04921eba73b 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1280,6 +1280,7 @@ struct intel_dp {
 	u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
 	u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE];
 	u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE];
+	u8 lttpr_common_caps[DP_LTTPR_COMMON_CAP_SIZE];
 	u8 fec_capable;
 	/* source rates */
 	int num_source_rates;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index b21f42193a11..64bf4aa384d3 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4726,6 +4726,9 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 {
 	int ret;
 
+	if (!intel_dp_is_edp(intel_dp))
+		intel_dp_lttpr_init(intel_dp);
+
 	if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd))
 		return false;
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
index 38d4553670a1..4f8f42cc25fa 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
@@ -34,6 +34,52 @@ intel_dp_dump_link_status(const u8 link_status[DP_LINK_STATUS_SIZE])
 		      link_status[3], link_status[4], link_status[5]);
 }
 
+static bool intel_dp_read_lttpr_common_caps(struct intel_dp *intel_dp)
+{
+	if (drm_dp_read_lttpr_common_caps(&intel_dp->aux,
+					  intel_dp->lttpr_common_caps) < 0) {
+		memset(intel_dp->lttpr_common_caps, 0,
+		       sizeof(intel_dp->lttpr_common_caps));
+		return false;
+	}
+
+	drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
+		    "LTTPR common capabilities: %*ph\n",
+		    (int)sizeof(intel_dp->lttpr_common_caps),
+		    intel_dp->lttpr_common_caps);
+
+	return true;
+}
+
+static bool
+intel_dp_set_lttpr_transparent_mode(struct intel_dp *intel_dp, bool enable)
+{
+	u8 val = enable ? DP_PHY_REPEATER_MODE_TRANSPARENT :
+			  DP_PHY_REPEATER_MODE_NON_TRANSPARENT;
+
+	return drm_dp_dpcd_write(&intel_dp->aux, DP_PHY_REPEATER_MODE, &val, 1) == 1;
+}
+
+/**
+ * intel_dp_lttpr_init - detect LTTPRs and init the LTTPR link training mode
+ * @intel_dp: Intel DP struct
+ *
+ * Read the LTTPR common capabilities and switch to transparent link training
+ * mode.
+ */
+int intel_dp_lttpr_init(struct intel_dp *intel_dp)
+{
+	intel_dp_read_lttpr_common_caps(intel_dp);
+
+	/*
+	 * See DP Standard v2.0 3.6.6.1. about the explicit disabling of
+	 * non-transparent mode.
+	 */
+	intel_dp_set_lttpr_transparent_mode(intel_dp, true);
+
+	return 0;
+}
+
 static u8 dp_voltage_max(u8 preemph)
 {
 	switch (preemph & DP_TRAIN_PRE_EMPHASIS_MASK) {
@@ -471,6 +517,12 @@ static void intel_dp_schedule_fallback_link_training(struct intel_dp *intel_dp)
  */
 void intel_dp_start_link_train(struct intel_dp *intel_dp)
 {
+	/*
+	 * TODO: Reiniting LTTPRs here won't be needed once proper connector
+	 * HW state readout is added.
+	 */
+	intel_dp_lttpr_init(intel_dp);
+
 	if (!intel_dp_link_train(intel_dp))
 		intel_dp_schedule_fallback_link_training(intel_dp);
 }
diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.h b/drivers/gpu/drm/i915/display/intel_dp_link_training.h
index 518d834dbc98..3536ce73a123 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.h
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.h
@@ -10,6 +10,8 @@
 
 struct intel_dp;
 
+int intel_dp_lttpr_init(struct intel_dp *intel_dp);
+
 void intel_dp_get_adjust_train(struct intel_dp *intel_dp,
 			       const u8 link_status[DP_LINK_STATUS_SIZE]);
 void intel_dp_start_link_train(struct intel_dp *intel_dp);
-- 
2.25.1

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

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

* [Intel-gfx] [PATCH v2 6/6] drm/i915: Switch to LTTPR non-transparent mode link training
  2020-09-24 18:47 ` [Intel-gfx] " Imre Deak
                   ` (5 preceding siblings ...)
  (?)
@ 2020-09-24 18:48 ` Imre Deak
  -1 siblings, 0 replies; 19+ messages in thread
From: Imre Deak @ 2020-09-24 18:48 UTC (permalink / raw)
  To: intel-gfx

The DP Standard's recommendation is to use the LTTPR non-transparent
mode link training if LTTPRs are detected, so let's do this.

Besides power-saving, the advantages of this are that the maximum number
of LTTPRs can only be used in non-transparent mode (the limit is 5-8 in
transparent mode), and it provides a way to narrow down the reason for a
link training failure to a given link segment. Non-transparent mode is
probably also the mode that was tested the most by the industry.

The changes in this patchset:
- Pass the DP PHY that is currently link trained to all LT helpers, so
  that these can access the correct LTTPR/DPRX DPCD registers.
- During LT take into account the LTTPR common lane rate/count and the
  per LTTPR-PHY vswing/pre-emph limits.
- Switch to LTTPR non-transparent LT mode and train each link segment
  according to the sequence in DP Standard v2.0 (complete CR/EQ for
  each segment before continuing with the next segment).

v2:
- Switch to non-transparent mode during connector detection, which is
  required before reading the per-PHY LTTPR capabilities.
- Move the DP_PHY_LTTPR() macro to drm_dp_helper.h (Ville)
- Use the new drm_dp_dpcd_read_phy_link_status() instead of adding the
  same logic to intel_dp_get_link_status(). (Ville)
- Make intel_dp_lttpr_phy_caps() return a pointer to the whole array
  instead of a pointer to its first element. (Ville)
- Add the intel_dp_phy_is_downstream_of_source() helper. (Ville)
- Add a code comment about the disable->enable quirk of
  non-transparent mode.
- Add the intel_dp_training_pattern_set_reg() helper.
- Fix checkpatch/sparse warns.

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 .../drm/i915/display/intel_display_types.h    |   1 +
 drivers/gpu/drm/i915/display/intel_dp.c       |  27 +-
 drivers/gpu/drm/i915/display/intel_dp.h       |   2 -
 .../drm/i915/display/intel_dp_link_training.c | 358 +++++++++++++++---
 .../drm/i915/display/intel_dp_link_training.h |   5 +-
 5 files changed, 315 insertions(+), 78 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index b04921eba73b..2fb4e9a6a316 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1281,6 +1281,7 @@ struct intel_dp {
 	u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE];
 	u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE];
 	u8 lttpr_common_caps[DP_LTTPR_COMMON_CAP_SIZE];
+	u8 lttpr_phy_caps[DP_MAX_LTTPR_COUNT][DP_LTTPR_PHY_CAP_SIZE];
 	u8 fec_capable;
 	/* source rates */
 	int num_source_rates;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 64bf4aa384d3..bbf5a02ef0c1 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -161,6 +161,7 @@ static void intel_dp_set_sink_rates(struct intel_dp *intel_dp)
 		162000, 270000, 540000, 810000
 	};
 	int i, max_rate;
+	int max_lttpr_rate;
 
 	if (drm_dp_has_quirk(&intel_dp->desc, 0,
 			     DP_DPCD_QUIRK_CAN_DO_MAX_LINK_RATE_3_24_GBPS)) {
@@ -174,6 +175,9 @@ static void intel_dp_set_sink_rates(struct intel_dp *intel_dp)
 	}
 
 	max_rate = drm_dp_bw_code_to_link_rate(intel_dp->dpcd[DP_MAX_LINK_RATE]);
+	max_lttpr_rate = drm_dp_lttpr_max_link_rate(intel_dp->lttpr_common_caps);
+	if (max_lttpr_rate)
+		max_rate = min(max_rate, max_lttpr_rate);
 
 	for (i = 0; i < ARRAY_SIZE(dp_rates); i++) {
 		if (dp_rates[i] > max_rate)
@@ -219,6 +223,10 @@ static int intel_dp_max_common_lane_count(struct intel_dp *intel_dp)
 	int source_max = dig_port->max_lanes;
 	int sink_max = drm_dp_max_lane_count(intel_dp->dpcd);
 	int fia_max = intel_tc_port_fia_max_lane_count(dig_port);
+	int lttpr_max = drm_dp_lttpr_max_lane_count(intel_dp->lttpr_common_caps);
+
+	if (lttpr_max)
+		sink_max = min(sink_max, lttpr_max);
 
 	return min3(source_max, sink_max, fia_max);
 }
@@ -4126,17 +4134,6 @@ static void chv_dp_post_pll_disable(struct intel_atomic_state *state,
 	chv_phy_post_pll_disable(encoder, old_crtc_state);
 }
 
-/*
- * Fetch AUX CH registers 0x202 - 0x207 which contain
- * link status information
- */
-bool
-intel_dp_get_link_status(struct intel_dp *intel_dp, u8 link_status[DP_LINK_STATUS_SIZE])
-{
-	return drm_dp_dpcd_read(&intel_dp->aux, DP_LANE0_1_STATUS, link_status,
-				DP_LINK_STATUS_SIZE) == DP_LINK_STATUS_SIZE;
-}
-
 static u8 intel_dp_voltage_max_2(struct intel_dp *intel_dp)
 {
 	return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
@@ -5545,13 +5542,14 @@ void intel_dp_process_phy_request(struct intel_dp *intel_dp)
 		&intel_dp->compliance.test_data.phytest;
 	u8 link_status[DP_LINK_STATUS_SIZE];
 
-	if (!intel_dp_get_link_status(intel_dp, link_status)) {
+	if (drm_dp_dpcd_read_phy_link_status(&intel_dp->aux, DP_PHY_DPRX,
+					     link_status) < 0) {
 		DRM_DEBUG_KMS("failed to get link status\n");
 		return;
 	}
 
 	/* retrieve vswing & pre-emphasis setting */
-	intel_dp_get_adjust_train(intel_dp, link_status);
+	intel_dp_get_adjust_train(intel_dp, DP_PHY_DPRX, link_status);
 
 	intel_dp_autotest_phy_ddi_disable(intel_dp);
 
@@ -5706,7 +5704,8 @@ intel_dp_needs_link_retrain(struct intel_dp *intel_dp)
 	if (intel_psr_enabled(intel_dp))
 		return false;
 
-	if (!intel_dp_get_link_status(intel_dp, link_status))
+	if (drm_dp_dpcd_read_phy_link_status(&intel_dp->aux, DP_PHY_DPRX,
+					     link_status) < 0)
 		return false;
 
 	/*
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index ca8319d6c63c..1832424cd057 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -99,8 +99,6 @@ void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
 			   u8 *link_bw, u8 *rate_select);
 bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp);
 bool intel_dp_source_supports_hbr3(struct intel_dp *intel_dp);
-bool
-intel_dp_get_link_status(struct intel_dp *intel_dp, u8 *link_status);
 
 bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp);
 int intel_dp_link_required(int pixel_clock, int bpp);
diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
index 4f8f42cc25fa..af0581e5fc38 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
@@ -34,6 +34,63 @@ intel_dp_dump_link_status(const u8 link_status[DP_LINK_STATUS_SIZE])
 		      link_status[3], link_status[4], link_status[5]);
 }
 
+static int intel_dp_lttpr_count(struct intel_dp *intel_dp)
+{
+	int count = drm_dp_lttpr_count(intel_dp->lttpr_common_caps);
+
+	/*
+	 * Pretend no LTTPRs in case of LTTPR detection error, or
+	 * if too many (>8) LTTPRs are detected. This translates to link
+	 * training in transparent mode.
+	 */
+	return count <= 0 ? 0 : count;
+}
+
+static void intel_dp_reset_lttpr_count(struct intel_dp *intel_dp)
+{
+	intel_dp->lttpr_common_caps[DP_PHY_REPEATER_CNT -
+				    DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV] = 0;
+}
+
+static const char *intel_dp_phy_name(enum drm_dp_phy dp_phy,
+				     char *buf, size_t buf_size)
+{
+	if (dp_phy == DP_PHY_DPRX)
+		snprintf(buf, buf_size, "DPRX");
+	else
+		snprintf(buf, buf_size, "LTTPR %d", dp_phy - DP_PHY_LTTPR1 + 1);
+
+	return buf;
+}
+
+static u8 *intel_dp_lttpr_phy_caps(struct intel_dp *intel_dp,
+				   enum drm_dp_phy dp_phy)
+{
+	return intel_dp->lttpr_phy_caps[dp_phy - DP_PHY_LTTPR1];
+}
+
+static void intel_dp_read_lttpr_phy_caps(struct intel_dp *intel_dp,
+					 enum drm_dp_phy dp_phy)
+{
+	u8 *phy_caps = intel_dp_lttpr_phy_caps(intel_dp, dp_phy);
+	char phy_name[10];
+
+	intel_dp_phy_name(dp_phy, phy_name, sizeof(phy_name));
+
+	if (drm_dp_read_lttpr_phy_caps(&intel_dp->aux, dp_phy, phy_caps) < 0) {
+		drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
+			    "failed to read the PHY caps for %s\n",
+			    phy_name);
+		return;
+	}
+
+	drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
+		    "%s PHY capabilities: %*ph\n",
+		    phy_name,
+		    (int)sizeof(intel_dp->lttpr_phy_caps[0]),
+		    phy_caps);
+}
+
 static bool intel_dp_read_lttpr_common_caps(struct intel_dp *intel_dp)
 {
 	if (drm_dp_read_lttpr_common_caps(&intel_dp->aux,
@@ -64,21 +121,61 @@ intel_dp_set_lttpr_transparent_mode(struct intel_dp *intel_dp, bool enable)
  * intel_dp_lttpr_init - detect LTTPRs and init the LTTPR link training mode
  * @intel_dp: Intel DP struct
  *
- * Read the LTTPR common capabilities and switch to transparent link training
- * mode.
+ * Read the LTTPR common capabilities, switch to non-transparent link training
+ * mode if any is detected and read the PHY capabilities for all detected
+ * LTTPRs. In case of an LTTPR detection error or if the number of
+ * LTTPRs is more than is supported (8), fall back to the no-LTTPR,
+ * transparent mode link training mode.
+ *
+ * Returns:
+ *   >0  if LTTPRs were detected and the non-transparent LT mode was set
+ *    0  if no LTTPRs or more than 8 LTTPRs were detected or in case of a
+ *       detection failure and the transparent LT mode was set
  */
 int intel_dp_lttpr_init(struct intel_dp *intel_dp)
 {
-	intel_dp_read_lttpr_common_caps(intel_dp);
+	int lttpr_count;
+	bool ret;
+	int i;
+
+	ret = intel_dp_read_lttpr_common_caps(intel_dp);
 
 	/*
 	 * See DP Standard v2.0 3.6.6.1. about the explicit disabling of
-	 * non-transparent mode.
+	 * non-transparent mode and the disable->enable non-transparent mode
+	 * sequence.
 	 */
 	intel_dp_set_lttpr_transparent_mode(intel_dp, true);
 
-	return 0;
+	if (!ret)
+		return 0;
+
+	lttpr_count = intel_dp_lttpr_count(intel_dp);
+
+	/*
+	 * In case of unsupported number of LTTPRs or failing to switch to
+	 * non-transparent mode fall-back to transparent link training mode,
+	 * still taking into account any LTTPR common lane- rate/count limits.
+	 */
+	if (lttpr_count == 0)
+		return 0;
+
+	if (!intel_dp_set_lttpr_transparent_mode(intel_dp, false)) {
+		drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
+			    "Switching to LTTPR non-transparent LT mode failed, fall-back to transparent mode\n");
+
+		intel_dp_set_lttpr_transparent_mode(intel_dp, true);
+		intel_dp_reset_lttpr_count(intel_dp);
+
+		return 0;
+	}
+
+	for (i = 0; i < lttpr_count; i++)
+		intel_dp_read_lttpr_phy_caps(intel_dp, DP_PHY_LTTPR(i));
+
+	return lttpr_count;
 }
+EXPORT_SYMBOL(intel_dp_lttpr_init);
 
 static u8 dp_voltage_max(u8 preemph)
 {
@@ -95,10 +192,88 @@ static u8 dp_voltage_max(u8 preemph)
 	}
 }
 
+static u8 intel_dp_lttpr_voltage_max(struct intel_dp *intel_dp,
+				     enum drm_dp_phy dp_phy)
+{
+	const u8 *phy_caps = intel_dp_lttpr_phy_caps(intel_dp, dp_phy);
+
+	if (drm_dp_lttpr_voltage_swing_level_3_supported(phy_caps))
+		return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
+	else
+		return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
+}
+
+static u8 intel_dp_lttpr_preemph_max(struct intel_dp *intel_dp,
+				     enum drm_dp_phy dp_phy)
+{
+	const u8 *phy_caps = intel_dp_lttpr_phy_caps(intel_dp, dp_phy);
+
+	if (drm_dp_lttpr_pre_emphasis_level_3_supported(phy_caps))
+		return DP_TRAIN_PRE_EMPH_LEVEL_3;
+	else
+		return DP_TRAIN_PRE_EMPH_LEVEL_2;
+}
+
+static bool
+intel_dp_phy_is_downstream_of_source(struct intel_dp *intel_dp,
+				     enum drm_dp_phy dp_phy)
+{
+	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+	int lttpr_count = intel_dp_lttpr_count(intel_dp);
+
+	drm_WARN_ON_ONCE(&i915->drm, lttpr_count == 0 && dp_phy != DP_PHY_DPRX);
+
+	return lttpr_count == 0 || dp_phy == DP_PHY_LTTPR(lttpr_count - 1);
+}
+
+static u8 intel_dp_phy_voltage_max(struct intel_dp *intel_dp,
+				   enum drm_dp_phy dp_phy)
+{
+	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+	u8 voltage_max;
+
+	/*
+	 * Get voltage_max from the DPTX_PHY (source or LTTPR) upstream from
+	 * the DPRX_PHY we train.
+	 */
+	if (intel_dp_phy_is_downstream_of_source(intel_dp, dp_phy))
+		voltage_max = intel_dp->voltage_max(intel_dp);
+	else
+		voltage_max = intel_dp_lttpr_voltage_max(intel_dp, dp_phy + 1);
+
+	drm_WARN_ON_ONCE(&i915->drm,
+			 voltage_max != DP_TRAIN_VOLTAGE_SWING_LEVEL_2 &&
+			 voltage_max != DP_TRAIN_VOLTAGE_SWING_LEVEL_3);
+
+	return voltage_max;
+}
+
+static u8 intel_dp_phy_preemph_max(struct intel_dp *intel_dp,
+				   enum drm_dp_phy dp_phy)
+{
+	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+	u8 preemph_max;
+
+	/*
+	 * Get preemph_max from the DPTX_PHY (source or LTTPR) upstream from
+	 * the DPRX_PHY we train.
+	 */
+	if (intel_dp_phy_is_downstream_of_source(intel_dp, dp_phy))
+		preemph_max = intel_dp->preemph_max(intel_dp);
+	else
+		preemph_max = intel_dp_lttpr_preemph_max(intel_dp, dp_phy + 1);
+
+	drm_WARN_ON_ONCE(&i915->drm,
+			 preemph_max != DP_TRAIN_PRE_EMPH_LEVEL_2 &&
+			 preemph_max != DP_TRAIN_PRE_EMPH_LEVEL_3);
+
+	return preemph_max;
+}
+
 void intel_dp_get_adjust_train(struct intel_dp *intel_dp,
+			       enum drm_dp_phy dp_phy,
 			       const u8 link_status[DP_LINK_STATUS_SIZE])
 {
-	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
 	u8 v = 0;
 	u8 p = 0;
 	int lane;
@@ -110,21 +285,13 @@ void intel_dp_get_adjust_train(struct intel_dp *intel_dp,
 		p = max(p, drm_dp_get_adjust_request_pre_emphasis(link_status, lane));
 	}
 
-	preemph_max = intel_dp->preemph_max(intel_dp);
-	drm_WARN_ON_ONCE(&i915->drm,
-			 preemph_max != DP_TRAIN_PRE_EMPH_LEVEL_2 &&
-			 preemph_max != DP_TRAIN_PRE_EMPH_LEVEL_3);
-
+	preemph_max = intel_dp_phy_preemph_max(intel_dp, dp_phy);
 	if (p >= preemph_max)
 		p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
 
 	v = min(v, dp_voltage_max(p));
 
-	voltage_max = intel_dp->voltage_max(intel_dp);
-	drm_WARN_ON_ONCE(&i915->drm,
-			 voltage_max != DP_TRAIN_VOLTAGE_SWING_LEVEL_2 &&
-			 voltage_max != DP_TRAIN_VOLTAGE_SWING_LEVEL_3);
-
+	voltage_max = intel_dp_phy_voltage_max(intel_dp, dp_phy);
 	if (v >= voltage_max)
 		v = voltage_max | DP_TRAIN_MAX_SWING_REACHED;
 
@@ -132,10 +299,19 @@ void intel_dp_get_adjust_train(struct intel_dp *intel_dp,
 		intel_dp->train_set[lane] = v | p;
 }
 
+static int intel_dp_training_pattern_set_reg(struct intel_dp *intel_dp,
+					     enum drm_dp_phy dp_phy)
+{
+	return dp_phy == DP_PHY_DPRX ?
+		DP_TRAINING_PATTERN_SET :
+		DP_TRAINING_PATTERN_SET_PHY_REPEATER(dp_phy);
+}
+
 static bool
-intel_dp_set_link_train(struct intel_dp *intel_dp,
+intel_dp_set_link_train(struct intel_dp *intel_dp, enum drm_dp_phy dp_phy,
 			u8 dp_train_pat)
 {
+	int reg = intel_dp_training_pattern_set_reg(intel_dp, dp_phy);
 	u8 buf[sizeof(intel_dp->train_set) + 1];
 	int len;
 
@@ -146,27 +322,29 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
 	memcpy(buf + 1, intel_dp->train_set, intel_dp->lane_count);
 	len = intel_dp->lane_count + 1;
 
-	return drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_PATTERN_SET,
-				 buf, len) == len;
+	return drm_dp_dpcd_write(&intel_dp->aux, reg, buf, len) == len;
 }
 
 static bool
-intel_dp_reset_link_train(struct intel_dp *intel_dp,
-			u8 dp_train_pat)
+intel_dp_reset_link_train(struct intel_dp *intel_dp, enum drm_dp_phy dp_phy,
+			  u8 dp_train_pat)
 {
 	memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set));
 	intel_dp_set_signal_levels(intel_dp);
-	return intel_dp_set_link_train(intel_dp, dp_train_pat);
+	return intel_dp_set_link_train(intel_dp, dp_phy, dp_train_pat);
 }
 
 static bool
-intel_dp_update_link_train(struct intel_dp *intel_dp)
+intel_dp_update_link_train(struct intel_dp *intel_dp, enum drm_dp_phy dp_phy)
 {
+	int reg = dp_phy == DP_PHY_DPRX ?
+			    DP_TRAINING_LANE0_SET :
+			    DP_TRAINING_LANE0_SET_PHY_REPEATER(dp_phy);
 	int ret;
 
 	intel_dp_set_signal_levels(intel_dp);
 
-	ret = drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_LANE0_SET,
+	ret = drm_dp_dpcd_write(&intel_dp->aux, reg,
 				intel_dp->train_set, intel_dp->lane_count);
 
 	return ret == intel_dp->lane_count;
@@ -226,9 +404,22 @@ static void intel_dp_prepare_link_train(struct intel_dp *intel_dp)
 	intel_dp->DP |= DP_PORT_EN;
 }
 
-/* Perform the link training clock recovery phase using training pattern 1. */
+static void intel_dp_link_training_clock_recovery_delay(struct intel_dp *intel_dp,
+							enum drm_dp_phy dp_phy)
+{
+	if (dp_phy == DP_PHY_DPRX)
+		drm_dp_link_train_clock_recovery_delay(intel_dp->dpcd);
+	else
+		drm_dp_lttpr_link_train_clock_recovery_delay();
+}
+
+/*
+ * Perform the link training clock recovery phase on the given DP PHY using
+ * training pattern 1.
+ */
 static bool
-intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
+intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp,
+				      enum drm_dp_phy dp_phy)
 {
 	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
 	u8 voltage;
@@ -236,7 +427,7 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
 	bool max_vswing_reached = false;
 
 	/* clock recovery */
-	if (!intel_dp_reset_link_train(intel_dp,
+	if (!intel_dp_reset_link_train(intel_dp, dp_phy,
 				       DP_TRAINING_PATTERN_1 |
 				       DP_LINK_SCRAMBLING_DISABLE)) {
 		drm_err(&i915->drm, "failed to enable link training\n");
@@ -260,9 +451,10 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
 	for (cr_tries = 0; cr_tries < max_cr_tries; ++cr_tries) {
 		u8 link_status[DP_LINK_STATUS_SIZE];
 
-		drm_dp_link_train_clock_recovery_delay(intel_dp->dpcd);
+		intel_dp_link_training_clock_recovery_delay(intel_dp, dp_phy);
 
-		if (!intel_dp_get_link_status(intel_dp, link_status)) {
+		if (drm_dp_dpcd_read_phy_link_status(&intel_dp->aux, dp_phy,
+						     link_status) < 0) {
 			drm_err(&i915->drm, "failed to get link status\n");
 			return false;
 		}
@@ -286,8 +478,8 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
 		voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
 
 		/* Update training set as requested by target */
-		intel_dp_get_adjust_train(intel_dp, link_status);
-		if (!intel_dp_update_link_train(intel_dp)) {
+		intel_dp_get_adjust_train(intel_dp, dp_phy, link_status);
+		if (!intel_dp_update_link_train(intel_dp, dp_phy)) {
 			drm_err(&i915->drm,
 				"failed to update link training\n");
 			return false;
@@ -313,7 +505,8 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
  * or for 1.4 devices that support it, training Pattern 3 for HBR2
  * or 1.2 devices that support it, Training Pattern 2 otherwise.
  */
-static u32 intel_dp_training_pattern(struct intel_dp *intel_dp)
+static u32 intel_dp_training_pattern(struct intel_dp *intel_dp,
+				     enum drm_dp_phy dp_phy)
 {
 	bool source_tps3, sink_tps3, source_tps4, sink_tps4;
 
@@ -322,9 +515,11 @@ static u32 intel_dp_training_pattern(struct intel_dp *intel_dp)
 	 * for all downstream devices that support HBR3. There are no known eDP
 	 * panels that support TPS4 as of Feb 2018 as per VESA eDP_v1.4b_E1
 	 * specification.
+	 * LTTPRs must support TPS4.
 	 */
 	source_tps4 = intel_dp_source_supports_hbr3(intel_dp);
-	sink_tps4 = drm_dp_tps4_supported(intel_dp->dpcd);
+	sink_tps4 = dp_phy != DP_PHY_DPRX ||
+		    drm_dp_tps4_supported(intel_dp->dpcd);
 	if (source_tps4 && sink_tps4) {
 		return DP_TRAINING_PATTERN_4;
 	} else if (intel_dp->link_rate == 810000) {
@@ -341,7 +536,8 @@ static u32 intel_dp_training_pattern(struct intel_dp *intel_dp)
 	 * all sinks follow the spec.
 	 */
 	source_tps3 = intel_dp_source_supports_hbr2(intel_dp);
-	sink_tps3 = drm_dp_tps3_supported(intel_dp->dpcd);
+	sink_tps3 = dp_phy != DP_PHY_DPRX ||
+		    drm_dp_tps3_supported(intel_dp->dpcd);
 	if (source_tps3 && sink_tps3) {
 		return  DP_TRAINING_PATTERN_3;
 	} else if (intel_dp->link_rate >= 540000) {
@@ -356,12 +552,27 @@ static u32 intel_dp_training_pattern(struct intel_dp *intel_dp)
 	return DP_TRAINING_PATTERN_2;
 }
 
+static void
+intel_dp_link_training_channel_equalization_delay(struct intel_dp *intel_dp,
+						  enum drm_dp_phy dp_phy)
+{
+	if (dp_phy == DP_PHY_DPRX) {
+		drm_dp_link_train_channel_eq_delay(intel_dp->dpcd);
+	} else {
+		const u8 *phy_caps = intel_dp_lttpr_phy_caps(intel_dp, dp_phy);
+
+		drm_dp_lttpr_link_train_channel_eq_delay(phy_caps);
+	}
+}
+
 /*
- * Perform the link training channel equalization phase using one of training
- * pattern 2, 3 or 4 depending on the source and sink capabilities.
+ * Perform the link training channel equalization phase on the given DP PHY
+ * using one of training pattern 2, 3 or 4 depending on the source and
+ * sink capabilities.
  */
 static bool
-intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
+intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp,
+					    enum drm_dp_phy dp_phy)
 {
 	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
 	int tries;
@@ -369,22 +580,22 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
 	u8 link_status[DP_LINK_STATUS_SIZE];
 	bool channel_eq = false;
 
-	training_pattern = intel_dp_training_pattern(intel_dp);
+	training_pattern = intel_dp_training_pattern(intel_dp, dp_phy);
 	/* Scrambling is disabled for TPS2/3 and enabled for TPS4 */
 	if (training_pattern != DP_TRAINING_PATTERN_4)
 		training_pattern |= DP_LINK_SCRAMBLING_DISABLE;
 
 	/* channel equalization */
-	if (!intel_dp_set_link_train(intel_dp,
-				     training_pattern)) {
+	if (!intel_dp_set_link_train(intel_dp, dp_phy, training_pattern)) {
 		drm_err(&i915->drm, "failed to start channel equalization\n");
 		return false;
 	}
 
 	for (tries = 0; tries < 5; tries++) {
-
-		drm_dp_link_train_channel_eq_delay(intel_dp->dpcd);
-		if (!intel_dp_get_link_status(intel_dp, link_status)) {
+		intel_dp_link_training_channel_equalization_delay(intel_dp,
+								  dp_phy);
+		if (drm_dp_dpcd_read_phy_link_status(&intel_dp->aux, dp_phy,
+						     link_status) < 0) {
 			drm_err(&i915->drm,
 				"failed to get link status\n");
 			break;
@@ -409,8 +620,8 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
 		}
 
 		/* Update training set as requested by target */
-		intel_dp_get_adjust_train(intel_dp, link_status);
-		if (!intel_dp_update_link_train(intel_dp)) {
+		intel_dp_get_adjust_train(intel_dp, dp_phy, link_status);
+		if (!intel_dp_update_link_train(intel_dp, dp_phy)) {
 			drm_err(&i915->drm,
 				"failed to update link training\n");
 			break;
@@ -424,17 +635,16 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
 			    "Channel equalization failed 5 times\n");
 	}
 
-	if (intel_dp->set_idle_link_train)
-		intel_dp->set_idle_link_train(intel_dp);
-
 	return channel_eq;
 }
 
-static bool intel_dp_disable_dpcd_training_pattern(struct intel_dp *intel_dp)
+static bool intel_dp_disable_dpcd_training_pattern(struct intel_dp *intel_dp,
+						   enum drm_dp_phy dp_phy)
 {
+	int reg = intel_dp_training_pattern_set_reg(intel_dp, dp_phy);
 	u8 val = DP_TRAINING_PATTERN_DISABLE;
 
-	return drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_PATTERN_SET, &val, 1) == 1;
+	return drm_dp_dpcd_write(&intel_dp->aux, reg, &val, 1) == 1;
 }
 
 /**
@@ -458,32 +668,32 @@ void intel_dp_stop_link_train(struct intel_dp *intel_dp)
 
 	intel_dp_program_link_training_pattern(intel_dp,
 					       DP_TRAINING_PATTERN_DISABLE);
-	intel_dp_disable_dpcd_training_pattern(intel_dp);
+	intel_dp_disable_dpcd_training_pattern(intel_dp, DP_PHY_DPRX);
 }
 
 static bool
-intel_dp_link_train(struct intel_dp *intel_dp)
+intel_dp_link_train_phy(struct intel_dp *intel_dp, enum drm_dp_phy dp_phy)
 {
 	struct intel_connector *intel_connector = intel_dp->attached_connector;
+	char phy_name[10];
 	bool ret = false;
 
-	intel_dp_prepare_link_train(intel_dp);
-
-	if (!intel_dp_link_training_clock_recovery(intel_dp))
+	if (!intel_dp_link_training_clock_recovery(intel_dp, dp_phy))
 		goto out;
 
-	if (!intel_dp_link_training_channel_equalization(intel_dp))
+	if (!intel_dp_link_training_channel_equalization(intel_dp, dp_phy))
 		goto out;
 
 	ret = true;
 
 out:
 	drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
-		    "[CONNECTOR:%d:%s] Link Training %s at Link Rate = %d, Lane count = %d",
+		    "[CONNECTOR:%d:%s] Link Training %s at Link Rate = %d, Lane count = %d, at %s",
 		    intel_connector->base.base.id,
 		    intel_connector->base.name,
 		    ret ? "passed" : "failed",
-		    intel_dp->link_rate, intel_dp->lane_count);
+		    intel_dp->link_rate, intel_dp->lane_count,
+		    intel_dp_phy_name(dp_phy, phy_name, sizeof(phy_name)));
 
 	return ret;
 }
@@ -506,6 +716,34 @@ static void intel_dp_schedule_fallback_link_training(struct intel_dp *intel_dp)
 	schedule_work(&intel_connector->modeset_retry_work);
 }
 
+/* Perform the link training on all LTTPRs and the DPRX on a link. */
+static bool
+intel_dp_link_train_all_phys(struct intel_dp *intel_dp, int lttpr_count)
+{
+	bool ret = true;
+	int i;
+
+	intel_dp_prepare_link_train(intel_dp);
+
+	for (i = lttpr_count - 1; i >= 0; i--) {
+		enum drm_dp_phy dp_phy = DP_PHY_LTTPR(i);
+
+		ret = intel_dp_link_train_phy(intel_dp, dp_phy);
+		intel_dp_disable_dpcd_training_pattern(intel_dp, dp_phy);
+
+		if (!ret)
+			break;
+	}
+
+	if (ret)
+		intel_dp_link_train_phy(intel_dp, DP_PHY_DPRX);
+
+	if (intel_dp->set_idle_link_train)
+		intel_dp->set_idle_link_train(intel_dp);
+
+	return ret;
+}
+
 /**
  * intel_dp_start_link_train - start link training
  * @intel_dp: DP struct
@@ -521,8 +759,8 @@ void intel_dp_start_link_train(struct intel_dp *intel_dp)
 	 * TODO: Reiniting LTTPRs here won't be needed once proper connector
 	 * HW state readout is added.
 	 */
-	intel_dp_lttpr_init(intel_dp);
+	int lttpr_count = intel_dp_lttpr_init(intel_dp);
 
-	if (!intel_dp_link_train(intel_dp))
+	if (!intel_dp_link_train_all_phys(intel_dp, lttpr_count))
 		intel_dp_schedule_fallback_link_training(intel_dp);
 }
diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.h b/drivers/gpu/drm/i915/display/intel_dp_link_training.h
index 3536ce73a123..26f0e46c26cf 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.h
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.h
@@ -12,8 +12,9 @@ struct intel_dp;
 
 int intel_dp_lttpr_init(struct intel_dp *intel_dp);
 
-void intel_dp_get_adjust_train(struct intel_dp *intel_dp,
-			       const u8 link_status[DP_LINK_STATUS_SIZE]);
+void
+intel_dp_get_adjust_train(struct intel_dp *intel_dp, enum drm_dp_phy dp_phy,
+			  const u8 link_status[DP_LINK_STATUS_SIZE]);
 void intel_dp_start_link_train(struct intel_dp *intel_dp);
 void intel_dp_stop_link_train(struct intel_dp *intel_dp);
 
-- 
2.25.1

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

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

* Re: [Intel-gfx] [PATCH v2 3/6] drm/i915: Factor out a helper to disable the DPCD training pattern
  2020-09-24 18:48 ` [Intel-gfx] [PATCH v2 3/6] drm/i915: Factor out a helper to disable the DPCD training pattern Imre Deak
@ 2020-09-24 18:57   ` Ville Syrjälä
  0 siblings, 0 replies; 19+ messages in thread
From: Ville Syrjälä @ 2020-09-24 18:57 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Thu, Sep 24, 2020 at 09:48:02PM +0300, Imre Deak wrote:
> To prepare for a follow-up LTTPR change factor out a helper to disable
> the training pattern in DPCD. We'll need to do this for each LTTPR
> (without programming the port to output the idle pattern) when training
> in LTTPR non-transparent mode.
> 
> While at it also move the disable-link-training logic from
> intel_dp_set_link_train() to intel_dp_stop_link_train(), since the
> latter is the only user of this.
> 
> v2:
> - Move the disable-link-training logic to intel_dp_stop_link_train()
>   (Ville)
> 
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  .../drm/i915/display/intel_dp_link_training.c | 32 +++++++++----------
>  1 file changed, 16 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
> index 78b0f165fadd..38d4553670a1 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
> @@ -91,25 +91,17 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
>  			u8 dp_train_pat)
>  {
>  	u8 buf[sizeof(intel_dp->train_set) + 1];
> -	int ret, len;
> +	int len;
>  
>  	intel_dp_program_link_training_pattern(intel_dp, dp_train_pat);
>  
>  	buf[0] = dp_train_pat;
> -	if (intel_dp_training_pattern_symbol(dp_train_pat) ==
> -	    DP_TRAINING_PATTERN_DISABLE) {
> -		/* don't write DP_TRAINING_LANEx_SET on disable */
> -		len = 1;
> -	} else {
> -		/* DP_TRAINING_LANEx_SET follow DP_TRAINING_PATTERN_SET */
> -		memcpy(buf + 1, intel_dp->train_set, intel_dp->lane_count);
> -		len = intel_dp->lane_count + 1;
> -	}
> +	/* DP_TRAINING_LANEx_SET follow DP_TRAINING_PATTERN_SET */
> +	memcpy(buf + 1, intel_dp->train_set, intel_dp->lane_count);
> +	len = intel_dp->lane_count + 1;
>  
> -	ret = drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_PATTERN_SET,
> -				buf, len);
> -
> -	return ret == len;
> +	return drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_PATTERN_SET,
> +				 buf, len) == len;

Much nicer without the silly if() cluttering things.

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

>  }
>  
>  static bool
> @@ -392,6 +384,13 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
>  	return channel_eq;
>  }
>  
> +static bool intel_dp_disable_dpcd_training_pattern(struct intel_dp *intel_dp)
> +{
> +	u8 val = DP_TRAINING_PATTERN_DISABLE;
> +
> +	return drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_PATTERN_SET, &val, 1) == 1;
> +}
> +
>  /**
>   * intel_dp_stop_link_train - stop link training
>   * @intel_dp: DP struct
> @@ -411,8 +410,9 @@ void intel_dp_stop_link_train(struct intel_dp *intel_dp)
>  {
>  	intel_dp->link_trained = true;
>  
> -	intel_dp_set_link_train(intel_dp,
> -				DP_TRAINING_PATTERN_DISABLE);
> +	intel_dp_program_link_training_pattern(intel_dp,
> +					       DP_TRAINING_PATTERN_DISABLE);
> +	intel_dp_disable_dpcd_training_pattern(intel_dp);
>  }
>  
>  static bool
> -- 
> 2.25.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] 19+ messages in thread

* [Intel-gfx] ✗ Fi.CI.SPARSE: warning for drm/i915: Add support for LTTPR non-transparent link training mode (rev2)
  2020-09-24 18:47 ` [Intel-gfx] " Imre Deak
                   ` (6 preceding siblings ...)
  (?)
@ 2020-09-24 22:01 ` Patchwork
  -1 siblings, 0 replies; 19+ messages in thread
From: Patchwork @ 2020-09-24 22:01 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Add support for LTTPR non-transparent link training mode (rev2)
URL   : https://patchwork.freedesktop.org/series/81968/
State : warning

== Summary ==

$ dim sparse --fast origin/drm-tip
Sparse version: v0.6.2
Fast mode used, each commit won't be checked separately.
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:1019:47:    expected unsigned int [addressable] [usertype] ulClockParams
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:1019:47:    got restricted __le32 [usertype]
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:1019:47: warning: incorrect type in assignment (different base types)
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:1028:50: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:1029:49: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:1037:47: warning: too many warnings
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:184:44: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:283:14: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:320:14: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:323:14: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:326:14: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:329:18: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:330:26: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:338:30: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:340:38: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:342:30: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:346:30: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:348:30: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:353:33: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:367:43: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:369:38: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:374:67: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:375:53: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:378:66: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:389:80: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:395:57: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:402:69: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:403:53: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:406:66: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:414:66: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:423:69: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:424:69: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:473:30: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:476:45: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:477:45: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:484:54: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:52:28: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:531:35: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:53:29: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:533:25: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:54:26: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:55:27: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:56:25: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:57:26: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:577:21: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:581:25: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:58:25: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:583:21: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:586:25: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:590:25: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:59:26: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:598:21: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:600:21: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:617:25: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:621:21: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:623:21: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:630:21: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:632:21: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:644:25: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:648:21: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:650:21: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:657:21: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:659:21: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:662:21: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:664:21: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:676:25: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:688:25: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:691:47: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:697:25: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:796:46: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:797:40: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:800:46: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:801:40: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:804:46: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:805:40: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:812:46: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:813:40: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:816:46: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:817:40: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:820:46: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:821:40: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:828:46: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:829:40: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:832:46: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:833:40: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:836:46: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:837:40: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:844:46: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:845:40: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:848:46: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:849:40: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:852:46: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:853:40: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:916:47: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:918:49: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:920:52: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:934:47: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:936:49: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:938:52: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:956:47: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:958:49: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:960:52: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:328:34: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:365:34: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:395:25: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:397:25: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:404:25: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:418:40: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:441:40: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:44:21: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:482:53: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:486:33: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:489:61: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:490:64: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:492:54: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:518:17: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:521:21: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:64:25: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:80:17: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:80:17: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:80:17: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:85:30: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:86:24: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:98:39: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:222:29: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:226:37: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:226:37: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:226:37: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:227:37: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:233:43: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:236:44: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:239:51: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:458:41: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:458:41: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:458:41: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:464:39: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:465:30: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:466:39: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:468:24: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:140:26:    expected unsigned long long [usertype] *chunk_array_user
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:140:26:    got void [noderef] __user *
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:140:26: warning: incorrect type in assignment (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:141:41:    expected void const [noderef] __user *from
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:141:41:    got unsigned long long [usertype] *chunk_array_user
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:141:41: warning: incorrect type in argument 2 (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:160:27:    expected struct drm_amdgpu_cs_chunk [noderef] __user **chunk_ptr
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:160:27:    got void [noderef] __user *
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:160:27: warning: incorrect type in assignment (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:161:49:    expected void const [noderef] __user *from
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:161:49:    got struct drm_amdgpu_cs_chunk [noderef] __user **chunk_ptr
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:161:49: warning: incorrect type in argument 2 (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:1624:21:    expected struct drm_amdgpu_fence *fences_user
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:1624:21:    got void [noderef] __user *
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:1624:21: warning: incorrect type in assignment (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:1625:36:    expected void const [noderef] __user *from
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:1625:36:    got struct drm_amdgpu_fence *fences_user
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:1625:36: warning: incorrect type in argument 2 (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:1364:25: error: incompatible types in comparison expression (different address spaces):
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:1364:25:    struct dma_fence *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:1364:25:    struct dma_fence [noderef] __rcu *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:1365:17: error: incompatible types in comparison expression (different address spaces):
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:1365:17:    struct dma_fence *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:1365:17:    struct dma_fence [noderef] __rcu *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:1424:17: error: incompatible types in comparison expression (different address spaces):
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:1424:17:    struct dma_fence *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:1424:17:    struct dma_fence [noderef] __rcu *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:143:17:    expected restricted __poll_t ( *poll )( ... )
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:143:17:    got unsigned int ( * )( ... )
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:143:17: warning: incorrect type in initializer (different base types)
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:266:29:    expected void const volatile [noderef] __user *ptr
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:266:29:    got unsigned int [usertype] *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:266:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:266:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:266:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:266:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:266:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:266:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:266:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:266:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:266:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:266:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:266:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:266:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:266:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:266:29: warning: incorrect type in argument 1 (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:268:29:    expected void const volatile [noderef] __user *ptr
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:268:29:    got unsigned int [usertype] *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:268:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:268:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:268:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:268:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:268:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:268:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:268:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:268:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:268:29: warning: incorrect type in argument 1 (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:359:21:    expected void const volatile [noderef] __user *ptr
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:359:21:    got unsigned int [usertype] *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:359:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:359:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:359:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:359:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:359:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:359:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:359:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:359:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:359:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:359:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:359:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:359:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:359:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:359:21: warning: incorrect type in argument 1 (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:417:21:    expected void const volatile [noderef] __user *ptr
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:417:21:    got unsigned int [usertype] *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:417:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:417:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:417:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:417:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:417:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:417:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:417:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:417:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:417:21: warning: incorrect type in argument 1 (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:478:21:    expected void const volatile [noderef] __user *ptr
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:478:21:    got unsigned int [usertype] *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:478:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:478:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:478:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:478:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:478:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:478:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:478:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:478:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:478:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:478:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:478:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:478:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:478:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:478:21: warning: incorrect type in argument 1 (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:536:21:    expected void const volatile [noderef] __user *ptr
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:536:21:    got unsigned int [usertype] *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:536:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:536:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:536:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:536:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:536:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:536:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:536:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:536:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:536:21: warning: incorrect type in argument 1 (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:597:21:    expected void const volatile [noderef] __user *ptr
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:597:21:    got unsigned int [usertype] *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:597:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:597:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:597:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:597:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:597:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:597:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:597:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:597:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:597:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:597:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:597:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:597:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:597:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:597:21: warning: incorrect type in argument 1 (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:655:21:    expected void const volatile [noderef] __user *ptr
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:655:21:    got unsigned int [usertype] *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:655:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:655:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:655:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:655:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:655:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:655:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:655:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:655:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:655:21: warning: incorrect type in argument 1 (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:752:21:    expected void const volatile [noderef] __user *ptr
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:752:21:    got unsigned int [usertype] *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:752:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:752:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:752:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:752:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:752:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:752:21: warning: incorrect type in argument 1 (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:752:21: warning: too many warnings
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1735:65: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1743:55: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1744:50: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1745:50: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1746:56: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1748:25: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1749:45: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1750:51: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1751:55: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1752:57: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1754:25: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1755:53: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1757:25: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1759:25: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1760:46: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1764:73: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1766:33: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1768:33: warning: cast to restricted __l


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

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

* [Intel-gfx] ✓ Fi.CI.BAT: success for drm/i915: Add support for LTTPR non-transparent link training mode (rev2)
  2020-09-24 18:47 ` [Intel-gfx] " Imre Deak
                   ` (7 preceding siblings ...)
  (?)
@ 2020-09-24 22:24 ` Patchwork
  -1 siblings, 0 replies; 19+ messages in thread
From: Patchwork @ 2020-09-24 22:24 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 7179 bytes --]

== Series Details ==

Series: drm/i915: Add support for LTTPR non-transparent link training mode (rev2)
URL   : https://patchwork.freedesktop.org/series/81968/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_9053 -> Patchwork_18567
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/index.html

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

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

### IGT changes ###

#### Issues hit ####

  * igt@i915_pm_rpm@basic-pci-d3-state:
    - fi-bsw-kefka:       [PASS][1] -> [DMESG-WARN][2] ([i915#1982])
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/fi-bsw-kefka/igt@i915_pm_rpm@basic-pci-d3-state.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/fi-bsw-kefka/igt@i915_pm_rpm@basic-pci-d3-state.html

  * igt@kms_flip@basic-flip-vs-wf_vblank@b-edp1:
    - fi-icl-u2:          [PASS][3] -> [DMESG-WARN][4] ([i915#1982])
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/fi-icl-u2/igt@kms_flip@basic-flip-vs-wf_vblank@b-edp1.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/fi-icl-u2/igt@kms_flip@basic-flip-vs-wf_vblank@b-edp1.html

  * igt@vgem_basic@setversion:
    - fi-tgl-y:           [PASS][5] -> [DMESG-WARN][6] ([i915#402]) +1 similar issue
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/fi-tgl-y/igt@vgem_basic@setversion.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/fi-tgl-y/igt@vgem_basic@setversion.html

  * igt@vgem_basic@unload:
    - fi-skl-guc:         [PASS][7] -> [DMESG-WARN][8] ([i915#2203])
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/fi-skl-guc/igt@vgem_basic@unload.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/fi-skl-guc/igt@vgem_basic@unload.html

  
#### Possible fixes ####

  * igt@gem_flink_basic@basic:
    - fi-tgl-y:           [DMESG-WARN][9] ([i915#402]) -> [PASS][10] +1 similar issue
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/fi-tgl-y/igt@gem_flink_basic@basic.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/fi-tgl-y/igt@gem_flink_basic@basic.html

  * igt@i915_module_load@reload:
    - {fi-ehl-1}:         [DMESG-WARN][11] ([i915#1982]) -> [PASS][12]
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/fi-ehl-1/igt@i915_module_load@reload.html
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/fi-ehl-1/igt@i915_module_load@reload.html
    - fi-tgl-y:           [DMESG-WARN][13] ([i915#1982] / [k.org#205379]) -> [PASS][14]
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/fi-tgl-y/igt@i915_module_load@reload.html
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/fi-tgl-y/igt@i915_module_load@reload.html

  * igt@i915_pm_rpm@module-reload:
    - fi-kbl-x1275:       [DMESG-FAIL][15] ([i915#62] / [i915#95]) -> [PASS][16]
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/fi-kbl-x1275/igt@i915_pm_rpm@module-reload.html
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/fi-kbl-x1275/igt@i915_pm_rpm@module-reload.html

  * igt@kms_busy@basic@flip:
    - {fi-tgl-dsi}:       [DMESG-WARN][17] ([i915#1982]) -> [PASS][18]
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/fi-tgl-dsi/igt@kms_busy@basic@flip.html
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/fi-tgl-dsi/igt@kms_busy@basic@flip.html
    - fi-tgl-y:           [DMESG-WARN][19] ([i915#1982]) -> [PASS][20]
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/fi-tgl-y/igt@kms_busy@basic@flip.html
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/fi-tgl-y/igt@kms_busy@basic@flip.html

  * igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy:
    - fi-icl-u2:          [DMESG-WARN][21] ([i915#1982]) -> [PASS][22]
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/fi-icl-u2/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/fi-icl-u2/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html

  * igt@kms_flip@basic-flip-vs-modeset@b-dp1:
    - fi-kbl-x1275:       [DMESG-WARN][23] ([i915#62] / [i915#92]) -> [PASS][24] +35 similar issues
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/fi-kbl-x1275/igt@kms_flip@basic-flip-vs-modeset@b-dp1.html
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/fi-kbl-x1275/igt@kms_flip@basic-flip-vs-modeset@b-dp1.html

  * igt@kms_force_connector_basic@prune-stale-modes:
    - fi-kbl-x1275:       [DMESG-WARN][25] ([i915#62] / [i915#92] / [i915#95]) -> [PASS][26] +7 similar issues
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/fi-kbl-x1275/igt@kms_force_connector_basic@prune-stale-modes.html
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/fi-kbl-x1275/igt@kms_force_connector_basic@prune-stale-modes.html

  
#### Warnings ####

  * igt@i915_pm_rpm@module-reload:
    - fi-kbl-guc:         [SKIP][27] ([fdo#109271]) -> [DMESG-FAIL][28] ([i915#2203])
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/fi-kbl-guc/igt@i915_pm_rpm@module-reload.html
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/fi-kbl-guc/igt@i915_pm_rpm@module-reload.html

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

  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [i915#1982]: https://gitlab.freedesktop.org/drm/intel/issues/1982
  [i915#2203]: https://gitlab.freedesktop.org/drm/intel/issues/2203
  [i915#402]: https://gitlab.freedesktop.org/drm/intel/issues/402
  [i915#62]: https://gitlab.freedesktop.org/drm/intel/issues/62
  [i915#92]: https://gitlab.freedesktop.org/drm/intel/issues/92
  [i915#95]: https://gitlab.freedesktop.org/drm/intel/issues/95
  [k.org#205379]: https://bugzilla.kernel.org/show_bug.cgi?id=205379


Participating hosts (46 -> 40)
------------------------------

  Missing    (6): fi-ilk-m540 fi-hsw-4200u fi-byt-squawks fi-bsw-cyan fi-byt-clapper fi-bdw-samus 


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

  * Linux: CI_DRM_9053 -> Patchwork_18567

  CI-20190529: 20190529
  CI_DRM_9053: 1cf86dfa098540e161420c4e6814d5629c8eceb4 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_5787: 0ec962017c8131de14e0cb038f7f76b1f17ed637 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  Patchwork_18567: ec239286430fc72b9320a4a69b93cb181cb20439 @ git://anongit.freedesktop.org/gfx-ci/linux


== Linux commits ==

ec239286430f drm/i915: Switch to LTTPR non-transparent mode link training
078f21ffc0b4 drm/i915: Switch to LTTPR transparent mode link training
7eb818d47b74 drm/dp: Add LTTPR helpers
08d7aee4b564 drm/i915: Factor out a helper to disable the DPCD training pattern
e902df2087f4 drm/i915: Simplify the link training functions
ef3b33e61770 drm/i915: Fix DP link training pattern mask

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/index.html

[-- Attachment #1.2: Type: text/html, Size: 8942 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

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

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

* [Intel-gfx] ✓ Fi.CI.IGT: success for drm/i915: Add support for LTTPR non-transparent link training mode (rev2)
  2020-09-24 18:47 ` [Intel-gfx] " Imre Deak
                   ` (8 preceding siblings ...)
  (?)
@ 2020-09-25  3:13 ` Patchwork
  -1 siblings, 0 replies; 19+ messages in thread
From: Patchwork @ 2020-09-25  3:13 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 11872 bytes --]

== Series Details ==

Series: drm/i915: Add support for LTTPR non-transparent link training mode (rev2)
URL   : https://patchwork.freedesktop.org/series/81968/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_9053_full -> Patchwork_18567_full
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  

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

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

### IGT changes ###

#### Issues hit ####

  * igt@feature_discovery@psr2:
    - shard-iclb:         [PASS][1] -> [SKIP][2] ([i915#658])
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/shard-iclb2/igt@feature_discovery@psr2.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/shard-iclb1/igt@feature_discovery@psr2.html

  * igt@i915_selftest@live@gt_heartbeat:
    - shard-skl:          [PASS][3] -> [DMESG-FAIL][4] ([i915#541])
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/shard-skl7/igt@i915_selftest@live@gt_heartbeat.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/shard-skl6/igt@i915_selftest@live@gt_heartbeat.html

  * igt@kms_cursor_legacy@2x-long-flip-vs-cursor-atomic:
    - shard-glk:          [PASS][5] -> [FAIL][6] ([i915#72])
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/shard-glk5/igt@kms_cursor_legacy@2x-long-flip-vs-cursor-atomic.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/shard-glk2/igt@kms_cursor_legacy@2x-long-flip-vs-cursor-atomic.html

  * igt@kms_cursor_legacy@basic-busy-flip-before-cursor-atomic:
    - shard-skl:          [PASS][7] -> [DMESG-WARN][8] ([i915#1982]) +4 similar issues
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/shard-skl10/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-atomic.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/shard-skl8/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-atomic.html

  * igt@kms_flip@2x-flip-vs-expired-vblank-interruptible@ac-hdmi-a1-hdmi-a2:
    - shard-glk:          [PASS][9] -> [FAIL][10] ([i915#79]) +1 similar issue
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/shard-glk6/igt@kms_flip@2x-flip-vs-expired-vblank-interruptible@ac-hdmi-a1-hdmi-a2.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/shard-glk6/igt@kms_flip@2x-flip-vs-expired-vblank-interruptible@ac-hdmi-a1-hdmi-a2.html

  * igt@kms_flip@plain-flip-fb-recreate-interruptible@a-edp1:
    - shard-skl:          [PASS][11] -> [FAIL][12] ([i915#2122])
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/shard-skl7/igt@kms_flip@plain-flip-fb-recreate-interruptible@a-edp1.html
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/shard-skl6/igt@kms_flip@plain-flip-fb-recreate-interruptible@a-edp1.html

  * igt@kms_frontbuffer_tracking@fbc-1p-primscrn-indfb-pgflip-blt:
    - shard-apl:          [PASS][13] -> [DMESG-WARN][14] ([i915#1635] / [i915#1982])
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/shard-apl3/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-indfb-pgflip-blt.html
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/shard-apl1/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-indfb-pgflip-blt.html

  * igt@kms_psr@psr2_suspend:
    - shard-iclb:         [PASS][15] -> [SKIP][16] ([fdo#109441]) +1 similar issue
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/shard-iclb2/igt@kms_psr@psr2_suspend.html
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/shard-iclb4/igt@kms_psr@psr2_suspend.html

  * igt@kms_setmode@basic:
    - shard-skl:          [PASS][17] -> [FAIL][18] ([i915#31])
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/shard-skl8/igt@kms_setmode@basic.html
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/shard-skl3/igt@kms_setmode@basic.html

  * igt@kms_vblank@pipe-d-wait-idle:
    - shard-tglb:         [PASS][19] -> [DMESG-WARN][20] ([i915#1982]) +2 similar issues
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/shard-tglb3/igt@kms_vblank@pipe-d-wait-idle.html
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/shard-tglb7/igt@kms_vblank@pipe-d-wait-idle.html

  
#### Possible fixes ####

  * igt@gem_ctx_param@vm:
    - shard-skl:          [DMESG-WARN][21] ([i915#1982]) -> [PASS][22] +5 similar issues
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/shard-skl10/igt@gem_ctx_param@vm.html
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/shard-skl6/igt@gem_ctx_param@vm.html

  * igt@gem_ctx_persistence@engines-mixed-process@rcs0:
    - shard-glk:          [FAIL][23] ([i915#2374]) -> [PASS][24]
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/shard-glk7/igt@gem_ctx_persistence@engines-mixed-process@rcs0.html
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/shard-glk5/igt@gem_ctx_persistence@engines-mixed-process@rcs0.html

  * igt@gem_exec_reloc@basic-many-active@vecs0:
    - shard-glk:          [FAIL][25] ([i915#2389]) -> [PASS][26] +2 similar issues
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/shard-glk6/igt@gem_exec_reloc@basic-many-active@vecs0.html
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/shard-glk7/igt@gem_exec_reloc@basic-many-active@vecs0.html

  * igt@gem_exec_whisper@basic-fds-forked-all:
    - shard-glk:          [DMESG-WARN][27] ([i915#118] / [i915#95]) -> [PASS][28]
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/shard-glk7/igt@gem_exec_whisper@basic-fds-forked-all.html
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/shard-glk3/igt@gem_exec_whisper@basic-fds-forked-all.html

  * igt@kms_cursor_legacy@2x-long-flip-vs-cursor-legacy:
    - shard-glk:          [FAIL][29] ([i915#72]) -> [PASS][30]
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/shard-glk2/igt@kms_cursor_legacy@2x-long-flip-vs-cursor-legacy.html
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/shard-glk5/igt@kms_cursor_legacy@2x-long-flip-vs-cursor-legacy.html

  * igt@kms_draw_crc@draw-method-rgb565-pwrite-untiled:
    - shard-skl:          [FAIL][31] ([i915#177] / [i915#52] / [i915#54]) -> [PASS][32]
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/shard-skl7/igt@kms_draw_crc@draw-method-rgb565-pwrite-untiled.html
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/shard-skl6/igt@kms_draw_crc@draw-method-rgb565-pwrite-untiled.html

  * igt@kms_flip@flip-vs-expired-vblank-interruptible@b-edp1:
    - shard-skl:          [FAIL][33] ([i915#79]) -> [PASS][34]
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/shard-skl5/igt@kms_flip@flip-vs-expired-vblank-interruptible@b-edp1.html
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/shard-skl4/igt@kms_flip@flip-vs-expired-vblank-interruptible@b-edp1.html

  * igt@kms_frontbuffer_tracking@psr-1p-offscren-pri-indfb-draw-mmap-cpu:
    - shard-skl:          [FAIL][35] ([i915#49]) -> [PASS][36]
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/shard-skl10/igt@kms_frontbuffer_tracking@psr-1p-offscren-pri-indfb-draw-mmap-cpu.html
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/shard-skl6/igt@kms_frontbuffer_tracking@psr-1p-offscren-pri-indfb-draw-mmap-cpu.html

  * igt@kms_frontbuffer_tracking@psr-1p-primscrn-pri-shrfb-draw-render:
    - shard-tglb:         [DMESG-WARN][37] ([i915#1982]) -> [PASS][38] +1 similar issue
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/shard-tglb8/igt@kms_frontbuffer_tracking@psr-1p-primscrn-pri-shrfb-draw-render.html
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/shard-tglb3/igt@kms_frontbuffer_tracking@psr-1p-primscrn-pri-shrfb-draw-render.html

  * igt@kms_plane_alpha_blend@pipe-a-constant-alpha-min:
    - shard-skl:          [FAIL][39] ([fdo#108145] / [i915#265]) -> [PASS][40] +1 similar issue
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/shard-skl10/igt@kms_plane_alpha_blend@pipe-a-constant-alpha-min.html
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/shard-skl6/igt@kms_plane_alpha_blend@pipe-a-constant-alpha-min.html

  * igt@kms_plane_alpha_blend@pipe-c-coverage-7efc:
    - shard-skl:          [DMESG-FAIL][41] ([fdo#108145] / [i915#1982]) -> [PASS][42]
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/shard-skl9/igt@kms_plane_alpha_blend@pipe-c-coverage-7efc.html
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/shard-skl1/igt@kms_plane_alpha_blend@pipe-c-coverage-7efc.html

  * igt@kms_psr@psr2_no_drrs:
    - shard-iclb:         [SKIP][43] ([fdo#109441]) -> [PASS][44] +1 similar issue
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/shard-iclb6/igt@kms_psr@psr2_no_drrs.html
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/shard-iclb2/igt@kms_psr@psr2_no_drrs.html

  
#### Warnings ####

  * igt@gen9_exec_parse@allowed-all:
    - shard-kbl:          [INCOMPLETE][45] ([i915#1436]) -> [DMESG-WARN][46] ([i915#1436] / [i915#716])
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/shard-kbl4/igt@gen9_exec_parse@allowed-all.html
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/shard-kbl1/igt@gen9_exec_parse@allowed-all.html

  * igt@kms_fbcon_fbt@psr-suspend:
    - shard-skl:          [INCOMPLETE][47] ([i915#198]) -> [DMESG-WARN][48] ([i915#1982])
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9053/shard-skl1/igt@kms_fbcon_fbt@psr-suspend.html
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18567/shard-skl9/igt@kms_fbcon_fbt@psr-suspend.html

  
  [fdo#108145]: https://bugs.freedesktop.org/show_bug.cgi?id=108145
  [fdo#109441]: https://bugs.freedesktop.org/show_bug.cgi?id=109441
  [i915#118]: https://gitlab.freedesktop.org/drm/intel/issues/118
  [i915#1436]: https://gitlab.freedesktop.org/drm/intel/issues/1436
  [i915#1635]: https://gitlab.freedesktop.org/drm/intel/issues/1635
  [i915#177]: https://gitlab.freedesktop.org/drm/intel/issues/177
  [i915#198]: https://gitlab.freedesktop.org/drm/intel/issues/198
  [i915#1982]: https://gitlab.freedesktop.org/drm/intel/issues/1982
  [i915#2122]: https://gitlab.freedesktop.org/drm/intel/issues/2122
  [i915#2374]: https://gitlab.freedesktop.org/drm/intel/issues/2374
  [i915#2389]: https://gitlab.freedesktop.org/drm/intel/issues/2389
  [i915#265]: https://gitlab.freedesktop.org/drm/intel/issues/265
  [i915#31]: https://gitlab.freedesktop.org/drm/intel/issues/31
  [i915#49]: https://gitlab.freedesktop.org/drm/intel/issues/49
  [i915#52]: https://gitlab.freedesktop.org/drm/intel/issues/52
  [i915#54]: https://gitlab.freedesktop.org/drm/intel/issues/54
  [i915#541]: https://gitlab.freedesktop.org/drm/intel/issues/541
  [i915#658]: https://gitlab.freedesktop.org/drm/intel/issues/658
  [i915#716]: https://gitlab.freedesktop.org/drm/intel/issues/716
  [i915#72]: https://gitlab.freedesktop.org/drm/intel/issues/72
  [i915#79]: https://gitlab.freedesktop.org/drm/intel/issues/79
  [i915#95]: https://gitlab.freedesktop.org/drm/intel/issues/95


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

  No changes in participating hosts


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

  * Linux: CI_DRM_9053 -> Patchwork_18567

  CI-20190529: 20190529
  CI_DRM_9053: 1cf86dfa098540e161420c4e6814d5629c8eceb4 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_5787: 0ec962017c8131de14e0cb038f7f76b1f17ed637 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  Patchwork_18567: ec239286430fc72b9320a4a69b93cb181cb20439 @ 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_18567/index.html

[-- Attachment #1.2: Type: text/html, Size: 13795 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

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

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

* Re: [PATCH v2 4/6] drm/dp: Add LTTPR helpers
  2020-09-24 18:48   ` [Intel-gfx] " Imre Deak
@ 2020-09-25 16:02     ` Ville Syrjälä
  -1 siblings, 0 replies; 19+ messages in thread
From: Ville Syrjälä @ 2020-09-25 16:02 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx, dri-devel

On Thu, Sep 24, 2020 at 09:48:03PM +0300, Imre Deak wrote:
> Add the helpers and register definitions needed to read out the common
> and per-PHY LTTPR capabilities and perform link training in the LTTPR
> non-transparent mode.
> 
> v2:
> - Add drm_dp_dpcd_read_phy_link_status() and DP_PHY_LTTPR() here instead
>   of adding these to i915. (Ville)
> 
> Cc: dri-devel@lists.freedesktop.org
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/drm_dp_helper.c | 244 +++++++++++++++++++++++++++++++-
>  include/drm/drm_dp_helper.h     |  62 ++++++++
>  2 files changed, 302 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
> index 478dd51f738d..6014c858b06b 100644
> --- a/drivers/gpu/drm/drm_dp_helper.c
> +++ b/drivers/gpu/drm/drm_dp_helper.c
> @@ -150,11 +150,8 @@ void drm_dp_link_train_clock_recovery_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
>  }
>  EXPORT_SYMBOL(drm_dp_link_train_clock_recovery_delay);
>  
> -void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
> +static void __drm_dp_link_train_channel_eq_delay(unsigned long rd_interval)
>  {
> -	unsigned long rd_interval = dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
> -					 DP_TRAINING_AUX_RD_MASK;
> -
>  	if (rd_interval > 4)
>  		DRM_DEBUG_KMS("AUX interval %lu, out of range (max 4)\n",
>  			      rd_interval);
> @@ -166,8 +163,35 @@ void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
>  
>  	usleep_range(rd_interval, rd_interval * 2);
>  }
> +
> +void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
> +{
> +	__drm_dp_link_train_channel_eq_delay(dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
> +					     DP_TRAINING_AUX_RD_MASK);
> +}
>  EXPORT_SYMBOL(drm_dp_link_train_channel_eq_delay);
>  
> +void drm_dp_lttpr_link_train_clock_recovery_delay(void)
> +{
> +	usleep_range(100, 200);
> +}
> +EXPORT_SYMBOL(drm_dp_lttpr_link_train_clock_recovery_delay);
> +
> +static u8 dp_lttpr_phy_cap(const u8 phy_cap[DP_LTTPR_PHY_CAP_SIZE], int r)
> +{
> +	return phy_cap[r - DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1];
> +}
> +
> +void drm_dp_lttpr_link_train_channel_eq_delay(const u8 phy_cap[DP_LTTPR_PHY_CAP_SIZE])
> +{
> +	u8 interval = dp_lttpr_phy_cap(phy_cap,
> +				       DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1) &
> +		      DP_TRAINING_AUX_RD_MASK;
> +
> +	__drm_dp_link_train_channel_eq_delay(interval);
> +}
> +EXPORT_SYMBOL(drm_dp_lttpr_link_train_channel_eq_delay);
> +
>  u8 drm_dp_link_rate_to_bw_code(int link_rate)
>  {
>  	/* Spec says link_bw = link_rate / 0.27Gbps */
> @@ -363,6 +387,71 @@ int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
>  }
>  EXPORT_SYMBOL(drm_dp_dpcd_read_link_status);
>  
> +/**
> + * drm_dp_dpcd_read_phy_link_status - get the link status information for a DP PHY
> + * @aux: DisplayPort AUX channel
> + * @dp_phy: the DP PHY to get the link status for
> + * @link_status: buffer to return the status in
> + *
> + * Fetch the AUX DPCD registers for the DPRX or an LTTPR PHY link status. The
> + * layout of the returned @link_status matches the DPCD register layout of the
> + * DPRX PHY link status.
> + *
> + * Returns 0 if the information was read successfully or a negative error code
> + * on failure.
> + */
> +int drm_dp_dpcd_read_phy_link_status(struct drm_dp_aux *aux,
> +				     enum drm_dp_phy dp_phy,
> +				     u8 link_status[DP_LINK_STATUS_SIZE])
> +{
> +	u8 lttpr_status[DP_LINK_STATUS_SIZE - 1];
> +	int ret;
> +
> +	if (dp_phy == DP_PHY_DPRX) {
> +		ret = drm_dp_dpcd_read(aux,
> +				       DP_LANE0_1_STATUS,
> +				       link_status,
> +				       DP_LINK_STATUS_SIZE);
> +
> +		if (ret < 0)
> +			return ret;
> +
> +		WARN_ON(ret != DP_LINK_STATUS_SIZE);
> +
> +		return 0;
> +	}
> +
> +	ret = drm_dp_dpcd_read(aux,
> +			       DP_LANE0_1_STATUS_PHY_REPEATER(dp_phy),
> +			       lttpr_status,
> +			       sizeof(lttpr_status));
> +
> +	if (ret < 0)
> +		return ret;
> +
> +	WARN_ON(ret != sizeof(lttpr_status));
> +
> +#define link_reg(reg)	link_status[(reg) - DP_LANE0_1_STATUS]
> +#define lttpr_reg(reg)	lttpr_status[(reg) - DP_LANE0_1_STATUS_PHY_REPEATER1]
> +
> +	/* Convert the LTTPR to the sink PHY link status layout */
> +	link_reg(DP_LANE0_1_STATUS) = lttpr_reg(DP_LANE0_1_STATUS_PHY_REPEATER1);
> +	link_reg(DP_LANE2_3_STATUS) = lttpr_reg(DP_LANE2_3_STATUS_PHY_REPEATER1);
> +	link_reg(DP_LANE_ALIGN_STATUS_UPDATED) =
> +		lttpr_reg(DP_LANE_ALIGN_STATUS_UPDATED_PHY_REPEATER1);
> +	link_reg(DP_SINK_STATUS) = 0;
> +	link_reg(DP_ADJUST_REQUEST_LANE0_1) =
> +		lttpr_reg(DP_ADJUST_REQUEST_LANE0_1_PHY_REPEATER1);
> +	link_reg(DP_ADJUST_REQUEST_LANE2_3) =
> +		lttpr_reg(DP_ADJUST_REQUEST_LANE2_3_PHY_REPEATER1);
> +
> +#undef link_reg
> +#undef lttpr_reg

Alternative might be to read to the target buffer directly
and just memmove() the stuff around a bit. Would avoid having
the second buffer on stack. But it's a small buffer so meh.

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(drm_dp_dpcd_read_phy_link_status);
> +
>  static bool is_edid_digital_input_dp(const struct edid *edid)
>  {
>  	return edid && edid->revision >= 4 &&
> @@ -2098,6 +2187,153 @@ int drm_dp_dsc_sink_supported_input_bpcs(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_S
>  }
>  EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs);
>  
> +/**
> + * drm_dp_read_lttpr_common_caps - read the LTTPR common capabilities
> + * @aux: DisplayPort AUX channel
> + * @caps: buffer to return the capability info in
> + *
> + * Read capabilities common to all LTTPRs.
> + *
> + * Returns 0 on success or a negative error code on failure.
> + */
> +int drm_dp_read_lttpr_common_caps(struct drm_dp_aux *aux,
> +				  u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
> +{
> +	int ret;
> +
> +	ret = drm_dp_dpcd_read(aux,
> +			       DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
> +			       caps, DP_LTTPR_COMMON_CAP_SIZE);
> +	if (ret < 0)
> +		return ret;
> +
> +	WARN_ON(ret != DP_LTTPR_COMMON_CAP_SIZE);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(drm_dp_read_lttpr_common_caps);
> +
> +/**
> + * drm_dp_read_lttpr_phy_caps - read the capabilities for a given LTTPR PHY
> + * @aux: DisplayPort AUX channel
> + * @dp_phy: LTTPR PHY to read the capabilities for
> + * @caps: buffer to return the capability info in
> + *
> + * Read the capabilities for the given LTTPR PHY.
> + *
> + * Returns 0 on success or a negative error code on failure.
> + */
> +int drm_dp_read_lttpr_phy_caps(struct drm_dp_aux *aux,
> +			       enum drm_dp_phy dp_phy,
> +			       u8 caps[DP_LTTPR_PHY_CAP_SIZE])
> +{
> +	int ret;
> +
> +	ret = drm_dp_dpcd_read(aux,
> +			       DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER(dp_phy),
> +			       caps, DP_LTTPR_PHY_CAP_SIZE);
> +	if (ret < 0)
> +		return ret;
> +
> +	WARN_ON(ret != DP_LTTPR_PHY_CAP_SIZE);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(drm_dp_read_lttpr_phy_caps);
> +
> +static u8 dp_lttpr_common_cap(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE], int r)
> +{
> +	return caps[r - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
> +}
> +
> +/**
> + * drm_dp_lttpr_count - get the number of detected LTTPRs
> + * @caps: LTTPR common capabilities
> + *
> + * Get the number of detected LTTPRs from the LTTPR common capabilities info.
> + *
> + * Returns:
> + *   -ERANGE if more than supported number (8) of LTTPRs are detected
> + *   -EINVAL if the DP_PHY_REPEATER_CNT register contains an invalid value
> + *   otherwise the number of detected LTTPRs
> + */
> +int drm_dp_lttpr_count(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
> +{
> +	u8 count = dp_lttpr_common_cap(caps, DP_PHY_REPEATER_CNT);
> +
> +	switch (hweight8(count)) {
> +	case 0:
> +		return 0;
> +	case 1:
> +		return 8 - ilog2(count);
> +	case 8:
> +		return -ERANGE;
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +EXPORT_SYMBOL(drm_dp_lttpr_count);
> +
> +/**
> + * drm_dp_lttpr_max_link_rate - get the maximum link rate supported by all LTTPRs
> + * @caps: LTTPR common capabilities
> + *
> + * Returns the maximum link rate supported by all detected LTTPRs.
> + */
> +int drm_dp_lttpr_max_link_rate(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
> +{
> +	u8 rate = dp_lttpr_common_cap(caps, DP_MAX_LINK_RATE_PHY_REPEATER);
> +
> +	return drm_dp_bw_code_to_link_rate(rate);
> +}
> +EXPORT_SYMBOL(drm_dp_lttpr_max_link_rate);
> +
> +/**
> + * drm_dp_lttpr_max_lane_count - get the maximum lane count supported by all LTTPRs
> + * @caps: LTTPR common capabilities
> + *
> + * Returns the maximum lane count supported by all detected LTTPRs.
> + */
> +int drm_dp_lttpr_max_lane_count(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
> +{
> +	u8 max_lanes = dp_lttpr_common_cap(caps, DP_MAX_LANE_COUNT_PHY_REPEATER);
> +
> +	return max_lanes & DP_MAX_LANE_COUNT_MASK;
> +}
> +EXPORT_SYMBOL(drm_dp_lttpr_max_lane_count);
> +
> +/**
> + * drm_dp_lttpr_voltage_swing_level_3_supported - check for LTTPR vswing3 support
> + * @caps: LTTPR PHY capabilities
> + *
> + * Returns true if the @caps for an LTTPR TX PHY indicate support for
> + * voltage swing level 3.
> + */
> +bool
> +drm_dp_lttpr_voltage_swing_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE])
> +{
> +	u8 txcap = dp_lttpr_phy_cap(caps, DP_TRANSMITTER_CAPABILITY_PHY_REPEATER1);
> +
> +	return txcap & DP_VOLTAGE_SWING_LEVEL_3_SUPPORTED;
> +}
> +EXPORT_SYMBOL(drm_dp_lttpr_voltage_swing_level_3_supported);
> +
> +/**
> + * drm_dp_lttpr_pre_emphasis_level_3_supported - check for LTTPR preemph3 support
> + * @caps: LTTPR PHY capabilities
> + *
> + * Returns true if the @caps for an LTTPR TX PHY indicate support for
> + * pre-emphasis level 3.
> + */
> +bool
> +drm_dp_lttpr_pre_emphasis_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE])
> +{
> +	u8 txcap = dp_lttpr_phy_cap(caps, DP_TRANSMITTER_CAPABILITY_PHY_REPEATER1);
> +
> +	return txcap & DP_PRE_EMPHASIS_LEVEL_3_SUPPORTED;
> +}
> +EXPORT_SYMBOL(drm_dp_lttpr_pre_emphasis_level_3_supported);
> +
>  /**
>   * drm_dp_get_phy_test_pattern() - get the requested pattern from the sink.
>   * @aux: DisplayPort AUX channel
> diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> index e144b4b9d79a..42b6ab14920a 100644
> --- a/include/drm/drm_dp_helper.h
> +++ b/include/drm/drm_dp_helper.h
> @@ -1118,15 +1118,58 @@ struct drm_device;
>  #define DP_MAX_LANE_COUNT_PHY_REPEATER			    0xf0004 /* 1.4a */
>  #define DP_Repeater_FEC_CAPABILITY			    0xf0004 /* 1.4 */
>  #define DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT		    0xf0005 /* 1.4a */
> +
> +enum drm_dp_phy {
> +	DP_PHY_DPRX,
> +
> +	DP_PHY_LTTPR1,
> +	DP_PHY_LTTPR2,
> +	DP_PHY_LTTPR3,
> +	DP_PHY_LTTPR4,
> +	DP_PHY_LTTPR5,
> +	DP_PHY_LTTPR6,
> +	DP_PHY_LTTPR7,
> +	DP_PHY_LTTPR8,
> +
> +	DP_MAX_LTTPR_COUNT = DP_PHY_LTTPR8,
> +};
> +
> +#define DP_PHY_LTTPR(i)					    (DP_PHY_LTTPR1 + (i))
> +
> +#define __DP_LTTPR1_BASE				    0xf0010 /* 1.3 */
> +#define __DP_LTTPR2_BASE				    0xf0060 /* 1.3 */
> +#define DP_LTTPR_BASE(dp_phy) \
> +	(__DP_LTTPR1_BASE + (__DP_LTTPR2_BASE - __DP_LTTPR1_BASE) * \
> +		((dp_phy) - DP_PHY_LTTPR1))
> +
> +#define DP_LTTPR_REG(dp_phy, lttpr1_reg) \
> +	(DP_LTTPR_BASE(dp_phy) - DP_LTTPR_BASE(DP_PHY_LTTPR1) + (lttpr1_reg))
> +
>  #define DP_TRAINING_PATTERN_SET_PHY_REPEATER1		    0xf0010 /* 1.3 */
> +#define DP_TRAINING_PATTERN_SET_PHY_REPEATER(dp_phy) \
> +	DP_LTTPR_REG(dp_phy, DP_TRAINING_PATTERN_SET_PHY_REPEATER1)
> +
>  #define DP_TRAINING_LANE0_SET_PHY_REPEATER1		    0xf0011 /* 1.3 */
> +#define DP_TRAINING_LANE0_SET_PHY_REPEATER(dp_phy) \
> +	DP_LTTPR_REG(dp_phy, DP_TRAINING_LANE0_SET_PHY_REPEATER1)
> +
>  #define DP_TRAINING_LANE1_SET_PHY_REPEATER1		    0xf0012 /* 1.3 */
>  #define DP_TRAINING_LANE2_SET_PHY_REPEATER1		    0xf0013 /* 1.3 */
>  #define DP_TRAINING_LANE3_SET_PHY_REPEATER1		    0xf0014 /* 1.3 */
>  #define DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1	    0xf0020 /* 1.4a */
> +#define DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER(dp_phy)	\
> +	DP_LTTPR_REG(dp_phy, DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1)
> +
>  #define DP_TRANSMITTER_CAPABILITY_PHY_REPEATER1		    0xf0021 /* 1.4a */
> +# define DP_VOLTAGE_SWING_LEVEL_3_SUPPORTED		    BIT(0)
> +# define DP_PRE_EMPHASIS_LEVEL_3_SUPPORTED		    BIT(1)
> +
>  #define DP_LANE0_1_STATUS_PHY_REPEATER1			    0xf0030 /* 1.3 */
> +#define DP_LANE0_1_STATUS_PHY_REPEATER(dp_phy) \
> +	DP_LTTPR_REG(dp_phy, DP_LANE0_1_STATUS_PHY_REPEATER1)
> +
>  #define DP_LANE2_3_STATUS_PHY_REPEATER1			    0xf0031 /* 1.3 */
> +
>  #define DP_LANE_ALIGN_STATUS_UPDATED_PHY_REPEATER1	    0xf0032 /* 1.3 */
>  #define DP_ADJUST_REQUEST_LANE0_1_PHY_REPEATER1		    0xf0033 /* 1.3 */
>  #define DP_ADJUST_REQUEST_LANE2_3_PHY_REPEATER1		    0xf0034 /* 1.3 */
> @@ -1236,9 +1279,13 @@ u8 drm_dp_get_adjust_request_post_cursor(const u8 link_status[DP_LINK_STATUS_SIZ
>  #define DP_DSC_RECEIVER_CAP_SIZE        0xf
>  #define EDP_PSR_RECEIVER_CAP_SIZE	2
>  #define EDP_DISPLAY_CTL_CAP_SIZE	3
> +#define DP_LTTPR_COMMON_CAP_SIZE	8
> +#define DP_LTTPR_PHY_CAP_SIZE		3
>  
>  void drm_dp_link_train_clock_recovery_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]);
> +void drm_dp_lttpr_link_train_clock_recovery_delay(void);
>  void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]);
> +void drm_dp_lttpr_link_train_channel_eq_delay(const u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
>  
>  u8 drm_dp_link_rate_to_bw_code(int link_rate);
>  int drm_dp_bw_code_to_link_rate(u8 link_bw);
> @@ -1697,6 +1744,10 @@ int drm_dp_read_dpcd_caps(struct drm_dp_aux *aux,
>  int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
>  				 u8 status[DP_LINK_STATUS_SIZE]);
>  
> +int drm_dp_dpcd_read_phy_link_status(struct drm_dp_aux *aux,
> +				     enum drm_dp_phy dp_phy,
> +				     u8 link_status[DP_LINK_STATUS_SIZE]);
> +
>  bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux,
>  				    u8 real_edid_checksum);
>  
> @@ -1746,6 +1797,17 @@ bool drm_dp_read_sink_count_cap(struct drm_connector *connector,
>  				const struct drm_dp_desc *desc);
>  int drm_dp_read_sink_count(struct drm_dp_aux *aux);
>  
> +int drm_dp_read_lttpr_common_caps(struct drm_dp_aux *aux,
> +				  u8 caps[DP_LTTPR_COMMON_CAP_SIZE]);
> +int drm_dp_read_lttpr_phy_caps(struct drm_dp_aux *aux,
> +			       enum drm_dp_phy dp_phy,
> +			       u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
> +int drm_dp_lttpr_count(const u8 cap[DP_LTTPR_COMMON_CAP_SIZE]);
> +int drm_dp_lttpr_max_link_rate(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE]);
> +int drm_dp_lttpr_max_lane_count(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE]);
> +bool drm_dp_lttpr_voltage_swing_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
> +bool drm_dp_lttpr_pre_emphasis_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
> +
>  void drm_dp_remote_aux_init(struct drm_dp_aux *aux);
>  void drm_dp_aux_init(struct drm_dp_aux *aux);
>  int drm_dp_aux_register(struct drm_dp_aux *aux);
> -- 
> 2.25.1

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

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

* Re: [Intel-gfx] [PATCH v2 4/6] drm/dp: Add LTTPR helpers
@ 2020-09-25 16:02     ` Ville Syrjälä
  0 siblings, 0 replies; 19+ messages in thread
From: Ville Syrjälä @ 2020-09-25 16:02 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx, dri-devel

On Thu, Sep 24, 2020 at 09:48:03PM +0300, Imre Deak wrote:
> Add the helpers and register definitions needed to read out the common
> and per-PHY LTTPR capabilities and perform link training in the LTTPR
> non-transparent mode.
> 
> v2:
> - Add drm_dp_dpcd_read_phy_link_status() and DP_PHY_LTTPR() here instead
>   of adding these to i915. (Ville)
> 
> Cc: dri-devel@lists.freedesktop.org
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/drm_dp_helper.c | 244 +++++++++++++++++++++++++++++++-
>  include/drm/drm_dp_helper.h     |  62 ++++++++
>  2 files changed, 302 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
> index 478dd51f738d..6014c858b06b 100644
> --- a/drivers/gpu/drm/drm_dp_helper.c
> +++ b/drivers/gpu/drm/drm_dp_helper.c
> @@ -150,11 +150,8 @@ void drm_dp_link_train_clock_recovery_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
>  }
>  EXPORT_SYMBOL(drm_dp_link_train_clock_recovery_delay);
>  
> -void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
> +static void __drm_dp_link_train_channel_eq_delay(unsigned long rd_interval)
>  {
> -	unsigned long rd_interval = dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
> -					 DP_TRAINING_AUX_RD_MASK;
> -
>  	if (rd_interval > 4)
>  		DRM_DEBUG_KMS("AUX interval %lu, out of range (max 4)\n",
>  			      rd_interval);
> @@ -166,8 +163,35 @@ void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
>  
>  	usleep_range(rd_interval, rd_interval * 2);
>  }
> +
> +void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
> +{
> +	__drm_dp_link_train_channel_eq_delay(dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
> +					     DP_TRAINING_AUX_RD_MASK);
> +}
>  EXPORT_SYMBOL(drm_dp_link_train_channel_eq_delay);
>  
> +void drm_dp_lttpr_link_train_clock_recovery_delay(void)
> +{
> +	usleep_range(100, 200);
> +}
> +EXPORT_SYMBOL(drm_dp_lttpr_link_train_clock_recovery_delay);
> +
> +static u8 dp_lttpr_phy_cap(const u8 phy_cap[DP_LTTPR_PHY_CAP_SIZE], int r)
> +{
> +	return phy_cap[r - DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1];
> +}
> +
> +void drm_dp_lttpr_link_train_channel_eq_delay(const u8 phy_cap[DP_LTTPR_PHY_CAP_SIZE])
> +{
> +	u8 interval = dp_lttpr_phy_cap(phy_cap,
> +				       DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1) &
> +		      DP_TRAINING_AUX_RD_MASK;
> +
> +	__drm_dp_link_train_channel_eq_delay(interval);
> +}
> +EXPORT_SYMBOL(drm_dp_lttpr_link_train_channel_eq_delay);
> +
>  u8 drm_dp_link_rate_to_bw_code(int link_rate)
>  {
>  	/* Spec says link_bw = link_rate / 0.27Gbps */
> @@ -363,6 +387,71 @@ int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
>  }
>  EXPORT_SYMBOL(drm_dp_dpcd_read_link_status);
>  
> +/**
> + * drm_dp_dpcd_read_phy_link_status - get the link status information for a DP PHY
> + * @aux: DisplayPort AUX channel
> + * @dp_phy: the DP PHY to get the link status for
> + * @link_status: buffer to return the status in
> + *
> + * Fetch the AUX DPCD registers for the DPRX or an LTTPR PHY link status. The
> + * layout of the returned @link_status matches the DPCD register layout of the
> + * DPRX PHY link status.
> + *
> + * Returns 0 if the information was read successfully or a negative error code
> + * on failure.
> + */
> +int drm_dp_dpcd_read_phy_link_status(struct drm_dp_aux *aux,
> +				     enum drm_dp_phy dp_phy,
> +				     u8 link_status[DP_LINK_STATUS_SIZE])
> +{
> +	u8 lttpr_status[DP_LINK_STATUS_SIZE - 1];
> +	int ret;
> +
> +	if (dp_phy == DP_PHY_DPRX) {
> +		ret = drm_dp_dpcd_read(aux,
> +				       DP_LANE0_1_STATUS,
> +				       link_status,
> +				       DP_LINK_STATUS_SIZE);
> +
> +		if (ret < 0)
> +			return ret;
> +
> +		WARN_ON(ret != DP_LINK_STATUS_SIZE);
> +
> +		return 0;
> +	}
> +
> +	ret = drm_dp_dpcd_read(aux,
> +			       DP_LANE0_1_STATUS_PHY_REPEATER(dp_phy),
> +			       lttpr_status,
> +			       sizeof(lttpr_status));
> +
> +	if (ret < 0)
> +		return ret;
> +
> +	WARN_ON(ret != sizeof(lttpr_status));
> +
> +#define link_reg(reg)	link_status[(reg) - DP_LANE0_1_STATUS]
> +#define lttpr_reg(reg)	lttpr_status[(reg) - DP_LANE0_1_STATUS_PHY_REPEATER1]
> +
> +	/* Convert the LTTPR to the sink PHY link status layout */
> +	link_reg(DP_LANE0_1_STATUS) = lttpr_reg(DP_LANE0_1_STATUS_PHY_REPEATER1);
> +	link_reg(DP_LANE2_3_STATUS) = lttpr_reg(DP_LANE2_3_STATUS_PHY_REPEATER1);
> +	link_reg(DP_LANE_ALIGN_STATUS_UPDATED) =
> +		lttpr_reg(DP_LANE_ALIGN_STATUS_UPDATED_PHY_REPEATER1);
> +	link_reg(DP_SINK_STATUS) = 0;
> +	link_reg(DP_ADJUST_REQUEST_LANE0_1) =
> +		lttpr_reg(DP_ADJUST_REQUEST_LANE0_1_PHY_REPEATER1);
> +	link_reg(DP_ADJUST_REQUEST_LANE2_3) =
> +		lttpr_reg(DP_ADJUST_REQUEST_LANE2_3_PHY_REPEATER1);
> +
> +#undef link_reg
> +#undef lttpr_reg

Alternative might be to read to the target buffer directly
and just memmove() the stuff around a bit. Would avoid having
the second buffer on stack. But it's a small buffer so meh.

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(drm_dp_dpcd_read_phy_link_status);
> +
>  static bool is_edid_digital_input_dp(const struct edid *edid)
>  {
>  	return edid && edid->revision >= 4 &&
> @@ -2098,6 +2187,153 @@ int drm_dp_dsc_sink_supported_input_bpcs(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_S
>  }
>  EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs);
>  
> +/**
> + * drm_dp_read_lttpr_common_caps - read the LTTPR common capabilities
> + * @aux: DisplayPort AUX channel
> + * @caps: buffer to return the capability info in
> + *
> + * Read capabilities common to all LTTPRs.
> + *
> + * Returns 0 on success or a negative error code on failure.
> + */
> +int drm_dp_read_lttpr_common_caps(struct drm_dp_aux *aux,
> +				  u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
> +{
> +	int ret;
> +
> +	ret = drm_dp_dpcd_read(aux,
> +			       DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
> +			       caps, DP_LTTPR_COMMON_CAP_SIZE);
> +	if (ret < 0)
> +		return ret;
> +
> +	WARN_ON(ret != DP_LTTPR_COMMON_CAP_SIZE);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(drm_dp_read_lttpr_common_caps);
> +
> +/**
> + * drm_dp_read_lttpr_phy_caps - read the capabilities for a given LTTPR PHY
> + * @aux: DisplayPort AUX channel
> + * @dp_phy: LTTPR PHY to read the capabilities for
> + * @caps: buffer to return the capability info in
> + *
> + * Read the capabilities for the given LTTPR PHY.
> + *
> + * Returns 0 on success or a negative error code on failure.
> + */
> +int drm_dp_read_lttpr_phy_caps(struct drm_dp_aux *aux,
> +			       enum drm_dp_phy dp_phy,
> +			       u8 caps[DP_LTTPR_PHY_CAP_SIZE])
> +{
> +	int ret;
> +
> +	ret = drm_dp_dpcd_read(aux,
> +			       DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER(dp_phy),
> +			       caps, DP_LTTPR_PHY_CAP_SIZE);
> +	if (ret < 0)
> +		return ret;
> +
> +	WARN_ON(ret != DP_LTTPR_PHY_CAP_SIZE);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(drm_dp_read_lttpr_phy_caps);
> +
> +static u8 dp_lttpr_common_cap(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE], int r)
> +{
> +	return caps[r - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
> +}
> +
> +/**
> + * drm_dp_lttpr_count - get the number of detected LTTPRs
> + * @caps: LTTPR common capabilities
> + *
> + * Get the number of detected LTTPRs from the LTTPR common capabilities info.
> + *
> + * Returns:
> + *   -ERANGE if more than supported number (8) of LTTPRs are detected
> + *   -EINVAL if the DP_PHY_REPEATER_CNT register contains an invalid value
> + *   otherwise the number of detected LTTPRs
> + */
> +int drm_dp_lttpr_count(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
> +{
> +	u8 count = dp_lttpr_common_cap(caps, DP_PHY_REPEATER_CNT);
> +
> +	switch (hweight8(count)) {
> +	case 0:
> +		return 0;
> +	case 1:
> +		return 8 - ilog2(count);
> +	case 8:
> +		return -ERANGE;
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +EXPORT_SYMBOL(drm_dp_lttpr_count);
> +
> +/**
> + * drm_dp_lttpr_max_link_rate - get the maximum link rate supported by all LTTPRs
> + * @caps: LTTPR common capabilities
> + *
> + * Returns the maximum link rate supported by all detected LTTPRs.
> + */
> +int drm_dp_lttpr_max_link_rate(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
> +{
> +	u8 rate = dp_lttpr_common_cap(caps, DP_MAX_LINK_RATE_PHY_REPEATER);
> +
> +	return drm_dp_bw_code_to_link_rate(rate);
> +}
> +EXPORT_SYMBOL(drm_dp_lttpr_max_link_rate);
> +
> +/**
> + * drm_dp_lttpr_max_lane_count - get the maximum lane count supported by all LTTPRs
> + * @caps: LTTPR common capabilities
> + *
> + * Returns the maximum lane count supported by all detected LTTPRs.
> + */
> +int drm_dp_lttpr_max_lane_count(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
> +{
> +	u8 max_lanes = dp_lttpr_common_cap(caps, DP_MAX_LANE_COUNT_PHY_REPEATER);
> +
> +	return max_lanes & DP_MAX_LANE_COUNT_MASK;
> +}
> +EXPORT_SYMBOL(drm_dp_lttpr_max_lane_count);
> +
> +/**
> + * drm_dp_lttpr_voltage_swing_level_3_supported - check for LTTPR vswing3 support
> + * @caps: LTTPR PHY capabilities
> + *
> + * Returns true if the @caps for an LTTPR TX PHY indicate support for
> + * voltage swing level 3.
> + */
> +bool
> +drm_dp_lttpr_voltage_swing_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE])
> +{
> +	u8 txcap = dp_lttpr_phy_cap(caps, DP_TRANSMITTER_CAPABILITY_PHY_REPEATER1);
> +
> +	return txcap & DP_VOLTAGE_SWING_LEVEL_3_SUPPORTED;
> +}
> +EXPORT_SYMBOL(drm_dp_lttpr_voltage_swing_level_3_supported);
> +
> +/**
> + * drm_dp_lttpr_pre_emphasis_level_3_supported - check for LTTPR preemph3 support
> + * @caps: LTTPR PHY capabilities
> + *
> + * Returns true if the @caps for an LTTPR TX PHY indicate support for
> + * pre-emphasis level 3.
> + */
> +bool
> +drm_dp_lttpr_pre_emphasis_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE])
> +{
> +	u8 txcap = dp_lttpr_phy_cap(caps, DP_TRANSMITTER_CAPABILITY_PHY_REPEATER1);
> +
> +	return txcap & DP_PRE_EMPHASIS_LEVEL_3_SUPPORTED;
> +}
> +EXPORT_SYMBOL(drm_dp_lttpr_pre_emphasis_level_3_supported);
> +
>  /**
>   * drm_dp_get_phy_test_pattern() - get the requested pattern from the sink.
>   * @aux: DisplayPort AUX channel
> diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> index e144b4b9d79a..42b6ab14920a 100644
> --- a/include/drm/drm_dp_helper.h
> +++ b/include/drm/drm_dp_helper.h
> @@ -1118,15 +1118,58 @@ struct drm_device;
>  #define DP_MAX_LANE_COUNT_PHY_REPEATER			    0xf0004 /* 1.4a */
>  #define DP_Repeater_FEC_CAPABILITY			    0xf0004 /* 1.4 */
>  #define DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT		    0xf0005 /* 1.4a */
> +
> +enum drm_dp_phy {
> +	DP_PHY_DPRX,
> +
> +	DP_PHY_LTTPR1,
> +	DP_PHY_LTTPR2,
> +	DP_PHY_LTTPR3,
> +	DP_PHY_LTTPR4,
> +	DP_PHY_LTTPR5,
> +	DP_PHY_LTTPR6,
> +	DP_PHY_LTTPR7,
> +	DP_PHY_LTTPR8,
> +
> +	DP_MAX_LTTPR_COUNT = DP_PHY_LTTPR8,
> +};
> +
> +#define DP_PHY_LTTPR(i)					    (DP_PHY_LTTPR1 + (i))
> +
> +#define __DP_LTTPR1_BASE				    0xf0010 /* 1.3 */
> +#define __DP_LTTPR2_BASE				    0xf0060 /* 1.3 */
> +#define DP_LTTPR_BASE(dp_phy) \
> +	(__DP_LTTPR1_BASE + (__DP_LTTPR2_BASE - __DP_LTTPR1_BASE) * \
> +		((dp_phy) - DP_PHY_LTTPR1))
> +
> +#define DP_LTTPR_REG(dp_phy, lttpr1_reg) \
> +	(DP_LTTPR_BASE(dp_phy) - DP_LTTPR_BASE(DP_PHY_LTTPR1) + (lttpr1_reg))
> +
>  #define DP_TRAINING_PATTERN_SET_PHY_REPEATER1		    0xf0010 /* 1.3 */
> +#define DP_TRAINING_PATTERN_SET_PHY_REPEATER(dp_phy) \
> +	DP_LTTPR_REG(dp_phy, DP_TRAINING_PATTERN_SET_PHY_REPEATER1)
> +
>  #define DP_TRAINING_LANE0_SET_PHY_REPEATER1		    0xf0011 /* 1.3 */
> +#define DP_TRAINING_LANE0_SET_PHY_REPEATER(dp_phy) \
> +	DP_LTTPR_REG(dp_phy, DP_TRAINING_LANE0_SET_PHY_REPEATER1)
> +
>  #define DP_TRAINING_LANE1_SET_PHY_REPEATER1		    0xf0012 /* 1.3 */
>  #define DP_TRAINING_LANE2_SET_PHY_REPEATER1		    0xf0013 /* 1.3 */
>  #define DP_TRAINING_LANE3_SET_PHY_REPEATER1		    0xf0014 /* 1.3 */
>  #define DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1	    0xf0020 /* 1.4a */
> +#define DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER(dp_phy)	\
> +	DP_LTTPR_REG(dp_phy, DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1)
> +
>  #define DP_TRANSMITTER_CAPABILITY_PHY_REPEATER1		    0xf0021 /* 1.4a */
> +# define DP_VOLTAGE_SWING_LEVEL_3_SUPPORTED		    BIT(0)
> +# define DP_PRE_EMPHASIS_LEVEL_3_SUPPORTED		    BIT(1)
> +
>  #define DP_LANE0_1_STATUS_PHY_REPEATER1			    0xf0030 /* 1.3 */
> +#define DP_LANE0_1_STATUS_PHY_REPEATER(dp_phy) \
> +	DP_LTTPR_REG(dp_phy, DP_LANE0_1_STATUS_PHY_REPEATER1)
> +
>  #define DP_LANE2_3_STATUS_PHY_REPEATER1			    0xf0031 /* 1.3 */
> +
>  #define DP_LANE_ALIGN_STATUS_UPDATED_PHY_REPEATER1	    0xf0032 /* 1.3 */
>  #define DP_ADJUST_REQUEST_LANE0_1_PHY_REPEATER1		    0xf0033 /* 1.3 */
>  #define DP_ADJUST_REQUEST_LANE2_3_PHY_REPEATER1		    0xf0034 /* 1.3 */
> @@ -1236,9 +1279,13 @@ u8 drm_dp_get_adjust_request_post_cursor(const u8 link_status[DP_LINK_STATUS_SIZ
>  #define DP_DSC_RECEIVER_CAP_SIZE        0xf
>  #define EDP_PSR_RECEIVER_CAP_SIZE	2
>  #define EDP_DISPLAY_CTL_CAP_SIZE	3
> +#define DP_LTTPR_COMMON_CAP_SIZE	8
> +#define DP_LTTPR_PHY_CAP_SIZE		3
>  
>  void drm_dp_link_train_clock_recovery_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]);
> +void drm_dp_lttpr_link_train_clock_recovery_delay(void);
>  void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]);
> +void drm_dp_lttpr_link_train_channel_eq_delay(const u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
>  
>  u8 drm_dp_link_rate_to_bw_code(int link_rate);
>  int drm_dp_bw_code_to_link_rate(u8 link_bw);
> @@ -1697,6 +1744,10 @@ int drm_dp_read_dpcd_caps(struct drm_dp_aux *aux,
>  int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
>  				 u8 status[DP_LINK_STATUS_SIZE]);
>  
> +int drm_dp_dpcd_read_phy_link_status(struct drm_dp_aux *aux,
> +				     enum drm_dp_phy dp_phy,
> +				     u8 link_status[DP_LINK_STATUS_SIZE]);
> +
>  bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux,
>  				    u8 real_edid_checksum);
>  
> @@ -1746,6 +1797,17 @@ bool drm_dp_read_sink_count_cap(struct drm_connector *connector,
>  				const struct drm_dp_desc *desc);
>  int drm_dp_read_sink_count(struct drm_dp_aux *aux);
>  
> +int drm_dp_read_lttpr_common_caps(struct drm_dp_aux *aux,
> +				  u8 caps[DP_LTTPR_COMMON_CAP_SIZE]);
> +int drm_dp_read_lttpr_phy_caps(struct drm_dp_aux *aux,
> +			       enum drm_dp_phy dp_phy,
> +			       u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
> +int drm_dp_lttpr_count(const u8 cap[DP_LTTPR_COMMON_CAP_SIZE]);
> +int drm_dp_lttpr_max_link_rate(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE]);
> +int drm_dp_lttpr_max_lane_count(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE]);
> +bool drm_dp_lttpr_voltage_swing_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
> +bool drm_dp_lttpr_pre_emphasis_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
> +
>  void drm_dp_remote_aux_init(struct drm_dp_aux *aux);
>  void drm_dp_aux_init(struct drm_dp_aux *aux);
>  int drm_dp_aux_register(struct drm_dp_aux *aux);
> -- 
> 2.25.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] 19+ messages in thread

* Re: [Intel-gfx] [PATCH v2 5/6] drm/i915: Switch to LTTPR transparent mode link training
  2020-09-24 18:48 ` [Intel-gfx] [PATCH v2 5/6] drm/i915: Switch to LTTPR transparent mode link training Imre Deak
@ 2020-09-25 16:03   ` Ville Syrjälä
  2020-09-25 16:40     ` Imre Deak
  0 siblings, 1 reply; 19+ messages in thread
From: Ville Syrjälä @ 2020-09-25 16:03 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Thu, Sep 24, 2020 at 09:48:04PM +0300, Imre Deak wrote:
> By default LTTPRs should be in transparent link training mode,
> nevertheless in this patch we switch to this default mode explicitly.
> 
> The DP Standard recommends this, supposedly because an LTTPR may be left
> in the non-transparent mode (by BIOS, previous kernel, or after reset
> due to a firmware bug). I haven't seen this happening, but let's follow
> the DP Standard.
> 
> v2:
> - Add a code comment about the explicit disabling of non-transparent
>   mode.
> 
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  .../drm/i915/display/intel_display_types.h    |  1 +
>  drivers/gpu/drm/i915/display/intel_dp.c       |  3 ++
>  .../drm/i915/display/intel_dp_link_training.c | 52 +++++++++++++++++++
>  .../drm/i915/display/intel_dp_link_training.h |  2 +
>  4 files changed, 58 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 3d4bf9b6a0a2..b04921eba73b 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -1280,6 +1280,7 @@ struct intel_dp {
>  	u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
>  	u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE];
>  	u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE];
> +	u8 lttpr_common_caps[DP_LTTPR_COMMON_CAP_SIZE];
>  	u8 fec_capable;
>  	/* source rates */
>  	int num_source_rates;
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index b21f42193a11..64bf4aa384d3 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -4726,6 +4726,9 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
>  {
>  	int ret;
>  
> +	if (!intel_dp_is_edp(intel_dp))
> +		intel_dp_lttpr_init(intel_dp);

I was initially a bit confused why this is before we read dpcd[], but
looks like the spec says that is the expected order.

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

> +
>  	if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd))
>  		return false;
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
> index 38d4553670a1..4f8f42cc25fa 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
> @@ -34,6 +34,52 @@ intel_dp_dump_link_status(const u8 link_status[DP_LINK_STATUS_SIZE])
>  		      link_status[3], link_status[4], link_status[5]);
>  }
>  
> +static bool intel_dp_read_lttpr_common_caps(struct intel_dp *intel_dp)
> +{
> +	if (drm_dp_read_lttpr_common_caps(&intel_dp->aux,
> +					  intel_dp->lttpr_common_caps) < 0) {
> +		memset(intel_dp->lttpr_common_caps, 0,
> +		       sizeof(intel_dp->lttpr_common_caps));
> +		return false;
> +	}
> +
> +	drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
> +		    "LTTPR common capabilities: %*ph\n",
> +		    (int)sizeof(intel_dp->lttpr_common_caps),
> +		    intel_dp->lttpr_common_caps);
> +
> +	return true;
> +}
> +
> +static bool
> +intel_dp_set_lttpr_transparent_mode(struct intel_dp *intel_dp, bool enable)
> +{
> +	u8 val = enable ? DP_PHY_REPEATER_MODE_TRANSPARENT :
> +			  DP_PHY_REPEATER_MODE_NON_TRANSPARENT;
> +
> +	return drm_dp_dpcd_write(&intel_dp->aux, DP_PHY_REPEATER_MODE, &val, 1) == 1;
> +}
> +
> +/**
> + * intel_dp_lttpr_init - detect LTTPRs and init the LTTPR link training mode
> + * @intel_dp: Intel DP struct
> + *
> + * Read the LTTPR common capabilities and switch to transparent link training
> + * mode.
> + */
> +int intel_dp_lttpr_init(struct intel_dp *intel_dp)
> +{
> +	intel_dp_read_lttpr_common_caps(intel_dp);
> +
> +	/*
> +	 * See DP Standard v2.0 3.6.6.1. about the explicit disabling of
> +	 * non-transparent mode.
> +	 */
> +	intel_dp_set_lttpr_transparent_mode(intel_dp, true);
> +
> +	return 0;
> +}
> +
>  static u8 dp_voltage_max(u8 preemph)
>  {
>  	switch (preemph & DP_TRAIN_PRE_EMPHASIS_MASK) {
> @@ -471,6 +517,12 @@ static void intel_dp_schedule_fallback_link_training(struct intel_dp *intel_dp)
>   */
>  void intel_dp_start_link_train(struct intel_dp *intel_dp)
>  {
> +	/*
> +	 * TODO: Reiniting LTTPRs here won't be needed once proper connector
> +	 * HW state readout is added.
> +	 */
> +	intel_dp_lttpr_init(intel_dp);
> +
>  	if (!intel_dp_link_train(intel_dp))
>  		intel_dp_schedule_fallback_link_training(intel_dp);
>  }
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.h b/drivers/gpu/drm/i915/display/intel_dp_link_training.h
> index 518d834dbc98..3536ce73a123 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.h
> +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.h
> @@ -10,6 +10,8 @@
>  
>  struct intel_dp;
>  
> +int intel_dp_lttpr_init(struct intel_dp *intel_dp);
> +
>  void intel_dp_get_adjust_train(struct intel_dp *intel_dp,
>  			       const u8 link_status[DP_LINK_STATUS_SIZE]);
>  void intel_dp_start_link_train(struct intel_dp *intel_dp);
> -- 
> 2.25.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] 19+ messages in thread

* Re: [Intel-gfx] [PATCH v2 5/6] drm/i915: Switch to LTTPR transparent mode link training
  2020-09-25 16:03   ` Ville Syrjälä
@ 2020-09-25 16:40     ` Imre Deak
  0 siblings, 0 replies; 19+ messages in thread
From: Imre Deak @ 2020-09-25 16:40 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Fri, Sep 25, 2020 at 07:03:50PM +0300, Ville Syrjälä wrote:
> On Thu, Sep 24, 2020 at 09:48:04PM +0300, Imre Deak wrote:
> > By default LTTPRs should be in transparent link training mode,
> > nevertheless in this patch we switch to this default mode explicitly.
> > 
> > The DP Standard recommends this, supposedly because an LTTPR may be left
> > in the non-transparent mode (by BIOS, previous kernel, or after reset
> > due to a firmware bug). I haven't seen this happening, but let's follow
> > the DP Standard.
> > 
> > v2:
> > - Add a code comment about the explicit disabling of non-transparent
> >   mode.
> > 
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  .../drm/i915/display/intel_display_types.h    |  1 +
> >  drivers/gpu/drm/i915/display/intel_dp.c       |  3 ++
> >  .../drm/i915/display/intel_dp_link_training.c | 52 +++++++++++++++++++
> >  .../drm/i915/display/intel_dp_link_training.h |  2 +
> >  4 files changed, 58 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> > index 3d4bf9b6a0a2..b04921eba73b 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> > +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> > @@ -1280,6 +1280,7 @@ struct intel_dp {
> >  	u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
> >  	u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE];
> >  	u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE];
> > +	u8 lttpr_common_caps[DP_LTTPR_COMMON_CAP_SIZE];
> >  	u8 fec_capable;
> >  	/* source rates */
> >  	int num_source_rates;
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> > index b21f42193a11..64bf4aa384d3 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> > @@ -4726,6 +4726,9 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
> >  {
> >  	int ret;
> >  
> > +	if (!intel_dp_is_edp(intel_dp))
> > +		intel_dp_lttpr_init(intel_dp);
> 
> I was initially a bit confused why this is before we read dpcd[], but
> looks like the spec says that is the expected order.

Yes. It's strange but reading the spec makes me think that even reading
regs could have side-effects, here the LTTPR caps reading is the first
according to the spec.

Btw, the other less clearly specified things are the order of
(explicitly) switching to transparent mode vs. reading the LTTPR common
caps, and in what case to perform the switch. I decided the correct
order is to read the caps first, and switch unconditionally. The latter
has the downside of an AUX timeout/NAK on platforms w/o LTTPRs, but this
seemed to be the more robust way.

> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Thanks. I mucked up the eDP check, missing it from
intel_dp_start_link_train(), will move it to intel_dp_lttpr_init()
instead.

> 
> > +
> >  	if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd))
> >  		return false;
> >  
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
> > index 38d4553670a1..4f8f42cc25fa 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
> > @@ -34,6 +34,52 @@ intel_dp_dump_link_status(const u8 link_status[DP_LINK_STATUS_SIZE])
> >  		      link_status[3], link_status[4], link_status[5]);
> >  }
> >  
> > +static bool intel_dp_read_lttpr_common_caps(struct intel_dp *intel_dp)
> > +{
> > +	if (drm_dp_read_lttpr_common_caps(&intel_dp->aux,
> > +					  intel_dp->lttpr_common_caps) < 0) {
> > +		memset(intel_dp->lttpr_common_caps, 0,
> > +		       sizeof(intel_dp->lttpr_common_caps));
> > +		return false;
> > +	}
> > +
> > +	drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
> > +		    "LTTPR common capabilities: %*ph\n",
> > +		    (int)sizeof(intel_dp->lttpr_common_caps),
> > +		    intel_dp->lttpr_common_caps);
> > +
> > +	return true;
> > +}
> > +
> > +static bool
> > +intel_dp_set_lttpr_transparent_mode(struct intel_dp *intel_dp, bool enable)
> > +{
> > +	u8 val = enable ? DP_PHY_REPEATER_MODE_TRANSPARENT :
> > +			  DP_PHY_REPEATER_MODE_NON_TRANSPARENT;
> > +
> > +	return drm_dp_dpcd_write(&intel_dp->aux, DP_PHY_REPEATER_MODE, &val, 1) == 1;
> > +}
> > +
> > +/**
> > + * intel_dp_lttpr_init - detect LTTPRs and init the LTTPR link training mode
> > + * @intel_dp: Intel DP struct
> > + *
> > + * Read the LTTPR common capabilities and switch to transparent link training
> > + * mode.
> > + */
> > +int intel_dp_lttpr_init(struct intel_dp *intel_dp)
> > +{
> > +	intel_dp_read_lttpr_common_caps(intel_dp);
> > +
> > +	/*
> > +	 * See DP Standard v2.0 3.6.6.1. about the explicit disabling of
> > +	 * non-transparent mode.
> > +	 */
> > +	intel_dp_set_lttpr_transparent_mode(intel_dp, true);
> > +
> > +	return 0;
> > +}
> > +
> >  static u8 dp_voltage_max(u8 preemph)
> >  {
> >  	switch (preemph & DP_TRAIN_PRE_EMPHASIS_MASK) {
> > @@ -471,6 +517,12 @@ static void intel_dp_schedule_fallback_link_training(struct intel_dp *intel_dp)
> >   */
> >  void intel_dp_start_link_train(struct intel_dp *intel_dp)
> >  {
> > +	/*
> > +	 * TODO: Reiniting LTTPRs here won't be needed once proper connector
> > +	 * HW state readout is added.
> > +	 */
> > +	intel_dp_lttpr_init(intel_dp);
> > +
> >  	if (!intel_dp_link_train(intel_dp))
> >  		intel_dp_schedule_fallback_link_training(intel_dp);
> >  }
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.h b/drivers/gpu/drm/i915/display/intel_dp_link_training.h
> > index 518d834dbc98..3536ce73a123 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.h
> > +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.h
> > @@ -10,6 +10,8 @@
> >  
> >  struct intel_dp;
> >  
> > +int intel_dp_lttpr_init(struct intel_dp *intel_dp);
> > +
> >  void intel_dp_get_adjust_train(struct intel_dp *intel_dp,
> >  			       const u8 link_status[DP_LINK_STATUS_SIZE]);
> >  void intel_dp_start_link_train(struct intel_dp *intel_dp);
> > -- 
> > 2.25.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] 19+ messages in thread

* Re: [PATCH v2 4/6] drm/dp: Add LTTPR helpers
  2020-09-25 16:02     ` [Intel-gfx] " Ville Syrjälä
@ 2020-09-25 16:51       ` Imre Deak
  -1 siblings, 0 replies; 19+ messages in thread
From: Imre Deak @ 2020-09-25 16:51 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

On Fri, Sep 25, 2020 at 07:02:47PM +0300, Ville Syrjälä wrote:
> On Thu, Sep 24, 2020 at 09:48:03PM +0300, Imre Deak wrote:
> > Add the helpers and register definitions needed to read out the common
> > and per-PHY LTTPR capabilities and perform link training in the LTTPR
> > non-transparent mode.
> > 
> > v2:
> > - Add drm_dp_dpcd_read_phy_link_status() and DP_PHY_LTTPR() here instead
> >   of adding these to i915. (Ville)
> > 
> > Cc: dri-devel@lists.freedesktop.org
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/drm_dp_helper.c | 244 +++++++++++++++++++++++++++++++-
> >  include/drm/drm_dp_helper.h     |  62 ++++++++
> >  2 files changed, 302 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
> > index 478dd51f738d..6014c858b06b 100644
> > --- a/drivers/gpu/drm/drm_dp_helper.c
> > +++ b/drivers/gpu/drm/drm_dp_helper.c
> > @@ -150,11 +150,8 @@ void drm_dp_link_train_clock_recovery_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
> >  }
> >  EXPORT_SYMBOL(drm_dp_link_train_clock_recovery_delay);
> >  
> > -void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
> > +static void __drm_dp_link_train_channel_eq_delay(unsigned long rd_interval)
> >  {
> > -	unsigned long rd_interval = dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
> > -					 DP_TRAINING_AUX_RD_MASK;
> > -
> >  	if (rd_interval > 4)
> >  		DRM_DEBUG_KMS("AUX interval %lu, out of range (max 4)\n",
> >  			      rd_interval);
> > @@ -166,8 +163,35 @@ void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
> >  
> >  	usleep_range(rd_interval, rd_interval * 2);
> >  }
> > +
> > +void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
> > +{
> > +	__drm_dp_link_train_channel_eq_delay(dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
> > +					     DP_TRAINING_AUX_RD_MASK);
> > +}
> >  EXPORT_SYMBOL(drm_dp_link_train_channel_eq_delay);
> >  
> > +void drm_dp_lttpr_link_train_clock_recovery_delay(void)
> > +{
> > +	usleep_range(100, 200);
> > +}
> > +EXPORT_SYMBOL(drm_dp_lttpr_link_train_clock_recovery_delay);
> > +
> > +static u8 dp_lttpr_phy_cap(const u8 phy_cap[DP_LTTPR_PHY_CAP_SIZE], int r)
> > +{
> > +	return phy_cap[r - DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1];
> > +}
> > +
> > +void drm_dp_lttpr_link_train_channel_eq_delay(const u8 phy_cap[DP_LTTPR_PHY_CAP_SIZE])
> > +{
> > +	u8 interval = dp_lttpr_phy_cap(phy_cap,
> > +				       DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1) &
> > +		      DP_TRAINING_AUX_RD_MASK;
> > +
> > +	__drm_dp_link_train_channel_eq_delay(interval);
> > +}
> > +EXPORT_SYMBOL(drm_dp_lttpr_link_train_channel_eq_delay);
> > +
> >  u8 drm_dp_link_rate_to_bw_code(int link_rate)
> >  {
> >  	/* Spec says link_bw = link_rate / 0.27Gbps */
> > @@ -363,6 +387,71 @@ int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
> >  }
> >  EXPORT_SYMBOL(drm_dp_dpcd_read_link_status);
> >  
> > +/**
> > + * drm_dp_dpcd_read_phy_link_status - get the link status information for a DP PHY
> > + * @aux: DisplayPort AUX channel
> > + * @dp_phy: the DP PHY to get the link status for
> > + * @link_status: buffer to return the status in
> > + *
> > + * Fetch the AUX DPCD registers for the DPRX or an LTTPR PHY link status. The
> > + * layout of the returned @link_status matches the DPCD register layout of the
> > + * DPRX PHY link status.
> > + *
> > + * Returns 0 if the information was read successfully or a negative error code
> > + * on failure.
> > + */
> > +int drm_dp_dpcd_read_phy_link_status(struct drm_dp_aux *aux,
> > +				     enum drm_dp_phy dp_phy,
> > +				     u8 link_status[DP_LINK_STATUS_SIZE])
> > +{
> > +	u8 lttpr_status[DP_LINK_STATUS_SIZE - 1];
> > +	int ret;
> > +
> > +	if (dp_phy == DP_PHY_DPRX) {
> > +		ret = drm_dp_dpcd_read(aux,
> > +				       DP_LANE0_1_STATUS,
> > +				       link_status,
> > +				       DP_LINK_STATUS_SIZE);
> > +
> > +		if (ret < 0)
> > +			return ret;
> > +
> > +		WARN_ON(ret != DP_LINK_STATUS_SIZE);
> > +
> > +		return 0;
> > +	}
> > +
> > +	ret = drm_dp_dpcd_read(aux,
> > +			       DP_LANE0_1_STATUS_PHY_REPEATER(dp_phy),
> > +			       lttpr_status,
> > +			       sizeof(lttpr_status));
> > +
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	WARN_ON(ret != sizeof(lttpr_status));
> > +
> > +#define link_reg(reg)	link_status[(reg) - DP_LANE0_1_STATUS]
> > +#define lttpr_reg(reg)	lttpr_status[(reg) - DP_LANE0_1_STATUS_PHY_REPEATER1]
> > +
> > +	/* Convert the LTTPR to the sink PHY link status layout */
> > +	link_reg(DP_LANE0_1_STATUS) = lttpr_reg(DP_LANE0_1_STATUS_PHY_REPEATER1);
> > +	link_reg(DP_LANE2_3_STATUS) = lttpr_reg(DP_LANE2_3_STATUS_PHY_REPEATER1);
> > +	link_reg(DP_LANE_ALIGN_STATUS_UPDATED) =
> > +		lttpr_reg(DP_LANE_ALIGN_STATUS_UPDATED_PHY_REPEATER1);
> > +	link_reg(DP_SINK_STATUS) = 0;
> > +	link_reg(DP_ADJUST_REQUEST_LANE0_1) =
> > +		lttpr_reg(DP_ADJUST_REQUEST_LANE0_1_PHY_REPEATER1);
> > +	link_reg(DP_ADJUST_REQUEST_LANE2_3) =
> > +		lttpr_reg(DP_ADJUST_REQUEST_LANE2_3_PHY_REPEATER1);
> > +
> > +#undef link_reg
> > +#undef lttpr_reg
> 
> Alternative might be to read to the target buffer directly
> and just memmove() the stuff around a bit. Would avoid having
> the second buffer on stack. But it's a small buffer so meh.

Yes, thought about using memmove, would be like

	memmove(&link_status[DP_SINK_STATUS - DP_LANE0_1_STATUS + 1],            
                &link_status[DP_SINK_STATUS - DP_LANE0_1_STATUS],                
                DP_LINK_STATUS_SIZE - DP_SINK_STATUS - 1);                       
        link_status[DP_SINK_STATUS - DP_LANE0_1_STATUS] = 0;

then thought that it's less clear what's going on, so decided writing it
out more explicitly. If you think that's not a concern I'll use memmove
instead.

> 
> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL(drm_dp_dpcd_read_phy_link_status);
> > +
> >  static bool is_edid_digital_input_dp(const struct edid *edid)
> >  {
> >  	return edid && edid->revision >= 4 &&
> > @@ -2098,6 +2187,153 @@ int drm_dp_dsc_sink_supported_input_bpcs(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_S
> >  }
> >  EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs);
> >  
> > +/**
> > + * drm_dp_read_lttpr_common_caps - read the LTTPR common capabilities
> > + * @aux: DisplayPort AUX channel
> > + * @caps: buffer to return the capability info in
> > + *
> > + * Read capabilities common to all LTTPRs.
> > + *
> > + * Returns 0 on success or a negative error code on failure.
> > + */
> > +int drm_dp_read_lttpr_common_caps(struct drm_dp_aux *aux,
> > +				  u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
> > +{
> > +	int ret;
> > +
> > +	ret = drm_dp_dpcd_read(aux,
> > +			       DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
> > +			       caps, DP_LTTPR_COMMON_CAP_SIZE);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	WARN_ON(ret != DP_LTTPR_COMMON_CAP_SIZE);
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL(drm_dp_read_lttpr_common_caps);
> > +
> > +/**
> > + * drm_dp_read_lttpr_phy_caps - read the capabilities for a given LTTPR PHY
> > + * @aux: DisplayPort AUX channel
> > + * @dp_phy: LTTPR PHY to read the capabilities for
> > + * @caps: buffer to return the capability info in
> > + *
> > + * Read the capabilities for the given LTTPR PHY.
> > + *
> > + * Returns 0 on success or a negative error code on failure.
> > + */
> > +int drm_dp_read_lttpr_phy_caps(struct drm_dp_aux *aux,
> > +			       enum drm_dp_phy dp_phy,
> > +			       u8 caps[DP_LTTPR_PHY_CAP_SIZE])
> > +{
> > +	int ret;
> > +
> > +	ret = drm_dp_dpcd_read(aux,
> > +			       DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER(dp_phy),
> > +			       caps, DP_LTTPR_PHY_CAP_SIZE);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	WARN_ON(ret != DP_LTTPR_PHY_CAP_SIZE);
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL(drm_dp_read_lttpr_phy_caps);
> > +
> > +static u8 dp_lttpr_common_cap(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE], int r)
> > +{
> > +	return caps[r - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
> > +}
> > +
> > +/**
> > + * drm_dp_lttpr_count - get the number of detected LTTPRs
> > + * @caps: LTTPR common capabilities
> > + *
> > + * Get the number of detected LTTPRs from the LTTPR common capabilities info.
> > + *
> > + * Returns:
> > + *   -ERANGE if more than supported number (8) of LTTPRs are detected
> > + *   -EINVAL if the DP_PHY_REPEATER_CNT register contains an invalid value
> > + *   otherwise the number of detected LTTPRs
> > + */
> > +int drm_dp_lttpr_count(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
> > +{
> > +	u8 count = dp_lttpr_common_cap(caps, DP_PHY_REPEATER_CNT);
> > +
> > +	switch (hweight8(count)) {
> > +	case 0:
> > +		return 0;
> > +	case 1:
> > +		return 8 - ilog2(count);
> > +	case 8:
> > +		return -ERANGE;
> > +	default:
> > +		return -EINVAL;
> > +	}
> > +}
> > +EXPORT_SYMBOL(drm_dp_lttpr_count);
> > +
> > +/**
> > + * drm_dp_lttpr_max_link_rate - get the maximum link rate supported by all LTTPRs
> > + * @caps: LTTPR common capabilities
> > + *
> > + * Returns the maximum link rate supported by all detected LTTPRs.
> > + */
> > +int drm_dp_lttpr_max_link_rate(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
> > +{
> > +	u8 rate = dp_lttpr_common_cap(caps, DP_MAX_LINK_RATE_PHY_REPEATER);
> > +
> > +	return drm_dp_bw_code_to_link_rate(rate);
> > +}
> > +EXPORT_SYMBOL(drm_dp_lttpr_max_link_rate);
> > +
> > +/**
> > + * drm_dp_lttpr_max_lane_count - get the maximum lane count supported by all LTTPRs
> > + * @caps: LTTPR common capabilities
> > + *
> > + * Returns the maximum lane count supported by all detected LTTPRs.
> > + */
> > +int drm_dp_lttpr_max_lane_count(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
> > +{
> > +	u8 max_lanes = dp_lttpr_common_cap(caps, DP_MAX_LANE_COUNT_PHY_REPEATER);
> > +
> > +	return max_lanes & DP_MAX_LANE_COUNT_MASK;
> > +}
> > +EXPORT_SYMBOL(drm_dp_lttpr_max_lane_count);
> > +
> > +/**
> > + * drm_dp_lttpr_voltage_swing_level_3_supported - check for LTTPR vswing3 support
> > + * @caps: LTTPR PHY capabilities
> > + *
> > + * Returns true if the @caps for an LTTPR TX PHY indicate support for
> > + * voltage swing level 3.
> > + */
> > +bool
> > +drm_dp_lttpr_voltage_swing_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE])
> > +{
> > +	u8 txcap = dp_lttpr_phy_cap(caps, DP_TRANSMITTER_CAPABILITY_PHY_REPEATER1);
> > +
> > +	return txcap & DP_VOLTAGE_SWING_LEVEL_3_SUPPORTED;
> > +}
> > +EXPORT_SYMBOL(drm_dp_lttpr_voltage_swing_level_3_supported);
> > +
> > +/**
> > + * drm_dp_lttpr_pre_emphasis_level_3_supported - check for LTTPR preemph3 support
> > + * @caps: LTTPR PHY capabilities
> > + *
> > + * Returns true if the @caps for an LTTPR TX PHY indicate support for
> > + * pre-emphasis level 3.
> > + */
> > +bool
> > +drm_dp_lttpr_pre_emphasis_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE])
> > +{
> > +	u8 txcap = dp_lttpr_phy_cap(caps, DP_TRANSMITTER_CAPABILITY_PHY_REPEATER1);
> > +
> > +	return txcap & DP_PRE_EMPHASIS_LEVEL_3_SUPPORTED;
> > +}
> > +EXPORT_SYMBOL(drm_dp_lttpr_pre_emphasis_level_3_supported);
> > +
> >  /**
> >   * drm_dp_get_phy_test_pattern() - get the requested pattern from the sink.
> >   * @aux: DisplayPort AUX channel
> > diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> > index e144b4b9d79a..42b6ab14920a 100644
> > --- a/include/drm/drm_dp_helper.h
> > +++ b/include/drm/drm_dp_helper.h
> > @@ -1118,15 +1118,58 @@ struct drm_device;
> >  #define DP_MAX_LANE_COUNT_PHY_REPEATER			    0xf0004 /* 1.4a */
> >  #define DP_Repeater_FEC_CAPABILITY			    0xf0004 /* 1.4 */
> >  #define DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT		    0xf0005 /* 1.4a */
> > +
> > +enum drm_dp_phy {
> > +	DP_PHY_DPRX,
> > +
> > +	DP_PHY_LTTPR1,
> > +	DP_PHY_LTTPR2,
> > +	DP_PHY_LTTPR3,
> > +	DP_PHY_LTTPR4,
> > +	DP_PHY_LTTPR5,
> > +	DP_PHY_LTTPR6,
> > +	DP_PHY_LTTPR7,
> > +	DP_PHY_LTTPR8,
> > +
> > +	DP_MAX_LTTPR_COUNT = DP_PHY_LTTPR8,
> > +};
> > +
> > +#define DP_PHY_LTTPR(i)					    (DP_PHY_LTTPR1 + (i))
> > +
> > +#define __DP_LTTPR1_BASE				    0xf0010 /* 1.3 */
> > +#define __DP_LTTPR2_BASE				    0xf0060 /* 1.3 */
> > +#define DP_LTTPR_BASE(dp_phy) \
> > +	(__DP_LTTPR1_BASE + (__DP_LTTPR2_BASE - __DP_LTTPR1_BASE) * \
> > +		((dp_phy) - DP_PHY_LTTPR1))
> > +
> > +#define DP_LTTPR_REG(dp_phy, lttpr1_reg) \
> > +	(DP_LTTPR_BASE(dp_phy) - DP_LTTPR_BASE(DP_PHY_LTTPR1) + (lttpr1_reg))
> > +
> >  #define DP_TRAINING_PATTERN_SET_PHY_REPEATER1		    0xf0010 /* 1.3 */
> > +#define DP_TRAINING_PATTERN_SET_PHY_REPEATER(dp_phy) \
> > +	DP_LTTPR_REG(dp_phy, DP_TRAINING_PATTERN_SET_PHY_REPEATER1)
> > +
> >  #define DP_TRAINING_LANE0_SET_PHY_REPEATER1		    0xf0011 /* 1.3 */
> > +#define DP_TRAINING_LANE0_SET_PHY_REPEATER(dp_phy) \
> > +	DP_LTTPR_REG(dp_phy, DP_TRAINING_LANE0_SET_PHY_REPEATER1)
> > +
> >  #define DP_TRAINING_LANE1_SET_PHY_REPEATER1		    0xf0012 /* 1.3 */
> >  #define DP_TRAINING_LANE2_SET_PHY_REPEATER1		    0xf0013 /* 1.3 */
> >  #define DP_TRAINING_LANE3_SET_PHY_REPEATER1		    0xf0014 /* 1.3 */
> >  #define DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1	    0xf0020 /* 1.4a */
> > +#define DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER(dp_phy)	\
> > +	DP_LTTPR_REG(dp_phy, DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1)
> > +
> >  #define DP_TRANSMITTER_CAPABILITY_PHY_REPEATER1		    0xf0021 /* 1.4a */
> > +# define DP_VOLTAGE_SWING_LEVEL_3_SUPPORTED		    BIT(0)
> > +# define DP_PRE_EMPHASIS_LEVEL_3_SUPPORTED		    BIT(1)
> > +
> >  #define DP_LANE0_1_STATUS_PHY_REPEATER1			    0xf0030 /* 1.3 */
> > +#define DP_LANE0_1_STATUS_PHY_REPEATER(dp_phy) \
> > +	DP_LTTPR_REG(dp_phy, DP_LANE0_1_STATUS_PHY_REPEATER1)
> > +
> >  #define DP_LANE2_3_STATUS_PHY_REPEATER1			    0xf0031 /* 1.3 */
> > +
> >  #define DP_LANE_ALIGN_STATUS_UPDATED_PHY_REPEATER1	    0xf0032 /* 1.3 */
> >  #define DP_ADJUST_REQUEST_LANE0_1_PHY_REPEATER1		    0xf0033 /* 1.3 */
> >  #define DP_ADJUST_REQUEST_LANE2_3_PHY_REPEATER1		    0xf0034 /* 1.3 */
> > @@ -1236,9 +1279,13 @@ u8 drm_dp_get_adjust_request_post_cursor(const u8 link_status[DP_LINK_STATUS_SIZ
> >  #define DP_DSC_RECEIVER_CAP_SIZE        0xf
> >  #define EDP_PSR_RECEIVER_CAP_SIZE	2
> >  #define EDP_DISPLAY_CTL_CAP_SIZE	3
> > +#define DP_LTTPR_COMMON_CAP_SIZE	8
> > +#define DP_LTTPR_PHY_CAP_SIZE		3
> >  
> >  void drm_dp_link_train_clock_recovery_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]);
> > +void drm_dp_lttpr_link_train_clock_recovery_delay(void);
> >  void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]);
> > +void drm_dp_lttpr_link_train_channel_eq_delay(const u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
> >  
> >  u8 drm_dp_link_rate_to_bw_code(int link_rate);
> >  int drm_dp_bw_code_to_link_rate(u8 link_bw);
> > @@ -1697,6 +1744,10 @@ int drm_dp_read_dpcd_caps(struct drm_dp_aux *aux,
> >  int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
> >  				 u8 status[DP_LINK_STATUS_SIZE]);
> >  
> > +int drm_dp_dpcd_read_phy_link_status(struct drm_dp_aux *aux,
> > +				     enum drm_dp_phy dp_phy,
> > +				     u8 link_status[DP_LINK_STATUS_SIZE]);
> > +
> >  bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux,
> >  				    u8 real_edid_checksum);
> >  
> > @@ -1746,6 +1797,17 @@ bool drm_dp_read_sink_count_cap(struct drm_connector *connector,
> >  				const struct drm_dp_desc *desc);
> >  int drm_dp_read_sink_count(struct drm_dp_aux *aux);
> >  
> > +int drm_dp_read_lttpr_common_caps(struct drm_dp_aux *aux,
> > +				  u8 caps[DP_LTTPR_COMMON_CAP_SIZE]);
> > +int drm_dp_read_lttpr_phy_caps(struct drm_dp_aux *aux,
> > +			       enum drm_dp_phy dp_phy,
> > +			       u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
> > +int drm_dp_lttpr_count(const u8 cap[DP_LTTPR_COMMON_CAP_SIZE]);
> > +int drm_dp_lttpr_max_link_rate(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE]);
> > +int drm_dp_lttpr_max_lane_count(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE]);
> > +bool drm_dp_lttpr_voltage_swing_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
> > +bool drm_dp_lttpr_pre_emphasis_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
> > +
> >  void drm_dp_remote_aux_init(struct drm_dp_aux *aux);
> >  void drm_dp_aux_init(struct drm_dp_aux *aux);
> >  int drm_dp_aux_register(struct drm_dp_aux *aux);
> > -- 
> > 2.25.1
> 
> -- 
> Ville Syrjälä
> Intel
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [Intel-gfx] [PATCH v2 4/6] drm/dp: Add LTTPR helpers
@ 2020-09-25 16:51       ` Imre Deak
  0 siblings, 0 replies; 19+ messages in thread
From: Imre Deak @ 2020-09-25 16:51 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

On Fri, Sep 25, 2020 at 07:02:47PM +0300, Ville Syrjälä wrote:
> On Thu, Sep 24, 2020 at 09:48:03PM +0300, Imre Deak wrote:
> > Add the helpers and register definitions needed to read out the common
> > and per-PHY LTTPR capabilities and perform link training in the LTTPR
> > non-transparent mode.
> > 
> > v2:
> > - Add drm_dp_dpcd_read_phy_link_status() and DP_PHY_LTTPR() here instead
> >   of adding these to i915. (Ville)
> > 
> > Cc: dri-devel@lists.freedesktop.org
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/drm_dp_helper.c | 244 +++++++++++++++++++++++++++++++-
> >  include/drm/drm_dp_helper.h     |  62 ++++++++
> >  2 files changed, 302 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
> > index 478dd51f738d..6014c858b06b 100644
> > --- a/drivers/gpu/drm/drm_dp_helper.c
> > +++ b/drivers/gpu/drm/drm_dp_helper.c
> > @@ -150,11 +150,8 @@ void drm_dp_link_train_clock_recovery_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
> >  }
> >  EXPORT_SYMBOL(drm_dp_link_train_clock_recovery_delay);
> >  
> > -void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
> > +static void __drm_dp_link_train_channel_eq_delay(unsigned long rd_interval)
> >  {
> > -	unsigned long rd_interval = dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
> > -					 DP_TRAINING_AUX_RD_MASK;
> > -
> >  	if (rd_interval > 4)
> >  		DRM_DEBUG_KMS("AUX interval %lu, out of range (max 4)\n",
> >  			      rd_interval);
> > @@ -166,8 +163,35 @@ void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
> >  
> >  	usleep_range(rd_interval, rd_interval * 2);
> >  }
> > +
> > +void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE])
> > +{
> > +	__drm_dp_link_train_channel_eq_delay(dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
> > +					     DP_TRAINING_AUX_RD_MASK);
> > +}
> >  EXPORT_SYMBOL(drm_dp_link_train_channel_eq_delay);
> >  
> > +void drm_dp_lttpr_link_train_clock_recovery_delay(void)
> > +{
> > +	usleep_range(100, 200);
> > +}
> > +EXPORT_SYMBOL(drm_dp_lttpr_link_train_clock_recovery_delay);
> > +
> > +static u8 dp_lttpr_phy_cap(const u8 phy_cap[DP_LTTPR_PHY_CAP_SIZE], int r)
> > +{
> > +	return phy_cap[r - DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1];
> > +}
> > +
> > +void drm_dp_lttpr_link_train_channel_eq_delay(const u8 phy_cap[DP_LTTPR_PHY_CAP_SIZE])
> > +{
> > +	u8 interval = dp_lttpr_phy_cap(phy_cap,
> > +				       DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1) &
> > +		      DP_TRAINING_AUX_RD_MASK;
> > +
> > +	__drm_dp_link_train_channel_eq_delay(interval);
> > +}
> > +EXPORT_SYMBOL(drm_dp_lttpr_link_train_channel_eq_delay);
> > +
> >  u8 drm_dp_link_rate_to_bw_code(int link_rate)
> >  {
> >  	/* Spec says link_bw = link_rate / 0.27Gbps */
> > @@ -363,6 +387,71 @@ int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
> >  }
> >  EXPORT_SYMBOL(drm_dp_dpcd_read_link_status);
> >  
> > +/**
> > + * drm_dp_dpcd_read_phy_link_status - get the link status information for a DP PHY
> > + * @aux: DisplayPort AUX channel
> > + * @dp_phy: the DP PHY to get the link status for
> > + * @link_status: buffer to return the status in
> > + *
> > + * Fetch the AUX DPCD registers for the DPRX or an LTTPR PHY link status. The
> > + * layout of the returned @link_status matches the DPCD register layout of the
> > + * DPRX PHY link status.
> > + *
> > + * Returns 0 if the information was read successfully or a negative error code
> > + * on failure.
> > + */
> > +int drm_dp_dpcd_read_phy_link_status(struct drm_dp_aux *aux,
> > +				     enum drm_dp_phy dp_phy,
> > +				     u8 link_status[DP_LINK_STATUS_SIZE])
> > +{
> > +	u8 lttpr_status[DP_LINK_STATUS_SIZE - 1];
> > +	int ret;
> > +
> > +	if (dp_phy == DP_PHY_DPRX) {
> > +		ret = drm_dp_dpcd_read(aux,
> > +				       DP_LANE0_1_STATUS,
> > +				       link_status,
> > +				       DP_LINK_STATUS_SIZE);
> > +
> > +		if (ret < 0)
> > +			return ret;
> > +
> > +		WARN_ON(ret != DP_LINK_STATUS_SIZE);
> > +
> > +		return 0;
> > +	}
> > +
> > +	ret = drm_dp_dpcd_read(aux,
> > +			       DP_LANE0_1_STATUS_PHY_REPEATER(dp_phy),
> > +			       lttpr_status,
> > +			       sizeof(lttpr_status));
> > +
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	WARN_ON(ret != sizeof(lttpr_status));
> > +
> > +#define link_reg(reg)	link_status[(reg) - DP_LANE0_1_STATUS]
> > +#define lttpr_reg(reg)	lttpr_status[(reg) - DP_LANE0_1_STATUS_PHY_REPEATER1]
> > +
> > +	/* Convert the LTTPR to the sink PHY link status layout */
> > +	link_reg(DP_LANE0_1_STATUS) = lttpr_reg(DP_LANE0_1_STATUS_PHY_REPEATER1);
> > +	link_reg(DP_LANE2_3_STATUS) = lttpr_reg(DP_LANE2_3_STATUS_PHY_REPEATER1);
> > +	link_reg(DP_LANE_ALIGN_STATUS_UPDATED) =
> > +		lttpr_reg(DP_LANE_ALIGN_STATUS_UPDATED_PHY_REPEATER1);
> > +	link_reg(DP_SINK_STATUS) = 0;
> > +	link_reg(DP_ADJUST_REQUEST_LANE0_1) =
> > +		lttpr_reg(DP_ADJUST_REQUEST_LANE0_1_PHY_REPEATER1);
> > +	link_reg(DP_ADJUST_REQUEST_LANE2_3) =
> > +		lttpr_reg(DP_ADJUST_REQUEST_LANE2_3_PHY_REPEATER1);
> > +
> > +#undef link_reg
> > +#undef lttpr_reg
> 
> Alternative might be to read to the target buffer directly
> and just memmove() the stuff around a bit. Would avoid having
> the second buffer on stack. But it's a small buffer so meh.

Yes, thought about using memmove, would be like

	memmove(&link_status[DP_SINK_STATUS - DP_LANE0_1_STATUS + 1],            
                &link_status[DP_SINK_STATUS - DP_LANE0_1_STATUS],                
                DP_LINK_STATUS_SIZE - DP_SINK_STATUS - 1);                       
        link_status[DP_SINK_STATUS - DP_LANE0_1_STATUS] = 0;

then thought that it's less clear what's going on, so decided writing it
out more explicitly. If you think that's not a concern I'll use memmove
instead.

> 
> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL(drm_dp_dpcd_read_phy_link_status);
> > +
> >  static bool is_edid_digital_input_dp(const struct edid *edid)
> >  {
> >  	return edid && edid->revision >= 4 &&
> > @@ -2098,6 +2187,153 @@ int drm_dp_dsc_sink_supported_input_bpcs(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_S
> >  }
> >  EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs);
> >  
> > +/**
> > + * drm_dp_read_lttpr_common_caps - read the LTTPR common capabilities
> > + * @aux: DisplayPort AUX channel
> > + * @caps: buffer to return the capability info in
> > + *
> > + * Read capabilities common to all LTTPRs.
> > + *
> > + * Returns 0 on success or a negative error code on failure.
> > + */
> > +int drm_dp_read_lttpr_common_caps(struct drm_dp_aux *aux,
> > +				  u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
> > +{
> > +	int ret;
> > +
> > +	ret = drm_dp_dpcd_read(aux,
> > +			       DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
> > +			       caps, DP_LTTPR_COMMON_CAP_SIZE);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	WARN_ON(ret != DP_LTTPR_COMMON_CAP_SIZE);
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL(drm_dp_read_lttpr_common_caps);
> > +
> > +/**
> > + * drm_dp_read_lttpr_phy_caps - read the capabilities for a given LTTPR PHY
> > + * @aux: DisplayPort AUX channel
> > + * @dp_phy: LTTPR PHY to read the capabilities for
> > + * @caps: buffer to return the capability info in
> > + *
> > + * Read the capabilities for the given LTTPR PHY.
> > + *
> > + * Returns 0 on success or a negative error code on failure.
> > + */
> > +int drm_dp_read_lttpr_phy_caps(struct drm_dp_aux *aux,
> > +			       enum drm_dp_phy dp_phy,
> > +			       u8 caps[DP_LTTPR_PHY_CAP_SIZE])
> > +{
> > +	int ret;
> > +
> > +	ret = drm_dp_dpcd_read(aux,
> > +			       DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER(dp_phy),
> > +			       caps, DP_LTTPR_PHY_CAP_SIZE);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	WARN_ON(ret != DP_LTTPR_PHY_CAP_SIZE);
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL(drm_dp_read_lttpr_phy_caps);
> > +
> > +static u8 dp_lttpr_common_cap(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE], int r)
> > +{
> > +	return caps[r - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
> > +}
> > +
> > +/**
> > + * drm_dp_lttpr_count - get the number of detected LTTPRs
> > + * @caps: LTTPR common capabilities
> > + *
> > + * Get the number of detected LTTPRs from the LTTPR common capabilities info.
> > + *
> > + * Returns:
> > + *   -ERANGE if more than supported number (8) of LTTPRs are detected
> > + *   -EINVAL if the DP_PHY_REPEATER_CNT register contains an invalid value
> > + *   otherwise the number of detected LTTPRs
> > + */
> > +int drm_dp_lttpr_count(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
> > +{
> > +	u8 count = dp_lttpr_common_cap(caps, DP_PHY_REPEATER_CNT);
> > +
> > +	switch (hweight8(count)) {
> > +	case 0:
> > +		return 0;
> > +	case 1:
> > +		return 8 - ilog2(count);
> > +	case 8:
> > +		return -ERANGE;
> > +	default:
> > +		return -EINVAL;
> > +	}
> > +}
> > +EXPORT_SYMBOL(drm_dp_lttpr_count);
> > +
> > +/**
> > + * drm_dp_lttpr_max_link_rate - get the maximum link rate supported by all LTTPRs
> > + * @caps: LTTPR common capabilities
> > + *
> > + * Returns the maximum link rate supported by all detected LTTPRs.
> > + */
> > +int drm_dp_lttpr_max_link_rate(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
> > +{
> > +	u8 rate = dp_lttpr_common_cap(caps, DP_MAX_LINK_RATE_PHY_REPEATER);
> > +
> > +	return drm_dp_bw_code_to_link_rate(rate);
> > +}
> > +EXPORT_SYMBOL(drm_dp_lttpr_max_link_rate);
> > +
> > +/**
> > + * drm_dp_lttpr_max_lane_count - get the maximum lane count supported by all LTTPRs
> > + * @caps: LTTPR common capabilities
> > + *
> > + * Returns the maximum lane count supported by all detected LTTPRs.
> > + */
> > +int drm_dp_lttpr_max_lane_count(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE])
> > +{
> > +	u8 max_lanes = dp_lttpr_common_cap(caps, DP_MAX_LANE_COUNT_PHY_REPEATER);
> > +
> > +	return max_lanes & DP_MAX_LANE_COUNT_MASK;
> > +}
> > +EXPORT_SYMBOL(drm_dp_lttpr_max_lane_count);
> > +
> > +/**
> > + * drm_dp_lttpr_voltage_swing_level_3_supported - check for LTTPR vswing3 support
> > + * @caps: LTTPR PHY capabilities
> > + *
> > + * Returns true if the @caps for an LTTPR TX PHY indicate support for
> > + * voltage swing level 3.
> > + */
> > +bool
> > +drm_dp_lttpr_voltage_swing_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE])
> > +{
> > +	u8 txcap = dp_lttpr_phy_cap(caps, DP_TRANSMITTER_CAPABILITY_PHY_REPEATER1);
> > +
> > +	return txcap & DP_VOLTAGE_SWING_LEVEL_3_SUPPORTED;
> > +}
> > +EXPORT_SYMBOL(drm_dp_lttpr_voltage_swing_level_3_supported);
> > +
> > +/**
> > + * drm_dp_lttpr_pre_emphasis_level_3_supported - check for LTTPR preemph3 support
> > + * @caps: LTTPR PHY capabilities
> > + *
> > + * Returns true if the @caps for an LTTPR TX PHY indicate support for
> > + * pre-emphasis level 3.
> > + */
> > +bool
> > +drm_dp_lttpr_pre_emphasis_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE])
> > +{
> > +	u8 txcap = dp_lttpr_phy_cap(caps, DP_TRANSMITTER_CAPABILITY_PHY_REPEATER1);
> > +
> > +	return txcap & DP_PRE_EMPHASIS_LEVEL_3_SUPPORTED;
> > +}
> > +EXPORT_SYMBOL(drm_dp_lttpr_pre_emphasis_level_3_supported);
> > +
> >  /**
> >   * drm_dp_get_phy_test_pattern() - get the requested pattern from the sink.
> >   * @aux: DisplayPort AUX channel
> > diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> > index e144b4b9d79a..42b6ab14920a 100644
> > --- a/include/drm/drm_dp_helper.h
> > +++ b/include/drm/drm_dp_helper.h
> > @@ -1118,15 +1118,58 @@ struct drm_device;
> >  #define DP_MAX_LANE_COUNT_PHY_REPEATER			    0xf0004 /* 1.4a */
> >  #define DP_Repeater_FEC_CAPABILITY			    0xf0004 /* 1.4 */
> >  #define DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT		    0xf0005 /* 1.4a */
> > +
> > +enum drm_dp_phy {
> > +	DP_PHY_DPRX,
> > +
> > +	DP_PHY_LTTPR1,
> > +	DP_PHY_LTTPR2,
> > +	DP_PHY_LTTPR3,
> > +	DP_PHY_LTTPR4,
> > +	DP_PHY_LTTPR5,
> > +	DP_PHY_LTTPR6,
> > +	DP_PHY_LTTPR7,
> > +	DP_PHY_LTTPR8,
> > +
> > +	DP_MAX_LTTPR_COUNT = DP_PHY_LTTPR8,
> > +};
> > +
> > +#define DP_PHY_LTTPR(i)					    (DP_PHY_LTTPR1 + (i))
> > +
> > +#define __DP_LTTPR1_BASE				    0xf0010 /* 1.3 */
> > +#define __DP_LTTPR2_BASE				    0xf0060 /* 1.3 */
> > +#define DP_LTTPR_BASE(dp_phy) \
> > +	(__DP_LTTPR1_BASE + (__DP_LTTPR2_BASE - __DP_LTTPR1_BASE) * \
> > +		((dp_phy) - DP_PHY_LTTPR1))
> > +
> > +#define DP_LTTPR_REG(dp_phy, lttpr1_reg) \
> > +	(DP_LTTPR_BASE(dp_phy) - DP_LTTPR_BASE(DP_PHY_LTTPR1) + (lttpr1_reg))
> > +
> >  #define DP_TRAINING_PATTERN_SET_PHY_REPEATER1		    0xf0010 /* 1.3 */
> > +#define DP_TRAINING_PATTERN_SET_PHY_REPEATER(dp_phy) \
> > +	DP_LTTPR_REG(dp_phy, DP_TRAINING_PATTERN_SET_PHY_REPEATER1)
> > +
> >  #define DP_TRAINING_LANE0_SET_PHY_REPEATER1		    0xf0011 /* 1.3 */
> > +#define DP_TRAINING_LANE0_SET_PHY_REPEATER(dp_phy) \
> > +	DP_LTTPR_REG(dp_phy, DP_TRAINING_LANE0_SET_PHY_REPEATER1)
> > +
> >  #define DP_TRAINING_LANE1_SET_PHY_REPEATER1		    0xf0012 /* 1.3 */
> >  #define DP_TRAINING_LANE2_SET_PHY_REPEATER1		    0xf0013 /* 1.3 */
> >  #define DP_TRAINING_LANE3_SET_PHY_REPEATER1		    0xf0014 /* 1.3 */
> >  #define DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1	    0xf0020 /* 1.4a */
> > +#define DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER(dp_phy)	\
> > +	DP_LTTPR_REG(dp_phy, DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1)
> > +
> >  #define DP_TRANSMITTER_CAPABILITY_PHY_REPEATER1		    0xf0021 /* 1.4a */
> > +# define DP_VOLTAGE_SWING_LEVEL_3_SUPPORTED		    BIT(0)
> > +# define DP_PRE_EMPHASIS_LEVEL_3_SUPPORTED		    BIT(1)
> > +
> >  #define DP_LANE0_1_STATUS_PHY_REPEATER1			    0xf0030 /* 1.3 */
> > +#define DP_LANE0_1_STATUS_PHY_REPEATER(dp_phy) \
> > +	DP_LTTPR_REG(dp_phy, DP_LANE0_1_STATUS_PHY_REPEATER1)
> > +
> >  #define DP_LANE2_3_STATUS_PHY_REPEATER1			    0xf0031 /* 1.3 */
> > +
> >  #define DP_LANE_ALIGN_STATUS_UPDATED_PHY_REPEATER1	    0xf0032 /* 1.3 */
> >  #define DP_ADJUST_REQUEST_LANE0_1_PHY_REPEATER1		    0xf0033 /* 1.3 */
> >  #define DP_ADJUST_REQUEST_LANE2_3_PHY_REPEATER1		    0xf0034 /* 1.3 */
> > @@ -1236,9 +1279,13 @@ u8 drm_dp_get_adjust_request_post_cursor(const u8 link_status[DP_LINK_STATUS_SIZ
> >  #define DP_DSC_RECEIVER_CAP_SIZE        0xf
> >  #define EDP_PSR_RECEIVER_CAP_SIZE	2
> >  #define EDP_DISPLAY_CTL_CAP_SIZE	3
> > +#define DP_LTTPR_COMMON_CAP_SIZE	8
> > +#define DP_LTTPR_PHY_CAP_SIZE		3
> >  
> >  void drm_dp_link_train_clock_recovery_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]);
> > +void drm_dp_lttpr_link_train_clock_recovery_delay(void);
> >  void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]);
> > +void drm_dp_lttpr_link_train_channel_eq_delay(const u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
> >  
> >  u8 drm_dp_link_rate_to_bw_code(int link_rate);
> >  int drm_dp_bw_code_to_link_rate(u8 link_bw);
> > @@ -1697,6 +1744,10 @@ int drm_dp_read_dpcd_caps(struct drm_dp_aux *aux,
> >  int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
> >  				 u8 status[DP_LINK_STATUS_SIZE]);
> >  
> > +int drm_dp_dpcd_read_phy_link_status(struct drm_dp_aux *aux,
> > +				     enum drm_dp_phy dp_phy,
> > +				     u8 link_status[DP_LINK_STATUS_SIZE]);
> > +
> >  bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux,
> >  				    u8 real_edid_checksum);
> >  
> > @@ -1746,6 +1797,17 @@ bool drm_dp_read_sink_count_cap(struct drm_connector *connector,
> >  				const struct drm_dp_desc *desc);
> >  int drm_dp_read_sink_count(struct drm_dp_aux *aux);
> >  
> > +int drm_dp_read_lttpr_common_caps(struct drm_dp_aux *aux,
> > +				  u8 caps[DP_LTTPR_COMMON_CAP_SIZE]);
> > +int drm_dp_read_lttpr_phy_caps(struct drm_dp_aux *aux,
> > +			       enum drm_dp_phy dp_phy,
> > +			       u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
> > +int drm_dp_lttpr_count(const u8 cap[DP_LTTPR_COMMON_CAP_SIZE]);
> > +int drm_dp_lttpr_max_link_rate(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE]);
> > +int drm_dp_lttpr_max_lane_count(const u8 caps[DP_LTTPR_COMMON_CAP_SIZE]);
> > +bool drm_dp_lttpr_voltage_swing_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
> > +bool drm_dp_lttpr_pre_emphasis_level_3_supported(const u8 caps[DP_LTTPR_PHY_CAP_SIZE]);
> > +
> >  void drm_dp_remote_aux_init(struct drm_dp_aux *aux);
> >  void drm_dp_aux_init(struct drm_dp_aux *aux);
> >  int drm_dp_aux_register(struct drm_dp_aux *aux);
> > -- 
> > 2.25.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] 19+ messages in thread

end of thread, other threads:[~2020-09-25 16:51 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-24 18:47 [PATCH v2 0/6] drm/i915: Add support for LTTPR non-transparent link training mode Imre Deak
2020-09-24 18:47 ` [Intel-gfx] " Imre Deak
2020-09-24 18:48 ` [Intel-gfx] [PATCH v2 1/6] drm/i915: Fix DP link training pattern mask Imre Deak
2020-09-24 18:48 ` [Intel-gfx] [PATCH v2 2/6] drm/i915: Simplify the link training functions Imre Deak
2020-09-24 18:48 ` [Intel-gfx] [PATCH v2 3/6] drm/i915: Factor out a helper to disable the DPCD training pattern Imre Deak
2020-09-24 18:57   ` Ville Syrjälä
2020-09-24 18:48 ` [PATCH v2 4/6] drm/dp: Add LTTPR helpers Imre Deak
2020-09-24 18:48   ` [Intel-gfx] " Imre Deak
2020-09-25 16:02   ` Ville Syrjälä
2020-09-25 16:02     ` [Intel-gfx] " Ville Syrjälä
2020-09-25 16:51     ` Imre Deak
2020-09-25 16:51       ` [Intel-gfx] " Imre Deak
2020-09-24 18:48 ` [Intel-gfx] [PATCH v2 5/6] drm/i915: Switch to LTTPR transparent mode link training Imre Deak
2020-09-25 16:03   ` Ville Syrjälä
2020-09-25 16:40     ` Imre Deak
2020-09-24 18:48 ` [Intel-gfx] [PATCH v2 6/6] drm/i915: Switch to LTTPR non-transparent " Imre Deak
2020-09-24 22:01 ` [Intel-gfx] ✗ Fi.CI.SPARSE: warning for drm/i915: Add support for LTTPR non-transparent link training mode (rev2) Patchwork
2020-09-24 22:24 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
2020-09-25  3:13 ` [Intel-gfx] ✓ Fi.CI.IGT: " Patchwork

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.