Currently we use the highest input BPC supported by DP sink while using
DSC.In cases where PCON with HDMI2.1 as branch device, if PCON supports
DSC but HDMI2.1 sink does not supports DSC, The PCON tries to use same
input BPC that is used between Source and the PCON without DSC, which
might not work even with the maximum FRL rate supported by HDMI2.1
sink.

This patch calculates the max BPC that can be sufficient with either
RGB or YCBCR420 format for the maximum FRL rate supported.

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

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 8ccbe591b9e2..f0a62f71904e 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -117,6 +117,7 @@ bool intel_dp_is_edp(struct intel_dp *intel_dp)
 
 static void intel_dp_unset_edid(struct intel_dp *intel_dp);
 static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc);
+static bool intel_dp_is_hdmi_2_1_sink(struct intel_dp *intel_dp);
 
 static bool
 is_dfp_hdmi_sink_dsc_1_2(struct intel_dp *intel_dp)
@@ -1455,6 +1456,74 @@ static int intel_dp_dsc_compute_params(struct 
intel_encoder *encoder,
        return drm_dsc_compute_rc_parameters(vdsc_cfg);
 }
 
+static int
+_intel_dp_pcon_hdmi21_get_bpp_nodsc(struct intel_dp *intel_dp,
+                                   const struct drm_display_mode 
*adjusted_mode,
+                                   int max_bpc, bool is_ycbcr420)
+{
+       struct intel_connector *intel_connector = intel_dp->attached_connector;
+       struct drm_connector *connector = &intel_connector->base;
+       int i, num_bpc;
+       u8 dsc_bpc[3] = {0};
+       int req_rate_gbps;
+       int max_frl_rate = connector->display_info.hdmi.max_lanes *
+                          connector->display_info.hdmi.max_frl_rate_per_lane;
+
+       /*
+        * Currently DSC with Ycbcr420 is not supported. So for modes with 
Ycbcr420,
+        * DSC will use RGB and support for RGB->YCBCR444->YCBCR420 conversion 
is
+        * required from DP HDMI2.1 PCON.
+        */
+       if (is_ycbcr420 && !(intel_dp->dfp.rgb_to_ycbcr || 
intel_dp->dfp.ycbcr_444_to_420))
+               return 0;
+
+       num_bpc = drm_dp_dsc_sink_supported_input_bpcs(intel_dp->dsc_dpcd,
+                                                      dsc_bpc);
+       for (i = 0; i < num_bpc; i++) {
+               if (dsc_bpc[i] > max_bpc)
+                       continue;
+
+               req_rate_gbps = DIV_ROUND_UP(dsc_bpc[i] * 3 * 
adjusted_mode->clock, 1000000);
+
+               /* YCBCR420 reduces data rate by 2 */
+               if (is_ycbcr420)
+                       req_rate_gbps /= 2;
+
+               if (req_rate_gbps < max_frl_rate)
+                       return dsc_bpc[i] * 3;
+       }
+
+       return 0;
+}
+
+static int
+intel_dp_pcon_hdmi21_get_bpp_nodsc(struct intel_dp *intel_dp,
+                                  struct intel_crtc_state *pipe_config,
+                                  int max_bpc)
+{
+       const struct drm_display_mode *adjusted_mode =
+               &pipe_config->hw.adjusted_mode;
+       struct intel_connector *connector = intel_dp->attached_connector;
+       const struct drm_display_info *info = &connector->base.display_info;
+       bool is_ycbcr420 = drm_mode_is_420_only(info, adjusted_mode);
+       int pipe_bpp;
+
+       pipe_bpp = _intel_dp_pcon_hdmi21_get_bpp_nodsc(intel_dp, adjusted_mode,
+                                                      max_bpc, is_ycbcr420);
+       if (!pipe_bpp && !is_ycbcr420 && drm_mode_is_420_also(info, 
adjusted_mode)) {
+               is_ycbcr420 = true;
+               pipe_bpp = _intel_dp_pcon_hdmi21_get_bpp_nodsc(intel_dp, 
adjusted_mode,
+                                                              max_bpc, 
is_ycbcr420);
+       }
+
+       if (!pipe_bpp && is_ycbcr420) {
+               pipe_config->dp_dfp_config.rgb_to_ycbcr = true;
+               pipe_config->dp_dfp_config.ycbcr_444_to_420 = true;
+       }
+
+       return pipe_bpp;
+}
+
 static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
                                       struct intel_crtc_state *pipe_config,
                                       struct drm_connector_state *conn_state,
@@ -1473,7 +1542,26 @@ static int intel_dp_dsc_compute_config(struct intel_dp 
*intel_dp,
        if (!intel_dp_supports_dsc(intel_dp, pipe_config))
                return -EINVAL;
 
-       pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, 
conn_state->max_requested_bpc);
+       /*
+        * In cases where PCON with HDMI2.1 as branch device, if PCON supports
+        * DSC but HDMI2.1 sink does not supports DSC, The PCON tries to use 
same
+        * input DSC bpc that is used between Source and PCON with Ycbcr420
+        * format.
+        * So use the max BPC that will be sufficient to show the mode in 
YCbcr420
+        * without DSC from PCON->HDMI2.1
+        */
+       if (intel_dp_is_hdmi_2_1_sink(intel_dp) &&
+           !is_dfp_hdmi_sink_dsc_1_2(intel_dp)) {
+               pipe_bpp = intel_dp_pcon_hdmi21_get_bpp_nodsc(intel_dp, 
pipe_config,
+                                                             
conn_state->max_requested_bpc);
+               if (!pipe_bpp) {
+                       drm_dbg_kms(&dev_priv->drm,
+                                   "No BPC possible to support the mode 
without HDMI2.1 DSC\n");
+                       return -EINVAL;
+               }
+       } else {
+               pipe_bpp = intel_dp_dsc_compute_bpp(intel_dp, 
conn_state->max_requested_bpc);
+       }
 
        /* Min Input BPC for ICL+ is 8 */
        if (pipe_bpp < 8 * 3) {
-- 
2.25.1

Reply via email to