Mike Banon has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/38202 )
Change subject: src/device/pci: Add support for discrete VGA initialization and OpROM loading ......................................................................
src/device/pci: Add support for discrete VGA initialization and OpROM loading
Required to make the discrete VGA working at some boards like AMD Lenovo G505S.
If CONFIG_MULTIPLE_VGA_ADAPTERS is enabled: coreboot will try to initialize the discrete VGA of PCI_CLASS_DISPLAY_OTHER class and load OpROM on it. ACPI VFCT table will be created only for discrete VGA of PCI_CLASS_DISPLAY_OTHER class instead of integrated (to avoid the discrete VGA init problems), but everything is working fine. Later will try to make a common VFCT table for both adapters.
Based on the original patches by Hans Jürgen Kitter eforname@freemail.hu.
Signed-off-by: Mike Banon mikebdp2@gmail.com Change-Id: I9a7aa31c956d8f716e2d5a73ff032134c144d3db --- M src/device/pci_device.c M src/device/pci_rom.c 2 files changed, 74 insertions(+), 11 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/02/38202/1
diff --git a/src/device/pci_device.c b/src/device/pci_device.c index 36b7c82..f0634fd 100644 --- a/src/device/pci_device.c +++ b/src/device/pci_device.c @@ -712,7 +712,9 @@ * ROMs when coming out of an S3 resume. */ if (!CONFIG(S3_VGA_ROM_RUN) && acpi_is_wakeup_s3() && - ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)) + (((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) || + (CONFIG(MULTIPLE_VGA_ADAPTERS) && + ((dev->class >> 8) == PCI_CLASS_DISPLAY_OTHER)))) return 0; if (CONFIG(ALWAYS_LOAD_OPROM)) return 1; @@ -726,34 +728,55 @@ void pci_dev_init(struct device *dev) { struct rom_header *rom, *ram; + unsigned int pci_class = (dev->class >> 8);
if (!CONFIG(VGA_ROM_RUN)) return;
- /* Only execute VGA ROMs. */ - if (((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)) + /* Only load VGA ROMs. */ + switch (pci_class) { + case PCI_CLASS_DISPLAY_VGA: + break; + case PCI_CLASS_DISPLAY_OTHER: + if (!CONFIG(MULTIPLE_VGA_ADAPTERS)) + return; + break; + default: return; + }
if (!should_load_oprom(dev)) return; timestamp_add_now(TS_OPROM_INITIALIZE);
rom = pci_rom_probe(dev); - if (rom == NULL) + if (rom == NULL) { + printk(BIOS_DEBUG, "%s%s ROM probe failed\n", + pci_class == PCI_CLASS_DISPLAY_VGA ? "" : "Non-", + "PCI_CLASS_DISPLAY_VGA"); return; + }
ram = pci_rom_load(dev, rom); - if (ram == NULL) + if (ram == NULL) { + printk(BIOS_DEBUG, "%s%s ROM load failed\n", + pci_class == PCI_CLASS_DISPLAY_VGA ? "" : "Non-", + "PCI_CLASS_DISPLAY_VGA"); return; + } timestamp_add_now(TS_OPROM_COPY_END);
if (!should_run_oprom(dev, rom)) return;
- run_bios(dev, (unsigned long)ram); + /* Only execute Integrated VGA Option ROM. */ + if (pci_class == PCI_CLASS_DISPLAY_VGA) { + run_bios(dev, (unsigned long)ram); + gfx_set_init_done(1); + printk(BIOS_DEBUG, "PCI_CLASS_DISPLAY_VGA Option ROM was run\n"); + } else + printk(BIOS_DEBUG, "Not running non-PCI_CLASS_DISPLAY_VGA Option ROM\n");
- gfx_set_init_done(1); - printk(BIOS_DEBUG, "VGA Option ROM was run\n"); timestamp_add_now(TS_OPROM_END); }
diff --git a/src/device/pci_rom.c b/src/device/pci_rom.c index 3676f9c..f1f7978 100644 --- a/src/device/pci_rom.c +++ b/src/device/pci_rom.c @@ -181,7 +181,20 @@ if (!CONFIG(VGA_ROM_RUN)) return NULL;
- run_rom = (struct rom_header *)(uintptr_t)PCI_VGA_RAM_IMAGE_START; + /* Set the start of shadow memory for this Integrated or Discrete VGA. */ + switch (dev->class >> 8) { + case PCI_CLASS_DISPLAY_VGA: + run_rom = (struct rom_header *)(uintptr_t)PCI_VGA_RAM_IMAGE_START; + break; + case PCI_CLASS_DISPLAY_OTHER: + if (!CONFIG(MULTIPLE_VGA_ADAPTERS)) + return NULL; + run_rom = (struct rom_header *)(uintptr_t)PCI_RAM_IMAGE_START; + break; + default: + return NULL; + } + if (read_le16(&run_rom->signature) != PCI_ROM_HDR) return NULL;
@@ -211,11 +224,26 @@ return current; }
- printk(BIOS_DEBUG, " Copying %sVBIOS image from %p\n", + /* Setup ROM address for copying it later from CBFS to ACPI VFCT. */ + switch (device->class >> 8) { + case PCI_CLASS_DISPLAY_VGA: + printk(BIOS_DEBUG, " Copying %sVBIOS image from %p\n", rom == (struct rom_header *) (uintptr_t)PCI_VGA_RAM_IMAGE_START ? "initialized " : "", rom); + break; + case PCI_CLASS_DISPLAY_OTHER: + printk(BIOS_DEBUG, " Copying %sVBIOS image from %p\n", + rom == (struct rom_header *) + (uintptr_t)PCI_RAM_IMAGE_START ? + "initialized " : "", + rom); + break; + default: + printk(BIOS_DEBUG, " Copying VBIOS image from %p\n", + rom); + }
header->DeviceID = device->device; header->VendorID = device->vendor; @@ -236,8 +264,20 @@ struct acpi_rsdp *rsdp) { /* Only handle VGA devices */ - if ((device->class >> 8) != PCI_CLASS_DISPLAY_VGA) + switch (device->class >> 8) { + case PCI_CLASS_DISPLAY_VGA: + if (CONFIG(MULTIPLE_VGA_ADAPTERS)) + return current; + /* Write ACPI VFCT only for Discrete VGA. */ + /* TODO: do this also for Integrated VGA. */ + break; + case PCI_CLASS_DISPLAY_OTHER: + if (!CONFIG(MULTIPLE_VGA_ADAPTERS)) + return current; + break; + default: return current; + }
/* Only handle enabled devices */ if (!device->enabled)