Skip to content

Commit 71f8e38

Browse files
committed
Input: ili210x - switch to using threaded IRQ
Let's switch the driver to using threaded IRQ so that we do not need to manage the interrupt and work separately, and we do not acknowledge interrupt until we finished handling it completely. Tested-by: Adam Ford <[email protected]> #imx6q-logicpd Tested-by: Sven Van Asbroeck <[email protected]> # ILI2118A variant Tested-by: Marek Vasut <[email protected]> # ILI2117 Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent eb91ecc commit 71f8e38

File tree

1 file changed

+56
-61
lines changed

1 file changed

+56
-61
lines changed

drivers/input/touchscreen/ili210x.c

Lines changed: 56 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
// SPDX-License-Identifier: GPL-2.0-only
2-
#include <linux/module.h>
2+
#include <linux/delay.h>
3+
#include <linux/gpio/consumer.h>
34
#include <linux/i2c.h>
4-
#include <linux/interrupt.h>
5-
#include <linux/slab.h>
65
#include <linux/input.h>
76
#include <linux/input/mt.h>
87
#include <linux/input/touchscreen.h>
9-
#include <linux/delay.h>
10-
#include <linux/workqueue.h>
11-
#include <linux/gpio/consumer.h>
8+
#include <linux/interrupt.h>
9+
#include <linux/module.h>
1210
#include <linux/of_device.h>
11+
#include <linux/slab.h>
1312
#include <asm/unaligned.h>
1413

1514
#define ILI210X_TOUCHES 2
1615
#define ILI211X_TOUCHES 10
1716
#define ILI251X_TOUCHES 10
18-
#define DEFAULT_POLL_PERIOD 20
17+
18+
#define ILI2XXX_POLL_PERIOD 20
1919

