[PATCH 16/49] drm/amd/display: add FreeSync/VRR module

Fangzhi Zuo <[email protected]>
Newsgroups org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>
From: Alex Hung <[email protected]>

[WHAT]
Group the FreeSync/VRR helpers from amdgpu_dm.c into a dedicated
amdgpu_dm_freesync.c and amdgpu_dm_freesync.h. The moved functions are:

  is_dc_timing_adjust_needed, is_timing_unchanged_for_freesync,
  set_freesync_fixed_config, reset_freesync_config_for_crtc,
  get_freesync_config_for_crtc, update_freesync_state_on_stream,
  update_stream_irq_parameters, amdgpu_dm_handle_vrr_transition.

The FreeSync/VRR helpers exposed by amdgpu_dm_freesync.h are called
from amdgpu_dm.c, so give the seven that lacked a namespace prefix the
standard amdgpu_dm_ prefix:

Relocate the corresponding KUnit tests into amdgpu_dm_freesync_test.c.

No functional change.

Reviewed-by: Bhawanpreet Lakha <[email protected]>
Signed-off-by: Alex Hung <[email protected]>
Signed-off-by: Fangzhi Zuo <[email protected]>
Tested-by: Dan Wheeler <[email protected]>
---
 .../gpu/drm/amd/display/amdgpu_dm/Makefile    |   3 +-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 349 +-------------
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |   8 -
 .../display/amdgpu_dm/amdgpu_dm_freesync.c    | 362 ++++++++++++++
 .../display/amdgpu_dm/amdgpu_dm_freesync.h    |  65 +++
 .../drm/amd/display/amdgpu_dm/tests/Makefile  |   1 +
 .../amdgpu_dm/tests/amdgpu_dm_freesync_test.c | 453 ++++++++++++++++++
 .../display/amdgpu_dm/tests/amdgpu_dm_test.c  | 417 ----------------
 8 files changed, 894 insertions(+), 764 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.c
 create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.h
 create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_freesync_test.c

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
index d83878e35b61..5cb8c143e72f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
@@ -45,7 +45,8 @@ AMDGPUDM = \
 	amdgpu_dm_backlight.o \
 	amdgpu_dm_audio.o \
 	amdgpu_dm_dmub.o \
-	amdgpu_dm_connector.o
+	amdgpu_dm_connector.o \
+	amdgpu_dm_freesync.o
 
 ifdef CONFIG_DRM_AMD_DC_FP
 AMDGPUDM += dc_fpu.o
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 dfc16f5e415a..c36eb8a1d2d1 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -71,6 +71,7 @@
 #include "amdgpu_dm_dmub.h"
 #include "amdgpu_dm_connector.h"
 #include "amdgpu_dm_pp_smu.h"
+#include "amdgpu_dm_freesync.h"
 
 #include "ivsrcid/ivsrcid_vislands30.h"
 
@@ -127,7 +128,6 @@ MODULE_FIRMWARE(FIRMWARE_NAVI12_DMCU);
 /* basic init/fini API */
 static int amdgpu_dm_init(struct amdgpu_device *adev);
 static void amdgpu_dm_fini(struct amdgpu_device *adev);
-STATIC_IFN_KUNIT void reset_freesync_config_for_crtc(struct dm_crtc_state *new_crtc_state);
 
 /*
  * initializes drm_device display related structures, based on the information
@@ -147,10 +147,6 @@ STATIC_IFN_KUNIT void dm_enable_per_frame_crtc_master_sync(struct dc_state *cont
 static int amdgpu_dm_atomic_check(struct drm_device *dev,
 				  struct drm_atomic_commit *state);
 
-STATIC_IFN_KUNIT bool
-is_timing_unchanged_for_freesync(struct drm_crtc_state *old_crtc_state,
-				 struct drm_crtc_state *new_crtc_state);
-
 static inline void amdgpu_dm_exit_ips_for_hw_access(struct dc *dc)
 {
 	if (dc->ctx->dmub_srv && !dc->ctx->dmub_srv->idle_exit_counter)
@@ -248,20 +244,6 @@ STATIC_IFN_KUNIT int dm_soft_reset(struct amdgpu_ip_block *ip_block)
 }
 EXPORT_IF_KUNIT(dm_soft_reset);
 
-STATIC_IFN_KUNIT bool is_dc_timing_adjust_needed(struct dm_crtc_state *old_state,
-						 struct dm_crtc_state *new_state)
-{
-	if (new_state->stream->adjust.timing_adjust_pending)
-		return true;
-	if (new_state->freesync_config.state ==  VRR_STATE_ACTIVE_FIXED)
-		return true;
-	else if (amdgpu_dm_crtc_vrr_active(old_state) != amdgpu_dm_crtc_vrr_active(new_state))
-		return true;
-	else
-		return false;
-}
-EXPORT_IF_KUNIT(is_dc_timing_adjust_needed);
-
 /*
  * DC will program planes with their z-order determined by their ordering
  * in the dc_surface_updates array. This comparator is used to sort them
@@ -1542,7 +1524,7 @@ static void dm_destroy_cached_state(struct amdgpu_device *adev)
 	for_each_new_crtc_in_state(dm->cached_state, crtc, new_crtc_state, i) {
 		new_crtc_state->active_changed = true;
 		dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
-		reset_freesync_config_for_crtc(dm_new_crtc_state);
+		amdgpu_dm_reset_freesync_config_for_crtc(dm_new_crtc_state);
 	}
 
 	/*
@@ -3614,213 +3596,6 @@ static void prepare_flip_isr(struct amdgpu_crtc *acrtc)
 		      acrtc->crtc_id);
 }
 
-static void update_freesync_state_on_stream(
-	struct amdgpu_display_manager *dm,
-	struct dm_crtc_state *new_crtc_state,
-	struct dc_stream_state *new_stream,
-	struct dc_plane_state *surface,
-	u32 flip_timestamp_in_us)
-{
-	struct mod_vrr_params vrr_params;
-	struct dc_info_packet vrr_infopacket = {0};
-	struct amdgpu_device *adev = dm->adev;
-	struct amdgpu_crtc *acrtc = to_amdgpu_crtc(new_crtc_state->base.crtc);
-	unsigned long flags;
-	bool pack_sdp_v1_3 = false;
-	struct amdgpu_dm_connector *aconn;
-	enum vrr_packet_type packet_type = PACKET_TYPE_VRR;
-
-	if (!new_stream)
-		return;
-
-	/*
-	 * TODO: Determine why min/max totals and vrefresh can be 0 here.
-	 * For now it's sufficient to just guard against these conditions.
-	 */
-
-	if (!new_stream->timing.h_total || !new_stream->timing.v_total)
-		return;
-
-	spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
-	vrr_params = acrtc->dm_irq_params.vrr_params;
-
-	if (surface) {
-		mod_freesync_handle_preflip(
-			dm->freesync_module,
-			surface,
-			new_stream,
-			flip_timestamp_in_us,
-			&vrr_params);
-
-		if (adev->family < AMDGPU_FAMILY_AI &&
-		    amdgpu_dm_crtc_vrr_active(new_crtc_state)) {
-			mod_freesync_handle_v_update(dm->freesync_module,
-						     new_stream, &vrr_params);
-
-			/* Need to call this before the frame ends. */
-			dc_stream_adjust_vmin_vmax(dm->dc,
-						   new_crtc_state->stream,
-						   &vrr_params.adjust);
-		}
-	}
-
-	aconn = (struct amdgpu_dm_connector *)new_stream->dm_stream_context;
-
-	if (aconn && (aconn->as_type == FREESYNC_TYPE_PCON_IN_WHITELIST || aconn->vsdb_info.replay_mode)) {
-		pack_sdp_v1_3 = aconn->pack_sdp_v1_3;
-
-		if (aconn->vsdb_info.amd_vsdb_version == 1)
-			packet_type = PACKET_TYPE_FS_V1;
-		else if (aconn->vsdb_info.amd_vsdb_version == 2)
-			packet_type = PACKET_TYPE_FS_V2;
-		else if (aconn->vsdb_info.amd_vsdb_version == 3)
-			packet_type = PACKET_TYPE_FS_V3;
-
-		mod_build_adaptive_sync_infopacket(new_stream, aconn->as_type, NULL,
-					&new_stream->adaptive_sync_infopacket);
-	}
-
-	mod_freesync_build_vrr_infopacket(
-		dm->freesync_module,
-		new_stream,
-		&vrr_params,
-		packet_type,
-		TRANSFER_FUNC_UNKNOWN,
-		&vrr_infopacket,
-		pack_sdp_v1_3);
-
-	new_crtc_state->freesync_vrr_info_changed |=
-		(memcmp(&new_crtc_state->vrr_infopacket,
-			&vrr_infopacket,
-			sizeof(vrr_infopacket)) != 0);
-
-	acrtc->dm_irq_params.vrr_params = vrr_params;
-	new_crtc_state->vrr_infopacket = vrr_infopacket;
-
-	new_stream->vrr_infopacket = vrr_infopacket;
-	new_stream->allow_freesync = mod_freesync_get_freesync_enabled(&vrr_params);
-
-	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,
-			      (int)new_crtc_state->base.vrr_enabled,
-			      (int)vrr_params.state);
-
-	spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
-}
-
-static void update_stream_irq_parameters(
-	struct amdgpu_display_manager *dm,
-	struct dm_crtc_state *new_crtc_state)
-{
-	struct dc_stream_state *new_stream = new_crtc_state->stream;
-	struct mod_vrr_params vrr_params;
-	struct mod_freesync_config config = new_crtc_state->freesync_config;
-	struct amdgpu_device *adev = dm->adev;
-	struct amdgpu_crtc *acrtc = to_amdgpu_crtc(new_crtc_state->base.crtc);
-	unsigned long flags;
-
-	if (!new_stream)
-		return;
-
-	/*
-	 * TODO: Determine why min/max totals and vrefresh can be 0 here.
-	 * For now it's sufficient to just guard against these conditions.
-	 */
-	if (!new_stream->timing.h_total || !new_stream->timing.v_total)
-		return;
-
-	spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
-	vrr_params = acrtc->dm_irq_params.vrr_params;
-
-	if (new_crtc_state->vrr_supported &&
-	    config.min_refresh_in_uhz &&
-	    config.max_refresh_in_uhz) {
-		/*
-		 * if freesync compatible mode was set, config.state will be set
-		 * in atomic check
-		 */
-		if (config.state == VRR_STATE_ACTIVE_FIXED && config.fixed_refresh_in_uhz &&
-		    (!drm_atomic_crtc_needs_modeset(&new_crtc_state->base) ||
-		     new_crtc_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED)) {
-			vrr_params.max_refresh_in_uhz = config.max_refresh_in_uhz;
-			vrr_params.min_refresh_in_uhz = config.min_refresh_in_uhz;
-			vrr_params.fixed_refresh_in_uhz = config.fixed_refresh_in_uhz;
-			vrr_params.state = VRR_STATE_ACTIVE_FIXED;
-		} else {
-			config.state = new_crtc_state->base.vrr_enabled ?
-						     VRR_STATE_ACTIVE_VARIABLE :
-						     VRR_STATE_INACTIVE;
-		}
-	} else {
-		config.state = VRR_STATE_UNSUPPORTED;
-	}
-
-	mod_freesync_build_vrr_params(dm->freesync_module,
-				      new_stream,
-				      &config, &vrr_params);
-
-	new_crtc_state->freesync_config = config;
-	/* Copy state for access from DM IRQ handler */
-	acrtc->dm_irq_params.freesync_config = config;
-	acrtc->dm_irq_params.active_planes = new_crtc_state->active_planes;
-	acrtc->dm_irq_params.vrr_params = vrr_params;
-	spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
-}
-
-static void amdgpu_dm_handle_vrr_transition(struct amdgpu_display_manager *dm,
-					    struct dm_crtc_state *old_state,
-					    struct dm_crtc_state *new_state)
-{
-	struct amdgpu_device *adev = dm->adev;
-	bool old_vrr_active = amdgpu_dm_crtc_vrr_active(old_state);
-	bool new_vrr_active = amdgpu_dm_crtc_vrr_active(new_state);
-
-	/* Only DCE gates vupdate on VRR, keep it enabled for DCN */
-	bool vrr_gates_vupdate = amdgpu_ip_version(adev, DCE_HWIP, 0) == 0;
-
-	if (!old_vrr_active && new_vrr_active) {
-		/* Transition VRR inactive -> active:
-		 * While VRR is active, we must not disable vblank irq, as a
-		 * reenable after disable would compute bogus vblank/pflip
-		 * timestamps if it likely happened inside display front-porch.
-		 *
-		 * We also need vupdate irq for the actual core vblank handling
-		 * at end of vblank.
-		 */
-		if (vrr_gates_vupdate)
-			WARN_ON(amdgpu_dm_crtc_set_vupdate_irq(new_state->base.crtc, true) != 0);
-		WARN_ON(drm_crtc_vblank_get(new_state->base.crtc) != 0);
-		drm_dbg_driver(new_state->base.crtc->dev, "%s: crtc=%u VRR off->on: Get vblank ref\n",
-				 __func__, new_state->base.crtc->base.id);
-
-		scoped_guard(mutex, &dm->dc_lock) {
-			dc_exit_ips_for_hw_access(dm->dc);
-			amdgpu_dm_psr_set_event(dm, new_state->stream, true,
-				psr_event_vrr_transition, true);
-			amdgpu_dm_replay_set_event(dm, new_state->stream, true,
-				replay_event_vrr, true);
-		}
-	} else if (old_vrr_active && !new_vrr_active) {
-		/* Transition VRR active -> inactive:
-		 * Allow vblank irq disable again for fixed refresh rate.
-		 */
-		if (vrr_gates_vupdate)
-			WARN_ON(amdgpu_dm_crtc_set_vupdate_irq(new_state->base.crtc, false) != 0);
-		drm_crtc_vblank_put(new_state->base.crtc);
-		drm_dbg_driver(new_state->base.crtc->dev, "%s: crtc=%u VRR on->off: Drop vblank ref\n",
-				 __func__, new_state->base.crtc->base.id);
-
-		scoped_guard(mutex, &dm->dc_lock) {
-			dc_exit_ips_for_hw_access(dm->dc);
-			amdgpu_dm_psr_set_event(dm, new_state->stream, false,
-				psr_event_vrr_transition, false);
-			amdgpu_dm_replay_set_event(dm, new_state->stream, false,
-				replay_event_vrr, false);
-		}
-	}
-}
-
 static void amdgpu_dm_commit_cursors(struct drm_atomic_commit *state)
 {
 	struct drm_plane *plane;
@@ -4177,7 +3952,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_commit *state,
 		}
 
 		if (plane == pcrtc->primary)
