[PATCH 17/44] drm/i915/hdmi: Introduce intel_hdmi_frl_level() for per-lane TxFFE

Ankit Nautiyal <[email protected]>
Newsgroups org.freedesktop.lists.intel-xe,org.freedesktop.lists.dri-devel,org.freedesktop.lists.intel-gfx
Message-ID <[email protected]>
From: Suraj Kandpal <[email protected]>

HDMI FRL link training tracks the TxFFE preset per lane: the sink
issues per-lane Ln(x)_LTP_req requests over SCDC and the source owns
an independent TxFFE counter for each lane.
The PHY HDMI FRL buf-trans table is laid out so that index 1 + 3*N
selects the normal-operation row for TxFFE level N.

Convert struct intel_hdmi.frl from a single link-wide ffe_level into
a per-lane ffe_level[4] array plus a max_ffe_level cap, and expose
intel_hdmi_frl_level(encoder, lane) which returns the buf-trans index
that the PHY set_signal_levels() callback should program for that
lane.

Wire it into intel_ddi_level(): on FRL the per-lane index is used,
TMDS keeps the existing intel_ddi_hdmi_level() VBT/default path.

No functional change yet: ffe_level[] is always zero, so
intel_hdmi_frl_level() returns the TxFFE0 row (index 1) on every
lane, matching pre-existing behaviour. The training-side updates
that drive ffe_level[] arrive in a follow-up patch.

Signed-off-by: Suraj Kandpal <[email protected]>
---
 drivers/gpu/drm/i915/display/intel_ddi.c      | 10 +++++---
 .../drm/i915/display/intel_display_types.h    |  3 ++-
 drivers/gpu/drm/i915/display/intel_hdmi.c     | 25 +++++++++++++++++--
 drivers/gpu/drm/i915/display/intel_hdmi.h     |  2 ++
 4 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index d6e7e7863d36..d1a60cdf55fa 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -1517,11 +1517,15 @@ int intel_ddi_level(struct intel_encoder *encoder,
 	if (drm_WARN_ON_ONCE(display->drm, !trans))
 		return 0;
 
-	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
-		level = intel_ddi_hdmi_level(encoder, trans);
-	else
+	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
+		if (intel_hdmi_is_frl(crtc_state->port_clock))
+			level = intel_hdmi_frl_level(encoder, lane);
+		else
+			level = intel_ddi_hdmi_level(encoder, trans);
+	} else {
 		level = intel_ddi_dp_level(enc_to_intel_dp(encoder), crtc_state,
 					   lane);
+	}
 
 	if (drm_WARN_ON_ONCE(display->drm, level >= n_entries))
 		level = n_entries - 1;
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 00775ad9019c..942dbad802a6 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1722,9 +1722,10 @@ struct intel_hdmi {
 		bool trained;
 		int lanes;
 		int rate_gbps;
-		int ffe_level;
 		int rate_cap;
 		bool reset_rate_cap;
+		u8 max_ffe_level;
+		u8 ffe_level[4];
 	} frl;
 };
 
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 2b0cdb0719e2..ba1543023373 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2554,7 +2554,27 @@ intel_hdmi_reset_frl_config(struct intel_hdmi *intel_hdmi)
 	intel_hdmi->frl.trained = false;
 	intel_hdmi->frl.lanes = 0;
 	intel_hdmi->frl.rate_gbps = 0;
-	intel_hdmi->frl.ffe_level = 0;
+	intel_hdmi->frl.max_ffe_level = 0;
+	memset(intel_hdmi->frl.ffe_level, 0, sizeof(intel_hdmi->frl.ffe_level));
+}
+
+/*
+ * HDMI FRL training level is encoded as follows:
+ *   i 0      : No FFE (LTP4 test mode)
+ *   i 1+3*N  : TxFFE N normal operation (N = 0..3)
+ *   i 1+3*N+1: TxFFE N de-emphasis only (LTP4 test mode)
+ *   i 1+3*N+2: TxFFE N pre-shoot only  (LTP4 test mode)
+ *
+ * Normal operation returns 1 + 3 * ffe_level[lane].
+ */
+int intel_hdmi_frl_level(struct intel_encoder *encoder, int lane)
+{
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+
+	if (lane < 0 || lane >= ARRAY_SIZE(intel_hdmi->frl.ffe_level))
+		return 1;
+
+	return 1 + 3 * intel_hdmi->frl.ffe_level[lane];
 }
 
 static void
@@ -3763,6 +3783,7 @@ int intel_hdmi_start_frl(struct intel_encoder *encoder,
 	}
 
 	intel_hdmi_reset_frl_config(intel_hdmi);
+	intel_hdmi->frl.max_ffe_level = ffe_level;
 
 	if (!intel_hdmi_frl_prepare_lts2(encoder,
 					 crtc_state->frl.required_rate,
@@ -3776,7 +3797,7 @@ int intel_hdmi_start_frl(struct intel_encoder *encoder,
 	case FRL_TRAINING_PASSED:
 		intel_hdmi->frl.trained = true;
 		intel_hdmi->frl.rate_gbps = req_rate;
-		intel_hdmi->frl.ffe_level = ffe_level;
+		intel_hdmi->frl.max_ffe_level = ffe_level;
 		drm_dbg_kms(display->drm,
 			    "[CONNECTOR:%d:%s] FRL Training Passed with rate=%d\n",
 			    connector->base.id, connector->name,
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.h b/drivers/gpu/drm/i915/display/intel_hdmi.h
index 59a561ad28e0..5baa38d326e5 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.h
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.h
@@ -68,6 +68,8 @@ int intel_hdmi_start_frl(struct intel_encoder *encoder,
 			 const struct intel_crtc_state *crtc_state);
 void intel_hdmi_disable_frl(struct intel_encoder *encoder,
 			    const struct intel_crtc_state *crtc_state);
+void intel_hdmi_prepare_for_frl_mode(const struct intel_crtc_state *crtc_state);
+int intel_hdmi_frl_level(struct intel_encoder *encoder, int lane);
 void hsw_write_infoframe(struct intel_encoder *encoder,
 			 const struct intel_crtc_state *crtc_state,
 			 unsigned int type,
-- 
2.50.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.