diff options
author | Charlene Liu <charlene.liu@amd.com> | 2018-04-18 14:31:41 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2018-05-18 17:08:23 -0400 |
commit | 3ba43a59927fbde07414393dfc2b6753cb233e00 (patch) | |
tree | 2723a35205e084a28704b87cfd610f1d0183f342 | |
parent | 0002d3ac8aadcb2850475557de32234b447ba502 (diff) |
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>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
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 cd4f4341cb53..1c39c9996a04 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 { | |||
239 | bool az_endpoint_mute_only; | 239 | bool az_endpoint_mute_only; |
240 | bool always_use_regamma; | 240 | bool always_use_regamma; |
241 | bool p010_mpo_support; | 241 | bool p010_mpo_support; |
242 | bool recovery_enabled; | ||
243 | |||
242 | }; | 244 | }; |
243 | struct dc_state; | 245 | struct dc_state; |
244 | struct resource_pool; | 246 | 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 b9fb14a3224b..943143efbb82 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) | |||
476 | DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, watermark_change_req); | 476 | DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, watermark_change_req); |
477 | } | 477 | } |
478 | 478 | ||
479 | void hubbub1_soft_reset(struct hubbub *hubbub, bool reset) | ||
480 | { | ||
481 | uint32_t reset_en = reset ? 1 : 0; | ||
482 | |||
483 | REG_UPDATE(DCHUBBUB_SOFT_RESET, | ||
484 | DCHUBBUB_GLOBAL_SOFT_RESET, reset_en); | ||
485 | } | ||
486 | |||
479 | static bool hubbub1_dcc_support_swizzle( | 487 | static bool hubbub1_dcc_support_swizzle( |
480 | enum swizzle_mode_values swizzle, | 488 | enum swizzle_mode_values swizzle, |
481 | unsigned int bytes_per_element, | 489 | 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 f479f54e5bb2..6315a0e6b0d6 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 @@ | |||
48 | SR(DCHUBBUB_ARB_DF_REQ_OUTSTAND),\ | 48 | SR(DCHUBBUB_ARB_DF_REQ_OUTSTAND),\ |
49 | SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ | 49 | SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ |
50 | SR(DCHUBBUB_TEST_DEBUG_INDEX), \ | 50 | SR(DCHUBBUB_TEST_DEBUG_INDEX), \ |
51 | SR(DCHUBBUB_TEST_DEBUG_DATA) | 51 | SR(DCHUBBUB_TEST_DEBUG_DATA),\ |
52 | SR(DCHUBBUB_SOFT_RESET) | ||
52 | 53 | ||
53 | #define HUBBUB_SR_WATERMARK_REG_LIST()\ | 54 | #define HUBBUB_SR_WATERMARK_REG_LIST()\ |
54 | SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A),\ | 55 | SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A),\ |
@@ -105,6 +106,7 @@ struct dcn_hubbub_registers { | |||
105 | uint32_t DCHUBBUB_SDPIF_AGP_BOT; | 106 | uint32_t DCHUBBUB_SDPIF_AGP_BOT; |
106 | uint32_t DCHUBBUB_SDPIF_AGP_TOP; | 107 | uint32_t DCHUBBUB_SDPIF_AGP_TOP; |
107 | uint32_t DCHUBBUB_CRC_CTRL; | 108 | uint32_t DCHUBBUB_CRC_CTRL; |
109 | uint32_t DCHUBBUB_SOFT_RESET; | ||
108 | }; | 110 | }; |
109 | 111 | ||
110 | /* set field name */ | 112 | /* set field name */ |
@@ -114,6 +116,7 @@ struct dcn_hubbub_registers { | |||
114 | 116 | ||
115 | #define HUBBUB_MASK_SH_LIST_DCN(mask_sh)\ | 117 | #define HUBBUB_MASK_SH_LIST_DCN(mask_sh)\ |
116 | HUBBUB_SF(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, mask_sh), \ | 118 | HUBBUB_SF(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, mask_sh), \ |
119 | HUBBUB_SF(DCHUBBUB_SOFT_RESET, DCHUBBUB_GLOBAL_SOFT_RESET, mask_sh), \ | ||
117 | HUBBUB_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh), \ | 120 | HUBBUB_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh), \ |
118 | HUBBUB_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh), \ | 121 | HUBBUB_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh), \ |
119 | HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh), \ | 122 | HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh), \ |
@@ -143,6 +146,7 @@ struct dcn_hubbub_registers { | |||
143 | type DCHUBBUB_ARB_SAT_LEVEL;\ | 146 | type DCHUBBUB_ARB_SAT_LEVEL;\ |
144 | type DCHUBBUB_ARB_MIN_REQ_OUTSTAND;\ | 147 | type DCHUBBUB_ARB_MIN_REQ_OUTSTAND;\ |
145 | type DCHUBBUB_GLOBAL_TIMER_REFDIV;\ | 148 | type DCHUBBUB_GLOBAL_TIMER_REFDIV;\ |
149 | type DCHUBBUB_GLOBAL_SOFT_RESET; \ | ||
146 | type SDPIF_FB_TOP;\ | 150 | type SDPIF_FB_TOP;\ |
147 | type SDPIF_FB_BASE;\ | 151 | type SDPIF_FB_BASE;\ |
148 | type SDPIF_FB_OFFSET;\ | 152 | type SDPIF_FB_OFFSET;\ |
@@ -201,6 +205,7 @@ void hubbub1_toggle_watermark_change_req( | |||
201 | void hubbub1_wm_read_state(struct hubbub *hubbub, | 205 | void hubbub1_wm_read_state(struct hubbub *hubbub, |
202 | struct dcn_hubbub_wm *wm); | 206 | struct dcn_hubbub_wm *wm); |
203 | 207 | ||
208 | void hubbub1_soft_reset(struct hubbub *hubbub, bool reset); | ||
204 | void hubbub1_construct(struct hubbub *hubbub, | 209 | void hubbub1_construct(struct hubbub *hubbub, |
205 | struct dc_context *ctx, | 210 | struct dc_context *ctx, |
206 | const struct dcn_hubbub_registers *hubbub_regs, | 211 | 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 185f93bda41b..d2ab78b35a7a 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) | |||
78 | CURSOR_ENABLE, 0); | 78 | CURSOR_ENABLE, 0); |
79 | } | 79 | } |
80 | 80 | ||
81 | static void hubp1_disable_control(struct hubp *hubp, bool disable_hubp) | ||
82 | { | ||
83 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); | ||
84 | uint32_t disable = disable_hubp ? 1 : 0; | ||
85 | |||
86 | REG_UPDATE(DCHUBP_CNTL, | ||
87 | HUBP_DISABLE, disable); | ||
88 | } | ||
89 | |||
90 | static unsigned int hubp1_get_underflow_status(struct hubp *hubp) | ||
91 | { | ||
92 | uint32_t hubp_underflow = 0; | ||
93 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); | ||
94 | |||
95 | REG_GET(DCHUBP_CNTL, | ||
96 | HUBP_UNDERFLOW_STATUS, | ||
97 | &hubp_underflow); | ||
98 | |||
99 | return hubp_underflow; | ||
100 | } | ||
101 | |||
81 | static void hubp1_set_hubp_blank_en(struct hubp *hubp, bool blank) | 102 | static void hubp1_set_hubp_blank_en(struct hubp *hubp, bool blank) |
82 | { | 103 | { |
83 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); | 104 | struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); |
@@ -1117,6 +1138,9 @@ static struct hubp_funcs dcn10_hubp_funcs = { | |||
1117 | .hubp_clk_cntl = hubp1_clk_cntl, | 1138 | .hubp_clk_cntl = hubp1_clk_cntl, |
1118 | .hubp_vtg_sel = hubp1_vtg_sel, | 1139 | .hubp_vtg_sel = hubp1_vtg_sel, |
1119 | .hubp_read_state = hubp1_read_state, | 1140 | .hubp_read_state = hubp1_read_state, |
1141 | .hubp_disable_control = hubp1_disable_control, | ||
1142 | .hubp_get_underflow_status = hubp1_get_underflow_status, | ||
1143 | |||
1120 | }; | 1144 | }; |
1121 | 1145 | ||
1122 | /*****************************************/ | 1146 | /*****************************************/ |
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 fe9b8c4a91ca..af384034398f 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 @@ | |||
253 | HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_UNDERFLOW_STATUS, mask_sh),\ | 253 | HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_UNDERFLOW_STATUS, mask_sh),\ |
254 | HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, mask_sh),\ | 254 | HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_NO_OUTSTANDING_REQ, mask_sh),\ |
255 | HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_VTG_SEL, mask_sh),\ | 255 | HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_VTG_SEL, mask_sh),\ |
256 | HUBP_SF(HUBP0_DCHUBP_CNTL, HUBP_DISABLE, mask_sh),\ | ||
256 | HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_PIPES, mask_sh),\ | 257 | HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_PIPES, mask_sh),\ |
257 | HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_BANKS, mask_sh),\ | 258 | HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, NUM_BANKS, mask_sh),\ |
258 | HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, PIPE_INTERLEAVE, mask_sh),\ | 259 | HUBP_SF(HUBP0_DCSURF_ADDR_CONFIG, PIPE_INTERLEAVE, mask_sh),\ |
@@ -421,6 +422,7 @@ | |||
421 | 422 | ||
422 | #define DCN_HUBP_REG_FIELD_LIST(type) \ | 423 | #define DCN_HUBP_REG_FIELD_LIST(type) \ |
423 | type HUBP_BLANK_EN;\ | 424 | type HUBP_BLANK_EN;\ |
425 | type HUBP_DISABLE;\ | ||
424 | type HUBP_TTU_DISABLE;\ | 426 | type HUBP_TTU_DISABLE;\ |
425 | type HUBP_NO_OUTSTANDING_REQ;\ | 427 | type HUBP_NO_OUTSTANDING_REQ;\ |
426 | type HUBP_VTG_SEL;\ | 428 | type HUBP_VTG_SEL;\ |
@@ -723,4 +725,5 @@ void hubp1_read_state(struct hubp *hubp); | |||
723 | 725 | ||
724 | enum cursor_pitch hubp1_get_cursor_pitch(unsigned int pitch); | 726 | enum cursor_pitch hubp1_get_cursor_pitch(unsigned int pitch); |
725 | 727 | ||
728 | |||
726 | #endif | 729 | #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 50bd7548e230..be8820d8a2e6 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 | |||
@@ -747,6 +747,90 @@ static void reset_back_end_for_pipe( | |||
747 | pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst); | 747 | pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst); |
748 | } | 748 | } |
749 | 749 | ||
750 | static bool dcn10_hw_wa_force_recovery(struct dc *dc) | ||
751 | { | ||
752 | struct hubp *hubp ; | ||
753 | unsigned int i; | ||
754 | bool need_recover = true; | ||
755 | |||
756 | if (!dc->debug.recovery_enabled) | ||
757 | return false; | ||
758 | |||
759 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | ||
760 | struct pipe_ctx *pipe_ctx = | ||
761 | &dc->current_state->res_ctx.pipe_ctx[i]; | ||
762 | if (pipe_ctx != NULL) { | ||
763 | hubp = pipe_ctx->plane_res.hubp; | ||
764 | if (hubp != NULL) { | ||
765 | if (hubp->funcs->hubp_get_underflow_status(hubp) != 0) { | ||
766 | /* one pipe underflow, we will reset all the pipes*/ | ||
767 | need_recover = true; | ||
768 | } | ||
769 | } | ||
770 | } | ||
771 | } | ||
772 | if (!need_recover) | ||
773 | return false; | ||
774 | /* | ||
775 | DCHUBP_CNTL:HUBP_BLANK_EN=1 | ||
776 | DCHUBBUB_SOFT_RESET:DCHUBBUB_GLOBAL_SOFT_RESET=1 | ||
777 | DCHUBP_CNTL:HUBP_DISABLE=1 | ||
778 | DCHUBP_CNTL:HUBP_DISABLE=0 | ||
779 | DCHUBBUB_SOFT_RESET:DCHUBBUB_GLOBAL_SOFT_RESET=0 | ||
780 | DCSURF_PRIMARY_SURFACE_ADDRESS | ||
781 | DCHUBP_CNTL:HUBP_BLANK_EN=0 | ||
782 | */ | ||
783 | |||
784 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | ||
785 | struct pipe_ctx *pipe_ctx = | ||
786 | &dc->current_state->res_ctx.pipe_ctx[i]; | ||
787 | if (pipe_ctx != NULL) { | ||
788 | hubp = pipe_ctx->plane_res.hubp; | ||
789 | /*DCHUBP_CNTL:HUBP_BLANK_EN=1*/ | ||
790 | if (hubp != NULL) | ||
791 | hubp->funcs->set_hubp_blank_en(hubp, true); | ||
792 | } | ||
793 | } | ||
794 | /*DCHUBBUB_SOFT_RESET:DCHUBBUB_GLOBAL_SOFT_RESET=1*/ | ||
795 | hubbub1_soft_reset(dc->res_pool->hubbub, true); | ||
796 | |||
797 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | ||
798 | struct pipe_ctx *pipe_ctx = | ||
799 | &dc->current_state->res_ctx.pipe_ctx[i]; | ||
800 | if (pipe_ctx != NULL) { | ||
801 | hubp = pipe_ctx->plane_res.hubp; | ||
802 | /*DCHUBP_CNTL:HUBP_DISABLE=1*/ | ||
803 | if (hubp != NULL) | ||
804 | hubp->funcs->hubp_disable_control(hubp, true); | ||
805 | } | ||
806 | } | ||
807 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | ||
808 | struct pipe_ctx *pipe_ctx = | ||
809 | &dc->current_state->res_ctx.pipe_ctx[i]; | ||
810 | if (pipe_ctx != NULL) { | ||
811 | hubp = pipe_ctx->plane_res.hubp; | ||
812 | /*DCHUBP_CNTL:HUBP_DISABLE=0*/ | ||
813 | if (hubp != NULL) | ||
814 | hubp->funcs->hubp_disable_control(hubp, true); | ||
815 | } | ||
816 | } | ||
817 | /*DCHUBBUB_SOFT_RESET:DCHUBBUB_GLOBAL_SOFT_RESET=0*/ | ||
818 | hubbub1_soft_reset(dc->res_pool->hubbub, false); | ||
819 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | ||
820 | struct pipe_ctx *pipe_ctx = | ||
821 | &dc->current_state->res_ctx.pipe_ctx[i]; | ||
822 | if (pipe_ctx != NULL) { | ||
823 | hubp = pipe_ctx->plane_res.hubp; | ||
824 | /*DCHUBP_CNTL:HUBP_BLANK_EN=0*/ | ||
825 | if (hubp != NULL) | ||
826 | hubp->funcs->set_hubp_blank_en(hubp, true); | ||
827 | } | ||
828 | } | ||
829 | return true; | ||
830 | |||
831 | } | ||
832 | |||
833 | |||
750 | static void dcn10_verify_allow_pstate_change_high(struct dc *dc) | 834 | static void dcn10_verify_allow_pstate_change_high(struct dc *dc) |
751 | { | 835 | { |
752 | static bool should_log_hw_state; /* prevent hw state log by default */ | 836 | static bool should_log_hw_state; /* prevent hw state log by default */ |
@@ -755,8 +839,12 @@ static void dcn10_verify_allow_pstate_change_high(struct dc *dc) | |||
755 | if (should_log_hw_state) { | 839 | if (should_log_hw_state) { |
756 | dcn10_log_hw_state(dc); | 840 | dcn10_log_hw_state(dc); |
757 | } | 841 | } |
758 | |||
759 | BREAK_TO_DEBUGGER(); | 842 | BREAK_TO_DEBUGGER(); |
843 | if (dcn10_hw_wa_force_recovery(dc)) { | ||
844 | /*check again*/ | ||
845 | if (!hubbub1_verify_allow_pstate_change_high(dc->res_pool->hubbub)) | ||
846 | BREAK_TO_DEBUGGER(); | ||
847 | } | ||
760 | } | 848 | } |
761 | } | 849 | } |
762 | 850 | ||
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 2c0a3150bf2d..16c84e9ee33b 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 = { | |||
446 | .vsr_support = true, | 446 | .vsr_support = true, |
447 | .performance_trace = false, | 447 | .performance_trace = false, |
448 | .az_endpoint_mute_only = true, | 448 | .az_endpoint_mute_only = true, |
449 | .recovery_enabled = false, /*enable this by default after testing.*/ | ||
449 | }; | 450 | }; |
450 | 451 | ||
451 | static const struct dc_debug debug_defaults_diags = { | 452 | 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 331f8ff57ed7..97df82cddf82 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 { | |||
121 | void (*hubp_clk_cntl)(struct hubp *hubp, bool enable); | 121 | void (*hubp_clk_cntl)(struct hubp *hubp, bool enable); |
122 | void (*hubp_vtg_sel)(struct hubp *hubp, uint32_t otg_inst); | 122 | void (*hubp_vtg_sel)(struct hubp *hubp, uint32_t otg_inst); |
123 | void (*hubp_read_state)(struct hubp *hubp); | 123 | void (*hubp_read_state)(struct hubp *hubp); |
124 | void (*hubp_disable_control)(struct hubp *hubp, bool disable_hubp); | ||
125 | unsigned int (*hubp_get_underflow_status)(struct hubp *hubp); | ||
124 | 126 | ||
125 | }; | 127 | }; |
126 | 128 | ||