Commit 1dc90497 authored by Andrey Grodzovsky's avatar Andrey Grodzovsky Committed by Alex Deucher
Browse files

drm/amd/display: Per stream validate_context build v2.



Until now new context would start as empty, then populated
with exsisting pipes + new. Now we start with duplication
of existing context and then add/delete from the context
pipes as needed.

This allows to do a per stream resource
population, start discarding dc_validation_set
and by this brings DC closer to to DRM.

v2: Add some fixes and rebase.

Signed-off-by: default avatarAndrey Grodzovsky <Andrey.Grodzovsky@amd.com>
Reviewed-by: default avatarTony Cheng <Tony.Cheng@amd.com>
Acked-by: default avatarHarry Wentland <Harry.Wentland@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent a185048c
Loading
Loading
Loading
Loading
+57 −11
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@

#include "dm_services_types.h"
#include "dc.h"
#include "dc/inc/core_types.h"

#include "vid.h"
#include "amdgpu.h"
@@ -690,13 +691,33 @@ struct drm_atomic_state *
dm_atomic_state_alloc(struct drm_device *dev)
{
	struct dm_atomic_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
	struct validate_context *new_ctx;
	struct amdgpu_device *adev = dev->dev_private;
	struct dc *dc = adev->dm.dc;

	if (!state || drm_atomic_state_init(dev, &state->base) < 0) {
		kfree(state);
	if (!state)
		return NULL;
	}

	if (drm_atomic_state_init(dev, &state->base) < 0)
		goto fail;

	/* copy existing configuration */
	new_ctx = dm_alloc(sizeof(*new_ctx));

	if (!new_ctx)
		goto fail;

	atomic_inc(&new_ctx->ref_count);

	dc_resource_validate_ctx_copy_construct_current(dc, new_ctx);

	state->context = new_ctx;

	return &state->base;

fail:
	kfree(state);
	return NULL;
}

