fd469c7
Bugzilla: 1093171
fd469c7
Upstream-status: Queued for 3.16
fd469c7
fd469c7
From 7f5b3e9378c0adfdb1cf2ffde6c4f890e05517c7 Mon Sep 17 00:00:00 2001
fd469c7
From: Hans de Goede <hdegoede@redhat.com>
fd469c7
Date: Mon, 2 Jun 2014 17:41:09 +0200
fd469c7
Subject: [PATCH 12/14] acpi-video: Unregister the backlight device if a raw
fd469c7
 one shows up later
fd469c7
fd469c7
When video.use_native_backlight=1 and non intel gfx are in use, the raw
fd469c7
backlight device of the gfx driver will show up after acpi-video has done its
fd469c7
acpi_video_verify_backlight_support() check.
fd469c7
fd469c7
This causes video.use_native_backlight=1 to not have the desired result.
fd469c7
fd469c7
This patch fixes this by adding a backlight notifier and when a raw
fd469c7
backlight is registered or unregistered re-doing the
fd469c7
acpi_video_verify_backlight_support() check.
fd469c7
fd469c7
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
fd469c7
---
fd469c7
 drivers/acpi/video.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++
fd469c7
 1 file changed, 57 insertions(+)
fd469c7
fd469c7
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
fd469c7
index d4d6ea3ac77a..ab7cd65ce21e 100644
fd469c7
--- a/drivers/acpi/video.c
fd469c7
+++ b/drivers/acpi/video.c
fd469c7
@@ -151,6 +151,7 @@ struct acpi_video_enumerated_device {
fd469c7
 struct acpi_video_bus {
fd469c7
 	struct acpi_device *device;
fd469c7
 	bool backlight_registered;
fd469c7
+	bool backlight_notifier_registered;
fd469c7
 	u8 dos_setting;
fd469c7
 	struct acpi_video_enumerated_device *attached_array;
fd469c7
 	u8 attached_count;
fd469c7
@@ -162,6 +163,7 @@ struct acpi_video_bus {
fd469c7
 	struct input_dev *input;
fd469c7
 	char phys[32];	/* for input device */
fd469c7
 	struct notifier_block pm_nb;
fd469c7
+	struct notifier_block backlight_nb;
fd469c7
 };
fd469c7
 
fd469c7
 struct acpi_video_device_flags {
fd469c7
@@ -1732,6 +1734,9 @@ static int acpi_video_bus_register_backlight(struct acpi_video_bus *video)
fd469c7
 {
fd469c7
 	struct acpi_video_device *dev;
fd469c7
 
fd469c7
+	if (video->backlight_registered)
fd469c7
+		return 0;
fd469c7
+
fd469c7
 	if (!acpi_video_verify_backlight_support())
fd469c7
 		return 0;
fd469c7
 
fd469c7
@@ -1876,6 +1881,56 @@ static void acpi_video_bus_remove_notify_handler(struct acpi_video_bus *video)
fd469c7
 	video->input = NULL;
fd469c7
 }
fd469c7
 
fd469c7
+static int acpi_video_backlight_notify(struct notifier_block *nb,
fd469c7
+					unsigned long val, void *bd)
fd469c7
+{
fd469c7
+	struct backlight_device *backlight = bd;
fd469c7
+	struct acpi_video_bus *video;
fd469c7
+
fd469c7
+	/* acpi_video_verify_backlight_support only cares about raw devices */
fd469c7
+	if (backlight->props.type != BACKLIGHT_RAW)
fd469c7
+		return NOTIFY_DONE;
fd469c7
+
fd469c7
+	video = container_of(nb, struct acpi_video_bus, backlight_nb);
fd469c7
+
fd469c7
+	switch (val) {
fd469c7
+	case BACKLIGHT_REGISTERED:
fd469c7
+		if (!acpi_video_verify_backlight_support())
fd469c7
+			acpi_video_bus_unregister_backlight(video);
fd469c7
+		break;
fd469c7
+	case BACKLIGHT_UNREGISTERED:
fd469c7
+		acpi_video_bus_register_backlight(video);
fd469c7
+		break;
fd469c7
+	}
fd469c7
+
fd469c7
+	return NOTIFY_OK;
fd469c7
+}
fd469c7
+
fd469c7
+static int acpi_video_bus_add_backlight_notify_handler(
fd469c7
+						struct acpi_video_bus *video)
fd469c7
+{
fd469c7
+	int error;
fd469c7
+
fd469c7
+	video->backlight_nb.notifier_call = acpi_video_backlight_notify;
fd469c7
+	video->backlight_nb.priority = 0;
fd469c7
+	error = backlight_register_notifier(&video->backlight_nb);
fd469c7
+	if (error == 0)
fd469c7
+		video->backlight_notifier_registered = true;
fd469c7
+
fd469c7
+	return error;
fd469c7
+}
fd469c7
+
fd469c7
+static int acpi_video_bus_remove_backlight_notify_handler(
fd469c7
+						struct acpi_video_bus *video)
fd469c7
+{
fd469c7
+	if (!video->backlight_notifier_registered)
fd469c7
+		return 0;
fd469c7
+
fd469c7
+	video->backlight_notifier_registered = false;
fd469c7
+
fd469c7
+	return backlight_unregister_notifier(&video->backlight_nb);
fd469c7
+}
fd469c7
+
fd469c7
 static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
fd469c7
 {
fd469c7
 	struct acpi_video_device *dev, *next;
fd469c7
@@ -1957,6 +2012,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
fd469c7
 
fd469c7
 	acpi_video_bus_register_backlight(video);
fd469c7
 	acpi_video_bus_add_notify_handler(video);
fd469c7
+	acpi_video_bus_add_backlight_notify_handler(video);
fd469c7
 
fd469c7
 	return 0;
fd469c7
 
fd469c7
@@ -1980,6 +2036,7 @@ static int acpi_video_bus_remove(struct acpi_device *device)
fd469c7
 
fd469c7
 	video = acpi_driver_data(device);
fd469c7
 
fd469c7
+	acpi_video_bus_remove_backlight_notify_handler(video);
fd469c7
 	acpi_video_bus_remove_notify_handler(video);
fd469c7
 	acpi_video_bus_unregister_backlight(video);
fd469c7
 	acpi_video_bus_put_devices(video);
fd469c7
-- 
fd469c7
1.9.0
fd469c7