From: Ivan Lipski <[email protected]>

[Why]
Brief blank on HDMI each time VRR engaged and disengaged, with no modeset
at either transition.

amdgpu_dm_update_freesync_state_on_stream() built the VTEM on top of the
buffer holding the AMD FreeSync SPD payload, which becomes
stream->vrr_infopacket. DC routes that to HDMI generic slot 3 (SPD) and
vtem_infopacket to slot 6 (VTEM), and vtem_infopacket was never populated.
So slot 3 carried a VTEM payload the sink parsed as an SPD
InfoFrame, no VTEM was sent, and v_total varied with no valid metadata
describing it. DP uses the VSC/AS-SDP path and is unaffected.

[How]
Build the VTEM into a separate vtem_infopacket, gated on the sink not
advertising AMD FreeSync. Track it in dm_crtc_state, include it in the
freesync_vrr_info_changed comparison and the reset path, and pass it
through bundle->stream_update.vtem_infopacket.

Reviewed-by: Jerry Zuo <[email protected]>
Signed-off-by: Ivan Lipski <[email protected]>
Signed-off-by: Roman Li <[email protected]>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  2 ++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  1 +
 .../display/amdgpu_dm/amdgpu_dm_freesync.c    | 26 +++++++++++++++----
 3 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 6e5dbe0bd82e..f3ed3fef59f9 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -4141,6 +4141,8 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_commit *state,
                        if (acrtc_state->freesync_vrr_info_changed) {
                                bundle->stream_update.vrr_infopacket =
                                        &acrtc_state->stream->vrr_infopacket;
+                               bundle->stream_update.vtem_infopacket =
+                                       &acrtc_state->stream->vtem_infopacket;
                                bundle->stream_update.vsp_infopacket =
                                        &acrtc_state->stream->vsp_infopacket;
                                stream_update_needed = true;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index 2ead9bc8e439..594d275918d5 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -1076,6 +1076,7 @@ struct dm_crtc_state {
        bool vrr_supported;
        struct mod_freesync_config freesync_config;
        struct dc_info_packet vrr_infopacket;
+       struct dc_info_packet vtem_infopacket;
 
        int abm_level;
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.c
index 1d9148ccfd4f..f4ce389fd0aa 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.c
@@ -107,6 +107,8 @@ void amdgpu_dm_reset_freesync_config_for_crtc(
 
        memset(&new_crtc_state->vrr_infopacket, 0,
               sizeof(new_crtc_state->vrr_infopacket));
+       memset(&new_crtc_state->vtem_infopacket, 0,
+              sizeof(new_crtc_state->vtem_infopacket));
 }
 EXPORT_SYMBOL_IF_KUNIT(amdgpu_dm_reset_freesync_config_for_crtc);
 
@@ -172,6 +174,7 @@ void amdgpu_dm_update_freesync_state_on_stream(
 {
        struct mod_vrr_params vrr_params;
        struct dc_info_packet vrr_infopacket = {0};
+       struct dc_info_packet vtem_infopacket = {0};
        struct amdgpu_device *adev = dm->adev;
        struct amdgpu_crtc *acrtc = to_amdgpu_crtc(new_crtc_state->base.crtc);
        unsigned long flags;
@@ -238,21 +241,34 @@ void amdgpu_dm_update_freesync_state_on_stream(
                &vrr_infopacket,
                pack_sdp_v1_3);
 
-       /* Per HDMI 2.1, VTEM is valid on TMDS as well as FRL */
-       if (new_stream->signal == SIGNAL_TYPE_HDMI_FRL ||
-           (new_stream->signal == SIGNAL_TYPE_HDMI_TYPE_A &&
-            aconn && aconn->base.display_info.hdmi.vrr_cap.supported))
-               mod_build_infopacket_vtem(new_stream, &vrr_params, 0, 
&vrr_infopacket);
+       /*
+        * If the sink does not support FreeSync, but it does support VRR,
+        * we need to build a VTEM packet to enable VRR.
+        */
+       if (aconn && !aconn->vsdb_info.freesync_supported &&
+           aconn->base.display_info.hdmi.vrr_cap.supported &&
+           (new_stream->signal == SIGNAL_TYPE_HDMI_FRL ||
+            new_stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)) {
+               mod_build_infopacket_vtem(new_stream, &vrr_params, 0, 
&vtem_infopacket);
+               memset(&vrr_infopacket, 0, sizeof(vrr_infopacket));
+       }
 
        new_crtc_state->freesync_vrr_info_changed |=
                (memcmp(&new_crtc_state->vrr_infopacket,
                        &vrr_infopacket,
                        sizeof(vrr_infopacket)) != 0);
 
+       new_crtc_state->freesync_vrr_info_changed |=
+               (memcmp(&new_crtc_state->vtem_infopacket,
+                       &vtem_infopacket,
+                       sizeof(vtem_infopacket)) != 0);
+
        acrtc->dm_irq_params.vrr_params = vrr_params;
        new_crtc_state->vrr_infopacket = vrr_infopacket;
+       new_crtc_state->vtem_infopacket = vtem_infopacket;
 
        new_stream->vrr_infopacket = vrr_infopacket;
+       new_stream->vtem_infopacket = vtem_infopacket;
        new_stream->allow_freesync = 
mod_freesync_get_freesync_enabled(&vrr_params);
 
        /*
-- 
2.34.1

Reply via email to