Merge tag 'icc-6.7-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/djakov/icc...
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / display / dc / link / protocols / link_dp_training_fixed_vs_pe_retimer.c
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 8b/10b link training specially modified to support an
28  * embedded retimer chip. This retimer chip is referred as fixed vs pe retimer.
29  * Unlike native dp connection this chip requires a modified link training
30  * protocol based on 8b/10b link training. Since this is a non standard sequence
31  * and we must support this hardware, we decided to isolate it in its own
32  * training sequence inside its own file.
33  */
34 #include "link_dp_training_fixed_vs_pe_retimer.h"
35 #include "link_dp_training_8b_10b.h"
36 #include "link_dpcd.h"
37 #include "link_dp_phy.h"
38 #include "link_dp_capability.h"
39 #include "link_ddc.h"
40
41 #define DC_LOGGER \
42         link->ctx->logger
43
44 void dp_fixed_vs_pe_read_lane_adjust(
45         struct dc_link *link,
46         union dpcd_training_lane dpcd_lane_adjust[LANE_COUNT_DP_MAX])
47 {
48         const uint8_t vendor_lttpr_write_data_vs[3] = {0x0, 0x53, 0x63};
49         const uint8_t vendor_lttpr_write_data_pe[3] = {0x0, 0x54, 0x63};
50         uint8_t dprx_vs = 0;
51         uint8_t dprx_pe = 0;
52         uint8_t lane;
53
54         /* W/A to read lane settings requested by DPRX */
55         link_configure_fixed_vs_pe_retimer(link->ddc,
56                         &vendor_lttpr_write_data_vs[0], sizeof(vendor_lttpr_write_data_vs));
57
58         link_query_fixed_vs_pe_retimer(link->ddc, &dprx_vs, 1);
59
60         link_configure_fixed_vs_pe_retimer(link->ddc,
61                         &vendor_lttpr_write_data_pe[0], sizeof(vendor_lttpr_write_data_pe));
62
63         link_query_fixed_vs_pe_retimer(link->ddc, &dprx_pe, 1);
64
65         for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
66                 dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_SET  = (dprx_vs >> (2 * lane)) & 0x3;
67                 dpcd_lane_adjust[lane].bits.PRE_EMPHASIS_SET = (dprx_pe >> (2 * lane)) & 0x3;
68         }
69 }
70
71
72 void dp_fixed_vs_pe_set_retimer_lane_settings(
73         struct dc_link *link,
74         const union dpcd_training_lane dpcd_lane_adjust[LANE_COUNT_DP_MAX],
75         uint8_t lane_count)
76 {
77         const uint8_t vendor_lttpr_write_data_reset[4] = {0x1, 0x50, 0x63, 0xFF};
78         uint8_t vendor_lttpr_write_data_vs[4] = {0x1, 0x51, 0x63, 0x0};
79         uint8_t vendor_lttpr_write_data_pe[4] = {0x1, 0x52, 0x63, 0x0};
80         uint8_t lane = 0;
81
82         for (lane = 0; lane < lane_count; lane++) {
83                 vendor_lttpr_write_data_vs[3] |=
84                                 dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_SET << (2 * lane);
85                 vendor_lttpr_write_data_pe[3] |=
86                                 dpcd_lane_adjust[lane].bits.PRE_EMPHASIS_SET << (2 * lane);
87         }
88
89         /* Force LTTPR to output desired VS and PE */
90         link_configure_fixed_vs_pe_retimer(link->ddc,
91                         &vendor_lttpr_write_data_reset[0], sizeof(vendor_lttpr_write_data_reset));
92
93         link_configure_fixed_vs_pe_retimer(link->ddc,
94                         &vendor_lttpr_write_data_vs[0], sizeof(vendor_lttpr_write_data_vs));
95
96         link_configure_fixed_vs_pe_retimer(link->ddc,
97                         &vendor_lttpr_write_data_pe[0], sizeof(vendor_lttpr_write_data_pe));
98 }
99
100 static enum link_training_result perform_fixed_vs_pe_nontransparent_training_sequence(
101                 struct dc_link *link,
102                 const struct link_resource *link_res,
103                 struct link_training_settings *lt_settings)
104 {
105         enum link_training_result status = LINK_TRAINING_SUCCESS;
106         uint8_t lane = 0;
107         uint8_t toggle_rate = 0x6;
108         uint8_t target_rate = 0x6;
109         bool apply_toggle_rate_wa = false;
110         uint8_t repeater_cnt;
111         uint8_t repeater_id;
112
113         /* Fixed VS/PE specific: Force CR AUX RD Interval to at least 16ms */
114         if (lt_settings->cr_pattern_time < 16000)
115                 lt_settings->cr_pattern_time = 16000;
116
117         /* Fixed VS/PE specific: Toggle link rate */
118         apply_toggle_rate_wa = ((link->vendor_specific_lttpr_link_rate_wa == target_rate) || (link->vendor_specific_lttpr_link_rate_wa == 0));
119         target_rate = get_dpcd_link_rate(&lt_settings->link_settings);
120         toggle_rate = (target_rate == 0x6) ? 0xA : 0x6;
121
122         if (apply_toggle_rate_wa)
123                 lt_settings->link_settings.link_rate = toggle_rate;
124
125         if (link->ctx->dc->work_arounds.lt_early_cr_pattern)
126                 start_clock_recovery_pattern_early(link, link_res, lt_settings, DPRX);
127
128         /* 1. set link rate, lane count and spread. */
129         dpcd_set_link_settings(link, lt_settings);
130
131         /* Fixed VS/PE specific: Toggle link rate back*/
132         if (apply_toggle_rate_wa) {
133                 core_link_write_dpcd(
134                                 link,
135                                 DP_LINK_BW_SET,
136                                 &target_rate,
137                                 1);
138         }
139
140         link->vendor_specific_lttpr_link_rate_wa = target_rate;
141
142         if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
143
144                 /* 2. perform link training (set link training done
145                  *  to false is done as well)
146                  */
147                 repeater_cnt = dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
148
149                 for (repeater_id = repeater_cnt; (repeater_id > 0 && status == LINK_TRAINING_SUCCESS);
150                                 repeater_id--) {
151                         status = perform_8b_10b_clock_recovery_sequence(link, link_res, lt_settings, repeater_id);
152
153                         if (status != LINK_TRAINING_SUCCESS) {
154                                 repeater_training_done(link, repeater_id);
155                                 break;
156                         }
157
158                         status = perform_8b_10b_channel_equalization_sequence(link,
159                                         link_res,
160                                         lt_settings,
161                                         repeater_id);
162
163                         repeater_training_done(link, repeater_id);
164
165                         if (status != LINK_TRAINING_SUCCESS)
166                                 break;
167
168                         for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
169                                 lt_settings->dpcd_lane_settings[lane].raw = 0;
170                                 lt_settings->hw_lane_settings[lane].VOLTAGE_SWING = 0;
171                                 lt_settings->hw_lane_settings[lane].PRE_EMPHASIS = 0;
172                         }
173                 }
174         }
175
176         if (status == LINK_TRAINING_SUCCESS) {
177                 status = perform_8b_10b_clock_recovery_sequence(link, link_res, lt_settings, DPRX);
178                 if (status == LINK_TRAINING_SUCCESS) {
179                         status = perform_8b_10b_channel_equalization_sequence(link,
180                                                                        link_res,
181                                                                        lt_settings,
182                                                                        DPRX);
183                 }
184         }
185
186         return status;
187 }
188
189
190 enum link_training_result dp_perform_fixed_vs_pe_training_sequence_legacy(
191         struct dc_link *link,
192         const struct link_resource *link_res,
193         struct link_training_settings *lt_settings)
194 {
195         const uint8_t vendor_lttpr_write_data_reset[4] = {0x1, 0x50, 0x63, 0xFF};
196         const uint8_t offset = dp_parse_lttpr_repeater_count(
197                         link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
198         const uint8_t vendor_lttpr_write_data_intercept_en[4] = {0x1, 0x55, 0x63, 0x0};
199         const uint8_t vendor_lttpr_write_data_intercept_dis[4] = {0x1, 0x55, 0x63, 0x68};
200         uint32_t pre_disable_intercept_delay_ms = 0;
201         uint8_t vendor_lttpr_write_data_vs[4] = {0x1, 0x51, 0x63, 0x0};
202         uint8_t vendor_lttpr_write_data_pe[4] = {0x1, 0x52, 0x63, 0x0};
203         const uint8_t vendor_lttpr_write_data_4lane_1[4] = {0x1, 0x6E, 0xF2, 0x19};
204         const uint8_t vendor_lttpr_write_data_4lane_2[4] = {0x1, 0x6B, 0xF2, 0x01};
205         const uint8_t vendor_lttpr_write_data_4lane_3[4] = {0x1, 0x6D, 0xF2, 0x18};
206         const uint8_t vendor_lttpr_write_data_4lane_4[4] = {0x1, 0x6C, 0xF2, 0x03};
207         const uint8_t vendor_lttpr_write_data_4lane_5[4] = {0x1, 0x03, 0xF3, 0x06};
208         enum link_training_result status = LINK_TRAINING_SUCCESS;
209         uint8_t lane = 0;
210         union down_spread_ctrl downspread = {0};
211         union lane_count_set lane_count_set = {0};
212         uint8_t toggle_rate;
213         uint8_t rate;
214
215         /* Only 8b/10b is supported */
216         ASSERT(link_dp_get_encoding_format(&lt_settings->link_settings) ==
217                         DP_8b_10b_ENCODING);
218
219         if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
220                 status = perform_fixed_vs_pe_nontransparent_training_sequence(link, link_res, lt_settings);
221                 return status;
222         }
223
224         if (offset != 0xFF) {
225                 if (offset == 2) {
226                         pre_disable_intercept_delay_ms = link->dc->debug.fixed_vs_aux_delay_config_wa;
227
228                 /* Certain display and cable configuration require extra delay */
229                 } else if (offset > 2) {
230                         pre_disable_intercept_delay_ms = link->dc->debug.fixed_vs_aux_delay_config_wa * 2;
231                 }
232         }
233
234         /* Vendor specific: Reset lane settings */
235         link_configure_fixed_vs_pe_retimer(link->ddc,
236                         &vendor_lttpr_write_data_reset[0], sizeof(vendor_lttpr_write_data_reset));
237         link_configure_fixed_vs_pe_retimer(link->ddc,
238                         &vendor_lttpr_write_data_vs[0], sizeof(vendor_lttpr_write_data_vs));
239         link_configure_fixed_vs_pe_retimer(link->ddc,
240                         &vendor_lttpr_write_data_pe[0], sizeof(vendor_lttpr_write_data_pe));
241
242         /* Vendor specific: Enable intercept */
243         link_configure_fixed_vs_pe_retimer(link->ddc,
244                         &vendor_lttpr_write_data_intercept_en[0], sizeof(vendor_lttpr_write_data_intercept_en));
245
246
247         /* 1. set link rate, lane count and spread. */
248
249         downspread.raw = (uint8_t)(lt_settings->link_settings.link_spread);
250
251         lane_count_set.bits.LANE_COUNT_SET =
252         lt_settings->link_settings.lane_count;
253
254         lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing;
255         lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
256
257
258         if (lt_settings->pattern_for_eq < DP_TRAINING_PATTERN_SEQUENCE_4) {
259                 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED =
260                                 link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED;
261         }
262
263         core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,
264                 &downspread.raw, sizeof(downspread));
265
266         core_link_write_dpcd(link, DP_LANE_COUNT_SET,
267                 &lane_count_set.raw, 1);
268
269         rate = get_dpcd_link_rate(&lt_settings->link_settings);
270
271         /* Vendor specific: Toggle link rate */
272         toggle_rate = (rate == 0x6) ? 0xA : 0x6;
273
274         if (link->vendor_specific_lttpr_link_rate_wa == rate || link->vendor_specific_lttpr_link_rate_wa == 0) {
275                 core_link_write_dpcd(
276                                 link,
277                                 DP_LINK_BW_SET,
278                                 &toggle_rate,
279                                 1);
280         }
281
282         link->vendor_specific_lttpr_link_rate_wa = rate;
283
284         core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
285
286         DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x framing = %x\n %x spread = %x\n",
287                 __func__,
288                 DP_LINK_BW_SET,
289                 lt_settings->link_settings.link_rate,
290                 DP_LANE_COUNT_SET,
291                 lt_settings->link_settings.lane_count,
292                 lt_settings->enhanced_framing,
293                 DP_DOWNSPREAD_CTRL,
294                 lt_settings->link_settings.link_spread);
295
296         if (lt_settings->link_settings.lane_count == LANE_COUNT_FOUR) {
297                 link_configure_fixed_vs_pe_retimer(link->ddc,
298                                 &vendor_lttpr_write_data_4lane_1[0], sizeof(vendor_lttpr_write_data_4lane_1));
299                 link_configure_fixed_vs_pe_retimer(link->ddc,
300                                 &vendor_lttpr_write_data_4lane_2[0], sizeof(vendor_lttpr_write_data_4lane_2));
301                 link_configure_fixed_vs_pe_retimer(link->ddc,
302                                 &vendor_lttpr_write_data_4lane_3[0], sizeof(vendor_lttpr_write_data_4lane_3));
303                 link_configure_fixed_vs_pe_retimer(link->ddc,
304                                 &vendor_lttpr_write_data_4lane_4[0], sizeof(vendor_lttpr_write_data_4lane_4));
305                 link_configure_fixed_vs_pe_retimer(link->ddc,
306                                 &vendor_lttpr_write_data_4lane_5[0], sizeof(vendor_lttpr_write_data_4lane_5));
307         }
308
309         /* 2. Perform link training */
310
311         /* Perform Clock Recovery Sequence */
312         if (status == LINK_TRAINING_SUCCESS) {
313                 const uint8_t max_vendor_dpcd_retries = 10;
314                 uint32_t retries_cr;
315                 uint32_t retry_count;
316                 uint32_t wait_time_microsec;
317                 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
318                 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
319                 union lane_align_status_updated dpcd_lane_status_updated;
320                 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
321                 uint8_t i = 0;
322
323                 retries_cr = 0;
324                 retry_count = 0;
325
326                 memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status));
327                 memset(&dpcd_lane_status_updated, '\0',
328                 sizeof(dpcd_lane_status_updated));
329
330                 while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) &&
331                         (retry_count < LINK_TRAINING_MAX_CR_RETRY)) {
332
333
334                         /* 1. call HWSS to set lane settings */
335                         dp_set_hw_lane_settings(
336                                         link,
337                                         link_res,
338                                         lt_settings,
339                                         0);
340
341                         /* 2. update DPCD of the receiver */
342                         if (!retry_count) {
343                                 /* EPR #361076 - write as a 5-byte burst,
344                                  * but only for the 1-st iteration.
345                                  */
346                                 dpcd_set_lt_pattern_and_lane_settings(
347                                                 link,
348                                                 lt_settings,
349                                                 lt_settings->pattern_for_cr,
350                                                 0);
351                                 /* Vendor specific: Disable intercept */
352                                 for (i = 0; i < max_vendor_dpcd_retries; i++) {
353                                         if (pre_disable_intercept_delay_ms != 0)
354                                                 msleep(pre_disable_intercept_delay_ms);
355                                         if (link_configure_fixed_vs_pe_retimer(link->ddc,
356                                                         &vendor_lttpr_write_data_intercept_dis[0],
357                                                         sizeof(vendor_lttpr_write_data_intercept_dis)))
358                                                 break;
359
360                                         link_configure_fixed_vs_pe_retimer(link->ddc,
361                                                         &vendor_lttpr_write_data_intercept_en[0],
362                                                         sizeof(vendor_lttpr_write_data_intercept_en));
363                                 }
364                         } else {
365                                 vendor_lttpr_write_data_vs[3] = 0;
366                                 vendor_lttpr_write_data_pe[3] = 0;
367
368                                 for (lane = 0; lane < lane_count; lane++) {
369                                         vendor_lttpr_write_data_vs[3] |=
370                                                         lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET << (2 * lane);
371                                         vendor_lttpr_write_data_pe[3] |=
372                                                         lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET << (2 * lane);
373                                 }
374
375                                 /* Vendor specific: Update VS and PE to DPRX requested value */
376                                 link_configure_fixed_vs_pe_retimer(link->ddc,
377                                                 &vendor_lttpr_write_data_vs[0], sizeof(vendor_lttpr_write_data_vs));
378                                 link_configure_fixed_vs_pe_retimer(link->ddc,
379                                                 &vendor_lttpr_write_data_pe[0], sizeof(vendor_lttpr_write_data_pe));
380
381                                 dpcd_set_lane_settings(
382                                                 link,
383                                                 lt_settings,
384                                                 0);
385                         }
386
387                         /* 3. wait receiver to lock-on*/
388                         wait_time_microsec = lt_settings->cr_pattern_time;
389
390                         dp_wait_for_training_aux_rd_interval(
391                                         link,
392                                         wait_time_microsec);
393
394                         /* 4. Read lane status and requested drive
395                          * settings as set by the sink
396                          */
397                         dp_get_lane_status_and_lane_adjust(
398                                         link,
399                                         lt_settings,
400                                         dpcd_lane_status,
401                                         &dpcd_lane_status_updated,
402                                         dpcd_lane_adjust,
403                                         0);
404
405                         /* 5. check CR done*/
406                         if (dp_is_cr_done(lane_count, dpcd_lane_status)) {
407                                 status = LINK_TRAINING_SUCCESS;
408                                 break;
409                         }
410
411                         /* 6. max VS reached*/
412                         if (dp_is_max_vs_reached(lt_settings))
413                                 break;
414
415                         /* 7. same lane settings */
416                         /* Note: settings are the same for all lanes,
417                          * so comparing first lane is sufficient
418                          */
419                         if (lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET ==
420                                         dpcd_lane_adjust[0].bits.VOLTAGE_SWING_LANE)
421                                 retries_cr++;
422                         else
423                                 retries_cr = 0;
424
425                         /* 8. update VS/PE/PC2 in lt_settings*/
426                         dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
427                                         lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
428                         retry_count++;
429                 }
430
431                 if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) {
432                         ASSERT(0);
433                         DC_LOG_ERROR("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue",
434                                 __func__,
435                                 LINK_TRAINING_MAX_CR_RETRY);
436
437                 }
438
439                 status = dp_get_cr_failure(lane_count, dpcd_lane_status);
440         }
441
442         /* Perform Channel EQ Sequence */
443         if (status == LINK_TRAINING_SUCCESS) {
444                 enum dc_dp_training_pattern tr_pattern;
445                 uint32_t retries_ch_eq;
446                 uint32_t wait_time_microsec;
447                 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
448                 union lane_align_status_updated dpcd_lane_status_updated = {0};
449                 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
450                 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
451
452                 /* Note: also check that TPS4 is a supported feature*/
453                 tr_pattern = lt_settings->pattern_for_eq;
454
455                 dp_set_hw_training_pattern(link, link_res, tr_pattern, 0);
456
457                 status = LINK_TRAINING_EQ_FAIL_EQ;
458
459                 for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT;
460                         retries_ch_eq++) {
461
462                         dp_set_hw_lane_settings(link, link_res, lt_settings, 0);
463
464                         vendor_lttpr_write_data_vs[3] = 0;
465                         vendor_lttpr_write_data_pe[3] = 0;
466
467                         for (lane = 0; lane < lane_count; lane++) {
468                                 vendor_lttpr_write_data_vs[3] |=
469                                                 lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET << (2 * lane);
470                                 vendor_lttpr_write_data_pe[3] |=
471                                                 lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET << (2 * lane);
472                         }
473
474                         /* Vendor specific: Update VS and PE to DPRX requested value */
475                         link_configure_fixed_vs_pe_retimer(link->ddc,
476                                         &vendor_lttpr_write_data_vs[0], sizeof(vendor_lttpr_write_data_vs));
477                         link_configure_fixed_vs_pe_retimer(link->ddc,
478                                         &vendor_lttpr_write_data_pe[0], sizeof(vendor_lttpr_write_data_pe));
479
480                         /* 2. update DPCD*/
481                         if (!retries_ch_eq)
482                                 /* EPR #361076 - write as a 5-byte burst,
483                                  * but only for the 1-st iteration
484                                  */
485
486                                 dpcd_set_lt_pattern_and_lane_settings(
487                                         link,
488                                         lt_settings,
489                                         tr_pattern, 0);
490                         else
491                                 dpcd_set_lane_settings(link, lt_settings, 0);
492
493                         /* 3. wait for receiver to lock-on*/
494                         wait_time_microsec = lt_settings->eq_pattern_time;
495
496                         dp_wait_for_training_aux_rd_interval(
497                                         link,
498                                         wait_time_microsec);
499
500                         /* 4. Read lane status and requested
501                          * drive settings as set by the sink
502                          */
503                         dp_get_lane_status_and_lane_adjust(
504                                 link,
505                                 lt_settings,
506                                 dpcd_lane_status,
507                                 &dpcd_lane_status_updated,
508                                 dpcd_lane_adjust,
509                                 0);
510
511                         /* 5. check CR done*/
512                         if (!dp_is_cr_done(lane_count, dpcd_lane_status)) {
513                                 status = LINK_TRAINING_EQ_FAIL_CR;
514                                 break;
515                         }
516
517                         /* 6. check CHEQ done*/
518                         if (dp_is_ch_eq_done(lane_count, dpcd_lane_status) &&
519                                         dp_is_symbol_locked(lane_count, dpcd_lane_status) &&
520                                         dp_is_interlane_aligned(dpcd_lane_status_updated)) {
521                                 status = LINK_TRAINING_SUCCESS;
522                                 break;
523                         }
524
525                         /* 7. update VS/PE/PC2 in lt_settings*/
526                         dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
527                                         lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
528                 }
529         }
530
531         return status;
532 }
533
534 enum link_training_result dp_perform_fixed_vs_pe_training_sequence(
535         struct dc_link *link,
536         const struct link_resource *link_res,
537         struct link_training_settings *lt_settings)
538 {
539         const uint8_t vendor_lttpr_write_data_reset[4] = {0x1, 0x50, 0x63, 0xFF};
540         const uint8_t offset = dp_parse_lttpr_repeater_count(
541                         link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
542         const uint8_t vendor_lttpr_write_data_intercept_en[4] = {0x1, 0x55, 0x63, 0x0};
543         const uint8_t vendor_lttpr_write_data_intercept_dis[4] = {0x1, 0x55, 0x63, 0x6E};
544         const uint8_t vendor_lttpr_write_data_adicora_eq1[4] = {0x1, 0x55, 0x63, 0x2E};
545         const uint8_t vendor_lttpr_write_data_adicora_eq2[4] = {0x1, 0x55, 0x63, 0x01};
546         const uint8_t vendor_lttpr_write_data_adicora_eq3[4] = {0x1, 0x55, 0x63, 0x68};
547         uint32_t pre_disable_intercept_delay_ms = 0;
548         uint8_t vendor_lttpr_write_data_vs[4] = {0x1, 0x51, 0x63, 0x0};
549         uint8_t vendor_lttpr_write_data_pe[4] = {0x1, 0x52, 0x63, 0x0};
550         const uint8_t vendor_lttpr_write_data_4lane_1[4] = {0x1, 0x6E, 0xF2, 0x19};
551         const uint8_t vendor_lttpr_write_data_4lane_2[4] = {0x1, 0x6B, 0xF2, 0x01};
552         const uint8_t vendor_lttpr_write_data_4lane_3[4] = {0x1, 0x6D, 0xF2, 0x18};
553         const uint8_t vendor_lttpr_write_data_4lane_4[4] = {0x1, 0x6C, 0xF2, 0x03};
554         const uint8_t vendor_lttpr_write_data_4lane_5[4] = {0x1, 0x03, 0xF3, 0x06};
555         enum link_training_result status = LINK_TRAINING_SUCCESS;
556         uint8_t lane = 0;
557         union down_spread_ctrl downspread = {0};
558         union lane_count_set lane_count_set = {0};
559         uint8_t toggle_rate;
560         uint8_t rate;
561
562         /* Only 8b/10b is supported */
563         ASSERT(link_dp_get_encoding_format(&lt_settings->link_settings) ==
564                         DP_8b_10b_ENCODING);
565
566         if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
567                 status = perform_fixed_vs_pe_nontransparent_training_sequence(link, link_res, lt_settings);
568                 return status;
569         }
570
571         if (offset != 0xFF) {
572                 if (offset == 2) {
573                         pre_disable_intercept_delay_ms = link->dc->debug.fixed_vs_aux_delay_config_wa;
574
575                 /* Certain display and cable configuration require extra delay */
576                 } else if (offset > 2) {
577                         pre_disable_intercept_delay_ms = link->dc->debug.fixed_vs_aux_delay_config_wa * 2;
578                 }
579         }
580
581         /* Vendor specific: Reset lane settings */
582         link_configure_fixed_vs_pe_retimer(link->ddc,
583                         &vendor_lttpr_write_data_reset[0], sizeof(vendor_lttpr_write_data_reset));
584         link_configure_fixed_vs_pe_retimer(link->ddc,
585                         &vendor_lttpr_write_data_vs[0], sizeof(vendor_lttpr_write_data_vs));
586         link_configure_fixed_vs_pe_retimer(link->ddc,
587                         &vendor_lttpr_write_data_pe[0], sizeof(vendor_lttpr_write_data_pe));
588
589         /* Vendor specific: Enable intercept */
590         link_configure_fixed_vs_pe_retimer(link->ddc,
591                         &vendor_lttpr_write_data_intercept_en[0], sizeof(vendor_lttpr_write_data_intercept_en));
592
593         /* 1. set link rate, lane count and spread. */
594
595         downspread.raw = (uint8_t)(lt_settings->link_settings.link_spread);
596
597         lane_count_set.bits.LANE_COUNT_SET =
598         lt_settings->link_settings.lane_count;
599
600         lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing;
601         lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
602
603
604         if (lt_settings->pattern_for_eq < DP_TRAINING_PATTERN_SEQUENCE_4) {
605                 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED =
606                                 link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED;
607         }
608
609         core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,
610                 &downspread.raw, sizeof(downspread));
611
612         core_link_write_dpcd(link, DP_LANE_COUNT_SET,
613                 &lane_count_set.raw, 1);
614
615         rate = get_dpcd_link_rate(&lt_settings->link_settings);
616
617         /* Vendor specific: Toggle link rate */
618         toggle_rate = (rate == 0x6) ? 0xA : 0x6;
619
620         if (link->vendor_specific_lttpr_link_rate_wa == rate || link->vendor_specific_lttpr_link_rate_wa == 0) {
621                 core_link_write_dpcd(
622                                 link,
623                                 DP_LINK_BW_SET,
624                                 &toggle_rate,
625                                 1);
626         }
627
628         link->vendor_specific_lttpr_link_rate_wa = rate;
629
630         core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1);
631
632         DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x framing = %x\n %x spread = %x\n",
633                 __func__,
634                 DP_LINK_BW_SET,
635                 lt_settings->link_settings.link_rate,
636                 DP_LANE_COUNT_SET,
637                 lt_settings->link_settings.lane_count,
638                 lt_settings->enhanced_framing,
639                 DP_DOWNSPREAD_CTRL,
640                 lt_settings->link_settings.link_spread);
641
642         if (lt_settings->link_settings.lane_count == LANE_COUNT_FOUR) {
643                 link_configure_fixed_vs_pe_retimer(link->ddc,
644                                 &vendor_lttpr_write_data_4lane_1[0], sizeof(vendor_lttpr_write_data_4lane_1));
645                 link_configure_fixed_vs_pe_retimer(link->ddc,
646                                 &vendor_lttpr_write_data_4lane_2[0], sizeof(vendor_lttpr_write_data_4lane_2));
647                 link_configure_fixed_vs_pe_retimer(link->ddc,
648                                 &vendor_lttpr_write_data_4lane_3[0], sizeof(vendor_lttpr_write_data_4lane_3));
649                 link_configure_fixed_vs_pe_retimer(link->ddc,
650                                 &vendor_lttpr_write_data_4lane_4[0], sizeof(vendor_lttpr_write_data_4lane_4));
651                 link_configure_fixed_vs_pe_retimer(link->ddc,
652                                 &vendor_lttpr_write_data_4lane_5[0], sizeof(vendor_lttpr_write_data_4lane_5));
653         }
654
655         /* 2. Perform link training */
656
657         /* Perform Clock Recovery Sequence */
658         if (status == LINK_TRAINING_SUCCESS) {
659                 const uint8_t max_vendor_dpcd_retries = 10;
660                 uint32_t retries_cr;
661                 uint32_t retry_count;
662                 uint32_t wait_time_microsec;
663                 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
664                 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
665                 union lane_align_status_updated dpcd_lane_status_updated;
666                 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
667                 uint8_t i = 0;
668
669                 retries_cr = 0;
670                 retry_count = 0;
671
672                 memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status));
673                 memset(&dpcd_lane_status_updated, '\0',
674                 sizeof(dpcd_lane_status_updated));
675
676                 while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) &&
677                         (retry_count < LINK_TRAINING_MAX_CR_RETRY)) {
678
679
680                         /* 1. call HWSS to set lane settings */
681                         dp_set_hw_lane_settings(
682                                         link,
683                                         link_res,
684                                         lt_settings,
685                                         0);
686
687                         /* 2. update DPCD of the receiver */
688                         if (!retry_count) {
689                                 /* EPR #361076 - write as a 5-byte burst,
690                                  * but only for the 1-st iteration.
691                                  */
692                                 dpcd_set_lt_pattern_and_lane_settings(
693                                                 link,
694                                                 lt_settings,
695                                                 lt_settings->pattern_for_cr,
696                                                 0);
697                                 /* Vendor specific: Disable intercept */
698                                 for (i = 0; i < max_vendor_dpcd_retries; i++) {
699                                         if (pre_disable_intercept_delay_ms != 0)
700                                                 msleep(pre_disable_intercept_delay_ms);
701                                         if (link_configure_fixed_vs_pe_retimer(link->ddc,
702                                                         &vendor_lttpr_write_data_intercept_dis[0],
703                                                         sizeof(vendor_lttpr_write_data_intercept_dis)))
704                                                 break;
705
706                                         link_configure_fixed_vs_pe_retimer(link->ddc,
707                                                         &vendor_lttpr_write_data_intercept_en[0],
708                                                         sizeof(vendor_lttpr_write_data_intercept_en));
709                                 }
710                         } else {
711                                 vendor_lttpr_write_data_vs[3] = 0;
712                                 vendor_lttpr_write_data_pe[3] = 0;
713
714                                 for (lane = 0; lane < lane_count; lane++) {
715                                         vendor_lttpr_write_data_vs[3] |=
716                                                         lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET << (2 * lane);
717                                         vendor_lttpr_write_data_pe[3] |=
718                                                         lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET << (2 * lane);
719                                 }
720
721                                 /* Vendor specific: Update VS and PE to DPRX requested value */
722                                 link_configure_fixed_vs_pe_retimer(link->ddc,
723                                                 &vendor_lttpr_write_data_vs[0], sizeof(vendor_lttpr_write_data_vs));
724                                 link_configure_fixed_vs_pe_retimer(link->ddc,
725                                                 &vendor_lttpr_write_data_pe[0], sizeof(vendor_lttpr_write_data_pe));
726
727                                 dpcd_set_lane_settings(
728                                                 link,
729                                                 lt_settings,
730                                                 0);
731                         }
732
733                         /* 3. wait receiver to lock-on*/
734                         wait_time_microsec = lt_settings->cr_pattern_time;
735
736                         dp_wait_for_training_aux_rd_interval(
737                                         link,
738                                         wait_time_microsec);
739
740                         /* 4. Read lane status and requested drive
741                          * settings as set by the sink
742                          */
743                         dp_get_lane_status_and_lane_adjust(
744                                         link,
745                                         lt_settings,
746                                         dpcd_lane_status,
747                                         &dpcd_lane_status_updated,
748                                         dpcd_lane_adjust,
749                                         0);
750
751                         /* 5. check CR done*/
752                         if (dp_is_cr_done(lane_count, dpcd_lane_status)) {
753                                 status = LINK_TRAINING_SUCCESS;
754                                 break;
755                         }
756
757                         /* 6. max VS reached*/
758                         if (dp_is_max_vs_reached(lt_settings))
759                                 break;
760
761                         /* 7. same lane settings */
762                         /* Note: settings are the same for all lanes,
763                          * so comparing first lane is sufficient
764                          */
765                         if (lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET ==
766                                         dpcd_lane_adjust[0].bits.VOLTAGE_SWING_LANE)
767                                 retries_cr++;
768                         else
769                                 retries_cr = 0;
770
771                         /* 8. update VS/PE/PC2 in lt_settings*/
772                         dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
773                                         lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
774                         retry_count++;
775                 }
776
777                 if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) {
778                         ASSERT(0);
779                         DC_LOG_ERROR("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue",
780                                 __func__,
781                                 LINK_TRAINING_MAX_CR_RETRY);
782
783                 }
784
785                 status = dp_get_cr_failure(lane_count, dpcd_lane_status);
786         }
787
788         /* Perform Channel EQ Sequence */
789         if (status == LINK_TRAINING_SUCCESS) {
790                 enum dc_dp_training_pattern tr_pattern;
791                 uint32_t retries_ch_eq;
792                 uint32_t wait_time_microsec;
793                 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
794                 union lane_align_status_updated dpcd_lane_status_updated = {0};
795                 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
796                 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
797
798                 link_configure_fixed_vs_pe_retimer(link->ddc,
799                                 &vendor_lttpr_write_data_adicora_eq1[0],
800                                 sizeof(vendor_lttpr_write_data_adicora_eq1));
801                 link_configure_fixed_vs_pe_retimer(link->ddc,
802                                 &vendor_lttpr_write_data_adicora_eq2[0],
803                                 sizeof(vendor_lttpr_write_data_adicora_eq2));
804
805
806                 /* Note: also check that TPS4 is a supported feature*/
807                 tr_pattern = lt_settings->pattern_for_eq;
808
809                 dp_set_hw_training_pattern(link, link_res, tr_pattern, 0);
810
811                 status = LINK_TRAINING_EQ_FAIL_EQ;
812
813                 for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT;
814                         retries_ch_eq++) {
815
816                         dp_set_hw_lane_settings(link, link_res, lt_settings, 0);
817
818                         vendor_lttpr_write_data_vs[3] = 0;
819                         vendor_lttpr_write_data_pe[3] = 0;
820
821                         for (lane = 0; lane < lane_count; lane++) {
822                                 vendor_lttpr_write_data_vs[3] |=
823                                                 lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET << (2 * lane);
824                                 vendor_lttpr_write_data_pe[3] |=
825                                                 lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET << (2 * lane);
826                         }
827
828                         /* Vendor specific: Update VS and PE to DPRX requested value */
829                         link_configure_fixed_vs_pe_retimer(link->ddc,
830                                         &vendor_lttpr_write_data_vs[0], sizeof(vendor_lttpr_write_data_vs));
831                         link_configure_fixed_vs_pe_retimer(link->ddc,
832                                         &vendor_lttpr_write_data_pe[0], sizeof(vendor_lttpr_write_data_pe));
833
834                         /* 2. update DPCD*/
835                         if (!retries_ch_eq) {
836                                 /* EPR #361076 - write as a 5-byte burst,
837                                  * but only for the 1-st iteration
838                                  */
839
840                                 dpcd_set_lt_pattern_and_lane_settings(
841                                         link,
842                                         lt_settings,
843                                         tr_pattern, 0);
844
845                                 link_configure_fixed_vs_pe_retimer(link->ddc,
846                                                 &vendor_lttpr_write_data_adicora_eq3[0],
847                                                 sizeof(vendor_lttpr_write_data_adicora_eq3));
848
849                         } else
850                                 dpcd_set_lane_settings(link, lt_settings, 0);
851
852                         /* 3. wait for receiver to lock-on*/
853                         wait_time_microsec = lt_settings->eq_pattern_time;
854
855                         dp_wait_for_training_aux_rd_interval(
856                                         link,
857                                         wait_time_microsec);
858
859                         /* 4. Read lane status and requested
860                          * drive settings as set by the sink
861                          */
862                         dp_get_lane_status_and_lane_adjust(
863                                 link,
864                                 lt_settings,
865                                 dpcd_lane_status,
866                                 &dpcd_lane_status_updated,
867                                 dpcd_lane_adjust,
868                                 0);
869
870                         /* 5. check CR done*/
871                         if (!dp_is_cr_done(lane_count, dpcd_lane_status)) {
872                                 status = LINK_TRAINING_EQ_FAIL_CR;
873                                 break;
874                         }
875
876                         /* 6. check CHEQ done*/
877                         if (dp_is_ch_eq_done(lane_count, dpcd_lane_status) &&
878                                         dp_is_symbol_locked(lane_count, dpcd_lane_status) &&
879                                         dp_is_interlane_aligned(dpcd_lane_status_updated)) {
880                                 status = LINK_TRAINING_SUCCESS;
881                                 break;
882                         }
883
884                         /* 7. update VS/PE/PC2 in lt_settings*/
885                         dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
886                                         lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
887                 }
888         }
889
890         return status;
891 }