return (value + 9) / 10;
 }
 
+static struct fixed31_32 compute_dsc_max_bandwidth_overhead(
+               const struct dc_crtc_timing *timing,
+               const int num_slices_h)
+{
+       struct fixed31_32 max_dsc_overhead;
+       struct fixed31_32 refresh_rate;
+
+       /* use target bpp that can take entire target bandwidth */
+       refresh_rate = dc_fixpt_from_int(timing->pix_clk_100hz);
+       refresh_rate = dc_fixpt_div_int(refresh_rate, timing->h_total);
+       refresh_rate = dc_fixpt_div_int(refresh_rate, timing->v_total);
+       refresh_rate = dc_fixpt_mul_int(refresh_rate, 100);
+
+       max_dsc_overhead = dc_fixpt_from_int(num_slices_h);
+       max_dsc_overhead = dc_fixpt_mul_int(max_dsc_overhead, timing->v_addressable);
+       max_dsc_overhead = dc_fixpt_mul_int(max_dsc_overhead, 256);
+       max_dsc_overhead = dc_fixpt_div_int(max_dsc_overhead, 1000);
+       max_dsc_overhead = dc_fixpt_mul(max_dsc_overhead, refresh_rate);
+
+       return max_dsc_overhead;
+}
+
+static uint32_t compute_bpp_x16_from_target_bandwidth(
+               const uint32_t bandwidth_in_kbps,
+               const struct dc_crtc_timing *timing,
+               const uint32_t num_slices_h,
+               const uint32_t bpp_increment_div)
+{
+       struct fixed31_32 overhead_in_kbps;
+       struct fixed31_32 effective_bandwidth_in_kbps;
+       struct fixed31_32 bpp_x16;
+
+       overhead_in_kbps = compute_dsc_max_bandwidth_overhead(
+                               timing, num_slices_h);
+       effective_bandwidth_in_kbps = dc_fixpt_from_int(bandwidth_in_kbps);
+       effective_bandwidth_in_kbps = dc_fixpt_sub(effective_bandwidth_in_kbps,
+                       overhead_in_kbps);
+       bpp_x16 = dc_fixpt_mul_int(effective_bandwidth_in_kbps, 10);
+       bpp_x16 = dc_fixpt_div_int(bpp_x16, timing->pix_clk_100hz);
+       bpp_x16 = dc_fixpt_from_int(dc_fixpt_floor(dc_fixpt_mul_int(bpp_x16, bpp_increment_div)));
+       bpp_x16 = dc_fixpt_div_int(bpp_x16, bpp_increment_div);
+       bpp_x16 = dc_fixpt_mul_int(bpp_x16, 16);
+       return dc_fixpt_floor(bpp_x16);
+}
+
 /* Get DSC bandwidth range based on [min_bpp, max_bpp] target bitrate range, and timing's pixel clock
  * and uncompressed bandwidth.
  */
 static void get_dsc_bandwidth_range(
                const uint32_t min_bpp_x16,
                const uint32_t max_bpp_x16,
+               const uint32_t num_slices_h,
                const struct dsc_enc_caps *dsc_caps,
                const struct dc_crtc_timing *timing,
                struct dc_dsc_bw_range *range)
        range->stream_kbps = dc_bandwidth_in_kbps_from_timing(timing);
 
        /* max dsc target bpp */
-       range->max_kbps = dc_dsc_stream_bandwidth_in_kbps(timing->pix_clk_100hz, max_bpp_x16);
+       range->max_kbps = dc_dsc_stream_bandwidth_in_kbps(timing,
+                       max_bpp_x16, num_slices_h);
        range->max_target_bpp_x16 = max_bpp_x16;
        if (range->max_kbps > range->stream_kbps) {
                /* max dsc target bpp is capped to native bandwidth */
                range->max_kbps = range->stream_kbps;
-               range->max_target_bpp_x16 = calc_dsc_bpp_x16(range->stream_kbps, timing->pix_clk_100hz, dsc_caps->bpp_increment_div);
+               range->max_target_bpp_x16 = compute_bpp_x16_from_target_bandwidth(
+                               range->max_kbps, timing, num_slices_h,
+                               dsc_caps->bpp_increment_div);
        }
 
        /* min dsc target bpp */
-       range->min_kbps = dc_dsc_stream_bandwidth_in_kbps(timing->pix_clk_100hz, min_bpp_x16);
+       range->min_kbps = dc_dsc_stream_bandwidth_in_kbps(timing,
+                       min_bpp_x16, num_slices_h);
        range->min_target_bpp_x16 = min_bpp_x16;
        if (range->min_kbps > range->max_kbps) {
                /* min dsc target bpp is capped to max dsc bandwidth*/
        }
 }
 
