* [PATCH v4 1/2] dt-bindings: input: touchscreen: add Hynitron CST816X
@ 2024-08-29 21:20 Oleh Kuzhylnyi
2024-08-29 21:20 ` [PATCH v4 2/2] input: add driver for Hynitron CST816X touchscreen Oleh Kuzhylnyi
0 siblings, 1 reply; 3+ messages in thread
From: Oleh Kuzhylnyi @ 2024-08-29 21:20 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-input, devicetree, linux-kernel, Oleh Kuzhylnyi,
Conor Dooley, igor.opaniuk, Neil Armstrong, Jeff LaBundy
Add documentation for the Hynitron CST816X touchscreen bindings.
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Oleh Kuzhylnyi <kuzhylol@gmail.com>
---
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,cst816s.yaml | 57 +++++++++++++++++++
1 file changed, 57 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/touchscreen/hynitron,cst816s.yaml
diff --git a/Documentation/devicetree/bindings/input/touchscreen/hynitron,cst816s.yaml b/Documentation/devicetree/bindings/input/touchscreen/hynitron,cst816s.yaml
new file mode 100644
index 000000000000..ac9f1d8e8fc0
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/hynitron,cst816s.yaml
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/touchscreen/hynitron,cst816s.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Hynitron CST816S Touchscreen controller
+
+description:
+ Hynitron CST816S Touchscreen controller for 1.28-inch 240x240 Resolution
+ Touch LCD Display Module
+
+maintainers:
+ - Oleh Kuzhylnyi <kuzhylol@gmail.com>
+
+allOf:
+ - $ref: touchscreen.yaml#
+
+properties:
+ compatible:
+ enum:
+ - hynitron,cst816s
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ reset-gpios:
+ maxItems: 1
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - reset-gpios
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.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>;
+ };
+ };
+
+...
--
2.34.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH v4 2/2] input: add driver for Hynitron CST816X touchscreen
2024-08-29 21:20 [PATCH v4 1/2] dt-bindings: input: touchscreen: add Hynitron CST816X Oleh Kuzhylnyi
@ 2024-08-29 21:20 ` Oleh Kuzhylnyi
2024-09-01 4:27 ` Dmitry Torokhov
0 siblings, 1 reply; 3+ messages in thread
From: Oleh Kuzhylnyi @ 2024-08-29 21:20 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-input, devicetree, linux-kernel, Oleh Kuzhylnyi,
Conor Dooley, igor.opaniuk, Neil Armstrong, Jeff LaBundy
Introduce support for the Hynitron CST816X 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 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 | 258 +++++++++++++++++++
3 files changed, 271 insertions(+)
create mode 100644 drivers/input/touchscreen/hynitron-cst816x.c
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index c821fe3ee794..02f40d0fbac0 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -481,6 +481,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 touchscreen support"
+ depends on I2C
+ help
+ Say Y here if you have a touchscreen using a Hynitron
+ CST816X 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 a81cb5aa21a5..a92a87417a97 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_TOUCHSCREEN_GOODIX_BERLIN_CORE) += goodix_berlin_core.o
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_CST816X) += hynitron-cst816x.o
obj-$(CONFIG_TOUCHSCREEN_HYNITRON_CSTXXX) += hynitron_cstxxx.o
obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o
obj-$(CONFIG_TOUCHSCREEN_ILITEK) += ilitek_ts_i2c.o
diff --git a/drivers/input/touchscreen/hynitron-cst816x.c b/drivers/input/touchscreen/hynitron-cst816x.c
new file mode 100644
index 000000000000..8e2587727e1c
--- /dev/null
+++ b/drivers/input/touchscreen/hynitron-cst816x.c
@@ -0,0 +1,258 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Driver for I2C connected Hynitron CST816X Touchscreen
+ *
+ * Copyright (C) 2024 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/interrupt.h>
+#include <linux/module.h>
+
+enum cst816x_registers {
+ CST816X_FRAME = 0x01,
+ CST816X_MOTION = 0xEC,
+};
+
+enum cst816x_gestures {
+ CST816X_SWIPE_UP = 0x01,
+ CST816X_SWIPE_DOWN = 0x02,
+ CST816X_SWIPE_LEFT = 0x03,
+ CST816X_SWIPE_RIGHT = 0x04,
+ CST816X_SINGLE_TAP = 0x05,
+ CST816X_LONG_PRESS = 0x0C,
+ CST816X_RESERVED = 0xFF,
+};
+
+struct cst816x_touch_info {
+ u8 gesture;
+ u8 touch;
+ u16 abs_x;
+ u16 abs_y;
+};
+
+struct cst816x_priv {
+ struct device *dev;
+ struct i2c_client *client;
+ struct gpio_desc *reset;
+ struct input_dev *input;
+};
+
+struct cst816x_event_mapping {
+ enum cst816x_gestures gesture;
+ u16 code;
+};
+
+static const struct cst816x_event_mapping event_map[16] = {
+ {CST816X_SWIPE_UP, BTN_FORWARD},
+ {CST816X_SWIPE_DOWN, BTN_BACK},
+ {CST816X_SWIPE_LEFT, BTN_LEFT},
+ {CST816X_SWIPE_RIGHT, BTN_RIGHT},
+ {CST816X_SINGLE_TAP, BTN_TOUCH},
+ {CST816X_LONG_PRESS, BTN_TOOL_TRIPLETAP},
+ {CST816X_RESERVED, KEY_RESERVED},
+ {CST816X_RESERVED, KEY_RESERVED},
+ {CST816X_RESERVED, KEY_RESERVED},
+ {CST816X_RESERVED, KEY_RESERVED},
+ {CST816X_RESERVED, KEY_RESERVED},
+ {CST816X_RESERVED, KEY_RESERVED},
+ {CST816X_RESERVED, KEY_RESERVED},
+ {CST816X_RESERVED, KEY_RESERVED},
+ {CST816X_RESERVED, KEY_RESERVED},
+ {CST816X_RESERVED, KEY_RESERVED},
+};
+
+static int cst816x_i2c_read_register(struct cst816x_priv *priv, u8 reg,
+ void *buf, size_t len)
+{
+ struct i2c_client *client;
+ struct i2c_msg xfer[2];
+ int rc;
+
+ client = priv->client;
+
+ xfer[0].addr = client->addr;
+ xfer[0].flags = 0;
+ xfer[0].buf = ®
+ xfer[0].len = sizeof(reg);
+
+ xfer[1].addr = client->addr;
+ xfer[1].flags = I2C_M_RD;
+ xfer[1].buf = buf;
+ xfer[1].len = len;
+
+ rc = i2c_transfer(client->adapter, xfer, ARRAY_SIZE(xfer));
+ if (rc != ARRAY_SIZE(xfer)) {
+ if (rc >= 0)
+ rc = -EIO;
+ } else {
+ rc = 0;
+ }
+
+ if (rc < 0)
+ dev_err(&client->dev, "i2c rx err: %d\n", rc);
+
+ return rc;
+}
+
+static int cst816x_process_touch(struct cst816x_priv *priv,
+ struct cst816x_touch_info *info)
+{
+ u8 raw[8];
+ int rc;
+
+ rc = cst816x_i2c_read_register(priv, CST816X_FRAME, raw, sizeof(raw));
+ if (!rc) {
+ info->gesture = raw[0];
+ info->touch = raw[1];
+ info->abs_x = ((raw[2] & 0x0F) << 8) | raw[3];
+ info->abs_y = ((raw[4] & 0x0F) << 8) | raw[5];
+
+ dev_dbg(priv->dev, "x: %d, y: %d, t: %d, g: 0x%x\n",
+ info->abs_x, info->abs_y, info->touch, info->gesture);
+ }
+
+ return rc;
+}
+
+static int cst816x_register_input(struct cst816x_priv *priv)
+{
+ priv->input = devm_input_allocate_device(priv->dev);
+ if (!priv->input)
+ return -ENOMEM;
+
+ priv->input->name = "Hynitron CST816X Touchscreen";
+ priv->input->phys = "input/ts";
+ priv->input->id.bustype = BUS_I2C;
+ input_set_drvdata(priv->input, priv);
+
+ for (unsigned int i = 0; i < ARRAY_SIZE(event_map); i++)
+ input_set_capability(priv->input, EV_KEY, event_map[i].code);
+
+ input_set_abs_params(priv->input, ABS_X, 0, 240, 0, 0);
+ input_set_abs_params(priv->input, ABS_Y, 0, 240, 0, 0);
+
+ 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 void report_gesture_event(const struct cst816x_priv *priv,
+ enum cst816x_gestures gesture, bool touch)
+{
+ u16 key = event_map[gesture & 0x0F].code;
+
+ if (key != KEY_RESERVED)
+ input_report_key(priv->input, key, touch);
+
+ if (!touch)
+ input_report_key(priv->input, BTN_TOUCH, 0);
+}
+
+/*
+ * Supports five gestures: TOUCH, LEFT, RIGHT, FORWARD, BACK, and LONG_PRESS.
+ * Reports surface interaction, sliding coordinates and finger detachment.
+ *
+ * 1. TOUCH Gesture Scenario:
+ *
+ * [x/y] [touch] [gesture] [Action] [Report ABS] [Report Key]
+ * x y true 0x00 Touch ABS_X_Y BTN_TOUCH
+ * x y true 0x00 Slide ABS_X_Y
+ * x y false 0x05 Gesture BTN_TOUCH
+ *
+ * 2. LEFT, RIGHT, FORWARD, BACK, and LONG_PRESS Gestures Scenario:
+ *
+ * [x/y] [touch] [gesture] [Action] [Report ABS] [Report Key]
+ * x y true 0x00 Touch ABS_X_Y BTN_TOUCH
+ * x y true 0x01 Gesture ABS_X_Y BTN_FORWARD
+ * x y true 0x01 Slide ABS_X_Y
+ * x y false 0x01 Detach BTN_FORWARD | BTN_TOUCH
+ */
+static irqreturn_t cst816x_irq_cb(int irq, void *cookie)
+{
+ struct cst816x_priv *priv = (struct cst816x_priv *)cookie;
+ struct cst816x_touch_info info;
+
+ if (!cst816x_process_touch(priv, &info)) {
+ if (info.touch) {
+ input_report_abs(priv->input, ABS_X, info.abs_x);
+ input_report_abs(priv->input, ABS_Y, info.abs_y);
+ input_report_key(priv->input, BTN_TOUCH, 1);
+ }
+
+ if (info.gesture)
+ report_gesture_event(priv, info.gesture, info.touch);
+
+ 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 rc;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->dev = dev;
+ priv->client = client;
+
+ priv->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(priv->reset))
+ return dev_err_probe(dev, PTR_ERR(priv->reset),
+ "reset gpio not found\n");
+
+ cst816x_reset(priv);
+
+ rc = cst816x_register_input(priv);
+ if (rc)
+ return dev_err_probe(dev, rc, "input register failed\n");
+
+ rc = devm_request_threaded_irq(dev, client->irq, NULL, cst816x_irq_cb,
+ IRQF_ONESHOT, dev->driver->name, priv);
+ if (rc)
+ return dev_err_probe(dev, rc, "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 Touchscreen Driver");
+MODULE_LICENSE("GPL");
--
2.34.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v4 2/2] input: add driver for Hynitron CST816X touchscreen
2024-08-29 21:20 ` [PATCH v4 2/2] input: add driver for Hynitron CST816X touchscreen Oleh Kuzhylnyi
@ 2024-09-01 4:27 ` Dmitry Torokhov
0 siblings, 0 replies; 3+ messages in thread
From: Dmitry Torokhov @ 2024-09-01 4:27 UTC (permalink / raw)
To: Oleh Kuzhylnyi
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-input,
devicetree, linux-kernel, Conor Dooley, igor.opaniuk,
Neil Armstrong, Jeff LaBundy
Hi Oleh,
On Thu, Aug 29, 2024 at 11:20:14PM +0200, Oleh Kuzhylnyi wrote:
> Introduce support for the Hynitron CST816X 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 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
Thank you for making the changes, a few more comments/suggestions:
> +
> +static const struct cst816x_event_mapping event_map[16] = {
> + {CST816X_SWIPE_UP, BTN_FORWARD},
> + {CST816X_SWIPE_DOWN, BTN_BACK},
> + {CST816X_SWIPE_LEFT, BTN_LEFT},
> + {CST816X_SWIPE_RIGHT, BTN_RIGHT},
> + {CST816X_SINGLE_TAP, BTN_TOUCH},
> + {CST816X_LONG_PRESS, BTN_TOOL_TRIPLETAP},
> + {CST816X_RESERVED, KEY_RESERVED},
> + {CST816X_RESERVED, KEY_RESERVED},
> + {CST816X_RESERVED, KEY_RESERVED},
> + {CST816X_RESERVED, KEY_RESERVED},
> + {CST816X_RESERVED, KEY_RESERVED},
> + {CST816X_RESERVED, KEY_RESERVED},
> + {CST816X_RESERVED, KEY_RESERVED},
> + {CST816X_RESERVED, KEY_RESERVED},
> + {CST816X_RESERVED, KEY_RESERVED},
> + {CST816X_RESERVED, KEY_RESERVED},
> +};
> +
> +static int cst816x_i2c_read_register(struct cst816x_priv *priv, u8 reg,
> + void *buf, size_t len)
> +{
> + struct i2c_client *client;
Whenever reasonable combine declaration and initialization:
struct i2c_client *client = priv->client;
> + struct i2c_msg xfer[2];
struct i2c_msg xfer[] = {
{
.addr = client->addr,
.buf = ®,
.len = sizeof(reg),
},
{
.addr = client->addr,
.flags = I2C_M_RD,
.buf = buf,
.len = len,
},
};
> + int rc;
> +
> + client = priv->client;
> +
> + xfer[0].addr = client->addr;
> + xfer[0].flags = 0;
> + xfer[0].buf = ®
> + xfer[0].len = sizeof(reg);
> +
> + xfer[1].addr = client->addr;
> + xfer[1].flags = I2C_M_RD;
> + xfer[1].buf = buf;
> + xfer[1].len = len;
> +
> + rc = i2c_transfer(client->adapter, xfer, ARRAY_SIZE(xfer));
> + if (rc != ARRAY_SIZE(xfer)) {
> + if (rc >= 0)
> + rc = -EIO;
rc = rc < 0 ? rc : -EIO;
dev_err(...);
return rc;
> + } else {
> + rc = 0;
> + }
> +
> + if (rc < 0)
> + dev_err(&client->dev, "i2c rx err: %d\n", rc);
> +
> + return rc;
Explicitly returning 0 on success is preferred if code looks reasonable.
return 0;
> +}
> +
> +static int cst816x_process_touch(struct cst816x_priv *priv,
> + struct cst816x_touch_info *info)
> +{
> + u8 raw[8];
> + int rc;
int error;
> +
> + rc = cst816x_i2c_read_register(priv, CST816X_FRAME, raw, sizeof(raw));
> + if (!rc) {
error = cst816x_i2c_read_register(...);
if (error)
return error;
> + info->gesture = raw[0];
> + info->touch = raw[1];
> + info->abs_x = ((raw[2] & 0x0F) << 8) | raw[3];
I think it can be written as
info->abs_x = get_unaligned_le16(&raw[2]) & GENMASK(11, 0);
> + info->abs_y = ((raw[4] & 0x0F) << 8) | raw[5];
> +
> + dev_dbg(priv->dev, "x: %d, y: %d, t: %d, g: 0x%x\n",
> + info->abs_x, info->abs_y, info->touch, info->gesture);
> + }
> +
> + return rc;
return 0;
> +}
> +
> +static int cst816x_register_input(struct cst816x_priv *priv)
> +{
> + priv->input = devm_input_allocate_device(priv->dev);
> + if (!priv->input)
> + return -ENOMEM;
> +
> + priv->input->name = "Hynitron CST816X Touchscreen";
> + priv->input->phys = "input/ts";
> + priv->input->id.bustype = BUS_I2C;
> + input_set_drvdata(priv->input, priv);
> +
> + for (unsigned int i = 0; i < ARRAY_SIZE(event_map); i++)
> + input_set_capability(priv->input, EV_KEY, event_map[i].code);
> +
> + input_set_abs_params(priv->input, ABS_X, 0, 240, 0, 0);
> + input_set_abs_params(priv->input, ABS_Y, 0, 240, 0, 0);
> +
> + return input_register_device(priv->input);
> +}
> +
> +static void cst816x_reset(struct cst816x_priv *priv)
> +{
I believe the reset line should be optional, and so check for non-NULL
here before trying to execute the reset sequence.
> + gpiod_set_value_cansleep(priv->reset, 1);
> + msleep(50);
> + gpiod_set_value_cansleep(priv->reset, 0);
> + msleep(100);
> +}
> +
> +static void report_gesture_event(const struct cst816x_priv *priv,
> + enum cst816x_gestures gesture, bool touch)
> +{
> + u16 key = event_map[gesture & 0x0F].code;
> +
> + if (key != KEY_RESERVED)
> + input_report_key(priv->input, key, touch);
> +
> + if (!touch)
> + input_report_key(priv->input, BTN_TOUCH, 0);
This chunk does not belong here but rather where you report the rest of
the touch state.
> +}
> +
> +/*
> + * Supports five gestures: TOUCH, LEFT, RIGHT, FORWARD, BACK, and LONG_PRESS.
> + * Reports surface interaction, sliding coordinates and finger detachment.
> + *
> + * 1. TOUCH Gesture Scenario:
> + *
> + * [x/y] [touch] [gesture] [Action] [Report ABS] [Report Key]
> + * x y true 0x00 Touch ABS_X_Y BTN_TOUCH
> + * x y true 0x00 Slide ABS_X_Y
> + * x y false 0x05 Gesture BTN_TOUCH
> + *
> + * 2. LEFT, RIGHT, FORWARD, BACK, and LONG_PRESS Gestures Scenario:
> + *
> + * [x/y] [touch] [gesture] [Action] [Report ABS] [Report Key]
> + * x y true 0x00 Touch ABS_X_Y BTN_TOUCH
> + * x y true 0x01 Gesture ABS_X_Y BTN_FORWARD
> + * x y true 0x01 Slide ABS_X_Y
> + * x y false 0x01 Detach BTN_FORWARD | BTN_TOUCH
> + */
> +static irqreturn_t cst816x_irq_cb(int irq, void *cookie)
> +{
> + struct cst816x_priv *priv = (struct cst816x_priv *)cookie;
No need to cast void pointers.
> + struct cst816x_touch_info info;
> +
> + if (!cst816x_process_touch(priv, &info)) {
This makes it appear cst816x_process_touch() returning boolean.
error = cst816x_process_touch(priv, &info);
if (error)
goto out;
> + if (info.touch) {
> + input_report_abs(priv->input, ABS_X, info.abs_x);
> + input_report_abs(priv->input, ABS_Y, info.abs_y);
> + input_report_key(priv->input, BTN_TOUCH, 1);
> + }
} else {
input_report_key(priv->input, BTN_TOUCH, 0);
}
> +
> + if (info.gesture)
> + report_gesture_event(priv, info.gesture, info.touch);
> +
> + input_sync(priv->input);
> + }
out:
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int cst816x_probe(struct i2c_client *client)
> +{
> + struct cst816x_priv *priv;
> + struct device *dev = &client->dev;
> + int rc;
int error;
> +
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + priv->dev = dev;
> + priv->client = client;
> +
> + priv->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
Please make reset optional, it does not have to be handled by the driver
if something else (firmware) will be doing power sequencing.
> + if (IS_ERR(priv->reset))
> + return dev_err_probe(dev, PTR_ERR(priv->reset),
> + "reset gpio not found\n");
> +
> + cst816x_reset(priv);
> +
> + rc = cst816x_register_input(priv);
> + if (rc)
> + return dev_err_probe(dev, rc, "input register failed\n");
> +
> + rc = devm_request_threaded_irq(dev, client->irq, NULL, cst816x_irq_cb,
> + IRQF_ONESHOT, dev->driver->name, priv);
> + if (rc)
> + return dev_err_probe(dev, rc, "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 Touchscreen Driver");
> +MODULE_LICENSE("GPL");
> --
> 2.34.1
>
Thanks.
--
Dmitry
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2024-09-01 4:27 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-29 21:20 [PATCH v4 1/2] dt-bindings: input: touchscreen: add Hynitron CST816X Oleh Kuzhylnyi
2024-08-29 21:20 ` [PATCH v4 2/2] input: add driver for Hynitron CST816X touchscreen Oleh Kuzhylnyi
2024-09-01 4:27 ` Dmitry Torokhov
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).