hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/input/touchscreen/eeti_ts.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Touch Screen driver for EETI's I2C connected touch screen panels
34 * Copyright (c) 2009,2018 Daniel Mack <daniel@zonque.org>
....@@ -8,20 +9,6 @@
89 * Based on migor_ts.c
910 * Copyright (c) 2008 Magnus Damm
1011 * Copyright (c) 2007 Ujjwal Pande <ujjwal@kenati.com>
11
- *
12
- * This file is free software; you can redistribute it and/or
13
- * modify it under the terms of the GNU General Public
14
- * License as published by the Free Software Foundation; either
15
- * version 2 of the License, or (at your option) any later version.
16
- *
17
- * This file is distributed in the hope that it will be useful,
18
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20
- * General Public License for more details.
21
- *
22
- * You should have received a copy of the GNU General Public
23
- * License along with this library; if not, write to the Free Software
24
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2512 */
2613
2714 #include <linux/module.h>
....@@ -41,6 +28,7 @@
4128 struct input_dev *input;
4229 struct gpio_desc *attn_gpio;
4330 struct touchscreen_properties props;
31
+ struct mutex mutex;
4432 bool running;
4533 };
4634
....@@ -75,42 +63,80 @@
7563 input_sync(eeti->input);
7664 }
7765
66
+static int eeti_ts_read(struct eeti_ts *eeti)
67
+{
68
+ int len, error;
69
+ char buf[6];
70
+
71
+ len = i2c_master_recv(eeti->client, buf, sizeof(buf));
72
+ if (len != sizeof(buf)) {
73
+ error = len < 0 ? len : -EIO;
74
+ dev_err(&eeti->client->dev,
75
+ "failed to read touchscreen data: %d\n",
76
+ error);
77
+ return error;
78
+ }
79
+
80
+ /* Motion packet */
81
+ if (buf[0] & 0x80)
82
+ eeti_ts_report_event(eeti, buf);
83
+
84
+ return 0;
85
+}
86
+
7887 static irqreturn_t eeti_ts_isr(int irq, void *dev_id)
7988 {
8089 struct eeti_ts *eeti = dev_id;
81
- int len;
8290 int error;
83
- char buf[6];
91
+
92
+ mutex_lock(&eeti->mutex);
8493
8594 do {
86
- len = i2c_master_recv(eeti->client, buf, sizeof(buf));
87
- if (len != sizeof(buf)) {
88
- error = len < 0 ? len : -EIO;
89
- dev_err(&eeti->client->dev,
90
- "failed to read touchscreen data: %d\n",
91
- error);
95
+ /*
96
+ * If we have attention GPIO, trust it. Otherwise we'll read
97
+ * once and exit. We assume that in this case we are using
98
+ * level triggered interrupt and it will get raised again
99
+ * if/when there is more data.
100
+ */
101
+ if (eeti->attn_gpio &&
102
+ !gpiod_get_value_cansleep(eeti->attn_gpio)) {
92103 break;
93104 }
94105
95
- if (buf[0] & 0x80) {
96
- /* Motion packet */
97
- eeti_ts_report_event(eeti, buf);
98
- }
99
- } while (eeti->running &&
100
- eeti->attn_gpio && gpiod_get_value_cansleep(eeti->attn_gpio));
106
+ error = eeti_ts_read(eeti);
107
+ if (error)
108
+ break;
101109
110
+ } while (eeti->running && eeti->attn_gpio);
111
+
112
+ mutex_unlock(&eeti->mutex);
102113 return IRQ_HANDLED;
103114 }
104115
105116 static void eeti_ts_start(struct eeti_ts *eeti)
106117 {
118
+ mutex_lock(&eeti->mutex);
119
+
107120 eeti->running = true;
108
- wmb();
109121 enable_irq(eeti->client->irq);
122
+
123
+ /*
124
+ * Kick the controller in case we are using edge interrupt and
125
+ * we missed our edge while interrupt was disabled. We expect
126
+ * the attention GPIO to be wired in this case.
127
+ */
128
+ if (eeti->attn_gpio && gpiod_get_value_cansleep(eeti->attn_gpio))
129
+ eeti_ts_read(eeti);
130
+
131
+ mutex_unlock(&eeti->mutex);
110132 }
111133
112134 static void eeti_ts_stop(struct eeti_ts *eeti)
113135 {
136
+ /*
137
+ * Not locking here, just setting a flag and expect that the
138
+ * interrupt thread will notice the flag eventually.
139
+ */
114140 eeti->running = false;
115141 wmb();
116142 disable_irq(eeti->client->irq);
....@@ -153,6 +179,8 @@
153179 return -ENOMEM;
154180 }
155181
182
+ mutex_init(&eeti->mutex);
183
+
156184 input = devm_input_allocate_device(dev);
157185 if (!input) {
158186 dev_err(dev, "Failed to allocate input device.\n");