Disable _BQC once it returns an invalid value. http://bugzilla.kernel.org/show_bug.cgi?id=13887 Signed-off-by: Zhang Rui --- drivers/acpi/video.c | 66 +++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 31 deletions(-) Index: linux-2.6/drivers/acpi/video.c =================================================================== --- linux-2.6.orig/drivers/acpi/video.c +++ linux-2.6/drivers/acpi/video.c @@ -603,37 +603,44 @@ acpi_video_device_lcd_get_level_current( unsigned long long *level) { acpi_status status = AE_OK; + int state; + char *buf; - if (device->cap._BQC || device->cap._BCQ) { - char *buf = device->cap._BQC ? "_BQC" : "_BCQ"; + *level = device->brightness->curr; + + if (!device->cap._BQC && !device->cap._BCQ) + return 0; - status = acpi_evaluate_integer(device->dev->handle, buf, - NULL, level); - if (ACPI_SUCCESS(status)) { - if (device->brightness->flags._BQC_use_index) { - if (device->brightness->flags._BCL_reversed) - *level = device->brightness->count - - 3 - (*level); - *level = device->brightness->levels[*level + 2]; + buf = device->cap._BQC ? "_BQC" : "_BCQ"; + status = acpi_evaluate_integer(device->dev->handle, buf, + NULL, level); + if (ACPI_SUCCESS(status)) { + if (device->brightness->flags._BQC_use_index) { + if (device->brightness->flags._BCL_reversed) + *level = device->brightness->count + - 3 - (*level); + *level = device->brightness->levels[*level + 2]; } - *level += bqc_offset_aml_bug_workaround; - device->brightness->curr = *level; - return 0; - } else { - /* Fixme: - * should we return an error or ignore this failure? - * dev->brightness->curr is a cached value which stores - * the correct current backlight level in most cases. - * ACPI video backlight still works w/ buggy _BQC. - * http://bugzilla.kernel.org/show_bug.cgi?id=12233 - */ - ACPI_WARNING((AE_INFO, "Evaluating %s failed", buf)); - device->cap._BQC = device->cap._BCQ = 0; - } - } + *level += bqc_offset_aml_bug_workaround; - *level = device->brightness->curr; + for (state = 2; state < device->brightness->count; state++) + if (level == device->brightness->levels[state]) { + device->brightness->curr = *level; + return 0; + } + } + /* Fixme: + * should we return an error or ignore this failure? + * dev->brightness->curr is a cached value which stores + * the correct current backlight level in most cases. + * ACPI video backlight still works w/ buggy _BQC. + * http://bugzilla.kernel.org/show_bug.cgi?id=12233 + * http://bugzilla.kernel.org/show_bug.cgi?id=13887 + */ + ACPI_WARNING((AE_INFO, "Evaluating %s %s, current brightness %d\n", + buf, ACPI_SUCCESS(status) ? "success" : "failed", *level)); + device->cap._BQC = device->cap._BCQ = 0; return 0; } @@ -1946,10 +1953,7 @@ static int acpi_video_switch_brightness(struct acpi_video_device *device, int event) { unsigned long long level_current, level_next; - int result = -EINVAL; - - if (!device->brightness) - goto out; + int result; result = acpi_video_device_lcd_get_level_current(device, &level_current); @@ -2124,7 +2128,7 @@ static void acpi_video_device_notify(acp struct input_dev *input; int keycode; - if (!video_device) + if (!video_device || !video_device->brightness) return; device = video_device->dev;