drm/amd/display: Wait for all pending cleared before full update
authorAlvin Lee <Alvin.Lee2@amd.com>
Mon, 9 Sep 2024 20:24:05 +0000 (16:24 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 1 Oct 2024 21:30:47 +0000 (17:30 -0400)
[Description]
Before every full update we must wait for all pending updates to be
cleared - this is particularly important for minimal transitions
because if we don't wait for pending cleared, it will be as if
there was no minimal transition at all. In OTG we must read 3 different
status registers for pending cleared, one specifically for OTG updates,
one specifically for OPTC updates, and the last for surface related
updates.

Reviewed-by: Dillon Varone <dillon.varone@amd.com>
Signed-off-by: Alvin Lee <Alvin.Lee2@amd.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
24 files changed:
drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.h
drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_init.c
drivers/gpu/drm/amd/display/dc/hwss/dcn301/dcn301_init.c
drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c
drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h
drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.h
drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.c
drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.h
drivers/gpu/drm/amd/display/dc/optc/dcn301/dcn301_optc.c
drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.h
drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.h
drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c
drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h
drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.h
drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c
drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.h
drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h
drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h

index 7ee2be8..2cb9253 100644 (file)
@@ -1071,8 +1071,13 @@ void hwss_wait_for_outstanding_hw_updates(struct dc *dc, struct dc_state *dc_con
                if (!pipe_ctx->stream)
                        continue;
 
-               if (pipe_ctx->stream_res.tg->funcs->wait_drr_doublebuffer_pending_clear)
-                       pipe_ctx->stream_res.tg->funcs->wait_drr_doublebuffer_pending_clear(pipe_ctx->stream_res.tg);
+               /* For full update we must wait for all double buffer updates, not just DRR updates. This
+                * is particularly important for minimal transitions. Only check for OTG_MASTER pipes,
+                * as non-OTG Master pipes share the same OTG as
+                */
+               if (resource_is_pipe_type(pipe_ctx, OTG_MASTER) && dc->hwss.wait_for_all_pending_updates) {
+                       dc->hwss.wait_for_all_pending_updates(pipe_ctx);
+               }
 
                hubp = pipe_ctx->plane_res.hubp;
                if (!hubp)
index a80c085..b383ed8 100644 (file)
@@ -2255,9 +2255,9 @@ void dcn20_post_unlock_program_front_end(
                        struct timing_generator *tg = pipe->stream_res.tg;
 
 
-                       if (tg->funcs->get_double_buffer_pending) {
+                       if (tg->funcs->get_optc_double_buffer_pending) {
                                for (j = 0; j < TIMEOUT_FOR_PIPE_ENABLE_US / polling_interval_us
-                               && tg->funcs->get_double_buffer_pending(tg); j++)
+                               && tg->funcs->get_optc_double_buffer_pending(tg); j++)
                                        udelay(polling_interval_us);
                        }
                }
index bded335..bf9b5da 100644 (file)
@@ -1185,3 +1185,30 @@ void dcn30_prepare_bandwidth(struct dc *dc,
        if (!dc->clk_mgr->clks.fw_based_mclk_switching)
                dc_dmub_srv_p_state_delegate(dc, false, context);
 }
+
+void dcn30_wait_for_all_pending_updates(const struct pipe_ctx *pipe_ctx)
+{
+       struct timing_generator *tg = pipe_ctx->stream_res.tg;
+       bool pending_updates = false;
+       unsigned int i;
+
+       if (tg && tg->funcs->is_tg_enabled(tg)) {
+               // Poll for 100ms maximum
+               for (i = 0; i < 100000; i++) {
+                       pending_updates = false;
+                       if (tg->funcs->get_optc_double_buffer_pending)
+                               pending_updates |= tg->funcs->get_optc_double_buffer_pending(tg);
+
+                       if (tg->funcs->get_otg_double_buffer_pending)
+                               pending_updates |= tg->funcs->get_otg_double_buffer_pending(tg);
+
+                       if (tg->funcs->get_pipe_update_pending && pipe_ctx->plane_state)
+                               pending_updates |= tg->funcs->get_pipe_update_pending(tg);
+
+                       if (!pending_updates)
+                               break;
+
+                       udelay(1);
+               }
+       }
+}
index 6a153e7..4b90b78 100644 (file)
@@ -96,4 +96,6 @@ void dcn30_set_hubp_blank(const struct dc *dc,
 void dcn30_prepare_bandwidth(struct dc *dc,
        struct dc_state *context);
 
+void dcn30_wait_for_all_pending_updates(const struct pipe_ctx *pipe_ctx);
+
 #endif /* __DC_HWSS_DCN30_H__ */
index 2a8dc40..0e8d32e 100644 (file)
@@ -108,7 +108,8 @@ static const struct hw_sequencer_funcs dcn30_funcs = {
        .set_disp_pattern_generator = dcn30_set_disp_pattern_generator,
        .get_dcc_en_bits = dcn10_get_dcc_en_bits,
        .update_visual_confirm_color = dcn10_update_visual_confirm_color,
-       .is_abm_supported = dcn21_is_abm_supported
+       .is_abm_supported = dcn21_is_abm_supported,
+       .wait_for_all_pending_updates = dcn30_wait_for_all_pending_updates,
 };
 
 static const struct hwseq_private_funcs dcn30_private_funcs = {
index 93e49d8..780ce4c 100644 (file)
@@ -107,6 +107,7 @@ static const struct hw_sequencer_funcs dcn301_funcs = {
        .optimize_pwr_state = dcn21_optimize_pwr_state,
        .exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state,
        .update_visual_confirm_color = dcn10_update_visual_confirm_color,
+       .wait_for_all_pending_updates = dcn30_wait_for_all_pending_updates,
 };
 
 static const struct hwseq_private_funcs dcn301_private_funcs = {
index 3422b56..8e0946f 100644 (file)
@@ -121,6 +121,7 @@ static const struct hw_sequencer_funcs dcn32_funcs = {
        .is_pipe_topology_transition_seamless = dcn32_is_pipe_topology_transition_seamless,
        .calculate_pix_rate_divider = dcn32_calculate_pix_rate_divider,
        .program_outstanding_updates = dcn32_program_outstanding_updates,
+       .wait_for_all_pending_updates = dcn30_wait_for_all_pending_updates,
 };
 
 static const struct hwseq_private_funcs dcn32_private_funcs = {
index a2ca072..73a632b 100644 (file)
@@ -100,6 +100,7 @@ static const struct hw_sequencer_funcs dcn401_funcs = {
        .fams2_update_config = dcn401_fams2_update_config,
        .fams2_global_control_lock_fast = dcn401_fams2_global_control_lock_fast,
        .program_outstanding_updates = dcn401_program_outstanding_updates,
+       .wait_for_all_pending_updates = dcn30_wait_for_all_pending_updates,
 };
 
 static const struct hwseq_private_funcs dcn401_private_funcs = {
index ac92056..b8c47e4 100644 (file)
@@ -462,6 +462,7 @@ struct hw_sequencer_funcs {
        void (*program_outstanding_updates)(struct dc *dc,
                        struct dc_state *context);
        void (*setup_hpo_hw_control)(const struct dce_hwseq *hws, bool enable);
+       void (*wait_for_all_pending_updates)(const struct pipe_ctx *pipe_ctx);
 };
 
 void color_space_to_black_color(
index 3d4c8bd..4e08e80 100644 (file)
@@ -342,7 +342,9 @@ 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);
-       bool (*get_double_buffer_pending)(struct timing_generator *tg);
+       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);
 };
 
 #endif
index b7a57f9..40757f2 100644 (file)
@@ -202,6 +202,7 @@ struct dcn_optc_registers {
        uint32_t OPTC_CLOCK_CONTROL;
        uint32_t OPTC_WIDTH_CONTROL2;
        uint32_t OTG_PSTATE_REGISTER;
+       uint32_t OTG_PIPE_UPDATE_STATUS;
 };
 
 #define TG_COMMON_MASK_SH_LIST_DCN(mask_sh)\
@@ -566,6 +567,12 @@ struct dcn_optc_registers {
        type OTG_H_TIMING_DIV_MODE_DB_UPDATE_PENDING;\
        type OPTC_DOUBLE_BUFFER_PENDING;\
 
+#define TG_REG_FIELD_LIST_DCN2_0(type) \
+       type OTG_FLIP_PENDING;\
+       type OTG_DC_REG_UPDATE_PENDING;\
+       type OTG_CURSOR_UPDATE_PENDING;\
+       type OTG_VUPDATE_KEEPOUT_STATUS;\
+
 #define TG_REG_FIELD_LIST_DCN3_2(type) \
        type OTG_H_TIMING_DIV_MODE_MANUAL;
 
@@ -600,6 +607,7 @@ struct dcn_optc_registers {
 
 struct dcn_optc_shift {
        TG_REG_FIELD_LIST(uint8_t)
+       TG_REG_FIELD_LIST_DCN2_0(uint8_t)
        TG_REG_FIELD_LIST_DCN3_2(uint8_t)
        TG_REG_FIELD_LIST_DCN3_5(uint8_t)
        TG_REG_FIELD_LIST_DCN401(uint8_t)
@@ -607,6 +615,7 @@ struct dcn_optc_shift {
 
 struct dcn_optc_mask {
        TG_REG_FIELD_LIST(uint32_t)
+       TG_REG_FIELD_LIST_DCN2_0(uint32_t)
        TG_REG_FIELD_LIST_DCN3_2(uint32_t)
        TG_REG_FIELD_LIST_DCN3_5(uint32_t)
        TG_REG_FIELD_LIST_DCN401(uint32_t)
index 364034b..928e110 100644 (file)
@@ -43,7 +43,8 @@
        SRI(OPTC_MEMORY_CONFIG, ODM, inst),\
        SR(DWB_SOURCE_SELECT),\
        SRI(OTG_MANUAL_FLOW_CONTROL, OTG, inst), \
-       SRI(OTG_DRR_CONTROL, OTG, inst)
+       SRI(OTG_DRR_CONTROL, OTG, inst),\
+       SRI(OTG_PIPE_UPDATE_STATUS, OTG, inst)
 
 #define TG_COMMON_MASK_SH_LIST_DCN2_0(mask_sh)\
        TG_COMMON_MASK_SH_LIST_DCN(mask_sh),\
        SF(OTG0_OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, mask_sh),\
        SF(OTG0_OTG_GLOBAL_CONTROL2, DIG_UPDATE_LOCATION, mask_sh),\
        SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_RANGE_TIMING_DBUF_UPDATE_MODE, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_FLIP_PENDING, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_DC_REG_UPDATE_PENDING, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_CURSOR_UPDATE_PENDING, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_VUPDATE_KEEPOUT_STATUS, mask_sh),\
        SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_START_X, mask_sh),\
        SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_END_X, mask_sh), \
        SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_START_Y, mask_sh),\
index abcd03d..4c95c09 100644 (file)
@@ -271,6 +271,48 @@ void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_c
        optc1->opp_count = opp_cnt;
 }
 
+/* OTG status register that indicates OPTC update is pending */
+bool optc3_get_optc_double_buffer_pending(struct timing_generator *optc)
+{
+       struct optc *optc1 = DCN10TG_FROM_TG(optc);
+       uint32_t update_pending = 0;
+
+       REG_GET(OPTC_INPUT_GLOBAL_CONTROL,
+                       OPTC_DOUBLE_BUFFER_PENDING,
+                       &update_pending);
+
+       return (update_pending == 1);
+}
+
+/* OTG status register that indicates OTG update is pending */
+bool optc3_get_otg_update_pending(struct timing_generator *optc)
+{
+       struct optc *optc1 = DCN10TG_FROM_TG(optc);
+       uint32_t update_pending = 0;
+
+       REG_GET(OTG_DOUBLE_BUFFER_CONTROL,
+                       OTG_UPDATE_PENDING,
+                       &update_pending);
+
+       return (update_pending == 1);
+}
+
+/* OTG status register that indicates surface update is pending */
+bool optc3_get_pipe_update_pending(struct timing_generator *optc)
+{
+       struct optc *optc1 = DCN10TG_FROM_TG(optc);
+       uint32_t flip_pending = 0;
+       uint32_t dc_update_pending = 0;
+
+       REG_GET_2(OTG_PIPE_UPDATE_STATUS,
+                       OTG_FLIP_PENDING,
+                       &flip_pending,
+                       OTG_DC_REG_UPDATE_PENDING,
+                       &dc_update_pending);
+
+       return (flip_pending == 1 || dc_update_pending == 1);
+}
+
 /**
  * optc3_set_timing_double_buffer() - DRR double buffering control
  *
@@ -375,6 +417,9 @@ static struct timing_generator_funcs dcn30_tg_funcs = {
                .get_hw_timing = optc1_get_hw_timing,
                .wait_drr_doublebuffer_pending_clear = optc3_wait_drr_doublebuffer_pending_clear,
                .is_two_pixels_per_container = optc1_is_two_pixels_per_container,
+               .get_optc_double_buffer_pending = optc3_get_optc_double_buffer_pending,
+               .get_otg_double_buffer_pending = optc3_get_otg_update_pending,
+               .get_pipe_update_pending = optc3_get_pipe_update_pending,
 };
 
 void dcn30_timing_generator_init(struct optc *optc1)
index bda974d..e2303f9 100644 (file)
        SRI(OPTC_BYTES_PER_PIXEL, ODM, inst),\
        SRI(OPTC_WIDTH_CONTROL, ODM, inst),\
        SRI(OPTC_MEMORY_CONFIG, ODM, inst),\
-       SR(DWB_SOURCE_SELECT)
+       SR(DWB_SOURCE_SELECT),\
+       SRI(OTG_PIPE_UPDATE_STATUS, OTG, inst)
 
 #define DCN30_VTOTAL_REGS_SF(mask_sh)
 
        SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\
        SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, mask_sh),\
        SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, mask_sh),\
+       SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_DOUBLE_BUFFER_PENDING, mask_sh),\
        SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\
        SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\
        SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh),\
        SF(OTG0_OTG_DRR_V_TOTAL_CHANGE, OTG_DRR_V_TOTAL_CHANGE_LIMIT, mask_sh),\
        SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE, mask_sh),\
        SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_PENDING, mask_sh),\
-       SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_MODE, mask_sh)
+       SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_MODE, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_FLIP_PENDING, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_DC_REG_UPDATE_PENDING, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_CURSOR_UPDATE_PENDING, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_VUPDATE_KEEPOUT_STATUS, mask_sh),\
 
 void dcn30_timing_generator_init(struct optc *optc1);
 
@@ -356,4 +362,7 @@ void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_c
 void optc3_wait_drr_doublebuffer_pending_clear(struct timing_generator *optc);
 void optc3_tg_init(struct timing_generator *optc);
 void optc3_set_vtotal_min_max(struct timing_generator *optc, int vtotal_min, int vtotal_max);
+bool optc3_get_optc_double_buffer_pending(struct timing_generator *optc);
+bool optc3_get_otg_update_pending(struct timing_generator *optc);
+bool optc3_get_pipe_update_pending(struct timing_generator *optc);
 #endif /* __DC_OPTC_DCN30_H__ */
index 1a22ae8..d7a45ef 100644 (file)
@@ -169,6 +169,9 @@ static struct timing_generator_funcs dcn30_tg_funcs = {
                .get_hw_timing = optc1_get_hw_timing,
                .wait_drr_doublebuffer_pending_clear = optc3_wait_drr_doublebuffer_pending_clear,
                .is_two_pixels_per_container = optc1_is_two_pixels_per_container,
+               .get_optc_double_buffer_pending = optc3_get_optc_double_buffer_pending,
+               .get_otg_double_buffer_pending = optc3_get_otg_update_pending,
+               .get_pipe_update_pending = optc3_get_pipe_update_pending,
 };
 
 void dcn301_timing_generator_init(struct optc *optc1)
index 30b81a4..fbbe86d 100644 (file)
@@ -99,7 +99,8 @@
        SRI(OPTC_MEMORY_CONFIG, ODM, inst),\
        SRI(OTG_CRC_CNTL2, OTG, inst),\
        SR(DWB_SOURCE_SELECT),\
-       SRI(OTG_DRR_CONTROL, OTG, inst)
+       SRI(OTG_DRR_CONTROL, OTG, inst),\
+       SRI(OTG_PIPE_UPDATE_STATUS, OTG, inst)
 
 #define OPTC_COMMON_MASK_SH_LIST_DCN3_1(mask_sh)\
        SF(OTG0_OTG_VSTARTUP_PARAM, VSTARTUP_START, mask_sh),\
        SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_COMBINE_MODE, mask_sh),\
        SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_SPLIT_MODE, mask_sh),\
        SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_FORMAT, mask_sh),\
-       SF(OTG0_OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, mask_sh)
+       SF(OTG0_OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_FLIP_PENDING, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_DC_REG_UPDATE_PENDING, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_CURSOR_UPDATE_PENDING, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_VUPDATE_KEEPOUT_STATUS, mask_sh),\
 
 void dcn31_timing_generator_init(struct optc *optc1);
 
index 99c098e..0ff72b9 100644 (file)
@@ -98,7 +98,8 @@
        SRI(OPTC_BYTES_PER_PIXEL, ODM, inst),\
        SRI(OPTC_WIDTH_CONTROL, ODM, inst),\
        SRI(OPTC_MEMORY_CONFIG, ODM, inst),\
-       SRI(OTG_DRR_CONTROL, OTG, inst)
+       SRI(OTG_DRR_CONTROL, OTG, inst),\
+       SRI(OTG_PIPE_UPDATE_STATUS, OTG, inst)
 
 #define OPTC_COMMON_MASK_SH_LIST_DCN3_14(mask_sh)\
        SF(OTG0_OTG_VSTARTUP_PARAM, VSTARTUP_START, mask_sh),\
        SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE, mask_sh),\
        SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE_MANUAL, mask_sh),\
        SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_MODE, mask_sh),\
