drivers/intel/gma: Support IGD Opregion 2.1

List of changes:
1. Define new configs for Opregion versions.
2. Assign RVDA to relative address of the Opregion buffer
   in case of opregion 2.1+.

BUG=b:190019970
BRANCH=None

Signed-off-by: Meera Ravindranath <meera.ravindranath@intel.com>
Change-Id: I95a9f3df185002a4e38faa910f867ace0b97ac2b
Reviewed-on: https://review.coreboot.org/c/coreboot/+/52758
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
diff --git a/src/drivers/intel/gma/opregion.c b/src/drivers/intel/gma/opregion.c
index 1385092..430bda3 100644
--- a/src/drivers/intel/gma/opregion.c
+++ b/src/drivers/intel/gma/opregion.c
@@ -258,6 +258,9 @@
 /* Function to get the IGD Opregion version */
 static struct opregion_version opregion_get_version(void)
 {
+	if (CONFIG(INTEL_GMA_OPREGION_2_1))
+		return (struct opregion_version) { .major = 2, .minor = 1 };
+
 	return (struct opregion_version) { .major = 2, .minor = 0 };
 }
 
@@ -271,6 +274,15 @@
 	return (vbt->hdr_vbt_size > sizeof(opregion->vbt.gvd1));
 }
 
+/* Function to determine if the VBT uses a relative address */
+static inline bool uses_relative_vbt_addr(opregion_header_t *header)
+{
+	if (header->opver.major > 2)
+		return true;
+
+	return header->opver.major >= 2 && header->opver.minor >= 1;
+}
+
 /*
  * Copy extended VBT at the end of opregion and fill rvda and rvds
  * values correctly for the opregion.
@@ -278,11 +290,19 @@
 static void opregion_add_ext_vbt(igd_opregion_t *opregion, uint8_t *ext_vbt,
 				optionrom_vbt_t *vbt)
 {
+
+	opregion_header_t *header = &opregion->header;
 	/* Copy VBT into extended VBT region (at offset 8 KiB) */
 	memcpy(ext_vbt, vbt, vbt->hdr_vbt_size);
 
-	/* Fill RVDA value with address of physical pointer */
-	opregion->mailbox3.rvda = (uintptr_t)ext_vbt;
+	/* Fill RVDA value with relative address of the opregion buffer in case of
+	IGD Opregion version 2.1+ and physical address otherwise */
+
+	if (uses_relative_vbt_addr(header))
+		opregion->mailbox3.rvda = sizeof(*opregion);
+	else
+		opregion->mailbox3.rvda = (uintptr_t)ext_vbt;
+
 	opregion->mailbox3.rvds = vbt->hdr_vbt_size;
 }
 
@@ -327,6 +347,10 @@
 		sizeof(opregion->header.signature));
 	memcpy(opregion->header.vbios_version, vbt->coreblock_biosbuild,
 					ARRAY_SIZE(vbt->coreblock_biosbuild));
+
+	/* Get the opregion version information */
+	opregion->header.opver = opregion_get_version();
+
 	/* Extended VBT support */
 	if (is_ext_vbt_required(opregion, vbt)) {
 		/* Place extended VBT just after opregion */
@@ -339,9 +363,6 @@
 
 	rdev_munmap(&rdev, vbt);
 
-	/* Get the opregion version information */
-	opregion->header.opver = opregion_get_version();
-
 	/* 8kb */
 	opregion->header.size = sizeof(igd_opregion_t) / 1024;