]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
x86: apl: Support writing the IntelGraphicsMem table
authorSimon Glass <sjg@chromium.org>
Tue, 22 Sep 2020 18:45:03 +0000 (12:45 -0600)
committerBin Meng <bmeng.cn@gmail.com>
Fri, 25 Sep 2020 03:27:15 +0000 (11:27 +0800)
This table is needed by the Linux graphics driver to handle graphics
correctly. Write it to ACPI.

Signed-off-by: Simon Glass <sjg@chromium.org>
arch/x86/Kconfig
arch/x86/cpu/apollolake/Kconfig
arch/x86/cpu/intel_common/Makefile
arch/x86/cpu/intel_common/intel_opregion.c [new file with mode: 0644]
arch/x86/include/asm/intel_opregion.h [new file with mode: 0644]
arch/x86/lib/fsp/fsp_graphics.c
include/bloblist.h

index 680f26f1b8e7cfc34748da7b3cb4d42486f2e043..675a43e3b60330ba60a1545bc302a026b96e2df7 100644 (file)
@@ -1001,4 +1001,12 @@ config PCIEX_LENGTH_128MB
 config PCIEX_LENGTH_64MB
        bool
 
+config INTEL_GMA_ACPI
+       bool "Generate ACPI table for Intel GMA graphics"
+       help
+         The Intel GMA graphics driver in Linux expects an ACPI table
+         which describes the layout of the registers and the display
+         connected to the device. Enable this option to create this
+         table so that graphics works correctly.
+
 endmenu
index 16ac2b3f504ffb04f944cd64df12afbd4c00a108..319f12684b705d97cfb22d0e046fdacf7d84c7eb 100644 (file)
@@ -48,6 +48,7 @@ config INTEL_APOLLOLAKE
        imply CMD_CLK
        imply CLK_INTEL
        imply ACPI_GPE
+       imply INTEL_GMA_ACPI
 
 if INTEL_APOLLOLAKE
 
index 374803b87607d0a624dd4e6ec0c6542ac62537e0..207d5413965eb3e967b675bb4bbcbb784140e349 100644 (file)
@@ -9,6 +9,10 @@ obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += report_platform.o
 obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += mrc.o
 endif
 
+ifndef CONFIG_SPL_BUILD
+obj-$(CONFIG_INTEL_GMA_ACPI) += intel_opregion.o
+endif
+
 ifdef CONFIG_INTEL_CAR_CQOS
 obj-$(CONFIG_TPL_BUILD) += car2.o
 ifndef CONFIG_SPL_BUILD
