From: Sung Joon Kim <sungkim@xxxxxxx> [why] Need a helper function to check idle power is allowed so that dc doesn't access any registers that are power-gated. [how] Implement helper function to check idle power optimization. Enable a hook to check if detection is allowed. V2: Add function hooks for set and get idle states. Check if function hook was properly initialized. Reviewed-by: Aric Cyr <aric.cyr@xxxxxxx> Reviewed-by: Nicholas Choi <nicholas.choi@xxxxxxx> Acked-by: Roman Li <roman.li@xxxxxxx> Signed-off-by: Sung Joon Kim <sungkim@xxxxxxx> --- drivers/gpu/drm/amd/display/dc/core/dc.c | 23 +++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../amd/display/dc/hwss/dcn31/dcn31_hwseq.c | 4 +++- .../amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 8 ++----- .../drm/amd/display/dc/hwss/hw_sequencer.h | 2 ++ .../gpu/drm/amd/display/dc/inc/hw/clk_mgr.h | 2 ++ .../gpu/drm/amd/display/dmub/src/dmub_srv.c | 1 + 7 files changed, 34 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 49e31bd52992..4f2b9911e6ff 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -4821,6 +4821,9 @@ void dc_allow_idle_optimizations(struct dc *dc, bool allow) if (dc->debug.disable_idle_power_optimizations) return; + if (dc->caps.ips_support && dc->config.disable_ips) + return; + if (dc->clk_mgr != NULL && dc->clk_mgr->funcs->is_smu_present) if (!dc->clk_mgr->funcs->is_smu_present(dc->clk_mgr)) return; @@ -4832,6 +4835,26 @@ void dc_allow_idle_optimizations(struct dc *dc, bool allow) dc->idle_optimizations_allowed = allow; } +bool dc_dmub_is_ips_idle_state(struct dc *dc) +{ + uint32_t idle_state = 0; + + if (dc->debug.disable_idle_power_optimizations) + return false; + + if (!dc->caps.ips_support || dc->config.disable_ips) + return false; + + if (dc->hwss.get_idle_state) + idle_state = dc->hwss.get_idle_state(dc); + + if ((idle_state & DMUB_IPS1_ALLOW_MASK) || + (idle_state & DMUB_IPS2_ALLOW_MASK)) + return true; + + return false; +} + /* set min and max memory clock to lowest and highest DPM level, respectively */ void dc_unlock_memory_clock_frequency(struct dc *dc) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index cc1cae4d7329..e3b8c71e2c31 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -2362,6 +2362,7 @@ bool dc_is_plane_eligible_for_idle_optimizations(struct dc *dc, struct dc_plane_ struct dc_cursor_attributes *cursor_attr); void dc_allow_idle_optimizations(struct dc *dc, bool allow); +bool dc_dmub_is_ips_idle_state(struct dc *dc); /* set min and max memory clock to lowest and highest DPM level, respectively */ void dc_unlock_memory_clock_frequency(struct dc *dc); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c index 5daedd893923..5d62805f3bdf 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c @@ -586,7 +586,9 @@ void dcn31_reset_hw_ctx_wrap( struct clock_source *old_clk = pipe_ctx_old->clock_source; /* Reset pipe which is seamless boot stream. */ - if (!pipe_ctx_old->plane_state) { + if (!pipe_ctx_old->plane_state && + dc->res_pool->hubbub->funcs->program_det_size && + dc->res_pool->hubbub->funcs->wait_for_det_apply) { dc->res_pool->hubbub->funcs->program_det_size( dc->res_pool->hubbub, pipe_ctx_old->plane_res.hubp->inst, 0); /* Wait det size changed. */ diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c index 12821cb9ab6c..36d2b91aa337 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c @@ -627,12 +627,8 @@ void dcn35_power_down_on_boot(struct dc *dc) if (dc->clk_mgr->funcs->set_low_power_state) dc->clk_mgr->funcs->set_low_power_state(dc->clk_mgr); - if (dc->clk_mgr->clks.pwr_state == DCN_PWR_STATE_LOW_POWER) { - if (!dc->idle_optimizations_allowed) { - dc_dmub_srv_notify_idle(dc, true); - dc->idle_optimizations_allowed = true; - } - } + if (dc->clk_mgr->clks.pwr_state == DCN_PWR_STATE_LOW_POWER) + dc_allow_idle_optimizations(dc, true); } bool dcn35_apply_idle_power_optimizations(struct dc *dc, bool enable) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h index d45302035e3f..c43d1f6c2a06 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h @@ -418,6 +418,8 @@ struct hw_sequencer_funcs { struct pg_block_update *update_state, bool power_on); void (*root_clock_control)(struct dc *dc, struct pg_block_update *update_state, bool power_on); + void (*set_idle_state)(const struct dc *dc, bool allow_idle); + uint32_t (*get_idle_state)(const struct dc *dc); bool (*is_pipe_topology_transition_seamless)(struct dc *dc, const struct dc_state *cur_ctx, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h index cb2dc3f75ae2..fa9614bcb160 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h @@ -262,6 +262,8 @@ struct clk_mgr_funcs { void (*set_low_power_state)(struct clk_mgr *clk_mgr); void (*exit_low_power_state)(struct clk_mgr *clk_mgr); bool (*is_ips_supported)(struct clk_mgr *clk_mgr); + void (*set_idle_state)(struct clk_mgr *clk_mgr, bool allow_idle); + uint32_t (*get_idle_state)(struct clk_mgr *clk_mgr); void (*init_clocks)(struct clk_mgr *clk_mgr); diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c index b99db771e071..e43e8d4bfe37 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c @@ -352,6 +352,7 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic) funcs->init_reg_offsets = dmub_srv_dcn35_regs_init; funcs->is_hw_powered_up = dmub_dcn35_is_hw_powered_up; + funcs->should_detect = dmub_dcn35_should_detect; break; default: -- 2.34.1