return false;
        }
 
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+       if (dongle_caps->dp_hdmi_frl_max_link_bw_in_kbps > 0) { // DP to HDMI FRL converter
+               struct dc_crtc_timing outputTiming = *timing;
+
+               if (timing->flags.DSC && !timing->dsc_cfg.is_frl)
+                       /* DP input has DSC, HDMI FRL output doesn't have DSC, remove DSC from output timing */
+                       outputTiming.flags.DSC = 0;
+               if (dc_bandwidth_in_kbps_from_timing(&outputTiming) > dongle_caps->dp_hdmi_frl_max_link_bw_in_kbps)
+                       return false;
+       } else { // DP to HDMI TMDS converter
+               if (get_timing_pixel_clock_100hz(timing) > (dongle_caps->dp_hdmi_max_pixel_clk_in_khz * 10))
+                       return false;
+       }
+#else
        if (get_timing_pixel_clock_100hz(timing) > (dongle_caps->dp_hdmi_max_pixel_clk_in_khz * 10))
                return false;
+#endif
 
 #if defined(CONFIG_DRM_AMD_DC_DCN)
        }
 
        return -1;
 }
 
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+uint32_t dc_link_bw_kbps_from_raw_frl_link_rate_data(uint8_t bw)
+{
+       switch (bw) {
+       case 0b001:
+               return 9000000;
+       case 0b010:
+               return 18000000;
+       case 0b011:
+               return 24000000;
+       case 0b100:
+               return 32000000;
+       case 0b101:
+               return 40000000;
+       case 0b110:
+               return 48000000;
+       }
+
+       return 0;
+}
+
+/**
+ * Return PCON's post FRL link training supported BW if its non-zero, otherwise return max_supported_frl_bw.
+ */
+static uint32_t intersect_frl_link_bw_support(
+       const uint32_t max_supported_frl_bw_in_kbps,
+       const union hdmi_encoded_link_bw hdmi_encoded_link_bw)
+{
+       uint32_t supported_bw_in_kbps = max_supported_frl_bw_in_kbps;
+
+       // HDMI_ENCODED_LINK_BW bits are only valid if HDMI Link Configuration bit is 1 (FRL mode)
+       if (hdmi_encoded_link_bw.bits.FRL_MODE) {
+               if (hdmi_encoded_link_bw.bits.BW_48Gbps)
+                       supported_bw_in_kbps = 48000000;
+               else if (hdmi_encoded_link_bw.bits.BW_40Gbps)
+                       supported_bw_in_kbps = 40000000;
+               else if (hdmi_encoded_link_bw.bits.BW_32Gbps)
+                       supported_bw_in_kbps = 32000000;
+               else if (hdmi_encoded_link_bw.bits.BW_24Gbps)
+                       supported_bw_in_kbps = 24000000;
+               else if (hdmi_encoded_link_bw.bits.BW_18Gbps)
+                       supported_bw_in_kbps = 18000000;
+               else if (hdmi_encoded_link_bw.bits.BW_9Gbps)
+                       supported_bw_in_kbps = 9000000;
+       }
+
+       return supported_bw_in_kbps;
+}
+#endif
+
 static void read_dp_device_vendor_id(struct dc_link *link)
 {
        struct dp_device_vendor_id dp_id;
                                                translate_dpcd_max_bpc(
                                                        hdmi_color_caps.bits.MAX_BITS_PER_COLOR_COMPONENT);
 
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+                                       if (link->dc->caps.hdmi_frl_pcon_support) {
+                                               union hdmi_encoded_link_bw hdmi_encoded_link_bw;
+
+                                               link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps =
+                                                               dc_link_bw_kbps_from_raw_frl_link_rate_data(
+                                                                               hdmi_color_caps.bits.MAX_ENCODED_LINK_BW_SUPPORT);
+
+                                               // Intersect reported max link bw support with the supported link rate post FRL link training
+                                               if (core_link_read_dpcd(link, DP_PCON_HDMI_POST_FRL_STATUS,
+                                                               &hdmi_encoded_link_bw.raw, sizeof(hdmi_encoded_link_bw)) == DC_OK) {
+                                                       link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps = intersect_frl_link_bw_support(
+                                                                       link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps,
+                                                                       hdmi_encoded_link_bw);
+                                               }
+
+                                               if (link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps > 0)
+                                                       link->dpcd_caps.dongle_caps.extendedCapValid = true;
+                                       }
+#endif
+
                                        if (link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk_in_khz != 0)
                                                link->dpcd_caps.dongle_caps.extendedCapValid = true;
                                }
 
        struct dc_color_caps color;
 #if defined(CONFIG_DRM_AMD_DC_DCN)
        bool dp_hpo;
