aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.14.71/2477-drm-amd-display-Refactor-dc_update_planes_and_stream.patch
blob: f2f53161607892d550c953459444dd0658281a1f (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
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
From 1600480c776884800cd9bf0ba601de578236cc22 Mon Sep 17 00:00:00 2001
From: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Date: Tue, 12 Sep 2017 13:56:57 -0400
Subject: [PATCH 2477/4131] drm/amd/display: Refactor
 dc_update_planes_and_stream.

Split update_planes_and_stream_state (split Software and Hardware
programming) as the state is already build, so we only need to
program the hardware

Change-Id: Ieb1f1be8693ec26cd430081199964c9d912c50cd
Signed-off-by: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com>
Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Reviewed-by: Harry Wentland <Harry.Wentland@amd.com>
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  21 +-
 drivers/gpu/drm/amd/display/dc/core/dc.c          | 256 +++++-----------------
 drivers/gpu/drm/amd/display/dc/dc.h               |  36 +--
 3 files changed, 87 insertions(+), 226 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 5565e32..ded1444 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3978,7 +3978,8 @@ static void prepare_flip_isr(struct amdgpu_crtc *acrtc)
  */
 static void amdgpu_dm_do_flip(struct drm_crtc *crtc,
 			      struct drm_framebuffer *fb,
-			      uint32_t target)
+			      uint32_t target,
+			      struct dc_state *state)
 {
 	unsigned long flags;
 	uint32_t target_vblank;
@@ -4053,7 +4054,13 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc,
 	surface_updates->flip_addr = &addr;
 
 
-	dc_update_planes_and_stream(adev->dm.dc, surface_updates, 1, acrtc_state->stream, NULL);
+	dc_commit_updates_for_stream(adev->dm.dc,
+					     surface_updates,
+					     1,
+					     acrtc_state->stream,
+					     NULL,
+					     &surface_updates->surface,
+					     state);
 
 	DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n",
 			 __func__,
@@ -4077,6 +4084,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
 	struct dc_plane_state *plane_states_constructed[MAX_SURFACES];
 	struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc);
 	struct dm_crtc_state *acrtc_state = to_dm_crtc_state(pcrtc->state);
+	struct dm_atomic_state *dm_state = to_dm_atomic_state(state);
 	int planes_count = 0;
 	unsigned long flags;
 
@@ -4137,7 +4145,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
 			amdgpu_dm_do_flip(
 				crtc,
 				fb,
-				drm_crtc_vblank_count(crtc) + *wait_for_vblank);
+				drm_crtc_vblank_count(crtc) + *wait_for_vblank,
+				dm_state->context);
 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
 			/*TODO BUG remove ASAP in 4.12 to avoid race between worker and flip IOCTL */
 
