xref: /dragonfly/sys/dev/drm/amd/display/dc/core/dc_link_dp.c (revision b843c749addef9340ee7d4e250b09fdd492602a1)
1 /* Copyright 2015 Advanced Micro Devices, Inc. */
2 #include "dm_services.h"
3 #include "dc.h"
4 #include "dc_link_dp.h"
5 #include "dm_helpers.h"
6 #include "opp.h"
7 
8 #include "inc/core_types.h"
9 #include "link_hwss.h"
10 #include "dc_link_ddc.h"
11 #include "core_status.h"
12 #include "dpcd_defs.h"
13 
14 #include "resource.h"
15 #define DC_LOGGER \
16           link->ctx->logger
17 
18 /* maximum pre emphasis level allowed for each voltage swing level*/
19 static const enum dc_pre_emphasis voltage_swing_to_pre_emphasis[] = {
20                     PRE_EMPHASIS_LEVEL3,
21                     PRE_EMPHASIS_LEVEL2,
22                     PRE_EMPHASIS_LEVEL1,
23                     PRE_EMPHASIS_DISABLED };
24 
25 enum {
26           POST_LT_ADJ_REQ_LIMIT = 6,
27           POST_LT_ADJ_REQ_TIMEOUT = 200
28 };
29 
30 enum {
31           LINK_TRAINING_MAX_RETRY_COUNT = 5,
32           /* to avoid infinite loop where-in the receiver
33            * switches between different VS
34            */
35           LINK_TRAINING_MAX_CR_RETRY = 100
36 };
37 
38 static bool decide_fallback_link_setting(
39                     struct dc_link_settings initial_link_settings,
40                     struct dc_link_settings *current_link_setting,
41                     enum link_training_result training_result);
42 static struct dc_link_settings get_common_supported_link_settings(
43                     struct dc_link_settings link_setting_a,
44                     struct dc_link_settings link_setting_b);
45 
wait_for_training_aux_rd_interval(struct dc_link * link,uint32_t default_wait_in_micro_secs)46 static void wait_for_training_aux_rd_interval(
47           struct dc_link *link,
48           uint32_t default_wait_in_micro_secs)
49 {
50           union training_aux_rd_interval training_rd_interval;
51 
52           /* overwrite the delay if rev > 1.1*/
53           if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
54                     /* DP 1.2 or later - retrieve delay through
55                      * "DPCD_ADDR_TRAINING_AUX_RD_INTERVAL" register */
56                     core_link_read_dpcd(
57                               link,
58                               DP_TRAINING_AUX_RD_INTERVAL,
59                               (uint8_t *)&training_rd_interval,
60                               sizeof(training_rd_interval));
61 
62                     if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL)
63                               default_wait_in_micro_secs =
64                                         training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000;
65           }
66 
67           udelay(default_wait_in_micro_secs);
68 
69           DC_LOG_HW_LINK_TRAINING("%s:\n wait = %d\n",
70                     __func__,
71                     default_wait_in_micro_secs);
72 }
73 
dpcd_set_training_pattern(struct dc_link * link,union dpcd_training_pattern dpcd_pattern)74 static void dpcd_set_training_pattern(
75           struct dc_link *link,
76           union dpcd_training_pattern dpcd_pattern)
77 {
78           core_link_write_dpcd(
79                     link,
80                     DP_TRAINING_PATTERN_SET,
81                     &dpcd_pattern.raw,
82                     1);
83 
84           DC_LOG_HW_LINK_TRAINING("%s\n %x pattern = %x\n",
85                     __func__,
86                     DP_TRAINING_PATTERN_SET,
87                     dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
88 }
89 
dpcd_set_link_settings(struct dc_link * link,const struct link_training_settings * lt_settings)90 static void dpcd_set_link_settings(
91           struct dc_link *link,
92           const struct link_training_settings *lt_settings)
93 {
94           uint8_t rate = (uint8_t)
95           (lt_settings->link_settings.link_rate);
96 
97           union down_spread_ctrl downspread = { {0} };
98           union lane_count_set lane_count_set = { {0} };
99           uint8_t link_set_buffer[2];
100 
101           downspread.raw = (uint8_t)
102           (lt_settings->link_settings.link_spread);
103 
104           lane_count_set.bits.LANE_COUNT_SET =
105           lt_settings->link_settings.lane_count;
106 
107           lane_count_set.bits.ENHANCED_FRAMING = 1;
108 
109           lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED =
110                     link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED;
111 
112           link_set_buffer[0] = rate;
113           link_set_buffer[1] = lane_count_set.raw;
114 
115           core_link_write_dpcd(link, DP_LINK_BW_SET,
116           link_set_buffer, 2);
117           core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,
118           &downspread.raw, sizeof(downspread));
119 
120           DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x\n %x spread = %x\n",
121                     __func__,
122                     DP_LINK_BW_SET,
123                     lt_settings->link_settings.link_rate,
124                     DP_LANE_COUNT_SET,
125                     lt_settings->link_settings.lane_count,
126                     DP_DOWNSPREAD_CTRL,
127                     lt_settings->link_settings.link_spread);
128 
129 }
130 
131 static enum dpcd_training_patterns
hw_training_pattern_to_dpcd_training_pattern(struct dc_link * link,enum hw_dp_training_pattern pattern)132           hw_training_pattern_to_dpcd_training_pattern(
133           struct dc_link *link,
134           enum hw_dp_training_pattern pattern)
135 {
136           enum dpcd_training_patterns dpcd_tr_pattern =
137           DPCD_TRAINING_PATTERN_VIDEOIDLE;
138 
139           switch (pattern) {
140           case HW_DP_TRAINING_PATTERN_1:
141                     dpcd_tr_pattern = DPCD_TRAINING_PATTERN_1;
142                     break;
143           case HW_DP_TRAINING_PATTERN_2:
144                     dpcd_tr_pattern = DPCD_TRAINING_PATTERN_2;
145                     break;
146           case HW_DP_TRAINING_PATTERN_3:
147                     dpcd_tr_pattern = DPCD_TRAINING_PATTERN_3;
148                     break;
149           case HW_DP_TRAINING_PATTERN_4:
150                     dpcd_tr_pattern = DPCD_TRAINING_PATTERN_4;
151                     break;
152           default:
153                     ASSERT(0);
154                     DC_LOG_HW_LINK_TRAINING("%s: Invalid HW Training pattern: %d\n",
155                               __func__, pattern);
156                     break;
157           }
158 
159           return dpcd_tr_pattern;
160 
161 }
162 
dpcd_set_lt_pattern_and_lane_settings(struct dc_link * link,const struct link_training_settings * lt_settings,enum hw_dp_training_pattern pattern)163 static void dpcd_set_lt_pattern_and_lane_settings(
164           struct dc_link *link,
165           const struct link_training_settings *lt_settings,
166           enum hw_dp_training_pattern pattern)
167 {
168           union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = { { {0} } };
169           const uint32_t dpcd_base_lt_offset =
170           DP_TRAINING_PATTERN_SET;
171           uint8_t dpcd_lt_buffer[5] = {0};
172           union dpcd_training_pattern dpcd_pattern = { {0} };
173           uint32_t lane;
174           uint32_t size_in_bytes;
175           bool edp_workaround = false; /* TODO link_prop.INTERNAL */
176 
177           /*****************************************************************
178           * DpcdAddress_TrainingPatternSet
179           *****************************************************************/
180           dpcd_pattern.v1_4.TRAINING_PATTERN_SET =
181                     hw_training_pattern_to_dpcd_training_pattern(link, pattern);
182 
183           dpcd_lt_buffer[DP_TRAINING_PATTERN_SET - dpcd_base_lt_offset]
184                     = dpcd_pattern.raw;
185 
186           DC_LOG_HW_LINK_TRAINING("%s\n %x pattern = %x\n",
187                     __func__,
188                     DP_TRAINING_PATTERN_SET,
189                     dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
190 
191           /*****************************************************************
192           * DpcdAddress_Lane0Set -> DpcdAddress_Lane3Set
193           *****************************************************************/
194           for (lane = 0; lane <
195                     (uint32_t)(lt_settings->link_settings.lane_count); lane++) {
196 
197                     dpcd_lane[lane].bits.VOLTAGE_SWING_SET =
198                     (uint8_t)(lt_settings->lane_settings[lane].VOLTAGE_SWING);
199                     dpcd_lane[lane].bits.PRE_EMPHASIS_SET =
200                     (uint8_t)(lt_settings->lane_settings[lane].PRE_EMPHASIS);
201 
202                     dpcd_lane[lane].bits.MAX_SWING_REACHED =
203                     (lt_settings->lane_settings[lane].VOLTAGE_SWING ==
204                     VOLTAGE_SWING_MAX_LEVEL ? 1 : 0);
205                     dpcd_lane[lane].bits.MAX_PRE_EMPHASIS_REACHED =
206                     (lt_settings->lane_settings[lane].PRE_EMPHASIS ==
207                     PRE_EMPHASIS_MAX_LEVEL ? 1 : 0);
208           }
209 
210           /* concatinate everything into one buffer*/
211 
212           size_in_bytes = lt_settings->link_settings.lane_count * sizeof(dpcd_lane[0]);
213 
214            // 0x00103 - 0x00102
215           memmove(
216                     &dpcd_lt_buffer[DP_TRAINING_LANE0_SET - dpcd_base_lt_offset],
217                     dpcd_lane,
218                     size_in_bytes);
219 
220           DC_LOG_HW_LINK_TRAINING("%s:\n %x VS set = %x  PE set = %x max VS Reached = %x  max PE Reached = %x\n",
221                     __func__,
222                     DP_TRAINING_LANE0_SET,
223                     dpcd_lane[0].bits.VOLTAGE_SWING_SET,
224                     dpcd_lane[0].bits.PRE_EMPHASIS_SET,
225                     dpcd_lane[0].bits.MAX_SWING_REACHED,
226                     dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
227 
228           if (edp_workaround) {
229                     /* for eDP write in 2 parts because the 5-byte burst is
230                     * causing issues on some eDP panels (EPR#366724)
231                     */
232                     core_link_write_dpcd(
233                               link,
234                               DP_TRAINING_PATTERN_SET,
235                               &dpcd_pattern.raw,
236                               sizeof(dpcd_pattern.raw));
237 
238                     core_link_write_dpcd(
239                               link,
240                               DP_TRAINING_LANE0_SET,
241                               (uint8_t *)(dpcd_lane),
242                               size_in_bytes);
243 
244                     } else
245                     /* write it all in (1 + number-of-lanes)-byte burst*/
246                               core_link_write_dpcd(
247                                         link,
248                                         dpcd_base_lt_offset,
249                                         dpcd_lt_buffer,
250                                         size_in_bytes + sizeof(dpcd_pattern.raw));
251 
252           link->cur_lane_setting = lt_settings->lane_settings[0];
253 }
254 
is_cr_done(enum dc_lane_count ln_count,union lane_status * dpcd_lane_status)255 static bool is_cr_done(enum dc_lane_count ln_count,
256           union lane_status *dpcd_lane_status)
257 {
258           bool done = true;
259           uint32_t lane;
260           /*LANEx_CR_DONE bits All 1's?*/
261           for (lane = 0; lane < (uint32_t)(ln_count); lane++) {
262                     if (!dpcd_lane_status[lane].bits.CR_DONE_0)
263                               done = false;
264           }
265           return done;
266 
267 }
268 
is_ch_eq_done(enum dc_lane_count ln_count,union lane_status * dpcd_lane_status,union lane_align_status_updated * lane_status_updated)269 static bool is_ch_eq_done(enum dc_lane_count ln_count,
270           union lane_status *dpcd_lane_status,
271           union lane_align_status_updated *lane_status_updated)
272 {
273           bool done = true;
274           uint32_t lane;
275           if (!lane_status_updated->bits.INTERLANE_ALIGN_DONE)
276                     done = false;
277           else {
278                     for (lane = 0; lane < (uint32_t)(ln_count); lane++) {
279                               if (!dpcd_lane_status[lane].bits.SYMBOL_LOCKED_0 ||
280                                         !dpcd_lane_status[lane].bits.CHANNEL_EQ_DONE_0)
281                                         done = false;
282                     }
283           }
284           return done;
285 
286 }
287 
update_drive_settings(struct link_training_settings * dest,struct link_training_settings src)288 static void update_drive_settings(
289                     struct link_training_settings *dest,
290                     struct link_training_settings src)
291 {
292           uint32_t lane;
293           for (lane = 0; lane < src.link_settings.lane_count; lane++) {
294                     dest->lane_settings[lane].VOLTAGE_SWING =
295                               src.lane_settings[lane].VOLTAGE_SWING;
296                     dest->lane_settings[lane].PRE_EMPHASIS =
297                               src.lane_settings[lane].PRE_EMPHASIS;
298                     dest->lane_settings[lane].POST_CURSOR2 =
299                               src.lane_settings[lane].POST_CURSOR2;
300           }
301 }
302 
get_nibble_at_index(const uint8_t * buf,uint32_t index)303 static uint8_t get_nibble_at_index(const uint8_t *buf,
304           uint32_t index)
305 {
306           uint8_t nibble;
307           nibble = buf[index / 2];
308 
309           if (index % 2)
310                     nibble >>= 4;
311           else
312                     nibble &= 0x0F;
313 
314           return nibble;
315 }
316 
get_max_pre_emphasis_for_voltage_swing(enum dc_voltage_swing voltage)317 static enum dc_pre_emphasis get_max_pre_emphasis_for_voltage_swing(
318           enum dc_voltage_swing voltage)
319 {
320           enum dc_pre_emphasis pre_emphasis;
321           pre_emphasis = PRE_EMPHASIS_MAX_LEVEL;
322 
323           if (voltage <= VOLTAGE_SWING_MAX_LEVEL)
324                     pre_emphasis = voltage_swing_to_pre_emphasis[voltage];
325 
326           return pre_emphasis;
327 
328 }
329 
find_max_drive_settings(const struct link_training_settings * link_training_setting,struct link_training_settings * max_lt_setting)330 static void find_max_drive_settings(
331           const struct link_training_settings *link_training_setting,
332           struct link_training_settings *max_lt_setting)
333 {
334           uint32_t lane;
335           struct dc_lane_settings max_requested;
336 
337           max_requested.VOLTAGE_SWING =
338                     link_training_setting->
339                     lane_settings[0].VOLTAGE_SWING;
340           max_requested.PRE_EMPHASIS =
341                     link_training_setting->
342                     lane_settings[0].PRE_EMPHASIS;
343           /*max_requested.postCursor2 =
344            * link_training_setting->laneSettings[0].postCursor2;*/
345 
346           /* Determine what the maximum of the requested settings are*/
347           for (lane = 1; lane < link_training_setting->link_settings.lane_count;
348                               lane++) {
349                     if (link_training_setting->lane_settings[lane].VOLTAGE_SWING >
350                               max_requested.VOLTAGE_SWING)
351 
352                               max_requested.VOLTAGE_SWING =
353                               link_training_setting->
354                               lane_settings[lane].VOLTAGE_SWING;
355 
356                     if (link_training_setting->lane_settings[lane].PRE_EMPHASIS >
357                                         max_requested.PRE_EMPHASIS)
358                               max_requested.PRE_EMPHASIS =
359                               link_training_setting->
360                               lane_settings[lane].PRE_EMPHASIS;
361 
362                     /*
363                     if (link_training_setting->laneSettings[lane].postCursor2 >
364                      max_requested.postCursor2)
365                     {
366                     max_requested.postCursor2 =
367                     link_training_setting->laneSettings[lane].postCursor2;
368                     }
369                     */
370           }
371 
372           /* make sure the requested settings are
373            * not higher than maximum settings*/
374           if (max_requested.VOLTAGE_SWING > VOLTAGE_SWING_MAX_LEVEL)
375                     max_requested.VOLTAGE_SWING = VOLTAGE_SWING_MAX_LEVEL;
376 
377           if (max_requested.PRE_EMPHASIS > PRE_EMPHASIS_MAX_LEVEL)
378                     max_requested.PRE_EMPHASIS = PRE_EMPHASIS_MAX_LEVEL;
379           /*
380           if (max_requested.postCursor2 > PostCursor2_MaxLevel)
381           max_requested.postCursor2 = PostCursor2_MaxLevel;
382           */
383 
384           /* make sure the pre-emphasis matches the voltage swing*/
385           if (max_requested.PRE_EMPHASIS >
386                     get_max_pre_emphasis_for_voltage_swing(
387                               max_requested.VOLTAGE_SWING))
388                     max_requested.PRE_EMPHASIS =
389                     get_max_pre_emphasis_for_voltage_swing(
390                               max_requested.VOLTAGE_SWING);
391 
392           /*
393            * Post Cursor2 levels are completely independent from
394            * pre-emphasis (Post Cursor1) levels. But Post Cursor2 levels
395            * can only be applied to each allowable combination of voltage
396            * swing and pre-emphasis levels */
397            /* if ( max_requested.postCursor2 >
398             *  getMaxPostCursor2ForVoltageSwing(max_requested.voltageSwing))
399             *  max_requested.postCursor2 =
400             *  getMaxPostCursor2ForVoltageSwing(max_requested.voltageSwing);
401             */
402 
403           max_lt_setting->link_settings.link_rate =
404                     link_training_setting->link_settings.link_rate;
405           max_lt_setting->link_settings.lane_count =
406           link_training_setting->link_settings.lane_count;
407           max_lt_setting->link_settings.link_spread =
408                     link_training_setting->link_settings.link_spread;
409 
410           for (lane = 0; lane <
411                     link_training_setting->link_settings.lane_count;
412                     lane++) {
413                     max_lt_setting->lane_settings[lane].VOLTAGE_SWING =
414                               max_requested.VOLTAGE_SWING;
415                     max_lt_setting->lane_settings[lane].PRE_EMPHASIS =
416                               max_requested.PRE_EMPHASIS;
417                     /*max_lt_setting->laneSettings[lane].postCursor2 =
418                      * max_requested.postCursor2;
419                      */
420           }
421 
422 }
423 
get_lane_status_and_drive_settings(struct dc_link * link,const struct link_training_settings * link_training_setting,union lane_status * ln_status,union lane_align_status_updated * ln_status_updated,struct link_training_settings * req_settings)424 static void get_lane_status_and_drive_settings(
425           struct dc_link *link,
426           const struct link_training_settings *link_training_setting,
427           union lane_status *ln_status,
428           union lane_align_status_updated *ln_status_updated,
429           struct link_training_settings *req_settings)
430 {
431           uint8_t dpcd_buf[6] = {0};
432           union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = { { {0} } };
433           struct link_training_settings request_settings = { {0} };
434           uint32_t lane;
435 
436           memset(req_settings, '\0', sizeof(struct link_training_settings));
437 
438           core_link_read_dpcd(
439                     link,
440                     DP_LANE0_1_STATUS,
441                     (uint8_t *)(dpcd_buf),
442                     sizeof(dpcd_buf));
443 
444           for (lane = 0; lane <
445                     (uint32_t)(link_training_setting->link_settings.lane_count);
446                     lane++) {
447 
448                     ln_status[lane].raw =
449                               get_nibble_at_index(&dpcd_buf[0], lane);
450                     dpcd_lane_adjust[lane].raw =
451                               get_nibble_at_index(&dpcd_buf[4], lane);
452           }
453 
454           ln_status_updated->raw = dpcd_buf[2];
455 
456           DC_LOG_HW_LINK_TRAINING("%s:\n%x Lane01Status = %x\n %x Lane23Status = %x\n ",
457                     __func__,
458                     DP_LANE0_1_STATUS, dpcd_buf[0],
459                     DP_LANE2_3_STATUS, dpcd_buf[1]);
460 
461           DC_LOG_HW_LINK_TRAINING("%s:\n %x Lane01AdjustRequest = %x\n %x Lane23AdjustRequest = %x\n",
462                     __func__,
463                     DP_ADJUST_REQUEST_LANE0_1,
464                     dpcd_buf[4],
465                     DP_ADJUST_REQUEST_LANE2_3,
466                     dpcd_buf[5]);
467 
468           /*copy to req_settings*/
469           request_settings.link_settings.lane_count =
470                     link_training_setting->link_settings.lane_count;
471           request_settings.link_settings.link_rate =
472                     link_training_setting->link_settings.link_rate;
473           request_settings.link_settings.link_spread =
474                     link_training_setting->link_settings.link_spread;
475 
476           for (lane = 0; lane <
477                     (uint32_t)(link_training_setting->link_settings.lane_count);
478                     lane++) {
479 
480                     request_settings.lane_settings[lane].VOLTAGE_SWING =
481                               (enum dc_voltage_swing)(dpcd_lane_adjust[lane].bits.
482                                         VOLTAGE_SWING_LANE);
483                     request_settings.lane_settings[lane].PRE_EMPHASIS =
484                               (enum dc_pre_emphasis)(dpcd_lane_adjust[lane].bits.
485                                         PRE_EMPHASIS_LANE);
486           }
487 
488           /*Note: for postcursor2, read adjusted
489            * postcursor2 settings from*/
490           /*DpcdAddress_AdjustRequestPostCursor2 =
491            *0x020C (not implemented yet)*/
492 
493           /* we find the maximum of the requested settings across all lanes*/
494           /* and set this maximum for all lanes*/
495           find_max_drive_settings(&request_settings, req_settings);
496 
497           /* if post cursor 2 is needed in the future,
498            * read DpcdAddress_AdjustRequestPostCursor2 = 0x020C
499            */
500 
501 }
502 
dpcd_set_lane_settings(struct dc_link * link,const struct link_training_settings * link_training_setting)503 static void dpcd_set_lane_settings(
504           struct dc_link *link,
505           const struct link_training_settings *link_training_setting)
506 {
507           union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}};
508           uint32_t lane;
509 
510           for (lane = 0; lane <
511                     (uint32_t)(link_training_setting->
512                     link_settings.lane_count);
513                     lane++) {
514                     dpcd_lane[lane].bits.VOLTAGE_SWING_SET =
515                               (uint8_t)(link_training_setting->
516                               lane_settings[lane].VOLTAGE_SWING);
517                     dpcd_lane[lane].bits.PRE_EMPHASIS_SET =
518                               (uint8_t)(link_training_setting->
519                               lane_settings[lane].PRE_EMPHASIS);
520                     dpcd_lane[lane].bits.MAX_SWING_REACHED =
521                               (link_training_setting->
522                               lane_settings[lane].VOLTAGE_SWING ==
523                               VOLTAGE_SWING_MAX_LEVEL ? 1 : 0);
524                     dpcd_lane[lane].bits.MAX_PRE_EMPHASIS_REACHED =
525                               (link_training_setting->
526                               lane_settings[lane].PRE_EMPHASIS ==
527                               PRE_EMPHASIS_MAX_LEVEL ? 1 : 0);
528           }
529 
530           core_link_write_dpcd(link,
531                     DP_TRAINING_LANE0_SET,
532                     (uint8_t *)(dpcd_lane),
533                     link_training_setting->link_settings.lane_count);
534 
535           /*
536           if (LTSettings.link.rate == LinkRate_High2)
537           {
538                     DpcdTrainingLaneSet2 dpcd_lane2[lane_count_DPMax] = {0};
539                     for ( uint32_t lane = 0;
540                     lane < lane_count_DPMax; lane++)
541                     {
542                               dpcd_lane2[lane].bits.post_cursor2_set =
543                               static_cast<unsigned char>(
544                               LTSettings.laneSettings[lane].postCursor2);
545                               dpcd_lane2[lane].bits.max_post_cursor2_reached = 0;
546                     }
547                     m_pDpcdAccessSrv->WriteDpcdData(
548                     DpcdAddress_Lane0Set2,
549                     reinterpret_cast<unsigned char*>(dpcd_lane2),
550                     LTSettings.link.lanes);
551           }
552           */
553 
554           DC_LOG_HW_LINK_TRAINING("%s\n %x VS set = %x  PE set = %x max VS Reached = %x  max PE Reached = %x\n",
555                     __func__,
556                     DP_TRAINING_LANE0_SET,
557                     dpcd_lane[0].bits.VOLTAGE_SWING_SET,
558                     dpcd_lane[0].bits.PRE_EMPHASIS_SET,
559                     dpcd_lane[0].bits.MAX_SWING_REACHED,
560                     dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
561 
562           link->cur_lane_setting = link_training_setting->lane_settings[0];
563 
564 }
565 
is_max_vs_reached(const struct link_training_settings * lt_settings)566 static bool is_max_vs_reached(
567           const struct link_training_settings *lt_settings)
568 {
569           uint32_t lane;
570           for (lane = 0; lane <
571                     (uint32_t)(lt_settings->link_settings.lane_count);
572                     lane++) {
573                     if (lt_settings->lane_settings[lane].VOLTAGE_SWING
574                               == VOLTAGE_SWING_MAX_LEVEL)
575                               return true;
576           }
577           return false;
578 
579 }
580 
dc_link_dp_set_drive_settings(struct dc_link * link,struct link_training_settings * lt_settings)581 void dc_link_dp_set_drive_settings(
582           struct dc_link *link,
583           struct link_training_settings *lt_settings)
584 {
585           /* program ASIC PHY settings*/
586           dp_set_hw_lane_settings(link, lt_settings);
587 
588           /* Notify DP sink the PHY settings from source */
589           dpcd_set_lane_settings(link, lt_settings);
590 }
591 
perform_post_lt_adj_req_sequence(struct dc_link * link,struct link_training_settings * lt_settings)592 static bool perform_post_lt_adj_req_sequence(
593           struct dc_link *link,
594           struct link_training_settings *lt_settings)
595 {
596           enum dc_lane_count lane_count =
597           lt_settings->link_settings.lane_count;
598 
599           uint32_t adj_req_count;
600           uint32_t adj_req_timer;
601           bool req_drv_setting_changed;
602           uint32_t lane;
603 
604           req_drv_setting_changed = false;
605           for (adj_req_count = 0; adj_req_count < POST_LT_ADJ_REQ_LIMIT;
606           adj_req_count++) {
607 
608                     req_drv_setting_changed = false;
609 
610                     for (adj_req_timer = 0;
611                               adj_req_timer < POST_LT_ADJ_REQ_TIMEOUT;
612                               adj_req_timer++) {
613 
614                               struct link_training_settings req_settings;
615                               union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
616                               union lane_align_status_updated
617                                         dpcd_lane_status_updated;
618 
619                               get_lane_status_and_drive_settings(
620                               link,
621                               lt_settings,
622                               dpcd_lane_status,
623                               &dpcd_lane_status_updated,
624                               &req_settings);
625 
626                               if (dpcd_lane_status_updated.bits.
627                                                   POST_LT_ADJ_REQ_IN_PROGRESS == 0)
628                                         return true;
629 
630                               if (!is_cr_done(lane_count, dpcd_lane_status))
631                                         return false;
632 
633                               if (!is_ch_eq_done(
634                                         lane_count,
635                                         dpcd_lane_status,
636                                         &dpcd_lane_status_updated))
637                                         return false;
638 
639                               for (lane = 0; lane < (uint32_t)(lane_count); lane++) {
640 
641                                         if (lt_settings->
642                                         lane_settings[lane].VOLTAGE_SWING !=
643                                         req_settings.lane_settings[lane].
644                                         VOLTAGE_SWING ||
645                                         lt_settings->lane_settings[lane].PRE_EMPHASIS !=
646                                         req_settings.lane_settings[lane].PRE_EMPHASIS) {
647 
648                                                   req_drv_setting_changed = true;
649                                                   break;
650                                         }
651                               }
652 
653                               if (req_drv_setting_changed) {
654                                         update_drive_settings(
655                                                   lt_settings, req_settings);
656 
657                                         dc_link_dp_set_drive_settings(link,
658                                                             lt_settings);
659                                         break;
660                               }
661 
662                               msleep(1);
663                     }
664 
665                     if (!req_drv_setting_changed) {
666                               DC_LOG_WARNING("%s: Post Link Training Adjust Request Timed out\n",
667                                         __func__);
668 
669                               ASSERT(0);
670                               return true;
671                     }
672           }
673           DC_LOG_WARNING("%s: Post Link Training Adjust Request limit reached\n",
674                     __func__);
675 
676           ASSERT(0);
677           return true;
678 
679 }
680 
get_supported_tp(struct dc_link * link)681 static enum hw_dp_training_pattern get_supported_tp(struct dc_link *link)
682 {
683           enum hw_dp_training_pattern highest_tp = HW_DP_TRAINING_PATTERN_2;
684           struct encoder_feature_support *features = &link->link_enc->features;
685           struct dpcd_caps *dpcd_caps = &link->dpcd_caps;
686 
687           if (features->flags.bits.IS_TPS3_CAPABLE)
688                     highest_tp = HW_DP_TRAINING_PATTERN_3;
689 
690           if (features->flags.bits.IS_TPS4_CAPABLE)
691                     highest_tp = HW_DP_TRAINING_PATTERN_4;
692 
693           if (dpcd_caps->max_down_spread.bits.TPS4_SUPPORTED &&
694                     highest_tp >= HW_DP_TRAINING_PATTERN_4)
695                     return HW_DP_TRAINING_PATTERN_4;
696 
697           if (dpcd_caps->max_ln_count.bits.TPS3_SUPPORTED &&
698                     highest_tp >= HW_DP_TRAINING_PATTERN_3)
699                     return HW_DP_TRAINING_PATTERN_3;
700 
701           return HW_DP_TRAINING_PATTERN_2;
702 }
703 
get_cr_failure(enum dc_lane_count ln_count,union lane_status * dpcd_lane_status)704 static enum link_training_result get_cr_failure(enum dc_lane_count ln_count,
705                                                   union lane_status *dpcd_lane_status)
706 {
707           enum link_training_result result = LINK_TRAINING_SUCCESS;
708 
709           if (ln_count >= LANE_COUNT_ONE && !dpcd_lane_status[0].bits.CR_DONE_0)
710                     result = LINK_TRAINING_CR_FAIL_LANE0;
711           else if (ln_count >= LANE_COUNT_TWO && !dpcd_lane_status[1].bits.CR_DONE_0)
712                     result = LINK_TRAINING_CR_FAIL_LANE1;
713           else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[2].bits.CR_DONE_0)
714                     result = LINK_TRAINING_CR_FAIL_LANE23;
715           else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[3].bits.CR_DONE_0)
716                     result = LINK_TRAINING_CR_FAIL_LANE23;
717           return result;
718 }
719 
perform_channel_equalization_sequence(struct dc_link * link,struct link_training_settings * lt_settings)720 static enum link_training_result perform_channel_equalization_sequence(
721           struct dc_link *link,
722           struct link_training_settings *lt_settings)
723 {
724           struct link_training_settings req_settings;
725           enum hw_dp_training_pattern hw_tr_pattern;
726           uint32_t retries_ch_eq;
727           enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
728           union lane_align_status_updated dpcd_lane_status_updated = { {0} };
729           union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } };
730 
731           hw_tr_pattern = get_supported_tp(link);
732 
733           dp_set_hw_training_pattern(link, hw_tr_pattern);
734 
735           for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT;
736                     retries_ch_eq++) {
737 
738                     dp_set_hw_lane_settings(link, lt_settings);
739 
740                     /* 2. update DPCD*/
741                     if (!retries_ch_eq)
742                               /* EPR #361076 - write as a 5-byte burst,
743                                * but only for the 1-st iteration*/
744                               dpcd_set_lt_pattern_and_lane_settings(
745                                         link,
746                                         lt_settings,
747                                         hw_tr_pattern);
748                     else
749                               dpcd_set_lane_settings(link, lt_settings);
750 
751                     /* 3. wait for receiver to lock-on*/
752                     wait_for_training_aux_rd_interval(link, 400);
753 
754                     /* 4. Read lane status and requested
755                      * drive settings as set by the sink*/
756 
757                     get_lane_status_and_drive_settings(
758                               link,
759                               lt_settings,
760                               dpcd_lane_status,
761                               &dpcd_lane_status_updated,
762                               &req_settings);
763 
764                     /* 5. check CR done*/
765                     if (!is_cr_done(lane_count, dpcd_lane_status))
766                               return LINK_TRAINING_EQ_FAIL_CR;
767 
768                     /* 6. check CHEQ done*/
769                     if (is_ch_eq_done(lane_count,
770                               dpcd_lane_status,
771                               &dpcd_lane_status_updated))
772                               return LINK_TRAINING_SUCCESS;
773 
774                     /* 7. update VS/PE/PC2 in lt_settings*/
775                     update_drive_settings(lt_settings, req_settings);
776           }
777 
778           return LINK_TRAINING_EQ_FAIL_EQ;
779 
780 }
781 
perform_clock_recovery_sequence(struct dc_link * link,struct link_training_settings * lt_settings)782 static enum link_training_result perform_clock_recovery_sequence(
783           struct dc_link *link,
784           struct link_training_settings *lt_settings)
785 {
786           uint32_t retries_cr;
787           uint32_t retry_count;
788           uint32_t lane;
789           struct link_training_settings req_settings;
790           enum dc_lane_count lane_count =
791           lt_settings->link_settings.lane_count;
792           enum hw_dp_training_pattern hw_tr_pattern = HW_DP_TRAINING_PATTERN_1;
793           union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
794           union lane_align_status_updated dpcd_lane_status_updated;
795 
796           retries_cr = 0;
797           retry_count = 0;
798           /* initial drive setting (VS/PE/PC2)*/
799           for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
800                     lt_settings->lane_settings[lane].VOLTAGE_SWING =
801                     VOLTAGE_SWING_LEVEL0;
802                     lt_settings->lane_settings[lane].PRE_EMPHASIS =
803                     PRE_EMPHASIS_DISABLED;
804                     lt_settings->lane_settings[lane].POST_CURSOR2 =
805                     POST_CURSOR2_DISABLED;
806           }
807 
808           dp_set_hw_training_pattern(link, hw_tr_pattern);
809 
810           /* najeeb - The synaptics MST hub can put the LT in
811           * infinite loop by switching the VS
812           */
813           /* between level 0 and level 1 continuously, here
814           * we try for CR lock for LinkTrainingMaxCRRetry count*/
815           while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) &&
816           (retry_count < LINK_TRAINING_MAX_CR_RETRY)) {
817 
818                     memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status));
819                     memset(&dpcd_lane_status_updated, '\0',
820                     sizeof(dpcd_lane_status_updated));
821 
822                     /* 1. call HWSS to set lane settings*/
823                     dp_set_hw_lane_settings(
824                                         link,
825                                         lt_settings);
826 
827                     /* 2. update DPCD of the receiver*/
828                     if (!retries_cr)
829                               /* EPR #361076 - write as a 5-byte burst,
830                                * but only for the 1-st iteration.*/
831                               dpcd_set_lt_pattern_and_lane_settings(
832                                                   link,
833                                                   lt_settings,
834                                                   hw_tr_pattern);
835                     else
836                               dpcd_set_lane_settings(
837                                                   link,
838                                                   lt_settings);
839 
840                     /* 3. wait receiver to lock-on*/
841                     wait_for_training_aux_rd_interval(
842                                         link,
843                                         100);
844 
845                     /* 4. Read lane status and requested drive
846                     * settings as set by the sink
847                     */
848                     get_lane_status_and_drive_settings(
849                                         link,
850                                         lt_settings,
851                                         dpcd_lane_status,
852                                         &dpcd_lane_status_updated,
853                                         &req_settings);
854 
855                     /* 5. check CR done*/
856                     if (is_cr_done(lane_count, dpcd_lane_status))
857                               return LINK_TRAINING_SUCCESS;
858 
859                     /* 6. max VS reached*/
860                     if (is_max_vs_reached(lt_settings))
861                               break;
862 
863                     /* 7. same voltage*/
864                     /* Note: VS same for all lanes,
865                     * so comparing first lane is sufficient*/
866                     if (lt_settings->lane_settings[0].VOLTAGE_SWING ==
867                               req_settings.lane_settings[0].VOLTAGE_SWING)
868                               retries_cr++;
869                     else
870                               retries_cr = 0;
871 
872                     /* 8. update VS/PE/PC2 in lt_settings*/
873                     update_drive_settings(lt_settings, req_settings);
874 
875                     retry_count++;
876           }
877 
878           if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) {
879                     ASSERT(0);
880                     DC_LOG_ERROR("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue",
881                               __func__,
882                               LINK_TRAINING_MAX_CR_RETRY);
883 
884           }
885 
886           return get_cr_failure(lane_count, dpcd_lane_status);
887 }
888 
perform_link_training_int(struct dc_link * link,struct link_training_settings * lt_settings,enum link_training_result status)889 static inline enum link_training_result perform_link_training_int(
890           struct dc_link *link,
891           struct link_training_settings *lt_settings,
892           enum link_training_result status)
893 {
894           union lane_count_set lane_count_set = { {0} };
895           union dpcd_training_pattern dpcd_pattern = { {0} };
896 
897           /* 3. set training not in progress*/
898           dpcd_pattern.v1_4.TRAINING_PATTERN_SET = DPCD_TRAINING_PATTERN_VIDEOIDLE;
899           dpcd_set_training_pattern(link, dpcd_pattern);
900 
901           /* 4. mainlink output idle pattern*/
902           dp_set_hw_test_pattern(link, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);
903 
904           /*
905            * 5. post training adjust if required
906            * If the upstream DPTX and downstream DPRX both support TPS4,
907            * TPS4 must be used instead of POST_LT_ADJ_REQ.
908            */
909           if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED != 1 ||
910                               get_supported_tp(link) == HW_DP_TRAINING_PATTERN_4)
911                     return status;
912 
913           if (status == LINK_TRAINING_SUCCESS &&
914                     perform_post_lt_adj_req_sequence(link, lt_settings) == false)
915                     status = LINK_TRAINING_LQA_FAIL;
916 
917           lane_count_set.bits.LANE_COUNT_SET = lt_settings->link_settings.lane_count;
918           lane_count_set.bits.ENHANCED_FRAMING = 1;
919           lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
920 
921           core_link_write_dpcd(
922                     link,
923                     DP_LANE_COUNT_SET,
924                     &lane_count_set.raw,
925                     sizeof(lane_count_set));
926 
927           return status;
928 }
929 
dc_link_dp_perform_link_training(struct dc_link * link,const struct dc_link_settings * link_setting,bool skip_video_pattern)930 enum link_training_result dc_link_dp_perform_link_training(
931           struct dc_link *link,
932           const struct dc_link_settings *link_setting,
933           bool skip_video_pattern)
934 {
935           enum link_training_result status = LINK_TRAINING_SUCCESS;
936 
937           char *link_rate = "Unknown";
938           char *lt_result = "Unknown";
939 
940           struct link_training_settings lt_settings;
941 
942           memset(&lt_settings, '\0', sizeof(lt_settings));
943 
944           lt_settings.link_settings.link_rate = link_setting->link_rate;
945           lt_settings.link_settings.lane_count = link_setting->lane_count;
946 
947           /*@todo[vdevulap] move SS to LS, should not be handled by displaypath*/
948 
949           /* TODO hard coded to SS for now
950            * lt_settings.link_settings.link_spread =
951            * dal_display_path_is_ss_supported(
952            * path_mode->display_path) ?
953            * LINK_SPREAD_05_DOWNSPREAD_30KHZ :
954            * LINK_SPREAD_DISABLED;
955            */
956           if (link->dp_ss_off)
957                     lt_settings.link_settings.link_spread = LINK_SPREAD_DISABLED;
958           else
959                     lt_settings.link_settings.link_spread = LINK_SPREAD_05_DOWNSPREAD_30KHZ;
960 
961           /* 1. set link rate, lane count and spread*/
962           dpcd_set_link_settings(link, &lt_settings);
963 
964           /* 2. perform link training (set link training done
965            *  to false is done as well)*/
966           status = perform_clock_recovery_sequence(link, &lt_settings);
967           if (status == LINK_TRAINING_SUCCESS) {
968                     status = perform_channel_equalization_sequence(link,
969                                         &lt_settings);
970           }
971 
972           if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern) {
973                     status = perform_link_training_int(link,
974                                         &lt_settings,
975                                         status);
976           }
977 
978           /* 6. print status message*/
979           switch (lt_settings.link_settings.link_rate) {
980 
981           case LINK_RATE_LOW:
982                     link_rate = "RBR";
983                     break;
984           case LINK_RATE_HIGH:
985                     link_rate = "HBR";
986                     break;
987           case LINK_RATE_HIGH2:
988                     link_rate = "HBR2";
989                     break;
990           case LINK_RATE_RBR2:
991                     link_rate = "RBR2";
992                     break;
993           case LINK_RATE_HIGH3:
994                     link_rate = "HBR3";
995                     break;
996           default:
997                     break;
998           }
999 
1000           switch (status) {
1001           case LINK_TRAINING_SUCCESS:
1002                     lt_result = "pass";
1003                     break;
1004           case LINK_TRAINING_CR_FAIL_LANE0:
1005                     lt_result = "CR failed lane0";
1006                     break;
1007           case LINK_TRAINING_CR_FAIL_LANE1:
1008                     lt_result = "CR failed lane1";
1009                     break;
1010           case LINK_TRAINING_CR_FAIL_LANE23:
1011                     lt_result = "CR failed lane23";
1012                     break;
1013           case LINK_TRAINING_EQ_FAIL_CR:
1014                     lt_result = "CR failed in EQ";
1015                     break;
1016           case LINK_TRAINING_EQ_FAIL_EQ:
1017                     lt_result = "EQ failed";
1018                     break;
1019           case LINK_TRAINING_LQA_FAIL:
1020                     lt_result = "LQA failed";
1021                     break;
1022           default:
1023                     break;
1024           }
1025 
1026           /* Connectivity log: link training */
1027           CONN_MSG_LT(link, "%sx%d %s VS=%d, PE=%d",
1028                               link_rate,
1029                               lt_settings.link_settings.lane_count,
1030                               lt_result,
1031                               lt_settings.lane_settings[0].VOLTAGE_SWING,
1032                               lt_settings.lane_settings[0].PRE_EMPHASIS);
1033 
1034           if (status != LINK_TRAINING_SUCCESS)
1035                     link->ctx->dc->debug_data.ltFailCount++;
1036 
1037           return status;
1038 }
1039 
1040 
perform_link_training_with_retries(struct dc_link * link,const struct dc_link_settings * link_setting,bool skip_video_pattern,int attempts)1041 bool perform_link_training_with_retries(
1042           struct dc_link *link,
1043           const struct dc_link_settings *link_setting,
1044           bool skip_video_pattern,
1045           int attempts)
1046 {
1047           uint8_t j;
1048           uint8_t delay_between_attempts = LINK_TRAINING_RETRY_DELAY;
1049 
1050           for (j = 0; j < attempts; ++j) {
1051 
1052                     if (dc_link_dp_perform_link_training(
1053                                         link,
1054                                         link_setting,
1055                                         skip_video_pattern) == LINK_TRAINING_SUCCESS)
1056                               return true;
1057 
1058                     msleep(delay_between_attempts);
1059                     delay_between_attempts += LINK_TRAINING_RETRY_DELAY;
1060           }
1061 
1062           return false;
1063 }
1064 
get_max_link_cap(struct dc_link * link)1065 static struct dc_link_settings get_max_link_cap(struct dc_link *link)
1066 {
1067           /* Set Default link settings */
1068           struct dc_link_settings max_link_cap = {LANE_COUNT_FOUR, LINK_RATE_HIGH,
1069                               LINK_SPREAD_05_DOWNSPREAD_30KHZ};
1070 
1071           /* Higher link settings based on feature supported */
1072           if (link->link_enc->features.flags.bits.IS_HBR2_CAPABLE)
1073                     max_link_cap.link_rate = LINK_RATE_HIGH2;
1074 
1075           if (link->link_enc->features.flags.bits.IS_HBR3_CAPABLE)
1076                     max_link_cap.link_rate = LINK_RATE_HIGH3;
1077 
1078           /* Lower link settings based on sink's link cap */
1079           if (link->reported_link_cap.lane_count < max_link_cap.lane_count)
1080                     max_link_cap.lane_count =
1081                                         link->reported_link_cap.lane_count;
1082           if (link->reported_link_cap.link_rate < max_link_cap.link_rate)
1083                     max_link_cap.link_rate =
1084                                         link->reported_link_cap.link_rate;
1085           if (link->reported_link_cap.link_spread <
1086                               max_link_cap.link_spread)
1087                     max_link_cap.link_spread =
1088                                         link->reported_link_cap.link_spread;
1089           return max_link_cap;
1090 }
1091 
dp_verify_link_cap(struct dc_link * link,struct dc_link_settings * known_limit_link_setting,int * fail_count)1092 bool dp_verify_link_cap(
1093           struct dc_link *link,
1094           struct dc_link_settings *known_limit_link_setting,
1095           int *fail_count)
1096 {
1097           struct dc_link_settings max_link_cap = {0};
1098           struct dc_link_settings cur_link_setting = {0};
1099           struct dc_link_settings *cur = &cur_link_setting;
1100           struct dc_link_settings initial_link_settings = {0};
1101           bool success;
1102           bool skip_link_training;
1103           bool skip_video_pattern;
1104           struct clock_source *dp_cs;
1105           enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_EXTERNAL;
1106           enum link_training_result status;
1107 
1108           if (link->dc->debug.skip_detection_link_training) {
1109                     link->verified_link_cap = *known_limit_link_setting;
1110                     return true;
1111           }
1112 
1113           success = false;
1114           skip_link_training = false;
1115 
1116           max_link_cap = get_max_link_cap(link);
1117 
1118           /* TODO implement override and monitor patch later */
1119 
1120           /* try to train the link from high to low to
1121            * find the physical link capability
1122            */
1123           /* disable PHY done possible by BIOS, will be done by driver itself */
1124           dp_disable_link_phy(link, link->connector_signal);
1125 
1126           dp_cs = link->dc->res_pool->dp_clock_source;
1127 
1128           if (dp_cs)
1129                     dp_cs_id = dp_cs->id;
1130           else {
1131                     /*
1132                      * dp clock source is not initialized for some reason.
1133                      * Should not happen, CLOCK_SOURCE_ID_EXTERNAL will be used
1134                      */
1135                     ASSERT(dp_cs);
1136           }
1137 
1138           /* link training starts with the maximum common settings
1139            * supported by both sink and ASIC.
1140            */
1141           initial_link_settings = get_common_supported_link_settings(
1142                               *known_limit_link_setting,
1143                               max_link_cap);
1144           cur_link_setting = initial_link_settings;
1145           do {
1146                     skip_video_pattern = true;
1147 
1148                     if (cur->link_rate == LINK_RATE_LOW)
1149                               skip_video_pattern = false;
1150 
1151                     dp_enable_link_phy(
1152                                         link,
1153                                         link->connector_signal,
1154                                         dp_cs_id,
1155                                         cur);
1156 
1157 
1158                     if (skip_link_training)
1159                               success = true;
1160                     else {
1161                               status = dc_link_dp_perform_link_training(
1162                                                                       link,
1163                                                                       cur,
1164                                                                       skip_video_pattern);
1165                               if (status == LINK_TRAINING_SUCCESS)
1166                                         success = true;
1167                               else
1168                                         (*fail_count)++;
1169                     }
1170 
1171                     if (success)
1172                               link->verified_link_cap = *cur;
1173 
1174                     /* always disable the link before trying another
1175                      * setting or before returning we'll enable it later
1176                      * based on the actual mode we're driving
1177                      */
1178                     dp_disable_link_phy(link, link->connector_signal);
1179           } while (!success && decide_fallback_link_setting(
1180                               initial_link_settings, cur, status));
1181 
1182           /* Link Training failed for all Link Settings
1183            *  (Lane Count is still unknown)
1184            */
1185           if (!success) {
1186                     /* If all LT fails for all settings,
1187                      * set verified = failed safe (1 lane low)
1188                      */
1189                     link->verified_link_cap.lane_count = LANE_COUNT_ONE;
1190                     link->verified_link_cap.link_rate = LINK_RATE_LOW;
1191 
1192                     link->verified_link_cap.link_spread =
1193                     LINK_SPREAD_DISABLED;
1194           }
1195 
1196 
1197           return success;
1198 }
1199 
get_common_supported_link_settings(struct dc_link_settings link_setting_a,struct dc_link_settings link_setting_b)1200 static struct dc_link_settings get_common_supported_link_settings(
1201                     struct dc_link_settings link_setting_a,
1202                     struct dc_link_settings link_setting_b)
1203 {
1204           struct dc_link_settings link_settings = {0};
1205 
1206           link_settings.lane_count =
1207                     (link_setting_a.lane_count <=
1208                               link_setting_b.lane_count) ?
1209                               link_setting_a.lane_count :
1210                               link_setting_b.lane_count;
1211           link_settings.link_rate =
1212                     (link_setting_a.link_rate <=
1213                               link_setting_b.link_rate) ?
1214                               link_setting_a.link_rate :
1215                               link_setting_b.link_rate;
1216           link_settings.link_spread = LINK_SPREAD_DISABLED;
1217 
1218           /* in DP compliance test, DPR-120 may have
1219            * a random value in its MAX_LINK_BW dpcd field.
1220            * We map it to the maximum supported link rate that
1221            * is smaller than MAX_LINK_BW in this case.
1222            */
1223           if (link_settings.link_rate > LINK_RATE_HIGH3) {
1224                     link_settings.link_rate = LINK_RATE_HIGH3;
1225           } else if (link_settings.link_rate < LINK_RATE_HIGH3
1226                               && link_settings.link_rate > LINK_RATE_HIGH2) {
1227                     link_settings.link_rate = LINK_RATE_HIGH2;
1228           } else if (link_settings.link_rate < LINK_RATE_HIGH2
1229                               && link_settings.link_rate > LINK_RATE_HIGH) {
1230                     link_settings.link_rate = LINK_RATE_HIGH;
1231           } else if (link_settings.link_rate < LINK_RATE_HIGH
1232                               && link_settings.link_rate > LINK_RATE_LOW) {
1233                     link_settings.link_rate = LINK_RATE_LOW;
1234           } else if (link_settings.link_rate < LINK_RATE_LOW) {
1235                     link_settings.link_rate = LINK_RATE_UNKNOWN;
1236           }
1237 
1238           return link_settings;
1239 }
1240 
reached_minimum_lane_count(enum dc_lane_count lane_count)1241 static inline bool reached_minimum_lane_count(enum dc_lane_count lane_count)
1242 {
1243           return lane_count <= LANE_COUNT_ONE;
1244 }
1245 
reached_minimum_link_rate(enum dc_link_rate link_rate)1246 static inline bool reached_minimum_link_rate(enum dc_link_rate link_rate)
1247 {
1248           return link_rate <= LINK_RATE_LOW;
1249 }
1250 
reduce_lane_count(enum dc_lane_count lane_count)1251 static enum dc_lane_count reduce_lane_count(enum dc_lane_count lane_count)
1252 {
1253           switch (lane_count) {
1254           case LANE_COUNT_FOUR:
1255                     return LANE_COUNT_TWO;
1256           case LANE_COUNT_TWO:
1257                     return LANE_COUNT_ONE;
1258           case LANE_COUNT_ONE:
1259                     return LANE_COUNT_UNKNOWN;
1260           default:
1261                     return LANE_COUNT_UNKNOWN;
1262           }
1263 }
1264 
reduce_link_rate(enum dc_link_rate link_rate)1265 static enum dc_link_rate reduce_link_rate(enum dc_link_rate link_rate)
1266 {
1267           switch (link_rate) {
1268           case LINK_RATE_HIGH3:
1269                     return LINK_RATE_HIGH2;
1270           case LINK_RATE_HIGH2:
1271                     return LINK_RATE_HIGH;
1272           case LINK_RATE_HIGH:
1273                     return LINK_RATE_LOW;
1274           case LINK_RATE_LOW:
1275                     return LINK_RATE_UNKNOWN;
1276           default:
1277                     return LINK_RATE_UNKNOWN;
1278           }
1279 }
1280 
increase_lane_count(enum dc_lane_count lane_count)1281 static enum dc_lane_count increase_lane_count(enum dc_lane_count lane_count)
1282 {
1283           switch (lane_count) {
1284           case LANE_COUNT_ONE:
1285                     return LANE_COUNT_TWO;
1286           case LANE_COUNT_TWO:
1287                     return LANE_COUNT_FOUR;
1288           default:
1289                     return LANE_COUNT_UNKNOWN;
1290           }
1291 }
1292 
increase_link_rate(enum dc_link_rate link_rate)1293 static enum dc_link_rate increase_link_rate(enum dc_link_rate link_rate)
1294 {
1295           switch (link_rate) {
1296           case LINK_RATE_LOW:
1297                     return LINK_RATE_HIGH;
1298           case LINK_RATE_HIGH:
1299                     return LINK_RATE_HIGH2;
1300           case LINK_RATE_HIGH2:
1301                     return LINK_RATE_HIGH3;
1302           default:
1303                     return LINK_RATE_UNKNOWN;
1304           }
1305 }
1306 
1307 /*
1308  * function: set link rate and lane count fallback based
1309  * on current link setting and last link training result
1310  * return value:
1311  *                            true - link setting could be set
1312  *                            false - has reached minimum setting
1313  *                                                and no further fallback could be done
1314  */
decide_fallback_link_setting(struct dc_link_settings initial_link_settings,struct dc_link_settings * current_link_setting,enum link_training_result training_result)1315 static bool decide_fallback_link_setting(
1316                     struct dc_link_settings initial_link_settings,
1317                     struct dc_link_settings *current_link_setting,
1318                     enum link_training_result training_result)
1319 {
1320           if (!current_link_setting)
1321                     return false;
1322 
1323           switch (training_result) {
1324           case LINK_TRAINING_CR_FAIL_LANE0:
1325           case LINK_TRAINING_CR_FAIL_LANE1:
1326           case LINK_TRAINING_CR_FAIL_LANE23:
1327           case LINK_TRAINING_LQA_FAIL:
1328           {
1329                     if (!reached_minimum_link_rate
1330                                         (current_link_setting->link_rate)) {
1331                               current_link_setting->link_rate =
1332                                         reduce_link_rate(
1333                                                   current_link_setting->link_rate);
1334                     } else if (!reached_minimum_lane_count
1335                                         (current_link_setting->lane_count)) {
1336                               current_link_setting->link_rate =
1337                                         initial_link_settings.link_rate;
1338                               if (training_result == LINK_TRAINING_CR_FAIL_LANE0)
1339                                         return false;
1340                               else if (training_result == LINK_TRAINING_CR_FAIL_LANE1)
1341                                         current_link_setting->lane_count =
1342                                                             LANE_COUNT_ONE;
1343                               else if (training_result ==
1344                                                   LINK_TRAINING_CR_FAIL_LANE23)
1345                                         current_link_setting->lane_count =
1346                                                             LANE_COUNT_TWO;
1347                               else
1348                                         current_link_setting->lane_count =
1349                                                   reduce_lane_count(
1350                                                   current_link_setting->lane_count);
1351                     } else {
1352                               return false;
1353                     }
1354                     break;
1355           }
1356           case LINK_TRAINING_EQ_FAIL_EQ:
1357           {
1358                     if (!reached_minimum_lane_count
1359                                         (current_link_setting->lane_count)) {
1360                               current_link_setting->lane_count =
1361                                         reduce_lane_count(
1362                                                   current_link_setting->lane_count);
1363                     } else if (!reached_minimum_link_rate
1364                                         (current_link_setting->link_rate)) {
1365                               current_link_setting->link_rate =
1366                                         reduce_link_rate(
1367                                                   current_link_setting->link_rate);
1368                     } else {
1369                               return false;
1370                     }
1371                     break;
1372           }
1373           case LINK_TRAINING_EQ_FAIL_CR:
1374           {
1375                     if (!reached_minimum_link_rate
1376                                         (current_link_setting->link_rate)) {
1377                               current_link_setting->link_rate =
1378                                         reduce_link_rate(
1379                                                   current_link_setting->link_rate);
1380                     } else {
1381                               return false;
1382                     }
1383                     break;
1384           }
1385           default:
1386                     return false;
1387           }
1388           return true;
1389 }
1390 
bandwidth_in_kbps_from_timing(const struct dc_crtc_timing * timing)1391 static uint32_t bandwidth_in_kbps_from_timing(
1392           const struct dc_crtc_timing *timing)
1393 {
1394           uint32_t bits_per_channel = 0;
1395           uint32_t kbps;
1396 
1397           switch (timing->display_color_depth) {
1398           case COLOR_DEPTH_666:
1399                     bits_per_channel = 6;
1400                     break;
1401           case COLOR_DEPTH_888:
1402                     bits_per_channel = 8;
1403                     break;
1404           case COLOR_DEPTH_101010:
1405                     bits_per_channel = 10;
1406                     break;
1407           case COLOR_DEPTH_121212:
1408                     bits_per_channel = 12;
1409                     break;
1410           case COLOR_DEPTH_141414:
1411                     bits_per_channel = 14;
1412                     break;
1413           case COLOR_DEPTH_161616:
1414                     bits_per_channel = 16;
1415                     break;
1416           default:
1417                     break;
1418           }
1419 
1420           ASSERT(bits_per_channel != 0);
1421 
1422           kbps = timing->pix_clk_khz;
1423           kbps *= bits_per_channel;
1424 
1425           if (timing->flags.Y_ONLY != 1) {
1426                     /*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/
1427                     kbps *= 3;
1428                     if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
1429                               kbps /= 2;
1430                     else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
1431                               kbps = kbps * 2 / 3;
1432           }
1433 
1434           return kbps;
1435 
1436 }
1437 
bandwidth_in_kbps_from_link_settings(const struct dc_link_settings * link_setting)1438 static uint32_t bandwidth_in_kbps_from_link_settings(
1439           const struct dc_link_settings *link_setting)
1440 {
1441           uint32_t link_rate_in_kbps = link_setting->link_rate *
1442                     LINK_RATE_REF_FREQ_IN_KHZ;
1443 
1444           uint32_t lane_count  = link_setting->lane_count;
1445           uint32_t kbps = link_rate_in_kbps;
1446 
1447           kbps *= lane_count;
1448           kbps *= 8;   /* 8 bits per byte*/
1449 
1450           return kbps;
1451 
1452 }
1453 
dp_validate_mode_timing(struct dc_link * link,const struct dc_crtc_timing * timing)1454 bool dp_validate_mode_timing(
1455           struct dc_link *link,
1456           const struct dc_crtc_timing *timing)
1457 {
1458           uint32_t req_bw;
1459           uint32_t max_bw;
1460 
1461           const struct dc_link_settings *link_setting;
1462 
1463           /*always DP fail safe mode*/
1464           if (timing->pix_clk_khz == (uint32_t) 25175 &&
1465                     timing->h_addressable == (uint32_t) 640 &&
1466                     timing->v_addressable == (uint32_t) 480)
1467                     return true;
1468 
1469           /* We always use verified link settings */
1470           link_setting = &link->verified_link_cap;
1471 
1472           /* TODO: DYNAMIC_VALIDATION needs to be implemented */
1473           /*if (flags.DYNAMIC_VALIDATION == 1 &&
1474                     link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN)
1475                     link_setting = &link->verified_link_cap;
1476           */
1477 
1478           req_bw = bandwidth_in_kbps_from_timing(timing);
1479           max_bw = bandwidth_in_kbps_from_link_settings(link_setting);
1480 
1481           if (req_bw <= max_bw) {
1482                     /* remember the biggest mode here, during
1483                      * initial link training (to get
1484                      * verified_link_cap), LS sends event about
1485                      * cannot train at reported cap to upper
1486                      * layer and upper layer will re-enumerate modes.
1487                      * this is not necessary if the lower
1488                      * verified_link_cap is enough to drive
1489                      * all the modes */
1490 
1491                     /* TODO: DYNAMIC_VALIDATION needs to be implemented */
1492                     /* if (flags.DYNAMIC_VALIDATION == 1)
1493                               dpsst->max_req_bw_for_verified_linkcap = dal_max(
1494                                         dpsst->max_req_bw_for_verified_linkcap, req_bw); */
1495                     return true;
1496           } else
1497                     return false;
1498 }
1499 
decide_link_settings(struct dc_stream_state * stream,struct dc_link_settings * link_setting)1500 void decide_link_settings(struct dc_stream_state *stream,
1501           struct dc_link_settings *link_setting)
1502 {
1503 
1504           struct dc_link_settings initial_link_setting = {
1505                     LANE_COUNT_ONE, LINK_RATE_LOW, LINK_SPREAD_DISABLED};
1506           struct dc_link_settings current_link_setting =
1507                               initial_link_setting;
1508           struct dc_link *link;
1509           uint32_t req_bw;
1510           uint32_t link_bw;
1511 
1512           req_bw = bandwidth_in_kbps_from_timing(&stream->timing);
1513 
1514           link = stream->sink->link;
1515 
1516           /* if preferred is specified through AMDDP, use it, if it's enough
1517            * to drive the mode
1518            */
1519           if (link->preferred_link_setting.lane_count !=
1520                               LANE_COUNT_UNKNOWN &&
1521                               link->preferred_link_setting.link_rate !=
1522                                                   LINK_RATE_UNKNOWN) {
1523                     *link_setting =  link->preferred_link_setting;
1524                     return;
1525           }
1526 
1527           /* MST doesn't perform link training for now
1528            * TODO: add MST specific link training routine
1529            */
1530           if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
1531                     *link_setting = link->verified_link_cap;
1532                     return;
1533           }
1534 
1535           /* EDP use the link cap setting */
1536           if (stream->sink->sink_signal == SIGNAL_TYPE_EDP) {
1537                     *link_setting = link->verified_link_cap;
1538                     return;
1539           }
1540 
1541           /* search for the minimum link setting that:
1542            * 1. is supported according to the link training result
1543            * 2. could support the b/w requested by the timing
1544            */
1545           while (current_link_setting.link_rate <=
1546                               link->verified_link_cap.link_rate) {
1547                     link_bw = bandwidth_in_kbps_from_link_settings(
1548                                         &current_link_setting);
1549                     if (req_bw <= link_bw) {
1550                               *link_setting = current_link_setting;
1551                               return;
1552                     }
1553 
1554                     if (current_link_setting.lane_count <
1555                                         link->verified_link_cap.lane_count) {
1556                               current_link_setting.lane_count =
1557                                                   increase_lane_count(
1558                                                                       current_link_setting.lane_count);
1559                     } else {
1560                               current_link_setting.link_rate =
1561                                                   increase_link_rate(
1562                                                                       current_link_setting.link_rate);
1563                               current_link_setting.lane_count =
1564                                                   initial_link_setting.lane_count;
1565                     }
1566           }
1567 
1568           BREAK_TO_DEBUGGER();
1569           ASSERT(link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN);
1570 
1571           *link_setting = link->verified_link_cap;
1572 }
1573 
1574 /*************************Short Pulse IRQ***************************/
1575 
hpd_rx_irq_check_link_loss_status(struct dc_link * link,union hpd_irq_data * hpd_irq_dpcd_data)1576 static bool hpd_rx_irq_check_link_loss_status(
1577           struct dc_link *link,
1578           union hpd_irq_data *hpd_irq_dpcd_data)
1579 {
1580           uint8_t irq_reg_rx_power_state = 0;
1581           enum dc_status dpcd_result = DC_ERROR_UNEXPECTED;
1582           union lane_status lane_status;
1583           uint32_t lane;
1584           bool sink_status_changed;
1585           bool return_code;
1586 
1587           sink_status_changed = false;
1588           return_code = false;
1589 
1590           if (link->cur_link_settings.lane_count == 0)
1591                     return return_code;
1592 
1593           /*1. Check that Link Status changed, before re-training.*/
1594 
1595           /*parse lane status*/
1596           for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) {
1597                     /* check status of lanes 0,1
1598                      * changed DpcdAddress_Lane01Status (0x202)
1599                      */
1600                     lane_status.raw = get_nibble_at_index(
1601                               &hpd_irq_dpcd_data->bytes.lane01_status.raw,
1602                               lane);
1603 
1604                     if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
1605                               !lane_status.bits.CR_DONE_0 ||
1606                               !lane_status.bits.SYMBOL_LOCKED_0) {
1607                               /* if one of the channel equalization, clock
1608                                * recovery or symbol lock is dropped
1609                                * consider it as (link has been
1610                                * dropped) dp sink status has changed
1611                                */
1612                               sink_status_changed = true;
1613                               break;
1614                     }
1615           }
1616 
1617           /* Check interlane align.*/
1618           if (sink_status_changed ||
1619                     !hpd_irq_dpcd_data->bytes.lane_status_updated.bits.INTERLANE_ALIGN_DONE) {
1620 
1621                     DC_LOG_HW_HPD_IRQ("%s: Link Status changed.\n", __func__);
1622 
1623                     return_code = true;
1624 
1625                     /*2. Check that we can handle interrupt: Not in FS DOS,
1626                      *  Not in "Display Timeout" state, Link is trained.
1627                      */
1628                     dpcd_result = core_link_read_dpcd(link,
1629                               DP_SET_POWER,
1630                               &irq_reg_rx_power_state,
1631                               sizeof(irq_reg_rx_power_state));
1632 
1633                     if (dpcd_result != DC_OK) {
1634                               DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain power state.\n",
1635                                         __func__);
1636                     } else {
1637                               if (irq_reg_rx_power_state != DP_SET_POWER_D0)
1638                                         return_code = false;
1639                     }
1640           }
1641 
1642           return return_code;
1643 }
1644 
read_hpd_rx_irq_data(struct dc_link * link,union hpd_irq_data * irq_data)1645 static enum dc_status read_hpd_rx_irq_data(
1646           struct dc_link *link,
1647           union hpd_irq_data *irq_data)
1648 {
1649           static enum dc_status retval;
1650 
1651           /* The HW reads 16 bytes from 200h on HPD,
1652            * but if we get an AUX_DEFER, the HW cannot retry
1653            * and this causes the CTS tests 4.3.2.1 - 3.2.4 to
1654            * fail, so we now explicitly read 6 bytes which is
1655            * the req from the above mentioned test cases.
1656            *
1657            * For DP 1.4 we need to read those from 2002h range.
1658            */
1659           if (link->dpcd_caps.dpcd_rev.raw < DPCD_REV_14)
1660                     retval = core_link_read_dpcd(
1661                               link,
1662                               DP_SINK_COUNT,
1663                               irq_data->raw,
1664                               sizeof(union hpd_irq_data));
1665           else {
1666                     /* Read 14 bytes in a single read and then copy only the required fields.
1667                      * This is more efficient than doing it in two separate AUX reads. */
1668 
1669                     uint8_t tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI + 1];
1670 
1671                     retval = core_link_read_dpcd(
1672                               link,
1673                               DP_SINK_COUNT_ESI,
1674                               tmp,
1675                               sizeof(tmp));
1676 
1677                     if (retval != DC_OK)
1678                               return retval;
1679 
1680                     irq_data->bytes.sink_cnt.raw = tmp[DP_SINK_COUNT_ESI - DP_SINK_COUNT_ESI];
1681                     irq_data->bytes.device_service_irq.raw = tmp[DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0 - DP_SINK_COUNT_ESI];
1682                     irq_data->bytes.lane01_status.raw = tmp[DP_LANE0_1_STATUS_ESI - DP_SINK_COUNT_ESI];
1683                     irq_data->bytes.lane23_status.raw = tmp[DP_LANE2_3_STATUS_ESI - DP_SINK_COUNT_ESI];
1684                     irq_data->bytes.lane_status_updated.raw = tmp[DP_LANE_ALIGN_STATUS_UPDATED_ESI - DP_SINK_COUNT_ESI];
1685                     irq_data->bytes.sink_status.raw = tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI];
1686           }
1687 
1688           return retval;
1689 }
1690 
allow_hpd_rx_irq(const struct dc_link * link)1691 static bool allow_hpd_rx_irq(const struct dc_link *link)
1692 {
1693           /*
1694            * Don't handle RX IRQ unless one of following is met:
1695            * 1) The link is established (cur_link_settings != unknown)
1696            * 2) We kicked off MST detection
1697            * 3) We know we're dealing with an active dongle
1698            */
1699 
1700           if ((link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) ||
1701                     (link->type == dc_connection_mst_branch) ||
1702                     is_dp_active_dongle(link))
1703                     return true;
1704 
1705           return false;
1706 }
1707 
handle_hpd_irq_psr_sink(const struct dc_link * link)1708 static bool handle_hpd_irq_psr_sink(const struct dc_link *link)
1709 {
1710           union dpcd_psr_configuration psr_configuration;
1711 
1712           if (!link->psr_enabled)
1713                     return false;
1714 
1715           dm_helpers_dp_read_dpcd(
1716                     link->ctx,
1717                     link,
1718                     368,/*DpcdAddress_PSR_Enable_Cfg*/
1719                     &psr_configuration.raw,
1720                     sizeof(psr_configuration.raw));
1721 
1722 
1723           if (psr_configuration.bits.ENABLE) {
1724                     unsigned char dpcdbuf[3] = {0};
1725                     union psr_error_status psr_error_status;
1726                     union psr_sink_psr_status psr_sink_psr_status;
1727 
1728                     dm_helpers_dp_read_dpcd(
1729                               link->ctx,
1730                               link,
1731                               0x2006, /*DpcdAddress_PSR_Error_Status*/
1732                               (unsigned char *) dpcdbuf,
1733                               sizeof(dpcdbuf));
1734 
1735                     /*DPCD 2006h   ERROR STATUS*/
1736                     psr_error_status.raw = dpcdbuf[0];
1737                     /*DPCD 2008h   SINK PANEL SELF REFRESH STATUS*/
1738                     psr_sink_psr_status.raw = dpcdbuf[2];
1739 
1740                     if (psr_error_status.bits.LINK_CRC_ERROR ||
1741                                         psr_error_status.bits.RFB_STORAGE_ERROR) {
1742                               /* Acknowledge and clear error bits */
1743                               dm_helpers_dp_write_dpcd(
1744                                         link->ctx,
1745                                         link,
1746                                         8198,/*DpcdAddress_PSR_Error_Status*/
1747                                         &psr_error_status.raw,
1748                                         sizeof(psr_error_status.raw));
1749 
1750                               /* PSR error, disable and re-enable PSR */
1751                               dc_link_set_psr_enable(link, false, true);
1752                               dc_link_set_psr_enable(link, true, true);
1753 
1754                               return true;
1755                     } else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS ==
1756                                         PSR_SINK_STATE_ACTIVE_DISPLAY_FROM_SINK_RFB){
1757                               /* No error is detect, PSR is active.
1758                                * We should return with IRQ_HPD handled without
1759                                * checking for loss of sync since PSR would have
1760                                * powered down main link.
1761                                */
1762                               return true;
1763                     }
1764           }
1765           return false;
1766 }
1767 
dp_test_send_link_training(struct dc_link * link)1768 static void dp_test_send_link_training(struct dc_link *link)
1769 {
1770           struct dc_link_settings link_settings = {0};
1771 
1772           core_link_read_dpcd(
1773                               link,
1774                               DP_TEST_LANE_COUNT,
1775                               (unsigned char *)(&link_settings.lane_count),
1776                               1);
1777           core_link_read_dpcd(
1778                               link,
1779                               DP_TEST_LINK_RATE,
1780                               (unsigned char *)(&link_settings.link_rate),
1781                               1);
1782 
1783           /* Set preferred link settings */
1784           link->verified_link_cap.lane_count = link_settings.lane_count;
1785           link->verified_link_cap.link_rate = link_settings.link_rate;
1786 
1787           dp_retrain_link_dp_test(link, &link_settings, false);
1788 }
1789 
1790 /* TODO Raven hbr2 compliance eye output is unstable
1791  * (toggling on and off) with debugger break
1792  * This caueses intermittent PHY automation failure
1793  * Need to look into the root cause */
dp_test_send_phy_test_pattern(struct dc_link * link)1794 static void dp_test_send_phy_test_pattern(struct dc_link *link)
1795 {
1796           union phy_test_pattern dpcd_test_pattern;
1797           union lane_adjust dpcd_lane_adjustment[2];
1798           unsigned char dpcd_post_cursor_2_adjustment = 0;
1799           unsigned char test_80_bit_pattern[
1800                               (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 -
1801                               DP_TEST_80BIT_CUSTOM_PATTERN_7_0)+1] = {0};
1802           enum dp_test_pattern test_pattern;
1803           struct dc_link_training_settings link_settings;
1804           union lane_adjust dpcd_lane_adjust;
1805           unsigned int lane;
1806           struct link_training_settings link_training_settings;
1807           int i = 0;
1808 
1809           dpcd_test_pattern.raw = 0;
1810           memset(dpcd_lane_adjustment, 0, sizeof(dpcd_lane_adjustment));
1811           memset(&link_settings, 0, sizeof(link_settings));
1812 
1813           /* get phy test pattern and pattern parameters from DP receiver */
1814           core_link_read_dpcd(
1815                               link,
1816                               DP_TEST_PHY_PATTERN,
1817                               &dpcd_test_pattern.raw,
1818                               sizeof(dpcd_test_pattern));
1819           core_link_read_dpcd(
1820                               link,
1821                               DP_ADJUST_REQUEST_LANE0_1,
1822                               &dpcd_lane_adjustment[0].raw,
1823                               sizeof(dpcd_lane_adjustment));
1824 
1825           /*get post cursor 2 parameters
1826            * For DP 1.1a or eariler, this DPCD register's value is 0
1827            * For DP 1.2 or later:
1828            * Bits 1:0 = POST_CURSOR2_LANE0; Bits 3:2 = POST_CURSOR2_LANE1
1829            * Bits 5:4 = POST_CURSOR2_LANE2; Bits 7:6 = POST_CURSOR2_LANE3
1830            */
1831           core_link_read_dpcd(
1832                               link,
1833                               DP_ADJUST_REQUEST_POST_CURSOR2,
1834                               &dpcd_post_cursor_2_adjustment,
1835                               sizeof(dpcd_post_cursor_2_adjustment));
1836 
1837           /* translate request */
1838           switch (dpcd_test_pattern.bits.PATTERN) {
1839           case PHY_TEST_PATTERN_D10_2:
1840                     test_pattern = DP_TEST_PATTERN_D102;
1841                     break;
1842           case PHY_TEST_PATTERN_SYMBOL_ERROR:
1843                     test_pattern = DP_TEST_PATTERN_SYMBOL_ERROR;
1844                     break;
1845           case PHY_TEST_PATTERN_PRBS7:
1846                     test_pattern = DP_TEST_PATTERN_PRBS7;
1847                     break;
1848           case PHY_TEST_PATTERN_80BIT_CUSTOM:
1849                     test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM;
1850                     break;
1851           case PHY_TEST_PATTERN_CP2520_1:
1852                     /* CP2520 pattern is unstable, temporarily use TPS4 instead */
1853                     test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
1854                                         DP_TEST_PATTERN_TRAINING_PATTERN4 :
1855                                         DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
1856                     break;
1857           case PHY_TEST_PATTERN_CP2520_2:
1858                     /* CP2520 pattern is unstable, temporarily use TPS4 instead */
1859                     test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
1860                                         DP_TEST_PATTERN_TRAINING_PATTERN4 :
1861                                         DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
1862                     break;
1863           case PHY_TEST_PATTERN_CP2520_3:
1864                     test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
1865                     break;
1866           default:
1867                     test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
1868           break;
1869           }
1870 
1871           if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM)
1872                     core_link_read_dpcd(
1873                                         link,
1874                                         DP_TEST_80BIT_CUSTOM_PATTERN_7_0,
1875                                         test_80_bit_pattern,
1876                                         sizeof(test_80_bit_pattern));
1877 
1878           /* prepare link training settings */
1879           link_settings.link = link->cur_link_settings;
1880 
1881           for (lane = 0; lane <
1882                     (unsigned int)(link->cur_link_settings.lane_count);
1883                     lane++) {
1884                     dpcd_lane_adjust.raw =
1885                               get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane);
1886                     link_settings.lane_settings[lane].VOLTAGE_SWING =
1887                               (enum dc_voltage_swing)
1888                               (dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE);
1889                     link_settings.lane_settings[lane].PRE_EMPHASIS =
1890                               (enum dc_pre_emphasis)
1891                               (dpcd_lane_adjust.bits.PRE_EMPHASIS_LANE);
1892                     link_settings.lane_settings[lane].POST_CURSOR2 =
1893                               (enum dc_post_cursor2)
1894                               ((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03);
1895           }
1896 
1897           for (i = 0; i < 4; i++)
1898                     link_training_settings.lane_settings[i] =
1899                                         link_settings.lane_settings[i];
1900           link_training_settings.link_settings = link_settings.link;
1901           link_training_settings.allow_invalid_msa_timing_param = false;
1902           /*Usage: Measure DP physical lane signal
1903            * by DP SI test equipment automatically.
1904            * PHY test pattern request is generated by equipment via HPD interrupt.
1905            * HPD needs to be active all the time. HPD should be active
1906            * all the time. Do not touch it.
1907            * forward request to DS
1908            */
1909           dc_link_dp_set_test_pattern(
1910                     link,
1911                     test_pattern,
1912                     &link_training_settings,
1913                     test_80_bit_pattern,
1914                     (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 -
1915                     DP_TEST_80BIT_CUSTOM_PATTERN_7_0)+1);
1916 }
1917 
dp_test_send_link_test_pattern(struct dc_link * link)1918 static void dp_test_send_link_test_pattern(struct dc_link *link)
1919 {
1920           union link_test_pattern dpcd_test_pattern;
1921           union test_misc dpcd_test_params;
1922           enum dp_test_pattern test_pattern;
1923 
1924           memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern));
1925           memset(&dpcd_test_params, 0, sizeof(dpcd_test_params));
1926 
1927           /* get link test pattern and pattern parameters */
1928           core_link_read_dpcd(
1929                               link,
1930                               DP_TEST_PATTERN,
1931                               &dpcd_test_pattern.raw,
1932                               sizeof(dpcd_test_pattern));
1933           core_link_read_dpcd(
1934                               link,
1935                               DP_TEST_MISC0,
1936                               &dpcd_test_params.raw,
1937                               sizeof(dpcd_test_params));
1938 
1939           switch (dpcd_test_pattern.bits.PATTERN) {
1940           case LINK_TEST_PATTERN_COLOR_RAMP:
1941                     test_pattern = DP_TEST_PATTERN_COLOR_RAMP;
1942           break;
1943           case LINK_TEST_PATTERN_VERTICAL_BARS:
1944                     test_pattern = DP_TEST_PATTERN_VERTICAL_BARS;
1945           break; /* black and white */
1946           case LINK_TEST_PATTERN_COLOR_SQUARES:
1947                     test_pattern = (dpcd_test_params.bits.DYN_RANGE ==
1948                                         TEST_DYN_RANGE_VESA ?
1949                                         DP_TEST_PATTERN_COLOR_SQUARES :
1950                                         DP_TEST_PATTERN_COLOR_SQUARES_CEA);
1951           break;
1952           default:
1953                     test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
1954           break;
1955           }
1956 
1957           dc_link_dp_set_test_pattern(
1958                               link,
1959                               test_pattern,
1960                               NULL,
1961                               NULL,
1962                               0);
1963 }
1964 
handle_automated_test(struct dc_link * link)1965 static void handle_automated_test(struct dc_link *link)
1966 {
1967           union test_request test_request;
1968           union test_response test_response;
1969 
1970           memset(&test_request, 0, sizeof(test_request));
1971           memset(&test_response, 0, sizeof(test_response));
1972 
1973           core_link_read_dpcd(
1974                     link,
1975                     DP_TEST_REQUEST,
1976                     &test_request.raw,
1977                     sizeof(union test_request));
1978           if (test_request.bits.LINK_TRAINING) {
1979                     /* ACK first to let DP RX test box monitor LT sequence */
1980                     test_response.bits.ACK = 1;
1981                     core_link_write_dpcd(
1982                               link,
1983                               DP_TEST_RESPONSE,
1984                               &test_response.raw,
1985                               sizeof(test_response));
1986                     dp_test_send_link_training(link);
1987                     /* no acknowledge request is needed again */
1988                     test_response.bits.ACK = 0;
1989           }
1990           if (test_request.bits.LINK_TEST_PATTRN) {
1991                     dp_test_send_link_test_pattern(link);
1992                     test_response.bits.ACK = 1;
1993           }
1994           if (test_request.bits.PHY_TEST_PATTERN) {
1995                     dp_test_send_phy_test_pattern(link);
1996                     test_response.bits.ACK = 1;
1997           }
1998           if (!test_request.raw)
1999                     /* no requests, revert all test signals
2000                      * TODO: revert all test signals
2001                      */
2002                     test_response.bits.ACK = 1;
2003           /* send request acknowledgment */
2004           if (test_response.bits.ACK)
2005                     core_link_write_dpcd(
2006                               link,
2007                               DP_TEST_RESPONSE,
2008                               &test_response.raw,
2009                               sizeof(test_response));
2010 }
2011 
dc_link_handle_hpd_rx_irq(struct dc_link * link,union hpd_irq_data * out_hpd_irq_dpcd_data,bool * out_link_loss)2012 bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd_irq_dpcd_data, bool *out_link_loss)
2013 {
2014           union hpd_irq_data hpd_irq_dpcd_data = { { { {0} } } };
2015           union device_service_irq device_service_clear = { { 0 } };
2016           enum dc_status result;
2017 
2018           bool status = false;
2019 
2020           if (out_link_loss)
2021                     *out_link_loss = false;
2022           /* For use cases related to down stream connection status change,
2023            * PSR and device auto test, refer to function handle_sst_hpd_irq
2024            * in DAL2.1*/
2025 
2026           DC_LOG_HW_HPD_IRQ("%s: Got short pulse HPD on link %d\n",
2027                     __func__, link->link_index);
2028 
2029 
2030            /* All the "handle_hpd_irq_xxx()" methods
2031                      * should be called only after
2032                      * dal_dpsst_ls_read_hpd_irq_data
2033                      * Order of calls is important too
2034                      */
2035           result = read_hpd_rx_irq_data(link, &hpd_irq_dpcd_data);
2036           if (out_hpd_irq_dpcd_data)
2037                     *out_hpd_irq_dpcd_data = hpd_irq_dpcd_data;
2038 
2039           if (result != DC_OK) {
2040                     DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain irq data\n",
2041                               __func__);
2042                     return false;
2043           }
2044 
2045           if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.AUTOMATED_TEST) {
2046                     device_service_clear.bits.AUTOMATED_TEST = 1;
2047                     core_link_write_dpcd(
2048                               link,
2049                               DP_DEVICE_SERVICE_IRQ_VECTOR,
2050                               &device_service_clear.raw,
2051                               sizeof(device_service_clear.raw));
2052                     device_service_clear.raw = 0;
2053                     handle_automated_test(link);
2054                     return false;
2055           }
2056 
2057           if (!allow_hpd_rx_irq(link)) {
2058                     DC_LOG_HW_HPD_IRQ("%s: skipping HPD handling on %d\n",
2059                               __func__, link->link_index);
2060                     return false;
2061           }
2062 
2063           if (handle_hpd_irq_psr_sink(link))
2064                     /* PSR-related error was detected and handled */
2065                     return true;
2066 
2067           /* If PSR-related error handled, Main link may be off,
2068            * so do not handle as a normal sink status change interrupt.
2069            */
2070 
2071           if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY)
2072                     return true;
2073 
2074           /* check if we have MST msg and return since we poll for it */
2075           if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY)
2076                     return false;
2077 
2078           /* For now we only handle 'Downstream port status' case.
2079            * If we got sink count changed it means
2080            * Downstream port status changed,
2081            * then DM should call DC to do the detection. */
2082           if (hpd_rx_irq_check_link_loss_status(
2083                     link,
2084                     &hpd_irq_dpcd_data)) {
2085                     /* Connectivity log: link loss */
2086                     CONN_DATA_LINK_LOSS(link,
2087                                                   hpd_irq_dpcd_data.raw,
2088                                                   sizeof(hpd_irq_dpcd_data),
2089                                                   "Status: ");
2090 
2091                     perform_link_training_with_retries(link,
2092                               &link->cur_link_settings,
2093                               true, LINK_TRAINING_ATTEMPTS);
2094 
2095                     status = false;
2096                     if (out_link_loss)
2097                               *out_link_loss = true;
2098           }
2099 
2100           if (link->type == dc_connection_active_dongle &&
2101                     hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT
2102                               != link->dpcd_sink_count)
2103                     status = true;
2104 
2105           /* reasons for HPD RX:
2106            * 1. Link Loss - ie Re-train the Link
2107            * 2. MST sideband message
2108            * 3. Automated Test - ie. Internal Commit
2109            * 4. CP (copy protection) - (not interesting for DM???)
2110            * 5. DRR
2111            * 6. Downstream Port status changed
2112            * -ie. Detect - this the only one
2113            * which is interesting for DM because
2114            * it must call dc_link_detect.
2115            */
2116           return status;
2117 }
2118 
2119 /*query dpcd for version and mst cap addresses*/
is_mst_supported(struct dc_link * link)2120 bool is_mst_supported(struct dc_link *link)
2121 {
2122           bool mst          = false;
2123           enum dc_status st = DC_OK;
2124           union dpcd_rev rev;
2125           union mstm_cap cap;
2126 
2127           rev.raw  = 0;
2128           cap.raw  = 0;
2129 
2130           st = core_link_read_dpcd(link, DP_DPCD_REV, &rev.raw,
2131                               sizeof(rev));
2132 
2133           if (st == DC_OK && rev.raw >= DPCD_REV_12) {
2134 
2135                     st = core_link_read_dpcd(link, DP_MSTM_CAP,
2136                                         &cap.raw, sizeof(cap));
2137                     if (st == DC_OK && cap.bits.MST_CAP == 1)
2138                               mst = true;
2139           }
2140           return mst;
2141 
2142 }
2143 
is_dp_active_dongle(const struct dc_link * link)2144 bool is_dp_active_dongle(const struct dc_link *link)
2145 {
2146           enum display_dongle_type dongle_type = link->dpcd_caps.dongle_type;
2147 
2148           return (dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) ||
2149                               (dongle_type == DISPLAY_DONGLE_DP_DVI_CONVERTER) ||
2150                               (dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER);
2151 }
2152 
translate_dpcd_max_bpc(enum dpcd_downstream_port_max_bpc bpc)2153 static int translate_dpcd_max_bpc(enum dpcd_downstream_port_max_bpc bpc)
2154 {
2155           switch (bpc) {
2156           case DOWN_STREAM_MAX_8BPC:
2157                     return 8;
2158           case DOWN_STREAM_MAX_10BPC:
2159                     return 10;
2160           case DOWN_STREAM_MAX_12BPC:
2161                     return 12;
2162           case DOWN_STREAM_MAX_16BPC:
2163                     return 16;
2164           default:
2165                     break;
2166           }
2167 
2168           return -1;
2169 }
2170 
get_active_converter_info(uint8_t data,struct dc_link * link)2171 static void get_active_converter_info(
2172           uint8_t data, struct dc_link *link)
2173 {
2174           union dp_downstream_port_present ds_port = { .byte = data };
2175           memset(&link->dpcd_caps.dongle_caps, 0, sizeof(link->dpcd_caps.dongle_caps));
2176 
2177           /* decode converter info*/
2178           if (!ds_port.fields.PORT_PRESENT) {
2179                     link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
2180                     ddc_service_set_dongle_type(link->ddc,
2181                                         link->dpcd_caps.dongle_type);
2182                     return;
2183           }
2184 
2185           switch (ds_port.fields.PORT_TYPE) {
2186           case DOWNSTREAM_VGA:
2187                     link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_VGA_CONVERTER;
2188                     break;
2189           case DOWNSTREAM_DVI_HDMI:
2190                     /* At this point we don't know is it DVI or HDMI,
2191                      * assume DVI.*/
2192                     link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_DVI_CONVERTER;
2193                     break;
2194           default:
2195                     link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
2196                     break;
2197           }
2198 
2199           if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_11) {
2200                     uint8_t det_caps[4];
2201                     union dwnstream_port_caps_byte0 *port_caps =
2202                               (union dwnstream_port_caps_byte0 *)det_caps;
2203                     core_link_read_dpcd(link, DP_DOWNSTREAM_PORT_0,
2204                                         det_caps, sizeof(det_caps));
2205 
2206                     switch (port_caps->bits.DWN_STRM_PORTX_TYPE) {
2207                     case DOWN_STREAM_DETAILED_VGA:
2208                               link->dpcd_caps.dongle_type =
2209                                         DISPLAY_DONGLE_DP_VGA_CONVERTER;
2210                               break;
2211                     case DOWN_STREAM_DETAILED_DVI:
2212                               link->dpcd_caps.dongle_type =
2213                                         DISPLAY_DONGLE_DP_DVI_CONVERTER;
2214                               break;
2215                     case DOWN_STREAM_DETAILED_HDMI:
2216                               link->dpcd_caps.dongle_type =
2217                                         DISPLAY_DONGLE_DP_HDMI_CONVERTER;
2218 
2219                               link->dpcd_caps.dongle_caps.dongle_type = link->dpcd_caps.dongle_type;
2220                               if (ds_port.fields.DETAILED_CAPS) {
2221 
2222                                         union dwnstream_port_caps_byte3_hdmi
2223                                                   hdmi_caps = {.raw = det_caps[3] };
2224                                         union dwnstream_port_caps_byte2
2225                                                   hdmi_color_caps = {.raw = det_caps[2] };
2226                                         link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk =
2227                                                   det_caps[1] * 25000;
2228 
2229                                         link->dpcd_caps.dongle_caps.is_dp_hdmi_s3d_converter =
2230                                                   hdmi_caps.bits.FRAME_SEQ_TO_FRAME_PACK;
2231                                         link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_pass_through =
2232                                                   hdmi_caps.bits.YCrCr422_PASS_THROUGH;
2233                                         link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_pass_through =
2234                                                   hdmi_caps.bits.YCrCr420_PASS_THROUGH;
2235                                         link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_converter =
2236                                                   hdmi_caps.bits.YCrCr422_CONVERSION;
2237                                         link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_converter =
2238                                                   hdmi_caps.bits.YCrCr420_CONVERSION;
2239 
2240                                         link->dpcd_caps.dongle_caps.dp_hdmi_max_bpc =
2241                                                   translate_dpcd_max_bpc(
2242                                                             hdmi_color_caps.bits.MAX_BITS_PER_COLOR_COMPONENT);
2243 
2244                                         if (link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk != 0)
2245                                                   link->dpcd_caps.dongle_caps.extendedCapValid = true;
2246                               }
2247 
2248                               break;
2249                     }
2250           }
2251 
2252           ddc_service_set_dongle_type(link->ddc, link->dpcd_caps.dongle_type);
2253 
2254           {
2255                     struct dp_device_vendor_id dp_id;
2256 
2257                     /* read IEEE branch device id */
2258                     core_link_read_dpcd(
2259                               link,
2260                               DP_BRANCH_OUI,
2261                               (uint8_t *)&dp_id,
2262                               sizeof(dp_id));
2263 
2264                     link->dpcd_caps.branch_dev_id =
2265                               (dp_id.ieee_oui[0] << 16) +
2266                               (dp_id.ieee_oui[1] << 8) +
2267                               dp_id.ieee_oui[2];
2268 
2269                     memmove(
2270                               link->dpcd_caps.branch_dev_name,
2271                               dp_id.ieee_device_id,
2272                               sizeof(dp_id.ieee_device_id));
2273           }
2274 
2275           {
2276                     struct dp_sink_hw_fw_revision dp_hw_fw_revision;
2277 
2278                     core_link_read_dpcd(
2279                               link,
2280                               DP_BRANCH_REVISION_START,
2281                               (uint8_t *)&dp_hw_fw_revision,
2282                               sizeof(dp_hw_fw_revision));
2283 
2284                     link->dpcd_caps.branch_hw_revision =
2285                               dp_hw_fw_revision.ieee_hw_rev;
2286 
2287                     memmove(
2288                               link->dpcd_caps.branch_fw_revision,
2289                               dp_hw_fw_revision.ieee_fw_rev,
2290                               sizeof(dp_hw_fw_revision.ieee_fw_rev));
2291           }
2292 }
2293 
dp_wa_power_up_0010FA(struct dc_link * link,uint8_t * dpcd_data,int length)2294 static void dp_wa_power_up_0010FA(struct dc_link *link, uint8_t *dpcd_data,
2295                     int length)
2296 {
2297           int retry = 0;
2298           union dp_downstream_port_present ds_port = { 0 };
2299 
2300           if (!link->dpcd_caps.dpcd_rev.raw) {
2301                     do {
2302                               dp_receiver_power_ctrl(link, true);
2303                               core_link_read_dpcd(link, DP_DPCD_REV,
2304                                                                       dpcd_data, length);
2305                               link->dpcd_caps.dpcd_rev.raw = dpcd_data[
2306                                         DP_DPCD_REV -
2307                                         DP_DPCD_REV];
2308                     } while (retry++ < 4 && !link->dpcd_caps.dpcd_rev.raw);
2309           }
2310 
2311           ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT -
2312                                          DP_DPCD_REV];
2313 
2314           if (link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) {
2315                     switch (link->dpcd_caps.branch_dev_id) {
2316                     /* Some active dongles (DP-VGA, DP-DLDVI converters) power down
2317                      * all internal circuits including AUX communication preventing
2318                      * reading DPCD table and EDID (spec violation).
2319                      * Encoder will skip DP RX power down on disable_output to
2320                      * keep receiver powered all the time.*/
2321                     case DP_BRANCH_DEVICE_ID_1:
2322                     case DP_BRANCH_DEVICE_ID_4:
2323                               link->wa_flags.dp_keep_receiver_powered = true;
2324                               break;
2325 
2326                     /* TODO: May need work around for other dongles. */
2327                     default:
2328                               link->wa_flags.dp_keep_receiver_powered = false;
2329                               break;
2330                     }
2331           } else
2332                     link->wa_flags.dp_keep_receiver_powered = false;
2333 }
2334 
retrieve_link_cap(struct dc_link * link)2335 static bool retrieve_link_cap(struct dc_link *link)
2336 {
2337           uint8_t dpcd_data[DP_ADAPTER_CAP - DP_DPCD_REV + 1];
2338 
2339           struct dp_device_vendor_id sink_id;
2340           union down_stream_port_count down_strm_port_count;
2341           union edp_configuration_cap edp_config_cap;
2342           union dp_downstream_port_present ds_port = { 0 };
2343           enum dc_status status = DC_ERROR_UNEXPECTED;
2344           uint32_t read_dpcd_retry_cnt = 3;
2345           int i;
2346           struct dp_sink_hw_fw_revision dp_hw_fw_revision;
2347 
2348           memset(dpcd_data, '\0', sizeof(dpcd_data));
2349           memset(&down_strm_port_count,
2350                     '\0', sizeof(union down_stream_port_count));
2351           memset(&edp_config_cap, '\0',
2352                     sizeof(union edp_configuration_cap));
2353 
2354           for (i = 0; i < read_dpcd_retry_cnt; i++) {
2355                     status = core_link_read_dpcd(
2356                                         link,
2357                                         DP_DPCD_REV,
2358                                         dpcd_data,
2359                                         sizeof(dpcd_data));
2360                     if (status == DC_OK)
2361                               break;
2362           }
2363 
2364           if (status != DC_OK) {
2365                     dm_error("%s: Read dpcd data failed.\n", __func__);
2366                     return false;
2367           }
2368 
2369           {
2370                     union training_aux_rd_interval aux_rd_interval;
2371 
2372                     aux_rd_interval.raw =
2373                               dpcd_data[DP_TRAINING_AUX_RD_INTERVAL];
2374 
2375                     if (aux_rd_interval.bits.EXT_RECIEVER_CAP_FIELD_PRESENT == 1) {
2376                               core_link_read_dpcd(
2377                                         link,
2378                                         DP_DP13_DPCD_REV,
2379                                         dpcd_data,
2380                                         sizeof(dpcd_data));
2381                     }
2382           }
2383 
2384           link->dpcd_caps.dpcd_rev.raw =
2385                     dpcd_data[DP_DPCD_REV - DP_DPCD_REV];
2386 
2387           ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT -
2388                                          DP_DPCD_REV];
2389 
2390           get_active_converter_info(ds_port.byte, link);
2391 
2392           dp_wa_power_up_0010FA(link, dpcd_data, sizeof(dpcd_data));
2393 
2394           link->dpcd_caps.allow_invalid_MSA_timing_param =
2395                     down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM;
2396 
2397           link->dpcd_caps.max_ln_count.raw = dpcd_data[
2398                     DP_MAX_LANE_COUNT - DP_DPCD_REV];
2399 
2400           link->dpcd_caps.max_down_spread.raw = dpcd_data[
2401                     DP_MAX_DOWNSPREAD - DP_DPCD_REV];
2402 
2403           link->reported_link_cap.lane_count =
2404                     link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT;
2405           link->reported_link_cap.link_rate = dpcd_data[
2406                     DP_MAX_LINK_RATE - DP_DPCD_REV];
2407           link->reported_link_cap.link_spread =
2408                     link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ?
2409                     LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED;
2410 
2411           edp_config_cap.raw = dpcd_data[
2412                     DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV];
2413           link->dpcd_caps.panel_mode_edp =
2414                     edp_config_cap.bits.ALT_SCRAMBLER_RESET;
2415           link->dpcd_caps.dpcd_display_control_capable =
2416                     edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE;
2417 
2418           link->test_pattern_enabled = false;
2419           link->compliance_test_state.raw = 0;
2420 
2421           /* read sink count */
2422           core_link_read_dpcd(link,
2423                               DP_SINK_COUNT,
2424                               &link->dpcd_caps.sink_count.raw,
2425                               sizeof(link->dpcd_caps.sink_count.raw));
2426 
2427           /* read sink ieee oui */
2428           core_link_read_dpcd(link,
2429                               DP_SINK_OUI,
2430                               (uint8_t *)(&sink_id),
2431                               sizeof(sink_id));
2432 
2433           link->dpcd_caps.sink_dev_id =
2434                               (sink_id.ieee_oui[0] << 16) +
2435                               (sink_id.ieee_oui[1] << 8) +
2436                               (sink_id.ieee_oui[2]);
2437 
2438           memmove(
2439                     link->dpcd_caps.sink_dev_id_str,
2440                     sink_id.ieee_device_id,
2441                     sizeof(sink_id.ieee_device_id));
2442 
2443           /* Quirk Apple MBP 2017 15" Retina panel: Wrong DP_MAX_LINK_RATE */
2444           {
2445                     uint8_t str_mbp_2017[] = { 101, 68, 21, 101, 98, 97 };
2446 
2447                     if ((link->dpcd_caps.sink_dev_id == 0x0010fa) &&
2448                         !memcmp(link->dpcd_caps.sink_dev_id_str, str_mbp_2017,
2449                                   sizeof(str_mbp_2017))) {
2450                               link->reported_link_cap.link_rate = 0x0c;
2451                     }
2452           }
2453 
2454           core_link_read_dpcd(
2455                     link,
2456                     DP_SINK_HW_REVISION_START,
2457                     (uint8_t *)&dp_hw_fw_revision,
2458                     sizeof(dp_hw_fw_revision));
2459 
2460           link->dpcd_caps.sink_hw_revision =
2461                     dp_hw_fw_revision.ieee_hw_rev;
2462 
2463           memmove(
2464                     link->dpcd_caps.sink_fw_revision,
2465                     dp_hw_fw_revision.ieee_fw_rev,
2466                     sizeof(dp_hw_fw_revision.ieee_fw_rev));
2467 
2468           /* Connectivity log: detection */
2469           CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: ");
2470 
2471           return true;
2472 }
2473 
detect_dp_sink_caps(struct dc_link * link)2474 bool detect_dp_sink_caps(struct dc_link *link)
2475 {
2476           return retrieve_link_cap(link);
2477 
2478           /* dc init_hw has power encoder using default
2479            * signal for connector. For native DP, no
2480            * need to power up encoder again. If not native
2481            * DP, hw_init may need check signal or power up
2482            * encoder here.
2483            */
2484           /* TODO save sink caps in link->sink */
2485 }
2486 
detect_edp_sink_caps(struct dc_link * link)2487 void detect_edp_sink_caps(struct dc_link *link)
2488 {
2489           retrieve_link_cap(link);
2490 
2491           if (link->reported_link_cap.link_rate == LINK_RATE_UNKNOWN)
2492                     link->reported_link_cap.link_rate = LINK_RATE_HIGH2;
2493 
2494           link->verified_link_cap = link->reported_link_cap;
2495 }
2496 
dc_link_dp_enable_hpd(const struct dc_link * link)2497 void dc_link_dp_enable_hpd(const struct dc_link *link)
2498 {
2499           struct link_encoder *encoder = link->link_enc;
2500 
2501           if (encoder != NULL && encoder->funcs->enable_hpd != NULL)
2502                     encoder->funcs->enable_hpd(encoder);
2503 }
2504 
dc_link_dp_disable_hpd(const struct dc_link * link)2505 void dc_link_dp_disable_hpd(const struct dc_link *link)
2506 {
2507           struct link_encoder *encoder = link->link_enc;
2508 
2509           if (encoder != NULL && encoder->funcs->enable_hpd != NULL)
2510                     encoder->funcs->disable_hpd(encoder);
2511 }
2512 
is_dp_phy_pattern(enum dp_test_pattern test_pattern)2513 static bool is_dp_phy_pattern(enum dp_test_pattern test_pattern)
2514 {
2515           if ((DP_TEST_PATTERN_PHY_PATTERN_BEGIN <= test_pattern &&
2516                               test_pattern <= DP_TEST_PATTERN_PHY_PATTERN_END) ||
2517                               test_pattern == DP_TEST_PATTERN_VIDEO_MODE)
2518                     return true;
2519           else
2520                     return false;
2521 }
2522 
set_crtc_test_pattern(struct dc_link * link,struct pipe_ctx * pipe_ctx,enum dp_test_pattern test_pattern)2523 static void set_crtc_test_pattern(struct dc_link *link,
2524                                         struct pipe_ctx *pipe_ctx,
2525                                         enum dp_test_pattern test_pattern)
2526 {
2527           enum controller_dp_test_pattern controller_test_pattern;
2528           enum dc_color_depth color_depth = pipe_ctx->
2529                     stream->timing.display_color_depth;
2530           struct bit_depth_reduction_params params;
2531 
2532           memset(&params, 0, sizeof(params));
2533 
2534           switch (test_pattern) {
2535           case DP_TEST_PATTERN_COLOR_SQUARES:
2536                     controller_test_pattern =
2537                                         CONTROLLER_DP_TEST_PATTERN_COLORSQUARES;
2538           break;
2539           case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
2540                     controller_test_pattern =
2541                                         CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA;
2542           break;
2543           case DP_TEST_PATTERN_VERTICAL_BARS:
2544                     controller_test_pattern =
2545                                         CONTROLLER_DP_TEST_PATTERN_VERTICALBARS;
2546           break;
2547           case DP_TEST_PATTERN_HORIZONTAL_BARS:
2548                     controller_test_pattern =
2549                                         CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS;
2550           break;
2551           case DP_TEST_PATTERN_COLOR_RAMP:
2552                     controller_test_pattern =
2553                                         CONTROLLER_DP_TEST_PATTERN_COLORRAMP;
2554           break;
2555           default:
2556                     controller_test_pattern =
2557                                         CONTROLLER_DP_TEST_PATTERN_VIDEOMODE;
2558           break;
2559           }
2560 
2561           switch (test_pattern) {
2562           case DP_TEST_PATTERN_COLOR_SQUARES:
2563           case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
2564           case DP_TEST_PATTERN_VERTICAL_BARS:
2565           case DP_TEST_PATTERN_HORIZONTAL_BARS:
2566           case DP_TEST_PATTERN_COLOR_RAMP:
2567           {
2568                     /* disable bit depth reduction */
2569                     pipe_ctx->stream->bit_depth_params = params;
2570                     pipe_ctx->stream_res.opp->funcs->
2571                               opp_program_bit_depth_reduction(pipe_ctx->stream_res.opp, &params);
2572                     if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
2573                               pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
2574                                         controller_test_pattern, color_depth);
2575           }
2576           break;
2577           case DP_TEST_PATTERN_VIDEO_MODE:
2578           {
2579                     /* restore bitdepth reduction */
2580                     resource_build_bit_depth_reduction_params(pipe_ctx->stream,
2581                                                   &params);
2582                     pipe_ctx->stream->bit_depth_params = params;
2583                     pipe_ctx->stream_res.opp->funcs->
2584                               opp_program_bit_depth_reduction(pipe_ctx->stream_res.opp, &params);
2585                     if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
2586                               pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
2587                                         CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
2588                                         color_depth);
2589           }
2590           break;
2591 
2592           default:
2593           break;
2594           }
2595 }
2596 
dc_link_dp_set_test_pattern(struct dc_link * link,enum dp_test_pattern test_pattern,const struct link_training_settings * p_link_settings,const unsigned char * p_custom_pattern,unsigned int cust_pattern_size)2597 bool dc_link_dp_set_test_pattern(
2598           struct dc_link *link,
2599           enum dp_test_pattern test_pattern,
2600           const struct link_training_settings *p_link_settings,
2601           const unsigned char *p_custom_pattern,
2602           unsigned int cust_pattern_size)
2603 {
2604           struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
2605           struct pipe_ctx *pipe_ctx = &pipes[0];
2606           unsigned int lane;
2607           unsigned int i;
2608           unsigned char link_qual_pattern[LANE_COUNT_DP_MAX] = {0};
2609           union dpcd_training_pattern training_pattern;
2610           enum dpcd_phy_test_patterns pattern;
2611 
2612           memset(&training_pattern, 0, sizeof(training_pattern));
2613 
2614           for (i = 0; i < MAX_PIPES; i++) {
2615                     if (pipes[i].stream->sink->link == link) {
2616                               pipe_ctx = &pipes[i];
2617                               break;
2618                     }
2619           }
2620 
2621           /* Reset CRTC Test Pattern if it is currently running and request
2622            * is VideoMode Reset DP Phy Test Pattern if it is currently running
2623            * and request is VideoMode
2624            */
2625           if (link->test_pattern_enabled && test_pattern ==
2626                               DP_TEST_PATTERN_VIDEO_MODE) {
2627                     /* Set CRTC Test Pattern */
2628                     set_crtc_test_pattern(link, pipe_ctx, test_pattern);
2629                     dp_set_hw_test_pattern(link, test_pattern,
2630                                         (uint8_t *)p_custom_pattern,
2631                                         (uint32_t)cust_pattern_size);
2632 
2633                     /* Unblank Stream */
2634                     link->dc->hwss.unblank_stream(
2635                               pipe_ctx,
2636                               &link->verified_link_cap);
2637                     /* TODO:m_pHwss->MuteAudioEndpoint
2638                      * (pPathMode->pDisplayPath, false);
2639                      */
2640 
2641                     /* Reset Test Pattern state */
2642                     link->test_pattern_enabled = false;
2643 
2644                     return true;
2645           }
2646 
2647           /* Check for PHY Test Patterns */
2648           if (is_dp_phy_pattern(test_pattern)) {
2649                     /* Set DPCD Lane Settings before running test pattern */
2650                     if (p_link_settings != NULL) {
2651                               dp_set_hw_lane_settings(link, p_link_settings);
2652                               dpcd_set_lane_settings(link, p_link_settings);
2653                     }
2654 
2655                     /* Blank stream if running test pattern */
2656                     if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
2657                               /*TODO:
2658                                * m_pHwss->
2659                                * MuteAudioEndpoint(pPathMode->pDisplayPath, true);
2660                                */
2661                               /* Blank stream */
2662                               pipes->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc);
2663                     }
2664 
2665                     dp_set_hw_test_pattern(link, test_pattern,
2666                                         (uint8_t *)p_custom_pattern,
2667                                         (uint32_t)cust_pattern_size);
2668 
2669                     if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
2670                               /* Set Test Pattern state */
2671                               link->test_pattern_enabled = true;
2672                               if (p_link_settings != NULL)
2673                                         dpcd_set_link_settings(link,
2674                                                             p_link_settings);
2675                     }
2676 
2677                     switch (test_pattern) {
2678                     case DP_TEST_PATTERN_VIDEO_MODE:
2679                               pattern = PHY_TEST_PATTERN_NONE;
2680                               break;
2681                     case DP_TEST_PATTERN_D102:
2682                               pattern = PHY_TEST_PATTERN_D10_2;
2683                               break;
2684                     case DP_TEST_PATTERN_SYMBOL_ERROR:
2685                               pattern = PHY_TEST_PATTERN_SYMBOL_ERROR;
2686                               break;
2687                     case DP_TEST_PATTERN_PRBS7:
2688                               pattern = PHY_TEST_PATTERN_PRBS7;
2689                               break;
2690                     case DP_TEST_PATTERN_80BIT_CUSTOM:
2691                               pattern = PHY_TEST_PATTERN_80BIT_CUSTOM;
2692                               break;
2693                     case DP_TEST_PATTERN_CP2520_1:
2694                               pattern = PHY_TEST_PATTERN_CP2520_1;
2695                               break;
2696                     case DP_TEST_PATTERN_CP2520_2:
2697                               pattern = PHY_TEST_PATTERN_CP2520_2;
2698                               break;
2699                     case DP_TEST_PATTERN_CP2520_3:
2700                               pattern = PHY_TEST_PATTERN_CP2520_3;
2701                               break;
2702                     default:
2703                               return false;
2704                     }
2705 
2706                     if (test_pattern == DP_TEST_PATTERN_VIDEO_MODE
2707                     /*TODO:&& !pPathMode->pDisplayPath->IsTargetPoweredOn()*/)
2708                               return false;
2709 
2710                     if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
2711                               /* tell receiver that we are sending qualification
2712                                * pattern DP 1.2 or later - DP receiver's link quality
2713                                * pattern is set using DPCD LINK_QUAL_LANEx_SET
2714                                * register (0x10B~0x10E)\
2715                                */
2716                               for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++)
2717                                         link_qual_pattern[lane] =
2718                                                             (unsigned char)(pattern);
2719 
2720                               core_link_write_dpcd(link,
2721                                                   DP_LINK_QUAL_LANE0_SET,
2722                                                   link_qual_pattern,
2723                                                   sizeof(link_qual_pattern));
2724                     } else if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_10 ||
2725                                  link->dpcd_caps.dpcd_rev.raw == 0) {
2726                               /* tell receiver that we are sending qualification
2727                                * pattern DP 1.1a or earlier - DP receiver's link
2728                                * quality pattern is set using
2729                                * DPCD TRAINING_PATTERN_SET -> LINK_QUAL_PATTERN_SET
2730                                * register (0x102). We will use v_1.3 when we are
2731                                * setting test pattern for DP 1.1.
2732                                */
2733                               core_link_read_dpcd(link, DP_TRAINING_PATTERN_SET,
2734                                                       &training_pattern.raw,
2735                                                       sizeof(training_pattern));
2736                               training_pattern.v1_3.LINK_QUAL_PATTERN_SET = pattern;
2737                               core_link_write_dpcd(link, DP_TRAINING_PATTERN_SET,
2738                                                        &training_pattern.raw,
2739                                                        sizeof(training_pattern));
2740                     }
2741           } else {
2742           /* CRTC Patterns */
2743                     set_crtc_test_pattern(link, pipe_ctx, test_pattern);
2744                     /* Set Test Pattern state */
2745                     link->test_pattern_enabled = true;
2746           }
2747 
2748           return true;
2749 }
2750 
dp_enable_mst_on_sink(struct dc_link * link,bool enable)2751 void dp_enable_mst_on_sink(struct dc_link *link, bool enable)
2752 {
2753           unsigned char mstmCntl;
2754 
2755           core_link_read_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1);
2756           if (enable)
2757                     mstmCntl |= DP_MST_EN;
2758           else
2759                     mstmCntl &= (~DP_MST_EN);
2760 
2761           core_link_write_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1);
2762 }
2763