drm/amd/display: power up all gating blocks when releasing hw DCN35
authorYihan Zhu <Yihan.Zhu@amd.com>
Thu, 5 Dec 2024 19:28:51 +0000 (14:28 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 6 Jan 2025 19:44:26 +0000 (14:44 -0500)
[WHY & HOW]
Driver disable will deallocate framebuffer to reset IPS state, this will cause IPS start with
INIT state to blindly power gate ONO region to break power sequence. All the gating blocks
should be powered up when releasing hw to ensure all the power optimizations are identical to pre-OS.

Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Reviewed-by: Duncan Ma <duncan.ma@amd.com>
Signed-off-by: Yihan Zhu <Yihan.Zhu@amd.com>
Signed-off-by: Roman Li <roman.li@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/hwss/dcn35/dcn35_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h
drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c

index 8207fea4f99a96e2369e90b828d77c218fee705e..59fc1c114fbe292b9b88fa3c6af4484dbe43cba9 100644 (file)
@@ -1596,3 +1596,37 @@ bool dcn35_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx)
 
        return false;
 }
+
+/*
+ * Set powerup to true for every pipe to match pre-OS configuration.
+ */
+static void dcn35_calc_blocks_to_ungate_for_hw_release(struct dc *dc, struct pg_block_update *update_state)
+{
+       int i = 0, j = 0;
+
+       memset(update_state, 0, sizeof(struct pg_block_update));
+
+       for (i = 0; i < dc->res_pool->pipe_count; i++)
+               for (j = 0; j < PG_HW_PIPE_RESOURCES_NUM_ELEMENT; j++)
+                       update_state->pg_pipe_res_update[j][i] = true;
+
+       update_state->pg_res_update[PG_HPO] = true;
+       update_state->pg_res_update[PG_DWB] = true;
+}
+
+/*
+ * The purpose is to power up all gatings to restore optimization to pre-OS env.
+ * Re-use hwss func and existing PG&RCG flags to decide powerup sequence.
+ */
+void dcn35_hardware_release(struct dc *dc)
+{
+       struct pg_block_update pg_update_state;
+
+       dcn35_calc_blocks_to_ungate_for_hw_release(dc, &pg_update_state);
+
+       if (dc->hwss.root_clock_control)
+               dc->hwss.root_clock_control(dc, &pg_update_state, true);
+       /*power up required HW block*/
+       if (dc->hwss.hw_block_power_up)
+               dc->hwss.hw_block_power_up(dc, &pg_update_state);
+}
index e27b3609020ffd29f7461216e236446f90fab847..0b1d6f608edd7c421249aeaccad98c02e15e1de7 100644 (file)
@@ -99,4 +99,6 @@ void dcn35_set_long_vblank(struct pipe_ctx **pipe_ctx,
 
 bool dcn35_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx);
 
+void dcn35_hardware_release(struct dc *dc);
+
 #endif /* __DC_HWSS_DCN35_H__ */
index 5ca8db2b2d032054a55b81d0eb73612840a2170c..1e2cf8a391c8ee6746c571fea279d52a1cfd7548 100644 (file)
@@ -122,6 +122,7 @@ static const struct hw_sequencer_funcs dcn35_funcs = {
        .root_clock_control = dcn35_root_clock_control,
        .set_long_vtotal = dcn35_set_long_vblank,
        .calculate_pix_rate_divider = dcn32_calculate_pix_rate_divider,
+       .hardware_release = dcn35_hardware_release,
 };
 
 static const struct hwseq_private_funcs dcn35_private_funcs = {