nb/intel/gm45: Export EDID-reading routine as a function

It will cache decoded EDID string in a static array. If called more
than once, a pointer to the static array is directly returned, without
reading EDID again.

Signed-off-by: Bill XIE <persmule@hardenedlinux.org>
Change-Id: Ibdbe4d76f9b59e7ae83b60cda042c2d1c39827ca
Reviewed-on: https://review.coreboot.org/c/coreboot/+/74180
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
diff --git a/src/northbridge/intel/gm45/gm45.h b/src/northbridge/intel/gm45/gm45.h
index f28c6d1..c85a16c 100644
--- a/src/northbridge/intel/gm45/gm45.h
+++ b/src/northbridge/intel/gm45/gm45.h
@@ -447,6 +447,9 @@
 u16 get_blc_pwm_freq_value(const char *edid_ascii_string);
 
 #include <device/device.h>
+#include <edid.h>
+
+const char *gm45_get_lvds_edid_str(struct device *dev);
 
 struct acpi_rsdp;
 unsigned long northbridge_write_acpi_tables(const struct device *device, unsigned long start,
diff --git a/src/northbridge/intel/gm45/gma.c b/src/northbridge/intel/gm45/gma.c
index 8043822..6759e74 100644
--- a/src/northbridge/intel/gm45/gma.c
+++ b/src/northbridge/intel/gm45/gma.c
@@ -143,16 +143,46 @@
 								reg8));
 }
 
-static void gma_func0_init(struct device *dev)
+const char *gm45_get_lvds_edid_str(struct device *dev)
 {
 	u8 *mmio;
 	u8 edid_data_lvds[128];
 	struct edid edid_lvds;
+	static char edid_str[EDID_ASCII_STRING_LENGTH + 1];
+
+	if (edid_str[0])
+		return edid_str;
+	if (!gtt_res)
+		gtt_res = probe_resource(dev, PCI_BASE_ADDRESS_0);
+	if (!gtt_res)
+		return NULL;
+	mmio = res2mmio(gtt_res, 0, 0);
+
+	printk(BIOS_DEBUG, "LVDS EDID\n");
+	intel_gmbus_read_edid(mmio + GMBUS0, GMBUS_PORT_PANEL, 0x50,
+			edid_data_lvds, sizeof(edid_data_lvds));
+	intel_gmbus_stop(mmio + GMBUS0);
+
+	if (decode_edid(edid_data_lvds, sizeof(edid_data_lvds), &edid_lvds)
+	    != EDID_CONFORMANT)
+		return NULL;
+	memcpy(edid_str, edid_lvds.ascii_string, sizeof(edid_str));
+	return edid_str;
+}
+
+static void gma_func0_init(struct device *dev)
+{
+	u8 *mmio;
 	const struct northbridge_intel_gm45_config *const conf = dev->chip_info;
+	const char *edid_str;
 
 	intel_gma_init_igd_opregion();
 
-	gtt_res = probe_resource(dev, PCI_BASE_ADDRESS_0);
+	edid_str = gm45_get_lvds_edid_str(dev);
+	if (!edid_str)
+		printk(BIOS_ERR, "Failed to obtain LVDS EDID string!\n");
+
+	/* gtt_res should have been inited in gm45_get_lvds_edid_str() */
 	if (!gtt_res)
 		return;
 	mmio = res2mmio(gtt_res, 0, 0);
@@ -173,14 +203,8 @@
 		pci_dev_init(dev);
 	}
 
-	printk(BIOS_DEBUG, "LVDS EDID\n");
-	intel_gmbus_read_edid(mmio + GMBUS0, GMBUS_PORT_PANEL, 0x50,
-			edid_data_lvds, sizeof(edid_data_lvds));
-	intel_gmbus_stop(mmio + GMBUS0);
-	decode_edid(edid_data_lvds, sizeof(edid_data_lvds), &edid_lvds);
-
 	/* Post VBIOS init */
-	gma_pm_init_post_vbios(dev, edid_lvds.ascii_string);
+	gma_pm_init_post_vbios(dev, edid_str);
 
 	if (CONFIG(MAINBOARD_USE_LIBGFXINIT) && !acpi_is_wakeup_s3()) {
 		int vga_disable = (pci_read_config16(dev, D0F0_GGC) & 2) >> 1;