From 1b12750315eadd93ca6a70fc8235e46306ba1aca Mon Sep 17 00:00:00 2001
From: Kamal Mostafa <kamal@canonical.com>
Date: Fri, 7 May 2010 11:35:01 -0700
Subject: [PATCH 1/2] acpi: video: acpi_set_backlight_register() hook

=== PRELIMINARY VERSION - NEEDS WORK ===
Add new backlight control override hook acpi_set_backlight_register()
to allow other drivers (e.g. i915) to override the _BCM/_BCL/_BQC
DSDT backlight control method.
---
 drivers/acpi/video.c |   37 ++++++++++++++++++++++++++++++++++++-
 include/acpi/video.h |    6 ++++++
 2 files changed, 42 insertions(+), 1 deletions(-)

diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index bd9843a..c6f8aeb 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -481,6 +481,18 @@ acpi_video_device_set_state(struct acpi_video_device *device, int state)
 	return status;
 }
 
+static u32 (*acpi_set_backlight_routine)(void *dev, u32 bclp);
+static void *acpi_set_backlight_dev;
+static u32 acpi_set_backlight_max;
+/* KAMAL TODO:
+
+- hook the backlight routine into:
+    acpi_video_init_brightness
+    acpi_video_device_lcd_query_levels somehow
+- divorce from _BCL, _BQC
+
+*/
+
 static int
 acpi_video_device_lcd_query_levels(struct acpi_video_device *device,
 				   union acpi_object **levels)
@@ -520,6 +532,14 @@ acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
 	struct acpi_object_list args = { 1, &arg0 };
 	int state;
 
+    if ( acpi_set_backlight_routine ) {
+
+	/* KAMAL TODO - fix this awful hack: move the 1<<31 to opregion code */
+	acpi_set_backlight_routine(acpi_set_backlight_dev,
+			(1<<31) | (level * acpi_set_backlight_max / 100));
+
+    } else {
+
 	arg0.integer.value = level;
 
 	status = acpi_evaluate_object(device->dev->handle, "_BCM",
@@ -529,6 +549,8 @@ acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
 		return -EIO;
 	}
 
+    }
+
 	device->brightness->curr = level;
 	for (state = 2; state < device->brightness->count; state++)
 		if (level == device->brightness->levels[state]) {
@@ -984,7 +1006,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
 		device->cap._DSS = 1;
 	}
 
-	if (acpi_video_backlight_support()) {
+	if (acpi_set_backlight_routine || acpi_video_backlight_support()) {
 		int result;
 		static int count = 0;
 		char *name;
@@ -2418,6 +2440,19 @@ void acpi_video_unregister(void)
 }
 EXPORT_SYMBOL(acpi_video_unregister);
 
+void acpi_set_backlight_register(
+		u32 (*set_backlight_routine)(void *dev, u32 bclp),
+		void *dev, int max_brightness)
+{
+	printk(KERN_INFO PREFIX "~kamal TEST %s\n", __func__);
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "set_backlight_register in use for "
+					"LCD brightness level\n"));
+	acpi_set_backlight_routine = set_backlight_routine;
+	acpi_set_backlight_dev = dev;
+	acpi_set_backlight_max = max_brightness;
+}
+EXPORT_SYMBOL(acpi_set_backlight_register);
+
 /*
  * This is kind of nasty. Hardware using Intel chipsets may require
  * the video opregion code to be run first in order to initialise
diff --git a/include/acpi/video.h b/include/acpi/video.h
index cf7be3d..aef6d2c 100644
--- a/include/acpi/video.h
+++ b/include/acpi/video.h
@@ -2,9 +2,15 @@
 #define __ACPI_VIDEO_H
 
 #if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE)
+extern void acpi_set_backlight_register(
+		u32 (*set_backlight_routine)(void *dev, u32 bclp),
+		void *dev, int max_brightness);
 extern int acpi_video_register(void);
 extern void acpi_video_unregister(void);
 #else
+static inline acpi_set_backlight_register(
+		u32 (*set_backlight_routine)(void *dev, u32 bclp),
+		void *dev, int max_brightness) { return; }
 static inline int acpi_video_register(void) { return 0; }
 static inline void acpi_video_unregister(void) { return; }
 #endif
-- 
1.7.0.4


