[PATCH v9 1/5] Input: synaptics-rmi4 - handle duplicate/unknown PDT entries
David Heidelberg via B4 Relay <[email protected]> Fri, 31 Jul 2026 22:34:12 +0200
| Newsgroups | org.kernel.vger.phone-devel,org.kernel.feeds.b4-sent,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-input,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
From: Casey Connolly <[email protected]> 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 <[email protected]> Signed-off-by: Kaustabh Chakraborty <[email protected]> Signed-off-by: Casey Connolly <[email protected]> Co-developed-by: David Heidelberg <[email protected]> Signed-off-by: David Heidelberg <[email protected]> --- 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 5d49a9021c7d0..3edec5ae1f8c9 100644 --- a/drivers/input/rmi4/rmi_driver.c +++ b/drivers/input/rmi4/rmi_driver.c @@ -493,22 +493,48 @@ static void rmi_driver_copy_pdt_to_fd(const struct pdt_entry *pdt, fd->command_base_addr = pdt->command_base_addr + pdt->page_start; fd->control_base_addr = pdt->control_base_addr + pdt->page_start; fd->data_base_addr = pdt->data_base_addr + pdt->page_start; fd->function_number = pdt->function_number; fd->interrupt_source_count = pdt->interrupt_source_count; 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, const struct pdt_entry *entry)) { struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev); struct pdt_entry pdt_entry; u16 page_start = RMI4_PAGE_SIZE * page; @@ -521,44 +547,47 @@ static int rmi_scan_pdt_page(struct rmi_device *rmi_dev, for (addr = pdt_start; addr >= pdt_end; addr -= RMI_PDT_ENTRY_SIZE) { error = rmi_read_pdt_entry(rmi_dev, &pdt_entry, addr); if (error) return error; 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; } /* * Count number of empty PDT pages. If a gap of two pages * 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; } int rmi_scan_pdt(struct rmi_device *rmi_dev, void *ctx, int (*callback)(struct rmi_device *rmi_dev, 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; } return retval < 0 ? retval : 0; } diff --git a/drivers/input/rmi4/rmi_driver.h b/drivers/input/rmi4/rmi_driver.h index abeafb77a4838..6de8faed08917 100644 --- a/drivers/input/rmi4/rmi_driver.h +++ b/drivers/input/rmi4/rmi_driver.h @@ -44,16 +44,23 @@ struct pdt_entry { u8 interrupt_source_count; u8 function_version; u8 function_number; }; #define RMI_REG_DESC_PRESENCE_BITS (32 * BITS_PER_BYTE) #define RMI_REG_DESC_PRESENCE_REGS_MAX (3 + RMI_REG_DESC_PRESENCE_BITS / 8) #define RMI_REG_DESC_SUBPACKET_BITS (37 * BITS_PER_BYTE) +#define RMI_PDT_MAX 0x55 + +struct pdt_scan_state { + u8 empty_pages; + bool pdts[RMI_PDT_MAX + 1]; +}; + /* describes a single packet register */ struct rmi_register_desc_item { u32 reg_size; u16 reg; u16 num_subpackets; DECLARE_BITMAP(subpacket_map, RMI_REG_DESC_SUBPACKET_BITS); }; -- 2.53.0