From: Wenjing Liu <wenjing....@amd.com>

[why]
when an update programming sequence requires both
front end and back end pipe to be updated synchronously,
a global update lock needs to be set to ensure that
we don't get a frame with only front end update but
not the back end update.

[how]
setup global lock parameters on enable_stream_timing.
enable global lock when pipe_control_lock_global is called.
disable global lock when pipe_control_lock is called.

Signed-off-by: Wenjing Liu <wenjing....@amd.com>
Reviewed-by: Tony Cheng <tony.ch...@amd.com>
Signed-off-by: Alex Deucher <alexander.deuc...@amd.com>
---
 .../drm/amd/display/dc/dcn20/dcn20_hwseq.c    |  4 ++
 .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 63 ++++++++++++++++++-
 .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.h |  3 +
 .../amd/display/dc/inc/hw/timing_generator.h  |  2 +
 .../gpu/drm/amd/display/dc/inc/hw_sequencer.h |  1 +
 5 files changed, 72 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
index dc34ce28505c..fbcb4d860e7a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
@@ -727,6 +727,10 @@ enum dc_status dcn20_enable_stream_timing(
                        pipe_ctx->stream->signal,
                        true);
 
+       if (pipe_ctx->stream_res.tg->funcs->setup_global_lock)
+               pipe_ctx->stream_res.tg->funcs->setup_global_lock(
+                               pipe_ctx->stream_res.tg);
+
        /* program otg blank color */
        color_space = stream->output_color_space;
        color_space_to_black_color(dc, color_space, &black_color);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
index 43e71b4ab5e8..ea6a19063b22 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
@@ -330,6 +330,65 @@ void optc2_triplebuffer_unlock(struct timing_generator 
*optc)
 
 }
 
+
+void optc2_setup_global_lock(struct timing_generator *optc)
+{
+       struct optc *optc1 = DCN10TG_FROM_TG(optc);
+       uint32_t v_blank_start = 0;
+       uint32_t h_blank_start = 0, h_total = 0;
+
+       REG_SET(OTG_GLOBAL_CONTROL1, 0, MASTER_UPDATE_LOCK_DB_EN, 1);
+
+       REG_SET(OTG_GLOBAL_CONTROL2, 0, DIG_UPDATE_LOCATION, 20);
+
+       REG_GET(OTG_V_BLANK_START_END, OTG_V_BLANK_START, &v_blank_start);
+
+       REG_GET(OTG_H_BLANK_START_END, OTG_H_BLANK_START, &h_blank_start);
+
+       REG_GET(OTG_H_TOTAL, OTG_H_TOTAL, &h_total);
+       REG_UPDATE_2(OTG_GLOBAL_CONTROL1,
+                       MASTER_UPDATE_LOCK_DB_X,
+                       h_blank_start - 200 - 1,
+                       MASTER_UPDATE_LOCK_DB_Y,
+                       v_blank_start - 1);
+}
+
+void optc2_lock_global(struct timing_generator *optc)
+{
+       struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+       REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 1);
+
+       REG_SET(OTG_GLOBAL_CONTROL0, 0,
+                       OTG_MASTER_UPDATE_LOCK_SEL, optc->inst);
+       REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
+                       OTG_MASTER_UPDATE_LOCK, 1);
+
+       /* Should be fast, status does not update on maximus */
+       if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS)
+               REG_WAIT(OTG_MASTER_UPDATE_LOCK,
+                               UPDATE_LOCK_STATUS, 1,
+                               1, 10);
+}
+
+void optc2_lock(struct timing_generator *optc)
+{
+       struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+       REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 0);
+
+       REG_SET(OTG_GLOBAL_CONTROL0, 0,
+                       OTG_MASTER_UPDATE_LOCK_SEL, optc->inst);
+       REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
+                       OTG_MASTER_UPDATE_LOCK, 1);
+
+       /* Should be fast, status does not update on maximus */
+       if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS)
+               REG_WAIT(OTG_MASTER_UPDATE_LOCK,
+                               UPDATE_LOCK_STATUS, 1,
+                               1, 10);
+}
+
 void optc2_lock_doublebuffer_enable(struct timing_generator *optc)
 {
        struct optc *optc1 = DCN10TG_FROM_TG(optc);
@@ -424,8 +483,10 @@ static struct timing_generator_funcs dcn20_tg_funcs = {
                .triplebuffer_lock = optc2_triplebuffer_lock,
                .triplebuffer_unlock = optc2_triplebuffer_unlock,
                .disable_reset_trigger = optc1_disable_reset_trigger,
-               .lock = optc1_lock,
+               .lock = optc2_lock,
                .unlock = optc1_unlock,
+               .lock_global = optc2_lock_global,
+               .setup_global_lock = optc2_setup_global_lock,
                .lock_doublebuffer_enable = optc2_lock_doublebuffer_enable,
                .lock_doublebuffer_disable = optc2_lock_doublebuffer_disable,
                .enable_optc_clock = optc1_enable_optc_clock,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h 
b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h
index d2651d846424..a21781332a06 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h
@@ -104,6 +104,9 @@ void optc2_get_optc_source(struct timing_generator *optc,
 
 void optc2_triplebuffer_lock(struct timing_generator *optc);
 void optc2_triplebuffer_unlock(struct timing_generator *optc);
+void optc2_lock(struct timing_generator *optc);
+void optc2_lock_global(struct timing_generator *optc);
+void optc2_setup_global_lock(struct timing_generator *optc);
 void optc2_lock_doublebuffer_disable(struct timing_generator *optc);
 void optc2_lock_doublebuffer_enable(struct timing_generator *optc);
 void optc2_program_manual_trigger(struct timing_generator *optc);
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h 
b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
index 75314de83b3e..2dee10f7f1fe 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
@@ -184,8 +184,10 @@ struct timing_generator_funcs {
        bool (*did_triggered_reset_occur)(struct timing_generator *tg);
        void (*setup_global_swap_lock)(struct timing_generator *tg,
                                                        const struct 
dcp_gsl_params *gsl_params);
+       void (*setup_global_lock)(struct timing_generator *tg);
        void (*unlock)(struct timing_generator *tg);
        void (*lock)(struct timing_generator *tg);
+       void (*lock_global)(struct timing_generator *tg);
        void (*lock_doublebuffer_disable)(struct timing_generator *tg);
        void (*lock_doublebuffer_enable)(struct timing_generator *tg);
 #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h 
b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
index a0227dedbdf6..13b113d0fe19 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
@@ -205,6 +205,7 @@ struct hw_sequencer_funcs {
                                struct dc *dc,
                                struct pipe_ctx *pipe,
                                bool lock);
+
        void (*pipe_control_lock_global)(
                                struct dc *dc,
                                struct pipe_ctx *pipe,
-- 
2.20.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to