xref: /linux/drivers/gpu/drm/amd/display/modules/power/power_replay.c (revision 18fbf5151d2c0bfe433c7428eef03cabf5fdb2fa)
1 // SPDX-License-Identifier: MIT
2 //
3 // Copyright 2026 Advanced Micro Devices, Inc.
4 
5 #include "dm_services.h"
6 #include "dc.h"
7 #include "mod_power.h"
8 #include "core_types.h"
9 #include "dmcu.h"
10 #include "abm.h"
11 #include "power_helpers.h"
12 #include "dce/dmub_psr.h"
13 #include "dal_asic_id.h"
14 #include "link_service.h"
15 #include <linux/math.h>
16 
17 #define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */
18 #define DC_TRACE_LEVEL_MESSAGEP(...) /* do nothing */
19 #include "power_helpers.h"
20 #include "dc/inc/hw/dmcu.h"
21 #include "dc/inc/hw/abm.h"
22 #include "dc.h"
23 #include "core_types.h"
24 #include "dmub_cmd.h"
25 
26 #define MOD_POWER_TO_CORE(mod_power)\
27 		container_of(mod_power, struct core_power, mod_public)
28 
29 #define LOW_REFRESH_RATE_DURATION_US_UPPER_BOUND 25000
30 
31 static bool mod_power_set_replay_active(struct dc_stream_state *stream,
32 	bool replay_active,
33 	bool wait,
34 	bool force_static)
35 {
36 	uint64_t state;
37 	unsigned int retry_count;
38 	const unsigned int max_retry = 1000;
39 	struct dc_link *link = NULL;
40 
41 	if (!stream)
42 		return false;
43 
44 	link = dc_stream_get_link(stream);
45 
46 	if (!link)
47 		return false;
48 
49 	if (!dc_link_set_replay_allow_active(link, &replay_active, false, force_static, NULL))
50 		return false;
51 
52 	if (wait == true) {
53 
54 		for (retry_count = 0; retry_count <= max_retry; retry_count++) {
55 			dc_link_get_replay_state(link, &state);
56 			if (replay_active) {
57 				if (state != REPLAY_STATE_0 &&
58 					(!force_static || state == REPLAY_STATE_3))
59 					break;
60 			} else {
61 				if (state == REPLAY_STATE_0)
62 					break;
63 			}
64 			udelay(500);
65 		}
66 
67 		/* assert if max retry hit */
68 		if (retry_count >= max_retry)
69 			ASSERT(0);
70 	} else {
71 		/* To-do: Add trace log */
72 	}
73 
74 	return true;
75 }
76 
77 static unsigned int mod_power_replay_setup_power_opt(struct dc_link *link,
78 	unsigned int active_replay_events, bool is_ultra_sleep_mode)
79 {
80 	unsigned int power_opt = 0;
81 
82 	if (is_ultra_sleep_mode) {
83 		/* Static Screen */
84 		power_opt |= (replay_power_opt_smu_opt_static_screen | replay_power_opt_z10_static_screen);
85 	} else if (active_replay_events & replay_event_test_harness_ultra_sleep) {
86 		power_opt |= replay_power_opt_z10_static_screen;
87 	}
88 
89 	/* replay_power_opt_flag is a configuration parameter into the module that determines
90 	 * which optimizations to enable during replay
91 	 */
92 	power_opt &= link->replay_settings.config.replay_power_opt_supported;
93 
94 	return power_opt;
95 }
96 
97 static bool mod_power_replay_set_power_opt(struct mod_power *mod_power,
98 	struct dc_stream_state *stream,
99 	unsigned int active_replay_events,
100 	bool is_ultra_sleep_mode)
101 {
102 	(void)mod_power;
103 	struct dc_link *link = NULL;
104 	unsigned int power_opt = 0;
105 
106 	if (!stream)
107 		return false;
108 
109 	link = dc_stream_get_link(stream);
110 
111 	if (!link || !link->replay_settings.replay_feature_enabled)
112 		return false;
113 
114 	power_opt = mod_power_replay_setup_power_opt(link, active_replay_events, is_ultra_sleep_mode);
115 
116 	if (!dc_link_set_replay_allow_active(link, NULL, false, false, &power_opt))
117 		return false;
118 
119 	return true;
120 }
121 
122 bool mod_power_get_replay_event(struct mod_power *mod_power,
123 	struct dc_stream_state *stream,
124 	unsigned int *active_replay_events)
125 {
126 	struct core_power *core_power = NULL;
127 	unsigned int stream_index = 0;
128 
129 	if (mod_power == NULL)
130 		return false;
131 
132 	core_power = MOD_POWER_TO_CORE(mod_power);
133 
134 	if (core_power->num_entities == 0)
135 		return false;
136 
137 	stream_index = map_index_from_stream(core_power, stream);
138 
139 	*active_replay_events = core_power->map[stream_index].replay_events;
140 
141 	return true;
142 }
143 
144 static bool mod_power_update_replay_active_status(unsigned int active_replay_events,
145 	struct dc_link *link, uint32_t *coasting_vtotal, bool *is_full_screen_video,
146 	bool *is_ultra_sleep_mode, uint16_t *frame_skip_number, bool *is_video_playback)
147 {
148 	if (!link || !coasting_vtotal || !is_full_screen_video || !is_video_playback)
149 		return false;
150 
151 	// Check coasting_vtotal_table has been updated.
152 	if (!link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_STATIC]
153 		|| !link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_NOM])
154 		return false;
155 
156 	unsigned int replay_enable_option =
157 		link->replay_settings.config.replay_enable_option;
158 
159 	/* TODO: To support test harness and DDS event */
160 
161 	*coasting_vtotal = link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_NOM];
162 	ASSERT(link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_NOM] <= 0xFFFF);
163 	*frame_skip_number = (uint16_t)link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_NOM];
164 
165 	link->replay_settings.config.replay_timing_sync_supported = false;
166 
167 	*is_full_screen_video = false;
168 
169 	*is_ultra_sleep_mode = false;
170 
171 	*is_video_playback = false;
172 
173 	/* DSAT test scenario */
174 	if (active_replay_events & replay_event_test_harness_mode) {
175 		if (link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS])
176 			*coasting_vtotal =
177 				link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS];
178 
179 		ASSERT(link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS] <= 0xFFFF);
180 		*frame_skip_number =
181 			(uint16_t)link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS];
182 
183 		/* During the ultra sleep mode testing, disable the timing sync in short vblank mode */
184 		if (active_replay_events & (replay_event_test_harness_enable_replay)) {
185 			if ((active_replay_events & replay_event_test_harness_ultra_sleep) &&
186 				  !link->replay_settings.config.replay_support_fast_resync_in_ultra_sleep_mode)
187 				link->replay_settings.config.replay_timing_sync_supported = false;
188 			return true;
189 		} else
190 			return false;
191 	} else if (active_replay_events & (replay_event_test_harness_enable_replay)) {
192 		if (link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS])
193 			*coasting_vtotal = link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS];
194 		if (link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS]) {
195 			uint32_t frame_skip_val =
196 				link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS];
197 
198 			ASSERT(frame_skip_val <= 0xFFFF);
199 			*frame_skip_number = (uint16_t)frame_skip_val;
200 		}
201 
202 		/* During the ultra sleep mode testing, disable the timing sync in short vblank mode */
203 		if ((active_replay_events & replay_event_test_harness_ultra_sleep) &&
204 			  !link->replay_settings.config.replay_support_fast_resync_in_ultra_sleep_mode) {
205 			link->replay_settings.config.replay_timing_sync_supported = false;
206 		}
207 		return true;
208 	} else if (active_replay_events &
209 			(replay_event_test_harness_disable_replay | replay_event_os_request_disable)) {
210 		// set last set coasting vtotal
211 		if (link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS])
212 			*coasting_vtotal = link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS];
213 		if (link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS]) {
214 			uint32_t frame_skip_val =
215 				link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS];
216 
217 			ASSERT(frame_skip_val <= 0xFFFF);
218 			*frame_skip_number = (uint16_t)frame_skip_val;
219 		}
220 		return false;
221 	}
222 
223 	/* Inactive conditions */
224 	if (active_replay_events & (replay_event_edp_panel_off_disable_psr |
225 			replay_event_hw_programming |
226 			replay_event_vrr |
227 			replay_event_immediate_flip |
228 			replay_event_prepare_vtotal |
229 			replay_event_vrr_transition |
230 			replay_event_pause |
231 			replay_event_disable_replay_while_DPMS |
232 			replay_event_sleep_resume |
233 			replay_event_disable_in_AC |
234 			replay_event_disable_replay_while_detect_display |
235 			replay_event_infopacket |
236 			replay_event_crc_window_active))
237 		return false;
238 
239 	// Full screen scenario
240 	if (active_replay_events & replay_event_full_screen) {
241 		if (!(replay_enable_option & pr_enable_option_full_screen))
242 			return false;
243 	}
244 
245 	/* Full screen video scenario */
246 	if (active_replay_events & replay_event_big_screen_video) {
247 
248 		link->replay_settings.config.replay_timing_sync_supported = false;
249 
250 		if (replay_enable_option & pr_enable_option_full_screen_video_coasting) {
251 			unsigned int fsn_vid =
252 				link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_FULL_SCREEN_VIDEO];
253 
254 			*coasting_vtotal =
255 				link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_FULL_SCREEN_VIDEO];
256 			ASSERT(fsn_vid <= 0xFFFF);
257 			*frame_skip_number = (uint16_t)fsn_vid;
258 		}
259 
260 		*is_video_playback = true;
261 
262 		if ((replay_enable_option & pr_enable_option_full_screen_video) &&
263 			(replay_enable_option & pr_enable_option_full_screen_video_coasting)) {
264 			*is_full_screen_video = true;
265 			return true;
266 		} else
267 			return false;
268 	}
269 
270 	/* MPO video scenario
271 	 * Some of the cases may contain a full screen UI layer in MPO video scenario which is
272 	 * not the expected case to enable Replay.
273 	 */
274 	if ((active_replay_events & replay_event_mpo_video_selective_update) &&
275 		!(active_replay_events & replay_event_full_screen)) {
276 
277 		link->replay_settings.config.replay_timing_sync_supported = false;
278 
279 		if (replay_enable_option & pr_enable_option_mpo_video_coasting) {
280 			*coasting_vtotal = link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_NOM];
281 			{
282 				uint32_t frame_skip_val =
283 					link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_NOM];
284 
285 				ASSERT(frame_skip_val <= 0xFFFF);
286 				*frame_skip_number = (uint16_t)frame_skip_val;
287 			}
288 		}
289 
290 		*is_video_playback = true;
291 
292 		if (replay_enable_option & pr_enable_option_mpo_video)
293 			return true;
294 		else
295 			return false;
296 	}
297 
298 	/* Static screen scenario */
299 	if (!(active_replay_events & replay_event_vsync)) {
300 
301 		if (replay_enable_option & pr_enable_option_static_screen_coasting) {
302 			// Do not adjust eDP refresh rate if static screen + normal sleep mode
303 			if ((!(link->replay_settings.config.replay_power_opt_supported &
304 				replay_power_opt_z10_static_screen)) ||
305 				(active_replay_events & replay_event_cursor_updating)) {
306 				// normal sleep mode
307 				*coasting_vtotal =
308 					link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_NOM];
309 				{
310 					uint32_t frame_skip_val =
311 						link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_NOM];
312 
313 					ASSERT(frame_skip_val <= 0xFFFF);
314 					*frame_skip_number = (uint16_t)frame_skip_val;
315 				}
316 			} else {
317 				// ultra sleep mode
318 				*coasting_vtotal =
319 					link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_STATIC];
320 				{
321 					uint32_t frame_skip_val =
322 						link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_STATIC];
323 
324 					ASSERT(frame_skip_val <= 0xFFFF);
325 					*frame_skip_number = (uint16_t)frame_skip_val;
326 				}
327 				*is_ultra_sleep_mode = true;
328 			}
329 		}
330 
331 		if (replay_enable_option & pr_enable_option_static_screen) {
332 			if (!link->replay_settings.config.replay_support_fast_resync_in_ultra_sleep_mode)
333 				link->replay_settings.config.replay_timing_sync_supported = false;
334 			return true;
335 		} else
336 			return false;
337 	}
338 
339 	/* General UI scenario */
340 	if (active_replay_events & replay_event_general_ui) {
341 		if (replay_enable_option & pr_enable_option_general_ui)
342 			return true;
343 		else
344 			return false;
345 	}
346 
347 	return false;
348 }
349 
350 bool mod_power_replay_set_coasting_vtotal(struct mod_power *mod_power,
351 	const struct dc_stream_state *stream,
352 	uint32_t coasting_vtotal,
353 	uint16_t frame_skip_number)
354 {
355 	struct core_power *core_power = NULL;
356 	struct dc_link *link = NULL;
357 
358 	if (!stream)
359 		return false;
360 
361 	link = dc_stream_get_link(stream);
362 	if (!link || !link->replay_settings.replay_feature_enabled)
363 		return false;
364 
365 	if (mod_power == NULL)
366 		return false;
367 
368 	core_power = MOD_POWER_TO_CORE(mod_power);
369 
370 	if (core_power->num_entities == 0)
371 		return false;
372 
373 	return link->dc->link_srv->edp_set_coasting_vtotal(link, coasting_vtotal, frame_skip_number);
374 }
375 
376 void mod_power_replay_set_timing_sync_supported(struct mod_power *mod_power,
377 	const struct dc_stream_state *stream)
378 {
379 	struct core_power *core_power = NULL;
380 	struct dc_link *link = NULL;
381 	unsigned int stream_index = 0;
382 	union dmub_replay_cmd_set cmd_data = { 0 };
383 
384 	if (!stream || mod_power == NULL)
385 		return;
386 
387 	core_power = MOD_POWER_TO_CORE(mod_power);
388 	if (core_power->num_entities == 0)
389 		return;
390 
391 	stream_index = map_index_from_stream(core_power, stream);
392 	if (stream_index > core_power->num_entities) //invalid index
393 		return;
394 
395 	link = dc_stream_get_link(stream);
396 	if (!link || !link->replay_settings.replay_feature_enabled)
397 		return;
398 
399 	cmd_data.sync_data.timing_sync_supported = link->replay_settings.config.replay_timing_sync_supported;
400 
401 	link->dc->link_srv->edp_send_replay_cmd(link, Replay_Set_Timing_Sync_Supported,
402 		&cmd_data);
403 }
404 
405 void mod_power_replay_disabled_adaptive_sync_sdp(struct mod_power *mod_power,
406 	const struct dc_stream_state *stream, bool force_disabled)
407 {
408 	struct core_power *core_power = NULL;
409 	struct dc_link *link = NULL;
410 	unsigned int stream_index = 0;
411 	union dmub_replay_cmd_set cmd_data = { 0 };
412 
413 	if (!stream || mod_power == NULL)
414 		return;
415 
416 	core_power = MOD_POWER_TO_CORE(mod_power);
417 	if (core_power->num_entities == 0)
418 		return;
419 
420 	stream_index = map_index_from_stream(core_power, stream);
421 	if (stream_index > core_power->num_entities) //invalid index
422 		return;
423 
424 	link = dc_stream_get_link(stream);
425 	if (!link || !link->replay_settings.replay_feature_enabled)
426 		return;
427 
428 	cmd_data.disabled_adaptive_sync_sdp_data.force_disabled = force_disabled;
429 
430 	link->dc->link_srv->edp_send_replay_cmd(link, Replay_Disabled_Adaptive_Sync_SDP,
431 		&cmd_data);
432 }
433 
434 static void mod_power_replay_set_general_cmd(struct mod_power *mod_power,
435 	const struct dc_stream_state *stream,
436 	const enum dmub_cmd_replay_general_subtype general_cmd_type,
437 	const uint32_t param1, const uint32_t param2)
438 {
439 	struct core_power *core_power = NULL;
440 	struct dc_link *link = NULL;
441 	unsigned int stream_index = 0;
442 	union dmub_replay_cmd_set cmd_data = { 0 };
443 
444 	if (!stream || mod_power == NULL)
445 		return;
446 
447 	core_power = MOD_POWER_TO_CORE(mod_power);
448 	if (core_power->num_entities == 0)
449 		return;
450 
451 	stream_index = map_index_from_stream(core_power, stream);
452 	if (stream_index > core_power->num_entities) //invalid index
453 		return;
454 
455 	link = dc_stream_get_link(stream);
456 	if (!link || !link->replay_settings.replay_feature_enabled)
457 		return;
458 
459 	cmd_data.set_general_cmd_data.subtype = general_cmd_type;
460 	cmd_data.set_general_cmd_data.param1 = param1;
461 	cmd_data.set_general_cmd_data.param2 = param2;
462 	link->dc->link_srv->edp_send_replay_cmd(link, Replay_Set_General_Cmd,
463 		&cmd_data);
464 }
465 
466 void mod_power_replay_disabled_desync_error_detection(struct mod_power *mod_power,
467 	const struct dc_stream_state *stream,  bool force_disabled)
468 {
469 	mod_power_replay_set_general_cmd(mod_power, stream,
470 			REPLAY_GENERAL_CMD_DISABLED_DESYNC_ERROR_DETECTION,
471 			force_disabled, 0);
472 }
473 
474 static void mod_power_replay_set_pseudo_vtotal(struct mod_power *mod_power,
475 	const struct dc_stream_state *stream, uint16_t vtotal)
476 {
477 	struct core_power *core_power = NULL;
478 	struct dc_link *link = NULL;
479 	unsigned int stream_index = 0;
480 	union dmub_replay_cmd_set cmd_data = { 0 };
481 
482 	if (!stream || mod_power == NULL)
483 		return;
484 
485 	core_power = MOD_POWER_TO_CORE(mod_power);
486 	if (core_power->num_entities == 0)
487 		return;
488 
489 	stream_index = map_index_from_stream(core_power, stream);
490 	if (stream_index > core_power->num_entities) //invalid index
491 		return;
492 
493 	link = dc_stream_get_link(stream);
494 	if (!link || !link->replay_settings.replay_feature_enabled)
495 		return;
496 
497 	cmd_data.pseudo_vtotal_data.vtotal = vtotal;
498 
499 	if (link->replay_settings.last_pseudo_vtotal != vtotal) {
500 		link->replay_settings.last_pseudo_vtotal = vtotal;
501 		link->dc->link_srv->edp_send_replay_cmd(link, Replay_Set_Pseudo_VTotal, &cmd_data);
502 	}
503 }
504 
505 static void mod_power_update_error_status(struct mod_power *mod_power,
506 	const struct dc_stream_state *stream)
507 {
508 	struct dc_link *link = NULL;
509 	union replay_debug_flags *pDebug = NULL;
510 
511 	if (mod_power == NULL || stream == NULL)
512 		return;
513 
514 	link = dc_stream_get_link(stream);
515 
516 	if (!link)
517 		return;
518 
519 	pDebug = (union replay_debug_flags *)&link->replay_settings.config.debug_flags;
520 
521 	if (pDebug->bitfields.enable_visual_confirm_debug == 0)
522 		return;
523 
524 	mod_power_replay_set_general_cmd(mod_power, stream,
525 		REPLAY_GENERAL_CMD_UPDATE_ERROR_STATUS,
526 		link->replay_settings.config.replay_error_status.raw, 0);
527 }
528 
529 void mod_power_set_low_rr_activate(struct mod_power *mod_power,
530 	const struct dc_stream_state *stream, bool low_rr_supported)
531 {
532 	struct dc_link *link = NULL;
533 
534 	if (mod_power == NULL || stream == NULL)
535 		return;
536 
537 	link = dc_stream_get_link(stream);
538 
539 	if (!link)
540 		return;
541 
542 	mod_power_replay_set_general_cmd(mod_power, stream,
543 		REPLAY_GENERAL_CMD_SET_LOW_RR_ACTIVATE,
544 		low_rr_supported, 0);
545 }
546 
547 void mod_power_set_video_conferencing_activate(struct mod_power *mod_power,
548 	const struct dc_stream_state *stream, bool video_conferencing_activate)
549 {
550 	struct dc_link *link = NULL;
551 
552 	if (mod_power == NULL || stream == NULL)
553 		return;
554 
555 	link = dc_stream_get_link(stream);
556 	if (!link || !link->replay_settings.replay_feature_enabled)
557 		return;
558 
559 	mod_power_replay_set_general_cmd(mod_power, stream,
560 		REPLAY_GENERAL_CMD_VIDEO_CONFERENCING,
561 		video_conferencing_activate, 0);
562 }
563 
564 void mod_power_set_coasting_vtotal_without_frame_update(struct mod_power *mod_power,
565 	const struct dc_stream_state *stream, uint32_t coasting_vtotal)
566 {
567 	struct dc_link *link = NULL;
568 
569 	if (mod_power == NULL || stream == NULL)
570 		return;
571 
572 	link = dc_stream_get_link(stream);
573 	if (!link || !link->replay_settings.replay_feature_enabled)
574 		return;
575 
576 	mod_power_replay_set_general_cmd(mod_power, stream,
577 		REPLAY_GENERAL_CMD_SET_COASTING_VTOTAL_WITHOUT_FRAME_UPDATE,
578 		coasting_vtotal, 0);
579 }
580 
581 void mod_power_set_replay_continuously_resync(struct mod_power *mod_power,
582 	const struct dc_stream_state *stream, bool enable)
583 {
584 	struct dc_link *link = NULL;
585 
586 	if (mod_power == NULL || stream == NULL)
587 		return;
588 
589 	link = dc_stream_get_link(stream);
590 	if (!link || !link->replay_settings.replay_feature_enabled)
591 		return;
592 
593 	mod_power_replay_set_general_cmd(mod_power, stream,
594 		REPLAY_GENERAL_CMD_SET_CONTINUOUSLY_RESYNC,
595 		enable, 0);
596 }
597 
598 void mod_power_set_live_capture_with_cvt_activate(struct mod_power *mod_power,
599 	const struct dc_stream_state *stream, bool live_capture_with_cvt_activate)
600 {
601 	struct dc_link *link = NULL;
602 
603 	if (mod_power == NULL || stream == NULL)
604 		return;
605 
606 	link = dc_stream_get_link(stream);
607 	if (!link || !link->replay_settings.replay_feature_enabled)
608 		return;
609 
610 	// Check if LIVE_CAPTURE_WITH_CVT bit is enabled in replay optimization config
611 	if (!link->replay_settings.config.replay_optimization.bits.LIVE_CAPTURE_WITH_CVT)
612 		return;
613 
614 	if (link->replay_settings.config.live_capture_with_cvt_activated != live_capture_with_cvt_activate) {
615 		link->replay_settings.config.live_capture_with_cvt_activated = live_capture_with_cvt_activate;
616 		mod_power_replay_set_general_cmd(mod_power, stream,
617 			REPLAY_GENERAL_CMD_LIVE_CAPTURE_WITH_CVT,
618 			live_capture_with_cvt_activate, 0);
619 	}
620 }
621 
622 bool mod_power_set_replay_event(struct mod_power *mod_power,
623 	struct dc_stream_state *stream, bool set_event,
624 	enum replay_event event, bool wait_for_disable)
625 {
626 	struct core_power *core_power = NULL;
627 	struct dc_link *link = NULL;
628 	unsigned int stream_index = 0;
629 	unsigned int active_replay_events = 0;
630 	bool replay_active_request = false;
631 	bool force_static = false;
632 	uint32_t coasting_vtotal = 0;
633 	bool current_timing_sync_status = false;
634 	bool is_full_screen_video = false;
635 	bool is_ultra_sleep_mode = false;
636 	unsigned int sink_duration_us = 0;
637 	bool low_rr_active = false;
638 	uint16_t frame_skip_number = 0;
639 	bool is_video_playback = false;
640 
641 	if (!stream)
642 		return false;
643 
644 	if (mod_power == NULL)
645 		return false;
646 
647 	core_power = MOD_POWER_TO_CORE(mod_power);
648 
649 	if (core_power->num_entities == 0)
650 		return false;
651 
652 	stream_index = map_index_from_stream(core_power, stream);
653 
654 	if (set_event)
655 		core_power->map[stream_index].replay_events |= event;
656 	else
657 		core_power->map[stream_index].replay_events &= ~event;
658 
659 	link = dc_stream_get_link(stream);
660 	if (!link || !link->replay_settings.replay_feature_enabled)
661 		return false;
662 
663 	if ((core_power->map[stream_index].replay_events & replay_event_disable_replay_while_switching_mux) != 0)
664 		return false;
665 
666 	if ((core_power->map[stream_index].replay_events & replay_event_os_override_hold) != 0)
667 		return false;
668 
669 	active_replay_events = core_power->map[stream_index].replay_events;
670 
671 	current_timing_sync_status =
672 		link->replay_settings.config.replay_timing_sync_supported;
673 
674 	replay_active_request = mod_power_update_replay_active_status(active_replay_events,
675 		link, &coasting_vtotal, &is_full_screen_video, &is_ultra_sleep_mode, &frame_skip_number, &is_video_playback);
676 
677 	if (is_full_screen_video)
678 		mod_power_replay_set_pseudo_vtotal(mod_power, stream,
679 			link->replay_settings.low_rr_full_screen_video_pseudo_vtotal);
680 	else
681 		mod_power_replay_set_pseudo_vtotal(mod_power, stream, 0);
682 
683 	//If timing_sync_status change, then re-enabled set timing_sync_supported value and re-enabled replay
684 	if (current_timing_sync_status != link->replay_settings.config.replay_timing_sync_supported)
685 		mod_power_replay_set_timing_sync_supported(mod_power, stream);
686 
687 	if (link->replay_settings.config.low_rr_supported) {
688 		sink_duration_us =
689 			(unsigned int)(div_u64(((unsigned long long)(coasting_vtotal)
690 				* 10000) * stream->timing.h_total,
691 					stream->timing.pix_clk_100hz));
692 		low_rr_active = sink_duration_us < LOW_REFRESH_RATE_DURATION_US_UPPER_BOUND ? false : true;
693 		if (low_rr_active != link->replay_settings.config.low_rr_activated) {
694 			mod_power_set_low_rr_activate(mod_power, stream, low_rr_active);
695 			link->replay_settings.config.low_rr_activated = low_rr_active;
696 		}
697 	}
698 
699 	// The function return fail when
700 	// 1. DMUB function is not support (for backward compatible).
701 	// 2. active_replay_events or coasting_vtotal is not updated in the same time
702 	if (!mod_power_replay_set_power_opt_and_coasting_vtotal(mod_power,
703 		stream, active_replay_events, coasting_vtotal, is_ultra_sleep_mode, frame_skip_number)) {
704 		if (!mod_power_replay_set_power_opt(mod_power, stream, active_replay_events, is_ultra_sleep_mode))
705 			return false;
706 
707 		if (!mod_power_replay_set_coasting_vtotal(mod_power, stream, coasting_vtotal, frame_skip_number))
708 			return false;
709 	}
710 
711 	mod_power_set_live_capture_with_cvt_activate(mod_power, stream, is_video_playback);
712 
713 	mod_power_update_error_status(mod_power, stream);
714 
715 	// If Replay is going to be enable (No matter is disable -> enable or enable -> enable), we don't need to wait.
716 	// If Replay is going to be disable
717 	//     if disable -> disable
718 	//         -> Replay DMUB state should be state 0.
719 	//            So no matter wait_for_disable is true or not, it should makes no difference.
720 	//     if enable -> disable -> We should wait if wait_for_disable is true.
721 	if (replay_active_request)
722 		wait_for_disable = false;
723 
724 	if (!mod_power_set_replay_active(stream, replay_active_request, wait_for_disable, force_static))
725 		return false;
726 
727 	return true;
728 }
729 
730 bool mod_power_get_replay_active_status(const struct dc_stream_state *stream,
731 	bool *replay_active)
732 {
733 	const struct dc_link *link = NULL;
734 
735 	if (!stream)
736 		return false;
737 
738 	link = dc_stream_get_link(stream);
739 	*replay_active = link->replay_settings.replay_allow_active;
740 
741 	return true;
742 }
743 
744 void mod_power_replay_residency(const struct dc_stream_state *stream,
745 	unsigned int *residency, const bool is_start, const bool is_alpm)
746 {
747 	const struct dc_link *link = NULL;
748 	enum pr_residency_mode mode;
749 
750 	if (!stream)
751 		return;
752 
753 	link = dc_stream_get_link(stream);
754 
755 	if (is_alpm)
756 		mode = PR_RESIDENCY_MODE_ALPM;
757 	else
758 		mode = PR_RESIDENCY_MODE_PHY;
759 
760 	if (link && link->dc && link->dc->link_srv)
761 		link->dc->link_srv->edp_replay_residency(link, residency, is_start, mode);
762 }
763 
764 bool mod_power_replay_set_power_opt_and_coasting_vtotal(struct mod_power *mod_power,
765 	const struct dc_stream_state *stream, unsigned int active_replay_events, uint32_t coasting_vtotal,
766 	bool is_ultra_sleep_mode, uint16_t frame_skip_number)
767 {
768 	struct core_power *core_power = NULL;
769 	struct dc_link *link = NULL;
770 	unsigned int power_opt = 0;
771 
772 	if (!stream)
773 		return false;
774 
775 	if (mod_power == NULL)
776 		return false;
777 
778 	core_power = MOD_POWER_TO_CORE(mod_power);
779 
780 	if (core_power->num_entities == 0)
781 		return false;
782 
783 	link = dc_stream_get_link(stream);
784 
785 	if (!link || !link->replay_settings.replay_feature_enabled)
786 		return false;
787 
788 	power_opt = mod_power_replay_setup_power_opt(link, active_replay_events, is_ultra_sleep_mode);
789 
790 	return link->dc->link_srv->edp_set_replay_power_opt_and_coasting_vtotal(link, &power_opt, coasting_vtotal, frame_skip_number);
791 }
792 
793 void mod_power_replay_notify_mode_change(struct mod_power *mod_power,
794 	struct dc *dc,
795 	struct dc_link *link,
796 	const struct dc_stream_state *stream,
797 	unsigned int stream_index)
798 {
799 	struct core_power *core_power = NULL;
800 	int active_replay_events = 0;
801 
802 	if (!mod_power || !dc || !link || !stream)
803 		return;
804 
805 	core_power = MOD_POWER_TO_CORE(mod_power);
806 	active_replay_events = core_power->map[stream_index].replay_events;
807 
808 	/* forced psr is active for seamless switch.
809 	 * Re-running edp_setup_psr would disturb the freeze,
810 	 * so skip the PSR re-setup until forced psr releases the override.
811 	 */
812 	if (active_replay_events & replay_event_os_override_hold)
813 		return;
814 
815 	link->replay_settings.replay_smu_opt_enable =
816 		(link->replay_settings.config.replay_smu_opt_supported &&
817 		mod_power_only_edp(dc->current_state, stream));
818 
819 	if (active_replay_events & replay_event_os_request_force_ffu) {
820 		link->replay_settings.config.os_request_force_ffu = true;
821 	}
822 
823 	if (dc_is_embedded_signal(stream->signal))
824 		dc->link_srv->dp_setup_replay(link, stream);
825 }
826 
827 void init_replay_config(struct dc_link *link, struct replay_config *pr_config)
828 {
829 	link->replay_settings.config = *pr_config;
830 }
831 
832 void set_replay_frame_skip_number(struct dc_link *link,
833 	enum replay_coasting_vtotal_type type,
834 	uint32_t coasting_vtotal_refresh_rate_uhz,
835 	uint32_t flicker_free_refresh_rate_uhz,
836 	bool is_defer)
837 {
838 	uint32_t *frame_skip_number_array = NULL;
839 	uint32_t frame_skip_number = 0;
840 
841 	if (link == NULL)
842 		return;
843 
844 	if (link->replay_settings.config.frame_skip_supported == false)
845 		return;
846 
847 	if (flicker_free_refresh_rate_uhz == 0 || coasting_vtotal_refresh_rate_uhz == 0)
848 		return;
849 
850 	if (is_defer)
851 		frame_skip_number_array = link->replay_settings.defer_frame_skip_number_table;
852 	else
853 		frame_skip_number_array = link->replay_settings.frame_skip_number_table;
854 
855 	if (frame_skip_number_array == NULL)
856 		return;
857 
858 	frame_skip_number = (coasting_vtotal_refresh_rate_uhz + 500000) / flicker_free_refresh_rate_uhz;
859 
860 	if (frame_skip_number >= 1)
861 		frame_skip_number_array[type] = frame_skip_number - 1;
862 	else
863 		frame_skip_number_array[type] = 0;
864 }
865 
866 void set_replay_defer_update_coasting_vtotal(struct dc_link *link,
867 	enum replay_coasting_vtotal_type type,
868 	uint32_t vtotal)
869 {
870 	link->replay_settings.defer_update_coasting_vtotal_table[type] = vtotal;
871 }
872 
873 void update_replay_coasting_vtotal_from_defer(struct dc_link *link,
874 	enum replay_coasting_vtotal_type type)
875 {
876 	link->replay_settings.coasting_vtotal_table[type] =
877 		link->replay_settings.defer_update_coasting_vtotal_table[type];
878 	link->replay_settings.frame_skip_number_table[type] =
879 		link->replay_settings.defer_frame_skip_number_table[type];
880 }
881 
882 void set_replay_coasting_vtotal(struct dc_link *link,
883 	enum replay_coasting_vtotal_type type,
884 	uint32_t vtotal)
885 {
886 	link->replay_settings.coasting_vtotal_table[type] = vtotal;
887 }
888 
889 void set_replay_low_rr_full_screen_video_src_vtotal(struct dc_link *link, uint16_t vtotal)
890 {
891 	link->replay_settings.low_rr_full_screen_video_pseudo_vtotal = vtotal;
892 }
893 
894 void calculate_replay_link_off_frame_count(struct dc_link *link,
895 	uint16_t vtotal, uint16_t htotal)
896 {
897 	uint32_t max_link_off_frame_count = 0;
898 	uint16_t max_deviation_line = 0,  pixel_deviation_per_line = 0;
899 
900 	if (!link || link->replay_settings.config.replay_version != DC_FREESYNC_REPLAY)
901 		return;
902 
903 	max_deviation_line = link->dpcd_caps.pr_info.max_deviation_line;
904 	pixel_deviation_per_line = link->dpcd_caps.pr_info.pixel_deviation_per_line;
905 
906 	if (htotal != 0 && vtotal != 0 && pixel_deviation_per_line != 0)
907 		max_link_off_frame_count = htotal * max_deviation_line / (pixel_deviation_per_line * vtotal);
908 	else
909 		ASSERT(0);
910 
911 	link->replay_settings.link_off_frame_count = max_link_off_frame_count;
912 }
913 
914 void reset_replay_dsync_error_count(struct dc_link *link)
915 {
916 	link->replay_settings.replay_desync_error_fail_count = 0;
917 }
918