Signed-off-by: Maarten Lankhorst <maarten.lankho...@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c | 234 +++++++++++++-----------
 drivers/gpu/drm/i915/display/intel_dp.h |   4 -
 2 files changed, 130 insertions(+), 108 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index b41ff88d3258..bf28970c01aa 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -248,7 +248,7 @@ intel_dp_max_data_rate(int max_link_clock, int max_lanes)
 }
 
 static int
-intel_dp_downstream_max_dotclock(struct intel_dp *intel_dp)
+intel_dp_downstream_max_dotclock(struct intel_dp *intel_dp, bool 
allow_bigjoiner)
 {
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        struct intel_encoder *encoder = &intel_dig_port->base;
@@ -258,6 +258,9 @@ intel_dp_downstream_max_dotclock(struct intel_dp *intel_dp)
 
        int type = intel_dp->downstream_ports[0] & DP_DS_PORT_TYPE_MASK;
 
+       if (allow_bigjoiner && INTEL_GEN(dev_priv) >= 11)
+               max_dotclk *= 2;
+
        if (type != DP_DS_PORT_TYPE_VGA)
                return max_dotclk;
 
@@ -493,6 +496,103 @@ int intel_dp_get_link_train_fallback_values(struct 
intel_dp *intel_dp,
        return 0;
 }
 
+static u16 intel_dp_dsc_get_output_bpp(int link_clock, u8 lane_count,
+                                      int mode_clock, int mode_hdisplay,
+                                      bool bigjoiner)
+{
+       u16 bits_per_pixel, max_bpp_small_joiner_ram;
+       int i;
+
+       /*
+        * Available Link Bandwidth(Kbits/sec) = (NumberOfLanes)*
+        * (LinkSymbolClock)* 8 * ((100-FECOverhead)/100)*(TimeSlotsPerMTP)
+        * FECOverhead = 2.4%, for SST -> TimeSlotsPerMTP is 1,
+        * for MST -> TimeSlotsPerMTP has to be calculated
+        */
+       bits_per_pixel = (link_clock * lane_count * 8 *
+                         DP_DSC_FEC_OVERHEAD_FACTOR) /
+               mode_clock;
+
+       /* Small Joiner Check: output bpp <= joiner RAM (bits) / Horiz. width */
+       max_bpp_small_joiner_ram = DP_DSC_MAX_SMALL_JOINER_RAM_BUFFER /
+               mode_hdisplay;
+
+       if (bigjoiner)
+               max_bpp_small_joiner_ram *= 2;
+
+       /*
+        * Greatest allowed DSC BPP = MIN (output BPP from avaialble Link BW
+        * check, output bpp from small joiner RAM check)
+        */
+       bits_per_pixel = min(bits_per_pixel, max_bpp_small_joiner_ram);
+
+       /* Error out if the max bpp is less than smallest allowed valid bpp */
+       if (bits_per_pixel < valid_dsc_bpp[0]) {
+               DRM_DEBUG_KMS("Unsupported BPP %d\n", bits_per_pixel);
+               return 0;
+       }
+
+       /* Find the nearest match in the array of known BPPs from VESA */
+       for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp) - 1; i++) {
+               if (bits_per_pixel < valid_dsc_bpp[i + 1])
+                       break;
+       }
+       bits_per_pixel = valid_dsc_bpp[i];
+
+       /*
+        * Compressed BPP in U6.4 format so multiply by 16, for Gen 11,
+        * fractional part is 0
+        */
+       return bits_per_pixel << 4;
+}
+
+static u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp,
+                                      int mode_clock, int mode_hdisplay,
+                                      bool bigjoiner)
+{
+       u8 min_slice_count, i;
+       int max_slice_width;
+
+       if (mode_clock <= DP_DSC_PEAK_PIXEL_RATE)
+               min_slice_count = DIV_ROUND_UP(mode_clock,
+                                              DP_DSC_MAX_ENC_THROUGHPUT_0);
+       else
+               min_slice_count = DIV_ROUND_UP(mode_clock,
+                                              DP_DSC_MAX_ENC_THROUGHPUT_1);
+
+       max_slice_width = drm_dp_dsc_sink_max_slice_width(intel_dp->dsc_dpcd);
+       if (max_slice_width < DP_DSC_MIN_SLICE_WIDTH_VALUE) {
+               DRM_DEBUG_KMS("Unsupported slice width %d by DP DSC Sink 
device\n",
+                             max_slice_width);
+               return 0;
+       }
+       /* Also take into account max slice width */
+       min_slice_count = min_t(u8, min_slice_count,
+                               DIV_ROUND_UP(mode_hdisplay,
+                                            max_slice_width));
+
+       /* Find the closest match to the valid slice count values */
+       for (i = 0; i < ARRAY_SIZE(valid_dsc_slicecount); i++) {
+               u8 test_slice_count = bigjoiner ?
+                       2 * valid_dsc_slicecount[i] :
+                       valid_dsc_slicecount[i];
+
+               if (test_slice_count >
+                   drm_dp_dsc_sink_max_slice_count(intel_dp->dsc_dpcd, false))
+                       break;
+
+               /* big joiner needs small joiner to be enabled */
+               if (bigjoiner && test_slice_count < 4)
+                       continue;
+
+               if (min_slice_count <= test_slice_count)
+                       return test_slice_count;
+       }
+
+       DRM_DEBUG_KMS("Unsupported Slice Count %d\n", min_slice_count);
+       return 0;
+}
+
 static enum drm_mode_status
 intel_dp_mode_valid(struct drm_connector *connector,
                    struct drm_display_mode *mode)
