From nobody Fri Jul 24 21:52:33 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EFFAB43B49B; Thu, 23 Jul 2026 11:27:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784806030; cv=none; b=TyK6VzuDtH1OwKG2x/cZKsjFRaLH87OeinnjhFtd/CVXs3A9Ii3ew/ROoscZ3L1ilgt8NQJvXbEp/tIYN6cCJoKLYs9OHvy8Kkk8PMXQiljg/kCRSUl29DujA6mXBGkKLbgbcaVgxvuhLnNXaoTR2rlsrHLjlsSFXuQ4nw6OdOo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784806030; c=relaxed/simple; bh=hzHKgZ4D+jeJoYuFb7yM5jGzuM70NqWd6XTX2mLqxlo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=OJJovd6uwpH8TN3qWfD9G+xSsAcTFu3wEqGbVC3Ao9ntbUUvWCqSFREeVpmLeIB0YLxG5w0KGckvf8LZxtyvhXJja0F98X1xhWcIDpicESC4XwrvZXGosJiaKsKDbtfsZiK+gn5suTszjLJ0anVg9vcUwSpVG17b5agWUOemNyA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QTljDhYS; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QTljDhYS" Received: by smtp.kernel.org (Postfix) with ESMTPS id C6EB0C2BCC7; Thu, 23 Jul 2026 11:27:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1784806029; bh=hzHKgZ4D+jeJoYuFb7yM5jGzuM70NqWd6XTX2mLqxlo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=QTljDhYSwgFzeA/1TwD7zB+WurAqS8b/Yd8JXWzxOFnTwfQG0ZRRrIOGkwNFl212I 7+IsZBlw87YdFO/opC+HqtcAjPeIttipFNW36CrCKttNeDCOeuFPhAgjFxHneA/ssY nxnF1uSJJignVecafquspEqItcCEbvau+MWc9DwuyZb3RqQzi+YVQmvfh1ZCray+qI Rc9knNPDvQ7oYwHu8KHU4eeBaXey9InjiEOy+GVJOeMp5puIzDYGxs54enFFb9GRN8 B6DyLbQWLY8U1YbMc5rKloS57diKNKEh9HxHYg8tqL2At3+pFUFKuyXcRi6QLNWs8S jPui0cv8WduFg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id B2A6CC531CF; Thu, 23 Jul 2026 11:27:09 +0000 (UTC) From: Alexandre Hamamdjian via B4 Relay Date: Thu, 23 Jul 2026 18:27:08 +0700 Subject: [PATCH 1/4] Input: edt-ft5x06 - ignore contacts with an out-of-range slot id Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260723-b4-ft5426-v1-1-d4b4e32be042@gmail.com> References: <20260723-b4-ft5426-v1-0-d4b4e32be042@gmail.com> In-Reply-To: <20260723-b4-ft5426-v1-0-d4b4e32be042@gmail.com> To: Dmitry Torokhov , Henrik Rydberg , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Alexandre Hamamdjian X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1784806028; l=1395; i=azkali.limited@gmail.com; s=20260510; h=from:subject:message-id; bh=D0XuFOboekFyulaNFU7MxXVtoV8b4Kp9OM9aoWYiFTo=; b=oso77UFU2tWgwp7TRwwFdKsBZiu0lKjhhcLPJNm0fpO3hsaHh+HTKbV8LSrOdbE2Q3op2RQu1 6OwLQ8qvABnD13r3CHrfXX2JWjVBjZF531nfbvGbgHss0RKGNsql16+ X-Developer-Key: i=azkali.limited@gmail.com; a=ed25519; pk=I0Z0IdCdQJqNGX+FQUnXhrHg950u3cM6Xzz3YT6JOyQ= X-Endpoint-Received: by B4 Relay for azkali.limited@gmail.com/20260510 with auth_id=774 X-Original-From: Alexandre Hamamdjian Reply-To: azkali.limited@gmail.com From: Alexandre Hamamdjian The per-contact slot id is taken from the top nibble of the third report byte, so it can be any value from 0 to 15. The driver only allocates max_support_points MT slots (2 to 10 depending on the variant), so a report that carries an id at or above that count - be it a genuinely higher-numbered contact or a corrupted byte - is outside the range the input core was told about. input_mt_slot() silently ignores an ABS_MT_SLOT beyond num_slots and leaves the current slot unchanged, so the following input_mt_report_slot_state()/touchscreen_report_pos() pair is applied to whichever slot happened to be selected last, reporting the contact at the wrong position. Skip such entries instead. Signed-off-by: Alexandre Hamamdjian --- drivers/input/touchscreen/edt-ft5x06.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchsc= reen/edt-ft5x06.c index d3b1177185a3..d6c3d033b83d 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -331,6 +331,8 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev= _id) swap(x, y); =20 id =3D (buf[2] >> 4) & 0x0f; + if (id >=3D tsdata->max_support_points) + continue; =20 input_mt_slot(tsdata->input, id); if (input_mt_report_slot_state(tsdata->input, MT_TOOL_FINGER, --=20 2.55.0 From nobody Fri Jul 24 21:52:33 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 417AF46EF80; Thu, 23 Jul 2026 11:27:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784806030; cv=none; b=aCxH+0c5DZCrLIcuY9iLkpLNsfaVyyhzLxKoeg5yvGbbkKjhN7W+vfl7aIq1LWA65+lPJSJkQo77HL6zNjYHuB2MrktE90DhyYWffDdzCzrrALgzzWzpHe7i699vHJSEpBrsrr6gIzXbzGayJlSP88Zjc+06Gqras/f+tI6aoFA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784806030; c=relaxed/simple; bh=F/STKscT5wBCfIr4tGpfk1umGluriePYuowtYacQTvo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=l1emxsmi15VYYkxB8fUYizkHqNkUW9+pfC5KSVmBwdgYUjjjjGGJ2dZGLEzjCBs5IKNkoY6aZ5FXWaInC38TFA8683MtmNRSI/uPqt5fj0LJ55y0unnojA8B0ybeDGT3GNU4YFI4Yg3o64gz0m7ghxKsCwdEwPpsKCvWxCXpzxc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=XeOu+r7m; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="XeOu+r7m" Received: by smtp.kernel.org (Postfix) with ESMTPS id E11CDC4AF0B; Thu, 23 Jul 2026 11:27:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1784806029; bh=F/STKscT5wBCfIr4tGpfk1umGluriePYuowtYacQTvo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=XeOu+r7mZQVq90XG8mgIEAN6RccE85BgyNVE5+2aCYvEAnRQtiNLghX8ukRyxwb/T K7LdjhTxeVM1MWrRnSCafMKGvpf+0Pa4CMIu88sqAwV6rGyUMUFUMjQXwj81G4pykG f3zsRR5aApyyNN0vXN0Qxbyi1HGi9KbAlb73lGo8yi3Tg7rF0eKZTsBJuKPuVhDv7i S9kcIcKvD2BhMGoHcJUkA8IYGbpkUsAzcU+JudelG86mm27w4P4HhLRsW/poSAZD0X UziGGoiCS3W+gxKocK1qqrWkHkhOwbqGUJ0kH37QsA4JdVUjhoFzT/FG5TeTJ1l6WF 6rxjHLg8FN+vQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id CB6E1C531D0; Thu, 23 Jul 2026 11:27:09 +0000 (UTC) From: Alexandre Hamamdjian via B4 Relay Date: Thu, 23 Jul 2026 18:27:09 +0700 Subject: [PATCH 2/4] dt-bindings: input: edt-ft5x06 - add no-regmap-bulk-read property Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260723-b4-ft5426-v1-2-d4b4e32be042@gmail.com> References: <20260723-b4-ft5426-v1-0-d4b4e32be042@gmail.com> In-Reply-To: <20260723-b4-ft5426-v1-0-d4b4e32be042@gmail.com> To: Dmitry Torokhov , Henrik Rydberg , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Alexandre Hamamdjian X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1784806028; l=1274; i=azkali.limited@gmail.com; s=20260510; h=from:subject:message-id; bh=Y6plFHAdYOrN+v0JnPDtGVQB09ZIhxaAyZp05Rxn6xo=; b=AnFiHS16i0k014X7gtwrdF8LI0B2V9NUk/mHSujJOLMYi7m1cJkwgsUyo80cOMKx8UUiRXHlO Ize2/S5daARBtx4frDkwkgciyZdjEGpqSt3k7N+jRkMZ8plRr0v9Nk+ X-Developer-Key: i=azkali.limited@gmail.com; a=ed25519; pk=I0Z0IdCdQJqNGX+FQUnXhrHg950u3cM6Xzz3YT6JOyQ= X-Endpoint-Received: by B4 Relay for azkali.limited@gmail.com/20260510 with auth_id=774 X-Original-From: Alexandre Hamamdjian Reply-To: azkali.limited@gmail.com From: Alexandre Hamamdjian Document an optional boolean property for boards whose i2c controller cannot reliably sustain the multi-byte block read of a full touch frame. When set, the driver reads the frame one register at a time instead of in a single bulk transfer. Signed-off-by: Alexandre Hamamdjian --- .../devicetree/bindings/input/touchscreen/edt-ft5x06.yaml | 8 ++++= ++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06= .yaml b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml index 68b2f1601654..0d8310a290ea 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml +++ b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml @@ -111,6 +111,14 @@ properties: =20 interrupt-controller: true =20 + no-regmap-bulk-read: + type: boolean + description: + Set this when the i2c controller the touch controller is attached to + cannot reliably sustain the multi-byte block read of a full touch + frame and aborts long transfers. The driver then reads the touch + frame one register at a time instead of in a single bulk transfer. + unevaluatedProperties: false =20 required: --=20 2.55.0 From nobody Fri Jul 24 21:52:33 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4A2BE46EF81; Thu, 23 Jul 2026 11:27:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784806030; cv=none; b=KdkleTPjqa8BpbZa0XgAVOBw9wPBjZVs/Zl+7HzylP4MOvmHISTftHGlAtsbcEcY8uJDQWKXOKarOm8hgkQ2dC3oG+Jhs04UmCjD7DH2yq1YbPrJtRV81bmXsABB6xBvDD6DcBGPqeQOrGUvjSabb1k6zQukoLInNSWsbVopqMk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784806030; c=relaxed/simple; bh=ODeGx9cxPdGjmXdph8GFdfMVSd4giqicWH6znncxKws=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=T0cMb+V2es2pfm0UIdJHuBYGSBRAzk3LJ6TUUH9nGzeFhdmYImX83nwBgz+XXw5gSjRa+vyt8xZtv379j91liYFamyypqyH9U6pTI3GKYE3dnWD5nyDh0m1RW0vbvXqmWzr4hrjqWleuvSwW2lZgpxIMTDDdFMo1vK1FB8X+A2M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Nr5hjqVJ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Nr5hjqVJ" Received: by smtp.kernel.org (Postfix) with ESMTPS id 1ABD9C2BCC7; Thu, 23 Jul 2026 11:27:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1784806030; bh=ODeGx9cxPdGjmXdph8GFdfMVSd4giqicWH6znncxKws=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=Nr5hjqVJTCLtNtg/fquLaE597DgRDC3vmA8VBOzkzsiJsUjr6cqYxZxJxdzxj7kEH 9pQtI0xaU3gQMh7j2cHX9AM4c304lTBUxXQHd364/sBtPLSHct3aoaCkerF3RmKjcK mCGjzi5CnbtQeQkoUUIS03tuUoi31L0zca3KP6dWcgp2xq7TiVVZ0Yy+5UQv+eCWR/ tJKYJxd9zU/4sramP+LKhsOg12baEkWbpMtmY5Ojoe0pRKSPctN0SXkqypbcxnJBN8 wDthhE+GhyOjjnece80xujeN9QDRof93dywT3rOe+3+aLX/NgfoCs1hk1vv5VOytC8 N07lHK0pLLjJQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0864BC531CB; Thu, 23 Jul 2026 11:27:10 +0000 (UTC) From: Alexandre Hamamdjian via B4 Relay Date: Thu, 23 Jul 2026 18:27:10 +0700 Subject: [PATCH 3/4] Input: edt-ft5x06 - allow reading the touch frame one register at a time Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260723-b4-ft5426-v1-3-d4b4e32be042@gmail.com> References: <20260723-b4-ft5426-v1-0-d4b4e32be042@gmail.com> In-Reply-To: <20260723-b4-ft5426-v1-0-d4b4e32be042@gmail.com> To: Dmitry Torokhov , Henrik Rydberg , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Alexandre Hamamdjian , Teguh Sobirin X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1784806028; l=3201; i=azkali.limited@gmail.com; s=20260510; h=from:subject:message-id; bh=/kaGFdHU8xM8Uq6yxPXvl4M3ZEPYoY2WUk9xAjehqNs=; b=bFJymW0Lwb9/tVbTBZZmejp1iA5i0JTyYdsXw5zot/D2NvYcilOHZlzNroDe6yl9cUyu92Wio DxGLEO7K12CA99RMH5aJ0e2C3BpGkkttZH0gV2vw4YWcNkPEEzFaFGL X-Developer-Key: i=azkali.limited@gmail.com; a=ed25519; pk=I0Z0IdCdQJqNGX+FQUnXhrHg950u3cM6Xzz3YT6JOyQ= X-Endpoint-Received: by B4 Relay for azkali.limited@gmail.com/20260510 with auth_id=774 X-Original-From: Alexandre Hamamdjian Reply-To: azkali.limited@gmail.com From: Teguh Sobirin Every touch interrupt reads the whole touch frame in a single i2c block read via regmap_bulk_read(). On some boards the i2c controller the panel is wired to cannot sustain that multi-byte transfer: on the AYANEO Pocket DS the FocalTech FT5426 sits on a marginal Qualcomm GENI bus that intermittently aborts a long read with -EAGAIN or -ETIMEDOUT, and the GENI controller has no bus recovery, so the block read fails on nearly every interrupt and the panel is unusable. Honour the "no-regmap-bulk-read" property. When set, the driver reads the frame one register at a time with a short retry on the transient bus errors, keeping each transfer small enough to complete. Boards on a healthy bus keep using the single bulk transfer and are unaffected. Signed-off-by: Teguh Sobirin Co-developed-by: Alexandre Hamamdjian Signed-off-by: Alexandre Hamamdjian --- drivers/input/touchscreen/edt-ft5x06.c | 37 ++++++++++++++++++++++++++++++= ++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchsc= reen/edt-ft5x06.c index d6c3d033b83d..ac61ac44fd64 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -146,6 +146,7 @@ struct edt_ft5x06_ts_data { enum edt_ver version; unsigned int crc_errors; unsigned int header_errors; + bool no_regmap_bulk_read; }; =20 struct edt_i2c_chip_data { @@ -295,6 +296,31 @@ static const struct regmap_config edt_M06_i2c_regmap_c= onfig =3D { .write =3D edt_M06_i2c_write, }; =20 +static int edt_ft5x06_bulk_read(struct regmap *map, unsigned int start, + void *val, size_t len) +{ + u8 *dst =3D val; + size_t off; + + for (off =3D 0; off < len; off++) { + unsigned int v; + int ret, tries; + + for (tries =3D 0; tries < 3; tries++) { + ret =3D regmap_read(map, start + off, &v); + if (!ret) + break; + if (ret =3D=3D -ETIMEDOUT || ret =3D=3D -EAGAIN) + usleep_range(2000, 4000); + } + if (ret) + return ret; + dst[off] =3D v; + } + + return 0; +} + static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) { struct edt_ft5x06_ts_data *tsdata =3D dev_id; @@ -304,8 +330,12 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *de= v_id) int error; =20 memset(rdbuf, 0, sizeof(rdbuf)); - error =3D regmap_bulk_read(tsdata->regmap, tsdata->tdata_cmd, rdbuf, - tsdata->tdata_len); + if (tsdata->no_regmap_bulk_read) + error =3D edt_ft5x06_bulk_read(tsdata->regmap, tsdata->tdata_cmd, + rdbuf, tsdata->tdata_len); + else + error =3D 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); @@ -1212,6 +1242,9 @@ static int edt_ft5x06_ts_probe(struct i2c_client *cli= ent) return error; } =20 + tsdata->no_regmap_bulk_read =3D + device_property_read_bool(&client->dev, "no-regmap-bulk-read"); + /* * Check which sleep modes we can support. Power-off requires the * reset-pin to ensure correct power-down/power-up behaviour. Start with --=20 2.55.0 From nobody Fri Jul 24 21:52:33 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 677DD46F494; Thu, 23 Jul 2026 11:27:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784806030; cv=none; b=KvAbCAc9Ws1vO/itdQnsNUTSIL/CLYRuhi6BfSfJiYVVIOzc33MjkEodlrCRspLAZRVJMOz4QtQKwpH5mnS1r5SflAGRHgSFeBhi6Gr1xU9giEdB1Jah1Fq+5+OUwuX1Z82DVogEsWgDpebv6cgfXvO6WLy3nU7sUeFS7aetNDk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784806030; c=relaxed/simple; bh=zUO9LnLrXA6kWhyHaixyYZdwF04RJZtsbTKEU/mNKDM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=llNL2GSU9jk/FGSpsrm4HxEgQ2ibrj/m2SyNYkGOWFNyzSUt+3nwB+aD6rpw+Q5cYjId9XKc5uZSmHEj5ZLZQO/mmU4326MaYEBiXxMY4rekBMBhLp6fx3MGIS+udzdSGkY0sS+Y+UkNblwcldzPTlDJhT02EGut3AE2DzZNg/Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=iHbQJDR2; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="iHbQJDR2" Received: by smtp.kernel.org (Postfix) with ESMTPS id 33D2DC2BCC9; Thu, 23 Jul 2026 11:27:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1784806030; bh=zUO9LnLrXA6kWhyHaixyYZdwF04RJZtsbTKEU/mNKDM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=iHbQJDR225qkCqYnW/ZZQeK5b2myaEVgws2mwnGJ7QHw2subKkzo5M9wn/XfYHDQo /WtNjKNa4XIIpA+5JZNF2euBh1HV7bVmKDKZl0acFJfqSHMdZPXU20enhfPOrd2h9b mHhYhxKLzV9dfDoETAGlnJMKHXutuXu/XurxaAhzx6o11hxYyR9e11T1/zzofRfop4 TeCEcgSfWbwfeTjkGgNWKBTXzunNJiYRXAJaizlRDD/arhFFz96ioJG22Byc9lAp8I P6mIN29vmqFk38szIOC+nseommIcnTkzUA6f+WUHouvU5qCeFhlkDntJO7gPEe5VV6 uphNyyy+8/dTA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 22F64C531CF; Thu, 23 Jul 2026 11:27:10 +0000 (UTC) From: Alexandre Hamamdjian via B4 Relay Date: Thu, 23 Jul 2026 18:27:11 +0700 Subject: [PATCH 4/4] Input: edt-ft5x06 - poll while a contact is down to recover dropped releases Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260723-b4-ft5426-v1-4-d4b4e32be042@gmail.com> References: <20260723-b4-ft5426-v1-0-d4b4e32be042@gmail.com> In-Reply-To: <20260723-b4-ft5426-v1-0-d4b4e32be042@gmail.com> To: Dmitry Torokhov , Henrik Rydberg , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Alexandre Hamamdjian X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1784806028; l=10202; i=azkali.limited@gmail.com; s=20260510; h=from:subject:message-id; bh=yaHIDDdKuKyw2nsbkxWJtOZ/A0eSGr3eWe261NjiyQE=; b=T6SY2d0DjXAzZSw785Jshbz8BI1LNpFgkHDPoW+gd2hdfEKYphOaAJ5/mdIJDGx/sYKvpKa0w PydLL2S35ESBt48QR9am11oLAd2vpJBl4pt2oFaHPploX3LYivBk6I+ X-Developer-Key: i=azkali.limited@gmail.com; a=ed25519; pk=I0Z0IdCdQJqNGX+FQUnXhrHg950u3cM6Xzz3YT6JOyQ= X-Endpoint-Received: by B4 Relay for azkali.limited@gmail.com/20260510 with auth_id=774 X-Original-From: Alexandre Hamamdjian Reply-To: azkali.limited@gmail.com From: Alexandre Hamamdjian The driver is purely interrupt driven: a touch-up is only reported when the controller raises an edge for the release frame and that frame is read successfully. On a marginal i2c bus a read can fail or be dropped, and if the read that carried the release is the one lost there is no further edge to re-read it, so the contact stays held down forever - the pointer sticks mid-drag. This is readily reproducible on the AYANEO Pocket DS, whose FT5426 hangs off an unreliable Qualcomm GENI bus. Stop trusting a single edge to deliver the release. Track which slots are held down in a mask and, while any contact is down, re-read the frame on a short timer. A contact missing from the frame is released only after a few consecutive misses so a lone glitchy read cannot cut a still-present tap or drag; conversely, once the finger is really gone the polled reads stop listing it and it is released regardless of whether an explicit touch-up frame ever arrives. The timer stops as soon as the last contact is released, so an idle panel is still fully interrupt driven. The read path also gains a bounded retry over the transient bus errors and, when reads keep failing for over a second, a reset-line pulse to recover a wedged controller, dropping any held contacts afterwards since the post-reset finger state is unknown. The poll worker is cancelled on suspend and, via a devm action registered before the IRQ, on removal, so it can never touch i2c after the device is powered down or the IRQ freed. Signed-off-by: Alexandre Hamamdjian --- drivers/input/touchscreen/edt-ft5x06.c | 173 +++++++++++++++++++++++++++++= +--- 1 file changed, 157 insertions(+), 16 deletions(-) diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchsc= reen/edt-ft5x06.c index ac61ac44fd64..794c0650f5cb 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -147,8 +148,19 @@ struct edt_ft5x06_ts_data { unsigned int crc_errors; unsigned int header_errors; bool no_regmap_bulk_read; + unsigned long last_reset; + unsigned long last_success; + struct delayed_work poll_work; + /* io_lock serialises the frame read between the IRQ and the poll work */ + struct mutex io_lock; + u16 down_mask; + u8 miss[16]; }; =20 +/* poll cadence and release debounce for the poll-while-touched recovery */ +#define EDT_POLL_INTERVAL_MS 15 +#define EDT_RELEASE_MISSES 3 + struct edt_i2c_chip_data { int max_support_points; }; @@ -321,26 +333,83 @@ static int edt_ft5x06_bulk_read(struct regmap *map, u= nsigned int start, return 0; } =20 -static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) +static void edt_ft5x06_release_all(struct edt_ft5x06_ts_data *tsdata) +{ + int id; + + if (!tsdata->down_mask) + return; + + for (id =3D 0; id < tsdata->max_support_points; id++) { + if (!(tsdata->down_mask & BIT(id))) + continue; + input_mt_slot(tsdata->input, id); + input_mt_report_slot_state(tsdata->input, MT_TOOL_FINGER, false); + } + tsdata->down_mask =3D 0; + memset(tsdata->miss, 0, sizeof(tsdata->miss)); + input_mt_report_pointer_emulation(tsdata->input, true); + input_sync(tsdata->input); +} + +static void edt_ft5x06_fetch_and_report(struct edt_ft5x06_ts_data *tsdata) { - struct edt_ft5x06_ts_data *tsdata =3D dev_id; struct device *dev =3D &tsdata->client->dev; + u16 new_mask =3D 0, released =3D 0; u8 rdbuf[63]; int i, type, x, y, id; - int error; + int error, tries; =20 memset(rdbuf, 0, sizeof(rdbuf)); - if (tsdata->no_regmap_bulk_read) - error =3D edt_ft5x06_bulk_read(tsdata->regmap, tsdata->tdata_cmd, - rdbuf, tsdata->tdata_len); - else - error =3D regmap_bulk_read(tsdata->regmap, tsdata->tdata_cmd, - rdbuf, tsdata->tdata_len); + for (tries =3D 0; tries < 4; tries++) { + if (tsdata->no_regmap_bulk_read) + error =3D edt_ft5x06_bulk_read(tsdata->regmap, + tsdata->tdata_cmd, rdbuf, + tsdata->tdata_len); + else + error =3D regmap_bulk_read(tsdata->regmap, + tsdata->tdata_cmd, rdbuf, + tsdata->tdata_len); + if (!error) + break; + if (error !=3D -EAGAIN && error !=3D -ETIMEDOUT && + error !=3D -EIO && error !=3D -ENXIO) + break; + usleep_range(min(1000U << tries, 4000U), + min(2000U << tries, 8000U)); + } if (error) { dev_err_ratelimited(dev, "Unable to fetch data, error: %d\n", error); - goto out; + /* + * A run of failed reads with no success for over a second means + * the controller is wedged rather than just glitching; pulse the + * reset line to recover it and drop any held contacts, since the + * post-reset finger state is unknown. + */ + if (tsdata->reset_gpio && + time_after(jiffies, tsdata->last_success + HZ) && + time_after(jiffies, tsdata->last_reset + 2 * HZ)) { + tsdata->last_reset =3D jiffies; + gpiod_set_value_cansleep(tsdata->reset_gpio, 1); + usleep_range(5000, 6000); + gpiod_set_value_cansleep(tsdata->reset_gpio, 0); + msleep(300); + tsdata->last_success =3D jiffies; + dev_warn_ratelimited(dev, "reset to recover controller\n"); + edt_ft5x06_release_all(tsdata); + } + return; } + tsdata->last_success =3D jiffies; + + /* + * TD_STATUS holds the active-contact count; a value above the panel + * maximum means the frame is corrupt, so keep the previous state. + */ + if (tsdata->version !=3D EDT_M06 && + (rdbuf[2] & 0x0f) > tsdata->max_support_points) + return; =20 for (i =3D 0; i < tsdata->max_support_points; i++) { u8 *buf =3D &rdbuf[i * tsdata->point_len + tsdata->tdata_offset]; @@ -349,10 +418,12 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *d= ev_id) /* ignore Reserved events */ if (type =3D=3D TOUCH_EVENT_RESERVED) continue; - /* M06 sometimes sends bogus coordinates in TOUCH_DOWN */ if (tsdata->version =3D=3D EDT_M06 && type =3D=3D TOUCH_EVENT_DOWN) continue; + /* releases are derived from the down-mask diff below */ + if (type =3D=3D TOUCH_EVENT_UP) + continue; =20 x =3D get_unaligned_be16(buf) & 0x0fff; y =3D get_unaligned_be16(buf + 2) & 0x0fff; @@ -363,21 +434,75 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *d= ev_id) id =3D (buf[2] >> 4) & 0x0f; if (id >=3D tsdata->max_support_points) continue; + if (tsdata->prop.max_x && + (x > tsdata->prop.max_x || y > tsdata->prop.max_y)) + continue; =20 input_mt_slot(tsdata->input, id); - if (input_mt_report_slot_state(tsdata->input, MT_TOOL_FINGER, - type !=3D TOUCH_EVENT_UP)) - touchscreen_report_pos(tsdata->input, &tsdata->prop, - x, y, true); + input_mt_report_slot_state(tsdata->input, MT_TOOL_FINGER, true); + touchscreen_report_pos(tsdata->input, &tsdata->prop, x, y, true); + new_mask |=3D BIT(id); } =20 + /* + * Reconcile held contacts with this frame. A contact absent from the + * frame is released only after EDT_RELEASE_MISSES consecutive misses so + * a single glitchy read cannot cut a still-present tap or drag. + */ + for (id =3D 0; id < tsdata->max_support_points; id++) { + if (new_mask & BIT(id)) { + tsdata->miss[id] =3D 0; + continue; + } + if (!(tsdata->down_mask & BIT(id))) + continue; + if (++tsdata->miss[id] >=3D EDT_RELEASE_MISSES) { + input_mt_slot(tsdata->input, id); + input_mt_report_slot_state(tsdata->input, + MT_TOOL_FINGER, false); + tsdata->miss[id] =3D 0; + released |=3D BIT(id); + } + } + tsdata->down_mask =3D (tsdata->down_mask | new_mask) & ~released; + 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 =3D dev_id; + + guard(mutex)(&tsdata->io_lock); + edt_ft5x06_fetch_and_report(tsdata); + if (tsdata->down_mask) + mod_delayed_work(system_wq, &tsdata->poll_work, + msecs_to_jiffies(EDT_POLL_INTERVAL_MS)); =20 -out: return IRQ_HANDLED; } =20 +static void edt_ft5x06_poll_work(struct work_struct *work) +{ + struct edt_ft5x06_ts_data *tsdata =3D + container_of(to_delayed_work(work), + struct edt_ft5x06_ts_data, poll_work); + + guard(mutex)(&tsdata->io_lock); + edt_ft5x06_fetch_and_report(tsdata); + if (tsdata->down_mask) + mod_delayed_work(system_wq, &tsdata->poll_work, + msecs_to_jiffies(EDT_POLL_INTERVAL_MS)); +} + +static void edt_ft5x06_cancel_poll(void *data) +{ + struct edt_ft5x06_ts_data *tsdata =3D data; + + cancel_delayed_work_sync(&tsdata->poll_work); +} + struct edt_ft5x06_attribute { struct device_attribute dattr; size_t field_offset; @@ -1244,6 +1369,10 @@ static int edt_ft5x06_ts_probe(struct i2c_client *cl= ient) =20 tsdata->no_regmap_bulk_read =3D device_property_read_bool(&client->dev, "no-regmap-bulk-read"); + tsdata->last_success =3D jiffies; + tsdata->last_reset =3D jiffies; + mutex_init(&tsdata->io_lock); + INIT_DELAYED_WORK(&tsdata->poll_work, edt_ft5x06_poll_work); =20 /* * Check which sleep modes we can support. Power-off requires the @@ -1341,6 +1470,15 @@ static int edt_ft5x06_ts_probe(struct i2c_client *cl= ient) return error; } =20 + /* + * Registered before the IRQ so it unwinds after the IRQ is freed on + * removal: no edge can re-arm the poll worker once it is cancelled. + */ + error =3D devm_add_action_or_reset(&client->dev, edt_ft5x06_cancel_poll, + tsdata); + if (error) + return error; + irq_flags =3D irq_get_trigger_type(client->irq); if (irq_flags =3D=3D IRQF_TRIGGER_NONE) irq_flags =3D IRQF_TRIGGER_FALLING; @@ -1383,6 +1521,9 @@ static int edt_ft5x06_ts_suspend(struct device *dev) struct gpio_desc *reset_gpio =3D tsdata->reset_gpio; int ret; =20 + /* stop the poll worker so it cannot touch i2c after power-down */ + cancel_delayed_work_sync(&tsdata->poll_work); + if (device_may_wakeup(dev)) return 0; =20 --=20 2.55.0