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@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)