[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250308-synaptics-rmi4-v3-7-215d3e7289a2@ixit.cz>
Date: Sat, 08 Mar 2025 15:08:43 +0100
From: David Heidelberg via B4 Relay <devnull+david.ixit.cz@...nel.org>
To: Dmitry Torokhov <dmitry.torokhov@...il.com>,
Rob Herring <robh@...nel.org>, Krzysztof Kozlowski <krzk+dt@...nel.org>,
Conor Dooley <conor+dt@...nel.org>, "Jason A. Donenfeld" <Jason@...c4.com>,
Matthias Schiffer <matthias.schiffer@...tq-group.com>,
Vincent Huang <vincent.huang@...synaptics.com>
Cc: linux-input@...r.kernel.org, devicetree@...r.kernel.org,
linux-kernel@...r.kernel.org, phone-devel@...r.kernel.org,
~postmarketos/upstreaming@...ts.sr.ht, methanal <baclofen@...a.io>,
Caleb Connolly <caleb.connolly@...aro.org>,
David Heidelberg <david@...t.cz>
Subject: [PATCH v3 7/7] Input: synaptics-rmi4 - support fallback values for
PDT descriptor bytes
From: methanal <baclofen@...a.io>
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)
Introduce a new devicetree property `syna,pdt-desc` which can be used to
provide platform-specific fallback values for users with a replacement
display with an aftermarket touch IC.
Signed-off-by: methanal <baclofen@...a.io>
[codeflow adjustments, checkpatch fixes, wording]
Signed-off-by: Caleb Connolly <caleb.connolly@...aro.org>
Signed-off-by: David Heidelberg <david@...t.cz>
---
drivers/input/rmi4/rmi_driver.c | 73 ++++++++++++++++++++++++++++++++++++-----
drivers/input/rmi4/rmi_driver.h | 2 ++
include/linux/rmi.h | 3 ++
3 files changed, 70 insertions(+), 8 deletions(-)
diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index 2790f00a58bc66c04656d0cd1b4afe9f843ee093..f233c0b1f8e6a936089fd81344c46b6741d3d82d 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -461,9 +461,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;
@@ -474,6 +475,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 DT */
+ 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];
@@ -551,7 +567,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;
@@ -1028,9 +1044,11 @@ 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 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,
@@ -1038,11 +1056,50 @@ 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 platform
+ * may have provided backup PDT entries in the device tree.
+ */
+
+ 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;
+
+ pdata->pdt_fallback_size = of_property_count_u8_elems(dev->of_node,
+ "syna,pdt-fallback-desc");
+
+ /* The rmi4 driver would fail later anyway, so just error out now. */
+ if (pdata->pdt_fallback_size == -EINVAL) {
+ dev_err(dev, "First PDT entry is empty and no backup values provided\n");
+ return -EINVAL;
+ }
+
+ if (pdata->pdt_fallback_size < 0) {
+ dev_err(dev, "syna,pdt-fallback-desc property was not specified properly: %d\n",
+ pdata->pdt_fallback_size);
+ return pdata->pdt_fallback_size;
+ }
+
+ pdata->pdt_fallback_desc = devm_kzalloc(dev, pdata->pdt_fallback_size, GFP_KERNEL);
+
+ retval = of_property_read_u8_array(dev->of_node, "syna,pdt-fallback-desc",
+ pdata->pdt_fallback_desc, pdata->pdt_fallback_size);
+ if (retval < 0)
+ return retval;
+
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;
}
@@ -1163,7 +1220,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 0ecbd19cefffe00ce7c8001db6479a2e213ac466..67a04133a4d85c56d80d0eafee65797319c75c54 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)
diff --git a/include/linux/rmi.h b/include/linux/rmi.h
index ab7eea01ab4274bfc9efcefcdb0cced6ec34966f..974597960b5ee61b670ab55a78c317710022d7cc 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;
+ u8 *pdt_fallback_desc;
+ int pdt_fallback_size;
+
struct rmi_device_platform_data_spi spi_data;
/* function handler pdata */
--
2.47.2
Powered by blists - more mailing lists