xref: /linux/drivers/gpu/drm/amd/display/modules/freesync/freesync.c (revision 3a6541e97c035dba90cdf37169d73b2d8057e55d)
1  /*
2   * Copyright 2016 Advanced Micro Devices, Inc.
3   *
4   * Permission is hereby granted, free of charge, to any person obtaining a
5   * copy of this software and associated documentation files (the "Software"),
6   * to deal in the Software without restriction, including without limitation
7   * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8   * and/or sell copies of the Software, and to permit persons to whom the
9   * Software is furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17   * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18   * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19   * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20   * OTHER DEALINGS IN THE SOFTWARE.
21   *
22   * Authors: AMD
23   *
24   */
25  
26  #include <linux/slab.h>
27  
28  #include "dm_services.h"
29  #include "dc.h"
30  #include "mod_freesync.h"
31  #include "core_types.h"
32  
33  #define MOD_FREESYNC_MAX_CONCURRENT_STREAMS  32
34  
35  #define MIN_REFRESH_RANGE 10
36  /* Refresh rate ramp at a fixed rate of 65 Hz/second */
37  #define STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME ((1000 / 60) * 65)
38  /* Number of elements in the render times cache array */
39  #define RENDER_TIMES_MAX_COUNT 10
40  /* Threshold to exit/exit BTR (to avoid frequent enter-exits at the lower limit) */
41  #define BTR_MAX_MARGIN 2500
42  /* Threshold to change BTR multiplier (to avoid frequent changes) */
43  #define BTR_DRIFT_MARGIN 2000
44  /* Threshold to exit fixed refresh rate */
45  #define FIXED_REFRESH_EXIT_MARGIN_IN_HZ 1
46  /* Number of consecutive frames to check before entering/exiting fixed refresh */
47  #define FIXED_REFRESH_ENTER_FRAME_COUNT 5
48  #define FIXED_REFRESH_EXIT_FRAME_COUNT 10
49  
50  struct core_freesync {
51  	struct mod_freesync public;
52  	struct dc *dc;
53  };
54  
55  #define MOD_FREESYNC_TO_CORE(mod_freesync)\
56  		container_of(mod_freesync, struct core_freesync, public)
57  
58  struct mod_freesync *mod_freesync_create(struct dc *dc)
59  {
60  	struct core_freesync *core_freesync =
61  			kzalloc(sizeof(struct core_freesync), GFP_KERNEL);
62  
63  	if (core_freesync == NULL)
64  		goto fail_alloc_context;
65  
66  	if (dc == NULL)
67  		goto fail_construct;
68  
69  	core_freesync->dc = dc;
70  	return &core_freesync->public;
71  
72  fail_construct:
73  	kfree(core_freesync);
74  
75  fail_alloc_context:
76  	return NULL;
77  }
78  
79  void mod_freesync_destroy(struct mod_freesync *mod_freesync)
80  {
81  	struct core_freesync *core_freesync = NULL;
82  	if (mod_freesync == NULL)
83  		return;
84  	core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync);
85  	kfree(core_freesync);
86  }
87  
88  #if 0 /* Unused currently */
89  static unsigned int calc_refresh_in_uhz_from_duration(
90  		unsigned int duration_in_ns)
91  {
92  	unsigned int refresh_in_uhz =
93  			((unsigned int)(div64_u64((1000000000ULL * 1000000),
94  					duration_in_ns)));
95  	return refresh_in_uhz;
96  }
97  #endif
98  
99  static unsigned int calc_duration_in_us_from_refresh_in_uhz(
100  		unsigned int refresh_in_uhz)
101  {
102  	unsigned int duration_in_us =
103  			((unsigned int)(div64_u64((1000000000ULL * 1000),
104  					refresh_in_uhz)));
105  	return duration_in_us;
106  }
107  
108  static unsigned int calc_duration_in_us_from_v_total(
109  		const struct dc_stream_state *stream,
110  		const struct mod_vrr_params *in_vrr,
111  		unsigned int v_total)
112  {
113  	unsigned int duration_in_us =
114  			(unsigned int)(div64_u64(((unsigned long long)(v_total)
115  				* 10000) * stream->timing.h_total,
116  					stream->timing.pix_clk_100hz));
117  
118  	return duration_in_us;
119  }
120  
121  unsigned int mod_freesync_calc_v_total_from_refresh(
122  		const struct dc_stream_state *stream,
123  		unsigned int refresh_in_uhz)
124  {
125  	unsigned int v_total;
126  	unsigned int frame_duration_in_ns;
127  
128  	frame_duration_in_ns =
129  			((unsigned int)(div64_u64((1000000000ULL * 1000000),
130  					refresh_in_uhz)));
131  
132  	v_total = div64_u64(div64_u64(((unsigned long long)(
133  			frame_duration_in_ns) * (stream->timing.pix_clk_100hz / 10)),
134  			stream->timing.h_total), 1000000);
135  
136  	/* v_total cannot be less than nominal */
137  	if (v_total < stream->timing.v_total) {
138  		ASSERT(v_total < stream->timing.v_total);
139  		v_total = stream->timing.v_total;
140  	}
141  
142  	return v_total;
143  }
144  
145  static unsigned int calc_v_total_from_duration(
146  		const struct dc_stream_state *stream,
147  		const struct mod_vrr_params *vrr,
148  		unsigned int duration_in_us)
149  {
150  	unsigned int v_total = 0;
151  
152  	if (duration_in_us < vrr->min_duration_in_us)
153  		duration_in_us = vrr->min_duration_in_us;
154  
155  	if (duration_in_us > vrr->max_duration_in_us)
156  		duration_in_us = vrr->max_duration_in_us;
157  
158  	v_total = div64_u64(div64_u64(((unsigned long long)(
159  				duration_in_us) * (stream->timing.pix_clk_100hz / 10)),
160  				stream->timing.h_total), 1000);
161  
162  	/* v_total cannot be less than nominal */
163  	if (v_total < stream->timing.v_total) {
164  		ASSERT(v_total < stream->timing.v_total);
165  		v_total = stream->timing.v_total;
166  	}
167  
168  	return v_total;
169  }
170  
171  static void update_v_total_for_static_ramp(
172  		struct core_freesync *core_freesync,
173  		const struct dc_stream_state *stream,
174  		struct mod_vrr_params *in_out_vrr)
175  {
176  	unsigned int v_total = 0;
177  	unsigned int current_duration_in_us =
178  			calc_duration_in_us_from_v_total(
179  				stream, in_out_vrr,
180  				in_out_vrr->adjust.v_total_max);
181  	unsigned int target_duration_in_us =
182  			calc_duration_in_us_from_refresh_in_uhz(
183  				in_out_vrr->fixed.target_refresh_in_uhz);
184  	bool ramp_direction_is_up = (current_duration_in_us >
185  				target_duration_in_us) ? true : false;
186  
187  	/* Calculate ratio between new and current frame duration with 3 digit */
188  	unsigned int frame_duration_ratio = div64_u64(1000000,
189  		(1000 +  div64_u64(((unsigned long long)(
190  		STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME) *
191  		current_duration_in_us),
192  		1000000)));
193  
194  	/* Calculate delta between new and current frame duration in us */
195  	unsigned int frame_duration_delta = div64_u64(((unsigned long long)(
196  		current_duration_in_us) *
197  		(1000 - frame_duration_ratio)), 1000);
198  
199  	/* Adjust frame duration delta based on ratio between current and
200  	 * standard frame duration (frame duration at 60 Hz refresh rate).
201  	 */
202  	unsigned int ramp_rate_interpolated = div64_u64(((unsigned long long)(
203  		frame_duration_delta) * current_duration_in_us), 16666);
204  
205  	/* Going to a higher refresh rate (lower frame duration) */
206  	if (ramp_direction_is_up) {
207  		/* Reduce frame duration */
208  		current_duration_in_us -= ramp_rate_interpolated;
209  
210  		/* Adjust for frame duration below min */
211  		if (current_duration_in_us <= target_duration_in_us) {
212  			in_out_vrr->fixed.ramping_active = false;
213  			in_out_vrr->fixed.ramping_done = true;
214  			current_duration_in_us =
215  				calc_duration_in_us_from_refresh_in_uhz(
216  				in_out_vrr->fixed.target_refresh_in_uhz);
217  		}
218  	/* Going to a lower refresh rate (larger frame duration) */
219  	} else {
220  		/* Increase frame duration */
221  		current_duration_in_us += ramp_rate_interpolated;
222  
223  		/* Adjust for frame duration above max */
224  		if (current_duration_in_us >= target_duration_in_us) {
225  			in_out_vrr->fixed.ramping_active = false;
226  			in_out_vrr->fixed.ramping_done = true;
227  			current_duration_in_us =
228  				calc_duration_in_us_from_refresh_in_uhz(
229  				in_out_vrr->fixed.target_refresh_in_uhz);
230  		}
231  	}
232  
233  	v_total = div64_u64(div64_u64(((unsigned long long)(
234  			current_duration_in_us) * (stream->timing.pix_clk_100hz / 10)),
235  				stream->timing.h_total), 1000);
236  
237  	/* v_total cannot be less than nominal */
238  	if (v_total < stream->timing.v_total)
239  		v_total = stream->timing.v_total;
240  
241  	in_out_vrr->adjust.v_total_min = v_total;
242  	in_out_vrr->adjust.v_total_max = v_total;
243  }
244  
245  static void apply_below_the_range(struct core_freesync *core_freesync,
246  		const struct dc_stream_state *stream,
247  		unsigned int last_render_time_in_us,
248  		struct mod_vrr_params *in_out_vrr)
249  {
250  	unsigned int inserted_frame_duration_in_us = 0;
251  	unsigned int mid_point_frames_ceil = 0;
252  	unsigned int mid_point_frames_floor = 0;
253  	unsigned int frame_time_in_us = 0;
254  	unsigned int delta_from_mid_point_in_us_1 = 0xFFFFFFFF;
255  	unsigned int delta_from_mid_point_in_us_2 = 0xFFFFFFFF;
256  	unsigned int frames_to_insert = 0;
257  	unsigned int delta_from_mid_point_delta_in_us;
258  	unsigned int max_render_time_in_us =
259  			in_out_vrr->max_duration_in_us - in_out_vrr->btr.margin_in_us;
260  
261  	/* Program BTR */
262  	if ((last_render_time_in_us + in_out_vrr->btr.margin_in_us / 2) < max_render_time_in_us) {
263  		/* Exit Below the Range */
264  		if (in_out_vrr->btr.btr_active) {
265  			in_out_vrr->btr.frame_counter = 0;
266  			in_out_vrr->btr.btr_active = false;
267  		}
268  	} else if (last_render_time_in_us > (max_render_time_in_us + in_out_vrr->btr.margin_in_us / 2)) {
269  		/* Enter Below the Range */
270  		if (!in_out_vrr->btr.btr_active) {
271  			in_out_vrr->btr.btr_active = true;
272  		}
273  	}
274  
275  	/* BTR set to "not active" so disengage */
276  	if (!in_out_vrr->btr.btr_active) {
277  		in_out_vrr->btr.inserted_duration_in_us = 0;
278  		in_out_vrr->btr.frames_to_insert = 0;
279  		in_out_vrr->btr.frame_counter = 0;
280  
281  		/* Restore FreeSync */
282  		in_out_vrr->adjust.v_total_min =
283  			mod_freesync_calc_v_total_from_refresh(stream,
284  				in_out_vrr->max_refresh_in_uhz);
285  		in_out_vrr->adjust.v_total_max =
286  			mod_freesync_calc_v_total_from_refresh(stream,
287  				in_out_vrr->min_refresh_in_uhz);
288  	/* BTR set to "active" so engage */
289  	} else {
290  
291  		/* Calculate number of midPoint frames that could fit within
292  		 * the render time interval - take ceil of this value
293  		 */
294  		mid_point_frames_ceil = (last_render_time_in_us +
295  				in_out_vrr->btr.mid_point_in_us - 1) /
296  					in_out_vrr->btr.mid_point_in_us;
297  
298  		if (mid_point_frames_ceil > 0) {
299  			frame_time_in_us = last_render_time_in_us /
300  				mid_point_frames_ceil;
301  			delta_from_mid_point_in_us_1 =
302  				(in_out_vrr->btr.mid_point_in_us >
303  				frame_time_in_us) ?
304  				(in_out_vrr->btr.mid_point_in_us - frame_time_in_us) :
305  				(frame_time_in_us - in_out_vrr->btr.mid_point_in_us);
306  		}
307  
308  		/* Calculate number of midPoint frames that could fit within
309  		 * the render time interval - take floor of this value
310  		 */
311  		mid_point_frames_floor = last_render_time_in_us /
312  				in_out_vrr->btr.mid_point_in_us;
313  
314  		if (mid_point_frames_floor > 0) {
315  
316  			frame_time_in_us = last_render_time_in_us /
317  				mid_point_frames_floor;
318  			delta_from_mid_point_in_us_2 =
319  				(in_out_vrr->btr.mid_point_in_us >
320  				frame_time_in_us) ?
321  				(in_out_vrr->btr.mid_point_in_us - frame_time_in_us) :
322  				(frame_time_in_us - in_out_vrr->btr.mid_point_in_us);
323  		}
324  
325  		/* Choose number of frames to insert based on how close it
326  		 * can get to the mid point of the variable range.
327  		 *  - Delta for CEIL: delta_from_mid_point_in_us_1
328  		 *  - Delta for FLOOR: delta_from_mid_point_in_us_2
329  		 */
330  		if ((last_render_time_in_us / mid_point_frames_ceil) < in_out_vrr->min_duration_in_us) {
331  			/* Check for out of range.
332  			 * If using CEIL produces a value that is out of range,
333  			 * then we are forced to use FLOOR.
334  			 */
335  			frames_to_insert = mid_point_frames_floor;
336  		} else if (mid_point_frames_floor < 2) {
337  			/* Check if FLOOR would result in non-LFC. In this case
338  			 * choose to use CEIL
339  			 */
340  			frames_to_insert = mid_point_frames_ceil;
341  		} else if (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2) {
342  			/* If choosing CEIL results in a frame duration that is
343  			 * closer to the mid point of the range.
344  			 * Choose CEIL
345  			 */
346  			frames_to_insert = mid_point_frames_ceil;
347  		} else {
348  			/* If choosing FLOOR results in a frame duration that is
349  			 * closer to the mid point of the range.
350  			 * Choose FLOOR
351  			 */
352  			frames_to_insert = mid_point_frames_floor;
353  		}
354  
355  		/* Prefer current frame multiplier when BTR is enabled unless it drifts
356  		 * too far from the midpoint
357  		 */
358  		if (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2) {
359  			delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_2 -
360  					delta_from_mid_point_in_us_1;
361  		} else {
362  			delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_1 -
363  					delta_from_mid_point_in_us_2;
364  		}
365  		if (in_out_vrr->btr.frames_to_insert != 0 &&
366  				delta_from_mid_point_delta_in_us < BTR_DRIFT_MARGIN) {
367  			if (((last_render_time_in_us / in_out_vrr->btr.frames_to_insert) <
368  					max_render_time_in_us) &&
369  				((last_render_time_in_us / in_out_vrr->btr.frames_to_insert) >
370  					in_out_vrr->min_duration_in_us))
371  				frames_to_insert = in_out_vrr->btr.frames_to_insert;
372  		}
373  
374  		/* Either we've calculated the number of frames to insert,
375  		 * or we need to insert min duration frames
376  		 */
377  		if (last_render_time_in_us / frames_to_insert <
378  				in_out_vrr->min_duration_in_us){
379  			frames_to_insert -= (frames_to_insert > 1) ?
380  					1 : 0;
381  		}
382  
383  		if (frames_to_insert > 0)
384  			inserted_frame_duration_in_us = last_render_time_in_us /
385  							frames_to_insert;
386  
387  		if (inserted_frame_duration_in_us < in_out_vrr->min_duration_in_us)
388  			inserted_frame_duration_in_us = in_out_vrr->min_duration_in_us;
389  
390  		/* Cache the calculated variables */
391  		in_out_vrr->btr.inserted_duration_in_us =
392  			inserted_frame_duration_in_us;
393  		in_out_vrr->btr.frames_to_insert = frames_to_insert;
394  		in_out_vrr->btr.frame_counter = frames_to_insert;
395  	}
396  }
397  
398  static void apply_fixed_refresh(struct core_freesync *core_freesync,
399  		const struct dc_stream_state *stream,
400  		unsigned int last_render_time_in_us,
401  		struct mod_vrr_params *in_out_vrr)
402  {
403  	bool update = false;
404  	unsigned int max_render_time_in_us = in_out_vrr->max_duration_in_us;
405  
406  	/* Compute the exit refresh rate and exit frame duration */
407  	unsigned int exit_refresh_rate_in_milli_hz = ((1000000000/max_render_time_in_us)
408  			+ (1000*FIXED_REFRESH_EXIT_MARGIN_IN_HZ));
409  	unsigned int exit_frame_duration_in_us = 1000000000/exit_refresh_rate_in_milli_hz;
410  
411  	if (last_render_time_in_us < exit_frame_duration_in_us) {
412  		/* Exit Fixed Refresh mode */
413  		if (in_out_vrr->fixed.fixed_active) {
414  			in_out_vrr->fixed.frame_counter++;
415  
416  			if (in_out_vrr->fixed.frame_counter >
417  					FIXED_REFRESH_EXIT_FRAME_COUNT) {
418  				in_out_vrr->fixed.frame_counter = 0;
419  				in_out_vrr->fixed.fixed_active = false;
420  				in_out_vrr->fixed.target_refresh_in_uhz = 0;
421  				update = true;
422  			}
423  		} else
424  			in_out_vrr->fixed.frame_counter = 0;
425  	} else if (last_render_time_in_us > max_render_time_in_us) {
426  		/* Enter Fixed Refresh mode */
427  		if (!in_out_vrr->fixed.fixed_active) {
428  			in_out_vrr->fixed.frame_counter++;
429  
430  			if (in_out_vrr->fixed.frame_counter >
431  					FIXED_REFRESH_ENTER_FRAME_COUNT) {
432  				in_out_vrr->fixed.frame_counter = 0;
433  				in_out_vrr->fixed.fixed_active = true;
434  				in_out_vrr->fixed.target_refresh_in_uhz =
435  						in_out_vrr->max_refresh_in_uhz;
436  				update = true;
437  			}
438  		} else
439  			in_out_vrr->fixed.frame_counter = 0;
440  	}
441  
442  	if (update) {
443  		if (in_out_vrr->fixed.fixed_active) {
444  			in_out_vrr->adjust.v_total_min =
445  				mod_freesync_calc_v_total_from_refresh(
446  				stream, in_out_vrr->max_refresh_in_uhz);
447  			in_out_vrr->adjust.v_total_max =
448  					in_out_vrr->adjust.v_total_min;
449  		} else {
450  			in_out_vrr->adjust.v_total_min =
451  				mod_freesync_calc_v_total_from_refresh(stream,
452  					in_out_vrr->max_refresh_in_uhz);
453  			in_out_vrr->adjust.v_total_max =
454  				mod_freesync_calc_v_total_from_refresh(stream,
455  					in_out_vrr->min_refresh_in_uhz);
456  		}
457  	}
458  }
459  
460  static bool vrr_settings_require_update(struct core_freesync *core_freesync,
461  		struct mod_freesync_config *in_config,
462  		unsigned int min_refresh_in_uhz,
463  		unsigned int max_refresh_in_uhz,
464  		struct mod_vrr_params *in_vrr)
465  {
466  	if (in_vrr->state != in_config->state) {
467  		return true;
468  	} else if (in_vrr->state == VRR_STATE_ACTIVE_FIXED &&
469  			in_vrr->fixed.target_refresh_in_uhz !=
470  					in_config->fixed_refresh_in_uhz) {
471  		return true;
472  	} else if (in_vrr->min_refresh_in_uhz != min_refresh_in_uhz) {
473  		return true;
474  	} else if (in_vrr->max_refresh_in_uhz != max_refresh_in_uhz) {
475  		return true;
476  	}
477  
478  	return false;
479  }
480  
481  bool mod_freesync_get_vmin_vmax(struct mod_freesync *mod_freesync,
482  		const struct dc_stream_state *stream,
483  		unsigned int *vmin,
484  		unsigned int *vmax)
485  {
486  	*vmin = stream->adjust.v_total_min;
487  	*vmax = stream->adjust.v_total_max;
488  
489  	return true;
490  }
491  
492  bool mod_freesync_get_v_position(struct mod_freesync *mod_freesync,
493  		struct dc_stream_state *stream,
494  		unsigned int *nom_v_pos,
495  		unsigned int *v_pos)
496  {
497  	struct core_freesync *core_freesync = NULL;
498  	struct crtc_position position;
499  
500  	if (mod_freesync == NULL)
501  		return false;
502  
503  	core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync);
504  
505  	if (dc_stream_get_crtc_position(core_freesync->dc, &stream, 1,
506  					&position.vertical_count,
507  					&position.nominal_vcount)) {
508  
509  		*nom_v_pos = position.nominal_vcount;
510  		*v_pos = position.vertical_count;
511  
512  		return true;
513  	}
514  
515  	return false;
516  }
517  
518  static void build_vrr_infopacket_data_v1(const struct mod_vrr_params *vrr,
519  		struct dc_info_packet *infopacket,
520  		bool freesync_on_desktop)
521  {
522  	/* PB1 = 0x1A (24bit AMD IEEE OUI (0x00001A) - Byte 0) */
523  	infopacket->sb[1] = 0x1A;
524  
525  	/* PB2 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 1) */
526  	infopacket->sb[2] = 0x00;
527  
528  	/* PB3 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 2) */
529  	infopacket->sb[3] = 0x00;
530  
531  	/* PB4 = Reserved */
532  
533  	/* PB5 = Reserved */
534  
535  	/* PB6 = [Bits 7:3 = Reserved] */
536  
537  	/* PB6 = [Bit 0 = FreeSync Supported] */
538  	if (vrr->state != VRR_STATE_UNSUPPORTED)
539  		infopacket->sb[6] |= 0x01;
540  
541  	/* PB6 = [Bit 1 = FreeSync Enabled] */
542  	if (vrr->state != VRR_STATE_DISABLED &&
543  			vrr->state != VRR_STATE_UNSUPPORTED)
544  		infopacket->sb[6] |= 0x02;
545  
546  	if (freesync_on_desktop) {
547  		/* PB6 = [Bit 2 = FreeSync Active] */
548  		if (vrr->state != VRR_STATE_DISABLED &&
549  			vrr->state != VRR_STATE_UNSUPPORTED)
550  			infopacket->sb[6] |= 0x04;
551  	} else {
552  		if (vrr->state == VRR_STATE_ACTIVE_VARIABLE ||
553  			vrr->state == VRR_STATE_ACTIVE_FIXED)
554  			infopacket->sb[6] |= 0x04;
555  	}
556  
557  	// For v1 & 2 infoframes program nominal if non-fs mode, otherwise full range
558  	/* PB7 = FreeSync Minimum refresh rate (Hz) */
559  	if (vrr->state == VRR_STATE_ACTIVE_VARIABLE ||
560  			vrr->state == VRR_STATE_ACTIVE_FIXED) {
561  		infopacket->sb[7] = (unsigned char)((vrr->min_refresh_in_uhz + 500000) / 1000000);
562  	} else {
563  		infopacket->sb[7] = (unsigned char)((vrr->max_refresh_in_uhz + 500000) / 1000000);
564  	}
565  
566  	/* PB8 = FreeSync Maximum refresh rate (Hz)
567  	 * Note: We should never go above the field rate of the mode timing set.
568  	 */
569  	infopacket->sb[8] = (unsigned char)((vrr->max_refresh_in_uhz + 500000) / 1000000);
570  
571  	/* FreeSync HDR */
572  	infopacket->sb[9] = 0;
573  	infopacket->sb[10] = 0;
574  }
575  
576  static void build_vrr_infopacket_data_v3(const struct mod_vrr_params *vrr,
577  		struct dc_info_packet *infopacket)
578  {
579  	unsigned int min_refresh;
580  	unsigned int max_refresh;
581  	unsigned int fixed_refresh;
582  	unsigned int min_programmed;
583  	unsigned int max_programmed;
584  
585  	/* PB1 = 0x1A (24bit AMD IEEE OUI (0x00001A) - Byte 0) */
586  	infopacket->sb[1] = 0x1A;
587  
588  	/* PB2 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 1) */
589  	infopacket->sb[2] = 0x00;
590  
591  	/* PB3 = 0x00 (24bit AMD IEEE OUI (0x00001A) - Byte 2) */
592  	infopacket->sb[3] = 0x00;
593  
594  	/* PB4 = Reserved */
595  
596  	/* PB5 = Reserved */
597  
598  	/* PB6 = [Bits 7:3 = Reserved] */
599  
600  	/* PB6 = [Bit 0 = FreeSync Supported] */
601  	if (vrr->state != VRR_STATE_UNSUPPORTED)
602  		infopacket->sb[6] |= 0x01;
603  
604  	/* PB6 = [Bit 1 = FreeSync Enabled] */
605  	if (vrr->state != VRR_STATE_DISABLED &&
606  			vrr->state != VRR_STATE_UNSUPPORTED)
607  		infopacket->sb[6] |= 0x02;
608  
609  	/* PB6 = [Bit 2 = FreeSync Active] */
610  	if (vrr->state == VRR_STATE_ACTIVE_VARIABLE ||
611  			vrr->state == VRR_STATE_ACTIVE_FIXED)
612  		infopacket->sb[6] |= 0x04;
613  
614  	min_refresh = (vrr->min_refresh_in_uhz + 500000) / 1000000;
615  	max_refresh = (vrr->max_refresh_in_uhz + 500000) / 1000000;
616  	fixed_refresh = (vrr->fixed_refresh_in_uhz + 500000) / 1000000;
617  
618  	min_programmed = (vrr->state == VRR_STATE_ACTIVE_FIXED) ? fixed_refresh :
619  			(vrr->state == VRR_STATE_ACTIVE_VARIABLE) ? min_refresh :
620  			(vrr->state == VRR_STATE_INACTIVE) ? min_refresh :
621  			max_refresh; // Non-fs case, program nominal range
622  
623  	max_programmed = (vrr->state == VRR_STATE_ACTIVE_FIXED) ? fixed_refresh :
624  			(vrr->state == VRR_STATE_ACTIVE_VARIABLE) ? max_refresh :
625  			max_refresh;// Non-fs case, program nominal range
626  
627  	/* PB7 = FreeSync Minimum refresh rate (Hz) */
628  	infopacket->sb[7] = min_programmed & 0xFF;
629  
630  	/* PB8 = FreeSync Maximum refresh rate (Hz) */
631  	infopacket->sb[8] = max_programmed & 0xFF;
632  
633  	/* PB11 : MSB FreeSync Minimum refresh rate [Hz] - bits 9:8 */
634  	infopacket->sb[11] = (min_programmed >> 8) & 0x03;
635  
636  	/* PB12 : MSB FreeSync Maximum refresh rate [Hz] - bits 9:8 */
637  	infopacket->sb[12] = (max_programmed >> 8) & 0x03;
638  
639  	/* PB16 : Reserved bits 7:1, FixedRate bit 0 */
640  	infopacket->sb[16] = (vrr->state == VRR_STATE_ACTIVE_FIXED) ? 1 : 0;
641  
642  	//FreeSync HDR
643  	infopacket->sb[9] = 0;
644  	infopacket->sb[10] = 0;
645  }
646  
647  static void build_vrr_infopacket_fs2_data(enum color_transfer_func app_tf,
648  		struct dc_info_packet *infopacket)
649  {
650  	if (app_tf != TRANSFER_FUNC_UNKNOWN) {
651  		infopacket->valid = true;
652  
653  		infopacket->sb[6] |= 0x08;  // PB6 = [Bit 3 = Native Color Active]
654  
655  		if (app_tf == TRANSFER_FUNC_GAMMA_22) {
656  			infopacket->sb[9] |= 0x04;  // PB6 = [Bit 2 = Gamma 2.2 EOTF Active]
657  		}
658  	}
659  }
660  
661  static void build_vrr_infopacket_header_v1(enum signal_type signal,
662  		struct dc_info_packet *infopacket,
663  		unsigned int *payload_size)
664  {
665  	if (dc_is_hdmi_signal(signal)) {
666  
667  		/* HEADER */
668  
669  		/* HB0  = Packet Type = 0x83 (Source Product
670  		 *	  Descriptor InfoFrame)
671  		 */
672  		infopacket->hb0 = DC_HDMI_INFOFRAME_TYPE_SPD;
673  
674  		/* HB1  = Version = 0x01 */
675  		infopacket->hb1 = 0x01;
676  
677  		/* HB2  = [Bits 7:5 = 0] [Bits 4:0 = Length = 0x08] */
678  		infopacket->hb2 = 0x08;
679  
680  		*payload_size = 0x08;
681  
682  	} else if (dc_is_dp_signal(signal)) {
683  
684  		/* HEADER */
685  
686  		/* HB0  = Secondary-data Packet ID = 0 - Only non-zero
687  		 *	  when used to associate audio related info packets
688  		 */
689  		infopacket->hb0 = 0x00;
690  
691  		/* HB1  = Packet Type = 0x83 (Source Product
692  		 *	  Descriptor InfoFrame)
693  		 */
694  		infopacket->hb1 = DC_HDMI_INFOFRAME_TYPE_SPD;
695  
696  		/* HB2  = [Bits 7:0 = Least significant eight bits -
697  		 *	  For INFOFRAME, the value must be 1Bh]
698  		 */
699  		infopacket->hb2 = 0x1B;
700  
701  		/* HB3  = [Bits 7:2 = INFOFRAME SDP Version Number = 0x1]
702  		 *	  [Bits 1:0 = Most significant two bits = 0x00]
703  		 */
704  		infopacket->hb3 = 0x04;
705  
706  		*payload_size = 0x1B;
707  	}
708  }
709  
710  static void build_vrr_infopacket_header_v2(enum signal_type signal,
711  		struct dc_info_packet *infopacket,
712  		unsigned int *payload_size)
713  {
714  	if (dc_is_hdmi_signal(signal)) {
715  
716  		/* HEADER */
717  
718  		/* HB0  = Packet Type = 0x83 (Source Product
719  		 *	  Descriptor InfoFrame)
720  		 */
721  		infopacket->hb0 = DC_HDMI_INFOFRAME_TYPE_SPD;
722  
723  		/* HB1  = Version = 0x02 */
724  		infopacket->hb1 = 0x02;
725  
726  		/* HB2  = [Bits 7:5 = 0] [Bits 4:0 = Length = 0x09] */
727  		infopacket->hb2 = 0x09;
728  
729  		*payload_size = 0x0A;
730  
731  	} else if (dc_is_dp_signal(signal)) {
732  
733  		/* HEADER */
734  
735  		/* HB0  = Secondary-data Packet ID = 0 - Only non-zero
736  		 *	  when used to associate audio related info packets
737  		 */
738  		infopacket->hb0 = 0x00;
739  
740  		/* HB1  = Packet Type = 0x83 (Source Product
741  		 *	  Descriptor InfoFrame)
742  		 */
743  		infopacket->hb1 = DC_HDMI_INFOFRAME_TYPE_SPD;
744  
745  		/* HB2  = [Bits 7:0 = Least significant eight bits -
746  		 *	  For INFOFRAME, the value must be 1Bh]
747  		 */
748  		infopacket->hb2 = 0x1B;
749  
750  		/* HB3  = [Bits 7:2 = INFOFRAME SDP Version Number = 0x2]
751  		 *	  [Bits 1:0 = Most significant two bits = 0x00]
752  		 */
753  		infopacket->hb3 = 0x08;
754  
755  		*payload_size = 0x1B;
756  	}
757  }
758  
759  static void build_vrr_infopacket_header_v3(enum signal_type signal,
760  		struct dc_info_packet *infopacket,
761  		unsigned int *payload_size)
762  {
763  	unsigned char version;
764  
765  	version = 3;
766  	if (dc_is_hdmi_signal(signal)) {
767  
768  		/* HEADER */
769  
770  		/* HB0  = Packet Type = 0x83 (Source Product
771  		 *	  Descriptor InfoFrame)
772  		 */
773  		infopacket->hb0 = DC_HDMI_INFOFRAME_TYPE_SPD;
774  
775  		/* HB1  = Version = 0x03 */
776  		infopacket->hb1 = version;
777  
778  		/* HB2  = [Bits 7:5 = 0] [Bits 4:0 = Length] */
779  		*payload_size = 0x10;
780  		infopacket->hb2 = *payload_size - 1; //-1 for checksum
781  
782  	} else if (dc_is_dp_signal(signal)) {
783  
784  		/* HEADER */
785  
786  		/* HB0  = Secondary-data Packet ID = 0 - Only non-zero
787  		 *	  when used to associate audio related info packets
788  		 */
789  		infopacket->hb0 = 0x00;
790  
791  		/* HB1  = Packet Type = 0x83 (Source Product
792  		 *	  Descriptor InfoFrame)
793  		 */
794  		infopacket->hb1 = DC_HDMI_INFOFRAME_TYPE_SPD;
795  
796  		/* HB2  = [Bits 7:0 = Least significant eight bits -
797  		 *	  For INFOFRAME, the value must be 1Bh]
798  		 */
799  		infopacket->hb2 = 0x1B;
800  
801  		/* HB3  = [Bits 7:2 = INFOFRAME SDP Version Number = 0x2]
802  		 *	  [Bits 1:0 = Most significant two bits = 0x00]
803  		 */
804  
805  		infopacket->hb3 = (version & 0x3F) << 2;
806  
807  		*payload_size = 0x1B;
808  	}
809  }
810  
811  static void build_vrr_infopacket_checksum(unsigned int *payload_size,
812  		struct dc_info_packet *infopacket)
813  {
814  	/* Calculate checksum */
815  	unsigned int idx = 0;
816  	unsigned char checksum = 0;
817  
818  	checksum += infopacket->hb0;
819  	checksum += infopacket->hb1;
820  	checksum += infopacket->hb2;
821  	checksum += infopacket->hb3;
822  
823  	for (idx = 1; idx <= *payload_size; idx++)
824  		checksum += infopacket->sb[idx];
825  
826  	/* PB0 = Checksum (one byte complement) */
827  	infopacket->sb[0] = (unsigned char)(0x100 - checksum);
828  
829  	infopacket->valid = true;
830  }
831  
832  static void build_vrr_infopacket_v1(enum signal_type signal,
833  		const struct mod_vrr_params *vrr,
834  		struct dc_info_packet *infopacket,
835  		bool freesync_on_desktop)
836  {
837  	/* SPD info packet for FreeSync */
838  	unsigned int payload_size = 0;
839  
840  	build_vrr_infopacket_header_v1(signal, infopacket, &payload_size);
841  	build_vrr_infopacket_data_v1(vrr, infopacket, freesync_on_desktop);
842  	build_vrr_infopacket_checksum(&payload_size, infopacket);
843  
844  	infopacket->valid = true;
845  }
846  
847  static void build_vrr_infopacket_v2(enum signal_type signal,
848  		const struct mod_vrr_params *vrr,
849  		enum color_transfer_func app_tf,
850  		struct dc_info_packet *infopacket,
851  		bool freesync_on_desktop)
852  {
853  	unsigned int payload_size = 0;
854  
855  	build_vrr_infopacket_header_v2(signal, infopacket, &payload_size);
856  	build_vrr_infopacket_data_v1(vrr, infopacket, freesync_on_desktop);
857  
858  	build_vrr_infopacket_fs2_data(app_tf, infopacket);
859  
860  	build_vrr_infopacket_checksum(&payload_size, infopacket);
861  
862  	infopacket->valid = true;
863  }
864  #ifndef TRIM_FSFT
865  static void build_vrr_infopacket_fast_transport_data(
866  	bool ftActive,
867  	unsigned int ftOutputRate,
868  	struct dc_info_packet *infopacket)
869  {
870  	/* PB9 : bit7 - fast transport Active*/
871  	unsigned char activeBit = (ftActive) ? 1 << 7 : 0;
872  
873  	infopacket->sb[1] &= ~activeBit;  //clear bit
874  	infopacket->sb[1] |=  activeBit;  //set bit
875  
876  	/* PB13 : Target Output Pixel Rate [kHz] - bits 7:0  */
877  	infopacket->sb[13] = ftOutputRate & 0xFF;
878  
879  	/* PB14 : Target Output Pixel Rate [kHz] - bits 15:8  */
880  	infopacket->sb[14] = (ftOutputRate >> 8) & 0xFF;
881  
882  	/* PB15 : Target Output Pixel Rate [kHz] - bits 23:16  */
883  	infopacket->sb[15] = (ftOutputRate >> 16) & 0xFF;
884  
885  }
886  #endif
887  
888  static void build_vrr_infopacket_v3(enum signal_type signal,
889  		const struct mod_vrr_params *vrr,
890  #ifndef TRIM_FSFT
891  		bool ftActive, unsigned int ftOutputRate,
892  #endif
893  		enum color_transfer_func app_tf,
894  		struct dc_info_packet *infopacket)
895  {
896  	unsigned int payload_size = 0;
897  
898  	build_vrr_infopacket_header_v3(signal, infopacket, &payload_size);
899  	build_vrr_infopacket_data_v3(vrr, infopacket);
900  
901  	build_vrr_infopacket_fs2_data(app_tf, infopacket);
902  
903  #ifndef TRIM_FSFT
904  	build_vrr_infopacket_fast_transport_data(
905  			ftActive,
906  			ftOutputRate,
907  			infopacket);
908  #endif
909  
910  	build_vrr_infopacket_checksum(&payload_size, infopacket);
911  
912  	infopacket->valid = true;
913  }
914  
915  static void build_vrr_infopacket_sdp_v1_3(enum vrr_packet_type packet_type,
916  										struct dc_info_packet *infopacket)
917  {
918  	uint8_t idx = 0, size = 0;
919  
920  	size = ((packet_type == PACKET_TYPE_FS_V1) ? 0x08 :
921  			(packet_type == PACKET_TYPE_FS_V3) ? 0x10 :
922  												0x09);
923  
924  	for (idx = infopacket->hb2; idx > 1; idx--) // Data Byte Count: 0x1B
925  		infopacket->sb[idx] = infopacket->sb[idx-1];
926  
927  	infopacket->sb[1] = size;                         // Length
928  	infopacket->sb[0] = (infopacket->hb3 >> 2) & 0x3F;//Version
929  	infopacket->hb3   = (0x13 << 2);                  // Header,SDP 1.3
930  	infopacket->hb2   = 0x1D;
931  }
932  
933  void mod_freesync_build_vrr_infopacket(struct mod_freesync *mod_freesync,
934  		const struct dc_stream_state *stream,
935  		const struct mod_vrr_params *vrr,
936  		enum vrr_packet_type packet_type,
937  		enum color_transfer_func app_tf,
938  		struct dc_info_packet *infopacket,
939  		bool pack_sdp_v1_3)
940  {
941  	/* SPD info packet for FreeSync
942  	 * VTEM info packet for HdmiVRR
943  	 * Check if Freesync is supported. Return if false. If true,
944  	 * set the corresponding bit in the info packet
945  	 */
946  	if (!vrr->send_info_frame)
947  		return;
948  
949  	switch (packet_type) {
950  	case PACKET_TYPE_FS_V3:
951  #ifndef TRIM_FSFT
952  		// always populate with pixel rate.
953  		build_vrr_infopacket_v3(
954  				stream->signal, vrr,
955  				stream->timing.flags.FAST_TRANSPORT,
956  				(stream->timing.flags.FAST_TRANSPORT) ?
957  						stream->timing.fast_transport_output_rate_100hz :
958  						stream->timing.pix_clk_100hz,
959  				app_tf, infopacket);
960  #else
961  		build_vrr_infopacket_v3(stream->signal, vrr, app_tf, infopacket);
962  #endif
963  		break;
964  	case PACKET_TYPE_FS_V2:
965  		build_vrr_infopacket_v2(stream->signal, vrr, app_tf, infopacket, stream->freesync_on_desktop);
966  		break;
967  	case PACKET_TYPE_VRR:
968  	case PACKET_TYPE_FS_V1:
969  	default:
970  		build_vrr_infopacket_v1(stream->signal, vrr, infopacket, stream->freesync_on_desktop);
971  	}
972  
973  	if (true == pack_sdp_v1_3 &&
974  		true == dc_is_dp_signal(stream->signal) &&
975  		packet_type != PACKET_TYPE_VRR &&
976  		packet_type != PACKET_TYPE_VTEM)
977  		build_vrr_infopacket_sdp_v1_3(packet_type, infopacket);
978  }
979  
980  void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
981  		const struct dc_stream_state *stream,
982  		struct mod_freesync_config *in_config,
983  		struct mod_vrr_params *in_out_vrr)
984  {
985  	struct core_freesync *core_freesync = NULL;
986  	unsigned long long nominal_field_rate_in_uhz = 0;
987  	unsigned long long rounded_nominal_in_uhz = 0;
988  	unsigned int refresh_range = 0;
989  	unsigned long long min_refresh_in_uhz = 0;
990  	unsigned long long max_refresh_in_uhz = 0;
991  
992  	if (mod_freesync == NULL)
993  		return;
994  
995  	core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync);
996  
997  	/* Calculate nominal field rate for stream */
998  	nominal_field_rate_in_uhz =
999  			mod_freesync_calc_nominal_field_rate(stream);
1000  
1001  	min_refresh_in_uhz = in_config->min_refresh_in_uhz;
1002  	max_refresh_in_uhz = in_config->max_refresh_in_uhz;
1003  
1004  	/* Full range may be larger than current video timing, so cap at nominal */
1005  	if (max_refresh_in_uhz > nominal_field_rate_in_uhz)
1006  		max_refresh_in_uhz = nominal_field_rate_in_uhz;
1007  
1008  	/* Full range may be larger than current video timing, so cap at nominal */
1009  	if (min_refresh_in_uhz > max_refresh_in_uhz)
1010  		min_refresh_in_uhz = max_refresh_in_uhz;
1011  
1012  	/* If a monitor reports exactly max refresh of 2x of min, enforce it on nominal */
1013  	rounded_nominal_in_uhz =
1014  			div_u64(nominal_field_rate_in_uhz + 50000, 100000) * 100000;
1015  	if (in_config->max_refresh_in_uhz == (2 * in_config->min_refresh_in_uhz) &&
1016  		in_config->max_refresh_in_uhz == rounded_nominal_in_uhz)
1017  		min_refresh_in_uhz = div_u64(nominal_field_rate_in_uhz, 2);
1018  
1019  	if (!vrr_settings_require_update(core_freesync,
1020  			in_config, (unsigned int)min_refresh_in_uhz, (unsigned int)max_refresh_in_uhz,
1021  			in_out_vrr))
1022  		return;
1023  
1024  	in_out_vrr->state = in_config->state;
1025  	in_out_vrr->send_info_frame = in_config->vsif_supported;
1026  
1027  	if (in_config->state == VRR_STATE_UNSUPPORTED) {
1028  		in_out_vrr->state = VRR_STATE_UNSUPPORTED;
1029  		in_out_vrr->supported = false;
1030  		in_out_vrr->adjust.v_total_min = stream->timing.v_total;
1031  		in_out_vrr->adjust.v_total_max = stream->timing.v_total;
1032  
1033  		return;
1034  
1035  	} else {
1036  		in_out_vrr->min_refresh_in_uhz = (unsigned int)min_refresh_in_uhz;
1037  		in_out_vrr->max_duration_in_us =
1038  				calc_duration_in_us_from_refresh_in_uhz(
1039  						(unsigned int)min_refresh_in_uhz);
1040  
1041  		in_out_vrr->max_refresh_in_uhz = (unsigned int)max_refresh_in_uhz;
1042  		in_out_vrr->min_duration_in_us =
1043  				calc_duration_in_us_from_refresh_in_uhz(
1044  						(unsigned int)max_refresh_in_uhz);
1045  
1046  		if (in_config->state == VRR_STATE_ACTIVE_FIXED)
1047  			in_out_vrr->fixed_refresh_in_uhz = in_config->fixed_refresh_in_uhz;
1048  		else
1049  			in_out_vrr->fixed_refresh_in_uhz = 0;
1050  
1051  		refresh_range = div_u64(in_out_vrr->max_refresh_in_uhz + 500000, 1000000) -
1052  +				div_u64(in_out_vrr->min_refresh_in_uhz + 500000, 1000000);
1053  
1054  		in_out_vrr->supported = true;
1055  	}
1056  
1057  	in_out_vrr->fixed.ramping_active = in_config->ramping;
1058  
1059  	in_out_vrr->btr.btr_enabled = in_config->btr;
1060  
1061  	if (in_out_vrr->max_refresh_in_uhz < (2 * in_out_vrr->min_refresh_in_uhz))
1062  		in_out_vrr->btr.btr_enabled = false;
1063  	else {
1064  		in_out_vrr->btr.margin_in_us = in_out_vrr->max_duration_in_us -
1065  				2 * in_out_vrr->min_duration_in_us;
1066  		if (in_out_vrr->btr.margin_in_us > BTR_MAX_MARGIN)
1067  			in_out_vrr->btr.margin_in_us = BTR_MAX_MARGIN;
1068  	}
1069  
1070  	in_out_vrr->btr.btr_active = false;
1071  	in_out_vrr->btr.inserted_duration_in_us = 0;
1072  	in_out_vrr->btr.frames_to_insert = 0;
1073  	in_out_vrr->btr.frame_counter = 0;
1074  	in_out_vrr->fixed.fixed_active = false;
1075  	in_out_vrr->fixed.target_refresh_in_uhz = 0;
1076  
1077  	in_out_vrr->btr.mid_point_in_us =
1078  				(in_out_vrr->min_duration_in_us +
1079  				 in_out_vrr->max_duration_in_us) / 2;
1080  
1081  	if (in_out_vrr->state == VRR_STATE_UNSUPPORTED) {
1082  		in_out_vrr->adjust.v_total_min = stream->timing.v_total;
1083  		in_out_vrr->adjust.v_total_max = stream->timing.v_total;
1084  	} else if (in_out_vrr->state == VRR_STATE_DISABLED) {
1085  		in_out_vrr->adjust.v_total_min = stream->timing.v_total;
1086  		in_out_vrr->adjust.v_total_max = stream->timing.v_total;
1087  	} else if (in_out_vrr->state == VRR_STATE_INACTIVE) {
1088  		in_out_vrr->adjust.v_total_min = stream->timing.v_total;
1089  		in_out_vrr->adjust.v_total_max = stream->timing.v_total;
1090  	} else if (in_out_vrr->state == VRR_STATE_ACTIVE_VARIABLE &&
1091  			refresh_range >= MIN_REFRESH_RANGE) {
1092  
1093  		in_out_vrr->adjust.v_total_min =
1094  			mod_freesync_calc_v_total_from_refresh(stream,
1095  				in_out_vrr->max_refresh_in_uhz);
1096  		in_out_vrr->adjust.v_total_max =
1097  			mod_freesync_calc_v_total_from_refresh(stream,
1098  				in_out_vrr->min_refresh_in_uhz);
1099  	} else if (in_out_vrr->state == VRR_STATE_ACTIVE_FIXED) {
1100  		in_out_vrr->fixed.target_refresh_in_uhz =
1101  				in_out_vrr->fixed_refresh_in_uhz;
1102  		if (in_out_vrr->fixed.ramping_active &&
1103  				in_out_vrr->fixed.fixed_active) {
1104  			/* Do not update vtotals if ramping is already active
1105  			 * in order to continue ramp from current refresh.
1106  			 */
1107  			in_out_vrr->fixed.fixed_active = true;
1108  		} else {
1109  			in_out_vrr->fixed.fixed_active = true;
1110  			in_out_vrr->adjust.v_total_min =
1111  				mod_freesync_calc_v_total_from_refresh(stream,
1112  					in_out_vrr->fixed.target_refresh_in_uhz);
1113  			in_out_vrr->adjust.v_total_max =
1114  				in_out_vrr->adjust.v_total_min;
1115  		}
1116  	} else {
1117  		in_out_vrr->state = VRR_STATE_INACTIVE;
1118  		in_out_vrr->adjust.v_total_min = stream->timing.v_total;
1119  		in_out_vrr->adjust.v_total_max = stream->timing.v_total;
1120  	}
1121  }
1122  
1123  void mod_freesync_handle_preflip(struct mod_freesync *mod_freesync,
1124  		const struct dc_plane_state *plane,
1125  		const struct dc_stream_state *stream,
1126  		unsigned int curr_time_stamp_in_us,
1127  		struct mod_vrr_params *in_out_vrr)
1128  {
1129  	struct core_freesync *core_freesync = NULL;
1130  	unsigned int last_render_time_in_us = 0;
1131  	unsigned int average_render_time_in_us = 0;
1132  
1133  	if (mod_freesync == NULL)
1134  		return;
1135  
1136  	core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync);
1137  
1138  	if (in_out_vrr->supported &&
1139  			in_out_vrr->state == VRR_STATE_ACTIVE_VARIABLE) {
1140  		unsigned int i = 0;
1141  		unsigned int oldest_index = plane->time.index + 1;
1142  
1143  		if (oldest_index >= DC_PLANE_UPDATE_TIMES_MAX)
1144  			oldest_index = 0;
1145  
1146  		last_render_time_in_us = curr_time_stamp_in_us -
1147  				plane->time.prev_update_time_in_us;
1148  
1149  		/* Sum off all entries except oldest one */
1150  		for (i = 0; i < DC_PLANE_UPDATE_TIMES_MAX; i++) {
1151  			average_render_time_in_us +=
1152  					plane->time.time_elapsed_in_us[i];
1153  		}
1154  		average_render_time_in_us -=
1155  				plane->time.time_elapsed_in_us[oldest_index];
1156  
1157  		/* Add render time for current flip */
1158  		average_render_time_in_us += last_render_time_in_us;
1159  		average_render_time_in_us /= DC_PLANE_UPDATE_TIMES_MAX;
1160  
1161  		if (in_out_vrr->btr.btr_enabled) {
1162  			apply_below_the_range(core_freesync,
1163  					stream,
1164  					last_render_time_in_us,
1165  					in_out_vrr);
1166  		} else {
1167  			apply_fixed_refresh(core_freesync,
1168  				stream,
1169  				last_render_time_in_us,
1170  				in_out_vrr);
1171  		}
1172  
1173  	}
1174  }
1175  
1176  void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync,
1177  		const struct dc_stream_state *stream,
1178  		struct mod_vrr_params *in_out_vrr)
1179  {
1180  	struct core_freesync *core_freesync = NULL;
1181  
1182  	if ((mod_freesync == NULL) || (stream == NULL) || (in_out_vrr == NULL))
1183  		return;
1184  
1185  	core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync);
1186  
1187  	if (in_out_vrr->supported == false)
1188  		return;
1189  
1190  	/* Below the Range Logic */
1191  
1192  	/* Only execute if in fullscreen mode */
1193  	if (in_out_vrr->state == VRR_STATE_ACTIVE_VARIABLE &&
1194  					in_out_vrr->btr.btr_active) {
1195  		/* TODO: pass in flag for Pre-DCE12 ASIC
1196  		 * in order for frame variable duration to take affect,
1197  		 * it needs to be done one VSYNC early, which is at
1198  		 * frameCounter == 1.
1199  		 * For DCE12 and newer updates to V_TOTAL_MIN/MAX
1200  		 * will take affect on current frame
1201  		 */
1202  		if (in_out_vrr->btr.frames_to_insert ==
1203  				in_out_vrr->btr.frame_counter) {
1204  			in_out_vrr->adjust.v_total_min =
1205  				calc_v_total_from_duration(stream,
1206  				in_out_vrr,
1207  				in_out_vrr->btr.inserted_duration_in_us);
1208  			in_out_vrr->adjust.v_total_max =
1209  				in_out_vrr->adjust.v_total_min;
1210  		}
1211  
1212  		if (in_out_vrr->btr.frame_counter > 0)
1213  			in_out_vrr->btr.frame_counter--;
1214  
1215  		/* Restore FreeSync */
1216  		if (in_out_vrr->btr.frame_counter == 0) {
1217  			in_out_vrr->adjust.v_total_min =
1218  				mod_freesync_calc_v_total_from_refresh(stream,
1219  				in_out_vrr->max_refresh_in_uhz);
1220  			in_out_vrr->adjust.v_total_max =
1221  				mod_freesync_calc_v_total_from_refresh(stream,
1222  				in_out_vrr->min_refresh_in_uhz);
1223  		}
1224  	}
1225  
1226  	/* If in fullscreen freesync mode or in video, do not program
1227  	 * static screen ramp values
1228  	 */
1229  	if (in_out_vrr->state == VRR_STATE_ACTIVE_VARIABLE)
1230  		in_out_vrr->fixed.ramping_active = false;
1231  
1232  	/* Gradual Static Screen Ramping Logic
1233  	 * Execute if ramp is active and user enabled freesync static screen
1234  	 */
1235  	if (in_out_vrr->state == VRR_STATE_ACTIVE_FIXED &&
1236  				in_out_vrr->fixed.ramping_active) {
1237  		update_v_total_for_static_ramp(
1238  				core_freesync, stream, in_out_vrr);
1239  	}
1240  }
1241  
1242  void mod_freesync_get_settings(struct mod_freesync *mod_freesync,
1243  		const struct mod_vrr_params *vrr,
1244  		unsigned int *v_total_min, unsigned int *v_total_max,
1245  		unsigned int *event_triggers,
1246  		unsigned int *window_min, unsigned int *window_max,
1247  		unsigned int *lfc_mid_point_in_us,
1248  		unsigned int *inserted_frames,
1249  		unsigned int *inserted_duration_in_us)
1250  {
1251  	if (mod_freesync == NULL)
1252  		return;
1253  
1254  	if (vrr->supported) {
1255  		*v_total_min = vrr->adjust.v_total_min;
1256  		*v_total_max = vrr->adjust.v_total_max;
1257  		*event_triggers = 0;
1258  		*lfc_mid_point_in_us = vrr->btr.mid_point_in_us;
1259  		*inserted_frames = vrr->btr.frames_to_insert;
1260  		*inserted_duration_in_us = vrr->btr.inserted_duration_in_us;
1261  	}
1262  }
1263  
1264  unsigned long long mod_freesync_calc_nominal_field_rate(
1265  			const struct dc_stream_state *stream)
1266  {
1267  	unsigned long long nominal_field_rate_in_uhz = 0;
1268  	unsigned int total = stream->timing.h_total * stream->timing.v_total;
1269  
1270  	/* Calculate nominal field rate for stream, rounded up to nearest integer */
1271  	nominal_field_rate_in_uhz = stream->timing.pix_clk_100hz;
1272  	nominal_field_rate_in_uhz *= 100000000ULL;
1273  
1274  	nominal_field_rate_in_uhz =	div_u64(nominal_field_rate_in_uhz, total);
1275  
1276  	return nominal_field_rate_in_uhz;
1277  }
1278  
1279  unsigned long long mod_freesync_calc_field_rate_from_timing(
1280  		unsigned int vtotal, unsigned int htotal, unsigned int pix_clk)
1281  {
1282  	unsigned long long field_rate_in_uhz = 0;
1283  	unsigned int total = htotal * vtotal;
1284  
1285  	/* Calculate nominal field rate for stream, rounded up to nearest integer */
1286  	field_rate_in_uhz = pix_clk;
1287  	field_rate_in_uhz *= 1000000ULL;
1288  
1289  	field_rate_in_uhz =	div_u64(field_rate_in_uhz, total);
1290  
1291  	return field_rate_in_uhz;
1292  }
1293  
1294  bool mod_freesync_is_valid_range(uint32_t min_refresh_cap_in_uhz,
1295  		uint32_t max_refresh_cap_in_uhz,
1296  		uint32_t nominal_field_rate_in_uhz)
1297  {
1298  
1299  	/* Typically nominal refresh calculated can have some fractional part.
1300  	 * Allow for some rounding error of actual video timing by taking floor
1301  	 * of caps and request. Round the nominal refresh rate.
1302  	 *
1303  	 * Dividing will convert everything to units in Hz although input
1304  	 * variable name is in uHz!
1305  	 *
1306  	 * Also note, this takes care of rounding error on the nominal refresh
1307  	 * so by rounding error we only expect it to be off by a small amount,
1308  	 * such as < 0.1 Hz. i.e. 143.9xxx or 144.1xxx.
1309  	 *
1310  	 * Example 1. Caps    Min = 40 Hz, Max = 144 Hz
1311  	 *            Request Min = 40 Hz, Max = 144 Hz
1312  	 *                    Nominal = 143.5x Hz rounded to 144 Hz
1313  	 *            This function should allow this as valid request
1314  	 *
1315  	 * Example 2. Caps    Min = 40 Hz, Max = 144 Hz
1316  	 *            Request Min = 40 Hz, Max = 144 Hz
1317  	 *                    Nominal = 144.4x Hz rounded to 144 Hz
1318  	 *            This function should allow this as valid request
1319  	 *
1320  	 * Example 3. Caps    Min = 40 Hz, Max = 144 Hz
1321  	 *            Request Min = 40 Hz, Max = 144 Hz
1322  	 *                    Nominal = 120.xx Hz rounded to 120 Hz
1323  	 *            This function should return NOT valid since the requested
1324  	 *            max is greater than current timing's nominal
1325  	 *
1326  	 * Example 4. Caps    Min = 40 Hz, Max = 120 Hz
1327  	 *            Request Min = 40 Hz, Max = 120 Hz
1328  	 *                    Nominal = 144.xx Hz rounded to 144 Hz
1329  	 *            This function should return NOT valid since the nominal
1330  	 *            is greater than the capability's max refresh
1331  	 */
1332  	nominal_field_rate_in_uhz =
1333  			div_u64(nominal_field_rate_in_uhz + 500000, 1000000);
1334  	min_refresh_cap_in_uhz /= 1000000;
1335  	max_refresh_cap_in_uhz /= 1000000;
1336  
1337  	/* Check nominal is within range */
1338  	if (nominal_field_rate_in_uhz > max_refresh_cap_in_uhz ||
1339  		nominal_field_rate_in_uhz < min_refresh_cap_in_uhz)
1340  		return false;
1341  
1342  	/* If nominal is less than max, limit the max allowed refresh rate */
1343  	if (nominal_field_rate_in_uhz < max_refresh_cap_in_uhz)
1344  		max_refresh_cap_in_uhz = nominal_field_rate_in_uhz;
1345  
1346  	/* Check min is within range */
1347  	if (min_refresh_cap_in_uhz > max_refresh_cap_in_uhz)
1348  		return false;
1349  
1350  	/* For variable range, check for at least 10 Hz range */
1351  	if (nominal_field_rate_in_uhz - min_refresh_cap_in_uhz < 10)
1352  		return false;
1353  
1354  	return true;
1355  }
1356