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

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
...@@ -820,22 +820,22 @@ static void dcn35_set_idle_state(struct clk_mgr *clk_mgr_base, bool allow_idle) ...@@ -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 || if (dc->config.disable_ips == DMUB_IPS_ENABLE ||
dc->config.disable_ips == DMUB_IPS_DISABLE_DYNAMIC) { 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_IPS1_ALLOW_MASK;
val = val & ~DMUB_IPS2_ALLOW_MASK; val = val & ~DMUB_IPS2_ALLOW_MASK;
} else if (dc->config.disable_ips == DMUB_IPS_DISABLE_IPS2) { } else if (dc->config.disable_ips == DMUB_IPS_DISABLE_IPS1) {
val |= DMUB_IPS1_ALLOW_MASK;
val = val & ~DMUB_IPS2_ALLOW_MASK;
} else if (dc->config.disable_ips == DMUB_IPS_DISABLE_IPS2_Z10) {
val |= DMUB_IPS1_ALLOW_MASK; val |= DMUB_IPS1_ALLOW_MASK;
val |= DMUB_IPS2_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) { if (!allow_idle) {
val = val & ~DMUB_IPS1_ALLOW_MASK; val |= DMUB_IPS1_ALLOW_MASK;
val = val & ~DMUB_IPS2_ALLOW_MASK; val |= DMUB_IPS2_ALLOW_MASK;
} }
dcn35_smu_write_ips_scratch(clk_mgr, val); dcn35_smu_write_ips_scratch(clk_mgr, val);
......
...@@ -4934,8 +4934,8 @@ bool dc_dmub_is_ips_idle_state(struct dc *dc) ...@@ -4934,8 +4934,8 @@ bool dc_dmub_is_ips_idle_state(struct dc *dc)
if (dc->hwss.get_idle_state) if (dc->hwss.get_idle_state)
idle_state = dc->hwss.get_idle_state(dc); idle_state = dc->hwss.get_idle_state(dc);
if ((idle_state & DMUB_IPS1_ALLOW_MASK) || if (!(idle_state & DMUB_IPS1_ALLOW_MASK) ||
(idle_state & DMUB_IPS2_ALLOW_MASK)) !(idle_state & DMUB_IPS2_ALLOW_MASK))
return true; return true;
return false; return false;
......
...@@ -1202,11 +1202,11 @@ void dc_dmub_srv_exit_low_power_state(const struct dc *dc) ...@@ -1202,11 +1202,11 @@ void dc_dmub_srv_exit_low_power_state(const struct dc *dc)
allow_state = dc->hwss.get_idle_state(dc); allow_state = dc->hwss.get_idle_state(dc);
dc->hwss.set_idle_state(dc, false); 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 // Wait for evaluation time
udelay(dc->debug.ips2_eval_delay_us); udelay(dc->debug.ips2_eval_delay_us);
commit_state = dc->hwss.get_idle_state(dc); 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 // Tell PMFW to exit low power state
dc->clk_mgr->funcs->exit_low_power_state(dc->clk_mgr); 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) ...@@ -1216,7 +1216,7 @@ void dc_dmub_srv_exit_low_power_state(const struct dc *dc)
for (i = 0; i < max_num_polls; ++i) { for (i = 0; i < max_num_polls; ++i) {
commit_state = dc->hwss.get_idle_state(dc); commit_state = dc->hwss.get_idle_state(dc);
if (!(commit_state & DMUB_IPS2_COMMIT_MASK)) if (commit_state & DMUB_IPS2_COMMIT_MASK)
break; break;
udelay(1); udelay(1);
...@@ -1235,10 +1235,10 @@ void dc_dmub_srv_exit_low_power_state(const struct dc *dc) ...@@ -1235,10 +1235,10 @@ void dc_dmub_srv_exit_low_power_state(const struct dc *dc)
} }
dc_dmub_srv_notify_idle(dc, false); 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) { for (i = 0; i < max_num_polls; ++i) {
commit_state = dc->hwss.get_idle_state(dc); commit_state = dc->hwss.get_idle_state(dc);
if (!(commit_state & DMUB_IPS1_COMMIT_MASK)) if (commit_state & DMUB_IPS1_COMMIT_MASK)
break; break;
udelay(1); udelay(1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment