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