xref: /linux/drivers/gpu/drm/amd/display/modules/power/power.c (revision 55e69772bd70fff0cb44d7686211137bb57ab7f3)
1 /*
2  * Copyright 2016 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: AMD
23  *
24  */
25 
26 #include "dm_services.h"
27 #include "dc.h"
28 #include "mod_power.h"
29 #include "core_types.h"
30 #include "dmcu.h"
31 #include "abm.h"
32 #include "power_helpers.h"
33 #include "dce/dmub_psr.h"
34 #include "dal_asic_id.h"
35 #include "link_service.h"
36 #include <linux/math.h>
37 
38 #define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */
39 #define DC_TRACE_LEVEL_MESSAGEP(...) /* do nothing */
40 
41 #define MOD_POWER_MAX_CONCURRENT_STREAMS 32
42 #define SMOOTH_BRIGHTNESS_ADJUSTMENT_TIME_IN_MS 500
43 #define LOW_REFRESH_RATE_DURATION_US_UPPER_BOUND 25000
44 
45 /* If system or panel does not report some sort of brightness percent to nits
46  * mapping, we will use following default values so backlight control using
47  * nits based interfaces will still work, but might not describe panel
48  * correctly. In this case percentage based backlight control should ideally
49  * be used.
50  * Min = 5 nits
51  * Max = 300 nits
52  */
53 
54 static const unsigned int pwr_default_min_brightness_millinits = 1000;
55 static const unsigned int pwr_default_sdr_brightness_millinits = 270000;
56 
57 static const unsigned int default_ac_backlight_percent   = 100;
58 static const unsigned int default_dc_backlight_percent   = 70;
59 
60 #define MOD_POWER_TO_CORE(mod_power)\
61 		container_of(mod_power, struct core_power, mod_public)
62 
63 /* Given a specific dc_stream* this function finds its equivalent
64  * on the core_freesync->map and returns the corresponding index
65  */
66 unsigned int map_index_from_stream(struct core_power *core_power,
67 		const struct dc_stream_state *stream)
68 {
69 	unsigned int index = 0;
70 
71 	for (index = 0; index < core_power->num_entities; index++) {
72 		if (core_power->map[index].stream == stream)
73 			return index;
74 	}
75 	/* Could not find stream requested, this is not trivial, fix when hit*/
76 	DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
77 						WPP_BIT_FLAG_Firmware_PsrState,
78 						"map index from stream: ERROR: core_power=%p stream=%p",
79 						core_power,
80 						stream);
81 	ASSERT(false);
82 	/* We come here only when we can't map stream index.
83 	 * In good cases, this would happen when we attempt to change
84 	 * brightness before stream creation, in which case we create a
85 	 * dummy stream with index 0.
86 	 * With external monitor connected, the index passed from this return
87 	 * is 1. Passing anything greater than 0 from here would always point
88 	 * to bad memory.
89 	 */
90 	return 0;
91 }
92 
93 bool mod_power_hw_init(struct mod_power *mod_power)
94 {
95 	/* Call backlight initialization */
96 	return mod_power_hw_init_backlight(mod_power);
97 
98 	/* Future: Add other HW init here */
99 }
100 
101 struct mod_power *mod_power_create(struct dc *dc,
102 		struct mod_power_init_params *init_params,
103 		unsigned int edp_num)
104 {
105 	struct core_power *core_power = NULL;
106 	int i = 0;
107 	unsigned int abm_max_config = 0;
108 	unsigned int inst = 0;
109 	bool is_brightness_range_valid = false;
110 
111 	if (dc == NULL)
112 		goto fail_dc_null;
113 
114 	core_power = kzalloc(sizeof(struct core_power), GFP_KERNEL);
115 
116 	if (core_power == NULL)
117 		goto fail_alloc_context;
118 
119 	core_power->edp_num = edp_num;
120 	core_power->map = kzalloc(sizeof(struct power_entity) * MOD_POWER_MAX_CONCURRENT_STREAMS,
121 				  GFP_KERNEL);
122 
123 	if (core_power->map == NULL)
124 		goto fail_alloc_map;
125 
126 	for (i = 0; i < MOD_POWER_MAX_CONCURRENT_STREAMS; i++) {
127 		core_power->map[i].stream = NULL;
128 	}
129 
130 	for (i = 0; i < MOD_POWER_MAX_CONCURRENT_STREAMS; i++) {
131 		core_power->map[i].psr_context =
132 				kzalloc(sizeof(struct mod_power_psr_context),
133 					GFP_KERNEL);
134 		if (core_power->map[i].psr_context == NULL)
135 			goto fail_construct;
136 	}
137 
138 	core_power->psr_smu_optimizations_support = init_params->allow_psr_smu_optimizations;
139 	core_power->multi_disp_optimizations_support = init_params->allow_psr_multi_disp_optimizations;
140 
141 	for (inst = 0; inst < edp_num; inst++) {
142 		core_power->bl_prop[inst].min_abm_backlight =
143 				init_params[inst].min_abm_backlight;
144 		core_power->bl_prop[inst].disable_fractional_pwm =
145 				init_params[inst].disable_fractional_pwm;
146 		core_power->bl_prop[inst].use_linear_backlight_curve =
147 				init_params[inst].use_linear_backlight_curve;
148 		core_power->bl_prop[inst].use_nits_based_brightness =
149 				init_params[inst].use_nits_based_brightness;
150 		core_power->bl_prop[inst].backlight_ramping_override =
151 				init_params[inst].backlight_ramping_override;
152 		core_power->bl_prop[inst].backlight_ramping_reduction =
153 				init_params[inst].backlight_ramping_reduction;
154 		core_power->bl_prop[inst].backlight_ramping_start =
155 				init_params[inst].backlight_ramping_start;
156 		core_power->bl_prop[inst].use_custom_backlight_caps =
157 				init_params[inst].use_custom_backlight_caps;
158 		core_power->bl_prop[inst].custom_backlight_caps_config_no =
159 				init_params[inst].custom_backlight_caps_config_no;
160 
161 		// Do not allow less than 101 backlight levels
162 		if (init_params[inst].num_backlight_levels < 101)
163 			core_power->bl_prop[inst].num_backlight_levels = 101;
164 		else
165 			core_power->bl_prop[inst].num_backlight_levels =
166 				init_params[inst].num_backlight_levels;
167 
168 		core_power->bl_prop[inst].backlight_lut = (unsigned int *)
169 				(kzalloc(sizeof(unsigned int) *
170 				core_power->bl_prop[inst].num_backlight_levels, GFP_KERNEL));
171 		if (core_power->bl_prop[inst].backlight_lut == NULL)
172 			goto fail_alloc_backlight_array;
173 	}
174 
175 	core_power->varibright_prop.varibright_active = false;
176 
177 	core_power->varibright_prop.varibright_user_enable =
178 			init_params->def_varibright_enable;
179 
180 	// Table of ABM levels here is 1-4, but level 0 also exists as 'off'
181 	if (init_params->varibright_level <= abm_defines_max_level) {
182 		core_power->varibright_prop.varibright_level =
183 			init_params->varibright_level;
184 
185 	} else {
186 		core_power->varibright_prop.varibright_level = 3;
187 	}
188 	if (init_params->def_varibright_level <= abm_defines_max_level) {
189 		core_power->varibright_prop.def_varibright_level =
190 			init_params->def_varibright_level;
191 	} else {
192 		core_power->varibright_prop.def_varibright_level = 3;
193 	}
194 
195 	// ABM used to contain 4 different configs. There is only 3 since ABM 2.3.
196 	if ((dc->res_pool->dmcu != NULL) && (dc->res_pool->dmcu->dmcu_version.abm_version < 0x23))
197 		abm_max_config = 4;
198 	else
199 		abm_max_config = 3;
200 
201 	if (init_params->abm_config_setting < abm_max_config)
202 		core_power->varibright_prop.varibright_config_setting =
203 			init_params->abm_config_setting;
204 	else
205 		core_power->varibright_prop.varibright_config_setting = 0;
206 
207 	for (inst = 0; inst < edp_num; inst++) {
208 		core_power->bl_prop[inst].backlight_lut[0] = init_params[inst].min_backlight_pwm;
209 		core_power->bl_prop[inst].backlight_lut[
210 			core_power->bl_prop[inst].num_backlight_levels-1] =
211 				init_params[inst].max_backlight_pwm;
212 		core_power->bl_prop[inst].min_backlight_pwm = init_params[inst].min_backlight_pwm;
213 		core_power->bl_prop[inst].max_backlight_pwm = init_params[inst].max_backlight_pwm;
214 		core_power->bl_prop[inst].ac_backlight_percent =
215 				default_ac_backlight_percent;
216 		core_power->bl_prop[inst].dc_backlight_percent =
217 				default_dc_backlight_percent;
218 		core_power->bl_prop[inst].backlight_caps_valid = false;
219 
220 		if (core_power->bl_prop[inst].use_nits_based_brightness) {
221 			core_power->bl_prop[inst].min_brightness_millinits =
222 					init_params[inst].panel_min_millinits;
223 			core_power->bl_prop[inst].max_brightness_millinits =
224 					init_params[inst].panel_max_millinits;
225 		} else {
226 
227 			core_power->bl_prop[inst].min_brightness_millinits =
228 					pwr_default_min_brightness_millinits;
229 			core_power->bl_prop[inst].max_brightness_millinits =
230 					pwr_default_sdr_brightness_millinits;
231 		}
232 
233 		core_power->bl_prop[inst].backlight_range =
234 				core_power->bl_prop[inst].max_backlight_pwm-
235 				core_power->bl_prop[inst].min_backlight_pwm;
236 
237 		core_power->bl_prop[inst].nits_range =
238 				core_power->bl_prop[inst].max_brightness_millinits -
239 				core_power->bl_prop[inst].min_brightness_millinits;
240 
241 		core_power->bl_state[inst].smooth_brightness_enabled = true;
242 	}
243 
244 	/* Check if at least 1 instance in core_power is populated before failing */
245 	for (inst = 0; inst < edp_num; inst++) {
246 		if (core_power->bl_prop[inst].nits_range != 0 && core_power->bl_prop[inst].backlight_range != 0) {
247 			is_brightness_range_valid = true;
248 			break;
249 		}
250 
251 	}
252 	if (!is_brightness_range_valid)
253 		goto fail_bad_brightness_range;
254 
255 	core_power->num_entities = 0;
256 
257 	core_power->dc = dc;
258 	for (inst = 0; inst < edp_num; inst++) {
259 		initialize_backlight_caps(core_power, inst);
260 		core_power->bl_state[inst].backlight_millipercent =
261 			core_power->bl_prop[inst].dc_backlight_percent * 1000;
262 		core_power->bl_state[inst].backlight_pwm = backlight_millipercent_to_pwm(core_power,
263 		core_power->bl_state[inst].backlight_millipercent, inst);
264 		core_power->bl_state[inst].backlight_millinit = backlight_millipercent_to_millinit(core_power,
265 		core_power->bl_state[inst].backlight_millipercent, inst);
266 	}
267 
268 	return &core_power->mod_public;
269 
270 fail_bad_brightness_range:
271 fail_alloc_backlight_array:
272 	for (inst = 0; inst < edp_num; inst++)
273 		if (core_power->bl_prop[inst].backlight_lut)
274 			kfree(core_power->bl_prop[inst].backlight_lut);
275 fail_construct:
276 	for (i = 0; i < MOD_POWER_MAX_CONCURRENT_STREAMS; i++) {
277 		if (core_power->map[i].psr_context)
278 			kfree(core_power->map[i].psr_context);
279 	}
280 	kfree(core_power->map);
281 
282 fail_alloc_map:
283 	kfree(core_power);
284 
285 fail_alloc_context:
286 fail_dc_null:
287 	return NULL;
288 }
289 
290 void mod_power_destroy(struct mod_power *mod_power)
291 {
292 	if (mod_power != NULL) {
293 		unsigned int i;
294 		struct core_power *core_power =
295 				MOD_POWER_TO_CORE(mod_power);
296 
297 		for (i = 0; i < MOD_POWER_MAX_CONCURRENT_STREAMS; i++)
298 			if (core_power->map[i].psr_context)
299 				kfree(core_power->map[i].psr_context);
300 
301 		for (i = 0; i < core_power->num_entities; i++)
302 			if (core_power->map[i].stream)
303 				dc_stream_release(core_power->map[i].stream);
304 
305 		kfree(core_power->map);
306 
307 		for (i = 0; i < MAX_NUM_EDP; i++)
308 			if (core_power->bl_prop[i].backlight_lut)
309 				kfree(core_power->bl_prop[i].backlight_lut);
310 
311 		kfree(core_power);
312 	}
313 }
314 
315 bool mod_power_add_stream(struct mod_power *mod_power,
316 		struct dc_stream_state *stream, struct psr_caps *caps)
317 {
318 	struct core_power *core_power = NULL;
319 
320 	if (mod_power == NULL)
321 		return false;
322 
323 	core_power = MOD_POWER_TO_CORE(mod_power);
324 
325 	if (core_power->num_entities < MOD_POWER_MAX_CONCURRENT_STREAMS) {
326 		dc_stream_retain(stream);
327 
328 		core_power->map[core_power->num_entities].stream = stream;
329 		core_power->map[core_power->num_entities].caps = caps;
330 
331 		// initialize cached PSR params to something "safe" (something that is
332 		// consistent with disabled PSR state)
333 		core_power->map[core_power->num_entities].psr_enabled = 0;
334 		core_power->map[core_power->num_entities].psr_events = psr_event_vsync;
335 		core_power->map[core_power->num_entities].psr_power_opt = 0;
336 		core_power->num_entities++;
337 		return true;
338 	}
339 
340 	DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
341 						WPP_BIT_FLAG_Firmware_PsrState,
342 						"mod_power: add_stream: ERROR: stream=%p num_entities=%u >= MOD_POWER_MAX_CONCURRENT_STREAMS",
343 						stream,
344 						core_power->num_entities);
345 
346 	return false;
347 }
348 
349 bool mod_power_remove_stream(struct mod_power *mod_power,
350 		const struct dc_stream_state *stream)
351 {
352 	unsigned int i = 0;
353 	struct core_power *core_power = NULL;
354 	unsigned int index = 0;
355 
356 	if (mod_power == NULL)
357 		return false;
358 
359 	core_power = MOD_POWER_TO_CORE(mod_power);
360 	if (core_power->num_entities == 0) {
361 		/* trying to remove a stream a second time or have not added yet */
362 		BREAK_TO_DEBUGGER();
363 		DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
364 							WPP_BIT_FLAG_Firmware_PsrState,
365 							"mod_power: remove_stream: ERROR: num_entities=0 stream=%p",
366 							stream);
367 		return false;
368 	}
369 
370 	index = map_index_from_stream(core_power, stream);
371 
372 	if (index >= core_power->num_entities) {
373 		/* trying to remove a stream a second time or have not added yet */
374 		BREAK_TO_DEBUGGER();
375 		DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
376 							WPP_BIT_FLAG_Firmware_PsrState,
377 							"mod_power: remove_stream: ERROR: index=%u >= num_entities=%u stream=%p",
378 							index,
379 							core_power->num_entities,
380 							stream);
381 		return false;
382 	}
383 
384 	dc_stream_release(core_power->map[index].stream);
385 	core_power->map[index].stream = NULL;
386 	/* To remove this entity, shift everything after down */
387 	for (i = index; i < core_power->num_entities - 1; i++) {
388 		core_power->map[i].stream = core_power->map[i + 1].stream;
389 		core_power->map[i].caps = core_power->map[i + 1].caps;
390 
391 		// copy over cached parameters in case they map to PSR capable display
392 		core_power->map[i].psr_enabled = core_power->map[i + 1].psr_enabled;
393 		core_power->map[i].psr_events = core_power->map[i + 1].psr_events;
394 		core_power->map[i].psr_power_opt = core_power->map[i + 1].psr_power_opt;
395 
396 		memcpy(core_power->map[i].psr_context, core_power->map[i + 1].psr_context, sizeof(struct mod_power_psr_context));
397 		memset(core_power->map[i + 1].psr_context, 0, sizeof(struct mod_power_psr_context));
398 	}
399 	core_power->num_entities--;
400 
401 	return true;
402 }
403 
404 /*
405  * Replace_stream should be used when there is a mode set for existing
406  * display target with a valid stream. In this case might need to retain
407  * cached PSR state (events, power opt, en/dis) if we are dealing with PSR
408  * capable display. If mod_power_remove and mod_power_add are used instead,
409  * then stream may be assigned to a different slot and may end up with
410  * wrong cached PSR state. It is hard to tell which PSR events should
411  * persist through mode set or what psr_events should be initialized to, so
412  * it might be better just to retain them all.
413  */
414 bool mod_power_replace_stream(struct mod_power *mod_power,
415 		const struct dc_stream_state *current_stream,
416 		struct dc_stream_state *new_stream,
417 		struct psr_caps *new_caps)
418 {
419 	struct core_power *core_power = NULL;
420 	unsigned int index = 0;
421 
422 	if (mod_power == NULL)
423 		return false;
424 
425 	core_power = MOD_POWER_TO_CORE(mod_power);
426 	if (core_power->num_entities == 0) {
427 		/* no streams exist in the table yet */
428 		BREAK_TO_DEBUGGER();
429 		DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
430 							WPP_BIT_FLAG_Firmware_PsrState,
431 							"mod_power: replace_stream: ERROR: num_entities=0 stream=%p",
432 							current_stream);
433 		return false;
434 	}
435 
436 	index = map_index_from_stream(core_power, current_stream);
437 
438 	if (index >= core_power->num_entities) {
439 		/* trying to replace a non-existent stream */
440 		BREAK_TO_DEBUGGER();
441 		DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
442 							WPP_BIT_FLAG_Firmware_PsrState,
443 							"mod_power: replace_stream: ERROR: index=%u >= num_entities=%u stream=%p",
444 							index,
445 							core_power->num_entities,
446 							current_stream);
447 		return false;
448 	}
449 
450 	dc_stream_release(core_power->map[index].stream);
451 	dc_stream_retain(new_stream);
452 	core_power->map[index].stream = new_stream;
453 	core_power->map[index].caps = new_caps;
454 	memset(core_power->map[index].psr_context, 0, sizeof(struct mod_power_psr_context));
455 
456 	return true;
457 }
458 
459 bool mod_power_notify_mode_change(struct mod_power *mod_power,
460 		const struct dc_stream_state *stream,
461 		bool is_hdr)
462 {
463 	unsigned int stream_index = 0;
464 	struct core_power *core_power = NULL;
465 	struct dc_link *link = NULL;
466 	struct dc *dc = NULL;
467 	unsigned int panel_inst = 0;
468 	int active_replay_events = 0;
469 
470 	if ((mod_power == NULL) || (stream == NULL))
471 		return false;
472 
473 	core_power = MOD_POWER_TO_CORE(mod_power);
474 
475 	if (core_power->num_entities == 0)
476 		return false;
477 
478 	stream_index = map_index_from_stream(core_power, stream);
479 
480 	if (stream_index >= core_power->num_entities)
481 		return false;
482 
483 	dc = core_power->dc;
484 	link = dc_stream_get_link(stream);
485 	active_replay_events = core_power->map[stream_index].replay_events;
486 	if (link != NULL && dc_get_edp_link_panel_inst(dc, link, &panel_inst)) {
487 		ASSERT(link->ddc->ddc_pin->hw_info.ddc_channel <= 0xFF);
488 		uint8_t aux_inst = (uint8_t)link->ddc->ddc_pin->hw_info.ddc_channel;
489 
490 		mod_power_update_backlight_on_mode_change(core_power, link, panel_inst, aux_inst, is_hdr);
491 
492 		/* Handle PSR notification */
493 		mod_power_psr_notify_mode_change(mod_power, stream, link, stream_index);
494 
495 		link->replay_settings.replay_smu_opt_enable =
496 			(link->replay_settings.config.replay_smu_opt_supported &&
497 			mod_power_only_edp(dc->current_state, stream));
498 
499 		if (active_replay_events & replay_event_os_request_force_ffu) {
500 			link->replay_settings.config.os_request_force_ffu = true;
501 		}
502 
503 		if (dc_is_embedded_signal(stream->signal))
504 			dc->link_srv->dp_setup_replay(link, stream);
505 	}
506 
507 	return true;
508 }
509 
510 static bool mod_power_set_replay_active(struct dc_stream_state *stream,
511 	bool replay_active,
512 	bool wait,
513 	bool force_static)
514 {
515 	uint64_t state;
516 	unsigned int retry_count;
517 	const unsigned int max_retry = 1000;
518 	struct dc_link *link = NULL;
519 
520 	if (!stream)
521 		return false;
522 
523 	link = dc_stream_get_link(stream);
524 
525 	if (!link)
526 		return false;
527 
528 	if (!dc_link_set_replay_allow_active(link, &replay_active, false, force_static, NULL))
529 		return false;
530 
531 	if (wait == true) {
532 
533 		for (retry_count = 0; retry_count <= max_retry; retry_count++) {
534 			dc_link_get_replay_state(link, &state);
535 			if (replay_active) {
536 				if (state != REPLAY_STATE_0 &&
537 					(!force_static || state == REPLAY_STATE_3))
538 					break;
539 			} else {
540 				if (state == REPLAY_STATE_0)
541 					break;
542 			}
543 			udelay(500);
544 		}
545 
546 		/* assert if max retry hit */
547 		if (retry_count >= max_retry)
548 			ASSERT(0);
549 	} else {
550 		/* To-do: Add trace log */
551 	}
552 
553 	return true;
554 }
555 
556 static unsigned int mod_power_replay_setup_power_opt(struct dc_link *link,
557 	unsigned int active_replay_events, bool is_ultra_sleep_mode)
558 {
559 	unsigned int power_opt = 0;
560 
561 	if (is_ultra_sleep_mode) {
562 		/* Static Screen */
563 		power_opt |= (replay_power_opt_smu_opt_static_screen | replay_power_opt_z10_static_screen);
564 	} else if (active_replay_events & replay_event_test_harness_ultra_sleep) {
565 		power_opt |= replay_power_opt_z10_static_screen;
566 	}
567 
568 	/* replay_power_opt_flag is a configuration parameter into the module that determines
569 	 * which optimizations to enable during replay
570 	 */
571 	power_opt &= link->replay_settings.config.replay_power_opt_supported;
572 
573 	return power_opt;
574 }
575 
576 static bool mod_power_replay_set_power_opt(struct mod_power *mod_power,
577 	struct dc_stream_state *stream,
578 	unsigned int active_replay_events,
579 	bool is_ultra_sleep_mode)
580 {
581 	(void)mod_power;
582 	struct dc_link *link = NULL;
583 	unsigned int power_opt = 0;
584 
585 	if (!stream)
586 		return false;
587 
588 	link = dc_stream_get_link(stream);
589 
590 	if (!link || !link->replay_settings.replay_feature_enabled)
591 		return false;
592 
593 	power_opt = mod_power_replay_setup_power_opt(link, active_replay_events, is_ultra_sleep_mode);
594 
595 	if (!dc_link_set_replay_allow_active(link, NULL, false, false, &power_opt))
596 		return false;
597 
598 	return true;
599 }
600 
601 bool mod_power_get_replay_event(struct mod_power *mod_power,
602 	struct dc_stream_state *stream,
603 	unsigned int *active_replay_events)
604 {
605 	struct core_power *core_power = NULL;
606 	unsigned int stream_index = 0;
607 
608 	if (mod_power == NULL)
609 		return false;
610 
611 	core_power = MOD_POWER_TO_CORE(mod_power);
612 
613 	if (core_power->num_entities == 0)
614 		return false;
615 
616 	stream_index = map_index_from_stream(core_power, stream);
617 
618 	*active_replay_events = core_power->map[stream_index].replay_events;
619 
620 	return true;
621 }
622 
623 static bool mod_power_update_replay_active_status(unsigned int active_replay_events,
624 	struct dc_link *link, uint32_t *coasting_vtotal, bool *is_full_screen_video, bool *is_ultra_sleep_mode, uint16_t *frame_skip_number, bool *is_video_playback)
625 {
626 	if (!link || !coasting_vtotal || !is_full_screen_video || !is_video_playback)
627 		return false;
628 
629 	// Check coasting_vtotal_table has been updated.
630 	if (!link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_STATIC]
631 		|| !link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_NOM])
632 		return false;
633 
634 	unsigned int replay_enable_option =
635 		link->replay_settings.config.replay_enable_option;
636 
637 	/* TODO: To support test harness and DDS event */
638 
639 	*coasting_vtotal = link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_NOM];
640 	ASSERT(link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_NOM] <= 0xFFFF);
641 	*frame_skip_number = (uint16_t)link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_NOM];
642 
643 	link->replay_settings.config.replay_timing_sync_supported = false;
644 
645 	*is_full_screen_video = false;
646 
647 	*is_ultra_sleep_mode = false;
648 
649 	*is_video_playback = false;
650 
651 	/* DSAT test scenario */
652 	if (active_replay_events & replay_event_test_harness_mode) {
653 		if (link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS])
654 			*coasting_vtotal =
655 				link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS];
656 		if (link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS]) {
657 			ASSERT(link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS] <= 0xFFFF);
658 			*frame_skip_number =
659 				(uint16_t)link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS];
660 		}
661 
662 		/* During the ultra sleep mode testing, disable the timing sync in short vblank mode */
663 		if (active_replay_events & (replay_event_test_harness_enable_replay)) {
664 			if ((active_replay_events & replay_event_test_harness_ultra_sleep) &&
665 				  !link->replay_settings.config.replay_support_fast_resync_in_ultra_sleep_mode)
666 				link->replay_settings.config.replay_timing_sync_supported = false;
667 			return true;
668 		} else
669 			return false;
670 	} else if (active_replay_events & (replay_event_test_harness_enable_replay)) {
671 		if (link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS])
672 			*coasting_vtotal = link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS];
673 		if (link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS]) {
674 			uint32_t frame_skip_val =
675 				link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS];
676 
677 			ASSERT(frame_skip_val <= 0xFFFF);
678 			*frame_skip_number = (uint16_t)frame_skip_val;
679 		}
680 
681 		/* During the ultra sleep mode testing, disable the timing sync in short vblank mode */
682 		if ((active_replay_events & replay_event_test_harness_ultra_sleep) &&
683 			  !link->replay_settings.config.replay_support_fast_resync_in_ultra_sleep_mode)
684 			link->replay_settings.config.replay_timing_sync_supported = false;
685 		return true;
686 	} else if (active_replay_events & (replay_event_test_harness_disable_replay | replay_event_os_request_disable)) {
687 		// set last set coasting vtotal
688 		if (link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS])
689 			*coasting_vtotal = link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS];
690 		if (link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS]) {
691 			uint32_t frame_skip_val =
692 				link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS];
693 
694 			ASSERT(frame_skip_val <= 0xFFFF);
695 			*frame_skip_number = (uint16_t)frame_skip_val;
696 		}
697 		return false;
698 	}
699 
700 	/* Inactive conditions */
701 	if (active_replay_events & (replay_event_edp_panel_off_disable_psr |
702 			replay_event_hw_programming |
703 			replay_event_vrr |
704 			replay_event_immediate_flip |
705 			replay_event_prepare_vtotal |
706 			replay_event_vrr_transition |
707 			replay_event_pause |
708 			replay_event_disable_replay_while_DPMS |
709 			replay_event_sleep_resume |
710 			replay_event_disable_in_AC |
711 			replay_event_disable_replay_while_detect_display |
712 			replay_event_infopacket |
713 			replay_event_crc_window_active))
714 		return false;
715 
716 	// Full screen scenario
717 	if (active_replay_events & replay_event_full_screen) {
718 		if (!(replay_enable_option & pr_enable_option_full_screen))
719 			return false;
720 	}
721 
722 	/* Full screen video scenario */
723 	if (active_replay_events & replay_event_big_screen_video) {
724 
725 		link->replay_settings.config.replay_timing_sync_supported = false;
726 
727 		if (replay_enable_option & pr_enable_option_full_screen_video_coasting) {
728 			unsigned int fsn_vid =
729 				link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_FULL_SCREEN_VIDEO];
730 
731 			*coasting_vtotal =
732 				link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_FULL_SCREEN_VIDEO];
733 			ASSERT(fsn_vid <= 0xFFFF);
734 			*frame_skip_number = (uint16_t)fsn_vid;
735 		}
736 
737 		*is_video_playback = true;
738 
739 		if ((replay_enable_option & pr_enable_option_full_screen_video) &&
740 			(replay_enable_option & pr_enable_option_full_screen_video_coasting)) {
741 			*is_full_screen_video = true;
742 			return true;
743 		} else
744 			return false;
745 	}
746 
747 	/* MPO video scenario
748 	 * Some of the cases may contain a full screen UI layer in MPO video scenario which is
749 	 * not the expected case to enable Replay.
750 	 */
751 	if ((active_replay_events & replay_event_mpo_video_selective_update) &&
752 		!(active_replay_events & replay_event_full_screen)) {
753 
754 		link->replay_settings.config.replay_timing_sync_supported = false;
755 
756 		if (replay_enable_option & pr_enable_option_mpo_video_coasting) {
757 			*coasting_vtotal = link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_NOM];
758 			{
759 				uint32_t frame_skip_val =
760 					link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_NOM];
761 
762 				ASSERT(frame_skip_val <= 0xFFFF);
763 				*frame_skip_number = (uint16_t)frame_skip_val;
764 			}
765 		}
766 
767 		*is_video_playback = true;
768 
769 		if (replay_enable_option & pr_enable_option_mpo_video)
770 			return true;
771 		else
772 			return false;
773 	}
774 
775 	/* Static screen scenario */
776 	if (!(active_replay_events & replay_event_vsync)) {
777 
778 		if (replay_enable_option & pr_enable_option_static_screen_coasting) {
779 			// Do not adjust eDP refresh rate if static screen + normal sleep mode
780 			if ((!(link->replay_settings.config.replay_power_opt_supported &
781 				replay_power_opt_z10_static_screen)) ||
782 				(active_replay_events & replay_event_cursor_updating)) {
783 				// normal sleep mode
784 				*coasting_vtotal =
785 					link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_NOM];
786 				{
787 					uint32_t frame_skip_val =
788 						link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_NOM];
789 
790 					ASSERT(frame_skip_val <= 0xFFFF);
791 					*frame_skip_number = (uint16_t)frame_skip_val;
792 				}
793 			} else {
794 				// ultra sleep mode
795 				*coasting_vtotal =
796 					link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_STATIC];
797 				{
798 					uint32_t frame_skip_val =
799 						link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_STATIC];
800 
801 					ASSERT(frame_skip_val <= 0xFFFF);
802 					*frame_skip_number = (uint16_t)frame_skip_val;
803 				}
804 				*is_ultra_sleep_mode = true;
805 			}
806 		}
807 
808 		if (replay_enable_option & pr_enable_option_static_screen) {
809 			if (!link->replay_settings.config.replay_support_fast_resync_in_ultra_sleep_mode)
810 				link->replay_settings.config.replay_timing_sync_supported = false;
811 			return true;
812 		} else
813 			return false;
814 	}
815 
816 	/* General UI scenario */
817 	if (active_replay_events & replay_event_general_ui) {
818 		if (replay_enable_option & pr_enable_option_general_ui)
819 			return true;
820 		else
821 			return false;
822 	}
823 
824 	return false;
825 }
826 
827 bool mod_power_replay_set_coasting_vtotal(struct mod_power *mod_power,
828 	const struct dc_stream_state *stream,
829 	uint32_t coasting_vtotal,
830 	uint16_t frame_skip_number)
831 {
832 	struct core_power *core_power = NULL;
833 	struct dc_link *link = NULL;
834 
835 	if (!stream)
836 		return false;
837 
838 	link = dc_stream_get_link(stream);
839 	if (!link || !link->replay_settings.replay_feature_enabled)
840 		return false;
841 
842 	if (mod_power == NULL)
843 		return false;
844 
845 	core_power = MOD_POWER_TO_CORE(mod_power);
846 
847 	if (core_power->num_entities == 0)
848 		return false;
849 
850 	return link->dc->link_srv->edp_set_coasting_vtotal(link, coasting_vtotal, frame_skip_number);
851 }
852 
853 void mod_power_replay_set_timing_sync_supported(struct mod_power *mod_power,
854 	const struct dc_stream_state *stream)
855 {
856 	struct core_power *core_power = NULL;
857 	struct dc_link *link = NULL;
858 	unsigned int stream_index = 0;
859 	union dmub_replay_cmd_set cmd_data = { 0 };
860 
861 	if (!stream || mod_power == NULL)
862 		return;
863 
864 	core_power = MOD_POWER_TO_CORE(mod_power);
865 	if (core_power->num_entities == 0)
866 		return;
867 
868 	stream_index = map_index_from_stream(core_power, stream);
869 	if (stream_index > core_power->num_entities) //invalid index
870 		return;
871 
872 	link = dc_stream_get_link(stream);
873 	if (!link || !link->replay_settings.replay_feature_enabled)
874 		return;
875 
876 	cmd_data.sync_data.timing_sync_supported = link->replay_settings.config.replay_timing_sync_supported;
877 
878 	link->dc->link_srv->edp_send_replay_cmd(link, Replay_Set_Timing_Sync_Supported,
879 		&cmd_data);
880 }
881 
882 void mod_power_replay_disabled_adaptive_sync_sdp(struct mod_power *mod_power,
883 	const struct dc_stream_state *stream, bool force_disabled)
884 {
885 	struct core_power *core_power = NULL;
886 	struct dc_link *link = NULL;
887 	unsigned int stream_index = 0;
888 	union dmub_replay_cmd_set cmd_data = { 0 };
889 
890 	if (!stream || mod_power == NULL)
891 		return;
892 
893 	core_power = MOD_POWER_TO_CORE(mod_power);
894 	if (core_power->num_entities == 0)
895 		return;
896 
897 	stream_index = map_index_from_stream(core_power, stream);
898 	if (stream_index > core_power->num_entities) //invalid index
899 		return;
900 
901 	link = dc_stream_get_link(stream);
902 	if (!link || !link->replay_settings.replay_feature_enabled)
903 		return;
904 
905 	cmd_data.disabled_adaptive_sync_sdp_data.force_disabled = force_disabled;
906 
907 	link->dc->link_srv->edp_send_replay_cmd(link, Replay_Disabled_Adaptive_Sync_SDP,
908 		&cmd_data);
909 }
910 
911 static void mod_power_replay_set_general_cmd(struct mod_power *mod_power,
912 	const struct dc_stream_state *stream,
913 	const enum dmub_cmd_replay_general_subtype general_cmd_type,
914 	const uint32_t param1, const uint32_t param2)
915 {
916 	struct core_power *core_power = NULL;
917 	struct dc_link *link = NULL;
918 	unsigned int stream_index = 0;
919 	union dmub_replay_cmd_set cmd_data = { 0 };
920 
921 	if (!stream || mod_power == NULL)
922 		return;
923 
924 	core_power = MOD_POWER_TO_CORE(mod_power);
925 	if (core_power->num_entities == 0)
926 		return;
927 
928 	stream_index = map_index_from_stream(core_power, stream);
929 	if (stream_index > core_power->num_entities) //invalid index
930 		return;
931 
932 	link = dc_stream_get_link(stream);
933 	if (!link || !link->replay_settings.replay_feature_enabled)
934 		return;
935 
936 	cmd_data.set_general_cmd_data.subtype = general_cmd_type;
937 	cmd_data.set_general_cmd_data.param1 = param1;
938 	cmd_data.set_general_cmd_data.param2 = param2;
939 	link->dc->link_srv->edp_send_replay_cmd(link, Replay_Set_General_Cmd,
940 		&cmd_data);
941 }
942 
943 void mod_power_replay_disabled_desync_error_detection(struct mod_power *mod_power,
944 	const struct dc_stream_state *stream,  bool force_disabled)
945 {
946 	mod_power_replay_set_general_cmd(mod_power, stream,
947 			REPLAY_GENERAL_CMD_DISABLED_DESYNC_ERROR_DETECTION,
948 			force_disabled, 0);
949 }
950 
951 static void mod_power_replay_set_pseudo_vtotal(struct mod_power *mod_power,
952 	const struct dc_stream_state *stream, uint16_t vtotal)
953 {
954 	struct core_power *core_power = NULL;
955 	struct dc_link *link = NULL;
956 	unsigned int stream_index = 0;
957 	union dmub_replay_cmd_set cmd_data = { 0 };
958 
959 	if (!stream || mod_power == NULL)
960 		return;
961 
962 	core_power = MOD_POWER_TO_CORE(mod_power);
963 	if (core_power->num_entities == 0)
964 		return;
965 
966 	stream_index = map_index_from_stream(core_power, stream);
967 	if (stream_index > core_power->num_entities) //invalid index
968 		return;
969 
970 	link = dc_stream_get_link(stream);
971 	if (!link || !link->replay_settings.replay_feature_enabled)
972 		return;
973 
974 	cmd_data.pseudo_vtotal_data.vtotal = vtotal;
975 
976 	if (link->replay_settings.last_pseudo_vtotal != vtotal) {
977 		link->replay_settings.last_pseudo_vtotal = vtotal;
978 		link->dc->link_srv->edp_send_replay_cmd(link, Replay_Set_Pseudo_VTotal, &cmd_data);
979 	}
980 }
981 
982 static void mod_power_update_error_status(struct mod_power *mod_power,
983 	const struct dc_stream_state *stream)
984 {
985 	struct dc_link *link = NULL;
986 	union replay_debug_flags *pDebug = NULL;
987 
988 	if (mod_power == NULL || stream == NULL)
989 		return;
990 
991 	link = dc_stream_get_link(stream);
992 
993 	if (!link)
994 		return;
995 
996 	pDebug = (union replay_debug_flags *)&link->replay_settings.config.debug_flags;
997 
998 	if (0 == pDebug->bitfields.enable_visual_confirm_debug)
999 		return;
1000 
1001 	mod_power_replay_set_general_cmd(mod_power, stream,
1002 		REPLAY_GENERAL_CMD_UPDATE_ERROR_STATUS,
1003 		link->replay_settings.config.replay_error_status.raw, 0);
1004 }
1005 
1006 void mod_power_set_low_rr_activate(struct mod_power *mod_power,
1007 	const struct dc_stream_state *stream, bool low_rr_supported)
1008 {
1009 	struct dc_link *link = NULL;
1010 
1011 	if (mod_power == NULL || stream == NULL)
1012 		return;
1013 
1014 	link = dc_stream_get_link(stream);
1015 
1016 	if (!link)
1017 		return;
1018 
1019 	mod_power_replay_set_general_cmd(mod_power, stream,
1020 		REPLAY_GENERAL_CMD_SET_LOW_RR_ACTIVATE,
1021 		low_rr_supported, 0);
1022 }
1023 
1024 void mod_power_set_video_conferencing_activate(struct mod_power *mod_power,
1025 	const struct dc_stream_state *stream, bool video_conferencing_activate)
1026 {
1027 	struct dc_link *link = NULL;
1028 
1029 	if (mod_power == NULL || stream == NULL)
1030 		return;
1031 
1032 	link = dc_stream_get_link(stream);
1033 	if (!link || !link->replay_settings.replay_feature_enabled)
1034 		return;
1035 
1036 	mod_power_replay_set_general_cmd(mod_power, stream,
1037 		REPLAY_GENERAL_CMD_VIDEO_CONFERENCING,
1038 		video_conferencing_activate, 0);
1039 }
1040 
1041 void mod_power_set_coasting_vtotal_without_frame_update(struct mod_power *mod_power,
1042 	const struct dc_stream_state *stream, uint32_t coasting_vtotal)
1043 {
1044 	struct dc_link *link = NULL;
1045 
1046 	if (mod_power == NULL || stream == NULL)
1047 		return;
1048 
1049 	link = dc_stream_get_link(stream);
1050 	if (!link || !link->replay_settings.replay_feature_enabled)
1051 		return;
1052 
1053 	mod_power_replay_set_general_cmd(mod_power, stream,
1054 		REPLAY_GENERAL_CMD_SET_COASTING_VTOTAL_WITHOUT_FRAME_UPDATE,
1055 		coasting_vtotal, 0);
1056 }
1057 
1058 void mod_power_set_replay_continuously_resync(struct mod_power *mod_power,
1059 	const struct dc_stream_state *stream, bool enable)
1060 {
1061 	struct dc_link *link = NULL;
1062 
1063 	if (mod_power == NULL || stream == NULL)
1064 		return;
1065 
1066 	link = dc_stream_get_link(stream);
1067 	if (!link || !link->replay_settings.replay_feature_enabled)
1068 		return;
1069 
1070 	mod_power_replay_set_general_cmd(mod_power, stream,
1071 		REPLAY_GENERAL_CMD_SET_CONTINUOUSLY_RESYNC,
1072 		enable, 0);
1073 }
1074 
1075 void mod_power_set_live_capture_with_cvt_activate(struct mod_power *mod_power,
1076 	const struct dc_stream_state *stream, bool live_capture_with_cvt_activate)
1077 {
1078 	struct dc_link *link = NULL;
1079 
1080 	if (mod_power == NULL || stream == NULL)
1081 		return;
1082 
1083 	link = dc_stream_get_link(stream);
1084 	if (!link || !link->replay_settings.replay_feature_enabled)
1085 		return;
1086 
1087 	// Check if LIVE_CAPTURE_WITH_CVT bit is enabled in DalRegKey_ReplayOptimization
1088 	if (!link->replay_settings.config.replay_optimization.bits.LIVE_CAPTURE_WITH_CVT)
1089 		return;
1090 
1091 	if (link->replay_settings.config.live_capture_with_cvt_activated != live_capture_with_cvt_activate) {
1092 		link->replay_settings.config.live_capture_with_cvt_activated = live_capture_with_cvt_activate;
1093 		mod_power_replay_set_general_cmd(mod_power, stream,
1094 			REPLAY_GENERAL_CMD_LIVE_CAPTURE_WITH_CVT,
1095 			live_capture_with_cvt_activate, 0);
1096 	}
1097 }
1098 
1099 bool mod_power_set_replay_event(struct mod_power *mod_power,
1100 	struct dc_stream_state *stream, bool set_event,
1101 	enum replay_event event, bool wait_for_disable)
1102 {
1103 	struct core_power *core_power = NULL;
1104 	struct dc_link *link = NULL;
1105 	unsigned int stream_index = 0;
1106 	unsigned int active_replay_events = 0;
1107 	bool replay_active_request = false;
1108 	bool force_static = false;
1109 	uint32_t coasting_vtotal = 0;
1110 	bool current_timing_sync_status = false;
1111 	bool is_full_screen_video = false;
1112 	bool is_ultra_sleep_mode = false;
1113 	unsigned int sink_duration_us = 0;
1114 	bool low_rr_active = false;
1115 	uint16_t frame_skip_number = 0;
1116 	bool is_video_playback = false;
1117 
1118 	if (!stream)
1119 		return false;
1120 
1121 	if (mod_power == NULL)
1122 		return false;
1123 
1124 	core_power = MOD_POWER_TO_CORE(mod_power);
1125 
1126 	if (core_power->num_entities == 0)
1127 		return false;
1128 
1129 	stream_index = map_index_from_stream(core_power, stream);
1130 
1131 	if (set_event)
1132 		core_power->map[stream_index].replay_events |= event;
1133 	else
1134 		core_power->map[stream_index].replay_events &= ~event;
1135 
1136 	link = dc_stream_get_link(stream);
1137 	if (!link || !link->replay_settings.replay_feature_enabled)
1138 		return false;
1139 
1140 	if ((core_power->map[stream_index].replay_events & replay_event_disable_replay_while_switching_mux) != 0)
1141 		return false;
1142 
1143 	if ((core_power->map[stream_index].replay_events & replay_event_os_override_hold) != 0)
1144 		return false;
1145 
1146 	active_replay_events = core_power->map[stream_index].replay_events;
1147 
1148 	current_timing_sync_status =
1149 		link->replay_settings.config.replay_timing_sync_supported;
1150 
1151 	replay_active_request = mod_power_update_replay_active_status(active_replay_events,
1152 		link, &coasting_vtotal, &is_full_screen_video, &is_ultra_sleep_mode, &frame_skip_number, &is_video_playback);
1153 
1154 	if (is_full_screen_video)
1155 		mod_power_replay_set_pseudo_vtotal(mod_power, stream,
1156 			link->replay_settings.low_rr_full_screen_video_pseudo_vtotal);
1157 	else
1158 		mod_power_replay_set_pseudo_vtotal(mod_power, stream, 0);
1159 
1160 	//If timing_sync_status change, then re-enabled set timing_sync_supported value and re-enabled replay
1161 	if (current_timing_sync_status != link->replay_settings.config.replay_timing_sync_supported)
1162 		mod_power_replay_set_timing_sync_supported(mod_power, stream);
1163 
1164 	if (link->replay_settings.config.low_rr_supported) {
1165 		sink_duration_us =
1166 			(unsigned int)(div_u64(((unsigned long long)(coasting_vtotal)
1167 				* 10000) * stream->timing.h_total,
1168 					stream->timing.pix_clk_100hz));
1169 		low_rr_active = sink_duration_us < LOW_REFRESH_RATE_DURATION_US_UPPER_BOUND ? false : true;
1170 		if (low_rr_active != link->replay_settings.config.low_rr_activated) {
1171 			mod_power_set_low_rr_activate(mod_power, stream, low_rr_active);
1172 			link->replay_settings.config.low_rr_activated = low_rr_active;
1173 		}
1174 	}
1175 
1176 	// The function return fail when
1177 	// 1. DMUB function is not support (for backward compatible).
1178 	// 2. active_replay_events or coasting_vtotal is not updated in the same time
1179 	if (!mod_power_replay_set_power_opt_and_coasting_vtotal(mod_power,
1180 		stream, active_replay_events, coasting_vtotal, is_ultra_sleep_mode, frame_skip_number)) {
1181 		if (!mod_power_replay_set_power_opt(mod_power, stream, active_replay_events, is_ultra_sleep_mode))
1182 			return false;
1183 
1184 		if (!mod_power_replay_set_coasting_vtotal(mod_power, stream, coasting_vtotal, frame_skip_number))
1185 			return false;
1186 	}
1187 
1188 	mod_power_set_live_capture_with_cvt_activate(mod_power, stream, is_video_playback);
1189 
1190 	mod_power_update_error_status(mod_power, stream);
1191 
1192 	// If Replay is going to be enable (No matter is disable -> enable or enable -> enable), we don't need to wait.
1193 	// If Replay is going to be disable
1194 	//     if disable -> disable
1195 	//         -> Replay DMUB state should be state 0.
1196 	//            So no matter wait_for_disable is true or not, it should makes no difference.
1197 	//     if enable -> disable -> We should wait if wait_for_disable is true.
1198 	if (replay_active_request)
1199 		wait_for_disable = false;
1200 
1201 	if (!mod_power_set_replay_active(stream, replay_active_request, wait_for_disable, force_static))
1202 		return false;
1203 
1204 	return true;
1205 }
1206 
1207 bool mod_power_get_replay_active_status(const struct dc_stream_state *stream,
1208 	bool *replay_active)
1209 {
1210 	const struct dc_link *link = NULL;
1211 
1212 	if (!stream)
1213 		return false;
1214 
1215 	link = dc_stream_get_link(stream);
1216 	*replay_active = link->replay_settings.replay_allow_active;
1217 
1218 	return true;
1219 }
1220 
1221 void mod_power_replay_residency(const struct dc_stream_state *stream,
1222 	unsigned int *residency, const bool is_start, const bool is_alpm)
1223 {
1224 	const struct dc_link *link = NULL;
1225 	enum pr_residency_mode mode;
1226 
1227 	if (!stream)
1228 		return;
1229 
1230 	link = dc_stream_get_link(stream);
1231 
1232 	if (is_alpm)
1233 		mode = PR_RESIDENCY_MODE_ALPM;
1234 	else
1235 		mode = PR_RESIDENCY_MODE_PHY;
1236 
1237 	if (link && link->dc && link->dc->link_srv)
1238 		link->dc->link_srv->edp_replay_residency(link, residency, is_start, mode);
1239 }
1240 
1241 bool mod_power_replay_set_power_opt_and_coasting_vtotal(struct mod_power *mod_power,
1242 	const struct dc_stream_state *stream, unsigned int active_replay_events, uint32_t coasting_vtotal,
1243 	bool is_ultra_sleep_mode, uint16_t frame_skip_number)
1244 {
1245 	struct core_power *core_power = NULL;
1246 	struct dc_link *link = NULL;
1247 	unsigned int power_opt = 0;
1248 
1249 	if (!stream)
1250 		return false;
1251 
1252 	if (mod_power == NULL)
1253 		return false;
1254 
1255 	core_power = MOD_POWER_TO_CORE(mod_power);
1256 
1257 	if (core_power->num_entities == 0)
1258 		return false;
1259 
1260 	link = dc_stream_get_link(stream);
1261 
1262 	if (!link || !link->replay_settings.replay_feature_enabled)
1263 		return false;
1264 
1265 	power_opt = mod_power_replay_setup_power_opt(link, active_replay_events, is_ultra_sleep_mode);
1266 
1267 	return link->dc->link_srv->edp_set_replay_power_opt_and_coasting_vtotal(link, &power_opt, coasting_vtotal, frame_skip_number);
1268 }
1269 
1270 
1271 
1272 
1273 
1274