Skip to contentSkip to conversation

Add Hynitron cstxxx Touchscreen

PATCH Superseded Chris Morgan 3 participants 8 messages Oct 28, 2022 – Oct 29, 2022

Subsystems (3)

v4 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

v4 cover Add Hynitron cstxxx Touchscreen

From: Chris Morgan <[email protected]>

This series adds support for the Hynitron cstxxx (specifically the cst3xx series). The cst3xx supports 5 point multitouch with hardware tracking of touch points.

Note that a datasheet was unavailable for this device, so it was built based on vendor provided source code that was tagged as GPLv2. Some of the register functions were discovered via trial and error and labelled as such.

Changes from V3:
- Removed of includes and changed from of_device_get_match_data() to device_get_match_data().
- Print checkcode read from the device in the event of an error.
- Removed extra dev_err() print functions.

Changes from V2:
- Fix issue identified by Intel Kernel Test Robot. Changed functions in driver to static. Reported-by: kernel test robot <[email protected]>

Changes from V1:
- Updated binding to specify cst340 instead of generic cst3xx.
- Defined various registers and commands to enhance code readability.
- Changed name of chip specific struct to hynitron_ts_chip_data.
- Removed unused and redundant values from driver data.
- Switch to gpiod cansleep functions in reset.
- Refactored read/write i2c functions.
- Changed variable names of ret to err in certain functions and added additional error handling in input registration function.

Chris Morgan (3):
dt-bindings: vendor-prefixes: add Hynitron vendor prefix
dt-bindings: input: touchscreen: Add Hynitron cstxxx input/touchscreen: Add Hynitron cstxxx touchscreen

 .../input/touchscreen/hynitron,cstxxx.yaml    |  65 +++
 .../devicetree/bindings/vendor-prefixes.yaml  |   2 +
 drivers/input/touchscreen/Kconfig             |  12 +
 drivers/input/touchscreen/Makefile            |   1 +
 drivers/input/touchscreen/hynitron_cstxxx.c   | 505 ++++++++++++++++++
 5 files changed, 585 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/input/touchscreen/hynitron,cstxxx.yaml
 create mode 100644 drivers/input/touchscreen/hynitron_cstxxx.c
Signature · 1 line
2.25.1
#1 lore raw

PATCH v4 1/3 dt-bindings: vendor-prefixes: add Hynitron vendor prefix

From: Chris Morgan <[email protected]>

Hynitron is a company based in Shanghai that makes controller ICs for touchscreens.

http://www.hynitron.com/

---
 Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
 1 file changed, 2 insertions(+)
Documentation/devicetree/bindings/vendor-prefixes.yaml +2 -0
index 6e323a380294..b11b19c14669 100644
@@ -567,6 +567,8 @@ patternProperties:
     description: Hycon Technology Corp.
   "^hydis,.*":
     description: Hydis Technologies
+  "^hynitron,.*":
+    description: Shanghai Hynitron Microelectronics Co. Ltd.
   "^hynix,.*":
     description: SK Hynix Inc.
   "^hyundai,.*":
Signature · 1 line
2.25.1
#2 lore raw

PATCH v4 2/3 dt-bindings: input: touchscreen: Add Hynitron cstxxx

In reply to Chris Morgan

From: Chris Morgan <[email protected]>

Add documentation for the Hynitron cstxxx touchscreen bindings. Hynitron makes a series of touchscreen controllers, however for now this is expected to only be compatible with the cst3xx series, specifically the CST340, CST348, and CST356.

---
 .../input/touchscreen/hynitron,cstxxx.yaml    | 65 +++++++++++++++++++
 1 file changed, 65 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/input/touchscreen/hynitron,cstxxx.yaml
Documentation/devicetree/bindings/input/touchscreen/hynitron,cstxxx.yaml new file +65 -0
new file mode 100644
index 000000000000..9cb5d4af00f7
@@ -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,cstxxx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Hynitron cstxxx series touchscreen controller
+
+description: |
+  Bindings for Hynitron cstxxx series multi-touch touchscreen
+  controllers.
+
+maintainers:
+  - Chris Morgan <[email protected]>
+
+allOf:
+  - $ref: touchscreen.yaml#
+
+properties:
+  compatible:
+    enum:
+      - hynitron,cst340
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  reset-gpios:
+    maxItems: 1
+
+  touchscreen-size-x: true
+  touchscreen-size-y: true
+  touchscreen-inverted-x: true
+  touchscreen-inverted-y: true
+  touchscreen-swapped-x-y: true
+
+additionalProperties: false
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - reset-gpios
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    i2c {
+      #address-cells = <1>;
+      #size-cells = <0>;
+      touchscreen@1a {
+        compatible = "hynitron,cst340";
+        reg = <0x1a>;
+        interrupt-parent = <&gpio4>;
+        interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
+        reset-gpios = <&gpio4 6 GPIO_ACTIVE_LOW>;
+        touchscreen-size-x = <640>;
+        touchscreen-size-y = <480>;
+      };
+    };
+
+...
Signature · 1 line
2.25.1
#3 lore raw

PATCH v4 3/3 input/touchscreen: Add Hynitron cstxxx touchscreen

In reply to Chris Morgan

From: Chris Morgan <[email protected]>

Add support for the Hynitron cst3xx controller found on devices such as the Anbernic RG353P and RG353V (the Hynitron CST340). This driver was built from sources provided by Hynitron to Anbernic (possibly via Rockchip as an intermediary) and marked as GPLv2 in the code. This driver was written strictly for the cst3xx series, but in most places was left somewhat generic so support could be easily added to other devices in the future.

---
 drivers/input/touchscreen/Kconfig           |  12 +
 drivers/input/touchscreen/Makefile          |   1 +
 drivers/input/touchscreen/hynitron_cstxxx.c | 505 ++++++++++++++++++++
 3 files changed, 518 insertions(+)
 create mode 100644 drivers/input/touchscreen/hynitron_cstxxx.c
drivers/input/touchscreen/Kconfig +12 -0
index dc90a3ea51ee..46b158c04c7b 100644
@@ -422,6 +422,18 @@ config TOUCHSCREEN_HYCON_HY46XX
 	  To compile this driver as a module, choose M here: the
 	  module will be called hycon-hy46xx.
 
+config TOUCHSCREEN_HYNITRON_CSTXXX
+	tristate "Hynitron touchscreen support"
+	depends on I2C
+	help
+	  Say Y here if you have a touchscreen using a Hynitron
+	  touchscreen controller.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called hynitron-cstxxx.
+
 config TOUCHSCREEN_ILI210X
 	tristate "Ilitek ILI210X based touchscreen"
 	depends on I2C
drivers/input/touchscreen/Makefile +1 -0
index 557f84fd2075..43860ca19b98 100644
@@ -47,6 +47,7 @@ obj-$(CONFIG_TOUCHSCREEN_EXC3000)	+= exc3000.o
 obj-$(CONFIG_TOUCHSCREEN_FUJITSU)	+= fujitsu_ts.o
 obj-$(CONFIG_TOUCHSCREEN_GOODIX)	+= goodix_ts.o
 obj-$(CONFIG_TOUCHSCREEN_HIDEEP)	+= hideep.o
+obj-$(CONFIG_TOUCHSCREEN_HYNITRON_CSTXXX)	+= hynitron_cstxxx.o
 obj-$(CONFIG_TOUCHSCREEN_ILI210X)	+= ili210x.o
 obj-$(CONFIG_TOUCHSCREEN_ILITEK)	+= ilitek_ts_i2c.o
 obj-$(CONFIG_TOUCHSCREEN_IMAGIS)	+= imagis.o
drivers/input/touchscreen/hynitron_cstxxx.c new file +505 -0

505 lines not on this page · raw message

Signature · 1 line
2.25.1
maintainer
#4 lore raw

Re: [PATCH V4 3/3] input/touchscreen: Add Hynitron cstxxx touchscreen

Hi Chris,

Quoted 64 lines · Chris Morgan

From: Chris Morgan <[email protected]>

Add support for the Hynitron cst3xx controller found on devices such as the Anbernic RG353P and RG353V (the Hynitron CST340). This driver was built from sources provided by Hynitron to Anbernic (possibly via Rockchip as an intermediary) and marked as GPLv2 in the code. This driver was written strictly for the cst3xx series, but in most places was left somewhat generic so support could be easily added to other devices in the future.

---
 drivers/input/touchscreen/Kconfig           |  12 +
 drivers/input/touchscreen/Makefile          |   1 +
 drivers/input/touchscreen/hynitron_cstxxx.c | 505 ++++++++++++++++++++
 3 files changed, 518 insertions(+)
 create mode 100644 drivers/input/touchscreen/hynitron_cstxxx.c
drivers/input/touchscreen/Kconfig +12 -0
index dc90a3ea51ee..46b158c04c7b 100644
@@ -422,6 +422,18 @@ config TOUCHSCREEN_HYCON_HY46XX
 	  To compile this driver as a module, choose M here: the
 	  module will be called hycon-hy46xx.
 
+config TOUCHSCREEN_HYNITRON_CSTXXX
+	tristate "Hynitron touchscreen support"
+	depends on I2C
+	help
+	  Say Y here if you have a touchscreen using a Hynitron
+	  touchscreen controller.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called hynitron-cstxxx.
+
 config TOUCHSCREEN_ILI210X
 	tristate "Ilitek ILI210X based touchscreen"
 	depends on I2C
drivers/input/touchscreen/Makefile +1 -0
index 557f84fd2075..43860ca19b98 100644
@@ -47,6 +47,7 @@ obj-$(CONFIG_TOUCHSCREEN_EXC3000)	+= exc3000.o
 obj-$(CONFIG_TOUCHSCREEN_FUJITSU)	+= fujitsu_ts.o
 obj-$(CONFIG_TOUCHSCREEN_GOODIX)	+= goodix_ts.o
 obj-$(CONFIG_TOUCHSCREEN_HIDEEP)	+= hideep.o
+obj-$(CONFIG_TOUCHSCREEN_HYNITRON_CSTXXX)	+= hynitron_cstxxx.o
 obj-$(CONFIG_TOUCHSCREEN_ILI210X)	+= ili210x.o
 obj-$(CONFIG_TOUCHSCREEN_ILITEK)	+= ilitek_ts_i2c.o
 obj-$(CONFIG_TOUCHSCREEN_IMAGIS)	+= imagis.o
drivers/input/touchscreen/hynitron_cstxxx.c new file +5 -0
new file mode 100644
index 000000000000..ca39e8a775b7
@@ -0,0 +1,505 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ *  Driver for Hynitron cstxxx Touchscreen
+ *
+ *  Copyright (c) 2022 Chris Morgan <[email protected]>

drivers/input/touchscreen/hynitron_cstxxx.c line 15

Quoted 10 lines
drivers/input/touchscreen/hynitron_cstxxx.c new file +10 -0
+ *
+ *  This code is based on hynitron_core.c authored by Hynitron.
+ *  Note that no datasheet was available, so much of these registers
+ *  are undocumented. This is essentially a cleaned-up version of the
+ *  vendor driver with support removed for hardware I cannot test and
+ *  device-specific functions replated with generic functions wherever
+ *  possible.
+ */
+
+#include <asm/unaligned.h>

For the future: "asm" goes after "linux".

