Input: edt-ft5x06: Poll the device if no interrupt is configured.
authorDave Stevenson <dave.stevenson@raspberrypi.com>
Fri, 6 Nov 2020 18:45:10 +0000 (18:45 +0000)
committerDom Cobley <popcornmix@gmail.com>
Mon, 21 Mar 2022 16:04:08 +0000 (16:04 +0000)
Not all systems have the interrupt line wired up, so switch to
polling the touchscreen off a timer if no interrupt line is
configured.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
drivers/input/touchscreen/edt-ft5x06.c

index bb2e1cb..339eae4 100644 (file)
@@ -72,6 +72,8 @@
 #define EDT_DEFAULT_NUM_X              1024
 #define EDT_DEFAULT_NUM_Y              1024
 
+#define POLL_INTERVAL_MS               17      /* 17ms = 60fps */
+
 enum edt_pmode {
        EDT_PMODE_NOT_SUPPORTED,
        EDT_PMODE_HIBERNATE,
@@ -130,6 +132,9 @@ struct edt_ft5x06_ts_data {
 
        struct edt_reg_addr reg_addr;
        enum edt_ver version;
+
+       struct timer_list timer;
+       struct work_struct work_i2c_poll;
 };
 
 struct edt_i2c_chip_data {
@@ -279,6 +284,22 @@ out:
        return IRQ_HANDLED;
 }
 
+static void edt_ft5x06_ts_irq_poll_timer(struct timer_list *t)
+{
+       struct edt_ft5x06_ts_data *tsdata = from_timer(tsdata, t, timer);
+
+       schedule_work(&tsdata->work_i2c_poll);
+       mod_timer(&tsdata->timer, jiffies + msecs_to_jiffies(POLL_INTERVAL_MS));
+}
+
+static void edt_ft5x06_ts_work_i2c_poll(struct work_struct *work)
+{
+       struct edt_ft5x06_ts_data *tsdata = container_of(work,
+                       struct edt_ft5x06_ts_data, work_i2c_poll);
+
+       edt_ft5x06_ts_isr(0, tsdata);
+}
+
 static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata,
                                     u8 addr, u8 value)
 {
@@ -1234,17 +1255,27 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
 
        i2c_set_clientdata(client, tsdata);
 
-       irq_flags = irq_get_trigger_type(client->irq);
-       if (irq_flags == IRQF_TRIGGER_NONE)
-               irq_flags = IRQF_TRIGGER_FALLING;
-       irq_flags |= IRQF_ONESHOT;
+       if (client->irq) {
+               irq_flags = irq_get_trigger_type(client->irq);
+               if (irq_flags == IRQF_TRIGGER_NONE)
+                       irq_flags = IRQF_TRIGGER_FALLING;
+               irq_flags |= IRQF_ONESHOT;
 
-       error = devm_request_threaded_irq(&client->dev, client->irq,
-                                       NULL, edt_ft5x06_ts_isr, irq_flags,
-                                       client->name, tsdata);
-       if (error) {
-               dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
-               return error;
+               error = devm_request_threaded_irq(&client->dev, client->irq,
+                                                 NULL, edt_ft5x06_ts_isr,
+                                                 irq_flags, client->name,
+                                                 tsdata);
+               if (error) {
+                       dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
+                       return error;
+               }
+       } else {
+               INIT_WORK(&tsdata->work_i2c_poll,
+                         edt_ft5x06_ts_work_i2c_poll);
+               timer_setup(&tsdata->timer, edt_ft5x06_ts_irq_poll_timer, 0);
+               tsdata->timer.expires = jiffies +
+                                       msecs_to_jiffies(POLL_INTERVAL_MS);
+               add_timer(&tsdata->timer);
        }
 
        error = devm_device_add_group(&client->dev, &edt_ft5x06_attr_group);