diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_opregion.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_opregion.c | 38 |
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 @@ | |||
| 55 | struct opregion_header { | 55 | struct 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 | ||
