diff options
author | Duncan Ma <duncan.ma@amd.com> | 2023-08-28 22:48:27 +0300 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2023-09-27 00:00:21 +0300 |
commit | 1288d702080949f87688d49dfeeacc99f40adc9b (patch) | |
tree | b2d894cd87eb9db0bb13bbb4fe1c6f45ac0e7771 /drivers/gpu/drm/amd/display/dc/dcn35 | |
parent | 786d3b1d83432d4c91468933793c25e248f26cb5 (diff) | |
download | linux-1288d702080949f87688d49dfeeacc99f40adc9b.tar.xz |
drm/amd/display: Improve x86 and dmub ips handshake
[Why]
There is a race condition between x86 and dmcub fw when attempting to exit
IPS2. Scenarios including exiting IPS2 before IPS2 has been entered. This
can cause unexpected hang when DMCUB attempt to exit while PMFW still
tries to enter IPS2.
[How]
A new design has been introduced to remove race conditions and improve the
handshake between x86 and DMCUB. An AON scratch register is borrowed from
PMFW to determine whether DMCUB has committed to IPS entry or not.
In the case when dmcub has committed IPS entry, x86 must poll until an exit
event occurred either from DMCUB(IPS1) or PMFW(IPS2). x86 will wait
upperbound of evaluation and IPS entry time to ensure IPS2 exit event has
been sent to PMFW.
Reviewed-by: Charlene Liu <charlene.liu@amd.com>
Acked-by: Wayne Lin <wayne.lin@amd.com>
Signed-off-by: Duncan Ma <duncan.ma@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dcn35')
4 files changed, 27 insertions, 12 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hwseq.c index 06960fada059..03ef7820139a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hwseq.c @@ -647,18 +647,10 @@ bool dcn35_apply_idle_power_optimizations(struct dc *dc, bool enable) // TODO: review other cases when idle optimization is allowed - if (!enable) { - // Tell PMFW to exit low power state - if (dc->clk_mgr->funcs->exit_low_power_state) - dc->clk_mgr->funcs->exit_low_power_state(dc->clk_mgr); - - dc_dmub_srv_is_hw_pwr_up(dc->ctx->dmub_srv, true); - } - - dc_dmub_srv_notify_idle(dc, enable); - if (!enable) - dc_dmub_srv_is_hw_pwr_up(dc->ctx->dmub_srv, true); + dc_dmub_srv_exit_low_power_state(dc); + else + dc_dmub_srv_notify_idle(dc, enable); return true; } @@ -1192,3 +1184,19 @@ void dcn35_optimize_bandwidth( dc->hwss.root_clock_control(dc, &pg_update_state, false); } } + +void dcn35_set_idle_state(const struct dc *dc, bool allow_idle) +{ + // TODO: Find a more suitable communcation + if (dc->clk_mgr->funcs->set_idle_state) + dc->clk_mgr->funcs->set_idle_state(dc->clk_mgr, allow_idle); +} + +uint32_t dcn35_get_idle_state(const struct dc *dc) +{ + // TODO: Find a more suitable communcation + if (dc->clk_mgr->funcs->get_idle_state) + return dc->clk_mgr->funcs->get_idle_state(dc->clk_mgr); + + return 0; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hwseq.h index 7c0ff7b163a9..14bbdb0fa634 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hwseq.h @@ -79,4 +79,7 @@ void dcn35_dsc_pg_control( struct dce_hwseq *hws, unsigned int dsc_inst, bool power_on); + +void dcn35_set_idle_state(const struct dc *dc, bool allow_idle); +uint32_t dcn35_get_idle_state(const struct dc *dc); #endif /* __DC_HWSS_DCN35_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_init.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_init.c index d68efe5c64a4..a9553a87b959 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_init.c @@ -117,7 +117,9 @@ static const struct hw_sequencer_funcs dcn35_funcs = { .calc_blocks_to_gate = dcn35_calc_blocks_to_gate, .calc_blocks_to_ungate = dcn35_calc_blocks_to_ungate, .block_power_control = dcn35_block_power_control, - .root_clock_control = dcn35_root_clock_control + .root_clock_control = dcn35_root_clock_control, + .set_idle_state = dcn35_set_idle_state, + .get_idle_state = dcn35_get_idle_state }; static const struct hwseq_private_funcs dcn35_private_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c index 06fd02084d7c..67ff19d4116d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c @@ -748,6 +748,8 @@ static const struct dc_debug_options debug_defaults_drv = { .ignore_pg = true, .psp_disabled_wa = true, .disable_ips = true, + .ips2_eval_delay_us = 200, + .ips2_entry_delay_us = 400 }; static const struct dc_panel_config panel_config_defaults = { |