19c92ab61SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2c6d81bd7SHeiko Stübner /*
3c6d81bd7SHeiko Stübner * Copyright (C) 2012-2013 MundoReader S.L.
4c6d81bd7SHeiko Stübner * Author: Heiko Stuebner <heiko@sntech.de>
5c6d81bd7SHeiko Stübner *
6c6d81bd7SHeiko Stübner * based in parts on Nook zforce driver
7c6d81bd7SHeiko Stübner *
8c6d81bd7SHeiko Stübner * Copyright (C) 2010 Barnes & Noble, Inc.
9c6d81bd7SHeiko Stübner * Author: Pieter Truter<ptruter@intrinsyc.com>
10c6d81bd7SHeiko Stübner */
11c6d81bd7SHeiko Stübner
12c6d81bd7SHeiko Stübner #include <linux/module.h>
13c6d81bd7SHeiko Stübner #include <linux/hrtimer.h>
14c6d81bd7SHeiko Stübner #include <linux/slab.h>
15c6d81bd7SHeiko Stübner #include <linux/input.h>
16c6d81bd7SHeiko Stübner #include <linux/interrupt.h>
17c6d81bd7SHeiko Stübner #include <linux/i2c.h>
18c6d81bd7SHeiko Stübner #include <linux/delay.h>
192d538095SDirk Behme #include <linux/gpio/consumer.h>
20c6d81bd7SHeiko Stübner #include <linux/device.h>
21c6d81bd7SHeiko Stübner #include <linux/sysfs.h>
22c6d81bd7SHeiko Stübner #include <linux/input/mt.h>
23c6d81bd7SHeiko Stübner #include <linux/platform_data/zforce_ts.h>
2439740370SHeiko Stuebner #include <linux/regulator/consumer.h>
256f2e6c9bSHeiko Stübner #include <linux/of.h>
26c6d81bd7SHeiko Stübner
27c6d81bd7SHeiko Stübner #define WAIT_TIMEOUT msecs_to_jiffies(1000)
28c6d81bd7SHeiko Stübner
29c6d81bd7SHeiko Stübner #define FRAME_START 0xee
30d333b606SLuis Ortega #define FRAME_MAXSIZE 257
31c6d81bd7SHeiko Stübner
32c6d81bd7SHeiko Stübner /* Offsets of the different parts of the payload the controller sends */
33c6d81bd7SHeiko Stübner #define PAYLOAD_HEADER 0
34c6d81bd7SHeiko Stübner #define PAYLOAD_LENGTH 1
35c6d81bd7SHeiko Stübner #define PAYLOAD_BODY 2
36c6d81bd7SHeiko Stübner
37c6d81bd7SHeiko Stübner /* Response offsets */
38c6d81bd7SHeiko Stübner #define RESPONSE_ID 0
39c6d81bd7SHeiko Stübner #define RESPONSE_DATA 1
40c6d81bd7SHeiko Stübner
41c6d81bd7SHeiko Stübner /* Commands */
42c6d81bd7SHeiko Stübner #define COMMAND_DEACTIVATE 0x00
43c6d81bd7SHeiko Stübner #define COMMAND_INITIALIZE 0x01
44c6d81bd7SHeiko Stübner #define COMMAND_RESOLUTION 0x02
45c6d81bd7SHeiko Stübner #define COMMAND_SETCONFIG 0x03
46c6d81bd7SHeiko Stübner #define COMMAND_DATAREQUEST 0x04
47c6d81bd7SHeiko Stübner #define COMMAND_SCANFREQ 0x08
48c6d81bd7SHeiko Stübner #define COMMAND_STATUS 0X1e
49c6d81bd7SHeiko Stübner
50c6d81bd7SHeiko Stübner /*
51c6d81bd7SHeiko Stübner * Responses the controller sends as a result of
52c6d81bd7SHeiko Stübner * command requests
53c6d81bd7SHeiko Stübner */
54c6d81bd7SHeiko Stübner #define RESPONSE_DEACTIVATE 0x00
55c6d81bd7SHeiko Stübner #define RESPONSE_INITIALIZE 0x01
56c6d81bd7SHeiko Stübner #define RESPONSE_RESOLUTION 0x02
57c6d81bd7SHeiko Stübner #define RESPONSE_SETCONFIG 0x03
58c6d81bd7SHeiko Stübner #define RESPONSE_SCANFREQ 0x08
59c6d81bd7SHeiko Stübner #define RESPONSE_STATUS 0X1e
60c6d81bd7SHeiko Stübner
61c6d81bd7SHeiko Stübner /*
62deb49819SLuis Ortega * Notifications are sent by the touch controller without
63c6d81bd7SHeiko Stübner * being requested by the driver and include for example
64c6d81bd7SHeiko Stübner * touch indications
65c6d81bd7SHeiko Stübner */
66c6d81bd7SHeiko Stübner #define NOTIFICATION_TOUCH 0x04
67c6d81bd7SHeiko Stübner #define NOTIFICATION_BOOTCOMPLETE 0x07
68c6d81bd7SHeiko Stübner #define NOTIFICATION_OVERRUN 0x25
69c6d81bd7SHeiko Stübner #define NOTIFICATION_PROXIMITY 0x26
70c6d81bd7SHeiko Stübner #define NOTIFICATION_INVALID_COMMAND 0xfe
71c6d81bd7SHeiko Stübner
72c6d81bd7SHeiko Stübner #define ZFORCE_REPORT_POINTS 2
73c6d81bd7SHeiko Stübner #define ZFORCE_MAX_AREA 0xff
74c6d81bd7SHeiko Stübner
75c6d81bd7SHeiko Stübner #define STATE_DOWN 0
76c6d81bd7SHeiko Stübner #define STATE_MOVE 1
77c6d81bd7SHeiko Stübner #define STATE_UP 2
78c6d81bd7SHeiko Stübner
79c6d81bd7SHeiko Stübner #define SETCONFIG_DUALTOUCH (1 << 0)
80c6d81bd7SHeiko Stübner
81c6d81bd7SHeiko Stübner struct zforce_point {
82c6d81bd7SHeiko Stübner int coord_x;
83c6d81bd7SHeiko Stübner int coord_y;
84c6d81bd7SHeiko Stübner int state;
85c6d81bd7SHeiko Stübner int id;
86c6d81bd7SHeiko Stübner int area_major;
87c6d81bd7SHeiko Stübner int area_minor;
88c6d81bd7SHeiko Stübner int orientation;
89c6d81bd7SHeiko Stübner int pressure;
90c6d81bd7SHeiko Stübner int prblty;
91c6d81bd7SHeiko Stübner };
92c6d81bd7SHeiko Stübner
93c6d81bd7SHeiko Stübner /*
94c6d81bd7SHeiko Stübner * @client the i2c_client
95c6d81bd7SHeiko Stübner * @input the input device
96c6d81bd7SHeiko Stübner * @suspending in the process of going to suspend (don't emit wakeup
97c6d81bd7SHeiko Stübner * events for commands executed to suspend the device)
98c6d81bd7SHeiko Stübner * @suspended device suspended
99c6d81bd7SHeiko Stübner * @access_mutex serialize i2c-access, to keep multipart reads together
100c6d81bd7SHeiko Stübner * @command_done completion to wait for the command result
101deb49819SLuis Ortega * @command_mutex serialize commands sent to the ic
102deb49819SLuis Ortega * @command_waiting the id of the command that is currently waiting
103c6d81bd7SHeiko Stübner * for a result
104c6d81bd7SHeiko Stübner * @command_result returned result of the command
105c6d81bd7SHeiko Stübner */
106c6d81bd7SHeiko Stübner struct zforce_ts {
107c6d81bd7SHeiko Stübner struct i2c_client *client;
108c6d81bd7SHeiko Stübner struct input_dev *input;
109c6d81bd7SHeiko Stübner const struct zforce_ts_platdata *pdata;
110c6d81bd7SHeiko Stübner char phys[32];
111c6d81bd7SHeiko Stübner
11239740370SHeiko Stuebner struct regulator *reg_vdd;
11339740370SHeiko Stuebner
1142d538095SDirk Behme struct gpio_desc *gpio_int;
1152d538095SDirk Behme struct gpio_desc *gpio_rst;
1162d538095SDirk Behme
117c6d81bd7SHeiko Stübner bool suspending;
118c6d81bd7SHeiko Stübner bool suspended;
119c6d81bd7SHeiko Stübner bool boot_complete;
120c6d81bd7SHeiko Stübner
121c6d81bd7SHeiko Stübner /* Firmware version information */
122c6d81bd7SHeiko Stübner u16 version_major;
123c6d81bd7SHeiko Stübner u16 version_minor;
124c6d81bd7SHeiko Stübner u16 version_build;
125c6d81bd7SHeiko Stübner u16 version_rev;
126c6d81bd7SHeiko Stübner
127c6d81bd7SHeiko Stübner struct mutex access_mutex;
128c6d81bd7SHeiko Stübner
129c6d81bd7SHeiko Stübner struct completion command_done;
130c6d81bd7SHeiko Stübner struct mutex command_mutex;
131c6d81bd7SHeiko Stübner int command_waiting;
132c6d81bd7SHeiko Stübner int command_result;
133c6d81bd7SHeiko Stübner };
134c6d81bd7SHeiko Stübner
zforce_command(struct zforce_ts * ts,u8 cmd)135c6d81bd7SHeiko Stübner static int zforce_command(struct zforce_ts *ts, u8 cmd)
136c6d81bd7SHeiko Stübner {
137c6d81bd7SHeiko Stübner struct i2c_client *client = ts->client;
138c6d81bd7SHeiko Stübner char buf[3];
139c6d81bd7SHeiko Stübner int ret;
140c6d81bd7SHeiko Stübner
141c6d81bd7SHeiko Stübner dev_dbg(&client->dev, "%s: 0x%x\n", __func__, cmd);
142c6d81bd7SHeiko Stübner
143c6d81bd7SHeiko Stübner buf[0] = FRAME_START;
144c6d81bd7SHeiko Stübner buf[1] = 1; /* data size, command only */
145c6d81bd7SHeiko Stübner buf[2] = cmd;
146c6d81bd7SHeiko Stübner
147c6d81bd7SHeiko Stübner mutex_lock(&ts->access_mutex);
148c6d81bd7SHeiko Stübner ret = i2c_master_send(client, &buf[0], ARRAY_SIZE(buf));
149c6d81bd7SHeiko Stübner mutex_unlock(&ts->access_mutex);
150c6d81bd7SHeiko Stübner if (ret < 0) {
151c6d81bd7SHeiko Stübner dev_err(&client->dev, "i2c send data request error: %d\n", ret);
152c6d81bd7SHeiko Stübner return ret;
153c6d81bd7SHeiko Stübner }
154c6d81bd7SHeiko Stübner
155c6d81bd7SHeiko Stübner return 0;
156c6d81bd7SHeiko Stübner }
157c6d81bd7SHeiko Stübner
zforce_reset_assert(struct zforce_ts * ts)1582d538095SDirk Behme static void zforce_reset_assert(struct zforce_ts *ts)
1592d538095SDirk Behme {
1602d538095SDirk Behme gpiod_set_value_cansleep(ts->gpio_rst, 1);
1612d538095SDirk Behme }
1622d538095SDirk Behme
zforce_reset_deassert(struct zforce_ts * ts)1632d538095SDirk Behme static void zforce_reset_deassert(struct zforce_ts *ts)
1642d538095SDirk Behme {
1652d538095SDirk Behme gpiod_set_value_cansleep(ts->gpio_rst, 0);
1662d538095SDirk Behme }
1672d538095SDirk Behme
zforce_send_wait(struct zforce_ts * ts,const char * buf,int len)168c6d81bd7SHeiko Stübner static int zforce_send_wait(struct zforce_ts *ts, const char *buf, int len)
169c6d81bd7SHeiko Stübner {
170c6d81bd7SHeiko Stübner struct i2c_client *client = ts->client;
171c6d81bd7SHeiko Stübner int ret;
172c6d81bd7SHeiko Stübner
173c6d81bd7SHeiko Stübner ret = mutex_trylock(&ts->command_mutex);
174c6d81bd7SHeiko Stübner if (!ret) {
175c6d81bd7SHeiko Stübner dev_err(&client->dev, "already waiting for a command\n");
176c6d81bd7SHeiko Stübner return -EBUSY;
177c6d81bd7SHeiko Stübner }
178c6d81bd7SHeiko Stübner
179c6d81bd7SHeiko Stübner dev_dbg(&client->dev, "sending %d bytes for command 0x%x\n",
180c6d81bd7SHeiko Stübner buf[1], buf[2]);
181c6d81bd7SHeiko Stübner
182c6d81bd7SHeiko Stübner ts->command_waiting = buf[2];
183c6d81bd7SHeiko Stübner
184c6d81bd7SHeiko Stübner mutex_lock(&ts->access_mutex);
185c6d81bd7SHeiko Stübner ret = i2c_master_send(client, buf, len);
186c6d81bd7SHeiko Stübner mutex_unlock(&ts->access_mutex);
187c6d81bd7SHeiko Stübner if (ret < 0) {
188c6d81bd7SHeiko Stübner dev_err(&client->dev, "i2c send data request error: %d\n", ret);
189c6d81bd7SHeiko Stübner goto unlock;
190c6d81bd7SHeiko Stübner }
191c6d81bd7SHeiko Stübner
192c6d81bd7SHeiko Stübner dev_dbg(&client->dev, "waiting for result for command 0x%x\n", buf[2]);
193c6d81bd7SHeiko Stübner
194c6d81bd7SHeiko Stübner if (wait_for_completion_timeout(&ts->command_done, WAIT_TIMEOUT) == 0) {
195c6d81bd7SHeiko Stübner ret = -ETIME;
196c6d81bd7SHeiko Stübner goto unlock;
197c6d81bd7SHeiko Stübner }
198c6d81bd7SHeiko Stübner
199c6d81bd7SHeiko Stübner ret = ts->command_result;
200c6d81bd7SHeiko Stübner
201c6d81bd7SHeiko Stübner unlock:
202c6d81bd7SHeiko Stübner mutex_unlock(&ts->command_mutex);
203c6d81bd7SHeiko Stübner return ret;
204c6d81bd7SHeiko Stübner }
205c6d81bd7SHeiko Stübner
zforce_command_wait(struct zforce_ts * ts,u8 cmd)206c6d81bd7SHeiko Stübner static int zforce_command_wait(struct zforce_ts *ts, u8 cmd)
207c6d81bd7SHeiko Stübner {
208c6d81bd7SHeiko Stübner struct i2c_client *client = ts->client;
209c6d81bd7SHeiko Stübner char buf[3];
210c6d81bd7SHeiko Stübner int ret;
211c6d81bd7SHeiko Stübner
212c6d81bd7SHeiko Stübner dev_dbg(&client->dev, "%s: 0x%x\n", __func__, cmd);
213c6d81bd7SHeiko Stübner
214c6d81bd7SHeiko Stübner buf[0] = FRAME_START;
215c6d81bd7SHeiko Stübner buf[1] = 1; /* data size, command only */
216c6d81bd7SHeiko Stübner buf[2] = cmd;
217c6d81bd7SHeiko Stübner
218c6d81bd7SHeiko Stübner ret = zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf));
219c6d81bd7SHeiko Stübner if (ret < 0) {
220c6d81bd7SHeiko Stübner dev_err(&client->dev, "i2c send data request error: %d\n", ret);
221c6d81bd7SHeiko Stübner return ret;
222c6d81bd7SHeiko Stübner }
223c6d81bd7SHeiko Stübner
224c6d81bd7SHeiko Stübner return 0;
225c6d81bd7SHeiko Stübner }
226c6d81bd7SHeiko Stübner
zforce_resolution(struct zforce_ts * ts,u16 x,u16 y)227c6d81bd7SHeiko Stübner static int zforce_resolution(struct zforce_ts *ts, u16 x, u16 y)
228c6d81bd7SHeiko Stübner {
229c6d81bd7SHeiko Stübner struct i2c_client *client = ts->client;
230c6d81bd7SHeiko Stübner char buf[7] = { FRAME_START, 5, COMMAND_RESOLUTION,
231c6d81bd7SHeiko Stübner (x & 0xff), ((x >> 8) & 0xff),
232c6d81bd7SHeiko Stübner (y & 0xff), ((y >> 8) & 0xff) };
233c6d81bd7SHeiko Stübner
234c6d81bd7SHeiko Stübner dev_dbg(&client->dev, "set resolution to (%d,%d)\n", x, y);
235c6d81bd7SHeiko Stübner
236c6d81bd7SHeiko Stübner return zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf));
237c6d81bd7SHeiko Stübner }
238c6d81bd7SHeiko Stübner
zforce_scan_frequency(struct zforce_ts * ts,u16 idle,u16 finger,u16 stylus)239c6d81bd7SHeiko Stübner static int zforce_scan_frequency(struct zforce_ts *ts, u16 idle, u16 finger,
240c6d81bd7SHeiko Stübner u16 stylus)
241c6d81bd7SHeiko Stübner {
242c6d81bd7SHeiko Stübner struct i2c_client *client = ts->client;
243c6d81bd7SHeiko Stübner char buf[9] = { FRAME_START, 7, COMMAND_SCANFREQ,
244c6d81bd7SHeiko Stübner (idle & 0xff), ((idle >> 8) & 0xff),
245c6d81bd7SHeiko Stübner (finger & 0xff), ((finger >> 8) & 0xff),
246c6d81bd7SHeiko Stübner (stylus & 0xff), ((stylus >> 8) & 0xff) };
247c6d81bd7SHeiko Stübner
248ad697b96SLuis Ortega dev_dbg(&client->dev,
249ad697b96SLuis Ortega "set scan frequency to (idle: %d, finger: %d, stylus: %d)\n",
250c6d81bd7SHeiko Stübner idle, finger, stylus);
251c6d81bd7SHeiko Stübner
252c6d81bd7SHeiko Stübner return zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf));
253c6d81bd7SHeiko Stübner }
254c6d81bd7SHeiko Stübner
zforce_setconfig(struct zforce_ts * ts,char b1)255c6d81bd7SHeiko Stübner static int zforce_setconfig(struct zforce_ts *ts, char b1)
256c6d81bd7SHeiko Stübner {
257c6d81bd7SHeiko Stübner struct i2c_client *client = ts->client;
258c6d81bd7SHeiko Stübner char buf[7] = { FRAME_START, 5, COMMAND_SETCONFIG,
259c6d81bd7SHeiko Stübner b1, 0, 0, 0 };
260c6d81bd7SHeiko Stübner
261c6d81bd7SHeiko Stübner dev_dbg(&client->dev, "set config to (%d)\n", b1);
262c6d81bd7SHeiko Stübner
263c6d81bd7SHeiko Stübner return zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf));
264c6d81bd7SHeiko Stübner }
265c6d81bd7SHeiko Stübner
zforce_start(struct zforce_ts * ts)266c6d81bd7SHeiko Stübner static int zforce_start(struct zforce_ts *ts)
267c6d81bd7SHeiko Stübner {
268c6d81bd7SHeiko Stübner struct i2c_client *client = ts->client;
26987273364SHeiko Stübner const struct zforce_ts_platdata *pdata = ts->pdata;
270c6d81bd7SHeiko Stübner int ret;
271c6d81bd7SHeiko Stübner
272c6d81bd7SHeiko Stübner dev_dbg(&client->dev, "starting device\n");
273c6d81bd7SHeiko Stübner
274c6d81bd7SHeiko Stübner ret = zforce_command_wait(ts, COMMAND_INITIALIZE);
275c6d81bd7SHeiko Stübner if (ret) {
276c6d81bd7SHeiko Stübner dev_err(&client->dev, "Unable to initialize, %d\n", ret);
277c6d81bd7SHeiko Stübner return ret;
278c6d81bd7SHeiko Stübner }
279c6d81bd7SHeiko Stübner
280c6d81bd7SHeiko Stübner ret = zforce_resolution(ts, pdata->x_max, pdata->y_max);
281c6d81bd7SHeiko Stübner if (ret) {
282c6d81bd7SHeiko Stübner dev_err(&client->dev, "Unable to set resolution, %d\n", ret);
283c6d81bd7SHeiko Stübner goto error;
284c6d81bd7SHeiko Stübner }
285c6d81bd7SHeiko Stübner
286c6d81bd7SHeiko Stübner ret = zforce_scan_frequency(ts, 10, 50, 50);
287c6d81bd7SHeiko Stübner if (ret) {
288c6d81bd7SHeiko Stübner dev_err(&client->dev, "Unable to set scan frequency, %d\n",
289c6d81bd7SHeiko Stübner ret);
290c6d81bd7SHeiko Stübner goto error;
291c6d81bd7SHeiko Stübner }
292c6d81bd7SHeiko Stübner
2933c4396b4SWei Yongjun ret = zforce_setconfig(ts, SETCONFIG_DUALTOUCH);
2943c4396b4SWei Yongjun if (ret) {
295c6d81bd7SHeiko Stübner dev_err(&client->dev, "Unable to set config\n");
296c6d81bd7SHeiko Stübner goto error;
297c6d81bd7SHeiko Stübner }
298c6d81bd7SHeiko Stübner
299c6d81bd7SHeiko Stübner /* start sending touch events */
300c6d81bd7SHeiko Stübner ret = zforce_command(ts, COMMAND_DATAREQUEST);
301c6d81bd7SHeiko Stübner if (ret) {
302c6d81bd7SHeiko Stübner dev_err(&client->dev, "Unable to request data\n");
303c6d81bd7SHeiko Stübner goto error;
304c6d81bd7SHeiko Stübner }
305c6d81bd7SHeiko Stübner
306c6d81bd7SHeiko Stübner /*
307c6d81bd7SHeiko Stübner * Per NN, initial cal. take max. of 200msec.
308c6d81bd7SHeiko Stübner * Allow time to complete this calibration
309c6d81bd7SHeiko Stübner */
310c6d81bd7SHeiko Stübner msleep(200);
311c6d81bd7SHeiko Stübner
312c6d81bd7SHeiko Stübner return 0;
313c6d81bd7SHeiko Stübner
314c6d81bd7SHeiko Stübner error:
315c6d81bd7SHeiko Stübner zforce_command_wait(ts, COMMAND_DEACTIVATE);
316c6d81bd7SHeiko Stübner return ret;
317c6d81bd7SHeiko Stübner }
318c6d81bd7SHeiko Stübner
zforce_stop(struct zforce_ts * ts)319c6d81bd7SHeiko Stübner static int zforce_stop(struct zforce_ts *ts)
320c6d81bd7SHeiko Stübner {
321c6d81bd7SHeiko Stübner struct i2c_client *client = ts->client;
322c6d81bd7SHeiko Stübner int ret;
323c6d81bd7SHeiko Stübner
324c6d81bd7SHeiko Stübner dev_dbg(&client->dev, "stopping device\n");
325c6d81bd7SHeiko Stübner
326c6d81bd7SHeiko Stübner /* Deactivates touch sensing and puts the device into sleep. */
327c6d81bd7SHeiko Stübner ret = zforce_command_wait(ts, COMMAND_DEACTIVATE);
328c6d81bd7SHeiko Stübner if (ret != 0) {
329c6d81bd7SHeiko Stübner dev_err(&client->dev, "could not deactivate device, %d\n",
330c6d81bd7SHeiko Stübner ret);
331c6d81bd7SHeiko Stübner return ret;
332c6d81bd7SHeiko Stübner }
333c6d81bd7SHeiko Stübner
334c6d81bd7SHeiko Stübner return 0;
335c6d81bd7SHeiko Stübner }
336c6d81bd7SHeiko Stübner
zforce_touch_event(struct zforce_ts * ts,u8 * payload)337c6d81bd7SHeiko Stübner static int zforce_touch_event(struct zforce_ts *ts, u8 *payload)
338c6d81bd7SHeiko Stübner {
339c6d81bd7SHeiko Stübner struct i2c_client *client = ts->client;
34087273364SHeiko Stübner const struct zforce_ts_platdata *pdata = ts->pdata;
341c6d81bd7SHeiko Stübner struct zforce_point point;
342c6d81bd7SHeiko Stübner int count, i, num = 0;
343c6d81bd7SHeiko Stübner
344c6d81bd7SHeiko Stübner count = payload[0];
345c6d81bd7SHeiko Stübner if (count > ZFORCE_REPORT_POINTS) {
346ad697b96SLuis Ortega dev_warn(&client->dev,
347ad697b96SLuis Ortega "too many coordinates %d, expected max %d\n",
348c6d81bd7SHeiko Stübner count, ZFORCE_REPORT_POINTS);
349c6d81bd7SHeiko Stübner count = ZFORCE_REPORT_POINTS;
350c6d81bd7SHeiko Stübner }
351c6d81bd7SHeiko Stübner
352c6d81bd7SHeiko Stübner for (i = 0; i < count; i++) {
353c6d81bd7SHeiko Stübner point.coord_x =
354c6d81bd7SHeiko Stübner payload[9 * i + 2] << 8 | payload[9 * i + 1];
355c6d81bd7SHeiko Stübner point.coord_y =
356c6d81bd7SHeiko Stübner payload[9 * i + 4] << 8 | payload[9 * i + 3];
357c6d81bd7SHeiko Stübner
358c6d81bd7SHeiko Stübner if (point.coord_x > pdata->x_max ||
359c6d81bd7SHeiko Stübner point.coord_y > pdata->y_max) {
360c6d81bd7SHeiko Stübner dev_warn(&client->dev, "coordinates (%d,%d) invalid\n",
361c6d81bd7SHeiko Stübner point.coord_x, point.coord_y);
362c6d81bd7SHeiko Stübner point.coord_x = point.coord_y = 0;
363c6d81bd7SHeiko Stübner }
364c6d81bd7SHeiko Stübner
3656984ab1aSKnut Wohlrab point.state = payload[9 * i + 5] & 0x0f;
3666984ab1aSKnut Wohlrab point.id = (payload[9 * i + 5] & 0xf0) >> 4;
367c6d81bd7SHeiko Stübner
368c6d81bd7SHeiko Stübner /* determine touch major, minor and orientation */
369c6d81bd7SHeiko Stübner point.area_major = max(payload[9 * i + 6],
370c6d81bd7SHeiko Stübner payload[9 * i + 7]);
371c6d81bd7SHeiko Stübner point.area_minor = min(payload[9 * i + 6],
372c6d81bd7SHeiko Stübner payload[9 * i + 7]);
373c6d81bd7SHeiko Stübner point.orientation = payload[9 * i + 6] > payload[9 * i + 7];
374c6d81bd7SHeiko Stübner
375c6d81bd7SHeiko Stübner point.pressure = payload[9 * i + 8];
376c6d81bd7SHeiko Stübner point.prblty = payload[9 * i + 9];
377c6d81bd7SHeiko Stübner
378c6d81bd7SHeiko Stübner dev_dbg(&client->dev,
379c6d81bd7SHeiko Stübner "point %d/%d: state %d, id %d, pressure %d, prblty %d, x %d, y %d, amajor %d, aminor %d, ori %d\n",
380c6d81bd7SHeiko Stübner i, count, point.state, point.id,
381c6d81bd7SHeiko Stübner point.pressure, point.prblty,
382c6d81bd7SHeiko Stübner point.coord_x, point.coord_y,
383c6d81bd7SHeiko Stübner point.area_major, point.area_minor,
384c6d81bd7SHeiko Stübner point.orientation);
385c6d81bd7SHeiko Stübner
386c6d81bd7SHeiko Stübner /* the zforce id starts with "1", so needs to be decreased */
387c6d81bd7SHeiko Stübner input_mt_slot(ts->input, point.id - 1);
388c6d81bd7SHeiko Stübner
389c6d81bd7SHeiko Stübner input_mt_report_slot_state(ts->input, MT_TOOL_FINGER,
390c6d81bd7SHeiko Stübner point.state != STATE_UP);
391c6d81bd7SHeiko Stübner
392c6d81bd7SHeiko Stübner if (point.state != STATE_UP) {
393c6d81bd7SHeiko Stübner input_report_abs(ts->input, ABS_MT_POSITION_X,
394c6d81bd7SHeiko Stübner point.coord_x);
395c6d81bd7SHeiko Stübner input_report_abs(ts->input, ABS_MT_POSITION_Y,
396c6d81bd7SHeiko Stübner point.coord_y);
397c6d81bd7SHeiko Stübner input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR,
398c6d81bd7SHeiko Stübner point.area_major);
399c6d81bd7SHeiko Stübner input_report_abs(ts->input, ABS_MT_TOUCH_MINOR,
400c6d81bd7SHeiko Stübner point.area_minor);
401c6d81bd7SHeiko Stübner input_report_abs(ts->input, ABS_MT_ORIENTATION,
402c6d81bd7SHeiko Stübner point.orientation);
403c6d81bd7SHeiko Stübner num++;
404c6d81bd7SHeiko Stübner }
405c6d81bd7SHeiko Stübner }
406c6d81bd7SHeiko Stübner
407c6d81bd7SHeiko Stübner input_mt_sync_frame(ts->input);
408c6d81bd7SHeiko Stübner
409c6d81bd7SHeiko Stübner input_mt_report_finger_count(ts->input, num);
410c6d81bd7SHeiko Stübner
411c6d81bd7SHeiko Stübner input_sync(ts->input);
412c6d81bd7SHeiko Stübner
413c6d81bd7SHeiko Stübner return 0;
414c6d81bd7SHeiko Stübner }
415c6d81bd7SHeiko Stübner
zforce_read_packet(struct zforce_ts * ts,u8 * buf)416c6d81bd7SHeiko Stübner static int zforce_read_packet(struct zforce_ts *ts, u8 *buf)
417c6d81bd7SHeiko Stübner {
418c6d81bd7SHeiko Stübner struct i2c_client *client = ts->client;
419c6d81bd7SHeiko Stübner int ret;
420c6d81bd7SHeiko Stübner
421c6d81bd7SHeiko Stübner mutex_lock(&ts->access_mutex);
422c6d81bd7SHeiko Stübner
423c6d81bd7SHeiko Stübner /* read 2 byte message header */
424c6d81bd7SHeiko Stübner ret = i2c_master_recv(client, buf, 2);
425c6d81bd7SHeiko Stübner if (ret < 0) {
426c6d81bd7SHeiko Stübner dev_err(&client->dev, "error reading header: %d\n", ret);
427c6d81bd7SHeiko Stübner goto unlock;
428c6d81bd7SHeiko Stübner }
429c6d81bd7SHeiko Stübner
430c6d81bd7SHeiko Stübner if (buf[PAYLOAD_HEADER] != FRAME_START) {
431c6d81bd7SHeiko Stübner dev_err(&client->dev, "invalid frame start: %d\n", buf[0]);
432c6d81bd7SHeiko Stübner ret = -EIO;
433c6d81bd7SHeiko Stübner goto unlock;
434c6d81bd7SHeiko Stübner }
435c6d81bd7SHeiko Stübner
4365aee41a6SLuis Ortega if (buf[PAYLOAD_LENGTH] == 0) {
437c6d81bd7SHeiko Stübner dev_err(&client->dev, "invalid payload length: %d\n",
438c6d81bd7SHeiko Stübner buf[PAYLOAD_LENGTH]);
439c6d81bd7SHeiko Stübner ret = -EIO;
440c6d81bd7SHeiko Stübner goto unlock;
441c6d81bd7SHeiko Stübner }
442c6d81bd7SHeiko Stübner
443c6d81bd7SHeiko Stübner /* read the message */
444c6d81bd7SHeiko Stübner ret = i2c_master_recv(client, &buf[PAYLOAD_BODY], buf[PAYLOAD_LENGTH]);
445c6d81bd7SHeiko Stübner if (ret < 0) {
446c6d81bd7SHeiko Stübner dev_err(&client->dev, "error reading payload: %d\n", ret);
447c6d81bd7SHeiko Stübner goto unlock;
448c6d81bd7SHeiko Stübner }
449c6d81bd7SHeiko Stübner
450c6d81bd7SHeiko Stübner dev_dbg(&client->dev, "read %d bytes for response command 0x%x\n",
451c6d81bd7SHeiko Stübner buf[PAYLOAD_LENGTH], buf[PAYLOAD_BODY]);
452c6d81bd7SHeiko Stübner
453c6d81bd7SHeiko Stübner unlock:
454c6d81bd7SHeiko Stübner mutex_unlock(&ts->access_mutex);
455c6d81bd7SHeiko Stübner return ret;
456c6d81bd7SHeiko Stübner }
457c6d81bd7SHeiko Stübner
zforce_complete(struct zforce_ts * ts,int cmd,int result)458c6d81bd7SHeiko Stübner static void zforce_complete(struct zforce_ts *ts, int cmd, int result)
459c6d81bd7SHeiko Stübner {
460c6d81bd7SHeiko Stübner struct i2c_client *client = ts->client;
461c6d81bd7SHeiko Stübner
462c6d81bd7SHeiko Stübner if (ts->command_waiting == cmd) {
463c6d81bd7SHeiko Stübner dev_dbg(&client->dev, "completing command 0x%x\n", cmd);
464c6d81bd7SHeiko Stübner ts->command_result = result;
465c6d81bd7SHeiko Stübner complete(&ts->command_done);
466c6d81bd7SHeiko Stübner } else {
467c6d81bd7SHeiko Stübner dev_dbg(&client->dev, "command %d not for us\n", cmd);
468c6d81bd7SHeiko Stübner }
469c6d81bd7SHeiko Stübner }
470c6d81bd7SHeiko Stübner
zforce_irq(int irq,void * dev_id)471499e6127SHeiko Stübner static irqreturn_t zforce_irq(int irq, void *dev_id)
472499e6127SHeiko Stübner {
473499e6127SHeiko Stübner struct zforce_ts *ts = dev_id;
474499e6127SHeiko Stübner struct i2c_client *client = ts->client;
475499e6127SHeiko Stübner
476499e6127SHeiko Stübner if (ts->suspended && device_may_wakeup(&client->dev))
477499e6127SHeiko Stübner pm_wakeup_event(&client->dev, 500);
478499e6127SHeiko Stübner
479499e6127SHeiko Stübner return IRQ_WAKE_THREAD;
480499e6127SHeiko Stübner }
481499e6127SHeiko Stübner
zforce_irq_thread(int irq,void * dev_id)482499e6127SHeiko Stübner static irqreturn_t zforce_irq_thread(int irq, void *dev_id)
483c6d81bd7SHeiko Stübner {
484c6d81bd7SHeiko Stübner struct zforce_ts *ts = dev_id;
485c6d81bd7SHeiko Stübner struct i2c_client *client = ts->client;
486c6d81bd7SHeiko Stübner int ret;
487d333b606SLuis Ortega u8 payload_buffer[FRAME_MAXSIZE];
488c6d81bd7SHeiko Stübner u8 *payload;
489c6d81bd7SHeiko Stübner
490c6d81bd7SHeiko Stübner /*
491499e6127SHeiko Stübner * When still suspended, return.
492c6d81bd7SHeiko Stübner * Due to the level-interrupt we will get re-triggered later.
493c6d81bd7SHeiko Stübner */
494c6d81bd7SHeiko Stübner if (ts->suspended) {
495c6d81bd7SHeiko Stübner msleep(20);
496c6d81bd7SHeiko Stübner return IRQ_HANDLED;
497c6d81bd7SHeiko Stübner }
498c6d81bd7SHeiko Stübner
499c6d81bd7SHeiko Stübner dev_dbg(&client->dev, "handling interrupt\n");
500c6d81bd7SHeiko Stübner
501c6d81bd7SHeiko Stübner /* Don't emit wakeup events from commands run by zforce_suspend */
502c6d81bd7SHeiko Stübner if (!ts->suspending && device_may_wakeup(&client->dev))
503c6d81bd7SHeiko Stübner pm_stay_awake(&client->dev);
504c6d81bd7SHeiko Stübner
50562f46669SDirk Behme /*
50662f46669SDirk Behme * Run at least once and exit the loop if
50762f46669SDirk Behme * - the optional interrupt GPIO isn't specified
50862f46669SDirk Behme * (there is only one packet read per ISR invocation, then)
50962f46669SDirk Behme * or
51062f46669SDirk Behme * - the GPIO isn't active any more
51162f46669SDirk Behme * (packet read until the level GPIO indicates that there is
51262f46669SDirk Behme * no IRQ any more)
51362f46669SDirk Behme */
51462f46669SDirk Behme do {
515c6d81bd7SHeiko Stübner ret = zforce_read_packet(ts, payload_buffer);
516c6d81bd7SHeiko Stübner if (ret < 0) {
517ad697b96SLuis Ortega dev_err(&client->dev,
518ad697b96SLuis Ortega "could not read packet, ret: %d\n", ret);
519c6d81bd7SHeiko Stübner break;
520c6d81bd7SHeiko Stübner }
521c6d81bd7SHeiko Stübner
522c6d81bd7SHeiko Stübner payload = &payload_buffer[PAYLOAD_BODY];
523c6d81bd7SHeiko Stübner
524c6d81bd7SHeiko Stübner switch (payload[RESPONSE_ID]) {
525c6d81bd7SHeiko Stübner case NOTIFICATION_TOUCH:
526c6d81bd7SHeiko Stübner /*
527c6d81bd7SHeiko Stübner * Always report touch-events received while
528c6d81bd7SHeiko Stübner * suspending, when being a wakeup source
529c6d81bd7SHeiko Stübner */
530c6d81bd7SHeiko Stübner if (ts->suspending && device_may_wakeup(&client->dev))
531c6d81bd7SHeiko Stübner pm_wakeup_event(&client->dev, 500);
532c6d81bd7SHeiko Stübner zforce_touch_event(ts, &payload[RESPONSE_DATA]);
533c6d81bd7SHeiko Stübner break;
534c6d81bd7SHeiko Stübner
535c6d81bd7SHeiko Stübner case NOTIFICATION_BOOTCOMPLETE:
536c6d81bd7SHeiko Stübner ts->boot_complete = payload[RESPONSE_DATA];
537c6d81bd7SHeiko Stübner zforce_complete(ts, payload[RESPONSE_ID], 0);
538c6d81bd7SHeiko Stübner break;
539c6d81bd7SHeiko Stübner
540c6d81bd7SHeiko Stübner case RESPONSE_INITIALIZE:
541c6d81bd7SHeiko Stübner case RESPONSE_DEACTIVATE:
542c6d81bd7SHeiko Stübner case RESPONSE_SETCONFIG:
543c6d81bd7SHeiko Stübner case RESPONSE_RESOLUTION:
544c6d81bd7SHeiko Stübner case RESPONSE_SCANFREQ:
545c6d81bd7SHeiko Stübner zforce_complete(ts, payload[RESPONSE_ID],
546c6d81bd7SHeiko Stübner payload[RESPONSE_DATA]);
547c6d81bd7SHeiko Stübner break;
548c6d81bd7SHeiko Stübner
549c6d81bd7SHeiko Stübner case RESPONSE_STATUS:
550c6d81bd7SHeiko Stübner /*
551c6d81bd7SHeiko Stübner * Version Payload Results
552c6d81bd7SHeiko Stübner * [2:major] [2:minor] [2:build] [2:rev]
553c6d81bd7SHeiko Stübner */
554c6d81bd7SHeiko Stübner ts->version_major = (payload[RESPONSE_DATA + 1] << 8) |
555c6d81bd7SHeiko Stübner payload[RESPONSE_DATA];
556c6d81bd7SHeiko Stübner ts->version_minor = (payload[RESPONSE_DATA + 3] << 8) |
557c6d81bd7SHeiko Stübner payload[RESPONSE_DATA + 2];
558c6d81bd7SHeiko Stübner ts->version_build = (payload[RESPONSE_DATA + 5] << 8) |
559c6d81bd7SHeiko Stübner payload[RESPONSE_DATA + 4];
560c6d81bd7SHeiko Stübner ts->version_rev = (payload[RESPONSE_DATA + 7] << 8) |
561c6d81bd7SHeiko Stübner payload[RESPONSE_DATA + 6];
562ad697b96SLuis Ortega dev_dbg(&ts->client->dev,
563ad697b96SLuis Ortega "Firmware Version %04x:%04x %04x:%04x\n",
564c6d81bd7SHeiko Stübner ts->version_major, ts->version_minor,
565c6d81bd7SHeiko Stübner ts->version_build, ts->version_rev);
566c6d81bd7SHeiko Stübner
567c6d81bd7SHeiko Stübner zforce_complete(ts, payload[RESPONSE_ID], 0);
568c6d81bd7SHeiko Stübner break;
569c6d81bd7SHeiko Stübner
570c6d81bd7SHeiko Stübner case NOTIFICATION_INVALID_COMMAND:
571c6d81bd7SHeiko Stübner dev_err(&ts->client->dev, "invalid command: 0x%x\n",
572c6d81bd7SHeiko Stübner payload[RESPONSE_DATA]);
573c6d81bd7SHeiko Stübner break;
574c6d81bd7SHeiko Stübner
575c6d81bd7SHeiko Stübner default:
576ad697b96SLuis Ortega dev_err(&ts->client->dev,
577ad697b96SLuis Ortega "unrecognized response id: 0x%x\n",
578c6d81bd7SHeiko Stübner payload[RESPONSE_ID]);
579c6d81bd7SHeiko Stübner break;
580c6d81bd7SHeiko Stübner }
58162f46669SDirk Behme } while (gpiod_get_value_cansleep(ts->gpio_int));
582c6d81bd7SHeiko Stübner
583c6d81bd7SHeiko Stübner if (!ts->suspending && device_may_wakeup(&client->dev))
584c6d81bd7SHeiko Stübner pm_relax(&client->dev);
585c6d81bd7SHeiko Stübner
586c6d81bd7SHeiko Stübner dev_dbg(&client->dev, "finished interrupt\n");
587c6d81bd7SHeiko Stübner
588c6d81bd7SHeiko Stübner return IRQ_HANDLED;
589c6d81bd7SHeiko Stübner }
590c6d81bd7SHeiko Stübner
zforce_input_open(struct input_dev * dev)591c6d81bd7SHeiko Stübner static int zforce_input_open(struct input_dev *dev)
592c6d81bd7SHeiko Stübner {
593c6d81bd7SHeiko Stübner struct zforce_ts *ts = input_get_drvdata(dev);
594c6d81bd7SHeiko Stübner
595a47fcbc2SJavier Martinez Canillas return zforce_start(ts);
596c6d81bd7SHeiko Stübner }
597c6d81bd7SHeiko Stübner
zforce_input_close(struct input_dev * dev)598c6d81bd7SHeiko Stübner static void zforce_input_close(struct input_dev *dev)
599c6d81bd7SHeiko Stübner {
600c6d81bd7SHeiko Stübner struct zforce_ts *ts = input_get_drvdata(dev);
601c6d81bd7SHeiko Stübner struct i2c_client *client = ts->client;
602c6d81bd7SHeiko Stübner int ret;
603c6d81bd7SHeiko Stübner
604c6d81bd7SHeiko Stübner ret = zforce_stop(ts);
605c6d81bd7SHeiko Stübner if (ret)
606c6d81bd7SHeiko Stübner dev_warn(&client->dev, "stopping zforce failed\n");
607c6d81bd7SHeiko Stübner
608c6d81bd7SHeiko Stübner return;
609c6d81bd7SHeiko Stübner }
610c6d81bd7SHeiko Stübner
zforce_suspend(struct device * dev)611dc69e98aSJonathan Cameron static int zforce_suspend(struct device *dev)
612c6d81bd7SHeiko Stübner {
613c6d81bd7SHeiko Stübner struct i2c_client *client = to_i2c_client(dev);
614c6d81bd7SHeiko Stübner struct zforce_ts *ts = i2c_get_clientdata(client);
615c6d81bd7SHeiko Stübner struct input_dev *input = ts->input;
616c6d81bd7SHeiko Stübner int ret = 0;
617c6d81bd7SHeiko Stübner
618c6d81bd7SHeiko Stübner mutex_lock(&input->mutex);
619c6d81bd7SHeiko Stübner ts->suspending = true;
620c6d81bd7SHeiko Stübner
621c6d81bd7SHeiko Stübner /*
622c6d81bd7SHeiko Stübner * When configured as a wakeup source device should always wake
623c6d81bd7SHeiko Stübner * the system, therefore start device if necessary.
624c6d81bd7SHeiko Stübner */
625c6d81bd7SHeiko Stübner if (device_may_wakeup(&client->dev)) {
626c6d81bd7SHeiko Stübner dev_dbg(&client->dev, "suspend while being a wakeup source\n");
627c6d81bd7SHeiko Stübner
628c6d81bd7SHeiko Stübner /* Need to start device, if not open, to be a wakeup source. */
629d69f0a43SAndrzej Pietrasiewicz if (!input_device_enabled(input)) {
630c6d81bd7SHeiko Stübner ret = zforce_start(ts);
631c6d81bd7SHeiko Stübner if (ret)
632c6d81bd7SHeiko Stübner goto unlock;
633c6d81bd7SHeiko Stübner }
634c6d81bd7SHeiko Stübner
635c6d81bd7SHeiko Stübner enable_irq_wake(client->irq);
636d69f0a43SAndrzej Pietrasiewicz } else if (input_device_enabled(input)) {
637ad697b96SLuis Ortega dev_dbg(&client->dev,
638ad697b96SLuis Ortega "suspend without being a wakeup source\n");
639c6d81bd7SHeiko Stübner
640c6d81bd7SHeiko Stübner ret = zforce_stop(ts);
641c6d81bd7SHeiko Stübner if (ret)
642c6d81bd7SHeiko Stübner goto unlock;
643c6d81bd7SHeiko Stübner
644c6d81bd7SHeiko Stübner disable_irq(client->irq);
645c6d81bd7SHeiko Stübner }
646c6d81bd7SHeiko Stübner
647c6d81bd7SHeiko Stübner ts->suspended = true;
648c6d81bd7SHeiko Stübner
649c6d81bd7SHeiko Stübner unlock:
650c6d81bd7SHeiko Stübner ts->suspending = false;
651c6d81bd7SHeiko Stübner mutex_unlock(&input->mutex);
652c6d81bd7SHeiko Stübner
653c6d81bd7SHeiko Stübner return ret;
654c6d81bd7SHeiko Stübner }
655c6d81bd7SHeiko Stübner
zforce_resume(struct device * dev)656dc69e98aSJonathan Cameron static int zforce_resume(struct device *dev)
657c6d81bd7SHeiko Stübner {
658c6d81bd7SHeiko Stübner struct i2c_client *client = to_i2c_client(dev);
659c6d81bd7SHeiko Stübner struct zforce_ts *ts = i2c_get_clientdata(client);
660c6d81bd7SHeiko Stübner struct input_dev *input = ts->input;
661c6d81bd7SHeiko Stübner int ret = 0;
662c6d81bd7SHeiko Stübner
663c6d81bd7SHeiko Stübner mutex_lock(&input->mutex);
664c6d81bd7SHeiko Stübner
665c6d81bd7SHeiko Stübner ts->suspended = false;
666c6d81bd7SHeiko Stübner
667c6d81bd7SHeiko Stübner if (device_may_wakeup(&client->dev)) {
668c6d81bd7SHeiko Stübner dev_dbg(&client->dev, "resume from being a wakeup source\n");
669c6d81bd7SHeiko Stübner
670c6d81bd7SHeiko Stübner disable_irq_wake(client->irq);
671c6d81bd7SHeiko Stübner
672c6d81bd7SHeiko Stübner /* need to stop device if it was not open on suspend */
673d69f0a43SAndrzej Pietrasiewicz if (!input_device_enabled(input)) {
674c6d81bd7SHeiko Stübner ret = zforce_stop(ts);
675c6d81bd7SHeiko Stübner if (ret)
676c6d81bd7SHeiko Stübner goto unlock;
677c6d81bd7SHeiko Stübner }
678d69f0a43SAndrzej Pietrasiewicz } else if (input_device_enabled(input)) {
679c6d81bd7SHeiko Stübner dev_dbg(&client->dev, "resume without being a wakeup source\n");
680c6d81bd7SHeiko Stübner
681c6d81bd7SHeiko Stübner enable_irq(client->irq);
682c6d81bd7SHeiko Stübner
683c6d81bd7SHeiko Stübner ret = zforce_start(ts);
684c6d81bd7SHeiko Stübner if (ret < 0)
685c6d81bd7SHeiko Stübner goto unlock;
686c6d81bd7SHeiko Stübner }
687c6d81bd7SHeiko Stübner
688c6d81bd7SHeiko Stübner unlock:
689c6d81bd7SHeiko Stübner mutex_unlock(&input->mutex);
690c6d81bd7SHeiko Stübner
691c6d81bd7SHeiko Stübner return ret;
692c6d81bd7SHeiko Stübner }
693c6d81bd7SHeiko Stübner
694dc69e98aSJonathan Cameron static DEFINE_SIMPLE_DEV_PM_OPS(zforce_pm_ops, zforce_suspend, zforce_resume);
695c6d81bd7SHeiko Stübner
zforce_reset(void * data)696c6d81bd7SHeiko Stübner static void zforce_reset(void *data)
697c6d81bd7SHeiko Stübner {
698c6d81bd7SHeiko Stübner struct zforce_ts *ts = data;
699c6d81bd7SHeiko Stübner
7002d538095SDirk Behme zforce_reset_assert(ts);
70139740370SHeiko Stuebner
70239740370SHeiko Stuebner udelay(10);
70339740370SHeiko Stuebner
70439740370SHeiko Stuebner if (!IS_ERR(ts->reg_vdd))
70539740370SHeiko Stuebner regulator_disable(ts->reg_vdd);
706c6d81bd7SHeiko Stübner }
707c6d81bd7SHeiko Stübner
zforce_parse_dt(struct device * dev)7086f2e6c9bSHeiko Stübner static struct zforce_ts_platdata *zforce_parse_dt(struct device *dev)
7096f2e6c9bSHeiko Stübner {
7106f2e6c9bSHeiko Stübner struct zforce_ts_platdata *pdata;
7116f2e6c9bSHeiko Stübner struct device_node *np = dev->of_node;
7126f2e6c9bSHeiko Stübner
7136f2e6c9bSHeiko Stübner if (!np)
7146f2e6c9bSHeiko Stübner return ERR_PTR(-ENOENT);
7156f2e6c9bSHeiko Stübner
7166f2e6c9bSHeiko Stübner pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
7176f2e6c9bSHeiko Stübner if (!pdata) {
7186f2e6c9bSHeiko Stübner dev_err(dev, "failed to allocate platform data\n");
7196f2e6c9bSHeiko Stübner return ERR_PTR(-ENOMEM);
7206f2e6c9bSHeiko Stübner }
7216f2e6c9bSHeiko Stübner
7226f2e6c9bSHeiko Stübner if (of_property_read_u32(np, "x-size", &pdata->x_max)) {
7236f2e6c9bSHeiko Stübner dev_err(dev, "failed to get x-size property\n");
7246f2e6c9bSHeiko Stübner return ERR_PTR(-EINVAL);
7256f2e6c9bSHeiko Stübner }
7266f2e6c9bSHeiko Stübner
7276f2e6c9bSHeiko Stübner if (of_property_read_u32(np, "y-size", &pdata->y_max)) {
7286f2e6c9bSHeiko Stübner dev_err(dev, "failed to get y-size property\n");
7296f2e6c9bSHeiko Stübner return ERR_PTR(-EINVAL);
7306f2e6c9bSHeiko Stübner }
7316f2e6c9bSHeiko Stübner
7326f2e6c9bSHeiko Stübner return pdata;
7336f2e6c9bSHeiko Stübner }
7346f2e6c9bSHeiko Stübner
zforce_probe(struct i2c_client * client)73556232e93SUwe Kleine-König static int zforce_probe(struct i2c_client *client)
736c6d81bd7SHeiko Stübner {
737c6d81bd7SHeiko Stübner const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev);
738c6d81bd7SHeiko Stübner struct zforce_ts *ts;
739c6d81bd7SHeiko Stübner struct input_dev *input_dev;
740c6d81bd7SHeiko Stübner int ret;
741c6d81bd7SHeiko Stübner
7426f2e6c9bSHeiko Stübner if (!pdata) {
7436f2e6c9bSHeiko Stübner pdata = zforce_parse_dt(&client->dev);
7446f2e6c9bSHeiko Stübner if (IS_ERR(pdata))
7456f2e6c9bSHeiko Stübner return PTR_ERR(pdata);
7466f2e6c9bSHeiko Stübner }
747c6d81bd7SHeiko Stübner
748c6d81bd7SHeiko Stübner ts = devm_kzalloc(&client->dev, sizeof(struct zforce_ts), GFP_KERNEL);
749c6d81bd7SHeiko Stübner if (!ts)
750c6d81bd7SHeiko Stübner return -ENOMEM;
751c6d81bd7SHeiko Stübner
75262f46669SDirk Behme ts->gpio_rst = devm_gpiod_get_optional(&client->dev, "reset",
75362f46669SDirk Behme GPIOD_OUT_HIGH);
75462f46669SDirk Behme if (IS_ERR(ts->gpio_rst)) {
75562f46669SDirk Behme ret = PTR_ERR(ts->gpio_rst);
75662f46669SDirk Behme dev_err(&client->dev,
75762f46669SDirk Behme "failed to request reset GPIO: %d\n", ret);
75862f46669SDirk Behme return ret;
75962f46669SDirk Behme }
76062f46669SDirk Behme
76162f46669SDirk Behme if (ts->gpio_rst) {
76262f46669SDirk Behme ts->gpio_int = devm_gpiod_get_optional(&client->dev, "irq",
76362f46669SDirk Behme GPIOD_IN);
76462f46669SDirk Behme if (IS_ERR(ts->gpio_int)) {
76562f46669SDirk Behme ret = PTR_ERR(ts->gpio_int);
76662f46669SDirk Behme dev_err(&client->dev,
76762f46669SDirk Behme "failed to request interrupt GPIO: %d\n", ret);
76862f46669SDirk Behme return ret;
76962f46669SDirk Behme }
77062f46669SDirk Behme } else {
77162f46669SDirk Behme /*
77262f46669SDirk Behme * Deprecated GPIO handling for compatibility
77362f46669SDirk Behme * with legacy binding.
77462f46669SDirk Behme */
77562f46669SDirk Behme
7762d538095SDirk Behme /* INT GPIO */
77762f46669SDirk Behme ts->gpio_int = devm_gpiod_get_index(&client->dev, NULL, 0,
77862f46669SDirk Behme GPIOD_IN);
7792d538095SDirk Behme if (IS_ERR(ts->gpio_int)) {
7802d538095SDirk Behme ret = PTR_ERR(ts->gpio_int);
7812d538095SDirk Behme dev_err(&client->dev,
7822d538095SDirk Behme "failed to request interrupt GPIO: %d\n", ret);
783c6d81bd7SHeiko Stübner return ret;
784c6d81bd7SHeiko Stübner }
785c6d81bd7SHeiko Stübner
7862d538095SDirk Behme /* RST GPIO */
7872d538095SDirk Behme ts->gpio_rst = devm_gpiod_get_index(&client->dev, NULL, 1,
7882d538095SDirk Behme GPIOD_OUT_HIGH);
7892d538095SDirk Behme if (IS_ERR(ts->gpio_rst)) {
7902d538095SDirk Behme ret = PTR_ERR(ts->gpio_rst);
7912d538095SDirk Behme dev_err(&client->dev,
7922d538095SDirk Behme "failed to request reset GPIO: %d\n", ret);
793c6d81bd7SHeiko Stübner return ret;
794c6d81bd7SHeiko Stübner }
79562f46669SDirk Behme }
796c6d81bd7SHeiko Stübner
79739740370SHeiko Stuebner ts->reg_vdd = devm_regulator_get_optional(&client->dev, "vdd");
79839740370SHeiko Stuebner if (IS_ERR(ts->reg_vdd)) {
79939740370SHeiko Stuebner ret = PTR_ERR(ts->reg_vdd);
80039740370SHeiko Stuebner if (ret == -EPROBE_DEFER)
80139740370SHeiko Stuebner return ret;
80239740370SHeiko Stuebner } else {
80339740370SHeiko Stuebner ret = regulator_enable(ts->reg_vdd);
80439740370SHeiko Stuebner if (ret)
80539740370SHeiko Stuebner return ret;
80639740370SHeiko Stuebner
80739740370SHeiko Stuebner /*
80839740370SHeiko Stuebner * according to datasheet add 100us grace time after regular
80939740370SHeiko Stuebner * regulator enable delay.
81039740370SHeiko Stuebner */
81139740370SHeiko Stuebner udelay(100);
81239740370SHeiko Stuebner }
81339740370SHeiko Stuebner
814c6d81bd7SHeiko Stübner ret = devm_add_action(&client->dev, zforce_reset, ts);
815c6d81bd7SHeiko Stübner if (ret) {
816c6d81bd7SHeiko Stübner dev_err(&client->dev, "failed to register reset action, %d\n",
817c6d81bd7SHeiko Stübner ret);
81839740370SHeiko Stuebner
81939740370SHeiko Stuebner /* hereafter the regulator will be disabled by the action */
82039740370SHeiko Stuebner if (!IS_ERR(ts->reg_vdd))
82139740370SHeiko Stuebner regulator_disable(ts->reg_vdd);
82239740370SHeiko Stuebner
823c6d81bd7SHeiko Stübner return ret;
824c6d81bd7SHeiko Stübner }
825c6d81bd7SHeiko Stübner
826c6d81bd7SHeiko Stübner snprintf(ts->phys, sizeof(ts->phys),
827c6d81bd7SHeiko Stübner "%s/input0", dev_name(&client->dev));
828c6d81bd7SHeiko Stübner
829c6d81bd7SHeiko Stübner input_dev = devm_input_allocate_device(&client->dev);
830c6d81bd7SHeiko Stübner if (!input_dev) {
831c6d81bd7SHeiko Stübner dev_err(&client->dev, "could not allocate input device\n");
832c6d81bd7SHeiko Stübner return -ENOMEM;
833c6d81bd7SHeiko Stübner }
834c6d81bd7SHeiko Stübner
835c6d81bd7SHeiko Stübner mutex_init(&ts->access_mutex);
836c6d81bd7SHeiko Stübner mutex_init(&ts->command_mutex);
837c6d81bd7SHeiko Stübner
838c6d81bd7SHeiko Stübner ts->pdata = pdata;
839c6d81bd7SHeiko Stübner ts->client = client;
840c6d81bd7SHeiko Stübner ts->input = input_dev;
841c6d81bd7SHeiko Stübner
842c6d81bd7SHeiko Stübner input_dev->name = "Neonode zForce touchscreen";
843c6d81bd7SHeiko Stübner input_dev->phys = ts->phys;
844c6d81bd7SHeiko Stübner input_dev->id.bustype = BUS_I2C;
845c6d81bd7SHeiko Stübner
846c6d81bd7SHeiko Stübner input_dev->open = zforce_input_open;
847c6d81bd7SHeiko Stübner input_dev->close = zforce_input_close;
848c6d81bd7SHeiko Stübner
849c6d81bd7SHeiko Stübner __set_bit(EV_KEY, input_dev->evbit);
850c6d81bd7SHeiko Stübner __set_bit(EV_SYN, input_dev->evbit);
851c6d81bd7SHeiko Stübner __set_bit(EV_ABS, input_dev->evbit);
852c6d81bd7SHeiko Stübner
853c6d81bd7SHeiko Stübner /* For multi touch */
854c6d81bd7SHeiko Stübner input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0,
855c6d81bd7SHeiko Stübner pdata->x_max, 0, 0);
856c6d81bd7SHeiko Stübner input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0,
857c6d81bd7SHeiko Stübner pdata->y_max, 0, 0);
858c6d81bd7SHeiko Stübner
859c6d81bd7SHeiko Stübner input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0,
860c6d81bd7SHeiko Stübner ZFORCE_MAX_AREA, 0, 0);
861c6d81bd7SHeiko Stübner input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, 0,
862c6d81bd7SHeiko Stübner ZFORCE_MAX_AREA, 0, 0);
863c6d81bd7SHeiko Stübner input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0);
864c6d81bd7SHeiko Stübner input_mt_init_slots(input_dev, ZFORCE_REPORT_POINTS, INPUT_MT_DIRECT);
865c6d81bd7SHeiko Stübner
866c6d81bd7SHeiko Stübner input_set_drvdata(ts->input, ts);
867c6d81bd7SHeiko Stübner
868c6d81bd7SHeiko Stübner init_completion(&ts->command_done);
869c6d81bd7SHeiko Stübner
870c6d81bd7SHeiko Stübner /*
871c6d81bd7SHeiko Stübner * The zforce pulls the interrupt low when it has data ready.
872c6d81bd7SHeiko Stübner * After it is triggered the isr thread runs until all the available
873c6d81bd7SHeiko Stübner * packets have been read and the interrupt is high again.
874c6d81bd7SHeiko Stübner * Therefore we can trigger the interrupt anytime it is low and do
875c6d81bd7SHeiko Stübner * not need to limit it to the interrupt edge.
876c6d81bd7SHeiko Stübner */
877499e6127SHeiko Stübner ret = devm_request_threaded_irq(&client->dev, client->irq,
878499e6127SHeiko Stübner zforce_irq, zforce_irq_thread,
879c6d81bd7SHeiko Stübner IRQF_TRIGGER_LOW | IRQF_ONESHOT,
880c6d81bd7SHeiko Stübner input_dev->name, ts);
881c6d81bd7SHeiko Stübner if (ret) {
882c6d81bd7SHeiko Stübner dev_err(&client->dev, "irq %d request failed\n", client->irq);
883c6d81bd7SHeiko Stübner return ret;
884c6d81bd7SHeiko Stübner }
885c6d81bd7SHeiko Stübner
886c6d81bd7SHeiko Stübner i2c_set_clientdata(client, ts);
887c6d81bd7SHeiko Stübner
888c6d81bd7SHeiko Stübner /* let the controller boot */
8892d538095SDirk Behme zforce_reset_deassert(ts);
890c6d81bd7SHeiko Stübner
891c6d81bd7SHeiko Stübner ts->command_waiting = NOTIFICATION_BOOTCOMPLETE;
892c6d81bd7SHeiko Stübner if (wait_for_completion_timeout(&ts->command_done, WAIT_TIMEOUT) == 0)
893c6d81bd7SHeiko Stübner dev_warn(&client->dev, "bootcomplete timed out\n");
894c6d81bd7SHeiko Stübner
895c6d81bd7SHeiko Stübner /* need to start device to get version information */
896c6d81bd7SHeiko Stübner ret = zforce_command_wait(ts, COMMAND_INITIALIZE);
897c6d81bd7SHeiko Stübner if (ret) {
898c6d81bd7SHeiko Stübner dev_err(&client->dev, "unable to initialize, %d\n", ret);
899c6d81bd7SHeiko Stübner return ret;
900c6d81bd7SHeiko Stübner }
901c6d81bd7SHeiko Stübner
902deb49819SLuis Ortega /* this gets the firmware version among other information */
903c6d81bd7SHeiko Stübner ret = zforce_command_wait(ts, COMMAND_STATUS);
904c6d81bd7SHeiko Stübner if (ret < 0) {
905c6d81bd7SHeiko Stübner dev_err(&client->dev, "couldn't get status, %d\n", ret);
906c6d81bd7SHeiko Stübner zforce_stop(ts);
907c6d81bd7SHeiko Stübner return ret;
908c6d81bd7SHeiko Stübner }
909c6d81bd7SHeiko Stübner
910c6d81bd7SHeiko Stübner /* stop device and put it into sleep until it is opened */
911c6d81bd7SHeiko Stübner ret = zforce_stop(ts);
912c6d81bd7SHeiko Stübner if (ret < 0)
913c6d81bd7SHeiko Stübner return ret;
914c6d81bd7SHeiko Stübner
915c6d81bd7SHeiko Stübner device_set_wakeup_capable(&client->dev, true);
916c6d81bd7SHeiko Stübner
917c6d81bd7SHeiko Stübner ret = input_register_device(input_dev);
918c6d81bd7SHeiko Stübner if (ret) {
919c6d81bd7SHeiko Stübner dev_err(&client->dev, "could not register input device, %d\n",
920c6d81bd7SHeiko Stübner ret);
921c6d81bd7SHeiko Stübner return ret;
922c6d81bd7SHeiko Stübner }
923c6d81bd7SHeiko Stübner
924c6d81bd7SHeiko Stübner return 0;
925c6d81bd7SHeiko Stübner }
926c6d81bd7SHeiko Stübner
927c6d81bd7SHeiko Stübner static struct i2c_device_id zforce_idtable[] = {
928c6d81bd7SHeiko Stübner { "zforce-ts", 0 },
929c6d81bd7SHeiko Stübner { }
930c6d81bd7SHeiko Stübner };
931c6d81bd7SHeiko Stübner MODULE_DEVICE_TABLE(i2c, zforce_idtable);
932c6d81bd7SHeiko Stübner
9336f2e6c9bSHeiko Stübner #ifdef CONFIG_OF
934f3f63193SJingoo Han static const struct of_device_id zforce_dt_idtable[] = {
9356f2e6c9bSHeiko Stübner { .compatible = "neonode,zforce" },
9366f2e6c9bSHeiko Stübner {},
9376f2e6c9bSHeiko Stübner };
9386f2e6c9bSHeiko Stübner MODULE_DEVICE_TABLE(of, zforce_dt_idtable);
9396f2e6c9bSHeiko Stübner #endif
9406f2e6c9bSHeiko Stübner
941c6d81bd7SHeiko Stübner static struct i2c_driver zforce_driver = {
942c6d81bd7SHeiko Stübner .driver = {
943c6d81bd7SHeiko Stübner .name = "zforce-ts",
944dc69e98aSJonathan Cameron .pm = pm_sleep_ptr(&zforce_pm_ops),
9456f2e6c9bSHeiko Stübner .of_match_table = of_match_ptr(zforce_dt_idtable),
946c6d81bd7SHeiko Stübner },
947*d8bde56dSUwe Kleine-König .probe = zforce_probe,
948c6d81bd7SHeiko Stübner .id_table = zforce_idtable,
949c6d81bd7SHeiko Stübner };
950c6d81bd7SHeiko Stübner
951c6d81bd7SHeiko Stübner module_i2c_driver(zforce_driver);
952c6d81bd7SHeiko Stübner
953c6d81bd7SHeiko Stübner MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
954c6d81bd7SHeiko Stübner MODULE_DESCRIPTION("zForce TouchScreen Driver");
955c6d81bd7SHeiko Stübner MODULE_LICENSE("GPL");
956