18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2012-2013 MundoReader S.L.
48c2ecf20Sopenharmony_ci * Author: Heiko Stuebner <heiko@sntech.de>
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * based in parts on Nook zforce driver
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Copyright (C) 2010 Barnes & Noble, Inc.
98c2ecf20Sopenharmony_ci * Author: Pieter Truter<ptruter@intrinsyc.com>
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <linux/module.h>
138c2ecf20Sopenharmony_ci#include <linux/hrtimer.h>
148c2ecf20Sopenharmony_ci#include <linux/slab.h>
158c2ecf20Sopenharmony_ci#include <linux/input.h>
168c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
178c2ecf20Sopenharmony_ci#include <linux/i2c.h>
188c2ecf20Sopenharmony_ci#include <linux/delay.h>
198c2ecf20Sopenharmony_ci#include <linux/gpio/consumer.h>
208c2ecf20Sopenharmony_ci#include <linux/device.h>
218c2ecf20Sopenharmony_ci#include <linux/sysfs.h>
228c2ecf20Sopenharmony_ci#include <linux/input/mt.h>
238c2ecf20Sopenharmony_ci#include <linux/platform_data/zforce_ts.h>
248c2ecf20Sopenharmony_ci#include <linux/regulator/consumer.h>
258c2ecf20Sopenharmony_ci#include <linux/of.h>
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci#define WAIT_TIMEOUT		msecs_to_jiffies(1000)
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#define FRAME_START		0xee
308c2ecf20Sopenharmony_ci#define FRAME_MAXSIZE		257
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci/* Offsets of the different parts of the payload the controller sends */
338c2ecf20Sopenharmony_ci#define PAYLOAD_HEADER		0
348c2ecf20Sopenharmony_ci#define PAYLOAD_LENGTH		1
358c2ecf20Sopenharmony_ci#define PAYLOAD_BODY		2
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci/* Response offsets */
388c2ecf20Sopenharmony_ci#define RESPONSE_ID		0
398c2ecf20Sopenharmony_ci#define RESPONSE_DATA		1
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci/* Commands */
428c2ecf20Sopenharmony_ci#define COMMAND_DEACTIVATE	0x00
438c2ecf20Sopenharmony_ci#define COMMAND_INITIALIZE	0x01
448c2ecf20Sopenharmony_ci#define COMMAND_RESOLUTION	0x02
458c2ecf20Sopenharmony_ci#define COMMAND_SETCONFIG	0x03
468c2ecf20Sopenharmony_ci#define COMMAND_DATAREQUEST	0x04
478c2ecf20Sopenharmony_ci#define COMMAND_SCANFREQ	0x08
488c2ecf20Sopenharmony_ci#define COMMAND_STATUS		0X1e
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci/*
518c2ecf20Sopenharmony_ci * Responses the controller sends as a result of
528c2ecf20Sopenharmony_ci * command requests
538c2ecf20Sopenharmony_ci */
548c2ecf20Sopenharmony_ci#define RESPONSE_DEACTIVATE	0x00
558c2ecf20Sopenharmony_ci#define RESPONSE_INITIALIZE	0x01
568c2ecf20Sopenharmony_ci#define RESPONSE_RESOLUTION	0x02
578c2ecf20Sopenharmony_ci#define RESPONSE_SETCONFIG	0x03
588c2ecf20Sopenharmony_ci#define RESPONSE_SCANFREQ	0x08
598c2ecf20Sopenharmony_ci#define RESPONSE_STATUS		0X1e
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci/*
628c2ecf20Sopenharmony_ci * Notifications are sent by the touch controller without
638c2ecf20Sopenharmony_ci * being requested by the driver and include for example
648c2ecf20Sopenharmony_ci * touch indications
658c2ecf20Sopenharmony_ci */
668c2ecf20Sopenharmony_ci#define NOTIFICATION_TOUCH		0x04
678c2ecf20Sopenharmony_ci#define NOTIFICATION_BOOTCOMPLETE	0x07
688c2ecf20Sopenharmony_ci#define NOTIFICATION_OVERRUN		0x25
698c2ecf20Sopenharmony_ci#define NOTIFICATION_PROXIMITY		0x26
708c2ecf20Sopenharmony_ci#define NOTIFICATION_INVALID_COMMAND	0xfe
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci#define ZFORCE_REPORT_POINTS		2
738c2ecf20Sopenharmony_ci#define ZFORCE_MAX_AREA			0xff
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci#define STATE_DOWN			0
768c2ecf20Sopenharmony_ci#define STATE_MOVE			1
778c2ecf20Sopenharmony_ci#define STATE_UP			2
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci#define SETCONFIG_DUALTOUCH		(1 << 0)
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cistruct zforce_point {
828c2ecf20Sopenharmony_ci	int coord_x;
838c2ecf20Sopenharmony_ci	int coord_y;
848c2ecf20Sopenharmony_ci	int state;
858c2ecf20Sopenharmony_ci	int id;
868c2ecf20Sopenharmony_ci	int area_major;
878c2ecf20Sopenharmony_ci	int area_minor;
888c2ecf20Sopenharmony_ci	int orientation;
898c2ecf20Sopenharmony_ci	int pressure;
908c2ecf20Sopenharmony_ci	int prblty;
918c2ecf20Sopenharmony_ci};
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci/*
948c2ecf20Sopenharmony_ci * @client		the i2c_client
958c2ecf20Sopenharmony_ci * @input		the input device
968c2ecf20Sopenharmony_ci * @suspending		in the process of going to suspend (don't emit wakeup
978c2ecf20Sopenharmony_ci *			events for commands executed to suspend the device)
988c2ecf20Sopenharmony_ci * @suspended		device suspended
998c2ecf20Sopenharmony_ci * @access_mutex	serialize i2c-access, to keep multipart reads together
1008c2ecf20Sopenharmony_ci * @command_done	completion to wait for the command result
1018c2ecf20Sopenharmony_ci * @command_mutex	serialize commands sent to the ic
1028c2ecf20Sopenharmony_ci * @command_waiting	the id of the command that is currently waiting
1038c2ecf20Sopenharmony_ci *			for a result
1048c2ecf20Sopenharmony_ci * @command_result	returned result of the command
1058c2ecf20Sopenharmony_ci */
1068c2ecf20Sopenharmony_cistruct zforce_ts {
1078c2ecf20Sopenharmony_ci	struct i2c_client	*client;
1088c2ecf20Sopenharmony_ci	struct input_dev	*input;
1098c2ecf20Sopenharmony_ci	const struct zforce_ts_platdata *pdata;
1108c2ecf20Sopenharmony_ci	char			phys[32];
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	struct regulator	*reg_vdd;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	struct gpio_desc	*gpio_int;
1158c2ecf20Sopenharmony_ci	struct gpio_desc	*gpio_rst;
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	bool			suspending;
1188c2ecf20Sopenharmony_ci	bool			suspended;
1198c2ecf20Sopenharmony_ci	bool			boot_complete;
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	/* Firmware version information */
1228c2ecf20Sopenharmony_ci	u16			version_major;
1238c2ecf20Sopenharmony_ci	u16			version_minor;
1248c2ecf20Sopenharmony_ci	u16			version_build;
1258c2ecf20Sopenharmony_ci	u16			version_rev;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	struct mutex		access_mutex;
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	struct completion	command_done;
1308c2ecf20Sopenharmony_ci	struct mutex		command_mutex;
1318c2ecf20Sopenharmony_ci	int			command_waiting;
1328c2ecf20Sopenharmony_ci	int			command_result;
1338c2ecf20Sopenharmony_ci};
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_cistatic int zforce_command(struct zforce_ts *ts, u8 cmd)
1368c2ecf20Sopenharmony_ci{
1378c2ecf20Sopenharmony_ci	struct i2c_client *client = ts->client;
1388c2ecf20Sopenharmony_ci	char buf[3];
1398c2ecf20Sopenharmony_ci	int ret;
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "%s: 0x%x\n", __func__, cmd);
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	buf[0] = FRAME_START;
1448c2ecf20Sopenharmony_ci	buf[1] = 1; /* data size, command only */
1458c2ecf20Sopenharmony_ci	buf[2] = cmd;
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	mutex_lock(&ts->access_mutex);
1488c2ecf20Sopenharmony_ci	ret = i2c_master_send(client, &buf[0], ARRAY_SIZE(buf));
1498c2ecf20Sopenharmony_ci	mutex_unlock(&ts->access_mutex);
1508c2ecf20Sopenharmony_ci	if (ret < 0) {
1518c2ecf20Sopenharmony_ci		dev_err(&client->dev, "i2c send data request error: %d\n", ret);
1528c2ecf20Sopenharmony_ci		return ret;
1538c2ecf20Sopenharmony_ci	}
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	return 0;
1568c2ecf20Sopenharmony_ci}
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_cistatic void zforce_reset_assert(struct zforce_ts *ts)
1598c2ecf20Sopenharmony_ci{
1608c2ecf20Sopenharmony_ci	gpiod_set_value_cansleep(ts->gpio_rst, 1);
1618c2ecf20Sopenharmony_ci}
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_cistatic void zforce_reset_deassert(struct zforce_ts *ts)
1648c2ecf20Sopenharmony_ci{
1658c2ecf20Sopenharmony_ci	gpiod_set_value_cansleep(ts->gpio_rst, 0);
1668c2ecf20Sopenharmony_ci}
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_cistatic int zforce_send_wait(struct zforce_ts *ts, const char *buf, int len)
1698c2ecf20Sopenharmony_ci{
1708c2ecf20Sopenharmony_ci	struct i2c_client *client = ts->client;
1718c2ecf20Sopenharmony_ci	int ret;
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	ret = mutex_trylock(&ts->command_mutex);
1748c2ecf20Sopenharmony_ci	if (!ret) {
1758c2ecf20Sopenharmony_ci		dev_err(&client->dev, "already waiting for a command\n");
1768c2ecf20Sopenharmony_ci		return -EBUSY;
1778c2ecf20Sopenharmony_ci	}
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "sending %d bytes for command 0x%x\n",
1808c2ecf20Sopenharmony_ci		buf[1], buf[2]);
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci	ts->command_waiting = buf[2];
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci	mutex_lock(&ts->access_mutex);
1858c2ecf20Sopenharmony_ci	ret = i2c_master_send(client, buf, len);
1868c2ecf20Sopenharmony_ci	mutex_unlock(&ts->access_mutex);
1878c2ecf20Sopenharmony_ci	if (ret < 0) {
1888c2ecf20Sopenharmony_ci		dev_err(&client->dev, "i2c send data request error: %d\n", ret);
1898c2ecf20Sopenharmony_ci		goto unlock;
1908c2ecf20Sopenharmony_ci	}
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "waiting for result for command 0x%x\n", buf[2]);
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci	if (wait_for_completion_timeout(&ts->command_done, WAIT_TIMEOUT) == 0) {
1958c2ecf20Sopenharmony_ci		ret = -ETIME;
1968c2ecf20Sopenharmony_ci		goto unlock;
1978c2ecf20Sopenharmony_ci	}
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	ret = ts->command_result;
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ciunlock:
2028c2ecf20Sopenharmony_ci	mutex_unlock(&ts->command_mutex);
2038c2ecf20Sopenharmony_ci	return ret;
2048c2ecf20Sopenharmony_ci}
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_cistatic int zforce_command_wait(struct zforce_ts *ts, u8 cmd)
2078c2ecf20Sopenharmony_ci{
2088c2ecf20Sopenharmony_ci	struct i2c_client *client = ts->client;
2098c2ecf20Sopenharmony_ci	char buf[3];
2108c2ecf20Sopenharmony_ci	int ret;
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "%s: 0x%x\n", __func__, cmd);
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	buf[0] = FRAME_START;
2158c2ecf20Sopenharmony_ci	buf[1] = 1; /* data size, command only */
2168c2ecf20Sopenharmony_ci	buf[2] = cmd;
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	ret = zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf));
2198c2ecf20Sopenharmony_ci	if (ret < 0) {
2208c2ecf20Sopenharmony_ci		dev_err(&client->dev, "i2c send data request error: %d\n", ret);
2218c2ecf20Sopenharmony_ci		return ret;
2228c2ecf20Sopenharmony_ci	}
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	return 0;
2258c2ecf20Sopenharmony_ci}
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_cistatic int zforce_resolution(struct zforce_ts *ts, u16 x, u16 y)
2288c2ecf20Sopenharmony_ci{
2298c2ecf20Sopenharmony_ci	struct i2c_client *client = ts->client;
2308c2ecf20Sopenharmony_ci	char buf[7] = { FRAME_START, 5, COMMAND_RESOLUTION,
2318c2ecf20Sopenharmony_ci			(x & 0xff), ((x >> 8) & 0xff),
2328c2ecf20Sopenharmony_ci			(y & 0xff), ((y >> 8) & 0xff) };
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "set resolution to (%d,%d)\n", x, y);
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	return zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf));
2378c2ecf20Sopenharmony_ci}
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_cistatic int zforce_scan_frequency(struct zforce_ts *ts, u16 idle, u16 finger,
2408c2ecf20Sopenharmony_ci				 u16 stylus)
2418c2ecf20Sopenharmony_ci{
2428c2ecf20Sopenharmony_ci	struct i2c_client *client = ts->client;
2438c2ecf20Sopenharmony_ci	char buf[9] = { FRAME_START, 7, COMMAND_SCANFREQ,
2448c2ecf20Sopenharmony_ci			(idle & 0xff), ((idle >> 8) & 0xff),
2458c2ecf20Sopenharmony_ci			(finger & 0xff), ((finger >> 8) & 0xff),
2468c2ecf20Sopenharmony_ci			(stylus & 0xff), ((stylus >> 8) & 0xff) };
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	dev_dbg(&client->dev,
2498c2ecf20Sopenharmony_ci		"set scan frequency to (idle: %d, finger: %d, stylus: %d)\n",
2508c2ecf20Sopenharmony_ci		idle, finger, stylus);
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	return zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf));
2538c2ecf20Sopenharmony_ci}
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_cistatic int zforce_setconfig(struct zforce_ts *ts, char b1)
2568c2ecf20Sopenharmony_ci{
2578c2ecf20Sopenharmony_ci	struct i2c_client *client = ts->client;
2588c2ecf20Sopenharmony_ci	char buf[7] = { FRAME_START, 5, COMMAND_SETCONFIG,
2598c2ecf20Sopenharmony_ci			b1, 0, 0, 0 };
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "set config to (%d)\n", b1);
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	return zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf));
2648c2ecf20Sopenharmony_ci}
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_cistatic int zforce_start(struct zforce_ts *ts)
2678c2ecf20Sopenharmony_ci{
2688c2ecf20Sopenharmony_ci	struct i2c_client *client = ts->client;
2698c2ecf20Sopenharmony_ci	const struct zforce_ts_platdata *pdata = ts->pdata;
2708c2ecf20Sopenharmony_ci	int ret;
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "starting device\n");
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	ret = zforce_command_wait(ts, COMMAND_INITIALIZE);
2758c2ecf20Sopenharmony_ci	if (ret) {
2768c2ecf20Sopenharmony_ci		dev_err(&client->dev, "Unable to initialize, %d\n", ret);
2778c2ecf20Sopenharmony_ci		return ret;
2788c2ecf20Sopenharmony_ci	}
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	ret = zforce_resolution(ts, pdata->x_max, pdata->y_max);
2818c2ecf20Sopenharmony_ci	if (ret) {
2828c2ecf20Sopenharmony_ci		dev_err(&client->dev, "Unable to set resolution, %d\n", ret);
2838c2ecf20Sopenharmony_ci		goto error;
2848c2ecf20Sopenharmony_ci	}
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	ret = zforce_scan_frequency(ts, 10, 50, 50);
2878c2ecf20Sopenharmony_ci	if (ret) {
2888c2ecf20Sopenharmony_ci		dev_err(&client->dev, "Unable to set scan frequency, %d\n",
2898c2ecf20Sopenharmony_ci			ret);
2908c2ecf20Sopenharmony_ci		goto error;
2918c2ecf20Sopenharmony_ci	}
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	ret = zforce_setconfig(ts, SETCONFIG_DUALTOUCH);
2948c2ecf20Sopenharmony_ci	if (ret) {
2958c2ecf20Sopenharmony_ci		dev_err(&client->dev, "Unable to set config\n");
2968c2ecf20Sopenharmony_ci		goto error;
2978c2ecf20Sopenharmony_ci	}
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	/* start sending touch events */
3008c2ecf20Sopenharmony_ci	ret = zforce_command(ts, COMMAND_DATAREQUEST);
3018c2ecf20Sopenharmony_ci	if (ret) {
3028c2ecf20Sopenharmony_ci		dev_err(&client->dev, "Unable to request data\n");
3038c2ecf20Sopenharmony_ci		goto error;
3048c2ecf20Sopenharmony_ci	}
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	/*
3078c2ecf20Sopenharmony_ci	 * Per NN, initial cal. take max. of 200msec.
3088c2ecf20Sopenharmony_ci	 * Allow time to complete this calibration
3098c2ecf20Sopenharmony_ci	 */
3108c2ecf20Sopenharmony_ci	msleep(200);
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	return 0;
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_cierror:
3158c2ecf20Sopenharmony_ci	zforce_command_wait(ts, COMMAND_DEACTIVATE);
3168c2ecf20Sopenharmony_ci	return ret;
3178c2ecf20Sopenharmony_ci}
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_cistatic int zforce_stop(struct zforce_ts *ts)
3208c2ecf20Sopenharmony_ci{
3218c2ecf20Sopenharmony_ci	struct i2c_client *client = ts->client;
3228c2ecf20Sopenharmony_ci	int ret;
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "stopping device\n");
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	/* Deactivates touch sensing and puts the device into sleep. */
3278c2ecf20Sopenharmony_ci	ret = zforce_command_wait(ts, COMMAND_DEACTIVATE);
3288c2ecf20Sopenharmony_ci	if (ret != 0) {
3298c2ecf20Sopenharmony_ci		dev_err(&client->dev, "could not deactivate device, %d\n",
3308c2ecf20Sopenharmony_ci			ret);
3318c2ecf20Sopenharmony_ci		return ret;
3328c2ecf20Sopenharmony_ci	}
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	return 0;
3358c2ecf20Sopenharmony_ci}
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_cistatic int zforce_touch_event(struct zforce_ts *ts, u8 *payload)
3388c2ecf20Sopenharmony_ci{
3398c2ecf20Sopenharmony_ci	struct i2c_client *client = ts->client;
3408c2ecf20Sopenharmony_ci	const struct zforce_ts_platdata *pdata = ts->pdata;
3418c2ecf20Sopenharmony_ci	struct zforce_point point;
3428c2ecf20Sopenharmony_ci	int count, i, num = 0;
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci	count = payload[0];
3458c2ecf20Sopenharmony_ci	if (count > ZFORCE_REPORT_POINTS) {
3468c2ecf20Sopenharmony_ci		dev_warn(&client->dev,
3478c2ecf20Sopenharmony_ci			 "too many coordinates %d, expected max %d\n",
3488c2ecf20Sopenharmony_ci			 count, ZFORCE_REPORT_POINTS);
3498c2ecf20Sopenharmony_ci		count = ZFORCE_REPORT_POINTS;
3508c2ecf20Sopenharmony_ci	}
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci	for (i = 0; i < count; i++) {
3538c2ecf20Sopenharmony_ci		point.coord_x =
3548c2ecf20Sopenharmony_ci			payload[9 * i + 2] << 8 | payload[9 * i + 1];
3558c2ecf20Sopenharmony_ci		point.coord_y =
3568c2ecf20Sopenharmony_ci			payload[9 * i + 4] << 8 | payload[9 * i + 3];
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci		if (point.coord_x > pdata->x_max ||
3598c2ecf20Sopenharmony_ci		    point.coord_y > pdata->y_max) {
3608c2ecf20Sopenharmony_ci			dev_warn(&client->dev, "coordinates (%d,%d) invalid\n",
3618c2ecf20Sopenharmony_ci				point.coord_x, point.coord_y);
3628c2ecf20Sopenharmony_ci			point.coord_x = point.coord_y = 0;
3638c2ecf20Sopenharmony_ci		}
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci		point.state = payload[9 * i + 5] & 0x0f;
3668c2ecf20Sopenharmony_ci		point.id = (payload[9 * i + 5] & 0xf0) >> 4;
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci		/* determine touch major, minor and orientation */
3698c2ecf20Sopenharmony_ci		point.area_major = max(payload[9 * i + 6],
3708c2ecf20Sopenharmony_ci					  payload[9 * i + 7]);
3718c2ecf20Sopenharmony_ci		point.area_minor = min(payload[9 * i + 6],
3728c2ecf20Sopenharmony_ci					  payload[9 * i + 7]);
3738c2ecf20Sopenharmony_ci		point.orientation = payload[9 * i + 6] > payload[9 * i + 7];
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci		point.pressure = payload[9 * i + 8];
3768c2ecf20Sopenharmony_ci		point.prblty = payload[9 * i + 9];
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci		dev_dbg(&client->dev,
3798c2ecf20Sopenharmony_ci			"point %d/%d: state %d, id %d, pressure %d, prblty %d, x %d, y %d, amajor %d, aminor %d, ori %d\n",
3808c2ecf20Sopenharmony_ci			i, count, point.state, point.id,
3818c2ecf20Sopenharmony_ci			point.pressure, point.prblty,
3828c2ecf20Sopenharmony_ci			point.coord_x, point.coord_y,
3838c2ecf20Sopenharmony_ci			point.area_major, point.area_minor,
3848c2ecf20Sopenharmony_ci			point.orientation);
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci		/* the zforce id starts with "1", so needs to be decreased */
3878c2ecf20Sopenharmony_ci		input_mt_slot(ts->input, point.id - 1);
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci		input_mt_report_slot_state(ts->input, MT_TOOL_FINGER,
3908c2ecf20Sopenharmony_ci						point.state != STATE_UP);
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci		if (point.state != STATE_UP) {
3938c2ecf20Sopenharmony_ci			input_report_abs(ts->input, ABS_MT_POSITION_X,
3948c2ecf20Sopenharmony_ci					 point.coord_x);
3958c2ecf20Sopenharmony_ci			input_report_abs(ts->input, ABS_MT_POSITION_Y,
3968c2ecf20Sopenharmony_ci					 point.coord_y);
3978c2ecf20Sopenharmony_ci			input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR,
3988c2ecf20Sopenharmony_ci					 point.area_major);
3998c2ecf20Sopenharmony_ci			input_report_abs(ts->input, ABS_MT_TOUCH_MINOR,
4008c2ecf20Sopenharmony_ci					 point.area_minor);
4018c2ecf20Sopenharmony_ci			input_report_abs(ts->input, ABS_MT_ORIENTATION,
4028c2ecf20Sopenharmony_ci					 point.orientation);
4038c2ecf20Sopenharmony_ci			num++;
4048c2ecf20Sopenharmony_ci		}
4058c2ecf20Sopenharmony_ci	}
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	input_mt_sync_frame(ts->input);
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	input_mt_report_finger_count(ts->input, num);
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	input_sync(ts->input);
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	return 0;
4148c2ecf20Sopenharmony_ci}
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_cistatic int zforce_read_packet(struct zforce_ts *ts, u8 *buf)
4178c2ecf20Sopenharmony_ci{
4188c2ecf20Sopenharmony_ci	struct i2c_client *client = ts->client;
4198c2ecf20Sopenharmony_ci	int ret;
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	mutex_lock(&ts->access_mutex);
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci	/* read 2 byte message header */
4248c2ecf20Sopenharmony_ci	ret = i2c_master_recv(client, buf, 2);
4258c2ecf20Sopenharmony_ci	if (ret < 0) {
4268c2ecf20Sopenharmony_ci		dev_err(&client->dev, "error reading header: %d\n", ret);
4278c2ecf20Sopenharmony_ci		goto unlock;
4288c2ecf20Sopenharmony_ci	}
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci	if (buf[PAYLOAD_HEADER] != FRAME_START) {
4318c2ecf20Sopenharmony_ci		dev_err(&client->dev, "invalid frame start: %d\n", buf[0]);
4328c2ecf20Sopenharmony_ci		ret = -EIO;
4338c2ecf20Sopenharmony_ci		goto unlock;
4348c2ecf20Sopenharmony_ci	}
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	if (buf[PAYLOAD_LENGTH] == 0) {
4378c2ecf20Sopenharmony_ci		dev_err(&client->dev, "invalid payload length: %d\n",
4388c2ecf20Sopenharmony_ci			buf[PAYLOAD_LENGTH]);
4398c2ecf20Sopenharmony_ci		ret = -EIO;
4408c2ecf20Sopenharmony_ci		goto unlock;
4418c2ecf20Sopenharmony_ci	}
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci	/* read the message */
4448c2ecf20Sopenharmony_ci	ret = i2c_master_recv(client, &buf[PAYLOAD_BODY], buf[PAYLOAD_LENGTH]);
4458c2ecf20Sopenharmony_ci	if (ret < 0) {
4468c2ecf20Sopenharmony_ci		dev_err(&client->dev, "error reading payload: %d\n", ret);
4478c2ecf20Sopenharmony_ci		goto unlock;
4488c2ecf20Sopenharmony_ci	}
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "read %d bytes for response command 0x%x\n",
4518c2ecf20Sopenharmony_ci		buf[PAYLOAD_LENGTH], buf[PAYLOAD_BODY]);
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ciunlock:
4548c2ecf20Sopenharmony_ci	mutex_unlock(&ts->access_mutex);
4558c2ecf20Sopenharmony_ci	return ret;
4568c2ecf20Sopenharmony_ci}
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_cistatic void zforce_complete(struct zforce_ts *ts, int cmd, int result)
4598c2ecf20Sopenharmony_ci{
4608c2ecf20Sopenharmony_ci	struct i2c_client *client = ts->client;
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	if (ts->command_waiting == cmd) {
4638c2ecf20Sopenharmony_ci		dev_dbg(&client->dev, "completing command 0x%x\n", cmd);
4648c2ecf20Sopenharmony_ci		ts->command_result = result;
4658c2ecf20Sopenharmony_ci		complete(&ts->command_done);
4668c2ecf20Sopenharmony_ci	} else {
4678c2ecf20Sopenharmony_ci		dev_dbg(&client->dev, "command %d not for us\n", cmd);
4688c2ecf20Sopenharmony_ci	}
4698c2ecf20Sopenharmony_ci}
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_cistatic irqreturn_t zforce_irq(int irq, void *dev_id)
4728c2ecf20Sopenharmony_ci{
4738c2ecf20Sopenharmony_ci	struct zforce_ts *ts = dev_id;
4748c2ecf20Sopenharmony_ci	struct i2c_client *client = ts->client;
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_ci	if (ts->suspended && device_may_wakeup(&client->dev))
4778c2ecf20Sopenharmony_ci		pm_wakeup_event(&client->dev, 500);
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ci	return IRQ_WAKE_THREAD;
4808c2ecf20Sopenharmony_ci}
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_cistatic irqreturn_t zforce_irq_thread(int irq, void *dev_id)
4838c2ecf20Sopenharmony_ci{
4848c2ecf20Sopenharmony_ci	struct zforce_ts *ts = dev_id;
4858c2ecf20Sopenharmony_ci	struct i2c_client *client = ts->client;
4868c2ecf20Sopenharmony_ci	int ret;
4878c2ecf20Sopenharmony_ci	u8 payload_buffer[FRAME_MAXSIZE];
4888c2ecf20Sopenharmony_ci	u8 *payload;
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci	/*
4918c2ecf20Sopenharmony_ci	 * When still suspended, return.
4928c2ecf20Sopenharmony_ci	 * Due to the level-interrupt we will get re-triggered later.
4938c2ecf20Sopenharmony_ci	 */
4948c2ecf20Sopenharmony_ci	if (ts->suspended) {
4958c2ecf20Sopenharmony_ci		msleep(20);
4968c2ecf20Sopenharmony_ci		return IRQ_HANDLED;
4978c2ecf20Sopenharmony_ci	}
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "handling interrupt\n");
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci	/* Don't emit wakeup events from commands run by zforce_suspend */
5028c2ecf20Sopenharmony_ci	if (!ts->suspending && device_may_wakeup(&client->dev))
5038c2ecf20Sopenharmony_ci		pm_stay_awake(&client->dev);
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	/*
5068c2ecf20Sopenharmony_ci	 * Run at least once and exit the loop if
5078c2ecf20Sopenharmony_ci	 * - the optional interrupt GPIO isn't specified
5088c2ecf20Sopenharmony_ci	 *   (there is only one packet read per ISR invocation, then)
5098c2ecf20Sopenharmony_ci	 * or
5108c2ecf20Sopenharmony_ci	 * - the GPIO isn't active any more
5118c2ecf20Sopenharmony_ci	 *   (packet read until the level GPIO indicates that there is
5128c2ecf20Sopenharmony_ci	 *    no IRQ any more)
5138c2ecf20Sopenharmony_ci	 */
5148c2ecf20Sopenharmony_ci	do {
5158c2ecf20Sopenharmony_ci		ret = zforce_read_packet(ts, payload_buffer);
5168c2ecf20Sopenharmony_ci		if (ret < 0) {
5178c2ecf20Sopenharmony_ci			dev_err(&client->dev,
5188c2ecf20Sopenharmony_ci				"could not read packet, ret: %d\n", ret);
5198c2ecf20Sopenharmony_ci			break;
5208c2ecf20Sopenharmony_ci		}
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci		payload =  &payload_buffer[PAYLOAD_BODY];
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci		switch (payload[RESPONSE_ID]) {
5258c2ecf20Sopenharmony_ci		case NOTIFICATION_TOUCH:
5268c2ecf20Sopenharmony_ci			/*
5278c2ecf20Sopenharmony_ci			 * Always report touch-events received while
5288c2ecf20Sopenharmony_ci			 * suspending, when being a wakeup source
5298c2ecf20Sopenharmony_ci			 */
5308c2ecf20Sopenharmony_ci			if (ts->suspending && device_may_wakeup(&client->dev))
5318c2ecf20Sopenharmony_ci				pm_wakeup_event(&client->dev, 500);
5328c2ecf20Sopenharmony_ci			zforce_touch_event(ts, &payload[RESPONSE_DATA]);
5338c2ecf20Sopenharmony_ci			break;
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci		case NOTIFICATION_BOOTCOMPLETE:
5368c2ecf20Sopenharmony_ci			ts->boot_complete = payload[RESPONSE_DATA];
5378c2ecf20Sopenharmony_ci			zforce_complete(ts, payload[RESPONSE_ID], 0);
5388c2ecf20Sopenharmony_ci			break;
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci		case RESPONSE_INITIALIZE:
5418c2ecf20Sopenharmony_ci		case RESPONSE_DEACTIVATE:
5428c2ecf20Sopenharmony_ci		case RESPONSE_SETCONFIG:
5438c2ecf20Sopenharmony_ci		case RESPONSE_RESOLUTION:
5448c2ecf20Sopenharmony_ci		case RESPONSE_SCANFREQ:
5458c2ecf20Sopenharmony_ci			zforce_complete(ts, payload[RESPONSE_ID],
5468c2ecf20Sopenharmony_ci					payload[RESPONSE_DATA]);
5478c2ecf20Sopenharmony_ci			break;
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci		case RESPONSE_STATUS:
5508c2ecf20Sopenharmony_ci			/*
5518c2ecf20Sopenharmony_ci			 * Version Payload Results
5528c2ecf20Sopenharmony_ci			 * [2:major] [2:minor] [2:build] [2:rev]
5538c2ecf20Sopenharmony_ci			 */
5548c2ecf20Sopenharmony_ci			ts->version_major = (payload[RESPONSE_DATA + 1] << 8) |
5558c2ecf20Sopenharmony_ci						payload[RESPONSE_DATA];
5568c2ecf20Sopenharmony_ci			ts->version_minor = (payload[RESPONSE_DATA + 3] << 8) |
5578c2ecf20Sopenharmony_ci						payload[RESPONSE_DATA + 2];
5588c2ecf20Sopenharmony_ci			ts->version_build = (payload[RESPONSE_DATA + 5] << 8) |
5598c2ecf20Sopenharmony_ci						payload[RESPONSE_DATA + 4];
5608c2ecf20Sopenharmony_ci			ts->version_rev   = (payload[RESPONSE_DATA + 7] << 8) |
5618c2ecf20Sopenharmony_ci						payload[RESPONSE_DATA + 6];
5628c2ecf20Sopenharmony_ci			dev_dbg(&ts->client->dev,
5638c2ecf20Sopenharmony_ci				"Firmware Version %04x:%04x %04x:%04x\n",
5648c2ecf20Sopenharmony_ci				ts->version_major, ts->version_minor,
5658c2ecf20Sopenharmony_ci				ts->version_build, ts->version_rev);
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_ci			zforce_complete(ts, payload[RESPONSE_ID], 0);
5688c2ecf20Sopenharmony_ci			break;
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci		case NOTIFICATION_INVALID_COMMAND:
5718c2ecf20Sopenharmony_ci			dev_err(&ts->client->dev, "invalid command: 0x%x\n",
5728c2ecf20Sopenharmony_ci				payload[RESPONSE_DATA]);
5738c2ecf20Sopenharmony_ci			break;
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci		default:
5768c2ecf20Sopenharmony_ci			dev_err(&ts->client->dev,
5778c2ecf20Sopenharmony_ci				"unrecognized response id: 0x%x\n",
5788c2ecf20Sopenharmony_ci				payload[RESPONSE_ID]);
5798c2ecf20Sopenharmony_ci			break;
5808c2ecf20Sopenharmony_ci		}
5818c2ecf20Sopenharmony_ci	} while (gpiod_get_value_cansleep(ts->gpio_int));
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	if (!ts->suspending && device_may_wakeup(&client->dev))
5848c2ecf20Sopenharmony_ci		pm_relax(&client->dev);
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "finished interrupt\n");
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
5898c2ecf20Sopenharmony_ci}
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_cistatic int zforce_input_open(struct input_dev *dev)
5928c2ecf20Sopenharmony_ci{
5938c2ecf20Sopenharmony_ci	struct zforce_ts *ts = input_get_drvdata(dev);
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	return zforce_start(ts);
5968c2ecf20Sopenharmony_ci}
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_cistatic void zforce_input_close(struct input_dev *dev)
5998c2ecf20Sopenharmony_ci{
6008c2ecf20Sopenharmony_ci	struct zforce_ts *ts = input_get_drvdata(dev);
6018c2ecf20Sopenharmony_ci	struct i2c_client *client = ts->client;
6028c2ecf20Sopenharmony_ci	int ret;
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci	ret = zforce_stop(ts);
6058c2ecf20Sopenharmony_ci	if (ret)
6068c2ecf20Sopenharmony_ci		dev_warn(&client->dev, "stopping zforce failed\n");
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci	return;
6098c2ecf20Sopenharmony_ci}
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_cistatic int __maybe_unused zforce_suspend(struct device *dev)
6128c2ecf20Sopenharmony_ci{
6138c2ecf20Sopenharmony_ci	struct i2c_client *client = to_i2c_client(dev);
6148c2ecf20Sopenharmony_ci	struct zforce_ts *ts = i2c_get_clientdata(client);
6158c2ecf20Sopenharmony_ci	struct input_dev *input = ts->input;
6168c2ecf20Sopenharmony_ci	int ret = 0;
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci	mutex_lock(&input->mutex);
6198c2ecf20Sopenharmony_ci	ts->suspending = true;
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	/*
6228c2ecf20Sopenharmony_ci	 * When configured as a wakeup source device should always wake
6238c2ecf20Sopenharmony_ci	 * the system, therefore start device if necessary.
6248c2ecf20Sopenharmony_ci	 */
6258c2ecf20Sopenharmony_ci	if (device_may_wakeup(&client->dev)) {
6268c2ecf20Sopenharmony_ci		dev_dbg(&client->dev, "suspend while being a wakeup source\n");
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci		/* Need to start device, if not open, to be a wakeup source. */
6298c2ecf20Sopenharmony_ci		if (!input->users) {
6308c2ecf20Sopenharmony_ci			ret = zforce_start(ts);
6318c2ecf20Sopenharmony_ci			if (ret)
6328c2ecf20Sopenharmony_ci				goto unlock;
6338c2ecf20Sopenharmony_ci		}
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci		enable_irq_wake(client->irq);
6368c2ecf20Sopenharmony_ci	} else if (input->users) {
6378c2ecf20Sopenharmony_ci		dev_dbg(&client->dev,
6388c2ecf20Sopenharmony_ci			"suspend without being a wakeup source\n");
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_ci		ret = zforce_stop(ts);
6418c2ecf20Sopenharmony_ci		if (ret)
6428c2ecf20Sopenharmony_ci			goto unlock;
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci		disable_irq(client->irq);
6458c2ecf20Sopenharmony_ci	}
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci	ts->suspended = true;
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ciunlock:
6508c2ecf20Sopenharmony_ci	ts->suspending = false;
6518c2ecf20Sopenharmony_ci	mutex_unlock(&input->mutex);
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci	return ret;
6548c2ecf20Sopenharmony_ci}
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_cistatic int __maybe_unused zforce_resume(struct device *dev)
6578c2ecf20Sopenharmony_ci{
6588c2ecf20Sopenharmony_ci	struct i2c_client *client = to_i2c_client(dev);
6598c2ecf20Sopenharmony_ci	struct zforce_ts *ts = i2c_get_clientdata(client);
6608c2ecf20Sopenharmony_ci	struct input_dev *input = ts->input;
6618c2ecf20Sopenharmony_ci	int ret = 0;
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_ci	mutex_lock(&input->mutex);
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	ts->suspended = false;
6668c2ecf20Sopenharmony_ci
6678c2ecf20Sopenharmony_ci	if (device_may_wakeup(&client->dev)) {
6688c2ecf20Sopenharmony_ci		dev_dbg(&client->dev, "resume from being a wakeup source\n");
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_ci		disable_irq_wake(client->irq);
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ci		/* need to stop device if it was not open on suspend */
6738c2ecf20Sopenharmony_ci		if (!input->users) {
6748c2ecf20Sopenharmony_ci			ret = zforce_stop(ts);
6758c2ecf20Sopenharmony_ci			if (ret)
6768c2ecf20Sopenharmony_ci				goto unlock;
6778c2ecf20Sopenharmony_ci		}
6788c2ecf20Sopenharmony_ci	} else if (input->users) {
6798c2ecf20Sopenharmony_ci		dev_dbg(&client->dev, "resume without being a wakeup source\n");
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ci		enable_irq(client->irq);
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_ci		ret = zforce_start(ts);
6848c2ecf20Sopenharmony_ci		if (ret < 0)
6858c2ecf20Sopenharmony_ci			goto unlock;
6868c2ecf20Sopenharmony_ci	}
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_ciunlock:
6898c2ecf20Sopenharmony_ci	mutex_unlock(&input->mutex);
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ci	return ret;
6928c2ecf20Sopenharmony_ci}
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(zforce_pm_ops, zforce_suspend, zforce_resume);
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_cistatic void zforce_reset(void *data)
6978c2ecf20Sopenharmony_ci{
6988c2ecf20Sopenharmony_ci	struct zforce_ts *ts = data;
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci	zforce_reset_assert(ts);
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci	udelay(10);
7038c2ecf20Sopenharmony_ci
7048c2ecf20Sopenharmony_ci	if (!IS_ERR(ts->reg_vdd))
7058c2ecf20Sopenharmony_ci		regulator_disable(ts->reg_vdd);
7068c2ecf20Sopenharmony_ci}
7078c2ecf20Sopenharmony_ci
7088c2ecf20Sopenharmony_cistatic struct zforce_ts_platdata *zforce_parse_dt(struct device *dev)
7098c2ecf20Sopenharmony_ci{
7108c2ecf20Sopenharmony_ci	struct zforce_ts_platdata *pdata;
7118c2ecf20Sopenharmony_ci	struct device_node *np = dev->of_node;
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_ci	if (!np)
7148c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOENT);
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
7178c2ecf20Sopenharmony_ci	if (!pdata) {
7188c2ecf20Sopenharmony_ci		dev_err(dev, "failed to allocate platform data\n");
7198c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
7208c2ecf20Sopenharmony_ci	}
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ci	if (of_property_read_u32(np, "x-size", &pdata->x_max)) {
7238c2ecf20Sopenharmony_ci		dev_err(dev, "failed to get x-size property\n");
7248c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
7258c2ecf20Sopenharmony_ci	}
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci	if (of_property_read_u32(np, "y-size", &pdata->y_max)) {
7288c2ecf20Sopenharmony_ci		dev_err(dev, "failed to get y-size property\n");
7298c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
7308c2ecf20Sopenharmony_ci	}
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_ci	return pdata;
7338c2ecf20Sopenharmony_ci}
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_cistatic int zforce_probe(struct i2c_client *client,
7368c2ecf20Sopenharmony_ci			const struct i2c_device_id *id)
7378c2ecf20Sopenharmony_ci{
7388c2ecf20Sopenharmony_ci	const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev);
7398c2ecf20Sopenharmony_ci	struct zforce_ts *ts;
7408c2ecf20Sopenharmony_ci	struct input_dev *input_dev;
7418c2ecf20Sopenharmony_ci	int ret;
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_ci	if (!pdata) {
7448c2ecf20Sopenharmony_ci		pdata = zforce_parse_dt(&client->dev);
7458c2ecf20Sopenharmony_ci		if (IS_ERR(pdata))
7468c2ecf20Sopenharmony_ci			return PTR_ERR(pdata);
7478c2ecf20Sopenharmony_ci	}
7488c2ecf20Sopenharmony_ci
7498c2ecf20Sopenharmony_ci	ts = devm_kzalloc(&client->dev, sizeof(struct zforce_ts), GFP_KERNEL);
7508c2ecf20Sopenharmony_ci	if (!ts)
7518c2ecf20Sopenharmony_ci		return -ENOMEM;
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_ci	ts->gpio_rst = devm_gpiod_get_optional(&client->dev, "reset",
7548c2ecf20Sopenharmony_ci					       GPIOD_OUT_HIGH);
7558c2ecf20Sopenharmony_ci	if (IS_ERR(ts->gpio_rst)) {
7568c2ecf20Sopenharmony_ci		ret = PTR_ERR(ts->gpio_rst);
7578c2ecf20Sopenharmony_ci		dev_err(&client->dev,
7588c2ecf20Sopenharmony_ci			"failed to request reset GPIO: %d\n", ret);
7598c2ecf20Sopenharmony_ci		return ret;
7608c2ecf20Sopenharmony_ci	}
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci	if (ts->gpio_rst) {
7638c2ecf20Sopenharmony_ci		ts->gpio_int = devm_gpiod_get_optional(&client->dev, "irq",
7648c2ecf20Sopenharmony_ci						       GPIOD_IN);
7658c2ecf20Sopenharmony_ci		if (IS_ERR(ts->gpio_int)) {
7668c2ecf20Sopenharmony_ci			ret = PTR_ERR(ts->gpio_int);
7678c2ecf20Sopenharmony_ci			dev_err(&client->dev,
7688c2ecf20Sopenharmony_ci				"failed to request interrupt GPIO: %d\n", ret);
7698c2ecf20Sopenharmony_ci			return ret;
7708c2ecf20Sopenharmony_ci		}
7718c2ecf20Sopenharmony_ci	} else {
7728c2ecf20Sopenharmony_ci		/*
7738c2ecf20Sopenharmony_ci		 * Deprecated GPIO handling for compatibility
7748c2ecf20Sopenharmony_ci		 * with legacy binding.
7758c2ecf20Sopenharmony_ci		 */
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_ci		/* INT GPIO */
7788c2ecf20Sopenharmony_ci		ts->gpio_int = devm_gpiod_get_index(&client->dev, NULL, 0,
7798c2ecf20Sopenharmony_ci						    GPIOD_IN);
7808c2ecf20Sopenharmony_ci		if (IS_ERR(ts->gpio_int)) {
7818c2ecf20Sopenharmony_ci			ret = PTR_ERR(ts->gpio_int);
7828c2ecf20Sopenharmony_ci			dev_err(&client->dev,
7838c2ecf20Sopenharmony_ci				"failed to request interrupt GPIO: %d\n", ret);
7848c2ecf20Sopenharmony_ci			return ret;
7858c2ecf20Sopenharmony_ci		}
7868c2ecf20Sopenharmony_ci
7878c2ecf20Sopenharmony_ci		/* RST GPIO */
7888c2ecf20Sopenharmony_ci		ts->gpio_rst = devm_gpiod_get_index(&client->dev, NULL, 1,
7898c2ecf20Sopenharmony_ci					    GPIOD_OUT_HIGH);
7908c2ecf20Sopenharmony_ci		if (IS_ERR(ts->gpio_rst)) {
7918c2ecf20Sopenharmony_ci			ret = PTR_ERR(ts->gpio_rst);
7928c2ecf20Sopenharmony_ci			dev_err(&client->dev,
7938c2ecf20Sopenharmony_ci				"failed to request reset GPIO: %d\n", ret);
7948c2ecf20Sopenharmony_ci			return ret;
7958c2ecf20Sopenharmony_ci		}
7968c2ecf20Sopenharmony_ci	}
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_ci	ts->reg_vdd = devm_regulator_get_optional(&client->dev, "vdd");
7998c2ecf20Sopenharmony_ci	if (IS_ERR(ts->reg_vdd)) {
8008c2ecf20Sopenharmony_ci		ret = PTR_ERR(ts->reg_vdd);
8018c2ecf20Sopenharmony_ci		if (ret == -EPROBE_DEFER)
8028c2ecf20Sopenharmony_ci			return ret;
8038c2ecf20Sopenharmony_ci	} else {
8048c2ecf20Sopenharmony_ci		ret = regulator_enable(ts->reg_vdd);
8058c2ecf20Sopenharmony_ci		if (ret)
8068c2ecf20Sopenharmony_ci			return ret;
8078c2ecf20Sopenharmony_ci
8088c2ecf20Sopenharmony_ci		/*
8098c2ecf20Sopenharmony_ci		 * according to datasheet add 100us grace time after regular
8108c2ecf20Sopenharmony_ci		 * regulator enable delay.
8118c2ecf20Sopenharmony_ci		 */
8128c2ecf20Sopenharmony_ci		udelay(100);
8138c2ecf20Sopenharmony_ci	}
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci	ret = devm_add_action(&client->dev, zforce_reset, ts);
8168c2ecf20Sopenharmony_ci	if (ret) {
8178c2ecf20Sopenharmony_ci		dev_err(&client->dev, "failed to register reset action, %d\n",
8188c2ecf20Sopenharmony_ci			ret);
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci		/* hereafter the regulator will be disabled by the action */
8218c2ecf20Sopenharmony_ci		if (!IS_ERR(ts->reg_vdd))
8228c2ecf20Sopenharmony_ci			regulator_disable(ts->reg_vdd);
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci		return ret;
8258c2ecf20Sopenharmony_ci	}
8268c2ecf20Sopenharmony_ci
8278c2ecf20Sopenharmony_ci	snprintf(ts->phys, sizeof(ts->phys),
8288c2ecf20Sopenharmony_ci		 "%s/input0", dev_name(&client->dev));
8298c2ecf20Sopenharmony_ci
8308c2ecf20Sopenharmony_ci	input_dev = devm_input_allocate_device(&client->dev);
8318c2ecf20Sopenharmony_ci	if (!input_dev) {
8328c2ecf20Sopenharmony_ci		dev_err(&client->dev, "could not allocate input device\n");
8338c2ecf20Sopenharmony_ci		return -ENOMEM;
8348c2ecf20Sopenharmony_ci	}
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci	mutex_init(&ts->access_mutex);
8378c2ecf20Sopenharmony_ci	mutex_init(&ts->command_mutex);
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_ci	ts->pdata = pdata;
8408c2ecf20Sopenharmony_ci	ts->client = client;
8418c2ecf20Sopenharmony_ci	ts->input = input_dev;
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_ci	input_dev->name = "Neonode zForce touchscreen";
8448c2ecf20Sopenharmony_ci	input_dev->phys = ts->phys;
8458c2ecf20Sopenharmony_ci	input_dev->id.bustype = BUS_I2C;
8468c2ecf20Sopenharmony_ci
8478c2ecf20Sopenharmony_ci	input_dev->open = zforce_input_open;
8488c2ecf20Sopenharmony_ci	input_dev->close = zforce_input_close;
8498c2ecf20Sopenharmony_ci
8508c2ecf20Sopenharmony_ci	__set_bit(EV_KEY, input_dev->evbit);
8518c2ecf20Sopenharmony_ci	__set_bit(EV_SYN, input_dev->evbit);
8528c2ecf20Sopenharmony_ci	__set_bit(EV_ABS, input_dev->evbit);
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_ci	/* For multi touch */
8558c2ecf20Sopenharmony_ci	input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0,
8568c2ecf20Sopenharmony_ci			     pdata->x_max, 0, 0);
8578c2ecf20Sopenharmony_ci	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0,
8588c2ecf20Sopenharmony_ci			     pdata->y_max, 0, 0);
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0,
8618c2ecf20Sopenharmony_ci			     ZFORCE_MAX_AREA, 0, 0);
8628c2ecf20Sopenharmony_ci	input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, 0,
8638c2ecf20Sopenharmony_ci			     ZFORCE_MAX_AREA, 0, 0);
8648c2ecf20Sopenharmony_ci	input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0);
8658c2ecf20Sopenharmony_ci	input_mt_init_slots(input_dev, ZFORCE_REPORT_POINTS, INPUT_MT_DIRECT);
8668c2ecf20Sopenharmony_ci
8678c2ecf20Sopenharmony_ci	input_set_drvdata(ts->input, ts);
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci	init_completion(&ts->command_done);
8708c2ecf20Sopenharmony_ci
8718c2ecf20Sopenharmony_ci	/*
8728c2ecf20Sopenharmony_ci	 * The zforce pulls the interrupt low when it has data ready.
8738c2ecf20Sopenharmony_ci	 * After it is triggered the isr thread runs until all the available
8748c2ecf20Sopenharmony_ci	 * packets have been read and the interrupt is high again.
8758c2ecf20Sopenharmony_ci	 * Therefore we can trigger the interrupt anytime it is low and do
8768c2ecf20Sopenharmony_ci	 * not need to limit it to the interrupt edge.
8778c2ecf20Sopenharmony_ci	 */
8788c2ecf20Sopenharmony_ci	ret = devm_request_threaded_irq(&client->dev, client->irq,
8798c2ecf20Sopenharmony_ci					zforce_irq, zforce_irq_thread,
8808c2ecf20Sopenharmony_ci					IRQF_TRIGGER_LOW | IRQF_ONESHOT,
8818c2ecf20Sopenharmony_ci					input_dev->name, ts);
8828c2ecf20Sopenharmony_ci	if (ret) {
8838c2ecf20Sopenharmony_ci		dev_err(&client->dev, "irq %d request failed\n", client->irq);
8848c2ecf20Sopenharmony_ci		return ret;
8858c2ecf20Sopenharmony_ci	}
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_ci	i2c_set_clientdata(client, ts);
8888c2ecf20Sopenharmony_ci
8898c2ecf20Sopenharmony_ci	/* let the controller boot */
8908c2ecf20Sopenharmony_ci	zforce_reset_deassert(ts);
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_ci	ts->command_waiting = NOTIFICATION_BOOTCOMPLETE;
8938c2ecf20Sopenharmony_ci	if (wait_for_completion_timeout(&ts->command_done, WAIT_TIMEOUT) == 0)
8948c2ecf20Sopenharmony_ci		dev_warn(&client->dev, "bootcomplete timed out\n");
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ci	/* need to start device to get version information */
8978c2ecf20Sopenharmony_ci	ret = zforce_command_wait(ts, COMMAND_INITIALIZE);
8988c2ecf20Sopenharmony_ci	if (ret) {
8998c2ecf20Sopenharmony_ci		dev_err(&client->dev, "unable to initialize, %d\n", ret);
9008c2ecf20Sopenharmony_ci		return ret;
9018c2ecf20Sopenharmony_ci	}
9028c2ecf20Sopenharmony_ci
9038c2ecf20Sopenharmony_ci	/* this gets the firmware version among other information */
9048c2ecf20Sopenharmony_ci	ret = zforce_command_wait(ts, COMMAND_STATUS);
9058c2ecf20Sopenharmony_ci	if (ret < 0) {
9068c2ecf20Sopenharmony_ci		dev_err(&client->dev, "couldn't get status, %d\n", ret);
9078c2ecf20Sopenharmony_ci		zforce_stop(ts);
9088c2ecf20Sopenharmony_ci		return ret;
9098c2ecf20Sopenharmony_ci	}
9108c2ecf20Sopenharmony_ci
9118c2ecf20Sopenharmony_ci	/* stop device and put it into sleep until it is opened */
9128c2ecf20Sopenharmony_ci	ret = zforce_stop(ts);
9138c2ecf20Sopenharmony_ci	if (ret < 0)
9148c2ecf20Sopenharmony_ci		return ret;
9158c2ecf20Sopenharmony_ci
9168c2ecf20Sopenharmony_ci	device_set_wakeup_capable(&client->dev, true);
9178c2ecf20Sopenharmony_ci
9188c2ecf20Sopenharmony_ci	ret = input_register_device(input_dev);
9198c2ecf20Sopenharmony_ci	if (ret) {
9208c2ecf20Sopenharmony_ci		dev_err(&client->dev, "could not register input device, %d\n",
9218c2ecf20Sopenharmony_ci			ret);
9228c2ecf20Sopenharmony_ci		return ret;
9238c2ecf20Sopenharmony_ci	}
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_ci	return 0;
9268c2ecf20Sopenharmony_ci}
9278c2ecf20Sopenharmony_ci
9288c2ecf20Sopenharmony_cistatic struct i2c_device_id zforce_idtable[] = {
9298c2ecf20Sopenharmony_ci	{ "zforce-ts", 0 },
9308c2ecf20Sopenharmony_ci	{ }
9318c2ecf20Sopenharmony_ci};
9328c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, zforce_idtable);
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_ci#ifdef CONFIG_OF
9358c2ecf20Sopenharmony_cistatic const struct of_device_id zforce_dt_idtable[] = {
9368c2ecf20Sopenharmony_ci	{ .compatible = "neonode,zforce" },
9378c2ecf20Sopenharmony_ci	{},
9388c2ecf20Sopenharmony_ci};
9398c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, zforce_dt_idtable);
9408c2ecf20Sopenharmony_ci#endif
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_cistatic struct i2c_driver zforce_driver = {
9438c2ecf20Sopenharmony_ci	.driver = {
9448c2ecf20Sopenharmony_ci		.name	= "zforce-ts",
9458c2ecf20Sopenharmony_ci		.pm	= &zforce_pm_ops,
9468c2ecf20Sopenharmony_ci		.of_match_table	= of_match_ptr(zforce_dt_idtable),
9478c2ecf20Sopenharmony_ci	},
9488c2ecf20Sopenharmony_ci	.probe		= zforce_probe,
9498c2ecf20Sopenharmony_ci	.id_table	= zforce_idtable,
9508c2ecf20Sopenharmony_ci};
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_cimodule_i2c_driver(zforce_driver);
9538c2ecf20Sopenharmony_ci
9548c2ecf20Sopenharmony_ciMODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
9558c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("zForce TouchScreen Driver");
9568c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
957