aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCharlene Liu <charlene.liu@amd.com>2018-04-18 14:31:41 -0400
committerAlex Deucher <alexander.deucher@amd.com>2018-05-18 17:08:23 -0400
commit3ba43a59927fbde07414393dfc2b6753cb233e00 (patch)
tree2723a35205e084a28704b87cfd610f1d0183f342
parent0002d3ac8aadcb2850475557de32234b447ba502 (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>
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c24
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c90
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h2
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};
243struct dc_state; 245struct dc_state;
244struct resource_pool; 246struct 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
479void 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
479static bool hubbub1_dcc_support_swizzle( 487static 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(
201void hubbub1_wm_read_state(struct hubbub *hubbub, 205void hubbub1_wm_read_state(struct hubbub *hubbub,
202 struct dcn_hubbub_wm *wm); 206 struct dcn_hubbub_wm *wm);
203 207
208void hubbub1_soft_reset(struct hubbub *hubbub, bool reset);
204void hubbub1_construct(struct hubbub *hubbub, 209void 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
81static 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
90static 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
81static void hubp1_set_hubp_blank_en(struct hubp *hubp, bool blank) 102static 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
724enum cursor_pitch hubp1_get_cursor_pitch(unsigned int pitch); 726enum 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
750static 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
750static void dcn10_verify_allow_pstate_change_high(struct dc *dc) 834static 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
451static const struct dc_debug debug_defaults_diags = { 452static 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