From: Ivan Lipski <[email protected]> [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 <[email protected]> Signed-off-by: Ivan Lipski <[email protected]> Signed-off-by: Roman Li <[email protected]> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 ++ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 1 + .../display/amdgpu_dm/amdgpu_dm_freesync.c | 26 +++++++++++++++---- 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 6e5dbe0bd82e..f3ed3fef59f9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4141,6 +4141,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 2ead9bc8e439..594d275918d5 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 1d9148ccfd4f..f4ce389fd0aa 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_SYMBOL_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); /* -- 2.34.1
