1
0
Fork 0

drm/amd/display: Move iteration out of dm_update_crtcs

[Why]
To reduce indent in dm_update_crtcs, and to make it operate on single
instances.

[How]
Move iteration of plane states into atomic_check.
No functional change is intended.

Signed-off-by: Leo Li <sunpeng.li@amd.com>
Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
hifive-unleashed-5.1
Leo Li 2018-11-11 11:35:13 -05:00 committed by Alex Deucher
parent 9e869063b0
commit 4b9674e509
1 changed files with 186 additions and 177 deletions

View File

@ -5461,15 +5461,15 @@ static void reset_freesync_config_for_crtc(
sizeof(new_crtc_state->vrr_infopacket));
}
static int dm_update_crtcs_state(struct amdgpu_display_manager *dm,
struct drm_atomic_state *state,
bool enable,
bool *lock_and_validation_needed)
static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
struct drm_atomic_state *state,
struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state,
struct drm_crtc_state *new_crtc_state,
bool enable,
bool *lock_and_validation_needed)
{
struct dm_atomic_state *dm_state = NULL;
struct drm_crtc *crtc;
struct drm_crtc_state *old_crtc_state, *new_crtc_state;
int i;
struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state;
struct dc_stream_state *new_stream;
int ret = 0;
@ -5478,200 +5478,199 @@ static int dm_update_crtcs_state(struct amdgpu_display_manager *dm,
* TODO Move this code into dm_crtc_atomic_check once we get rid of dc_validation_set
* update changed items
*/
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
struct amdgpu_crtc *acrtc = NULL;
struct amdgpu_dm_connector *aconnector = NULL;
struct drm_connector_state *drm_new_conn_state = NULL, *drm_old_conn_state = NULL;
struct dm_connector_state *dm_new_conn_state = NULL, *dm_old_conn_state = NULL;
struct drm_plane_state *new_plane_state = NULL;
struct amdgpu_crtc *acrtc = NULL;
struct amdgpu_dm_connector *aconnector = NULL;
struct drm_connector_state *drm_new_conn_state = NULL, *drm_old_conn_state = NULL;
struct dm_connector_state *dm_new_conn_state = NULL, *dm_old_conn_state = NULL;
struct drm_plane_state *new_plane_state = NULL;
new_stream = NULL;
new_stream = NULL;
dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
acrtc = to_amdgpu_crtc(crtc);
dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
acrtc = to_amdgpu_crtc(crtc);
new_plane_state = drm_atomic_get_new_plane_state(state, new_crtc_state->crtc->primary);
new_plane_state = drm_atomic_get_new_plane_state(state, new_crtc_state->crtc->primary);
if (new_crtc_state->enable && new_plane_state && !new_plane_state->fb) {
if (new_crtc_state->enable && new_plane_state && !new_plane_state->fb) {
ret = -EINVAL;
goto fail;
}
aconnector = amdgpu_dm_find_first_crtc_matching_connector(state, crtc);
/* TODO This hack should go away */
if (aconnector && enable) {
/* Make sure fake sink is created in plug-in scenario */
drm_new_conn_state = drm_atomic_get_new_connector_state(state,
&aconnector->base);
drm_old_conn_state = drm_atomic_get_old_connector_state(state,
&aconnector->base);
if (IS_ERR(drm_new_conn_state)) {
ret = PTR_ERR_OR_ZERO(drm_new_conn_state);
goto fail;
}
dm_new_conn_state = to_dm_connector_state(drm_new_conn_state);
dm_old_conn_state = to_dm_connector_state(drm_old_conn_state);
new_stream = create_stream_for_sink(aconnector,
&new_crtc_state->mode,
dm_new_conn_state,
dm_old_crtc_state->stream);
/*
* we can have no stream on ACTION_SET if a display
* was disconnected during S3, in this case it is not an
* error, the OS will be updated after detection, and
* will do the right thing on next atomic commit
*/
if (!new_stream) {
DRM_DEBUG_DRIVER("%s: Failed to create new stream for crtc %d\n",
__func__, acrtc->base.base.id);
ret = -ENOMEM;
goto fail;
}
dm_new_crtc_state->abm_level = dm_new_conn_state->abm_level;
if (dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream) &&
dc_is_stream_scaling_unchanged(new_stream, dm_old_crtc_state->stream)) {
new_crtc_state->mode_changed = false;
DRM_DEBUG_DRIVER("Mode change not required, setting mode_changed to %d",
new_crtc_state->mode_changed);
}
}
if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
goto skip_modeset;
DRM_DEBUG_DRIVER(
"amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, "
"planes_changed:%d, mode_changed:%d,active_changed:%d,"
"connectors_changed:%d\n",
acrtc->crtc_id,
new_crtc_state->enable,
new_crtc_state->active,
new_crtc_state->planes_changed,
new_crtc_state->mode_changed,
new_crtc_state->active_changed,
new_crtc_state->connectors_changed);
/* Remove stream for any changed/disabled CRTC */
if (!enable) {
if (!dm_old_crtc_state->stream)
goto skip_modeset;
ret = dm_atomic_get_state(state, &dm_state);
if (ret)
goto fail;
DRM_DEBUG_DRIVER("Disabling DRM crtc: %d\n",
crtc->base.id);
/* i.e. reset mode */
if (dc_remove_stream_from_ctx(
dm->dc,
dm_state->context,
dm_old_crtc_state->stream) != DC_OK) {
ret = -EINVAL;
goto fail;
}
aconnector = amdgpu_dm_find_first_crtc_matching_connector(state, crtc);
dc_stream_release(dm_old_crtc_state->stream);
dm_new_crtc_state->stream = NULL;
/* TODO This hack should go away */
if (aconnector && enable) {
/* Make sure fake sink is created in plug-in scenario */
drm_new_conn_state = drm_atomic_get_new_connector_state(state,
&aconnector->base);
drm_old_conn_state = drm_atomic_get_old_connector_state(state,
&aconnector->base);
reset_freesync_config_for_crtc(dm_new_crtc_state);
if (IS_ERR(drm_new_conn_state)) {
ret = PTR_ERR_OR_ZERO(drm_new_conn_state);
break;
}
*lock_and_validation_needed = true;
dm_new_conn_state = to_dm_connector_state(drm_new_conn_state);
dm_old_conn_state = to_dm_connector_state(drm_old_conn_state);
} else {/* Add stream for any updated/enabled CRTC */
/*
* Quick fix to prevent NULL pointer on new_stream when
* added MST connectors not found in existing crtc_state in the chained mode
* TODO: need to dig out the root cause of that
*/
if (!aconnector || (!aconnector->dc_sink && aconnector->mst_port))
goto skip_modeset;
new_stream = create_stream_for_sink(aconnector,
&new_crtc_state->mode,
dm_new_conn_state,
dm_old_crtc_state->stream);
if (modereset_required(new_crtc_state))
goto skip_modeset;
/*
* we can have no stream on ACTION_SET if a display
* was disconnected during S3, in this case it is not an
* error, the OS will be updated after detection, and
* will do the right thing on next atomic commit
*/
if (modeset_required(new_crtc_state, new_stream,
dm_old_crtc_state->stream)) {
if (!new_stream) {
DRM_DEBUG_DRIVER("%s: Failed to create new stream for crtc %d\n",
__func__, acrtc->base.base.id);
break;
}
dm_new_crtc_state->abm_level = dm_new_conn_state->abm_level;
if (dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream) &&
dc_is_stream_scaling_unchanged(new_stream, dm_old_crtc_state->stream)) {
new_crtc_state->mode_changed = false;
DRM_DEBUG_DRIVER("Mode change not required, setting mode_changed to %d",
new_crtc_state->mode_changed);
}
}
if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
goto next_crtc;
DRM_DEBUG_DRIVER(
"amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, "
"planes_changed:%d, mode_changed:%d,active_changed:%d,"
"connectors_changed:%d\n",
acrtc->crtc_id,
new_crtc_state->enable,
new_crtc_state->active,
new_crtc_state->planes_changed,
new_crtc_state->mode_changed,
new_crtc_state->active_changed,
new_crtc_state->connectors_changed);
/* Remove stream for any changed/disabled CRTC */
if (!enable) {
if (!dm_old_crtc_state->stream)
goto next_crtc;
WARN_ON(dm_new_crtc_state->stream);
ret = dm_atomic_get_state(state, &dm_state);
if (ret)
goto fail;
DRM_DEBUG_DRIVER("Disabling DRM crtc: %d\n",
crtc->base.id);
dm_new_crtc_state->stream = new_stream;
/* i.e. reset mode */
if (dc_remove_stream_from_ctx(
dc_stream_retain(new_stream);
DRM_DEBUG_DRIVER("Enabling DRM crtc: %d\n",
crtc->base.id);
if (dc_add_stream_to_ctx(
dm->dc,
dm_state->context,
dm_old_crtc_state->stream) != DC_OK) {
dm_new_crtc_state->stream) != DC_OK) {
ret = -EINVAL;
goto fail;
}
dc_stream_release(dm_old_crtc_state->stream);
dm_new_crtc_state->stream = NULL;
reset_freesync_config_for_crtc(dm_new_crtc_state);
*lock_and_validation_needed = true;
} else {/* Add stream for any updated/enabled CRTC */
/*
* Quick fix to prevent NULL pointer on new_stream when
* added MST connectors not found in existing crtc_state in the chained mode
* TODO: need to dig out the root cause of that
*/
if (!aconnector || (!aconnector->dc_sink && aconnector->mst_port))
goto next_crtc;
if (modereset_required(new_crtc_state))
goto next_crtc;
if (modeset_required(new_crtc_state, new_stream,
dm_old_crtc_state->stream)) {
WARN_ON(dm_new_crtc_state->stream);
ret = dm_atomic_get_state(state, &dm_state);
if (ret)
goto fail;
dm_new_crtc_state->stream = new_stream;
dc_stream_retain(new_stream);
DRM_DEBUG_DRIVER("Enabling DRM crtc: %d\n",
crtc->base.id);
if (dc_add_stream_to_ctx(
dm->dc,
dm_state->context,
dm_new_crtc_state->stream) != DC_OK) {
ret = -EINVAL;
goto fail;
}
*lock_and_validation_needed = true;
}
}
next_crtc:
/* Release extra reference */
if (new_stream)
dc_stream_release(new_stream);
/*
* We want to do dc stream updates that do not require a
* full modeset below.
*/
if (!(enable && aconnector && new_crtc_state->enable &&
new_crtc_state->active))
continue;
/*
* Given above conditions, the dc state cannot be NULL because:
* 1. We're in the process of enabling CRTCs (just been added
* to the dc context, or already is on the context)
* 2. Has a valid connector attached, and
* 3. Is currently active and enabled.
* => The dc stream state currently exists.
*/
BUG_ON(dm_new_crtc_state->stream == NULL);
/* Scaling or underscan settings */
if (is_scaling_state_different(dm_old_conn_state, dm_new_conn_state))
update_stream_scaling_settings(
&new_crtc_state->mode, dm_new_conn_state, dm_new_crtc_state->stream);
/*
* Color management settings. We also update color properties
* when a modeset is needed, to ensure it gets reprogrammed.
*/
if (dm_new_crtc_state->base.color_mgmt_changed ||
drm_atomic_crtc_needs_modeset(new_crtc_state)) {
ret = amdgpu_dm_set_regamma_lut(dm_new_crtc_state);
if (ret)
goto fail;
amdgpu_dm_set_ctm(dm_new_crtc_state);
}
/* Update Freesync settings. */
get_freesync_config_for_crtc(dm_new_crtc_state,
dm_new_conn_state);
}
skip_modeset:
/* Release extra reference */
if (new_stream)
dc_stream_release(new_stream);
/*
* We want to do dc stream updates that do not require a
* full modeset below.
*/
if (!(enable && aconnector && new_crtc_state->enable &&
new_crtc_state->active))
return 0;
/*
* Given above conditions, the dc state cannot be NULL because:
* 1. We're in the process of enabling CRTCs (just been added
* to the dc context, or already is on the context)
* 2. Has a valid connector attached, and
* 3. Is currently active and enabled.
* => The dc stream state currently exists.
*/
BUG_ON(dm_new_crtc_state->stream == NULL);
/* Scaling or underscan settings */
if (is_scaling_state_different(dm_old_conn_state, dm_new_conn_state))
update_stream_scaling_settings(
&new_crtc_state->mode, dm_new_conn_state, dm_new_crtc_state->stream);
/*
* Color management settings. We also update color properties
* when a modeset is needed, to ensure it gets reprogrammed.
*/
if (dm_new_crtc_state->base.color_mgmt_changed ||
drm_atomic_crtc_needs_modeset(new_crtc_state)) {
ret = amdgpu_dm_set_regamma_lut(dm_new_crtc_state);
if (ret)
goto fail;
amdgpu_dm_set_ctm(dm_new_crtc_state);
}
/* Update Freesync settings. */
get_freesync_config_for_crtc(dm_new_crtc_state,
dm_new_conn_state);
return ret;
fail:
@ -6019,15 +6018,25 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
}
/* Disable all crtcs which require disable */
ret = dm_update_crtcs_state(&adev->dm, state, false, &lock_and_validation_needed);
if (ret) {
goto fail;
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
ret = dm_update_crtc_state(&adev->dm, state, crtc,
old_crtc_state,
new_crtc_state,
false,
&lock_and_validation_needed);
if (ret)
goto fail;
}
/* Enable all crtcs which require enable */
ret = dm_update_crtcs_state(&adev->dm, state, true, &lock_and_validation_needed);
if (ret) {
goto fail;
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
ret = dm_update_crtc_state(&adev->dm, state, crtc,
old_crtc_state,
new_crtc_state,
true,
&lock_and_validation_needed);
if (ret)
goto fail;
}
/* Add new/modified planes */