Commit 4b5e7d62 authored by Hersen Wu's avatar Hersen Wu Committed by Alex Deucher
Browse files

drm/amd/display: set blank functionality



1. remove the sleep mechanism while set_blank true from
the timing generator.
Since Hw sequencer is the one that manages the flow
he will be responsible for wait for blanck in a critical places.

Signed-off-by: default avatarLeon Elazar <leon.elazar@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 b06b7680
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -91,3 +91,23 @@ void color_space_to_black_color(
		break;
	}
}

bool hwss_wait_for_blank_complete(
		struct timing_generator *tg)
{
	int counter;

	for (counter = 0; counter < 100; counter++) {
		if (tg->funcs->is_blanked(tg))
			break;

		msleep(1);
	}

	if (counter == 100) {
		dm_error("DC: failed to blank crtc!\n");
		return false;
	}

	return true;
}
+6 −6
Original line number Diff line number Diff line
@@ -623,7 +623,7 @@ static void program_scaler(const struct core_dc *dc,
		&pipe_ctx->scl_data);
}

static enum dc_status prog_pixclk_crtc_otg(
static enum dc_status dce110_prog_pixclk_crtc_otg(
		struct pipe_ctx *pipe_ctx,
		struct validate_context *context,
		struct core_dc *dc)
@@ -641,6 +641,7 @@ static enum dc_status prog_pixclk_crtc_otg(
		pipe_ctx->tg->funcs->set_blank_color(
				pipe_ctx->tg,
				&black_color);

		/*
		 * Must blank CRTC after disabling power gating and before any
		 * programming, otherwise CRTC will be hung in bad state
@@ -1047,7 +1048,8 @@ static void reset_single_pipe_hw_ctx(
		struct validate_context *context)
{
	core_link_disable_stream(pipe_ctx);
	if (!pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true)) {
	pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true);
	if (!hwss_wait_for_blank_complete(pipe_ctx->tg)) {
		dm_error("DC: failed to blank crtc!\n");
		BREAK_TO_DEBUGGER();
	}
@@ -1560,9 +1562,6 @@ static void update_plane_addr(const struct core_dc *dc,
			surface->public.flip_immediate);

	surface->status.requested_address = surface->public.address;

	if (surface->public.visible)
		pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, false);
}

void dce110_update_pending_status(struct pipe_ctx *pipe_ctx)
@@ -1718,6 +1717,7 @@ static void init_hw(struct core_dc *dc)
		/* Blank controller using driver code instead of
		 * command table. */
		tg->funcs->set_blank(tg, true);
		hwss_wait_for_blank_complete(tg);
	}

	for (i = 0; i < dc->res_pool->audio_count; i++) {
@@ -2002,7 +2002,7 @@ static const struct hw_sequencer_funcs dce110_funcs = {
	.set_drr = set_drr,
	.set_static_screen_control = set_static_screen_control,
	.reset_hw_ctx_wrap = reset_hw_ctx_wrap,
	.prog_pixclk_crtc_otg = prog_pixclk_crtc_otg,
	.prog_pixclk_crtc_otg = dce110_prog_pixclk_crtc_otg,
};

bool dce110_hw_sequencer_construct(struct core_dc *dc)
+1 −27
Original line number Diff line number Diff line
@@ -1808,7 +1808,7 @@ bool dce110_tg_is_blanked(struct timing_generator *tg)
	return false;
}

bool dce110_tg_set_blank(struct timing_generator *tg,
void dce110_tg_set_blank(struct timing_generator *tg,
		bool enable_blanking)
{
	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
@@ -1824,8 +1824,6 @@ bool dce110_tg_set_blank(struct timing_generator *tg,
	value = 0;

	if (enable_blanking) {
		int counter;

		set_reg_field_value(
			value,
			1,
@@ -1834,32 +1832,8 @@ bool dce110_tg_set_blank(struct timing_generator *tg,

		dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), value);

		for (counter = 0; counter < 100; counter++) {
			value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL));

			if (get_reg_field_value(
				value,
				CRTC_BLANK_CONTROL,
				CRTC_BLANK_DATA_EN) == 1 &&
				get_reg_field_value(
				value,
				CRTC_BLANK_CONTROL,
				CRTC_CURRENT_BLANK_STATE) == 1)
				break;

			msleep(1);
		}

		if (counter == 100) {
			dm_logger_write(tg->ctx->logger, LOG_ERROR,
					"timing generator %d blank timing out.\n",
					tg110->controller_id);
			return false;
		}
	} else
		dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), 0);

	return true;
}

