From 2a1fde7aa3f540bb6bd5e1b14e54dd9fb7a185b8 Mon Sep 17 00:00:00 2001 From: Joel Jaldemark Date: Wed, 9 Oct 2024 07:25:59 +0200 Subject: [PATCH] drivers: input: ili2132a: add support for ili2132a touch controller This commit adds basic ili2132a touch controller driver. Signed-off-by: Joel Jaldemark --- drivers/input/CMakeLists.txt | 1 + drivers/input/Kconfig | 1 + drivers/input/Kconfig.ili2132a | 10 ++ drivers/input/input_ili2132a.c | 135 ++++++++++++++++++++++ dts/bindings/input/ilitek,ili2132a.yaml | 21 ++++ tests/drivers/build_all/input/app.overlay | 8 ++ 6 files changed, 176 insertions(+) create mode 100644 drivers/input/Kconfig.ili2132a create mode 100644 drivers/input/input_ili2132a.c create mode 100644 dts/bindings/input/ilitek,ili2132a.yaml diff --git a/drivers/input/CMakeLists.txt b/drivers/input/CMakeLists.txt index aa1f843476288c..47eea1a1e1ea51 100644 --- a/drivers/input/CMakeLists.txt +++ b/drivers/input/CMakeLists.txt @@ -17,6 +17,7 @@ zephyr_library_sources_ifdef(CONFIG_INPUT_GPIO_KBD_MATRIX input_gpio_kbd_matrix. zephyr_library_sources_ifdef(CONFIG_INPUT_GPIO_KEYS input_gpio_keys.c) zephyr_library_sources_ifdef(CONFIG_INPUT_GPIO_QDEC input_gpio_qdec.c) zephyr_library_sources_ifdef(CONFIG_INPUT_GT911 input_gt911.c) +zephyr_library_sources_ifdef(CONFIG_INPUT_ILI2132A input_ili2132a.c) zephyr_library_sources_ifdef(CONFIG_INPUT_ITE_IT8XXX2_KBD input_ite_it8xxx2_kbd.c) zephyr_library_sources_ifdef(CONFIG_INPUT_KBD_MATRIX input_kbd_matrix.c) zephyr_library_sources_ifdef(CONFIG_INPUT_NPCX_KBD input_npcx_kbd.c) diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index e76d3fc6fc76bd..ba0541398f666a 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -19,6 +19,7 @@ source "drivers/input/Kconfig.gpio_kbd_matrix" source "drivers/input/Kconfig.gpio_keys" source "drivers/input/Kconfig.gpio_qdec" source "drivers/input/Kconfig.gt911" +source "drivers/input/Kconfig.ili2132a" source "drivers/input/Kconfig.it8xxx2" source "drivers/input/Kconfig.kbd_matrix" source "drivers/input/Kconfig.npcx" diff --git a/drivers/input/Kconfig.ili2132a b/drivers/input/Kconfig.ili2132a new file mode 100644 index 00000000000000..911b5a8699385d --- /dev/null +++ b/drivers/input/Kconfig.ili2132a @@ -0,0 +1,10 @@ +# Copyright (c) 2024 Joel Jaldemark +# SPDX-License-Identifier: Apache-2.0 + +config INPUT_ILI2132A + bool "ILI2132A capacitive touch controller driver" + default y + depends on DT_HAS_ILITEK_ILI2132A_ENABLED + select I2C + help + Enable driver for ilitek ili2132a touch controller diff --git a/drivers/input/input_ili2132a.c b/drivers/input/input_ili2132a.c new file mode 100644 index 00000000000000..be31f55bae0c5a --- /dev/null +++ b/drivers/input/input_ili2132a.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2024 Joel Jaldemark + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ilitek_ili2132a + +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(ili2132a, CONFIG_INPUT_LOG_LEVEL); + +#define IS_TOUCHED_BIT 0x40 +#define TIP 1 +#define X_COORD 2 +#define Y_COORD 4 + +struct ili2132a_data { + const struct device *dev; + struct gpio_callback gpio_cb; + struct k_work work; +}; + +struct ili2132a_config { + struct i2c_dt_spec i2c; + struct gpio_dt_spec rst; + struct gpio_dt_spec irq; +}; + +static void gpio_isr(const struct device *dev, struct gpio_callback *cb, uint32_t pin) +{ + struct ili2132a_data *data = CONTAINER_OF(cb, struct ili2132a_data, gpio_cb); + + k_work_submit(&data->work); +} + +static void ili2132a_process(const struct device *dev) +{ + const struct ili2132a_config *dev_cfg = dev->config; + uint8_t buf[8]; + uint16_t x, y; + + i2c_read_dt(&dev_cfg->i2c, buf, sizeof(buf)); + if (buf[TIP] & IS_TOUCHED_BIT) { + x = sys_get_le16(&buf[X_COORD]); + y = sys_get_le16(&buf[Y_COORD]); + input_report_abs(dev, INPUT_ABS_X, x, false, K_FOREVER); + input_report_abs(dev, INPUT_ABS_Y, y, false, K_FOREVER); + input_report_key(dev, INPUT_BTN_TOUCH, 1, true, K_FOREVER); + } else { + input_report_key(dev, INPUT_BTN_TOUCH, 0, true, K_FOREVER); + } +} + +static void ili2132a_work_handler(struct k_work *work_item) +{ + struct ili2132a_data *data = CONTAINER_OF(work_item, struct ili2132a_data, work); + + ili2132a_process(data->dev); +} + +static int ili2132a_init(const struct device *dev) +{ + struct ili2132a_data *data = dev->data; + const struct ili2132a_config *dev_cfg = dev->config; + int ret; + + if (!i2c_is_ready_dt(&dev_cfg->i2c)) { + LOG_ERR("%s is not ready", dev_cfg->i2c.bus->name); + return -ENODEV; + } + + if (!gpio_is_ready_dt(&dev_cfg->rst)) { + LOG_ERR("Reset GPIO controller device not ready"); + return -ENODEV; + } + + if (!gpio_is_ready_dt(&dev_cfg->irq)) { + LOG_ERR("Interrupt GPIO controller device not ready"); + return -ENODEV; + } + + data->dev = dev; + + ret = gpio_pin_configure_dt(&dev_cfg->irq, GPIO_INPUT); + if (ret < 0) { + LOG_ERR("Could not configure interrupt gpio"); + return ret; + } + + ret = gpio_pin_configure_dt(&dev_cfg->rst, GPIO_OUTPUT_ACTIVE); + if (ret < 0) { + LOG_ERR("Could not configure reset gpio"); + return ret; + } + + ret = gpio_pin_set_dt(&dev_cfg->rst, 0); + if (ret < 0) { + return ret; + } + + gpio_init_callback(&data->gpio_cb, gpio_isr, BIT(dev_cfg->irq.pin)); + ret = gpio_add_callback(dev_cfg->irq.port, &data->gpio_cb); + if (ret < 0) { + LOG_ERR("Could not set gpio callback"); + return ret; + } + + ret = gpio_pin_interrupt_configure_dt(&dev_cfg->irq, GPIO_INT_EDGE_FALLING); + if (ret < 0) { + LOG_ERR("Could not configure interrupt"); + return ret; + } + + k_work_init(&data->work, ili2132a_work_handler); + + return 0; +} +#define ILI2132A_INIT(index) \ + static const struct ili2132a_config ili2132a_config_##index = { \ + .i2c = I2C_DT_SPEC_INST_GET(index), \ + .rst = GPIO_DT_SPEC_INST_GET(index, rst_gpios), \ + .irq = GPIO_DT_SPEC_INST_GET(index, irq_gpios), \ + }; \ + static struct ili2132a_data ili2132a_data_##index; \ + DEVICE_DT_INST_DEFINE(index, ili2132a_init, NULL, &ili2132a_data_##index, \ + &ili2132a_config_##index, POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, \ + NULL); + +DT_INST_FOREACH_STATUS_OKAY(ILI2132A_INIT) diff --git a/dts/bindings/input/ilitek,ili2132a.yaml b/dts/bindings/input/ilitek,ili2132a.yaml new file mode 100644 index 00000000000000..a1aef2ad34e66e --- /dev/null +++ b/dts/bindings/input/ilitek,ili2132a.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2024 Joel Jaldemark +# SPDX-License-Identifier: Apache-2.0 + +description: ILI2132A capacitive touch controller + +compatible: "ilitek,ili2132a" + +include: i2c-device.yaml + +properties: + irq-gpios: + type: phandle-array + required: true + description: | + Interrupt pin + + rst-gpios: + type: phandle-array + required: true + description: | + Reset pin diff --git a/tests/drivers/build_all/input/app.overlay b/tests/drivers/build_all/input/app.overlay index 80be92b765d25b..3873a6b14ac98f 100644 --- a/tests/drivers/build_all/input/app.overlay +++ b/tests/drivers/build_all/input/app.overlay @@ -261,6 +261,14 @@ primary-tap-enable; swap-xy; }; + + touch_dev: ili2132a@41 { + compatible = "ilitek,ili2132a"; + reg = <0x41>; + irq-gpios = <&test_gpio 0 0>; + rst-gpios = <&test_gpio 1 0>; + }; + }; spi@2 {