[coreboot-gerrit] Change in coreboot[master]: [WIP] Nvidia Optimus support for ThinkPads

Evgeny Zinoviev (Code Review) gerrit at coreboot.org
Wed Aug 29 01:53:26 CEST 2018


Evgeny Zinoviev has uploaded this change for review. ( https://review.coreboot.org/28380


Change subject: [WIP] Nvidia Optimus support for ThinkPads
......................................................................

[WIP] Nvidia Optimus support for ThinkPads

Based on siro's work #23041.
Tested on ThinkPad W530.

Enables dual graphics mode for T420, T420s, T530, T430, T430s, T530
mainboards, adds ACPI code for dGPU power management.

What works (tested on 4.16.13-gentoo kernel):
- power management via _PS0 and _DSM + _PS3 ACPI calls
- nouveau driver (with a workaround, see below)
- bumblebee (from the "develop" branch)
- bbswitch

Known problems:
- `lspci -s 01:00.0 -vv` turns dGPU on if it was off before. Not sure why it
  happens (probably it calls _PS0 at some point) or whether it should
  happen.

- nouveau driver unloading (`rmmod` or `modprobe -r`) does not work well: it
  crashes in nouveau_backlight_exit (invalid pointer). The current hack is
  to comment out these lines in drivers/gpu/drm/nouveau/nouveau_backlight.c,
  function  `nouveau_backlight_exit`:

  list_for_each_entry(connector, &drm->bl_connectors, head) {
    if (connector->id >= 0)
      ida_simple_remove(&bl_ida, connector->id);
    }

  Need to debug why it happens.

- VGA ROM for Nvidia GPU is not loaded from BIOS (i.e. coreboot). Need
  to debug and fix this too. The current workaround is to load it from
  a file.

  To do this automatically, create a new file in /etc/modprobe.d with this
  line:

  config=NvBios=pci10de-0ffc.rom

  where "pci10de-0ffc.rom" is a file in /lib/firmware directory
  (the path is relative to /lib/firmware). VGA ROM has to be extracted
  from vendor UEFI dump, GUID is 9781FA9D-5A3B-431A-AD59-2748C9A170EC.

Not tested yet:
- nvidia proprietary driver

Change-Id: I277808d6c1d8bd6e0a267a53f25471597698f8d5
Signed-off-by: Evgeny Zinoviev <me at ch1p.com>
---
A src/drivers/lenovo/hybrid_graphics/acpi/gpu.asl
A src/drivers/nvidia/optimus/acpi/optimus.asl
A src/ec/lenovo/pmh7/acpi/pmh7.asl
M src/mainboard/lenovo/t420/acpi/ec.asl
M src/mainboard/lenovo/t420/cmos.layout
M src/mainboard/lenovo/t420/dsdt.asl
M src/mainboard/lenovo/t420/romstage.c
M src/mainboard/lenovo/t420s/acpi/ec.asl
M src/mainboard/lenovo/t420s/cmos.layout
M src/mainboard/lenovo/t420s/dsdt.asl
M src/mainboard/lenovo/t420s/romstage.c
M src/mainboard/lenovo/t430/acpi/ec.asl
M src/mainboard/lenovo/t430/cmos.layout
M src/mainboard/lenovo/t430/devicetree.cb
M src/mainboard/lenovo/t430/dsdt.asl
M src/mainboard/lenovo/t430/romstage.c
M src/mainboard/lenovo/t430s/Kconfig
M src/mainboard/lenovo/t430s/Makefile.inc
M src/mainboard/lenovo/t430s/acpi/ec.asl
M src/mainboard/lenovo/t430s/cmos.default
M src/mainboard/lenovo/t430s/cmos.layout
M src/mainboard/lenovo/t430s/devicetree.cb
M src/mainboard/lenovo/t430s/dsdt.asl
M src/mainboard/lenovo/t430s/romstage.c
M src/mainboard/lenovo/t520/acpi/ec.asl
M src/mainboard/lenovo/t520/dsdt.asl
M src/mainboard/lenovo/t520/romstage.c
M src/mainboard/lenovo/t530/acpi/ec.asl
M src/mainboard/lenovo/t530/cmos.layout
M src/mainboard/lenovo/t530/dsdt.asl
M src/mainboard/lenovo/t530/romstage.c
M src/mainboard/lenovo/t530/variants/t530/devicetree.cb
M src/mainboard/lenovo/t530/variants/w530/devicetree.cb
M src/northbridge/intel/sandybridge/acpi/peg.asl
34 files changed, 427 insertions(+), 4 deletions(-)



  git pull ssh://review.coreboot.org:29418/coreboot refs/changes/80/28380/1

diff --git a/src/drivers/lenovo/hybrid_graphics/acpi/gpu.asl b/src/drivers/lenovo/hybrid_graphics/acpi/gpu.asl
new file mode 100644
index 0000000..feb9d5e
--- /dev/null
+++ b/src/drivers/lenovo/hybrid_graphics/acpi/gpu.asl
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2017-2018 Patrick Rudolph <siro at das-labor.org>
+ *
+ * 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.
+ */
+
+Scope (\_SB.PCI0.PEGP.DEV0) {
+	Method (_INI) {
+		// Tell peg.asl that we have _OFF and _ON
+		Store (One, DEVP)
+	}
+
+	Method (_OFF) {
+		\_SB.PCI0.LPCB.PMH7.GPUP(Zero)
+	}
+
+	Method (_ON) {
+		\_SB.PCI0.LPCB.PMH7.GPUP(One)
+	}
+
+	Method (_STA) {
+		Return (\_SB.PCI0.LPCB.PMH7.GPUS())
+	}
+}
diff --git a/src/drivers/nvidia/optimus/acpi/optimus.asl b/src/drivers/nvidia/optimus/acpi/optimus.asl
new file mode 100644
index 0000000..feb2b5d
--- /dev/null
+++ b/src/drivers/nvidia/optimus/acpi/optimus.asl
@@ -0,0 +1,199 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (c) 2011 Sven Schnelle <svens at stackframe.org>
+ *
+ * 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.
+ */
+ Scope (\_SB.PCI0.PEGP.DEV0) {
+
+	Name (DGOS, 0x00)
+	Name (OMPR, 0x02)
+	Name (HDAS, 0x00)
+
+	Method (NVOP, 4, Serialized)
+	{
+		If (LNotEqual (Arg1, 0x0100))
+		{
+			Return (0x80000001)
+		}
+
+		Store (ToInteger (Arg2), Local0)
+
+		/* Supported Optimus functions advertisement */
+		If (LEqual (Local0, 0x00))
+		{
+			Return (Buffer (0x04)
+			{
+				0x09, 0x00, 0x00, 0x06
+			})
+		}
+		/* NOUVEAU_DSM_OPTIMUS_CAPS */
+		If (LEqual (Local0, 0x1A))
+		{
+			CreateField (Arg3, 0x18, 0x02, OPCE)
+			CreateField (Arg3, 0x00, 0x01, FLCH)
+			If (ToInteger (FLCH))
+			{
+				// NOUVEAU_DSM_OPTIMUS_SET_POWERDOWN
+				// only called if no _PR3 in parent
+				Store (OPCE, OMPR)
+			}
+
+			Store (Buffer (0x04)
+			{
+				 0x00, 0x00, 0x00, 0x00
+			}, Local0)
+			CreateField (Local0, 0x00, 0x01, OPEN)
+			CreateField (Local0, 0x03, 0x02, CGCS)
+			CreateField (Local0, 0x06, 0x01, SHPC)
+			CreateField (Local0, 0x18, 0x03, DGPC)
+			CreateField (Local0, 0x1B, 0x02, HDAC)
+			Store (One, OPEN) // OPTIMUS_ENABLED
+			Store (One, SHPC) // OPTIMUS_DISPLAY_HOTPLUG
+			Store (One, DGPC) // OPTIMUS_DYNAMIC_PWR_CAP
+			If (\_SB.PCI0.PEGP.DEV0._STA ())
+			{
+				Store (0x03, CGCS) // OPTIMUS_STATUS_PWR_STABLE
+			}
+
+			Store (0x02, HDAC) // OPTIMUS_HDA_CODEC_MASK
+			Return (Local0)
+		}
+		/* NOUVEAU_DSM_OPTIMUS_FLAGS */
+		If (LEqual (Local0, 0x1B))
+		{
+			CreateField (Arg3, 0x00, 0x01, HDAU)
+			CreateField (Arg3, 0x01, 0x01, HDAR)
+			Store (Buffer (0x04)
+			{
+				 0x00, 0x00, 0x00, 0x00
+			}, Local0)
+			CreateField (Local0, 0x02, 0x02, RQGS)
+			CreateField (Local0, 0x04, 0x01, PWST)
+			Store (One, PWST)
+			Store (Zero, RQGS)
+			If (ToInteger (HDAR))
+			{
+				//VGA switcheroo: Called on card power off
+				Store (ToInteger (HDAU), HDAS)
+			}
+
+			Return (Local0)
+		}
+		/* NOUVEAU_DSM_POWER */
+		If (LEqual (Local0, 3))
+		{
+			// Unused if _PS0 and _PS3 is present ?
+			If (ToInteger(Arg3)) {
+				\_SB.PCI0.PEGP.DEV0._ON()
+			} Else {
+				\_SB.PCI0.PEGP.DEV0._OFF()
+			}
+		}
+
+		Return (0x80000002)
+	}
+
+	// helper function to compare two buffers
+	Method (CMP, 2, NotSerialized)
+	{
+		If (LNotEqual (0x10, SizeOf (Arg0)))
+		{
+			Return (0x00)
+		}
+
+		If (LNotEqual (0x10, SizeOf (Arg1)))
+		{
+			Return (0x00)
+		}
+
+		Store (0x00, Local0)
+		While (LLess (Local0, 0x10))
+		{
+			If (LNotEqual (DerefOf (Index (Arg0, Local0)), DerefOf (Index (
+				Arg1, Local0))))
+			{
+				Return (0x00)
+			}
+
+			Increment (Local0)
+		}
+
+		Return (0x01)
+	}
+
+	Method (_DSM, 4, NotSerialized)
+	{
+		/* NV DSM OPTIMUS */
+		If (CMP (Arg0, Buffer (0x10) {
+			0xF8, 0xD8, 0x86, 0xA4, 0xDA, 0x0B, 0x1B, 0x47,
+			0xA7, 0x2B, 0x60, 0x42, 0xA6, 0xB5, 0xBE, 0xE0}))
+		{
+			Return (NVOP (Arg0, Arg1, Arg2, Arg3))
+		}
+
+		Return (Buffer (0x04)
+		{
+			0x01, 0x00, 0x00, 0x80
+		})
+	}
+
+	OperationRegion (RPCS, PCI_Config, 0x00, 0x100)
+	Field (RPCS, AnyAcc, NoLock, Preserve)
+	{
+		VID, 16,
+	}
+
+	Method (_PS0, 0, NotSerialized)
+	{
+		If (\_SB.PCI0.PEGP.DEV0.DGOS)
+		{
+			\_SB.PCI0.PEGP.DEV0._ON ()
+			Sleep(50)
+
+			\_SB.PCI0.PEGP._ON ()
+			Sleep(50)
+
+			Store (0x32, Local0)
+			While (Or(LEqual(VID, 0xffff), LEqual(VID, 0x0000)))
+			{
+				Sleep (10)
+				Decrement (Local0)
+			}
+			Store (Zero, HDAS)
+			Store (Zero, DGOS)
+		}
+	}
+
+	Method (_PS1, 0, NotSerialized)
+	{
+	}
+
+	Method (_PS2, 0, NotSerialized)
+	{
+	}
+
+	Method (_PS3, 0, NotSerialized)
+	{
+		If (LEqual (\_SB.PCI0.PEGP.DEV0.OMPR, 0x03))
+		{
+			\_SB.PCI0.PEGP._OFF ()
+			Sleep(50)
+
+			\_SB.PCI0.PEGP.DEV0._OFF ()
+			Sleep(50)
+
+			Store (0x02, \_SB.PCI0.PEGP.DEV0.OMPR)
+			Store (0x01, \_SB.PCI0.PEGP.DEV0.DGOS)
+		}
+	}
+}
diff --git a/src/ec/lenovo/pmh7/acpi/pmh7.asl b/src/ec/lenovo/pmh7/acpi/pmh7.asl
new file mode 100644
index 0000000..1559209
--- /dev/null
+++ b/src/ec/lenovo/pmh7/acpi/pmh7.asl
@@ -0,0 +1,62 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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.
+ */
+
+Device(PMH7)
+{
+	Name (_HID, EISAID("PNP0C09"))
+	Name (_UID, 0)
+
+	OperationRegion (CREG, SystemIO, 0x15e0, 0x10)
+	Field (CREG, ByteAcc, NoLock, Preserve)
+	{
+		Offset(0x0c),
+		ADDR, 16, /* PMH7 has 9-bit address space, which is supported by
+		             pmh7tool, and if some register greater than 0xff was
+		             read before, then 0x0D port must be cleared, otherwise
+		             it won't work (as it contains the wrong address) */
+		DATA, 8
+	}
+
+	IndexField (ADDR, DATA, ByteAcc, NoLock, Preserve)
+	{
+		Offset (0x50),
+		, 3,
+		DPWR, 1,
+		, 3,
+		DRST, 1
+	}
+
+	// Control dGPU power
+	Method (GPUP, 1)
+	{
+		If (LNotEqual(Arg0, GPUS())) {
+			If (Arg0) {
+				Store (Zero, DRST)
+				Store (One, DPWR)
+				Sleep (50)
+				Store (One, DRST)
+				Sleep (100)
+			} Else {
+				Store (Zero, DRST)
+				Sleep (10)
+				Store (Zero, DPWR)
+			}
+		}
+	}
+
+	// Return dGPU power state
+	Method (GPUS)
+	{
+		Return (DPWR)
+	}
+}
diff --git a/src/mainboard/lenovo/t420/acpi/ec.asl b/src/mainboard/lenovo/t420/acpi/ec.asl
index d631f12..faf8f86 100644
--- a/src/mainboard/lenovo/t420/acpi/ec.asl
+++ b/src/mainboard/lenovo/t420/acpi/ec.asl
@@ -15,6 +15,7 @@
  */
 
 #include <ec/lenovo/h8/acpi/ec.asl>
+#include <ec/lenovo/pmh7/acpi/pmh7.asl>
 
 Scope(\_SB.PCI0.LPCB.EC)
 {
diff --git a/src/mainboard/lenovo/t420/cmos.layout b/src/mainboard/lenovo/t420/cmos.layout
index 5a9e570..f55c203 100644
--- a/src/mainboard/lenovo/t420/cmos.layout
+++ b/src/mainboard/lenovo/t420/cmos.layout
@@ -129,6 +129,7 @@
 11    6     224M
 12    0     Integrated Only
 12    1     Discrete Only
+12    2     Dual Graphics
 13    0     Disable
 13    1     AC and battery
 13    2     AC only
diff --git a/src/mainboard/lenovo/t420/dsdt.asl b/src/mainboard/lenovo/t420/dsdt.asl
index 7db8344..a4af7cf 100644
--- a/src/mainboard/lenovo/t420/dsdt.asl
+++ b/src/mainboard/lenovo/t420/dsdt.asl
@@ -50,6 +50,9 @@
 		}
 	}
 
