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