[coreboot-gerrit] Patch set updated for coreboot: device/device: handle multiple VGA devices

Patrick Rudolph (siro@das-labor.org) gerrit at coreboot.org
Thu Apr 21 10:24:47 CEST 2016


Patrick Rudolph (siro at das-labor.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/12897

-gerrit

commit ba7ac2235606b8bac2087b6196c748a8ba4801c2
Author: Patrick Rudolph <siro at das-labor.org>
Date:   Sat Dec 26 08:27:20 2015 +0100

    device/device: handle multiple VGA devices
    
    Add nvram options "vga_primary_is_peg" and "vga_secondary_powersave"
    to switch between VGA devices.
    
    Both options only affects systems where an onboard and a PEG device
    is installed. Systems with only one VGA device will always use it as
    the primary VGA device.
    
    vga_primary_is_peg allows to choose the primary VGA device, that is where the
    VGA Option ROM will be run on.
    In case of a laptop the panel will be connected to the primary device.
    
    vga_primary_is_peg=0 : Onboard is primary
    vga_primary_is_peg=1 : Dedicated is primary
    
    vga_secondary_powersave allows to disable secondary VGA devices to save power.
    
    vga_secondary_powersave=0 : Leave secondary VGA devices enabled
    vga_secondary_powersave=1 : Disable secondary VGA devices
    
    Tested on Lenovo T530 using Nvidia NVS 5400m.
    
    WIP: Do not commit yet !
    
    Change-Id: Ie37ec4aeae8ab49fe8e26438c430911d1815551c
    Signed-off-by: Patrick Rudolph <siro at das-labor.org>
---
 src/device/device.c | 93 +++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 72 insertions(+), 21 deletions(-)

diff --git a/src/device/device.c b/src/device/device.c
index 9ea32cc..5f2a487 100644
--- a/src/device/device.c
+++ b/src/device/device.c
@@ -50,6 +50,7 @@
 #include <arch/ebda.h>
 #endif
 #include <timer.h>
+#include <option.h>
 
 /** Linked list of ALL devices */
 struct device *all_devices = &dev_root;
@@ -754,28 +755,52 @@ static void avoid_fixed_resources(struct device *dev)
 	}
 }
 
+static struct device *get_next_vga_dev(struct device *dev)
+{
+	while ((dev = dev_find_class(PCI_CLASS_DISPLAY_VGA << 8, dev))) {
+		if (!dev->enabled)
+			continue;
+
+		return dev;
+	}
+	return NULL;
+}
+
+/*
+ * Disables all PCI_CLASS_DISPLAY_VGA devices except the one
+ * given as argument.
+ * @param dev_primary The device to ignore
+ */
+static void disable_secondary_vga_devs(struct device *dev_primary)
+{
+	struct device *dev = NULL;
+
+	while ((dev = get_next_vga_dev(dev))) {
+		/* disable unused devices to save power */
+		if (dev != dev_primary) {
+			if (dev->ops && dev->ops->disable)
+				dev->ops->disable(dev);
+			else
+				dev->enabled = 0;
+		}
+	}
+}
+
 device_t vga_pri = 0;
 static void set_vga_bridge_bits(void)
 {
-	/*
-	 * FIXME: Modify set_vga_bridge() so it is less PCI-centric!
-	 * This function knows too much about PCI stuff, it should be just
-	 * an iterator/visitor.
-	 */
-
 	/* FIXME: Handle the VGA palette snooping. */
 	struct device *dev, *vga, *vga_onboard;
 	struct bus *bus;
+	u8 vga_primary_is_peg;
+	u8 vga_secondary_powersave;
 
 	bus = 0;
 	vga = 0;
 	vga_onboard = 0;
 
 	dev = NULL;
-	while ((dev = dev_find_class(PCI_CLASS_DISPLAY_VGA << 8, dev))) {
-		if (!dev->enabled)
-			continue;
-
+	while ((dev = get_next_vga_dev(dev))) {
 		printk(BIOS_DEBUG, "found VGA at %s\n", dev_path(dev));
 
 		if (dev->on_mainboard) {
@@ -788,23 +813,49 @@ static void set_vga_bridge_bits(void)
 		dev->command &= ~(PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
 	}
 
-	if (!vga)
-		vga = vga_onboard;
+	if ((get_option(&vga_primary_is_peg, "vga_primary_is_peg") != CB_SUCCESS) ||
+		(get_option(&vga_secondary_powersave, "vga_secondary_powersave") != CB_SUCCESS) ||
+		!vga || !vga_onboard) {
+		/* fallback */
+		if (!vga)
+			vga = vga_onboard;
+
+		if (IS_ENABLED(CONFIG_ONBOARD_VGA_IS_PRIMARY) && vga_onboard)
+			vga = vga_onboard;
+
+		/* If we prefer plugin VGA over chipset VGA, the chipset might
+		   want to know. */
+		if (!IS_ENABLED(CONFIG_ONBOARD_VGA_IS_PRIMARY) &&
+			(vga != vga_onboard) &&
+			vga_onboard) {
+			printk(BIOS_DEBUG, "Use plugin graphics over integrated.\n");
+
+			if (vga_onboard->ops && vga_onboard->ops->disable)
+				vga_onboard->ops->disable(vga_onboard);
+			else
+				vga_onboard->enabled = 0;
+		}
+
+		disable_secondary_vga_devs(vga);
+	} else {
+		/* have vga and vga_onboard (two or more VGAs) */
 
-	if (CONFIG_ONBOARD_VGA_IS_PRIMARY && vga_onboard)
-		vga = vga_onboard;
+		/* make onboard primary if vga_primary_is_peg is disabled */
+		if (vga_primary_is_peg == 0) {
+			printk(BIOS_DEBUG, "Use integrated graphics over plugin.\n");
+			vga = vga_onboard;
+		}
 
-	/* If we prefer plugin VGA over chipset VGA, the chipset might
-	   want to know. */
-	if (!CONFIG_ONBOARD_VGA_IS_PRIMARY && (vga != vga_onboard) &&
-		vga_onboard && vga_onboard->ops && vga_onboard->ops->disable) {
-		printk(BIOS_DEBUG, "Use plugin graphics over integrated.\n");
-		vga_onboard->ops->disable(vga_onboard);
+		/* disable secondary VGAs if vga_secondary_powersave is enabled */
+		if (vga_secondary_powersave == 1) {
+			printk(BIOS_DEBUG, "Disable secondary graphics to save power.\n");
+			disable_secondary_vga_devs(vga);
+		}
 	}
 
 	if (vga) {
 		/* VGA is first add-on card or the only onboard VGA. */
-		printk(BIOS_DEBUG, "Setting up VGA for %s\n", dev_path(vga));
+		printk(BIOS_DEBUG, "Setting up %s for primary VGA.\n", dev_path(vga));
 		/* All legacy VGA cards have MEM & I/O space registers. */
 		vga->command |= (PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
 		vga_pri = vga;



More information about the coreboot-gerrit mailing list