drm/amd/display: Add IPS checks before dcn register access
authorRoman Li <roman.li@amd.com>
Tue, 9 Jan 2024 22:31:33 +0000 (17:31 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 22 Jan 2024 22:13:27 +0000 (17:13 -0500)
[Why]
With IPS enabled a system hangs once PSR is active.
PSR active triggers transition to IPS2 state.
While in IPS2 an access to dcn registers results in hard hang.
Existing check doesn't cover for PSR sequence.

[How]
Safeguard register access by disabling idle optimization in atomic commit
and crtc scanout. It will be re-enabled on next vblank.

Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Acked-by: Roman Li <roman.li@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c

index 8623722e954f9c6559759c374220da1165d06067..4e42c4dfd88e2d50bc7030d980822c72fe6540b8 100644 (file)
@@ -273,6 +273,7 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
 {
        u32 v_blank_start, v_blank_end, h_position, v_position;
        struct amdgpu_crtc *acrtc = NULL;
+       struct dc *dc = adev->dm.dc;
 
        if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc))
                return -EINVAL;
@@ -285,6 +286,9 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
                return 0;
        }
 
+       if (dc && dc->caps.ips_support && dc->idle_optimizations_allowed)
+               dc_allow_idle_optimizations(dc, false);
+
        /*
         * TODO rework base driver to use values directly.
         * for now parse it back into reg-format
@@ -9011,16 +9015,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
 
        trace_amdgpu_dm_atomic_commit_tail_begin(state);
 
-       if (dm->dc->caps.ips_support) {
-               for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) {
-                       if (new_con_state->crtc &&
-                               new_con_state->crtc->state->active &&
-                               drm_atomic_crtc_needs_modeset(new_con_state->crtc->state)) {
-                               dc_dmub_srv_apply_idle_power_optimizations(dm->dc, false);
-                               break;
-                       }
-               }
-       }
+       if (dm->dc->caps.ips_support && dm->dc->idle_optimizations_allowed)
+               dc_allow_idle_optimizations(dm->dc, false);
 
        drm_atomic_helper_update_legacy_modeset_state(dev, state);
        drm_dp_mst_atomic_wait_for_dependencies(state);