aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/video.c
diff options
context:
space:
mode:
authorMatthew Garrett <mjg59@srcf.ucam.org>2009-03-19 17:35:39 -0400
committerLen Brown <len.brown@intel.com>2009-03-27 22:11:03 -0400
commit74a365b3f354fafc537efa5867deb7a9fadbfe27 (patch)
tree66ebff203807d2ed77e77e1ccc2f71f63e571098 /drivers/acpi/video.c
parentc60d638e29c780b75b648283a197d0226e3576c3 (diff)
ACPI: Populate DIDL before registering ACPI video device on Intel
Intel graphics hardware that implements the ACPI IGD OpRegion spec requires that the list of display devices be populated before any ACPI video methods are called. Detect when this is the case and defer registration until the opregion code calls it. Fixes crashes on HP laptops. http://bugzilla.kernel.org/show_bug.cgi?id=11259 Signed-off-by: Matthew Garrett <mjg@redhat.com> Acked-by: Eric Anholt <eric@anholt.net> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/video.c')
-rw-r--r--drivers/acpi/video.c40
1 files changed, 39 insertions, 1 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 9730ec167590..ae427100a1ef 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -37,6 +37,8 @@
37#include <linux/thermal.h> 37#include <linux/thermal.h>
38#include <linux/video_output.h> 38#include <linux/video_output.h>
39#include <linux/sort.h> 39#include <linux/sort.h>
40#include <linux/pci.h>
41#include <linux/pci_ids.h>
40#include <asm/uaccess.h> 42#include <asm/uaccess.h>
41 43
42#include <acpi/acpi_bus.h> 44#include <acpi/acpi_bus.h>
@@ -2251,7 +2253,27 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type)
2251 return 0; 2253 return 0;
2252} 2254}
2253 2255
2254static int __init acpi_video_init(void) 2256static int __init intel_opregion_present(void)
2257{
2258#if defined(CONFIG_DRM_I915) || defined(CONFIG_DRM_I915_MODULE)
2259 struct pci_dev *dev = NULL;
2260 u32 address;
2261
2262 for_each_pci_dev(dev) {
2263 if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
2264 continue;
2265 if (dev->vendor != PCI_VENDOR_ID_INTEL)
2266 continue;
2267 pci_read_config_dword(dev, 0xfc, &address);
2268 if (!address)
2269 continue;
2270 return 1;
2271 }
2272#endif
2273 return 0;
2274}
2275
2276int acpi_video_register(void)
2255{ 2277{
2256 int result = 0; 2278 int result = 0;
2257 2279
@@ -2268,6 +2290,22 @@ static int __init acpi_video_init(void)
2268 2290
2269 return 0; 2291 return 0;
2270} 2292}
2293EXPORT_SYMBOL(acpi_video_register);
2294
2295/*
2296 * This is kind of nasty. Hardware using Intel chipsets may require
2297 * the video opregion code to be run first in order to initialise
2298 * state before any ACPI video calls are made. To handle this we defer
2299 * registration of the video class until the opregion code has run.
2300 */
2301
2302static int __init acpi_video_init(void)
2303{
2304 if (intel_opregion_present())
2305 return 0;
2306
2307 return acpi_video_register();
2308}
2271 2309
2272static void __exit acpi_video_exit(void) 2310static void __exit acpi_video_exit(void)
2273{ 2311{