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