diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.14.71/0579-drm-amd-display-Commit-validation-set-from-state.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.14.71/0579-drm-amd-display-Commit-validation-set-from-state.patch | 286 |
1 files changed, 286 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.14.71/0579-drm-amd-display-Commit-validation-set-from-state.patch b/common/recipes-kernel/linux/linux-yocto-4.14.71/0579-drm-amd-display-Commit-validation-set-from-state.patch new file mode 100644 index 00000000..91319379 --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.14.71/0579-drm-amd-display-Commit-validation-set-from-state.patch @@ -0,0 +1,286 @@ +From 597a1c3327738758cd3c19491d3928212de2cc26 Mon Sep 17 00:00:00 2001 +From: Harry Wentland <harry.wentland@amd.com> +Date: Mon, 6 Mar 2017 09:43:30 -0500 +Subject: [PATCH 0579/4131] drm/amd/display: Commit validation set from state + +Signed-off-by: Harry Wentland <harry.wentland@amd.com> +Reviewed-by: Tony Cheng <Tony.Cheng@amd.com> +Acked-by: Harry Wentland <Harry.Wentland@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@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 716b440..ee07b8c 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 +@@ -2662,20 +2662,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; +@@ -2706,16 +2708,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); + +@@ -2743,6 +2745,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 +@@ -2801,15 +2810,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 +@@ -2838,7 +2838,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); +@@ -3196,6 +3197,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 + |