xref: /linux/drivers/gpu/drm/amd/display/modules/power/power.c (revision 35a8ecb704938596fd655c25dca4234ee5cc031f)
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 
46 struct backlight_state {
47 	/* HW uses u16.16 format for backlight PWM */
48 	unsigned int backlight_pwm;
49 	/* DM may call power module to set backlight
50 	 * targeting percent brightness
51 	 */
52 	unsigned int backlight_millipercent;
53 	/* DM may call power module to set backlight based on an explicit
54 	 * nits value.
55 	 */
56 	unsigned int backlight_millinit;
57 	unsigned int frame_ramp;
58 	bool smooth_brightness_enabled;
59 	bool isHDR;
60 };
61 struct power_entity {
62 	struct dc_stream_state *stream;
63 	struct psr_caps *caps;
64 	struct mod_power_psr_context *psr_context;
65 
66 	/*PSR cached properties*/
67 	bool psr_enabled;
68 	unsigned int psr_events;
69 	unsigned int psr_power_opt;
70 	unsigned int replay_events;
71 };
72 
73 struct pwr_backlight_properties {
74 	bool use_nits_based_brightness;
75 	bool disable_fractional_pwm;
76 
77 	unsigned int min_abm_backlight;
78 	unsigned int num_backlight_levels;
79 
80 	bool backlight_ramping_override;
81 	unsigned int backlight_ramping_reduction;
82 	unsigned int backlight_ramping_start;
83 
84 	/* Backlight cached properties */
85 	unsigned int ac_backlight_percent;
86 	unsigned int dc_backlight_percent;
87 
88 	/* backlight LUT stored in HW u16.16 format*/
89 	unsigned int *backlight_lut;
90 	unsigned int min_backlight_pwm;
91 	unsigned int max_backlight_pwm;
92 	unsigned int backlight_range;
93 
94 	/* Describes the panel's min and max luminance in millinits measured
95 	 * on full white screen, in min and max backlight settings.
96 	 */
97 	unsigned int min_brightness_millinits;
98 	unsigned int max_brightness_millinits;
99 	unsigned int nits_range;
100 
101 	bool backlight_caps_valid;
102 	bool use_custom_backlight_caps;
103 	unsigned int custom_backlight_caps_config_no;
104 	bool use_linear_backlight_curve;
105 };
106 
107 struct dmcu_varibright_cached_properties {
108 	unsigned int varibright_config_setting;
109 	unsigned int varibright_level;
110 	unsigned int varibright_hw_level;
111 	unsigned int def_varibright_level;
112 	bool varibright_user_enable;
113 	bool varibright_active;
114 };
115 
116 struct core_power {
117 	struct mod_power public;
118 	struct dc *dc;
119 	struct power_entity *map;
120 	struct dmcu_varibright_cached_properties varibright_prop;
121 	struct pwr_backlight_properties bl_prop[MAX_NUM_EDP];
122 	struct backlight_state bl_state[MAX_NUM_EDP];
123 	unsigned int edp_num;
124 
125 	bool psr_smu_optimizations_support;
126 	bool multi_disp_optimizations_support;
127 
128 	int num_entities;
129 };
130 
131 union dmcu_abm_set_bl_params {
132 	struct {
133 		unsigned int gradual_change : 1; /* [0:0] */
134 		unsigned int reserved : 15; /* [15:1] */
135 		unsigned int frame_ramp : 16; /* [31:16] */
136 	} bits;
137 	unsigned int u32All;
138 };
139 
140 /* If system or panel does not report some sort of brightness percent to nits
141  * mapping, we will use following default values so backlight control using
142  * nits based interfaces will still work, but might not describe panel
143  * correctly. In this case percentage based backlight control should ideally
144  * be used.
145  * Min = 5 nits
146  * Max = 300 nits
147  */
148 
149 static const unsigned int pwr_default_min_brightness_millinits = 1000;
150 static const unsigned int pwr_default_sdr_brightness_millinits = 270000;
151 
152 static const unsigned int default_ac_backlight_percent   = 100;
153 static const unsigned int default_dc_backlight_percent   = 70;
154 
155 #define MOD_POWER_TO_CORE(mod_power)\
156 		container_of(mod_power, struct core_power, public)
157 
158 static unsigned int calc_psr_num_static_frames(unsigned int vsync_rate_hz)
159 {
160 	/* Initialize fail-safe to 2 static frames. */
161 	unsigned int num_frames_static = 2;
162 
163 	/* Calculate number of frames such that at least 30 ms has passed.
164 	 * Round up to ensure the static period is not shorter than 30 ms.
165 	 */
166 	if (vsync_rate_hz != 0)
167 		num_frames_static = DIV_ROUND_UP(30000 * vsync_rate_hz, 1000000);
168 
169 	return num_frames_static;
170 }
171 
172 /* Given a specific dc_stream* this function finds its equivalent
173  * on the core_freesync->map and returns the corresponding index
174  */
175 static unsigned int map_index_from_stream(struct core_power *core_power,
176 		const struct dc_stream_state *stream)
177 {
178 	unsigned int index = 0;
179 
180 	for (index = 0; index < core_power->num_entities; index++) {
181 		if (core_power->map[index].stream == stream)
182 			return index;
183 	}
184 	/* Could not find stream requested, this is not trivial, fix when hit*/
185 	DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
186 						WPP_BIT_FLAG_Firmware_PsrState,
187 						"map index from stream: ERROR: core_power=%p stream=%p",
188 						core_power,
189 						stream);
190 	ASSERT(false);
191 	/* We come here only when we can't map stream index.
192 	 * In good cases, this would happen when we attempt to change
193 	 * brightness before stream creation, in which case we create a
194 	 * dummy stream with index 0.
195 	 * With external monitor connected, the index passed from this return
196 	 * is 1. Passing anything greater than 0 from here would always point
197 	 * to bad memory.
198 	 */
199 	return 0;
200 }
201 
202 static uint16_t backlight_8_to_16(unsigned int backlight_8bit)
203 {
204 	return (uint16_t)(backlight_8bit * 0x101);
205 }
206 
207 
208 static unsigned int backlight_millipercent_to_millinit(
209 		struct core_power *core_power, unsigned int millipercent, unsigned int inst)
210 {
211 	unsigned int millinit = 0;
212 	unsigned long long numerator = 0;
213 
214 	if (core_power == NULL)
215 		return 0;
216 
217 	numerator = ((unsigned long long)millipercent) *
218 				core_power->bl_prop[inst].nits_range;
219 	millinit = ((unsigned int)div_u64(numerator, 100000)) +
220 			core_power->bl_prop[inst].min_brightness_millinits;
221 
222 	return millinit;
223 }
224 
225 static unsigned int backlight_millinit_to_millipercent(
226 		struct core_power *core_power, unsigned int millinit, unsigned int inst)
227 {
228 	unsigned int millipercent = 0;
229 	unsigned long long numerator = 0;
230 
231 	if (core_power == NULL)
232 		return 0;
233 
234 	if (millinit <= core_power->bl_prop[inst].min_brightness_millinits)
235 		return 0;
236 
237 	if (millinit >= core_power->bl_prop[inst].max_brightness_millinits)
238 		return (100 * 1000);
239 
240 	numerator = (((unsigned long long)millinit) -
241 			core_power->bl_prop[inst].min_brightness_millinits) * 100000;
242 	millipercent = ((unsigned int)div_u64(numerator,
243 				core_power->bl_prop[inst].nits_range));
244 
245 	return millipercent;
246 }
247 
248 static unsigned int backlight_pwm_to_millipercent(
249 		struct core_power *core_power, unsigned int pwm, unsigned int inst)
250 {
251 	unsigned int millipercent = 0;
252 	unsigned int max_index = 0;
253 
254 	if (core_power == NULL)
255 		return 0;
256 
257 	if (!core_power->bl_prop[inst].backlight_caps_valid)
258 		return 0;
259 
260 	/* Doesn't really make sense to have one single backlight level
261 	 * possible...
262 	 */
263 	if (core_power->bl_prop[inst].num_backlight_levels < 2)
264 		return 0;
265 
266 	max_index = core_power->bl_prop[inst].num_backlight_levels - 1;
267 
268 	if (pwm <= core_power->bl_prop[inst].backlight_lut[0])
269 		return 0;
270 
271 	if (pwm > core_power->bl_prop[inst].backlight_lut[max_index])
272 		return (100 * 1000);
273 
274 	/* We need to do a binary search over the array for where the pwm level
275 	 * is in the lut. Based on the index we can determine percentage.
276 	 */
277 	unsigned int min = 0;
278 	unsigned int max = max_index;
279 	unsigned int mid = 0;
280 
281 	while (max >= min) {
282 		mid = (min + max) / 2; /* floor of half range */
283 
284 		if (core_power->bl_prop[inst].backlight_lut[mid] < pwm)
285 			min = mid + 1;
286 		else if (core_power->bl_prop[inst].backlight_lut[mid] > pwm)
287 			max = mid - 1;
288 		else
289 			break;
290 	}
291 
292 	/* In this case, exact match is not found. Check if mid/min/max
293 	 * value is actually closer.
294 	 */
295 	if (max < min) {
296 		unsigned int min_delta;
297 		unsigned int mid_delta;
298 		unsigned int max_delta;
299 
300 		min_delta = (core_power->bl_prop[inst].backlight_lut[min] > pwm) ?
301 				core_power->bl_prop[inst].backlight_lut[min] - pwm :
302 				pwm - core_power->bl_prop[inst].backlight_lut[min];
303 
304 		mid_delta = (core_power->bl_prop[inst].backlight_lut[mid] > pwm) ?
305 				core_power->bl_prop[inst].backlight_lut[mid] - pwm :
306 				pwm - core_power->bl_prop[inst].backlight_lut[mid];
307 
308 		max_delta = (core_power->bl_prop[inst].backlight_lut[max] > pwm) ?
309 				core_power->bl_prop[inst].backlight_lut[max] - pwm :
310 				pwm - core_power->bl_prop[inst].backlight_lut[max];
311 
312 		if ((min_delta < mid_delta) && (min_delta < max_delta))
313 			mid = min;
314 
315 		if ((max_delta < mid_delta) && (max_delta < min_delta))
316 			mid = max;
317 	}
318 
319 	/* No interpolation, just take closest index */
320 	millipercent = 1000 * 100 * mid / max_index;
321 
322 	return millipercent;
323 }
324 
325 static unsigned int backlight_pwm_to_millinit(
326 		struct core_power *core_power, unsigned int pwm, unsigned int inst)
327 {
328 	unsigned int millinit = 0;
329 
330 	if (core_power == NULL)
331 		return 0;
332 
333 	if (pwm <= core_power->bl_prop[inst].min_backlight_pwm)
334 		return core_power->bl_prop[inst].min_brightness_millinits;
335 
336 	if (pwm >= core_power->bl_prop[inst].max_backlight_pwm)
337 		return core_power->bl_prop[inst].max_brightness_millinits;
338 
339 	millinit = ((unsigned int)div_u64(((unsigned long long)pwm -
340 				core_power->bl_prop[inst].min_backlight_pwm) *
341 				core_power->bl_prop[inst].nits_range,
342 				core_power->bl_prop[inst].backlight_range));
343 
344 	millinit += core_power->bl_prop[inst].min_brightness_millinits;
345 
346 	if (millinit > core_power->bl_prop[inst].max_brightness_millinits)
347 		millinit = core_power->bl_prop[inst].max_brightness_millinits;
348 
349 	return millinit;
350 }
351 
352 static unsigned int backlight_millipercent_to_pwm(
353 		struct core_power *core_power, unsigned int millipercent, unsigned int inst)
354 {
355 	unsigned int pwm = (unsigned int)-1;
356 	unsigned int index = 0;
357 
358 	if (core_power == NULL)
359 		return 0;
360 
361 	// Bypass the brightness mapping LUT
362 	if (core_power->bl_prop->use_linear_backlight_curve) {
363 		pwm = core_power->bl_prop[inst].min_backlight_pwm +
364 			(unsigned int) div_u64((unsigned long long) millipercent *
365 			core_power->bl_prop[inst].backlight_range,
366 			100000);
367 
368 		if (pwm > core_power->bl_prop[inst].max_backlight_pwm)
369 			pwm = core_power->bl_prop[inst].max_backlight_pwm;
370 
371 		return pwm;
372 	}
373 
374 	if (millipercent >= (100 * 1000))
375 		return core_power->bl_prop[inst].backlight_lut[core_power->bl_prop[inst].num_backlight_levels - 1];
376 
377 	/* This will give the floor index. */
378 	index = ((core_power->bl_prop[inst].num_backlight_levels - 1) *
379 						millipercent) / 100000;
380 	/* Null check otherwise eDP doesn't lightup when connected to DP1 */
381 	if (core_power->bl_prop[inst].backlight_lut == NULL)
382 		return pwm;
383 
384 	pwm = core_power->bl_prop[inst].backlight_lut[index];
385 
386 	return pwm;
387 }
388 
389 static unsigned int backlight_millinit_to_pwm(
390 		struct core_power *core_power, unsigned int millinit, unsigned int inst)
391 {
392 	unsigned int pwm = 0;
393 
394 	if (core_power == NULL)
395 		return 0;
396 
397 	/* For nits based brightness, the signal will be a value
398 	 * between the minimum and maximum value.
399 	 */
400 	if (millinit >= core_power->bl_prop[inst].max_brightness_millinits)
401 		return core_power->bl_prop[inst].max_backlight_pwm;
402 	else if (millinit <= core_power->bl_prop[inst].min_brightness_millinits)
403 		return core_power->bl_prop[inst].min_backlight_pwm;
404 
405 	pwm = ((unsigned int)div_u64(((unsigned long long)millinit -
406 			core_power->bl_prop[inst].min_brightness_millinits) *
407 			core_power->bl_prop[inst].backlight_range,
408 			core_power->bl_prop[inst].nits_range));
409 
410 	pwm += core_power->bl_prop[inst].min_backlight_pwm;
411 
412 	if (pwm > core_power->bl_prop[inst].max_backlight_pwm)
413 		pwm = core_power->bl_prop[inst].max_backlight_pwm;
414 
415 	return pwm;
416 }
417 
418 static bool validate_ext_backlight_caps(
419 		struct dm_acpi_atif_backlight_caps *ext_backlight_caps)
420 {
421 	unsigned int i;
422 	unsigned int num_of_data_points = 0;
423 	unsigned int last_signal_level = 0;
424 	unsigned int last_luminance = 0;
425 
426 	num_of_data_points = ext_backlight_caps->num_data_points;
427 
428 	/* Validation rules:
429 	 * 1. BIOS should carry customized data points and
430 	 * the number of data points should not be larger than 99.
431 	 * 2. The max_input_signal should be larger than min_input_signal.
432 	 * 3. For each data point:
433 	 *	a. luminance should be in ascending order and
434 	 *	should not be 0 or 100 since the corresponding signal_level
435 	 *	are assigned by min_input_signal and max_input_signal.
436 	 *	b. signal_level should be in ascending order and
437 	 *	be within the range of min/max_input_signal.
438 	 */
439 	if (num_of_data_points > BL_DATA_POINTS)
440 		return false;
441 
442 	if (ext_backlight_caps->min_input_signal >= ext_backlight_caps->max_input_signal)
443 		return false;
444 
445 	last_signal_level = ext_backlight_caps->min_input_signal;
446 	for (i = 0; i < num_of_data_points; i++) {
447 		unsigned int luminance = ext_backlight_caps->data_points[i].luminance;
448 		unsigned int signal_level = ext_backlight_caps->data_points[i].signal_level;
449 
450 		if ((luminance <= last_luminance) || (luminance > BL_DATA_POINTS))
451 			return false;
452 
453 		if ((signal_level <= last_signal_level) || (signal_level >= ext_backlight_caps->max_input_signal))
454 			return false;
455 
456 		last_signal_level = signal_level;
457 		last_luminance = luminance;
458 	}
459 
460 	return true;
461 }
462 
463 /* hard coded to default backlight curve. */
464 static void initialize_backlight_caps(struct core_power *core_power, unsigned int inst)
465 {
466 	unsigned int i;
467 	struct dm_acpi_atif_backlight_caps *ext_backlight_caps = NULL;
468 	bool custom_curve_present = false;
469 	unsigned int num_levels = 0;
470 	struct dc *dc = NULL;
471 	enum dm_acpi_display_type acpi_display_type =
472 		(inst == 0) ? AcpiDisplayType_LCD1 : AcpiDisplayType_LCD2;
473 
474 	if (core_power == NULL)
475 		return;
476 	dc = core_power->dc;
477 
478 	num_levels = core_power->bl_prop[inst].num_backlight_levels;
479 
480 	/* Allocate memory for ATIF output
481 	 * (do not want to use 256 bytes on the stack)
482 	 */
483 	ext_backlight_caps = (struct dm_acpi_atif_backlight_caps *)
484 		(kzalloc(sizeof(struct dm_acpi_atif_backlight_caps),
485 				GFP_KERNEL));
486 
487 	if (ext_backlight_caps == NULL)
488 		return;
489 
490 	/* Retrieve ACPI extended brightness caps */
491 	if (dm_query_extended_brightness_caps
492 		(dc->ctx, acpi_display_type, ext_backlight_caps)) {
493 		custom_curve_present = validate_ext_backlight_caps(ext_backlight_caps);
494 	}
495 
496 	if (core_power->bl_prop[inst].use_custom_backlight_caps &&
497 			fill_custom_backlight_caps(
498 					core_power->bl_prop[inst].custom_backlight_caps_config_no,
499 					ext_backlight_caps)) {
500 		custom_curve_present = validate_ext_backlight_caps(ext_backlight_caps);
501 	}
502 
503 	if (custom_curve_present) {
504 		unsigned int index = 1;
505 		unsigned int num_of_data_points = ext_backlight_caps->num_data_points;
506 
507 		core_power->bl_prop[inst].ac_backlight_percent =
508 			ext_backlight_caps->ac_level_percentage;
509 		core_power->bl_prop[inst].dc_backlight_percent =
510 			ext_backlight_caps->dc_level_percentage;
511 		core_power->bl_prop[inst].backlight_lut[0] =
512 			backlight_8_to_16(
513 				ext_backlight_caps->min_input_signal);
514 		core_power->bl_prop[inst].backlight_lut[num_levels - 1] =
515 			backlight_8_to_16(
516 				ext_backlight_caps->max_input_signal);
517 
518 		/* Filling translation table from data points -
519 		 * between every two provided data points we
520 		 * lineary interpolate missing values
521 		 */
522 		for (i = 0; i < num_of_data_points; i++) {
523 			unsigned int luminance =
524 				ext_backlight_caps->data_points[i].luminance;
525 			unsigned int signal_level =
526 				backlight_8_to_16(
527 					ext_backlight_caps->data_points[i].signal_level);
528 
529 			/* Since luminance is a percentage, scale it by num_levels*/
530 			luminance = (luminance * num_levels) / 101;
531 
532 			/* Lineary interpolate missing values */
533 			if (index < luminance) {
534 				unsigned int base_value =
535 					core_power->bl_prop[inst].backlight_lut[index-1];
536 				unsigned int delta_signal =
537 					signal_level - base_value;
538 				unsigned int delta_luma =
539 					luminance - index + 1;
540 				unsigned int step  = delta_signal;
541 
542 				for (; index < luminance; index++) {
543 					core_power->bl_prop[inst].backlight_lut[index] =
544 						base_value + (step / delta_luma);
545 					step += delta_signal;
546 				}
547 			}
548 
549 			/* Now [index == luminance],
550 			 * so we can add data point to the translation table
551 			 */
552 			core_power->bl_prop[inst].backlight_lut[index++] = signal_level;
553 		}
554 
555 		/* Complete the final segment of interpolation -
556 		 * between last datapoint and maximum value
557 		 */
558 		if (index < num_levels - 1) {
559 			unsigned int base_value =
560 				core_power->bl_prop[inst].backlight_lut[index-1];
561 			unsigned int delta_signal =
562 				core_power->bl_prop[inst].backlight_lut[num_levels - 1] -
563 								base_value;
564 			unsigned int delta_luma = num_levels - index;
565 			unsigned int step = delta_signal;
566 
567 			for (; index < num_levels - 1; index++) {
568 				core_power->bl_prop[inst].backlight_lut[index] =
569 						base_value + (step / delta_luma);
570 				step += delta_signal;
571 			}
572 		}
573 	/* Build backlight translation table based on default curve */
574 	} else {
575 		/* Defines default backlight curve F(x) = A(x*x) + Bx + C.
576 		 *
577 		 * Backlight curve should always  satisfy:
578 		 * F(0) = min, F(100) = max,
579 		 * So polynom coefficients are:
580 		 * A is 0.0255 - B/100 - min/10000 - (255-max)/10000 =
581 		 * (max - min)/10000 - B/100
582 		 * B is adjustable factor to modify the curve.
583 		 * Bigger B results in less concave curve.
584 		 * B range is [0..(max-min)/100]
585 		 * C is backlight minimum
586 		 */
587 		unsigned int backlight_curve_coeff_a_factor =
588 				num_levels * num_levels;
589 		unsigned int backlight_curve_coeff_b = num_levels;
590 		unsigned int delta =
591 			core_power->bl_prop[inst].backlight_lut[num_levels - 1] -
592 				core_power->bl_prop[inst].backlight_lut[0];
593 		unsigned int coeffC = core_power->bl_prop[inst].backlight_lut[0];
594 		unsigned int coeffB =
595 				(backlight_curve_coeff_b < delta ?
596 					backlight_curve_coeff_b : delta);
597 		unsigned long long coeffA = delta - coeffB; /* coeffB is B*100 */
598 
599 		for (i = 1; i < num_levels - 1; i++) {
600 			uint64_t lut_val = div_u64(coeffA * i * i, backlight_curve_coeff_a_factor) +
601 				div_u64((uint64_t)coeffB * i, backlight_curve_coeff_b) + coeffC;
602 
603 			ASSERT(lut_val <= 0xFFFFFFFF);
604 			core_power->bl_prop[inst].backlight_lut[i] = (unsigned int)lut_val;
605 		}
606 	}
607 
608 	if (ext_backlight_caps != NULL)
609 		kfree(ext_backlight_caps);
610 
611 	/* Successfully initialized */
612 	core_power->bl_prop[inst].backlight_caps_valid = true;
613 }
614 
615 static void varibright_set_level(struct core_power *core_power)
616 {
617 	if (!core_power->varibright_prop.varibright_active ||
618 		!core_power->varibright_prop.varibright_user_enable)
619 		core_power->varibright_prop.varibright_hw_level = 0;
620 	else
621 		core_power->varibright_prop.varibright_hw_level =
622 			core_power->varibright_prop.varibright_level;
623 }
624 
625 bool mod_power_hw_init(struct mod_power *mod_power)
626 {
627 	struct core_power *core_power = NULL;
628 	struct dc *dc = NULL;
629 	struct dmcu *dmcu = NULL;
630 	struct dmcu_iram_parameters params;
631 	int i;
632 
633 	if (mod_power == NULL)
634 		return false;
635 
636 	core_power = MOD_POWER_TO_CORE(mod_power);
637 	dc = core_power->dc;
638 
639 	for (i = 0; i < core_power->edp_num; i++) {
640 		params.set = core_power->varibright_prop.varibright_config_setting;
641 		params.backlight_ramping_override = core_power->bl_prop[i].backlight_ramping_override;
642 		params.backlight_ramping_reduction = core_power->bl_prop[i].backlight_ramping_reduction;
643 		params.backlight_ramping_start = core_power->bl_prop[i].backlight_ramping_start;
644 		params.backlight_lut_array = core_power->bl_prop[i].backlight_lut;
645 		params.backlight_lut_array_size = core_power->bl_prop[i].num_backlight_levels;
646 		params.min_abm_backlight = core_power->bl_prop[i].min_abm_backlight;
647 
648 		dmcu = dc->res_pool->dmcu;
649 
650 		// In the case where abm is implemented on dmcub,
651 		// dmcu object will be null.
652 		// ABM 2.4 and up are implemented on dmcub.
653 		if (dmcu) {
654 			//DMCU does not support multiple eDP
655 			return dmcu_load_iram(dmcu, params);
656 		} else if (dc->ctx->dmub_srv) {
657 			if (!dmub_init_abm_config(dc->res_pool, params, i))
658 				return false;
659 		} else
660 			return false;
661 	}
662 	return true;
663 }
664 
665 struct mod_power *mod_power_create(struct dc *dc,
666 		struct mod_power_init_params *init_params,
667 		unsigned int edp_num)
668 {
669 	struct core_power *core_power = NULL;
670 	int i = 0;
671 	int abm_max_config = 0;
672 	unsigned int inst = 0;
673 	bool is_brightness_range_valid = false;
674 
675 	if (dc == NULL)
676 		goto fail_dc_null;
677 
678 	core_power = kzalloc(sizeof(struct core_power), GFP_KERNEL);
679 
680 	if (core_power == NULL)
681 		goto fail_alloc_context;
682 
683 	core_power->edp_num = edp_num;
684 	core_power->map = kzalloc(sizeof(struct power_entity) * MOD_POWER_MAX_CONCURRENT_STREAMS,
685 				  GFP_KERNEL);
686 
687 	if (core_power->map == NULL)
688 		goto fail_alloc_map;
689 
690 	for (i = 0; i < MOD_POWER_MAX_CONCURRENT_STREAMS; i++) {
691 		core_power->map[i].stream = NULL;
692 	}
693 
694 	for (i = 0; i < MOD_POWER_MAX_CONCURRENT_STREAMS; i++) {
695 		core_power->map[i].psr_context =
696 				kzalloc(sizeof(struct mod_power_psr_context),
697 					GFP_KERNEL);
698 		if (core_power->map[i].psr_context == NULL)
699 			goto fail_construct;
700 	}
701 
702 	core_power->psr_smu_optimizations_support = init_params->allow_psr_smu_optimizations;
703 	core_power->multi_disp_optimizations_support = init_params->allow_psr_multi_disp_optimizations;
704 
705 	for (inst = 0; inst < edp_num; inst++) {
706 		core_power->bl_prop[inst].min_abm_backlight =
707 				init_params[inst].min_abm_backlight;
708 		core_power->bl_prop[inst].disable_fractional_pwm =
709 				init_params[inst].disable_fractional_pwm;
710 		core_power->bl_prop[inst].use_linear_backlight_curve =
711 				init_params[inst].use_linear_backlight_curve;
712 		core_power->bl_prop[inst].use_nits_based_brightness =
713 				init_params[inst].use_nits_based_brightness;
714 		core_power->bl_prop[inst].backlight_ramping_override =
715 				init_params[inst].backlight_ramping_override;
716 		core_power->bl_prop[inst].backlight_ramping_reduction =
717 				init_params[inst].backlight_ramping_reduction;
718 		core_power->bl_prop[inst].backlight_ramping_start =
719 				init_params[inst].backlight_ramping_start;
720 		core_power->bl_prop[inst].use_custom_backlight_caps =
721 				init_params[inst].use_custom_backlight_caps;
722 		core_power->bl_prop[inst].custom_backlight_caps_config_no =
723 				init_params[inst].custom_backlight_caps_config_no;
724 
725 		// Do not allow less than 101 backlight levels
726 		if (init_params[inst].num_backlight_levels < 101)
727 			core_power->bl_prop[inst].num_backlight_levels = 101;
728 		else
729 			core_power->bl_prop[inst].num_backlight_levels =
730 				init_params[inst].num_backlight_levels;
731 
732 		core_power->bl_prop[inst].backlight_lut = (unsigned int *)
733 				(kzalloc(sizeof(unsigned int) *
734 				core_power->bl_prop[inst].num_backlight_levels, GFP_KERNEL));
735 		if (core_power->bl_prop[inst].backlight_lut == NULL)
736 			goto fail_alloc_backlight_array;
737 	}
738 
739 	core_power->varibright_prop.varibright_active = false;
740 
741 	core_power->varibright_prop.varibright_user_enable =
742 			init_params->def_varibright_enable;
743 
744 	// Table of ABM levels here is 1-4, but level 0 also exists as 'off'
745 	if (init_params->varibright_level <= abm_defines_max_level) {
746 		core_power->varibright_prop.varibright_level =
747 			init_params->varibright_level;
748 
749 	} else {
750 		core_power->varibright_prop.varibright_level = 3;
751 	}
752 	if (init_params->def_varibright_level <= abm_defines_max_level) {
753 		core_power->varibright_prop.def_varibright_level =
754 			init_params->def_varibright_level;
755 	} else {
756 		core_power->varibright_prop.def_varibright_level = 3;
757 	}
758 
759 	// ABM used to contain 4 different configs. There is only 3 since ABM 2.3.
760 	if ((dc->res_pool->dmcu != NULL) && (dc->res_pool->dmcu->dmcu_version.abm_version < 0x23))
761 		abm_max_config = 4;
762 	else
763 		abm_max_config = 3;
764 
765 	if (init_params->abm_config_setting < abm_max_config)
766 		core_power->varibright_prop.varibright_config_setting =
767 			init_params->abm_config_setting;
768 	else
769 		core_power->varibright_prop.varibright_config_setting = 0;
770 
771 	for (inst = 0; inst < edp_num; inst++) {
772 		core_power->bl_prop[inst].backlight_lut[0] = init_params[inst].min_backlight_pwm;
773 		core_power->bl_prop[inst].backlight_lut[
774 			core_power->bl_prop[inst].num_backlight_levels-1] =
775 				init_params[inst].max_backlight_pwm;
776 		core_power->bl_prop[inst].min_backlight_pwm = init_params[inst].min_backlight_pwm;
777 		core_power->bl_prop[inst].max_backlight_pwm = init_params[inst].max_backlight_pwm;
778 		core_power->bl_prop[inst].ac_backlight_percent =
779 				default_ac_backlight_percent;
780 		core_power->bl_prop[inst].dc_backlight_percent =
781 				default_dc_backlight_percent;
782 		core_power->bl_prop[inst].backlight_caps_valid = false;
783 
784 		if (core_power->bl_prop[inst].use_nits_based_brightness) {
785 			core_power->bl_prop[inst].min_brightness_millinits =
786 					init_params[inst].panel_min_millinits;
787 			core_power->bl_prop[inst].max_brightness_millinits =
788 					init_params[inst].panel_max_millinits;
789 		} else {
790 
791 			core_power->bl_prop[inst].min_brightness_millinits =
792 					pwr_default_min_brightness_millinits;
793 			core_power->bl_prop[inst].max_brightness_millinits =
794 					pwr_default_sdr_brightness_millinits;
795 		}
796 
797 		core_power->bl_prop[inst].backlight_range =
798 				core_power->bl_prop[inst].max_backlight_pwm-
799 				core_power->bl_prop[inst].min_backlight_pwm;
800 
801 		core_power->bl_prop[inst].nits_range =
802 				core_power->bl_prop[inst].max_brightness_millinits -
803 				core_power->bl_prop[inst].min_brightness_millinits;
804 
805 		core_power->bl_state[inst].smooth_brightness_enabled = true;
806 	}
807 
808 	/* Check if at least 1 instance in core_power is populated before failing */
809 	for (inst = 0; inst < edp_num; inst++) {
810 		if (core_power->bl_prop[inst].nits_range != 0 && core_power->bl_prop[inst].backlight_range != 0) {
811 			is_brightness_range_valid = true;
812 			break;
813 		}
814 
815 	}
816 	if (!is_brightness_range_valid)
817 		goto fail_bad_brightness_range;
818 
819 	core_power->num_entities = 0;
820 
821 	core_power->dc = dc;
822 	for (inst = 0; inst < edp_num; inst++) {
823 		initialize_backlight_caps(core_power, inst);
824 		core_power->bl_state[inst].backlight_millipercent =
825 			core_power->bl_prop[inst].dc_backlight_percent * 1000;
826 		core_power->bl_state[inst].backlight_pwm = backlight_millipercent_to_pwm(core_power,
827 		core_power->bl_state[inst].backlight_millipercent, inst);
828 		core_power->bl_state[inst].backlight_millinit = backlight_millipercent_to_millinit(core_power,
829 		core_power->bl_state[inst].backlight_millipercent, inst);
830 	}
831 
832 	return &core_power->public;
833 
834 fail_bad_brightness_range:
835 fail_alloc_backlight_array:
836 	for (inst = 0; inst < edp_num; inst++)
837 		if (core_power->bl_prop[inst].backlight_lut)
838 			kfree(core_power->bl_prop[inst].backlight_lut);
839 fail_construct:
840 	for (i = 0; i < MOD_POWER_MAX_CONCURRENT_STREAMS; i++) {
841 		if (core_power->map[i].psr_context)
842 			kfree(core_power->map[i].psr_context);
843 	}
844 	kfree(core_power->map);
845 
846 fail_alloc_map:
847 	kfree(core_power);
848 
849 fail_alloc_context:
850 fail_dc_null:
851 	return NULL;
852 }
853 
854 void mod_power_destroy(struct mod_power *mod_power)
855 {
856 	if (mod_power != NULL) {
857 		int i;
858 		struct core_power *core_power =
859 				MOD_POWER_TO_CORE(mod_power);
860 
861 		for (i = 0; i < MOD_POWER_MAX_CONCURRENT_STREAMS; i++)
862 			if (core_power->map[i].psr_context)
863 				kfree(core_power->map[i].psr_context);
864 
865 		for (i = 0; i < core_power->num_entities; i++)
866 			if (core_power->map[i].stream)
867 				dc_stream_release(core_power->map[i].stream);
868 
869 		kfree(core_power->map);
870 
871 		for (i = 0; i < MAX_NUM_EDP; i++)
872 			if (core_power->bl_prop[i].backlight_lut)
873 				kfree(core_power->bl_prop[i].backlight_lut);
874 
875 		kfree(core_power);
876 	}
877 }
878 
879 bool mod_power_add_stream(struct mod_power *mod_power,
880 		struct dc_stream_state *stream, struct psr_caps *caps)
881 {
882 	struct core_power *core_power = NULL;
883 
884 	if (mod_power == NULL)
885 		return false;
886 
887 	core_power = MOD_POWER_TO_CORE(mod_power);
888 
889 	if (core_power->num_entities < MOD_POWER_MAX_CONCURRENT_STREAMS) {
890 		dc_stream_retain(stream);
891 
892 		core_power->map[core_power->num_entities].stream = stream;
893 		core_power->map[core_power->num_entities].caps = caps;
894 
895 		// initialize cached PSR params to something "safe" (something that is
896 		// consistent with disabled PSR state)
897 		core_power->map[core_power->num_entities].psr_enabled = 0;
898 		core_power->map[core_power->num_entities].psr_events = psr_event_vsync;
899 		core_power->map[core_power->num_entities].psr_power_opt = 0;
900 		core_power->num_entities++;
901 		return true;
902 	}
903 
904 	DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
905 						WPP_BIT_FLAG_Firmware_PsrState,
906 						"mod_power: add_stream: ERROR: stream=%p num_entities=%d >= MOD_POWER_MAX_CONCURRENT_STREAMS",
907 						stream,
908 						core_power->num_entities);
909 
910 	return false;
911 }
912 
913 bool mod_power_remove_stream(struct mod_power *mod_power,
914 		const struct dc_stream_state *stream)
915 {
916 	int i = 0;
917 	struct core_power *core_power = NULL;
918 	unsigned int index = 0;
919 
920 	if (mod_power == NULL)
921 		return false;
922 
923 	core_power = MOD_POWER_TO_CORE(mod_power);
924 	if (core_power->num_entities == 0) {
925 		/* trying to remove a stream a second time or have not added yet */
926 		BREAK_TO_DEBUGGER();
927 		DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
928 							WPP_BIT_FLAG_Firmware_PsrState,
929 							"mod_power: remove_stream: ERROR: num_entities=0 stream=%p",
930 							stream);
931 		return false;
932 	}
933 
934 	index = map_index_from_stream(core_power, stream);
935 
936 	if (index >= core_power->num_entities) {
937 		/* trying to remove a stream a second time or have not added yet */
938 		BREAK_TO_DEBUGGER();
939 		DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
940 							WPP_BIT_FLAG_Firmware_PsrState,
941 							"mod_power: remove_stream: ERROR: index=%u >= num_entities=%d stream=%p",
942 							index,
943 							core_power->num_entities,
944 							stream);
945 		return false;
946 	}
947 
948 	dc_stream_release(core_power->map[index].stream);
949 	core_power->map[index].stream = NULL;
950 	/* To remove this entity, shift everything after down */
951 	for (i = index; i < core_power->num_entities - 1; i++) {
952 		core_power->map[i].stream = core_power->map[i + 1].stream;
953 		core_power->map[i].caps = core_power->map[i + 1].caps;
954 
955 		// copy over cached parameters in case they map to PSR capable display
956 		core_power->map[i].psr_enabled = core_power->map[i + 1].psr_enabled;
957 		core_power->map[i].psr_events = core_power->map[i + 1].psr_events;
958 		core_power->map[i].psr_power_opt = core_power->map[i + 1].psr_power_opt;
959 
960 		memcpy(core_power->map[i].psr_context, core_power->map[i + 1].psr_context, sizeof(struct mod_power_psr_context));
961 		memset(core_power->map[i + 1].psr_context, 0, sizeof(struct mod_power_psr_context));
962 	}
963 	core_power->num_entities--;
964 
965 	return true;
966 }
967 
968 /*
969  * Replace_stream should be used when there is a mode set for existing
970  * display target with a valid stream. In this case might need to retain
971  * cached PSR state (events, power opt, en/dis) if we are dealing with PSR
972  * capable display. If mod_power_remove and mod_power_add are used instead,
973  * then stream may be assigned to a different slot and may end up with
974  * wrong cached PSR state. It is hard to tell which PSR events should
975  * persist through mode set or what psr_events should be initialized to, so
976  * it might be better just to retain them all.
977  */
978 bool mod_power_replace_stream(struct mod_power *mod_power,
979 		const struct dc_stream_state *current_stream,
980 		struct dc_stream_state *new_stream,
981 		struct psr_caps *new_caps)
982 {
983 	struct core_power *core_power = NULL;
984 	unsigned int index = 0;
985 
986 	if (mod_power == NULL)
987 		return false;
988 
989 	core_power = MOD_POWER_TO_CORE(mod_power);
990 	if (core_power->num_entities == 0) {
991 		/* no streams exist in the table yet */
992 		BREAK_TO_DEBUGGER();
993 		DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
994 							WPP_BIT_FLAG_Firmware_PsrState,
995 							"mod_power: replace_stream: ERROR: num_entities=0 stream=%p",
996 							current_stream);
997 		return false;
998 	}
999 
1000 	index = map_index_from_stream(core_power, current_stream);
1001 
1002 	if (index >= core_power->num_entities) {
1003 		/* trying to replace a non-existent stream */
1004 		BREAK_TO_DEBUGGER();
1005 		DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
1006 							WPP_BIT_FLAG_Firmware_PsrState,
1007 							"mod_power: replace_stream: ERROR: index=%u >= num_entities=%d stream=%p",
1008 							index,
1009 							core_power->num_entities,
1010 							current_stream);
1011 		return false;
1012 	}
1013 
1014 	dc_stream_release(core_power->map[index].stream);
1015 	dc_stream_retain(new_stream);
1016 	core_power->map[index].stream = new_stream;
1017 	core_power->map[index].caps = new_caps;
1018 	memset(core_power->map[index].psr_context, 0, sizeof(struct mod_power_psr_context));
1019 
1020 	return true;
1021 }
1022 
1023 static bool set_backlight_millinits_aux(struct core_power *core_power,
1024 		struct dc_stream_state *stream,
1025 		unsigned int backlight_millinits,
1026 		unsigned int transition_time_millisec,
1027 		unsigned int inst)
1028 {
1029 	struct dc_link *link = NULL;
1030 
1031 	if (core_power == NULL)
1032 		return false;
1033 
1034 	if (stream == NULL)
1035 		return true;
1036 
1037 	link = dc_stream_get_link(stream);
1038 
1039 	return dc_link_set_backlight_level_nits(link, core_power->bl_state[inst].isHDR,
1040 			backlight_millinits, transition_time_millisec);
1041 }
1042 
1043 static bool set_backlight(struct core_power *core_power,
1044 		struct dc_stream_state *stream,
1045 		struct set_backlight_level_params *backlight_level_params,
1046 		unsigned int inst)
1047 {
1048 	bool retv = false;
1049 	unsigned int frame_ramp = 0;
1050 	unsigned int vsync_rate_hz;
1051 	union dmcu_abm_set_bl_params params;
1052 	const struct dc_link *link = NULL;
1053 	unsigned int backlight_pwm_u16_16 = backlight_level_params->backlight_pwm_u16_16;
1054 	unsigned int transition_time_millisec = backlight_level_params->transition_time_in_ms;
1055 
1056 	if (core_power == NULL)
1057 		return false;
1058 
1059 	core_power->bl_state[inst].backlight_pwm = backlight_pwm_u16_16;
1060 
1061 	if (stream == NULL)
1062 		return true;
1063 
1064 	if (stream->link->connector_signal != SIGNAL_TYPE_EDP)
1065 		return false;
1066 
1067 	if (transition_time_millisec != 0) {
1068 		unsigned int v_total =
1069 			(stream->adjust.v_total_max == 0) ? stream->timing.v_total : stream->adjust.v_total_max;
1070 
1071 		vsync_rate_hz = (unsigned int)div_u64(div_u64((stream->
1072 			timing.pix_clk_100hz * 100),
1073 			v_total),
1074 			stream->timing.h_total);
1075 
1076 		if (core_power->bl_state[inst].smooth_brightness_enabled)
1077 			frame_ramp = ((vsync_rate_hz *
1078 				transition_time_millisec) + 500) / 1000;
1079 	}
1080 
1081 	core_power->bl_state[inst].frame_ramp = frame_ramp;
1082 	params.u32All = 0;
1083 	params.bits.gradual_change = (frame_ramp > 0);
1084 	params.bits.frame_ramp = frame_ramp;
1085 	link = dc_stream_get_link(stream);
1086 
1087 	mod_power_set_psr_event(&core_power->public, stream, true, psr_event_hw_programming, true);
1088 	mod_power_set_replay_event(&core_power->public, stream, true, replay_event_hw_programming, true);
1089 
1090 	backlight_level_params->frame_ramp = params.u32All;
1091 	retv = dc_link_set_backlight_level(link, backlight_level_params);
1092 
1093 	mod_power_set_psr_event(&core_power->public, stream, false, psr_event_hw_programming, false);
1094 	mod_power_set_replay_event(&core_power->public, stream, false, replay_event_hw_programming, false);
1095 
1096 	return retv;
1097 }
1098 
1099 static void fill_backlight_level_params(struct core_power *core_power,
1100 	struct set_backlight_level_params *backlight_level_params,
1101 	int panel_inst, uint8_t aux_inst, unsigned int backlight_pwm,
1102 	enum backlight_control_type backlight_control_type,
1103 	unsigned int backlight_millinit, unsigned int transition_time_millisec,
1104 	bool is_hdr)
1105 {
1106 	struct pwr_backlight_properties *bl_prop = &core_power->bl_prop[panel_inst];
1107 
1108 	backlight_level_params->aux_inst = aux_inst;
1109 	backlight_level_params->backlight_pwm_u16_16 = backlight_pwm;
1110 	backlight_level_params->control_type = backlight_control_type;
1111 	backlight_level_params->backlight_millinits = backlight_millinit;
1112 	backlight_level_params->transition_time_in_ms = transition_time_millisec;
1113 	backlight_level_params->min_luminance = bl_prop->min_brightness_millinits;
1114 	backlight_level_params->max_luminance = bl_prop->max_brightness_millinits;
1115 	backlight_level_params->min_backlight_pwm = bl_prop->min_backlight_pwm;
1116 	backlight_level_params->max_backlight_pwm = bl_prop->max_backlight_pwm;
1117 
1118 	if (backlight_control_type == BACKLIGHT_CONTROL_AMD_AUX && !is_hdr)
1119 		backlight_level_params->control_type = BACKLIGHT_CONTROL_PWM;
1120 }
1121 
1122 bool mod_power_set_backlight_nits(struct mod_power *mod_power,
1123 		struct dc_stream_state *stream,
1124 		unsigned int backlight_millinit,
1125 		unsigned int transition_time_millisec,
1126 		bool skip_aux,
1127 		bool is_hdr)
1128 {
1129 	struct core_power *core_power = NULL;
1130 	unsigned int backlight_pwm;
1131 	unsigned int panel_inst = 0;
1132 	struct set_backlight_level_params backlight_level_params = { 0 };
1133 	const struct dc_link *link = NULL;
1134 	uint8_t aux_inst = 0;
1135 
1136 	if (mod_power == NULL)
1137 		return false;
1138 
1139 	core_power = MOD_POWER_TO_CORE(mod_power);
1140 	link = dc_stream_get_link(stream);
1141 
1142 	ASSERT(link->ddc->ddc_pin->hw_info.ddc_channel <= 0xFF);
1143 	aux_inst = (uint8_t)link->ddc->ddc_pin->hw_info.ddc_channel;
1144 
1145 	if (!dc_get_edp_link_panel_inst(core_power->dc, stream->link, &panel_inst))
1146 		return false;
1147 
1148 	if (!skip_aux) {
1149 		if (!set_backlight_millinits_aux(core_power, stream,
1150 						backlight_millinit, transition_time_millisec, panel_inst))
1151 			return false;
1152 	}
1153 // always send both AUX (above) and PWM (below)
1154 	core_power->bl_state[panel_inst].backlight_millinit = backlight_millinit;
1155 
1156 	core_power->bl_state[panel_inst].backlight_millipercent =
1157 		backlight_millinit_to_millipercent(
1158 				core_power, backlight_millinit, panel_inst);
1159 
1160 	backlight_pwm = backlight_millinit_to_pwm(
1161 				core_power, backlight_millinit, panel_inst);
1162 
1163 	fill_backlight_level_params(core_power, &backlight_level_params, panel_inst, aux_inst, backlight_pwm,
1164 		link->backlight_control_type, backlight_millinit, transition_time_millisec, is_hdr);
1165 
1166 	return set_backlight(core_power, stream,
1167 			&backlight_level_params, panel_inst);
1168 }
1169 
1170 
1171 bool mod_power_backlight_percent_to_nits(struct mod_power *mod_power,
1172 		struct dc_stream_state *stream,
1173 		unsigned int backlight_millipercent,
1174 		unsigned int *backlight_millinit)
1175 {
1176 	struct core_power *core_power = NULL;
1177 	unsigned int inst = 0;
1178 
1179 	if (mod_power == NULL)
1180 		return false;
1181 
1182 	core_power = MOD_POWER_TO_CORE(mod_power);
1183 
1184 	if (!dc_get_edp_link_panel_inst(core_power->dc, stream->link, &inst))
1185 		return false;
1186 
1187 	*backlight_millinit = backlight_millipercent_to_millinit(
1188 			core_power, backlight_millipercent, inst);
1189 	return true;
1190 }
1191 
1192 bool mod_power_backlight_nits_to_percent(struct mod_power *mod_power,
1193 		struct dc_stream_state *stream,
1194 		unsigned int backlight_millinit,
1195 		unsigned int *backlight_millipercent)
1196 {
1197 	struct core_power *core_power = NULL;
1198 	unsigned int inst = 0;
1199 
1200 	if (mod_power == NULL)
1201 		return false;
1202 
1203 	core_power = MOD_POWER_TO_CORE(mod_power);
1204 
1205 	if (!dc_get_edp_link_panel_inst(core_power->dc, stream->link, &inst))
1206 		return false;
1207 
1208 	*backlight_millipercent = backlight_millinit_to_millipercent(
1209 			core_power, backlight_millinit, inst);
1210 	return true;
1211 }
1212 
1213 bool mod_power_set_backlight_percent(struct mod_power *mod_power,
1214 		struct dc_stream_state *stream,
1215 		unsigned int backlight_millipercent,
1216 		unsigned int transition_time_millisec,
1217 		bool is_hdr)
1218 {
1219 	struct core_power *core_power = NULL;
1220 	struct set_backlight_level_params backlight_level_params = { 0 };
1221 	const struct dc_link *link = NULL;
1222 	unsigned int backlight_pwm;
1223 	unsigned int panel_inst = 0;
1224 	uint8_t aux_inst = 0;
1225 
1226 	if (mod_power == NULL)
1227 		return false;
1228 
1229 	core_power = MOD_POWER_TO_CORE(mod_power);
1230 	link = dc_stream_get_link(stream);
1231 	ASSERT(link->ddc->ddc_pin->hw_info.ddc_channel <= 0xFF);
1232 	aux_inst = (uint8_t)link->ddc->ddc_pin->hw_info.ddc_channel;
1233 
1234 	if (!dc_get_edp_link_panel_inst(core_power->dc, stream->link, &panel_inst))
1235 		return false;
1236 	core_power->bl_state[panel_inst].backlight_millipercent = backlight_millipercent;
1237 
1238 	core_power->bl_state[panel_inst].backlight_millinit =
1239 		backlight_millipercent_to_millinit(
1240 				core_power, backlight_millipercent, panel_inst);
1241 
1242 	backlight_pwm = backlight_millipercent_to_pwm(
1243 				core_power, backlight_millipercent, panel_inst);
1244 
1245 	fill_backlight_level_params(core_power, &backlight_level_params, panel_inst,
1246 		aux_inst, backlight_pwm, link->backlight_control_type,
1247 		core_power->bl_state[panel_inst].backlight_millinit, transition_time_millisec, is_hdr);
1248 
1249 	return set_backlight(core_power, stream,
1250 			&backlight_level_params, panel_inst);
1251 }
1252 
1253 void mod_power_update_backlight(struct mod_power *mod_power,
1254 		struct dc_stream_state *stream,
1255 		unsigned int backlight_millipercent)
1256 {
1257 	struct core_power *core_power = NULL;
1258 	unsigned int inst = 0;
1259 
1260 	if (mod_power == NULL)
1261 		return;
1262 
1263 	core_power = MOD_POWER_TO_CORE(mod_power);
1264 
1265 	if (!dc_get_edp_link_panel_inst(core_power->dc, stream->link, &inst))
1266 		return;
1267 	core_power->bl_state[inst].backlight_millipercent = backlight_millipercent;
1268 
1269 	core_power->bl_state[inst].backlight_millinit =
1270 		backlight_millipercent_to_millinit(
1271 			core_power, backlight_millipercent, inst);
1272 
1273 	core_power->bl_state[inst].backlight_pwm = backlight_millipercent_to_pwm(
1274 		core_power, backlight_millipercent, inst);
1275 }
1276 
1277 void mod_power_update_backlight_nits(struct mod_power *mod_power,
1278 		struct dc_stream_state *stream,
1279 		unsigned int backlight_millinit)
1280 {
1281 	struct core_power *core_power = NULL;
1282 	unsigned int inst = 0;
1283 
1284 	if (mod_power == NULL)
1285 		return;
1286 
1287 	core_power = MOD_POWER_TO_CORE(mod_power);
1288 
1289 	if (!dc_get_edp_link_panel_inst(core_power->dc, stream->link, &inst))
1290 		return;
1291 
1292 	core_power->bl_state[inst].backlight_millinit = backlight_millinit;
1293 
1294 	core_power->bl_state[inst].backlight_millipercent = backlight_millinit_to_millipercent(
1295 		core_power, backlight_millinit, inst);
1296 	core_power->bl_state[inst].backlight_pwm = backlight_millinit_to_pwm(
1297 		core_power, backlight_millinit, inst);
1298 }
1299 
1300 bool mod_power_get_backlight_pwm(struct mod_power *mod_power,
1301 		unsigned int *backlight_pwm,
1302 		unsigned int inst)
1303 {
1304 	struct core_power *core_power = NULL;
1305 
1306 	if (mod_power == NULL)
1307 		return false;
1308 
1309 	core_power = MOD_POWER_TO_CORE(mod_power);
1310 
1311 	*backlight_pwm = core_power->bl_state[inst].backlight_pwm;
1312 
1313 	return true;
1314 }
1315 
1316 bool mod_power_get_backlight_nits(struct mod_power *mod_power,
1317 		unsigned int *backlight_millinit,
1318 		unsigned int inst)
1319 {
1320 	struct core_power *core_power = NULL;
1321 
1322 	if (mod_power == NULL)
1323 		return false;
1324 
1325 	core_power = MOD_POWER_TO_CORE(mod_power);
1326 
1327 	*backlight_millinit = core_power->bl_state[inst].backlight_millinit;
1328 
1329 	return true;
1330 }
1331 
1332 bool mod_power_get_backlight_percent(struct mod_power *mod_power,
1333 		unsigned int *backlight_millipercent,
1334 		unsigned int inst)
1335 {
1336 	struct core_power *core_power = NULL;
1337 
1338 	if (mod_power == NULL)
1339 		return false;
1340 
1341 	core_power = MOD_POWER_TO_CORE(mod_power);
1342 
1343 	*backlight_millipercent = core_power->bl_state[inst].backlight_millipercent;
1344 
1345 	return true;
1346 }
1347 
1348 bool mod_power_get_hw_target_backlight_pwm_nits(struct mod_power *mod_power,
1349 		const struct dc_link *link,
1350 		unsigned int *backlight_millinit,
1351 		unsigned int inst)
1352 {
1353 	struct core_power *core_power = NULL;
1354 	unsigned int backlight_u16_16 = 0;
1355 
1356 	if (mod_power == NULL)
1357 		return false;
1358 
1359 	core_power = MOD_POWER_TO_CORE(mod_power);
1360 
1361 	if (mod_power_get_hw_target_backlight_pwm(mod_power, link,
1362 							&backlight_u16_16)) {
1363 		*backlight_millinit =
1364 			backlight_pwm_to_millinit(core_power,
1365 					backlight_u16_16, inst);
1366 		return true;
1367 	}
1368 	return false;
1369 }
1370 
1371 bool mod_power_get_hw_target_backlight_pwm_percent(struct mod_power *mod_power,
1372 		const struct dc_link *link,
1373 		unsigned int *backlight_millipercent,
1374 		unsigned int inst)
1375 {
1376 	struct core_power *core_power = NULL;
1377 	unsigned int backlight_u16_16 = 0;
1378 
1379 	if (mod_power == NULL)
1380 		return false;
1381 
1382 	core_power = MOD_POWER_TO_CORE(mod_power);
1383 
1384 	if (mod_power_get_hw_target_backlight_pwm(mod_power, link,
1385 							&backlight_u16_16)) {
1386 		*backlight_millipercent =
1387 			backlight_pwm_to_millipercent(core_power,
1388 					backlight_u16_16, inst);
1389 		return true;
1390 	}
1391 	return false;
1392 }
1393 
1394 bool mod_power_get_hw_target_backlight_pwm(struct mod_power *mod_power,
1395 		const struct dc_link *link,
1396 		unsigned int *backlight_u16_16)
1397 {
1398 	if (mod_power == NULL)
1399 		return false;
1400 
1401 	*backlight_u16_16 = dc_link_get_target_backlight_pwm(link);
1402 
1403 	return true;
1404 }
1405 
1406 bool mod_power_get_hw_backlight_pwm_nits(struct mod_power *mod_power,
1407 		const struct dc_link *link,
1408 		unsigned int *backlight_millinit,
1409 		unsigned int inst)
1410 {
1411 	struct core_power *core_power = NULL;
1412 	unsigned int backlight_u16_16 = 0;
1413 
1414 	if (mod_power == NULL)
1415 		return false;
1416 
1417 	core_power = MOD_POWER_TO_CORE(mod_power);
1418 
1419 	if (mod_power_get_hw_backlight_pwm(mod_power, link, &backlight_u16_16)) {
1420 		*backlight_millinit =
1421 			backlight_pwm_to_millinit(core_power,
1422 					backlight_u16_16, inst);
1423 		return true;
1424 	}
1425 	return false;
1426 }
1427 
1428 bool mod_power_get_hw_backlight_aux_nits(struct mod_power *mod_power,
1429 		struct dc_stream_state **streams, int num_streams,
1430 		unsigned int *backlight_millinit_avg,
1431 		unsigned int *backlight_millinit_peak)
1432 {
1433 	struct core_power *core_power = NULL;
1434 	struct dc_link *link = NULL;
1435 	unsigned int stream_index;
1436 
1437 	if (mod_power == NULL)
1438 		return false;
1439 
1440 	core_power = MOD_POWER_TO_CORE(mod_power);
1441 
1442 	if (core_power == NULL)
1443 		return false;
1444 
1445 	if (num_streams < 1)
1446 		return true;
1447 
1448 	for (stream_index = 0; stream_index < num_streams; stream_index++)
1449 		if (streams[stream_index]->link->connector_signal == SIGNAL_TYPE_EDP ||
1450 				streams[stream_index]->link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT)
1451 			break;
1452 
1453 	if (stream_index == num_streams)
1454 		return false;
1455 
1456 	link = dc_stream_get_link(streams[stream_index]);
1457 	if (link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 0)
1458 		return false;
1459 
1460 	return dc_link_get_backlight_level_nits(link, backlight_millinit_avg,
1461 			backlight_millinit_peak);
1462 }
1463 
1464 bool mod_power_get_hw_backlight_pwm_percent(struct mod_power *mod_power,
1465 		const struct dc_link *link,
1466 		unsigned int *backlight_millipercent,
1467 		unsigned int inst)
1468 {
1469 	struct core_power *core_power = NULL;
1470 	unsigned int backlight_u16_16 = 0;
1471 
1472 	if (mod_power == NULL)
1473 		return false;
1474 
1475 	core_power = MOD_POWER_TO_CORE(mod_power);
1476 
1477 	if (mod_power_get_hw_backlight_pwm(mod_power, link, &backlight_u16_16)) {
1478 		*backlight_millipercent =
1479 			backlight_pwm_to_millipercent(core_power,
1480 					backlight_u16_16, inst);
1481 		return true;
1482 	}
1483 	return false;
1484 }
1485 
1486 bool mod_power_get_hw_backlight_pwm(struct mod_power *mod_power,
1487 		const struct dc_link *link,
1488 		unsigned int *backlight_u16_16)
1489 {
1490 	if (mod_power == NULL)
1491 		return false;
1492 
1493 	*backlight_u16_16 = dc_link_get_backlight_level(link);
1494 
1495 	return true;
1496 }
1497 
1498 bool mod_power_get_panel_backlight_boundaries(
1499 				struct mod_power *mod_power,
1500 				unsigned int *out_min_backlight,
1501 				unsigned int *out_max_backlight,
1502 				unsigned int *out_ac_backlight_percent,
1503 				unsigned int *out_dc_backlight_percent,
1504 				unsigned int inst)
1505 {
1506 	struct core_power *core_power = NULL;
1507 
1508 	if (mod_power == NULL)
1509 		return false;
1510 
1511 	core_power = MOD_POWER_TO_CORE(mod_power);
1512 
1513 	/* If cache was successfully updated,
1514 	 * copy the values to output structure and return success
1515 	 */
1516 	if (core_power->bl_prop[inst].backlight_caps_valid) {
1517 		*out_min_backlight = core_power->bl_prop[inst].backlight_lut[0];
1518 		*out_max_backlight =
1519 			core_power->bl_prop[inst].backlight_lut[
1520 				core_power->bl_prop[inst].num_backlight_levels - 1];
1521 		*out_ac_backlight_percent =
1522 			core_power->bl_prop[inst].ac_backlight_percent;
1523 		*out_dc_backlight_percent =
1524 			core_power->bl_prop[inst].dc_backlight_percent;
1525 
1526 		return true;
1527 	}
1528 
1529 	return false;
1530 }
1531 
1532 bool mod_power_set_smooth_brightness(struct mod_power *mod_power,
1533 		bool enable_brightness,
1534 		unsigned int inst)
1535 {
1536 	struct core_power *core_power = NULL;
1537 
1538 	if (mod_power == NULL)
1539 		return false;
1540 
1541 	core_power = MOD_POWER_TO_CORE(mod_power);
1542 
1543 	core_power->bl_state[inst].smooth_brightness_enabled = enable_brightness;
1544 
1545 	return true;
1546 }
1547 
1548 bool mod_power_notify_mode_change(struct mod_power *mod_power,
1549 		const struct dc_stream_state *stream,
1550 		bool is_hdr)
1551 {
1552 	unsigned int stream_index = 0;
1553 	struct core_power *core_power = NULL;
1554 	struct dc_link *link = NULL;
1555 	struct psr_config psr_config = {0};
1556 	struct psr_context psr_context = {0};
1557 	struct dc *dc = NULL;
1558 	unsigned int panel_inst = 0;
1559 	int active_psr_events = 0;
1560 	int active_replay_events = 0;
1561 
1562 	if ((mod_power == NULL) || (stream == NULL))
1563 		return false;
1564 
1565 	core_power = MOD_POWER_TO_CORE(mod_power);
1566 
1567 	if (core_power->num_entities == 0)
1568 		return false;
1569 
1570 	stream_index = map_index_from_stream(core_power, stream);
1571 
1572 	if (stream_index >= core_power->num_entities)
1573 		return false;
1574 
1575 	dc = core_power->dc;
1576 	link = dc_stream_get_link(stream);
1577 	active_psr_events = core_power->map[stream_index].psr_events;
1578 	active_replay_events = core_power->map[stream_index].replay_events;
1579 	if (link != NULL && dc_get_edp_link_panel_inst(dc, link, &panel_inst)) {
1580 		struct set_backlight_level_params backlight_level_params = { 0 };
1581 
1582 		ASSERT(link->ddc->ddc_pin->hw_info.ddc_channel <= 0xFF);
1583 		uint8_t aux_inst = (uint8_t)link->ddc->ddc_pin->hw_info.ddc_channel;
1584 
1585 		if (link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1 ||
1586 			link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1)
1587 			dc_link_set_backlight_level_nits(link, core_power->bl_state[panel_inst].isHDR,
1588 				core_power->bl_state[panel_inst].backlight_millinit, 0);
1589 
1590 		backlight_level_params.frame_ramp = 0;
1591 
1592 		fill_backlight_level_params(core_power, &backlight_level_params, panel_inst, aux_inst,
1593 			core_power->bl_state[panel_inst].backlight_pwm, link->backlight_control_type,
1594 			core_power->bl_state[panel_inst].backlight_millinit, 0, is_hdr);
1595 
1596 		dc_link_set_backlight_level(link, &backlight_level_params);
1597 
1598 		mod_power_calc_psr_configs(&psr_config, link, stream);
1599 
1600 		psr_config.psr_exit_link_training_required = core_power->map[stream_index].caps->psr_exit_link_training_required;
1601 
1602 		if (dc->ctx->asic_id.chip_family >= AMDGPU_FAMILY_GC_11_0_1)
1603 			psr_config.allow_smu_optimizations =
1604 					core_power->psr_smu_optimizations_support && dc_is_embedded_signal(stream->signal);
1605 		else
1606 			psr_config.allow_smu_optimizations =
1607 					core_power->psr_smu_optimizations_support && mod_power_only_edp(dc->current_state, stream);
1608 
1609 		psr_config.allow_multi_disp_optimizations = core_power->multi_disp_optimizations_support;
1610 
1611 		psr_config.rate_control_caps = core_power->map[stream_index].caps->rate_control_caps;
1612 
1613 		if (active_psr_events & psr_event_os_request_force_ffu) {
1614 			psr_config.os_request_force_ffu = true;
1615 		}
1616 		/*
1617 		* DSC support:
1618 		* DSC slice height value must be 'mod' by su_y_granularity.
1619 		* According to Panel Vendor, there might be varied conditions to fulfill.
1620 		* Right now, DSC slice height value must be multiple of su_y_granularity.
1621 		*
1622 		* The value of DSC slice height is determined in DSC Driver but it does not
1623 		* propagated out here, so we need to calculate it as below 'slice_height'.
1624 		*/
1625 		psr_su_set_dsc_slice_height(dc, link,
1626 					(struct dc_stream_state *) stream,
1627 					&psr_config);
1628 
1629 		dc_link_setup_psr(link, stream, &psr_config, &psr_context);
1630 
1631 		link->replay_settings.replay_smu_opt_enable =
1632 			(link->replay_settings.config.replay_smu_opt_supported &&
1633 			mod_power_only_edp(dc->current_state, stream));
1634 
1635 		if (active_replay_events & replay_event_os_request_force_ffu) {
1636 			link->replay_settings.config.os_request_force_ffu = true;
1637 		}
1638 
1639 		if (dc_is_embedded_signal(stream->signal))
1640 			dc->link_srv->dp_setup_replay(link, stream);
1641 	}
1642 
1643 	return true;
1644 }
1645 
1646 bool mod_power_varibright_feature_enable(struct mod_power *mod_power, bool enable,
1647 		struct dc_stream_update *stream_update)
1648 {
1649 	struct core_power *core_power = NULL;
1650 
1651 	if (mod_power == NULL)
1652 		return false;
1653 
1654 	core_power = MOD_POWER_TO_CORE(mod_power);
1655 	core_power->varibright_prop.varibright_user_enable = enable;
1656 
1657 	/* find abm hw level to program, and save in stream update */
1658 	varibright_set_level(core_power);
1659 	*stream_update->abm_level = core_power->varibright_prop.varibright_hw_level;
1660 
1661 	DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION,
1662 						WPP_BIT_FLAG_Backlight_ABM,
1663 						">ABM feature enable: enable=%u su->varibright_level=%u varibright_hw_level=%u",
1664 						(unsigned int) enable,
1665 						*stream_update->abm_level,
1666 						core_power->varibright_prop.varibright_hw_level);
1667 	return true;
1668 }
1669 
1670 bool mod_power_varibright_activate(struct mod_power *mod_power,
1671 		bool activate,
1672 		struct dc_stream_update *stream_update)
1673 {
1674 	struct core_power *core_power = NULL;
1675 
1676 	if (mod_power == NULL)
1677 		return false;
1678 
1679 	core_power = MOD_POWER_TO_CORE(mod_power);
1680 	core_power->varibright_prop.varibright_active = activate;
1681 
1682 	/* find abm hw level to program, and save in stream update */
1683 	varibright_set_level(core_power);
1684 	*stream_update->abm_level = core_power->varibright_prop.varibright_hw_level;
1685 
1686 	DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION,
1687 						WPP_BIT_FLAG_Backlight_ABM,
1688 						">ABM activate: activate=%u su->varibright_level=%u",
1689 						(unsigned int) activate,
1690 						*stream_update->abm_level);
1691 	return true;
1692 }
1693 bool mod_power_varibright_set_level(struct mod_power *mod_power, unsigned int level,
1694 		struct dc_stream_update *stream_update)
1695 {
1696 	struct core_power *core_power = NULL;
1697 
1698 	if (mod_power == NULL)
1699 		return false;
1700 
1701 	core_power = MOD_POWER_TO_CORE(mod_power);
1702 	core_power->varibright_prop.varibright_level = level;
1703 	core_power->varibright_prop.varibright_hw_level = level;
1704 
1705 	/* find abm hw level to program, and save in stream update */
1706 	varibright_set_level(core_power);
1707 	*stream_update->abm_level = core_power->varibright_prop.varibright_hw_level;
1708 
1709 	DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION,
1710 						WPP_BIT_FLAG_Backlight_ABM,
1711 						">ABM set level: level=%u -> (varibright_level=%u varibright_hw_level=%u) -> su->varibright_level=%u",
1712 						level,
1713 						core_power->varibright_prop.varibright_level,
1714 						core_power->varibright_prop.varibright_hw_level,
1715 						*stream_update->abm_level);
1716 	return true;
1717 }
1718 
1719 bool mod_power_varibright_set_hw_level(struct mod_power *mod_power, unsigned int level,
1720 		struct dc_stream_update *stream_update)
1721 {
1722 	struct core_power *core_power = NULL;
1723 
1724 	if (mod_power == NULL)
1725 		return false;
1726 
1727 	core_power = MOD_POWER_TO_CORE(mod_power);
1728 
1729 	if (level == 0 || level == ABM_LEVEL_IMMEDIATE_DISABLE)
1730 		core_power->varibright_prop.varibright_active = 0;
1731 	else
1732 		core_power->varibright_prop.varibright_active = 1;
1733 	core_power->varibright_prop.varibright_hw_level = level;
1734 	*stream_update->abm_level = core_power->varibright_prop.varibright_hw_level;
1735 
1736 	DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION,
1737 						WPP_BIT_FLAG_Backlight_ABM,
1738 						">ABM set level: level=%u -> (varibright_level=%u varibright_hw_level=%u) -> su->varibright_level=%u",
1739 						level,
1740 						core_power->varibright_prop.varibright_level,
1741 						core_power->varibright_prop.varibright_hw_level,
1742 						*stream_update->abm_level);
1743 	return true;
1744 }
1745 
1746 bool mod_power_get_varibright_level(struct mod_power *mod_power,
1747 		unsigned int *varibright_level)
1748 {
1749 	struct core_power *core_power = NULL;
1750 
1751 	if (mod_power == NULL)
1752 		return false;
1753 
1754 	core_power = MOD_POWER_TO_CORE(mod_power);
1755 
1756 	*varibright_level = core_power->varibright_prop.varibright_level;
1757 
1758 	DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION,
1759 						WPP_BIT_FLAG_Backlight_ABM,
1760 						">get varibright level: cp->varibright_level=%u",
1761 						*varibright_level);
1762 	return true;
1763 
1764 }
1765 
1766 bool mod_power_get_varibright_hw_level(struct mod_power *mod_power,
1767 		unsigned int *varibright_level)
1768 {
1769 	struct core_power *core_power = NULL;
1770 
1771 	if (mod_power == NULL)
1772 		return false;
1773 
1774 	core_power = MOD_POWER_TO_CORE(mod_power);
1775 
1776 	*varibright_level = core_power->varibright_prop.varibright_hw_level;
1777 	DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION,
1778 						WPP_BIT_FLAG_Backlight_ABM,
1779 						">get varibright HW level: hw_level=%u",
1780 						*varibright_level);
1781 	return true;
1782 }
1783 
1784 bool mod_power_get_varibright_default_level(struct mod_power *mod_power,
1785 		unsigned int *varibright_level)
1786 {
1787 	struct core_power *core_power = NULL;
1788 
1789 	if (mod_power == NULL)
1790 		return false;
1791 
1792 	core_power = MOD_POWER_TO_CORE(mod_power);
1793 
1794 	*varibright_level = core_power->varibright_prop.def_varibright_level;
1795 	DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION,
1796 						WPP_BIT_FLAG_Backlight_ABM,
1797 						">get varibright default level: def_varibright_level=%u",
1798 						*varibright_level);
1799 	return true;
1800 }
1801 
1802 bool mod_power_get_varibright_enable(struct mod_power *mod_power,
1803 		bool *varibright_enable)
1804 {
1805 	struct core_power *core_power = NULL;
1806 
1807 	if (mod_power == NULL)
1808 		return false;
1809 
1810 	core_power = MOD_POWER_TO_CORE(mod_power);
1811 
1812 	*varibright_enable = core_power->varibright_prop.varibright_user_enable;
1813 	DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION,
1814 				WPP_BIT_FLAG_Backlight_ABM,
1815 				">get varibright enable state: varibright_user_enable=%u",
1816 				(unsigned int) (*varibright_enable));
1817 	return true;
1818 }
1819 
1820 bool mod_power_is_abm_active(struct mod_power *mod_power,
1821 		const struct dc_link *link,
1822 		unsigned int inst)
1823 {
1824 	unsigned int user_backlight = 0;
1825 	unsigned int current_backlight = 0;
1826 	bool is_active = false;
1827 
1828 	if (mod_power == NULL)
1829 		return false;
1830 
1831 	mod_power_get_backlight_pwm(mod_power, &user_backlight, inst);
1832 	mod_power_get_hw_backlight_pwm(mod_power, link,	&current_backlight);
1833 
1834 	if (user_backlight != current_backlight)
1835 		is_active = true;
1836 	else
1837 		is_active = false;
1838 	DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION,
1839 						WPP_BIT_FLAG_Backlight_ABM,
1840 						">get ABM active state: is_active=%u (user_backlight_pwm=%u, current_backlight_pwm=%u)",
1841 						(unsigned int)is_active,
1842 						user_backlight,
1843 						current_backlight);
1844 	return is_active;
1845 }
1846 
1847 
1848 static void mod_power_psr_set_power_opt(struct mod_power *mod_power,
1849 	struct dc_stream_state *stream,
1850 	unsigned int active_psr_events,
1851 	bool psr_enable_request)
1852 {
1853 	(void)psr_enable_request;
1854 	struct core_power *core_power = NULL;
1855 	struct dc_link *link = NULL;
1856 	unsigned int stream_index = 0;
1857 	unsigned int power_opt = 0;
1858 
1859 	if (!stream)
1860 		return;
1861 
1862 	core_power = MOD_POWER_TO_CORE(mod_power);
1863 	stream_index = map_index_from_stream(core_power, stream);
1864 	if (!core_power->map[stream_index].caps->psr_version)
1865 		return;
1866 
1867 	link = dc_stream_get_link(stream);
1868 
1869 	if (active_psr_events == 0) {
1870 		/* Static Screen */
1871 		power_opt |= (psr_power_opt_smu_opt_static_screen | psr_power_opt_z10_static_screen |
1872 					psr_power_opt_ds_disable_allow);
1873 	}
1874 
1875 	/* psr_power_opt_flag is a configuration parameter into the module that determines
1876 	 * which optimizations to enable during psr
1877 	 */
1878 	power_opt &= core_power->map[stream_index].caps->psr_power_opt_flag;
1879 	if (core_power->map[stream_index].psr_power_opt != power_opt) {
1880 		DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_VERBOSE,
1881 				WPP_BIT_FLAG_Firmware_PsrState,
1882 				"mod_power set_power_opt: psr_power_opt=0x%04x, power_opt=0x%04x"
1883 				"active_psr_events=0x%04x, psr_power_opt_flag=0x%04x",
1884 				core_power->map[stream_index].psr_power_opt,
1885 				power_opt,
1886 				active_psr_events,
1887 				core_power->map[stream_index].caps->psr_power_opt_flag);
1888 		dc_link_set_psr_allow_active(link, NULL, false, false, &power_opt);
1889 		core_power->map[stream_index].psr_power_opt = power_opt;
1890 	}
1891 }
1892 
1893 static bool set_psr_enable(struct mod_power *mod_power,
1894 		struct dc_stream_state *stream,
1895 		bool psr_enable,
1896 		bool wait,
1897 		bool force_static)
1898 {
1899 	struct core_power *core_power = NULL;
1900 	enum dc_psr_state state = PSR_STATE0;
1901 	unsigned int retry_count;
1902 	const unsigned int max_retry = 1000;
1903 	struct dc_link *link = NULL;
1904 
1905 	if (mod_power == NULL)
1906 		return false;
1907 
1908 	core_power = MOD_POWER_TO_CORE(mod_power);
1909 
1910 	if (core_power->num_entities == 0) {
1911 		DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
1912 							WPP_BIT_FLAG_Firmware_PsrState,
1913 							"set psr enable: ERROR: stream=%p num_entities=%d",
1914 							stream,
1915 							core_power->num_entities);
1916 		return false;
1917 	}
1918 
1919 	if (psr_enable)	{
1920 		unsigned int vsync_rate_hz;
1921 		struct dc_static_screen_params params = {0};
1922 
1923 		vsync_rate_hz = (unsigned int)div_u64(div_u64((
1924 				stream->timing.pix_clk_100hz * 100),
1925 				stream->timing.v_total),
1926 				stream->timing.h_total);
1927 
1928 		params.triggers.cursor_update = true;
1929 		params.triggers.overlay_update = true;
1930 		params.triggers.surface_update = true;
1931 		params.num_frames = calc_psr_num_static_frames(vsync_rate_hz);
1932 
1933 		DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
1934 							WPP_BIT_FLAG_Firmware_PsrState,
1935 							"set psr enable: CALCS: pix_clk_100hz=%u v_total=%u h_total=%u vsync_rate_hz=%u num_frames=%u",
1936 							stream->timing.pix_clk_100hz,
1937 							stream->timing.v_total,
1938 							stream->timing.h_total,
1939 							vsync_rate_hz,
1940 							params.num_frames);
1941 
1942 		dc_stream_set_static_screen_params(core_power->dc,
1943 						   &stream, 1,
1944 						   &params);
1945 	}
1946 
1947 	link = dc_stream_get_link(stream);
1948 
1949 	if (!dc_link_set_psr_allow_active(link, &psr_enable, false, force_static, NULL)) {
1950 		DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
1951 							WPP_BIT_FLAG_Firmware_PsrState,
1952 							"set psr enable: ERROR: stream=%p link=%p psr_enable=%d",
1953 							stream,
1954 							link,
1955 							psr_enable);
1956 		return false;
1957 	}
1958 
1959 	if (wait == true) {
1960 
1961 		DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
1962 							WPP_BIT_FLAG_Firmware_PsrState,
1963 							"set psr enable: BEGIN WAIT: psr_enable=%d",
1964 							(int)psr_enable);
1965 
1966 		for (retry_count = 0; retry_count <= max_retry; retry_count++) {
1967 			dc_link_get_psr_state(link, &state);
1968 			if (psr_enable) {
1969 				if (state != PSR_STATE0 &&
1970 						(!force_static || state == PSR_STATE3))
1971 					break;
1972 			} else {
1973 				if (state == PSR_STATE0)
1974 					break;
1975 			}
1976 			udelay(500);
1977 		}
1978 
1979 		DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
1980 							WPP_BIT_FLAG_Firmware_PsrState,
1981 							"set psr enable: END WAIT: psr_enable=%d",
1982 							(int)psr_enable);
1983 
1984 		/* assert if max retry hit */
1985 		if (retry_count >= max_retry) {
1986 			ASSERT(0);
1987 			DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
1988 								WPP_BIT_FLAG_Firmware_PsrState,
1989 								"set psr enable: ERROR: retry_count=%u: Unexpectedly long wait for PSR state change.",
1990 								retry_count);
1991 		}
1992 	} else {
1993 		DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
1994 							WPP_BIT_FLAG_Firmware_PsrState,
1995 							"set psr enable: PSR state change initiated (wait=false): psr_enable=%d",
1996 							(int)psr_enable);
1997 	}
1998 
1999 	return true;
2000 }
2001 
2002 bool mod_power_get_psr_event(struct mod_power *mod_power,
2003 			struct dc_stream_state *stream,
2004 			unsigned int *active_psr_events)
2005 {
2006 	struct core_power *core_power = NULL;
2007 	unsigned int stream_index = 0;
2008 
2009 	if (mod_power == NULL)
2010 		return false;
2011 
2012 	core_power = MOD_POWER_TO_CORE(mod_power);
2013 
2014 	if (core_power->num_entities == 0)
2015 		return false;
2016 
2017 	stream_index = map_index_from_stream(core_power, stream);
2018 
2019 	if (!core_power->map[stream_index].caps->psr_version)
2020 		return false;
2021 
2022 	*active_psr_events = core_power->map[stream_index].psr_events;
2023 
2024 	return true;
2025 }
2026 
2027 bool mod_power_set_psr_event(struct mod_power *mod_power,
2028 		struct dc_stream_state *stream, bool set_event,
2029 		enum psr_event event, bool wait)
2030 {
2031 	struct core_power *core_power = NULL;
2032 	unsigned int stream_index = 0;
2033 	unsigned int active_psr_events = 0;
2034 	bool psr_enable_request = false;
2035 	bool force_static = false;
2036 
2037 	if (mod_power == NULL || stream == NULL)
2038 		return false;
2039 
2040 	core_power = MOD_POWER_TO_CORE(mod_power);
2041 	stream_index = map_index_from_stream(core_power, stream);
2042 
2043 	if (core_power->num_entities == 0) {
2044 		DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
2045 							WPP_BIT_FLAG_Firmware_PsrState,
2046 							"mod_power set_psr_event: ERROR: stream=%p event=%d num_entities=%d",
2047 							stream,
2048 							(int)event,
2049 							core_power->num_entities);
2050 		return false;
2051 	}
2052 
2053 	if (!core_power->map[stream_index].caps->psr_version)
2054 		return false;
2055 
2056 	if (set_event)
2057 		core_power->map[stream_index].psr_events |= event;
2058 	else
2059 		core_power->map[stream_index].psr_events &= ~event;
2060 
2061 	active_psr_events = core_power->map[stream_index].psr_events;
2062 
2063 	// ignore other events when we're in forced psr enabled state
2064 	if (active_psr_events & psr_event_dynamic_display_switch &&
2065 			event != psr_event_dynamic_display_switch)
2066 		return false;
2067 
2068 	// ignore other events when we're in forced psr enabled state
2069 	if (active_psr_events & psr_event_os_override_hold &&
2070 			event != psr_event_os_override_hold)
2071 		return false;
2072 
2073 	// ignore other events when we're in forced psr enabled state
2074 	// dds events need to be processed while in dynamic_link_rate_control
2075 	if (active_psr_events & psr_event_dynamic_link_rate_control &&
2076 			event != psr_event_dynamic_link_rate_control &&
2077 			event != psr_event_dds_defer_stream_enable &&
2078 			event != psr_event_dynamic_display_switch)
2079 		return false;
2080 
2081 	if (active_psr_events & (psr_event_test_harness_disable_psr | psr_event_os_request_disable))
2082 		psr_enable_request = false;
2083 	else if (active_psr_events & psr_event_pause)
2084 		psr_enable_request = false;
2085 	else if (active_psr_events & psr_event_test_harness_enable_psr)
2086 		psr_enable_request = true;
2087 	else if (active_psr_events & psr_event_dynamic_display_switch) {
2088 		psr_enable_request = true;
2089 		force_static = true;
2090 	} else if (active_psr_events & psr_event_dynamic_link_rate_control) {
2091 		psr_enable_request = true;
2092 		force_static = true;
2093 	} else if (active_psr_events & psr_event_edp_panel_off_disable_psr)
2094 		psr_enable_request = false;
2095 	else if (active_psr_events & (psr_event_hw_programming |
2096 			psr_event_defer_enable |
2097 			psr_event_dds_defer_stream_enable |
2098 			psr_event_vrr_transition |
2099 			psr_event_immediate_flip))
2100 		psr_enable_request = false;
2101 	else if (active_psr_events & psr_event_big_screen_video)
2102 		psr_enable_request = true;
2103 	else if (active_psr_events & psr_event_full_screen)
2104 		psr_enable_request = false;
2105 	else if (active_psr_events & psr_event_mpo_video_selective_update)
2106 		psr_enable_request = true;
2107 	else if (active_psr_events & psr_event_vsync)
2108 		psr_enable_request = false;
2109 	else if (active_psr_events & psr_event_crc_window_active)
2110 		psr_enable_request = false;
2111 	else
2112 		psr_enable_request = true;
2113 
2114 	DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_VERBOSE,
2115 						WPP_BIT_FLAG_Firmware_PsrState,
2116 						"mod_power set_psr_event: before: psr_enabled=%d -> request: set_event=%d event=0x%04x -> result: psr_events=0x%04x psr_enable_request=%d",
2117 						(int)core_power->map[stream_index].psr_enabled,
2118 						(int)set_event,
2119 						(unsigned int)event,
2120 						(unsigned int)core_power->map[stream_index].psr_events,
2121 						(int)psr_enable_request);
2122 	mod_power_psr_set_power_opt(mod_power, stream, active_psr_events, psr_enable_request);
2123 
2124 	if (core_power->map[stream_index].psr_enabled != psr_enable_request || force_static) {
2125 		if (set_psr_enable(mod_power, stream, psr_enable_request, wait, force_static)) {
2126 			core_power->map[stream_index].psr_enabled = psr_enable_request;
2127 		}
2128 	}
2129 
2130 	return true;
2131 }
2132 
2133 bool mod_power_get_psr_state(struct mod_power *mod_power,
2134 		const struct dc_stream_state *stream,
2135 		enum dc_psr_state *state)
2136 {
2137 	struct core_power *core_power = NULL;
2138 	const struct dc_link *link = NULL;
2139 
2140 	if (!stream)
2141 		return false;
2142 
2143 	if (mod_power == NULL)
2144 		return false;
2145 
2146 	core_power = MOD_POWER_TO_CORE(mod_power);
2147 
2148 	if (core_power->num_entities == 0)
2149 		return false;
2150 
2151 	link = dc_stream_get_link(stream);
2152 	return dc_link_get_psr_state(link, state);
2153 }
2154 
2155 bool mod_power_get_psr_enabled_status(struct mod_power *mod_power,
2156 		const struct dc_stream_state *stream,
2157 		bool *psr_enabled)
2158 {
2159 	struct core_power *core_power = NULL;
2160 	unsigned int stream_index = 0;
2161 
2162 	if (mod_power == NULL)
2163 		return false;
2164 
2165 	core_power = MOD_POWER_TO_CORE(mod_power);
2166 
2167 	if (core_power->num_entities == 0)
2168 		return false;
2169 
2170 	stream_index = map_index_from_stream(core_power, stream);
2171 
2172 	if (!core_power->map[stream_index].caps->psr_version)
2173 		return false;
2174 
2175 	*psr_enabled = core_power->map[stream_index].psr_enabled;
2176 
2177 	return true;
2178 }
2179 
2180 void mod_power_psr_residency(struct mod_power *mod_power,
2181 		const struct dc_stream_state *stream,
2182 		unsigned int *residency,
2183 		const uint8_t mode)
2184 {
2185 	struct core_power *core_power = NULL;
2186 	const struct dc_link *link = NULL;
2187 
2188 	if (!stream)
2189 		return;
2190 
2191 	if (mod_power == NULL)
2192 		return;
2193 
2194 	core_power = MOD_POWER_TO_CORE(mod_power);
2195 
2196 	if (core_power->num_entities == 0)
2197 		return;
2198 
2199 	link = dc_stream_get_link(stream);
2200 
2201 	if (link != NULL)
2202 		link->dc->link_srv->edp_get_psr_residency(link, residency, mode);
2203 }
2204 bool mod_power_psr_get_active_psr_events(struct mod_power *mod_power,
2205 		const struct dc_stream_state *stream, unsigned int *active_psr_events)
2206 {
2207 	struct core_power *core_power = NULL;
2208 	unsigned int stream_index = 0;
2209 
2210 	if (!stream)
2211 		return false;
2212 
2213 	if (mod_power == NULL)
2214 		return false;
2215 
2216 	if (active_psr_events == NULL)
2217 		return false;
2218 
2219 	core_power = MOD_POWER_TO_CORE(mod_power);
2220 
2221 	if (core_power->num_entities == 0)
2222 		return false;
2223 
2224 	stream_index = map_index_from_stream(core_power, stream);
2225 
2226 	*active_psr_events = core_power->map[stream_index].psr_events;
2227 	return true;
2228 }
2229 
2230 bool mod_power_psr_set_sink_vtotal_in_psr_active(struct mod_power *mod_power,
2231 		const struct dc_stream_state *stream,
2232 		uint16_t psr_vtotal_idle,
2233 		uint16_t psr_vtotal_su)
2234 {
2235 	struct core_power *core_power = NULL;
2236 	unsigned int stream_index = 0;
2237 	const struct dc_link *link = NULL;
2238 
2239 	if (!stream)
2240 		return false;
2241 
2242 	if (mod_power == NULL)
2243 		return false;
2244 
2245 	core_power = MOD_POWER_TO_CORE(mod_power);
2246 
2247 	if (core_power->num_entities == 0)
2248 		return false;
2249 
2250 	stream_index = map_index_from_stream(core_power, stream);
2251 
2252 	if (!core_power->map[stream_index].caps->psr_version)
2253 		return false;
2254 
2255 	link = dc_stream_get_link(stream);
2256 
2257 	return link->dc->link_srv->edp_set_sink_vtotal_in_psr_active(
2258 			link, psr_vtotal_idle, psr_vtotal_su);
2259 }
2260 
2261 static bool mod_power_set_replay_active(struct dc_stream_state *stream,
2262 	bool replay_active,
2263 	bool wait,
2264 	bool force_static)
2265 {
2266 	uint64_t state;
2267 	unsigned int retry_count;
2268 	const unsigned int max_retry = 1000;
2269 	struct dc_link *link = NULL;
2270 
2271 	if (!stream)
2272 		return false;
2273 
2274 	link = dc_stream_get_link(stream);
2275 
2276 	if (!link)
2277 		return false;
2278 
2279 	if (!dc_link_set_replay_allow_active(link, &replay_active, false, force_static, NULL))
2280 		return false;
2281 
2282 	if (wait == true) {
2283 
2284 		for (retry_count = 0; retry_count <= max_retry; retry_count++) {
2285 			dc_link_get_replay_state(link, &state);
2286 			if (replay_active) {
2287 				if (state != REPLAY_STATE_0 &&
2288 					(!force_static || state == REPLAY_STATE_3))
2289 					break;
2290 			} else {
2291 				if (state == REPLAY_STATE_0)
2292 					break;
2293 			}
2294 			udelay(500);
2295 		}
2296 
2297 		/* assert if max retry hit */
2298 		if (retry_count >= max_retry)
2299 			ASSERT(0);
2300 	} else {
2301 		/* To-do: Add trace log */
2302 	}
2303 
2304 	return true;
2305 }
2306 
2307 static unsigned int mod_power_replay_setup_power_opt(struct dc_link *link,
2308 	unsigned int active_replay_events, bool is_ultra_sleep_mode)
2309 {
2310 	unsigned int power_opt = 0;
2311 
2312 	if (is_ultra_sleep_mode) {
2313 		/* Static Screen */
2314 		power_opt |= (replay_power_opt_smu_opt_static_screen | replay_power_opt_z10_static_screen);
2315 	} else if (active_replay_events & replay_event_test_harness_ultra_sleep) {
2316 		power_opt |= replay_power_opt_z10_static_screen;
2317 	}
2318 
2319 	/* replay_power_opt_flag is a configuration parameter into the module that determines
2320 	 * which optimizations to enable during replay
2321 	 */
2322 	power_opt &= link->replay_settings.config.replay_power_opt_supported;
2323 
2324 	return power_opt;
2325 }
2326 
2327 static bool mod_power_replay_set_power_opt(struct mod_power *mod_power,
2328 	struct dc_stream_state *stream,
2329 	unsigned int active_replay_events,
2330 	bool is_ultra_sleep_mode)
2331 {
2332 	(void)mod_power;
2333 	struct dc_link *link = NULL;
2334 	unsigned int power_opt = 0;
2335 
2336 	if (!stream)
2337 		return false;
2338 
2339 	link = dc_stream_get_link(stream);
2340 
2341 	if (!link || !link->replay_settings.replay_feature_enabled)
2342 		return false;
2343 
2344 	power_opt = mod_power_replay_setup_power_opt(link, active_replay_events, is_ultra_sleep_mode);
2345 
2346 	if (!dc_link_set_replay_allow_active(link, NULL, false, false, &power_opt))
2347 		return false;
2348 
2349 	return true;
2350 }
2351 
2352 bool mod_power_get_replay_event(struct mod_power *mod_power,
2353 	struct dc_stream_state *stream,
2354 	unsigned int *active_replay_events)
2355 {
2356 	struct core_power *core_power = NULL;
2357 	unsigned int stream_index = 0;
2358 
2359 	if (mod_power == NULL)
2360 		return false;
2361 
2362 	core_power = MOD_POWER_TO_CORE(mod_power);
2363 
2364 	if (core_power->num_entities == 0)
2365 		return false;
2366 
2367 	stream_index = map_index_from_stream(core_power, stream);
2368 
2369 	*active_replay_events = core_power->map[stream_index].replay_events;
2370 
2371 	return true;
2372 }
2373 
2374 static bool mod_power_update_replay_active_status(unsigned int active_replay_events,
2375 	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)
2376 {
2377 	if (!link || !coasting_vtotal || !is_full_screen_video || !is_video_playback)
2378 		return false;
2379 
2380 	// Check coasting_vtotal_table has been updated.
2381 	if (!link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_STATIC]
2382 		|| !link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_NOM])
2383 		return false;
2384 
2385 	unsigned int replay_enable_option =
2386 		link->replay_settings.config.replay_enable_option;
2387 
2388 	/* TODO: To support test harness and DDS event */
2389 
2390 	*coasting_vtotal = link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_NOM];
2391 	ASSERT(link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_NOM] <= 0xFFFF);
2392 	*frame_skip_number = (uint16_t)link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_NOM];
2393 
2394 	link->replay_settings.config.replay_timing_sync_supported = false;
2395 
2396 	*is_full_screen_video = false;
2397 
2398 	*is_ultra_sleep_mode = false;
2399 
2400 	*is_video_playback = false;
2401 
2402 	/* DSAT test scenario */
2403 	if (active_replay_events & replay_event_test_harness_mode) {
2404 		if (link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS])
2405 			*coasting_vtotal =
2406 				link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS];
2407 		if (link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS]) {
2408 			ASSERT(link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS] <= 0xFFFF);
2409 			*frame_skip_number =
2410 				(uint16_t)link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS];
2411 		}
2412 
2413 		/* During the ultra sleep mode testing, disable the timing sync in short vblank mode */
2414 		if (active_replay_events & (replay_event_test_harness_enable_replay)) {
2415 			if ((active_replay_events & replay_event_test_harness_ultra_sleep) &&
2416 				  !link->replay_settings.config.replay_support_fast_resync_in_ultra_sleep_mode)
2417 				link->replay_settings.config.replay_timing_sync_supported = false;
2418 			return true;
2419 		} else
2420 			return false;
2421 	} else if (active_replay_events & (replay_event_test_harness_enable_replay)) {
2422 		if (link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS])
2423 			*coasting_vtotal = link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS];
2424 		if (link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS]) {
2425 			uint32_t frame_skip_val =
2426 				link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS];
2427 
2428 			ASSERT(frame_skip_val <= 0xFFFF);
2429 			*frame_skip_number = (uint16_t)frame_skip_val;
2430 		}
2431 
2432 		/* During the ultra sleep mode testing, disable the timing sync in short vblank mode */
2433 		if ((active_replay_events & replay_event_test_harness_ultra_sleep) &&
2434 			  !link->replay_settings.config.replay_support_fast_resync_in_ultra_sleep_mode)
2435 			link->replay_settings.config.replay_timing_sync_supported = false;
2436 		return true;
2437 	} else if (active_replay_events & (replay_event_test_harness_disable_replay | replay_event_os_request_disable)) {
2438 		// set last set coasting vtotal
2439 		if (link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS])
2440 			*coasting_vtotal = link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS];
2441 		if (link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS]) {
2442 			uint32_t frame_skip_val =
2443 				link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS];
2444 
2445 			ASSERT(frame_skip_val <= 0xFFFF);
2446 			*frame_skip_number = (uint16_t)frame_skip_val;
2447 		}
2448 		return false;
2449 	}
2450 
2451 	/* Inactive conditions */
2452 	if (active_replay_events & (replay_event_edp_panel_off_disable_psr |
2453 			replay_event_hw_programming |
2454 			replay_event_vrr |
2455 			replay_event_immediate_flip |
2456 			replay_event_prepare_vtotal |
2457 			replay_event_vrr_transition |
2458 			replay_event_pause |
2459 			replay_event_disable_replay_while_DPMS |
2460 			replay_event_sleep_resume |
2461 			replay_event_disable_in_AC |
2462 			replay_event_disable_replay_while_detect_display |
2463 			replay_event_infopacket |
2464 			replay_event_crc_window_active))
2465 		return false;
2466 
2467 	// Full screen scenario
2468 	if (active_replay_events & replay_event_full_screen) {
2469 		if (!(replay_enable_option & pr_enable_option_full_screen))
2470 			return false;
2471 	}
2472 
2473 	/* Full screen video scenario */
2474 	if (active_replay_events & replay_event_big_screen_video) {
2475 
2476 		link->replay_settings.config.replay_timing_sync_supported = false;
2477 
2478 		if (replay_enable_option & pr_enable_option_full_screen_video_coasting) {
2479 			unsigned int fsn_vid =
2480 				link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_FULL_SCREEN_VIDEO];
2481 
2482 			*coasting_vtotal =
2483 				link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_FULL_SCREEN_VIDEO];
2484 			ASSERT(fsn_vid <= 0xFFFF);
2485 			*frame_skip_number = (uint16_t)fsn_vid;
2486 		}
2487 
2488 		*is_video_playback = true;
2489 
2490 		if ((replay_enable_option & pr_enable_option_full_screen_video) &&
2491 			(replay_enable_option & pr_enable_option_full_screen_video_coasting)) {
2492 			*is_full_screen_video = true;
2493 			return true;
2494 		} else
2495 			return false;
2496 	}
2497 
2498 	/* MPO video scenario
2499 	 * Some of the cases may contain a full screen UI layer in MPO video scenario which is
2500 	 * not the expected case to enable Replay.
2501 	 */
2502 	if ((active_replay_events & replay_event_mpo_video_selective_update) &&
2503 		!(active_replay_events & replay_event_full_screen)) {
2504 
2505 		link->replay_settings.config.replay_timing_sync_supported = false;
2506 
2507 		if (replay_enable_option & pr_enable_option_mpo_video_coasting) {
2508 			*coasting_vtotal = link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_NOM];
2509 			{
2510 				uint32_t frame_skip_val =
2511 					link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_NOM];
2512 
2513 				ASSERT(frame_skip_val <= 0xFFFF);
2514 				*frame_skip_number = (uint16_t)frame_skip_val;
2515 			}
2516 		}
2517 
2518 		*is_video_playback = true;
2519 
2520 		if (replay_enable_option & pr_enable_option_mpo_video)
2521 			return true;
2522 		else
2523 			return false;
2524 	}
2525 
2526 	/* Static screen scenario */
2527 	if (!(active_replay_events & replay_event_vsync)) {
2528 
2529 		if (replay_enable_option & pr_enable_option_static_screen_coasting) {
2530 			// Do not adjust eDP refresh rate if static screen + normal sleep mode
2531 			if ((!(link->replay_settings.config.replay_power_opt_supported &
2532 				replay_power_opt_z10_static_screen)) ||
2533 				(active_replay_events & replay_event_cursor_updating)) {
2534 				// normal sleep mode
2535 				*coasting_vtotal =
2536 					link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_NOM];
2537 				{
2538 					uint32_t frame_skip_val =
2539 						link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_NOM];
2540 
2541 					ASSERT(frame_skip_val <= 0xFFFF);
2542 					*frame_skip_number = (uint16_t)frame_skip_val;
2543 				}
2544 			} else {
2545 				// ultra sleep mode
2546 				*coasting_vtotal =
2547 					link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_STATIC];
2548 				{
2549 					uint32_t frame_skip_val =
2550 						link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_STATIC];
2551 
2552 					ASSERT(frame_skip_val <= 0xFFFF);
2553 					*frame_skip_number = (uint16_t)frame_skip_val;
2554 				}
2555 				*is_ultra_sleep_mode = true;
2556 			}
2557 		}
2558 
2559 		if (replay_enable_option & pr_enable_option_static_screen) {
2560 			if (!link->replay_settings.config.replay_support_fast_resync_in_ultra_sleep_mode)
2561 				link->replay_settings.config.replay_timing_sync_supported = false;
2562 			return true;
2563 		} else
2564 			return false;
2565 	}
2566 
2567 	/* General UI scenario */
2568 	if (active_replay_events & replay_event_general_ui) {
2569 		if (replay_enable_option & pr_enable_option_general_ui)
2570 			return true;
2571 		else
2572 			return false;
2573 	}
2574 
2575 	return false;
2576 }
2577 
2578 bool mod_power_replay_set_coasting_vtotal(struct mod_power *mod_power,
2579 	const struct dc_stream_state *stream,
2580 	uint32_t coasting_vtotal,
2581 	uint16_t frame_skip_number)
2582 {
2583 	struct core_power *core_power = NULL;
2584 	struct dc_link *link = NULL;
2585 
2586 	if (!stream)
2587 		return false;
2588 
2589 	link = dc_stream_get_link(stream);
2590 	if (!link || !link->replay_settings.replay_feature_enabled)
2591 		return false;
2592 
2593 	if (mod_power == NULL)
2594 		return false;
2595 
2596 	core_power = MOD_POWER_TO_CORE(mod_power);
2597 
2598 	if (core_power->num_entities == 0)
2599 		return false;
2600 
2601 	return link->dc->link_srv->edp_set_coasting_vtotal(link, coasting_vtotal, frame_skip_number);
2602 }
2603 
2604 void mod_power_replay_set_timing_sync_supported(struct mod_power *mod_power,
2605 	const struct dc_stream_state *stream)
2606 {
2607 	struct core_power *core_power = NULL;
2608 	struct dc_link *link = NULL;
2609 	unsigned int stream_index = 0;
2610 	union dmub_replay_cmd_set cmd_data = { 0 };
2611 
2612 	if (!stream || mod_power == NULL)
2613 		return;
2614 
2615 	core_power = MOD_POWER_TO_CORE(mod_power);
2616 	if (core_power->num_entities == 0)
2617 		return;
2618 
2619 	stream_index = map_index_from_stream(core_power, stream);
2620 	if (stream_index > core_power->num_entities) //invalid index
2621 		return;
2622 
2623 	link = dc_stream_get_link(stream);
2624 	if (!link || !link->replay_settings.replay_feature_enabled)
2625 		return;
2626 
2627 	cmd_data.sync_data.timing_sync_supported = link->replay_settings.config.replay_timing_sync_supported;
2628 
2629 	link->dc->link_srv->edp_send_replay_cmd(link, Replay_Set_Timing_Sync_Supported,
2630 		&cmd_data);
2631 }
2632 
2633 void mod_power_replay_disabled_adaptive_sync_sdp(struct mod_power *mod_power,
2634 	const struct dc_stream_state *stream, bool force_disabled)
2635 {
2636 	struct core_power *core_power = NULL;
2637 	struct dc_link *link = NULL;
2638 	unsigned int stream_index = 0;
2639 	union dmub_replay_cmd_set cmd_data = { 0 };
2640 
2641 	if (!stream || mod_power == NULL)
2642 		return;
2643 
2644 	core_power = MOD_POWER_TO_CORE(mod_power);
2645 	if (core_power->num_entities == 0)
2646 		return;
2647 
2648 	stream_index = map_index_from_stream(core_power, stream);
2649 	if (stream_index > core_power->num_entities) //invalid index
2650 		return;
2651 
2652 	link = dc_stream_get_link(stream);
2653 	if (!link || !link->replay_settings.replay_feature_enabled)
2654 		return;
2655 
2656 	cmd_data.disabled_adaptive_sync_sdp_data.force_disabled = force_disabled;
2657 
2658 	link->dc->link_srv->edp_send_replay_cmd(link, Replay_Disabled_Adaptive_Sync_SDP,
2659 		&cmd_data);
2660 }
2661 
2662 static void mod_power_replay_set_general_cmd(struct mod_power *mod_power,
2663 	const struct dc_stream_state *stream,
2664 	const enum dmub_cmd_replay_general_subtype general_cmd_type,
2665 	const uint32_t param1, const uint32_t param2)
2666 {
2667 	struct core_power *core_power = NULL;
2668 	struct dc_link *link = NULL;
2669 	unsigned int stream_index = 0;
2670 	union dmub_replay_cmd_set cmd_data = { 0 };
2671 
2672 	if (!stream || mod_power == NULL)
2673 		return;
2674 
2675 	core_power = MOD_POWER_TO_CORE(mod_power);
2676 	if (core_power->num_entities == 0)
2677 		return;
2678 
2679 	stream_index = map_index_from_stream(core_power, stream);
2680 	if (stream_index > core_power->num_entities) //invalid index
2681 		return;
2682 
2683 	link = dc_stream_get_link(stream);
2684 	if (!link || !link->replay_settings.replay_feature_enabled)
2685 		return;
2686 
2687 	cmd_data.set_general_cmd_data.subtype = general_cmd_type;
2688 	cmd_data.set_general_cmd_data.param1 = param1;
2689 	cmd_data.set_general_cmd_data.param2 = param2;
2690 	link->dc->link_srv->edp_send_replay_cmd(link, Replay_Set_General_Cmd,
2691 		&cmd_data);
2692 }
2693 
2694 void mod_power_replay_disabled_desync_error_detection(struct mod_power *mod_power,
2695 	const struct dc_stream_state *stream,  bool force_disabled)
2696 {
2697 	mod_power_replay_set_general_cmd(mod_power, stream,
2698 			REPLAY_GENERAL_CMD_DISABLED_DESYNC_ERROR_DETECTION,
2699 			force_disabled, 0);
2700 }
2701 
2702 static void mod_power_replay_set_pseudo_vtotal(struct mod_power *mod_power,
2703 	const struct dc_stream_state *stream, uint16_t vtotal)
2704 {
2705 	struct core_power *core_power = NULL;
2706 	struct dc_link *link = NULL;
2707 	unsigned int stream_index = 0;
2708 	union dmub_replay_cmd_set cmd_data = { 0 };
2709 
2710 	if (!stream || mod_power == NULL)
2711 		return;
2712 
2713 	core_power = MOD_POWER_TO_CORE(mod_power);
2714 	if (core_power->num_entities == 0)
2715 		return;
2716 
2717 	stream_index = map_index_from_stream(core_power, stream);
2718 	if (stream_index > core_power->num_entities) //invalid index
2719 		return;
2720 
2721 	link = dc_stream_get_link(stream);
2722 	if (!link || !link->replay_settings.replay_feature_enabled)
2723 		return;
2724 
2725 	cmd_data.pseudo_vtotal_data.vtotal = vtotal;
2726 
2727 	if (link->replay_settings.last_pseudo_vtotal != vtotal) {
2728 		link->replay_settings.last_pseudo_vtotal = vtotal;
2729 		link->dc->link_srv->edp_send_replay_cmd(link, Replay_Set_Pseudo_VTotal, &cmd_data);
2730 	}
2731 }
2732 
2733 static void mod_power_update_error_status(struct mod_power *mod_power,
2734 	const struct dc_stream_state *stream)
2735 {
2736 	struct dc_link *link = NULL;
2737 	union replay_debug_flags *pDebug = NULL;
2738 
2739 	if (mod_power == NULL || stream == NULL)
2740 		return;
2741 
2742 	link = dc_stream_get_link(stream);
2743 
2744 	if (!link)
2745 		return;
2746 
2747 	pDebug = (union replay_debug_flags *)&link->replay_settings.config.debug_flags;
2748 
2749 	if (0 == pDebug->bitfields.enable_visual_confirm_debug)
2750 		return;
2751 
2752 	mod_power_replay_set_general_cmd(mod_power, stream,
2753 		REPLAY_GENERAL_CMD_UPDATE_ERROR_STATUS,
2754 		link->replay_settings.config.replay_error_status.raw, 0);
2755 }
2756 
2757 void mod_power_set_low_rr_activate(struct mod_power *mod_power,
2758 	const struct dc_stream_state *stream, bool low_rr_supported)
2759 {
2760 	struct dc_link *link = NULL;
2761 
2762 	if (mod_power == NULL || stream == NULL)
2763 		return;
2764 
2765 	link = dc_stream_get_link(stream);
2766 
2767 	if (!link)
2768 		return;
2769 
2770 	mod_power_replay_set_general_cmd(mod_power, stream,
2771 		REPLAY_GENERAL_CMD_SET_LOW_RR_ACTIVATE,
2772 		low_rr_supported, 0);
2773 }
2774 
2775 void mod_power_set_video_conferencing_activate(struct mod_power *mod_power,
2776 	const struct dc_stream_state *stream, bool video_conferencing_activate)
2777 {
2778 	struct dc_link *link = NULL;
2779 
2780 	if (mod_power == NULL || stream == NULL)
2781 		return;
2782 
2783 	link = dc_stream_get_link(stream);
2784 	if (!link || !link->replay_settings.replay_feature_enabled)
2785 		return;
2786 
2787 	mod_power_replay_set_general_cmd(mod_power, stream,
2788 		REPLAY_GENERAL_CMD_VIDEO_CONFERENCING,
2789 		video_conferencing_activate, 0);
2790 }
2791 
2792 void mod_power_set_coasting_vtotal_without_frame_update(struct mod_power *mod_power,
2793 	const struct dc_stream_state *stream, uint32_t coasting_vtotal)
2794 {
2795 	struct dc_link *link = NULL;
2796 
2797 	if (mod_power == NULL || stream == NULL)
2798 		return;
2799 
2800 	link = dc_stream_get_link(stream);
2801 	if (!link || !link->replay_settings.replay_feature_enabled)
2802 		return;
2803 
2804 	mod_power_replay_set_general_cmd(mod_power, stream,
2805 		REPLAY_GENERAL_CMD_SET_COASTING_VTOTAL_WITHOUT_FRAME_UPDATE,
2806 		coasting_vtotal, 0);
2807 }
2808 
2809 void mod_power_set_replay_continuously_resync(struct mod_power *mod_power,
2810 	const struct dc_stream_state *stream, bool enable)
2811 {
2812 	struct dc_link *link = NULL;
2813 
2814 	if (mod_power == NULL || stream == NULL)
2815 		return;
2816 
2817 	link = dc_stream_get_link(stream);
2818 	if (!link || !link->replay_settings.replay_feature_enabled)
2819 		return;
2820 
2821 	mod_power_replay_set_general_cmd(mod_power, stream,
2822 		REPLAY_GENERAL_CMD_SET_CONTINUOUSLY_RESYNC,
2823 		enable, 0);
2824 }
2825 
2826 void mod_power_set_live_capture_with_cvt_activate(struct mod_power *mod_power,
2827 	const struct dc_stream_state *stream, bool live_capture_with_cvt_activate)
2828 {
2829 	struct dc_link *link = NULL;
2830 
2831 	if (mod_power == NULL || stream == NULL)
2832 		return;
2833 
2834 	link = dc_stream_get_link(stream);
2835 	if (!link || !link->replay_settings.replay_feature_enabled)
2836 		return;
2837 
2838 	// Check if LIVE_CAPTURE_WITH_CVT bit is enabled in DalRegKey_ReplayOptimization
2839 	if (!link->replay_settings.config.replay_optimization.bits.LIVE_CAPTURE_WITH_CVT)
2840 		return;
2841 
2842 	if (link->replay_settings.config.live_capture_with_cvt_activated != live_capture_with_cvt_activate) {
2843 		link->replay_settings.config.live_capture_with_cvt_activated = live_capture_with_cvt_activate;
2844 		mod_power_replay_set_general_cmd(mod_power, stream,
2845 			REPLAY_GENERAL_CMD_LIVE_CAPTURE_WITH_CVT,
2846 			live_capture_with_cvt_activate, 0);
2847 	}
2848 }
2849 
2850 bool mod_power_set_replay_event(struct mod_power *mod_power,
2851 	struct dc_stream_state *stream, bool set_event,
2852 	enum replay_event event, bool wait_for_disable)
2853 {
2854 	struct core_power *core_power = NULL;
2855 	struct dc_link *link = NULL;
2856 	unsigned int stream_index = 0;
2857 	unsigned int active_replay_events = 0;
2858 	bool replay_active_request = false;
2859 	bool force_static = false;
2860 	uint32_t coasting_vtotal = 0;
2861 	bool current_timing_sync_status = false;
2862 	bool is_full_screen_video = false;
2863 	bool is_ultra_sleep_mode = false;
2864 	unsigned int sink_duration_us = 0;
2865 	bool low_rr_active = false;
2866 	uint16_t frame_skip_number = 0;
2867 	bool is_video_playback = false;
2868 
2869 	if (!stream)
2870 		return false;
2871 
2872 	if (mod_power == NULL)
2873 		return false;
2874 
2875 	core_power = MOD_POWER_TO_CORE(mod_power);
2876 
2877 	if (core_power->num_entities == 0)
2878 		return false;
2879 
2880 	stream_index = map_index_from_stream(core_power, stream);
2881 
2882 	if (set_event)
2883 		core_power->map[stream_index].replay_events |= event;
2884 	else
2885 		core_power->map[stream_index].replay_events &= ~event;
2886 
2887 	link = dc_stream_get_link(stream);
2888 	if (!link || !link->replay_settings.replay_feature_enabled)
2889 		return false;
2890 
2891 	if ((core_power->map[stream_index].replay_events & replay_event_disable_replay_while_switching_mux) != 0)
2892 		return false;
2893 
2894 	if ((core_power->map[stream_index].replay_events & replay_event_os_override_hold) != 0)
2895 		return false;
2896 
2897 	active_replay_events = core_power->map[stream_index].replay_events;
2898 
2899 	current_timing_sync_status =
2900 		link->replay_settings.config.replay_timing_sync_supported;
2901 
2902 	replay_active_request = mod_power_update_replay_active_status(active_replay_events,
2903 		link, &coasting_vtotal, &is_full_screen_video, &is_ultra_sleep_mode, &frame_skip_number, &is_video_playback);
2904 
2905 	if (is_full_screen_video)
2906 		mod_power_replay_set_pseudo_vtotal(mod_power, stream,
2907 			link->replay_settings.low_rr_full_screen_video_pseudo_vtotal);
2908 	else
2909 		mod_power_replay_set_pseudo_vtotal(mod_power, stream, 0);
2910 
2911 	//If timing_sync_status change, then re-enabled set timing_sync_supported value and re-enabled replay
2912 	if (current_timing_sync_status != link->replay_settings.config.replay_timing_sync_supported)
2913 		mod_power_replay_set_timing_sync_supported(mod_power, stream);
2914 
2915 	if (link->replay_settings.config.low_rr_supported) {
2916 		sink_duration_us =
2917 			(unsigned int)(div_u64(((unsigned long long)(coasting_vtotal)
2918 				* 10000) * stream->timing.h_total,
2919 					stream->timing.pix_clk_100hz));
2920 		low_rr_active = sink_duration_us < LOW_REFRESH_RATE_DURATION_US_UPPER_BOUND ? false : true;
2921 		if (low_rr_active != link->replay_settings.config.low_rr_activated) {
2922 			mod_power_set_low_rr_activate(mod_power, stream, low_rr_active);
2923 			link->replay_settings.config.low_rr_activated = low_rr_active;
2924 		}
2925 	}
2926 
2927 	// The function return fail when
2928 	// 1. DMUB function is not support (for backward compatible).
2929 	// 2. active_replay_events or coasting_vtotal is not updated in the same time
2930 	if (!mod_power_replay_set_power_opt_and_coasting_vtotal(mod_power,
2931 		stream, active_replay_events, coasting_vtotal, is_ultra_sleep_mode, frame_skip_number)) {
2932 		if (!mod_power_replay_set_power_opt(mod_power, stream, active_replay_events, is_ultra_sleep_mode))
2933 			return false;
2934 
2935 		if (!mod_power_replay_set_coasting_vtotal(mod_power, stream, coasting_vtotal, frame_skip_number))
2936 			return false;
2937 	}
2938 
2939 	mod_power_set_live_capture_with_cvt_activate(mod_power, stream, is_video_playback);
2940 
2941 	mod_power_update_error_status(mod_power, stream);
2942 
2943 	// If Replay is going to be enable (No matter is disable -> enable or enable -> enable), we don't need to wait.
2944 	// If Replay is going to be disable
2945 	//     if disable -> disable
2946 	//         -> Replay DMUB state should be state 0.
2947 	//            So no matter wait_for_disable is true or not, it should makes no difference.
2948 	//     if enable -> disable -> We should wait if wait_for_disable is true.
2949 	if (replay_active_request)
2950 		wait_for_disable = false;
2951 
2952 	if (!mod_power_set_replay_active(stream, replay_active_request, wait_for_disable, force_static))
2953 		return false;
2954 
2955 	return true;
2956 }
2957 
2958 bool mod_power_get_replay_active_status(const struct dc_stream_state *stream,
2959 	bool *replay_active)
2960 {
2961 	const struct dc_link *link = NULL;
2962 
2963 	if (!stream)
2964 		return false;
2965 
2966 	link = dc_stream_get_link(stream);
2967 	*replay_active = link->replay_settings.replay_allow_active;
2968 
2969 	return true;
2970 }
2971 
2972 void mod_power_replay_residency(const struct dc_stream_state *stream,
2973 	unsigned int *residency, const bool is_start, const bool is_alpm)
2974 {
2975 	const struct dc_link *link = NULL;
2976 	enum pr_residency_mode mode;
2977 
2978 	if (!stream)
2979 		return;
2980 
2981 	link = dc_stream_get_link(stream);
2982 
2983 	if (is_alpm)
2984 		mode = PR_RESIDENCY_MODE_ALPM;
2985 	else
2986 		mode = PR_RESIDENCY_MODE_PHY;
2987 
2988 	if (link && link->dc && link->dc->link_srv)
2989 		link->dc->link_srv->edp_replay_residency(link, residency, is_start, mode);
2990 }
2991 
2992 bool mod_power_replay_set_power_opt_and_coasting_vtotal(struct mod_power *mod_power,
2993 	const struct dc_stream_state *stream, unsigned int active_replay_events, uint32_t coasting_vtotal,
2994 	bool is_ultra_sleep_mode, uint16_t frame_skip_number)
2995 {
2996 	struct core_power *core_power = NULL;
2997 	struct dc_link *link = NULL;
2998 	unsigned int power_opt = 0;
2999 
3000 	if (!stream)
3001 		return false;
3002 
3003 	if (mod_power == NULL)
3004 		return false;
3005 
3006 	core_power = MOD_POWER_TO_CORE(mod_power);
3007 
3008 	if (core_power->num_entities == 0)
3009 		return false;
3010 
3011 	link = dc_stream_get_link(stream);
3012 
3013 	if (!link || !link->replay_settings.replay_feature_enabled)
3014 		return false;
3015 
3016 	power_opt = mod_power_replay_setup_power_opt(link, active_replay_events, is_ultra_sleep_mode);
3017 
3018 	return link->dc->link_srv->edp_set_replay_power_opt_and_coasting_vtotal(link, &power_opt, coasting_vtotal, frame_skip_number);
3019 }
3020 
3021 
3022 
3023 
3024 
3025