Patrick Rudolph has uploaded this change for review. ( https://review.coreboot.org/21766
Change subject: nb/intel/*/gma: Port ACPI opregion to older platforms ......................................................................
nb/intel/*/gma: Port ACPI opregion to older platforms
Port the ACPI opregion implementation that resides in drivers/intel/gma to older platforms.
It allows to include a vbt.bin and to allows GNU/Linux to load the opregion as ASLS is being set.
Windows' Intel will likely ignore it as it relies on legacy VBIOS to be loaded at 0xc0000.
Needs test on all platforms.
Change-Id: I1896411155592b343e48cbd116e2f70fb0dbfafa Signed-off-by: Patrick Rudolph siro@das-labor.org --- M src/northbridge/intel/gm45/gma.c M src/northbridge/intel/i945/gma.c M src/northbridge/intel/x4x/gma.c 3 files changed, 158 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/66/21766/1
diff --git a/src/northbridge/intel/gm45/gma.c b/src/northbridge/intel/gm45/gma.c index 00b3fa0..bdad49b 100644 --- a/src/northbridge/intel/gm45/gma.c +++ b/src/northbridge/intel/gm45/gma.c @@ -25,6 +25,8 @@ #include <cpu/x86/msr.h> #include <cpu/x86/mtrr.h> #include <commonlib/helpers.h> +#include <cbmem.h> +#include <southbridge/intel/i82801ix/nvs.h>
#include "drivers/intel/gma/i915_reg.h" #include "chip.h" @@ -32,6 +34,7 @@ #include <drivers/intel/gma/intel_bios.h> #include <drivers/intel/gma/edid.h> #include <drivers/intel/gma/i915.h> +#include <drivers/intel/gma/opregion.h> #include <pc80/vga.h> #include <pc80/vga_io.h>
@@ -47,6 +50,19 @@ void gtt_write(u32 reg, u32 data) { write32(res2mmio(gtt_res, reg, 0), data); +} + +uintptr_t gma_get_gnvs_aslb(const void *gnvs) +{ + const global_nvs_t *gnvs_ptr = gnvs; + return (uintptr_t)(gnvs_ptr ? gnvs_ptr->aslb : 0); +} + +void gma_set_gnvs_aslb(void *gnvs, uintptr_t aslb) +{ + global_nvs_t *gnvs_ptr = gnvs; + if (gnvs_ptr) + gnvs_ptr->aslb = aslb; }
static void gma_init_lvds(const struct northbridge_intel_gm45_config *info, @@ -758,6 +774,8 @@
if (IS_ENABLED(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT)) gma_ngi(dev, &edid_lvds); + + intel_gma_restore_opregion(); }
static void gma_set_subsystem(device_t dev, unsigned vendor, unsigned device) @@ -793,6 +811,37 @@ drivers_intel_gma_displays_ssdt_generate(gfx); }
+static unsigned long +gma_write_acpi_tables(struct device *const dev, + unsigned long current, + struct acpi_rsdp *const rsdp) +{ + igd_opregion_t *opregion = (igd_opregion_t *)current; + global_nvs_t *gnvs; + + if (intel_gma_init_igd_opregion(opregion) != CB_SUCCESS) + return current; + + current += sizeof(igd_opregion_t); + + /* GNVS has been already set up */ + gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS); + if (gnvs) { + /* IGD OpRegion Base Address */ + gma_set_gnvs_aslb(gnvs, (uintptr_t)opregion); + } else { + printk(BIOS_ERR, "Error: GNVS table not found.\n"); + } + + current = acpi_align_current(current); + return current; +} + +static const char *gma_acpi_name(const struct device *dev) +{ + return "GFX0"; +} + static struct pci_operations gma_pci_ops = { .set_subsystem = gma_set_subsystem, }; @@ -806,6 +855,8 @@ .scan_bus = 0, .enable = 0, .ops_pci = &gma_pci_ops, + .acpi_name = gma_acpi_name, + .write_acpi_tables = gma_write_acpi_tables, };
static const unsigned short pci_device_ids[] = diff --git a/src/northbridge/intel/i945/gma.c b/src/northbridge/intel/i945/gma.c index 37f73ed..8d60bc9 100644 --- a/src/northbridge/intel/i945/gma.c +++ b/src/northbridge/intel/i945/gma.c @@ -23,10 +23,13 @@ #include <edid.h> #include <drivers/intel/gma/edid.h> #include <drivers/intel/gma/i915.h> +#include <drivers/intel/gma/opregion.h> #include <string.h> #include <pc80/vga.h> #include <pc80/vga_io.h> #include <commonlib/helpers.h> +#include <cbmem.h> +#include <southbridge/intel/i82801gx/nvs.h>
#include "i945.h" #include "chip.h" @@ -48,6 +51,19 @@ #define BASE_FREQUENCY 100000
#define DEFAULT_BLC_PWM 180 + +uintptr_t gma_get_gnvs_aslb(const void *gnvs) +{ + const global_nvs_t *gnvs_ptr = gnvs; + return (uintptr_t)(gnvs_ptr ? gnvs_ptr->aslb : 0); +} + +void gma_set_gnvs_aslb(void *gnvs, uintptr_t aslb) +{ + global_nvs_t *gnvs_ptr = gnvs; + if (gnvs_ptr) + gnvs_ptr->aslb = aslb; +}
static int gtt_setup(u8 *mmiobase) { @@ -687,6 +703,8 @@ /* PCI Init, will run VBIOS */ pci_dev_init(dev); } + + intel_gma_restore_opregion(); }
/* This doesn't reclaim stolen UMA memory, but IGD could still @@ -767,6 +785,37 @@ pci_dev_read_resources(dev); }
+static unsigned long +gma_write_acpi_tables(struct device *const dev, + unsigned long current, + struct acpi_rsdp *const rsdp) +{ + igd_opregion_t *opregion = (igd_opregion_t *)current; + global_nvs_t *gnvs; + + if (intel_gma_init_igd_opregion(opregion) != CB_SUCCESS) + return current; + + current += sizeof(igd_opregion_t); + + /* GNVS has been already set up */ + gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS); + if (gnvs) { + /* IGD OpRegion Base Address */ + gma_set_gnvs_aslb(gnvs, (uintptr_t)opregion); + } else { + printk(BIOS_ERR, "Error: GNVS table not found.\n"); + } + + current = acpi_align_current(current); + return current; +} + +static const char *gma_acpi_name(const struct device *dev) +{ + return "GFX0"; +} + static struct pci_operations gma_pci_ops = { .set_subsystem = gma_set_subsystem, }; @@ -781,6 +830,8 @@ .enable = 0, .disable = gma_func0_disable, .ops_pci = &gma_pci_ops, + .acpi_name = gma_acpi_name, + .write_acpi_tables = gma_write_acpi_tables, };
diff --git a/src/northbridge/intel/x4x/gma.c b/src/northbridge/intel/x4x/gma.c index db96fac..cf3804d 100644 --- a/src/northbridge/intel/x4x/gma.c +++ b/src/northbridge/intel/x4x/gma.c @@ -26,6 +26,7 @@ #include <cpu/x86/msr.h> #include <cpu/x86/mtrr.h> #include <commonlib/helpers.h> +#include <cbmem.h>
#include "drivers/intel/gma/i915_reg.h" #include "chip.h" @@ -33,10 +34,30 @@ #include <drivers/intel/gma/intel_bios.h> #include <drivers/intel/gma/edid.h> #include <drivers/intel/gma/i915.h> +#include <drivers/intel/gma/opregion.h> #include <pc80/vga.h> #include <pc80/vga_io.h>
+#if IS_ENABLED(CONFIG_SOUTHBRIDGE_INTEL_I82801JX) +#include <southbridge/intel/i82801jx/nvs.h> +#elif IS_ENABLED(CONFIG_SOUTHBRIDGE_INTEL_I82801GX) +#include <southbridge/intel/i82801gx/nvs.h> +#endif + #define BASE_FREQUENCY 96000 + +uintptr_t gma_get_gnvs_aslb(const void *gnvs) +{ + const global_nvs_t *gnvs_ptr = gnvs; + return (uintptr_t)(gnvs_ptr ? gnvs_ptr->aslb : 0); +} + +void gma_set_gnvs_aslb(void *gnvs, uintptr_t aslb) +{ + global_nvs_t *gnvs_ptr = gnvs; + if (gnvs_ptr) + gnvs_ptr->aslb = aslb; +}
static u8 edid_is_present(u8 *edid, u32 edid_size) { @@ -395,6 +416,8 @@ } else { pci_dev_init(dev); } + + intel_gma_restore_opregion(); }
static void gma_func0_disable(struct device *dev) @@ -439,6 +462,37 @@ drivers_intel_gma_displays_ssdt_generate(gfx); }
+static unsigned long +gma_write_acpi_tables(struct device *const dev, + unsigned long current, + struct acpi_rsdp *const rsdp) +{ + igd_opregion_t *opregion = (igd_opregion_t *)current; + global_nvs_t *gnvs; + + if (intel_gma_init_igd_opregion(opregion) != CB_SUCCESS) + return current; + + current += sizeof(igd_opregion_t); + + /* GNVS has been already set up */ + gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS); + if (gnvs) { + /* IGD OpRegion Base Address */ + gma_set_gnvs_aslb(gnvs, (uintptr_t)opregion); + } else { + printk(BIOS_ERR, "Error: GNVS table not found.\n"); + } + + current = acpi_align_current(current); + return current; +} + +static const char *gma_acpi_name(const struct device *dev) +{ + return "GFX0"; +} + static struct pci_operations gma_pci_ops = { .set_subsystem = gma_set_subsystem, }; @@ -451,6 +505,8 @@ .init = gma_func0_init, .ops_pci = &gma_pci_ops, .disable = gma_func0_disable, + .acpi_name = gma_acpi_name, + .write_acpi_tables = gma_write_acpi_tables, };
static const unsigned short pci_device_ids[] = {