[PATCH 17/20] drm/i915/dp: Get optimal link config to have best compressed bpp

2023-08-10 Thread Ankit Nautiyal
Currently, we take the max lane, rate and pipe bpp, to get the maximum
compressed bpp possible. We then set the output bpp to this value.
This patch provides support to have max bpp, min rate and min lanes,
that can support the min compressed bpp.

v2:
-Avoid ending up with compressed bpp, same as pipe bpp. (Stan)
-Fix the checks for limits->max/min_bpp while iterating over list of
 valid DSC bpcs. (Stan)

v3:
-Refactor the code to have pipe bpp/compressed bpp computation and slice
count calculation separately for different cases.

v4:
-Separate the pipe_bpp calculation for eDP and DP.

v5:
-Get rid of magic numbers for max and min bpp,
and improve documentation. (Stan).
-Use functions for {src_sink}_{min_max}_compressed_bpp (Ville).

v6:
-Remove lines to set link config to max.

v7:
-Split the part to separate edp and dp functions for computing DSC BPP
into separate patch.

v8:
-Separate mechanism to get compressed bpp for ICL,TGL and XELPD+.

Signed-off-by: Ankit Nautiyal 
Reviewed-by: Stanislav Lisovskiy 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 294 +---
 1 file changed, 261 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 6901ab809587..196bda630944 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1689,6 +1689,231 @@ static bool intel_dp_dsc_supports_format(struct 
intel_dp *intel_dp,
return drm_dp_dsc_sink_supports_format(intel_dp->dsc_dpcd, 
sink_dsc_format);
 }
 
+static bool is_bw_sufficient_for_dsc_config(u16 compressed_bpp, u32 link_clock,
+   u32 lane_count, u32 mode_clock,
+   enum intel_output_format 
output_format,
+   int timeslots)
+{
+   u32 available_bw, required_bw;
+
+   available_bw = (link_clock * lane_count * timeslots)  / 8;
+   required_bw = compressed_bpp * (intel_dp_mode_to_fec_clock(mode_clock));
+
+   return available_bw > required_bw;
+}
+
+static int dsc_compute_link_config(struct intel_dp *intel_dp,
+  struct intel_crtc_state *pipe_config,
+  struct link_config_limits *limits,
+  u16 compressed_bpp,
+  int timeslots)
+{
+   const struct drm_display_mode *adjusted_mode = 
_config->hw.adjusted_mode;
+   int link_rate, lane_count;
+   int i;
+
+   for (i = 0; i < intel_dp->num_common_rates; i++) {
+   link_rate = intel_dp_common_rate(intel_dp, i);
+   if (link_rate < limits->min_rate || link_rate > 
limits->max_rate)
+   continue;
+
+   for (lane_count = limits->min_lane_count;
+lane_count <= limits->max_lane_count;
+lane_count <<= 1) {
+   if (!is_bw_sufficient_for_dsc_config(compressed_bpp, 
link_rate, lane_count,
+
adjusted_mode->clock,
+
pipe_config->output_format,
+timeslots))
+   continue;
+
+   pipe_config->lane_count = lane_count;
+   pipe_config->port_clock = link_rate;
+
+   return 0;
+   }
+   }
+
+   return -EINVAL;
+}
+
+static
+u16 intel_dp_dsc_max_sink_compressed_bppx16(struct intel_dp *intel_dp,
+   struct intel_crtc_state 
*pipe_config,
+   int bpc)
+{
+   u16 max_bppx16 = drm_edp_dsc_sink_output_bpp(intel_dp->dsc_dpcd);
+
+   if (max_bppx16)
+   return max_bppx16;
+   /*
+* If support not given in DPCD 67h, 68h use the Maximum Allowed bit 
rate
+* values as given in spec Table 2-157 DP v2.0
+*/
+   switch (pipe_config->output_format) {
+   case INTEL_OUTPUT_FORMAT_RGB:
+   case INTEL_OUTPUT_FORMAT_YCBCR444:
+   return (3 * bpc) << 4;
+   case INTEL_OUTPUT_FORMAT_YCBCR420:
+   return (3 * (bpc / 2)) << 4;
+   default:
+   MISSING_CASE(pipe_config->output_format);
+   break;
+   }
+
+   return 0;
+}
+
+static int dsc_sink_min_compressed_bpp(struct intel_crtc_state *pipe_config)
+{
+   /* From Mandatory bit rate range Support Table 2-157 (DP v2.0) */
+   switch (pipe_config->output_format) {
+   case INTEL_OUTPUT_FORMAT_RGB:
+   case INTEL_OUTPUT_FORMAT_YCBCR444:
+   return 8;
+   case INTEL_OUTPUT_FORMAT_YCBCR420:
+   return 6;
+   default:
+   MISSING_CASE(pipe_config->output_format);
+   break;
+   }
+
+   return 0;
+}
+
+static int 

