aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_opregion.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_opregion.c')
-rw-r--r--drivers/gpu/drm/i915/intel_opregion.c38
1 files changed, 33 insertions, 5 deletions
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index b8f106d9ecf8..3ac20153705a 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -55,7 +55,12 @@
55struct opregion_header { 55struct opregion_header {
56 u8 signature[16]; 56 u8 signature[16];
57 u32 size; 57 u32 size;
58 u32 opregion_ver; 58 struct {
59 u8 rsvd;
60 u8 revision;
61 u8 minor;
62 u8 major;
63 } __packed over;
59 u8 bios_ver[32]; 64 u8 bios_ver[32];
60 u8 vbios_ver[16]; 65 u8 vbios_ver[16];
61 u8 driver_ver[16]; 66 u8 driver_ver[16];
@@ -119,7 +124,8 @@ struct opregion_asle {
119 u64 fdss; 124 u64 fdss;
120 u32 fdsp; 125 u32 fdsp;
121 u32 stat; 126 u32 stat;
122 u64 rvda; /* Physical address of raw vbt data */ 127 u64 rvda; /* Physical (2.0) or relative from opregion (2.1+)
128 * address of raw VBT data. */
123 u32 rvds; /* Size of raw vbt data */ 129 u32 rvds; /* Size of raw vbt data */
124 u8 rsvd[58]; 130 u8 rsvd[58];
125} __packed; 131} __packed;
@@ -925,6 +931,11 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv)
925 opregion->header = base; 931 opregion->header = base;
926 opregion->lid_state = base + ACPI_CLID; 932 opregion->lid_state = base + ACPI_CLID;
927 933
934 DRM_DEBUG_DRIVER("ACPI OpRegion version %u.%u.%u\n",
935 opregion->header->over.major,
936 opregion->header->over.minor,
937 opregion->header->over.revision);
938
928 mboxes = opregion->header->mboxes; 939 mboxes = opregion->header->mboxes;
929 if (mboxes & MBOX_ACPI) { 940 if (mboxes & MBOX_ACPI) {
930 DRM_DEBUG_DRIVER("Public ACPI methods supported\n"); 941 DRM_DEBUG_DRIVER("Public ACPI methods supported\n");
@@ -953,11 +964,26 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv)
953 if (dmi_check_system(intel_no_opregion_vbt)) 964 if (dmi_check_system(intel_no_opregion_vbt))
954 goto out; 965 goto out;
955 966
956 if (opregion->header->opregion_ver >= 2 && opregion->asle && 967 if (opregion->header->over.major >= 2 && opregion->asle &&
957 opregion->asle->rvda && opregion->asle->rvds) { 968 opregion->asle->rvda && opregion->asle->rvds) {
958 opregion->rvda = memremap(opregion->asle->rvda, 969 resource_size_t rvda = opregion->asle->rvda;
959 opregion->asle->rvds, 970
971 /*
972 * opregion 2.0: rvda is the physical VBT address.
973 *
974 * opregion 2.1+: rvda is unsigned, relative offset from
975 * opregion base, and should never point within opregion.
976 */
977 if (opregion->header->over.major > 2 ||
978 opregion->header->over.minor >= 1) {
979 WARN_ON(rvda < OPREGION_SIZE);
980
981 rvda += asls;
982 }
983
984 opregion->rvda = memremap(rvda, opregion->asle->rvds,
960 MEMREMAP_WB); 985 MEMREMAP_WB);
986
961 vbt = opregion->rvda; 987 vbt = opregion->rvda;
962 vbt_size = opregion->asle->rvds; 988 vbt_size = opregion->asle->rvds;
963 if (intel_bios_is_valid_vbt(vbt, vbt_size)) { 989 if (intel_bios_is_valid_vbt(vbt, vbt_size)) {
@@ -967,6 +993,8 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv)
967 goto out; 993 goto out;
968 } else { 994 } else {
969 DRM_DEBUG_KMS("Invalid VBT in ACPI OpRegion (RVDA)\n"); 995 DRM_DEBUG_KMS("Invalid VBT in ACPI OpRegion (RVDA)\n");
996 memunmap(opregion->rvda);
997 opregion->rvda = NULL;
970 } 998 }
971 } 999 }
972 1000