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