aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0510-drm-amd-display-RV-stereo-support.patch
blob: 3614c0f94e02f653ddcf02c4abccf933c9083e95 (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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
From a940b5d4286edc8561639b49f4f09cce8832b631 Mon Sep 17 00:00:00 2001
From: Vitaly Prosyak <vitaly.prosyak@amd.com>
Date: Wed, 7 Jun 2017 12:23:59 -0500
Subject: [PATCH 0510/4131] drm/amd/display: RV stereo support

HDMI frame pack and DP frame alternate in band

Signed-off-by: Vitaly Prosyak <vitaly.prosyak@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>
---
 drivers/gpu/drm/amd/display/dc/dc.h                |  21 ++-
 .../amd/display/dc/dcn10/dcn10_timing_generator.c  | 184 ++++++++++-----------
 .../amd/display/dc/dcn10/dcn10_timing_generator.h  |   5 +
 .../drm/amd/display/dc/inc/hw/timing_generator.h   |  12 ++
 drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h  |   4 +
 5 files changed, 124 insertions(+), 102 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index e08e532..fb86808 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -361,6 +361,7 @@ struct dc_surface_status {
 	struct dc_plane_address requested_address;
 	struct dc_plane_address current_address;
 	bool is_flip_pending;
+	bool is_right_eye;
 };
 
 /*
@@ -476,7 +477,7 @@ struct dc_stream {
 	const struct dc_transfer_func *out_transfer_func;
 	struct colorspace_transform gamut_remap_matrix;
 	struct csc_transform csc_color_matrix;
-
+	enum view_3d_format view_format;
 	/* TODO: custom INFO packets */
 	/* TODO: ABM info (DMCU) */
 	/* TODO: PSR info */
@@ -591,6 +592,15 @@ bool dc_commit_streams(
 		struct dc *dc,
 		const struct dc_stream *streams[],
 		uint8_t stream_count);
+/*
+ * Enable stereo when commit_streams is not required,
+ * for example, frame alternate.
+ */
+bool dc_enable_stereo(
+	struct dc *dc,
+	struct validate_context *context,
+	const struct dc_stream *streams[],
+	uint8_t stream_count);
 
 /**
  * Create a new default stream for the requested sink
@@ -777,6 +787,14 @@ struct dc_container_id {
 	unsigned short productCode;
 };
 
+struct stereo_3d_features {
+	bool supported			;
+	bool allTimings			;
+	bool cloneMode			;
+	bool scaling			;
+	bool singleFrameSWPacked;
+};
+
 /*
  * The sink structure contains EDID and other display device properties
  */
@@ -788,6 +806,7 @@ struct dc_sink {
 	uint32_t dongle_max_pix_clk;
 	bool converter_disable_audio;
 	void *priv;
+	struct stereo_3d_features features_3d[TIMING_3D_FORMAT_MAX];
 };
 
 void dc_sink_retain(const struct dc_sink *sink);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c
index c5a636c..bc3934d 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.c
@@ -78,112 +78,22 @@ static void dcn10_program_global_sync(
 			VREADY_OFFSET, tg->dlg_otg_param.vready_offset);
 }
 
