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