bool dce110_tg_validate_timing(struct timing_generator *tg,
+1 −1
Original line number Diff line number Diff line
@@ -257,7 +257,7 @@ void dce110_tg_program_timing(struct timing_generator *tg,

bool dce110_tg_is_blanked(struct timing_generator *tg);

bool dce110_tg_set_blank(struct timing_generator *tg,
void dce110_tg_set_blank(struct timing_generator *tg,
		bool enable_blanking);

bool dce110_tg_validate_timing(struct timing_generator *tg,
+5 −34
Original line number Diff line number Diff line
@@ -72,12 +72,11 @@ static bool dce110_timing_generator_v_disable_crtc(struct timing_generator *tg)
	return true;
}

static bool dce110_timing_generator_v_blank_crtc(struct timing_generator *tg)
static void dce110_timing_generator_v_blank_crtc(struct timing_generator *tg)
{
	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
	uint32_t addr = mmCRTCV_BLANK_CONTROL;
	uint32_t value = dm_read_reg(tg->ctx, addr);
	uint8_t counter = 100;

	set_reg_field_value(
		value,
@@ -92,35 +91,9 @@ static bool dce110_timing_generator_v_blank_crtc(struct timing_generator *tg)
		CRTC_BLANK_DE_MODE);

	dm_write_reg(tg->ctx, addr, value);

	while (counter > 0) {
		value = dm_read_reg(tg->ctx, addr);

		if (get_reg_field_value(
			value,
			CRTCV_BLANK_CONTROL,
			CRTC_BLANK_DATA_EN) == 1 &&
			get_reg_field_value(
			value,
			CRTCV_BLANK_CONTROL,
			CRTC_CURRENT_BLANK_STATE) == 1)
			break;

		msleep(1);
		counter--;
}

	if (!counter) {
		dm_logger_write(tg->ctx->logger, LOG_ERROR,
				"timing generator %d blank timing out.\n",
				tg110->controller_id);
		return false;
	}

	return true;
}

static bool dce110_timing_generator_v_unblank_crtc(struct timing_generator *tg)
static void dce110_timing_generator_v_unblank_crtc(struct timing_generator *tg)
{
	uint32_t addr = mmCRTCV_BLANK_CONTROL;
	uint32_t value = dm_read_reg(tg->ctx, addr);
@@ -138,8 +111,6 @@ static bool dce110_timing_generator_v_unblank_crtc(struct timing_generator *tg)
		CRTC_BLANK_DE_MODE);

	dm_write_reg(tg->ctx, addr, value);

	return true;
}

static bool dce110_timing_generator_v_is_in_vertical_blank(
@@ -429,13 +400,13 @@ static void dce110_timing_generator_v_enable_advanced_request(
	dm_write_reg(tg->ctx, addr, value);
}

static bool dce110_timing_generator_v_set_blank(struct timing_generator *tg,
static void dce110_timing_generator_v_set_blank(struct timing_generator *tg,
		bool enable_blanking)
{
	if (enable_blanking)
		return dce110_timing_generator_v_blank_crtc(tg);
		dce110_timing_generator_v_blank_crtc(tg);
	else
		return dce110_timing_generator_v_unblank_crtc(tg);
		dce110_timing_generator_v_unblank_crtc(tg);
}

static void dce110_timing_generator_v_program_timing(struct timing_generator *tg,
Loading