-struct crtc_stereo_flags {
-	uint8_t PROGRAM_STEREO         :1;
-	uint8_t PROGRAM_POLARITY       :1;
-	uint8_t RIGHT_EYE_POLARITY     :1;
-	uint8_t FRAME_PACKED           :1;
-	uint8_t DISABLE_STEREO_DP_SYNC :1;
-};
-
-static void dcn10_enable_stereo(struct timing_generator *tg,
-		const struct crtc_stereo_flags *flags,
-		const struct dc_crtc_timing *timing)
-{
-	struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg);
-
-	uint32_t active_width = timing->h_addressable;
-	uint32_t space1_size = timing->v_total - timing->v_addressable;
-
-	if (flags) {
-		uint32_t stereo_en = flags->FRAME_PACKED == 0 ? 1 : 0;
-
-		if (flags->PROGRAM_STEREO)
-			REG_UPDATE_3(OTG_STEREO_CONTROL,
-					OTG_STEREO_EN, stereo_en,
-					OTG_STEREO_SYNC_OUTPUT_LINE_NUM, 0,
-					OTG_STEREO_SYNC_OUTPUT_POLARITY, 0);
-
-		if (flags->PROGRAM_POLARITY)
-			REG_UPDATE(OTG_STEREO_CONTROL,
-					OTG_STEREO_EYE_FLAG_POLARITY,
-					flags->RIGHT_EYE_POLARITY == 0 ? 0:1);
-
-		if (flags->DISABLE_STEREO_DP_SYNC)
-			REG_UPDATE(OTG_STEREO_CONTROL,
-					OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, 1);
-
-		if (flags->PROGRAM_STEREO && flags->FRAME_PACKED)
-			REG_UPDATE_3(OTG_3D_STRUCTURE_CONTROL,
-					OTG_3D_STRUCTURE_EN, 1,
-					OTG_3D_STRUCTURE_V_UPDATE_MODE, 1,
-					OTG_3D_STRUCTURE_STEREO_SEL_OVR, 1);
-
-	}
-
-	REG_UPDATE(OPPBUF_CONTROL,
-			OPPBUF_ACTIVE_WIDTH, active_width);
-
-	REG_UPDATE(OPPBUF_3D_PARAMETERS_0,
-			OPPBUF_3D_VACT_SPACE1_SIZE, space1_size);
-
-	return;
-}
-
 static void dcn10_disable_stereo(struct timing_generator *tg)
 {
 	struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg);
 
 	REG_SET(OTG_STEREO_CONTROL, 0,
-			OTG_STEREO_EN, 0);
+		OTG_STEREO_EN, 0);
 
 	REG_SET_3(OTG_3D_STRUCTURE_CONTROL, 0,
-			OTG_3D_STRUCTURE_EN, 0,
-			OTG_3D_STRUCTURE_V_UPDATE_MODE, 0,
-			OTG_3D_STRUCTURE_STEREO_SEL_OVR, 0);
+		OTG_3D_STRUCTURE_EN, 0,
+		OTG_3D_STRUCTURE_V_UPDATE_MODE, 0,
+		OTG_3D_STRUCTURE_STEREO_SEL_OVR, 0);
 
 	REG_UPDATE(OPPBUF_CONTROL,
-			OPPBUF_ACTIVE_WIDTH, 0);
+		OPPBUF_ACTIVE_WIDTH, 0);
 	REG_UPDATE(OPPBUF_3D_PARAMETERS_0,
-			OPPBUF_3D_VACT_SPACE1_SIZE, 0);
-	return;
-}
-
-static bool is_frame_alternate_stereo(enum dc_timing_3d_format fmt)
-{
-	bool ret = false;
-	if (fmt == TIMING_3D_FORMAT_FRAME_ALTERNATE ||
-		fmt == TIMING_3D_FORMAT_INBAND_FA ||
-		fmt == TIMING_3D_FORMAT_DP_HDMI_INBAND_FA ||
-		fmt == TIMING_3D_FORMAT_SIDEBAND_FA)
-		ret = true;
-	return ret;
-}
-
-static void dcn10_do_stereo(struct timing_generator *tg,
-		const struct dc_crtc_timing *dc_crtc_timing)
-{
-	struct crtc_stereo_flags stereo_flags = {0};
-	if (dc_crtc_timing->timing_3d_format == TIMING_3D_FORMAT_NONE ||
-		dc_crtc_timing->timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE ||
-		dc_crtc_timing->timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM)
-		dcn10_disable_stereo(tg);
-	else {
-		stereo_flags.PROGRAM_STEREO = 1;
-		stereo_flags.PROGRAM_POLARITY = 1;
-		stereo_flags.DISABLE_STEREO_DP_SYNC = 0;
-		stereo_flags.RIGHT_EYE_POLARITY =
-				dc_crtc_timing->flags.RIGHT_EYE_3D_POLARITY;
-		if (dc_crtc_timing->timing_3d_format ==
-				TIMING_3D_FORMAT_HW_FRAME_PACKING)
-			stereo_flags.FRAME_PACKED = 1;
-
-		if (is_frame_alternate_stereo(
-				dc_crtc_timing->timing_3d_format) ||
-				dc_crtc_timing->timing_3d_format ==
-					TIMING_3D_FORMAT_HW_FRAME_PACKING)
-			dcn10_enable_stereo(tg, &stereo_flags, dc_crtc_timing);
-	}
+		OPPBUF_3D_VACT_SPACE1_SIZE, 0);
 }
 
 /**
@@ -361,9 +271,8 @@ static void tg_program_timing_generator(
 	REG_UPDATE(OTG_H_TIMING_CNTL,
 			OTG_H_TIMING_DIV_BY2, h_div_2);
 
-	/* Enable crtc stereo frame pack tested... todo more
-	 */
-	dcn10_do_stereo(tg, &patched_crtc_timing);
+	dcn10_disable_stereo( tg);
+
 }
 
 /** tg_program_blanking
@@ -605,7 +514,8 @@ static bool tg_validate_timing(
 		timing->timing_3d_format != TIMING_3D_FORMAT_HW_FRAME_PACKING &&
 		timing->timing_3d_format != TIMING_3D_FORMAT_TOP_AND_BOTTOM &&
 		timing->timing_3d_format != TIMING_3D_FORMAT_SIDE_BY_SIDE &&
-		timing->timing_3d_format != TIMING_3D_FORMAT_FRAME_ALTERNATE)
+		timing->timing_3d_format != TIMING_3D_FORMAT_FRAME_ALTERNATE &&
+		timing->timing_3d_format != TIMING_3D_FORMAT_INBAND_FA)
 		return false;
 
 	/* Temporarily blocking interlacing mode until it's supported */
