]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/amd/display: Do not wait for PSR disable on vbl enable
authorLeo Li <sunpeng.li@amd.com>
Mon, 9 Dec 2024 17:58:33 +0000 (12:58 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 10 Jan 2025 18:40:47 +0000 (13:40 -0500)
[Why]

Outside of a modeset/link configuration change, we should not have to
wait for the panel to exit PSR. Depending on the panel and it's state,
it may take multiple frames for it to exit PSR. Therefore, waiting in
all scenarios may cause perceived stuttering, especially in combination
with faster vblank shutdown.

[How]

PSR1 disable is hooked up to the vblank enable event, and vice versa. In
case of vblank enable, do not wait for panel to exit PSR, but still wait
in all other cases.

We also avoid a call to unnecessarily change power_opts on disable -
this ends up sending another command to dmcub fw.

When testing against IGT, some crc tests like kms_plane_alpha_blend and
amd_hotplug were failing due to CRC timeouts. This was found to be
caused by the early return before HW has fully exited PSR1. Fix this by
first making sure we grab a vblank reference, then waiting for panel to
exit PSR1, before programming hw for CRC generation.

Fixes: 58a261bfc967 ("drm/amd/display: use a more lax vblank enable policy for older ASICs")
Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3743
Reviewed-by: Tom Chung <chiahsuan.chung@amd.com>
Signed-off-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Tom Chung <chiahsuan.chung@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit aa6713fa2046f4c09bf3013dd1420ae15603ca6f)
Cc: stable@vger.kernel.org
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.h

index cd16dae534dccb9556445b16d6563d45eef49ac2..56b47e02db0b47ca4197daf1869bd79bdb003311 100644 (file)
@@ -9100,7 +9100,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                                acrtc_state->stream->link->psr_settings.psr_dirty_rects_change_timestamp_ns =
                                timestamp_ns;
                                if (acrtc_state->stream->link->psr_settings.psr_allow_active)
-                                       amdgpu_dm_psr_disable(acrtc_state->stream);
+                                       amdgpu_dm_psr_disable(acrtc_state->stream, true);
                                mutex_unlock(&dm->dc_lock);
                        }
                }
@@ -9270,7 +9270,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                        if (acrtc_state->stream->link->replay_settings.replay_allow_active)
                                amdgpu_dm_replay_disable(acrtc_state->stream);
                        if (acrtc_state->stream->link->psr_settings.psr_allow_active)
-                               amdgpu_dm_psr_disable(acrtc_state->stream);
+                               amdgpu_dm_psr_disable(acrtc_state->stream, true);
                }
                mutex_unlock(&dm->dc_lock);
 
index f936a35fa9ebb716b8082d8e53cf0b4053e1a586..0f6ba7b1575d087cd7c046c1d713eec59a4425c3 100644 (file)
@@ -30,6 +30,7 @@
 #include "amdgpu_dm.h"
 #include "dc.h"
 #include "amdgpu_securedisplay.h"
