pp_smu->set_display_count(&pp_smu->pp_smu, display_count);
        }
 
-       if (should_set_clock(safe_to_lower, new_clocks->phyclk_khz, clk_mgr_base->clks.phyclk_khz)) {
-               clk_mgr_base->clks.phyclk_khz = new_clocks->phyclk_khz;
-               if (pp_smu && pp_smu->set_voltage_by_freq)
-                       pp_smu->set_voltage_by_freq(&pp_smu->pp_smu, PP_SMU_NV_PHYCLK, clk_mgr_base->clks.phyclk_khz / 1000);
-       }
-
-
        if (dc->debug.force_min_dcfclk_mhz > 0)
                new_clocks->dcfclk_khz = (new_clocks->dcfclk_khz > (dc->debug.force_min_dcfclk_mhz * 1000)) ?
                                new_clocks->dcfclk_khz : (dc->debug.force_min_dcfclk_mhz * 1000);
                return false;
        else if (a->dcfclk_deep_sleep_khz != b->dcfclk_deep_sleep_khz)
                return false;
-       else if (a->phyclk_khz != b->phyclk_khz)
-               return false;
        else if (a->dramclk_khz != b->dramclk_khz)
                return false;
        else if (a->p_state_change_support != b->p_state_change_support)
        return true;
 }
 
+/* Notify clk_mgr of a change in link rate, update phyclk frequency if necessary */
+static void dcn2_notify_link_rate_change(struct clk_mgr *clk_mgr_base, struct dc_link *link)
+{
+       struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+       unsigned int i, max_phyclk_req = 0;
+       struct pp_smu_funcs_nv *pp_smu = NULL;
+
+       if (!clk_mgr->pp_smu || !clk_mgr->pp_smu->nv_funcs.set_voltage_by_freq)
+               return;
+
+       pp_smu = &clk_mgr->pp_smu->nv_funcs;
+
+       clk_mgr->cur_phyclk_req_table[link->link_index] = link->cur_link_settings.link_rate * LINK_RATE_REF_FREQ_IN_KHZ;
+
+       for (i = 0; i < MAX_PIPES * 2; i++) {
+               if (clk_mgr->cur_phyclk_req_table[i] > max_phyclk_req)
+                       max_phyclk_req = clk_mgr->cur_phyclk_req_table[i];
+       }
+
+       if (max_phyclk_req != clk_mgr_base->clks.phyclk_khz) {
+               clk_mgr_base->clks.phyclk_khz = max_phyclk_req;
+               pp_smu->set_voltage_by_freq(&pp_smu->pp_smu, PP_SMU_NV_PHYCLK, clk_mgr_base->clks.phyclk_khz / 1000);
+       }
+}
+
 static struct clk_mgr_funcs dcn2_funcs = {
        .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
        .update_clocks = dcn2_update_clocks,
        .enable_pme_wa = dcn2_enable_pme_wa,
        .get_clock = dcn2_get_clock,
        .are_clock_states_equal = dcn2_are_clock_states_equal,
+       .notify_link_rate_change = dcn2_notify_link_rate_change,
 };
 
 
 
                }
        }
 
-       if (should_set_clock(safe_to_lower, new_clocks->phyclk_khz, clk_mgr_base->clks.phyclk_khz)) {
-               clk_mgr_base->clks.phyclk_khz = new_clocks->phyclk_khz;
-               rn_vbios_smu_set_phyclk(clk_mgr, clk_mgr_base->clks.phyclk_khz);
-       }
-
        if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz)) {
                clk_mgr_base->clks.dcfclk_khz = new_clocks->dcfclk_khz;
                rn_vbios_smu_set_hard_min_dcfclk(clk_mgr, clk_mgr_base->clks.dcfclk_khz);
 }
 
 
+/* Notify clk_mgr of a change in link rate, update phyclk frequency if necessary */
+static void rn_notify_link_rate_change(struct clk_mgr *clk_mgr_base, struct dc_link *link)
+{
+       struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+       unsigned int i, max_phyclk_req = 0;
+
+       clk_mgr->cur_phyclk_req_table[link->link_index] = link->cur_link_settings.link_rate * LINK_RATE_REF_FREQ_IN_KHZ;
+
+       for (i = 0; i < MAX_PIPES * 2; i++) {
+               if (clk_mgr->cur_phyclk_req_table[i] > max_phyclk_req)
+                       max_phyclk_req = clk_mgr->cur_phyclk_req_table[i];
+       }
+
+       if (max_phyclk_req != clk_mgr_base->clks.phyclk_khz) {
+               clk_mgr_base->clks.phyclk_khz = max_phyclk_req;
+               rn_vbios_smu_set_phyclk(clk_mgr, clk_mgr_base->clks.phyclk_khz);
+       }
+}
+
 static struct clk_mgr_funcs dcn21_funcs = {
        .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
        .update_clocks = rn_update_clocks,
        .init_clocks = rn_init_clocks,
        .enable_pme_wa = rn_enable_pme_wa,
        .are_clock_states_equal = rn_are_clock_states_equal,
-       .notify_wm_ranges = rn_notify_wm_ranges
+       .notify_wm_ranges = rn_notify_wm_ranges,
+       .notify_link_rate_change = rn_notify_link_rate_change,
 };
 
 static struct clk_bw_params rn_bw_params = {
 
        if (enter_display_off == safe_to_lower)
                dcn30_smu_set_num_of_displays(clk_mgr, display_count);
 
-       if (should_set_clock(safe_to_lower, new_clocks->phyclk_khz, clk_mgr_base->clks.phyclk_khz)) {
-               clk_mgr_base->clks.phyclk_khz = new_clocks->phyclk_khz;
-               dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_PHYCLK, clk_mgr_base->clks.phyclk_khz / 1000);
-       }
-
        if (dc->debug.force_min_dcfclk_mhz > 0)
                new_clocks->dcfclk_khz = (new_clocks->dcfclk_khz > (dc->debug.force_min_dcfclk_mhz * 1000)) ?
                                new_clocks->dcfclk_khz : (dc->debug.force_min_dcfclk_mhz * 1000);
                return false;
        else if (a->dcfclk_deep_sleep_khz != b->dcfclk_deep_sleep_khz)
                return false;
