* [PATCH v9 1/2] dt-bindings: input: touchscreen: add hynitron cst816x series
@ 2025-07-06 15:44 Oleh Kuzhylnyi
2025-07-06 15:44 ` [PATCH v9 2/2] input: " Oleh Kuzhylnyi
2025-07-07 6:25 ` [PATCH v9 1/2] dt-bindings: input: touchscreen: " Krzysztof Kozlowski
0 siblings, 2 replies; 3+ messages in thread
From: Oleh Kuzhylnyi @ 2025-07-06 15:44 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sasha Finkelstein,
Javier Carrasco, Linus Walleij, Javier Martinez Canillas,
Janne Grunau, Igor Opaniuk, Neal Gompa, Jeff LaBundy,
Neil Armstrong, Oleh Kuzhylnyi, linux-input, devicetree,
linux-kernel
Add documentation for Hynitron CST816x series touchscreen bindings.
Signed-off-by: Oleh Kuzhylnyi <kuzhylol@gmail.com>
---
Changes in v9:
- Adjust linux,keycodes: Add items with event descriptions, and remove maxItems
- Adjust dt example: Fix four-spaces indentation
Changes in v8:
- Update the bindings title to indicate CST816x series support
- Rephrase bindings description to describe controller more precisely
- Remove redundant description field from the reset-gpio property
- Completely remove cst816x,gestures object with all dependants
- Apply linux,keycodes to represent gestures (slide up, slide down, etc.)
- Extend dt example with linux,keycodes
- Align indentation in dt example to use four spaces
Changes in v7:
- Introduce the gestures field along with its sub-fields
- Make reset-gpio property optional
- Extend main description
- Remove "touchscreen" reference
Changes in v6:
- Fix minor tweak adviced by Krzysztof:
- Move additionalProperties field after required
Changes in v5:
- No code changes
Changes in v4:
- Add Conor's Dooley "Reviewed-by" tag
Changes in v3:
- Rename filename to hynitron,cst816s.yaml
- Update description with display details
Changes in v2:
- Apply pin definitions and DT headers
- Use generic name for DT node
- Drop status field
.../input/touchscreen/hynitron,cst816x.yaml | 65 +++++++++++++++++++
1 file changed, 65 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/touchscreen/hynitron,cst816x.yaml
diff --git a/Documentation/devicetree/bindings/input/touchscreen/hynitron,cst816x.yaml b/Documentation/devicetree/bindings/input/touchscreen/hynitron,cst816x.yaml
new file mode 100644
index 000000000000..72d4da636881
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/hynitron,cst816x.yaml
@@ -0,0 +1,65 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/touchscreen/hynitron,cst816x.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Hynitron CST816x Series Capacitive Touch controller
+
+maintainers:
+ - Oleh Kuzhylnyi <kuzhylol@gmail.com>
+
+description: |
+ Bindings for CST816x high performance self-capacitance touch chip series
+ with single point gesture and real two-point operation.
+
+properties:
+ compatible:
+ enum:
+ - hynitron,cst816s
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ reset-gpios:
+ maxItems: 1
+
+ linux,keycodes:
+ minItems: 1
+ items:
+ - description: Slide up gesture
+ - description: Slide down gesture
+ - description: Slide left gesture
+ - description: Slide right gesture
+ - description: Long press gesture
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/input/linux-event-codes.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ touchscreen@15 {
+ compatible = "hynitron,cst816s";
+ reg = <0x15>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <4 IRQ_TYPE_EDGE_RISING>;
+ reset-gpios = <&gpio 17 GPIO_ACTIVE_LOW>;
+ linux,keycodes = <KEY_UP>, <KEY_DOWN>, <KEY_LEFT>, <KEY_RIGHT>,
+ <BTN_TOOL_TRIPLETAP>;
+ };
+ };
+
+...
--
2.34.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH v9 2/2] input: add hynitron cst816x series
2025-07-06 15:44 [PATCH v9 1/2] dt-bindings: input: touchscreen: add hynitron cst816x series Oleh Kuzhylnyi
@ 2025-07-06 15:44 ` Oleh Kuzhylnyi
2025-07-07 6:25 ` [PATCH v9 1/2] dt-bindings: input: touchscreen: " Krzysztof Kozlowski
1 sibling, 0 replies; 3+ messages in thread
From: Oleh Kuzhylnyi @ 2025-07-06 15:44 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sasha Finkelstein,
Javier Carrasco, Linus Walleij, Javier Martinez Canillas,
Janne Grunau, Igor Opaniuk, Neal Gompa, Jeff LaBundy,
Neil Armstrong, Oleh Kuzhylnyi, linux-input, devicetree,
linux-kernel
Introduce support for the Hynitron CST816x series touchscreen controller
used for 240×240 1.28-inch Round LCD Display Module manufactured
by Waveshare Electronics. The driver is designed based on an Arduino
implementation marked as under MIT License. This driver is written
for a particular round display based on the CST816S controller, which
is not compatiable with existing driver for Hynitron controllers.
Signed-off-by: Oleh Kuzhylnyi <kuzhylol@gmail.com>
---
Changes in v9:
- Do not treat TOUCH as a gesture. Use BTN_TOUCH to indicate active touch slots.
- Use u16 for coordinate values to align with the expected input types
- Add cst816x_gest_to_idx() to map gesture ID to keycodes[i] event
- Simplify input reporting order by reporting coordinates first
- Reword cst816x_touch's fields: "gesture" to "gest", and "touch" to "active"
- Rename *desc argument to *tch
Changes in v8:
- Change driver's name to: Hynitron CST816x Series Touchscreen
- Simplify DT gesture mapping for better consistency:
linux,code[0-15]: event_map[gest_id] -> linux,keycodes[0-15]: keycode[gest_id]
- Treat TOUCH as a user-defined gesture
- Minor rewords: error/rc to ret, CST816X_FRAME to CST816X_RD_REG
Changes in v7:
- Update commit based on Jeffs's feedback:
- Move event_map table to Device Tree
- Implement DT parsing functionality
- Use "int" type for iterators
- Get rid of "*dev" entry from private struct
- Use touch_info directly as a buffer for I2C
- Fix coding style tweaks
Changes in v6:
- No code changes
Changes in v5:
- Update commit based on Dmitry's feedback:
- Make GPIO reset optional
- Combine declaration and initialization for i2c_xfer
- Return 0 explicitly where possible
- Rename rc (return code) to error
- Make Touch processing call return boolean
- Improve error handling for i2c_transfer
- Use get_unaligned_be16 for getting coordinates
- Move touch event completeness upper to irq callback
Changes in v4:
- Update commit based on Dmitry's feedback:
- Move abs_x and abs_y to u16
- Remove __packed qualifier for touch_info struct
- Hide tiny touch irq context to stack
- Extend cst816x_i2c_read_register() with buf and buf_size
- Remove loop from event lookup
Changes in v3:
- Drop timer and delayed work
- Process touch in threaded IRQ context
- Fix chip reset sequence
- Move input_register() before devm_request_threaded_irq()
- Re-arrange and document input reporting
- Set u16 data type for event_code
- Remove double tap event to prevent continuous double side sliding
Changes in v2:
- Apply dev_err_probe() for better error handling
- Remove redundant printing, remove dev_warn() message spamming
- Get rid of PM since the touchscreen goes into sleep mode automatically
- Get rid of IRQ control and IRQF_NO_AUTOEN flag
- Reduce timer timeout up to 10ms to handle touch events faster
- Skip registering of non-gesture CST816X_SWIPE event
- Shift input_register_device() as a final call in probe() callback
- Specify name of i2c_device_id explicitly
- Update module description and fix typo
- Add necessary spaces between lines
drivers/input/touchscreen/Kconfig | 12 +
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/hynitron-cst816x.c | 243 +++++++++++++++++++
3 files changed, 256 insertions(+)
create mode 100644 drivers/input/touchscreen/hynitron-cst816x.c
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 196905162945..8c32aeaf6efa 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -465,6 +465,18 @@ config TOUCHSCREEN_HYNITRON_CSTXXX
To compile this driver as a module, choose M here: the
module will be called hynitron-cstxxx.
+config TOUCHSCREEN_HYNITRON_CST816X
+ tristate "Hynitron CST816x series touchscreen"
+ depends on I2C
+ help
+ Say Y here if you have a touchscreen using a Hynitron
+ CST816x series touchscreen controller.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called hynitron-cst816x.
+
config TOUCHSCREEN_ILI210X
tristate "Ilitek ILI210X based touchscreen"
depends on I2C
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 97a025c6a377..6805ab60f016 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_TOUCHSCREEN_GOODIX_BERLIN_I2C) += goodix_berlin_i2c.o
obj-$(CONFIG_TOUCHSCREEN_GOODIX_BERLIN_SPI) += goodix_berlin_spi.o
obj-$(CONFIG_TOUCHSCREEN_HIDEEP) += hideep.o
obj-$(CONFIG_TOUCHSCREEN_HYNITRON_CSTXXX) += hynitron_cstxxx.o
+obj-$(CONFIG_TOUCHSCREEN_HYNITRON_CST816X) += hynitron-cst816x.o
obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o
obj-$(CONFIG_TOUCHSCREEN_ILITEK) += ilitek_ts_i2c.o
obj-$(CONFIG_TOUCHSCREEN_IMAGIS) += imagis.o
diff --git a/drivers/input/touchscreen/hynitron-cst816x.c b/drivers/input/touchscreen/hynitron-cst816x.c
new file mode 100644
index 000000000000..0de9bb6a6ef5
--- /dev/null
+++ b/drivers/input/touchscreen/hynitron-cst816x.c
@@ -0,0 +1,243 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Driver for I2C connected Hynitron CST816x Series Touchscreen
+ *
+ * Copyright (C) 2025 Oleh Kuzhylnyi <kuzhylol@gmail.com>
+ */
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/unaligned.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+
+#define CST816X_RD_REG 0x01
+#define CST816X_NUM_KEYS 5
+
+struct cst816x_touch {
+ u8 gest;
+ u8 active;
+ u16 abs_x;
+ u16 abs_y;
+} __packed;
+
+struct cst816x_priv {
+ struct i2c_client *client;
+ struct gpio_desc *reset;
+ struct input_dev *input;
+ unsigned int keycode[CST816X_NUM_KEYS];
+ unsigned int keycodemax;
+};
+
+static int cst816x_parse_keycodes(struct device *dev, struct cst816x_priv *priv)
+{
+ int ret;
+
+ if (device_property_present(dev, "linux,keycodes")) {
+ ret = device_property_count_u32(dev, "linux,keycodes");
+ if (ret < 0) {
+ dev_err(dev, "failed to count keys: %d\n", ret);
+ return ret;
+ } else if (ret > ARRAY_SIZE(priv->keycode)) {
+ dev_err(dev, "too many keys defined: %d\n", ret);
+ return -EINVAL;
+ }
+ priv->keycodemax = ret;
+
+ ret = device_property_read_u32_array(dev, "linux,keycodes",
+ priv->keycode,
+ priv->keycodemax);
+ if (ret) {
+ dev_err(dev, "failed to read keycodes: %d\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int cst816x_i2c_read_register(struct cst816x_priv *priv, u8 reg,
+ void *buf, size_t len)
+{
+ int ret;
+ struct i2c_msg xfer[] = {
+ {
+ .addr = priv->client->addr,
+ .flags = 0,
+ .buf = ®,
+ .len = sizeof(reg),
+ },
+ {
+ .addr = priv->client->addr,
+ .flags = I2C_M_RD,
+ .buf = buf,
+ .len = len,
+ },
+ };
+
+ ret = i2c_transfer(priv->client->adapter, xfer, ARRAY_SIZE(xfer));
+ if (ret != ARRAY_SIZE(xfer)) {
+ ret = ret < 0 ? ret : -EIO;
+ dev_err(&priv->client->dev, "i2c rx err: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static u8 cst816x_gest_idx(u8 gest)
+{
+ u8 index;
+
+ switch (gest) {
+ case 0x01: // Slide up gesture
+ case 0x02: // Slide down gesture
+ case 0x03: // Slide left gesture
+ case 0x04: // Slide right gesture
+ index = gest;
+ break;
+ case 0x0c: // Long press gesture
+ default:
+ index = CST816X_NUM_KEYS;
+ break;
+ }
+
+ return index - 1;
+}
+
+static bool cst816x_process_touch(struct cst816x_priv *priv,
+ struct cst816x_touch *tch)
+{
+ if (cst816x_i2c_read_register(priv, CST816X_RD_REG, tch, sizeof(*tch)))
+ return false;
+
+ tch->abs_x = get_unaligned_be16(&tch->abs_x) & GENMASK(11, 0);
+ tch->abs_y = get_unaligned_be16(&tch->abs_y) & GENMASK(11, 0);
+
+ dev_dbg(&priv->client->dev, "x: %u, y: %u, t: %u, g: 0x%x\n",
+ tch->abs_x, tch->abs_y, tch->active, tch->gest);
+
+ return true;
+}
+
+static int cst816x_register_input(struct cst816x_priv *priv)
+{
+ priv->input = devm_input_allocate_device(&priv->client->dev);
+ if (!priv->input)
+ return -ENOMEM;
+
+ priv->input->name = "Hynitron CST816x Series Touchscreen";
+ priv->input->phys = "input/ts";
+ priv->input->id.bustype = BUS_I2C;
+ input_set_drvdata(priv->input, priv);
+
+ input_set_abs_params(priv->input, ABS_X, 0, 240, 0, 0);
+ input_set_abs_params(priv->input, ABS_Y, 0, 240, 0, 0);
+ input_set_capability(priv->input, EV_KEY, BTN_TOUCH);
+
+ for (int i = 0; i < priv->keycodemax; i++) {
+ if (priv->keycode[i] == KEY_RESERVED)
+ continue;
+
+ input_set_capability(priv->input, EV_KEY, priv->keycode[i]);
+ }
+
+ return input_register_device(priv->input);
+}
+
+static void cst816x_reset(struct cst816x_priv *priv)
+{
+ gpiod_set_value_cansleep(priv->reset, 1);
+ msleep(50);
+ gpiod_set_value_cansleep(priv->reset, 0);
+ msleep(100);
+}
+
+static irqreturn_t cst816x_irq_cb(int irq, void *cookie)
+{
+ struct cst816x_priv *priv = cookie;
+ struct cst816x_touch tch;
+
+ if (!cst816x_process_touch(priv, &tch))
+ return IRQ_HANDLED;
+
+ input_report_abs(priv->input, ABS_X, tch.abs_x);
+ input_report_abs(priv->input, ABS_Y, tch.abs_y);
+
+ if (tch.gest) {
+ input_report_key(priv->input,
+ priv->keycode[cst816x_gest_idx(tch.gest)],
+ tch.active);
+ }
+
+ input_report_key(priv->input, BTN_TOUCH, tch.active);
+
+ input_sync(priv->input);
+
+ return IRQ_HANDLED;
+}
+
+static int cst816x_probe(struct i2c_client *client)
+{
+ struct cst816x_priv *priv;
+ struct device *dev = &client->dev;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->client = client;
+
+ priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(priv->reset))
+ return dev_err_probe(dev, PTR_ERR(priv->reset),
+ "gpio reset request failed\n");
+
+ if (priv->reset)
+ cst816x_reset(priv);
+
+ ret = cst816x_parse_keycodes(dev, priv);
+ if (ret)
+ dev_warn(dev, "no gestures found in dt\n");
+
+ ret = cst816x_register_input(priv);
+ if (ret)
+ return dev_err_probe(dev, ret, "input register failed\n");
+
+ ret = devm_request_threaded_irq(dev, client->irq, NULL, cst816x_irq_cb,
+ IRQF_ONESHOT, dev->driver->name, priv);
+ if (ret)
+ return dev_err_probe(dev, ret, "irq request failed\n");
+
+ return 0;
+}
+
+static const struct i2c_device_id cst816x_id[] = {
+ { .name = "cst816s", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, cst816x_id);
+
+static const struct of_device_id cst816x_of_match[] = {
+ { .compatible = "hynitron,cst816s", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, cst816x_of_match);
+
+static struct i2c_driver cst816x_driver = {
+ .driver = {
+ .name = "cst816x",
+ .of_match_table = cst816x_of_match,
+ },
+ .id_table = cst816x_id,
+ .probe = cst816x_probe,
+};
+
+module_i2c_driver(cst816x_driver);
+
+MODULE_AUTHOR("Oleh Kuzhylnyi <kuzhylol@gmail.com>");
+MODULE_DESCRIPTION("Hynitron CST816x Series Touchscreen Driver");
+MODULE_LICENSE("GPL");
--
2.34.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v9 1/2] dt-bindings: input: touchscreen: add hynitron cst816x series
2025-07-06 15:44 [PATCH v9 1/2] dt-bindings: input: touchscreen: add hynitron cst816x series Oleh Kuzhylnyi
2025-07-06 15:44 ` [PATCH v9 2/2] input: " Oleh Kuzhylnyi
@ 2025-07-07 6:25 ` Krzysztof Kozlowski
1 sibling, 0 replies; 3+ messages in thread
From: Krzysztof Kozlowski @ 2025-07-07 6:25 UTC (permalink / raw)
To: Oleh Kuzhylnyi
Cc: Dmitry Torokhov, Rob Herring, Conor Dooley, Sasha Finkelstein,
Javier Carrasco, Linus Walleij, Javier Martinez Canillas,
Janne Grunau, Igor Opaniuk, Neal Gompa, Jeff LaBundy,
Neil Armstrong, linux-input, devicetree, linux-kernel
On Sun, Jul 06, 2025 at 05:44:29PM +0200, Oleh Kuzhylnyi wrote:
> Add documentation for Hynitron CST816x series touchscreen bindings.
>
> Signed-off-by: Oleh Kuzhylnyi <kuzhylol@gmail.com>
> ---
> Changes in v9:
> - Adjust linux,keycodes: Add items with event descriptions, and remove maxItems
> - Adjust dt example: Fix four-spaces indentation
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
<form letter>
This is an automated instruction, just in case, because many review
tags are being ignored. If you know the process, just skip it entirely
(please do not feel offended by me posting it here - no bad intentions
intended, no patronizing, I just want to avoid wasted efforts). If you
do not know the process, here is a short explanation:
Please add Acked-by/Reviewed-by/Tested-by tags when posting new
versions of patchset, under or above your Signed-off-by tag, unless
patch changed significantly (e.g. new properties added to the DT
bindings). Tag is "received", when provided in a message replied to you
on the mailing list. Tools like b4 can help here ('b4 trailers -u ...').
However, there's no need to repost patches *only* to add the tags. The
upstream maintainer will do that for tags received on the version they
apply.
https://elixir.bootlin.com/linux/v6.15/source/Documentation/process/submitting-patches.rst#L591
</form letter>
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-07-07 6:25 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-06 15:44 [PATCH v9 1/2] dt-bindings: input: touchscreen: add hynitron cst816x series Oleh Kuzhylnyi
2025-07-06 15:44 ` [PATCH v9 2/2] input: " Oleh Kuzhylnyi
2025-07-07 6:25 ` [PATCH v9 1/2] dt-bindings: input: touchscreen: " 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).