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>
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 9730ec1..ae42710 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -37,6 +37,8 @@
 #include <linux/thermal.h>
 #include <linux/video_output.h>
 #include <linux/sort.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
 #include <asm/uaccess.h>
 
 #include <acpi/acpi_bus.h>
@@ -2251,7 +2253,27 @@
 	return 0;
 }
 
-static int __init acpi_video_init(void)
+static int __init intel_opregion_present(void)
+{
+#if defined(CONFIG_DRM_I915) || defined(CONFIG_DRM_I915_MODULE)
+	struct pci_dev *dev = NULL;
+	u32 address;
+
+	for_each_pci_dev(dev) {
+		if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
+			continue;
+		if (dev->vendor != PCI_VENDOR_ID_INTEL)
+			continue;
+		pci_read_config_dword(dev, 0xfc, &address);
+		if (!address)
+			continue;
+		return 1;
+	}
+#endif
+	return 0;
+}
+
+int acpi_video_register(void)
 {
 	int result = 0;
 
@@ -2268,6 +2290,22 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(acpi_video_register);
+
+/*
+ * This is kind of nasty. Hardware using Intel chipsets may require
+ * the video opregion code to be run first in order to initialise
+ * state before any ACPI video calls are made. To handle this we defer
+ * registration of the video class until the opregion code has run.
+ */
+
+static int __init acpi_video_init(void)
+{
+	if (intel_opregion_present())
+		return 0;
+
+	return acpi_video_register();
+}
 
 static void __exit acpi_video_exit(void)
 {