From: Bhuvanachandra Pinninti <[email protected]>

[why]
Bandwidth clock programming build and execution phases were coupled,
preventing the HWSS from orchestrating them through block sequencing.

[how]
Separate clock programming into build and execute phases across
latest versions. Build phase populates the clk_mgr internal block
sequence array, then registers a single CLK_MGR_UPDATE_CLOCKS HWSS step.
Execute phase dispatches the pre-built sequence. Add HWSS operations for
clk_mgr_set_max_memclk, hubbub_program_watermarks, hubbub_program_arbiter,
and hubbub_program_compbuf_segments.

Reviewed-by: Alvin Lee <[email protected]>
Signed-off-by: Bhuvanachandra Pinninti <[email protected]>
Signed-off-by: George Zhang <[email protected]>
---
 .../dc/clk_mgr/dcn401/dcn401_clk_mgr.c        |  57 ++++++-
 .../dc/clk_mgr/dcn401/dcn401_clk_mgr.h        |   9 +
 drivers/gpu/drm/amd/display/dc/core/dc.c      |   4 +-
 .../drm/amd/display/dc/core/dc_hw_sequencer.c | 154 ++++++++++++++++++
 .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c |  95 +++++++++++
 .../amd/display/dc/hwss/dcn401/dcn401_hwseq.h |  10 ++
 .../amd/display/dc/hwss/dcn401/dcn401_init.c  |   2 +
 .../drm/amd/display/dc/hwss/hw_sequencer.h    |  82 ++++++++++
 .../gpu/drm/amd/display/dc/inc/hw/clk_mgr.h   |   8 +
 9 files changed, 416 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c 
b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c
index 5f9398745a38..42ce5a304125 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c
@@ -10,6 +10,7 @@
 #include "dcn31/dcn31_clk_mgr.h"
 #include "dcn32/dcn32_clk_mgr.h"
 #include "dcn401/dcn401_clk_mgr.h"
+#include "hw_sequencer.h"
 #include "reg_helper.h"
 #include "core_types.h"
 #include "dm_helpers.h"
