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

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

input: synaptics_dsx: add support for 2D sensor for soft-keys



The touchscreen controllers are field-swappable on both customer
devices and internal reference devices. It is possible to have
multiple Synaptics touch controllers where each controller would
support softkey in a different way. While some touch controllers
support 2-dimensional touch sensor, some others support capacitative
button(0D) sensing. In the former case, the touch sensor reports
native X-Y touch coordinates of the touch sensor in the soft key region.
This is implemented by RMI4 function F11 or F12 and software needs to
translate these coordinates to keycodes. In the latter case, the touch
sensor directly reports the key codes and hence there is no need for
software to do any translation. This is implemented by RMI4 function
F1A or F19.

The current architecture of Synaptics touchscreen driver does not have
support to disambiguate between more than two Synaptics touch controllers
that support 2-dimensional touch sensor for soft keys. To support
this functionality in driver, a device-tree property is defined that
describes the key codes for the soft-key area. The driver calculates
the total soft key area based on the display resolution and touch sensor
dimensions. Based on the total soft-key area and number of keys to be
supported, it calculates the area for each of the soft-keys. It exports
this information to userspace by populating a sysfs file. User-space
programs can then translate the touch coordinates received to key codes.

Change-Id: I99876527660d0be7cef86e88d7583e331159e7eb
Signed-off-by: default avatarHimanshu Aggarwal <haggarwa@codeaurora.org>
Signed-off-by: default avatarShantanu Jain <shjain@codeaurora.org>
parent 03328cdf
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ Optional property:
				- synaptics,panel-coords
				- synaptics-display-coords
				- synaptics,button-map
				- synaptics,key-codes

Optional properties inside child node:
These properties are defined only when synaptics,detect-device property is defined in DT.
@@ -48,8 +49,11 @@ These properties are defined only when synaptics,detect-device property is defin
				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.

 - synaptics,button-map		: Key code mappings to be used when device
				supports 0D buttons and directly sends key codes.
 - synaptics,key-codes		: Virtual key code mappings to be used when device
				supports 2D buttons and sends coordinates instead of
				key codes.

Example:
	i2c@f9927000 {
@@ -79,6 +83,7 @@ Example:
				synaptics,package-id = <3408>;
				synaptics,display-coords = <0 0 1079 1919>;
				synaptics,panel-coords = <0 0 1079 2084>;
				synaptics,key-codes = <139 172 158 217>;
			};
		};
	};
+193 −49
Original line number Diff line number Diff line
@@ -384,6 +384,43 @@ static struct device_attribute attrs[] = {
#endif
};

#define MAX_BUF_SIZE	256
#define VKEY_VER_CODE	"0x01"

#define HEIGHT_SCALE_NUM 8
#define HEIGHT_SCALE_DENOM 10

/* numerator and denomenator for border equations */
#define BORDER_ADJUST_NUM 3
#define BORDER_ADJUST_DENOM 4

static struct kobject *vkey_kobj;
static char *vkey_buf;

static ssize_t vkey_show(struct kobject  *obj,
	struct kobj_attribute *attr, char *buf)
{
	strlcpy(buf, vkey_buf, MAX_BUF_SIZE);
	return strnlen(buf, MAX_BUF_SIZE);
}

static struct kobj_attribute vkey_obj_attr = {
	.attr = {
		.mode = S_IRUGO,
		.name = "virtualkeys."PLATFORM_DRIVER_NAME,
	},
	.show = vkey_show,
};

static struct attribute *vkey_attr[] = {
	&vkey_obj_attr.attr,
	NULL,
};

static struct attribute_group vkey_grp = {
	.attrs = vkey_attr,
};

