[PATCH 49/77] drm/amd/display: Refactor atomic check.

Harry Wentland harry.wentland at amd.com
Thu Aug 31 18:08:44 UTC 2017


From: Andrey Grodzovsky <Andrey.Grodzovsky at amd.com>

Split into update crtcs and update plane functions.

Change-Id: I57a739070861553de9b787f995e44a1da4e3c2d0
Signed-off-by: Andrey Grodzovsky <Andrey.Grodzovsky at amd.com>
Reviewed-by: Harry Wentland <Harry.Wentland at amd.com>
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 453 ++++++++++++----------
 1 file changed, 257 insertions(+), 196 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 5218432361fd..e24c44f6720b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1660,12 +1660,6 @@ static bool modeset_required(struct drm_crtc_state *crtc_state,
 			     struct dc_stream_state *new_stream,
 			     struct dc_stream_state *old_stream)
 {
-	if (dc_is_stream_unchanged(new_stream, old_stream)) {
-		crtc_state->mode_changed = false;
-		DRM_DEBUG_KMS("Mode change not required, setting mode_changed to %d",
-			      crtc_state->mode_changed);
-	}
-
 	if (!drm_atomic_crtc_needs_modeset(crtc_state))
 		return false;
 
@@ -3990,9 +3984,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
 			continue;
 		}
 
-		if (!fb || !crtc || pcrtc != crtc || !crtc->state->active ||
-				(!crtc->state->planes_changed &&
-						!pcrtc->state->color_mgmt_changed))
+		if (!fb || !crtc || pcrtc != crtc || !crtc->state->active)
 			continue;
 
 		pflip_needed = !state->allow_modeset;
@@ -4469,91 +4461,77 @@ static int do_aquire_global_lock(
 	return ret < 0 ? ret : 0;
 }
 
-int amdgpu_dm_atomic_check(struct drm_device *dev,
-			struct drm_atomic_state *state)
+static int dm_update_crtcs_state(
+		struct dc *dc,
+		struct drm_atomic_state *state,
+		bool enable,
+		bool *lock_and_validation_needed)
 {
 	struct drm_crtc *crtc;
 	struct drm_crtc_state *crtc_state;
-	struct drm_plane *plane;
-	struct drm_plane_state *plane_state;
-	int i, j;
-	int ret;
-	struct amdgpu_device *adev = dev->dev_private;
-	struct dc *dc = adev->dm.dc;
-	struct drm_connector *connector;
-	struct drm_connector_state *conn_state;
+	int i;
 	struct dm_crtc_state *old_acrtc_state, *new_acrtc_state;
 	struct dm_atomic_state *dm_state = to_dm_atomic_state(state);
-	bool pflip_needed  = !state->allow_modeset;
-
-	/*
-	 * This bool will be set for true for any modeset/reset
-	 * or plane update which implies non fast surface update.
-	 */
-	bool lock_and_validation_needed = false;
+	int ret = 0;
 
-	ret = drm_atomic_helper_check_modeset(dev, state);
+	/*TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set */
+	/* update changed items */
+	for_each_crtc_in_state(state, crtc, crtc_state, i) {
+		struct amdgpu_crtc *acrtc = NULL;
+		struct amdgpu_connector *aconnector = NULL;
+		struct dc_stream_state *new_stream = NULL;
+		struct drm_connector_state *conn_state = NULL;
+		struct dm_connector_state *dm_conn_state = NULL;
 
-	if (ret) {
-		DRM_ERROR("Atomic state validation failed with error :%d !\n", ret);
-		return ret;
-	}
 
-	/* Remove exiting planes if they are disabled or their CRTC is updated */
-	for_each_crtc_in_state(state, crtc, crtc_state, i) {
+		old_acrtc_state = to_dm_crtc_state(crtc->state);
 		new_acrtc_state = to_dm_crtc_state(crtc_state);
+		acrtc = to_amdgpu_crtc(crtc);
 
-		if (pflip_needed)
-			continue;
+		aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc, true);
 
-		for_each_plane_in_state(state, plane, plane_state, j) {
-			struct drm_crtc *plane_crtc = plane_state->crtc;
-			struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state);
+		/* TODO This hack should go away */
+		if (aconnector && aconnector->dc_sink) {
+			conn_state = drm_atomic_get_connector_state(state,
+								    &aconnector->base);
 
-			if (plane->type == DRM_PLANE_TYPE_CURSOR)
-				continue;
-
-			if (crtc != plane_crtc || !dm_plane_state->dc_state)
-				continue;
+			if (IS_ERR(conn_state)) {
+				ret = PTR_ERR_OR_ZERO(conn_state);
+				break;
+			}
 
-			WARN_ON(!new_acrtc_state->stream);
+			dm_conn_state = to_dm_connector_state(conn_state);
 
-			if (drm_atomic_plane_disabling(plane->state, plane_state) ||
-					drm_atomic_crtc_needs_modeset(crtc_state)) {
-				if (!dc_remove_plane_from_context(
-						dc,
-						new_acrtc_state->stream,
-						dm_plane_state->dc_state,
-						dm_state->context)) {
+			new_stream = create_stream_for_sink(aconnector,
+							    &crtc_state->mode,
+							    dm_conn_state);
 
-					ret = EINVAL;
-					goto fail;
-				}
+			/*
+			 * we can have no stream on ACTION_SET if a display
+			 * was disconnected during S3, in this case it not and
+			 * error, the OS will be updated after detection, and
+			 * do the right thing on next atomic commit
+			 */
 
+			if (!new_stream) {
+				DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n",
+						__func__, acrtc->base.base.id);
+				break;
 			}
+		}
 
-			dc_plane_state_release(dm_plane_state->dc_state);
-			dm_plane_state->dc_state = NULL;
+		if (dc_is_stream_unchanged(new_stream,
+				old_acrtc_state->stream)) {
 
-			DRM_DEBUG_KMS("Disabling DRM plane: %d on DRM crtc %d\n",
-					plane->base.id, crtc->base.id);
-		}
-	}
+				crtc_state->mode_changed = false;
 
-	/*TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set */
-	/* update changed items */
-	for_each_crtc_in_state(state, crtc, crtc_state, i) {
-		struct amdgpu_crtc *acrtc = NULL;
-		struct amdgpu_connector *aconnector = NULL;
-		struct dc_stream_state *new_stream = NULL;
-		struct drm_connector_state *conn_state = NULL;
-		struct dm_connector_state *dm_conn_state = NULL;
+				DRM_DEBUG_KMS("Mode change not required, setting mode_changed to %d",
+					      crtc_state->mode_changed);
+		}
 
-		old_acrtc_state = to_dm_crtc_state(crtc->state);
-		new_acrtc_state = to_dm_crtc_state(crtc_state);
-		acrtc = to_amdgpu_crtc(crtc);
 
-		aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc, true);
+		if (!drm_atomic_crtc_needs_modeset(crtc_state))
+				continue;
 
 		DRM_DEBUG_KMS(
 			"amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, "
@@ -4567,109 +4545,252 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
 			crtc_state->active_changed,
 			crtc_state->connectors_changed);
 
-		if (modereset_required(crtc_state)) {
+		/* Remove stream for any changed/disabled CRTC */
+		if (!enable) {
+
+			if (!old_acrtc_state->stream)
+				continue;
+
+			DRM_DEBUG_KMS("Disabling DRM crtc: %d\n",
+					crtc->base.id);
 
 			/* i.e. reset mode */
-			if (new_acrtc_state->stream) {
+			if (!dc_remove_stream_from_ctx(
+					dc,
+					dm_state->context,
+					old_acrtc_state->stream)) {
+				ret = -EINVAL;
+				break;
+			}
+
+			dc_stream_release(old_acrtc_state->stream);
+			new_acrtc_state->stream = NULL;
+
+			*lock_and_validation_needed = true;
+
+		} else {/* Add stream for any updated/enabled CRTC */
+
+			if (modereset_required(crtc_state))
+				continue;
+
+			if (modeset_required(crtc_state, new_stream,
+					     old_acrtc_state->stream)) {
+
+				WARN_ON(new_acrtc_state->stream);
+
+				new_acrtc_state->stream = new_stream;
+				dc_stream_retain(new_stream);
+
+				DRM_DEBUG_KMS("Enabling DRM crtc: %d\n",
+							crtc->base.id);
 
-				if (!dc_remove_stream_from_ctx(
+				if (!dc_add_stream_to_ctx(
 						dc,
 						dm_state->context,
 						new_acrtc_state->stream)) {
 					ret = -EINVAL;
-					goto fail;
+					break;
 				}
 
-				dc_stream_release(new_acrtc_state->stream);
-				new_acrtc_state->stream = NULL;
-
-				lock_and_validation_needed = true;
+				*lock_and_validation_needed = true;
 			}
+		}
 
-		} else {
+		/* Release extra reference */
+		if (new_stream)
+			 dc_stream_release(new_stream);
+	}
 
-			if (aconnector) {
-				conn_state = drm_atomic_get_connector_state(state,
-									    &aconnector->base);
+	return ret;
+}
 
-				if (IS_ERR(conn_state)) {
-					ret = PTR_ERR_OR_ZERO(conn_state);
-					goto fail;
-				}
+static int dm_update_planes_state(
+		struct dc *dc,
+		struct drm_atomic_state *state,
+		bool enable,
+		bool *lock_and_validation_needed)
+{
+	struct drm_crtc *new_plane_crtc, *old_plane_crtc;
+	struct drm_crtc_state *new_crtc_state;
+	struct drm_plane *plane;
+	struct drm_plane_state *old_plane_state, *new_plane_state;
+	struct dm_crtc_state *new_acrtc_state, *old_acrtc_state;
+	struct dm_atomic_state *dm_state = to_dm_atomic_state(state);
+	struct dm_plane_state *new_dm_plane_state, *old_dm_plane_state;
+	int i ;
+	/* TODO return page_flip_needed() function */
+	bool pflip_needed  = !state->allow_modeset;
+	int ret = 0;
 
-				dm_conn_state = to_dm_connector_state(conn_state);
+	if (pflip_needed)
+		return ret;
 
-				new_stream = create_stream_for_sink(aconnector,
-								    &crtc_state->mode,
-								    dm_conn_state);
+	/* Add new planes */
+	for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
+		new_plane_crtc = new_plane_state->crtc;
+		old_plane_crtc = old_plane_state->crtc;
+		new_dm_plane_state = to_dm_plane_state(new_plane_state);
+		old_dm_plane_state = to_dm_plane_state(old_plane_state);
+
+		/*TODO Implement atomic check for cursor plane */
+		if (plane->type == DRM_PLANE_TYPE_CURSOR)
+			continue;
 
-				/*
-				 * we can have no stream on ACTION_SET if a display
-				 * was disconnected during S3, in this case it not and
-				 * error, the OS will be updated after detection, and
-				 * do the right thing on next atomic commit
-				 */
+		/* Remove any changed/removed planes */
+		if (!enable) {
 
-				if (!new_stream) {
-					DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n",
-							__func__, acrtc->base.base.id);
-					break;
-				}
+			if (!old_plane_crtc)
+				continue;
+
+			old_acrtc_state = to_dm_crtc_state(
+					drm_atomic_get_old_crtc_state(
+							state,
+							old_plane_crtc));
+
+			if (!old_acrtc_state->stream)
+				continue;
+
+			DRM_DEBUG_KMS("Disabling DRM plane: %d on DRM crtc %d\n",
+					plane->base.id, old_plane_crtc->base.id);
 
+			if (!dc_remove_plane_from_context(
+					dc,
+					old_acrtc_state->stream,
+					old_dm_plane_state->dc_state,
+					dm_state->context)) {
 
+				ret = EINVAL;
+				return ret;
 			}
 
-			if (modeset_required(crtc_state, new_stream,
-					     old_acrtc_state->stream)) {
 
-				if (new_acrtc_state->stream) {
+			dc_plane_state_release(old_dm_plane_state->dc_state);
+			new_dm_plane_state->dc_state = NULL;
 
-					if (!dc_remove_stream_from_ctx(
-							dc,
-							dm_state->context,
-							new_acrtc_state->stream)) {
-						ret = -EINVAL;
-						goto fail;
-					}
+			*lock_and_validation_needed = true;
 
+		} else { /* Add new planes */
 
-					dc_stream_release(new_acrtc_state->stream);
-				}
+			if (drm_atomic_plane_disabling(plane->state, new_plane_state))
+				continue;
 
-				new_acrtc_state->stream = new_stream;
+			if (!new_plane_crtc)
+				continue;
 
-				if (!dc_add_stream_to_ctx(
-						dc,
-						dm_state->context,
-						new_acrtc_state->stream)) {
-					ret = -EINVAL;
-					goto fail;
-				}
+			new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_crtc);
+			new_acrtc_state = to_dm_crtc_state(new_crtc_state);
 
-				lock_and_validation_needed = true;
-			} else {
-				/*
-				 * The new stream is unused, so we release it
-				 */
-				if (new_stream)
-					dc_stream_release(new_stream);
+			if (!new_acrtc_state->stream)
+				continue;
+
+
+			WARN_ON(new_dm_plane_state->dc_state);
+
+			new_dm_plane_state->dc_state = dc_create_plane_state(dc);
+
+			DRM_DEBUG_KMS("Enabling DRM plane: %d on DRM crtc %d\n",
+					plane->base.id, new_plane_crtc->base.id);
+
+			if (!new_dm_plane_state->dc_state) {
+				ret = -EINVAL;
+				return ret;
+			}
+
+			ret = fill_plane_attributes(
+				new_plane_crtc->dev->dev_private,
+				new_dm_plane_state->dc_state,
+				new_plane_state,
+				new_crtc_state,
+				false);
+			if (ret)
+				return ret;
+
+
+			if (!dc_add_plane_to_context(
+					dc,
+					new_acrtc_state->stream,
+					new_dm_plane_state->dc_state,
+					dm_state->context)) {
 
+				ret = -EINVAL;
+				return ret;
 			}
+
+			*lock_and_validation_needed = true;
 		}
+	}
 
 
-		/*
-		 * Hack: Commit needs planes right now, specifically for gamma
-		 * TODO rework commit to check CRTC for gamma change
-		 */
-		if (crtc_state->color_mgmt_changed) {
+	return ret;
+}
+
+int amdgpu_dm_atomic_check(struct drm_device *dev,
+			struct drm_atomic_state *state)
+{
+	int i;
+	int ret;
+	struct amdgpu_device *adev = dev->dev_private;
+	struct dc *dc = adev->dm.dc;
+	struct dm_atomic_state *dm_state = to_dm_atomic_state(state);
+	struct drm_connector *connector;
+	struct drm_connector_state *conn_state;
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *crtc_state;
+
+	/*
+	 * This bool will be set for true for any modeset/reset
+	 * or plane update which implies non fast surface update.
+	 */
+	bool lock_and_validation_needed = false;
+
+	ret = drm_atomic_helper_check_modeset(dev, state);
 
+	if (ret) {
+		DRM_ERROR("Atomic state validation failed with error :%d !\n", ret);
+		return ret;
+	}
+
+	/*
+	 * Hack: Commit needs planes right now, specifically for gamma
+	 * TODO rework commit to check CRTC for gamma change
+	 */
+	for_each_crtc_in_state(state, crtc, crtc_state, i) {
+		if (crtc_state->color_mgmt_changed) {
 			ret = drm_atomic_add_affected_planes(state, crtc);
 			if (ret)
 				goto fail;
 		}
 	}
 
+	/* Remove exiting planes if they are modified */
+	ret = dm_update_planes_state(dc, state, false, &lock_and_validation_needed);
+	if (ret) {
+		goto fail;
+	}
+
+	/* Disable all crtcs which require disable */
+	ret = dm_update_crtcs_state(dc, state, false, &lock_and_validation_needed);
+	if (ret) {
+		goto fail;
+	}
+
+	/* Enable all crtcs which require enable */
+	ret = dm_update_crtcs_state(dc, state, true, &lock_and_validation_needed);
+	if (ret) {
+		goto fail;
+	}
+
+	/* Add new/modified planes */
+	ret = dm_update_planes_state(dc, state, true, &lock_and_validation_needed);
+	if (ret) {
+		goto fail;
+	}
+
+	 /* Run this here since we want to validate the streams we created */
+	 ret = drm_atomic_helper_check_planes(dev, state);
+	 if (ret)
+		 goto fail;
+
 	/* Check scaling and undersacn changes*/
 	/*TODO Removed scaling changes validation due to inability to commit
 	 * new stream into context w\o causing full reset. Need to
@@ -4694,66 +4815,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
 		lock_and_validation_needed = true;
 	}
 
-	/* Add new planes */
-	for_each_crtc_in_state(state, crtc, crtc_state, i) {
-		new_acrtc_state = to_dm_crtc_state(crtc_state);
-
-		if (pflip_needed)
-			continue;
-
-		for_each_plane_in_state(state, plane, plane_state, j) {
-			struct drm_crtc *plane_crtc = plane_state->crtc;
-			struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state);
-
-			/*TODO Implement atomic check for cursor plane */
-			if (plane->type == DRM_PLANE_TYPE_CURSOR)
-				continue;
-
-			if (crtc != plane_crtc)
-				continue;
-
-			if (!drm_atomic_plane_disabling(plane->state, plane_state)) {
-				struct dc_plane_state *dc_plane_state;
-
-				WARN_ON(!new_acrtc_state->stream);
-
-				dc_plane_state = dc_create_plane_state(dc);
-
-				WARN_ON(dm_plane_state->dc_state);
-
-				dm_plane_state->dc_state = dc_plane_state;
-
-				ret = fill_plane_attributes(
-					plane_crtc->dev->dev_private,
-					dc_plane_state,
-					plane_state,
-					crtc_state,
-					false);
-				if (ret)
-					goto fail;
-
-
-				if (!dc_add_plane_to_context(
-						dc,
-						new_acrtc_state->stream,
-						dc_plane_state,
-						dm_state->context)) {
-
-					ret = EINVAL;
-					goto fail;
-				}
-
-
-				lock_and_validation_needed = true;
-			}
-		}
-	}
-
-	/* Run this here since we want to validate the streams we created */
-	ret = drm_atomic_helper_check_planes(dev, state);
-	if (ret)
-		goto fail;
-
 	/*
 	 * For full updates case when
 	 * removing/adding/updating  streams on once CRTC while flipping
@@ -4786,7 +4847,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
 	else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS)
 		DRM_DEBUG_KMS("Atomic check stopped due to to signal.\n");
 	else
-		DRM_ERROR("Atomic check failed with err: %d .\n", ret);
+		DRM_ERROR("Atomic check failed with err: %d \n", ret);
 
 	return ret;
 }
-- 
2.11.0



More information about the amd-gfx mailing list