Commit 72ada5f7 authored by Eric Cook's avatar Eric Cook Committed by Alex Deucher
Browse files

drm/amd/display: FreeSync Auto Sweep Support



Implement core support to allow for FreeSync Auto Sweep to work

Signed-off-by: default avatarEric Cook <Eric.Cook@amd.com>
Acked-by: default avatarHarry Wentland <Harry.Wentland@amd.com>
Reviewed-by: default avatarTony Cheng <Tony.Cheng@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 84f6739f
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -175,6 +175,31 @@ static bool stream_adjust_vmin_vmax(struct dc *dc,
	return ret;
}

static bool stream_get_crtc_position(struct dc *dc,
		const struct dc_stream **stream, int num_streams,
		unsigned int *v_pos, unsigned int *nom_v_pos)
{
	/* TODO: Support multiple streams */
	struct core_dc *core_dc = DC_TO_CORE(dc);
	struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[0]);
	int i = 0;
	bool ret = false;
	struct crtc_position position;

	for (i = 0; i < MAX_PIPES; i++) {
		struct pipe_ctx *pipe =
				&core_dc->current_context->res_ctx.pipe_ctx[i];

		if (pipe->stream == core_stream && pipe->stream_enc) {
			core_dc->hwss.get_position(&pipe, 1, &position);

			*v_pos = position.vertical_count;
			*nom_v_pos = position.nominal_vcount;
			ret = true;
		}
	}
	return ret;
}

static bool set_gamut_remap(struct dc *dc,
			const struct dc_stream **stream, int num_streams)
@@ -349,6 +374,9 @@ static void allocate_dc_stream_funcs(struct core_dc *core_dc)
	core_dc->public.stream_funcs.set_static_screen_events =
			set_static_screen_events;

	core_dc->public.stream_funcs.get_crtc_position =
			stream_get_crtc_position;

	core_dc->public.stream_funcs.set_gamut_remap =
			set_gamut_remap;

