linux/drivers/gpu/drm/tegra/dp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: MIT
   2/*
   3 * Copyright (C) 2013-2019 NVIDIA Corporation
   4 * Copyright (C) 2015 Rob Clark
   5 */
   6
   7#include <drm/drm_crtc.h>
   8#include <drm/drm_dp_helper.h>
   9#include <drm/drm_print.h>
  10
  11#include "dp.h"
  12
  13static const u8 drm_dp_edp_revisions[] = { 0x11, 0x12, 0x13, 0x14 };
  14
  15static void drm_dp_link_caps_reset(struct drm_dp_link_caps *caps)
  16{
  17        caps->enhanced_framing = false;
  18        caps->tps3_supported = false;
  19        caps->fast_training = false;
  20        caps->channel_coding = false;
  21        caps->alternate_scrambler_reset = false;
  22}
  23
  24void drm_dp_link_caps_copy(struct drm_dp_link_caps *dest,
  25                           const struct drm_dp_link_caps *src)
  26{
  27        dest->enhanced_framing = src->enhanced_framing;
  28        dest->tps3_supported = src->tps3_supported;
  29        dest->fast_training = src->fast_training;
  30        dest->channel_coding = src->channel_coding;
  31        dest->alternate_scrambler_reset = src->alternate_scrambler_reset;
  32}
  33
  34static void drm_dp_link_reset(struct drm_dp_link *link)
  35{
  36        unsigned int i;
  37
  38        if (!link)
  39                return;
  40
  41        link->revision = 0;
  42        link->max_rate = 0;
  43        link->max_lanes = 0;
  44
  45        drm_dp_link_caps_reset(&link->caps);
  46        link->aux_rd_interval.cr = 0;
  47        link->aux_rd_interval.ce = 0;
  48        link->edp = 0;
  49
  50        link->rate = 0;
  51        link->lanes = 0;
  52
  53        for (i = 0; i < DP_MAX_SUPPORTED_RATES; i++)
  54                link->rates[i] = 0;
  55
  56        link->num_rates = 0;
  57}
  58
  59/**
  60 * drm_dp_link_add_rate() - add a rate to the list of supported rates
  61 * @link: the link to add the rate to
  62 * @rate: the rate to add
  63 *
  64 * Add a link rate to the list of supported link rates.
  65 *
  66 * Returns:
  67 * 0 on success or one of the following negative error codes on failure:
  68 * - ENOSPC if the maximum number of supported rates has been reached
  69 * - EEXISTS if the link already supports this rate
  70 *
  71 * See also:
  72 * drm_dp_link_remove_rate()
  73 */
  74int drm_dp_link_add_rate(struct drm_dp_link *link, unsigned long rate)
  75{
  76        unsigned int i, pivot;
  77
  78        if (link->num_rates == DP_MAX_SUPPORTED_RATES)
  79                return -ENOSPC;
  80
  81        for (pivot = 0; pivot < link->num_rates; pivot++)
  82                if (rate <= link->rates[pivot])
  83                        break;
  84
  85        if (pivot != link->num_rates && rate == link->rates[pivot])
  86                return -EEXIST;
  87
  88        for (i = link->num_rates; i > pivot; i--)
  89                link->rates[i] = link->rates[i - 1];
  90
  91        link->rates[pivot] = rate;
  92        link->num_rates++;
  93
  94        return 0;
  95}
  96
  97/**
  98 * drm_dp_link_remove_rate() - remove a rate from the list of supported rates
  99 * @link: the link from which to remove the rate
 100 * @rate: the rate to remove
 101 *
 102 * Removes a link rate from the list of supported link rates.
 103 *
 104 * Returns:
 105 * 0 on success or one of the following negative error codes on failure:
 106 * - EINVAL if the specified rate is not among the supported rates
 107 *
 108 * See also:
 109 * drm_dp_link_add_rate()
 110 */
 111int drm_dp_link_remove_rate(struct drm_dp_link *link, unsigned long rate)
 112{
 113        unsigned int i;
 114
 115        for (i = 0; i < link->num_rates; i++)
 116                if (rate == link->rates[i])
 117                        break;
 118
 119        if (i == link->num_rates)
 120                return -EINVAL;
 121
 122        link->num_rates--;
 123
 124        while (i < link->num_rates) {
 125                link->rates[i] = link->rates[i + 1];
 126                i++;
 127        }
 128
 129        return 0;
 130}
 131
 132/**
 133 * drm_dp_link_update_rates() - normalize the supported link rates array
 134 * @link: the link for which to normalize the supported link rates
 135 *
 136 * Users should call this function after they've manually modified the array
 137 * of supported link rates. This function removes any stale entries, compacts
 138 * the array and updates the supported link rate count. Note that calling the
 139 * drm_dp_link_remove_rate() function already does this janitorial work.
 140 *
 141 * See also:
 142 * drm_dp_link_add_rate(), drm_dp_link_remove_rate()
 143 */
 144void drm_dp_link_update_rates(struct drm_dp_link *link)
 145{
 146        unsigned int i, count = 0;
 147
 148        for (i = 0; i < link->num_rates; i++) {
 149                if (link->rates[i] != 0)
 150                        link->rates[count++] = link->rates[i];
 151        }
 152
 153        for (i = count; i < link->num_rates; i++)
 154                link->rates[i] = 0;
 155
 156        link->num_rates = count;
 157}
 158
 159/**
 160 * drm_dp_link_probe() - probe a DisplayPort link for capabilities
 161 * @aux: DisplayPort AUX channel
 162 * @link: pointer to structure in which to return link capabilities
 163 *
 164 * The structure filled in by this function can usually be passed directly
 165 * into drm_dp_link_power_up() and drm_dp_link_configure() to power up and
 166 * configure the link based on the link's capabilities.
 167 *
 168 * Returns 0 on success or a negative error code on failure.
 169 */
 170int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link)
 171{
 172        u8 dpcd[DP_RECEIVER_CAP_SIZE], value;
 173        unsigned int rd_interval;
 174        int err;
 175
 176        drm_dp_link_reset(link);
 177
 178        err = drm_dp_dpcd_read(aux, DP_DPCD_REV, dpcd, sizeof(dpcd));
 179        if (err < 0)
 180                return err;
 181
 182        link->revision = dpcd[DP_DPCD_REV];
 183        link->max_rate = drm_dp_max_link_rate(dpcd);
 184        link->max_lanes = drm_dp_max_lane_count(dpcd);
 185
 186        link->caps.enhanced_framing = drm_dp_enhanced_frame_cap(dpcd);
 187        link->caps.tps3_supported = drm_dp_tps3_supported(dpcd);
 188        link->caps.fast_training = drm_dp_fast_training_cap(dpcd);
 189        link->caps.channel_coding = drm_dp_channel_coding_supported(dpcd);
 190
 191        if (drm_dp_alternate_scrambler_reset_cap(dpcd)) {
 192                link->caps.alternate_scrambler_reset = true;
 193
 194                err = drm_dp_dpcd_readb(aux, DP_EDP_DPCD_REV, &value);
 195                if (err < 0)
 196                        return err;
 197
 198                if (value >= ARRAY_SIZE(drm_dp_edp_revisions))
 199                        DRM_ERROR("unsupported eDP version: %02x\n", value);
 200                else
 201                        link->edp = drm_dp_edp_revisions[value];
 202        }
 203
 204        /*
 205         * The DPCD stores the AUX read interval in units of 4 ms. There are
 206         * two special cases:
 207         *
 208         *   1) if the TRAINING_AUX_RD_INTERVAL field is 0, the clock recovery
 209         *      and channel equalization should use 100 us or 400 us AUX read
 210         *      intervals, respectively
 211         *
 212         *   2) for DP v1.4 and above, clock recovery should always use 100 us
 213         *      AUX read intervals
 214         */
 215        rd_interval = dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
 216                           DP_TRAINING_AUX_RD_MASK;
 217
 218        if (rd_interval > 4) {
 219                DRM_DEBUG_KMS("AUX interval %u out of range (max. 4)\n",
 220                              rd_interval);
 221                rd_interval = 4;
 222        }
 223
 224        rd_interval *= 4 * USEC_PER_MSEC;
 225
 226        if (rd_interval == 0 || link->revision >= DP_DPCD_REV_14)
 227                link->aux_rd_interval.cr = 100;
 228
 229        if (rd_interval == 0)
 230                link->aux_rd_interval.ce = 400;
 231
 232        link->rate = link->max_rate;
 233        link->lanes = link->max_lanes;
 234
 235        /* Parse SUPPORTED_LINK_RATES from eDP 1.4 */
 236        if (link->edp >= 0x14) {
 237                u8 supported_rates[DP_MAX_SUPPORTED_RATES * 2];
 238                unsigned int i;
 239                u16 rate;
 240
 241                err = drm_dp_dpcd_read(aux, DP_SUPPORTED_LINK_RATES,
 242                                       supported_rates,
 243                                       sizeof(supported_rates));
 244                if (err < 0)
 245                        return err;
 246
 247                for (i = 0; i < DP_MAX_SUPPORTED_RATES; i++) {
 248                        rate = supported_rates[i * 2 + 1] << 8 |
 249                               supported_rates[i * 2 + 0];
 250
 251                        drm_dp_link_add_rate(link, rate * 200);
 252                }
 253        }
 254
 255        return 0;
 256}
 257
 258/**
 259 * drm_dp_link_power_up() - power up a DisplayPort link
 260 * @aux: DisplayPort AUX channel
 261 * @link: pointer to a structure containing the link configuration
 262 *
 263 * Returns 0 on success or a negative error code on failure.
 264 */
 265int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link)
 266{
 267        u8 value;
 268        int err;
 269
 270        /* DP_SET_POWER register is only available on DPCD v1.1 and later */
 271        if (link->revision < 0x11)
 272                return 0;
 273
 274        err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value);
 275        if (err < 0)
 276                return err;
 277
 278        value &= ~DP_SET_POWER_MASK;
 279        value |= DP_SET_POWER_D0;
 280
 281        err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value);
 282        if (err < 0)
 283                return err;
 284
 285        /*
 286         * According to the DP 1.1 specification, a "Sink Device must exit the
 287         * power saving state within 1 ms" (Section 2.5.3.1, Table 5-52, "Sink
 288         * Control Field" (register 0x600).
 289         */
 290        usleep_range(1000, 2000);
 291
 292        return 0;
 293}
 294
 295/**
 296 * drm_dp_link_power_down() - power down a DisplayPort link
 297 * @aux: DisplayPort AUX channel
 298 * @link: pointer to a structure containing the link configuration
 299 *
 300 * Returns 0 on success or a negative error code on failure.
 301 */
 302int drm_dp_link_power_down(struct drm_dp_aux *aux, struct drm_dp_link *link)
 303{
 304        u8 value;
 305        int err;
 306
 307        /* DP_SET_POWER register is only available on DPCD v1.1 and later */
 308        if (link->revision < 0x11)
 309                return 0;
 310
 311        err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value);
 312        if (err < 0)
 313                return err;
 314
 315        value &= ~DP_SET_POWER_MASK;
 316        value |= DP_SET_POWER_D3;
 317
 318        err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value);
 319        if (err < 0)
 320                return err;
 321
 322        return 0;
 323}
 324
 325/**
 326 * drm_dp_link_configure() - configure a DisplayPort link
 327 * @aux: DisplayPort AUX channel
 328 * @link: pointer to a structure containing the link configuration
 329 *
 330 * Returns 0 on success or a negative error code on failure.
 331 */
 332int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link)
 333{
 334        u8 values[2], value;
 335        int err;
 336
 337        if (link->ops && link->ops->configure) {
 338                err = link->ops->configure(link);
 339                if (err < 0) {
 340                        DRM_ERROR("failed to configure DP link: %d\n", err);
 341                        return err;
 342                }
 343        }
 344
 345        values[0] = drm_dp_link_rate_to_bw_code(link->rate);
 346        values[1] = link->lanes;
 347
 348        if (link->caps.enhanced_framing)
 349                values[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
 350
 351        err = drm_dp_dpcd_write(aux, DP_LINK_BW_SET, values, sizeof(values));
 352        if (err < 0)
 353                return err;
 354
 355        if (link->caps.channel_coding)
 356                value = DP_SET_ANSI_8B10B;
 357        else
 358                value = 0;
 359
 360        err = drm_dp_dpcd_writeb(aux, DP_MAIN_LINK_CHANNEL_CODING_SET, value);
 361        if (err < 0)
 362                return err;
 363
 364        if (link->caps.alternate_scrambler_reset) {
 365                err = drm_dp_dpcd_writeb(aux, DP_EDP_CONFIGURATION_SET,
 366                                         DP_ALTERNATE_SCRAMBLER_RESET_ENABLE);
 367                if (err < 0)
 368                        return err;
 369        }
 370
 371        return 0;
 372}
 373
 374/**
 375 * drm_dp_link_choose() - choose the lowest possible configuration for a mode
 376 * @link: DRM DP link object
 377 * @mode: DRM display mode
 378 * @info: DRM display information
 379 *
 380 * According to the eDP specification, a source should select a configuration
 381 * with the lowest number of lanes and the lowest possible link rate that can
 382 * match the bitrate requirements of a video mode. However it must ensure not
 383 * to exceed the capabilities of the sink.
 384 *
 385 * Returns: 0 on success or a negative error code on failure.
 386 */
 387int drm_dp_link_choose(struct drm_dp_link *link,
 388                       const struct drm_display_mode *mode,
 389                       const struct drm_display_info *info)
 390{
 391        /* available link symbol clock rates */
 392        static const unsigned int rates[3] = { 162000, 270000, 540000 };
 393        /* available number of lanes */
 394        static const unsigned int lanes[3] = { 1, 2, 4 };
 395        unsigned long requirement, capacity;
 396        unsigned int rate = link->max_rate;
 397        unsigned int i, j;
 398
 399        /* bandwidth requirement */
 400        requirement = mode->clock * info->bpc * 3;
 401
 402        for (i = 0; i < ARRAY_SIZE(lanes) && lanes[i] <= link->max_lanes; i++) {
 403                for (j = 0; j < ARRAY_SIZE(rates) && rates[j] <= rate; j++) {
 404                        /*
 405                         * Capacity for this combination of lanes and rate,
 406                         * factoring in the ANSI 8B/10B encoding.
 407                         *
 408                         * Link rates in the DRM DP helpers are really link
 409                         * symbol frequencies, so a tenth of the actual rate
 410                         * of the link.
 411                         */
 412                        capacity = lanes[i] * (rates[j] * 10) * 8 / 10;
 413
 414                        if (capacity >= requirement) {
 415                                DRM_DEBUG_KMS("using %u lanes at %u kHz (%lu/%lu kbps)\n",
 416                                              lanes[i], rates[j], requirement,
 417                                              capacity);
 418                                link->lanes = lanes[i];
 419                                link->rate = rates[j];
 420                                return 0;
 421                        }
 422                }
 423        }
 424
 425        return -ERANGE;
 426}
 427
 428/**
 429 * DOC: Link training
 430 *
 431 * These functions contain common logic and helpers to implement DisplayPort
 432 * link training.
 433 */
 434
 435/**
 436 * drm_dp_link_train_init() - initialize DisplayPort link training state
 437 * @train: DisplayPort link training state
 438 */
 439void drm_dp_link_train_init(struct drm_dp_link_train *train)
 440{
 441        struct drm_dp_link_train_set *request = &train->request;
 442        struct drm_dp_link_train_set *adjust = &train->adjust;
 443        unsigned int i;
 444
 445        for (i = 0; i < 4; i++) {
 446                request->voltage_swing[i] = 0;
 447                adjust->voltage_swing[i] = 0;
 448
 449                request->pre_emphasis[i] = 0;
 450                adjust->pre_emphasis[i] = 0;
 451
 452                request->post_cursor[i] = 0;
 453                adjust->post_cursor[i] = 0;
 454        }
 455
 456        train->pattern = DP_TRAINING_PATTERN_DISABLE;
 457        train->clock_recovered = false;
 458        train->channel_equalized = false;
 459}
 460
 461static bool drm_dp_link_train_valid(const struct drm_dp_link_train *train)
 462{
 463        return train->clock_recovered && train->channel_equalized;
 464}
 465
 466static int drm_dp_link_apply_training(struct drm_dp_link *link)
 467{
 468        struct drm_dp_link_train_set *request = &link->train.request;
 469        unsigned int lanes = link->lanes, *vs, *pe, *pc, i;
 470        struct drm_dp_aux *aux = link->aux;
 471        u8 values[4], pattern = 0;
 472        int err;
 473
 474        err = link->ops->apply_training(link);
 475        if (err < 0) {
 476                DRM_ERROR("failed to apply link training: %d\n", err);
 477                return err;
 478        }
 479
 480        vs = request->voltage_swing;
 481        pe = request->pre_emphasis;
 482        pc = request->post_cursor;
 483
 484        /* write currently selected voltage-swing and pre-emphasis levels */
 485        for (i = 0; i < lanes; i++)
 486                values[i] = DP_TRAIN_VOLTAGE_SWING_LEVEL(vs[i]) |
 487                            DP_TRAIN_PRE_EMPHASIS_LEVEL(pe[i]);
 488
 489        err = drm_dp_dpcd_write(aux, DP_TRAINING_LANE0_SET, values, lanes);
 490        if (err < 0) {
 491                DRM_ERROR("failed to set training parameters: %d\n", err);
 492                return err;
 493        }
 494
 495        /* write currently selected post-cursor level (if supported) */
 496        if (link->revision >= 0x12 && link->rate == 540000) {
 497                values[0] = values[1] = 0;
 498
 499                for (i = 0; i < lanes; i++)
 500                        values[i / 2] |= DP_LANE_POST_CURSOR(i, pc[i]);
 501
 502                err = drm_dp_dpcd_write(aux, DP_TRAINING_LANE0_1_SET2, values,
 503                                        DIV_ROUND_UP(lanes, 2));
 504                if (err < 0) {
 505                        DRM_ERROR("failed to set post-cursor: %d\n", err);
 506                        return err;
 507                }
 508        }
 509
 510        /* write link pattern */
 511        if (link->train.pattern != DP_TRAINING_PATTERN_DISABLE)
 512                pattern |= DP_LINK_SCRAMBLING_DISABLE;
 513
 514        pattern |= link->train.pattern;
 515
 516        err = drm_dp_dpcd_writeb(aux, DP_TRAINING_PATTERN_SET, pattern);
 517        if (err < 0) {
 518                DRM_ERROR("failed to set training pattern: %d\n", err);
 519                return err;
 520        }
 521
 522        return 0;
 523}
 524
 525static void drm_dp_link_train_wait(struct drm_dp_link *link)
 526{
 527        unsigned long min = 0;
 528
 529        switch (link->train.pattern) {
 530        case DP_TRAINING_PATTERN_1:
 531                min = link->aux_rd_interval.cr;
 532                break;
 533
 534        case DP_TRAINING_PATTERN_2:
 535        case DP_TRAINING_PATTERN_3:
 536                min = link->aux_rd_interval.ce;
 537                break;
 538
 539        default:
 540                break;
 541        }
 542
 543        if (min > 0)
 544                usleep_range(min, 2 * min);
 545}
 546
 547static void drm_dp_link_get_adjustments(struct drm_dp_link *link,
 548                                        u8 status[DP_LINK_STATUS_SIZE])
 549{
 550        struct drm_dp_link_train_set *adjust = &link->train.adjust;
 551        unsigned int i;
 552
 553        for (i = 0; i < link->lanes; i++) {
 554                adjust->voltage_swing[i] =
 555                        drm_dp_get_adjust_request_voltage(status, i) >>
 556                                DP_TRAIN_VOLTAGE_SWING_SHIFT;
 557
 558                adjust->pre_emphasis[i] =
 559                        drm_dp_get_adjust_request_pre_emphasis(status, i) >>
 560                                DP_TRAIN_PRE_EMPHASIS_SHIFT;
 561
 562                adjust->post_cursor[i] =
 563                        drm_dp_get_adjust_request_post_cursor(status, i);
 564        }
 565}
 566
 567static void drm_dp_link_train_adjust(struct drm_dp_link_train *train)
 568{
 569        struct drm_dp_link_train_set *request = &train->request;
 570        struct drm_dp_link_train_set *adjust = &train->adjust;
 571        unsigned int i;
 572
 573        for (i = 0; i < 4; i++)
 574                if (request->voltage_swing[i] != adjust->voltage_swing[i])
 575                        request->voltage_swing[i] = adjust->voltage_swing[i];
 576
 577        for (i = 0; i < 4; i++)
 578                if (request->pre_emphasis[i] != adjust->pre_emphasis[i])
 579                        request->pre_emphasis[i] = adjust->pre_emphasis[i];
 580
 581        for (i = 0; i < 4; i++)
 582                if (request->post_cursor[i] != adjust->post_cursor[i])
 583                        request->post_cursor[i] = adjust->post_cursor[i];
 584}
 585
 586static int drm_dp_link_recover_clock(struct drm_dp_link *link)
 587{
 588        u8 status[DP_LINK_STATUS_SIZE];
 589        int err;
 590
 591        err = drm_dp_link_apply_training(link);
 592        if (err < 0)
 593                return err;
 594
 595        drm_dp_link_train_wait(link);
 596
 597        err = drm_dp_dpcd_read_link_status(link->aux, status);
 598        if (err < 0) {
 599                DRM_ERROR("failed to read link status: %d\n", err);
 600                return err;
 601        }
 602
 603        if (!drm_dp_clock_recovery_ok(status, link->lanes))
 604                drm_dp_link_get_adjustments(link, status);
 605        else
 606                link->train.clock_recovered = true;
 607
 608        return 0;
 609}
 610
 611static int drm_dp_link_clock_recovery(struct drm_dp_link *link)
 612{
 613        unsigned int repeat;
 614        int err;
 615
 616        /* start clock recovery using training pattern 1 */
 617        link->train.pattern = DP_TRAINING_PATTERN_1;
 618
 619        for (repeat = 1; repeat < 5; repeat++) {
 620                err = drm_dp_link_recover_clock(link);
 621                if (err < 0) {
 622                        DRM_ERROR("failed to recover clock: %d\n", err);
 623                        return err;
 624                }
 625
 626                if (link->train.clock_recovered)
 627                        break;
 628
 629                drm_dp_link_train_adjust(&link->train);
 630        }
 631
 632        return 0;
 633}
 634
 635static int drm_dp_link_equalize_channel(struct drm_dp_link *link)
 636{
 637        struct drm_dp_aux *aux = link->aux;
 638        u8 status[DP_LINK_STATUS_SIZE];
 639        int err;
 640
 641        err = drm_dp_link_apply_training(link);
 642        if (err < 0)
 643                return err;
 644
 645        drm_dp_link_train_wait(link);
 646
 647        err = drm_dp_dpcd_read_link_status(aux, status);
 648        if (err < 0) {
 649                DRM_ERROR("failed to read link status: %d\n", err);
 650                return err;
 651        }
 652
 653        if (!drm_dp_clock_recovery_ok(status, link->lanes)) {
 654                DRM_ERROR("clock recovery lost while equalizing channel\n");
 655                link->train.clock_recovered = false;
 656                return 0;
 657        }
 658
 659        if (!drm_dp_channel_eq_ok(status, link->lanes))
 660                drm_dp_link_get_adjustments(link, status);
 661        else
 662                link->train.channel_equalized = true;
 663
 664        return 0;
 665}
 666
 667static int drm_dp_link_channel_equalization(struct drm_dp_link *link)
 668{
 669        unsigned int repeat;
 670        int err;
 671
 672        /* start channel equalization using pattern 2 or 3 */
 673        if (link->caps.tps3_supported)
 674                link->train.pattern = DP_TRAINING_PATTERN_3;
 675        else
 676                link->train.pattern = DP_TRAINING_PATTERN_2;
 677
 678        for (repeat = 1; repeat < 5; repeat++) {
 679                err = drm_dp_link_equalize_channel(link);
 680                if (err < 0) {
 681                        DRM_ERROR("failed to equalize channel: %d\n", err);
 682                        return err;
 683                }
 684
 685                if (link->train.channel_equalized)
 686                        break;
 687
 688                drm_dp_link_train_adjust(&link->train);
 689        }
 690
 691        return 0;
 692}
 693
 694static int drm_dp_link_downgrade(struct drm_dp_link *link)
 695{
 696        switch (link->rate) {
 697        case 162000:
 698                return -EINVAL;
 699
 700        case 270000:
 701                link->rate = 162000;
 702                break;
 703
 704        case 540000:
 705                link->rate = 270000;
 706                return 0;
 707        }
 708
 709        return 0;
 710}
 711
 712static void drm_dp_link_train_disable(struct drm_dp_link *link)
 713{
 714        int err;
 715
 716        link->train.pattern = DP_TRAINING_PATTERN_DISABLE;
 717
 718        err = drm_dp_link_apply_training(link);
 719        if (err < 0)
 720                DRM_ERROR("failed to disable link training: %d\n", err);
 721}
 722
 723static int drm_dp_link_train_full(struct drm_dp_link *link)
 724{
 725        int err;
 726
 727retry:
 728        DRM_DEBUG_KMS("full-training link: %u lane%s at %u MHz\n",
 729                      link->lanes, (link->lanes > 1) ? "s" : "",
 730                      link->rate / 100);
 731
 732        err = drm_dp_link_configure(link->aux, link);
 733        if (err < 0) {
 734                DRM_ERROR("failed to configure DP link: %d\n", err);
 735                return err;
 736        }
 737
 738        err = drm_dp_link_clock_recovery(link);
 739        if (err < 0) {
 740                DRM_ERROR("clock recovery failed: %d\n", err);
 741                goto out;
 742        }
 743
 744        if (!link->train.clock_recovered) {
 745                DRM_ERROR("clock recovery failed, downgrading link\n");
 746
 747                err = drm_dp_link_downgrade(link);
 748                if (err < 0)
 749                        goto out;
 750
 751                goto retry;
 752        }
 753
 754        DRM_DEBUG_KMS("clock recovery succeeded\n");
 755
 756        err = drm_dp_link_channel_equalization(link);
 757        if (err < 0) {
 758                DRM_ERROR("channel equalization failed: %d\n", err);
 759                goto out;
 760        }
 761
 762        if (!link->train.channel_equalized) {
 763                DRM_ERROR("channel equalization failed, downgrading link\n");
 764
 765                err = drm_dp_link_downgrade(link);
 766                if (err < 0)
 767                        goto out;
 768
 769                goto retry;
 770        }
 771
 772        DRM_DEBUG_KMS("channel equalization succeeded\n");
 773
 774out:
 775        drm_dp_link_train_disable(link);
 776        return err;
 777}
 778
 779static int drm_dp_link_train_fast(struct drm_dp_link *link)
 780{
 781        u8 status[DP_LINK_STATUS_SIZE];
 782        int err;
 783
 784        DRM_DEBUG_KMS("fast-training link: %u lane%s at %u MHz\n",
 785                      link->lanes, (link->lanes > 1) ? "s" : "",
 786                      link->rate / 100);
 787
 788        err = drm_dp_link_configure(link->aux, link);
 789        if (err < 0) {
 790                DRM_ERROR("failed to configure DP link: %d\n", err);
 791                return err;
 792        }
 793
 794        /* transmit training pattern 1 for 500 microseconds */
 795        link->train.pattern = DP_TRAINING_PATTERN_1;
 796
 797        err = drm_dp_link_apply_training(link);
 798        if (err < 0)
 799                goto out;
 800
 801        usleep_range(500, 1000);
 802
 803        /* transmit training pattern 2 or 3 for 500 microseconds */
 804        if (link->caps.tps3_supported)
 805                link->train.pattern = DP_TRAINING_PATTERN_3;
 806        else
 807                link->train.pattern = DP_TRAINING_PATTERN_2;
 808
 809        err = drm_dp_link_apply_training(link);
 810        if (err < 0)
 811                goto out;
 812
 813        usleep_range(500, 1000);
 814
 815        err = drm_dp_dpcd_read_link_status(link->aux, status);
 816        if (err < 0) {
 817                DRM_ERROR("failed to read link status: %d\n", err);
 818                goto out;
 819        }
 820
 821        if (!drm_dp_clock_recovery_ok(status, link->lanes)) {
 822                DRM_ERROR("clock recovery failed\n");
 823                err = -EIO;
 824        }
 825
 826        if (!drm_dp_channel_eq_ok(status, link->lanes)) {
 827                DRM_ERROR("channel equalization failed\n");
 828                err = -EIO;
 829        }
 830
 831out:
 832        drm_dp_link_train_disable(link);
 833        return err;
 834}
 835
 836/**
 837 * drm_dp_link_train() - perform DisplayPort link training
 838 * @link: a DP link object
 839 *
 840 * Uses the context stored in the DP link object to perform link training. It
 841 * is expected that drivers will call drm_dp_link_probe() to obtain the link
 842 * capabilities before performing link training.
 843 *
 844 * If the sink supports fast link training (no AUX CH handshake) and valid
 845 * training settings are available, this function will try to perform fast
 846 * link training and fall back to full link training on failure.
 847 *
 848 * Returns: 0 on success or a negative error code on failure.
 849 */
 850int drm_dp_link_train(struct drm_dp_link *link)
 851{
 852        int err;
 853
 854        drm_dp_link_train_init(&link->train);
 855
 856        if (link->caps.fast_training) {
 857                if (drm_dp_link_train_valid(&link->train)) {
 858                        err = drm_dp_link_train_fast(link);
 859                        if (err < 0)
 860                                DRM_ERROR("fast link training failed: %d\n",
 861                                          err);
 862                        else
 863                                return 0;
 864                } else {
 865                        DRM_DEBUG_KMS("training parameters not available\n");
 866                }
 867        } else {
 868                DRM_DEBUG_KMS("fast link training not supported\n");
 869        }
 870
 871        err = drm_dp_link_train_full(link);
 872        if (err < 0)
 873                DRM_ERROR("full link training failed: %d\n", err);
 874
 875        return err;
 876}
 877