On 8/10/26 7:39 PM, Fangzhi Zuo wrote:
why:
HDMI 2.1 Auto Low-Latency Mode (ALLM) lets a Source request the Sink's
low-latency mode through the HF-VSIF. amdgpu never set ALLM_Mode in the
HF-VSIF, so ALLM was never signalled to the sink.
how:
- In create_stream_for_sink(), build the HF-VSIF with ALLM_Mode set when
the sink advertises ALLM (connector->display_info.hdmi.allm, parsed by
DRM core from the HF-VSDB) and the content type is Game (content-type =
Game is how userspace requests low-latency mode, HDMI GCTS HF1-56).
- In update_freesync_state_on_stream(), also set ALLM_Mode when
Gaming-VRR is active (VRR_EN=1, HDMI GCTS HF1-58 step 8.3.1), and push
the updated HF-VSIF (vsp_infopacket) as a stream update.
Signed-off-by: Fangzhi Zuo <[email protected]>
Reviewed-by: Harry Wentland <[email protected]>
---
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 ++-
.../display/amdgpu_dm/amdgpu_dm_connector.c | 18 +++++++++--
.../display/amdgpu_dm/amdgpu_dm_freesync.c | 31 +++++++++++++++++++
3 files changed, 51 insertions(+), 3 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 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_connector.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
index 2fe7bfb1e88f..953b2a470734 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
@@ -1572,8 +1572,22 @@ create_stream_for_sink(struct drm_connector *connector,
update_stream_signal(stream, sink);
if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A ||
- stream->signal == SIGNAL_TYPE_HDMI_FRL)
- mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket,
false, false);
+ stream->signal == SIGNAL_TYPE_HDMI_FRL) {
+ /*
+ * Enable HDMI ALLM (Auto Low-Latency Mode) when the sink
+ * advertises ALLM in the SCDS and the content type is Game.
+ * Setting content-type = Game is how userspace requests the
+ * Sink's low-latency mode (HDMI GCTS HF1-56).
+ */
+ bool allm = connector->display_info.hdmi.allm &&
+ stream->content_type == DISPLAY_CONTENT_TYPE_GAME;
+
+ drm_dbg_driver(dev,
+ "ALLM: set mode: sink_allm=%d content_type=%d ->
ALLM_Mode=%d\n",
+ connector->display_info.hdmi.allm,
stream->content_type, allm);
+
+ mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket,
allm, allm);
+ }
if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST ||
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..0fa72c77415e 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,37 @@ 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: transmit the HF-VSIF with ALLM_Mode=1 when the sink
+ * advertises ALLM in the SCDS and either the content type is Game
+ * (HF1-56) or Gaming-VRR is active (VRR_EN=1, HF1-58 step 8.3.1).
+ * HDMI 2.1 7.6.6.
+ */
Tying this to Gaming-VRR seems potentially surprising. Gaming-VRR
doesn't mean we're playing a game. We might be using it to play back
judder free video (where we'd like ALLM off to preserve the sink's image
enhancement), or we might be at the desktop.
I'd imagine some users would still want their sink to use all the image
enhancements they saw in the showroom even when playing a game, so I'm
not sure any kind of "auto" decision making in the kernel makes sense at
all, even based on content type. It's a very subjective trade-off.
To me, this seems like something a compositor would want control of with
a simple boolean property.
Thanks,
Derek
+ 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 &&
+ (new_stream->content_type == DISPLAY_CONTENT_TYPE_GAME
||
+ 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
content_type=%d vrr_state=%d -> ALLM_Mode=%d\n",
+ new_crtc_state->base.crtc->base.id,
+ sink_allm,
+ new_stream->content_type, 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,