aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/2015-drm-amd-display-Ensure-DRR-triggers-in-BP.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/2015-drm-amd-display-Ensure-DRR-triggers-in-BP.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/2015-drm-amd-display-Ensure-DRR-triggers-in-BP.patch317
1 files changed, 317 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/2015-drm-amd-display-Ensure-DRR-triggers-in-BP.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/2015-drm-amd-display-Ensure-DRR-triggers-in-BP.patch
new file mode 100644
index 00000000..c113d142
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/2015-drm-amd-display-Ensure-DRR-triggers-in-BP.patch
@@ -0,0 +1,317 @@
+From b686fdb7ba09010aed42f8ab33dc6156d564658b Mon Sep 17 00:00:00 2001
+From: Eryk Brol <eryk.brol@amd.com>
+Date: Tue, 23 Apr 2019 11:53:52 -0400
+Subject: [PATCH 2015/2940] drm/amd/display: Ensure DRR triggers in BP
+
+[Why]
+In the previous implementation DRR event sometimes came
+in during FP2 region which is a keep-out zone. This
+would cause the frame not to latch until the next frame
+which resulted in heavy flicker. To fix this we need
+to make sure that it triggers in the BP.
+
+[How]
+1. Remove DRR programming during flip
+2. Setup manual trigger for DRR event and trigger it
+after surface programming is complete
+
+Signed-off-by: Eryk Brol <eryk.brol@amd.com>
+Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
+Acked-by: Leo Li <sunpeng.li@amd.com>
+Signed-off-by: Chaudhary Amit Kumar <Chaudharyamit.Kumar@amd.com>
+---
+ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 23 ++++++++++---
+ drivers/gpu/drm/amd/display/dc/core/dc.c | 23 ++++++++-----
+ drivers/gpu/drm/amd/display/dc/dc_stream.h | 1 -
+ .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 4 +--
+ .../gpu/drm/amd/display/dc/dcn10/dcn10_optc.c | 32 +++++++++++++++++++
+ .../gpu/drm/amd/display/dc/dcn10/dcn10_optc.h | 31 ++++++++++++++----
+ .../amd/display/dc/inc/hw/timing_generator.h | 3 ++
+ 7 files changed, 95 insertions(+), 22 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 378aa4251347..27f2618c58aa 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -5241,6 +5241,10 @@ static void update_freesync_state_on_stream(
+ amdgpu_dm_vrr_active(new_crtc_state)) {
+ mod_freesync_handle_v_update(dm->freesync_module,
+ new_stream, &vrr_params);
++ /* Need to call this before the frame ends. */
++ dc_stream_adjust_vmin_vmax(dm->dc,
++ new_crtc_state->stream,
++ &vrr_params.adjust);
+ }
+ }
+
+@@ -5579,11 +5583,6 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
+ }
+
+ if (acrtc_state->stream) {
+-
+- if (acrtc_state->freesync_timing_changed)
+- bundle->stream_update.adjust =
+- &acrtc_state->stream->adjust;
+-
+ if (acrtc_state->freesync_vrr_info_changed)
+ bundle->stream_update.vrr_infopacket =
+ &acrtc_state->stream->vrr_infopacket;
+@@ -5604,6 +5603,20 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
+ if (acrtc_state->abm_level != dm_old_crtc_state->abm_level)
+ bundle->stream_update.abm_level = &acrtc_state->abm_level;
+
++ /*
++ * If FreeSync state on the stream has changed then we need to
++ * re-adjust the min/max bounds now that DC doesn't handle this
++ * as part of commit.
++ */
++ if (amdgpu_dm_vrr_active(dm_old_crtc_state) !=
++ amdgpu_dm_vrr_active(acrtc_state)) {
++ spin_lock_irqsave(&pcrtc->dev->event_lock, flags);
++ dc_stream_adjust_vmin_vmax(
++ dm->dc, acrtc_state->stream,
++ &acrtc_state->vrr_params.adjust);
++ spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags);
++ }
++
+ mutex_lock(&dm->dc_lock);
+ dc_commit_updates_for_stream(dm->dc,
+ bundle->surface_updates,
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
+index 0327d891c1d8..45d11459d738 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
+@@ -269,7 +269,7 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
+ for (i = 0; i < MAX_PIPES; i++) {
+ struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+
+- if (pipe->stream == stream && pipe->stream_res.stream_enc) {
++ if (pipe->stream == stream && pipe->stream_res.tg) {
+ pipe->stream->adjust = *adjust;
+ dc->hwss.set_drr(&pipe,
+ 1,
+@@ -1757,13 +1757,6 @@ static void commit_planes_do_stream_update(struct dc *dc,
+ pipe_ctx->stream &&
+ pipe_ctx->stream == stream) {
+
+- /* Fast update*/
+- // VRR program can be done as part of FAST UPDATE
+- if (stream_update->adjust)
+- dc->hwss.set_drr(&pipe_ctx, 1,
+- stream_update->adjust->v_total_min,
+- stream_update->adjust->v_total_max);
+-
+ if (stream_update->periodic_interrupt0 &&
+ dc->hwss.setup_periodic_interrupt)
+ dc->hwss.setup_periodic_interrupt(pipe_ctx, VLINE0);
+@@ -1920,6 +1913,20 @@ static void commit_planes_for_stream(struct dc *dc,
+ }
+ dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false);
+ }
++
++ // Fire manual trigger
++ for (i = 0; i < dc->res_pool->pipe_count; i++) {
++ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
++
++ if (pipe_ctx->top_pipe ||
++ !pipe_ctx->stream ||
++ pipe_ctx->stream != stream ||
++ !srf_updates[i].flip_addr)
++ continue;
++
++ if (pipe_ctx->stream_res.tg->funcs->program_manual_trigger)
++ pipe_ctx->stream_res.tg->funcs->program_manual_trigger(pipe_ctx->stream_res.tg);
++ }
+ }
+
+ void dc_commit_updates_for_stream(struct dc *dc,
+diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h
+index 189bdab929a5..4da138ded8b7 100644
+--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
++++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
+@@ -172,7 +172,6 @@ struct dc_stream_update {
+ struct periodic_interrupt_config *periodic_interrupt0;
+ struct periodic_interrupt_config *periodic_interrupt1;
+
+- struct dc_crtc_timing_adjust *adjust;
+ struct dc_info_packet *vrr_infopacket;
+ struct dc_info_packet *vsc_infopacket;
+ struct dc_info_packet *vsp_infopacket;
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+index fd0c7999d489..06c01a93616e 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+@@ -2505,8 +2505,8 @@ static void set_drr(struct pipe_ctx **pipe_ctx,
+ {
+ int i = 0;
+ struct drr_params params = {0};
+- // DRR should set trigger event to monitor surface update event
+- unsigned int event_triggers = 0x80;
++ // DRR set trigger event mapped to OTG_TRIG_A (bit 11) for manual control flow
++ unsigned int event_triggers = 0x800;
+
+ params.vertical_total_max = vmax;
+ params.vertical_total_min = vmin;
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c
+index 13fe638c9d9c..dd84fea16aea 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c
+@@ -799,6 +799,32 @@ void optc1_set_static_screen_control(
+ OTG_STATIC_SCREEN_FRAME_COUNT, 2);
+ }
+
++void optc1_setup_manual_trigger(struct timing_generator *optc)
++{
++ struct optc *optc1 = DCN10TG_FROM_TG(optc);
++
++ REG_SET(OTG_GLOBAL_CONTROL2, 0,
++ MANUAL_FLOW_CONTROL_SEL, optc->inst);
++
++ REG_SET_8(OTG_TRIGA_CNTL, 0,
++ OTG_TRIGA_SOURCE_SELECT, 22,
++ OTG_TRIGA_SOURCE_PIPE_SELECT, optc->inst,
++ OTG_TRIGA_RISING_EDGE_DETECT_CNTL, 1,
++ OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, 0,
++ OTG_TRIGA_POLARITY_SELECT, 0,
++ OTG_TRIGA_FREQUENCY_SELECT, 0,
++ OTG_TRIGA_DELAY, 0,
++ OTG_TRIGA_CLEAR, 1);
++}
++
++void optc1_program_manual_trigger(struct timing_generator *optc)
++{
++ struct optc *optc1 = DCN10TG_FROM_TG(optc);
++
++ REG_SET(OTG_MANUAL_FLOW_CONTROL, 0,
++ MANUAL_FLOW_CONTROL, 1);
++}
++
+
+ /**
+ *****************************************************************************
+@@ -831,6 +857,10 @@ void optc1_set_drr(
+ OTG_FORCE_LOCK_ON_EVENT, 0,
+ OTG_SET_V_TOTAL_MIN_MASK_EN, 0,
+ OTG_SET_V_TOTAL_MIN_MASK, 0);
++
++ // Setup manual flow control for EOF via TRIG_A
++ optc->funcs->setup_manual_trigger(optc);
++
+ } else {
+ REG_UPDATE_4(OTG_V_TOTAL_CONTROL,
+ OTG_SET_V_TOTAL_MIN_MASK, 0,
+@@ -1466,6 +1496,8 @@ static const struct timing_generator_funcs dcn10_tg_funcs = {
+ .get_crc = optc1_get_crc,
+ .configure_crc = optc1_configure_crc,
+ .set_vtg_params = optc1_set_vtg_params,
++ .program_manual_trigger = optc1_program_manual_trigger,
++ .setup_manual_trigger = optc1_setup_manual_trigger
+ };
+
+ void dcn10_timing_generator_init(struct optc *optc1)
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
+index 70fd56fa56c5..444c56c8104f 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
+@@ -85,13 +85,17 @@
+ SRI(OTG_CRC0_WINDOWA_Y_CONTROL, OTG, inst),\
+ SRI(OTG_CRC0_WINDOWB_X_CONTROL, OTG, inst),\
+ SRI(OTG_CRC0_WINDOWB_Y_CONTROL, OTG, inst),\
+- SR(GSL_SOURCE_SELECT)
++ SR(GSL_SOURCE_SELECT),\
++ SRI(OTG_GLOBAL_CONTROL2, OTG, inst),\
++ SRI(OTG_TRIGA_MANUAL_TRIG, OTG, inst)
++
+
+ #define TG_COMMON_REG_LIST_DCN1_0(inst) \
+ TG_COMMON_REG_LIST_DCN(inst),\
+ SRI(OTG_TEST_PATTERN_PARAMETERS, OTG, inst),\
+ SRI(OTG_TEST_PATTERN_CONTROL, OTG, inst),\
+- SRI(OTG_TEST_PATTERN_COLOR, OTG, inst)
++ SRI(OTG_TEST_PATTERN_COLOR, OTG, inst),\
++ SRI(OTG_MANUAL_FLOW_CONTROL, OTG, inst)
+
+
+ struct dcn_optc_registers {
+@@ -125,6 +129,8 @@ struct dcn_optc_registers {
+ uint32_t OTG_V_TOTAL_MIN;
+ uint32_t OTG_V_TOTAL_CONTROL;
+ uint32_t OTG_TRIGA_CNTL;
++ uint32_t OTG_TRIGA_MANUAL_TRIG;
++ uint32_t OTG_MANUAL_FLOW_CONTROL;
+ uint32_t OTG_FORCE_COUNT_NOW_CNTL;
+ uint32_t OTG_STATIC_SCREEN_CONTROL;
+ uint32_t OTG_STATUS_FRAME_COUNT;
+@@ -215,6 +221,11 @@ struct dcn_optc_registers {
+ SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_PIPE_SELECT, mask_sh),\
+ SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_RISING_EDGE_DETECT_CNTL, mask_sh),\
+ SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, mask_sh),\
++ SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_POLARITY_SELECT, mask_sh),\
++ SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FREQUENCY_SELECT, mask_sh),\
++ SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_DELAY, mask_sh),\
++ SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_CLEAR, mask_sh),\
++ SF(OTG0_OTG_TRIGA_MANUAL_TRIG, OTG_TRIGA_MANUAL_TRIG, mask_sh),\
+ SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_EVENT_MASK, mask_sh),\
+ SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_FRAME_COUNT, mask_sh),\
+ SF(OTG0_OTG_STATUS_FRAME_COUNT, OTG_FRAME_COUNT, mask_sh),\
+@@ -271,8 +282,8 @@ struct dcn_optc_registers {
+ SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_END, mask_sh),\
+ SF(GSL_SOURCE_SELECT, GSL0_READY_SOURCE_SEL, mask_sh),\
+ SF(GSL_SOURCE_SELECT, GSL1_READY_SOURCE_SEL, mask_sh),\
+- SF(GSL_SOURCE_SELECT, GSL2_READY_SOURCE_SEL, mask_sh)
+-
++ SF(GSL_SOURCE_SELECT, GSL2_READY_SOURCE_SEL, mask_sh),\
++ SF(OTG0_OTG_GLOBAL_CONTROL2, MANUAL_FLOW_CONTROL_SEL, mask_sh)
+
+ #define TG_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\
+ TG_COMMON_MASK_SH_LIST_DCN(mask_sh),\
+@@ -287,7 +298,8 @@ struct dcn_optc_registers {
+ SF(OTG0_OTG_TEST_PATTERN_CONTROL, OTG_TEST_PATTERN_COLOR_FORMAT, mask_sh),\
+ SF(OTG0_OTG_TEST_PATTERN_COLOR, OTG_TEST_PATTERN_MASK, mask_sh),\
+ SF(OTG0_OTG_TEST_PATTERN_COLOR, OTG_TEST_PATTERN_DATA, mask_sh),\
+- SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SRC_SEL, mask_sh)
++ SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SRC_SEL, mask_sh),\
++ SF(OTG0_OTG_MANUAL_FLOW_CONTROL, MANUAL_FLOW_CONTROL, mask_sh),\
+
+ #define TG_REG_FIELD_LIST_DCN1_0(type) \
+ type VSTARTUP_START;\
+@@ -343,6 +355,11 @@ struct dcn_optc_registers {
+ type OTG_TRIGA_SOURCE_PIPE_SELECT;\
+ type OTG_TRIGA_RISING_EDGE_DETECT_CNTL;\
+ type OTG_TRIGA_FALLING_EDGE_DETECT_CNTL;\
++ type OTG_TRIGA_POLARITY_SELECT;\
++ type OTG_TRIGA_FREQUENCY_SELECT;\
++ type OTG_TRIGA_DELAY;\
++ type OTG_TRIGA_CLEAR;\
++ type OTG_TRIGA_MANUAL_TRIG;\
+ type OTG_STATIC_SCREEN_EVENT_MASK;\
+ type OTG_STATIC_SCREEN_FRAME_COUNT;\
+ type OTG_FRAME_COUNT;\
+@@ -421,7 +438,9 @@ struct dcn_optc_registers {
+ type OTG_CRC0_WINDOWB_Y_END;\
+ type GSL0_READY_SOURCE_SEL;\
+ type GSL1_READY_SOURCE_SEL;\
+- type GSL2_READY_SOURCE_SEL;
++ type GSL2_READY_SOURCE_SEL;\
++ type MANUAL_FLOW_CONTROL;\
++ type MANUAL_FLOW_CONTROL_SEL;
+
+
+ #define TG_REG_FIELD_LIST(type) \
+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 0b8c6896581f..a89d0cf59cca 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
+@@ -238,6 +238,9 @@ struct timing_generator_funcs {
+ bool (*get_crc)(struct timing_generator *tg,
+ uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb);
+
++ void (*program_manual_trigger)(struct timing_generator *optc);
++ void (*setup_manual_trigger)(struct timing_generator *optc);
++
+ void (*set_vtg_params)(struct timing_generator *optc,
+ const struct dc_crtc_timing *dc_crtc_timing);
+ };
+--
+2.17.1
+