mb/lenovo/t*00/romstage: Switch to new hybrid driver

Get rid of old hybrid graphics driver and use the new one.

1. Disable IGD and PEG in early romstage.
 The PEG port will get disabled on devices that do not have a
 discrete GPU. The power savings are around ~1Watt.

 The disabled IGD does no longer waste GFX stolen memory.

2. Get rid of PCI driver
 The Nvidia GPU can be handled by the generic PCI driver and allows
 to use the ACPI _ROM generator for Switchable graphics.

3. Settings are stored in devicetree.
 One driver for all Lenovo hybrid graphics capable devices.

4. Add support for Thinker1 GPU power handling.
 Only boards that do use reference design 2012 are known to be
 supported. Needs test on boards that do you use reference design 2013.
 Should reduce idle power consumption when using IGD by ~5Watt.

Tested on Lenovo T430 without DGPU. PEG port is disabled.
Needs test on all devices.

Change-Id: Ibf18b75e8afe2568de8498b39a608dac8db3ba73
Signed-off-by: Patrick Rudolph <siro@das-labor.org>
Reviewed-on: https://review.coreboot.org/20794
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
This commit is contained in:
Patrick Rudolph 2017-07-27 18:00:59 +02:00 committed by Martin Roth
parent 24680d0902
commit db27e3384a
14 changed files with 216 additions and 131 deletions

View File

@ -27,15 +27,3 @@ config DIGITIZER_ABSENT
endchoice endchoice
endif 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.

View File

@ -1,2 +1 @@
ramstage-$(CONFIG_DRIVERS_LENOVO_WACOM) += wacom.c ramstage-$(CONFIG_DRIVERS_LENOVO_WACOM) += wacom.c
ramstage-$(CONFIG_DRIVERS_LENOVO_HYBRID_GRAPHICS) += hybrid_graphics.c

View File

@ -1,114 +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,
};

View File

@ -22,6 +22,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy
select MAINBOARD_HAS_LPC_TPM select MAINBOARD_HAS_LPC_TPM
select MAINBOARD_HAS_LIBGFXINIT select MAINBOARD_HAS_LIBGFXINIT
select GFX_GMA_INTERNAL_IS_LVDS select GFX_GMA_INTERNAL_IS_LVDS
select DRIVERS_LENOVO_HYBRID_GRAPHICS
# Workaround for EC/KBC IRQ1. # Workaround for EC/KBC IRQ1.
select SERIRQ_CONTINUOUS_MODE select SERIRQ_CONTINUOUS_MODE

View File

@ -162,6 +162,20 @@ chip northbridge/intel/sandybridge
register "eventd_enable" = "0xff" register "eventd_enable" = "0xff"
register "evente_enable" = "0x0d" register "evente_enable" = "0x0d"
end 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 end # LPC Controller
device pci 1f.2 on device pci 1f.2 on
subsystemid 0x17aa 0x21ce subsystemid 0x17aa 0x21ce

View File