+  #include <drivers/lenovo/hybrid_graphics/acpi/gpu.asl>
+	#include <drivers/nvidia/optimus/acpi/optimus.asl>
+
 	/* Chipset specific sleep states */
 	#include <southbridge/intel/bd82x6x/acpi/sleepstates.asl>
 }
diff --git a/src/mainboard/lenovo/t420/romstage.c b/src/mainboard/lenovo/t420/romstage.c
index 36e83a3..bef2562 100644
--- a/src/mainboard/lenovo/t420/romstage.c
+++ b/src/mainboard/lenovo/t420/romstage.c
@@ -30,6 +30,9 @@
 
 	early_hybrid_graphics(&igd, &peg);
 
+	if (peg && igd)
+		return;
+
 	/* Hide disabled devices */
 	reg32 = pci_read_config32(PCI_DEV(0, 0, 0), DEVEN);
 	reg32 &= ~(DEVEN_PEG10 | DEVEN_IGD);
diff --git a/src/mainboard/lenovo/t420s/acpi/ec.asl b/src/mainboard/lenovo/t420s/acpi/ec.asl
index d631f12..faf8f86 100644
--- a/src/mainboard/lenovo/t420s/acpi/ec.asl
+++ b/src/mainboard/lenovo/t420s/acpi/ec.asl
@@ -15,6 +15,7 @@
  */
 
 #include <ec/lenovo/h8/acpi/ec.asl>
