Skip to content

Commit c2db81c

Browse files
committed
initial work on touch input
1 parent f4df447 commit c2db81c

File tree

3 files changed

+262
-17
lines changed

3 files changed

+262
-17
lines changed

boards/nxp/mimxrt700_evk/mimxrt700_evk_mimxrt798s_cm33_cpu0.dts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ zephyr_udc0: &usb0 {
403403
pinctrl-names = "default";
404404
};
405405

406-
p3t1755dp_ard_i2c_interface: &flexcomm8_lpi2c8 {};
406+
//p3t1755dp_ard_i2c_interface: &flexcomm8_lpi2c8 {};
407407

408408
&rtc0 {
409409
status = "okay";
@@ -421,6 +421,3 @@ p3t1755dp_ard_i2c_interface: &flexcomm8_lpi2c8 {};
421421
status = "okay";
422422
};
423423

424-
&pca9422 {
425-
status = "okay";
426-
};

boards/shields/zc143ac72mipi/zc143ac72mipi.overlay

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,45 +7,38 @@
77
/ {
88
chosen {
99
zephyr,display = &co5300_zc143ac72mipi;
10-
/* zephyr,touch = &ft3267_g1120b0mipi;*/
10+
zephyr,touch = &tma525b_zc143ac72mipi;
1111
};
1212

13-
/*
1413
en_mipi_display_g1120b0mipi: enable-mipi-display {
1514
compatible = "regulator-fixed";
1615
regulator-name = "en_mipi_display";
1716
enable-gpios = <&nxp_mipi_connector 32 GPIO_ACTIVE_HIGH>;
1817
regulator-boot-on;
1918
};
20-
*/
2119

22-
/*
2320
lvgl_pointer {
2421
compatible = "zephyr,lvgl-pointer-input";
25-
input = <&ft3267_g1120b0mipi>;
26-
display = <&rm67162_g1120b0mipi>;
22+
input = <&ft3267_zc143ac72mipi>;
23+
display = <&co5300_zc143ac72mipi>;
2724
invert-y;
2825
};
29-
*/
3026
};
3127

32-
/*
3328
&nxp_mipi_i2c {
3429
status = "okay";
3530

36-
ft3267_g1120b0mipi: ft3267@38 {
31+
tma525b_zc143ac72mipi: tma525b@24 {
3732
/*
3833
* Note- the actual controller present on this IC is a FT3267,
3934
* but the FT35336 driver in Zephyr supports this IC.
4035
*/
41-
/*
42-
compatible = "focaltech,ft5336";
43-
reg = <0x38>;
36+
compatible = "focaltech,tma525b";
37+
reg = <0x24>;
4438
int-gpios = <&nxp_mipi_connector 29 GPIO_ACTIVE_LOW>;
4539
reset-gpios = <&nxp_mipi_connector 28 GPIO_ACTIVE_LOW>;
4640
};
4741
};
48-
*/
4942

