diff options
| author | Duncan Ma <duncan.ma@amd.com> | 2023-08-28 15:48:27 -0400 |
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2023-09-26 17:00:21 -0400 |
| commit | 1288d702080949f87688d49dfeeacc99f40adc9b (patch) | |
| tree | b2d894cd87eb9db0bb13bbb4fe1c6f45ac0e7771 /drivers/gpu/drm/amd/display/dc/clk_mgr | |
| parent | 786d3b1d83432d4c91468933793c25e248f26cb5 (diff) | |
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/clk_mgr')
3 files changed, 52 insertions, 3 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c index 819d273f011d..c9c7baf45be3 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c @@ -738,6 +738,34 @@ static void dcn35_set_low_power_state(struct clk_mgr *clk_mgr_base) } } +static void dcn35_set_idle_state(struct clk_mgr *clk_mgr_base, bool allow_idle) +{ + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + struct dc *dc = clk_mgr_base->ctx->dc; + uint32_t val = dcn35_smu_read_ips_scratch(clk_mgr); + + if (dc->debug.disable_ips == 0) { + val |= DMUB_IPS1_ALLOW_MASK; + val |= DMUB_IPS2_ALLOW_MASK; + } else if (dc->debug.disable_ips == DMUB_IPS_DISABLE_IPS1) { + val = val & ~DMUB_IPS1_ALLOW_MASK; + val = val & ~DMUB_IPS2_ALLOW_MASK; + } else if (dc->debug.disable_ips == DMUB_IPS_DISABLE_IPS2) { + val |= DMUB_IPS1_ALLOW_MASK; + val = val & ~DMUB_IPS2_ALLOW_MASK; + } else if (dc->debug.disable_ips == DMUB_IPS_DISABLE_IPS2_Z10) { + val |= DMUB_IPS1_ALLOW_MASK; + val |= DMUB_IPS2_ALLOW_MASK; + } + + if (!allow_idle) { + val = val & ~DMUB_IPS1_ALLOW_MASK; + val = val & ~DMUB_IPS2_ALLOW_MASK; + } + + dcn35_smu_write_ips_scratch(clk_mgr, val); +} + static void dcn35_exit_low_power_state(struct clk_mgr *clk_mgr_base) { struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); @@ -757,6 +785,13 @@ static bool dcn35_is_ips_supported(struct clk_mgr *clk_mgr_base) return ips_supported; } +static uint32_t dcn35_get_idle_state(struct clk_mgr *clk_mgr_base) +{ + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + + return dcn35_smu_read_ips_scratch(clk_mgr); +} + static void dcn35_init_clocks_fpga(struct clk_mgr *clk_mgr) { dcn35_init_clocks(clk_mgr); @@ -844,6 +879,8 @@ static struct clk_mgr_funcs dcn35_funcs = { .set_low_power_state = dcn35_set_low_power_state, .exit_low_power_state = dcn35_exit_low_power_state, .is_ips_supported = dcn35_is_ips_supported, + .set_idle_state = dcn35_set_idle_state, + .get_idle_state = dcn35_get_idle_state }; struct clk_mgr_funcs dcn35_fpga_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c index f42c0a727dc8..cf74e69cb2a1 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c @@ -444,9 +444,9 @@ void dcn35_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn(struct clk_mgr_internal *cl enable); } -void dcn35_smu_exit_low_power_state(struct clk_mgr_internal *clk_mgr) +int dcn35_smu_exit_low_power_state(struct clk_mgr_internal *clk_mgr) { - dcn35_smu_send_msg_with_param( + return dcn35_smu_send_msg_with_param( clk_mgr, VBIOSSMC_MSG_DispPsrExit, 0); @@ -459,3 +459,13 @@ int dcn35_smu_get_ips_supported(struct clk_mgr_internal *clk_mgr) VBIOSSMC_MSG_QueryIPS2Support, 0); } + +void dcn35_smu_write_ips_scratch(struct clk_mgr_internal *clk_mgr, uint32_t param) +{ + REG_WRITE(MP1_SMN_C2PMSG_71, param); +} + +uint32_t dcn35_smu_read_ips_scratch(struct clk_mgr_internal *clk_mgr) +{ + return REG_READ(MP1_SMN_C2PMSG_71); +} diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.h index 4d441d6db8d0..8fb65a49351b 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.h @@ -174,8 +174,10 @@ void dcn35_smu_set_zstate_support(struct clk_mgr_internal *clk_mgr, enum dcn_zst void dcn35_smu_set_dtbclk(struct clk_mgr_internal *clk_mgr, bool enable); void dcn35_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable); -void dcn35_smu_exit_low_power_state(struct clk_mgr_internal *clk_mgr); +int dcn35_smu_exit_low_power_state(struct clk_mgr_internal *clk_mgr); int dcn35_smu_get_ips_supported(struct clk_mgr_internal *clk_mgr); int dcn35_smu_get_dtbclk(struct clk_mgr_internal *clk_mgr); int dcn35_smu_get_dprefclk(struct clk_mgr_internal *clk_mgr); +void dcn35_smu_write_ips_scratch(struct clk_mgr_internal *clk_mgr, uint32_t param); +uint32_t dcn35_smu_read_ips_scratch(struct clk_mgr_internal *clk_mgr); #endif /* DAL_DC_35_SMU_H_ */ |
