Commit bf224e00 authored by Nicholas Kazlauskas's avatar Nicholas Kazlauskas Committed by Alex Deucher
Browse files

drm/amd/display: Fix 4to1 MPC black screen with DPP RCO



[Why]
DPP Root clock optimization when combined with 4to1 MPC combine results
in the screen turning black.

This is because the DPPCLK is stopped during the middle of an
optimize_bandwidth sequence during commit_minimal_transition without
going through plane power down/power up.

[How]
The intent of a 0Hz DPP clock through update_clocks is to disable the
DTO. This differs from the behavior of stopping the DPPCLK entirely
(utilizing a 0Hz clock on some ASIC) so it's better to move this logic
to reside next to plane power up/power down where we gate the HUBP/DPP
DOMAIN.

The new  sequence should be:
Power down: PG enabled -> RCO on
Power up: RCO off -> PG disabled

Rename power_on_plane to power_on_plane_resources to reflect the
actual operation that's occurring.

Cc: stable@vger.kernel.org
Cc: Mario Limonciello <mario.limonciello@amd.com>
Reviewed-by: default avatarJun Lei <Jun.Lei@amd.com>
Acked-by: default avatarQingqing Zhuo <qingqing.zhuo@amd.com>
Signed-off-by: default avatarNicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 19914818
Loading
Loading
Loading
Loading
+10 −2
Original line number Original line Diff line number Diff line
@@ -726,11 +726,15 @@ void dcn10_hubp_pg_control(
	}
	}
}
}


static void power_on_plane(
static void power_on_plane_resources(
	struct dce_hwseq *hws,
	struct dce_hwseq *hws,
	int plane_id)
	int plane_id)
{
{
	DC_LOGGER_INIT(hws->ctx->logger);
	DC_LOGGER_INIT(hws->ctx->logger);

	if (hws->funcs.dpp_root_clock_control)
		hws->funcs.dpp_root_clock_control(hws, plane_id, true);

	if (REG(DC_IP_REQUEST_CNTL)) {
	if (REG(DC_IP_REQUEST_CNTL)) {
		REG_SET(DC_IP_REQUEST_CNTL, 0,
		REG_SET(DC_IP_REQUEST_CNTL, 0,
				IP_REQUEST_EN, 1);
				IP_REQUEST_EN, 1);
@@ -1237,11 +1241,15 @@ void dcn10_plane_atomic_power_down(struct dc *dc,
			hws->funcs.hubp_pg_control(hws, hubp->inst, false);
			hws->funcs.hubp_pg_control(hws, hubp->inst, false);


		dpp->funcs->dpp_reset(dpp);
		dpp->funcs->dpp_reset(dpp);

		REG_SET(DC_IP_REQUEST_CNTL, 0,
		REG_SET(DC_IP_REQUEST_CNTL, 0,
				IP_REQUEST_EN, 0);
				IP_REQUEST_EN, 0);
		DC_LOG_DEBUG(
		DC_LOG_DEBUG(
				"Power gated front end %d\n", hubp->inst);
				"Power gated front end %d\n", hubp->inst);
	}
	}

	if (hws->funcs.dpp_root_clock_control)
		hws->funcs.dpp_root_clock_control(hws, dpp->inst, false);
}
}


/* disable HW used by plane.
/* disable HW used by plane.
@@ -2462,7 +2470,7 @@ static void dcn10_enable_plane(


	undo_DEGVIDCN10_253_wa(dc);
	undo_DEGVIDCN10_253_wa(dc);


	power_on_plane(dc->hwseq,
	power_on_plane_resources(dc->hwseq,
		pipe_ctx->plane_res.hubp->inst);
		pipe_ctx->plane_res.hubp->inst);


	/* enable DCFCLK current DCHUB */
	/* enable DCFCLK current DCHUB */
+6 −2
Original line number Original line Diff line number Diff line
@@ -1130,11 +1130,15 @@ void dcn20_blank_pixel_data(
}
}




