diff mbox series

[13/16] drm/i915/dp: Enable DSC pixel replication

Message ID 20241023065257.190035-14-ankit.k.nautiyal@intel.com (mailing list archive)
State New
Headers show
Series Add support for 3 VDSC engines 12 slices | expand

Commit Message

Ankit Nautiyal Oct. 23, 2024, 6:52 a.m. UTC
Allow DSC slice count that do not divide the hactive evenly by adding
extra pixels (replicated pixels).
Check if the pixel replication is supported and store the no. of
replicated pixel count in crtc_state.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c     | 20 +++++++++++++++--
 drivers/gpu/drm/i915/display/intel_dp.h     |  1 +
 drivers/gpu/drm/i915/display/intel_dp_mst.c |  2 ++
 drivers/gpu/drm/i915/display/intel_vdsc.c   | 25 ++++++++++++++++-----
 drivers/gpu/drm/i915/display/intel_vdsc.h   |  3 +++
 5 files changed, 44 insertions(+), 7 deletions(-)
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index f4a446824cb3..026254687a8d 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -992,9 +992,11 @@  u16 intel_dp_dsc_get_max_compressed_bpp(struct drm_i915_private *i915,
 
 u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
 				int mode_clock, int mode_hdisplay,
+				enum intel_output_format output_format,
 				int num_joined_pipes)
 {
-	struct drm_i915_private *i915 = to_i915(connector->base.dev);
+	struct intel_display *display = to_intel_display(connector);
+	struct drm_i915_private *i915 = to_i915(display->drm);
 	u8 min_slice_count, i;
 	int max_slice_width;
 
@@ -1047,7 +1049,11 @@  u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
 		if (num_joined_pipes > 1 && valid_dsc_slicecount[i] < 2)
 			continue;
 
-		if (mode_hdisplay % test_slice_count)
+		if (mode_hdisplay % test_slice_count &&
+		    !intel_dsc_can_use_pixel_replication(display,
+							 mode_hdisplay,
+							 test_slice_count,
+							 output_format))
 			continue;
 
 		if (min_slice_count <= test_slice_count)
@@ -1474,6 +1480,7 @@  intel_dp_mode_valid(struct drm_connector *_connector,
 				intel_dp_dsc_get_slice_count(connector,
 							     target_clock,
 							     mode->hdisplay,
+							     output_format,
 							     num_joined_pipes);
 		}
 
@@ -2366,6 +2373,7 @@  int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
 				int timeslots,
 				bool compute_pipe_bpp)
 {
+	struct intel_display *display = to_intel_display(intel_dp);
 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
 	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
 	const struct intel_connector *connector =
@@ -2428,6 +2436,7 @@  int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
 			intel_dp_dsc_get_slice_count(connector,
 						     adjusted_mode->crtc_clock,
 						     adjusted_mode->crtc_hdisplay,
+						     pipe_config->output_format,
 						     num_joined_pipes);
 		if (!dsc_dp_slice_count) {
 			drm_dbg_kms(&dev_priv->drm,
@@ -2437,6 +2446,13 @@  int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
 
 		pipe_config->dsc.slice_count = dsc_dp_slice_count;
 	}
+
+	pipe_config->dsc.replicated_pixels =
+		intel_dsc_get_replicated_pixels(display,
+						adjusted_mode->crtc_hdisplay,
+						pipe_config->dsc.slice_count,
+						pipe_config->output_format);
+
 	/*
 	 * VDSC engine operates at 1 Pixel per clock, so if peak pixel rate
 	 * is greater than the maximum Cdclock and if slice count is even
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index e90a9dc1a8f5..7460675c16f6 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -150,6 +150,7 @@  int intel_dp_dsc_sink_max_compressed_bpp(const struct intel_connector *connector
 					 int bpc);
 u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
 				int mode_clock, int mode_hdisplay,
+				enum intel_output_format output_format,
 				int num_joined_pipes);
 int intel_dp_num_joined_pipes(struct intel_dp *intel_dp,
 			      struct intel_connector *connector,
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 2bd33e1b318e..794a5121e661 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -172,6 +172,7 @@  static int intel_dp_mst_dsc_get_slice_count(const struct intel_connector *connec
 	return intel_dp_dsc_get_slice_count(connector,
 					    adjusted_mode->clock,
 					    adjusted_mode->hdisplay,
+					    crtc_state->output_format,
 					    num_joined_pipes);
 }
 
@@ -1538,6 +1539,7 @@  intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
 				intel_dp_dsc_get_slice_count(intel_connector,
 							     target_clock,
 							     mode->hdisplay,
+							     INTEL_OUTPUT_FORMAT_RGB,
 							     num_joined_pipes);
 		}
 
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
index 9eaf608995dc..0aa2d96ee329 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.c
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
@@ -1041,6 +1041,22 @@  void intel_vdsc_state_dump(struct drm_printer *p, int indent,
 	drm_dsc_dump_config(p, indent, &crtc_state->dsc.config);
 }
 
+bool intel_dsc_can_use_pixel_replication(struct intel_display *display,
+					 int mode_hdisplay, u8 slice_count,
+					 enum intel_output_format output_format)
+{
+	int slice_width = DIV_ROUND_UP(mode_hdisplay, slice_count);
+
+	if (!HAS_PIXEL_REPLICATION(display))
+		return false;
+
+	/* Odd slice width is not supported by YCbCr420 format */
+	if (slice_width % 2 && output_format == INTEL_OUTPUT_FORMAT_YCBCR420)
+		return false;
+
+	return true;
+}
+
 int intel_dsc_get_replicated_pixels(struct intel_display *display,
 				    int mode_hdisplay,
 				    int slice_count,
@@ -1049,11 +1065,10 @@  int intel_dsc_get_replicated_pixels(struct intel_display *display,
 	int replicated_pixels;
 	int slice_width = DIV_ROUND_UP(mode_hdisplay, slice_count);
 
-	if (!HAS_PIXEL_REPLICATION(display))
-		return 0;
-
-	/* Odd slice width is not supported by YCbCr420 format */
-	if (slice_width % 2 && output_format == INTEL_OUTPUT_FORMAT_YCBCR420)
+	if (!intel_dsc_can_use_pixel_replication(display,
+						 mode_hdisplay,
+						 slice_count,
+						 output_format))
 		return 0;
 
 	replicated_pixels = (slice_width * slice_count) - mode_hdisplay;
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.h b/drivers/gpu/drm/i915/display/intel_vdsc.h
index 41b8b5c5866e..3611fc53840d 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.h
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.h
@@ -33,6 +33,9 @@  void intel_dsc_dp_pps_write(struct intel_encoder *encoder,
 			    const struct intel_crtc_state *crtc_state);
 void intel_vdsc_state_dump(struct drm_printer *p, int indent,
 			   const struct intel_crtc_state *crtc_state);
+bool intel_dsc_can_use_pixel_replication(struct intel_display *display,
+					 int mode_hdisplay, u8 slice_count,
+					 enum intel_output_format output_format);
 int intel_dsc_get_replicated_pixels(struct intel_display *display,
 				    int mode_hdisplay,
 				    int slice_count,