1c6d81bd7SHeiko Stübner /*
2c6d81bd7SHeiko Stübner  * Copyright (C) 2012-2013 MundoReader S.L.
3c6d81bd7SHeiko Stübner  * Author: Heiko Stuebner <heiko@sntech.de>
4c6d81bd7SHeiko Stübner  *
5c6d81bd7SHeiko Stübner  * based in parts on Nook zforce driver
6c6d81bd7SHeiko Stübner  *
7c6d81bd7SHeiko Stübner  * Copyright (C) 2010 Barnes & Noble, Inc.
8c6d81bd7SHeiko Stübner  * Author: Pieter Truter<ptruter@intrinsyc.com>
9c6d81bd7SHeiko Stübner  *
10c6d81bd7SHeiko Stübner  * This software is licensed under the terms of the GNU General Public
11c6d81bd7SHeiko Stübner  * License version 2, as published by the Free Software Foundation, and
12c6d81bd7SHeiko Stübner  * may be copied, distributed, and modified under those terms.
13c6d81bd7SHeiko Stübner  *
14c6d81bd7SHeiko Stübner  * This program is distributed in the hope that it will be useful,
15c6d81bd7SHeiko Stübner  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16c6d81bd7SHeiko Stübner  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17c6d81bd7SHeiko Stübner  * GNU General Public License for more details.
18c6d81bd7SHeiko Stübner  */
19c6d81bd7SHeiko Stübner 
20c6d81bd7SHeiko Stübner #include <linux/module.h>
21c6d81bd7SHeiko Stübner #include <linux/hrtimer.h>
22c6d81bd7SHeiko Stübner #include <linux/slab.h>
23c6d81bd7SHeiko Stübner #include <linux/input.h>
24c6d81bd7SHeiko Stübner #include <linux/interrupt.h>
25c6d81bd7SHeiko Stübner #include <linux/i2c.h>
26c6d81bd7SHeiko Stübner #include <linux/delay.h>
27c6d81bd7SHeiko Stübner #include <linux/gpio.h>
28c6d81bd7SHeiko Stübner #include <linux/device.h>
29c6d81bd7SHeiko Stübner #include <linux/sysfs.h>
30c6d81bd7SHeiko Stübner #include <linux/input/mt.h>
31c6d81bd7SHeiko Stübner #include <linux/platform_data/zforce_ts.h>
32c6d81bd7SHeiko Stübner 
33c6d81bd7SHeiko Stübner #define WAIT_TIMEOUT		msecs_to_jiffies(1000)
34c6d81bd7SHeiko Stübner 
35c6d81bd7SHeiko Stübner #define FRAME_START		0xee
36d333b606SLuis Ortega #define FRAME_MAXSIZE		257
37c6d81bd7SHeiko Stübner 
38c6d81bd7SHeiko Stübner /* Offsets of the different parts of the payload the controller sends */
39c6d81bd7SHeiko Stübner #define PAYLOAD_HEADER		0
40c6d81bd7SHeiko Stübner #define PAYLOAD_LENGTH		1
41c6d81bd7SHeiko Stübner #define PAYLOAD_BODY		2
42c6d81bd7SHeiko Stübner 
43c6d81bd7SHeiko Stübner /* Response offsets */
44c6d81bd7SHeiko Stübner #define RESPONSE_ID		0
45c6d81bd7SHeiko Stübner #define RESPONSE_DATA		1
46c6d81bd7SHeiko Stübner 
47c6d81bd7SHeiko Stübner /* Commands */
48c6d81bd7SHeiko Stübner #define COMMAND_DEACTIVATE	0x00
49c6d81bd7SHeiko Stübner #define COMMAND_INITIALIZE	0x01
50c6d81bd7SHeiko Stübner #define COMMAND_RESOLUTION	0x02
51c6d81bd7SHeiko Stübner #define COMMAND_SETCONFIG	0x03
52c6d81bd7SHeiko Stübner #define COMMAND_DATAREQUEST	0x04
53c6d81bd7SHeiko Stübner #define COMMAND_SCANFREQ	0x08
54c6d81bd7SHeiko Stübner #define COMMAND_STATUS		0X1e
55c6d81bd7SHeiko Stübner 
56c6d81bd7SHeiko Stübner /*
57c6d81bd7SHeiko Stübner  * Responses the controller sends as a result of
58c6d81bd7SHeiko Stübner  * command requests
59c6d81bd7SHeiko Stübner  */
60c6d81bd7SHeiko Stübner #define RESPONSE_DEACTIVATE	0x00
61c6d81bd7SHeiko Stübner #define RESPONSE_INITIALIZE	0x01
62c6d81bd7SHeiko Stübner #define RESPONSE_RESOLUTION	0x02
63c6d81bd7SHeiko Stübner #define RESPONSE_SETCONFIG	0x03
64c6d81bd7SHeiko Stübner #define RESPONSE_SCANFREQ	0x08
65c6d81bd7SHeiko Stübner #define RESPONSE_STATUS		0X1e
66c6d81bd7SHeiko Stübner 
67c6d81bd7SHeiko Stübner /*
68deb49819SLuis Ortega  * Notifications are sent by the touch controller without
69c6d81bd7SHeiko Stübner  * being requested by the driver and include for example
70c6d81bd7SHeiko Stübner  * touch indications
71c6d81bd7SHeiko Stübner  */
72c6d81bd7SHeiko Stübner #define NOTIFICATION_TOUCH		0x04
73c6d81bd7SHeiko Stübner #define NOTIFICATION_BOOTCOMPLETE	0x07
74c6d81bd7SHeiko Stübner #define NOTIFICATION_OVERRUN		0x25
75c6d81bd7SHeiko Stübner #define NOTIFICATION_PROXIMITY		0x26
76c6d81bd7SHeiko Stübner #define NOTIFICATION_INVALID_COMMAND	0xfe
77c6d81bd7SHeiko Stübner 
78c6d81bd7SHeiko Stübner #define ZFORCE_REPORT_POINTS		2
79c6d81bd7SHeiko Stübner #define ZFORCE_MAX_AREA			0xff
80c6d81bd7SHeiko Stübner 
81c6d81bd7SHeiko Stübner #define STATE_DOWN			0
82c6d81bd7SHeiko Stübner #define STATE_MOVE			1
83c6d81bd7SHeiko Stübner #define STATE_UP			2
84c6d81bd7SHeiko Stübner 
85c6d81bd7SHeiko Stübner #define SETCONFIG_DUALTOUCH		(1 << 0)
86c6d81bd7SHeiko Stübner 
87c6d81bd7SHeiko Stübner struct zforce_point {
88c6d81bd7SHeiko Stübner 	int coord_x;
89c6d81bd7SHeiko Stübner 	int coord_y;
90c6d81bd7SHeiko Stübner 	int state;
91c6d81bd7SHeiko Stübner 	int id;
92c6d81bd7SHeiko Stübner 	int area_major;
93c6d81bd7SHeiko Stübner 	int area_minor;
94c6d81bd7SHeiko Stübner 	int orientation;
95c6d81bd7SHeiko Stübner 	int pressure;
96c6d81bd7SHeiko Stübner 	int prblty;
97c6d81bd7SHeiko Stübner };
98c6d81bd7SHeiko Stübner 
99c6d81bd7SHeiko Stübner /*
100c6d81bd7SHeiko Stübner  * @client		the i2c_client
101c6d81bd7SHeiko Stübner  * @input		the input device
102c6d81bd7SHeiko Stübner  * @suspending		in the process of going to suspend (don't emit wakeup
103c6d81bd7SHeiko Stübner  *			events for commands executed to suspend the device)
104c6d81bd7SHeiko Stübner  * @suspended		device suspended
105c6d81bd7SHeiko Stübner  * @access_mutex	serialize i2c-access, to keep multipart reads together
106c6d81bd7SHeiko Stübner  * @command_done	completion to wait for the command result
107deb49819SLuis Ortega  * @command_mutex	serialize commands sent to the ic
108deb49819SLuis Ortega  * @command_waiting	the id of the command that is currently waiting
109c6d81bd7SHeiko Stübner  *			for a result
110c6d81bd7SHeiko Stübner  * @command_result	returned result of the command
111c6d81bd7SHeiko Stübner  */
112c6d81bd7SHeiko Stübner struct zforce_ts {
113c6d81bd7SHeiko Stübner 	struct i2c_client	*client;
114c6d81bd7SHeiko Stübner 	struct input_dev	*input;
115c6d81bd7SHeiko Stübner 	const struct zforce_ts_platdata *pdata;
116c6d81bd7SHeiko Stübner 	char			phys[32];
117c6d81bd7SHeiko Stübner 
118c6d81bd7SHeiko Stübner 	bool			suspending;
119c6d81bd7SHeiko Stübner 	bool			suspended;
120c6d81bd7SHeiko Stübner 	bool			boot_complete;
121c6d81bd7SHeiko Stübner 
122c6d81bd7SHeiko Stübner 	/* Firmware version information */
123c6d81bd7SHeiko Stübner 	u16			version_major;
124c6d81bd7SHeiko Stübner 	u16			version_minor;
125c6d81bd7SHeiko Stübner 	u16			version_build;
126c6d81bd7SHeiko Stübner 	u16			version_rev;
127c6d81bd7SHeiko Stübner 
128c6d81bd7SHeiko Stübner 	struct mutex		access_mutex;
129c6d81bd7SHeiko Stübner 
130c6d81bd7SHeiko Stübner 	struct completion	command_done;
131c6d81bd7SHeiko Stübner 	struct mutex		command_mutex;
132c6d81bd7SHeiko Stübner 	int			command_waiting;
133c6d81bd7SHeiko Stübner 	int			command_result;
134c6d81bd7SHeiko Stübner };
135c6d81bd7SHeiko Stübner 
136c6d81bd7SHeiko Stübner static int zforce_command(struct zforce_ts *ts, u8 cmd)
137c6d81bd7SHeiko Stübner {
138c6d81bd7SHeiko Stübner 	struct i2c_client *client = ts->client;
139c6d81bd7SHeiko Stübner 	char buf[3];
140c6d81bd7SHeiko Stübner 	int ret;
141c6d81bd7SHeiko Stübner 
142c6d81bd7SHeiko Stübner 	dev_dbg(&client->dev, "%s: 0x%x\n", __func__, cmd);
143c6d81bd7SHeiko Stübner 
144c6d81bd7SHeiko Stübner 	buf[0] = FRAME_START;
145c6d81bd7SHeiko Stübner 	buf[1] = 1; /* data size, command only */
146c6d81bd7SHeiko Stübner 	buf[2] = cmd;
147c6d81bd7SHeiko Stübner 
148c6d81bd7SHeiko Stübner 	mutex_lock(&ts->access_mutex);
149c6d81bd7SHeiko Stübner 	ret = i2c_master_send(client, &buf[0], ARRAY_SIZE(buf));
150c6d81bd7SHeiko Stübner 	mutex_unlock(&ts->access_mutex);
151c6d81bd7SHeiko Stübner 	if (ret < 0) {
152c6d81bd7SHeiko Stübner 		dev_err(&client->dev, "i2c send data request error: %d\n", ret);
153c6d81bd7SHeiko Stübner 		return ret;
154c6d81bd7SHeiko Stübner 	}
155c6d81bd7SHeiko Stübner 
156c6d81bd7SHeiko Stübner 	return 0;
157c6d81bd7SHeiko Stübner }
158c6d81bd7SHeiko Stübner 
159c6d81bd7SHeiko Stübner static int zforce_send_wait(struct zforce_ts *ts, const char *buf, int len)
160c6d81bd7SHeiko Stübner {
161c6d81bd7SHeiko Stübner 	struct i2c_client *client = ts->client;
162c6d81bd7SHeiko Stübner 	int ret;
163c6d81bd7SHeiko Stübner 
164c6d81bd7SHeiko Stübner 	ret = mutex_trylock(&ts->command_mutex);
165c6d81bd7SHeiko Stübner 	if (!ret) {
166c6d81bd7SHeiko Stübner 		dev_err(&client->dev, "already waiting for a command\n");
167c6d81bd7SHeiko Stübner 		return -EBUSY;
168c6d81bd7SHeiko Stübner 	}
169c6d81bd7SHeiko Stübner 
170c6d81bd7SHeiko Stübner 	dev_dbg(&client->dev, "sending %d bytes for command 0x%x\n",
171c6d81bd7SHeiko Stübner 		buf[1], buf[2]);
172c6d81bd7SHeiko Stübner 
173c6d81bd7SHeiko Stübner 	ts->command_waiting = buf[2];
174c6d81bd7SHeiko Stübner 
175c6d81bd7SHeiko Stübner 	mutex_lock(&ts->access_mutex);
176c6d81bd7SHeiko Stübner 	ret = i2c_master_send(client, buf, len);
177c6d81bd7SHeiko Stübner 	mutex_unlock(&ts->access_mutex);
178c6d81bd7SHeiko Stübner 	if (ret < 0) {
179c6d81bd7SHeiko Stübner 		dev_err(&client->dev, "i2c send data request error: %d\n", ret);
180c6d81bd7SHeiko Stübner 		goto unlock;
181c6d81bd7SHeiko Stübner 	}
182c6d81bd7SHeiko Stübner 
183c6d81bd7SHeiko Stübner 	dev_dbg(&client->dev, "waiting for result for command 0x%x\n", buf[2]);
184c6d81bd7SHeiko Stübner 
185c6d81bd7SHeiko Stübner 	if (wait_for_completion_timeout(&ts->command_done, WAIT_TIMEOUT) == 0) {
186c6d81bd7SHeiko Stübner 		ret = -ETIME;
187c6d81bd7SHeiko Stübner 		goto unlock;
188c6d81bd7SHeiko Stübner 	}
189c6d81bd7SHeiko Stübner 
190c6d81bd7SHeiko Stübner 	ret = ts->command_result;
191c6d81bd7SHeiko Stübner 
192c6d81bd7SHeiko Stübner unlock:
193c6d81bd7SHeiko Stübner 	mutex_unlock(&ts->command_mutex);
194c6d81bd7SHeiko Stübner 	return ret;
195c6d81bd7SHeiko Stübner }
196c6d81bd7SHeiko Stübner 
197c6d81bd7SHeiko Stübner static int zforce_command_wait(struct zforce_ts *ts, u8 cmd)
198c6d81bd7SHeiko Stübner {
199c6d81bd7SHeiko Stübner 	struct i2c_client *client = ts->client;
200c6d81bd7SHeiko Stübner 	char buf[3];
201c6d81bd7SHeiko Stübner 	int ret;
202c6d81bd7SHeiko Stübner 
203c6d81bd7SHeiko Stübner 	dev_dbg(&client->dev, "%s: 0x%x\n", __func__, cmd);
204c6d81bd7SHeiko Stübner 
205c6d81bd7SHeiko Stübner 	buf[0] = FRAME_START;
206c6d81bd7SHeiko Stübner 	buf[1] = 1; /* data size, command only */
207c6d81bd7SHeiko Stübner 	buf[2] = cmd;
208c6d81bd7SHeiko Stübner 
209c6d81bd7SHeiko Stübner 	ret = zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf));
210c6d81bd7SHeiko Stübner 	if (ret < 0) {
211c6d81bd7SHeiko Stübner 		dev_err(&client->dev, "i2c send data request error: %d\n", ret);
212c6d81bd7SHeiko Stübner 		return ret;
213c6d81bd7SHeiko Stübner 	}
214c6d81bd7SHeiko Stübner 
215c6d81bd7SHeiko Stübner 	return 0;
216c6d81bd7SHeiko Stübner }
217c6d81bd7SHeiko Stübner 
218c6d81bd7SHeiko Stübner static int zforce_resolution(struct zforce_ts *ts, u16 x, u16 y)
219c6d81bd7SHeiko Stübner {
220c6d81bd7SHeiko Stübner 	struct i2c_client *client = ts->client;
221c6d81bd7SHeiko Stübner 	char buf[7] = { FRAME_START, 5, COMMAND_RESOLUTION,
222c6d81bd7SHeiko Stübner 			(x & 0xff), ((x >> 8) & 0xff),
223c6d81bd7SHeiko Stübner 			(y & 0xff), ((y >> 8) & 0xff) };
224c6d81bd7SHeiko Stübner 
225c6d81bd7SHeiko Stübner 	dev_dbg(&client->dev, "set resolution to (%d,%d)\n", x, y);
226c6d81bd7SHeiko Stübner 
227c6d81bd7SHeiko Stübner 	return zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf));
228c6d81bd7SHeiko Stübner }
229c6d81bd7SHeiko Stübner 
230c6d81bd7SHeiko Stübner static int zforce_scan_frequency(struct zforce_ts *ts, u16 idle, u16 finger,
231c6d81bd7SHeiko Stübner 				 u16 stylus)
232c6d81bd7SHeiko Stübner {
233c6d81bd7SHeiko Stübner 	struct i2c_client *client = ts->client;
234c6d81bd7SHeiko Stübner 	char buf[9] = { FRAME_START, 7, COMMAND_SCANFREQ,
235c6d81bd7SHeiko Stübner 			(idle & 0xff), ((idle >> 8) & 0xff),
236c6d81bd7SHeiko Stübner 			(finger & 0xff), ((finger >> 8) & 0xff),
237c6d81bd7SHeiko Stübner 			(stylus & 0xff), ((stylus >> 8) & 0xff) };
238c6d81bd7SHeiko Stübner 
239ad697b96SLuis Ortega 	dev_dbg(&client->dev,
240ad697b96SLuis Ortega 		"set scan frequency to (idle: %d, finger: %d, stylus: %d)\n",
241c6d81bd7SHeiko Stübner 		idle, finger, stylus);
242c6d81bd7SHeiko Stübner 
243c6d81bd7SHeiko Stübner 	return zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf));
244c6d81bd7SHeiko Stübner }
245c6d81bd7SHeiko Stübner 
246c6d81bd7SHeiko Stübner static int zforce_setconfig(struct zforce_ts *ts, char b1)
247c6d81bd7SHeiko Stübner {
248c6d81bd7SHeiko Stübner 	struct i2c_client *client = ts->client;
249c6d81bd7SHeiko Stübner 	char buf[7] = { FRAME_START, 5, COMMAND_SETCONFIG,
250c6d81bd7SHeiko Stübner 			b1, 0, 0, 0 };
251c6d81bd7SHeiko Stübner 
252c6d81bd7SHeiko Stübner 	dev_dbg(&client->dev, "set config to (%d)\n", b1);
253c6d81bd7SHeiko Stübner 
254c6d81bd7SHeiko Stübner 	return zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf));
255c6d81bd7SHeiko Stübner }
256c6d81bd7SHeiko Stübner 
257c6d81bd7SHeiko Stübner static int zforce_start(struct zforce_ts *ts)
258c6d81bd7SHeiko Stübner {
259c6d81bd7SHeiko Stübner 	struct i2c_client *client = ts->client;
260c6d81bd7SHeiko Stübner 	const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev);
261c6d81bd7SHeiko Stübner 	int ret;
262c6d81bd7SHeiko Stübner 
263c6d81bd7SHeiko Stübner 	dev_dbg(&client->dev, "starting device\n");
264c6d81bd7SHeiko Stübner 
265c6d81bd7SHeiko Stübner 	ret = zforce_command_wait(ts, COMMAND_INITIALIZE);
266c6d81bd7SHeiko Stübner 	if (ret) {
267c6d81bd7SHeiko Stübner 		dev_err(&client->dev, "Unable to initialize, %d\n", ret);
268c6d81bd7SHeiko Stübner 		return ret;
269c6d81bd7SHeiko Stübner 	}
270c6d81bd7SHeiko Stübner 
271c6d81bd7SHeiko Stübner 	ret = zforce_resolution(ts, pdata->x_max, pdata->y_max);
272c6d81bd7SHeiko Stübner 	if (ret) {
273c6d81bd7SHeiko Stübner 		dev_err(&client->dev, "Unable to set resolution, %d\n", ret);
274c6d81bd7SHeiko Stübner 		goto error;
275c6d81bd7SHeiko Stübner 	}
276c6d81bd7SHeiko Stübner 
277c6d81bd7SHeiko Stübner 	ret = zforce_scan_frequency(ts, 10, 50, 50);
278c6d81bd7SHeiko Stübner 	if (ret) {
279c6d81bd7SHeiko Stübner 		dev_err(&client->dev, "Unable to set scan frequency, %d\n",
280c6d81bd7SHeiko Stübner 			ret);
281c6d81bd7SHeiko Stübner 		goto error;
282c6d81bd7SHeiko Stübner 	}
283c6d81bd7SHeiko Stübner 
2843c4396b4SWei Yongjun 	ret = zforce_setconfig(ts, SETCONFIG_DUALTOUCH);
2853c4396b4SWei Yongjun 	if (ret) {
286c6d81bd7SHeiko Stübner 		dev_err(&client->dev, "Unable to set config\n");
287c6d81bd7SHeiko Stübner 		goto error;
288c6d81bd7SHeiko Stübner 	}
289c6d81bd7SHeiko Stübner 
290c6d81bd7SHeiko Stübner 	/* start sending touch events */
291c6d81bd7SHeiko Stübner 	ret = zforce_command(ts, COMMAND_DATAREQUEST);
292c6d81bd7SHeiko Stübner 	if (ret) {
293c6d81bd7SHeiko Stübner 		dev_err(&client->dev, "Unable to request data\n");
294c6d81bd7SHeiko Stübner 		goto error;
295c6d81bd7SHeiko Stübner 	}
296c6d81bd7SHeiko Stübner 
297c6d81bd7SHeiko Stübner 	/*
298c6d81bd7SHeiko Stübner 	 * Per NN, initial cal. take max. of 200msec.
299c6d81bd7SHeiko Stübner 	 * Allow time to complete this calibration
300c6d81bd7SHeiko Stübner 	 */
301c6d81bd7SHeiko Stübner 	msleep(200);
302c6d81bd7SHeiko Stübner 
303c6d81bd7SHeiko Stübner 	return 0;
304c6d81bd7SHeiko Stübner 
305c6d81bd7SHeiko Stübner error:
306c6d81bd7SHeiko Stübner 	zforce_command_wait(ts, COMMAND_DEACTIVATE);
307c6d81bd7SHeiko Stübner 	return ret;
308c6d81bd7SHeiko Stübner }
309c6d81bd7SHeiko Stübner 
310c6d81bd7SHeiko Stübner static int zforce_stop(struct zforce_ts *ts)
311c6d81bd7SHeiko Stübner {
312c6d81bd7SHeiko Stübner 	struct i2c_client *client = ts->client;
313c6d81bd7SHeiko Stübner 	int ret;
314c6d81bd7SHeiko Stübner 
315c6d81bd7SHeiko Stübner 	dev_dbg(&client->dev, "stopping device\n");
316c6d81bd7SHeiko Stübner 
317c6d81bd7SHeiko Stübner 	/* Deactivates touch sensing and puts the device into sleep. */
318c6d81bd7SHeiko Stübner 	ret = zforce_command_wait(ts, COMMAND_DEACTIVATE);
319c6d81bd7SHeiko Stübner 	if (ret != 0) {
320c6d81bd7SHeiko Stübner 		dev_err(&client->dev, "could not deactivate device, %d\n",
321c6d81bd7SHeiko Stübner 			ret);
322c6d81bd7SHeiko Stübner 		return ret;
323c6d81bd7SHeiko Stübner 	}
324c6d81bd7SHeiko Stübner 
325c6d81bd7SHeiko Stübner 	return 0;
326c6d81bd7SHeiko Stübner }
327c6d81bd7SHeiko Stübner 
328c6d81bd7SHeiko Stübner static int zforce_touch_event(struct zforce_ts *ts, u8 *payload)
329c6d81bd7SHeiko Stübner {
330c6d81bd7SHeiko Stübner 	struct i2c_client *client = ts->client;
331c6d81bd7SHeiko Stübner 	const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev);
332c6d81bd7SHeiko Stübner 	struct zforce_point point;
333c6d81bd7SHeiko Stübner 	int count, i, num = 0;
334c6d81bd7SHeiko Stübner 
335c6d81bd7SHeiko Stübner 	count = payload[0];
336c6d81bd7SHeiko Stübner 	if (count > ZFORCE_REPORT_POINTS) {
337ad697b96SLuis Ortega 		dev_warn(&client->dev,
338ad697b96SLuis Ortega 			 "too many coordinates %d, expected max %d\n",
339c6d81bd7SHeiko Stübner 			 count, ZFORCE_REPORT_POINTS);
340c6d81bd7SHeiko Stübner 		count = ZFORCE_REPORT_POINTS;
341c6d81bd7SHeiko Stübner 	}
342c6d81bd7SHeiko Stübner 
343c6d81bd7SHeiko Stübner 	for (i = 0; i < count; i++) {
344c6d81bd7SHeiko Stübner 		point.coord_x =
345c6d81bd7SHeiko Stübner 			payload[9 * i + 2] << 8 | payload[9 * i + 1];
346c6d81bd7SHeiko Stübner 		point.coord_y =
347c6d81bd7SHeiko Stübner 			payload[9 * i + 4] << 8 | payload[9 * i + 3];
348c6d81bd7SHeiko Stübner 
349c6d81bd7SHeiko Stübner 		if (point.coord_x > pdata->x_max ||
350c6d81bd7SHeiko Stübner 		    point.coord_y > pdata->y_max) {
351c6d81bd7SHeiko Stübner 			dev_warn(&client->dev, "coordinates (%d,%d) invalid\n",
352c6d81bd7SHeiko Stübner 				point.coord_x, point.coord_y);
353c6d81bd7SHeiko Stübner 			point.coord_x = point.coord_y = 0;
354c6d81bd7SHeiko Stübner 		}
355c6d81bd7SHeiko Stübner 
356c6d81bd7SHeiko Stübner 		point.state = payload[9 * i + 5] & 0x03;
357c6d81bd7SHeiko Stübner 		point.id = (payload[9 * i + 5] & 0xfc) >> 2;
358c6d81bd7SHeiko Stübner 
359c6d81bd7SHeiko Stübner 		/* determine touch major, minor and orientation */
360c6d81bd7SHeiko Stübner 		point.area_major = max(payload[9 * i + 6],
361c6d81bd7SHeiko Stübner 					  payload[9 * i + 7]);
362c6d81bd7SHeiko Stübner 		point.area_minor = min(payload[9 * i + 6],
363c6d81bd7SHeiko Stübner 					  payload[9 * i + 7]);
364c6d81bd7SHeiko Stübner 		point.orientation = payload[9 * i + 6] > payload[9 * i + 7];
365c6d81bd7SHeiko Stübner 
366c6d81bd7SHeiko Stübner 		point.pressure = payload[9 * i + 8];
367c6d81bd7SHeiko Stübner 		point.prblty = payload[9 * i + 9];
368c6d81bd7SHeiko Stübner 
369c6d81bd7SHeiko Stübner 		dev_dbg(&client->dev,
370c6d81bd7SHeiko Stübner 			"point %d/%d: state %d, id %d, pressure %d, prblty %d, x %d, y %d, amajor %d, aminor %d, ori %d\n",
371c6d81bd7SHeiko Stübner 			i, count, point.state, point.id,
372c6d81bd7SHeiko Stübner 			point.pressure, point.prblty,
373c6d81bd7SHeiko Stübner 			point.coord_x, point.coord_y,
374c6d81bd7SHeiko Stübner 			point.area_major, point.area_minor,
375c6d81bd7SHeiko Stübner 			point.orientation);
376c6d81bd7SHeiko Stübner 
377c6d81bd7SHeiko Stübner 		/* the zforce id starts with "1", so needs to be decreased */
378c6d81bd7SHeiko Stübner 		input_mt_slot(ts->input, point.id - 1);
379c6d81bd7SHeiko Stübner 
380c6d81bd7SHeiko Stübner 		input_mt_report_slot_state(ts->input, MT_TOOL_FINGER,
381c6d81bd7SHeiko Stübner 						point.state != STATE_UP);
382c6d81bd7SHeiko Stübner 
383c6d81bd7SHeiko Stübner 		if (point.state != STATE_UP) {
384c6d81bd7SHeiko Stübner 			input_report_abs(ts->input, ABS_MT_POSITION_X,
385c6d81bd7SHeiko Stübner 					 point.coord_x);
386c6d81bd7SHeiko Stübner 			input_report_abs(ts->input, ABS_MT_POSITION_Y,
387c6d81bd7SHeiko Stübner 					 point.coord_y);
388c6d81bd7SHeiko Stübner 			input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR,
389c6d81bd7SHeiko Stübner 					 point.area_major);
390c6d81bd7SHeiko Stübner 			input_report_abs(ts->input, ABS_MT_TOUCH_MINOR,
391c6d81bd7SHeiko Stübner 					 point.area_minor);
392c6d81bd7SHeiko Stübner 			input_report_abs(ts->input, ABS_MT_ORIENTATION,
393c6d81bd7SHeiko Stübner 					 point.orientation);
394c6d81bd7SHeiko Stübner 			num++;
395c6d81bd7SHeiko Stübner 		}
396c6d81bd7SHeiko Stübner 	}
397c6d81bd7SHeiko Stübner 
398c6d81bd7SHeiko Stübner 	input_mt_sync_frame(ts->input);
399c6d81bd7SHeiko Stübner 
400c6d81bd7SHeiko Stübner 	input_mt_report_finger_count(ts->input, num);
401c6d81bd7SHeiko Stübner 
402c6d81bd7SHeiko Stübner 	input_sync(ts->input);
403c6d81bd7SHeiko Stübner 
404c6d81bd7SHeiko Stübner 	return 0;
405c6d81bd7SHeiko Stübner }
406c6d81bd7SHeiko Stübner 
407c6d81bd7SHeiko Stübner static int zforce_read_packet(struct zforce_ts *ts, u8 *buf)
408c6d81bd7SHeiko Stübner {
409c6d81bd7SHeiko Stübner 	struct i2c_client *client = ts->client;
410c6d81bd7SHeiko Stübner 	int ret;
411c6d81bd7SHeiko Stübner 
412c6d81bd7SHeiko Stübner 	mutex_lock(&ts->access_mutex);
413c6d81bd7SHeiko Stübner 
414c6d81bd7SHeiko Stübner 	/* read 2 byte message header */
415c6d81bd7SHeiko Stübner 	ret = i2c_master_recv(client, buf, 2);
416c6d81bd7SHeiko Stübner 	if (ret < 0) {
417c6d81bd7SHeiko Stübner 		dev_err(&client->dev, "error reading header: %d\n", ret);
418c6d81bd7SHeiko Stübner 		goto unlock;
419c6d81bd7SHeiko Stübner 	}
420c6d81bd7SHeiko Stübner 
421c6d81bd7SHeiko Stübner 	if (buf[PAYLOAD_HEADER] != FRAME_START) {
422c6d81bd7SHeiko Stübner 		dev_err(&client->dev, "invalid frame start: %d\n", buf[0]);
423c6d81bd7SHeiko Stübner 		ret = -EIO;
424c6d81bd7SHeiko Stübner 		goto unlock;
425c6d81bd7SHeiko Stübner 	}
426c6d81bd7SHeiko Stübner 
4275aee41a6SLuis Ortega 	if (buf[PAYLOAD_LENGTH] == 0) {
428c6d81bd7SHeiko Stübner 		dev_err(&client->dev, "invalid payload length: %d\n",
429c6d81bd7SHeiko Stübner 			buf[PAYLOAD_LENGTH]);
430c6d81bd7SHeiko Stübner 		ret = -EIO;
431c6d81bd7SHeiko Stübner 		goto unlock;
432c6d81bd7SHeiko Stübner 	}
433c6d81bd7SHeiko Stübner 
434c6d81bd7SHeiko Stübner 	/* read the message */
435c6d81bd7SHeiko Stübner 	ret = i2c_master_recv(client, &buf[PAYLOAD_BODY], buf[PAYLOAD_LENGTH]);
436c6d81bd7SHeiko Stübner 	if (ret < 0) {
437c6d81bd7SHeiko Stübner 		dev_err(&client->dev, "error reading payload: %d\n", ret);
438c6d81bd7SHeiko Stübner 		goto unlock;
439c6d81bd7SHeiko Stübner 	}
440c6d81bd7SHeiko Stübner 
441c6d81bd7SHeiko Stübner 	dev_dbg(&client->dev, "read %d bytes for response command 0x%x\n",
442c6d81bd7SHeiko Stübner 		buf[PAYLOAD_LENGTH], buf[PAYLOAD_BODY]);
443c6d81bd7SHeiko Stübner 
444c6d81bd7SHeiko Stübner unlock:
445c6d81bd7SHeiko Stübner 	mutex_unlock(&ts->access_mutex);
446c6d81bd7SHeiko Stübner 	return ret;
447c6d81bd7SHeiko Stübner }
448c6d81bd7SHeiko Stübner 
449c6d81bd7SHeiko Stübner static void zforce_complete(struct zforce_ts *ts, int cmd, int result)
450c6d81bd7SHeiko Stübner {
451c6d81bd7SHeiko Stübner 	struct i2c_client *client = ts->client;
452c6d81bd7SHeiko Stübner 
453c6d81bd7SHeiko Stübner 	if (ts->command_waiting == cmd) {
454c6d81bd7SHeiko Stübner 		dev_dbg(&client->dev, "completing command 0x%x\n", cmd);
455c6d81bd7SHeiko Stübner 		ts->command_result = result;
456c6d81bd7SHeiko Stübner 		complete(&ts->command_done);
457c6d81bd7SHeiko Stübner 	} else {
458c6d81bd7SHeiko Stübner 		dev_dbg(&client->dev, "command %d not for us\n", cmd);
459c6d81bd7SHeiko Stübner 	}
460c6d81bd7SHeiko Stübner }
461c6d81bd7SHeiko Stübner 
462c6d81bd7SHeiko Stübner static irqreturn_t zforce_interrupt(int irq, void *dev_id)
463c6d81bd7SHeiko Stübner {
464c6d81bd7SHeiko Stübner 	struct zforce_ts *ts = dev_id;
465c6d81bd7SHeiko Stübner 	struct i2c_client *client = ts->client;
466c6d81bd7SHeiko Stübner 	const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev);
467c6d81bd7SHeiko Stübner 	int ret;
468d333b606SLuis Ortega 	u8 payload_buffer[FRAME_MAXSIZE];
469c6d81bd7SHeiko Stübner 	u8 *payload;
470c6d81bd7SHeiko Stübner 
471c6d81bd7SHeiko Stübner 	/*
472c6d81bd7SHeiko Stübner 	 * When suspended, emit a wakeup signal if necessary and return.
473c6d81bd7SHeiko Stübner 	 * Due to the level-interrupt we will get re-triggered later.
474c6d81bd7SHeiko Stübner 	 */
475c6d81bd7SHeiko Stübner 	if (ts->suspended) {
476c6d81bd7SHeiko Stübner 		if (device_may_wakeup(&client->dev))
477c6d81bd7SHeiko Stübner 			pm_wakeup_event(&client->dev, 500);
478c6d81bd7SHeiko Stübner 		msleep(20);
479c6d81bd7SHeiko Stübner 		return IRQ_HANDLED;
480c6d81bd7SHeiko Stübner 	}
481c6d81bd7SHeiko Stübner 
482c6d81bd7SHeiko Stübner 	dev_dbg(&client->dev, "handling interrupt\n");
483c6d81bd7SHeiko Stübner 
484c6d81bd7SHeiko Stübner 	/* Don't emit wakeup events from commands run by zforce_suspend */
485c6d81bd7SHeiko Stübner 	if (!ts->suspending && device_may_wakeup(&client->dev))
486c6d81bd7SHeiko Stübner 		pm_stay_awake(&client->dev);
487c6d81bd7SHeiko Stübner 
488c6d81bd7SHeiko Stübner 	while (!gpio_get_value(pdata->gpio_int)) {
489c6d81bd7SHeiko Stübner 		ret = zforce_read_packet(ts, payload_buffer);
490c6d81bd7SHeiko Stübner 		if (ret < 0) {
491ad697b96SLuis Ortega 			dev_err(&client->dev,
492ad697b96SLuis Ortega 				"could not read packet, ret: %d\n", ret);
493c6d81bd7SHeiko Stübner 			break;
494c6d81bd7SHeiko Stübner 		}
495c6d81bd7SHeiko Stübner 
496c6d81bd7SHeiko Stübner 		payload =  &payload_buffer[PAYLOAD_BODY];
497c6d81bd7SHeiko Stübner 
498c6d81bd7SHeiko Stübner 		switch (payload[RESPONSE_ID]) {
499c6d81bd7SHeiko Stübner 		case NOTIFICATION_TOUCH:
500c6d81bd7SHeiko Stübner 			/*
501c6d81bd7SHeiko Stübner 			 * Always report touch-events received while
502c6d81bd7SHeiko Stübner 			 * suspending, when being a wakeup source
503c6d81bd7SHeiko Stübner 			 */
504c6d81bd7SHeiko Stübner 			if (ts->suspending && device_may_wakeup(&client->dev))
505c6d81bd7SHeiko Stübner 				pm_wakeup_event(&client->dev, 500);
506c6d81bd7SHeiko Stübner 			zforce_touch_event(ts, &payload[RESPONSE_DATA]);
507c6d81bd7SHeiko Stübner 			break;
508c6d81bd7SHeiko Stübner 
509c6d81bd7SHeiko Stübner 		case NOTIFICATION_BOOTCOMPLETE:
510c6d81bd7SHeiko Stübner 			ts->boot_complete = payload[RESPONSE_DATA];
511c6d81bd7SHeiko Stübner 			zforce_complete(ts, payload[RESPONSE_ID], 0);
512c6d81bd7SHeiko Stübner 			break;
513c6d81bd7SHeiko Stübner 
514c6d81bd7SHeiko Stübner 		case RESPONSE_INITIALIZE:
515c6d81bd7SHeiko Stübner 		case RESPONSE_DEACTIVATE:
516c6d81bd7SHeiko Stübner 		case RESPONSE_SETCONFIG:
517c6d81bd7SHeiko Stübner 		case RESPONSE_RESOLUTION:
518c6d81bd7SHeiko Stübner 		case RESPONSE_SCANFREQ:
519c6d81bd7SHeiko Stübner 			zforce_complete(ts, payload[RESPONSE_ID],
520c6d81bd7SHeiko Stübner 					payload[RESPONSE_DATA]);
521c6d81bd7SHeiko Stübner 			break;
522c6d81bd7SHeiko Stübner 
523c6d81bd7SHeiko Stübner 		case RESPONSE_STATUS:
524c6d81bd7SHeiko Stübner 			/*
525c6d81bd7SHeiko Stübner 			 * Version Payload Results
526c6d81bd7SHeiko Stübner 			 * [2:major] [2:minor] [2:build] [2:rev]
527c6d81bd7SHeiko Stübner 			 */
528c6d81bd7SHeiko Stübner 			ts->version_major = (payload[RESPONSE_DATA + 1] << 8) |
529c6d81bd7SHeiko Stübner 						payload[RESPONSE_DATA];
530c6d81bd7SHeiko Stübner 			ts->version_minor = (payload[RESPONSE_DATA + 3] << 8) |
531c6d81bd7SHeiko Stübner 						payload[RESPONSE_DATA + 2];
532c6d81bd7SHeiko Stübner 			ts->version_build = (payload[RESPONSE_DATA + 5] << 8) |
533c6d81bd7SHeiko Stübner 						payload[RESPONSE_DATA + 4];
534c6d81bd7SHeiko Stübner 			ts->version_rev   = (payload[RESPONSE_DATA + 7] << 8) |
535c6d81bd7SHeiko Stübner 						payload[RESPONSE_DATA + 6];
536ad697b96SLuis Ortega 			dev_dbg(&ts->client->dev,
537ad697b96SLuis Ortega 				"Firmware Version %04x:%04x %04x:%04x\n",
538c6d81bd7SHeiko Stübner 				ts->version_major, ts->version_minor,
539c6d81bd7SHeiko Stübner 				ts->version_build, ts->version_rev);
540c6d81bd7SHeiko Stübner 
541c6d81bd7SHeiko Stübner 			zforce_complete(ts, payload[RESPONSE_ID], 0);
542c6d81bd7SHeiko Stübner 			break;
543c6d81bd7SHeiko Stübner 
544c6d81bd7SHeiko Stübner 		case NOTIFICATION_INVALID_COMMAND:
545c6d81bd7SHeiko Stübner 			dev_err(&ts->client->dev, "invalid command: 0x%x\n",
546c6d81bd7SHeiko Stübner 				payload[RESPONSE_DATA]);
547c6d81bd7SHeiko Stübner 			break;
548c6d81bd7SHeiko Stübner 
549c6d81bd7SHeiko Stübner 		default:
550ad697b96SLuis Ortega 			dev_err(&ts->client->dev,
551ad697b96SLuis Ortega 				"unrecognized response id: 0x%x\n",
552c6d81bd7SHeiko Stübner 				payload[RESPONSE_ID]);
553c6d81bd7SHeiko Stübner 			break;
554c6d81bd7SHeiko Stübner 		}
555c6d81bd7SHeiko Stübner 	}
556c6d81bd7SHeiko Stübner 
557c6d81bd7SHeiko Stübner 	if (!ts->suspending && device_may_wakeup(&client->dev))
558c6d81bd7SHeiko Stübner 		pm_relax(&client->dev);
559c6d81bd7SHeiko Stübner 
560c6d81bd7SHeiko Stübner 	dev_dbg(&client->dev, "finished interrupt\n");
561c6d81bd7SHeiko Stübner 
562c6d81bd7SHeiko Stübner 	return IRQ_HANDLED;
563c6d81bd7SHeiko Stübner }
564c6d81bd7SHeiko Stübner 
565c6d81bd7SHeiko Stübner static int zforce_input_open(struct input_dev *dev)
566c6d81bd7SHeiko Stübner {
567c6d81bd7SHeiko Stübner 	struct zforce_ts *ts = input_get_drvdata(dev);
568c6d81bd7SHeiko Stübner 	int ret;
569c6d81bd7SHeiko Stübner 
570c6d81bd7SHeiko Stübner 	ret = zforce_start(ts);
571c6d81bd7SHeiko Stübner 	if (ret)
572c6d81bd7SHeiko Stübner 		return ret;
573c6d81bd7SHeiko Stübner 
574c6d81bd7SHeiko Stübner 	return 0;
575c6d81bd7SHeiko Stübner }
576c6d81bd7SHeiko Stübner 
577c6d81bd7SHeiko Stübner static void zforce_input_close(struct input_dev *dev)
578c6d81bd7SHeiko Stübner {
579c6d81bd7SHeiko Stübner 	struct zforce_ts *ts = input_get_drvdata(dev);
580c6d81bd7SHeiko Stübner 	struct i2c_client *client = ts->client;
581c6d81bd7SHeiko Stübner 	int ret;
582c6d81bd7SHeiko Stübner 
583c6d81bd7SHeiko Stübner 	ret = zforce_stop(ts);
584c6d81bd7SHeiko Stübner 	if (ret)
585c6d81bd7SHeiko Stübner 		dev_warn(&client->dev, "stopping zforce failed\n");
586c6d81bd7SHeiko Stübner 
587c6d81bd7SHeiko Stübner 	return;
588c6d81bd7SHeiko Stübner }
589c6d81bd7SHeiko Stübner 
590c6d81bd7SHeiko Stübner #ifdef CONFIG_PM_SLEEP
591c6d81bd7SHeiko Stübner static int zforce_suspend(struct device *dev)
592c6d81bd7SHeiko Stübner {
593c6d81bd7SHeiko Stübner 	struct i2c_client *client = to_i2c_client(dev);
594c6d81bd7SHeiko Stübner 	struct zforce_ts *ts = i2c_get_clientdata(client);
595c6d81bd7SHeiko Stübner 	struct input_dev *input = ts->input;
596c6d81bd7SHeiko Stübner 	int ret = 0;
597c6d81bd7SHeiko Stübner 
598c6d81bd7SHeiko Stübner 	mutex_lock(&input->mutex);
599c6d81bd7SHeiko Stübner 	ts->suspending = true;
600c6d81bd7SHeiko Stübner 
601c6d81bd7SHeiko Stübner 	/*
602c6d81bd7SHeiko Stübner 	 * When configured as a wakeup source device should always wake
603c6d81bd7SHeiko Stübner 	 * the system, therefore start device if necessary.
604c6d81bd7SHeiko Stübner 	 */
605c6d81bd7SHeiko Stübner 	if (device_may_wakeup(&client->dev)) {
606c6d81bd7SHeiko Stübner 		dev_dbg(&client->dev, "suspend while being a wakeup source\n");
607c6d81bd7SHeiko Stübner 
608c6d81bd7SHeiko Stübner 		/* Need to start device, if not open, to be a wakeup source. */
609c6d81bd7SHeiko Stübner 		if (!input->users) {
610c6d81bd7SHeiko Stübner 			ret = zforce_start(ts);
611c6d81bd7SHeiko Stübner 			if (ret)
612c6d81bd7SHeiko Stübner 				goto unlock;
613c6d81bd7SHeiko Stübner 		}
614c6d81bd7SHeiko Stübner 
615c6d81bd7SHeiko Stübner 		enable_irq_wake(client->irq);
616c6d81bd7SHeiko Stübner 	} else if (input->users) {
617ad697b96SLuis Ortega 		dev_dbg(&client->dev,
618ad697b96SLuis Ortega 			"suspend without being a wakeup source\n");
619c6d81bd7SHeiko Stübner 
620c6d81bd7SHeiko Stübner 		ret = zforce_stop(ts);
621c6d81bd7SHeiko Stübner 		if (ret)
622c6d81bd7SHeiko Stübner 			goto unlock;
623c6d81bd7SHeiko Stübner 
624c6d81bd7SHeiko Stübner 		disable_irq(client->irq);
625c6d81bd7SHeiko Stübner 	}
626c6d81bd7SHeiko Stübner 
627c6d81bd7SHeiko Stübner 	ts->suspended = true;
628c6d81bd7SHeiko Stübner 
629c6d81bd7SHeiko Stübner unlock:
630c6d81bd7SHeiko Stübner 	ts->suspending = false;
631c6d81bd7SHeiko Stübner 	mutex_unlock(&input->mutex);
632c6d81bd7SHeiko Stübner 
633c6d81bd7SHeiko Stübner 	return ret;
634c6d81bd7SHeiko Stübner }
635c6d81bd7SHeiko Stübner 
636c6d81bd7SHeiko Stübner static int zforce_resume(struct device *dev)
637c6d81bd7SHeiko Stübner {
638c6d81bd7SHeiko Stübner 	struct i2c_client *client = to_i2c_client(dev);
639c6d81bd7SHeiko Stübner 	struct zforce_ts *ts = i2c_get_clientdata(client);
640c6d81bd7SHeiko Stübner 	struct input_dev *input = ts->input;
641c6d81bd7SHeiko Stübner 	int ret = 0;
642c6d81bd7SHeiko Stübner 
643c6d81bd7SHeiko Stübner 	mutex_lock(&input->mutex);
644c6d81bd7SHeiko Stübner 
645c6d81bd7SHeiko Stübner 	ts->suspended = false;
646c6d81bd7SHeiko Stübner 
647c6d81bd7SHeiko Stübner 	if (device_may_wakeup(&client->dev)) {
648c6d81bd7SHeiko Stübner 		dev_dbg(&client->dev, "resume from being a wakeup source\n");
649c6d81bd7SHeiko Stübner 
650c6d81bd7SHeiko Stübner 		disable_irq_wake(client->irq);
651c6d81bd7SHeiko Stübner 
652c6d81bd7SHeiko Stübner 		/* need to stop device if it was not open on suspend */
653c6d81bd7SHeiko Stübner 		if (!input->users) {
654c6d81bd7SHeiko Stübner 			ret = zforce_stop(ts);
655c6d81bd7SHeiko Stübner 			if (ret)
656c6d81bd7SHeiko Stübner 				goto unlock;
657c6d81bd7SHeiko Stübner 		}
658c6d81bd7SHeiko Stübner 	} else if (input->users) {
659c6d81bd7SHeiko Stübner 		dev_dbg(&client->dev, "resume without being a wakeup source\n");
660c6d81bd7SHeiko Stübner 
661c6d81bd7SHeiko Stübner 		enable_irq(client->irq);
662c6d81bd7SHeiko Stübner 
663c6d81bd7SHeiko Stübner 		ret = zforce_start(ts);
664c6d81bd7SHeiko Stübner 		if (ret < 0)
665c6d81bd7SHeiko Stübner 			goto unlock;
666c6d81bd7SHeiko Stübner 	}
667c6d81bd7SHeiko Stübner 
668c6d81bd7SHeiko Stübner unlock:
669c6d81bd7SHeiko Stübner 	mutex_unlock(&input->mutex);
670c6d81bd7SHeiko Stübner 
671c6d81bd7SHeiko Stübner 	return ret;
672c6d81bd7SHeiko Stübner }
673c6d81bd7SHeiko Stübner #endif
674c6d81bd7SHeiko Stübner 
675c6d81bd7SHeiko Stübner static SIMPLE_DEV_PM_OPS(zforce_pm_ops, zforce_suspend, zforce_resume);
676c6d81bd7SHeiko Stübner 
677c6d81bd7SHeiko Stübner static void zforce_reset(void *data)
678c6d81bd7SHeiko Stübner {
679c6d81bd7SHeiko Stübner 	struct zforce_ts *ts = data;
680c6d81bd7SHeiko Stübner 
681c6d81bd7SHeiko Stübner 	gpio_set_value(ts->pdata->gpio_rst, 0);
682c6d81bd7SHeiko Stübner }
683c6d81bd7SHeiko Stübner 
684c6d81bd7SHeiko Stübner static int zforce_probe(struct i2c_client *client,
685c6d81bd7SHeiko Stübner 			const struct i2c_device_id *id)
686c6d81bd7SHeiko Stübner {
687c6d81bd7SHeiko Stübner 	const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev);
688c6d81bd7SHeiko Stübner 	struct zforce_ts *ts;
689c6d81bd7SHeiko Stübner 	struct input_dev *input_dev;
690c6d81bd7SHeiko Stübner 	int ret;
691c6d81bd7SHeiko Stübner 
692c6d81bd7SHeiko Stübner 	if (!pdata)
693c6d81bd7SHeiko Stübner 		return -EINVAL;
694c6d81bd7SHeiko Stübner 
695c6d81bd7SHeiko Stübner 	ts = devm_kzalloc(&client->dev, sizeof(struct zforce_ts), GFP_KERNEL);
696c6d81bd7SHeiko Stübner 	if (!ts)
697c6d81bd7SHeiko Stübner 		return -ENOMEM;
698c6d81bd7SHeiko Stübner 
699c6d81bd7SHeiko Stübner 	ret = devm_gpio_request_one(&client->dev, pdata->gpio_int, GPIOF_IN,
700c6d81bd7SHeiko Stübner 				    "zforce_ts_int");
701c6d81bd7SHeiko Stübner 	if (ret) {
702c6d81bd7SHeiko Stübner 		dev_err(&client->dev, "request of gpio %d failed, %d\n",
703c6d81bd7SHeiko Stübner 			pdata->gpio_int, ret);
704c6d81bd7SHeiko Stübner 		return ret;
705c6d81bd7SHeiko Stübner 	}
706c6d81bd7SHeiko Stübner 
707c6d81bd7SHeiko Stübner 	ret = devm_gpio_request_one(&client->dev, pdata->gpio_rst,
708c6d81bd7SHeiko Stübner 				    GPIOF_OUT_INIT_LOW, "zforce_ts_rst");
709c6d81bd7SHeiko Stübner 	if (ret) {
710c6d81bd7SHeiko Stübner 		dev_err(&client->dev, "request of gpio %d failed, %d\n",
711c6d81bd7SHeiko Stübner 			pdata->gpio_rst, ret);
712c6d81bd7SHeiko Stübner 		return ret;
713c6d81bd7SHeiko Stübner 	}
714c6d81bd7SHeiko Stübner 
715c6d81bd7SHeiko Stübner 	ret = devm_add_action(&client->dev, zforce_reset, ts);
716c6d81bd7SHeiko Stübner 	if (ret) {
717c6d81bd7SHeiko Stübner 		dev_err(&client->dev, "failed to register reset action, %d\n",
718c6d81bd7SHeiko Stübner 			ret);
719c6d81bd7SHeiko Stübner 		return ret;
720c6d81bd7SHeiko Stübner 	}
721c6d81bd7SHeiko Stübner 
722c6d81bd7SHeiko Stübner 	snprintf(ts->phys, sizeof(ts->phys),
723c6d81bd7SHeiko Stübner 		 "%s/input0", dev_name(&client->dev));
724c6d81bd7SHeiko Stübner 
725c6d81bd7SHeiko Stübner 	input_dev = devm_input_allocate_device(&client->dev);
726c6d81bd7SHeiko Stübner 	if (!input_dev) {
727c6d81bd7SHeiko Stübner 		dev_err(&client->dev, "could not allocate input device\n");
728c6d81bd7SHeiko Stübner 		return -ENOMEM;
729c6d81bd7SHeiko Stübner 	}
730c6d81bd7SHeiko Stübner 
731c6d81bd7SHeiko Stübner 	mutex_init(&ts->access_mutex);
732c6d81bd7SHeiko Stübner 	mutex_init(&ts->command_mutex);
733c6d81bd7SHeiko Stübner 
734c6d81bd7SHeiko Stübner 	ts->pdata = pdata;
735c6d81bd7SHeiko Stübner 	ts->client = client;
736c6d81bd7SHeiko Stübner 	ts->input = input_dev;
737c6d81bd7SHeiko Stübner 
738c6d81bd7SHeiko Stübner 	input_dev->name = "Neonode zForce touchscreen";
739c6d81bd7SHeiko Stübner 	input_dev->phys = ts->phys;
740c6d81bd7SHeiko Stübner 	input_dev->id.bustype = BUS_I2C;
741c6d81bd7SHeiko Stübner 
742c6d81bd7SHeiko Stübner 	input_dev->open = zforce_input_open;
743c6d81bd7SHeiko Stübner 	input_dev->close = zforce_input_close;
744c6d81bd7SHeiko Stübner 
745c6d81bd7SHeiko Stübner 	__set_bit(EV_KEY, input_dev->evbit);
746c6d81bd7SHeiko Stübner 	__set_bit(EV_SYN, input_dev->evbit);
747c6d81bd7SHeiko Stübner 	__set_bit(EV_ABS, input_dev->evbit);
748c6d81bd7SHeiko Stübner 
749c6d81bd7SHeiko Stübner 	/* For multi touch */
750c6d81bd7SHeiko Stübner 	input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0,
751c6d81bd7SHeiko Stübner 			     pdata->x_max, 0, 0);
752c6d81bd7SHeiko Stübner 	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0,
753c6d81bd7SHeiko Stübner 			     pdata->y_max, 0, 0);
754c6d81bd7SHeiko Stübner 
755c6d81bd7SHeiko Stübner 	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0,
756c6d81bd7SHeiko Stübner 			     ZFORCE_MAX_AREA, 0, 0);
757c6d81bd7SHeiko Stübner 	input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, 0,
758c6d81bd7SHeiko Stübner 			     ZFORCE_MAX_AREA, 0, 0);
759c6d81bd7SHeiko Stübner 	input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0);
760c6d81bd7SHeiko Stübner 	input_mt_init_slots(input_dev, ZFORCE_REPORT_POINTS, INPUT_MT_DIRECT);
761c6d81bd7SHeiko Stübner 
762c6d81bd7SHeiko Stübner 	input_set_drvdata(ts->input, ts);
763c6d81bd7SHeiko Stübner 
764c6d81bd7SHeiko Stübner 	init_completion(&ts->command_done);
765c6d81bd7SHeiko Stübner 
766c6d81bd7SHeiko Stübner 	/*
767c6d81bd7SHeiko Stübner 	 * The zforce pulls the interrupt low when it has data ready.
768c6d81bd7SHeiko Stübner 	 * After it is triggered the isr thread runs until all the available
769c6d81bd7SHeiko Stübner 	 * packets have been read and the interrupt is high again.
770c6d81bd7SHeiko Stübner 	 * Therefore we can trigger the interrupt anytime it is low and do
771c6d81bd7SHeiko Stübner 	 * not need to limit it to the interrupt edge.
772c6d81bd7SHeiko Stübner 	 */
773c6d81bd7SHeiko Stübner 	ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
774c6d81bd7SHeiko Stübner 					zforce_interrupt,
775c6d81bd7SHeiko Stübner 					IRQF_TRIGGER_LOW | IRQF_ONESHOT,
776c6d81bd7SHeiko Stübner 					input_dev->name, ts);
777c6d81bd7SHeiko Stübner 	if (ret) {
778c6d81bd7SHeiko Stübner 		dev_err(&client->dev, "irq %d request failed\n", client->irq);
779c6d81bd7SHeiko Stübner 		return ret;
780c6d81bd7SHeiko Stübner 	}
781c6d81bd7SHeiko Stübner 
782c6d81bd7SHeiko Stübner 	i2c_set_clientdata(client, ts);
783c6d81bd7SHeiko Stübner 
784c6d81bd7SHeiko Stübner 	/* let the controller boot */
785c6d81bd7SHeiko Stübner 	gpio_set_value(pdata->gpio_rst, 1);
786c6d81bd7SHeiko Stübner 
787c6d81bd7SHeiko Stübner 	ts->command_waiting = NOTIFICATION_BOOTCOMPLETE;
788c6d81bd7SHeiko Stübner 	if (wait_for_completion_timeout(&ts->command_done, WAIT_TIMEOUT) == 0)
789c6d81bd7SHeiko Stübner 		dev_warn(&client->dev, "bootcomplete timed out\n");
790c6d81bd7SHeiko Stübner 
791c6d81bd7SHeiko Stübner 	/* need to start device to get version information */
792c6d81bd7SHeiko Stübner 	ret = zforce_command_wait(ts, COMMAND_INITIALIZE);
793c6d81bd7SHeiko Stübner 	if (ret) {
794c6d81bd7SHeiko Stübner 		dev_err(&client->dev, "unable to initialize, %d\n", ret);
795c6d81bd7SHeiko Stübner 		return ret;
796c6d81bd7SHeiko Stübner 	}
797c6d81bd7SHeiko Stübner 
798deb49819SLuis Ortega 	/* this gets the firmware version among other information */
799c6d81bd7SHeiko Stübner 	ret = zforce_command_wait(ts, COMMAND_STATUS);
800c6d81bd7SHeiko Stübner 	if (ret < 0) {
801c6d81bd7SHeiko Stübner 		dev_err(&client->dev, "couldn't get status, %d\n", ret);
802c6d81bd7SHeiko Stübner 		zforce_stop(ts);
803c6d81bd7SHeiko Stübner 		return ret;
804c6d81bd7SHeiko Stübner 	}
805c6d81bd7SHeiko Stübner 
806c6d81bd7SHeiko Stübner 	/* stop device and put it into sleep until it is opened */
807c6d81bd7SHeiko Stübner 	ret = zforce_stop(ts);
808c6d81bd7SHeiko Stübner 	if (ret < 0)
809c6d81bd7SHeiko Stübner 		return ret;
810c6d81bd7SHeiko Stübner 
811c6d81bd7SHeiko Stübner 	device_set_wakeup_capable(&client->dev, true);
812c6d81bd7SHeiko Stübner 
813c6d81bd7SHeiko Stübner 	ret = input_register_device(input_dev);
814c6d81bd7SHeiko Stübner 	if (ret) {
815c6d81bd7SHeiko Stübner 		dev_err(&client->dev, "could not register input device, %d\n",
816c6d81bd7SHeiko Stübner 			ret);
817c6d81bd7SHeiko Stübner 		return ret;
818c6d81bd7SHeiko Stübner 	}
819c6d81bd7SHeiko Stübner 
820c6d81bd7SHeiko Stübner 	return 0;
821c6d81bd7SHeiko Stübner }
822c6d81bd7SHeiko Stübner 
823c6d81bd7SHeiko Stübner static struct i2c_device_id zforce_idtable[] = {
824c6d81bd7SHeiko Stübner 	{ "zforce-ts", 0 },
825c6d81bd7SHeiko Stübner 	{ }
826c6d81bd7SHeiko Stübner };
827c6d81bd7SHeiko Stübner MODULE_DEVICE_TABLE(i2c, zforce_idtable);
828c6d81bd7SHeiko Stübner 
829c6d81bd7SHeiko Stübner static struct i2c_driver zforce_driver = {
830c6d81bd7SHeiko Stübner 	.driver = {
831c6d81bd7SHeiko Stübner 		.owner	= THIS_MODULE,
832c6d81bd7SHeiko Stübner 		.name	= "zforce-ts",
833c6d81bd7SHeiko Stübner 		.pm	= &zforce_pm_ops,
834c6d81bd7SHeiko Stübner 	},
835c6d81bd7SHeiko Stübner 	.probe		= zforce_probe,
836c6d81bd7SHeiko Stübner 	.id_table	= zforce_idtable,
837c6d81bd7SHeiko Stübner };
838c6d81bd7SHeiko Stübner 
839c6d81bd7SHeiko Stübner module_i2c_driver(zforce_driver);
840c6d81bd7SHeiko Stübner 
841c6d81bd7SHeiko Stübner MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
842c6d81bd7SHeiko Stübner MODULE_DESCRIPTION("zForce TouchScreen Driver");
843c6d81bd7SHeiko Stübner MODULE_LICENSE("GPL");
844