[PATCH 1/1] UBUNTU: SAUCE: don't use buggy _BCL/_BCM/_BQC for backlight control
Andy Whitcroft
apw at canonical.com
Wed Jan 7 14:14:38 UTC 2009
OriginalAuthor: Zhang Rui <rui.zhang at intel.com>
Bug: #311716
[This patch is currently in the acpi-test tree, it is reported to fix
brightness inversion regressions by our tester. We expect this to be
merged and superceeded by an upstream commit.]
Some BIOSes export buggy _BCL/_BCM/_BQC methods.
Don't use them for backlight control
Signed-off-by: Zhang Rui <rui.zhang at intel.com>
Signed-off-by: Andy Whitcroft <apw at canonical.com>
---
drivers/acpi/video_detect.c | 83 +++++++++++++++++++++++++++++++++++++++---
1 files changed, 77 insertions(+), 6 deletions(-)
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index 70b1e91..9bf4865 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -45,17 +45,88 @@ static long acpi_video_support;
static bool acpi_video_caps_checked;
static acpi_status
+acpi_backlight_validate_bcl(acpi_handle handle)
+{
+ union acpi_object *obj, *obj2;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ int level_ac = 0, level_battery = 0;
+ int i, count;
+ int *levels;
+ acpi_status status;
+
+
+ status = acpi_evaluate_object(handle, "_BCL", NULL, &buffer);
+ if (!ACPI_SUCCESS(status))
+ return status;
+ obj = (union acpi_object *)buffer.pointer;
+ if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
+ printk(KERN_ERR PREFIX "Invalid _BCL data\n");
+ status = AE_BAD_DATA;
+ goto out;
+ }
+
+ if (obj->package.count < 2) {
+ status = AE_BAD_DATA;
+ goto out;
+ }
+
+ levels = kzalloc(obj->package.count * sizeof(*levels), GFP_KERNEL);
+ if (!levels) {
+ status = AE_NO_MEMORY;
+ goto out;
+ }
+
+ for (i = 0, count = 0; i < obj->package.count; i++) {
+ obj2 = (union acpi_object *)&obj->package.elements[i];
+ if (obj2->type != ACPI_TYPE_INTEGER) {
+ printk(KERN_ERR PREFIX "Invalid data\n");
+ continue;
+ }
+ levels[i] = (u32) obj2->integer.value;
+ count ++;
+ }
+
+ if (count < 2) {
+ status = AE_BAD_DATA;
+ goto out_free_levels;
+ }
+
+ for (i = 2, level_ac = levels[0], level_battery = levels[1]; i < count; i ++) {
+ if (levels[0] == levels[i])
+ level_ac = 1;
+ if (levels[1] == levels[i])
+ level_battery = 1;
+ }
+
+ if (!level_ac || !level_battery) {
+ printk(KERN_ERR PREFIX "Invalid _BCL package\n");
+ status = AE_BAD_DATA;
+ goto out_free_levels;
+ }
+
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "found %d brightness levels\n", count));
+
+out_free_levels:
+ kfree(levels);
+out:
+ kfree(obj);
+ return status;
+}
+
+static acpi_status
acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context,
void **retyurn_value)
{
long *cap = context;
- acpi_handle h_dummy;
+ acpi_handle h_dummy1, h_dummy2;
- if (ACPI_SUCCESS(acpi_get_handle(handle, "_BCM", &h_dummy)) &&
- ACPI_SUCCESS(acpi_get_handle(handle, "_BCL", &h_dummy))) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found generic backlight "
- "support\n"));
- *cap |= ACPI_VIDEO_BACKLIGHT;
+ if (ACPI_SUCCESS(acpi_get_handle(handle, "_BCM", &h_dummy1)) &&
+ ACPI_SUCCESS(acpi_get_handle(handle, "_BCL", &h_dummy2))) {
+ if (ACPI_SUCCESS(acpi_backlight_validate_bcl(h_dummy2))) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found generic backlight "
+ "support\n"));
+ *cap |= ACPI_VIDEO_BACKLIGHT;
+ }
/* We have backlight support, no need to scan further */
return AE_CTRL_TERMINATE;
}
--
1.6.0.4.911.gc990
More information about the kernel-team
mailing list