@ -18,6 +18,33 @@
#include <arch/io.h> #include <arch/io.h>
#include <northbridge/intel/sandybridge/raminit_native.h> #include <northbridge/intel/sandybridge/raminit_native.h>
#include <southbridge/intel/bd82x6x/pch.h> #include <southbridge/intel/bd82x6x/pch.h>
#include <drivers/lenovo/hybrid_graphics/hybrid_graphics.h>
#include <northbridge/intel/sandybridge/sandybridge.h>
#include <device/device.h>
#include <device/pci.h>
static void hybrid_graphics_init(void)
{
bool peg, igd;
u32 reg32;
early_hybrid_graphics(&igd, &peg);
/* 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) void pch_enable_lpc(void)
{ {
@ -65,6 +92,7 @@ void mainboard_get_spd(spd_raw_data *spd, bool id_only)
void mainboard_early_init(int s3resume) void mainboard_early_init(int s3resume)
{ {
hybrid_graphics_init();
} }
void mainboard_config_superio(void) void mainboard_config_superio(void)

View File

@ -154,6 +154,20 @@ chip northbridge/intel/sandybridge
register "eventd_enable" = "0xff" register "eventd_enable" = "0xff"
register "evente_enable" = "0x0d" register "evente_enable" = "0x0d"
end 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 end # LPC Controller
device pci 1f.2 on device pci 1f.2 on
subsystemid 0x17aa 0x21d2 subsystemid 0x17aa 0x21d2

View File

@ -17,10 +17,36 @@
#include <arch/byteorder.h> #include <arch/byteorder.h>
#include <arch/io.h> #include <arch/io.h>
#include <device/pci_def.h>
#include <console/console.h> #include <console/console.h>
#include <northbridge/intel/sandybridge/raminit_native.h> #include <northbridge/intel/sandybridge/raminit_native.h>
#include <southbridge/intel/bd82x6x/pch.h> #include <southbridge/intel/bd82x6x/pch.h>
#include <drivers/lenovo/hybrid_graphics/hybrid_graphics.h>
#include <northbridge/intel/sandybridge/sandybridge.h>
#include <device/device.h>
#include <device/pci.h>
static void hybrid_graphics_init(void)
{
bool peg, igd;
u32 reg32;
early_hybrid_graphics(&igd, &peg);
/* 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) void pch_enable_lpc(void)
{ {
@ -65,7 +91,9 @@ void mainboard_get_spd(spd_raw_data *spd, bool id_only) {
read_spd(&spd[2], 0x51, id_only); read_spd(&spd[2], 0x51, id_only);
} }
void mainboard_early_init(int s3resume) { void mainboard_early_init(int s3resume)
{
hybrid_graphics_init();
} }
void mainboard_config_superio(void) void mainboard_config_superio(void)

View File

@ -150,6 +150,20 @@ chip northbridge/intel/sandybridge
register "eventd_enable" = "0xff" register "eventd_enable" = "0xff"
register "evente_enable" = "0x0d" register "evente_enable" = "0x0d"
end 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" = "0"
end
end end
device pci 1f.2 on # SATA Controller 1 device pci 1f.2 on # SATA Controller 1
subsystemid 0x17aa 0x21f3 subsystemid 0x17aa 0x21f3

View File

@ -18,6 +18,33 @@
#include <northbridge/intel/sandybridge/raminit_native.h> #include <northbridge/intel/sandybridge/raminit_native.h>
#include <southbridge/intel/bd82x6x/pch.h> #include <southbridge/intel/bd82x6x/pch.h>
#include <ec/lenovo/pmh7/pmh7.h> #include <ec/lenovo/pmh7/pmh7.h>
#include <drivers/lenovo/hybrid_graphics/hybrid_graphics.h>
#include <northbridge/intel/sandybridge/sandybridge.h>
#include <device/device.h>
#include <device/pci.h>
static void hybrid_graphics_init(void)
{
bool peg, igd;
u32 reg32;
early_hybrid_graphics(&igd, &peg);
/* 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) void pch_enable_lpc(void)
{ {
@ -57,6 +84,7 @@ const struct southbridge_usb_port mainboard_usb_ports[] = {
void mainboard_early_init(int s3resume) void mainboard_early_init(int s3resume)
{ {
hybrid_graphics_init();
} }
void mainboard_config_superio(void) void mainboard_config_superio(void)

View File

@ -133,6 +133,20 @@ chip northbridge/intel/sandybridge
register "eventd_enable" = "0xff" register "eventd_enable" = "0xff"
register "evente_enable" = "0x0d" register "evente_enable" = "0x0d"
end 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 bridge end # LPC bridge
device pci 1f.2 on end # SATA Controller 1 device pci 1f.2 on end # SATA Controller 1
device pci 1f.3 on # SMBUS controller device pci 1f.3 on # SMBUS controller

View File

@ -35,6 +35,32 @@
#include <arch/cpu.h> #include <arch/cpu.h>
#include <cpu/x86/msr.h> #include <cpu/x86/msr.h>
#include <cbfs.h> #include <cbfs.h>
#include <drivers/lenovo/hybrid_graphics/hybrid_graphics.h>
#include <device/device.h>
#include <device/pci.h>
static void hybrid_graphics_init(void)
{
bool peg, igd;
u32 reg32;
early_hybrid_graphics(&igd, &peg);
/* 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) void pch_enable_lpc(void)
{ {
@ -79,7 +105,9 @@ void mainboard_get_spd(spd_raw_data *spd, bool id_only) {
read_spd (&spd[2], 0x51, id_only); read_spd (&spd[2], 0x51, id_only);
} }
void mainboard_early_init(int s3resume) { void mainboard_early_init(int s3resume)
{
hybrid_graphics_init();
} }
void mainboard_config_superio(void) void mainboard_config_superio(void)

View File

@ -140,6 +140,20 @@ chip northbridge/intel/sandybridge
register "eventd_enable" = "0xff" register "eventd_enable" = "0xff"
register "evente_enable" = "0x0d" register "evente_enable" = "0x0d"
end 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" = "0"
end
end # LPC bridge end # LPC bridge
device pci 1f.2 on end # SATA Controller 1 device pci 1f.2 on end # SATA Controller 1
device pci 1f.3 on device pci 1f.3 on

View File

@ -22,6 +22,33 @@
#include <console/console.h> #include <console/console.h>
#include <northbridge/intel/sandybridge/raminit_native.h> #include <northbridge/intel/sandybridge/raminit_native.h>
#include <southbridge/intel/bd82x6x/pch.h> #include <southbridge/intel/bd82x6x/pch.h>
#include <northbridge/intel/sandybridge/sandybridge.h>
#include <drivers/lenovo/hybrid_graphics/hybrid_graphics.h>
#include <device/device.h>
#include <device/pci.h>
static void hybrid_graphics_init(void)
{
bool peg, igd;
u32 reg32;
early_hybrid_graphics(&igd, &peg);
/* 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) void pch_enable_lpc(void)
{ {
@ -66,7 +93,9 @@ void mainboard_get_spd(spd_raw_data *spd, bool id_only) {
read_spd (&spd[2], 0x51, id_only); read_spd (&spd[2], 0x51, id_only);
} }
void mainboard_early_init(int s3resume) { void mainboard_early_init(int s3resume)
{
hybrid_graphics_init();
} }
void mainboard_config_superio(void) void mainboard_config_superio(void)