public inbox for intel-gfx@lists.freedesktop.org
 help / color / mirror / Atom feed
* [PATCH 00/14] Account for DSC bubble overhead for horizontal slices
@ 2026-01-21  3:53 Ankit Nautiyal
  2026-01-21  3:53 ` [PATCH 01/14] drm/i915/dp: Early reject bad hdisplay in intel_dp_mode_valid Ankit Nautiyal
                   ` (14 more replies)
  0 siblings, 15 replies; 28+ messages in thread
From: Ankit Nautiyal @ 2026-01-21  3:53 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: imre.deak, Ankit Nautiyal

When DSC is enabled on a pipe, the pipe pixel rate input to cdclk frequency
and pipe joiner calculations needs to be adjusted to account for
compression overhead: specifically, the "bubbles" added at each horizontal
slice boundary. This overhead has always existed, even on earlier
platforms, but was not previously accounted for.

Currently, the number of joined pipes is computed much earlier than the
decision to use DSC: both during the mode_valid phase for each mode and in
the compute_config phase for a given mode. As a result, the DSC bubble
overhead cannot be considered when determining the number of pipes to join,
which may lead to incorrect configurations.

This series refactors the sequence of steps used to determine the number of
pipes to be joined and the DSC policy. The first few patches restructure
the mode_valid and compute config logic to make room for DSC bubble
overhead accounting. With these, we iterate over joiner candidates and
select the minimal joiner configuration that satisfies the
mode-requirements. The later patches introduce the actual overhead
adjustment and use it for: the minimum cdclk requirements with DSC,
SST mode_valid logic, and SST/MST compute_config logic.

Rev 2:
 - Refactor joiner computation for compute config.
 - Refactor DSC BW calculation.
 - Add overhead for SST/MST compute config phase for recomputing joiner
   requirements for DSC.
 - NOTE:
   - For Patch#7 (drm/i915/dp: Rework pipe joiner logic in mode_valid)
     git diff = --patience is used for better readability.

Rev 3:
 - Use diff = --patience in format-patch for better readability.
 - Add a macro to iterate over the joiner candidates.
 - Add a separate helper to check pixel rate against dotclock limit.
 - Add patch from Chaitanya for additional platform specific
   limitations [1].

[1] https://patchwork.freedesktop.org/patch/661952/?series=151047&rev=1

Ankit Nautiyal (13):
  drm/i915/dp: Early reject bad hdisplay in intel_dp_mode_valid
  drm/i915/dp: Move num_joined_pipes and related checks together
  drm/i915/dp: Extract helper to get the hdisplay limit
  drm/i915/dp: Rework pipe joiner logic in mode_valid
  drm/i915/dp: Rework pipe joiner logic in compute_config
  drm/i915/dp_mst: Move the check for dotclock at the end
  drm/i915/dp_mst: Move the joiner dependent code together
  drm/i915/dp_mst: Rework pipe joiner logic in mode_valid
  drm/i915/dp_mst: Extract helper to compute link for given joiner
    config
  drm/i915/dp_mst: Rework pipe joiner logic in compute_config
  drm/i915/dp: Introduce helper to check pixel rate against dotclock
    limits
  drm/i915/dp: Refactor dsc_slice_count handling in
    intel_dp_mode_valid()
  drm/i915/dp: Account for DSC slice overhead

Chaitanya Kumar Borah (1):
  drm/i915/display: Add upper limit check for pixel clock

 drivers/gpu/drm/i915/display/intel_display.c |  12 +
 drivers/gpu/drm/i915/display/intel_display.h |   1 +
 drivers/gpu/drm/i915/display/intel_dp.c      | 297 ++++++++++++++-----
 drivers/gpu/drm/i915/display/intel_dp.h      |  13 +
 drivers/gpu/drm/i915/display/intel_dp_mst.c  | 217 ++++++++++----
 drivers/gpu/drm/i915/display/intel_vdsc.c    |   1 -
 drivers/gpu/drm/i915/display/intel_vdsc.h    |   3 +
 7 files changed, 402 insertions(+), 142 deletions(-)

-- 
2.45.2


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

* [PATCH 01/14] drm/i915/dp: Early reject bad hdisplay in intel_dp_mode_valid
  2026-01-21  3:53 [PATCH 00/14] Account for DSC bubble overhead for horizontal slices Ankit Nautiyal
@ 2026-01-21  3:53 ` Ankit Nautiyal
  2026-01-23 18:06   ` Imre Deak
  2026-01-21  3:53 ` [PATCH 02/14] drm/i915/dp: Move num_joined_pipes and related checks together Ankit Nautiyal
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 28+ messages in thread
From: Ankit Nautiyal @ 2026-01-21  3:53 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: imre.deak, Ankit Nautiyal

Move check for bad hdisplay early as it is independent on other checks.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 79fd3b8d8b25..126da297efc5 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1460,6 +1460,9 @@ intel_dp_mode_valid(struct drm_connector *_connector,
 	if (mode->clock < 10000)
 		return MODE_CLOCK_LOW;
 
+	if (intel_dp_hdisplay_bad(display, mode->hdisplay))
+		return MODE_H_ILLEGAL;
+
 	fixed_mode = intel_panel_fixed_mode(connector, mode);
 	if (intel_dp_is_edp(intel_dp) && fixed_mode) {
 		status = intel_panel_mode_valid(connector, mode);
@@ -1483,9 +1486,6 @@ intel_dp_mode_valid(struct drm_connector *_connector,
 	if (target_clock > max_dotclk)
 		return MODE_CLOCK_HIGH;
 
-	if (intel_dp_hdisplay_bad(display, mode->hdisplay))
-		return MODE_H_ILLEGAL;
-
 	max_link_clock = intel_dp_max_link_rate(intel_dp);
 	max_lanes = intel_dp_max_lane_count(intel_dp);
 
-- 
2.45.2


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

* [PATCH 02/14] drm/i915/dp: Move num_joined_pipes and related checks together
  2026-01-21  3:53 [PATCH 00/14] Account for DSC bubble overhead for horizontal slices Ankit Nautiyal
  2026-01-21  3:53 ` [PATCH 01/14] drm/i915/dp: Early reject bad hdisplay in intel_dp_mode_valid Ankit Nautiyal
@ 2026-01-21  3:53 ` Ankit Nautiyal
  2026-01-23 18:25   ` Imre Deak
  2026-01-21  3:53 ` [PATCH 03/14] drm/i915/dp: Extract helper to get the hdisplay limit Ankit Nautiyal
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 28+ messages in thread
From: Ankit Nautiyal @ 2026-01-21  3:53 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: imre.deak, Ankit Nautiyal

Move the calculation of `num_joined_pipes` and other constraints that
depend on it, into a single block.
This groups all joiner-dependent logic together, preparing the code for a
future loop-based evaluation of multiple joiner configurations.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c | 32 ++++++++++++-------------
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 126da297efc5..c0a8ffac6312 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1472,20 +1472,9 @@ intel_dp_mode_valid(struct drm_connector *_connector,
 		target_clock = fixed_mode->clock;
 	}
 
-	num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector,
-						     mode->hdisplay, target_clock);
-	max_dotclk *= num_joined_pipes;
-
 	sink_format = intel_dp_sink_format(connector, mode);
 	output_format = intel_dp_output_format(connector, sink_format);
 
-	status = intel_pfit_mode_valid(display, mode, output_format, num_joined_pipes);
-	if (status != MODE_OK)
-		return status;
-
-	if (target_clock > max_dotclk)
-		return MODE_CLOCK_HIGH;
-
 	max_link_clock = intel_dp_max_link_rate(intel_dp);
 	max_lanes = intel_dp_max_lane_count(intel_dp);
 
@@ -1496,6 +1485,17 @@ intel_dp_mode_valid(struct drm_connector *_connector,
 					   target_clock, mode->hdisplay,
 					   link_bpp_x16, 0);
 
+	num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector,
+						     mode->hdisplay, target_clock);
+	max_dotclk *= num_joined_pipes;
+
+	if (target_clock > max_dotclk)
+		return MODE_CLOCK_HIGH;
+
+	status = intel_pfit_mode_valid(display, mode, output_format, num_joined_pipes);
+	if (status != MODE_OK)
+		return status;
+
 	if (intel_dp_has_dsc(connector)) {
 		int pipe_bpp;
 
@@ -1538,14 +1538,14 @@ intel_dp_mode_valid(struct drm_connector *_connector,
 	if (intel_dp_joiner_needs_dsc(display, num_joined_pipes) && !dsc)
 		return MODE_CLOCK_HIGH;
 
+	status = intel_mode_valid_max_plane_size(display, mode, num_joined_pipes);
+	if (status != MODE_OK)
+		return status;
+
 	if (mode_rate > max_rate && !dsc)
 		return MODE_CLOCK_HIGH;
 
-	status = intel_dp_mode_valid_downstream(connector, mode, target_clock);
-	if (status != MODE_OK)
-		return status;
-
-	return intel_mode_valid_max_plane_size(display, mode, num_joined_pipes);
+	return intel_dp_mode_valid_downstream(connector, mode, target_clock);
 }
 
 bool intel_dp_source_supports_tps3(struct intel_display *display)
-- 
2.45.2


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

* [PATCH 03/14] drm/i915/dp: Extract helper to get the hdisplay limit
  2026-01-21  3:53 [PATCH 00/14] Account for DSC bubble overhead for horizontal slices Ankit Nautiyal
  2026-01-21  3:53 ` [PATCH 01/14] drm/i915/dp: Early reject bad hdisplay in intel_dp_mode_valid Ankit Nautiyal
  2026-01-21  3:53 ` [PATCH 02/14] drm/i915/dp: Move num_joined_pipes and related checks together Ankit Nautiyal
@ 2026-01-21  3:53 ` Ankit Nautiyal
  2026-01-23 18:28   ` Imre Deak
  2026-01-21  3:53 ` [PATCH 04/14] drm/i915/dp: Rework pipe joiner logic in mode_valid Ankit Nautiyal
                   ` (11 subsequent siblings)
  14 siblings, 1 reply; 28+ messages in thread
From: Ankit Nautiyal @ 2026-01-21  3:53 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: imre.deak, Ankit Nautiyal

Separate out function to get the hdisplay limit for a given platform.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index c0a8ffac6312..fc7d48460a52 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1371,6 +1371,12 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector,
 	return MODE_OK;
 }
 
+static
+int intel_dp_hdisplay_limit(struct intel_display *display)
+{
+	return DISPLAY_VER(display) >= 30 ? 6144 : 5120;
+}
+
 static
 bool intel_dp_needs_joiner(struct intel_dp *intel_dp,
 			   struct intel_connector *connector,
@@ -1378,17 +1384,14 @@ bool intel_dp_needs_joiner(struct intel_dp *intel_dp,
 			   int num_joined_pipes)
 {
 	struct intel_display *display = to_intel_display(intel_dp);
-	int hdisplay_limit;
 
 	if (!intel_dp_has_joiner(intel_dp))
 		return false;
 
 	num_joined_pipes /= 2;
 
-	hdisplay_limit = DISPLAY_VER(display) >= 30 ? 6144 : 5120;
-
 	return clock > num_joined_pipes * display->cdclk.max_dotclk_freq ||
-	       hdisplay > num_joined_pipes * hdisplay_limit;
+	       hdisplay > num_joined_pipes * intel_dp_hdisplay_limit(display);
 }
 
 int intel_dp_num_joined_pipes(struct intel_dp *intel_dp,
-- 
2.45.2


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

* [PATCH 04/14] drm/i915/dp: Rework pipe joiner logic in mode_valid
  2026-01-21  3:53 [PATCH 00/14] Account for DSC bubble overhead for horizontal slices Ankit Nautiyal
                   ` (2 preceding siblings ...)
  2026-01-21  3:53 ` [PATCH 03/14] drm/i915/dp: Extract helper to get the hdisplay limit Ankit Nautiyal
@ 2026-01-21  3:53 ` Ankit Nautiyal
  2026-01-21 10:54   ` Jani Nikula
  2026-01-21  3:53 ` [PATCH 05/14] drm/i915/dp: Rework pipe joiner logic in compute_config Ankit Nautiyal
                   ` (10 subsequent siblings)
  14 siblings, 1 reply; 28+ messages in thread
From: Ankit Nautiyal @ 2026-01-21  3:53 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: imre.deak, Ankit Nautiyal

Currently in intel_dp_mode_valid(), we compute the number of joined pipes
required before deciding whether DSC is needed. This ordering prevents us
from accounting for DSC-related overhead when determining pipe
requirements.

Refactor the logic to start with a single pipe and incrementally try
additional pipes only if needed. While DSC overhead is not yet computed
here, this restructuring prepares the code to support that in a follow-up
changes.

Additionally, if a forced joiner configuration is present, we first check
whether it satisfies the bandwidth and timing constraints. If it does not,
we fall back to evaluating configurations with 1, 2, or 4 pipes joined
and prune or keep the mode accordingly.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c | 144 +++++++++++++++---------
 drivers/gpu/drm/i915/display/intel_dp.h |   7 ++
 2 files changed, 96 insertions(+), 55 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index fc7d48460a52..02381f84fa58 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -107,6 +107,13 @@
 /* Constants for DP DSC configurations */
 static const u8 valid_dsc_bpp[] = {6, 8, 10, 12, 15};
 
+static const enum joiner_type joiner_candidates[] = {
+	FORCED_JOINER,
+	NO_JOINER,
+	BIG_JOINER,
+	ULTRA_JOINER,
+};
+
 /**
  * intel_dp_is_edp - is the given port attached to an eDP panel (either CPU or PCH)
  * @intel_dp: DP struct
@@ -1445,13 +1452,13 @@ intel_dp_mode_valid(struct drm_connector *_connector,
 	const struct drm_display_mode *fixed_mode;
 	int target_clock = mode->clock;
 	int max_rate, mode_rate, max_lanes, max_link_clock;
-	int max_dotclk = display->cdclk.max_dotclk_freq;
 	u16 dsc_max_compressed_bpp = 0;
 	u8 dsc_slice_count = 0;
 	enum drm_mode_status status;
 	bool dsc = false;
 	int num_joined_pipes;
 	int link_bpp_x16;
+	int i;
 
 	status = intel_cpu_transcoder_mode_valid(display, mode);
 	if (status != MODE_OK)
@@ -1488,67 +1495,94 @@ intel_dp_mode_valid(struct drm_connector *_connector,
 					   target_clock, mode->hdisplay,
 					   link_bpp_x16, 0);
 
-	num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector,
-						     mode->hdisplay, target_clock);
-	max_dotclk *= num_joined_pipes;
-
-	if (target_clock > max_dotclk)
-		return MODE_CLOCK_HIGH;
-
-	status = intel_pfit_mode_valid(display, mode, output_format, num_joined_pipes);
-	if (status != MODE_OK)
-		return status;
-
-	if (intel_dp_has_dsc(connector)) {
-		int pipe_bpp;
-
-		/*
-		 * TBD pass the connector BPC,
-		 * for now U8_MAX so that max BPC on that platform would be picked
-		 */
-		pipe_bpp = intel_dp_dsc_compute_max_bpp(connector, U8_MAX);
-
-		/*
-		 * Output bpp is stored in 6.4 format so right shift by 4 to get the
-		 * integer value since we support only integer values of bpp.
-		 */
-		if (intel_dp_is_edp(intel_dp)) {
-			dsc_max_compressed_bpp =
-				drm_edp_dsc_sink_output_bpp(connector->dp.dsc_dpcd) >> 4;
-
-			dsc_slice_count =
-				intel_dp_dsc_get_slice_count(connector,
-							     target_clock,
-							     mode->hdisplay,
-							     num_joined_pipes);
-
-			dsc = dsc_max_compressed_bpp && dsc_slice_count;
-		} else if (drm_dp_sink_supports_fec(connector->dp.fec_capability)) {
-			unsigned long bw_overhead_flags = 0;
-
-			if (!drm_dp_is_uhbr_rate(max_link_clock))
-				bw_overhead_flags |= DRM_DP_BW_OVERHEAD_FEC;
-
-			dsc = intel_dp_mode_valid_with_dsc(connector,
-							   max_link_clock, max_lanes,
-							   target_clock, mode->hdisplay,
-							   num_joined_pipes,
-							   output_format, pipe_bpp,
-							   bw_overhead_flags);
+	for (i = 0; i < ARRAY_SIZE(joiner_candidates); i++) {
+		int max_dotclk = display->cdclk.max_dotclk_freq;
+		enum joiner_type joiner = joiner_candidates[i];
+
+		status = MODE_CLOCK_HIGH;
+
+		if (joiner == FORCED_JOINER) {
+			if (!connector->force_joined_pipes)
+				continue;
+			num_joined_pipes = connector->force_joined_pipes;
+		} else {
+			num_joined_pipes = 1 << joiner;
+		}
+
+		if ((joiner >= NO_JOINER && !intel_dp_has_joiner(intel_dp)) ||
+		    (joiner == BIG_JOINER && !HAS_BIGJOINER(display)) ||
+		    (joiner == ULTRA_JOINER && !HAS_ULTRAJOINER(display)))
+			break;
+
+		if (mode->hdisplay > num_joined_pipes * intel_dp_hdisplay_limit(display))
+			continue;
+
+		status = intel_pfit_mode_valid(display, mode, output_format, num_joined_pipes);
+		if (status != MODE_OK)
+			continue;
+
+		if (intel_dp_has_dsc(connector)) {
+			int pipe_bpp;
+
+			/*
+			 * TBD pass the connector BPC,
+			 * for now U8_MAX so that max BPC on that platform would be picked
+			 */
+			pipe_bpp = intel_dp_dsc_compute_max_bpp(connector, U8_MAX);
+
+			/*
+			 * Output bpp is stored in 6.4 format so right shift by 4 to get the
+			 * integer value since we support only integer values of bpp.
+			 */
+			if (intel_dp_is_edp(intel_dp)) {
+				dsc_max_compressed_bpp =
+					drm_edp_dsc_sink_output_bpp(connector->dp.dsc_dpcd) >> 4;
+
+				dsc_slice_count =
+					intel_dp_dsc_get_slice_count(connector,
+								     target_clock,
+								     mode->hdisplay,
+								     num_joined_pipes);
+
+				dsc = dsc_max_compressed_bpp && dsc_slice_count;
+			} else if (drm_dp_sink_supports_fec(connector->dp.fec_capability)) {
+				unsigned long bw_overhead_flags = 0;
+
+				if (!drm_dp_is_uhbr_rate(max_link_clock))
+					bw_overhead_flags |= DRM_DP_BW_OVERHEAD_FEC;
+
+				dsc = intel_dp_mode_valid_with_dsc(connector,
+								   max_link_clock, max_lanes,
+								   target_clock, mode->hdisplay,
+								   num_joined_pipes,
+								   output_format, pipe_bpp,
+								   bw_overhead_flags);
+			}
+		}
+
+		if (intel_dp_joiner_needs_dsc(display, num_joined_pipes) && !dsc)
+			continue;
+
+		if (mode_rate > max_rate && !dsc)
+			continue;
+
+		status = intel_mode_valid_max_plane_size(display, mode, num_joined_pipes);
+		if (status != MODE_OK)
+			continue;
+
+		max_dotclk *= num_joined_pipes;
+
+		if (target_clock <= max_dotclk) {
+			status = MODE_OK;
+			break;
 		}
 	}
 
-	if (intel_dp_joiner_needs_dsc(display, num_joined_pipes) && !dsc)
-		return MODE_CLOCK_HIGH;
-
-	status = intel_mode_valid_max_plane_size(display, mode, num_joined_pipes);
 	if (status != MODE_OK)
 		return status;
 
-	if (mode_rate > max_rate && !dsc)
-		return MODE_CLOCK_HIGH;
-
 	return intel_dp_mode_valid_downstream(connector, mode, target_clock);
+
 }
 
 bool intel_dp_source_supports_tps3(struct intel_display *display)
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index 25bfbfd291b0..a27e3b5829bd 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -24,6 +24,13 @@ struct intel_display;
 struct intel_dp;
 struct intel_encoder;
 
+enum joiner_type {
+	FORCED_JOINER = -1,
+	NO_JOINER = 0,		/* 1 pipe */
+	BIG_JOINER = 1,		/* 2 pipes */
+	ULTRA_JOINER = 2,	/* 4 pipes */
+};
+
 struct link_config_limits {
 	int min_rate, max_rate;
 	int min_lane_count, max_lane_count;
-- 
2.45.2


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

* [PATCH 05/14] drm/i915/dp: Rework pipe joiner logic in compute_config
  2026-01-21  3:53 [PATCH 00/14] Account for DSC bubble overhead for horizontal slices Ankit Nautiyal
                   ` (3 preceding siblings ...)
  2026-01-21  3:53 ` [PATCH 04/14] drm/i915/dp: Rework pipe joiner logic in mode_valid Ankit Nautiyal
@ 2026-01-21  3:53 ` Ankit Nautiyal
  2026-01-23 19:06   ` Imre Deak
  2026-01-21  3:53 ` [PATCH 06/14] drm/i915/dp_mst: Move the check for dotclock at the end Ankit Nautiyal
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 28+ messages in thread
From: Ankit Nautiyal @ 2026-01-21  3:53 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: imre.deak, Ankit Nautiyal