5043
&zephyr_mipi_dsi {
5144
status = "okay";

drivers/input/input_tma525b.c

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
/*
2+
* Copyright 2025 NXP
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#define DT_DRV_COMPAT ..._tma525b
8+
9+
#include <zephyr/drivers/gpio.h>
10+
#include <zephyr/drivers/i2c.h>
11+
#include <zephyr/input/input.h>
12+
#include <zephyr/input/input_touch.h>
13+
#include <zephyr/pm/device.h>
14+
#include <zephyr/pm/device_runtime.h>
15+
#include <zephyr/sys/util.h>
16+
17+
#include <zephyr/logging/log.h>
18+
LOG_MODULE_REGISTER(tma525b, CONFIG_INPUT_LOG_LEVEL);
19+
20+
#if 0
21+
/* TMA525B used registers */
22+
#define REG_TD_STATUS 0x02U
23+
#define REG_P1_XH 0x03U
24+
#define REG_G_PMODE 0xA5U
25+
26+
/* REG_TD_STATUS: Touch points. */
27+
#define TOUCH_POINTS_POS 0U
28+
#define TOUCH_POINTS_MSK 0x0FU
29+
30+
/* REG_Pn_XH: Events. */
31+
#define EVENT_POS 6U
32+
#define EVENT_MSK 0x03U
33+
34+
#define EVENT_PRESS_DOWN 0x00U
35+
#define EVENT_LIFT_UP 0x01U
36+
#define EVENT_CONTACT 0x02U
37+
#define EVENT_NONE 0x03U
38+
39+
/* REG_Pn_YH: Touch ID */
40+
#define TOUCH_ID_POS 4U
41+
#define TOUCH_ID_MSK 0x0FU
42+
43+
#define TOUCH_ID_INVALID 0x0FU
44+
45+
/* REG_Pn_XH and REG_Pn_YH: Position */
46+
#define POSITION_H_MSK 0x0FU
47+
48+
/* REG_G_PMODE: Power Consume Mode */
49+
#define PMOD_HIBERNATE 0x03U
50+
#endif
51+
52+
/** TMA525B configuration (DT). */
53+
struct tma525b_config {
54+
struct input_touchscreen_common_config common;
55+
/** I2C bus. */
56+
struct i2c_dt_spec bus;
57+
struct gpio_dt_spec reset_gpio;
58+
#ifdef CONFIG_INPUT_TMA525B_INTERRUPT
59+
/** Interrupt GPIO information. */
60+
struct gpio_dt_spec int_gpio;
61+
#endif
62+
};
63+
64+
/** TMA525B data. */
65+
struct tma525b_data {
66+
/** Work queue (for deferred read). */
67+
struct k_work work;
68+
#ifdef CONFIG_INPUT_TMA525B_INTERRUPT
69+
/** Interrupt GPIO callback. */
70+
struct gpio_callback int_gpio_cb;
71+
#else
72+
/** Timer (polling mode). */
73+
struct k_timer timer;
74+
#endif
75+
/** Last pressed state. */
76+
bool pressed_old;
77+
};
78+
79+
INPUT_TOUCH_STRUCT_CHECK(struct tma525b_config);
80+
81+
static int tma525b_process(const struct device *dev)
82+
{
83+
#if 0
84+
const struct tma525b_config *config = dev->config;
85+
struct tma525b_data *data = dev->data;
86+
87+
int r;
88+
uint8_t points;
89+
uint8_t coords[4U];
90+
uint16_t row, col;
91+
bool pressed;
92+
93+
/* obtain number of touch points */
94+
r = i2c_reg_read_byte_dt(&config->bus, REG_TD_STATUS, &points);
95+
if (r < 0) {
96+
return r;
97+
}
98+
99+
points = FIELD_GET(TOUCH_POINTS_MSK, points);
100+
if (points != 0) {
101+
/* Any number of touches still counts as one touch. All touch
102+
* points except the first are ignored. Obtain first point
103+
* X, Y coordinates from:
104+
* REG_P1_XH, REG_P1_XL, REG_P1_YH, REG_P1_YL.
105+
* We ignore the Event Flag because Zephyr only cares about
106+
* pressed / not pressed and not press down / lift up
107+
*/
108+
r = i2c_burst_read_dt(&config->bus, REG_P1_XH, coords, sizeof(coords));
109+
if (r < 0) {
110+
return r;
111+
}
112+
113+
row = ((coords[0] & POSITION_H_MSK) << 8U) | coords[1];
114+
col = ((coords[2] & POSITION_H_MSK) << 8U) | coords[3];
115+
116+
uint8_t touch_id = FIELD_GET(TOUCH_ID_MSK, coords[2]);
117+
118+
if (touch_id != TOUCH_ID_INVALID) {
119+
pressed = true;
120+
LOG_DBG("points: %d, touch_id: %d, row: %d, col: %d",
121+
points, touch_id, row, col);
122+
} else {
123+
pressed = false;
124+
LOG_WRN("bad TOUCH_ID: row: %d, col: %d", row, col);
125+
}
126+
} else {
127+
/* no touch = no press */
128+
pressed = false;
129+
}
130+
131+
if (pressed) {
132+
input_touchscreen_report_pos(dev, col, row, K_FOREVER);
133+
input_report_key(dev, INPUT_BTN_TOUCH, 1, true, K_FOREVER);
134+
} else if (data->pressed_old && !pressed) {
135+
input_report_key(dev, INPUT_BTN_TOUCH, 0, true, K_FOREVER);
136+
}
137+
data->pressed_old = pressed;
138+
#endif
139+
140+
return 0;
141+
}
142+
143+
static void tma525b_work_handler(struct k_work *work)
144+
{
145+
struct tma525b_data *data = CONTAINER_OF(work, struct tma525b_data, work);
146+
147+
tma525b_process(data->dev);
148+
}
149+
150+
#ifdef CONFIG_INPUT_TMA525B_INTERRUPT
151+
static void tma525b_isr_handler(const struct device *dev,
152+
struct gpio_callback *cb, uint32_t pins)
153+
{
154+
struct tma525b_data *data = CONTAINER_OF(cb, struct tma525b_data, int_gpio_cb);
155+
156+
k_work_submit(&data->work);
157+
}
158+
#else
159+
static void tma525b_timer_handler(struct k_timer *timer)
160+
{
161+
struct tma525b_data *data = CONTAINER_OF(timer, struct tma525b_data, timer);
162+
163+
k_work_submit(&data->work);
164+
}
165+
#endif
166+
167+
static int tma525b_init(const struct device *dev)
168+
{
169+
const struct tma525b_config *config = dev->config;
170+
struct tma525b_data *data = dev->data;
171+
int err_code;
172+
173+
174+
if (!device_is_ready(config->bus.bus)) {
175+
LOG_ERR("I2C controller device not ready");
176+
return -ENODEV;
177+
}
178+
179+
k_work_init(&data->work, tma525b_work_handler);
180+
181+
/* GPIO Power on Sequence */
182+
if (config->power_gpio.port != NULL) {
183+
err_code = gpio_pin_set_dt(&config->power_gpio, 1);
184+
if (err_code < 0) {
185+
LOG_ERR("Could not enable power GPIO");
186+
return err_code;
187+
}
188+
if (config->reset_gpio.port != NULL) {
189+
err_code = gpio_pin_set_dt(&config->reset_gpio, 0);
190+
if (err_code < 0) {
191+
LOG_ERR("Could not set reset GPIO low");
192+
return r;
193+
}
194+
/* Datasheet states to hold for 5ms after activation of reset pin */
195+
k_sleep(K_MSEC(5));
196+
197+
err_code = gpio_pin_set_dt(&config->reset_gpio, 1);
198+
if (err_code < 0) {
199+
LOG_ERR("Could not set reset GPIO high");
200+
return err_code;
201+
}
202+
}
203+
} else {
204+
LOG_ERR("Could not enable power GPIO");
205+
return err_code;
206+
}
207+
208+
#ifdef CONFIG_INPUT_TMA525B_INTERRUPT
209+
if (!gpio_is_ready_dt(&config->int_gpio)) {
210+
LOG_ERR("Interrupt GPIO controller device not ready");
211+
return -ENODEV;
212+
}
213+
214+
err_code = gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT);
215+
if (err_code < 0) {
216+
LOG_ERR("Could not configure interrupt GPIO pin");
217+
return err_code;
218+
}
219+
220+
err_code = gpio_pin_interrupt_configure_dt(&config->int_gpio,
221+
GPIO_INT_EDGE_TO_ACTIVE);
222+
if (err_code < 0) {
223+
LOG_ERR("Could not configure interrupt GPIO interrupt.");
224+
return err_code;
225+
}
226+
227+
gpio_init_callback(&data->int_gpio_cb, tma525b_isr_handler,
228+
BIT(config->int_gpio.pin));
229+
err_code = gpio_add_callback(config->int_gpio.port, &data->int_gpio_cb);
230+
if (err_code < 0) {
231+
LOG_ERR("Could not set gpio callback");
232+
return err_code;
233+
}
234+
#else
235+
k_timer_init(&data->timer, tma525b_timer_handler, NULL);
236+
k_timer_start(&data->timer, K_MSEC(CONFIG_INPUT_TMA525B_PERIOD),
237+
K_MSEC(CONFIG_INPUT_TMA525B_PERIOD));
238+
#endif
239+
return 0;
240+
}
241+
242+
#define TMA525B_INIT(index) \
243+
static const struct tma525b_config tma525b_config_##index = { \
244+
.common = INPUT_TOUCH_DT_INST_COMMON_CONFIG_INIT(index), \
245+
.bus = I2C_DT_SPEC_INST_GET(index), \
246+
.reset_gpio = GPIO_DT_SPEC_INST_GET_OR(index, reset_gpios, {0}), \
247+
IF_ENABLED(CONFIG_INPUT_TMA525B_INTERRUPT, \
248+
(.int_gpio = GPIO_DT_SPEC_INST_GET(index, int_gpios),)) \
249+
}; \
250+
static struct tma525b_data tma525b_data_##index; \
251+
DEVICE_DT_INST_DEFINE(index, tma525b_init, 0, \
252+
&tma525b_data_##index, &tma525b_config_##index, \
253+
POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, NULL);
254+
255+
DT_INST_FOREACH_STATUS_OKAY(TMA525B_INIT)

0 commit comments

Comments
 (0)