Angel Pons | 4b42983 | 2020-04-02 23:48:50 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
Patrick Georgi | 2efc880 | 2012-11-06 11:03:53 +0100 | [diff] [blame] | 2 | |
| 3 | #include <stdint.h> |
Kyösti Mälkki | f1b58b7 | 2019-03-01 13:43:02 +0200 | [diff] [blame] | 4 | #include <device/pci_ops.h> |
Patrick Georgi | 2efc880 | 2012-11-06 11:03:53 +0100 | [diff] [blame] | 5 | #include <device/pci_def.h> |
| 6 | #include <console/console.h> |
Kyösti Mälkki | cbf9571 | 2020-01-05 08:05:45 +0200 | [diff] [blame] | 7 | #include <option.h> |
Patrick Georgi | 2efc880 | 2012-11-06 11:03:53 +0100 | [diff] [blame] | 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. */ |
| 16 | static void enable_igd(const sysinfo_t *const sysinfo, const int no_peg) |
| 17 | { |
Furquan Shaikh | 25f75b2 | 2016-08-29 22:51:41 -0700 | [diff] [blame] | 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); |
Patrick Georgi | 2efc880 | 2012-11-06 11:03:53 +0100 | [diff] [blame] | 21 | |
Patrick Georgi | 2efc880 | 2012-11-06 11:03:53 +0100 | [diff] [blame] | 22 | printk(BIOS_DEBUG, "Enabling IGD.\n"); |
| 23 | |
| 24 | /* HSync/VSync */ |
Angel Pons | 3f1f8ef | 2021-03-27 13:52:43 +0100 | [diff] [blame] | 25 | mchbar_write8(0xbd0 + 3, 0x5a); |
| 26 | mchbar_write8(0xbd0 + 4, 0x5a); |
Patrick Georgi | 2efc880 | 2012-11-06 11:03:53 +0100 | [diff] [blame] | 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(); |
Patrick Georgi | 2efc880 | 2012-11-06 11:03:53 +0100 | [diff] [blame] | 35 | |
Angel Pons | b053583 | 2020-06-08 11:46:58 +0200 | [diff] [blame] | 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); |
Patrick Georgi | 2efc880 | 2012-11-06 11:03:53 +0100 | [diff] [blame] | 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. */ |
Angel Pons | b053583 | 2020-06-08 11:46:58 +0200 | [diff] [blame] | 49 | pci_and_config16(peg_dev, 0xa08, (u16)~(1 << 15)); |
Patrick Georgi | 2efc880 | 2012-11-06 11:03:53 +0100 | [diff] [blame] | 50 | |
Angel Pons | b053583 | 2020-06-08 11:46:58 +0200 | [diff] [blame] | 51 | pci_or_config16(peg_dev, 0xa84, 1 << 8); |
Patrick Georgi | 2efc880 | 2012-11-06 11:03:53 +0100 | [diff] [blame] | 52 | |
Angel Pons | b053583 | 2020-06-08 11:46:58 +0200 | [diff] [blame] | 53 | pci_or_config16(peg_dev, 0xb00, (3 << 8) | (7 << 3)); |
Patrick Georgi | 2efc880 | 2012-11-06 11:03:53 +0100 | [diff] [blame] | 54 | |
Angel Pons | b053583 | 2020-06-08 11:46:58 +0200 | [diff] [blame] | 55 | pci_and_config32(peg_dev, 0xb14, ~(1 << 17)); |
Patrick Georgi | 2efc880 | 2012-11-06 11:03:53 +0100 | [diff] [blame] | 56 | |
| 57 | if (!(deven & 2) || no_peg) { |
| 58 | /* Disable PEG finally. */ |
| 59 | printk(BIOS_DEBUG, "Finally disabling " |
| 60 | "PEG in favor of IGD.\n"); |
Angel Pons | 3f1f8ef | 2021-03-27 13:52:43 +0100 | [diff] [blame] | 61 | mchbar_setbits8(0xc14, 1 << 5 | 1 << 0); |
Patrick Georgi | 2efc880 | 2012-11-06 11:03:53 +0100 | [diff] [blame] | 62 | |
Angel Pons | b053583 | 2020-06-08 11:46:58 +0200 | [diff] [blame] | 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 | ; |
Patrick Georgi | 2efc880 | 2012-11-06 11:03:53 +0100 | [diff] [blame] | 71 | |
| 72 | pci_write_config32(mch_dev, D0F0_DEVEN, deven & ~2); |
Angel Pons | 3f1f8ef | 2021-03-27 13:52:43 +0100 | [diff] [blame] | 73 | mchbar_clrbits8(0xc14, 1 << 5 | 1 << 0); |
Patrick Georgi | 2efc880 | 2012-11-06 11:03:53 +0100 | [diff] [blame] | 74 | } |
| 75 | } |
| 76 | } |
| 77 | |
| 78 | static void disable_igd(const sysinfo_t *const sysinfo) |
| 79 | { |
Furquan Shaikh | 25f75b2 | 2016-08-29 22:51:41 -0700 | [diff] [blame] | 80 | const pci_devfn_t mch_dev = PCI_DEV(0, 0, 0); |
Patrick Georgi | 2efc880 | 2012-11-06 11:03:53 +0100 | [diff] [blame] | 81 | |
| 82 | printk(BIOS_DEBUG, "Disabling IGD.\n"); |
| 83 | |
Angel Pons | b053583 | 2020-06-08 11:46:58 +0200 | [diff] [blame] | 84 | /* Disable Graphics Stolen Memory. */ |
| 85 | pci_update_config16(mch_dev, D0F0_GGC, 0xff0f, 0x0002); |
Patrick Georgi | 2efc880 | 2012-11-06 11:03:53 +0100 | [diff] [blame] | 86 | |
Angel Pons | 3f1f8ef | 2021-03-27 13:52:43 +0100 | [diff] [blame] | 87 | mchbar_setbits8(0xf10, 1 << 0); |
Patrick Georgi | 2efc880 | 2012-11-06 11:03:53 +0100 | [diff] [blame] | 88 | |
| 89 | if (!(pci_read_config8(mch_dev, D0F0_CAPID0 + 4) & (1 << (33 - 32)))) { |
Angel Pons | 3f1f8ef | 2021-03-27 13:52:43 +0100 | [diff] [blame] | 90 | mchbar_setbits16(0x1190, 1 << 14); |
| 91 | mchbar_clrsetbits16(0x119e, 7 << 13, 4 << 13); |
| 92 | mchbar_setbits16(0x119e, 1 << 12); |
Patrick Georgi | 2efc880 | 2012-11-06 11:03:53 +0100 | [diff] [blame] | 93 | } |
Patrick Rudolph | bb1af99 | 2017-01-21 10:43:52 +0100 | [diff] [blame] | 94 | |
| 95 | /* Hide IGD. */ |
Angel Pons | b053583 | 2020-06-08 11:46:58 +0200 | [diff] [blame] | 96 | pci_and_config32(mch_dev, D0F0_DEVEN, ~(3 << 3)); |
Patrick Georgi | 2efc880 | 2012-11-06 11:03:53 +0100 | [diff] [blame] | 97 | } |
| 98 | |
Vladimir Serbinenko | 56ae8a0 | 2014-08-16 10:59:02 +0200 | [diff] [blame] | 99 | void init_igd(const sysinfo_t *const sysinfo) |
Patrick Georgi | 2efc880 | 2012-11-06 11:03:53 +0100 | [diff] [blame] | 100 | { |
Furquan Shaikh | 25f75b2 | 2016-08-29 22:51:41 -0700 | [diff] [blame] | 101 | const pci_devfn_t mch_dev = PCI_DEV(0, 0, 0); |
Patrick Georgi | 2efc880 | 2012-11-06 11:03:53 +0100 | [diff] [blame] | 102 | |
| 103 | const u8 capid = pci_read_config8(mch_dev, D0F0_CAPID0 + 4); |
Vladimir Serbinenko | 56ae8a0 | 2014-08-16 10:59:02 +0200 | [diff] [blame] | 104 | if (!sysinfo->enable_igd || (capid & (1 << (33 - 32)))) |
Patrick Georgi | 2efc880 | 2012-11-06 11:03:53 +0100 | [diff] [blame] | 105 | disable_igd(sysinfo); |
| 106 | else |
Vladimir Serbinenko | 56ae8a0 | 2014-08-16 10:59:02 +0200 | [diff] [blame] | 107 | enable_igd(sysinfo, !sysinfo->enable_peg); |
| 108 | } |
| 109 | |
| 110 | void igd_compute_ggc(sysinfo_t *const sysinfo) |
| 111 | { |
Furquan Shaikh | 25f75b2 | 2016-08-29 22:51:41 -0700 | [diff] [blame] | 112 | const pci_devfn_t mch_dev = PCI_DEV(0, 0, 0); |
Vladimir Serbinenko | 56ae8a0 | 2014-08-16 10:59:02 +0200 | [diff] [blame] | 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 { |
Elyes HAOUAS | 2119d0b | 2020-02-16 10:01:33 +0100 | [diff] [blame] | 118 | /* 4 for 32MB, default if not set in CMOS */ |
Angel Pons | 88dcb31 | 2021-04-26 17:10:28 +0200 | [diff] [blame] | 119 | u8 gfxsize = get_uint_option("gfx_uma_size", 4); |
Vladimir Serbinenko | 56ae8a0 | 2014-08-16 10:59:02 +0200 | [diff] [blame] | 120 | |
| 121 | /* Graphics Stolen Memory: 2MB GTT (0x0300) when VT-d disabled, |
| 122 | 2MB GTT + 2MB shadow GTT (0x0b00) else. */ |
Angel Pons | f9c9390 | 2020-11-02 22:21:54 +0100 | [diff] [blame] | 123 | |
Elyes HAOUAS | 2119d0b | 2020-02-16 10:01:33 +0100 | [diff] [blame] | 124 | /* Handle invalid CMOS settings */ |
Arthur Heymans | d65ff22 | 2017-06-13 20:57:05 +0200 | [diff] [blame] | 125 | /* Only allow settings between 32MB and 352MB */ |
| 126 | gfxsize = MIN(MAX(gfxsize, 4), 12); |
| 127 | |
Arthur Heymans | 7afcfe0 | 2016-05-19 15:34:49 +0200 | [diff] [blame] | 128 | sysinfo->ggc = 0x0300 | ((gfxsize + 1) << 4); |
Vladimir Serbinenko | 56ae8a0 | 2014-08-16 10:59:02 +0200 | [diff] [blame] | 129 | if (!(capid & (1 << (48 - 32)))) |
| 130 | sysinfo->ggc |= 0x0800; |
| 131 | } |
Patrick Georgi | 2efc880 | 2012-11-06 11:03:53 +0100 | [diff] [blame] | 132 | } |