* Re: [PATCH] arm64: dts: qcom: milos-fairphone-fp6: Add Hall Effect sensor
From: Konrad Dybcio @ 2026-01-22 8:32 UTC (permalink / raw)
To: Dmitry Torokhov, Luca Weiss
Cc: Dmitry Baryshkov, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, ~postmarketos/upstreaming,
phone-devel, linux-arm-msm, devicetree, linux-kernel, linux-input
In-Reply-To: <t4yjnuty7tmvs4vqzm4vdid7oowicy7hcnmqmu6nqtit3yru55@zpo6kprnarth>
On 1/21/26 9:06 PM, Dmitry Torokhov wrote:
> On Wed, Jan 21, 2026 at 09:07:44AM +0100, Luca Weiss wrote:
>> On Wed Jan 21, 2026 at 12:05 AM CET, Dmitry Baryshkov wrote:
>>> On Mon, Jan 19, 2026 at 04:52:23PM +0100, Luca Weiss wrote:
>>>> On Mon Jan 19, 2026 at 3:41 PM CET, Konrad Dybcio wrote:
>>>>> On 1/16/26 3:22 PM, Luca Weiss wrote:
>>>>>> Add a node for the Hall Effect sensor, used to detect whether the Flip
>>>>>> Cover is closed or not.
>>>>>>
>>>>>> The sensor is powered through vreg_l10b, so let's put a
>>>>>> regulator-always-on on that to make sure the sensor gets power.
>>>>>
>>>>> Is there anything else on L10B? Can we turn it off if the hall sensor
>>>>> is e.g. user-disabled?
>>>>
>>>> It's the voltage source for pull-up of sensor I2C bus (so
>>>> ADSP-managed?), DVDD for amplifiers and VDD for a most sensors like
>>>> the gyro.
>>>>
>>>> So realistically, it'll probably be (nearly) always on anyways. And I
>>>> don't want to shave another yak by adding vdd support to gpio-keys...
>>>
>>> Why? If it is exactly what happens on the board: the device producing
>>> GPIO events _is_ powered via a vdd. Added Input maintainer / list to cc.
>>
>> Yes, the hall sensor which is connected to the GPIO on the SoC, has an
>> extra VDD input which needs to be on in order for the Hall-effect sensor
>> to be on.
>>
>> See page 133 "HALL" in the center of the page
>> https://www.fairphone.com/wp-content/uploads/2025/08/Fairphone-Gen.-6_-Information-on-how-to-repair-dispose-of-and-recycle-EN-NL-FR-DE.pdf
>>
>> The IC is OCH166AEV4AD where VDD is (as expected) "Power Supply Input":
>> https://www.orient-chip.com/Public/Uploads/uploadfile/files/20231014/1OCH166Adatasheet202203221.pdf
>
> If we add regulator support to gpio-keys do we expect it to be
> per-gpio/per-key? Or we'd recommend splitting into several instances of
> gpio-keys so that there is on set of supplies per gpio-keys device?
gpio-keys {} is very broad and generic, I would imagine it would only
make sense to keep it per-entry, like Luca suggested
Konrad
^ permalink raw reply
* [PATCH v12 08/11] HID: asus: listen to the asus-wmi brightness device instead of creating one
From: Antheas Kapenekakis @ 2026-01-22 7:50 UTC (permalink / raw)
To: platform-driver-x86, linux-input
Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires, Corentin Chary,
Luke D . Jones, Hans de Goede, Ilpo Järvinen, Denis Benato,
Antheas Kapenekakis, Denis Benato
In-Reply-To: <20260122075044.5070-1-lkml@antheas.dev>
Some ROG laptops expose multiple interfaces for controlling the
keyboard/RGB brightness. This creates a name conflict under
asus::kbd_brightness, where the second device ends up being
named asus::kbd_brightness_1 and they are both broken.
Therefore, register a listener to the asus-wmi brightness device
instead of creating a new one.
Reviewed-by: Luke D. Jones <luke@ljones.dev>
Reviewed-by: Benjamin Tissoires <bentiss@kernel.org>
Reviewed-by: Denis Benato <benato.denis96@gmail.com>
Acked-by: Benjamin Tissoires <bentiss@kernel.org>
Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
---
drivers/hid/hid-asus.c | 65 +++++++-----------------------------------
1 file changed, 10 insertions(+), 55 deletions(-)
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index 6084ec66a134..415629ebee15 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -27,7 +27,6 @@
#include <linux/hid.h>
#include <linux/module.h>
#include <linux/platform_data/x86/asus-wmi.h>
-#include <linux/platform_data/x86/asus-wmi-leds-ids.h>
#include <linux/input/mt.h>
#include <linux/usb.h> /* For to_usb_interface for T100 touchpad intf check */
#include <linux/power_supply.h>
@@ -103,7 +102,7 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
#define TRKID_SGN ((TRKID_MAX + 1) >> 1)
struct asus_kbd_leds {
- struct led_classdev cdev;
+ struct asus_hid_listener listener;
struct hid_device *hdev;
struct work_struct work;
unsigned int brightness;
@@ -495,11 +494,11 @@ static void asus_schedule_work(struct asus_kbd_leds *led)
spin_unlock_irqrestore(&led->lock, flags);
}
-static void asus_kbd_backlight_set(struct led_classdev *led_cdev,
- enum led_brightness brightness)
+static void asus_kbd_backlight_set(struct asus_hid_listener *listener,
+ int brightness)
{
- struct asus_kbd_leds *led = container_of(led_cdev, struct asus_kbd_leds,
- cdev);
+ struct asus_kbd_leds *led = container_of(listener, struct asus_kbd_leds,
+ listener);
unsigned long flags;
spin_lock_irqsave(&led->lock, flags);
@@ -509,20 +508,6 @@ static void asus_kbd_backlight_set(struct led_classdev *led_cdev,
asus_schedule_work(led);
}
-static enum led_brightness asus_kbd_backlight_get(struct led_classdev *led_cdev)
-{
- struct asus_kbd_leds *led = container_of(led_cdev, struct asus_kbd_leds,
- cdev);
- enum led_brightness brightness;
- unsigned long flags;
-
- spin_lock_irqsave(&led->lock, flags);
- brightness = led->brightness;
- spin_unlock_irqrestore(&led->lock, flags);
-
- return brightness;
-}
-
static void asus_kbd_backlight_work(struct work_struct *work)
{
struct asus_kbd_leds *led = container_of(work, struct asus_kbd_leds, work);
@@ -539,34 +524,6 @@ static void asus_kbd_backlight_work(struct work_struct *work)
hid_err(led->hdev, "Asus failed to set keyboard backlight: %d\n", ret);
}
-/* WMI-based keyboard backlight LED control (via asus-wmi driver) takes
- * precedence. We only activate HID-based backlight control when the
- * WMI control is not available.
- */
-static bool asus_kbd_wmi_led_control_present(struct hid_device *hdev)
-{
- struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
- u32 value;
- int ret;
-
- if (!IS_ENABLED(CONFIG_ASUS_WMI))
- return false;
-
- if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD &&
- dmi_check_system(asus_use_hid_led_dmi_ids)) {
- hid_info(hdev, "using HID for asus::kbd_backlight\n");
- return false;
- }
-
- ret = asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS,
- ASUS_WMI_DEVID_KBD_BACKLIGHT, 0, &value);
- hid_dbg(hdev, "WMI backlight check: rc %d value %x", ret, value);
- if (ret)
- return false;
-
- return !!(value & ASUS_WMI_DSTS_PRESENCE_BIT);
-}
-
/*
* We don't care about any other part of the string except the version section.
* Example strings: FGA80100.RC72LA.312_T01, FGA80100.RC71LS.318_T01
@@ -706,14 +663,11 @@ static int asus_kbd_register_leds(struct hid_device *hdev)
drvdata->kbd_backlight->removed = false;
drvdata->kbd_backlight->brightness = 0;
drvdata->kbd_backlight->hdev = hdev;
- drvdata->kbd_backlight->cdev.name = "asus::kbd_backlight";
- drvdata->kbd_backlight->cdev.max_brightness = 3;
- drvdata->kbd_backlight->cdev.brightness_set = asus_kbd_backlight_set;
- drvdata->kbd_backlight->cdev.brightness_get = asus_kbd_backlight_get;
+ drvdata->kbd_backlight->listener.brightness_set = asus_kbd_backlight_set;
INIT_WORK(&drvdata->kbd_backlight->work, asus_kbd_backlight_work);
spin_lock_init(&drvdata->kbd_backlight->lock);
- ret = devm_led_classdev_register(&hdev->dev, &drvdata->kbd_backlight->cdev);
+ ret = asus_hid_register_listener(&drvdata->kbd_backlight->listener);
if (ret < 0) {
/* No need to have this still around */
devm_kfree(&hdev->dev, drvdata->kbd_backlight);
@@ -1102,7 +1056,7 @@ static int __maybe_unused asus_resume(struct hid_device *hdev) {
if (drvdata->kbd_backlight) {
const u8 buf[] = { FEATURE_KBD_REPORT_ID, 0xba, 0xc5, 0xc4,
- drvdata->kbd_backlight->cdev.brightness };
+ drvdata->kbd_backlight->brightness };
ret = asus_kbd_set_report(hdev, buf, sizeof(buf));
if (ret < 0) {
hid_err(hdev, "Asus failed to set keyboard backlight: %d\n", ret);
@@ -1228,7 +1182,6 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
}
if (is_vendor && (drvdata->quirks & QUIRK_USE_KBD_BACKLIGHT) &&
- !asus_kbd_wmi_led_control_present(hdev) &&
asus_kbd_register_leds(hdev))
hid_warn(hdev, "Failed to initialize backlight.\n");
@@ -1275,6 +1228,8 @@ static void asus_remove(struct hid_device *hdev)
unsigned long flags;
if (drvdata->kbd_backlight) {
+ asus_hid_unregister_listener(&drvdata->kbd_backlight->listener);
+
spin_lock_irqsave(&drvdata->kbd_backlight->lock, flags);
drvdata->kbd_backlight->removed = true;
spin_unlock_irqrestore(&drvdata->kbd_backlight->lock, flags);
--
2.52.0
^ permalink raw reply related
* [PATCH v12 11/11] HID: asus: add support for the asus-wmi brightness handler
From: Antheas Kapenekakis @ 2026-01-22 7:50 UTC (permalink / raw)
To: platform-driver-x86, linux-input
Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires, Corentin Chary,
Luke D . Jones, Hans de Goede, Ilpo Järvinen, Denis Benato,
Antheas Kapenekakis, Denis Benato
In-Reply-To: <20260122075044.5070-1-lkml@antheas.dev>
If the asus-wmi brightness handler is available, send the
keyboard brightness events to it instead of passing them
to userspace. If it is not, fall back to sending them to it.
Reviewed-by: Luke D. Jones <luke@ljones.dev>
Tested-by: Luke D. Jones <luke@ljones.dev>
Reviewed-by: Denis Benato <benato.denis96@gmail.com>
Acked-by: Benjamin Tissoires <bentiss@kernel.org>
Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
---
drivers/hid/hid-asus.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index 415629ebee15..f5c8df20b88b 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -324,6 +324,17 @@ static int asus_event(struct hid_device *hdev, struct hid_field *field,
usage->hid & HID_USAGE);
}
+ if (usage->type == EV_KEY && value) {
+ switch (usage->code) {
+ case KEY_KBDILLUMUP:
+ return !asus_hid_event(ASUS_EV_BRTUP);
+ case KEY_KBDILLUMDOWN:
+ return !asus_hid_event(ASUS_EV_BRTDOWN);
+ case KEY_KBDILLUMTOGGLE:
+ return !asus_hid_event(ASUS_EV_BRTTOGGLE);
+ }
+ }
+
return 0;
}
--
2.52.0
^ permalink raw reply related
* [PATCH v12 09/11] platform/x86: asus-wmi: remove unused keyboard backlight quirk
From: Antheas Kapenekakis @ 2026-01-22 7:50 UTC (permalink / raw)
To: platform-driver-x86, linux-input
Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires, Corentin Chary,
Luke D . Jones, Hans de Goede, Ilpo Järvinen, Denis Benato,
Antheas Kapenekakis, Denis Benato
In-Reply-To: <20260122075044.5070-1-lkml@antheas.dev>
The quirk for selecting whether keyboard backlight should be controlled
by HID or WMI is not needed anymore, so remove the file containing it.
Reviewed-by: Denis Benato <benato.denis96@gmail.com>
Acked-by: Benjamin Tissoires <bentiss@kernel.org>
Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
---
.../platform_data/x86/asus-wmi-leds-ids.h | 50 -------------------
1 file changed, 50 deletions(-)
delete mode 100644 include/linux/platform_data/x86/asus-wmi-leds-ids.h
diff --git a/include/linux/platform_data/x86/asus-wmi-leds-ids.h b/include/linux/platform_data/x86/asus-wmi-leds-ids.h
deleted file mode 100644
index 034a039c4e37..000000000000
--- a/include/linux/platform_data/x86/asus-wmi-leds-ids.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __PLATFORM_DATA_X86_ASUS_WMI_LEDS_IDS_H
-#define __PLATFORM_DATA_X86_ASUS_WMI_LEDS_IDS_H
-
-#include <linux/dmi.h>
-#include <linux/types.h>
-
-/* To be used by both hid-asus and asus-wmi to determine which controls kbd_brightness */
-#if IS_REACHABLE(CONFIG_ASUS_WMI) || IS_REACHABLE(CONFIG_HID_ASUS)
-static const struct dmi_system_id asus_use_hid_led_dmi_ids[] = {
- {
- .matches = {
- DMI_MATCH(DMI_PRODUCT_FAMILY, "ROG Zephyrus"),
- },
- },
- {
- .matches = {
- DMI_MATCH(DMI_PRODUCT_FAMILY, "ROG Strix"),
- },
- },
- {
- .matches = {
- DMI_MATCH(DMI_PRODUCT_FAMILY, "ROG Flow"),
- },
- },
- {
- .matches = {
- DMI_MATCH(DMI_PRODUCT_FAMILY, "ProArt P16"),
- },
- },
- {
- .matches = {
- DMI_MATCH(DMI_BOARD_NAME, "GA403U"),
- },
- },
- {
- .matches = {
- DMI_MATCH(DMI_BOARD_NAME, "GU605M"),
- },
- },
- {
- .matches = {
- DMI_MATCH(DMI_BOARD_NAME, "RC71L"),
- },
- },
- { },
-};
-#endif
-
-#endif /* __PLATFORM_DATA_X86_ASUS_WMI_LEDS_IDS_H */
--
2.52.0
^ permalink raw reply related
* [PATCH v12 10/11] platform/x86: asus-wmi: add keyboard brightness event handler
From: Antheas Kapenekakis @ 2026-01-22 7:50 UTC (permalink / raw)
To: platform-driver-x86, linux-input
Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires, Corentin Chary,
Luke D . Jones, Hans de Goede, Ilpo Järvinen, Denis Benato,
Antheas Kapenekakis, Denis Benato
In-Reply-To: <20260122075044.5070-1-lkml@antheas.dev>
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.
Reviewed-by: Luke D. Jones <luke@ljones.dev>
Tested-by: Luke D. Jones <luke@ljones.dev>
Acked-by: Benjamin Tissoires <bentiss@kernel.org>
Reviewed-by: Denis Benato <benato.denis96@gmail.com>
Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
---
drivers/platform/x86/asus-wmi.c | 46 +++++++++++++++++++---
include/linux/platform_data/x86/asus-wmi.h | 13 ++++++
2 files changed, 54 insertions(+), 5 deletions(-)
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index c45846be3f99..4cbd7b9806dc 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -1719,6 +1719,44 @@ static void kbd_led_update_all(struct work_struct *work)
}
}
+/*
+ * This function is called from hid-asus to inform asus-wmi of brightness
+ * changes initiated by the keyboard backlight keys.
+ */
+int asus_hid_event(enum asus_hid_event event)
+{
+ struct asus_wmi *asus;
+ int brightness;
+
+ guard(spinlock_irqsave)(&asus_ref.lock);
+ asus = asus_ref.asus;
+ if (!asus || !asus->kbd_led_registered)
+ return -EBUSY;
+
+ brightness = asus->kbd_led_wk;
+
+ switch (event) {
+ case ASUS_EV_BRTUP:
+ brightness += 1;
+ break;
+ case ASUS_EV_BRTDOWN:
+ brightness -= 1;
+ break;
+ case ASUS_EV_BRTTOGGLE:
+ if (brightness >= ASUS_EV_MAX_BRIGHTNESS)
+ brightness = 0;
+ else
+ brightness += 1;
+ break;
+ }
+
+ asus->kbd_led_wk = clamp_val(brightness, 0, ASUS_EV_MAX_BRIGHTNESS);
+ asus->kbd_led_notify = true;
+ queue_work(asus->led_workqueue, &asus->kbd_led_work);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(asus_hid_event);
+
/*
* These functions actually update the LED's, and are called from a
* 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)
{
struct asus_hid_listener *listener;
struct asus_wmi *asus;
- int max_level;
asus = container_of(led_cdev, struct asus_wmi, kbd_led);
- max_level = asus->kbd_led.max_brightness;
scoped_guard(spinlock_irqsave, &asus_ref.lock)
- asus->kbd_led_wk = clamp_val(value, 0, max_level);
+ asus->kbd_led_wk = clamp_val(value, 0, ASUS_EV_MAX_BRIGHTNESS);
if (asus->kbd_led_avail)
kbd_led_update(asus);
@@ -2011,7 +2047,7 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
asus->kbd_led.flags = LED_BRIGHT_HW_CHANGED;
asus->kbd_led.brightness_set_blocking = kbd_led_set;
asus->kbd_led.brightness_get = kbd_led_get;
- asus->kbd_led.max_brightness = 3;
+ asus->kbd_led.max_brightness = ASUS_EV_MAX_BRIGHTNESS;
asus->kbd_led_avail = !kbd_led_read(asus, &led_val, NULL);
INIT_WORK(&asus->kbd_led_work, kbd_led_update_all);
@@ -4530,7 +4566,7 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus)
return;
}
if (code == NOTIFY_KBD_BRTTOGGLE) {
- if (led_value >= asus->kbd_led.max_brightness)
+ if (led_value >= ASUS_EV_MAX_BRIGHTNESS)
kbd_led_set_by_kbd(asus, 0);
else
kbd_led_set_by_kbd(asus, led_value + 1);
diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h
index d347cffd05d5..7b872b5d0960 100644
--- a/include/linux/platform_data/x86/asus-wmi.h
+++ b/include/linux/platform_data/x86/asus-wmi.h
@@ -178,6 +178,14 @@ struct asus_hid_listener {
void (*brightness_set)(struct asus_hid_listener *listener, int brightness);
};
+enum asus_hid_event {
+ ASUS_EV_BRTUP,
+ ASUS_EV_BRTDOWN,
+ ASUS_EV_BRTTOGGLE,
+};
+
+#define ASUS_EV_MAX_BRIGHTNESS 3
+
#if IS_REACHABLE(CONFIG_ASUS_WMI)
void set_ally_mcu_hack(enum asus_ally_mcu_hack status);
void set_ally_mcu_powersave(bool enabled);
@@ -186,6 +194,7 @@ int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param, u32 *retval);
int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, u32 *retval);
int asus_hid_register_listener(struct asus_hid_listener *cdev);
void asus_hid_unregister_listener(struct asus_hid_listener *cdev);
+int asus_hid_event(enum asus_hid_event event);
#else
static inline void set_ally_mcu_hack(enum asus_ally_mcu_hack status)
{
@@ -213,6 +222,10 @@ static inline int asus_hid_register_listener(struct asus_hid_listener *bdev)
static inline void asus_hid_unregister_listener(struct asus_hid_listener *bdev)
{
}
+static inline int asus_hid_event(enum asus_hid_event event)
+{
+ return -ENODEV;
+}
#endif
#endif /* __PLATFORM_DATA_X86_ASUS_WMI_H */
--
2.52.0
^ permalink raw reply related
* [PATCH v12 06/11] HID: asus: early return for ROG devices
From: Antheas Kapenekakis @ 2026-01-22 7:50 UTC (permalink / raw)
To: platform-driver-x86, linux-input
Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires, Corentin Chary,
Luke D . Jones, Hans de Goede, Ilpo Järvinen, Denis Benato,
Antheas Kapenekakis, Denis Benato
In-Reply-To: <20260122075044.5070-1-lkml@antheas.dev>
Some ROG devices have a new dynamic backlight interface for control by
Windows. This interface does not create an ->input device, causing the
kernel to print an error message and to eject it. In addition, ROG
devices have proper HID names in their descriptors so renaming them is
not necessary.
Therefore, if a device is identified as ROG, early return from probe to
skip renaming and ->input checks.
Acked-by: Benjamin Tissoires <bentiss@kernel.org>
Reviewed-by: Denis Benato <benato.denis96@gmail.com>
Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
---
drivers/hid/hid-asus.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index dc8795b59cc2..6084ec66a134 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -1232,6 +1232,13 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
asus_kbd_register_leds(hdev))
hid_warn(hdev, "Failed to initialize backlight.\n");
+ /*
+ * For ROG keyboards, skip rename for consistency and ->input check as
+ * some devices do not have inputs.
+ */
+ if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD)
+ return 0;
+
/*
* Check that input registration succeeded. Checking that
* HID_CLAIMED_INPUT is set prevents a UAF when all input devices
--
2.52.0
^ permalink raw reply related
* [PATCH v12 05/11] HID: asus: move vendor initialization to probe
From: Antheas Kapenekakis @ 2026-01-22 7:50 UTC (permalink / raw)
To: platform-driver-x86, linux-input
Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires, Corentin Chary,
Luke D . Jones, Hans de Goede, Ilpo Järvinen, Denis Benato,
Antheas Kapenekakis, Denis Benato
In-Reply-To: <20260122075044.5070-1-lkml@antheas.dev>
ROG NKEY devices have multiple HID endpoints, around 3-4. One of those
endpoints has a usage page of 0xff31, and is the one that emits keyboard
shortcuts and controls RGB/backlight. Currently, this driver places
the usage page check under asus_input_mapping and then inits backlight
in asus_input_configured which is unnecessarily complicated and prevents
probe from performing customizations on the vendor endpoint.
Simplify the logic by introducing an is_vendor variable into probe that
checks for usage page 0xff31. Then, use this variable to move backlight
initialization into probe instead of asus_input_configured, and remove
the backlight check from asus_input_mapping.
Acked-by: Benjamin Tissoires <bentiss@kernel.org>
Reviewed-by: Denis Benato <benato.denis96@gmail.com>
Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
---
drivers/hid/hid-asus.c | 35 ++++++++++++++++++-----------------
1 file changed, 18 insertions(+), 17 deletions(-)
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index cbf5bab9113b..dc8795b59cc2 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -48,6 +48,7 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
#define T100CHI_MOUSE_REPORT_ID 0x06
#define FEATURE_REPORT_ID 0x0d
#define INPUT_REPORT_ID 0x5d
+#define HID_USAGE_PAGE_VENDOR 0xff310000
#define FEATURE_KBD_REPORT_ID 0x5a
#define FEATURE_KBD_REPORT_SIZE 64
#define FEATURE_KBD_LED_REPORT_ID1 0x5d
@@ -127,7 +128,6 @@ struct asus_drvdata {
struct input_dev *tp_kbd_input;
struct asus_kbd_leds *kbd_backlight;
const struct asus_touchpad_info *tp;
- bool enable_backlight;
struct power_supply *battery;
struct power_supply_desc battery_desc;
int battery_capacity;
@@ -318,7 +318,7 @@ static int asus_e1239t_event(struct asus_drvdata *drvdat, u8 *data, int size)
static int asus_event(struct hid_device *hdev, struct hid_field *field,
struct hid_usage *usage, __s32 value)
{
- if ((usage->hid & HID_USAGE_PAGE) == 0xff310000 &&
+ if ((usage->hid & HID_USAGE_PAGE) == HID_USAGE_PAGE_VENDOR &&
(usage->hid & HID_USAGE) != 0x00 &&
(usage->hid & HID_USAGE) != 0xff && !usage->type) {
hid_warn(hdev, "Unmapped Asus vendor usagepage code 0x%02x\n",
@@ -938,11 +938,6 @@ static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi)
drvdata->input = input;
- if (drvdata->enable_backlight &&
- !asus_kbd_wmi_led_control_present(hdev) &&
- asus_kbd_register_leds(hdev))
- hid_warn(hdev, "Failed to initialize backlight.\n");
-
return 0;
}
@@ -1015,15 +1010,6 @@ static int asus_input_mapping(struct hid_device *hdev,
return -1;
}
- /*
- * Check and enable backlight only on devices with UsagePage ==
- * 0xff31 to avoid initializing the keyboard firmware multiple
- * times on devices with multiple HID descriptors but same
- * PID/VID.
- */
- if (drvdata->quirks & QUIRK_USE_KBD_BACKLIGHT)
- drvdata->enable_backlight = true;
-
set_bit(EV_REP, hi->input->evbit);
return 1;
}
@@ -1140,8 +1126,11 @@ static int __maybe_unused asus_reset_resume(struct hid_device *hdev)
static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
- int ret;
+ struct hid_report_enum *rep_enum;
struct asus_drvdata *drvdata;
+ struct hid_report *rep;
+ bool is_vendor = false;
+ int ret;
drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL);
if (drvdata == NULL) {
@@ -1225,12 +1214,24 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
return ret;
}
+ /* Check for vendor for RGB init and handle generic devices properly. */
+ rep_enum = &hdev->report_enum[HID_INPUT_REPORT];
+ list_for_each_entry(rep, &rep_enum->report_list, list) {
+ if ((rep->application & HID_USAGE_PAGE) == HID_USAGE_PAGE_VENDOR)
+ is_vendor = true;
+ }
+
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
if (ret) {
hid_err(hdev, "Asus hw start failed: %d\n", ret);
return ret;
}
+ if (is_vendor && (drvdata->quirks & QUIRK_USE_KBD_BACKLIGHT) &&
+ !asus_kbd_wmi_led_control_present(hdev) &&
+ asus_kbd_register_leds(hdev))
+ hid_warn(hdev, "Failed to initialize backlight.\n");
+
/*
* Check that input registration succeeded. Checking that
* HID_CLAIMED_INPUT is set prevents a UAF when all input devices
--
2.52.0
^ permalink raw reply related
* [PATCH v12 04/11] HID: asus: fortify keyboard handshake
From: Antheas Kapenekakis @ 2026-01-22 7:50 UTC (permalink / raw)
To: platform-driver-x86, linux-input
Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires, Corentin Chary,
Luke D . Jones, Hans de Goede, Ilpo Järvinen, Denis Benato,
Antheas Kapenekakis, Denis Benato
In-Reply-To: <20260122075044.5070-1-lkml@antheas.dev>
Handshaking with an Asus device involves sending it a feature report
with the string "ASUS Tech.Inc." and then reading it back to verify the
handshake was successful, under the feature ID the interaction will
take place.
Currently, the driver only does the first part. Add the readback to
verify the handshake was successful. As this could cause breakages,
allow the verification to fail with a dmesg error until we verify
all devices work with it (they seem to).
Since the response is more than 16 bytes, increase the buffer size
to 64 as well to avoid overflow errors. In addition, add the report
ID to prints, to help identify failed handshakes.
Reviewed-by: Benjamin Tissoires <bentiss@kernel.org>
Reviewed-by: Denis Benato <benato.denis96@gmail.com>
Acked-by: Benjamin Tissoires <bentiss@kernel.org>
Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
---
drivers/hid/hid-asus.c | 34 ++++++++++++++++++++++++++++++----
1 file changed, 30 insertions(+), 4 deletions(-)
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index 2ff2170dc30a..cbf5bab9113b 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -49,7 +49,7 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
#define FEATURE_REPORT_ID 0x0d
#define INPUT_REPORT_ID 0x5d
#define FEATURE_KBD_REPORT_ID 0x5a
-#define FEATURE_KBD_REPORT_SIZE 16
+#define FEATURE_KBD_REPORT_SIZE 64
#define FEATURE_KBD_LED_REPORT_ID1 0x5d
#define FEATURE_KBD_LED_REPORT_ID2 0x5e
@@ -395,15 +395,41 @@ static int asus_kbd_set_report(struct hid_device *hdev, const u8 *buf, size_t bu
static int asus_kbd_init(struct hid_device *hdev, u8 report_id)
{
+ /*
+ * The handshake is first sent as a set_report, then retrieved
+ * from a get_report. They should be equal.
+ */
const u8 buf[] = { report_id, 0x41, 0x53, 0x55, 0x53, 0x20, 0x54,
0x65, 0x63, 0x68, 0x2e, 0x49, 0x6e, 0x63, 0x2e, 0x00 };
int ret;
ret = asus_kbd_set_report(hdev, buf, sizeof(buf));
- if (ret < 0)
- hid_err(hdev, "Asus failed to send init command: %d\n", ret);
+ if (ret < 0) {
+ hid_err(hdev, "Asus handshake %02x failed to send: %d\n",
+ report_id, ret);
+ return ret;
+ }
- return ret;
+ u8 *readbuf __free(kfree) = kzalloc(FEATURE_KBD_REPORT_SIZE, GFP_KERNEL);
+ if (!readbuf)
+ return -ENOMEM;
+
+ ret = hid_hw_raw_request(hdev, report_id, readbuf,
+ FEATURE_KBD_REPORT_SIZE, HID_FEATURE_REPORT,
+ HID_REQ_GET_REPORT);
+ if (ret < 0) {
+ hid_warn(hdev, "Asus handshake %02x failed to receive ack: %d\n",
+ report_id, ret);
+ } else if (memcmp(readbuf, buf, sizeof(buf)) != 0) {
+ hid_warn(hdev, "Asus handshake %02x returned invalid response: %*ph\n",
+ report_id, FEATURE_KBD_REPORT_SIZE, readbuf);
+ }
+
+ /*
+ * Do not return error if handshake is wrong until this is
+ * verified to work for all devices.
+ */
+ return 0;
}
static int asus_kbd_get_functions(struct hid_device *hdev,
--
2.52.0
^ permalink raw reply related
* [PATCH v12 07/11] platform/x86: asus-wmi: Add support for multiple kbd led handlers
From: Antheas Kapenekakis @ 2026-01-22 7:50 UTC (permalink / raw)
To: platform-driver-x86, linux-input
Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires, Corentin Chary,
Luke D . Jones, Hans de Goede, Ilpo Järvinen, Denis Benato,
Antheas Kapenekakis
In-Reply-To: <20260122075044.5070-1-lkml@antheas.dev>
Some devices, such as the Z13 have multiple Aura devices connected
to them by USB. In addition, they might have a WMI interface for
RGB. In Windows, Armoury Crate exposes a unified brightness slider
for all of them, with 3 brightness levels.
Therefore, to be synergistic in Linux, and support existing tooling
such as UPower, allow adding listeners to the RGB device of the WMI
interface. If WMI does not exist, lazy initialize the interface.
Since hid-asus and asus-wmi can both interact with the led objects
including from an atomic context, protect the brightness access with a
spinlock and update the values from a workqueue. Use this workqueue to
also process WMI keyboard events, so they are handled asynchronously.
Acked-by: Benjamin Tissoires <bentiss@kernel.org>
Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
---
drivers/platform/x86/asus-wmi.c | 183 ++++++++++++++++++---
include/linux/platform_data/x86/asus-wmi.h | 15 ++
2 files changed, 173 insertions(+), 25 deletions(-)
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 4aec7ec69250..c45846be3f99 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -31,13 +31,13 @@
#include <linux/pci.h>
#include <linux/pci_hotplug.h>
#include <linux/platform_data/x86/asus-wmi.h>
-#include <linux/platform_data/x86/asus-wmi-leds-ids.h>
#include <linux/platform_device.h>
#include <linux/platform_profile.h>
#include <linux/power_supply.h>
#include <linux/rfkill.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
+#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/units.h>
@@ -256,6 +256,9 @@ struct asus_wmi {
int tpd_led_wk;
struct led_classdev kbd_led;
int kbd_led_wk;
+ bool kbd_led_notify;
+ bool kbd_led_avail;
+ bool kbd_led_registered;
struct led_classdev lightbar_led;
int lightbar_led_wk;
struct led_classdev micmute_led;
@@ -264,6 +267,7 @@ struct asus_wmi {
struct work_struct tpd_led_work;
struct work_struct wlan_led_work;
struct work_struct lightbar_led_work;
+ struct work_struct kbd_led_work;
struct asus_rfkill wlan;
struct asus_rfkill bluetooth;
@@ -1615,6 +1619,106 @@ static void asus_wmi_battery_exit(struct asus_wmi *asus)
/* LEDs ***********************************************************************/
+struct asus_hid_ref {
+ struct list_head listeners;
+ struct asus_wmi *asus;
+ /* Protects concurrent access from hid-asus and asus-wmi to leds */
+ spinlock_t lock;
+};
+
+static struct asus_hid_ref asus_ref = {
+ .listeners = LIST_HEAD_INIT(asus_ref.listeners),
+ .asus = NULL,
+ /*
+ * Protects .asus, .asus.kbd_led_{wk,notify}, and .listener refs. Other
+ * asus variables are read-only after .asus is set.
+ *
+ * The led cdev device is not protected because it calls backlight_get
+ * during initialization, which would result in a nested lock attempt.
+ *
+ * The led cdev is safe to access without a lock because if
+ * kbd_led_avail is true it is initialized before .asus is set and never
+ * changed until .asus is dropped. If kbd_led_avail is false, the led
+ * cdev is registered by the workqueue, which is single-threaded and
+ * cancelled before asus-wmi would access the led cdev to unregister it.
+ *
+ * A spinlock is used, because the protected variables can be accessed
+ * from an IRQ context from asus-hid.
+ */
+ .lock = __SPIN_LOCK_UNLOCKED(asus_ref.lock),
+};
+
+/*
+ * Allows registering hid-asus listeners that want to be notified of
+ * keyboard backlight changes.
+ */
+int asus_hid_register_listener(struct asus_hid_listener *bdev)
+{
+ struct asus_wmi *asus;
+
+ guard(spinlock_irqsave)(&asus_ref.lock);
+ list_add_tail(&bdev->list, &asus_ref.listeners);
+ asus = asus_ref.asus;
+ if (asus)
+ queue_work(asus->led_workqueue, &asus->kbd_led_work);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(asus_hid_register_listener);
+
+/*
+ * Allows unregistering hid-asus listeners that were added with
+ * asus_hid_register_listener().
+ */
+void asus_hid_unregister_listener(struct asus_hid_listener *bdev)
+{
+ guard(spinlock_irqsave)(&asus_ref.lock);
+ list_del(&bdev->list);
+}
+EXPORT_SYMBOL_GPL(asus_hid_unregister_listener);
+
+static void do_kbd_led_set(struct led_classdev *led_cdev, int value);
+
+static void kbd_led_update_all(struct work_struct *work)
+{
+ struct asus_wmi *asus;
+ bool registered, notify;
+ int ret, value;
+
+ asus = container_of(work, struct asus_wmi, kbd_led_work);
+
+ scoped_guard(spinlock_irqsave, &asus_ref.lock) {
+ registered = asus->kbd_led_registered;
+ value = asus->kbd_led_wk;
+ notify = asus->kbd_led_notify;
+ }
+
+ if (!registered) {
+ /*
+ * This workqueue runs under asus-wmi, which means probe has
+ * completed and asus-wmi will keep running until it finishes.
+ * Therefore, we can safely register the LED without holding
+ * a spinlock.
+ */
+ ret = devm_led_classdev_register(&asus->platform_device->dev,
+ &asus->kbd_led);
+ if (!ret) {
+ scoped_guard(spinlock_irqsave, &asus_ref.lock)
+ asus->kbd_led_registered = true;
+ } else {
+ pr_warn("Failed to register keyboard backlight LED: %d\n", ret);
+ return;
+ }
+ }
+
+ if (value >= 0)
+ do_kbd_led_set(&asus->kbd_led, value);
+ if (notify) {
+ scoped_guard(spinlock_irqsave, &asus_ref.lock)
+ asus->kbd_led_notify = false;
+ led_classdev_notify_brightness_hw_changed(&asus->kbd_led, value);
+ }
+}
+
/*
* These functions actually update the LED's, and are called from a
* workqueue. By doing this as separate work rather than when the LED
@@ -1661,7 +1765,8 @@ static void kbd_led_update(struct asus_wmi *asus)
{
int ctrl_param = 0;
- ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F);
+ scoped_guard(spinlock_irqsave, &asus_ref.lock)
+ ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F);
asus_wmi_set_devstate(ASUS_WMI_DEVID_KBD_BACKLIGHT, ctrl_param, NULL);
}
@@ -1694,14 +1799,23 @@ static int kbd_led_read(struct asus_wmi *asus, int *level, int *env)
static void do_kbd_led_set(struct led_classdev *led_cdev, int value)
{
+ struct asus_hid_listener *listener;
struct asus_wmi *asus;
int max_level;
asus = container_of(led_cdev, struct asus_wmi, kbd_led);
max_level = asus->kbd_led.max_brightness;
- asus->kbd_led_wk = clamp_val(value, 0, max_level);
- kbd_led_update(asus);
+ scoped_guard(spinlock_irqsave, &asus_ref.lock)
+ asus->kbd_led_wk = clamp_val(value, 0, max_level);
+
+ if (asus->kbd_led_avail)
+ kbd_led_update(asus);
+
+ scoped_guard(spinlock_irqsave, &asus_ref.lock) {
+ list_for_each_entry(listener, &asus_ref.listeners, list)
+ listener->brightness_set(listener, asus->kbd_led_wk);
+ }
}
static int kbd_led_set(struct led_classdev *led_cdev, enum led_brightness value)
@@ -1716,10 +1830,11 @@ static int kbd_led_set(struct led_classdev *led_cdev, enum led_brightness value)
static void kbd_led_set_by_kbd(struct asus_wmi *asus, enum led_brightness value)
{
- struct led_classdev *led_cdev = &asus->kbd_led;
-
- do_kbd_led_set(led_cdev, value);
- led_classdev_notify_brightness_hw_changed(led_cdev, asus->kbd_led_wk);
+ scoped_guard(spinlock_irqsave, &asus_ref.lock) {
+ asus->kbd_led_wk = value;
+ asus->kbd_led_notify = true;
+ }
+ queue_work(asus->led_workqueue, &asus->kbd_led_work);
}
static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
@@ -1729,10 +1844,18 @@ static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
asus = container_of(led_cdev, struct asus_wmi, kbd_led);
+ scoped_guard(spinlock_irqsave, &asus_ref.lock) {
+ if (!asus->kbd_led_avail)
+ return asus->kbd_led_wk;
+ }
+
retval = kbd_led_read(asus, &value, NULL);
if (retval < 0)
return retval;
+ scoped_guard(spinlock_irqsave, &asus_ref.lock)
+ asus->kbd_led_wk = value;
+
return value;
}
@@ -1844,7 +1967,9 @@ static int camera_led_set(struct led_classdev *led_cdev,
static void asus_wmi_led_exit(struct asus_wmi *asus)
{
- led_classdev_unregister(&asus->kbd_led);
+ scoped_guard(spinlock_irqsave, &asus_ref.lock)
+ asus_ref.asus = NULL;
+
led_classdev_unregister(&asus->tpd_led);
led_classdev_unregister(&asus->wlan_led);
led_classdev_unregister(&asus->lightbar_led);
@@ -1882,22 +2007,26 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
goto error;
}
- if (!kbd_led_read(asus, &led_val, NULL) && !dmi_check_system(asus_use_hid_led_dmi_ids)) {
- pr_info("using asus-wmi for asus::kbd_backlight\n");
- asus->kbd_led_wk = led_val;
- asus->kbd_led.name = "asus::kbd_backlight";
- asus->kbd_led.flags = LED_BRIGHT_HW_CHANGED;
- asus->kbd_led.brightness_set_blocking = kbd_led_set;
- asus->kbd_led.brightness_get = kbd_led_get;
- asus->kbd_led.max_brightness = 3;
+ asus->kbd_led.name = "asus::kbd_backlight";
+ asus->kbd_led.flags = LED_BRIGHT_HW_CHANGED;
+ asus->kbd_led.brightness_set_blocking = kbd_led_set;
+ asus->kbd_led.brightness_get = kbd_led_get;
+ asus->kbd_led.max_brightness = 3;
+ asus->kbd_led_avail = !kbd_led_read(asus, &led_val, NULL);
+ INIT_WORK(&asus->kbd_led_work, kbd_led_update_all);
+ if (asus->kbd_led_avail) {
+ asus->kbd_led_wk = led_val;
if (num_rgb_groups != 0)
asus->kbd_led.groups = kbd_rgb_mode_groups;
+ } else {
+ asus->kbd_led_wk = -1;
+ }
- rv = led_classdev_register(&asus->platform_device->dev,
- &asus->kbd_led);
- if (rv)
- goto error;
+ scoped_guard(spinlock_irqsave, &asus_ref.lock) {
+ asus_ref.asus = asus;
+ if (asus->kbd_led_avail || !list_empty(&asus_ref.listeners))
+ queue_work(asus->led_workqueue, &asus->kbd_led_work);
}
if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_WIRELESS_LED)
@@ -4372,6 +4501,7 @@ static int asus_wmi_get_event_code(union acpi_object *obj)
static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus)
{
+ enum led_brightness led_value;
unsigned int key_value = 1;
bool autorelease = 1;
@@ -4388,19 +4518,22 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus)
return;
}
+ scoped_guard(spinlock_irqsave, &asus_ref.lock)
+ led_value = asus->kbd_led_wk;
+
if (code == NOTIFY_KBD_BRTUP) {
- kbd_led_set_by_kbd(asus, asus->kbd_led_wk + 1);
+ kbd_led_set_by_kbd(asus, led_value + 1);
return;
}
if (code == NOTIFY_KBD_BRTDWN) {
- kbd_led_set_by_kbd(asus, asus->kbd_led_wk - 1);
+ kbd_led_set_by_kbd(asus, led_value - 1);
return;
}
if (code == NOTIFY_KBD_BRTTOGGLE) {
- if (asus->kbd_led_wk == asus->kbd_led.max_brightness)
+ if (led_value >= asus->kbd_led.max_brightness)
kbd_led_set_by_kbd(asus, 0);
else
- kbd_led_set_by_kbd(asus, asus->kbd_led_wk + 1);
+ kbd_led_set_by_kbd(asus, led_value + 1);
return;
}
diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h
index 419491d4abca..d347cffd05d5 100644
--- a/include/linux/platform_data/x86/asus-wmi.h
+++ b/include/linux/platform_data/x86/asus-wmi.h
@@ -172,12 +172,20 @@ enum asus_ally_mcu_hack {
ASUS_WMI_ALLY_MCU_HACK_DISABLED,
};
+/* Used to notify hid-asus when asus-wmi changes keyboard backlight */
+struct asus_hid_listener {
+ struct list_head list;
+ void (*brightness_set)(struct asus_hid_listener *listener, int brightness);
+};
+
#if IS_REACHABLE(CONFIG_ASUS_WMI)
void set_ally_mcu_hack(enum asus_ally_mcu_hack status);
void set_ally_mcu_powersave(bool enabled);
int asus_wmi_get_devstate_dsts(u32 dev_id, u32 *retval);
int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param, u32 *retval);
int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, u32 *retval);
+int asus_hid_register_listener(struct asus_hid_listener *cdev);
+void asus_hid_unregister_listener(struct asus_hid_listener *cdev);
#else
static inline void set_ally_mcu_hack(enum asus_ally_mcu_hack status)
{
@@ -198,6 +206,13 @@ static inline int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1,
{
return -ENODEV;
}
+static inline int asus_hid_register_listener(struct asus_hid_listener *bdev)
+{
+ return -ENODEV;
+}
+static inline void asus_hid_unregister_listener(struct asus_hid_listener *bdev)
+{
+}
#endif
#endif /* __PLATFORM_DATA_X86_ASUS_WMI_H */
--
2.52.0
^ permalink raw reply related
* [PATCH v12 03/11] HID: asus: use same report_id in response
From: Antheas Kapenekakis @ 2026-01-22 7:50 UTC (permalink / raw)
To: platform-driver-x86, linux-input
Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires, Corentin Chary,
Luke D . Jones, Hans de Goede, Ilpo Järvinen, Denis Benato,
Antheas Kapenekakis, Denis Benato
In-Reply-To: <20260122075044.5070-1-lkml@antheas.dev>
Currently, asus_kbd_get_functions prods the device using feature
report report_id, but then is hardcoded to check the response through
FEATURE_KBD_REPORT_ID. This only works if report_id is that value
(currently true). So, use report_id in the response as well to
maintain functionality if that value changes in the future.
Reviewed-by: Denis Benato <benato.denis96@gmail.com>
Acked-by: Benjamin Tissoires <bentiss@kernel.org>
Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
---
drivers/hid/hid-asus.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index 92904b5a700c..2ff2170dc30a 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -424,7 +424,7 @@ static int asus_kbd_get_functions(struct hid_device *hdev,
if (!readbuf)
return -ENOMEM;
- ret = hid_hw_raw_request(hdev, FEATURE_KBD_REPORT_ID, readbuf,
+ ret = hid_hw_raw_request(hdev, report_id, readbuf,
FEATURE_KBD_REPORT_SIZE, HID_FEATURE_REPORT,
HID_REQ_GET_REPORT);
if (ret < 0) {
--
2.52.0
^ permalink raw reply related
* [PATCH v12 00/11] HID: asus: Fix ASUS ROG Laptop's Keyboard backlight handling
From: Antheas Kapenekakis @ 2026-01-22 7:50 UTC (permalink / raw)
To: platform-driver-x86, linux-input
Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires, Corentin Chary,
Luke D . Jones, Hans de Goede, Ilpo Järvinen, Denis Benato,
Antheas Kapenekakis
This is a two part series which does the following:
- Clean-up init sequence
- Unify backlight handling to happen under asus-wmi so that all Aura
devices have synced brightness controls and the backlight button works
properly when it is on a USB laptop keyboard instead of one w/ WMI.
For more context, see cover letter of V1. Since V5, I removed some patches
to make this easier to merge.
---
V11: https://lore.kernel.org/lkml/20260116133150.5606-1-lkml@antheas.dev/
V10: https://lore.kernel.org/lkml/20251122110032.4274-1-lkml@antheas.dev/
V9: https://lore.kernel.org/all/20251120094617.11672-1-lkml@antheas.dev/
V8: https://lore.kernel.org/all/20251101104712.8011-1-lkml@antheas.dev/
V7: https://lore.kernel.org/all/20251018101759.4089-1-lkml@antheas.dev/
V6: https://lore.kernel.org/all/20251013201535.6737-1-lkml@antheas.dev/
V5: https://lore.kernel.org/all/20250325184601.10990-1-lkml@antheas.dev/
V4: https://lore.kernel.org/lkml/20250324210151.6042-1-lkml@antheas.dev/
V3: https://lore.kernel.org/lkml/20250322102804.418000-1-lkml@antheas.dev/
V2: https://lore.kernel.org/all/20250320220924.5023-1-lkml@antheas.dev/
V1: https://lore.kernel.org/all/20250319191320.10092-1-lkml@antheas.dev/
Changes since V11:
- Rebase to review-ilpo-next
- Legacy to ID1/ID2 and reword "HID: asus: initialize additional endpoints
only for certain devices"
- in "platform/x86: asus-wmi: Add support for multiple kbd led handlers":
== -> >=
Changes since V10:
- Fix conflict with ccb61a328321 ("platform/x86: asus-wmi: use
brightness_set_blocking() for kbd led")
- We are on v6.19-rc5 mainline again
- In "HID: asus: initialize additional endpoints only for legacy devices"
additionally remove the if checks to avoid bailing if the device does not
support the init. Those inits are purely done as a precaution, we do not
care if they fail. Dismissed Denis' review as the patch diverged
- In "HID: asus: fortify keyboard handshake" do not bail if set report fails,
as noted by Benjamin, but only print a warning. Also, start printing the
report id in errors to identify them and use hid_warn for both non-fatal
errors. The changes are minor so the reviews are kept.
Changes since V9:
- No functional changes
- Rebase to review-ilpo-next
- Fix armoury series conflict by removing the file asus-wmi-leds-ids on
"remove unused keyboard backlight quirk" + imports
Dismiss Luke's review as this patch diverged
- Reword paragraph in "Add support for multiple kbd led handlers" to be
more verbose
- Use kfree in fortify patch
- Fix minor style quirks from --nonstict checkpatch run
Changes since V8:
- No functional changes
- Move legacy init patch to second, modify first patch so that their
diff is minimized
- Split "prevent binding to all HID devices on ROG" into two patches:
- moving backlight initialization into probe
- early exit to skip ->init check and rename
- Remove skipping vendor fixups for non-vendor devices. It is not possible
to read usages before the report fixups are applied, so it did not work
- In that patch, reword a comment to be single line and make is_vendor a bool
- Dismiss Luke's tags from "Add support for multiple kbd led handlers" as it
has drifted too far since he reviewed/tested it.
Changes since V7:
- Readd legacy init quirk for Dennis
- Remove HID_QUIRK_INPUT_PER_APP as a courtesy to asusctl
- Fix warning due to enum_backlight receiving negative values
Changes since V6:
- Split initialization refactor into three patches, update commit text
to be clearer in what it does
- Replace spinlock accesses with guard and scoped guard in all patches
- Add missing includes mentioned by Ilpo
- Reflow, tweak comment in prevent binding to all HID devices on ROG
- Replace asus_ref.asus with local reference in all patches
- Add missing kernel doc comments
- Other minor nits from Ilpo
- User reported warning due to scheduling work while holding a spinlock.
Restructure patch for multiple handlers to limit when spinlock is held to
variable access only. In parallel, setup a workqueue to handle registration
of led device and setting brightness. This is required as registering the
led device triggers kbd_led_get which needs to hold the spinlock to
protect the led_wk value. The workqueue is also required for the hid
event passthrough to avoid scheduling work while holding the spinlock.
Apply the workqueue to wmi brightness buttons as well, as that was
omitted before this series and WMI access was performed.
- On "HID: asus: prevent binding to all HID devices on ROG", rename
quirk HANDLE_GENERIC to SKIP_REPORT_FIXUP and only skip report fixup.
This allows other quirks to apply (applies quirk that fixes keyboard
being named as a pointer device).
Changes since V5:
- It's been a long time
- Remove addition of RGB as that had some comments I need to work on
- Remove folio patch (already merged)
- Remove legacy fix patch 11 from V4. There is a small chance that
without this patch, some old NKEY keyboards might not respond to
RGB commands according to Luke, but the kernel driver does not do
RGB currently. The 0x5d init is done by Armoury crate software in
Windows. If an issue is found, we can re-add it or just remove patches
1/2 before merging. However, init could use the cleanup.
Changes since V4:
- Fix KConfig (reported by kernel robot)
- Fix Ilpo's nits, if I missed anything lmk
Changes since V3:
- Add initializer for 0x5d for old NKEY keyboards until it is verified
that it is not needed for their media keys to function.
- Cover init in asus-wmi with spinlock as per Hans
- If asus-wmi registers WMI handler with brightness, init the brightness
in USB Asus keyboards, per Hans.
- Change hid handler name to asus-UNIQ:rgb:peripheral to match led class
- Fix oops when unregistering asus-wmi by moving unregister outside of
the spin lock (but after the asus reference is set to null)
Changes since V2:
- Check lazy init succeds in asus-wmi before setting register variable
- make explicit check in asus_hid_register_listener for listener existing
to avoid re-init
- rename asus_brt to asus_hid in most places and harmonize everything
- switch to a spinlock instead of a mutex to avoid kernel ooops
- fixup hid device quirks to avoid multiple RGB devices while still exposing
all input vendor devices. This includes moving rgb init to probe
instead of the input_configured callbacks.
- Remove fan key (during retest it appears to be 0xae that is already
supported by hid-asus)
- Never unregister asus::kbd_backlight while asus-wmi is active, as that
- removes fds from userspace and breaks backlight functionality. All
- current mainline drivers do not support backlight hotplugging, so most
userspace software (e.g., KDE, UPower) is built with that assumption.
For the Ally, since it disconnects its controller during sleep, this
caused the backlight slider to not work in KDE.
Changes since V1:
- Add basic RGB support on hid-asus, (Z13/Ally) tested in KDE/Z13
- Fix ifdef else having an invalid signature (reported by kernel robot)
- Restore input arguments to init and keyboard function so they can
be re-used for RGB controls.
- Remove Z13 delay (it did not work to fix the touchpad) and replace it
with a HID_GROUP_GENERIC quirk to allow hid-multitouch to load. Squash
keyboard rename into it.
- Unregister brightness listener before removing work queue to avoid
a race condition causing corruption
- Remove spurious mutex unlock in asus_brt_event
- Place mutex lock in kbd_led_set after LED_UNREGISTERING check to avoid
relocking the mutex and causing a deadlock when unregistering leds
- Add extra check during unregistering to avoid calling unregister when
no led device is registered.
- Temporarily HID_QUIRK_INPUT_PER_APP from the ROG endpoint as it causes
the driver to create 4 RGB handlers per device. I also suspect some
extra events sneak through (KDE had the @@@@@@).
Antheas Kapenekakis (11):
HID: asus: simplify RGB init sequence
HID: asus: initialize additional endpoints only for certain devices
HID: asus: use same report_id in response
HID: asus: fortify keyboard handshake
HID: asus: move vendor initialization to probe
HID: asus: early return for ROG devices
platform/x86: asus-wmi: Add support for multiple kbd led handlers
HID: asus: listen to the asus-wmi brightness device instead of
creating one
platform/x86: asus-wmi: remove unused keyboard backlight quirk
platform/x86: asus-wmi: add keyboard brightness event handler
HID: asus: add support for the asus-wmi brightness handler
drivers/hid/hid-asus.c | 214 ++++++++---------
drivers/platform/x86/asus-wmi.c | 223 +++++++++++++++---
.../platform_data/x86/asus-wmi-leds-ids.h | 50 ----
include/linux/platform_data/x86/asus-wmi.h | 28 +++
4 files changed, 325 insertions(+), 190 deletions(-)
delete mode 100644 include/linux/platform_data/x86/asus-wmi-leds-ids.h
base-commit: 2ccbdb612d0d95f25c38189b83666ff0fb2bfb47
--
2.52.0
^ permalink raw reply
* [PATCH v12 01/11] HID: asus: simplify RGB init sequence
From: Antheas Kapenekakis @ 2026-01-22 7:50 UTC (permalink / raw)
To: platform-driver-x86, linux-input
Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires, Corentin Chary,
Luke D . Jones, Hans de Goede, Ilpo Järvinen, Denis Benato,
Antheas Kapenekakis
In-Reply-To: <20260122075044.5070-1-lkml@antheas.dev>
Currently, RGB initialization forks depending on whether a device is
NKEY. However, in reality both initialization forks are the same, other
than the NKEY initialization initializing the LED_REPORT_ID1,
LED_REPORT_ID2 endpoints, and the non-NKEY initialization having a
functionality check which is skipped for the NKEY path.
Therefore, merge the if blocks, gate the ID1/ID2 initializations
behind the NKEY quirk instead, and introduce the functionality check
for NKEY devices (it is supported by them).
There should be no functional change with this patch.
Acked-by: Benjamin Tissoires <bentiss@kernel.org>
Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
---
drivers/hid/hid-asus.c | 52 ++++++++++++++++++------------------------
1 file changed, 22 insertions(+), 30 deletions(-)
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index 472bca54642b..323e6302bac5 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -639,13 +639,20 @@ static int asus_kbd_register_leds(struct hid_device *hdev)
unsigned char kbd_func;
int ret;
- if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD) {
- /* Initialize keyboard */
- ret = asus_kbd_init(hdev, FEATURE_KBD_REPORT_ID);
- if (ret < 0)
- return ret;
+ ret = asus_kbd_init(hdev, FEATURE_KBD_REPORT_ID);
+ if (ret < 0)
+ return ret;
- /* The LED endpoint is initialised in two HID */
+ /* Get keyboard functions */
+ ret = asus_kbd_get_functions(hdev, &kbd_func, FEATURE_KBD_REPORT_ID);
+ if (ret < 0)
+ return ret;
+
+ /* Check for backlight support */
+ if (!(kbd_func & SUPPORT_KBD_BACKLIGHT))
+ return -ENODEV;
+
+ if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD) {
ret = asus_kbd_init(hdev, FEATURE_KBD_LED_REPORT_ID1);
if (ret < 0)
return ret;
@@ -653,34 +660,19 @@ static int asus_kbd_register_leds(struct hid_device *hdev)
ret = asus_kbd_init(hdev, FEATURE_KBD_LED_REPORT_ID2);
if (ret < 0)
return ret;
+ }
- if (dmi_match(DMI_PRODUCT_FAMILY, "ProArt P16")) {
- ret = asus_kbd_disable_oobe(hdev);
- if (ret < 0)
- return ret;
- }
-
- if (drvdata->quirks & QUIRK_ROG_ALLY_XPAD) {
- intf = to_usb_interface(hdev->dev.parent);
- udev = interface_to_usbdev(intf);
- validate_mcu_fw_version(hdev,
- le16_to_cpu(udev->descriptor.idProduct));
- }
-
- } else {
- /* Initialize keyboard */
- ret = asus_kbd_init(hdev, FEATURE_KBD_REPORT_ID);
- if (ret < 0)
- return ret;
-
- /* Get keyboard functions */
- ret = asus_kbd_get_functions(hdev, &kbd_func, FEATURE_KBD_REPORT_ID);
+ if (dmi_match(DMI_PRODUCT_FAMILY, "ProArt P16")) {
+ ret = asus_kbd_disable_oobe(hdev);
if (ret < 0)
return ret;
+ }
- /* Check for backlight support */
- if (!(kbd_func & SUPPORT_KBD_BACKLIGHT))
- return -ENODEV;
+ if (drvdata->quirks & QUIRK_ROG_ALLY_XPAD) {
+ intf = to_usb_interface(hdev->dev.parent);
+ udev = interface_to_usbdev(intf);
+ validate_mcu_fw_version(hdev,
+ le16_to_cpu(udev->descriptor.idProduct));
}
drvdata->kbd_backlight = devm_kzalloc(&hdev->dev,
--
2.52.0
^ permalink raw reply related
* [PATCH v12 02/11] HID: asus: initialize additional endpoints only for certain devices
From: Antheas Kapenekakis @ 2026-01-22 7:50 UTC (permalink / raw)
To: platform-driver-x86, linux-input
Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires, Corentin Chary,
Luke D . Jones, Hans de Goede, Ilpo Järvinen, Denis Benato,
Antheas Kapenekakis
In-Reply-To: <20260122075044.5070-1-lkml@antheas.dev>
Currently, ID1/ID2 initializations are performed for all NKEY devices.
However, ID1 initializations are only required for RGB control and are
only supported for RGB capable devices. ID2 initializations are only
required for initializing the Anime display endpoint which is only
supported on devices with an Anime display. Both of these
initializations are for functionality that is not present on this driver
and are performed for devices which might not support them.
At the same time, there are older NKEY devices that have only been
tested with these initializations in the kernel and it is not possible
to recheck them. There is a possibility that especially with the ID1
initialization, certain laptop models might have their shortcuts stop
working (currently unproven).
To avoid sending unnecessary commands, change to only initialize ID1/ID2
for those NKEY devices suspected to be problematic without them by
introducing a quirk for them and replacing the NKEY quirk in the block
that performs the inits with that. Therefore, new devices that do not
need (and some do not support) these initializations will not have
them performed.
In addition, as these initializations might not be supported by the
affected devices, change the function to not bail if they fail.
Acked-by: Benjamin Tissoires <bentiss@kernel.org>
Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
---
drivers/hid/hid-asus.c | 16 ++++++----------
1 file changed, 6 insertions(+), 10 deletions(-)
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index 323e6302bac5..92904b5a700c 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -90,6 +90,7 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
#define QUIRK_ROG_NKEY_KEYBOARD BIT(11)
#define QUIRK_ROG_CLAYMORE_II_KEYBOARD BIT(12)
#define QUIRK_ROG_ALLY_XPAD BIT(13)
+#define QUIRK_ROG_NKEY_ID1ID2_INIT BIT(14)
#define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \
QUIRK_NO_INIT_REPORTS | \
@@ -652,14 +653,9 @@ static int asus_kbd_register_leds(struct hid_device *hdev)
if (!(kbd_func & SUPPORT_KBD_BACKLIGHT))
return -ENODEV;
- if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD) {
- ret = asus_kbd_init(hdev, FEATURE_KBD_LED_REPORT_ID1);
- if (ret < 0)
- return ret;
-
- ret = asus_kbd_init(hdev, FEATURE_KBD_LED_REPORT_ID2);
- if (ret < 0)
- return ret;
+ if (drvdata->quirks & QUIRK_ROG_NKEY_ID1ID2_INIT) {
+ asus_kbd_init(hdev, FEATURE_KBD_LED_REPORT_ID1);
+ asus_kbd_init(hdev, FEATURE_KBD_LED_REPORT_ID2);
}
if (dmi_match(DMI_PRODUCT_FAMILY, "ProArt P16")) {
@@ -1376,10 +1372,10 @@ static const struct hid_device_id asus_devices[] = {
QUIRK_USE_KBD_BACKLIGHT },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD),
- QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD },
+ QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD | QUIRK_ROG_NKEY_ID1ID2_INIT },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD2),
- QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD },
+ QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD | QUIRK_ROG_NKEY_ID1ID2_INIT },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
USB_DEVICE_ID_ASUSTEK_ROG_Z13_LIGHTBAR),
QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD },
--
2.52.0
^ permalink raw reply related
* Re: [PATCH] arm64: dts: qcom: milos-fairphone-fp6: Add Hall Effect sensor
From: Luca Weiss @ 2026-01-22 7:48 UTC (permalink / raw)
To: Dmitry Torokhov, Luca Weiss
Cc: Dmitry Baryshkov, Konrad Dybcio, Bjorn Andersson, Konrad Dybcio,
Rob Herring, Krzysztof Kozlowski, Conor Dooley,
~postmarketos/upstreaming, phone-devel, linux-arm-msm, devicetree,
linux-kernel, linux-input
In-Reply-To: <t4yjnuty7tmvs4vqzm4vdid7oowicy7hcnmqmu6nqtit3yru55@zpo6kprnarth>
On Wed Jan 21, 2026 at 9:06 PM CET, Dmitry Torokhov wrote:
> On Wed, Jan 21, 2026 at 09:07:44AM +0100, Luca Weiss wrote:
>> On Wed Jan 21, 2026 at 12:05 AM CET, Dmitry Baryshkov wrote:
>> > On Mon, Jan 19, 2026 at 04:52:23PM +0100, Luca Weiss wrote:
>> >> On Mon Jan 19, 2026 at 3:41 PM CET, Konrad Dybcio wrote:
>> >> > On 1/16/26 3:22 PM, Luca Weiss wrote:
>> >> >> Add a node for the Hall Effect sensor, used to detect whether the Flip
>> >> >> Cover is closed or not.
>> >> >>
>> >> >> The sensor is powered through vreg_l10b, so let's put a
>> >> >> regulator-always-on on that to make sure the sensor gets power.
>> >> >
>> >> > Is there anything else on L10B? Can we turn it off if the hall sensor
>> >> > is e.g. user-disabled?
>> >>
>> >> It's the voltage source for pull-up of sensor I2C bus (so
>> >> ADSP-managed?), DVDD for amplifiers and VDD for a most sensors like
>> >> the gyro.
>> >>
>> >> So realistically, it'll probably be (nearly) always on anyways. And I
>> >> don't want to shave another yak by adding vdd support to gpio-keys...
>> >
>> > Why? If it is exactly what happens on the board: the device producing
>> > GPIO events _is_ powered via a vdd. Added Input maintainer / list to cc.
>>
>> Yes, the hall sensor which is connected to the GPIO on the SoC, has an
>> extra VDD input which needs to be on in order for the Hall-effect sensor
>> to be on.
>>
>> See page 133 "HALL" in the center of the page
>> https://www.fairphone.com/wp-content/uploads/2025/08/Fairphone-Gen.-6_-Information-on-how-to-repair-dispose-of-and-recycle-EN-NL-FR-DE.pdf
>>
>> The IC is OCH166AEV4AD where VDD is (as expected) "Power Supply Input":
>> https://www.orient-chip.com/Public/Uploads/uploadfile/files/20231014/1OCH166Adatasheet202203221.pdf
>
> If we add regulator support to gpio-keys do we expect it to be
> per-gpio/per-key? Or we'd recommend splitting into several instances of
> gpio-keys so that there is on set of supplies per gpio-keys device?
In my opinion it would fit in this case in the event-hall-sensor node,
that next to gpios = <&tlmm 70 GPIO_ACTIVE_LOW> we get a
vdd-supply = <&vreg_l10b>.
Regards
Luca
>
> Thanks.
^ permalink raw reply
* [PATCH] Input: i8042 - add quirk for ASUS Zenbook UX425QA_UM425QA
From: feng @ 2026-01-22 1:39 UTC (permalink / raw)
To: dtor; +Cc: linux-input, linux-kernel, feng
The ASUS Zenbook UX425QA_UM425QA fails to initialize the keyboard after a
cold boot.
A quirk already exists for "ZenBook UX425", but some Zenbooks report "Zenbook" with a lowercase 'b'.
Since DMI matching is case-sensitive, the existing quirk is not applied to these "extra special" Zenbooks.
Testing confirms that this model needs the same quirks as the ZenBook UX425 variants.
Signed-off-by: feng <alec.jiang@gmail.com>
---
drivers/input/serio/i8042-acpipnpio.h | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/input/serio/i8042-acpipnpio.h b/drivers/input/serio/i8042-acpipnpio.h
index 654771275..b34d922a9 100644
--- a/drivers/input/serio/i8042-acpipnpio.h
+++ b/drivers/input/serio/i8042-acpipnpio.h
@@ -115,6 +115,16 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = {
},
.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_NEVER)
},
+ /* ASUS Zenbook UX425QA_UM425QA
+ * Some Zenbooks report "Zenbook" with a lowercase b.
+ */
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Zenbook UX425QA_UM425QA"),
+ },
+ .driver_data = (void *)(SERIO_QUIRK_PROBE_DEFER | SERIO_QUIRK_RESET_NEVER)
+ },
{
/* ASUS ZenBook UX425UA/QA */
.matches = {
--
2.34.1
^ permalink raw reply related
* Re: [PATCH v5 1/2] dt-bindings: touchscreen: trivial-touch: Drop 'interrupts' requirement for old Ilitek
From: Marek Vasut @ 2026-01-22 0:22 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: linux-input, Frank Li, Krzysztof Kozlowski, Conor Dooley,
Job Noorman, Krzysztof Kozlowski, Rob Herring, devicetree,
linux-kernel, linux-renesas-soc
In-Reply-To: <kzt3myrtfigzvtuw62eqts5tjfwvlueuzifk7dsm5jvawztsle@5wyzecmltldb>
On 1/22/26 1:19 AM, Dmitry Torokhov wrote:
> On Thu, Jan 22, 2026 at 12:06:46AM +0100, Marek Vasut wrote:
>> The old Ilitek touch controllers V3 and V6 can operate without
>> interrupt line, in polling mode. Drop the 'interrupts' property
>> requirement for those four controllers. To avoid overloading the
>> trivial-touch, fork the old Ilitek V3/V6 touch controller binding
>> into separate document.
>>
>> Reviewed-by: Frank Li <Frank.Li@nxp.com>
>> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
>> Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
>
> Applied the lot, thank you.
Likewise, thank you.
^ permalink raw reply
* Re: [PATCH v5 1/2] dt-bindings: touchscreen: trivial-touch: Drop 'interrupts' requirement for old Ilitek
From: Dmitry Torokhov @ 2026-01-22 0:19 UTC (permalink / raw)
To: Marek Vasut
Cc: linux-input, Frank Li, Krzysztof Kozlowski, Conor Dooley,
Job Noorman, Krzysztof Kozlowski, Rob Herring, devicetree,
linux-kernel, linux-renesas-soc
In-Reply-To: <20260121230736.114623-1-marek.vasut+renesas@mailbox.org>
On Thu, Jan 22, 2026 at 12:06:46AM +0100, Marek Vasut wrote:
> The old Ilitek touch controllers V3 and V6 can operate without
> interrupt line, in polling mode. Drop the 'interrupts' property
> requirement for those four controllers. To avoid overloading the
> trivial-touch, fork the old Ilitek V3/V6 touch controller binding
> into separate document.
>
> Reviewed-by: Frank Li <Frank.Li@nxp.com>
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
> Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
Applied the lot, thank you.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v3] Input: novatek-nvt-ts - drop wake_type check
From: Dmitry Torokhov @ 2026-01-22 0:14 UTC (permalink / raw)
To: Gianluca Boiano; +Cc: linux-input, hdegoede
In-Reply-To: <20260122001040.76869-1-morf3089@gmail.com>
On Thu, Jan 22, 2026 at 01:10:40AM +0100, Gianluca Boiano wrote:
> The wake_type parameter from touchscreen registers is not used for
> anything functional - the driver only validates that it matches a
> hardcoded expected value per chip variant. This causes probe to fail
> on touchscreens that report a different wake_type despite being
> otherwise compatible.
>
> Drop the wake_type check and the associated chip data member to allow
> the existing compatibles to work with more touchscreen variants.
>
> Signed-off-by: Gianluca Boiano <morf3089@gmail.com>
I think this deserves "Suggested-by:" tag. I'll add it unless there are
objections...
> ---
> Changes in v3:
> - Completely reworked per Hans de Goede's suggestion: instead of adding
> a new compatible for the e7t variant, simply drop the wake_type check
> entirely since it serves no functional purpose
> - Dropped dt-bindings patch (no longer needed)
>
> Changes in v2:
> - Removed Closes: tag referencing downstream repository
>
> drivers/input/touchscreen/novatek-nvt-ts.c | 5 -----
> 1 file changed, 5 deletions(-)
>
> diff --git a/drivers/input/touchscreen/novatek-nvt-ts.c b/drivers/input/touchscreen/novatek-nvt-ts.c
> index 44b58e0dc1ad..3e6e2ee0ba8f 100644
> --- a/drivers/input/touchscreen/novatek-nvt-ts.c
> +++ b/drivers/input/touchscreen/novatek-nvt-ts.c
> @@ -27,7 +27,6 @@
> #define NVT_TS_PARAMS_MAX_TOUCH 0x09
> #define NVT_TS_PARAMS_MAX_BUTTONS 0x0a
> #define NVT_TS_PARAMS_IRQ_TYPE 0x0b
> -#define NVT_TS_PARAMS_WAKE_TYPE 0x0c
> #define NVT_TS_PARAMS_CHIP_ID 0x0e
> #define NVT_TS_PARAMS_SIZE 0x0f
>
> @@ -49,7 +48,6 @@ static const int nvt_ts_irq_type[4] = {
> };
>
> struct nvt_ts_i2c_chip_data {
> - u8 wake_type;
> u8 chip_id;
> };
>
> @@ -261,7 +259,6 @@ static int nvt_ts_probe(struct i2c_client *client)
> if (width > NVT_TS_MAX_SIZE || height >= NVT_TS_MAX_SIZE ||
> data->max_touches > NVT_TS_MAX_TOUCHES ||
> irq_type >= ARRAY_SIZE(nvt_ts_irq_type) ||
> - data->buf[NVT_TS_PARAMS_WAKE_TYPE] != chip->wake_type ||
> data->buf[NVT_TS_PARAMS_CHIP_ID] != chip->chip_id) {
> dev_err(dev, "Unsupported touchscreen parameters: %*ph\n",
> NVT_TS_PARAMS_SIZE, data->buf);
> @@ -314,12 +311,10 @@ static int nvt_ts_probe(struct i2c_client *client)
> }
>
> static const struct nvt_ts_i2c_chip_data nvt_nt11205_ts_data = {
> - .wake_type = 0x05,
> .chip_id = 0x05,
> };
>
> static const struct nvt_ts_i2c_chip_data nvt_nt36672a_ts_data = {
> - .wake_type = 0x01,
> .chip_id = 0x08,
> };
>
Thanks.
--
Dmitry
^ permalink raw reply
* [PATCH v3] Input: novatek-nvt-ts - drop wake_type check
From: Gianluca Boiano @ 2026-01-22 0:10 UTC (permalink / raw)
To: linux-input; +Cc: hdegoede, dmitry.torokhov, Gianluca Boiano
In-Reply-To: <20260121-fervent-wren-1730d5@quoll>
The wake_type parameter from touchscreen registers is not used for
anything functional - the driver only validates that it matches a
hardcoded expected value per chip variant. This causes probe to fail
on touchscreens that report a different wake_type despite being
otherwise compatible.
Drop the wake_type check and the associated chip data member to allow
the existing compatibles to work with more touchscreen variants.
Signed-off-by: Gianluca Boiano <morf3089@gmail.com>
---
Changes in v3:
- Completely reworked per Hans de Goede's suggestion: instead of adding
a new compatible for the e7t variant, simply drop the wake_type check
entirely since it serves no functional purpose
- Dropped dt-bindings patch (no longer needed)
Changes in v2:
- Removed Closes: tag referencing downstream repository
drivers/input/touchscreen/novatek-nvt-ts.c | 5 -----
1 file changed, 5 deletions(-)
diff --git a/drivers/input/touchscreen/novatek-nvt-ts.c b/drivers/input/touchscreen/novatek-nvt-ts.c
index 44b58e0dc1ad..3e6e2ee0ba8f 100644
--- a/drivers/input/touchscreen/novatek-nvt-ts.c
+++ b/drivers/input/touchscreen/novatek-nvt-ts.c
@@ -27,7 +27,6 @@
#define NVT_TS_PARAMS_MAX_TOUCH 0x09
#define NVT_TS_PARAMS_MAX_BUTTONS 0x0a
#define NVT_TS_PARAMS_IRQ_TYPE 0x0b
-#define NVT_TS_PARAMS_WAKE_TYPE 0x0c
#define NVT_TS_PARAMS_CHIP_ID 0x0e
#define NVT_TS_PARAMS_SIZE 0x0f
@@ -49,7 +48,6 @@ static const int nvt_ts_irq_type[4] = {
};
struct nvt_ts_i2c_chip_data {
- u8 wake_type;
u8 chip_id;
};
@@ -261,7 +259,6 @@ static int nvt_ts_probe(struct i2c_client *client)
if (width > NVT_TS_MAX_SIZE || height >= NVT_TS_MAX_SIZE ||
data->max_touches > NVT_TS_MAX_TOUCHES ||
irq_type >= ARRAY_SIZE(nvt_ts_irq_type) ||
- data->buf[NVT_TS_PARAMS_WAKE_TYPE] != chip->wake_type ||
data->buf[NVT_TS_PARAMS_CHIP_ID] != chip->chip_id) {
dev_err(dev, "Unsupported touchscreen parameters: %*ph\n",
NVT_TS_PARAMS_SIZE, data->buf);
@@ -314,12 +311,10 @@ static int nvt_ts_probe(struct i2c_client *client)
}
static const struct nvt_ts_i2c_chip_data nvt_nt11205_ts_data = {
- .wake_type = 0x05,
.chip_id = 0x05,
};
static const struct nvt_ts_i2c_chip_data nvt_nt36672a_ts_data = {
- .wake_type = 0x01,
.chip_id = 0x08,
};
--
2.52.0
^ permalink raw reply related
* Re: [PATCH 2/2] input: touchscreen: novatek-nvt-ts: Add support for NT36672A e7t variant
From: Gianluca Boiano @ 2026-01-22 0:09 UTC (permalink / raw)
To: hdegoede; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <b4113f8c-0fbd-4a96-9cf6-9675f837ac91@kernel.org>
Hi Hans,
Thanks for the suggestion. You're right that removing code is better than
adding more variants.
I've sent v3 which drops the wake_type check entirely, as you suggested.
Gianluca
^ permalink raw reply
* [PATCH 2/2] Input: ili210x - convert to disable_valid_irq scoped guard
From: Marek Vasut @ 2026-01-21 23:23 UTC (permalink / raw)
To: linux-input
Cc: Marek Vasut, Peter Zijlstra (Intel), Cheng-Yang Chou,
Dmitry Torokhov, Frank Li, Geert Uytterhoeven, Jinjie Ruan,
Krzysztof Kozlowski, Marc Zyngier, Sebastian Andrzej Siewior,
Thomas Gleixner, linux-kernel, linux-renesas-soc
In-Reply-To: <20260121232522.154771-1-marek.vasut+renesas@mailbox.org>
Use disable_valid_irq scoped guard to simplify the code and
deduplicate the polling and IRQ driver case. No functional
change.
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
---
Cc: "Peter Zijlstra (Intel)" <peterz@infradead.org>
Cc: Cheng-Yang Chou <yphbchou0911@gmail.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Frank Li <Frank.Li@nxp.com>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Jinjie Ruan <ruanjinjie@huawei.com>
Cc: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: Thomas Gleixner <tglx@kernel.org>
Cc: linux-input@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-renesas-soc@vger.kernel.org
---
drivers/input/touchscreen/ili210x.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c
index 3bf524a6ee204..70abbd675bb01 100644
--- a/drivers/input/touchscreen/ili210x.c
+++ b/drivers/input/touchscreen/ili210x.c
@@ -893,10 +893,7 @@ static ssize_t ili210x_firmware_update_store(struct device *dev,
* the touch controller to disable the IRQs during update, so we have
* to do it this way here.
*/
- if (client->irq > 0) {
- guard(disable_irq)(&client->irq);
- error = ili210x_firmware_update(dev, fwbuf, ac_end, df_end);
- } else {
+ scoped_guard(disable_valid_irq, &client->irq) {
error = ili210x_firmware_update(dev, fwbuf, ac_end, df_end);
}
--
2.51.0
^ permalink raw reply related
* [PATCH 1/2] linux/interrupt.h: allow "guard" notation to disable and reenable IRQ with valid IRQ check
From: Marek Vasut @ 2026-01-21 23:23 UTC (permalink / raw)
To: linux-input
Cc: Marek Vasut, Peter Zijlstra (Intel), Cheng-Yang Chou,
Dmitry Torokhov, Frank Li, Geert Uytterhoeven, Jinjie Ruan,
Krzysztof Kozlowski, Marc Zyngier, Sebastian Andrzej Siewior,
Thomas Gleixner, linux-kernel, linux-renesas-soc
Introduce disable_valid_irq scoped guard. This is an extension
of disable_irq scoped guard, which disables and enables IRQs
around a scope. The disable_valid_irq scoped guard does almost
the same, except it handles the case where IRQ is not valid,
in which case it does not do anything. This is meant to be used
by for example touch controller drivers, which can do both IRQ
driven and polling mode of operation, and this makes their code
slighly simpler.
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
---
Cc: "Peter Zijlstra (Intel)" <peterz@infradead.org>
Cc: Cheng-Yang Chou <yphbchou0911@gmail.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Frank Li <Frank.Li@nxp.com>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Jinjie Ruan <ruanjinjie@huawei.com>
Cc: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: Thomas Gleixner <tglx@kernel.org>
Cc: linux-input@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-renesas-soc@vger.kernel.org
---
include/linux/interrupt.h | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 00c01b0a43be1..becbeab4a7473 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -242,6 +242,21 @@ extern void irq_wake_thread(unsigned int irq, void *dev_id);
DEFINE_LOCK_GUARD_1(disable_irq, int,
disable_irq(*_T->lock), enable_irq(*_T->lock))
+static inline void disable_valid_irq(unsigned int irq)
+{
+ if (irq > 0)
+ disable_irq(irq);
+}
+
+static inline void enable_valid_irq(unsigned int irq)
+{
+ if (irq > 0)
+ enable_irq(irq);
+}
+
+DEFINE_LOCK_GUARD_1(disable_valid_irq, int,
+ disable_valid_irq(*_T->lock), enable_valid_irq(*_T->lock))
+
extern void disable_nmi_nosync(unsigned int irq);
extern void disable_percpu_nmi(unsigned int irq);
extern void enable_nmi(unsigned int irq);
--
2.51.0
^ permalink raw reply related
* Re: [PATCH v4 3/3] Input: ili210x - add support for polling mode
From: Marek Vasut @ 2026-01-21 23:12 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: linux-input, Conor Dooley, Frank Li, Job Noorman,
Krzysztof Kozlowski, Rob Herring, devicetree, linux-kernel,
linux-renesas-soc
In-Reply-To: <tuvidadi4sezm5b3ydvuie6pcxpf7pw2jrysafwdhpmtz6vjxl@o4zqdnjxkaed>
On 1/21/26 11:53 PM, Dmitry Torokhov wrote:
> On Wed, Jan 21, 2026 at 11:42:55PM +0100, Marek Vasut wrote:
>> On 1/21/26 6:23 AM, Dmitry Torokhov wrote:
>>> On Tue, Jan 20, 2026 at 11:50:53PM +0100, Marek Vasut wrote:
>>>> On 1/20/26 7:31 PM, Dmitry Torokhov wrote:
>>>>> Hi Marek,
>>>>>
>>>>> On Sat, Jan 17, 2026 at 01:12:04AM +0100, Marek Vasut wrote:
>>>>>> @@ -860,16 +893,12 @@ static ssize_t ili210x_firmware_update_store(struct device *dev,
>>>>>> * the touch controller to disable the IRQs during update, so we have
>>>>>> * to do it this way here.
>>>>>> */
>>>>>> - scoped_guard(disable_irq, &client->irq) {
>>>>>> - dev_dbg(dev, "Firmware update started, firmware=%s\n", fwname);
>>>>>> -
>>>>>> - ili210x_hardware_reset(priv->reset_gpio);
>>>>>> -
>>>>>> - error = ili210x_do_firmware_update(priv, fwbuf, ac_end, df_end);
>>>>>> -
>>>>>> - ili210x_hardware_reset(priv->reset_gpio);
>>>>>> -
>>>>>> - dev_dbg(dev, "Firmware update ended, error=%i\n", error);
>>>>>> + if (client->irq > 0) {
>>>>>> + scoped_guard(disable_irq, &client->irq) {
>>>>>> + error = ili210x_firmware_update_noirq(dev, fwbuf, ac_end, df_end);
>>>>>> + }
>>>>>
>>>>> You already have a scope here, no need to establish a new one:
>>>>>
>>>>> guard(disable_irq)(&client->irq);
>>>>> error = ili210x_firmware_update_noirq(dev, fwbuf, ac_end, df_end);
>>>>
>>>> This part ^ I do not understand. If there is no IRQ defined in DT, I need to
>>>> call ili210x_firmware_update_noirq() without the guard because I cannot
>>>> disable_irq() with client->irq < 0, else I need to call
>>>> ili210x_firmware_update_noirq() within the scoped_guard() to disable IRQs to
>>>> avoid spurious IRQs that would interfere with the firmware update ?
>>>
>>> You do not need to use scoped_guard() because you already define a scope
>>> in your if statement:
>>>
>>> if (client->irq > 0) {
>>> guard(disable_irq)(&client->irq);
>>> error = ili210x_firmware_update_noirq(dev, fwbuf, ac_end, df_end);
>>> } else {
>>> error = ili210x_firmware_update_noirq(dev, fwbuf, ac_end, df_end);
>>> }
>>>
>>> This is sill a bit awkward. Maybe we could add to interrupt.h
>>
>> Let me do the part above in V5 , and then the part below as a separate
>> follow up patch/series. I already added the later in tree so it won't be
>> lost. Does that work for you ?
>
> It does, thanks.
OK, V5 is out, the disable_valid_interrupt guard part is coming shortly.
^ permalink raw reply
* [PATCH v5 2/2] Input: ili210x - add support for polling mode
From: Marek Vasut @ 2026-01-21 23:06 UTC (permalink / raw)
To: linux-input
Cc: Marek Vasut, Frank Li, Conor Dooley, Dmitry Torokhov, Job Noorman,
Krzysztof Kozlowski, Rob Herring, devicetree, linux-kernel,
linux-renesas-soc
In-Reply-To: <20260121230736.114623-1-marek.vasut+renesas@mailbox.org>
There are designs incorporating Ilitek ILI2xxx touch controller that
do not connect interrupt pin, for example Waveshare 13.3" DSI display.
To support such systems use polling mode for the input device when I2C
client does not have interrupt assigned to it.
Factor out ili210x_firmware_update_noirq() to allow conditional scoped
guard around this code. The scoped guard has to be applied only in case
the IRQ line is connected, and not applied otherwise.
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
---
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Frank Li <Frank.Li@nxp.com>
Cc: Job Noorman <job@noorman.info>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Rob Herring <robh@kernel.org>
Cc: devicetree@vger.kernel.org
Cc: linux-input@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-renesas-soc@vger.kernel.org
---
V2: Test client->irq > 0 for IRQ presence
V3: - Rebase on dev_err_probe() conversion
- Fix if (client->irq > 0) in ili210x_firmware_update_store()
V4: No change
V5: - Add RB from Frank
- Rename ili210x_firmware_update_noirq() to ili210x_firmware_update()
- Change scoped_guard() to guard()
---
drivers/input/touchscreen/ili210x.c | 75 +++++++++++++++++++++--------
1 file changed, 55 insertions(+), 20 deletions(-)
diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c
index 264eee3e61d0a..3bf524a6ee204 100644
--- a/drivers/input/touchscreen/ili210x.c
+++ b/drivers/input/touchscreen/ili210x.c
@@ -327,9 +327,8 @@ static bool ili210x_report_events(struct ili210x *priv, u8 *touchdata)
return contact;
}
-static irqreturn_t ili210x_irq(int irq, void *irq_data)
+static void ili210x_process_events(struct ili210x *priv)
{
- struct ili210x *priv = irq_data;
struct i2c_client *client = priv->client;
const struct ili2xxx_chip *chip = priv->chip;
u8 touchdata[ILI210X_DATA_SIZE] = { 0 };
@@ -356,8 +355,22 @@ static irqreturn_t ili210x_irq(int irq, void *irq_data)
usleep_range(time_delta, time_delta + 1000);
}
} while (!priv->stop && keep_polling);
+}
+
+static irqreturn_t ili210x_irq(int irq, void *irq_data)
+{
+ struct ili210x *priv = irq_data;
+
+ ili210x_process_events(priv);
return IRQ_HANDLED;
+};
+
+static void ili210x_work_i2c_poll(struct input_dev *input)
+{
+ struct ili210x *priv = input_get_drvdata(input);
+
+ ili210x_process_events(priv);
}
static int ili251x_firmware_update_resolution(struct device *dev)
@@ -829,12 +842,32 @@ static int ili210x_do_firmware_update(struct ili210x *priv,
return 0;
}
+static ssize_t ili210x_firmware_update(struct device *dev, const u8 *fwbuf,
+ u16 ac_end, u16 df_end)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct ili210x *priv = i2c_get_clientdata(client);
+ const char *fwname = ILI251X_FW_FILENAME;
+ int error;
+
+ dev_dbg(dev, "Firmware update started, firmware=%s\n", fwname);
+
+ ili210x_hardware_reset(priv->reset_gpio);
+
+ error = ili210x_do_firmware_update(priv, fwbuf, ac_end, df_end);
+
+ ili210x_hardware_reset(priv->reset_gpio);
+
+ dev_dbg(dev, "Firmware update ended, error=%i\n", error);
+
+ return error;
+}
+
static ssize_t ili210x_firmware_update_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
- struct ili210x *priv = i2c_get_clientdata(client);
const char *fwname = ILI251X_FW_FILENAME;
u16 ac_end, df_end;
int error;
@@ -860,16 +893,11 @@ static ssize_t ili210x_firmware_update_store(struct device *dev,
* the touch controller to disable the IRQs during update, so we have
* to do it this way here.
*/
- scoped_guard(disable_irq, &client->irq) {
- dev_dbg(dev, "Firmware update started, firmware=%s\n", fwname);
-
- ili210x_hardware_reset(priv->reset_gpio);
-
- error = ili210x_do_firmware_update(priv, fwbuf, ac_end, df_end);
-
- ili210x_hardware_reset(priv->reset_gpio);
-
- dev_dbg(dev, "Firmware update ended, error=%i\n", error);
+ if (client->irq > 0) {
+ guard(disable_irq)(&client->irq);
+ error = ili210x_firmware_update(dev, fwbuf, ac_end, df_end);
+ } else {
+ error = ili210x_firmware_update(dev, fwbuf, ac_end, df_end);
}
return error ?: count;
@@ -945,9 +973,6 @@ static int ili210x_i2c_probe(struct i2c_client *client)
if (!chip)
return dev_err_probe(&client->dev, -ENODEV, "unknown device model\n");
- if (client->irq <= 0)
- return dev_err_probe(dev, -EINVAL, "No IRQ!\n");
-
reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(reset_gpio))
return PTR_ERR(reset_gpio);
@@ -997,10 +1022,20 @@ static int ili210x_i2c_probe(struct i2c_client *client)
if (error)
return dev_err_probe(dev, error, "Unable to set up slots\n");
- error = devm_request_threaded_irq(dev, client->irq, NULL, ili210x_irq,
- IRQF_ONESHOT, client->name, priv);
- if (error)
- return dev_err_probe(dev, error, "Unable to request touchscreen IRQ\n");
+ input_set_drvdata(input, priv);
+
+ if (client->irq > 0) {
+ error = devm_request_threaded_irq(dev, client->irq, NULL, ili210x_irq,
+ IRQF_ONESHOT, client->name, priv);
+ if (error)
+ return dev_err_probe(dev, error, "Unable to request touchscreen IRQ\n");
+ } else {
+ error = input_setup_polling(input, ili210x_work_i2c_poll);
+ if (error)
+ return dev_err_probe(dev, error, "Could not set up polling mode\n");
+
+ input_set_poll_interval(input, ILI2XXX_POLL_PERIOD);
+ }
error = devm_add_action_or_reset(dev, ili210x_stop, priv);
if (error)
--
2.51.0
^ permalink raw reply related
* [PATCH v5 1/2] dt-bindings: touchscreen: trivial-touch: Drop 'interrupts' requirement for old Ilitek
From: Marek Vasut @ 2026-01-21 23:06 UTC (permalink / raw)
To: linux-input
Cc: Marek Vasut, Frank Li, Krzysztof Kozlowski, Conor Dooley,
Dmitry Torokhov, Job Noorman, Krzysztof Kozlowski, Rob Herring,
devicetree, linux-kernel, linux-renesas-soc
The old Ilitek touch controllers V3 and V6 can operate without
interrupt line, in polling mode. Drop the 'interrupts' property
requirement for those four controllers. To avoid overloading the
trivial-touch, fork the old Ilitek V3/V6 touch controller binding
into separate document.
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
---
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Frank Li <Frank.Li@nxp.com>
Cc: Job Noorman <job@noorman.info>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Rob Herring <robh@kernel.org>
Cc: devicetree@vger.kernel.org
Cc: linux-input@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-renesas-soc@vger.kernel.org
---
V2: Fork the Ilitek V3/V6 bindings into separate document
V3: Add RB from Frank
V4: No change
V5: - Move allOf: after required:
- Add RB from Krzysztof
---
.../input/touchscreen/ilitek,ili210x.yaml | 51 +++++++++++++++++++
.../input/touchscreen/trivial-touch.yaml | 4 --
2 files changed, 51 insertions(+), 4 deletions(-)
create mode 100644 Documentation/devicetree/bindings/input/touchscreen/ilitek,ili210x.yaml
diff --git a/Documentation/devicetree/bindings/input/touchscreen/ilitek,ili210x.yaml b/Documentation/devicetree/bindings/input/touchscreen/ilitek,ili210x.yaml
new file mode 100644
index 0000000000000..c47d7752a194c
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/ilitek,ili210x.yaml
@@ -0,0 +1,51 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/touchscreen/ilitek,ili210x.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Ilitek ILI21xx/ILI251x V3/V6 touch screen controller with i2c interface
+
+maintainers:
+ - Frank Li <Frank.Li@nxp.com>
+ - Marek Vasut <marek.vasut+renesas@mailbox.org>
+
+properties:
+ compatible:
+ enum:
+ - ilitek,ili210x
+ - ilitek,ili2117
+ - ilitek,ili2120
+ - ilitek,ili251x
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ reset-gpios:
+ maxItems: 1
+
+ wakeup-source: true
+
+required:
+ - compatible
+ - reg
+
+allOf:
+ - $ref: touchscreen.yaml
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ touchscreen@41 {
+ compatible = "ilitek,ili2120";
+ reg = <0x41>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/input/touchscreen/trivial-touch.yaml b/Documentation/devicetree/bindings/input/touchscreen/trivial-touch.yaml
index fa27c6754ca4e..6441d21223caf 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/trivial-touch.yaml
+++ b/Documentation/devicetree/bindings/input/touchscreen/trivial-touch.yaml
@@ -23,9 +23,6 @@ properties:
# Hynitron cstxxx series touchscreen controller
- hynitron,cst340
# Ilitek I2C Touchscreen Controller
- - ilitek,ili210x
- - ilitek,ili2117
- - ilitek,ili2120
- ilitek,ili2130
- ilitek,ili2131
- ilitek,ili2132
@@ -33,7 +30,6 @@ properties:
- ilitek,ili2322
- ilitek,ili2323
- ilitek,ili2326
- - ilitek,ili251x
- ilitek,ili2520
- ilitek,ili2521
# MAXI MAX11801 Resistive touch screen controller with i2c interface
--
2.51.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox