Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bc87ffc9 authored by Shantanu Jain's avatar Shantanu Jain Committed by Himanshu Aggarwal
Browse files

input: synaptics_dsx: add ability to identify controller



The touchscreen controllers are field-swappable on both customer
devices and internal reference devices. Current touch driver
architecture for Synaptics does not support dynamic detection
of two or more Synaptics touchscreens having same slave address. The
patch provides a solution for the scenario in which it is required
to swap two Synaptics touchscreens without changing DT. Support of
this is added in driver as follows:

1. During driver probe, touch controller is identified by reading
the Package Id from controller. Package ID in F01_RMI_Query register
comprises of a 16-bit Package ID and a 16-bit Package ID Revision
of which both are unique for a touch controller part. If Package ID
is present,then a RMI read operation in UI Mode at seventeenth
register from F01 Query base returns it. First two bytes of this
Package ID base are used to select the correct Synaptics touch
controller from device tree.

2. Add a new property synaptics,detect-device in DT files which
will allow software to enable this logic to detect correct
touchscreen slave.

3. All such devices are placed as child nodes of Synaptics
Touchpanel node. These child nodes are parsed only if the property
synaptics,detect-device is defined in DT file.

Change-Id: I2383b8bed85b130a8558db403b565cec693d17fa
Signed-off-by: default avatarHimanshu Aggarwal <haggarwa@codeaurora.org>
Signed-off-by: default avatarShantanu Jain <shjain@codeaurora.org>
parent dfc6b80d
Loading
Loading
Loading
Loading
+29 −2
Original line number Diff line number Diff line
@@ -31,6 +31,25 @@ Optional property:
			config defined in pin groups of interrupt and reset gpio.
			"pmx_ts_suspend" : Disabled configuration of pins, this should specify sleep
			config defined in pin groups of interrupt and reset gpio.
 - synaptics,detect-device	: Define this property when two Synaptics Touchscreen controllers
				need to be supported without changing the DT. In this case, all
				such devices are placed as child nodes of Synaptics touchscreen
				node. Following are the properties that can be defined inside
				these child nodes:
				- synaptics-package-id
				- synaptics,panel-coords
				- synaptics-display-coords
				- synaptics,button-map

Optional properties inside child node:
These properties are defined only when synaptics,detect-device property is defined in DT.
 - synaptics,package-id		: Specifies the Package Id of touch controller.
 - synaptics,panel-coords	: Specifies the Touch panel min x, min y, max x and max y
				resolution.
 - synaptics,display-coords	: Specifies the display min x, min y, max x and max y
				resolution.
 - synaptics,button-map		: virtual key code mappings to be used.


Example:
	i2c@f9927000 {
@@ -43,7 +62,6 @@ Example:
			avdd-supply = <&pm8226_lvs1>;
			synaptics,reset-gpio = <&msmgpio 16 0x00>;
			synaptics,irq-gpio = <&msmgpio 17 0x00>;
			synaptics,button-map = [8B 66 9E];
			synaptics,reset-delay-ms = <100>;
			synaptics,x-flip;
			synaptics,y-flip;
@@ -52,6 +70,15 @@ Example:
			pinctrl-names = "pmx_ts_active","pmx_ts_suspend";
			pinctrl-0 = <&ts_int_active &ts_reset_active>;
			pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;

			synaptics,detect-device;
			synaptics,device1 {
				synaptics,package-id = <3202>;
				synaptics,button-map = <139 172 158>;
			};
			synaptics,device2 {
				synaptics,package-id = <3408>;
				synaptics,display-coords = <0 0 1079 1919>;
				synaptics,panel-coords = <0 0 1079 2084>;
			};
		};
	};
+137 −0
Original line number Diff line number Diff line
@@ -2054,6 +2054,7 @@ static int synaptics_rmi4_query_device(struct synaptics_rmi4_data *rmi4_data)
	struct synaptics_rmi4_fn_desc rmi_fd;
	struct synaptics_rmi4_fn *fhandler;
	struct synaptics_rmi4_device_info *rmi;
	unsigned char pkg_id[PACKAGE_ID_SIZE];

	rmi = &(rmi4_data->rmi4_mod_info);

@@ -2251,6 +2252,19 @@ flash_prog_mode:
				__func__, rmi->manufacturer_id);
	}

	retval = synaptics_rmi4_reg_read(rmi4_data,
			rmi4_data->f01_query_base_addr + F01_PACKAGE_ID_OFFSET,
			pkg_id, sizeof(pkg_id));
	if (retval < 0) {
		dev_err(rmi4_data->pdev->dev.parent,
			"%s: Failed to read device package id (code %d)\n",
			__func__, retval);
		return retval;
	}

	rmi->package_id = (pkg_id[1] << 8) | pkg_id[0];
	rmi->package_id_rev = (pkg_id[3] << 8) | pkg_id[2];

	retval = synaptics_rmi4_reg_read(rmi4_data,
			rmi4_data->f01_query_base_addr + F01_BUID_ID_OFFSET,
			rmi->build_id,
@@ -2355,6 +2369,118 @@ static void synaptics_rmi4_set_params(struct synaptics_rmi4_data *rmi4_data)
	return;
}

static int synaptics_dsx_get_button_map(struct device *dev, char *name,
				struct synaptics_dsx_board_data *rmi4_pdata,
				struct device_node *np)
{
	struct property *prop;
	int rc, i;
	u32 temp_val, num_buttons;
	u32 button_map[MAX_NUMBER_OF_BUTTONS];

	prop = of_find_property(np, "synaptics,button-map", NULL);
	if (prop) {
		num_buttons = prop->length / sizeof(temp_val);

		rmi4_pdata->cap_button_map = devm_kzalloc(dev,
				sizeof(*rmi4_pdata->cap_button_map),
				GFP_KERNEL);
		if (!rmi4_pdata->cap_button_map)
			return -ENOMEM;

		rmi4_pdata->cap_button_map->map = devm_kzalloc(dev,
			sizeof(*rmi4_pdata->cap_button_map->map) *
			num_buttons, GFP_KERNEL);
		if (!rmi4_pdata->cap_button_map->map)
			return -ENOMEM;

		if (num_buttons <= MAX_NUMBER_OF_BUTTONS) {
			rc = of_property_read_u32_array(np,
					"synaptics,button-map", button_map,
					num_buttons);
			if (rc) {
				dev_err(dev, "Unable to read key codes\n");
				return rc;
			}
			for (i = 0; i < num_buttons; i++)
				rmi4_pdata->cap_button_map->map[i] =
					button_map[i];
			rmi4_pdata->cap_button_map->nbuttons = num_buttons;
		} else {
			return -EINVAL;
		}
	}
	return 0;
}

static int synaptics_rmi4_parse_dt_children(struct device *dev,
		struct synaptics_dsx_board_data *rmi4_pdata,
		struct synaptics_rmi4_data *rmi4_data)
{
	struct synaptics_rmi4_device_info *rmi = &rmi4_data->rmi4_mod_info;
	struct device_node *node = dev->of_node, *child = NULL;
	int rc = 0;
	struct synaptics_rmi4_fn *fhandler = NULL;

	for_each_child_of_node(node, child) {
		rc = of_property_read_u32(child, "synaptics,package-id",
				&rmi4_pdata->package_id);
		if (rc && (rc != -EINVAL)) {
			dev_err(dev, "Unable to read package_id\n");
			return rc;
		} else if (rc == -EINVAL) {
			rmi4_pdata->package_id = 0x00;
		}

		if (rmi4_pdata->package_id && (rmi4_pdata->package_id !=
					rmi->package_id)) {
			dev_err(dev,
				"%s: Synaptics package id don't match %d %d\n",
				__func__,
				rmi4_pdata->package_id, rmi->package_id);

			/* Iterate over next child if package id not matched */
			continue;
		}

		rc = synaptics_dsx_get_dt_coords(dev,
				"synaptics,display-coords", rmi4_pdata, child);
		if (rc && (rc != -EINVAL))
			return rc;

		rc = synaptics_dsx_get_dt_coords(dev,
				 "synaptics,panel-coords", rmi4_pdata, child);
		if (rc && (rc != -EINVAL))
			return rc;

		rc = synaptics_dsx_get_button_map(dev,
				 "synaptics,button-map", rmi4_pdata, child);
		if (rc < 0) {
			dev_err(dev, "Unable to read key codes\n");
			return rc;
		}

		if (!list_empty(&rmi->support_fn_list)) {
			list_for_each_entry(fhandler,
					&rmi->support_fn_list, link) {
				if (fhandler->fn_number == SYNAPTICS_RMI4_F1A)
					break;
			}
		}

		if (fhandler && fhandler->fn_number == SYNAPTICS_RMI4_F1A) {
			rc = synaptics_rmi4_f1a_button_map(rmi4_data, fhandler);
			if (rc < 0) {
				dev_err(dev, "Fail to register F1A %d\n", rc);
				return rc;
			}
		}
		break;
	}

	return 0;
}

static int synaptics_rmi4_set_input_dev(struct synaptics_rmi4_data *rmi4_data)
{
	int retval;
@@ -2377,6 +2503,17 @@ static int synaptics_rmi4_set_input_dev(struct synaptics_rmi4_data *rmi4_data)
		goto err_query_device;
	}

	if (rmi4_data->hw_if->board_data->detect_device) {
		retval = synaptics_rmi4_parse_dt_children(
				rmi4_data->pdev->dev.parent,
				rmi4_data->hw_if->board_data,
				rmi4_data);
		if (retval < 0)
			dev_err(rmi4_data->pdev->dev.parent,
				"%s: Failed to parse device tree property\n",
				__func__);
	}

	rmi4_data->input_dev->name = PLATFORM_DRIVER_NAME;
	rmi4_data->input_dev->phys = INPUT_PHYS_NAME;
	rmi4_data->input_dev->id.product = SYNAPTICS_DSX_DRIVER_PRODUCT;