+#include <ec/lenovo/pmh7/acpi/pmh7.asl>
 
 Scope(\_SB.PCI0.LPCB.EC)
 {
diff --git a/src/mainboard/lenovo/t420s/cmos.layout b/src/mainboard/lenovo/t420s/cmos.layout
index f395c0c..2be55f6 100644
--- a/src/mainboard/lenovo/t420s/cmos.layout
+++ b/src/mainboard/lenovo/t420s/cmos.layout
@@ -129,6 +129,7 @@
 11    6     224M
 12    0     Integrated Only
 12    1     Discrete Only
+12    2     Dual Graphics
 13    0     Disable
 13    1     AC and battery
 13    2     AC only
diff --git a/src/mainboard/lenovo/t420s/dsdt.asl b/src/mainboard/lenovo/t420s/dsdt.asl
index c549988..3893114 100644
--- a/src/mainboard/lenovo/t420s/dsdt.asl
+++ b/src/mainboard/lenovo/t420s/dsdt.asl
@@ -51,6 +51,9 @@
 		}
 	}
 
+	#include <drivers/lenovo/hybrid_graphics/acpi/gpu.asl>
+	#include <drivers/nvidia/optimus/acpi/optimus.asl>
+
 	/* Chipset specific sleep states */
 	#include <southbridge/intel/bd82x6x/acpi/sleepstates.asl>
 }
