Commit efc7d165 authored by Joshua Aberback's avatar Joshua Aberback Committed by Alex Deucher

drm/amd/display: Request PHYCLK adjustment on PHY enable/disable

[Why]
Currently we don't explicitly send a request for a minimum PHYCLK, and
we hope that the dependencies other clocks have will raise PHYCLK when
needed.

[How]
- new clk_mgr function to keep track of PHYCLK requirements
- request maximum requirement across all links
- remove PHYCLK from clock state comparator, as it doesn't come from DML
Signed-off-by: default avatarJoshua Aberback <joshua.aberback@amd.com>
Reviewed-by: default avatarJun Lei <Jun.Lei@amd.com>
Acked-by: default avatarEryk Brol <eryk.brol@amd.com>
Acked-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent d3d847d8
...@@ -184,13 +184,6 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base, ...@@ -184,13 +184,6 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base,
pp_smu->set_display_count(&pp_smu->pp_smu, display_count); 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) 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 = (new_clocks->dcfclk_khz > (dc->debug.force_min_dcfclk_mhz * 1000)) ?
new_clocks->dcfclk_khz : (dc->debug.force_min_dcfclk_mhz * 1000); new_clocks->dcfclk_khz : (dc->debug.force_min_dcfclk_mhz * 1000);
...@@ -417,8 +410,6 @@ static bool dcn2_are_clock_states_equal(struct dc_clocks *a, ...@@ -417,8 +410,6 @@ static bool dcn2_are_clock_states_equal(struct dc_clocks *a,
return false; return false;
else if (a->dcfclk_deep_sleep_khz != b->dcfclk_deep_sleep_khz) else if (a->dcfclk_deep_sleep_khz != b->dcfclk_deep_sleep_khz)
return false; return false;
else if (a->phyclk_khz != b->phyclk_khz)
return false;
else if (a->dramclk_khz != b->dramclk_khz) else if (a->dramclk_khz != b->dramclk_khz)
return false; return false;
else if (a->p_state_change_support != b->p_state_change_support) else if (a->p_state_change_support != b->p_state_change_support)
...@@ -427,6 +418,31 @@ static bool dcn2_are_clock_states_equal(struct dc_clocks *a, ...@@ -427,6 +418,31 @@ static bool dcn2_are_clock_states_equal(struct dc_clocks *a,
return true; 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 = { static struct clk_mgr_funcs dcn2_funcs = {
.get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz, .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
.update_clocks = dcn2_update_clocks, .update_clocks = dcn2_update_clocks,
...@@ -434,6 +450,7 @@ static struct clk_mgr_funcs dcn2_funcs = { ...@@ -434,6 +450,7 @@ static struct clk_mgr_funcs dcn2_funcs = {
.enable_pme_wa = dcn2_enable_pme_wa, .enable_pme_wa = dcn2_enable_pme_wa,
.get_clock = dcn2_get_clock, .get_clock = dcn2_get_clock,
.are_clock_states_equal = dcn2_are_clock_states_equal, .are_clock_states_equal = dcn2_are_clock_states_equal,
.notify_link_rate_change = dcn2_notify_link_rate_change,
}; };
......
...@@ -136,11 +136,6 @@ void rn_update_clocks(struct clk_mgr *clk_mgr_base, ...@@ -136,11 +136,6 @@ void rn_update_clocks(struct clk_mgr *clk_mgr_base,
} }
} }
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)) { 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; 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); rn_vbios_smu_set_hard_min_dcfclk(clk_mgr, clk_mgr_base->clks.dcfclk_khz);
...@@ -496,13 +491,33 @@ static bool rn_are_clock_states_equal(struct dc_clocks *a, ...@@ -496,13 +491,33 @@ static bool rn_are_clock_states_equal(struct dc_clocks *a,
} }
/* 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 = { static struct clk_mgr_funcs dcn21_funcs = {
.get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz, .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
.update_clocks = rn_update_clocks, .update_clocks = rn_update_clocks,
.init_clocks = rn_init_clocks, .init_clocks = rn_init_clocks,
.enable_pme_wa = rn_enable_pme_wa, .enable_pme_wa = rn_enable_pme_wa,
.are_clock_states_equal = rn_are_clock_states_equal, .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 = { static struct clk_bw_params rn_bw_params = {
......
...@@ -260,11 +260,6 @@ static void dcn3_update_clocks(struct clk_mgr *clk_mgr_base, ...@@ -260,11 +260,6 @@ static void dcn3_update_clocks(struct clk_mgr *clk_mgr_base,
if (enter_display_off == safe_to_lower) if (enter_display_off == safe_to_lower)
dcn30_smu_set_num_of_displays(clk_mgr, display_count); 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) 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 = (new_clocks->dcfclk_khz > (dc->debug.force_min_dcfclk_mhz * 1000)) ?
new_clocks->dcfclk_khz : (dc->debug.force_min_dcfclk_mhz * 1000); new_clocks->dcfclk_khz : (dc->debug.force_min_dcfclk_mhz * 1000);
...@@ -431,8 +426,6 @@ static bool dcn3_are_clock_states_equal(struct dc_clocks *a, ...@@ -431,8 +426,6 @@ static bool dcn3_are_clock_states_equal(struct dc_clocks *a,
return false; return false;
else if (a->dcfclk_deep_sleep_khz != b->dcfclk_deep_sleep_khz) else if (a->dcfclk_deep_sleep_khz != b->dcfclk_deep_sleep_khz)
return false; return false;
else if (a->phyclk_khz != b->phyclk_khz)
return false;
else if (a->dramclk_khz != b->dramclk_khz) else if (a->dramclk_khz != b->dramclk_khz)
return false; return false;
else if (a->p_state_change_support != b->p_state_change_support) else if (a->p_state_change_support != b->p_state_change_support)
...@@ -451,6 +444,28 @@ static void dcn3_enable_pme_wa(struct clk_mgr *clk_mgr_base) ...@@ -451,6 +444,28 @@ static void dcn3_enable_pme_wa(struct clk_mgr *clk_mgr_base)
dcn30_smu_set_pme_workaround(clk_mgr); 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 = { static struct clk_mgr_funcs dcn3_funcs = {
.get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz, .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
.update_clocks = dcn3_update_clocks, .update_clocks = dcn3_update_clocks,
...@@ -460,7 +475,8 @@ static struct clk_mgr_funcs dcn3_funcs = { ...@@ -460,7 +475,8 @@ static struct clk_mgr_funcs dcn3_funcs = {
.set_hard_max_memclk = dcn3_set_hard_max_memclk, .set_hard_max_memclk = dcn3_set_hard_max_memclk,
.get_memclk_states_from_smu = dcn3_get_memclk_states_from_smu, .get_memclk_states_from_smu = dcn3_get_memclk_states_from_smu,
.are_clock_states_equal = dcn3_are_clock_states_equal, .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) static void dcn3_init_clocks_fpga(struct clk_mgr *clk_mgr)
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "dpcd_defs.h" #include "dpcd_defs.h"
#include "dsc.h" #include "dsc.h"
#include "resource.h" #include "resource.h"
#include "clk_mgr.h"
static uint8_t convert_to_count(uint8_t lttpr_repeater_count) static uint8_t convert_to_count(uint8_t lttpr_repeater_count)
{ {
...@@ -123,6 +124,11 @@ void dp_enable_link_phy( ...@@ -123,6 +124,11 @@ void dp_enable_link_phy(
} }
} }
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) if (dmcu != NULL && dmcu->funcs->lock_phy)
dmcu->funcs->lock_phy(dmcu); dmcu->funcs->lock_phy(dmcu);
...@@ -141,8 +147,6 @@ void dp_enable_link_phy( ...@@ -141,8 +147,6 @@ void dp_enable_link_phy(
if (dmcu != NULL && dmcu->funcs->unlock_phy) if (dmcu != NULL && dmcu->funcs->unlock_phy)
dmcu->funcs->unlock_phy(dmcu); dmcu->funcs->unlock_phy(dmcu);
link->cur_link_settings = *link_settings;
dp_receiver_power_ctrl(link, true); dp_receiver_power_ctrl(link, true);
} }
...@@ -234,6 +238,9 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) ...@@ -234,6 +238,9 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal)
/* Clear current link setting.*/ /* Clear current link setting.*/
memset(&link->cur_link_settings, 0, memset(&link->cur_link_settings, 0,
sizeof(link->cur_link_settings)); 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) void dp_disable_link_phy_mst(struct dc_link *link, enum signal_type signal)
......
...@@ -241,6 +241,9 @@ struct clk_mgr_funcs { ...@@ -241,6 +241,9 @@ struct clk_mgr_funcs {
bool (*are_clock_states_equal) (struct dc_clocks *a, bool (*are_clock_states_equal) (struct dc_clocks *a,
struct dc_clocks *b); struct dc_clocks *b);
void (*notify_wm_ranges)(struct clk_mgr *clk_mgr); 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 #ifdef CONFIG_DRM_AMD_DC_DCN3_0
/* /*
* Send message to PMFW to set hard min memclk frequency * Send message to PMFW to set hard min memclk frequency
......
...@@ -270,6 +270,8 @@ struct clk_mgr_internal { ...@@ -270,6 +270,8 @@ struct clk_mgr_internal {
enum dm_pp_clocks_state max_clks_state; enum dm_pp_clocks_state max_clks_state;
enum dm_pp_clocks_state cur_min_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 #ifdef CONFIG_DRM_AMD_DC_DCN3_0
bool smu_present; bool smu_present;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment