diff mbox series

[v2,7/7] Input: synaptics-rmi4 - support fallback values for PDT descriptor bytes

Message ID 20230929-caleb-rmi4-quirks-v2-7-b227ac498d88@linaro.org
State New
Headers show
Series Input: synaptics-rmi4: add quirks for third party touchscreen controllers | expand

Commit Message

Caleb Connolly Oct. 15, 2023, 9:11 p.m. UTC
From: methanal <baclofen@tuta.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@tuta.io>
[codeflow adjustments, checkpatch fixes, wording]
Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
---
 drivers/input/rmi4/rmi_driver.c | 67 ++++++++++++++++++++++++++++++++++++++---
 drivers/input/rmi4/rmi_driver.h |  2 ++
 include/linux/rmi.h             |  3 ++
 3 files changed, 67 insertions(+), 5 deletions(-)

Comments

kernel test robot Oct. 18, 2023, 6:14 p.m. UTC | #1
Hi Caleb,

kernel test robot noticed the following build errors:

[auto build test ERROR on linus/master]
[also build test ERROR on v6.6-rc6 next-20231018]
[cannot apply to dtor-input/next dtor-input/for-linus]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Caleb-Connolly/Input-synaptics-rmi4-handle-duplicate-unknown-PDT-entries/20231017-132844
base:   linus/master
patch link:    https://lore.kernel.org/r/20230929-caleb-rmi4-quirks-v2-7-b227ac498d88%40linaro.org
patch subject: [PATCH v2 7/7] Input: synaptics-rmi4 - support fallback values for PDT descriptor bytes
config: x86_64-rhel-8.3 (https://download.01.org/0day-ci/archive/20231019/202310190215.hvnjZ9RG-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231019/202310190215.hvnjZ9RG-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202310190215.hvnjZ9RG-lkp@intel.com/

All errors (new ones prefixed by >>):

   drivers/input/rmi4/rmi_driver.c: In function 'rmi_driver_probe':
>> drivers/input/rmi4/rmi_driver.c:1223:46: error: passing argument 1 of 'rmi_driver_of_probe' from incompatible pointer type [-Werror=incompatible-pointer-types]
    1223 |                 retval = rmi_driver_of_probe(rmi_dev, pdata);
         |                                              ^~~~~~~
         |                                              |
         |                                              struct rmi_device *
   drivers/input/rmi4/rmi_driver.c:1101:54: note: expected 'struct device *' but argument is of type 'struct rmi_device *'
    1101 | static inline int rmi_driver_of_probe(struct device *dev,
         |                                       ~~~~~~~~~~~~~~~^~~
   cc1: some warnings being treated as errors


vim +/rmi_driver_of_probe +1223 drivers/input/rmi4/rmi_driver.c

  1199	
  1200	static int rmi_driver_probe(struct device *dev)
  1201	{
  1202		struct rmi_driver *rmi_driver;
  1203		struct rmi_driver_data *data;
  1204		struct rmi_device_platform_data *pdata;
  1205		struct rmi_device *rmi_dev;
  1206		int retval;
  1207	
  1208		rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Starting probe.\n",
  1209				__func__);
  1210	
  1211		if (!rmi_is_physical_device(dev)) {
  1212			rmi_dbg(RMI_DEBUG_CORE, dev, "Not a physical device.\n");
  1213			return -ENODEV;
  1214		}
  1215	
  1216		rmi_dev = to_rmi_device(dev);
  1217		rmi_driver = to_rmi_driver(dev->driver);
  1218		rmi_dev->driver = rmi_driver;
  1219	
  1220		pdata = rmi_get_platform_data(rmi_dev);
  1221	
  1222		if (rmi_dev->xport->dev->of_node) {
> 1223			retval = rmi_driver_of_probe(rmi_dev, pdata);
  1224			if (retval)
  1225				return retval;
  1226		}
  1227	
  1228		data = devm_kzalloc(dev, sizeof(struct rmi_driver_data), GFP_KERNEL);
  1229		if (!data)
  1230			return -ENOMEM;
  1231	
  1232		INIT_LIST_HEAD(&data->function_list);
  1233		data->rmi_dev = rmi_dev;
  1234		dev_set_drvdata(&rmi_dev->dev, data);
  1235	
  1236		/*
  1237		 * Right before a warm boot, the sensor might be in some unusual state,
  1238		 * such as F54 diagnostics, or F34 bootloader mode after a firmware
  1239		 * or configuration update.  In order to clear the sensor to a known
  1240		 * state and/or apply any updates, we issue a initial reset to clear any
  1241		 * previous settings and force it into normal operation.
  1242		 *
  1243		 * We have to do this before actually building the PDT because
  1244		 * the reflash updates (if any) might cause various registers to move
  1245		 * around.
  1246		 *
  1247		 * For a number of reasons, this initial reset may fail to return
  1248		 * within the specified time, but we'll still be able to bring up the
  1249		 * driver normally after that failure.  This occurs most commonly in
  1250		 * a cold boot situation (where then firmware takes longer to come up
  1251		 * than from a warm boot) and the reset_delay_ms in the platform data
  1252		 * has been set too short to accommodate that.  Since the sensor will
  1253		 * eventually come up and be usable, we don't want to just fail here
  1254		 * and leave the customer's device unusable.  So we warn them, and
  1255		 * continue processing.
  1256		 */
  1257		retval = rmi_scan_pdt(rmi_dev, NULL, rmi_initial_reset);
  1258		if (retval < 0)
  1259			dev_warn(dev, "RMI initial reset failed! Continuing in spite of this.\n");
  1260	
  1261		retval = rmi_read(rmi_dev, PDT_PROPERTIES_LOCATION, &data->pdt_props);
  1262		if (retval < 0) {
  1263			/*
  1264			 * we'll print out a warning and continue since
  1265			 * failure to get the PDT properties is not a cause to fail
  1266			 */
  1267			dev_warn(dev, "Could not read PDT properties from %#06x (code %d). Assuming 0x00.\n",
  1268				 PDT_PROPERTIES_LOCATION, retval);
  1269		}
  1270	
  1271		mutex_init(&data->irq_mutex);
  1272		mutex_init(&data->enabled_mutex);
  1273	
  1274		retval = rmi_probe_interrupts(data);
  1275		if (retval)
  1276			goto err;
  1277	
  1278		if (rmi_dev->xport->input) {
  1279			/*
  1280			 * The transport driver already has an input device.
  1281			 * In some cases it is preferable to reuse the transport
  1282			 * devices input device instead of creating a new one here.
  1283			 * One example is some HID touchpads report "pass-through"
  1284			 * button events are not reported by rmi registers.
  1285			 */
  1286			data->input = rmi_dev->xport->input;
  1287		} else {
  1288			data->input = devm_input_allocate_device(dev);
  1289			if (!data->input) {
  1290				dev_err(dev, "%s: Failed to allocate input device.\n",
  1291					__func__);
  1292				retval = -ENOMEM;
  1293				goto err;
  1294			}
  1295			rmi_driver_set_input_params(rmi_dev, data->input);
  1296			data->input->phys = devm_kasprintf(dev, GFP_KERNEL,
  1297							"%s/input0", dev_name(dev));
  1298		}
  1299	
  1300		retval = rmi_init_functions(data);
  1301		if (retval)
  1302			goto err;
  1303	
  1304		retval = rmi_f34_create_sysfs(rmi_dev);
  1305		if (retval)
  1306			goto err;
  1307	
  1308		if (data->input) {
  1309			rmi_driver_set_input_name(rmi_dev, data->input);
  1310			if (!rmi_dev->xport->input) {
  1311				retval = input_register_device(data->input);
  1312				if (retval) {
  1313					dev_err(dev, "%s: Failed to register input device.\n",
  1314						__func__);
  1315					goto err_destroy_functions;
  1316				}
  1317			}
  1318		}
  1319	
  1320		retval = rmi_irq_init(rmi_dev);
  1321		if (retval < 0)
  1322			goto err_destroy_functions;
  1323	
  1324		if (data->f01_container->dev.driver) {
  1325			/* Driver already bound, so enable ATTN now. */
  1326			retval = rmi_enable_sensor(rmi_dev);
  1327			if (retval)
  1328				goto err_disable_irq;
  1329		}
  1330	
  1331		return 0;
  1332	
  1333	err_disable_irq:
  1334		rmi_disable_irq(rmi_dev, false);
  1335	err_destroy_functions:
  1336		rmi_free_function_list(rmi_dev);
  1337	err:
  1338		return retval;
  1339	}
  1340
kernel test robot Oct. 18, 2023, 10:17 p.m. UTC | #2
Hi Caleb,

kernel test robot noticed the following build errors:

[auto build test ERROR on linus/master]
[also build test ERROR on v6.6-rc6 next-20231018]
[cannot apply to dtor-input/next dtor-input/for-linus]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Caleb-Connolly/Input-synaptics-rmi4-handle-duplicate-unknown-PDT-entries/20231017-132844
base:   linus/master
patch link:    https://lore.kernel.org/r/20230929-caleb-rmi4-quirks-v2-7-b227ac498d88%40linaro.org
patch subject: [PATCH v2 7/7] Input: synaptics-rmi4 - support fallback values for PDT descriptor bytes
config: x86_64-rhel-8.3-rust (https://download.01.org/0day-ci/archive/20231019/202310190640.pxJQCbWc-lkp@intel.com/config)
compiler: clang version 16.0.4 (https://github.com/llvm/llvm-project.git ae42196bc493ffe877a7e3dff8be32035dea4d07)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231019/202310190640.pxJQCbWc-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202310190640.pxJQCbWc-lkp@intel.com/

All errors (new ones prefixed by >>):

>> drivers/input/rmi4/rmi_driver.c:1223:32: error: incompatible pointer types passing 'struct rmi_device *' to parameter of type 'struct device *' [-Werror,-Wincompatible-pointer-types]
                   retval = rmi_driver_of_probe(rmi_dev, pdata);
                                                ^~~~~~~
   drivers/input/rmi4/rmi_driver.c:1101:54: note: passing argument to parameter 'dev' here
   static inline int rmi_driver_of_probe(struct device *dev,
                                                        ^
   1 error generated.


vim +1223 drivers/input/rmi4/rmi_driver.c

  1199	
  1200	static int rmi_driver_probe(struct device *dev)
  1201	{
  1202		struct rmi_driver *rmi_driver;
  1203		struct rmi_driver_data *data;
  1204		struct rmi_device_platform_data *pdata;
  1205		struct rmi_device *rmi_dev;
  1206		int retval;
  1207	
  1208		rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Starting probe.\n",
  1209				__func__);
  1210	
  1211		if (!rmi_is_physical_device(dev)) {
  1212			rmi_dbg(RMI_DEBUG_CORE, dev, "Not a physical device.\n");
  1213			return -ENODEV;
  1214		}
  1215	
  1216		rmi_dev = to_rmi_device(dev);
  1217		rmi_driver = to_rmi_driver(dev->driver);
  1218		rmi_dev->driver = rmi_driver;
  1219	
  1220		pdata = rmi_get_platform_data(rmi_dev);
  1221	
  1222		if (rmi_dev->xport->dev->of_node) {
> 1223			retval = rmi_driver_of_probe(rmi_dev, pdata);
  1224			if (retval)
  1225				return retval;
  1226		}
  1227	
  1228		data = devm_kzalloc(dev, sizeof(struct rmi_driver_data), GFP_KERNEL);
  1229		if (!data)
  1230			return -ENOMEM;
  1231	
  1232		INIT_LIST_HEAD(&data->function_list);
  1233		data->rmi_dev = rmi_dev;
  1234		dev_set_drvdata(&rmi_dev->dev, data);
  1235	
  1236		/*
  1237		 * Right before a warm boot, the sensor might be in some unusual state,
  1238		 * such as F54 diagnostics, or F34 bootloader mode after a firmware
  1239		 * or configuration update.  In order to clear the sensor to a known
  1240		 * state and/or apply any updates, we issue a initial reset to clear any
  1241		 * previous settings and force it into normal operation.
  1242		 *
  1243		 * We have to do this before actually building the PDT because
  1244		 * the reflash updates (if any) might cause various registers to move
  1245		 * around.
  1246		 *
  1247		 * For a number of reasons, this initial reset may fail to return
  1248		 * within the specified time, but we'll still be able to bring up the
  1249		 * driver normally after that failure.  This occurs most commonly in
  1250		 * a cold boot situation (where then firmware takes longer to come up
  1251		 * than from a warm boot) and the reset_delay_ms in the platform data
  1252		 * has been set too short to accommodate that.  Since the sensor will
  1253		 * eventually come up and be usable, we don't want to just fail here
  1254		 * and leave the customer's device unusable.  So we warn them, and
  1255		 * continue processing.
  1256		 */
  1257		retval = rmi_scan_pdt(rmi_dev, NULL, rmi_initial_reset);
  1258		if (retval < 0)
  1259			dev_warn(dev, "RMI initial reset failed! Continuing in spite of this.\n");
  1260	
  1261		retval = rmi_read(rmi_dev, PDT_PROPERTIES_LOCATION, &data->pdt_props);
  1262		if (retval < 0) {
  1263			/*
  1264			 * we'll print out a warning and continue since
  1265			 * failure to get the PDT properties is not a cause to fail
  1266			 */
  1267			dev_warn(dev, "Could not read PDT properties from %#06x (code %d). Assuming 0x00.\n",
  1268				 PDT_PROPERTIES_LOCATION, retval);
  1269		}
  1270	
  1271		mutex_init(&data->irq_mutex);
  1272		mutex_init(&data->enabled_mutex);
  1273	
  1274		retval = rmi_probe_interrupts(data);
  1275		if (retval)
  1276			goto err;
  1277	
  1278		if (rmi_dev->xport->input) {
  1279			/*
  1280			 * The transport driver already has an input device.
  1281			 * In some cases it is preferable to reuse the transport
  1282			 * devices input device instead of creating a new one here.
  1283			 * One example is some HID touchpads report "pass-through"
  1284			 * button events are not reported by rmi registers.
  1285			 */
  1286			data->input = rmi_dev->xport->input;
  1287		} else {
  1288			data->input = devm_input_allocate_device(dev);
  1289			if (!data->input) {
  1290				dev_err(dev, "%s: Failed to allocate input device.\n",
  1291					__func__);
  1292				retval = -ENOMEM;
  1293				goto err;
  1294			}
  1295			rmi_driver_set_input_params(rmi_dev, data->input);
  1296			data->input->phys = devm_kasprintf(dev, GFP_KERNEL,
  1297							"%s/input0", dev_name(dev));
  1298		}
  1299	
  1300		retval = rmi_init_functions(data);
  1301		if (retval)
  1302			goto err;
  1303	
  1304		retval = rmi_f34_create_sysfs(rmi_dev);
  1305		if (retval)
  1306			goto err;
  1307	
  1308		if (data->input) {
  1309			rmi_driver_set_input_name(rmi_dev, data->input);
  1310			if (!rmi_dev->xport->input) {
  1311				retval = input_register_device(data->input);
  1312				if (retval) {
  1313					dev_err(dev, "%s: Failed to register input device.\n",
  1314						__func__);
  1315					goto err_destroy_functions;
  1316				}
  1317			}
  1318		}
  1319	
  1320		retval = rmi_irq_init(rmi_dev);
  1321		if (retval < 0)
  1322			goto err_destroy_functions;
  1323	
  1324		if (data->f01_container->dev.driver) {
  1325			/* Driver already bound, so enable ATTN now. */
  1326			retval = rmi_enable_sensor(rmi_dev);
  1327			if (retval)
  1328				goto err_disable_irq;
  1329		}
  1330	
  1331		return 0;
  1332	
  1333	err_disable_irq:
  1334		rmi_disable_irq(rmi_dev, false);
  1335	err_destroy_functions:
  1336		rmi_free_function_list(rmi_dev);
  1337	err:
  1338		return retval;
  1339	}
  1340
diff mbox series

Patch

diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index 22f0b35bb70b..f1c09fdb8d73 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,
+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,6 +1056,45 @@  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
@@ -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 e1a5412f2f8f..2531c32d6163 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 ab7eea01ab42..974597960b5e 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 */