From fbbc8d6a278c733eca475c17cbf95a8946e2c173 Mon Sep 17 00:00:00 2001
From: Arthur Heymans <arthur@aheymans.xyz>
Date: Thu, 4 Aug 2016 11:00:13 +0200
Subject: [PATCH 1/3] Revert "drivers/lenovo: Add hybrid graphics driver"

This reverts commit 5919ba42ed0ce5b1b13717514698444232c6036c.

Change-Id: I027581ef769ca8232e72f89738c1bdec13f62687

diff --git a/src/drivers/lenovo/Kconfig b/src/drivers/lenovo/Kconfig
index f8eddf2..f20f3b2 100644
--- a/src/drivers/lenovo/Kconfig
+++ b/src/drivers/lenovo/Kconfig
@@ -27,16 +27,3 @@ config DIGITIZER_ABSENT
 endchoice
 
 endif
-
-config DRIVERS_LENOVO_HYBRID_GRAPHICS
-	bool
-	default n
-
-config HYBRID_GRAPHICS_GPIO_NUM
-	depends on DRIVERS_LENOVO_HYBRID_GRAPHICS
-	int
-	default 52
-	help
-	  Set a default GPIO that sets the panel LVDS signal routing to
-	  integrated or discrete GPU.
-
diff --git a/src/drivers/lenovo/Makefile.inc b/src/drivers/lenovo/Makefile.inc
index 66f8594..c50db5b 100644
--- a/src/drivers/lenovo/Makefile.inc
+++ b/src/drivers/lenovo/Makefile.inc
@@ -1,2 +1 @@
 ramstage-$(CONFIG_DRIVERS_LENOVO_WACOM) += wacom.c
