Evgeny Zinoviev has uploaded this change for review.

View Change

[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@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@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@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 change 28380. To unsubscribe, or for help writing mail filters, visit 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@ch1p.com>