+4 −1
Original line number Diff line number Diff line
@@ -287,6 +287,7 @@ void context_timing_trace(
	struct core_dc *core_dc = DC_TO_CORE(dc);
	struct dal_logger *logger =  core_dc->ctx->logger;
	int h_pos[MAX_PIPES], v_pos[MAX_PIPES];
	struct crtc_position position;

	for (i = 0; i < core_dc->res_pool->pipe_count; i++) {
		struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
@@ -294,7 +295,9 @@ void context_timing_trace(
		if (pipe_ctx->stream == NULL)
			continue;

		pipe_ctx->tg->funcs->get_position(pipe_ctx->tg, &h_pos[i], &v_pos[i]);
		pipe_ctx->tg->funcs->get_position(pipe_ctx->tg, &position);
		h_pos[i] = position.horizontal_count;
		v_pos[i] = position.vertical_count;
	}
	for (i = 0; i < core_dc->res_pool->pipe_count; i++) {
		struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
+6 −0
Original line number Diff line number Diff line
@@ -103,6 +103,12 @@ struct dc_stream_funcs {
			int num_streams,
			int vmin,
			int vmax);
	bool (*get_crtc_position)(struct dc *dc,
			const struct dc_stream **stream,
			int num_streams,
			unsigned int *v_pos,
			unsigned int *nom_v_pos);


	void (*stream_update_scaling)(const struct dc *dc,
			const struct dc_stream *dc_stream,
+13 −0
Original line number Diff line number Diff line
@@ -1362,6 +1362,18 @@ static void set_drr(struct pipe_ctx **pipe_ctx,
	}
}

static void get_position(struct pipe_ctx **pipe_ctx,
		int num_pipes,
		struct crtc_position *position)
{
	int i = 0;

	/* TODO: handle pipes > 1
	 */
	for (i = 0; i < num_pipes; i++)
		pipe_ctx[i]->tg->funcs->get_position(pipe_ctx[i]->tg, position);
}

static void set_static_screen_control(struct pipe_ctx **pipe_ctx,
		int num_pipes, const struct dc_static_screen_events *events)
{
@@ -2486,6 +2498,7 @@ static const struct hw_sequencer_funcs dce110_funcs = {
	.pipe_control_lock = dce_pipe_control_lock,
	.set_bandwidth = dce110_set_bandwidth,
	.set_drr = set_drr,
	.get_position = get_position,
	.set_static_screen_control = set_static_screen_control,
	.reset_hw_ctx_wrap = reset_hw_ctx_wrap,
	.prog_pixclk_crtc_otg = dce110_prog_pixclk_crtc_otg,
+28 −33
Original line number Diff line number Diff line
@@ -518,34 +518,38 @@ uint32_t dce110_timing_generator_get_vblank_counter(struct timing_generator *tg)

/**
 *****************************************************************************
 *  Function: dce110_get_crtc_positions
 *  Function: dce110_timing_generator_get_position
 *
 *  @brief
 *     Returns CRTC vertical/horizontal counters
 *
 *  @param [out] v_position, h_position
 *  @param [out] position
 *****************************************************************************
 */

void dce110_timing_generator_get_crtc_positions(
	struct timing_generator *tg,
	int32_t *h_position,
	int32_t *v_position)
void dce110_timing_generator_get_position(struct timing_generator *tg,
	struct crtc_position *position)
{
	uint32_t value;
	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);

	value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_STATUS_POSITION));

	*h_position = get_reg_field_value(
	position->horizontal_count = get_reg_field_value(
			value,
			CRTC_STATUS_POSITION,
			CRTC_HORZ_COUNT);

	*v_position = get_reg_field_value(
	position->vertical_count = get_reg_field_value(
			value,
			CRTC_STATUS_POSITION,
			CRTC_VERT_COUNT);

	value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_NOM_VERT_POSITION));

	position->nominal_vcount = get_reg_field_value(
			value,
			CRTC_NOM_VERT_POSITION,
			CRTC_VERT_COUNT_NOM);
}

/**
@@ -566,18 +570,23 @@ void dce110_timing_generator_get_crtc_scanoutpos(
	uint32_t *v_position)
{
	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
	struct crtc_position position;

	uint32_t v_blank_start_end  = dm_read_reg(tg->ctx,
	uint32_t value  = dm_read_reg(tg->ctx,
			CRTC_REG(mmCRTC_V_BLANK_START_END));

	*v_blank_start = get_reg_field_value(v_blank_start_end,
	*v_blank_start = get_reg_field_value(value,
					     CRTC_V_BLANK_START_END,
					     CRTC_V_BLANK_START);
	*v_blank_end = get_reg_field_value(v_blank_start_end,
	*v_blank_end = get_reg_field_value(value,
					   CRTC_V_BLANK_START_END,
					   CRTC_V_BLANK_END);

	dce110_timing_generator_get_crtc_positions(tg, h_position, v_position);
	dce110_timing_generator_get_position(
			tg, &position);

	*h_position = position.horizontal_count;
	*v_position = position.vertical_count;
}

/* TODO: is it safe to assume that mask/shift of Primary and Underlay
@@ -1344,15 +1353,13 @@ void dce110_timing_generator_tear_down_global_swap_lock(
 */
bool dce110_timing_generator_is_counter_moving(struct timing_generator *tg)
{
	uint32_t h1 = 0;
	uint32_t h2 = 0;
	uint32_t v1 = 0;
	uint32_t v2 = 0;
	struct crtc_position position1, position2;

	tg->funcs->get_position(tg, &h1, &v1);
	tg->funcs->get_position(tg, &h2, &v2);
	tg->funcs->get_position(tg, &position1);
	tg->funcs->get_position(tg, &position2);

	if (h1 == h2 && v1 == v2)
	if (position1.horizontal_count == position2.horizontal_count &&
		position1.vertical_count == position2.vertical_count)
		return false;
	else
		return true;
@@ -1750,18 +1757,6 @@ void dce110_tg_set_overscan_color(struct timing_generator *tg,
	dm_write_reg(ctx, addr, value);
}

void dce110_tg_get_position(struct timing_generator *tg,
	struct crtc_position *position)
{
	int32_t h_position;
	int32_t v_position;

	dce110_timing_generator_get_crtc_positions(tg, &h_position, &v_position);

	position->horizontal_count = (uint32_t)h_position;
	position->vertical_count = (uint32_t)v_position;
}

void dce110_tg_program_timing(struct timing_generator *tg,
	const struct dc_crtc_timing *timing,
	bool use_vbios)
@@ -1895,7 +1890,7 @@ static const struct timing_generator_funcs dce110_tg_funcs = {
		.enable_crtc = dce110_timing_generator_enable_crtc,
		.disable_crtc = dce110_timing_generator_disable_crtc,
		.is_counter_moving = dce110_timing_generator_is_counter_moving,
		.get_position = dce110_timing_generator_get_crtc_positions,
		.get_position = dce110_timing_generator_get_position,
		.get_frame_count = dce110_timing_generator_get_vblank_counter,
		.get_scanoutpos = dce110_timing_generator_get_crtc_scanoutpos,
		.set_early_control = dce110_timing_generator_set_early_control,
Loading