-       SF(OTG0_OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, mask_sh)
+       SF(OTG0_OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_FLIP_PENDING, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_DC_REG_UPDATE_PENDING, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_CURSOR_UPDATE_PENDING, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_VUPDATE_KEEPOUT_STATUS, mask_sh),\
 
 void dcn314_timing_generator_init(struct optc *optc1);
 
index 00094f0..c217f65 100644 (file)
@@ -297,18 +297,6 @@ static void optc32_set_drr(
        optc32_setup_manual_trigger(optc);
 }
 
-bool optc32_get_double_buffer_pending(struct timing_generator *optc)
-{
-       struct optc *optc1 = DCN10TG_FROM_TG(optc);
-       uint32_t update_pending = 0;
-
-       REG_GET(OPTC_INPUT_GLOBAL_CONTROL,
-                       OPTC_DOUBLE_BUFFER_PENDING,
-                       &update_pending);
-
-       return (update_pending == 1);
-}
-
 static struct timing_generator_funcs dcn32_tg_funcs = {
                .validate_timing = optc1_validate_timing,
                .program_timing = optc1_program_timing,
@@ -373,7 +361,9 @@ static struct timing_generator_funcs dcn32_tg_funcs = {
                .setup_manual_trigger = optc2_setup_manual_trigger,
                .get_hw_timing = optc1_get_hw_timing,
                .is_two_pixels_per_container = optc1_is_two_pixels_per_container,
-               .get_double_buffer_pending = optc32_get_double_buffer_pending,
+               .get_optc_double_buffer_pending = optc3_get_optc_double_buffer_pending,
+               .get_otg_double_buffer_pending = optc3_get_otg_update_pending,
+               .get_pipe_update_pending = optc3_get_pipe_update_pending,
 };
 
 void dcn32_timing_generator_init(struct optc *optc1)
index 665d7c5..0b0964a 100644 (file)
        SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE, mask_sh),\
        SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE_MANUAL, mask_sh),\
        SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_MODE, mask_sh),\
