uboot/drivers/video/tegra124/sor.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2011-2013, NVIDIA Corporation.
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0
   5 */
   6
   7#include <common.h>
   8#include <dm.h>
   9#include <errno.h>
  10#include <fdtdec.h>
  11#include <malloc.h>
  12#include <panel.h>
  13#include <video_bridge.h>
  14#include <asm/io.h>
  15#include <asm/arch/clock.h>
  16#include <asm/arch-tegra/dc.h>
  17#include "displayport.h"
  18#include "sor.h"
  19
  20DECLARE_GLOBAL_DATA_PTR;
  21
  22#define DEBUG_SOR 0
  23
  24#define APBDEV_PMC_DPD_SAMPLE                           0x20
  25#define APBDEV_PMC_DPD_SAMPLE_ON_DISABLE                0
  26#define APBDEV_PMC_DPD_SAMPLE_ON_ENABLE                 1
  27#define APBDEV_PMC_SEL_DPD_TIM                          0x1c8
  28#define APBDEV_PMC_SEL_DPD_TIM_SEL_DPD_TIM_DEFAULT      0x7f
  29#define APBDEV_PMC_IO_DPD2_REQ                          0x1c0
  30#define APBDEV_PMC_IO_DPD2_REQ_LVDS_SHIFT               25
  31#define APBDEV_PMC_IO_DPD2_REQ_LVDS_OFF                 (0 << 25)
  32#define APBDEV_PMC_IO_DPD2_REQ_LVDS_ON                  (1 << 25)
  33#define APBDEV_PMC_IO_DPD2_REQ_CODE_SHIFT               30
  34#define APBDEV_PMC_IO_DPD2_REQ_CODE_DEFAULT_MASK        (0x3 << 30)
  35#define APBDEV_PMC_IO_DPD2_REQ_CODE_IDLE                (0 << 30)
  36#define APBDEV_PMC_IO_DPD2_REQ_CODE_DPD_OFF             (1 << 30)
  37#define APBDEV_PMC_IO_DPD2_REQ_CODE_DPD_ON              (2 << 30)
  38#define APBDEV_PMC_IO_DPD2_STATUS                       0x1c4
  39#define APBDEV_PMC_IO_DPD2_STATUS_LVDS_SHIFT            25
  40#define APBDEV_PMC_IO_DPD2_STATUS_LVDS_OFF              (0 << 25)
  41#define APBDEV_PMC_IO_DPD2_STATUS_LVDS_ON               (1 << 25)
  42
  43struct tegra_dc_sor_data {
  44        void *base;
  45        void *pmc_base;
  46        u8 portnum;     /* 0 or 1 */
  47        int power_is_up;
  48        struct udevice *panel;
  49};
  50
  51static inline u32 tegra_sor_readl(struct tegra_dc_sor_data *sor, u32 reg)
  52{
  53        return readl((u32 *)sor->base + reg);
  54}
  55
  56static inline void tegra_sor_writel(struct tegra_dc_sor_data *sor, u32 reg,
  57                                    u32 val)
  58{
  59        writel(val, (u32 *)sor->base + reg);
  60}
  61
  62static inline void tegra_sor_write_field(struct tegra_dc_sor_data *sor,
  63        u32 reg, u32 mask, u32 val)
  64{
  65        u32 reg_val = tegra_sor_readl(sor, reg);
  66        reg_val &= ~mask;
  67        reg_val |= val;
  68        tegra_sor_writel(sor, reg, reg_val);
  69}
  70
  71void tegra_dp_disable_tx_pu(struct udevice *dev)
  72{
  73        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
  74
  75        tegra_sor_write_field(sor, DP_PADCTL(sor->portnum),
  76                              DP_PADCTL_TX_PU_MASK, DP_PADCTL_TX_PU_DISABLE);
  77}
  78
  79void tegra_dp_set_pe_vs_pc(struct udevice *dev, u32 mask, u32 pe_reg,
  80                           u32 vs_reg, u32 pc_reg, u8 pc_supported)
  81{
  82        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
  83
  84        tegra_sor_write_field(sor, PR(sor->portnum), mask, pe_reg);
  85        tegra_sor_write_field(sor, DC(sor->portnum), mask, vs_reg);
  86        if (pc_supported) {
  87                tegra_sor_write_field(sor, POSTCURSOR(sor->portnum), mask,
  88                                      pc_reg);
  89        }
  90}
  91
  92static int tegra_dc_sor_poll_register(struct tegra_dc_sor_data *sor, u32 reg,
  93                                      u32 mask, u32 exp_val,
  94                                      int poll_interval_us, int timeout_ms)
  95{
  96        u32 reg_val = 0;
  97        ulong start;
  98
  99        start = get_timer(0);
 100        do {
 101                reg_val = tegra_sor_readl(sor, reg);
 102                if (((reg_val & mask) == exp_val))
 103                        return 0;
 104                udelay(poll_interval_us);
 105        } while (get_timer(start) < timeout_ms);
 106
 107        debug("sor_poll_register 0x%x: timeout, (reg_val)0x%08x & (mask)0x%08x != (exp_val)0x%08x\n",
 108              reg, reg_val, mask, exp_val);
 109
 110        return -ETIMEDOUT;
 111}
 112
 113int tegra_dc_sor_set_power_state(struct udevice *dev, int pu_pd)
 114{
 115        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
 116        u32 reg_val;
 117        u32 orig_val;
 118
 119        orig_val = tegra_sor_readl(sor, PWR);
 120
 121        reg_val = pu_pd ? PWR_NORMAL_STATE_PU :
 122                PWR_NORMAL_STATE_PD; /* normal state only */
 123
 124        if (reg_val == orig_val)
 125                return 0;       /* No update needed */
 126
 127        reg_val |= PWR_SETTING_NEW_TRIGGER;
 128        tegra_sor_writel(sor, PWR, reg_val);
 129
 130        /* Poll to confirm it is done */
 131        if (tegra_dc_sor_poll_register(sor, PWR,
 132                                       PWR_SETTING_NEW_DEFAULT_MASK,
 133                                       PWR_SETTING_NEW_DONE,
 134                                       100, TEGRA_SOR_TIMEOUT_MS)) {
 135                debug("dc timeout waiting for SOR_PWR = NEW_DONE\n");
 136                return -EFAULT;
 137        }
 138
 139        return 0;
 140}
 141
 142void tegra_dc_sor_set_dp_linkctl(struct udevice *dev, int ena,
 143                                 u8 training_pattern,
 144                                 const struct tegra_dp_link_config *link_cfg)
 145{
 146        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
 147        u32 reg_val;
 148
 149        reg_val = tegra_sor_readl(sor, DP_LINKCTL(sor->portnum));
 150
 151        if (ena)
 152                reg_val |= DP_LINKCTL_ENABLE_YES;
 153        else
 154                reg_val &= DP_LINKCTL_ENABLE_NO;
 155
 156        reg_val &= ~DP_LINKCTL_TUSIZE_MASK;
 157        reg_val |= (link_cfg->tu_size << DP_LINKCTL_TUSIZE_SHIFT);
 158
 159        if (link_cfg->enhanced_framing)
 160                reg_val |= DP_LINKCTL_ENHANCEDFRAME_ENABLE;
 161
 162        tegra_sor_writel(sor, DP_LINKCTL(sor->portnum), reg_val);
 163
 164        switch (training_pattern) {
 165        case training_pattern_1:
 166                tegra_sor_writel(sor, DP_TPG, 0x41414141);
 167                break;
 168        case training_pattern_2:
 169        case training_pattern_3:
 170                reg_val = (link_cfg->link_bw == SOR_LINK_SPEED_G5_4) ?
 171                        0x43434343 : 0x42424242;
 172                tegra_sor_writel(sor, DP_TPG, reg_val);
 173                break;
 174        default:
 175                tegra_sor_writel(sor, DP_TPG, 0x50505050);
 176                break;
 177        }
 178}
 179
 180static int tegra_dc_sor_enable_lane_sequencer(struct tegra_dc_sor_data *sor,
 181                                              int pu, int is_lvds)
 182{
 183        u32 reg_val;
 184
 185        /* SOR lane sequencer */
 186        if (pu) {
 187                reg_val = LANE_SEQ_CTL_SETTING_NEW_TRIGGER |
 188                        LANE_SEQ_CTL_SEQUENCE_DOWN |
 189                        LANE_SEQ_CTL_NEW_POWER_STATE_PU;
 190        } else {
 191                reg_val = LANE_SEQ_CTL_SETTING_NEW_TRIGGER |
 192                        LANE_SEQ_CTL_SEQUENCE_UP |
 193                        LANE_SEQ_CTL_NEW_POWER_STATE_PD;
 194        }
 195
 196        if (is_lvds)
 197                reg_val |= 15 << LANE_SEQ_CTL_DELAY_SHIFT;
 198        else
 199                reg_val |= 1 << LANE_SEQ_CTL_DELAY_SHIFT;
 200
 201        tegra_sor_writel(sor, LANE_SEQ_CTL, reg_val);
 202
 203        if (tegra_dc_sor_poll_register(sor, LANE_SEQ_CTL,
 204                                       LANE_SEQ_CTL_SETTING_MASK,
 205                                       LANE_SEQ_CTL_SETTING_NEW_DONE,
 206                                       100, TEGRA_SOR_TIMEOUT_MS)) {
 207                debug("dp: timeout while waiting for SOR lane sequencer to power down lanes\n");
 208                return -1;
 209        }
 210
 211        return 0;
 212}
 213
 214static int tegra_dc_sor_power_dplanes(struct udevice *dev,
 215                                      u32 lane_count, int pu)
 216{
 217        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
 218        u32 reg_val;
 219
 220        reg_val = tegra_sor_readl(sor, DP_PADCTL(sor->portnum));
 221
 222        if (pu) {
 223                switch (lane_count) {
 224                case 4:
 225                        reg_val |= (DP_PADCTL_PD_TXD_3_NO |
 226                                DP_PADCTL_PD_TXD_2_NO);
 227                        /* fall through */
 228                case 2:
 229                        reg_val |= DP_PADCTL_PD_TXD_1_NO;
 230                case 1:
 231                        reg_val |= DP_PADCTL_PD_TXD_0_NO;
 232                        break;
 233                default:
 234                        debug("dp: invalid lane number %d\n", lane_count);
 235                        return -1;
 236                }
 237
 238                tegra_sor_writel(sor, DP_PADCTL(sor->portnum), reg_val);
 239                tegra_dc_sor_set_lane_count(dev, lane_count);
 240        }
 241
 242        return tegra_dc_sor_enable_lane_sequencer(sor, pu, 0);
 243}
 244
 245void tegra_dc_sor_set_panel_power(struct udevice *dev, int power_up)
 246{
 247        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
 248        u32 reg_val;
 249
 250        reg_val = tegra_sor_readl(sor, DP_PADCTL(sor->portnum));
 251
 252        if (power_up)
 253                reg_val |= DP_PADCTL_PAD_CAL_PD_POWERUP;
 254        else
 255                reg_val &= ~DP_PADCTL_PAD_CAL_PD_POWERUP;
 256
 257        tegra_sor_writel(sor, DP_PADCTL(sor->portnum), reg_val);
 258}
 259
 260static void tegra_dc_sor_config_pwm(struct tegra_dc_sor_data *sor, u32 pwm_div,
 261                                    u32 pwm_dutycycle)
 262{
 263        tegra_sor_writel(sor, PWM_DIV, pwm_div);
 264        tegra_sor_writel(sor, PWM_CTL,
 265                         (pwm_dutycycle & PWM_CTL_DUTY_CYCLE_MASK) |
 266                         PWM_CTL_SETTING_NEW_TRIGGER);
 267
 268        if (tegra_dc_sor_poll_register(sor, PWM_CTL,
 269                                       PWM_CTL_SETTING_NEW_SHIFT,
 270                                       PWM_CTL_SETTING_NEW_DONE,
 271                                       100, TEGRA_SOR_TIMEOUT_MS)) {
 272                debug("dp: timeout while waiting for SOR PWM setting\n");
 273        }
 274}
 275
 276static void tegra_dc_sor_set_dp_mode(struct udevice *dev,
 277                                const struct tegra_dp_link_config *link_cfg)
 278{
 279        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
 280        u32 reg_val;
 281
 282        tegra_dc_sor_set_link_bandwidth(dev, link_cfg->link_bw);
 283
 284        tegra_dc_sor_set_dp_linkctl(dev, 1, training_pattern_none, link_cfg);
 285        reg_val = tegra_sor_readl(sor, DP_CONFIG(sor->portnum));
 286        reg_val &= ~DP_CONFIG_WATERMARK_MASK;
 287        reg_val |= link_cfg->watermark;
 288        reg_val &= ~DP_CONFIG_ACTIVESYM_COUNT_MASK;
 289        reg_val |= (link_cfg->active_count <<
 290                DP_CONFIG_ACTIVESYM_COUNT_SHIFT);
 291        reg_val &= ~DP_CONFIG_ACTIVESYM_FRAC_MASK;
 292        reg_val |= (link_cfg->active_frac <<
 293                DP_CONFIG_ACTIVESYM_FRAC_SHIFT);
 294        if (link_cfg->activepolarity)
 295                reg_val |= DP_CONFIG_ACTIVESYM_POLARITY_POSITIVE;
 296        else
 297                reg_val &= ~DP_CONFIG_ACTIVESYM_POLARITY_POSITIVE;
 298        reg_val |= (DP_CONFIG_ACTIVESYM_CNTL_ENABLE |
 299                DP_CONFIG_RD_RESET_VAL_NEGATIVE);
 300
 301        tegra_sor_writel(sor, DP_CONFIG(sor->portnum), reg_val);
 302
 303        /* program h/vblank sym */
 304        tegra_sor_write_field(sor, DP_AUDIO_HBLANK_SYMBOLS,
 305                              DP_AUDIO_HBLANK_SYMBOLS_MASK,
 306                              link_cfg->hblank_sym);
 307
 308        tegra_sor_write_field(sor, DP_AUDIO_VBLANK_SYMBOLS,
 309                              DP_AUDIO_VBLANK_SYMBOLS_MASK,
 310                              link_cfg->vblank_sym);
 311}
 312
 313static inline void tegra_dc_sor_super_update(struct tegra_dc_sor_data *sor)
 314{
 315        tegra_sor_writel(sor, SUPER_STATE0, 0);
 316        tegra_sor_writel(sor, SUPER_STATE0, 1);
 317        tegra_sor_writel(sor, SUPER_STATE0, 0);
 318}
 319
 320static inline void tegra_dc_sor_update(struct tegra_dc_sor_data *sor)
 321{
 322        tegra_sor_writel(sor, STATE0, 0);
 323        tegra_sor_writel(sor, STATE0, 1);
 324        tegra_sor_writel(sor, STATE0, 0);
 325}
 326
 327static int tegra_dc_sor_io_set_dpd(struct tegra_dc_sor_data *sor, int up)
 328{
 329        u32 reg_val;
 330        void *pmc_base = sor->pmc_base;
 331
 332        if (up) {
 333                writel(APBDEV_PMC_DPD_SAMPLE_ON_ENABLE,
 334                       pmc_base + APBDEV_PMC_DPD_SAMPLE);
 335                writel(10, pmc_base + APBDEV_PMC_SEL_DPD_TIM);
 336        }
 337
 338        reg_val = readl(pmc_base + APBDEV_PMC_IO_DPD2_REQ);
 339        reg_val &= ~(APBDEV_PMC_IO_DPD2_REQ_LVDS_ON ||
 340                        APBDEV_PMC_IO_DPD2_REQ_CODE_DEFAULT_MASK);
 341
 342        reg_val = up ? APBDEV_PMC_IO_DPD2_REQ_LVDS_ON |
 343                        APBDEV_PMC_IO_DPD2_REQ_CODE_DPD_OFF :
 344                        APBDEV_PMC_IO_DPD2_REQ_LVDS_OFF |
 345                        APBDEV_PMC_IO_DPD2_REQ_CODE_DPD_ON;
 346
 347        writel(reg_val, pmc_base + APBDEV_PMC_IO_DPD2_REQ);
 348
 349        /* Polling */
 350        u32 temp = 10 * 1000;
 351        do {
 352                udelay(20);
 353                reg_val = readl(pmc_base + APBDEV_PMC_IO_DPD2_STATUS);
 354                if (temp > 20)
 355                        temp -= 20;
 356                else
 357                        break;
 358        } while ((reg_val & APBDEV_PMC_IO_DPD2_STATUS_LVDS_ON) != 0);
 359
 360        if ((reg_val & APBDEV_PMC_IO_DPD2_STATUS_LVDS_ON) != 0) {
 361                debug("PMC_IO_DPD2 polling failed (0x%x)\n", reg_val);
 362                return -EIO;
 363        }
 364
 365        if (up) {
 366                writel(APBDEV_PMC_DPD_SAMPLE_ON_DISABLE,
 367                       pmc_base + APBDEV_PMC_DPD_SAMPLE);
 368        }
 369
 370        return 0;
 371}
 372
 373void tegra_dc_sor_set_internal_panel(struct udevice *dev, int is_int)
 374{
 375        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
 376        u32 reg_val;
 377
 378        reg_val = tegra_sor_readl(sor, DP_SPARE(sor->portnum));
 379        if (is_int)
 380                reg_val |= DP_SPARE_PANEL_INTERNAL;
 381        else
 382                reg_val &= ~DP_SPARE_PANEL_INTERNAL;
 383
 384        reg_val |= DP_SPARE_SOR_CLK_SEL_MACRO_SORCLK |
 385                DP_SPARE_SEQ_ENABLE_YES;
 386        tegra_sor_writel(sor, DP_SPARE(sor->portnum), reg_val);
 387}
 388
 389void tegra_dc_sor_read_link_config(struct udevice *dev, u8 *link_bw,
 390                                   u8 *lane_count)
 391{
 392        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
 393        u32 reg_val;
 394
 395        reg_val = tegra_sor_readl(sor, CLK_CNTRL);
 396        *link_bw = (reg_val & CLK_CNTRL_DP_LINK_SPEED_MASK)
 397                >> CLK_CNTRL_DP_LINK_SPEED_SHIFT;
 398        reg_val = tegra_sor_readl(sor,
 399                DP_LINKCTL(sor->portnum));
 400
 401        switch (reg_val & DP_LINKCTL_LANECOUNT_MASK) {
 402        case DP_LINKCTL_LANECOUNT_ZERO:
 403                *lane_count = 0;
 404                break;
 405        case DP_LINKCTL_LANECOUNT_ONE:
 406                *lane_count = 1;
 407                break;
 408        case DP_LINKCTL_LANECOUNT_TWO:
 409                *lane_count = 2;
 410                break;
 411        case DP_LINKCTL_LANECOUNT_FOUR:
 412                *lane_count = 4;
 413                break;
 414        default:
 415                printf("Unknown lane count\n");
 416        }
 417}
 418
 419void tegra_dc_sor_set_link_bandwidth(struct udevice *dev, u8 link_bw)
 420{
 421        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
 422
 423        tegra_sor_write_field(sor, CLK_CNTRL,
 424                              CLK_CNTRL_DP_LINK_SPEED_MASK,
 425                              link_bw << CLK_CNTRL_DP_LINK_SPEED_SHIFT);
 426}
 427
 428void tegra_dc_sor_set_lane_count(struct udevice *dev, u8 lane_count)
 429{
 430        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
 431        u32 reg_val;
 432
 433        reg_val = tegra_sor_readl(sor, DP_LINKCTL(sor->portnum));
 434        reg_val &= ~DP_LINKCTL_LANECOUNT_MASK;
 435        switch (lane_count) {
 436        case 0:
 437                break;
 438        case 1:
 439                reg_val |= DP_LINKCTL_LANECOUNT_ONE;
 440                break;
 441        case 2:
 442                reg_val |= DP_LINKCTL_LANECOUNT_TWO;
 443                break;
 444        case 4:
 445                reg_val |= DP_LINKCTL_LANECOUNT_FOUR;
 446                break;
 447        default:
 448                /* 0 should be handled earlier. */
 449                printf("dp: Invalid lane count %d\n", lane_count);
 450                return;
 451        }
 452        tegra_sor_writel(sor, DP_LINKCTL(sor->portnum), reg_val);
 453}
 454
 455/*
 456 * The SOR power sequencer does not work for t124 so SW has to
 457 *  go through the power sequence manually
 458 * Power up steps from spec:
 459 * STEP PDPORT  PDPLL   PDBG    PLLVCOD PLLCAPD E_DPD   PDCAL
 460 * 1    1       1       1       1       1       1       1
 461 * 2    1       1       1       1       1       0       1
 462 * 3    1       1       0       1       1       0       1
 463 * 4    1       0       0       0       0       0       1
 464 * 5    0       0       0       0       0       0       1
 465 */
 466static int tegra_dc_sor_power_up(struct udevice *dev, int is_lvds)
 467{
 468        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
 469        int ret;
 470
 471        if (sor->power_is_up)
 472                return 0;
 473
 474        /* Set link bw */
 475        tegra_dc_sor_set_link_bandwidth(dev, is_lvds ?
 476                                        CLK_CNTRL_DP_LINK_SPEED_LVDS :
 477                                        CLK_CNTRL_DP_LINK_SPEED_G1_62);
 478
 479        /* step 1 */
 480        tegra_sor_write_field(sor, PLL2,
 481                              PLL2_AUX7_PORT_POWERDOWN_MASK | /* PDPORT */
 482                              PLL2_AUX6_BANDGAP_POWERDOWN_MASK | /* PDBG */
 483                              PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_MASK, /* PLLCAPD */
 484                              PLL2_AUX7_PORT_POWERDOWN_ENABLE |
 485                              PLL2_AUX6_BANDGAP_POWERDOWN_ENABLE |
 486                              PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_ENABLE);
 487        tegra_sor_write_field(sor, PLL0, PLL0_PWR_MASK | /* PDPLL */
 488                              PLL0_VCOPD_MASK, /* PLLVCOPD */
 489                              PLL0_PWR_OFF | PLL0_VCOPD_ASSERT);
 490        tegra_sor_write_field(sor, DP_PADCTL(sor->portnum),
 491                              DP_PADCTL_PAD_CAL_PD_POWERDOWN, /* PDCAL */
 492                              DP_PADCTL_PAD_CAL_PD_POWERDOWN);
 493
 494        /* step 2 */
 495        ret = tegra_dc_sor_io_set_dpd(sor, 1);
 496        if (ret)
 497                return ret;
 498        udelay(15);
 499
 500        /* step 3 */
 501        tegra_sor_write_field(sor, PLL2,
 502                              PLL2_AUX6_BANDGAP_POWERDOWN_MASK,
 503                              PLL2_AUX6_BANDGAP_POWERDOWN_DISABLE);
 504        udelay(25);
 505
 506        /* step 4 */
 507        tegra_sor_write_field(sor, PLL0,
 508                              PLL0_PWR_MASK | /* PDPLL */
 509                              PLL0_VCOPD_MASK, /* PLLVCOPD */
 510                              PLL0_PWR_ON | PLL0_VCOPD_RESCIND);
 511        /* PLLCAPD */
 512        tegra_sor_write_field(sor, PLL2,
 513                              PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_MASK,
 514                              PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_DISABLE);
 515        udelay(225);
 516
 517        /* step 5 PDPORT */
 518        tegra_sor_write_field(sor, PLL2,
 519                              PLL2_AUX7_PORT_POWERDOWN_MASK,
 520                              PLL2_AUX7_PORT_POWERDOWN_DISABLE);
 521
 522        sor->power_is_up = 1;
 523
 524        return 0;
 525}
 526
 527#if DEBUG_SOR
 528static void dump_sor_reg(struct tegra_dc_sor_data *sor)
 529{
 530#define DUMP_REG(a) printk(BIOS_INFO, "%-32s  %03x  %08x\n",            \
 531                #a, a, tegra_sor_readl(sor, a));
 532
 533        DUMP_REG(SUPER_STATE0);
 534        DUMP_REG(SUPER_STATE1);
 535        DUMP_REG(STATE0);
 536        DUMP_REG(STATE1);
 537        DUMP_REG(NV_HEAD_STATE0(0));
 538        DUMP_REG(NV_HEAD_STATE0(1));
 539        DUMP_REG(NV_HEAD_STATE1(0));
 540        DUMP_REG(NV_HEAD_STATE1(1));
 541        DUMP_REG(NV_HEAD_STATE2(0));
 542        DUMP_REG(NV_HEAD_STATE2(1));
 543        DUMP_REG(NV_HEAD_STATE3(0));
 544        DUMP_REG(NV_HEAD_STATE3(1));
 545        DUMP_REG(NV_HEAD_STATE4(0));
 546        DUMP_REG(NV_HEAD_STATE4(1));
 547        DUMP_REG(NV_HEAD_STATE5(0));
 548        DUMP_REG(NV_HEAD_STATE5(1));
 549        DUMP_REG(CRC_CNTRL);
 550        DUMP_REG(CLK_CNTRL);
 551        DUMP_REG(CAP);
 552        DUMP_REG(PWR);
 553        DUMP_REG(TEST);
 554        DUMP_REG(PLL0);
 555        DUMP_REG(PLL1);
 556        DUMP_REG(PLL2);
 557        DUMP_REG(PLL3);
 558        DUMP_REG(CSTM);
 559        DUMP_REG(LVDS);
 560        DUMP_REG(CRCA);
 561        DUMP_REG(CRCB);
 562        DUMP_REG(SEQ_CTL);
 563        DUMP_REG(LANE_SEQ_CTL);
 564        DUMP_REG(SEQ_INST(0));
 565        DUMP_REG(SEQ_INST(1));
 566        DUMP_REG(SEQ_INST(2));
 567        DUMP_REG(SEQ_INST(3));
 568        DUMP_REG(SEQ_INST(4));
 569        DUMP_REG(SEQ_INST(5));
 570        DUMP_REG(SEQ_INST(6));
 571        DUMP_REG(SEQ_INST(7));
 572        DUMP_REG(SEQ_INST(8));
 573        DUMP_REG(PWM_DIV);
 574        DUMP_REG(PWM_CTL);
 575        DUMP_REG(MSCHECK);
 576        DUMP_REG(XBAR_CTRL);
 577        DUMP_REG(DP_LINKCTL(0));
 578        DUMP_REG(DP_LINKCTL(1));
 579        DUMP_REG(DC(0));
 580        DUMP_REG(DC(1));
 581        DUMP_REG(LANE_DRIVE_CURRENT(0));
 582        DUMP_REG(PR(0));
 583        DUMP_REG(LANE4_PREEMPHASIS(0));
 584        DUMP_REG(POSTCURSOR(0));
 585        DUMP_REG(DP_CONFIG(0));
 586        DUMP_REG(DP_CONFIG(1));
 587        DUMP_REG(DP_MN(0));
 588        DUMP_REG(DP_MN(1));
 589        DUMP_REG(DP_PADCTL(0));
 590        DUMP_REG(DP_PADCTL(1));
 591        DUMP_REG(DP_DEBUG(0));
 592        DUMP_REG(DP_DEBUG(1));
 593        DUMP_REG(DP_SPARE(0));
 594        DUMP_REG(DP_SPARE(1));
 595        DUMP_REG(DP_TPG);
 596
 597        return;
 598}
 599#endif
 600
 601static void tegra_dc_sor_config_panel(struct tegra_dc_sor_data *sor,
 602                        int is_lvds,
 603                        const struct tegra_dp_link_config *link_cfg,
 604                        const struct display_timing *timing)
 605{
 606        const int       head_num = 0;
 607        u32             reg_val  = STATE1_ASY_OWNER_HEAD0 << head_num;
 608        u32             vtotal, htotal;
 609        u32             vsync_end, hsync_end;
 610        u32             vblank_end, hblank_end;
 611        u32             vblank_start, hblank_start;
 612
 613        reg_val |= is_lvds ? STATE1_ASY_PROTOCOL_LVDS_CUSTOM :
 614                STATE1_ASY_PROTOCOL_DP_A;
 615        reg_val |= STATE1_ASY_SUBOWNER_NONE |
 616                STATE1_ASY_CRCMODE_COMPLETE_RASTER;
 617
 618        reg_val |= STATE1_ASY_HSYNCPOL_NEGATIVE_TRUE;
 619        reg_val |= STATE1_ASY_VSYNCPOL_NEGATIVE_TRUE;
 620        reg_val |= (link_cfg->bits_per_pixel > 18) ?
 621                STATE1_ASY_PIXELDEPTH_BPP_24_444 :
 622                STATE1_ASY_PIXELDEPTH_BPP_18_444;
 623
 624        tegra_sor_writel(sor, STATE1, reg_val);
 625
 626        /*
 627         * Skipping programming NV_HEAD_STATE0, assuming:
 628         * interlacing: PROGRESSIVE, dynamic range: VESA, colorspace: RGB
 629         */
 630        vtotal = timing->vsync_len.typ + timing->vback_porch.typ +
 631                timing->vactive.typ + timing->vfront_porch.typ;
 632        htotal = timing->hsync_len.typ + timing->hback_porch.typ +
 633                timing->hactive.typ + timing->hfront_porch.typ;
 634
 635        tegra_sor_writel(sor, NV_HEAD_STATE1(head_num),
 636                         vtotal << NV_HEAD_STATE1_VTOTAL_SHIFT |
 637                         htotal << NV_HEAD_STATE1_HTOTAL_SHIFT);
 638
 639        vsync_end = timing->vsync_len.typ - 1;
 640        hsync_end = timing->hsync_len.typ - 1;
 641        tegra_sor_writel(sor, NV_HEAD_STATE2(head_num),
 642                         vsync_end << NV_HEAD_STATE2_VSYNC_END_SHIFT |
 643                         hsync_end << NV_HEAD_STATE2_HSYNC_END_SHIFT);
 644
 645        vblank_end = vsync_end + timing->vback_porch.typ;
 646        hblank_end = hsync_end + timing->hback_porch.typ;
 647        tegra_sor_writel(sor, NV_HEAD_STATE3(head_num),
 648                         vblank_end << NV_HEAD_STATE3_VBLANK_END_SHIFT |
 649                         hblank_end << NV_HEAD_STATE3_HBLANK_END_SHIFT);
 650
 651        vblank_start = vblank_end + timing->vactive.typ;
 652        hblank_start = hblank_end + timing->hactive.typ;
 653        tegra_sor_writel(sor, NV_HEAD_STATE4(head_num),
 654                         vblank_start << NV_HEAD_STATE4_VBLANK_START_SHIFT |
 655                         hblank_start << NV_HEAD_STATE4_HBLANK_START_SHIFT);
 656
 657        /* TODO: adding interlace mode support */
 658        tegra_sor_writel(sor, NV_HEAD_STATE5(head_num), 0x1);
 659
 660        tegra_sor_write_field(sor, CSTM,
 661                              CSTM_ROTCLK_DEFAULT_MASK |
 662                              CSTM_LVDS_EN_ENABLE,
 663                              2 << CSTM_ROTCLK_SHIFT |
 664                              is_lvds ? CSTM_LVDS_EN_ENABLE :
 665                              CSTM_LVDS_EN_DISABLE);
 666
 667         tegra_dc_sor_config_pwm(sor, 1024, 1024);
 668}
 669
 670static void tegra_dc_sor_enable_dc(struct dc_ctlr *disp_ctrl)
 671{
 672        u32 reg_val = readl(&disp_ctrl->cmd.state_access);
 673
 674        writel(reg_val | WRITE_MUX_ACTIVE, &disp_ctrl->cmd.state_access);
 675        writel(VSYNC_H_POSITION(1), &disp_ctrl->disp.disp_timing_opt);
 676
 677        /* Enable DC now - otherwise pure text console may not show. */
 678        writel(CTRL_MODE_C_DISPLAY << CTRL_MODE_SHIFT,
 679               &disp_ctrl->cmd.disp_cmd);
 680        writel(reg_val, &disp_ctrl->cmd.state_access);
 681}
 682
 683int tegra_dc_sor_enable_dp(struct udevice *dev,
 684                           const struct tegra_dp_link_config *link_cfg)
 685{
 686        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
 687        int ret;
 688
 689        tegra_sor_write_field(sor, CLK_CNTRL,
 690                              CLK_CNTRL_DP_CLK_SEL_MASK,
 691                              CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK);
 692
 693        tegra_sor_write_field(sor, PLL2,
 694                              PLL2_AUX6_BANDGAP_POWERDOWN_MASK,
 695                              PLL2_AUX6_BANDGAP_POWERDOWN_DISABLE);
 696        udelay(25);
 697
 698        tegra_sor_write_field(sor, PLL3,
 699                              PLL3_PLLVDD_MODE_MASK,
 700                              PLL3_PLLVDD_MODE_V3_3);
 701        tegra_sor_writel(sor, PLL0,
 702                         0xf << PLL0_ICHPMP_SHFIT |
 703                         0x3 << PLL0_VCOCAP_SHIFT |
 704                         PLL0_PLLREG_LEVEL_V45 |
 705                         PLL0_RESISTORSEL_EXT |
 706                         PLL0_PWR_ON | PLL0_VCOPD_RESCIND);
 707        tegra_sor_write_field(sor, PLL2,
 708                              PLL2_AUX1_SEQ_MASK |
 709                              PLL2_AUX9_LVDSEN_OVERRIDE |
 710                              PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_MASK,
 711                              PLL2_AUX1_SEQ_PLLCAPPD_OVERRIDE |
 712                              PLL2_AUX9_LVDSEN_OVERRIDE |
 713                              PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_DISABLE);
 714        tegra_sor_writel(sor, PLL1, PLL1_TERM_COMPOUT_HIGH |
 715                         PLL1_TMDS_TERM_ENABLE);
 716
 717        if (tegra_dc_sor_poll_register(sor, PLL2,
 718                                       PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_MASK,
 719                                       PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_DISABLE,
 720                                       100, TEGRA_SOR_TIMEOUT_MS)) {
 721                printf("DP failed to lock PLL\n");
 722                return -EIO;
 723        }
 724
 725        tegra_sor_write_field(sor, PLL2, PLL2_AUX2_MASK |
 726                              PLL2_AUX7_PORT_POWERDOWN_MASK,
 727                              PLL2_AUX2_OVERRIDE_POWERDOWN |
 728                              PLL2_AUX7_PORT_POWERDOWN_DISABLE);
 729
 730        ret = tegra_dc_sor_power_up(dev, 0);
 731        if (ret) {
 732                debug("DP failed to power up\n");
 733                return ret;
 734        }
 735
 736        /* re-enable SOR clock */
 737        clock_sor_enable_edp_clock();
 738
 739        /* Power up lanes */
 740        tegra_dc_sor_power_dplanes(dev, link_cfg->lane_count, 1);
 741
 742        tegra_dc_sor_set_dp_mode(dev, link_cfg);
 743        debug("%s ret\n", __func__);
 744
 745        return 0;
 746}
 747
 748int tegra_dc_sor_attach(struct udevice *dc_dev, struct udevice *dev,
 749                        const struct tegra_dp_link_config *link_cfg,
 750                        const struct display_timing *timing)
 751{
 752        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
 753        const void *blob = gd->fdt_blob;
 754        struct dc_ctlr *disp_ctrl;
 755        u32 reg_val;
 756        int node;
 757
 758        /* Use the first display controller */
 759        debug("%s\n", __func__);
 760        node = dc_dev->of_offset;
 761        disp_ctrl = (struct dc_ctlr *)fdtdec_get_addr(blob, node, "reg");
 762
 763        tegra_dc_sor_enable_dc(disp_ctrl);
 764        tegra_dc_sor_config_panel(sor, 0, link_cfg, timing);
 765
 766        writel(0x9f00, &disp_ctrl->cmd.state_ctrl);
 767        writel(0x9f, &disp_ctrl->cmd.state_ctrl);
 768
 769        writel(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
 770               PW4_ENABLE | PM0_ENABLE | PM1_ENABLE,
 771               &disp_ctrl->cmd.disp_pow_ctrl);
 772
 773        reg_val = tegra_sor_readl(sor, TEST);
 774        if (reg_val & TEST_ATTACHED_TRUE)
 775                return -EEXIST;
 776
 777        tegra_sor_writel(sor, SUPER_STATE1,
 778                         SUPER_STATE1_ATTACHED_NO);
 779
 780        /*
 781         * Enable display2sor clock at least 2 cycles before DC start,
 782         * to clear sor internal valid signal.
 783         */
 784        writel(SOR_ENABLE, &disp_ctrl->disp.disp_win_opt);
 785        writel(GENERAL_ACT_REQ, &disp_ctrl->cmd.state_ctrl);
 786        writel(0, &disp_ctrl->disp.disp_win_opt);
 787        writel(GENERAL_ACT_REQ, &disp_ctrl->cmd.state_ctrl);
 788
 789        /* Attach head */
 790        tegra_dc_sor_update(sor);
 791        tegra_sor_writel(sor, SUPER_STATE1,
 792                         SUPER_STATE1_ATTACHED_YES);
 793        tegra_sor_writel(sor, SUPER_STATE1,
 794                         SUPER_STATE1_ATTACHED_YES |
 795                         SUPER_STATE1_ASY_HEAD_OP_AWAKE |
 796                         SUPER_STATE1_ASY_ORMODE_NORMAL);
 797        tegra_dc_sor_super_update(sor);
 798
 799        /* Enable dc */
 800        reg_val = readl(&disp_ctrl->cmd.state_access);
 801        writel(reg_val | WRITE_MUX_ACTIVE, &disp_ctrl->cmd.state_access);
 802        writel(CTRL_MODE_C_DISPLAY << CTRL_MODE_SHIFT,
 803               &disp_ctrl->cmd.disp_cmd);
 804        writel(SOR_ENABLE, &disp_ctrl->disp.disp_win_opt);
 805        writel(reg_val, &disp_ctrl->cmd.state_access);
 806
 807        if (tegra_dc_sor_poll_register(sor, TEST,
 808                                       TEST_ACT_HEAD_OPMODE_DEFAULT_MASK,
 809                                       TEST_ACT_HEAD_OPMODE_AWAKE,
 810                                       100,
 811                                       TEGRA_SOR_ATTACH_TIMEOUT_MS)) {
 812                printf("dc timeout waiting for OPMOD = AWAKE\n");
 813                return -ETIMEDOUT;
 814        } else {
 815                debug("%s: sor is attached\n", __func__);
 816        }
 817
 818#if DEBUG_SOR
 819        dump_sor_reg(sor);
 820#endif
 821        debug("%s: ret=%d\n", __func__, 0);
 822
 823        return 0;
 824}
 825
 826void tegra_dc_sor_set_lane_parm(struct udevice *dev,
 827                const struct tegra_dp_link_config *link_cfg)
 828{
 829        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
 830
 831        tegra_sor_writel(sor, LANE_DRIVE_CURRENT(sor->portnum),
 832                         link_cfg->drive_current);
 833        tegra_sor_writel(sor, PR(sor->portnum),
 834                         link_cfg->preemphasis);
 835        tegra_sor_writel(sor, POSTCURSOR(sor->portnum),
 836                         link_cfg->postcursor);
 837        tegra_sor_writel(sor, LVDS, 0);
 838
 839        tegra_dc_sor_set_link_bandwidth(dev, link_cfg->link_bw);
 840        tegra_dc_sor_set_lane_count(dev, link_cfg->lane_count);
 841
 842        tegra_sor_write_field(sor, DP_PADCTL(sor->portnum),
 843                              DP_PADCTL_TX_PU_ENABLE |
 844                              DP_PADCTL_TX_PU_VALUE_DEFAULT_MASK,
 845                              DP_PADCTL_TX_PU_ENABLE |
 846                              2 << DP_PADCTL_TX_PU_VALUE_SHIFT);
 847
 848        /* Precharge */
 849        tegra_sor_write_field(sor, DP_PADCTL(sor->portnum), 0xf0, 0xf0);
 850        udelay(20);
 851
 852        tegra_sor_write_field(sor, DP_PADCTL(sor->portnum), 0xf0, 0x0);
 853}
 854
 855int tegra_dc_sor_set_voltage_swing(struct udevice *dev,
 856                                    const struct tegra_dp_link_config *link_cfg)
 857{
 858        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
 859        u32 drive_current = 0;
 860        u32 pre_emphasis = 0;
 861
 862        /* Set to a known-good pre-calibrated setting */
 863        switch (link_cfg->link_bw) {
 864        case SOR_LINK_SPEED_G1_62:
 865        case SOR_LINK_SPEED_G2_7:
 866                drive_current = 0x13131313;
 867                pre_emphasis = 0;
 868                break;
 869        case SOR_LINK_SPEED_G5_4:
 870                debug("T124 does not support 5.4G link clock.\n");
 871        default:
 872                debug("Invalid sor link bandwidth: %d\n", link_cfg->link_bw);
 873                return -ENOLINK;
 874        }
 875
 876        tegra_sor_writel(sor, LANE_DRIVE_CURRENT(sor->portnum), drive_current);
 877        tegra_sor_writel(sor, PR(sor->portnum), pre_emphasis);
 878
 879        return 0;
 880}
 881
 882void tegra_dc_sor_power_down_unused_lanes(struct udevice *dev,
 883                        const struct tegra_dp_link_config *link_cfg)
 884{
 885        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
 886        u32 pad_ctrl = 0;
 887        int err = 0;
 888
 889        switch (link_cfg->lane_count) {
 890        case 4:
 891                pad_ctrl = DP_PADCTL_PD_TXD_0_NO |
 892                        DP_PADCTL_PD_TXD_1_NO |
 893                        DP_PADCTL_PD_TXD_2_NO |
 894                        DP_PADCTL_PD_TXD_3_NO;
 895                break;
 896        case 2:
 897                pad_ctrl = DP_PADCTL_PD_TXD_0_NO |
 898                        DP_PADCTL_PD_TXD_1_NO |
 899                        DP_PADCTL_PD_TXD_2_YES |
 900                        DP_PADCTL_PD_TXD_3_YES;
 901                break;
 902        case 1:
 903                pad_ctrl = DP_PADCTL_PD_TXD_0_NO |
 904                        DP_PADCTL_PD_TXD_1_YES |
 905                        DP_PADCTL_PD_TXD_2_YES |
 906                        DP_PADCTL_PD_TXD_3_YES;
 907                break;
 908        default:
 909                printf("Invalid sor lane count: %u\n", link_cfg->lane_count);
 910                return;
 911        }
 912
 913        pad_ctrl |= DP_PADCTL_PAD_CAL_PD_POWERDOWN;
 914        tegra_sor_writel(sor, DP_PADCTL(sor->portnum), pad_ctrl);
 915
 916        err = tegra_dc_sor_enable_lane_sequencer(sor, 0, 0);
 917        if (err) {
 918                debug("Wait for lane power down failed: %d\n", err);
 919                return;
 920        }
 921}
 922
 923int tegra_sor_precharge_lanes(struct udevice *dev,
 924                              const struct tegra_dp_link_config *cfg)
 925{
 926        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
 927        u32 val = 0;
 928
 929        switch (cfg->lane_count) {
 930        case 4:
 931                val |= (DP_PADCTL_PD_TXD_3_NO |
 932                        DP_PADCTL_PD_TXD_2_NO);
 933                /* fall through */
 934        case 2:
 935                val |= DP_PADCTL_PD_TXD_1_NO;
 936                /* fall through */
 937        case 1:
 938                val |= DP_PADCTL_PD_TXD_0_NO;
 939                break;
 940        default:
 941                debug("dp: invalid lane number %d\n", cfg->lane_count);
 942                return -EINVAL;
 943        }
 944
 945        tegra_sor_write_field(sor, DP_PADCTL(sor->portnum),
 946                              (0xf << DP_PADCTL_COMODE_TXD_0_DP_TXD_2_SHIFT),
 947                              (val << DP_PADCTL_COMODE_TXD_0_DP_TXD_2_SHIFT));
 948        udelay(100);
 949        tegra_sor_write_field(sor, DP_PADCTL(sor->portnum),
 950                              (0xf << DP_PADCTL_COMODE_TXD_0_DP_TXD_2_SHIFT),
 951                              0);
 952
 953        return 0;
 954}
 955
 956static void tegra_dc_sor_enable_sor(struct dc_ctlr *disp_ctrl, bool enable)
 957{
 958        u32 reg_val = readl(&disp_ctrl->disp.disp_win_opt);
 959
 960        reg_val = enable ? reg_val | SOR_ENABLE : reg_val & ~SOR_ENABLE;
 961        writel(reg_val, &disp_ctrl->disp.disp_win_opt);
 962}
 963
 964int tegra_dc_sor_detach(struct udevice *dc_dev, struct udevice *dev)
 965{
 966        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
 967        int dc_reg_ctx[DC_REG_SAVE_SPACE];
 968        const void *blob = gd->fdt_blob;
 969        struct dc_ctlr *disp_ctrl;
 970        unsigned long dc_int_mask;
 971        int node;
 972        int ret;
 973
 974        debug("%s\n", __func__);
 975        /* Use the first display controller */
 976        node = dc_dev->of_offset;
 977        disp_ctrl = (struct dc_ctlr *)fdtdec_get_addr(blob, node, "reg");
 978
 979        /* Sleep mode */
 980        tegra_sor_writel(sor, SUPER_STATE1, SUPER_STATE1_ASY_HEAD_OP_SLEEP |
 981                         SUPER_STATE1_ASY_ORMODE_SAFE |
 982                         SUPER_STATE1_ATTACHED_YES);
 983        tegra_dc_sor_super_update(sor);
 984
 985        tegra_dc_sor_disable_win_short_raster(disp_ctrl, dc_reg_ctx);
 986
 987        if (tegra_dc_sor_poll_register(sor, TEST,
 988                                       TEST_ACT_HEAD_OPMODE_DEFAULT_MASK,
 989                                       TEST_ACT_HEAD_OPMODE_SLEEP, 100,
 990                                       TEGRA_SOR_ATTACH_TIMEOUT_MS)) {
 991                debug("dc timeout waiting for OPMOD = SLEEP\n");
 992                ret = -ETIMEDOUT;
 993                goto err;
 994        }
 995
 996        tegra_sor_writel(sor, SUPER_STATE1, SUPER_STATE1_ASY_HEAD_OP_SLEEP |
 997                         SUPER_STATE1_ASY_ORMODE_SAFE |
 998                         SUPER_STATE1_ATTACHED_NO);
 999
1000        /* Mask DC interrupts during the 2 dummy frames required for detach */
1001        dc_int_mask = readl(&disp_ctrl->cmd.int_mask);
1002        writel(0, &disp_ctrl->cmd.int_mask);
1003
1004        /* Stop DC->SOR path */
1005        tegra_dc_sor_enable_sor(disp_ctrl, false);
1006        ret = tegra_dc_sor_general_act(disp_ctrl);
1007        if (ret)
1008                goto err;
1009
1010        /* Stop DC */
1011        writel(CTRL_MODE_STOP << CTRL_MODE_SHIFT, &disp_ctrl->cmd.disp_cmd);
1012        ret = tegra_dc_sor_general_act(disp_ctrl);
1013        if (ret)
1014                goto err;
1015
1016        tegra_dc_sor_restore_win_and_raster(disp_ctrl, dc_reg_ctx);
1017
1018        writel(dc_int_mask, &disp_ctrl->cmd.int_mask);
1019
1020        return 0;
1021err:
1022        debug("%s: ret=%d\n", __func__, ret);
1023
1024        return ret;
1025}
1026
1027static int tegra_sor_set_backlight(struct udevice *dev, int percent)
1028{
1029        struct tegra_dc_sor_data *priv = dev_get_priv(dev);
1030        int ret;
1031
1032        ret = panel_enable_backlight(priv->panel);
1033        if (ret) {
1034                debug("sor: Cannot enable panel backlight\n");
1035                return ret;
1036        }
1037
1038        return 0;
1039}
1040
1041static int tegra_sor_ofdata_to_platdata(struct udevice *dev)
1042{
1043        struct tegra_dc_sor_data *priv = dev_get_priv(dev);
1044        const void *blob = gd->fdt_blob;
1045        int node;
1046        int ret;
1047
1048        priv->base = (void *)fdtdec_get_addr(blob, dev->of_offset, "reg");
1049
1050        node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA124_PMC);
1051        if (node < 0) {
1052                debug("%s: Cannot find PMC\n", __func__);
1053                return -ENOENT;
1054        }
1055        priv->pmc_base = (void *)fdtdec_get_addr(blob, node, "reg");
1056
1057        ret = uclass_get_device_by_phandle(UCLASS_PANEL, dev, "nvidia,panel",
1058                                           &priv->panel);
1059        if (ret) {
1060                debug("%s: Cannot find panel for '%s' (ret=%d)\n", __func__,
1061                      dev->name, ret);
1062                return ret;
1063        }
1064
1065        return 0;
1066}
1067
1068static const struct video_bridge_ops tegra_sor_ops = {
1069        .set_backlight  = tegra_sor_set_backlight,
1070};
1071
1072static const struct udevice_id tegra_sor_ids[] = {
1073        { .compatible = "nvidia,tegra124-sor" },
1074        { }
1075};
1076
1077U_BOOT_DRIVER(sor_tegra) = {
1078        .name   = "sor_tegra",
1079        .id     = UCLASS_VIDEO_BRIDGE,
1080        .of_match = tegra_sor_ids,
1081        .ofdata_to_platdata = tegra_sor_ofdata_to_platdata,
1082        .ops    = &tegra_sor_ops,
1083        .priv_auto_alloc_size = sizeof(struct tegra_dc_sor_data),
1084};
1085