[PATCH 2/2] drm/amd/display: make dc_commit_surfaces_to_stream() re-entrant

Harry Wentland harry.wentland at amd.com
Fri May 5 13:19:41 UTC 2017


From: Shirish S <shirish.s at amd.com>

dc_commit_surfaces_to_stream() function currently
is handle's only one plane at a time.
This will not work if multiple planes have to be set to a crtc.

The functionality of dc_commit_surfaces_to_stream() with this patch
is slit into
1. Accumulate and initialise all the surfaces that needs to be
   set to a crtc.
2. Update the intialised set of surfaces to the steam in one go.

Hence dc_commit_surfaces_to_stream() is renamed to init_surfaces().
Once all the planes requested by user space are initialised,
dc_commit_surfaces_to_stream() shall sequentially populates *updates,
 *flip_addr, *plane_info and *scaling_info for all surfaces.

BUG: SWDEV-119421
TEST: (On Chromium OS for Stoney Only)
* Chromium UI comes up, on both eDP & DP.
* 'new_surface_count' now changes as per user input for e.g for
  all below run tests its 2, without this patch for the below
  tests it used to be 1
* Executed below tests to see YUV(underlay) & RGB planes on eDP
plane_test --format XR24 --size 500x100 -p --format YV12 --size 500x500
plane_test --format AR24 --size 500x50 -p --format YV12 --size 150x150
plane_test --format AR24 --size 500x50 -p --format YV12 --size 1366x768

Change-Id: I7c8cc8302a970fbf7b8db5e6f66af1ab711b7f49
Signed-off-by: Harry Wentland <Harry.Wentland at amd.com>
Signed-off-by: Shirish S <shirish.s at amd.com>
---
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c    | 71 ++++++++++++++--------
 1 file changed, 44 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c
index 5a206bee189c..a819e6ba659f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c
@@ -729,19 +729,20 @@ static void update_stream_scaling_settings(
 
 }
 
-static void dm_dc_surface_commit(
-		struct dc *dc,
-		struct drm_crtc *crtc)
+static void add_surface(struct dc *dc,
+			struct drm_crtc *crtc,
+			struct drm_plane *plane,
+			const struct dc_surface **dc_surfaces)
 {
 	struct dc_surface *dc_surface;
-	const struct dc_surface *dc_surfaces[1];
 	struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
 	const struct dc_stream *dc_stream = acrtc->stream;
 	unsigned long flags;
 
 	spin_lock_irqsave(&crtc->dev->event_lock, flags);
 	if (acrtc->pflip_status != AMDGPU_FLIP_NONE) {
-		DRM_ERROR("dm_dc_surface_commit: acrtc %d, already busy\n", acrtc->crtc_id);
+		DRM_ERROR("add_surface: acrtc %d, already busy\n",
+			  acrtc->crtc_id);
 		spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
 		/* In comit tail framework this cannot happen */
 		BUG_ON(0);
@@ -769,22 +770,11 @@ static void dm_dc_surface_commit(
 	fill_plane_attributes(
 			crtc->dev->dev_private,
 			dc_surface,
-			crtc->primary->state,
+			plane->state,
 			true);
 
-	dc_surfaces[0] = dc_surface;
-
-	if (false == dc_commit_surfaces_to_stream(
-			dc,
-			dc_surfaces,
-			1,
-			dc_stream)) {
-		dm_error(
-			"%s: Failed to attach surface!\n",
-			__func__);
-	}
+	*dc_surfaces = dc_surface;
 
-	dc_surface_release(dc_surface);
 fail:
 	return;
 }
@@ -2569,11 +2559,16 @@ static void amdgpu_dm_do_flip(
 }
 
 void dc_commit_surfaces(struct drm_atomic_state *state,
-	struct drm_device *dev, struct amdgpu_display_manager *dm)
+			struct drm_device *dev,
+			struct amdgpu_display_manager *dm,
+			struct drm_crtc *pcrtc)
 {
 	uint32_t i;
 	struct drm_plane *plane;
 	struct drm_plane_state *old_plane_state;
+	const struct dc_stream *dc_stream_attach;
+	const struct dc_surface *dc_surfaces_constructed[MAX_SURFACES];
+	int planes_count = 0;
 
 	/* update planes when needed */
 	for_each_plane_in_state(state, plane, old_plane_state, i) {
@@ -2582,6 +2577,7 @@ void dc_commit_surfaces(struct drm_atomic_state *state,
 		struct drm_framebuffer *fb = plane_state->fb;
 		struct drm_connector *connector;
 		struct dm_connector_state *dm_state = NULL;
+		struct amdgpu_crtc *acrtc_attach;
 		enum dm_commit_action action;
 		bool pflip_needed;
 
@@ -2623,9 +2619,26 @@ void dc_commit_surfaces(struct drm_atomic_state *state,
 			 */
 			if (!dm_state)
 				continue;
+			if (crtc == pcrtc) {
+				add_surface(dm->dc, crtc, plane,
+					    &dc_surfaces_constructed[planes_count]);
+				acrtc_attach = to_amdgpu_crtc(crtc);
+				dc_stream_attach = acrtc_attach->stream;
+				planes_count++;
+			}
+		}
+	}
 
-			dm_dc_surface_commit(dm->dc, crtc);
+	if (planes_count) {
+		if (false == dc_commit_surfaces_to_stream(dm->dc,
+							  dc_surfaces_constructed,
+							  planes_count,
+							  dc_stream_attach)) {
+			dm_error("%s: Failed to attach surface!\n", __func__);
+			return;
 		}
+		for (i = 0; i < planes_count; i++)
+			dc_surface_release(dc_surfaces_constructed[i]);
 	}
 }
 
@@ -2637,10 +2650,10 @@ void amdgpu_dm_atomic_commit_tail(
 	struct amdgpu_display_manager *dm = &adev->dm;
 	struct drm_plane *plane;
 	struct drm_plane_state *old_plane_state;
-	uint32_t i;
+	uint32_t i, j;
 	uint32_t commit_streams_count = 0;
 	uint32_t new_crtcs_count = 0;
-	struct drm_crtc *crtc;
+	struct drm_crtc *crtc, *pcrtc;
 	struct drm_crtc_state *old_crtc_state;
 	const struct dc_stream *commit_streams[MAX_STREAMS];
 	struct amdgpu_crtc *new_crtcs[MAX_STREAMS];
@@ -2799,8 +2812,9 @@ void amdgpu_dm_atomic_commit_tail(
 				dc_stream_get_status(acrtc->stream)->primary_otg_inst;
 	}
 
-	/* update planes when needed */
-	dc_commit_surfaces(state, dev, dm);
+	/* update planes when needed per crtc*/
+	for_each_crtc_in_state(state, pcrtc, old_crtc_state, j)
+		dc_commit_surfaces(state, dev, dm, pcrtc);
 
 	for (i = 0; i < new_crtcs_count; i++) {
 		/*
@@ -2977,15 +2991,18 @@ static uint32_t add_val_sets_surface(
 	const struct dc_stream *stream,
 	const struct dc_surface *surface)
 {
-	uint32_t i = 0;
+	uint32_t i = 0, j = 0;
 
 	while (i < set_count) {
-		if (val_sets[i].stream == stream)
+		if (val_sets[i].stream == stream) {
+			while (val_sets[i].surfaces[j])
+				j++;
 			break;
+		}
 		++i;
 	}
 
-	val_sets[i].surfaces[val_sets[i].surface_count] = surface;
+	val_sets[i].surfaces[j] = surface;
 	val_sets[i].surface_count++;
 
 	return val_sets[i].surface_count;
-- 
2.11.0



More information about the amd-gfx mailing list