Currently, the number of joined pipes are determined early in the flow,
which limits flexibility for accounting DSC slice overhead. To address
this, recompute the joined pipe count during DSC configuration.

Refactor intel_dp_dsc_compute_config() to iterate over joiner candidates
and select the minimal joiner configuration that satisfies the mode
requirements. This prepares the logic for future changes that will
consider DSC slice overhead.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c | 102 +++++++++++++++++++-----
 1 file changed, 84 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 02381f84fa58..d96d9ac1e830 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2790,33 +2790,20 @@ bool intel_dp_joiner_needs_dsc(struct intel_display *display,
 }
 
 static int
-intel_dp_compute_link_config(struct intel_encoder *encoder,
-			     struct intel_crtc_state *pipe_config,
-			     struct drm_connector_state *conn_state,
-			     bool respect_downstream_limits)
+_intel_dp_compute_link_config(struct intel_encoder *encoder,
+			      struct intel_crtc_state *pipe_config,
+			      struct drm_connector_state *conn_state,
+			      bool respect_downstream_limits)
 {
 	struct intel_display *display = to_intel_display(encoder);
-	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
+	int num_joined_pipes = intel_crtc_num_joined_pipes(pipe_config);
 	struct intel_connector *connector =
 		to_intel_connector(conn_state->connector);
-	const struct drm_display_mode *adjusted_mode =
-		&pipe_config->hw.adjusted_mode;
 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 	struct link_config_limits limits;
 	bool dsc_needed, joiner_needs_dsc;
-	int num_joined_pipes;
 	int ret = 0;
 
-	if (pipe_config->fec_enable &&
-	    !intel_dp_supports_fec(intel_dp, connector, pipe_config))
-		return -EINVAL;
-
-	num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector,
-						     adjusted_mode->crtc_hdisplay,
-						     adjusted_mode->crtc_clock);
-	if (num_joined_pipes > 1)
-		pipe_config->joiner_pipes = GENMASK(crtc->pipe + num_joined_pipes - 1, crtc->pipe);
-
 	joiner_needs_dsc = intel_dp_joiner_needs_dsc(display, num_joined_pipes);
 
 	dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
@@ -2879,6 +2866,85 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
 	return 0;
 }
 
+static int
+intel_dp_compute_link_config(struct intel_encoder *encoder,
+			     struct intel_crtc_state *crtc_state,
+			     struct drm_connector_state *conn_state,
+			     bool respect_downstream_limits)
+{
+	struct intel_display *display = to_intel_display(encoder);
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+	struct intel_connector *connector =
+		to_intel_connector(conn_state->connector);
+	const struct drm_display_mode *adjusted_mode =
+		&crtc_state->hw.adjusted_mode;
+	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+	int num_joined_pipes;
+	int ret = 0;
+	int i;
+
+	if (crtc_state->fec_enable &&
+	    !intel_dp_supports_fec(intel_dp, connector, crtc_state))
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(joiner_candidates); i++) {
+		enum joiner_type joiner = joiner_candidates[i];
+		int max_dotclk = display->cdclk.max_dotclk_freq;
+
+		if (joiner == FORCED_JOINER) {
+			if (!connector->force_joined_pipes)
+				continue;
+			num_joined_pipes = connector->force_joined_pipes;
+		} else {
+			num_joined_pipes = 1 << joiner;
+		}
+
+		if ((joiner >= NO_JOINER && !intel_dp_has_joiner(intel_dp)) ||
+		    (joiner == BIG_JOINER && !HAS_BIGJOINER(display)) ||
+		    (joiner == ULTRA_JOINER && !HAS_ULTRAJOINER(display))) {
+			ret = -EINVAL;
+			break;
+		}
+
+		if (adjusted_mode->hdisplay > num_joined_pipes * intel_dp_hdisplay_limit(display))
+			continue;
+
+		/*
+		 * NOTE:
+		 * The crtc_state->joiner_pipes should have been set at the end
+		 * only if all the conditions are met. However that would mean
+		 * that num_joined_pipes is passed around to all helpers and
+		 * make them use it instead of using crtc_state->joiner_pipes
+		 * directly or indirectly (via intel_crtc_num_joined_pipes()).
+		 *
+		 * For now, setting crtc_state->joiner_pipes to the candidate
+		 * value to avoid the above churn and resetting it to 0, in case
+		 * no joiner candidate is found to be suitable for the given
+		 * configuration.
+		 */
+		if (num_joined_pipes > 1)
+			crtc_state->joiner_pipes = GENMASK(crtc->pipe + num_joined_pipes - 1,
+							   crtc->pipe);
+
+		ret = _intel_dp_compute_link_config(encoder, crtc_state, conn_state,
+						    respect_downstream_limits);
+		if (ret)
+			continue;
+
+		max_dotclk *= num_joined_pipes;
+
+		if (adjusted_mode->crtc_clock <= max_dotclk) {
+			ret = 0;
+			break;
+		}
+	}
+
+	if (ret < 0)
+		crtc_state->joiner_pipes = 0;
+
+	return ret;
+}
+
 bool intel_dp_limited_color_range(const struct intel_crtc_state *crtc_state,
 				  const struct drm_connector_state *conn_state)
 {
-- 
2.45.2


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

* [PATCH 06/14] drm/i915/dp_mst: Move the check for dotclock at the end
  2026-01-21  3:53 [PATCH 00/14] Account for DSC bubble overhead for horizontal slices Ankit Nautiyal
                   ` (4 preceding siblings ...)
  2026-01-21  3:53 ` [PATCH 05/14] drm/i915/dp: Rework pipe joiner logic in compute_config Ankit Nautiyal
@ 2026-01-21  3:53 ` Ankit Nautiyal
  2026-01-23 19:11   ` Imre Deak
  2026-01-21  3:53 ` [PATCH 07/14] drm/i915/dp_mst: Move the joiner dependent code together Ankit Nautiyal
                   ` (8 subsequent siblings)
  14 siblings, 1 reply; 28+ messages in thread
From: Ankit Nautiyal @ 2026-01-21  3:53 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: imre.deak, Ankit Nautiyal

Refactor the mode_valid to have all joiner dependent stuff together and
place the check for dotclock limit at the very end.

This will help in the following refactor to iterate over the joiner
candidates and find the best joiner candidate that satisfy all checks
and limits.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 24f8e60df9ac..31e2eae6e4b3 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -1470,20 +1470,19 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector,
 	 *   corresponding link capabilities of the sink) in case the
 	 *   stream is uncompressed for it by the last branch device.
 	 */
-	num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector,
-						     mode->hdisplay, target_clock);
-	max_dotclk *= num_joined_pipes;
-
 	ret = drm_modeset_lock(&mgr->base.lock, ctx);
 	if (ret)
 		return ret;
 
-	if (mode_rate > max_rate || mode->clock > max_dotclk ||
+	if (mode_rate > max_rate ||
 	    drm_dp_calc_pbn_mode(mode->clock, min_bpp << 4) > port->full_pbn) {
 		*status = MODE_CLOCK_HIGH;
 		return 0;
 	}
 
+	num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector,
+						     mode->hdisplay, target_clock);
+
 	if (intel_dp_has_dsc(connector) && drm_dp_sink_supports_fec(connector->dp.fec_capability)) {
 		/*
 		 * TBD pass the connector BPC,
@@ -1513,6 +1512,15 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector,
 	}
 
 	*status = intel_mode_valid_max_plane_size(display, mode, num_joined_pipes);
+
+	if (*status != MODE_OK)
+		return 0;
+
+	max_dotclk *= num_joined_pipes;
+
+	if (mode->clock <= max_dotclk)
+		*status = MODE_OK;
+
 	return 0;
 }
 
-- 
2.45.2


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

* [PATCH 07/14] drm/i915/dp_mst: Move the joiner dependent code together
  2026-01-21  3:53 [PATCH 00/14] Account for DSC bubble overhead for horizontal slices Ankit Nautiyal
                   ` (5 preceding siblings ...)
  2026-01-21  3:53 ` [PATCH 06/14] drm/i915/dp_mst: Move the check for dotclock at the end Ankit Nautiyal
@ 2026-01-21  3:53 ` Ankit Nautiyal
  2026-01-23 19:16   ` Imre Deak
  2026-01-21  3:53 ` [PATCH 08/14] drm/i915/dp_mst: Rework pipe joiner logic in mode_valid Ankit Nautiyal
                   ` (7 subsequent siblings)
  14 siblings, 1 reply; 28+ messages in thread
From: Ankit Nautiyal @ 2026-01-21  3:53 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: imre.deak, Ankit Nautiyal

Move the calculation of num_joined_pipes and other constraints that
depend on it, into a single block in mst_stream_compute_config().

This groups all joiner-dependent logic together, preparing the code for a
future loop-based evaluation of multiple joiner configurations.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 31e2eae6e4b3..8a42da2588eb 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -619,16 +619,16 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
 	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
 		return -EINVAL;
 
+	pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
+	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
+	pipe_config->has_pch_encoder = false;
+
 	num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector,
 						     adjusted_mode->crtc_hdisplay,
 						     adjusted_mode->crtc_clock);
 	if (num_joined_pipes > 1)
 		pipe_config->joiner_pipes = GENMASK(crtc->pipe + num_joined_pipes - 1, crtc->pipe);
 
-	pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
-	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
-	pipe_config->has_pch_encoder = false;
-
 	joiner_needs_dsc = intel_dp_joiner_needs_dsc(display, num_joined_pipes);
 
 	dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
@@ -685,6 +685,10 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
 						  pipe_config->dp_m_n.tu);
 	}
 
+	if (ret)
+		return ret;
+
+	ret = intel_dp_compute_min_hblank(pipe_config, conn_state);
 	if (ret)
 		return ret;
 
@@ -695,10 +699,6 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
 		pipe_config->lane_lat_optim_mask =
 			bxt_dpio_phy_calc_lane_lat_optim_mask(pipe_config->lane_count);
 
-	ret = intel_dp_compute_min_hblank(pipe_config, conn_state);
-	if (ret)
-		return ret;
-
 	intel_vrr_compute_config(pipe_config, conn_state);
 
 	intel_dp_audio_compute_config(encoder, pipe_config, conn_state);
-- 
2.45.2


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

* [PATCH 08/14] drm/i915/dp_mst: Rework pipe joiner logic in mode_valid
  2026-01-21  3:53 [PATCH 00/14] Account for DSC bubble overhead for horizontal slices Ankit Nautiyal
                   ` (6 preceding siblings ...)
  2026-01-21  3:53 ` [PATCH 07/14] drm/i915/dp_mst: Move the joiner dependent code together Ankit Nautiyal
@ 2026-01-21  3:53 ` Ankit Nautiyal
  2026-01-21  3:53 ` [PATCH 09/14] drm/i915/dp_mst: Extract helper to compute link for given joiner config Ankit Nautiyal
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 28+ messages in thread
From: Ankit Nautiyal @ 2026-01-21  3:53 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: imre.deak, Ankit Nautiyal

Refactor the logic to get the number of joined pipes. Start with a single
pipe and incrementally try additional pipes only if needed. While DSC
overhead is not yet computed here, this restructuring prepares the code to
support that in follow-up changes.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c     |   1 -
 drivers/gpu/drm/i915/display/intel_dp.h     |   1 +
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 100 ++++++++++++--------
 3 files changed, 64 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index d96d9ac1e830..2ead783129f4 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1378,7 +1378,6 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector,
 	return MODE_OK;
 }
 
-static
 int intel_dp_hdisplay_limit(struct intel_display *display)
 {
 	return DISPLAY_VER(display) >= 30 ? 6144 : 5120;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index a27e3b5829bd..e5913fba0143 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -232,5 +232,6 @@ int intel_dp_compute_config_late(struct intel_encoder *encoder,
 				 struct drm_connector_state *conn_state);
 int intel_dp_sdp_min_guardband(const struct intel_crtc_state *crtc_state,
 			       bool assume_all_enabled);
+int intel_dp_hdisplay_limit(struct intel_display *display);
 
 #endif /* __INTEL_DP_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 8a42da2588eb..3b1825161d18 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -92,6 +92,13 @@
  * registers.
  */
 
+static const enum joiner_type joiner_candidates[] = {
+	FORCED_JOINER,
+	NO_JOINER,
+	BIG_JOINER,
+	ULTRA_JOINER,
+};
+
 /* From fake MST stream encoder to primary encoder */
 static struct intel_encoder *to_primary_encoder(struct intel_encoder *encoder)
 {
@@ -1420,7 +1427,6 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector,
 	struct drm_dp_mst_topology_mgr *mgr = &intel_dp->mst.mgr;
 	struct drm_dp_mst_port *port = connector->mst.port;
 	const int min_bpp = 18;
-	int max_dotclk = display->cdclk.max_dotclk_freq;
 	int max_rate, mode_rate, max_lanes, max_link_clock;
 	unsigned long bw_overhead_flags =
 		DRM_DP_BW_OVERHEAD_MST | DRM_DP_BW_OVERHEAD_SSC_REF_CLK;
@@ -1428,6 +1434,7 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector,
 	bool dsc = false;
 	int target_clock = mode->clock;
 	int num_joined_pipes;
+	int i;
 
 	if (drm_connector_is_unregistered(&connector->base)) {
 		*status = MODE_ERROR;
@@ -1480,47 +1487,66 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector,
 		return 0;
 	}
 
-	num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector,
-						     mode->hdisplay, target_clock);
-
-	if (intel_dp_has_dsc(connector) && drm_dp_sink_supports_fec(connector->dp.fec_capability)) {
-		/*
-		 * TBD pass the connector BPC,
-		 * for now U8_MAX so that max BPC on that platform would be picked
-		 */
-		int pipe_bpp = intel_dp_dsc_compute_max_bpp(connector, U8_MAX);
-
-		if (!drm_dp_is_uhbr_rate(max_link_clock))
-			bw_overhead_flags |= DRM_DP_BW_OVERHEAD_FEC;
-
-		dsc = intel_dp_mode_valid_with_dsc(connector,
-						   max_link_clock, max_lanes,
-						   target_clock, mode->hdisplay,
-						   num_joined_pipes,
-						   INTEL_OUTPUT_FORMAT_RGB, pipe_bpp,
-						   bw_overhead_flags);
-	}
+	for (i = 0; i < ARRAY_SIZE(joiner_candidates); i++) {
+		int max_dotclk = display->cdclk.max_dotclk_freq;
+		enum joiner_type joiner = joiner_candidates[i];
 
-	if (intel_dp_joiner_needs_dsc(display, num_joined_pipes) && !dsc) {
 		*status = MODE_CLOCK_HIGH;
-		return 0;
-	}
 
-	if (mode_rate > max_rate && !dsc) {
-		*status = MODE_CLOCK_HIGH;
-		return 0;
+		if (joiner == FORCED_JOINER) {
+			if (!connector->force_joined_pipes)
+				continue;
+			num_joined_pipes = connector->force_joined_pipes;
+		} else {
+			num_joined_pipes = 1 << joiner;
+		}
+
+		if ((joiner >= NO_JOINER && !intel_dp_has_joiner(intel_dp)) ||
+		    (joiner == BIG_JOINER && !HAS_BIGJOINER(display)) ||
+		    (joiner == ULTRA_JOINER && !HAS_ULTRAJOINER(display)))
+			break;
+
+		if (mode->hdisplay > num_joined_pipes * intel_dp_hdisplay_limit(display))
+			continue;
+
+		if (intel_dp_has_dsc(connector) &&
+		    drm_dp_sink_supports_fec(connector->dp.fec_capability)) {
+			/*
+			 * TBD pass the connector BPC,
+			 * for now U8_MAX so that max BPC on that platform would be picked
+			 */
+			int pipe_bpp = intel_dp_dsc_compute_max_bpp(connector, U8_MAX);
+
+			if (!drm_dp_is_uhbr_rate(max_link_clock))
+				bw_overhead_flags |= DRM_DP_BW_OVERHEAD_FEC;
+
+			dsc = intel_dp_mode_valid_with_dsc(connector,
+							   max_link_clock, max_lanes,
+							   target_clock, mode->hdisplay,
+							   num_joined_pipes,
+							   INTEL_OUTPUT_FORMAT_RGB, pipe_bpp,
+							   bw_overhead_flags);
+		}
+
+		if (intel_dp_joiner_needs_dsc(display, num_joined_pipes) && !dsc)
+			continue;
+
+		if (mode_rate > max_rate && !dsc)
+			continue;
+
+		*status = intel_mode_valid_max_plane_size(display, mode, num_joined_pipes);
+
+		if (*status != MODE_OK)
+			continue;
+
+		max_dotclk *= num_joined_pipes;
+
+		if (mode->clock <= max_dotclk) {
+			*status = MODE_OK;
+			break;
+		}
 	}
 
-	*status = intel_mode_valid_max_plane_size(display, mode, num_joined_pipes);
-
-	if (*status != MODE_OK)
-		return 0;
-
-	max_dotclk *= num_joined_pipes;
-
-	if (mode->clock <= max_dotclk)
-		*status = MODE_OK;
-
 	return 0;
 }
 
-- 
2.45.2


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

* [PATCH 09/14] drm/i915/dp_mst: Extract helper to compute link for given joiner config
  2026-01-21  3:53 [PATCH 00/14] Account for DSC bubble overhead for horizontal slices Ankit Nautiyal
                   ` (7 preceding siblings ...)
  2026-01-21  3:53 ` [PATCH 08/14] drm/i915/dp_mst: Rework pipe joiner logic in mode_valid Ankit Nautiyal
@ 2026-01-21  3:53 ` Ankit Nautiyal
  2026-01-23 19:23   ` Imre Deak
  2026-01-21  3:53 ` [PATCH 10/14] drm/i915/dp_mst: Rework pipe joiner logic in compute_config Ankit Nautiyal
                   ` (5 subsequent siblings)
  14 siblings, 1 reply; 28+ messages in thread
From: Ankit Nautiyal @ 2026-01-21  3:53 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: imre.deak, Ankit Nautiyal

Move the joiner-dependent portion of mst_stream_compute_config() into
mst_stream_compute_link_for_joined_pipes(), which computes the MST link
configuration for a specific num_joined_pipes.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 72 ++++++++++++++-------
 1 file changed, 47 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 3b1825161d18..e9cfce00efcc 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -602,40 +602,19 @@ mst_stream_compute_config_limits(struct intel_dp *intel_dp,
 							    dsc);
 }
 
-static int mst_stream_compute_config(struct intel_encoder *encoder,
-				     struct intel_crtc_state *pipe_config,
-				     struct drm_connector_state *conn_state)
+static int mst_stream_compute_link_for_joined_pipes(struct intel_encoder *encoder,
+						    struct intel_crtc_state *pipe_config,
+						    struct drm_connector_state *conn_state,
+						    int num_joined_pipes)
 {
 	struct intel_display *display = to_intel_display(encoder);
-	struct intel_atomic_state *state = to_intel_atomic_state(conn_state->state);
-	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
 	struct intel_dp *intel_dp = to_primary_dp(encoder);
 	struct intel_connector *connector =
 		to_intel_connector(conn_state->connector);
-	const struct drm_display_mode *adjusted_mode =
-		&pipe_config->hw.adjusted_mode;
 	struct link_config_limits limits;
 	bool dsc_needed, joiner_needs_dsc;
-	int num_joined_pipes;
 	int ret = 0;
 
-	if (pipe_config->fec_enable &&
-	    !intel_dp_supports_fec(intel_dp, connector, pipe_config))
-		return -EINVAL;
-
-	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
-		return -EINVAL;
-
-	pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
-	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
-	pipe_config->has_pch_encoder = false;
-
-	num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector,
-						     adjusted_mode->crtc_hdisplay,
-						     adjusted_mode->crtc_clock);
-	if (num_joined_pipes > 1)
-		pipe_config->joiner_pipes = GENMASK(crtc->pipe + num_joined_pipes - 1, crtc->pipe);
-
 	joiner_needs_dsc = intel_dp_joiner_needs_dsc(display, num_joined_pipes);
 
 	dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
