From 3e19095534caec6be8f8c1a7d8fd4879e23637ed Mon Sep 17 00:00:00 2001 From: Joshua Aberback Date: Wed, 29 Apr 2020 19:01:14 -0400 Subject: [PATCH] drm/amd/display: Force enable pstate on driver unload [Why] During driver unload, it is expected that p-state switching is supported. If it's not supported, PMFW will hang due to a forced p-state switch. Even if the current timing does not support p-state normally, we still want to force allow because the worst that can happen is underflow. This will match Navi10 behaviour. [How] - new hubbub func to control the force pstate register - force allow when releasing display ownership - registers are inaccessible after due to m_cgs.hwNotAvailable - explicitly disable force signal during hw_init - if driver is disabled and re-enabled, register not cleared otherwise Also, remove DCN3 part of dcn10_init_hw, we will not be going back to it. Signed-off-by: Joshua Aberback Reviewed-by: Jun Lei Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 7 +++++++ drivers/gpu/drm/amd/display/dc/dc.h | 3 +++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 6 ------ drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 13 +++++++++++++ drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h | 2 ++ drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c | 1 + drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 3 +++ 7 files changed, 29 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 014d757..8d96ef1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -3097,4 +3097,11 @@ bool dc_is_plane_eligible_for_idle_optimizaitons(struct dc *dc, { return false; } + +/* cleanup on driver unload */ +void dc_hardware_release(struct dc *dc) +{ + if (dc->hwss.hardware_release) + dc->hwss.hardware_release(dc); +} #endif diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 3ea4be4..d893211 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1267,6 +1267,9 @@ void dc_unlock_memory_clock_frequency(struct dc *dc); */ void dc_lock_memory_clock_frequency(struct dc *dc); +/* cleanup on driver unload */ +void dc_hardware_release(struct dc *dc); + #endif bool dc_set_psr_allow_active(struct dc *dc, bool enable); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 256185a..86a0d46 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1434,12 +1434,6 @@ void dcn10_init_hw(struct dc *dc) if (dc->clk_mgr->funcs->notify_wm_ranges) dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr); - -#ifdef CONFIG_DRM_AMD_DC_DCN3_0 - if (dc->clk_mgr->funcs->set_hard_max_memclk) - dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr); -#endif - } /* In headless boot cases, DIG may be turned diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c index 204773f..2ace138 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c @@ -622,6 +622,10 @@ void dcn30_init_hw(struct dc *dc) if (dc->clk_mgr->funcs->set_hard_max_memclk) dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr); + + if (dc->res_pool->hubbub->funcs->force_pstate_change_control) + dc->res_pool->hubbub->funcs->force_pstate_change_control( + dc->res_pool->hubbub, false, false); } void dcn30_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) @@ -711,3 +715,12 @@ bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable) return true; } + +void dcn30_hardware_release(struct dc *dc) +{ + /* if pstate unsupported, force it supported */ + if (!dc->clk_mgr->clks.p_state_change_support && + dc->res_pool->hubbub->funcs->force_pstate_change_control) + dc->res_pool->hubbub->funcs->force_pstate_change_control( + dc->res_pool->hubbub, true, true); +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h index a4989f5a..0ae0472 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h @@ -67,4 +67,6 @@ void dcn30_program_dmdata_engine(struct pipe_ctx *pipe_ctx); bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable); +void dcn30_hardware_release(struct dc *dc); + #endif /* __DC_HWSS_DCN30_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c index 7c90c22..ae7a789 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c @@ -93,6 +93,7 @@ static const struct hw_sequencer_funcs dcn30_funcs = { .apply_idle_power_optimizations = dcn30_apply_idle_power_optimizations, .set_backlight_level = dcn21_set_backlight_level, .set_abm_immediate_disable = dcn21_set_abm_immediate_disable, + .hardware_release = dcn30_hardware_release, }; static const struct hwseq_private_funcs dcn30_private_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index f48ee24..55c6429 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -50,6 +50,9 @@ struct dpp; struct dce_hwseq; struct hw_sequencer_funcs { +#ifdef CONFIG_DRM_AMD_DC_DCN3_0 + void (*hardware_release)(struct dc *dc); +#endif /* Embedded Display Related */ void (*edp_power_control)(struct dc_link *link, bool enable); void (*edp_wait_for_hpd_ready)(struct dc_link *link, bool power_up); -- 2.7.4