0001
0002
0003
0004
0005
0006
0007 #include <drm/display/drm_dp_helper.h>
0008 #include <drm/drm_crtc.h>
0009 #include <drm/drm_print.h>
0010
0011 #include "dp.h"
0012
0013 static const u8 drm_dp_edp_revisions[] = { 0x11, 0x12, 0x13, 0x14 };
0014
0015 static void drm_dp_link_caps_reset(struct drm_dp_link_caps *caps)
0016 {
0017 caps->enhanced_framing = false;
0018 caps->tps3_supported = false;
0019 caps->fast_training = false;
0020 caps->channel_coding = false;
0021 caps->alternate_scrambler_reset = false;
0022 }
0023
0024 void drm_dp_link_caps_copy(struct drm_dp_link_caps *dest,
0025 const struct drm_dp_link_caps *src)
0026 {
0027 dest->enhanced_framing = src->enhanced_framing;
0028 dest->tps3_supported = src->tps3_supported;
0029 dest->fast_training = src->fast_training;
0030 dest->channel_coding = src->channel_coding;
0031 dest->alternate_scrambler_reset = src->alternate_scrambler_reset;
0032 }
0033
0034 static void drm_dp_link_reset(struct drm_dp_link *link)
0035 {
0036 unsigned int i;
0037
0038 if (!link)
0039 return;
0040
0041 link->revision = 0;
0042 link->max_rate = 0;
0043 link->max_lanes = 0;
0044
0045 drm_dp_link_caps_reset(&link->caps);
0046 link->aux_rd_interval.cr = 0;
0047 link->aux_rd_interval.ce = 0;
0048 link->edp = 0;
0049
0050 link->rate = 0;
0051 link->lanes = 0;
0052
0053 for (i = 0; i < DP_MAX_SUPPORTED_RATES; i++)
0054 link->rates[i] = 0;
0055
0056 link->num_rates = 0;
0057 }
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074 int drm_dp_link_add_rate(struct drm_dp_link *link, unsigned long rate)
0075 {
0076 unsigned int i, pivot;
0077
0078 if (link->num_rates == DP_MAX_SUPPORTED_RATES)
0079 return -ENOSPC;
0080
0081 for (pivot = 0; pivot < link->num_rates; pivot++)
0082 if (rate <= link->rates[pivot])
0083 break;
0084
0085 if (pivot != link->num_rates && rate == link->rates[pivot])
0086 return -EEXIST;
0087
0088 for (i = link->num_rates; i > pivot; i--)
0089 link->rates[i] = link->rates[i - 1];
0090
0091 link->rates[pivot] = rate;
0092 link->num_rates++;
0093
0094 return 0;
0095 }
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111 int drm_dp_link_remove_rate(struct drm_dp_link *link, unsigned long rate)
0112 {
0113 unsigned int i;
0114
0115 for (i = 0; i < link->num_rates; i++)
0116 if (rate == link->rates[i])
0117 break;
0118
0119 if (i == link->num_rates)
0120 return -EINVAL;
0121
0122 link->num_rates--;
0123
0124 while (i < link->num_rates) {
0125 link->rates[i] = link->rates[i + 1];
0126 i++;
0127 }
0128
0129 return 0;
0130 }
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144 void drm_dp_link_update_rates(struct drm_dp_link *link)
0145 {
0146 unsigned int i, count = 0;
0147
0148 for (i = 0; i < link->num_rates; i++) {
0149 if (link->rates[i] != 0)
0150 link->rates[count++] = link->rates[i];
0151 }
0152
0153 for (i = count; i < link->num_rates; i++)
0154 link->rates[i] = 0;
0155
0156 link->num_rates = count;
0157 }
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170 int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link)
0171 {
0172 u8 dpcd[DP_RECEIVER_CAP_SIZE], value;
0173 unsigned int rd_interval;
0174 int err;
0175
0176 drm_dp_link_reset(link);
0177
0178 err = drm_dp_dpcd_read(aux, DP_DPCD_REV, dpcd, sizeof(dpcd));
0179 if (err < 0)
0180 return err;
0181
0182 link->revision = dpcd[DP_DPCD_REV];
0183 link->max_rate = drm_dp_max_link_rate(dpcd);
0184 link->max_lanes = drm_dp_max_lane_count(dpcd);
0185
0186 link->caps.enhanced_framing = drm_dp_enhanced_frame_cap(dpcd);
0187 link->caps.tps3_supported = drm_dp_tps3_supported(dpcd);
0188 link->caps.fast_training = drm_dp_fast_training_cap(dpcd);
0189 link->caps.channel_coding = drm_dp_channel_coding_supported(dpcd);
0190
0191 if (drm_dp_alternate_scrambler_reset_cap(dpcd)) {
0192 link->caps.alternate_scrambler_reset = true;
0193
0194 err = drm_dp_dpcd_readb(aux, DP_EDP_DPCD_REV, &value);
0195 if (err < 0)
0196 return err;
0197
0198 if (value >= ARRAY_SIZE(drm_dp_edp_revisions))
0199 DRM_ERROR("unsupported eDP version: %02x\n", value);
0200 else
0201 link->edp = drm_dp_edp_revisions[value];
0202 }
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215 rd_interval = dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
0216 DP_TRAINING_AUX_RD_MASK;
0217
0218 if (rd_interval > 4) {
0219 DRM_DEBUG_KMS("AUX interval %u out of range (max. 4)\n",
0220 rd_interval);
0221 rd_interval = 4;
0222 }
0223
0224 rd_interval *= 4 * USEC_PER_MSEC;
0225
0226 if (rd_interval == 0 || link->revision >= DP_DPCD_REV_14)
0227 link->aux_rd_interval.cr = 100;
0228
0229 if (rd_interval == 0)
0230 link->aux_rd_interval.ce = 400;
0231
0232 link->rate = link->max_rate;
0233 link->lanes = link->max_lanes;
0234
0235
0236 if (link->edp >= 0x14) {
0237 u8 supported_rates[DP_MAX_SUPPORTED_RATES * 2];
0238 unsigned int i;
0239 u16 rate;
0240
0241 err = drm_dp_dpcd_read(aux, DP_SUPPORTED_LINK_RATES,
0242 supported_rates,
0243 sizeof(supported_rates));
0244 if (err < 0)
0245 return err;
0246
0247 for (i = 0; i < DP_MAX_SUPPORTED_RATES; i++) {
0248 rate = supported_rates[i * 2 + 1] << 8 |
0249 supported_rates[i * 2 + 0];
0250
0251 drm_dp_link_add_rate(link, rate * 200);
0252 }
0253 }
0254
0255 return 0;
0256 }
0257
0258
0259
0260
0261
0262
0263
0264
0265 int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link)
0266 {
0267 u8 value;
0268 int err;
0269
0270
0271 if (link->revision < 0x11)
0272 return 0;
0273
0274 err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value);
0275 if (err < 0)
0276 return err;
0277
0278 value &= ~DP_SET_POWER_MASK;
0279 value |= DP_SET_POWER_D0;
0280
0281 err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value);
0282 if (err < 0)
0283 return err;
0284
0285
0286
0287
0288
0289
0290 usleep_range(1000, 2000);
0291
0292 return 0;
0293 }
0294
0295
0296
0297
0298
0299
0300
0301
0302 int drm_dp_link_power_down(struct drm_dp_aux *aux, struct drm_dp_link *link)
0303 {
0304 u8 value;
0305 int err;
0306
0307
0308 if (link->revision < 0x11)
0309 return 0;
0310
0311 err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value);
0312 if (err < 0)
0313 return err;
0314
0315 value &= ~DP_SET_POWER_MASK;
0316 value |= DP_SET_POWER_D3;
0317
0318 err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value);
0319 if (err < 0)
0320 return err;
0321
0322 return 0;
0323 }
0324
0325
0326
0327
0328
0329
0330
0331
0332 int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link)
0333 {
0334 u8 values[2], value;
0335 int err;
0336
0337 if (link->ops && link->ops->configure) {
0338 err = link->ops->configure(link);
0339 if (err < 0) {
0340 DRM_ERROR("failed to configure DP link: %d\n", err);
0341 return err;
0342 }
0343 }
0344
0345 values[0] = drm_dp_link_rate_to_bw_code(link->rate);
0346 values[1] = link->lanes;
0347
0348 if (link->caps.enhanced_framing)
0349 values[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
0350
0351 err = drm_dp_dpcd_write(aux, DP_LINK_BW_SET, values, sizeof(values));
0352 if (err < 0)
0353 return err;
0354
0355 if (link->caps.channel_coding)
0356 value = DP_SET_ANSI_8B10B;
0357 else
0358 value = 0;
0359
0360 err = drm_dp_dpcd_writeb(aux, DP_MAIN_LINK_CHANNEL_CODING_SET, value);
0361 if (err < 0)
0362 return err;
0363
0364 if (link->caps.alternate_scrambler_reset) {
0365 err = drm_dp_dpcd_writeb(aux, DP_EDP_CONFIGURATION_SET,
0366 DP_ALTERNATE_SCRAMBLER_RESET_ENABLE);
0367 if (err < 0)
0368 return err;
0369 }
0370
0371 return 0;
0372 }
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387 int drm_dp_link_choose(struct drm_dp_link *link,
0388 const struct drm_display_mode *mode,
0389 const struct drm_display_info *info)
0390 {
0391
0392 static const unsigned int rates[3] = { 162000, 270000, 540000 };
0393
0394 static const unsigned int lanes[3] = { 1, 2, 4 };
0395 unsigned long requirement, capacity;
0396 unsigned int rate = link->max_rate;
0397 unsigned int i, j;
0398
0399
0400 requirement = mode->clock * info->bpc * 3;
0401
0402 for (i = 0; i < ARRAY_SIZE(lanes) && lanes[i] <= link->max_lanes; i++) {
0403 for (j = 0; j < ARRAY_SIZE(rates) && rates[j] <= rate; j++) {
0404
0405
0406
0407
0408
0409
0410
0411
0412 capacity = lanes[i] * (rates[j] * 10) * 8 / 10;
0413
0414 if (capacity >= requirement) {
0415 DRM_DEBUG_KMS("using %u lanes at %u kHz (%lu/%lu kbps)\n",
0416 lanes[i], rates[j], requirement,
0417 capacity);
0418 link->lanes = lanes[i];
0419 link->rate = rates[j];
0420 return 0;
0421 }
0422 }
0423 }
0424
0425 return -ERANGE;
0426 }
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439 void drm_dp_link_train_init(struct drm_dp_link_train *train)
0440 {
0441 struct drm_dp_link_train_set *request = &train->request;
0442 struct drm_dp_link_train_set *adjust = &train->adjust;
0443 unsigned int i;
0444
0445 for (i = 0; i < 4; i++) {
0446 request->voltage_swing[i] = 0;
0447 adjust->voltage_swing[i] = 0;
0448
0449 request->pre_emphasis[i] = 0;
0450 adjust->pre_emphasis[i] = 0;
0451
0452 request->post_cursor[i] = 0;
0453 adjust->post_cursor[i] = 0;
0454 }
0455
0456 train->pattern = DP_TRAINING_PATTERN_DISABLE;
0457 train->clock_recovered = false;
0458 train->channel_equalized = false;
0459 }
0460
0461 static bool drm_dp_link_train_valid(const struct drm_dp_link_train *train)
0462 {
0463 return train->clock_recovered && train->channel_equalized;
0464 }
0465
0466 static int drm_dp_link_apply_training(struct drm_dp_link *link)
0467 {
0468 struct drm_dp_link_train_set *request = &link->train.request;
0469 unsigned int lanes = link->lanes, *vs, *pe, *pc, i;
0470 struct drm_dp_aux *aux = link->aux;
0471 u8 values[4], pattern = 0;
0472 int err;
0473
0474 err = link->ops->apply_training(link);
0475 if (err < 0) {
0476 DRM_ERROR("failed to apply link training: %d\n", err);
0477 return err;
0478 }
0479
0480 vs = request->voltage_swing;
0481 pe = request->pre_emphasis;
0482 pc = request->post_cursor;
0483
0484
0485 for (i = 0; i < lanes; i++)
0486 values[i] = DP_TRAIN_VOLTAGE_SWING_LEVEL(vs[i]) |
0487 DP_TRAIN_PRE_EMPHASIS_LEVEL(pe[i]);
0488
0489 err = drm_dp_dpcd_write(aux, DP_TRAINING_LANE0_SET, values, lanes);
0490 if (err < 0) {
0491 DRM_ERROR("failed to set training parameters: %d\n", err);
0492 return err;
0493 }
0494
0495
0496 if (link->revision >= 0x12 && link->rate == 540000) {
0497 values[0] = values[1] = 0;
0498
0499 for (i = 0; i < lanes; i++)
0500 values[i / 2] |= DP_LANE_POST_CURSOR(i, pc[i]);
0501
0502 err = drm_dp_dpcd_write(aux, DP_TRAINING_LANE0_1_SET2, values,
0503 DIV_ROUND_UP(lanes, 2));
0504 if (err < 0) {
0505 DRM_ERROR("failed to set post-cursor: %d\n", err);
0506 return err;
0507 }
0508 }
0509
0510
0511 if (link->train.pattern != DP_TRAINING_PATTERN_DISABLE)
0512 pattern |= DP_LINK_SCRAMBLING_DISABLE;
0513
0514 pattern |= link->train.pattern;
0515
0516 err = drm_dp_dpcd_writeb(aux, DP_TRAINING_PATTERN_SET, pattern);
0517 if (err < 0) {
0518 DRM_ERROR("failed to set training pattern: %d\n", err);
0519 return err;
0520 }
0521
0522 return 0;
0523 }
0524
0525 static void drm_dp_link_train_wait(struct drm_dp_link *link)
0526 {
0527 unsigned long min = 0;
0528
0529 switch (link->train.pattern) {
0530 case DP_TRAINING_PATTERN_1:
0531 min = link->aux_rd_interval.cr;
0532 break;
0533
0534 case DP_TRAINING_PATTERN_2:
0535 case DP_TRAINING_PATTERN_3:
0536 min = link->aux_rd_interval.ce;
0537 break;
0538
0539 default:
0540 break;
0541 }
0542
0543 if (min > 0)
0544 usleep_range(min, 2 * min);
0545 }
0546
0547 static void drm_dp_link_get_adjustments(struct drm_dp_link *link,
0548 u8 status[DP_LINK_STATUS_SIZE])
0549 {
0550 struct drm_dp_link_train_set *adjust = &link->train.adjust;
0551 unsigned int i;
0552 u8 post_cursor;
0553 int err;
0554
0555 err = drm_dp_dpcd_read(link->aux, DP_ADJUST_REQUEST_POST_CURSOR2,
0556 &post_cursor, sizeof(post_cursor));
0557 if (err < 0) {
0558 DRM_ERROR("failed to read post_cursor2: %d\n", err);
0559 post_cursor = 0;
0560 }
0561
0562 for (i = 0; i < link->lanes; i++) {
0563 adjust->voltage_swing[i] =
0564 drm_dp_get_adjust_request_voltage(status, i) >>
0565 DP_TRAIN_VOLTAGE_SWING_SHIFT;
0566
0567 adjust->pre_emphasis[i] =
0568 drm_dp_get_adjust_request_pre_emphasis(status, i) >>
0569 DP_TRAIN_PRE_EMPHASIS_SHIFT;
0570
0571 adjust->post_cursor[i] =
0572 (post_cursor >> (i << 1)) & 0x3;
0573 }
0574 }
0575
0576 static void drm_dp_link_train_adjust(struct drm_dp_link_train *train)
0577 {
0578 struct drm_dp_link_train_set *request = &train->request;
0579 struct drm_dp_link_train_set *adjust = &train->adjust;
0580 unsigned int i;
0581
0582 for (i = 0; i < 4; i++)
0583 if (request->voltage_swing[i] != adjust->voltage_swing[i])
0584 request->voltage_swing[i] = adjust->voltage_swing[i];
0585
0586 for (i = 0; i < 4; i++)
0587 if (request->pre_emphasis[i] != adjust->pre_emphasis[i])
0588 request->pre_emphasis[i] = adjust->pre_emphasis[i];
0589
0590 for (i = 0; i < 4; i++)
0591 if (request->post_cursor[i] != adjust->post_cursor[i])
0592 request->post_cursor[i] = adjust->post_cursor[i];
0593 }
0594
0595 static int drm_dp_link_recover_clock(struct drm_dp_link *link)
0596 {
0597 u8 status[DP_LINK_STATUS_SIZE];
0598 int err;
0599
0600 err = drm_dp_link_apply_training(link);
0601 if (err < 0)
0602 return err;
0603
0604 drm_dp_link_train_wait(link);
0605
0606 err = drm_dp_dpcd_read_link_status(link->aux, status);
0607 if (err < 0) {
0608 DRM_ERROR("failed to read link status: %d\n", err);
0609 return err;
0610 }
0611
0612 if (!drm_dp_clock_recovery_ok(status, link->lanes))
0613 drm_dp_link_get_adjustments(link, status);
0614 else
0615 link->train.clock_recovered = true;
0616
0617 return 0;
0618 }
0619
0620 static int drm_dp_link_clock_recovery(struct drm_dp_link *link)
0621 {
0622 unsigned int repeat;
0623 int err;
0624
0625
0626 link->train.pattern = DP_TRAINING_PATTERN_1;
0627
0628 for (repeat = 1; repeat < 5; repeat++) {
0629 err = drm_dp_link_recover_clock(link);
0630 if (err < 0) {
0631 DRM_ERROR("failed to recover clock: %d\n", err);
0632 return err;
0633 }
0634
0635 if (link->train.clock_recovered)
0636 break;
0637
0638 drm_dp_link_train_adjust(&link->train);
0639 }
0640
0641 return 0;
0642 }
0643
0644 static int drm_dp_link_equalize_channel(struct drm_dp_link *link)
0645 {
0646 struct drm_dp_aux *aux = link->aux;
0647 u8 status[DP_LINK_STATUS_SIZE];
0648 int err;
0649
0650 err = drm_dp_link_apply_training(link);
0651 if (err < 0)
0652 return err;
0653
0654 drm_dp_link_train_wait(link);
0655
0656 err = drm_dp_dpcd_read_link_status(aux, status);
0657 if (err < 0) {
0658 DRM_ERROR("failed to read link status: %d\n", err);
0659 return err;
0660 }
0661
0662 if (!drm_dp_clock_recovery_ok(status, link->lanes)) {
0663 DRM_ERROR("clock recovery lost while equalizing channel\n");
0664 link->train.clock_recovered = false;
0665 return 0;
0666 }
0667
0668 if (!drm_dp_channel_eq_ok(status, link->lanes))
0669 drm_dp_link_get_adjustments(link, status);
0670 else
0671 link->train.channel_equalized = true;
0672
0673 return 0;
0674 }
0675
0676 static int drm_dp_link_channel_equalization(struct drm_dp_link *link)
0677 {
0678 unsigned int repeat;
0679 int err;
0680
0681
0682 if (link->caps.tps3_supported)
0683 link->train.pattern = DP_TRAINING_PATTERN_3;
0684 else
0685 link->train.pattern = DP_TRAINING_PATTERN_2;
0686
0687 for (repeat = 1; repeat < 5; repeat++) {
0688 err = drm_dp_link_equalize_channel(link);
0689 if (err < 0) {
0690 DRM_ERROR("failed to equalize channel: %d\n", err);
0691 return err;
0692 }
0693
0694 if (link->train.channel_equalized)
0695 break;
0696
0697 drm_dp_link_train_adjust(&link->train);
0698 }
0699
0700 return 0;
0701 }
0702
0703 static int drm_dp_link_downgrade(struct drm_dp_link *link)
0704 {
0705 switch (link->rate) {
0706 case 162000:
0707 return -EINVAL;
0708
0709 case 270000:
0710 link->rate = 162000;
0711 break;
0712
0713 case 540000:
0714 link->rate = 270000;
0715 return 0;
0716 }
0717
0718 return 0;
0719 }
0720
0721 static void drm_dp_link_train_disable(struct drm_dp_link *link)
0722 {
0723 int err;
0724
0725 link->train.pattern = DP_TRAINING_PATTERN_DISABLE;
0726
0727 err = drm_dp_link_apply_training(link);
0728 if (err < 0)
0729 DRM_ERROR("failed to disable link training: %d\n", err);
0730 }
0731
0732 static int drm_dp_link_train_full(struct drm_dp_link *link)
0733 {
0734 int err;
0735
0736 retry:
0737 DRM_DEBUG_KMS("full-training link: %u lane%s at %u MHz\n",
0738 link->lanes, (link->lanes > 1) ? "s" : "",
0739 link->rate / 100);
0740
0741 err = drm_dp_link_configure(link->aux, link);
0742 if (err < 0) {
0743 DRM_ERROR("failed to configure DP link: %d\n", err);
0744 return err;
0745 }
0746
0747 err = drm_dp_link_clock_recovery(link);
0748 if (err < 0) {
0749 DRM_ERROR("clock recovery failed: %d\n", err);
0750 goto out;
0751 }
0752
0753 if (!link->train.clock_recovered) {
0754 DRM_ERROR("clock recovery failed, downgrading link\n");
0755
0756 err = drm_dp_link_downgrade(link);
0757 if (err < 0)
0758 goto out;
0759
0760 goto retry;
0761 }
0762
0763 DRM_DEBUG_KMS("clock recovery succeeded\n");
0764
0765 err = drm_dp_link_channel_equalization(link);
0766 if (err < 0) {
0767 DRM_ERROR("channel equalization failed: %d\n", err);
0768 goto out;
0769 }
0770
0771 if (!link->train.channel_equalized) {
0772 DRM_ERROR("channel equalization failed, downgrading link\n");
0773
0774 err = drm_dp_link_downgrade(link);
0775 if (err < 0)
0776 goto out;
0777
0778 goto retry;
0779 }
0780
0781 DRM_DEBUG_KMS("channel equalization succeeded\n");
0782
0783 out:
0784 drm_dp_link_train_disable(link);
0785 return err;
0786 }
0787
0788 static int drm_dp_link_train_fast(struct drm_dp_link *link)
0789 {
0790 u8 status[DP_LINK_STATUS_SIZE];
0791 int err;
0792
0793 DRM_DEBUG_KMS("fast-training link: %u lane%s at %u MHz\n",
0794 link->lanes, (link->lanes > 1) ? "s" : "",
0795 link->rate / 100);
0796
0797 err = drm_dp_link_configure(link->aux, link);
0798 if (err < 0) {
0799 DRM_ERROR("failed to configure DP link: %d\n", err);
0800 return err;
0801 }
0802
0803
0804 link->train.pattern = DP_TRAINING_PATTERN_1;
0805
0806 err = drm_dp_link_apply_training(link);
0807 if (err < 0)
0808 goto out;
0809
0810 usleep_range(500, 1000);
0811
0812
0813 if (link->caps.tps3_supported)
0814 link->train.pattern = DP_TRAINING_PATTERN_3;
0815 else
0816 link->train.pattern = DP_TRAINING_PATTERN_2;
0817
0818 err = drm_dp_link_apply_training(link);
0819 if (err < 0)
0820 goto out;
0821
0822 usleep_range(500, 1000);
0823
0824 err = drm_dp_dpcd_read_link_status(link->aux, status);
0825 if (err < 0) {
0826 DRM_ERROR("failed to read link status: %d\n", err);
0827 goto out;
0828 }
0829
0830 if (!drm_dp_clock_recovery_ok(status, link->lanes)) {
0831 DRM_ERROR("clock recovery failed\n");
0832 err = -EIO;
0833 }
0834
0835 if (!drm_dp_channel_eq_ok(status, link->lanes)) {
0836 DRM_ERROR("channel equalization failed\n");
0837 err = -EIO;
0838 }
0839
0840 out:
0841 drm_dp_link_train_disable(link);
0842 return err;
0843 }
0844
0845
0846
0847
0848
0849
0850
0851
0852
0853
0854
0855
0856
0857
0858
0859 int drm_dp_link_train(struct drm_dp_link *link)
0860 {
0861 int err;
0862
0863 drm_dp_link_train_init(&link->train);
0864
0865 if (link->caps.fast_training) {
0866 if (drm_dp_link_train_valid(&link->train)) {
0867 err = drm_dp_link_train_fast(link);
0868 if (err < 0)
0869 DRM_ERROR("fast link training failed: %d\n",
0870 err);
0871 else
0872 return 0;
0873 } else {
0874 DRM_DEBUG_KMS("training parameters not available\n");
0875 }
0876 } else {
0877 DRM_DEBUG_KMS("fast link training not supported\n");
0878 }
0879
0880 err = drm_dp_link_train_full(link);
0881 if (err < 0)
0882 DRM_ERROR("full link training failed: %d\n", err);
0883
0884 return err;
0885 }