@@ -699,6 +678,49 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
 	if (ret)
 		return ret;
 
+	return 0;
+}
+
+static int mst_stream_compute_config(struct intel_encoder *encoder,
+				     struct intel_crtc_state *pipe_config,
+				     struct drm_connector_state *conn_state)
+{
+	struct intel_display *display = to_intel_display(encoder);
+	struct intel_atomic_state *state = to_intel_atomic_state(conn_state->state);
+	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
+	struct intel_dp *intel_dp = to_primary_dp(encoder);
+	struct intel_connector *connector =
+		to_intel_connector(conn_state->connector);
+	const struct drm_display_mode *adjusted_mode =
+		&pipe_config->hw.adjusted_mode;
+	int num_joined_pipes;
+	int ret = 0;
+
+	if (pipe_config->fec_enable &&
+	    !intel_dp_supports_fec(intel_dp, connector, pipe_config))
+		return -EINVAL;
+
+	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
+		return -EINVAL;
+
+	pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
+	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
+	pipe_config->has_pch_encoder = false;
+
+	num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector,
+						     adjusted_mode->crtc_hdisplay,
+						     adjusted_mode->crtc_clock);
+
+	if (num_joined_pipes > 1)
+		pipe_config->joiner_pipes = GENMASK(crtc->pipe + num_joined_pipes - 1, crtc->pipe);
+
+	ret = mst_stream_compute_link_for_joined_pipes(encoder,
+						       pipe_config,
+						       conn_state,
+						       num_joined_pipes);
+	if (ret)
+		return ret;
+
 	pipe_config->limited_color_range =
 		intel_dp_limited_color_range(pipe_config, conn_state);
 
-- 
2.45.2


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

* [PATCH 10/14] drm/i915/dp_mst: Rework pipe joiner logic in compute_config
  2026-01-21  3:53 [PATCH 00/14] Account for DSC bubble overhead for horizontal slices Ankit Nautiyal
                   ` (8 preceding siblings ...)
  2026-01-21  3:53 ` [PATCH 09/14] drm/i915/dp_mst: Extract helper to compute link for given joiner config Ankit Nautiyal
@ 2026-01-21  3:53 ` Ankit Nautiyal
  2026-01-21  3:53 ` [PATCH 11/14] drm/i915/dp: Introduce helper to check pixel rate against dotclock limits Ankit Nautiyal
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 28+ messages in thread
From: Ankit Nautiyal @ 2026-01-21  3:53 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: imre.deak, Ankit Nautiyal

Similar to the DP SST, refactor `mst_stream_compute_config()` to iterate
over joiner candidates and select the minimal joiner configuration that
satisfies the mode requirements. This prepares the logic for future changes
that will consider DSC slice overhead.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 50 +++++++++++++++++----
 1 file changed, 41 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index e9cfce00efcc..46208ee67905 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -695,6 +695,7 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
 		&pipe_config->hw.adjusted_mode;
 	int num_joined_pipes;
 	int ret = 0;
+	int i;
 
 	if (pipe_config->fec_enable &&
 	    !intel_dp_supports_fec(intel_dp, connector, pipe_config))
@@ -707,17 +708,48 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
 	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
 	pipe_config->has_pch_encoder = false;
 
-	num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector,
-						     adjusted_mode->crtc_hdisplay,
-						     adjusted_mode->crtc_clock);
+	for (i = 0; i < ARRAY_SIZE(joiner_candidates); i++) {
+		enum joiner_type joiner = joiner_candidates[i];
+		int max_dotclk = display->cdclk.max_dotclk_freq;
 
-	if (num_joined_pipes > 1)
-		pipe_config->joiner_pipes = GENMASK(crtc->pipe + num_joined_pipes - 1, crtc->pipe);
+		ret = -EINVAL;
+
+		if (joiner == FORCED_JOINER) {
+			if (!connector->force_joined_pipes)
+				continue;
+			num_joined_pipes = connector->force_joined_pipes;
+		} else {
+			num_joined_pipes = 1 << joiner;
+		}
+
+		if ((joiner >= NO_JOINER && !intel_dp_has_joiner(intel_dp)) ||
+		    (joiner == BIG_JOINER && !HAS_BIGJOINER(display)) ||
+		    (joiner == ULTRA_JOINER && !HAS_ULTRAJOINER(display))) {
+			break;
+		}
+
+		if (adjusted_mode->hdisplay > num_joined_pipes * intel_dp_hdisplay_limit(display))
+			continue;
+
+		if (num_joined_pipes > 1)
+			pipe_config->joiner_pipes = GENMASK(crtc->pipe + num_joined_pipes - 1,
+							    crtc->pipe);
+
+		ret = mst_stream_compute_link_for_joined_pipes(encoder,
+							       pipe_config,
+							       conn_state,
+							       num_joined_pipes);
+		if (ret)
+			continue;
+
+		max_dotclk *= num_joined_pipes;
+
+		if (adjusted_mode->clock <= max_dotclk) {
+			ret = 0;
+			break;
+		}
+	}
 
-	ret = mst_stream_compute_link_for_joined_pipes(encoder,
-						       pipe_config,
-						       conn_state,
-						       num_joined_pipes);
 	if (ret)
 		return ret;
 
-- 
2.45.2


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

* [PATCH 11/14] drm/i915/dp: Introduce helper to check pixel rate against dotclock limits
  2026-01-21  3:53 [PATCH 00/14] Account for DSC bubble overhead for horizontal slices Ankit Nautiyal
                   ` (9 preceding siblings ...)
  2026-01-21  3:53 ` [PATCH 10/14] drm/i915/dp_mst: Rework pipe joiner logic in compute_config Ankit Nautiyal
@ 2026-01-21  3:53 ` Ankit Nautiyal
  2026-01-23 19:30   ` Imre Deak
  2026-01-21  3:53 ` [PATCH 12/14] drm/i915/dp: Refactor dsc_slice_count handling in intel_dp_mode_valid() Ankit Nautiyal
                   ` (3 subsequent siblings)
  14 siblings, 1 reply; 28+ messages in thread
From: Ankit Nautiyal @ 2026-01-21  3:53 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: imre.deak, Ankit Nautiyal

Add intel_dp_pixel_rate_fits_dotclk() helper, that checks the
required pixel rate against platform dotclock limit.
With joined pipes the effective dotclock limit depends upon the number
of joined pipes.

Call the helper from the mode_valid phase and from the compute_config
phase where we need to check the limits for the given target clock for a
given joiner candidate.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c     | 26 ++++++++++++++-------
 drivers/gpu/drm/i915/display/intel_dp.h     |  3 +++
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 14 +++++------
 3 files changed, 27 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 2ead783129f4..ed81cf4adb9b 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1440,6 +1440,18 @@ bool intel_dp_has_dsc(const struct intel_connector *connector)
 	return true;
 }
 
+bool intel_dp_pixel_rate_fits_dotclk(struct intel_display *display,
+				     int target_clock,
+				     int num_joined_pipes)
+{
+	int max_dotclk = display->cdclk.max_dotclk_freq;
+	int effective_dotclk_limit;
+
+	effective_dotclk_limit = max_dotclk * num_joined_pipes;
+
+	return target_clock <= effective_dotclk_limit;
+}
+
 static enum drm_mode_status
 intel_dp_mode_valid(struct drm_connector *_connector,
 		    const struct drm_display_mode *mode)
