diff mbox series

[3/8] input: touchscreen: ili210x: Convert to threaded IRQ

Message ID 20181213151442.27854-4-marex@denx.de (mailing list archive)
State Superseded
Headers show
Series input: touchscreen: ili210x: Add ILI2511 support | expand

Commit Message

Marek Vasut Dec. 13, 2018, 3:14 p.m. UTC
Get rid of the workqueue, just spawn a threaded IRQ and handle
all the touchscreen readouts in the handler thread.

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Henrik Rydberg <rydberg@bitmath.org>
Cc: Olivier Sobrie <olivier@sobrie.be>
To: linux-input@vger.kernel.org
---
 drivers/input/touchscreen/ili210x.c | 51 +++++------------------------
 1 file changed, 8 insertions(+), 43 deletions(-)

Comments

Dmitry Torokhov Dec. 13, 2018, 7:08 p.m. UTC | #1
On Thu, Dec 13, 2018 at 7:15 AM Marek Vasut <marex@denx.de> wrote:
>
> Get rid of the workqueue, just spawn a threaded IRQ and handle
> all the touchscreen readouts in the handler thread.

So we reliably get interrupt on release? Also this probably means that
clients have to use level interrupts....

Thanks.
Marek Vasut Dec. 13, 2018, 8:39 p.m. UTC | #2
On 12/13/2018 08:08 PM, Dmitry Torokhov wrote:
> On Thu, Dec 13, 2018 at 7:15 AM Marek Vasut <marex@denx.de> wrote:
>>
>> Get rid of the workqueue, just spawn a threaded IRQ and handle
>> all the touchscreen readouts in the handler thread.
> 
> So we reliably get interrupt on release?

What am I missing here , can you elaborate a bit ?

> Also this probably means that clients have to use level interrupts....

The interrupt line of the ILI2511 is indeed level triggered (pen/finger
down means IRQ line goes down, pen/finger up means it goes up).
Dmitry Torokhov Dec. 14, 2018, 1:17 a.m. UTC | #3
On Thu, Dec 13, 2018 at 4:44 PM Marek Vasut <marex@denx.de> wrote:
>
> On 12/13/2018 08:08 PM, Dmitry Torokhov wrote:
> > On Thu, Dec 13, 2018 at 7:15 AM Marek Vasut <marex@denx.de> wrote:
> >>
> >> Get rid of the workqueue, just spawn a threaded IRQ and handle
> >> all the touchscreen readouts in the handler thread.
> >
> > So we reliably get interrupt on release?
>
> What am I missing here , can you elaborate a bit ?

If I'm reading the old code correctly it would be OK even if interrupt
was only delivered on initial touch, and then we'd be simply polling
the device...

>
> > Also this probably means that clients have to use level interrupts....
>
> The interrupt line of the ILI2511 is indeed level triggered (pen/finger
> down means IRQ line goes down, pen/finger up means it goes up).

So what happens when pen goes up just as you are leaving the ISR? The
controller would clear interrupt, but you already reported touch and
would not report release. The controller needs to make sure that it
keeps the line low even after you removed pen/finger, until you read
controller state once again so you can reliably report touch release.

Does this make sense?

Thanks.
Marek Vasut Dec. 14, 2018, 2:27 a.m. UTC | #4
On 12/14/2018 02:17 AM, Dmitry Torokhov wrote:
> On Thu, Dec 13, 2018 at 4:44 PM Marek Vasut <marex@denx.de> wrote:
>>
>> On 12/13/2018 08:08 PM, Dmitry Torokhov wrote:
>>> On Thu, Dec 13, 2018 at 7:15 AM Marek Vasut <marex@denx.de> wrote:
>>>>
>>>> Get rid of the workqueue, just spawn a threaded IRQ and handle
>>>> all the touchscreen readouts in the handler thread.
>>>
>>> So we reliably get interrupt on release?
>>
>> What am I missing here , can you elaborate a bit ?
> 
> If I'm reading the old code correctly it would be OK even if interrupt
> was only delivered on initial touch, and then we'd be simply polling
> the device...

Sure, although that's not how the controller behaves, so do we care
about retaining that behavior ?

>>
>>> Also this probably means that clients have to use level interrupts....
>>
>> The interrupt line of the ILI2511 is indeed level triggered (pen/finger
>> down means IRQ line goes down, pen/finger up means it goes up).
> 
> So what happens when pen goes up just as you are leaving the ISR? The
> controller would clear interrupt, but you already reported touch and
> would not report release. The controller needs to make sure that it
> keeps the line low even after you removed pen/finger, until you read
> controller state once again so you can reliably report touch release.
> 
> Does this make sense?

