diff options
Diffstat (limited to 'drivers/acpi/video.c')
-rw-r--r-- | drivers/acpi/video.c | 174 |
1 files changed, 153 insertions, 21 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 350d52a8f78..8e7e18567ae 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -82,9 +82,9 @@ module_param(allow_duplicates, bool, 0644); * For Windows 8 systems: used to decide if video module * should skip registering backlight interface of its own. */ -static int use_native_backlight_param = 1; +static int use_native_backlight_param = -1; module_param_named(use_native_backlight, use_native_backlight_param, int, 0444); -static bool use_native_backlight_dmi = false; +static bool use_native_backlight_dmi = true; static int register_count; static struct mutex video_list_lock; @@ -204,6 +204,8 @@ struct acpi_video_device { struct acpi_video_device_flags flags; struct acpi_video_device_cap cap; struct list_head entry; + struct delayed_work switch_brightness_work; + int switch_brightness_event; struct acpi_video_bus *video; struct acpi_device *dev; struct acpi_video_device_brightness *brightness; @@ -230,8 +232,7 @@ static int acpi_video_device_lcd_get_level_current( unsigned long long *level, bool raw); static int acpi_video_get_next_level(struct acpi_video_device *device, u32 level_current, u32 event); -static int acpi_video_switch_brightness(struct acpi_video_device *device, - int event); +static void acpi_video_switch_brightness(struct work_struct *work); static bool acpi_video_use_native_backlight(void) { @@ -275,6 +276,7 @@ static int acpi_video_set_brightness(struct backlight_device *bd) int request_level = bd->props.brightness + 2; struct acpi_video_device *vd = bl_get_data(bd); + cancel_delayed_work(&vd->switch_brightness_work); return acpi_video_device_lcd_set_level(vd, vd->brightness->levels[request_level]); } @@ -415,6 +417,12 @@ static int __init video_set_use_native_backlight(const struct dmi_system_id *d) return 0; } +static int __init video_disable_native_backlight(const struct dmi_system_id *d) +{ + use_native_backlight_dmi = false; + return 0; +} + static struct dmi_system_id video_dmi_table[] __initdata = { /* * Broken _BQC workaround http://bugzilla.kernel.org/show_bug.cgi?id=13121 @@ -461,6 +469,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = { }, { .callback = video_set_use_native_backlight, + .ident = "ThinkPad X230", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"), + }, + }, + { + .callback = video_set_use_native_backlight, .ident = "ThinkPad T430 and T430s", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), @@ -469,10 +485,42 @@ static struct dmi_system_id video_dmi_table[] __initdata = { }, { .callback = video_set_use_native_backlight, - .ident = "ThinkPad X230", + .ident = "ThinkPad T430", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"), + DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "ThinkPad T431s", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "20AACTO1WW"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "ThinkPad Edge E530", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "3259A2G"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "ThinkPad Edge E530", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "3259CTO"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "ThinkPad Edge E530", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "3259HJG"), }, }, { @@ -572,6 +620,30 @@ static struct dmi_system_id video_dmi_table[] __initdata = { }, }, { + .callback = video_set_use_native_backlight, + .ident = "Acer Aspire V5-572G", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"), + DMI_MATCH(DMI_PRODUCT_VERSION, "V5-572G/Dazzle_CX"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "Acer Aspire V5-573G", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"), + DMI_MATCH(DMI_PRODUCT_VERSION, "V5-573G/Dazzle_HW"), + }, + }, + { + .callback = video_set_use_native_backlight, + .ident = "ASUS Zenbook Prime UX31A", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "UX31A"), + }, + }, + { .callback = video_set_use_native_backlight, .ident = "HP ProBook 4340s", .matches = { @@ -607,6 +679,15 @@ static struct dmi_system_id video_dmi_table[] __initdata = { }, { .callback = video_set_use_native_backlight, + .ident = "HP EliteBook 2014 models", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook "), + DMI_MATCH(DMI_PRODUCT_NAME, " G2"), + }, + }, + { + .callback = video_set_use_native_backlight, .ident = "HP ZBook 14", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), @@ -645,6 +726,49 @@ static struct dmi_system_id video_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 8780w"), }, }, + + /* + * These models have a working acpi_video backlight control, and using + * native backlight causes a regression where backlight does not work + * when userspace is not handling brightness key events. Disable + * native_backlight on these to fix this: + * https://bugzilla.kernel.org/show_bug.cgi?id=81691 + */ + { + .callback = video_disable_native_backlight, + .ident = "ThinkPad T420", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T420"), + }, + }, + { + .callback = video_disable_native_backlight, + .ident = "ThinkPad T520", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T520"), + }, + }, + { + .callback = video_disable_native_backlight, + .ident = "ThinkPad X201s", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201s"), + }, + }, + + /* The native backlight controls do not work on some older machines */ + { + /* https://bugs.freedesktop.org/show_bug.cgi?id=81515 */ + .callback = video_disable_native_backlight, + .ident = "HP ENVY 15 Notebook", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP ENVY 15 Notebook PC"), + }, + }, {} }; @@ -1188,6 +1312,8 @@ acpi_video_bus_get_one_device(struct acpi_device *device, data->device_id = device_id; data->video = video; data->dev = device; + INIT_DELAYED_WORK(&data->switch_brightness_work, + acpi_video_switch_brightness); attribute = acpi_video_get_device_attr(video, device_id); @@ -1410,15 +1536,18 @@ acpi_video_get_next_level(struct acpi_video_device *device, } } -static int -acpi_video_switch_brightness(struct acpi_video_device *device, int event) +static void +acpi_video_switch_brightness(struct work_struct *work) { + struct acpi_video_device *device = container_of(to_delayed_work(work), + struct acpi_video_device, switch_brightness_work); unsigned long long level_current, level_next; + int event = device->switch_brightness_event; int result = -EINVAL; /* no warning message if acpi_backlight=vendor or a quirk is used */ if (!acpi_video_verify_backlight_support()) - return 0; + return; if (!device->brightness) goto out; @@ -1440,8 +1569,6 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event) out: if (result) printk(KERN_ERR PREFIX "Failed to switch the brightness\n"); - - return result; } int acpi_video_get_edid(struct acpi_device *device, int type, int device_id, @@ -1609,6 +1736,16 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event) return; } +static void brightness_switch_event(struct acpi_video_device *video_device, + u32 event) +{ + if (!brightness_switch_enabled) + return; + + video_device->switch_brightness_event = event; + schedule_delayed_work(&video_device->switch_brightness_work, HZ / 10); +} + static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) { struct acpi_video_device *video_device = data; @@ -1626,28 +1763,23 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) switch (event) { case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */ - if (brightness_switch_enabled) - acpi_video_switch_brightness(video_device, event); + brightness_switch_event(video_device, event); keycode = KEY_BRIGHTNESS_CYCLE; break; case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */ - if (brightness_switch_enabled) - acpi_video_switch_brightness(video_device, event); + brightness_switch_event(video_device, event); keycode = KEY_BRIGHTNESSUP; break; case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */ - if (brightness_switch_enabled) - acpi_video_switch_brightness(video_device, event); + brightness_switch_event(video_device, event); keycode = KEY_BRIGHTNESSDOWN; break; case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightness */ - if (brightness_switch_enabled) - acpi_video_switch_brightness(video_device, event); + brightness_switch_event(video_device, event); keycode = KEY_BRIGHTNESS_ZERO; break; case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */ - if (brightness_switch_enabled) - acpi_video_switch_brightness(video_device, event); + brightness_switch_event(video_device, event); keycode = KEY_DISPLAY_OFF; break; default: |