-			update_freesync_state_on_stream(
+			amdgpu_dm_update_freesync_state_on_stream(
 				dm,
 				acrtc_state,
 				acrtc_state->stream,
@@ -4295,7 +4070,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_commit *state,
 		 * re-adjust the min/max bounds now that DC doesn't handle this
 		 * as part of commit.
 		 */
-		if (is_dc_timing_adjust_needed(dm_old_crtc_state, acrtc_state)) {
+		if (amdgpu_dm_is_dc_timing_adjust_needed(dm_old_crtc_state, acrtc_state)) {
 			spin_lock_irqsave(&pcrtc->dev->event_lock, flags);
 			dc_stream_adjust_vmin_vmax(
 				dm->dc, acrtc_state->stream,
@@ -5344,7 +5119,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_commit *state)
 		dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
 
 		/* For freesync config update on crtc state and params for irq */
-		update_stream_irq_parameters(dm, dm_new_crtc_state);
+		amdgpu_dm_update_stream_irq_parameters(dm, dm_new_crtc_state);
 
 #ifdef CONFIG_DEBUG_FS
 		spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
@@ -5544,108 +5319,6 @@ static int do_aquire_global_lock(struct drm_device *dev,
 	return ret < 0 ? ret : 0;
 }
 
-STATIC_IFN_KUNIT void get_freesync_config_for_crtc(
-	struct dm_crtc_state *new_crtc_state,
-	struct dm_connector_state *new_con_state)
-{
-	struct mod_freesync_config config = {0};
-	struct amdgpu_dm_connector *aconnector;
-	struct drm_display_mode *mode = &new_crtc_state->base.mode;
-	int vrefresh = drm_mode_vrefresh(mode);
-	bool fs_vid_mode = false;
-
-	if (new_con_state->base.connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
-		return;
-
-	aconnector = to_amdgpu_dm_connector(new_con_state->base.connector);
-
-	new_crtc_state->vrr_supported = new_con_state->freesync_capable &&
-					vrefresh >= aconnector->min_vfreq &&
-					vrefresh <= aconnector->max_vfreq;
-
-	if (new_crtc_state->vrr_supported) {
-		new_crtc_state->stream->ignore_msa_timing_param = true;
-		fs_vid_mode = new_crtc_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED;
-
-		config.min_refresh_in_uhz = aconnector->min_vfreq * 1000000;
-		config.max_refresh_in_uhz = aconnector->max_vfreq * 1000000;
-		config.vsif_supported = true;
-		config.btr = true;
-
-		if (fs_vid_mode) {
-			config.state = VRR_STATE_ACTIVE_FIXED;
-			config.fixed_refresh_in_uhz = new_crtc_state->freesync_config.fixed_refresh_in_uhz;
-			goto out;
-		} else if (new_crtc_state->base.vrr_enabled) {
-			config.state = VRR_STATE_ACTIVE_VARIABLE;
-		} else {
-			config.state = VRR_STATE_INACTIVE;
-		}
-	} else {
-		config.state = VRR_STATE_UNSUPPORTED;
-	}
-out:
-	new_crtc_state->freesync_config = config;
-}
-EXPORT_IF_KUNIT(get_freesync_config_for_crtc);
-
-STATIC_IFN_KUNIT void reset_freesync_config_for_crtc(
-	struct dm_crtc_state *new_crtc_state)
-{
-	new_crtc_state->vrr_supported = false;
-
-	memset(&new_crtc_state->vrr_infopacket, 0,
-	       sizeof(new_crtc_state->vrr_infopacket));
-}
-EXPORT_IF_KUNIT(reset_freesync_config_for_crtc);
-
-STATIC_IFN_KUNIT bool
-is_timing_unchanged_for_freesync(struct drm_crtc_state *old_crtc_state,
-				 struct drm_crtc_state *new_crtc_state)
-{
-	const struct drm_display_mode *old_mode, *new_mode;
-
-	if (!old_crtc_state || !new_crtc_state)
-		return false;
-
-	old_mode = &old_crtc_state->mode;
-	new_mode = &new_crtc_state->mode;
-
-	if (old_mode->clock       == new_mode->clock &&
-	    old_mode->hdisplay    == new_mode->hdisplay &&
-	    old_mode->vdisplay    == new_mode->vdisplay &&
-	    old_mode->htotal      == new_mode->htotal &&
-	    old_mode->vtotal      != new_mode->vtotal &&
-	    old_mode->hsync_start == new_mode->hsync_start &&
-	    old_mode->vsync_start != new_mode->vsync_start &&
-	    old_mode->hsync_end   == new_mode->hsync_end &&
-	    old_mode->vsync_end   != new_mode->vsync_end &&
-	    old_mode->hskew       == new_mode->hskew &&
-	    old_mode->vscan       == new_mode->vscan &&
-	    (old_mode->vsync_end - old_mode->vsync_start) ==
-	    (new_mode->vsync_end - new_mode->vsync_start))
-		return true;
-
-	return false;
-}
-EXPORT_IF_KUNIT(is_timing_unchanged_for_freesync);
-
-STATIC_IFN_KUNIT void set_freesync_fixed_config(struct dm_crtc_state *dm_new_crtc_state)
-{
-	u64 num, den, res;
-	struct drm_crtc_state *new_crtc_state = &dm_new_crtc_state->base;
-
-	dm_new_crtc_state->freesync_config.state = VRR_STATE_ACTIVE_FIXED;
-
-	num = (unsigned long long)new_crtc_state->mode.clock * 1000 * 1000000;
-	den = (unsigned long long)new_crtc_state->mode.htotal *
-	      (unsigned long long)new_crtc_state->mode.vtotal;
-
-	res = div_u64(num, den);
-	dm_new_crtc_state->freesync_config.fixed_refresh_in_uhz = res;
-}
-EXPORT_IF_KUNIT(set_freesync_fixed_config);
-
 static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
 			 struct drm_atomic_commit *state,
 			 struct drm_crtc *crtc,
@@ -5742,7 +5415,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
 		 */
 		if (amdgpu_freesync_vid_mode &&
 		    dm_new_crtc_state->stream &&
-		    is_timing_unchanged_for_freesync(new_crtc_state, old_crtc_state))
+		    amdgpu_dm_is_timing_unchanged_for_freesync(new_crtc_state, old_crtc_state))
 			goto skip_modeset;
 
 		if (dm_new_crtc_state->stream &&
@@ -5784,14 +5457,14 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
 		if (amdgpu_freesync_vid_mode && dm_new_crtc_state->stream &&
 		    dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream) &&
 		    dc_is_stream_scaling_unchanged(new_stream, dm_old_crtc_state->stream) &&
-		    is_timing_unchanged_for_freesync(new_crtc_state,
+		    amdgpu_dm_is_timing_unchanged_for_freesync(new_crtc_state,
 						     old_crtc_state)) {
 			new_crtc_state->mode_changed = false;
 			drm_dbg_driver(adev_to_drm(adev),
 				"Mode change not required for front porch change, setting mode_changed to %d",
 				new_crtc_state->mode_changed);
 
-			set_freesync_fixed_config(dm_new_crtc_state);
+			amdgpu_dm_set_freesync_fixed_config(dm_new_crtc_state);
 
 			goto skip_modeset;
 		} else if (amdgpu_freesync_vid_mode && aconnector &&
@@ -5801,7 +5474,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
 
 			high_mode = amdgpu_dm_get_highest_refresh_rate_mode(aconnector, false);
 			if (!drm_mode_equal(&new_crtc_state->mode, high_mode))
-				set_freesync_fixed_config(dm_new_crtc_state);
+				amdgpu_dm_set_freesync_fixed_config(dm_new_crtc_state);
 		}
 
 		ret = dm_atomic_get_state(state, &dm_state);
@@ -5823,7 +5496,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
 		dc_stream_release(dm_old_crtc_state->stream);
 		dm_new_crtc_state->stream = NULL;
 
-		reset_freesync_config_for_crtc(dm_new_crtc_state);
+		amdgpu_dm_reset_freesync_config_for_crtc(dm_new_crtc_state);
 
 		*lock_and_validation_needed = true;
 
@@ -5911,7 +5584,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
 	}
 
 	/* Update Freesync settings. */
-	get_freesync_config_for_crtc(dm_new_crtc_state,
+	amdgpu_dm_get_freesync_config_for_crtc(dm_new_crtc_state,
 				     dm_new_conn_state);
 
 	return ret;
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 70220997cde9..1ef92a28e3e9 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -1172,16 +1172,8 @@ void dm_get_plane_scale(struct drm_plane_state *plane_state,
 			int *out_plane_scale_w, int *out_plane_scale_h);
 bool is_scaling_state_different(const struct dm_connector_state *dm_state,
 				const struct dm_connector_state *old_dm_state);
-bool is_timing_unchanged_for_freesync(struct drm_crtc_state *old_crtc_state,
-				      struct drm_crtc_state *new_crtc_state);
-void set_freesync_fixed_config(struct dm_crtc_state *dm_new_crtc_state);
-bool is_dc_timing_adjust_needed(struct dm_crtc_state *old_state,
-				struct dm_crtc_state *new_state);
 void set_multisync_trigger_params(struct dc_stream_state *stream);
 void set_master_stream(struct dc_stream_state *stream_set[], int stream_count);
-void reset_freesync_config_for_crtc(struct dm_crtc_state *new_crtc_state);
-void get_freesync_config_for_crtc(struct dm_crtc_state *new_crtc_state,
-				  struct dm_connector_state *new_con_state);
 void dm_enable_per_frame_crtc_master_sync(struct dc_state *context);
 struct hdcp_workqueue;
 bool is_content_protection_different(struct drm_crtc_state *new_crtc_state,
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
new file mode 100644
index 000000000000..7e484adb4120
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.c
@@ -0,0 +1,362 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_vblank.h>
+
+#include "dc.h"
+#include "amdgpu.h"
+#include "amdgpu_dm.h"
+#include "amdgpu_dm_crtc.h"
+#include "amdgpu_dm_psr.h"
+#include "amdgpu_dm_replay.h"
+#include "amdgpu_dm_freesync.h"
+#include "dm_helpers.h"
+#include "modules/inc/mod_freesync.h"
+
+bool amdgpu_dm_is_dc_timing_adjust_needed(struct dm_crtc_state *old_state,
+					  struct dm_crtc_state *new_state)
+{
+	if (new_state->stream->adjust.timing_adjust_pending)
+		return true;
+	if (new_state->freesync_config.state ==  VRR_STATE_ACTIVE_FIXED)
+		return true;
+	else if (amdgpu_dm_crtc_vrr_active(old_state) != amdgpu_dm_crtc_vrr_active(new_state))
+		return true;
+	else
+		return false;
+}
+EXPORT_IF_KUNIT(amdgpu_dm_is_dc_timing_adjust_needed);
+
+bool
+amdgpu_dm_is_timing_unchanged_for_freesync(struct drm_crtc_state *old_crtc_state,
+					   struct drm_crtc_state *new_crtc_state)
+{
+	const struct drm_display_mode *old_mode, *new_mode;
+
+	if (!old_crtc_state || !new_crtc_state)
+		return false;
+
+	old_mode = &old_crtc_state->mode;
+	new_mode = &new_crtc_state->mode;
+
+	if (old_mode->clock       == new_mode->clock &&
+	    old_mode->hdisplay    == new_mode->hdisplay &&
+	    old_mode->vdisplay    == new_mode->vdisplay &&
+	    old_mode->htotal      == new_mode->htotal &&
+	    old_mode->vtotal      != new_mode->vtotal &&
+	    old_mode->hsync_start == new_mode->hsync_start &&
+	    old_mode->vsync_start != new_mode->vsync_start &&
+	    old_mode->hsync_end   == new_mode->hsync_end &&
+	    old_mode->vsync_end   != new_mode->vsync_end &&
+	    old_mode->hskew       == new_mode->hskew &&
+	    old_mode->vscan       == new_mode->vscan &&
+	    (old_mode->vsync_end - old_mode->vsync_start) ==
+	    (new_mode->vsync_end - new_mode->vsync_start))
+		return true;
+
+	return false;
+}
+EXPORT_IF_KUNIT(amdgpu_dm_is_timing_unchanged_for_freesync);
+
+void amdgpu_dm_set_freesync_fixed_config(struct dm_crtc_state *dm_new_crtc_state)
+{
+	u64 num, den, res;
+	struct drm_crtc_state *new_crtc_state = &dm_new_crtc_state->base;
+
+	dm_new_crtc_state->freesync_config.state = VRR_STATE_ACTIVE_FIXED;
+
+	num = (unsigned long long)new_crtc_state->mode.clock * 1000 * 1000000;
+	den = (unsigned long long)new_crtc_state->mode.htotal *
+	      (unsigned long long)new_crtc_state->mode.vtotal;
+
+	res = div_u64(num, den);
+	dm_new_crtc_state->freesync_config.fixed_refresh_in_uhz = res;
+}
+EXPORT_IF_KUNIT(amdgpu_dm_set_freesync_fixed_config);
+
+void amdgpu_dm_reset_freesync_config_for_crtc(
+	struct dm_crtc_state *new_crtc_state)
+{
+	new_crtc_state->vrr_supported = false;
+
+	memset(&new_crtc_state->vrr_infopacket, 0,
+	       sizeof(new_crtc_state->vrr_infopacket));
+}
+EXPORT_IF_KUNIT(amdgpu_dm_reset_freesync_config_for_crtc);
+
+void amdgpu_dm_get_freesync_config_for_crtc(
+	struct dm_crtc_state *new_crtc_state,
+	struct dm_connector_state *new_con_state)
+{
+	struct mod_freesync_config config = {0};
+	struct amdgpu_dm_connector *aconnector;
+	struct drm_display_mode *mode = &new_crtc_state->base.mode;
+	int vrefresh = drm_mode_vrefresh(mode);
+	bool fs_vid_mode = false;
+
+	if (new_con_state->base.connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
+		return;
+
+	aconnector = to_amdgpu_dm_connector(new_con_state->base.connector);
+
+	new_crtc_state->vrr_supported = new_con_state->freesync_capable &&
+					vrefresh >= aconnector->min_vfreq &&
+					vrefresh <= aconnector->max_vfreq;
+
+	if (new_crtc_state->vrr_supported) {
+		new_crtc_state->stream->ignore_msa_timing_param = true;
+		fs_vid_mode = new_crtc_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED;
+
+		config.min_refresh_in_uhz = aconnector->min_vfreq * 1000000;
+		config.max_refresh_in_uhz = aconnector->max_vfreq * 1000000;
+		config.vsif_supported = true;
+		config.btr = true;
+
+		if (fs_vid_mode) {
+			config.state = VRR_STATE_ACTIVE_FIXED;
+			config.fixed_refresh_in_uhz = new_crtc_state->freesync_config.fixed_refresh_in_uhz;
+			goto out;
+		} else if (new_crtc_state->base.vrr_enabled) {
+			config.state = VRR_STATE_ACTIVE_VARIABLE;
+		} else {
+			config.state = VRR_STATE_INACTIVE;
+		}
+	} else {
+		config.state = VRR_STATE_UNSUPPORTED;
+	}
+out:
+	new_crtc_state->freesync_config = config;
+}
+EXPORT_IF_KUNIT(amdgpu_dm_get_freesync_config_for_crtc);
+
+void amdgpu_dm_update_freesync_state_on_stream(
+	struct amdgpu_display_manager *dm,
+	struct dm_crtc_state *new_crtc_state,
+	struct dc_stream_state *new_stream,
+	struct dc_plane_state *surface,
+	u32 flip_timestamp_in_us)
+{
+	struct mod_vrr_params vrr_params;
+	struct dc_info_packet vrr_infopacket = {0};
+	struct amdgpu_device *adev = dm->adev;
+	struct amdgpu_crtc *acrtc = to_amdgpu_crtc(new_crtc_state->base.crtc);
+	unsigned long flags;
+	bool pack_sdp_v1_3 = false;
+	struct amdgpu_dm_connector *aconn;
+	enum vrr_packet_type packet_type = PACKET_TYPE_VRR;
+
+	if (!new_stream)
+		return;
+
+	/*
+	 * TODO: Determine why min/max totals and vrefresh can be 0 here.
+	 * For now it's sufficient to just guard against these conditions.
+	 */
+
+	if (!new_stream->timing.h_total || !new_stream->timing.v_total)
+		return;
+
+	spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
+	vrr_params = acrtc->dm_irq_params.vrr_params;
+
+	if (surface) {
+		mod_freesync_handle_preflip(
+			dm->freesync_module,
+			surface,
+			new_stream,
+			flip_timestamp_in_us,
+			&vrr_params);
+
+		if (adev->family < AMDGPU_FAMILY_AI &&
+		    amdgpu_dm_crtc_vrr_active(new_crtc_state)) {
+			mod_freesync_handle_v_update(dm->freesync_module,
+						     new_stream, &vrr_params);
+
+			/* Need to call this before the frame ends. */
+			dc_stream_adjust_vmin_vmax(dm->dc,
+						   new_crtc_state->stream,
+						   &vrr_params.adjust);
+		}
+	}
+
+	aconn = (struct amdgpu_dm_connector *)new_stream->dm_stream_context;
+
+	if (aconn && (aconn->as_type == FREESYNC_TYPE_PCON_IN_WHITELIST || aconn->vsdb_info.replay_mode)) {
+		pack_sdp_v1_3 = aconn->pack_sdp_v1_3;
+
+		if (aconn->vsdb_info.amd_vsdb_version == 1)
+			packet_type = PACKET_TYPE_FS_V1;
+		else if (aconn->vsdb_info.amd_vsdb_version == 2)
+			packet_type = PACKET_TYPE_FS_V2;
+		else if (aconn->vsdb_info.amd_vsdb_version == 3)
+			packet_type = PACKET_TYPE_FS_V3;
+
+		mod_build_adaptive_sync_infopacket(new_stream, aconn->as_type, NULL,
+					&new_stream->adaptive_sync_infopacket);
+	}
+
+	mod_freesync_build_vrr_infopacket(
+		dm->freesync_module,
+		new_stream,
+		&vrr_params,
+		packet_type,
+		TRANSFER_FUNC_UNKNOWN,
+		&vrr_infopacket,
+		pack_sdp_v1_3);
+
+	new_crtc_state->freesync_vrr_info_changed |=
+		(memcmp(&new_crtc_state->vrr_infopacket,
+			&vrr_infopacket,
+			sizeof(vrr_infopacket)) != 0);
+
+	acrtc->dm_irq_params.vrr_params = vrr_params;
+	new_crtc_state->vrr_infopacket = vrr_infopacket;
+
+	new_stream->vrr_infopacket = vrr_infopacket;
+	new_stream->allow_freesync = mod_freesync_get_freesync_enabled(&vrr_params);
+
+	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,
+			      (int)new_crtc_state->base.vrr_enabled,
+			      (int)vrr_params.state);
+
+	spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
+}
+
+void amdgpu_dm_update_stream_irq_parameters(
+	struct amdgpu_display_manager *dm,
+	struct dm_crtc_state *new_crtc_state)
+{
+	struct dc_stream_state *new_stream = new_crtc_state->stream;
+	struct mod_vrr_params vrr_params;
+	struct mod_freesync_config config = new_crtc_state->freesync_config;
+	struct amdgpu_device *adev = dm->adev;
+	struct amdgpu_crtc *acrtc = to_amdgpu_crtc(new_crtc_state->base.crtc);
+	unsigned long flags;
+
+	if (!new_stream)
+		return;
+
+	/*
+	 * TODO: Determine why min/max totals and vrefresh can be 0 here.
+	 * For now it's sufficient to just guard against these conditions.
+	 */
+	if (!new_stream->timing.h_total || !new_stream->timing.v_total)
+		return;
+
+	spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
+	vrr_params = acrtc->dm_irq_params.vrr_params;
+
+	if (new_crtc_state->vrr_supported &&
+	    config.min_refresh_in_uhz &&
+	    config.max_refresh_in_uhz) {
+		/*
+		 * if freesync compatible mode was set, config.state will be set
+		 * in atomic check
+		 */
+		if (config.state == VRR_STATE_ACTIVE_FIXED && config.fixed_refresh_in_uhz &&
+		    (!drm_atomic_crtc_needs_modeset(&new_crtc_state->base) ||
+		     new_crtc_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED)) {
+			vrr_params.max_refresh_in_uhz = config.max_refresh_in_uhz;
+			vrr_params.min_refresh_in_uhz = config.min_refresh_in_uhz;
+			vrr_params.fixed_refresh_in_uhz = config.fixed_refresh_in_uhz;
+			vrr_params.state = VRR_STATE_ACTIVE_FIXED;
+		} else {
+			config.state = new_crtc_state->base.vrr_enabled ?
+						     VRR_STATE_ACTIVE_VARIABLE :
+						     VRR_STATE_INACTIVE;
+		}
+	} else {
+		config.state = VRR_STATE_UNSUPPORTED;
+	}
+
+	mod_freesync_build_vrr_params(dm->freesync_module,
+				      new_stream,
+				      &config, &vrr_params);
+
+	new_crtc_state->freesync_config = config;
+	/* Copy state for access from DM IRQ handler */
+	acrtc->dm_irq_params.freesync_config = config;
+	acrtc->dm_irq_params.active_planes = new_crtc_state->active_planes;
+	acrtc->dm_irq_params.vrr_params = vrr_params;
+	spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
+}
+
+void amdgpu_dm_handle_vrr_transition(struct amdgpu_display_manager *dm,
+				     struct dm_crtc_state *old_state,
+				     struct dm_crtc_state *new_state)
+{
+	struct amdgpu_device *adev = dm->adev;
+	bool old_vrr_active = amdgpu_dm_crtc_vrr_active(old_state);
+	bool new_vrr_active = amdgpu_dm_crtc_vrr_active(new_state);
+
+	/* Only DCE gates vupdate on VRR, keep it enabled for DCN */
+	bool vrr_gates_vupdate = amdgpu_ip_version(adev, DCE_HWIP, 0) == 0;
+
+	if (!old_vrr_active && new_vrr_active) {
+		/* Transition VRR inactive -> active:
+		 * While VRR is active, we must not disable vblank irq, as a
+		 * reenable after disable would compute bogus vblank/pflip
+		 * timestamps if it likely happened inside display front-porch.
+		 *
+		 * We also need vupdate irq for the actual core vblank handling
+		 * at end of vblank.
+		 */
+		if (vrr_gates_vupdate)
+			WARN_ON(amdgpu_dm_crtc_set_vupdate_irq(new_state->base.crtc, true) != 0);
+		WARN_ON(drm_crtc_vblank_get(new_state->base.crtc) != 0);
+		drm_dbg_driver(new_state->base.crtc->dev, "%s: crtc=%u VRR off->on: Get vblank ref\n",
+				 __func__, new_state->base.crtc->base.id);
+
+		scoped_guard(mutex, &dm->dc_lock) {
+			dc_exit_ips_for_hw_access(dm->dc);
+			amdgpu_dm_psr_set_event(dm, new_state->stream, true,
+				psr_event_vrr_transition, true);
+			amdgpu_dm_replay_set_event(dm, new_state->stream, true,
+				replay_event_vrr, true);
+		}
+	} else if (old_vrr_active && !new_vrr_active) {
+		/* Transition VRR active -> inactive:
+		 * Allow vblank irq disable again for fixed refresh rate.
+		 */
+		if (vrr_gates_vupdate)
+			WARN_ON(amdgpu_dm_crtc_set_vupdate_irq(new_state->base.crtc, false) != 0);
+		drm_crtc_vblank_put(new_state->base.crtc);
+		drm_dbg_driver(new_state->base.crtc->dev, "%s: crtc=%u VRR on->off: Drop vblank ref\n",
+				 __func__, new_state->base.crtc->base.id);
+
+		scoped_guard(mutex, &dm->dc_lock) {
+			dc_exit_ips_for_hw_access(dm->dc);
+			amdgpu_dm_psr_set_event(dm, new_state->stream, false,
+				psr_event_vrr_transition, false);
+			amdgpu_dm_replay_set_event(dm, new_state->stream, false,
+				replay_event_vrr, false);
+		}
+	}
+}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.h
new file mode 100644
index 000000000000..24c410306284
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __AMDGPU_DM_FREESYNC_H__
+#define __AMDGPU_DM_FREESYNC_H__
+
+#include <linux/types.h>
+
+struct amdgpu_display_manager;
+struct dm_crtc_state;
+struct dm_connector_state;
+struct dc_stream_state;
+struct dc_plane_state;
+struct drm_crtc_state;
+
+bool amdgpu_dm_is_dc_timing_adjust_needed(struct dm_crtc_state *old_state,
+					  struct dm_crtc_state *new_state);
+
+bool amdgpu_dm_is_timing_unchanged_for_freesync(struct drm_crtc_state *old_crtc_state,
+						struct drm_crtc_state *new_crtc_state);
+
+void amdgpu_dm_set_freesync_fixed_config(struct dm_crtc_state *dm_new_crtc_state);
+
+void amdgpu_dm_reset_freesync_config_for_crtc(struct dm_crtc_state *new_crtc_state);
+
+void amdgpu_dm_get_freesync_config_for_crtc(struct dm_crtc_state *new_crtc_state,
+					    struct dm_connector_state *new_con_state);
+
+void amdgpu_dm_update_freesync_state_on_stream(struct amdgpu_display_manager *dm,
+					       struct dm_crtc_state *new_crtc_state,
+					       struct dc_stream_state *new_stream,
+					       struct dc_plane_state *surface,
+					       u32 flip_timestamp_in_us);
+
+void amdgpu_dm_update_stream_irq_parameters(struct amdgpu_display_manager *dm,
+					    struct dm_crtc_state *new_crtc_state);
+
+void amdgpu_dm_handle_vrr_transition(struct amdgpu_display_manager *dm,
+				     struct dm_crtc_state *old_state,
+				     struct dm_crtc_state *new_state);
+
+#endif /* __AMDGPU_DM_FREESYNC_H__ */
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile
index 1592e8dae1a9..e58ffc4dcd84 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_plane_test.o
 obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_mst_types_test.o
 obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_pp_smu_test.o
 obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_test.o
+obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_freesync_test.o
 obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_crtc_test.o
 obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_services_test.o
 obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_helpers_test.o
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_freesync_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_freesync_test.c
new file mode 100644
index 000000000000..0ae636dcbbe4
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_freesync_test.c
@@ -0,0 +1,453 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * KUnit tests for amdgpu_dm_freesync.c
+ *
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ */
+
+#include <kunit/test.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_modes.h>
+
+#include "dc.h"
+#include "inc/core_types.h"
+#include "amd_shared.h"
+#include "amdgpu.h"
+#include "amdgpu_mode.h"
+#include "amdgpu_dm.h"
+#include "amdgpu_dm_freesync.h"
+#include "amdgpu_dm_kunit_test_helpers.h"
+
+/* Tests for amdgpu_dm_is_timing_unchanged_for_freesync() */
+
+/**
+ * dm_test_timing_unchanged_null_args - Test NULL crtc states return false
+ * @test: The KUnit test context
+ */
+static void dm_test_timing_unchanged_null_args(struct kunit *test)
+{
+	struct drm_crtc_state crtc_state = { 0 };
+
+	KUNIT_EXPECT_FALSE(test,
+			   amdgpu_dm_is_timing_unchanged_for_freesync(NULL, &crtc_state));
+	KUNIT_EXPECT_FALSE(test,
+			   amdgpu_dm_is_timing_unchanged_for_freesync(&crtc_state, NULL));
+}
+
+/**
+ * dm_test_timing_unchanged_identical_modes - Test identical modes are not "unchanged"
+ * @test: The KUnit test context
+ *
+ * The helper only returns true when vtotal/vsync shift (vrr) while the rest
+ * of the timing stays fixed, so identical modes must return false.
+ */
+static void dm_test_timing_unchanged_identical_modes(struct kunit *test)
+{
+	struct drm_crtc_state old_state = { 0 };
+	struct drm_crtc_state new_state = { 0 };
+
+	old_state.mode.clock = 148500;
+	old_state.mode.hdisplay = 1920;
+	old_state.mode.vdisplay = 1080;
+	old_state.mode.htotal = 2200;
+	old_state.mode.vtotal = 1125;
+	new_state.mode = old_state.mode;
+
+	KUNIT_EXPECT_FALSE(test,
+			   amdgpu_dm_is_timing_unchanged_for_freesync(&old_state, &new_state));
+}
+
+/**
+ * dm_test_timing_unchanged_vrr_shift - Test vrr-style vtotal/vsync shift is detected
+ * @test: The KUnit test context
+ */
+static void dm_test_timing_unchanged_vrr_shift(struct kunit *test)
+{
+	struct drm_crtc_state old_state = { 0 };
+	struct drm_crtc_state new_state = { 0 };
+
+	old_state.mode.clock = 148500;
+	old_state.mode.hdisplay = 1920;
+	old_state.mode.vdisplay = 1080;
+	old_state.mode.htotal = 2200;
+	old_state.mode.vtotal = 1125;
+	old_state.mode.hsync_start = 2008;
+	old_state.mode.vsync_start = 1084;
+	old_state.mode.hsync_end = 2052;
+	old_state.mode.vsync_end = 1089;
+
+	/* Same horizontal timing, vertical totals/sync shifted by 125 lines */
+	new_state.mode = old_state.mode;
+	new_state.mode.vtotal = 1250;
+	new_state.mode.vsync_start = 1209;
+	new_state.mode.vsync_end = 1214;
+
+	KUNIT_EXPECT_TRUE(test,
+			  amdgpu_dm_is_timing_unchanged_for_freesync(&old_state, &new_state));
+}
+
+/**
+ * dm_test_timing_unchanged_clock_changed - Test pixel clock change returns false
+ * @test: The KUnit test context
+ */
+static void dm_test_timing_unchanged_clock_changed(struct kunit *test)
+{
+	struct drm_crtc_state old_state = { 0 };
+	struct drm_crtc_state new_state = { 0 };
+
+	old_state.mode.clock = 148500;
+	old_state.mode.htotal = 2200;
+	old_state.mode.vtotal = 1125;
+	old_state.mode.vsync_start = 1084;
+	old_state.mode.vsync_end = 1089;
+
+	new_state.mode = old_state.mode;
+	new_state.mode.clock = 297000;
+	new_state.mode.vtotal = 1250;
+	new_state.mode.vsync_start = 1209;
+	new_state.mode.vsync_end = 1214;
+
+	KUNIT_EXPECT_FALSE(test,
+			   amdgpu_dm_is_timing_unchanged_for_freesync(&old_state, &new_state));
+}
+
+/* Tests for amdgpu_dm_set_freesync_fixed_config() */
+
+/**
+ * dm_test_set_freesync_fixed_config_60hz - Test fixed refresh computed for 1080p60
+ * @test: The KUnit test context
+ */
+static void dm_test_set_freesync_fixed_config_60hz(struct kunit *test)
+{
+	struct dm_crtc_state dm_crtc_state = { 0 };
+
+	dm_crtc_state.base.mode.clock = 148500;
+	dm_crtc_state.base.mode.htotal = 2200;
+	dm_crtc_state.base.mode.vtotal = 1125;
+
+	amdgpu_dm_set_freesync_fixed_config(&dm_crtc_state);
+
+	KUNIT_EXPECT_EQ(test, (int)dm_crtc_state.freesync_config.state,
+			(int)VRR_STATE_ACTIVE_FIXED);
+	/* 148500 kHz / (2200 * 1125) = 60 Hz = 60000000 uHz */
+	KUNIT_EXPECT_EQ(test, dm_crtc_state.freesync_config.fixed_refresh_in_uhz,
+			60000000U);
+}
+
+/* Tests for amdgpu_dm_is_dc_timing_adjust_needed() */
+
+/**
+ * dm_test_dc_timing_adjust_pending - Test a pending hw timing adjust forces true
+ * @test: The KUnit test context
+ */
+static void dm_test_dc_timing_adjust_pending(struct kunit *test)
+{
+	struct dm_crtc_state *old_state, *new_state;
+	struct dc_stream_state *stream;
+
+	old_state = kunit_kzalloc(test, sizeof(*old_state), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_state);
+	new_state = kunit_kzalloc(test, sizeof(*new_state), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_state);
+	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
+
+	new_state->stream = stream;
+	stream->adjust.timing_adjust_pending = 1;
+
+	KUNIT_EXPECT_TRUE(test, amdgpu_dm_is_dc_timing_adjust_needed(old_state, new_state));
+}
+
+/**
+ * dm_test_dc_timing_adjust_active_fixed - Test VRR active-fixed forces true
+ * @test: The KUnit test context
+ */
+static void dm_test_dc_timing_adjust_active_fixed(struct kunit *test)
+{
+	struct dm_crtc_state *old_state, *new_state;
+	struct dc_stream_state *stream;
+
+	old_state = kunit_kzalloc(test, sizeof(*old_state), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_state);
+	new_state = kunit_kzalloc(test, sizeof(*new_state), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_state);
+	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
+
+	new_state->stream = stream;
+	new_state->freesync_config.state = VRR_STATE_ACTIVE_FIXED;
+
+	KUNIT_EXPECT_TRUE(test, amdgpu_dm_is_dc_timing_adjust_needed(old_state, new_state));
+}
+
+/**
+ * dm_test_dc_timing_adjust_vrr_toggle - Test a change in vrr active state forces true
+ * @test: The KUnit test context
+ */
+static void dm_test_dc_timing_adjust_vrr_toggle(struct kunit *test)
+{
+	struct dm_crtc_state *old_state, *new_state;
+	struct dc_stream_state *stream;
+
+	old_state = kunit_kzalloc(test, sizeof(*old_state), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_state);
+	new_state = kunit_kzalloc(test, sizeof(*new_state), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_state);
+	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
+
+	new_state->stream = stream;
+	old_state->freesync_config.state = VRR_STATE_ACTIVE_VARIABLE;
+	new_state->freesync_config.state = VRR_STATE_INACTIVE;
+
+	KUNIT_EXPECT_TRUE(test, amdgpu_dm_is_dc_timing_adjust_needed(old_state, new_state));
+}
+
+/**
+ * dm_test_dc_timing_adjust_not_needed - Test steady-state timing needs no adjust
+ * @test: The KUnit test context
+ */
+static void dm_test_dc_timing_adjust_not_needed(struct kunit *test)
+{
+	struct dm_crtc_state *old_state, *new_state;
+	struct dc_stream_state *stream;
+
+	old_state = kunit_kzalloc(test, sizeof(*old_state), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_state);
+	new_state = kunit_kzalloc(test, sizeof(*new_state), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_state);
+	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
+
+	new_state->stream = stream;
+	old_state->freesync_config.state = VRR_STATE_INACTIVE;
+	new_state->freesync_config.state = VRR_STATE_INACTIVE;
+
+	KUNIT_EXPECT_FALSE(test, amdgpu_dm_is_dc_timing_adjust_needed(old_state, new_state));
+}
+
+/* Tests for amdgpu_dm_get_freesync_config_for_crtc() */
+
+struct dm_test_freesync_ctx {
+	struct amdgpu_dm_connector *aconnector;
+	struct dm_crtc_state *crtc_state;
+	struct dm_connector_state *conn_state;
+	struct dc_stream_state *stream;
+};
+
+static struct dm_test_freesync_ctx *dm_test_freesync_ctx_alloc(struct kunit *test)
+{
+	struct dm_test_freesync_ctx *ctx;
+
+	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, ctx);
+
+	ctx->aconnector = kunit_kzalloc(test, sizeof(*ctx->aconnector), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, ctx->aconnector);
+	ctx->crtc_state = kunit_kzalloc(test, sizeof(*ctx->crtc_state), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, ctx->crtc_state);
+	ctx->conn_state = kunit_kzalloc(test, sizeof(*ctx->conn_state), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, ctx->conn_state);
+	ctx->stream = dm_kunit_alloc_stream(test, NULL);
+
+	ctx->conn_state->base.connector = &ctx->aconnector->base;
+	ctx->aconnector->base.connector_type = DRM_MODE_CONNECTOR_DisplayPort;
+	ctx->crtc_state->stream = ctx->stream;
+
+	/* 1080p60 timing so drm_mode_vrefresh() == 60 */
+	ctx->crtc_state->base.mode.clock = 148500;
+	ctx->crtc_state->base.mode.htotal = 2200;
+	ctx->crtc_state->base.mode.vtotal = 1125;
+
+	return ctx;
+}
+
+/**
+ * dm_test_freesync_config_writeback - Test writeback connector is left untouched
+ * @test: The KUnit test context
+ */
+static void dm_test_freesync_config_writeback(struct kunit *test)
+{
+	struct dm_test_freesync_ctx *ctx = dm_test_freesync_ctx_alloc(test);
+
+	ctx->aconnector->base.connector_type = DRM_MODE_CONNECTOR_WRITEBACK;
+	ctx->conn_state->freesync_capable = true;
+	ctx->aconnector->min_vfreq = 48;
+	ctx->aconnector->max_vfreq = 120;
+	ctx->crtc_state->vrr_supported = true;	/* sentinel: must stay set */
+
+	amdgpu_dm_get_freesync_config_for_crtc(ctx->crtc_state, ctx->conn_state);
+
+	/* Writeback: early return leaves vrr_supported sentinel untouched */
+	KUNIT_EXPECT_TRUE(test, ctx->crtc_state->vrr_supported);
+}
+
+/**
+ * dm_test_freesync_config_not_capable - Test a non-freesync sink reports UNSUPPORTED
+ * @test: The KUnit test context
+ */
+static void dm_test_freesync_config_not_capable(struct kunit *test)
+{
+	struct dm_test_freesync_ctx *ctx = dm_test_freesync_ctx_alloc(test);
+
+	ctx->conn_state->freesync_capable = false;
+	ctx->aconnector->min_vfreq = 48;
+	ctx->aconnector->max_vfreq = 120;
+
+	amdgpu_dm_get_freesync_config_for_crtc(ctx->crtc_state, ctx->conn_state);
+
+	KUNIT_EXPECT_FALSE(test, ctx->crtc_state->vrr_supported);
+	KUNIT_EXPECT_EQ(test, (int)ctx->crtc_state->freesync_config.state,
+			(int)VRR_STATE_UNSUPPORTED);
+}
+
+/**
+ * dm_test_freesync_config_out_of_range - Test a refresh outside the range is UNSUPPORTED
+ * @test: The KUnit test context
+ */
+static void dm_test_freesync_config_out_of_range(struct kunit *test)
+{
+	struct dm_test_freesync_ctx *ctx = dm_test_freesync_ctx_alloc(test);
+
+	ctx->conn_state->freesync_capable = true;
+	ctx->aconnector->min_vfreq = 90;	/* 60 < 90 -> out of range */
+	ctx->aconnector->max_vfreq = 120;
+
+	amdgpu_dm_get_freesync_config_for_crtc(ctx->crtc_state, ctx->conn_state);
+
+	KUNIT_EXPECT_FALSE(test, ctx->crtc_state->vrr_supported);
+	KUNIT_EXPECT_EQ(test, (int)ctx->crtc_state->freesync_config.state,
+			(int)VRR_STATE_UNSUPPORTED);
+}
+
+/**
+ * dm_test_freesync_config_active_variable - Test vrr_enabled yields ACTIVE_VARIABLE
+ * @test: The KUnit test context
+ */
+static void dm_test_freesync_config_active_variable(struct kunit *test)
+{
+	struct dm_test_freesync_ctx *ctx = dm_test_freesync_ctx_alloc(test);
+
+	ctx->conn_state->freesync_capable = true;
+	ctx->aconnector->min_vfreq = 48;
+	ctx->aconnector->max_vfreq = 120;
+	ctx->crtc_state->base.vrr_enabled = true;
+
+	amdgpu_dm_get_freesync_config_for_crtc(ctx->crtc_state, ctx->conn_state);
+
+	KUNIT_EXPECT_TRUE(test, ctx->crtc_state->vrr_supported);
+	KUNIT_EXPECT_TRUE(test, ctx->stream->ignore_msa_timing_param);
+	KUNIT_EXPECT_EQ(test, (int)ctx->crtc_state->freesync_config.state,
+			(int)VRR_STATE_ACTIVE_VARIABLE);
+	KUNIT_EXPECT_EQ(test, ctx->crtc_state->freesync_config.min_refresh_in_uhz,
+			48000000U);
+	KUNIT_EXPECT_EQ(test, ctx->crtc_state->freesync_config.max_refresh_in_uhz,
+			120000000U);
+	KUNIT_EXPECT_TRUE(test, ctx->crtc_state->freesync_config.vsif_supported);
+	KUNIT_EXPECT_TRUE(test, ctx->crtc_state->freesync_config.btr);
+}
+
+/**
+ * dm_test_freesync_config_inactive - Test supported-but-off yields INACTIVE
+ * @test: The KUnit test context
+ */
+static void dm_test_freesync_config_inactive(struct kunit *test)
+{
+	struct dm_test_freesync_ctx *ctx = dm_test_freesync_ctx_alloc(test);
+
+	ctx->conn_state->freesync_capable = true;
+	ctx->aconnector->min_vfreq = 48;
+	ctx->aconnector->max_vfreq = 120;
+	ctx->crtc_state->base.vrr_enabled = false;
+
+	amdgpu_dm_get_freesync_config_for_crtc(ctx->crtc_state, ctx->conn_state);
+
+	KUNIT_EXPECT_TRUE(test, ctx->crtc_state->vrr_supported);
+	KUNIT_EXPECT_EQ(test, (int)ctx->crtc_state->freesync_config.state,
+			(int)VRR_STATE_INACTIVE);
+}
+
+/**
+ * dm_test_freesync_config_active_fixed - Test freesync-video mode yields ACTIVE_FIXED
+ * @test: The KUnit test context
+ */
+static void dm_test_freesync_config_active_fixed(struct kunit *test)
+{
+	struct dm_test_freesync_ctx *ctx = dm_test_freesync_ctx_alloc(test);
+
+	ctx->conn_state->freesync_capable = true;
+	ctx->aconnector->min_vfreq = 48;
+	ctx->aconnector->max_vfreq = 120;
+	/* Pre-set fixed state selects the freesync-video (fixed) path */
+	ctx->crtc_state->freesync_config.state = VRR_STATE_ACTIVE_FIXED;
+	ctx->crtc_state->freesync_config.fixed_refresh_in_uhz = 60000000;
+	ctx->crtc_state->base.vrr_enabled = true;	/* ignored on the fixed path */
+
+	amdgpu_dm_get_freesync_config_for_crtc(ctx->crtc_state, ctx->conn_state);
+
+	KUNIT_EXPECT_TRUE(test, ctx->crtc_state->vrr_supported);
+	KUNIT_EXPECT_EQ(test, (int)ctx->crtc_state->freesync_config.state,
+			(int)VRR_STATE_ACTIVE_FIXED);
+	KUNIT_EXPECT_EQ(test, ctx->crtc_state->freesync_config.fixed_refresh_in_uhz,
+			60000000U);
+}
+
+/* Tests for amdgpu_dm_reset_freesync_config_for_crtc() */
+
+/**
+ * dm_test_reset_freesync_config - Test reset clears vrr support and info packet
+ * @test: The KUnit test context
+ */
+static void dm_test_reset_freesync_config(struct kunit *test)
+{
+	struct dm_crtc_state *crtc_state;
+
+	crtc_state = kunit_kzalloc(test, sizeof(*crtc_state), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, crtc_state);
+
+	crtc_state->vrr_supported = true;
+	crtc_state->vrr_infopacket.valid = true;
+
+	amdgpu_dm_reset_freesync_config_for_crtc(crtc_state);
+
+	KUNIT_EXPECT_FALSE(test, crtc_state->vrr_supported);
+	KUNIT_EXPECT_FALSE(test, crtc_state->vrr_infopacket.valid);
+}
+
+static struct kunit_case amdgpu_dm_freesync_tests[] = {
+	/* amdgpu_dm_is_timing_unchanged_for_freesync */
+	KUNIT_CASE(dm_test_timing_unchanged_null_args),
+	KUNIT_CASE(dm_test_timing_unchanged_identical_modes),
+	KUNIT_CASE(dm_test_timing_unchanged_vrr_shift),
+	KUNIT_CASE(dm_test_timing_unchanged_clock_changed),
+	/* amdgpu_dm_set_freesync_fixed_config */
+	KUNIT_CASE(dm_test_set_freesync_fixed_config_60hz),
+	/* amdgpu_dm_is_dc_timing_adjust_needed */
+	KUNIT_CASE(dm_test_dc_timing_adjust_pending),
+	KUNIT_CASE(dm_test_dc_timing_adjust_active_fixed),
+	KUNIT_CASE(dm_test_dc_timing_adjust_vrr_toggle),
+	KUNIT_CASE(dm_test_dc_timing_adjust_not_needed),
+	/* amdgpu_dm_get_freesync_config_for_crtc */
+	KUNIT_CASE(dm_test_freesync_config_writeback),
+	KUNIT_CASE(dm_test_freesync_config_not_capable),
+	KUNIT_CASE(dm_test_freesync_config_out_of_range),
+	KUNIT_CASE(dm_test_freesync_config_active_variable),
+	KUNIT_CASE(dm_test_freesync_config_inactive),
+	KUNIT_CASE(dm_test_freesync_config_active_fixed),
+	/* amdgpu_dm_reset_freesync_config_for_crtc */
+	KUNIT_CASE(dm_test_reset_freesync_config),
+	{}
+};
+
+static struct kunit_suite amdgpu_dm_freesync_test_suite = {
+	.name = "amdgpu_dm_freesync",
+	.test_cases = amdgpu_dm_freesync_tests,
+};
+
+kunit_test_suite(amdgpu_dm_freesync_test_suite);
+
+MODULE_AUTHOR("AMD");
+MODULE_DESCRIPTION("KUnit tests for amdgpu_dm_freesync");
+MODULE_LICENSE("Dual MIT/GPL");
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c
index 49a1d2ae5588..428d24259198 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c
@@ -860,214 +860,6 @@ static void dm_test_scaling_state_underscan_border_changed(struct kunit *test)
 	KUNIT_EXPECT_TRUE(test, is_scaling_state_different(a, b));
 }
 
-/* Tests for is_timing_unchanged_for_freesync() */
-
-/**
- * dm_test_timing_unchanged_null_args - Test NULL crtc states return false
- * @test: The KUnit test context
- */
-static void dm_test_timing_unchanged_null_args(struct kunit *test)
-{
-	struct drm_crtc_state crtc_state = { 0 };
-
-	KUNIT_EXPECT_FALSE(test,
-			   is_timing_unchanged_for_freesync(NULL, &crtc_state));
-	KUNIT_EXPECT_FALSE(test,
-			   is_timing_unchanged_for_freesync(&crtc_state, NULL));
-}
-
-/**
- * dm_test_timing_unchanged_identical_modes - Test identical modes are not "unchanged"
- * @test: The KUnit test context
- *
- * The helper only returns true when vtotal/vsync shift (vrr) while the rest
- * of the timing stays fixed, so identical modes must return false.
- */
-static void dm_test_timing_unchanged_identical_modes(struct kunit *test)
-{
-	struct drm_crtc_state old_state = { 0 };
-	struct drm_crtc_state new_state = { 0 };
-
-	old_state.mode.clock = 148500;
-	old_state.mode.hdisplay = 1920;
-	old_state.mode.vdisplay = 1080;
-	old_state.mode.htotal = 2200;
-	old_state.mode.vtotal = 1125;
-	new_state.mode = old_state.mode;
-
-	KUNIT_EXPECT_FALSE(test,
-			   is_timing_unchanged_for_freesync(&old_state, &new_state));
-}
-
-/**
- * dm_test_timing_unchanged_vrr_shift - Test vrr-style vtotal/vsync shift is detected
- * @test: The KUnit test context
- */
-static void dm_test_timing_unchanged_vrr_shift(struct kunit *test)
-{
-	struct drm_crtc_state old_state = { 0 };
-	struct drm_crtc_state new_state = { 0 };
-
-	old_state.mode.clock = 148500;
-	old_state.mode.hdisplay = 1920;
-	old_state.mode.vdisplay = 1080;
-	old_state.mode.htotal = 2200;
-	old_state.mode.vtotal = 1125;
-	old_state.mode.hsync_start = 2008;
-	old_state.mode.vsync_start = 1084;
-	old_state.mode.hsync_end = 2052;
-	old_state.mode.vsync_end = 1089;
-
-	/* Same horizontal timing, vertical totals/sync shifted by 125 lines */
-	new_state.mode = old_state.mode;
-	new_state.mode.vtotal = 1250;
-	new_state.mode.vsync_start = 1209;
-	new_state.mode.vsync_end = 1214;
-
-	KUNIT_EXPECT_TRUE(test,
-			  is_timing_unchanged_for_freesync(&old_state, &new_state));
-}
-
-/**
- * dm_test_timing_unchanged_clock_changed - Test pixel clock change returns false
- * @test: The KUnit test context
- */
-static void dm_test_timing_unchanged_clock_changed(struct kunit *test)
-{
-	struct drm_crtc_state old_state = { 0 };
-	struct drm_crtc_state new_state = { 0 };
-
-	old_state.mode.clock = 148500;
-	old_state.mode.htotal = 2200;
-	old_state.mode.vtotal = 1125;
-	old_state.mode.vsync_start = 1084;
-	old_state.mode.vsync_end = 1089;
-
-	new_state.mode = old_state.mode;
-	new_state.mode.clock = 297000;
-	new_state.mode.vtotal = 1250;
-	new_state.mode.vsync_start = 1209;
-	new_state.mode.vsync_end = 1214;
-
-	KUNIT_EXPECT_FALSE(test,
-			   is_timing_unchanged_for_freesync(&old_state, &new_state));
-}
-
-/* Tests for set_freesync_fixed_config() */
-
-/**
- * dm_test_set_freesync_fixed_config_60hz - Test fixed refresh computed for 1080p60
- * @test: The KUnit test context
- */
-static void dm_test_set_freesync_fixed_config_60hz(struct kunit *test)
-{
-	struct dm_crtc_state dm_crtc_state = { 0 };
-
-	dm_crtc_state.base.mode.clock = 148500;
-	dm_crtc_state.base.mode.htotal = 2200;
-	dm_crtc_state.base.mode.vtotal = 1125;
-
-	set_freesync_fixed_config(&dm_crtc_state);
-
-	KUNIT_EXPECT_EQ(test, (int)dm_crtc_state.freesync_config.state,
-			(int)VRR_STATE_ACTIVE_FIXED);
-	/* 148500 kHz / (2200 * 1125) = 60 Hz = 60000000 uHz */
-	KUNIT_EXPECT_EQ(test, dm_crtc_state.freesync_config.fixed_refresh_in_uhz,
-			60000000U);
-}
-
-/* Tests for is_dc_timing_adjust_needed() */
-
-/**
- * dm_test_dc_timing_adjust_pending - Test a pending hw timing adjust forces true
- * @test: The KUnit test context
- */
-static void dm_test_dc_timing_adjust_pending(struct kunit *test)
-{
-	struct dm_crtc_state *old_state, *new_state;
-	struct dc_stream_state *stream;
-
-	old_state = kunit_kzalloc(test, sizeof(*old_state), GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_state);
-	new_state = kunit_kzalloc(test, sizeof(*new_state), GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_state);
-	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
-
-	new_state->stream = stream;
-	stream->adjust.timing_adjust_pending = 1;
-
-	KUNIT_EXPECT_TRUE(test, is_dc_timing_adjust_needed(old_state, new_state));
-}
-
-/**
- * dm_test_dc_timing_adjust_active_fixed - Test VRR active-fixed forces true
- * @test: The KUnit test context
- */
-static void dm_test_dc_timing_adjust_active_fixed(struct kunit *test)
-{
-	struct dm_crtc_state *old_state, *new_state;
-	struct dc_stream_state *stream;
-
-	old_state = kunit_kzalloc(test, sizeof(*old_state), GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_state);
-	new_state = kunit_kzalloc(test, sizeof(*new_state), GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_state);
-	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
-
-	new_state->stream = stream;
-	new_state->freesync_config.state = VRR_STATE_ACTIVE_FIXED;
-
-	KUNIT_EXPECT_TRUE(test, is_dc_timing_adjust_needed(old_state, new_state));
-}
-
-/**
- * dm_test_dc_timing_adjust_vrr_toggle - Test a change in vrr active state forces true
- * @test: The KUnit test context
- */
-static void dm_test_dc_timing_adjust_vrr_toggle(struct kunit *test)
-{
-	struct dm_crtc_state *old_state, *new_state;
-	struct dc_stream_state *stream;
-
-	old_state = kunit_kzalloc(test, sizeof(*old_state), GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_state);
-	new_state = kunit_kzalloc(test, sizeof(*new_state), GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_state);
-	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
-
-	new_state->stream = stream;
-	old_state->freesync_config.state = VRR_STATE_ACTIVE_VARIABLE;
-	new_state->freesync_config.state = VRR_STATE_INACTIVE;
-
-	KUNIT_EXPECT_TRUE(test, is_dc_timing_adjust_needed(old_state, new_state));
-}
-
-/**
- * dm_test_dc_timing_adjust_not_needed - Test steady-state timing needs no adjust
- * @test: The KUnit test context
- */
-static void dm_test_dc_timing_adjust_not_needed(struct kunit *test)
-{
-	struct dm_crtc_state *old_state, *new_state;
-	struct dc_stream_state *stream;
-
-	old_state = kunit_kzalloc(test, sizeof(*old_state), GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_state);
-	new_state = kunit_kzalloc(test, sizeof(*new_state), GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_state);
-	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
-
-	new_state->stream = stream;
-	old_state->freesync_config.state = VRR_STATE_INACTIVE;
-	new_state->freesync_config.state = VRR_STATE_INACTIVE;
-
-	KUNIT_EXPECT_FALSE(test, is_dc_timing_adjust_needed(old_state, new_state));
-}
-
 /* Tests for set_multisync_trigger_params() */
 
 /**
@@ -1435,194 +1227,6 @@ static void dm_test_cp_diff_desired_to_undesired(struct kunit *test)
 	KUNIT_EXPECT_TRUE(test, dm_test_cp_diff(ctx));
 }
 
-/* Tests for get_freesync_config_for_crtc() */
-
-struct dm_test_freesync_ctx {
-	struct amdgpu_dm_connector *aconnector;
-	struct dm_crtc_state *crtc_state;
-	struct dm_connector_state *conn_state;
-	struct dc_stream_state *stream;
-};
-
-static struct dm_test_freesync_ctx *dm_test_freesync_ctx_alloc(struct kunit *test)
-{
-	struct dm_test_freesync_ctx *ctx;
-
-	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
-	KUNIT_ASSERT_NOT_NULL(test, ctx);
-
-	ctx->aconnector = kunit_kzalloc(test, sizeof(*ctx->aconnector), GFP_KERNEL);
-	KUNIT_ASSERT_NOT_NULL(test, ctx->aconnector);
-	ctx->crtc_state = kunit_kzalloc(test, sizeof(*ctx->crtc_state), GFP_KERNEL);
-	KUNIT_ASSERT_NOT_NULL(test, ctx->crtc_state);
-	ctx->conn_state = kunit_kzalloc(test, sizeof(*ctx->conn_state), GFP_KERNEL);
-	KUNIT_ASSERT_NOT_NULL(test, ctx->conn_state);
-	ctx->stream = dm_kunit_alloc_stream(test, NULL);
-
-	ctx->conn_state->base.connector = &ctx->aconnector->base;
-	ctx->aconnector->base.connector_type = DRM_MODE_CONNECTOR_DisplayPort;
-	ctx->crtc_state->stream = ctx->stream;
-
-	/* 1080p60 timing so drm_mode_vrefresh() == 60 */
-	ctx->crtc_state->base.mode.clock = 148500;
-	ctx->crtc_state->base.mode.htotal = 2200;
-	ctx->crtc_state->base.mode.vtotal = 1125;
-
-	return ctx;
-}
-
-/**
- * dm_test_freesync_config_writeback - Test writeback connector is left untouched
- * @test: The KUnit test context
- */
-static void dm_test_freesync_config_writeback(struct kunit *test)
-{
-	struct dm_test_freesync_ctx *ctx = dm_test_freesync_ctx_alloc(test);
-
-	ctx->aconnector->base.connector_type = DRM_MODE_CONNECTOR_WRITEBACK;
-	ctx->conn_state->freesync_capable = true;
-	ctx->aconnector->min_vfreq = 48;
-	ctx->aconnector->max_vfreq = 120;
-	ctx->crtc_state->vrr_supported = true;	/* sentinel: must stay set */
-
-	get_freesync_config_for_crtc(ctx->crtc_state, ctx->conn_state);
-
-	/* Writeback: early return leaves vrr_supported sentinel untouched */
-	KUNIT_EXPECT_TRUE(test, ctx->crtc_state->vrr_supported);
-}
-
-/**
- * dm_test_freesync_config_not_capable - Test a non-freesync sink reports UNSUPPORTED
- * @test: The KUnit test context
- */
-static void dm_test_freesync_config_not_capable(struct kunit *test)
-{
-	struct dm_test_freesync_ctx *ctx = dm_test_freesync_ctx_alloc(test);
-
-	ctx->conn_state->freesync_capable = false;
-	ctx->aconnector->min_vfreq = 48;
-	ctx->aconnector->max_vfreq = 120;
-
-	get_freesync_config_for_crtc(ctx->crtc_state, ctx->conn_state);
-
-	KUNIT_EXPECT_FALSE(test, ctx->crtc_state->vrr_supported);
-	KUNIT_EXPECT_EQ(test, (int)ctx->crtc_state->freesync_config.state,
-			(int)VRR_STATE_UNSUPPORTED);
-}
-
-/**
- * dm_test_freesync_config_out_of_range - Test a refresh outside the range is UNSUPPORTED
- * @test: The KUnit test context
- */
-static void dm_test_freesync_config_out_of_range(struct kunit *test)
-{
-	struct dm_test_freesync_ctx *ctx = dm_test_freesync_ctx_alloc(test);
-
-	ctx->conn_state->freesync_capable = true;
-	ctx->aconnector->min_vfreq = 90;	/* 60 < 90 -> out of range */
-	ctx->aconnector->max_vfreq = 120;
-
-	get_freesync_config_for_crtc(ctx->crtc_state, ctx->conn_state);
-
-	KUNIT_EXPECT_FALSE(test, ctx->crtc_state->vrr_supported);
-	KUNIT_EXPECT_EQ(test, (int)ctx->crtc_state->freesync_config.state,
-			(int)VRR_STATE_UNSUPPORTED);
-}
-
-/**
- * dm_test_freesync_config_active_variable - Test vrr_enabled yields ACTIVE_VARIABLE
- * @test: The KUnit test context
- */
-static void dm_test_freesync_config_active_variable(struct kunit *test)
-{
-	struct dm_test_freesync_ctx *ctx = dm_test_freesync_ctx_alloc(test);
-
-	ctx->conn_state->freesync_capable = true;
-	ctx->aconnector->min_vfreq = 48;
-	ctx->aconnector->max_vfreq = 120;
-	ctx->crtc_state->base.vrr_enabled = true;
-
-	get_freesync_config_for_crtc(ctx->crtc_state, ctx->conn_state);
-
-	KUNIT_EXPECT_TRUE(test, ctx->crtc_state->vrr_supported);
-	KUNIT_EXPECT_TRUE(test, ctx->stream->ignore_msa_timing_param);
-	KUNIT_EXPECT_EQ(test, (int)ctx->crtc_state->freesync_config.state,
-			(int)VRR_STATE_ACTIVE_VARIABLE);
-	KUNIT_EXPECT_EQ(test, ctx->crtc_state->freesync_config.min_refresh_in_uhz,
-			48000000U);
-	KUNIT_EXPECT_EQ(test, ctx->crtc_state->freesync_config.max_refresh_in_uhz,
-			120000000U);
-	KUNIT_EXPECT_TRUE(test, ctx->crtc_state->freesync_config.vsif_supported);
-	KUNIT_EXPECT_TRUE(test, ctx->crtc_state->freesync_config.btr);
-}
-
-/**
- * dm_test_freesync_config_inactive - Test supported-but-off yields INACTIVE
- * @test: The KUnit test context
- */
-static void dm_test_freesync_config_inactive(struct kunit *test)
-{
-	struct dm_test_freesync_ctx *ctx = dm_test_freesync_ctx_alloc(test);
-
-	ctx->conn_state->freesync_capable = true;
-	ctx->aconnector->min_vfreq = 48;
-	ctx->aconnector->max_vfreq = 120;
-	ctx->crtc_state->base.vrr_enabled = false;
-
-	get_freesync_config_for_crtc(ctx->crtc_state, ctx->conn_state);
-
-	KUNIT_EXPECT_TRUE(test, ctx->crtc_state->vrr_supported);
-	KUNIT_EXPECT_EQ(test, (int)ctx->crtc_state->freesync_config.state,
-			(int)VRR_STATE_INACTIVE);
-}
-
-/**
- * dm_test_freesync_config_active_fixed - Test freesync-video mode yields ACTIVE_FIXED
- * @test: The KUnit test context
- */
-static void dm_test_freesync_config_active_fixed(struct kunit *test)
-{
-	struct dm_test_freesync_ctx *ctx = dm_test_freesync_ctx_alloc(test);
-
-	ctx->conn_state->freesync_capable = true;
-	ctx->aconnector->min_vfreq = 48;
-	ctx->aconnector->max_vfreq = 120;
-	/* Pre-set fixed state selects the freesync-video (fixed) path */
-	ctx->crtc_state->freesync_config.state = VRR_STATE_ACTIVE_FIXED;
-	ctx->crtc_state->freesync_config.fixed_refresh_in_uhz = 60000000;
-	ctx->crtc_state->base.vrr_enabled = true;	/* ignored on the fixed path */
-
-	get_freesync_config_for_crtc(ctx->crtc_state, ctx->conn_state);
-
-	KUNIT_EXPECT_TRUE(test, ctx->crtc_state->vrr_supported);
-	KUNIT_EXPECT_EQ(test, (int)ctx->crtc_state->freesync_config.state,
-			(int)VRR_STATE_ACTIVE_FIXED);
-	KUNIT_EXPECT_EQ(test, ctx->crtc_state->freesync_config.fixed_refresh_in_uhz,
-			60000000U);
-}
-
-/* Tests for reset_freesync_config_for_crtc() */
-
-/**
- * dm_test_reset_freesync_config - Test reset clears vrr support and info packet
- * @test: The KUnit test context
- */
-static void dm_test_reset_freesync_config(struct kunit *test)
-{
-	struct dm_crtc_state *crtc_state;
-
-	crtc_state = kunit_kzalloc(test, sizeof(*crtc_state), GFP_KERNEL);
-	KUNIT_ASSERT_NOT_NULL(test, crtc_state);
-
-	crtc_state->vrr_supported = true;
-	crtc_state->vrr_infopacket.valid = true;
-
-	reset_freesync_config_for_crtc(crtc_state);
-
-	KUNIT_EXPECT_FALSE(test, crtc_state->vrr_supported);
-	KUNIT_EXPECT_FALSE(test, crtc_state->vrr_infopacket.valid);
-}
-
 /* Tests for dm_enable_per_frame_crtc_master_sync() */
 
 /**
@@ -1818,18 +1422,6 @@ static struct kunit_case amdgpu_dm_tests[] = {
 	KUNIT_CASE(dm_test_scaling_state_underscan_enabled),
 	KUNIT_CASE(dm_test_scaling_state_underscan_disabled),
 	KUNIT_CASE(dm_test_scaling_state_underscan_border_changed),
-	/* is_timing_unchanged_for_freesync */
-	KUNIT_CASE(dm_test_timing_unchanged_null_args),
-	KUNIT_CASE(dm_test_timing_unchanged_identical_modes),
-	KUNIT_CASE(dm_test_timing_unchanged_vrr_shift),
-	KUNIT_CASE(dm_test_timing_unchanged_clock_changed),
-	/* set_freesync_fixed_config */
-	KUNIT_CASE(dm_test_set_freesync_fixed_config_60hz),
-	/* is_dc_timing_adjust_needed */
-	KUNIT_CASE(dm_test_dc_timing_adjust_pending),
-	KUNIT_CASE(dm_test_dc_timing_adjust_active_fixed),
-	KUNIT_CASE(dm_test_dc_timing_adjust_vrr_toggle),
-	KUNIT_CASE(dm_test_dc_timing_adjust_not_needed),
 	/* set_multisync_trigger_params */
 	KUNIT_CASE(dm_test_multisync_trigger_disabled),
 	KUNIT_CASE(dm_test_multisync_trigger_rising),
@@ -1849,15 +1441,6 @@ static struct kunit_case amdgpu_dm_tests[] = {
 	KUNIT_CASE(dm_test_cp_diff_s3_undesired_to_enabled),
 	KUNIT_CASE(dm_test_cp_diff_desired_to_enabled),
 	KUNIT_CASE(dm_test_cp_diff_desired_to_undesired),
-	/* get_freesync_config_for_crtc */
-	KUNIT_CASE(dm_test_freesync_config_writeback),
-	KUNIT_CASE(dm_test_freesync_config_not_capable),
-	KUNIT_CASE(dm_test_freesync_config_out_of_range),
-	KUNIT_CASE(dm_test_freesync_config_active_variable),
-	KUNIT_CASE(dm_test_freesync_config_inactive),
-	KUNIT_CASE(dm_test_freesync_config_active_fixed),
-	/* reset_freesync_config_for_crtc */
-	KUNIT_CASE(dm_test_reset_freesync_config),
 	/* dm_enable_per_frame_crtc_master_sync */
 	KUNIT_CASE(dm_test_per_frame_master_sync_single_stream),
 	KUNIT_CASE(dm_test_per_frame_master_sync_two_streams),
-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.