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
