From: Andrey Grodzovsky <andrey.grodzov...@amd.com>

Remove acrtc->stream and move it into dm_crtc_state.
This allows to get rid of dm_atomic_state->dm_set.
Also reuse streams created in atomic_check during
commit.

Change-Id: I8d9868695a3a530c55e7fa934f9d5ea3800dfb8b
Signed-off-by: Andrey Grodzovsky <andrey.grodzov...@amd.com>
Reviewed-by: Tony Cheng <tony.ch...@amd.com>
Acked-by: Harry Wentland <harry.wentl...@amd.com>
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c  |  33 +-
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c    | 411 +++++++++++----------
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.h    |   9 +-
 drivers/gpu/drm/amd/display/dc/dc.h                |   2 -
 4 files changed, 232 insertions(+), 223 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 d0651b6..e5a27ab 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -100,13 +100,16 @@ static u32 dm_vblank_get_counter(struct amdgpu_device 
*adev, int crtc)
                return 0;
        else {
                struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc];
+               struct dm_crtc_state *acrtc_state = to_dm_crtc_state(
+                               acrtc->base.state);
 
-               if (NULL == acrtc->stream) {
+
+               if (acrtc_state->stream == NULL) {
                        DRM_ERROR("dc_stream is NULL for crtc '%d'!\n", crtc);
                        return 0;
                }
 
-               return dc_stream_get_vblank_counter(acrtc->stream);
+               return dc_stream_get_vblank_counter(acrtc_state->stream);
        }
 }
 
@@ -119,8 +122,10 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device 
*adev, int crtc,
                return -EINVAL;
        else {
                struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc];
+               struct dm_crtc_state *acrtc_state = to_dm_crtc_state(
+                                               acrtc->base.state);
 
