[PATCH] Input: goodix - add support for polling on devices without IRQ line

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add the capability of polling the touch controller for events every
16ms, which is useful on hardware that did integrate this touch
controller, but did not integrate the IRQ line, like the RasPi .

Make use of the generic input poller code. Factor out the code
from goodix_ts_irq_handler() into generic goodix_ts_handler(), so
it can be used both by the IRQ handler and poller callback.

Use of_client->irq to find out whether the interrupt line is present
or not, independent of whether this is OF or ACPI system. It is not
possible to register poller in case request_irq() fails, because the
request_irq() in this driver is deliberately called after the input
device was registered, and registering the generic poller at that point
is too late already.

Signed-off-by: Marek Vasut <marek.vasut+renesas@xxxxxxxxxxx>
---
This is a rework of https://github.com/raspberrypi/linux 3756b7801f3e ("input: goodix: Add option to poll instead of relying on IRQ line")
---
Cc: Dave Stevenson <dave.stevenson@xxxxxxxxxxxxxxx>
Cc: Dmitry Torokhov <dmitry.torokhov@xxxxxxxxx>
Cc: Hans de Goede <hdegoede@xxxxxxxxxx>
Cc: linux-input@xxxxxxxxxxxxxxx
Cc: linux-renesas-soc@xxxxxxxxxxxxxxx
---
 drivers/input/touchscreen/goodix.c | 57 ++++++++++++++++++++++++++++--
 1 file changed, 54 insertions(+), 3 deletions(-)

diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
index a3e8a51c9144..91b7d244301d 100644
--- a/drivers/input/touchscreen/goodix.c
+++ b/drivers/input/touchscreen/goodix.c
@@ -48,6 +48,9 @@
 #define MAX_CONTACTS_LOC	5
 #define TRIGGER_LOC		6
 
+/* Polling interval (ms) , 16 ms ~= 60 FPS */
+#define POLL_INTERVAL		16
+
 /* Our special handling for GPIO accesses through ACPI is x86 specific */
 #if defined CONFIG_X86 && defined CONFIG_ACPI
 #define ACPI_GPIO_SUPPORT
@@ -497,6 +500,12 @@ static void goodix_process_events(struct goodix_ts_data *ts)
 	input_sync(ts->input_dev);
 }
 
+static void goodix_ts_handler(struct goodix_ts_data *ts)
+{
+	goodix_process_events(ts);
+	goodix_i2c_write_u8(ts->client, GOODIX_READ_COOR_ADDR, 0);
+}
+
 /**
  * goodix_ts_irq_handler - The IRQ handler
  *
@@ -507,24 +516,57 @@ static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id)
 {
 	struct goodix_ts_data *ts = dev_id;
 
-	goodix_process_events(ts);
-	goodix_i2c_write_u8(ts->client, GOODIX_READ_COOR_ADDR, 0);
+	goodix_ts_handler(ts);
 
 	return IRQ_HANDLED;
 }
 
+static void goodix_ts_poll(struct input_dev *input_dev)
+{
+	struct goodix_ts_data *ts = input_get_drvdata(input_dev);
+
+	goodix_ts_handler(ts);
+}
+
 static void goodix_free_irq(struct goodix_ts_data *ts)
 {
-	devm_free_irq(&ts->client->dev, ts->client->irq, ts);
+	if (ts->client->irq > 0)
+		devm_free_irq(&ts->client->dev, ts->client->irq, ts);
 }
 
 static int goodix_request_irq(struct goodix_ts_data *ts)
 {
+	/* The interrupts property is not present in DT, use poller */
+	if (ts->client->irq <= 0)
+		return 0;
+
+	/* The interrupts property is present in DT, use IRQs */
 	return devm_request_threaded_irq(&ts->client->dev, ts->client->irq,
 					 NULL, goodix_ts_irq_handler,
 					 ts->irq_flags, ts->client->name, ts);
 }
 
+static int goodix_request_poller(struct goodix_ts_data *ts)
+{
+	struct device *dev = &ts->client->dev;
+	int error;
+
+	/* The interrupts property is present in DT, use IRQs */
+	if (ts->client->irq > 0)
+		return 0;
+
+	/* The interrupts property is not present in DT, use poller */
+	error = input_setup_polling(ts->input_dev, goodix_ts_poll);
+	if (error) {
+		dev_err(dev, "Unable to set up polling: %d\n", error);
+		return error;
+	}
+
+	input_set_poll_interval(ts->input_dev, POLL_INTERVAL);
+
+	return 0;
+}
+
 static int goodix_check_cfg_8(struct goodix_ts_data *ts, const u8 *cfg, int len)
 {
 	int i, raw_cfg_len = len - 2;
@@ -1219,6 +1261,15 @@ static int goodix_configure_dev(struct goodix_ts_data *ts)
 		return error;
 	}
 
+	input_set_drvdata(ts->input_dev, ts);
+
+	error = goodix_request_poller(ts);
+	if (error) {
+		dev_err(&ts->client->dev,
+			"Failed to initialize poller: %d", error);
+		return error;
+	}
+
 	error = input_register_device(ts->input_dev);
 	if (error) {
 		dev_err(&ts->client->dev,
-- 
2.47.2





[Index of Archives]     [Linux Samsung SOC]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux