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