From 82d185307ef39c0ee9a95806a2f21679479721b4 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sun, 5 Apr 2015 18:10:09 -0500 Subject: [PATCH 1/9] mainboard/lenovo/t400: Add initial hybrid graphics support TEST: Booted T400 with Intel/ATI hybrid graphics in integrated mode with native Intel graphics init and verified integrated panel framebuffer functionality in SeaBIOS and Linux. Change-Id: I37e72c5dad0d7ab3915cc3d439ae9a4a9b3787e3 Signed-off-by: Timothy Pearson --- src/mainboard/lenovo/t400/cmos.default | 1 + src/mainboard/lenovo/t400/cmos.layout | 8 +- src/mainboard/lenovo/t400/romstage.c | 143 +++++++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+), 1 deletion(-) diff --git a/src/mainboard/lenovo/t400/cmos.default b/src/mainboard/lenovo/t400/cmos.default index 67b8920..06eec57 100644 --- a/src/mainboard/lenovo/t400/cmos.default +++ b/src/mainboard/lenovo/t400/cmos.default @@ -14,3 +14,4 @@ sticky_fn=Disable power_management_beeps=Enable low_battery_beep=Enable sata_mode=AHCI +hybrid_graphics_mode=Integrated Only \ No newline at end of file diff --git a/src/mainboard/lenovo/t400/cmos.layout b/src/mainboard/lenovo/t400/cmos.layout index 2dc91bf..44f5d04 100644 --- a/src/mainboard/lenovo/t400/cmos.layout +++ b/src/mainboard/lenovo/t400/cmos.layout @@ -85,7 +85,10 @@ entries # coreboot config options: northbridge 941 3 e 11 gfx_uma_size -#944 2 r 0 unused +# coreboot config options: graphics +944 2 e 12 hybrid_graphics_mode + +#946 2 r 0 unused # coreboot config options: check sums 984 16 h 0 check_sum @@ -137,6 +140,9 @@ enumerations 11 3 128M 11 5 96M 11 6 160M +12 0 Integrated Only +12 1 Discrete Only +12 2 Switchable # ----------------------------------------------------------------- checksums diff --git a/src/mainboard/lenovo/t400/romstage.c b/src/mainboard/lenovo/t400/romstage.c index a739d18..c62df60 100644 --- a/src/mainboard/lenovo/t400/romstage.c +++ b/src/mainboard/lenovo/t400/romstage.c @@ -1,6 +1,7 @@ /* * This file is part of the coreboot project. * + * Copyright (C) 2015 Timothy Pearson , Raptor Engineering * Copyright (C) 2012 secunet Security Networks AG * * This program is free software; you can redistribute it and/or @@ -37,6 +38,118 @@ #define LPC_DEV PCI_DEV(0, 0x1f, 0) #define MCH_DEV PCI_DEV(0, 0, 0) +#define HYBRID_GRAPHICS_INTEGRATED_ONLY 0 +#define HYBRID_GRAPHICS_DISCRETE_ONLY 1 +#define HYBRID_GRAPHICS_SWITCHABLE 2 + +#define HYBRID_GRAPHICS_GP_LVL_BITS 0x004a0000 +#define HYBRID_GRAPHICS_GP_LVL2_BITS 0x00020000 + +#define HYBRID_GRAPHICS_DETECT_GP_BITS 0x00000010 + +#define HYBRID_GRAPHICS_INT_CLAIM_VGA 0x2 +#define HYBRID_GRAPHICS_SEC_VGA_EN 0x2 + +static void hybrid_graphics_configure_switchable_graphics(bool enable) +{ + uint32_t tmp; + + if (enable) { + /* Disable integrated graphics legacy VGA cycles */ + tmp = pci_read_config16(MCH_DEV, D0F0_GGC); + pci_write_config16(MCH_DEV, D0F0_GGC, tmp | HYBRID_GRAPHICS_INT_CLAIM_VGA); + + /* Enable secondary VGA controller */ + tmp = pci_read_config16(MCH_DEV, D0F0_DEVEN); + pci_write_config16(MCH_DEV, D0F0_DEVEN, tmp | HYBRID_GRAPHICS_SEC_VGA_EN); + } + else { + /* Enable integrated graphics legacy VGA cycles */ + tmp = pci_read_config16(MCH_DEV, D0F0_GGC); + pci_write_config16(MCH_DEV, D0F0_GGC, tmp & ~HYBRID_GRAPHICS_INT_CLAIM_VGA); + + /* Disable secondary VGA controller */ + tmp = pci_read_config16(MCH_DEV, D0F0_DEVEN); + pci_write_config16(MCH_DEV, D0F0_DEVEN, tmp & ~HYBRID_GRAPHICS_SEC_VGA_EN); + } +} + +static void hybrid_graphics_set_up_gpio(void) +{ + uint32_t tmp; + + /* Enable hybrid graphics GPIO lines */ + tmp = inl(DEFAULT_GPIOBASE + GP_IO_USE_SEL); + tmp = tmp | HYBRID_GRAPHICS_GP_LVL_BITS; + outl(tmp, DEFAULT_GPIOBASE + GP_IO_USE_SEL); + + tmp = inl(DEFAULT_GPIOBASE + GP_IO_USE_SEL2); + tmp = tmp | HYBRID_GRAPHICS_GP_LVL2_BITS; + outl(tmp, DEFAULT_GPIOBASE + GP_IO_USE_SEL2); + + /* Set hybrid graphics control GPIO lines to output */ + tmp = inl(DEFAULT_GPIOBASE + GP_IO_SEL); + tmp = tmp & ~HYBRID_GRAPHICS_GP_LVL_BITS; + outl(tmp, DEFAULT_GPIOBASE + GP_IO_SEL); + + tmp = inl(DEFAULT_GPIOBASE + GP_IO_SEL2); + tmp = tmp & ~HYBRID_GRAPHICS_GP_LVL2_BITS; + outl(tmp, DEFAULT_GPIOBASE + GP_IO_SEL2); + + /* Set hybrid graphics detect GPIO lines to input */ + tmp = inl(DEFAULT_GPIOBASE + GP_IO_SEL); + tmp = tmp | HYBRID_GRAPHICS_DETECT_GP_BITS; + outl(tmp, DEFAULT_GPIOBASE + GP_IO_SEL); +} + +static bool hybrid_graphics_installed(void) +{ + if (inl(DEFAULT_GPIOBASE + GP_LVL) & HYBRID_GRAPHICS_DETECT_GP_BITS) + return false; + else + return true; +} + +static void hybrid_graphics_switch_to_integrated_graphics(void) +{ + uint32_t tmp; + + /* Disable switchable graphics */ + hybrid_graphics_configure_switchable_graphics(false); + + /* Configure muxes */ + tmp = inl(DEFAULT_GPIOBASE + GP_LVL); + tmp = tmp & ~HYBRID_GRAPHICS_GP_LVL_BITS; + outl(tmp, DEFAULT_GPIOBASE + GP_LVL); + + tmp = inl(DEFAULT_GPIOBASE + GP_LVL2); + tmp = tmp & ~HYBRID_GRAPHICS_GP_LVL2_BITS; + outl(tmp, DEFAULT_GPIOBASE + GP_LVL2); +} + +static void hybrid_graphics_switch_to_discrete_graphics(void) +{ + uint32_t tmp; + + /* Disable switchable graphics */ + hybrid_graphics_configure_switchable_graphics(false); + + /* Configure muxes */ + tmp = inl(DEFAULT_GPIOBASE + GP_LVL); + tmp = tmp | HYBRID_GRAPHICS_GP_LVL_BITS; + outl(tmp, DEFAULT_GPIOBASE + GP_LVL); + + tmp = inl(DEFAULT_GPIOBASE + GP_LVL2); + tmp = tmp | HYBRID_GRAPHICS_GP_LVL2_BITS; + outl(tmp, DEFAULT_GPIOBASE + GP_LVL2); +} + +static void hybrid_graphics_switch_to_dual_graphics(void) +{ + /* Enable switchable graphics */ + hybrid_graphics_configure_switchable_graphics(true); +} + static void default_southbridge_gpio_setup(void) { outl(0x197e23fe, DEFAULT_GPIOBASE + GP_IO_USE_SEL); @@ -98,6 +211,31 @@ void main(unsigned long bist) default_southbridge_gpio_setup(); + uint8_t hybrid_graphics_mode = HYBRID_GRAPHICS_INTEGRATED_ONLY; + get_option(&hybrid_graphics_mode, "hybrid_graphics_mode"); + + /* Set up hybrid graphics */ + hybrid_graphics_set_up_gpio(); + if (hybrid_graphics_installed()) { + /* Select appropriate hybrid graphics device */ + printk(BIOS_DEBUG, "Hybrid graphics available, setting mode %d\n", hybrid_graphics_mode); + if (hybrid_graphics_mode == HYBRID_GRAPHICS_INTEGRATED_ONLY) + hybrid_graphics_switch_to_integrated_graphics(); + else if (hybrid_graphics_mode == HYBRID_GRAPHICS_DISCRETE_ONLY) + hybrid_graphics_switch_to_discrete_graphics(); + else if (hybrid_graphics_mode == HYBRID_GRAPHICS_SWITCHABLE) + hybrid_graphics_switch_to_integrated_graphics(); + /* Switchable graphics are fully enabled after raminit */ + /* FIXME + * Enabling switchable graphics prevents bootup! + * Debug and fix appropriately... + */ + } + else { + printk(BIOS_DEBUG, "Hybrid graphics not installed\n"); + hybrid_graphics_switch_to_integrated_graphics(); + } + /* ASPM related setting, set early by original BIOS. */ DMIBAR16(0x204) &= ~(3 << 10); @@ -177,6 +315,11 @@ void main(unsigned long bist) outl(inl(DEFAULT_GPIOBASE + 0x38) & ~0x400, DEFAULT_GPIOBASE + 0x38); cbmem_initted = !cbmem_recovery(s3resume); + + if (hybrid_graphics_installed()) + if (hybrid_graphics_mode == HYBRID_GRAPHICS_SWITCHABLE) + hybrid_graphics_switch_to_dual_graphics(); + #if CONFIG_HAVE_ACPI_RESUME /* If there is no high memory area, we didn't boot before, so * this is not a resume. In that case we just create the cbmem toc. -- 1.9.1