}
        }
 }
+static struct fixed31_32 get_link_symbol_clk_freq_mhz(enum dc_link_rate link_rate)
+{
+       switch (link_rate) {
+       case LINK_RATE_LOW:
+               return dc_fixpt_from_int(162); /* 162 MHz */
+       case LINK_RATE_HIGH:
+               return dc_fixpt_from_int(270); /* 270 MHz */
+       case LINK_RATE_HIGH2:
+               return dc_fixpt_from_int(540); /* 540 MHz */
+       case LINK_RATE_HIGH3:
+               return dc_fixpt_from_int(810); /* 810 MHz */
+       case LINK_RATE_UHBR10:
+               return dc_fixpt_from_fraction(3125, 10); /* 312.5 MHz */
+       case LINK_RATE_UHBR13_5:
+               return dc_fixpt_from_fraction(421875, 1000); /* 421.875 MHz */
+       case LINK_RATE_UHBR20:
+               return dc_fixpt_from_int(625); /* 625 MHz */
+       default:
+               /* Unexpected case, this requires debug if encountered. */
+               ASSERT(0);
+               return dc_fixpt_from_int(0);
+       }
+}
+
+struct dp_audio_layout_config {
+       uint8_t layouts_per_sample_denom;
+       uint8_t symbols_per_layout;
+       uint8_t max_layouts_per_audio_sdp;
+};
+
+static void get_audio_layout_config(
+       uint32_t channel_count,
+       enum dp_link_encoding encoding,
+       struct dp_audio_layout_config *output)
+{
+       /* Assuming L-PCM audio. Current implementation uses max 1 layout per SDP,
+        * with each layout being the same size (8ch layout).
+        */
+       if (encoding == DP_8b_10b_ENCODING) {
+               if (channel_count == 2) {
+                       output->layouts_per_sample_denom = 4;
+                       output->symbols_per_layout = 40;
+                       output->max_layouts_per_audio_sdp = 1;
+               } else if (channel_count == 8) {
+                       output->layouts_per_sample_denom = 1;
+                       output->symbols_per_layout = 40;
+                       output->max_layouts_per_audio_sdp = 1;
+               }
+       } else if (encoding == DP_128b_132b_ENCODING) {
+               if (channel_count == 2) {
+                       output->layouts_per_sample_denom = 4;
+                       output->symbols_per_layout = 10;
+                       output->max_layouts_per_audio_sdp = 1;
+               } else if (channel_count == 8) {
+                       output->layouts_per_sample_denom = 1;
+                       output->symbols_per_layout = 10;
+                       output->max_layouts_per_audio_sdp = 1;
+               }
+       }
+}
 
