From: <IVAN.LIPSKI@amd.com>
To: <amd-gfx@lists.freedesktop.org>
Cc: Harry Wentland <harry.wentland@amd.com>,
Leo Li <sunpeng.li@amd.com>,
Aurabindo Pillai <aurabindo.pillai@amd.com>,
Roman Li <roman.li@amd.com>, Wayne Lin <wayne.lin@amd.com>,
Tom Chung <chiahsuan.chung@amd.com>,
"Fangzhi Zuo" <jerry.zuo@amd.com>,
Dan Wheeler <daniel.wheeler@amd.com>, Ray Wu <Ray.Wu@amd.com>,
Ivan Lipski <ivan.lipski@amd.com>, Alex Hung <alex.hung@amd.com>,
James Lin <PingLei.Lin@amd.com>,
Chenyu Chen <Chen-Yu.Chen@amd.com>,
Tomasz Siemek <tomasz.siemek@amd.com>,
Alvin Lee <alvin.lee2@amd.com>
Subject: [PATCH 05/82] drm/amd/display: Split OPTC_PIPE_CONTROL_LOCK into smaller HWSS blocks
Date: Tue, 18 Aug 2026 16:14:57 -0400 [thread overview]
Message-ID: <20260818202139.4172592-6-IVAN.LIPSKI@amd.com> (raw)
In-Reply-To: <20260818202139.4172592-1-IVAN.LIPSKI@amd.com>
From: Tomasz Siemek <tomasz.siemek@amd.com>
[why]
Block level sequence operations should not use global state structs such
as pipe_ctx. OPTC_PIPE_CONTROL_LOCK is a BLS with complex logic
dispatching a lot of smaller hardware programming operations.
BLS should be a simple and atomic hardware operation without performing
mutations or having an access to global state. All operations on global
state should be moved to build step in HWSS.
[how]
- Split OPTC_PIPE_CONTROL_LOCK into substeps:
- HUBP_WAIT_FLIP_PENDING,
- TG_SET_GSL,
- TG_SET_GSL_SOURCE_SELECT,
- TG_LOCK,
- TG_3DLUT_WA_UNLOCK.
- Add hwss_pipe_control_lock - for in place build + execution.
- Remove timeout from HUBP_WAIT_FOR_FLIP_PENDING.
- Move software logic to builder. which fills pipe_control_lock_params
containing data for programming actual hwss blocks.
- Due to differences in what pipe control lock means bettween
asics following builder variants are added:
- dce_build_pipe_control_lock_sequence for asics pre DCN20,
- dcn20_build_pipe_control_lock_sequence.
- Rework gsl group programming to use builder / executor pattern.
Reviewed-by: Alvin Lee <alvin.lee2@amd.com>
Signed-off-by: Tomasz Siemek <tomasz.siemek@amd.com>
Signed-off-by: Ivan Lipski <ivan.lipski@amd.com>
---
drivers/gpu/drm/amd/display/dc/core/dc.c | 8 +-
.../drm/amd/display/dc/core/dc_hw_sequencer.c | 125 ++++++++++----
.../drm/amd/display/dc/hwss/dce/dce_hwseq.c | 46 ++++--
.../drm/amd/display/dc/hwss/dce/dce_hwseq.h | 12 +-
.../amd/display/dc/hwss/dce110/dce110_hwseq.c | 5 +-
.../amd/display/dc/hwss/dce60/dce60_hwseq.c | 5 +-
.../amd/display/dc/hwss/dce80/dce80_hwseq.c | 3 +-
.../amd/display/dc/hwss/dcn10/dcn10_hwseq.c | 31 ++--
.../amd/display/dc/hwss/dcn10/dcn10_hwseq.h | 5 +-
.../amd/display/dc/hwss/dcn10/dcn10_init.c | 4 +-
.../amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 153 +++++++++++-------
.../amd/display/dc/hwss/dcn20/dcn20_hwseq.h | 14 +-
.../amd/display/dc/hwss/dcn20/dcn20_init.c | 3 +-
.../amd/display/dc/hwss/dcn201/dcn201_hwseq.c | 34 ++--
.../amd/display/dc/hwss/dcn201/dcn201_hwseq.h | 5 +-
.../amd/display/dc/hwss/dcn201/dcn201_init.c | 4 +-
.../amd/display/dc/hwss/dcn21/dcn21_init.c | 3 +-
.../amd/display/dc/hwss/dcn30/dcn30_init.c | 3 +-
.../amd/display/dc/hwss/dcn301/dcn301_init.c | 3 +-
.../amd/display/dc/hwss/dcn31/dcn31_init.c | 3 +-
.../amd/display/dc/hwss/dcn314/dcn314_init.c | 3 +-
.../amd/display/dc/hwss/dcn32/dcn32_hwseq.c | 4 +-
.../amd/display/dc/hwss/dcn32/dcn32_init.c | 3 +-
.../amd/display/dc/hwss/dcn35/dcn35_init.c | 3 +-
.../amd/display/dc/hwss/dcn351/dcn351_init.c | 3 +-
.../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 140 ++++------------
.../amd/display/dc/hwss/dcn401/dcn401_hwseq.h | 3 +-
.../amd/display/dc/hwss/dcn401/dcn401_init.c | 3 +-
.../amd/display/dc/hwss/dcn42/dcn42_init.c | 3 +-
.../amd/display/dc/hwss/dcn60/dcn60_init.c | 3 +-
.../drm/amd/display/dc/hwss/hw_sequencer.h | 43 +++--
.../display/dc/hwss/hw_sequencer_private.h | 3 +-
32 files changed, 367 insertions(+), 316 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 6f7b715d4717e..3c6936943960d 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -1221,7 +1221,7 @@ static void apply_ctx_interdependent_lock(struct dc *dc,
if (stream == pipe_ctx->stream) {
if (resource_is_pipe_type(pipe_ctx, OPP_HEAD) &&
(pipe_ctx->plane_state || old_pipe_ctx->plane_state))
- dc->hwss.pipe_control_lock(dc, pipe_ctx, lock);
+ hwss_pipe_control_lock(dc, pipe_ctx, lock);
}
}
}
@@ -4991,7 +4991,7 @@ static void commit_planes_for_stream(struct dc *dc,
* plane addr update event triggers to be synchronized.
* top_pipe_to_program is expected to never be NULL
*/
- dc->hwss.pipe_control_lock(dc, top_pipe_to_program, true);
+ hwss_pipe_control_lock(dc, top_pipe_to_program, true);
}
dc_dmub_update_dirty_rect(dc, surface_count, stream, srf_updates, context);
@@ -5013,7 +5013,7 @@ static void commit_planes_for_stream(struct dc *dc,
if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) {
dc->hwss.interdependent_update_lock(dc, context, false);
} else {
- dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false);
+ hwss_pipe_control_lock(dc, top_pipe_to_program, false);
}
dc->hwss.post_unlock_program_front_end(dc, context);
@@ -5200,7 +5200,7 @@ static void commit_planes_for_stream(struct dc *dc,
if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) {
dc->hwss.interdependent_update_lock(dc, context, false);
} else {
- dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false);
+ hwss_pipe_control_lock(dc, top_pipe_to_program, false);
}
if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed)
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 d61c4d9488c59..8b723c3ca933d 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
@@ -1051,7 +1051,7 @@ void hwss_build_post_unlock_full_sequence(struct dc *dc,
unsigned int polling_interval_us;
polling_interval_us = 1;
- hwss_add_hubp_wait_flip_pending(&seq_state, pipe->plane_res.hubp, 100000, polling_interval_us);
+ hwss_add_hubp_wait_flip_pending(&seq_state, pipe->plane_res.hubp, polling_interval_us);
}
}
@@ -1212,13 +1212,9 @@ void hwss_build_fast_sequence(struct dc *dc,
block_sequence[*num_steps].func = DMUB_HW_CONTROL_LOCK_FAST;
(*num_steps)++;
}
- if (dc->hwss.pipe_control_lock) {
- block_sequence[*num_steps].params.pipe_control_lock_params.dc = dc;
- block_sequence[*num_steps].params.pipe_control_lock_params.lock = true;
- block_sequence[*num_steps].params.pipe_control_lock_params.pipe_ctx = pipe_ctx;
- block_sequence[*num_steps].func = OPTC_PIPE_CONTROL_LOCK;
- (*num_steps)++;
- }
+ hwss_add_optc_pipe_control_lock(
+ &(struct block_sequence_state){ block_sequence, num_steps },
+ dc, pipe_ctx, true);
for (i = 0; i < dmub_cmd_count; i++) {
block_sequence[*num_steps].params.send_dmcub_cmd_params.ctx = dc->ctx;
@@ -1646,13 +1642,9 @@ void hwss_build_fast_sequence(struct dc *dc,
current_pipe = current_pipe->next_odm_pipe;
}
- if (dc->hwss.pipe_control_lock) {
- block_sequence[*num_steps].params.pipe_control_lock_params.dc = dc;
- block_sequence[*num_steps].params.pipe_control_lock_params.lock = false;
- block_sequence[*num_steps].params.pipe_control_lock_params.pipe_ctx = pipe_ctx;
- block_sequence[*num_steps].func = OPTC_PIPE_CONTROL_LOCK;
- (*num_steps)++;
- }
+ hwss_add_optc_pipe_control_lock(
+ &(struct block_sequence_state){ block_sequence, num_steps },
+ dc, pipe_ctx, false);
if (dc->hwss.subvp_pipe_control_lock_fast) {
block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.dc = dc;
block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.lock = false;
@@ -1710,10 +1702,14 @@ void hwss_execute_sequence(struct dc *dc,
case DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST:
dc->hwss.subvp_pipe_control_lock_fast(params);
break;
- case OPTC_PIPE_CONTROL_LOCK:
- dc->hwss.pipe_control_lock(params->pipe_control_lock_params.dc,
- params->pipe_control_lock_params.pipe_ctx,
- params->pipe_control_lock_params.lock);
+ case TG_LOCK:
+ dc->hwss.tg_lock(¶ms->tg_lock_params);
+ break;
+ case TG_3DLUT_WA_UNLOCK:
+ if (dc->hwseq->funcs.perform_3dlut_wa_unlock)
+ dc->hwseq->funcs.perform_3dlut_wa_unlock(
+ params->tg_3dlut_wa_unlock_params.tg,
+ params->tg_3dlut_wa_unlock_params.hubp);
break;
case HUBP_SET_FLIP_CONTROL_GSL:
params->set_flip_control_gsl_params.hubp->funcs->hubp_set_flip_control_surface_gsl(
@@ -1925,7 +1921,8 @@ void hwss_execute_sequence(struct dc *dc,
hwss_tg_set_gsl_source_select(params);
break;
case HUBP_WAIT_FLIP_PENDING:
- hwss_hubp_wait_flip_pending(params);
+ hwss_hubp_wait_flip_pending(params->hubp_wait_flip_pending_params.hubp,
+ params->hubp_wait_flip_pending_params.polling_interval_us);
break;
case TG_WAIT_DOUBLE_BUFFER_PENDING:
hwss_tg_wait_double_buffer_pending(params);
@@ -2234,23 +2231,85 @@ void hwss_execute_sequence(struct dc *dc,
}
}
-/*
- * Helper function to add OPTC pipe control lock to block sequence
- */
void hwss_add_optc_pipe_control_lock(struct block_sequence_state *seq_state,
struct dc *dc,
struct pipe_ctx *pipe_ctx,
bool lock)
{
- if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
- seq_state->steps[*seq_state->num_steps].params.pipe_control_lock_params.dc = dc;
- seq_state->steps[*seq_state->num_steps].params.pipe_control_lock_params.pipe_ctx = pipe_ctx;
- seq_state->steps[*seq_state->num_steps].params.pipe_control_lock_params.lock = lock;
- seq_state->steps[*seq_state->num_steps].func = OPTC_PIPE_CONTROL_LOCK;
- (*seq_state->num_steps)++;
+ struct pipe_control_lock_params params = { 0 };
+ unsigned int hubp_idx;
+ unsigned int polling_interval_us = 1;
+
+ if (!dc->hwss.build_pipe_control_lock_sequence ||
+ !dc->hwss.build_pipe_control_lock_sequence(dc, pipe_ctx, lock, ¶ms))
+ return;
+
+ for (hubp_idx = 0; hubp_idx < MAX_PIPES; hubp_idx++)
+ if (params.hubps_to_wait_for_flip[hubp_idx])
+ hwss_add_hubp_wait_flip_pending(seq_state, params.hubps_to_wait_for_flip[hubp_idx],
+ polling_interval_us);
+
+ if (params.gsl_lock) {
+ hwss_add_tg_set_gsl(seq_state, params.gsl.tg, params.gsl.gsl);
+ hwss_add_tg_set_gsl_source_select(seq_state, params.gsl_source_select.tg,
+ params.gsl_source_select.group_idx, params.gsl_source_select.gsl_ready_signal);
+ }
+
+ if (params.tg_3dlut_wa_unlock) {
+ if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+ seq_state->steps[*seq_state->num_steps].params.tg_3dlut_wa_unlock_params =
+ params.tg_3dlut_wa_unlock_params;
+ seq_state->steps[*seq_state->num_steps].func = TG_3DLUT_WA_UNLOCK;
+ (*seq_state->num_steps)++;
+ }
+ } else {
+ if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+ seq_state->steps[*seq_state->num_steps].params.tg_lock_params = params.tg_lock;
+ seq_state->steps[*seq_state->num_steps].func = TG_LOCK;
+ (*seq_state->num_steps)++;
+ }
}
}
+void hwss_pipe_control_lock(struct dc *dc,
+ struct pipe_ctx *pipe_ctx,
+ bool lock)
+{
+ struct pipe_control_lock_params params = { 0 };
+ unsigned int hubp_idx;
+ unsigned int polling_interval_us = 1;
+
+ if (!dc->hwss.build_pipe_control_lock_sequence ||
+ !dc->hwss.build_pipe_control_lock_sequence(dc, pipe_ctx, lock, ¶ms))
+ return;
+
+ for (hubp_idx = 0; hubp_idx < MAX_PIPES; hubp_idx++)
+ if (params.hubps_to_wait_for_flip[hubp_idx])
+ hwss_hubp_wait_flip_pending(
+ params.hubps_to_wait_for_flip[hubp_idx],
+ polling_interval_us);
+
+ if (params.gsl_lock) {
+ if (params.gsl.tg->funcs->set_gsl)
+ params.gsl.tg->funcs->set_gsl(params.gsl.tg, ¶ms.gsl.gsl);
+ if (params.gsl_source_select.tg->funcs->set_gsl_source_select)
+ params.gsl_source_select.tg->funcs->set_gsl_source_select(
+ params.gsl_source_select.tg,
+ params.gsl_source_select.group_idx,
+ params.gsl_source_select.gsl_ready_signal);
+ }
+
+ if (params.tg_3dlut_wa_unlock) {
+ dc->hwseq->funcs.perform_3dlut_wa_unlock(
+ params.tg_3dlut_wa_unlock_params.tg,
+ params.tg_3dlut_wa_unlock_params.hubp);
+ return;
+ }
+
+ if (dc->hwss.tg_lock)
+ dc->hwss.tg_lock(¶ms.tg_lock);
+}
+
/*
* Helper function to add HUBP set flip control GSL to block sequence
*/
@@ -2853,12 +2912,10 @@ void hwss_add_tg_enable_crtc(struct block_sequence_state *seq_state,
*/
void hwss_add_hubp_wait_flip_pending(struct block_sequence_state *seq_state,
struct hubp *hubp,
- unsigned int timeout_us,
unsigned int polling_interval_us)
{
if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
seq_state->steps[*seq_state->num_steps].params.hubp_wait_flip_pending_params.hubp = hubp;
- seq_state->steps[*seq_state->num_steps].params.hubp_wait_flip_pending_params.timeout_us = timeout_us;
seq_state->steps[*seq_state->num_steps].params.hubp_wait_flip_pending_params.polling_interval_us = polling_interval_us;
seq_state->steps[*seq_state->num_steps].func = HUBP_WAIT_FLIP_PENDING;
(*seq_state->num_steps)++;
@@ -3611,11 +3668,9 @@ void hwss_tg_set_gsl_source_select(union block_sequence_params *params)
tg->funcs->set_gsl_source_select(tg, group_idx, gsl_ready_signal);
}
-void hwss_hubp_wait_flip_pending(union block_sequence_params *params)
+void hwss_hubp_wait_flip_pending(struct hubp *hubp, unsigned int polling_interval_us)
{
- struct hubp *hubp = params->hubp_wait_flip_pending_params.hubp;
- unsigned int timeout_us = params->hubp_wait_flip_pending_params.timeout_us;
- unsigned int polling_interval_us = params->hubp_wait_flip_pending_params.polling_interval_us;
+ const unsigned int timeout_us = 100000U;
unsigned int j = 0;
for (j = 0; j < timeout_us / polling_interval_us
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.c
index 4202fadb2c0e9..0f44577572fbe 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.c
@@ -44,20 +44,36 @@ void dce_enable_fe_clock(struct dce_hwseq *hws,
DCFE_CLOCK_ENABLE, enable);
}
-void dce_pipe_control_lock(struct dc *dc,
+bool dce_build_pipe_control_lock_sequence(struct dc *dc,
struct pipe_ctx *pipe,
- bool lock)
+ bool lock,
+ struct pipe_control_lock_params *params)
{
- uint32_t lock_val = lock ? 1 : 0;
+ if (!pipe || pipe->top_pipe)
+ return false;
+
+ params->lock = lock;
+ params->tg_lock.dc = dc;
+ params->tg_lock.tg = pipe->stream_res.tg;
+ params->tg_lock.lock = lock;
+ params->tg_lock.triplebuffer_flips = pipe->plane_state &&
+ pipe->plane_state->triplebuffer_flips;
+ return true;
+}
+
+void dce_tg_lock(struct tg_lock_params *params)
+{
+ uint32_t lock_val = params->lock ? 1 : 0;
uint32_t dcp_grph, scl, blnd, update_lock_mode, val;
- struct dce_hwseq *hws = dc->hwseq;
+ struct dce_hwseq *hws = params->dc->hwseq;
+ unsigned int tg_inst = params->tg->inst;
/* Not lock pipe when blank */
- if (lock && pipe->stream_res.tg->funcs->is_blanked &&
- pipe->stream_res.tg->funcs->is_blanked(pipe->stream_res.tg))
+ if (params->lock && params->tg->funcs->is_blanked &&
+ params->tg->funcs->is_blanked(params->tg))
return;
- val = REG_GET_4(BLND_V_UPDATE_LOCK[pipe->stream_res.tg->inst],
+ val = REG_GET_4(BLND_V_UPDATE_LOCK[tg_inst],
BLND_DCP_GRPH_V_UPDATE_LOCK, &dcp_grph,
BLND_SCL_V_UPDATE_LOCK, &scl,
BLND_BLND_V_UPDATE_LOCK, &blnd,
@@ -68,28 +84,28 @@ void dce_pipe_control_lock(struct dc *dc,
blnd = lock_val;
update_lock_mode = lock_val;
- REG_SET_2(BLND_V_UPDATE_LOCK[pipe->stream_res.tg->inst], val,
+ REG_SET_2(BLND_V_UPDATE_LOCK[tg_inst], val,
BLND_DCP_GRPH_V_UPDATE_LOCK, dcp_grph,
BLND_SCL_V_UPDATE_LOCK, scl);
if (hws->masks->BLND_BLND_V_UPDATE_LOCK != 0)
- REG_SET_2(BLND_V_UPDATE_LOCK[pipe->stream_res.tg->inst], val,
+ REG_SET_2(BLND_V_UPDATE_LOCK[tg_inst], val,
BLND_BLND_V_UPDATE_LOCK, blnd,
BLND_V_UPDATE_LOCK_MODE, update_lock_mode);
if (hws->wa.blnd_crtc_trigger) {
- if (!lock) {
- uint32_t value = REG_READ(CRTC_H_BLANK_START_END[pipe->stream_res.tg->inst]);
- REG_WRITE(CRTC_H_BLANK_START_END[pipe->stream_res.tg->inst], value);
+ if (!params->lock) {
+ uint32_t value = REG_READ(CRTC_H_BLANK_START_END[tg_inst]);
+
+ REG_WRITE(CRTC_H_BLANK_START_END[tg_inst], value);
}
}
}
#if defined(CONFIG_DRM_AMD_DC_SI)
-void dce60_pipe_control_lock(struct dc *dc,
- struct pipe_ctx *pipe,
- bool lock)
+void dce60_tg_lock(struct tg_lock_params *params)
{
+ (void)params;
/* DCE6 has no BLND_V_UPDATE_LOCK register */
}
#endif
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h
index 2cc4e7516a5d7..0b9b418626110 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h
@@ -26,6 +26,7 @@
#define __DCE_HWSEQ_H__
#include "dc_types.h"
+#include "hw_sequencer_private.h"
#define HWSEQ_DCEF_REG_LIST_DCE8() \
.DCFE_CLOCK_CONTROL[0] = mmCRTC0_CRTC_DCFE_CLOCK_CONTROL, \
@@ -1299,17 +1300,16 @@ struct clock_source;
void dce_enable_fe_clock(struct dce_hwseq *hwss,
unsigned int inst, bool enable);
-void dce_pipe_control_lock(struct dc *dc,
- struct pipe_ctx *pipe,
- bool lock);
+bool dce_build_pipe_control_lock_sequence(struct dc *dc,
+ struct pipe_ctx *pipe, bool lock,
+ struct pipe_control_lock_params *params);
+void dce_tg_lock(struct tg_lock_params *params);
void dce_set_blender_mode(struct dce_hwseq *hws,
unsigned int blnd_inst, enum blnd_mode mode);
#if defined(CONFIG_DRM_AMD_DC_SI)
-void dce60_pipe_control_lock(struct dc *dc,
- struct pipe_ctx *pipe,
- bool lock);
+void dce60_tg_lock(struct tg_lock_params *params);
#endif
void dce_clock_gating_power_up(struct dce_hwseq *hws,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
index ef91c61033a33..bb46d72490259 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
@@ -3640,9 +3640,10 @@ static const struct hw_sequencer_funcs dce110_funcs = {
.enable_audio_stream = dce110_enable_audio_stream,
.disable_audio_stream = dce110_disable_audio_stream,
.disable_plane = dce110_power_down_fe,
- .pipe_control_lock = dce_pipe_control_lock,
+ .build_pipe_control_lock_sequence = dce_build_pipe_control_lock_sequence,
+ .tg_lock = dce_tg_lock,
.interdependent_update_lock = NULL,
- .cursor_lock = dce_pipe_control_lock,
+ .cursor_lock = hwss_pipe_control_lock,
.prepare_bandwidth = dce110_prepare_bandwidth,
.optimize_bandwidth = dce110_optimize_bandwidth,
.set_drr = set_drr,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce60/dce60_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce60/dce60_hwseq.c
index 1652e47716a0a..b73a10b0acbd7 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dce60/dce60_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dce60/dce60_hwseq.c
@@ -423,8 +423,9 @@ void dce60_hw_sequencer_construct(struct dc *dc)
dc->hwseq->funcs.enable_display_power_gating = dce100_enable_display_power_gating;
dc->hwss.apply_ctx_for_surface = dce60_apply_ctx_for_surface;
- dc->hwss.cursor_lock = dce60_pipe_control_lock;
- dc->hwss.pipe_control_lock = dce60_pipe_control_lock;
+ dc->hwss.cursor_lock = hwss_pipe_control_lock;
+ dc->hwss.build_pipe_control_lock_sequence = dce_build_pipe_control_lock_sequence;
+ dc->hwss.tg_lock = dce60_tg_lock;
dc->hwss.prepare_bandwidth = dce100_prepare_bandwidth;
dc->hwss.optimize_bandwidth = dce100_optimize_bandwidth;
dc->hwss.clear_surface_dcc_and_tiling = dce100_reset_surface_dcc_and_tiling;
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce80/dce80_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce80/dce80_hwseq.c
index 76fd45550c5e7..f44f41b13007d 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dce80/dce80_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dce80/dce80_hwseq.c
@@ -47,7 +47,8 @@ void dce80_hw_sequencer_construct(struct dc *dc)
dce110_hw_sequencer_construct(dc);
dc->hwseq->funcs.enable_display_power_gating = dce100_enable_display_power_gating;
- dc->hwss.pipe_control_lock = dce_pipe_control_lock;
+ dc->hwss.build_pipe_control_lock_sequence = dce_build_pipe_control_lock_sequence;
+ dc->hwss.tg_lock = dce_tg_lock;
dc->hwss.prepare_bandwidth = dce100_prepare_bandwidth;
dc->hwss.optimize_bandwidth = dce100_optimize_bandwidth;
dc->hwss.clear_surface_dcc_and_tiling = dce100_reset_surface_dcc_and_tiling;
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
index d76fc6ef38c4e..b1679791f903f 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
@@ -246,9 +246,9 @@ void dcn10_lock_all_pipes(struct dc *dc,
continue;
if (lock)
- dc->hwss.pipe_control_lock(dc, pipe_ctx, true);
+ hwss_pipe_control_lock(dc, pipe_ctx, true);
else
- dc->hwss.pipe_control_lock(dc, pipe_ctx, false);
+ hwss_pipe_control_lock(dc, pipe_ctx, false);
}
}
@@ -2202,29 +2202,20 @@ bool dcn10_set_output_transfer_func(struct set_output_transfer_func_params *para
return true;
}
-void dcn10_pipe_control_lock(
- struct dc *dc,
- struct pipe_ctx *pipe,
- bool lock)
+void dcn10_tg_lock(struct tg_lock_params *params)
{
- struct dce_hwseq *hws = dc->hwseq;
-
- /* use TG master update lock to lock everything on the TG
- * therefore only top pipe need to lock
- */
- if (!pipe || pipe->top_pipe)
- return;
+ struct dce_hwseq *hws = params->dc->hwseq;
- if (dc->debug.sanity_checks)
- hws->funcs.verify_allow_pstate_change_high(dc);
+ if (params->dc->debug.sanity_checks)
+ hws->funcs.verify_allow_pstate_change_high(params->dc);
- if (lock)
- pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg);
+ if (params->lock)
+ params->tg->funcs->lock(params->tg);
else
- pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg);
+ params->tg->funcs->unlock(params->tg);
- if (dc->debug.sanity_checks)
- hws->funcs.verify_allow_pstate_change_high(dc);
+ if (params->dc->debug.sanity_checks)
+ hws->funcs.verify_allow_pstate_change_high(params->dc);
}
/**
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.h
index 1f36bd58beb24..30c213f2e8d6c 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.h
@@ -57,10 +57,7 @@ void dcn10_wait_for_pipe_update_if_needed(
void dcn10_set_wait_for_update_needed_for_pipe(
struct dc *dc,
struct pipe_ctx *pipe_ctx);
-void dcn10_pipe_control_lock(
- struct dc *dc,
- struct pipe_ctx *pipe,
- bool lock);
+void dcn10_tg_lock(struct tg_lock_params *params);
void dcn10_cursor_lock(struct dc *dc, struct pipe_ctx *pipe, bool lock);
void dcn10_blank_pixel_data(
struct dc *dc,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_init.c
index b5e82e1901247..47ab50a3fab1c 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_init.c
@@ -27,6 +27,7 @@
#include "dce110/dce110_hwseq.h"
#include "dcn10/dcn10_hwseq.h"
#include "dcn20/dcn20_hwseq.h"
+#include "dc/hwss/dce/dce_hwseq.h"
static const struct hw_sequencer_funcs dcn10_funcs = {
.program_gamut_remap = dcn10_program_gamut_remap,
@@ -54,7 +55,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = {
.enable_audio_stream = dce110_enable_audio_stream,
.disable_audio_stream = dce110_disable_audio_stream,
.disable_plane = dcn10_disable_plane,
- .pipe_control_lock = dcn10_pipe_control_lock,
+ .build_pipe_control_lock_sequence = dce_build_pipe_control_lock_sequence,
+ .tg_lock = dcn10_tg_lock,
.cursor_lock = dcn10_cursor_lock,
.interdependent_update_lock = dcn10_lock_all_pipes,
.prepare_bandwidth = dcn10_prepare_bandwidth,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
index 23e191d472991..38d587af9dd82 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
@@ -217,15 +217,18 @@ static int find_free_gsl_group(const struct dc *dc)
* gsl_0 <=> pipe_ctx->stream_res.gsl_group == 1
* Using a magic value like -1 would require tracking all inits/resets
*/
-void dcn20_setup_gsl_group_as_lock(
+void dcn20_build_gsl_group_as_lock(
const struct dc *dc,
struct pipe_ctx *pipe_ctx,
- bool enable)
+ bool enable,
+ struct tg_set_gsl_params *gsl_params,
+ struct tg_set_gsl_source_select_params *gsl_source_select_params)
{
- struct gsl_params gsl;
int group_idx;
- memset(&gsl, 0, sizeof(struct gsl_params));
+ memset(&gsl_params->gsl, 0, sizeof(gsl_params->gsl));
+ gsl_params->tg = pipe_ctx->stream_res.tg;
+ gsl_source_select_params->tg = pipe_ctx->stream_res.tg;
if (enable) {
/* return if group already assigned since GSL was set up
@@ -241,22 +244,22 @@ void dcn20_setup_gsl_group_as_lock(
/* set gsl group reg field and mark resource used */
switch (group_idx) {
case 1:
- gsl.gsl0_en = 1;
+ gsl_params->gsl.gsl0_en = 1;
dc->res_pool->gsl_groups.gsl_0 = 1;
break;
case 2:
- gsl.gsl1_en = 1;
+ gsl_params->gsl.gsl1_en = 1;
dc->res_pool->gsl_groups.gsl_1 = 1;
break;
case 3:
- gsl.gsl2_en = 1;
+ gsl_params->gsl.gsl2_en = 1;
dc->res_pool->gsl_groups.gsl_2 = 1;
break;
default:
BREAK_TO_DEBUGGER();
return; // invalid case
}
- gsl.gsl_master_en = 1;
+ gsl_params->gsl.gsl_master_en = 1;
} else {
group_idx = pipe_ctx->stream_res.gsl_group;
if (group_idx == 0)
@@ -267,32 +270,46 @@ void dcn20_setup_gsl_group_as_lock(
/* unset gsl group reg field and mark resource free */
switch (group_idx) {
case 1:
- gsl.gsl0_en = 0;
dc->res_pool->gsl_groups.gsl_0 = 0;
break;
case 2:
- gsl.gsl1_en = 0;
dc->res_pool->gsl_groups.gsl_1 = 0;
break;
case 3:
- gsl.gsl2_en = 0;
dc->res_pool->gsl_groups.gsl_2 = 0;
break;
default:
BREAK_TO_DEBUGGER();
return;
}
- gsl.gsl_master_en = 0;
}
+ gsl_source_select_params->group_idx = group_idx;
+ gsl_source_select_params->gsl_ready_signal = enable ? 4 : 0;
+}
+
+void dcn20_setup_gsl_group_as_lock(
+ const struct dc *dc,
+ struct pipe_ctx *pipe_ctx,
+ bool enable)
+{
+ struct tg_set_gsl_params gsl_params = { 0 };
+ struct tg_set_gsl_source_select_params gsl_source_select_params = { 0 };
+
+ dcn20_build_gsl_group_as_lock(dc, pipe_ctx, enable,
+ &gsl_params, &gsl_source_select_params);
+ if (!gsl_source_select_params.group_idx)
+ return;
+
/* at this point we want to program whether it's to enable or disable */
if (pipe_ctx->stream_res.tg->funcs->set_gsl != NULL) {
pipe_ctx->stream_res.tg->funcs->set_gsl(
pipe_ctx->stream_res.tg,
- &gsl);
+ &gsl_params.gsl);
if (pipe_ctx->stream_res.tg->funcs->set_gsl_source_select != NULL)
pipe_ctx->stream_res.tg->funcs->set_gsl_source_select(
- pipe_ctx->stream_res.tg, group_idx, enable ? 4 : 0);
+ pipe_ctx->stream_res.tg, gsl_source_select_params.group_idx,
+ gsl_source_select_params.gsl_ready_signal);
} else
BREAK_TO_DEBUGGER();
}
@@ -1386,19 +1403,30 @@ void dcn20_enable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx,
// }
}
-void dcn20_pipe_control_lock(
- struct dc *dc,
- struct pipe_ctx *pipe,
- bool lock)
+bool dcn20_build_pipe_control_lock_sequence(
+ struct dc *dc,
+ struct pipe_ctx *pipe,
+ bool lock,
+ struct pipe_control_lock_params *params)
{
struct pipe_ctx *temp_pipe;
bool flip_immediate = false;
+ unsigned int hubp_count = 0;
/* use TG master update lock to lock everything on the TG
* therefore only top pipe need to lock
*/
if (!pipe || pipe->top_pipe)
- return;
+ return false;
+
+ params->lock = lock;
+ params->tg_lock.dc = dc;
+ params->tg_lock.lock = lock;
+ params->tg_lock.tg = pipe->stream_res.tg;
+ params->tg_lock.use_dmub_inbox1 = pipe->stream &&
+ should_use_dmub_inbox1_lock(dc, pipe->stream->link);
+ params->tg_lock.triplebuffer_flips = pipe->plane_state &&
+ pipe->plane_state->triplebuffer_flips;
if (pipe->plane_state != NULL)
flip_immediate = pipe->plane_state->flip_immediate;
@@ -1413,22 +1441,10 @@ void dcn20_pipe_control_lock(
}
if (flip_immediate && lock) {
- const unsigned int TIMEOUT_FOR_FLIP_PENDING_US = 100000U;
- unsigned int polling_interval_us = 1;
- unsigned int i;
-
temp_pipe = pipe;
while (temp_pipe) {
- if (temp_pipe->plane_state && temp_pipe->plane_state->flip_immediate) {
- for (i = 0; i < TIMEOUT_FOR_FLIP_PENDING_US / polling_interval_us; ++i) {
- if (!temp_pipe->plane_res.hubp->funcs->hubp_is_flip_pending(temp_pipe->plane_res.hubp))
- break;
- udelay(polling_interval_us);
- }
-
- /* no reason it should take this long for immediate flips */
- ASSERT(i != TIMEOUT_FOR_FLIP_PENDING_US);
- }
+ if (temp_pipe->plane_state && temp_pipe->plane_state->flip_immediate)
+ params->hubps_to_wait_for_flip[hubp_count++] = temp_pipe->plane_res.hubp;
temp_pipe = temp_pipe->bottom_pipe;
}
}
@@ -1438,8 +1454,11 @@ void dcn20_pipe_control_lock(
*/
if (lock && (pipe->bottom_pipe != NULL || !flip_immediate))
if ((flip_immediate && pipe->stream_res.gsl_group == 0) ||
- (!flip_immediate && pipe->stream_res.gsl_group > 0))
- dcn20_setup_gsl_group_as_lock(dc, pipe, flip_immediate);
+ (!flip_immediate && pipe->stream_res.gsl_group > 0)) {
+ params->gsl_lock = true;
+ dcn20_build_gsl_group_as_lock(dc, pipe, flip_immediate,
+ ¶ms->gsl, ¶ms->gsl_source_select);
+ }
if (pipe->plane_state != NULL)
flip_immediate = pipe->plane_state->flip_immediate;
@@ -1452,37 +1471,53 @@ void dcn20_pipe_control_lock(
}
if (!lock && pipe->stream_res.gsl_group > 0 && pipe->plane_state &&
- !flip_immediate)
- dcn20_setup_gsl_group_as_lock(dc, pipe, false);
+ !flip_immediate) {
+ params->gsl_lock = true;
+ dcn20_build_gsl_group_as_lock(dc, pipe, false,
+ ¶ms->gsl, ¶ms->gsl_source_select);
+ }
+
+ if (!lock && !params->tg_lock.use_dmub_inbox1 &&
+ !params->tg_lock.triplebuffer_flips &&
+ dc->hwseq->funcs.perform_3dlut_wa_unlock) {
+ const struct pipe_ctx *otg_master_pipe = resource_get_otg_master(pipe);
+ const struct pipe_ctx *primary_dpp_pipe = resource_is_pipe_type(pipe, DPP_PIPE) ?
+ resource_get_primary_dpp_pipe(pipe) : pipe;
+
+ if (otg_master_pipe && otg_master_pipe->stream_res.tg &&
+ primary_dpp_pipe && primary_dpp_pipe->plane_state &&
+ primary_dpp_pipe->plane_state->cm.flags.bits.lut3d_enable &&
+ primary_dpp_pipe->plane_state->cm.flags.bits.lut3d_dma_enable) {
+ params->tg_3dlut_wa_unlock = true;
+ params->tg_3dlut_wa_unlock_params.tg = otg_master_pipe->stream_res.tg;
+ params->tg_3dlut_wa_unlock_params.hubp = primary_dpp_pipe->plane_res.hubp;
+ }
+ }
+
+ return true;
+}
- if (pipe->stream && should_use_dmub_inbox1_lock(dc, pipe->stream->link)) {
+void dcn20_tg_lock(struct tg_lock_params *params)
+{
+ if (params->use_dmub_inbox1) {
union dmub_hw_lock_flags hw_locks = { 0 };
struct dmub_hw_lock_inst_flags inst_flags = { 0 };
hw_locks.bits.lock_pipe = 1;
- inst_flags.otg_inst = (uint8_t)pipe->stream_res.tg->inst;
-
- if (pipe->plane_state != NULL)
- hw_locks.bits.triple_buffer_lock = pipe->plane_state->triplebuffer_flips;
-
- dmub_hw_lock_mgr_cmd(dc->ctx->dmub_srv,
- lock,
- &hw_locks,
- &inst_flags);
- } else if (pipe->plane_state != NULL && pipe->plane_state->triplebuffer_flips) {
- if (lock)
- pipe->stream_res.tg->funcs->triplebuffer_lock(pipe->stream_res.tg);
+ inst_flags.otg_inst = (uint8_t)params->tg->inst;
+ hw_locks.bits.triple_buffer_lock = params->triplebuffer_flips;
+ dmub_hw_lock_mgr_cmd(params->dc->ctx->dmub_srv, params->lock,
+ &hw_locks, &inst_flags);
+ } else if (params->triplebuffer_flips) {
+ if (params->lock)
+ params->tg->funcs->triplebuffer_lock(params->tg);
else
- pipe->stream_res.tg->funcs->triplebuffer_unlock(pipe->stream_res.tg);
+ params->tg->funcs->triplebuffer_unlock(params->tg);
} else {
- if (lock)
- pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg);
- else {
- if (dc->hwseq->funcs.perform_3dlut_wa_unlock)
- dc->hwseq->funcs.perform_3dlut_wa_unlock(pipe);
- else
- pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg);
- }
+ if (params->lock)
+ params->tg->funcs->lock(params->tg);
+ else
+ params->tg->funcs->unlock(params->tg);
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.h
index 9312c88e31ad9..c7bf79fda54c7 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.h
@@ -61,10 +61,16 @@ void dcn20_blank_pixel_data(
struct dc *dc,
struct pipe_ctx *pipe_ctx,
bool blank);
-void dcn20_pipe_control_lock(
- struct dc *dc,
- struct pipe_ctx *pipe,
- bool lock);
+bool dcn20_build_pipe_control_lock_sequence(struct dc *dc,
+ struct pipe_ctx *pipe, bool lock,
+ struct pipe_control_lock_params *params);
+void dcn20_build_gsl_group_as_lock(
+ const struct dc *dc,
+ struct pipe_ctx *pipe_ctx,
+ bool enable,
+ struct tg_set_gsl_params *gsl_params,
+ struct tg_set_gsl_source_select_params *gsl_source_select_params);
+void dcn20_tg_lock(struct tg_lock_params *params);
void dcn20_prepare_bandwidth(
struct dc *dc,
struct dc_state *context);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_init.c
index 1797a91b0186e..1c6c4e19bdda3 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_init.c
@@ -56,7 +56,8 @@ static const struct hw_sequencer_funcs dcn20_funcs = {
.enable_audio_stream = dce110_enable_audio_stream,
.disable_audio_stream = dce110_disable_audio_stream,
.disable_plane = dcn20_disable_plane,
- .pipe_control_lock = dcn20_pipe_control_lock,
+ .build_pipe_control_lock_sequence = dcn20_build_pipe_control_lock_sequence,
+ .tg_lock = dcn20_tg_lock,
.interdependent_update_lock = dcn10_lock_all_pipes,
.cursor_lock = dcn10_cursor_lock,
.prepare_bandwidth = dcn20_prepare_bandwidth,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c
index 7b820bdae55b4..9f4bc2a498730 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c
@@ -525,35 +525,27 @@ void dcn201_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
hubp->mpcc_id = mpcc_id;
}
-void dcn201_pipe_control_lock(
- struct dc *dc,
- struct pipe_ctx *pipe,
- bool lock)
+void dcn201_tg_lock(struct tg_lock_params *params)
{
- struct dce_hwseq *hws = dc->hwseq;
- /* use TG master update lock to lock everything on the TG
- * therefore only top pipe need to lock
- */
- if (pipe->top_pipe)
- return;
+ struct dce_hwseq *hws = params->dc->hwseq;
- if (dc->debug.sanity_checks)
- hws->funcs.verify_allow_pstate_change_high(dc);
+ if (params->dc->debug.sanity_checks)
+ hws->funcs.verify_allow_pstate_change_high(params->dc);
- if (pipe->plane_state != NULL && pipe->plane_state->triplebuffer_flips) {
- if (lock)
- pipe->stream_res.tg->funcs->triplebuffer_lock(pipe->stream_res.tg);
+ if (params->triplebuffer_flips) {
+ if (params->lock)
+ params->tg->funcs->triplebuffer_lock(params->tg);
else
- pipe->stream_res.tg->funcs->triplebuffer_unlock(pipe->stream_res.tg);
+ params->tg->funcs->triplebuffer_unlock(params->tg);
} else {
- if (lock)
- pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg);
+ if (params->lock)
+ params->tg->funcs->lock(params->tg);
else
- pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg);
+ params->tg->funcs->unlock(params->tg);
}
- if (dc->debug.sanity_checks)
- hws->funcs.verify_allow_pstate_change_high(dc);
+ if (params->dc->debug.sanity_checks)
+ hws->funcs.verify_allow_pstate_change_high(params->dc);
}
void dcn201_set_cursor_attribute(struct pipe_ctx *pipe_ctx)
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.h
index 6a50a9894be6a..bab5d9e6912e4 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.h
@@ -36,10 +36,7 @@ void dcn201_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx);
void dcn201_plane_atomic_disconnect(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx);
void dcn201_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx);
void dcn201_set_cursor_attribute(struct pipe_ctx *pipe_ctx);
-void dcn201_pipe_control_lock(
- struct dc *dc,
- struct pipe_ctx *pipe,
- bool lock);
+void dcn201_tg_lock(struct tg_lock_params *params);
void dcn201_init_blank(
struct dc *dc,
struct timing_generator *tg);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_init.c
index dec57fb4c05c9..95dda06b6b175 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_init.c
@@ -23,6 +23,7 @@
*
*/
+#include "dce/dce_hwseq.h"
#include "dce110/dce110_hwseq.h"
#include "dcn10/dcn10_hwseq.h"
#include "dcn20/dcn20_hwseq.h"
@@ -55,7 +56,8 @@ static const struct hw_sequencer_funcs dcn201_funcs = {
.enable_audio_stream = dce110_enable_audio_stream,
.disable_audio_stream = dce110_disable_audio_stream,
.disable_plane = dcn10_disable_plane,
- .pipe_control_lock = dcn201_pipe_control_lock,
+ .build_pipe_control_lock_sequence = dce_build_pipe_control_lock_sequence,
+ .tg_lock = dcn201_tg_lock,
.interdependent_update_lock = dcn10_lock_all_pipes,
.cursor_lock = dcn10_cursor_lock,
.prepare_bandwidth = dcn20_prepare_bandwidth,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_init.c
index c7701a8b574aa..b8ed664e1babf 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_init.c
@@ -56,7 +56,8 @@ static const struct hw_sequencer_funcs dcn21_funcs = {
.enable_audio_stream = dce110_enable_audio_stream,
.disable_audio_stream = dce110_disable_audio_stream,
.disable_plane = dcn20_disable_plane,
- .pipe_control_lock = dcn20_pipe_control_lock,
+ .build_pipe_control_lock_sequence = dcn20_build_pipe_control_lock_sequence,
+ .tg_lock = dcn20_tg_lock,
.interdependent_update_lock = dcn10_lock_all_pipes,
.cursor_lock = dcn10_cursor_lock,
.prepare_bandwidth = dcn20_prepare_bandwidth,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_init.c
index d5aa58462855c..b655c01f013bc 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_init.c
@@ -57,7 +57,8 @@ static const struct hw_sequencer_funcs dcn30_funcs = {
.disable_audio_stream = dce110_disable_audio_stream,
.disable_plane = dcn20_disable_plane,
.disable_pixel_data = dcn20_disable_pixel_data,
- .pipe_control_lock = dcn20_pipe_control_lock,
+ .build_pipe_control_lock_sequence = dcn20_build_pipe_control_lock_sequence,
+ .tg_lock = dcn20_tg_lock,
.interdependent_update_lock = dcn10_lock_all_pipes,
.cursor_lock = dcn10_cursor_lock,
.prepare_bandwidth = dcn30_prepare_bandwidth,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn301/dcn301_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn301/dcn301_init.c
index a570333aeac18..dfacc59166cdd 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn301/dcn301_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn301/dcn301_init.c
@@ -58,7 +58,8 @@ static const struct hw_sequencer_funcs dcn301_funcs = {
.enable_audio_stream = dce110_enable_audio_stream,
.disable_audio_stream = dce110_disable_audio_stream,
.disable_plane = dcn20_disable_plane,
- .pipe_control_lock = dcn20_pipe_control_lock,
+ .build_pipe_control_lock_sequence = dcn20_build_pipe_control_lock_sequence,
+ .tg_lock = dcn20_tg_lock,
.interdependent_update_lock = dcn10_lock_all_pipes,
.cursor_lock = dcn10_cursor_lock,
.prepare_bandwidth = dcn20_prepare_bandwidth,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_init.c
index 7197414e5bd69..3c2e2162da117 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_init.c
@@ -60,7 +60,8 @@ static const struct hw_sequencer_funcs dcn31_funcs = {
.disable_audio_stream = dce110_disable_audio_stream,
.disable_plane = dcn20_disable_plane,
.disable_pixel_data = dcn20_disable_pixel_data,
- .pipe_control_lock = dcn20_pipe_control_lock,
+ .build_pipe_control_lock_sequence = dcn20_build_pipe_control_lock_sequence,
+ .tg_lock = dcn20_tg_lock,
.interdependent_update_lock = dcn10_lock_all_pipes,
.cursor_lock = dcn10_cursor_lock,
.prepare_bandwidth = dcn20_prepare_bandwidth,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c
index 4966c044a8644..b50ab468b8f8f 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c
@@ -62,7 +62,8 @@ static const struct hw_sequencer_funcs dcn314_funcs = {
.disable_audio_stream = dce110_disable_audio_stream,
.disable_plane = dcn20_disable_plane,
.disable_pixel_data = dcn20_disable_pixel_data,
- .pipe_control_lock = dcn20_pipe_control_lock,
+ .build_pipe_control_lock_sequence = dcn20_build_pipe_control_lock_sequence,
+ .tg_lock = dcn20_tg_lock,
.interdependent_update_lock = dcn10_lock_all_pipes,
.cursor_lock = dcn10_cursor_lock,
.prepare_bandwidth = dcn20_prepare_bandwidth,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
index ec38fc2ba65cc..79be5c385280c 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
@@ -1867,9 +1867,9 @@ void dcn32_interdependent_update_lock(struct dc *dc,
continue;
if (lock)
- dc->hwss.pipe_control_lock(dc, pipe, true);
+ hwss_pipe_control_lock(dc, pipe, true);
else
- dc->hwss.pipe_control_lock(dc, pipe, false);
+ hwss_pipe_control_lock(dc, pipe, false);
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c
index 364b4108f5d6f..2251289622167 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c
@@ -60,7 +60,8 @@ static const struct hw_sequencer_funcs dcn32_funcs = {
.disable_audio_stream = dce110_disable_audio_stream,
.disable_plane = dcn20_disable_plane,
.disable_pixel_data = dcn20_disable_pixel_data,
- .pipe_control_lock = dcn20_pipe_control_lock,
+ .build_pipe_control_lock_sequence = dcn20_build_pipe_control_lock_sequence,
+ .tg_lock = dcn20_tg_lock,
.interdependent_update_lock = dcn32_interdependent_update_lock,
.cursor_lock = dcn10_cursor_lock,
.prepare_bandwidth = dcn32_prepare_bandwidth,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c
index fc18d2207711f..c9125cc25d157 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c
@@ -64,7 +64,8 @@ static const struct hw_sequencer_funcs dcn35_funcs = {
.disable_audio_stream = dce110_disable_audio_stream,
.disable_plane = dcn35_disable_plane,
.disable_pixel_data = dcn20_disable_pixel_data,
- .pipe_control_lock = dcn20_pipe_control_lock,
+ .build_pipe_control_lock_sequence = dcn20_build_pipe_control_lock_sequence,
+ .tg_lock = dcn20_tg_lock,
.interdependent_update_lock = dcn10_lock_all_pipes,
.cursor_lock = dcn10_cursor_lock,
.prepare_bandwidth = dcn35_prepare_bandwidth,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c
index 19ec5b4edfdc9..e6f7d57cbfed5 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c
@@ -63,7 +63,8 @@ static const struct hw_sequencer_funcs dcn351_funcs = {
.disable_audio_stream = dce110_disable_audio_stream,
.disable_plane = dcn35_disable_plane,
.disable_pixel_data = dcn20_disable_pixel_data,
- .pipe_control_lock = dcn20_pipe_control_lock,
+ .build_pipe_control_lock_sequence = dcn20_build_pipe_control_lock_sequence,
+ .tg_lock = dcn20_tg_lock,
.interdependent_update_lock = dcn10_lock_all_pipes,
.cursor_lock = dcn10_cursor_lock,
.prepare_bandwidth = dcn35_prepare_bandwidth,
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 0e107754c891e..8e0ccc9d58199 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
@@ -32,6 +32,7 @@
#include "dcn10/dcn10_cm_common.h"
#include "dcn10/dcn10_hubbub.h"
#include "dcn20/dcn20_optc.h"
+#include "dcn20/dcn20_hwseq.h"
#include "dcn30/dcn30_cm_common.h"
#include "dcn32/dcn32_hwseq.h"
#include "dcn401_hwseq.h"
@@ -1935,7 +1936,7 @@ void dcn401_interdependent_update_lock(struct dc *dc,
!tg->funcs->is_tg_enabled(tg) ||
dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM)
continue;
- dc->hwss.pipe_control_lock(dc, pipe, true);
+ hwss_pipe_control_lock(dc, pipe, true);
}
} else {
/* Need to free DET being used first and have pipe update, then unlock the remaining pipes*/
@@ -1951,7 +1952,7 @@ void dcn401_interdependent_update_lock(struct dc *dc,
if (dc->scratch.pipes_to_unlock_first[i]) {
struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
- dc->hwss.pipe_control_lock(dc, pipe, false);
+ hwss_pipe_control_lock(dc, pipe, false);
/* Assumes pipe of the same index in current_state is also an OTG_MASTER pipe*/
dcn401_wait_for_det_buffer_update_under_otg_master(dc, dc->current_state, old_pipe);
}
@@ -1970,12 +1971,13 @@ void dcn401_interdependent_update_lock(struct dc *dc,
continue;
}
- dc->hwss.pipe_control_lock(dc, pipe, false);
+ hwss_pipe_control_lock(dc, pipe, false);
}
}
}
-void dcn401_perform_3dlut_wa_unlock(struct pipe_ctx *pipe_ctx)
+void dcn401_perform_3dlut_wa_unlock(struct timing_generator *tg,
+ struct hubp *primary_hubp)
{
/* If 3DLUT FL is enabled and 3DLUT is in use, follow the workaround sequence for pipe unlock to make sure that
* HUBP will properly fetch 3DLUT contents after unlock.
@@ -1983,45 +1985,24 @@ void dcn401_perform_3dlut_wa_unlock(struct pipe_ctx *pipe_ctx)
* This is meant to work around a known HW issue where VREADY will cancel the pending 3DLUT_ENABLE signal regardless
* of whether OTG lock is currently being held or not.
*/
- if (!pipe_ctx)
+ if (!tg)
return;
- const struct pipe_ctx *otg_master_pipe_ctx = resource_get_otg_master(pipe_ctx);
- struct timing_generator *tg = otg_master_pipe_ctx ?
- otg_master_pipe_ctx->stream_res.tg : NULL;
- const struct pipe_ctx *primary_dpp_pipe_ctx = resource_is_pipe_type(pipe_ctx, DPP_PIPE) ?
- resource_get_primary_dpp_pipe(pipe_ctx) : pipe_ctx;
- struct hubp *primary_hubp = primary_dpp_pipe_ctx ?
- primary_dpp_pipe_ctx->plane_res.hubp : NULL;
-
- if (!otg_master_pipe_ctx || !tg) {
- return;
- }
-
- if (primary_dpp_pipe_ctx &&
- primary_dpp_pipe_ctx->plane_state &&
- primary_dpp_pipe_ctx->plane_state->cm.flags.bits.lut3d_enable &&
- primary_dpp_pipe_ctx->plane_state->cm.flags.bits.lut3d_dma_enable) {
- if (tg->funcs->set_vupdate_keepout)
- tg->funcs->set_vupdate_keepout(tg, true);
+ if (tg->funcs->set_vupdate_keepout)
+ tg->funcs->set_vupdate_keepout(tg, true);
- if (primary_hubp && primary_hubp->funcs->hubp_enable_3dlut_fl) {
- primary_hubp->funcs->hubp_enable_3dlut_fl(primary_hubp, true);
- }
+ if (primary_hubp && primary_hubp->funcs->hubp_enable_3dlut_fl)
+ primary_hubp->funcs->hubp_enable_3dlut_fl(primary_hubp, true);
- tg->funcs->unlock(tg);
- if (tg->funcs->wait_update_lock_status)
- tg->funcs->wait_update_lock_status(tg, false);
+ tg->funcs->unlock(tg);
+ if (tg->funcs->wait_update_lock_status)
+ tg->funcs->wait_update_lock_status(tg, false);
- if (primary_hubp && primary_hubp->funcs->hubp_enable_3dlut_fl) {
- primary_hubp->funcs->hubp_enable_3dlut_fl(primary_hubp, true);
- }
+ if (primary_hubp && primary_hubp->funcs->hubp_enable_3dlut_fl)
+ primary_hubp->funcs->hubp_enable_3dlut_fl(primary_hubp, true);
- if (tg->funcs->set_vupdate_keepout)
- tg->funcs->set_vupdate_keepout(tg, false);
- } else {
- tg->funcs->unlock(tg);
- }
+ if (tg->funcs->set_vupdate_keepout)
+ tg->funcs->set_vupdate_keepout(tg, false);
}
void dcn401_program_outstanding_updates(struct dc *dc,
@@ -3462,89 +3443,24 @@ void dcn401_update_writeback_sequence(
hwss_add_mcif_wb_config_buf(seq_state, mcif_wb, &wb_info->mcif_buf_params, wb_info->dwb_params.dest_height);
}
-static int find_free_gsl_group(const struct dc *dc)
-{
- if (dc->res_pool->gsl_groups.gsl_0 == 0)
- return 1;
- if (dc->res_pool->gsl_groups.gsl_1 == 0)
- return 2;
- if (dc->res_pool->gsl_groups.gsl_2 == 0)
- return 3;
-
- return 0;
-}
-
void dcn401_setup_gsl_group_as_lock_sequence(
const struct dc *dc,
struct pipe_ctx *pipe_ctx,
bool enable,
struct block_sequence_state *seq_state)
{
- struct gsl_params gsl;
- int group_idx;
-
- memset(&gsl, 0, sizeof(struct gsl_params));
+ struct tg_set_gsl_params gsl_params = { 0 };
+ struct tg_set_gsl_source_select_params gsl_source_select_params = { 0 };
- if (enable) {
- /* return if group already assigned since GSL was set up
- * for vsync flip, we would unassign so it can't be "left over"
- */
- if (pipe_ctx->stream_res.gsl_group > 0)
- return;
-
- group_idx = find_free_gsl_group(dc);
- ASSERT(group_idx != 0);
- pipe_ctx->stream_res.gsl_group = (uint8_t)group_idx;
-
- /* set gsl group reg field and mark resource used */
- switch (group_idx) {
- case 1:
- gsl.gsl0_en = 1;
- dc->res_pool->gsl_groups.gsl_0 = 1;
- break;
- case 2:
- gsl.gsl1_en = 1;
- dc->res_pool->gsl_groups.gsl_1 = 1;
- break;
- case 3:
- gsl.gsl2_en = 1;
- dc->res_pool->gsl_groups.gsl_2 = 1;
- break;
- default:
- BREAK_TO_DEBUGGER();
- return; // invalid case
- }
- gsl.gsl_master_en = 1;
- } else {
- group_idx = pipe_ctx->stream_res.gsl_group;
- if (group_idx == 0)
- return; // if not in use, just return
-
- pipe_ctx->stream_res.gsl_group = 0;
-
- /* unset gsl group reg field and mark resource free */
- switch (group_idx) {
- case 1:
- gsl.gsl0_en = 0;
- dc->res_pool->gsl_groups.gsl_0 = 0;
- break;
- case 2:
- gsl.gsl1_en = 0;
- dc->res_pool->gsl_groups.gsl_1 = 0;
- break;
- case 3:
- gsl.gsl2_en = 0;
- dc->res_pool->gsl_groups.gsl_2 = 0;
- break;
- default:
- BREAK_TO_DEBUGGER();
- return;
- }
- gsl.gsl_master_en = 0;
- }
+ dcn20_build_gsl_group_as_lock(dc, pipe_ctx, enable,
+ &gsl_params, &gsl_source_select_params);
+ if (!gsl_source_select_params.group_idx)
+ return;
- hwss_add_tg_set_gsl(seq_state, pipe_ctx->stream_res.tg, gsl);
- hwss_add_tg_set_gsl_source_select(seq_state, pipe_ctx->stream_res.tg, group_idx, enable ? 4 : 0);
+ hwss_add_tg_set_gsl(seq_state, gsl_params.tg, gsl_params.gsl);
+ hwss_add_tg_set_gsl_source_select(seq_state, gsl_source_select_params.tg,
+ gsl_source_select_params.group_idx,
+ gsl_source_select_params.gsl_ready_signal);
}
void dcn401_disable_plane_sequence(
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 c08fd359b38b0..756b2d98a9309 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
@@ -109,7 +109,8 @@ void dcn401_program_pipe_sequence(
struct pipe_ctx *pipe_ctx,
struct dc_state *context,
struct block_sequence_state *seq_state);
-void dcn401_perform_3dlut_wa_unlock(struct pipe_ctx *pipe_ctx);
+void dcn401_perform_3dlut_wa_unlock(struct timing_generator *tg,
+ struct hubp *primary_hubp);
void dcn401_program_front_end_for_ctx(struct dc *dc, struct dc_state *context);
void dcn401_post_unlock_program_front_end(struct dc *dc, struct dc_state *context);
bool dcn401_update_bandwidth(struct dc *dc, struct dc_state *context);
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 7039f40ea880d..783415e4e3a10 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
@@ -40,7 +40,8 @@ static const struct hw_sequencer_funcs dcn401_funcs = {
.disable_audio_stream = dce110_disable_audio_stream,
.disable_plane = dcn20_disable_plane,
.disable_plane_sequence = dcn401_disable_plane_sequence,
- .pipe_control_lock = dcn20_pipe_control_lock,
+ .build_pipe_control_lock_sequence = dcn20_build_pipe_control_lock_sequence,
+ .tg_lock = dcn20_tg_lock,
.interdependent_update_lock = dcn401_interdependent_update_lock,
.cursor_lock = dcn10_cursor_lock,
.prepare_bandwidth = dcn401_prepare_bandwidth,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c
index ba12a97a220fe..aad1885cc9887 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c
@@ -42,7 +42,8 @@ static const struct hw_sequencer_funcs dcn42_funcs = {
.enable_audio_stream = dce110_enable_audio_stream,
.disable_audio_stream = dce110_disable_audio_stream,
.disable_plane = dcn35_disable_plane,
- .pipe_control_lock = dcn20_pipe_control_lock,
+ .build_pipe_control_lock_sequence = dcn20_build_pipe_control_lock_sequence,
+ .tg_lock = dcn20_tg_lock,
.interdependent_update_lock = dcn401_interdependent_update_lock,
.cursor_lock = dcn10_cursor_lock,
.prepare_bandwidth = dcn42_prepare_bandwidth,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.c
index 1c908964153b7..37e88d45409be 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.c
@@ -42,7 +42,8 @@ static const struct hw_sequencer_funcs dcn60_funcs = {
.disable_audio_stream = dce110_disable_audio_stream,
.disable_plane = dcn20_disable_plane,
.disable_plane_sequence = dcn401_disable_plane_sequence,
- .pipe_control_lock = dcn20_pipe_control_lock,
+ .build_pipe_control_lock_sequence = dcn20_build_pipe_control_lock_sequence,
+ .tg_lock = dcn20_tg_lock,
.interdependent_update_lock = dcn401_interdependent_update_lock,
.cursor_lock = dcn10_cursor_lock,
.prepare_bandwidth = dcn401_prepare_bandwidth,
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 169f3420ac6dd..4f0d000eab948 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
@@ -66,10 +66,17 @@ struct subvp_pipe_control_lock_fast_params {
bool subvp_immediate_flip;
};
-struct pipe_control_lock_params {
+struct tg_lock_params {
struct dc *dc;
- struct pipe_ctx *pipe_ctx;
+ struct timing_generator *tg;
bool lock;
+ bool use_dmub_inbox1;
+ bool triplebuffer_flips;
+};
+
+struct tg_3dlut_wa_unlock_params {
+ struct timing_generator *tg;
+ struct hubp *hubp;
};
struct set_flip_control_gsl_params {
@@ -342,6 +349,17 @@ struct tg_set_gsl_source_select_params {
uint32_t gsl_ready_signal;
};
+struct pipe_control_lock_params {
+ bool lock;
+ struct hubp *hubps_to_wait_for_flip[MAX_PIPES];
+ bool gsl_lock;
+ struct tg_set_gsl_params gsl;
+ struct tg_set_gsl_source_select_params gsl_source_select;
+ struct tg_lock_params tg_lock;
+ bool tg_3dlut_wa_unlock;
+ struct tg_3dlut_wa_unlock_params tg_3dlut_wa_unlock_params;
+};
+
struct setup_vupdate_interrupt_params {
struct dc *dc;
struct pipe_ctx *pipe_ctx;
@@ -487,7 +505,6 @@ struct tg_enable_crtc_params {
struct hubp_wait_flip_pending_params {
struct hubp *hubp;
- unsigned int timeout_us;
unsigned int polling_interval_us;
};
@@ -1026,7 +1043,8 @@ struct link_set_dpms_on_params {
union block_sequence_params {
struct update_plane_addr_params update_plane_addr_params;
struct subvp_pipe_control_lock_fast_params subvp_pipe_control_lock_fast_params;
- struct pipe_control_lock_params pipe_control_lock_params;
+ struct tg_lock_params tg_lock_params;
+ struct tg_3dlut_wa_unlock_params tg_3dlut_wa_unlock_params;
struct set_flip_control_gsl_params set_flip_control_gsl_params;
struct program_triplebuffer_params program_triplebuffer_params;
struct set_input_transfer_func_params set_input_transfer_func_params;
@@ -1200,7 +1218,8 @@ union block_sequence_params {
enum block_sequence_func {
DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST = 0,
- OPTC_PIPE_CONTROL_LOCK,
+ TG_LOCK,
+ TG_3DLUT_WA_UNLOCK,
HUBP_SET_FLIP_CONTROL_GSL,
HUBP_PROGRAM_TRIPLEBUFFER,
HUBP_UPDATE_PLANE_ADDR,
@@ -1432,8 +1451,10 @@ struct hw_sequencer_funcs {
void (*clear_surface_dcc_and_tiling)(struct pipe_ctx *pipe_ctx, struct dc_plane_state *plane_state, bool clear_tiling);
/* Pipe Lock Related */
- void (*pipe_control_lock)(struct dc *dc,
- struct pipe_ctx *pipe, bool lock);
+ bool (*build_pipe_control_lock_sequence)(struct dc *dc,
+ struct pipe_ctx *pipe, bool lock,
+ struct pipe_control_lock_params *params);
+ void (*tg_lock)(struct tg_lock_params *params);
void (*interdependent_update_lock)(struct dc *dc,
struct dc_state *context, bool lock);
void (*set_flip_control_gsl)(struct pipe_ctx *pipe_ctx,
@@ -1959,7 +1980,8 @@ void hwss_tg_set_gsl(union block_sequence_params *params);
void hwss_tg_set_gsl_source_select(union block_sequence_params *params);
-void hwss_hubp_wait_flip_pending(union block_sequence_params *params);
+void hwss_hubp_wait_flip_pending(struct hubp *hubp,
+ unsigned int polling_interval_us);
void hwss_tg_wait_double_buffer_pending(union block_sequence_params *params);
@@ -2130,6 +2152,9 @@ void hwss_set_input_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx);
void hwss_add_optc_pipe_control_lock(struct block_sequence_state *seq_state,
struct dc *dc, struct pipe_ctx *pipe_ctx, bool lock);
+void hwss_pipe_control_lock(struct dc *dc,
+ struct pipe_ctx *pipe_ctx, bool lock);
+
void hwss_add_hubp_set_flip_control_gsl(struct block_sequence_state *seq_state,
struct hubp *hubp, bool flip_immediate);
@@ -2243,7 +2268,7 @@ void hwss_add_tg_enable_crtc(struct block_sequence_state *seq_state,
struct timing_generator *tg);
void hwss_add_hubp_wait_flip_pending(struct block_sequence_state *seq_state,
- struct hubp *hubp, unsigned int timeout_us, unsigned int polling_interval_us);
+ struct hubp *hubp, unsigned int polling_interval_us);
void hwss_add_tg_wait_double_buffer_pending(struct block_sequence_state *seq_state,
struct timing_generator *tg, unsigned int timeout_us, unsigned int polling_interval_us);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h
index 956513125be0b..9730f51cf3c04 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h
@@ -217,7 +217,8 @@ struct hwseq_private_funcs {
void (*reset_back_end_for_pipe)(struct dc *dc,
struct pipe_ctx *pipe_ctx,
struct dc_state *context);
- void (*perform_3dlut_wa_unlock)(struct pipe_ctx *pipe_ctx);
+ void (*perform_3dlut_wa_unlock)(struct timing_generator *tg,
+ struct hubp *primary_hubp);
void (*wait_for_pipe_update_if_needed)(struct dc *dc, struct pipe_ctx *pipe_ctx, bool is_surface_update_only);
void (*set_wait_for_update_needed_for_pipe)(struct dc *dc, struct pipe_ctx *pipe_ctx);
void (*dc_ip_request_cntl)(struct dc *dc, bool enable);
--
2.43.0
next prev parent reply other threads:[~2026-08-18 20:23 UTC|newest]
Thread overview: 86+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-18 20:14 [PATCH 00/82] DC Patches August 17, 2026 IVAN.LIPSKI
2026-08-18 20:14 ` [PATCH 01/82] drm/amd/display: Fall back to overlay cursor on dcn4x when top plane doesn't fill CRTC IVAN.LIPSKI
2026-08-19 7:27 ` Michel Dänzer
2026-08-20 10:04 ` Timur Kristóf
2026-08-18 20:14 ` [PATCH 02/82] drm/amd/display: Fixes for HPO test regressions IVAN.LIPSKI
2026-08-18 20:14 ` [PATCH 03/82] drm/amd/display: Refactor DPP_SET_INPUT_TRANSFER_FUNC to drop pipe_ctx IVAN.LIPSKI
2026-08-18 20:14 ` [PATCH 04/82] drm/amd/display: Use fast update path for address-only plane flips IVAN.LIPSKI
2026-08-18 20:14 ` IVAN.LIPSKI [this message]
2026-08-18 20:14 ` [PATCH 06/82] drm/amd/display: Fix DPREFCLK override when SMU isn't present or ready for DCN315 IVAN.LIPSKI
2026-08-18 20:14 ` [PATCH 07/82] drm/amd/display: Test writeback connector IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 08/82] drm/amd/display: Test GPU memory allocation IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 09/82] drm/amd/display: Cover MST path in encoder atomic_check IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 10/82] drm/amd/display: Cover amdgpu_dm_encoder_init IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 11/82] drm/amd/display: Cover MST-start failure in detect_mst IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 12/82] drm/amd/display: Cover amdgpu_dm_update_connector_after_detect IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 13/82] drm/amd/display: Cover HDMI infoframe/freesync timing paths IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 14/82] drm/amd/display: Clear HUBPREQ_DEBUG_DB on DCN6 IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 15/82] drm/amd/display: Disable alt-ch until dependencies are ready IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 16/82] drm/amd/display: Fix CalculateFlipSchedule Calculation IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 17/82] drm/amd/display: Test EDID quirks and ACPI EDID read IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 18/82] drm/amd/display: Test execute_synaptics_rc_command failures IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 19/82] drm/amd/display: Test MST stream feature read failure IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 20/82] drm/amd/display: Test dm_helpers_submit_i2c_over_aux IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 21/82] drm/amd/display: Test GPU memory allocate and free helpers IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 22/82] drm/amd/display: Test dm_helpers_dmub_set_config_sync IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 23/82] drm/amd/display: Test dm_helpers_is_dp_sink_present IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 24/82] drm/amd/display: Test dm_helpers_read_local_edid IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 25/82] drm/amd/display: Test dp_handle_test_pattern_request patterns IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 26/82] drm/amd/display: Test DMUB reg callbacks IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 27/82] drm/amd/display: Test VBIOS bounding box IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 28/82] drm/amd/display: Test dm_init_microcode IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 29/82] drm/amd/display: Test dm_dmub_sw_init IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 30/82] drm/amd/display: Add hook to disable alt-ch in PMO IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 31/82] drm/amd/display: Update alt-ch size calculations IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 32/82] drm/amd/display: Enable min dispclk ODM on DCN42 IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 33/82] drm/amd/display: Add amdgpu_dm_connector_poll KUnit tests IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 34/82] drm/amd/display: Cover hide_secondary_tile_from_userspace IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 35/82] drm/amd/display: Cover dm_validate_stream_and_context IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 36/82] drm/amd/display: Cover amdgpu_dm_create_validate_stream_for_sink IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 37/82] drm/amd/display: Cover amdgpu_dm_connector_mode_valid IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 38/82] drm/amd/display: Test MST sideband message ack path IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 39/82] drm/amd/display: Test dm_dp_mst_get_modes without a remote EDID IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 40/82] drm/amd/display: Test dm_dp_mst_get_modes with " IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 41/82] drm/amd/display: Test dm_dp_mst_detect DPCD probe and unplug IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 42/82] drm/amd/display: Test MST connector register and unregister IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 43/82] drm/amd/display: Test dm_dp_mst_connector_destroy IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 44/82] drm/amd/display: Test plane state duplicate and destroy IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 45/82] drm/amd/display: Test modifier list de-duplication IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 46/82] drm/amd/display: Test GFX6-8 tiling info from modifiers IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 47/82] drm/amd/display: Test GFX6-8 tile mode and tile split lookups IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 48/82] drm/amd/display: Test GFX6-8 modifier calculation IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 49/82] drm/amd/display: Test GFX6-8 modifier list generation IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 50/82] drm/amd/display: Test framebuffer prepare and cleanup IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 51/82] drm/amd/display: Test cursor update and async plane update IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 52/82] drm/amd/display: Remove RMCM tetrahedral cube from dc_plane_state IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 53/82] drm/amd/display: Cover mode_valid EDID mgmt path IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 54/82] drm/amd/display: Cover amdgpu_dm_fill_hdr_info_packet IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 55/82] drm/amd/display: Cover amdgpu_dm_connector_atomic_check IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 56/82] drm/amd/display: Cover atomic_check modeset triggers IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 57/82] drm/amd/display: Cover funcs_force valid EDID path IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 58/82] drm/amd/display: Cover amdgpu_dm_connector_get_modes IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 59/82] drm/amd/display: Cover create_eml_sink valid EDID path IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 60/82] drm/amd/display: Cover amdgpu_set_panel_orientation IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 61/82] drm/amd/display: Refactor amdgpu_dm_irq_test IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 62/82] drm/amd/display: Test pageflip completion in the high IRQ handlers IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 63/82] drm/amd/display: Test writeback handling in dm_crtc_high_irq IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 64/82] drm/amd/display: Test schedule_dc_vmin_vmax IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 65/82] drm/amd/display: Test handle_hpd_irq_helper detect and debounce exits IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 66/82] drm/amd/display: Test HPD RX, HPD init and DMUB callback branches IVAN.LIPSKI
2026-08-18 20:15 ` [PATCH 67/82] drm/amd/display: Test dm_dmub_outbox1_low_irq drain and work guards IVAN.LIPSKI
2026-08-18 20:16 ` [PATCH 68/82] drm/amd/display: Test amdgpu_dm_dce110_register_irq_handlers IVAN.LIPSKI
2026-08-18 20:16 ` [PATCH 69/82] drm/amd/display: Test amdgpu_dm_dcn10_register_irq_handlers IVAN.LIPSKI
2026-08-18 20:16 ` [PATCH 70/82] drm/amd/display: Fix mismatch number of OPP/DPP accounting IVAN.LIPSKI
2026-08-18 20:16 ` [PATCH 71/82] drm/amd/display: Cover amdgpu_dm_prune_primary_tile_modes IVAN.LIPSKI
2026-08-18 20:16 ` [PATCH 72/82] drm/amd/display: Cover add_fs_modes mode generation IVAN.LIPSKI
2026-08-18 20:16 ` [PATCH 73/82] drm/amd/display: Cover add_fs_modes illegal timing skip IVAN.LIPSKI
2026-08-18 20:16 ` [PATCH 74/82] drm/amd/display: Refactor hdmi_frl_status_polling_work for Kunit testing IVAN.LIPSKI
2026-08-18 20:16 ` [PATCH 75/82] drm/amd/display: Cover hdmi_frl_status_polling_work IVAN.LIPSKI
2026-08-18 20:16 ` [PATCH 76/82] drm/amd/display: Cover amdgpu_dm_i2c_xfer IVAN.LIPSKI
2026-08-18 20:16 ` [PATCH 77/82] drm/amd/display: Cover amdgpu_dm_create_i2c IVAN.LIPSKI
2026-08-18 20:16 ` [PATCH 78/82] drm/amd/display: Add passthrough visual confirm IVAN.LIPSKI
2026-08-18 20:16 ` [PATCH 79/82] drm/amd/display: Populate vblank_nom according to bounding box IVAN.LIPSKI
2026-08-18 20:16 ` [PATCH 80/82] drm/amd/display: Adjust vblank_nom policy for HW SDP tranmission reqs IVAN.LIPSKI
2026-08-18 20:16 ` [PATCH 81/82] drm/amd/display: Guard amdgpu_dm_irq_schedule_work against NULL irq_wq IVAN.LIPSKI
2026-08-18 20:16 ` [PATCH 82/82] drm/amd/display: Promote DC to 3.2.395 IVAN.LIPSKI
2026-08-24 13:46 ` [PATCH 00/82] DC Patches August 17, 2026 Wheeler, Daniel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260818202139.4172592-6-IVAN.LIPSKI@amd.com \
--to=ivan.lipski@amd.com \
--cc=Chen-Yu.Chen@amd.com \
--cc=PingLei.Lin@amd.com \
--cc=Ray.Wu@amd.com \
--cc=alex.hung@amd.com \
--cc=alvin.lee2@amd.com \
--cc=amd-gfx@lists.freedesktop.org \
--cc=aurabindo.pillai@amd.com \
--cc=chiahsuan.chung@amd.com \
--cc=daniel.wheeler@amd.com \
--cc=harry.wentland@amd.com \
--cc=jerry.zuo@amd.com \
--cc=roman.li@amd.com \
--cc=sunpeng.li@amd.com \
--cc=tomasz.siemek@amd.com \
--cc=wayne.lin@amd.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox