summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Grodzovsky <Andrey.Grodzovsky@amd.com>2017-08-18 10:52:20 -0400
committerAlex Deucher <alexander.deucher@amd.com>2017-09-26 18:17:06 -0400
commit62f555377f972c206c69c6acc93d91f2baec9a26 (patch)
tree9b2267e62820e1037bd2144f57582a2c7cd6b96d
parent19f89e2392e692208a0a00465d30b2b2bf43e9a9 (diff)
drm/amd/display: Refactor atomic check.
Split into update crtcs and update plane functions. Signed-off-by: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com> Reviewed-by: Harry Wentland <Harry.Wentland@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c462
1 files changed, 261 insertions, 201 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 e8835e751702..193a634f46e6 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1640,12 +1640,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;
@@ -3875,9 +3869,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;
@@ -4354,95 +4346,76 @@ 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;
-
- ret = drm_atomic_helper_check_modeset(dev, state);
-
- if (ret) {
- DRM_ERROR("Atomic state validation failed with error :%d !\n", ret);
- return ret;
- }
-
- dm_state->context = dc_create_state();
- ASSERT(dm_state->context);
- dc_resource_validate_ctx_copy_construct_current(dc, dm_state->context);
+ int ret = 0;
- /* Remove exiting planes if they are disabled or their CRTC is updated */
+ /*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) {
- new_acrtc_state = to_dm_crtc_state(crtc_state);
+ 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 (pflip_needed)
- continue;
+ old_acrtc_state = to_dm_crtc_state(crtc->state);
+ new_acrtc_state = to_dm_crtc_state(crtc_state);
+ acrtc = to_amdgpu_crtc(crtc);
- 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);
+ aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc, true);
- if (plane->type == DRM_PLANE_TYPE_CURSOR)
- continue;
+ /* TODO This hack should go away */
+ if (aconnector && aconnector->dc_sink) {
+ conn_state = drm_atomic_get_connector_state(state,
+ &aconnector->base);
- 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, "
@@ -4456,109 +4429,256 @@ 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;
}
}
+ dm_state->context = dc_create_state();
+ ASSERT(dm_state->context);
+ dc_resource_validate_ctx_copy_construct_current(dc, dm_state->context);
+
+ /* 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
@@ -4583,66 +4703,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
@@ -4675,7 +4735,7 @@ fail:
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;
}