Commit 5e8a0d35 authored by Duncan Ma's avatar Duncan Ma Committed by Alex Deucher
Browse files

drm/amd/display: Negate IPS allow and commit bits



[WHY]
On s0i3, IPS mask isn't saved and restored.
It is reset to zero on exit.

If it is cleared unexpectedly, driver will
proceed operations while DCN is in IPS2 and
cause a hang.

[HOW]
Negate the bit logic. Default value of
zero indicates it is still in IPS2. Driver
must poll for the bit to assert.

Cc: Mario Limonciello <mario.limonciello@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
Reviewed-by: default avatarCharlene Liu <charlene.liu@amd.com>
Acked-by: default avatarAlex Hung <alex.hung@amd.com>
Signed-off-by: default avatarDuncan Ma <duncan.ma@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 0f216364
Loading
Loading
Loading
Loading
+9 −9
Original line number Diff line number Diff line
@@ -820,22 +820,22 @@ static void dcn35_set_idle_state(struct clk_mgr *clk_mgr_base, bool allow_idle)

	if (dc->config.disable_ips == DMUB_IPS_ENABLE ||
		dc->config.disable_ips == DMUB_IPS_DISABLE_DYNAMIC) {
		val |= DMUB_IPS1_ALLOW_MASK;
		val |= DMUB_IPS2_ALLOW_MASK;
	} else if (dc->config.disable_ips == DMUB_IPS_DISABLE_IPS1) {
		val = val & ~DMUB_IPS1_ALLOW_MASK;
		val = val & ~DMUB_IPS2_ALLOW_MASK;
	} else if (dc->config.disable_ips == DMUB_IPS_DISABLE_IPS2) {
		val |= DMUB_IPS1_ALLOW_MASK;
		val = val & ~DMUB_IPS2_ALLOW_MASK;
	} else if (dc->config.disable_ips == DMUB_IPS_DISABLE_IPS2_Z10) {
	} else if (dc->config.disable_ips == DMUB_IPS_DISABLE_IPS1) {
		val |= DMUB_IPS1_ALLOW_MASK;
		val |= DMUB_IPS2_ALLOW_MASK;
	} else if (dc->config.disable_ips == DMUB_IPS_DISABLE_IPS2) {
		val = val & ~DMUB_IPS1_ALLOW_MASK;
		val |= DMUB_IPS2_ALLOW_MASK;
	} else if (dc->config.disable_ips == DMUB_IPS_DISABLE_IPS2_Z10) {
		val = val & ~DMUB_IPS1_ALLOW_MASK;
		val = val & ~DMUB_IPS2_ALLOW_MASK;
	}

	if (!allow_idle) {
		val = val & ~DMUB_IPS1_ALLOW_MASK;
		val = val & ~DMUB_IPS2_ALLOW_MASK;
		val |= DMUB_IPS1_ALLOW_MASK;
		val |= DMUB_IPS2_ALLOW_MASK;
	}

	dcn35_smu_write_ips_scratch(clk_mgr, val);
+2 −2
Original line number Diff line number Diff line
@@ -4934,8 +4934,8 @@ bool dc_dmub_is_ips_idle_state(struct dc *dc)
	if (dc->hwss.get_idle_state)
		idle_state = dc->hwss.get_idle_state(dc);

	if ((idle_state & DMUB_IPS1_ALLOW_MASK) ||
		(idle_state & DMUB_IPS2_ALLOW_MASK))
	if (!(idle_state & DMUB_IPS1_ALLOW_MASK) ||
		!(idle_state & DMUB_IPS2_ALLOW_MASK))
		return true;

	return false;
+5 −5
Original line number Diff line number Diff line
@@ -1202,11 +1202,11 @@ void dc_dmub_srv_exit_low_power_state(const struct dc *dc)
		allow_state = dc->hwss.get_idle_state(dc);
		dc->hwss.set_idle_state(dc, false);

		if (allow_state & DMUB_IPS2_ALLOW_MASK) {
		if (!(allow_state & DMUB_IPS2_ALLOW_MASK)) {
			// Wait for evaluation time
			udelay(dc->debug.ips2_eval_delay_us);
			commit_state = dc->hwss.get_idle_state(dc);
			if (commit_state & DMUB_IPS2_COMMIT_MASK) {
			if (!(commit_state & DMUB_IPS2_COMMIT_MASK)) {
				// Tell PMFW to exit low power state
				dc->clk_mgr->funcs->exit_low_power_state(dc->clk_mgr);

@@ -1216,7 +1216,7 @@ void dc_dmub_srv_exit_low_power_state(const struct dc *dc)

				for (i = 0; i < max_num_polls; ++i) {
					commit_state = dc->hwss.get_idle_state(dc);
					if (!(commit_state & DMUB_IPS2_COMMIT_MASK))
					if (commit_state & DMUB_IPS2_COMMIT_MASK)
						break;

					udelay(1);
@@ -1235,10 +1235,10 @@ void dc_dmub_srv_exit_low_power_state(const struct dc *dc)
		}

		dc_dmub_srv_notify_idle(dc, false);
		if (allow_state & DMUB_IPS1_ALLOW_MASK) {
		if (!(allow_state & DMUB_IPS1_ALLOW_MASK)) {
			for (i = 0; i < max_num_polls; ++i) {
				commit_state = dc->hwss.get_idle_state(dc);
				if (!(commit_state & DMUB_IPS1_COMMIT_MASK))
				if (commit_state & DMUB_IPS1_COMMIT_MASK)
					break;

				udelay(1);