drm/amd/display: Add a check for idle power optimization
authorSung Joon Kim <sungkim@amd.com>
Fri, 29 Sep 2023 16:12:47 +0000 (12:12 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 26 Oct 2023 22:57:15 +0000 (18:57 -0400)
[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@amd.com>
Reviewed-by: Nicholas Choi <nicholas.choi@amd.com>
Acked-by: Roman Li <roman.li@amd.com>
Signed-off-by: Sung Joon Kim <sungkim@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h
drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c

index e13d8bab0b336251a41b412d7a6a8d6a5b1c9b1e..d13904548505bdc81cf8a89105a6a3ae20919409 100644 (file)
@@ -4884,6 +4884,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;
@@ -4895,6 +4898,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)
 {
index 342022b7ab37ec969eb1f4b3f22390649890a6c7..eab9a0be33286032d7b13c4902590631bf28181a 100644 (file)
@@ -2315,6 +2315,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);
index a22cd2aee286e8a9a2d91b34d45e7d42e316dbbc..97798cee876e2ec903aeb5777000910319d4dc7d 100644 (file)
@@ -585,7 +585,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. */
index 8f717db01f8537059757f0db2064a4af3a248171..ece806a63d8dae6784ff38258729508c0efb5d2b 100644 (file)
@@ -629,12 +629,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)
index d45302035e3fe44aebacd01507f77b36ec25ab7b..c43d1f6c2a063aed58997e0438f2c63168ee0c40 100644 (file)
@@ -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,
index cb2dc3f75ae2888cb1807599ea8fae767750b29c..fa9614bcb1605f6b75f116ca5387df338bc3dc4c 100644 (file)
@@ -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);
 
index b99db771e071499ecbd7cffa7e00c8fab87c6ce8..e43e8d4bfe375e93f9e75d285e57bb41cffc44de 100644 (file)
@@ -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: