1 /*
2  * Copyright 2022 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 /* FILE POLICY AND INTENDED USAGE:
27  * This file implements retrieval and configuration of eDP panel features such
28  * as PSR and ABM and it also manages specs defined eDP panel power sequences.
29  */
30 
31 #include "link_edp_panel_control.h"
32 #include "link_dpcd.h"
33 #include "link_dp_capability.h"
34 #include "dm_helpers.h"
35 #include "dal_asic_id.h"
36 #include "link_dp_phy.h"
37 #include "dce/dmub_psr.h"
38 #include "dc/dc_dmub_srv.h"
39 #include "dce/dmub_replay.h"
40 #include "abm.h"
41 #define DC_LOGGER \
42 	link->ctx->logger
43 #define DC_LOGGER_INIT(logger)
44 
45 #define DP_SINK_PR_ENABLE_AND_CONFIGURATION		0x37B
46 
47 /* Travis */
48 static const uint8_t DP_VGA_LVDS_CONVERTER_ID_2[] = "sivarT";
49 /* Nutmeg */
50 static const uint8_t DP_VGA_LVDS_CONVERTER_ID_3[] = "dnomlA";
51 
dp_set_panel_mode(struct dc_link * link,enum dp_panel_mode panel_mode)52 void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode)
53 {
54 	union dpcd_edp_config edp_config_set;
55 	bool panel_mode_edp = false;
56 	enum dc_status result;
57 
58 	memset(&edp_config_set, '\0', sizeof(union dpcd_edp_config));
59 
60 	switch (panel_mode) {
61 	case DP_PANEL_MODE_EDP:
62 	case DP_PANEL_MODE_SPECIAL:
63 		panel_mode_edp = true;
64 		break;
65 
66 	default:
67 		break;
68 	}
69 
70 	/*set edp panel mode in receiver*/
71 	result = core_link_read_dpcd(
72 		link,
73 		DP_EDP_CONFIGURATION_SET,
74 		&edp_config_set.raw,
75 		sizeof(edp_config_set.raw));
76 
77 	if (result == DC_OK &&
78 		edp_config_set.bits.PANEL_MODE_EDP
79 		!= panel_mode_edp) {
80 
81 		edp_config_set.bits.PANEL_MODE_EDP =
82 		panel_mode_edp;
83 		result = core_link_write_dpcd(
84 			link,
85 			DP_EDP_CONFIGURATION_SET,
86 			&edp_config_set.raw,
87 			sizeof(edp_config_set.raw));
88 
89 		ASSERT(result == DC_OK);
90 	}
91 
92 	link->panel_mode = panel_mode;
93 	DC_LOG_DETECTION_DP_CAPS("Link: %d eDP panel mode supported: %d "
94 		 "eDP panel mode enabled: %d \n",
95 		 link->link_index,
96 		 link->dpcd_caps.panel_mode_edp,
97 		 panel_mode_edp);
98 }
99 
dp_get_panel_mode(struct dc_link * link)100 enum dp_panel_mode dp_get_panel_mode(struct dc_link *link)
101 {
102 	/* We need to explicitly check that connector
103 	 * is not DP. Some Travis_VGA get reported
104 	 * by video bios as DP.
105 	 */
106 	if (link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) {
107 
108 		switch (link->dpcd_caps.branch_dev_id) {
109 		case DP_BRANCH_DEVICE_ID_0022B9:
110 			/* alternate scrambler reset is required for Travis
111 			 * for the case when external chip does not
112 			 * provide sink device id, alternate scrambler
113 			 * scheme will  be overriden later by querying
114 			 * Encoder features
115 			 */
116 			if (strncmp(
117 				link->dpcd_caps.branch_dev_name,
118 				DP_VGA_LVDS_CONVERTER_ID_2,
119 				sizeof(
120 				link->dpcd_caps.
121 				branch_dev_name)) == 0) {
122 					return DP_PANEL_MODE_SPECIAL;
123 			}
124 			break;
125 		case DP_BRANCH_DEVICE_ID_00001A:
126 			/* alternate scrambler reset is required for Travis
127 			 * for the case when external chip does not provide
128 			 * sink device id, alternate scrambler scheme will
129 			 * be overriden later by querying Encoder feature
130 			 */
131 			if (strncmp(link->dpcd_caps.branch_dev_name,
132 				DP_VGA_LVDS_CONVERTER_ID_3,
133 				sizeof(
134 				link->dpcd_caps.
135 				branch_dev_name)) == 0) {
136 					return DP_PANEL_MODE_SPECIAL;
137 			}
138 			break;
139 		default:
140 			break;
141 		}
142 	}
143 
144 	if (link->dpcd_caps.panel_mode_edp &&
145 		(link->connector_signal == SIGNAL_TYPE_EDP ||
146 		 (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT &&
147 		  link->is_internal_display))) {
148 		return DP_PANEL_MODE_EDP;
149 	}
150 
151 	return DP_PANEL_MODE_DEFAULT;
152 }
153 
edp_set_backlight_level_nits(struct dc_link * link,bool isHDR,uint32_t backlight_millinits,uint32_t transition_time_in_ms)154 bool edp_set_backlight_level_nits(struct dc_link *link,
155 		bool isHDR,
156 		uint32_t backlight_millinits,
157 		uint32_t transition_time_in_ms)
158 {
159 	struct dpcd_source_backlight_set dpcd_backlight_set;
160 	uint8_t backlight_control = isHDR ? 1 : 0;
161 
162 	if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
163 			link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
164 		return false;
165 
166 	// OLEDs have no PWM, they can only use AUX
167 	if (link->dpcd_sink_ext_caps.bits.oled == 1)
168 		backlight_control = 1;
169 
170 	*(uint32_t *)&dpcd_backlight_set.backlight_level_millinits = backlight_millinits;
171 	*(uint16_t *)&dpcd_backlight_set.backlight_transition_time_ms = (uint16_t)transition_time_in_ms;
172 
173 
174 	if (!link->dpcd_caps.panel_luminance_control) {
175 		if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL,
176 			(uint8_t *)(&dpcd_backlight_set),
177 			sizeof(dpcd_backlight_set)) != DC_OK)
178 			return false;
179 
180 		if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_CONTROL,
181 			&backlight_control, 1) != DC_OK)
182 			return false;
183 	} else {
184 		uint8_t backlight_enable = 0;
185 		struct target_luminance_value *target_luminance = NULL;
186 
187 		//if target luminance value is greater than 24 bits, clip the value to 24 bits
188 		if (backlight_millinits > 0xFFFFFF)
189 			backlight_millinits = 0xFFFFFF;
190 
191 		target_luminance = (struct target_luminance_value *)&backlight_millinits;
192 
193 		core_link_read_dpcd(link, DP_EDP_BACKLIGHT_MODE_SET_REGISTER,
194 			&backlight_enable, sizeof(uint8_t));
195 
196 		backlight_enable |= DP_EDP_PANEL_LUMINANCE_CONTROL_ENABLE;
197 
198 		if (core_link_write_dpcd(link, DP_EDP_BACKLIGHT_MODE_SET_REGISTER,
199 			&backlight_enable,
200 			sizeof(backlight_enable)) != DC_OK)
201 			return false;
202 
203 		if (core_link_write_dpcd(link, DP_EDP_PANEL_TARGET_LUMINANCE_VALUE,
204 			(uint8_t *)(target_luminance),
205 			sizeof(struct target_luminance_value)) != DC_OK)
206 			return false;
207 	}
208 
209 	return true;
210 }
211 
edp_get_backlight_level_nits(struct dc_link * link,uint32_t * backlight_millinits_avg,uint32_t * backlight_millinits_peak)212 bool edp_get_backlight_level_nits(struct dc_link *link,
213 		uint32_t *backlight_millinits_avg,
214 		uint32_t *backlight_millinits_peak)
215 {
216 	union dpcd_source_backlight_get dpcd_backlight_get;
217 
218 	memset(&dpcd_backlight_get, 0, sizeof(union dpcd_source_backlight_get));
219 
220 	if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
221 			link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
222 		return false;
223 
224 	if (!core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_CURRENT_PEAK,
225 			dpcd_backlight_get.raw,
226 			sizeof(union dpcd_source_backlight_get)))
227 		return false;
228 
229 	*backlight_millinits_avg =
230 		dpcd_backlight_get.bytes.backlight_millinits_avg;
231 	*backlight_millinits_peak =
232 		dpcd_backlight_get.bytes.backlight_millinits_peak;
233 
234 	/* On non-supported panels dpcd_read usually succeeds with 0 returned */
235 	if (*backlight_millinits_avg == 0 ||
236 			*backlight_millinits_avg > *backlight_millinits_peak)
237 		return false;
238 
239 	return true;
240 }
241 
edp_backlight_enable_aux(struct dc_link * link,bool enable)242 bool edp_backlight_enable_aux(struct dc_link *link, bool enable)
243 {
244 	uint8_t backlight_enable = enable ? 1 : 0;
245 
246 	if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
247 		link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
248 		return false;
249 
250 	if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_ENABLE,
251 		&backlight_enable, 1) != DC_OK)
252 		return false;
253 
254 	return true;
255 }
256 
257 // we read default from 0x320 because we expect BIOS wrote it there
258 // regular get_backlight_nit reads from panel set at 0x326
read_default_bl_aux(struct dc_link * link,uint32_t * backlight_millinits)259 static bool read_default_bl_aux(struct dc_link *link, uint32_t *backlight_millinits)
260 {
261 	if (!link || (link->connector_signal != SIGNAL_TYPE_EDP &&
262 		link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT))
263 		return false;
264 
265 	if (!link->dpcd_caps.panel_luminance_control) {
266 		if (!core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL,
267 			(uint8_t *)backlight_millinits,
268 			sizeof(uint32_t)))
269 			return false;
270 	} else {
271 		//setting to 0 as a precaution, since target_luminance_value is 3 bytes
272 		memset(backlight_millinits, 0, sizeof(uint32_t));
273 
274 		if (!core_link_read_dpcd(link, DP_EDP_PANEL_TARGET_LUMINANCE_VALUE,
275 			(uint8_t *)backlight_millinits,
276 			sizeof(struct target_luminance_value)))
277 			return false;
278 	}
279 
280 	return true;
281 }
282 
set_default_brightness_aux(struct dc_link * link)283 bool set_default_brightness_aux(struct dc_link *link)
284 {
285 	uint32_t default_backlight;
286 
287 	if (link && link->dpcd_sink_ext_caps.bits.oled == 1) {
288 		if (!read_default_bl_aux(link, &default_backlight))
289 			default_backlight = 150000;
290 		// if < 1 nits or > 5000, it might be wrong readback
291 		if (default_backlight < 1000 || default_backlight > 5000000)
292 			default_backlight = 150000;
293 
294 		return edp_set_backlight_level_nits(link, true,
295 				default_backlight, 0);
296 	}
297 	return false;
298 }
299 
edp_is_ilr_optimization_enabled(struct dc_link * link)300 bool edp_is_ilr_optimization_enabled(struct dc_link *link)
301 {
302 	if (link->dpcd_caps.edp_supported_link_rates_count == 0 || !link->panel_config.ilr.optimize_edp_link_rate)
303 		return false;
304 	return true;
305 }
306 
get_max_link_rate_from_ilr_table(struct dc_link * link)307 enum dc_link_rate get_max_link_rate_from_ilr_table(struct dc_link *link)
308 {
309 	enum dc_link_rate link_rate = link->reported_link_cap.link_rate;
310 
311 	for (int i = 0; i < link->dpcd_caps.edp_supported_link_rates_count; i++) {
312 		if (link_rate < link->dpcd_caps.edp_supported_link_rates[i])
313 			link_rate = link->dpcd_caps.edp_supported_link_rates[i];
314 	}
315 
316 	return link_rate;
317 }
318 
edp_is_ilr_optimization_required(struct dc_link * link,struct dc_crtc_timing * crtc_timing)319 bool edp_is_ilr_optimization_required(struct dc_link *link,
320 		struct dc_crtc_timing *crtc_timing)
321 {
322 	struct dc_link_settings link_setting;
323 	uint8_t link_bw_set;
324 	uint8_t link_rate_set;
325 	uint32_t req_bw;
326 	union lane_count_set lane_count_set = {0};
327 
328 	ASSERT(link || crtc_timing); // invalid input
329 
330 	if (!edp_is_ilr_optimization_enabled(link))
331 		return false;
332 
333 
334 	// Read DPCD 00100h to find if standard link rates are set
335 	core_link_read_dpcd(link, DP_LINK_BW_SET,
336 				&link_bw_set, sizeof(link_bw_set));
337 
338 	if (link_bw_set) {
339 		DC_LOG_EVENT_LINK_TRAINING("eDP ILR: Optimization required, VBIOS used link_bw_set\n");
340 		return true;
341 	}
342 
343 	// Read DPCD 00115h to find the edp link rate set used
344 	core_link_read_dpcd(link, DP_LINK_RATE_SET,
345 			    &link_rate_set, sizeof(link_rate_set));
346 
347 	// Read DPCD 00101h to find out the number of lanes currently set
348 	core_link_read_dpcd(link, DP_LANE_COUNT_SET,
349 				&lane_count_set.raw, sizeof(lane_count_set));
350 
351 	req_bw = dc_bandwidth_in_kbps_from_timing(crtc_timing, dc_link_get_highest_encoding_format(link));
352 
353 	if (!crtc_timing->flags.DSC)
354 		edp_decide_link_settings(link, &link_setting, req_bw);
355 	else
356 		decide_edp_link_settings_with_dsc(link, &link_setting, req_bw, LINK_RATE_UNKNOWN);
357 
358 	if (link->dpcd_caps.edp_supported_link_rates[link_rate_set] != link_setting.link_rate ||
359 			lane_count_set.bits.LANE_COUNT_SET != link_setting.lane_count) {
360 		DC_LOG_EVENT_LINK_TRAINING("eDP ILR: Optimization required, VBIOS link_rate_set not optimal\n");
361 		return true;
362 	}
363 
364 	DC_LOG_EVENT_LINK_TRAINING("eDP ILR: No optimization required, VBIOS set optimal link_rate_set\n");
365 	return false;
366 }
367 
edp_panel_backlight_power_on(struct dc_link * link,bool wait_for_hpd)368 void edp_panel_backlight_power_on(struct dc_link *link, bool wait_for_hpd)
369 {
370 	if (link->connector_signal != SIGNAL_TYPE_EDP)
371 		return;
372 
373 	link->dc->hwss.edp_power_control(link, true);
374 	if (wait_for_hpd)
375 		link->dc->hwss.edp_wait_for_hpd_ready(link, true);
376 	if (link->dc->hwss.edp_backlight_control)
377 		link->dc->hwss.edp_backlight_control(link, true);
378 }
379 
edp_set_panel_power(struct dc_link * link,bool powerOn)380 void edp_set_panel_power(struct dc_link *link, bool powerOn)
381 {
382 	if (powerOn) {
383 		// 1. panel VDD on
384 		if (!link->dc->config.edp_no_power_sequencing)
385 			link->dc->hwss.edp_power_control(link, true);
386 		link->dc->hwss.edp_wait_for_hpd_ready(link, true);
387 
388 		// 2. panel BL on
389 		if (link->dc->hwss.edp_backlight_control)
390 			link->dc->hwss.edp_backlight_control(link, true);
391 
392 		// 3. Rx power on
393 		dpcd_write_rx_power_ctrl(link, true);
394 	} else {
395 		// 3. Rx power off
396 		dpcd_write_rx_power_ctrl(link, false);
397 
398 		// 2. panel BL off
399 		if (link->dc->hwss.edp_backlight_control)
400 			link->dc->hwss.edp_backlight_control(link, false);
401 
402 		// 1. panel VDD off
403 		if (!link->dc->config.edp_no_power_sequencing)
404 			link->dc->hwss.edp_power_control(link, false);
405 	}
406 }
407 
edp_wait_for_t12(struct dc_link * link)408 bool edp_wait_for_t12(struct dc_link *link)
409 {
410 	if (link->connector_signal == SIGNAL_TYPE_EDP && link->dc->hwss.edp_wait_for_T12) {
411 		link->dc->hwss.edp_wait_for_T12(link);
412 
413 		return true;
414 	}
415 
416 	return false;
417 }
418 
edp_add_delay_for_T9(struct dc_link * link)419 void edp_add_delay_for_T9(struct dc_link *link)
420 {
421 	if (link && link->panel_config.pps.extra_delay_backlight_off > 0)
422 		fsleep(link->panel_config.pps.extra_delay_backlight_off * 1000);
423 }
424 
edp_receiver_ready_T9(struct dc_link * link)425 bool edp_receiver_ready_T9(struct dc_link *link)
426 {
427 	unsigned int tries = 0;
428 	unsigned char sinkstatus = 0;
429 	unsigned char edpRev = 0;
430 	enum dc_status result = DC_OK;
431 
432 	result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev));
433 
434 	/* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/
435 	if (result == DC_OK && edpRev >= DP_EDP_12) {
436 		do {
437 			sinkstatus = 1;
438 			result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
439 			if (sinkstatus == 0)
440 				break;
441 			if (result != DC_OK)
442 				break;
443 			udelay(100); //MAx T9
444 		} while (++tries < 50);
445 	}
446 
447 	return result;
448 }
449 
edp_receiver_ready_T7(struct dc_link * link)450 bool edp_receiver_ready_T7(struct dc_link *link)
451 {
452 	unsigned char sinkstatus = 0;
453 	unsigned char edpRev = 0;
454 	enum dc_status result = DC_OK;
455 
456 	/* use absolute time stamp to constrain max T7*/
457 	unsigned long long enter_timestamp = 0;
458 	unsigned long long finish_timestamp = 0;
459 	unsigned long long time_taken_in_ns = 0;
460 
461 	result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev));
462 
463 	if (result == DC_OK && edpRev >= DP_EDP_12) {
464 		/* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/
465 		enter_timestamp = dm_get_timestamp(link->ctx);
466 		do {
467 			sinkstatus = 0;
468 			result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus));
469 			if (sinkstatus == 1)
470 				break;
471 			if (result != DC_OK)
472 				break;
473 			udelay(25);
474 			finish_timestamp = dm_get_timestamp(link->ctx);
475 			time_taken_in_ns = dm_get_elapse_time_in_ns(link->ctx, finish_timestamp, enter_timestamp);
476 		} while (time_taken_in_ns < 50 * 1000000); //MAx T7 is 50ms
477 	}
478 
479 	if (link && link->panel_config.pps.extra_t7_ms > 0)
480 		fsleep(link->panel_config.pps.extra_t7_ms * 1000);
481 
482 	return result;
483 }
484 
edp_power_alpm_dpcd_enable(struct dc_link * link,bool enable)485 bool edp_power_alpm_dpcd_enable(struct dc_link *link, bool enable)
486 {
487 	bool ret = false;
488 	union dpcd_alpm_configuration alpm_config;
489 
490 	if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) {
491 		memset(&alpm_config, 0, sizeof(alpm_config));
492 
493 		alpm_config.bits.ENABLE = (enable ? true : false);
494 		ret = dm_helpers_dp_write_dpcd(link->ctx, link,
495 				DP_RECEIVER_ALPM_CONFIG, &alpm_config.raw,
496 				sizeof(alpm_config.raw));
497 	}
498 	return ret;
499 }
500 
get_pipe_from_link(const struct dc_link * link)501 static struct pipe_ctx *get_pipe_from_link(const struct dc_link *link)
502 {
503 	int i;
504 	struct dc *dc = link->ctx->dc;
505 	struct pipe_ctx *pipe_ctx = NULL;
506 
507 	for (i = 0; i < MAX_PIPES; i++) {
508 		if (dc->current_state->res_ctx.pipe_ctx[i].stream) {
509 			if (dc->current_state->res_ctx.pipe_ctx[i].stream->link == link) {
510 				pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
511 				break;
512 			}
513 		}
514 	}
515 
516 	return pipe_ctx;
517 }
518 
edp_set_backlight_level(const struct dc_link * link,uint32_t backlight_pwm_u16_16,uint32_t frame_ramp)519 bool edp_set_backlight_level(const struct dc_link *link,
520 		uint32_t backlight_pwm_u16_16,
521 		uint32_t frame_ramp)
522 {
523 	struct dc  *dc = link->ctx->dc;
524 
525 	DC_LOGGER_INIT(link->ctx->logger);
526 	DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n",
527 			backlight_pwm_u16_16, backlight_pwm_u16_16);
528 
529 	if (dc_is_embedded_signal(link->connector_signal)) {
530 		struct pipe_ctx *pipe_ctx = get_pipe_from_link(link);
531 
532 		if (link->panel_cntl)
533 			link->panel_cntl->stored_backlight_registers.USER_LEVEL = backlight_pwm_u16_16;
534 
535 		if (pipe_ctx) {
536 			/* Disable brightness ramping when the display is blanked
537 			 * as it can hang the DMCU
538 			 */
539 			if (pipe_ctx->plane_state == NULL)
540 				frame_ramp = 0;
541 		} else {
542 			return false;
543 		}
544 
545 		dc->hwss.set_backlight_level(
546 				pipe_ctx,
547 				backlight_pwm_u16_16,
548 				frame_ramp);
549 	}
550 	return true;
551 }
552 
edp_set_psr_allow_active(struct dc_link * link,const bool * allow_active,bool wait,bool force_static,const unsigned int * power_opts)553 bool edp_set_psr_allow_active(struct dc_link *link, const bool *allow_active,
554 		bool wait, bool force_static, const unsigned int *power_opts)
555 {
556 	struct dc  *dc = link->ctx->dc;
557 	struct dmcu *dmcu = dc->res_pool->dmcu;
558 	struct dmub_psr *psr = dc->res_pool->psr;
559 	unsigned int panel_inst;
560 
561 	if (psr == NULL && force_static)
562 		return false;
563 
564 	if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
565 		return false;
566 
567 	if ((allow_active != NULL) && (*allow_active == true) && (link->type == dc_connection_none)) {
568 		// Don't enter PSR if panel is not connected
569 		return false;
570 	}
571 
572 	/* Set power optimization flag */
573 	if (power_opts && link->psr_settings.psr_power_opt != *power_opts) {
574 		link->psr_settings.psr_power_opt = *power_opts;
575 
576 		if (psr != NULL && link->psr_settings.psr_feature_enabled && psr->funcs->psr_set_power_opt)
577 			psr->funcs->psr_set_power_opt(psr, link->psr_settings.psr_power_opt, panel_inst);
578 	}
579 
580 	if (psr != NULL && link->psr_settings.psr_feature_enabled &&
581 			force_static && psr->funcs->psr_force_static)
582 		psr->funcs->psr_force_static(psr, panel_inst);
583 
584 	/* Enable or Disable PSR */
585 	if (allow_active && link->psr_settings.psr_allow_active != *allow_active) {
586 		link->psr_settings.psr_allow_active = *allow_active;
587 
588 		if (!link->psr_settings.psr_allow_active)
589 			dc_z10_restore(dc);
590 
591 		if (psr != NULL && link->psr_settings.psr_feature_enabled) {
592 			psr->funcs->psr_enable(psr, link->psr_settings.psr_allow_active, wait, panel_inst);
593 		} else if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) &&
594 			link->psr_settings.psr_feature_enabled)
595 			dmcu->funcs->set_psr_enable(dmcu, link->psr_settings.psr_allow_active, wait);
596 		else
597 			return false;
598 	}
599 	return true;
600 }
601 
edp_get_psr_state(const struct dc_link * link,enum dc_psr_state * state)602 bool edp_get_psr_state(const struct dc_link *link, enum dc_psr_state *state)
603 {
604 	struct dc  *dc = link->ctx->dc;
605 	struct dmcu *dmcu = dc->res_pool->dmcu;
606 	struct dmub_psr *psr = dc->res_pool->psr;
607 	unsigned int panel_inst;
608 
609 	if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
610 		return false;
611 
612 	if (psr != NULL && link->psr_settings.psr_feature_enabled)
613 		psr->funcs->psr_get_state(psr, state, panel_inst);
614 	else if (dmcu != NULL && link->psr_settings.psr_feature_enabled)
615 		dmcu->funcs->get_psr_state(dmcu, state);
616 
617 	return true;
618 }
619 
620 static inline enum physical_phy_id
transmitter_to_phy_id(struct dc_link * link)621 transmitter_to_phy_id(struct dc_link *link)
622 {
623 	struct dc_context *dc_ctx = link->ctx;
624 	enum transmitter transmitter_value = link->link_enc->transmitter;
625 
626 	switch (transmitter_value) {
627 	case TRANSMITTER_UNIPHY_A:
628 		return PHYLD_0;
629 	case TRANSMITTER_UNIPHY_B:
630 		return PHYLD_1;
631 	case TRANSMITTER_UNIPHY_C:
632 		return PHYLD_2;
633 	case TRANSMITTER_UNIPHY_D:
634 		return PHYLD_3;
635 	case TRANSMITTER_UNIPHY_E:
636 		return PHYLD_4;
637 	case TRANSMITTER_UNIPHY_F:
638 		return PHYLD_5;
639 	case TRANSMITTER_NUTMEG_CRT:
640 		return PHYLD_6;
641 	case TRANSMITTER_TRAVIS_CRT:
642 		return PHYLD_7;
643 	case TRANSMITTER_TRAVIS_LCD:
644 		return PHYLD_8;
645 	case TRANSMITTER_UNIPHY_G:
646 		return PHYLD_9;
647 	case TRANSMITTER_COUNT:
648 		return PHYLD_COUNT;
649 	case TRANSMITTER_UNKNOWN:
650 		return PHYLD_UNKNOWN;
651 	default:
652 		DC_ERROR("Unknown transmitter value %d\n", transmitter_value);
653 		return PHYLD_UNKNOWN;
654 	}
655 }
656 
edp_setup_psr(struct dc_link * link,const struct dc_stream_state * stream,struct psr_config * psr_config,struct psr_context * psr_context)657 bool edp_setup_psr(struct dc_link *link,
658 		const struct dc_stream_state *stream, struct psr_config *psr_config,
659 		struct psr_context *psr_context)
660 {
661 	struct dc *dc;
662 	struct dmcu *dmcu;
663 	struct dmub_psr *psr;
664 	int i;
665 	unsigned int panel_inst;
666 	/* updateSinkPsrDpcdConfig*/
667 	union dpcd_psr_configuration psr_configuration;
668 	union dpcd_sink_active_vtotal_control_mode vtotal_control = {0};
669 
670 	psr_context->controllerId = CONTROLLER_ID_UNDEFINED;
671 
672 	if (!link)
673 		return false;
674 
675 	dc = link->ctx->dc;
676 	dmcu = dc->res_pool->dmcu;
677 	psr = dc->res_pool->psr;
678 
679 	if (!dmcu && !psr)
680 		return false;
681 
682 	if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
683 		return false;
684 
685 
686 	memset(&psr_configuration, 0, sizeof(psr_configuration));
687 
688 	psr_configuration.bits.ENABLE                    = 1;
689 	psr_configuration.bits.CRC_VERIFICATION          = 1;
690 	psr_configuration.bits.FRAME_CAPTURE_INDICATION  =
691 			psr_config->psr_frame_capture_indication_req;
692 
693 	/* Check for PSR v2*/
694 	if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) {
695 		/* For PSR v2 selective update.
696 		 * Indicates whether sink should start capturing
697 		 * immediately following active scan line,
698 		 * or starting with the 2nd active scan line.
699 		 */
700 		psr_configuration.bits.LINE_CAPTURE_INDICATION = 0;
701 		/*For PSR v2, determines whether Sink should generate
702 		 * IRQ_HPD when CRC mismatch is detected.
703 		 */
704 		psr_configuration.bits.IRQ_HPD_WITH_CRC_ERROR    = 1;
705 		/* For PSR v2, set the bit when the Source device will
706 		 * be enabling PSR2 operation.
707 		 */
708 		psr_configuration.bits.ENABLE_PSR2    = 1;
709 		/* For PSR v2, the Sink device must be able to receive
710 		 * SU region updates early in the frame time.
711 		 */
712 		psr_configuration.bits.EARLY_TRANSPORT_ENABLE    = 1;
713 	}
714 
715 	dm_helpers_dp_write_dpcd(
716 		link->ctx,
717 		link,
718 		368,
719 		&psr_configuration.raw,
720 		sizeof(psr_configuration.raw));
721 
722 	if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) {
723 		edp_power_alpm_dpcd_enable(link, true);
724 		psr_context->su_granularity_required =
725 			psr_config->su_granularity_required;
726 		psr_context->su_y_granularity =
727 			psr_config->su_y_granularity;
728 		psr_context->line_time_in_us = psr_config->line_time_in_us;
729 
730 		/* linux must be able to expose AMD Source DPCD definition
731 		 * in order to support FreeSync PSR
732 		 */
733 		if (link->psr_settings.psr_vtotal_control_support) {
734 			psr_context->rate_control_caps = psr_config->rate_control_caps;
735 			vtotal_control.bits.ENABLE = true;
736 			core_link_write_dpcd(link, DP_SINK_PSR_ACTIVE_VTOTAL_CONTROL_MODE,
737 							&vtotal_control.raw, sizeof(vtotal_control.raw));
738 		}
739 	}
740 
741 	psr_context->channel = link->ddc->ddc_pin->hw_info.ddc_channel;
742 	psr_context->transmitterId = link->link_enc->transmitter;
743 	psr_context->engineId = link->link_enc->preferred_engine;
744 
745 	for (i = 0; i < MAX_PIPES; i++) {
746 		if (dc->current_state->res_ctx.pipe_ctx[i].stream
747 				== stream) {
748 			/* dmcu -1 for all controller id values,
749 			 * therefore +1 here
750 			 */
751 			psr_context->controllerId =
752 				dc->current_state->res_ctx.
753 				pipe_ctx[i].stream_res.tg->inst + 1;
754 			break;
755 		}
756 	}
757 
758 	/* Hardcoded for now.  Can be Pcie or Uniphy (or Unknown)*/
759 	psr_context->phyType = PHY_TYPE_UNIPHY;
760 	/*PhyId is associated with the transmitter id*/
761 	psr_context->smuPhyId = transmitter_to_phy_id(link);
762 
763 	psr_context->crtcTimingVerticalTotal = stream->timing.v_total;
764 	psr_context->vsync_rate_hz = div64_u64(div64_u64((stream->
765 					timing.pix_clk_100hz * 100),
766 					stream->timing.v_total),
767 					stream->timing.h_total);
768 
769 	psr_context->psrSupportedDisplayConfig = true;
770 	psr_context->psrExitLinkTrainingRequired =
771 		psr_config->psr_exit_link_training_required;
772 	psr_context->sdpTransmitLineNumDeadline =
773 		psr_config->psr_sdp_transmit_line_num_deadline;
774 	psr_context->psrFrameCaptureIndicationReq =
775 		psr_config->psr_frame_capture_indication_req;
776 
777 	psr_context->skipPsrWaitForPllLock = 0; /* only = 1 in KV */
778 
779 	psr_context->numberOfControllers =
780 			link->dc->res_pool->timing_generator_count;
781 
782 	psr_context->rfb_update_auto_en = true;
783 
784 	/* 2 frames before enter PSR. */
785 	psr_context->timehyst_frames = 2;
786 	/* half a frame
787 	 * (units in 100 lines, i.e. a value of 1 represents 100 lines)
788 	 */
789 	psr_context->hyst_lines = stream->timing.v_total / 2 / 100;
790 	psr_context->aux_repeats = 10;
791 
792 	psr_context->psr_level.u32all = 0;
793 
794 	/*skip power down the single pipe since it blocks the cstate*/
795 	if (link->ctx->asic_id.chip_family >= FAMILY_RV) {
796 		switch (link->ctx->asic_id.chip_family) {
797 		case FAMILY_YELLOW_CARP:
798 		case AMDGPU_FAMILY_GC_10_3_6:
799 		case AMDGPU_FAMILY_GC_11_0_1:
800 			if (dc->debug.disable_z10 || dc->debug.psr_skip_crtc_disable)
801 				psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true;
802 			break;
803 		default:
804 			psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true;
805 			break;
806 		}
807 	}
808 
809 	/* SMU will perform additional powerdown sequence.
810 	 * For unsupported ASICs, set psr_level flag to skip PSR
811 	 *  static screen notification to SMU.
812 	 *  (Always set for DAL2, did not check ASIC)
813 	 */
814 	psr_context->allow_smu_optimizations = psr_config->allow_smu_optimizations;
815 	psr_context->allow_multi_disp_optimizations = psr_config->allow_multi_disp_optimizations;
816 
817 	/* Complete PSR entry before aborting to prevent intermittent
818 	 * freezes on certain eDPs
819 	 */
820 	psr_context->psr_level.bits.DISABLE_PSR_ENTRY_ABORT = 1;
821 
822 	/* Disable ALPM first for compatible non-ALPM panel now */
823 	psr_context->psr_level.bits.DISABLE_ALPM = 0;
824 	psr_context->psr_level.bits.ALPM_DEFAULT_PD_MODE = 1;
825 
826 	/* Controls additional delay after remote frame capture before
827 	 * continuing power down, default = 0
828 	 */
829 	psr_context->frame_delay = 0;
830 
831 	psr_context->dsc_slice_height = psr_config->dsc_slice_height;
832 
833 	if (psr) {
834 		link->psr_settings.psr_feature_enabled = psr->funcs->psr_copy_settings(psr,
835 			link, psr_context, panel_inst);
836 		link->psr_settings.psr_power_opt = 0;
837 		link->psr_settings.psr_allow_active = 0;
838 	} else {
839 		link->psr_settings.psr_feature_enabled = dmcu->funcs->setup_psr(dmcu, link, psr_context);
840 	}
841 
842 	/* psr_enabled == 0 indicates setup_psr did not succeed, but this
843 	 * should not happen since firmware should be running at this point
844 	 */
845 	if (link->psr_settings.psr_feature_enabled == 0)
846 		ASSERT(0);
847 
848 	return true;
849 
850 }
851 
edp_get_psr_residency(const struct dc_link * link,uint32_t * residency)852 void edp_get_psr_residency(const struct dc_link *link, uint32_t *residency)
853 {
854 	struct dc  *dc = link->ctx->dc;
855 	struct dmub_psr *psr = dc->res_pool->psr;
856 	unsigned int panel_inst;
857 
858 	if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
859 		return;
860 
861 	// PSR residency measurements only supported on DMCUB
862 	if (psr != NULL && link->psr_settings.psr_feature_enabled)
863 		psr->funcs->psr_get_residency(psr, residency, panel_inst);
864 	else
865 		*residency = 0;
866 }
edp_set_sink_vtotal_in_psr_active(const struct dc_link * link,uint16_t psr_vtotal_idle,uint16_t psr_vtotal_su)867 bool edp_set_sink_vtotal_in_psr_active(const struct dc_link *link, uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su)
868 {
869 	struct dc *dc = link->ctx->dc;
870 	struct dmub_psr *psr = dc->res_pool->psr;
871 
872 	if (psr == NULL || !link->psr_settings.psr_feature_enabled || !link->psr_settings.psr_vtotal_control_support)
873 		return false;
874 
875 	psr->funcs->psr_set_sink_vtotal_in_psr_active(psr, psr_vtotal_idle, psr_vtotal_su);
876 
877 	return true;
878 }
879 
edp_set_replay_allow_active(struct dc_link * link,const bool * allow_active,bool wait,bool force_static,const unsigned int * power_opts)880 bool edp_set_replay_allow_active(struct dc_link *link, const bool *allow_active,
881 	bool wait, bool force_static, const unsigned int *power_opts)
882 {
883 	struct dc  *dc = link->ctx->dc;
884 	struct dmub_replay *replay = dc->res_pool->replay;
885 	unsigned int panel_inst;
886 
887 	if (replay == NULL && force_static)
888 		return false;
889 
890 	if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
891 		return false;
892 
893 	/* Set power optimization flag */
894 	if (power_opts && link->replay_settings.replay_power_opt_active != *power_opts) {
895 		if (link->replay_settings.replay_feature_enabled && replay->funcs->replay_set_power_opt) {
896 			replay->funcs->replay_set_power_opt(replay, *power_opts, panel_inst);
897 			link->replay_settings.replay_power_opt_active = *power_opts;
898 		}
899 	}
900 
901 	/* Activate or deactivate Replay */
902 	if (allow_active && link->replay_settings.replay_allow_active != *allow_active) {
903 		// TODO: Handle mux change case if force_static is set
904 		// If force_static is set, just change the replay_allow_active state directly
905 		if (replay != NULL && link->replay_settings.replay_feature_enabled)
906 			replay->funcs->replay_enable(replay, *allow_active, wait, panel_inst);
907 		link->replay_settings.replay_allow_active = *allow_active;
908 	}
909 
910 	return true;
911 }
912 
edp_get_replay_state(const struct dc_link * link,uint64_t * state)913 bool edp_get_replay_state(const struct dc_link *link, uint64_t *state)
914 {
915 	struct dc  *dc = link->ctx->dc;
916 	struct dmub_replay *replay = dc->res_pool->replay;
917 	unsigned int panel_inst;
918 	enum replay_state pr_state = REPLAY_STATE_0;
919 
920 	if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
921 		return false;
922 
923 	if (replay != NULL && link->replay_settings.replay_feature_enabled)
924 		replay->funcs->replay_get_state(replay, &pr_state, panel_inst);
925 	*state = pr_state;
926 
927 	return true;
928 }
929 
edp_setup_replay(struct dc_link * link,const struct dc_stream_state * stream)930 bool edp_setup_replay(struct dc_link *link, const struct dc_stream_state *stream)
931 {
932 	/* To-do: Setup Replay */
933 	struct dc *dc;
934 	struct dmub_replay *replay;
935 	int i;
936 	unsigned int panel_inst;
937 	struct replay_context replay_context = { 0 };
938 	unsigned int lineTimeInNs = 0;
939 
940 
941 	union replay_enable_and_configuration replay_config;
942 
943 	union dpcd_alpm_configuration alpm_config;
944 
945 	replay_context.controllerId = CONTROLLER_ID_UNDEFINED;
946 
947 	if (!link)
948 		return false;
949 
950 	dc = link->ctx->dc;
951 
952 	replay = dc->res_pool->replay;
953 
954 	if (!replay)
955 		return false;
956 
957 	if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
958 		return false;
959 
960 	replay_context.aux_inst = link->ddc->ddc_pin->hw_info.ddc_channel;
961 	replay_context.digbe_inst = link->link_enc->transmitter;
962 	replay_context.digfe_inst = link->link_enc->preferred_engine;
963 
964 	for (i = 0; i < MAX_PIPES; i++) {
965 		if (dc->current_state->res_ctx.pipe_ctx[i].stream
966 				== stream) {
967 			/* dmcu -1 for all controller id values,
968 			 * therefore +1 here
969 			 */
970 			replay_context.controllerId =
971 				dc->current_state->res_ctx.pipe_ctx[i].stream_res.tg->inst + 1;
972 			break;
973 		}
974 	}
975 
976 	lineTimeInNs =
977 		((stream->timing.h_total * 1000000) /
978 			(stream->timing.pix_clk_100hz / 10)) + 1;
979 
980 	replay_context.line_time_in_ns = lineTimeInNs;
981 
982 	link->replay_settings.replay_feature_enabled =
983 			replay->funcs->replay_copy_settings(replay, link, &replay_context, panel_inst);
984 	if (link->replay_settings.replay_feature_enabled) {
985 
986 		replay_config.bits.FREESYNC_PANEL_REPLAY_MODE = 1;
987 		replay_config.bits.TIMING_DESYNC_ERROR_VERIFICATION =
988 			link->replay_settings.config.replay_timing_sync_supported;
989 		replay_config.bits.STATE_TRANSITION_ERROR_DETECTION = 1;
990 		dm_helpers_dp_write_dpcd(link->ctx, link,
991 			DP_SINK_PR_ENABLE_AND_CONFIGURATION,
992 			(uint8_t *)&(replay_config.raw), sizeof(uint8_t));
993 
994 		memset(&alpm_config, 0, sizeof(alpm_config));
995 		alpm_config.bits.ENABLE = 1;
996 		dm_helpers_dp_write_dpcd(
997 			link->ctx,
998 			link,
999 			DP_RECEIVER_ALPM_CONFIG,
1000 			&alpm_config.raw,
1001 			sizeof(alpm_config.raw));
1002 	}
1003 	return true;
1004 }
1005 
1006 /*
1007  * This is general Interface for Replay to set an 32 bit variable to dmub
1008  * replay_FW_Message_type: Indicates which instruction or variable pass to DMUB
1009  * cmd_data: Value of the config.
1010  */
edp_send_replay_cmd(struct dc_link * link,enum replay_FW_Message_type msg,union dmub_replay_cmd_set * cmd_data)1011 bool edp_send_replay_cmd(struct dc_link *link,
1012 			enum replay_FW_Message_type msg,
1013 			union dmub_replay_cmd_set *cmd_data)
1014 {
1015 	struct dc *dc = link->ctx->dc;
1016 	struct dmub_replay *replay = dc->res_pool->replay;
1017 	unsigned int panel_inst;
1018 
1019 	if (!replay)
1020 		return false;
1021 
1022 	DC_LOGGER_INIT(link->ctx->logger);
1023 
1024 	if (dc_get_edp_link_panel_inst(dc, link, &panel_inst))
1025 		cmd_data->panel_inst = panel_inst;
1026 	else {
1027 		DC_LOG_DC("%s(): get edp panel inst fail ", __func__);
1028 		return false;
1029 	}
1030 
1031 	replay->funcs->replay_send_cmd(replay, msg, cmd_data);
1032 
1033 	return true;
1034 }
1035 
edp_set_coasting_vtotal(struct dc_link * link,uint16_t coasting_vtotal)1036 bool edp_set_coasting_vtotal(struct dc_link *link, uint16_t coasting_vtotal)
1037 {
1038 	struct dc *dc = link->ctx->dc;
1039 	struct dmub_replay *replay = dc->res_pool->replay;
1040 	unsigned int panel_inst;
1041 
1042 	if (!replay)
1043 		return false;
1044 
1045 	if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
1046 		return false;
1047 
1048 	if (coasting_vtotal && link->replay_settings.coasting_vtotal != coasting_vtotal) {
1049 		replay->funcs->replay_set_coasting_vtotal(replay, coasting_vtotal, panel_inst);
1050 		link->replay_settings.coasting_vtotal = coasting_vtotal;
1051 	}
1052 
1053 	return true;
1054 }
1055 
edp_replay_residency(const struct dc_link * link,unsigned int * residency,const bool is_start,const bool is_alpm)1056 bool edp_replay_residency(const struct dc_link *link,
1057 	unsigned int *residency, const bool is_start, const bool is_alpm)
1058 {
1059 	struct dc  *dc = link->ctx->dc;
1060 	struct dmub_replay *replay = dc->res_pool->replay;
1061 	unsigned int panel_inst;
1062 
1063 	if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
1064 		return false;
1065 
1066 	if (replay != NULL && link->replay_settings.replay_feature_enabled)
1067 		replay->funcs->replay_residency(replay, panel_inst, residency, is_start, is_alpm);
1068 	else
1069 		*residency = 0;
1070 
1071 	return true;
1072 }
1073 
edp_set_replay_power_opt_and_coasting_vtotal(struct dc_link * link,const unsigned int * power_opts,uint16_t coasting_vtotal)1074 bool edp_set_replay_power_opt_and_coasting_vtotal(struct dc_link *link,
1075 	const unsigned int *power_opts, uint16_t coasting_vtotal)
1076 {
1077 	struct dc  *dc = link->ctx->dc;
1078 	struct dmub_replay *replay = dc->res_pool->replay;
1079 	unsigned int panel_inst;
1080 
1081 	if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
1082 		return false;
1083 
1084 	/* Only both power and coasting vtotal changed, this func could return true */
1085 	if (power_opts && link->replay_settings.replay_power_opt_active != *power_opts &&
1086 		coasting_vtotal && link->replay_settings.coasting_vtotal != coasting_vtotal) {
1087 		if (link->replay_settings.replay_feature_enabled &&
1088 			replay->funcs->replay_set_power_opt_and_coasting_vtotal) {
1089 			replay->funcs->replay_set_power_opt_and_coasting_vtotal(replay,
1090 				*power_opts, panel_inst, coasting_vtotal);
1091 			link->replay_settings.replay_power_opt_active = *power_opts;
1092 			link->replay_settings.coasting_vtotal = coasting_vtotal;
1093 		} else
1094 			return false;
1095 	} else
1096 		return false;
1097 
1098 	return true;
1099 }
1100 
get_abm_from_stream_res(const struct dc_link * link)1101 static struct abm *get_abm_from_stream_res(const struct dc_link *link)
1102 {
1103 	int i;
1104 	struct dc *dc = link->ctx->dc;
1105 	struct abm *abm = NULL;
1106 
1107 	for (i = 0; i < MAX_PIPES; i++) {
1108 		struct pipe_ctx pipe_ctx = dc->current_state->res_ctx.pipe_ctx[i];
1109 		struct dc_stream_state *stream = pipe_ctx.stream;
1110 
1111 		if (stream && stream->link == link) {
1112 			abm = pipe_ctx.stream_res.abm;
1113 			break;
1114 		}
1115 	}
1116 	return abm;
1117 }
1118 
edp_get_backlight_level(const struct dc_link * link)1119 int edp_get_backlight_level(const struct dc_link *link)
1120 {
1121 	struct abm *abm = get_abm_from_stream_res(link);
1122 	struct panel_cntl *panel_cntl = link->panel_cntl;
1123 	struct dc  *dc = link->ctx->dc;
1124 	struct dmcu *dmcu = dc->res_pool->dmcu;
1125 	bool fw_set_brightness = true;
1126 
1127 	if (dmcu)
1128 		fw_set_brightness = dmcu->funcs->is_dmcu_initialized(dmcu);
1129 
1130 	if (!fw_set_brightness && panel_cntl->funcs->get_current_backlight)
1131 		return panel_cntl->funcs->get_current_backlight(panel_cntl);
1132 	else if (abm != NULL && abm->funcs->get_current_backlight != NULL)
1133 		return (int) abm->funcs->get_current_backlight(abm);
1134 	else
1135 		return DC_ERROR_UNEXPECTED;
1136 }
1137 
edp_get_target_backlight_pwm(const struct dc_link * link)1138 int edp_get_target_backlight_pwm(const struct dc_link *link)
1139 {
1140 	struct abm *abm = get_abm_from_stream_res(link);
1141 
1142 	if (abm == NULL || abm->funcs->get_target_backlight == NULL)
1143 		return DC_ERROR_UNEXPECTED;
1144 
1145 	return (int) abm->funcs->get_target_backlight(abm);
1146 }
1147