@@ -1145,6 +1055,76 @@ void dcn10_timing_generator_get_crtc_scanoutpos(
 	*v_position = position.vertical_count;
 }
 
+
+
+static void dcn10_enable_stereo(struct timing_generator *tg,
+	const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags)
+{
+	struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg);
+
+	uint32_t active_width = timing->h_addressable;
+	uint32_t space1_size = timing->v_total - timing->v_addressable;
+
+	if (flags) {
+		uint32_t stereo_en;
+		stereo_en = flags->FRAME_PACKED == 0 ? 1 : 0;
+
+		if (flags->PROGRAM_STEREO)
+			REG_UPDATE_3(OTG_STEREO_CONTROL,
+				OTG_STEREO_EN, stereo_en,
+				OTG_STEREO_SYNC_OUTPUT_LINE_NUM, 0,
+				OTG_STEREO_SYNC_OUTPUT_POLARITY, 0);
+
+		if (flags->PROGRAM_POLARITY)
+			REG_UPDATE(OTG_STEREO_CONTROL,
+				OTG_STEREO_EYE_FLAG_POLARITY,
+				flags->RIGHT_EYE_POLARITY == 0 ? 0 : 1);
+
+		if (flags->DISABLE_STEREO_DP_SYNC)
+			REG_UPDATE(OTG_STEREO_CONTROL,
+				OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, 1);
+
+		if (flags->PROGRAM_STEREO && flags->FRAME_PACKED)
+			REG_UPDATE_3(OTG_3D_STRUCTURE_CONTROL,
+				OTG_3D_STRUCTURE_EN, 1,
+				OTG_3D_STRUCTURE_V_UPDATE_MODE, 1,
+				OTG_3D_STRUCTURE_STEREO_SEL_OVR, 1);
+
+	}
+
+	REG_UPDATE(OPPBUF_CONTROL,
+		OPPBUF_ACTIVE_WIDTH, active_width);
+
+	REG_UPDATE(OPPBUF_3D_PARAMETERS_0,
+		OPPBUF_3D_VACT_SPACE1_SIZE, space1_size);
+}
+
+static void dcn10_program_stereo(struct timing_generator *tg,
+	const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags)
+{
+	if (flags->PROGRAM_STEREO)
+		dcn10_enable_stereo(tg, timing, flags);
+	else
+		dcn10_disable_stereo(tg);
+}
+
+
+static bool dcn10_is_stereo_left_eye(struct timing_generator *tg)
+{
+	bool ret = false;
+	uint32_t left_eye = 0;
+	struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg);
+
+	REG_GET(OTG_STEREO_STATUS,
+		OTG_STEREO_CURRENT_EYE, &left_eye);
+	if (left_eye == 1)
+		ret = true;
+	else
+		ret = false;
+
+	return ret;
+}
+
 static struct timing_generator_funcs dcn10_tg_funcs = {
 		.validate_timing = tg_validate_timing,
 		.program_timing = tg_program_timing,
@@ -1183,7 +1163,9 @@ static struct timing_generator_funcs dcn10_tg_funcs = {
 		.enable_optc_clock = enable_optc_clock,
 		.set_drr = dcn10_timing_generator_set_drr,
 		.set_static_screen_control = set_static_screen_control,
-		.set_test_pattern = dcn10_timing_generator_set_test_pattern
+		.set_test_pattern = dcn10_timing_generator_set_test_pattern,
+		.program_stereo = dcn10_program_stereo,
+		.is_stereo_left_eye = dcn10_is_stereo_left_eye
 };
 
 void dcn10_timing_generator_init(struct dcn10_timing_generator *tgn10)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h
index 85a763a..c880fa5 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_timing_generator.h
@@ -51,6 +51,7 @@
 	SRI(OTG_CONTROL, OTG, inst),\
 	SRI(OTG_STEREO_CONTROL, OTG, inst),\
 	SRI(OTG_3D_STRUCTURE_CONTROL, OTG, inst),\
+	SRI(OTG_STEREO_STATUS, OTG, inst),\
 	SRI(OTG_V_TOTAL_MAX, OTG, inst),\
 	SRI(OTG_V_TOTAL_MIN, OTG, inst),\
 	SRI(OTG_V_TOTAL_CONTROL, OTG, inst),\
@@ -96,6 +97,7 @@ struct dcn_tg_registers {
 	uint32_t OTG_CONTROL;
 	uint32_t OTG_STEREO_CONTROL;
 	uint32_t OTG_3D_STRUCTURE_CONTROL;
+	uint32_t OTG_STEREO_STATUS;
 	uint32_t OTG_V_TOTAL_MAX;
 	uint32_t OTG_V_TOTAL_MIN;
 	uint32_t OTG_V_TOTAL_CONTROL;
@@ -157,6 +159,8 @@ struct dcn_tg_registers {
 	SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_POLARITY, mask_sh),\
 	SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EYE_FLAG_POLARITY, mask_sh),\
 	SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\
+	SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\
+	SF(OTG0_OTG_STEREO_STATUS, OTG_STEREO_CURRENT_EYE, mask_sh),\
 	SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_EN, mask_sh),\
 	SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_V_UPDATE_MODE, mask_sh),\
 	SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_STEREO_SEL_OVR, mask_sh),\