diff --git a/arch/x86/cpu/intel_common/intel_opregion.c b/arch/x86/cpu/intel_common/intel_opregion.c
new file mode 100644 (file)
index 0000000..4e6c64d
--- /dev/null
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Writing IntelGraphicsMem table for ACPI
+ *
+ * Copyright 2019 Google LLC
+ * Modified from coreboot src/soc/intel/gma/opregion.c
+ */
+
+#include <common.h>
+#include <binman.h>
+#include <bloblist.h>
+#include <dm.h>
+#include <spi_flash.h>
+#include <asm/intel_opregion.h>
+
+static char vbt_data[8 << 10];
+
+static int locate_vbt(char **vbtp, int *sizep)
+{
+       struct binman_entry vbt;
+       struct udevice *dev;
+       u32 vbtsig = 0;
+       int size;
+       int ret;
+
+       ret = binman_entry_find("intel-vbt", &vbt);
+       if (ret)
+               return log_msg_ret("find VBT", ret);
+       ret = uclass_first_device_err(UCLASS_SPI_FLASH, &dev);
+       if (ret)
+               return log_msg_ret("find flash", ret);
+       size = vbt.size;
+       if (size > sizeof(vbt_data))
+               return log_msg_ret("vbt", -E2BIG);
+       ret = spi_flash_read_dm(dev, vbt.image_pos, size, vbt_data);
+       if (ret)
+               return log_msg_ret("read", ret);
+
+       memcpy(&vbtsig, vbt_data, sizeof(vbtsig));
+       if (vbtsig != VBT_SIGNATURE) {
+               log_err("Missing/invalid signature in VBT data file!\n");
+               return -EINVAL;
+       }
+
+       log_info("Found a VBT of %u bytes\n", size);
+       *sizep = size;
+       *vbtp = vbt_data;
+
+       return 0;
+}
+
+/* Write ASLS PCI register and prepare SWSCI register */
+static int intel_gma_opregion_register(struct udevice *dev, ulong opregion)
+{
+       int sci_reg;
+
+       if (!device_active(dev))
+               return -ENOENT;
+
+       /*
+        * Intel BIOS Specification
+        * Chapter 5.3.7 "Initialise Hardware State"
+        */
+       dm_pci_write_config32(dev, ASLS, opregion);
+
+       /*
+        * Atom-based platforms use a combined SMI/SCI register,
+        * whereas non-Atom platforms use a separate SCI register
+        */
+       if (IS_ENABLED(CONFIG_INTEL_GMA_SWSMISCI))
+               sci_reg = SWSMISCI;
+       else
+               sci_reg = SWSCI;
+
+       /*
+        * Intel's Windows driver relies on this:
+        * Intel BIOS Specification
+        * Chapter 5.4 "ASL Software SCI Handler"
+        */
+       dm_pci_clrset_config16(dev, sci_reg, GSSCIE, SMISCISEL);
+
+       return 0;
+}
+
+int intel_gma_init_igd_opregion(struct udevice *dev,
+                               struct igd_opregion *opregion)
+{
+       struct optionrom_vbt *vbt = NULL;
+       char *vbt_buf;
+       int vbt_size;
+       int ret;
+
+       ret = locate_vbt(&vbt_buf, &vbt_size);
+       if (ret) {
+               log_err("GMA: VBT couldn't be found\n");
+               return log_msg_ret("find vbt", ret);
+       }
+       vbt = (struct optionrom_vbt *)vbt_buf;
+
+       memset(opregion, '\0', sizeof(struct igd_opregion));
+
+       memcpy(&opregion->header.signature, IGD_OPREGION_SIGNATURE,
+              sizeof(opregion->header.signature));
+       memcpy(opregion->header.vbios_version, vbt->coreblock_biosbuild,
+              ARRAY_SIZE(vbt->coreblock_biosbuild));
+       /* Extended VBT support */
+       if (vbt->hdr_vbt_size > sizeof(opregion->vbt.gvd1)) {
+               struct optionrom_vbt *ext_vbt;
+
+               ret = bloblist_ensure_size(BLOBLISTT_INTEL_VBT,
+                                          vbt->hdr_vbt_size,
+                                          (void **)&ext_vbt);
+               if (ret) {
+                       log_err("GMA: Unable to add Ext VBT to bloblist\n");
+                       return log_msg_ret("blob", ret);
+               }
+
+               memcpy(ext_vbt, vbt, vbt->hdr_vbt_size);
+               opregion->mailbox3.rvda = (uintptr_t)ext_vbt;
+               opregion->mailbox3.rvds = vbt->hdr_vbt_size;
+       } else {
+               /* Raw VBT size which can fit in gvd1 */
+               printf("copy to %p\n", opregion->vbt.gvd1);
+               memcpy(opregion->vbt.gvd1, vbt, vbt->hdr_vbt_size);
+       }
+
+       /* 8kb */
+       opregion->header.size = sizeof(struct igd_opregion) / 1024;
+
+       /*
+        * Left-shift version field to accommodate Intel Windows driver quirk
+        * when not using a VBIOS.
+        * Required for Legacy boot + NGI, UEFI + NGI, and UEFI + GOP driver.
+        *
+        * No adverse effects when using VBIOS or booting Linux.
+        */
+       opregion->header.version = IGD_OPREGION_VERSION << 24;
+
+       /* We just assume we're mobile for now */
+       opregion->header.mailboxes = MAILBOXES_MOBILE;
+
+       /* Initialise Mailbox 1 */
+       opregion->mailbox1.clid = 1;
+
+       /* Initialise 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;
+
+       /* Write ASLS PCI register and prepare SWSCI register */
+       ret = intel_gma_opregion_register(dev, (ulong)opregion);
+       if (ret)
+               return log_msg_ret("write asls", ret);
+
+       return 0;
+}
diff --git a/arch/x86/include/asm/intel_opregion.h b/arch/x86/include/asm/intel_opregion.h
new file mode 100644 (file)
index 0000000..fb3e386
--- /dev/null
@@ -0,0 +1,247 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Writing IntelGraphicsMem table for ACPI
+ *
+ * Copyright 2019 Google LLC
+ * Modified from coreboot src/soc/intel/gma/opregion.h
+ */
+
+#ifndef _ASM_INTEL_OPREGION_H_
+#define _ASM_INTEL_OPREGION_H_
+
+#define VBT_SIGNATURE          0x54425624
+
+/* IGD PCI Configuration register */
+#define ASLS           0xfc            /* OpRegion Base */
+#define SWSCI          0xe8            /* SWSCI Register */
+#define SWSMISCI       0xe0            /* SWSMISCI Register */
+#define GSSCIE         BIT(0)          /* SCI Event trigger */
+#define SMISCISEL      BIT(15)         /* Select SMI or SCI event source */
+
+/* mailbox 0: header */
+struct __packed opregion_header {
+       u8      signature[16];      /* Offset 0    OpRegion signature */
+       u32     size;               /* Offset 16   OpRegion size */
+       u32     version;            /* Offset 20   OpRegion structure version */
+       u8      sbios_version[32];  /* Offset 24   System BIOS build version */
+       u8      vbios_version[16];  /* Offset 56   Video BIOS build version */
+       u8      driver_version[16]; /* Offset 72   Graphic drvr build version */
+       u32     mailboxes;          /* Offset 88   Mailboxes supported */
+       u32     dmod;               /* Offset 92   Driver Model */
+       u32     pcon;               /* Offset 96   Platform Capabilities */
+       u16     dver[16];           /* Offset 100  GOP Version */
+       u8      reserved[124];      /* Offset 132  Reserved */
+};
+
+#define IGD_OPREGION_SIGNATURE "IntelGraphicsMem"
+#define IGD_OPREGION_VERSION  2
+
+#define IGD_MBOX1      BIT(0)
+#define IGD_MBOX2      BIT(1)
+#define IGD_MBOX3      BIT(2)
+#define IGD_MBOX4      BIT(3)
+#define IGD_MBOX5      BIT(4)
+
+#define MAILBOXES_MOBILE  (IGD_MBOX1 | IGD_MBOX2 | IGD_MBOX3 | \
+                          IGD_MBOX4 | IGD_MBOX5)
+#define MAILBOXES_DESKTOP (IGD_MBOX2 | IGD_MBOX4)
+
+#define SBIOS_VERSION_SIZE 32
+
+/* mailbox 1: public ACPI methods */
+struct __packed opregion_mailbox1 {
+       u32     drdy;   /* Offset 0    Driver readiness */
+       u32     csts;   /* Offset 4    Status */
+       u32     cevt;   /* Offset 8    Current event */
+       u8      reserved[20];   /* Offset 12   Reserved */
+       u32     didl;   /* Offset 32   Supported display device 1 */
+       u32     ddl2;   /* Offset 36   Supported display device 2 */
+       u32     ddl3;   /* Offset 40   Supported display device 3 */
+       u32     ddl4;   /* Offset 44   Supported display device 4 */
+       u32     ddl5;   /* Offset 48   Supported display device 5 */
+       u32     ddl6;   /* Offset 52   Supported display device 6 */
+       u32     ddl7;   /* Offset 56   Supported display device 7 */
+       u32     ddl8;   /* Offset 60   Supported display device 8 */
+       u32     cpdl;   /* Offset 64   Currently present display device 1 */
+       u32     cpl2;   /* Offset 68   Currently present display device 2 */
+       u32     cpl3;   /* Offset 72   Currently present display device 3 */
+       u32     cpl4;   /* Offset 76   Currently present display device 4 */
+       u32     cpl5;   /* Offset 80   Currently present display device 5 */
+       u32     cpl6;   /* Offset 84   Currently present display device 6 */
+       u32     cpl7;   /* Offset 88   Currently present display device 7 */
+       u32     cpl8;   /* Offset 92   Currently present display device 8 */
+       u32     cadl;   /* Offset 96   Currently active display device 1 */
+       u32     cal2;   /* Offset 100  Currently active display device 2 */
+       u32     cal3;   /* Offset 104  Currently active display device 3 */
+       u32     cal4;   /* Offset 108  Currently active display device 4 */
+       u32     cal5;   /* Offset 112  Currently active display device 5 */
+       u32     cal6;   /* Offset 116  Currently active display device 6 */
+       u32     cal7;   /* Offset 120  Currently active display device 7 */
+       u32     cal8;   /* Offset 124  Currently active display device 8 */
+       u32     nadl;   /* Offset 128  Next active device 1 */
+       u32     ndl2;   /* Offset 132  Next active device 2 */
+       u32     ndl3;   /* Offset 136  Next active device 3 */
+       u32     ndl4;   /* Offset 140  Next active device 4 */
+       u32     ndl5;   /* Offset 144  Next active device 5 */
+       u32     ndl6;   /* Offset 148  Next active device 6 */
+       u32     ndl7;   /* Offset 152  Next active device 7 */
+       u32     ndl8;   /* Offset 156  Next active device 8 */
+       u32     aslp;   /* Offset 160  ASL sleep timeout */
+       u32     tidx;   /* Offset 164  Toggle table index */
+       u32     chpd;   /* Offset 168  Current hot plug enable indicator */
+       u32     clid;   /* Offset 172  Current lid state indicator */
+       u32     cdck;   /* Offset 176  Current docking state indicator */
+       u32     sxsw;   /* Offset 180  Display Switch notification on Sx State
+                        * resume
+                        */
+       u32     evts;   /* Offset 184  Events supported by ASL */
+       u32     cnot;   /* Offset 188  Current OS Notification */
+       u32     nrdy;   /* Offset 192  Reasons for DRDY = 0 */
+       u32     ddl9;   /* Offset 196  Extended Supported display device 1 */
+       u32     dd10;   /* Offset 200  Extended Supported display device 2 */
+       u32     dd11;   /* Offset 204  Extended Supported display device 3 */
+       u32     dd12;   /* Offset 208  Extended Supported display device 4 */
+       u32     dd13;   /* Offset 212  Extended Supported display device 5 */
+       u32     dd14;   /* Offset 216  Extended Supported display device 6 */
+       u32     dd15;   /* Offset 220  Extended Supported display device 7 */
+       u32     cpl9;   /* Offset 224  Extended Currently present device 1 */
+       u32     cp10;   /* Offset 228  Extended Currently present device 2 */
+       u32     cp11;   /* Offset 232  Extended Currently present device 3 */
+       u32     cp12;   /* Offset 236  Extended Currently present device 4 */
+       u32     cp13;   /* Offset 240  Extended Currently present device 5 */
+       u32     cp14;   /* Offset 244  Extended Currently present device 6 */
+       u32     cp15;   /* Offset 248  Extended Currently present device 7 */
+       u8      reserved2[4];   /* Offset 252  Reserved 4 bytes */
+};
+
+/* mailbox 2: software sci interface */
+struct __packed opregion_mailbox2 {
+       u32     scic;   /* Offset 0  Software SCI function number parameters */
+       u32     parm;   /* Offset 4  Software SCI function number parameters */
+       u32     dslp;   /* Offset 8  Driver sleep timeout */
+       u8      reserved[244];  /* Offset 12   Reserved */
+};
+
+/* mailbox 3: power conservation */
+struct __packed opregion_mailbox3 {
+       u32     ardy;           /* Offset 0   Driver readiness */
+       u32     aslc;           /* Offset 4   ASLE interrupt command / status */
+       u32     tche;           /* Offset 8   Technology enabled indicator */
+       u32     alsi;           /* Offset 12  Current ALS illuminance reading */
+       u32     bclp;           /* Offset 16  Backlight britness to set */
+       u32     pfit;           /* Offset 20  Panel fitting Request */
+       u32     cblv;           /* Offset 24  Brightness Current State */
+       /* Offset 28  Backlight Brightness Level Duty Cycle Mapping Table */
+       u16     bclm[20];
+       u32     cpfm;           /* Offset 68  Panel Fitting Current Mode */
+       u32     epfm;           /* Offset 72  Enabled Panel Fitting Modes */
+       u8      plut[74];       /* Offset 76  Panel Look Up Table */
+       /* Offset 150 PWM Frequency and Minimum Brightness */
+       u32     pfmb;
+       u32     ccdv;           /* Offset 154 Color Correction Default Values */
+       u32     pcft;           /* Offset 158 Power Conservation Features */
+       u32     srot;           /* Offset 162 Supported Rotation angle */
+       u32     iuer;           /* Offset 166 Intel Ultrabook Event Register */
+       u64     fdsp;           /* Offset 170 FFS Display Physical address */
+       u32     fdss;           /* Offset 178 FFS Display Size */
+       u32     stat;           /* Offset 182 State Indicator */
+       /*
+        * Offset 186 (Igd opregion offset 0x3BAh)
+        * Physical address of Raw VBT data
+        */
+       u64     rvda;
+       /* Offset 194 (Igd opregion offset 0x3C2h) Size of Raw VBT data */
+       u32     rvds;
+       u8      reserved[58];   /* Offset 198 Reserved */
+};
+
+#define IGD_BACKLIGHT_BRIGHTNESS 0xff
+#define IGD_INITIAL_BRIGHTNESS 0x64
+
+#define IGD_FIELD_VALID                BIT(31)
+#define IGD_WORD_FIELD_VALID   BIT(15)
+#define IGD_PFIT_STRETCH 6
+
+/* mailbox 4: vbt */
+struct __packed opregion_vbt {
+       u8 gvd1[6 << 10];
+};
+
+/* Mailbox 5: BIOS to Driver Notification Extension */
+struct __packed opregion_mailbox5 {
+       u32     phed;           /* Offset 7168 Panel Header */
+       u8      bddc[256];      /* Offset 7172 Panel EDID */
+       u8      reserved[764];  /* Offset 7428 764 bytes */
+};
+
+/* IGD OpRegion */
+struct __packed igd_opregion {
+       struct opregion_header header;
+       struct opregion_mailbox1 mailbox1;
+       struct opregion_mailbox2 mailbox2;
+       struct opregion_mailbox3 mailbox3;
+       struct opregion_vbt vbt;
+       struct opregion_mailbox5 mailbox5;
+};
+
+/* Intel Video BIOS (Option ROM) */
+struct __packed optionrom_header {
+       u16     signature;
+       u8      size;
+       u8      reserved[21];
+       u16     pcir_offset;
+       u16     vbt_offset;
+};
+
+#define OPROM_SIGNATURE 0xaa55
+
+struct __packed optionrom_pcir {
+       u32     signature;
+       u16     vendor;
+       u16     device;
+       u16     reserved1;
+       u16     length;
+       u8      revision;
+       u8      classcode[3];
+       u16     imagelength;
+       u16     coderevision;
+       u8      codetype;
+       u8      indicator;
+       u16     reserved2;
+};
+
+struct __packed optionrom_vbt {
+       u8      hdr_signature[20];
+       u16     hdr_version;
+       u16     hdr_size;
+       u16     hdr_vbt_size;
+       u8      hdr_vbt_checksum;
+       u8      hdr_reserved;
+       u32     hdr_vbt_datablock;
+       u32     hdr_aim[4];
+       u8      datahdr_signature[16];
+       u16     datahdr_version;
+       u16     datahdr_size;
+       u16     datahdr_datablocksize;
+       u8      coreblock_id;
+       u16     coreblock_size;
+       u16     coreblock_biossize;
+       u8      coreblock_biostype;
+       u8      coreblock_releasestatus;
+       u8      coreblock_hwsupported;
+       u8      coreblock_integratedhw;
+       u8      coreblock_biosbuild[4];
+       u8      coreblock_biossignon[155];
+};
+
+/**
+ * intel_gma_init_igd_opregion() - Initialise IGD OpRegion
+ *
+ * This is called from ACPI code and OS drivers
+ *
+ * @return 0 if OK, -ve on error
+ */
+int intel_gma_init_igd_opregion(struct udevice *dev,
+                               struct igd_opregion *opregion);
+
+#endif /* _ASM_INTEL_OPREGION_H_ */
index e8c1e07af1cb4d38e58f4621065c703cdd0b70f2..858d7942fed5fdf6610fb485a1ef6e704634abed 100644 (file)
@@ -3,14 +3,19 @@
  * Copyright (C) 2017, Bin Meng <bmeng.cn@gmail.com>
  */
 