Quoted 16 lines
drivers/input/touchscreen/hynitron_cstxxx.c new file +16 -0
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/input/touchscreen.h>
+#include <linux/module.h>
+
+/* Per chip data */
+struct hynitron_ts_chip_data {
+	unsigned int max_touch_num;
+	u32 ic_chkcode;
+	int (*firmware_info)(struct i2c_client *client);
+	int (*bootloader_enter)(struct i2c_client *client);
+	int (*init_input)(struct i2c_client *client);
+	void (*report_touch)(struct i2c_client *client);

drivers/input/touchscreen/hynitron_cstxxx.c line 41

Quoted 10 lines
drivers/input/touchscreen/hynitron_cstxxx.c new file +10 -0
+};
+
+/* Data generic to all (supported and non-supported) controllers. */
+struct hynitron_ts_data {
+	const struct hynitron_ts_chip_data *pdata;
+	struct i2c_client *client;
+	struct input_dev *input_dev;
+	struct touchscreen_properties prop;
+	struct gpio_desc *reset_gpio;
+	struct gpio_desc *irq_gpio;

I do not believe irq_gpio is used so I'll drop it.

Quoted 84 lines
drivers/input/touchscreen/hynitron_cstxxx.c new file +84 -0
+};
+
+/*
+ * Since I have no datasheet, these values are guessed and/or assumed
+ * based on observation and testing.
+ */
+#define CST3XX_FIRMWARE_INFO_START_CMD		0x01d1
+#define CST3XX_FIRMWARE_INFO_END_CMD		0x09d1
+#define CST3XX_FIRMWARE_CHK_CODE_REG		0xfcd1
+#define CST3XX_FIRMWARE_VERSION_REG		0x08d2
+#define CST3XX_FIRMWARE_VER_INVALID_VAL		0xa5a5a5a5
+
+#define CST3XX_BOOTLDR_PROG_CMD			0xaa01a0
+#define CST3XX_BOOTLDR_PROG_CHK_REG		0x02a0
+#define CST3XX_BOOTLDR_CHK_VAL			0xac
+
+#define CST3XX_TOUCH_DATA_PART_REG		0x00d0
+#define CST3XX_TOUCH_DATA_FULL_REG		0x07d0
+#define CST3XX_TOUCH_DATA_CHK_VAL		0xab
+#define CST3XX_TOUCH_DATA_TOUCH_VAL		0x03
+#define CST3XX_TOUCH_DATA_STOP_CMD		0xab00d0
+#define CST3XX_TOUCH_COUNT_MASK			GENMASK(6, 0)
+
+
+/*
+ * Hard coded reset delay value of 20ms not IC dependent in
+ * vendor driver.
+ */
+static void hyn_reset_proc(struct i2c_client *client, int delay)
+{
+	struct hynitron_ts_data *ts_data = i2c_get_clientdata(client);
+
+	gpiod_set_value_cansleep(ts_data->reset_gpio, 1);
+	mdelay(20);
+	gpiod_set_value_cansleep(ts_data->reset_gpio, 0);
+	if (delay)
+		mdelay(delay);
+}
+
+static irqreturn_t hyn_interrupt_handler(int irq, void *dev_id)
+{
+	struct i2c_client *client = dev_id;
+	struct hynitron_ts_data *ts_data = i2c_get_clientdata(client);
+
+	ts_data->pdata->report_touch(client);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * The vendor driver would retry twice before failing to read or write
+ * to the i2c device.
+ */
+
+static int cst3xx_i2c_write(struct i2c_client *client,
+			    unsigned char *buf, int len)
+{
+	int ret;
+	int retries = 0;
+
+	while (retries < 2) {
+		ret = i2c_master_send(client, buf, len);
+		if (ret == len)
+			return 0;
+		if (ret <= 0)
+			retries++;
+		else
+			break;
+	}
+
+	return ret < 0 ? ret : -EIO;
+}
+
+static int cst3xx_i2c_read_register(struct i2c_client *client, u16 reg,
+				    u8 *val, u16 len)
+{
+	__le16 buf = cpu_to_le16(reg);
+	struct i2c_msg msgs[] = {
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = 2,
+			.buf = (u8 *)&buf,
+		},

drivers/input/touchscreen/hynitron_cstxxx.c line 135

Quoted 10 lines
drivers/input/touchscreen/hynitron_cstxxx.c new file +10 -0
+		{
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+			.len = len,
+			.buf = val,
+		}
+	};
+	int ret;
+
+	ret = i2c_transfer(client->adapter, msgs, 2);

ARRAY_SIZE() instead of 2 is better here.

Quoted 15 lines
drivers/input/touchscreen/hynitron_cstxxx.c new file +15 -0
+	if (ret >= 0)
+		ret = (ret == ARRAY_SIZE(msgs) ? 0 : -EIO);
+
+	if (ret)
+		dev_err(&client->dev,
+			"Error reading %d bytes from 0x%04x: %d\n",
+			len, reg, ret);
+
+	return ret;
+}
+
+static int cst3xx_firmware_info(struct i2c_client *client)
+{
+	struct hynitron_ts_data *ts_data = i2c_get_clientdata(client);
+	int ret;

drivers/input/touchscreen/hynitron_cstxxx.c line 160

Quoted 10 lines
drivers/input/touchscreen/hynitron_cstxxx.c new file +10 -0
+	u32 tmp;
+	unsigned char buf[4];
+
+	/*
+	 * Tests suggest this command needed to read firmware regs.
+	 */
+	put_unaligned_le16(CST3XX_FIRMWARE_INFO_START_CMD, buf);
+	ret = cst3xx_i2c_write(client, buf, 2);
+	if (ret < 0)
+		return -EIO;

I do not think we should be overriding errors returned by cst3xx_i2c_write() and friends.

I'll update on my end, no need to resubmit.

Thanks.

Signature · 1 line
Dmitry
maintainer
#5 lore raw

Re: [PATCH V4 3/3] input/touchscreen: Add Hynitron cstxxx touchscreen

In reply to Chris Morgan

Hi Chris,

drivers/input/touchscreen/hynitron_cstxxx.c line 78

Quoted 9 lines · Chris Morgan
drivers/input/touchscreen/hynitron_cstxxx.c new file +9 -0
+static void hyn_reset_proc(struct i2c_client *client, int delay)
+{
+	struct hynitron_ts_data *ts_data = i2c_get_clientdata(client);
+
+	gpiod_set_value_cansleep(ts_data->reset_gpio, 1);
+	mdelay(20);
+	gpiod_set_value_cansleep(ts_data->reset_gpio, 0);
+	if (delay)
+		mdelay(delay);

Just wanted to ask - you do not really want to spin for 20+ msecs here, right? I think changing mdelay() to msleep()/usleep() should be OK throughout the driver...

Thanks.

Signature · 1 line
Dmitry
#6 lore raw

Re: [PATCH V4 3/3] input/touchscreen: Add Hynitron cstxxx touchscreen

Quoted 16 lines · Dmitry Torokhov

Hi Chris,

drivers/input/touchscreen/hynitron_cstxxx.c line 78

Quoted 9 lines · Chris Morgan
drivers/input/touchscreen/hynitron_cstxxx.c new file +9 -0
+static void hyn_reset_proc(struct i2c_client *client, int delay)
+{
+	struct hynitron_ts_data *ts_data = i2c_get_clientdata(client);
+
+	gpiod_set_value_cansleep(ts_data->reset_gpio, 1);
+	mdelay(20);
+	gpiod_set_value_cansleep(ts_data->reset_gpio, 0);
+	if (delay)
+		mdelay(delay);

Just wanted to ask - you do not really want to spin for 20+ msecs here, right? I think changing mdelay() to msleep()/usleep() should be OK throughout the driver...

I just tested changing all instances of mdelay to msleep and msleep works just fine. Do you want me to resubmit or can you change that as well?

Thank you.

Quoted 5 lines

Thanks.

Signature · 1 line
Dmitry
maintainer
#7 lore raw

Re: [PATCH V4 3/3] input/touchscreen: Add Hynitron cstxxx touchscreen

Quoted 18 lines · Chris Morgan
Quoted 16 lines · Dmitry Torokhov

Hi Chris,

drivers/input/touchscreen/hynitron_cstxxx.c line 78

Quoted 9 lines · Chris Morgan
drivers/input/touchscreen/hynitron_cstxxx.c new file +9 -0
+static void hyn_reset_proc(struct i2c_client *client, int delay)
+{
+	struct hynitron_ts_data *ts_data = i2c_get_clientdata(client);
+
+	gpiod_set_value_cansleep(ts_data->reset_gpio, 1);
+	mdelay(20);
+	gpiod_set_value_cansleep(ts_data->reset_gpio, 0);
+	if (delay)
+		mdelay(delay);

Just wanted to ask - you do not really want to spin for 20+ msecs here, right? I think changing mdelay() to msleep()/usleep() should be OK throughout the driver...

Quoted 2 lines

I just tested changing all instances of mdelay to msleep and msleep works just fine. Do you want me to resubmit or can you change that as well?

No need. I made a few additional changes and applied. Please take a look in my 'next' branch and yell if something is wrong.

Thanks.

Signature · 1 line
Dmitry