-ramstage-$(CONFIG_DRIVERS_LENOVO_HYBRID_GRAPHICS) += hybrid_graphics.c
diff --git a/src/drivers/lenovo/hybrid_graphics.c b/src/drivers/lenovo/hybrid_graphics.c
deleted file mode 100644
index 9b46646..0000000
--- a/src/drivers/lenovo/hybrid_graphics.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2015-2016 Patrick Rudolph
- * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <types.h>
-#include <string.h>
-#include <option.h>
-#include <device/device.h>
-#include <device/pci_def.h>
-#include <device/pci_ops.h>
-#include <device/pci_ids.h>
-#include <device/pci.h>
-#include <console/console.h>
-#include <southbridge/intel/common/gpio.h>
-
-/* Hybrid graphics allows to connect LVDS interface to either iGPU
- * or dGPU depending on GPIO level.
- * Nvidia is calling this functionality "muxed Optimus".
- * Some devices, like T430s, only support "muxless Optimus" where the
- * Intel GPU is always connected to the panel.
- * As it is only linked on lenovo and only executed if the GPU exists
- * we know for sure that the dGPU is there and connected to first PEG slot.
- *
- * Note: Once native gfx init is done for AMD or Nvida graphic
- *       cards, merge this code.
- */
-
-#define HYBRID_GRAPHICS_INTEGRATED 0
-#define HYBRID_GRAPHICS_DISCRETE 1
-
-static void hybrid_graphics_disable_peg(struct device *dev)
-{
-	struct device *peg_dev;
-
-	/* connect LVDS interface to iGPU */
-	set_gpio(CONFIG_HYBRID_GRAPHICS_GPIO_NUM, GPIO_LEVEL_HIGH);
-	printk(BIOS_DEBUG, "Hybrid graphics: Switching panel to integrated GPU.\n");
-	dev->enabled = 0;
-
-	/* Disable PEG10 */
-	peg_dev = dev_find_slot(0, PCI_DEVFN(1, 0));
-	if (peg_dev)
-		peg_dev->enabled = 0;
-
-	printk(BIOS_DEBUG, "Hybrid graphics: Disabled PEG10.\n");
-}
-
-/* Called before VGA enable bits are set and only if dGPU
- * is present. Enable/disable VGA devices here. */
-static void hybrid_graphics_enable_peg(struct device *dev)
-{
-	u8 hybrid_graphics_mode;
-
-	hybrid_graphics_mode = HYBRID_GRAPHICS_INTEGRATED;
-	get_option(&hybrid_graphics_mode, "hybrid_graphics_mode");
-
-	if (hybrid_graphics_mode == HYBRID_GRAPHICS_DISCRETE) {
-		/* connect LVDS interface to dGPU */
-		set_gpio(CONFIG_HYBRID_GRAPHICS_GPIO_NUM, GPIO_LEVEL_LOW);
-		printk(BIOS_DEBUG, "Hybrid graphics: Switching panel to discrete GPU.\n");
-		dev->enabled = 1;
-
-		/* Disable IGD */
-		dev = dev_find_slot(0, PCI_DEVFN(2, 0));
-		if (dev && dev->ops->disable)
-			dev->ops->disable(dev);
-		dev->enabled = 0;
-
-		printk(BIOS_DEBUG, "Hybrid graphics: Disabled IGD.\n");
-	} else
-		hybrid_graphics_disable_peg(dev);
-}
-
-static struct pci_operations pci_dev_ops_pci = {
-	.set_subsystem = pci_dev_set_subsystem,
-};
-
-struct device_operations hybrid_graphics_ops = {
-	.read_resources   = pci_dev_read_resources,
-	.set_resources    = pci_dev_set_resources,
-	.enable_resources = pci_dev_enable_resources,
-	.init             = pci_dev_init,
-	.scan_bus         = 0,
-	.enable           = hybrid_graphics_enable_peg,
-	.disable          = hybrid_graphics_disable_peg,
-	.ops_pci          = &pci_dev_ops_pci,
-};
-
-static const unsigned short pci_device_ids_nvidia[] = {
-		0x0ffc, /* Nvidia NVS Quadro K1000m Lenovo W530 */
-		0x0def, /* NVidia NVS 5400m Lenovo T430/T530 */
-		0x0dfc, /* NVidia NVS 5200m Lenovo T430s */
-		0x1056, /* NVidia NVS 4200m Lenovo T420/T520 */
-		0x1057, /* NVidia NVS 4200m Lenovo T420/T520 */
-		0x0a6c, /* NVidia NVS 3100m Lenovo T410/T510 */
-		0 };
-
-static const struct pci_driver hybrid_peg_nvidia __pci_driver = {
-	.ops	 = &hybrid_graphics_ops,
-	.vendor	 = PCI_VENDOR_ID_NVIDIA,
-	.devices = pci_device_ids_nvidia,
-};
-
-static const unsigned short pci_device_ids_amd[] = {
-		0x9591, /* ATI Mobility Radeon HD 3650 Lenovo T500/W500 */
-		0x95c4, /* ATI Mobility Radeon HD 3470 Lenovo T400/R400 */
-		0 };
-
-static const struct pci_driver hybrid_peg_amd __pci_driver = {
-	.ops	 = &hybrid_graphics_ops,
-	.vendor	 = PCI_VENDOR_ID_ATI,
-	.devices = pci_device_ids_amd,
-};
diff --git a/src/mainboard/lenovo/t400/Kconfig b/src/mainboard/lenovo/t400/Kconfig
index a444bf8..d74a813 100644
--- a/src/mainboard/lenovo/t400/Kconfig
+++ b/src/mainboard/lenovo/t400/Kconfig
@@ -22,7 +22,6 @@ config BOARD_SPECIFIC_OPTIONS # dummy
 	select MAINBOARD_HAS_NATIVE_VGA_INIT_TEXTMODECFG
 	select INTEL_INT15
 	select SUPERIO_NSC_PC87382
-	select DRIVERS_LENOVO_HYBRID_GRAPHICS
 
 config MAINBOARD_DIR
 	string
diff --git a/src/mainboard/lenovo/t400/cmos.default b/src/mainboard/lenovo/t400/cmos.default
index 5cf3e63..ac9f96d 100644
--- a/src/mainboard/lenovo/t400/cmos.default
+++ b/src/mainboard/lenovo/t400/cmos.default
@@ -13,5 +13,3 @@ sticky_fn=Disable
 power_management_beeps=Enable
 low_battery_beep=Enable
 sata_mode=AHCI
