From: George Shen <george.s...@amd.com>

[Why]
Current BW calculations do not account for the additional padding added
for uncompressed pixel-to-symbol packing.

This results in X.Y being too low for 128b/132b SST streams in certain
scenarios. If X.Y is too low, end user can observe image corruption.

[How]
Add function to calculate stream overhead to timing BW calculation for
128b/132b SST cases.

Reviewed-by: Wenjing Liu <wenjing....@amd.com>
Acked-by: Alan Liu <haoping....@amd.com>
Signed-off-by: George Shen <george.s...@amd.com>
---
 drivers/gpu/drm/amd/display/dc/dc.h         |  2 +
 drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c | 42 +++++++++++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/dc.h 
b/drivers/gpu/drm/amd/display/dc/dc.h
index 819c326baefe..7aa7085c3bec 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -1410,6 +1410,8 @@ struct dc_plane_state *dc_get_surface_for_mpcc(struct dc 
*dc,
 
 uint32_t dc_get_opp_for_plane(struct dc *dc, struct dc_plane_state *plane);
 
+void dc_set_disable_128b_132b_stream_overhead(bool disable);
+
 /* The function returns minimum bandwidth required to drive a given timing
  * return - minimum required timing bandwidth in kbps.
  */
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c 
b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
index 58dd62cce4bb..aed0d3dafa24 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
@@ -40,6 +40,8 @@ static bool dsc_policy_enable_dsc_when_not_needed;
 
 static bool dsc_policy_disable_dsc_stream_overhead;
 
+static bool disable_128b_132b_stream_overhead;
+
 #ifndef MAX
 #define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
 #endif
@@ -47,6 +49,41 @@ static bool dsc_policy_disable_dsc_stream_overhead;
 #define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
 #endif
 
+/* Need to account for padding due to pixel-to-symbol packing
+ * for uncompressed 128b/132b streams.
+ */
+static uint32_t apply_128b_132b_stream_overhead(
+       const struct dc_crtc_timing *timing, const uint32_t kbps)
+{
+       uint32_t total_kbps = kbps;
+
+       if (disable_128b_132b_stream_overhead)
+               return kbps;
+
+       if (!timing->flags.DSC) {
+               struct fixed31_32 bpp;
+               struct fixed31_32 overhead_factor;
+
+               bpp = dc_fixpt_from_int(kbps);
+               bpp = dc_fixpt_div_int(bpp, timing->pix_clk_100hz / 10);
+
+               /* Symbols_per_HActive = HActive * bpp / (4 lanes * 32-bit 
symbol size)
+                * Overhead_factor = ceil(Symbols_per_HActive) / 
Symbols_per_HActive
+                */
+               overhead_factor = dc_fixpt_from_int(timing->h_addressable);
+               overhead_factor = dc_fixpt_mul(overhead_factor, bpp);
+               overhead_factor = dc_fixpt_div_int(overhead_factor, 128);
+               overhead_factor = dc_fixpt_div(
+                       dc_fixpt_from_int(dc_fixpt_ceil(overhead_factor)),
+                       overhead_factor);
+
+               total_kbps = dc_fixpt_ceil(
+                       dc_fixpt_mul_int(overhead_factor, total_kbps));
+       }
+
+       return total_kbps;
+}
+
 uint32_t dc_bandwidth_in_kbps_from_timing(
        const struct dc_crtc_timing *timing)
 {
@@ -1165,6 +1202,11 @@ void dc_dsc_policy_set_disable_dsc_stream_overhead(bool 
disable)
        dsc_policy_disable_dsc_stream_overhead = disable;
 }
 
+void dc_set_disable_128b_132b_stream_overhead(bool disable)
+{
+       disable_128b_132b_stream_overhead = disable;
+}
+
 void dc_dsc_get_default_config_option(const struct dc *dc, struct 
dc_dsc_config_options *options)
 {
        options->dsc_min_slice_height_override = 
dc->debug.dsc_min_slice_height_override;
-- 
2.34.1

Reply via email to