-/*For DP SST, calculate if specified sample rates can fit into a given timing */
-static void check_audio_bandwidth_dpsst(
+static uint32_t get_av_stream_map_lane_count(
+       enum dp_link_encoding encoding,
+       enum dc_lane_count lane_count,
+       bool is_mst)
+{
+       uint32_t av_stream_map_lane_count = 0;
+
+       if (encoding == DP_8b_10b_ENCODING) {
+               if (!is_mst)
+                       av_stream_map_lane_count = lane_count;
+               else
+                       av_stream_map_lane_count = 4;
+       } else if (encoding == DP_128b_132b_ENCODING) {
+               av_stream_map_lane_count = 4;
+       }
+
+       ASSERT(av_stream_map_lane_count != 0);
+
+       return av_stream_map_lane_count;
+}
+
+static uint32_t get_audio_sdp_overhead(
+       enum dp_link_encoding encoding,
+       enum dc_lane_count lane_count,
+       bool is_mst)
+{
+       uint32_t audio_sdp_overhead = 0;
+
+       if (encoding == DP_8b_10b_ENCODING) {
+               if (is_mst)
+                       audio_sdp_overhead = 16; /* 4 * 2 + 8 */
+               else
+                       audio_sdp_overhead = lane_count * 2 + 8;
+       } else if (encoding == DP_128b_132b_ENCODING) {
+               audio_sdp_overhead = 10; /* 4 x 2.5 */
+       }
+
+       ASSERT(audio_sdp_overhead != 0);
+
+       return audio_sdp_overhead;
+}
+
+static uint32_t calculate_required_audio_bw_in_symbols(
        const struct audio_crtc_info *crtc_info,
+       const struct dp_audio_layout_config *layout_config,
        uint32_t channel_count,
-       union audio_sample_rates *sample_rates)
+       uint32_t sample_rate_hz,
+       uint32_t av_stream_map_lane_count,
+       uint32_t audio_sdp_overhead)
 {
-       /* do nothing */
+       /* DP spec recommends between 1.05 to 1.1 safety margin to prevent sample under-run */
+       struct fixed31_32 audio_sdp_margin = dc_fixpt_from_fraction(110, 100);
+       struct fixed31_32 horizontal_line_freq_khz = dc_fixpt_from_fraction(
+                       crtc_info->requested_pixel_clock_100Hz, crtc_info->h_total * 10);
+       struct fixed31_32 samples_per_line;
+       struct fixed31_32 layouts_per_line;
+       struct fixed31_32 symbols_per_sdp_max_layout;
+       struct fixed31_32 remainder;
+       uint32_t num_sdp_with_max_layouts;
+       uint32_t required_symbols_per_hblank;
+
+       samples_per_line = dc_fixpt_from_fraction(sample_rate_hz, 1000);
+       samples_per_line = dc_fixpt_div(samples_per_line, horizontal_line_freq_khz);
+       layouts_per_line = dc_fixpt_div_int(samples_per_line, layout_config->layouts_per_sample_denom);
+
+       num_sdp_with_max_layouts = dc_fixpt_floor(
+                       dc_fixpt_div_int(layouts_per_line, layout_config->max_layouts_per_audio_sdp));
+       symbols_per_sdp_max_layout = dc_fixpt_from_int(
+                       layout_config->max_layouts_per_audio_sdp * layout_config->symbols_per_layout);
+       symbols_per_sdp_max_layout = dc_fixpt_add_int(symbols_per_sdp_max_layout, audio_sdp_overhead);
+       symbols_per_sdp_max_layout = dc_fixpt_mul(symbols_per_sdp_max_layout, audio_sdp_margin);
+       required_symbols_per_hblank = num_sdp_with_max_layouts;
+       required_symbols_per_hblank *= ((dc_fixpt_ceil(symbols_per_sdp_max_layout) + av_stream_map_lane_count) /
+                       av_stream_map_lane_count) *     av_stream_map_lane_count;
+
+       if (num_sdp_with_max_layouts != dc_fixpt_ceil(
+                       dc_fixpt_div_int(layouts_per_line, layout_config->max_layouts_per_audio_sdp))) {
+               remainder = dc_fixpt_sub_int(layouts_per_line,
+                               num_sdp_with_max_layouts * layout_config->max_layouts_per_audio_sdp);
+               remainder = dc_fixpt_mul_int(remainder, layout_config->symbols_per_layout);
+               remainder = dc_fixpt_add_int(remainder, audio_sdp_overhead);
+               remainder = dc_fixpt_mul(remainder, audio_sdp_margin);
+               required_symbols_per_hblank += ((dc_fixpt_ceil(remainder) + av_stream_map_lane_count) /
+                               av_stream_map_lane_count) * av_stream_map_lane_count;
+       }
+
+       return required_symbols_per_hblank;
 }
 
