diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2320-drm-amd-display-Refactor-atomic-check.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2320-drm-amd-display-Refactor-atomic-check.patch | 578 |
1 files changed, 578 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2320-drm-amd-display-Refactor-atomic-check.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2320-drm-amd-display-Refactor-atomic-check.patch new file mode 100644 index 00000000..c48308c5 --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2320-drm-amd-display-Refactor-atomic-check.patch @@ -0,0 +1,578 @@ +From e1ea26640715bd15a1452b2568aa76fe7371c805 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 2320/4131] 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> +--- + 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 9e01146..7d6f48b 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -1673,12 +1673,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; + +@@ -4129,9 +4123,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; +@@ -4614,91 +4606,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; + + #if !defined(OS_NAME_RHEL_7_2) + DRM_DEBUG_KMS( +@@ -4714,109 +4692,252 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, + crtc_state->connectors_changed); + #endif + +- 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 +@@ -4841,66 +4962,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 +@@ -4933,7 +4994,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.7.4 + |