2020
/* Touchscreen commands */
2121
#define REG_TOUCHDATA 0x10
@@ -38,12 +38,11 @@ enum ili2xxx_model {
3838
struct ili210x {
3939
struct i2c_client *client;
4040
struct input_dev *input;
41-
unsigned int poll_period;
42-
struct delayed_work dwork;
4341
struct gpio_desc *reset_gpio;
4442
struct touchscreen_properties prop;
4543
enum ili2xxx_model model;
4644
unsigned int max_touches;
45+
bool stop;
4746
};
4847

4948
static int ili210x_read_reg(struct i2c_client *client, u8 reg, void *buf,
@@ -196,57 +195,54 @@ static bool ili210x_report_events(struct ili210x *priv, u8 *touchdata)
196195
return contact;
197196
}
198197

199-
static void ili210x_work(struct work_struct *work)
198+
static irqreturn_t ili210x_irq(int irq, void *irq_data)
200199
{
201-
struct ili210x *priv = container_of(work, struct ili210x,
202-
dwork.work);
200+
struct ili210x *priv = irq_data;
203201
struct i2c_client *client = priv->client;
204202
u8 touchdata[64] = { 0 };
205203
s16 sum = 0;
206204
bool touch;
207-
int i, error = -EINVAL;
208-
209-
if (priv->model == MODEL_ILI210X) {
210-
error = ili210x_read_reg(client, REG_TOUCHDATA,
211-
touchdata, sizeof(touchdata));
212-
} else if (priv->model == MODEL_ILI211X) {
213-
error = ili210x_read(client, touchdata, 43);
214-
if (!error) {
215-
/* This chip uses custom checksum at the end of data */
216-
for (i = 0; i <= 41; i++)
217-
sum = (sum + touchdata[i]) & 0xff;
218-
if ((-sum & 0xff) != touchdata[42]) {
219-
dev_err(&client->dev,
220-
"CRC error (crc=0x%02x expected=0x%02x)\n",
221-
sum, touchdata[42]);
222-
return;
205+
int i;
206+
int error;
207+
208+
do {
209+
if (priv->model == MODEL_ILI210X) {
210+
error = ili210x_read_reg(client, REG_TOUCHDATA,
211+
touchdata, sizeof(touchdata));
212+
} else if (priv->model == MODEL_ILI211X) {
213+
error = ili210x_read(client, touchdata, 43);
214+
if (!error) {
215+
/*
216+
* This chip uses custom checksum at the end
217+
* of data.
218+
*/
219+
for (i = 0; i <= 41; i++)
220+
sum = (sum + touchdata[i]) & 0xff;
221+
if ((-sum & 0xff) != touchdata[42]) {
222+
dev_err(&client->dev,
223+
"CRC error (crc=0x%02x expected=0x%02x)\n",
224+
sum, touchdata[42]);
225+
break;
226+
}
223227
}
228+
} else if (priv->model == MODEL_ILI251X) {
229+
error = ili210x_read_reg(client, REG_TOUCHDATA,
230+
touchdata, 31);
231+
if (!error && touchdata[0] == 2)
232+
error = ili210x_read(client,
233+
&touchdata[31], 20);
224234
}
225-
} else if (priv->model == MODEL_ILI251X) {
226-
error = ili210x_read_reg(client, REG_TOUCHDATA,
227-
touchdata, 31);
228-
if (!error && touchdata[0] == 2)
229-
error = ili210x_read(client, &touchdata[31], 20);
230-
}
231-
232-
if (error) {
233-
dev_err(&client->dev,
234-
"Unable to get touchdata, err = %d\n", error);
235-
return;
236-
}
237235

238-
touch = ili210x_report_events(priv, touchdata);
239-
240-
if (touch)
241-
schedule_delayed_work(&priv->dwork,
242-
msecs_to_jiffies(priv->poll_period));
243-
}
244-
245-
static irqreturn_t ili210x_irq(int irq, void *irq_data)
246-
{
247-
struct ili210x *priv = irq_data;
236+
if (error) {
237+
dev_err(&client->dev,
238+
"Unable to get touchdata, err = %d\n", error);
239+
break;
240+
}
248241

249-
schedule_delayed_work(&priv->dwork, 0);
242+
touch = ili210x_report_events(priv, touchdata);
243+
if (touch)
244+
msleep(ILI2XXX_POLL_PERIOD);
245+
} while (!priv->stop && touch);
250246

251247
return IRQ_HANDLED;
252248
}
@@ -293,11 +289,12 @@ static void ili210x_power_down(void *data)
293289
gpiod_set_value_cansleep(reset_gpio, 1);
294290
}
295291

296-
static void ili210x_cancel_work(void *data)
292+
static void ili210x_stop(void *data)
297293
{
298294
struct ili210x *priv = data;
299295

300-
cancel_delayed_work_sync(&priv->dwork);
296+
/* Tell ISR to quit even if there is a contact. */
297+
priv->stop = true;
301298
}
302299

303300
static int ili210x_i2c_probe(struct i2c_client *client,
@@ -345,8 +342,6 @@ static int ili210x_i2c_probe(struct i2c_client *client,
345342

346343
priv->client = client;
347344
priv->input = input;
348-
priv->poll_period = DEFAULT_POLL_PERIOD;
349-
INIT_DELAYED_WORK(&priv->dwork, ili210x_work);
350345
priv->reset_gpio = reset_gpio;
351346
priv->model = model;
352347
if (model == MODEL_ILI210X)
@@ -378,18 +373,18 @@ static int ili210x_i2c_probe(struct i2c_client *client,
378373
touchscreen_parse_properties(input, true, &priv->prop);
379374
input_mt_init_slots(input, priv->max_touches, INPUT_MT_DIRECT);
380375

381-
error = devm_add_action(dev, ili210x_cancel_work, priv);
382-
if (error)
383-
return error;
384-
385-
error = devm_request_irq(dev, client->irq, ili210x_irq, 0,
386-
client->name, priv);
376+
error = devm_request_threaded_irq(dev, client->irq, NULL, ili210x_irq,
377+
IRQF_ONESHOT, client->name, priv);
387378
if (error) {
388379
dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n",
389380
error);
390381
return error;
391382
}
392383

384+
error = devm_add_action_or_reset(dev, ili210x_stop, priv);
385+
if (error)
386+
return error;
387+
393388
error = devm_device_add_group(dev, &ili210x_attr_group);
394389
if (error) {
395390
dev_err(dev, "Unable to create sysfs attributes, err: %d\n",

0 commit comments

Comments
 (0)