@@ -506,12 +606,15 @@ intel_dp_mode_valid(struct drm_connector *connector,
        int max_dotclk;
        u16 dsc_max_output_bpp = 0;
        u8 dsc_slice_count = 0;
-       bool dsc;
+       bool dsc = false, bigjoiner = false;
 
        if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
                return MODE_NO_DBLESCAN;
 
-       max_dotclk = intel_dp_downstream_max_dotclock(intel_dp);
+       if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+               return MODE_H_ILLEGAL;
+
+       max_dotclk = intel_dp_downstream_max_dotclock(intel_dp, false);
 
        if (intel_dp_is_edp(intel_dp) && fixed_mode) {
                if (mode->hdisplay > fixed_mode->hdisplay)
@@ -523,6 +626,18 @@ intel_dp_mode_valid(struct drm_connector *connector,
                target_clock = fixed_mode->clock;
        }
 
+       if (mode->clock < 10000)
+               return MODE_CLOCK_LOW;
+
+       if (target_clock > max_dotclk) {
+               max_dotclk = intel_dp_downstream_max_dotclock(intel_dp, true);
+
+               if (target_clock > max_dotclk)
+                       return MODE_CLOCK_HIGH;
+
+               bigjoiner = true;
+       }
+
        max_link_clock = intel_dp_max_link_rate(intel_dp);
        max_lanes = intel_dp_max_lane_count(intel_dp);
 
@@ -546,28 +661,24 @@ intel_dp_mode_valid(struct drm_connector *connector,
                                intel_dp_dsc_get_output_bpp(max_link_clock,
                                                            max_lanes,
                                                            target_clock,
-                                                           mode->hdisplay) >> 
4;
+                                                           mode->hdisplay,
+                                                           bigjoiner) >> 4;
                        dsc_slice_count =
                                intel_dp_dsc_get_slice_count(intel_dp,
                                                             target_clock,
-                                                            mode->hdisplay);
+                                                            mode->hdisplay,
+                                                            bigjoiner);
                }
-       }
-
-       dsc = dsc_max_output_bpp && dsc_slice_count;
 
-       /* Gen11 has big joiner for handling this */
-       if (dsc && dsc_slice_count >= 2 && INTEL_GEN(dev_priv) >= 11)
-               max_dotclk *= 2;
+               dsc = dsc_max_output_bpp && dsc_slice_count;
+       }
 
-       if ((mode_rate > max_rate && !dsc) || target_clock > max_dotclk)
+       /* big joiner configuration needs DSC */
+       if (bigjoiner && !dsc)
                return MODE_CLOCK_HIGH;
 
-       if (mode->clock < 10000)
-               return MODE_CLOCK_LOW;
-
-       if (mode->flags & DRM_MODE_FLAG_DBLCLK)
-               return MODE_H_ILLEGAL;
+       if (mode_rate > max_rate && !dsc)
+               return MODE_CLOCK_HIGH;
 
        return MODE_OK;
 }
