summaryrefslogtreecommitdiffstats
path: root/src/drivers/lenovo/hybrid_graphics/romstage.c
diff options
context:
space:
mode:
authorPatrick Rudolph <siro@das-labor.org>2017-07-25 17:40:36 +0200
committerMartin Roth <martinroth@google.com>2017-08-10 16:05:56 +0000
commitd7dcc44eb97dcf99093e64b887b9dc2296a31d21 (patch)
tree77f6a0ea002cf32df5a5dc0f846d9949e3b28733 /src/drivers/lenovo/hybrid_graphics/romstage.c
parent0c67a66d23428151686ec25d046c4353dbdec91a (diff)
downloadcoreboot-d7dcc44eb97dcf99093e64b887b9dc2296a31d21.tar.gz
coreboot-d7dcc44eb97dcf99093e64b887b9dc2296a31d21.tar.bz2
coreboot-d7dcc44eb97dcf99093e64b887b9dc2296a31d21.zip
drvs/lenovo/hybrid_graphics: Add new hybrid graphics driver
Introduce a chip_driver that uses devicetree instead of Kconfig. The new driver has the following advantages: * No more wasted IGD GFX stolen memory * Can be used by T500 series * Is even run on devices that do not have a dGPU installed * Can disable unused PEG port on devices without dGPU (and save power) * Use devicetree instead of Kconfig options * Support for multiple hybrid GPIO active levels * Support for backlight control GPIO * Support for _ROM on Optimus capable devices The driver is split into romstage part and ramstage part. Every mainboard has to call the driver in romstage to get the requested GPU state. The mainboard code then has to toggle GPU power or disable the IGD or PEG port. The ramstage part does handle the hygrid graphics GPIO, including optional backlight mux GPIO. Every GPIO can have it's own active level, as defined in devicetree. Devices are no longer disabled in ramstage. The existing hybrid graphics driver does the same configuration and should not interfere with this commit until it has been removed. Change-Id: Ie467f9a18b35ab3b8a523dbf51c5575db5b374a5 Signed-off-by: Patrick Rudolph <siro@das-labor.org> Reviewed-on: https://review.coreboot.org/20792 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Nico Huber <nico.h@gmx.de> Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
Diffstat (limited to 'src/drivers/lenovo/hybrid_graphics/romstage.c')
-rw-r--r--src/drivers/lenovo/hybrid_graphics/romstage.c95
1 files changed, 95 insertions, 0 deletions
diff --git a/src/drivers/lenovo/hybrid_graphics/romstage.c b/src/drivers/lenovo/hybrid_graphics/romstage.c
new file mode 100644
index 000000000000..9009c5841a65
--- /dev/null
+++ b/src/drivers/lenovo/hybrid_graphics/romstage.c
@@ -0,0 +1,95 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2017 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.
+ */
+
+#include <types.h>
+#include <option.h>
+#include <device/device.h>
+
+#include <southbridge/intel/common/gpio.h>
+#include <ec/lenovo/pmh7/pmh7.h>
+#include <console/console.h>
+#include <delay.h>
+
+#include "hybrid_graphics.h"
+#include "chip.h"
+
+/*
+ * Returns the hybrid graphics presence and user's card preferences.
+ */
+void early_hybrid_graphics(bool *enable_igd, bool *enable_peg)
+{
+ const struct drivers_lenovo_hybrid_graphics_config *config;
+ const struct device *dev;
+ enum hybrid_graphics_req mode = HYBRID_GRAPHICS_DEFAULT_GPU;
+
+ /* TODO: Use generic device instead of dummy PNP device */
+ dev = dev_find_slot_pnp(HYBRID_GRAPHICS_PORT, HYBRID_GRAPHICS_DEVICE);
+
+ if (!dev || !dev->chip_info) {
+ printk(BIOS_ERR, "Hybrid graphics: ERROR\n");
+ *enable_igd = true;
+ *enable_peg = false;
+ return;
+ }
+
+ config = dev->chip_info;
+ if (get_gpio(config->detect_gpio) == DGPU_NOT_INSTALLED) {
+ printk(BIOS_DEBUG, "Hybrid graphics:"
+ " No discrete GPU present.\n");
+ *enable_igd = true;
+ *enable_peg = false;
+ return;
+ }
+
+ get_option(&mode, "hybrid_graphics_mode");
+
+ if (mode == HYBRID_GRAPHICS_DISCRETE) {
+ printk(BIOS_DEBUG, "Hybrid graphics:"
+ " Disabling integrated GPU.\n");
+
+ *enable_igd = false;
+ *enable_peg = true;
+ } else if (mode == HYBRID_GRAPHICS_INTEGRATED) {
+ printk(BIOS_DEBUG, "Hybrid graphics:"
+ " Disabling discrete GPU.\n");
+
+ *enable_igd = true;
+ *enable_peg = false;
+ } else {
+ printk(BIOS_DEBUG, "Hybrid graphics:"
+ " Activating Switchable (both GPUs).\n");
+
+ *enable_igd = true;
+ *enable_peg = true;
+ }
+
+ /*
+ * Need to do power handling here as we know there's a dGPU to
+ * turn off. Support GPIO and Thinker1.
+ */
+ if (!*enable_peg) {
+ if (config->has_dgpu_power_gpio) {
+ set_gpio(config->dgpu_power_gpio,
+ config->dgpu_power_off_lvl);
+ } else if (config->has_thinker1) {
+ pmh7_register_clear_bit(0x50, 7); // DGPU_RST
+ udelay(100);
+ pmh7_register_clear_bit(0x50, 3); // DGPU_PWR
+ } else {
+ printk(BIOS_ERR, "Hybrid graphics:"
+ " FIXME: dGPU power not disabled !\n");
+ }
+ }
+}