From: Yihan Zhu <yihan....@amd.com>

[WHY & HOW]
OTG pending update unlatched will cause system fail, wait OTG fully disabled to
avoid this error.

Reviewed-by: Nicholas Kazlauskas <nicholas.kazlaus...@amd.com>
Signed-off-by: Yihan Zhu <yihan....@amd.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pil...@amd.com>
---
 .../drm/amd/display/dc/core/dc_hw_sequencer.c  |  2 ++
 .../amd/display/dc/inc/hw/timing_generator.h   |  1 +
 .../drm/amd/display/dc/optc/dcn32/dcn32_optc.h |  1 +
 .../drm/amd/display/dc/optc/dcn35/dcn35_optc.c | 18 ++++++++++++++++++
 4 files changed, 22 insertions(+)

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 ec4e80e5b6eb..d82b1cb467f4 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
@@ -1177,6 +1177,8 @@ void hwss_wait_for_odm_update_pending_complete(struct dc 
*dc, struct dc_state *c
                tg = otg_master->stream_res.tg;
                if (tg->funcs->wait_odm_doublebuffer_pending_clear)
                        tg->funcs->wait_odm_doublebuffer_pending_clear(tg);
+               if (tg->funcs->wait_otg_disable)
+                       tg->funcs->wait_otg_disable(tg);
        }
 
        /* ODM update may require to reprogram blank pattern for each OPP */
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 267ace4eef8a..f2de2cf23859 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
@@ -374,6 +374,7 @@ struct timing_generator_funcs {
        void (*wait_drr_doublebuffer_pending_clear)(struct timing_generator 
*tg);
        void (*set_long_vtotal)(struct timing_generator *optc, const struct 
long_vtotal_params *params);
        void (*wait_odm_doublebuffer_pending_clear)(struct timing_generator 
*tg);
+       void (*wait_otg_disable)(struct timing_generator *optc);
        bool (*get_optc_double_buffer_pending)(struct timing_generator *tg);
        bool (*get_otg_double_buffer_pending)(struct timing_generator *tg);
        bool (*get_pipe_update_pending)(struct timing_generator *tg);
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h 
b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h
index d159e3ed3bb3..ead92ad78a23 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h
@@ -62,6 +62,7 @@
        SF(OTG0_OTG_CONTROL, OTG_DISABLE_POINT_CNTL, mask_sh),\
        SF(OTG0_OTG_CONTROL, OTG_FIELD_NUMBER_CNTL, mask_sh),\
        SF(OTG0_OTG_CONTROL, OTG_OUT_MUX, mask_sh),\
+       SF(OTG0_OTG_CONTROL, OTG_CURRENT_MASTER_EN_STATE, mask_sh),\
        SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EN, mask_sh),\
        SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_LINE_NUM, mask_sh),\
        SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_POLARITY, mask_sh),\
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c 
b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c
index 72bff94cb57d..52d5ea98c86b 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c
@@ -162,6 +162,8 @@ static bool optc35_disable_crtc(struct timing_generator 
*optc)
        REG_WAIT(OTG_CLOCK_CONTROL,
                        OTG_BUSY, 0,
                        1, 100000);
+       REG_WAIT(OTG_CONTROL, OTG_CURRENT_MASTER_EN_STATE, 0, 1, 100000);
+
        optc1_clear_optc_underflow(optc);
 
        return true;
@@ -428,6 +430,21 @@ static void optc35_set_long_vtotal(
        }
 }
 
+static void optc35_wait_otg_disable(struct timing_generator *optc)
+{
+       struct optc *optc1;
+       uint32_t is_master_en;
+
+       if (!optc || !optc->ctx)
+               return;
+
+       optc1 = DCN10TG_FROM_TG(optc);
+
+       REG_GET(OTG_CONTROL, OTG_MASTER_EN, &is_master_en);
+       if (!is_master_en)
+               REG_WAIT(OTG_CLOCK_CONTROL, OTG_CURRENT_MASTER_EN_STATE, 0, 1, 
100000);
+}
+
 static const struct timing_generator_funcs dcn35_tg_funcs = {
                .validate_timing = optc1_validate_timing,
                .program_timing = optc1_program_timing,
@@ -479,6 +496,7 @@ static const struct timing_generator_funcs dcn35_tg_funcs = 
{
                .set_odm_bypass = optc32_set_odm_bypass,
                .set_odm_combine = optc35_set_odm_combine,
                .get_optc_source = optc2_get_optc_source,
+               .wait_otg_disable = optc35_wait_otg_disable,
                .set_h_timing_div_manual_mode = 
optc32_set_h_timing_div_manual_mode,
                .set_out_mux = optc3_set_out_mux,
                .set_drr_trigger_window = optc3_set_drr_trigger_window,
-- 
2.50.1

Reply via email to