@@ -1085,7 +1086,8 @@ static unsigned int 
dcn401_build_update_display_clocks_sequence(
                struct clk_mgr *clk_mgr_base,
                struct dc_state *context,
                struct dc_clocks *new_clocks,
-               bool safe_to_lower)
+               bool safe_to_lower,
+               unsigned int num_steps_start)
 {
        struct clk_mgr_internal *clk_mgr_internal = 
TO_CLK_MGR_INTERNAL(clk_mgr_base);
        struct dcn401_clk_mgr *clk_mgr401 = TO_DCN401_CLK_MGR(clk_mgr_internal);
@@ -1100,7 +1102,7 @@ static unsigned int 
dcn401_build_update_display_clocks_sequence(
        bool frl_present = false;
        unsigned int i;
 
-       unsigned int num_steps = 0;
+       unsigned int num_steps = num_steps_start;
 
        /* CLK_MGR401_READ_CLOCKS_FROM_DENTIST */
        if (clk_mgr_base->clks.dispclk_khz == 0 ||
@@ -1239,6 +1241,44 @@ static unsigned int 
dcn401_build_update_display_clocks_sequence(
        return num_steps;
 }
 
+/*
+ * Build-for-BLS functions.
+ * These build both bandwidth and display clock sequences into the clk_mgr's
+ * internal block sequence array, then add a single CLK_MGR_UPDATE_CLOCKS step
+ * to the HWSS block sequence whose executor will call
+ * execute_clk_mgr_block_sequence to dispatch all accumulated steps.
+ */
+void dcn401_build_clock_update_for_bls(
+               struct clk_mgr *clk_mgr_base,
+               struct dc_state *context,
+               bool safe_to_lower,
+               struct block_sequence_state *seq_state)
+{
+       struct clk_mgr_internal *clk_mgr_internal = 
TO_CLK_MGR_INTERNAL(clk_mgr_base);
+       struct dcn401_clk_mgr *clk_mgr401 = TO_DCN401_CLK_MGR(clk_mgr_internal);
+       unsigned int num_bw_steps;
+       unsigned int total_steps;
+
+       /* Build bandwidth clocks sequence starting at index 0 */
+       num_bw_steps = 
dcn401_build_update_bandwidth_clocks_sequence(clk_mgr_base,
+                       context,
+                       &context->bw_ctx.bw.dcn.clk,
+                       safe_to_lower);
+
+       /* Build display clocks sequence appended after bandwidth steps */
+       total_steps = dcn401_build_update_display_clocks_sequence(clk_mgr_base,
+                       context,
+                       &context->bw_ctx.bw.dcn.clk,
+                       safe_to_lower,
+                       num_bw_steps);
+
+       /* Store total step count for the executor */
+       clk_mgr401->num_block_sequence_steps = total_steps;
+
+       /* Add single HWSS step that will execute all clk_mgr block sequence 
steps */
+       hwss_add_clk_mgr_update_clocks(seq_state, clk_mgr_base);
+}
+
 static void dcn401_update_clocks(struct clk_mgr *clk_mgr_base,
                struct dc_state *context,
                bool safe_to_lower)
@@ -1260,7 +1300,8 @@ static void dcn401_update_clocks(struct clk_mgr 
*clk_mgr_base,
        num_steps = dcn401_build_update_display_clocks_sequence(clk_mgr_base,
                        context,
                        &context->bw_ctx.bw.dcn.clk,
-                       safe_to_lower);
+                       safe_to_lower,
+                       0);
 
        /* execute sequence */
        dcn401_execute_block_sequence(clk_mgr_base,     num_steps);
@@ -1549,6 +1590,14 @@ unsigned int dcn401_get_max_clock_khz(struct clk_mgr 
*clk_mgr_base, enum clk_typ
        return 0;
 }
 
+static void dcn401_execute_clk_mgr_block_sequence_bls(struct clk_mgr 
*clk_mgr_base)
+{
+       struct clk_mgr_internal *clk_mgr_internal = 
TO_CLK_MGR_INTERNAL(clk_mgr_base);
+       struct dcn401_clk_mgr *clk_mgr401 = TO_DCN401_CLK_MGR(clk_mgr_internal);
+
+       dcn401_execute_block_sequence(clk_mgr_base, 
clk_mgr401->num_block_sequence_steps);
+}
+
 static struct clk_mgr_funcs dcn401_funcs = {
                .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
                .get_dtb_ref_clk_frequency = dcn401_get_dtb_ref_freq_khz,
@@ -1566,6 +1615,8 @@ static struct clk_mgr_funcs dcn401_funcs = {
                .get_hard_min_fclk = dcn401_get_hard_min_fclk,
                .is_dc_mode_present = dcn401_is_dc_mode_present,
                .get_max_clock_khz = dcn401_get_max_clock_khz,
+               .build_clock_update_for_bls = dcn401_build_clock_update_for_bls,
+               .execute_clk_mgr_block_sequence = 
dcn401_execute_clk_mgr_block_sequence_bls,
 };
 
 struct clk_mgr_internal *dcn401_clk_mgr_construct(
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.h 
b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.h
index 370d2ddd6064..d4cd69a5a8dd 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.h
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.h
@@ -102,6 +102,7 @@ struct dcn401_clk_mgr {
        struct clk_mgr_internal base;
 
        struct dcn401_clk_mgr_block_sequence 
block_sequence[DCN401_CLK_MGR_MAX_SEQUENCE_SIZE];
+       unsigned int num_block_sequence_steps;
 };
 
 void dcn401_init_clocks(struct clk_mgr *clk_mgr_base);
@@ -114,4 +115,12 @@ void dcn401_clk_mgr_destroy(struct clk_mgr_internal 
*clk_mgr);
 
 unsigned int dcn401_get_max_clock_khz(struct clk_mgr *clk_mgr_base, enum 
clk_type clk_type);
 
+struct block_sequence_state;
+
+void dcn401_build_clock_update_for_bls(
+               struct clk_mgr *clk_mgr_base,
+               struct dc_state *context,
+               bool safe_to_lower,
+               struct block_sequence_state *seq_state);
+
 #endif /* __DCN401_CLK_MGR_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c 
b/drivers/gpu/drm/amd/display/dc/core/dc.c
index ae776519e6ea..8922078d75d9 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -4257,8 +4257,8 @@ static void 
commit_planes_do_stream_update_sequence(struct dc *dc,
                                        
hwss_add_dc_set_optimized_required(&seq_state, dc, true);
 
                                } else {
-                                       if 
(get_seamless_boot_stream_count(context) == 0)
-                                               
hwss_add_prepare_bandwidth(&seq_state, dc, dc->current_state);
+                                       if 
(get_seamless_boot_stream_count(context) == 0 && 
dc->hwss.prepare_bandwidth_sequence)
+                                               
dc->hwss.prepare_bandwidth_sequence(dc, dc->current_state, &seq_state);
                                        hwss_add_link_set_dpms_on(&seq_state, 
dc->current_state, dpms_pipe_ctx);
                                }
                        } else if 
(pipe_ctx->stream->link->wa_flags.blank_stream_on_ocs_change && 
stream_update->output_color_space
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c 
b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
index c7c32c0a6b50..e47c8cf5d036 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
@@ -37,6 +37,7 @@
 #include "dchubbub.h"
 #include "dccg.h"
 #include "abm.h"
+#include "clk_mgr.h"
 #include "dcn10/dcn10_hubbub.h"
 #include "dce/dmub_hw_lock_mgr.h"
 #include "link_service.h"
@@ -1668,6 +1669,21 @@ void hwss_execute_sequence(struct dc *dc,
                case LINK_SET_DPMS_ON:
                        hwss_link_set_dpms_on(params);
                        break;
+               case CLK_MGR_SET_MAX_MEMCLK:
+                       hwss_clk_mgr_set_max_memclk(params);
+                       break;
+               case CLK_MGR_UPDATE_CLOCKS:
+                       hwss_clk_mgr_update_clocks(params);
+                       break;
+               case HUBBUB_PROGRAM_WATERMARKS:
+                       hwss_hubbub_program_watermarks(params);
+                       break;
+               case HUBBUB_PROGRAM_ARBITER:
+                       hwss_hubbub_program_arbiter(params);
+                       break;
+               case HUBBUB_PROGRAM_COMPBUF_SEGMENTS:
+                       hwss_hubbub_program_compbuf_segments(params);
+                       break;
                default:
                        ASSERT(false);
                        break;
@@ -3849,6 +3865,70 @@ void hwss_dsc_set_config_simple(union 
block_sequence_params *params)
                dsc->funcs->dsc_set_config(dsc, dsc_cfg, dsc_optc_cfg);
 }
 
+/*
+ * Clock manager executor functions
+ */
+void hwss_clk_mgr_set_max_memclk(union block_sequence_params *params)
+{
+       struct clk_mgr *clk_mgr = params->clk_mgr_set_max_memclk_params.clk_mgr;
+       unsigned int memclk_mhz = 
params->clk_mgr_set_max_memclk_params.memclk_mhz;
+
+       if (clk_mgr && clk_mgr->funcs && clk_mgr->funcs->set_max_memclk)
+               clk_mgr->funcs->set_max_memclk(clk_mgr, memclk_mhz);
+}
+
+void hwss_clk_mgr_update_clocks(union block_sequence_params *params)
+{
+       struct clk_mgr *clk_mgr = params->clk_mgr_update_clocks_params.clk_mgr;
+
+       if (clk_mgr && clk_mgr->funcs && 
clk_mgr->funcs->execute_clk_mgr_block_sequence)
+               clk_mgr->funcs->execute_clk_mgr_block_sequence(clk_mgr);
+}
+
+/*
+ * Hubbub executor functions
+ */
+void hwss_hubbub_program_watermarks(union block_sequence_params *params)
+{
+       struct dc *dc = params->hubbub_program_watermarks_params.dc;
+       struct hubbub *hubbub = params->hubbub_program_watermarks_params.hubbub;
+       union dcn_watermark_set *watermarks = 
params->hubbub_program_watermarks_params.watermarks;
+       unsigned int refclk_mhz = 
params->hubbub_program_watermarks_params.refclk_mhz;
+       bool safe_to_lower = 
params->hubbub_program_watermarks_params.safe_to_lower;
+
+       if (hubbub && hubbub->funcs && hubbub->funcs->program_watermarks) {
+               bool wm_changed = hubbub->funcs->program_watermarks(hubbub, 
watermarks, refclk_mhz, safe_to_lower);
+
+               if (dc && !safe_to_lower)
+                       dc->optimized_required |= wm_changed;
+       }
+}
+
+void hwss_hubbub_program_arbiter(union block_sequence_params *params)
+{
+       struct dc *dc = params->hubbub_program_arbiter_params.dc;
+       struct hubbub *hubbub = params->hubbub_program_arbiter_params.hubbub;
+       struct dml2_display_arb_regs *arb_regs = 
params->hubbub_program_arbiter_params.arb_regs;
+       bool safe_to_lower = 
params->hubbub_program_arbiter_params.safe_to_lower;
+
+       if (hubbub && hubbub->funcs && hubbub->funcs->program_arbiter) {
+               bool arb_changed = hubbub->funcs->program_arbiter(hubbub, 
arb_regs, safe_to_lower);
+
+               if (dc && !safe_to_lower)
+                       dc->optimized_required |= arb_changed;
+       }
+}
+
+void hwss_hubbub_program_compbuf_segments(union block_sequence_params *params)
+{
+       struct hubbub *hubbub = 
params->hubbub_program_compbuf_segments_params.hubbub;
+       unsigned int compbuf_size = 
params->hubbub_program_compbuf_segments_params.compbuf_size;
+       bool safe_to_lower = 
params->hubbub_program_compbuf_segments_params.safe_to_lower;
+
+       if (hubbub && hubbub->funcs && hubbub->funcs->program_compbuf_segments)
+               hubbub->funcs->program_compbuf_segments(hubbub, compbuf_size, 
safe_to_lower);
+}
+
 void hwss_add_dccg_set_dto_dscclk(struct block_sequence_state *seq_state,
                struct dccg *dccg, int inst, int num_slices_h)
 {
@@ -4909,6 +4989,9 @@ void 
hwss_add_hpo_dp_stream_enc_update_dp_info_packets_sdp_line_num(struct block
        }
 }
 
+/*
+ * Clock manager helper functions
+ */
 void hwss_add_hpo_dp_stream_enc_update_dp_info_packets(struct 
block_sequence_state *seq_state,
                struct pipe_ctx *pipe_ctx)
 {
@@ -4919,6 +5002,28 @@ void 
hwss_add_hpo_dp_stream_enc_update_dp_info_packets(struct block_sequence_sta
        }
 }
 
+void hwss_add_clk_mgr_set_max_memclk(struct block_sequence_state *seq_state,
+               struct clk_mgr *clk_mgr,
+               unsigned int memclk_mhz)
+{
+       if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+               seq_state->steps[*seq_state->num_steps].func = 
CLK_MGR_SET_MAX_MEMCLK;
+               
seq_state->steps[*seq_state->num_steps].params.clk_mgr_set_max_memclk_params.clk_mgr
 = clk_mgr;
+               
seq_state->steps[*seq_state->num_steps].params.clk_mgr_set_max_memclk_params.memclk_mhz
 = memclk_mhz;
+               (*seq_state->num_steps)++;
+       }
+}
+
+void hwss_add_clk_mgr_update_clocks(struct block_sequence_state *seq_state,
+               struct clk_mgr *clk_mgr)
+{
+       if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+               seq_state->steps[*seq_state->num_steps].func = 
CLK_MGR_UPDATE_CLOCKS;
+               
seq_state->steps[*seq_state->num_steps].params.clk_mgr_update_clocks_params.clk_mgr
 = clk_mgr;
+               (*seq_state->num_steps)++;
+       }
+}
+
 void hwss_add_stream_enc_update_dp_info_packets_sdp_line_num(struct 
block_sequence_state *seq_state,
                struct pipe_ctx *pipe_ctx)
 {
@@ -5022,6 +5127,26 @@ void hwss_add_setup_periodic_interrupt(struct 
block_sequence_state *seq_state,
                (*seq_state->num_steps)++;
        }
 }
+/*
+ * Hubbub helper functions
+ */
+void hwss_add_hubbub_program_watermarks(struct block_sequence_state *seq_state,
+               struct dc *dc,
+               struct hubbub *hubbub,
+               union dcn_watermark_set *watermarks,
+               unsigned int refclk_mhz,
+               bool safe_to_lower)
+{
+       if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+               seq_state->steps[*seq_state->num_steps].func = 
HUBBUB_PROGRAM_WATERMARKS;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_program_watermarks_params.dc
 = dc;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_program_watermarks_params.hubbub
 = hubbub;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_program_watermarks_params.watermarks
 = watermarks;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_program_watermarks_params.refclk_mhz
 = refclk_mhz;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_program_watermarks_params.safe_to_lower
 = safe_to_lower;
+               (*seq_state->num_steps)++;
+       }
+}
 
 void hwss_add_dp_trace_source_sequence(struct block_sequence_state *seq_state,
                struct dc_link *link,
@@ -5035,6 +5160,22 @@ void hwss_add_dp_trace_source_sequence(struct 
block_sequence_state *seq_state,
        }
 }
 
+void hwss_add_hubbub_program_arbiter(struct block_sequence_state *seq_state,
+               struct dc *dc,
+               struct hubbub *hubbub,
+               struct dml2_display_arb_regs *arb_regs,
+               bool safe_to_lower)
+{
+       if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+               seq_state->steps[*seq_state->num_steps].func = 
HUBBUB_PROGRAM_ARBITER;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_program_arbiter_params.dc 
= dc;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_program_arbiter_params.hubbub
 = hubbub;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_program_arbiter_params.arb_regs
 = arb_regs;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_program_arbiter_params.safe_to_lower
 = safe_to_lower;
+               (*seq_state->num_steps)++;
+       }
+}
+
 void hwss_add_set_dmdata_attributes(struct block_sequence_state *seq_state,
                struct pipe_ctx *pipe_ctx)
 {
@@ -5119,6 +5260,19 @@ void hwss_add_disable_audio_stream(struct 
block_sequence_state *seq_state,
                (*seq_state->num_steps)++;
        }
 }
+void hwss_add_hubbub_program_compbuf_segments(struct block_sequence_state 
*seq_state,
+               struct hubbub *hubbub,
+               unsigned int compbuf_size,
+               bool safe_to_lower)
+{
+       if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+               seq_state->steps[*seq_state->num_steps].func = 
HUBBUB_PROGRAM_COMPBUF_SEGMENTS;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_program_compbuf_segments_params.hubbub
 = hubbub;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_program_compbuf_segments_params.compbuf_size
 = compbuf_size;
+               
seq_state->steps[*seq_state->num_steps].params.hubbub_program_compbuf_segments_params.safe_to_lower
 = safe_to_lower;
+               (*seq_state->num_steps)++;
+       }
+}
 
 void hwss_add_prepare_bandwidth(struct block_sequence_state *seq_state,
                struct dc *dc,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
index b708881222e8..632f183fe755 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
@@ -1496,6 +1496,57 @@ void dcn401_prepare_bandwidth(struct dc *dc,
        }
 }
 