+       bool hdmi_frl_pcon_support;
 #endif
        bool edp_dsc_support;
        bool vbios_lttpr_aware;
        // 'true' if these are virtual DPCD's DSC caps (immediately upstream of sink in MST topology),
        // 'false' if they are sink's DSC caps
        bool is_virtual_dpcd_dsc;
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+       // 'true' if MST topology supports DSC passthrough for sink
+       // 'false' if MST topology does not support DSC passthrough
+       bool is_dsc_passthrough_supported;
+#endif
        struct dsc_dec_dpcd_caps dsc_dec_caps;
 };
 
 
 union dwnstream_port_caps_byte2 {
        struct {
                uint8_t MAX_BITS_PER_COLOR_COMPONENT:2;
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+               uint8_t MAX_ENCODED_LINK_BW_SUPPORT:3;
+               uint8_t SOURCE_CONTROL_MODE_SUPPORT:1;
+               uint8_t CONCURRENT_LINK_BRING_UP_SEQ_SUPPORT:1;
+               uint8_t RESERVED:1;
+#else
                uint8_t RESERVED:6;
+#endif
        } bits;
        uint8_t raw;
 };
        uint8_t raw;
 };
 
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+union hdmi_sink_encoded_link_bw_support {
+       struct {
+               uint8_t HDMI_SINK_ENCODED_LINK_BW_SUPPORT:3;
+               uint8_t RESERVED:5;
+       } bits;
+       uint8_t raw;
+};
+
+union hdmi_encoded_link_bw {
+       struct {
+               uint8_t FRL_MODE:1; // Bit 0
+               uint8_t BW_9Gbps:1;
+               uint8_t BW_18Gbps:1;
+               uint8_t BW_24Gbps:1;
+               uint8_t BW_32Gbps:1;
+               uint8_t BW_40Gbps:1;
+               uint8_t BW_48Gbps:1;
+               uint8_t RESERVED:1; // Bit 7
+       } bits;
+       uint8_t raw;
+};
+#endif
+
 /*4-byte structure for detailed capabilities of a down-stream port
 (DP-to-TMDS converter).*/
 union dwnstream_portxcaps {
 
        uint32_t version_minor; /* DSC minor version. Full version is formed as 1.version_minor. */
        bool ycbcr422_simple; /* Tell DSC engine to convert YCbCr 4:2:2 to 'YCbCr 4:2:2 simple'. */
        int32_t rc_buffer_size; /* DSC RC buffer block size in bytes */
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+       bool is_frl; /* indicate if DSC is applied based on HDMI FRL sink's capability */
+#endif
        bool is_dp; /* indicate if DSC is applied based on DP's capability */
 };
 struct dc_crtc_timing {
 
 bool dc_link_should_enable_fec(const struct dc_link *link);
 
 #if defined(CONFIG_DRM_AMD_DC_DCN)
+uint32_t dc_link_bw_kbps_from_raw_frl_link_rate_data(uint8_t bw);
 enum dp_link_encoding dc_link_dp_mst_decide_link_encoding_format(const struct dc_link *link);
 #endif
 #endif /* DC_LINK_H_ */
 
        uint32_t dp_hdmi_max_bpc;
        uint32_t dp_hdmi_max_pixel_clk_in_khz;
 #if defined(CONFIG_DRM_AMD_DC_DCN)
+       uint32_t dp_hdmi_frl_max_link_bw_in_kbps;
        struct dc_dongle_dfp_cap_ext dfp_cap_ext;
 #endif
 };
 
        dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
        dc->caps.color.mpc.ocsc = 1;
 
+       dc->caps.hdmi_frl_pcon_support = true;
+
        if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) {
                dc->debug = debug_defaults_drv;
        } else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) {
 
        dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
        dc->caps.color.mpc.ocsc = 1;
 
+       dc->caps.hdmi_frl_pcon_support = true;
+
        if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
                dc->debug = debug_defaults_drv;
        else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) {
 
        dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
        dc->caps.color.mpc.ocsc = 1;
 
+       dc->caps.hdmi_frl_pcon_support = true;
+
        /* read VBIOS LTTPR caps */
        {
                if (ctx->dc_bios->funcs->get_lttpr_caps) {
 
        dc->caps.post_blend_color_processing = true;
        dc->caps.force_dp_tps4_for_cp2520 = true;
        dc->caps.dp_hpo = true;
+       dc->caps.hdmi_frl_pcon_support = true;
        dc->caps.edp_dsc_support = true;
        dc->caps.extended_aux_timeout_support = true;
        dc->caps.dmcub_support = true;