@@ -243,6 +247,7 @@ struct dcn_tg_registers {
 	type OTG_STEREO_SYNC_OUTPUT_LINE_NUM;\
 	type OTG_STEREO_SYNC_OUTPUT_POLARITY;\
 	type OTG_STEREO_EYE_FLAG_POLARITY;\
+	type OTG_STEREO_CURRENT_EYE;\
 	type OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP;\
 	type OTG_3D_STRUCTURE_EN;\
 	type OTG_3D_STRUCTURE_V_UPDATE_MODE;\
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 9f130af..2b72d1d 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
@@ -100,6 +100,15 @@ struct _dlg_otg_param {
 	enum signal_type signal;
 };
 #endif
+
+struct crtc_stereo_flags {
+	uint8_t PROGRAM_STEREO         : 1;
+	uint8_t PROGRAM_POLARITY       : 1;
+	uint8_t RIGHT_EYE_POLARITY     : 1;
+	uint8_t FRAME_PACKED           : 1;
+	uint8_t DISABLE_STEREO_DP_SYNC : 1;
+};
+
 struct timing_generator {
 	const struct timing_generator_funcs *funcs;
 	struct dc_bios *bp;
@@ -171,6 +180,9 @@ struct timing_generator_funcs {
 	void (*program_global_sync)(struct timing_generator *tg);
 	void (*enable_optc_clock)(struct timing_generator *tg, bool enable);
 #endif
+	void (*program_stereo)(struct timing_generator *tg,
+		const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags);
+	bool (*is_stereo_left_eye)(struct timing_generator *tg);
 };
 
 #endif
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 6f8733e..5288481 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
@@ -143,6 +143,10 @@ struct hw_sequencer_funcs {
 			struct pipe_ctx *pipe_ctx,
 			struct validate_context *context,
 			struct core_dc *dc);
+
+	void (*setup_stereo)(
+			struct pipe_ctx *pipe_ctx,
+			struct core_dc *dc);
 };
 
 void color_space_to_black_color(
-- 
2.7.4