From: Harry Wentland <harry.wentland@xxxxxxx> Change-Id: If474c444f6dc902b632ce068b6fac2428bac52b2 Signed-off-by: Harry Wentland <harry.wentland at amd.com> Reviewed-by: Tony Cheng <Tony.Cheng at amd.com> Acked-by: Harry Wentland <Harry.Wentland at 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