* [PATCH v2 1/4] drm/amd/display: Add 2.1 FreeSync support for AMD VSDB EDID Block
2026-08-06 20:54 ` [PATCH v2 0/4] HDMI 2.1 VRR and ALLM support Fangzhi Zuo
@ 2026-08-06 20:54 ` Fangzhi Zuo
2026-08-06 21:13 ` sashiko-bot
2026-08-06 20:54 ` [PATCH v2 2/4] drm/edid: parse HDMI 2.1 gaming (ALLM/VRR) capabilities from HF-VSDB Fangzhi Zuo
` (3 subsequent siblings)
4 siblings, 1 reply; 43+ messages in thread
From: Fangzhi Zuo @ 2026-08-06 20:54 UTC (permalink / raw)
To: amd-gfx
Cc: dri-devel, Fangzhi Zuo, Harry Wentland, Leo Li, Rodrigo Siqueira,
Alex Deucher, Christian König, David Airlie, Simona Vetter,
open list
From: Fangzhi Zuo <Jerry.Zuo@amd.com>
why:
HDMI FRL sinks were not parsed for the AMD VSDB and no VTEM info packet
was emitted for them, so 2.1 FreeSync over HDMI FRL did not work. It is
backward-compatible with 2.0 FreeSync.
how:
- Accept SIGNAL_TYPE_HDMI_FRL alongside SIGNAL_TYPE_HDMI_TYPE_A when
parsing the AMD VSDB in amdgpu_dm_update_freesync_caps().
- Build and send the VTEM info packet via mod_build_infopacket_vtem()
when the stream signal is HDMI FRL during the freesync state update.
- Set the VTEM Data_Set_Length to 0 when no VTEM feature is enabled.
build_infopacket_header_vtem() hardcodes Data_Set_Length = 4, so a VTEM
with Data_Set_Length = 4 would be transmitted even when no VTEM feature
is enabled (VRR_EN = 0 and no FVA), e.g. when the sink advertises
VRRMIN = 0 and vrr_capable is false. This fails HDMI GCTS HF1-58 step
6.2.
The VTEM must keep being transmitted every MTW while VRR is enabled
(HF1-58 steps 8.1 and 8.3), so it cannot simply be suppressed per
frame. Instead, follow the MLDS option in HDMI 2.1 10.10.2.4: keep
transmitting the VTEM but set Data_Set_Length = 0 when no feature is
enabled. When VRR becomes active the full Data_Set_Length = 4 payload
with VRR_EN = 1 is sent as before.
Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com>
---
.../display/amdgpu_dm/amdgpu_dm_connector.c | 4 +-
.../display/amdgpu_dm/amdgpu_dm_freesync.c | 4 +
.../amd/display/modules/inc/mod_info_packet.h | 4 +
.../display/modules/info_packet/info_packet.c | 109 ++++++++++++++++++
4 files changed, 120 insertions(+), 1 deletion(-)
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 4304520d2484..5e7ab9158995 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
@@ -3838,7 +3838,9 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
amdgpu_dm_connector->as_type = ADAPTIVE_SYNC_TYPE_EDP;
}
- } else if (drm_edid && sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) {
+ } else if (drm_edid &&
+ (sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A ||
+ sink->sink_signal == SIGNAL_TYPE_HDMI_FRL)) {
i = parse_hdmi_amd_vsdb(amdgpu_dm_connector, edid, &vsdb_info);
if (i >= 0) {
amdgpu_dm_connector->vsdb_info = vsdb_info;
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 7e484adb4120..1fa078cdba52 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
@@ -37,6 +37,7 @@
#include "amdgpu_dm_freesync.h"
#include "dm_helpers.h"
#include "modules/inc/mod_freesync.h"
+#include "modules/inc/mod_info_packet.h"
bool amdgpu_dm_is_dc_timing_adjust_needed(struct dm_crtc_state *old_state,
struct dm_crtc_state *new_state)
@@ -229,6 +230,9 @@ void amdgpu_dm_update_freesync_state_on_stream(
&vrr_infopacket,
pack_sdp_v1_3);
+ if (new_stream->sink->sink_signal == SIGNAL_TYPE_HDMI_FRL)
+ mod_build_infopacket_vtem(new_stream, &vrr_params, 0, &vrr_infopacket);
+
new_crtc_state->freesync_vrr_info_changed |=
(memcmp(&new_crtc_state->vrr_infopacket,
&vrr_infopacket,
diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h
index eee8206bc531..5181d889fe7f 100644
--- a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h
+++ b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h
@@ -67,6 +67,10 @@ struct AS_Df_params {
struct frame_duration_op decrease;
};
+void mod_build_infopacket_vtem(const struct dc_stream_state *stream,
+ const struct mod_vrr_params *vrr, int fva_factor,
+ struct dc_info_packet *infopacket);
+
void mod_build_adaptive_sync_infopacket(const struct dc_stream_state *stream,
enum adaptive_sync_type asType, const struct AS_Df_params *param,
struct dc_info_packet *info_packet);
diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
index f5ac4bf32a78..e956c707ac50 100644
--- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
+++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
@@ -291,6 +291,21 @@ void set_vsc_packet_colorimetry_data(
info_packet->sb[18] = 0;
}
+static void setFieldWithMask(unsigned char *dest, unsigned int mask, unsigned int value)
+{
+ unsigned int shift = 0;
+
+ if (!mask || !dest)
+ return;
+
+ while (!((mask >> shift) & 1))
+ shift++;
+
+ *dest = *dest & ~mask;
+ value = value & (mask >> shift);
+ *dest = *dest | (value << shift);
+}
+
void mod_build_vsc_infopacket(const struct dc_stream_state *stream,
struct dc_info_packet *info_packet,
enum dc_color_space cs,
@@ -644,6 +659,100 @@ void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream,
info_packet->valid = true;
}
+static void build_vtem_infopacket_data(const struct dc_stream_state *stream,
+ const struct mod_vrr_params *vrr, int fva_factor,
+ struct dc_info_packet *infopacket)
+{
+ unsigned int fieldRateInHz;
+
+ /* FVA Factor setting */
+ setFieldWithMask(&infopacket->sb[VTEM_MD0], MASK_VTEM_MD0__FVA_FACTOR_M1,
+ (fva_factor > 0)?(fva_factor-1):0);
+ /* VRR Parameters */
+ if (vrr->state == VRR_STATE_ACTIVE_VARIABLE ||
+ vrr->state == VRR_STATE_ACTIVE_FIXED) {
+ setFieldWithMask(&infopacket->sb[VTEM_MD0], MASK_VTEM_MD0__VRR_EN, 1);
+ } else {
+ setFieldWithMask(&infopacket->sb[VTEM_MD0], MASK_VTEM_MD0__VRR_EN, 0);
+ }
+
+ if (vrr->state == VRR_STATE_ACTIVE_FIXED)
+ setFieldWithMask(&infopacket->sb[VTEM_MD0], MASK_VTEM_MD0__M_CONST, vrr->m_const);
+
+ if (!stream->timing.vic) {
+ setFieldWithMask(&infopacket->sb[VTEM_MD1], MASK_VTEM_MD1__BASE_VFRONT,
+ stream->timing.v_front_porch);
+
+
+ /* TODO: In dal2, we check mode flags for a reduced blanking timing.
+ * Need a way to relay that information to this function.
+ * if("ReducedBlanking")
+ * {
+ * setFieldWithMask(&infopacket->sb[VRR_VTEM_MD2], MASK__VRR_VTEM_MD2__RB, 1;
+ * }
+ */
+
+ fieldRateInHz = stream->timing.pix_clk_100hz * 100;
+ fieldRateInHz /= stream->timing.h_total;
+ fieldRateInHz = (fieldRateInHz + stream->timing.v_total / 2)
+ / stream->timing.v_total;
+
+ setFieldWithMask(&infopacket->sb[VTEM_MD2], MASK_VTEM_MD2__BASE_REFRESH_RATE_98,
+ fieldRateInHz >> 8);
+ setFieldWithMask(&infopacket->sb[VTEM_MD3], MASK_VTEM_MD3__BASE_REFRESH_RATE_07,
+ fieldRateInHz);
+
+ }
+
+ /*
+ * When no VTEM feature is enabled (neither VRR nor FVA), signal a
+ * zero-length data set (MLDS) by clearing Data_Set_Length. HDMI 2.1
+ * 10.10.2.4 requires the Source to either stop transmitting the VTEM
+ * or set Data_Set_Length = 0 when no feature is enabled; keeping the
+ * VTEM with Data_Set_Length = 0 preserves the every-MTW cadence while
+ * staying compliant (e.g. HDMI GCTS HF1-58 step 6.2).
+ */
+ if (vrr->state != VRR_STATE_ACTIVE_VARIABLE &&
+ vrr->state != VRR_STATE_ACTIVE_FIXED && fva_factor == 0)
+ setFieldWithMask(&infopacket->sb[VTEM_PB6],
+ MASK_VTEM_PB6__DATA_SET_LENGTH_LSB, 0);
+
+ infopacket->valid = true;
+}
+
+static void build_infopacket_header_vtem(enum signal_type signal,
+ struct dc_info_packet *infopacket)
+{
+ // HEADER
+
+ // HB0, HB1, HB2 indicates PacketType VTEMPacket
+ infopacket->hb0 = 0x7F;
+ infopacket->hb1 = 0xC0;
+ infopacket->hb2 = 0x00; //sequence_index
+
+ setFieldWithMask(&infopacket->sb[VTEM_PB0], MASK_VTEM_PB0__VFR, 1);
+ setFieldWithMask(&infopacket->sb[VTEM_PB2], MASK_VTEM_PB2__ORGANIZATION_ID, 1);
+ setFieldWithMask(&infopacket->sb[VTEM_PB3], MASK_VTEM_PB3__DATA_SET_TAG_MSB, 0);
+ setFieldWithMask(&infopacket->sb[VTEM_PB4], MASK_VTEM_PB4__DATA_SET_TAG_LSB, 1);
+ setFieldWithMask(&infopacket->sb[VTEM_PB5], MASK_VTEM_PB5__DATA_SET_LENGTH_MSB, 0);
+ setFieldWithMask(&infopacket->sb[VTEM_PB6], MASK_VTEM_PB6__DATA_SET_LENGTH_LSB, 4);
+}
+
+void mod_build_infopacket_vtem(const struct dc_stream_state *stream,
+ const struct mod_vrr_params *vrr, int fva_factor,
+ struct dc_info_packet *infopacket)
+{
+ //VTEM info packet for HdmiVrr
+
+ memset(infopacket, 0, sizeof(struct dc_info_packet));
+
+ //VTEM Packet is structured differently
+ build_infopacket_header_vtem(stream->signal, infopacket);
+ build_vtem_infopacket_data(stream, vrr, fva_factor, infopacket);
+
+ infopacket->valid = true;
+}
+
void mod_build_adaptive_sync_infopacket(const struct dc_stream_state *stream,
enum adaptive_sync_type asType,
const struct AS_Df_params *param,
--
2.53.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* Re: [PATCH v2 1/4] drm/amd/display: Add 2.1 FreeSync support for AMD VSDB EDID Block
2026-08-06 20:54 ` [PATCH v2 1/4] drm/amd/display: Add 2.1 FreeSync support for AMD VSDB EDID Block Fangzhi Zuo
@ 2026-08-06 21:13 ` sashiko-bot
0 siblings, 0 replies; 43+ messages in thread
From: sashiko-bot @ 2026-08-06 21:13 UTC (permalink / raw)
To: Fangzhi Zuo; +Cc: dri-devel
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [High] Dereferencing deprecated `new_stream->sink` pointer risks a NULL pointer dereference.
- [High] VTEM packet overwrites the FreeSync SPD infopacket and is misrouted to the hardware's SPD slot.
- [Medium] Unconditional VTEM transmission to all HDMI FRL displays, including non-VRR sinks.
- [Medium] 32-bit integer overflow when calculating `fieldRateInHz` for VTEM packets in ultra-high bandwidth modes.
- [Low] Unused parameter `signal` in `build_infopacket_header_vtem()`.
--
--- Patch [1]: [PATCH v2 1/4] drm/amd/display: Add 2.1 FreeSync support for AMD VSDB EDID Block ---
commit b0ebd1a49b36a5e82edcd0396a4c4d22fe23f9d3
Author: Fangzhi Zuo <Jerry.Zuo@amd.com>
drm/amd/display: Add 2.1 FreeSync support for AMD VSDB EDID Block
This commit adds 2.1 FreeSync support for AMD VSDB EDID block over HDMI FRL.
It updates the capability parsing to accept HDMI FRL signals and builds the
required VTEM info packet. The VTEM data set length is dynamically set to 0
when no VTEM feature is enabled to comply with HDMI GCTS.
> 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 7e484adb4120f..1fa078cdba527 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
> @@ -229,6 +230,9 @@ void amdgpu_dm_update_freesync_state_on_stream(
> &vrr_infopacket,
> pack_sdp_v1_3);
>
> + if (new_stream->sink->sink_signal == SIGNAL_TYPE_HDMI_FRL)
^^^^^^^^^^^^^^^^
[Severity: High]
Can this dereference a NULL pointer? The sink pointer inside
dc_stream_state is officially deprecated and could be NULL in headless or
writeback scenarios. Would it be safer to use new_stream->signal here?
[Severity: Medium]
Will this transmit VTEM packets even to sinks that do not support VRR or FVA?
There doesn't appear to be a check for vrr_params.send_info_frame, which
could result in unconditional VTEM transmission to all HDMI FRL displays,
potentially violating the HDMI 2.1 specifications.
> + mod_build_infopacket_vtem(new_stream, &vrr_params, 0, &vrr_infopacket);
^^^^^^^^^^^^^^^
[Severity: High]
Does this overwrite the previously built AMD Vendor Specific InfoFrame
(VSIF)? By passing &vrr_infopacket, the newly created VTEM packet is stored
in the same local variable.
Additionally, since dc_resource.c writes stream->vrr_infopacket exclusively
to the hardware's SPD slot, will this cause the VTEM packet to be incorrectly
transmitted through the SPD slot instead of the VTEM slot?
> +
> new_crtc_state->freesync_vrr_info_changed |=
> (memcmp(&new_crtc_state->vrr_infopacket,
> &vrr_infopacket,
> diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
> index f5ac4bf32a784..e956c707ac507 100644
> --- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
> +++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
[ ... ]
> @@ -644,6 +659,100 @@ void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream,
> info_packet->valid = true;
> }
>
> +static void build_vtem_infopacket_data(const struct dc_stream_state *stream,
> + const struct mod_vrr_params *vrr, int fva_factor,
> + struct dc_info_packet *infopacket)
> +{
> + unsigned int fieldRateInHz;
> +
> + /* FVA Factor setting */
> + setFieldWithMask(&infopacket->sb[VTEM_MD0], MASK_VTEM_MD0__FVA_FACTOR_M1,
> + (fva_factor > 0)?(fva_factor-1):0);
[ ... ]
> + fieldRateInHz = stream->timing.pix_clk_100hz * 100;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[Severity: Medium]
Can this multiplication overflow for ultra-high bandwidth modes? For displays
like 8K@120Hz, stream->timing.pix_clk_100hz * 100 could exceed the 32-bit
unsigned integer limit before the subsequent division. Should this be cast
to a 64-bit integer?
> + fieldRateInHz /= stream->timing.h_total;
> + fieldRateInHz = (fieldRateInHz + stream->timing.v_total / 2)
> + / stream->timing.v_total;
> +
> + }
> +
[ ... ]
> +static void build_infopacket_header_vtem(enum signal_type signal,
^^^^^^^^^^^^^^^^^^^^^^^
[Severity: Low]
Is the signal parameter needed here? It doesn't appear to be evaluated or
used anywhere within the body of this function.
> + struct dc_info_packet *infopacket)
> +{
> + // HEADER
> +
> + // HB0, HB1, HB2 indicates PacketType VTEMPacket
> + infopacket->hb0 = 0x7F;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260806205449.16806-1-jerry.zuo@amd.com?part=1
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH v2 2/4] drm/edid: parse HDMI 2.1 gaming (ALLM/VRR) capabilities from HF-VSDB
2026-08-06 20:54 ` [PATCH v2 0/4] HDMI 2.1 VRR and ALLM support Fangzhi Zuo
2026-08-06 20:54 ` [PATCH v2 1/4] drm/amd/display: Add 2.1 FreeSync support for AMD VSDB EDID Block Fangzhi Zuo
@ 2026-08-06 20:54 ` Fangzhi Zuo
2026-08-06 20:54 ` [PATCH v2 3/4] drm/amd/display: Add HDMI 2.1 VRR support " Fangzhi Zuo
` (2 subsequent siblings)
4 siblings, 0 replies; 43+ messages in thread
From: Fangzhi Zuo @ 2026-08-06 20:54 UTC (permalink / raw)
To: amd-gfx
Cc: dri-devel, Tomasz Pakuła, Fangzhi Zuo, Bernhard Berger,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, open list
From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
Parse the HDMI 2.1 gaming-related capabilities advertised in the HDMI
Forum VSDB (HF-VSDB) and expose them through struct drm_hdmi_info so
drivers can consume them.
Add struct drm_hdmi_vrr_cap describing the sink's VRR capabilities: Fast
VActive (Quick Frame Transport), Negative M VRR, Cinema VRR, MDelta, and
the VRRmin/VRRmax range, together with a "supported" flag derived from
that range. Add the fapa_start_location and allm (Auto Low Latency Mode)
flags to struct drm_hdmi_info.
drm_parse_hdmi_gaming_info() reads byte 8 of the HF-VSDB for the
FAPA/ALLM/FVA/CNMVRR/CinemaVRR/MDelta flags and bytes 9-10 for
VRRmin/VRRmax. Per HDMI 2.1, VRR is considered supported when VRRmin is
within 1-48 and VRRmax is either 0 (maximum based on the video mode) or
>= 100. It is invoked from drm_parse_hdmi_forum_scds(), and the parsed
values are logged for debugging.
Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com>
Tested-by: Bernhard Berger <bernhard.berger@gmail.com>
---
drivers/gpu/drm/drm_edid.c | 42 +++++++++++++++++++++++++++++++++
include/drm/drm_connector.h | 47 +++++++++++++++++++++++++++++++++++++
2 files changed, 89 insertions(+)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index ae26618a9a57..d508ec633c9b 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -6182,6 +6182,33 @@ static void drm_parse_ycbcr420_deep_color_info(struct drm_connector *connector,
hdmi->y420_dc_modes = dc_mask;
}
+static void drm_parse_hdmi_gaming_info(struct drm_hdmi_info *hdmi, const u8 *db)
+{
+ struct drm_hdmi_vrr_cap *vrr = &hdmi->vrr_cap;
+
+ if (cea_db_payload_len(db) < 8)
+ return;
+
+ hdmi->fapa_start_location = db[8] & DRM_EDID_FAPA_START_LOCATION;
+ hdmi->allm = db[8] & DRM_EDID_ALLM;
+ vrr->fva = db[8] & DRM_EDID_FVA;
+ vrr->cnmvrr = db[8] & DRM_EDID_CNMVRR;
+ vrr->cinema_vrr = db[8] & DRM_EDID_CINEMA_VRR;
+ vrr->mdelta = db[8] & DRM_EDID_MDELTA;
+
+ if (cea_db_payload_len(db) < 9)
+ return;
+
+ vrr->vrr_min = db[9] & DRM_EDID_VRR_MIN_MASK;
+ vrr->supported = (vrr->vrr_min > 0 && vrr->vrr_min <= 48);
+
+ if (cea_db_payload_len(db) < 10)
+ return;
+
+ vrr->vrr_max = (db[9] & DRM_EDID_VRR_MAX_UPPER_MASK) << 2 | db[10];
+ vrr->supported &= (vrr->vrr_max == 0 || vrr->vrr_max >= 100);
+}
+
static void drm_parse_dsc_info(struct drm_hdmi_dsc_cap *hdmi_dsc,
const u8 *hf_scds)
{
@@ -6308,6 +6335,8 @@ static void drm_parse_hdmi_forum_scds(struct drm_connector *connector,
drm_parse_ycbcr420_deep_color_info(connector, hf_scds);
+ drm_parse_hdmi_gaming_info(&connector->display_info.hdmi, hf_scds);
+
if (cea_db_payload_len(hf_scds) >= 11 && hf_scds[11]) {
drm_parse_dsc_info(hdmi_dsc, hf_scds);
dsc_support = true;
@@ -6317,6 +6346,19 @@ static void drm_parse_hdmi_forum_scds(struct drm_connector *connector,
"[CONNECTOR:%d:%s] HF-VSDB: max TMDS clock: %d KHz, HDMI 2.1 support: %s, DSC 1.2 support: %s\n",
connector->base.id, connector->name,
max_tmds_clock, str_yes_no(max_frl_rate), str_yes_no(dsc_support));
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] FAPA in blanking: %s, ALLM support: %s, Fast Vactive support: %s\n",
+ connector->base.id, connector->name, str_yes_no(hdmi->fapa_start_location),
+ str_yes_no(hdmi->allm), str_yes_no(hdmi->vrr_cap.fva));
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] Negative M VRR support: %s, CinemaVRR support: %s, Mdelta: %d\n",
+ connector->base.id, connector->name, str_yes_no(hdmi->vrr_cap.cnmvrr),
+ str_yes_no(hdmi->vrr_cap.cinema_vrr), hdmi->vrr_cap.mdelta);
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] VRRmin: %u, VRRmax: %u, VRR supported: %s\n",
+ connector->base.id, connector->name, hdmi->vrr_cap.vrr_min,
+ hdmi->vrr_cap.vrr_max, str_yes_no(hdmi->vrr_cap.supported));
+
}
static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector,
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index cd06a3b914a0..9f8f109c2dd1 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -254,6 +254,44 @@ struct drm_scdc {
struct drm_scrambling scrambling;
};
+/**
+ * struct drm_hdmi_vrr_cap - Information about VRR capabilities of a HDMI sink
+ *
+ * Describes the VRR support provided by HDMI 2.1 sink. The information is
+ * fetched fom additional HFVSDB blocks defined for HDMI 2.1.
+ */
+struct drm_hdmi_vrr_cap {
+ /** @fva: flag for Fast VActive (Quick Frame Transport) support */
+ bool fva;
+
+ /** @mcnmvrr: flag for Negative M VRR support */
+ bool cnmvrr;
+
+ /** @mcinema_vrr: flag for Cinema VRR support */
+ bool cinema_vrr;
+
+ /** @mdelta: flag for limited frame-to-frame compensation support */
+ bool mdelta;
+
+ /**
+ * @vrr_min : minimum supported variable refresh rate in Hz.
+ * Valid values only inide 1 - 48 range
+ */
+ u16 vrr_min;
+
+ /**
+ * @vrr_max : maximum supported variable refresh rate in Hz (optional).
+ * Valid values are either 0 (max based on video mode) or >= 100
+ */
+ u16 vrr_max;
+
+ /**
+ * @supported: flag for vrr support based on checking for VRRmin and
+ * VRRmax values having correct values.
+ */
+ bool supported;
+};
+
/**
* struct drm_hdmi_dsc_cap - DSC capabilities of HDMI sink
*
@@ -330,6 +368,15 @@ struct drm_hdmi_info {
/** @max_lanes: supported by sink */
u8 max_lanes;
+ /** @fapa_start_location: flag for the FAPA in blanking support */
+ bool fapa_start_location;
+
+ /** @allm: flag for Auto Low Latency Mode support by sink */
+ bool allm;
+
+ /** @vrr_cap: VRR capabilities of the sink */
+ struct drm_hdmi_vrr_cap vrr_cap;
+
/** @dsc_cap: DSC capabilities of the sink */
struct drm_hdmi_dsc_cap dsc_cap;
};
--
2.53.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH v2 3/4] drm/amd/display: Add HDMI 2.1 VRR support from HF-VSDB
2026-08-06 20:54 ` [PATCH v2 0/4] HDMI 2.1 VRR and ALLM support Fangzhi Zuo
2026-08-06 20:54 ` [PATCH v2 1/4] drm/amd/display: Add 2.1 FreeSync support for AMD VSDB EDID Block Fangzhi Zuo
2026-08-06 20:54 ` [PATCH v2 2/4] drm/edid: parse HDMI 2.1 gaming (ALLM/VRR) capabilities from HF-VSDB Fangzhi Zuo
@ 2026-08-06 20:54 ` Fangzhi Zuo
2026-08-06 21:07 ` sashiko-bot
2026-08-06 20:54 ` [PATCH v2 4/4] drm/amd/display: Add HDMI ALLM support Fangzhi Zuo
2026-08-11 0:39 ` [PATCH v3 0/4] HDMI 2.1 VRR and " Fangzhi Zuo
4 siblings, 1 reply; 43+ messages in thread
From: Fangzhi Zuo @ 2026-08-06 20:54 UTC (permalink / raw)
To: amd-gfx
Cc: dri-devel, Fangzhi Zuo, Fangzhi Zuo, Harry Wentland, Leo Li,
Rodrigo Siqueira, Alex Deucher, Christian König,
David Airlie, Simona Vetter, open list
why:
HDMI 2.1 sinks advertise their VRR range in the HDMI Forum VSDB
(HF-VSDB), but amdgpu derived FreeSync capability only from the AMD
VSDB. Sinks that expose just the HDMI Forum VRR capability (e.g. HDMI
compliance EDIDs) were therefore reported as not VRR capable.
how:
- In amdgpu_dm_update_freesync_caps(), when the AMD VSDB does not
provide a valid FreeSync range, fall back to the HDMI 2.1 VRR range
parsed by DRM core from the HF-VSDB
(connector->display_info.hdmi.vrr_cap). VRRMAX = 0 means "up to the
Base Refresh Rate"; when the EDID provides no monitor range maximum
either, fall back to the Base Refresh Rate (the highest refresh-rate
mode of the preferred timing) so a valid VRR range is still reported
to userspace.
- Add VRR debug logging along the FreeSync capability and config paths.
Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com>
---
.../display/amdgpu_dm/amdgpu_dm_connector.c | 67 +++++++++++++++++++
.../display/amdgpu_dm/amdgpu_dm_freesync.c | 8 +++
2 files changed, 75 insertions(+)
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 5e7ab9158995..df39bc70ec6c 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
@@ -3812,6 +3812,15 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
if (!adev->dm.freesync_module || !dc_supports_vrr(sink->ctx->dce_version))
goto update;
+ drm_dbg_driver(adev_to_drm(adev),
+ "VRR: enter signal=%d hdmi_vrr=%d mrange[%d-%d] hdmi.vrr_cap[sup=%d min=%d max=%d]\n",
+ sink->sink_signal, connector->display_info.hdmi.vrr_cap.supported,
+ connector->display_info.monitor_range.min_vfreq,
+ connector->display_info.monitor_range.max_vfreq,
+ connector->display_info.hdmi.vrr_cap.supported,
+ connector->display_info.hdmi.vrr_cap.vrr_min,
+ connector->display_info.hdmi.vrr_cap.vrr_max);
+
/* FIXME: Get rid of drm_edid_raw() */
edid = drm_edid_raw(drm_edid);
@@ -3856,6 +3865,59 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
connector->display_info.monitor_range.max_vfreq = vsdb_info.max_refresh_rate_hz;
}
}
+
+ drm_dbg_driver(adev_to_drm(adev),
+ "VRR: amd_vsdb i=%d fs_sup=%d min=%d max=%d fs_capable=%d\n",
+ i, vsdb_info.freesync_supported,
+ vsdb_info.min_refresh_rate_hz,
+ vsdb_info.max_refresh_rate_hz, freesync_capable);
+
+ /*
+ * If AMD VSDB didn't provide a valid FreeSync range, fall back to
+ * the HDMI 2.1 VRR capability parsed from the HF-VSDB.
+ */
+ if (!freesync_capable && connector->display_info.hdmi.vrr_cap.supported) {
+ struct drm_hdmi_vrr_cap *vrr_cap =
+ &connector->display_info.hdmi.vrr_cap;
+
+ drm_dbg_driver(adev_to_drm(adev),
+ "VRR: HF-VSDB fallback: hdmi_vrr=1 vrr_cap[sup=%d min=%d max=%d] mrange_max=%d\n",
+ vrr_cap->supported, vrr_cap->vrr_min, vrr_cap->vrr_max,
+ connector->display_info.monitor_range.max_vfreq);
+
+ if (vrr_cap->supported && vrr_cap->vrr_min > 0) {
+ amdgpu_dm_connector->min_vfreq = vrr_cap->vrr_min;
+ amdgpu_dm_connector->max_vfreq = vrr_cap->vrr_max ?
+ vrr_cap->vrr_max :
+ connector->display_info.monitor_range.max_vfreq;
+
+ /*
+ * VRRMAX = 0 in the HF-VSDB means "up to the Base
+ * Refresh Rate". If the EDID also did not provide a
+ * monitor range max, fall back to the Base Refresh
+ * Rate (the highest refresh rate of the preferred
+ * timing) so a valid VRR range is still reported to
+ * userspace.
+ */
+ if (!amdgpu_dm_connector->max_vfreq) {
+ struct drm_display_mode *brr_mode =
+ amdgpu_dm_get_highest_refresh_rate_mode(amdgpu_dm_connector, true);
+
+ if (brr_mode)
+ amdgpu_dm_connector->max_vfreq =
+ drm_mode_vrefresh(brr_mode);
+ }
+
+ if (amdgpu_dm_connector->max_vfreq -
+ amdgpu_dm_connector->min_vfreq > 10)
+ freesync_capable = true;
+
+ connector->display_info.monitor_range.min_vfreq =
+ amdgpu_dm_connector->min_vfreq;
+ connector->display_info.monitor_range.max_vfreq =
+ amdgpu_dm_connector->max_vfreq;
+ }
+ }
}
if (amdgpu_dm_connector->dc_link)
@@ -3899,6 +3961,11 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
if (dm_con_state)
dm_con_state->freesync_capable = freesync_capable;
+ drm_dbg_driver(adev_to_drm(adev),
+ "VRR: caps result: freesync_capable=%d min_vfreq=%d max_vfreq=%d\n",
+ freesync_capable, amdgpu_dm_connector->min_vfreq,
+ amdgpu_dm_connector->max_vfreq);
+
if (connector->state && amdgpu_dm_connector->dc_link && !freesync_capable &&
amdgpu_dm_connector->dc_link->replay_settings.config.replay_supported) {
amdgpu_dm_connector->dc_link->replay_settings.config.replay_supported = false;
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 1fa078cdba52..cb49184813de 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
@@ -152,6 +152,14 @@ void amdgpu_dm_get_freesync_config_for_crtc(
}
out:
new_crtc_state->freesync_config = config;
+
+ drm_dbg_driver(new_con_state->base.connector->dev,
+ "VRR: cfg vrr_enabled=%d vrr_supported=%d fs_capable=%d vrefresh=%d min=%d max=%d state=%d\n",
+ new_crtc_state->base.vrr_enabled,
+ new_crtc_state->vrr_supported,
+ new_con_state->freesync_capable, vrefresh,
+ aconnector->min_vfreq, aconnector->max_vfreq,
+ config.state);
}
EXPORT_IF_KUNIT(amdgpu_dm_get_freesync_config_for_crtc);
--
2.53.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* Re: [PATCH v2 3/4] drm/amd/display: Add HDMI 2.1 VRR support from HF-VSDB
2026-08-06 20:54 ` [PATCH v2 3/4] drm/amd/display: Add HDMI 2.1 VRR support " Fangzhi Zuo
@ 2026-08-06 21:07 ` sashiko-bot
0 siblings, 0 replies; 43+ messages in thread
From: sashiko-bot @ 2026-08-06 21:07 UTC (permalink / raw)
To: Fangzhi Zuo; +Cc: dri-devel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The HF-VSDB VRR fallback is unconditionally overwritten to false for HDMI TMDS sinks because they lack an AMD FreeSync VCP code.
--
--- Patch [3]: [PATCH v2 3/4] drm/amd/display: Add HDMI 2.1 VRR support from HF-VSDB ---
commit 3db5053c0ea2b238965bfd80def111ee342642b8
Author: Fangzhi Zuo <jerry.zuo@amd.com>
drm/amd/display: Add HDMI 2.1 VRR support from HF-VSDB
This commit adds support for HDMI 2.1 VRR capabilities derived from the
HDMI Forum VSDB (HF-VSDB) as a fallback. It parses the VRR ranges and sets
the FreeSync capability appropriately when an AMD VSDB is missing or invalid.
> 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
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
[ ... ]
> @@ -3856,6 +3865,59 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
[ ... ]
> + /*
> + * If AMD VSDB didn't provide a valid FreeSync range, fall back to
> + * the HDMI 2.1 VRR capability parsed from the HF-VSDB.
> + */
> + if (!freesync_capable && connector->display_info.hdmi.vrr_cap.supported) {
[ ... ]
> + if (amdgpu_dm_connector->max_vfreq -
> + amdgpu_dm_connector->min_vfreq > 10)
> + freesync_capable = true;
[Severity: Medium]
Will this newly enabled HF-VSDB fallback be unconditionally overwritten to
false for HDMI TMDS sinks?
For a monitor advertising VRR only via HF-VSDB on an HDMI TMDS link, the
AMD VSDB parsing fails, leaving sink->edid_caps.freesync_vcp_code as 0.
While this new fallback block correctly sets freesync_capable to true, later
in amdgpu_dm_update_freesync_caps(), there is an existing check:
if ((sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A ||
as_type == FREESYNC_TYPE_PCON_IN_WHITELIST) &&
(!sink->edid_caps.freesync_vcp_code ||
(sink->edid_caps.freesync_vcp_code && !sink->mccs_caps.freesync_supported)))
freesync_capable = false;
Since sink_signal == SIGNAL_TYPE_HDMI_TYPE_A and freesync_vcp_code is 0,
does this existing logic silently disable the fallback feature being
introduced here?
> +
> + connector->display_info.monitor_range.min_vfreq =
> + amdgpu_dm_connector->min_vfreq;
> + connector->display_info.monitor_range.max_vfreq =
> + amdgpu_dm_connector->max_vfreq;
> + }
> + }
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260806205449.16806-1-jerry.zuo@amd.com?part=3
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH v2 4/4] drm/amd/display: Add HDMI ALLM support
2026-08-06 20:54 ` [PATCH v2 0/4] HDMI 2.1 VRR and ALLM support Fangzhi Zuo
` (2 preceding siblings ...)
2026-08-06 20:54 ` [PATCH v2 3/4] drm/amd/display: Add HDMI 2.1 VRR support " Fangzhi Zuo
@ 2026-08-06 20:54 ` Fangzhi Zuo
2026-08-06 21:08 ` sashiko-bot
2026-08-10 21:04 ` Harry Wentland
2026-08-11 0:39 ` [PATCH v3 0/4] HDMI 2.1 VRR and " Fangzhi Zuo
4 siblings, 2 replies; 43+ messages in thread
From: Fangzhi Zuo @ 2026-08-06 20:54 UTC (permalink / raw)
To: amd-gfx
Cc: dri-devel, Fangzhi Zuo, Fangzhi Zuo, Harry Wentland, Leo Li,
Rodrigo Siqueira, Alex Deucher, Christian König,
David Airlie, Simona Vetter, open list
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 <Jerry.Zuo@amd.com>
---
.../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 df39bc70ec6c..6cfd7526ab56 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 cb49184813de..c4bc6e717df9 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.
+ */
+ 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,
--
2.53.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* Re: [PATCH v2 4/4] drm/amd/display: Add HDMI ALLM support
2026-08-06 20:54 ` [PATCH v2 4/4] drm/amd/display: Add HDMI ALLM support Fangzhi Zuo
@ 2026-08-06 21:08 ` sashiko-bot
2026-08-10 21:04 ` Harry Wentland
1 sibling, 0 replies; 43+ messages in thread
From: sashiko-bot @ 2026-08-06 21:08 UTC (permalink / raw)
To: Fangzhi Zuo; +Cc: dri-devel
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
New issues:
- [High] Enabling ALLM replaces the HDMI 1.4 VSIF with the HF-VSIF, dropping `hdmi_vic` signaling required for legacy 4K formats.
Pre-existing issues:
- [High] HDMI VRR (VTEM) is artificially restricted to FRL links, breaking HDMI VRR over TMDS.
--
--- Patch [4]: [PATCH v2 4/4] drm/amd/display: Add HDMI ALLM support ---
commit 4ebe402fb25e863740386dee88638b0ecc01f7ba
Author: Fangzhi Zuo <jerry.zuo@amd.com>
drm/amd/display: Add HDMI ALLM support
This commit adds HDMI 2.1 Auto Low-Latency Mode (ALLM) support by setting
ALLM_Mode in the HF-VSIF. It builds the HF-VSIF when the sink advertises ALLM
and the content type is Game or Gaming-VRR is active.
[ ... ]
> 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 df39bc70ec6c3..6cfd7526ab56a 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);
[Severity: High]
Does enabling ALLM replace the HDMI 1.4 VSIF with the HF-VSIF, dropping
hdmi_vic signaling for legacy 4K formats?
When ALLM is requested, calling mod_build_hf_vsif_infopacket() with allm=true
overrides the VSIF payload in vsp_infopacket.
Looking at the implementation in info_packet.c:mod_build_hf_vsif_infopacket():
if (!bALLM) {
info_packet->sb[1] = 0x03;
...
} else {
info_packet->sb[1] = 0xD8;
...
This acts as a mutually exclusive switch rather than populating two separate
info frames. If a user selects a display mode requiring hdmi_vic and sets the
content type to Game, will this cause the display to lose format signaling and
result in a black screen or corrupted display?
[ ... ]
> 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 cb49184813dee..c4bc6e717df93 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;
[Severity: High]
This is a pre-existing issue, but does restricting VTEM generation strictly to
FRL links break HDMI VRR on HDMI 2.0 displays?
HDMI 2.1 VRR requires the VTEM packet to operate. Looking earlier in
amdgpu_dm_update_freesync_state_on_stream():
if (new_stream->sink->sink_signal == SIGNAL_TYPE_HDMI_FRL)
mod_build_infopacket_vtem(new_stream, &vrr_params, 0, &vrr_infopacket);
By checking for SIGNAL_TYPE_HDMI_FRL, it appears the driver will silently
skip VTEM generation for TMDS-only sinks that support VRR (via firmware
updates or HDMI 2.1 features on TMDS), causing VRR to fail to engage.
> 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 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;
[Severity: High]
As noted above in create_stream_for_sink(), does unconditionally replacing
vsp_infopacket with the HF-VSIF here cause the display to lose hdmi_vic
signaling when Gaming-VRR is active?
> +
> + 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);
> + }
> +
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260806205449.16806-1-jerry.zuo@amd.com?part=4
^ permalink raw reply [flat|nested] 43+ messages in thread* Re: [PATCH v2 4/4] drm/amd/display: Add HDMI ALLM support
2026-08-06 20:54 ` [PATCH v2 4/4] drm/amd/display: Add HDMI ALLM support Fangzhi Zuo
2026-08-06 21:08 ` sashiko-bot
@ 2026-08-10 21:04 ` Harry Wentland
1 sibling, 0 replies; 43+ messages in thread
From: Harry Wentland @ 2026-08-10 21:04 UTC (permalink / raw)
To: Fangzhi Zuo, amd-gfx
Cc: dri-devel, Leo Li, Rodrigo Siqueira, Alex Deucher,
Christian König, David Airlie, Simona Vetter, open list
On 2026-08-06 16:54, 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 <Jerry.Zuo@amd.com>
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Harry
> ---
> .../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 df39bc70ec6c..6cfd7526ab56 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 cb49184813de..c4bc6e717df9 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.
> + */
> + 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,
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH v3 0/4] HDMI 2.1 VRR and ALLM support
2026-08-06 20:54 ` [PATCH v2 0/4] HDMI 2.1 VRR and ALLM support Fangzhi Zuo
` (3 preceding siblings ...)
2026-08-06 20:54 ` [PATCH v2 4/4] drm/amd/display: Add HDMI ALLM support Fangzhi Zuo
@ 2026-08-11 0:39 ` Fangzhi Zuo
2026-08-11 0:39 ` [PATCH v3 1/4] drm/amd/display: Add 2.1 FreeSync support for AMD VSDB EDID Block Fangzhi Zuo
` (4 more replies)
4 siblings, 5 replies; 43+ messages in thread
From: Fangzhi Zuo @ 2026-08-11 0:39 UTC (permalink / raw)
To: amd-gfx; +Cc: dri-devel, Harry Wentland, Tomasz Pakuła, Fangzhi Zuo
This series adds HDMI 2.1 gaming support to amdgpu: Variable Refresh Rate
(VRR) derived from the HDMI Forum VSDB (HF-VSDB), and Auto Low-Latency
Mode (ALLM). It builds on a drm/edid patch that parses the HF-VSDB gaming
capabilities into struct drm_hdmi_info.
- Patch 1 reports FreeSync from the AMD VSDB (existing mechanism).
- Patch 2 (drm/edid) parses the HF-VSDB VRR range and ALLM bit.
- Patch 3 enables VRR from the HF-VSDB when the AMD VSDB has no range.
- Patch 4 signals ALLM_Mode in the HF-VSIF for Game content / active VRR.
v1: https://lore.kernel.org/amd-gfx/20260730171754.704049-1-jerry.zuo@amd.com/
v2: https://lore.kernel.org/amd-gfx/20260806205449.16806-1-jerry.zuo@amd.com/
Changes since v2:
- Fix coding-style issues in the VTEM info-packet code.
Fangzhi Zuo (3):
drm/amd/display: Add 2.1 FreeSync support for AMD VSDB EDID Block
drm/amd/display: Add HDMI 2.1 VRR support from HF-VSDB
drm/amd/display: Add HDMI ALLM support
Tomasz Pakuła (1):
drm/edid: parse HDMI 2.1 gaming (ALLM/VRR) capabilities from HF-VSDB
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +-
.../display/amdgpu_dm/amdgpu_dm_connector.c | 89 +++++++++++++-
.../display/amdgpu_dm/amdgpu_dm_freesync.c | 43 +++++++
.../amd/display/modules/inc/mod_info_packet.h | 4 +
.../display/modules/info_packet/info_packet.c | 109 ++++++++++++++++++
drivers/gpu/drm/drm_edid.c | 42 +++++++
include/drm/drm_connector.h | 47 ++++++++
7 files changed, 335 insertions(+), 4 deletions(-)
base-commit: de2622bbc20276eaaaafa8fdbd374ace1ced28dc
--
2.53.0
^ permalink raw reply [flat|nested] 43+ messages in thread* [PATCH v3 1/4] drm/amd/display: Add 2.1 FreeSync support for AMD VSDB EDID Block
2026-08-11 0:39 ` [PATCH v3 0/4] HDMI 2.1 VRR and " Fangzhi Zuo
@ 2026-08-11 0:39 ` Fangzhi Zuo
2026-08-11 0:39 ` [PATCH v3 2/4] drm/edid: parse HDMI 2.1 gaming (ALLM/VRR) capabilities from HF-VSDB Fangzhi Zuo
` (3 subsequent siblings)
4 siblings, 0 replies; 43+ messages in thread
From: Fangzhi Zuo @ 2026-08-11 0:39 UTC (permalink / raw)
To: amd-gfx; +Cc: dri-devel, Harry Wentland, Tomasz Pakuła, Fangzhi Zuo
From: Fangzhi Zuo <Jerry.Zuo@amd.com>
why:
HDMI FRL sinks were not parsed for the AMD VSDB and no VTEM info packet
was emitted for them, so 2.1 FreeSync over HDMI FRL did not work. It is
backward-compatible with 2.0 FreeSync.
how:
- Accept SIGNAL_TYPE_HDMI_FRL alongside SIGNAL_TYPE_HDMI_TYPE_A when
parsing the AMD VSDB in amdgpu_dm_update_freesync_caps().
- Build and send the VTEM info packet via mod_build_infopacket_vtem()
when the stream signal is HDMI FRL during the freesync state update.
- Set the VTEM Data_Set_Length to 0 when no VTEM feature is enabled.
build_infopacket_header_vtem() hardcodes Data_Set_Length = 4, so a VTEM
with Data_Set_Length = 4 would be transmitted even when no VTEM feature
is enabled (VRR_EN = 0 and no FVA), e.g. when the sink advertises
VRRMIN = 0 and vrr_capable is false. This fails HDMI GCTS HF1-58 step
6.2.
The VTEM must keep being transmitted every MTW while VRR is enabled
(HF1-58 steps 8.1 and 8.3), so it cannot simply be suppressed per
frame. Instead, follow the MLDS option in HDMI 2.1 10.10.2.4: keep
transmitting the VTEM but set Data_Set_Length = 0 when no feature is
enabled. When VRR becomes active the full Data_Set_Length = 4 payload
with VRR_EN = 1 is sent as before.
Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com>
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
---
.../display/amdgpu_dm/amdgpu_dm_connector.c | 4 +-
.../display/amdgpu_dm/amdgpu_dm_freesync.c | 4 +
.../amd/display/modules/inc/mod_info_packet.h | 4 +
.../display/modules/info_packet/info_packet.c | 109 ++++++++++++++++++
4 files changed, 120 insertions(+), 1 deletion(-)
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 2cc3734c992b..9eaa20ec528e 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
@@ -3838,7 +3838,9 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
amdgpu_dm_connector->as_type = ADAPTIVE_SYNC_TYPE_EDP;
}
- } else if (drm_edid && sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) {
+ } else if (drm_edid &&
+ (sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A ||
+ sink->sink_signal == SIGNAL_TYPE_HDMI_FRL)) {
i = parse_hdmi_amd_vsdb(amdgpu_dm_connector, edid, &vsdb_info);
if (i >= 0) {
amdgpu_dm_connector->vsdb_info = vsdb_info;
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 46674b83183c..035d7e88c3ed 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
@@ -37,6 +37,7 @@
#include "amdgpu_dm_freesync.h"
#include "dm_helpers.h"
#include "modules/inc/mod_freesync.h"
+#include "modules/inc/mod_info_packet.h"
bool amdgpu_dm_is_dc_timing_adjust_needed(struct dm_crtc_state *old_state,
struct dm_crtc_state *new_state)
@@ -229,6 +230,9 @@ void amdgpu_dm_update_freesync_state_on_stream(
&vrr_infopacket,
pack_sdp_v1_3);
+ if (new_stream->sink->sink_signal == SIGNAL_TYPE_HDMI_FRL)
+ mod_build_infopacket_vtem(new_stream, &vrr_params, 0, &vrr_infopacket);
+
new_crtc_state->freesync_vrr_info_changed |=
(memcmp(&new_crtc_state->vrr_infopacket,
&vrr_infopacket,
diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h
index eee8206bc531..5181d889fe7f 100644
--- a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h
+++ b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h
@@ -67,6 +67,10 @@ struct AS_Df_params {
struct frame_duration_op decrease;
};
+void mod_build_infopacket_vtem(const struct dc_stream_state *stream,
+ const struct mod_vrr_params *vrr, int fva_factor,
+ struct dc_info_packet *infopacket);
+
void mod_build_adaptive_sync_infopacket(const struct dc_stream_state *stream,
enum adaptive_sync_type asType, const struct AS_Df_params *param,
struct dc_info_packet *info_packet);
diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
index f5ac4bf32a78..32b697f46788 100644
--- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
+++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
@@ -291,6 +291,21 @@ void set_vsc_packet_colorimetry_data(
info_packet->sb[18] = 0;
}
+static void set_field_with_mask(unsigned char *dest, unsigned int mask, unsigned int value)
+{
+ unsigned int shift = 0;
+
+ if (!mask || !dest)
+ return;
+
+ while (!((mask >> shift) & 1))
+ shift++;
+
+ *dest = *dest & ~mask;
+ value = value & (mask >> shift);
+ *dest = *dest | (value << shift);
+}
+
void mod_build_vsc_infopacket(const struct dc_stream_state *stream,
struct dc_info_packet *info_packet,
enum dc_color_space cs,
@@ -644,6 +659,100 @@ void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream,
info_packet->valid = true;
}
+static void build_vtem_infopacket_data(const struct dc_stream_state *stream,
+ const struct mod_vrr_params *vrr, int fva_factor,
+ struct dc_info_packet *infopacket)
+{
+ unsigned int field_rate_in_hz;
+
+ /* FVA Factor setting */
+ set_field_with_mask(&infopacket->sb[VTEM_MD0], MASK_VTEM_MD0__FVA_FACTOR_M1,
+ (fva_factor > 0) ? (fva_factor - 1) : 0);
+ /* VRR Parameters */
+ if (vrr->state == VRR_STATE_ACTIVE_VARIABLE ||
+ vrr->state == VRR_STATE_ACTIVE_FIXED) {
+ set_field_with_mask(&infopacket->sb[VTEM_MD0], MASK_VTEM_MD0__VRR_EN, 1);
+ } else {
+ set_field_with_mask(&infopacket->sb[VTEM_MD0], MASK_VTEM_MD0__VRR_EN, 0);
+ }
+
+ if (vrr->state == VRR_STATE_ACTIVE_FIXED)
+ set_field_with_mask(&infopacket->sb[VTEM_MD0], MASK_VTEM_MD0__M_CONST, vrr->m_const);
+
+ if (!stream->timing.vic) {
+ set_field_with_mask(&infopacket->sb[VTEM_MD1], MASK_VTEM_MD1__BASE_VFRONT,
+ stream->timing.v_front_porch);
+
+
+ /* TODO: In dal2, we check mode flags for a reduced blanking timing.
+ * Need a way to relay that information to this function.
+ * if("ReducedBlanking")
+ * {
+ * set_field_with_mask(&infopacket->sb[VRR_VTEM_MD2], MASK__VRR_VTEM_MD2__RB, 1;
+ * }
+ */
+
+ field_rate_in_hz = stream->timing.pix_clk_100hz * 100;
+ field_rate_in_hz /= stream->timing.h_total;
+ field_rate_in_hz = (field_rate_in_hz + stream->timing.v_total / 2)
+ / stream->timing.v_total;
+
+ set_field_with_mask(&infopacket->sb[VTEM_MD2], MASK_VTEM_MD2__BASE_REFRESH_RATE_98,
+ field_rate_in_hz >> 8);
+ set_field_with_mask(&infopacket->sb[VTEM_MD3], MASK_VTEM_MD3__BASE_REFRESH_RATE_07,
+ field_rate_in_hz);
+
+ }
+
+ /*
+ * When no VTEM feature is enabled (neither VRR nor FVA), signal a
+ * zero-length data set (MLDS) by clearing Data_Set_Length. HDMI 2.1
+ * 10.10.2.4 requires the Source to either stop transmitting the VTEM
+ * or set Data_Set_Length = 0 when no feature is enabled; keeping the
+ * VTEM with Data_Set_Length = 0 preserves the every-MTW cadence while
+ * staying compliant (e.g. HDMI GCTS HF1-58 step 6.2).
+ */
+ if (vrr->state != VRR_STATE_ACTIVE_VARIABLE &&
+ vrr->state != VRR_STATE_ACTIVE_FIXED && fva_factor == 0)
+ set_field_with_mask(&infopacket->sb[VTEM_PB6],
+ MASK_VTEM_PB6__DATA_SET_LENGTH_LSB, 0);
+
+ infopacket->valid = true;
+}
+
+static void build_infopacket_header_vtem(enum signal_type signal,
+ struct dc_info_packet *infopacket)
+{
+ /* HEADER */
+
+ /* HB0, HB1, HB2 indicates PacketType VTEMPacket */
+ infopacket->hb0 = 0x7F;
+ infopacket->hb1 = 0xC0;
+ infopacket->hb2 = 0x00; /* sequence_index */
+
+ set_field_with_mask(&infopacket->sb[VTEM_PB0], MASK_VTEM_PB0__VFR, 1);
+ set_field_with_mask(&infopacket->sb[VTEM_PB2], MASK_VTEM_PB2__ORGANIZATION_ID, 1);
+ set_field_with_mask(&infopacket->sb[VTEM_PB3], MASK_VTEM_PB3__DATA_SET_TAG_MSB, 0);
+ set_field_with_mask(&infopacket->sb[VTEM_PB4], MASK_VTEM_PB4__DATA_SET_TAG_LSB, 1);
+ set_field_with_mask(&infopacket->sb[VTEM_PB5], MASK_VTEM_PB5__DATA_SET_LENGTH_MSB, 0);
+ set_field_with_mask(&infopacket->sb[VTEM_PB6], MASK_VTEM_PB6__DATA_SET_LENGTH_LSB, 4);
+}
+
+void mod_build_infopacket_vtem(const struct dc_stream_state *stream,
+ const struct mod_vrr_params *vrr, int fva_factor,
+ struct dc_info_packet *infopacket)
+{
+ /* VTEM info packet for HdmiVrr */
+
+ memset(infopacket, 0, sizeof(struct dc_info_packet));
+
+ /* VTEM Packet is structured differently */
+ build_infopacket_header_vtem(stream->signal, infopacket);
+ build_vtem_infopacket_data(stream, vrr, fva_factor, infopacket);
+
+ infopacket->valid = true;
+}
+
void mod_build_adaptive_sync_infopacket(const struct dc_stream_state *stream,
enum adaptive_sync_type asType,
const struct AS_Df_params *param,
--
2.53.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH v3 2/4] drm/edid: parse HDMI 2.1 gaming (ALLM/VRR) capabilities from HF-VSDB
2026-08-11 0:39 ` [PATCH v3 0/4] HDMI 2.1 VRR and " Fangzhi Zuo
2026-08-11 0:39 ` [PATCH v3 1/4] drm/amd/display: Add 2.1 FreeSync support for AMD VSDB EDID Block Fangzhi Zuo
@ 2026-08-11 0:39 ` Fangzhi Zuo
2026-08-11 17:35 ` Harry Wentland
2026-08-11 0:39 ` [PATCH v3 3/4] drm/amd/display: Add HDMI 2.1 VRR support " Fangzhi Zuo
` (2 subsequent siblings)
4 siblings, 1 reply; 43+ messages in thread
From: Fangzhi Zuo @ 2026-08-11 0:39 UTC (permalink / raw)
To: amd-gfx
Cc: dri-devel, Harry Wentland, Tomasz Pakuła, Fangzhi Zuo,
Bernhard Berger
From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
Parse the HDMI 2.1 gaming-related capabilities advertised in the HDMI
Forum VSDB (HF-VSDB) and expose them through struct drm_hdmi_info so
drivers can consume them.
Add struct drm_hdmi_vrr_cap describing the sink's VRR capabilities: Fast
VActive (Quick Frame Transport), Negative M VRR, Cinema VRR, MDelta, and
the VRRmin/VRRmax range, together with a "supported" flag derived from
that range. Add the fapa_start_location and allm (Auto Low Latency Mode)
flags to struct drm_hdmi_info.
drm_parse_hdmi_gaming_info() reads byte 8 of the HF-VSDB for the
FAPA/ALLM/FVA/CNMVRR/CinemaVRR/MDelta flags and bytes 9-10 for
VRRmin/VRRmax. Per HDMI 2.1, VRR is considered supported when VRRmin is
within 1-48 and VRRmax is either 0 (maximum based on the video mode) or
>= 100. It is invoked from drm_parse_hdmi_forum_scds(), and the parsed
values are logged for debugging.
Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com>
Tested-by: Bernhard Berger <bernhard.berger@gmail.com>
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
---
drivers/gpu/drm/drm_edid.c | 42 +++++++++++++++++++++++++++++++++
include/drm/drm_connector.h | 47 +++++++++++++++++++++++++++++++++++++
2 files changed, 89 insertions(+)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index ae26618a9a57..d508ec633c9b 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -6182,6 +6182,33 @@ static void drm_parse_ycbcr420_deep_color_info(struct drm_connector *connector,
hdmi->y420_dc_modes = dc_mask;
}
+static void drm_parse_hdmi_gaming_info(struct drm_hdmi_info *hdmi, const u8 *db)
+{
+ struct drm_hdmi_vrr_cap *vrr = &hdmi->vrr_cap;
+
+ if (cea_db_payload_len(db) < 8)
+ return;
+
+ hdmi->fapa_start_location = db[8] & DRM_EDID_FAPA_START_LOCATION;
+ hdmi->allm = db[8] & DRM_EDID_ALLM;
+ vrr->fva = db[8] & DRM_EDID_FVA;
+ vrr->cnmvrr = db[8] & DRM_EDID_CNMVRR;
+ vrr->cinema_vrr = db[8] & DRM_EDID_CINEMA_VRR;
+ vrr->mdelta = db[8] & DRM_EDID_MDELTA;
+
+ if (cea_db_payload_len(db) < 9)
+ return;
+
+ vrr->vrr_min = db[9] & DRM_EDID_VRR_MIN_MASK;
+ vrr->supported = (vrr->vrr_min > 0 && vrr->vrr_min <= 48);
+
+ if (cea_db_payload_len(db) < 10)
+ return;
+
+ vrr->vrr_max = (db[9] & DRM_EDID_VRR_MAX_UPPER_MASK) << 2 | db[10];
+ vrr->supported &= (vrr->vrr_max == 0 || vrr->vrr_max >= 100);
+}
+
static void drm_parse_dsc_info(struct drm_hdmi_dsc_cap *hdmi_dsc,
const u8 *hf_scds)
{
@@ -6308,6 +6335,8 @@ static void drm_parse_hdmi_forum_scds(struct drm_connector *connector,
drm_parse_ycbcr420_deep_color_info(connector, hf_scds);
+ drm_parse_hdmi_gaming_info(&connector->display_info.hdmi, hf_scds);
+
if (cea_db_payload_len(hf_scds) >= 11 && hf_scds[11]) {
drm_parse_dsc_info(hdmi_dsc, hf_scds);
dsc_support = true;
@@ -6317,6 +6346,19 @@ static void drm_parse_hdmi_forum_scds(struct drm_connector *connector,
"[CONNECTOR:%d:%s] HF-VSDB: max TMDS clock: %d KHz, HDMI 2.1 support: %s, DSC 1.2 support: %s\n",
connector->base.id, connector->name,
max_tmds_clock, str_yes_no(max_frl_rate), str_yes_no(dsc_support));
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] FAPA in blanking: %s, ALLM support: %s, Fast Vactive support: %s\n",
+ connector->base.id, connector->name, str_yes_no(hdmi->fapa_start_location),
+ str_yes_no(hdmi->allm), str_yes_no(hdmi->vrr_cap.fva));
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] Negative M VRR support: %s, CinemaVRR support: %s, Mdelta: %d\n",
+ connector->base.id, connector->name, str_yes_no(hdmi->vrr_cap.cnmvrr),
+ str_yes_no(hdmi->vrr_cap.cinema_vrr), hdmi->vrr_cap.mdelta);
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] VRRmin: %u, VRRmax: %u, VRR supported: %s\n",
+ connector->base.id, connector->name, hdmi->vrr_cap.vrr_min,
+ hdmi->vrr_cap.vrr_max, str_yes_no(hdmi->vrr_cap.supported));
+
}
static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector,
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index cd06a3b914a0..9f8f109c2dd1 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -254,6 +254,44 @@ struct drm_scdc {
struct drm_scrambling scrambling;
};
+/**
+ * struct drm_hdmi_vrr_cap - Information about VRR capabilities of a HDMI sink
+ *
+ * Describes the VRR support provided by HDMI 2.1 sink. The information is
+ * fetched fom additional HFVSDB blocks defined for HDMI 2.1.
+ */
+struct drm_hdmi_vrr_cap {
+ /** @fva: flag for Fast VActive (Quick Frame Transport) support */
+ bool fva;
+
+ /** @mcnmvrr: flag for Negative M VRR support */
+ bool cnmvrr;
+
+ /** @mcinema_vrr: flag for Cinema VRR support */
+ bool cinema_vrr;
+
+ /** @mdelta: flag for limited frame-to-frame compensation support */
+ bool mdelta;
+
+ /**
+ * @vrr_min : minimum supported variable refresh rate in Hz.
+ * Valid values only inide 1 - 48 range
+ */
+ u16 vrr_min;
+
+ /**
+ * @vrr_max : maximum supported variable refresh rate in Hz (optional).
+ * Valid values are either 0 (max based on video mode) or >= 100
+ */
+ u16 vrr_max;
+
+ /**
+ * @supported: flag for vrr support based on checking for VRRmin and
+ * VRRmax values having correct values.
+ */
+ bool supported;
+};
+
/**
* struct drm_hdmi_dsc_cap - DSC capabilities of HDMI sink
*
@@ -330,6 +368,15 @@ struct drm_hdmi_info {
/** @max_lanes: supported by sink */
u8 max_lanes;
+ /** @fapa_start_location: flag for the FAPA in blanking support */
+ bool fapa_start_location;
+
+ /** @allm: flag for Auto Low Latency Mode support by sink */
+ bool allm;
+
+ /** @vrr_cap: VRR capabilities of the sink */
+ struct drm_hdmi_vrr_cap vrr_cap;
+
/** @dsc_cap: DSC capabilities of the sink */
struct drm_hdmi_dsc_cap dsc_cap;
};
--
2.53.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* Re: [PATCH v3 2/4] drm/edid: parse HDMI 2.1 gaming (ALLM/VRR) capabilities from HF-VSDB
2026-08-11 0:39 ` [PATCH v3 2/4] drm/edid: parse HDMI 2.1 gaming (ALLM/VRR) capabilities from HF-VSDB Fangzhi Zuo
@ 2026-08-11 17:35 ` Harry Wentland
2026-08-11 17:38 ` Deucher, Alexander
0 siblings, 1 reply; 43+ messages in thread
From: Harry Wentland @ 2026-08-11 17:35 UTC (permalink / raw)
To: Fangzhi Zuo, amd-gfx, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Deucher, Alexander
Cc: dri-devel, Tomasz Pakuła, Bernhard Berger
On 2026-08-10 20:39, Fangzhi Zuo wrote:
> From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
>
> Parse the HDMI 2.1 gaming-related capabilities advertised in the HDMI
> Forum VSDB (HF-VSDB) and expose them through struct drm_hdmi_info so
> drivers can consume them.
>
> Add struct drm_hdmi_vrr_cap describing the sink's VRR capabilities: Fast
> VActive (Quick Frame Transport), Negative M VRR, Cinema VRR, MDelta, and
> the VRRmin/VRRmax range, together with a "supported" flag derived from
> that range. Add the fapa_start_location and allm (Auto Low Latency Mode)
> flags to struct drm_hdmi_info.
>
> drm_parse_hdmi_gaming_info() reads byte 8 of the HF-VSDB for the
> FAPA/ALLM/FVA/CNMVRR/CinemaVRR/MDelta flags and bytes 9-10 for
> VRRmin/VRRmax. Per HDMI 2.1, VRR is considered supported when VRRmin is
> within 1-48 and VRRmax is either 0 (maximum based on the video mode) or
>> = 100. It is invoked from drm_parse_hdmi_forum_scds(), and the parsed
> values are logged for debugging.
>
> Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
> Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com>
> Tested-by: Bernhard Berger <bernhard.berger@gmail.com>
> Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Maarten, Maxime, Thomas, I'd like to merge this into amd-staging-drm-next
since other changes depend on it. Would you like me to push it to
drm-misc-next as well or wait for amd-staging-drm-next pull to get it?
Alex, any objections to taking this directly via asdn?
Harry
> ---
> drivers/gpu/drm/drm_edid.c | 42 +++++++++++++++++++++++++++++++++
> include/drm/drm_connector.h | 47 +++++++++++++++++++++++++++++++++++++
> 2 files changed, 89 insertions(+)
>
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index ae26618a9a57..d508ec633c9b 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -6182,6 +6182,33 @@ static void drm_parse_ycbcr420_deep_color_info(struct drm_connector *connector,
> hdmi->y420_dc_modes = dc_mask;
> }
>
> +static void drm_parse_hdmi_gaming_info(struct drm_hdmi_info *hdmi, const u8 *db)
> +{
> + struct drm_hdmi_vrr_cap *vrr = &hdmi->vrr_cap;
> +
> + if (cea_db_payload_len(db) < 8)
> + return;
> +
> + hdmi->fapa_start_location = db[8] & DRM_EDID_FAPA_START_LOCATION;
> + hdmi->allm = db[8] & DRM_EDID_ALLM;
> + vrr->fva = db[8] & DRM_EDID_FVA;
> + vrr->cnmvrr = db[8] & DRM_EDID_CNMVRR;
> + vrr->cinema_vrr = db[8] & DRM_EDID_CINEMA_VRR;
> + vrr->mdelta = db[8] & DRM_EDID_MDELTA;
> +
> + if (cea_db_payload_len(db) < 9)
> + return;
> +
> + vrr->vrr_min = db[9] & DRM_EDID_VRR_MIN_MASK;
> + vrr->supported = (vrr->vrr_min > 0 && vrr->vrr_min <= 48);
> +
> + if (cea_db_payload_len(db) < 10)
> + return;
> +
> + vrr->vrr_max = (db[9] & DRM_EDID_VRR_MAX_UPPER_MASK) << 2 | db[10];
> + vrr->supported &= (vrr->vrr_max == 0 || vrr->vrr_max >= 100);
> +}
> +
> static void drm_parse_dsc_info(struct drm_hdmi_dsc_cap *hdmi_dsc,
> const u8 *hf_scds)
> {
> @@ -6308,6 +6335,8 @@ static void drm_parse_hdmi_forum_scds(struct drm_connector *connector,
>
> drm_parse_ycbcr420_deep_color_info(connector, hf_scds);
>
> + drm_parse_hdmi_gaming_info(&connector->display_info.hdmi, hf_scds);
> +
> if (cea_db_payload_len(hf_scds) >= 11 && hf_scds[11]) {
> drm_parse_dsc_info(hdmi_dsc, hf_scds);
> dsc_support = true;
> @@ -6317,6 +6346,19 @@ static void drm_parse_hdmi_forum_scds(struct drm_connector *connector,
> "[CONNECTOR:%d:%s] HF-VSDB: max TMDS clock: %d KHz, HDMI 2.1 support: %s, DSC 1.2 support: %s\n",
> connector->base.id, connector->name,
> max_tmds_clock, str_yes_no(max_frl_rate), str_yes_no(dsc_support));
> + drm_dbg_kms(connector->dev,
> + "[CONNECTOR:%d:%s] FAPA in blanking: %s, ALLM support: %s, Fast Vactive support: %s\n",
> + connector->base.id, connector->name, str_yes_no(hdmi->fapa_start_location),
> + str_yes_no(hdmi->allm), str_yes_no(hdmi->vrr_cap.fva));
> + drm_dbg_kms(connector->dev,
> + "[CONNECTOR:%d:%s] Negative M VRR support: %s, CinemaVRR support: %s, Mdelta: %d\n",
> + connector->base.id, connector->name, str_yes_no(hdmi->vrr_cap.cnmvrr),
> + str_yes_no(hdmi->vrr_cap.cinema_vrr), hdmi->vrr_cap.mdelta);
> + drm_dbg_kms(connector->dev,
> + "[CONNECTOR:%d:%s] VRRmin: %u, VRRmax: %u, VRR supported: %s\n",
> + connector->base.id, connector->name, hdmi->vrr_cap.vrr_min,
> + hdmi->vrr_cap.vrr_max, str_yes_no(hdmi->vrr_cap.supported));
> +
> }
>
> static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector,
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index cd06a3b914a0..9f8f109c2dd1 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -254,6 +254,44 @@ struct drm_scdc {
> struct drm_scrambling scrambling;
> };
>
> +/**
> + * struct drm_hdmi_vrr_cap - Information about VRR capabilities of a HDMI sink
> + *
> + * Describes the VRR support provided by HDMI 2.1 sink. The information is
> + * fetched fom additional HFVSDB blocks defined for HDMI 2.1.
> + */
> +struct drm_hdmi_vrr_cap {
> + /** @fva: flag for Fast VActive (Quick Frame Transport) support */
> + bool fva;
> +
> + /** @mcnmvrr: flag for Negative M VRR support */
> + bool cnmvrr;
> +
> + /** @mcinema_vrr: flag for Cinema VRR support */
> + bool cinema_vrr;
> +
> + /** @mdelta: flag for limited frame-to-frame compensation support */
> + bool mdelta;
> +
> + /**
> + * @vrr_min : minimum supported variable refresh rate in Hz.
> + * Valid values only inide 1 - 48 range
> + */
> + u16 vrr_min;
> +
> + /**
> + * @vrr_max : maximum supported variable refresh rate in Hz (optional).
> + * Valid values are either 0 (max based on video mode) or >= 100
> + */
> + u16 vrr_max;
> +
> + /**
> + * @supported: flag for vrr support based on checking for VRRmin and
> + * VRRmax values having correct values.
> + */
> + bool supported;
> +};
> +
> /**
> * struct drm_hdmi_dsc_cap - DSC capabilities of HDMI sink
> *
> @@ -330,6 +368,15 @@ struct drm_hdmi_info {
> /** @max_lanes: supported by sink */
> u8 max_lanes;
>
> + /** @fapa_start_location: flag for the FAPA in blanking support */
> + bool fapa_start_location;
> +
> + /** @allm: flag for Auto Low Latency Mode support by sink */
> + bool allm;
> +
> + /** @vrr_cap: VRR capabilities of the sink */
> + struct drm_hdmi_vrr_cap vrr_cap;
> +
> /** @dsc_cap: DSC capabilities of the sink */
> struct drm_hdmi_dsc_cap dsc_cap;
> };
^ permalink raw reply [flat|nested] 43+ messages in thread* RE: [PATCH v3 2/4] drm/edid: parse HDMI 2.1 gaming (ALLM/VRR) capabilities from HF-VSDB
2026-08-11 17:35 ` Harry Wentland
@ 2026-08-11 17:38 ` Deucher, Alexander
0 siblings, 0 replies; 43+ messages in thread
From: Deucher, Alexander @ 2026-08-11 17:38 UTC (permalink / raw)
To: Wentland, Harry, Zuo, Jerry, amd-gfx@lists.freedesktop.org,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann
Cc: dri-devel@lists.freedesktop.org, Tomasz Pakuła,
Bernhard Berger
Public
> -----Original Message-----
> From: Wentland, Harry <Harry.Wentland@amd.com>
> Sent: Tuesday, August 11, 2026 1:36 PM
> To: Zuo, Jerry <Jerry.Zuo@amd.com>; amd-gfx@lists.freedesktop.org;
> Maarten Lankhorst <maarten.lankhorst@linux.intel.com>; Maxime Ripard
> <mripard@kernel.org>; Thomas Zimmermann <tzimmermann@suse.de>;
> Deucher, Alexander <Alexander.Deucher@amd.com>
> Cc: dri-devel@lists.freedesktop.org; Tomasz Pakuła
> <tomasz.pakula.oficjalny@gmail.com>; Bernhard Berger
> <bernhard.berger@gmail.com>
> Subject: Re: [PATCH v3 2/4] drm/edid: parse HDMI 2.1 gaming (ALLM/VRR)
> capabilities from HF-VSDB
>
> On 2026-08-10 20:39, Fangzhi Zuo wrote:
> > From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
> >
> > Parse the HDMI 2.1 gaming-related capabilities advertised in the HDMI
> > Forum VSDB (HF-VSDB) and expose them through struct drm_hdmi_info so
> > drivers can consume them.
> >
> > Add struct drm_hdmi_vrr_cap describing the sink's VRR capabilities:
> > Fast VActive (Quick Frame Transport), Negative M VRR, Cinema VRR,
> > MDelta, and the VRRmin/VRRmax range, together with a "supported" flag
> > derived from that range. Add the fapa_start_location and allm (Auto
> > Low Latency Mode) flags to struct drm_hdmi_info.
> >
> > drm_parse_hdmi_gaming_info() reads byte 8 of the HF-VSDB for the
> > FAPA/ALLM/FVA/CNMVRR/CinemaVRR/MDelta flags and bytes 9-10 for
> > VRRmin/VRRmax. Per HDMI 2.1, VRR is considered supported when VRRmin
> > is within 1-48 and VRRmax is either 0 (maximum based on the video
> > mode) or
> >> = 100. It is invoked from drm_parse_hdmi_forum_scds(), and the parsed
> > values are logged for debugging.
> >
> > Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
> > Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com>
> > Tested-by: Bernhard Berger <bernhard.berger@gmail.com>
> > Reviewed-by: Harry Wentland <harry.wentland@amd.com>
>
> Maarten, Maxime, Thomas, I'd like to merge this into amd-staging-drm-next
> since other changes depend on it. Would you like me to push it to drm-misc-
> next as well or wait for amd-staging-drm-next pull to get it?
>
> Alex, any objections to taking this directly via asdn?
No objections from me.
Alex
>
> Harry
>
> > ---
> > drivers/gpu/drm/drm_edid.c | 42
> +++++++++++++++++++++++++++++++++
> > include/drm/drm_connector.h | 47
> +++++++++++++++++++++++++++++++++++++
> > 2 files changed, 89 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> > index ae26618a9a57..d508ec633c9b 100644
> > --- a/drivers/gpu/drm/drm_edid.c
> > +++ b/drivers/gpu/drm/drm_edid.c
> > @@ -6182,6 +6182,33 @@ static void
> drm_parse_ycbcr420_deep_color_info(struct drm_connector *connector,
> > hdmi->y420_dc_modes = dc_mask;
> > }
> >
> > +static void drm_parse_hdmi_gaming_info(struct drm_hdmi_info *hdmi,
> > +const u8 *db) {
> > + struct drm_hdmi_vrr_cap *vrr = &hdmi->vrr_cap;
> > +
> > + if (cea_db_payload_len(db) < 8)
> > + return;
> > +
> > + hdmi->fapa_start_location = db[8] &
> DRM_EDID_FAPA_START_LOCATION;
> > + hdmi->allm = db[8] & DRM_EDID_ALLM;
> > + vrr->fva = db[8] & DRM_EDID_FVA;
> > + vrr->cnmvrr = db[8] & DRM_EDID_CNMVRR;
> > + vrr->cinema_vrr = db[8] & DRM_EDID_CINEMA_VRR;
> > + vrr->mdelta = db[8] & DRM_EDID_MDELTA;
> > +
> > + if (cea_db_payload_len(db) < 9)
> > + return;
> > +
> > + vrr->vrr_min = db[9] & DRM_EDID_VRR_MIN_MASK;
> > + vrr->supported = (vrr->vrr_min > 0 && vrr->vrr_min <= 48);
> > +
> > + if (cea_db_payload_len(db) < 10)
> > + return;
> > +
> > + vrr->vrr_max = (db[9] & DRM_EDID_VRR_MAX_UPPER_MASK) << 2 |
> db[10];
> > + vrr->supported &= (vrr->vrr_max == 0 || vrr->vrr_max >= 100); }
> > +
> > static void drm_parse_dsc_info(struct drm_hdmi_dsc_cap *hdmi_dsc,
> > const u8 *hf_scds)
> > {
> > @@ -6308,6 +6335,8 @@ static void drm_parse_hdmi_forum_scds(struct
> > drm_connector *connector,
> >
> > drm_parse_ycbcr420_deep_color_info(connector, hf_scds);
> >
> > + drm_parse_hdmi_gaming_info(&connector->display_info.hdmi,
> hf_scds);
> > +
> > if (cea_db_payload_len(hf_scds) >= 11 && hf_scds[11]) {
> > drm_parse_dsc_info(hdmi_dsc, hf_scds);
> > dsc_support = true;
> > @@ -6317,6 +6346,19 @@ static void drm_parse_hdmi_forum_scds(struct
> drm_connector *connector,
> > "[CONNECTOR:%d:%s] HF-VSDB: max TMDS clock: %d KHz,
> HDMI 2.1 support: %s, DSC 1.2 support: %s\n",
> > connector->base.id, connector->name,
> > max_tmds_clock, str_yes_no(max_frl_rate),
> > str_yes_no(dsc_support));
> > + drm_dbg_kms(connector->dev,
> > + "[CONNECTOR:%d:%s] FAPA in blanking: %s, ALLM support:
> %s, Fast Vactive support: %s\n",
> > + connector->base.id, connector->name, str_yes_no(hdmi-
> >fapa_start_location),
> > + str_yes_no(hdmi->allm), str_yes_no(hdmi->vrr_cap.fva));
> > + drm_dbg_kms(connector->dev,
> > + "[CONNECTOR:%d:%s] Negative M VRR support: %s,
> CinemaVRR support: %s, Mdelta: %d\n",
> > + connector->base.id, connector->name, str_yes_no(hdmi-
> >vrr_cap.cnmvrr),
> > + str_yes_no(hdmi->vrr_cap.cinema_vrr), hdmi-
> >vrr_cap.mdelta);
> > + drm_dbg_kms(connector->dev,
> > + "[CONNECTOR:%d:%s] VRRmin: %u, VRRmax: %u, VRR
> supported: %s\n",
> > + connector->base.id, connector->name, hdmi-
> >vrr_cap.vrr_min,
> > + hdmi->vrr_cap.vrr_max, str_yes_no(hdmi-
> >vrr_cap.supported));
> > +
> > }
> >
> > static void drm_parse_hdmi_deep_color_info(struct drm_connector
> > *connector, diff --git a/include/drm/drm_connector.h
> > b/include/drm/drm_connector.h index cd06a3b914a0..9f8f109c2dd1
> 100644
> > --- a/include/drm/drm_connector.h
> > +++ b/include/drm/drm_connector.h
> > @@ -254,6 +254,44 @@ struct drm_scdc {
> > struct drm_scrambling scrambling;
> > };
> >
> > +/**
> > + * struct drm_hdmi_vrr_cap - Information about VRR capabilities of a
> > +HDMI sink
> > + *
> > + * Describes the VRR support provided by HDMI 2.1 sink. The
> > +information is
> > + * fetched fom additional HFVSDB blocks defined for HDMI 2.1.
> > + */
> > +struct drm_hdmi_vrr_cap {
> > + /** @fva: flag for Fast VActive (Quick Frame Transport) support */
> > + bool fva;
> > +
> > + /** @mcnmvrr: flag for Negative M VRR support */
> > + bool cnmvrr;
> > +
> > + /** @mcinema_vrr: flag for Cinema VRR support */
> > + bool cinema_vrr;
> > +
> > + /** @mdelta: flag for limited frame-to-frame compensation support
> */
> > + bool mdelta;
> > +
> > + /**
> > + * @vrr_min : minimum supported variable refresh rate in Hz.
> > + * Valid values only inide 1 - 48 range
> > + */
> > + u16 vrr_min;
> > +
> > + /**
> > + * @vrr_max : maximum supported variable refresh rate in Hz
> (optional).
> > + * Valid values are either 0 (max based on video mode) or >= 100
> > + */
> > + u16 vrr_max;
> > +
> > + /**
> > + * @supported: flag for vrr support based on checking for VRRmin and
> > + * VRRmax values having correct values.
> > + */
> > + bool supported;
> > +};
> > +
> > /**
> > * struct drm_hdmi_dsc_cap - DSC capabilities of HDMI sink
> > *
> > @@ -330,6 +368,15 @@ struct drm_hdmi_info {
> > /** @max_lanes: supported by sink */
> > u8 max_lanes;
> >
> > + /** @fapa_start_location: flag for the FAPA in blanking support */
> > + bool fapa_start_location;
> > +
> > + /** @allm: flag for Auto Low Latency Mode support by sink */
> > + bool allm;
> > +
> > + /** @vrr_cap: VRR capabilities of the sink */
> > + struct drm_hdmi_vrr_cap vrr_cap;
> > +
> > /** @dsc_cap: DSC capabilities of the sink */
> > struct drm_hdmi_dsc_cap dsc_cap;
> > };
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH v3 3/4] drm/amd/display: Add HDMI 2.1 VRR support from HF-VSDB
2026-08-11 0:39 ` [PATCH v3 0/4] HDMI 2.1 VRR and " Fangzhi Zuo
2026-08-11 0:39 ` [PATCH v3 1/4] drm/amd/display: Add 2.1 FreeSync support for AMD VSDB EDID Block Fangzhi Zuo
2026-08-11 0:39 ` [PATCH v3 2/4] drm/edid: parse HDMI 2.1 gaming (ALLM/VRR) capabilities from HF-VSDB Fangzhi Zuo
@ 2026-08-11 0:39 ` Fangzhi Zuo
2026-08-11 0:39 ` [PATCH v3 4/4] drm/amd/display: Add HDMI ALLM support Fangzhi Zuo
2026-08-14 16:43 ` [PATCH v4 0/4] HDMI 2.1 VRR and " Fangzhi Zuo
4 siblings, 0 replies; 43+ messages in thread
From: Fangzhi Zuo @ 2026-08-11 0:39 UTC (permalink / raw)
To: amd-gfx
Cc: dri-devel, Harry Wentland, Tomasz Pakuła, Fangzhi Zuo,
Fangzhi Zuo
why:
HDMI 2.1 sinks advertise their VRR range in the HDMI Forum VSDB
(HF-VSDB), but amdgpu derived FreeSync capability only from the AMD
VSDB. Sinks that expose just the HDMI Forum VRR capability (e.g. HDMI
compliance EDIDs) were therefore reported as not VRR capable.
how:
- In amdgpu_dm_update_freesync_caps(), when the AMD VSDB does not
provide a valid FreeSync range, fall back to the HDMI 2.1 VRR range
parsed by DRM core from the HF-VSDB
(connector->display_info.hdmi.vrr_cap). VRRMAX = 0 means "up to the
Base Refresh Rate"; when the EDID provides no monitor range maximum
either, fall back to the Base Refresh Rate (the highest refresh-rate
mode of the preferred timing) so a valid VRR range is still reported
to userspace.
- Add VRR debug logging along the FreeSync capability and config paths.
Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com>
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
---
.../display/amdgpu_dm/amdgpu_dm_connector.c | 67 +++++++++++++++++++
.../display/amdgpu_dm/amdgpu_dm_freesync.c | 8 +++
2 files changed, 75 insertions(+)
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 9eaa20ec528e..2fe7bfb1e88f 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
@@ -3812,6 +3812,15 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
if (!adev->dm.freesync_module || !dc_supports_vrr(sink->ctx->dce_version))
goto update;
+ drm_dbg_driver(adev_to_drm(adev),
+ "VRR: enter signal=%d hdmi_vrr=%d mrange[%d-%d] hdmi.vrr_cap[sup=%d min=%d max=%d]\n",
+ sink->sink_signal, connector->display_info.hdmi.vrr_cap.supported,
+ connector->display_info.monitor_range.min_vfreq,
+ connector->display_info.monitor_range.max_vfreq,
+ connector->display_info.hdmi.vrr_cap.supported,
+ connector->display_info.hdmi.vrr_cap.vrr_min,
+ connector->display_info.hdmi.vrr_cap.vrr_max);
+
/* FIXME: Get rid of drm_edid_raw() */
edid = drm_edid_raw(drm_edid);
@@ -3856,6 +3865,59 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
connector->display_info.monitor_range.max_vfreq = vsdb_info.max_refresh_rate_hz;
}
}
+
+ drm_dbg_driver(adev_to_drm(adev),
+ "VRR: amd_vsdb i=%d fs_sup=%d min=%d max=%d fs_capable=%d\n",
+ i, vsdb_info.freesync_supported,
+ vsdb_info.min_refresh_rate_hz,
+ vsdb_info.max_refresh_rate_hz, freesync_capable);
+
+ /*
+ * If AMD VSDB didn't provide a valid FreeSync range, fall back to
+ * the HDMI 2.1 VRR capability parsed from the HF-VSDB.
+ */
+ if (!freesync_capable && connector->display_info.hdmi.vrr_cap.supported) {
+ struct drm_hdmi_vrr_cap *vrr_cap =
+ &connector->display_info.hdmi.vrr_cap;
+
+ drm_dbg_driver(adev_to_drm(adev),
+ "VRR: HF-VSDB fallback: hdmi_vrr=1 vrr_cap[sup=%d min=%d max=%d] mrange_max=%d\n",
+ vrr_cap->supported, vrr_cap->vrr_min, vrr_cap->vrr_max,
+ connector->display_info.monitor_range.max_vfreq);
+
+ if (vrr_cap->supported && vrr_cap->vrr_min > 0) {
+ amdgpu_dm_connector->min_vfreq = vrr_cap->vrr_min;
+ amdgpu_dm_connector->max_vfreq = vrr_cap->vrr_max ?
+ vrr_cap->vrr_max :
+ connector->display_info.monitor_range.max_vfreq;
+
+ /*
+ * VRRMAX = 0 in the HF-VSDB means "up to the Base
+ * Refresh Rate". If the EDID also did not provide a
+ * monitor range max, fall back to the Base Refresh
+ * Rate (the highest refresh rate of the preferred
+ * timing) so a valid VRR range is still reported to
+ * userspace.
+ */
+ if (!amdgpu_dm_connector->max_vfreq) {
+ struct drm_display_mode *brr_mode =
+ amdgpu_dm_get_highest_refresh_rate_mode(amdgpu_dm_connector, true);
+
+ if (brr_mode)
+ amdgpu_dm_connector->max_vfreq =
+ drm_mode_vrefresh(brr_mode);
+ }
+
+ if (amdgpu_dm_connector->max_vfreq -
+ amdgpu_dm_connector->min_vfreq > 10)
+ freesync_capable = true;
+
+ connector->display_info.monitor_range.min_vfreq =
+ amdgpu_dm_connector->min_vfreq;
+ connector->display_info.monitor_range.max_vfreq =
+ amdgpu_dm_connector->max_vfreq;
+ }
+ }
}
if (amdgpu_dm_connector->dc_link)
@@ -3911,6 +3973,11 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
if (dm_con_state)
dm_con_state->freesync_capable = freesync_capable;
+ drm_dbg_driver(adev_to_drm(adev),
+ "VRR: caps result: freesync_capable=%d min_vfreq=%d max_vfreq=%d\n",
+ freesync_capable, amdgpu_dm_connector->min_vfreq,
+ amdgpu_dm_connector->max_vfreq);
+
if (connector->state && amdgpu_dm_connector->dc_link && !freesync_capable &&
amdgpu_dm_connector->dc_link->replay_settings.config.replay_supported) {
amdgpu_dm_connector->dc_link->replay_settings.config.replay_supported = false;
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 035d7e88c3ed..382c339b67b1 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
@@ -152,6 +152,14 @@ void amdgpu_dm_get_freesync_config_for_crtc(
}
out:
new_crtc_state->freesync_config = config;
+
+ drm_dbg_driver(new_con_state->base.connector->dev,
+ "VRR: cfg vrr_enabled=%d vrr_supported=%d fs_capable=%d vrefresh=%d min=%d max=%d state=%d\n",
+ new_crtc_state->base.vrr_enabled,
+ new_crtc_state->vrr_supported,
+ new_con_state->freesync_capable, vrefresh,
+ aconnector->min_vfreq, aconnector->max_vfreq,
+ config.state);
}
EXPORT_IF_KUNIT(amdgpu_dm_get_freesync_config_for_crtc);
--
2.53.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* [PATCH v3 4/4] drm/amd/display: Add HDMI ALLM support
2026-08-11 0:39 ` [PATCH v3 0/4] HDMI 2.1 VRR and " Fangzhi Zuo
` (2 preceding siblings ...)
2026-08-11 0:39 ` [PATCH v3 3/4] drm/amd/display: Add HDMI 2.1 VRR support " Fangzhi Zuo
@ 2026-08-11 0:39 ` Fangzhi Zuo
2026-08-11 13:48 ` Derek Foreman
2026-08-14 16:43 ` [PATCH v4 0/4] HDMI 2.1 VRR and " Fangzhi Zuo
4 siblings, 1 reply; 43+ messages in thread
From: Fangzhi Zuo @ 2026-08-11 0:39 UTC (permalink / raw)
To: amd-gfx
Cc: dri-devel, Harry Wentland, Tomasz Pakuła, Fangzhi Zuo,
Fangzhi Zuo
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 <Jerry.Zuo@amd.com>
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
---
.../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.
+ */
+ 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,
--
2.53.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* Re: [PATCH v3 4/4] drm/amd/display: Add HDMI ALLM support
2026-08-11 0:39 ` [PATCH v3 4/4] drm/amd/display: Add HDMI ALLM support Fangzhi Zuo
@ 2026-08-11 13:48 ` Derek Foreman
2026-08-11 15:23 ` Daniel Stone
0 siblings, 1 reply; 43+ messages in thread
From: Derek Foreman @ 2026-08-11 13:48 UTC (permalink / raw)
To: Fangzhi Zuo, amd-gfx; +Cc: dri-devel, Harry Wentland, Tomasz Pakuła
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 <Jerry.Zuo@amd.com>
> Reviewed-by: Harry Wentland <harry.wentland@amd.com>
> ---
> .../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,
^ permalink raw reply [flat|nested] 43+ messages in thread* Re: [PATCH v3 4/4] drm/amd/display: Add HDMI ALLM support
2026-08-11 13:48 ` Derek Foreman
@ 2026-08-11 15:23 ` Daniel Stone
2026-08-11 17:42 ` Harry Wentland
2026-08-12 0:43 ` Zuo, Jerry
0 siblings, 2 replies; 43+ messages in thread
From: Daniel Stone @ 2026-08-11 15:23 UTC (permalink / raw)
To: Derek Foreman
Cc: Fangzhi Zuo, amd-gfx, dri-devel, Harry Wentland,
Tomasz Pakuła
Hi,
On Tue, 11 Aug 2026 at 14:54, Derek Foreman <derek.foreman@collabora.com> wrote:
> On 8/10/26 7:39 PM, Fangzhi Zuo wrote:
> > + /*
> > + * 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).
> > + */
Is it mandatory for the source to set ALLM when the sink advertises
ALLM support, and content-type == game?
Is it allowable for the source to set ALLM when the sink advertises
ALLM support, and content-type != game?
> > + /*
> > + * 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.
> > + */
Is it mandatory for the source to set ALLM when the sink advertises
ALLM support, and game-VRR is active?
Is it allowable for the source to set ALLM when the sink advertises
ALLM support, and non-game-VRR is active?
> 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.
I strongly agree. I really don't want to see more magic implicit
semantics unless they're completely necessary for some reason.
Someone passed on second-hand that one of the reasons to do this was
to make it easier to support X11 - however, if X11 needs better ALLM
control, then it can be exposed as a connector property via RandR,
just like content-type.
Cheers,
Daniel
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v3 4/4] drm/amd/display: Add HDMI ALLM support
2026-08-11 15:23 ` Daniel Stone
@ 2026-08-11 17:42 ` Harry Wentland
2026-08-13 10:29 ` Daniel Stone
2026-08-12 0:43 ` Zuo, Jerry
1 sibling, 1 reply; 43+ messages in thread
From: Harry Wentland @ 2026-08-11 17:42 UTC (permalink / raw)
To: Daniel Stone, Derek Foreman
Cc: Fangzhi Zuo, amd-gfx, dri-devel, Tomasz Pakuła
On 2026-08-11 11:23, Daniel Stone wrote:
> Hi,
>
> On Tue, 11 Aug 2026 at 14:54, Derek Foreman <derek.foreman@collabora.com> wrote:
>> On 8/10/26 7:39 PM, Fangzhi Zuo wrote:
>>> + /*
>>> + * 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).
>>> + */
>
> Is it mandatory for the source to set ALLM when the sink advertises
> ALLM support, and content-type == game?
>
> Is it allowable for the source to set ALLM when the sink advertises
> ALLM support, and content-type != game?
>
>>> + /*
>>> + * 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.
>>> + */
>
> Is it mandatory for the source to set ALLM when the sink advertises
> ALLM support, and game-VRR is active?
>
> Is it allowable for the source to set ALLM when the sink advertises
> ALLM support, and non-game-VRR is active?
>
>> 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.
>
> I strongly agree. I really don't want to see more magic implicit
> semantics unless they're completely necessary for some reason.
>
Yes, though I wonder what's the point of the content_type property
then. It's another one of those properties that's defined and unused
by all canonical upstream compositors.
Harry
> Someone passed on second-hand that one of the reasons to do this was
> to make it easier to support X11 - however, if X11 needs better ALLM
> control, then it can be exposed as a connector property via RandR,
> just like content-type.
>
> Cheers,
> Daniel
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v3 4/4] drm/amd/display: Add HDMI ALLM support
2026-08-11 17:42 ` Harry Wentland
@ 2026-08-13 10:29 ` Daniel Stone
2026-08-13 13:36 ` Harry Wentland
0 siblings, 1 reply; 43+ messages in thread
From: Daniel Stone @ 2026-08-13 10:29 UTC (permalink / raw)
To: Harry Wentland
Cc: Derek Foreman, Fangzhi Zuo, amd-gfx, dri-devel,
Tomasz Pakuła
On Tue, 11 Aug 2026 at 18:42, Harry Wentland <harry.wentland@amd.com> wrote:
> On 2026-08-11 11:23, Daniel Stone wrote:
> > On Tue, 11 Aug 2026 at 14:54, Derek Foreman <derek.foreman@collabora.com> wrote:
> >> 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.
> >
> > I strongly agree. I really don't want to see more magic implicit
> > semantics unless they're completely necessary for some reason.
> >
>
> Yes, though I wonder what's the point of the content_type property
> then. It's another one of those properties that's defined and unused
> by all canonical upstream compositors.
Poor old Weston, no longer canonical ... !
Seriously though, I see the point, I'm just really wary about the
kernel trying to be too cute about policy. If you want to use Weston
as a vehicle for an ALLM property, we'll happily give you one
tomorrow. It would be static as is all our current output
configuration, but we could also type up something easily enough to
implement the content-type hint protocol for dynamic use, with a user
configuration of 'enable ALLM if there are no games on screen'.
Cheers,
Daniel
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v3 4/4] drm/amd/display: Add HDMI ALLM support
2026-08-13 10:29 ` Daniel Stone
@ 2026-08-13 13:36 ` Harry Wentland
0 siblings, 0 replies; 43+ messages in thread
From: Harry Wentland @ 2026-08-13 13:36 UTC (permalink / raw)
To: Daniel Stone
Cc: Derek Foreman, Fangzhi Zuo, amd-gfx, dri-devel,
Tomasz Pakuła
On 2026-08-13 06:29, Daniel Stone wrote:
> On Tue, 11 Aug 2026 at 18:42, Harry Wentland <harry.wentland@amd.com> wrote:
>> On 2026-08-11 11:23, Daniel Stone wrote:
>>> On Tue, 11 Aug 2026 at 14:54, Derek Foreman <derek.foreman@collabora.com> wrote:
>>>> 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.
>>>
>>> I strongly agree. I really don't want to see more magic implicit
>>> semantics unless they're completely necessary for some reason.
>>>
>>
>> Yes, though I wonder what's the point of the content_type property
>> then. It's another one of those properties that's defined and unused
>> by all canonical upstream compositors.
>
> Poor old Weston, no longer canonical ... !
>
Apologies, I realized Weston used it after sending the email.
But it also doesn't do it dynamically but with a config file,
if I understand it right. So, it exercises the option but is
not super useful to judge how a dynamic/general purpose compositor
would behave.
> Seriously though, I see the point, I'm just really wary about the
> kernel trying to be too cute about policy. If you want to use Weston
> as a vehicle for an ALLM property, we'll happily give you one
> tomorrow. It would be static as is all our current output
> configuration, but we could also type up something easily enough to
> implement the content-type hint protocol for dynamic use, with a user
> configuration of 'enable ALLM if there are no games on screen'.
>
No, thanks for pushing on the policy. These specs (HDMI, VESA) generally
don't think about SW architecture and treat a source as a monolithic
beast controlled by an IHV, which it is not.
Harry
> Cheers,
> Daniel
^ permalink raw reply [flat|nested] 43+ messages in thread
* RE: [PATCH v3 4/4] drm/amd/display: Add HDMI ALLM support
2026-08-11 15:23 ` Daniel Stone
2026-08-11 17:42 ` Harry Wentland
@ 2026-08-12 0:43 ` Zuo, Jerry
2026-08-13 8:35 ` Daniel Stone
1 sibling, 1 reply; 43+ messages in thread
From: Zuo, Jerry @ 2026-08-12 0:43 UTC (permalink / raw)
To: Daniel Stone, Derek Foreman
Cc: amd-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org,
Wentland, Harry, Tomasz Pakuła
AMD General
> -----Original Message-----
> From: Daniel Stone <daniel@fooishbar.org>
> Sent: Tuesday, August 11, 2026 11:24
> To: Derek Foreman <derek.foreman@collabora.com>
> Cc: Zuo, Jerry <Jerry.Zuo@amd.com>; amd-gfx@lists.freedesktop.org; dri-
> devel@lists.freedesktop.org; Wentland, Harry <Harry.Wentland@amd.com>;
> Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
> Subject: Re: [PATCH v3 4/4] drm/amd/display: Add HDMI ALLM support
>
> [You don't often get email from daniel@fooishbar.org. Learn why this is
> important at https://aka.ms/LearnAboutSenderIdentification ]
>
> Hi,
>
> On Tue, 11 Aug 2026 at 14:54, Derek Foreman
> <derek.foreman@collabora.com> wrote:
> > On 8/10/26 7:39 PM, Fangzhi Zuo wrote:
> > > + /*
> > > + * 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).
> > > + */
>
Below two scenarios belong to static/modeset ALLM
#1
> Is it mandatory for the source to set ALLM when the sink advertises ALLM
> support, and content-type == game?
Allowable ALLM == 1, but not mandatory, means ALLM can be set to 0
From spec 10.11, P456, 582, 583
#2
> Is it allowable for the source to set ALLM when the sink advertises ALLM
> support, and content-type != game?
Allowable ALLM == 1
From spec 10.11, P456, 582
Above two scenarios are simply subjective policies, not defined in the spec.
>
> > > + /*
> > > + * 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.
> > > + */
#3. Gaming-VRR
> Is it mandatory for the source to set ALLM when the sink advertises ALLM
> support, and game-VRR is active?
Mandatory to set ALLM == 1
From spec 7.6.6, P240
It is spec mandatory, and we follow it.
#4. QMS-VRR
> Is it allowable for the source to set ALLM when the sink advertises ALLM
> support, and non-game-VRR is active?
It is QMS-VRR, mandatory to set ALLM == 0
From spec 10.11, P456, 240
It is spec mandatory when enabling QMS-VRR, but it is not yet implemented in current change.
>
> > 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.
ALLM_Mode is a protocol-level HF-VSIF bit; like VRR_EN, the driver derives
it from existing compositor-set KMS state rather than exposing a new bit.
The Gaming-VRR case #3 is not policy at all. 7.6.6 mandates ALLM_Mode=1
when VRR_EN=1 and the sink advertise ALLM, so it must live in the driver.
The only discretionary piece is content_type = Game ⇒ ALLM (#1, #2),
which CTA-861's latency-minimization recommendation for Game IT content
makes a reasonable default (Appendix G lists it as allowable).
To avoid per-driver divergence, that default could live in a DRM helper,
with room to add an explicit override property later if a concrete need arises.
It can be planned in the future.
>
> I strongly agree. I really don't want to see more magic implicit semantics
> unless they're completely necessary for some reason.
>
> Someone passed on second-hand that one of the reasons to do this was to
> make it easier to support X11 - however, if X11 needs better ALLM control,
> then it can be exposed as a connector property via RandR, just like content-
> type.
>
> Cheers,
> Daniel
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH v3 4/4] drm/amd/display: Add HDMI ALLM support
2026-08-12 0:43 ` Zuo, Jerry
@ 2026-08-13 8:35 ` Daniel Stone
2026-08-14 15:41 ` Zuo, Jerry
0 siblings, 1 reply; 43+ messages in thread
From: Daniel Stone @ 2026-08-13 8:35 UTC (permalink / raw)
To: Zuo, Jerry
Cc: Derek Foreman, amd-gfx@lists.freedesktop.org,
dri-devel@lists.freedesktop.org, Wentland, Harry,
Tomasz Pakuła
Hi there,
On Wed, 12 Aug 2026 at 01:43, Zuo, Jerry <Jerry.Zuo@amd.com> wrote:
> Below two scenarios belong to static/modeset ALLM
Thanks a lot for these clarifications.
> #3. Gaming-VRR
> > Is it mandatory for the source to set ALLM when the sink advertises ALLM
> > support, and game-VRR is active?
> Mandatory to set ALLM == 1
> From spec 7.6.6, P240
> It is spec mandatory, and we follow it.
>
> #4. QMS-VRR
> > Is it allowable for the source to set ALLM when the sink advertises ALLM
> > support, and non-game-VRR is active?
> It is QMS-VRR, mandatory to set ALLM == 0
> From spec 10.11, P456, 240
> It is spec mandatory when enabling QMS-VRR, but it is not yet implemented in current change.
This is the interesting part.
> > > 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.
>
> ALLM_Mode is a protocol-level HF-VSIF bit; like VRR_EN, the driver derives
> it from existing compositor-set KMS state rather than exposing a new bit.
VRR_ENABLED is a completely separate bit though.
> The Gaming-VRR case #3 is not policy at all. 7.6.6 mandates ALLM_Mode=1
> when VRR_EN=1 and the sink advertise ALLM, so it must live in the driver.
>
> The only discretionary piece is content_type = Game ⇒ ALLM (#1, #2),
> which CTA-861's latency-minimization recommendation for Game IT content
> makes a reasonable default (Appendix G lists it as allowable).
> To avoid per-driver divergence, that default could live in a DRM helper,
> with room to add an explicit override property later if a concrete need arises.
> It can be planned in the future.
I really think the burden of proof for implicit semantics in KMS
should be the other way around: do we unavoidably need this, or is
there (currently) no other option at all?
I don't think ALLM falls into this basket at all. It's nice to have
for gaming (and mandatory for gaming VRR mode), but there are plenty
of different scenarios where having it on or off is a legitimate
choice. For instance, should desktops imply ALLM because they aren't
going to smooth your text into oblivion, or should they not because
you're probably not going to read text on a 49" display? Should all
games imply ALLM because you need the response time, or are you maybe
playing Myst on your TV?
I understand the attraction behind 'we can just stuff this in the
kernel and it will dtrt', but hey, that's what people thought about
Broadcast RGB at the time. Or colour model/subsampling selection on
the wire. Or or or ...
Cheers,
Daniel
^ permalink raw reply [flat|nested] 43+ messages in thread
* RE: [PATCH v3 4/4] drm/amd/display: Add HDMI ALLM support
2026-08-13 8:35 ` Daniel Stone
@ 2026-08-14 15:41 ` Zuo, Jerry
0 siblings, 0 replies; 43+ messages in thread
From: Zuo, Jerry @ 2026-08-14 15:41 UTC (permalink / raw)
To: Daniel Stone
Cc: Derek Foreman, amd-gfx@lists.freedesktop.org,
dri-devel@lists.freedesktop.org, Wentland, Harry,
Tomasz Pakuła
AMD General
Hi:
Thanks for your feedback.
> -----Original Message-----
> From: Daniel Stone <daniel@fooishbar.org>
> Sent: Thursday, August 13, 2026 04:36
> To: Zuo, Jerry <Jerry.Zuo@amd.com>
> Cc: Derek Foreman <derek.foreman@collabora.com>; amd-
> gfx@lists.freedesktop.org; dri-devel@lists.freedesktop.org; Wentland, Harry
> <Harry.Wentland@amd.com>; Tomasz Pakuła
> <tomasz.pakula.oficjalny@gmail.com>
> Subject: Re: [PATCH v3 4/4] drm/amd/display: Add HDMI ALLM support
>
> Hi there,
>
> On Wed, 12 Aug 2026 at 01:43, Zuo, Jerry <Jerry.Zuo@amd.com> wrote:
> > Below two scenarios belong to static/modeset ALLM
>
> Thanks a lot for these clarifications.
>
> > #3. Gaming-VRR
> > > Is it mandatory for the source to set ALLM when the sink advertises
> > > ALLM support, and game-VRR is active?
> > Mandatory to set ALLM == 1
> > From spec 7.6.6, P240
> > It is spec mandatory, and we follow it.
> >
> > #4. QMS-VRR
> > > Is it allowable for the source to set ALLM when the sink advertises
> > > ALLM support, and non-game-VRR is active?
> > It is QMS-VRR, mandatory to set ALLM == 0 From spec 10.11, P456, 240
> > It is spec mandatory when enabling QMS-VRR, but it is not yet implemented
> in current change.
>
> This is the interesting part.
>
> > > > 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.
> >
> > ALLM_Mode is a protocol-level HF-VSIF bit; like VRR_EN, the driver
> > derives it from existing compositor-set KMS state rather than exposing a
> new bit.
>
> VRR_ENABLED is a completely separate bit though.
Yes, VRR_ENABLED is its own dedicated property that maps 1:1 to VRR_EN.
There are two independent triggers in the patch, and only one of them is a
policy decision:
1. During Gaming-VRR the sink is expected to be in its low-latency mode
regardless of the bit — a compositor property that cleared ALLM here
would be both non-compliant and ineffective. This part therefore has to
stay in the driver.
2. content_type == Game -> ALLM. This one I agree is a policy decision, and
it's the subjective trade-off you're describing.
(Game with ALLM_Mode=0 is a valid combination)
>
> > The Gaming-VRR case #3 is not policy at all. 7.6.6 mandates
> > ALLM_Mode=1 when VRR_EN=1 and the sink advertise ALLM, so it must live
> in the driver.
> >
> > The only discretionary piece is content_type = Game ⇒ ALLM (#1, #2),
> > which CTA-861's latency-minimization recommendation for Game IT
> > content makes a reasonable default (Appendix G lists it as allowable).
> > To avoid per-driver divergence, that default could live in a DRM
> > helper, with room to add an explicit override property later if a concrete
> need arises.
> > It can be planned in the future.
>
> I really think the burden of proof for implicit semantics in KMS should be the
> other way around: do we unavoidably need this, or is there (currently) no
> other option at all?
>
> I don't think ALLM falls into this basket at all. It's nice to have for gaming (and
> mandatory for gaming VRR mode), but there are plenty of different scenarios
> where having it on or off is a legitimate choice. For instance, should desktops
> imply ALLM because they aren't going to smooth your text into oblivion, or
> should they not because you're probably not going to read text on a 49"
> display? Should all games imply ALLM because you need the response time,
> or are you maybe playing Myst on your TV?
>
> I understand the attraction behind 'we can just stuff this in the kernel and it
> will dtrt', but hey, that's what people thought about Broadcast RGB at the
> time. Or colour model/subsampling selection on the wire. Or or or ...
>
Yes I agreed. content_type -> ALLM doesn't clear that bar, and I'll drop it.
I'll submit another v4 based on below soon:
1. Keep only the case we have no choice about: set ALLM_Mode=1 when
Gaming-VRR is active (VRR_EN=1) and the sink advertises ALLM, per spec 7.6.6.
This stays in the driver.
2. Remove the content_type == Game heuristic from both the modeset and the
freesync paths. No implicit ALLM derived from content type.
3. No new implicit semantics, and no DRM-helper "default" either. If a
concrete need for explicit ALLM control shows up, it should be a proper
(ideally generic) property with a real userspace user driving it, not
something the kernel infers.
Regards,
Jerry
> Cheers,
> Daniel
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH v4 0/4] HDMI 2.1 VRR and ALLM support
2026-08-11 0:39 ` [PATCH v3 0/4] HDMI 2.1 VRR and " Fangzhi Zuo
` (3 preceding siblings ...)
2026-08-11 0:39 ` [PATCH v3 4/4] drm/amd/display: Add HDMI ALLM support Fangzhi Zuo
@ 2026-08-14 16:43 ` Fangzhi Zuo
2026-08-14 16:43 ` [PATCH v4 1/4] drm/amd/display: Add 2.1 FreeSync support for AMD VSDB EDID Block Fangzhi Zuo
` (3 more replies)
4 siblings, 4 replies; 43+ messages in thread
From: Fangzhi Zuo @ 2026-08-14 16:43 UTC (permalink / raw)
To: amd-gfx; +Cc: dri-devel, Harry Wentland, Tomasz Pakuła, daniel,
Fangzhi Zuo
This series adds HDMI 2.1 gaming support to amdgpu: Variable Refresh Rate
(VRR) derived from the HDMI Forum VSDB (HF-VSDB), and Auto Low-Latency
Mode (ALLM). It builds on a drm/edid patch that parses the HF-VSDB gaming
capabilities into struct drm_hdmi_info.
- Patch 1 reports FreeSync from the AMD VSDB (existing mechanism).
- Patch 2 (drm/edid) parses the HF-VSDB VRR range and ALLM bit.
- Patch 3 enables VRR from the HF-VSDB when the AMD VSDB has no range.
- Patch 4 signals ALLM_Mode in the HF-VSIF when Gaming-VRR is active.
v1: https://lore.kernel.org/amd-gfx/20260730171754.704049-1-jerry.zuo@amd.com/
v2: https://lore.kernel.org/amd-gfx/20260806205449.16806-1-jerry.zuo@amd.com/
v3: https://lore.kernel.org/amd-gfx/20260811003921.1398292-1-jerry.zuo@amd.com/
Changes since v3:
- Drop the content-type based ALLM heuristic. ALLM_Mode is now set only
for the mandatory Gaming-VRR case (VRR_EN=1 with a sink that advertises
ALLM), per HDMI 2.1 Section 7.6.6; it is no longer derived from the
content type.
Changes since v2:
- Fix coding-style issues in the VTEM info-packet code.
Fangzhi Zuo (3):
drm/amd/display: Add 2.1 FreeSync support for AMD VSDB EDID Block
drm/amd/display: Add HDMI 2.1 VRR support from HF-VSDB
drm/amd/display: Enable HDMI ALLM for Gaming-VRR
Tomasz Pakuła (1):
drm/edid: parse HDMI 2.1 gaming (ALLM/VRR) capabilities from HF-VSDB
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +-
.../display/amdgpu_dm/amdgpu_dm_connector.c | 71 +++++++++++-
.../display/amdgpu_dm/amdgpu_dm_freesync.c | 41 +++++++
.../amd/display/modules/inc/mod_info_packet.h | 4 +
.../display/modules/info_packet/info_packet.c | 109 ++++++++++++++++++
drivers/gpu/drm/drm_edid.c | 42 +++++++
include/drm/drm_connector.h | 47 ++++++++
7 files changed, 317 insertions(+), 2 deletions(-)
base-commit: de2622bbc20276eaaaafa8fdbd374ace1ced28dc
--
2.53.0
^ permalink raw reply [flat|nested] 43+ messages in thread* [PATCH v4 1/4] drm/amd/display: Add 2.1 FreeSync support for AMD VSDB EDID Block
2026-08-14 16:43 ` [PATCH v4 0/4] HDMI 2.1 VRR and " Fangzhi Zuo
@ 2026-08-14 16:43 ` Fangzhi Zuo
2026-08-14 16:55 ` sashiko-bot
2026-08-14 16:43 ` [PATCH v4 2/4] drm/edid: parse HDMI 2.1 gaming (ALLM/VRR) capabilities from HF-VSDB Fangzhi Zuo
` (2 subsequent siblings)
3 siblings, 1 reply; 43+ messages in thread
From: Fangzhi Zuo @ 2026-08-14 16:43 UTC (permalink / raw)
To: amd-gfx; +Cc: dri-devel, Harry Wentland, Tomasz Pakuła, daniel,
Fangzhi Zuo
From: Fangzhi Zuo <Jerry.Zuo@amd.com>
why:
HDMI FRL sinks were not parsed for the AMD VSDB and no VTEM info packet
was emitted for them, so 2.1 FreeSync over HDMI FRL did not work. It is
backward-compatible with 2.0 FreeSync.
how:
- Accept SIGNAL_TYPE_HDMI_FRL alongside SIGNAL_TYPE_HDMI_TYPE_A when
parsing the AMD VSDB in amdgpu_dm_update_freesync_caps().
- Build and send the VTEM info packet via mod_build_infopacket_vtem()
when the stream signal is HDMI FRL during the freesync state update.
- Set the VTEM Data_Set_Length to 0 when no VTEM feature is enabled.
build_infopacket_header_vtem() hardcodes Data_Set_Length = 4, so a VTEM
with Data_Set_Length = 4 would be transmitted even when no VTEM feature
is enabled (VRR_EN = 0 and no FVA), e.g. when the sink advertises
VRRMIN = 0 and vrr_capable is false. This fails HDMI GCTS HF1-58 step
6.2.
The VTEM must keep being transmitted every MTW while VRR is enabled
(HF1-58 steps 8.1 and 8.3), so it cannot simply be suppressed per
frame. Instead, follow the MLDS option in HDMI 2.1 10.10.2.4: keep
transmitting the VTEM but set Data_Set_Length = 0 when no feature is
enabled. When VRR becomes active the full Data_Set_Length = 4 payload
with VRR_EN = 1 is sent as before.
Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com>
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
---
.../display/amdgpu_dm/amdgpu_dm_connector.c | 4 +-
.../display/amdgpu_dm/amdgpu_dm_freesync.c | 4 +
.../amd/display/modules/inc/mod_info_packet.h | 4 +
.../display/modules/info_packet/info_packet.c | 109 ++++++++++++++++++
4 files changed, 120 insertions(+), 1 deletion(-)
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 2cc3734c992b..9eaa20ec528e 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
@@ -3838,7 +3838,9 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
amdgpu_dm_connector->as_type = ADAPTIVE_SYNC_TYPE_EDP;
}
- } else if (drm_edid && sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) {
+ } else if (drm_edid &&
+ (sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A ||
+ sink->sink_signal == SIGNAL_TYPE_HDMI_FRL)) {
i = parse_hdmi_amd_vsdb(amdgpu_dm_connector, edid, &vsdb_info);
if (i >= 0) {
amdgpu_dm_connector->vsdb_info = vsdb_info;
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 46674b83183c..035d7e88c3ed 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
@@ -37,6 +37,7 @@
#include "amdgpu_dm_freesync.h"
#include "dm_helpers.h"
#include "modules/inc/mod_freesync.h"
+#include "modules/inc/mod_info_packet.h"
bool amdgpu_dm_is_dc_timing_adjust_needed(struct dm_crtc_state *old_state,
struct dm_crtc_state *new_state)
@@ -229,6 +230,9 @@ void amdgpu_dm_update_freesync_state_on_stream(
&vrr_infopacket,
pack_sdp_v1_3);
+ if (new_stream->sink->sink_signal == SIGNAL_TYPE_HDMI_FRL)
+ mod_build_infopacket_vtem(new_stream, &vrr_params, 0, &vrr_infopacket);
+
new_crtc_state->freesync_vrr_info_changed |=
(memcmp(&new_crtc_state->vrr_infopacket,
&vrr_infopacket,
diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h
index eee8206bc531..5181d889fe7f 100644
--- a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h
+++ b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h
@@ -67,6 +67,10 @@ struct AS_Df_params {
struct frame_duration_op decrease;
};
+void mod_build_infopacket_vtem(const struct dc_stream_state *stream,
+ const struct mod_vrr_params *vrr, int fva_factor,
+ struct dc_info_packet *infopacket);
+
void mod_build_adaptive_sync_infopacket(const struct dc_stream_state *stream,
enum adaptive_sync_type asType, const struct AS_Df_params *param,
struct dc_info_packet *info_packet);
diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
index f5ac4bf32a78..32b697f46788 100644
--- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
+++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
@@ -291,6 +291,21 @@ void set_vsc_packet_colorimetry_data(
info_packet->sb[18] = 0;
}
+static void set_field_with_mask(unsigned char *dest, unsigned int mask, unsigned int value)
+{
+ unsigned int shift = 0;
+
+ if (!mask || !dest)
+ return;
+
+ while (!((mask >> shift) & 1))
+ shift++;
+
+ *dest = *dest & ~mask;
+ value = value & (mask >> shift);
+ *dest = *dest | (value << shift);
+}
+
void mod_build_vsc_infopacket(const struct dc_stream_state *stream,
struct dc_info_packet *info_packet,
enum dc_color_space cs,
@@ -644,6 +659,100 @@ void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream,
info_packet->valid = true;
}
+static void build_vtem_infopacket_data(const struct dc_stream_state *stream,
+ const struct mod_vrr_params *vrr, int fva_factor,
+ struct dc_info_packet *infopacket)
+{
+ unsigned int field_rate_in_hz;
+
+ /* FVA Factor setting */
+ set_field_with_mask(&infopacket->sb[VTEM_MD0], MASK_VTEM_MD0__FVA_FACTOR_M1,
+ (fva_factor > 0) ? (fva_factor - 1) : 0);
+ /* VRR Parameters */
+ if (vrr->state == VRR_STATE_ACTIVE_VARIABLE ||
+ vrr->state == VRR_STATE_ACTIVE_FIXED) {
+ set_field_with_mask(&infopacket->sb[VTEM_MD0], MASK_VTEM_MD0__VRR_EN, 1);
+ } else {
+ set_field_with_mask(&infopacket->sb[VTEM_MD0], MASK_VTEM_MD0__VRR_EN, 0);
+ }
+
+ if (vrr->state == VRR_STATE_ACTIVE_FIXED)
+ set_field_with_mask(&infopacket->sb[VTEM_MD0], MASK_VTEM_MD0__M_CONST, vrr->m_const);
+
+ if (!stream->timing.vic) {
+ set_field_with_mask(&infopacket->sb[VTEM_MD1], MASK_VTEM_MD1__BASE_VFRONT,
+ stream->timing.v_front_porch);
+
+
+ /* TODO: In dal2, we check mode flags for a reduced blanking timing.
+ * Need a way to relay that information to this function.
+ * if("ReducedBlanking")
+ * {
+ * set_field_with_mask(&infopacket->sb[VRR_VTEM_MD2], MASK__VRR_VTEM_MD2__RB, 1;
+ * }
+ */
+
+ field_rate_in_hz = stream->timing.pix_clk_100hz * 100;
+ field_rate_in_hz /= stream->timing.h_total;
+ field_rate_in_hz = (field_rate_in_hz + stream->timing.v_total / 2)
+ / stream->timing.v_total;
+
+ set_field_with_mask(&infopacket->sb[VTEM_MD2], MASK_VTEM_MD2__BASE_REFRESH_RATE_98,
+ field_rate_in_hz >> 8);
+ set_field_with_mask(&infopacket->sb[VTEM_MD3], MASK_VTEM_MD3__BASE_REFRESH_RATE_07,
+ field_rate_in_hz);
+
+ }
+
+ /*
+ * When no VTEM feature is enabled (neither VRR nor FVA), signal a
+ * zero-length data set (MLDS) by clearing Data_Set_Length. HDMI 2.1
+ * 10.10.2.4 requires the Source to either stop transmitting the VTEM
+ * or set Data_Set_Length = 0 when no feature is enabled; keeping the
+ * VTEM with Data_Set_Length = 0 preserves the every-MTW cadence while
+ * staying compliant (e.g. HDMI GCTS HF1-58 step 6.2).
+ */
+ if (vrr->state != VRR_STATE_ACTIVE_VARIABLE &&
+ vrr->state != VRR_STATE_ACTIVE_FIXED && fva_factor == 0)
+ set_field_with_mask(&infopacket->sb[VTEM_PB6],
+ MASK_VTEM_PB6__DATA_SET_LENGTH_LSB, 0);
+
+ infopacket->valid = true;
+}
+
+static void build_infopacket_header_vtem(enum signal_type signal,
+ struct dc_info_packet *infopacket)
+{
+ /* HEADER */
+
+ /* HB0, HB1, HB2 indicates PacketType VTEMPacket */
+ infopacket->hb0 = 0x7F;
+ infopacket->hb1 = 0xC0;
+ infopacket->hb2 = 0x00; /* sequence_index */
+
+ set_field_with_mask(&infopacket->sb[VTEM_PB0], MASK_VTEM_PB0__VFR, 1);
+ set_field_with_mask(&infopacket->sb[VTEM_PB2], MASK_VTEM_PB2__ORGANIZATION_ID, 1);
+ set_field_with_mask(&infopacket->sb[VTEM_PB3], MASK_VTEM_PB3__DATA_SET_TAG_MSB, 0);
+ set_field_with_mask(&infopacket->sb[VTEM_PB4], MASK_VTEM_PB4__DATA_SET_TAG_LSB, 1);
+ set_field_with_mask(&infopacket->sb[VTEM_PB5], MASK_VTEM_PB5__DATA_SET_LENGTH_MSB, 0);
+ set_field_with_mask(&infopacket->sb[VTEM_PB6], MASK_VTEM_PB6__DATA_SET_LENGTH_LSB, 4);
+}
+
+void mod_build_infopacket_vtem(const struct dc_stream_state *stream,
+ const struct mod_vrr_params *vrr, int fva_factor,
+ struct dc_info_packet *infopacket)
+{
+ /* VTEM info packet for HdmiVrr */
+
+ memset(infopacket, 0, sizeof(struct dc_info_packet));
+
+ /* VTEM Packet is structured differently */
+ build_infopacket_header_vtem(stream->signal, infopacket);
+ build_vtem_infopacket_data(stream, vrr, fva_factor, infopacket);
+
+ infopacket->valid = true;
+}
+
void mod_build_adaptive_sync_infopacket(const struct dc_stream_state *stream,
enum adaptive_sync_type asType,
const struct AS_Df_params *param,
--
2.53.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* Re: [PATCH v4 1/4] drm/amd/display: Add 2.1 FreeSync support for AMD VSDB EDID Block
2026-08-14 16:43 ` [PATCH v4 1/4] drm/amd/display: Add 2.1 FreeSync support for AMD VSDB EDID Block Fangzhi Zuo
@ 2026-08-14 16:55 ` sashiko-bot
0 siblings, 0 replies; 43+ messages in thread
From: sashiko-bot @ 2026-08-14 16:55 UTC (permalink / raw)
To: Fangzhi Zuo; +Cc: dri-devel
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] The VTEM info packet incorrectly overwrites the AMD FreeSync (SPD) info packet in the local `vrr_infopacket` variable, causing the FreeSync metadata to be lost and the VTEM packet to be programmed into the wrong hardware slot.
- [High] Unsafe dereference of the deprecated `new_stream->sink` pointer without a NULL check inside a spinlock, risking a kernel panic and system deadlock.
--
--- Patch [1]: [PATCH v4 1/4] drm/amd/display: Add 2.1 FreeSync support for AMD VSDB EDID Block ---
commit ac51682620be921a897de496468475a6c9820661
Author: Fangzhi Zuo <Jerry.Zuo@amd.com>
Subject: drm/amd/display: Add 2.1 FreeSync support for AMD VSDB EDID Block
This commit adds HDMI 2.1 FreeSync support by parsing the AMD VSDB for HDMI
FRL signals. It updates the FreeSync capabilities and introduces a function to
build and send the VTEM info packet during the freesync state update.
> 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
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.c
[ ... ]
> @@ -229,6 +230,9 @@ void amdgpu_dm_update_freesync_state_on_stream(
> &vrr_infopacket,
> pack_sdp_v1_3);
>
> + if (new_stream->sink->sink_signal == SIGNAL_TYPE_HDMI_FRL)
[Severity: High]
Is it possible for new_stream->sink to be NULL here?
Existing KUnit tests like dm_test_update_freesync_state_default_packet()
allocate dummy streams with a NULL sink. Phantom streams or writeback setups
can also have a NULL sink.
Since this check occurs inside the event_lock spinlock, would a NULL sink
cause a kernel panic and a system deadlock? Would it be safer to verify
new_stream->sink is not NULL before dereferencing it, or use the already
available new_stream->signal instead?
> + mod_build_infopacket_vtem(new_stream, &vrr_params, 0, &vrr_infopacket);
[Severity: High]
Does this overwrite the existing AMD FreeSync metadata stored in
vrr_infopacket?
Looking at the newly added mod_build_infopacket_vtem(), it calls memset()
on the passed infopacket:
drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c:mod_build_infopacket_vtem() {
memset(infopacket, 0, sizeof(struct dc_info_packet));
...
}
Since vrr_infopacket was just populated by mod_freesync_build_vrr_infopacket()
immediately before this block, the memset() appears to erase the SPD packet.
Furthermore, this assigns the VTEM packet to the vrr_infopacket variable,
which is later routed to the SPD hardware slot in set_spd_info_packet().
Should the VTEM packet be stored in new_stream->vtem_infopacket instead to
preserve the FreeSync packet and ensure VTEM is sent in the correct slot?
> +
> new_crtc_state->freesync_vrr_info_changed |=
> (memcmp(&new_crtc_state->vrr_infopacket,
> &vrr_infopacket,
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260814164344.3098143-1-jerry.zuo@amd.com?part=1
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH v4 2/4] drm/edid: parse HDMI 2.1 gaming (ALLM/VRR) capabilities from HF-VSDB
2026-08-14 16:43 ` [PATCH v4 0/4] HDMI 2.1 VRR and " Fangzhi Zuo
2026-08-14 16:43 ` [PATCH v4 1/4] drm/amd/display: Add 2.1 FreeSync support for AMD VSDB EDID Block Fangzhi Zuo
@ 2026-08-14 16:43 ` Fangzhi Zuo
2026-08-14 16:49 ` sashiko-bot
2026-08-14 16:43 ` [PATCH v4 3/4] drm/amd/display: Add HDMI 2.1 VRR support " Fangzhi Zuo
2026-08-14 16:43 ` [PATCH v4 4/4] drm/amd/display: Enable HDMI ALLM for Gaming-VRR Fangzhi Zuo
3 siblings, 1 reply; 43+ messages in thread
From: Fangzhi Zuo @ 2026-08-14 16:43 UTC (permalink / raw)
To: amd-gfx
Cc: dri-devel, Harry Wentland, Tomasz Pakuła, daniel,
Fangzhi Zuo, Bernhard Berger
From: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
Parse the HDMI 2.1 gaming-related capabilities advertised in the HDMI
Forum VSDB (HF-VSDB) and expose them through struct drm_hdmi_info so
drivers can consume them.
Add struct drm_hdmi_vrr_cap describing the sink's VRR capabilities: Fast
VActive (Quick Frame Transport), Negative M VRR, Cinema VRR, MDelta, and
the VRRmin/VRRmax range, together with a "supported" flag derived from
that range. Add the fapa_start_location and allm (Auto Low Latency Mode)
flags to struct drm_hdmi_info.
drm_parse_hdmi_gaming_info() reads byte 8 of the HF-VSDB for the
FAPA/ALLM/FVA/CNMVRR/CinemaVRR/MDelta flags and bytes 9-10 for
VRRmin/VRRmax. Per HDMI 2.1, VRR is considered supported when VRRmin is
within 1-48 and VRRmax is either 0 (maximum based on the video mode) or
>= 100. It is invoked from drm_parse_hdmi_forum_scds(), and the parsed
values are logged for debugging.
Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com>
Tested-by: Bernhard Berger <bernhard.berger@gmail.com>
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
---
drivers/gpu/drm/drm_edid.c | 42 +++++++++++++++++++++++++++++++++
include/drm/drm_connector.h | 47 +++++++++++++++++++++++++++++++++++++
2 files changed, 89 insertions(+)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index ae26618a9a57..d508ec633c9b 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -6182,6 +6182,33 @@ static void drm_parse_ycbcr420_deep_color_info(struct drm_connector *connector,
hdmi->y420_dc_modes = dc_mask;
}
+static void drm_parse_hdmi_gaming_info(struct drm_hdmi_info *hdmi, const u8 *db)
+{
+ struct drm_hdmi_vrr_cap *vrr = &hdmi->vrr_cap;
+
+ if (cea_db_payload_len(db) < 8)
+ return;
+
+ hdmi->fapa_start_location = db[8] & DRM_EDID_FAPA_START_LOCATION;
+ hdmi->allm = db[8] & DRM_EDID_ALLM;
+ vrr->fva = db[8] & DRM_EDID_FVA;
+ vrr->cnmvrr = db[8] & DRM_EDID_CNMVRR;
+ vrr->cinema_vrr = db[8] & DRM_EDID_CINEMA_VRR;
+ vrr->mdelta = db[8] & DRM_EDID_MDELTA;
+
+ if (cea_db_payload_len(db) < 9)
+ return;
+
+ vrr->vrr_min = db[9] & DRM_EDID_VRR_MIN_MASK;
+ vrr->supported = (vrr->vrr_min > 0 && vrr->vrr_min <= 48);
+
+ if (cea_db_payload_len(db) < 10)
+ return;
+
+ vrr->vrr_max = (db[9] & DRM_EDID_VRR_MAX_UPPER_MASK) << 2 | db[10];
+ vrr->supported &= (vrr->vrr_max == 0 || vrr->vrr_max >= 100);
+}
+
static void drm_parse_dsc_info(struct drm_hdmi_dsc_cap *hdmi_dsc,
const u8 *hf_scds)
{
@@ -6308,6 +6335,8 @@ static void drm_parse_hdmi_forum_scds(struct drm_connector *connector,
drm_parse_ycbcr420_deep_color_info(connector, hf_scds);
+ drm_parse_hdmi_gaming_info(&connector->display_info.hdmi, hf_scds);
+
if (cea_db_payload_len(hf_scds) >= 11 && hf_scds[11]) {
drm_parse_dsc_info(hdmi_dsc, hf_scds);
dsc_support = true;
@@ -6317,6 +6346,19 @@ static void drm_parse_hdmi_forum_scds(struct drm_connector *connector,
"[CONNECTOR:%d:%s] HF-VSDB: max TMDS clock: %d KHz, HDMI 2.1 support: %s, DSC 1.2 support: %s\n",
connector->base.id, connector->name,
max_tmds_clock, str_yes_no(max_frl_rate), str_yes_no(dsc_support));
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] FAPA in blanking: %s, ALLM support: %s, Fast Vactive support: %s\n",
+ connector->base.id, connector->name, str_yes_no(hdmi->fapa_start_location),
+ str_yes_no(hdmi->allm), str_yes_no(hdmi->vrr_cap.fva));
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] Negative M VRR support: %s, CinemaVRR support: %s, Mdelta: %d\n",
+ connector->base.id, connector->name, str_yes_no(hdmi->vrr_cap.cnmvrr),
+ str_yes_no(hdmi->vrr_cap.cinema_vrr), hdmi->vrr_cap.mdelta);
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] VRRmin: %u, VRRmax: %u, VRR supported: %s\n",
+ connector->base.id, connector->name, hdmi->vrr_cap.vrr_min,
+ hdmi->vrr_cap.vrr_max, str_yes_no(hdmi->vrr_cap.supported));
+
}
static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector,
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index cd06a3b914a0..9f8f109c2dd1 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -254,6 +254,44 @@ struct drm_scdc {
struct drm_scrambling scrambling;
};
+/**
+ * struct drm_hdmi_vrr_cap - Information about VRR capabilities of a HDMI sink
+ *
+ * Describes the VRR support provided by HDMI 2.1 sink. The information is
+ * fetched fom additional HFVSDB blocks defined for HDMI 2.1.
+ */
+struct drm_hdmi_vrr_cap {
+ /** @fva: flag for Fast VActive (Quick Frame Transport) support */
+ bool fva;
+
+ /** @mcnmvrr: flag for Negative M VRR support */
+ bool cnmvrr;
+
+ /** @mcinema_vrr: flag for Cinema VRR support */
+ bool cinema_vrr;
+
+ /** @mdelta: flag for limited frame-to-frame compensation support */
+ bool mdelta;
+
+ /**
+ * @vrr_min : minimum supported variable refresh rate in Hz.
+ * Valid values only inide 1 - 48 range
+ */
+ u16 vrr_min;
+
+ /**
+ * @vrr_max : maximum supported variable refresh rate in Hz (optional).
+ * Valid values are either 0 (max based on video mode) or >= 100
+ */
+ u16 vrr_max;
+
+ /**
+ * @supported: flag for vrr support based on checking for VRRmin and
+ * VRRmax values having correct values.
+ */
+ bool supported;
+};
+
/**
* struct drm_hdmi_dsc_cap - DSC capabilities of HDMI sink
*
@@ -330,6 +368,15 @@ struct drm_hdmi_info {
/** @max_lanes: supported by sink */
u8 max_lanes;
+ /** @fapa_start_location: flag for the FAPA in blanking support */
+ bool fapa_start_location;
+
+ /** @allm: flag for Auto Low Latency Mode support by sink */
+ bool allm;
+
+ /** @vrr_cap: VRR capabilities of the sink */
+ struct drm_hdmi_vrr_cap vrr_cap;
+
/** @dsc_cap: DSC capabilities of the sink */
struct drm_hdmi_dsc_cap dsc_cap;
};
--
2.53.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* Re: [PATCH v4 2/4] drm/edid: parse HDMI 2.1 gaming (ALLM/VRR) capabilities from HF-VSDB
2026-08-14 16:43 ` [PATCH v4 2/4] drm/edid: parse HDMI 2.1 gaming (ALLM/VRR) capabilities from HF-VSDB Fangzhi Zuo
@ 2026-08-14 16:49 ` sashiko-bot
0 siblings, 0 replies; 43+ messages in thread
From: sashiko-bot @ 2026-08-14 16:49 UTC (permalink / raw)
To: Fangzhi Zuo; +Cc: dri-devel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Kerneldoc comments for `struct drm_hdmi_vrr_cap` refer to non-existent fields `@mcnmvrr` and `@mcinema_vrr` instead of `cnmvrr` and `cinema_vrr`, and contain minor typos.
--
--- Patch [2]: [PATCH v4 2/4] drm/edid: parse HDMI 2.1 gaming (ALLM/VRR) capabilities from HF-VSDB ---
commit c7bd732acb69a8a5eeca4f1e80e71d88085a1ae5
Author: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
drm/edid: parse HDMI 2.1 gaming (ALLM/VRR) capabilities from HF-VSDB
This commit parses the HDMI 2.1 gaming-related capabilities from the HDMI
Forum VSDB (HF-VSDB). It exposes them through struct drm_hdmi_info and
adds a new struct drm_hdmi_vrr_cap to describe VRR capabilities.
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index cd06a3b914a03..9f8f109c2dd1f 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -254,6 +254,44 @@ struct drm_scdc {
> struct drm_scrambling scrambling;
> };
>
> +/**
> + * struct drm_hdmi_vrr_cap - Information about VRR capabilities of a HDMI sink
> + *
> + * Describes the VRR support provided by HDMI 2.1 sink. The information is
> + * fetched fom additional HFVSDB blocks defined for HDMI 2.1.
[Severity: Low]
This isn't a bug, but there is a typo here ("fom" instead of "from").
> + */
> +struct drm_hdmi_vrr_cap {
> + /** @fva: flag for Fast VActive (Quick Frame Transport) support */
> + bool fva;
> +
> + /** @mcnmvrr: flag for Negative M VRR support */
> + bool cnmvrr;
[Severity: Low]
This isn't a bug, but does this kerneldoc mismatch the field name?
The documentation uses @mcnmvrr while the field is named cnmvrr.
> +
> + /** @mcinema_vrr: flag for Cinema VRR support */
> + bool cinema_vrr;
[Severity: Low]
This isn't a bug, but similarly here, the kerneldoc uses @mcinema_vrr
instead of cinema_vrr.
> +
> + /** @mdelta: flag for limited frame-to-frame compensation support */
> + bool mdelta;
> +
> + /**
> + * @vrr_min : minimum supported variable refresh rate in Hz.
> + * Valid values only inide 1 - 48 range
[Severity: Low]
This isn't a bug, but there is a typo here ("inide" instead of "inside").
> + */
> + u16 vrr_min;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260814164344.3098143-1-jerry.zuo@amd.com?part=2
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH v4 3/4] drm/amd/display: Add HDMI 2.1 VRR support from HF-VSDB
2026-08-14 16:43 ` [PATCH v4 0/4] HDMI 2.1 VRR and " Fangzhi Zuo
2026-08-14 16:43 ` [PATCH v4 1/4] drm/amd/display: Add 2.1 FreeSync support for AMD VSDB EDID Block Fangzhi Zuo
2026-08-14 16:43 ` [PATCH v4 2/4] drm/edid: parse HDMI 2.1 gaming (ALLM/VRR) capabilities from HF-VSDB Fangzhi Zuo
@ 2026-08-14 16:43 ` Fangzhi Zuo
2026-08-14 16:55 ` sashiko-bot
2026-08-14 16:43 ` [PATCH v4 4/4] drm/amd/display: Enable HDMI ALLM for Gaming-VRR Fangzhi Zuo
3 siblings, 1 reply; 43+ messages in thread
From: Fangzhi Zuo @ 2026-08-14 16:43 UTC (permalink / raw)
To: amd-gfx
Cc: dri-devel, Harry Wentland, Tomasz Pakuła, daniel,
Fangzhi Zuo, Fangzhi Zuo
why:
HDMI 2.1 sinks advertise their VRR range in the HDMI Forum VSDB
(HF-VSDB), but amdgpu derived FreeSync capability only from the AMD
VSDB. Sinks that expose just the HDMI Forum VRR capability (e.g. HDMI
compliance EDIDs) were therefore reported as not VRR capable.
how:
- In amdgpu_dm_update_freesync_caps(), when the AMD VSDB does not
provide a valid FreeSync range, fall back to the HDMI 2.1 VRR range
parsed by DRM core from the HF-VSDB
(connector->display_info.hdmi.vrr_cap). VRRMAX = 0 means "up to the
Base Refresh Rate"; when the EDID provides no monitor range maximum
either, fall back to the Base Refresh Rate (the highest refresh-rate
mode of the preferred timing) so a valid VRR range is still reported
to userspace.
- Add VRR debug logging along the FreeSync capability and config paths.
Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com>
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
---
.../display/amdgpu_dm/amdgpu_dm_connector.c | 67 +++++++++++++++++++
.../display/amdgpu_dm/amdgpu_dm_freesync.c | 8 +++
2 files changed, 75 insertions(+)
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 9eaa20ec528e..2fe7bfb1e88f 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
@@ -3812,6 +3812,15 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
if (!adev->dm.freesync_module || !dc_supports_vrr(sink->ctx->dce_version))
goto update;
+ drm_dbg_driver(adev_to_drm(adev),
+ "VRR: enter signal=%d hdmi_vrr=%d mrange[%d-%d] hdmi.vrr_cap[sup=%d min=%d max=%d]\n",
+ sink->sink_signal, connector->display_info.hdmi.vrr_cap.supported,
+ connector->display_info.monitor_range.min_vfreq,
+ connector->display_info.monitor_range.max_vfreq,
+ connector->display_info.hdmi.vrr_cap.supported,
+ connector->display_info.hdmi.vrr_cap.vrr_min,
+ connector->display_info.hdmi.vrr_cap.vrr_max);
+
/* FIXME: Get rid of drm_edid_raw() */
edid = drm_edid_raw(drm_edid);
@@ -3856,6 +3865,59 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
connector->display_info.monitor_range.max_vfreq = vsdb_info.max_refresh_rate_hz;
}
}
+
+ drm_dbg_driver(adev_to_drm(adev),
+ "VRR: amd_vsdb i=%d fs_sup=%d min=%d max=%d fs_capable=%d\n",
+ i, vsdb_info.freesync_supported,
+ vsdb_info.min_refresh_rate_hz,
+ vsdb_info.max_refresh_rate_hz, freesync_capable);
+
+ /*
+ * If AMD VSDB didn't provide a valid FreeSync range, fall back to
+ * the HDMI 2.1 VRR capability parsed from the HF-VSDB.
+ */
+ if (!freesync_capable && connector->display_info.hdmi.vrr_cap.supported) {
+ struct drm_hdmi_vrr_cap *vrr_cap =
+ &connector->display_info.hdmi.vrr_cap;
+
+ drm_dbg_driver(adev_to_drm(adev),
+ "VRR: HF-VSDB fallback: hdmi_vrr=1 vrr_cap[sup=%d min=%d max=%d] mrange_max=%d\n",
+ vrr_cap->supported, vrr_cap->vrr_min, vrr_cap->vrr_max,
+ connector->display_info.monitor_range.max_vfreq);
+
+ if (vrr_cap->supported && vrr_cap->vrr_min > 0) {
+ amdgpu_dm_connector->min_vfreq = vrr_cap->vrr_min;
+ amdgpu_dm_connector->max_vfreq = vrr_cap->vrr_max ?
+ vrr_cap->vrr_max :
+ connector->display_info.monitor_range.max_vfreq;
+
+ /*
+ * VRRMAX = 0 in the HF-VSDB means "up to the Base
+ * Refresh Rate". If the EDID also did not provide a
+ * monitor range max, fall back to the Base Refresh
+ * Rate (the highest refresh rate of the preferred
+ * timing) so a valid VRR range is still reported to
+ * userspace.
+ */
+ if (!amdgpu_dm_connector->max_vfreq) {
+ struct drm_display_mode *brr_mode =
+ amdgpu_dm_get_highest_refresh_rate_mode(amdgpu_dm_connector, true);
+
+ if (brr_mode)
+ amdgpu_dm_connector->max_vfreq =
+ drm_mode_vrefresh(brr_mode);
+ }
+
+ if (amdgpu_dm_connector->max_vfreq -
+ amdgpu_dm_connector->min_vfreq > 10)
+ freesync_capable = true;
+
+ connector->display_info.monitor_range.min_vfreq =
+ amdgpu_dm_connector->min_vfreq;
+ connector->display_info.monitor_range.max_vfreq =
+ amdgpu_dm_connector->max_vfreq;
+ }
+ }
}
if (amdgpu_dm_connector->dc_link)
@@ -3911,6 +3973,11 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
if (dm_con_state)
dm_con_state->freesync_capable = freesync_capable;
+ drm_dbg_driver(adev_to_drm(adev),
+ "VRR: caps result: freesync_capable=%d min_vfreq=%d max_vfreq=%d\n",
+ freesync_capable, amdgpu_dm_connector->min_vfreq,
+ amdgpu_dm_connector->max_vfreq);
+
if (connector->state && amdgpu_dm_connector->dc_link && !freesync_capable &&
amdgpu_dm_connector->dc_link->replay_settings.config.replay_supported) {
amdgpu_dm_connector->dc_link->replay_settings.config.replay_supported = false;
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 035d7e88c3ed..382c339b67b1 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
@@ -152,6 +152,14 @@ void amdgpu_dm_get_freesync_config_for_crtc(
}
out:
new_crtc_state->freesync_config = config;
+
+ drm_dbg_driver(new_con_state->base.connector->dev,
+ "VRR: cfg vrr_enabled=%d vrr_supported=%d fs_capable=%d vrefresh=%d min=%d max=%d state=%d\n",
+ new_crtc_state->base.vrr_enabled,
+ new_crtc_state->vrr_supported,
+ new_con_state->freesync_capable, vrefresh,
+ aconnector->min_vfreq, aconnector->max_vfreq,
+ config.state);
}
EXPORT_IF_KUNIT(amdgpu_dm_get_freesync_config_for_crtc);
--
2.53.0
^ permalink raw reply related [flat|nested] 43+ messages in thread* Re: [PATCH v4 3/4] drm/amd/display: Add HDMI 2.1 VRR support from HF-VSDB
2026-08-14 16:43 ` [PATCH v4 3/4] drm/amd/display: Add HDMI 2.1 VRR support " Fangzhi Zuo
@ 2026-08-14 16:55 ` sashiko-bot
0 siblings, 0 replies; 43+ messages in thread
From: sashiko-bot @ 2026-08-14 16:55 UTC (permalink / raw)
To: Fangzhi Zuo; +Cc: dri-devel
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
New issues:
- [High] The HF-VSDB VRR fallback is negated for HDMI TMDS connections due to a pre-existing AMD FreeSync MCCS check resetting `freesync_capable` to `false`.
Pre-existing issues:
- [High] The highest refresh rate mode cache (`freesync_vid_base`) is never invalidated across hotplugs, corrupting `max_vfreq` calculations for subsequently connected displays.
--
--- Patch [3]: [PATCH v4 3/4] drm/amd/display: Add HDMI 2.1 VRR support from HF-VSDB ---
commit cf4d7fc4ac615fcafd91467c91d4c4582773cd6b
Author: Fangzhi Zuo <jerry.zuo@amd.com>
drm/amd/display: Add HDMI 2.1 VRR support from HF-VSDB
This commit updates the FreeSync capabilities logic to fall back to the
HDMI 2.1 VRR range parsed from the HF-VSDB when the AMD VSDB does not
provide a valid range.
> 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 9eaa20ec528ec..2fe7bfb1e88f7 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
[ ... ]
> @@ -3856,6 +3865,59 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
> connector->display_info.monitor_range.max_vfreq = vsdb_info.max_refresh_rate_hz;
> }
> }
> +
> + drm_dbg_driver(adev_to_drm(adev),
> + "VRR: amd_vsdb i=%d fs_sup=%d min=%d max=%d fs_capable=%d\n",
> + i, vsdb_info.freesync_supported,
> + vsdb_info.min_refresh_rate_hz,
> + vsdb_info.max_refresh_rate_hz, freesync_capable);
> +
> + /*
> + * If AMD VSDB didn't provide a valid FreeSync range, fall back to
> + * the HDMI 2.1 VRR capability parsed from the HF-VSDB.
> + */
> + if (!freesync_capable && connector->display_info.hdmi.vrr_cap.supported) {
> + struct drm_hdmi_vrr_cap *vrr_cap =
> + &connector->display_info.hdmi.vrr_cap;
> +
> + drm_dbg_driver(adev_to_drm(adev),
> + "VRR: HF-VSDB fallback: hdmi_vrr=1 vrr_cap[sup=%d min=%d max=%d] mrange_max=%d\n",
> + vrr_cap->supported, vrr_cap->vrr_min, vrr_cap->vrr_max,
> + connector->display_info.monitor_range.max_vfreq);
> +
> + if (vrr_cap->supported && vrr_cap->vrr_min > 0) {
> + amdgpu_dm_connector->min_vfreq = vrr_cap->vrr_min;
> + amdgpu_dm_connector->max_vfreq = vrr_cap->vrr_max ?
> + vrr_cap->vrr_max :
> + connector->display_info.monitor_range.max_vfreq;
> +
> + /*
> + * VRRMAX = 0 in the HF-VSDB means "up to the Base
> + * Refresh Rate". If the EDID also did not provide a
> + * monitor range max, fall back to the Base Refresh
> + * Rate (the highest refresh rate of the preferred
> + * timing) so a valid VRR range is still reported to
> + * userspace.
> + */
> + if (!amdgpu_dm_connector->max_vfreq) {
> + struct drm_display_mode *brr_mode =
> + amdgpu_dm_get_highest_refresh_rate_mode(amdgpu_dm_connector, true);
[Severity: High]
This is a pre-existing issue, but does amdgpu_dm_get_highest_refresh_rate_mode()
return stale data across hotplugs?
It appears aconnector->freesync_vid_base is never cleared on hotplug:
amdgpu_dm_get_highest_refresh_rate_mode() {
...
if (aconnector->freesync_vid_base.clock != 0)
return &aconnector->freesync_vid_base;
...
}
If a high-refresh monitor is unplugged and an HDMI 2.1 VRR monitor with
VRRMAX = 0 is plugged into the same port, will this use the cached
high-refresh mode of the disconnected monitor and calculate an incorrect
max_vfreq?
> +
> + if (brr_mode)
> + amdgpu_dm_connector->max_vfreq =
> + drm_mode_vrefresh(brr_mode);
> + }
> +
> + if (amdgpu_dm_connector->max_vfreq -
> + amdgpu_dm_connector->min_vfreq > 10)
> + freesync_capable = true;
[Severity: High]
Does this new fallback get negated later in amdgpu_dm_update_freesync_caps()
for HDMI TMDS connections?
When an HDMI monitor without an AMD VSDB is connected, freesync_vcp_code
remains 0. Later in this same function, the pre-existing MCCS check does this:
if ((sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A ||
as_type == FREESYNC_TYPE_PCON_IN_WHITELIST) &&
(!sink->edid_caps.freesync_vcp_code ||
(sink->edid_caps.freesync_vcp_code && !sink->mccs_caps.freesync_supported)))
freesync_capable = false;
Since !sink->edid_caps.freesync_vcp_code evaluates to true for TMDS,
could this prevent the HF-VSDB fallback from working for these displays?
> +
> + connector->display_info.monitor_range.min_vfreq =
> + amdgpu_dm_connector->min_vfreq;
> + connector->display_info.monitor_range.max_vfreq =
> + amdgpu_dm_connector->max_vfreq;
> + }
> + }
> }
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260814164344.3098143-1-jerry.zuo@amd.com?part=3
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH v4 4/4] drm/amd/display: Enable HDMI ALLM for Gaming-VRR
2026-08-14 16:43 ` [PATCH v4 0/4] HDMI 2.1 VRR and " Fangzhi Zuo
` (2 preceding siblings ...)
2026-08-14 16:43 ` [PATCH v4 3/4] drm/amd/display: Add HDMI 2.1 VRR support " Fangzhi Zuo
@ 2026-08-14 16:43 ` Fangzhi Zuo
2026-08-14 17:01 ` sashiko-bot
3 siblings, 1 reply; 43+ messages in thread
From: Fangzhi Zuo @ 2026-08-14 16:43 UTC (permalink / raw)
To: amd-gfx
Cc: dri-devel, Harry Wentland, Tomasz Pakuła, daniel,
Fangzhi Zuo, Fangzhi Zuo
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 <Jerry.Zuo@amd.com>
---
.../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
^ permalink raw reply related [flat|nested] 43+ messages in thread* Re: [PATCH v4 4/4] drm/amd/display: Enable HDMI ALLM for Gaming-VRR
2026-08-14 16:43 ` [PATCH v4 4/4] drm/amd/display: Enable HDMI ALLM for Gaming-VRR Fangzhi Zuo
@ 2026-08-14 17:01 ` sashiko-bot
0 siblings, 0 replies; 43+ messages in thread
From: sashiko-bot @ 2026-08-14 17:01 UTC (permalink / raw)
To: Fangzhi Zuo; +Cc: dri-devel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Overloading `vsp_infopacket` with the HDMI Forum VSIF (HF-VSIF) overwrites the standard HDMI 1.4 VSIF, silently dropping the HDMI VIC required for certain modes.
--
--- Patch [4]: [PATCH v4 4/4] drm/amd/display: Enable HDMI ALLM for Gaming-VRR ---
commit d9e1d834d57e6ab1f6bb6abbfa9007cc7a9851fc
Author: Fangzhi Zuo <jerry.zuo@amd.com>
drm/amd/display: Enable HDMI ALLM for Gaming-VRR
This commit enables Auto Low-Latency Mode (ALLM) by setting ALLM_Mode=1
in the HF-VSIF when Gaming-VRR is active. It transmits the updated HF-VSIF
as a stream update when the sink advertises ALLM support.
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> --- 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;
[Severity: High]
Does updating the stream using vsp_infopacket drop the standard HDMI Vendor
Specific InfoFrame (VSIF)?
The dc_stream_state structure has a separate hfvsif_infopacket member that
might be intended for the HF-VSIF payload instead of overloading the
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
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.c
[ ... ]
> + 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;
[Severity: High]
Does storing the HF-VSIF inside the vsp_infopacket slot overwrite the
standard HDMI 1.4 VSIF?
When ALLM is active, this assignment appears to silently overwrite the VSIF
designated for HDMI 1.4, which can result in the display losing format
information like the hdmi_vic required for certain modes.
Looking at resource_build_info_frame() in dc_resource.c, the hardware
explicitly supports transmitting both the standard VSIF and the HF-VSIF
simultaneously via separate slots:
dc/core/dc_resource.c:resource_build_info_frame() {
...
set_vendor_info_packet(&info->vendor, pipe_ctx->stream);
set_hfvs_info_packet(&info->hfvsif, pipe_ctx->stream);
...
}
Should this code instead populate the hfvsif_infopacket member of new_stream?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260814164344.3098143-1-jerry.zuo@amd.com?part=4
^ permalink raw reply [flat|nested] 43+ messages in thread