uboot/drivers/video/broadwell_igd.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * From coreboot src/soc/intel/broadwell/igd.c
   4 *
   5 * Copyright (C) 2016 Google, Inc
   6 */
   7
   8#include <common.h>
   9#include <bios_emul.h>
  10#include <bootstage.h>
  11#include <dm.h>
  12#include <init.h>
  13#include <log.h>
  14#include <vbe.h>
  15#include <video.h>
  16#include <asm/cpu.h>
  17#include <asm/global_data.h>
  18#include <asm/intel_regs.h>
  19#include <asm/io.h>
  20#include <asm/mtrr.h>
  21#include <asm/arch/cpu.h>
  22#include <asm/arch/iomap.h>
  23#include <asm/arch/pch.h>
  24#include <linux/delay.h>
  25#include "i915_reg.h"
  26
  27struct broadwell_igd_priv {
  28        u8 *regs;
  29};
  30
  31struct broadwell_igd_plat {
  32        u32 dp_hotplug[3];
  33
  34        int port_select;
  35        int power_up_delay;
  36        int power_backlight_on_delay;
  37        int power_down_delay;
  38        int power_backlight_off_delay;
  39        int power_cycle_delay;
  40        int cpu_backlight;
  41        int pch_backlight;
  42        int cdclk;
  43        int pre_graphics_delay;
  44};
  45
  46#define GT_RETRY                1000
  47#define GT_CDCLK_337            0
  48#define GT_CDCLK_450            1
  49#define GT_CDCLK_540            2
  50#define GT_CDCLK_675            3
  51
  52u32 board_map_oprom_vendev(u32 vendev)
  53{
  54        return SA_IGD_OPROM_VENDEV;
  55}
  56
  57static int poll32(u8 *addr, uint mask, uint value)
  58{
  59        ulong start;
  60
  61        start = get_timer(0);
  62        debug("%s: addr %p = %x\n", __func__, addr, readl(addr));
  63        while ((readl(addr) & mask) != value) {
  64                if (get_timer(start) > GT_RETRY) {
  65                        debug("poll32: timeout: %x\n", readl(addr));
  66                        return -ETIMEDOUT;
  67                }
  68        }
  69
  70        return 0;
  71}
  72
  73static int haswell_early_init(struct udevice *dev)
  74{
  75        struct broadwell_igd_priv *priv = dev_get_priv(dev);
  76        u8 *regs = priv->regs;
  77        int ret;
  78
  79        /* Enable Force Wake */
  80        writel(0x00000020, regs + 0xa180);
  81        writel(0x00010001, regs + 0xa188);
  82        ret = poll32(regs + 0x130044, 1, 1);
  83        if (ret)
  84                goto err;
  85
  86        /* Enable Counters */
  87        setbits_le32(regs + 0xa248, 0x00000016);
  88
  89        /* GFXPAUSE settings */
  90        writel(0x00070020, regs + 0xa000);
  91
  92        /* ECO Settings */
  93        clrsetbits_le32(regs + 0xa180, ~0xff3fffff, 0x15000000);
  94
  95        /* Enable DOP Clock Gating */
  96        writel(0x000003fd, regs + 0x9424);
  97
  98        /* Enable Unit Level Clock Gating */
  99        writel(0x00000080, regs + 0x9400);
 100        writel(0x40401000, regs + 0x9404);
 101        writel(0x00000000, regs + 0x9408);
 102        writel(0x02000001, regs + 0x940c);
 103
 104        /*
 105         * RC6 Settings
 106         */
 107
 108        /* Wake Rate Limits */
 109        setbits_le32(regs + 0xa090, 0x00000000);
 110        setbits_le32(regs + 0xa098, 0x03e80000);
 111        setbits_le32(regs + 0xa09c, 0x00280000);
 112        setbits_le32(regs + 0xa0a8, 0x0001e848);
 113        setbits_le32(regs + 0xa0ac, 0x00000019);
 114
 115        /* Render/Video/Blitter Idle Max Count */
 116        writel(0x0000000a, regs + 0x02054);
 117        writel(0x0000000a, regs + 0x12054);
 118        writel(0x0000000a, regs + 0x22054);
 119        writel(0x0000000a, regs + 0x1a054);
 120
 121        /* RC Sleep / RCx Thresholds */
 122        setbits_le32(regs + 0xa0b0, 0x00000000);
 123        setbits_le32(regs + 0xa0b4, 0x000003e8);
 124        setbits_le32(regs + 0xa0b8, 0x0000c350);
 125
 126        /* RP Settings */
 127        setbits_le32(regs + 0xa010, 0x000f4240);
 128        setbits_le32(regs + 0xa014, 0x12060000);
 129        setbits_le32(regs + 0xa02c, 0x0000e808);
 130        setbits_le32(regs + 0xa030, 0x0003bd08);
 131        setbits_le32(regs + 0xa068, 0x000101d0);
 132        setbits_le32(regs + 0xa06c, 0x00055730);
 133        setbits_le32(regs + 0xa070, 0x0000000a);
 134
 135        /* RP Control */
 136        writel(0x00000b92, regs + 0xa024);
 137
 138        /* HW RC6 Control */
 139        writel(0x88040000, regs + 0xa090);
 140
 141        /* Video Frequency Request */
 142        writel(0x08000000, regs + 0xa00c);
 143
 144        /* Set RC6 VIDs */
 145        ret = poll32(regs + 0x138124, (1 << 31), 0);
 146        if (ret)
 147                goto err;
 148        writel(0, regs + 0x138128);
 149        writel(0x80000004, regs + 0x138124);
 150        ret = poll32(regs + 0x138124, (1 << 31), 0);
 151        if (ret)
 152                goto err;
 153
 154        /* Enable PM Interrupts */
 155        writel(0x03000076, regs + 0x4402c);
 156
 157        /* Enable RC6 in idle */
 158        writel(0x00040000, regs + 0xa094);
 159
 160        return 0;
 161err:
 162        debug("%s: ret=%d\n", __func__, ret);
 163        return ret;
 164};
 165
 166static int haswell_late_init(struct udevice *dev)
 167{
 168        struct broadwell_igd_priv *priv = dev_get_priv(dev);
 169        u8 *regs = priv->regs;
 170        int ret;
 171
 172        /* Lock settings */
 173        setbits_le32(regs + 0x0a248, (1 << 31));
 174        setbits_le32(regs + 0x0a004, (1 << 4));
 175        setbits_le32(regs + 0x0a080, (1 << 2));
 176        setbits_le32(regs + 0x0a180, (1 << 31));
 177
 178        /* Disable Force Wake */
 179        writel(0x00010000, regs + 0xa188);
 180        ret = poll32(regs + 0x130044, 1, 0);
 181        if (ret)
 182                goto err;
 183        writel(0x00000001, regs + 0xa188);
 184
 185        /* Enable power well for DP and Audio */
 186        setbits_le32(regs + 0x45400, (1 << 31));
 187        ret = poll32(regs + 0x45400, 1 << 30, 1 << 30);
 188        if (ret)
 189                goto err;
 190
 191        return 0;
 192err:
 193        debug("%s: ret=%d\n", __func__, ret);
 194        return ret;
 195};
 196
 197static int broadwell_early_init(struct udevice *dev)
 198{
 199        struct broadwell_igd_priv *priv = dev_get_priv(dev);
 200        u8 *regs = priv->regs;
 201        int ret;
 202
 203        /* Enable Force Wake */
 204        writel(0x00010001, regs + 0xa188);
 205        ret = poll32(regs + 0x130044, 1, 1);
 206        if (ret)
 207                goto err;
 208
 209        /* Enable push bus metric control and shift */
 210        writel(0x00000004, regs + 0xa248);
 211        writel(0x000000ff, regs + 0xa250);
 212        writel(0x00000010, regs + 0xa25c);
 213
 214        /* GFXPAUSE settings (set based on stepping) */
 215
 216        /* ECO Settings */
 217        writel(0x45200000, regs + 0xa180);
 218
 219        /* Enable DOP Clock Gating */
 220        writel(0x000000fd, regs + 0x9424);
 221
 222        /* Enable Unit Level Clock Gating */
 223        writel(0x00000000, regs + 0x9400);
 224        writel(0x40401000, regs + 0x9404);
 225        writel(0x00000000, regs + 0x9408);
 226        writel(0x02000001, regs + 0x940c);
 227        writel(0x0000000a, regs + 0x1a054);
 228
 229        /* Video Frequency Request */
 230        writel(0x08000000, regs + 0xa00c);
 231
 232        writel(0x00000009, regs + 0x138158);
 233        writel(0x0000000d, regs + 0x13815c);
 234
 235        /*
 236         * RC6 Settings
 237         */
 238
 239        /* Wake Rate Limits */
 240        clrsetbits_le32(regs + 0x0a090, ~0, 0);
 241        setbits_le32(regs + 0x0a098, 0x03e80000);
 242        setbits_le32(regs + 0x0a09c, 0x00280000);
 243        setbits_le32(regs + 0x0a0a8, 0x0001e848);
 244        setbits_le32(regs + 0x0a0ac, 0x00000019);
 245
 246        /* Render/Video/Blitter Idle Max Count */
 247        writel(0x0000000a, regs + 0x02054);
 248        writel(0x0000000a, regs + 0x12054);
 249        writel(0x0000000a, regs + 0x22054);
 250
 251        /* RC Sleep / RCx Thresholds */
 252        setbits_le32(regs + 0x0a0b0, 0x00000000);
 253        setbits_le32(regs + 0x0a0b8, 0x00000271);
 254
 255        /* RP Settings */
 256        setbits_le32(regs + 0x0a010, 0x000f4240);
 257        setbits_le32(regs + 0x0a014, 0x12060000);
 258        setbits_le32(regs + 0x0a02c, 0x0000e808);
 259        setbits_le32(regs + 0x0a030, 0x0003bd08);
 260        setbits_le32(regs + 0x0a068, 0x000101d0);
 261        setbits_le32(regs + 0x0a06c, 0x00055730);
 262        setbits_le32(regs + 0x0a070, 0x0000000a);
 263        setbits_le32(regs + 0x0a168, 0x00000006);
 264
 265        /* RP Control */
 266        writel(0x00000b92, regs + 0xa024);
 267
 268        /* HW RC6 Control */
 269        writel(0x90040000, regs + 0xa090);
 270
 271        /* Set RC6 VIDs */
 272        ret = poll32(regs + 0x138124, (1 << 31), 0);
 273        if (ret)
 274                goto err;
 275        writel(0, regs + 0x138128);
 276        writel(0x80000004, regs + 0x138124);
 277        ret = poll32(regs + 0x138124, (1 << 31), 0);
 278        if (ret)
 279                goto err;
 280
 281        /* Enable PM Interrupts */
 282        writel(0x03000076, regs + 0x4402c);
 283
 284        /* Enable RC6 in idle */
 285        writel(0x00040000, regs + 0xa094);
 286
 287        return 0;
 288err:
 289        debug("%s: ret=%d\n", __func__, ret);
 290        return ret;
 291}
 292
 293static int broadwell_late_init(struct udevice *dev)
 294{
 295        struct broadwell_igd_priv *priv = dev_get_priv(dev);
 296        u8 *regs = priv->regs;
 297        int ret;
 298
 299        /* Lock settings */
 300        setbits_le32(regs + 0x0a248, 1 << 31);
 301        setbits_le32(regs + 0x0a000, 1 << 18);
 302        setbits_le32(regs + 0x0a180, 1 << 31);
 303
 304        /* Disable Force Wake */
 305        writel(0x00010000, regs + 0xa188);
 306        ret = poll32(regs + 0x130044, 1, 0);
 307        if (ret)
 308                goto err;
 309
 310        /* Enable power well for DP and Audio */
 311        setbits_le32(regs + 0x45400, 1 << 31);
 312        ret = poll32(regs + 0x45400, 1 << 30, 1 << 30);
 313        if (ret)
 314                goto err;
 315
 316        return 0;
 317err:
 318        debug("%s: ret=%d\n", __func__, ret);
 319        return ret;
 320};
 321
 322
 323static unsigned long gtt_read(struct broadwell_igd_priv *priv,
 324                              unsigned long reg)
 325{
 326        return readl(priv->regs + reg);
 327}
 328
 329static void gtt_write(struct broadwell_igd_priv *priv, unsigned long reg,
 330                      unsigned long data)
 331{
 332        writel(data, priv->regs + reg);
 333}
 334
 335static inline void gtt_clrsetbits(struct broadwell_igd_priv *priv, u32 reg,
 336                                  u32 bic, u32 or)
 337{
 338        clrsetbits_le32(priv->regs + reg, bic, or);
 339}
 340
 341static int gtt_poll(struct broadwell_igd_priv *priv, u32 reg, u32 mask,
 342                    u32 value)
 343{
 344        unsigned try = GT_RETRY;
 345        u32 data;
 346
 347        while (try--) {
 348                data = gtt_read(priv, reg);
 349                if ((data & mask) == value)
 350                        return 0;
 351                udelay(10);
 352        }
 353
 354        debug("GT init timeout\n");
 355        return -ETIMEDOUT;
 356}
 357
 358static void igd_setup_panel(struct udevice *dev)
 359{
 360        struct broadwell_igd_plat *plat = dev_get_plat(dev);
 361        struct broadwell_igd_priv *priv = dev_get_priv(dev);
 362        u32 reg32;
 363
 364        /* Setup Digital Port Hotplug */
 365        reg32 = (plat->dp_hotplug[0] & 0x7) << 2;
 366        reg32 |= (plat->dp_hotplug[1] & 0x7) << 10;
 367        reg32 |= (plat->dp_hotplug[2] & 0x7) << 18;
 368        gtt_write(priv, PCH_PORT_HOTPLUG, reg32);
 369
 370        /* Setup Panel Power On Delays */
 371        reg32 = (plat->port_select & 0x3) << 30;
 372        reg32 |= (plat->power_up_delay & 0x1fff) << 16;
 373        reg32 |= (plat->power_backlight_on_delay & 0x1fff);
 374        gtt_write(priv, PCH_PP_ON_DELAYS, reg32);
 375
 376        /* Setup Panel Power Off Delays */
 377        reg32 = (plat->power_down_delay & 0x1fff) << 16;
 378        reg32 |= (plat->power_backlight_off_delay & 0x1fff);
 379        gtt_write(priv, PCH_PP_OFF_DELAYS, reg32);
 380
 381        /* Setup Panel Power Cycle Delay */
 382        if (plat->power_cycle_delay) {
 383                reg32 = gtt_read(priv, PCH_PP_DIVISOR);
 384                reg32 &= ~0xff;
 385                reg32 |= plat->power_cycle_delay & 0xff;
 386                gtt_write(priv, PCH_PP_DIVISOR, reg32);
 387        }
 388
 389        /* Enable Backlight if needed */
 390        if (plat->cpu_backlight) {
 391                gtt_write(priv, BLC_PWM_CPU_CTL2, BLC_PWM2_ENABLE);
 392                gtt_write(priv, BLC_PWM_CPU_CTL, plat->cpu_backlight);
 393        }
 394        if (plat->pch_backlight) {
 395                gtt_write(priv, BLC_PWM_PCH_CTL1, BLM_PCH_PWM_ENABLE);
 396                gtt_write(priv, BLC_PWM_PCH_CTL2, plat->pch_backlight);
 397        }
 398}
 399
 400static int igd_cdclk_init_haswell(struct udevice *dev)
 401{
 402        struct broadwell_igd_plat *plat = dev_get_plat(dev);
 403        struct broadwell_igd_priv *priv = dev_get_priv(dev);
 404        int cdclk = plat->cdclk;
 405        u16 devid;
 406        int gpu_is_ulx = 0;
 407        u32 dpdiv, lpcll;
 408        int ret;
 409
 410        dm_pci_read_config16(dev, PCI_DEVICE_ID, &devid);
 411
 412        /* Check for ULX GT1 or GT2 */
 413        if (devid == 0x0a0e || devid == 0x0a1e)
 414                gpu_is_ulx = 1;
 415
 416        /* 675MHz is not supported on haswell */
 417        if (cdclk == GT_CDCLK_675)
 418                cdclk = GT_CDCLK_337;
 419
 420        /* If CD clock is fixed or ULT then set to 450MHz */
 421        if ((gtt_read(priv, 0x42014) & 0x1000000) || cpu_is_ult())
 422                cdclk = GT_CDCLK_450;
 423
 424        /* 540MHz is not supported on ULX */
 425        if (gpu_is_ulx && cdclk == GT_CDCLK_540)
 426                cdclk = GT_CDCLK_337;
 427
 428        /* 337.5MHz is not supported on non-ULT/ULX */
 429        if (!gpu_is_ulx && !cpu_is_ult() && cdclk == GT_CDCLK_337)
 430                cdclk = GT_CDCLK_450;
 431
 432        /* Set variables based on CD Clock setting */
 433        switch (cdclk) {
 434        case GT_CDCLK_337:
 435                dpdiv = 169;
 436                lpcll = (1 << 26);
 437                break;
 438        case GT_CDCLK_450:
 439                dpdiv = 225;
 440                lpcll = 0;
 441                break;
 442        case GT_CDCLK_540:
 443                dpdiv = 270;
 444                lpcll = (1 << 26);
 445                break;
 446        default:
 447                ret = -EDOM;
 448                goto err;
 449        }
 450
 451        /* Set LPCLL_CTL CD Clock Frequency Select */
 452        gtt_clrsetbits(priv, 0x130040, ~0xf3ffffff, lpcll);
 453
 454        /* ULX: Inform power controller of selected frequency */
 455        if (gpu_is_ulx) {
 456                if (cdclk == GT_CDCLK_450)
 457                        gtt_write(priv, 0x138128, 0x00000000); /* 450MHz */
 458                else
 459                        gtt_write(priv, 0x138128, 0x00000001); /* 337.5MHz */
 460                gtt_write(priv, 0x13812c, 0x00000000);
 461                gtt_write(priv, 0x138124, 0x80000017);
 462        }
 463
 464        /* Set CPU DP AUX 2X bit clock dividers */
 465        gtt_clrsetbits(priv, 0x64010, ~0xfffff800, dpdiv);
 466        gtt_clrsetbits(priv, 0x64810, ~0xfffff800, dpdiv);
 467
 468        return 0;
 469err:
 470        debug("%s: ret=%d\n", __func__, ret);
 471        return ret;
 472}
 473
 474static int igd_cdclk_init_broadwell(struct udevice *dev)
 475{
 476        struct broadwell_igd_plat *plat = dev_get_plat(dev);
 477        struct broadwell_igd_priv *priv = dev_get_priv(dev);
 478        int cdclk = plat->cdclk;
 479        u32 dpdiv, lpcll, pwctl, cdset;
 480        int ret;
 481
 482        /* Inform power controller of upcoming frequency change */
 483        gtt_write(priv, 0x138128, 0);
 484        gtt_write(priv, 0x13812c, 0);
 485        gtt_write(priv, 0x138124, 0x80000018);
 486
 487        /* Poll GT driver mailbox for run/busy clear */
 488        if (gtt_poll(priv, 0x138124, 1 << 31, 0 << 31))
 489                cdclk = GT_CDCLK_450;
 490
 491        if (gtt_read(priv, 0x42014) & 0x1000000) {
 492                /* If CD clock is fixed then set to 450MHz */
 493                cdclk = GT_CDCLK_450;
 494        } else {
 495                /* Program CD clock to highest supported freq */
 496                if (cpu_is_ult())
 497                        cdclk = GT_CDCLK_540;
 498                else
 499                        cdclk = GT_CDCLK_675;
 500        }
 501
 502        /* CD clock frequency 675MHz not supported on ULT */
 503        if (cpu_is_ult() && cdclk == GT_CDCLK_675)
 504                cdclk = GT_CDCLK_540;
 505
 506        /* Set variables based on CD Clock setting */
 507        switch (cdclk) {
 508        case GT_CDCLK_337:
 509                cdset = 337;
 510                lpcll = (1 << 27);
 511                pwctl = 2;
 512                dpdiv = 169;
 513                break;
 514        case GT_CDCLK_450:
 515                cdset = 449;
 516                lpcll = 0;
 517                pwctl = 0;
 518                dpdiv = 225;
 519                break;
 520        case GT_CDCLK_540:
 521                cdset = 539;
 522                lpcll = (1 << 26);
 523                pwctl = 1;
 524                dpdiv = 270;
 525                break;
 526        case GT_CDCLK_675:
 527                cdset = 674;
 528                lpcll = (1 << 26) | (1 << 27);
 529                pwctl = 3;
 530                dpdiv = 338;
 531                break;
 532        default:
 533                ret = -EDOM;
 534                goto err;
 535        }
 536        debug("%s: frequency = %d\n", __func__, cdclk);
 537
 538        /* Set LPCLL_CTL CD Clock Frequency Select */
 539        gtt_clrsetbits(priv, 0x130040, ~0xf3ffffff, lpcll);
 540
 541        /* Inform power controller of selected frequency */
 542        gtt_write(priv, 0x138128, pwctl);
 543        gtt_write(priv, 0x13812c, 0);
 544        gtt_write(priv, 0x138124, 0x80000017);
 545
 546        /* Program CD Clock Frequency */
 547        gtt_clrsetbits(priv, 0x46200, ~0xfffffc00, cdset);
 548
 549        /* Set CPU DP AUX 2X bit clock dividers */
 550        gtt_clrsetbits(priv, 0x64010, ~0xfffff800, dpdiv);
 551        gtt_clrsetbits(priv, 0x64810, ~0xfffff800, dpdiv);
 552
 553        return 0;
 554err:
 555        debug("%s: ret=%d\n", __func__, ret);
 556        return ret;
 557}
 558
 559u8 systemagent_revision(struct udevice *bus)
 560{
 561        ulong val;
 562
 563        pci_bus_read_config(bus, PCI_BDF(0, 0, 0), PCI_REVISION_ID, &val,
 564                            PCI_SIZE_32);
 565
 566        return val;
 567}
 568
 569static int igd_pre_init(struct udevice *dev, bool is_broadwell)
 570{
 571        struct broadwell_igd_plat *plat = dev_get_plat(dev);
 572        struct broadwell_igd_priv *priv = dev_get_priv(dev);
 573        u32 rp1_gfx_freq;
 574        int ret;
 575
 576        mdelay(plat->pre_graphics_delay);
 577
 578        /* Early init steps */
 579        if (is_broadwell) {
 580                ret = broadwell_early_init(dev);
 581                if (ret)
 582                        goto err;
 583
 584                /* Set GFXPAUSE based on stepping */
 585                if (cpu_get_stepping() <= (CPUID_BROADWELL_E0 & 0xf) &&
 586                    systemagent_revision(pci_get_controller(dev)) <= 9) {
 587                        gtt_write(priv, 0xa000, 0x300ff);
 588                } else {
 589                        gtt_write(priv, 0xa000, 0x30020);
 590                }
 591        } else {
 592                ret = haswell_early_init(dev);
 593                if (ret)
 594                        goto err;
 595        }
 596
 597        /* Set RP1 graphics frequency */
 598        rp1_gfx_freq = (readl(MCHBAR_REG(0x5998)) >> 8) & 0xff;
 599        gtt_write(priv, 0xa008, rp1_gfx_freq << 24);
 600
 601        /* Post VBIOS panel setup */
 602        igd_setup_panel(dev);
 603
 604        return 0;
 605err:
 606        debug("%s: ret=%d\n", __func__, ret);
 607        return ret;
 608}
 609
 610static int igd_post_init(struct udevice *dev, bool is_broadwell)
 611{
 612        int ret;
 613
 614        /* Late init steps */
 615        if (is_broadwell) {
 616                ret = igd_cdclk_init_broadwell(dev);
 617                if (ret)
 618                        return ret;
 619                ret = broadwell_late_init(dev);
 620                if (ret)
 621                        return ret;
 622        } else {
 623                igd_cdclk_init_haswell(dev);
 624                ret = haswell_late_init(dev);
 625                if (ret)
 626                        return ret;
 627        }
 628
 629        return 0;
 630}
 631
 632static int broadwell_igd_int15_handler(void)
 633{
 634        int res = 0;
 635
 636        debug("%s: INT15 function %04x!\n", __func__, M.x86.R_AX);
 637
 638        switch (M.x86.R_AX) {
 639        case 0x5f35:
 640                /*
 641                 * Boot Display Device Hook:
 642                 *  bit 0 = CRT
 643                 *  bit 1 = TV (eDP)
 644                 *  bit 2 = EFP
 645                 *  bit 3 = LFP
 646                 *  bit 4 = CRT2
 647                 *  bit 5 = TV2 (eDP)
 648                 *  bit 6 = EFP2
 649                 *  bit 7 = LFP2
 650                 */
 651                M.x86.R_AX = 0x005f;
 652                M.x86.R_CX = 0x0000; /* Use video bios default */
 653                res = 1;
 654                break;
 655        default:
 656                debug("Unknown INT15 function %04x!\n", M.x86.R_AX);
 657                break;
 658        }
 659
 660        return res;
 661}
 662
 663static int broadwell_igd_probe(struct udevice *dev)
 664{
 665        struct video_uc_plat *plat = dev_get_uclass_plat(dev);
 666        struct video_priv *uc_priv = dev_get_uclass_priv(dev);
 667        bool is_broadwell;
 668        ulong fbbase;
 669        int ret;
 670
 671        if (!ll_boot_init()) {
 672                /*
 673                 * If we are running from EFI or coreboot, this driver can't
 674                 * work.
 675                 */
 676                printf("Not available (previous bootloader prevents it)\n");
 677                return -EPERM;
 678        }
 679        is_broadwell = cpu_get_family_model() == BROADWELL_FAMILY_ULT;
 680        bootstage_start(BOOTSTAGE_ID_ACCUM_LCD, "vesa display");
 681        debug("%s: is_broadwell=%d\n", __func__, is_broadwell);
 682        ret = igd_pre_init(dev, is_broadwell);
 683        if (!ret) {
 684                ret = vbe_setup_video(dev, broadwell_igd_int15_handler);
 685                if (ret)
 686                        debug("failed to run video BIOS: %d\n", ret);
 687        }
 688        if (!ret)
 689                ret = igd_post_init(dev, is_broadwell);
 690        bootstage_accum(BOOTSTAGE_ID_ACCUM_LCD);
 691        if (ret)
 692                return ret;
 693
 694        /* Use write-combining for the graphics memory, 256MB */
 695        fbbase = IS_ENABLED(CONFIG_VIDEO_COPY) ? plat->copy_base : plat->base;
 696        ret = mtrr_add_request(MTRR_TYPE_WRCOMB, fbbase, 256 << 20);
 697        if (!ret)
 698                ret = mtrr_commit(true);
 699        if (ret && ret != -ENOSYS) {
 700                printf("Failed to add MTRR: Display will be slow (err %d)\n",
 701                       ret);
 702        }
 703
 704        debug("fb=%lx, size %x, display size=%d %d %d\n", plat->base,
 705              plat->size, uc_priv->xsize, uc_priv->ysize, uc_priv->bpix);
 706
 707        return 0;
 708}
 709
 710static int broadwell_igd_of_to_plat(struct udevice *dev)
 711{
 712        struct broadwell_igd_plat *plat = dev_get_plat(dev);
 713        struct broadwell_igd_priv *priv = dev_get_priv(dev);
 714        int node = dev_of_offset(dev);
 715        const void *blob = gd->fdt_blob;
 716
 717        if (fdtdec_get_int_array(blob, node, "intel,dp-hotplug",
 718                                 plat->dp_hotplug,
 719                                 ARRAY_SIZE(plat->dp_hotplug)))
 720                return -EINVAL;
 721        plat->port_select = fdtdec_get_int(blob, node, "intel,port-select", 0);
 722        plat->power_cycle_delay = fdtdec_get_int(blob, node,
 723                        "intel,power-cycle-delay", 0);
 724        plat->power_up_delay = fdtdec_get_int(blob, node,
 725                        "intel,power-up-delay", 0);
 726        plat->power_down_delay = fdtdec_get_int(blob, node,
 727                        "intel,power-down-delay", 0);
 728        plat->power_backlight_on_delay = fdtdec_get_int(blob, node,
 729                        "intel,power-backlight-on-delay", 0);
 730        plat->power_backlight_off_delay = fdtdec_get_int(blob, node,
 731                        "intel,power-backlight-off-delay", 0);
 732        plat->cpu_backlight = fdtdec_get_int(blob, node,
 733                        "intel,cpu-backlight", 0);
 734        plat->pch_backlight = fdtdec_get_int(blob, node,
 735                        "intel,pch-backlight", 0);
 736        plat->pre_graphics_delay = fdtdec_get_int(blob, node,
 737                        "intel,pre-graphics-delay", 0);
 738        priv->regs = (u8 *)dm_pci_read_bar32(dev, 0);
 739        debug("%s: regs at %p\n", __func__, priv->regs);
 740        debug("dp_hotplug %d %d %d\n", plat->dp_hotplug[0], plat->dp_hotplug[1],
 741              plat->dp_hotplug[2]);
 742        debug("port_select = %d\n", plat->port_select);
 743        debug("power_up_delay = %d\n", plat->power_up_delay);
 744        debug("power_backlight_on_delay = %d\n",
 745              plat->power_backlight_on_delay);
 746        debug("power_down_delay = %d\n", plat->power_down_delay);
 747        debug("power_backlight_off_delay = %d\n",
 748              plat->power_backlight_off_delay);
 749        debug("power_cycle_delay = %d\n", plat->power_cycle_delay);
 750        debug("cpu_backlight = %x\n", plat->cpu_backlight);
 751        debug("pch_backlight = %x\n", plat->pch_backlight);
 752        debug("cdclk = %d\n", plat->cdclk);
 753        debug("pre_graphics_delay = %d\n", plat->pre_graphics_delay);
 754
 755        return 0;
 756}
 757
 758static int broadwell_igd_bind(struct udevice *dev)
 759{
 760        struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev);
 761
 762        /* Set the maximum supported resolution */
 763        uc_plat->size = 2560 * 1600 * 4;
 764        log_debug("%s: Frame buffer size %x\n", __func__, uc_plat->size);
 765
 766        return 0;
 767}
 768
 769static const struct video_ops broadwell_igd_ops = {
 770};
 771
 772static const struct udevice_id broadwell_igd_ids[] = {
 773        { .compatible = "intel,broadwell-igd" },
 774        { }
 775};
 776
 777U_BOOT_DRIVER(broadwell_igd) = {
 778        .name   = "broadwell_igd",
 779        .id     = UCLASS_VIDEO,
 780        .of_match = broadwell_igd_ids,
 781        .ops    = &broadwell_igd_ops,
 782        .of_to_plat = broadwell_igd_of_to_plat,
 783        .bind   = broadwell_igd_bind,
 784        .probe  = broadwell_igd_probe,
 785        .priv_auto      = sizeof(struct broadwell_igd_priv),
 786        .plat_auto      = sizeof(struct broadwell_igd_plat),
 787};
 788