static void
@@ -4418,7 +4439,6 @@ static int do_aquire_global_lock(
int amdgpu_dm_atomic_check(struct drm_device *dev,
			struct drm_atomic_state *state)
{
	struct dm_atomic_state *dm_state;
	struct drm_crtc *crtc;
	struct drm_crtc_state *crtc_state;
	struct drm_plane *plane;
@@ -4432,6 +4452,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
	int set_count;
	struct dc_validation_set set[MAX_STREAMS] = { { 0 } };
	struct dm_crtc_state *old_acrtc_state, *new_acrtc_state;
	struct dm_atomic_state *dm_state = to_dm_atomic_state(state);

	/*
	 * This bool will be set for true for any modeset/reset
@@ -4446,8 +4467,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
		return ret;
	}

	dm_state = to_dm_atomic_state(state);

	/* copy existing configuration */
	set_count = 0;
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
@@ -4492,6 +4511,15 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,

			/* i.e. reset mode */
			if (new_acrtc_state->stream) {

				if (!dc_remove_stream_from_ctx(
						dc,
						dm_state->context,
						new_acrtc_state->stream)) {
					ret = -EINVAL;
					goto fail;
				}

				set_count = remove_from_val_sets(
						set,
						set_count,
@@ -4539,8 +4567,19 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
			if (modeset_required(crtc_state, new_stream,
					     old_acrtc_state->stream)) {

				if (new_acrtc_state->stream)
				if (new_acrtc_state->stream) {

					if (!dc_remove_stream_from_ctx(
							dc,
							dm_state->context,
							new_acrtc_state->stream)) {
						ret = -EINVAL;
						goto fail;
					}


					dc_stream_release(new_acrtc_state->stream);
				}

				new_acrtc_state->stream = new_stream;

@@ -4551,6 +4590,14 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
						new_acrtc_state->stream,
						crtc);

				if (!dc_add_stream_to_ctx(
						dc,
						dm_state->context,
						new_acrtc_state->stream)) {
					ret = -EINVAL;
					goto fail;
				}

				lock_and_validation_needed = true;
			} else {
				/*
@@ -4667,9 +4714,8 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
		ret = do_aquire_global_lock(dev, state);
		if (ret)
			goto fail;
		WARN_ON(dm_state->context);
		dm_state->context = dc_get_validate_context(dc, set, set_count);
		if (!dm_state->context) {

		if (!dc_validate_global_state(dc, set, set_count, dm_state->context)) {
			ret = -EINVAL;
			goto fail;
		}
+13 −95
Original line number Diff line number Diff line
@@ -669,41 +669,6 @@ void dc_destroy(struct dc **dc)
	*dc = NULL;
}

static bool is_validation_required(
		const struct dc *dc,
		const struct dc_validation_set set[],
		int set_count)
{
	const struct validate_context *context = dc->current_context;
	int i, j;

	if (context->stream_count != set_count)
		return true;

	for (i = 0; i < set_count; i++) {

		if (set[i].plane_count != context->stream_status[i].plane_count)
			return true;
		if (!dc_is_stream_unchanged(set[i].stream, context->streams[i]))
			return true;

		for (j = 0; j < set[i].plane_count; j++) {
			struct dc_plane_state temp_plane;
			memset(&temp_plane, 0, sizeof(temp_plane));

			temp_plane = *context->stream_status[i].plane_states[j];
			temp_plane.clip_rect = set[i].plane_states[j]->clip_rect;
			temp_plane.dst_rect.x = set[i].plane_states[j]->dst_rect.x;
			temp_plane.dst_rect.y = set[i].plane_states[j]->dst_rect.y;

			if (memcmp(&temp_plane, set[i].plane_states[j], sizeof(temp_plane)) != 0)
				return true;
		}
	}

	return false;
}

static bool validate_streams (
		struct dc *dc,
		const struct dc_validation_set set[],
@@ -733,52 +698,12 @@ static bool validate_surfaces(
	return true;
}

struct validate_context *dc_get_validate_context(
		struct dc *dc,
		const struct dc_validation_set set[],
		uint8_t set_count)
{
	struct dc *core_dc = dc;
	enum dc_status result = DC_ERROR_UNEXPECTED;
	struct validate_context *context;


	context = dm_alloc(sizeof(struct validate_context));
	if (context == NULL)
		goto context_alloc_fail;

	atomic_inc(&context->ref_count);

	if (!is_validation_required(core_dc, set, set_count)) {
		dc_resource_validate_ctx_copy_construct(core_dc->current_context, context);
		return context;
	}

	result = core_dc->res_pool->funcs->validate_with_context(
			core_dc, set, set_count, context, core_dc->current_context);

context_alloc_fail:
	if (result != DC_OK) {
		dm_logger_write(core_dc->ctx->logger, LOG_WARNING,
				"%s:resource validation failed, dc_status:%d\n",
				__func__,
				result);

		dc_release_validate_context(context);
		context = NULL;
	}

	return context;

}

bool dc_validate_resources(
		struct dc *dc,
		const struct dc_validation_set set[],
		uint8_t set_count)
{
	struct dc  *core_dc = dc;
	enum dc_status result = DC_ERROR_UNEXPECTED;
	bool result = false;
	struct validate_context *context;

	if (!validate_streams(dc, set, set_count))
@@ -793,21 +718,16 @@ bool dc_validate_resources(

	atomic_inc(&context->ref_count);

	result = core_dc->res_pool->funcs->validate_with_context(
				core_dc, set, set_count, context, NULL);
	dc_resource_validate_ctx_copy_construct_current(dc, context);

context_alloc_fail:
	if (result != DC_OK) {
		dm_logger_write(core_dc->ctx->logger, LOG_WARNING,
				"%s:resource validation failed, dc_status:%d\n",
				__func__,
				result);
	}
	result = dc_validate_with_context(
				dc, set, set_count, context);

context_alloc_fail:
	dc_release_validate_context(context);
	context = NULL;

	return result == DC_OK;
	return result;
}

bool dc_validate_guaranteed(
@@ -1093,7 +1013,7 @@ bool dc_commit_streams(
	uint8_t stream_count)
{
	struct dc  *core_dc = dc;
	enum dc_status result = DC_ERROR_UNEXPECTED;
	bool result = false;
	struct validate_context *context;
	struct dc_validation_set set[MAX_STREAMS] = { {0, {0} } };
	int i;
@@ -1135,13 +1055,11 @@ bool dc_commit_streams(

	atomic_inc(&context->ref_count);

	result = core_dc->res_pool->funcs->validate_with_context(
			core_dc, set, stream_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);
	dc_resource_validate_ctx_copy_construct_current(dc, context);

	result = dc_validate_with_context(
			dc, set, stream_count, context);
	if (!result) {
		BREAK_TO_DEBUGGER();
		goto fail;
	}
@@ -1152,7 +1070,7 @@ bool dc_commit_streams(
	dc_release_validate_context(context);

context_alloc_fail:
	return (result == DC_OK);
	return result;
}

bool dc_post_update_surfaces_to_stream(struct dc *dc)
+330 −138
Original line number Diff line number Diff line
@@ -938,7 +938,7 @@ struct pipe_ctx *resource_get_head_pipe_for_stream(
	int i;
	for (i = 0; i < MAX_PIPES; i++) {
		if (res_ctx->pipe_ctx[i].stream == stream &&
				res_ctx->pipe_ctx[i].stream_res.stream_enc) {
				!res_ctx->pipe_ctx[i].top_pipe) {
			return &res_ctx->pipe_ctx[i];
			break;
		}
@@ -1217,29 +1217,31 @@ bool resource_validate_attach_surfaces(
#define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000
#define TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST 297000

static void set_stream_engine_in_use(
static void update_stream_engine_usage(
		struct resource_context *res_ctx,
		const struct resource_pool *pool,
		struct stream_encoder *stream_enc)
		struct stream_encoder *stream_enc,
		bool acquired)
{
	int i;

	for (i = 0; i < pool->stream_enc_count; i++) {
		if (pool->stream_enc[i] == stream_enc)
			res_ctx->is_stream_enc_acquired[i] = true;
			res_ctx->is_stream_enc_acquired[i] = acquired;
	}
}

/* TODO: release audio object */
static void set_audio_in_use(
static void update_audio_usage(
		struct resource_context *res_ctx,
		const struct resource_pool *pool,
		struct audio *audio)
		struct audio *audio,
		bool acquired)
{
	int i;
	for (i = 0; i < pool->audio_count; i++) {
		if (pool->audios[i] == audio)
			res_ctx->is_audio_acquired[i] = true;
			res_ctx->is_audio_acquired[i] = acquired;
	}
}

@@ -1361,6 +1363,100 @@ bool resource_is_stream_unchanged(
	return false;
}

bool dc_add_stream_to_ctx(
		struct dc *dc,
		struct validate_context *new_ctx,
		struct dc_stream_state *stream)
{
	struct dc_context *dc_ctx = dc->ctx;
	enum dc_status res;

	if (new_ctx->stream_count >= dc->res_pool->pipe_count) {
		DC_ERROR("Max streams reached, can add stream %p !\n", stream);
		return DC_ERROR_UNEXPECTED;
	}

	new_ctx->streams[new_ctx->stream_count] = stream;
	dc_stream_retain(stream);
	new_ctx->stream_count++;

	res = dc->res_pool->funcs->add_stream_to_ctx(dc, new_ctx, stream);
	if (res != DC_OK)
		DC_ERROR("Adding stream %p to context failed with err %d!\n", stream, res);

	return res == DC_OK;
}

bool dc_remove_stream_from_ctx(
			struct dc *dc,
			struct validate_context *new_ctx,
			struct dc_stream_state *stream)
{
	int i, j;
	struct dc_context *dc_ctx = dc->ctx;
	struct pipe_ctx *del_pipe = NULL;

	/*TODO MPO to remove extra pipe or in surface remove ?*/

	/* Release primary and secondary pipe (if exsist) */
	for (i = 0; i < MAX_PIPES; i++) {
		if (new_ctx->res_ctx.pipe_ctx[i].stream == stream) {
			del_pipe = &new_ctx->res_ctx.pipe_ctx[i];

			if (del_pipe->stream_res.stream_enc)
				update_stream_engine_usage(
						&new_ctx->res_ctx,
						dc->res_pool,
						del_pipe->stream_res.stream_enc,
						false);

			if (del_pipe->stream_res.audio)
				update_audio_usage(
					&new_ctx->res_ctx,
					dc->res_pool,
					del_pipe->stream_res.audio,
					false);

			memset(del_pipe, 0, sizeof(*del_pipe));
		}
	}

	if (!del_pipe) {
		DC_ERROR("Pipe not found for stream %p !\n", stream);
		return DC_ERROR_UNEXPECTED;
	}

	for (i = 0; i < new_ctx->stream_count; i++)
		if (new_ctx->streams[i] == stream)
			break;

	if (new_ctx->streams[i] != stream) {
		DC_ERROR("Context doesn't have stream %p !\n", stream);
		return DC_ERROR_UNEXPECTED;
	}

	dc_stream_release(new_ctx->streams[i]);
	new_ctx->stream_count--;

	/*TODO move into dc_remove_surface_from_ctx	?*/
	for (j = 0; j < new_ctx->stream_status[i].plane_count; j++)
		dc_plane_state_release(new_ctx->stream_status[i].plane_states[j]);

	/* Trim back arrays */
	for (; i < new_ctx->stream_count; i++) {
		new_ctx->streams[i] = new_ctx->streams[i + 1];
		new_ctx->stream_status[i] = new_ctx->stream_status[i + 1];
	}

	new_ctx->streams[new_ctx->stream_count] = NULL;
	memset(
			&new_ctx->stream_status[new_ctx->stream_count],
			0,
			sizeof(new_ctx->stream_status[0]));

	return DC_OK;
}

static void copy_pipe_ctx(
	const struct pipe_ctx *from_pipe_ctx, struct pipe_ctx *to_pipe_ctx)
{
@@ -1440,15 +1536,16 @@ static void calculate_phy_pix_clks(struct dc_stream_state *stream)
enum dc_status resource_map_pool_resources(
		const struct dc  *dc,
		struct validate_context *context,
		struct validate_context *old_context)
		struct dc_stream_state *stream)
{
	const struct resource_pool *pool = dc->res_pool;
	int i, j;

	for (i = 0; old_context && i < context->stream_count; i++) {
		struct dc_stream_state *stream = context->streams[i];
	int i;
	struct dc_context *dc_ctx = dc->ctx;
	struct pipe_ctx *pipe_ctx = NULL;
	int pipe_idx = -1;

		if (!resource_is_stream_unchanged(old_context, stream)) {
	/* TODO Check if this is needed */
	/*if (!resource_is_stream_unchanged(old_context, stream)) {
			if (stream != NULL && old_context->streams[i] != NULL) {
				stream->bit_depth_params =
						old_context->streams[i]->bit_depth_params;
@@ -1456,57 +1553,11 @@ enum dc_status resource_map_pool_resources(
				continue;
			}
		}

		/* mark resources used for stream that is already active */
		for (j = 0; j < pool->pipe_count; j++) {
			struct pipe_ctx *pipe_ctx =
				&context->res_ctx.pipe_ctx[j];
			const struct pipe_ctx *old_pipe_ctx =
					&old_context->res_ctx.pipe_ctx[j];

			if (!are_stream_backends_same(old_pipe_ctx->stream, stream))
				continue;

			if (old_pipe_ctx->top_pipe)
				continue;

			pipe_ctx->stream = stream;
			copy_pipe_ctx(old_pipe_ctx, pipe_ctx);

			/* Split pipe resource, do not acquire back end */
			if (!pipe_ctx->stream_res.stream_enc)
				continue;

			set_stream_engine_in_use(
				&context->res_ctx, pool,
				pipe_ctx->stream_res.stream_enc);

			/* Switch to dp clock source only if there is
			 * no non dp stream that shares the same timing
			 * with the dp stream.
	*/
			if (dc_is_dp_signal(pipe_ctx->stream->signal) &&
				!find_pll_sharable_stream(stream, context))
				pipe_ctx->clock_source = pool->dp_clock_source;

			resource_reference_clock_source(
				&context->res_ctx, pool,
				pipe_ctx->clock_source);

			set_audio_in_use(&context->res_ctx, pool,
					pipe_ctx->stream_res.audio);
		}
	}

	for (i = 0; i < context->stream_count; i++) {
		struct dc_stream_state *stream = context->streams[i];
		struct pipe_ctx *pipe_ctx = NULL;
		int pipe_idx = -1;

		if (old_context && resource_is_stream_unchanged(old_context, stream))
			continue;
	/* acquire new resources */
	pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream);

#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
	if (pipe_idx < 0)
		acquire_first_split_pipe(&context->res_ctx, pool, stream);
@@ -1523,9 +1574,10 @@ enum dc_status resource_map_pool_resources(
	if (!pipe_ctx->stream_res.stream_enc)
		return DC_NO_STREAM_ENG_RESOURCE;

		set_stream_engine_in_use(
	update_stream_engine_usage(
		&context->res_ctx, pool,
			pipe_ctx->stream_res.stream_enc);
		pipe_ctx->stream_res.stream_enc,
		true);

	/* TODO: Add check if ASIC support and EDID audio */
	if (!stream->sink->converter_disable_audio &&
@@ -1540,15 +1592,18 @@ enum dc_status resource_map_pool_resources(
		 * resources less then number of pipes
		 */
		if (pipe_ctx->stream_res.audio)
				set_audio_in_use(
					&context->res_ctx, pool,
					pipe_ctx->stream_res.audio);
			update_audio_usage(&context->res_ctx, pool,
					   pipe_ctx->stream_res.audio, true);
	}

	for (i = 0; i < context->stream_count; i++)
		if (context->streams[i] == stream) {
			context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst;
			return DC_OK;
		}

	return DC_OK;
	DC_ERROR("Stream %p not found in new ctx!\n", stream);
	return DC_ERROR_UNEXPECTED;
}

/* first stream in the context is used to populate the rest */
@@ -1571,6 +1626,157 @@ void validate_guaranteed_copy_streams(
	}
}

void dc_resource_validate_ctx_copy_construct_current(
		const struct dc *dc,
		struct validate_context *dst_ctx)
{
	dc_resource_validate_ctx_copy_construct(dc->current_context, dst_ctx);
}

bool dc_validate_with_context(
		struct dc *dc,
		const struct dc_validation_set set[],
		int set_count,
		struct validate_context *context)
{
	int i, j;
	enum dc_status res = DC_ERROR_UNEXPECTED;
	bool found = false;
	int old_stream_count = context->stream_count;
	struct dc_stream_state *del_streams[MAX_PIPES] = { 0 };
	struct dc_stream_state *add_streams[MAX_PIPES] = { 0 };
	int del_streams_count = 0;
	int add_streams_count = 0;


	/* First remove from context all deleted streams */
	for (i = 0; i < old_stream_count; i++) {
		struct dc_stream_state *stream = context->streams[i];

		for (j = 0; j < set_count; j++) {
			if (stream == set[j].stream) {
				found = true;
				break;
			}
		}

		if (!found)
			del_streams[del_streams_count++] = stream;

		found = false;
	}

	/* Now add new ones */
	for (i = 0; i < set_count; i++) {
		struct dc_stream_state *stream = set[i].stream;

		for (j = 0; j < old_stream_count; j++) {
			if (stream == context->streams[j]) {
				found = true;
				break;
			}
		}

		if (!found)
			add_streams[add_streams_count++] = stream;

		found = false;
	}

	for (i = 0; i < del_streams_count; i++)
		if (!dc_remove_stream_from_ctx(dc, context, del_streams[i]))
			goto fail;

	for (i = 0; i < add_streams_count; i++)
		if (!dc_add_stream_to_ctx(dc, context, add_streams[i]))
			goto fail;

	if (!dc_validate_global_state(dc, set, set_count, context))
		goto fail;

	res = DC_OK;

fail:
	if (res != DC_OK) {
		dm_logger_write(dc->ctx->logger, LOG_WARNING,
				"%s:resource validation failed, dc_status:%d\n",
				__func__,
				res);
}
	return res == DC_OK;
}

bool dc_validate_global_state(
		struct dc *dc,
		const struct dc_validation_set set[],
		int set_count,
		struct validate_context *new_ctx)
{
	enum dc_status result = DC_ERROR_UNEXPECTED;
	struct dc_context *dc_ctx = dc->ctx;
	struct validate_context *old_context = dc->current_context;
	int i, j;

	if (dc->res_pool->funcs->validate_global &&
	    dc->res_pool->funcs->validate_global(dc, set, set_count,
						 old_context, new_ctx) != DC_OK)
		return false;

	/* TODO without this SWDEV-114774 brakes */
	for (i = 0; i < dc->res_pool->pipe_count; i++) {
		struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[i];

		if (pipe_ctx->top_pipe)
			memset(pipe_ctx, 0, sizeof(*pipe_ctx));
	}

	for (i = 0; new_ctx && i < new_ctx->stream_count; i++) {
		struct dc_stream_state *stream = new_ctx->streams[i];

		for (j = 0; j < dc->res_pool->pipe_count; j++) {
			struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[j];

			if (pipe_ctx->stream != stream)
				continue;

			/* Switch to dp clock source only if there is
			 * no non dp stream that shares the same timing
			 * with the dp stream.
			 */
			if (dc_is_dp_signal(pipe_ctx->stream->signal) &&
				!find_pll_sharable_stream(stream, new_ctx)) {

				resource_unreference_clock_source(
						&new_ctx->res_ctx,
						dc->res_pool,
						&pipe_ctx->clock_source);
				pipe_ctx->clock_source = dc->res_pool->dp_clock_source;
				resource_reference_clock_source(
						&new_ctx->res_ctx,
						dc->res_pool,
						 pipe_ctx->clock_source);
			}
		}
	}

	/*TODO This should be ok */
	/* Split pipe resource, do not acquire back end */

	if (!resource_validate_attach_surfaces(
			set, set_count, old_context, new_ctx, dc->res_pool)) {
		DC_ERROR("Failed to attach surface to stream!\n");
		return DC_FAIL_ATTACH_SURFACES;
	}

	result = resource_build_scaling_params_for_context(dc, new_ctx);

	if (result == DC_OK)
		if (!dc->res_pool->funcs->validate_bandwidth(dc, new_ctx))
			result = DC_FAIL_BANDWIDTH_VALIDATE;

	return result;
}

static void patch_gamut_packet_checksum(
		struct encoder_info_packet *gamut_packet)
{
@@ -2318,24 +2524,15 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx)
enum dc_status resource_map_clock_resources(
		const struct dc  *dc,
		struct validate_context *context,
		struct validate_context *old_context)
		struct dc_stream_state *stream)
{
	int i, j;
	const struct resource_pool *pool = dc->res_pool;

	/* acquire new resources */
	for (i = 0; i < context->stream_count; i++) {
		struct dc_stream_state *stream = context->streams[i];

		if (old_context && resource_is_stream_unchanged(old_context, stream))
			continue;

		for (j = 0; j < MAX_PIPES; j++) {
			struct pipe_ctx *pipe_ctx =
				&context->res_ctx.pipe_ctx[j];
	const struct resource_pool *pool = dc->res_pool;
	struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(
				&context->res_ctx, stream);

			if (context->res_ctx.pipe_ctx[j].stream != stream)
				continue;
	if (!pipe_ctx)
		return DC_ERROR_UNEXPECTED;

	if (dc_is_dp_signal(pipe_ctx->stream->signal)
		|| pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL)
@@ -2362,11 +2559,6 @@ enum dc_status resource_map_clock_resources(
		&context->res_ctx, pool,
		pipe_ctx->clock_source);

			/* only one cs per stream regardless of mpo */
			break;
		}
	}

	return DC_OK;
}

+24 −8
Original line number Diff line number Diff line
@@ -618,6 +618,16 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream,
				  uint32_t *h_position,
				  uint32_t *v_position);

bool dc_remove_stream_from_ctx(
			struct dc *dc,
			struct validate_context *new_ctx,
			struct dc_stream_state *stream);

bool dc_add_stream_to_ctx(
		struct dc *dc,
		struct validate_context *new_ctx,
		struct dc_stream_state *stream);

/*
 * Structure to store surface/stream associations for validation
 */
@@ -630,16 +640,18 @@ struct dc_validation_set {
bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream);

bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state);
/*
 * This function takes a set of resources and checks that they are cofunctional.
 *
 * After this call:
 *   No hardware is programmed for call.  Only validation is done.
 */
struct validate_context *dc_get_validate_context(

bool dc_validate_with_context(
		struct dc *dc,
		const struct dc_validation_set set[],
		uint8_t set_count);
		int set_count,
		struct validate_context *context);

bool dc_validate_global_state(
		struct dc *dc,
		const struct dc_validation_set set[],
		int set_count,
		struct validate_context *new_ctx);

bool dc_validate_resources(
		struct dc *dc,
@@ -662,6 +674,10 @@ void dc_resource_validate_ctx_copy_construct(
		const struct validate_context *src_ctx,
		struct validate_context *dst_ctx);

void dc_resource_validate_ctx_copy_construct_current(
		const struct dc *dc,
		struct validate_context *dst_ctx);

void dc_resource_validate_ctx_destruct(struct validate_context *context);

/*
+16 −62
Original line number Diff line number Diff line
@@ -654,23 +654,13 @@ static void destruct(struct dce110_resource_pool *pool)
static enum dc_status build_mapped_resource(
		const struct dc  *dc,
		struct validate_context *context,
		struct validate_context *old_context)
		struct dc_stream_state *stream)
{
	enum dc_status status = DC_OK;
	uint8_t i, j;
	struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream(&context->res_ctx, stream);

	for (i = 0; i < context->stream_count; i++) {
		struct dc_stream_state *stream = context->streams[i];

		if (old_context && resource_is_stream_unchanged(old_context, stream))
			continue;

		for (j = 0; j < MAX_PIPES; j++) {
			struct pipe_ctx *pipe_ctx =
				&context->res_ctx.pipe_ctx[j];

			if (context->res_ctx.pipe_ctx[j].stream != stream)
				continue;
	if (!pipe_ctx)
		return DC_ERROR_UNEXPECTED;

	status = dce110_resource_build_pipe_hw_param(pipe_ctx);

@@ -679,11 +669,6 @@ static enum dc_status build_mapped_resource(

	resource_build_info_frame(pipe_ctx);

			/* do not need to validate non root pipes */
			break;
		}
	}

	return DC_OK;
}

@@ -719,48 +704,17 @@ static bool dce100_validate_surface_sets(
	return true;
}

enum dc_status dce100_validate_with_context(
enum dc_status dce100_validate_global(
		struct dc  *dc,
		const struct dc_validation_set set[],
		int set_count,
		struct validate_context *context,
		struct validate_context *old_context)
		struct validate_context *old_context,
		struct validate_context *context)
{
	struct dc_context *dc_ctx = dc->ctx;
	enum dc_status result = DC_ERROR_UNEXPECTED;
	int i;

	if (!dce100_validate_surface_sets(set, set_count))
		return DC_FAIL_SURFACE_VALIDATE;

	for (i = 0; i < set_count; i++) {
		context->streams[i] = set[i].stream;
		dc_stream_retain(context->streams[i]);
		context->stream_count++;
	}

	result = resource_map_pool_resources(dc, context, old_context);

	if (result == DC_OK)
		result = resource_map_clock_resources(dc, context, old_context);

	if (!resource_validate_attach_surfaces(set, set_count,
			old_context, context, dc->res_pool)) {
		DC_ERROR("Failed to attach surface to stream!\n");
		return DC_FAIL_ATTACH_SURFACES;
	}

	if (result == DC_OK)
		result = build_mapped_resource(dc, context, old_context);

	if (result == DC_OK)
		result = resource_build_scaling_params_for_context(dc, context);

	if (result == DC_OK)
		if (!dce100_validate_bandwidth(dc, context))
			result = DC_FAIL_BANDWIDTH_VALIDATE;

	return result;
	return DC_OK;
}

enum dc_status dce100_validate_guaranteed(
@@ -774,13 +728,13 @@ enum dc_status dce100_validate_guaranteed(
	dc_stream_retain(context->streams[0]);
	context->stream_count++;

	result = resource_map_pool_resources(dc, context, NULL);
	result = resource_map_pool_resources(dc, context, dc_stream);

	if (result == DC_OK)
		result = resource_map_clock_resources(dc, context, NULL);
		result = resource_map_clock_resources(dc, context, dc_stream);

	if (result == DC_OK)
		result = build_mapped_resource(dc, context, NULL);
		result = build_mapped_resource(dc, context, dc_stream);

	if (result == DC_OK) {
		validate_guaranteed_copy_streams(
@@ -816,10 +770,10 @@ enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state)
static const struct resource_funcs dce100_res_pool_funcs = {
	.destroy = dce100_destroy_resource_pool,
	.link_enc_create = dce100_link_encoder_create,
	.validate_with_context = dce100_validate_with_context,
	.validate_guaranteed = dce100_validate_guaranteed,
	.validate_bandwidth = dce100_validate_bandwidth,
	.validate_plane = dce100_validate_plane,
	.validate_global = dce100_validate_global
};

static bool construct(
Loading