drm/amd/display: Unify loop for surface update and page flip.
authorAndrey Grodzovsky <Andrey.Grodzovsky@amd.com>
Mon, 15 May 2017 22:55:38 +0000 (18:55 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 26 Sep 2017 22:07:16 +0000 (18:07 -0400)
Remove extra loop we have for page flips and do flips in same loop we do
for surface create/update.
Add documentation for synchronization between commits on different crtcs.
Rename function to have DM prefix.

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_types.c

index 7d989b6..d6ea2d5 100644 (file)
@@ -2381,10 +2381,11 @@ static void amdgpu_dm_do_flip(
                                                 acrtc->crtc_id);
 }
 
-void dc_commit_surfaces(struct drm_atomic_state *state,
+static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state,
                        struct drm_device *dev,
                        struct amdgpu_display_manager *dm,
-                       struct drm_crtc *pcrtc)
+                       struct drm_crtc *pcrtc,
+                       bool *wait_for_vblank)
 {
        uint32_t i;
        struct drm_plane *plane;
@@ -2397,10 +2398,11 @@ void dc_commit_surfaces(struct drm_atomic_state *state,
        for_each_plane_in_state(state, plane, old_plane_state, i) {
                struct drm_plane_state *plane_state = plane->state;
                struct drm_crtc *crtc = plane_state->crtc;
+               struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(crtc);
                struct drm_framebuffer *fb = plane_state->fb;
                struct drm_connector *connector;
                struct dm_connector_state *dm_state = NULL;
-               struct amdgpu_crtc *acrtc_attach;
+
                enum dm_commit_action action;
                bool pflip_needed;
 
@@ -2409,13 +2411,13 @@ void dc_commit_surfaces(struct drm_atomic_state *state,
 
                action = get_dm_commit_action(crtc->state);
 
-               /* Surfaces are created under two scenarios:
-                * 1. This commit is not a page flip.
-                * 2. This commit is a page flip, and streams are created.
+               /*
+                * TODO - TO decide if it's a flip or surface update
+                * stop relying on allow_modeset flag and query DC
+                * using dc_check_update_surfaces_for_stream.
                 */
                pflip_needed = !state->allow_modeset;
-               if (!pflip_needed || action == DM_COMMIT_ACTION_DPMS_ON
-                               || action == DM_COMMIT_ACTION_SET) {
+               if (!pflip_needed) {
                        list_for_each_entry(connector,
                                            &dev->mode_config.connector_list,
                                            head) {
@@ -2445,11 +2447,23 @@ void dc_commit_surfaces(struct drm_atomic_state *state,
                        if (crtc == pcrtc) {
                                add_surface(dm->dc, crtc, plane,
                                            &dc_surfaces_constructed[planes_count]);
-                               acrtc_attach = to_amdgpu_crtc(crtc);
                                dc_stream_attach = acrtc_attach->stream;
                                planes_count++;
                        }
+               } else if (crtc->state->planes_changed) {
+                       *wait_for_vblank =
+                               acrtc_attach->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC ?
+                               false : true;
+
+                       amdgpu_dm_do_flip(
+                               crtc,
+                               fb,
+                               drm_crtc_vblank_count(crtc) + *wait_for_vblank);
+
+                       /*clean up the flags for next usage*/
+                       acrtc_attach->flip_flags = 0;
                }
+
        }
 
        if (planes_count) {
@@ -2471,8 +2485,6 @@ void amdgpu_dm_atomic_commit_tail(
        struct drm_device *dev = state->dev;
        struct amdgpu_device *adev = dev->dev_private;
        struct amdgpu_display_manager *dm = &adev->dm;
-       struct drm_plane *plane;
-       struct drm_plane_state *old_plane_state;
        uint32_t i, j;
        uint32_t commit_streams_count = 0;
        uint32_t new_crtcs_count = 0;
@@ -2637,7 +2649,7 @@ void amdgpu_dm_atomic_commit_tail(
 
        /* update planes when needed per crtc*/
        for_each_crtc_in_state(state, pcrtc, old_crtc_state, j)
-               dc_commit_surfaces(state, dev, dm, pcrtc);
+               amdgpu_dm_commit_surfaces(state, dev, dm, pcrtc, &wait_for_vblank);
 
        for (i = 0; i < new_crtcs_count; i++) {
                /*
@@ -2651,34 +2663,6 @@ void amdgpu_dm_atomic_commit_tail(
 
                manage_dm_interrupts(adev, acrtc, true);
                dm_crtc_cursor_reset(&acrtc->base);
-
-       }
-
-       for_each_plane_in_state(state, plane, old_plane_state, i) {
-               struct drm_plane_state *plane_state = plane->state;
-               struct drm_crtc *crtc = plane_state->crtc;
-               struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
-               struct drm_framebuffer *fb = plane_state->fb;
-               bool pflip_needed;
-
-               if (!fb || !crtc || !crtc->state->planes_changed ||
-                       !crtc->state->active)
-                       continue;
-               pflip_needed = !state->allow_modeset;
-
-               if (pflip_needed) {
-                       wait_for_vblank =
-                               acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC ?
-                               false : true;
-
-                       amdgpu_dm_do_flip(
-                               crtc,
-                               fb,
-                               drm_crtc_vblank_count(crtc) + wait_for_vblank);
-
-                       /*clean up the flags for next usage*/
-                       acrtc->flip_flags = 0;
-               }
        }
 
 
@@ -2901,7 +2885,11 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
        struct dc *dc = adev->dm.dc;
        bool need_to_validate = false;
        struct validate_context *context;
-       bool wait_4_prev_commits = false;
+       /*
+        * This bool will be set for true for any modeset/reset
+        * or surface update which implies non fast surfae update.
+        */
+       bool wait_for_prev_commits = false;
 
        ret = drm_atomic_helper_check(dev, state);
 
@@ -2978,7 +2966,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
 
                        new_stream_count++;
                        need_to_validate = true;
-                       wait_4_prev_commits = true;
+                       wait_for_prev_commits = true;
                        break;
                }
 
@@ -3024,7 +3012,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
 
                        new_stream_count++;
                        need_to_validate = true;
-                       wait_4_prev_commits = true;
+                       wait_for_prev_commits = true;
 
                        break;
                }
@@ -3036,7 +3024,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
                                                set,
                                                set_count,
                                                acrtc->stream);
-                               wait_4_prev_commits = true;
+                               wait_for_prev_commits = true;
                        }
                        break;
                }
@@ -3132,8 +3120,16 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
        if (need_to_validate == false || set_count == 0 || context) {
 
                ret = 0;
-
-               if (wait_4_prev_commits) {
+               /*
+                * For full updates case when
+                * removing/adding/updateding  streams on once CRTC while flipping
+                * on another CRTC,
+                * Adding all current active CRTC's states to the atomic commit in
+                * amdgpu_dm_atomic_check will guarantee that any such full update commit
+                * will wait for completion of any outstanding flip using DRMs
+                * synchronization events.
+                */
+               if (wait_for_prev_commits) {
                        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                                struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
                                struct drm_crtc_state *crtc_state;