diff --git a/src/mainboard/lenovo/t420s/romstage.c b/src/mainboard/lenovo/t420s/romstage.c
index 55011cf2..be8052c 100644
--- a/src/mainboard/lenovo/t420s/romstage.c
+++ b/src/mainboard/lenovo/t420s/romstage.c
@@ -32,6 +32,9 @@
 
 	early_hybrid_graphics(&igd, &peg);
 
+	if (peg && igd)
+		return;
+
 	/* Hide disabled devices */
 	reg32 = pci_read_config32(PCI_DEV(0, 0, 0), DEVEN);
 	reg32 &= ~(DEVEN_PEG10 | DEVEN_IGD);
diff --git a/src/mainboard/lenovo/t430/acpi/ec.asl b/src/mainboard/lenovo/t430/acpi/ec.asl
index 3c7f89d..924bd37 100644
--- a/src/mainboard/lenovo/t430/acpi/ec.asl
+++ b/src/mainboard/lenovo/t430/acpi/ec.asl
@@ -20,3 +20,4 @@
 #define THINKPAD_EC_GPE 17
 
 #include <ec/lenovo/h8/acpi/ec.asl>
+#include <ec/lenovo/pmh7/acpi/pmh7.asl>
diff --git a/src/mainboard/lenovo/t430/cmos.layout b/src/mainboard/lenovo/t430/cmos.layout
index 2b687c2..1b50e7f 100644
--- a/src/mainboard/lenovo/t430/cmos.layout
+++ b/src/mainboard/lenovo/t430/cmos.layout
@@ -128,6 +128,7 @@
 11    6     224M
 12    0     Integrated Only
 12    1     Discrete Only
