From 384e9aed8c477922c960e2cbd429bd3a15b371de Mon Sep 17 00:00:00 2001 From: Evgeny Zinoviev Date: Thu, 30 Aug 2018 02:18:48 +0300 Subject: mb/lenovo: Support dual graphics for xx20/xx30 ThinkPads Add CMOS option that allows to use both integrated and discrete GPU. Tested on ThinkPad W530. Change-Id: I8842fef0fa1235eb91abf6b7e655ed4d8598adc7 Signed-off-by: Evgeny Zinoviev Reviewed-on: https://review.coreboot.org/28393 Reviewed-by: Patrick Rudolph Tested-by: build bot (Jenkins) --- src/drivers/lenovo/hybrid_graphics/romstage.c | 16 +++------------- src/ec/lenovo/pmh7/pmh7.c | 21 +++++++++++++++++++++ src/ec/lenovo/pmh7/pmh7.h | 2 ++ src/mainboard/lenovo/t420/cmos.layout | 1 + src/mainboard/lenovo/t420/romstage.c | 3 +++ src/mainboard/lenovo/t420s/cmos.layout | 1 + src/mainboard/lenovo/t420s/romstage.c | 3 +++ src/mainboard/lenovo/t430/cmos.layout | 1 + src/mainboard/lenovo/t430/romstage.c | 3 +++ src/mainboard/lenovo/t430s/cmos.default | 1 + src/mainboard/lenovo/t430s/cmos.layout | 3 ++- src/mainboard/lenovo/t430s/romstage.c | 18 ++++++++++++++++++ src/mainboard/lenovo/t520/romstage.c | 3 +++ src/mainboard/lenovo/t530/cmos.layout | 1 + src/mainboard/lenovo/t530/romstage.c | 3 +++ 15 files changed, 66 insertions(+), 14 deletions(-) diff --git a/src/drivers/lenovo/hybrid_graphics/romstage.c b/src/drivers/lenovo/hybrid_graphics/romstage.c index 8814916872..35cb384301 100644 --- a/src/drivers/lenovo/hybrid_graphics/romstage.c +++ b/src/drivers/lenovo/hybrid_graphics/romstage.c @@ -20,7 +20,6 @@ #include #include #include -#include #include "hybrid_graphics.h" #include "chip.h" @@ -87,18 +86,9 @@ void early_hybrid_graphics(bool *enable_igd, bool *enable_peg) set_gpio(config->dgpu_power_gpio, config->dgpu_power_off_lvl); } else if (config->has_thinker1) { - const size_t power_en = !!(pmh7_register_read(0x50) & 0x08); - if (*enable_peg && !power_en) { - pmh7_register_clear_bit(0x50, 7); // DGPU_RST - pmh7_register_set_bit(0x50, 3); // DGPU_PWR - mdelay(10); - pmh7_register_set_bit(0x50, 7); // DGPU_RST - mdelay(50); - } else if (!*enable_peg && power_en) { - pmh7_register_clear_bit(0x50, 7); // DGPU_RST - udelay(100); - pmh7_register_clear_bit(0x50, 3); // DGPU_PWR - } + bool power_en = pmh7_dgpu_power_state(); + if (*enable_peg != power_en) + pmh7_dgpu_power_enable(!power_en); } else { printk(BIOS_ERR, "Hybrid graphics:" " FIXME: dGPU power handling not implemented\n"); diff --git a/src/ec/lenovo/pmh7/pmh7.c b/src/ec/lenovo/pmh7/pmh7.c index b160fd0bc1..f7b798be33 100644 --- a/src/ec/lenovo/pmh7/pmh7.c +++ b/src/ec/lenovo/pmh7/pmh7.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "pmh7.h" #include "chip.h" @@ -64,6 +65,26 @@ void pmh7_ultrabay_power_enable(int onoff) pmh7_register_set_bit(0x62, 0); } +void pmh7_dgpu_power_enable(int onoff) +{ + if (onoff) { + pmh7_register_clear_bit(0x50, 7); // DGPU_RST + pmh7_register_set_bit(0x50, 3); // DGPU_PWR + mdelay(10); + pmh7_register_set_bit(0x50, 7); // DGPU_RST + mdelay(50); + } else { + pmh7_register_clear_bit(0x50, 7); // DGPU_RST + udelay(100); + pmh7_register_clear_bit(0x50, 3); // DGPU_PWR + } +} + +bool pmh7_dgpu_power_state(void) +{ + return (pmh7_register_read(0x50) & 0x08) == 8; +} + void pmh7_register_set_bit(int reg, int bit) { char val; diff --git a/src/ec/lenovo/pmh7/pmh7.h b/src/ec/lenovo/pmh7/pmh7.h index d486ceb041..a641fce0fa 100644 --- a/src/ec/lenovo/pmh7/pmh7.h +++ b/src/ec/lenovo/pmh7/pmh7.h @@ -35,5 +35,7 @@ void pmh7_dock_event_enable(int onoff); void pmh7_touchpad_enable(int onoff); void pmh7_ultrabay_power_enable(int onoff); void pmh7_trackpoint_enable(int onoff); +void pmh7_dgpu_power_enable(int onoff); +bool pmh7_dgpu_power_state(void); #endif /* EC_LENOVO_PMH7_H */ diff --git a/src/mainboard/lenovo/t420/cmos.layout b/src/mainboard/lenovo/t420/cmos.layout index 5a9e570c3f..f55c2037d5 100644 --- a/src/mainboard/lenovo/t420/cmos.layout +++ b/src/mainboard/lenovo/t420/cmos.layout @@ -129,6 +129,7 @@ enumerations 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/romstage.c b/src/mainboard/lenovo/t420/romstage.c index 36e83a3c72..bef256200e 100644 --- a/src/mainboard/lenovo/t420/romstage.c +++ b/src/mainboard/lenovo/t420/romstage.c @@ -30,6 +30,9 @@ static void hybrid_graphics_init(void) 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/cmos.layout b/src/mainboard/lenovo/t420s/cmos.layout index f395c0c808..2be55f67c7 100644 --- a/src/mainboard/lenovo/t420s/cmos.layout +++ b/src/mainboard/lenovo/t420s/cmos.layout @@ -129,6 +129,7 @@ enumerations 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/romstage.c b/src/mainboard/lenovo/t420s/romstage.c index 55011cf2e2..be8052c3ba 100644 --- a/src/mainboard/lenovo/t420s/romstage.c +++ b/src/mainboard/lenovo/t420s/romstage.c @@ -32,6 +32,9 @@ static void hybrid_graphics_init(void) 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/cmos.layout b/src/mainboard/lenovo/t430/cmos.layout index 2b687c296b..1b50e7fa74 100644 --- a/src/mainboard/lenovo/t430/cmos.layout +++ b/src/mainboard/lenovo/t430/cmos.layout @@ -128,6 +128,7 @@ enumerations 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/romstage.c b/src/mainboard/lenovo/t430/romstage.c index 94679df0a6..90d0886af1 100644 --- a/src/mainboard/lenovo/t430/romstage.c +++ b/src/mainboard/lenovo/t430/romstage.c @@ -30,6 +30,9 @@ static void hybrid_graphics_init(void) 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/cmos.default b/src/mainboard/lenovo/t430s/cmos.default index 979f132863..3e1f130ce4 100644 --- a/src/mainboard/lenovo/t430s/cmos.default +++ b/src/mainboard/lenovo/t430s/cmos.default @@ -13,4 +13,5 @@ fn_ctrl_swap=Disable sticky_fn=Disable trackpoint=Enable backlight=Both +enable_dual_graphics=Disable usb_always_on=Disable diff --git a/src/mainboard/lenovo/t430s/cmos.layout b/src/mainboard/lenovo/t430s/cmos.layout index 538e624350..97d97ed349 100644 --- a/src/mainboard/lenovo/t430s/cmos.layout +++ b/src/mainboard/lenovo/t430s/cmos.layout @@ -76,7 +76,8 @@ entries # coreboot config options: northbridge 432 3 e 11 gfx_uma_size -#435 5 r 0 unused +435 1 e 1 enable_dual_graphics +#436 4 r 0 unused 440 8 h 0 volume # SandyBridge MRC Scrambler Seed values diff --git a/src/mainboard/lenovo/t430s/romstage.c b/src/mainboard/lenovo/t430s/romstage.c index 3f6d9f2836..633ba3f142 100644 --- a/src/mainboard/lenovo/t430s/romstage.c +++ b/src/mainboard/lenovo/t430s/romstage.c @@ -15,12 +15,14 @@ * GNU General Public License for more details. */ +#include #include #include #include #include #include #include +#include void pch_enable_lpc(void) { @@ -64,6 +66,22 @@ void mainboard_get_spd(spd_raw_data *spd, bool id_only) { } void mainboard_early_init(int s3resume) { + u8 enable_peg; + if (get_option(&enable_peg, "enable_dual_graphics") != CB_SUCCESS) + enable_peg = 0; + + bool power_en = pmh7_dgpu_power_state(); + + if (enable_peg != power_en) + pmh7_dgpu_power_enable(!power_en); + + if (!enable_peg) { + // Hide disabled dGPU device + u32 reg32 = pci_read_config32(PCI_DEV(0, 0, 0), DEVEN); + reg32 &= ~DEVEN_PEG10; + + pci_write_config32(PCI_DEV(0, 0, 0), DEVEN, reg32); + } } void mainboard_config_superio(void) diff --git a/src/mainboard/lenovo/t520/romstage.c b/src/mainboard/lenovo/t520/romstage.c index 328ae37abd..4fcd651b6a 100644 --- a/src/mainboard/lenovo/t520/romstage.c +++ b/src/mainboard/lenovo/t520/romstage.c @@ -42,6 +42,9 @@ static void hybrid_graphics_init(void) 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/cmos.layout b/src/mainboard/lenovo/t530/cmos.layout index 9a099f5b3a..3400a4d4c7 100644 --- a/src/mainboard/lenovo/t530/cmos.layout +++ b/src/mainboard/lenovo/t530/cmos.layout @@ -129,6 +129,7 @@ enumerations 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/romstage.c b/src/mainboard/lenovo/t530/romstage.c index ba7a229a0d..88e07c1712 100644 --- a/src/mainboard/lenovo/t530/romstage.c +++ b/src/mainboard/lenovo/t530/romstage.c @@ -34,6 +34,9 @@ static void hybrid_graphics_init(void) 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); -- cgit v1.2.3