From 51fdf98b4786bf43e0b3ae63faca3d2a4888de8f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 3 Jun 2014 09:57:03 -0400 Subject: [PATCH] Fix brightness key issues on various Acer models (rhbz 1012674) From: Hans de Goede --- ...spire-5741-to-video_vendor_dmi_table.patch | 40 ++++ ...h-to-acpi_video_unregister_backlight.patch | 64 ++++++ ...n-acpi_video_unregister_backlight-fu.patch | 112 +++++++++ ...-register-acpi_video_resume-notifier.patch | 214 ++++++++++++++++++ kernel.spec | 8 + 5 files changed, 438 insertions(+) create mode 100644 acer-wmi-Add-Aspire-5741-to-video_vendor_dmi_table.patch create mode 100644 acer-wmi-Switch-to-acpi_video_unregister_backlight.patch create mode 100644 acpi-video-Add-an-acpi_video_unregister_backlight-fu.patch create mode 100644 acpi-video-Don-t-register-acpi_video_resume-notifier.patch diff --git a/acer-wmi-Add-Aspire-5741-to-video_vendor_dmi_table.patch b/acer-wmi-Add-Aspire-5741-to-video_vendor_dmi_table.patch new file mode 100644 index 000000000..668fa0956 --- /dev/null +++ b/acer-wmi-Add-Aspire-5741-to-video_vendor_dmi_table.patch @@ -0,0 +1,40 @@ +Bugzilla: 1012674 +Upstream-status: Queued for 3.16 + +From a94de796cd769fc5c4a9c57ebe99c0ae74b9c8a1 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 2 Jun 2014 17:41:06 +0200 +Subject: [PATCH 09/14] acer-wmi: Add Aspire 5741 to video_vendor_dmi_table + +The Aspire 5741 has broken acpi-video backlight control, so add it to the +quirk table. + +https://bugzilla.redhat.com/show_bug.cgi?id=1012674 + +Signed-off-by: Hans de Goede +--- + drivers/platform/x86/acer-wmi.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c +index 3a746998f92a..bbf78b2d6d93 100644 +--- a/drivers/platform/x86/acer-wmi.c ++++ b/drivers/platform/x86/acer-wmi.c +@@ -570,6 +570,14 @@ static const struct dmi_system_id video_vendor_dmi_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5750"), + }, + }, ++ { ++ .callback = video_set_backlight_video_vendor, ++ .ident = "Acer Aspire 5741", ++ .matches = { ++ DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5741"), ++ }, ++ }, + {} + }; + +-- +1.9.0 + diff --git a/acer-wmi-Switch-to-acpi_video_unregister_backlight.patch b/acer-wmi-Switch-to-acpi_video_unregister_backlight.patch new file mode 100644 index 000000000..310e8a299 --- /dev/null +++ b/acer-wmi-Switch-to-acpi_video_unregister_backlight.patch @@ -0,0 +1,64 @@ +Bugzilla: 1012674 +Upstream-status: Queued for 3.16 + +From d8aceabf18681a92e8031c43d3917f6826ac6691 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 2 Jun 2014 17:41:05 +0200 +Subject: [PATCH 08/14] acer-wmi: Switch to acpi_video_unregister_backlight + +Switch from acpi_video_unregister(), to acpi_video_unregister_backlight(), +so that the hotkeys handler registered by acpi-video stays in place. + +Since there are no mappings for the atkbd raw codes for the brightness +keys used by newer Acer models in /lib/udev/hwdb.d/60-keyboard.hwdb, and +since we map the wmi events with a code of KE_IGNORE, we rely on acpi-video +to do the hotkey handling for us. + +For laptops such as the Acer Aspire 5750 which uses intel gfx this works +despite us calling acpi_video_unregister() because the following happens: + +1) acpi-video module gets loaded (as it is a dependency of acer-wmi and i915) +2) acpi-video does NOT call acpi_video_register() +3) acer-wmi loads (assume it loads before i915), calls +acpi_video_dmi_promote_vendor(); which sets ACPI_VIDEO_BACKLIGHT_DMI_VENDOR +4) calls acpi_video_unregister -> not registered, nop +5) i915 loads, calls acpi_video_register +6) acpi_video_register registers the acpi_notifier for the hotkeys, + does NOT register a backlight device because of ACPI_VIDEO_BACKLIGHT_DMI_VENDOR + +But on the Acer Aspire 5750G, which uses nvidia graphics the following happens: +1) acpi-video module gets loaded (as it is a dependency of acer-wmi) +2) acpi-video calls acpi_video_register() +3) acpi_video_register registers the acpi_notifier for the hotkeys, + and a backlight device +4) acer-wmi loads, calls acpi_video_dmi_promote_vendor() +5) calls acpi_video_unregister, this unregisters BOTH the acpi_notifier for + the hotkeys AND the backlight device + +And we end up without any handler for the brightness hotkeys. This patch fixes +this by switching over to acpi_video_unregister_backlight() which keeps the +hotkey handler in place. + +https://bugzilla.kernel.org/show_bug.cgi?id=35622 + +Signed-off-by: Hans de Goede +--- + drivers/platform/x86/acer-wmi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c +index c91f69b39db4..3a746998f92a 100644 +--- a/drivers/platform/x86/acer-wmi.c ++++ b/drivers/platform/x86/acer-wmi.c +@@ -2228,7 +2228,7 @@ static int __init acer_wmi_init(void) + pr_info("Brightness must be controlled by acpi video driver\n"); + } else { + pr_info("Disabling ACPI video driver\n"); +- acpi_video_unregister(); ++ acpi_video_unregister_backlight(); + } + + if (wmi_has_guid(WMID_GUID3)) { +-- +1.9.0 + diff --git a/acpi-video-Add-an-acpi_video_unregister_backlight-fu.patch b/acpi-video-Add-an-acpi_video_unregister_backlight-fu.patch new file mode 100644 index 000000000..c956ad0c2 --- /dev/null +++ b/acpi-video-Add-an-acpi_video_unregister_backlight-fu.patch @@ -0,0 +1,112 @@ +Bugzilla: 1012674 +Upstream-status: Queued for 3.16 + +From 4cf3eac89ed731d7cdb7d9d815a97109472af824 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 2 Jun 2014 17:41:04 +0200 +Subject: [PATCH 07/14] acpi-video: Add an acpi_video_unregister_backlight + function + +Add an acpi_video_unregister_backlight function, which only unregisters +the backlight device, and leaves the acpi_notifier in place. Some acpi_vendor +driver need this as they don't want the acpi_video# backlight device, but do +need the acpi-video driver for hotkey handling. + +Chances are that this new acpi_video_unregister_backlight() is actually +what existing acpi_vendor drivers have wanted all along. Currently acpi_vendor +drivers which want to disable the acpi_video# backlight device, make 2 calls: + +acpi_video_dmi_promote_vendor(); +acpi_video_unregister(); + +The intention here is to make things independent of when acpi_video_register() +gets called. As acpi_video_register() will get called on acpi-video load time +on non intel gfx machines, while it gets called on i915 load time on intel +gfx machines. + +This leads to the following 2 interesting scenarios: + +a) intel gfx: +1) acpi-video module gets loaded (as it is a dependency of acpi_vendor and i915) +2) acpi-video does NOT call acpi_video_register() +3) acpi_vendor loads (lets assume it loads before i915), calls +acpi_video_dmi_promote_vendor(); which sets ACPI_VIDEO_BACKLIGHT_DMI_VENDOR +4) calls acpi_video_unregister -> not registered, nop +5) i915 loads, calls acpi_video_register +6) acpi_video_register registers the acpi_notifier for the hotkeys, + does NOT register a backlight device because of ACPI_VIDEO_BACKLIGHT_DMI_VENDOR + +b) non intel gfx +1) acpi-video module gets loaded (as it is a dependency acpi_vendor) +2) acpi-video calls acpi_video_register() +3) acpi_video_register registers the acpi_notifier for the hotkeys, + and a backlight device +4) acpi_vendor loads, calls acpi_video_dmi_promote_vendor() +5) calls acpi_video_unregister, this unregisters BOTH the acpi_notifier for + the hotkeys AND the backlight device + +So here we have possibly the same acpi_vendor module, making the same calls, +but with different results, in one cases acpi-video does handle hotkeys, +in the other it does not. + +Note that the a) scenario turns into b) if we assume the i915 module loads +before the vendor_acpi module, so we also have different behavior depending +on module loading order! + +So as said I believe that quite a few existing acpi_vendor modules really +always want the behavior of a), hence this patch adds a new +acpi_video_unregister_backlight() which gives the behavior of a) independent +of module loading order. + +Signed-off-by: Hans de Goede +--- + drivers/acpi/video.c | 14 ++++++++++++++ + include/acpi/video.h | 2 ++ + 2 files changed, 16 insertions(+) + +diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c +index a68313720c9c..d4d6ea3ac77a 100644 +--- a/drivers/acpi/video.c ++++ b/drivers/acpi/video.c +@@ -2070,6 +2070,20 @@ void acpi_video_unregister(void) + } + EXPORT_SYMBOL(acpi_video_unregister); + ++void acpi_video_unregister_backlight(void) ++{ ++ struct acpi_video_bus *video; ++ ++ if (!register_count) ++ return; ++ ++ mutex_lock(&video_list_lock); ++ list_for_each_entry(video, &video_bus_head, entry) ++ acpi_video_bus_unregister_backlight(video); ++ mutex_unlock(&video_list_lock); ++} ++EXPORT_SYMBOL(acpi_video_unregister_backlight); ++ + /* + * This is kind of nasty. Hardware using Intel chipsets may require + * the video opregion code to be run first in order to initialise +diff --git a/include/acpi/video.h b/include/acpi/video.h +index 61109f2609fc..ea4c7bbded4d 100644 +--- a/include/acpi/video.h ++++ b/include/acpi/video.h +@@ -19,11 +19,13 @@ struct acpi_device; + #if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE) + extern int acpi_video_register(void); + extern void acpi_video_unregister(void); ++extern void acpi_video_unregister_backlight(void); + extern int acpi_video_get_edid(struct acpi_device *device, int type, + int device_id, void **edid); + #else + static inline int acpi_video_register(void) { return 0; } + static inline void acpi_video_unregister(void) { return; } ++static inline void acpi_video_unregister_backlight(void) { return; } + static inline int acpi_video_get_edid(struct acpi_device *device, int type, + int device_id, void **edid) + { +-- +1.9.0 + diff --git a/acpi-video-Don-t-register-acpi_video_resume-notifier.patch b/acpi-video-Don-t-register-acpi_video_resume-notifier.patch new file mode 100644 index 000000000..ac40462cd --- /dev/null +++ b/acpi-video-Don-t-register-acpi_video_resume-notifier.patch @@ -0,0 +1,214 @@ +Bugzilla: 1012674 +Upstream-status: Queued for 3.16 + +From 5d9b5801af7cbeaab060fa07576ca6cd7dc3be89 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Mon, 2 Jun 2014 17:41:03 +0200 +Subject: [PATCH 06/14] acpi-video: Don't register acpi_video_resume notifier + without backlight devices + +If we're not going to be registering any backlight devices then +acpi_video_resume is always nop, so don't register it in that case. + +Signed-off-by: Hans de Goede + +-- + +Note to reviewers the changes to acpi_video_dev_register_backlight() only +remove the "if (!acpi_video_verify_backlight_support()) {" which surrounded +the entire body of the function, as that is checked earlier now. +--- + drivers/acpi/video.c | 139 +++++++++++++++++++++++++++------------------------ + 1 file changed, 74 insertions(+), 65 deletions(-) + +diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c +index f8bc5a755dda..a68313720c9c 100644 +--- a/drivers/acpi/video.c ++++ b/drivers/acpi/video.c +@@ -150,6 +150,7 @@ struct acpi_video_enumerated_device { + + struct acpi_video_bus { + struct acpi_device *device; ++ bool backlight_registered; + u8 dos_setting; + struct acpi_video_enumerated_device *attached_array; + u8 attached_count; +@@ -1658,88 +1659,89 @@ acpi_video_bus_match(acpi_handle handle, u32 level, void *context, + + static void acpi_video_dev_register_backlight(struct acpi_video_device *device) + { +- if (acpi_video_verify_backlight_support()) { +- struct backlight_properties props; +- struct pci_dev *pdev; +- acpi_handle acpi_parent; +- struct device *parent = NULL; +- int result; +- static int count; +- char *name; +- +- result = acpi_video_init_brightness(device); +- if (result) +- return; +- name = kasprintf(GFP_KERNEL, "acpi_video%d", count); +- if (!name) +- return; +- count++; ++ struct backlight_properties props; ++ struct pci_dev *pdev; ++ acpi_handle acpi_parent; ++ struct device *parent = NULL; ++ int result; ++ static int count; ++ char *name; + +- acpi_get_parent(device->dev->handle, &acpi_parent); ++ result = acpi_video_init_brightness(device); ++ if (result) ++ return; ++ name = kasprintf(GFP_KERNEL, "acpi_video%d", count); ++ if (!name) ++ return; ++ count++; + +- pdev = acpi_get_pci_dev(acpi_parent); +- if (pdev) { +- parent = &pdev->dev; +- pci_dev_put(pdev); +- } ++ acpi_get_parent(device->dev->handle, &acpi_parent); + +- memset(&props, 0, sizeof(struct backlight_properties)); +- props.type = BACKLIGHT_FIRMWARE; +- props.max_brightness = device->brightness->count - 3; +- device->backlight = backlight_device_register(name, +- parent, +- device, +- &acpi_backlight_ops, +- &props); +- kfree(name); +- if (IS_ERR(device->backlight)) +- return; ++ pdev = acpi_get_pci_dev(acpi_parent); ++ if (pdev) { ++ parent = &pdev->dev; ++ pci_dev_put(pdev); ++ } + +- /* +- * Save current brightness level in case we have to restore it +- * before acpi_video_device_lcd_set_level() is called next time. +- */ +- device->backlight->props.brightness = +- acpi_video_get_brightness(device->backlight); ++ memset(&props, 0, sizeof(struct backlight_properties)); ++ props.type = BACKLIGHT_FIRMWARE; ++ props.max_brightness = device->brightness->count - 3; ++ device->backlight = backlight_device_register(name, ++ parent, ++ device, ++ &acpi_backlight_ops, ++ &props); ++ kfree(name); ++ if (IS_ERR(device->backlight)) ++ return; + +- device->cooling_dev = thermal_cooling_device_register("LCD", +- device->dev, &video_cooling_ops); +- if (IS_ERR(device->cooling_dev)) { +- /* +- * Set cooling_dev to NULL so we don't crash trying to +- * free it. +- * Also, why the hell we are returning early and +- * not attempt to register video output if cooling +- * device registration failed? +- * -- dtor +- */ +- device->cooling_dev = NULL; +- return; +- } ++ /* ++ * Save current brightness level in case we have to restore it ++ * before acpi_video_device_lcd_set_level() is called next time. ++ */ ++ device->backlight->props.brightness = ++ acpi_video_get_brightness(device->backlight); + +- dev_info(&device->dev->dev, "registered as cooling_device%d\n", +- device->cooling_dev->id); +- result = sysfs_create_link(&device->dev->dev.kobj, +- &device->cooling_dev->device.kobj, +- "thermal_cooling"); +- if (result) +- printk(KERN_ERR PREFIX "Create sysfs link\n"); +- result = sysfs_create_link(&device->cooling_dev->device.kobj, +- &device->dev->dev.kobj, "device"); +- if (result) +- printk(KERN_ERR PREFIX "Create sysfs link\n"); ++ device->cooling_dev = thermal_cooling_device_register("LCD", ++ device->dev, &video_cooling_ops); ++ if (IS_ERR(device->cooling_dev)) { ++ /* ++ * Set cooling_dev to NULL so we don't crash trying to free it. ++ * Also, why the hell we are returning early and not attempt to ++ * register video output if cooling device registration failed? ++ * -- dtor ++ */ ++ device->cooling_dev = NULL; ++ return; + } ++ ++ dev_info(&device->dev->dev, "registered as cooling_device%d\n", ++ device->cooling_dev->id); ++ result = sysfs_create_link(&device->dev->dev.kobj, ++ &device->cooling_dev->device.kobj, ++ "thermal_cooling"); ++ if (result) ++ printk(KERN_ERR PREFIX "Create sysfs link\n"); ++ result = sysfs_create_link(&device->cooling_dev->device.kobj, ++ &device->dev->dev.kobj, "device"); ++ if (result) ++ printk(KERN_ERR PREFIX "Create sysfs link\n"); + } + + static int acpi_video_bus_register_backlight(struct acpi_video_bus *video) + { + struct acpi_video_device *dev; + ++ if (!acpi_video_verify_backlight_support()) ++ return 0; ++ + mutex_lock(&video->device_list_lock); + list_for_each_entry(dev, &video->video_device_list, entry) + acpi_video_dev_register_backlight(dev); + mutex_unlock(&video->device_list_lock); + ++ video->backlight_registered = true; ++ + video->pm_nb.notifier_call = acpi_video_resume; + video->pm_nb.priority = 0; + return register_pm_notifier(&video->pm_nb); +@@ -1767,13 +1769,20 @@ static void acpi_video_dev_unregister_backlight(struct acpi_video_device *device + static int acpi_video_bus_unregister_backlight(struct acpi_video_bus *video) + { + struct acpi_video_device *dev; +- int error = unregister_pm_notifier(&video->pm_nb); ++ int error; ++ ++ if (!video->backlight_registered) ++ return 0; ++ ++ error = unregister_pm_notifier(&video->pm_nb); + + mutex_lock(&video->device_list_lock); + list_for_each_entry(dev, &video->video_device_list, entry) + acpi_video_dev_unregister_backlight(dev); + mutex_unlock(&video->device_list_lock); + ++ video->backlight_registered = false; ++ + return error; + } + +-- +1.9.0 + diff --git a/kernel.spec b/kernel.spec index 529e26310..4bd07a5d3 100644 --- a/kernel.spec +++ b/kernel.spec @@ -649,6 +649,10 @@ Patch26002: samsung-laptop-Add-broken-acpi-video-quirk-for-NC210.patch Patch26003: ideapad-laptop-Blacklist-rfkill-control-on-the-Lenov.patch Patch26004: asus-wmi-Add-a-no-backlight-quirk.patch Patch26005: eeepc-wmi-Add-no-backlight-quirk-for-Asus-H87I-PLUS-.patch +Patch26006: acpi-video-Don-t-register-acpi_video_resume-notifier.patch +Patch26007: acpi-video-Add-an-acpi_video_unregister_backlight-fu.patch +Patch26008: acer-wmi-Switch-to-acpi_video_unregister_backlight.patch +Patch26009: acer-wmi-Add-Aspire-5741-to-video_vendor_dmi_table.patch # END OF PATCH DEFINITIONS @@ -1375,6 +1379,10 @@ ApplyPatch samsung-laptop-Add-broken-acpi-video-quirk-for-NC210.patch ApplyPatch ideapad-laptop-Blacklist-rfkill-control-on-the-Lenov.patch ApplyPatch asus-wmi-Add-a-no-backlight-quirk.patch ApplyPatch eeepc-wmi-Add-no-backlight-quirk-for-Asus-H87I-PLUS-.patch +ApplyPatch acpi-video-Don-t-register-acpi_video_resume-notifier.patch +ApplyPatch acpi-video-Add-an-acpi_video_unregister_backlight-fu.patch +ApplyPatch acer-wmi-Switch-to-acpi_video_unregister_backlight.patch +ApplyPatch acer-wmi-Add-Aspire-5741-to-video_vendor_dmi_table.patch # END OF PATCH APPLICATIONS