@@ -1950,11 +2061,11 @@ static int intel_dp_dsc_compute_config(struct intel_dp 
*intel_dp,
                        intel_dp_dsc_get_output_bpp(pipe_config->port_clock,
                                                    pipe_config->lane_count,
                                                    adjusted_mode->crtc_clock,
-                                                   
adjusted_mode->crtc_hdisplay);
+                                                   
adjusted_mode->crtc_hdisplay, false);
                dsc_dp_slice_count =
                        intel_dp_dsc_get_slice_count(intel_dp,
                                                     adjusted_mode->crtc_clock,
-                                                    
adjusted_mode->crtc_hdisplay);
+                                                    
adjusted_mode->crtc_hdisplay, false);
                if (!dsc_max_output_bpp || !dsc_dp_slice_count) {
                        DRM_DEBUG_KMS("Compressed BPP/Slice Count not 
supported\n");
                        return -EINVAL;
@@ -4325,91 +4436,6 @@ intel_dp_get_sink_irq_esi(struct intel_dp *intel_dp, u8 
*sink_irq_vector)
                DP_DPRX_ESI_LEN;
 }
 
-u16 intel_dp_dsc_get_output_bpp(int link_clock, u8 lane_count,
-                               int mode_clock, int mode_hdisplay)
-{
-       u16 bits_per_pixel, max_bpp_small_joiner_ram;
-       int i;
-
-       /*
-        * Available Link Bandwidth(Kbits/sec) = (NumberOfLanes)*
-        * (LinkSymbolClock)* 8 * ((100-FECOverhead)/100)*(TimeSlotsPerMTP)
-        * FECOverhead = 2.4%, for SST -> TimeSlotsPerMTP is 1,
-        * for MST -> TimeSlotsPerMTP has to be calculated
-        */
-       bits_per_pixel = (link_clock * lane_count * 8 *
-                         DP_DSC_FEC_OVERHEAD_FACTOR) /
-               mode_clock;
-
-       /* Small Joiner Check: output bpp <= joiner RAM (bits) / Horiz. width */
-       max_bpp_small_joiner_ram = DP_DSC_MAX_SMALL_JOINER_RAM_BUFFER /
-               mode_hdisplay;
-
-       /*
-        * Greatest allowed DSC BPP = MIN (output BPP from avaialble Link BW
-        * check, output bpp from small joiner RAM check)
-        */
-       bits_per_pixel = min(bits_per_pixel, max_bpp_small_joiner_ram);
-
-       /* Error out if the max bpp is less than smallest allowed valid bpp */
-       if (bits_per_pixel < valid_dsc_bpp[0]) {
-               DRM_DEBUG_KMS("Unsupported BPP %d\n", bits_per_pixel);
-               return 0;
-       }
-
-       /* Find the nearest match in the array of known BPPs from VESA */
-       for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp) - 1; i++) {
-               if (bits_per_pixel < valid_dsc_bpp[i + 1])
-                       break;
-       }
-       bits_per_pixel = valid_dsc_bpp[i];
-
-       /*
-        * Compressed BPP in U6.4 format so multiply by 16, for Gen 11,
-        * fractional part is 0
-        */
-       return bits_per_pixel << 4;
-}
-
-u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp,
-                               int mode_clock,
-                               int mode_hdisplay)
-{
-       u8 min_slice_count, i;
-       int max_slice_width;
-
-       if (mode_clock <= DP_DSC_PEAK_PIXEL_RATE)
-               min_slice_count = DIV_ROUND_UP(mode_clock,
-                                              DP_DSC_MAX_ENC_THROUGHPUT_0);
-       else
-               min_slice_count = DIV_ROUND_UP(mode_clock,
-                                              DP_DSC_MAX_ENC_THROUGHPUT_1);
-
-       max_slice_width = drm_dp_dsc_sink_max_slice_width(intel_dp->dsc_dpcd);
-       if (max_slice_width < DP_DSC_MIN_SLICE_WIDTH_VALUE) {
-               DRM_DEBUG_KMS("Unsupported slice width %d by DP DSC Sink 
device\n",
-                             max_slice_width);
-               return 0;
-       }
-       /* Also take into account max slice width */
-       min_slice_count = min_t(u8, min_slice_count,
-                               DIV_ROUND_UP(mode_hdisplay,
-                                            max_slice_width));
-
-       /* Find the closest match to the valid slice count values */
-       for (i = 0; i < ARRAY_SIZE(valid_dsc_slicecount); i++) {
-               if (valid_dsc_slicecount[i] >
-                   drm_dp_dsc_sink_max_slice_count(intel_dp->dsc_dpcd,
-                                                   false))
-                       break;
-               if (min_slice_count  <= valid_dsc_slicecount[i])
-                       return valid_dsc_slicecount[i];
-       }
-
-       DRM_DEBUG_KMS("Unsupported Slice Count %d\n", min_slice_count);
-       return 0;
-}
-
 static void
 intel_pixel_encoding_setup_vsc(struct intel_dp *intel_dp,
                               const struct intel_crtc_state *crtc_state)
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h 
b/drivers/gpu/drm/i915/display/intel_dp.h
index 657bbb1f5ed0..b11ca45272ed 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -102,10 +102,6 @@ bool intel_dp_source_supports_hbr2(struct intel_dp 
*intel_dp);
 bool intel_dp_source_supports_hbr3(struct intel_dp *intel_dp);
 bool
 intel_dp_get_link_status(struct intel_dp *intel_dp, u8 *link_status);
-u16 intel_dp_dsc_get_output_bpp(int link_clock, u8 lane_count,
-                               int mode_clock, int mode_hdisplay);
-u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp, int mode_clock,
-                               int mode_hdisplay);
 
 bool intel_dp_read_dpcd(struct intel_dp *intel_dp);
 bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp);
-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to