+#include "amdgpu_dm_psr.h"
 
 static const char *const pipe_crc_sources[] = {
        "none",
@@ -224,6 +225,10 @@ int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc,
 
        mutex_lock(&adev->dm.dc_lock);
 
+       /* For PSR1, check that the panel has exited PSR */
+       if (stream_state->link->psr_settings.psr_version < DC_PSR_VERSION_SU_1)
+               amdgpu_dm_psr_wait_disable(stream_state);
+
        /* Enable or disable CRTC CRC generation */
        if (dm_is_crc_source_crtc(source) || source == AMDGPU_DM_PIPE_CRC_SOURCE_NONE) {
                if (!dc_stream_configure_crc(stream_state->ctx->dc,
@@ -357,6 +362,17 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
 
        }
 
+       /*
+        * Reading the CRC requires the vblank interrupt handler to be
+        * enabled. Keep a reference until CRC capture stops.
+        */
+       enabled = amdgpu_dm_is_valid_crc_source(cur_crc_src);
+       if (!enabled && enable) {
+               ret = drm_crtc_vblank_get(crtc);
+               if (ret)
+                       goto cleanup;
+       }
+
 #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
        /* Reset secure_display when we change crc source from debugfs */
        amdgpu_dm_set_crc_window_default(crtc, crtc_state->stream);
@@ -367,16 +383,7 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
                goto cleanup;
        }
 
-       /*
-        * Reading the CRC requires the vblank interrupt handler to be
-        * enabled. Keep a reference until CRC capture stops.
-        */
-       enabled = amdgpu_dm_is_valid_crc_source(cur_crc_src);
        if (!enabled && enable) {
-               ret = drm_crtc_vblank_get(crtc);
-               if (ret)
-                       goto cleanup;
-
                if (dm_is_crc_source_dprx(source)) {
                        if (drm_dp_start_crc(aux, crtc)) {
                                DRM_DEBUG_DRIVER("dp start crc failed\n");
index 64a041c2af05c336f3a6437c8fe8f52c48ca0ea4..3011ea709b910c0c483825346a68ea172363c70a 100644 (file)
@@ -142,7 +142,7 @@ static void amdgpu_dm_crtc_set_panel_sr_feature(
                amdgpu_dm_replay_enable(vblank_work->stream, true);
        } else if (vblank_enabled) {
                if (link->psr_settings.psr_version < DC_PSR_VERSION_SU_1 && is_sr_active)
-                       amdgpu_dm_psr_disable(vblank_work->stream);
+                       amdgpu_dm_psr_disable(vblank_work->stream, false);
        } else if (link->psr_settings.psr_feature_enabled &&
                allow_sr_entry && !is_sr_active && !is_crc_window_active) {
 
index 6a97bb2d9160155301b028af882b4d9eea30c323..8b7c1a428f642271a121c0ce7c87959423f088d2 100644 (file)
@@ -3606,7 +3606,7 @@ static int crc_win_update_set(void *data, u64 val)
                /* PSR may write to OTG CRC window control register,
                 * so close it before starting secure_display.
                 */
-               amdgpu_dm_psr_disable(acrtc->dm_irq_params.stream);
+               amdgpu_dm_psr_disable(acrtc->dm_irq_params.stream, true);
 
                spin_lock_irq(&adev_to_drm(adev)->event_lock);
 
index f40240aafe988ee5d42ea53960e6f3ae136c0731..45858bf1523d8f6e8922aa087d98e310e02cd129 100644 (file)
@@ -201,14 +201,13 @@ void amdgpu_dm_psr_enable(struct dc_stream_state *stream)
  *
  * Return: true if success
  */
-bool amdgpu_dm_psr_disable(struct dc_stream_state *stream)
+bool amdgpu_dm_psr_disable(struct dc_stream_state *stream, bool wait)
 {
-       unsigned int power_opt = 0;
        bool psr_enable = false;
 
        DRM_DEBUG_DRIVER("Disabling psr...\n");
 
-       return dc_link_set_psr_allow_active(stream->link, &psr_enable, true, false, &power_opt);
+       return dc_link_set_psr_allow_active(stream->link, &psr_enable, wait, false, NULL);
 }
 
 /*
@@ -251,3 +250,33 @@ bool amdgpu_dm_psr_is_active_allowed(struct amdgpu_display_manager *dm)
 
        return allow_active;
 }
+
+/**
+ * amdgpu_dm_psr_wait_disable() - Wait for eDP panel to exit PSR
+ * @stream: stream state attached to the eDP link
+ *
+ * Waits for a max of 500ms for the eDP panel to exit PSR.
+ *
+ * Return: true if panel exited PSR, false otherwise.
+ */
+bool amdgpu_dm_psr_wait_disable(struct dc_stream_state *stream)
+{
+       enum dc_psr_state psr_state = PSR_STATE0;
+       struct dc_link *link = stream->link;
+       int retry_count;
+
+       if (link == NULL)
+               return false;
+
+       for (retry_count = 0; retry_count <= 1000; retry_count++) {
+               dc_link_get_psr_state(link, &psr_state);
+               if (psr_state == PSR_STATE0)
+                       break;
+               udelay(500);
+       }
+
+       if (retry_count == 1000)
+               return false;
+
+       return true;
+}
index cd2d45c2b5ef01f73601e7504e39e9fe619fe8fc..e2366321a3c1bdbb6991a1dd0d78f4fdd74f25fd 100644 (file)
@@ -34,8 +34,9 @@
 void amdgpu_dm_set_psr_caps(struct dc_link *link);
 void amdgpu_dm_psr_enable(struct dc_stream_state *stream);
 bool amdgpu_dm_link_setup_psr(struct dc_stream_state *stream);
-bool amdgpu_dm_psr_disable(struct dc_stream_state *stream);
+bool amdgpu_dm_psr_disable(struct dc_stream_state *stream, bool wait);
 bool amdgpu_dm_psr_disable_all(struct amdgpu_display_manager *dm);
 bool amdgpu_dm_psr_is_active_allowed(struct amdgpu_display_manager *dm);
+bool amdgpu_dm_psr_wait_disable(struct dc_stream_state *stream);
 
 #endif /* AMDGPU_DM_AMDGPU_DM_PSR_H_ */