-       SF(OTG0_OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, mask_sh)
+       SF(OTG0_OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_FLIP_PENDING, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_DC_REG_UPDATE_PENDING, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_CURSOR_UPDATE_PENDING, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_VUPDATE_KEEPOUT_STATUS, mask_sh)
 
 void dcn32_timing_generator_init(struct optc *optc1);
 void optc32_set_h_timing_div_manual_mode(struct timing_generator *optc, bool manual_mode);
@@ -185,6 +189,5 @@ void optc32_get_odm_combine_segments(struct timing_generator *tg, int *odm_combi
 void optc32_set_odm_bypass(struct timing_generator *optc,
                const struct dc_crtc_timing *dc_crtc_timing);
 void optc32_wait_odm_doublebuffer_pending_clear(struct timing_generator *tg);
-bool optc32_get_double_buffer_pending(struct timing_generator *optc);
 
 #endif /* __DC_OPTC_DCN32_H__ */
index d077e23..be749ab 100644 (file)
        SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL_READBACK, OTG_CRC1_WINDOWB_Y_END_READBACK, mask_sh),\
        SF(OPTC_CLOCK_CONTROL, OPTC_FGCG_REP_DIS, mask_sh),\
        SF(OTG0_OTG_V_COUNT_STOP_CONTROL, OTG_V_COUNT_STOP, mask_sh),\
-       SF(OTG0_OTG_V_COUNT_STOP_CONTROL2, OTG_V_COUNT_STOP_TIMER, mask_sh)
+       SF(OTG0_OTG_V_COUNT_STOP_CONTROL2, OTG_V_COUNT_STOP_TIMER, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_FLIP_PENDING, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_DC_REG_UPDATE_PENDING, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_CURSOR_UPDATE_PENDING, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_VUPDATE_KEEPOUT_STATUS, mask_sh)
 
 void dcn35_timing_generator_init(struct optc *optc1);
 
index a5d6a7d..db670fc 100644 (file)
@@ -493,7 +493,9 @@ static struct timing_generator_funcs dcn401_tg_funcs = {
                .setup_manual_trigger = optc2_setup_manual_trigger,
                .get_hw_timing = optc1_get_hw_timing,
                .is_two_pixels_per_container = optc1_is_two_pixels_per_container,
-               .get_double_buffer_pending = optc32_get_double_buffer_pending,
+               .get_optc_double_buffer_pending = optc3_get_optc_double_buffer_pending,
+               .get_otg_double_buffer_pending = optc3_get_otg_update_pending,
+               .get_pipe_update_pending = optc3_get_pipe_update_pending,
 };
 
 void dcn401_timing_generator_init(struct optc *optc1)