static void dcn20_power_on_plane(
static void dcn20_power_on_plane_resources(
	struct dce_hwseq *hws,
	struct dce_hwseq *hws,
	struct pipe_ctx *pipe_ctx)
	struct pipe_ctx *pipe_ctx)
{
{
	DC_LOGGER_INIT(hws->ctx->logger);
	DC_LOGGER_INIT(hws->ctx->logger);

	if (hws->funcs.dpp_root_clock_control)
		hws->funcs.dpp_root_clock_control(hws, pipe_ctx->plane_res.dpp->inst, true);

	if (REG(DC_IP_REQUEST_CNTL)) {
	if (REG(DC_IP_REQUEST_CNTL)) {
		REG_SET(DC_IP_REQUEST_CNTL, 0,
		REG_SET(DC_IP_REQUEST_CNTL, 0,
				IP_REQUEST_EN, 1);
				IP_REQUEST_EN, 1);
@@ -1158,7 +1162,7 @@ static void dcn20_enable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx,
	//if (dc->debug.sanity_checks) {
	//if (dc->debug.sanity_checks) {
	//	dcn10_verify_allow_pstate_change_high(dc);
	//	dcn10_verify_allow_pstate_change_high(dc);
	//}
	//}
	dcn20_power_on_plane(dc->hwseq, pipe_ctx);
	dcn20_power_on_plane_resources(dc->hwseq, pipe_ctx);


	/* enable DCFCLK current DCHUB */
	/* enable DCFCLK current DCHUB */
	pipe_ctx->plane_res.hubp->funcs->hubp_clk_cntl(pipe_ctx->plane_res.hubp, true);
	pipe_ctx->plane_res.hubp->funcs->hubp_clk_cntl(pipe_ctx->plane_res.hubp, true);
+2 −11
Original line number Original line Diff line number Diff line
@@ -65,19 +65,10 @@ void dccg31_update_dpp_dto(struct dccg *dccg, int dpp_inst, int req_dppclk)
				DPPCLK0_DTO_MODULO, modulo);
				DPPCLK0_DTO_MODULO, modulo);
		REG_UPDATE(DPPCLK_DTO_CTRL,
		REG_UPDATE(DPPCLK_DTO_CTRL,
				DPPCLK_DTO_ENABLE[dpp_inst], 1);
				DPPCLK_DTO_ENABLE[dpp_inst], 1);
	} else {
		//DTO must be enabled to generate a 0Hz clock output
		if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpp) {
			REG_UPDATE(DPPCLK_DTO_CTRL,
					DPPCLK_DTO_ENABLE[dpp_inst], 1);
			REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
					DPPCLK0_DTO_PHASE, 0,
					DPPCLK0_DTO_MODULO, 1);
	} else {
	} else {
		REG_UPDATE(DPPCLK_DTO_CTRL,
		REG_UPDATE(DPPCLK_DTO_CTRL,
				DPPCLK_DTO_ENABLE[dpp_inst], 0);
				DPPCLK_DTO_ENABLE[dpp_inst], 0);
	}
	}
	}
	dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk;
	dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk;
}
}


+23 −0
Original line number Original line Diff line number Diff line
@@ -289,8 +289,31 @@ static void dccg314_set_valid_pixel_rate(
	dccg314_set_dtbclk_dto(dccg, &dto_params);
	dccg314_set_dtbclk_dto(dccg, &dto_params);
}
}


static void dccg314_dpp_root_clock_control(
		struct dccg *dccg,
		unsigned int dpp_inst,
		bool clock_on)
{
	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);

	if (clock_on) {
		/* turn off the DTO and leave phase/modulo at max */
		REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_ENABLE[dpp_inst], 0);
		REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
			  DPPCLK0_DTO_PHASE, 0xFF,
			  DPPCLK0_DTO_MODULO, 0xFF);
	} else {
		/* turn on the DTO to generate a 0hz clock */
		REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_ENABLE[dpp_inst], 1);
		REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
			  DPPCLK0_DTO_PHASE, 0,
			  DPPCLK0_DTO_MODULO, 1);
	}
}

static const struct dccg_funcs dccg314_funcs = {
static const struct dccg_funcs dccg314_funcs = {
	.update_dpp_dto = dccg31_update_dpp_dto,
	.update_dpp_dto = dccg31_update_dpp_dto,
	.dpp_root_clock_control = dccg314_dpp_root_clock_control,
	.get_dccg_ref_freq = dccg31_get_dccg_ref_freq,
	.get_dccg_ref_freq = dccg31_get_dccg_ref_freq,
	.dccg_init = dccg31_init,
	.dccg_init = dccg31_init,
	.set_dpstreamclk = dccg314_set_dpstreamclk,
	.set_dpstreamclk = dccg314_set_dpstreamclk,
+10 −0
Original line number Original line Diff line number Diff line
@@ -390,6 +390,16 @@ void dcn314_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx)
				pix_per_cycle);
				pix_per_cycle);
}
}


void dcn314_dpp_root_clock_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool clock_on)
{
	if (!hws->ctx->dc->debug.root_clock_optimization.bits.dpp)
		return;

	if (hws->ctx->dc->res_pool->dccg->funcs->dpp_root_clock_control)
		hws->ctx->dc->res_pool->dccg->funcs->dpp_root_clock_control(
			hws->ctx->dc->res_pool->dccg, dpp_inst, clock_on);
}

void dcn314_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on)
void dcn314_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on)
{
{
	struct dc_context *ctx = hws->ctx;
	struct dc_context *ctx = hws->ctx;
Loading