-hybrid_graphics_mode=Integrated Only
-gfx_uma_size=32M
\ No newline at end of file
diff --git a/src/mainboard/lenovo/t400/cmos.layout b/src/mainboard/lenovo/t400/cmos.layout
index b4b7766..e1a088d 100644
--- a/src/mainboard/lenovo/t400/cmos.layout
+++ b/src/mainboard/lenovo/t400/cmos.layout
@@ -77,8 +77,7 @@ entries
 940         1       e       1        uwb
 
 # coreboot config options: northbridge
-944         2       e       12       hybrid_graphics_mode
-946         4       e       11       gfx_uma_size
+941         4       e       11       gfx_uma_size
 
 # coreboot config options: EC
 952         8       h       0        volume
diff --git a/src/mainboard/lenovo/t420/cmos.default b/src/mainboard/lenovo/t420/cmos.default
index 3a82c97..1b8e212 100644
--- a/src/mainboard/lenovo/t420/cmos.default
+++ b/src/mainboard/lenovo/t420/cmos.default
@@ -14,4 +14,3 @@ fn_ctrl_swap=Disable
 sticky_fn=Disable
 trackpoint=Enable
 hyper_threading=Enable
-hybrid_graphics_mode=Integrated Only
\ No newline at end of file
diff --git a/src/mainboard/lenovo/t420/cmos.layout b/src/mainboard/lenovo/t420/cmos.layout
index 58a4abe..bf0f195 100644
--- a/src/mainboard/lenovo/t420/cmos.layout
+++ b/src/mainboard/lenovo/t420/cmos.layout
@@ -77,8 +77,7 @@ entries
 
 # coreboot config options: northbridge
 432          3       e       11       gfx_uma_size
-435          2        e       12       hybrid_graphics_mode
-#437         3        r       0        unused
+#435          5       r       0        unused
 
 440          8       h       0        volume
 
@@ -136,8 +135,6 @@ enumerations
 11    4     160M
 11    5     192M
 11    6     224M
-12    0     Integrated Only
-12    1     Discrete Only
 
 # -----------------------------------------------------------------
 checksums
diff --git a/src/mainboard/lenovo/t420s/Kconfig b/src/mainboard/lenovo/t420s/Kconfig
index feacb51..935e659 100644
--- a/src/mainboard/lenovo/t420s/Kconfig
+++ b/src/mainboard/lenovo/t420s/Kconfig
@@ -18,7 +18,6 @@ config BOARD_SPECIFIC_OPTIONS # dummy
 	select INTEL_INT15
 	select SANDYBRIDGE_IVYBRIDGE_LVDS
 	select MAINBOARD_HAS_LPC_TPM
-	select DRIVERS_LENOVO_HYBRID_GRAPHICS
 
 	# Workaround for EC/KBC IRQ1.
 	select SERIRQ_CONTINUOUS_MODE
diff --git a/src/mainboard/lenovo/t420s/cmos.default b/src/mainboard/lenovo/t420s/cmos.default
index 3a82c97..1b8e212 100644
--- a/src/mainboard/lenovo/t420s/cmos.default
+++ b/src/mainboard/lenovo/t420s/cmos.default
@@ -14,4 +14,3 @@ fn_ctrl_swap=Disable
 sticky_fn=Disable
 trackpoint=Enable
 hyper_threading=Enable
-hybrid_graphics_mode=Integrated Only
\ No newline at end of file
diff --git a/src/mainboard/lenovo/t420s/cmos.layout b/src/mainboard/lenovo/t420s/cmos.layout
index 3521849..43628406 100644
--- a/src/mainboard/lenovo/t420s/cmos.layout
+++ b/src/mainboard/lenovo/t420s/cmos.layout
@@ -77,8 +77,7 @@ entries
 
 # coreboot config options: northbridge
 432          3       e       11       gfx_uma_size
