diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 73 |
1 files changed, 65 insertions, 8 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c index 24c5765890fa..c664404a75d4 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c @@ -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)) { 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); @@ -153,8 +148,9 @@ void rn_update_clocks(struct clk_mgr *clk_mgr_base, } // workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch to plus 4K monitor underflow. + // Do not adjust dppclk if dppclk is 0 to avoid unexpected result if (!IS_DIAG_DC(dc->ctx->dce_environment)) { - if (new_clocks->dppclk_khz < 100000) + if (new_clocks->dppclk_khz < 100000 && new_clocks->dppclk_khz > 0) new_clocks->dppclk_khz = 100000; } @@ -495,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 = { .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 = { @@ -618,6 +634,42 @@ static struct wm_table lpddr4_wm_table = { } }; +static struct wm_table lpddr4_wm_table_with_disabled_ppt = { + .entries = { + { + .wm_inst = WM_A, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.65333, + .sr_exit_time_us = 8.32, + .sr_enter_plus_exit_time_us = 9.38, + .valid = true, + }, + { + .wm_inst = WM_B, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.65333, + .sr_exit_time_us = 9.82, + .sr_enter_plus_exit_time_us = 11.196, + .valid = true, + }, + { + .wm_inst = WM_C, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.65333, + .sr_exit_time_us = 9.89, + .sr_enter_plus_exit_time_us = 11.24, + .valid = true, + }, + { + .wm_inst = WM_D, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.65333, + .sr_exit_time_us = 9.748, + .sr_enter_plus_exit_time_us = 11.102, + .valid = true, + }, + } +}; static unsigned int find_dcfclk_for_voltage(struct dpm_clocks *clock_table, unsigned int voltage) { @@ -722,6 +774,7 @@ void rn_clk_mgr_construct( struct clk_log_info log_info = {0}; clk_mgr->smu_ver = rn_vbios_smu_get_smu_version(clk_mgr); + clk_mgr->periodic_retraining_disabled = rn_vbios_smu_is_periodic_retraining_disabled(clk_mgr); /* SMU Version 55.51.0 and up no longer have an issue * that needs to limit minimum dispclk */ @@ -736,7 +789,11 @@ void rn_clk_mgr_construct( clk_mgr->base.dentist_vco_freq_khz = 3600000; if (ctx->dc_bios->integrated_info->memory_type == LpDdr4MemType) { - rn_bw_params.wm_table = lpddr4_wm_table; + if (clk_mgr->periodic_retraining_disabled) { + rn_bw_params.wm_table = lpddr4_wm_table_with_disabled_ppt; + } else { + rn_bw_params.wm_table = lpddr4_wm_table; + } } else { rn_bw_params.wm_table = ddr4_wm_table; } |