index bb13a64..1be8957 100644 (file)
        SF(OTG0_OTG_PSTATE_REGISTER, OTG_PSTATE_KEEPOUT_START, mask_sh),\
        SF(OTG0_OTG_PSTATE_REGISTER, OTG_PSTATE_EXTEND, mask_sh),\
        SF(OTG0_OTG_PSTATE_REGISTER, OTG_UNBLANK, mask_sh),\
-       SF(OTG0_OTG_PSTATE_REGISTER, OTG_PSTATE_ALLOW_WIDTH_MIN, mask_sh)
+       SF(OTG0_OTG_PSTATE_REGISTER, OTG_PSTATE_ALLOW_WIDTH_MIN, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_FLIP_PENDING, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_DC_REG_UPDATE_PENDING, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_CURSOR_UPDATE_PENDING, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_VUPDATE_KEEPOUT_STATUS, mask_sh)
 
 void dcn401_timing_generator_init(struct optc *optc1);
 
index 7901792..86c6e5e 100644 (file)
@@ -1054,7 +1054,8 @@ unsigned int dcn32_calculate_mall_ways_from_bytes(const struct dc *dc, unsigned
       SRI_ARR(OPTC_BYTES_PER_PIXEL, ODM, inst),                                \
       SRI_ARR(OPTC_WIDTH_CONTROL, ODM, inst),                                  \
       SRI_ARR(OPTC_MEMORY_CONFIG, ODM, inst),                                  \
-      SRI_ARR(OTG_DRR_CONTROL, OTG, inst)
+      SRI_ARR(OTG_DRR_CONTROL, OTG, inst),                                     \
+         SRI_ARR(OTG_PIPE_UPDATE_STATUS, OTG, inst)
 
 /* HUBP */
 
index 514d1ce..bdafa74 100644 (file)
@@ -536,8 +536,9 @@ void dcn401_prepare_mcache_programming(struct dc *dc, struct dc_state *context);
        SRI_ARR(OPTC_WIDTH_CONTROL, ODM, inst),                                  \
        SRI_ARR(OPTC_WIDTH_CONTROL2, ODM, inst),                                 \
        SRI_ARR(OPTC_MEMORY_CONFIG, ODM, inst),                                  \
-       SRI_ARR(OTG_DRR_CONTROL, OTG, inst),                                                                             \
-       SRI_ARR(OTG_PSTATE_REGISTER, OTG, inst)
+       SRI_ARR(OTG_DRR_CONTROL, OTG, inst),                                     \
+       SRI_ARR(OTG_PSTATE_REGISTER, OTG, inst),                                 \
+       SRI_ARR(OTG_PIPE_UPDATE_STATUS, OTG, inst)
 
 /* HUBBUB */
 #define HUBBUB_REG_LIST_DCN4_01_RI(id)                                       \