Re: [PATCH 4/4] drm/amd/display: Add HDMI ALLM support

Harry Wentland <[email protected]> Fri, 31 Jul 2026 16:11:25 -0400
Newsgroups org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>

On 2026-07-30 13:17, 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:
> - Add an allm capability flag to struct dc_edid_caps and populate it in
>   dm_helpers_parse_edid_caps() from the HF-VSDB ALLM bit parsed by DRM
>   core (connector->display_info.hdmi.allm).
> - In create_stream_for_sink(), build the HF-VSIF with ALLM_Mode set when
>   the sink advertises ALLM 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]>
> ---
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 35 ++++++++++++++++++-
>  .../display/amdgpu_dm/amdgpu_dm_connector.c   | 18 ++++++++--
>  .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |  5 ++-
>  drivers/gpu/drm/amd/display/dc/dc_types.h     |  3 ++
>  4 files changed, 57 insertions(+), 4 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 223b562f7005..fc3005ecc681 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -3895,6 +3895,36 @@ static void 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.
> +	 */
> +	if (new_stream->signal == SIGNAL_TYPE_HDMI_TYPE_A ||
> +	    new_stream->signal == SIGNAL_TYPE_HDMI_FRL) {
> +		struct dc_info_packet vsp_infopacket = {0};
> +		bool allm = new_stream->sink->edid_caps.allm &&

We have an `aconn` in this function above, so we can simply get the allm
bit from the connector:

		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);

Then we don't need to add a new allm bool to edid_caps.

Harry

> +			(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,
> +				    new_stream->sink->edid_caps.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,
> @@ -4429,9 +4459,12 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *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 ebead39939a6..430f1628ced0 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
> @@ -1511,8 +1511,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 = sink->edid_caps.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",
> +			    sink->edid_caps.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_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> index 42f5673acb4d..e69ce0a1b4b4 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
> @@ -197,7 +197,10 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
>  				  edid_caps->display_name,
>  				  AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS);
>  
> -	edid_caps->edid_hdmi = connector->display_info.is_hdmi;
> +	if (connector->display_info.is_hdmi) {
> +		edid_caps->edid_hdmi = true;
> +		edid_caps->allm = connector->display_info.hdmi.allm;
> +	}
>  
>  	if (edid_caps->edid_hdmi) {
>  		populate_hdmi_info_from_connector(link->dc->config.enable_frl, &connector->display_info.hdmi, edid_caps);
> diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
> index 3edeb94fba23..ae409cc59ae4 100644
> --- a/drivers/gpu/drm/amd/display/dc/dc_types.h
> +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
> @@ -226,6 +226,9 @@ struct dc_edid_caps {
>  	/*HDMI 2.0 caps*/
>  	bool lte_340mcsc_scramble;
>  
> +	/* HDMI 2.1 caps */
> +	bool allm;
> +
>  	bool edid_hdmi;
>  	bool hdr_supported;
>  	bool rr_capable;