+#define LOG_CATEGORY UCLASS_VIDEO
+
 #include <common.h>
 #include <dm.h>
 #include <init.h>
 #include <log.h>
 #include <vbe.h>
 #include <video.h>
+#include <acpi/acpi_table.h>
 #include <asm/fsp/fsp_support.h>
+#include <asm/intel_opregion.h>
 #include <asm/mtrr.h>
+#include <dm/acpi.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -127,6 +132,32 @@ static int fsp_video_bind(struct udevice *dev)
        return 0;
 }
 
+#ifdef CONFIG_INTEL_GMA_ACPI
+static int fsp_video_acpi_write_tables(const struct udevice *dev,
+                                      struct acpi_ctx *ctx)
+{
+       struct igd_opregion *opregion;
+       int ret;
+
+       printf("ACPI:    * IGD OpRegion\n");
+       opregion = (struct igd_opregion *)ctx->current;
+
+       ret = intel_gma_init_igd_opregion((struct udevice *)dev, opregion);
+       if (ret)
+               return ret;
+
+       acpi_inc_align(ctx, sizeof(struct igd_opregion));
+
+       return 0;
+}
+#endif
+
+struct acpi_ops fsp_video_acpi_ops = {
+#ifdef CONFIG_INTEL_GMA_ACPI
+       .write_tables   = fsp_video_acpi_write_tables,
+#endif
+};
+
 static const struct udevice_id fsp_video_ids[] = {
        { .compatible = "fsp-fb" },
        { }
@@ -139,6 +170,7 @@ U_BOOT_DRIVER(fsp_video) = {
        .bind   = fsp_video_bind,
        .probe  = fsp_video_probe,
        .flags  = DM_FLAG_PRE_RELOC,
+       ACPI_OPS_PTR(&fsp_video_acpi_ops)
 };
 
 static struct pci_device_id fsp_video_supported[] = {
index bbe0a35d5a2a4250d590a6cb3b5a3940cf0e2d7d..7d8480548e0214617f08c86c6f02bbbeb04cf134 100644 (file)
@@ -32,6 +32,7 @@ enum bloblist_tag_t {
         * Sleeping table. This forms part of the ACPI tables passed to Linux.
         */
        BLOBLISTT_ACPI_GNVS,
+       BLOBLISTT_INTEL_VBT,            /* Intel Video-BIOS table */
 };
 
 /**