-435          2       e       12       hybrid_graphics_mode
-#437         3       r       0        unused
+#435         5       r       0        unused
 
 440          8       h       0        volume
 
@@ -136,8 +135,6 @@ enumerations
 11    4     160M
 11    5     192M
 11    6     224M
-12    0     Integrated Only
-12    1     Discrete Only
 
 # -----------------------------------------------------------------
 checksums
diff --git a/src/mainboard/lenovo/t520/Kconfig b/src/mainboard/lenovo/t520/Kconfig
index ee5dd81..c70581a 100644
--- a/src/mainboard/lenovo/t520/Kconfig
+++ b/src/mainboard/lenovo/t520/Kconfig
@@ -18,7 +18,6 @@ config BOARD_SPECIFIC_OPTIONS # dummy
 	select INTEL_INT15
 	select SANDYBRIDGE_IVYBRIDGE_LVDS
 	select MAINBOARD_HAS_LPC_TPM
-	select DRIVERS_LENOVO_HYBRID_GRAPHICS
 
 	# Workaround for EC/KBC IRQ1.
 	select SERIRQ_CONTINUOUS_MODE
diff --git a/src/mainboard/lenovo/t520/cmos.default b/src/mainboard/lenovo/t520/cmos.default
index ad7dcf5..00e8863 100644
--- a/src/mainboard/lenovo/t520/cmos.default
+++ b/src/mainboard/lenovo/t520/cmos.default
@@ -15,4 +15,3 @@ sticky_fn=Disable
 trackpoint=Enable
 hyper_threading=Enable
 backlight=Both
-hybrid_graphics_mode=Integrated Only
\ No newline at end of file
diff --git a/src/mainboard/lenovo/t520/cmos.layout b/src/mainboard/lenovo/t520/cmos.layout
index 044c310..2cf3629 100644
--- a/src/mainboard/lenovo/t520/cmos.layout
+++ b/src/mainboard/lenovo/t520/cmos.layout
@@ -77,8 +77,7 @@ entries
 
 # coreboot config options: northbridge
 432         3        e      11        gfx_uma_size
-435         2        e       12       hybrid_graphics_mode
-#437        3        r       0        unused
+#435        5        r       0        unused
 440         8        h       0        volume
 
 # SandyBridge MRC Scrambler Seed values
@@ -135,8 +134,6 @@ enumerations
 11    4	    160M
 11    5	    192M
 11    6	    224M
-12    0     Integrated Only
-12    1     Discrete Only
 # -----------------------------------------------------------------
 checksums
 
diff --git a/src/mainboard/lenovo/t530/Kconfig b/src/mainboard/lenovo/t530/Kconfig
index 76147fc..030c01f 100644
--- a/src/mainboard/lenovo/t530/Kconfig
+++ b/src/mainboard/lenovo/t530/Kconfig
@@ -21,7 +21,6 @@ config BOARD_SPECIFIC_OPTIONS # dummy
 	select SANDYBRIDGE_IVYBRIDGE_LVDS
 	select ENABLE_VMX
 	select MAINBOARD_HAS_LPC_TPM
-	select DRIVERS_LENOVO_HYBRID_GRAPHICS
 
 	# Workaround for EC/KBC IRQ1.
 	select SERIRQ_CONTINUOUS_MODE
diff --git a/src/mainboard/lenovo/t530/cmos.default b/src/mainboard/lenovo/t530/cmos.default
index ad7dcf5..00e8863 100644
--- a/src/mainboard/lenovo/t530/cmos.default
+++ b/src/mainboard/lenovo/t530/cmos.default
@@ -15,4 +15,3 @@ sticky_fn=Disable
 trackpoint=Enable
 hyper_threading=Enable
 backlight=Both
-hybrid_graphics_mode=Integrated Only
\ No newline at end of file
diff --git a/src/mainboard/lenovo/t530/cmos.layout b/src/mainboard/lenovo/t530/cmos.layout
index 0e28bdd..e21c197 100644
--- a/src/mainboard/lenovo/t530/cmos.layout
+++ b/src/mainboard/lenovo/t530/cmos.layout
@@ -77,8 +77,7 @@ entries
 
 # coreboot config options: northbridge
 432         3        e      11        gfx_uma_size
