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 "dm_services.h"
27 #include "dc.h"
28 #include "mod_freesync.h"
29 #include "core_types.h"
30 #include "core_dc.h"
31 
32 #define MOD_FREESYNC_MAX_CONCURRENT_STREAMS  32
33 
34 /* Refresh rate ramp at a fixed rate of 65 Hz/second */
35 #define STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME ((1000 / 60) * 65)
36 /* Number of elements in the render times cache array */
37 #define RENDER_TIMES_MAX_COUNT 20
38 /* Threshold to exit BTR (to avoid frequent enter-exits at the lower limit) */
39 #define BTR_EXIT_MARGIN 2000
40 
41 #define FREESYNC_REGISTRY_NAME "freesync_v1"
42 
43 struct gradual_static_ramp {
44 	bool ramp_is_active;
45 	bool ramp_direction_is_up;
46 	unsigned int ramp_current_frame_duration_in_ns;
47 };
48 
49 struct time_cache {
50 	/* video (48Hz feature) related */
51 	unsigned int update_duration_in_ns;
52 
53 	/* BTR/fixed refresh related */
54 	unsigned int prev_time_stamp_in_us;
55 
56 	unsigned int min_render_time_in_us;
57 	unsigned int max_render_time_in_us;
58 
59 	unsigned int render_times_index;
60 	unsigned int render_times[RENDER_TIMES_MAX_COUNT];
61 };
62 
63 struct below_the_range {
64 	bool btr_active;
65 	bool program_btr;
66 
67 	unsigned int mid_point_in_us;
68 
69 	unsigned int inserted_frame_duration_in_us;
70 	unsigned int frames_to_insert;
71 	unsigned int frame_counter;
72 };
73 
74 struct fixed_refresh {
75 	bool fixed_refresh_active;
76 	bool program_fixed_refresh;
77 };
78 
79 struct freesync_range {
80 	unsigned int min_refresh;
81 	unsigned int max_frame_duration;
82 	unsigned int vmax;
83 
84 	unsigned int max_refresh;
85 	unsigned int min_frame_duration;
86 	unsigned int vmin;
87 };
88 
89 struct freesync_state {
90 	bool fullscreen;
91 	bool static_screen;
92 	bool video;
93 
94 	unsigned int nominal_refresh_rate_in_micro_hz;
95 	bool windowed_fullscreen;
96 
97 	struct time_cache time;
98 
99 	struct gradual_static_ramp static_ramp;
100 	struct below_the_range btr;
101 	struct fixed_refresh fixed_refresh;
102 	struct freesync_range freesync_range;
103 };
104 
105 struct freesync_entity {
106 	const struct dc_stream *stream;
107 	struct mod_freesync_caps *caps;
108 	struct freesync_state state;
109 	struct mod_freesync_user_enable user_enable;
110 };
111 
112 struct freesync_registry_options {
113 	unsigned int min_refresh_from_edid;
114 };
115 
116 struct core_freesync {
117 	struct mod_freesync public;
118 	struct dc *dc;
119 	struct freesync_entity *map;
120 	int num_entities;
121 	struct freesync_registry_options opts;
122 };
123 
124 #define MOD_FREESYNC_TO_CORE(mod_freesync)\
125 		container_of(mod_freesync, struct core_freesync, public)
126 
127 static bool check_dc_support(const struct dc *dc)
128 {
129 	if (dc->stream_funcs.adjust_vmin_vmax == NULL)
130 		return false;
131 
132 	return true;
133 }
134 
135 struct mod_freesync *mod_freesync_create(struct dc *dc)
136 {
137 	struct core_freesync *core_freesync =
138 			dm_alloc(sizeof(struct core_freesync));
139 
140 	struct core_dc *core_dc = DC_TO_CORE(dc);
141 
142 	struct persistent_data_flag flag;
143 
144 	int i, data = 0;
145 
146 	if (core_freesync == NULL)
147 		goto fail_alloc_context;
148 
149 	core_freesync->map = dm_alloc(sizeof(struct freesync_entity) *
150 			MOD_FREESYNC_MAX_CONCURRENT_STREAMS);
151 
152 	if (core_freesync->map == NULL)
153 		goto fail_alloc_map;
154 
155 	for (i = 0; i < MOD_FREESYNC_MAX_CONCURRENT_STREAMS; i++)
156 		core_freesync->map[i].stream = NULL;
157 
158 	core_freesync->num_entities = 0;
159 
160 	if (dc == NULL)
161 		goto fail_construct;
162 
163 	core_freesync->dc = dc;
164 
165 	if (!check_dc_support(dc))
166 		goto fail_construct;
167 
168 	/* Create initial module folder in registry for freesync enable data */
169 	flag.save_per_edid = true;
170 	flag.save_per_link = false;
171 	dm_write_persistent_data(core_dc->ctx, NULL, FREESYNC_REGISTRY_NAME, NULL, NULL,
172 					0, &flag);
173 	flag.save_per_edid = false;
174 	flag.save_per_link = false;
175 	if (dm_read_persistent_data(core_dc->ctx, NULL, NULL,
176 			"DalDrrSupport", &data, sizeof(data), &flag)) {
177 		core_freesync->opts.min_refresh_from_edid = data;
178 	}
179 
180 	return &core_freesync->public;
181 
182 fail_construct:
183 	dm_free(core_freesync->map);
184 
185 fail_alloc_map:
186 	dm_free(core_freesync);
187 
188 fail_alloc_context:
189 	return NULL;
190 }
191 
192 void mod_freesync_destroy(struct mod_freesync *mod_freesync)
193 {
194 	if (mod_freesync != NULL) {
195 		int i;
196 		struct core_freesync *core_freesync =
197 				MOD_FREESYNC_TO_CORE(mod_freesync);
198 
199 		for (i = 0; i < core_freesync->num_entities; i++)
200 			if (core_freesync->map[i].stream)
201 				dc_stream_release(core_freesync->map[i].stream);
202 
203 		dm_free(core_freesync->map);
204 
205 		dm_free(core_freesync);
206 	}
207 }
208 
209 /* Given a specific dc_stream* this function finds its equivalent
210  * on the core_freesync->map and returns the corresponding index
211  */
212 static unsigned int map_index_from_stream(struct core_freesync *core_freesync,
213 		const struct dc_stream *stream)
214 {
215 	unsigned int index = 0;
216 
217 	for (index = 0; index < core_freesync->num_entities; index++) {
218 		if (core_freesync->map[index].stream == stream) {
219 			return index;
220 		}
221 	}
222 	/* Could not find stream requested */
223 	ASSERT(false);
224 	return index;
225 }
226 
227 bool mod_freesync_add_stream(struct mod_freesync *mod_freesync,
228 		const struct dc_stream *stream, struct mod_freesync_caps *caps)
229 {
230 	struct core_stream *core_stream = NULL;
231 	struct core_dc *core_dc = NULL;
232 	struct core_freesync *core_freesync = NULL;
233 	int persistent_freesync_enable = 0;
234 	struct persistent_data_flag flag;
235 	unsigned int nom_refresh_rate_micro_hz;
236 	unsigned long long temp;
237 
238 	if (mod_freesync == NULL)
239 		return false;
240 
241 	core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync);
242 	core_stream = DC_STREAM_TO_CORE(stream);
243 	core_dc = DC_TO_CORE(core_freesync->dc);
244 
245 	flag.save_per_edid = true;
246 	flag.save_per_link = false;
247 
248 	if (core_freesync->num_entities < MOD_FREESYNC_MAX_CONCURRENT_STREAMS) {
249 
250 		dc_stream_retain(stream);
251 
252 		temp = stream->timing.pix_clk_khz;
253 		temp *= 1000ULL * 1000ULL * 1000ULL;
254 		temp = div_u64(temp, stream->timing.h_total);
255 		temp = div_u64(temp, stream->timing.v_total);
256 
257 		nom_refresh_rate_micro_hz = (unsigned int) temp;
258 
259 		if (core_freesync->opts.min_refresh_from_edid != 0 &&
260 				dc_is_embedded_signal(
261 					stream->sink->sink_signal)) {
262 			caps->supported = true;
263 			caps->min_refresh_in_micro_hz =
264 				core_freesync->opts.min_refresh_from_edid *
265 					1000000;
266 			caps->max_refresh_in_micro_hz =
267 					nom_refresh_rate_micro_hz;
268 		}
269 
270 		core_freesync->map[core_freesync->num_entities].stream = stream;
271 		core_freesync->map[core_freesync->num_entities].caps = caps;
272 
273 		core_freesync->map[core_freesync->num_entities].state.
274 			fullscreen = false;
275 		core_freesync->map[core_freesync->num_entities].state.
276 			static_screen = false;
277 		core_freesync->map[core_freesync->num_entities].state.
278 			video = false;
279 		core_freesync->map[core_freesync->num_entities].state.time.
280 			update_duration_in_ns = 0;
281 		core_freesync->map[core_freesync->num_entities].state.
282 			static_ramp.ramp_is_active = false;
283 
284 		/* get persistent data from registry */
285 		if (dm_read_persistent_data(core_dc->ctx, stream->sink,
286 					FREESYNC_REGISTRY_NAME,
287 					"userenable", &persistent_freesync_enable,
288 					sizeof(int), &flag)) {
289 			core_freesync->map[core_freesync->num_entities].user_enable.
290 				enable_for_gaming =
291 				(persistent_freesync_enable & 1) ? true : false;
292 			core_freesync->map[core_freesync->num_entities].user_enable.
293 				enable_for_static =
294 				(persistent_freesync_enable & 2) ? true : false;
295 			core_freesync->map[core_freesync->num_entities].user_enable.
296 				enable_for_video =
297 				(persistent_freesync_enable & 4) ? true : false;
298 		} else {
299 			core_freesync->map[core_freesync->num_entities].user_enable.
300 					enable_for_gaming = false;
301 			core_freesync->map[core_freesync->num_entities].user_enable.
302 					enable_for_static = false;
303 			core_freesync->map[core_freesync->num_entities].user_enable.
304 					enable_for_video = false;
305 		}
306 
307 		if (caps->supported &&
308 		    nom_refresh_rate_micro_hz >= caps->min_refresh_in_micro_hz &&
309 		    nom_refresh_rate_micro_hz <= caps->max_refresh_in_micro_hz)
310 			core_stream->public.ignore_msa_timing_param = 1;
311 
312 		core_freesync->num_entities++;
313 		return true;
314 	}
315 	return false;
316 }
317 
318 bool mod_freesync_remove_stream(struct mod_freesync *mod_freesync,
319 		const struct dc_stream *stream)
320 {
321 	int i = 0;
322 	struct core_freesync *core_freesync = NULL;
323 	unsigned int index = 0;
324 
325 	if (mod_freesync == NULL)
326 		return false;
327 
328 	core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync);
329 	index = map_index_from_stream(core_freesync, stream);
330 
331 	dc_stream_release(core_freesync->map[index].stream);
332 	core_freesync->map[index].stream = NULL;
333 	/* To remove this entity, shift everything after down */
334 	for (i = index; i < core_freesync->num_entities - 1; i++)
335 		core_freesync->map[i] = core_freesync->map[i + 1];
336 	core_freesync->num_entities--;
337 	return true;
338 }
339 
340 static void update_stream_freesync_context(struct core_freesync *core_freesync,
341 		const struct dc_stream *stream)
342 {
343 	unsigned int index;
344 	struct freesync_context *ctx;
345 	struct core_stream *core_stream;
346 
347 	core_stream = DC_STREAM_TO_CORE(stream);
348 	ctx = &core_stream->public.freesync_ctx;
349 
350 	index = map_index_from_stream(core_freesync, stream);
351 
352 	ctx->supported = core_freesync->map[index].caps->supported;
353 	ctx->enabled = (core_freesync->map[index].user_enable.enable_for_gaming ||
354 		core_freesync->map[index].user_enable.enable_for_video ||
355 		core_freesync->map[index].user_enable.enable_for_static);
356 	ctx->active = (core_freesync->map[index].state.fullscreen ||
357 		core_freesync->map[index].state.video ||
358 		core_freesync->map[index].state.static_ramp.ramp_is_active);
359 	ctx->min_refresh_in_micro_hz =
360 			core_freesync->map[index].caps->min_refresh_in_micro_hz;
361 	ctx->nominal_refresh_in_micro_hz = core_freesync->
362 		map[index].state.nominal_refresh_rate_in_micro_hz;
363 
364 }
365 
366 static void update_stream(struct core_freesync *core_freesync,
367 		const struct dc_stream *stream)
368 {
369 	struct core_stream *core_stream = DC_STREAM_TO_CORE(stream);
370 
371 	unsigned int index = map_index_from_stream(core_freesync, stream);
372 	if (core_freesync->map[index].caps->supported) {
373 		core_stream->public.ignore_msa_timing_param = 1;
374 		update_stream_freesync_context(core_freesync, stream);
375 	}
376 }
377 
378 static void calc_freesync_range(struct core_freesync *core_freesync,
379 		const struct dc_stream *stream,
380 		struct freesync_state *state,
381 		unsigned int min_refresh_in_uhz,
382 		unsigned int max_refresh_in_uhz)
383 {
384 	unsigned int min_frame_duration_in_ns = 0, max_frame_duration_in_ns = 0;
385 	unsigned int index = map_index_from_stream(core_freesync, stream);
386 	uint32_t vtotal = stream->timing.v_total;
387 
388 	if ((min_refresh_in_uhz == 0) || (max_refresh_in_uhz == 0)) {
389 		state->freesync_range.min_refresh =
390 				state->nominal_refresh_rate_in_micro_hz;
391 		state->freesync_range.max_refresh =
392 				state->nominal_refresh_rate_in_micro_hz;
393 
394 		state->freesync_range.max_frame_duration = 0;
395 		state->freesync_range.min_frame_duration = 0;
396 
397 		state->freesync_range.vmax = vtotal;
398 		state->freesync_range.vmin = vtotal;
399 
400 		return;
401 	}
402 
403 	min_frame_duration_in_ns = ((unsigned int) (div64_u64(
404 					(1000000000ULL * 1000000),
405 					max_refresh_in_uhz)));
406 	max_frame_duration_in_ns = ((unsigned int) (div64_u64(
407 		(1000000000ULL * 1000000),
408 		min_refresh_in_uhz)));
409 
410 	state->freesync_range.min_refresh = min_refresh_in_uhz;
411 	state->freesync_range.max_refresh = max_refresh_in_uhz;
412 
413 	state->freesync_range.max_frame_duration = max_frame_duration_in_ns;
414 	state->freesync_range.min_frame_duration = min_frame_duration_in_ns;
415 
416 	state->freesync_range.vmax = div64_u64(div64_u64(((unsigned long long)(
417 		max_frame_duration_in_ns) * stream->timing.pix_clk_khz),
418 		stream->timing.h_total), 1000000);
419 	state->freesync_range.vmin = div64_u64(div64_u64(((unsigned long long)(
420 		min_frame_duration_in_ns) * stream->timing.pix_clk_khz),
421 		stream->timing.h_total), 1000000);
422 
423 	/* In case of 4k free sync monitor, vmin or vmax cannot be less than vtotal */
424 	if (state->freesync_range.vmin < vtotal) {
425 		ASSERT(false);
426 		state->freesync_range.vmin = vtotal;
427 	}
428 
429 	if (state->freesync_range.vmax < vtotal) {
430 		ASSERT(false);
431 		state->freesync_range.vmax = vtotal;
432 	}
433 
434 	/* Determine whether BTR can be supported */
435 	if (max_frame_duration_in_ns >=
436 			2 * min_frame_duration_in_ns)
437 		core_freesync->map[index].caps->btr_supported = true;
438 	else
439 		core_freesync->map[index].caps->btr_supported = false;
440 
441 	/* Cache the time variables */
442 	state->time.max_render_time_in_us =
443 		max_frame_duration_in_ns / 1000;
444 	state->time.min_render_time_in_us =
445 		min_frame_duration_in_ns / 1000;
446 	state->btr.mid_point_in_us =
447 		(max_frame_duration_in_ns +
448 		min_frame_duration_in_ns) / 2000;
449 }
450 
451 static void calc_v_total_from_duration(const struct dc_stream *stream,
452 		unsigned int duration_in_ns, int *v_total_nominal)
453 {
454 	*v_total_nominal = div64_u64(div64_u64(((unsigned long long)(
455 				duration_in_ns) * stream->timing.pix_clk_khz),
456 				stream->timing.h_total), 1000000);
457 }
458 
459 static void calc_v_total_for_static_ramp(struct core_freesync *core_freesync,
460 		const struct dc_stream *stream,
461 		unsigned int index, int *v_total)
462 {
463 	unsigned int frame_duration = 0;
464 
465 	struct gradual_static_ramp *static_ramp_variables =
466 				&core_freesync->map[index].state.static_ramp;
467 
468 	/* Calc ratio between new and current frame duration with 3 digit */
469 	unsigned int frame_duration_ratio = div64_u64(1000000,
470 		(1000 +  div64_u64(((unsigned long long)(
471 		STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME) *
472 		static_ramp_variables->ramp_current_frame_duration_in_ns),
473 		1000000000)));
474 
475 	/* Calculate delta between new and current frame duration in ns */
476 	unsigned int frame_duration_delta = div64_u64(((unsigned long long)(
477 		static_ramp_variables->ramp_current_frame_duration_in_ns) *
478 		(1000 - frame_duration_ratio)), 1000);
479 
480 	/* Adjust frame duration delta based on ratio between current and
481 	 * standard frame duration (frame duration at 60 Hz refresh rate).
482 	 */
483 	unsigned int ramp_rate_interpolated = div64_u64(((unsigned long long)(
484 		frame_duration_delta) * static_ramp_variables->
485 		ramp_current_frame_duration_in_ns), 16666666);
486 
487 	/* Going to a higher refresh rate (lower frame duration) */
488 	if (static_ramp_variables->ramp_direction_is_up) {
489 		/* reduce frame duration */
490 		static_ramp_variables->ramp_current_frame_duration_in_ns -=
491 			ramp_rate_interpolated;
492 
493 		/* min frame duration */
494 		frame_duration = ((unsigned int) (div64_u64(
495 			(1000000000ULL * 1000000),
496 			core_freesync->map[index].state.
497 			nominal_refresh_rate_in_micro_hz)));
498 
499 		/* adjust for frame duration below min */
500 		if (static_ramp_variables->ramp_current_frame_duration_in_ns <=
501 			frame_duration) {
502 
503 			static_ramp_variables->ramp_is_active = false;
504 			static_ramp_variables->
505 				ramp_current_frame_duration_in_ns =
506 				frame_duration;
507 		}
508 	/* Going to a lower refresh rate (larger frame duration) */
509 	} else {
510 		/* increase frame duration */
511 		static_ramp_variables->ramp_current_frame_duration_in_ns +=
512 			ramp_rate_interpolated;
513 
514 		/* max frame duration */
515 		frame_duration = ((unsigned int) (div64_u64(
516 			(1000000000ULL * 1000000),
517 			core_freesync->map[index].caps->min_refresh_in_micro_hz)));
518 
519 		/* adjust for frame duration above max */
520 		if (static_ramp_variables->ramp_current_frame_duration_in_ns >=
521 			frame_duration) {
522 
523 			static_ramp_variables->ramp_is_active = false;
524 			static_ramp_variables->
525 				ramp_current_frame_duration_in_ns =
526 				frame_duration;
527 		}
528 	}
529 
530 	calc_v_total_from_duration(stream, static_ramp_variables->
531 		ramp_current_frame_duration_in_ns, v_total);
532 }
533 
534 static void reset_freesync_state_variables(struct freesync_state* state)
535 {
536 	state->static_ramp.ramp_is_active = false;
537 	if (state->nominal_refresh_rate_in_micro_hz)
538 		state->static_ramp.ramp_current_frame_duration_in_ns =
539 			((unsigned int) (div64_u64(
540 			(1000000000ULL * 1000000),
541 			state->nominal_refresh_rate_in_micro_hz)));
542 
543 	state->btr.btr_active = false;
544 	state->btr.frame_counter = 0;
545 	state->btr.frames_to_insert = 0;
546 	state->btr.inserted_frame_duration_in_us = 0;
547 	state->btr.program_btr = false;
548 
549 	state->fixed_refresh.fixed_refresh_active = false;
550 	state->fixed_refresh.program_fixed_refresh = false;
551 }
552 /*
553  * Sets freesync mode on a stream depending on current freesync state.
554  */
555 static bool set_freesync_on_streams(struct core_freesync *core_freesync,
556 		const struct dc_stream **streams, int num_streams)
557 {
558 	int v_total_nominal = 0, v_total_min = 0, v_total_max = 0;
559 	unsigned int stream_idx, map_index = 0;
560 	struct freesync_state *state;
561 
562 	if (num_streams == 0 || streams == NULL || num_streams > 1)
563 		return false;
564 
565 	for (stream_idx = 0; stream_idx < num_streams; stream_idx++) {
566 
567 		map_index = map_index_from_stream(core_freesync,
568 				streams[stream_idx]);
569 
570 		state = &core_freesync->map[map_index].state;
571 
572 		if (core_freesync->map[map_index].caps->supported) {
573 
574 			/* Fullscreen has the topmost priority. If the
575 			 * fullscreen bit is set, we are in a fullscreen
576 			 * application where it should not matter if it is
577 			 * static screen. We should not check the static_screen
578 			 * or video bit.
579 			 *
580 			 * Special cases of fullscreen include btr and fixed
581 			 * refresh. We program btr on every flip and involves
582 			 * programming full range right before the last inserted frame.
583 			 * However, we do not want to program the full freesync range
584 			 * when fixed refresh is active, because we only program
585 			 * that logic once and this will override it.
586 			 */
587 			if (core_freesync->map[map_index].user_enable.
588 				enable_for_gaming == true &&
589 				state->fullscreen == true &&
590 				state->fixed_refresh.fixed_refresh_active == false) {
591 				/* Enable freesync */
592 
593 				v_total_min = state->freesync_range.vmin;
594 				v_total_max = state->freesync_range.vmax;
595 
596 				/* Update the freesync context for the stream */
597 				update_stream_freesync_context(core_freesync,
598 						streams[stream_idx]);
599 
600 				core_freesync->dc->stream_funcs.
601 				adjust_vmin_vmax(core_freesync->dc, streams,
602 						num_streams, v_total_min,
603 						v_total_max);
604 
605 				return true;
606 
607 			} else if (core_freesync->map[map_index].user_enable.
608 				enable_for_video && state->video == true) {
609 				/* Enable 48Hz feature */
610 
611 				calc_v_total_from_duration(streams[stream_idx],
612 					state->time.update_duration_in_ns,
613 					&v_total_nominal);
614 
615 				/* Program only if v_total_nominal is in range*/
616 				if (v_total_nominal >=
617 					streams[stream_idx]->timing.v_total) {
618 
619 					/* Update the freesync context for
620 					 * the stream
621 					 */
622 					update_stream_freesync_context(
623 						core_freesync,
624 						streams[stream_idx]);
625 
626 					core_freesync->dc->stream_funcs.
627 					adjust_vmin_vmax(
628 						core_freesync->dc, streams,
629 						num_streams, v_total_nominal,
630 						v_total_nominal);
631 				}
632 				return true;
633 
634 			} else {
635 				/* Disable freesync */
636 				v_total_nominal = streams[stream_idx]->
637 					timing.v_total;
638 
639 				/* Update the freesync context for
640 				 * the stream
641 				 */
642 				update_stream_freesync_context(
643 					core_freesync,
644 					streams[stream_idx]);
645 
646 				core_freesync->dc->stream_funcs.
647 						adjust_vmin_vmax(
648 						core_freesync->dc, streams,
649 						num_streams, v_total_nominal,
650 						v_total_nominal);
651 
652 				/* Reset the cached variables */
653 				reset_freesync_state_variables(state);
654 
655 				return true;
656 			}
657 		} else {
658 			/* Disable freesync */
659 			v_total_nominal = streams[stream_idx]->
660 				timing.v_total;
661 			/*
662 			 * we have to reset drr always even sink does
663 			 * not support freesync because a former stream has
664 			 * be programmed
665 			 */
666 			core_freesync->dc->stream_funcs.
667 					adjust_vmin_vmax(
668 					core_freesync->dc, streams,
669 					num_streams, v_total_nominal,
670 					v_total_nominal);
671 			/* Reset the cached variables */
672 			reset_freesync_state_variables(state);
673 		}
674 
675 	}
676 
677 	return false;
678 }
679 
680 static void set_static_ramp_variables(struct core_freesync *core_freesync,
681 		unsigned int index, bool enable_static_screen)
682 {
683 	unsigned int frame_duration = 0;
684 
685 	struct gradual_static_ramp *static_ramp_variables =
686 			&core_freesync->map[index].state.static_ramp;
687 
688 	/* If ramp is not active, set initial frame duration depending on
689 	 * whether we are enabling/disabling static screen mode. If the ramp is
690 	 * already active, ramp should continue in the opposite direction
691 	 * starting with the current frame duration
692 	 */
693 	if (!static_ramp_variables->ramp_is_active) {
694 
695 		static_ramp_variables->ramp_is_active = true;
696 
697 		if (enable_static_screen == true) {
698 			/* Going to lower refresh rate, so start from max
699 			 * refresh rate (min frame duration)
700 			 */
701 			frame_duration = ((unsigned int) (div64_u64(
702 				(1000000000ULL * 1000000),
703 				core_freesync->map[index].state.
704 				nominal_refresh_rate_in_micro_hz)));
705 		} else {
706 			/* Going to higher refresh rate, so start from min
707 			 * refresh rate (max frame duration)
708 			 */
709 			frame_duration = ((unsigned int) (div64_u64(
710 				(1000000000ULL * 1000000),
711 				core_freesync->map[index].caps->min_refresh_in_micro_hz)));
712 		}
713 
714 		static_ramp_variables->
715 			ramp_current_frame_duration_in_ns = frame_duration;
716 	}
717 
718 	/* If we are ENABLING static screen, refresh rate should go DOWN.
719 	 * If we are DISABLING static screen, refresh rate should go UP.
720 	 */
721 	static_ramp_variables->ramp_direction_is_up = !enable_static_screen;
722 }
723 
724 void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync,
725 		const struct dc_stream **streams, int num_streams)
726 {
727 	unsigned int index, v_total, inserted_frame_v_total = 0;
728 	unsigned int min_frame_duration_in_ns, vmax, vmin = 0;
729 	struct freesync_state *state;
730 	struct core_freesync *core_freesync = NULL;
731 	struct dc_static_screen_events triggers = {0};
732 
733 	if (mod_freesync == NULL)
734 		return;
735 
736 	core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync);
737 
738 	if (core_freesync->num_entities == 0)
739 		return;
740 
741 	index = map_index_from_stream(core_freesync,
742 		streams[0]);
743 
744 	if (core_freesync->map[index].caps->supported == false)
745 		return;
746 
747 	state = &core_freesync->map[index].state;
748 
749 	/* Below the Range Logic */
750 
751 	/* Only execute if in fullscreen mode */
752 	if (state->fullscreen == true &&
753 		core_freesync->map[index].user_enable.enable_for_gaming &&
754 		core_freesync->map[index].caps->btr_supported &&
755 		state->btr.btr_active) {
756 
757 		/* TODO: pass in flag for Pre-DCE12 ASIC
758 		 * in order for frame variable duration to take affect,
759 		 * it needs to be done one VSYNC early, which is at
760 		 * frameCounter == 1.
761 		 * For DCE12 and newer updates to V_TOTAL_MIN/MAX
762 		 * will take affect on current frame
763 		 */
764 		if (state->btr.frames_to_insert == state->btr.frame_counter) {
765 
766 			min_frame_duration_in_ns = ((unsigned int) (div64_u64(
767 					(1000000000ULL * 1000000),
768 					state->nominal_refresh_rate_in_micro_hz)));
769 
770 			vmin = state->freesync_range.vmin;
771 
772 			inserted_frame_v_total = vmin;
773 
774 			if (min_frame_duration_in_ns / 1000)
775 				inserted_frame_v_total =
776 					state->btr.inserted_frame_duration_in_us *
777 					vmin / (min_frame_duration_in_ns / 1000);
778 
779 			/* Set length of inserted frames as v_total_max*/
780 			vmax = inserted_frame_v_total;
781 			vmin = inserted_frame_v_total;
782 
783 			/* Program V_TOTAL */
784 			core_freesync->dc->stream_funcs.adjust_vmin_vmax(
785 				core_freesync->dc, streams,
786 				num_streams, vmin, vmax);
787 		}
788 
789 		if (state->btr.frame_counter > 0)
790 			state->btr.frame_counter--;
791 
792 		/* Restore FreeSync */
793 		if (state->btr.frame_counter == 0)
794 			set_freesync_on_streams(core_freesync, streams, num_streams);
795 	}
796 
797 	/* If in fullscreen freesync mode or in video, do not program
798 	 * static screen ramp values
799 	 */
800 	if (state->fullscreen == true || state->video == true) {
801 
802 		state->static_ramp.ramp_is_active = false;
803 
804 		return;
805 	}
806 
807 	/* Gradual Static Screen Ramping Logic */
808 
809 	/* Execute if ramp is active and user enabled freesync static screen*/
810 	if (state->static_ramp.ramp_is_active &&
811 		core_freesync->map[index].user_enable.enable_for_static) {
812 
813 		calc_v_total_for_static_ramp(core_freesync, streams[0],
814 				index, &v_total);
815 
816 		/* Update the freesync context for the stream */
817 		update_stream_freesync_context(core_freesync, streams[0]);
818 
819 		/* Program static screen ramp values */
820 		core_freesync->dc->stream_funcs.adjust_vmin_vmax(
821 					core_freesync->dc, streams,
822 					num_streams, v_total,
823 					v_total);
824 
825 		triggers.overlay_update = true;
826 		triggers.surface_update = true;
827 
828 		core_freesync->dc->stream_funcs.set_static_screen_events(
829 					core_freesync->dc, streams,	num_streams,
830 					&triggers);
831 	}
832 }
833 
834 void mod_freesync_update_state(struct mod_freesync *mod_freesync,
835 		const struct dc_stream **streams, int num_streams,
836 		struct mod_freesync_params *freesync_params)
837 {
838 	bool freesync_program_required = false;
839 	unsigned int stream_index;
840 	struct freesync_state *state;
841 	struct core_freesync *core_freesync = NULL;
842 
843 	if (mod_freesync == NULL)
844 		return;
845 
846 	core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync);
847 
848 	if (core_freesync->num_entities == 0)
849 		return;
850 
851 	for(stream_index = 0; stream_index < num_streams; stream_index++) {
852 
853 		unsigned int map_index = map_index_from_stream(core_freesync,
854 				streams[stream_index]);
855 
856 		state = &core_freesync->map[map_index].state;
857 
858 		switch (freesync_params->state){
859 		case FREESYNC_STATE_FULLSCREEN:
860 			state->fullscreen = freesync_params->enable;
861 			freesync_program_required = true;
862 			state->windowed_fullscreen =
863 					freesync_params->windowed_fullscreen;
864 			break;
865 		case FREESYNC_STATE_STATIC_SCREEN:
866 			/* Static screen ramp is only enabled for embedded
867 			 * panels. Also change core variables only if there
868 			 * is a change.
869 			 */
870 			if (dc_is_embedded_signal(
871 				streams[stream_index]->sink->sink_signal) &&
872 				state->static_screen !=
873 				freesync_params->enable) {
874 
875 				/* Change the state flag */
876 				state->static_screen = freesync_params->enable;
877 
878 				/* Change static screen ramp variables */
879 				set_static_ramp_variables(core_freesync,
880 						map_index,
881 						freesync_params->enable);
882 			}
883 			/* We program the ramp starting next VUpdate */
884 			break;
885 		case FREESYNC_STATE_VIDEO:
886 			/* Change core variables only if there is a change*/
887 			if(freesync_params->update_duration_in_ns !=
888 				state->time.update_duration_in_ns) {
889 
890 				state->video = freesync_params->enable;
891 				state->time.update_duration_in_ns =
892 					freesync_params->update_duration_in_ns;
893 
894 				freesync_program_required = true;
895 			}
896 			break;
897 		case FREESYNC_STATE_NONE:
898 			/* handle here to avoid warning */
899 			break;
900 		}
901 	}
902 
903 	if (freesync_program_required)
904 		/* Program freesync according to current state*/
905 		set_freesync_on_streams(core_freesync, streams, num_streams);
906 }
907 
908 
909 bool mod_freesync_get_state(struct mod_freesync *mod_freesync,
910 		const struct dc_stream *stream,
911 		struct mod_freesync_params *freesync_params)
912 {
913 	unsigned int index = 0;
914 	struct core_freesync *core_freesync = NULL;
915 
916 	if (mod_freesync == NULL)
917 		return false;
918 
919 	core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync);
920 	index = map_index_from_stream(core_freesync, stream);
921 
922 	if (core_freesync->map[index].state.fullscreen) {
923 		freesync_params->state = FREESYNC_STATE_FULLSCREEN;
924 		freesync_params->enable = true;
925 	} else if (core_freesync->map[index].state.static_screen) {
926 		freesync_params->state = FREESYNC_STATE_STATIC_SCREEN;
927 		freesync_params->enable = true;
928 	} else if (core_freesync->map[index].state.video) {
929 		freesync_params->state = FREESYNC_STATE_VIDEO;
930 		freesync_params->enable = true;
931 	} else {
932 		freesync_params->state = FREESYNC_STATE_NONE;
933 		freesync_params->enable = false;
934 	}
935 
936 	freesync_params->update_duration_in_ns =
937 		core_freesync->map[index].state.time.update_duration_in_ns;
938 
939 	freesync_params->windowed_fullscreen =
940 			core_freesync->map[index].state.windowed_fullscreen;
941 
942 	return true;
943 }
944 
945 bool mod_freesync_set_user_enable(struct mod_freesync *mod_freesync,
946 		const struct dc_stream **streams, int num_streams,
947 		struct mod_freesync_user_enable *user_enable)
948 {
949 	unsigned int stream_index, map_index;
950 	int persistent_data = 0;
951 	struct persistent_data_flag flag;
952 	struct core_dc *core_dc = NULL;
953 	struct core_freesync *core_freesync = NULL;
954 
955 	if (mod_freesync == NULL)
956 		return false;
957 
958 	core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync);
959 	core_dc = DC_TO_CORE(core_freesync->dc);
960 
961 	flag.save_per_edid = true;
962 	flag.save_per_link = false;
963 
964 	for(stream_index = 0; stream_index < num_streams;
965 			stream_index++){
966 
967 		map_index = map_index_from_stream(core_freesync,
968 				streams[stream_index]);
969 
970 		core_freesync->map[map_index].user_enable = *user_enable;
971 
972 		/* Write persistent data in registry*/
973 		if (core_freesync->map[map_index].user_enable.
974 				enable_for_gaming)
975 			persistent_data = persistent_data | 1;
976 		if (core_freesync->map[map_index].user_enable.
977 				enable_for_static)
978 			persistent_data = persistent_data | 2;
979 		if (core_freesync->map[map_index].user_enable.
980 				enable_for_video)
981 			persistent_data = persistent_data | 4;
982 
983 		dm_write_persistent_data(core_dc->ctx,
984 					streams[stream_index]->sink,
985 					FREESYNC_REGISTRY_NAME,
986 					"userenable",
987 					&persistent_data,
988 					sizeof(int),
989 					&flag);
990 	}
991 
992 	set_freesync_on_streams(core_freesync, streams, num_streams);
993 
994 	return true;
995 }
996 
997 bool mod_freesync_get_user_enable(struct mod_freesync *mod_freesync,
998 		const struct dc_stream *stream,
999 		struct mod_freesync_user_enable *user_enable)
1000 {
1001 	unsigned int index = 0;
1002 	struct core_freesync *core_freesync = NULL;
1003 
1004 	if (mod_freesync == NULL)
1005 		return false;
1006 
1007 	core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync);
1008 	index = map_index_from_stream(core_freesync, stream);
1009 
1010 	*user_enable = core_freesync->map[index].user_enable;
1011 
1012 	return true;
1013 }
1014 
1015 bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync,
1016 		const struct dc_stream *streams,
1017 		unsigned int min_refresh,
1018 		unsigned int max_refresh)
1019 {
1020 	unsigned int index = 0;
1021 	struct core_freesync *core_freesync;
1022 	struct freesync_state *state;
1023 
1024 	if (mod_freesync == NULL)
1025 		return false;
1026 
1027 	core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync);
1028 	index = map_index_from_stream(core_freesync, streams);
1029 	state = &core_freesync->map[index].state;
1030 
1031 	if (min_refresh == 0 || max_refresh == 0) {
1032 		/* Restore defaults */
1033 		calc_freesync_range(core_freesync, streams, state,
1034 			core_freesync->map[index].caps->
1035 			min_refresh_in_micro_hz,
1036 			state->nominal_refresh_rate_in_micro_hz);
1037 	} else {
1038 		calc_freesync_range(core_freesync, streams,
1039 				state,
1040 				min_refresh,
1041 				max_refresh);
1042 
1043 		/* Program vtotal min/max */
1044 		core_freesync->dc->stream_funcs.adjust_vmin_vmax(
1045 			core_freesync->dc, &streams, 1,
1046 			state->freesync_range.vmin,
1047 			state->freesync_range.vmax);
1048 	}
1049 
1050 	return true;
1051 }
1052 
1053 bool mod_freesync_get_min_max(struct mod_freesync *mod_freesync,
1054 		const struct dc_stream *stream,
1055 		unsigned int *min_refresh,
1056 		unsigned int *max_refresh)
1057 {
1058 	unsigned int index = 0;
1059 	struct core_freesync *core_freesync = NULL;
1060 
1061 	if (mod_freesync == NULL)
1062 		return false;
1063 
1064 	core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync);
1065 	index = map_index_from_stream(core_freesync, stream);
1066 
1067 	*min_refresh =
1068 		core_freesync->map[index].state.freesync_range.min_refresh;
1069 	*max_refresh =
1070 		core_freesync->map[index].state.freesync_range.max_refresh;
1071 
1072 	return true;
1073 }
1074 
1075 bool mod_freesync_get_vmin_vmax(struct mod_freesync *mod_freesync,
1076 		const struct dc_stream *stream,
1077 		unsigned int *vmin,
1078 		unsigned int *vmax)
1079 {
1080 	unsigned int index = 0;
1081 	struct core_freesync *core_freesync = NULL;
1082 
1083 	if (mod_freesync == NULL)
1084 		return false;
1085 
1086 	core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync);
1087 	index = map_index_from_stream(core_freesync, stream);
1088 
1089 	*vmin =
1090 		core_freesync->map[index].state.freesync_range.vmin;
1091 	*vmax =
1092 		core_freesync->map[index].state.freesync_range.vmax;
1093 
1094 	return true;
1095 }
1096 
1097 bool mod_freesync_get_v_position(struct mod_freesync *mod_freesync,
1098 		const struct dc_stream *stream,
1099 		unsigned int *nom_v_pos,
1100 		unsigned int *v_pos)
1101 {
1102 	unsigned int index = 0;
1103 	struct core_freesync *core_freesync = NULL;
1104 	struct crtc_position position;
1105 
1106 	if (mod_freesync == NULL)
1107 		return false;
1108 
1109 	core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync);
1110 	index = map_index_from_stream(core_freesync, stream);
1111 
1112 	if (core_freesync->dc->stream_funcs.get_crtc_position(
1113 			core_freesync->dc, &stream, 1,
1114 			&position.vertical_count, &position.nominal_vcount)) {
1115 
1116 		*nom_v_pos = position.vertical_count;
1117 		*v_pos = position.nominal_vcount;
1118 
1119 		return true;
1120 	}
1121 
1122 	return false;
1123 }
1124 
1125 void mod_freesync_notify_mode_change(struct mod_freesync *mod_freesync,
1126 		const struct dc_stream **streams, int num_streams)
1127 {
1128 	unsigned int stream_index, map_index;
1129 	struct freesync_state *state;
1130 	struct core_freesync *core_freesync = NULL;
1131 
1132 	if (mod_freesync == NULL)
1133 		return;
1134 
1135 	core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync);
1136 
1137 	for (stream_index = 0; stream_index < num_streams; stream_index++) {
1138 		map_index = map_index_from_stream(core_freesync,
1139 				streams[stream_index]);
1140 
1141 		state = &core_freesync->map[map_index].state;
1142 
1143 		if (core_freesync->map[map_index].caps->supported) {
1144 			/* Update the field rate for new timing */
1145 			unsigned long long temp;
1146 			temp = streams[stream_index]->timing.pix_clk_khz;
1147 			temp *= 1000ULL * 1000ULL * 1000ULL;
1148 			temp = div_u64(temp,
1149 					streams[stream_index]->timing.h_total);
1150 			temp = div_u64(temp,
1151 					streams[stream_index]->timing.v_total);
1152 			state->nominal_refresh_rate_in_micro_hz =
1153 					(unsigned int) temp;
1154 
1155 			/* Update the stream */
1156 			update_stream(core_freesync, streams[stream_index]);
1157 
1158 			/* Calculate vmin/vmax and refresh rate for
1159 			 * current mode
1160 			 */
1161 			calc_freesync_range(core_freesync, *streams, state,
1162 				core_freesync->map[map_index].caps->
1163 				min_refresh_in_micro_hz,
1164 				state->nominal_refresh_rate_in_micro_hz);
1165 		}
1166 	}
1167 
1168 	/* Program freesync according to current state*/
1169 	set_freesync_on_streams(core_freesync, streams, num_streams);
1170 }
1171 
1172 /* Add the timestamps to the cache and determine whether BTR programming
1173  * is required, depending on the times calculated
1174  */
1175 static void update_timestamps(struct core_freesync *core_freesync,
1176 		const struct dc_stream *stream, unsigned int map_index,
1177 		unsigned int last_render_time_in_us)
1178 {
1179 	struct freesync_state *state = &core_freesync->map[map_index].state;
1180 
1181 	state->time.render_times[state->time.render_times_index] =
1182 			last_render_time_in_us;
1183 	state->time.render_times_index++;
1184 
1185 	if (state->time.render_times_index >= RENDER_TIMES_MAX_COUNT)
1186 		state->time.render_times_index = 0;
1187 
1188 	if (last_render_time_in_us + BTR_EXIT_MARGIN <
1189 		state->time.max_render_time_in_us) {
1190 
1191 		/* Exit Below the Range */
1192 		if (state->btr.btr_active) {
1193 
1194 			state->btr.program_btr = true;
1195 			state->btr.btr_active = false;
1196 			state->btr.frame_counter = 0;
1197 
1198 		/* Exit Fixed Refresh mode */
1199 		} else if (state->fixed_refresh.fixed_refresh_active) {
1200 
1201 			state->fixed_refresh.program_fixed_refresh = true;
1202 			state->fixed_refresh.fixed_refresh_active = false;
1203 
1204 		}
1205 
1206 	} else if (last_render_time_in_us > state->time.max_render_time_in_us) {
1207 
1208 		/* Enter Below the Range */
1209 		if (!state->btr.btr_active &&
1210 				core_freesync->map[map_index].caps->btr_supported) {
1211 
1212 			state->btr.program_btr = true;
1213 			state->btr.btr_active = true;
1214 
1215 		/* Enter Fixed Refresh mode */
1216 		} else if (!state->fixed_refresh.fixed_refresh_active &&
1217 			!core_freesync->map[map_index].caps->btr_supported) {
1218 
1219 			state->fixed_refresh.program_fixed_refresh = true;
1220 			state->fixed_refresh.fixed_refresh_active = true;
1221 
1222 		}
1223 	}
1224 
1225 	/* When Below the Range is active, must react on every frame */
1226 	if (state->btr.btr_active)
1227 		state->btr.program_btr = true;
1228 }
1229 
1230 static void apply_below_the_range(struct core_freesync *core_freesync,
1231 		const struct dc_stream *stream, unsigned int map_index,
1232 		unsigned int last_render_time_in_us)
1233 {
1234 	unsigned int inserted_frame_duration_in_us = 0;
1235 	unsigned int mid_point_frames_ceil = 0;
1236 	unsigned int mid_point_frames_floor = 0;
1237 	unsigned int frame_time_in_us = 0;
1238 	unsigned int delta_from_mid_point_in_us_1 = 0xFFFFFFFF;
1239 	unsigned int delta_from_mid_point_in_us_2 = 0xFFFFFFFF;
1240 	unsigned int frames_to_insert = 0;
1241 	unsigned int min_frame_duration_in_ns = 0;
1242 	struct freesync_state *state = &core_freesync->map[map_index].state;
1243 
1244 	if (!state->btr.program_btr)
1245 		return;
1246 
1247 	state->btr.program_btr = false;
1248 
1249 	min_frame_duration_in_ns = ((unsigned int) (div64_u64(
1250 		(1000000000ULL * 1000000),
1251 		state->nominal_refresh_rate_in_micro_hz)));
1252 
1253 	/* Program BTR */
1254 
1255 	/* BTR set to "not active" so disengage */
1256 	if (!state->btr.btr_active)
1257 
1258 		/* Restore FreeSync */
1259 		set_freesync_on_streams(core_freesync, &stream, 1);
1260 
1261 	/* BTR set to "active" so engage */
1262 	else {
1263 
1264 		/* Calculate number of midPoint frames that could fit within
1265 		 * the render time interval- take ceil of this value
1266 		 */
1267 		mid_point_frames_ceil = (last_render_time_in_us +
1268 			state->btr.mid_point_in_us- 1) /
1269 			state->btr.mid_point_in_us;
1270 
1271 		if (mid_point_frames_ceil > 0) {
1272 
1273 			frame_time_in_us = last_render_time_in_us /
1274 				mid_point_frames_ceil;
1275 			delta_from_mid_point_in_us_1 = (state->btr.mid_point_in_us >
1276 				frame_time_in_us) ?
1277 				(state->btr.mid_point_in_us - frame_time_in_us):
1278 				(frame_time_in_us - state->btr.mid_point_in_us);
1279 		}
1280 
1281 		/* Calculate number of midPoint frames that could fit within
1282 		 * the render time interval- take floor of this value
1283 		 */
1284 		mid_point_frames_floor = last_render_time_in_us /
1285 			state->btr.mid_point_in_us;
1286 
1287 		if (mid_point_frames_floor > 0) {
1288 
1289 			frame_time_in_us = last_render_time_in_us /
1290 				mid_point_frames_floor;
1291 			delta_from_mid_point_in_us_2 = (state->btr.mid_point_in_us >
1292 				frame_time_in_us) ?
1293 				(state->btr.mid_point_in_us - frame_time_in_us):
1294 				(frame_time_in_us - state->btr.mid_point_in_us);
1295 		}
1296 
1297 		/* Choose number of frames to insert based on how close it
1298 		 * can get to the mid point of the variable range.
1299 		 */
1300 		if (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2)
1301 			frames_to_insert = mid_point_frames_ceil;
1302 		else
1303 			frames_to_insert = mid_point_frames_floor;
1304 
1305 		/* Either we've calculated the number of frames to insert,
1306 		 * or we need to insert min duration frames
1307 		 */
1308 		if (frames_to_insert > 0)
1309 			inserted_frame_duration_in_us = last_render_time_in_us /
1310 							frames_to_insert;
1311 
1312 		if (inserted_frame_duration_in_us <
1313 			state->time.min_render_time_in_us)
1314 
1315 			inserted_frame_duration_in_us =
1316 				state->time.min_render_time_in_us;
1317 
1318 		/* Cache the calculated variables */
1319 		state->btr.inserted_frame_duration_in_us =
1320 			inserted_frame_duration_in_us;
1321 		state->btr.frames_to_insert = frames_to_insert;
1322 		state->btr.frame_counter = frames_to_insert;
1323 
1324 	}
1325 }
1326 
1327 static void apply_fixed_refresh(struct core_freesync *core_freesync,
1328 		const struct dc_stream *stream, unsigned int map_index)
1329 {
1330 	unsigned int vmin = 0, vmax = 0;
1331 	struct freesync_state *state = &core_freesync->map[map_index].state;
1332 
1333 	if (!state->fixed_refresh.program_fixed_refresh)
1334 		return;
1335 
1336 	state->fixed_refresh.program_fixed_refresh = false;
1337 
1338 	/* Program Fixed Refresh */
1339 
1340 	/* Fixed Refresh set to "not active" so disengage */
1341 	if (!state->fixed_refresh.fixed_refresh_active) {
1342 		set_freesync_on_streams(core_freesync, &stream, 1);
1343 
1344 	/* Fixed Refresh set to "active" so engage (fix to max) */
1345 	} else {
1346 
1347 		vmin = state->freesync_range.vmin;
1348 
1349 		vmax = vmin;
1350 
1351 		core_freesync->dc->stream_funcs.adjust_vmin_vmax(
1352 				core_freesync->dc, &stream,
1353 				1, vmin,
1354 				vmax);
1355 	}
1356 }
1357 
1358 void mod_freesync_pre_update_plane_addresses(struct mod_freesync *mod_freesync,
1359 		const struct dc_stream **streams, int num_streams,
1360 		unsigned int curr_time_stamp_in_us)
1361 {
1362 	unsigned int stream_index, map_index, last_render_time_in_us = 0;
1363 	struct core_freesync *core_freesync = NULL;
1364 
1365 	if (mod_freesync == NULL)
1366 		return;
1367 
1368 	core_freesync = MOD_FREESYNC_TO_CORE(mod_freesync);
1369 
1370 	for (stream_index = 0; stream_index < num_streams; stream_index++) {
1371 
1372 		map_index = map_index_from_stream(core_freesync,
1373 						streams[stream_index]);
1374 
1375 		if (core_freesync->map[map_index].caps->supported) {
1376 
1377 			last_render_time_in_us = curr_time_stamp_in_us -
1378 					core_freesync->map[map_index].state.time.
1379 					prev_time_stamp_in_us;
1380 
1381 			/* Add the timestamps to the cache and determine
1382 			 * whether BTR program is required
1383 			 */
1384 			update_timestamps(core_freesync, streams[stream_index],
1385 					map_index, last_render_time_in_us);
1386 
1387 			if (core_freesync->map[map_index].state.fullscreen &&
1388 				core_freesync->map[map_index].user_enable.
1389 				enable_for_gaming) {
1390 
1391 				if (core_freesync->map[map_index].caps->btr_supported) {
1392 
1393 					apply_below_the_range(core_freesync,
1394 						streams[stream_index], map_index,
1395 						last_render_time_in_us);
1396 				} else {
1397 					apply_fixed_refresh(core_freesync,
1398 						streams[stream_index], map_index);
1399 				}
1400 			}
1401 
1402 			core_freesync->map[map_index].state.time.
1403 				prev_time_stamp_in_us = curr_time_stamp_in_us;
1404 		}
1405 
1406 	}
1407 }
1408