History

platform/x86: asus-wmi: add keyboard brightness event handler

The keyboard brightness control of Asus WMI keyboards is handled in kernel, which leads to the shortcut going from brightness 0, to 1, to 2, and 3. However, for HID keyboards it is exposed as a key and handled by the user's desktop environment. For the toggle button, this means that brightness control becomes on/off. In addition, in the absence of a DE, the keyboard brightness does not work. Therefore, expose an event handler for the keyboard brightness control which can then be used by hid-asus. Since this handler is called from an interrupt context, defer the actual work to a workqueue. In the process, introduce ASUS_EV_MAX_BRIGHTNESS to hold the constant for maximum brightness since it is shared between hid-asus/asus-wmi.

Antheas Kapenekakis committed 9 months ago

Commit 75255661 parent d3133cc2 files · +54 −5Browse files

Unified · Split

2 files
  1. drivers/platform/x86/asus-wmi.c +41 −5
  2. include/linux/platform_data/x86/asus-wmi.h +13 −0
drivers/platform/x86/asus-wmi.c+41−5
@@ -1719,6 +1719,44 @@ static void kbd_led_update_all(struct work_struct *work) · 1718 unmodified lines
1719 }1719 }
1720}1720}
1721 1721
1722/*
1723 * This function is called from hid-asus to inform asus-wmi of brightness
1724 * changes initiated by the keyboard backlight keys.
1725 */
1726int asus_hid_event(enum asus_hid_event event)
1727{
1728 struct asus_wmi *asus;
1729 int brightness;
1730
1731 guard(spinlock_irqsave)(&asus_ref.lock);
1732 asus = asus_ref.asus;
1733 if (!asus || !asus->kbd_led_registered)
1734 return -EBUSY;
1735
1736 brightness = asus->kbd_led_wk;
1737
1738 switch (event) {
1739 case ASUS_EV_BRTUP:
1740 brightness += 1;
1741 break;
1742 case ASUS_EV_BRTDOWN:
1743 brightness -= 1;
1744 break;
1745 case ASUS_EV_BRTTOGGLE:
1746 if (brightness >= ASUS_EV_MAX_BRIGHTNESS)
1747 brightness = 0;
1748 else
1749 brightness += 1;
1750 break;
1751 }
1752
1753 asus->kbd_led_wk = clamp_val(brightness, 0, ASUS_EV_MAX_BRIGHTNESS);
1754 asus->kbd_led_notify = true;
1755 queue_work(asus->led_workqueue, &asus->kbd_led_work);
1756 return 0;
1757}
1758EXPORT_SYMBOL_GPL(asus_hid_event);
1759
1722/*1760/*
1723 * These functions actually update the LED's, and are called from a1761 * These functions actually update the LED's, and are called from a
1724 * workqueue. By doing this as separate work rather than when the LED1762 * workqueue. By doing this as separate work rather than when the LED
@@ -1801,13 +1839,11 @@ static void do_kbd_led_set(struct led_classdev *led_cdev, int value) · 76 unmodified lines
1801{1839{
1802 struct asus_hid_listener *listener;1840 struct asus_hid_listener *listener;
1803 struct asus_wmi *asus;1841 struct asus_wmi *asus;
1804 int max_level;
1805 1842
1806 asus = container_of(led_cdev, struct asus_wmi, kbd_led);1843 asus = container_of(led_cdev, struct asus_wmi, kbd_led);
1807 max_level = asus->kbd_led.max_brightness;
1808 1844
1809 scoped_guard(spinlock_irqsave, &asus_ref.lock)1845 scoped_guard(spinlock_irqsave, &asus_ref.lock)
1810 asus->kbd_led_wk = clamp_val(value, 0, max_level);1846 asus->kbd_led_wk = clamp_val(value, 0, ASUS_EV_MAX_BRIGHTNESS);
1811 1847
1812 if (asus->kbd_led_avail)1848 if (asus->kbd_led_avail)
1813 kbd_led_update(asus);1849 kbd_led_update(asus);
@@ -2011,7 +2047,7 @@ static int asus_wmi_led_init(struct asus_wmi *asus) · 197 unmodified lines
2011 asus->kbd_led.flags = LED_BRIGHT_HW_CHANGED;2047 asus->kbd_led.flags = LED_BRIGHT_HW_CHANGED;
2012 asus->kbd_led.brightness_set_blocking = kbd_led_set;2048 asus->kbd_led.brightness_set_blocking = kbd_led_set;
2013 asus->kbd_led.brightness_get = kbd_led_get;2049 asus->kbd_led.brightness_get = kbd_led_get;
2014 asus->kbd_led.max_brightness = 3;2050 asus->kbd_led.max_brightness = ASUS_EV_MAX_BRIGHTNESS;
2015 asus->kbd_led_avail = !kbd_led_read(asus, &led_val, NULL);2051 asus->kbd_led_avail = !kbd_led_read(asus, &led_val, NULL);
2016 INIT_WORK(&asus->kbd_led_work, kbd_led_update_all);2052 INIT_WORK(&asus->kbd_led_work, kbd_led_update_all);
2017 2053
@@ -4530,7 +4566,7 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus) · 2512 unmodified lines
4530 return;4566 return;
4531 }4567 }
4532 if (code == NOTIFY_KBD_BRTTOGGLE) {4568 if (code == NOTIFY_KBD_BRTTOGGLE) {
4533 if (led_value >= asus->kbd_led.max_brightness)4569 if (led_value >= ASUS_EV_MAX_BRIGHTNESS)
4534 kbd_led_set_by_kbd(asus, 0);4570 kbd_led_set_by_kbd(asus, 0);
4535 else4571 else
4536 kbd_led_set_by_kbd(asus, led_value + 1);4572 kbd_led_set_by_kbd(asus, led_value + 1);
include/linux/platform_data/x86/asus-wmi.h+13−0
@@ -178,6 +178,14 @@ struct asus_hid_listener { · 177 unmodified lines
178 void (*brightness_set)(struct asus_hid_listener *listener, int brightness);178 void (*brightness_set)(struct asus_hid_listener *listener, int brightness);
179};179};
180 180
181enum asus_hid_event {
182 ASUS_EV_BRTUP,
183 ASUS_EV_BRTDOWN,
184 ASUS_EV_BRTTOGGLE,
185};
186
187#define ASUS_EV_MAX_BRIGHTNESS 3
188
181#if IS_REACHABLE(CONFIG_ASUS_WMI)189#if IS_REACHABLE(CONFIG_ASUS_WMI)
182void set_ally_mcu_hack(enum asus_ally_mcu_hack status);190void set_ally_mcu_hack(enum asus_ally_mcu_hack status);
183void set_ally_mcu_powersave(bool enabled);191void set_ally_mcu_powersave(bool enabled);
@@ -186,6 +194,7 @@ int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param, u32 *retval); · 2 unmodified lines
186int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, u32 *retval);194int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, u32 *retval);
187int asus_hid_register_listener(struct asus_hid_listener *cdev);195int asus_hid_register_listener(struct asus_hid_listener *cdev);
188void asus_hid_unregister_listener(struct asus_hid_listener *cdev);196void asus_hid_unregister_listener(struct asus_hid_listener *cdev);
197int asus_hid_event(enum asus_hid_event event);
189#else198#else
190static inline void set_ally_mcu_hack(enum asus_ally_mcu_hack status)199static inline void set_ally_mcu_hack(enum asus_ally_mcu_hack status)
191{200{
@@ -213,6 +222,10 @@ static inline int asus_hid_register_listener(struct asus_hid_listener *bdev) · 21 unmodified lines
213static inline void asus_hid_unregister_listener(struct asus_hid_listener *bdev)222static inline void asus_hid_unregister_listener(struct asus_hid_listener *bdev)
214{223{
215}224}
225static inline int asus_hid_event(enum asus_hid_event event)
226{
227 return -ENODEV;
228}
216#endif229#endif
217 230
218#endif /* __PLATFORM_DATA_X86_ASUS_WMI_H */231#endif /* __PLATFORM_DATA_X86_ASUS_WMI_H */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t