===================================================================
@@ -43,8 +43,8 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
+#include <acpi/video.h>
-#define ACPI_VIDEO_CLASS "video"
#define ACPI_VIDEO_BUS_NAME "Video Bus"
#define ACPI_VIDEO_DEVICE_NAME "Video Device"
#define ACPI_VIDEO_NOTIFY_SWITCH 0x80
@@ -2260,7 +2260,16 @@
return 0;
}
-int acpi_video_register(void)
+/*
+ * 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.
+ * If there is no opregion is supported, it will continue the original
+ * flowchart. Register the ACPI video bus driver.
+ */
+
+static int __init acpi_video_init(void)
{
int result = 0;
@@ -2268,34 +2277,22 @@
if (!acpi_video_dir)
return -ENODEV;
+ if (intel_opregion_present()) {
+ acpi_video_register(&acpi_video_bus);
+ return 0;
+ }
result = acpi_bus_register_driver(&acpi_video_bus);
+
if (result < 0) {
remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
- return -ENODEV;
}
- 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();
+ return result;
}
static void __exit acpi_video_exit(void)
{
-
+ acpi_video_unregister(&acpi_video_bus);
acpi_bus_unregister_driver(&acpi_video_bus);
remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
===================================================================
@@ -36,13 +36,22 @@
#include <linux/acpi.h>
#include <linux/dmi.h>
+#include <acpi/video.h>
+#include <acpi/acpi_bus.h>
ACPI_MODULE_NAME("video");
#define _COMPONENT ACPI_VIDEO_COMPONENT
+#define I915_VIDEO_REGISTER 0x01
+#define ACPI_VIDEO_REGISTER 0x02
+#define VIDEO_REGISTER 0x03
static long acpi_video_support;
static bool acpi_video_caps_checked;
-
+struct video_register {
+ void *private_data;
+ unsigned int video_flags;
+};
+static struct video_register video_register_data;
static acpi_status
acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context,
void **retyurn_value)
@@ -63,7 +72,70 @@
}
return 0;
}
+static int video_register(void)
+{
+ int result = 0;
+
+ if (video_register_data.video_flags == VIDEO_REGISTER) {
+ /*
+ * When both flag bits are set, we will register the ACPI
+ * bus device driver.
+ */
+ struct acpi_driver *video_driver = (struct acpi_driver *)
+ video_register_data.private_data;
+
+ result = acpi_bus_register_driver(video_driver);
+ if (result < 0)
+ remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
+ }
+
+ return result;
+}
+/*
+ * After the I915 driver is loaded, this function will resume the
+ * deferrable flowchart of registering the ACPI video bus driver.
+ */
+int i915_video_register(void)
+{
+ int result = 0;
+
+ video_register_data.video_flags |= I915_VIDEO_REGISTER;
+ result = video_register();
+
+ return result;
+}
+EXPORT_SYMBOL(i915_video_register);
+int acpi_video_register(struct acpi_driver *video_driver)
+{
+ int result = 0;
+
+ if (!video_driver) {
+ /*
+ * the ACPI_VIDEO_REGISTER flag will be clear if NULL pointer
+ * is passed.
+ */
+ video_register_data.video_flags &= ~ACPI_VIDEO_REGISTER;
+ video_register_data.private_data = NULL;
+ return 1;
+ }
+
+ video_register_data.video_flags |= ACPI_VIDEO_REGISTER;
+ video_register_data.private_data = (void *)video_driver;
+
+ result = video_register();
+
+ return result;
+}
+EXPORT_SYMBOL(acpi_video_register);
+
+int acpi_video_unregister(struct acpi_driver *video_driver)
+{
+ video_register_data.video_flags &= ~ACPI_VIDEO_REGISTER;
+ video_register_data.private_data = NULL;
+ return 0;
+}
+EXPORT_SYMBOL(acpi_video_unregister);
/* Returns true if the device is a video device which can be handled by
* video.ko.
* The device will get a Linux specific CID added in scan.c to
===================================================================
@@ -1,10 +1,17 @@
#ifndef __ACPI_VIDEO_H
#define __ACPI_VIDEO_H
+#define ACPI_VIDEO_CLASS "video"
#if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE)
-extern int acpi_video_register(void);
+extern int acpi_video_register(struct acpi_driver *driver);
+extern int acpi_video_unregister(struct acpi_driver *driver);
+extern int i915_video_register(void);
#else
-static inline int acpi_video_register(void) { return 0; }
+static inline int acpi_video_register(struct acpi_driver *driver)
+ { return 0; }
+static inline int acpi_video_unregister(struct acpi_driver *driver)
+ { return 0; }
+static inline int i915_video_register(void) { return 0; }
#endif
#endif
===================================================================
@@ -373,7 +373,7 @@
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
intel_didl_outputs(dev);
if (!resume)
- acpi_video_register();
+ i915_video_register();
}
} else {
DRM_DEBUG("Public ACPI methods not supported\n");