008bdf36da70ab9bc1449a72a7c48d69088b6436
[openwrt/openwrt.git] /
1 From 13a9614267e7d8d4075144a7bf4dbebfcc565367 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Mon, 30 Jan 2023 14:46:16 +0000
4 Subject: [PATCH] input: goodix: Add option to poll instead of relying
5 on IRQ line
6
7 The interrupt line from the touch controller is not necessarily
8 connected to the SoC, so add the option to poll for touch info.
9
10 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
11 ---
12 drivers/input/touchscreen/goodix.c | 70 +++++++++++++++++++++++++++---
13 drivers/input/touchscreen/goodix.h | 2 +
14 2 files changed, 66 insertions(+), 6 deletions(-)
15
16 --- a/drivers/input/touchscreen/goodix.c
17 +++ b/drivers/input/touchscreen/goodix.c
18 @@ -48,6 +48,8 @@
19 #define MAX_CONTACTS_LOC 5
20 #define TRIGGER_LOC 6
21
22 +#define POLL_INTERVAL_MS 17 /* 17ms = 60fps */
23 +
24 /* Our special handling for GPIO accesses through ACPI is x86 specific */
25 #if defined CONFIG_X86 && defined CONFIG_ACPI
26 #define ACPI_GPIO_SUPPORT
27 @@ -513,16 +515,67 @@ static irqreturn_t goodix_ts_irq_handler
28 return IRQ_HANDLED;
29 }
30
31 +static void goodix_ts_irq_poll_timer(struct timer_list *t)
32 +{
33 + struct goodix_ts_data *ts = from_timer(ts, t, timer);
34 +
35 + schedule_work(&ts->work_i2c_poll);
36 + mod_timer(&ts->timer, jiffies + msecs_to_jiffies(POLL_INTERVAL_MS));
37 +}
38 +
39 +static void goodix_ts_work_i2c_poll(struct work_struct *work)
40 +{
41 + struct goodix_ts_data *ts = container_of(work,
42 + struct goodix_ts_data, work_i2c_poll);
43 +
44 + goodix_process_events(ts);
45 + goodix_i2c_write_u8(ts->client, GOODIX_READ_COOR_ADDR, 0);
46 +}
47 +
48 +static void goodix_enable_irq(struct goodix_ts_data *ts)
49 +{
50 + if (ts->client->irq) {
51 + enable_irq(ts->client->irq);
52 + } else {
53 + ts->timer.expires = jiffies + msecs_to_jiffies(POLL_INTERVAL_MS);
54 + add_timer(&ts->timer);
55 + }
56 +}
57 +
58 +static void goodix_disable_irq(struct goodix_ts_data *ts)
59 +{
60 + if (ts->client->irq) {
61 + disable_irq(ts->client->irq);
62 + } else {
63 + del_timer(&ts->timer);
64 + cancel_work_sync(&ts->work_i2c_poll);
65 + }
66 +}
67 +
68 static void goodix_free_irq(struct goodix_ts_data *ts)
69 {
70 - devm_free_irq(&ts->client->dev, ts->client->irq, ts);
71 + if (ts->client->irq) {
72 + devm_free_irq(&ts->client->dev, ts->client->irq, ts);
73 + } else {
74 + del_timer(&ts->timer);
75 + cancel_work_sync(&ts->work_i2c_poll);
76 + }
77 }
78
79 static int goodix_request_irq(struct goodix_ts_data *ts)
80 {
81 - return devm_request_threaded_irq(&ts->client->dev, ts->client->irq,
82 - NULL, goodix_ts_irq_handler,
83 - ts->irq_flags, ts->client->name, ts);
84 + if (ts->client->irq) {
85 + return devm_request_threaded_irq(&ts->client->dev, ts->client->irq,
86 + NULL, goodix_ts_irq_handler,
87 + ts->irq_flags, ts->client->name, ts);
88 + } else {
89 + INIT_WORK(&ts->work_i2c_poll,
90 + goodix_ts_work_i2c_poll);
91 + timer_setup(&ts->timer, goodix_ts_irq_poll_timer, 0);
92 + if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_NONE)
93 + goodix_enable_irq(ts);
94 + return 0;
95 + }
96 }
97
98 static int goodix_check_cfg_8(struct goodix_ts_data *ts, const u8 *cfg, int len)
99 @@ -1406,6 +1459,11 @@ static void goodix_ts_remove(struct i2c_
100 {
101 struct goodix_ts_data *ts = i2c_get_clientdata(client);
102
103 + if (!client->irq) {
104 + del_timer(&ts->timer);
105 + cancel_work_sync(&ts->work_i2c_poll);
106 + }
107 +
108 if (ts->load_cfg_from_disk)
109 wait_for_completion(&ts->firmware_loading_complete);
110 }
111 @@ -1421,7 +1479,7 @@ static int __maybe_unused goodix_suspend
112
113 /* We need gpio pins to suspend/resume */
114 if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_NONE) {
115 - disable_irq(client->irq);
116 + goodix_disable_irq(ts);
117 return 0;
118 }
119
120 @@ -1465,7 +1523,7 @@ static int __maybe_unused goodix_resume(
121 int error;
122
123 if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_NONE) {
124 - enable_irq(client->irq);
125 + goodix_enable_irq(ts);
126 return 0;
127 }
128
129 --- a/drivers/input/touchscreen/goodix.h
130 +++ b/drivers/input/touchscreen/goodix.h
131 @@ -104,6 +104,8 @@ struct goodix_ts_data {
132 u8 main_clk[GOODIX_MAIN_CLK_LEN];
133 int bak_ref_len;
134 u8 *bak_ref;
135 + struct timer_list timer;
136 + struct work_struct work_i2c_poll;
137 };
138
139 int goodix_i2c_read(struct i2c_client *client, u16 reg, u8 *buf, int len);