xref: /aosp_15_r20/external/coreboot/src/northbridge/intel/gm45/igd.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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