From b45dde0b78cbe646e12316408ac67cdc72ed9a9d Mon Sep 17 00:00:00 2001 From: robbie zhang Date: Thu, 1 Oct 2015 17:21:33 -0700 Subject: intel/skylake: Add support for Gfx PEIM (AKA GOP) This patch implements the igd_opregion using the write_acpi_tables mechanism to support GOP usage. BRANCH=none BUG=chrome-os-partner:44559 TEST=W/o GOP_SUPPORT in config, Built and boot on kunimitsu/glados. W/ GOP_SUPPORT enabled, build and boot on kunimitsu/glados, but on glados Dev screen can not be seen (OS display is fine). CQ-DEPEND=CL:303539 Change-Id: I4cd63dfe0d3f456c5f084e38db976425143f79e7 Signed-off-by: Patrick Georgi Original-Commit-Id: 4db57463a69c6114b1e2ed4035d378ee3a82783f Original-Change-Id: I6f3c29c1b608eeaad8f2bf79d17394d49f8e412c Original-Signed-off-by: robbie zhang Original-Reviewed-on: https://chromium-review.googlesource.com/303387 Original-Commit-Ready: Robbie Zhang Original-Tested-by: Robbie Zhang Original-Reviewed-by: Aaron Durbin Reviewed-on: http://review.coreboot.org/12142 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi --- src/soc/intel/skylake/acpi.c | 20 ++------ src/soc/intel/skylake/igd.c | 86 ++++++++++++++++++++++++++++++++ src/soc/intel/skylake/include/soc/acpi.h | 2 + 3 files changed, 92 insertions(+), 16 deletions(-) (limited to 'src/soc') diff --git a/src/soc/intel/skylake/acpi.c b/src/soc/intel/skylake/acpi.c index 471fd17981..4b9440a068 100644 --- a/src/soc/intel/skylake/acpi.c +++ b/src/soc/intel/skylake/acpi.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -29,14 +30,10 @@ #include #include #include -#include -#include -#include #include #include #include #include -#include #include #include #include @@ -45,6 +42,9 @@ #include #include #include +#include +#include +#include /* * List of suported C-states in this processor. @@ -541,8 +541,6 @@ unsigned long acpi_madt_irq_overrides(unsigned long current) return current; } -#define ALIGN_CURRENT current = (ALIGN(current, 16)) - unsigned long southcluster_write_acpi_tables(device_t device, unsigned long current, struct acpi_rsdp *rsdp) @@ -552,16 +550,6 @@ unsigned long southcluster_write_acpi_tables(device_t device, current = acpi_write_hpet(device, current, rsdp); ALIGN_CURRENT; -#if CONFIG_GOP_SUPPORT - igd_opregion_t *opregion; - - printk(BIOS_DEBUG, "ACPI: * IGD OpRegion\n"); - opregion = (igd_opregion_t *)current; - init_igd_opregion(opregion); - current += sizeof(igd_opregion_t); - ALIGN_CURRENT; -#endif - ssdt2 = (acpi_header_t *)current; memset(ssdt2, 0, sizeof(acpi_header_t)); if (ssdt2->length) { diff --git a/src/soc/intel/skylake/igd.c b/src/soc/intel/skylake/igd.c index 5422217351..d105fc9b9f 100644 --- a/src/soc/intel/skylake/igd.c +++ b/src/soc/intel/skylake/igd.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include #include @@ -64,6 +66,9 @@ static inline void gtt_rmw(u32 reg, u32 andmask, u32 ormask) static void igd_init(struct device *dev) { + if (IS_ENABLED(CONFIG_GOP_SUPPORT)) + return; + /* IGD needs to be Bus Master */ u32 reg32 = pci_read_config32(dev, PCI_COMMAND); reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO; @@ -102,12 +107,93 @@ static void igd_init(struct device *dev) #endif } +/* Initialize IGD OpRegion, called from ACPI code */ +static int init_igd_opregion(igd_opregion_t *opregion) +{ + const optionrom_vbt_t *vbt; + uint32_t vbt_len; + u16 reg16; + + memset(opregion, 0, sizeof(igd_opregion_t)); + + /* Read VBT table from flash */ + vbt = fsp_get_vbt(&vbt_len); + if (!vbt) + die("vbt data not found"); + + memcpy(&opregion->header.signature, IGD_OPREGION_SIGNATURE, + sizeof(IGD_OPREGION_SIGNATURE)); + memcpy(opregion->header.vbios_version, vbt->coreblock_biosbuild, sizeof(u32)); + memcpy(opregion->vbt.gvd1, vbt, vbt->hdr_vbt_size < + sizeof(opregion->vbt.gvd1) ? vbt->hdr_vbt_size : + sizeof(opregion->vbt.gvd1)); + + /* Size, in KB, of the entire OpRegion structure (including header)*/ + opregion->header.size = sizeof(igd_opregion_t) / KiB; + opregion->header.version = IGD_OPREGION_VERSION; + + /* We just assume we're mobile for now */ + opregion->header.mailboxes = MAILBOXES_MOBILE; + + /* TODO Initialize Mailbox 1 */ + + /* Initialize Mailbox 3 */ + opregion->mailbox3.bclp = IGD_BACKLIGHT_BRIGHTNESS; + opregion->mailbox3.pfit = IGD_FIELD_VALID | IGD_PFIT_STRETCH; + opregion->mailbox3.pcft = 0; /* should be (IMON << 1) & 0x3e */ + opregion->mailbox3.cblv = IGD_FIELD_VALID | IGD_INITIAL_BRIGHTNESS; + opregion->mailbox3.bclm[0] = IGD_WORD_FIELD_VALID + 0x0000; + opregion->mailbox3.bclm[1] = IGD_WORD_FIELD_VALID + 0x0a19; + opregion->mailbox3.bclm[2] = IGD_WORD_FIELD_VALID + 0x1433; + opregion->mailbox3.bclm[3] = IGD_WORD_FIELD_VALID + 0x1e4c; + opregion->mailbox3.bclm[4] = IGD_WORD_FIELD_VALID + 0x2866; + opregion->mailbox3.bclm[5] = IGD_WORD_FIELD_VALID + 0x327f; + opregion->mailbox3.bclm[6] = IGD_WORD_FIELD_VALID + 0x3c99; + opregion->mailbox3.bclm[7] = IGD_WORD_FIELD_VALID + 0x46b2; + opregion->mailbox3.bclm[8] = IGD_WORD_FIELD_VALID + 0x50cc; + opregion->mailbox3.bclm[9] = IGD_WORD_FIELD_VALID + 0x5ae5; + opregion->mailbox3.bclm[10] = IGD_WORD_FIELD_VALID + 0x64ff; + + /* TODO This may need to happen in S3 resume */ + pci_write_config32(SA_DEV_IGD, ASLS, (u32)opregion); + reg16 = pci_read_config16(SA_DEV_IGD, SWSCI); + reg16 &= ~GSSCIE; + reg16 |= SMISCISEL; + pci_write_config16(SA_DEV_IGD, SWSCI, reg16); + + return 0; +} + +static unsigned long write_acpi_igd_opregion(device_t device, + unsigned long current, struct acpi_rsdp *rsdp) +{ + igd_opregion_t *opregion; + + /* If GOP is not used, exit here */ + if (!IS_ENABLED(CONFIG_GOP_SUPPORT)) + return current; + + /* If IGD is disabled, exit here */ + if (pci_read_config16(device, PCI_VENDOR_ID) == 0xFFFF) + return current; + + printk(BIOS_DEBUG, "ACPI: * IGD OpRegion\n"); + opregion = (igd_opregion_t *)current; + init_igd_opregion(opregion); + current += sizeof(igd_opregion_t); + ALIGN_CURRENT; + + printk(BIOS_DEBUG, "current = %lx\n", current); + return current; +} + static struct device_operations igd_ops = { .read_resources = &pci_dev_read_resources, .set_resources = &pci_dev_set_resources, .enable_resources = &pci_dev_enable_resources, .init = &igd_init, .ops_pci = &soc_pci_ops, + .write_acpi_tables = write_acpi_igd_opregion, }; static const unsigned short pci_device_ids[] = { diff --git a/src/soc/intel/skylake/include/soc/acpi.h b/src/soc/intel/skylake/include/soc/acpi.h index 7418fe0be5..7e9a3dba88 100644 --- a/src/soc/intel/skylake/include/soc/acpi.h +++ b/src/soc/intel/skylake/include/soc/acpi.h @@ -30,6 +30,8 @@ #define PSS_LATENCY_TRANSITION 10 #define PSS_LATENCY_BUSMASTER 10 +#define ALIGN_CURRENT current = (ALIGN(current, 16)) + void acpi_fill_in_fadt(acpi_fadt_t *fadt); unsigned long acpi_madt_irq_overrides(unsigned long current); void acpi_mainboard_gnvs(global_nvs_t *gnvs); -- cgit v1.2.3