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 dp 8b/10b link training software policies and 28 * sequences. 29 */ 30 #include "link_dp_training_8b_10b.h" 31 #include "link_dpcd.h" 32 #include "link_dp_phy.h" 33 #include "link_dp_capability.h" 34 35 #define DC_LOGGER \ 36 link->ctx->logger 37 38 static int32_t get_cr_training_aux_rd_interval(struct dc_link *link, 39 const struct dc_link_settings *link_settings) 40 { 41 union training_aux_rd_interval training_rd_interval; 42 uint32_t wait_in_micro_secs = 100; 43 44 memset(&training_rd_interval, 0, sizeof(training_rd_interval)); 45 if (link_dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING && 46 link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { 47 core_link_read_dpcd( 48 link, 49 DP_TRAINING_AUX_RD_INTERVAL, 50 (uint8_t *)&training_rd_interval, 51 sizeof(training_rd_interval)); 52 if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL) 53 wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000; 54 } 55 return wait_in_micro_secs; 56 } 57 58 static uint32_t get_eq_training_aux_rd_interval( 59 struct dc_link *link, 60 const struct dc_link_settings *link_settings) 61 { 62 union training_aux_rd_interval training_rd_interval; 63 64 memset(&training_rd_interval, 0, sizeof(training_rd_interval)); 65 if (link_dp_get_encoding_format(link_settings) == DP_128b_132b_ENCODING) { 66 core_link_read_dpcd( 67 link, 68 DP_128B132B_TRAINING_AUX_RD_INTERVAL, 69 (uint8_t *)&training_rd_interval, 70 sizeof(training_rd_interval)); 71 } else if (link_dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING && 72 link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { 73 core_link_read_dpcd( 74 link, 75 DP_TRAINING_AUX_RD_INTERVAL, 76 (uint8_t *)&training_rd_interval, 77 sizeof(training_rd_interval)); 78 } 79 80 switch (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL) { 81 case 0: return 400; 82 case 1: return 4000; 83 case 2: return 8000; 84 case 3: return 12000; 85 case 4: return 16000; 86 case 5: return 32000; 87 case 6: return 64000; 88 default: return 400; 89 } 90 } 91 92 void decide_8b_10b_training_settings( 93 struct dc_link *link, 94 const struct dc_link_settings *link_setting, 95 struct link_training_settings *lt_settings) 96 { 97 memset(lt_settings, '\0', sizeof(struct link_training_settings)); 98 99 /* Initialize link settings */ 100 lt_settings->link_settings.use_link_rate_set = link_setting->use_link_rate_set; 101 lt_settings->link_settings.link_rate_set = link_setting->link_rate_set; 102 lt_settings->link_settings.link_rate = link_setting->link_rate; 103 lt_settings->link_settings.lane_count = link_setting->lane_count; 104 /* TODO hard coded to SS for now 105 * lt_settings.link_settings.link_spread = 106 * dal_display_path_is_ss_supported( 107 * path_mode->display_path) ? 108 * LINK_SPREAD_05_DOWNSPREAD_30KHZ : 109 * LINK_SPREAD_DISABLED; 110 */ 111 lt_settings->link_settings.link_spread = link->dp_ss_off ? 112 LINK_SPREAD_DISABLED : LINK_SPREAD_05_DOWNSPREAD_30KHZ; 113 lt_settings->cr_pattern_time = get_cr_training_aux_rd_interval(link, link_setting); 114 lt_settings->eq_pattern_time = get_eq_training_aux_rd_interval(link, link_setting); 115 lt_settings->pattern_for_cr = decide_cr_training_pattern(link_setting); 116 lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_setting); 117 lt_settings->enhanced_framing = 1; 118 lt_settings->should_set_fec_ready = true; 119 lt_settings->disallow_per_lane_settings = true; 120 lt_settings->always_match_dpcd_with_hw_lane_settings = true; 121 lt_settings->lttpr_mode = dp_decide_8b_10b_lttpr_mode(link); 122 dp_hw_to_dpcd_lane_settings(lt_settings, lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings); 123 } 124 125 enum lttpr_mode dp_decide_8b_10b_lttpr_mode(struct dc_link *link) 126 { 127 bool is_lttpr_present = dp_is_lttpr_present(link); 128 bool vbios_lttpr_force_non_transparent = link->dc->caps.vbios_lttpr_enable; 129 bool vbios_lttpr_aware = link->dc->caps.vbios_lttpr_aware; 130 131 if (!is_lttpr_present) 132 return LTTPR_MODE_NON_LTTPR; 133 134 if (vbios_lttpr_aware) { 135 if (vbios_lttpr_force_non_transparent) { 136 DC_LOG_DC("chose LTTPR_MODE_NON_TRANSPARENT due to VBIOS DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE set to 1.\n"); 137 return LTTPR_MODE_NON_TRANSPARENT; 138 } else { 139 DC_LOG_DC("chose LTTPR_MODE_NON_TRANSPARENT by default due to VBIOS not set DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE set to 1.\n"); 140 return LTTPR_MODE_TRANSPARENT; 141 } 142 } 143 144 if (link->dc->config.allow_lttpr_non_transparent_mode.bits.DP1_4A && 145 link->dc->caps.extended_aux_timeout_support) { 146 DC_LOG_DC("chose LTTPR_MODE_NON_TRANSPARENT by default and dc->config.allow_lttpr_non_transparent_mode.bits.DP1_4A set to 1.\n"); 147 return LTTPR_MODE_NON_TRANSPARENT; 148 } 149 150 DC_LOG_DC("chose LTTPR_MODE_NON_LTTPR.\n"); 151 return LTTPR_MODE_NON_LTTPR; 152 } 153 154 enum link_training_result perform_8b_10b_clock_recovery_sequence( 155 struct dc_link *link, 156 const struct link_resource *link_res, 157 struct link_training_settings *lt_settings, 158 uint32_t offset) 159 { 160 uint32_t retries_cr; 161 uint32_t retry_count; 162 uint32_t wait_time_microsec; 163 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count; 164 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX]; 165 union lane_align_status_updated dpcd_lane_status_updated; 166 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0}; 167 168 retries_cr = 0; 169 retry_count = 0; 170 171 memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status)); 172 memset(&dpcd_lane_status_updated, '\0', 173 sizeof(dpcd_lane_status_updated)); 174 175 if (!link->ctx->dc->work_arounds.lt_early_cr_pattern) 176 dp_set_hw_training_pattern(link, link_res, lt_settings->pattern_for_cr, offset); 177 178 /* najeeb - The synaptics MST hub can put the LT in 179 * infinite loop by switching the VS 180 */ 181 /* between level 0 and level 1 continuously, here 182 * we try for CR lock for LinkTrainingMaxCRRetry count*/ 183 while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) && 184 (retry_count < LINK_TRAINING_MAX_CR_RETRY)) { 185 186 187 /* 1. call HWSS to set lane settings*/ 188 dp_set_hw_lane_settings( 189 link, 190 link_res, 191 lt_settings, 192 offset); 193 194 /* 2. update DPCD of the receiver*/ 195 if (!retry_count) 196 /* EPR #361076 - write as a 5-byte burst, 197 * but only for the 1-st iteration.*/ 198 dpcd_set_lt_pattern_and_lane_settings( 199 link, 200 lt_settings, 201 lt_settings->pattern_for_cr, 202 offset); 203 else 204 dpcd_set_lane_settings( 205 link, 206 lt_settings, 207 offset); 208 209 /* 3. wait receiver to lock-on*/ 210 wait_time_microsec = lt_settings->cr_pattern_time; 211 212 dp_wait_for_training_aux_rd_interval( 213 link, 214 wait_time_microsec); 215 216 /* 4. Read lane status and requested drive 217 * settings as set by the sink 218 */ 219 dp_get_lane_status_and_lane_adjust( 220 link, 221 lt_settings, 222 dpcd_lane_status, 223 &dpcd_lane_status_updated, 224 dpcd_lane_adjust, 225 offset); 226 227 /* 5. check CR done*/ 228 if (dp_is_cr_done(lane_count, dpcd_lane_status)) { 229 DC_LOG_HW_LINK_TRAINING("%s: Clock recovery OK\n", __func__); 230 return LINK_TRAINING_SUCCESS; 231 } 232 233 /* 6. max VS reached*/ 234 if ((link_dp_get_encoding_format(<_settings->link_settings) == 235 DP_8b_10b_ENCODING) && 236 dp_is_max_vs_reached(lt_settings)) 237 break; 238 239 /* 7. same lane settings*/ 240 /* Note: settings are the same for all lanes, 241 * so comparing first lane is sufficient*/ 242 if ((link_dp_get_encoding_format(<_settings->link_settings) == DP_8b_10b_ENCODING) && 243 lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET == 244 dpcd_lane_adjust[0].bits.VOLTAGE_SWING_LANE) 245 retries_cr++; 246 else if ((link_dp_get_encoding_format(<_settings->link_settings) == DP_128b_132b_ENCODING) && 247 lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE == 248 dpcd_lane_adjust[0].tx_ffe.PRESET_VALUE) 249 retries_cr++; 250 else 251 retries_cr = 0; 252 253 /* 8. update VS/PE/PC2 in lt_settings*/ 254 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust, 255 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings); 256 retry_count++; 257 } 258 259 if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) { 260 ASSERT(0); 261 DC_LOG_ERROR("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue", 262 __func__, 263 LINK_TRAINING_MAX_CR_RETRY); 264 265 } 266 267 return dp_get_cr_failure(lane_count, dpcd_lane_status); 268 } 269 270 enum link_training_result perform_8b_10b_channel_equalization_sequence( 271 struct dc_link *link, 272 const struct link_resource *link_res, 273 struct link_training_settings *lt_settings, 274 uint32_t offset) 275 { 276 enum dc_dp_training_pattern tr_pattern; 277 uint32_t retries_ch_eq; 278 uint32_t wait_time_microsec; 279 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count; 280 union lane_align_status_updated dpcd_lane_status_updated = {0}; 281 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0}; 282 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0}; 283 284 /* Note: also check that TPS4 is a supported feature*/ 285 tr_pattern = lt_settings->pattern_for_eq; 286 287 if (is_repeater(lt_settings, offset) && link_dp_get_encoding_format(<_settings->link_settings) == DP_8b_10b_ENCODING) 288 tr_pattern = DP_TRAINING_PATTERN_SEQUENCE_4; 289 290 dp_set_hw_training_pattern(link, link_res, tr_pattern, offset); 291 292 for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT; 293 retries_ch_eq++) { 294 295 dp_set_hw_lane_settings(link, link_res, lt_settings, offset); 296 297 /* 2. update DPCD*/ 298 if (!retries_ch_eq) 299 /* EPR #361076 - write as a 5-byte burst, 300 * but only for the 1-st iteration 301 */ 302 303 dpcd_set_lt_pattern_and_lane_settings( 304 link, 305 lt_settings, 306 tr_pattern, offset); 307 else 308 dpcd_set_lane_settings(link, lt_settings, offset); 309 310 /* 3. wait for receiver to lock-on*/ 311 wait_time_microsec = lt_settings->eq_pattern_time; 312 313 if (is_repeater(lt_settings, offset)) 314 wait_time_microsec = 315 dp_translate_training_aux_read_interval( 316 link->dpcd_caps.lttpr_caps.aux_rd_interval[offset - 1]); 317 318 dp_wait_for_training_aux_rd_interval( 319 link, 320 wait_time_microsec); 321 322 /* 4. Read lane status and requested 323 * drive settings as set by the sink*/ 324 325 dp_get_lane_status_and_lane_adjust( 326 link, 327 lt_settings, 328 dpcd_lane_status, 329 &dpcd_lane_status_updated, 330 dpcd_lane_adjust, 331 offset); 332 333 /* 5. check CR done*/ 334 if (!dp_is_cr_done(lane_count, dpcd_lane_status)) 335 return dpcd_lane_status[0].bits.CR_DONE_0 ? 336 LINK_TRAINING_EQ_FAIL_CR_PARTIAL : 337 LINK_TRAINING_EQ_FAIL_CR; 338 339 /* 6. check CHEQ done*/ 340 if (dp_is_ch_eq_done(lane_count, dpcd_lane_status) && 341 dp_is_symbol_locked(lane_count, dpcd_lane_status) && 342 dp_is_interlane_aligned(dpcd_lane_status_updated)) 343 return LINK_TRAINING_SUCCESS; 344 345 /* 7. update VS/PE/PC2 in lt_settings*/ 346 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust, 347 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings); 348 } 349 350 return LINK_TRAINING_EQ_FAIL_EQ; 351 352 } 353 354 enum link_training_result dp_perform_8b_10b_link_training( 355 struct dc_link *link, 356 const struct link_resource *link_res, 357 struct link_training_settings *lt_settings) 358 { 359 enum link_training_result status = LINK_TRAINING_SUCCESS; 360 361 uint8_t repeater_cnt; 362 uint8_t repeater_id; 363 uint8_t lane = 0; 364 365 if (link->ctx->dc->work_arounds.lt_early_cr_pattern) 366 start_clock_recovery_pattern_early(link, link_res, lt_settings, DPRX); 367 368 /* 1. set link rate, lane count and spread. */ 369 dpcd_set_link_settings(link, lt_settings); 370 371 if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) { 372 373 /* 2. perform link training (set link training done 374 * to false is done as well) 375 */ 376 repeater_cnt = dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt); 377 378 for (repeater_id = repeater_cnt; (repeater_id > 0 && status == LINK_TRAINING_SUCCESS); 379 repeater_id--) { 380 status = perform_8b_10b_clock_recovery_sequence(link, link_res, lt_settings, repeater_id); 381 382 if (status != LINK_TRAINING_SUCCESS) { 383 repeater_training_done(link, repeater_id); 384 break; 385 } 386 387 status = perform_8b_10b_channel_equalization_sequence(link, 388 link_res, 389 lt_settings, 390 repeater_id); 391 392 repeater_training_done(link, repeater_id); 393 394 if (status != LINK_TRAINING_SUCCESS) 395 break; 396 397 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) { 398 lt_settings->dpcd_lane_settings[lane].raw = 0; 399 lt_settings->hw_lane_settings[lane].VOLTAGE_SWING = 0; 400 lt_settings->hw_lane_settings[lane].PRE_EMPHASIS = 0; 401 } 402 } 403 } 404 405 if (status == LINK_TRAINING_SUCCESS) { 406 status = perform_8b_10b_clock_recovery_sequence(link, link_res, lt_settings, DPRX); 407 if (status == LINK_TRAINING_SUCCESS) { 408 status = perform_8b_10b_channel_equalization_sequence(link, 409 link_res, 410 lt_settings, 411 DPRX); 412 } 413 } 414 415 return status; 416 } 417