-435         2        e       12       hybrid_graphics_mode
-#437        3        r       0        unused
+#435        5        r       0        unused
 
 440          8       h       0        volume
 
@@ -136,9 +135,6 @@ enumerations
 11    4	    160M
 11    5	    192M
 11    6	    224M
-12    0     Integrated Only
-12    1     Discrete Only
-
 # -----------------------------------------------------------------
 checksums
 
diff --git a/src/southbridge/intel/i82801ix/Kconfig b/src/southbridge/intel/i82801ix/Kconfig
index b3e5069..2822774 100644
--- a/src/southbridge/intel/i82801ix/Kconfig
+++ b/src/southbridge/intel/i82801ix/Kconfig
@@ -23,7 +23,6 @@ config SOUTHBRIDGE_INTEL_I82801IX
 	select USE_WATCHDOG_ON_BOOT
 	select HAVE_SMI_HANDLER
 	select HAVE_USBDEBUG_OPTIONS
-	select SOUTHBRIDGE_INTEL_COMMON_GPIO
 
 if SOUTHBRIDGE_INTEL_I82801IX
 
-- 
2.9.2

From 90f5f34629ff88506bb803988da1552f3373d4f0 Mon Sep 17 00:00:00 2001
From: Arthur Heymans <arthur@aheymans.xyz>
Date: Thu, 4 Aug 2016 11:01:53 +0200
Subject: [PATCH 2/3] Revert "Revert "mainboard/lenovo/t400: Add initial hybrid
 graphics support""

This reverts commit 14d1a93e444b91311eeed2a25953bf6c0779cdcb.

Change-Id: I965ea55bddb7cf919e7b02ecf8e160c9ad3ea3d4

diff --git a/src/mainboard/lenovo/t400/cmos.default b/src/mainboard/lenovo/t400/cmos.default
index ac9f96d..98ce970 100644
--- a/src/mainboard/lenovo/t400/cmos.default
+++ b/src/mainboard/lenovo/t400/cmos.default
@@ -13,3 +13,4 @@ sticky_fn=Disable
 power_management_beeps=Enable
 low_battery_beep=Enable
 sata_mode=AHCI
+hybrid_graphics_mode=Integrated Only
\ No newline at end of file
diff --git a/src/mainboard/lenovo/t400/cmos.layout b/src/mainboard/lenovo/t400/cmos.layout
index e1a088d..b4b7766 100644
--- a/src/mainboard/lenovo/t400/cmos.layout
+++ b/src/mainboard/lenovo/t400/cmos.layout
@@ -77,7 +77,8 @@ entries
 940         1       e       1        uwb
 
 # coreboot config options: northbridge
-941         4       e       11       gfx_uma_size
+944         2       e       12       hybrid_graphics_mode
+946         4       e       11       gfx_uma_size
 
 # coreboot config options: EC
 952         8       h       0        volume