+void dcn401_prepare_bandwidth_sequence(struct dc *dc,
+               struct dc_state *context,
+               struct block_sequence_state *seq_state)
+{
+       struct hubbub *hubbub = dc->res_pool->hubbub;
+       bool p_state_change_support = 
context->bw_ctx.bw.dcn.clk.p_state_change_support;
+       unsigned int compbuf_size = 0;
+
+       /* Any transition into P-State support should disable MCLK switching 
first to avoid hangs */
+       if (p_state_change_support) {
+               dc->optimized_required = true;
+               context->bw_ctx.bw.dcn.clk.p_state_change_support = false;
+       }
+
+       if (dc->clk_mgr->dc_mode_softmax_enabled)
+               if (dc->clk_mgr->clks.dramclk_khz <= 
(int)dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000 &&
+                               context->bw_ctx.bw.dcn.clk.dramclk_khz > 
(int)dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000)
+                       hwss_add_clk_mgr_set_max_memclk(seq_state, dc->clk_mgr,
+                                       
dc->clk_mgr->bw_params->clk_table.entries[dc->clk_mgr->bw_params->clk_table.num_entries
 - 1].memclk_mhz);
+
+       /* Build bandwidth and display clocks back-to-back (SW calc + append 
BLS steps) */
+       if (dc->clk_mgr->funcs->build_clock_update_for_bls)
+               dc->clk_mgr->funcs->build_clock_update_for_bls(
+                               dc->clk_mgr, context, false, seq_state);
+
+       hwss_add_hubbub_program_watermarks(seq_state, dc, hubbub,
+                                       &context->bw_ctx.bw.dcn.watermarks,
+                                       
dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
+                                       false);
+
+       if (hubbub->funcs->program_arbiter)
+               hwss_add_hubbub_program_arbiter(seq_state, dc, hubbub,
+                               &context->bw_ctx.bw.dcn.arb_regs, false);
+
+       if (hubbub->funcs->program_compbuf_segments) {
+               compbuf_size = context->bw_ctx.bw.dcn.arb_regs.compbuf_size;
+               dc->optimized_required |= (compbuf_size != 
dc->current_state->bw_ctx.bw.dcn.arb_regs.compbuf_size);
+
+               hwss_add_hubbub_program_compbuf_segments(seq_state, hubbub, 
compbuf_size, false);
+       }
+
+       if (dc->debug.fams2_config.bits.enable) {
+               dcn401_dmub_hw_control_lock(dc, context, true);
+               dcn401_fams2_update_config(dc, context, false);
+               dcn401_dmub_hw_control_lock(dc, context, false);
+       }
+
+       if (p_state_change_support != 
context->bw_ctx.bw.dcn.clk.p_state_change_support)
+               context->bw_ctx.bw.dcn.clk.p_state_change_support = 
p_state_change_support;
+}
+
 void dcn401_optimize_bandwidth(
                struct dc *dc,
                struct dc_state *context)