+12    2     Dual Graphics
 13    0     Disable
 13    1     AC and battery
 13    2     AC only
diff --git a/src/mainboard/lenovo/t430/devicetree.cb b/src/mainboard/lenovo/t430/devicetree.cb
index d466b36..5eb92bc 100644
--- a/src/mainboard/lenovo/t430/devicetree.cb
+++ b/src/mainboard/lenovo/t430/devicetree.cb
@@ -167,7 +167,7 @@
 					register "has_backlight_gpio" = "0"
 					register "has_dgpu_power_gpio" = "0"
 
-					register "has_thinker1" = "0"
+					register "has_thinker1" = "1"
 				end
 				chip drivers/pc80/tpm
 					device pnp 0c31.0 on end
diff --git a/src/mainboard/lenovo/t430/dsdt.asl b/src/mainboard/lenovo/t430/dsdt.asl
index dff8dcd..ad817f0 100644
--- a/src/mainboard/lenovo/t430/dsdt.asl
+++ b/src/mainboard/lenovo/t430/dsdt.asl
@@ -40,4 +40,7 @@
 			#include <southbridge/intel/bd82x6x/acpi/pch.asl>
 		}
 	}
+
+	#include <drivers/lenovo/hybrid_graphics/acpi/gpu.asl>
+	#include <drivers/nvidia/optimus/acpi/optimus.asl>
 }
diff --git a/src/mainboard/lenovo/t430/romstage.c b/src/mainboard/lenovo/t430/romstage.c
index 94679df..90d0886 100644
--- a/src/mainboard/lenovo/t430/romstage.c
+++ b/src/mainboard/lenovo/t430/romstage.c
@@ -30,6 +30,9 @@
 
 	early_hybrid_graphics(&igd, &peg);
 
+	if (peg && igd)
+		return;
+
 	/* Hide disabled devices */
 	reg32 = pci_read_config32(PCI_DEV(0, 0, 0), DEVEN);
 	reg32 &= ~(DEVEN_PEG10 | DEVEN_IGD);
diff --git a/src/mainboard/lenovo/t430s/Kconfig b/src/mainboard/lenovo/t430s/Kconfig
index 728dd5c..a86f9f5 100644
--- a/src/mainboard/lenovo/t430s/Kconfig
+++ b/src/mainboard/lenovo/t430s/Kconfig
@@ -23,6 +23,7 @@
 	select MAINBOARD_HAS_LIBGFXINIT
 	select GFX_GMA_INTERNAL_IS_LVDS
 	select INTEL_GMA_HAVE_VBT
+	select DRIVERS_LENOVO_HYBRID_GRAPHICS
 
 	# Workaround for EC/KBC IRQ1.
 	select SERIRQ_CONTINUOUS_MODE
