* [PATCH v8 1/7] dt-bindings: input: syna,rmi4: Document syna,rmi4-s3706b
2026-03-24 19:40 [PATCH v8 0/7] Input: synaptics-rmi4 - add quirks for third party touchscreen controllers David Heidelberg via B4 Relay
@ 2026-03-24 19:40 ` David Heidelberg via B4 Relay
2026-03-24 19:42 ` Dmitry Torokhov
2026-03-24 19:40 ` [PATCH v8 2/7] Input: synaptics-rmi4 - handle duplicate/unknown PDT entries David Heidelberg via B4 Relay
` (5 subsequent siblings)
6 siblings, 1 reply; 10+ messages in thread
From: David Heidelberg via B4 Relay @ 2026-03-24 19:40 UTC (permalink / raw)
To: Kaustabh Chakraborty, Dmitry Torokhov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jason A. Donenfeld,
Matthias Schiffer, Vincent Huang, Casey Connolly
Cc: David Heidelberg, linux-input, devicetree, linux-kernel,
phone-devel, Krzysztof Kozlowski
From: David Heidelberg <david@ixit.cz>
Mostly irrelevant for authentic Synaptics touchscreens, but very important
for applying workarounds to cheap TS knockoffs.
These knockoffs work well with the downstream driver, and since the user
has no way to distinguish them, later in this patch set, we introduce
workarounds to ensure they function as well as possible.
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
Documentation/devicetree/bindings/input/syna,rmi4.yaml | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/input/syna,rmi4.yaml b/Documentation/devicetree/bindings/input/syna,rmi4.yaml
index 8685ef4481f4a..fb4804ac3544d 100644
--- a/Documentation/devicetree/bindings/input/syna,rmi4.yaml
+++ b/Documentation/devicetree/bindings/input/syna,rmi4.yaml
@@ -18,9 +18,14 @@ description: |
properties:
compatible:
- enum:
- - syna,rmi4-i2c
- - syna,rmi4-spi
+ oneOf:
+ - enum:
+ - syna,rmi4-i2c
+ - syna,rmi4-spi
+ - items:
+ - enum:
+ - syna,rmi4-s3706b # OnePlus 6/6T
+ - const: syna,rmi4-i2c
reg:
maxItems: 1
--
2.53.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [PATCH v8 1/7] dt-bindings: input: syna,rmi4: Document syna,rmi4-s3706b
2026-03-24 19:40 ` [PATCH v8 1/7] dt-bindings: input: syna,rmi4: Document syna,rmi4-s3706b David Heidelberg via B4 Relay
@ 2026-03-24 19:42 ` Dmitry Torokhov
2026-03-25 11:33 ` David Heidelberg
0 siblings, 1 reply; 10+ messages in thread
From: Dmitry Torokhov @ 2026-03-24 19:42 UTC (permalink / raw)
To: david
Cc: Kaustabh Chakraborty, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jason A. Donenfeld, Matthias Schiffer,
Vincent Huang, Casey Connolly, linux-input, devicetree,
linux-kernel, phone-devel, Krzysztof Kozlowski
On Tue, Mar 24, 2026 at 08:40:34PM +0100, David Heidelberg via B4 Relay wrote:
> From: David Heidelberg <david@ixit.cz>
>
> Mostly irrelevant for authentic Synaptics touchscreens, but very important
> for applying workarounds to cheap TS knockoffs.
>
> These knockoffs work well with the downstream driver, and since the user
> has no way to distinguish them, later in this patch set, we introduce
> workarounds to ensure they function as well as possible.
>
> Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> Signed-off-by: David Heidelberg <david@ixit.cz>
> ---
> Documentation/devicetree/bindings/input/syna,rmi4.yaml | 11 ++++++++---
> 1 file changed, 8 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/input/syna,rmi4.yaml b/Documentation/devicetree/bindings/input/syna,rmi4.yaml
> index 8685ef4481f4a..fb4804ac3544d 100644
> --- a/Documentation/devicetree/bindings/input/syna,rmi4.yaml
> +++ b/Documentation/devicetree/bindings/input/syna,rmi4.yaml
> @@ -18,9 +18,14 @@ description: |
>
> properties:
> compatible:
> - enum:
> - - syna,rmi4-i2c
> - - syna,rmi4-spi
> + oneOf:
> + - enum:
> + - syna,rmi4-i2c
> + - syna,rmi4-spi
> + - items:
> + - enum:
> + - syna,rmi4-s3706b # OnePlus 6/6T
I thought that all the workarounds will be keyed off this new
compatible, but I do not see that. What am I missing?
Thanks.
--
Dmitry
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v8 1/7] dt-bindings: input: syna,rmi4: Document syna,rmi4-s3706b
2026-03-24 19:42 ` Dmitry Torokhov
@ 2026-03-25 11:33 ` David Heidelberg
0 siblings, 0 replies; 10+ messages in thread
From: David Heidelberg @ 2026-03-25 11:33 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Kaustabh Chakraborty, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Jason A. Donenfeld, Matthias Schiffer,
Vincent Huang, Casey Connolly, linux-input, devicetree,
linux-kernel, phone-devel, Krzysztof Kozlowski
On 24/03/2026 20:42, Dmitry Torokhov wrote:
> On Tue, Mar 24, 2026 at 08:40:34PM +0100, David Heidelberg via B4 Relay wrote:
>> From: David Heidelberg <david@ixit.cz>
>>
>> Mostly irrelevant for authentic Synaptics touchscreens, but very important
>> for applying workarounds to cheap TS knockoffs.
>>
>> These knockoffs work well with the downstream driver, and since the user
>> has no way to distinguish them, later in this patch set, we introduce
>> workarounds to ensure they function as well as possible.
>>
>> Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
>> Signed-off-by: David Heidelberg <david@ixit.cz>
>> ---
>> Documentation/devicetree/bindings/input/syna,rmi4.yaml | 11 ++++++++---
>> 1 file changed, 8 insertions(+), 3 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/input/syna,rmi4.yaml b/Documentation/devicetree/bindings/input/syna,rmi4.yaml
>> index 8685ef4481f4a..fb4804ac3544d 100644
>> --- a/Documentation/devicetree/bindings/input/syna,rmi4.yaml
>> +++ b/Documentation/devicetree/bindings/input/syna,rmi4.yaml
>> @@ -18,9 +18,14 @@ description: |
>>
>> properties:
>> compatible:
>> - enum:
>> - - syna,rmi4-i2c
>> - - syna,rmi4-spi
>> + oneOf:
>> + - enum:
>> + - syna,rmi4-i2c
>> + - syna,rmi4-spi
>> + - items:
>> + - enum:
>> + - syna,rmi4-s3706b # OnePlus 6/6T
>
> I thought that all the workarounds will be keyed off this new
> compatible, but I do not see that. What am I missing?
The compatible is used for sequence in the
Input: synaptics-rmi4 - support fallback values for PDT descriptor bytes
where it is used to provide values missing for OP6 (and possible others in the
future, when added).
From my understanding the series, only two patches (1st and last) are specific
for the OP6, rest will likely benefit various TS not implementing full Synaptics
set. All measures apply only when touchscreen reports something wrong.
David
>
> Thanks.
>
--
David Heidelberg
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v8 2/7] Input: synaptics-rmi4 - handle duplicate/unknown PDT entries
2026-03-24 19:40 [PATCH v8 0/7] Input: synaptics-rmi4 - add quirks for third party touchscreen controllers David Heidelberg via B4 Relay
2026-03-24 19:40 ` [PATCH v8 1/7] dt-bindings: input: syna,rmi4: Document syna,rmi4-s3706b David Heidelberg via B4 Relay
@ 2026-03-24 19:40 ` David Heidelberg via B4 Relay
2026-03-24 19:40 ` [PATCH v8 3/7] Input: synaptics-rmi4 - f12: use hardcoded values for aftermarket touch ICs David Heidelberg via B4 Relay
` (4 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: David Heidelberg via B4 Relay @ 2026-03-24 19:40 UTC (permalink / raw)
To: Kaustabh Chakraborty, Dmitry Torokhov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jason A. Donenfeld,
Matthias Schiffer, Vincent Huang, Casey Connolly
Cc: David Heidelberg, linux-input, devicetree, linux-kernel,
phone-devel
From: Casey Connolly <casey.connolly@linaro.org>
Some third party rmi4-compatible ICs don't expose their PDT entries
very well. Add a few checks to skip duplicate entries as well as entries
for unsupported functions.
This is required to support some phones with third party displays.
Validated on a stock OnePlus 6T (original parts):
manufacturer: Synaptics, product: S3706B, fw id: 2852315
Co-developed-by: Kaustabh Chakraborty <kauschluss@disroot.org>
Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
Signed-off-by: Casey Connolly <casey.connolly@linaro.org>
Co-developed-by: David Heidelberg <david@ixit.cz>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
drivers/input/rmi4/rmi_driver.c | 41 +++++++++++++++++++++++++++++++++++------
drivers/input/rmi4/rmi_driver.h | 7 +++++++
2 files changed, 42 insertions(+), 6 deletions(-)
diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index ccd9338a44dbe..dea04cf076eb4 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -494,12 +494,38 @@ static void rmi_driver_copy_pdt_to_fd(const struct pdt_entry *pdt,
fd->function_version = pdt->function_version;
}
+static bool rmi_pdt_entry_is_valid(struct rmi_device *rmi_dev,
+ struct pdt_scan_state *state, u8 fn)
+{
+ switch (fn) {
+ case 0x01:
+ case 0x03:
+ case 0x11:
+ case 0x12:
+ case 0x30:
+ case 0x34:
+ case 0x3a:
+ case 0x54:
+ case 0x55:
+ if (state->pdts[fn] == true)
+ return false;
+ break;
+ default:
+ rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev,
+ "PDT has unknown function number %#02x\n", fn);
+ return false;
+ }
+
+ state->pdts[fn] = true;
+ return true;
+}
+
#define RMI_SCAN_CONTINUE 0
#define RMI_SCAN_DONE 1
static int rmi_scan_pdt_page(struct rmi_device *rmi_dev,
int page,
- int *empty_pages,
+ struct pdt_scan_state *state,
void *ctx,
int (*callback)(struct rmi_device *rmi_dev,
void *ctx,
@@ -522,6 +548,9 @@ static int rmi_scan_pdt_page(struct rmi_device *rmi_dev,
if (RMI4_END_OF_PDT(pdt_entry.function_number))
break;
+ if (!rmi_pdt_entry_is_valid(rmi_dev, state, pdt_entry.function_number))
+ continue;
+
retval = callback(rmi_dev, ctx, &pdt_entry);
if (retval != RMI_SCAN_CONTINUE)
return retval;
@@ -532,11 +561,11 @@ static int rmi_scan_pdt_page(struct rmi_device *rmi_dev,
* or more is found, stop scanning.
*/
if (addr == pdt_start)
- ++*empty_pages;
+ ++state->empty_pages;
else
- *empty_pages = 0;
+ state->empty_pages = 0;
- return (data->bootloader_mode || *empty_pages >= 2) ?
+ return (data->bootloader_mode || state->empty_pages >= 2) ?
RMI_SCAN_DONE : RMI_SCAN_CONTINUE;
}
@@ -545,11 +574,11 @@ int rmi_scan_pdt(struct rmi_device *rmi_dev, void *ctx,
void *ctx, const struct pdt_entry *entry))
{
int page;
- int empty_pages = 0;
+ struct pdt_scan_state state = {0, 0, {0}};
int retval = RMI_SCAN_DONE;
for (page = 0; page <= RMI4_MAX_PAGE; page++) {
- retval = rmi_scan_pdt_page(rmi_dev, page, &empty_pages,
+ retval = rmi_scan_pdt_page(rmi_dev, page, &state,
ctx, callback);
if (retval != RMI_SCAN_CONTINUE)
break;
diff --git a/drivers/input/rmi4/rmi_driver.h b/drivers/input/rmi4/rmi_driver.h
index e84495caab151..2c47373c3d177 100644
--- a/drivers/input/rmi4/rmi_driver.h
+++ b/drivers/input/rmi4/rmi_driver.h
@@ -46,6 +46,13 @@ struct pdt_entry {
u8 function_number;
};
+#define RMI_PDT_MAX 0x55
+
+struct pdt_scan_state {
+ u8 empty_pages;
+ bool pdts[RMI_PDT_MAX + 1];
+};
+
#define RMI_REG_DESC_PRESENSE_BITS (32 * BITS_PER_BYTE)
#define RMI_REG_DESC_SUBPACKET_BITS (37 * BITS_PER_BYTE)
--
2.53.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v8 3/7] Input: synaptics-rmi4 - f12: use hardcoded values for aftermarket touch ICs
2026-03-24 19:40 [PATCH v8 0/7] Input: synaptics-rmi4 - add quirks for third party touchscreen controllers David Heidelberg via B4 Relay
2026-03-24 19:40 ` [PATCH v8 1/7] dt-bindings: input: syna,rmi4: Document syna,rmi4-s3706b David Heidelberg via B4 Relay
2026-03-24 19:40 ` [PATCH v8 2/7] Input: synaptics-rmi4 - handle duplicate/unknown PDT entries David Heidelberg via B4 Relay
@ 2026-03-24 19:40 ` David Heidelberg via B4 Relay
2026-03-24 19:40 ` [PATCH v8 4/7] Input: synaptics-rmi4 - f55: handle zero electrode count David Heidelberg via B4 Relay
` (3 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: David Heidelberg via B4 Relay @ 2026-03-24 19:40 UTC (permalink / raw)
To: Kaustabh Chakraborty, Dmitry Torokhov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jason A. Donenfeld,
Matthias Schiffer, Vincent Huang, Casey Connolly
Cc: David Heidelberg, linux-input, devicetree, linux-kernel,
phone-devel
From: Kaustabh Chakraborty <kauschluss@disroot.org>
Some replacement displays include third-party touch ICs which are
devoid of register descriptors. Create a fake data register descriptor
for such ICs and provide hardcoded default values.
It isn't possible to reliably determine if the touch IC is original or
not, so these fallback values are offered as an alternative to the error
path when register descriptors aren't available.
Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
[changes for readability / codeflow, checkpatch fixes]
Signed-off-by: Casey Connolly <casey.connolly@linaro.org>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
drivers/input/rmi4/rmi_f12.c | 117 +++++++++++++++++++++++++++++++++----------
1 file changed, 91 insertions(+), 26 deletions(-)
diff --git a/drivers/input/rmi4/rmi_f12.c b/drivers/input/rmi4/rmi_f12.c
index 8246fe77114bb..1a103cc5f2235 100644
--- a/drivers/input/rmi4/rmi_f12.c
+++ b/drivers/input/rmi4/rmi_f12.c
@@ -218,6 +218,41 @@ static void rmi_f12_process_objects(struct f12_data *f12, u8 *data1, int size)
rmi_2d_sensor_abs_report(sensor, &sensor->objs[i], i);
}
+static void rmi_f12_set_hardcoded_desc(struct rmi_function *fn, struct f12_data *f12)
+{
+ struct rmi_2d_sensor *sensor = &f12->sensor;
+ struct rmi_register_desc_item *reg_desc;
+
+ /* We have no f12->data_reg_desc, so the pkt_size is 0, override it with
+ * a somewhat sensible default (this corresponds to 10 fingers).
+ */
+ sensor->pkt_size = 88;
+
+ /*
+ * There are no register descriptors to get these values from.
+ * We set them to high values to either be overwritten by the clip
+ * properties from devicetree, or to just not get in the way.
+ */
+ sensor->max_x = 65535;
+ sensor->max_y = 65535;
+
+ /*
+ * Create the Data1 register descriptor so that touch events
+ * can work properly.
+ */
+ reg_desc = devm_kcalloc(&fn->dev, 1,
+ sizeof(struct rmi_register_desc_item), GFP_KERNEL);
+ reg_desc->reg = 1;
+ reg_desc->reg_size = 80;
+ reg_desc->num_subpackets = 10;
+
+ f12->data1 = reg_desc;
+ f12->data1_offset = 0;
+ sensor->nbr_fingers = reg_desc->num_subpackets;
+ sensor->report_abs = 1;
+ sensor->attn_size += reg_desc->reg_size;
+}
+
static irqreturn_t rmi_f12_attention(int irq, void *ctx)
{
int retval;
@@ -338,6 +373,40 @@ static int rmi_f12_config(struct rmi_function *fn)
return 0;
}
+static int rmi_f12_sensor_init(struct rmi_function *fn, struct f12_data *f12)
+{
+ struct rmi_2d_sensor *sensor = &f12->sensor;
+
+ sensor->fn = fn;
+ f12->data_addr = fn->fd.data_base_addr;
+
+ /* On quirky devices that don't have a data_reg_desc we hardcode the packet
+ * in rmi_f12_set_hardcoded_desc(). Make sure not to set it to 0 here.
+ */
+ if (!sensor->pkt_size)
+ sensor->pkt_size = rmi_register_desc_calc_size(&f12->data_reg_desc);
+
+ sensor->axis_align =
+ f12->sensor_pdata.axis_align;
+
+ sensor->x_mm = f12->sensor_pdata.x_mm;
+ sensor->y_mm = f12->sensor_pdata.y_mm;
+ sensor->dribble = f12->sensor_pdata.dribble;
+
+ if (sensor->sensor_type == rmi_sensor_default)
+ sensor->sensor_type =
+ f12->sensor_pdata.sensor_type;
+
+ rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: data packet size: %d\n", __func__,
+ sensor->pkt_size);
+
+ sensor->data_pkt = devm_kzalloc(&fn->dev, sensor->pkt_size, GFP_KERNEL);
+ if (!sensor->data_pkt)
+ return -ENOMEM;
+
+ return 0;
+}
+
static int rmi_f12_probe(struct rmi_function *fn)
{
struct f12_data *f12;
@@ -351,6 +420,7 @@ static int rmi_f12_probe(struct rmi_function *fn)
struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
u16 data_offset = 0;
int mask_size;
+ bool hardcoded_desc_quirk = false;
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s\n", __func__);
@@ -365,9 +435,9 @@ static int rmi_f12_probe(struct rmi_function *fn)
++query_addr;
if (!(buf & BIT(0))) {
- dev_err(&fn->dev,
- "Behavior of F12 without register descriptors is undefined.\n");
- return -ENODEV;
+ rmi_dbg(RMI_DEBUG_FN, &fn->dev,
+ "No register descriptors defined for F12, using fallback\n");
+ hardcoded_desc_quirk = true;
}
f12 = devm_kzalloc(&fn->dev, sizeof(struct f12_data) + mask_size * 2,
@@ -375,6 +445,8 @@ static int rmi_f12_probe(struct rmi_function *fn)
if (!f12)
return -ENOMEM;
+ dev_set_drvdata(&fn->dev, f12);
+
f12->abs_mask = (unsigned long *)((char *)f12
+ sizeof(struct f12_data));
f12->rel_mask = (unsigned long *)((char *)f12
@@ -393,6 +465,18 @@ static int rmi_f12_probe(struct rmi_function *fn)
f12->sensor_pdata = pdata->sensor_pdata;
}
+ sensor = &f12->sensor;
+
+ if (hardcoded_desc_quirk) {
+ rmi_f12_set_hardcoded_desc(fn, f12);
+
+ ret = rmi_f12_sensor_init(fn, f12);
+ if (ret)
+ return ret;
+
+ goto skip_register_desc;
+ }
+
ret = rmi_read_register_desc(rmi_dev, query_addr,
&f12->query_reg_desc);
if (ret) {
@@ -423,29 +507,9 @@ static int rmi_f12_probe(struct rmi_function *fn)
}
query_addr += 3;
- sensor = &f12->sensor;
- sensor->fn = fn;
- f12->data_addr = fn->fd.data_base_addr;
- sensor->pkt_size = rmi_register_desc_calc_size(&f12->data_reg_desc);
-
- sensor->axis_align =
- f12->sensor_pdata.axis_align;
-
- sensor->x_mm = f12->sensor_pdata.x_mm;
- sensor->y_mm = f12->sensor_pdata.y_mm;
- sensor->dribble = f12->sensor_pdata.dribble;
-
- if (sensor->sensor_type == rmi_sensor_default)
- sensor->sensor_type =
- f12->sensor_pdata.sensor_type;
-
- rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: data packet size: %d\n", __func__,
- sensor->pkt_size);
- sensor->data_pkt = devm_kzalloc(&fn->dev, sensor->pkt_size, GFP_KERNEL);
- if (!sensor->data_pkt)
- return -ENOMEM;
-
- dev_set_drvdata(&fn->dev, f12);
+ ret = rmi_f12_sensor_init(fn, f12);
+ if (ret)
+ return ret;
ret = rmi_f12_read_sensor_tuning(f12);
if (ret)
@@ -543,6 +607,7 @@ static int rmi_f12_probe(struct rmi_function *fn)
data_offset += item->reg_size;
}
+skip_register_desc:
/* allocate the in-kernel tracking buffers */
sensor->tracking_pos = devm_kcalloc(&fn->dev,
sensor->nbr_fingers, sizeof(struct input_mt_pos),
--
2.53.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v8 4/7] Input: synaptics-rmi4 - f55: handle zero electrode count
2026-03-24 19:40 [PATCH v8 0/7] Input: synaptics-rmi4 - add quirks for third party touchscreen controllers David Heidelberg via B4 Relay
` (2 preceding siblings ...)
2026-03-24 19:40 ` [PATCH v8 3/7] Input: synaptics-rmi4 - f12: use hardcoded values for aftermarket touch ICs David Heidelberg via B4 Relay
@ 2026-03-24 19:40 ` David Heidelberg via B4 Relay
2026-03-24 19:40 ` [PATCH v8 5/7] Input: synaptics-rmi4 - don't do unaligned reads in IRQ context David Heidelberg via B4 Relay
` (2 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: David Heidelberg via B4 Relay @ 2026-03-24 19:40 UTC (permalink / raw)
To: Kaustabh Chakraborty, Dmitry Torokhov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jason A. Donenfeld,
Matthias Schiffer, Vincent Huang, Casey Connolly
Cc: David Heidelberg, linux-input, devicetree, linux-kernel,
phone-devel
From: Kaustabh Chakraborty <kauschluss@disroot.org>
Some third party ICs claim to support f55 but report an electrode count
of 0. Catch this and bail out early so that we don't confuse the i2c bus
with 0 sized reads.
Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
[simplify code, adjust wording]
Signed-off-by: Casey Connolly <casey.connolly@linaro.org>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
drivers/input/rmi4/rmi_f55.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/input/rmi4/rmi_f55.c b/drivers/input/rmi4/rmi_f55.c
index 488adaca4dd00..776c915b82e72 100644
--- a/drivers/input/rmi4/rmi_f55.c
+++ b/drivers/input/rmi4/rmi_f55.c
@@ -52,6 +52,11 @@ static int rmi_f55_detect(struct rmi_function *fn)
f55->num_rx_electrodes = f55->qry[F55_NUM_RX_OFFSET];
f55->num_tx_electrodes = f55->qry[F55_NUM_TX_OFFSET];
+ if (!f55->num_rx_electrodes || !f55->num_tx_electrodes) {
+ dev_err(&fn->dev, "%s: F55 query returned no electrodes, giving up\n",
+ __func__);
+ return -EINVAL;
+ }
f55->cfg_num_rx_electrodes = f55->num_rx_electrodes;
f55->cfg_num_tx_electrodes = f55->num_rx_electrodes;
--
2.53.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v8 5/7] Input: synaptics-rmi4 - don't do unaligned reads in IRQ context
2026-03-24 19:40 [PATCH v8 0/7] Input: synaptics-rmi4 - add quirks for third party touchscreen controllers David Heidelberg via B4 Relay
` (3 preceding siblings ...)
2026-03-24 19:40 ` [PATCH v8 4/7] Input: synaptics-rmi4 - f55: handle zero electrode count David Heidelberg via B4 Relay
@ 2026-03-24 19:40 ` David Heidelberg via B4 Relay
2026-03-24 19:40 ` [PATCH v8 6/7] Input: synaptics-rmi4 - read product ID on aftermarket touch ICs David Heidelberg via B4 Relay
2026-03-24 19:40 ` [PATCH v8 7/7] Input: synaptics-rmi4 - support fallback values for PDT descriptor bytes David Heidelberg via B4 Relay
6 siblings, 0 replies; 10+ messages in thread
From: David Heidelberg via B4 Relay @ 2026-03-24 19:40 UTC (permalink / raw)
To: Kaustabh Chakraborty, Dmitry Torokhov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jason A. Donenfeld,
Matthias Schiffer, Vincent Huang, Casey Connolly
Cc: David Heidelberg, linux-input, devicetree, linux-kernel,
phone-devel
From: Kaustabh Chakraborty <kauschluss@disroot.org>
Some replacement displays include third-party touch ICs which incur a
significant penalty (1-2 seconds) when doing certain unaligned reads.
This is enough to break functionality when it happens in the hot path,
so adjust the interrupt handler to not read from an unaligned address.
Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
Signed-off-by: Casey Connolly <casey.connolly@linaro.org>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
drivers/input/rmi4/rmi_driver.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index dea04cf076eb4..fc84799c36e04 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -137,9 +137,14 @@ static int rmi_process_interrupt_requests(struct rmi_device *rmi_dev)
return 0;
if (!data->attn_data.data) {
+ /*
+ * Read the device status register as well and ignore it.
+ * Some aftermarket ICs have issues with interrupt requests
+ * otherwise.
+ */
error = rmi_read_block(rmi_dev,
- data->f01_container->fd.data_base_addr + 1,
- data->irq_status, data->num_of_irq_regs);
+ data->f01_container->fd.data_base_addr,
+ (u8 *)data->irq_status - 1, data->num_of_irq_regs + 1);
if (error < 0) {
dev_err(dev, "Failed to read irqs, code=%d\n", error);
return error;
@@ -1078,16 +1083,17 @@ int rmi_probe_interrupts(struct rmi_driver_data *data)
data->num_of_irq_regs = (data->irq_count + 7) / 8;
size = BITS_TO_LONGS(data->irq_count) * sizeof(unsigned long);
- data->irq_memory = devm_kcalloc(dev, size, 4, GFP_KERNEL);
+ data->irq_memory = devm_kzalloc(dev, size * 4 + 1, GFP_KERNEL);
if (!data->irq_memory) {
dev_err(dev, "Failed to allocate memory for irq masks.\n");
return -ENOMEM;
}
- data->irq_status = data->irq_memory + size * 0;
- data->fn_irq_bits = data->irq_memory + size * 1;
- data->current_irq_mask = data->irq_memory + size * 2;
- data->new_irq_mask = data->irq_memory + size * 3;
+ /* The first byte is reserved for the device status register */
+ data->irq_status = data->irq_memory + size * 0 + 1;
+ data->fn_irq_bits = data->irq_memory + size * 1 + 1;
+ data->current_irq_mask = data->irq_memory + size * 2 + 1;
+ data->new_irq_mask = data->irq_memory + size * 3 + 1;
return retval;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v8 6/7] Input: synaptics-rmi4 - read product ID on aftermarket touch ICs
2026-03-24 19:40 [PATCH v8 0/7] Input: synaptics-rmi4 - add quirks for third party touchscreen controllers David Heidelberg via B4 Relay
` (4 preceding siblings ...)
2026-03-24 19:40 ` [PATCH v8 5/7] Input: synaptics-rmi4 - don't do unaligned reads in IRQ context David Heidelberg via B4 Relay
@ 2026-03-24 19:40 ` David Heidelberg via B4 Relay
2026-03-24 19:40 ` [PATCH v8 7/7] Input: synaptics-rmi4 - support fallback values for PDT descriptor bytes David Heidelberg via B4 Relay
6 siblings, 0 replies; 10+ messages in thread
From: David Heidelberg via B4 Relay @ 2026-03-24 19:40 UTC (permalink / raw)
To: Kaustabh Chakraborty, Dmitry Torokhov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jason A. Donenfeld,
Matthias Schiffer, Vincent Huang, Casey Connolly
Cc: David Heidelberg, linux-input, devicetree, linux-kernel,
phone-devel
From: Kaustabh Chakraborty <kauschluss@disroot.org>
Some replacement displays include third-party touch ICs which do not
report the product ID correctly unless we read directly from the
product ID register. Add a check and a fallback read to handle this.
Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
Signed-off-by: Casey Connolly <casey.connolly@linaro.org>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
drivers/input/rmi4/rmi_f01.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/drivers/input/rmi4/rmi_f01.c b/drivers/input/rmi4/rmi_f01.c
index 47be64284b25e..2278e9b6a9207 100644
--- a/drivers/input/rmi4/rmi_f01.c
+++ b/drivers/input/rmi4/rmi_f01.c
@@ -250,6 +250,20 @@ static int rmi_f01_read_properties(struct rmi_device *rmi_dev,
}
}
+ /*
+ * Some aftermarket ICs put garbage into the product id field unless
+ * we read directly from the product id register.
+ */
+ if (props->product_id[0] < 0x20) {
+ ret = rmi_read_block(rmi_dev, query_base_addr + 11,
+ props->product_id, RMI_PRODUCT_ID_LENGTH);
+ if (ret) {
+ dev_err(&rmi_dev->dev,
+ "Failed to read product id: %d\n", ret);
+ return ret;
+ }
+ }
+
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v8 7/7] Input: synaptics-rmi4 - support fallback values for PDT descriptor bytes
2026-03-24 19:40 [PATCH v8 0/7] Input: synaptics-rmi4 - add quirks for third party touchscreen controllers David Heidelberg via B4 Relay
` (5 preceding siblings ...)
2026-03-24 19:40 ` [PATCH v8 6/7] Input: synaptics-rmi4 - read product ID on aftermarket touch ICs David Heidelberg via B4 Relay
@ 2026-03-24 19:40 ` David Heidelberg via B4 Relay
6 siblings, 0 replies; 10+ messages in thread
From: David Heidelberg via B4 Relay @ 2026-03-24 19:40 UTC (permalink / raw)
To: Kaustabh Chakraborty, Dmitry Torokhov, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jason A. Donenfeld,
Matthias Schiffer, Vincent Huang, Casey Connolly
Cc: David Heidelberg, linux-input, devicetree, linux-kernel,
phone-devel
From: Kaustabh Chakraborty <kauschluss@disroot.org>
Some replacement displays include third-party touch ICs which do not
expose the function number and the interrupt status in its PDT entries.
OnePlus 6 (original touch IC)
rmi4_i2c 12-0020: read 6 bytes at 0x00e3: 0 (2b 22 0d 06 01 01)
OnePlus 6 (aftermarket touch IC)
rmi4_i2c 12-0020: read 6 bytes at 0x00e3: 0 (2c 23 0d 06 00 00)
Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
[codeflow adjustments, checkpatch fixes, wording]
Signed-off-by: Casey Connolly <casey.connolly@linaro.org>
Co-developed-by: David Heidelberg <david@ixit.cz>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
drivers/input/rmi4/rmi_driver.c | 63 +++++++++++++++++++++++++++++++++++------
drivers/input/rmi4/rmi_driver.h | 3 ++
include/linux/rmi.h | 3 ++
3 files changed, 61 insertions(+), 8 deletions(-)
diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index fc84799c36e04..bb1db5bbb3abb 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -462,9 +462,10 @@ static int rmi_driver_reset_handler(struct rmi_device *rmi_dev)
return 0;
}
-static int rmi_read_pdt_entry(struct rmi_device *rmi_dev,
- struct pdt_entry *entry, u16 pdt_address)
+static int rmi_read_pdt_entry(struct rmi_device *rmi_dev, struct pdt_entry *entry,
+ struct pdt_scan_state *state, u16 pdt_address)
{
+ const struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
u8 buf[RMI_PDT_ENTRY_SIZE];
int error;
@@ -475,6 +476,21 @@ static int rmi_read_pdt_entry(struct rmi_device *rmi_dev,
return error;
}
+ if (pdata->pdt_fallback_size > state->pdt_count * RMI_OF_PDT_DESC_CELLS + 1) {
+ /* Use the description bytes from the driver */
+ buf[5] = pdata->pdt_fallback_desc[state->pdt_count * RMI_OF_PDT_DESC_CELLS];
+ buf[4] = pdata->pdt_fallback_desc[state->pdt_count * RMI_OF_PDT_DESC_CELLS + 1];
+
+ error = rmi_read_block(rmi_dev, pdt_address, buf,
+ RMI_PDT_ENTRY_SIZE - 2);
+ if (error) {
+ dev_err(&rmi_dev->dev,
+ "Read PDT entry at %#06x failed, code: %d.\n",
+ pdt_address, error);
+ return error;
+ }
+ }
+
entry->page_start = pdt_address & RMI4_PAGE_MASK;
entry->query_base_addr = buf[0];
entry->command_base_addr = buf[1];
@@ -522,6 +538,7 @@ static bool rmi_pdt_entry_is_valid(struct rmi_device *rmi_dev,
}
state->pdts[fn] = true;
+ state->pdt_count++;
return true;
}
@@ -546,7 +563,7 @@ static int rmi_scan_pdt_page(struct rmi_device *rmi_dev,
int retval;
for (addr = pdt_start; addr >= pdt_end; addr -= RMI_PDT_ENTRY_SIZE) {
- error = rmi_read_pdt_entry(rmi_dev, &pdt_entry, addr);
+ error = rmi_read_pdt_entry(rmi_dev, &pdt_entry, state, addr);
if (error)
return error;
@@ -1023,9 +1040,13 @@ static int rmi_driver_remove(struct device *dev)
}
#ifdef CONFIG_OF
-static int rmi_driver_of_probe(struct device *dev,
- struct rmi_device_platform_data *pdata)
+static const u8 rmi_s3706_fallback_pdt[] = {34, 41, 01, 01, 12, 01};
+
+static int rmi_driver_of_probe(struct rmi_device *rmi_dev,
+ struct rmi_device_platform_data *pdata)
{
+ struct device *dev = rmi_dev->xport->dev;
+ u8 buf[RMI_PDT_ENTRY_SIZE];
int retval;
retval = rmi_of_property_read_u32(dev, &pdata->reset_delay_ms,
@@ -1033,11 +1054,37 @@ static int rmi_driver_of_probe(struct device *dev,
if (retval)
return retval;
+ /*
+ * In some aftermerket touch ICs, the first PDT entry is empty and
+ * the function number register is 0. If so, the driver
+ * may have provide backup PDT entries.
+ */
+
+ retval = rmi_read_block(rmi_dev, PDT_START_SCAN_LOCATION,
+ buf, RMI_PDT_ENTRY_SIZE);
+ if (retval) {
+ dev_err(dev, "Read PDT entry at %#06x failed, code: %d.\n",
+ PDT_START_SCAN_LOCATION, retval);
+ return retval;
+ }
+
+ if (!RMI4_END_OF_PDT(buf[5]))
+ return 0;
+
+ /* List of known PDT entries per compatible. */
+ if (of_device_is_compatible(dev->of_node, "syna,rmi4-s3706b")) {
+ pdata->pdt_fallback_desc = rmi_s3706_fallback_pdt;
+ pdata->pdt_fallback_size = ARRAY_SIZE(rmi_s3706_fallback_pdt);
+ } else {
+ dev_err(dev, "First PDT entry is empty and no backup values provided.\n");
+ return -EINVAL;
+ }
+
return 0;
}
#else
-static inline int rmi_driver_of_probe(struct device *dev,
- struct rmi_device_platform_data *pdata)
+static inline int rmi_driver_of_probe(struct rmi_device *rmi_dev,
+ struct rmi_device_platform_data *pdata)
{
return -ENODEV;
}
@@ -1158,7 +1205,7 @@ static int rmi_driver_probe(struct device *dev)
pdata = rmi_get_platform_data(rmi_dev);
if (rmi_dev->xport->dev->of_node) {
- retval = rmi_driver_of_probe(rmi_dev->xport->dev, pdata);
+ retval = rmi_driver_of_probe(rmi_dev, pdata);
if (retval)
return retval;
}
diff --git a/drivers/input/rmi4/rmi_driver.h b/drivers/input/rmi4/rmi_driver.h
index 2c47373c3d177..a6a29fde49f35 100644
--- a/drivers/input/rmi4/rmi_driver.h
+++ b/drivers/input/rmi4/rmi_driver.h
@@ -31,6 +31,8 @@
#define RMI_PDT_FUNCTION_VERSION_MASK 0x60
#define RMI_PDT_INT_SOURCE_COUNT_MASK 0x07
+#define RMI_OF_PDT_DESC_CELLS 2
+
#define PDT_START_SCAN_LOCATION 0x00e9
#define PDT_END_SCAN_LOCATION 0x0005
#define RMI4_END_OF_PDT(id) ((id) == 0x00 || (id) == 0xff)
@@ -50,6 +52,7 @@ struct pdt_entry {
struct pdt_scan_state {
u8 empty_pages;
+ u8 pdt_count;
bool pdts[RMI_PDT_MAX + 1];
};
diff --git a/include/linux/rmi.h b/include/linux/rmi.h
index ab7eea01ab427..4ba2cefac8558 100644
--- a/include/linux/rmi.h
+++ b/include/linux/rmi.h
@@ -214,6 +214,9 @@ struct rmi_device_platform_data {
int reset_delay_ms;
int irq;
+ unsigned int pdt_fallback_size;
+ const u8 *pdt_fallback_desc;
+
struct rmi_device_platform_data_spi spi_data;
/* function handler pdata */
--
2.53.0
^ permalink raw reply related [flat|nested] 10+ messages in thread