+10 −2
Original line number Diff line number Diff line
@@ -71,6 +71,9 @@
#define SYNAPTICS_RMI4_PRODUCT_ID_SIZE 10
#define SYNAPTICS_RMI4_BUILD_ID_SIZE 3

#define F01_PACKAGE_ID_OFFSET 17
#define PACKAGE_ID_SIZE 4

#define F12_FINGERS_TO_SUPPORT 10
#define F12_NO_OBJECT_STATUS 0x00
#define F12_FINGER_STATUS 0x01
@@ -104,7 +107,7 @@ enum exp_fn {
};

struct synaptics_dsx_hw_interface {
	const struct synaptics_dsx_board_data *board_data;
	struct synaptics_dsx_board_data *board_data;
	const struct synaptics_dsx_bus_access *bus_access;
};

@@ -199,6 +202,8 @@ struct synaptics_rmi4_device_info {
	unsigned char product_id_string[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1];
	unsigned char build_id[SYNAPTICS_RMI4_BUILD_ID_SIZE];
	struct list_head support_fn_list;
	unsigned int package_id;
	unsigned int package_id_rev;
};

/*
@@ -322,6 +327,10 @@ void synaptics_rmi4_dsx_new_function(struct synaptics_rmi4_exp_fn *exp_fn_mod,

int synaptics_dsx_fw_updater(unsigned char *fw_data);

int synaptics_dsx_get_dt_coords(struct device *dev, char *name,
				struct synaptics_dsx_board_data *pdata,
				struct device_node *node);

static inline int synaptics_rmi4_reg_read(
		struct synaptics_rmi4_data *rmi4_data,
		unsigned short addr,
@@ -369,5 +378,4 @@ static inline void hstoba(unsigned char *dest, unsigned short src)
	dest[0] = src % 0x100;
	dest[1] = src / 0x100;
}

#endif
+2 −3
Original line number Diff line number Diff line
@@ -37,7 +37,6 @@
#define LOCKDOWN_OFFSET 0xb0
#define FW_IMAGE_OFFSET 0x100

#define PACKAGE_ID_OFFSET 17
#define BOOTLOADER_ID_OFFSET 0
#define BLOCK_NUMBER_OFFSET 0

@@ -1786,12 +1785,12 @@ static ssize_t fwu_sysfs_package_id_show(struct device *dev,
			struct device_attribute *attr, char *buf)
{
	int retval;
	unsigned char package_id[4];
	unsigned char package_id[PACKAGE_ID_SIZE];
	struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;

	/* read device package id */
	retval = synaptics_rmi4_reg_read(rmi4_data,
			rmi4_data->f01_query_base_addr + PACKAGE_ID_OFFSET,
			rmi4_data->f01_query_base_addr + F01_PACKAGE_ID_OFFSET,
			package_id,
			sizeof(package_id));

+11 −5
Original line number Diff line number Diff line
@@ -224,12 +224,13 @@ static void synaptics_rmi4_i2c_dev_release(struct device *dev)
	return;
}
#ifdef CONFIG_OF
static int synaptics_dsx_get_dt_coords(struct device *dev, char *name,
				struct synaptics_dsx_board_data *pdata)
int synaptics_dsx_get_dt_coords(struct device *dev, char *name,
				struct synaptics_dsx_board_data *pdata,
				struct device_node *node)
{
	u32 coords[DSX_COORDS_ARR_SIZE];
	struct property *prop;
	struct device_node *np = dev->of_node;
	struct device_node *np = (node == NULL) ? (dev->of_node) : (node);
	int coords_size, rc;

	prop = of_find_property(np, name, NULL);
@@ -307,15 +308,20 @@ static int synaptics_dsx_parse_dt(struct device *dev,
			"synaptics,irq-gpio", 0, &rmi4_pdata->irq_flags);

	rc = synaptics_dsx_get_dt_coords(dev, "synaptics,display-coords",
				rmi4_pdata);
				rmi4_pdata, NULL);
	if (rc && (rc != -EINVAL))
		return rc;

	rc = synaptics_dsx_get_dt_coords(dev, "synaptics,panel-coords",
				rmi4_pdata);
				rmi4_pdata, NULL);
	if (rc && (rc != -EINVAL))
		return rc;

	rmi4_pdata->detect_device = of_property_read_bool(np,
				"synaptics,detect-device");

	if (rmi4_pdata->detect_device)
		return 0;

	prop = of_find_property(np, "synaptics,button-map", NULL);
	if (prop) {
Loading