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