-
 /* Decides if DSC should be used and calculates target bpp if it should, applying DSC policy.
  *
  * Returns:
                const struct dsc_enc_caps *dsc_common_caps,
                const int target_bandwidth_kbps,
                const struct dc_crtc_timing *timing,
+               const int num_slices_h,
                int *target_bpp_x16)
 {
        bool should_use_dsc = false;
        memset(&range, 0, sizeof(range));
 
        get_dsc_bandwidth_range(policy->min_target_bpp * 16, policy->max_target_bpp * 16,
-                       dsc_common_caps, timing, &range);
+                       num_slices_h, dsc_common_caps, timing, &range);
        if (!policy->enable_dsc_when_not_needed && target_bandwidth_kbps >= range.stream_kbps) {
                /* enough bandwidth without dsc */
                *target_bpp_x16 = 0;
                should_use_dsc = true;
        } else if (target_bandwidth_kbps >= range.min_kbps) {
                /* use target bpp that can take entire target bandwidth */
-               *target_bpp_x16 = calc_dsc_bpp_x16(target_bandwidth_kbps, timing->pix_clk_100hz, dsc_common_caps->bpp_increment_div);
+               *target_bpp_x16 = compute_bpp_x16_from_target_bandwidth(
+                               range.max_kbps, timing, num_slices_h,
+                               dsc_common_caps->bpp_increment_div);
+               if (*target_bpp_x16 < range.min_kbps)
+                       *target_bpp_x16 = range.min_kbps;
                should_use_dsc = true;
        } else {
                /* not enough bandwidth to fulfill minimum requirement */
        if (!is_dsc_possible)
                goto done;
 
-       if (target_bandwidth_kbps > 0) {
-               is_dsc_possible = decide_dsc_target_bpp_x16(
-                               &policy,
-                               &dsc_common_caps,
-                               target_bandwidth_kbps,
-                               timing,
-                               &target_bpp);
-               dsc_cfg->bits_per_pixel = target_bpp;
-       }
-       if (!is_dsc_possible)
-               goto done;
-
        sink_per_slice_throughput_mps = 0;
 
        // Validate available DSC settings against the mode timing
 
        dsc_cfg->num_slices_v = pic_height/slice_height;
 
+       if (target_bandwidth_kbps > 0) {
+               is_dsc_possible = decide_dsc_target_bpp_x16(
+                               &policy,
+                               &dsc_common_caps,
+                               target_bandwidth_kbps,
+                               timing,
+                               num_slices_h,
+                               &target_bpp);
+               dsc_cfg->bits_per_pixel = target_bpp;
+       }
+       if (!is_dsc_possible)
+               goto done;
+
        // Final decission: can we do DSC or not?
        if (is_dsc_possible) {
                // Fill out the rest of DSC settings
                                dsc_min_slice_height_override, max_bpp_x16, &config);
 
        if (is_dsc_possible)
-               get_dsc_bandwidth_range(min_bpp_x16, max_bpp_x16, &dsc_common_caps, timing, range);
+               get_dsc_bandwidth_range(min_bpp_x16, max_bpp_x16,
+                               config.num_slices_h, &dsc_common_caps, timing, range);
 
        return is_dsc_possible;
 }
        return is_dsc_possible;
 }
 
-uint32_t dc_dsc_stream_bandwidth_in_kbps(uint32_t pix_clk_100hz, uint32_t bpp_x16)
+uint32_t dc_dsc_stream_bandwidth_in_kbps(const struct dc_crtc_timing *timing,
+               uint32_t bpp_x16, uint32_t num_slices_h)
 {
-       struct fixed31_32 link_bw_kbps;
-       link_bw_kbps = dc_fixpt_from_int(pix_clk_100hz);
-       link_bw_kbps = dc_fixpt_div_int(link_bw_kbps, 160);
-       link_bw_kbps = dc_fixpt_mul_int(link_bw_kbps, bpp_x16);
-       return dc_fixpt_ceil(link_bw_kbps);
+       struct fixed31_32 overhead_in_kbps;
+       struct fixed31_32 bpp;
+       struct fixed31_32 actual_bandwidth_in_kbps;
+
+       overhead_in_kbps = compute_dsc_max_bandwidth_overhead(
+                       timing, num_slices_h);
+       bpp = dc_fixpt_from_fraction(bpp_x16, 16);
+       actual_bandwidth_in_kbps = dc_fixpt_from_fraction(timing->pix_clk_100hz, 10);
+       actual_bandwidth_in_kbps = dc_fixpt_mul(actual_bandwidth_in_kbps, bpp);
+       actual_bandwidth_in_kbps = dc_fixpt_add(actual_bandwidth_in_kbps, overhead_in_kbps);
+       return dc_fixpt_ceil(actual_bandwidth_in_kbps);
 }
 
 void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing, uint32_t max_target_bpp_limit_override_x16, struct dc_dsc_policy *policy)