@@ -4163,7 +4172,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
 		if (false == dc_commit_planes_to_stream(dm->dc,
 							plane_states_constructed,
 							planes_count,
-							dc_stream_attach))
+							dc_stream_attach,
+							dm_state->context))
 			dm_error("%s: Failed to attach plane!\n", __func__);
 	} else {
 		/*TODO BUG Here should go disable planes on CRTC. */
@@ -4386,7 +4396,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
 				dm->dc,
 				status->plane_states,
 				status->plane_count,
-				new_acrtc_state->stream))
+				new_acrtc_state->stream,
+				dm_state->context))
 			dm_error("%s: Failed to update stream scaling!\n", __func__);
 	}
 
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 6737bd4..9433f9b 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -869,7 +869,8 @@ bool dc_commit_planes_to_stream(
 		struct dc *dc,
 		struct dc_plane_state **plane_states,
 		uint8_t new_plane_count,
-		struct dc_stream_state *dc_stream)
+		struct dc_stream_state *dc_stream,
+		struct dc_state *state)
 {
 	struct dc_surface_update updates[MAX_SURFACES];
 	struct dc_flip_addrs flip_addr[MAX_SURFACES];
@@ -920,11 +921,11 @@ bool dc_commit_planes_to_stream(
 		updates[i].scaling_info = &scaling_info[i];
 	}
 
-	dc_update_planes_and_stream(
+	dc_commit_updates_for_stream(
 			dc,
 			updates,
 			new_plane_count,
-			dc_stream, stream_update);
+			dc_stream, stream_update, plane_states, state);
 
 	dc_post_update_surfaces_to_stream(dc);
 
@@ -1150,192 +1151,20 @@ static struct dc_stream_status *stream_get_status(
 
 static const enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL;
 
-void dc_update_planes_and_stream(struct dc *dc,
-		struct dc_surface_update *srf_updates, int surface_count,
+
+static void commit_planes_for_stream(struct dc *dc,
+		struct dc_surface_update *srf_updates,
+		int surface_count,
 		struct dc_stream_state *stream,
-		struct dc_stream_update *stream_update)
+		struct dc_stream_update *stream_update,
+		enum surface_update_type update_type,
+		struct dc_state *context)
 {
-	struct dc_state *context;
 	int i, j;
-	enum surface_update_type update_type;
-	const struct dc_stream_status *stream_status;
-	struct dc_context *dc_ctx = dc->ctx;
-
-	stream_status = dc_stream_get_status(stream);
-
-	ASSERT(stream_status);
-	if (!stream_status)
-		return; /* Cannot commit surface to stream that is not committed */
-
-#ifdef ENABLE_FBC
-	if (srf_updates->flip_addr) {
-		if (srf_updates->flip_addr->address.grph.addr.low_part == 0)
-			ASSERT(0);
-	}
-#endif
-	context = dc->current_state;
-
-	/* update current stream with the new updates */
-	if (stream_update) {
-		if ((stream_update->src.height != 0) &&
-				(stream_update->src.width != 0))
-			stream->src = stream_update->src;
-
-		if ((stream_update->dst.height != 0) &&
-				(stream_update->dst.width != 0))
-			stream->dst = stream_update->dst;
-
-		if (stream_update->out_transfer_func &&
-				stream_update->out_transfer_func !=
-						stream->out_transfer_func) {
-			if (stream->out_transfer_func != NULL)
-				dc_transfer_func_release(stream->out_transfer_func);
-			dc_transfer_func_retain(stream_update->out_transfer_func);
-			stream->out_transfer_func =
-				stream_update->out_transfer_func;
-		}
-	}
-
-	/* do not perform surface update if surface has invalid dimensions
-	 * (all zero) and no scaling_info is provided
-	 */
-	if (surface_count > 0 &&
-			srf_updates->surface->src_rect.width == 0 &&
-			srf_updates->surface->src_rect.height == 0 &&
-			srf_updates->surface->dst_rect.width == 0 &&
-			srf_updates->surface->dst_rect.height == 0 &&
-			!srf_updates->scaling_info) {
-		ASSERT(false);
-		return;
-	}
-
-	update_type = dc_check_update_surfaces_for_stream(
-			dc, srf_updates, surface_count, stream_update, stream_status);
-
-	if (update_type >= update_surface_trace_level)
-		update_surface_trace(dc, srf_updates, surface_count);
-
-	if (update_type >= UPDATE_TYPE_FULL) {
-		struct dc_plane_state *new_planes[MAX_SURFACES] = {0};
-
-		for (i = 0; i < surface_count; i++)
-			new_planes[i] = srf_updates[i].surface;
-
-		/* initialize scratch memory for building context */
-		context = dc_create_state();
-		if (context == NULL) {
-			DC_ERROR("Failed to allocate new validate context!\n");
-			return;
-		}
-
-		dc_resource_state_copy_construct(
-				dc->current_state, context);
-
-		/*remove old surfaces from context */
-		if (!dc_rem_all_planes_for_stream(dc, stream, context)) {
-
-			BREAK_TO_DEBUGGER();
-			goto fail;
-		}
-
-		/* add surface to context */
-		if (!dc_add_all_planes_for_stream(dc, stream, new_planes, surface_count, context)) {
-
-			BREAK_TO_DEBUGGER();
-			goto fail;
-		}
-	}
-
-	/* save update parameters into surface */
-	for (i = 0; i < surface_count; i++) {
-		struct dc_plane_state *surface = srf_updates[i].surface;
-
-		if (srf_updates[i].flip_addr) {
-			surface->address = srf_updates[i].flip_addr->address;
-			surface->flip_immediate =
-					srf_updates[i].flip_addr->flip_immediate;
-		}
-
-		if (srf_updates[i].scaling_info) {
-			surface->scaling_quality =
-					srf_updates[i].scaling_info->scaling_quality;
-			surface->dst_rect =
-					srf_updates[i].scaling_info->dst_rect;
-			surface->src_rect =
-					srf_updates[i].scaling_info->src_rect;
-			surface->clip_rect =
-					srf_updates[i].scaling_info->clip_rect;
-		}
-
-		if (srf_updates[i].plane_info) {
-			surface->color_space =
-					srf_updates[i].plane_info->color_space;
-			surface->format =
-					srf_updates[i].plane_info->format;
-			surface->plane_size =
-					srf_updates[i].plane_info->plane_size;
-			surface->rotation =
-					srf_updates[i].plane_info->rotation;
-			surface->horizontal_mirror =
-					srf_updates[i].plane_info->horizontal_mirror;
-			surface->stereo_format =
-					srf_updates[i].plane_info->stereo_format;
-			surface->tiling_info =
-					srf_updates[i].plane_info->tiling_info;
-			surface->visible =
-					srf_updates[i].plane_info->visible;
-			surface->per_pixel_alpha =
-					srf_updates[i].plane_info->per_pixel_alpha;
-			surface->dcc =
-					srf_updates[i].plane_info->dcc;
-		}
-
-		if (update_type >= UPDATE_TYPE_MED) {
-			for (j = 0; j < dc->res_pool->pipe_count; j++) {
-				struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
-
-				if (pipe_ctx->plane_state != surface)
-					continue;
-
-				resource_build_scaling_params(pipe_ctx);
-			}
-		}
-
-		if (srf_updates[i].gamma &&
-			srf_updates[i].gamma != surface->gamma_correction) {
-			if (surface->gamma_correction != NULL)
-				dc_gamma_release(&surface->gamma_correction);
-
-			dc_gamma_retain(srf_updates[i].gamma);
-			surface->gamma_correction = srf_updates[i].gamma;
-		}
-
-		if (srf_updates[i].in_transfer_func &&
-			srf_updates[i].in_transfer_func != surface->in_transfer_func) {
-			if (surface->in_transfer_func != NULL)
-				dc_transfer_func_release(
-						surface->
-						in_transfer_func);
-
-			dc_transfer_func_retain(
-					srf_updates[i].in_transfer_func);
-			surface->in_transfer_func =
-					srf_updates[i].in_transfer_func;
-		}
-
-		if (srf_updates[i].hdr_static_metadata)
-			surface->hdr_static_ctx =
-				*(srf_updates[i].hdr_static_metadata);
-	}
 
 	if (update_type == UPDATE_TYPE_FULL) {
-		if (!dc->res_pool->funcs->validate_bandwidth(dc, context)) {
-			BREAK_TO_DEBUGGER();
-			goto fail;
-		} else {
-			dc->hwss.set_bandwidth(dc, context, false);
-			context_clock_trace(dc, context);
-		}
+		dc->hwss.set_bandwidth(dc, context, false);
+		context_clock_trace(dc, context);
 	}
 
 	if (update_type > UPDATE_TYPE_FAST) {
@@ -1459,27 +1288,60 @@ void dc_update_planes_and_stream(struct dc *dc,
 			break;
 		}
 	}
+}
+
+void dc_commit_updates_for_stream(struct dc *dc,
+		struct dc_surface_update *srf_updates,
+		int surface_count,
+		struct dc_stream_state *stream,
+		struct dc_stream_update *stream_update,
+		struct dc_plane_state **plane_states,
+		struct dc_state *state)
+{
+	const struct dc_stream_status *stream_status;
+	enum surface_update_type update_type;
+	struct dc_state *context;
+	int i;
 
-	if (dc->current_state != context) {
+	stream_status = dc_stream_get_status(stream);
+	context = dc->current_state;
+
+	update_type = dc_check_update_surfaces_for_stream(
+				dc, srf_updates, surface_count, stream_update, stream_status);
+
+	if (update_type >= update_surface_trace_level)
+		update_surface_trace(dc, srf_updates, surface_count);
 
-		/* Since memory free requires elevated IRQL, an interrupt
-		 * request is generated by mem free. If this happens
-		 * between freeing and reassigning the context, our vsync
-		 * interrupt will call into dc and cause a memory
-		 * corruption BSOD. Hence, we first reassign the context,
-		 * then free the old context.
-		 */
 
-		struct dc_state *old = dc->current_state;
+	if (update_type >= UPDATE_TYPE_FULL)
+		dc_resource_state_copy_construct(state, context);
 
-		dc->current_state = context;
-		dc_release_state(old);
+
+	for (i = 0; i < surface_count; i++) {
+		struct dc_plane_state *surface = srf_updates[i].surface;
+
+		/* TODO: On flip we don't build the state, so it still has the
+		 * old address. Which is why we are updating the address here
+		 */
+		if (srf_updates[i].flip_addr)
+			surface->address = srf_updates[i].flip_addr->address;
 
 	}
+
+
+	commit_planes_for_stream(
+				dc,
+				srf_updates,
+				surface_count,
+				stream,
+				stream_update,
+				update_type,
+				context);
+
+	dc_post_update_surfaces_to_stream(dc);
+
 	return;
 
-fail:
-	dc_release_state(context);
 }
 
 uint8_t dc_get_current_stream_count(struct dc *dc)
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index 9967d4a..dae931c 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -461,23 +461,6 @@ void dc_flip_plane_addrs(struct dc *dc,
 		struct dc_flip_addrs flip_addrs[],
 		uint32_t count);
 
-/*
- * Set up surface attributes and associate to a stream
- * The surfaces parameter is an absolute set of all surface active for the stream.
- * If no surfaces are provided, the stream will be blanked; no memory read.
- * Any flip related attribute changes must be done through this interface.
- *
- * After this call:
- *   Surfaces attributes are programmed and configured to be composed into stream.
- *   This does not trigger a flip.  No surface address is programmed.
- */
-
-bool dc_commit_planes_to_stream(
-		struct dc *dc,
-		struct dc_plane_state **plane_states,
-		uint8_t new_plane_count,
-		struct dc_stream_state *stream);
-
 bool dc_post_update_surfaces_to_stream(
 		struct dc *dc);
 
@@ -583,9 +566,6 @@ bool dc_is_stream_unchanged(
 	struct dc_stream_state *old_stream, struct dc_stream_state *stream);
 
 /*
- * Setup stream attributes if no stream updates are provided
- * there will be no impact on the stream parameters
- *
  * Set up surface attributes and associate to a stream
  * The surfaces parameter is an absolute set of all surface active for the stream.
  * If no surfaces are provided, the stream will be blanked; no memory read.
@@ -594,14 +574,22 @@ bool dc_is_stream_unchanged(
  * After this call:
  *   Surfaces attributes are programmed and configured to be composed into stream.
  *   This does not trigger a flip.  No surface address is programmed.
- *
  */
 
-void dc_update_planes_and_stream(struct dc *dc,
-		struct dc_surface_update *surface_updates, int surface_count,
+bool dc_commit_planes_to_stream(
+		struct dc *dc,
+		struct dc_plane_state **plane_states,
+		uint8_t new_plane_count,
 		struct dc_stream_state *dc_stream,
-		struct dc_stream_update *stream_update);
+		struct dc_state *state);
 
+void dc_commit_updates_for_stream(struct dc *dc,
+		struct dc_surface_update *srf_updates,
+		int surface_count,
+		struct dc_stream_state *stream,
+		struct dc_stream_update *stream_update,
+		struct dc_plane_state **plane_states,
+		struct dc_state *state);
 /*
  * Log the current stream state.
  */
-- 
2.7.4