[PATCH v2 2/4] platform/x86: x86-android-tablets: Describe Yoga Book haptics
From: Maurizio Casciano
Date: Thu Aug 27 2026 - 14:19:28 EST
ACPI enumerates the Yoga Book YB1-X91F/L haptic controllers as
DRV2604:00 and DRV2604:01, but omits the properties used by drv260x to
identify their mode, waveform library and enable GPIO.
Register board software nodes and attach them to the existing I2C
devices. Describe the enable signals using their Cherryview GPIO
providers and pins from the firmware resource tables, keeping this
board-specific mapping out of the generic input driver. Hold device
references until removal, reprobe after adding properties to cover an
earlier built-in probe, and detach the nodes in reverse order.
Signed-off-by: Maurizio Casciano <mauriziocasciano7@xxxxxxxxx>
Assisted-by: LLM sparse
---
.../platform/x86/x86-android-tablets/lenovo.c | 98 +++++++++++++++++++
1 file changed, 98 insertions(+)
diff --git a/drivers/platform/x86/x86-android-tablets/lenovo.c b/drivers/platform/x86/x86-android-tablets/lenovo.c
index 8d825e0b4661..a8c849ee03db 100644
--- a/drivers/platform/x86/x86-android-tablets/lenovo.c
+++ b/drivers/platform/x86/x86-android-tablets/lenovo.c
@@ -114,6 +114,41 @@ static const struct software_node lenovo_yb1_x90_hideep_ts_node = {
.properties = lenovo_yb1_x90_hideep_ts_props,
};
+static const struct property_entry lenovo_yb1_x91_drv2604_0_props[] = {
+ PROPERTY_ENTRY_U32("mode", 0), /* DRV260X_LRA_MODE */
+ PROPERTY_ENTRY_U32("library-sel", 0), /* DRV260X_LIB_EMPTY */
+ PROPERTY_ENTRY_GPIO("enable-gpios", &cherryview_gpiochip_nodes[0], 79,
+ GPIO_ACTIVE_HIGH),
+ { }
+};
+
+static const struct property_entry lenovo_yb1_x91_drv2604_1_props[] = {
+ PROPERTY_ENTRY_U32("mode", 0), /* DRV260X_LRA_MODE */
+ PROPERTY_ENTRY_U32("library-sel", 0), /* DRV260X_LIB_EMPTY */
+ PROPERTY_ENTRY_GPIO("enable-gpios", &cherryview_gpiochip_nodes[1], 47,
+ GPIO_ACTIVE_HIGH),
+ { }
+};
+
+static const struct software_node lenovo_yb1_x91_drv2604_0_node = {
+ .properties = lenovo_yb1_x91_drv2604_0_props,
+};
+
+static const struct software_node lenovo_yb1_x91_drv2604_1_node = {
+ .properties = lenovo_yb1_x91_drv2604_1_props,
+};
+
+static const struct software_node *lenovo_yb1_x91_swnodes[] = {
+ &lenovo_yb1_x91_drv2604_0_node,
+ &lenovo_yb1_x91_drv2604_1_node,
+ NULL
+};
+
+static const struct software_node * const lenovo_yb1_x91_drv2604_nodes[] = {
+ &lenovo_yb1_x91_drv2604_0_node,
+ &lenovo_yb1_x91_drv2604_1_node,
+};
+
static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst = {
{
/* BQ27542 fuel-gauge */
@@ -283,9 +318,72 @@ static const struct x86_i2c_client_info lenovo_yogabook_x91_i2c_clients[] __init
},
};
+#define YB1_X91_DRV2604_0_DEVICE "i2c-DRV2604:00"
+#define YB1_X91_DRV2604_1_DEVICE "i2c-DRV2604:01"
+
+static struct device *lenovo_yb1_x91_drv2604_devs[2];
+
+static void lenovo_yb1_x91_add_haptics_props(struct device *dev, int index,
+ const char *name)
+{
+ struct device *haptics_dev;
+ int ret;
+
+ haptics_dev = bus_find_device_by_name(&i2c_bus_type, NULL, name);
+ if (!haptics_dev) {
+ dev_warn(dev, "cannot find %s, haptics will be unavailable\n", name);
+ return;
+ }
+
+ ret = device_add_software_node(haptics_dev,
+ lenovo_yb1_x91_drv2604_nodes[index]);
+ if (ret) {
+ put_device(haptics_dev);
+ dev_warn(dev, "failed to add properties to %s: %d\n", name, ret);
+ return;
+ }
+
+ /* Apply the properties if a built-in driver already attempted to probe. */
+ ret = device_reprobe(haptics_dev);
+ if (ret)
+ dev_warn(dev, "failed to reprobe %s: %d\n", name, ret);
+
+ lenovo_yb1_x91_drv2604_devs[index] = haptics_dev;
+}
+
+static void lenovo_yb1_x91_remove_haptics_props(int index)
+{
+ struct device *haptics_dev = lenovo_yb1_x91_drv2604_devs[index];
+
+ if (!haptics_dev)
+ return;
+
+ device_remove_software_node(haptics_dev);
+ put_device(haptics_dev);
+ lenovo_yb1_x91_drv2604_devs[index] = NULL;
+}
+
+static int __init lenovo_yb1_x91_init(struct device *dev)
+{
+ lenovo_yb1_x91_add_haptics_props(dev, 0, YB1_X91_DRV2604_0_DEVICE);
+ lenovo_yb1_x91_add_haptics_props(dev, 1, YB1_X91_DRV2604_1_DEVICE);
+
+ return 0;
+}
+
+static void lenovo_yb1_x91_exit(void)
+{
+ lenovo_yb1_x91_remove_haptics_props(1);
+ lenovo_yb1_x91_remove_haptics_props(0);
+}
+
const struct x86_dev_info lenovo_yogabook_x91_info __initconst = {
.i2c_client_info = lenovo_yogabook_x91_i2c_clients,
.i2c_client_count = ARRAY_SIZE(lenovo_yogabook_x91_i2c_clients),
+ .swnode_group = lenovo_yb1_x91_swnodes,
+ .gpiochip_type = X86_GPIOCHIP_CHERRYVIEW,
+ .init = lenovo_yb1_x91_init,
+ .exit = lenovo_yb1_x91_exit,
};
/* Lenovo Yoga Tablet 2 1050F/L's Android factory image has everything hardcoded */
--
2.53.0