Yeah, that makes sense, so we probably want to retain the workqueue
afterall ? Or is there a better option ?
diff mbox series

Patch

diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c
index 7ba93de712432..1102ee560bf4d 100644
--- a/drivers/input/touchscreen/ili210x.c
+++ b/drivers/input/touchscreen/ili210x.c
@@ -5,7 +5,6 @@ 
 #include <linux/input.h>
 #include <linux/input/mt.h>
 #include <linux/delay.h>
-#include <linux/workqueue.h>
 
 #define MAX_TOUCHES		2
 #define DEFAULT_POLL_PERIOD	20
@@ -43,9 +42,6 @@  struct firmware_version {
 struct ili210x {
 	struct i2c_client *client;
 	struct input_dev *input;
-	bool (*get_pendown_state)(void);
-	unsigned int poll_period;
-	struct delayed_work dwork;
 };
 
 static int ili210x_read_reg(struct i2c_client *client, u8 reg, void *buf,
@@ -102,20 +98,9 @@  static void ili210x_report_events(struct input_dev *input,
 	input_sync(input);
 }
 
-static bool get_pendown_state(const struct ili210x *priv)
-{
-	bool state = false;
-
-	if (priv->get_pendown_state)
-		state = priv->get_pendown_state();
-
-	return state;
-}
-
-static void ili210x_work(struct work_struct *work)
+static irqreturn_t ili210x_irq(int irq, void *irq_data)
 {
-	struct ili210x *priv = container_of(work, struct ili210x,
-					    dwork.work);
+	struct ili210x *priv = irq_data;
 	struct i2c_client *client = priv->client;
 	struct touchdata touchdata;
 	int error;
@@ -125,21 +110,10 @@  static void ili210x_work(struct work_struct *work)
 	if (error) {
 		dev_err(&client->dev,
 			"Unable to get touchdata, err = %d\n", error);
-		return;
+		return IRQ_HANDLED;
 	}
 
-	ili210x_report_events(priv->input, &touchdata);
-
-	if ((touchdata.status & 0xf3) || get_pendown_state(priv))
-		schedule_delayed_work(&priv->dwork,
-				      msecs_to_jiffies(priv->poll_period));
-}
-
-static irqreturn_t ili210x_irq(int irq, void *irq_data)
-{
-	struct ili210x *priv = irq_data;
-
-	schedule_delayed_work(&priv->dwork, 0);
+	ili210x_report_events(priv, &touchdata);
 
 	return IRQ_HANDLED;
 }
@@ -224,8 +198,6 @@  static int ili210x_i2c_probe(struct i2c_client *client,
 
 	priv->client = client;
 	priv->input = input;
-	priv->poll_period = DEFAULT_POLL_PERIOD;
-	INIT_DELAYED_WORK(&priv->dwork, ili210x_work);
 
 	/* Setup input device */
 	input->name = "ILI210x Touchscreen";
@@ -248,19 +220,19 @@  static int ili210x_i2c_probe(struct i2c_client *client,
 
 	i2c_set_clientdata(client, priv);
 
-	error = request_irq(client->irq, ili210x_irq, 0,
-			    client->name, priv);
+	error = devm_request_threaded_irq(dev, client->irq, NULL, ili210x_irq,
+				 IRQF_ONESHOT, client->name, priv);
 	if (error) {
 		dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n",
 			error);
-		goto err_free_mem;
+		return error;
 	}
 
 	error = sysfs_create_group(&dev->kobj, &ili210x_attr_group);
 	if (error) {
 		dev_err(dev, "Unable to create sysfs attributes, err: %d\n",
 			error);
-		goto err_free_irq;
+		return error;
 	}
 
 	error = input_register_device(priv->input);
@@ -279,19 +251,12 @@  static int ili210x_i2c_probe(struct i2c_client *client,
 
 err_remove_sysfs:
 	sysfs_remove_group(&dev->kobj, &ili210x_attr_group);
-err_free_irq:
-	free_irq(client->irq, priv);
-err_free_mem:
 	return error;
 }
 
 static int ili210x_i2c_remove(struct i2c_client *client)
 {
-	struct ili210x *priv = i2c_get_clientdata(client);
-
 	sysfs_remove_group(&client->dev.kobj, &ili210x_attr_group);
-	free_irq(priv->client->irq, priv);
-	cancel_delayed_work_sync(&priv->dwork);
 	input_unregister_device(priv->input);
 
 	return 0;