Check the value returned by _BQC after each brightness change, and if it doesn't match the value written disable use of _BQC. This works around problems on some Lenovos when valid brightness values are ignored by _BCM. Signed-off-by: Seth Forshee <seth.forshee@xxxxxxxxxxxxx> --- drivers/acpi/video.c | 59 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index b83fbbd..6a19bf7 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -230,6 +230,8 @@ static int acpi_video_device_lcd_set_state(struct acpi_video_device *device, int state); static int acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level); +static int acpi_video_device_get_bqc_level(struct acpi_video_device *device, + unsigned long long *level); static int acpi_video_device_lcd_get_level_current( struct acpi_video_device *device, unsigned long long *level, int init); @@ -395,6 +397,20 @@ acpi_video_device_lcd_set_state(struct acpi_video_device *device, int state) result = -EIO; break; } + + if (device->cap._BQC || device->cap._BCQ) { + int bqc_result; + unsigned long long level; + bqc_result = acpi_video_device_get_bqc_level(device, + &level); + if (!bqc_result && + level != device->brightness->levels[curr_state]) { + printk(KERN_WARNING FW_BUG + "%s level does not match level set; disabling\n", + device->cap._BQC ? "_BQC" : "_BCQ"); + device->cap._BQC = device->cap._BCQ = 0; + } + } } while (curr_state != state); device->brightness->curr_state = curr_state; @@ -495,26 +511,36 @@ static struct dmi_system_id video_dmi_table[] __initdata = { }; static int +acpi_video_device_get_bqc_level(struct acpi_video_device *device, + unsigned long long *level) +{ + acpi_status status; + char *buf = device->cap._BQC ? "_BQC" : "_BCQ"; + + status = acpi_evaluate_integer(device->dev->handle, buf, NULL, level); + if (ACPI_FAILURE(status)) + return -EIO; + + 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; + return 0; +} + +static int acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, unsigned long long *level, int init) { - acpi_status status = AE_OK; + int result; int i; if (device->cap._BQC || device->cap._BCQ) { - char *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; + result = acpi_video_device_get_bqc_level(device, level); + if (!result) { for (i = 2; i < device->brightness->count; i++) if (device->brightness->levels[i] == *level) { device->brightness->curr_state = i; @@ -527,7 +553,7 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, */ ACPI_WARNING((AE_INFO, "%s returned an invalid level", - buf)); + device->cap._BQC ? "_BQC" : "_BCQ")); device->cap._BQC = device->cap._BCQ = 0; } } else { @@ -539,7 +565,8 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, * buggy _BQC. * http://bugzilla.kernel.org/show_bug.cgi?id=12233 */ - ACPI_WARNING((AE_INFO, "Evaluating %s failed", buf)); + ACPI_WARNING((AE_INFO, "Evaluating %s failed", + device->cap._BQC ? "_BQC" : "_BCQ")); device->cap._BQC = device->cap._BCQ = 0; } } -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html