diff --git a/src/mainboard/lenovo/t430s/Makefile.inc b/src/mainboard/lenovo/t430s/Makefile.inc
index cb01f1c..2dab950 100644
--- a/src/mainboard/lenovo/t430s/Makefile.inc
+++ b/src/mainboard/lenovo/t430s/Makefile.inc
@@ -15,4 +15,5 @@
 
 smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c
 romstage-y += gpio.c
+
 ramstage-$(CONFIG_MAINBOARD_USE_LIBGFXINIT) += gma-mainboard.ads
diff --git a/src/mainboard/lenovo/t430s/acpi/ec.asl b/src/mainboard/lenovo/t430s/acpi/ec.asl
index d631f12..faf8f86 100644
--- a/src/mainboard/lenovo/t430s/acpi/ec.asl
+++ b/src/mainboard/lenovo/t430s/acpi/ec.asl
@@ -15,6 +15,7 @@
  */
 
 #include <ec/lenovo/h8/acpi/ec.asl>
+#include <ec/lenovo/pmh7/acpi/pmh7.asl>
 
 Scope(\_SB.PCI0.LPCB.EC)
 {
diff --git a/src/mainboard/lenovo/t430s/cmos.default b/src/mainboard/lenovo/t430s/cmos.default
index 979f132..e65869b 100644
--- a/src/mainboard/lenovo/t430s/cmos.default
+++ b/src/mainboard/lenovo/t430s/cmos.default
@@ -14,3 +14,4 @@
 trackpoint=Enable
 backlight=Both
 usb_always_on=Disable
+hybrid_graphics_mode=Integrated Only
diff --git a/src/mainboard/lenovo/t430s/cmos.layout b/src/mainboard/lenovo/t430s/cmos.layout
index 538e624..1689b64 100644
--- a/src/mainboard/lenovo/t430s/cmos.layout
+++ b/src/mainboard/lenovo/t430s/cmos.layout
@@ -76,7 +76,8 @@
 
 # coreboot config options: northbridge
 432          3       e       11       gfx_uma_size
-#435         5       r       0        unused
+435          2       e       12       hybrid_graphics_mode
+#437         3       r       0        unused
 440          8       h       0        volume
 
 # SandyBridge MRC Scrambler Seed values
diff --git a/src/mainboard/lenovo/t430s/devicetree.cb b/src/mainboard/lenovo/t430s/devicetree.cb
index b14d60c..376ea07 100644
--- a/src/mainboard/lenovo/t430s/devicetree.cb
+++ b/src/mainboard/lenovo/t430s/devicetree.cb
@@ -159,6 +159,20 @@
 					register "bdc_gpio_num" = "54"
 					register "bdc_gpio_lvl" = "0"
 				end
+				chip drivers/lenovo/hybrid_graphics
+					device pnp ff.f on end # dummy
+
+					register "detect_gpio" = "21"
+
+					register "has_panel_hybrid_gpio" = "1"
+					register "panel_hybrid_gpio" = "52"
+					register "panel_integrated_lvl" = "1"
+
+					register "has_backlight_gpio" = "0"
+					register "has_dgpu_power_gpio" = "0"
+
+					register "has_thinker1" = "1"
+				end
 			end # LPC Controller
 			device pci 1f.2 on
 				subsystemid 0x17aa 0x21fb
diff --git a/src/mainboard/lenovo/t430s/dsdt.asl b/src/mainboard/lenovo/t430s/dsdt.asl
index c549988..3893114 100644
--- a/src/mainboard/lenovo/t430s/dsdt.asl
+++ b/src/mainboard/lenovo/t430s/dsdt.asl
@@ -51,6 +51,9 @@
 		}
 	}
 
+	#include <drivers/lenovo/hybrid_graphics/acpi/gpu.asl>
+	#include <drivers/nvidia/optimus/acpi/optimus.asl>
+
 	/* Chipset specific sleep states */
 	#include <southbridge/intel/bd82x6x/acpi/sleepstates.asl>
 }
diff --git a/src/mainboard/lenovo/t430s/romstage.c b/src/mainboard/lenovo/t430s/romstage.c
index 3f6d9f2..8b7e396 100644
--- a/src/mainboard/lenovo/t430s/romstage.c
+++ b/src/mainboard/lenovo/t430s/romstage.c
@@ -20,8 +20,35 @@
 #include <device/pci_def.h>
 #include <console/console.h>
 #include <northbridge/intel/sandybridge/raminit_native.h>
+#include <drivers/lenovo/hybrid_graphics/hybrid_graphics.h>
 #include <southbridge/intel/bd82x6x/pch.h>
 
