b3bf708ade9b56bb5aef40a39448846d899b40ac
[openwrt/openwrt.git] /
1 From 5171a96d17e35b7af7efbf6e9c9667f93fbd828f Mon Sep 17 00:00:00 2001
2 From: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
3 Date: Wed, 11 Oct 2023 15:14:59 +0100
4 Subject: [PATCH 0669/1085] input: touchscreen: edt-ft5x06: Suppress bogus data
5 on startup
6
7 When polled without the use of IRQ, FT5x06 registers may return
8 undefined initial data, causing unwanted touches or event spamming.
9 A simple way to filter this out is to suppress touches until the
10 TD_STATUS register changes for the first time.
11
12 Increase the delay before first polling to 300ms, to avoid
13 transient I2C read flakiness that seems to occur after reset.
14
15 Signed-off-by: Nick Hollinghurst <nick.hollinghurst@raspberrypi.com>
16 ---
17 drivers/input/touchscreen/edt-ft5x06.c | 25 ++++++++++++++++++++++---
18 1 file changed, 22 insertions(+), 3 deletions(-)
19
20 --- a/drivers/input/touchscreen/edt-ft5x06.c
21 +++ b/drivers/input/touchscreen/edt-ft5x06.c
22 @@ -80,6 +80,8 @@
23 #define M06_REG_CMD(factory) ((factory) ? 0xf3 : 0xfc)
24 #define M06_REG_ADDR(factory, addr) ((factory) ? (addr) & 0x7f : (addr) & 0x3f)
25
26 +#define RESET_DELAY_MS 300 /* reset deassert to I2C */
27 +#define FIRST_POLL_DELAY_MS 300 /* in addition to the above */
28 #define POLL_INTERVAL_MS 17 /* 17ms = 60fps */
29
30 enum edt_pmode {
31 @@ -145,6 +147,7 @@ struct edt_ft5x06_ts_data {
32
33 char name[EDT_NAME_LEN];
34 char fw_version[EDT_NAME_LEN];
35 + int init_td_status;
36
37 struct edt_reg_addr reg_addr;
38 enum edt_ver version;
39 @@ -324,6 +327,21 @@ static irqreturn_t edt_ft5x06_ts_isr(int
40 * points.
41 */
42 num_points = min(rdbuf[2] & 0xf, tsdata->max_support_points);
43 +
44 + /* When polling FT5x06 without IRQ: initial register contents
45 + * could be stale or undefined; discard all readings until
46 + * TD_STATUS changes for the first time (or num_points is 0).
47 + */
48 + if (tsdata->init_td_status) {
49 + if (tsdata->init_td_status < 0)
50 + tsdata->init_td_status = rdbuf[2];
51 +
52 + if (num_points && rdbuf[2] == tsdata->init_td_status)
53 + goto out;
54 +
55 + tsdata->init_td_status = 0;
56 + }
57 +
58 if (!error && num_points)
59 error = regmap_bulk_read(tsdata->regmap,
60 tsdata->tdata_offset,
61 @@ -1300,7 +1318,7 @@ static int edt_ft5x06_ts_probe(struct i2
62 if (tsdata->reset_gpio) {
63 usleep_range(5000, 6000);
64 gpiod_set_value_cansleep(tsdata->reset_gpio, 0);
65 - msleep(300);
66 + msleep(RESET_DELAY_MS);
67 }
68
69 input = devm_input_allocate_device(&client->dev);
70 @@ -1389,11 +1407,12 @@ static int edt_ft5x06_ts_probe(struct i2
71 return error;
72 }
73 } else {
74 + tsdata->init_td_status = -1; /* filter bogus initial data */
75 INIT_WORK(&tsdata->work_i2c_poll,
76 edt_ft5x06_ts_work_i2c_poll);
77 timer_setup(&tsdata->timer, edt_ft5x06_ts_irq_poll_timer, 0);
78 - tsdata->timer.expires = jiffies +
79 - msecs_to_jiffies(POLL_INTERVAL_MS);
80 + tsdata->timer.expires =
81 + jiffies + msecs_to_jiffies(FIRST_POLL_DELAY_MS);
82 add_timer(&tsdata->timer);
83 }
84