why:
HDMI 2.1 Auto Low-Latency Mode (ALLM) lets a Source request the Sink's
low-latency mode through the HF-VSIF. HDMI 2.1 Section 7.6.6 requires
that when Gaming-VRR is enabled (VRR_EN=1) and the Sink advertises ALLM
in the SCDS, the Source shall transmit the HF-VSIF and set ALLM_Mode=1.
amdgpu never set ALLM_Mode, so this requirement was not met.

how:
- In update_freesync_state_on_stream(), set ALLM_Mode=1 in the HF-VSIF
  when Gaming-VRR is active (vrr state ACTIVE_VARIABLE/ACTIVE_FIXED,
  i.e. VRR_EN=1) and the sink advertises ALLM, per HDMI 2.1 Section
  7.6.6, and push the updated HF-VSIF (vsp_infopacket) as a stream
  update.

ALLM is driven only by the mandatory Gaming-VRR case.

Signed-off-by: Fangzhi Zuo <[email protected]>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  5 +++-
 .../display/amdgpu_dm/amdgpu_dm_freesync.c    | 29 +++++++++++++++++++
 2 files changed, 33 insertions(+), 1 deletion(-)

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 567bf04979ee..ff0db0cb9880 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -4029,9 +4029,12 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_commit *state,
                }
 
                if (acrtc_state->stream) {
-                       if (acrtc_state->freesync_vrr_info_changed)
+                       if (acrtc_state->freesync_vrr_info_changed) {
                                bundle->stream_update.vrr_infopacket =
                                        &acrtc_state->stream->vrr_infopacket;
+                               bundle->stream_update.vsp_infopacket =
+                                       &acrtc_state->stream->vsp_infopacket;
+                       }
                }
        }
 
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 382c339b67b1..63d10cb7f5ed 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
@@ -252,6 +252,35 @@ void amdgpu_dm_update_freesync_state_on_stream(
        new_stream->vrr_infopacket = vrr_infopacket;
        new_stream->allow_freesync = 
mod_freesync_get_freesync_enabled(&vrr_params);
 
+       /*
+        * HDMI ALLM: when Gaming-VRR is active (VRR_EN=1) and the sink
+        * advertises ALLM in the SCDS, the Source shall transmit the HF-VSIF
+        * with ALLM_Mode=1 (HDMI 2.1 Section 7.6.6).
+        */
+       if (new_stream->signal == SIGNAL_TYPE_HDMI_TYPE_A ||
+           new_stream->signal == SIGNAL_TYPE_HDMI_FRL) {
+               struct dc_info_packet vsp_infopacket = {0};
+               bool sink_allm = aconn && aconn->base.display_info.hdmi.allm;
+               bool allm = sink_allm &&
+                       (vrr_params.state == VRR_STATE_ACTIVE_VARIABLE ||
+                        vrr_params.state == VRR_STATE_ACTIVE_FIXED);
+               bool allm_changed;
+
+               mod_build_hf_vsif_infopacket(new_stream, &vsp_infopacket, allm, 
allm);
+
+               allm_changed = memcmp(&new_stream->vsp_infopacket, 
&vsp_infopacket,
+                                     sizeof(vsp_infopacket)) != 0;
+               new_crtc_state->freesync_vrr_info_changed |= allm_changed;
+               new_stream->vsp_infopacket = vsp_infopacket;
+
+               if (allm_changed)
+                       drm_dbg_driver(adev_to_drm(adev),
+                                      "ALLM: flip on crtc=%u: sink_allm=%d 
vrr_state=%d -> ALLM_Mode=%d\n",
+                                   new_crtc_state->base.crtc->base.id,
+                                   sink_allm,
+                                   vrr_params.state, allm);
+       }
+
        if (new_crtc_state->freesync_vrr_info_changed)
                drm_dbg_kms(adev_to_drm(adev), "VRR packet update: crtc=%u 
enabled=%d state=%d",
                              new_crtc_state->base.crtc->base.id,
-- 
2.53.0

Reply via email to