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