1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <stdint.h>
4 #include <device/pci_ops.h>
5 #include <device/pci_def.h>
6 #include <console/console.h>
7 #include <option.h>
8
9 #include "gm45.h"
10
11 /* TODO: Chipset supports Protected Audio Video Path (PAVP) */
12
13 /* TODO: We could pass DVMT structure in GetBIOSData() SCI interface */
14
15 /* The PEG settings have to be set before ASPM is setup on DMI. */
enable_igd(const sysinfo_t * const sysinfo,const int no_peg)16 static void enable_igd(const sysinfo_t *const sysinfo, const int no_peg)
17 {
18 const pci_devfn_t mch_dev = PCI_DEV(0, 0, 0);
19 const pci_devfn_t peg_dev = PCI_DEV(0, 1, 0);
20 const pci_devfn_t igd_dev = PCI_DEV(0, 2, 0);
21
22 printk(BIOS_DEBUG, "Enabling IGD.\n");
23
24 /* HSync/VSync */
25 mchbar_write8(0xbd0 + 3, 0x5a);
26 mchbar_write8(0xbd0 + 4, 0x5a);
27
28 static const u16 display_clock_from_f0_and_vco[][4] = {
29 /* VCO 2666 VCO 3200 VCO 4000 VCO 5333 */
30 { 222, 228, 222, 222, },
31 { 333, 320, 333, 333, },
32 };
33 const int f0_12 = (pci_read_config16(igd_dev, 0xf0) >> 12) & 1;
34 const int vco = raminit_read_vco_index();
35
36 pci_update_config16(igd_dev, 0xcc, 0xfc00, display_clock_from_f0_and_vco[f0_12][vco]);
37
38 pci_update_config16(mch_dev, D0F0_GGC, 0xf00f, sysinfo->ggc);
39
40 if ((sysinfo->gfx_type != GMCH_GL40) &&
41 (sysinfo->gfx_type != GMCH_GS40) &&
42 (sysinfo->gfx_type != GMCH_GL43)) {
43 const u32 deven = pci_read_config32(mch_dev, D0F0_DEVEN);
44 if (!(deven & 2))
45 /* Enable PEG temporarily to access D1:F0. */
46 pci_write_config32(mch_dev, D0F0_DEVEN, deven | 2);
47
48 /* Some IGD related settings on D1:F0. */
49 pci_and_config16(peg_dev, 0xa08, (u16)~(1 << 15));
50
51 pci_or_config16(peg_dev, 0xa84, 1 << 8);
52
53 pci_or_config16(peg_dev, 0xb00, (3 << 8) | (7 << 3));
54
55 pci_and_config32(peg_dev, 0xb14, ~(1 << 17));
56
57 if (!(deven & 2) || no_peg) {
58 /* Disable PEG finally. */
59 printk(BIOS_DEBUG, "Finally disabling "
60 "PEG in favor of IGD.\n");
61 mchbar_setbits8(0xc14, 1 << 5 | 1 << 0);
62
63 pci_or_config32(peg_dev, 0x200, 1 << 18);
64
65 pci_or_config16(peg_dev, 0x224, 1 << 8);
66
67 pci_and_config32(peg_dev, 0x200, ~(1 << 18));
68
69 while (pci_read_config32(peg_dev, 0x214) & (0xf << 16))
70 ;
71
72 pci_write_config32(mch_dev, D0F0_DEVEN, deven & ~2);
73 mchbar_clrbits8(0xc14, 1 << 5 | 1 << 0);
74 }
75 }
76 }
77
disable_igd(const sysinfo_t * const sysinfo)78 static void disable_igd(const sysinfo_t *const sysinfo)
79 {
80 const pci_devfn_t mch_dev = PCI_DEV(0, 0, 0);
81
82 printk(BIOS_DEBUG, "Disabling IGD.\n");
83
84 /* Disable Graphics Stolen Memory. */
85 pci_update_config16(mch_dev, D0F0_GGC, 0xff0f, 0x0002);
86
87 mchbar_setbits8(0xf10, 1 << 0);
88
89 if (!(pci_read_config8(mch_dev, D0F0_CAPID0 + 4) & (1 << (33 - 32)))) {
90 mchbar_setbits16(0x1190, 1 << 14);
91 mchbar_clrsetbits16(0x119e, 7 << 13, 4 << 13);
92 mchbar_setbits16(0x119e, 1 << 12);
93 }
94
95 /* Hide IGD. */
96 pci_and_config32(mch_dev, D0F0_DEVEN, ~(3 << 3));
97 }
98
init_igd(const sysinfo_t * const sysinfo)99 void init_igd(const sysinfo_t *const sysinfo)
100 {
101 const pci_devfn_t mch_dev = PCI_DEV(0, 0, 0);
102
103 const u8 capid = pci_read_config8(mch_dev, D0F0_CAPID0 + 4);
104 if (!sysinfo->enable_igd || (capid & (1 << (33 - 32))))
105 disable_igd(sysinfo);
106 else
107 enable_igd(sysinfo, !sysinfo->enable_peg);
108 }
109
igd_compute_ggc(sysinfo_t * const sysinfo)110 void igd_compute_ggc(sysinfo_t *const sysinfo)
111 {
112 const pci_devfn_t mch_dev = PCI_DEV(0, 0, 0);
113
114 const u32 capid = pci_read_config32(mch_dev, D0F0_CAPID0 + 4);
115 if (!sysinfo->enable_igd || (capid & (1 << (33 - 32))))
116 sysinfo->ggc = 0x0002;
117 else {
118 /* 4 for 32MB, default if not set in CMOS */
119 u8 gfxsize = get_uint_option("gfx_uma_size", 4);
120
121 /* Graphics Stolen Memory: 2MB GTT (0x0300) when VT-d disabled,
122 2MB GTT + 2MB shadow GTT (0x0b00) else. */
123
124 /* Handle invalid CMOS settings */
125 /* Only allow settings between 32MB and 352MB */
126 gfxsize = MIN(MAX(gfxsize, 4), 12);
127
128 sysinfo->ggc = 0x0300 | ((gfxsize + 1) << 4);
129 if (!(capid & (1 << (48 - 32))))
130 sysinfo->ggc |= 0x0800;
131 }
132 }
133