mb/prodrive/hermes: Allow using the Intel iGPU as primary

Configure the Intel iGPU as primary video adapter if enabled according
to EEPROM settings. The default is to use the ASPEED BMC as primary
video adapter, which only has a VGA output and the remote KVM output.

For now, use the FSP GOP driver to light up the iGPU. There are several
issues with libgfxinit on the Hermes, probably due to the unusual setup
of the iGPU's display outputs. They are routed to a mezzanine connector
for a piggy-back sub-board, of which there are two models. The Poseidon
piggy-back has two DisplayPort outputs and an HDMI output coming from a
MegaChips LSPCON. The Avalanche piggy-back routes all three DisplayPort
outputs from the iGPU into a FPGA, which acts as a DisplayPort sink.

Note that the FSP GOP only initializes at most 2 iGPU display outputs.
However, all three outputs function properly once OS (Windows, Linux)
graphics drivers take over.

Additionally, update the config file that Prodrive uses to build
coreboot images so that the iGPU can be used as primary.

TEST=Verify that the iGPU's outputs work properly in pre-OS, Windows and
     Linux, on both the Poseidon and Avalanche piggy-backs.

Change-Id: I24d9ebc2055dc246e7f257aa2f3853b22c8af370
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Signed-off-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/62649
Reviewed-by: Lean Sheng Tan <sheng.tan@9elements.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
diff --git a/configs/config.prodrive_hermes b/configs/config.prodrive_hermes
index ce8d687..62b856b 100644
--- a/configs/config.prodrive_hermes
+++ b/configs/config.prodrive_hermes
@@ -13,3 +13,4 @@
 CONFIG_MAINBOARD_SERIAL_NUMBER="N/A"
 CONFIG_PCIEXP_SUPPORT_RESIZABLE_BARS=y
 CONFIG_PCIEXP_DEFAULT_MAX_RESIZABLE_BAR_BITS=36
+CONFIG_RUN_FSP_GOP=y
diff --git a/src/mainboard/prodrive/hermes/eeprom.h b/src/mainboard/prodrive/hermes/eeprom.h
index 6befd8e..f02206f 100644
--- a/src/mainboard/prodrive/hermes/eeprom.h
+++ b/src/mainboard/prodrive/hermes/eeprom.h
@@ -65,6 +65,11 @@
 	};
 };
 
+enum {
+	PRIMARY_VIDEO_ASPEED = 0,
+	PRIMARY_VIDEO_INTEL  = 1,
+};
+
 _Static_assert(sizeof(struct eeprom_board_settings) == (12 + sizeof(uint32_t)),
 		"struct eeprom_board_settings has invalid size!");
 
diff --git a/src/mainboard/prodrive/hermes/mainboard.c b/src/mainboard/prodrive/hermes/mainboard.c
index 64494b1..b85186d 100644
--- a/src/mainboard/prodrive/hermes/mainboard.c
+++ b/src/mainboard/prodrive/hermes/mainboard.c
@@ -8,6 +8,7 @@
 #include <crc_byte.h>
 #include <device/device.h>
 #include <device/dram/spd.h>
+#include <device/pci_ids.h>
 #include <drivers/intel/gma/opregion.h>
 #include <gpio.h>
 #include <intelblocks/gpio.h>
@@ -302,3 +303,26 @@
 }
 
 BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_EXIT, mainboard_early, NULL);
+
+/*
+ * coreboot only exposes the last framebuffer that is set up.
+ * The ASPEED BMC will always be initialized after the IGD due to its higher
+ * bus number. To have coreboot only expose the IGD framebuffer skip the init
+ * function on the ASPEED.
+ */
+static void mainboard_configure_internal_gfx(void *unused)
+{
+	struct device *dev;
+	const struct eeprom_board_settings *board_cfg = get_board_settings();
+	if (!board_cfg)
+		return;
+
+	if (board_cfg->primary_video == PRIMARY_VIDEO_INTEL) {
+		dev = dev_find_device(PCI_VID_ASPEED, PCI_DID_ASPEED_AST2050_VGA, NULL);
+		dev->on_mainboard = false;
+		dev->enabled = false;
+		dev->ops->init = NULL;
+	}
+}
+
+BOOT_STATE_INIT_ENTRY(BS_DEV_RESOURCES, BS_ON_ENTRY, mainboard_configure_internal_gfx, NULL)
diff --git a/src/mainboard/prodrive/hermes/romstage.c b/src/mainboard/prodrive/hermes/romstage.c
index b52c52c..9853426 100644
--- a/src/mainboard/prodrive/hermes/romstage.c
+++ b/src/mainboard/prodrive/hermes/romstage.c
@@ -46,6 +46,11 @@
 	memupd->FspmTestConfig.SmbusSpdWriteDisable = 0;
 	cannonlake_memcfg_init(&memupd->FspmConfig, &baseboard_mem_cfg);
 
+	/* Tell FSP-M about the desired primary video adapter so that GGC is set up properly */
+	const struct eeprom_board_settings *board_cfg = get_board_settings();
+	if (board_cfg && board_cfg->primary_video == PRIMARY_VIDEO_INTEL)
+		memupd->FspmConfig.PrimaryDisplay = 0; /* iGPU is primary */
+
 	/* Overwrite memupd */
 	if (!check_signature(offsetof(struct eeprom_layout, mupd), FSPM_UPD_SIGNATURE))
 		return;