@@ -1495,7 +1507,6 @@ intel_dp_mode_valid(struct drm_connector *_connector,
 					   link_bpp_x16, 0);
 
 	for (i = 0; i < ARRAY_SIZE(joiner_candidates); i++) {
-		int max_dotclk = display->cdclk.max_dotclk_freq;
 		enum joiner_type joiner = joiner_candidates[i];
 
 		status = MODE_CLOCK_HIGH;
@@ -1569,9 +1580,9 @@ intel_dp_mode_valid(struct drm_connector *_connector,
 		if (status != MODE_OK)
 			continue;
 
-		max_dotclk *= num_joined_pipes;
-
-		if (target_clock <= max_dotclk) {
+		if (intel_dp_pixel_rate_fits_dotclk(display,
+						    target_clock,
+						    num_joined_pipes)) {
 			status = MODE_OK;
 			break;
 		}
@@ -2888,7 +2899,6 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
 
 	for (i = 0; i < ARRAY_SIZE(joiner_candidates); i++) {
 		enum joiner_type joiner = joiner_candidates[i];
-		int max_dotclk = display->cdclk.max_dotclk_freq;
 
 		if (joiner == FORCED_JOINER) {
 			if (!connector->force_joined_pipes)
@@ -2930,9 +2940,9 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
 		if (ret)
 			continue;
 
-		max_dotclk *= num_joined_pipes;
-
-		if (adjusted_mode->crtc_clock <= max_dotclk) {
+		if (intel_dp_pixel_rate_fits_dotclk(display,
+						    adjusted_mode->crtc_clock,
+						    num_joined_pipes)) {
 			ret = 0;
 			break;
 		}
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index e5913fba0143..0c1cd843bd0a 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -233,5 +233,8 @@ int intel_dp_compute_config_late(struct intel_encoder *encoder,
 int intel_dp_sdp_min_guardband(const struct intel_crtc_state *crtc_state,
 			       bool assume_all_enabled);
 int intel_dp_hdisplay_limit(struct intel_display *display);
+bool intel_dp_pixel_rate_fits_dotclk(struct intel_display *display,
+				     int target_clock,
+				     int num_joined_pipes);
 
 #endif /* __INTEL_DP_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 46208ee67905..7c957351467e 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -710,7 +710,6 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
 
 	for (i = 0; i < ARRAY_SIZE(joiner_candidates); i++) {
 		enum joiner_type joiner = joiner_candidates[i];
-		int max_dotclk = display->cdclk.max_dotclk_freq;
 
 		ret = -EINVAL;
 
@@ -742,9 +741,9 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
 		if (ret)
 			continue;
 
-		max_dotclk *= num_joined_pipes;
-
-		if (adjusted_mode->clock <= max_dotclk) {
+		if (intel_dp_pixel_rate_fits_dotclk(display,
+						    adjusted_mode->clock,
+						    num_joined_pipes)) {
 			ret = 0;
 			break;
 		}
@@ -1542,7 +1541,6 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector,
 	}
 
 	for (i = 0; i < ARRAY_SIZE(joiner_candidates); i++) {
-		int max_dotclk = display->cdclk.max_dotclk_freq;
 		enum joiner_type joiner = joiner_candidates[i];
 
 		*status = MODE_CLOCK_HIGH;
@@ -1593,9 +1591,9 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector,
 		if (*status != MODE_OK)
 			continue;
 
-		max_dotclk *= num_joined_pipes;
-
-		if (mode->clock <= max_dotclk) {
+		if (intel_dp_pixel_rate_fits_dotclk(display,
+						    mode->clock,
+						    num_joined_pipes)) {
 			*status = MODE_OK;
 			break;
 		}
-- 
2.45.2


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

* [PATCH 12/14] drm/i915/dp: Refactor dsc_slice_count handling in intel_dp_mode_valid()
  2026-01-21  3:53 [PATCH 00/14] Account for DSC bubble overhead for horizontal slices Ankit Nautiyal
                   ` (10 preceding siblings ...)
  2026-01-21  3:53 ` [PATCH 11/14] drm/i915/dp: Introduce helper to check pixel rate against dotclock limits Ankit Nautiyal
@ 2026-01-21  3:53 ` Ankit Nautiyal
  2026-01-21  3:53 ` [PATCH 13/14] drm/i915/dp: Account for DSC slice overhead Ankit Nautiyal
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 28+ messages in thread
From: Ankit Nautiyal @ 2026-01-21  3:53 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: imre.deak, Ankit Nautiyal

Make dsc_slice_count closer to the block where it is used and promote it
from u8 to int. This aligns it with upcoming DSC bubble pixel-rate
adjustments, where the slice count participates in wider arithmetic.

Currently, for non-eDP (DP/DP_MST) cases  the slice count is computed only
inside intel_dp_dsc_mode_valid() and is not used by the caller. Once DSC
bubble handling is added, dp_mode_valid() will need access to its own local
slice count for non-eDP cases as well.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index ed81cf4adb9b..9f73a1307b6c 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1464,7 +1464,6 @@ intel_dp_mode_valid(struct drm_connector *_connector,
 	int target_clock = mode->clock;
 	int max_rate, mode_rate, max_lanes, max_link_clock;
 	u16 dsc_max_compressed_bpp = 0;
-	u8 dsc_slice_count = 0;
 	enum drm_mode_status status;
 	bool dsc = false;
 	int num_joined_pipes;
@@ -1508,6 +1507,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
 
 	for (i = 0; i < ARRAY_SIZE(joiner_candidates); i++) {
 		enum joiner_type joiner = joiner_candidates[i];
+		int dsc_slice_count = 0;
 
 		status = MODE_CLOCK_HIGH;
 
@@ -1534,6 +1534,11 @@ intel_dp_mode_valid(struct drm_connector *_connector,
 		if (intel_dp_has_dsc(connector)) {
 			int pipe_bpp;
 
+			dsc_slice_count = intel_dp_dsc_get_slice_count(connector,
+								       target_clock,
+								       mode->hdisplay,
+								       num_joined_pipes);
+
 			/*
 			 * TBD pass the connector BPC,
 			 * for now U8_MAX so that max BPC on that platform would be picked
@@ -1548,12 +1553,6 @@ intel_dp_mode_valid(struct drm_connector *_connector,
 				dsc_max_compressed_bpp =
 					drm_edp_dsc_sink_output_bpp(connector->dp.dsc_dpcd) >> 4;
 
-				dsc_slice_count =
-					intel_dp_dsc_get_slice_count(connector,
-								     target_clock,
-								     mode->hdisplay,
-								     num_joined_pipes);
-
 				dsc = dsc_max_compressed_bpp && dsc_slice_count;
 			} else if (drm_dp_sink_supports_fec(connector->dp.fec_capability)) {
 				unsigned long bw_overhead_flags = 0;
-- 
2.45.2


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

* [PATCH 13/14] drm/i915/dp: Account for DSC slice overhead
  2026-01-21  3:53 [PATCH 00/14] Account for DSC bubble overhead for horizontal slices Ankit Nautiyal
                   ` (11 preceding siblings ...)
  2026-01-21  3:53 ` [PATCH 12/14] drm/i915/dp: Refactor dsc_slice_count handling in intel_dp_mode_valid() Ankit Nautiyal
@ 2026-01-21  3:53 ` Ankit Nautiyal
  2026-01-21  3:53 ` [PATCH 14/14] drm/i915/display: Add upper limit check for pixel clock Ankit Nautiyal
  2026-01-21  5:59 ` ✗ i915.CI.BAT: failure for Account for DSC bubble overhead for horizontal slices (rev3) Patchwork
  14 siblings, 0 replies; 28+ messages in thread
From: Ankit Nautiyal @ 2026-01-21  3:53 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: imre.deak, Ankit Nautiyal

Account for DSC slice overhead bubbles and adjust the pixel rate while
checking the pixel rate against the max dotclock limits.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c     | 19 +++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_dp.h     |  2 ++
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 13 +++++++++++++
 drivers/gpu/drm/i915/display/intel_vdsc.c   |  1 -
 drivers/gpu/drm/i915/display/intel_vdsc.h   |  3 +++
 5 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 9f73a1307b6c..a6a1a803d860 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1442,6 +1442,8 @@ bool intel_dp_has_dsc(const struct intel_connector *connector)
 
 bool intel_dp_pixel_rate_fits_dotclk(struct intel_display *display,
 				     int target_clock,
+				     int htotal,
+				     int dsc_slice_count,
 				     int num_joined_pipes)
 {
 	int max_dotclk = display->cdclk.max_dotclk_freq;
@@ -1449,6 +1451,12 @@ bool intel_dp_pixel_rate_fits_dotclk(struct intel_display *display,
 
 	effective_dotclk_limit = max_dotclk * num_joined_pipes;
 
+	if (dsc_slice_count)
+		target_clock = intel_dsc_get_pixel_rate_with_dsc_bubbles(display,
+									 target_clock,
+									 htotal,
+									 dsc_slice_count);
+
 	return target_clock <= effective_dotclk_limit;
 }
 
@@ -1579,8 +1587,13 @@ intel_dp_mode_valid(struct drm_connector *_connector,
 		if (status != MODE_OK)
 			continue;
 
+		if (!dsc)
+			dsc_slice_count = 0;
+
 		if (intel_dp_pixel_rate_fits_dotclk(display,
 						    target_clock,
+						    mode->htotal,
+						    dsc_slice_count,
 						    num_joined_pipes)) {
 			status = MODE_OK;
 			break;
@@ -2898,6 +2911,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
 
 	for (i = 0; i < ARRAY_SIZE(joiner_candidates); i++) {
 		enum joiner_type joiner = joiner_candidates[i];
+		int dsc_slice_count = 0;
 
 		if (joiner == FORCED_JOINER) {
 			if (!connector->force_joined_pipes)
@@ -2939,8 +2953,13 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
 		if (ret)
 			continue;
 
+		if (crtc_state->dsc.compression_enable)
+			dsc_slice_count = intel_dsc_line_slice_count(&crtc_state->dsc.slice_config);
+
 		if (intel_dp_pixel_rate_fits_dotclk(display,
 						    adjusted_mode->crtc_clock,
+						    adjusted_mode->crtc_htotal,
+						    dsc_slice_count,
 						    num_joined_pipes)) {
 			ret = 0;
 			break;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index 0c1cd843bd0a..78b457b11f07 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -235,6 +235,8 @@ int intel_dp_sdp_min_guardband(const struct intel_crtc_state *crtc_state,
 int intel_dp_hdisplay_limit(struct intel_display *display);
 bool intel_dp_pixel_rate_fits_dotclk(struct intel_display *display,
 				     int target_clock,
+				     int htotal,
+				     int dsc_slice_count,
 				     int num_joined_pipes);
 
 #endif /* __INTEL_DP_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 7c957351467e..25d229843459 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -710,6 +710,7 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
 
 	for (i = 0; i < ARRAY_SIZE(joiner_candidates); i++) {
 		enum joiner_type joiner = joiner_candidates[i];
+		int dsc_slice_count = 0;
 
 		ret = -EINVAL;
 
@@ -741,8 +742,12 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
 		if (ret)
 			continue;
 
+		dsc_slice_count = intel_dp_mst_dsc_get_slice_count(connector, pipe_config);
+
 		if (intel_dp_pixel_rate_fits_dotclk(display,
 						    adjusted_mode->clock,
+						    adjusted_mode->htotal,
+						    dsc_slice_count,
 						    num_joined_pipes)) {
 			ret = 0;
 			break;
@@ -1542,6 +1547,7 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector,
 
 	for (i = 0; i < ARRAY_SIZE(joiner_candidates); i++) {
 		enum joiner_type joiner = joiner_candidates[i];
+		int dsc_slice_count = 0;
 
 		*status = MODE_CLOCK_HIGH;
 
@@ -1569,6 +1575,11 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector,
 			 */
 			int pipe_bpp = intel_dp_dsc_compute_max_bpp(connector, U8_MAX);
 
+			dsc_slice_count = intel_dp_dsc_get_slice_count(connector,
+								       mode->clock,
+								       mode->hdisplay,
+								       num_joined_pipes);
+
 			if (!drm_dp_is_uhbr_rate(max_link_clock))
 				bw_overhead_flags |= DRM_DP_BW_OVERHEAD_FEC;
 
@@ -1593,6 +1604,8 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector,
 
 		if (intel_dp_pixel_rate_fits_dotclk(display,
 						    mode->clock,
+						    mode->htotal,
+						    dsc_slice_count,
 						    num_joined_pipes)) {
 			*status = MODE_OK;
 			break;
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
index 642a89270d8e..7e53201b3cb1 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.c
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
@@ -1104,7 +1104,6 @@ void intel_vdsc_state_dump(struct drm_printer *p, int indent,
 	drm_dsc_dump_config(p, indent, &crtc_state->dsc.config);
 }
 
-static
 int intel_dsc_get_pixel_rate_with_dsc_bubbles(struct intel_display *display,
 					      int pixel_rate, int htotal,
 					      int dsc_horizontal_slices)
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.h b/drivers/gpu/drm/i915/display/intel_vdsc.h
index aeb17670307b..f4d5b37293cf 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.h
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.h
@@ -41,5 +41,8 @@ void intel_vdsc_state_dump(struct drm_printer *p, int indent,
 			   const struct intel_crtc_state *crtc_state);
 int intel_vdsc_min_cdclk(const struct intel_crtc_state *crtc_state);
 unsigned int intel_vdsc_prefill_lines(const struct intel_crtc_state *crtc_state);
+int intel_dsc_get_pixel_rate_with_dsc_bubbles(struct intel_display *display,
+					      int pixel_rate, int htotal,
+					      int dsc_horizontal_slices);
 
 #endif /* __INTEL_VDSC_H__ */
-- 
2.45.2


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

* [PATCH 14/14] drm/i915/display: Add upper limit check for pixel clock
  2026-01-21  3:53 [PATCH 00/14] Account for DSC bubble overhead for horizontal slices Ankit Nautiyal
                   ` (12 preceding siblings ...)
  2026-01-21  3:53 ` [PATCH 13/14] drm/i915/dp: Account for DSC slice overhead Ankit Nautiyal
@ 2026-01-21  3:53 ` Ankit Nautiyal
  2026-01-23 19:48   ` Imre Deak
  2026-01-21  5:59 ` ✗ i915.CI.BAT: failure for Account for DSC bubble overhead for horizontal slices (rev3) Patchwork
  14 siblings, 1 reply; 28+ messages in thread
From: Ankit Nautiyal @ 2026-01-21  3:53 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: imre.deak, Chaitanya Kumar Borah, Ankit Nautiyal

From: Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com>

Add upper limit check for pixel clock by platform. Limits don't apply
when DSC is enabled.

For the currently supported versions of HDMI, pixel clock is already
limited to 600Mhz so nothing needs to be done there as of now.

BSpec: 49199, 68912

v2: Add this limit to the new helper
    intel_dp_pixel_rate_fits_dotclk(). (Ankit)

Signed-off-by: Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com>
Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c | 12 ++++++++++++
 drivers/gpu/drm/i915/display/intel_display.h |  1 +
 drivers/gpu/drm/i915/display/intel_dp.c      |  3 +++
 3 files changed, 16 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 7491e00e3858..04021ad6b473 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -8001,6 +8001,18 @@ void intel_setup_outputs(struct intel_display *display)
 	drm_helper_move_panel_connectors_to_head(display->drm);
 }
 
+int intel_dotclock_limit(struct intel_display *display)
+{
+	if (DISPLAY_VERx100(display) == 3002)
+		return 937500;
+	else if (DISPLAY_VER(display) >= 30)
+		return 1350000;
+	else if (DISPLAY_VER(display) >= 13)
+		return 1200000;
+	else
+		return 1100000;
+}
+
 static int max_dotclock(struct intel_display *display)
 {
 	int max_dotclock = display->cdclk.max_dotclk_freq;
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index f8e6e4e82722..0009c305f140 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -488,6 +488,7 @@ void intel_cpu_transcoder_get_m2_n2(struct intel_crtc *crtc,
 				    struct intel_link_m_n *m_n);
 int intel_dotclock_calculate(int link_freq, const struct intel_link_m_n *m_n);
 int intel_crtc_dotclock(const struct intel_crtc_state *pipe_config);
+int intel_dotclock_limit(struct intel_display *display);
 enum intel_display_power_domain intel_port_to_power_domain(struct intel_digital_port *dig_port);
 enum intel_display_power_domain
 intel_aux_power_domain(struct intel_digital_port *dig_port);
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index a6a1a803d860..bd8ba6db01db 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1456,6 +1456,9 @@ bool intel_dp_pixel_rate_fits_dotclk(struct intel_display *display,
 									 target_clock,
 									 htotal,
 									 dsc_slice_count);
+	else
+		effective_dotclk_limit =
+			min(max_dotclk, intel_dotclock_limit(display)) * num_joined_pipes;
 
 	return target_clock <= effective_dotclk_limit;
 }
-- 
2.45.2


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

* ✗ i915.CI.BAT: failure for Account for DSC bubble overhead for horizontal slices (rev3)
  2026-01-21  3:53 [PATCH 00/14] Account for DSC bubble overhead for horizontal slices Ankit Nautiyal
                   ` (13 preceding siblings ...)
  2026-01-21  3:53 ` [PATCH 14/14] drm/i915/display: Add upper limit check for pixel clock Ankit Nautiyal
@ 2026-01-21  5:59 ` Patchwork
  14 siblings, 0 replies; 28+ messages in thread
From: Patchwork @ 2026-01-21  5:59 UTC (permalink / raw)
  To: Ankit Nautiyal; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 32290 bytes --]

== Series Details ==

Series: Account for DSC bubble overhead for horizontal slices (rev3)
URL   : https://patchwork.freedesktop.org/series/152804/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_17857 -> Patchwork_152804v3
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with Patchwork_152804v3 absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in Patchwork_152804v3, please notify your bug team (I915-ci-infra@lists.freedesktop.org) to allow them
  to document this new failure mode, which will reduce false positives in CI.

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

Participating hosts (43 -> 40)
------------------------------

  Missing    (3): bat-dg2-13 fi-snb-2520m bat-adls-6 

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

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

### IGT changes ###

#### Possible regressions ####

  * igt@core_hotunplug@unbind-rebind:
    - bat-apl-1:          [PASS][1] -> [ABORT][2]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-apl-1/igt@core_hotunplug@unbind-rebind.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-apl-1/igt@core_hotunplug@unbind-rebind.html
    - bat-rplp-1:         [PASS][3] -> [ABORT][4]
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-rplp-1/igt@core_hotunplug@unbind-rebind.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-rplp-1/igt@core_hotunplug@unbind-rebind.html

  * igt@fbdev@eof:
    - bat-twl-1:          [PASS][5] -> [SKIP][6] +13 other tests skip
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-twl-1/igt@fbdev@eof.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-twl-1/igt@fbdev@eof.html

  * igt@fbdev@nullptr:
    - bat-jsl-1:          [PASS][7] -> [SKIP][8] +8 other tests skip
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-jsl-1/igt@fbdev@nullptr.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-jsl-1/igt@fbdev@nullptr.html

  * igt@i915_selftest@live:
    - fi-glk-j4005:       [PASS][9] -> [ABORT][10] +1 other test abort
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/fi-glk-j4005/igt@i915_selftest@live.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/fi-glk-j4005/igt@i915_selftest@live.html

  * igt@kms_flip@basic-flip-vs-wf_vblank:
    - bat-arlh-3:         [PASS][11] -> [SKIP][12] +9 other tests skip
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-arlh-3/igt@kms_flip@basic-flip-vs-wf_vblank.html
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-arlh-3/igt@kms_flip@basic-flip-vs-wf_vblank.html

  * igt@kms_pm_backlight@basic-brightness:
    - bat-rplp-1:         [PASS][13] -> [SKIP][14]
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-rplp-1/igt@kms_pm_backlight@basic-brightness.html
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-rplp-1/igt@kms_pm_backlight@basic-brightness.html

  * igt@kms_psr@psr-sprite-plane-onoff:
    - bat-twl-2:          [PASS][15] -> [SKIP][16] +13 other tests skip
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-twl-2/igt@kms_psr@psr-sprite-plane-onoff.html
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-twl-2/igt@kms_psr@psr-sprite-plane-onoff.html

  
#### Warnings ####

  * igt@kms_psr@psr-primary-mmap-gtt:
    - bat-arlh-3:         [SKIP][17] ([i915#12637] / [i915#9688]) -> [SKIP][18]
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-arlh-3/igt@kms_psr@psr-primary-mmap-gtt.html
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-arlh-3/igt@kms_psr@psr-primary-mmap-gtt.html

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

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

### IGT changes ###

#### Issues hit ####

  * igt@fbdev@eof:
    - fi-kbl-7567u:       [PASS][19] -> [SKIP][20] +9 other tests skip
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/fi-kbl-7567u/igt@fbdev@eof.html
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/fi-kbl-7567u/igt@fbdev@eof.html
    - bat-apl-1:          [PASS][21] -> [SKIP][22] +9 other tests skip
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-apl-1/igt@fbdev@eof.html
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-apl-1/igt@fbdev@eof.html
    - bat-rplp-1:         [PASS][23] -> [SKIP][24] ([i915#2582]) +3 other tests skip
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-rplp-1/igt@fbdev@eof.html
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-rplp-1/igt@fbdev@eof.html

  * igt@fbdev@info:
    - fi-cfl-8109u:       [PASS][25] -> [SKIP][26] ([i915#1849])
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/fi-cfl-8109u/igt@fbdev@info.html
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/fi-cfl-8109u/igt@fbdev@info.html
    - fi-skl-6600u:       [PASS][27] -> [SKIP][28] ([i915#1849])
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/fi-skl-6600u/igt@fbdev@info.html
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/fi-skl-6600u/igt@fbdev@info.html
    - bat-twl-2:          [PASS][29] -> [SKIP][30] ([i915#1849])
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-twl-2/igt@fbdev@info.html
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-twl-2/igt@fbdev@info.html
    - bat-mtlp-9:         [PASS][31] -> [SKIP][32] ([i915#1849] / [i915#2582])
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-mtlp-9/igt@fbdev@info.html
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-mtlp-9/igt@fbdev@info.html
    - bat-mtlp-8:         [PASS][33] -> [SKIP][34] ([i915#1849] / [i915#2582])
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-mtlp-8/igt@fbdev@info.html
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-mtlp-8/igt@fbdev@info.html
    - bat-jsl-1:          [PASS][35] -> [SKIP][36] ([i915#1849])
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-jsl-1/igt@fbdev@info.html
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-jsl-1/igt@fbdev@info.html
    - bat-arlh-3:         [PASS][37] -> [SKIP][38] ([i915#1849])
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-arlh-3/igt@fbdev@info.html
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-arlh-3/igt@fbdev@info.html
    - fi-kbl-7567u:       [PASS][39] -> [SKIP][40] ([i915#1849])
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/fi-kbl-7567u/igt@fbdev@info.html
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/fi-kbl-7567u/igt@fbdev@info.html
    - bat-twl-1:          [PASS][41] -> [SKIP][42] ([i915#1849])
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-twl-1/igt@fbdev@info.html
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-twl-1/igt@fbdev@info.html
    - bat-apl-1:          [PASS][43] -> [SKIP][44] ([i915#1849])
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-apl-1/igt@fbdev@info.html
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-apl-1/igt@fbdev@info.html
    - bat-rplp-1:         [PASS][45] -> [SKIP][46] ([i915#1849] / [i915#2582])
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-rplp-1/igt@fbdev@info.html
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-rplp-1/igt@fbdev@info.html

  * igt@fbdev@nullptr:
    - bat-mtlp-9:         [PASS][47] -> [SKIP][48] ([i915#2582]) +3 other tests skip
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-mtlp-9/igt@fbdev@nullptr.html
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-mtlp-9/igt@fbdev@nullptr.html
    - bat-mtlp-8:         [PASS][49] -> [SKIP][50] ([i915#2582]) +3 other tests skip
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-mtlp-8/igt@fbdev@nullptr.html
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-mtlp-8/igt@fbdev@nullptr.html
    - bat-arlh-3:         [PASS][51] -> [SKIP][52] ([i915#11345]) +3 other tests skip
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-arlh-3/igt@fbdev@nullptr.html
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-arlh-3/igt@fbdev@nullptr.html

  * igt@i915_selftest@live@workarounds:
    - bat-arlh-3:         [PASS][53] -> [DMESG-FAIL][54] ([i915#12061]) +1 other test dmesg-fail
   [53]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-arlh-3/igt@i915_selftest@live@workarounds.html
   [54]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-arlh-3/igt@i915_selftest@live@workarounds.html
    - bat-dg2-9:          [PASS][55] -> [DMESG-FAIL][56] ([i915#12061]) +1 other test dmesg-fail
   [55]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-dg2-9/igt@i915_selftest@live@workarounds.html
   [56]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-dg2-9/igt@i915_selftest@live@workarounds.html
    - bat-dg2-14:         [PASS][57] -> [DMESG-FAIL][58] ([i915#12061]) +1 other test dmesg-fail
   [57]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-dg2-14/igt@i915_selftest@live@workarounds.html
   [58]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-dg2-14/igt@i915_selftest@live@workarounds.html
    - bat-mtlp-9:         [PASS][59] -> [DMESG-FAIL][60] ([i915#12061]) +1 other test dmesg-fail
   [59]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-mtlp-9/igt@i915_selftest@live@workarounds.html
   [60]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-mtlp-9/igt@i915_selftest@live@workarounds.html

  * igt@kms_cursor_legacy@basic-flip-after-cursor-atomic:
    - bat-mtlp-9:         [PASS][61] -> [SKIP][62] ([i915#11190]) +13 other tests skip
   [61]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-mtlp-9/igt@kms_cursor_legacy@basic-flip-after-cursor-atomic.html
   [62]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-mtlp-9/igt@kms_cursor_legacy@basic-flip-after-cursor-atomic.html
    - bat-mtlp-8:         [PASS][63] -> [SKIP][64] ([i915#11190]) +13 other tests skip
   [63]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-mtlp-8/igt@kms_cursor_legacy@basic-flip-after-cursor-atomic.html
   [64]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-mtlp-8/igt@kms_cursor_legacy@basic-flip-after-cursor-atomic.html
    - bat-jsl-1:          [PASS][65] -> [SKIP][66] ([i915#11190]) +13 other tests skip
   [65]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-jsl-1/igt@kms_cursor_legacy@basic-flip-after-cursor-atomic.html
   [66]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-jsl-1/igt@kms_cursor_legacy@basic-flip-after-cursor-atomic.html

  * igt@kms_cursor_legacy@basic-flip-after-cursor-legacy:
    - fi-skl-6600u:       [PASS][67] -> [SKIP][68] ([i915#11190]) +12 other tests skip
   [67]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/fi-skl-6600u/igt@kms_cursor_legacy@basic-flip-after-cursor-legacy.html
   [68]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/fi-skl-6600u/igt@kms_cursor_legacy@basic-flip-after-cursor-legacy.html

  * igt@kms_flip@basic-flip-vs-wf_vblank:
    - bat-mtlp-9:         [PASS][69] -> [SKIP][70] ([i915#3637]) +3 other tests skip
   [69]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-mtlp-9/igt@kms_flip@basic-flip-vs-wf_vblank.html
   [70]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-mtlp-9/igt@kms_flip@basic-flip-vs-wf_vblank.html
    - bat-mtlp-8:         [PASS][71] -> [SKIP][72] ([i915#3637]) +3 other tests skip
   [71]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-mtlp-8/igt@kms_flip@basic-flip-vs-wf_vblank.html
   [72]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-mtlp-8/igt@kms_flip@basic-flip-vs-wf_vblank.html
    - bat-rplp-1:         [PASS][73] -> [SKIP][74] ([i915#3637]) +3 other tests skip
   [73]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-rplp-1/igt@kms_flip@basic-flip-vs-wf_vblank.html
   [74]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-rplp-1/igt@kms_flip@basic-flip-vs-wf_vblank.html

  * igt@kms_frontbuffer_tracking@basic:
    - fi-cfl-8109u:       [PASS][75] -> [SKIP][76] +9 other tests skip
   [75]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/fi-cfl-8109u/igt@kms_frontbuffer_tracking@basic.html
   [76]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/fi-cfl-8109u/igt@kms_frontbuffer_tracking@basic.html
    - bat-mtlp-9:         [PASS][77] -> [SKIP][78] ([i915#15099] / [i915#4342] / [i915#5354])
   [77]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-mtlp-9/igt@kms_frontbuffer_tracking@basic.html
   [78]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-mtlp-9/igt@kms_frontbuffer_tracking@basic.html
    - bat-mtlp-8:         [PASS][79] -> [SKIP][80] ([i915#15099] / [i915#4342] / [i915#5354])
   [79]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-mtlp-8/igt@kms_frontbuffer_tracking@basic.html
   [80]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-mtlp-8/igt@kms_frontbuffer_tracking@basic.html
    - bat-rplp-1:         [PASS][81] -> [SKIP][82] ([i915#1849])
   [81]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-rplp-1/igt@kms_frontbuffer_tracking@basic.html
   [82]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-rplp-1/igt@kms_frontbuffer_tracking@basic.html

  * igt@kms_pipe_crc_basic@hang-read-crc:
    - bat-rplp-1:         [PASS][83] -> [SKIP][84] ([i915#11190]) +13 other tests skip
   [83]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-rplp-1/igt@kms_pipe_crc_basic@hang-read-crc.html
   [84]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-rplp-1/igt@kms_pipe_crc_basic@hang-read-crc.html

  * igt@kms_pipe_crc_basic@nonblocking-crc:
    - bat-arlh-3:         [PASS][85] -> [SKIP][86] ([i915#11190]) +13 other tests skip
   [85]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-arlh-3/igt@kms_pipe_crc_basic@nonblocking-crc.html
   [86]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-arlh-3/igt@kms_pipe_crc_basic@nonblocking-crc.html
    - fi-kbl-7567u:       [PASS][87] -> [SKIP][88] ([i915#11190]) +13 other tests skip
   [87]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/fi-kbl-7567u/igt@kms_pipe_crc_basic@nonblocking-crc.html
   [88]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/fi-kbl-7567u/igt@kms_pipe_crc_basic@nonblocking-crc.html
    - bat-twl-1:          [PASS][89] -> [SKIP][90] ([i915#11190]) +13 other tests skip
   [89]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-twl-1/igt@kms_pipe_crc_basic@nonblocking-crc.html
   [90]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-twl-1/igt@kms_pipe_crc_basic@nonblocking-crc.html
    - bat-apl-1:          [PASS][91] -> [SKIP][92] ([i915#11190]) +12 other tests skip
   [91]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-apl-1/igt@kms_pipe_crc_basic@nonblocking-crc.html
   [92]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-apl-1/igt@kms_pipe_crc_basic@nonblocking-crc.html

  * igt@kms_pipe_crc_basic@nonblocking-crc-frame-sequence:
    - bat-twl-2:          [PASS][93] -> [SKIP][94] ([i915#11190]) +13 other tests skip
   [93]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-twl-2/igt@kms_pipe_crc_basic@nonblocking-crc-frame-sequence.html
   [94]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-twl-2/igt@kms_pipe_crc_basic@nonblocking-crc-frame-sequence.html

  * igt@kms_pipe_crc_basic@read-crc:
    - fi-cfl-8109u:       [PASS][95] -> [SKIP][96] ([i915#11190]) +13 other tests skip
   [95]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/fi-cfl-8109u/igt@kms_pipe_crc_basic@read-crc.html
   [96]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/fi-cfl-8109u/igt@kms_pipe_crc_basic@read-crc.html

  * igt@kms_pm_backlight@basic-brightness:
    - bat-adlp-6:         [PASS][97] -> [SKIP][98] ([i915#9812])
   [97]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-adlp-6/igt@kms_pm_backlight@basic-brightness.html
   [98]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-adlp-6/igt@kms_pm_backlight@basic-brightness.html
    - bat-mtlp-9:         [PASS][99] -> [SKIP][100] ([i915#5354])
   [99]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-mtlp-9/igt@kms_pm_backlight@basic-brightness.html
   [100]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-mtlp-9/igt@kms_pm_backlight@basic-brightness.html
    - bat-mtlp-8:         [PASS][101] -> [SKIP][102] ([i915#5354])
   [101]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-mtlp-8/igt@kms_pm_backlight@basic-brightness.html
   [102]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-mtlp-8/igt@kms_pm_backlight@basic-brightness.html
    - bat-jsl-1:          [PASS][103] -> [SKIP][104] ([i915#15205])
   [103]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-jsl-1/igt@kms_pm_backlight@basic-brightness.html
   [104]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-jsl-1/igt@kms_pm_backlight@basic-brightness.html

  * igt@kms_psr@psr-cursor-plane-move:
    - fi-skl-6600u:       [PASS][105] -> [SKIP][106] +14 other tests skip
   [105]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/fi-skl-6600u/igt@kms_psr@psr-cursor-plane-move.html
   [106]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/fi-skl-6600u/igt@kms_psr@psr-cursor-plane-move.html
    - bat-adlp-6:         [PASS][107] -> [SKIP][108] ([i915#1072] / [i915#9732]) +3 other tests skip
   [107]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-adlp-6/igt@kms_psr@psr-cursor-plane-move.html
   [108]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-adlp-6/igt@kms_psr@psr-cursor-plane-move.html

  * igt@kms_psr@psr-sprite-plane-onoff:
    - bat-mtlp-9:         [PASS][109] -> [SKIP][110] ([i915#1072] / [i915#9732]) +2 other tests skip
   [109]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-mtlp-9/igt@kms_psr@psr-sprite-plane-onoff.html
   [110]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-mtlp-9/igt@kms_psr@psr-sprite-plane-onoff.html
    - bat-mtlp-8:         [PASS][111] -> [SKIP][112] ([i915#1072] / [i915#9732]) +2 other tests skip
   [111]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-mtlp-8/igt@kms_psr@psr-sprite-plane-onoff.html
   [112]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-mtlp-8/igt@kms_psr@psr-sprite-plane-onoff.html
    - bat-jsl-1:          [PASS][113] -> [SKIP][114] ([i915#1072]) +3 other tests skip
   [113]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-jsl-1/igt@kms_psr@psr-sprite-plane-onoff.html
   [114]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-jsl-1/igt@kms_psr@psr-sprite-plane-onoff.html

  * igt@prime_vgem@basic-fence-flip:
    - bat-twl-2:          [PASS][115] -> [SKIP][116] ([i915#3708])
   [115]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-twl-2/igt@prime_vgem@basic-fence-flip.html
   [116]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-twl-2/igt@prime_vgem@basic-fence-flip.html
    - bat-mtlp-9:         [PASS][117] -> [SKIP][118] ([i915#3708])
   [117]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-mtlp-9/igt@prime_vgem@basic-fence-flip.html
   [118]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-mtlp-9/igt@prime_vgem@basic-fence-flip.html
    - bat-mtlp-8:         [PASS][119] -> [SKIP][120] ([i915#3708])
   [119]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-mtlp-8/igt@prime_vgem@basic-fence-flip.html
   [120]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-mtlp-8/igt@prime_vgem@basic-fence-flip.html
    - bat-jsl-1:          [PASS][121] -> [SKIP][122]
   [121]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-jsl-1/igt@prime_vgem@basic-fence-flip.html
   [122]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-jsl-1/igt@prime_vgem@basic-fence-flip.html
    - bat-twl-1:          [PASS][123] -> [SKIP][124] ([i915#3708])
   [123]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-twl-1/igt@prime_vgem@basic-fence-flip.html
   [124]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-twl-1/igt@prime_vgem@basic-fence-flip.html
    - bat-rplp-1:         [PASS][125] -> [SKIP][126] ([i915#3708])
   [125]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-rplp-1/igt@prime_vgem@basic-fence-flip.html
   [126]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-rplp-1/igt@prime_vgem@basic-fence-flip.html

  
#### Possible fixes ####

  * igt@i915_selftest@live:
    - bat-arls-5:         [INCOMPLETE][127] -> [PASS][128]
   [127]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-arls-5/igt@i915_selftest@live.html
   [128]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-arls-5/igt@i915_selftest@live.html

  * igt@i915_selftest@live@requests:
    - bat-arls-5:         [INCOMPLETE][129] ([i915#14564]) -> [PASS][130]
   [129]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-arls-5/igt@i915_selftest@live@requests.html
   [130]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-arls-5/igt@i915_selftest@live@requests.html

  
#### Warnings ####

  * igt@i915_selftest@live:
    - bat-atsm-1:         [DMESG-FAIL][131] ([i915#12061] / [i915#13929]) -> [DMESG-FAIL][132] ([i915#12061] / [i915#14204])
   [131]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-atsm-1/igt@i915_selftest@live.html
   [132]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-atsm-1/igt@i915_selftest@live.html

  * igt@i915_selftest@live@mman:
    - bat-atsm-1:         [DMESG-FAIL][133] ([i915#13929]) -> [DMESG-FAIL][134] ([i915#14204])
   [133]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-atsm-1/igt@i915_selftest@live@mman.html
   [134]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-atsm-1/igt@i915_selftest@live@mman.html

  * igt@kms_cursor_legacy@basic-busy-flip-before-cursor-atomic:
    - bat-twl-2:          [SKIP][135] ([i915#11030] / [i915#11731]) -> [SKIP][136] ([i915#11190]) +1 other test skip
   [135]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-twl-2/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-atomic.html
   [136]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-twl-2/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-atomic.html

  * igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy:
    - bat-mtlp-9:         [SKIP][137] ([i915#4213]) -> [SKIP][138] ([i915#11190]) +1 other test skip
   [137]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-mtlp-9/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html
   [138]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-mtlp-9/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html
    - bat-mtlp-8:         [SKIP][139] ([i915#4213]) -> [SKIP][140] ([i915#11190]) +1 other test skip
   [139]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-mtlp-8/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html
   [140]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-mtlp-8/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html
    - bat-jsl-1:          [SKIP][141] ([i915#4103]) -> [SKIP][142] ([i915#11190]) +1 other test skip
   [141]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-jsl-1/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html
   [142]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-jsl-1/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html
    - bat-arlh-3:         [SKIP][143] ([i915#11731]) -> [SKIP][144] ([i915#11190]) +1 other test skip
   [143]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-arlh-3/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html
   [144]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-arlh-3/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html
    - bat-twl-1:          [SKIP][145] ([i915#11030] / [i915#11731]) -> [SKIP][146] ([i915#11190]) +1 other test skip
   [145]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-twl-1/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html
   [146]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-twl-1/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html
    - bat-rplp-1:         [SKIP][147] ([i915#4103] / [i915#4213]) -> [SKIP][148] ([i915#11190]) +1 other test skip
   [147]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-rplp-1/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html
   [148]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-rplp-1/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html

  * igt@kms_dsc@dsc-basic:
    - fi-kbl-7567u:       [SKIP][149] -> [SKIP][150] ([i915#11190]) +2 other tests skip
   [149]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/fi-kbl-7567u/igt@kms_dsc@dsc-basic.html
   [150]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/fi-kbl-7567u/igt@kms_dsc@dsc-basic.html
    - bat-twl-1:          [SKIP][151] ([i915#9886]) -> [SKIP][152] ([i915#11190])
   [151]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-twl-1/igt@kms_dsc@dsc-basic.html
   [152]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-twl-1/igt@kms_dsc@dsc-basic.html
    - bat-apl-1:          [SKIP][153] -> [SKIP][154] ([i915#11190]) +3 other tests skip
   [153]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-apl-1/igt@kms_dsc@dsc-basic.html
   [154]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-apl-1/igt@kms_dsc@dsc-basic.html
    - bat-rplp-1:         [SKIP][155] ([i915#3555] / [i915#3840]) -> [SKIP][156] ([i915#11190])
   [155]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-rplp-1/igt@kms_dsc@dsc-basic.html
   [156]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-rplp-1/igt@kms_dsc@dsc-basic.html
    - fi-cfl-8109u:       [SKIP][157] -> [SKIP][158] ([i915#11190]) +2 other tests skip
   [157]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/fi-cfl-8109u/igt@kms_dsc@dsc-basic.html
   [158]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/fi-cfl-8109u/igt@kms_dsc@dsc-basic.html
    - fi-skl-6600u:       [SKIP][159] -> [SKIP][160] ([i915#11190]) +3 other tests skip
   [159]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/fi-skl-6600u/igt@kms_dsc@dsc-basic.html
   [160]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/fi-skl-6600u/igt@kms_dsc@dsc-basic.html
    - bat-twl-2:          [SKIP][161] ([i915#9886]) -> [SKIP][162] ([i915#11190])
   [161]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-twl-2/igt@kms_dsc@dsc-basic.html
   [162]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-twl-2/igt@kms_dsc@dsc-basic.html
    - bat-mtlp-9:         [SKIP][163] ([i915#3555] / [i915#3840] / [i915#9159]) -> [SKIP][164] ([i915#11190])
   [163]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-mtlp-9/igt@kms_dsc@dsc-basic.html
   [164]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-mtlp-9/igt@kms_dsc@dsc-basic.html
    - bat-mtlp-8:         [SKIP][165] ([i915#3555] / [i915#3840] / [i915#9159]) -> [SKIP][166] ([i915#11190])
   [165]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-mtlp-8/igt@kms_dsc@dsc-basic.html
   [166]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-mtlp-8/igt@kms_dsc@dsc-basic.html
    - bat-jsl-1:          [SKIP][167] ([i915#3555] / [i915#9886]) -> [SKIP][168] ([i915#11190])
   [167]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-jsl-1/igt@kms_dsc@dsc-basic.html
   [168]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-jsl-1/igt@kms_dsc@dsc-basic.html
    - bat-arlh-3:         [SKIP][169] ([i915#9886]) -> [SKIP][170] ([i915#11190])
   [169]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-arlh-3/igt@kms_dsc@dsc-basic.html
   [170]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-arlh-3/igt@kms_dsc@dsc-basic.html

  * igt@kms_psr@psr-primary-mmap-gtt:
    - bat-mtlp-9:         [SKIP][171] ([i915#4077] / [i915#9688]) -> [SKIP][172] ([i915#1072] / [i915#9732])
   [171]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-mtlp-9/igt@kms_psr@psr-primary-mmap-gtt.html
   [172]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-mtlp-9/igt@kms_psr@psr-primary-mmap-gtt.html
    - bat-mtlp-8:         [SKIP][173] ([i915#4077] / [i915#9688]) -> [SKIP][174] ([i915#1072] / [i915#9732])
   [173]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_17857/bat-mtlp-8/igt@kms_psr@psr-primary-mmap-gtt.html
   [174]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_152804v3/bat-mtlp-8/igt@kms_psr@psr-primary-mmap-gtt.html

  
  [i915#1072]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/1072
  [i915#11030]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/11030
  [i915#11190]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/11190
  [i915#11345]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/11345
  [i915#11731]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/11731
  [i915#12061]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12061
  [i915#12637]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12637
  [i915#13929]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/13929
  [i915#14204]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14204
  [i915#14564]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14564
  [i915#15099]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15099
  [i915#15205]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15205
  [i915#1849]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/1849
  [i915#2582]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/2582
  [i915#3555]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3555
  [i915#3637]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3637
  [i915#3708]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3708
  [i915#3840]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/3840
  [i915#4077]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4077
  [i915#4103]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4103
  [i915#4213]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4213
  [i915#4342]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4342
  [i915#5354]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/5354
  [i915#9159]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9159
  [i915#9688]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9688
  [i915#9732]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9732
  [i915#9812]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9812
  [i915#9886]: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/9886


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

  * Linux: CI_DRM_17857 -> Patchwork_152804v3

  CI-20190529: 20190529
  CI_DRM_17857: cee03fb98c51b597d51379b308eabee23db0954e @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_8709: 16ce286cac6acc9669a1c758572ae9fceb483c46 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  Patchwork_152804v3: cee03fb98c51b597d51379b308eabee23db0954e @ git://anongit.freedesktop.org/gfx-ci/linux

== Logs ==

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

[-- Attachment #2: Type: text/html, Size: 40308 bytes --]

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

* Re: [PATCH 04/14] drm/i915/dp: Rework pipe joiner logic in mode_valid
  2026-01-21  3:53 ` [PATCH 04/14] drm/i915/dp: Rework pipe joiner logic in mode_valid Ankit Nautiyal
@ 2026-01-21 10:54   ` Jani Nikula
  2026-01-21 11:19     ` Nautiyal, Ankit K
  0 siblings, 1 reply; 28+ messages in thread
From: Jani Nikula @ 2026-01-21 10:54 UTC (permalink / raw)
  To: Ankit Nautiyal, intel-gfx, intel-xe; +Cc: imre.deak, Ankit Nautiyal

On Wed, 21 Jan 2026, Ankit Nautiyal <ankit.k.nautiyal@intel.com> wrote:
> Currently in intel_dp_mode_valid(), we compute the number of joined pipes
> required before deciding whether DSC is needed. This ordering prevents us
> from accounting for DSC-related overhead when determining pipe
> requirements.
>
> Refactor the logic to start with a single pipe and incrementally try
> additional pipes only if needed. While DSC overhead is not yet computed
> here, this restructuring prepares the code to support that in a follow-up
> changes.
>
> Additionally, if a forced joiner configuration is present, we first check
> whether it satisfies the bandwidth and timing constraints. If it does not,
> we fall back to evaluating configurations with 1, 2, or 4 pipes joined
> and prune or keep the mode accordingly.
>
> Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_dp.c | 144 +++++++++++++++---------
>  drivers/gpu/drm/i915/display/intel_dp.h |   7 ++
>  2 files changed, 96 insertions(+), 55 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index fc7d48460a52..02381f84fa58 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -107,6 +107,13 @@
>  /* Constants for DP DSC configurations */
>  static const u8 valid_dsc_bpp[] = {6, 8, 10, 12, 15};
>  
> +static const enum joiner_type joiner_candidates[] = {
> +	FORCED_JOINER,
> +	NO_JOINER,
> +	BIG_JOINER,
> +	ULTRA_JOINER,
> +};
> +
>  /**
>   * intel_dp_is_edp - is the given port attached to an eDP panel (either CPU or PCH)
>   * @intel_dp: DP struct
> @@ -1445,13 +1452,13 @@ intel_dp_mode_valid(struct drm_connector *_connector,
>  	const struct drm_display_mode *fixed_mode;
>  	int target_clock = mode->clock;
>  	int max_rate, mode_rate, max_lanes, max_link_clock;
> -	int max_dotclk = display->cdclk.max_dotclk_freq;
>  	u16 dsc_max_compressed_bpp = 0;
>  	u8 dsc_slice_count = 0;
>  	enum drm_mode_status status;
>  	bool dsc = false;
>  	int num_joined_pipes;
>  	int link_bpp_x16;
> +	int i;
>  
>  	status = intel_cpu_transcoder_mode_valid(display, mode);
>  	if (status != MODE_OK)
> @@ -1488,67 +1495,94 @@ intel_dp_mode_valid(struct drm_connector *_connector,
>  					   target_clock, mode->hdisplay,
>  					   link_bpp_x16, 0);
>  
> -	num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector,
> -						     mode->hdisplay, target_clock);
> -	max_dotclk *= num_joined_pipes;
> -
> -	if (target_clock > max_dotclk)
> -		return MODE_CLOCK_HIGH;
> -
> -	status = intel_pfit_mode_valid(display, mode, output_format, num_joined_pipes);
> -	if (status != MODE_OK)
> -		return status;
> -
> -	if (intel_dp_has_dsc(connector)) {
> -		int pipe_bpp;
> -
> -		/*
> -		 * TBD pass the connector BPC,
> -		 * for now U8_MAX so that max BPC on that platform would be picked
> -		 */
> -		pipe_bpp = intel_dp_dsc_compute_max_bpp(connector, U8_MAX);
> -
> -		/*
> -		 * Output bpp is stored in 6.4 format so right shift by 4 to get the
> -		 * integer value since we support only integer values of bpp.
> -		 */
> -		if (intel_dp_is_edp(intel_dp)) {
> -			dsc_max_compressed_bpp =
> -				drm_edp_dsc_sink_output_bpp(connector->dp.dsc_dpcd) >> 4;
> -
> -			dsc_slice_count =
> -				intel_dp_dsc_get_slice_count(connector,
> -							     target_clock,
> -							     mode->hdisplay,
> -							     num_joined_pipes);
> -
> -			dsc = dsc_max_compressed_bpp && dsc_slice_count;
> -		} else if (drm_dp_sink_supports_fec(connector->dp.fec_capability)) {
> -			unsigned long bw_overhead_flags = 0;
> -
> -			if (!drm_dp_is_uhbr_rate(max_link_clock))
> -				bw_overhead_flags |= DRM_DP_BW_OVERHEAD_FEC;
> -
> -			dsc = intel_dp_mode_valid_with_dsc(connector,
> -							   max_link_clock, max_lanes,
> -							   target_clock, mode->hdisplay,
> -							   num_joined_pipes,
> -							   output_format, pipe_bpp,
> -							   bw_overhead_flags);
> +	for (i = 0; i < ARRAY_SIZE(joiner_candidates); i++) {
> +		int max_dotclk = display->cdclk.max_dotclk_freq;
> +		enum joiner_type joiner = joiner_candidates[i];
> +
> +		status = MODE_CLOCK_HIGH;
> +
> +		if (joiner == FORCED_JOINER) {
> +			if (!connector->force_joined_pipes)
> +				continue;
> +			num_joined_pipes = connector->force_joined_pipes;
> +		} else {
> +			num_joined_pipes = 1 << joiner;
> +		}
> +
> +		if ((joiner >= NO_JOINER && !intel_dp_has_joiner(intel_dp)) ||
> +		    (joiner == BIG_JOINER && !HAS_BIGJOINER(display)) ||
> +		    (joiner == ULTRA_JOINER && !HAS_ULTRAJOINER(display)))

There's a bunch of superfluous braces in there.

Anyway, this makes me think if we should reconsider the HAS_BIGJOINER()
and HAS_ULTRAJOINER() naming, and the enum thing here.

We're adding a bunch of logic to enumerate combos, and to check those
against joiner availability. But really, we could have a HAS_JOINER(num)
which says whether we can join that many pipes. Maybe even have the
compression as parameter.

I know the spec talks about big/ultra joiner, but for the more casual
reader of the code, you really want to know how many pipes you're
talking about joining, not the *name* of the thing.

If we had that in place, we could turn the whole joiner loop here from
enumerating the enums to enumerating the number of joined pipes. and
whether we can join them. No need for the enum at all, and I think the
code might end up cleaner too.


> +			break;
> +
> +		if (mode->hdisplay > num_joined_pipes * intel_dp_hdisplay_limit(display))
> +			continue;
> +
> +		status = intel_pfit_mode_valid(display, mode, output_format, num_joined_pipes);
> +		if (status != MODE_OK)
> +			continue;
> +
> +		if (intel_dp_has_dsc(connector)) {
> +			int pipe_bpp;
> +
> +			/*
> +			 * TBD pass the connector BPC,
> +			 * for now U8_MAX so that max BPC on that platform would be picked
> +			 */
> +			pipe_bpp = intel_dp_dsc_compute_max_bpp(connector, U8_MAX);
> +
> +			/*
> +			 * Output bpp is stored in 6.4 format so right shift by 4 to get the
> +			 * integer value since we support only integer values of bpp.
> +			 */
> +			if (intel_dp_is_edp(intel_dp)) {
> +				dsc_max_compressed_bpp =
> +					drm_edp_dsc_sink_output_bpp(connector->dp.dsc_dpcd) >> 4;
> +
> +				dsc_slice_count =
> +					intel_dp_dsc_get_slice_count(connector,
> +								     target_clock,
> +								     mode->hdisplay,
> +								     num_joined_pipes);
> +
> +				dsc = dsc_max_compressed_bpp && dsc_slice_count;
> +			} else if (drm_dp_sink_supports_fec(connector->dp.fec_capability)) {
> +				unsigned long bw_overhead_flags = 0;
> +
> +				if (!drm_dp_is_uhbr_rate(max_link_clock))
> +					bw_overhead_flags |= DRM_DP_BW_OVERHEAD_FEC;
> +
> +				dsc = intel_dp_mode_valid_with_dsc(connector,
> +								   max_link_clock, max_lanes,
> +								   target_clock, mode->hdisplay,
> +								   num_joined_pipes,
> +								   output_format, pipe_bpp,
> +								   bw_overhead_flags);
> +			}
> +		}
> +
> +		if (intel_dp_joiner_needs_dsc(display, num_joined_pipes) && !dsc)
> +			continue;
> +
> +		if (mode_rate > max_rate && !dsc)
> +			continue;
> +
> +		status = intel_mode_valid_max_plane_size(display, mode, num_joined_pipes);
> +		if (status != MODE_OK)
> +			continue;
> +
> +		max_dotclk *= num_joined_pipes;
> +
> +		if (target_clock <= max_dotclk) {
> +			status = MODE_OK;
> +			break;
>  		}
>  	}
>  
> -	if (intel_dp_joiner_needs_dsc(display, num_joined_pipes) && !dsc)
> -		return MODE_CLOCK_HIGH;
> -
> -	status = intel_mode_valid_max_plane_size(display, mode, num_joined_pipes);
>  	if (status != MODE_OK)
>  		return status;
>  
> -	if (mode_rate > max_rate && !dsc)
> -		return MODE_CLOCK_HIGH;
> -
>  	return intel_dp_mode_valid_downstream(connector, mode, target_clock);
> +
>  }
>  
>  bool intel_dp_source_supports_tps3(struct intel_display *display)
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
> index 25bfbfd291b0..a27e3b5829bd 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.h
> +++ b/drivers/gpu/drm/i915/display/intel_dp.h
> @@ -24,6 +24,13 @@ struct intel_display;
>  struct intel_dp;
>  struct intel_encoder;
>  
> +enum joiner_type {

I wrote the below *before* I wrote the comment above, which makes all of
this moot, but here goes anyway:

"joiner_type" is too generic, it needs a prefix.

> +	FORCED_JOINER = -1,
> +	NO_JOINER = 0,		/* 1 pipe */
> +	BIG_JOINER = 1,		/* 2 pipes */
> +	ULTRA_JOINER = 2,	/* 4 pipes */

Ditto for the enumerations. Why are you explicitly initializing the
values, are they somehow meaningful?

> +};

The enum is about the joiner, not about DP. intel_dp.h doesn't have
anything that requires the joiner type.


> +
>  struct link_config_limits {
>  	int min_rate, max_rate;
>  	int min_lane_count, max_lane_count;

-- 
Jani Nikula, Intel

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

* Re: [PATCH 04/14] drm/i915/dp: Rework pipe joiner logic in mode_valid
  2026-01-21 10:54   ` Jani Nikula
@ 2026-01-21 11:19     ` Nautiyal, Ankit K
  2026-01-23 18:44       ` Imre Deak
  0 siblings, 1 reply; 28+ messages in thread
From: Nautiyal, Ankit K @ 2026-01-21 11:19 UTC (permalink / raw)
  To: Jani Nikula, intel-gfx, intel-xe; +Cc: imre.deak


On 1/21/2026 4:24 PM, Jani Nikula wrote:
> On Wed, 21 Jan 2026, Ankit Nautiyal <ankit.k.nautiyal@intel.com> wrote:
>> Currently in intel_dp_mode_valid(), we compute the number of joined pipes
>> required before deciding whether DSC is needed. This ordering prevents us
>> from accounting for DSC-related overhead when determining pipe
>> requirements.
>>
>> Refactor the logic to start with a single pipe and incrementally try
>> additional pipes only if needed. While DSC overhead is not yet computed
>> here, this restructuring prepares the code to support that in a follow-up
>> changes.
>>
>> Additionally, if a forced joiner configuration is present, we first check
>> whether it satisfies the bandwidth and timing constraints. If it does not,
>> we fall back to evaluating configurations with 1, 2, or 4 pipes joined
>> and prune or keep the mode accordingly.
>>
>> Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
>> ---
>>   drivers/gpu/drm/i915/display/intel_dp.c | 144 +++++++++++++++---------
>>   drivers/gpu/drm/i915/display/intel_dp.h |   7 ++
>>   2 files changed, 96 insertions(+), 55 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
>> index fc7d48460a52..02381f84fa58 100644
>> --- a/drivers/gpu/drm/i915/display/intel_dp.c
>> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
>> @@ -107,6 +107,13 @@
>>   /* Constants for DP DSC configurations */
>>   static const u8 valid_dsc_bpp[] = {6, 8, 10, 12, 15};
>>   
>> +static const enum joiner_type joiner_candidates[] = {
>> +	FORCED_JOINER,
>> +	NO_JOINER,
>> +	BIG_JOINER,
>> +	ULTRA_JOINER,
>> +};
>> +
>>   /**
>>    * intel_dp_is_edp - is the given port attached to an eDP panel (either CPU or PCH)
>>    * @intel_dp: DP struct
>> @@ -1445,13 +1452,13 @@ intel_dp_mode_valid(struct drm_connector *_connector,
>>   	const struct drm_display_mode *fixed_mode;
>>   	int target_clock = mode->clock;
>>   	int max_rate, mode_rate, max_lanes, max_link_clock;
>> -	int max_dotclk = display->cdclk.max_dotclk_freq;
>>   	u16 dsc_max_compressed_bpp = 0;
>>   	u8 dsc_slice_count = 0;
>>   	enum drm_mode_status status;
>>   	bool dsc = false;
>>   	int num_joined_pipes;
>>   	int link_bpp_x16;
>> +	int i;
>>   
>>   	status = intel_cpu_transcoder_mode_valid(display, mode);
>>   	if (status != MODE_OK)
>> @@ -1488,67 +1495,94 @@ intel_dp_mode_valid(struct drm_connector *_connector,
>>   					   target_clock, mode->hdisplay,
>>   					   link_bpp_x16, 0);
>>   
>> -	num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector,
>> -						     mode->hdisplay, target_clock);
>> -	max_dotclk *= num_joined_pipes;
>> -
>> -	if (target_clock > max_dotclk)
>> -		return MODE_CLOCK_HIGH;
>> -
>> -	status = intel_pfit_mode_valid(display, mode, output_format, num_joined_pipes);
>> -	if (status != MODE_OK)
>> -		return status;
>> -
>> -	if (intel_dp_has_dsc(connector)) {
>> -		int pipe_bpp;
>> -
>> -		/*
>> -		 * TBD pass the connector BPC,
>> -		 * for now U8_MAX so that max BPC on that platform would be picked
>> -		 */
>> -		pipe_bpp = intel_dp_dsc_compute_max_bpp(connector, U8_MAX);
>> -
>> -		/*
>> -		 * Output bpp is stored in 6.4 format so right shift by 4 to get the
>> -		 * integer value since we support only integer values of bpp.
>> -		 */
>> -		if (intel_dp_is_edp(intel_dp)) {
>> -			dsc_max_compressed_bpp =
>> -				drm_edp_dsc_sink_output_bpp(connector->dp.dsc_dpcd) >> 4;
>> -
>> -			dsc_slice_count =
>> -				intel_dp_dsc_get_slice_count(connector,
>> -							     target_clock,
>> -							     mode->hdisplay,
>> -							     num_joined_pipes);
>> -
>> -			dsc = dsc_max_compressed_bpp && dsc_slice_count;
>> -		} else if (drm_dp_sink_supports_fec(connector->dp.fec_capability)) {
>> -			unsigned long bw_overhead_flags = 0;
>> -
>> -			if (!drm_dp_is_uhbr_rate(max_link_clock))
>> -				bw_overhead_flags |= DRM_DP_BW_OVERHEAD_FEC;
>> -
>> -			dsc = intel_dp_mode_valid_with_dsc(connector,
>> -							   max_link_clock, max_lanes,
>> -							   target_clock, mode->hdisplay,
>> -							   num_joined_pipes,
>> -							   output_format, pipe_bpp,
>> -							   bw_overhead_flags);
>> +	for (i = 0; i < ARRAY_SIZE(joiner_candidates); i++) {
>> +		int max_dotclk = display->cdclk.max_dotclk_freq;
>> +		enum joiner_type joiner = joiner_candidates[i];
>> +
>> +		status = MODE_CLOCK_HIGH;
>> +
>> +		if (joiner == FORCED_JOINER) {
>> +			if (!connector->force_joined_pipes)
>> +				continue;
>> +			num_joined_pipes = connector->force_joined_pipes;
>> +		} else {
>> +			num_joined_pipes = 1 << joiner;
>> +		}
>> +
>> +		if ((joiner >= NO_JOINER && !intel_dp_has_joiner(intel_dp)) ||
>> +		    (joiner == BIG_JOINER && !HAS_BIGJOINER(display)) ||
>> +		    (joiner == ULTRA_JOINER && !HAS_ULTRAJOINER(display)))
> There's a bunch of superfluous braces in there.
>
> Anyway, this makes me think if we should reconsider the HAS_BIGJOINER()
> and HAS_ULTRAJOINER() naming, and the enum thing here.
>
> We're adding a bunch of logic to enumerate combos, and to check those
> against joiner availability. But really, we could have a HAS_JOINER(num)
> which says whether we can join that many pipes. Maybe even have the
> compression as parameter.
>
> I know the spec talks about big/ultra joiner, but for the more casual
> reader of the code, you really want to know how many pipes you're
> talking about joining, not the *name* of the thing.
>
> If we had that in place, we could turn the whole joiner loop here from
> enumerating the enums to enumerating the number of joined pipes. and
> whether we can join them. No need for the enum at all, and I think the
> code might end up cleaner too.

Oh yes you are right! It will indeed be more intuitive to iterate over 
number of pipes we want to join rather than iterating over the joiner type.

Still need that weird force joiner index though.

Also realized check for NO_JOINER should have been (joiner > NO_JOINER ...)

This explains the BAT issues. (With above suggestion this will be not be 
needed).

>
>
>> +			break;
>> +
>> +		if (mode->hdisplay > num_joined_pipes * intel_dp_hdisplay_limit(display))
>> +			continue;
>> +
>> +		status = intel_pfit_mode_valid(display, mode, output_format, num_joined_pipes);
>> +		if (status != MODE_OK)
>> +			continue;
>> +
>> +		if (intel_dp_has_dsc(connector)) {
>> +			int pipe_bpp;
>> +
>> +			/*
>> +			 * TBD pass the connector BPC,
>> +			 * for now U8_MAX so that max BPC on that platform would be picked
>> +			 */
>> +			pipe_bpp = intel_dp_dsc_compute_max_bpp(connector, U8_MAX);
>> +
>> +			/*
>> +			 * Output bpp is stored in 6.4 format so right shift by 4 to get the
>> +			 * integer value since we support only integer values of bpp.
>> +			 */
>> +			if (intel_dp_is_edp(intel_dp)) {
>> +				dsc_max_compressed_bpp =
>> +					drm_edp_dsc_sink_output_bpp(connector->dp.dsc_dpcd) >> 4;
>> +
>> +				dsc_slice_count =
>> +					intel_dp_dsc_get_slice_count(connector,
>> +								     target_clock,
>> +								     mode->hdisplay,
>> +								     num_joined_pipes);
>> +
>> +				dsc = dsc_max_compressed_bpp && dsc_slice_count;
>> +			} else if (drm_dp_sink_supports_fec(connector->dp.fec_capability)) {
>> +				unsigned long bw_overhead_flags = 0;
>> +
>> +				if (!drm_dp_is_uhbr_rate(max_link_clock))
>> +					bw_overhead_flags |= DRM_DP_BW_OVERHEAD_FEC;
>> +
>> +				dsc = intel_dp_mode_valid_with_dsc(connector,
>> +								   max_link_clock, max_lanes,
>> +								   target_clock, mode->hdisplay,
>> +								   num_joined_pipes,
>> +								   output_format, pipe_bpp,
>> +								   bw_overhead_flags);
>> +			}
>> +		}
>> +
>> +		if (intel_dp_joiner_needs_dsc(display, num_joined_pipes) && !dsc)
>> +			continue;
>> +
>> +		if (mode_rate > max_rate && !dsc)
>> +			continue;
>> +
>> +		status = intel_mode_valid_max_plane_size(display, mode, num_joined_pipes);
>> +		if (status != MODE_OK)
>> +			continue;
>> +
>> +		max_dotclk *= num_joined_pipes;
>> +
>> +		if (target_clock <= max_dotclk) {
>> +			status = MODE_OK;
>> +			break;
>>   		}
>>   	}
>>   
>> -	if (intel_dp_joiner_needs_dsc(display, num_joined_pipes) && !dsc)
>> -		return MODE_CLOCK_HIGH;
>> -
>> -	status = intel_mode_valid_max_plane_size(display, mode, num_joined_pipes);
>>   	if (status != MODE_OK)
>>   		return status;
>>   
>> -	if (mode_rate > max_rate && !dsc)
>> -		return MODE_CLOCK_HIGH;
>> -
>>   	return intel_dp_mode_valid_downstream(connector, mode, target_clock);
>> +
>>   }
>>   
>>   bool intel_dp_source_supports_tps3(struct intel_display *display)
>> diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
>> index 25bfbfd291b0..a27e3b5829bd 100644
>> --- a/drivers/gpu/drm/i915/display/intel_dp.h
>> +++ b/drivers/gpu/drm/i915/display/intel_dp.h
>> @@ -24,6 +24,13 @@ struct intel_display;
>>   struct intel_dp;
>>   struct intel_encoder;
>>   
>> +enum joiner_type {
> I wrote the below *before* I wrote the comment above, which makes all of
> this moot, but here goes anyway:
>
> "joiner_type" is too generic, it needs a prefix.
>
>> +	FORCED_JOINER = -1,
>> +	NO_JOINER = 0,		/* 1 pipe */
>> +	BIG_JOINER = 1,		/* 2 pipes */
>> +	ULTRA_JOINER = 2,	/* 4 pipes */
> Ditto for the enumerations. Why are you explicitly initializing the
> values, are they somehow meaningful?

The idea was to shift 1 << joiner_type to get number of pipes that are used.

Wanted to check for forced joiner first that we get from the debugfs, if 
the value provided can be supported well and good but if it cannot be 
supported, we do our default thing from next iteration onward.


>
>> +};
> The enum is about the joiner, not about DP. intel_dp.h doesn't have
> anything that requires the joiner type.

Agreed. This is more of a DSS CTL thing.


Regards,

Ankit

>
>> +
>>   struct link_config_limits {
>>   	int min_rate, max_rate;
>>   	int min_lane_count, max_lane_count;

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

* Re: [PATCH 01/14] drm/i915/dp: Early reject bad hdisplay in intel_dp_mode_valid
  2026-01-21  3:53 ` [PATCH 01/14] drm/i915/dp: Early reject bad hdisplay in intel_dp_mode_valid Ankit Nautiyal
@ 2026-01-23 18:06   ` Imre Deak
  0 siblings, 0 replies; 28+ messages in thread
From: Imre Deak @ 2026-01-23 18:06 UTC (permalink / raw)
  To: Ankit Nautiyal; +Cc: intel-gfx, intel-xe

On Wed, Jan 21, 2026 at 09:23:17AM +0530, Ankit Nautiyal wrote:
> Move check for bad hdisplay early as it is independent on other checks.
> 
> Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>

Reviewed-by: Imre Deak <imre.deak@intel.com>

> ---
>  drivers/gpu/drm/i915/display/intel_dp.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index 79fd3b8d8b25..126da297efc5 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -1460,6 +1460,9 @@ intel_dp_mode_valid(struct drm_connector *_connector,
>  	if (mode->clock < 10000)
>  		return MODE_CLOCK_LOW;
>  
> +	if (intel_dp_hdisplay_bad(display, mode->hdisplay))
> +		return MODE_H_ILLEGAL;
> +
>  	fixed_mode = intel_panel_fixed_mode(connector, mode);
>  	if (intel_dp_is_edp(intel_dp) && fixed_mode) {
>  		status = intel_panel_mode_valid(connector, mode);
> @@ -1483,9 +1486,6 @@ intel_dp_mode_valid(struct drm_connector *_connector,
>  	if (target_clock > max_dotclk)
>  		return MODE_CLOCK_HIGH;
>  
> -	if (intel_dp_hdisplay_bad(display, mode->hdisplay))
> -		return MODE_H_ILLEGAL;
> -
>  	max_link_clock = intel_dp_max_link_rate(intel_dp);
>  	max_lanes = intel_dp_max_lane_count(intel_dp);
>  
> -- 
> 2.45.2
> 

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

* Re: [PATCH 02/14] drm/i915/dp: Move num_joined_pipes and related checks together
  2026-01-21  3:53 ` [PATCH 02/14] drm/i915/dp: Move num_joined_pipes and related checks together Ankit Nautiyal
@ 2026-01-23 18:25   ` Imre Deak
  0 siblings, 0 replies; 28+ messages in thread
From: Imre Deak @ 2026-01-23 18:25 UTC (permalink / raw)
  To: Ankit Nautiyal; +Cc: intel-gfx, intel-xe

On Wed, Jan 21, 2026 at 09:23:18AM +0530, Ankit Nautiyal wrote:
> Move the calculation of `num_joined_pipes` and other constraints that
> depend on it, into a single block.
> This groups all joiner-dependent logic together, preparing the code for a
> future loop-based evaluation of multiple joiner configurations.
> 
> Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>

Reviewed-by: Imre Deak <imre.deak@intel.com>

> ---
>  drivers/gpu/drm/i915/display/intel_dp.c | 32 ++++++++++++-------------
>  1 file changed, 16 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index 126da297efc5..c0a8ffac6312 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -1472,20 +1472,9 @@ intel_dp_mode_valid(struct drm_connector *_connector,
>  		target_clock = fixed_mode->clock;
>  	}
>  
> -	num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector,
> -						     mode->hdisplay, target_clock);
> -	max_dotclk *= num_joined_pipes;
> -
>  	sink_format = intel_dp_sink_format(connector, mode);
>  	output_format = intel_dp_output_format(connector, sink_format);
>  
> -	status = intel_pfit_mode_valid(display, mode, output_format, num_joined_pipes);
> -	if (status != MODE_OK)
> -		return status;
> -
> -	if (target_clock > max_dotclk)
> -		return MODE_CLOCK_HIGH;
> -
>  	max_link_clock = intel_dp_max_link_rate(intel_dp);
>  	max_lanes = intel_dp_max_lane_count(intel_dp);
>  
> @@ -1496,6 +1485,17 @@ intel_dp_mode_valid(struct drm_connector *_connector,
>  					   target_clock, mode->hdisplay,
>  					   link_bpp_x16, 0);
>  
> +	num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector,
> +						     mode->hdisplay, target_clock);
> +	max_dotclk *= num_joined_pipes;
> +
> +	if (target_clock > max_dotclk)
> +		return MODE_CLOCK_HIGH;
> +
> +	status = intel_pfit_mode_valid(display, mode, output_format, num_joined_pipes);
> +	if (status != MODE_OK)
> +		return status;
> +
>  	if (intel_dp_has_dsc(connector)) {
>  		int pipe_bpp;
>  
> @@ -1538,14 +1538,14 @@ intel_dp_mode_valid(struct drm_connector *_connector,
>  	if (intel_dp_joiner_needs_dsc(display, num_joined_pipes) && !dsc)
>  		return MODE_CLOCK_HIGH;
>  
> +	status = intel_mode_valid_max_plane_size(display, mode, num_joined_pipes);
> +	if (status != MODE_OK)
> +		return status;
> +
>  	if (mode_rate > max_rate && !dsc)
>  		return MODE_CLOCK_HIGH;
>  
> -	status = intel_dp_mode_valid_downstream(connector, mode, target_clock);
> -	if (status != MODE_OK)
> -		return status;
> -
> -	return intel_mode_valid_max_plane_size(display, mode, num_joined_pipes);
> +	return intel_dp_mode_valid_downstream(connector, mode, target_clock);
>  }
>  
>  bool intel_dp_source_supports_tps3(struct intel_display *display)
> -- 
> 2.45.2
> 

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

* Re: [PATCH 03/14] drm/i915/dp: Extract helper to get the hdisplay limit
  2026-01-21  3:53 ` [PATCH 03/14] drm/i915/dp: Extract helper to get the hdisplay limit Ankit Nautiyal
@ 2026-01-23 18:28   ` Imre Deak
  0 siblings, 0 replies; 28+ messages in thread
From: Imre Deak @ 2026-01-23 18:28 UTC (permalink / raw)
  To: Ankit Nautiyal; +Cc: intel-gfx, intel-xe

On Wed, Jan 21, 2026 at 09:23:19AM +0530, Ankit Nautiyal wrote:
> Separate out function to get the hdisplay limit for a given platform.
> 
> Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_dp.c | 11 +++++++----
>  1 file changed, 7 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index c0a8ffac6312..fc7d48460a52 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -1371,6 +1371,12 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector,
>  	return MODE_OK;
>  }
>  
> +static
> +int intel_dp_hdisplay_limit(struct intel_display *display)

Nit: intel_dp_max_hdisplay_per_pipe()?

Reviewed-by: Imre Deak <imre.deak@intel.com>

> +{
> +	return DISPLAY_VER(display) >= 30 ? 6144 : 5120;
> +}
> +
>  static
>  bool intel_dp_needs_joiner(struct intel_dp *intel_dp,
>  			   struct intel_connector *connector,
> @@ -1378,17 +1384,14 @@ bool intel_dp_needs_joiner(struct intel_dp *intel_dp,
>  			   int num_joined_pipes)
>  {
>  	struct intel_display *display = to_intel_display(intel_dp);
> -	int hdisplay_limit;
>  
>  	if (!intel_dp_has_joiner(intel_dp))
>  		return false;
>  
>  	num_joined_pipes /= 2;
>  
> -	hdisplay_limit = DISPLAY_VER(display) >= 30 ? 6144 : 5120;
> -
>  	return clock > num_joined_pipes * display->cdclk.max_dotclk_freq ||
> -	       hdisplay > num_joined_pipes * hdisplay_limit;
> +	       hdisplay > num_joined_pipes * intel_dp_hdisplay_limit(display);
>  }
>  
>  int intel_dp_num_joined_pipes(struct intel_dp *intel_dp,
> -- 
> 2.45.2
> 

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

* Re: [PATCH 04/14] drm/i915/dp: Rework pipe joiner logic in mode_valid
  2026-01-21 11:19     ` Nautiyal, Ankit K
@ 2026-01-23 18:44       ` Imre Deak
  0 siblings, 0 replies; 28+ messages in thread
From: Imre Deak @ 2026-01-23 18:44 UTC (permalink / raw)
  To: Nautiyal, Ankit K; +Cc: Jani Nikula, intel-gfx, intel-xe

On Wed, Jan 21, 2026 at 04:49:46PM +0530, Nautiyal, Ankit K wrote:
> 
> On 1/21/2026 4:24 PM, Jani Nikula wrote:
> > On Wed, 21 Jan 2026, Ankit Nautiyal <ankit.k.nautiyal@intel.com> wrote:
> > > Currently in intel_dp_mode_valid(), we compute the number of joined pipes
> > > required before deciding whether DSC is needed. This ordering prevents us
> > > from accounting for DSC-related overhead when determining pipe
> > > requirements.

It isn't possible either to first (a) determine if DSC is needed and
then (b) calculate the required number of joined pipes, since (a) also
requires (b). This could be added here as well explaining why a loop
over the number of joined pipes is the only way.

> > > 
> > > Refactor the logic to start with a single pipe and incrementally try
> > > additional pipes only if needed. While DSC overhead is not yet computed
> > > here, this restructuring prepares the code to support that in a follow-up
> > > changes.
> > > 
> > > Additionally, if a forced joiner configuration is present, we first check
> > > whether it satisfies the bandwidth and timing constraints. If it does not,
> > > we fall back to evaluating configurations with 1, 2, or 4 pipes joined
> > > and prune or keep the mode accordingly.
> > > 
> > > Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
> > > ---
> > >   drivers/gpu/drm/i915/display/intel_dp.c | 144 +++++++++++++++---------
> > >   drivers/gpu/drm/i915/display/intel_dp.h |   7 ++
> > >   2 files changed, 96 insertions(+), 55 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> > > index fc7d48460a52..02381f84fa58 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_dp.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> > > @@ -107,6 +107,13 @@
> > >   /* Constants for DP DSC configurations */
> > >   static const u8 valid_dsc_bpp[] = {6, 8, 10, 12, 15};
> > > +static const enum joiner_type joiner_candidates[] = {
> > > +	FORCED_JOINER,
> > > +	NO_JOINER,
> > > +	BIG_JOINER,
> > > +	ULTRA_JOINER,
> > > +};
> > > +
> > >
> > > [...]
> > >
> > > +	for (i = 0; i < ARRAY_SIZE(joiner_candidates); i++) {
> > > +		int max_dotclk = display->cdclk.max_dotclk_freq;
> > > +		enum joiner_type joiner = joiner_candidates[i];
> > > +
> > > +		status = MODE_CLOCK_HIGH;
> > > +
> > > +		if (joiner == FORCED_JOINER) {
> > > +			if (!connector->force_joined_pipes)
> > > +				continue;
> > > +			num_joined_pipes = connector->force_joined_pipes;
> > > +		} else {
> > > +			num_joined_pipes = 1 << joiner;
> > > +		}
> > > +
> > > +		if ((joiner >= NO_JOINER && !intel_dp_has_joiner(intel_dp)) ||
> > > +		    (joiner == BIG_JOINER && !HAS_BIGJOINER(display)) ||
> > > +		    (joiner == ULTRA_JOINER && !HAS_ULTRAJOINER(display)))
> > There's a bunch of superfluous braces in there.
> > 
> > Anyway, this makes me think if we should reconsider the HAS_BIGJOINER()
> > and HAS_ULTRAJOINER() naming, and the enum thing here.
> > 
> > We're adding a bunch of logic to enumerate combos, and to check those
> > against joiner availability. But really, we could have a HAS_JOINER(num)
> > which says whether we can join that many pipes. Maybe even have the
> > compression as parameter.
> > 
> > I know the spec talks about big/ultra joiner, but for the more casual
> > reader of the code, you really want to know how many pipes you're
> > talking about joining, not the *name* of the thing.
> > 
> > If we had that in place, we could turn the whole joiner loop here from
> > enumerating the enums to enumerating the number of joined pipes. and
> > whether we can join them. No need for the enum at all, and I think the
> > code might end up cleaner too.
> 
> Oh yes you are right! It will indeed be more intuitive to iterate over
> number of pipes we want to join rather than iterating over the joiner type.
> 
> Still need that weird force joiner index though.

Agreed, a simple loop over the possible number of joined pipes would be
cleaner.

> 
> Also realized check for NO_JOINER should have been (joiner > NO_JOINER ...)
> 
> This explains the BAT issues. (With above suggestion this will be not be
> needed).
> 
> > 
> > 
> > > +			break;
> > > +
> > > +		if (mode->hdisplay > num_joined_pipes * intel_dp_hdisplay_limit(display))
> > > +			continue;
> > > +
> > > +		status = intel_pfit_mode_valid(display, mode, output_format, num_joined_pipes);
> > > +		if (status != MODE_OK)
> > > +			continue;
> > > +
> > > +		if (intel_dp_has_dsc(connector)) {
> > > +			int pipe_bpp;
> > > +
> > > +			/*
> > > +			 * TBD pass the connector BPC,
> > > +			 * for now U8_MAX so that max BPC on that platform would be picked
> > > +			 */
> > > +			pipe_bpp = intel_dp_dsc_compute_max_bpp(connector, U8_MAX);
> > > +
> > > +			/*
> > > +			 * Output bpp is stored in 6.4 format so right shift by 4 to get the
> > > +			 * integer value since we support only integer values of bpp.
> > > +			 */
> > > +			if (intel_dp_is_edp(intel_dp)) {
> > > +				dsc_max_compressed_bpp =
> > > +					drm_edp_dsc_sink_output_bpp(connector->dp.dsc_dpcd) >> 4;
> > > +
> > > +				dsc_slice_count =
> > > +					intel_dp_dsc_get_slice_count(connector,
> > > +								     target_clock,
> > > +								     mode->hdisplay,
> > > +								     num_joined_pipes);
> > > +
> > > +				dsc = dsc_max_compressed_bpp && dsc_slice_count;
> > > +			} else if (drm_dp_sink_supports_fec(connector->dp.fec_capability)) {
> > > +				unsigned long bw_overhead_flags = 0;
> > > +
> > > +				if (!drm_dp_is_uhbr_rate(max_link_clock))
> > > +					bw_overhead_flags |= DRM_DP_BW_OVERHEAD_FEC;
> > > +
> > > +				dsc = intel_dp_mode_valid_with_dsc(connector,
> > > +								   max_link_clock, max_lanes,
> > > +								   target_clock, mode->hdisplay,
> > > +								   num_joined_pipes,
> > > +								   output_format, pipe_bpp,
> > > +								   bw_overhead_flags);
> > > +			}
> > > +		}
> > > +
> > > +		if (intel_dp_joiner_needs_dsc(display, num_joined_pipes) && !dsc)
> > > +			continue;
> > > +
> > > +		if (mode_rate > max_rate && !dsc)
> > > +			continue;
> > > +
> > > +		status = intel_mode_valid_max_plane_size(display, mode, num_joined_pipes);
> > > +		if (status != MODE_OK)
> > > +			continue;
> > > +
> > > +		max_dotclk *= num_joined_pipes;
> > > +
> > > +		if (target_clock <= max_dotclk) {
> > > +			status = MODE_OK;
> > > +			break;
> > >   		}
> > >   	}
> > > -	if (intel_dp_joiner_needs_dsc(display, num_joined_pipes) && !dsc)
> > > -		return MODE_CLOCK_HIGH;
> > > -
> > > -	status = intel_mode_valid_max_plane_size(display, mode, num_joined_pipes);
> > >   	if (status != MODE_OK)
> > >   		return status;
> > > -	if (mode_rate > max_rate && !dsc)
> > > -		return MODE_CLOCK_HIGH;
> > > -
> > >   	return intel_dp_mode_valid_downstream(connector, mode, target_clock);
> > > +
> > >   }
> > >   bool intel_dp_source_supports_tps3(struct intel_display *display)
> > > diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
> > > index 25bfbfd291b0..a27e3b5829bd 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_dp.h
> > > +++ b/drivers/gpu/drm/i915/display/intel_dp.h
> > > @@ -24,6 +24,13 @@ struct intel_display;
> > >   struct intel_dp;
> > >   struct intel_encoder;
> > > +enum joiner_type {
> > I wrote the below *before* I wrote the comment above, which makes all of
> > this moot, but here goes anyway:
> > 
> > "joiner_type" is too generic, it needs a prefix.
> > 
> > > +	FORCED_JOINER = -1,
> > > +	NO_JOINER = 0,		/* 1 pipe */
> > > +	BIG_JOINER = 1,		/* 2 pipes */
> > > +	ULTRA_JOINER = 2,	/* 4 pipes */
> > Ditto for the enumerations. Why are you explicitly initializing the
> > values, are they somehow meaningful?
> 
> The idea was to shift 1 << joiner_type to get number of pipes that are used.
> 
> Wanted to check for forced joiner first that we get from the debugfs, if the
> value provided can be supported well and good but if it cannot be supported,
> we do our default thing from next iteration onward.
> 
> 
> > 
> > > +};
> > The enum is about the joiner, not about DP. intel_dp.h doesn't have
> > anything that requires the joiner type.
> 
> Agreed. This is more of a DSS CTL thing.
> 
> 
> Regards,
> 
> Ankit
> 
> > 
> > > +
> > >   struct link_config_limits {
> > >   	int min_rate, max_rate;
> > >   	int min_lane_count, max_lane_count;

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

* Re: [PATCH 05/14] drm/i915/dp: Rework pipe joiner logic in compute_config
  2026-01-21  3:53 ` [PATCH 05/14] drm/i915/dp: Rework pipe joiner logic in compute_config Ankit Nautiyal
@ 2026-01-23 19:06   ` Imre Deak
  0 siblings, 0 replies; 28+ messages in thread
From: Imre Deak @ 2026-01-23 19:06 UTC (permalink / raw)
  To: Ankit Nautiyal; +Cc: intel-gfx, intel-xe

On Wed, Jan 21, 2026 at 09:23:21AM +0530, Ankit Nautiyal wrote:
> Currently, the number of joined pipes are determined early in the flow,
> which limits flexibility for accounting DSC slice overhead. To address
> this, recompute the joined pipe count during DSC configuration.
> 
> Refactor intel_dp_dsc_compute_config() to iterate over joiner candidates
> and select the minimal joiner configuration that satisfies the mode
> requirements. This prepares the logic for future changes that will
> consider DSC slice overhead.
> 
> Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_dp.c | 102 +++++++++++++++++++-----
>  1 file changed, 84 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index 02381f84fa58..d96d9ac1e830 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -2790,33 +2790,20 @@ bool intel_dp_joiner_needs_dsc(struct intel_display *display,
>  }
>  
>  static int
> -intel_dp_compute_link_config(struct intel_encoder *encoder,
> -			     struct intel_crtc_state *pipe_config,
> -			     struct drm_connector_state *conn_state,
> -			     bool respect_downstream_limits)
> +_intel_dp_compute_link_config(struct intel_encoder *encoder,

intel_dp_compute_link_for_joined_pipes(), similarly to the MST
counterpart?

> +			      struct intel_crtc_state *pipe_config,
> +			      struct drm_connector_state *conn_state,
> +			      bool respect_downstream_limits)
>  {
>  	struct intel_display *display = to_intel_display(encoder);
> -	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
> +	int num_joined_pipes = intel_crtc_num_joined_pipes(pipe_config);
>  	struct intel_connector *connector =
>  		to_intel_connector(conn_state->connector);
> -	const struct drm_display_mode *adjusted_mode =
> -		&pipe_config->hw.adjusted_mode;
>  	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
>  	struct link_config_limits limits;
>  	bool dsc_needed, joiner_needs_dsc;
> -	int num_joined_pipes;
>  	int ret = 0;
>  
> -	if (pipe_config->fec_enable &&
> -	    !intel_dp_supports_fec(intel_dp, connector, pipe_config))
> -		return -EINVAL;
> -
> -	num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector,
> -						     adjusted_mode->crtc_hdisplay,
> -						     adjusted_mode->crtc_clock);
> -	if (num_joined_pipes > 1)
> -		pipe_config->joiner_pipes = GENMASK(crtc->pipe + num_joined_pipes - 1, crtc->pipe);
> -
>  	joiner_needs_dsc = intel_dp_joiner_needs_dsc(display, num_joined_pipes);
>  
>  	dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
> @@ -2879,6 +2866,85 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
>  	return 0;
>  }
>  
> +static int
> +intel_dp_compute_link_config(struct intel_encoder *encoder,
> +			     struct intel_crtc_state *crtc_state,
> +			     struct drm_connector_state *conn_state,
> +			     bool respect_downstream_limits)
> +{
> +	struct intel_display *display = to_intel_display(encoder);
> +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> +	struct intel_connector *connector =
> +		to_intel_connector(conn_state->connector);
> +	const struct drm_display_mode *adjusted_mode =
> +		&crtc_state->hw.adjusted_mode;
> +	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> +	int num_joined_pipes;
> +	int ret = 0;
> +	int i;
> +
> +	if (crtc_state->fec_enable &&
> +	    !intel_dp_supports_fec(intel_dp, connector, crtc_state))
> +		return -EINVAL;
> +
> +	for (i = 0; i < ARRAY_SIZE(joiner_candidates); i++) {
> +		enum joiner_type joiner = joiner_candidates[i];
> +		int max_dotclk = display->cdclk.max_dotclk_freq;
> +
> +		if (joiner == FORCED_JOINER) {
> +			if (!connector->force_joined_pipes)
> +				continue;
> +			num_joined_pipes = connector->force_joined_pipes;
> +		} else {
> +			num_joined_pipes = 1 << joiner;
> +		}
> +
> +		if ((joiner >= NO_JOINER && !intel_dp_has_joiner(intel_dp)) ||
> +		    (joiner == BIG_JOINER && !HAS_BIGJOINER(display)) ||
> +		    (joiner == ULTRA_JOINER && !HAS_ULTRAJOINER(display))) {
> +			ret = -EINVAL;
> +			break;

A simple loop over the number of possible joined pipes would be simpler
here as well, as in the mode_valid() function.

> +		}
> +
> +		if (adjusted_mode->hdisplay > num_joined_pipes * intel_dp_hdisplay_limit(display))
> +			continue;
> +
> +		/*
> +		 * NOTE:
> +		 * The crtc_state->joiner_pipes should have been set at the end
> +		 * only if all the conditions are met. However that would mean
> +		 * that num_joined_pipes is passed around to all helpers and
> +		 * make them use it instead of using crtc_state->joiner_pipes
> +		 * directly or indirectly (via intel_crtc_num_joined_pipes()).
> +		 *
> +		 * For now, setting crtc_state->joiner_pipes to the candidate
> +		 * value to avoid the above churn and resetting it to 0, in case
> +		 * no joiner candidate is found to be suitable for the given
> +		 * configuration.
> +		 */
> +		if (num_joined_pipes > 1)
> +			crtc_state->joiner_pipes = GENMASK(crtc->pipe + num_joined_pipes - 1,
> +							   crtc->pipe);
> +
> +		ret = _intel_dp_compute_link_config(encoder, crtc_state, conn_state,
> +						    respect_downstream_limits);
> +		if (ret)
> +			continue;
> +
> +		max_dotclk *= num_joined_pipes;
> +
> +		if (adjusted_mode->crtc_clock <= max_dotclk) {

There seems to be a difference in the maximum dotclock for the DSC and
non-DSC modes, introduced later in the patchset. Since the non-DSC max
dotclock may be lower than the DSC one (oddly), there should be a
fallback to DSC mode for a given number of joined pipes if the non-DSC
mode is not possible with the same number of joined pipes because of the
mode specific dot clock limit. So the above check should be moved to
intel_dp_compute_link_for_joined_pipes() and performed for both the DSC
and non-DSC modes.

> +			ret = 0;
> +			break;
> +		}
> +	}
> +
> +	if (ret < 0)
> +		crtc_state->joiner_pipes = 0;
> +
> +	return ret;
> +}
> +
>  bool intel_dp_limited_color_range(const struct intel_crtc_state *crtc_state,
>  				  const struct drm_connector_state *conn_state)
>  {
> -- 
> 2.45.2
> 

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

* Re: [PATCH 06/14] drm/i915/dp_mst: Move the check for dotclock at the end
  2026-01-21  3:53 ` [PATCH 06/14] drm/i915/dp_mst: Move the check for dotclock at the end Ankit Nautiyal
@ 2026-01-23 19:11   ` Imre Deak
  0 siblings, 0 replies; 28+ messages in thread
From: Imre Deak @ 2026-01-23 19:11 UTC (permalink / raw)
  To: Ankit Nautiyal; +Cc: intel-gfx, intel-xe

On Wed, Jan 21, 2026 at 09:23:22AM +0530, Ankit Nautiyal wrote:
> Refactor the mode_valid to have all joiner dependent stuff together and
> place the check for dotclock limit at the very end.
> 
> This will help in the following refactor to iterate over the joiner
> candidates and find the best joiner candidate that satisfy all checks
> and limits.
> 
> Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_dp_mst.c | 18 +++++++++++++-----
>  1 file changed, 13 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> index 24f8e60df9ac..31e2eae6e4b3 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> @@ -1470,20 +1470,19 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector,
>  	 *   corresponding link capabilities of the sink) in case the
>  	 *   stream is uncompressed for it by the last branch device.
>  	 */
> -	num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector,
> -						     mode->hdisplay, target_clock);
> -	max_dotclk *= num_joined_pipes;
> -
>  	ret = drm_modeset_lock(&mgr->base.lock, ctx);
>  	if (ret)
>  		return ret;
>  
> -	if (mode_rate > max_rate || mode->clock > max_dotclk ||
> +	if (mode_rate > max_rate ||
>  	    drm_dp_calc_pbn_mode(mode->clock, min_bpp << 4) > port->full_pbn) {
>  		*status = MODE_CLOCK_HIGH;
>  		return 0;
>  	}
>  
> +	num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector,
> +						     mode->hdisplay, target_clock);
> +
>  	if (intel_dp_has_dsc(connector) && drm_dp_sink_supports_fec(connector->dp.fec_capability)) {
>  		/*
>  		 * TBD pass the connector BPC,
> @@ -1513,6 +1512,15 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector,
>  	}
>  
>  	*status = intel_mode_valid_max_plane_size(display, mode, num_joined_pipes);
> +
> +	if (*status != MODE_OK)
> +		return 0;
> +
> +	max_dotclk *= num_joined_pipes;
> +
> +	if (mode->clock <= max_dotclk)
> +		*status = MODE_OK;

This leaves *status set to MODE_OK if mode->clock > max_dotclk.

> +
>  	return 0;
>  }
>  
> -- 
> 2.45.2
> 

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

* Re: [PATCH 07/14] drm/i915/dp_mst: Move the joiner dependent code together
  2026-01-21  3:53 ` [PATCH 07/14] drm/i915/dp_mst: Move the joiner dependent code together Ankit Nautiyal
@ 2026-01-23 19:16   ` Imre Deak
  0 siblings, 0 replies; 28+ messages in thread
From: Imre Deak @ 2026-01-23 19:16 UTC (permalink / raw)
  To: Ankit Nautiyal; +Cc: intel-gfx, intel-xe

On Wed, Jan 21, 2026 at 09:23:23AM +0530, Ankit Nautiyal wrote:
> Move the calculation of num_joined_pipes and other constraints that
> depend on it, into a single block in mst_stream_compute_config().
> 
> This groups all joiner-dependent logic together, preparing the code for a
> future loop-based evaluation of multiple joiner configurations.
> 
> Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>

Reviewed-by: Imre Deak <imre.deak@intel.com>

> ---
>  drivers/gpu/drm/i915/display/intel_dp_mst.c | 16 ++++++++--------
>  1 file changed, 8 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> index 31e2eae6e4b3..8a42da2588eb 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> @@ -619,16 +619,16 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
>  	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
>  		return -EINVAL;
>  
> +	pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
> +	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
> +	pipe_config->has_pch_encoder = false;
> +
>  	num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector,
>  						     adjusted_mode->crtc_hdisplay,
>  						     adjusted_mode->crtc_clock);
>  	if (num_joined_pipes > 1)
>  		pipe_config->joiner_pipes = GENMASK(crtc->pipe + num_joined_pipes - 1, crtc->pipe);
>  
> -	pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
> -	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
> -	pipe_config->has_pch_encoder = false;
> -
>  	joiner_needs_dsc = intel_dp_joiner_needs_dsc(display, num_joined_pipes);
>  
>  	dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
> @@ -685,6 +685,10 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
>  						  pipe_config->dp_m_n.tu);
>  	}
>  
> +	if (ret)
> +		return ret;
> +
> +	ret = intel_dp_compute_min_hblank(pipe_config, conn_state);
>  	if (ret)
>  		return ret;
>  
> @@ -695,10 +699,6 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
>  		pipe_config->lane_lat_optim_mask =
>  			bxt_dpio_phy_calc_lane_lat_optim_mask(pipe_config->lane_count);
>  
> -	ret = intel_dp_compute_min_hblank(pipe_config, conn_state);
> -	if (ret)
> -		return ret;
> -
>  	intel_vrr_compute_config(pipe_config, conn_state);
>  
>  	intel_dp_audio_compute_config(encoder, pipe_config, conn_state);
> -- 
> 2.45.2
> 

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

* Re: [PATCH 09/14] drm/i915/dp_mst: Extract helper to compute link for given joiner config
  2026-01-21  3:53 ` [PATCH 09/14] drm/i915/dp_mst: Extract helper to compute link for given joiner config Ankit Nautiyal
@ 2026-01-23 19:23   ` Imre Deak
  0 siblings, 0 replies; 28+ messages in thread
From: Imre Deak @ 2026-01-23 19:23 UTC (permalink / raw)
  To: Ankit Nautiyal; +Cc: intel-gfx, intel-xe

On Wed, Jan 21, 2026 at 09:23:25AM +0530, Ankit Nautiyal wrote:
> Move the joiner-dependent portion of mst_stream_compute_config() into
> mst_stream_compute_link_for_joined_pipes(), which computes the MST link
> configuration for a specific num_joined_pipes.
> 
> Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>

Reviewed-by: Imre Deak <imre.deak@intel.com>

> ---
>  drivers/gpu/drm/i915/display/intel_dp_mst.c | 72 ++++++++++++++-------
>  1 file changed, 47 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> index 3b1825161d18..e9cfce00efcc 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> @@ -602,40 +602,19 @@ mst_stream_compute_config_limits(struct intel_dp *intel_dp,
>  							    dsc);
>  }
>  
> -static int mst_stream_compute_config(struct intel_encoder *encoder,
> -				     struct intel_crtc_state *pipe_config,
> -				     struct drm_connector_state *conn_state)
> +static int mst_stream_compute_link_for_joined_pipes(struct intel_encoder *encoder,
> +						    struct intel_crtc_state *pipe_config,
> +						    struct drm_connector_state *conn_state,
> +						    int num_joined_pipes)
>  {
>  	struct intel_display *display = to_intel_display(encoder);
> -	struct intel_atomic_state *state = to_intel_atomic_state(conn_state->state);
> -	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
>  	struct intel_dp *intel_dp = to_primary_dp(encoder);
>  	struct intel_connector *connector =
>  		to_intel_connector(conn_state->connector);
> -	const struct drm_display_mode *adjusted_mode =
> -		&pipe_config->hw.adjusted_mode;
>  	struct link_config_limits limits;
>  	bool dsc_needed, joiner_needs_dsc;
> -	int num_joined_pipes;
>  	int ret = 0;
>  
> -	if (pipe_config->fec_enable &&
> -	    !intel_dp_supports_fec(intel_dp, connector, pipe_config))
> -		return -EINVAL;
> -
> -	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
> -		return -EINVAL;
> -
> -	pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
> -	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
> -	pipe_config->has_pch_encoder = false;
> -
> -	num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector,
> -						     adjusted_mode->crtc_hdisplay,
> -						     adjusted_mode->crtc_clock);
> -	if (num_joined_pipes > 1)
> -		pipe_config->joiner_pipes = GENMASK(crtc->pipe + num_joined_pipes - 1, crtc->pipe);
> -
>  	joiner_needs_dsc = intel_dp_joiner_needs_dsc(display, num_joined_pipes);
>  
>  	dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
> @@ -699,6 +678,49 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
>  	if (ret)
>  		return ret;
>  
> +	return 0;
> +}
> +
> +static int mst_stream_compute_config(struct intel_encoder *encoder,
> +				     struct intel_crtc_state *pipe_config,
> +				     struct drm_connector_state *conn_state)
> +{
> +	struct intel_display *display = to_intel_display(encoder);
> +	struct intel_atomic_state *state = to_intel_atomic_state(conn_state->state);
> +	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
> +	struct intel_dp *intel_dp = to_primary_dp(encoder);
> +	struct intel_connector *connector =
> +		to_intel_connector(conn_state->connector);
> +	const struct drm_display_mode *adjusted_mode =
> +		&pipe_config->hw.adjusted_mode;
> +	int num_joined_pipes;
> +	int ret = 0;
> +
> +	if (pipe_config->fec_enable &&
> +	    !intel_dp_supports_fec(intel_dp, connector, pipe_config))
> +		return -EINVAL;
> +
> +	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
> +		return -EINVAL;
> +
> +	pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
> +	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
> +	pipe_config->has_pch_encoder = false;
> +
> +	num_joined_pipes = intel_dp_num_joined_pipes(intel_dp, connector,
> +						     adjusted_mode->crtc_hdisplay,
> +						     adjusted_mode->crtc_clock);
> +
> +	if (num_joined_pipes > 1)
> +		pipe_config->joiner_pipes = GENMASK(crtc->pipe + num_joined_pipes - 1, crtc->pipe);
> +
> +	ret = mst_stream_compute_link_for_joined_pipes(encoder,
> +						       pipe_config,
> +						       conn_state,
> +						       num_joined_pipes);
> +	if (ret)
> +		return ret;
> +
>  	pipe_config->limited_color_range =
>  		intel_dp_limited_color_range(pipe_config, conn_state);
>  
> -- 
> 2.45.2
> 

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

* Re: [PATCH 11/14] drm/i915/dp: Introduce helper to check pixel rate against dotclock limits
  2026-01-21  3:53 ` [PATCH 11/14] drm/i915/dp: Introduce helper to check pixel rate against dotclock limits Ankit Nautiyal
@ 2026-01-23 19:30   ` Imre Deak
  0 siblings, 0 replies; 28+ messages in thread
From: Imre Deak @ 2026-01-23 19:30 UTC (permalink / raw)
  To: Ankit Nautiyal; +Cc: intel-gfx, intel-xe

On Wed, Jan 21, 2026 at 09:23:27AM +0530, Ankit Nautiyal wrote:
> Add intel_dp_pixel_rate_fits_dotclk() helper, that checks the
> required pixel rate against platform dotclock limit.
> With joined pipes the effective dotclock limit depends upon the number
> of joined pipes.
> 
> Call the helper from the mode_valid phase and from the compute_config
> phase where we need to check the limits for the given target clock for a
> given joiner candidate.
> 
> Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_dp.c     | 26 ++++++++++++++-------
>  drivers/gpu/drm/i915/display/intel_dp.h     |  3 +++
>  drivers/gpu/drm/i915/display/intel_dp_mst.c | 14 +++++------
>  3 files changed, 27 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index 2ead783129f4..ed81cf4adb9b 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -1440,6 +1440,18 @@ bool intel_dp_has_dsc(const struct intel_connector *connector)
>  	return true;
>  }
>  
> +bool intel_dp_pixel_rate_fits_dotclk(struct intel_display *display,

intel_dp_dotclk_valid()?

> +				     int target_clock,
> +				     int num_joined_pipes)
> +{
> +	int max_dotclk = display->cdclk.max_dotclk_freq;
> +	int effective_dotclk_limit;
> +
> +	effective_dotclk_limit = max_dotclk * num_joined_pipes;
> +
> +	return target_clock <= effective_dotclk_limit;
> +}
> +
>  static enum drm_mode_status
>  intel_dp_mode_valid(struct drm_connector *_connector,
>  		    const struct drm_display_mode *mode)
> @@ -1495,7 +1507,6 @@ intel_dp_mode_valid(struct drm_connector *_connector,
>  					   link_bpp_x16, 0);
>  
>  	for (i = 0; i < ARRAY_SIZE(joiner_candidates); i++) {
> -		int max_dotclk = display->cdclk.max_dotclk_freq;
>  		enum joiner_type joiner = joiner_candidates[i];
>  
>  		status = MODE_CLOCK_HIGH;
> @@ -1569,9 +1580,9 @@ intel_dp_mode_valid(struct drm_connector *_connector,
>  		if (status != MODE_OK)
>  			continue;
>  
> -		max_dotclk *= num_joined_pipes;
> -
> -		if (target_clock <= max_dotclk) {
> +		if (intel_dp_pixel_rate_fits_dotclk(display,
> +						    target_clock,
> +						    num_joined_pipes)) {
>  			status = MODE_OK;
>  			break;
>  		}
> @@ -2888,7 +2899,6 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
>  
>  	for (i = 0; i < ARRAY_SIZE(joiner_candidates); i++) {
>  		enum joiner_type joiner = joiner_candidates[i];
> -		int max_dotclk = display->cdclk.max_dotclk_freq;
>  
>  		if (joiner == FORCED_JOINER) {
>  			if (!connector->force_joined_pipes)
> @@ -2930,9 +2940,9 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
>  		if (ret)
>  			continue;
>  
> -		max_dotclk *= num_joined_pipes;
> -
> -		if (adjusted_mode->crtc_clock <= max_dotclk) {
> +		if (intel_dp_pixel_rate_fits_dotclk(display,
> +						    adjusted_mode->crtc_clock,
> +						    num_joined_pipes)) {
>  			ret = 0;
>  			break;
>  		}
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
> index e5913fba0143..0c1cd843bd0a 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.h
> +++ b/drivers/gpu/drm/i915/display/intel_dp.h
> @@ -233,5 +233,8 @@ int intel_dp_compute_config_late(struct intel_encoder *encoder,
>  int intel_dp_sdp_min_guardband(const struct intel_crtc_state *crtc_state,
>  			       bool assume_all_enabled);
>  int intel_dp_hdisplay_limit(struct intel_display *display);
> +bool intel_dp_pixel_rate_fits_dotclk(struct intel_display *display,
> +				     int target_clock,
> +				     int num_joined_pipes);
>  
>  #endif /* __INTEL_DP_H__ */
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> index 46208ee67905..7c957351467e 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
> @@ -710,7 +710,6 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
>  
>  	for (i = 0; i < ARRAY_SIZE(joiner_candidates); i++) {
>  		enum joiner_type joiner = joiner_candidates[i];
> -		int max_dotclk = display->cdclk.max_dotclk_freq;
>  
>  		ret = -EINVAL;
>  
> @@ -742,9 +741,9 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
>  		if (ret)
>  			continue;
>  
> -		max_dotclk *= num_joined_pipes;
> -
> -		if (adjusted_mode->clock <= max_dotclk) {
> +		if (intel_dp_pixel_rate_fits_dotclk(display,
> +						    adjusted_mode->clock,
> +						    num_joined_pipes)) {
>  			ret = 0;
>  			break;
>  		}
> @@ -1542,7 +1541,6 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector,
>  	}
>  
>  	for (i = 0; i < ARRAY_SIZE(joiner_candidates); i++) {
> -		int max_dotclk = display->cdclk.max_dotclk_freq;
>  		enum joiner_type joiner = joiner_candidates[i];
>  
>  		*status = MODE_CLOCK_HIGH;
> @@ -1593,9 +1591,9 @@ mst_connector_mode_valid_ctx(struct drm_connector *_connector,
>  		if (*status != MODE_OK)
>  			continue;
>  
> -		max_dotclk *= num_joined_pipes;
> -
> -		if (mode->clock <= max_dotclk) {
> +		if (intel_dp_pixel_rate_fits_dotclk(display,
> +						    mode->clock,
> +						    num_joined_pipes)) {
>  			*status = MODE_OK;
>  			break;
>  		}
> -- 
> 2.45.2
> 

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

* Re: [PATCH 14/14] drm/i915/display: Add upper limit check for pixel clock
  2026-01-21  3:53 ` [PATCH 14/14] drm/i915/display: Add upper limit check for pixel clock Ankit Nautiyal
@ 2026-01-23 19:48   ` Imre Deak
  0 siblings, 0 replies; 28+ messages in thread
From: Imre Deak @ 2026-01-23 19:48 UTC (permalink / raw)
  To: Ankit Nautiyal; +Cc: intel-gfx, intel-xe, Chaitanya Kumar Borah

On Wed, Jan 21, 2026 at 09:23:30AM +0530, Ankit Nautiyal wrote:
> From: Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com>
> 
> Add upper limit check for pixel clock by platform. Limits don't apply
> when DSC is enabled.
> 
> For the currently supported versions of HDMI, pixel clock is already
> limited to 600Mhz so nothing needs to be done there as of now.
> 
> BSpec: 49199, 68912
> 
> v2: Add this limit to the new helper
>     intel_dp_pixel_rate_fits_dotclk(). (Ankit)
> 
> Signed-off-by: Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com>
> Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_display.c | 12 ++++++++++++
>  drivers/gpu/drm/i915/display/intel_display.h |  1 +
>  drivers/gpu/drm/i915/display/intel_dp.c      |  3 +++
>  3 files changed, 16 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 7491e00e3858..04021ad6b473 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -8001,6 +8001,18 @@ void intel_setup_outputs(struct intel_display *display)
>  	drm_helper_move_panel_connectors_to_head(display->drm);
>  }
>  
> +int intel_dotclock_limit(struct intel_display *display)

The name should reflect that it's the (stricter) non-DSC dotclock limit,
so maybe intel_max_uncompressed_dotclock()?

> +{

I guess display->cdclk.max_dotclk_freq could be used as a base, reducing
it if needed.

> +	if (DISPLAY_VERx100(display) == 3002)
> +		return 937500;

While the above WCL limit is indeed in bspec, I couldn't find the HSD
for it. Windows doesn't use this limit either. So could it be a
follow-up to add the limit for this platform, to reduce the number of
affacted platforms until it's clarified why Windows doesn't use it?

> +	else if (DISPLAY_VER(display) >= 30)
> +		return 1350000;

This one for PTL matches bspec, there is an HSD for it and it is also
used by Windows.

> +	else if (DISPLAY_VER(display) >= 13)
> +		return 1200000;
> +	else
> +		return 1100000;

The above ICL-MTL limits are not used by Windows either and I couldn't
find the corresponding HSDs. So could adding these two be done
separately as a follow-up (even though they are listed by bspec)?

> +}
> +
>  static int max_dotclock(struct intel_display *display)
>  {
>  	int max_dotclock = display->cdclk.max_dotclk_freq;
> diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
> index f8e6e4e82722..0009c305f140 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.h
> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> @@ -488,6 +488,7 @@ void intel_cpu_transcoder_get_m2_n2(struct intel_crtc *crtc,
>  				    struct intel_link_m_n *m_n);
>  int intel_dotclock_calculate(int link_freq, const struct intel_link_m_n *m_n);
>  int intel_crtc_dotclock(const struct intel_crtc_state *pipe_config);
> +int intel_dotclock_limit(struct intel_display *display);
>  enum intel_display_power_domain intel_port_to_power_domain(struct intel_digital_port *dig_port);
>  enum intel_display_power_domain
>  intel_aux_power_domain(struct intel_digital_port *dig_port);
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index a6a1a803d860..bd8ba6db01db 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -1456,6 +1456,9 @@ bool intel_dp_pixel_rate_fits_dotclk(struct intel_display *display,
>  									 target_clock,
>  									 htotal,
>  									 dsc_slice_count);
> +	else
> +		effective_dotclk_limit =
> +			min(max_dotclk, intel_dotclock_limit(display)) * num_joined_pipes;
>  
>  	return target_clock <= effective_dotclk_limit;
>  }
> -- 
> 2.45.2
> 

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

end of thread, other threads:[~2026-01-23 19:48 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-21  3:53 [PATCH 00/14] Account for DSC bubble overhead for horizontal slices Ankit Nautiyal
2026-01-21  3:53 ` [PATCH 01/14] drm/i915/dp: Early reject bad hdisplay in intel_dp_mode_valid Ankit Nautiyal
2026-01-23 18:06   ` Imre Deak
2026-01-21  3:53 ` [PATCH 02/14] drm/i915/dp: Move num_joined_pipes and related checks together Ankit Nautiyal
2026-01-23 18:25   ` Imre Deak
2026-01-21  3:53 ` [PATCH 03/14] drm/i915/dp: Extract helper to get the hdisplay limit Ankit Nautiyal
2026-01-23 18:28   ` Imre Deak
2026-01-21  3:53 ` [PATCH 04/14] drm/i915/dp: Rework pipe joiner logic in mode_valid Ankit Nautiyal
2026-01-21 10:54   ` Jani Nikula
2026-01-21 11:19     ` Nautiyal, Ankit K
2026-01-23 18:44       ` Imre Deak
2026-01-21  3:53 ` [PATCH 05/14] drm/i915/dp: Rework pipe joiner logic in compute_config Ankit Nautiyal
2026-01-23 19:06   ` Imre Deak
2026-01-21  3:53 ` [PATCH 06/14] drm/i915/dp_mst: Move the check for dotclock at the end Ankit Nautiyal
2026-01-23 19:11   ` Imre Deak
2026-01-21  3:53 ` [PATCH 07/14] drm/i915/dp_mst: Move the joiner dependent code together Ankit Nautiyal
2026-01-23 19:16   ` Imre Deak
2026-01-21  3:53 ` [PATCH 08/14] drm/i915/dp_mst: Rework pipe joiner logic in mode_valid Ankit Nautiyal
2026-01-21  3:53 ` [PATCH 09/14] drm/i915/dp_mst: Extract helper to compute link for given joiner config Ankit Nautiyal
2026-01-23 19:23   ` Imre Deak
2026-01-21  3:53 ` [PATCH 10/14] drm/i915/dp_mst: Rework pipe joiner logic in compute_config Ankit Nautiyal
2026-01-21  3:53 ` [PATCH 11/14] drm/i915/dp: Introduce helper to check pixel rate against dotclock limits Ankit Nautiyal
2026-01-23 19:30   ` Imre Deak
2026-01-21  3:53 ` [PATCH 12/14] drm/i915/dp: Refactor dsc_slice_count handling in intel_dp_mode_valid() Ankit Nautiyal
2026-01-21  3:53 ` [PATCH 13/14] drm/i915/dp: Account for DSC slice overhead Ankit Nautiyal
2026-01-21  3:53 ` [PATCH 14/14] drm/i915/display: Add upper limit check for pixel clock Ankit Nautiyal
2026-01-23 19:48   ` Imre Deak
2026-01-21  5:59 ` ✗ i915.CI.BAT: failure for Account for DSC bubble overhead for horizontal slices (rev3) Patchwork

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