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