public inbox for linux-input@vger.kernel.org
 help / color / mirror / Atom feed
From: Marek Vasut <marex@nabladev.com>
To: linux-input@vger.kernel.org
Cc: Marek Vasut <marex@nabladev.com>,
	Conor Dooley <conor+dt@kernel.org>,
	Dmitry Torokhov <dmitry.torokhov@gmail.com>,
	Jens Reidel <adrian@mainlining.org>,
	Joel Selvaraj <foss@joelselvaraj.com>,
	Krzysztof Kozlowski <krzk+dt@kernel.org>,
	Rob Herring <robh@kernel.org>,
	Wolfram Sang <wsa+renesas@sang-engineering.com>,
	devicetree@vger.kernel.org, kernel@dh-electronics.com,
	linux-kernel@vger.kernel.org
Subject: [PATCH 2/2] Input: edt-ft5x06 - add support for polling mode
Date: Fri,  9 Jan 2026 04:51:45 +0100	[thread overview]
Message-ID: <20260109035149.1341931-2-marex@nabladev.com> (raw)
In-Reply-To: <20260109035149.1341931-1-marex@nabladev.com>

There are designs incorporating EDT ETM touch controller that do not
connect interrupt pin, for example Raspberry Pi. To support such systems
use polling mode for the input device when I2C client does not have
interrupt assigned to it.

Signed-off-by: Marek Vasut <marex@nabladev.com>
---
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Jens Reidel <adrian@mainlining.org>
Cc: Joel Selvaraj <foss@joelselvaraj.com>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Rob Herring <robh@kernel.org>
Cc: Wolfram Sang <wsa+renesas@sang-engineering.com>
Cc: devicetree@vger.kernel.org
Cc: kernel@dh-electronics.com
Cc: linux-input@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/input/touchscreen/edt-ft5x06.c | 74 ++++++++++++++++++--------
 1 file changed, 53 insertions(+), 21 deletions(-)

diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index 9a0add3d39159..a16bf93243976 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -69,6 +69,7 @@
 #define TOUCH_EVENT_RESERVED		0x03
 
 #define EDT_NAME_LEN			23
+#define EDT_POLL_INTERVAL_MS		17 /* msec */
 #define EDT_SWITCH_MODE_RETRIES		10
 #define EDT_SWITCH_MODE_DELAY		5 /* msec */
 #define EDT_RAW_DATA_RETRIES		100
@@ -295,9 +296,9 @@ static const struct regmap_config edt_M06_i2c_regmap_config = {
 	.write = edt_M06_i2c_write,
 };
 
-static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
+static void edt_ft5x06_ts_process_events(struct edt_ft5x06_ts_data *tsdata,
+					 bool poll)
 {
-	struct edt_ft5x06_ts_data *tsdata = dev_id;
 	struct device *dev = &tsdata->client->dev;
 	u8 rdbuf[63];
 	int i, type, x, y, id;
@@ -307,9 +308,13 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
 	error = regmap_bulk_read(tsdata->regmap, tsdata->tdata_cmd, rdbuf,
 				 tsdata->tdata_len);
 	if (error) {
-		dev_err_ratelimited(dev, "Unable to fetch data, error: %d\n",
-				    error);
-		goto out;
+		if (!poll) {
+			/* Polling may result in no data. */
+			dev_err_ratelimited(dev,
+					    "Unable to fetch data, error: %d\n",
+					    error);
+		}
+		return;
 	}
 
 	for (i = 0; i < tsdata->max_support_points; i++) {
@@ -341,11 +346,24 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
 
 	input_mt_report_pointer_emulation(tsdata->input, true);
 	input_sync(tsdata->input);
+}
+
+static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
+{
+	struct edt_ft5x06_ts_data *tsdata = dev_id;
+
+	edt_ft5x06_ts_process_events(tsdata, false);
 
-out:
 	return IRQ_HANDLED;
 }
 
+static void edt_ft5x06_work_i2c_poll(struct input_dev *input)
+{
+	struct edt_ft5x06_ts_data *tsdata = input_get_drvdata(input);
+
+	edt_ft5x06_ts_process_events(tsdata, true);
+}
+
 struct edt_ft5x06_attribute {
 	struct device_attribute dattr;
 	size_t field_offset;
@@ -613,7 +631,8 @@ static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata)
 		return -EINVAL;
 	}
 
-	disable_irq(client->irq);
+	if (client->irq)
+		disable_irq(client->irq);
 
 	if (!tsdata->raw_buffer) {
 		tsdata->raw_bufsize = tsdata->num_x * tsdata->num_y *
@@ -656,7 +675,8 @@ static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata)
 	kfree(tsdata->raw_buffer);
 	tsdata->raw_buffer = NULL;
 	tsdata->factory_mode = false;
-	enable_irq(client->irq);
+	if (client->irq)
+		enable_irq(client->irq);
 
 	return error;
 }
@@ -697,7 +717,8 @@ static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata)
 	tsdata->raw_buffer = NULL;
 
 	edt_ft5x06_restore_reg_parameters(tsdata);
-	enable_irq(client->irq);
+	if (client->irq)
+		enable_irq(client->irq);
 
 	return 0;
 }
@@ -1331,17 +1352,26 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client)
 		return error;
 	}
 
-	irq_flags = irq_get_trigger_type(client->irq);
-	if (irq_flags == IRQF_TRIGGER_NONE)
-		irq_flags = IRQF_TRIGGER_FALLING;
-	irq_flags |= IRQF_ONESHOT;
+	input_set_drvdata(input, tsdata);
 
-	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;
+	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;
+		}
+	} else {
+		error = input_setup_polling(input, edt_ft5x06_work_i2c_poll);
+		if (error)
+			return dev_err_probe(&client->dev, error, "Unable to set up polling.\n");
+		input_set_poll_interval(input, EDT_POLL_INTERVAL_MS);
 	}
 
 	error = input_register_device(input);
@@ -1394,7 +1424,8 @@ static int edt_ft5x06_ts_suspend(struct device *dev)
 	 * settings. Disable the irq to avoid adjusting each host till the
 	 * device is back in a full functional state.
 	 */
-	disable_irq(tsdata->client->irq);
+	if (tsdata->client->irq)
+		disable_irq(tsdata->client->irq);
 
 	gpiod_set_value_cansleep(reset_gpio, 1);
 	usleep_range(1000, 2000);
@@ -1456,7 +1487,8 @@ static int edt_ft5x06_ts_resume(struct device *dev)
 		msleep(300);
 
 		edt_ft5x06_restore_reg_parameters(tsdata);
-		enable_irq(tsdata->client->irq);
+		if (tsdata->client->irq)
+			enable_irq(tsdata->client->irq);
 
 		if (tsdata->factory_mode)
 			ret = edt_ft5x06_factory_mode(tsdata);
-- 
2.51.0


  reply	other threads:[~2026-01-09  3:52 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-09  3:51 [PATCH 1/2] dt-bindings: input: touchscreen: edt-ft5x06: Drop 'interrupts' requirement Marek Vasut
2026-01-09  3:51 ` Marek Vasut [this message]
2026-01-15 17:14 ` Rob Herring (Arm)

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260109035149.1341931-2-marex@nabladev.com \
    --to=marex@nabladev.com \
    --cc=adrian@mainlining.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=dmitry.torokhov@gmail.com \
    --cc=foss@joelselvaraj.com \
    --cc=kernel@dh-electronics.com \
    --cc=krzk+dt@kernel.org \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=robh@kernel.org \
    --cc=wsa+renesas@sang-engineering.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox