diff options
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.patch | 317 |
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 + |