From: Harry Wentland <harry.wentl...@amd.com>

Change-Id: If474c444f6dc902b632ce068b6fac2428bac52b2
Signed-off-by: Harry Wentland <harry.wentl...@amd.com>
Reviewed-by: Tony Cheng <tony.ch...@amd.com>
Acked-by: Harry Wentland <harry.wentl...@amd.com>
---
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c    |  34 +++---
 drivers/gpu/drm/amd/display/dc/core/dc.c           | 118 +++++++++++++++++++++
 drivers/gpu/drm/amd/display/dc/dc.h                |  16 +++
 3 files changed, 152 insertions(+), 16 deletions(-)

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 13fc497..b0734bb 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
@@ -2681,20 +2681,22 @@ 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 dm_atomic_state *dm_state;
        uint32_t i, j;
-       uint32_t commit_streams_count = 0;
        uint32_t new_crtcs_count = 0;
        struct drm_crtc *crtc, *pcrtc;
        struct drm_crtc_state *old_crtc_state;
-       const struct dc_stream *commit_streams[MAX_STREAMS];
        struct amdgpu_crtc *new_crtcs[MAX_STREAMS];
-       const struct dc_stream *new_stream;
+       const struct dc_stream *new_stream = NULL;
        unsigned long flags;
        bool wait_for_vblank = true;
        struct drm_connector *connector;
        struct drm_connector_state *old_conn_state;
 
        drm_atomic_helper_update_legacy_modeset_state(dev, state);
+
+       dm_state = to_dm_atomic_state(state);
+
        /* update changed items */
        for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
                struct amdgpu_crtc *acrtc;
@@ -2725,16 +2727,16 @@ void amdgpu_dm_atomic_commit_tail(
                 */
 
                if (modeset_required(new_state)) {
-                       struct dm_connector_state *dm_state = NULL;
+                       struct dm_connector_state *dm_conn_state = NULL;
                        new_stream = NULL;
 
                        if (aconnector)
-                               dm_state = 
to_dm_connector_state(aconnector->base.state);
+                               dm_conn_state = 
to_dm_connector_state(aconnector->base.state);
 
                        new_stream = create_stream_for_sink(
                                        aconnector,
                                        &crtc->state->mode,
-                                       dm_state);
+                                       dm_conn_state);
 
                        DRM_INFO("Atomic commit: SET crtc id %d: [%p]\n", 
acrtc->crtc_id, acrtc);
 
@@ -2762,6 +2764,13 @@ void amdgpu_dm_atomic_commit_tail(
                        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;
+                               }
                        /*
                         * this loop saves set mode crtcs
                         * we needed to enable vblanks once all
@@ -2820,15 +2829,6 @@ void amdgpu_dm_atomic_commit_tail(
                        dm_error("%s: Failed to update stream scaling!\n", 
__func__);
        }
 
-       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-
-               struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
-
-               if (acrtc->stream) {
-                       commit_streams[commit_streams_count] = acrtc->stream;
-                       ++commit_streams_count;
-               }
-       }
 
        /*
         * Add streams after required streams from new and replaced streams
@@ -2857,7 +2857,8 @@ void amdgpu_dm_atomic_commit_tail(
        }
 
        /* DC is optimized not to do anything if 'streams' didn't change. */
-       WARN_ON(!dc_commit_streams(dm->dc, commit_streams, 
commit_streams_count));
+       WARN_ON(!dc_commit_validation_set(dm->dc, dm_state->set,
+                                         dm_state->set_count));
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
@@ -3215,6 +3216,7 @@ 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
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c 
b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 1d2e421e..b50fc0d 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -841,6 +841,24 @@ static void program_timing_sync(
        }
 }
 
