[PATCH 2/2] drm/i915/dp: Add kernel param to limit eDP rate to HBR2"

Ankit Nautiyal ankit.k.nautiyal at intel.com
Mon Jun 2 09:45:09 UTC 2025


Some ICL+ platforms with combo PHY ports can theoretically support HBR3,
but in practice, signal integrity issues may prevent stable operation.
While some systems include a Parade PS8461 mux chip to mitigate jitter and
enable HBR3, there is no reliable way to detect its presence.
Additionally, many systems have broken or missing VBT entries, making it
unsafe to rely on VBT for link rate limits.

To address this, introduce a new kernel parameter i915.limit_edp_hbr2.
When set, this parameter forces the eDP link rate to be capped at
HBR2 (540000 kHz), overriding any higher advertised rates from the sink or
DPCD. By default, the higher rates will be allowed, i.e. the parameter
will be set to false.

This provides a manual override for users and OEMs to ensure stable eDP
operation on affected platforms.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal at intel.com>
---
 .../drm/i915/display/intel_display_params.h   |  1 +
 drivers/gpu/drm/i915/display/intel_dp.c       | 50 ++++++++++++++++---
 2 files changed, 44 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_params.h b/drivers/gpu/drm/i915/display/intel_display_params.h
index 5317138e6044..f7ba9805f97f 100644
--- a/drivers/gpu/drm/i915/display/intel_display_params.h
+++ b/drivers/gpu/drm/i915/display/intel_display_params.h
@@ -48,6 +48,7 @@ struct drm_printer;
 	param(bool, psr_safest_params, false, 0400) \
 	param(bool, enable_psr2_sel_fetch, true, 0400) \
 	param(int, enable_dmc_wl, -1, 0400) \
+	param(bool, limit_edp_hbr2, false, 0400) \
 
 #define MEMBER(T, member, ...) T member;
 struct intel_display_params {
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 2a0b76ae33cd..4ba5b1a1d283 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -174,10 +174,29 @@ int intel_dp_link_symbol_clock(int rate)
 
 static int max_dprx_rate(struct intel_dp *intel_dp)
 {
+	struct intel_display *display = to_intel_display(intel_dp);
+	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
+	int max_rate;
+
 	if (intel_dp_tunnel_bw_alloc_is_enabled(intel_dp))
-		return drm_dp_tunnel_max_dprx_rate(intel_dp->tunnel);
+		max_rate = drm_dp_tunnel_max_dprx_rate(intel_dp->tunnel);
+	else
+		max_rate = drm_dp_bw_code_to_link_rate(intel_dp->dpcd[DP_MAX_LINK_RATE]);
 
-	return drm_dp_bw_code_to_link_rate(intel_dp->dpcd[DP_MAX_LINK_RATE]);
+	/*
+	 * Some platforms with combo PHY ports may not reliably support HBR3
+	 * due to signal integrity limitations, despite advertising it.
+	 * If the kernel parameter `i915.limit_edp_hbr2` is set, cap the link
+	 * rate to HBR2 to avoid unstable configurations.
+	 */
+	if (max_rate >= 810000 && display->params.limit_edp_hbr2) {
+		drm_dbg_kms(display->drm,
+			    "[ENCODER:%d:%s] Forcing max link rate to HBR2 due to limit_edp_hbr2 set\n",
+			    encoder->base.base.id, encoder->base.name);
+		max_rate = 540000;
+	}
+
+	return max_rate;
 }
 
 static int max_dprx_lane_count(struct intel_dp *intel_dp)
@@ -4253,6 +4272,9 @@ static void intel_edp_mso_init(struct intel_dp *intel_dp)
 static void
 intel_edp_set_sink_rates(struct intel_dp *intel_dp)
 {
+	struct intel_display *display = to_intel_display(intel_dp);
+	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
+
 	intel_dp->num_sink_rates = 0;
 
 	if (intel_dp->edp_dpcd[0] >= DP_EDP_14) {
@@ -4263,10 +4285,7 @@ intel_edp_set_sink_rates(struct intel_dp *intel_dp)
 				 sink_rates, sizeof(sink_rates));
 
 		for (i = 0; i < ARRAY_SIZE(sink_rates); i++) {
-			int val = le16_to_cpu(sink_rates[i]);
-
-			if (val == 0)
-				break;
+			int rate;
 
 			/* Value read multiplied by 200kHz gives the per-lane
 			 * link rate in kHz. The source rates are, however,
@@ -4274,7 +4293,24 @@ intel_edp_set_sink_rates(struct intel_dp *intel_dp)
 			 * back to symbols is
 			 * (val * 200kHz)*(8/10 ch. encoding)*(1/8 bit to Byte)
 			 */
-			intel_dp->sink_rates[i] = (val * 200) / 10;
+			rate = le16_to_cpu(sink_rates[i]) * 200 / 10;
+
+			if (rate == 0)
+				break;
+
+			/*
+			 * Some platforms cannot reliably drive HBR3 rates due to PHY limitations,
+			 * even if the sink advertises support. If i915.limit_edp_hbr2 is set,
+			 * reject any sink rates above HBR2 to ensure stable operation.
+			 */
+			if (rate >= 810000 && display->params.limit_edp_hbr2) {
+				drm_dbg_kms(display->drm,
+					    "[ENCODER:%d:%s] Limit the rate to HBR2 due to limit_edp_hbr2 param\n",
+					    encoder->base.base.id, encoder->base.name);
+				break;
+			}
+
+			intel_dp->sink_rates[i] = rate;
 		}
 		intel_dp->num_sink_rates = i;
 	}
-- 
2.45.2



More information about the Intel-gfx-trybot mailing list