diff --git a/src/mainboard/lenovo/t400/romstage.c b/src/mainboard/lenovo/t400/romstage.c
index f518775..fcc545b 100644
--- a/src/mainboard/lenovo/t400/romstage.c
+++ b/src/mainboard/lenovo/t400/romstage.c
@@ -1,6 +1,7 @@
 /*
  * This file is part of the coreboot project.
  *
+ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
  * Copyright (C) 2012 secunet Security Networks AG
  *
  * This program is free software; you can redistribute it and/or
@@ -34,6 +35,118 @@
 #define LPC_DEV PCI_DEV(0, 0x1f, 0)
 #define MCH_DEV PCI_DEV(0, 0, 0)
 
+#define HYBRID_GRAPHICS_INTEGRATED_ONLY 0
+#define HYBRID_GRAPHICS_DISCRETE_ONLY 1
+#define HYBRID_GRAPHICS_SWITCHABLE 2
+
+#define HYBRID_GRAPHICS_GP_LVL_BITS 0x004a0000
+#define HYBRID_GRAPHICS_GP_LVL2_BITS 0x00020000
+
+#define HYBRID_GRAPHICS_DETECT_GP_BITS 0x00000010
+
+#define HYBRID_GRAPHICS_INT_CLAIM_VGA 0x2
+#define HYBRID_GRAPHICS_SEC_VGA_EN 0x2
+
+static void hybrid_graphics_configure_switchable_graphics(bool enable)
+{
+	uint32_t tmp;
+
+	if (enable) {
+		/* Disable integrated graphics legacy VGA cycles */
+		tmp = pci_read_config16(MCH_DEV, D0F0_GGC);
+		pci_write_config16(MCH_DEV, D0F0_GGC, tmp | HYBRID_GRAPHICS_INT_CLAIM_VGA);
+
+		/* Enable secondary VGA controller */
+		tmp = pci_read_config16(MCH_DEV, D0F0_DEVEN);
+		pci_write_config16(MCH_DEV, D0F0_DEVEN, tmp | HYBRID_GRAPHICS_SEC_VGA_EN);
+	}
+	else {
+		/* Enable integrated graphics legacy VGA cycles */
+		tmp = pci_read_config16(MCH_DEV, D0F0_GGC);
+		pci_write_config16(MCH_DEV, D0F0_GGC, tmp & ~HYBRID_GRAPHICS_INT_CLAIM_VGA);
+
+		/* Disable secondary VGA controller */
+		tmp = pci_read_config16(MCH_DEV, D0F0_DEVEN);
+		pci_write_config16(MCH_DEV, D0F0_DEVEN, tmp & ~HYBRID_GRAPHICS_SEC_VGA_EN);
+	}
+}
+
+static void hybrid_graphics_set_up_gpio(void)
+{
+	uint32_t tmp;
+
+	/* Enable hybrid graphics GPIO lines */
+	tmp = inl(DEFAULT_GPIOBASE + GP_IO_USE_SEL);
+	tmp = tmp | HYBRID_GRAPHICS_GP_LVL_BITS;
+	outl(tmp, DEFAULT_GPIOBASE + GP_IO_USE_SEL);
+
+	tmp = inl(DEFAULT_GPIOBASE + GP_IO_USE_SEL2);
+	tmp = tmp | HYBRID_GRAPHICS_GP_LVL2_BITS;
+	outl(tmp, DEFAULT_GPIOBASE + GP_IO_USE_SEL2);
+
+	/* Set hybrid graphics control GPIO lines to output */
+	tmp = inl(DEFAULT_GPIOBASE + GP_IO_SEL);
+	tmp = tmp & ~HYBRID_GRAPHICS_GP_LVL_BITS;
+	outl(tmp, DEFAULT_GPIOBASE + GP_IO_SEL);
+
+	tmp = inl(DEFAULT_GPIOBASE + GP_IO_SEL2);
+	tmp = tmp & ~HYBRID_GRAPHICS_GP_LVL2_BITS;
+	outl(tmp, DEFAULT_GPIOBASE + GP_IO_SEL2);
+
+	/* Set hybrid graphics detect GPIO lines to input */
+	tmp = inl(DEFAULT_GPIOBASE + GP_IO_SEL);
+	tmp = tmp | HYBRID_GRAPHICS_DETECT_GP_BITS;
+	outl(tmp, DEFAULT_GPIOBASE + GP_IO_SEL);
+}
+
+static bool hybrid_graphics_installed(void)
+{
+	if (inl(DEFAULT_GPIOBASE + GP_LVL) & HYBRID_GRAPHICS_DETECT_GP_BITS)
+		return false;
+	else
+		return true;
+}
+
+static void hybrid_graphics_switch_to_integrated_graphics(void)
+{
+	uint32_t tmp;
+
+	/* Disable switchable graphics */
+	hybrid_graphics_configure_switchable_graphics(false);
+
+	/* Configure muxes */
+	tmp = inl(DEFAULT_GPIOBASE + GP_LVL);
+	tmp = tmp & ~HYBRID_GRAPHICS_GP_LVL_BITS;
+	outl(tmp, DEFAULT_GPIOBASE + GP_LVL);
+
+	tmp = inl(DEFAULT_GPIOBASE + GP_LVL2);
+	tmp = tmp & ~HYBRID_GRAPHICS_GP_LVL2_BITS;
+	outl(tmp, DEFAULT_GPIOBASE + GP_LVL2);
+}
+
+static void hybrid_graphics_switch_to_discrete_graphics(void)
+{
+	uint32_t tmp;
+
+	/* Disable switchable graphics */
+	hybrid_graphics_configure_switchable_graphics(false);
+
+	/* Configure muxes */
+	tmp = inl(DEFAULT_GPIOBASE + GP_LVL);
+	tmp = tmp | HYBRID_GRAPHICS_GP_LVL_BITS;
+	outl(tmp, DEFAULT_GPIOBASE + GP_LVL);
+
+	tmp = inl(DEFAULT_GPIOBASE + GP_LVL2);
+	tmp = tmp | HYBRID_GRAPHICS_GP_LVL2_BITS;
+	outl(tmp, DEFAULT_GPIOBASE + GP_LVL2);
+}
+
+static void hybrid_graphics_switch_to_dual_graphics(void)
+{
+	/* Enable switchable graphics */
+	hybrid_graphics_configure_switchable_graphics(true);
+}
+
 static void default_southbridge_gpio_setup(void)
 {
 	outl(0x197e23fe, DEFAULT_GPIOBASE + GP_IO_USE_SEL);
@@ -95,6 +208,31 @@ void mainboard_romstage_entry(unsigned long bist)
 
 	default_southbridge_gpio_setup();
 
+	uint8_t hybrid_graphics_mode = HYBRID_GRAPHICS_INTEGRATED_ONLY;
+	get_option(&hybrid_graphics_mode, "hybrid_graphics_mode");
+
+	/* Set up hybrid graphics */
+	hybrid_graphics_set_up_gpio();
+	if (hybrid_graphics_installed()) {
+		/* Select appropriate hybrid graphics device */
+		printk(BIOS_DEBUG, "Hybrid graphics available, setting mode %d\n", hybrid_graphics_mode);
+		if (hybrid_graphics_mode == HYBRID_GRAPHICS_INTEGRATED_ONLY)
+			hybrid_graphics_switch_to_integrated_graphics();
+		else if (hybrid_graphics_mode == HYBRID_GRAPHICS_DISCRETE_ONLY)
+			hybrid_graphics_switch_to_discrete_graphics();
+		else if (hybrid_graphics_mode == HYBRID_GRAPHICS_SWITCHABLE)
+			hybrid_graphics_switch_to_integrated_graphics();
+			/* Switchable graphics are fully enabled after raminit */
+			/* FIXME
+			 * Enabling switchable graphics prevents bootup!
+			 * Debug and fix appropriately...
+			 */
+	}
+	else {
+		printk(BIOS_DEBUG, "Hybrid graphics not installed\n");
+		hybrid_graphics_switch_to_integrated_graphics();
+	}
+
 	/* ASPM related setting, set early by original BIOS. */
 	DMIBAR16(0x204) &= ~(3 << 10);
 
@@ -174,6 +312,11 @@ void mainboard_romstage_entry(unsigned long bist)
 	outl(inl(DEFAULT_GPIOBASE + 0x38) & ~0x400, DEFAULT_GPIOBASE + 0x38);
 
 	cbmem_initted = !cbmem_recovery(s3resume);
+
+	if (hybrid_graphics_installed())
+		if (hybrid_graphics_mode == HYBRID_GRAPHICS_SWITCHABLE)
+			hybrid_graphics_switch_to_dual_graphics();
+
 #if CONFIG_HAVE_ACPI_RESUME
 	/* If there is no high memory area, we didn't boot before, so
 	 * this is not a resume. In that case we just create the cbmem toc.
-- 
2.9.2

