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