1 /*
2 * Copyright (c) 2021 Qingsong Gou <gouqs@hotmail.com>
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT hynitron_cst816s
8
9 #include <zephyr/sys/byteorder.h>
10 #include <zephyr/input/input.h>
11 #include <zephyr/drivers/i2c.h>
12 #include <zephyr/drivers/gpio.h>
13 #include <zephyr/logging/log.h>
14 #include <zephyr/dt-bindings/input/cst816s-gesture-codes.h>
15
16 LOG_MODULE_REGISTER(cst816s, CONFIG_INPUT_LOG_LEVEL);
17
18 #define CST816S_CHIP_ID1 0xB4
19 #define CST816S_CHIP_ID2 0xB5
20 #define CST816S_CHIP_ID3 0xB6
21
22 #define CST816S_REG_DATA 0x00
23 #define CST816S_REG_GESTURE_ID 0x01
24 #define CST816S_REG_FINGER_NUM 0x02
25 #define CST816S_REG_XPOS_H 0x03
26 #define CST816S_REG_XPOS_L 0x04
27 #define CST816S_REG_YPOS_H 0x05
28 #define CST816S_REG_YPOS_L 0x06
29 #define CST816S_REG_BPC0H 0xB0
30 #define CST816S_REG_BPC0L 0xB1
31 #define CST816S_REG_BPC1H 0xB2
32 #define CST816S_REG_BPC1L 0xB3
33 #define CST816S_REG_POWER_MODE 0xA5
34 #define CST816S_REG_CHIP_ID 0xA7
35 #define CST816S_REG_PROJ_ID 0xA8
36 #define CST816S_REG_FW_VERSION 0xA9
37 #define CST816S_REG_MOTION_MASK 0xEC
38 #define CST816S_REG_IRQ_PULSE_WIDTH 0xED
39 #define CST816S_REG_NOR_SCAN_PER 0xEE
40 #define CST816S_REG_MOTION_S1_ANGLE 0xEF
41 #define CST816S_REG_LP_SCAN_RAW1H 0xF0
42 #define CST816S_REG_LP_SCAN_RAW1L 0xF1
43 #define CST816S_REG_LP_SCAN_RAW2H 0xF2
44 #define CST816S_REG_LP_SCAN_RAW2L 0xF3
45 #define CST816S_REG_LP_AUTO_WAKEUP_TIME 0xF4
46 #define CST816S_REG_LP_SCAN_TH 0xF5
47 #define CST816S_REG_LP_SCAN_WIN 0xF6
48 #define CST816S_REG_LP_SCAN_FREQ 0xF7
49 #define CST816S_REG_LP_SCAN_I_DAC 0xF8
50 #define CST816S_REG_AUTOSLEEP_TIME 0xF9
51 #define CST816S_REG_IRQ_CTL 0xFA
52 #define CST816S_REG_DEBOUNCE_TIME 0xFB
53 #define CST816S_REG_LONG_PRESS_TIME 0xFC
54 #define CST816S_REG_IOCTL 0xFD
55 #define CST816S_REG_DIS_AUTO_SLEEP 0xFE
56
57 #define CST816S_MOTION_EN_CON_LR BIT(2)
58 #define CST816S_MOTION_EN_CON_UR BIT(1)
59 #define CST816S_MOTION_EN_DCLICK BIT(0)
60
61 #define CST816S_IRQ_EN_TEST BIT(7)
62 #define CST816S_IRQ_EN_TOUCH BIT(6)
63 #define CST816S_IRQ_EN_CHANGE BIT(5)
64 #define CST816S_IRQ_EN_MOTION BIT(4)
65 #define CST816S_IRQ_ONCE_WLP BIT(0)
66
67 #define CST816S_IOCTL_SOFT_RTS BIT(2)
68 #define CST816S_IOCTL_IIC_OD BIT(1)
69 #define CST816S_IOCTL_EN_1V8 BIT(0)
70
71 #define CST816S_POWER_MODE_SLEEP (0x03)
72 #define CST816S_POWER_MODE_EXPERIMENTAL (0x05)
73
74 #define CST816S_EVENT_BITS_POS (0x06)
75
76 #define CST816S_RESET_DELAY (5) /* in ms */
77 #define CST816S_WAIT_DELAY (50) /* in ms */
78
79 #define EVENT_PRESS_DOWN 0x00U
80 #define EVENT_LIFT_UP 0x01U
81 #define EVENT_CONTACT 0x02U
82 #define EVENT_NONE 0x03U
83
84 /** cst816s configuration (DT). */
85 struct cst816s_config {
86 struct i2c_dt_spec i2c;
87 const struct gpio_dt_spec rst_gpio;
88 #ifdef CONFIG_INPUT_CST816S_INTERRUPT
89 const struct gpio_dt_spec int_gpio;
90 #endif
91 };
92
93 /** cst816s data. */
94 struct cst816s_data {
95 /** Device pointer. */
96 const struct device *dev;
97 /** Work queue (for deferred read). */
98 struct k_work work;
99
100 #ifdef CONFIG_INPUT_CST816S_INTERRUPT
101 /** Interrupt GPIO callback. */
102 struct gpio_callback int_gpio_cb;
103 #else
104 /** Timer (polling mode). */
105 struct k_timer timer;
106 #endif
107 };
108
cst816s_process(const struct device * dev)109 static int cst816s_process(const struct device *dev)
110 {
111 const struct cst816s_config *cfg = dev->config;
112
113 int r;
114 uint8_t event;
115 uint16_t row, col;
116 bool pressed;
117 uint16_t x;
118 uint16_t y;
119
120 #ifdef CONFIG_INPUT_CST816S_EV_DEVICE
121 uint8_t gesture;
122
123 r = i2c_burst_read_dt(&cfg->i2c, CST816S_REG_GESTURE_ID, &gesture, sizeof(gesture));
124 if (r < 0) {
125 LOG_ERR("Could not read gesture-ID data");
126 return r;
127 }
128 #endif
129
130 r = i2c_burst_read_dt(&cfg->i2c, CST816S_REG_XPOS_H, (uint8_t *)&x, sizeof(x));
131 if (r < 0) {
132 LOG_ERR("Could not read x data");
133 return r;
134 }
135
136 r = i2c_burst_read_dt(&cfg->i2c, CST816S_REG_YPOS_H, (uint8_t *)&y, sizeof(y));
137 if (r < 0) {
138 LOG_ERR("Could not read y data");
139 return r;
140 }
141 col = sys_be16_to_cpu(x) & 0x0fff;
142 row = sys_be16_to_cpu(y) & 0x0fff;
143
144 event = (x & 0xff) >> CST816S_EVENT_BITS_POS;
145 pressed = (event == EVENT_PRESS_DOWN) || (event == EVENT_CONTACT);
146
147 LOG_DBG("event: %d, row: %d, col: %d", event, row, col);
148
149 if (pressed) {
150 input_report_abs(dev, INPUT_ABS_X, col, false, K_FOREVER);
151 input_report_abs(dev, INPUT_ABS_Y, row, false, K_FOREVER);
152 input_report_key(dev, INPUT_BTN_TOUCH, 1, true, K_FOREVER);
153 } else {
154 input_report_key(dev, INPUT_BTN_TOUCH, 0, true, K_FOREVER);
155 }
156
157 #ifdef CONFIG_INPUT_CST816S_EV_DEVICE
158 /* Also put the custom touch gestures into the input queue,
159 * some applications may want to process it
160 */
161
162 LOG_DBG("gesture: %d", gesture);
163
164 if (gesture != CST816S_GESTURE_CODE_NONE) {
165 input_report(dev, INPUT_EV_DEVICE, (uint16_t)gesture, 0, true, K_FOREVER);
166 }
167 #endif
168
169 return r;
170 }
171
cst816s_work_handler(struct k_work * work)172 static void cst816s_work_handler(struct k_work *work)
173 {
174 struct cst816s_data *data = CONTAINER_OF(work, struct cst816s_data, work);
175
176 cst816s_process(data->dev);
177 }
178
179 #ifdef CONFIG_INPUT_CST816S_INTERRUPT
cst816s_isr_handler(const struct device * dev,struct gpio_callback * cb,uint32_t pins)180 static void cst816s_isr_handler(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
181 {
182 struct cst816s_data *data = CONTAINER_OF(cb, struct cst816s_data, int_gpio_cb);
183
184 k_work_submit(&data->work);
185 }
186 #else
cst816s_timer_handler(struct k_timer * timer)187 static void cst816s_timer_handler(struct k_timer *timer)
188 {
189 struct cst816s_data *data = CONTAINER_OF(timer, struct cst816s_data, timer);
190
191 k_work_submit(&data->work);
192 }
193 #endif
194
cst816s_chip_reset(const struct device * dev)195 static void cst816s_chip_reset(const struct device *dev)
196 {
197 const struct cst816s_config *config = dev->config;
198 int ret;
199
200 if (gpio_is_ready_dt(&config->rst_gpio)) {
201 ret = gpio_pin_configure_dt(&config->rst_gpio, GPIO_OUTPUT_ACTIVE);
202 if (ret < 0) {
203 LOG_ERR("Could not configure reset GPIO pin");
204 return;
205 }
206 k_msleep(CST816S_RESET_DELAY);
207 gpio_pin_set_dt(&config->rst_gpio, 0);
208 k_msleep(CST816S_WAIT_DELAY);
209 }
210 }
211
cst816s_chip_init(const struct device * dev)212 static int cst816s_chip_init(const struct device *dev)
213 {
214 const struct cst816s_config *cfg = dev->config;
215 int ret = 0;
216 uint8_t chip_id = 0;
217
218 cst816s_chip_reset(dev);
219
220 if (!device_is_ready(cfg->i2c.bus)) {
221 LOG_ERR("I2C bus %s not ready", cfg->i2c.bus->name);
222 return -ENODEV;
223 }
224 ret = i2c_reg_read_byte_dt(&cfg->i2c, CST816S_REG_CHIP_ID, &chip_id);
225 if (ret < 0) {
226 LOG_ERR("failed reading chip id");
227 return ret;
228 }
229
230 if ((chip_id != CST816S_CHIP_ID1) && (chip_id != CST816S_CHIP_ID2) &&
231 (chip_id != CST816S_CHIP_ID3)) {
232 LOG_ERR("CST816S wrong chip id: returned 0x%x", chip_id);
233 return -ENODEV;
234 }
235
236 ret = i2c_reg_update_byte_dt(&cfg->i2c, CST816S_REG_IRQ_CTL,
237 CST816S_IRQ_EN_TOUCH | CST816S_IRQ_EN_CHANGE,
238 CST816S_IRQ_EN_TOUCH | CST816S_IRQ_EN_CHANGE);
239 if (ret < 0) {
240 LOG_ERR("Could not enable irq");
241 return ret;
242 }
243 return ret;
244 }
245
cst816s_init(const struct device * dev)246 static int cst816s_init(const struct device *dev)
247 {
248 struct cst816s_data *data = dev->data;
249 int ret;
250
251 data->dev = dev;
252 k_work_init(&data->work, cst816s_work_handler);
253
254 ret = cst816s_chip_init(dev);
255 if (ret < 0) {
256 return ret;
257 }
258
259 #ifdef CONFIG_INPUT_CST816S_INTERRUPT
260 const struct cst816s_config *config = dev->config;
261
262 if (!gpio_is_ready_dt(&config->int_gpio)) {
263 LOG_ERR("GPIO port %s not ready", config->int_gpio.port->name);
264 return -ENODEV;
265 }
266
267 ret = gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT);
268 if (ret < 0) {
269 LOG_ERR("Could not configure interrupt GPIO pin");
270 return ret;
271 }
272
273 ret = gpio_pin_interrupt_configure_dt(&config->int_gpio, GPIO_INT_EDGE_TO_ACTIVE);
274 if (ret < 0) {
275 LOG_ERR("Could not configure interrupt GPIO interrupt.");
276 return ret;
277 }
278
279 gpio_init_callback(&data->int_gpio_cb, cst816s_isr_handler, BIT(config->int_gpio.pin));
280
281 ret = gpio_add_callback(config->int_gpio.port, &data->int_gpio_cb);
282 if (ret < 0) {
283 LOG_ERR("Could not set gpio callback");
284 return ret;
285 }
286 #else
287 k_timer_init(&data->timer, cst816s_timer_handler, NULL);
288 k_timer_start(&data->timer, K_MSEC(CONFIG_INPUT_CST816S_PERIOD),
289 K_MSEC(CONFIG_INPUT_CST816S_PERIOD));
290 #endif
291
292 return ret;
293 }
294
295 #define CST816S_DEFINE(index) \
296 static const struct cst816s_config cst816s_config_##index = { \
297 .i2c = I2C_DT_SPEC_INST_GET(index), \
298 COND_CODE_1(CONFIG_INPUT_CST816S_INTERRUPT, \
299 (.int_gpio = GPIO_DT_SPEC_INST_GET(index, irq_gpios),), ()) \
300 .rst_gpio = GPIO_DT_SPEC_INST_GET_OR(index, rst_gpios, {}), \
301 }; \
302 static struct cst816s_data cst816s_data_##index; \
303 DEVICE_DT_INST_DEFINE(index, cst816s_init, NULL, &cst816s_data_##index, \
304 &cst816s_config_##index, POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, \
305 NULL);
306
307 DT_INST_FOREACH_STATUS_OKAY(CST816S_DEFINE)
308