From: Tomasz Siemek <[email protected]>

[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 <[email protected]>
Signed-off-by: Tomasz Siemek <[email protected]>
Signed-off-by: Ivan Lipski <[email protected]>
---
 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(&params->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, &params))
+               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, &params))
+               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, 
&params.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(&params.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,
+                                       &params->gsl, 
&params->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,
+                               &params->gsl, &params->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

Reply via email to