1 /*
2 * Copyright (c) 2024 Joel Jaldemark
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT ilitek_ili2132a
8
9 #include <zephyr/drivers/gpio.h>
10 #include <zephyr/drivers/i2c.h>
11 #include <zephyr/input/input.h>
12 #include <zephyr/pm/device.h>
13 #include <zephyr/sys/byteorder.h>
14
15 #include <zephyr/logging/log.h>
16 LOG_MODULE_REGISTER(ili2132a, CONFIG_INPUT_LOG_LEVEL);
17
18 #define IS_TOUCHED_BIT 0x40
19 #define TIP 1
20 #define X_COORD 2
21 #define Y_COORD 4
22
23 struct ili2132a_data {
24 const struct device *dev;
25 struct gpio_callback gpio_cb;
26 struct k_work work;
27 };
28
29 struct ili2132a_config {
30 struct i2c_dt_spec i2c;
31 struct gpio_dt_spec rst;
32 struct gpio_dt_spec irq;
33 };
34
gpio_isr(const struct device * dev,struct gpio_callback * cb,uint32_t pin)35 static void gpio_isr(const struct device *dev, struct gpio_callback *cb, uint32_t pin)
36 {
37 struct ili2132a_data *data = CONTAINER_OF(cb, struct ili2132a_data, gpio_cb);
38
39 k_work_submit(&data->work);
40 }
41
ili2132a_process(const struct device * dev)42 static void ili2132a_process(const struct device *dev)
43 {
44 const struct ili2132a_config *dev_cfg = dev->config;
45 uint8_t buf[8];
46 uint16_t x, y;
47 int ret;
48
49 ret = i2c_read_dt(&dev_cfg->i2c, buf, sizeof(buf));
50 if (ret < 0) {
51 LOG_ERR("Failed to read data: %d", ret);
52 return;
53 }
54
55 if (buf[TIP] & IS_TOUCHED_BIT) {
56 x = sys_get_le16(&buf[X_COORD]);
57 y = sys_get_le16(&buf[Y_COORD]);
58 input_report_abs(dev, INPUT_ABS_X, x, false, K_FOREVER);
59 input_report_abs(dev, INPUT_ABS_Y, y, false, K_FOREVER);
60 input_report_key(dev, INPUT_BTN_TOUCH, 1, true, K_FOREVER);
61 } else {
62 input_report_key(dev, INPUT_BTN_TOUCH, 0, true, K_FOREVER);
63 }
64 }
65
ili2132a_work_handler(struct k_work * work_item)66 static void ili2132a_work_handler(struct k_work *work_item)
67 {
68 struct ili2132a_data *data = CONTAINER_OF(work_item, struct ili2132a_data, work);
69
70 ili2132a_process(data->dev);
71 }
72
ili2132a_init(const struct device * dev)73 static int ili2132a_init(const struct device *dev)
74 {
75 struct ili2132a_data *data = dev->data;
76 const struct ili2132a_config *dev_cfg = dev->config;
77 int ret;
78
79 if (!i2c_is_ready_dt(&dev_cfg->i2c)) {
80 LOG_ERR("%s is not ready", dev_cfg->i2c.bus->name);
81 return -ENODEV;
82 }
83
84 if (!gpio_is_ready_dt(&dev_cfg->rst)) {
85 LOG_ERR("Reset GPIO controller device not ready");
86 return -ENODEV;
87 }
88
89 if (!gpio_is_ready_dt(&dev_cfg->irq)) {
90 LOG_ERR("Interrupt GPIO controller device not ready");
91 return -ENODEV;
92 }
93
94 data->dev = dev;
95
96 ret = gpio_pin_configure_dt(&dev_cfg->irq, GPIO_INPUT);
97 if (ret < 0) {
98 LOG_ERR("Could not configure interrupt gpio");
99 return ret;
100 }
101
102 ret = gpio_pin_configure_dt(&dev_cfg->rst, GPIO_OUTPUT_ACTIVE);
103 if (ret < 0) {
104 LOG_ERR("Could not configure reset gpio");
105 return ret;
106 }
107
108 ret = gpio_pin_set_dt(&dev_cfg->rst, 0);
109 if (ret < 0) {
110 return ret;
111 }
112
113 gpio_init_callback(&data->gpio_cb, gpio_isr, BIT(dev_cfg->irq.pin));
114 ret = gpio_add_callback(dev_cfg->irq.port, &data->gpio_cb);
115 if (ret < 0) {
116 LOG_ERR("Could not set gpio callback");
117 return ret;
118 }
119
120 ret = gpio_pin_interrupt_configure_dt(&dev_cfg->irq, GPIO_INT_EDGE_FALLING);
121 if (ret < 0) {
122 LOG_ERR("Could not configure interrupt");
123 return ret;
124 }
125
126 k_work_init(&data->work, ili2132a_work_handler);
127
128 return 0;
129 }
130 #define ILI2132A_INIT(index) \
131 static const struct ili2132a_config ili2132a_config_##index = { \
132 .i2c = I2C_DT_SPEC_INST_GET(index), \
133 .rst = GPIO_DT_SPEC_INST_GET(index, rst_gpios), \
134 .irq = GPIO_DT_SPEC_INST_GET(index, irq_gpios), \
135 }; \
136 static struct ili2132a_data ili2132a_data_##index; \
137 DEVICE_DT_INST_DEFINE(index, ili2132a_init, NULL, &ili2132a_data_##index, \
138 &ili2132a_config_##index, POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, \
139 NULL);
140
141 DT_INST_FOREACH_STATUS_OKAY(ILI2132A_INIT)
142