@@ -1549,6 +1600,50 @@ void dcn401_optimize_bandwidth(
        }
 }
 
+/*
+ * optimize_bandwidth_sequence is unused for now. It will be used when
+ * dc_commit_state_no_check is moved into block sequence pattern, similar
+ * to how commit_planes_do_stream_update_sequence replaces
+ * commit_planes_do_stream_update.
+ */
+void dcn401_optimize_bandwidth_sequence(struct dc *dc,
+               struct dc_state *context,
+               struct block_sequence_state *seq_state)
+{
+       struct hubbub *hubbub = dc->res_pool->hubbub;
+
+       /* enable fams2 if needed */
+       if (dc->debug.fams2_config.bits.enable) {
+               dcn401_dmub_hw_control_lock(dc, context, true);
+               dcn401_fams2_update_config(dc, context, true);
+               dcn401_dmub_hw_control_lock(dc, context, false);
+       }
+
+       hwss_add_hubbub_program_watermarks(seq_state, dc, hubbub,
+                                       &context->bw_ctx.bw.dcn.watermarks,
+                                       
dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
+                                       true);
+
+       if (hubbub->funcs->program_arbiter)
+               hwss_add_hubbub_program_arbiter(seq_state, dc, hubbub,
+                               &context->bw_ctx.bw.dcn.arb_regs, true);
+
+       if (dc->clk_mgr->dc_mode_softmax_enabled)
+               if (dc->clk_mgr->clks.dramclk_khz > 
(int)dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000 &&
+                               context->bw_ctx.bw.dcn.clk.dramclk_khz <= 
(int)dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000)
+                       hwss_add_clk_mgr_set_max_memclk(seq_state, dc->clk_mgr,
+                                       
dc->clk_mgr->bw_params->dc_mode_softmax_memclk);
+
+       if (hubbub->funcs->program_compbuf_segments)
+               hwss_add_hubbub_program_compbuf_segments(seq_state, hubbub,
+                               context->bw_ctx.bw.dcn.arb_regs.compbuf_size, 
true);
+
+       /* Build bandwidth and display clocks (SW calc + append BLS steps) */
+       if (dc->clk_mgr->funcs->build_clock_update_for_bls)
+               dc->clk_mgr->funcs->build_clock_update_for_bls(
+                               dc->clk_mgr, context, true, seq_state);
+}
+
 void dcn401_dmub_hw_control_lock(struct dc *dc,
                struct dc_state *context,
                bool lock)
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h
index 2afeafc902c7..a760050eea8c 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h
@@ -70,10 +70,20 @@ void dcn401_wait_for_dcc_meta_propagation(const struct dc 
*dc,
 void dcn401_prepare_bandwidth(struct dc *dc,
                struct dc_state *context);
 
+struct block_sequence_state;
+
+void dcn401_prepare_bandwidth_sequence(struct dc *dc,
+               struct dc_state *context,
+               struct block_sequence_state *seq_state);
+
 void dcn401_optimize_bandwidth(
                struct dc *dc,
                struct dc_state *context);
 
+void dcn401_optimize_bandwidth_sequence(struct dc *dc,
+               struct dc_state *context,
+               struct block_sequence_state *seq_state);
+
 void dcn401_dmub_hw_control_lock(struct dc *dc,
                struct dc_state *context,
                bool lock);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
index 33b2cf344f1e..f206e221f926 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
@@ -44,7 +44,9 @@ static const struct hw_sequencer_funcs dcn401_funcs = {
        .interdependent_update_lock = dcn401_interdependent_update_lock,
        .cursor_lock = dcn10_cursor_lock,
        .prepare_bandwidth = dcn401_prepare_bandwidth,
+       .prepare_bandwidth_sequence = dcn401_prepare_bandwidth_sequence,
        .optimize_bandwidth = dcn401_optimize_bandwidth,
+       .optimize_bandwidth_sequence = dcn401_optimize_bandwidth_sequence,
        .update_bandwidth = dcn401_update_bandwidth,
        .set_drr = dcn10_set_drr,
        .get_position = dcn10_get_position,
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 dfb278a9fc3e..65df8002d3d7 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
@@ -894,6 +894,36 @@ struct disable_audio_stream_params {
        struct pipe_ctx *pipe_ctx;
 };
 
+struct clk_mgr_set_max_memclk_params {
+       struct clk_mgr *clk_mgr;
+       unsigned int memclk_mhz;
+};
+
+struct clk_mgr_update_clocks_params {
+       struct clk_mgr *clk_mgr;
+};
+
+struct hubbub_program_watermarks_params {
+       struct dc *dc;
+       struct hubbub *hubbub;
+       union dcn_watermark_set *watermarks;
+       unsigned int refclk_mhz;
+       bool safe_to_lower;
+};
+
+struct hubbub_program_arbiter_params {
+       struct dc *dc;
+       struct hubbub *hubbub;
+       struct dml2_display_arb_regs *arb_regs;
+       bool safe_to_lower;
+};
+
+struct hubbub_program_compbuf_segments_params {
+       struct hubbub *hubbub;
+       unsigned int compbuf_size;
+       bool safe_to_lower;
+};
+
 struct prepare_bandwidth_params {
        struct dc *dc;
        struct dc_state *context;
@@ -1057,6 +1087,11 @@ union block_sequence_params {
        struct disable_audio_stream_params disable_audio_stream_params;
        struct prepare_bandwidth_params prepare_bandwidth_params;
        struct link_set_dpms_on_params link_set_dpms_on_params;
+       struct clk_mgr_set_max_memclk_params clk_mgr_set_max_memclk_params;
+       struct clk_mgr_update_clocks_params clk_mgr_update_clocks_params;
+       struct hubbub_program_watermarks_params 
hubbub_program_watermarks_params;
+       struct hubbub_program_arbiter_params hubbub_program_arbiter_params;
+       struct hubbub_program_compbuf_segments_params 
hubbub_program_compbuf_segments_params;
 };
 
 enum block_sequence_func {
@@ -1209,6 +1244,11 @@ enum block_sequence_func {
        DISABLE_AUDIO_STREAM,
        PREPARE_BANDWIDTH,
        LINK_SET_DPMS_ON,
+       CLK_MGR_SET_MAX_MEMCLK,
+       CLK_MGR_UPDATE_CLOCKS,
+       HUBBUB_PROGRAM_WATERMARKS,
+       HUBBUB_PROGRAM_ARBITER,
+       HUBBUB_PROGRAM_COMPBUF_SEGMENTS,
        /* This must be the last value in this enum, add new ones above */
        HWSS_BLOCK_SEQUENCE_FUNC_COUNT
 };
@@ -1316,8 +1356,14 @@ struct hw_sequencer_funcs {
 
        /* Bandwidth Related */
        void (*prepare_bandwidth)(struct dc *dc, struct dc_state *context);
+       void (*prepare_bandwidth_sequence)(struct dc *dc,
+                       struct dc_state *context,
+                       struct block_sequence_state *seq_state);
        bool (*update_bandwidth)(struct dc *dc, struct dc_state *context);
        void (*optimize_bandwidth)(struct dc *dc, struct dc_state *context);
+       void (*optimize_bandwidth_sequence)(struct dc *dc,
+                       struct dc_state *context,
+                       struct block_sequence_state *seq_state);
 
        /* Infopacket Related */
        void (*set_avmute)(struct pipe_ctx *pipe_ctx, bool enable);
@@ -2475,4 +2521,40 @@ void hwss_add_link_set_dpms_on(struct 
block_sequence_state *seq_state,
                struct dc_state *state,
                struct pipe_ctx *pipe_ctx);
 
+/* Clock manager BLS executor functions */
+void hwss_clk_mgr_set_max_memclk(union block_sequence_params *params);
+void hwss_clk_mgr_update_clocks(union block_sequence_params *params);
+
+void hwss_hubbub_program_watermarks(union block_sequence_params *params);
+
+void hwss_hubbub_program_arbiter(union block_sequence_params *params);
+
+void hwss_hubbub_program_compbuf_segments(union block_sequence_params *params);
+
+/* Clock manager BLS add-helper functions */
+void hwss_add_clk_mgr_set_max_memclk(struct block_sequence_state *seq_state,
+               struct clk_mgr *clk_mgr,
+               unsigned int memclk_mhz);
+
+void hwss_add_clk_mgr_update_clocks(struct block_sequence_state *seq_state,
+               struct clk_mgr *clk_mgr);
+
+void hwss_add_hubbub_program_watermarks(struct block_sequence_state *seq_state,
+               struct dc *dc,
+               struct hubbub *hubbub,
+               union dcn_watermark_set *watermarks,
+               unsigned int refclk_mhz,
+               bool safe_to_lower);
+
+void hwss_add_hubbub_program_arbiter(struct block_sequence_state *seq_state,
+               struct dc *dc,
+               struct hubbub *hubbub,
+               struct dml2_display_arb_regs *arb_regs,
+               bool safe_to_lower);
+
+void hwss_add_hubbub_program_compbuf_segments(struct block_sequence_state 
*seq_state,
+               struct hubbub *hubbub,
+               unsigned int compbuf_size,
+               bool safe_to_lower);
+
 #endif /* __DC_HW_SEQUENCER_H__ */
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 69c4a49a40fc..68dc2d4ba7ca 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
@@ -320,6 +320,8 @@ struct clk_states {
        uint32_t dprefclk_khz;
 };
 
+struct block_sequence_state;
+
 struct clk_mgr_funcs {
        /*
         * This function should set new clocks based on the input 
"safe_to_lower".
@@ -409,6 +411,12 @@ struct clk_mgr_funcs {
        void (*get_requested_memory_qos)(
                        struct clk_mgr *clk_mgr,
                        struct dc_requested_memory_qos *qos);
+
+       void (*build_clock_update_for_bls)(struct clk_mgr *clk_mgr,
+                       struct dc_state *context, bool safe_to_lower,
+                       struct block_sequence_state *seq_state);
+
+       void (*execute_clk_mgr_block_sequence)(struct clk_mgr *clk_mgr);
 };
 
 struct clk_mgr {
-- 
2.53.0

Reply via email to