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