-/*For DP MST, calculate if specified sample rates can fit into a given timing */
-static void check_audio_bandwidth_dpmst(
+/* Current calculation only applicable for 8b/10b MST and 128b/132b SST/MST.
+ */
+static uint32_t calculate_available_hblank_bw_in_symbols(
        const struct audio_crtc_info *crtc_info,
+       const struct audio_dp_link_info *dp_link_info)
+{
+       uint64_t hblank = crtc_info->h_total - crtc_info->h_active;
+       struct fixed31_32 hblank_time_msec =
+                       dc_fixpt_from_fraction(hblank * 10, crtc_info->requested_pixel_clock_100Hz);
+       struct fixed31_32 lsclkfreq_mhz =
+                       get_link_symbol_clk_freq_mhz(dp_link_info->link_rate);
+       struct fixed31_32 average_stream_sym_bw_frac;
+       struct fixed31_32 peak_stream_bw_kbps;
+       struct fixed31_32 bits_per_pixel;
+       struct fixed31_32 link_bw_kbps;
+       struct fixed31_32 available_stream_sym_count;
+       uint32_t available_hblank_bw = 0; /* in stream symbols */
+
+       if (crtc_info->dsc_bits_per_pixel) {
+               bits_per_pixel = dc_fixpt_from_fraction(crtc_info->dsc_bits_per_pixel, 16);
+       } else {
+               switch (crtc_info->color_depth) {
+               case COLOR_DEPTH_666:
+                       bits_per_pixel = dc_fixpt_from_int(6);
+                       break;
+               case COLOR_DEPTH_888:
+                       bits_per_pixel = dc_fixpt_from_int(8);
+                       break;
+               case COLOR_DEPTH_101010:
+                       bits_per_pixel = dc_fixpt_from_int(10);
+                       break;
+               case COLOR_DEPTH_121212:
+                       bits_per_pixel = dc_fixpt_from_int(12);
+                       break;
+               default:
+                       /* Default to commonly supported color depth. */
+                       bits_per_pixel = dc_fixpt_from_int(8);
+                       break;
+               }
+
+               bits_per_pixel = dc_fixpt_mul_int(bits_per_pixel, 3);
+
+               if (crtc_info->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
+                       bits_per_pixel = dc_fixpt_div_int(bits_per_pixel, 3);
+                       bits_per_pixel = dc_fixpt_mul_int(bits_per_pixel, 2);
+               } else if (crtc_info->pixel_encoding == PIXEL_ENCODING_YCBCR420) {
+                       bits_per_pixel = dc_fixpt_div_int(bits_per_pixel, 2);
+               }
+       }
+
+       /* Use simple stream BW calculation because mainlink overhead is
+        * accounted for separately in the audio BW calculations.
+        */
+       peak_stream_bw_kbps = dc_fixpt_from_fraction(crtc_info->requested_pixel_clock_100Hz, 10);
+       peak_stream_bw_kbps = dc_fixpt_mul(peak_stream_bw_kbps, bits_per_pixel);
+       link_bw_kbps = dc_fixpt_from_int(dp_link_info->link_bandwidth_kbps);
+       average_stream_sym_bw_frac = dc_fixpt_div(peak_stream_bw_kbps, link_bw_kbps);
+
+       available_stream_sym_count = dc_fixpt_mul_int(hblank_time_msec, 1000);
+       available_stream_sym_count = dc_fixpt_mul(available_stream_sym_count, lsclkfreq_mhz);
+       available_stream_sym_count = dc_fixpt_mul(available_stream_sym_count, average_stream_sym_bw_frac);
+       available_hblank_bw = dc_fixpt_floor(available_stream_sym_count);
+       available_hblank_bw *= dp_link_info->lane_count;
+       available_hblank_bw -= crtc_info->dsc_num_slices * 4; /* EOC overhead */
+
+       if (available_hblank_bw < dp_link_info->hblank_min_symbol_width)
+               available_hblank_bw = dp_link_info->hblank_min_symbol_width;
+
+       if (available_hblank_bw < 12)
+               available_hblank_bw = 0;
+       else
+               available_hblank_bw -= 12; /* Main link overhead */
+
+       return available_hblank_bw;
+}
+
+static void check_audio_bandwidth_dp(
+       const struct audio_crtc_info *crtc_info,
+       const struct audio_dp_link_info *dp_link_info,
        uint32_t channel_count,
        union audio_sample_rates *sample_rates)
 {
-       /* do nothing  */
+       struct dp_audio_layout_config layout_config = {0};
+       uint32_t available_hblank_bw;
+       uint32_t av_stream_map_lane_count;
+       uint32_t audio_sdp_overhead;
+
+       /* TODO: Add validation for SST 8b/10 case  */
+       if (!dp_link_info->is_mst && dp_link_info->encoding == DP_8b_10b_ENCODING)
+               return;
+
+       available_hblank_bw = calculate_available_hblank_bw_in_symbols(
+                       crtc_info, dp_link_info);
+       av_stream_map_lane_count = get_av_stream_map_lane_count(
+                       dp_link_info->encoding, dp_link_info->lane_count, dp_link_info->is_mst);
+       audio_sdp_overhead = get_audio_sdp_overhead(
+                       dp_link_info->encoding, dp_link_info->lane_count, dp_link_info->is_mst);
+       get_audio_layout_config(
+                       channel_count, dp_link_info->encoding, &layout_config);
+
+       if (available_hblank_bw < calculate_required_audio_bw_in_symbols(
+                       crtc_info, &layout_config, channel_count, 192000,
+                       av_stream_map_lane_count, audio_sdp_overhead))
+               sample_rates->rate.RATE_192 = 0;
+       if (available_hblank_bw < calculate_required_audio_bw_in_symbols(
+                       crtc_info, &layout_config, channel_count, 176400,
+                       av_stream_map_lane_count, audio_sdp_overhead))
+               sample_rates->rate.RATE_176_4 = 0;
+       if (available_hblank_bw < calculate_required_audio_bw_in_symbols(
+                       crtc_info, &layout_config, channel_count, 96000,
+                       av_stream_map_lane_count, audio_sdp_overhead))
+               sample_rates->rate.RATE_96 = 0;
+       if (available_hblank_bw < calculate_required_audio_bw_in_symbols(
+                       crtc_info, &layout_config, channel_count, 88200,
+                       av_stream_map_lane_count, audio_sdp_overhead))
+               sample_rates->rate.RATE_88_2 = 0;
+       if (available_hblank_bw < calculate_required_audio_bw_in_symbols(
+                       crtc_info, &layout_config, channel_count, 48000,
+                       av_stream_map_lane_count, audio_sdp_overhead))
+               sample_rates->rate.RATE_48 = 0;
+       if (available_hblank_bw < calculate_required_audio_bw_in_symbols(
+                       crtc_info, &layout_config, channel_count, 44100,
+                       av_stream_map_lane_count, audio_sdp_overhead))
+               sample_rates->rate.RATE_44_1 = 0;
+       if (available_hblank_bw < calculate_required_audio_bw_in_symbols(
+                       crtc_info, &layout_config, channel_count, 32000,
+                       av_stream_map_lane_count, audio_sdp_overhead))
+               sample_rates->rate.RATE_32 = 0;
 }
 
 static void check_audio_bandwidth(
        const struct audio_crtc_info *crtc_info,
+       const struct audio_dp_link_info *dp_link_info,
        uint32_t channel_count,
        enum signal_type signal,
        union audio_sample_rates *sample_rates)
                break;
        case SIGNAL_TYPE_EDP:
        case SIGNAL_TYPE_DISPLAY_PORT:
-               check_audio_bandwidth_dpsst(
-                       crtc_info, channel_count, sample_rates);
-               break;
        case SIGNAL_TYPE_DISPLAY_PORT_MST:
-               check_audio_bandwidth_dpmst(
-                       crtc_info, channel_count, sample_rates);
+               check_audio_bandwidth_dp(
+                       crtc_info, dp_link_info, channel_count, sample_rates);
                break;
        default:
                break;
        struct audio *audio,
        enum signal_type signal,
        const struct audio_crtc_info *crtc_info,
-       const struct audio_info *audio_info)
+       const struct audio_info *audio_info,
+       const struct audio_dp_link_info *dp_link_info)
 {
        struct dce_audio *aud = DCE_AUD(audio);
 
 
                                check_audio_bandwidth(
                                        crtc_info,
+                                       dp_link_info,
                                        channel_count,
                                        signal,
                                        &sample_rates);
 
        check_audio_bandwidth(
                crtc_info,
+               dp_link_info,
                8,
                signal,
                &sample_rate);
 
        }
 }
 
