diff options
Diffstat (limited to 'src/drivers')
-rw-r--r-- | src/drivers/intel/gma/Makefile.inc | 1 | ||||
-rw-r--r-- | src/drivers/intel/gma/opregion.c | 105 | ||||
-rw-r--r-- | src/drivers/intel/gma/opregion.h | 1 |
3 files changed, 106 insertions, 1 deletions
diff --git a/src/drivers/intel/gma/Makefile.inc b/src/drivers/intel/gma/Makefile.inc index 50494e19de..940d15a038 100644 --- a/src/drivers/intel/gma/Makefile.inc +++ b/src/drivers/intel/gma/Makefile.inc @@ -21,7 +21,6 @@ endif ramstage-$(CONFIG_INTEL_GMA_ACPI) += acpi.c ramstage-$(CONFIG_INTEL_GMA_ACPI) += opregion.c - ifeq ($(CONFIG_MAINBOARD_USE_LIBGFXINIT),y) $(call add-special-class,gfxinit) diff --git a/src/drivers/intel/gma/opregion.c b/src/drivers/intel/gma/opregion.c index 721a5d8239..e9cbba13cc 100644 --- a/src/drivers/intel/gma/opregion.c +++ b/src/drivers/intel/gma/opregion.c @@ -14,12 +14,16 @@ * GNU General Public License for more details. */ +#include <arch/acpi.h> +#include <types.h> +#include <string.h> #include <device/device.h> #include <device/pci.h> #include <device/pci_ids.h> #include <device/pci_ops.h> #include <console/console.h> #include <cbmem.h> +#include "intel_bios.h" #include "opregion.h" /* Write ASLS PCI register and prepare SWSCI register. */ @@ -62,3 +66,104 @@ void intel_gma_restore_opregion(void) printk(BIOS_ERR, "Error: GNVS or ASLB not set.\n"); } } + +static void *get_intel_vbios(void) +{ + /* This should probably be looking at CBFS or we should always + * deploy the VBIOS on Intel systems, even if we don't run it + * in coreboot (e.g. SeaBIOS only scenarios). + */ + u8 *vbios = (u8 *)0xc0000; + + optionrom_header_t *oprom = (optionrom_header_t *)vbios; + optionrom_pcir_t *pcir = (optionrom_pcir_t *)(vbios + + oprom->pcir_offset); + + printk(BIOS_DEBUG, "GET_VBIOS: %x %x %x %x %x\n", + oprom->signature, pcir->vendor, pcir->classcode[0], + pcir->classcode[1], pcir->classcode[2]); + + + if ((oprom->signature == OPROM_SIGNATURE) && + (pcir->vendor == PCI_VENDOR_ID_INTEL) && + (pcir->classcode[0] == 0x00) && + (pcir->classcode[1] == 0x00) && + (pcir->classcode[2] == 0x03)) + return (void *)vbios; + + return NULL; +} + +static enum cb_err init_opregion_vbt(igd_opregion_t *opregion) +{ + void *vbios; + vbios = get_intel_vbios(); + if (!vbios) { + printk(BIOS_DEBUG, "VBIOS not found.\n"); + return CB_ERR; + } + + printk(BIOS_DEBUG, " ... VBIOS found at %p\n", vbios); + optionrom_header_t *oprom = (optionrom_header_t *)vbios; + optionrom_vbt_t *vbt = (optionrom_vbt_t *)(vbios + + oprom->vbt_offset); + + if (read32(vbt->hdr_signature) != VBT_SIGNATURE) { + printk(BIOS_DEBUG, "VBT not found!\n"); + return CB_ERR; + } + + memcpy(opregion->header.vbios_version, vbt->coreblock_biosbuild, 4); + memcpy(opregion->vbt.gvd1, vbt, vbt->hdr_vbt_size < 7168 ? + vbt->hdr_vbt_size : 7168); + + return CB_SUCCESS; +} + +/* Initialize IGD OpRegion, called from ACPI code and OS drivers */ +enum cb_err intel_gma_init_igd_opregion(igd_opregion_t *opregion) +{ + enum cb_err ret; + + memset((void *)opregion, 0, sizeof(igd_opregion_t)); + + // FIXME if IGD is disabled, we should exit here. + + memcpy(&opregion->header.signature, IGD_OPREGION_SIGNATURE, + sizeof(opregion->header.signature)); + + /* 8kb */ + opregion->header.size = sizeof(igd_opregion_t) / 1024; + opregion->header.version = IGD_OPREGION_VERSION; + + // FIXME We just assume we're mobile for now + opregion->header.mailboxes = MAILBOXES_MOBILE; + + // TODO Initialize Mailbox 1 + + // TODO 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; + + ret = init_opregion_vbt(opregion); + if (ret != CB_SUCCESS) + return ret; + + /* Write ASLS PCI register and prepare SWSCI register. */ + intel_gma_opregion_register((uintptr_t)opregion); + + return CB_SUCCESS; +} diff --git a/src/drivers/intel/gma/opregion.h b/src/drivers/intel/gma/opregion.h index 10c1691774..3ae68e527b 100644 --- a/src/drivers/intel/gma/opregion.h +++ b/src/drivers/intel/gma/opregion.h @@ -250,5 +250,6 @@ void intel_gma_opregion_register(uintptr_t opregion); void intel_gma_restore_opregion(void); uintptr_t gma_get_gnvs_aslb(const void *gnvs); void gma_set_gnvs_aslb(void *gnvs, uintptr_t aslb); +enum cb_err intel_gma_init_igd_opregion(igd_opregion_t *opregion); #endif /* _COMMON_GMA_H_ */ |