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