+static void hybrid_graphics_init(void)
+{
+	bool peg, igd;
+	u32 reg32;
+
+	early_hybrid_graphics(&igd, &peg);
+
+	if (peg && igd)
+		return;
+
+	/* Hide disabled devices */
+	reg32 = pci_read_config32(PCI_DEV(0, 0, 0), DEVEN);
+	reg32 &= ~(DEVEN_PEG10 | DEVEN_IGD);
+
+	if (peg)
+		reg32 |= DEVEN_PEG10;
+
+	if (igd)
+		reg32 |= DEVEN_IGD;
+	else
+		/* Disable IGD VGA decode, no GTT or GFX stolen */
+		pci_write_config16(PCI_DEV(0, 0, 0), GGC, 2);
+
+	pci_write_config32(PCI_DEV(0, 0, 0), DEVEN, reg32);
+}
+
 void pch_enable_lpc(void)
 {
 	/* EC Decode Range Port60/64, Port62/66 */
@@ -64,6 +91,7 @@
 }
 
 void mainboard_early_init(int s3resume) {
+	hybrid_graphics_init();
 }
 
 void mainboard_config_superio(void)
diff --git a/src/mainboard/lenovo/t520/acpi/ec.asl b/src/mainboard/lenovo/t520/acpi/ec.asl
index d631f12..faf8f86 100644
--- a/src/mainboard/lenovo/t520/acpi/ec.asl
+++ b/src/mainboard/lenovo/t520/acpi/ec.asl
@@ -15,6 +15,7 @@
  */
 
 #include <ec/lenovo/h8/acpi/ec.asl>
+#include <ec/lenovo/pmh7/acpi/pmh7.asl>
 
 Scope(\_SB.PCI0.LPCB.EC)
 {
diff --git a/src/mainboard/lenovo/t520/dsdt.asl b/src/mainboard/lenovo/t520/dsdt.asl
index 7db8344..39d6d29 100644
--- a/src/mainboard/lenovo/t520/dsdt.asl
+++ b/src/mainboard/lenovo/t520/dsdt.asl
@@ -50,6 +50,9 @@
 		}
 	}
 
+	#include <drivers/lenovo/hybrid_graphics/acpi/gpu.asl>
+	#include <drivers/nvidia/optimus/acpi/optimus.asl>
+
 	/* Chipset specific sleep states */
 	#include <southbridge/intel/bd82x6x/acpi/sleepstates.asl>
 }
diff --git a/src/mainboard/lenovo/t520/romstage.c b/src/mainboard/lenovo/t520/romstage.c
index 328ae37..4fcd651 100644
--- a/src/mainboard/lenovo/t520/romstage.c
+++ b/src/mainboard/lenovo/t520/romstage.c
@@ -42,6 +42,9 @@
 
 	early_hybrid_graphics(&igd, &peg);
 
+	if (peg && igd)
+		return;
+
 	/* Hide disabled devices */
 	reg32 = pci_read_config32(PCI_DEV(0, 0, 0), DEVEN);
 	reg32 &= ~(DEVEN_PEG10 | DEVEN_IGD);
diff --git a/src/mainboard/lenovo/t530/acpi/ec.asl b/src/mainboard/lenovo/t530/acpi/ec.asl
index d631f12..faf8f86 100644
--- a/src/mainboard/lenovo/t530/acpi/ec.asl
+++ b/src/mainboard/lenovo/t530/acpi/ec.asl
@@ -15,6 +15,7 @@
  */
 
 #include <ec/lenovo/h8/acpi/ec.asl>
+#include <ec/lenovo/pmh7/acpi/pmh7.asl>
 
 Scope(\_SB.PCI0.LPCB.EC)
 {
diff --git a/src/mainboard/lenovo/t530/cmos.layout b/src/mainboard/lenovo/t530/cmos.layout
index 9a099f5..a47b7e8 100644
--- a/src/mainboard/lenovo/t530/cmos.layout
+++ b/src/mainboard/lenovo/t530/cmos.layout
@@ -3,6 +3,7 @@
 ##
 ## Copyright (C) 2007-2008 coresystems GmbH
 ## Copyright (C) 2014 Vladimir Serbinenko
+## Copyright (C) 2018 Evgeny Zinoviev
 ##
 ## 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
@@ -129,6 +130,7 @@
 11    6     224M
 12    0     Integrated Only
 12    1     Discrete Only
+12    2     Dual Graphics
 13    0     Disable
 13    1     AC and battery
 13    2     AC only
diff --git a/src/mainboard/lenovo/t530/dsdt.asl b/src/mainboard/lenovo/t530/dsdt.asl
index 7db8344..39d6d29 100644
--- a/src/mainboard/lenovo/t530/dsdt.asl
+++ b/src/mainboard/lenovo/t530/dsdt.asl
@@ -50,6 +50,9 @@
 		}
 	}
 
