summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorIvan Lipski <ivan.lipski@amd.com>2026-09-24 14:15:52 -0400
committerAlex Deucher <alexander.deucher@amd.com>2026-10-07 12:07:35 -0400
commit123e9515f7e05c694d8abc6f786aecd457aab2f3 (patch)
tree8faf9f1bc18aeb7a80c94d9fe52646698fe8bcb5 /drivers/gpu
parente476b30d67743f1af00d8bc92189af4070a73906 (diff)
downloadlinux-123e9515f7e05c694d8abc6f786aecd457aab2f3.tar.gz
linux-123e9515f7e05c694d8abc6f786aecd457aab2f3.zip
drm/amd/display: Send HDMI VRR metadata in VTEM info packet slot
[Why] Brief blank on HDMI each time VRR engaged and disengaged, with no modeset at either transition. amdgpu_dm_update_freesync_state_on_stream() built the VTEM on top of the buffer holding the AMD FreeSync SPD payload, which becomes stream->vrr_infopacket. DC routes that to HDMI generic slot 3 (SPD) and vtem_infopacket to slot 6 (VTEM), and vtem_infopacket was never populated. So slot 3 carried a VTEM payload the sink parsed as an SPD InfoFrame, no VTEM was sent, and v_total varied with no valid metadata describing it. DP uses the VSC/AS-SDP path and is unaffected. [How] Build the VTEM into a separate vtem_infopacket, gated on the sink not advertising AMD FreeSync. Track it in dm_crtc_state, include it in the freesync_vrr_info_changed comparison and the reset path, and pass it through bundle->stream_update.vtem_infopacket. Reviewed-by: Jerry Zuo <jerry.zuo@amd.com> Signed-off-by: Ivan Lipski <ivan.lipski@amd.com> Signed-off-by: Roman Li <roman.li@amd.com> Tested-by: Dan Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c2
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h1
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.c26
3 files changed, 24 insertions, 5 deletions
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 1e63e4157408..284edb404125 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -4150,6 +4150,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_commit *state,
if (acrtc_state->freesync_vrr_info_changed) {
bundle->stream_update.vrr_infopacket =
&acrtc_state->stream->vrr_infopacket;
+ bundle->stream_update.vtem_infopacket =
+ &acrtc_state->stream->vtem_infopacket;
bundle->stream_update.vsp_infopacket =
&acrtc_state->stream->vsp_infopacket;
stream_update_needed = true;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index 0143b42fa2bd..1b91fe4c3171 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -1076,6 +1076,7 @@ struct dm_crtc_state {
bool vrr_supported;
struct mod_freesync_config freesync_config;
struct dc_info_packet vrr_infopacket;
+ struct dc_info_packet vtem_infopacket;
int abm_level;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.c
index e8ae238bbb69..ab9cfbce8d73 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.c
@@ -107,6 +107,8 @@ void amdgpu_dm_reset_freesync_config_for_crtc(
memset(&new_crtc_state->vrr_infopacket, 0,
sizeof(new_crtc_state->vrr_infopacket));
+ memset(&new_crtc_state->vtem_infopacket, 0,
+ sizeof(new_crtc_state->vtem_infopacket));
}
EXPORT_IF_KUNIT(amdgpu_dm_reset_freesync_config_for_crtc);
@@ -172,6 +174,7 @@ void amdgpu_dm_update_freesync_state_on_stream(
{
struct mod_vrr_params vrr_params;
struct dc_info_packet vrr_infopacket = {0};
+ struct dc_info_packet vtem_infopacket = {0};
struct amdgpu_device *adev = dm->adev;
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(new_crtc_state->base.crtc);
unsigned long flags;
@@ -238,21 +241,34 @@ void amdgpu_dm_update_freesync_state_on_stream(
&vrr_infopacket,
pack_sdp_v1_3);
- /* Per HDMI 2.1, VTEM is valid on TMDS as well as FRL */
- if (new_stream->signal == SIGNAL_TYPE_HDMI_FRL ||
- (new_stream->signal == SIGNAL_TYPE_HDMI_TYPE_A &&
- aconn && aconn->base.display_info.hdmi.vrr_cap.supported))
- mod_build_infopacket_vtem(new_stream, &vrr_params, 0, &vrr_infopacket);
+ /*
+ * If the sink does not support FreeSync, but it does support VRR,
+ * we need to build a VTEM packet to enable VRR.
+ */
+ if (aconn && !aconn->vsdb_info.freesync_supported &&
+ aconn->base.display_info.hdmi.vrr_cap.supported &&
+ (new_stream->signal == SIGNAL_TYPE_HDMI_FRL ||
+ new_stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)) {
+ mod_build_infopacket_vtem(new_stream, &vrr_params, 0, &vtem_infopacket);
+ memset(&vrr_infopacket, 0, sizeof(vrr_infopacket));
+ }
new_crtc_state->freesync_vrr_info_changed |=
(memcmp(&new_crtc_state->vrr_infopacket,
&vrr_infopacket,
sizeof(vrr_infopacket)) != 0);
+ new_crtc_state->freesync_vrr_info_changed |=
+ (memcmp(&new_crtc_state->vtem_infopacket,
+ &vtem_infopacket,
+ sizeof(vtem_infopacket)) != 0);
+
acrtc->dm_irq_params.vrr_params = vrr_params;
new_crtc_state->vrr_infopacket = vrr_infopacket;
+ new_crtc_state->vtem_infopacket = vtem_infopacket;
new_stream->vrr_infopacket = vrr_infopacket;
+ new_stream->vtem_infopacket = vtem_infopacket;
new_stream->allow_freesync = mod_freesync_get_freesync_enabled(&vrr_params);
/*