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>
This commit is contained in:
parent
19f89e2392
commit
62f555377f
@ -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,80 +4346,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;
|
||||
}
|
||||
|
||||
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 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 */
|
||||
@ -4444,6 +4374,49 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
|
||||
|
||||
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, "
|
||||
"planes_changed:%d, mode_changed:%d,active_changed:%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,
|
||||
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;
|
||||
if (!dc_remove_stream_from_ctx(
|
||||
dc,
|
||||
dm_state->context,
|
||||
old_acrtc_state->stream)) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
dc_stream_release(old_acrtc_state->stream);
|
||||
new_acrtc_state->stream = NULL;
|
||||
|
||||
if (aconnector) {
|
||||
conn_state = drm_atomic_get_connector_state(state,
|
||||
&aconnector->base);
|
||||
*lock_and_validation_needed = true;
|
||||
|
||||
if (IS_ERR(conn_state)) {
|
||||
ret = PTR_ERR_OR_ZERO(conn_state);
|
||||
goto fail;
|
||||
}
|
||||
} else {/* Add stream for any updated/enabled CRTC */
|
||||
|
||||
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 (modereset_required(crtc_state))
|
||||
continue;
|
||||
|
||||
if (modeset_required(crtc_state, new_stream,
|
||||
old_acrtc_state->stream)) {
|
||||
|
||||
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);
|
||||
}
|
||||
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
|
||||
*/
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (pflip_needed)
|
||||
return ret;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Remove any changed/removed planes */
|
||||
if (!enable) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
dc_plane_state_release(old_dm_plane_state->dc_state);
|
||||
new_dm_plane_state->dc_state = NULL;
|
||||
|
||||
*lock_and_validation_needed = true;
|
||||
|
||||
} else { /* Add new planes */
|
||||
|
||||
if (drm_atomic_plane_disabling(plane->state, new_plane_state))
|
||||
continue;
|
||||
|
||||
if (!new_plane_crtc)
|
||||
continue;
|
||||
|
||||
new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_crtc);
|
||||
new_acrtc_state = to_dm_crtc_state(new_crtc_state);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user