diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.14.71/4460-drm-amd-display-underflow-blankscreen-recovery.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.14.71/4460-drm-amd-display-underflow-blankscreen-recovery.patch | 307 |
1 files changed, 307 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.14.71/4460-drm-amd-display-underflow-blankscreen-recovery.patch b/common/recipes-kernel/linux/linux-yocto-4.14.71/4460-drm-amd-display-underflow-blankscreen-recovery.patch new file mode 100644 index 00000000..429487ce --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.14.71/4460-drm-amd-display-underflow-blankscreen-recovery.patch @@ -0,0 +1,307 @@ +From 40113a9e16c7dad25263c1f3a37a1102f06ad21d Mon Sep 17 00:00:00 2001 +From: Charlene Liu <charlene.liu@amd.com> +Date: Wed, 18 Apr 2018 14:31:41 -0400 +Subject: [PATCH 4460/5725] drm/amd/display: underflow/blankscreen recovery + +[Description] +for any reason, if driver detects HUBP underflow, +if a debug option enabled to enable recovery. +it will kick in a sequence of recovery. + +Signed-off-by: Charlene Liu <charlene.liu@amd.com> +Reviewed-by: Tony Cheng <Tony.Cheng@amd.com> +Acked-by: Harry Wentland <harry.wentland@amd.com> +--- + drivers/gpu/drm/amd/display/dc/dc.h | 2 + + .../gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c | 8 ++ + .../gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h | 7 +- + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c | 24 ++++++ + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h | 3 + + .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 90 +++++++++++++++++++++- + .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 1 + + drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h | 2 + + 8 files changed, 135 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h +index 936adbf..28c6210 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc.h ++++ b/drivers/gpu/drm/amd/display/dc/dc.h +@@ -239,6 +239,8 @@ struct dc_debug { + bool az_endpoint_mute_only; + bool always_use_regamma; + bool p010_mpo_support; ++ bool recovery_enabled; ++ + }; + struct dc_state; + struct resource_pool; +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c +index b9fb14a..943143e 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c +@@ -476,6 +476,14 @@ void hubbub1_toggle_watermark_change_req(struct hubbub *hubbub) + DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, watermark_change_req); + } + ++void hubbub1_soft_reset(struct hubbub *hubbub, bool reset) ++{ ++ uint32_t reset_en = reset ? 1 : 0; ++ ++ REG_UPDATE(DCHUBBUB_SOFT_RESET, ++ DCHUBBUB_GLOBAL_SOFT_RESET, reset_en); ++} ++ + static bool hubbub1_dcc_support_swizzle( + enum swizzle_mode_values swizzle, + unsigned int bytes_per_element, +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h +index f479f54..6315a0e 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h +@@ -48,7 +48,8 @@ + SR(DCHUBBUB_ARB_DF_REQ_OUTSTAND),\ + SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ + SR(DCHUBBUB_TEST_DEBUG_INDEX), \ +- SR(DCHUBBUB_TEST_DEBUG_DATA) ++ SR(DCHUBBUB_TEST_DEBUG_DATA),\ ++ SR(DCHUBBUB_SOFT_RESET) + + #define HUBBUB_SR_WATERMARK_REG_LIST()\ + SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A),\ +@@ -105,6 +106,7 @@ struct dcn_hubbub_registers { + uint32_t DCHUBBUB_SDPIF_AGP_BOT; + uint32_t DCHUBBUB_SDPIF_AGP_TOP; + uint32_t DCHUBBUB_CRC_CTRL; ++ uint32_t DCHUBBUB_SOFT_RESET; + }; + + /* set field name */ +@@ -114,6 +116,7 @@ struct dcn_hubbub_registers { + + #define HUBBUB_MASK_SH_LIST_DCN(mask_sh)\ + HUBBUB_SF(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, mask_sh), \ ++ HUBBUB_SF(DCHUBBUB_SOFT_RESET, DCHUBBUB_GLOBAL_SOFT_RESET, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh), \ + HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh), \ +@@ -143,6 +146,7 @@ struct dcn_hubbub_registers { + type DCHUBBUB_ARB_SAT_LEVEL;\ + type DCHUBBUB_ARB_MIN_REQ_OUTSTAND;\ + type DCHUBBUB_GLOBAL_TIMER_REFDIV;\ ++ type DCHUBBUB_GLOBAL_SOFT_RESET; \ + type SDPIF_FB_TOP;\ + type SDPIF_FB_BASE;\ + type SDPIF_FB_OFFSET;\ +@@ -201,6 +205,7 @@ void hubbub1_toggle_watermark_change_req( + void hubbub1_wm_read_state(struct hubbub *hubbub, + struct dcn_hubbub_wm *wm); + ++void hubbub1_soft_reset(struct hubbub *hubbub, bool reset); + void hubbub1_construct(struct hubbub *hubbub, + struct dc_context *ctx, + const struct dcn_hubbub_registers *hubbub_regs, +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c +index 185f93b..d2ab78b 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c +@@ -78,6 +78,27 @@ static void hubp1_disconnect(struct hubp *hubp) + CURSOR_ENABLE, 0); + } + ++static void hubp1_disable_control(struct hubp *hubp, bool disable_hubp) ++{ ++ struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); ++ uint32_t disable = disable_hubp ? 1 : 0; ++ ++ REG_UPDATE(DCHUBP_CNTL, ++ HUBP_DISABLE, disable); ++} ++ ++static unsigned int hubp1_get_underflow_status(struct hubp *hubp) ++{ ++ uint32_t hubp_underflow = 0; ++ struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); ++ ++ REG_GET(DCHUBP_CNTL, ++ HUBP_UNDERFLOW_STATUS, ++ &hubp_underflow); ++ ++ return hubp_underflow; ++} ++ + static void hubp1_set_hubp_blank_en(struct hubp *hubp, bool blank) + { + struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); +@@ -1117,6 +1138,9 @@ static struct hubp_funcs dcn10_hubp_funcs = { + .hubp_clk_cntl = hubp1_clk_cntl, + .hubp_vtg_sel = hubp1_vtg_sel, + .hubp_read_state = hubp1_read_state, ++ .hubp_disable_control = hubp1_disable_control, ++ .hubp_get_underflow_status = hubp1_get_underflow_status, ++ + }; + + /*****************************************/ +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h +index fe9b8c4..af38403 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h +@@ -253,6 +253,7 @@ + HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_UNDERFLOW_STATUS, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, mask_sh),\ + HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_VTG_SEL, mask_sh),\ ++ HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_DISABLE, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_PIPES, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_BANKS, mask_sh),\ + HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, PIPE_INTERLEAVE, mask_sh),\ +@@ -421,6 +422,7 @@ + + #define DCN_HUBP_REG_FIELD_LIST(type) \ + type HUBP_BLANK_EN;\ ++ type HUBP_DISABLE;\ + type HUBP_TTU_DISABLE;\ + type HUBP_NO_OUTSTANDING_REQ;\ + type HUBP_VTG_SEL;\ +@@ -723,4 +725,5 @@ void hubp1_read_state(struct hubp *hubp); + + enum cursor_pitch hubp1_get_cursor_pitch(unsigned int pitch); + ++ + #endif +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 d3fc1a2..ada55a9 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 +@@ -762,6 +762,90 @@ static void reset_back_end_for_pipe( + pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst); + } + ++static bool dcn10_hw_wa_force_recovery(struct dc *dc) ++{ ++ struct hubp *hubp ; ++ unsigned int i; ++ bool need_recover = true; ++ ++ if (!dc->debug.recovery_enabled) ++ return false; ++ ++ for (i = 0; i < dc->res_pool->pipe_count; i++) { ++ struct pipe_ctx *pipe_ctx = ++ &dc->current_state->res_ctx.pipe_ctx[i]; ++ if (pipe_ctx != NULL) { ++ hubp = pipe_ctx->plane_res.hubp; ++ if (hubp != NULL) { ++ if (hubp->funcs->hubp_get_underflow_status(hubp) != 0) { ++ /* one pipe underflow, we will reset all the pipes*/ ++ need_recover = true; ++ } ++ } ++ } ++ } ++ if (!need_recover) ++ return false; ++ /* ++ DCHUBP_CNTL:HUBP_BLANK_EN=1 ++ DCHUBBUB_SOFT_RESET:DCHUBBUB_GLOBAL_SOFT_RESET=1 ++ DCHUBP_CNTL:HUBP_DISABLE=1 ++ DCHUBP_CNTL:HUBP_DISABLE=0 ++ DCHUBBUB_SOFT_RESET:DCHUBBUB_GLOBAL_SOFT_RESET=0 ++ DCSURF_PRIMARY_SURFACE_ADDRESS ++ DCHUBP_CNTL:HUBP_BLANK_EN=0 ++ */ ++ ++ for (i = 0; i < dc->res_pool->pipe_count; i++) { ++ struct pipe_ctx *pipe_ctx = ++ &dc->current_state->res_ctx.pipe_ctx[i]; ++ if (pipe_ctx != NULL) { ++ hubp = pipe_ctx->plane_res.hubp; ++ /*DCHUBP_CNTL:HUBP_BLANK_EN=1*/ ++ if (hubp != NULL) ++ hubp->funcs->set_hubp_blank_en(hubp, true); ++ } ++ } ++ /*DCHUBBUB_SOFT_RESET:DCHUBBUB_GLOBAL_SOFT_RESET=1*/ ++ hubbub1_soft_reset(dc->res_pool->hubbub, true); ++ ++ for (i = 0; i < dc->res_pool->pipe_count; i++) { ++ struct pipe_ctx *pipe_ctx = ++ &dc->current_state->res_ctx.pipe_ctx[i]; ++ if (pipe_ctx != NULL) { ++ hubp = pipe_ctx->plane_res.hubp; ++ /*DCHUBP_CNTL:HUBP_DISABLE=1*/ ++ if (hubp != NULL) ++ hubp->funcs->hubp_disable_control(hubp, true); ++ } ++ } ++ for (i = 0; i < dc->res_pool->pipe_count; i++) { ++ struct pipe_ctx *pipe_ctx = ++ &dc->current_state->res_ctx.pipe_ctx[i]; ++ if (pipe_ctx != NULL) { ++ hubp = pipe_ctx->plane_res.hubp; ++ /*DCHUBP_CNTL:HUBP_DISABLE=0*/ ++ if (hubp != NULL) ++ hubp->funcs->hubp_disable_control(hubp, true); ++ } ++ } ++ /*DCHUBBUB_SOFT_RESET:DCHUBBUB_GLOBAL_SOFT_RESET=0*/ ++ hubbub1_soft_reset(dc->res_pool->hubbub, false); ++ for (i = 0; i < dc->res_pool->pipe_count; i++) { ++ struct pipe_ctx *pipe_ctx = ++ &dc->current_state->res_ctx.pipe_ctx[i]; ++ if (pipe_ctx != NULL) { ++ hubp = pipe_ctx->plane_res.hubp; ++ /*DCHUBP_CNTL:HUBP_BLANK_EN=0*/ ++ if (hubp != NULL) ++ hubp->funcs->set_hubp_blank_en(hubp, true); ++ } ++ } ++ return true; ++ ++} ++ ++ + static void dcn10_verify_allow_pstate_change_high(struct dc *dc) + { + static bool should_log_hw_state; /* prevent hw state log by default */ +@@ -770,8 +854,12 @@ static void dcn10_verify_allow_pstate_change_high(struct dc *dc) + if (should_log_hw_state) { + dcn10_log_hw_state(dc); + } +- + BREAK_TO_DEBUGGER(); ++ if (dcn10_hw_wa_force_recovery(dc)) { ++ /*check again*/ ++ if (!hubbub1_verify_allow_pstate_change_high(dc->res_pool->hubbub)) ++ BREAK_TO_DEBUGGER(); ++ } + } + } + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +index 2c0a315..16c84e9 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +@@ -446,6 +446,7 @@ static const struct dc_debug debug_defaults_drv = { + .vsr_support = true, + .performance_trace = false, + .az_endpoint_mute_only = true, ++ .recovery_enabled = false, /*enable this by default after testing.*/ + }; + + static const struct dc_debug debug_defaults_diags = { +diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h +index 331f8ff..97df82c 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h +@@ -121,6 +121,8 @@ struct hubp_funcs { + void (*hubp_clk_cntl)(struct hubp *hubp, bool enable); + void (*hubp_vtg_sel)(struct hubp *hubp, uint32_t otg_inst); + void (*hubp_read_state)(struct hubp *hubp); ++ void (*hubp_disable_control)(struct hubp *hubp, bool disable_hubp); ++ unsigned int (*hubp_get_underflow_status)(struct hubp *hubp); + + }; + +-- +2.7.4 + |