uboot/drivers/video/tegra124/dp.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2011-2013, NVIDIA Corporation.
   3 * Copyright 2014 Google Inc.
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0
   6 */
   7
   8#include <common.h>
   9#include <display.h>
  10#include <dm.h>
  11#include <div64.h>
  12#include <errno.h>
  13#include <video_bridge.h>
  14#include <asm/io.h>
  15#include <asm/arch-tegra/dc.h>
  16#include "display.h"
  17#include "edid.h"
  18#include "sor.h"
  19#include "displayport.h"
  20
  21DECLARE_GLOBAL_DATA_PTR;
  22
  23#define DO_FAST_LINK_TRAINING           1
  24
  25struct tegra_dp_plat {
  26        ulong base;
  27};
  28
  29/**
  30 * struct tegra_dp_priv - private displayport driver info
  31 *
  32 * @dc_dev:     Display controller device that is sending the video feed
  33 */
  34struct tegra_dp_priv {
  35        struct udevice *sor;
  36        struct udevice *dc_dev;
  37        struct dpaux_ctlr *regs;
  38        u8 revision;
  39        int enabled;
  40};
  41
  42struct tegra_dp_priv dp_data;
  43
  44static inline u32 tegra_dpaux_readl(struct tegra_dp_priv *dp, u32 reg)
  45{
  46        return readl((u32 *)dp->regs + reg);
  47}
  48
  49static inline void tegra_dpaux_writel(struct tegra_dp_priv *dp, u32 reg,
  50                                      u32 val)
  51{
  52        writel(val, (u32 *)dp->regs + reg);
  53}
  54
  55static inline u32 tegra_dc_dpaux_poll_register(struct tegra_dp_priv *dp,
  56                                           u32 reg, u32 mask, u32 exp_val,
  57                                           u32 poll_interval_us,
  58                                           u32 timeout_us)
  59{
  60        u32 reg_val = 0;
  61        u32 temp = timeout_us;
  62
  63        do {
  64                udelay(poll_interval_us);
  65                reg_val = tegra_dpaux_readl(dp, reg);
  66                if (timeout_us > poll_interval_us)
  67                        timeout_us -= poll_interval_us;
  68                else
  69                        break;
  70        } while ((reg_val & mask) != exp_val);
  71
  72        if ((reg_val & mask) == exp_val)
  73                return 0;       /* success */
  74        debug("dpaux_poll_register 0x%x: timeout: (reg_val)0x%08x & (mask)0x%08x != (exp_val)0x%08x\n",
  75              reg, reg_val, mask, exp_val);
  76        return temp;
  77}
  78
  79static inline int tegra_dpaux_wait_transaction(struct tegra_dp_priv *dp)
  80{
  81        /* According to DP spec, each aux transaction needs to finish
  82           within 40ms. */
  83        if (tegra_dc_dpaux_poll_register(dp, DPAUX_DP_AUXCTL,
  84                                         DPAUX_DP_AUXCTL_TRANSACTREQ_MASK,
  85                                         DPAUX_DP_AUXCTL_TRANSACTREQ_DONE,
  86                                         100, DP_AUX_TIMEOUT_MS * 1000) != 0) {
  87                debug("dp: DPAUX transaction timeout\n");
  88                return -1;
  89        }
  90        return 0;
  91}
  92
  93static int tegra_dc_dpaux_write_chunk(struct tegra_dp_priv *dp, u32 cmd,
  94                                          u32 addr, u8 *data, u32 *size,
  95                                          u32 *aux_stat)
  96{
  97        int i;
  98        u32 reg_val;
  99        u32 timeout_retries = DP_AUX_TIMEOUT_MAX_TRIES;
 100        u32 defer_retries = DP_AUX_DEFER_MAX_TRIES;
 101        u32 temp_data;
 102
 103        if (*size > DP_AUX_MAX_BYTES)
 104                return -1;      /* only write one chunk of data */
 105
 106        /* Make sure the command is write command */
 107        switch (cmd) {
 108        case DPAUX_DP_AUXCTL_CMD_I2CWR:
 109        case DPAUX_DP_AUXCTL_CMD_MOTWR:
 110        case DPAUX_DP_AUXCTL_CMD_AUXWR:
 111                break;
 112        default:
 113                debug("dp: aux write cmd 0x%x is invalid\n", cmd);
 114                return -EINVAL;
 115        }
 116
 117        tegra_dpaux_writel(dp, DPAUX_DP_AUXADDR, addr);
 118        for (i = 0; i < DP_AUX_MAX_BYTES / 4; ++i) {
 119                memcpy(&temp_data, data, 4);
 120                tegra_dpaux_writel(dp, DPAUX_DP_AUXDATA_WRITE_W(i), temp_data);
 121                data += 4;
 122        }
 123
 124        reg_val = tegra_dpaux_readl(dp, DPAUX_DP_AUXCTL);
 125        reg_val &= ~DPAUX_DP_AUXCTL_CMD_MASK;
 126        reg_val |= cmd;
 127        reg_val &= ~DPAUX_DP_AUXCTL_CMDLEN_FIELD;
 128        reg_val |= ((*size - 1) << DPAUX_DP_AUXCTL_CMDLEN_SHIFT);
 129
 130        while ((timeout_retries > 0) && (defer_retries > 0)) {
 131                if ((timeout_retries != DP_AUX_TIMEOUT_MAX_TRIES) ||
 132                    (defer_retries != DP_AUX_DEFER_MAX_TRIES))
 133                        udelay(1);
 134
 135                reg_val |= DPAUX_DP_AUXCTL_TRANSACTREQ_PENDING;
 136                tegra_dpaux_writel(dp, DPAUX_DP_AUXCTL, reg_val);
 137
 138                if (tegra_dpaux_wait_transaction(dp))
 139                        debug("dp: aux write transaction timeout\n");
 140
 141                *aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT);
 142
 143                if ((*aux_stat & DPAUX_DP_AUXSTAT_TIMEOUT_ERROR_PENDING) ||
 144                    (*aux_stat & DPAUX_DP_AUXSTAT_RX_ERROR_PENDING) ||
 145                    (*aux_stat & DPAUX_DP_AUXSTAT_SINKSTAT_ERROR_PENDING) ||
 146                    (*aux_stat & DPAUX_DP_AUXSTAT_NO_STOP_ERROR_PENDING)) {
 147                        if (timeout_retries-- > 0) {
 148                                debug("dp: aux write retry (0x%x) -- %d\n",
 149                                      *aux_stat, timeout_retries);
 150                                /* clear the error bits */
 151                                tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT,
 152                                                   *aux_stat);
 153                                continue;
 154                        } else {
 155                                debug("dp: aux write got error (0x%x)\n",
 156                                      *aux_stat);
 157                                return -ETIMEDOUT;
 158                        }
 159                }
 160
 161                if ((*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_I2CDEFER) ||
 162                    (*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_DEFER)) {
 163                        if (defer_retries-- > 0) {
 164                                debug("dp: aux write defer (0x%x) -- %d\n",
 165                                      *aux_stat, defer_retries);
 166                                /* clear the error bits */
 167                                tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT,
 168                                                   *aux_stat);
 169                                continue;
 170                        } else {
 171                                debug("dp: aux write defer exceeds max retries (0x%x)\n",
 172                                      *aux_stat);
 173                                return -ETIMEDOUT;
 174                        }
 175                }
 176
 177                if ((*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_MASK) ==
 178                        DPAUX_DP_AUXSTAT_REPLYTYPE_ACK) {
 179                        *size = ((*aux_stat) & DPAUX_DP_AUXSTAT_REPLY_M_MASK);
 180                        return 0;
 181                } else {
 182                        debug("dp: aux write failed (0x%x)\n", *aux_stat);
 183                        return -EIO;
 184                }
 185        }
 186        /* Should never come to here */
 187        return -EIO;
 188}
 189
 190static int tegra_dc_dpaux_read_chunk(struct tegra_dp_priv *dp, u32 cmd,
 191                                         u32 addr, u8 *data, u32 *size,
 192                                         u32 *aux_stat)
 193{
 194        u32 reg_val;
 195        u32 timeout_retries = DP_AUX_TIMEOUT_MAX_TRIES;
 196        u32 defer_retries = DP_AUX_DEFER_MAX_TRIES;
 197
 198        if (*size > DP_AUX_MAX_BYTES) {
 199                debug("only read one chunk\n");
 200                return -EIO;    /* only read one chunk */
 201        }
 202
 203        /* Check to make sure the command is read command */
 204        switch (cmd) {
 205        case DPAUX_DP_AUXCTL_CMD_I2CRD:
 206        case DPAUX_DP_AUXCTL_CMD_I2CREQWSTAT:
 207        case DPAUX_DP_AUXCTL_CMD_MOTRD:
 208        case DPAUX_DP_AUXCTL_CMD_AUXRD:
 209                break;
 210        default:
 211                debug("dp: aux read cmd 0x%x is invalid\n", cmd);
 212                return -EIO;
 213        }
 214
 215        *aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT);
 216        if (!(*aux_stat & DPAUX_DP_AUXSTAT_HPD_STATUS_PLUGGED)) {
 217                debug("dp: HPD is not detected\n");
 218                return -EIO;
 219        }
 220
 221        tegra_dpaux_writel(dp, DPAUX_DP_AUXADDR, addr);
 222
 223        reg_val = tegra_dpaux_readl(dp, DPAUX_DP_AUXCTL);
 224        reg_val &= ~DPAUX_DP_AUXCTL_CMD_MASK;
 225        reg_val |= cmd;
 226        reg_val &= ~DPAUX_DP_AUXCTL_CMDLEN_FIELD;
 227        reg_val |= ((*size - 1) << DPAUX_DP_AUXCTL_CMDLEN_SHIFT);
 228        while ((timeout_retries > 0) && (defer_retries > 0)) {
 229                if ((timeout_retries != DP_AUX_TIMEOUT_MAX_TRIES) ||
 230                    (defer_retries != DP_AUX_DEFER_MAX_TRIES))
 231                        udelay(DP_DPCP_RETRY_SLEEP_NS * 2);
 232
 233                reg_val |= DPAUX_DP_AUXCTL_TRANSACTREQ_PENDING;
 234                tegra_dpaux_writel(dp, DPAUX_DP_AUXCTL, reg_val);
 235
 236                if (tegra_dpaux_wait_transaction(dp))
 237                        debug("dp: aux read transaction timeout\n");
 238
 239                *aux_stat = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT);
 240
 241                if ((*aux_stat & DPAUX_DP_AUXSTAT_TIMEOUT_ERROR_PENDING) ||
 242                    (*aux_stat & DPAUX_DP_AUXSTAT_RX_ERROR_PENDING) ||
 243                    (*aux_stat & DPAUX_DP_AUXSTAT_SINKSTAT_ERROR_PENDING) ||
 244                    (*aux_stat & DPAUX_DP_AUXSTAT_NO_STOP_ERROR_PENDING)) {
 245                        if (timeout_retries-- > 0) {
 246                                debug("dp: aux read retry (0x%x) -- %d\n",
 247                                      *aux_stat, timeout_retries);
 248                                /* clear the error bits */
 249                                tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT,
 250                                                   *aux_stat);
 251                                continue;       /* retry */
 252                        } else {
 253                                debug("dp: aux read got error (0x%x)\n",
 254                                      *aux_stat);
 255                                return -ETIMEDOUT;
 256                        }
 257                }
 258
 259                if ((*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_I2CDEFER) ||
 260                    (*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_DEFER)) {
 261                        if (defer_retries-- > 0) {
 262                                debug("dp: aux read defer (0x%x) -- %d\n",
 263                                      *aux_stat, defer_retries);
 264                                /* clear the error bits */
 265                                tegra_dpaux_writel(dp, DPAUX_DP_AUXSTAT,
 266                                                   *aux_stat);
 267                                continue;
 268                        } else {
 269                                debug("dp: aux read defer exceeds max retries (0x%x)\n",
 270                                      *aux_stat);
 271                                return -ETIMEDOUT;
 272                        }
 273                }
 274
 275                if ((*aux_stat & DPAUX_DP_AUXSTAT_REPLYTYPE_MASK) ==
 276                        DPAUX_DP_AUXSTAT_REPLYTYPE_ACK) {
 277                        int i;
 278                        u32 temp_data[4];
 279
 280                        for (i = 0; i < DP_AUX_MAX_BYTES / 4; ++i)
 281                                temp_data[i] = tegra_dpaux_readl(dp,
 282                                                DPAUX_DP_AUXDATA_READ_W(i));
 283
 284                        *size = ((*aux_stat) & DPAUX_DP_AUXSTAT_REPLY_M_MASK);
 285                        memcpy(data, temp_data, *size);
 286
 287                        return 0;
 288                } else {
 289                        debug("dp: aux read failed (0x%x\n", *aux_stat);
 290                        return -EIO;
 291                }
 292        }
 293        /* Should never come to here */
 294        debug("%s: can't\n", __func__);
 295
 296        return -EIO;
 297}
 298
 299static int tegra_dc_dpaux_read(struct tegra_dp_priv *dp, u32 cmd, u32 addr,
 300                        u8 *data, u32 *size, u32 *aux_stat)
 301{
 302        u32 finished = 0;
 303        u32 cur_size;
 304        int ret = 0;
 305
 306        do {
 307                cur_size = *size - finished;
 308                if (cur_size > DP_AUX_MAX_BYTES)
 309                        cur_size = DP_AUX_MAX_BYTES;
 310
 311                ret = tegra_dc_dpaux_read_chunk(dp, cmd, addr,
 312                                                data, &cur_size, aux_stat);
 313                if (ret)
 314                        break;
 315
 316                /* cur_size should be the real size returned */
 317                addr += cur_size;
 318                data += cur_size;
 319                finished += cur_size;
 320
 321        } while (*size > finished);
 322        *size = finished;
 323
 324        return ret;
 325}
 326
 327static int tegra_dc_dp_dpcd_read(struct tegra_dp_priv *dp, u32 cmd,
 328                                 u8 *data_ptr)
 329{
 330        u32 size = 1;
 331        u32 status = 0;
 332        int ret;
 333
 334        ret = tegra_dc_dpaux_read_chunk(dp, DPAUX_DP_AUXCTL_CMD_AUXRD,
 335                                        cmd, data_ptr, &size, &status);
 336        if (ret) {
 337                debug("dp: Failed to read DPCD data. CMD 0x%x, Status 0x%x\n",
 338                      cmd, status);
 339        }
 340
 341        return ret;
 342}
 343
 344static int tegra_dc_dp_dpcd_write(struct tegra_dp_priv *dp, u32 cmd,
 345                                u8 data)
 346{
 347        u32 size = 1;
 348        u32 status = 0;
 349        int ret;
 350
 351        ret = tegra_dc_dpaux_write_chunk(dp, DPAUX_DP_AUXCTL_CMD_AUXWR,
 352                                        cmd, &data, &size, &status);
 353        if (ret) {
 354                debug("dp: Failed to write DPCD data. CMD 0x%x, Status 0x%x\n",
 355                      cmd, status);
 356        }
 357
 358        return ret;
 359}
 360
 361static int tegra_dc_i2c_aux_read(struct tegra_dp_priv *dp, u32 i2c_addr,
 362                                 u8 addr, u8 *data, u32 size, u32 *aux_stat)
 363{
 364        u32 finished = 0;
 365        int ret = 0;
 366
 367        do {
 368                u32 cur_size = min((u32)DP_AUX_MAX_BYTES, size - finished);
 369
 370                u32 len = 1;
 371                ret = tegra_dc_dpaux_write_chunk(
 372                                dp, DPAUX_DP_AUXCTL_CMD_MOTWR, i2c_addr,
 373                                &addr, &len, aux_stat);
 374                if (ret) {
 375                        debug("%s: error sending address to read.\n",
 376                              __func__);
 377                        return ret;
 378                }
 379
 380                ret = tegra_dc_dpaux_read_chunk(
 381                                dp, DPAUX_DP_AUXCTL_CMD_I2CRD, i2c_addr,
 382                                data, &cur_size, aux_stat);
 383                if (ret) {
 384                        debug("%s: error reading data.\n", __func__);
 385                        return ret;
 386                }
 387
 388                /* cur_size should be the real size returned */
 389                addr += cur_size;
 390                data += cur_size;
 391                finished += cur_size;
 392        } while (size > finished);
 393
 394        return finished;
 395}
 396
 397static void tegra_dc_dpaux_enable(struct tegra_dp_priv *dp)
 398{
 399        /* clear interrupt */
 400        tegra_dpaux_writel(dp, DPAUX_INTR_AUX, 0xffffffff);
 401        /* do not enable interrupt for now. Enable them when Isr in place */
 402        tegra_dpaux_writel(dp, DPAUX_INTR_EN_AUX, 0x0);
 403
 404        tegra_dpaux_writel(dp, DPAUX_HYBRID_PADCTL,
 405                           DPAUX_HYBRID_PADCTL_AUX_DRVZ_OHM_50 |
 406                           DPAUX_HYBRID_PADCTL_AUX_CMH_V0_70 |
 407                           0x18 << DPAUX_HYBRID_PADCTL_AUX_DRVI_SHIFT |
 408                           DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV_ENABLE);
 409
 410        tegra_dpaux_writel(dp, DPAUX_HYBRID_SPARE,
 411                           DPAUX_HYBRID_SPARE_PAD_PWR_POWERUP);
 412}
 413
 414#ifdef DEBUG
 415static void tegra_dc_dp_dump_link_cfg(struct tegra_dp_priv *dp,
 416        const struct tegra_dp_link_config *link_cfg)
 417{
 418        debug("DP config: cfg_name               cfg_value\n");
 419        debug("           Lane Count             %d\n",
 420              link_cfg->max_lane_count);
 421        debug("           SupportEnhancedFraming %s\n",
 422              link_cfg->support_enhanced_framing ? "Y" : "N");
 423        debug("           Bandwidth              %d\n",
 424              link_cfg->max_link_bw);
 425        debug("           bpp                    %d\n",
 426              link_cfg->bits_per_pixel);
 427        debug("           EnhancedFraming        %s\n",
 428              link_cfg->enhanced_framing ? "Y" : "N");
 429        debug("           Scramble_enabled       %s\n",
 430              link_cfg->scramble_ena ? "Y" : "N");
 431        debug("           LinkBW                 %d\n",
 432              link_cfg->link_bw);
 433        debug("           lane_count             %d\n",
 434              link_cfg->lane_count);
 435        debug("           activespolarity        %d\n",
 436              link_cfg->activepolarity);
 437        debug("           active_count           %d\n",
 438              link_cfg->active_count);
 439        debug("           tu_size                %d\n",
 440              link_cfg->tu_size);
 441        debug("           active_frac            %d\n",
 442              link_cfg->active_frac);
 443        debug("           watermark              %d\n",
 444              link_cfg->watermark);
 445        debug("           hblank_sym             %d\n",
 446              link_cfg->hblank_sym);
 447        debug("           vblank_sym             %d\n",
 448              link_cfg->vblank_sym);
 449}
 450#endif
 451
 452static int _tegra_dp_lower_link_config(struct tegra_dp_priv *dp,
 453                                       struct tegra_dp_link_config *cfg)
 454{
 455        switch (cfg->link_bw) {
 456        case SOR_LINK_SPEED_G1_62:
 457                if (cfg->max_link_bw > SOR_LINK_SPEED_G1_62)
 458                        cfg->link_bw = SOR_LINK_SPEED_G2_7;
 459                cfg->lane_count /= 2;
 460                break;
 461        case SOR_LINK_SPEED_G2_7:
 462                cfg->link_bw = SOR_LINK_SPEED_G1_62;
 463                break;
 464        case SOR_LINK_SPEED_G5_4:
 465                if (cfg->lane_count == 1) {
 466                        cfg->link_bw = SOR_LINK_SPEED_G2_7;
 467                        cfg->lane_count = cfg->max_lane_count;
 468                } else {
 469                        cfg->lane_count /= 2;
 470                }
 471                break;
 472        default:
 473                debug("dp: Error link rate %d\n", cfg->link_bw);
 474                return -ENOLINK;
 475        }
 476
 477        return (cfg->lane_count > 0) ? 0 : -ENOLINK;
 478}
 479
 480/*
 481 * Calcuate if given cfg can meet the mode request.
 482 * Return 0 if mode is possible, -1 otherwise
 483 */
 484static int tegra_dc_dp_calc_config(struct tegra_dp_priv *dp,
 485                                   const struct display_timing *timing,
 486                                   struct tegra_dp_link_config *link_cfg)
 487{
 488        const u32       link_rate = 27 * link_cfg->link_bw * 1000 * 1000;
 489        const u64       f         = 100000;     /* precision factor */
 490        u32     num_linkclk_line; /* Number of link clocks per line */
 491        u64     ratio_f; /* Ratio of incoming to outgoing data rate */
 492        u64     frac_f;
 493        u64     activesym_f;    /* Activesym per TU */
 494        u64     activecount_f;
 495        u32     activecount;
 496        u32     activepolarity;
 497        u64     approx_value_f;
 498        u32     activefrac                = 0;
 499        u64     accumulated_error_f       = 0;
 500        u32     lowest_neg_activecount    = 0;
 501        u32     lowest_neg_activepolarity = 0;
 502        u32     lowest_neg_tusize         = 64;
 503        u32     num_symbols_per_line;
 504        u64     lowest_neg_activefrac     = 0;
 505        u64     lowest_neg_error_f        = 64 * f;
 506        u64     watermark_f;
 507        int     i;
 508        int     neg;
 509
 510        if (!link_rate || !link_cfg->lane_count || !timing->pixelclock.typ ||
 511            !link_cfg->bits_per_pixel)
 512                return -1;
 513
 514        if ((u64)timing->pixelclock.typ * link_cfg->bits_per_pixel >=
 515                (u64)link_rate * 8 * link_cfg->lane_count)
 516                return -1;
 517
 518        num_linkclk_line = (u32)(lldiv(link_rate * timing->hactive.typ,
 519                                       timing->pixelclock.typ));
 520
 521        ratio_f = (u64)timing->pixelclock.typ * link_cfg->bits_per_pixel * f;
 522        ratio_f /= 8;
 523        do_div(ratio_f, link_rate * link_cfg->lane_count);
 524
 525        for (i = 64; i >= 32; --i) {
 526                activesym_f     = ratio_f * i;
 527                activecount_f   = lldiv(activesym_f, (u32)f) * f;
 528                frac_f          = activesym_f - activecount_f;
 529                activecount     = (u32)(lldiv(activecount_f, (u32)f));
 530
 531                if (frac_f < (lldiv(f, 2))) /* fraction < 0.5 */
 532                        activepolarity = 0;
 533                else {
 534                        activepolarity = 1;
 535                        frac_f = f - frac_f;
 536                }
 537
 538                if (frac_f != 0) {
 539                        /* warning: frac_f should be 64-bit */
 540                        frac_f = lldiv(f * f, frac_f); /* 1 / fraction */
 541                        if (frac_f > (15 * f))
 542                                activefrac = activepolarity ? 1 : 15;
 543                        else
 544                                activefrac = activepolarity ?
 545                                        (u32)lldiv(frac_f, (u32)f) + 1 :
 546                                        (u32)lldiv(frac_f, (u32)f);
 547                }
 548
 549                if (activefrac == 1)
 550                        activepolarity = 0;
 551
 552                if (activepolarity == 1)
 553                        approx_value_f = activefrac ? lldiv(
 554                                (activecount_f + (activefrac * f - f) * f),
 555                                (activefrac * f)) :
 556                                activecount_f + f;
 557                else
 558                        approx_value_f = activefrac ?
 559                                activecount_f + lldiv(f, activefrac) :
 560                                activecount_f;
 561
 562                if (activesym_f < approx_value_f) {
 563                        accumulated_error_f = num_linkclk_line *
 564                                lldiv(approx_value_f - activesym_f, i);
 565                        neg = 1;
 566                } else {
 567                        accumulated_error_f = num_linkclk_line *
 568                                lldiv(activesym_f - approx_value_f, i);
 569                        neg = 0;
 570                }
 571
 572                if ((neg && (lowest_neg_error_f > accumulated_error_f)) ||
 573                    (accumulated_error_f == 0)) {
 574                        lowest_neg_error_f = accumulated_error_f;
 575                        lowest_neg_tusize = i;
 576                        lowest_neg_activecount = activecount;
 577                        lowest_neg_activepolarity = activepolarity;
 578                        lowest_neg_activefrac = activefrac;
 579
 580                        if (accumulated_error_f == 0)
 581                                break;
 582                }
 583        }
 584
 585        if (lowest_neg_activefrac == 0) {
 586                link_cfg->activepolarity = 0;
 587                link_cfg->active_count   = lowest_neg_activepolarity ?
 588                        lowest_neg_activecount : lowest_neg_activecount - 1;
 589                link_cfg->tu_size             = lowest_neg_tusize;
 590                link_cfg->active_frac    = 1;
 591        } else {
 592                link_cfg->activepolarity = lowest_neg_activepolarity;
 593                link_cfg->active_count   = (u32)lowest_neg_activecount;
 594                link_cfg->tu_size             = lowest_neg_tusize;
 595                link_cfg->active_frac    = (u32)lowest_neg_activefrac;
 596        }
 597
 598        watermark_f = lldiv(ratio_f * link_cfg->tu_size * (f - ratio_f), f);
 599        link_cfg->watermark = (u32)(lldiv(watermark_f + lowest_neg_error_f,
 600                f)) + link_cfg->bits_per_pixel / 4 - 1;
 601        num_symbols_per_line = (timing->hactive.typ *
 602                                link_cfg->bits_per_pixel) /
 603                               (8 * link_cfg->lane_count);
 604
 605        if (link_cfg->watermark > 30) {
 606                debug("dp: sor setting: unable to get a good tusize, force watermark to 30\n");
 607                link_cfg->watermark = 30;
 608                return -1;
 609        } else if (link_cfg->watermark > num_symbols_per_line) {
 610                debug("dp: sor setting: force watermark to the number of symbols in the line\n");
 611                link_cfg->watermark = num_symbols_per_line;
 612                return -1;
 613        }
 614
 615        /*
 616         * Refer to dev_disp.ref for more information.
 617         * # symbols/hblank = ((SetRasterBlankEnd.X + SetRasterSize.Width -
 618         *                      SetRasterBlankStart.X - 7) * link_clk / pclk)
 619         *                      - 3 * enhanced_framing - Y
 620         * where Y = (# lanes == 4) 3 : (# lanes == 2) ? 6 : 12
 621         */
 622        link_cfg->hblank_sym = (int)lldiv(((uint64_t)timing->hback_porch.typ +
 623                        timing->hfront_porch.typ + timing->hsync_len.typ - 7) *
 624                        link_rate, timing->pixelclock.typ) -
 625                        3 * link_cfg->enhanced_framing -
 626                        (12 / link_cfg->lane_count);
 627
 628        if (link_cfg->hblank_sym < 0)
 629                link_cfg->hblank_sym = 0;
 630
 631
 632        /*
 633         * Refer to dev_disp.ref for more information.
 634         * # symbols/vblank = ((SetRasterBlankStart.X -
 635         *                      SetRasterBlankEen.X - 25) * link_clk / pclk)
 636         *                      - Y - 1;
 637         * where Y = (# lanes == 4) 12 : (# lanes == 2) ? 21 : 39
 638         */
 639        link_cfg->vblank_sym = (int)lldiv(((uint64_t)timing->hactive.typ - 25)
 640                        * link_rate, timing->pixelclock.typ) - (36 /
 641                        link_cfg->lane_count) - 4;
 642
 643        if (link_cfg->vblank_sym < 0)
 644                link_cfg->vblank_sym = 0;
 645
 646        link_cfg->is_valid = 1;
 647#ifdef DEBUG
 648        tegra_dc_dp_dump_link_cfg(dp, link_cfg);
 649#endif
 650
 651        return 0;
 652}
 653
 654static int tegra_dc_dp_init_max_link_cfg(
 655                        const struct display_timing *timing,
 656                        struct tegra_dp_priv *dp,
 657                        struct tegra_dp_link_config *link_cfg)
 658{
 659        const int drive_current = 0x40404040;
 660        const int preemphasis = 0x0f0f0f0f;
 661        const int postcursor = 0;
 662        u8 dpcd_data;
 663        int ret;
 664
 665        ret = tegra_dc_dp_dpcd_read(dp, DP_MAX_LANE_COUNT, &dpcd_data);
 666        if (ret)
 667                return ret;
 668        link_cfg->max_lane_count = dpcd_data & DP_MAX_LANE_COUNT_MASK;
 669        link_cfg->tps3_supported = (dpcd_data &
 670                        DP_MAX_LANE_COUNT_TPS3_SUPPORTED_YES) ? 1 : 0;
 671
 672        link_cfg->support_enhanced_framing =
 673                (dpcd_data & DP_MAX_LANE_COUNT_ENHANCED_FRAMING_YES) ?
 674                1 : 0;
 675
 676        ret = tegra_dc_dp_dpcd_read(dp, DP_MAX_DOWNSPREAD, &dpcd_data);
 677        if (ret)
 678                return ret;
 679        link_cfg->downspread = (dpcd_data & DP_MAX_DOWNSPREAD_VAL_0_5_PCT) ?
 680                                1 : 0;
 681
 682        ret = tegra_dc_dp_dpcd_read(dp, NV_DPCD_TRAINING_AUX_RD_INTERVAL,
 683                                    &link_cfg->aux_rd_interval);
 684        if (ret)
 685                return ret;
 686        ret = tegra_dc_dp_dpcd_read(dp, DP_MAX_LINK_RATE,
 687                                    &link_cfg->max_link_bw);
 688        if (ret)
 689                return ret;
 690
 691        /*
 692         * Set to a high value for link training and attach.
 693         * Will be re-programmed when dp is enabled.
 694         */
 695        link_cfg->drive_current = drive_current;
 696        link_cfg->preemphasis = preemphasis;
 697        link_cfg->postcursor = postcursor;
 698
 699        ret = tegra_dc_dp_dpcd_read(dp, DP_EDP_CONFIGURATION_CAP, &dpcd_data);
 700        if (ret)
 701                return ret;
 702
 703        link_cfg->alt_scramber_reset_cap =
 704                (dpcd_data & DP_EDP_CONFIGURATION_CAP_ASC_RESET_YES) ?
 705                1 : 0;
 706        link_cfg->only_enhanced_framing =
 707                (dpcd_data & DP_EDP_CONFIGURATION_CAP_FRAMING_CHANGE_YES) ?
 708                1 : 0;
 709
 710        link_cfg->lane_count = link_cfg->max_lane_count;
 711        link_cfg->link_bw = link_cfg->max_link_bw;
 712        link_cfg->enhanced_framing = link_cfg->support_enhanced_framing;
 713        link_cfg->frame_in_ms = (1000 / 60) + 1;
 714
 715        tegra_dc_dp_calc_config(dp, timing, link_cfg);
 716        return 0;
 717}
 718
 719static int tegra_dc_dp_set_assr(struct tegra_dp_priv *priv,
 720                                struct udevice *sor, int ena)
 721{
 722        int ret;
 723
 724        u8 dpcd_data = ena ?
 725                DP_MAIN_LINK_CHANNEL_CODING_SET_ASC_RESET_ENABLE :
 726                DP_MAIN_LINK_CHANNEL_CODING_SET_ASC_RESET_DISABLE;
 727
 728        ret = tegra_dc_dp_dpcd_write(priv, DP_EDP_CONFIGURATION_SET,
 729                                     dpcd_data);
 730        if (ret)
 731                return ret;
 732
 733        /* Also reset the scrambler to 0xfffe */
 734        tegra_dc_sor_set_internal_panel(sor, ena);
 735        return 0;
 736}
 737
 738static int tegra_dp_set_link_bandwidth(struct tegra_dp_priv *dp,
 739                                       struct udevice *sor,
 740                                       u8 link_bw)
 741{
 742        tegra_dc_sor_set_link_bandwidth(sor, link_bw);
 743
 744        /* Sink side */
 745        return tegra_dc_dp_dpcd_write(dp, DP_LINK_BW_SET, link_bw);
 746}
 747
 748static int tegra_dp_set_lane_count(struct tegra_dp_priv *dp,
 749                const struct tegra_dp_link_config *link_cfg,
 750                struct udevice *sor)
 751{
 752        u8      dpcd_data;
 753        int     ret;
 754
 755        /* check if panel support enhanched_framing */
 756        dpcd_data = link_cfg->lane_count;
 757        if (link_cfg->enhanced_framing)
 758                dpcd_data |= DP_LANE_COUNT_SET_ENHANCEDFRAMING_T;
 759        ret = tegra_dc_dp_dpcd_write(dp, DP_LANE_COUNT_SET, dpcd_data);
 760        if (ret)
 761                return ret;
 762
 763        tegra_dc_sor_set_lane_count(sor, link_cfg->lane_count);
 764
 765        /* Also power down lanes that will not be used */
 766        return 0;
 767}
 768
 769static int tegra_dc_dp_link_trained(struct tegra_dp_priv *dp,
 770                                    const struct tegra_dp_link_config *cfg)
 771{
 772        u32 lane;
 773        u8 mask;
 774        u8 data;
 775        int ret;
 776
 777        for (lane = 0; lane < cfg->lane_count; ++lane) {
 778                ret = tegra_dc_dp_dpcd_read(dp, (lane / 2) ?
 779                                DP_LANE2_3_STATUS : DP_LANE0_1_STATUS,
 780                                &data);
 781                if (ret)
 782                        return ret;
 783                mask = (lane & 1) ?
 784                        NV_DPCD_STATUS_LANEXPLUS1_CR_DONE_YES |
 785                        NV_DPCD_STATUS_LANEXPLUS1_CHN_EQ_DONE_YES |
 786                        NV_DPCD_STATUS_LANEXPLUS1_SYMBOL_LOCKED_YES :
 787                        DP_LANE_CR_DONE |
 788                        DP_LANE_CHANNEL_EQ_DONE |
 789                        DP_LANE_SYMBOL_LOCKED;
 790                if ((data & mask) != mask)
 791                        return -1;
 792        }
 793        return 0;
 794}
 795
 796static int tegra_dp_channel_eq_status(struct tegra_dp_priv *dp,
 797                                      const struct tegra_dp_link_config *cfg)
 798{
 799        u32 cnt;
 800        u32 n_lanes = cfg->lane_count;
 801        u8 data;
 802        u8 ce_done = 1;
 803        int ret;
 804
 805        for (cnt = 0; cnt < n_lanes / 2; cnt++) {
 806                ret = tegra_dc_dp_dpcd_read(dp, DP_LANE0_1_STATUS + cnt, &data);
 807                if (ret)
 808                        return ret;
 809
 810                if (n_lanes == 1) {
 811                        ce_done = (data & (0x1 <<
 812                        NV_DPCD_STATUS_LANEX_CHN_EQ_DONE_SHIFT)) &&
 813                        (data & (0x1 <<
 814                        NV_DPCD_STATUS_LANEX_SYMBOL_LOCKED_SHFIT));
 815                        break;
 816                } else if (!(data & (0x1 <<
 817                                NV_DPCD_STATUS_LANEX_CHN_EQ_DONE_SHIFT)) ||
 818                           !(data & (0x1 <<
 819                                NV_DPCD_STATUS_LANEX_SYMBOL_LOCKED_SHFIT)) ||
 820                           !(data & (0x1 <<
 821                                NV_DPCD_STATUS_LANEXPLUS1_CHN_EQ_DONE_SHIFT)) ||
 822                           !(data & (0x1 <<
 823                                NV_DPCD_STATUS_LANEXPLUS1_SYMBOL_LOCKED_SHIFT)))
 824                        return -EIO;
 825        }
 826
 827        if (ce_done) {
 828                ret = tegra_dc_dp_dpcd_read(dp,
 829                                            DP_LANE_ALIGN_STATUS_UPDATED,
 830                                            &data);
 831                if (ret)
 832                        return ret;
 833                if (!(data & NV_DPCD_LANE_ALIGN_STATUS_UPDATED_DONE_YES))
 834                        ce_done = 0;
 835        }
 836
 837        return ce_done ? 0 : -EIO;
 838}
 839
 840static int tegra_dp_clock_recovery_status(struct tegra_dp_priv *dp,
 841                                         const struct tegra_dp_link_config *cfg)
 842{
 843        u32 cnt;
 844        u32 n_lanes = cfg->lane_count;
 845        u8 data_ptr;
 846        int ret;
 847
 848        for (cnt = 0; cnt < n_lanes / 2; cnt++) {
 849                ret = tegra_dc_dp_dpcd_read(dp, (DP_LANE0_1_STATUS + cnt),
 850                                            &data_ptr);
 851                if (ret)
 852                        return ret;
 853
 854                if (n_lanes == 1)
 855                        return (data_ptr & NV_DPCD_STATUS_LANEX_CR_DONE_YES) ?
 856                                1 : 0;
 857                else if (!(data_ptr & NV_DPCD_STATUS_LANEX_CR_DONE_YES) ||
 858                         !(data_ptr & (NV_DPCD_STATUS_LANEXPLUS1_CR_DONE_YES)))
 859                        return 0;
 860        }
 861
 862        return 1;
 863}
 864
 865static int tegra_dp_lt_adjust(struct tegra_dp_priv *dp, u32 pe[4], u32 vs[4],
 866                              u32 pc[4], u8 pc_supported,
 867                              const struct tegra_dp_link_config *cfg)
 868{
 869        size_t cnt;
 870        u8 data_ptr;
 871        u32 n_lanes = cfg->lane_count;
 872        int ret;
 873
 874        for (cnt = 0; cnt < n_lanes / 2; cnt++) {
 875                ret = tegra_dc_dp_dpcd_read(dp, DP_ADJUST_REQUEST_LANE0_1 + cnt,
 876                                            &data_ptr);
 877                if (ret)
 878                        return ret;
 879                pe[2 * cnt] = (data_ptr & NV_DPCD_ADJUST_REQ_LANEX_PE_MASK) >>
 880                                        NV_DPCD_ADJUST_REQ_LANEX_PE_SHIFT;
 881                vs[2 * cnt] = (data_ptr & NV_DPCD_ADJUST_REQ_LANEX_DC_MASK) >>
 882                                        NV_DPCD_ADJUST_REQ_LANEX_DC_SHIFT;
 883                pe[1 + 2 * cnt] =
 884                        (data_ptr & NV_DPCD_ADJUST_REQ_LANEXPLUS1_PE_MASK) >>
 885                                        NV_DPCD_ADJUST_REQ_LANEXPLUS1_PE_SHIFT;
 886                vs[1 + 2 * cnt] =
 887                        (data_ptr & NV_DPCD_ADJUST_REQ_LANEXPLUS1_DC_MASK) >>
 888                                        NV_DPCD_ADJUST_REQ_LANEXPLUS1_DC_SHIFT;
 889        }
 890        if (pc_supported) {
 891                ret = tegra_dc_dp_dpcd_read(dp, NV_DPCD_ADJUST_REQ_POST_CURSOR2,
 892                                            &data_ptr);
 893                if (ret)
 894                        return ret;
 895                for (cnt = 0; cnt < n_lanes; cnt++) {
 896                        pc[cnt] = (data_ptr >>
 897                        NV_DPCD_ADJUST_REQ_POST_CURSOR2_LANE_SHIFT(cnt)) &
 898                        NV_DPCD_ADJUST_REQ_POST_CURSOR2_LANE_MASK;
 899                }
 900        }
 901
 902        return 0;
 903}
 904
 905static void tegra_dp_wait_aux_training(struct tegra_dp_priv *dp,
 906                                        bool is_clk_recovery,
 907                                        const struct tegra_dp_link_config *cfg)
 908{
 909        if (!cfg->aux_rd_interval)
 910                udelay(is_clk_recovery ? 200 : 500);
 911        else
 912                mdelay(cfg->aux_rd_interval * 4);
 913}
 914
 915static void tegra_dp_tpg(struct tegra_dp_priv *dp, u32 tp, u32 n_lanes,
 916                         const struct tegra_dp_link_config *cfg)
 917{
 918        u8 data = (tp == training_pattern_disabled)
 919                ? (tp | NV_DPCD_TRAINING_PATTERN_SET_SC_DISABLED_F)
 920                : (tp | NV_DPCD_TRAINING_PATTERN_SET_SC_DISABLED_T);
 921
 922        tegra_dc_sor_set_dp_linkctl(dp->sor, 1, tp, cfg);
 923        tegra_dc_dp_dpcd_write(dp, DP_TRAINING_PATTERN_SET, data);
 924}
 925
 926static int tegra_dp_link_config(struct tegra_dp_priv *dp,
 927                                const struct tegra_dp_link_config *link_cfg)
 928{
 929        u8 dpcd_data;
 930        u32 retry;
 931        int ret;
 932
 933        if (link_cfg->lane_count == 0) {
 934                debug("dp: error: lane count is 0. Can not set link config.\n");
 935                return -ENOLINK;
 936        }
 937
 938        /* Set power state if it is not in normal level */
 939        ret = tegra_dc_dp_dpcd_read(dp, DP_SET_POWER, &dpcd_data);
 940        if (ret)
 941                return ret;
 942
 943        if (dpcd_data == DP_SET_POWER_D3) {
 944                dpcd_data = DP_SET_POWER_D0;
 945
 946                /* DP spec requires 3 retries */
 947                for (retry = 3; retry > 0; --retry) {
 948                        ret = tegra_dc_dp_dpcd_write(dp, DP_SET_POWER,
 949                                                     dpcd_data);
 950                        if (!ret)
 951                                break;
 952                        if (retry == 1) {
 953                                debug("dp: Failed to set DP panel power\n");
 954                                return ret;
 955                        }
 956                }
 957        }
 958
 959        /* Enable ASSR if possible */
 960        if (link_cfg->alt_scramber_reset_cap) {
 961                ret = tegra_dc_dp_set_assr(dp, dp->sor, 1);
 962                if (ret)
 963                        return ret;
 964        }
 965
 966        ret = tegra_dp_set_link_bandwidth(dp, dp->sor, link_cfg->link_bw);
 967        if (ret) {
 968                debug("dp: Failed to set link bandwidth\n");
 969                return ret;
 970        }
 971        ret = tegra_dp_set_lane_count(dp, link_cfg, dp->sor);
 972        if (ret) {
 973                debug("dp: Failed to set lane count\n");
 974                return ret;
 975        }
 976        tegra_dc_sor_set_dp_linkctl(dp->sor, 1, training_pattern_none,
 977                                    link_cfg);
 978
 979        return 0;
 980}
 981
 982static int tegra_dp_lower_link_config(struct tegra_dp_priv *dp,
 983                                      const struct display_timing *timing,
 984                                      struct tegra_dp_link_config *cfg)
 985{
 986        struct tegra_dp_link_config tmp_cfg;
 987        int ret;
 988
 989        tmp_cfg = *cfg;
 990        cfg->is_valid = 0;
 991
 992        ret = _tegra_dp_lower_link_config(dp, cfg);
 993        if (!ret)
 994                ret = tegra_dc_dp_calc_config(dp, timing, cfg);
 995        if (!ret)
 996                ret = tegra_dp_link_config(dp, cfg);
 997        if (ret)
 998                goto fail;
 999
1000        return 0;
1001
1002fail:
1003        *cfg = tmp_cfg;
1004        tegra_dp_link_config(dp, &tmp_cfg);
1005        return ret;
1006}
1007
1008static int tegra_dp_lt_config(struct tegra_dp_priv *dp, u32 pe[4], u32 vs[4],
1009                              u32 pc[4], const struct tegra_dp_link_config *cfg)
1010{
1011        struct udevice *sor = dp->sor;
1012        u32 n_lanes = cfg->lane_count;
1013        u8 pc_supported = cfg->tps3_supported;
1014        u32 cnt;
1015        u32 val;
1016
1017        for (cnt = 0; cnt < n_lanes; cnt++) {
1018                u32 mask = 0;
1019                u32 pe_reg, vs_reg, pc_reg;
1020                u32 shift = 0;
1021
1022                switch (cnt) {
1023                case 0:
1024                        mask = PR_LANE2_DP_LANE0_MASK;
1025                        shift = PR_LANE2_DP_LANE0_SHIFT;
1026                        break;
1027                case 1:
1028                        mask = PR_LANE1_DP_LANE1_MASK;
1029                        shift = PR_LANE1_DP_LANE1_SHIFT;
1030                        break;
1031                case 2:
1032                        mask = PR_LANE0_DP_LANE2_MASK;
1033                        shift = PR_LANE0_DP_LANE2_SHIFT;
1034                        break;
1035                case 3:
1036                        mask = PR_LANE3_DP_LANE3_MASK;
1037                        shift = PR_LANE3_DP_LANE3_SHIFT;
1038                        break;
1039                default:
1040                        debug("dp: incorrect lane cnt\n");
1041                        return -EINVAL;
1042                }
1043
1044                pe_reg = tegra_dp_pe_regs[pc[cnt]][vs[cnt]][pe[cnt]];
1045                vs_reg = tegra_dp_vs_regs[pc[cnt]][vs[cnt]][pe[cnt]];
1046                pc_reg = tegra_dp_pc_regs[pc[cnt]][vs[cnt]][pe[cnt]];
1047
1048                tegra_dp_set_pe_vs_pc(sor, mask, pe_reg << shift,
1049                                      vs_reg << shift, pc_reg << shift,
1050                                      pc_supported);
1051        }
1052
1053        tegra_dp_disable_tx_pu(dp->sor);
1054        udelay(20);
1055
1056        for (cnt = 0; cnt < n_lanes; cnt++) {
1057                u32 max_vs_flag = tegra_dp_is_max_vs(pe[cnt], vs[cnt]);
1058                u32 max_pe_flag = tegra_dp_is_max_pe(pe[cnt], vs[cnt]);
1059
1060                val = (vs[cnt] << NV_DPCD_TRAINING_LANEX_SET_DC_SHIFT) |
1061                        (max_vs_flag ?
1062                        NV_DPCD_TRAINING_LANEX_SET_DC_MAX_REACHED_T :
1063                        NV_DPCD_TRAINING_LANEX_SET_DC_MAX_REACHED_F) |
1064                        (pe[cnt] << NV_DPCD_TRAINING_LANEX_SET_PE_SHIFT) |
1065                        (max_pe_flag ?
1066                        NV_DPCD_TRAINING_LANEX_SET_PE_MAX_REACHED_T :
1067                        NV_DPCD_TRAINING_LANEX_SET_PE_MAX_REACHED_F);
1068                tegra_dc_dp_dpcd_write(dp, (DP_TRAINING_LANE0_SET + cnt), val);
1069        }
1070
1071        if (pc_supported) {
1072                for (cnt = 0; cnt < n_lanes / 2; cnt++) {
1073                        u32 max_pc_flag0 = tegra_dp_is_max_pc(pc[cnt]);
1074                        u32 max_pc_flag1 = tegra_dp_is_max_pc(pc[cnt + 1]);
1075                        val = (pc[cnt] << NV_DPCD_LANEX_SET2_PC2_SHIFT) |
1076                                (max_pc_flag0 ?
1077                                NV_DPCD_LANEX_SET2_PC2_MAX_REACHED_T :
1078                                NV_DPCD_LANEX_SET2_PC2_MAX_REACHED_F) |
1079                                (pc[cnt + 1] <<
1080                                NV_DPCD_LANEXPLUS1_SET2_PC2_SHIFT) |
1081                                (max_pc_flag1 ?
1082                                NV_DPCD_LANEXPLUS1_SET2_PC2_MAX_REACHED_T :
1083                                NV_DPCD_LANEXPLUS1_SET2_PC2_MAX_REACHED_F);
1084                        tegra_dc_dp_dpcd_write(dp,
1085                                               NV_DPCD_TRAINING_LANE0_1_SET2 +
1086                                               cnt, val);
1087                }
1088        }
1089
1090        return 0;
1091}
1092
1093static int _tegra_dp_channel_eq(struct tegra_dp_priv *dp, u32 pe[4],
1094                                u32 vs[4], u32 pc[4], u8 pc_supported,
1095                                u32 n_lanes,
1096                                const struct tegra_dp_link_config *cfg)
1097{
1098        u32 retry_cnt;
1099
1100        for (retry_cnt = 0; retry_cnt < 4; retry_cnt++) {
1101                int ret;
1102
1103                if (retry_cnt) {
1104                        ret = tegra_dp_lt_adjust(dp, pe, vs, pc, pc_supported,
1105                                                 cfg);
1106                        if (ret)
1107                                return ret;
1108                        tegra_dp_lt_config(dp, pe, vs, pc, cfg);
1109                }
1110
1111                tegra_dp_wait_aux_training(dp, false, cfg);
1112
1113                if (!tegra_dp_clock_recovery_status(dp, cfg)) {
1114                        debug("dp: CR failed in channel EQ sequence!\n");
1115                        break;
1116                }
1117
1118                if (!tegra_dp_channel_eq_status(dp, cfg))
1119                        return 0;
1120        }
1121
1122        return -EIO;
1123}
1124
1125static int tegra_dp_channel_eq(struct tegra_dp_priv *dp, u32 pe[4], u32 vs[4],
1126                               u32 pc[4],
1127                               const struct tegra_dp_link_config *cfg)
1128{
1129        u32 n_lanes = cfg->lane_count;
1130        u8 pc_supported = cfg->tps3_supported;
1131        int ret;
1132        u32 tp_src = training_pattern_2;
1133
1134        if (pc_supported)
1135                tp_src = training_pattern_3;
1136
1137        tegra_dp_tpg(dp, tp_src, n_lanes, cfg);
1138
1139        ret = _tegra_dp_channel_eq(dp, pe, vs, pc, pc_supported, n_lanes, cfg);
1140
1141        tegra_dp_tpg(dp, training_pattern_disabled, n_lanes, cfg);
1142
1143        return ret;
1144}
1145
1146static int _tegra_dp_clk_recovery(struct tegra_dp_priv *dp, u32 pe[4],
1147                                  u32 vs[4], u32 pc[4], u8 pc_supported,
1148                                  u32 n_lanes,
1149                                  const struct tegra_dp_link_config *cfg)
1150{
1151        u32 vs_temp[4];
1152        u32 retry_cnt = 0;
1153
1154        do {
1155                tegra_dp_lt_config(dp, pe, vs, pc, cfg);
1156                tegra_dp_wait_aux_training(dp, true, cfg);
1157
1158                if (tegra_dp_clock_recovery_status(dp, cfg))
1159                        return 0;
1160
1161                memcpy(vs_temp, vs, sizeof(vs_temp));
1162                tegra_dp_lt_adjust(dp, pe, vs, pc, pc_supported, cfg);
1163
1164                if (memcmp(vs_temp, vs, sizeof(vs_temp)))
1165                        retry_cnt = 0;
1166                else
1167                        ++retry_cnt;
1168        } while (retry_cnt < 5);
1169
1170        return -EIO;
1171}
1172
1173static int tegra_dp_clk_recovery(struct tegra_dp_priv *dp, u32 pe[4],
1174                                 u32 vs[4], u32 pc[4],
1175                                 const struct tegra_dp_link_config *cfg)
1176{
1177        u32 n_lanes = cfg->lane_count;
1178        u8 pc_supported = cfg->tps3_supported;
1179        int err;
1180
1181        tegra_dp_tpg(dp, training_pattern_1, n_lanes, cfg);
1182
1183        err = _tegra_dp_clk_recovery(dp, pe, vs, pc, pc_supported, n_lanes,
1184                                     cfg);
1185        if (err < 0)
1186                tegra_dp_tpg(dp, training_pattern_disabled, n_lanes, cfg);
1187
1188        return err;
1189}
1190
1191static int tegra_dc_dp_full_link_training(struct tegra_dp_priv *dp,
1192                                          const struct display_timing *timing,
1193                                          struct tegra_dp_link_config *cfg)
1194{
1195        struct udevice *sor = dp->sor;
1196        int err;
1197        u32 pe[4], vs[4], pc[4];
1198
1199        tegra_sor_precharge_lanes(sor, cfg);
1200
1201retry_cr:
1202        memset(pe, PREEMPHASIS_DISABLED, sizeof(pe));
1203        memset(vs, DRIVECURRENT_LEVEL0, sizeof(vs));
1204        memset(pc, POSTCURSOR2_LEVEL0, sizeof(pc));
1205
1206        err = tegra_dp_clk_recovery(dp, pe, vs, pc, cfg);
1207        if (err) {
1208                if (!tegra_dp_lower_link_config(dp, timing, cfg))
1209                        goto retry_cr;
1210
1211                debug("dp: clk recovery failed\n");
1212                goto fail;
1213        }
1214
1215        err = tegra_dp_channel_eq(dp, pe, vs, pc, cfg);
1216        if (err) {
1217                if (!tegra_dp_lower_link_config(dp, timing, cfg))
1218                        goto retry_cr;
1219
1220                debug("dp: channel equalization failed\n");
1221                goto fail;
1222        }
1223#ifdef DEBUG
1224        tegra_dc_dp_dump_link_cfg(dp, cfg);
1225#endif
1226        return 0;
1227
1228fail:
1229        return err;
1230}
1231
1232/*
1233 * All link training functions are ported from kernel dc driver.
1234 * See more details at drivers/video/tegra/dc/dp.c
1235 */
1236static int tegra_dc_dp_fast_link_training(struct tegra_dp_priv *dp,
1237                const struct tegra_dp_link_config *link_cfg,
1238                struct udevice *sor)
1239{
1240        u8      link_bw;
1241        u8      lane_count;
1242        u16     data16;
1243        u32     data32;
1244        u32     size;
1245        u32     status;
1246        int     j;
1247        u32     mask = 0xffff >> ((4 - link_cfg->lane_count) * 4);
1248
1249        tegra_dc_sor_set_lane_parm(sor, link_cfg);
1250        tegra_dc_dp_dpcd_write(dp, DP_MAIN_LINK_CHANNEL_CODING_SET,
1251                               DP_SET_ANSI_8B10B);
1252
1253        /* Send TP1 */
1254        tegra_dc_sor_set_dp_linkctl(sor, 1, training_pattern_1, link_cfg);
1255        tegra_dc_dp_dpcd_write(dp, DP_TRAINING_PATTERN_SET,
1256                               DP_TRAINING_PATTERN_1);
1257
1258        for (j = 0; j < link_cfg->lane_count; ++j)
1259                tegra_dc_dp_dpcd_write(dp, DP_TRAINING_LANE0_SET + j, 0x24);
1260        udelay(520);
1261
1262        size = sizeof(data16);
1263        tegra_dc_dpaux_read(dp, DPAUX_DP_AUXCTL_CMD_AUXRD,
1264                            DP_LANE0_1_STATUS, (u8 *)&data16, &size, &status);
1265        status = mask & 0x1111;
1266        if ((data16 & status) != status) {
1267                debug("dp: Link training error for TP1 (%#x, status %#x)\n",
1268                      data16, status);
1269                return -EFAULT;
1270        }
1271
1272        /* enable ASSR */
1273        tegra_dc_dp_set_assr(dp, sor, link_cfg->scramble_ena);
1274        tegra_dc_sor_set_dp_linkctl(sor, 1, training_pattern_3, link_cfg);
1275
1276        tegra_dc_dp_dpcd_write(dp, DP_TRAINING_PATTERN_SET,
1277                               link_cfg->link_bw == 20 ? 0x23 : 0x22);
1278        for (j = 0; j < link_cfg->lane_count; ++j)
1279                tegra_dc_dp_dpcd_write(dp, DP_TRAINING_LANE0_SET + j, 0x24);
1280        udelay(520);
1281
1282        size = sizeof(data32);
1283        tegra_dc_dpaux_read(dp, DPAUX_DP_AUXCTL_CMD_AUXRD, DP_LANE0_1_STATUS,
1284                            (u8 *)&data32, &size, &status);
1285        if ((data32 & mask) != (0x7777 & mask)) {
1286                debug("dp: Link training error for TP2/3 (0x%x)\n", data32);
1287                return -EFAULT;
1288        }
1289
1290        tegra_dc_sor_set_dp_linkctl(sor, 1, training_pattern_disabled,
1291                                    link_cfg);
1292        tegra_dc_dp_dpcd_write(dp, DP_TRAINING_PATTERN_SET, 0);
1293
1294        if (tegra_dc_dp_link_trained(dp, link_cfg)) {
1295                tegra_dc_sor_read_link_config(sor, &link_bw, &lane_count);
1296                debug("Fast link training failed, link bw %d, lane # %d\n",
1297                      link_bw, lane_count);
1298                return -EFAULT;
1299        }
1300
1301        debug("Fast link training succeeded, link bw %d, lane %d\n",
1302              link_cfg->link_bw, link_cfg->lane_count);
1303
1304        return 0;
1305}
1306
1307static int tegra_dp_do_link_training(struct tegra_dp_priv *dp,
1308                struct tegra_dp_link_config *link_cfg,
1309                const struct display_timing *timing,
1310                struct udevice *sor)
1311{
1312        u8      link_bw;
1313        u8      lane_count;
1314        int     ret;
1315
1316        if (DO_FAST_LINK_TRAINING) {
1317                ret = tegra_dc_dp_fast_link_training(dp, link_cfg, sor);
1318                if (ret) {
1319                        debug("dp: fast link training failed\n");
1320                } else {
1321                        /*
1322                        * set to a known-good drive setting if fast link
1323                        * succeeded. Ignore any error.
1324                        */
1325                        ret = tegra_dc_sor_set_voltage_swing(dp->sor, link_cfg);
1326                        if (ret)
1327                                debug("Failed to set voltage swing\n");
1328                }
1329        } else {
1330                ret = -ENOSYS;
1331        }
1332        if (ret) {
1333                /* Try full link training then */
1334                ret = tegra_dc_dp_full_link_training(dp, timing, link_cfg);
1335                if (ret) {
1336                        debug("dp: full link training failed\n");
1337                        return ret;
1338                }
1339        }
1340
1341        /* Everything is good; double check the link config */
1342        tegra_dc_sor_read_link_config(sor, &link_bw, &lane_count);
1343
1344        if ((link_cfg->link_bw == link_bw) &&
1345            (link_cfg->lane_count == lane_count))
1346                return 0;
1347        else
1348                return -EFAULT;
1349}
1350
1351static int tegra_dc_dp_explore_link_cfg(struct tegra_dp_priv *dp,
1352                        struct tegra_dp_link_config *link_cfg,
1353                        struct udevice *sor,
1354                        const struct display_timing *timing)
1355{
1356        struct tegra_dp_link_config temp_cfg;
1357
1358        if (!timing->pixelclock.typ || !timing->hactive.typ ||
1359            !timing->vactive.typ) {
1360                debug("dp: error mode configuration");
1361                return -EINVAL;
1362        }
1363        if (!link_cfg->max_link_bw || !link_cfg->max_lane_count) {
1364                debug("dp: error link configuration");
1365                return -EINVAL;
1366        }
1367
1368        link_cfg->is_valid = 0;
1369
1370        memcpy(&temp_cfg, link_cfg, sizeof(temp_cfg));
1371
1372        temp_cfg.link_bw = temp_cfg.max_link_bw;
1373        temp_cfg.lane_count = temp_cfg.max_lane_count;
1374
1375        /*
1376         * set to max link config
1377         */
1378        if ((!tegra_dc_dp_calc_config(dp, timing, &temp_cfg)) &&
1379            (!tegra_dp_link_config(dp, &temp_cfg)) &&
1380                (!tegra_dp_do_link_training(dp, &temp_cfg, timing, sor)))
1381                /* the max link cfg is doable */
1382                memcpy(link_cfg, &temp_cfg, sizeof(temp_cfg));
1383
1384        return link_cfg->is_valid ? 0 : -EFAULT;
1385}
1386
1387static int tegra_dp_hpd_plug(struct tegra_dp_priv *dp)
1388{
1389        const int vdd_to_hpd_delay_ms = 200;
1390        u32 val;
1391        ulong start;
1392
1393        start = get_timer(0);
1394        do {
1395                val = tegra_dpaux_readl(dp, DPAUX_DP_AUXSTAT);
1396                if (val & DPAUX_DP_AUXSTAT_HPD_STATUS_PLUGGED)
1397                        return 0;
1398                udelay(100);
1399        } while (get_timer(start) < vdd_to_hpd_delay_ms);
1400
1401        return -EIO;
1402}
1403
1404static int tegra_dc_dp_sink_out_of_sync(struct tegra_dp_priv *dp, u32 delay_ms)
1405{
1406        u8 dpcd_data;
1407        int out_of_sync;
1408        int ret;
1409
1410        debug("%s: delay=%d\n", __func__, delay_ms);
1411        mdelay(delay_ms);
1412        ret = tegra_dc_dp_dpcd_read(dp, DP_SINK_STATUS, &dpcd_data);
1413        if (ret)
1414                return ret;
1415
1416        out_of_sync = !(dpcd_data & DP_SINK_STATUS_PORT0_IN_SYNC);
1417        if (out_of_sync)
1418                debug("SINK receive port 0 out of sync, data=%x\n", dpcd_data);
1419        else
1420                debug("SINK is in synchronization\n");
1421
1422        return out_of_sync;
1423}
1424
1425static int tegra_dc_dp_check_sink(struct tegra_dp_priv *dp,
1426                                  struct tegra_dp_link_config *link_cfg,
1427                                  const struct display_timing *timing)
1428{
1429        const int max_retry = 5;
1430        int delay_frame;
1431        int retries;
1432
1433        /*
1434         * DP TCON may skip some main stream frames, thus we need to wait
1435         * some delay before reading the DPCD SINK STATUS register, starting
1436         * from 5
1437         */
1438        delay_frame = 5;
1439
1440        retries = max_retry;
1441        do {
1442                int ret;
1443
1444                if (!tegra_dc_dp_sink_out_of_sync(dp, link_cfg->frame_in_ms *
1445                                                  delay_frame))
1446                        return 0;
1447
1448                debug("%s: retries left %d\n", __func__, retries);
1449                if (!retries--) {
1450                        printf("DP: Out of sync after %d retries\n", max_retry);
1451                        return -EIO;
1452                }
1453                ret = tegra_dc_sor_detach(dp->dc_dev, dp->sor);
1454                if (ret)
1455                        return ret;
1456                if (tegra_dc_dp_explore_link_cfg(dp, link_cfg, dp->sor,
1457                                                 timing)) {
1458                        debug("dp: %s: error to configure link\n", __func__);
1459                        continue;
1460                }
1461
1462                tegra_dc_sor_set_power_state(dp->sor, 1);
1463                tegra_dc_sor_attach(dp->dc_dev, dp->sor, link_cfg, timing);
1464
1465                /* Increase delay_frame for next try in case the sink is
1466                   skipping more frames */
1467                delay_frame += 10;
1468        } while (1);
1469}
1470
1471int tegra_dp_enable(struct udevice *dev, int panel_bpp,
1472                    const struct display_timing *timing)
1473{
1474        struct tegra_dp_priv *priv = dev_get_priv(dev);
1475        struct tegra_dp_link_config slink_cfg, *link_cfg = &slink_cfg;
1476        struct udevice *sor;
1477        int data;
1478        int retry;
1479        int ret;
1480
1481        memset(link_cfg, '\0', sizeof(*link_cfg));
1482        link_cfg->is_valid = 0;
1483        link_cfg->scramble_ena = 1;
1484
1485        tegra_dc_dpaux_enable(priv);
1486
1487        if (tegra_dp_hpd_plug(priv) < 0) {
1488                debug("dp: hpd plug failed\n");
1489                return -EIO;
1490        }
1491
1492        link_cfg->bits_per_pixel = panel_bpp;
1493        if (tegra_dc_dp_init_max_link_cfg(timing, priv, link_cfg)) {
1494                debug("dp: failed to init link configuration\n");
1495                return -ENOLINK;
1496        }
1497
1498        ret = uclass_first_device(UCLASS_VIDEO_BRIDGE, &sor);
1499        if (ret || !sor) {
1500                debug("dp: failed to find SOR device: ret=%d\n", ret);
1501                return ret;
1502        }
1503        priv->sor = sor;
1504        ret = tegra_dc_sor_enable_dp(sor, link_cfg);
1505        if (ret)
1506                return ret;
1507
1508        tegra_dc_sor_set_panel_power(sor, 1);
1509
1510        /* Write power on to DPCD */
1511        data = DP_SET_POWER_D0;
1512        retry = 0;
1513        do {
1514                ret = tegra_dc_dp_dpcd_write(priv, DP_SET_POWER, data);
1515        } while ((retry++ < DP_POWER_ON_MAX_TRIES) && ret);
1516
1517        if (ret || retry >= DP_POWER_ON_MAX_TRIES) {
1518                debug("dp: failed to power on panel (0x%x)\n", ret);
1519                return -ENETUNREACH;
1520                goto error_enable;
1521        }
1522
1523        /* Confirm DP plugging status */
1524        if (!(tegra_dpaux_readl(priv, DPAUX_DP_AUXSTAT) &
1525                        DPAUX_DP_AUXSTAT_HPD_STATUS_PLUGGED)) {
1526                debug("dp: could not detect HPD\n");
1527                return -ENXIO;
1528        }
1529
1530        /* Check DP version */
1531        if (tegra_dc_dp_dpcd_read(priv, DP_DPCD_REV, &priv->revision)) {
1532                debug("dp: failed to read the revision number from sink\n");
1533                return -EIO;
1534        }
1535
1536        if (tegra_dc_dp_explore_link_cfg(priv, link_cfg, sor, timing)) {
1537                debug("dp: error configuring link\n");
1538                return -ENOMEDIUM;
1539        }
1540
1541        tegra_dc_sor_set_power_state(sor, 1);
1542        ret = tegra_dc_sor_attach(priv->dc_dev, sor, link_cfg, timing);
1543        if (ret && ret != -EEXIST)
1544                return ret;
1545
1546        /*
1547         * This takes a long time, but can apparently resolve a failure to
1548         * bring up the display correctly.
1549         */
1550        if (0) {
1551                ret = tegra_dc_dp_check_sink(priv, link_cfg, timing);
1552                if (ret)
1553                        return ret;
1554        }
1555
1556        /* Power down the unused lanes to save power - a few hundred mW */
1557        tegra_dc_sor_power_down_unused_lanes(sor, link_cfg);
1558
1559        ret = video_bridge_set_backlight(sor, 80);
1560        if (ret) {
1561                debug("dp: failed to set backlight\n");
1562                return ret;
1563        }
1564
1565        priv->enabled = true;
1566error_enable:
1567        return 0;
1568}
1569
1570static int tegra_dp_ofdata_to_platdata(struct udevice *dev)
1571{
1572        struct tegra_dp_plat *plat = dev_get_platdata(dev);
1573
1574        plat->base = dev_read_addr(dev);
1575
1576        return 0;
1577}
1578
1579static int tegra_dp_read_edid(struct udevice *dev, u8 *buf, int buf_size)
1580{
1581        struct tegra_dp_priv *priv = dev_get_priv(dev);
1582        const int tegra_edid_i2c_address = 0x50;
1583        u32 aux_stat = 0;
1584
1585        tegra_dc_dpaux_enable(priv);
1586
1587        return tegra_dc_i2c_aux_read(priv, tegra_edid_i2c_address, 0, buf,
1588                                     buf_size, &aux_stat);
1589}
1590
1591static const struct dm_display_ops dp_tegra_ops = {
1592        .read_edid = tegra_dp_read_edid,
1593        .enable = tegra_dp_enable,
1594};
1595
1596static int dp_tegra_probe(struct udevice *dev)
1597{
1598        struct tegra_dp_plat *plat = dev_get_platdata(dev);
1599        struct tegra_dp_priv *priv = dev_get_priv(dev);
1600        struct display_plat *disp_uc_plat = dev_get_uclass_platdata(dev);
1601
1602        priv->regs = (struct dpaux_ctlr *)plat->base;
1603        priv->enabled = false;
1604
1605        /* Remember the display controller that is sending us video */
1606        priv->dc_dev = disp_uc_plat->src_dev;
1607
1608        return 0;
1609}
1610
1611static const struct udevice_id tegra_dp_ids[] = {
1612        { .compatible = "nvidia,tegra124-dpaux" },
1613        { }
1614};
1615
1616U_BOOT_DRIVER(dp_tegra) = {
1617        .name   = "dpaux_tegra",
1618        .id     = UCLASS_DISPLAY,
1619        .of_match = tegra_dp_ids,
1620        .ofdata_to_platdata = tegra_dp_ofdata_to_platdata,
1621        .probe  = dp_tegra_probe,
1622        .ops    = &dp_tegra_ops,
1623        .priv_auto_alloc_size = sizeof(struct tegra_dp_priv),
1624        .platdata_auto_alloc_size = sizeof(struct tegra_dp_plat),
1625};
1626