-       else if (a->phyclk_khz != b->phyclk_khz)
-               return false;
        else if (a->dramclk_khz != b->dramclk_khz)
                return false;
        else if (a->p_state_change_support != b->p_state_change_support)
        dcn30_smu_set_pme_workaround(clk_mgr);
 }
 
+/* Notify clk_mgr of a change in link rate, update phyclk frequency if necessary */
+static void dcn30_notify_link_rate_change(struct clk_mgr *clk_mgr_base, struct dc_link *link)
+{
+       struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+       unsigned int i, max_phyclk_req = clk_mgr_base->bw_params->clk_table.entries[0].phyclk_mhz * 1000;
+
+       if (!clk_mgr->smu_present)
+               return;
+
+       clk_mgr->cur_phyclk_req_table[link->link_index] = link->cur_link_settings.link_rate * LINK_RATE_REF_FREQ_IN_KHZ;
+
+       for (i = 0; i < MAX_PIPES * 2; i++) {
+               if (clk_mgr->cur_phyclk_req_table[i] > max_phyclk_req)
+                       max_phyclk_req = clk_mgr->cur_phyclk_req_table[i];
+       }
+
+       if (max_phyclk_req != clk_mgr_base->clks.phyclk_khz) {
+               clk_mgr_base->clks.phyclk_khz = max_phyclk_req;
+               dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_PHYCLK, clk_mgr_base->clks.phyclk_khz / 1000);
+       }
+}
+
 static struct clk_mgr_funcs dcn3_funcs = {
                .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
                .update_clocks = dcn3_update_clocks,
                .set_hard_max_memclk = dcn3_set_hard_max_memclk,
                .get_memclk_states_from_smu = dcn3_get_memclk_states_from_smu,
                .are_clock_states_equal = dcn3_are_clock_states_equal,
-               .enable_pme_wa = dcn3_enable_pme_wa
+               .enable_pme_wa = dcn3_enable_pme_wa,
+               .notify_link_rate_change = dcn30_notify_link_rate_change,
 };
 
 static void dcn3_init_clocks_fpga(struct clk_mgr *clk_mgr)
 
 #include "dpcd_defs.h"
 #include "dsc.h"
 #include "resource.h"
+#include "clk_mgr.h"
 
 static uint8_t convert_to_count(uint8_t lttpr_repeater_count)
 {
                }
        }
 
+       link->cur_link_settings = *link_settings;
+
+       if (dc->clk_mgr->funcs->notify_link_rate_change)
+               dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link);
+
        if (dmcu != NULL && dmcu->funcs->lock_phy)
                dmcu->funcs->lock_phy(dmcu);
 
        if (dmcu != NULL && dmcu->funcs->unlock_phy)
                dmcu->funcs->unlock_phy(dmcu);
 
-       link->cur_link_settings = *link_settings;
-
        dp_receiver_power_ctrl(link, true);
 }
 
        /* Clear current link setting.*/
        memset(&link->cur_link_settings, 0,
                        sizeof(link->cur_link_settings));
+
+       if (dc->clk_mgr->funcs->notify_link_rate_change)
+               dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link);
 }
 
 void dp_disable_link_phy_mst(struct dc_link *link, enum signal_type signal)
 
        bool (*are_clock_states_equal) (struct dc_clocks *a,
                        struct dc_clocks *b);
        void (*notify_wm_ranges)(struct clk_mgr *clk_mgr);
+
+       /* Notify clk_mgr of a change in link rate, update phyclk frequency if necessary */
+       void (*notify_link_rate_change)(struct clk_mgr *clk_mgr, struct dc_link *link);
 #ifdef CONFIG_DRM_AMD_DC_DCN3_0
        /*
         * Send message to PMFW to set hard min memclk frequency
 
 
        enum dm_pp_clocks_state max_clks_state;
        enum dm_pp_clocks_state cur_min_clks_state;
+
+       unsigned int cur_phyclk_req_table[MAX_PIPES * 2];
 #ifdef CONFIG_DRM_AMD_DC_DCN3_0
 
        bool smu_present;