return 0;
 }
 
-static void
+/**
+ * intel_dp_compute_config_link_bpp_limits - compute output link bpp limits
+ * @intel_dp: intel DP
+ * @crtc_state: crtc state
+ * @dsc: DSC compression mode
+ * @limits: link configuration limits
+ *
+ * Calculates the output link min, max bpp values in @limits based on the
+ * pipe bpp range, @crtc_state and @dsc mode.
+ *
+ * Returns %true in case of success.
+ */
+bool
+intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp,
+                                       const struct intel_crtc_state *crtc_state,
+                                       bool dsc,
+                                       struct link_config_limits *limits)
+{
+       struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+       const struct drm_display_mode *adjusted_mode =
+               &crtc_state->hw.adjusted_mode;
+       const struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+       const struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
+       int max_link_bpp_x16;
+
+       max_link_bpp_x16 = to_bpp_x16(limits->pipe.max_bpp);
+
+       if (!dsc) {
+               max_link_bpp_x16 = rounddown(max_link_bpp_x16, to_bpp_x16(2 * 3));
+
+               if (max_link_bpp_x16 < to_bpp_x16(limits->pipe.min_bpp))
+                       return false;
+
+               limits->link.min_bpp_x16 = to_bpp_x16(limits->pipe.min_bpp);
+       } else {
+               /*
+                * TODO: set the DSC link limits already here, atm these are
+                * initialized only later in intel_edp_dsc_compute_pipe_bpp() /
+                * intel_dp_dsc_compute_pipe_bpp()
+                */
+               limits->link.min_bpp_x16 = 0;
+       }
+
+       limits->link.max_bpp_x16 = max_link_bpp_x16;
+
+       drm_dbg_kms(&i915->drm,
+                   "[ENCODER:%d:%s][CRTC:%d:%s] DP link limits: pixel clock %d kHz DSC %s max lanes %d max rate %d max pipe_bpp %d max link_bpp " BPP_X16_FMT "\n",
+                   encoder->base.base.id, encoder->base.name,
+                   crtc->base.base.id, crtc->base.name,
+                   adjusted_mode->crtc_clock,
+                   dsc ? "on" : "off",
+                   limits->max_lane_count,
+                   limits->max_rate,
+                   limits->pipe.max_bpp,
+                   BPP_X16_ARGS(limits->link.max_bpp_x16));
+
+       return true;
+}
+
+static bool
 intel_dp_compute_config_limits(struct intel_dp *intel_dp,
                               struct intel_crtc_state *crtc_state,
                               bool respect_downstream_limits,
+                              bool dsc,
                               struct link_config_limits *limits)
 {
-       struct drm_i915_private *i915 = dp_to_i915(intel_dp);
-       const struct drm_display_mode *adjusted_mode =
-               &crtc_state->hw.adjusted_mode;
-
        limits->min_rate = intel_dp_common_rate(intel_dp, 0);
        limits->max_rate = intel_dp_max_link_rate(intel_dp);
 
 
        intel_dp_adjust_compliance_config(intel_dp, crtc_state, limits);
 
-       limits->link.min_bpp_x16 = to_bpp_x16(limits->pipe.min_bpp);
-       limits->link.max_bpp_x16 = to_bpp_x16(limits->pipe.max_bpp);
-
-       drm_dbg_kms(&i915->drm, "DP link computation with max lane count %i "
-                   "max rate %d max bpp %d pixel clock %iKHz\n",
-                   limits->max_lane_count, limits->max_rate,
-                   to_bpp_int(limits->link.max_bpp_x16), adjusted_mode->crtc_clock);
+       return intel_dp_compute_config_link_bpp_limits(intel_dp,
+                                                      crtc_state,
+                                                      dsc,
+                                                      limits);
 }
 
 static int
        bool dsc_needed;
        int ret = 0;
 
-       intel_dp_compute_config_limits(intel_dp, pipe_config,
-                                      respect_downstream_limits, &limits);
-
        if (intel_dp_need_bigjoiner(intel_dp, adjusted_mode->crtc_hdisplay,
                                    adjusted_mode->crtc_clock))
                pipe_config->bigjoiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe);
         */
        joiner_needs_dsc = DISPLAY_VER(i915) < 13 && pipe_config->bigjoiner_pipes;
 
-       dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en;
+       dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en ||
+                    !intel_dp_compute_config_limits(intel_dp, pipe_config,
+                                                    respect_downstream_limits,
+                                                    false,
+                                                    &limits);
 
        if (!dsc_needed) {
                /*
                drm_dbg_kms(&i915->drm, "Try DSC (fallback=%s, joiner=%s, force=%s)\n",
                            str_yes_no(ret), str_yes_no(joiner_needs_dsc),
                            str_yes_no(intel_dp->force_dsc_en));
+
+               if (!intel_dp_compute_config_limits(intel_dp, pipe_config,
+                                                   respect_downstream_limits,
+                                                   true,
+                                                   &limits))
+                       return -EINVAL;
+
                ret = intel_dp_dsc_compute_config(intel_dp, pipe_config,
                                                  conn_state, &limits, 64, true);
                if (ret < 0)
 
        return 0;
 }
 
-static void
+static bool
 intel_dp_mst_compute_config_limits(struct intel_dp *intel_dp,
                                   struct intel_crtc_state *crtc_state,
+                                  bool dsc,
                                   struct link_config_limits *limits)
 {
        /*
 
        intel_dp_adjust_compliance_config(intel_dp, crtc_state, limits);
 
-       limits->link.min_bpp_x16 = to_bpp_x16(limits->pipe.min_bpp);
-       limits->link.max_bpp_x16 = to_bpp_x16(limits->pipe.max_bpp);
+       return intel_dp_compute_config_link_bpp_limits(intel_dp,
+                                                      crtc_state,
+                                                      dsc,
+                                                      limits);
 }
 
 static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
        pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
        pipe_config->has_pch_encoder = false;
 
-       intel_dp_mst_compute_config_limits(intel_dp, pipe_config, &limits);
-
-       dsc_needed = intel_dp->force_dsc_en;
+       dsc_needed = intel_dp->force_dsc_en ||
+                    !intel_dp_mst_compute_config_limits(intel_dp,
+                                                        pipe_config,
+                                                        false,
+                                                        &limits);
 
        if (!dsc_needed) {
                ret = intel_dp_mst_compute_link_config(encoder, pipe_config,
                            str_yes_no(ret),
                            str_yes_no(intel_dp->force_dsc_en));
 
+               if (!intel_dp_mst_compute_config_limits(intel_dp,
+                                                       pipe_config,
+                                                       true,
+                                                       &limits))
+                       return -EINVAL;
+
                /*
                 * FIXME: As bpc is hardcoded to 8, as mentioned above,
                 * WARN and ignore the debug flag force_dsc_bpc for now.