xref: /linux/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_freesync.c (revision 67f8bc848ee31831336bd478e57d2f993551902e)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright 2026 Advanced Micro Devices, Inc.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21  * OTHER DEALINGS IN THE SOFTWARE.
22  *
23  * Authors: AMD
24  *
25  */
26 
27 #include <drm/drm_atomic.h>
28 #include <drm/drm_modes.h>
29 #include <drm/drm_vblank.h>
30 
31 #include "dc.h"
32 #include "amdgpu.h"
33 #include "amdgpu_dm.h"
34 #include "amdgpu_dm_crtc.h"
35 #include "amdgpu_dm_psr.h"
36 #include "amdgpu_dm_replay.h"
37 #include "amdgpu_dm_freesync.h"
38 #include "dm_helpers.h"
39 #include "modules/inc/mod_freesync.h"
40 
41 bool amdgpu_dm_is_dc_timing_adjust_needed(struct dm_crtc_state *old_state,
42 					  struct dm_crtc_state *new_state)
43 {
44 	if (new_state->stream->adjust.timing_adjust_pending)
45 		return true;
46 	if (new_state->freesync_config.state ==  VRR_STATE_ACTIVE_FIXED)
47 		return true;
48 	else if (amdgpu_dm_crtc_vrr_active(old_state) != amdgpu_dm_crtc_vrr_active(new_state))
49 		return true;
50 	else
51 		return false;
52 }
53 EXPORT_IF_KUNIT(amdgpu_dm_is_dc_timing_adjust_needed);
54 
55 bool
56 amdgpu_dm_is_timing_unchanged_for_freesync(struct drm_crtc_state *old_crtc_state,
57 					   struct drm_crtc_state *new_crtc_state)
58 {
59 	const struct drm_display_mode *old_mode, *new_mode;
60 
61 	if (!old_crtc_state || !new_crtc_state)
62 		return false;
63 
64 	old_mode = &old_crtc_state->mode;
65 	new_mode = &new_crtc_state->mode;
66 
67 	if (old_mode->clock       == new_mode->clock &&
68 	    old_mode->hdisplay    == new_mode->hdisplay &&
69 	    old_mode->vdisplay    == new_mode->vdisplay &&
70 	    old_mode->htotal      == new_mode->htotal &&
71 	    old_mode->vtotal      != new_mode->vtotal &&
72 	    old_mode->hsync_start == new_mode->hsync_start &&
73 	    old_mode->vsync_start != new_mode->vsync_start &&
74 	    old_mode->hsync_end   == new_mode->hsync_end &&
75 	    old_mode->vsync_end   != new_mode->vsync_end &&
76 	    old_mode->hskew       == new_mode->hskew &&
77 	    old_mode->vscan       == new_mode->vscan &&
78 	    (old_mode->vsync_end - old_mode->vsync_start) ==
79 	    (new_mode->vsync_end - new_mode->vsync_start))
80 		return true;
81 
82 	return false;
83 }
84 EXPORT_IF_KUNIT(amdgpu_dm_is_timing_unchanged_for_freesync);
85 
86 void amdgpu_dm_set_freesync_fixed_config(struct dm_crtc_state *dm_new_crtc_state)
87 {
88 	u64 num, den, res;
89 	struct drm_crtc_state *new_crtc_state = &dm_new_crtc_state->base;
90 
91 	dm_new_crtc_state->freesync_config.state = VRR_STATE_ACTIVE_FIXED;
92 
93 	num = (unsigned long long)new_crtc_state->mode.clock * 1000 * 1000000;
94 	den = (unsigned long long)new_crtc_state->mode.htotal *
95 	      (unsigned long long)new_crtc_state->mode.vtotal;
96 
97 	res = div_u64(num, den);
98 	dm_new_crtc_state->freesync_config.fixed_refresh_in_uhz = res;
99 }
100 EXPORT_IF_KUNIT(amdgpu_dm_set_freesync_fixed_config);
101 
102 void amdgpu_dm_reset_freesync_config_for_crtc(
103 	struct dm_crtc_state *new_crtc_state)
104 {
105 	new_crtc_state->vrr_supported = false;
106 
107 	memset(&new_crtc_state->vrr_infopacket, 0,
108 	       sizeof(new_crtc_state->vrr_infopacket));
109 }
110 EXPORT_IF_KUNIT(amdgpu_dm_reset_freesync_config_for_crtc);
111 
112 void amdgpu_dm_get_freesync_config_for_crtc(
113 	struct dm_crtc_state *new_crtc_state,
114 	struct dm_connector_state *new_con_state)
115 {
116 	struct mod_freesync_config config = {0};
117 	struct amdgpu_dm_connector *aconnector;
118 	struct drm_display_mode *mode = &new_crtc_state->base.mode;
119 	int vrefresh = drm_mode_vrefresh(mode);
120 	bool fs_vid_mode = false;
121 
122 	if (new_con_state->base.connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
123 		return;
124 
125 	aconnector = to_amdgpu_dm_connector(new_con_state->base.connector);
126 
127 	new_crtc_state->vrr_supported = new_con_state->freesync_capable &&
128 					vrefresh >= aconnector->min_vfreq &&
129 					vrefresh <= aconnector->max_vfreq;
130 
131 	if (new_crtc_state->vrr_supported) {
132 		new_crtc_state->stream->ignore_msa_timing_param = true;
133 		fs_vid_mode = new_crtc_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED;
134 
135 		config.min_refresh_in_uhz = aconnector->min_vfreq * 1000000;
136 		config.max_refresh_in_uhz = aconnector->max_vfreq * 1000000;
137 		config.vsif_supported = true;
138 		config.btr = true;
139 
140 		if (fs_vid_mode) {
141 			config.state = VRR_STATE_ACTIVE_FIXED;
142 			config.fixed_refresh_in_uhz = new_crtc_state->freesync_config.fixed_refresh_in_uhz;
143 			goto out;
144 		} else if (new_crtc_state->base.vrr_enabled) {
145 			config.state = VRR_STATE_ACTIVE_VARIABLE;
146 		} else {
147 			config.state = VRR_STATE_INACTIVE;
148 		}
149 	} else {
150 		config.state = VRR_STATE_UNSUPPORTED;
151 	}
152 out:
153 	new_crtc_state->freesync_config = config;
154 }
155 EXPORT_IF_KUNIT(amdgpu_dm_get_freesync_config_for_crtc);
156 
157 void amdgpu_dm_update_freesync_state_on_stream(
158 	struct amdgpu_display_manager *dm,
159 	struct dm_crtc_state *new_crtc_state,
160 	struct dc_stream_state *new_stream,
161 	struct dc_plane_state *surface,
162 	u32 flip_timestamp_in_us)
163 {
164 	struct mod_vrr_params vrr_params;
165 	struct dc_info_packet vrr_infopacket = {0};
166 	struct amdgpu_device *adev = dm->adev;
167 	struct amdgpu_crtc *acrtc = to_amdgpu_crtc(new_crtc_state->base.crtc);
168 	unsigned long flags;
169 	bool pack_sdp_v1_3 = false;
170 	struct amdgpu_dm_connector *aconn;
171 	enum vrr_packet_type packet_type = PACKET_TYPE_VRR;
172 
173 	if (!new_stream)
174 		return;
175 
176 	/*
177 	 * TODO: Determine why min/max totals and vrefresh can be 0 here.
178 	 * For now it's sufficient to just guard against these conditions.
179 	 */
180 
181 	if (!new_stream->timing.h_total || !new_stream->timing.v_total)
182 		return;
183 
184 	spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
185 	vrr_params = acrtc->dm_irq_params.vrr_params;
186 
187 	if (surface) {
188 		mod_freesync_handle_preflip(
189 			dm->freesync_module,
190 			surface,
191 			new_stream,
192 			flip_timestamp_in_us,
193 			&vrr_params);
194 
195 		if (adev->family < AMDGPU_FAMILY_AI &&
196 		    amdgpu_dm_crtc_vrr_active(new_crtc_state)) {
197 			mod_freesync_handle_v_update(dm->freesync_module,
198 						     new_stream, &vrr_params);
199 
200 			/* Need to call this before the frame ends. */
201 			dc_stream_adjust_vmin_vmax(dm->dc,
202 						   new_crtc_state->stream,
203 						   &vrr_params.adjust);
204 		}
205 	}
206 
207 	aconn = (struct amdgpu_dm_connector *)new_stream->dm_stream_context;
208 
209 	if (aconn && (aconn->as_type == FREESYNC_TYPE_PCON_IN_WHITELIST || aconn->vsdb_info.replay_mode)) {
210 		pack_sdp_v1_3 = aconn->pack_sdp_v1_3;
211 
212 		if (aconn->vsdb_info.amd_vsdb_version == 1)
213 			packet_type = PACKET_TYPE_FS_V1;
214 		else if (aconn->vsdb_info.amd_vsdb_version == 2)
215 			packet_type = PACKET_TYPE_FS_V2;
216 		else if (aconn->vsdb_info.amd_vsdb_version == 3)
217 			packet_type = PACKET_TYPE_FS_V3;
218 
219 		mod_build_adaptive_sync_infopacket(new_stream, aconn->as_type, NULL,
220 					&new_stream->adaptive_sync_infopacket);
221 	}
222 
223 	mod_freesync_build_vrr_infopacket(
224 		dm->freesync_module,
225 		new_stream,
226 		&vrr_params,
227 		packet_type,
228 		TRANSFER_FUNC_UNKNOWN,
229 		&vrr_infopacket,
230 		pack_sdp_v1_3);
231 
232 	new_crtc_state->freesync_vrr_info_changed |=
233 		(memcmp(&new_crtc_state->vrr_infopacket,
234 			&vrr_infopacket,
235 			sizeof(vrr_infopacket)) != 0);
236 
237 	acrtc->dm_irq_params.vrr_params = vrr_params;
238 	new_crtc_state->vrr_infopacket = vrr_infopacket;
239 
240 	new_stream->vrr_infopacket = vrr_infopacket;
241 	new_stream->allow_freesync = mod_freesync_get_freesync_enabled(&vrr_params);
242 
243 	if (new_crtc_state->freesync_vrr_info_changed)
244 		drm_dbg_kms(adev_to_drm(adev), "VRR packet update: crtc=%u enabled=%d state=%d",
245 			      new_crtc_state->base.crtc->base.id,
246 			      (int)new_crtc_state->base.vrr_enabled,
247 			      (int)vrr_params.state);
248 
249 	spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
250 }
251 
252 void amdgpu_dm_update_stream_irq_parameters(
253 	struct amdgpu_display_manager *dm,
254 	struct dm_crtc_state *new_crtc_state)
255 {
256 	struct dc_stream_state *new_stream = new_crtc_state->stream;
257 	struct mod_vrr_params vrr_params;
258 	struct mod_freesync_config config = new_crtc_state->freesync_config;
259 	struct amdgpu_device *adev = dm->adev;
260 	struct amdgpu_crtc *acrtc = to_amdgpu_crtc(new_crtc_state->base.crtc);
261 	unsigned long flags;
262 
263 	if (!new_stream)
264 		return;
265 
266 	/*
267 	 * TODO: Determine why min/max totals and vrefresh can be 0 here.
268 	 * For now it's sufficient to just guard against these conditions.
269 	 */
270 	if (!new_stream->timing.h_total || !new_stream->timing.v_total)
271 		return;
272 
273 	spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
274 	vrr_params = acrtc->dm_irq_params.vrr_params;
275 
276 	if (new_crtc_state->vrr_supported &&
277 	    config.min_refresh_in_uhz &&
278 	    config.max_refresh_in_uhz) {
279 		/*
280 		 * if freesync compatible mode was set, config.state will be set
281 		 * in atomic check
282 		 */
283 		if (config.state == VRR_STATE_ACTIVE_FIXED && config.fixed_refresh_in_uhz &&
284 		    (!drm_atomic_crtc_needs_modeset(&new_crtc_state->base) ||
285 		     new_crtc_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED)) {
286 			vrr_params.max_refresh_in_uhz = config.max_refresh_in_uhz;
287 			vrr_params.min_refresh_in_uhz = config.min_refresh_in_uhz;
288 			vrr_params.fixed_refresh_in_uhz = config.fixed_refresh_in_uhz;
289 			vrr_params.state = VRR_STATE_ACTIVE_FIXED;
290 		} else {
291 			config.state = new_crtc_state->base.vrr_enabled ?
292 						     VRR_STATE_ACTIVE_VARIABLE :
293 						     VRR_STATE_INACTIVE;
294 		}
295 	} else {
296 		config.state = VRR_STATE_UNSUPPORTED;
297 	}
298 
299 	mod_freesync_build_vrr_params(dm->freesync_module,
300 				      new_stream,
301 				      &config, &vrr_params);
302 
303 	new_crtc_state->freesync_config = config;
304 	/* Copy state for access from DM IRQ handler */
305 	acrtc->dm_irq_params.freesync_config = config;
306 	acrtc->dm_irq_params.active_planes = new_crtc_state->active_planes;
307 	acrtc->dm_irq_params.vrr_params = vrr_params;
308 	spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
309 }
310 
311 void amdgpu_dm_handle_vrr_transition(struct amdgpu_display_manager *dm,
312 				     struct dm_crtc_state *old_state,
313 				     struct dm_crtc_state *new_state)
314 {
315 	struct amdgpu_device *adev = dm->adev;
316 	bool old_vrr_active = amdgpu_dm_crtc_vrr_active(old_state);
317 	bool new_vrr_active = amdgpu_dm_crtc_vrr_active(new_state);
318 
319 	/* Only DCE gates vupdate on VRR, keep it enabled for DCN */
320 	bool vrr_gates_vupdate = amdgpu_ip_version(adev, DCE_HWIP, 0) == 0;
321 
322 	if (!old_vrr_active && new_vrr_active) {
323 		/* Transition VRR inactive -> active:
324 		 * While VRR is active, we must not disable vblank irq, as a
325 		 * reenable after disable would compute bogus vblank/pflip
326 		 * timestamps if it likely happened inside display front-porch.
327 		 *
328 		 * We also need vupdate irq for the actual core vblank handling
329 		 * at end of vblank.
330 		 */
331 		if (vrr_gates_vupdate)
332 			WARN_ON(amdgpu_dm_crtc_set_vupdate_irq(new_state->base.crtc, true) != 0);
333 		WARN_ON(drm_crtc_vblank_get(new_state->base.crtc) != 0);
334 		drm_dbg_driver(new_state->base.crtc->dev, "%s: crtc=%u VRR off->on: Get vblank ref\n",
335 				 __func__, new_state->base.crtc->base.id);
336 
337 		scoped_guard(mutex, &dm->dc_lock) {
338 			dc_exit_ips_for_hw_access(dm->dc);
339 			amdgpu_dm_psr_set_event(dm, new_state->stream, true,
340 				psr_event_vrr_transition, true);
341 			amdgpu_dm_replay_set_event(dm, new_state->stream, true,
342 				replay_event_vrr, true);
343 		}
344 	} else if (old_vrr_active && !new_vrr_active) {
345 		/* Transition VRR active -> inactive:
346 		 * Allow vblank irq disable again for fixed refresh rate.
347 		 */
348 		if (vrr_gates_vupdate)
349 			WARN_ON(amdgpu_dm_crtc_set_vupdate_irq(new_state->base.crtc, false) != 0);
350 		drm_crtc_vblank_put(new_state->base.crtc);
351 		drm_dbg_driver(new_state->base.crtc->dev, "%s: crtc=%u VRR on->off: Drop vblank ref\n",
352 				 __func__, new_state->base.crtc->base.id);
353 
354 		scoped_guard(mutex, &dm->dc_lock) {
355 			dc_exit_ips_for_hw_access(dm->dc);
356 			amdgpu_dm_psr_set_event(dm, new_state->stream, false,
357 				psr_event_vrr_transition, false);
358 			amdgpu_dm_replay_set_event(dm, new_state->stream, false,
359 				replay_event_vrr, false);
360 		}
361 	}
362 }
363