xref: /linux/drivers/gpu/drm/amd/display/modules/power/power_replay.c (revision bba2c3615bd6cfee7456d1130f2e6b01b3f4e9ba)
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 		if (link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS]) {
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 
184 		/* During the ultra sleep mode testing, disable the timing sync in short vblank mode */
185 		if (active_replay_events & (replay_event_test_harness_enable_replay)) {
186 			if ((active_replay_events & replay_event_test_harness_ultra_sleep) &&
187 				  !link->replay_settings.config.replay_support_fast_resync_in_ultra_sleep_mode)
188 				link->replay_settings.config.replay_timing_sync_supported = false;
189 			return true;
190 		} else
191 			return false;
192 	} else if (active_replay_events & (replay_event_test_harness_enable_replay)) {
193 		if (link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS])
194 			*coasting_vtotal = link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS];
195 		if (link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS]) {
196 			uint32_t frame_skip_val =
197 				link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS];
198 
199 			ASSERT(frame_skip_val <= 0xFFFF);
200 			*frame_skip_number = (uint16_t)frame_skip_val;
201 		}
202 
203 		/* During the ultra sleep mode testing, disable the timing sync in short vblank mode */
204 		if ((active_replay_events & replay_event_test_harness_ultra_sleep) &&
205 			  !link->replay_settings.config.replay_support_fast_resync_in_ultra_sleep_mode) {
206 			link->replay_settings.config.replay_timing_sync_supported = false;
207 		}
208 		return true;
209 	} else if (active_replay_events &
210 			(replay_event_test_harness_disable_replay | replay_event_os_request_disable)) {
211 		// set last set coasting vtotal
212 		if (link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS])
213 			*coasting_vtotal = link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS];
214 		if (link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS]) {
215 			uint32_t frame_skip_val =
216 				link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS];
217 
218 			ASSERT(frame_skip_val <= 0xFFFF);
219 			*frame_skip_number = (uint16_t)frame_skip_val;
220 		}
221 		return false;
222 	}
223 
224 	/* Inactive conditions */
225 	if (active_replay_events & (replay_event_edp_panel_off_disable_psr |
226 			replay_event_hw_programming |
227 			replay_event_vrr |
228 			replay_event_immediate_flip |
229 			replay_event_prepare_vtotal |
230 			replay_event_vrr_transition |
231 			replay_event_pause |
232 			replay_event_disable_replay_while_DPMS |
233 			replay_event_sleep_resume |
234 			replay_event_disable_in_AC |
235 			replay_event_disable_replay_while_detect_display |
236 			replay_event_infopacket |
237 			replay_event_crc_window_active))
238 		return false;
239 
240 	// Full screen scenario
241 	if (active_replay_events & replay_event_full_screen) {
242 		if (!(replay_enable_option & pr_enable_option_full_screen))
243 			return false;
244 	}
245 
246 	/* Full screen video scenario */
247 	if (active_replay_events & replay_event_big_screen_video) {
248 
249 		link->replay_settings.config.replay_timing_sync_supported = false;
250 
251 		if (replay_enable_option & pr_enable_option_full_screen_video_coasting) {
252 			unsigned int fsn_vid =
253 				link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_FULL_SCREEN_VIDEO];
254 
255 			*coasting_vtotal =
256 				link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_FULL_SCREEN_VIDEO];
257 			ASSERT(fsn_vid <= 0xFFFF);
258 			*frame_skip_number = (uint16_t)fsn_vid;
259 		}
260 
261 		*is_video_playback = true;
262 
263 		if ((replay_enable_option & pr_enable_option_full_screen_video) &&
264 			(replay_enable_option & pr_enable_option_full_screen_video_coasting)) {
265 			*is_full_screen_video = true;
266 			return true;
267 		} else
268 			return false;
269 	}
270 
271 	/* MPO video scenario
272 	 * Some of the cases may contain a full screen UI layer in MPO video scenario which is
273 	 * not the expected case to enable Replay.
274 	 */
275 	if ((active_replay_events & replay_event_mpo_video_selective_update) &&
276 		!(active_replay_events & replay_event_full_screen)) {
277 
278 		link->replay_settings.config.replay_timing_sync_supported = false;
279 
280 		if (replay_enable_option & pr_enable_option_mpo_video_coasting) {
281 			*coasting_vtotal = link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_NOM];
282 			{
283 				uint32_t frame_skip_val =
284 					link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_NOM];
285 
286 				ASSERT(frame_skip_val <= 0xFFFF);
287 				*frame_skip_number = (uint16_t)frame_skip_val;
288 			}
289 		}
290 
291 		*is_video_playback = true;
292 
293 		if (replay_enable_option & pr_enable_option_mpo_video)
294 			return true;
295 		else
296 			return false;
297 	}
298 
299 	/* Static screen scenario */
300 	if (!(active_replay_events & replay_event_vsync)) {
301 
302 		if (replay_enable_option & pr_enable_option_static_screen_coasting) {
303 			// Do not adjust eDP refresh rate if static screen + normal sleep mode
304 			if ((!(link->replay_settings.config.replay_power_opt_supported &
305 				replay_power_opt_z10_static_screen)) ||
306 				(active_replay_events & replay_event_cursor_updating)) {
307 				// normal sleep mode
308 				*coasting_vtotal =
309 					link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_NOM];
310 				{
311 					uint32_t frame_skip_val =
312 						link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_NOM];
313 
314 					ASSERT(frame_skip_val <= 0xFFFF);
315 					*frame_skip_number = (uint16_t)frame_skip_val;
316 				}
317 			} else {
318 				// ultra sleep mode
319 				*coasting_vtotal =
320 					link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_STATIC];
321 				{
322 					uint32_t frame_skip_val =
323 						link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_STATIC];
324 
325 					ASSERT(frame_skip_val <= 0xFFFF);
326 					*frame_skip_number = (uint16_t)frame_skip_val;
327 				}
328 				*is_ultra_sleep_mode = true;
329 			}
330 		}
331 
332 		if (replay_enable_option & pr_enable_option_static_screen) {
333 			if (!link->replay_settings.config.replay_support_fast_resync_in_ultra_sleep_mode)
334 				link->replay_settings.config.replay_timing_sync_supported = false;
335 			return true;
336 		} else
337 			return false;
338 	}
339 
340 	/* General UI scenario */
341 	if (active_replay_events & replay_event_general_ui) {
342 		if (replay_enable_option & pr_enable_option_general_ui)
343 			return true;
344 		else
345 			return false;
346 	}
347 
348 	return false;
349 }
350 
351 bool mod_power_replay_set_coasting_vtotal(struct mod_power *mod_power,
352 	const struct dc_stream_state *stream,
353 	uint32_t coasting_vtotal,
354 	uint16_t frame_skip_number)
355 {
356 	struct core_power *core_power = NULL;
357 	struct dc_link *link = NULL;
358 
359 	if (!stream)
360 		return false;
361 
362 	link = dc_stream_get_link(stream);
363 	if (!link || !link->replay_settings.replay_feature_enabled)
364 		return false;
365 
366 	if (mod_power == NULL)
367 		return false;
368 
369 	core_power = MOD_POWER_TO_CORE(mod_power);
370 
371 	if (core_power->num_entities == 0)
372 		return false;
373 
374 	return link->dc->link_srv->edp_set_coasting_vtotal(link, coasting_vtotal, frame_skip_number);
375 }
376 
377 void mod_power_replay_set_timing_sync_supported(struct mod_power *mod_power,
378 	const struct dc_stream_state *stream)
379 {
380 	struct core_power *core_power = NULL;
381 	struct dc_link *link = NULL;
382 	unsigned int stream_index = 0;
383 	union dmub_replay_cmd_set cmd_data = { 0 };
384 
385 	if (!stream || mod_power == NULL)
386 		return;
387 
388 	core_power = MOD_POWER_TO_CORE(mod_power);
389 	if (core_power->num_entities == 0)
390 		return;
391 
392 	stream_index = map_index_from_stream(core_power, stream);
393 	if (stream_index > core_power->num_entities) //invalid index
394 		return;
395 
396 	link = dc_stream_get_link(stream);
397 	if (!link || !link->replay_settings.replay_feature_enabled)
398 		return;
399 
400 	cmd_data.sync_data.timing_sync_supported = link->replay_settings.config.replay_timing_sync_supported;
401 
402 	link->dc->link_srv->edp_send_replay_cmd(link, Replay_Set_Timing_Sync_Supported,
403 		&cmd_data);
404 }
405 
406 void mod_power_replay_disabled_adaptive_sync_sdp(struct mod_power *mod_power,
407 	const struct dc_stream_state *stream, bool force_disabled)
408 {
409 	struct core_power *core_power = NULL;
410 	struct dc_link *link = NULL;
411 	unsigned int stream_index = 0;
412 	union dmub_replay_cmd_set cmd_data = { 0 };
413 
414 	if (!stream || mod_power == NULL)
415 		return;
416 
417 	core_power = MOD_POWER_TO_CORE(mod_power);
418 	if (core_power->num_entities == 0)
419 		return;
420 
421 	stream_index = map_index_from_stream(core_power, stream);
422 	if (stream_index > core_power->num_entities) //invalid index
423 		return;
424 
425 	link = dc_stream_get_link(stream);
426 	if (!link || !link->replay_settings.replay_feature_enabled)
427 		return;
428 
429 	cmd_data.disabled_adaptive_sync_sdp_data.force_disabled = force_disabled;
430 
431 	link->dc->link_srv->edp_send_replay_cmd(link, Replay_Disabled_Adaptive_Sync_SDP,
432 		&cmd_data);
433 }
434 
435 static void mod_power_replay_set_general_cmd(struct mod_power *mod_power,
436 	const struct dc_stream_state *stream,
437 	const enum dmub_cmd_replay_general_subtype general_cmd_type,
438 	const uint32_t param1, const uint32_t param2)
439 {
440 	struct core_power *core_power = NULL;
441 	struct dc_link *link = NULL;
442 	unsigned int stream_index = 0;
443 	union dmub_replay_cmd_set cmd_data = { 0 };
444 
445 	if (!stream || mod_power == NULL)
446 		return;
447 
448 	core_power = MOD_POWER_TO_CORE(mod_power);
449 	if (core_power->num_entities == 0)
450 		return;
451 
452 	stream_index = map_index_from_stream(core_power, stream);
453 	if (stream_index > core_power->num_entities) //invalid index
454 		return;
455 
456 	link = dc_stream_get_link(stream);
457 	if (!link || !link->replay_settings.replay_feature_enabled)
458 		return;
459 
460 	cmd_data.set_general_cmd_data.subtype = general_cmd_type;
461 	cmd_data.set_general_cmd_data.param1 = param1;
462 	cmd_data.set_general_cmd_data.param2 = param2;
463 	link->dc->link_srv->edp_send_replay_cmd(link, Replay_Set_General_Cmd,
464 		&cmd_data);
465 }
466 
467 void mod_power_replay_disabled_desync_error_detection(struct mod_power *mod_power,
468 	const struct dc_stream_state *stream,  bool force_disabled)
469 {
470 	mod_power_replay_set_general_cmd(mod_power, stream,
471 			REPLAY_GENERAL_CMD_DISABLED_DESYNC_ERROR_DETECTION,
472 			force_disabled, 0);
473 }
474 
475 static void mod_power_replay_set_pseudo_vtotal(struct mod_power *mod_power,
476 	const struct dc_stream_state *stream, uint16_t vtotal)
477 {
478 	struct core_power *core_power = NULL;
479 	struct dc_link *link = NULL;
480 	unsigned int stream_index = 0;
481 	union dmub_replay_cmd_set cmd_data = { 0 };
482 
483 	if (!stream || mod_power == NULL)
484 		return;
485 
486 	core_power = MOD_POWER_TO_CORE(mod_power);
487 	if (core_power->num_entities == 0)
488 		return;
489 
490 	stream_index = map_index_from_stream(core_power, stream);
491 	if (stream_index > core_power->num_entities) //invalid index
492 		return;
493 
494 	link = dc_stream_get_link(stream);
495 	if (!link || !link->replay_settings.replay_feature_enabled)
496 		return;
497 
498 	cmd_data.pseudo_vtotal_data.vtotal = vtotal;
499 
500 	if (link->replay_settings.last_pseudo_vtotal != vtotal) {
501 		link->replay_settings.last_pseudo_vtotal = vtotal;
502 		link->dc->link_srv->edp_send_replay_cmd(link, Replay_Set_Pseudo_VTotal, &cmd_data);
503 	}
504 }
505 
506 static void mod_power_update_error_status(struct mod_power *mod_power,
507 	const struct dc_stream_state *stream)
508 {
509 	struct dc_link *link = NULL;
510 	union replay_debug_flags *pDebug = NULL;
511 
512 	if (mod_power == NULL || stream == NULL)
513 		return;
514 
515 	link = dc_stream_get_link(stream);
516 
517 	if (!link)
518 		return;
519 
520 	pDebug = (union replay_debug_flags *)&link->replay_settings.config.debug_flags;
521 
522 	if (pDebug->bitfields.enable_visual_confirm_debug == 0)
523 		return;
524 
525 	mod_power_replay_set_general_cmd(mod_power, stream,
526 		REPLAY_GENERAL_CMD_UPDATE_ERROR_STATUS,
527 		link->replay_settings.config.replay_error_status.raw, 0);
528 }
529 
530 void mod_power_set_low_rr_activate(struct mod_power *mod_power,
531 	const struct dc_stream_state *stream, bool low_rr_supported)
532 {
533 	struct dc_link *link = NULL;
534 
535 	if (mod_power == NULL || stream == NULL)
536 		return;
537 
538 	link = dc_stream_get_link(stream);
539 
540 	if (!link)
541 		return;
542 
543 	mod_power_replay_set_general_cmd(mod_power, stream,
544 		REPLAY_GENERAL_CMD_SET_LOW_RR_ACTIVATE,
545 		low_rr_supported, 0);
546 }
547 
548 void mod_power_set_video_conferencing_activate(struct mod_power *mod_power,
549 	const struct dc_stream_state *stream, bool video_conferencing_activate)
550 {
551 	struct dc_link *link = NULL;
552 
553 	if (mod_power == NULL || stream == NULL)
554 		return;
555 
556 	link = dc_stream_get_link(stream);
557 	if (!link || !link->replay_settings.replay_feature_enabled)
558 		return;
559 
560 	mod_power_replay_set_general_cmd(mod_power, stream,
561 		REPLAY_GENERAL_CMD_VIDEO_CONFERENCING,
562 		video_conferencing_activate, 0);
563 }
564 
565 void mod_power_set_coasting_vtotal_without_frame_update(struct mod_power *mod_power,
566 	const struct dc_stream_state *stream, uint32_t coasting_vtotal)
567 {
568 	struct dc_link *link = NULL;
569 
570 	if (mod_power == NULL || stream == NULL)
571 		return;
572 
573 	link = dc_stream_get_link(stream);
574 	if (!link || !link->replay_settings.replay_feature_enabled)
575 		return;
576 
577 	mod_power_replay_set_general_cmd(mod_power, stream,
578 		REPLAY_GENERAL_CMD_SET_COASTING_VTOTAL_WITHOUT_FRAME_UPDATE,
579 		coasting_vtotal, 0);
580 }
581 
582 void mod_power_set_replay_continuously_resync(struct mod_power *mod_power,
583 	const struct dc_stream_state *stream, bool enable)
584 {
585 	struct dc_link *link = NULL;
586 
587 	if (mod_power == NULL || stream == NULL)
588 		return;
589 
590 	link = dc_stream_get_link(stream);
591 	if (!link || !link->replay_settings.replay_feature_enabled)
592 		return;
593 
594 	mod_power_replay_set_general_cmd(mod_power, stream,
595 		REPLAY_GENERAL_CMD_SET_CONTINUOUSLY_RESYNC,
596 		enable, 0);
597 }
598 
599 void mod_power_set_live_capture_with_cvt_activate(struct mod_power *mod_power,
600 	const struct dc_stream_state *stream, bool live_capture_with_cvt_activate)
601 {
602 	struct dc_link *link = NULL;
603 
604 	if (mod_power == NULL || stream == NULL)
605 		return;
606 
607 	link = dc_stream_get_link(stream);
608 	if (!link || !link->replay_settings.replay_feature_enabled)
609 		return;
610 
611 	// Check if LIVE_CAPTURE_WITH_CVT bit is enabled in replay optimization config
612 	if (!link->replay_settings.config.replay_optimization.bits.LIVE_CAPTURE_WITH_CVT)
613 		return;
614 
615 	if (link->replay_settings.config.live_capture_with_cvt_activated != live_capture_with_cvt_activate) {
616 		link->replay_settings.config.live_capture_with_cvt_activated = live_capture_with_cvt_activate;
617 		mod_power_replay_set_general_cmd(mod_power, stream,
618 			REPLAY_GENERAL_CMD_LIVE_CAPTURE_WITH_CVT,
619 			live_capture_with_cvt_activate, 0);
620 	}
621 }
622 
623 bool mod_power_set_replay_event(struct mod_power *mod_power,
624 	struct dc_stream_state *stream, bool set_event,
625 	enum replay_event event, bool wait_for_disable)
626 {
627 	struct core_power *core_power = NULL;
628 	struct dc_link *link = NULL;
629 	unsigned int stream_index = 0;
630 	unsigned int active_replay_events = 0;
631 	bool replay_active_request = false;
632 	bool force_static = false;
633 	uint32_t coasting_vtotal = 0;
634 	bool current_timing_sync_status = false;
635 	bool is_full_screen_video = false;
636 	bool is_ultra_sleep_mode = false;
637 	unsigned int sink_duration_us = 0;
638 	bool low_rr_active = false;
639 	uint16_t frame_skip_number = 0;
640 	bool is_video_playback = false;
641 
642 	if (!stream)
643 		return false;
644 
645 	if (mod_power == NULL)
646 		return false;
647 
648 	core_power = MOD_POWER_TO_CORE(mod_power);
649 
650 	if (core_power->num_entities == 0)
651 		return false;
652 
653 	stream_index = map_index_from_stream(core_power, stream);
654 
655 	if (set_event)
656 		core_power->map[stream_index].replay_events |= event;
657 	else
658 		core_power->map[stream_index].replay_events &= ~event;
659 
660 	link = dc_stream_get_link(stream);
661 	if (!link || !link->replay_settings.replay_feature_enabled)
662 		return false;
663 
664 	if ((core_power->map[stream_index].replay_events & replay_event_disable_replay_while_switching_mux) != 0)
665 		return false;
666 
667 	if ((core_power->map[stream_index].replay_events & replay_event_os_override_hold) != 0)
668 		return false;
669 
670 	active_replay_events = core_power->map[stream_index].replay_events;
671 
672 	current_timing_sync_status =
673 		link->replay_settings.config.replay_timing_sync_supported;
674 
675 	replay_active_request = mod_power_update_replay_active_status(active_replay_events,
676 		link, &coasting_vtotal, &is_full_screen_video, &is_ultra_sleep_mode, &frame_skip_number, &is_video_playback);
677 
678 	if (is_full_screen_video)
679 		mod_power_replay_set_pseudo_vtotal(mod_power, stream,
680 			link->replay_settings.low_rr_full_screen_video_pseudo_vtotal);
681 	else
682 		mod_power_replay_set_pseudo_vtotal(mod_power, stream, 0);
683 
684 	//If timing_sync_status change, then re-enabled set timing_sync_supported value and re-enabled replay
685 	if (current_timing_sync_status != link->replay_settings.config.replay_timing_sync_supported)
686 		mod_power_replay_set_timing_sync_supported(mod_power, stream);
687 
688 	if (link->replay_settings.config.low_rr_supported) {
689 		sink_duration_us =
690 			(unsigned int)(div_u64(((unsigned long long)(coasting_vtotal)
691 				* 10000) * stream->timing.h_total,
692 					stream->timing.pix_clk_100hz));
693 		low_rr_active = sink_duration_us < LOW_REFRESH_RATE_DURATION_US_UPPER_BOUND ? false : true;
694 		if (low_rr_active != link->replay_settings.config.low_rr_activated) {
695 			mod_power_set_low_rr_activate(mod_power, stream, low_rr_active);
696 			link->replay_settings.config.low_rr_activated = low_rr_active;
697 		}
698 	}
699 
700 	// The function return fail when
701 	// 1. DMUB function is not support (for backward compatible).
702 	// 2. active_replay_events or coasting_vtotal is not updated in the same time
703 	if (!mod_power_replay_set_power_opt_and_coasting_vtotal(mod_power,
704 		stream, active_replay_events, coasting_vtotal, is_ultra_sleep_mode, frame_skip_number)) {
705 		if (!mod_power_replay_set_power_opt(mod_power, stream, active_replay_events, is_ultra_sleep_mode))
706 			return false;
707 
708 		if (!mod_power_replay_set_coasting_vtotal(mod_power, stream, coasting_vtotal, frame_skip_number))
709 			return false;
710 	}
711 
712 	mod_power_set_live_capture_with_cvt_activate(mod_power, stream, is_video_playback);
713 
714 	mod_power_update_error_status(mod_power, stream);
715 
716 	// If Replay is going to be enable (No matter is disable -> enable or enable -> enable), we don't need to wait.
717 	// If Replay is going to be disable
718 	//     if disable -> disable
719 	//         -> Replay DMUB state should be state 0.
720 	//            So no matter wait_for_disable is true or not, it should makes no difference.
721 	//     if enable -> disable -> We should wait if wait_for_disable is true.
722 	if (replay_active_request)
723 		wait_for_disable = false;
724 
725 	if (!mod_power_set_replay_active(stream, replay_active_request, wait_for_disable, force_static))
726 		return false;
727 
728 	return true;
729 }
730 
731 bool mod_power_get_replay_active_status(const struct dc_stream_state *stream,
732 	bool *replay_active)
733 {
734 	const struct dc_link *link = NULL;
735 
736 	if (!stream)
737 		return false;
738 
739 	link = dc_stream_get_link(stream);
740 	*replay_active = link->replay_settings.replay_allow_active;
741 
742 	return true;
743 }
744 
745 void mod_power_replay_residency(const struct dc_stream_state *stream,
746 	unsigned int *residency, const bool is_start, const bool is_alpm)
747 {
748 	const struct dc_link *link = NULL;
749 	enum pr_residency_mode mode;
750 
751 	if (!stream)
752 		return;
753 
754 	link = dc_stream_get_link(stream);
755 
756 	if (is_alpm)
757 		mode = PR_RESIDENCY_MODE_ALPM;
758 	else
759 		mode = PR_RESIDENCY_MODE_PHY;
760 
761 	if (link && link->dc && link->dc->link_srv)
762 		link->dc->link_srv->edp_replay_residency(link, residency, is_start, mode);
763 }
764 
765 bool mod_power_replay_set_power_opt_and_coasting_vtotal(struct mod_power *mod_power,
766 	const struct dc_stream_state *stream, unsigned int active_replay_events, uint32_t coasting_vtotal,
767 	bool is_ultra_sleep_mode, uint16_t frame_skip_number)
768 {
769 	struct core_power *core_power = NULL;
770 	struct dc_link *link = NULL;
771 	unsigned int power_opt = 0;
772 
773 	if (!stream)
774 		return false;
775 
776 	if (mod_power == NULL)
777 		return false;
778 
779 	core_power = MOD_POWER_TO_CORE(mod_power);
780 
781 	if (core_power->num_entities == 0)
782 		return false;
783 
784 	link = dc_stream_get_link(stream);
785 
786 	if (!link || !link->replay_settings.replay_feature_enabled)
787 		return false;
788 
789 	power_opt = mod_power_replay_setup_power_opt(link, active_replay_events, is_ultra_sleep_mode);
790 
791 	return link->dc->link_srv->edp_set_replay_power_opt_and_coasting_vtotal(link, &power_opt, coasting_vtotal, frame_skip_number);
792 }
793 
794 void mod_power_replay_notify_mode_change(struct mod_power *mod_power,
795 	struct dc *dc,
796 	struct dc_link *link,
797 	const struct dc_stream_state *stream,
798 	unsigned int stream_index)
799 {
800 	struct core_power *core_power = NULL;
801 	int active_replay_events = 0;
802 
803 	if (!mod_power || !dc || !link || !stream)
804 		return;
805 
806 	core_power = MOD_POWER_TO_CORE(mod_power);
807 	active_replay_events = core_power->map[stream_index].replay_events;
808 
809 	link->replay_settings.replay_smu_opt_enable =
810 		(link->replay_settings.config.replay_smu_opt_supported &&
811 		mod_power_only_edp(dc->current_state, stream));
812 
813 	if (active_replay_events & replay_event_os_request_force_ffu) {
814 		link->replay_settings.config.os_request_force_ffu = true;
815 	}
816 
817 	if (dc_is_embedded_signal(stream->signal))
818 		dc->link_srv->dp_setup_replay(link, stream);
819 }
820 
821 void init_replay_config(struct dc_link *link, struct replay_config *pr_config)
822 {
823 	link->replay_settings.config = *pr_config;
824 }
825 
826 void set_replay_frame_skip_number(struct dc_link *link,
827 	enum replay_coasting_vtotal_type type,
828 	uint32_t coasting_vtotal_refresh_rate_uhz,
829 	uint32_t flicker_free_refresh_rate_uhz,
830 	bool is_defer)
831 {
832 	uint32_t *frame_skip_number_array = NULL;
833 	uint32_t frame_skip_number = 0;
834 
835 	if (link == NULL)
836 		return;
837 
838 	if (link->replay_settings.config.frame_skip_supported == false)
839 		return;
840 
841 	if (flicker_free_refresh_rate_uhz == 0 || coasting_vtotal_refresh_rate_uhz == 0)
842 		return;
843 
844 	if (is_defer)
845 		frame_skip_number_array = link->replay_settings.defer_frame_skip_number_table;
846 	else
847 		frame_skip_number_array = link->replay_settings.frame_skip_number_table;
848 
849 	if (frame_skip_number_array == NULL)
850 		return;
851 
852 	frame_skip_number = (coasting_vtotal_refresh_rate_uhz + 500000) / flicker_free_refresh_rate_uhz;
853 
854 	if (frame_skip_number >= 1)
855 		frame_skip_number_array[type] = frame_skip_number - 1;
856 	else
857 		frame_skip_number_array[type] = 0;
858 }
859 
860 void set_replay_defer_update_coasting_vtotal(struct dc_link *link,
861 	enum replay_coasting_vtotal_type type,
862 	uint32_t vtotal)
863 {
864 	link->replay_settings.defer_update_coasting_vtotal_table[type] = vtotal;
865 }
866 
867 void update_replay_coasting_vtotal_from_defer(struct dc_link *link,
868 	enum replay_coasting_vtotal_type type)
869 {
870 	link->replay_settings.coasting_vtotal_table[type] =
871 		link->replay_settings.defer_update_coasting_vtotal_table[type];
872 	link->replay_settings.frame_skip_number_table[type] =
873 		link->replay_settings.defer_frame_skip_number_table[type];
874 }
875 
876 void set_replay_coasting_vtotal(struct dc_link *link,
877 	enum replay_coasting_vtotal_type type,
878 	uint32_t vtotal)
879 {
880 	link->replay_settings.coasting_vtotal_table[type] = vtotal;
881 }
882 
883 void set_replay_low_rr_full_screen_video_src_vtotal(struct dc_link *link, uint16_t vtotal)
884 {
885 	link->replay_settings.low_rr_full_screen_video_pseudo_vtotal = vtotal;
886 }
887 
888 void calculate_replay_link_off_frame_count(struct dc_link *link,
889 	uint16_t vtotal, uint16_t htotal)
890 {
891 	uint32_t max_link_off_frame_count = 0;
892 	uint16_t max_deviation_line = 0,  pixel_deviation_per_line = 0;
893 
894 	if (!link || link->replay_settings.config.replay_version != DC_FREESYNC_REPLAY)
895 		return;
896 
897 	max_deviation_line = link->dpcd_caps.pr_info.max_deviation_line;
898 	pixel_deviation_per_line = link->dpcd_caps.pr_info.pixel_deviation_per_line;
899 
900 	if (htotal != 0 && vtotal != 0 && pixel_deviation_per_line != 0)
901 		max_link_off_frame_count = htotal * max_deviation_line / (pixel_deviation_per_line * vtotal);
902 	else
903 		ASSERT(0);
904 
905 	link->replay_settings.link_off_frame_count = max_link_off_frame_count;
906 }
907 
908 void reset_replay_dsync_error_count(struct dc_link *link)
909 {
910 	link->replay_settings.replay_desync_error_fail_count = 0;
911 }
912