aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/2502-drm-amd-display-add-global-master-update-lock-for-DC.patch
blob: c6a4b2faed60309be4ab8212f659f210097d4723 (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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
From 2b593b7c34424d6e62665667e89a5ea19da27457 Mon Sep 17 00:00:00 2001
From: Wenjing Liu <Wenjing.Liu@amd.com>
Date: Tue, 5 Mar 2019 19:28:10 -0500
Subject: [PATCH 2502/2940] drm/amd/display: add global master update lock for
 DCN2

[why]
when an update programming sequence requires both
front end and back end pipe to be updated synchronously,
a global update lock needs to be set to ensure that
we don't get a frame with only front end update but
not the back end update.

[how]
setup global lock parameters on enable_stream_timing.
enable global lock when pipe_control_lock_global is called.
disable global lock when pipe_control_lock is called.

Signed-off-by: Wenjing Liu <Wenjing.Liu@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 .../drm/amd/display/dc/dcn20/dcn20_hwseq.c    |  4 ++
 .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 63 ++++++++++++++++++-
 .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.h |  3 +
 .../amd/display/dc/inc/hw/timing_generator.h  |  2 +
 .../gpu/drm/amd/display/dc/inc/hw_sequencer.h |  1 +
 5 files changed, 72 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
index dc34ce28505c..fbcb4d860e7a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
@@ -727,6 +727,10 @@ enum dc_status dcn20_enable_stream_timing(
 			pipe_ctx->stream->signal,
 			true);
 
+	if (pipe_ctx->stream_res.tg->funcs->setup_global_lock)
+		pipe_ctx->stream_res.tg->funcs->setup_global_lock(
+				pipe_ctx->stream_res.tg);
+
 	/* program otg blank color */
 	color_space = stream->output_color_space;
 	color_space_to_black_color(dc, color_space, &black_color);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
index 43e71b4ab5e8..ea6a19063b22 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
@@ -330,6 +330,65 @@ void optc2_triplebuffer_unlock(struct timing_generator *optc)
 
 }
 
+
+void optc2_setup_global_lock(struct timing_generator *optc)
+{
+	struct optc *optc1 = DCN10TG_FROM_TG(optc);
+	uint32_t v_blank_start = 0;
+	uint32_t h_blank_start = 0, h_total = 0;
+
+	REG_SET(OTG_GLOBAL_CONTROL1, 0, MASTER_UPDATE_LOCK_DB_EN, 1);
+
+	REG_SET(OTG_GLOBAL_CONTROL2, 0, DIG_UPDATE_LOCATION, 20);
+
+	REG_GET(OTG_V_BLANK_START_END, OTG_V_BLANK_START, &v_blank_start);
+
+	REG_GET(OTG_H_BLANK_START_END, OTG_H_BLANK_START, &h_blank_start);
+
+	REG_GET(OTG_H_TOTAL, OTG_H_TOTAL, &h_total);
+	REG_UPDATE_2(OTG_GLOBAL_CONTROL1,
+			MASTER_UPDATE_LOCK_DB_X,
+			h_blank_start - 200 - 1,
+			MASTER_UPDATE_LOCK_DB_Y,
+			v_blank_start - 1);
+}
+
+void optc2_lock_global(struct timing_generator *optc)
+{
+	struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+	REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 1);
+
+	REG_SET(OTG_GLOBAL_CONTROL0, 0,
+			OTG_MASTER_UPDATE_LOCK_SEL, optc->inst);
+	REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
+			OTG_MASTER_UPDATE_LOCK, 1);
+
+	/* Should be fast, status does not update on maximus */
+	if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS)
+		REG_WAIT(OTG_MASTER_UPDATE_LOCK,
+				UPDATE_LOCK_STATUS, 1,
+				1, 10);
+}
+
+void optc2_lock(struct timing_generator *optc)
+{
+	struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+	REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 0);
+
+	REG_SET(OTG_GLOBAL_CONTROL0, 0,
+			OTG_MASTER_UPDATE_LOCK_SEL, optc->inst);
+	REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
+			OTG_MASTER_UPDATE_LOCK, 1);
+
+	/* Should be fast, status does not update on maximus */
+	if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS)
+		REG_WAIT(OTG_MASTER_UPDATE_LOCK,
+				UPDATE_LOCK_STATUS, 1,
+				1, 10);
+}
+
 void optc2_lock_doublebuffer_enable(struct timing_generator *optc)
 {
 	struct optc *optc1 = DCN10TG_FROM_TG(optc);
@@ -424,8 +483,10 @@ static struct timing_generator_funcs dcn20_tg_funcs = {
 		.triplebuffer_lock = optc2_triplebuffer_lock,
 		.triplebuffer_unlock = optc2_triplebuffer_unlock,
 		.disable_reset_trigger = optc1_disable_reset_trigger,
-		.lock = optc1_lock,
+		.lock = optc2_lock,
 		.unlock = optc1_unlock,
+		.lock_global = optc2_lock_global,
+		.setup_global_lock = optc2_setup_global_lock,
 		.lock_doublebuffer_enable = optc2_lock_doublebuffer_enable,
 		.lock_doublebuffer_disable = optc2_lock_doublebuffer_disable,
 		.enable_optc_clock = optc1_enable_optc_clock,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h
index d2651d846424..a21781332a06 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h
@@ -104,6 +104,9 @@ void optc2_get_optc_source(struct timing_generator *optc,
 
 void optc2_triplebuffer_lock(struct timing_generator *optc);
 void optc2_triplebuffer_unlock(struct timing_generator *optc);
+void optc2_lock(struct timing_generator *optc);
+void optc2_lock_global(struct timing_generator *optc);
+void optc2_setup_global_lock(struct timing_generator *optc);
 void optc2_lock_doublebuffer_disable(struct timing_generator *optc);
 void optc2_lock_doublebuffer_enable(struct timing_generator *optc);
 void optc2_program_manual_trigger(struct timing_generator *optc);
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 75314de83b3e..2dee10f7f1fe 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
@@ -184,8 +184,10 @@ struct timing_generator_funcs {
 	bool (*did_triggered_reset_occur)(struct timing_generator *tg);
 	void (*setup_global_swap_lock)(struct timing_generator *tg,
 							const struct dcp_gsl_params *gsl_params);
+	void (*setup_global_lock)(struct timing_generator *tg);
 	void (*unlock)(struct timing_generator *tg);
 	void (*lock)(struct timing_generator *tg);
+	void (*lock_global)(struct timing_generator *tg);
 	void (*lock_doublebuffer_disable)(struct timing_generator *tg);
 	void (*lock_doublebuffer_enable)(struct timing_generator *tg);
 #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
index a0227dedbdf6..13b113d0fe19 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
@@ -205,6 +205,7 @@ struct hw_sequencer_funcs {
 				struct dc *dc,
 				struct pipe_ctx *pipe,
 				bool lock);
+
 	void (*pipe_control_lock_global)(
 				struct dc *dc,
 				struct pipe_ctx *pipe,
-- 
2.17.1