Intel-GFX Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] drm/i915/dp: Avoid YCbCr420 on HDMI2.1 PCONs due to the TMDS CLK limit
@ 2026-11-11  4:06 Xiao Lu
  2026-11-11  4:37 ` sashiko-bot
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Xiao Lu @ 2026-11-11  4:06 UTC (permalink / raw)
  To: intel-gfx, intel-xe
  Cc: jani.nikula, rodrigo.vivi, ville.syrjala, imre.deak, Xiao Lu

When the DP->HDMI PCON drives an HDMI 2.1 sink using FRL, the sink's
max TMDS clock is irrelevant: the HDMI link doesn't carry a TMDS clock
at all. However intel_dp_hdmi_compute_bpc() always compares the TMDS
clock against the EDID/DPCD max TMDS clock when the downstream limits
are respected.

For a 4k120 sink behind a PCON with a 600 MHz max TMDS clock this makes
RGB 8bpc (1188 MHz) fail, so intel_dp_max_bpp() returns 0 for RGB.
YCbCr 4:2:0 halves the TMDS clock to 594 MHz and passes, so the driver
ends up sending 4:2:0 to the sink (using DSC to fit the DP link), even
though the FRL link has plenty of bandwidth for RGB.

Check the FRL bandwidth instead when the PCON will use FRL, i.e. when
it supports source control mode and the sink is HDMI 2.1, limited by
the lower of the PCON and sink max FRL rate. Account for the 16b/18b
FRL encoding overhead so that higher bpc values that don't fit are
still rejected. The TMDS clock check is unchanged for TMDS links.

intel_dp_mode_valid_downstream() already checked the FRL bandwidth, but
with a different set of conditions and without the encoding overhead.
Use the same helper there so that the mode list and the bpc/format
selection agree. As a result:

- Modes that need more than the lower of the PCON and sink max FRL rate
  are no longer listed, even if they fit the PCON max FRL rate.
- If the PCON won't use FRL (e.g. an HDMI 2.0 sink), the TMDS limits are
  applied to the mode list instead of the FRL bandwidth. RGB-only modes
  above the max TMDS clock are no longer listed.
- Modes that were previously capped to 8bpc by the TMDS clock limit can
  now use a higher bpc, up to what the sink, the PCON and the FRL
  bandwidth allow.

Signed-off-by: Xiao Lu <xiaolu.xie@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c | 84 ++++++++++++++++---------
 1 file changed, 56 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index ef164a797..1b8cb934a 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1154,6 +1154,40 @@ static int intel_dp_max_tmds_clock(struct intel_dp *intel_dp)
 	return max_tmds_clock;
 }
 
+static bool intel_dp_is_hdmi_2_1_sink(struct intel_dp *intel_dp);
+static int intel_dp_hdmi_sink_max_frl(struct intel_dp *intel_dp);
+
+static int frl_required_bw(int clock, int bpc,
+			   enum intel_output_format sink_format)
+{
+	if (sink_format == INTEL_OUTPUT_FORMAT_YCBCR420)
+		clock /= 2;
+
+	return clock * bpc * 3;
+}
+
+/* Max HDMI FRL rate in Gbps if the PCON will use FRL to the sink, 0 for TMDS */
+static int intel_dp_hdmi_frl_max_bw(struct intel_dp *intel_dp)
+{
+	if (!(intel_dp->downstream_ports[2] & DP_PCON_SOURCE_CTL_MODE) ||
+	    !intel_dp_is_hdmi_2_1_sink(intel_dp))
+		return 0;
+
+	return min(intel_dp->dfp.pcon_max_frl_bw,
+		   intel_dp_hdmi_sink_max_frl(intel_dp));
+}
+
+/* Check the pixel data fits the FRL link, including the 16b/18b encoding overhead */
+static enum drm_mode_status
+intel_dp_frl_bw_valid(int max_frl_bw, int clock, int bpc,
+		      enum intel_output_format sink_format)
+{
+	u64 required_bw = (u64)frl_required_bw(clock, bpc, sink_format) * 18;
+	u64 available_bw = (u64)max_frl_bw * 1000000 * 16;
+
+	return required_bw > available_bw ? MODE_CLOCK_HIGH : MODE_OK;
+}
+
 static enum drm_mode_status
 intel_dp_tmds_clock_valid(struct intel_dp *intel_dp,
 			  int clock, int bpc,
@@ -1179,15 +1213,6 @@ intel_dp_tmds_clock_valid(struct intel_dp *intel_dp,
 	return MODE_OK;
 }
 
-static int frl_required_bw(int clock, int bpc,
-			   enum intel_output_format sink_format)
-{
-	if (sink_format == INTEL_OUTPUT_FORMAT_YCBCR420)
-		clock /= 2;
-
-	return clock * bpc * 3;
-}
-
 static enum drm_mode_status
 intel_dp_mode_valid_downstream(struct intel_connector *connector,
 			       const struct drm_display_mode *mode,
@@ -1195,23 +1220,14 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector,
 			       enum intel_output_format sink_format)
 {
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
+	int max_frl_bw;
 
-	/* If PCON supports FRL MODE, check FRL bandwidth constraints */
-	if (intel_dp->dfp.pcon_max_frl_bw) {
-		int target_bw, max_frl_bw;
-
+	/* If the PCON will use FRL, check FRL bandwidth constraints */
+	max_frl_bw = intel_dp_hdmi_frl_max_bw(intel_dp);
+	if (max_frl_bw) {
 		/* Assume 8bpc for the FRL bandwidth check */
-		target_bw = frl_required_bw(target_clock, 8, sink_format);
-
-		max_frl_bw = intel_dp->dfp.pcon_max_frl_bw;
-
-		/* converting bw from Gbps to Kbps*/
-		max_frl_bw = max_frl_bw * 1000000;
-
-		if (target_bw > max_frl_bw)
-			return MODE_CLOCK_HIGH;
-
-		return MODE_OK;
+		return intel_dp_frl_bw_valid(max_frl_bw, target_clock, 8,
+					     sink_format);
 	}
 
 	if (intel_dp->dfp.max_dotclock &&
@@ -1728,6 +1744,8 @@ static int intel_dp_hdmi_compute_bpc(struct intel_dp *intel_dp,
 				     int bpc, bool respect_downstream_limits)
 {
 	int clock = crtc_state->hw.adjusted_mode.crtc_clock;
+	int max_frl_bw = intel_dp_hdmi_frl_max_bw(intel_dp);
+	enum drm_mode_status status;
 
 	/*
 	 * Current bpc could already be below 8bpc due to
@@ -1745,10 +1763,20 @@ static int intel_dp_hdmi_compute_bpc(struct intel_dp *intel_dp,
 		bpc = 8;
 
 	for (; bpc >= 8; bpc -= 2) {
-		if (intel_hdmi_bpc_possible(crtc_state, bpc,
-					    intel_dp_has_hdmi_sink(intel_dp)) &&
-		    intel_dp_tmds_clock_valid(intel_dp, clock, bpc, crtc_state->sink_format,
-					      respect_downstream_limits) == MODE_OK)
+		if (!intel_hdmi_bpc_possible(crtc_state, bpc,
+					     intel_dp_has_hdmi_sink(intel_dp)))
+			continue;
+
+		/* The TMDS clock limits don't apply when the PCON uses FRL */
+		if (max_frl_bw && respect_downstream_limits)
+			status = intel_dp_frl_bw_valid(max_frl_bw, clock, bpc,
+						       crtc_state->sink_format);
+		else
+			status = intel_dp_tmds_clock_valid(intel_dp, clock, bpc,
+							   crtc_state->sink_format,
+							   respect_downstream_limits);
+
+		if (status == MODE_OK)
 			return bpc;
 	}
 
-- 
2.43.0


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

end of thread, other threads:[~2026-11-12  5:50 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-11  4:06 [PATCH] drm/i915/dp: Avoid YCbCr420 on HDMI2.1 PCONs due to the TMDS CLK limit Xiao Lu
2026-11-11  4:37 ` sashiko-bot
2026-11-11  5:05 ` [PATCH v2] " Xiao Lu
2026-11-12  5:48   ` Xiao Lu
2026-11-11  5:06 ` ✓ i915.CI.BAT: success for " Patchwork
2026-11-11  6:31 ` ✓ i915.CI.BAT: success for drm/i915/dp: Avoid YCbCr420 on HDMI2.1 PCONs due to the TMDS CLK limit (rev2) Patchwork
2026-11-11 15:38 ` ✗ i915.CI.Full: failure " Patchwork

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox