OSDN Git Service

drm/amd/display: Refactor atomic check.
authorAndrey Grodzovsky <Andrey.Grodzovsky@amd.com>
Fri, 18 Aug 2017 14:52:20 +0000 (10:52 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 26 Sep 2017 22:17:06 +0000 (18:17 -0400)
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

index e8835e7..193a634 100644 (file)
@@ -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;
 }