[PATCH 17/20] drm/i915/dp: Get optimal link config to have best compressed bpp

2023-07-27 Thread Ankit Nautiyal
Currently, we take the max lane, rate and pipe bpp, to get the maximum
compressed bpp possible. We then set the output bpp to this value.
This patch provides support to have max bpp, min rate and min lanes,
that can support the min compressed bpp.

v2:
-Avoid ending up with compressed bpp, same as pipe bpp. (Stan)
-Fix the checks for limits->max/min_bpp while iterating over list of
 valid DSC bpcs. (Stan)

v3:
-Refactor the code to have pipe bpp/compressed bpp computation and slice
count calculation separately for different cases.

v4:
-Separate the pipe_bpp calculation for eDP and DP.

v5:
-Get rid of magic numbers for max and min bpp,
and improve documentation. (Stan).
-Use functions for {src_sink}_{min_max}_compressed_bpp (Ville).

v6:
-Remove lines to set link config to max.

v7:
-Split the part to separate edp and dp functions for computing DSC BPP
into separate patch.

v8:
-Separate mechanism to get compressed bpp for ICL,TGL and XELPD+.

Signed-off-by: Ankit Nautiyal 
Reviewed-by: Stanislav Lisovskiy 
---
 drivers/gpu/drm/i915/display/intel_dp.c | 294 +---
 1 file changed, 261 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 9720d32c6301..7e755bea919c 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1689,6 +1689,231 @@ static bool intel_dp_dsc_supports_format(struct 
intel_dp *intel_dp,
return drm_dp_dsc_sink_supports_format(intel_dp->dsc_dpcd, 
sink_dsc_format);
 }
 
+static bool is_bw_sufficient_for_dsc_config(u16 compressed_bpp, u32 link_clock,
+   u32 lane_count, u32 mode_clock,
+   enum intel_output_format 
output_format,
+   int timeslots)
+{
+   u32 available_bw, required_bw;
+
+   available_bw = (link_clock * lane_count * timeslots)  / 8;
+   required_bw = compressed_bpp * (intel_dp_mode_to_fec_clock(mode_clock));
+
+   return available_bw > required_bw;
+}
+
+static int dsc_compute_link_config(struct intel_dp *intel_dp,
+  struct intel_crtc_state *pipe_config,
+  struct link_config_limits *limits,
+  u16 compressed_bpp,
+  int timeslots)
+{
+   const struct drm_display_mode *adjusted_mode = 
_config->hw.adjusted_mode;
+   int link_rate, lane_count;
+   int i;
+
+   for (i = 0; i < intel_dp->num_common_rates; i++) {
+   link_rate = intel_dp_common_rate(intel_dp, i);
+   if (link_rate < limits->min_rate || link_rate > 
limits->max_rate)
+   continue;
+
+   for (lane_count = limits->min_lane_count;
+lane_count <= limits->max_lane_count;
+lane_count <<= 1) {
+   if (!is_bw_sufficient_for_dsc_config(compressed_bpp, 
link_rate, lane_count,
+
adjusted_mode->clock,
+
pipe_config->output_format,
+timeslots))
+   continue;
+
+   pipe_config->lane_count = lane_count;
+   pipe_config->port_clock = link_rate;
+
+   return 0;
+   }
+   }
+
+   return -EINVAL;
+}
+
+static
+u16 intel_dp_dsc_max_sink_compressed_bppx16(struct intel_dp *intel_dp,
+   struct intel_crtc_state 
*pipe_config,
+   int bpc)
+{
+   u16 max_bppx16 = drm_edp_dsc_sink_output_bpp(intel_dp->dsc_dpcd);
+
+   if (max_bppx16)
+   return max_bppx16;
+   /*
+* If support not given in DPCD 67h, 68h use the Maximum Allowed bit 
rate
+* values as given in spec Table 2-157 DP v2.0
+*/
+   switch (pipe_config->output_format) {
+   case INTEL_OUTPUT_FORMAT_RGB:
+   case INTEL_OUTPUT_FORMAT_YCBCR444:
+   return (3 * bpc) << 4;
+   case INTEL_OUTPUT_FORMAT_YCBCR420:
+   return (3 * (bpc / 2)) << 4;
+   default:
+   MISSING_CASE(pipe_config->output_format);
+   break;
+   }
+
+   return 0;
+}
+
+static int dsc_sink_min_compressed_bpp(struct intel_crtc_state *pipe_config)
+{
+   /* From Mandatory bit rate range Support Table 2-157 (DP v2.0) */
+   switch (pipe_config->output_format) {
+   case INTEL_OUTPUT_FORMAT_RGB:
+   case INTEL_OUTPUT_FORMAT_YCBCR444:
+   return 8;
+   case INTEL_OUTPUT_FORMAT_YCBCR420:
+   return 6;
+   default:
+   MISSING_CASE(pipe_config->output_format);
+   break;
+   }
+
+   return 0;
+}
+
+static int