* [PATCH 0/2] Add support for Wacom W9000-series penabled touchscreens
@ 2025-10-27 16:36 Hendrik Noack
2025-10-27 17:36 ` Krzysztof Kozlowski
2025-10-27 21:25 ` [PATCH 1/2] dt-bindings: Input: Add " Hendrik Noack
0 siblings, 2 replies; 8+ messages in thread
From: Hendrik Noack @ 2025-10-27 16:36 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Hendrik Noack, linux-input, devicetree, linux-kernel
Add devicetree bindings and a driver for the Wacom W9000-series penabled
touchscreens.
The driver currently only contains the information for the W9007A, which I
tested on my devices. It should also work with other chips, such as W9001 or
W9010. However, I couldn't test it on these and the message length would
need to be added.
Note: This is my first driver I have ever worked on so if there is
anything I can do to improve it please let me know!
Signed-off-by: Hendrik Noack <hendrik-noack@gmx.de>
---
Hendrik Noack (2):
dt-bindings: Input: Add Wacom W9000-series penabled touchscreens
Input: Add support for Wacom W9000-series penabled touchscreens
.../input/touchscreen/wacom,w9000-series.yaml | 79 +++
drivers/input/touchscreen/Kconfig | 12 +
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/wacom_w9000.c | 525 ++++++++++++++++++
4 files changed, 617 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/touchscreen/wacom,w9000-series.yaml
create mode 100644 drivers/input/touchscreen/wacom_w9000.c
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/2] Add support for Wacom W9000-series penabled touchscreens
2025-10-27 16:36 [PATCH 0/2] Add support for Wacom W9000-series penabled touchscreens Hendrik Noack
@ 2025-10-27 17:36 ` Krzysztof Kozlowski
2025-10-27 21:25 ` [PATCH 1/2] dt-bindings: Input: Add " Hendrik Noack
1 sibling, 0 replies; 8+ messages in thread
From: Krzysztof Kozlowski @ 2025-10-27 17:36 UTC (permalink / raw)
To: Hendrik Noack, Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: linux-input, devicetree, linux-kernel
On 27/10/2025 17:36, Hendrik Noack wrote:
> Add devicetree bindings and a driver for the Wacom W9000-series penabled
> touchscreens.
>
> The driver currently only contains the information for the W9007A, which I
> tested on my devices. It should also work with other chips, such as W9001 or
> W9010. However, I couldn't test it on these and the message length would
> need to be added.
>
> Note: This is my first driver I have ever worked on so if there is
> anything I can do to improve it please let me know!
>
> Signed-off-by: Hendrik Noack <hendrik-noack@gmx.de>
> ---
> Hendrik Noack (2):
> dt-bindings: Input: Add Wacom W9000-series penabled touchscreens
> Input: Add support for Wacom W9000-series penabled touchscreens
You missed to send actual patches or this is incorrectly threaded.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/2] dt-bindings: Input: Add Wacom W9000-series penabled touchscreens
2025-10-27 16:36 [PATCH 0/2] Add support for Wacom W9000-series penabled touchscreens Hendrik Noack
2025-10-27 17:36 ` Krzysztof Kozlowski
@ 2025-10-27 21:25 ` Hendrik Noack
2025-10-27 21:25 ` [PATCH 2/2] Input: Add support for " Hendrik Noack
` (2 more replies)
1 sibling, 3 replies; 8+ messages in thread
From: Hendrik Noack @ 2025-10-27 21:25 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Hendrik Noack, linux-input, devicetree, linux-kernel
Add bindings for two Wacom W9007 variants which can be found in tablets.
Signed-off-by: Hendrik Noack <hendrik-noack@gmx.de>
---
.../input/touchscreen/wacom,w9000-series.yaml | 79 +++++++++++++++++++
1 file changed, 79 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/touchscreen/wacom,w9000-series.yaml
diff --git a/Documentation/devicetree/bindings/input/touchscreen/wacom,w9000-series.yaml b/Documentation/devicetree/bindings/input/touchscreen/wacom,w9000-series.yaml
new file mode 100644
index 000000000000..93579ae0297e
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/wacom,w9000-series.yaml
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/touchscreen/wacom,w9000-series.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Wacom W9000-series penabled I2C touchscreen driver
+
+description:
+ The W9000-series are penabled touchscreen controllers by Wacom.
+
+maintainers:
+ - Hendrik Noack <hendrik-noack@gmx.de>
+
+allOf:
+ - $ref: touchscreen.yaml#
+
+properties:
+ compatible:
+ enum:
+ - wacom,w9007a_lt03
+ - wacom,w9007a_v1
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ vdd-supply:
+ description:
+ Optional regulator for the VDD digital voltage.
+
+ pdct-gpios:
+ maxItems: 1
+ description:
+ Optional GPIO specifier for the touchscreen's pdct pin.
+
+ flash-mode-gpios:
+ maxItems: 1
+ description:
+ Optional GPIO specifier for the touchscreen's flash-mode pin.
+
+ pen-inserted-gpios:
+ maxItems: 1
+ description:
+ Optional GPIO specifier for the touchscreen's pen-insert pin.
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - vdd-supply
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/gpio/gpio.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ digitizer@56 {
+ compatible = "wacom,wacom,w9007a_v1";
+ reg = <0x56>;
+ interrupt-parent = <&gpx3>;
+ interrupts = <5 IRQ_TYPE_EDGE_RISING>;
+
+ vdd-supply = <&stylus_reg>;
+
+ pdct-gpios = <&gpd1 2 GPIO_ACTIVE_HIGH>;
+ flash-mode-gpios = <&gpd1 3 GPIO_ACTIVE_HIGH>;
+ pen-inserted-gpios = <&gpx0 0 GPIO_ACTIVE_LOW>;
+
+ touchscreen-x-mm = <262>;
+ touchscreen-y-mm = <164>;
+ };
+ };
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/2] Input: Add support for Wacom W9000-series penabled touchscreens
2025-10-27 21:25 ` [PATCH 1/2] dt-bindings: Input: Add " Hendrik Noack
@ 2025-10-27 21:25 ` Hendrik Noack
2025-10-28 7:44 ` Krzysztof Kozlowski
2025-10-27 23:30 ` [PATCH 1/2] dt-bindings: Input: Add " Rob Herring (Arm)
2025-10-28 7:38 ` Krzysztof Kozlowski
2 siblings, 1 reply; 8+ messages in thread
From: Hendrik Noack @ 2025-10-27 21:25 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Hendrik Noack, linux-input, devicetree, linux-kernel
Add driver for two Wacom W9007A variants. These are penabled touchscreens
supporting passive Wacom Pens and use I2C.
Signed-off-by: Hendrik Noack <hendrik-noack@gmx.de>
---
drivers/input/touchscreen/Kconfig | 12 +
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/wacom_w9000.c | 525 ++++++++++++++++++++++++
3 files changed, 538 insertions(+)
create mode 100644 drivers/input/touchscreen/wacom_w9000.c
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 7d5b72ee07fa..40f7af0a681a 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -610,6 +610,18 @@ config TOUCHSCREEN_WACOM_I2C
To compile this driver as a module, choose M here: the module
will be called wacom_i2c.
+config TOUCHSCREEN_WACOM_W9000
+ tristate "Wacom W9000-series penabled touchscreen (I2C)"
+ depends on I2C
+ help
+ Say Y here if you have a Wacom W9000-series penabled I2C touchscreen.
+ This driver supports model W9007A.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the module
+ will be called wacom_w9000.
+
config TOUCHSCREEN_LPC32XX
tristate "LPC32XX touchscreen controller"
depends on ARCH_LPC32XX
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index ab9abd151078..aa3915df83b2 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -102,6 +102,7 @@ tsc2007-$(CONFIG_TOUCHSCREEN_TSC2007_IIO) += tsc2007_iio.o
obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o
obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001) += wacom_w8001.o
obj-$(CONFIG_TOUCHSCREEN_WACOM_I2C) += wacom_i2c.o
+obj-$(CONFIG_TOUCHSCREEN_WACOM_W9000) += wacom_w9000.o
obj-$(CONFIG_TOUCHSCREEN_WDT87XX_I2C) += wdt87xx_i2c.o
obj-$(CONFIG_TOUCHSCREEN_WM831X) += wm831x-ts.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o
diff --git a/drivers/input/touchscreen/wacom_w9000.c b/drivers/input/touchscreen/wacom_w9000.c
new file mode 100644
index 000000000000..11c6c98303b8
--- /dev/null
+++ b/drivers/input/touchscreen/wacom_w9000.c
@@ -0,0 +1,525 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Wacom W9000-series penabled I2C touchscreen driver
+ *
+ * Copyright (c) 2025 Hendrik Noack <hendrik-noack@gmx.de>
+ *
+ * Partially based on vendor driver:
+ * Copyright (C) 2012, Samsung Electronics Co. Ltd.
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/touchscreen.h>
+
+// Message length
+#define COM_COORD_NUM_MAX 12
+#define COM_QUERY_NUM_MAX 9
+
+// Commands
+#define COM_QUERY 0x2a
+
+struct wacom_w9000_variant {
+ int com_coord_num;
+ int com_query_num;
+ char *name;
+};
+
+struct wacom_w9000_data {
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ const struct wacom_w9000_variant *variant;
+ unsigned int fw_version;
+
+ struct touchscreen_properties prop;
+ unsigned int max_pressure;
+
+ struct regulator *regulator;
+
+ struct gpio_desc *flash_mode_gpio;
+ struct gpio_desc *pen_detect_gpio;
+ struct gpio_desc *pen_inserted_gpio;
+
+ unsigned int irq;
+ unsigned int pen_detect_irq;
+ unsigned int pen_insert_irq;
+
+ bool pen_inserted;
+ bool pen_detect;
+ bool pen_proximity;
+};
+
+static const struct wacom_w9000_variant wacom_w9007a_lt03 = {
+ .com_coord_num = 8,
+ .com_query_num = 9,
+ .name = "Wacom W9007 LT03 Digitizer",
+};
+
+static const struct wacom_w9000_variant wacom_w9007a_v1 = {
+ .com_coord_num = 12,
+ .com_query_num = 9,
+ .name = "Wacom W9007 V1 Digitizer",
+};
+
+static const struct of_device_id wacom_w9000_of_match[] = {
+ { .compatible = "wacom,w9007a_lt03", .data = &wacom_w9007a_lt03, },
+ { .compatible = "wacom,w9007a_v1", .data = &wacom_w9007a_v1, },
+ {},
+};
+MODULE_DEVICE_TABLE(of, wacom_w9000_of_match);
+
+static int wacom_w9000_read(struct i2c_client *client, u8 command, int len, char *data)
+{
+ struct i2c_msg xfer[2];
+ bool retried = false;
+ int ret;
+
+ /* Write register */
+ xfer[0].addr = client->addr;
+ xfer[0].flags = 0;
+ xfer[0].len = 1;
+ xfer[0].buf = &command;
+
+ /* Read data */
+ xfer[1].addr = client->addr;
+ xfer[1].flags = I2C_M_RD;
+ xfer[1].len = len;
+ xfer[1].buf = data;
+
+retry:
+ ret = i2c_transfer(client->adapter, xfer, 2);
+ if (ret == 2) {
+ ret = 0;
+ } else if (!retried) {
+ retried = true;
+ goto retry;
+ } else {
+ if (ret >= 0)
+ ret = -EIO;
+ dev_err(&client->dev, "%s: i2c transfer failed (%d)\n", __func__, ret);
+ }
+
+ return ret;
+}
+
+static int wacom_w9000_query(struct wacom_w9000_data *wacom_data)
+{
+ struct i2c_client *client = wacom_data->client;
+ struct device *dev = &wacom_data->client->dev;
+ bool retried = false;
+ int ret;
+ u8 data[COM_QUERY_NUM_MAX];
+
+retry:
+ ret = wacom_w9000_read(client, COM_QUERY, wacom_data->variant->com_query_num, data);
+ if (ret)
+ return ret;
+
+ if (data[0] == 0x0f) {
+ wacom_data->fw_version = get_unaligned_be16(&data[7]);
+ } else if (!retried) {
+ retried = true;
+ goto retry;
+ } else {
+ return -EIO;
+ }
+
+ dev_dbg(dev, "query: %X, %X, %X, %X, %X, %X, %X, %X, %X, %d\n", data[0], data[1], data[2],
+ data[3], data[4], data[5], data[6], data[7], data[8], retried);
+
+ wacom_data->prop.max_x = get_unaligned_be16(&data[1]);
+ wacom_data->prop.max_y = get_unaligned_be16(&data[3]);
+ wacom_data->max_pressure = get_unaligned_be16(&data[5]);
+
+ dev_dbg(dev, "max_x:%d, max_y:%d, max_pressure:%d, fw:0x%X", wacom_data->prop.max_x,
+ wacom_data->prop.max_y, wacom_data->max_pressure,
+ wacom_data->fw_version);
+
+ return 0;
+}
+
+static void wacom_w9000_coord(struct wacom_w9000_data *wacom_data)
+{
+ struct i2c_client *client = wacom_data->client;
+ struct device *dev = &wacom_data->client->dev;
+ int ret;
+ u8 data[COM_COORD_NUM_MAX];
+ bool touch, rubber, side_button;
+ u16 x, y, pressure;
+ u8 distance;
+
+ ret = i2c_master_recv(client, data, wacom_data->variant->com_coord_num);
+ if (ret != wacom_data->variant->com_coord_num) {
+ if (ret >= 0)
+ ret = -EIO;
+ dev_err(dev, "%s: i2c receive failed (%d)\n", __func__, ret);
+ return;
+ }
+
+ dev_dbg(dev, "data: %X, %X, %X, %X, %X, %X, %X, %X, %X, %X, %X, %X", data[0], data[1],
+ data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10],
+ data[11]);
+
+ if (data[0] & BIT(7)) {
+ wacom_data->pen_proximity = 1;
+
+ touch = !!(data[0] & BIT(4));
+ side_button = !!(data[0] & BIT(5));
+ rubber = !!(data[0] & BIT(6));
+
+ x = get_unaligned_be16(&data[1]);
+ y = get_unaligned_be16(&data[3]);
+ pressure = get_unaligned_be16(&data[5]);
+ distance = data[7];
+
+ if (!((x <= wacom_data->prop.max_x) && (y <= wacom_data->prop.max_y))) {
+ dev_warn(dev, "Coordinates out of range x=%d, y=%d", x, y);
+ return;
+ }
+
+ touchscreen_report_pos(wacom_data->input_dev, &wacom_data->prop, x, y, false);
+ input_report_abs(wacom_data->input_dev, ABS_PRESSURE, pressure);
+ input_report_abs(wacom_data->input_dev, ABS_DISTANCE, distance);
+ input_report_key(wacom_data->input_dev, BTN_STYLUS, side_button);
+ input_report_key(wacom_data->input_dev, BTN_TOUCH, touch);
+ input_report_key(wacom_data->input_dev, BTN_TOOL_PEN, !rubber);
+ input_report_key(wacom_data->input_dev, BTN_TOOL_RUBBER, rubber);
+ input_sync(wacom_data->input_dev);
+ } else {
+ if (wacom_data->pen_proximity) {
+ input_report_abs(wacom_data->input_dev, ABS_PRESSURE, 0);
+ input_report_abs(wacom_data->input_dev, ABS_DISTANCE, 0);
+ input_report_key(wacom_data->input_dev, BTN_STYLUS, 0);
+ input_report_key(wacom_data->input_dev, BTN_TOUCH, 0);
+ input_report_key(wacom_data->input_dev, BTN_TOOL_PEN, 0);
+ input_report_key(wacom_data->input_dev, BTN_TOOL_RUBBER, 0);
+ input_sync(wacom_data->input_dev);
+
+ wacom_data->pen_proximity = 0;
+ }
+ }
+}
+
+static irqreturn_t wacom_w9000_interrupt(int irq, void *dev_id)
+{
+ struct wacom_w9000_data *wacom_data = dev_id;
+
+ wacom_w9000_coord(wacom_data);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t wacom_w9000_interrupt_pen_detect(int irq, void *dev_id)
+{
+ struct wacom_w9000_data *wacom_data = dev_id;
+
+ wacom_data->pen_detect = gpiod_get_value(wacom_data->pen_detect_gpio);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t wacom_w9000_interrupt_pen_insert(int irq, void *dev_id)
+{
+ struct wacom_w9000_data *wacom_data = dev_id;
+ struct device *dev = &wacom_data->client->dev;
+ int ret;
+
+ wacom_data->pen_inserted = gpiod_get_value(wacom_data->pen_inserted_gpio);
+
+ input_report_switch(wacom_data->input_dev, SW_PEN_INSERTED, wacom_data->pen_inserted);
+ input_sync(wacom_data->input_dev);
+
+ if (!wacom_data->pen_inserted && !regulator_is_enabled(wacom_data->regulator)) {
+ ret = regulator_enable(wacom_data->regulator);
+ if (ret) {
+ dev_err(dev, "Failed to enable regulators: %d\n", ret);
+ return IRQ_HANDLED;
+ }
+ msleep(200);
+ enable_irq(wacom_data->irq);
+ } else if (wacom_data->pen_inserted && regulator_is_enabled(wacom_data->regulator)) {
+ disable_irq(wacom_data->irq);
+ regulator_disable(wacom_data->regulator);
+ }
+
+ dev_dbg(dev, "Pen inserted changed to %d", wacom_data->pen_inserted);
+
+ return IRQ_HANDLED;
+}
+
+static int wacom_w9000_open(struct input_dev *dev)
+{
+ struct wacom_w9000_data *wacom_data = input_get_drvdata(dev);
+ int ret;
+
+ if (!wacom_data->pen_inserted && !regulator_is_enabled(wacom_data->regulator)) {
+ ret = regulator_enable(wacom_data->regulator);
+ if (ret) {
+ dev_err(&wacom_data->client->dev, "Failed to enable regulators: %d\n",
+ ret);
+ return ret;
+ }
+ msleep(200);
+ enable_irq(wacom_data->irq);
+ }
+ return 0;
+}
+
+static void wacom_w9000_close(struct input_dev *dev)
+{
+ struct wacom_w9000_data *wacom_data = input_get_drvdata(dev);
+
+ if (regulator_is_enabled(wacom_data->regulator)) {
+ disable_irq(wacom_data->irq);
+ regulator_disable(wacom_data->regulator);
+ }
+}
+
+static int wacom_w9000_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct wacom_w9000_data *wacom_data;
+ struct input_dev *input_dev;
+ int ret;
+ u32 val;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_err(dev, "i2c_check_functionality error\n");
+ return -EIO;
+ }
+
+ wacom_data = devm_kzalloc(dev, sizeof(struct wacom_w9000_data), GFP_KERNEL);
+ if (!wacom_data)
+ return -ENOMEM;
+
+ wacom_data->variant = i2c_get_match_data(client);
+
+ wacom_data->client = client;
+
+ input_dev = devm_input_allocate_device(dev);
+ if (!input_dev)
+ return -ENOMEM;
+ wacom_data->input_dev = input_dev;
+
+ wacom_data->irq = client->irq;
+ i2c_set_clientdata(client, wacom_data);
+
+ wacom_data->regulator = devm_regulator_get(dev, "vdd");
+ if (IS_ERR(wacom_data->regulator)) {
+ ret = PTR_ERR(wacom_data->regulator);
+ dev_err(dev, "Failed to get regulators %d\n", ret);
+ return ret;
+ }
+
+ /* Request flash-mode line and don't go into flash mode */
+ wacom_data->flash_mode_gpio = devm_gpiod_get_optional(dev, "flash-mode", GPIOD_OUT_LOW);
+ if (IS_ERR(wacom_data->flash_mode_gpio)) {
+ ret = PTR_ERR(wacom_data->flash_mode_gpio);
+ dev_err(dev, "Failed to get flash-mode gpio: %d\n", ret);
+ return ret;
+ }
+
+ /* Request pdct line */
+ wacom_data->pen_detect_gpio = devm_gpiod_get_optional(dev, "pdct", GPIOD_IN);
+ if (IS_ERR(wacom_data->pen_detect_gpio)) {
+ ret = PTR_ERR(wacom_data->pen_detect_gpio);
+ dev_err(dev, "Failed to get pdct gpio: %d\n", ret);
+ return ret;
+ }
+
+ /* Request pen-insert line */
+ wacom_data->pen_inserted_gpio = devm_gpiod_get_optional(dev, "pen-inserted", GPIOD_IN);
+ if (IS_ERR(wacom_data->pen_inserted_gpio)) {
+ ret = PTR_ERR(wacom_data->pen_inserted_gpio);
+ dev_err(dev, "Failed to get pen-insert gpio: %d\n", ret);
+ return ret;
+ }
+
+ ret = regulator_enable(wacom_data->regulator);
+ if (ret) {
+ dev_err(dev, "Failed to enable regulators: %d\n", ret);
+ return ret;
+ }
+
+ msleep(200);
+
+ ret = wacom_w9000_query(wacom_data);
+ if (ret)
+ goto err_disable_regulators;
+
+ input_dev->name = wacom_data->variant->name;
+ input_dev->id.bustype = BUS_I2C;
+ input_dev->dev.parent = dev;
+ input_dev->id.vendor = 0x56a;
+ input_dev->id.version = wacom_data->fw_version;
+ input_dev->open = wacom_w9000_open;
+ input_dev->close = wacom_w9000_close;
+
+ __set_bit(EV_KEY, input_dev->evbit);
+ __set_bit(EV_ABS, input_dev->evbit);
+ __set_bit(BTN_TOUCH, input_dev->keybit);
+ __set_bit(BTN_TOOL_PEN, input_dev->keybit);
+ __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
+ __set_bit(BTN_STYLUS, input_dev->keybit);
+
+ // Calculate x and y resolution from size in devicetree
+ ret = device_property_read_u32(dev, "touchscreen-x-mm", &val);
+ if (ret)
+ input_abs_set_res(input_dev, ABS_X, 100);
+ else
+ input_abs_set_res(input_dev, ABS_X, wacom_data->prop.max_x / val);
+ ret = device_property_read_u32(dev, "touchscreen-y-mm", &val);
+ if (ret)
+ input_abs_set_res(input_dev, ABS_Y, 100);
+ else
+ input_abs_set_res(input_dev, ABS_Y, wacom_data->prop.max_y / val);
+
+ input_set_abs_params(input_dev, ABS_X, 0, wacom_data->prop.max_x, 4, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0, wacom_data->prop.max_y, 4, 0);
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom_data->max_pressure, 0, 0);
+ input_set_abs_params(input_dev, ABS_DISTANCE, 0, 255, 0, 0);
+
+ touchscreen_parse_properties(input_dev, false, &wacom_data->prop);
+
+ ret = devm_request_threaded_irq(dev, wacom_data->irq, NULL, wacom_w9000_interrupt,
+ IRQF_ONESHOT | IRQF_NO_AUTOEN, client->name, wacom_data);
+ if (ret) {
+ dev_err(dev, "Failed to register interrupt\n");
+ goto err_disable_regulators;
+ }
+
+ if (wacom_data->pen_detect_gpio) {
+ wacom_data->pen_detect_irq = gpiod_to_irq(wacom_data->pen_detect_gpio);
+ ret = devm_request_threaded_irq(dev, wacom_data->pen_detect_irq, NULL,
+ wacom_w9000_interrupt_pen_detect, IRQF_ONESHOT |
+ IRQF_NO_AUTOEN | IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING, "wacom_pdct", wacom_data);
+ if (ret) {
+ dev_err(dev, "Failed to register pdct interrupt\n");
+ goto err_disable_regulators;
+ }
+ }
+
+ if (wacom_data->pen_inserted_gpio) {
+ input_dev->evbit[0] |= BIT_MASK(EV_SW);
+ input_set_capability(input_dev, EV_SW, SW_PEN_INSERTED);
+ wacom_data->pen_insert_irq = gpiod_to_irq(wacom_data->pen_inserted_gpio);
+ ret = devm_request_threaded_irq(dev, wacom_data->pen_insert_irq, NULL,
+ wacom_w9000_interrupt_pen_insert, IRQF_ONESHOT |
+ IRQF_NO_AUTOEN | IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING, "wacom_pen_insert",
+ wacom_data);
+ if (ret) {
+ dev_err(dev, "Failed to register pen-insert interrupt\n");
+ goto err_disable_regulators;
+ }
+ }
+
+ input_set_drvdata(input_dev, wacom_data);
+
+ wacom_data->pen_inserted = gpiod_get_value(wacom_data->pen_inserted_gpio);
+ if (wacom_data->pen_inserted)
+ regulator_disable(wacom_data->regulator);
+ else
+ enable_irq(wacom_data->irq);
+
+ input_report_switch(wacom_data->input_dev, SW_PEN_INSERTED, wacom_data->pen_inserted);
+ input_sync(wacom_data->input_dev);
+
+ if (wacom_data->pen_inserted_gpio)
+ enable_irq(wacom_data->pen_insert_irq);
+
+ if (wacom_data->pen_detect_gpio)
+ enable_irq(wacom_data->pen_detect_irq);
+
+ ret = input_register_device(wacom_data->input_dev);
+ if (ret) {
+ dev_err(dev, "Failed to register input device: %d\n", ret);
+ goto err_disable_regulators;
+ }
+
+ return 0;
+
+err_disable_regulators:
+ regulator_disable(wacom_data->regulator);
+ return ret;
+}
+
+static void wacom_w9000_remove(struct i2c_client *client)
+{
+ struct wacom_w9000_data *wacom_data = i2c_get_clientdata(client);
+
+ if (regulator_is_enabled(wacom_data->regulator))
+ regulator_disable(wacom_data->regulator);
+}
+
+static int wacom_w9000_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct wacom_w9000_data *wacom_data = i2c_get_clientdata(client);
+ struct input_dev *input_dev = wacom_data->input_dev;
+
+ mutex_lock(&input_dev->mutex);
+
+ if (regulator_is_enabled(wacom_data->regulator)) {
+ disable_irq(wacom_data->irq);
+ regulator_disable(wacom_data->regulator);
+ }
+
+ mutex_unlock(&input_dev->mutex);
+
+ return 0;
+}
+
+static int wacom_w9000_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct wacom_w9000_data *wacom_data = i2c_get_clientdata(client);
+ struct input_dev *input_dev = wacom_data->input_dev;
+ int ret = 0;
+
+ mutex_lock(&input_dev->mutex);
+
+ if (!wacom_data->pen_inserted && !regulator_is_enabled(wacom_data->regulator)) {
+ ret = regulator_enable(wacom_data->regulator);
+ if (ret) {
+ dev_err(&wacom_data->client->dev, "Failed to enable regulators: %d\n",
+ ret);
+ } else {
+ msleep(200);
+ enable_irq(wacom_data->irq);
+ }
+ }
+
+ mutex_unlock(&input_dev->mutex);
+
+ return ret;
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(wacom_w9000_pm, wacom_w9000_suspend, wacom_w9000_resume);
+
+static const struct i2c_device_id wacom_w9000_id[] = {
+ { "w9007a_lt03" },
+ { "w9007a_v1" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wacom_w9000_id);
+
+static struct i2c_driver wacom_w9000_driver = {
+ .driver = {
+ .name = "wacom_w9000",
+ .of_match_table = wacom_w9000_of_match,
+ .pm = pm_sleep_ptr(&wacom_w9000_pm),
+ },
+ .probe = wacom_w9000_probe,
+ .remove = wacom_w9000_remove,
+ .id_table = wacom_w9000_id,
+};
+module_i2c_driver(wacom_w9000_driver);
+
+/* Module information */
+MODULE_AUTHOR("Hendrik Noack <hendrik-noack@gmx.de>");
+MODULE_DESCRIPTION("Wacom W9000-series penabled touchscreen driver");
+MODULE_LICENSE("GPL");
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] dt-bindings: Input: Add Wacom W9000-series penabled touchscreens
2025-10-27 21:25 ` [PATCH 1/2] dt-bindings: Input: Add " Hendrik Noack
2025-10-27 21:25 ` [PATCH 2/2] Input: Add support for " Hendrik Noack
@ 2025-10-27 23:30 ` Rob Herring (Arm)
2025-10-28 7:38 ` Krzysztof Kozlowski
2 siblings, 0 replies; 8+ messages in thread
From: Rob Herring (Arm) @ 2025-10-27 23:30 UTC (permalink / raw)
To: Hendrik Noack
Cc: linux-input, Conor Dooley, linux-kernel, devicetree,
Krzysztof Kozlowski, Dmitry Torokhov
On Mon, 27 Oct 2025 22:25:34 +0100, Hendrik Noack wrote:
> Add bindings for two Wacom W9007 variants which can be found in tablets.
>
> Signed-off-by: Hendrik Noack <hendrik-noack@gmx.de>
> ---
> .../input/touchscreen/wacom,w9000-series.yaml | 79 +++++++++++++++++++
> 1 file changed, 79 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/input/touchscreen/wacom,w9000-series.yaml
>
My bot found errors running 'make dt_binding_check' on your patch:
yamllint warnings/errors:
dtschema/dtc warnings/errors:
Documentation/devicetree/bindings/input/touchscreen/wacom,w9000-series.example.dtb: /example-0/i2c/digitizer@56: failed to match any schema with compatible: ['wacom,wacom,w9007a_v1']
doc reference errors (make refcheckdocs):
See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20251027212535.4078-1-hendrik-noack@gmx.de
The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] dt-bindings: Input: Add Wacom W9000-series penabled touchscreens
2025-10-27 21:25 ` [PATCH 1/2] dt-bindings: Input: Add " Hendrik Noack
2025-10-27 21:25 ` [PATCH 2/2] Input: Add support for " Hendrik Noack
2025-10-27 23:30 ` [PATCH 1/2] dt-bindings: Input: Add " Rob Herring (Arm)
@ 2025-10-28 7:38 ` Krzysztof Kozlowski
2 siblings, 0 replies; 8+ messages in thread
From: Krzysztof Kozlowski @ 2025-10-28 7:38 UTC (permalink / raw)
To: Hendrik Noack
Cc: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-input, devicetree, linux-kernel
On Mon, Oct 27, 2025 at 10:25:34PM +0100, Hendrik Noack wrote:
> Add bindings for two Wacom W9007 variants which can be found in tablets.
>
> Signed-off-by: Hendrik Noack <hendrik-noack@gmx.de>
> ---
> .../input/touchscreen/wacom,w9000-series.yaml | 79 +++++++++++++++++++
> 1 file changed, 79 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/input/touchscreen/wacom,w9000-series.yaml
Filename matching compatible,
>
> diff --git a/Documentation/devicetree/bindings/input/touchscreen/wacom,w9000-series.yaml b/Documentation/devicetree/bindings/input/touchscreen/wacom,w9000-series.yaml
> new file mode 100644
> index 000000000000..93579ae0297e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/input/touchscreen/wacom,w9000-series.yaml
> @@ -0,0 +1,79 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/input/touchscreen/wacom,w9000-series.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Wacom W9000-series penabled I2C touchscreen driver
Driver as Linux driver? if so, then drop.
> +
> +description:
> + The W9000-series are penabled touchscreen controllers by Wacom.
> +
> +maintainers:
> + - Hendrik Noack <hendrik-noack@gmx.de>
> +
> +allOf:
> + - $ref: touchscreen.yaml#
> +
> +properties:
> + compatible:
> + enum:
> + - wacom,w9007a_lt03
> + - wacom,w9007a_v1
None of the compatibles use underscores. Please do not come up with
entirely different coding style than existing kernel.
Also, nothing explain here differences - not commit msg, not
description.
> +
> + reg:
> + maxItems: 1
> +
> + interrupts:
> + maxItems: 1
> +
> + vdd-supply:
> + description:
> + Optional regulator for the VDD digital voltage.
> +
> + pdct-gpios:
> + maxItems: 1
> + description:
> + Optional GPIO specifier for the touchscreen's pdct pin.
> +
> + flash-mode-gpios:
> + maxItems: 1
> + description:
> + Optional GPIO specifier for the touchscreen's flash-mode pin.
> +
> + pen-inserted-gpios:
> + maxItems: 1
> + description:
> + Optional GPIO specifier for the touchscreen's pen-insert pin.
> +
> +required:
> + - compatible
> + - reg
> + - interrupts
> + - vdd-supply
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/interrupt-controller/irq.h>
> + #include <dt-bindings/gpio/gpio.h>
> + i2c {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + digitizer@56 {
> + compatible = "wacom,wacom,w9007a_v1";
> + reg = <0x56>;
> + interrupt-parent = <&gpx3>;
> + interrupts = <5 IRQ_TYPE_EDGE_RISING>;
> +
> + vdd-supply = <&stylus_reg>;
> +
> + pdct-gpios = <&gpd1 2 GPIO_ACTIVE_HIGH>;
> + flash-mode-gpios = <&gpd1 3 GPIO_ACTIVE_HIGH>;
> + pen-inserted-gpios = <&gpx0 0 GPIO_ACTIVE_LOW>;
> +
> + touchscreen-x-mm = <262>;
> + touchscreen-y-mm = <164>;
Never tested, after fixing compatible you will see errors. You need
unevaluatedProperties.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/2] Input: Add support for Wacom W9000-series penabled touchscreens
2025-10-27 21:25 ` [PATCH 2/2] Input: Add support for " Hendrik Noack
@ 2025-10-28 7:44 ` Krzysztof Kozlowski
2025-11-03 10:55 ` Kernel GMX
0 siblings, 1 reply; 8+ messages in thread
From: Krzysztof Kozlowski @ 2025-10-28 7:44 UTC (permalink / raw)
To: Hendrik Noack
Cc: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-input, devicetree, linux-kernel
On Mon, Oct 27, 2025 at 10:25:35PM +0100, Hendrik Noack wrote:
> +
> +static const struct of_device_id wacom_w9000_of_match[] = {
> + { .compatible = "wacom,w9007a_lt03", .data = &wacom_w9007a_lt03, },
> + { .compatible = "wacom,w9007a_v1", .data = &wacom_w9007a_v1, },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, wacom_w9000_of_match);
This goes next to other ID table, around the probe.
> +
> +static int wacom_w9000_read(struct i2c_client *client, u8 command, int len, char *data)
> +{
> + struct i2c_msg xfer[2];
> + bool retried = false;
> + int ret;
> +
...
> +
> +static int wacom_w9000_probe(struct i2c_client *client)
> +{
> + struct device *dev = &client->dev;
> + struct wacom_w9000_data *wacom_data;
> + struct input_dev *input_dev;
> + int ret;
> + u32 val;
> +
> + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
> + dev_err(dev, "i2c_check_functionality error\n");
> + return -EIO;
> + }
> +
> + wacom_data = devm_kzalloc(dev, sizeof(struct wacom_w9000_data), GFP_KERNEL);
sizeof(*)
Please use existing kernel coding style, not some downstream version.
> + if (!wacom_data)
> + return -ENOMEM;
> +
> + wacom_data->variant = i2c_get_match_data(client);
> +
> + wacom_data->client = client;
> +
> + input_dev = devm_input_allocate_device(dev);
> + if (!input_dev)
> + return -ENOMEM;
> + wacom_data->input_dev = input_dev;
> +
> + wacom_data->irq = client->irq;
> + i2c_set_clientdata(client, wacom_data);
> +
> + wacom_data->regulator = devm_regulator_get(dev, "vdd");
> + if (IS_ERR(wacom_data->regulator)) {
> + ret = PTR_ERR(wacom_data->regulator);
> + dev_err(dev, "Failed to get regulators %d\n", ret);
> + return ret;
Nope. Look at all other drivers. Syntax is since some years return
dev_err_probe.
> + }
> +
> + /* Request flash-mode line and don't go into flash mode */
> + wacom_data->flash_mode_gpio = devm_gpiod_get_optional(dev, "flash-mode", GPIOD_OUT_LOW);
> + if (IS_ERR(wacom_data->flash_mode_gpio)) {
> + ret = PTR_ERR(wacom_data->flash_mode_gpio);
> + dev_err(dev, "Failed to get flash-mode gpio: %d\n", ret);
> + return ret;
You must handle deferred probe. Please look at all other drivers how
they do it.
> + }
> +
> + /* Request pdct line */
> + wacom_data->pen_detect_gpio = devm_gpiod_get_optional(dev, "pdct", GPIOD_IN);
> + if (IS_ERR(wacom_data->pen_detect_gpio)) {
> + ret = PTR_ERR(wacom_data->pen_detect_gpio);
> + dev_err(dev, "Failed to get pdct gpio: %d\n", ret);
> + return ret;
> + }
> +
> + /* Request pen-insert line */
> + wacom_data->pen_inserted_gpio = devm_gpiod_get_optional(dev, "pen-inserted", GPIOD_IN);
> + if (IS_ERR(wacom_data->pen_inserted_gpio)) {
> + ret = PTR_ERR(wacom_data->pen_inserted_gpio);
> + dev_err(dev, "Failed to get pen-insert gpio: %d\n", ret);
> + return ret;
> + }
> +
> + ret = regulator_enable(wacom_data->regulator);
> + if (ret) {
> + dev_err(dev, "Failed to enable regulators: %d\n", ret);
> + return ret;
> + }
> +
> + msleep(200);
> +
> + ret = wacom_w9000_query(wacom_data);
> + if (ret)
> + goto err_disable_regulators;
> +
> + input_dev->name = wacom_data->variant->name;
> + input_dev->id.bustype = BUS_I2C;
> + input_dev->dev.parent = dev;
> + input_dev->id.vendor = 0x56a;
> + input_dev->id.version = wacom_data->fw_version;
> + input_dev->open = wacom_w9000_open;
> + input_dev->close = wacom_w9000_close;
> +
> + __set_bit(EV_KEY, input_dev->evbit);
> + __set_bit(EV_ABS, input_dev->evbit);
> + __set_bit(BTN_TOUCH, input_dev->keybit);
> + __set_bit(BTN_TOOL_PEN, input_dev->keybit);
> + __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
> + __set_bit(BTN_STYLUS, input_dev->keybit);
> +
> + // Calculate x and y resolution from size in devicetree
> + ret = device_property_read_u32(dev, "touchscreen-x-mm", &val);
> + if (ret)
> + input_abs_set_res(input_dev, ABS_X, 100);
> + else
> + input_abs_set_res(input_dev, ABS_X, wacom_data->prop.max_x / val);
> + ret = device_property_read_u32(dev, "touchscreen-y-mm", &val);
> + if (ret)
> + input_abs_set_res(input_dev, ABS_Y, 100);
> + else
> + input_abs_set_res(input_dev, ABS_Y, wacom_data->prop.max_y / val);
> +
> + input_set_abs_params(input_dev, ABS_X, 0, wacom_data->prop.max_x, 4, 0);
> + input_set_abs_params(input_dev, ABS_Y, 0, wacom_data->prop.max_y, 4, 0);
> + input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom_data->max_pressure, 0, 0);
> + input_set_abs_params(input_dev, ABS_DISTANCE, 0, 255, 0, 0);
> +
> + touchscreen_parse_properties(input_dev, false, &wacom_data->prop);
> +
> + ret = devm_request_threaded_irq(dev, wacom_data->irq, NULL, wacom_w9000_interrupt,
> + IRQF_ONESHOT | IRQF_NO_AUTOEN, client->name, wacom_data);
> + if (ret) {
> + dev_err(dev, "Failed to register interrupt\n");
> + goto err_disable_regulators;
> + }
> +
> + if (wacom_data->pen_detect_gpio) {
> + wacom_data->pen_detect_irq = gpiod_to_irq(wacom_data->pen_detect_gpio);
Why is this a GPIO? Your binding said this is GPIO, your code says this
is an interrupt.
> + ret = devm_request_threaded_irq(dev, wacom_data->pen_detect_irq, NULL,
> + wacom_w9000_interrupt_pen_detect, IRQF_ONESHOT |
> + IRQF_NO_AUTOEN | IRQF_TRIGGER_RISING |
> + IRQF_TRIGGER_FALLING, "wacom_pdct", wacom_data);
> + if (ret) {
> + dev_err(dev, "Failed to register pdct interrupt\n");
> + goto err_disable_regulators;
> + }
> + }
> +
> + if (wacom_data->pen_inserted_gpio) {
> + input_dev->evbit[0] |= BIT_MASK(EV_SW);
> + input_set_capability(input_dev, EV_SW, SW_PEN_INSERTED);
> + wacom_data->pen_insert_irq = gpiod_to_irq(wacom_data->pen_inserted_gpio);
Same question here.
> + ret = devm_request_threaded_irq(dev, wacom_data->pen_insert_irq, NULL,
> + wacom_w9000_interrupt_pen_insert, IRQF_ONESHOT |
> + IRQF_NO_AUTOEN | IRQF_TRIGGER_RISING |
> + IRQF_TRIGGER_FALLING, "wacom_pen_insert",
> + wacom_data);
> + if (ret) {
> + dev_err(dev, "Failed to register pen-insert interrupt\n");
> + goto err_disable_regulators;
> + }
> + }
> +
> + input_set_drvdata(input_dev, wacom_data);
> +
> + wacom_data->pen_inserted = gpiod_get_value(wacom_data->pen_inserted_gpio);
> + if (wacom_data->pen_inserted)
> + regulator_disable(wacom_data->regulator);
> + else
> + enable_irq(wacom_data->irq);
> +
> + input_report_switch(wacom_data->input_dev, SW_PEN_INSERTED, wacom_data->pen_inserted);
> + input_sync(wacom_data->input_dev);
> +
> + if (wacom_data->pen_inserted_gpio)
> + enable_irq(wacom_data->pen_insert_irq);
> +
> + if (wacom_data->pen_detect_gpio)
> + enable_irq(wacom_data->pen_detect_irq);
> +
> + ret = input_register_device(wacom_data->input_dev);
> + if (ret) {
> + dev_err(dev, "Failed to register input device: %d\n", ret);
> + goto err_disable_regulators;
> + }
> +
> + return 0;
> +
> +err_disable_regulators:
> + regulator_disable(wacom_data->regulator);
> + return ret;
> +}
> +
> +static void wacom_w9000_remove(struct i2c_client *client)
> +{
> + struct wacom_w9000_data *wacom_data = i2c_get_clientdata(client);
> +
> + if (regulator_is_enabled(wacom_data->regulator))
> + regulator_disable(wacom_data->regulator);
> +}
> +
> +static int wacom_w9000_suspend(struct device *dev)
> +{
> + struct i2c_client *client = to_i2c_client(dev);
> + struct wacom_w9000_data *wacom_data = i2c_get_clientdata(client);
> + struct input_dev *input_dev = wacom_data->input_dev;
> +
> + mutex_lock(&input_dev->mutex);
> +
> + if (regulator_is_enabled(wacom_data->regulator)) {
> + disable_irq(wacom_data->irq);
> + regulator_disable(wacom_data->regulator);
> + }
> +
> + mutex_unlock(&input_dev->mutex);
> +
> + return 0;
> +}
> +
> +static int wacom_w9000_resume(struct device *dev)
> +{
> + struct i2c_client *client = to_i2c_client(dev);
> + struct wacom_w9000_data *wacom_data = i2c_get_clientdata(client);
> + struct input_dev *input_dev = wacom_data->input_dev;
> + int ret = 0;
> +
> + mutex_lock(&input_dev->mutex);
> +
> + if (!wacom_data->pen_inserted && !regulator_is_enabled(wacom_data->regulator)) {
> + ret = regulator_enable(wacom_data->regulator);
> + if (ret) {
> + dev_err(&wacom_data->client->dev, "Failed to enable regulators: %d\n",
> + ret);
> + } else {
> + msleep(200);
> + enable_irq(wacom_data->irq);
> + }
> + }
> +
> + mutex_unlock(&input_dev->mutex);
> +
> + return ret;
> +}
> +
> +static DEFINE_SIMPLE_DEV_PM_OPS(wacom_w9000_pm, wacom_w9000_suspend, wacom_w9000_resume);
> +
> +static const struct i2c_device_id wacom_w9000_id[] = {
> + { "w9007a_lt03" },
> + { "w9007a_v1" },
This does not match your OF table.
> + { }
> +};
> +MODULE_DEVICE_TABLE(i2c, wacom_w9000_id);
> +
> +static struct i2c_driver wacom_w9000_driver = {
> + .driver = {
> + .name = "wacom_w9000",
> + .of_match_table = wacom_w9000_of_match,
> + .pm = pm_sleep_ptr(&wacom_w9000_pm),
> + },
> + .probe = wacom_w9000_probe,
> + .remove = wacom_w9000_remove,
> + .id_table = wacom_w9000_id,
> +};
> +module_i2c_driver(wacom_w9000_driver);
> +
> +/* Module information */
> +MODULE_AUTHOR("Hendrik Noack <hendrik-noack@gmx.de>");
> +MODULE_DESCRIPTION("Wacom W9000-series penabled touchscreen driver");
> +MODULE_LICENSE("GPL");
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/2] Input: Add support for Wacom W9000-series penabled touchscreens
2025-10-28 7:44 ` Krzysztof Kozlowski
@ 2025-11-03 10:55 ` Kernel GMX
0 siblings, 0 replies; 8+ messages in thread
From: Kernel GMX @ 2025-11-03 10:55 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Hendrik Noack, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
linux-input, devicetree, linux-kernel
28.10.2025 08:44:34 Krzysztof Kozlowski <krzk@kernel.org>:
> On Mon, Oct 27, 2025 at 10:25:35PM +0100, Hendrik Noack wrote:
>> +
>> +static const struct of_device_id wacom_w9000_of_match[] = {
>> + { .compatible = "wacom,w9007a_lt03", .data = &wacom_w9007a_lt03, },
>> + { .compatible = "wacom,w9007a_v1", .data = &wacom_w9007a_v1, },
>> + {},
>> +};
>> +MODULE_DEVICE_TABLE(of, wacom_w9000_of_match);
>
> This goes next to other ID table, around the probe.
>
>> +
>> +static int wacom_w9000_read(struct i2c_client *client, u8 command, int len, char *data)
>> +{
>> + struct i2c_msg xfer[2];
>> + bool retried = false;
>> + int ret;
>> +
>
> ...
>
>> +
>> +static int wacom_w9000_probe(struct i2c_client *client)
>> +{
>> + struct device *dev = &client->dev;
>> + struct wacom_w9000_data *wacom_data;
>> + struct input_dev *input_dev;
>> + int ret;
>> + u32 val;
>> +
>> + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
>> + dev_err(dev, "i2c_check_functionality error\n");
>> + return -EIO;
>> + }
>> +
>> + wacom_data = devm_kzalloc(dev, sizeof(struct wacom_w9000_data), GFP_KERNEL);
>
> sizeof(*)
>
> Please use existing kernel coding style, not some downstream version.
>
Okay, I was orienting myself on the atmel_mxt_ts driver and it had it like this.
>> + if (!wacom_data)
>> + return -ENOMEM;
>> +
>> + wacom_data->variant = i2c_get_match_data(client);
>> +
>> + wacom_data->client = client;
>> +
>> + input_dev = devm_input_allocate_device(dev);
>> + if (!input_dev)
>> + return -ENOMEM;
>> + wacom_data->input_dev = input_dev;
>> +
>> + wacom_data->irq = client->irq;
>> + i2c_set_clientdata(client, wacom_data);
>> +
>> + wacom_data->regulator = devm_regulator_get(dev, "vdd");
>> + if (IS_ERR(wacom_data->regulator)) {
>> + ret = PTR_ERR(wacom_data->regulator);
>> + dev_err(dev, "Failed to get regulators %d\n", ret);
>> + return ret;
>
> Nope. Look at all other drivers. Syntax is since some years return
> dev_err_probe.
>
>> + }
>> +
>> + /* Request flash-mode line and don't go into flash mode */
>> + wacom_data->flash_mode_gpio = devm_gpiod_get_optional(dev, "flash-mode", GPIOD_OUT_LOW);
>> + if (IS_ERR(wacom_data->flash_mode_gpio)) {
>> + ret = PTR_ERR(wacom_data->flash_mode_gpio);
>> + dev_err(dev, "Failed to get flash-mode gpio: %d\n", ret);
>> + return ret;
>
> You must handle deferred probe. Please look at all other drivers how
> they do it.
>
>> + }
>> +
>> + /* Request pdct line */
>> + wacom_data->pen_detect_gpio = devm_gpiod_get_optional(dev, "pdct", GPIOD_IN);
>> + if (IS_ERR(wacom_data->pen_detect_gpio)) {
>> + ret = PTR_ERR(wacom_data->pen_detect_gpio);
>> + dev_err(dev, "Failed to get pdct gpio: %d\n", ret);
>> + return ret;
>> + }
>> +
>> + /* Request pen-insert line */
>> + wacom_data->pen_inserted_gpio = devm_gpiod_get_optional(dev, "pen-inserted", GPIOD_IN);
>> + if (IS_ERR(wacom_data->pen_inserted_gpio)) {
>> + ret = PTR_ERR(wacom_data->pen_inserted_gpio);
>> + dev_err(dev, "Failed to get pen-insert gpio: %d\n", ret);
>> + return ret;
>> + }
>> +
>> + ret = regulator_enable(wacom_data->regulator);
>> + if (ret) {
>> + dev_err(dev, "Failed to enable regulators: %d\n", ret);
>> + return ret;
>> + }
>> +
>> + msleep(200);
>> +
>> + ret = wacom_w9000_query(wacom_data);
>> + if (ret)
>> + goto err_disable_regulators;
>> +
>> + input_dev->name = wacom_data->variant->name;
>> + input_dev->id.bustype = BUS_I2C;
>> + input_dev->dev.parent = dev;
>> + input_dev->id.vendor = 0x56a;
>> + input_dev->id.version = wacom_data->fw_version;
>> + input_dev->open = wacom_w9000_open;
>> + input_dev->close = wacom_w9000_close;
>> +
>> + __set_bit(EV_KEY, input_dev->evbit);
>> + __set_bit(EV_ABS, input_dev->evbit);
>> + __set_bit(BTN_TOUCH, input_dev->keybit);
>> + __set_bit(BTN_TOOL_PEN, input_dev->keybit);
>> + __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
>> + __set_bit(BTN_STYLUS, input_dev->keybit);
>> +
>> + // Calculate x and y resolution from size in devicetree
>> + ret = device_property_read_u32(dev, "touchscreen-x-mm", &val);
>> + if (ret)
>> + input_abs_set_res(input_dev, ABS_X, 100);
>> + else
>> + input_abs_set_res(input_dev, ABS_X, wacom_data->prop.max_x / val);
>> + ret = device_property_read_u32(dev, "touchscreen-y-mm", &val);
>> + if (ret)
>> + input_abs_set_res(input_dev, ABS_Y, 100);
>> + else
>> + input_abs_set_res(input_dev, ABS_Y, wacom_data->prop.max_y / val);
>> +
>> + input_set_abs_params(input_dev, ABS_X, 0, wacom_data->prop.max_x, 4, 0);
>> + input_set_abs_params(input_dev, ABS_Y, 0, wacom_data->prop.max_y, 4, 0);
>> + input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom_data->max_pressure, 0, 0);
>> + input_set_abs_params(input_dev, ABS_DISTANCE, 0, 255, 0, 0);
>> +
>> + touchscreen_parse_properties(input_dev, false, &wacom_data->prop);
>> +
>> + ret = devm_request_threaded_irq(dev, wacom_data->irq, NULL, wacom_w9000_interrupt,
>> + IRQF_ONESHOT | IRQF_NO_AUTOEN, client->name, wacom_data);
>> + if (ret) {
>> + dev_err(dev, "Failed to register interrupt\n");
>> + goto err_disable_regulators;
>> + }
>> +
>> + if (wacom_data->pen_detect_gpio) {
>> + wacom_data->pen_detect_irq = gpiod_to_irq(wacom_data->pen_detect_gpio);
>
> Why is this a GPIO? Your binding said this is GPIO, your code says this
> is an interrupt.
You are right, it's not necessary here.
>> + ret = devm_request_threaded_irq(dev, wacom_data->pen_detect_irq, NULL,
>> + wacom_w9000_interrupt_pen_detect, IRQF_ONESHOT |
>> + IRQF_NO_AUTOEN | IRQF_TRIGGER_RISING |
>> + IRQF_TRIGGER_FALLING, "wacom_pdct", wacom_data);
>> + if (ret) {
>> + dev_err(dev, "Failed to register pdct interrupt\n");
>> + goto err_disable_regulators;
>> + }
>> + }
>> +
>> + if (wacom_data->pen_inserted_gpio) {
>> + input_dev->evbit[0] |= BIT_MASK(EV_SW);
>> + input_set_capability(input_dev, EV_SW, SW_PEN_INSERTED);
>> + wacom_data->pen_insert_irq = gpiod_to_irq(wacom_data->pen_inserted_gpio);
>
> Same question here.
>
The driver needs to know the GPIO state to determine if the pen is inserted
so that it can enable or disable the regulator and main interrupt accordingly.
An interrupt for this GPIO is necessary for this evaluation to occur
on every signal change.
>> + ret = devm_request_threaded_irq(dev, wacom_data->pen_insert_irq, NULL,
>> + wacom_w9000_interrupt_pen_insert, IRQF_ONESHOT |
>> + IRQF_NO_AUTOEN | IRQF_TRIGGER_RISING |
>> + IRQF_TRIGGER_FALLING, "wacom_pen_insert",
>> + wacom_data);
>> + if (ret) {
>> + dev_err(dev, "Failed to register pen-insert interrupt\n");
>> + goto err_disable_regulators;
>> + }
>> + }
>> +
...
Thank you for you feedback, I will address the feedback in my next iteration.
Best regards,
Hendrik
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2025-11-03 10:55 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-27 16:36 [PATCH 0/2] Add support for Wacom W9000-series penabled touchscreens Hendrik Noack
2025-10-27 17:36 ` Krzysztof Kozlowski
2025-10-27 21:25 ` [PATCH 1/2] dt-bindings: Input: Add " Hendrik Noack
2025-10-27 21:25 ` [PATCH 2/2] Input: Add support for " Hendrik Noack
2025-10-28 7:44 ` Krzysztof Kozlowski
2025-11-03 10:55 ` Kernel GMX
2025-10-27 23:30 ` [PATCH 1/2] dt-bindings: Input: Add " Rob Herring (Arm)
2025-10-28 7:38 ` Krzysztof Kozlowski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).