Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: MIT
0002 /*
0003  * Copyright (C) 2013-2019 NVIDIA Corporation
0004  * Copyright (C) 2015 Rob Clark
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  * drm_dp_link_add_rate() - add a rate to the list of supported rates
0061  * @link: the link to add the rate to
0062  * @rate: the rate to add
0063  *
0064  * Add a link rate to the list of supported link rates.
0065  *
0066  * Returns:
0067  * 0 on success or one of the following negative error codes on failure:
0068  * - ENOSPC if the maximum number of supported rates has been reached
0069  * - EEXISTS if the link already supports this rate
0070  *
0071  * See also:
0072  * drm_dp_link_remove_rate()
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  * drm_dp_link_remove_rate() - remove a rate from the list of supported rates
0099  * @link: the link from which to remove the rate
0100  * @rate: the rate to remove
0101  *
0102  * Removes a link rate from the list of supported link rates.
0103  *
0104  * Returns:
0105  * 0 on success or one of the following negative error codes on failure:
0106  * - EINVAL if the specified rate is not among the supported rates
0107  *
0108  * See also:
0109  * drm_dp_link_add_rate()
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  * drm_dp_link_update_rates() - normalize the supported link rates array
0134  * @link: the link for which to normalize the supported link rates
0135  *
0136  * Users should call this function after they've manually modified the array
0137  * of supported link rates. This function removes any stale entries, compacts
0138  * the array and updates the supported link rate count. Note that calling the
0139  * drm_dp_link_remove_rate() function already does this janitorial work.
0140  *
0141  * See also:
0142  * drm_dp_link_add_rate(), drm_dp_link_remove_rate()
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  * drm_dp_link_probe() - probe a DisplayPort link for capabilities
0161  * @aux: DisplayPort AUX channel
0162  * @link: pointer to structure in which to return link capabilities
0163  *
0164  * The structure filled in by this function can usually be passed directly
0165  * into drm_dp_link_power_up() and drm_dp_link_configure() to power up and
0166  * configure the link based on the link's capabilities.
0167  *
0168  * Returns 0 on success or a negative error code on failure.
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      * The DPCD stores the AUX read interval in units of 4 ms. There are
0206      * two special cases:
0207      *
0208      *   1) if the TRAINING_AUX_RD_INTERVAL field is 0, the clock recovery
0209      *      and channel equalization should use 100 us or 400 us AUX read
0210      *      intervals, respectively
0211      *
0212      *   2) for DP v1.4 and above, clock recovery should always use 100 us
0213      *      AUX read intervals
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     /* Parse SUPPORTED_LINK_RATES from eDP 1.4 */
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  * drm_dp_link_power_up() - power up a DisplayPort link
0260  * @aux: DisplayPort AUX channel
0261  * @link: pointer to a structure containing the link configuration
0262  *
0263  * Returns 0 on success or a negative error code on failure.
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     /* DP_SET_POWER register is only available on DPCD v1.1 and later */
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      * According to the DP 1.1 specification, a "Sink Device must exit the
0287      * power saving state within 1 ms" (Section 2.5.3.1, Table 5-52, "Sink
0288      * Control Field" (register 0x600).
0289      */
0290     usleep_range(1000, 2000);
0291 
0292     return 0;
0293 }
0294 
0295 /**
0296  * drm_dp_link_power_down() - power down a DisplayPort link
0297  * @aux: DisplayPort AUX channel
0298  * @link: pointer to a structure containing the link configuration
0299  *
0300  * Returns 0 on success or a negative error code on failure.
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     /* DP_SET_POWER register is only available on DPCD v1.1 and later */
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  * drm_dp_link_configure() - configure a DisplayPort link
0327  * @aux: DisplayPort AUX channel
0328  * @link: pointer to a structure containing the link configuration
0329  *
0330  * Returns 0 on success or a negative error code on failure.
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  * drm_dp_link_choose() - choose the lowest possible configuration for a mode
0376  * @link: DRM DP link object
0377  * @mode: DRM display mode
0378  * @info: DRM display information
0379  *
0380  * According to the eDP specification, a source should select a configuration
0381  * with the lowest number of lanes and the lowest possible link rate that can
0382  * match the bitrate requirements of a video mode. However it must ensure not
0383  * to exceed the capabilities of the sink.
0384  *
0385  * Returns: 0 on success or a negative error code on failure.
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     /* available link symbol clock rates */
0392     static const unsigned int rates[3] = { 162000, 270000, 540000 };
0393     /* available number of lanes */
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     /* bandwidth requirement */
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              * Capacity for this combination of lanes and rate,
0406              * factoring in the ANSI 8B/10B encoding.
0407              *
0408              * Link rates in the DRM DP helpers are really link
0409              * symbol frequencies, so a tenth of the actual rate
0410              * of the link.
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  * DOC: Link training
0430  *
0431  * These functions contain common logic and helpers to implement DisplayPort
0432  * link training.
0433  */
0434 
0435 /**
0436  * drm_dp_link_train_init() - initialize DisplayPort link training state
0437  * @train: DisplayPort link training state
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     /* write currently selected voltage-swing and pre-emphasis levels */
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     /* write currently selected post-cursor level (if supported) */
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     /* write link pattern */
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     /* start clock recovery using training pattern 1 */
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     /* start channel equalization using pattern 2 or 3 */
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     /* transmit training pattern 1 for 500 microseconds */
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     /* transmit training pattern 2 or 3 for 500 microseconds */
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  * drm_dp_link_train() - perform DisplayPort link training
0847  * @link: a DP link object
0848  *
0849  * Uses the context stored in the DP link object to perform link training. It
0850  * is expected that drivers will call drm_dp_link_probe() to obtain the link
0851  * capabilities before performing link training.
0852  *
0853  * If the sink supports fast link training (no AUX CH handshake) and valid
0854  * training settings are available, this function will try to perform fast
0855  * link training and fall back to full link training on failure.
0856  *
0857  * Returns: 0 on success or a negative error code on failure.
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 }