1 /* 2 * Copyright © 2008-2015 Intel Corporation 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 (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24 #include "intel_drv.h" 25 26 static void 27 intel_get_adjust_train(struct intel_dp *intel_dp, 28 const uint8_t link_status[DP_LINK_STATUS_SIZE]) 29 { 30 uint8_t v = 0; 31 uint8_t p = 0; 32 int lane; 33 uint8_t voltage_max; 34 uint8_t preemph_max; 35 36 for (lane = 0; lane < intel_dp->lane_count; lane++) { 37 uint8_t this_v = drm_dp_get_adjust_request_voltage(link_status, lane); 38 uint8_t this_p = drm_dp_get_adjust_request_pre_emphasis(link_status, lane); 39 40 if (this_v > v) 41 v = this_v; 42 if (this_p > p) 43 p = this_p; 44 } 45 46 voltage_max = intel_dp_voltage_max(intel_dp); 47 if (v >= voltage_max) 48 v = voltage_max | DP_TRAIN_MAX_SWING_REACHED; 49 50 preemph_max = intel_dp_pre_emphasis_max(intel_dp, v); 51 if (p >= preemph_max) 52 p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; 53 54 for (lane = 0; lane < 4; lane++) 55 intel_dp->train_set[lane] = v | p; 56 } 57 58 static bool 59 intel_dp_set_link_train(struct intel_dp *intel_dp, 60 uint8_t dp_train_pat) 61 { 62 uint8_t buf[sizeof(intel_dp->train_set) + 1]; 63 int ret, len; 64 65 intel_dp_program_link_training_pattern(intel_dp, dp_train_pat); 66 67 buf[0] = dp_train_pat; 68 if ((dp_train_pat & DP_TRAINING_PATTERN_MASK) == 69 DP_TRAINING_PATTERN_DISABLE) { 70 /* don't write DP_TRAINING_LANEx_SET on disable */ 71 len = 1; 72 } else { 73 /* DP_TRAINING_LANEx_SET follow DP_TRAINING_PATTERN_SET */ 74 memcpy(buf + 1, intel_dp->train_set, intel_dp->lane_count); 75 len = intel_dp->lane_count + 1; 76 } 77 78 ret = drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_PATTERN_SET, 79 buf, len); 80 81 return ret == len; 82 } 83 84 static bool 85 intel_dp_reset_link_train(struct intel_dp *intel_dp, 86 uint8_t dp_train_pat) 87 { 88 if (!intel_dp->train_set_valid) 89 memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set)); 90 intel_dp_set_signal_levels(intel_dp); 91 return intel_dp_set_link_train(intel_dp, dp_train_pat); 92 } 93 94 static bool 95 intel_dp_update_link_train(struct intel_dp *intel_dp) 96 { 97 int ret; 98 99 intel_dp_set_signal_levels(intel_dp); 100 101 ret = drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_LANE0_SET, 102 intel_dp->train_set, intel_dp->lane_count); 103 104 return ret == intel_dp->lane_count; 105 } 106 107 /* Enable corresponding port and start training pattern 1 */ 108 static void 109 intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp) 110 { 111 int i; 112 uint8_t voltage; 113 int voltage_tries, loop_tries; 114 uint8_t link_config[2]; 115 uint8_t link_bw, rate_select; 116 117 if (intel_dp->prepare_link_retrain) 118 intel_dp->prepare_link_retrain(intel_dp); 119 120 intel_dp_compute_rate(intel_dp, intel_dp->link_rate, 121 &link_bw, &rate_select); 122 123 /* Write the link configuration data */ 124 link_config[0] = link_bw; 125 link_config[1] = intel_dp->lane_count; 126 if (drm_dp_enhanced_frame_cap(intel_dp->dpcd)) 127 link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; 128 drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_BW_SET, link_config, 2); 129 if (intel_dp->num_sink_rates) 130 drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_RATE_SET, 131 &rate_select, 1); 132 133 link_config[0] = 0; 134 link_config[1] = DP_SET_ANSI_8B10B; 135 drm_dp_dpcd_write(&intel_dp->aux, DP_DOWNSPREAD_CTRL, link_config, 2); 136 137 intel_dp->DP |= DP_PORT_EN; 138 139 /* clock recovery */ 140 if (!intel_dp_reset_link_train(intel_dp, 141 DP_TRAINING_PATTERN_1 | 142 DP_LINK_SCRAMBLING_DISABLE)) { 143 DRM_ERROR("failed to enable link training\n"); 144 return; 145 } 146 147 voltage = 0xff; 148 voltage_tries = 0; 149 loop_tries = 0; 150 for (;;) { 151 uint8_t link_status[DP_LINK_STATUS_SIZE]; 152 153 drm_dp_link_train_clock_recovery_delay(intel_dp->dpcd); 154 if (!intel_dp_get_link_status(intel_dp, link_status)) { 155 DRM_ERROR("failed to get link status\n"); 156 break; 157 } 158 159 if (drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)) { 160 DRM_DEBUG_KMS("clock recovery OK\n"); 161 break; 162 } 163 164 /* 165 * if we used previously trained voltage and pre-emphasis values 166 * and we don't get clock recovery, reset link training values 167 */ 168 if (intel_dp->train_set_valid) { 169 DRM_DEBUG_KMS("clock recovery not ok, reset"); 170 /* clear the flag as we are not reusing train set */ 171 intel_dp->train_set_valid = false; 172 if (!intel_dp_reset_link_train(intel_dp, 173 DP_TRAINING_PATTERN_1 | 174 DP_LINK_SCRAMBLING_DISABLE)) { 175 DRM_ERROR("failed to enable link training\n"); 176 return; 177 } 178 continue; 179 } 180 181 /* Check to see if we've tried the max voltage */ 182 for (i = 0; i < intel_dp->lane_count; i++) 183 if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) 184 break; 185 if (i == intel_dp->lane_count) { 186 ++loop_tries; 187 if (loop_tries == 5) { 188 DRM_ERROR("too many full retries, give up\n"); 189 break; 190 } 191 intel_dp_reset_link_train(intel_dp, 192 DP_TRAINING_PATTERN_1 | 193 DP_LINK_SCRAMBLING_DISABLE); 194 voltage_tries = 0; 195 continue; 196 } 197 198 /* Check to see if we've tried the same voltage 5 times */ 199 if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { 200 ++voltage_tries; 201 if (voltage_tries == 5) { 202 DRM_ERROR("too many voltage retries, give up\n"); 203 break; 204 } 205 } else 206 voltage_tries = 0; 207 voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; 208 209 /* Update training set as requested by target */ 210 intel_get_adjust_train(intel_dp, link_status); 211 if (!intel_dp_update_link_train(intel_dp)) { 212 DRM_ERROR("failed to update link training\n"); 213 break; 214 } 215 } 216 } 217 218 /* 219 * Pick training pattern for channel equalization. Training Pattern 3 for HBR2 220 * or 1.2 devices that support it, Training Pattern 2 otherwise. 221 */ 222 static u32 intel_dp_training_pattern(struct intel_dp *intel_dp) 223 { 224 u32 training_pattern = DP_TRAINING_PATTERN_2; 225 bool source_tps3, sink_tps3; 226 227 /* 228 * Intel platforms that support HBR2 also support TPS3. TPS3 support is 229 * also mandatory for downstream devices that support HBR2. However, not 230 * all sinks follow the spec. 231 * 232 * Due to WaDisableHBR2 SKL < B0 is the only exception where TPS3 is 233 * supported in source but still not enabled. 234 */ 235 source_tps3 = intel_dp_source_supports_hbr2(intel_dp); 236 sink_tps3 = drm_dp_tps3_supported(intel_dp->dpcd); 237 238 if (source_tps3 && sink_tps3) { 239 training_pattern = DP_TRAINING_PATTERN_3; 240 } else if (intel_dp->link_rate == 540000) { 241 if (!source_tps3) 242 DRM_DEBUG_KMS("5.4 Gbps link rate without source HBR2/TPS3 support\n"); 243 if (!sink_tps3) 244 DRM_DEBUG_KMS("5.4 Gbps link rate without sink TPS3 support\n"); 245 } 246 247 return training_pattern; 248 } 249 250 static void 251 intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp) 252 { 253 bool channel_eq = false; 254 int tries, cr_tries; 255 u32 training_pattern; 256 257 training_pattern = intel_dp_training_pattern(intel_dp); 258 259 /* channel equalization */ 260 if (!intel_dp_set_link_train(intel_dp, 261 training_pattern | 262 DP_LINK_SCRAMBLING_DISABLE)) { 263 DRM_ERROR("failed to start channel equalization\n"); 264 return; 265 } 266 267 tries = 0; 268 cr_tries = 0; 269 channel_eq = false; 270 for (;;) { 271 uint8_t link_status[DP_LINK_STATUS_SIZE]; 272 273 if (cr_tries > 5) { 274 DRM_ERROR("failed to train DP, aborting\n"); 275 break; 276 } 277 278 drm_dp_link_train_channel_eq_delay(intel_dp->dpcd); 279 if (!intel_dp_get_link_status(intel_dp, link_status)) { 280 DRM_ERROR("failed to get link status\n"); 281 break; 282 } 283 284 /* Make sure clock is still ok */ 285 if (!drm_dp_clock_recovery_ok(link_status, 286 intel_dp->lane_count)) { 287 intel_dp->train_set_valid = false; 288 intel_dp_link_training_clock_recovery(intel_dp); 289 intel_dp_set_link_train(intel_dp, 290 training_pattern | 291 DP_LINK_SCRAMBLING_DISABLE); 292 cr_tries++; 293 continue; 294 } 295 296 if (drm_dp_channel_eq_ok(link_status, 297 intel_dp->lane_count)) { 298 channel_eq = true; 299 break; 300 } 301 302 /* Try 5 times, then try clock recovery if that fails */ 303 if (tries > 5) { 304 intel_dp->train_set_valid = false; 305 intel_dp_link_training_clock_recovery(intel_dp); 306 intel_dp_set_link_train(intel_dp, 307 training_pattern | 308 DP_LINK_SCRAMBLING_DISABLE); 309 tries = 0; 310 cr_tries++; 311 continue; 312 } 313 314 /* Update training set as requested by target */ 315 intel_get_adjust_train(intel_dp, link_status); 316 if (!intel_dp_update_link_train(intel_dp)) { 317 DRM_ERROR("failed to update link training\n"); 318 break; 319 } 320 ++tries; 321 } 322 323 intel_dp_set_idle_link_train(intel_dp); 324 325 if (channel_eq) { 326 intel_dp->train_set_valid = true; 327 DRM_DEBUG_KMS("Channel EQ done. DP Training successful\n"); 328 } 329 } 330 331 void intel_dp_stop_link_train(struct intel_dp *intel_dp) 332 { 333 intel_dp_set_link_train(intel_dp, 334 DP_TRAINING_PATTERN_DISABLE); 335 } 336 337 void 338 intel_dp_start_link_train(struct intel_dp *intel_dp) 339 { 340 intel_dp_link_training_clock_recovery(intel_dp); 341 intel_dp_link_training_channel_equalization(intel_dp); 342 } 343