+static void populate_audio_dp_link_info(
+       const struct pipe_ctx *pipe_ctx,
+       struct audio_dp_link_info *dp_link_info)
+{
+       const struct dc_stream_state *stream = pipe_ctx->stream;
+       const struct dc_link *link = stream->link;
+       struct fixed31_32 link_bw_kbps;
+
+       dp_link_info->encoding = link->dc->link_srv->dp_get_encoding_format(
+                               &pipe_ctx->link_config.dp_link_settings);
+       dp_link_info->is_mst = (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST);
+       dp_link_info->lane_count = pipe_ctx->link_config.dp_link_settings.lane_count;
+       dp_link_info->link_rate = pipe_ctx->link_config.dp_link_settings.link_rate;
+
+       link_bw_kbps = dc_fixpt_from_int(dc_link_bandwidth_kbps(link,
+                       &pipe_ctx->link_config.dp_link_settings));
+
+       /* For audio stream calculations, the video stream should not include FEC or SSC
+        * in order to get the most pessimistic values.
+        */
+       if (dp_link_info->encoding == DP_8b_10b_ENCODING &&
+                       link->dc->link_srv->dp_is_fec_supported(link)) {
+               link_bw_kbps = dc_fixpt_mul(link_bw_kbps,
+                               dc_fixpt_from_fraction(100, DATA_EFFICIENCY_8b_10b_FEC_EFFICIENCY_x100));
+       } else if (dp_link_info->encoding == DP_128b_132b_ENCODING) {
+               link_bw_kbps = dc_fixpt_mul(link_bw_kbps,
+                               dc_fixpt_from_fraction(10000, 9975)); /* 99.75% SSC overhead*/
+       }
+
+       dp_link_info->link_bandwidth_kbps = dc_fixpt_floor(link_bw_kbps);
+
+       /* HW minimum for 128b/132b HBlank is 4 frame symbols.
+        * TODO: Plumb the actual programmed HBlank min symbol width to here.
+        */
+       if (dp_link_info->encoding == DP_128b_132b_ENCODING)
+               dp_link_info->hblank_min_symbol_width = 4;
+       else
+               dp_link_info->hblank_min_symbol_width = 0;
+}
+
 static void build_audio_output(
        struct dc_state *state,
        const struct pipe_ctx *pipe_ctx,
        audio_output->crtc_info.calculated_pixel_clock_100Hz =
                        pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz;
 
+       audio_output->crtc_info.pixel_encoding =
+               stream->timing.pixel_encoding;
+
+       audio_output->crtc_info.dsc_bits_per_pixel =
+                       stream->timing.dsc_cfg.bits_per_pixel;
+
+       audio_output->crtc_info.dsc_num_slices =
+                       stream->timing.dsc_cfg.num_slices_h;
+
 /*for HDMI, audio ACR is with deep color ratio factor*/
        if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal) &&
                audio_output->crtc_info.requested_pixel_clock_100Hz ==
 
        audio_output->pll_info.ss_percentage =
                        pipe_ctx->pll_settings.ss_percentage;
+
+       if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
+               populate_audio_dp_link_info(pipe_ctx, &audio_output->dp_link_info);
+       }
 }
 
 static void program_scaler(const struct dc *dc,
                                pipe_ctx->stream_res.audio,
                                pipe_ctx->stream->signal,
                                &audio_output.crtc_info,
-                               &pipe_ctx->stream->audio_info);
+                               &pipe_ctx->stream->audio_info,
+                               &audio_output.dp_link_info);
        }
 
        /* make sure no pipes syncd to the pipe being enabled */