+	#include <drivers/lenovo/hybrid_graphics/acpi/gpu.asl>
+	#include <drivers/nvidia/optimus/acpi/optimus.asl>
+
 	/* Chipset specific sleep states */
 	#include <southbridge/intel/bd82x6x/acpi/sleepstates.asl>
 }
diff --git a/src/mainboard/lenovo/t530/romstage.c b/src/mainboard/lenovo/t530/romstage.c
index ba7a229..88e07c1 100644
--- a/src/mainboard/lenovo/t530/romstage.c
+++ b/src/mainboard/lenovo/t530/romstage.c
@@ -34,6 +34,9 @@
 
 	early_hybrid_graphics(&igd, &peg);
 
+	if (peg && igd)
+		return;
+
 	/* Hide disabled devices */
 	reg32 = pci_read_config32(PCI_DEV(0, 0, 0), DEVEN);
 	reg32 &= ~(DEVEN_PEG10 | DEVEN_IGD);
diff --git a/src/mainboard/lenovo/t530/variants/t530/devicetree.cb b/src/mainboard/lenovo/t530/variants/t530/devicetree.cb
index 0da05e0..4dcdc9d 100644
--- a/src/mainboard/lenovo/t530/variants/t530/devicetree.cb
+++ b/src/mainboard/lenovo/t530/variants/t530/devicetree.cb
@@ -157,7 +157,7 @@
 					register "has_backlight_gpio" = "0"
 					register "has_dgpu_power_gpio" = "0"
 
-					register "has_thinker1" = "0"
+					register "has_thinker1" = "1"
 				end
 			end # LPC bridge
 			device pci 1f.2 on end # SATA Controller 1
diff --git a/src/mainboard/lenovo/t530/variants/w530/devicetree.cb b/src/mainboard/lenovo/t530/variants/w530/devicetree.cb
index d9d9df5..7a72b26 100644
--- a/src/mainboard/lenovo/t530/variants/w530/devicetree.cb
+++ b/src/mainboard/lenovo/t530/variants/w530/devicetree.cb
@@ -179,7 +179,7 @@
 					register "has_backlight_gpio" = "0"
 					register "has_dgpu_power_gpio" = "0"
 
-					register "has_thinker1" = "0"
+					register "has_thinker1" = "1"
 				end
 			end
 			device pci 1f.2 on # SATA Controller 1
diff --git a/src/northbridge/intel/sandybridge/acpi/peg.asl b/src/northbridge/intel/sandybridge/acpi/peg.asl
index f98a4ce..89c2e25 100644
--- a/src/northbridge/intel/sandybridge/acpi/peg.asl
+++ b/src/northbridge/intel/sandybridge/acpi/peg.asl
@@ -28,6 +28,44 @@
 	{
 		Name(_ADR, 0x00000000)
 	}
+
+	OperationRegion (RPCS, PCI_Config, 0x00, 0x100)
+	Field (RPCS, AnyAcc, NoLock, Preserve)
+	{
+		Offset (0xb0),	// Link Capabilities
+		, 4,
+		LNKD, 1,	// Link Disable
+		RTRL, 1,	// Retrain Link
+		Offset (0xb2),	// Link Status
+		, 10,
+		LNKT, 1,	// Link Training
+	}
+
+	Name (DEVP, 0)
+
+	Method (_ON)
+	{
+		Store(Zero, LNKD)
+		Store(One, RTRL)
+
+		Store (0x32, Local1)
+		While (Local1)
+		{
+			Sleep (10)
+			If (LEqual(LNKT, 0))
+			{
+				Break
+			}
+
+			Decrement (Local1)
+		}
+	}
+
+	Method (_OFF)
+	{
+		Store(One, LNKD)
+		Sleep (10)
+	}
 }
 
 Device (PEG1)

-- 
To view, visit https://review.coreboot.org/28380
To unsubscribe, or for help writing mail filters, visit https://review.coreboot.org/settings

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I277808d6c1d8bd6e0a267a53f25471597698f8d5
Gerrit-Change-Number: 28380
Gerrit-PatchSet: 1
Gerrit-Owner: Evgeny Zinoviev <me at ch1p.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.coreboot.org/pipermail/coreboot-gerrit/attachments/20180828/9753a1d0/attachment-0001.html>


More information about the coreboot-gerrit mailing list