xref: /dflybsd-src/sys/dev/drm/i915/intel_dp_link_training.c (revision 3f2dd94a569761201b5b0a18b2f697f97fe1b9dc)
1aee94f86SFrançois Tigeot /*
2aee94f86SFrançois Tigeot  * Copyright © 2008-2015 Intel Corporation
3aee94f86SFrançois Tigeot  *
4aee94f86SFrançois Tigeot  * Permission is hereby granted, free of charge, to any person obtaining a
5aee94f86SFrançois Tigeot  * copy of this software and associated documentation files (the "Software"),
6aee94f86SFrançois Tigeot  * to deal in the Software without restriction, including without limitation
7aee94f86SFrançois Tigeot  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8aee94f86SFrançois Tigeot  * and/or sell copies of the Software, and to permit persons to whom the
9aee94f86SFrançois Tigeot  * Software is furnished to do so, subject to the following conditions:
10aee94f86SFrançois Tigeot  *
11aee94f86SFrançois Tigeot  * The above copyright notice and this permission notice (including the next
12aee94f86SFrançois Tigeot  * paragraph) shall be included in all copies or substantial portions of the
13aee94f86SFrançois Tigeot  * Software.
14aee94f86SFrançois Tigeot  *
15aee94f86SFrançois Tigeot  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16aee94f86SFrançois Tigeot  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17aee94f86SFrançois Tigeot  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18aee94f86SFrançois Tigeot  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19aee94f86SFrançois Tigeot  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20aee94f86SFrançois Tigeot  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21aee94f86SFrançois Tigeot  * IN THE SOFTWARE.
22aee94f86SFrançois Tigeot  */
23aee94f86SFrançois Tigeot 
24aee94f86SFrançois Tigeot #include "intel_drv.h"
25aee94f86SFrançois Tigeot 
26aee94f86SFrançois Tigeot static void
intel_dp_dump_link_status(const uint8_t link_status[DP_LINK_STATUS_SIZE])271e12ee3bSFrançois Tigeot intel_dp_dump_link_status(const uint8_t link_status[DP_LINK_STATUS_SIZE])
281e12ee3bSFrançois Tigeot {
291e12ee3bSFrançois Tigeot 
301e12ee3bSFrançois Tigeot 	DRM_DEBUG_KMS("ln0_1:0x%x ln2_3:0x%x align:0x%x sink:0x%x adj_req0_1:0x%x adj_req2_3:0x%x",
311e12ee3bSFrançois Tigeot 		      link_status[0], link_status[1], link_status[2],
321e12ee3bSFrançois Tigeot 		      link_status[3], link_status[4], link_status[5]);
331e12ee3bSFrançois Tigeot }
341e12ee3bSFrançois Tigeot 
351e12ee3bSFrançois Tigeot static void
intel_get_adjust_train(struct intel_dp * intel_dp,const uint8_t link_status[DP_LINK_STATUS_SIZE])36aee94f86SFrançois Tigeot intel_get_adjust_train(struct intel_dp *intel_dp,
37aee94f86SFrançois Tigeot 		       const uint8_t link_status[DP_LINK_STATUS_SIZE])
38aee94f86SFrançois Tigeot {
39aee94f86SFrançois Tigeot 	uint8_t v = 0;
40aee94f86SFrançois Tigeot 	uint8_t p = 0;
41aee94f86SFrançois Tigeot 	int lane;
42aee94f86SFrançois Tigeot 	uint8_t voltage_max;
43aee94f86SFrançois Tigeot 	uint8_t preemph_max;
44aee94f86SFrançois Tigeot 
45aee94f86SFrançois Tigeot 	for (lane = 0; lane < intel_dp->lane_count; lane++) {
46aee94f86SFrançois Tigeot 		uint8_t this_v = drm_dp_get_adjust_request_voltage(link_status, lane);
47aee94f86SFrançois Tigeot 		uint8_t this_p = drm_dp_get_adjust_request_pre_emphasis(link_status, lane);
48aee94f86SFrançois Tigeot 
49aee94f86SFrançois Tigeot 		if (this_v > v)
50aee94f86SFrançois Tigeot 			v = this_v;
51aee94f86SFrançois Tigeot 		if (this_p > p)
52aee94f86SFrançois Tigeot 			p = this_p;
53aee94f86SFrançois Tigeot 	}
54aee94f86SFrançois Tigeot 
55aee94f86SFrançois Tigeot 	voltage_max = intel_dp_voltage_max(intel_dp);
56aee94f86SFrançois Tigeot 	if (v >= voltage_max)
57aee94f86SFrançois Tigeot 		v = voltage_max | DP_TRAIN_MAX_SWING_REACHED;
58aee94f86SFrançois Tigeot 
59aee94f86SFrançois Tigeot 	preemph_max = intel_dp_pre_emphasis_max(intel_dp, v);
60aee94f86SFrançois Tigeot 	if (p >= preemph_max)
61aee94f86SFrançois Tigeot 		p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
62aee94f86SFrançois Tigeot 
63aee94f86SFrançois Tigeot 	for (lane = 0; lane < 4; lane++)
64aee94f86SFrançois Tigeot 		intel_dp->train_set[lane] = v | p;
65aee94f86SFrançois Tigeot }
66aee94f86SFrançois Tigeot 
67aee94f86SFrançois Tigeot static bool
intel_dp_set_link_train(struct intel_dp * intel_dp,uint8_t dp_train_pat)68aee94f86SFrançois Tigeot intel_dp_set_link_train(struct intel_dp *intel_dp,
69aee94f86SFrançois Tigeot 			uint8_t dp_train_pat)
70aee94f86SFrançois Tigeot {
71aee94f86SFrançois Tigeot 	uint8_t buf[sizeof(intel_dp->train_set) + 1];
72aee94f86SFrançois Tigeot 	int ret, len;
73aee94f86SFrançois Tigeot 
74aee94f86SFrançois Tigeot 	intel_dp_program_link_training_pattern(intel_dp, dp_train_pat);
75aee94f86SFrançois Tigeot 
76aee94f86SFrançois Tigeot 	buf[0] = dp_train_pat;
77aee94f86SFrançois Tigeot 	if ((dp_train_pat & DP_TRAINING_PATTERN_MASK) ==
78aee94f86SFrançois Tigeot 	    DP_TRAINING_PATTERN_DISABLE) {
79aee94f86SFrançois Tigeot 		/* don't write DP_TRAINING_LANEx_SET on disable */
80aee94f86SFrançois Tigeot 		len = 1;
81aee94f86SFrançois Tigeot 	} else {
82aee94f86SFrançois Tigeot 		/* DP_TRAINING_LANEx_SET follow DP_TRAINING_PATTERN_SET */
83aee94f86SFrançois Tigeot 		memcpy(buf + 1, intel_dp->train_set, intel_dp->lane_count);
84aee94f86SFrançois Tigeot 		len = intel_dp->lane_count + 1;
85aee94f86SFrançois Tigeot 	}
86aee94f86SFrançois Tigeot 
87aee94f86SFrançois Tigeot 	ret = drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_PATTERN_SET,
88aee94f86SFrançois Tigeot 				buf, len);
89aee94f86SFrançois Tigeot 
90aee94f86SFrançois Tigeot 	return ret == len;
91aee94f86SFrançois Tigeot }
92aee94f86SFrançois Tigeot 
93aee94f86SFrançois Tigeot static bool
intel_dp_reset_link_train(struct intel_dp * intel_dp,uint8_t dp_train_pat)94aee94f86SFrançois Tigeot intel_dp_reset_link_train(struct intel_dp *intel_dp,
95aee94f86SFrançois Tigeot 			uint8_t dp_train_pat)
96aee94f86SFrançois Tigeot {
97aee94f86SFrançois Tigeot 	memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set));
98aee94f86SFrançois Tigeot 	intel_dp_set_signal_levels(intel_dp);
99aee94f86SFrançois Tigeot 	return intel_dp_set_link_train(intel_dp, dp_train_pat);
100aee94f86SFrançois Tigeot }
101aee94f86SFrançois Tigeot 
102aee94f86SFrançois Tigeot static bool
intel_dp_update_link_train(struct intel_dp * intel_dp)103aee94f86SFrançois Tigeot intel_dp_update_link_train(struct intel_dp *intel_dp)
104aee94f86SFrançois Tigeot {
105aee94f86SFrançois Tigeot 	int ret;
106aee94f86SFrançois Tigeot 
107aee94f86SFrançois Tigeot 	intel_dp_set_signal_levels(intel_dp);
108aee94f86SFrançois Tigeot 
109aee94f86SFrançois Tigeot 	ret = drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_LANE0_SET,
110aee94f86SFrançois Tigeot 				intel_dp->train_set, intel_dp->lane_count);
111aee94f86SFrançois Tigeot 
112aee94f86SFrançois Tigeot 	return ret == intel_dp->lane_count;
113aee94f86SFrançois Tigeot }
114aee94f86SFrançois Tigeot 
intel_dp_link_max_vswing_reached(struct intel_dp * intel_dp)1151e12ee3bSFrançois Tigeot static bool intel_dp_link_max_vswing_reached(struct intel_dp *intel_dp)
1161e12ee3bSFrançois Tigeot {
1171e12ee3bSFrançois Tigeot 	int lane;
1181e12ee3bSFrançois Tigeot 
1191e12ee3bSFrançois Tigeot 	for (lane = 0; lane < intel_dp->lane_count; lane++)
1201e12ee3bSFrançois Tigeot 		if ((intel_dp->train_set[lane] &
1211e12ee3bSFrançois Tigeot 		     DP_TRAIN_MAX_SWING_REACHED) == 0)
1221e12ee3bSFrançois Tigeot 			return false;
1231e12ee3bSFrançois Tigeot 
1241e12ee3bSFrançois Tigeot 	return true;
1251e12ee3bSFrançois Tigeot }
1261e12ee3bSFrançois Tigeot 
127aee94f86SFrançois Tigeot /* Enable corresponding port and start training pattern 1 */
1281e12ee3bSFrançois Tigeot static bool
intel_dp_link_training_clock_recovery(struct intel_dp * intel_dp)129aee94f86SFrançois Tigeot intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
130aee94f86SFrançois Tigeot {
131aee94f86SFrançois Tigeot 	uint8_t voltage;
1321e12ee3bSFrançois Tigeot 	int voltage_tries, max_vswing_tries;
133aee94f86SFrançois Tigeot 	uint8_t link_config[2];
134aee94f86SFrançois Tigeot 	uint8_t link_bw, rate_select;
135aee94f86SFrançois Tigeot 
136aee94f86SFrançois Tigeot 	if (intel_dp->prepare_link_retrain)
137aee94f86SFrançois Tigeot 		intel_dp->prepare_link_retrain(intel_dp);
138aee94f86SFrançois Tigeot 
139aee94f86SFrançois Tigeot 	intel_dp_compute_rate(intel_dp, intel_dp->link_rate,
140aee94f86SFrançois Tigeot 			      &link_bw, &rate_select);
141aee94f86SFrançois Tigeot 
142aee94f86SFrançois Tigeot 	/* Write the link configuration data */
143aee94f86SFrançois Tigeot 	link_config[0] = link_bw;
144aee94f86SFrançois Tigeot 	link_config[1] = intel_dp->lane_count;
145aee94f86SFrançois Tigeot 	if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
146aee94f86SFrançois Tigeot 		link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
147aee94f86SFrançois Tigeot 	drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_BW_SET, link_config, 2);
1481e12ee3bSFrançois Tigeot 
149*3f2dd94aSFrançois Tigeot 	/* eDP 1.4 rate select method. */
150*3f2dd94aSFrançois Tigeot 	if (!link_bw)
151aee94f86SFrançois Tigeot 		drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_RATE_SET,
152aee94f86SFrançois Tigeot 				  &rate_select, 1);
153aee94f86SFrançois Tigeot 
154aee94f86SFrançois Tigeot 	link_config[0] = 0;
155aee94f86SFrançois Tigeot 	link_config[1] = DP_SET_ANSI_8B10B;
156aee94f86SFrançois Tigeot 	drm_dp_dpcd_write(&intel_dp->aux, DP_DOWNSPREAD_CTRL, link_config, 2);
157aee94f86SFrançois Tigeot 
158aee94f86SFrançois Tigeot 	intel_dp->DP |= DP_PORT_EN;
159aee94f86SFrançois Tigeot 
160aee94f86SFrançois Tigeot 	/* clock recovery */
161aee94f86SFrançois Tigeot 	if (!intel_dp_reset_link_train(intel_dp,
162aee94f86SFrançois Tigeot 				       DP_TRAINING_PATTERN_1 |
163aee94f86SFrançois Tigeot 				       DP_LINK_SCRAMBLING_DISABLE)) {
164aee94f86SFrançois Tigeot 		DRM_ERROR("failed to enable link training\n");
1651e12ee3bSFrançois Tigeot 		return false;
166aee94f86SFrançois Tigeot 	}
167aee94f86SFrançois Tigeot 
1681e12ee3bSFrançois Tigeot 	voltage_tries = 1;
1691e12ee3bSFrançois Tigeot 	max_vswing_tries = 0;
170aee94f86SFrançois Tigeot 	for (;;) {
171aee94f86SFrançois Tigeot 		uint8_t link_status[DP_LINK_STATUS_SIZE];
172aee94f86SFrançois Tigeot 
173aee94f86SFrançois Tigeot 		drm_dp_link_train_clock_recovery_delay(intel_dp->dpcd);
1741e12ee3bSFrançois Tigeot 
175aee94f86SFrançois Tigeot 		if (!intel_dp_get_link_status(intel_dp, link_status)) {
176aee94f86SFrançois Tigeot 			DRM_ERROR("failed to get link status\n");
1771e12ee3bSFrançois Tigeot 			return false;
178aee94f86SFrançois Tigeot 		}
179aee94f86SFrançois Tigeot 
180aee94f86SFrançois Tigeot 		if (drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)) {
181aee94f86SFrançois Tigeot 			DRM_DEBUG_KMS("clock recovery OK\n");
1821e12ee3bSFrançois Tigeot 			return true;
183aee94f86SFrançois Tigeot 		}
184aee94f86SFrançois Tigeot 
185aee94f86SFrançois Tigeot 		if (voltage_tries == 5) {
1861e12ee3bSFrançois Tigeot 			DRM_DEBUG_KMS("Same voltage tried 5 times\n");
1871e12ee3bSFrançois Tigeot 			return false;
188aee94f86SFrançois Tigeot 		}
1891e12ee3bSFrançois Tigeot 
1901e12ee3bSFrançois Tigeot 		if (max_vswing_tries == 1) {
1911e12ee3bSFrançois Tigeot 			DRM_DEBUG_KMS("Max Voltage Swing reached\n");
1921e12ee3bSFrançois Tigeot 			return false;
1931e12ee3bSFrançois Tigeot 		}
1941e12ee3bSFrançois Tigeot 
195aee94f86SFrançois Tigeot 		voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
196aee94f86SFrançois Tigeot 
197aee94f86SFrançois Tigeot 		/* Update training set as requested by target */
198aee94f86SFrançois Tigeot 		intel_get_adjust_train(intel_dp, link_status);
199aee94f86SFrançois Tigeot 		if (!intel_dp_update_link_train(intel_dp)) {
200aee94f86SFrançois Tigeot 			DRM_ERROR("failed to update link training\n");
2011e12ee3bSFrançois Tigeot 			return false;
202aee94f86SFrançois Tigeot 		}
2031e12ee3bSFrançois Tigeot 
2041e12ee3bSFrançois Tigeot 		if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) ==
2051e12ee3bSFrançois Tigeot 		    voltage)
2061e12ee3bSFrançois Tigeot 			++voltage_tries;
2071e12ee3bSFrançois Tigeot 		else
2081e12ee3bSFrançois Tigeot 			voltage_tries = 1;
2091e12ee3bSFrançois Tigeot 
2101e12ee3bSFrançois Tigeot 		if (intel_dp_link_max_vswing_reached(intel_dp))
2111e12ee3bSFrançois Tigeot 			++max_vswing_tries;
2121e12ee3bSFrançois Tigeot 
213aee94f86SFrançois Tigeot 	}
214aee94f86SFrançois Tigeot }
215aee94f86SFrançois Tigeot 
216aee94f86SFrançois Tigeot /*
217aee94f86SFrançois Tigeot  * Pick training pattern for channel equalization. Training Pattern 3 for HBR2
218aee94f86SFrançois Tigeot  * or 1.2 devices that support it, Training Pattern 2 otherwise.
219aee94f86SFrançois Tigeot  */
intel_dp_training_pattern(struct intel_dp * intel_dp)220aee94f86SFrançois Tigeot static u32 intel_dp_training_pattern(struct intel_dp *intel_dp)
221aee94f86SFrançois Tigeot {
222aee94f86SFrançois Tigeot 	u32 training_pattern = DP_TRAINING_PATTERN_2;
223aee94f86SFrançois Tigeot 	bool source_tps3, sink_tps3;
224aee94f86SFrançois Tigeot 
225aee94f86SFrançois Tigeot 	/*
226aee94f86SFrançois Tigeot 	 * Intel platforms that support HBR2 also support TPS3. TPS3 support is
227aee94f86SFrançois Tigeot 	 * also mandatory for downstream devices that support HBR2. However, not
228aee94f86SFrançois Tigeot 	 * all sinks follow the spec.
229aee94f86SFrançois Tigeot 	 */
230aee94f86SFrançois Tigeot 	source_tps3 = intel_dp_source_supports_hbr2(intel_dp);
231aee94f86SFrançois Tigeot 	sink_tps3 = drm_dp_tps3_supported(intel_dp->dpcd);
232aee94f86SFrançois Tigeot 
233aee94f86SFrançois Tigeot 	if (source_tps3 && sink_tps3) {
234aee94f86SFrançois Tigeot 		training_pattern = DP_TRAINING_PATTERN_3;
235aee94f86SFrançois Tigeot 	} else if (intel_dp->link_rate == 540000) {
236aee94f86SFrançois Tigeot 		if (!source_tps3)
237aee94f86SFrançois Tigeot 			DRM_DEBUG_KMS("5.4 Gbps link rate without source HBR2/TPS3 support\n");
238aee94f86SFrançois Tigeot 		if (!sink_tps3)
239aee94f86SFrançois Tigeot 			DRM_DEBUG_KMS("5.4 Gbps link rate without sink TPS3 support\n");
240aee94f86SFrançois Tigeot 	}
241aee94f86SFrançois Tigeot 
242aee94f86SFrançois Tigeot 	return training_pattern;
243aee94f86SFrançois Tigeot }
244aee94f86SFrançois Tigeot 
2451e12ee3bSFrançois Tigeot static bool
intel_dp_link_training_channel_equalization(struct intel_dp * intel_dp)246aee94f86SFrançois Tigeot intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
247aee94f86SFrançois Tigeot {
2481e12ee3bSFrançois Tigeot 	int tries;
249aee94f86SFrançois Tigeot 	u32 training_pattern;
2501e12ee3bSFrançois Tigeot 	uint8_t link_status[DP_LINK_STATUS_SIZE];
251aee94f86SFrançois Tigeot 
252aee94f86SFrançois Tigeot 	training_pattern = intel_dp_training_pattern(intel_dp);
253aee94f86SFrançois Tigeot 
254aee94f86SFrançois Tigeot 	/* channel equalization */
255aee94f86SFrançois Tigeot 	if (!intel_dp_set_link_train(intel_dp,
256aee94f86SFrançois Tigeot 				     training_pattern |
257aee94f86SFrançois Tigeot 				     DP_LINK_SCRAMBLING_DISABLE)) {
258aee94f86SFrançois Tigeot 		DRM_ERROR("failed to start channel equalization\n");
2591e12ee3bSFrançois Tigeot 		return false;
260aee94f86SFrançois Tigeot 	}
261aee94f86SFrançois Tigeot 
2621e12ee3bSFrançois Tigeot 	intel_dp->channel_eq_status = false;
2631e12ee3bSFrançois Tigeot 	for (tries = 0; tries < 5; tries++) {
264aee94f86SFrançois Tigeot 
265aee94f86SFrançois Tigeot 		drm_dp_link_train_channel_eq_delay(intel_dp->dpcd);
266aee94f86SFrançois Tigeot 		if (!intel_dp_get_link_status(intel_dp, link_status)) {
267aee94f86SFrançois Tigeot 			DRM_ERROR("failed to get link status\n");
268aee94f86SFrançois Tigeot 			break;
269aee94f86SFrançois Tigeot 		}
270aee94f86SFrançois Tigeot 
271aee94f86SFrançois Tigeot 		/* Make sure clock is still ok */
272aee94f86SFrançois Tigeot 		if (!drm_dp_clock_recovery_ok(link_status,
273aee94f86SFrançois Tigeot 					      intel_dp->lane_count)) {
2741e12ee3bSFrançois Tigeot 			intel_dp_dump_link_status(link_status);
2751e12ee3bSFrançois Tigeot 			DRM_DEBUG_KMS("Clock recovery check failed, cannot "
2761e12ee3bSFrançois Tigeot 				      "continue channel equalization\n");
2771e12ee3bSFrançois Tigeot 			break;
278aee94f86SFrançois Tigeot 		}
279aee94f86SFrançois Tigeot 
280aee94f86SFrançois Tigeot 		if (drm_dp_channel_eq_ok(link_status,
281aee94f86SFrançois Tigeot 					 intel_dp->lane_count)) {
2821e12ee3bSFrançois Tigeot 			intel_dp->channel_eq_status = true;
2831e12ee3bSFrançois Tigeot 			DRM_DEBUG_KMS("Channel EQ done. DP Training "
2841e12ee3bSFrançois Tigeot 				      "successful\n");
285aee94f86SFrançois Tigeot 			break;
286aee94f86SFrançois Tigeot 		}
287aee94f86SFrançois Tigeot 
288aee94f86SFrançois Tigeot 		/* Update training set as requested by target */
289aee94f86SFrançois Tigeot 		intel_get_adjust_train(intel_dp, link_status);
290aee94f86SFrançois Tigeot 		if (!intel_dp_update_link_train(intel_dp)) {
291aee94f86SFrançois Tigeot 			DRM_ERROR("failed to update link training\n");
292aee94f86SFrançois Tigeot 			break;
293aee94f86SFrançois Tigeot 		}
2941e12ee3bSFrançois Tigeot 	}
2951e12ee3bSFrançois Tigeot 
2961e12ee3bSFrançois Tigeot 	/* Try 5 times, else fail and try at lower BW */
2971e12ee3bSFrançois Tigeot 	if (tries == 5) {
2981e12ee3bSFrançois Tigeot 		intel_dp_dump_link_status(link_status);
2991e12ee3bSFrançois Tigeot 		DRM_DEBUG_KMS("Channel equalization failed 5 times\n");
300aee94f86SFrançois Tigeot 	}
301aee94f86SFrançois Tigeot 
302aee94f86SFrançois Tigeot 	intel_dp_set_idle_link_train(intel_dp);
303aee94f86SFrançois Tigeot 
3041e12ee3bSFrançois Tigeot 	return intel_dp->channel_eq_status;
3051e12ee3bSFrançois Tigeot 
306aee94f86SFrançois Tigeot }
307aee94f86SFrançois Tigeot 
intel_dp_stop_link_train(struct intel_dp * intel_dp)308aee94f86SFrançois Tigeot void intel_dp_stop_link_train(struct intel_dp *intel_dp)
309aee94f86SFrançois Tigeot {
310aee94f86SFrançois Tigeot 	intel_dp_set_link_train(intel_dp,
311aee94f86SFrançois Tigeot 				DP_TRAINING_PATTERN_DISABLE);
312aee94f86SFrançois Tigeot }
313aee94f86SFrançois Tigeot 
314aee94f86SFrançois Tigeot void
intel_dp_start_link_train(struct intel_dp * intel_dp)315aee94f86SFrançois Tigeot intel_dp_start_link_train(struct intel_dp *intel_dp)
316aee94f86SFrançois Tigeot {
317*3f2dd94aSFrançois Tigeot 	struct intel_connector *intel_connector = intel_dp->attached_connector;
318*3f2dd94aSFrançois Tigeot 
319*3f2dd94aSFrançois Tigeot 	if (!intel_dp_link_training_clock_recovery(intel_dp))
320*3f2dd94aSFrançois Tigeot 		goto failure_handling;
321*3f2dd94aSFrançois Tigeot 	if (!intel_dp_link_training_channel_equalization(intel_dp))
322*3f2dd94aSFrançois Tigeot 		goto failure_handling;
323*3f2dd94aSFrançois Tigeot 
324*3f2dd94aSFrançois Tigeot 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Link Training Passed at Link Rate = %d, Lane count = %d",
325*3f2dd94aSFrançois Tigeot 		      intel_connector->base.base.id,
326*3f2dd94aSFrançois Tigeot 		      intel_connector->base.name,
327*3f2dd94aSFrançois Tigeot 		      intel_dp->link_rate, intel_dp->lane_count);
328*3f2dd94aSFrançois Tigeot 	return;
329*3f2dd94aSFrançois Tigeot 
330*3f2dd94aSFrançois Tigeot  failure_handling:
331*3f2dd94aSFrançois Tigeot 	/* Dont fallback and prune modes if its eDP */
332*3f2dd94aSFrançois Tigeot 	if (!intel_dp_is_edp(intel_dp)) {
333*3f2dd94aSFrançois Tigeot 		DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Link Training failed at link rate = %d, lane count = %d",
334*3f2dd94aSFrançois Tigeot 			      intel_connector->base.base.id,
335*3f2dd94aSFrançois Tigeot 			      intel_connector->base.name,
336*3f2dd94aSFrançois Tigeot 			      intel_dp->link_rate, intel_dp->lane_count);
337*3f2dd94aSFrançois Tigeot 		if (!intel_dp_get_link_train_fallback_values(intel_dp,
338*3f2dd94aSFrançois Tigeot 							     intel_dp->link_rate,
339*3f2dd94aSFrançois Tigeot 							     intel_dp->lane_count))
340*3f2dd94aSFrançois Tigeot 			/* Schedule a Hotplug Uevent to userspace to start modeset */
341*3f2dd94aSFrançois Tigeot 			schedule_work(&intel_connector->modeset_retry_work);
342*3f2dd94aSFrançois Tigeot 	} else {
343*3f2dd94aSFrançois Tigeot 		DRM_ERROR("[CONNECTOR:%d:%s] Link Training failed at link rate = %d, lane count = %d",
344*3f2dd94aSFrançois Tigeot 			  intel_connector->base.base.id,
345*3f2dd94aSFrançois Tigeot 			  intel_connector->base.name,
346*3f2dd94aSFrançois Tigeot 			  intel_dp->link_rate, intel_dp->lane_count);
347*3f2dd94aSFrançois Tigeot 	}
348*3f2dd94aSFrançois Tigeot 	return;
349aee94f86SFrançois Tigeot }
350