diff mbox

[04/94] ACPI: video: Fix reversed brightness behavior on ThinkPad SL series

Message ID 935e5f290ec1eb0f1c15004421f5fd3154380fd5.1231492607.git.len.brown@intel.com (mailing list archive)
State Accepted, archived
Headers show

Commit Message

Len Brown Jan. 9, 2009, 9:26 a.m. UTC
From: Zhang Rui <rui.zhang@intel.com>

Section B.6.2 of ACPI 3.0b specification that defines _BCL method
doesn't require the brightness levels returned to be sorted.
At least ThinkPad SL300 (and probably all IdeaPads) returns the
array reversed (i.e. bightest levels have lowest indexes), which
causes the brightness management behave in completely reversed
manner on these machines (brightness increases when the laptop is
idle, while the display dims when used).

Sorting the array by brightness level values after reading the list
fixes the issue.

http://bugzilla.kernel.org/show_bug.cgi?id=12037

Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Tested-by: Lubomir Rintel <lkundrak@v3.sk>
Signed-off-by: Len Brown <len.brown@intel.com>
---
 drivers/acpi/video.c |   15 +++++++++++++++
 1 files changed, 15 insertions(+), 0 deletions(-)
diff mbox

Patch

diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index baa4419..38bf8b4 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -36,6 +36,7 @@ 
 #include <linux/backlight.h>
 #include <linux/thermal.h>
 #include <linux/video_output.h>
+#include <linux/sort.h>
 #include <asm/uaccess.h>
 
 #include <acpi/acpi_bus.h>
@@ -626,6 +627,16 @@  acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag)
 }
 
 /*
+ * Simple comparison function used to sort backlight levels.
+ */
+
+static int
+acpi_video_cmp_level(const void *a, const void *b)
+{
+	return *(int *)a - *(int *)b;
+}
+
+/*
  *  Arg:	
  *  	device	: video output device (LCD, CRT, ..)
  *
@@ -676,6 +687,10 @@  acpi_video_init_brightness(struct acpi_video_device *device)
 		count++;
 	}
 
+	/* don't sort the first two brightness levels */
+	sort(&br->levels[2], count - 2, sizeof(br->levels[2]),
+		acpi_video_cmp_level, NULL);
+
 	if (count < 2)
 		goto out_free_levels;