FILE
link_dp_training.c
File preview with syntax highlighting.
linux-6.19.14/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
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 all generic dp link training helper functions and top 28 * level generic training sequence. All variations of dp link training sequence 29 * should be called inside the top level training functions in this file to 30 * ensure the integrity of our overall training procedure across different types 31 * of link encoding and back end hardware. 32 */ 33#include "link_dp_training.h" 34#include "link_dp_training_8b_10b.h" 35#include "link_dp_training_128b_132b.h" 36#include "link_dp_training_auxless.h" 37#include "link_dp_training_dpia.h" 38#include "link_dp_training_fixed_vs_pe_retimer.h" 39#include "link_dpcd.h" 40#include "link/accessories/link_dp_trace.h" 41#include "link_dp_phy.h" 42#include "link_dp_capability.h" 43#include "link_edp_panel_control.h" 44#include "link/link_detection.h" 45#include "link/link_validation.h" 46#include "atomfirmware.h" 47#include "link_enc_cfg.h" 48#include "resource.h" 49#include "dm_helpers.h" 50 51#define DC_LOGGER \ 52 link->ctx->logger 53 54#define POST_LT_ADJ_REQ_LIMIT 6 55#define POST_LT_ADJ_REQ_TIMEOUT 200 56#define LINK_TRAINING_RETRY_DELAY 50 /* ms */ 57 58void dp_log_training_result( 59 struct dc_link *link, 60 const struct link_training_settings *lt_settings, 61 enum link_training_result status) 62{ 63 char *link_rate = "Unknown"; 64 char *lt_result = "Unknown"; 65 char *lt_spread = "Disabled"; 66 67 switch (lt_settings->link_settings.link_rate) { 68 case LINK_RATE_LOW: 69 link_rate = "RBR"; 70 break; 71 case LINK_RATE_RATE_2: 72 link_rate = "R2"; 73 break; 74 case LINK_RATE_RATE_3: 75 link_rate = "R3"; 76 break; 77 case LINK_RATE_HIGH: 78 link_rate = "HBR"; 79 break; 80 case LINK_RATE_RBR2: 81 link_rate = "RBR2"; 82 break; 83 case LINK_RATE_RATE_6: 84 link_rate = "R6"; 85 break; 86 case LINK_RATE_HIGH2: 87 link_rate = "HBR2"; 88 break; 89 case LINK_RATE_RATE_8: 90 link_rate = "R8"; 91 break; 92 case LINK_RATE_HIGH3: 93 link_rate = "HBR3"; 94 break; 95 case LINK_RATE_UHBR10: 96 link_rate = "UHBR10"; 97 break; 98 case LINK_RATE_UHBR13_5: 99 link_rate = "UHBR13.5"; 100 break; 101 case LINK_RATE_UHBR20: 102 link_rate = "UHBR20"; 103 break; 104 default: 105 break; 106 } 107 108 switch (status) { 109 case LINK_TRAINING_SUCCESS: 110 lt_result = "pass"; 111 break; 112 case LINK_TRAINING_CR_FAIL_LANE0: 113 lt_result = "CR failed lane0"; 114 break; 115 case LINK_TRAINING_CR_FAIL_LANE1: 116 lt_result = "CR failed lane1"; 117 break; 118 case LINK_TRAINING_CR_FAIL_LANE23: 119 lt_result = "CR failed lane23"; 120 break; 121 case LINK_TRAINING_EQ_FAIL_CR: 122 lt_result = "CR failed in EQ"; 123 break; 124 case LINK_TRAINING_EQ_FAIL_CR_PARTIAL: 125 lt_result = "CR failed in EQ partially"; 126 break; 127 case LINK_TRAINING_EQ_FAIL_EQ: 128 lt_result = "EQ failed"; 129 break; 130 case LINK_TRAINING_LQA_FAIL: 131 lt_result = "LQA failed"; 132 break; 133 case LINK_TRAINING_LINK_LOSS: 134 lt_result = "Link loss"; 135 break; 136 case DP_128b_132b_LT_FAILED: 137 lt_result = "LT_FAILED received"; 138 break; 139 case DP_128b_132b_MAX_LOOP_COUNT_REACHED: 140 lt_result = "max loop count reached"; 141 break; 142 case DP_128b_132b_CHANNEL_EQ_DONE_TIMEOUT: 143 lt_result = "channel EQ timeout"; 144 break; 145 case DP_128b_132b_CDS_DONE_TIMEOUT: 146 lt_result = "CDS timeout"; 147 break; 148 default: 149 break; 150 } 151 152 switch (lt_settings->link_settings.link_spread) { 153 case LINK_SPREAD_DISABLED: 154 lt_spread = "Disabled"; 155 break; 156 case LINK_SPREAD_05_DOWNSPREAD_30KHZ: 157 lt_spread = "0.5% 30KHz"; 158 break; 159 case LINK_SPREAD_05_DOWNSPREAD_33KHZ: 160 lt_spread = "0.5% 33KHz"; 161 break; 162 default: 163 break; 164 } 165 166 /* Connectivity log: link training */ 167 168 /* TODO - DP2.0 Log: add connectivity log for FFE PRESET */ 169 170 CONN_MSG_LT(link, "%sx%d %s VS=%d, PE=%d, DS=%s", 171 link_rate, 172 lt_settings->link_settings.lane_count, 173 lt_result, 174 lt_settings->hw_lane_settings[0].VOLTAGE_SWING, 175 lt_settings->hw_lane_settings[0].PRE_EMPHASIS, 176 lt_spread); 177} 178 179uint8_t dp_initialize_scrambling_data_symbols( 180 struct dc_link *link, 181 enum dc_dp_training_pattern pattern) 182{ 183 uint8_t disable_scrabled_data_symbols = 0; 184 185 switch (pattern) { 186 case DP_TRAINING_PATTERN_SEQUENCE_1: 187 case DP_TRAINING_PATTERN_SEQUENCE_2: 188 case DP_TRAINING_PATTERN_SEQUENCE_3: 189 disable_scrabled_data_symbols = 1; 190 break; 191 case DP_TRAINING_PATTERN_SEQUENCE_4: 192 case DP_128b_132b_TPS1: 193 case DP_128b_132b_TPS2: 194 disable_scrabled_data_symbols = 0; 195 break; 196 default: 197 ASSERT(0); 198 DC_LOG_HW_LINK_TRAINING("%s: Invalid HW Training pattern: %d\n", 199 __func__, pattern); 200 break; 201 } 202 return disable_scrabled_data_symbols; 203} 204 205enum dpcd_training_patterns 206 dp_training_pattern_to_dpcd_training_pattern( 207 struct dc_link *link, 208 enum dc_dp_training_pattern pattern) 209{ 210 enum dpcd_training_patterns dpcd_tr_pattern = 211 DPCD_TRAINING_PATTERN_VIDEOIDLE; 212 213 switch (pattern) { 214 case DP_TRAINING_PATTERN_SEQUENCE_1: 215 DC_LOG_HW_LINK_TRAINING("%s: Using DP training pattern TPS1\n", __func__); 216 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_1; 217 break; 218 case DP_TRAINING_PATTERN_SEQUENCE_2: 219 DC_LOG_HW_LINK_TRAINING("%s: Using DP training pattern TPS2\n", __func__); 220 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_2; 221 break; 222 case DP_TRAINING_PATTERN_SEQUENCE_3: 223 DC_LOG_HW_LINK_TRAINING("%s: Using DP training pattern TPS3\n", __func__); 224 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_3; 225 break; 226 case DP_TRAINING_PATTERN_SEQUENCE_4: 227 DC_LOG_HW_LINK_TRAINING("%s: Using DP training pattern TPS4\n", __func__); 228 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_4; 229 break; 230 case DP_128b_132b_TPS1: 231 DC_LOG_HW_LINK_TRAINING("%s: Using DP 128b/132b training pattern TPS1\n", __func__); 232 dpcd_tr_pattern = DPCD_128b_132b_TPS1; 233 break; 234 case DP_128b_132b_TPS2: 235 DC_LOG_HW_LINK_TRAINING("%s: Using DP 128b/132b training pattern TPS2\n", __func__); 236 dpcd_tr_pattern = DPCD_128b_132b_TPS2; 237 break; 238 case DP_128b_132b_TPS2_CDS: 239 DC_LOG_HW_LINK_TRAINING("%s: Using DP 128b/132b training pattern TPS2 CDS\n", 240 __func__); 241 dpcd_tr_pattern = DPCD_128b_132b_TPS2_CDS; 242 break; 243 case DP_TRAINING_PATTERN_VIDEOIDLE: 244 DC_LOG_HW_LINK_TRAINING("%s: Using DP training pattern videoidle\n", __func__); 245 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_VIDEOIDLE; 246 break; 247 default: 248 ASSERT(0); 249 DC_LOG_HW_LINK_TRAINING("%s: Invalid HW Training pattern: %d\n", 250 __func__, pattern); 251 break; 252 } 253 254 return dpcd_tr_pattern; 255} 256 257uint8_t dp_get_nibble_at_index(const uint8_t *buf, 258 uint32_t index) 259{ 260 uint8_t nibble; 261 nibble = buf[index / 2]; 262 263 if (index % 2) 264 nibble >>= 4; 265 else 266 nibble &= 0x0F; 267 268 return nibble; 269} 270 271void dp_wait_for_training_aux_rd_interval( 272 struct dc_link *link, 273 uint32_t wait_in_micro_secs) 274{ 275 usleep_range_state(wait_in_micro_secs, wait_in_micro_secs, TASK_UNINTERRUPTIBLE); 276 277 DC_LOG_HW_LINK_TRAINING("%s:\n wait = %d\n", 278 __func__, 279 wait_in_micro_secs); 280} 281 282/* maximum pre emphasis level allowed for each voltage swing level*/ 283static const enum dc_pre_emphasis voltage_swing_to_pre_emphasis[] = { 284 PRE_EMPHASIS_LEVEL3, 285 PRE_EMPHASIS_LEVEL2, 286 PRE_EMPHASIS_LEVEL1, 287 PRE_EMPHASIS_DISABLED }; 288 289static enum dc_pre_emphasis get_max_pre_emphasis_for_voltage_swing( 290 enum dc_voltage_swing voltage) 291{ 292 enum dc_pre_emphasis pre_emphasis; 293 pre_emphasis = PRE_EMPHASIS_MAX_LEVEL; 294 295 if (voltage <= VOLTAGE_SWING_MAX_LEVEL) 296 pre_emphasis = voltage_swing_to_pre_emphasis[voltage]; 297 298 return pre_emphasis; 299 300} 301 302static void maximize_lane_settings(const struct link_training_settings *lt_settings, 303 struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]) 304{ 305 uint32_t lane; 306 struct dc_lane_settings max_requested; 307 308 max_requested.VOLTAGE_SWING = lane_settings[0].VOLTAGE_SWING; 309 max_requested.PRE_EMPHASIS = lane_settings[0].PRE_EMPHASIS; 310 max_requested.FFE_PRESET = lane_settings[0].FFE_PRESET; 311 312 /* Determine what the maximum of the requested settings are*/ 313 for (lane = 1; lane < lt_settings->link_settings.lane_count; lane++) { 314 if (lane_settings[lane].VOLTAGE_SWING > max_requested.VOLTAGE_SWING) 315 max_requested.VOLTAGE_SWING = lane_settings[lane].VOLTAGE_SWING; 316 317 if (lane_settings[lane].PRE_EMPHASIS > max_requested.PRE_EMPHASIS) 318 max_requested.PRE_EMPHASIS = lane_settings[lane].PRE_EMPHASIS; 319 if (lane_settings[lane].FFE_PRESET.settings.level > 320 max_requested.FFE_PRESET.settings.level) 321 max_requested.FFE_PRESET.settings.level = 322 lane_settings[lane].FFE_PRESET.settings.level; 323 } 324 325 /* make sure the requested settings are 326 * not higher than maximum settings*/ 327 if (max_requested.VOLTAGE_SWING > VOLTAGE_SWING_MAX_LEVEL) 328 max_requested.VOLTAGE_SWING = VOLTAGE_SWING_MAX_LEVEL; 329 330 if (max_requested.PRE_EMPHASIS > PRE_EMPHASIS_MAX_LEVEL) 331 max_requested.PRE_EMPHASIS = PRE_EMPHASIS_MAX_LEVEL; 332 333 /* Note, we are not checking 334 * if max_requested.FFE_PRESET.settings.level > DP_FFE_PRESET_MAX_LEVEL, 335 * since FFE_PRESET.settings.level is 4 bits and DP_FFE_PRESET_MAX_LEVEL equals 15, 336 * so FFE_PRESET.settings.level will never be greater than 15. 337 */ 338 339 /* make sure the pre-emphasis matches the voltage swing*/ 340 if (max_requested.PRE_EMPHASIS > 341 get_max_pre_emphasis_for_voltage_swing( 342 max_requested.VOLTAGE_SWING)) 343 max_requested.PRE_EMPHASIS = 344 get_max_pre_emphasis_for_voltage_swing( 345 max_requested.VOLTAGE_SWING); 346 347 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) { 348 lane_settings[lane].VOLTAGE_SWING = max_requested.VOLTAGE_SWING; 349 lane_settings[lane].PRE_EMPHASIS = max_requested.PRE_EMPHASIS; 350 lane_settings[lane].FFE_PRESET = max_requested.FFE_PRESET; 351 } 352} 353 354void dp_hw_to_dpcd_lane_settings( 355 const struct link_training_settings *lt_settings, 356 const struct dc_lane_settings hw_lane_settings[LANE_COUNT_DP_MAX], 357 union dpcd_training_lane dpcd_lane_settings[LANE_COUNT_DP_MAX]) 358{ 359 uint8_t lane = 0; 360 361 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) { 362 if (link_dp_get_encoding_format(<_settings->link_settings) == 363 DP_8b_10b_ENCODING) { 364 dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET = 365 (uint8_t)(hw_lane_settings[lane].VOLTAGE_SWING); 366 dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET = 367 (uint8_t)(hw_lane_settings[lane].PRE_EMPHASIS); 368 dpcd_lane_settings[lane].bits.MAX_SWING_REACHED = 369 (hw_lane_settings[lane].VOLTAGE_SWING == 370 VOLTAGE_SWING_MAX_LEVEL ? 1 : 0); 371 dpcd_lane_settings[lane].bits.MAX_PRE_EMPHASIS_REACHED = 372 (hw_lane_settings[lane].PRE_EMPHASIS == 373 PRE_EMPHASIS_MAX_LEVEL ? 1 : 0); 374 } else if (link_dp_get_encoding_format(<_settings->link_settings) == 375 DP_128b_132b_ENCODING) { 376 dpcd_lane_settings[lane].tx_ffe.PRESET_VALUE = 377 hw_lane_settings[lane].FFE_PRESET.settings.level; 378 } 379 } 380} 381 382uint8_t get_dpcd_link_rate(const struct dc_link_settings *link_settings) 383{ 384 uint8_t link_rate = 0; 385 enum dp_link_encoding encoding = link_dp_get_encoding_format(link_settings); 386 387 if (encoding == DP_128b_132b_ENCODING) 388 switch (link_settings->link_rate) { 389 case LINK_RATE_UHBR10: 390 link_rate = 0x1; 391 break; 392 case LINK_RATE_UHBR20: 393 link_rate = 0x2; 394 break; 395 case LINK_RATE_UHBR13_5: 396 link_rate = 0x4; 397 break; 398 default: 399 link_rate = 0; 400 break; 401 } 402 else if (encoding == DP_8b_10b_ENCODING) 403 link_rate = (uint8_t) link_settings->link_rate; 404 else 405 link_rate = 0; 406 407 return link_rate; 408} 409 410/* Only used for channel equalization */ 411uint32_t dp_translate_training_aux_read_interval(uint32_t dpcd_aux_read_interval) 412{ 413 unsigned int aux_rd_interval_us = 400; 414 415 switch (dpcd_aux_read_interval) { 416 case 0x01: 417 aux_rd_interval_us = 4000; 418 break; 419 case 0x02: 420 aux_rd_interval_us = 8000; 421 break; 422 case 0x03: 423 aux_rd_interval_us = 12000; 424 break; 425 case 0x04: 426 aux_rd_interval_us = 16000; 427 break; 428 case 0x05: 429 aux_rd_interval_us = 32000; 430 break; 431 case 0x06: 432 aux_rd_interval_us = 64000; 433 break; 434 default: 435 break; 436 } 437 438 return aux_rd_interval_us; 439} 440 441enum link_training_result dp_get_cr_failure(enum dc_lane_count ln_count, 442 union lane_status *dpcd_lane_status) 443{ 444 enum link_training_result result = LINK_TRAINING_SUCCESS; 445 446 if (ln_count >= LANE_COUNT_ONE && !dpcd_lane_status[0].bits.CR_DONE_0) 447 result = LINK_TRAINING_CR_FAIL_LANE0; 448 else if (ln_count >= LANE_COUNT_TWO && !dpcd_lane_status[1].bits.CR_DONE_0) 449 result = LINK_TRAINING_CR_FAIL_LANE1; 450 else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[2].bits.CR_DONE_0) 451 result = LINK_TRAINING_CR_FAIL_LANE23; 452 else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[3].bits.CR_DONE_0) 453 result = LINK_TRAINING_CR_FAIL_LANE23; 454 return result; 455} 456 457bool is_repeater(const struct link_training_settings *lt_settings, uint32_t offset) 458{ 459 return (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && (offset != 0); 460} 461 462bool dp_is_max_vs_reached( 463 const struct link_training_settings *lt_settings) 464{ 465 uint32_t lane; 466 for (lane = 0; lane < 467 (uint32_t)(lt_settings->link_settings.lane_count); 468 lane++) { 469 if (lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET 470 == VOLTAGE_SWING_MAX_LEVEL) 471 return true; 472 } 473 return false; 474 475} 476 477bool dp_is_cr_done(enum dc_lane_count ln_count, 478 union lane_status *dpcd_lane_status) 479{ 480 bool done = true; 481 uint32_t lane; 482 /*LANEx_CR_DONE bits All 1's?*/ 483 for (lane = 0; lane < (uint32_t)(ln_count); lane++) { 484 if (!dpcd_lane_status[lane].bits.CR_DONE_0) 485 done = false; 486 } 487 return done; 488 489} 490 491bool dp_is_ch_eq_done(enum dc_lane_count ln_count, 492 union lane_status *dpcd_lane_status) 493{ 494 bool done = true; 495 uint32_t lane; 496 for (lane = 0; lane < (uint32_t)(ln_count); lane++) 497 if (!dpcd_lane_status[lane].bits.CHANNEL_EQ_DONE_0) 498 done = false; 499 return done; 500} 501 502bool dp_is_symbol_locked(enum dc_lane_count ln_count, 503 union lane_status *dpcd_lane_status) 504{ 505 bool locked = true; 506 uint32_t lane; 507 for (lane = 0; lane < (uint32_t)(ln_count); lane++) 508 if (!dpcd_lane_status[lane].bits.SYMBOL_LOCKED_0) 509 locked = false; 510 return locked; 511} 512 513bool dp_is_interlane_aligned(union lane_align_status_updated align_status) 514{ 515 return align_status.bits.INTERLANE_ALIGN_DONE == 1; 516} 517 518bool dp_check_interlane_aligned(union lane_align_status_updated align_status, 519 struct dc_link *link, 520 uint8_t retries) 521{ 522 /* Take into consideration corner case for DP 1.4a LL Compliance CTS as USB4 523 * has to share encoders unlike DP and USBC 524 */ 525 return (dp_is_interlane_aligned(align_status) || 526 (link->skip_fallback_on_link_loss && retries)); 527} 528 529uint32_t dp_get_eq_aux_rd_interval( 530 const struct dc_link *link, 531 const struct link_training_settings *lt_settings, 532 uint32_t offset, 533 uint8_t retries) 534{ 535 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) { 536 if (offset == 0 && retries == 1 && lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) 537 return max(lt_settings->eq_pattern_time, (uint32_t) DPIA_CLK_SYNC_DELAY); 538 else 539 return dpia_get_eq_aux_rd_interval(link, lt_settings, offset); 540 } else if (is_repeater(lt_settings, offset)) 541 return dp_translate_training_aux_read_interval( 542 link->dpcd_caps.lttpr_caps.aux_rd_interval[offset - 1]); 543 else 544 return lt_settings->eq_pattern_time; 545} 546 547bool dp_check_dpcd_reqeust_status(const struct dc_link *link, 548 enum dc_status status) 549{ 550 return (status != DC_OK && link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA); 551} 552 553enum link_training_result dp_check_link_loss_status( 554 struct dc_link *link, 555 const struct link_training_settings *link_training_setting) 556{ 557 enum link_training_result status = LINK_TRAINING_SUCCESS; 558 union lane_status lane_status; 559 union lane_align_status_updated dpcd_lane_status_updated; 560 uint8_t dpcd_buf[6] = {0}; 561 uint32_t lane; 562 563 core_link_read_dpcd( 564 link, 565 DP_SINK_COUNT, 566 (uint8_t *)(dpcd_buf), 567 sizeof(dpcd_buf)); 568 569 /*parse lane status*/ 570 for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) { 571 /* 572 * check lanes status 573 */ 574 lane_status.raw = dp_get_nibble_at_index(&dpcd_buf[2], lane); 575 dpcd_lane_status_updated.raw = dpcd_buf[4]; 576 577 if (!lane_status.bits.CHANNEL_EQ_DONE_0 || 578 !lane_status.bits.CR_DONE_0 || 579 !lane_status.bits.SYMBOL_LOCKED_0 || 580 !dp_is_interlane_aligned(dpcd_lane_status_updated)) { 581 /* if one of the channel equalization, clock 582 * recovery or symbol lock is dropped 583 * consider it as (link has been 584 * dropped) dp sink status has changed 585 */ 586 status = LINK_TRAINING_LINK_LOSS; 587 break; 588 } 589 } 590 591 return status; 592} 593 594enum dc_status dp_get_lane_status_and_lane_adjust( 595 struct dc_link *link, 596 const struct link_training_settings *link_training_setting, 597 union lane_status ln_status[LANE_COUNT_DP_MAX], 598 union lane_align_status_updated *ln_align, 599 union lane_adjust ln_adjust[LANE_COUNT_DP_MAX], 600 uint32_t offset) 601{ 602 unsigned int lane01_status_address = DP_LANE0_1_STATUS; 603 uint8_t lane_adjust_offset = 4; 604 unsigned int lane01_adjust_address; 605 uint8_t dpcd_buf[6] = {0}; 606 uint32_t lane; 607 enum dc_status status; 608 609 if (is_repeater(link_training_setting, offset)) { 610 lane01_status_address = 611 DP_LANE0_1_STATUS_PHY_REPEATER1 + 612 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1)); 613 lane_adjust_offset = 3; 614 } 615 616 status = core_link_read_dpcd( 617 link, 618 lane01_status_address, 619 (uint8_t *)(dpcd_buf), 620 sizeof(dpcd_buf)); 621 622 if (status != DC_OK) { 623 DC_LOG_HW_LINK_TRAINING("%s:\n Failed to read from address 0x%X," 624 " keep current lane status and lane adjust unchanged", 625 __func__, 626 lane01_status_address); 627 return status; 628 } 629 630 for (lane = 0; lane < 631 (uint32_t)(link_training_setting->link_settings.lane_count); 632 lane++) { 633 634 ln_status[lane].raw = 635 dp_get_nibble_at_index(&dpcd_buf[0], lane); 636 ln_adjust[lane].raw = 637 dp_get_nibble_at_index(&dpcd_buf[lane_adjust_offset], lane); 638 } 639 640 ln_align->raw = dpcd_buf[2]; 641 642 if (is_repeater(link_training_setting, offset)) { 643 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n" 644 " 0x%X Lane01Status = %x\n 0x%X Lane23Status = %x\n ", 645 __func__, 646 offset, 647 lane01_status_address, dpcd_buf[0], 648 lane01_status_address + 1, dpcd_buf[1]); 649 650 lane01_adjust_address = DP_ADJUST_REQUEST_LANE0_1_PHY_REPEATER1 + 651 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1)); 652 653 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n" 654 " 0x%X Lane01AdjustRequest = %x\n 0x%X Lane23AdjustRequest = %x\n", 655 __func__, 656 offset, 657 lane01_adjust_address, 658 dpcd_buf[lane_adjust_offset], 659 lane01_adjust_address + 1, 660 dpcd_buf[lane_adjust_offset + 1]); 661 } else { 662 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X Lane01Status = %x\n 0x%X Lane23Status = %x\n ", 663 __func__, 664 lane01_status_address, dpcd_buf[0], 665 lane01_status_address + 1, dpcd_buf[1]); 666 667 lane01_adjust_address = DP_ADJUST_REQUEST_LANE0_1; 668 669 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X Lane01AdjustRequest = %x\n 0x%X Lane23AdjustRequest = %x\n", 670 __func__, 671 lane01_adjust_address, 672 dpcd_buf[lane_adjust_offset], 673 lane01_adjust_address + 1, 674 dpcd_buf[lane_adjust_offset + 1]); 675 } 676 677 return status; 678} 679 680static void override_lane_settings(const struct link_training_settings *lt_settings, 681 struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]) 682{ 683 uint32_t lane; 684 685 if (lt_settings->voltage_swing == NULL && 686 lt_settings->pre_emphasis == NULL && 687 lt_settings->ffe_preset == NULL && 688 lt_settings->post_cursor2 == NULL) 689 690 return; 691 692 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) { 693 if (lt_settings->voltage_swing) 694 lane_settings[lane].VOLTAGE_SWING = *lt_settings->voltage_swing; 695 if (lt_settings->pre_emphasis) 696 lane_settings[lane].PRE_EMPHASIS = *lt_settings->pre_emphasis; 697 if (lt_settings->post_cursor2) 698 lane_settings[lane].POST_CURSOR2 = *lt_settings->post_cursor2; 699 if (lt_settings->ffe_preset) 700 lane_settings[lane].FFE_PRESET = *lt_settings->ffe_preset; 701 } 702} 703 704void dp_get_lttpr_mode_override(struct dc_link *link, enum lttpr_mode *override) 705{ 706 if (!dp_is_lttpr_present(link)) 707 return; 708 709 if (link->dc->debug.lttpr_mode_override == LTTPR_MODE_TRANSPARENT) { 710 *override = LTTPR_MODE_TRANSPARENT; 711 } else if (link->dc->debug.lttpr_mode_override == LTTPR_MODE_NON_TRANSPARENT) { 712 *override = LTTPR_MODE_NON_TRANSPARENT; 713 } else if (link->dc->debug.lttpr_mode_override == LTTPR_MODE_NON_LTTPR) { 714 *override = LTTPR_MODE_NON_LTTPR; 715 } 716 DC_LOG_DC("lttpr_mode_override chose LTTPR_MODE = %d\n", (uint8_t)(*override)); 717} 718 719void override_training_settings( 720 struct dc_link *link, 721 const struct dc_link_training_overrides *overrides, 722 struct link_training_settings *lt_settings) 723{ 724 uint32_t lane; 725 726 /* Override link spread */ 727 if (!link->dp_ss_off && overrides->downspread != NULL) 728 lt_settings->link_settings.link_spread = *overrides->downspread ? 729 LINK_SPREAD_05_DOWNSPREAD_30KHZ 730 : LINK_SPREAD_DISABLED; 731 732 /* Override lane settings */ 733 if (overrides->voltage_swing != NULL) 734 lt_settings->voltage_swing = overrides->voltage_swing; 735 if (overrides->pre_emphasis != NULL) 736 lt_settings->pre_emphasis = overrides->pre_emphasis; 737 if (overrides->post_cursor2 != NULL) 738 lt_settings->post_cursor2 = overrides->post_cursor2; 739 if (link->wa_flags.force_dp_ffe_preset && !dp_is_lttpr_present(link)) 740 lt_settings->ffe_preset = &link->forced_dp_ffe_preset; 741 if (overrides->ffe_preset != NULL) 742 lt_settings->ffe_preset = overrides->ffe_preset; 743 /* Override HW lane settings with BIOS forced values if present */ 744 if ((link->chip_caps & AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && 745 lt_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT) { 746 lt_settings->voltage_swing = &link->bios_forced_drive_settings.VOLTAGE_SWING; 747 lt_settings->pre_emphasis = &link->bios_forced_drive_settings.PRE_EMPHASIS; 748 lt_settings->always_match_dpcd_with_hw_lane_settings = false; 749 } 750 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) { 751 lt_settings->hw_lane_settings[lane].VOLTAGE_SWING = 752 lt_settings->voltage_swing != NULL ? 753 *lt_settings->voltage_swing : 754 VOLTAGE_SWING_LEVEL0; 755 lt_settings->hw_lane_settings[lane].PRE_EMPHASIS = 756 lt_settings->pre_emphasis != NULL ? 757 *lt_settings->pre_emphasis 758 : PRE_EMPHASIS_DISABLED; 759 lt_settings->hw_lane_settings[lane].POST_CURSOR2 = 760 lt_settings->post_cursor2 != NULL ? 761 *lt_settings->post_cursor2 762 : POST_CURSOR2_DISABLED; 763 } 764 765 if (lt_settings->always_match_dpcd_with_hw_lane_settings) 766 dp_hw_to_dpcd_lane_settings(lt_settings, 767 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings); 768 769 /* Override training timings */ 770 if (overrides->cr_pattern_time != NULL) 771 lt_settings->cr_pattern_time = *overrides->cr_pattern_time; 772 if (overrides->eq_pattern_time != NULL) 773 lt_settings->eq_pattern_time = *overrides->eq_pattern_time; 774 if (overrides->pattern_for_cr != NULL) 775 lt_settings->pattern_for_cr = *overrides->pattern_for_cr; 776 if (overrides->pattern_for_eq != NULL) 777 lt_settings->pattern_for_eq = *overrides->pattern_for_eq; 778 if (overrides->enhanced_framing != NULL) 779 lt_settings->enhanced_framing = *overrides->enhanced_framing; 780 if (link->preferred_training_settings.fec_enable != NULL) 781 lt_settings->should_set_fec_ready = *link->preferred_training_settings.fec_enable; 782 783 /* Check DP tunnel LTTPR mode debug option. */ 784 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && link->dc->debug.dpia_debug.bits.force_non_lttpr) 785 lt_settings->lttpr_mode = LTTPR_MODE_NON_LTTPR; 786 787 dp_get_lttpr_mode_override(link, <_settings->lttpr_mode); 788} 789 790enum dc_dp_training_pattern decide_cr_training_pattern( 791 const struct dc_link_settings *link_settings) 792{ 793 switch (link_dp_get_encoding_format(link_settings)) { 794 case DP_8b_10b_ENCODING: 795 default: 796 return DP_TRAINING_PATTERN_SEQUENCE_1; 797 case DP_128b_132b_ENCODING: 798 return DP_128b_132b_TPS1; 799 } 800} 801 802enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *link, 803 const struct link_resource *link_res, 804 const struct dc_link_settings *link_settings) 805{ 806 struct link_encoder *link_enc = link_res->dio_link_enc; 807 struct encoder_feature_support *enc_caps; 808 struct dpcd_caps *rx_caps = &link->dpcd_caps; 809 enum dc_dp_training_pattern pattern = DP_TRAINING_PATTERN_SEQUENCE_2; 810 811 switch (link_dp_get_encoding_format(link_settings)) { 812 case DP_8b_10b_ENCODING: 813 if (!link->dc->config.unify_link_enc_assignment) 814 link_enc = link_enc_cfg_get_link_enc(link); 815 816 if (!link_enc) 817 break; 818 819 enc_caps = &link_enc->features; 820 if (enc_caps->flags.bits.IS_TPS4_CAPABLE && 821 rx_caps->max_down_spread.bits.TPS4_SUPPORTED) 822 pattern = DP_TRAINING_PATTERN_SEQUENCE_4; 823 else if (enc_caps->flags.bits.IS_TPS3_CAPABLE && 824 rx_caps->max_ln_count.bits.TPS3_SUPPORTED) 825 pattern = DP_TRAINING_PATTERN_SEQUENCE_3; 826 else 827 pattern = DP_TRAINING_PATTERN_SEQUENCE_2; 828 break; 829 case DP_128b_132b_ENCODING: 830 pattern = DP_128b_132b_TPS2; 831 break; 832 default: 833 pattern = DP_TRAINING_PATTERN_SEQUENCE_2; 834 break; 835 } 836 return pattern; 837} 838 839enum lttpr_mode dp_decide_lttpr_mode(struct dc_link *link, 840 struct dc_link_settings *link_setting) 841{ 842 enum dp_link_encoding encoding = link_dp_get_encoding_format(link_setting); 843 844 if (encoding == DP_8b_10b_ENCODING) 845 return dp_decide_8b_10b_lttpr_mode(link); 846 else if (encoding == DP_128b_132b_ENCODING) 847 return dp_decide_128b_132b_lttpr_mode(link); 848 849 ASSERT(0); 850 return LTTPR_MODE_NON_LTTPR; 851} 852 853void dp_decide_lane_settings( 854 const struct link_training_settings *lt_settings, 855 const union lane_adjust ln_adjust[LANE_COUNT_DP_MAX], 856 struct dc_lane_settings hw_lane_settings[LANE_COUNT_DP_MAX], 857 union dpcd_training_lane *dpcd_lane_settings) 858{ 859 uint32_t lane; 860 861 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) { 862 if (link_dp_get_encoding_format(<_settings->link_settings) == 863 DP_8b_10b_ENCODING) { 864 hw_lane_settings[lane].VOLTAGE_SWING = 865 (enum dc_voltage_swing)(ln_adjust[lane].bits. 866 VOLTAGE_SWING_LANE); 867 hw_lane_settings[lane].PRE_EMPHASIS = 868 (enum dc_pre_emphasis)(ln_adjust[lane].bits. 869 PRE_EMPHASIS_LANE); 870 } else if (link_dp_get_encoding_format(<_settings->link_settings) == 871 DP_128b_132b_ENCODING) { 872 hw_lane_settings[lane].FFE_PRESET.raw = 873 ln_adjust[lane].tx_ffe.PRESET_VALUE; 874 } 875 } 876 dp_hw_to_dpcd_lane_settings(lt_settings, hw_lane_settings, dpcd_lane_settings); 877 878 if (lt_settings->disallow_per_lane_settings) { 879 /* we find the maximum of the requested settings across all lanes*/ 880 /* and set this maximum for all lanes*/ 881 maximize_lane_settings(lt_settings, hw_lane_settings); 882 override_lane_settings(lt_settings, hw_lane_settings); 883 884 if (lt_settings->always_match_dpcd_with_hw_lane_settings) 885 dp_hw_to_dpcd_lane_settings(lt_settings, hw_lane_settings, dpcd_lane_settings); 886 } 887 888} 889 890void dp_decide_training_settings( 891 struct dc_link *link, 892 const struct link_resource *link_res, 893 const struct dc_link_settings *link_settings, 894 struct link_training_settings *lt_settings) 895{ 896 if (link_dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING) 897 decide_8b_10b_training_settings(link, link_res, link_settings, lt_settings); 898 else if (link_dp_get_encoding_format(link_settings) == DP_128b_132b_ENCODING) 899 decide_128b_132b_training_settings(link, link_res, link_settings, lt_settings); 900} 901 902 903enum dc_status configure_lttpr_mode_transparent(struct dc_link *link) 904{ 905 uint8_t repeater_mode = DP_PHY_REPEATER_MODE_TRANSPARENT; 906 907 DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Transparent Mode\n", __func__); 908 return core_link_write_dpcd(link, 909 DP_PHY_REPEATER_MODE, 910 (uint8_t *)&repeater_mode, 911 sizeof(repeater_mode)); 912} 913 914static enum dc_status configure_lttpr_mode_non_transparent( 915 struct dc_link *link, 916 const struct link_training_settings *lt_settings) 917{ 918 /* aux timeout is already set to extended */ 919 /* RESET/SET lttpr mode to enable non transparent mode */ 920 uint8_t repeater_cnt; 921 uint32_t aux_interval_address; 922 uint8_t repeater_id; 923 enum dc_status result = DC_ERROR_UNEXPECTED; 924 uint8_t repeater_mode = DP_PHY_REPEATER_MODE_TRANSPARENT; 925 const struct dc *dc = link->dc; 926 927 enum dp_link_encoding encoding = dc->link_srv->dp_get_encoding_format(<_settings->link_settings); 928 929 if (encoding == DP_8b_10b_ENCODING) { 930 DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Transparent Mode\n", __func__); 931 result = core_link_write_dpcd(link, 932 DP_PHY_REPEATER_MODE, 933 (uint8_t *)&repeater_mode, 934 sizeof(repeater_mode)); 935 936 } 937 938 if (result == DC_OK) { 939 link->dpcd_caps.lttpr_caps.mode = repeater_mode; 940 } 941 942 if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) { 943 944 DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Non Transparent Mode\n", __func__); 945 946 repeater_mode = DP_PHY_REPEATER_MODE_NON_TRANSPARENT; 947 result = core_link_write_dpcd(link, 948 DP_PHY_REPEATER_MODE, 949 (uint8_t *)&repeater_mode, 950 sizeof(repeater_mode)); 951 952 if (result == DC_OK) { 953 link->dpcd_caps.lttpr_caps.mode = repeater_mode; 954 } 955 956 if (encoding == DP_8b_10b_ENCODING) { 957 repeater_cnt = dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt); 958 959 /* Driver does not need to train the first hop. Skip DPCD read and clear 960 * AUX_RD_INTERVAL for DPTX-to-DPIA hop. 961 */ 962 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && repeater_cnt > 0 && repeater_cnt < MAX_REPEATER_CNT) 963 link->dpcd_caps.lttpr_caps.aux_rd_interval[--repeater_cnt] = 0; 964 965 for (repeater_id = repeater_cnt; repeater_id > 0 && repeater_id < MAX_REPEATER_CNT; repeater_id--) { 966 aux_interval_address = DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1 + 967 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (repeater_id - 1)); 968 core_link_read_dpcd( 969 link, 970 aux_interval_address, 971 (uint8_t *)&link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1], 972 sizeof(link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1])); 973 link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1] &= 0x7F; 974 } 975 } 976 } 977 978 return result; 979} 980 981enum dc_status dpcd_configure_lttpr_mode(struct dc_link *link, struct link_training_settings *lt_settings) 982{ 983 enum dc_status status = DC_OK; 984 985 if (lt_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT) 986 status = configure_lttpr_mode_transparent(link); 987 988 else if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) 989 status = configure_lttpr_mode_non_transparent(link, lt_settings); 990 991 return status; 992} 993 994void repeater_training_done(struct dc_link *link, uint32_t offset) 995{ 996 union dpcd_training_pattern dpcd_pattern = {0}; 997 998 const uint32_t dpcd_base_lt_offset = 999 DP_TRAINING_PATTERN_SET_PHY_REPEATER1 + 1000 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1)); 1001 /* Set training not in progress*/ 1002 dpcd_pattern.v1_4.TRAINING_PATTERN_SET = DPCD_TRAINING_PATTERN_VIDEOIDLE; 1003 1004 core_link_write_dpcd( 1005 link, 1006 dpcd_base_lt_offset, 1007 &dpcd_pattern.raw, 1008 1); 1009 1010 DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Id: %d 0x%X pattern = %x\n", 1011 __func__, 1012 offset, 1013 dpcd_base_lt_offset, 1014 dpcd_pattern.v1_4.TRAINING_PATTERN_SET); 1015} 1016 1017static enum link_training_result dpcd_exit_training_mode(struct dc_link *link, enum dp_link_encoding encoding) 1018{ 1019 enum dc_status status; 1020 uint8_t sink_status = 0; 1021 uint32_t i; 1022 uint8_t lttpr_count = dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt); 1023 uint32_t intra_hop_disable_time_ms = (lttpr_count > 0 ? lttpr_count * 300 : 10); 1024 1025 // Each hop could theoretically take over 256ms (max 128b/132b AUX RD INTERVAL) 1026 // To be safe, allow 300ms per LTTPR and 10ms for no LTTPR case 1027 1028 /* clear training pattern set */ 1029 status = dpcd_set_training_pattern(link, DP_TRAINING_PATTERN_VIDEOIDLE); 1030 1031 if (dp_check_dpcd_reqeust_status(link, status)) 1032 return LINK_TRAINING_ABORT; 1033 1034 if (encoding == DP_128b_132b_ENCODING) { 1035 /* poll for intra-hop disable */ 1036 for (i = 0; i < intra_hop_disable_time_ms; i++) { 1037 if ((core_link_read_dpcd(link, DP_SINK_STATUS, &sink_status, 1) == DC_OK) && 1038 (sink_status & DP_INTRA_HOP_AUX_REPLY_INDICATION) == 0) 1039 break; 1040 fsleep(1000); 1041 } 1042 } 1043 1044 return LINK_TRAINING_SUCCESS; 1045} 1046 1047enum dc_status dpcd_configure_channel_coding(struct dc_link *link, 1048 struct link_training_settings *lt_settings) 1049{ 1050 enum dp_link_encoding encoding = 1051 link_dp_get_encoding_format( 1052 <_settings->link_settings); 1053 enum dc_status status; 1054 1055 status = core_link_write_dpcd( 1056 link, 1057 DP_MAIN_LINK_CHANNEL_CODING_SET, 1058 (uint8_t *) &encoding, 1059 1); 1060 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X MAIN_LINK_CHANNEL_CODING_SET = %x\n", 1061 __func__, 1062 DP_MAIN_LINK_CHANNEL_CODING_SET, 1063 encoding); 1064 1065 return status; 1066} 1067 1068enum dc_status dpcd_set_training_pattern( 1069 struct dc_link *link, 1070 enum dc_dp_training_pattern training_pattern) 1071{ 1072 enum dc_status status; 1073 union dpcd_training_pattern dpcd_pattern = {0}; 1074 1075 dpcd_pattern.v1_4.TRAINING_PATTERN_SET = 1076 dp_training_pattern_to_dpcd_training_pattern( 1077 link, training_pattern); 1078 1079 status = core_link_write_dpcd( 1080 link, 1081 DP_TRAINING_PATTERN_SET, 1082 &dpcd_pattern.raw, 1083 1); 1084 1085 DC_LOG_HW_LINK_TRAINING("%s\n %x pattern = %x\n", 1086 __func__, 1087 DP_TRAINING_PATTERN_SET, 1088 dpcd_pattern.v1_4.TRAINING_PATTERN_SET); 1089 1090 return status; 1091} 1092 1093enum dc_status dpcd_set_link_settings( 1094 struct dc_link *link, 1095 const struct link_training_settings *lt_settings) 1096{ 1097 uint8_t rate; 1098 enum dc_status status; 1099 1100 union down_spread_ctrl downspread = {0}; 1101 union lane_count_set lane_count_set = {0}; 1102 1103 downspread.raw = (uint8_t) 1104 (lt_settings->link_settings.link_spread); 1105 1106 lane_count_set.bits.LANE_COUNT_SET = 1107 lt_settings->link_settings.lane_count; 1108 1109 lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing; 1110 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0; 1111 1112 1113 if (link->ep_type == DISPLAY_ENDPOINT_PHY && 1114 lt_settings->pattern_for_eq < DP_TRAINING_PATTERN_SEQUENCE_4) { 1115 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 1116 link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED; 1117 } 1118 1119 status = core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL, 1120 &downspread.raw, sizeof(downspread)); 1121 if (status != DC_OK) 1122 DC_LOG_ERROR("%s:%d: core_link_write_dpcd (DP_DOWNSPREAD_CTRL) failed\n", __func__, __LINE__); 1123 1124 status = core_link_write_dpcd(link, DP_LANE_COUNT_SET, 1125 &lane_count_set.raw, 1); 1126 if (status != DC_OK) 1127 DC_LOG_ERROR("%s:%d: core_link_write_dpcd (DP_LANE_COUNT_SET) failed\n", __func__, __LINE__); 1128 1129 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_13 && 1130 lt_settings->link_settings.use_link_rate_set == true) { 1131 rate = 0; 1132 /* WA for some MUX chips that will power down with eDP and lose supported 1133 * link rate set for eDP 1.4. Source reads DPCD 0x010 again to ensure 1134 * MUX chip gets link rate set back before link training. 1135 */ 1136 if (link->connector_signal == SIGNAL_TYPE_EDP) { 1137 uint8_t supported_link_rates[16] = {0}; 1138 1139 core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES, 1140 supported_link_rates, sizeof(supported_link_rates)); 1141 } 1142 status = core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1); 1143 if (status != DC_OK) 1144 DC_LOG_ERROR("%s:%d: core_link_write_dpcd (DP_LINK_BW_SET) failed\n", __func__, __LINE__); 1145 1146 status = core_link_write_dpcd(link, DP_LINK_RATE_SET, 1147 <_settings->link_settings.link_rate_set, 1); 1148 if (status != DC_OK) 1149 DC_LOG_ERROR("%s:%d: core_link_write_dpcd (DP_LINK_RATE_SET) failed\n", __func__, __LINE__); 1150 } else { 1151 rate = get_dpcd_link_rate(<_settings->link_settings); 1152 1153 status = core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1); 1154 if (status != DC_OK) 1155 DC_LOG_ERROR("%s:%d: core_link_write_dpcd (DP_LINK_BW_SET) failed\n", __func__, __LINE__); 1156 } 1157 1158 if (rate) { 1159 DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x framing = %x\n %x spread = %x\n", 1160 __func__, 1161 DP_LINK_BW_SET, 1162 lt_settings->link_settings.link_rate, 1163 DP_LANE_COUNT_SET, 1164 lt_settings->link_settings.lane_count, 1165 lt_settings->enhanced_framing, 1166 DP_DOWNSPREAD_CTRL, 1167 lt_settings->link_settings.link_spread); 1168 } else { 1169 DC_LOG_HW_LINK_TRAINING("%s\n %x rate set = %x\n %x lane = %x framing = %x\n %x spread = %x\n", 1170 __func__, 1171 DP_LINK_RATE_SET, 1172 lt_settings->link_settings.link_rate_set, 1173 DP_LANE_COUNT_SET, 1174 lt_settings->link_settings.lane_count, 1175 lt_settings->enhanced_framing, 1176 DP_DOWNSPREAD_CTRL, 1177 lt_settings->link_settings.link_spread); 1178 } 1179 1180 return status; 1181} 1182 1183enum dc_status dpcd_set_lane_settings( 1184 struct dc_link *link, 1185 const struct link_training_settings *link_training_setting, 1186 uint32_t offset) 1187{ 1188 unsigned int lane0_set_address; 1189 enum dc_status status; 1190 lane0_set_address = DP_TRAINING_LANE0_SET; 1191 1192 if (is_repeater(link_training_setting, offset)) 1193 lane0_set_address = DP_TRAINING_LANE0_SET_PHY_REPEATER1 + 1194 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1)); 1195 1196 status = core_link_write_dpcd(link, 1197 lane0_set_address, 1198 (uint8_t *)(link_training_setting->dpcd_lane_settings), 1199 link_training_setting->link_settings.lane_count); 1200 1201 if (is_repeater(link_training_setting, offset)) { 1202 DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n" 1203 " 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n", 1204 __func__, 1205 offset, 1206 lane0_set_address, 1207 link_training_setting->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET, 1208 link_training_setting->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET, 1209 link_training_setting->dpcd_lane_settings[0].bits.MAX_SWING_REACHED, 1210 link_training_setting->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED); 1211 1212 } else { 1213 DC_LOG_HW_LINK_TRAINING("%s\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n", 1214 __func__, 1215 lane0_set_address, 1216 link_training_setting->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET, 1217 link_training_setting->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET, 1218 link_training_setting->dpcd_lane_settings[0].bits.MAX_SWING_REACHED, 1219 link_training_setting->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED); 1220 } 1221 1222 return status; 1223} 1224 1225void dpcd_set_lt_pattern_and_lane_settings( 1226 struct dc_link *link, 1227 const struct link_training_settings *lt_settings, 1228 enum dc_dp_training_pattern pattern, 1229 uint32_t offset) 1230{ 1231 uint32_t dpcd_base_lt_offset; 1232 uint8_t dpcd_lt_buffer[5] = {0}; 1233 union dpcd_training_pattern dpcd_pattern = {0}; 1234 uint32_t size_in_bytes; 1235 bool edp_workaround = false; /* TODO link_prop.INTERNAL */ 1236 dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET; 1237 1238 if (is_repeater(lt_settings, offset)) 1239 dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET_PHY_REPEATER1 + 1240 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1)); 1241 1242 /***************************************************************** 1243 * DpcdAddress_TrainingPatternSet 1244 *****************************************************************/ 1245 dpcd_pattern.v1_4.TRAINING_PATTERN_SET = 1246 dp_training_pattern_to_dpcd_training_pattern(link, pattern); 1247 1248 dpcd_pattern.v1_4.SCRAMBLING_DISABLE = 1249 dp_initialize_scrambling_data_symbols(link, pattern); 1250 1251 dpcd_lt_buffer[DP_TRAINING_PATTERN_SET - DP_TRAINING_PATTERN_SET] 1252 = dpcd_pattern.raw; 1253 1254 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) 1255 dpia_set_tps_notification( 1256 link, 1257 lt_settings, 1258 dpcd_pattern.v1_4.TRAINING_PATTERN_SET, 1259 offset); 1260 1261 if (is_repeater(lt_settings, offset)) { 1262 DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n 0x%X pattern = %x\n", 1263 __func__, 1264 offset, 1265 dpcd_base_lt_offset, 1266 dpcd_pattern.v1_4.TRAINING_PATTERN_SET); 1267 } else { 1268 DC_LOG_HW_LINK_TRAINING("%s\n 0x%X pattern = %x\n", 1269 __func__, 1270 dpcd_base_lt_offset, 1271 dpcd_pattern.v1_4.TRAINING_PATTERN_SET); 1272 } 1273 1274 /* concatenate everything into one buffer*/ 1275 size_in_bytes = lt_settings->link_settings.lane_count * 1276 sizeof(lt_settings->dpcd_lane_settings[0]); 1277 1278 // 0x00103 - 0x00102 1279 memmove( 1280 &dpcd_lt_buffer[DP_TRAINING_LANE0_SET - DP_TRAINING_PATTERN_SET], 1281 lt_settings->dpcd_lane_settings, 1282 size_in_bytes); 1283 1284 if (is_repeater(lt_settings, offset)) { 1285 if (link_dp_get_encoding_format(<_settings->link_settings) == 1286 DP_128b_132b_ENCODING) 1287 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n" 1288 " 0x%X TX_FFE_PRESET_VALUE = %x\n", 1289 __func__, 1290 offset, 1291 dpcd_base_lt_offset, 1292 lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE); 1293 else if (link_dp_get_encoding_format(<_settings->link_settings) == 1294 DP_8b_10b_ENCODING) 1295 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n" 1296 " 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n", 1297 __func__, 1298 offset, 1299 dpcd_base_lt_offset, 1300 lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET, 1301 lt_settings->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET, 1302 lt_settings->dpcd_lane_settings[0].bits.MAX_SWING_REACHED, 1303 lt_settings->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED); 1304 } else { 1305 if (link_dp_get_encoding_format(<_settings->link_settings) == 1306 DP_128b_132b_ENCODING) 1307 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X TX_FFE_PRESET_VALUE = %x\n", 1308 __func__, 1309 dpcd_base_lt_offset, 1310 lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE); 1311 else if (link_dp_get_encoding_format(<_settings->link_settings) == 1312 DP_8b_10b_ENCODING) 1313 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n", 1314 __func__, 1315 dpcd_base_lt_offset, 1316 lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET, 1317 lt_settings->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET, 1318 lt_settings->dpcd_lane_settings[0].bits.MAX_SWING_REACHED, 1319 lt_settings->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED); 1320 } 1321 if (edp_workaround) { 1322 /* for eDP write in 2 parts because the 5-byte burst is 1323 * causing issues on some eDP panels (EPR#366724) 1324 */ 1325 core_link_write_dpcd( 1326 link, 1327 DP_TRAINING_PATTERN_SET, 1328 &dpcd_pattern.raw, 1329 sizeof(dpcd_pattern.raw)); 1330 1331 core_link_write_dpcd( 1332 link, 1333 DP_TRAINING_LANE0_SET, 1334 (uint8_t *)(lt_settings->dpcd_lane_settings), 1335 size_in_bytes); 1336 1337 } else if (link_dp_get_encoding_format(<_settings->link_settings) == 1338 DP_128b_132b_ENCODING) { 1339 core_link_write_dpcd( 1340 link, 1341 dpcd_base_lt_offset, 1342 dpcd_lt_buffer, 1343 sizeof(dpcd_lt_buffer)); 1344 } else 1345 /* write it all in (1 + number-of-lanes)-byte burst*/ 1346 core_link_write_dpcd( 1347 link, 1348 dpcd_base_lt_offset, 1349 dpcd_lt_buffer, 1350 size_in_bytes + sizeof(dpcd_pattern.raw)); 1351} 1352 1353void start_clock_recovery_pattern_early(struct dc_link *link, 1354 const struct link_resource *link_res, 1355 struct link_training_settings *lt_settings, 1356 uint32_t offset) 1357{ 1358 DC_LOG_HW_LINK_TRAINING("%s\n GPU sends TPS1. Wait 400us.\n", 1359 __func__); 1360 dp_set_hw_training_pattern(link, link_res, lt_settings->pattern_for_cr, offset); 1361 dp_set_hw_lane_settings(link, link_res, lt_settings, offset); 1362 udelay(400); 1363} 1364 1365void dp_set_hw_test_pattern( 1366 struct dc_link *link, 1367 const struct link_resource *link_res, 1368 enum dp_test_pattern test_pattern, 1369 uint8_t *custom_pattern, 1370 uint32_t custom_pattern_size) 1371{ 1372 const struct link_hwss *link_hwss = get_link_hwss(link, link_res); 1373 struct encoder_set_dp_phy_pattern_param pattern_param = {0}; 1374 1375 pattern_param.dp_phy_pattern = test_pattern; 1376 pattern_param.custom_pattern = custom_pattern; 1377 pattern_param.custom_pattern_size = custom_pattern_size; 1378 pattern_param.dp_panel_mode = dp_get_panel_mode(link); 1379 1380 if (link_hwss->ext.set_dp_link_test_pattern) 1381 link_hwss->ext.set_dp_link_test_pattern(link, link_res, &pattern_param); 1382} 1383 1384bool dp_set_hw_training_pattern( 1385 struct dc_link *link, 1386 const struct link_resource *link_res, 1387 enum dc_dp_training_pattern pattern, 1388 uint32_t offset) 1389{ 1390 enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED; 1391 1392 switch (pattern) { 1393 case DP_TRAINING_PATTERN_SEQUENCE_1: 1394 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN1; 1395 break; 1396 case DP_TRAINING_PATTERN_SEQUENCE_2: 1397 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN2; 1398 break; 1399 case DP_TRAINING_PATTERN_SEQUENCE_3: 1400 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN3; 1401 break; 1402 case DP_TRAINING_PATTERN_SEQUENCE_4: 1403 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4; 1404 break; 1405 case DP_128b_132b_TPS1: 1406 test_pattern = DP_TEST_PATTERN_128b_132b_TPS1_TRAINING_MODE; 1407 break; 1408 case DP_128b_132b_TPS2: 1409 test_pattern = DP_TEST_PATTERN_128b_132b_TPS2_TRAINING_MODE; 1410 break; 1411 default: 1412 break; 1413 } 1414 1415 dp_set_hw_test_pattern(link, link_res, test_pattern, NULL, 0); 1416 1417 return true; 1418} 1419 1420static bool perform_post_lt_adj_req_sequence( 1421 struct dc_link *link, 1422 const struct link_resource *link_res, 1423 struct link_training_settings *lt_settings) 1424{ 1425 enum dc_lane_count lane_count = 1426 lt_settings->link_settings.lane_count; 1427 1428 uint32_t adj_req_count; 1429 uint32_t adj_req_timer; 1430 bool req_drv_setting_changed; 1431 uint32_t lane; 1432 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0}; 1433 union lane_align_status_updated dpcd_lane_status_updated = {0}; 1434 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0}; 1435 1436 req_drv_setting_changed = false; 1437 for (adj_req_count = 0; adj_req_count < POST_LT_ADJ_REQ_LIMIT; 1438 adj_req_count++) { 1439 1440 req_drv_setting_changed = false; 1441 1442 for (adj_req_timer = 0; 1443 adj_req_timer < POST_LT_ADJ_REQ_TIMEOUT; 1444 adj_req_timer++) { 1445 1446 dp_get_lane_status_and_lane_adjust( 1447 link, 1448 lt_settings, 1449 dpcd_lane_status, 1450 &dpcd_lane_status_updated, 1451 dpcd_lane_adjust, 1452 DPRX); 1453 1454 if (dpcd_lane_status_updated.bits. 1455 POST_LT_ADJ_REQ_IN_PROGRESS == 0) 1456 return true; 1457 1458 if (!dp_is_cr_done(lane_count, dpcd_lane_status)) 1459 return false; 1460 1461 if (!dp_is_ch_eq_done(lane_count, dpcd_lane_status) || 1462 !dp_is_symbol_locked(lane_count, dpcd_lane_status) || 1463 !dp_is_interlane_aligned(dpcd_lane_status_updated)) 1464 return false; 1465 1466 for (lane = 0; lane < (uint32_t)(lane_count); lane++) { 1467 1468 if (lt_settings-> 1469 dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET != 1470 dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_LANE || 1471 lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET != 1472 dpcd_lane_adjust[lane].bits.PRE_EMPHASIS_LANE) { 1473 1474 req_drv_setting_changed = true; 1475 break; 1476 } 1477 } 1478 1479 if (req_drv_setting_changed) { 1480 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust, 1481 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings); 1482 1483 dp_set_drive_settings(link, 1484 link_res, 1485 lt_settings); 1486 break; 1487 } 1488 1489 msleep(1); 1490 } 1491 1492 if (!req_drv_setting_changed) { 1493 DC_LOG_WARNING("%s: Post Link Training Adjust Request Timed out\n", 1494 __func__); 1495 1496 ASSERT(0); 1497 return true; 1498 } 1499 } 1500 DC_LOG_WARNING("%s: Post Link Training Adjust Request limit reached\n", 1501 __func__); 1502 1503 ASSERT(0); 1504 return true; 1505 1506} 1507 1508static enum link_training_result dp_transition_to_video_idle( 1509 struct dc_link *link, 1510 const struct link_resource *link_res, 1511 struct link_training_settings *lt_settings, 1512 enum link_training_result status) 1513{ 1514 union lane_count_set lane_count_set = {0}; 1515 1516 /* 4. mainlink output idle pattern*/ 1517 dp_set_hw_test_pattern(link, link_res, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0); 1518 1519 /* 1520 * 5. post training adjust if required 1521 * If the upstream DPTX and downstream DPRX both support TPS4, 1522 * TPS4 must be used instead of POST_LT_ADJ_REQ. 1523 */ 1524 if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED != 1 || 1525 lt_settings->pattern_for_eq >= DP_TRAINING_PATTERN_SEQUENCE_4) { 1526 /* delay 5ms after Main Link output idle pattern and then check 1527 * DPCD 0202h. 1528 */ 1529 if (link->connector_signal != SIGNAL_TYPE_EDP && status == LINK_TRAINING_SUCCESS) { 1530 msleep(5); 1531 if (!link->skip_fallback_on_link_loss) 1532 status = dp_check_link_loss_status(link, lt_settings); 1533 } 1534 return status; 1535 } 1536 1537 if (status == LINK_TRAINING_SUCCESS && 1538 perform_post_lt_adj_req_sequence(link, link_res, lt_settings) == false) 1539 status = LINK_TRAINING_LQA_FAIL; 1540 1541 lane_count_set.bits.LANE_COUNT_SET = lt_settings->link_settings.lane_count; 1542 lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing; 1543 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0; 1544 1545 core_link_write_dpcd( 1546 link, 1547 DP_LANE_COUNT_SET, 1548 &lane_count_set.raw, 1549 sizeof(lane_count_set)); 1550 1551 return status; 1552} 1553 1554enum link_training_result dp_perform_link_training( 1555 struct dc_link *link, 1556 const struct link_resource *link_res, 1557 const struct dc_link_settings *link_settings, 1558 bool skip_video_pattern) 1559{ 1560 enum link_training_result status = LINK_TRAINING_SUCCESS; 1561 struct link_training_settings lt_settings = {0}; 1562 enum dp_link_encoding encoding = 1563 link_dp_get_encoding_format(link_settings); 1564 1565 /* decide training settings */ 1566 dp_decide_training_settings( 1567 link, 1568 link_res, 1569 link_settings, 1570 <_settings); 1571 1572 override_training_settings( 1573 link, 1574 &link->preferred_training_settings, 1575 <_settings); 1576 1577 /* reset previous training states */ 1578 dpcd_exit_training_mode(link, encoding); 1579 1580 /* configure link prior to entering training mode */ 1581 dpcd_configure_lttpr_mode(link, <_settings); 1582 if (link_dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING) 1583 dp_set_fec_ready(link, link_res, lt_settings.should_set_fec_ready); 1584 dpcd_configure_channel_coding(link, <_settings); 1585 1586 /* enter training mode: 1587 * Per DP specs starting from here, DPTX device shall not issue 1588 * Non-LT AUX transactions inside training mode. 1589 */ 1590 if (((link->chip_caps & AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK) == AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && encoding == DP_8b_10b_ENCODING) 1591 status = dp_perform_fixed_vs_pe_training_sequence(link, link_res, <_settings); 1592 else if (encoding == DP_8b_10b_ENCODING) 1593 status = dp_perform_8b_10b_link_training(link, link_res, <_settings); 1594 else if (encoding == DP_128b_132b_ENCODING) 1595 status = dp_perform_128b_132b_link_training(link, link_res, <_settings); 1596 else 1597 ASSERT(0); 1598 1599 /* exit training mode */ 1600 if ((dpcd_exit_training_mode(link, encoding) != LINK_TRAINING_SUCCESS || status == LINK_TRAINING_ABORT) && 1601 link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) 1602 dpia_training_abort(link, <_settings, 0); 1603 1604 /* switch to video idle */ 1605 if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern) 1606 status = dp_transition_to_video_idle(link, 1607 link_res, 1608 <_settings, 1609 status); 1610 1611 /* dump debug data */ 1612 dp_log_training_result(link, <_settings, status); 1613 if (status != LINK_TRAINING_SUCCESS) 1614 link->ctx->dc->debug_data.ltFailCount++; 1615 return status; 1616} 1617 1618bool perform_link_training_with_retries( 1619 const struct dc_link_settings *link_setting, 1620 bool skip_video_pattern, 1621 int attempts, 1622 struct pipe_ctx *pipe_ctx, 1623 enum signal_type signal, 1624 bool do_fallback) 1625{ 1626 int j; 1627 uint8_t delay_between_attempts = LINK_TRAINING_RETRY_DELAY; 1628 struct dc_stream_state *stream = pipe_ctx->stream; 1629 struct dc_link *link = stream->link; 1630 enum dp_panel_mode panel_mode = dp_get_panel_mode(link); 1631 enum link_training_result status = LINK_TRAINING_CR_FAIL_LANE0; 1632 struct dc_link_settings cur_link_settings = *link_setting; 1633 struct dc_link_settings max_link_settings = *link_setting; 1634 const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); 1635 int fail_count = 0; 1636 bool is_link_bw_low = false; /* link bandwidth < stream bandwidth */ 1637 bool is_link_bw_min = /* RBR x 1 */ 1638 (cur_link_settings.link_rate <= LINK_RATE_LOW) && 1639 (cur_link_settings.lane_count <= LANE_COUNT_ONE); 1640 1641 dp_trace_commit_lt_init(link); 1642 1643 1644 if (link_dp_get_encoding_format(&cur_link_settings) == DP_8b_10b_ENCODING) 1645 /* We need to do this before the link training to ensure the idle 1646 * pattern in SST mode will be sent right after the link training 1647 */ 1648 link_hwss->setup_stream_encoder(pipe_ctx); 1649 1650 dp_trace_set_lt_start_timestamp(link, false); 1651 j = 0; 1652 while (j < attempts && fail_count < (attempts * 10)) { 1653 1654 DC_LOG_HW_LINK_TRAINING("%s: Beginning link(%d) training attempt %u of %d @ rate(%d) x lane(%d) @ spread = %x\n", 1655 __func__, link->link_index, (unsigned int)j + 1, attempts, 1656 cur_link_settings.link_rate, cur_link_settings.lane_count, 1657 cur_link_settings.link_spread); 1658 1659 dp_enable_link_phy( 1660 link, 1661 &pipe_ctx->link_res, 1662 signal, 1663 pipe_ctx->clock_source->id, 1664 &cur_link_settings); 1665 1666 if (stream->sink_patches.dppowerup_delay > 0) { 1667 int delay_dp_power_up_in_ms = stream->sink_patches.dppowerup_delay; 1668 1669 msleep(delay_dp_power_up_in_ms); 1670 } 1671 1672 edp_set_panel_assr(link, pipe_ctx, &panel_mode, true); 1673 1674 dp_set_panel_mode(link, panel_mode); 1675 1676 if (link->aux_access_disabled) { 1677 dp_perform_link_training_skip_aux(link, &pipe_ctx->link_res, &cur_link_settings); 1678 return true; 1679 } else { 1680 if (!link->dc->config.consolidated_dpia_dp_lt && link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) { 1681 status = dpia_perform_link_training( 1682 link, 1683 &pipe_ctx->link_res, 1684 &cur_link_settings, 1685 skip_video_pattern); 1686 1687 /* Transmit idle pattern once training successful. */ 1688 if (status == LINK_TRAINING_SUCCESS && !is_link_bw_low) { 1689 dp_set_hw_test_pattern(link, &pipe_ctx->link_res, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0); 1690 // Update verified link settings to current one 1691 // Because DPIA LT might fallback to lower link setting. 1692 if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { 1693 link->verified_link_cap.link_rate = link->cur_link_settings.link_rate; 1694 link->verified_link_cap.lane_count = link->cur_link_settings.lane_count; 1695 dm_helpers_dp_mst_update_branch_bandwidth(link->ctx, link); 1696 } 1697 } 1698 } else { 1699 status = dp_perform_link_training( 1700 link, 1701 &pipe_ctx->link_res, 1702 &cur_link_settings, 1703 skip_video_pattern); 1704 } 1705 1706 dp_trace_lt_total_count_increment(link, false); 1707 dp_trace_lt_result_update(link, status, false); 1708 dp_trace_set_lt_end_timestamp(link, false); 1709 if (status == LINK_TRAINING_SUCCESS && !is_link_bw_low) { 1710 // Update verified link settings to current one 1711 // Because DPIA LT might fallback to lower link setting. 1712 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && 1713 stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { 1714 link->verified_link_cap.link_rate = link->cur_link_settings.link_rate; 1715 link->verified_link_cap.lane_count = link->cur_link_settings.lane_count; 1716 dm_helpers_dp_mst_update_branch_bandwidth(link->ctx, link); 1717 } 1718 return true; 1719 } 1720 } 1721 1722 fail_count++; 1723 dp_trace_lt_fail_count_update(link, fail_count, false); 1724 if (link->ep_type == DISPLAY_ENDPOINT_PHY) { 1725 /* latest link training still fail or link training is aborted 1726 * skip delay and keep PHY on 1727 */ 1728 if (j == (attempts - 1) || (status == LINK_TRAINING_ABORT)) 1729 break; 1730 } 1731 1732 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && 1733 stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST && 1734 !link->dc->config.enable_dpia_pre_training) { 1735 if (j == (attempts - 1)) 1736 do_fallback = true; 1737 else 1738 do_fallback = false; 1739 } 1740 1741 if (j == (attempts - 1)) { 1742 DC_LOG_WARNING( 1743 "%s: Link(%d) training attempt %u of %d failed @ rate(%d) x lane(%d) @ spread = %x : fail reason:(%d)\n", 1744 __func__, link->link_index, (unsigned int)j + 1, attempts, 1745 cur_link_settings.link_rate, cur_link_settings.lane_count, 1746 cur_link_settings.link_spread, status); 1747 } else { 1748 DC_LOG_HW_LINK_TRAINING( 1749 "%s: Link(%d) training attempt %u of %d failed @ rate(%d) x lane(%d) @ spread = %x : fail reason:(%d)\n", 1750 __func__, link->link_index, (unsigned int)j + 1, attempts, 1751 cur_link_settings.link_rate, cur_link_settings.lane_count, 1752 cur_link_settings.link_spread, status); 1753 } 1754 1755 dp_disable_link_phy(link, &pipe_ctx->link_res, signal); 1756 1757 /* Abort link training if failure due to sink being unplugged. */ 1758 if (status == LINK_TRAINING_ABORT) { 1759 enum dc_connection_type type = dc_connection_none; 1760 1761 if (link_detect_connection_type(link, &type) && type == dc_connection_none) { 1762 DC_LOG_HW_LINK_TRAINING("%s: Aborting training because sink unplugged\n", __func__); 1763 break; 1764 } 1765 } 1766 1767 /* Try to train again at original settings if: 1768 * - not falling back between training attempts; 1769 * - aborted previous attempt due to reasons other than sink unplug; 1770 * - successfully trained but at a link rate lower than that required by stream; 1771 * - reached minimum link bandwidth. 1772 */ 1773 if (!do_fallback || (status == LINK_TRAINING_ABORT) || 1774 (status == LINK_TRAINING_SUCCESS && is_link_bw_low) || 1775 is_link_bw_min) { 1776 j++; 1777 cur_link_settings = *link_setting; 1778 delay_between_attempts += LINK_TRAINING_RETRY_DELAY; 1779 is_link_bw_low = false; 1780 is_link_bw_min = (cur_link_settings.link_rate <= LINK_RATE_LOW) && 1781 (cur_link_settings.lane_count <= LANE_COUNT_ONE); 1782 1783 } else if (do_fallback) { /* Try training at lower link bandwidth if doing fallback. */ 1784 uint32_t req_bw; 1785 uint32_t link_bw; 1786 enum dc_link_encoding_format link_encoding = DC_LINK_ENCODING_UNSPECIFIED; 1787 1788 decide_fallback_link_setting(link, &max_link_settings, 1789 &cur_link_settings, status); 1790 1791 if (link_dp_get_encoding_format(&cur_link_settings) == DP_8b_10b_ENCODING) 1792 link_encoding = DC_LINK_ENCODING_DP_8b_10b; 1793 else if (link_dp_get_encoding_format(&cur_link_settings) == DP_128b_132b_ENCODING) 1794 link_encoding = DC_LINK_ENCODING_DP_128b_132b; 1795 1796 /* Flag if reduced link bandwidth no longer meets stream requirements or fallen back to 1797 * minimum link bandwidth. 1798 */ 1799 req_bw = dc_bandwidth_in_kbps_from_timing(&stream->timing, link_encoding); 1800 link_bw = dp_link_bandwidth_kbps(link, &cur_link_settings); 1801 is_link_bw_low = (req_bw > link_bw); 1802 is_link_bw_min = ((cur_link_settings.link_rate <= LINK_RATE_LOW) && 1803 (cur_link_settings.lane_count <= LANE_COUNT_ONE)); 1804 1805 if (is_link_bw_low) 1806 DC_LOG_WARNING( 1807 "%s: Link(%d) bandwidth too low after fallback req_bw(%d) > link_bw(%d)\n", 1808 __func__, link->link_index, req_bw, link_bw); 1809 } 1810 1811 msleep(delay_between_attempts); 1812 } 1813 1814 return false; 1815} 1816
~/
Read-only file preview.