aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.14.71/0667-drm-amd-display-separate-plane-disable-sequence.patch
blob: 12a021dedd5f01fff92858829243264549663680 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
From 9ce9dde42caa76521b7b104425d377a8ea0caedb Mon Sep 17 00:00:00 2001
From: Tony Cheng <tony.cheng@amd.com>
Date: Sun, 23 Jul 2017 15:22:47 -0400
Subject: [PATCH 0667/4131] drm/amd/display: separate plane disable sequence

- disconnect:  trigger hw to disconnect plane on next vsync
- disable: disables HW block and disable clocks
- power_down: kill power

Signed-off-by: Tony Cheng <tony.cheng@amd.com>
Reviewed-by: Eric Yang <eric.yang2@amd.com>
Acked-by: Harry Wentland <Harry.Wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c  | 83 ++++++++++++++++------
 1 file changed, 61 insertions(+), 22 deletions(-)

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 c25a392..3a0fcaa 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
@@ -815,8 +815,8 @@ static void reset_back_end_for_pipe(
 					pipe_ctx->pipe_idx, pipe_ctx->tg->inst);
 }
 
-static void plane_atomic_stop(
-		struct core_dc *dc,
+/* trigger HW to start disconnect plane from stream on the next vsync */
+static void plane_atomic_disconnect(struct core_dc *dc,
 		int fe_idx)
 {
 	struct mpcc_cfg mpcc_cfg;
@@ -824,6 +824,12 @@ static void plane_atomic_stop(
 	struct transform *xfm = dc->res_pool->transforms[fe_idx];
 	struct mpcc *mpcc = dc->res_pool->mpcc[fe_idx];
 	struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id];
+	unsigned int opp_id = mpcc->opp_id;
+	int opp_id_cached = mpcc->opp_id;
+
+	/*Already reset*/
+	if (opp_id == 0xf)
+		return;
 
 	mi->funcs->dcc_control(mi, false, false);
 
@@ -833,11 +839,19 @@ static void plane_atomic_stop(
 	mpcc_cfg.top_of_tree = tg->inst == mpcc->inst;
 	mpcc->funcs->set(mpcc, &mpcc_cfg);
 
+	/* Hack to preserve old opp_id for plane_atomic_disable
+	 * to find the correct otg */
+	mpcc->opp_id = opp_id_cached;
+
+	/* todo:call remove pipe from tree */
+	/* flag mpcc idle pending */
+
 	xfm->funcs->transform_reset(xfm);
 }
 
-static void reset_front_end(
-		struct core_dc *dc,
+/* disable HW used by plane.
+ * note:  cannot disable until disconnect is complete */
+static void plane_atomic_disable(struct core_dc *dc,
 		int fe_idx)
 {
 	struct dce_hwseq *hws = dc->hwseq;
@@ -846,24 +860,9 @@ static void reset_front_end(
 	struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id];
 	unsigned int opp_id = mpcc->opp_id;
 
-	/*Already reset*/
 	if (opp_id == 0xf)
 		return;
 
-	tg->funcs->lock(tg);
-
-	plane_atomic_stop(dc, fe_idx);
-
-	REG_UPDATE(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_CLEAR, 1);
-	tg->funcs->unlock(tg);
-
-	if (dc->public.debug.sanity_checks)
-		verify_allow_pstate_change_high(dc->hwseq);
-
-	if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS)
-		REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst],
-				VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, 20000, 200000);
-
 	mpcc->funcs->wait_for_idle(mpcc);
 
 	mi->funcs->set_blank(mi, true);
@@ -880,14 +879,54 @@ static void reset_front_end(
 		REG_UPDATE(OPP_PIPE_CONTROL[opp_id],
 				OPP_PIPE_CLOCK_EN, 0);
 
-	dm_logger_write(dc->ctx->logger, LOG_DC,
-					"Reset front end %d\n",
-					fe_idx);
+	mpcc->opp_id = 0xf;
 
 	if (dc->public.debug.sanity_checks)
 		verify_allow_pstate_change_high(dc->hwseq);
 }
 
+/* kill power to plane hw
+ * note: cannot power down until plane is disable
+static void plane_atomic_power_down()
+{
+
+}
+*/
+
+static void reset_front_end(
+		struct core_dc *dc,
+		int fe_idx)
+{
+	struct dce_hwseq *hws = dc->hwseq;
+	struct mpcc *mpcc = dc->res_pool->mpcc[fe_idx];
+	struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id];
+	unsigned int opp_id = mpcc->opp_id;
+
+	/*Already reset*/
+	if (opp_id == 0xf)
+		return;
+
+	tg->funcs->lock(tg);
+
+	plane_atomic_disconnect(dc, fe_idx);
+
+	REG_UPDATE(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_CLEAR, 1);
+	tg->funcs->unlock(tg);
+
+	if (dc->public.debug.sanity_checks)
+		verify_allow_pstate_change_high(dc->hwseq);
+
+	if (tg->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS)
+		REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst],
+				VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, 20000, 200000);
+
+	plane_atomic_disable(dc, fe_idx);
+
+	dm_logger_write(dc->ctx->logger, LOG_DC,
+					"Reset front end %d\n",
+					fe_idx);
+}
+
 static void dcn10_power_down_fe(struct core_dc *dc, int fe_idx)
 {
 	struct dce_hwseq *hws = dc->hwseq;
-- 
2.7.4