-               if (NULL == acrtc->stream) {
+               if (acrtc_state->stream ==  NULL) {
                        DRM_ERROR("dc_stream is NULL for crtc '%d'!\n", crtc);
                        return 0;
                }
@@ -129,7 +134,7 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device 
*adev, int crtc,
                 * TODO rework base driver to use values directly.
                 * for now parse it back into reg-format
                 */
-               dc_stream_get_scanoutpos(acrtc->stream,
+               dc_stream_get_scanoutpos(acrtc_state->stream,
                                         &v_blank_start,
                                         &v_blank_end,
                                         &h_position,
@@ -652,22 +657,12 @@ dm_atomic_state_alloc(struct drm_device *dev)
 void dm_atomic_state_clear(struct drm_atomic_state *state)
 {
        struct dm_atomic_state *dm_state = to_dm_atomic_state(state);
-       int i, j;
-
-       for (i = 0; i < dm_state->set_count; i++) {
-               for (j = 0; j < dm_state->set[i].surface_count; j++) {
-                       dc_surface_release(dm_state->set[i].surfaces[j]);
-                       dm_state->set[i].surfaces[j] = NULL;
-               }
 
-               dc_stream_release(dm_state->set[i].stream);
-               dm_state->set[i].stream = NULL;
+       if (dm_state->context) {
+               dc_resource_validate_ctx_destruct(dm_state->context);
+               dm_free(dm_state->context);
+               dm_state->context = NULL;
        }
-       dm_state->set_count = 0;
-
-       dc_resource_validate_ctx_destruct(dm_state->context);
-       dm_free(dm_state->context);
-       dm_state->context = NULL;
 
        drm_atomic_state_default_clear(state);
 }
@@ -676,7 +671,7 @@ static const struct drm_mode_config_funcs 
amdgpu_dm_mode_funcs = {
        .fb_create = amdgpu_user_framebuffer_create,
        .output_poll_changed = amdgpu_output_poll_changed,
        .atomic_check = amdgpu_dm_atomic_check,
-       .atomic_commit = drm_atomic_helper_commit,
+       .atomic_commit = amdgpu_dm_atomic_commit,
        .atomic_state_alloc = dm_atomic_state_alloc,
        .atomic_state_clear = dm_atomic_state_clear,
 };
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c
index 2a5c7b1..750e095 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c
@@ -87,6 +87,7 @@ static void dm_set_cursor(
        struct drm_crtc *crtc = &amdgpu_crtc->base;
        int x, y;
        int xorigin = 0, yorigin = 0;
+       struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state);
 
        amdgpu_crtc->cursor_width = width;
        amdgpu_crtc->cursor_height = height;
@@ -125,13 +126,13 @@ static void dm_set_cursor(
        position.y_hotspot = yorigin;
 
        if (!dc_stream_set_cursor_attributes(
-                               amdgpu_crtc->stream,
+                               acrtc_state->stream,
                                &attributes)) {
                DRM_ERROR("DC failed to set cursor attributes\n");
        }
 
        if (!dc_stream_set_cursor_position(
-                               amdgpu_crtc->stream,
+                               acrtc_state->stream,
                                &position)) {
                DRM_ERROR("DC failed to set cursor position\n");
        }
@@ -144,6 +145,7 @@ static int dm_crtc_cursor_set(
        uint32_t height)
 {
        struct dc_cursor_position position;
+       struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state);
 
        int ret;
 
@@ -163,10 +165,10 @@ static int dm_crtc_cursor_set(
                position.x = 0;
                position.y = 0;
 
-               if (amdgpu_crtc->stream) {
+               if (acrtc_state->stream) {
                        /*set cursor visible false*/
                        dc_stream_set_cursor_position(
-                               amdgpu_crtc->stream,
+                               acrtc_state->stream,
                                &position);
                }
                goto release;
@@ -197,6 +199,7 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc,
        struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
        int xorigin = 0, yorigin = 0;
        struct dc_cursor_position position;
+       struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state);
 
        amdgpu_crtc->cursor_x = x;
        amdgpu_crtc->cursor_y = y;
@@ -234,9 +237,9 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc,
        position.x_hotspot = xorigin;
        position.y_hotspot = yorigin;
 
-       if (amdgpu_crtc->stream) {
+       if (acrtc_state->stream) {
                if (!dc_stream_set_cursor_position(
-                                       amdgpu_crtc->stream,
+                                       acrtc_state->stream,
                                        &position)) {
                        DRM_ERROR("DC failed to set cursor position\n");
                        return -EINVAL;
@@ -612,7 +615,8 @@ static void add_surface(struct dc *dc,
 {
        struct dc_surface *dc_surface;
        struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
-       const struct dc_stream *dc_stream = acrtc->stream;
+       struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state);
+       const struct dc_stream *dc_stream = acrtc_state->stream;
        unsigned long flags;
 
        spin_lock_irqsave(&crtc->dev->event_lock, flags);
@@ -1038,11 +1042,10 @@ static void dm_crtc_destroy_state(struct drm_crtc *crtc,
 {
        struct dm_crtc_state *cur = to_dm_crtc_state(state);
 
-       if (cur->dc_stream) {
-               /* TODO Destroy dc_stream objects are stream object is 
flattened */
-               dm_free(cur->dc_stream);
-       } else
-               WARN_ON(1);
+       /* TODO Destroy dc_stream objects are stream object is flattened */
+       if (cur->stream)
+               dc_stream_release(cur->stream);
+
 
        __drm_atomic_helper_crtc_destroy_state(state);
 
@@ -1061,40 +1064,29 @@ static void dm_crtc_reset_state(struct drm_crtc *crtc)
        if (WARN_ON(!state))
                return;
 
-
        crtc->state = &state->base;
        crtc->state->crtc = crtc;
 
-       state->dc_stream = dm_alloc(sizeof(*state->dc_stream));
-       WARN_ON(!state->dc_stream);
 }
 
 static struct drm_crtc_state *
 dm_crtc_duplicate_state(struct drm_crtc *crtc)
 {
        struct dm_crtc_state *state, *cur;
-       struct dc_stream *dc_stream;
-
-       if (WARN_ON(!crtc->state))
-               return NULL;
 
        cur = to_dm_crtc_state(crtc->state);
-       if (WARN_ON(!cur->dc_stream))
-               return NULL;
 
-       dc_stream = dm_alloc(sizeof(*dc_stream));
-       if (WARN_ON(!dc_stream))
+       if (WARN_ON(!crtc->state))
                return NULL;
 
        state = dm_alloc(sizeof(*state));
-       if (WARN_ON(!state)) {
-               dm_free(dc_stream);
-               return NULL;
-       }
 
        __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
 
-       state->dc_stream = dc_stream;
+       if (cur->stream) {
+               state->stream = cur->stream;
+               dc_stream_retain(state->stream);
+       }
 
        /* TODO Duplicate dc_stream after objects are stream object is 
flattened */
 
@@ -1161,6 +1153,7 @@ static int amdgpu_freesync_set_property_atomic(
        struct amdgpu_crtc *acrtc;
        int ret;
        uint64_t val_capable;
+       struct dm_crtc_state *acrtc_state;
 
        dev  = connector->dev;
        adev = dev->dev_private;
@@ -1184,9 +1177,12 @@ static int amdgpu_freesync_set_property_atomic(
                user_enable.enable_for_video  = user_enable.enable_for_gaming;
                ret  = -EINVAL;
                acrtc = to_amdgpu_crtc(connector_state->crtc);
-               if (connector_state->connector == connector && acrtc->stream) {
+               acrtc_state = to_dm_crtc_state(connector_state->crtc->state);
+
+
+               if (connector_state->connector == connector && 
acrtc_state->stream) {
                        mod_freesync_set_user_enable(adev->dm.freesync_module,
-                                                    &acrtc->stream, 1,
+                                                    &acrtc_state->stream, 1,
                                                     &user_enable);
                        ret = 0;
                }
@@ -2401,21 +2397,15 @@ static bool is_scaling_state_different(
        return false;
 }
 
-static void remove_stream(struct amdgpu_device *adev, struct amdgpu_crtc 
*acrtc)
+static void remove_stream(
+               struct amdgpu_device *adev,
+               struct amdgpu_crtc *acrtc,
+               const struct dc_stream *stream)
 {
-       /*
-        * we evade vblanks and pflips on crtc that
-        * should be changed
-        */
-       manage_dm_interrupts(adev, acrtc, false);
-
        /* this is the update mode case */
        if (adev->dm.freesync_module)
-               mod_freesync_remove_stream(adev->dm.freesync_module,
-                                          acrtc->stream);
+               mod_freesync_remove_stream(adev->dm.freesync_module, stream);
 
-       dc_stream_release(acrtc->stream);
-       acrtc->stream = NULL;
        acrtc->otg_inst = -1;
        acrtc->enabled = false;
 }
@@ -2487,6 +2477,8 @@ static void amdgpu_dm_do_flip(
        bool async_flip = (acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0;
        struct dc_flip_addrs addr = { {0} };
        struct dc_surface_update surface_updates[1] = { {0} };
+       struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state);
+
 
        /* Prepare wait for target vblank early - before the fence-waits */
        target_vblank = target - drm_crtc_vblank_count(crtc) +
@@ -2529,7 +2521,7 @@ static void amdgpu_dm_do_flip(
        crtc->primary->fb = fb;
 
        WARN_ON(acrtc->pflip_status != AMDGPU_FLIP_NONE);
-       WARN_ON(!acrtc->stream);
+       WARN_ON(!acrtc_state->stream);
 
        addr.address.grph.addr.low_part = lower_32_bits(afb->address);
        addr.address.grph.addr.high_part = upper_32_bits(afb->address);
@@ -2539,11 +2531,11 @@ static void amdgpu_dm_do_flip(
        if (acrtc->base.state->event)
                prepare_flip_isr(acrtc);
 
-       surface_updates->surface = 
dc_stream_get_status(acrtc->stream)->surfaces[0];
+       surface_updates->surface = 
dc_stream_get_status(acrtc_state->stream)->surfaces[0];
        surface_updates->flip_addr = &addr;
 
 
-       dc_update_surfaces_and_stream(adev->dm.dc, surface_updates, 1, 
acrtc->stream, NULL);
+       dc_update_surfaces_and_stream(adev->dm.dc, surface_updates, 1, 
acrtc_state->stream, NULL);
 
        DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n",
                         __func__,
@@ -2566,6 +2558,7 @@ static void amdgpu_dm_commit_surfaces(struct 
drm_atomic_state *state,
        const struct dc_stream *dc_stream_attach;
        const struct dc_surface *dc_surfaces_constructed[MAX_SURFACES];
        struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc);
+       struct dm_crtc_state *acrtc_state = to_dm_crtc_state(pcrtc->state);
        int planes_count = 0;
 
        /* update planes when needed */
@@ -2620,7 +2613,7 @@ static void amdgpu_dm_commit_surfaces(struct 
drm_atomic_state *state,
                                dm_error("%s: Failed to add surface!\n", 
__func__);
                                continue;
                        }
-                       dc_stream_attach = acrtc_attach->stream;
+                       dc_stream_attach = acrtc_state->stream;
                        planes_count++;
 
                } else if (crtc->state->planes_changed) {
@@ -2675,6 +2668,37 @@ static void amdgpu_dm_commit_surfaces(struct 
drm_atomic_state *state,
        }
 }
 
+
+int amdgpu_dm_atomic_commit(
+               struct drm_device *dev,
+               struct drm_atomic_state *state,
+               bool nonblock)
+{
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *new_state;
+       struct amdgpu_device *adev = dev->dev_private;
+       int i;
+
+       /*
+        * We evade vblanks and pflips on crtc that
+        * should be changed. We do it here to flush & disable
+        * interrupts before drm_swap_state is called in 
drm_atomic_helper_commit
+        * it will update crtc->dm_crtc_state->stream pointer which is used in
+        * the ISRs.
+        */
+       for_each_crtc_in_state(state, crtc, new_state, i) {
+               struct dm_crtc_state *old_acrtc_state = 
to_dm_crtc_state(crtc->state);
+               struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+
+               if (drm_atomic_crtc_needs_modeset(new_state) && 
old_acrtc_state->stream)
+                       manage_dm_interrupts(adev, acrtc, false);
+       }
+
+       return drm_atomic_helper_commit(dev, state, nonblock);
+
+       /*TODO Handle EINTR, reenable IRQ*/
+}
+
 void amdgpu_dm_atomic_commit_tail(
        struct drm_atomic_state *state)
 {
@@ -2692,6 +2716,7 @@ void amdgpu_dm_atomic_commit_tail(
        bool wait_for_vblank = true;
        struct drm_connector *connector;
        struct drm_connector_state *old_conn_state;
+       struct dm_crtc_state *old_acrtc_state, *new_acrtc_state;
 
        drm_atomic_helper_update_legacy_modeset_state(dev, state);
 
@@ -2699,16 +2724,10 @@ void amdgpu_dm_atomic_commit_tail(
 
        /* update changed items */
        for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
-               struct amdgpu_crtc *acrtc;
-               struct amdgpu_connector *aconnector = NULL;
+               struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
                struct drm_crtc_state *new_state = crtc->state;
-
-               acrtc = to_amdgpu_crtc(crtc);
-               aconnector =
-                       amdgpu_dm_find_first_crct_matching_connector(
-                               state,
-                               crtc,
-                               false);
+               new_acrtc_state = to_dm_crtc_state(new_state);
+               old_acrtc_state = to_dm_crtc_state(old_crtc_state);
 
                DRM_DEBUG_KMS(
                        "amdgpu_crtc id:%d crtc_state_flags: enable:%d, 
active:%d, "
@@ -2727,109 +2746,60 @@ void amdgpu_dm_atomic_commit_tail(
                 */
 
                if (modeset_required(new_state)) {
-                       struct dm_connector_state *dm_conn_state = NULL;
-                       new_stream = NULL;
-
-                       if (aconnector)
-                               dm_conn_state = 
to_dm_connector_state(aconnector->base.state);
-
-                       new_stream = create_stream_for_sink(
-                                       aconnector,
-                                       &crtc->state->mode,
-                                       dm_conn_state);
 
                        DRM_INFO("Atomic commit: SET crtc id %d: [%p]\n", 
acrtc->crtc_id, acrtc);
 
-                       if (!new_stream) {
+                       if (!new_acrtc_state->stream) {
                                /*
-                                * this could happen because of issues with
-                                * userspace notifications delivery.
-                                * In this case userspace tries to set mode on
-                                * display which is disconnect in fact.
-                                * dc_sink in NULL in this case on aconnector.
-                                * We expect reset mode will come soon.
-                                *
-                                * This can also happen when unplug is done
-                                * during resume sequence ended
-                                *
-                                * In this case, we want to pretend we still
-                                * have a sink to keep the pipe running so that
-                                * hw state is consistent with the sw state
-                                */
+                               * this could happen because of issues with
+                               * userspace notifications delivery.
+                               * In this case userspace tries to set mode on
+                               * display which is disconnect in fact.
+                               * dc_sink in NULL in this case on aconnector.
+                               * We expect reset mode will come soon.
+                               *
+                               * This can also happen when unplug is done
+                               * during resume sequence ended
+                               *
+                               * In this case, we want to pretend we still
+                               * have a sink to keep the pipe running so that
+                               * hw state is consistent with the sw state
+                               */
                                DRM_DEBUG_KMS("%s: Failed to create new stream 
for crtc %d\n",
                                                __func__, acrtc->base.base.id);
-                               break;
+                               continue;
                        }
 
-                       if (acrtc->stream)
-                               remove_stream(adev, acrtc);
 
-                       /* TODO clean this stupid hack */
-                       for (j = 0; j < dm_state->set_count; j++)
-                               if (dm_state->set[j].stream->priv == acrtc) {
-                                       ASSERT(acrtc->stream == NULL);
-                                       new_stream = dm_state->set[j].stream;
-                                       break;
-                               }
+                       if (old_acrtc_state->stream)
+                               remove_stream(adev, acrtc, 
old_acrtc_state->stream);
+
 
                        /*
                         * this loop saves set mode crtcs
                         * we needed to enable vblanks once all
                         * resources acquired in dc after dc_commit_streams
                         */
+
+                       /*TODO move all this into dm_crtc_state, get rid of
+                        * new_crtcs array and use old and new atomic states
+                        * instead
+                        */
                        new_crtcs[new_crtcs_count] = acrtc;
                        new_crtcs_count++;
 
-                       acrtc->stream = new_stream;
                        acrtc->enabled = true;
                        acrtc->hw_mode = crtc->state->mode;
                        crtc->hwmode = crtc->state->mode;
                } else if (modereset_required(new_state)) {
-
                        DRM_INFO("Atomic commit: RESET. crtc id %d:[%p]\n", 
acrtc->crtc_id, acrtc);
+
                        /* i.e. reset mode */
-                       if (acrtc->stream)
-                               remove_stream(adev, acrtc);
+                       if (old_acrtc_state->stream)
+                               remove_stream(adev, acrtc, 
old_acrtc_state->stream);
                }
        } /* for_each_crtc_in_state() */
 
-       /* Handle scaling and undersacn changes*/
-       for_each_connector_in_state(state, connector, old_conn_state, i) {
-               struct amdgpu_connector *aconnector = 
to_amdgpu_connector(connector);
-               struct dm_connector_state *con_new_state =
-                               to_dm_connector_state(aconnector->base.state);
-               struct dm_connector_state *con_old_state =
-                               to_dm_connector_state(old_conn_state);
-               struct amdgpu_crtc *acrtc = 
to_amdgpu_crtc(con_new_state->base.crtc);
-               const struct dc_stream_status *status = NULL;
-
-               /* Skip any modesets/resets */
-               if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state))
-                       continue;
-
-               /* Skip any thing not scale or underscan chnages */
-               if (!is_scaling_state_different(con_new_state, con_old_state))
-                       continue;
-
-               update_stream_scaling_settings(&con_new_state->base.crtc->mode,
-                               con_new_state, (struct dc_stream 
*)acrtc->stream);
-
-               status = dc_stream_get_status(acrtc->stream);
-               WARN_ON(!status);
-               WARN_ON(!status->surface_count);
-
-               if (!acrtc->stream)
-                       continue;
-
-               /*TODO How it works with MPO ?*/
-               if (!dc_commit_surfaces_to_stream(
-                               dm->dc,
-                               (const struct dc_surface **)status->surfaces,
-                               status->surface_count,
-                               acrtc->stream))
-                       dm_error("%s: Failed to update stream scaling!\n", 
__func__);
-       }
-
        /*
         * Add streams after required streams from new and replaced streams
         * are removed from freesync module
@@ -2837,7 +2807,9 @@ void amdgpu_dm_atomic_commit_tail(
        if (adev->dm.freesync_module) {
                for (i = 0; i < new_crtcs_count; i++) {
                        struct amdgpu_connector *aconnector = NULL;
-                       new_stream = new_crtcs[i]->stream;
+                       new_acrtc_state = 
to_dm_crtc_state(new_crtcs[i]->base.state);
+
+                       new_stream = new_acrtc_state->stream;
                        aconnector =
                                amdgpu_dm_find_first_crct_matching_connector(
                                        state,
@@ -2862,35 +2834,77 @@ void amdgpu_dm_atomic_commit_tail(
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+               new_acrtc_state = to_dm_crtc_state(crtc->state);
 
-               if (acrtc->stream != NULL) {
-                       const struct dc_stream_status *status = 
dc_stream_get_status(acrtc->stream);
+               if (new_acrtc_state->stream != NULL) {
+                       const struct dc_stream_status *status =
+                                       
dc_stream_get_status(new_acrtc_state->stream);
 
                        if (!status)
-                               DC_ERR("got no status for stream %p on 
acrtc%p\n", acrtc->stream, acrtc);
+                               DC_ERR("got no status for stream %p on 
acrtc%p\n", new_acrtc_state->stream, acrtc);
                        else
                                acrtc->otg_inst = status->primary_otg_inst;
                }
        }
 
+       /* Handle scaling and undersacn changes*/
+       for_each_connector_in_state(state, connector, old_conn_state, i) {
+               struct amdgpu_connector *aconnector = 
to_amdgpu_connector(connector);
+               struct dm_connector_state *con_new_state =
+                               to_dm_connector_state(aconnector->base.state);
+               struct dm_connector_state *con_old_state =
+                               to_dm_connector_state(old_conn_state);
+               struct amdgpu_crtc *acrtc = 
to_amdgpu_crtc(con_new_state->base.crtc);
+               const struct dc_stream_status *status = NULL;
+
+               /* Skip any modesets/resets */
+               if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state))
+                       continue;
+
+               /* Skip any thing not scale or underscan changes */
+               if (!is_scaling_state_different(con_new_state, con_old_state))
+                       continue;
+
+               new_acrtc_state = to_dm_crtc_state(acrtc->base.state);
+
+               update_stream_scaling_settings(&con_new_state->base.crtc->mode,
+                               con_new_state, (struct dc_stream 
*)new_acrtc_state->stream);
+
+               status = dc_stream_get_status(new_acrtc_state->stream);
+               WARN_ON(!status);
+               WARN_ON(!status->surface_count);
+
+               if (!new_acrtc_state->stream)
+                       continue;
+
+               /*TODO How it works with MPO ?*/
+               if (!dc_commit_surfaces_to_stream(
+                               dm->dc,
+                               (const struct dc_surface **)status->surfaces,
+                               status->surface_count,
+                               new_acrtc_state->stream))
+                       dm_error("%s: Failed to update stream scaling!\n", 
__func__);
+       }
+
        for (i = 0; i < new_crtcs_count; i++) {
                /*
                 * loop to enable interrupts on newly arrived crtc
                 */
                struct amdgpu_crtc *acrtc = new_crtcs[i];
+               new_acrtc_state = to_dm_crtc_state(acrtc->base.state);
 
                if (adev->dm.freesync_module)
                        mod_freesync_notify_mode_change(
-                               adev->dm.freesync_module, &acrtc->stream, 1);
+                               adev->dm.freesync_module, 
&new_acrtc_state->stream, 1);
 
                manage_dm_interrupts(adev, acrtc, true);
        }
 
        /* update planes when needed per crtc*/
        for_each_crtc_in_state(state, pcrtc, old_crtc_state, j) {
-               struct amdgpu_crtc *acrtc = to_amdgpu_crtc(pcrtc);
+               new_acrtc_state = to_dm_crtc_state(pcrtc->state);
 
-               if (acrtc->stream)
+               if (new_acrtc_state->stream)
                        amdgpu_dm_commit_surfaces(state, dev, dm, pcrtc, 
&wait_for_vblank);
        }
 
@@ -2986,13 +3000,15 @@ void dm_restore_drm_connector_state(struct drm_device 
*dev, struct drm_connector
 {
        struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
        struct amdgpu_crtc *disconnected_acrtc;
+       struct dm_crtc_state *acrtc_state;
 
        if (!aconnector->dc_sink || !connector->state || !connector->encoder)
                return;
 
        disconnected_acrtc = to_amdgpu_crtc(connector->encoder->crtc);
+       acrtc_state = to_dm_crtc_state(disconnected_acrtc->base.state);
 
-       if (!disconnected_acrtc || !disconnected_acrtc->stream)
+       if (!disconnected_acrtc || !acrtc_state->stream)
                return;
 
        /*
@@ -3000,7 +3016,7 @@ void dm_restore_drm_connector_state(struct drm_device 
*dev, struct drm_connector
         * we deduce we are in a state where we can not rely on usermode call
         * to turn on the display, so we do it here
         */
-       if (disconnected_acrtc->stream->sink != aconnector->dc_sink)
+       if (acrtc_state->stream->sink != aconnector->dc_sink)
                dm_force_atomic_commit(&aconnector->base);
 }
 
@@ -3044,17 +3060,11 @@ static uint32_t update_in_val_sets_stream(
        }
 
        val_sets[i].stream = new_stream;
-       dc_stream_retain(new_stream);
        crtcs[i] = crtc;
 
-       if (i == set_count) {
+       if (i == set_count)
                /* nothing found. add new one to the end */
                return set_count + 1;
-       } else {
-               /* update. relase old stream */
-               dc_stream_release(old_stream);
-
-       }
 
        return set_count;
 }
@@ -3075,7 +3085,6 @@ static uint32_t remove_from_val_sets(
                return set_count;
        }
 
-       dc_stream_release(stream);
        set_count--;
 
        for (; i < set_count; i++) {
@@ -3145,14 +3154,16 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
        struct drm_plane_state *plane_state;
        int i, j;
        int ret;
-       int new_stream_count;
-       struct dc_stream *new_streams[MAX_STREAMS] = { 0 };
        struct drm_crtc *crtc_set[MAX_STREAMS] = { 0 };
        struct amdgpu_device *adev = dev->dev_private;
        struct dc *dc = adev->dm.dc;
        bool need_to_validate = false;
        struct drm_connector *connector;
        struct drm_connector_state *conn_state;
+       int set_count;
+       struct dc_validation_set set[MAX_STREAMS] = { { 0 } };
+       struct dm_crtc_state *old_acrtc_state, *new_acrtc_state;
+
        /*
         * This bool will be set for true for any modeset/reset
         * or surface update which implies non fast surfae update.
@@ -3172,17 +3183,16 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
        dm_state = to_dm_atomic_state(state);
 
        /* copy existing configuration */
-       new_stream_count = 0;
-       dm_state->set_count = 0;
+       set_count = 0;
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 
-               struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+               old_acrtc_state = to_dm_crtc_state(crtc->state);
 
-               if (acrtc->stream) {
-                       dc_stream_retain(acrtc->stream);
-                       dm_state->set[dm_state->set_count].stream = 
acrtc->stream;
-                       crtc_set[dm_state->set_count] = crtc;
-                       ++dm_state->set_count;
+               if (old_acrtc_state->stream) {
+                       dc_stream_retain(old_acrtc_state->stream);
+                       set[set_count].stream = old_acrtc_state->stream;
+                       crtc_set[set_count] = crtc;
+                       ++set_count;
                }
        }
 
@@ -3190,7 +3200,8 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
        for_each_crtc_in_state(state, crtc, crtc_state, i) {
                struct amdgpu_crtc *acrtc = NULL;
                struct amdgpu_connector *aconnector = NULL;
-
+               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);
@@ -3221,7 +3232,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
                        }
 
                        new_stream = create_stream_for_sink(aconnector, 
&crtc_state->mode, dm_conn_state);
-                       new_stream->priv = acrtc;
 
                        /*
                         * we can have no stream on ACTION_SET if a display
@@ -3235,27 +3245,33 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
                                break;
                        }
 
-                       new_streams[new_stream_count] = new_stream;
-                       dm_state->set_count = update_in_val_sets_stream(
-                                       dm_state->set,
+                       if (new_acrtc_state->stream)
+                               dc_stream_release(new_acrtc_state->stream);
+                       new_acrtc_state->stream = new_stream;
+
+                       set_count = update_in_val_sets_stream(
+                                       set,
                                        crtc_set,
-                                       dm_state->set_count,
-                                       acrtc->stream,
-                                       new_stream,
+                                       set_count,
+                                       old_acrtc_state->stream,
+                                       new_acrtc_state->stream,
                                        crtc);
 
-                       new_stream_count++;
                        need_to_validate = true;
                        aquire_global_lock = true;
 
                } else if (modereset_required(crtc_state)) {
 
                        /* i.e. reset mode */
-                       if (acrtc->stream) {
-                               dm_state->set_count = remove_from_val_sets(
-                                               dm_state->set,
-                                               dm_state->set_count,
-                                               acrtc->stream);
+                       if (new_acrtc_state->stream) {
+                               set_count = remove_from_val_sets(
+                                               set,
+                                               set_count,
+                                               new_acrtc_state->stream);
+
+                               dc_stream_release(new_acrtc_state->stream);
+                               new_acrtc_state->stream = NULL;
+
                                aquire_global_lock = true;
                        }
                }
@@ -3276,6 +3292,10 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
        }
 
        /* 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
+        * decide how to handle.
+        */
        for_each_connector_in_state(state, connector, conn_state, i) {
                struct amdgpu_connector *aconnector = 
to_amdgpu_connector(connector);
                struct dm_connector_state *con_old_state =
@@ -3283,7 +3303,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
                struct dm_connector_state *con_new_state =
                                                
to_dm_connector_state(conn_state);
                struct amdgpu_crtc *acrtc = 
to_amdgpu_crtc(con_new_state->base.crtc);
-               struct dc_stream *new_stream;
 
                /* Skip any modesets/resets */
                if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state))
@@ -3293,32 +3312,11 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
                if (!is_scaling_state_different(con_new_state, con_old_state))
                        continue;
 
-               new_stream = create_stream_for_sink(
-                               aconnector,
-                               &acrtc->base.state->mode,
-                               con_new_state);
-
-               if (!new_stream) {
-                       DRM_ERROR("%s: Failed to create new stream for crtc 
%d\n",
-                                       __func__, acrtc->base.base.id);
-                       continue;
-               }
-
-               new_streams[new_stream_count] = new_stream;
-               dm_state->set_count = update_in_val_sets_stream(
-                               dm_state->set,
-                               crtc_set,
-                               dm_state->set_count,
-                               acrtc->stream,
-                               new_stream,
-                               &acrtc->base);
-
-               new_stream_count++;
                need_to_validate = true;
                aquire_global_lock = true;
        }
 
-       for (i = 0; i < dm_state->set_count; i++) {
+       for (i = 0; i < set_count; i++) {
                for_each_plane_in_state(state, plane, plane_state, j) {
                        struct drm_crtc *crtc = plane_state->crtc;
                        struct drm_framebuffer *fb = plane_state->fb;
@@ -3374,9 +3372,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
                                        plane_state,
                                        false);
 
-                               add_val_sets_surface(dm_state->set,
-                                                    dm_state->set_count,
-                                                    dm_state->set[i].stream,
+                               add_val_sets_surface(set,
+                                                    set_count,
+                                                    set[i].stream,
                                                     surface);
 
                                need_to_validate = true;
@@ -3385,9 +3383,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
                }
        }
 
-       dm_state->context = dc_get_validate_context(dc, dm_state->set, 
dm_state->set_count);
+       dm_state->context = dc_get_validate_context(dc, set, set_count);
 
-       if (need_to_validate == false || dm_state->set_count == 0 || 
dm_state->context) {
+       if (need_to_validate == false || set_count == 0 || dm_state->context) {
                ret = 0;
                /*
                 * For full updates case when
@@ -3403,6 +3401,21 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
 
        }
 
+       /* TODO until surfaces are moved into dm_plane_state release them
+        * here
+        */
+       for (i = 0; i < set_count; i++)
+               for (j = 0; j < set[i].surface_count; j++)
+                       dc_surface_release(set[i].surfaces[j]);
+
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               old_acrtc_state = to_dm_crtc_state(crtc->state);
+
+               if (old_acrtc_state->stream)
+                       dc_stream_release(old_acrtc_state->stream);
+       }
+
+
        if (ret != 0) {
                if (ret == -EDEADLK)
                        DRM_DEBUG_KMS("Atomic check stopped due to to 
deadlock.\n");
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h
index 1e444cb..36cb1c8 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h
@@ -45,7 +45,7 @@ struct dm_plane_state {
 
 struct dm_crtc_state {
        struct drm_crtc_state base;
-       struct dc_stream *dc_stream;
+       const struct dc_stream *stream;
 };
 
 #define to_dm_crtc_state(x)    container_of(x, struct dm_crtc_state, base)
@@ -53,8 +53,6 @@ struct dm_crtc_state {
 struct dm_atomic_state {
        struct drm_atomic_state base;
 
-       struct dc_validation_set set[MAX_STREAMS];
-       int set_count;
        struct validate_context *context;
 };
 
@@ -83,6 +81,11 @@ void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder);
 
 int amdgpu_dm_connector_get_modes(struct drm_connector *connector);
 
+int amdgpu_dm_atomic_commit(
+               struct drm_device *dev,
+               struct drm_atomic_state *state,
+               bool nonblock);
+
 void amdgpu_dm_atomic_commit_tail(
        struct drm_atomic_state *state);
 
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h 
b/drivers/gpu/drm/amd/display/dc/dc.h
index 5d65416..42c1aa8 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -481,8 +481,6 @@ struct dc_stream {
        /* TODO: ABM info (DMCU) */
        /* TODO: PSR info */
        /* TODO: CEA VIC */
-
-       void *priv;
 };
 
 struct dc_stream_update {
-- 
2.7.4

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to