aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1007-drm-amd-display-Refactor-atomic-check.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1007-drm-amd-display-Refactor-atomic-check.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1007-drm-amd-display-Refactor-atomic-check.patch666
1 files changed, 666 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1007-drm-amd-display-Refactor-atomic-check.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1007-drm-amd-display-Refactor-atomic-check.patch
new file mode 100644
index 00000000..96b6c2b3
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1007-drm-amd-display-Refactor-atomic-check.patch
@@ -0,0 +1,666 @@
+From ad3d14ad6eff85578426d10db69eaf2fc56b1c81 Mon Sep 17 00:00:00 2001
+From: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com>
+Date: Fri, 18 Aug 2017 10:52:20 -0400
+Subject: [PATCH 1007/4131] drm/amd/display: Refactor atomic check.
+
+Split into update crtcs and update plane functions.
+
+Change-Id: I57a739070861553de9b787f995e44a1da4e3c2d0
+Signed-off-by: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com>
+Reviewed-by: Harry Wentland <Harry.Wentland@amd.com>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 550 ++++++++++++----------
+ 1 file changed, 303 insertions(+), 247 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 4b817bf..edbf952 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -1789,12 +1789,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;
+
+@@ -4119,9 +4113,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;
+@@ -4598,76 +4590,18 @@ 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;
+- }
+-
+- /* Remove exiting planes if they are disabled or their CRTC is updated */
+- 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);
+-
+- if (plane->type == DRM_PLANE_TYPE_CURSOR)
+- continue;
+-
+- if (crtc != plane_crtc || !dm_plane_state->dc_state)
+- continue;
+-
+- WARN_ON(!new_acrtc_state->stream);
+-
+- 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)) {
+-
+- ret = EINVAL;
+- goto fail;
+- }
+-
+- }
+-
+- dc_plane_state_release(dm_plane_state->dc_state);
+- dm_plane_state->dc_state = NULL;
+-
+- DRM_DEBUG_KMS("Disabling DRM plane: %d on DRM crtc %d\n",
+- plane->base.id, crtc->base.id);
+- }
+- }
++ int ret = 0;
+
+ /*TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set */
+ /* update changed items */
+@@ -4677,12 +4611,52 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
+ struct dc_stream_state *new_stream = NULL;
+ struct drm_connector_state *conn_state = NULL;
+ struct dm_connector_state *dm_conn_state = NULL;
+-
++
+ 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);
++
++ /* TODO This hack should go away */
++ if (aconnector && aconnector->dc_sink) {
++ conn_state = drm_atomic_get_connector_state(state,
++ &aconnector->base);
++
++ if (IS_ERR(conn_state)) {
++ ret = PTR_ERR_OR_ZERO(conn_state);
++ break;
++ }
++
++ dm_conn_state = to_dm_connector_state(conn_state);
++
++ new_stream = create_stream_for_sink(aconnector,
++ &crtc_state->mode,
++ dm_conn_state);
++ /*
++ * 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;
++ }
++ }
++
++ if (dc_is_stream_unchanged(new_stream,
++ old_acrtc_state->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))
++ continue;
+
+ DRM_DEBUG_KMS(
+ "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, "
+@@ -4696,228 +4670,310 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
+ crtc_state->active_changed,
+ crtc_state->connectors_changed);
+
+- if (modereset_required(crtc_state)) {
+-
+- /* i.e. reset mode */
+- if (new_acrtc_state->stream) {
+-
+- if (!dc_remove_stream_from_ctx(
+- dc,
+- dm_state->context,
+- new_acrtc_state->stream)) {
+- ret = -EINVAL;
+- goto fail;
+- }
+-
+- dc_stream_release(new_acrtc_state->stream);
+- new_acrtc_state->stream = NULL;
+-
+- lock_and_validation_needed = true;
+- }
+-
+- } else {
+-
+- if (aconnector) {
+- conn_state = drm_atomic_get_connector_state(state,
+- &aconnector->base);
+-
+- if (IS_ERR(conn_state)) {
+- ret = PTR_ERR_OR_ZERO(conn_state);
+- goto fail;
+- }
+-
+- dm_conn_state = to_dm_connector_state(conn_state);
+-
+- new_stream = create_stream_for_sink(aconnector,
+- &crtc_state->mode,
+- dm_conn_state);
+-
+- /*
+- * 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;
+- }
++ /* 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 (!dc_remove_stream_from_ctx(
++ dc,
++ dm_state->context,
++ old_acrtc_state->stream)) {
++ ret = -EINVAL;
++ break;
+ }
+
+- if (modeset_required(crtc_state, new_stream,
+- old_acrtc_state->stream)) {
++ dc_stream_release(old_acrtc_state->stream);
++ new_acrtc_state->stream = NULL;
+
+- if (new_acrtc_state->stream) {
++ *lock_and_validation_needed = true;
+
+- if (!dc_remove_stream_from_ctx(
+- dc,
+- dm_state->context,
+- new_acrtc_state->stream)) {
+- ret = -EINVAL;
+- goto fail;
+- }
++ } else {/* Add stream for any updated/enabled CRTC */
+
++ if (modereset_required(crtc_state))
++ continue;
+
+- dc_stream_release(new_acrtc_state->stream);
+- }
++ 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_add_stream_to_ctx(
+ dc,
+ dm_state->context,
+ new_acrtc_state->stream)) {
+ ret = -EINVAL;
+- goto fail;
++ break;
+ }
+-
+- lock_and_validation_needed = true;
+- } else {
+- /*
+- * The new stream is unused, so we release it
+- */
+- if (new_stream)
+- dc_stream_release(new_stream);
+-
++
++ *lock_and_validation_needed = true;
+ }
+ }
+
++ /* Release extra reference */
++ if (new_stream)
++ dc_stream_release(new_stream);
++ }
+
+- /*
+- * 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;
++}
+
+- ret = drm_atomic_add_affected_planes(state, crtc);
+- if (ret)
+- 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;
+
+- /* 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
+- * decide how to handle.
+- */
+- for_each_connector_in_state(state, connector, conn_state, i) {
+- struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
+- struct dm_connector_state *con_old_state =
+- to_dm_connector_state(aconnector->base.state);
+- struct dm_connector_state *con_new_state =
+- to_dm_connector_state(conn_state);
+- struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc);
++ if (pflip_needed)
++ return ret;
+
+- /* Skip any modesets/resets */
+- if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state))
+- continue;
++ /* 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);
+
+- /* Skip any thing not scale or underscan changes */
+- if (!is_scaling_state_different(con_new_state, con_old_state))
+- continue;
++ /*TODO Implement atomic check for cursor plane */
++ if (plane->type == DRM_PLANE_TYPE_CURSOR)
++ continue;
+
+- lock_and_validation_needed = true;
+- }
++ /* Remove any changed/removed planes */
++ if (!enable) {
+
+- /* Add new planes */
+- for_each_crtc_in_state(state, crtc, crtc_state, i) {
+- new_acrtc_state = to_dm_crtc_state(crtc_state);
++ if (!old_plane_crtc)
++ continue;
+
+- if (pflip_needed)
+- continue;
++ old_acrtc_state = to_dm_crtc_state(
++ drm_atomic_get_old_crtc_state(
++ state,
++ old_plane_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);
++ if (!old_acrtc_state->stream)
++ continue;
+
+- /*TODO Implement atomic check for cursor plane */
+- if (plane->type == DRM_PLANE_TYPE_CURSOR)
+- continue;
++ DRM_DEBUG_KMS("Disabling DRM plane: %d on DRM crtc %d\n",
++ plane->base.id, old_plane_crtc->base.id);
+
+- if (crtc != plane_crtc)
+- continue;
++ if (!dc_remove_plane_from_context(
++ dc,
++ old_acrtc_state->stream,
++ old_dm_plane_state->dc_state,
++ dm_state->context)) {
+
+- if (!drm_atomic_plane_disabling(plane->state, plane_state)) {
+- struct dc_plane_state *dc_plane_state;
++ ret = EINVAL;
++ return ret;
++ }
+
+- WARN_ON(!new_acrtc_state->stream);
+
+- dc_plane_state = dc_create_plane_state(dc);
++ dc_plane_state_release(old_dm_plane_state->dc_state);
++ new_dm_plane_state->dc_state = NULL;
+
+- WARN_ON(dm_plane_state->dc_state);
++ *lock_and_validation_needed = true;
+
+- dm_plane_state->dc_state = dc_plane_state;
++ } else { /* Add new planes */
+
+- ret = fill_plane_attributes(
+- plane_crtc->dev->dev_private,
+- dc_plane_state,
+- plane_state,
+- crtc_state,
+- false);
+- if (ret)
+- goto fail;
++ if (drm_atomic_plane_disabling(plane->state, new_plane_state))
++ continue;
+
++ if (!new_plane_crtc)
++ continue;
+
+- if (!dc_add_plane_to_context(
+- dc,
+- new_acrtc_state->stream,
+- dc_plane_state,
+- dm_state->context)) {
++ new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_crtc);
++ new_acrtc_state = to_dm_crtc_state(new_crtc_state);
+
+- ret = EINVAL;
+- goto fail;
+- }
++ if (!new_acrtc_state->stream)
++ continue;
+
+
+- lock_and_validation_needed = true;
+- }
+- }
+- }
++ WARN_ON(new_dm_plane_state->dc_state);
+
+- /* Run this here since we want to validate the streams we created */
+- ret = drm_atomic_helper_check_planes(dev, state);
+- if (ret)
+- goto fail;
++ new_dm_plane_state->dc_state = dc_create_plane_state(dc);
+
+- /*
+- * For full updates case when
+- * removing/adding/updating streams on once CRTC while flipping
+- * on another CRTC,
+- * acquiring global lock will guarantee that any such full
+- * update commit
+- * will wait for completion of any outstanding flip using DRMs
+- * synchronization events.
+- */
++ DRM_DEBUG_KMS("Enabling DRM plane: %d on DRM crtc %d\n",
++ plane->base.id, new_plane_crtc->base.id);
+
+- if (lock_and_validation_needed) {
++ if (!new_dm_plane_state->dc_state) {
++ ret = -EINVAL;
++ return ret;
++ }
+
+- ret = do_aquire_global_lock(dev, state);
+- if (ret)
+- goto fail;
++ 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_validate_global_state(dc, dm_state->context)) {
+- ret = -EINVAL;
+- goto fail;
+- }
+- }
+
+- /* Must be success */
+- WARN_ON(ret);
+- return ret;
++ if (!dc_add_plane_to_context(
++ dc,
++ new_acrtc_state->stream,
++ new_dm_plane_state->dc_state,
++ dm_state->context)) {
+
+-fail:
+- if (ret == -EDEADLK)
+- DRM_DEBUG_KMS("Atomic check stopped due to to deadlock.\n");
+- 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);
++ ret = -EINVAL;
++ return ret;
++ }
+
+- return ret;
++ *lock_and_validation_needed = true;
++ }
++ }
++
++
++ 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
++ * decide how to handle.
++ */
++ for_each_connector_in_state(state, connector, conn_state, i) {
++ struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
++ struct dm_connector_state *con_old_state =
++ to_dm_connector_state(aconnector->base.state);
++ struct dm_connector_state *con_new_state =
++ to_dm_connector_state(conn_state);
++ struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc);
++
++ /* Skip any modesets/resets */
++ if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state))
++ continue;
++
++ /* Skip any thing not scale or underscan changes */
++ if (!is_scaling_state_different(con_new_state, con_old_state))
++ continue;
++
++ lock_and_validation_needed = true;
++ }
++
++ /*
++ * For full updates case when
++ * removing/adding/updating streams on once CRTC while flipping
++ * on another CRTC,
++ * acquiring global lock will guarantee that any such full
++ * update commit
++ * will wait for completion of any outstanding flip using DRMs
++ * synchronization events.
++ */
++
++ if (lock_and_validation_needed) {
++
++ ret = do_aquire_global_lock(dev, state);
++ if (ret)
++ goto fail;
++
++ if (!dc_validate_global_state(dc, dm_state->context)) {
++ ret = -EINVAL;
++ goto fail;
++ }
++ }
++
++ /* Must be success */
++ WARN_ON(ret);
++ return ret;
++
++fail:
++ if (ret == -EDEADLK)
++ DRM_DEBUG_KMS("Atomic check stopped due to to deadlock.\n");
++ 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);
++
++ return ret;
+ }
+
+ static bool is_dp_capable_without_timing_msa(
+--
+2.7.4
+