+static bool set_changed(
+               struct core_dc *dc,
+               const struct dc_validation_set set[],
+               uint8_t set_count)
+{
+       uint8_t i;
+
+       if (set_count != dc->current_context->stream_count)
+               return true;
+
+       for (i = 0; i < dc->current_context->stream_count; i++) {
+               if (&dc->current_context->streams[i]->public != set[i].stream)
+                       return true;
+       }
+
+       return false;
+}
+
 static bool streams_changed(
                struct core_dc *dc,
                const struct dc_stream *streams[],
@@ -896,6 +914,106 @@ bool dc_enable_stereo(
        return ret;
 }
 
+/* TODO operate on validation set (or something like it) */
+bool dc_commit_validation_set(
+       const struct dc *dc,
+       const struct dc_validation_set set[],
+       uint8_t set_count)
+{
+       struct core_dc *core_dc = DC_TO_CORE(dc);
+       struct dc_bios *dcb = core_dc->ctx->dc_bios;
+       enum dc_status result = DC_ERROR_UNEXPECTED;
+       struct validate_context *context;
+       struct pipe_ctx *pipe;
+       int i, j, k, l;
+
+       /* TODO check validation set changed */
+       if (false == set_changed(core_dc, set, set_count))
+               return DC_OK;
+
+       dm_logger_write(core_dc->ctx->logger, LOG_DC, "%s: %d streams\n",
+                               __func__, set_count);
+
+       for (i = 0; i < set_count; i++)
+               dc_stream_log(set[i].stream,
+                             core_dc->ctx->logger,
+                             LOG_DC);
+
+       context = dm_alloc(sizeof(struct validate_context));
+       if (context == NULL)
+               goto context_alloc_fail;
+
+       /* TODO no need for validation. just rebuild context */
+       /* TODO check context is created deterministically */
+       result = core_dc->res_pool->funcs->validate_with_context(core_dc, set,
+                                                                set_count,
+                                                                context,
+                                                                
core_dc->current_context);
+       if (result != DC_OK) {
+               dm_logger_write(core_dc->ctx->logger, LOG_ERROR,
+                                       "%s: Context validation failed! 
dc_status:%d\n",
+                                       __func__,
+                                       result);
+               BREAK_TO_DEBUGGER();
+               dc_resource_validate_ctx_destruct(context);
+               goto fail;
+       }
+
+       if (!dcb->funcs->is_accelerated_mode(dcb))
+               core_dc->hwss.enable_accelerated_mode(core_dc);
+
+       if (result == DC_OK)
+               result = core_dc->hwss.apply_ctx_to_hw(core_dc, context);
+
+       program_timing_sync(core_dc, context);
+
+       for (i = 0; i < context->stream_count; i++) {
+               const struct core_sink *sink = context->streams[i]->sink;
+
+               for (j = 0; j < context->stream_status[i].surface_count; j++) {
+                       struct core_surface *surface =
+                                       
DC_SURFACE_TO_CORE(context->stream_status[i].surfaces[j]);
+
+                       core_dc->hwss.apply_ctx_for_surface(core_dc, surface, 
context);
+
+                       /*
+                        * enable stereo
+                        * TODO rework dc_enable_stereo call to work with 
validation sets?
+                        */
+                       for (k = 0; k < MAX_PIPES; k++) {
+                               pipe = &context->res_ctx.pipe_ctx[k];
+
+                               for (l = 0 ; pipe && l < context->stream_count; 
l++)  {
+                                       if (context->streams[l] &&
+                                           context->streams[l] == pipe->stream 
&&
+                                           core_dc->hwss.setup_stereo)
+                                               
core_dc->hwss.setup_stereo(pipe, core_dc);
+                               }
+                       }
+               }
+
+               CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}",
+                               
context->streams[i]->public.timing.h_addressable,
+                               
context->streams[i]->public.timing.v_addressable,
+                               context->streams[i]->public.timing.h_total,
+                               context->streams[i]->public.timing.v_total,
+                               context->streams[i]->public.timing.pix_clk_khz);
+       }
+
+       dc_resource_validate_ctx_destruct(core_dc->current_context);
+       dm_free(core_dc->current_context);
+
+       core_dc->current_context = context;
+
+       return (result == DC_OK);
+
+fail:
+       dm_free(context);
+
+context_alloc_fail:
+       return (result == DC_OK);
+}
+
 bool dc_commit_streams(
        struct dc *dc,
        const struct dc_stream *streams[],
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h 
b/drivers/gpu/drm/amd/display/dc/dc.h
index 93aff82..5487fb1 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -481,6 +481,8 @@ struct dc_stream {
        /* TODO: ABM info (DMCU) */
        /* TODO: PSR info */
        /* TODO: CEA VIC */
+
+       void *priv;
 };
 
 struct dc_stream_update {
@@ -580,6 +582,20 @@ void dc_resource_validate_ctx_copy_construct(
 void dc_resource_validate_ctx_destruct(struct validate_context *context);
 
 /*
+ * TODO update to make it about validation sets
+ * Set up streams and links associated to drive sinks
+ * The streams parameter is an absolute set of all active streams.
+ *
+ * After this call:
+ *   Phy, Encoder, Timing Generator are programmed and enabled.
+ *   New streams are enabled with blank stream; no memory read.
+ */
+bool dc_commit_validation_set(
+               const struct dc *dc,
+               const struct dc_validation_set set[],
+               uint8_t set_count);
+
+/*
  * Set up streams and links associated to drive sinks
  * The streams parameter is an absolute set of all active streams.
  *
-- 
2.7.4

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

Reply via email to