uboot/drivers/video/tegra124/sor.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2011-2013, NVIDIA Corporation.
   4 */
   5
   6#include <common.h>
   7#include <dm.h>
   8#include <errno.h>
   9#include <log.h>
  10#include <malloc.h>
  11#include <panel.h>
  12#include <syscon.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 <linux/delay.h>
  18#include "displayport.h"
  19#include "sor.h"
  20#include <linux/err.h>
  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        u32 reg;
 470        int ret;
 471
 472        if (sor->power_is_up)
 473                return 0;
 474
 475        /*
 476         * If for some reason it is already powered up, don't do it again.
 477         * This can happen if U-Boot is the secondary boot loader.
 478         */
 479        reg = tegra_sor_readl(sor, DP_PADCTL(sor->portnum));
 480        if (reg & DP_PADCTL_PD_TXD_0_NO)
 481                return 0;
 482
 483        /* Set link bw */
 484        tegra_dc_sor_set_link_bandwidth(dev, is_lvds ?
 485                                        CLK_CNTRL_DP_LINK_SPEED_LVDS :
 486                                        CLK_CNTRL_DP_LINK_SPEED_G1_62);
 487
 488        /* step 1 */
 489        tegra_sor_write_field(sor, PLL2,
 490                              PLL2_AUX7_PORT_POWERDOWN_MASK | /* PDPORT */
 491                              PLL2_AUX6_BANDGAP_POWERDOWN_MASK | /* PDBG */
 492                              PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_MASK, /* PLLCAPD */
 493                              PLL2_AUX7_PORT_POWERDOWN_ENABLE |
 494                              PLL2_AUX6_BANDGAP_POWERDOWN_ENABLE |
 495                              PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_ENABLE);
 496        tegra_sor_write_field(sor, PLL0, PLL0_PWR_MASK | /* PDPLL */
 497                              PLL0_VCOPD_MASK, /* PLLVCOPD */
 498                              PLL0_PWR_OFF | PLL0_VCOPD_ASSERT);
 499        tegra_sor_write_field(sor, DP_PADCTL(sor->portnum),
 500                              DP_PADCTL_PAD_CAL_PD_POWERDOWN, /* PDCAL */
 501                              DP_PADCTL_PAD_CAL_PD_POWERDOWN);
 502
 503        /* step 2 */
 504        ret = tegra_dc_sor_io_set_dpd(sor, 1);
 505        if (ret)
 506                return ret;
 507        udelay(15);
 508
 509        /* step 3 */
 510        tegra_sor_write_field(sor, PLL2,
 511                              PLL2_AUX6_BANDGAP_POWERDOWN_MASK,
 512                              PLL2_AUX6_BANDGAP_POWERDOWN_DISABLE);
 513        udelay(25);
 514
 515        /* step 4 */
 516        tegra_sor_write_field(sor, PLL0,
 517                              PLL0_PWR_MASK | /* PDPLL */
 518                              PLL0_VCOPD_MASK, /* PLLVCOPD */
 519                              PLL0_PWR_ON | PLL0_VCOPD_RESCIND);
 520        /* PLLCAPD */
 521        tegra_sor_write_field(sor, PLL2,
 522                              PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_MASK,
 523                              PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_DISABLE);
 524        udelay(225);
 525
 526        /* step 5 PDPORT */
 527        tegra_sor_write_field(sor, PLL2,
 528                              PLL2_AUX7_PORT_POWERDOWN_MASK,
 529                              PLL2_AUX7_PORT_POWERDOWN_DISABLE);
 530
 531        sor->power_is_up = 1;
 532
 533        return 0;
 534}
 535
 536#if DEBUG_SOR
 537static void dump_sor_reg(struct tegra_dc_sor_data *sor)
 538{
 539#define DUMP_REG(a) printk(BIOS_INFO, \
 540                "%-32s  %03x  %08x\n",          \
 541                #a, a, tegra_sor_readl(sor, a));
 542
 543        DUMP_REG(SUPER_STATE0);
 544        DUMP_REG(SUPER_STATE1);
 545        DUMP_REG(STATE0);
 546        DUMP_REG(STATE1);
 547        DUMP_REG(NV_HEAD_STATE0(0));
 548        DUMP_REG(NV_HEAD_STATE0(1));
 549        DUMP_REG(NV_HEAD_STATE1(0));
 550        DUMP_REG(NV_HEAD_STATE1(1));
 551        DUMP_REG(NV_HEAD_STATE2(0));
 552        DUMP_REG(NV_HEAD_STATE2(1));
 553        DUMP_REG(NV_HEAD_STATE3(0));
 554        DUMP_REG(NV_HEAD_STATE3(1));
 555        DUMP_REG(NV_HEAD_STATE4(0));
 556        DUMP_REG(NV_HEAD_STATE4(1));
 557        DUMP_REG(NV_HEAD_STATE5(0));
 558        DUMP_REG(NV_HEAD_STATE5(1));
 559        DUMP_REG(CRC_CNTRL);
 560        DUMP_REG(CLK_CNTRL);
 561        DUMP_REG(CAP);
 562        DUMP_REG(PWR);
 563        DUMP_REG(TEST);
 564        DUMP_REG(PLL0);
 565        DUMP_REG(PLL1);
 566        DUMP_REG(PLL2);
 567        DUMP_REG(PLL3);
 568        DUMP_REG(CSTM);
 569        DUMP_REG(LVDS);
 570        DUMP_REG(CRCA);
 571        DUMP_REG(CRCB);
 572        DUMP_REG(SEQ_CTL);
 573        DUMP_REG(LANE_SEQ_CTL);
 574        DUMP_REG(SEQ_INST(0));
 575        DUMP_REG(SEQ_INST(1));
 576        DUMP_REG(SEQ_INST(2));
 577        DUMP_REG(SEQ_INST(3));
 578        DUMP_REG(SEQ_INST(4));
 579        DUMP_REG(SEQ_INST(5));
 580        DUMP_REG(SEQ_INST(6));
 581        DUMP_REG(SEQ_INST(7));
 582        DUMP_REG(SEQ_INST(8));
 583        DUMP_REG(PWM_DIV);
 584        DUMP_REG(PWM_CTL);
 585        DUMP_REG(MSCHECK);
 586        DUMP_REG(XBAR_CTRL);
 587        DUMP_REG(DP_LINKCTL(0));
 588        DUMP_REG(DP_LINKCTL(1));
 589        DUMP_REG(DC(0));
 590        DUMP_REG(DC(1));
 591        DUMP_REG(LANE_DRIVE_CURRENT(0));
 592        DUMP_REG(PR(0));
 593        DUMP_REG(LANE4_PREEMPHASIS(0));
 594        DUMP_REG(POSTCURSOR(0));
 595        DUMP_REG(DP_CONFIG(0));
 596        DUMP_REG(DP_CONFIG(1));
 597        DUMP_REG(DP_MN(0));
 598        DUMP_REG(DP_MN(1));
 599        DUMP_REG(DP_PADCTL(0));
 600        DUMP_REG(DP_PADCTL(1));
 601        DUMP_REG(DP_DEBUG(0));
 602        DUMP_REG(DP_DEBUG(1));
 603        DUMP_REG(DP_SPARE(0));
 604        DUMP_REG(DP_SPARE(1));
 605        DUMP_REG(DP_TPG);
 606
 607        return;
 608}
 609#endif
 610
 611static void tegra_dc_sor_config_panel(struct tegra_dc_sor_data *sor,
 612                        int is_lvds,
 613                        const struct tegra_dp_link_config *link_cfg,
 614                        const struct display_timing *timing)
 615{
 616        const int       head_num = 0;
 617        u32             reg_val  = STATE1_ASY_OWNER_HEAD0 << head_num;
 618        u32             vtotal, htotal;
 619        u32             vsync_end, hsync_end;
 620        u32             vblank_end, hblank_end;
 621        u32             vblank_start, hblank_start;
 622
 623        reg_val |= is_lvds ? STATE1_ASY_PROTOCOL_LVDS_CUSTOM :
 624                STATE1_ASY_PROTOCOL_DP_A;
 625        reg_val |= STATE1_ASY_SUBOWNER_NONE |
 626                STATE1_ASY_CRCMODE_COMPLETE_RASTER;
 627
 628        reg_val |= STATE1_ASY_HSYNCPOL_NEGATIVE_TRUE;
 629        reg_val |= STATE1_ASY_VSYNCPOL_NEGATIVE_TRUE;
 630        reg_val |= (link_cfg->bits_per_pixel > 18) ?
 631                STATE1_ASY_PIXELDEPTH_BPP_24_444 :
 632                STATE1_ASY_PIXELDEPTH_BPP_18_444;
 633
 634        tegra_sor_writel(sor, STATE1, reg_val);
 635
 636        /*
 637         * Skipping programming NV_HEAD_STATE0, assuming:
 638         * interlacing: PROGRESSIVE, dynamic range: VESA, colorspace: RGB
 639         */
 640        vtotal = timing->vsync_len.typ + timing->vback_porch.typ +
 641                timing->vactive.typ + timing->vfront_porch.typ;
 642        htotal = timing->hsync_len.typ + timing->hback_porch.typ +
 643                timing->hactive.typ + timing->hfront_porch.typ;
 644
 645        tegra_sor_writel(sor, NV_HEAD_STATE1(head_num),
 646                         vtotal << NV_HEAD_STATE1_VTOTAL_SHIFT |
 647                         htotal << NV_HEAD_STATE1_HTOTAL_SHIFT);
 648
 649        vsync_end = timing->vsync_len.typ - 1;
 650        hsync_end = timing->hsync_len.typ - 1;
 651        tegra_sor_writel(sor, NV_HEAD_STATE2(head_num),
 652                         vsync_end << NV_HEAD_STATE2_VSYNC_END_SHIFT |
 653                         hsync_end << NV_HEAD_STATE2_HSYNC_END_SHIFT);
 654
 655        vblank_end = vsync_end + timing->vback_porch.typ;
 656        hblank_end = hsync_end + timing->hback_porch.typ;
 657        tegra_sor_writel(sor, NV_HEAD_STATE3(head_num),
 658                         vblank_end << NV_HEAD_STATE3_VBLANK_END_SHIFT |
 659                         hblank_end << NV_HEAD_STATE3_HBLANK_END_SHIFT);
 660
 661        vblank_start = vblank_end + timing->vactive.typ;
 662        hblank_start = hblank_end + timing->hactive.typ;
 663        tegra_sor_writel(sor, NV_HEAD_STATE4(head_num),
 664                         vblank_start << NV_HEAD_STATE4_VBLANK_START_SHIFT |
 665                         hblank_start << NV_HEAD_STATE4_HBLANK_START_SHIFT);
 666
 667        /* TODO: adding interlace mode support */
 668        tegra_sor_writel(sor, NV_HEAD_STATE5(head_num), 0x1);
 669
 670        tegra_sor_write_field(sor, CSTM,
 671                              CSTM_ROTCLK_DEFAULT_MASK |
 672                              CSTM_LVDS_EN_ENABLE,
 673                              2 << CSTM_ROTCLK_SHIFT |
 674                              (is_lvds ? CSTM_LVDS_EN_ENABLE :
 675                              CSTM_LVDS_EN_DISABLE));
 676
 677         tegra_dc_sor_config_pwm(sor, 1024, 1024);
 678}
 679
 680static void tegra_dc_sor_enable_dc(struct dc_ctlr *disp_ctrl)
 681{
 682        u32 reg_val = readl(&disp_ctrl->cmd.state_access);
 683
 684        writel(reg_val | WRITE_MUX_ACTIVE, &disp_ctrl->cmd.state_access);
 685        writel(VSYNC_H_POSITION(1), &disp_ctrl->disp.disp_timing_opt);
 686
 687        /* Enable DC now - otherwise pure text console may not show. */
 688        writel(CTRL_MODE_C_DISPLAY << CTRL_MODE_SHIFT,
 689               &disp_ctrl->cmd.disp_cmd);
 690        writel(reg_val, &disp_ctrl->cmd.state_access);
 691}
 692
 693int tegra_dc_sor_enable_dp(struct udevice *dev,
 694                           const struct tegra_dp_link_config *link_cfg)
 695{
 696        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
 697        int ret;
 698
 699        tegra_sor_write_field(sor, CLK_CNTRL,
 700                              CLK_CNTRL_DP_CLK_SEL_MASK,
 701                              CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK);
 702
 703        tegra_sor_write_field(sor, PLL2,
 704                              PLL2_AUX6_BANDGAP_POWERDOWN_MASK,
 705                              PLL2_AUX6_BANDGAP_POWERDOWN_DISABLE);
 706        udelay(25);
 707
 708        tegra_sor_write_field(sor, PLL3,
 709                              PLL3_PLLVDD_MODE_MASK,
 710                              PLL3_PLLVDD_MODE_V3_3);
 711        tegra_sor_writel(sor, PLL0,
 712                         0xf << PLL0_ICHPMP_SHFIT |
 713                         0x3 << PLL0_VCOCAP_SHIFT |
 714                         PLL0_PLLREG_LEVEL_V45 |
 715                         PLL0_RESISTORSEL_EXT |
 716                         PLL0_PWR_ON | PLL0_VCOPD_RESCIND);
 717        tegra_sor_write_field(sor, PLL2,
 718                              PLL2_AUX1_SEQ_MASK |
 719                              PLL2_AUX9_LVDSEN_OVERRIDE |
 720                              PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_MASK,
 721                              PLL2_AUX1_SEQ_PLLCAPPD_OVERRIDE |
 722                              PLL2_AUX9_LVDSEN_OVERRIDE |
 723                              PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_DISABLE);
 724        tegra_sor_writel(sor, PLL1, PLL1_TERM_COMPOUT_HIGH |
 725                         PLL1_TMDS_TERM_ENABLE);
 726
 727        if (tegra_dc_sor_poll_register(sor, PLL2,
 728                                       PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_MASK,
 729                                       PLL2_AUX8_SEQ_PLLCAPPD_ENFORCE_DISABLE,
 730                                       100, TEGRA_SOR_TIMEOUT_MS)) {
 731                printf("DP failed to lock PLL\n");
 732                return -EIO;
 733        }
 734
 735        tegra_sor_write_field(sor, PLL2, PLL2_AUX2_MASK |
 736                              PLL2_AUX7_PORT_POWERDOWN_MASK,
 737                              PLL2_AUX2_OVERRIDE_POWERDOWN |
 738                              PLL2_AUX7_PORT_POWERDOWN_DISABLE);
 739
 740        ret = tegra_dc_sor_power_up(dev, 0);
 741        if (ret) {
 742                debug("DP failed to power up\n");
 743                return ret;
 744        }
 745
 746        /* re-enable SOR clock */
 747        clock_sor_enable_edp_clock();
 748
 749        /* Power up lanes */
 750        tegra_dc_sor_power_dplanes(dev, link_cfg->lane_count, 1);
 751
 752        tegra_dc_sor_set_dp_mode(dev, link_cfg);
 753        debug("%s ret\n", __func__);
 754
 755        return 0;
 756}
 757
 758int tegra_dc_sor_attach(struct udevice *dc_dev, struct udevice *dev,
 759                        const struct tegra_dp_link_config *link_cfg,
 760                        const struct display_timing *timing)
 761{
 762        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
 763        struct dc_ctlr *disp_ctrl;
 764        u32 reg_val;
 765
 766        /* Use the first display controller */
 767        debug("%s\n", __func__);
 768        disp_ctrl = (struct dc_ctlr *)dev_read_addr(dc_dev);
 769
 770        tegra_dc_sor_enable_dc(disp_ctrl);
 771        tegra_dc_sor_config_panel(sor, 0, link_cfg, timing);
 772
 773        writel(0x9f00, &disp_ctrl->cmd.state_ctrl);
 774        writel(0x9f, &disp_ctrl->cmd.state_ctrl);
 775
 776        writel(PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
 777               PW4_ENABLE | PM0_ENABLE | PM1_ENABLE,
 778               &disp_ctrl->cmd.disp_pow_ctrl);
 779
 780        reg_val = tegra_sor_readl(sor, TEST);
 781        if (reg_val & TEST_ATTACHED_TRUE)
 782                return -EEXIST;
 783
 784        tegra_sor_writel(sor, SUPER_STATE1,
 785                         SUPER_STATE1_ATTACHED_NO);
 786
 787        /*
 788         * Enable display2sor clock at least 2 cycles before DC start,
 789         * to clear sor internal valid signal.
 790         */
 791        writel(SOR_ENABLE, &disp_ctrl->disp.disp_win_opt);
 792        writel(GENERAL_ACT_REQ, &disp_ctrl->cmd.state_ctrl);
 793        writel(0, &disp_ctrl->disp.disp_win_opt);
 794        writel(GENERAL_ACT_REQ, &disp_ctrl->cmd.state_ctrl);
 795
 796        /* Attach head */
 797        tegra_dc_sor_update(sor);
 798        tegra_sor_writel(sor, SUPER_STATE1,
 799                         SUPER_STATE1_ATTACHED_YES);
 800        tegra_sor_writel(sor, SUPER_STATE1,
 801                         SUPER_STATE1_ATTACHED_YES |
 802                         SUPER_STATE1_ASY_HEAD_OP_AWAKE |
 803                         SUPER_STATE1_ASY_ORMODE_NORMAL);
 804        tegra_dc_sor_super_update(sor);
 805
 806        /* Enable dc */
 807        reg_val = readl(&disp_ctrl->cmd.state_access);
 808        writel(reg_val | WRITE_MUX_ACTIVE, &disp_ctrl->cmd.state_access);
 809        writel(CTRL_MODE_C_DISPLAY << CTRL_MODE_SHIFT,
 810               &disp_ctrl->cmd.disp_cmd);
 811        writel(SOR_ENABLE, &disp_ctrl->disp.disp_win_opt);
 812        writel(reg_val, &disp_ctrl->cmd.state_access);
 813
 814        if (tegra_dc_sor_poll_register(sor, TEST,
 815                                       TEST_ACT_HEAD_OPMODE_DEFAULT_MASK,
 816                                       TEST_ACT_HEAD_OPMODE_AWAKE,
 817                                       100,
 818                                       TEGRA_SOR_ATTACH_TIMEOUT_MS)) {
 819                printf("dc timeout waiting for OPMOD = AWAKE\n");
 820                return -ETIMEDOUT;
 821        } else {
 822                debug("%s: sor is attached\n", __func__);
 823        }
 824
 825#if DEBUG_SOR
 826        dump_sor_reg(sor);
 827#endif
 828        debug("%s: ret=%d\n", __func__, 0);
 829
 830        return 0;
 831}
 832
 833void tegra_dc_sor_set_lane_parm(struct udevice *dev,
 834                const struct tegra_dp_link_config *link_cfg)
 835{
 836        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
 837
 838        tegra_sor_writel(sor, LANE_DRIVE_CURRENT(sor->portnum),
 839                         link_cfg->drive_current);
 840        tegra_sor_writel(sor, PR(sor->portnum),
 841                         link_cfg->preemphasis);
 842        tegra_sor_writel(sor, POSTCURSOR(sor->portnum),
 843                         link_cfg->postcursor);
 844        tegra_sor_writel(sor, LVDS, 0);
 845
 846        tegra_dc_sor_set_link_bandwidth(dev, link_cfg->link_bw);
 847        tegra_dc_sor_set_lane_count(dev, link_cfg->lane_count);
 848
 849        tegra_sor_write_field(sor, DP_PADCTL(sor->portnum),
 850                              DP_PADCTL_TX_PU_ENABLE |
 851                              DP_PADCTL_TX_PU_VALUE_DEFAULT_MASK,
 852                              DP_PADCTL_TX_PU_ENABLE |
 853                              2 << DP_PADCTL_TX_PU_VALUE_SHIFT);
 854
 855        /* Precharge */
 856        tegra_sor_write_field(sor, DP_PADCTL(sor->portnum), 0xf0, 0xf0);
 857        udelay(20);
 858
 859        tegra_sor_write_field(sor, DP_PADCTL(sor->portnum), 0xf0, 0x0);
 860}
 861
 862int tegra_dc_sor_set_voltage_swing(struct udevice *dev,
 863                                    const struct tegra_dp_link_config *link_cfg)
 864{
 865        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
 866        u32 drive_current = 0;
 867        u32 pre_emphasis = 0;
 868
 869        /* Set to a known-good pre-calibrated setting */
 870        switch (link_cfg->link_bw) {
 871        case SOR_LINK_SPEED_G1_62:
 872        case SOR_LINK_SPEED_G2_7:
 873                drive_current = 0x13131313;
 874                pre_emphasis = 0;
 875                break;
 876        case SOR_LINK_SPEED_G5_4:
 877                debug("T124 does not support 5.4G link clock.\n");
 878        default:
 879                debug("Invalid sor link bandwidth: %d\n", link_cfg->link_bw);
 880                return -ENOLINK;
 881        }
 882
 883        tegra_sor_writel(sor, LANE_DRIVE_CURRENT(sor->portnum), drive_current);
 884        tegra_sor_writel(sor, PR(sor->portnum), pre_emphasis);
 885
 886        return 0;
 887}
 888
 889void tegra_dc_sor_power_down_unused_lanes(struct udevice *dev,
 890                        const struct tegra_dp_link_config *link_cfg)
 891{
 892        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
 893        u32 pad_ctrl = 0;
 894        int err = 0;
 895
 896        switch (link_cfg->lane_count) {
 897        case 4:
 898                pad_ctrl = DP_PADCTL_PD_TXD_0_NO |
 899                        DP_PADCTL_PD_TXD_1_NO |
 900                        DP_PADCTL_PD_TXD_2_NO |
 901                        DP_PADCTL_PD_TXD_3_NO;
 902                break;
 903        case 2:
 904                pad_ctrl = DP_PADCTL_PD_TXD_0_NO |
 905                        DP_PADCTL_PD_TXD_1_NO |
 906                        DP_PADCTL_PD_TXD_2_YES |
 907                        DP_PADCTL_PD_TXD_3_YES;
 908                break;
 909        case 1:
 910                pad_ctrl = DP_PADCTL_PD_TXD_0_NO |
 911                        DP_PADCTL_PD_TXD_1_YES |
 912                        DP_PADCTL_PD_TXD_2_YES |
 913                        DP_PADCTL_PD_TXD_3_YES;
 914                break;
 915        default:
 916                printf("Invalid sor lane count: %u\n", link_cfg->lane_count);
 917                return;
 918        }
 919
 920        pad_ctrl |= DP_PADCTL_PAD_CAL_PD_POWERDOWN;
 921        tegra_sor_writel(sor, DP_PADCTL(sor->portnum), pad_ctrl);
 922
 923        err = tegra_dc_sor_enable_lane_sequencer(sor, 0, 0);
 924        if (err) {
 925                debug("Wait for lane power down failed: %d\n", err);
 926                return;
 927        }
 928}
 929
 930int tegra_sor_precharge_lanes(struct udevice *dev,
 931                              const struct tegra_dp_link_config *cfg)
 932{
 933        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
 934        u32 val = 0;
 935
 936        switch (cfg->lane_count) {
 937        case 4:
 938                val |= (DP_PADCTL_PD_TXD_3_NO |
 939                        DP_PADCTL_PD_TXD_2_NO);
 940                /* fall through */
 941        case 2:
 942                val |= DP_PADCTL_PD_TXD_1_NO;
 943                /* fall through */
 944        case 1:
 945                val |= DP_PADCTL_PD_TXD_0_NO;
 946                break;
 947        default:
 948                debug("dp: invalid lane number %d\n", cfg->lane_count);
 949                return -EINVAL;
 950        }
 951
 952        tegra_sor_write_field(sor, DP_PADCTL(sor->portnum),
 953                              (0xf << DP_PADCTL_COMODE_TXD_0_DP_TXD_2_SHIFT),
 954                              (val << DP_PADCTL_COMODE_TXD_0_DP_TXD_2_SHIFT));
 955        udelay(100);
 956        tegra_sor_write_field(sor, DP_PADCTL(sor->portnum),
 957                              (0xf << DP_PADCTL_COMODE_TXD_0_DP_TXD_2_SHIFT),
 958                              0);
 959
 960        return 0;
 961}
 962
 963static void tegra_dc_sor_enable_sor(struct dc_ctlr *disp_ctrl, bool enable)
 964{
 965        u32 reg_val = readl(&disp_ctrl->disp.disp_win_opt);
 966
 967        reg_val = enable ? reg_val | SOR_ENABLE : reg_val & ~SOR_ENABLE;
 968        writel(reg_val, &disp_ctrl->disp.disp_win_opt);
 969}
 970
 971int tegra_dc_sor_detach(struct udevice *dc_dev, struct udevice *dev)
 972{
 973        struct tegra_dc_sor_data *sor = dev_get_priv(dev);
 974        int dc_reg_ctx[DC_REG_SAVE_SPACE];
 975        struct dc_ctlr *disp_ctrl;
 976        unsigned long dc_int_mask;
 977        int ret;
 978
 979        debug("%s\n", __func__);
 980        /* Use the first display controller */
 981        disp_ctrl = (struct dc_ctlr *)dev_read_addr(dev);
 982
 983        /* Sleep mode */
 984        tegra_sor_writel(sor, SUPER_STATE1, SUPER_STATE1_ASY_HEAD_OP_SLEEP |
 985                         SUPER_STATE1_ASY_ORMODE_SAFE |
 986                         SUPER_STATE1_ATTACHED_YES);
 987        tegra_dc_sor_super_update(sor);
 988
 989        tegra_dc_sor_disable_win_short_raster(disp_ctrl, dc_reg_ctx);
 990
 991        if (tegra_dc_sor_poll_register(sor, TEST,
 992                                       TEST_ACT_HEAD_OPMODE_DEFAULT_MASK,
 993                                       TEST_ACT_HEAD_OPMODE_SLEEP, 100,
 994                                       TEGRA_SOR_ATTACH_TIMEOUT_MS)) {
 995                debug("dc timeout waiting for OPMOD = SLEEP\n");
 996                ret = -ETIMEDOUT;
 997                goto err;
 998        }
 999
1000        tegra_sor_writel(sor, SUPER_STATE1, SUPER_STATE1_ASY_HEAD_OP_SLEEP |
1001                         SUPER_STATE1_ASY_ORMODE_SAFE |
1002                         SUPER_STATE1_ATTACHED_NO);
1003
1004        /* Mask DC interrupts during the 2 dummy frames required for detach */
1005        dc_int_mask = readl(&disp_ctrl->cmd.int_mask);
1006        writel(0, &disp_ctrl->cmd.int_mask);
1007
1008        /* Stop DC->SOR path */
1009        tegra_dc_sor_enable_sor(disp_ctrl, false);
1010        ret = tegra_dc_sor_general_act(disp_ctrl);
1011        if (ret)
1012                goto err;
1013
1014        /* Stop DC */
1015        writel(CTRL_MODE_STOP << CTRL_MODE_SHIFT, &disp_ctrl->cmd.disp_cmd);
1016        ret = tegra_dc_sor_general_act(disp_ctrl);
1017        if (ret)
1018                goto err;
1019
1020        tegra_dc_sor_restore_win_and_raster(disp_ctrl, dc_reg_ctx);
1021
1022        writel(dc_int_mask, &disp_ctrl->cmd.int_mask);
1023
1024        return 0;
1025err:
1026        debug("%s: ret=%d\n", __func__, ret);
1027
1028        return ret;
1029}
1030
1031static int tegra_sor_set_backlight(struct udevice *dev, int percent)
1032{
1033        struct tegra_dc_sor_data *priv = dev_get_priv(dev);
1034        int ret;
1035
1036        ret = panel_enable_backlight(priv->panel);
1037        if (ret) {
1038                debug("sor: Cannot enable panel backlight\n");
1039                return ret;
1040        }
1041
1042        return 0;
1043}
1044
1045static int tegra_sor_of_to_plat(struct udevice *dev)
1046{
1047        struct tegra_dc_sor_data *priv = dev_get_priv(dev);
1048        int ret;
1049
1050        priv->base = (void *)dev_read_addr(dev);
1051
1052        priv->pmc_base = (void *)syscon_get_first_range(TEGRA_SYSCON_PMC);
1053        if (IS_ERR(priv->pmc_base))
1054                return PTR_ERR(priv->pmc_base);
1055
1056        ret = uclass_get_device_by_phandle(UCLASS_PANEL, dev, "nvidia,panel",
1057                                           &priv->panel);
1058        if (ret) {
1059                debug("%s: Cannot find panel for '%s' (ret=%d)\n", __func__,
1060                      dev->name, ret);
1061                return ret;
1062        }
1063
1064        return 0;
1065}
1066
1067static const struct video_bridge_ops tegra_sor_ops = {
1068        .set_backlight  = tegra_sor_set_backlight,
1069};
1070
1071static const struct udevice_id tegra_sor_ids[] = {
1072        { .compatible = "nvidia,tegra124-sor" },
1073        { }
1074};
1075
1076U_BOOT_DRIVER(sor_tegra) = {
1077        .name   = "sor_tegra",
1078        .id     = UCLASS_VIDEO_BRIDGE,
1079        .of_match = tegra_sor_ids,
1080        .of_to_plat = tegra_sor_of_to_plat,
1081        .ops    = &tegra_sor_ops,
1082        .priv_auto      = sizeof(struct tegra_dc_sor_data),
1083};
1084