static int synaptics_rmi4_debug_suspend_set(void *_data, u64 val)
{
	struct synaptics_rmi4_data *rmi4_data = _data;
@@ -2369,18 +2406,99 @@ 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,
static int synaptics_dsx_virtual_keys_init(struct device *dev,
			struct synaptics_dsx_board_data	*rmi4_pdata)
{
	int width, height, center_x, center_y;
	int x1 = 0, x2 = 0, i, c = 0, rc = 0, border;

	vkey_buf = devm_kzalloc(dev, MAX_BUF_SIZE, GFP_KERNEL);
	if (!vkey_buf) {
		dev_err(dev, "Failed to allocate memory\n");
		return -ENOMEM;
	}

	border = (rmi4_pdata->panel_maxx - rmi4_pdata->disp_maxx) * 2;
	width = ((rmi4_pdata->disp_maxx -
			(border * (rmi4_pdata->virtual_key_map->nkeys - 1)))
			/ rmi4_pdata->virtual_key_map->nkeys);
	height = (rmi4_pdata->panel_maxy - rmi4_pdata->disp_maxy);
	center_y = rmi4_pdata->disp_maxy + (height / 2);
	height = height * HEIGHT_SCALE_NUM / HEIGHT_SCALE_DENOM;

	x2 -= border * BORDER_ADJUST_NUM / BORDER_ADJUST_DENOM;

	for (i = 0; i < rmi4_pdata->virtual_key_map->nkeys; i++) {
		x1 = x2 + border;
		x2 = x2 + border + width;
		center_x = x1 + (x2 - x1) / 2;
		c += snprintf(vkey_buf + c, MAX_BUF_SIZE - c,
				"%s:%d:%d:%d:%d:%d\n", VKEY_VER_CODE,
				rmi4_pdata->virtual_key_map->map[i],
				center_x, center_y, width, height);
	}

	vkey_buf[c] = '\0';

	vkey_kobj = kobject_create_and_add("board_properties", NULL);
	if (!vkey_kobj) {
		dev_err(dev, "unable to create kobject\n");
		return -ENOMEM;
	}

	rc = sysfs_create_group(vkey_kobj, &vkey_grp);
	if (rc) {
		dev_err(dev, "failed to create attributes\n");
		kobject_put(vkey_kobj);
	}

	return rc;
}

static int synaptics_dsx_get_virtual_keys(struct device *dev,
				struct property *prop, char *name,
				struct synaptics_dsx_board_data *rmi4_pdata,
				struct device_node *np)
{
	u32 num_keys;
	int rc;

	num_keys = prop->length / sizeof(u32);

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

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

	rc = of_property_read_u32_array(np, name,
			rmi4_pdata->virtual_key_map->map,
			num_keys);
	if (rc) {
		dev_err(dev, "Failed to read key codes\n");
		return -EINVAL;
	}
	rmi4_pdata->virtual_key_map->nkeys = num_keys;

	return 0;
}

static int synaptics_dsx_get_button_map(struct device *dev,
				struct property *prop, 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 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);
	num_buttons = prop->length / sizeof(u32);

	rmi4_pdata->cap_button_map = devm_kzalloc(dev,
			sizeof(*rmi4_pdata->cap_button_map),
@@ -2396,8 +2514,7 @@ static int synaptics_dsx_get_button_map(struct device *dev, char *name,

	if (num_buttons <= MAX_NUMBER_OF_BUTTONS) {
		rc = of_property_read_u32_array(np,
					"synaptics,button-map", button_map,
					num_buttons);
				name, button_map, num_buttons);
		if (rc) {
			dev_err(dev, "Unable to read key codes\n");
			return rc;
@@ -2409,7 +2526,7 @@ static int synaptics_dsx_get_button_map(struct device *dev, char *name,
	} else {
		return -EINVAL;
	}
	}

	return 0;
}

@@ -2421,6 +2538,7 @@ static int synaptics_rmi4_parse_dt_children(struct device *dev,
	struct device_node *node = dev->of_node, *child = NULL;
	int rc = 0;
	struct synaptics_rmi4_fn *fhandler = NULL;
	struct property *prop;

	for_each_child_of_node(node, child) {
		rc = of_property_read_u32(child, "synaptics,package-id",
@@ -2439,7 +2557,7 @@ static int synaptics_rmi4_parse_dt_children(struct device *dev,
				__func__,
				rmi4_pdata->package_id, rmi->package_id);

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

@@ -2453,28 +2571,51 @@ static int synaptics_rmi4_parse_dt_children(struct device *dev,
		if (rc && (rc != -EINVAL))
			return rc;

		rc = synaptics_dsx_get_button_map(dev,
		prop = of_find_property(child, "synaptics,button-map", NULL);
		if (prop) {
			rc = synaptics_dsx_get_button_map(dev, prop,
				"synaptics,button-map", rmi4_pdata, child);
			if (rc < 0) {
			dev_err(dev, "Unable to read key codes\n");
				dev_err(dev, "Unable to read button map\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)
					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 (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);
					dev_err(dev,
						"Fail to register F1A %d\n",
						rc);
					return rc;
				}
			}
		}

		prop = of_find_property(child, "synaptics,key-codes", NULL);
		if (prop) {
			rc = synaptics_dsx_get_virtual_keys(dev, prop,
				"synaptics,key-codes", rmi4_pdata, child);
			if (!rc) {
				synaptics_dsx_virtual_keys_init(dev,
					rmi4_pdata);
			} else {
				dev_err(dev,
					"Unable to read virtual key codes\n");
				return rc;
			}
		}

		break;
	}

@@ -3364,6 +3505,9 @@ static int synaptics_rmi4_remove(struct platform_device *pdev)
	const struct synaptics_dsx_board_data *bdata =
			rmi4_data->hw_if->board_data;

	sysfs_remove_group(vkey_kobj, &vkey_grp);
	kobject_put(vkey_kobj);

	for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
		sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
				&attrs[attr_count].attr);
+11 −0
Original line number Diff line number Diff line
@@ -34,6 +34,16 @@ struct synaptics_dsx_cap_button_map {
	unsigned char *map;
};

/*
 * struct synaptics_virtual_key_map - 2d button map
 * @nkeys: number of virtual keys
 * @map: pointer to array of virtual keys
 */
struct synaptics_rmi4_virtual_key_map {
	unsigned char nkeys;
	unsigned int *map;
};

/*
 * struct synaptics_dsx_board_data - dsx board data
 * @x_flip: x flip flag
@@ -77,6 +87,7 @@ struct synaptics_dsx_board_data {
	unsigned int package_id;
	int (*gpio_config)(int gpio, bool configure, int dir, int state);
	struct synaptics_dsx_cap_button_map *cap_button_map;
	struct synaptics_rmi4_virtual_key_map *virtual_key_map;
	u32 panel_minx;
	u32 panel_miny;
	u32 panel_maxx;