Commit 3ebf766c authored by Ivan Lipski's avatar Ivan Lipski Committed by Alex Deucher
Browse files

drm/amd/display: Clear the CUR_ENABLE register on DCN314 w/out DPP PG

[Why&How]
ON DCN314, clearing DPP SW structure without power gating it can cause a
double cursor in full screen with non-native scaling.

A W/A that clears CURSOR0_CONTROL cursor_enable flag if
dcn10_plane_atomic_power_down is called and DPP power gating is disabled.

Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4168


Reviewed-by: default avatarSun peng (Leo) Li <sunpeng.li@amd.com>
Signed-off-by: default avatarIvan Lipski <ivan.lipski@amd.com>
Signed-off-by: default avatarAlex Hung <alex.hung@amd.com>
Tested-by: default avatarDan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 645f74f1)
Cc: stable@vger.kernel.org
parent 71403f58
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -520,6 +520,15 @@ void dpp1_dppclk_control(
		REG_UPDATE(DPP_CONTROL, DPP_CLOCK_ENABLE, 0);
}

void dpp_force_disable_cursor(struct dpp *dpp_base)
{
	struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);

	/* Force disable cursor */
	REG_UPDATE(CURSOR0_CONTROL, CUR0_ENABLE, 0);
	dpp_base->pos.cur0_ctl.bits.cur0_enable = 0;
}

static const struct dpp_funcs dcn10_dpp_funcs = {
		.dpp_read_state = dpp_read_state,
		.dpp_reset = dpp_reset,
+2 −0
Original line number Diff line number Diff line
@@ -1525,4 +1525,6 @@ void dpp1_construct(struct dcn10_dpp *dpp1,

void dpp1_cm_get_gamut_remap(struct dpp *dpp_base,
			     struct dpp_grph_csc_adjustment *adjust);
void dpp_force_disable_cursor(struct dpp *dpp_base);

#endif
+1 −0
Original line number Diff line number Diff line
@@ -1494,6 +1494,7 @@ static struct dpp_funcs dcn30_dpp_funcs = {
	.dpp_dppclk_control		= dpp1_dppclk_control,
	.dpp_set_hdr_multiplier		= dpp3_set_hdr_multiplier,
	.dpp_get_gamut_remap		= dpp3_cm_get_gamut_remap,
	.dpp_force_disable_cursor 	= dpp_force_disable_cursor,
};


+72 −0
Original line number Diff line number Diff line
@@ -528,3 +528,75 @@ void dcn314_disable_link_output(struct dc_link *link,

	apply_symclk_on_tx_off_wa(link);
}

/**
 * dcn314_dpp_pg_control - DPP power gate control.
 *
 * @hws: dce_hwseq reference.
 * @dpp_inst: DPP instance reference.
 * @power_on: true if we want to enable power gate, false otherwise.
 *
 * Enable or disable power gate in the specific DPP instance.
 * If power gating is disabled, will force disable cursor in the DPP instance.
 */
void dcn314_dpp_pg_control(
		struct dce_hwseq *hws,
		unsigned int dpp_inst,
		bool power_on)
{
	uint32_t power_gate = power_on ? 0 : 1;
	uint32_t pwr_status = power_on ? 0 : 2;


	if (hws->ctx->dc->debug.disable_dpp_power_gate) {
		/* Workaround for DCN314 with disabled power gating */
		if (!power_on) {

			/* Force disable cursor if power gating is disabled */
			struct dpp *dpp = hws->ctx->dc->res_pool->dpps[dpp_inst];
			if (dpp && dpp->funcs->dpp_force_disable_cursor)
				dpp->funcs->dpp_force_disable_cursor(dpp);
		}
		return;
	}
	if (REG(DOMAIN1_PG_CONFIG) == 0)
		return;

	switch (dpp_inst) {
	case 0: /* DPP0 */
		REG_UPDATE(DOMAIN1_PG_CONFIG,
				DOMAIN1_POWER_GATE, power_gate);

		REG_WAIT(DOMAIN1_PG_STATUS,
				DOMAIN1_PGFSM_PWR_STATUS, pwr_status,
				1, 1000);
		break;
	case 1: /* DPP1 */
		REG_UPDATE(DOMAIN3_PG_CONFIG,
				DOMAIN3_POWER_GATE, power_gate);

		REG_WAIT(DOMAIN3_PG_STATUS,
				DOMAIN3_PGFSM_PWR_STATUS, pwr_status,
				1, 1000);
		break;
	case 2: /* DPP2 */
		REG_UPDATE(DOMAIN5_PG_CONFIG,
				DOMAIN5_POWER_GATE, power_gate);

		REG_WAIT(DOMAIN5_PG_STATUS,
				DOMAIN5_PGFSM_PWR_STATUS, pwr_status,
				1, 1000);
		break;
	case 3: /* DPP3 */
		REG_UPDATE(DOMAIN7_PG_CONFIG,
				DOMAIN7_POWER_GATE, power_gate);

		REG_WAIT(DOMAIN7_PG_STATUS,
				DOMAIN7_PGFSM_PWR_STATUS, pwr_status,
				1, 1000);
		break;
	default:
		BREAK_TO_DEBUGGER();
		break;
	}
}
+2 −0
Original line number Diff line number Diff line
@@ -47,4 +47,6 @@ void dcn314_dpp_root_clock_control(struct dce_hwseq *hws, unsigned int dpp_inst,

void dcn314_disable_link_output(struct dc_link *link, const struct link_resource *link_res, enum signal_type signal);

void dcn314_dpp_pg_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on);

#endif /* __DC_HWSS_DCN314_H__ */
Loading