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

Commit b3fc7055 authored by Himanshu Aggarwal's avatar Himanshu Aggarwal Committed by Sudhakar Manapati
Browse files

input: synaptics_i2c_rmi4: 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 Synaptics touchscreens with the 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.

This patch is propagated from msm-3.10 kernel
(commit: 07f733b47550c625d04cf954ae27de22a793f3a0
input: synaptics_i2c_rmi4: add ability to identify controller)

Change-Id: Iac0eaef1b8cd301da763ef980a33ba27ccfb858d
Signed-off-by: default avatarHimanshu Aggarwal <haggarwa@codeaurora.org>
parent 51436926
Loading
Loading
Loading
Loading
+28 −2
Original line number Diff line number Diff line
@@ -33,6 +33,24 @@ Optional property:
 - synaptics,fw-image-name	: name of firmware .img file in /etc/firmware
 - synaptics,power-down		: fully power down regulators in suspend
 - synaptics,do-lockdown	: perform one time lockdown procedure
 - 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 { /* BLSP1 QUP5 */
@@ -56,13 +74,21 @@ Example:
			interrupts = <17 0x2>;
			vdd-supply = <&pm8226_l19>;
			vcc_i2c-supply = <&pm8226_lvs1>;

			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,reset-gpio = <&msmgpio 16 0x00>;
			synaptics,irq-gpio = <&msmgpio 17 0x00>;
			synaptics,button-map = [8B 66 9E];
			synaptics,i2c-pull-up;
			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>;
			};
		};
	};
+140 −5
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@
#define MAX_ABS_MT_TOUCH_MAJOR 15

#define F01_STD_QUERY_LEN 21
#define F01_PACKAGE_ID_OFFSET 17
#define F01_BUID_ID_OFFSET 18
#define F11_STD_QUERY_LEN 9
#define F11_STD_CTRL_LEN 10
@@ -1362,12 +1363,58 @@ static irqreturn_t synaptics_rmi4_irq(int irq, void *data)
}

#ifdef CONFIG_OF
static int synaptics_rmi4_get_button_map(struct device *dev, char *name,
				struct synaptics_rmi4_platform_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->capacitance_button_map = devm_kzalloc(dev,
				sizeof(*rmi4_pdata->capacitance_button_map),
				GFP_KERNEL);
		if (!rmi4_pdata->capacitance_button_map)
			return -ENOMEM;

		rmi4_pdata->capacitance_button_map->map = devm_kzalloc(dev,
			sizeof(*rmi4_pdata->capacitance_button_map->map) *
			MAX_NUMBER_OF_BUTTONS, GFP_KERNEL);
		if (!rmi4_pdata->capacitance_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->capacitance_button_map->map[i] =
					button_map[i];
			rmi4_pdata->capacitance_button_map->nbuttons =
				num_buttons;
		} else {
			return -EINVAL;
		}
	}
	return 0;
}

static int synaptics_rmi4_get_dt_coords(struct device *dev, char *name,
				struct synaptics_rmi4_platform_data *pdata)
				struct synaptics_rmi4_platform_data *pdata,
				struct device_node *node)
{
	u32 coords[RMI4_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);
@@ -1406,10 +1453,57 @@ static int synaptics_rmi4_get_dt_coords(struct device *dev, char *name,
	return 0;
}

static int synaptics_rmi4_parse_dt_children(struct device *dev,
		struct synaptics_rmi4_platform_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;
	int rc;

	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) {
			if (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);

				continue;
			}
		}

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

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

		break;
	}
	return 0;
}

static int synaptics_rmi4_parse_dt(struct device *dev,
				struct synaptics_rmi4_platform_data *rmi4_pdata)
{
	struct device_node *np = dev->of_node;
	struct device_node *np = dev->of_node, *child;
	struct property *prop;
	u32 temp_val, num_buttons;
	u32 button_map[MAX_NUMBER_OF_BUTTONS];
@@ -1427,12 +1521,12 @@ static int synaptics_rmi4_parse_dt(struct device *dev,
			"synaptics,do-lockdown");

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

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

@@ -1458,6 +1552,12 @@ static int synaptics_rmi4_parse_dt(struct device *dev,
	rmi4_pdata->irq_gpio = of_get_named_gpio_flags(np,
			"synaptics,irq-gpio", 0, &rmi4_pdata->irq_flags);

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

	if (rmi4_pdata->detect_device)
		goto parse_button_map_for_children;

	prop = of_find_property(np, "synaptics,button-map", NULL);
	if (prop) {
		num_buttons = prop->length / sizeof(temp_val);
@@ -1492,6 +1592,17 @@ static int synaptics_rmi4_parse_dt(struct device *dev,
		}
	}
	return 0;

parse_button_map_for_children:
	for_each_child_of_node(np, child) {
		rc = synaptics_rmi4_get_button_map(dev, "synaptics,button-map",
				rmi4_pdata, child);
		if (rc < 0) {
			dev_err(dev, "Unable to read key codes\n");
			return rc;
		}
	}
	return 0;
}
#else
static inline int synaptics_rmi4_parse_dt(struct device *dev,
@@ -1999,6 +2110,7 @@ static int synaptics_rmi4_query_device_info(
	int retval;
	unsigned char f01_query[F01_STD_QUERY_LEN];
	struct synaptics_rmi4_device_info *rmi = &(rmi4_data->rmi4_mod_info);
	unsigned char pkg_id[4];

	retval = synaptics_rmi4_i2c_read(rmi4_data,
			rmi4_data->f01_query_base_addr,
@@ -2030,6 +2142,20 @@ static int synaptics_rmi4_query_device_info(
				__func__, rmi->manufacturer_id);
	}

	retval = synaptics_rmi4_i2c_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->i2c_client->dev,
				"%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_i2c_read(rmi4_data,
			rmi4_data->f01_query_base_addr + F01_BUID_ID_OFFSET,
			rmi->build_id,
@@ -2970,6 +3096,15 @@ static int synaptics_rmi4_probe(struct i2c_client *client,
		goto err_free_gpios;
	}

	if (platform_data->detect_device) {
		retval = synaptics_rmi4_parse_dt_children(&client->dev,
				platform_data, rmi4_data);
		if (retval < 0)
			dev_err(&client->dev,
				"%s: Failed to parse device tree property\n",
					__func__);
	}

	if (rmi4_data->board->disp_maxx)
		rmi4_data->disp_maxx = rmi4_data->board->disp_maxx;
	else
+2 −0
Original line number Diff line number Diff line
@@ -163,6 +163,8 @@ struct synaptics_rmi4_device_info {
	unsigned char config_id[3];
	struct mutex support_fn_list_mutex;
	struct list_head support_fn_list;
	unsigned int package_id;
	unsigned int package_id_rev;
};

/*
+3 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@
 *
 * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
 * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
@@ -62,6 +62,7 @@ struct synaptics_rmi4_platform_data {
	bool power_down_enable;
	bool disable_gpios;
	bool do_lockdown;
	bool detect_device;
	unsigned irq_gpio;
	u32 irq_flags;
	u32 reset_flags;
@@ -76,6 +77,7 @@ struct synaptics_rmi4_platform_data {
	unsigned disp_maxy;
	unsigned reset_delay;
	const char *fw_image_name;
	unsigned int package_id;
	int (*gpio_config)(unsigned gpio, bool configure);
	struct synaptics_rmi4_capacitance_button_map *capacitance_button_map;
};