mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-09 02:00:43 -04:00
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>
This commit is contained in:
committed by
Alex Deucher
parent
b29fc8661d
commit
7cf2c840c6
@@ -2517,12 +2517,11 @@ 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;
|
||||
unsigned long flags;
|
||||
@@ -2531,6 +2530,9 @@ void amdgpu_dm_atomic_commit_tail(
|
||||
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;
|
||||
@@ -2561,16 +2563,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);
|
||||
|
||||
@@ -2598,6 +2600,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
|
||||
@@ -2656,15 +2665,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
|
||||
@@ -2693,7 +2693,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);
|
||||
@@ -3051,6 +3052,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
|
||||
|
||||
@@ -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[],
|
||||
|
||||
@@ -481,6 +481,8 @@ struct dc_stream {
|
||||
/* TODO: ABM info (DMCU) */
|
||||
/* TODO: PSR info */
|
||||
/* TODO: CEA VIC */
|
||||
|
||||
void *priv;
|
||||
};
|
||||
|
||||
struct dc_stream_update {
|
||||
@@ -579,6 +581,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.
|
||||
|
||||
Reference in New Issue
Block a user