summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBhuvanachandra Pinninti <BhuvanaChandra.Pinninti@amd.com>2026-04-24 19:52:25 +0530
committerAlex Deucher <alexander.deucher@amd.com>2026-07-01 11:34:25 -0400
commitf3403ab74a29f244cecc7d64b2076ba0021fa737 (patch)
tree91742c8648ced0382c97074475b9e54e04a32b47
parentb34e4c1d05e772b7eb574ef2f383516bcdb12105 (diff)
downloadlinux-stable-f3403ab74a29f244cecc7d64b2076ba0021fa737.tar.gz
linux-stable-f3403ab74a29f244cecc7d64b2076ba0021fa737.zip
drm/amd/display: Add block sequence support for bandwidth programming operations
[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 <alvin.lee2@amd.com> Signed-off-by: Bhuvanachandra Pinninti <BhuvanaChandra.Pinninti@amd.com> Signed-off-by: George Zhang <george.zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c57
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.h9
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c154
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c95
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h10
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h82
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h8
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 4a60c5f54a04..6ee3da89d058 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 3aa95410006a..28339e4b6d67 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -4256,8 +4256,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 af83286c6114..0336d118e77e 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 {