blob: ef76e69fef2ccd45e067bbe0cc9faa7fe7aa69fd [file] [log] [blame]
Mohan Pallakaa2595072012-01-12 22:23:15 +05301/*
2 *
3 * FocalTech ft5x06 TouchScreen driver.
4 *
5 * Copyright (c) 2010 Focal tech Ltd.
Mohan Pallaka3a138202013-05-09 16:30:00 +05306 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
Mohan Pallakaa2595072012-01-12 22:23:15 +05307 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 */
18
19#include <linux/i2c.h>
20#include <linux/input.h>
Mohan Pallaka959a69a2013-06-14 17:12:24 +053021#include <linux/input/mt.h>
Mohan Pallakaa2595072012-01-12 22:23:15 +053022#include <linux/slab.h>
23#include <linux/interrupt.h>
24#include <linux/delay.h>
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/gpio.h>
Mohan Pallaka3a138202013-05-09 16:30:00 +053028#include <linux/of_gpio.h>
Mohan Pallakaa2595072012-01-12 22:23:15 +053029#include <linux/regulator/consumer.h>
Mohan Pallaka6d2ab952013-06-04 17:36:20 +053030#include <linux/firmware.h>
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +053031#include <linux/debugfs.h>
Mohan Pallakaa2595072012-01-12 22:23:15 +053032#include <linux/input/ft5x06_ts.h>
33
Mohan Pallakaa5d601b2013-05-10 15:34:44 +053034#if defined(CONFIG_FB)
35#include <linux/notifier.h>
36#include <linux/fb.h>
37
38#elif defined(CONFIG_HAS_EARLYSUSPEND)
Mohan Pallakaa2595072012-01-12 22:23:15 +053039#include <linux/earlysuspend.h>
40/* Early-suspend level */
Mohan Pallaka6d2ab952013-06-04 17:36:20 +053041#define FT_SUSPEND_LEVEL 1
Mohan Pallakaa2595072012-01-12 22:23:15 +053042#endif
43
Mohan Pallakaa348d752013-08-28 13:44:36 +053044#define FT_DRIVER_VERSION 0x02
Mohan Pallakaa2595072012-01-12 22:23:15 +053045
Mohan Pallaka9eb064d2013-08-13 16:11:47 +053046#define FT_META_REGS 3
47#define FT_ONE_TCH_LEN 6
48#define FT_TCH_LEN(x) (FT_META_REGS + FT_ONE_TCH_LEN * x)
Mohan Pallakaa2595072012-01-12 22:23:15 +053049
50#define FT_PRESS 0x7F
51#define FT_MAX_ID 0x0F
Mohan Pallakaa2595072012-01-12 22:23:15 +053052#define FT_TOUCH_X_H_POS 3
53#define FT_TOUCH_X_L_POS 4
54#define FT_TOUCH_Y_H_POS 5
55#define FT_TOUCH_Y_L_POS 6
Mohan Pallaka9eb064d2013-08-13 16:11:47 +053056#define FT_TD_STATUS 2
Mohan Pallakaa2595072012-01-12 22:23:15 +053057#define FT_TOUCH_EVENT_POS 3
58#define FT_TOUCH_ID_POS 5
Mohan Pallaka9eb064d2013-08-13 16:11:47 +053059#define FT_TOUCH_DOWN 0
60#define FT_TOUCH_CONTACT 2
Mohan Pallakaa2595072012-01-12 22:23:15 +053061
62/*register address*/
Mohan Pallaka6d2ab952013-06-04 17:36:20 +053063#define FT_REG_DEV_MODE 0x00
64#define FT_DEV_MODE_REG_CAL 0x02
65#define FT_REG_ID 0xA3
66#define FT_REG_PMODE 0xA5
67#define FT_REG_FW_VER 0xA6
68#define FT_REG_POINT_RATE 0x88
69#define FT_REG_THGROUP 0x80
70#define FT_REG_ECC 0xCC
71#define FT_REG_RESET_FW 0x07
Mohan Pallakaa348d752013-08-28 13:44:36 +053072#define FT_REG_FW_MAJ_VER 0xB1
73#define FT_REG_FW_MIN_VER 0xB2
74#define FT_REG_FW_SUB_MIN_VER 0xB3
Mohan Pallakaa2595072012-01-12 22:23:15 +053075
76/* power register bits*/
Mohan Pallaka6d2ab952013-06-04 17:36:20 +053077#define FT_PMODE_ACTIVE 0x00
78#define FT_PMODE_MONITOR 0x01
79#define FT_PMODE_STANDBY 0x02
80#define FT_PMODE_HIBERNATE 0x03
81#define FT_FACTORYMODE_VALUE 0x40
82#define FT_WORKMODE_VALUE 0x00
Mohan Pallakaec271e42013-07-23 15:35:28 +053083#define FT_RST_CMD_REG1 0xFC
84#define FT_RST_CMD_REG2 0xBC
Mohan Pallaka6d2ab952013-06-04 17:36:20 +053085#define FT_READ_ID_REG 0x90
86#define FT_ERASE_APP_REG 0x61
87#define FT_ERASE_PANEL_REG 0x63
88#define FT_FW_START_REG 0xBF
Mohan Pallakaa2595072012-01-12 22:23:15 +053089
Figo Wangd21893a2013-07-18 15:15:03 +080090#define FT_STATUS_NUM_TP_MASK 0x0F
Mohan Pallakaa2595072012-01-12 22:23:15 +053091
Mohan Pallaka6d2ab952013-06-04 17:36:20 +053092#define FT_VTG_MIN_UV 2600000
93#define FT_VTG_MAX_UV 3300000
94#define FT_I2C_VTG_MIN_UV 1800000
95#define FT_I2C_VTG_MAX_UV 1800000
96
97#define FT_COORDS_ARR_SIZE 4
Mohan Pallaka3a138202013-05-09 16:30:00 +053098#define MAX_BUTTONS 4
99
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530100#define FT_8BIT_SHIFT 8
101#define FT_4BIT_SHIFT 4
102#define FT_FW_NAME_MAX_LEN 50
103
104#define FT5316_ID 0x0A
105#define FT5306I_ID 0x55
Mohan Pallakaec271e42013-07-23 15:35:28 +0530106#define FT6X06_ID 0x06
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530107
108#define FT_UPGRADE_AA 0xAA
109#define FT_UPGRADE_55 0x55
110
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530111#define FT_FW_MIN_SIZE 8
112#define FT_FW_MAX_SIZE 32768
Mohan Pallakaa348d752013-08-28 13:44:36 +0530113
114/* Firmware file is not supporting minor and sub minor so use 0 */
115#define FT_FW_FILE_MAJ_VER(x) ((x)->data[(x)->size - 2])
116#define FT_FW_FILE_MIN_VER(x) 0
117#define FT_FW_FILE_SUB_MIN_VER(x) 0
118
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530119#define FT_FW_CHECK(x) \
120 (((x)->data[(x)->size - 8] ^ (x)->data[(x)->size - 6]) == 0xFF \
121 && (((x)->data[(x)->size - 7] ^ (x)->data[(x)->size - 5]) == 0xFF \
122 && (((x)->data[(x)->size - 3] ^ (x)->data[(x)->size - 4]) == 0xFF)))
123
124#define FT_MAX_TRIES 5
125#define FT_RETRY_DLY 20
126
127#define FT_MAX_WR_BUF 10
128#define FT_MAX_RD_BUF 2
129#define FT_FW_PKT_LEN 128
130#define FT_FW_PKT_META_LEN 6
131#define FT_FW_PKT_DLY_MS 20
132#define FT_FW_LAST_PKT 0x6ffa
133#define FT_EARSE_DLY_MS 100
134
Mohan Pallakaec271e42013-07-23 15:35:28 +0530135#define FT_UPGRADE_LOOP 10
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530136#define FT_CAL_START 0x04
137#define FT_CAL_FIN 0x00
138#define FT_CAL_STORE 0x05
139#define FT_CAL_RETRY 100
140#define FT_REG_CAL 0x00
141#define FT_CAL_MASK 0x70
142
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530143#define FT_INFO_MAX_LEN 512
Mohan Pallaka768d5e32013-06-14 17:50:10 +0530144
Mohan Pallakaa348d752013-08-28 13:44:36 +0530145#define FT_STORE_TS_INFO(buf, id, name, max_tch, group_id, fw_vkey_support, \
146 fw_name, fw_maj, fw_min, fw_sub_min) \
Mohan Pallaka768d5e32013-06-14 17:50:10 +0530147 snprintf(buf, FT_INFO_MAX_LEN, \
148 "controller\t= focaltech\n" \
149 "model\t\t= 0x%x\n" \
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530150 "name\t\t= %s\n" \
151 "max_touches\t= %d\n" \
152 "drv_ver\t\t= 0x%x\n" \
153 "group_id\t= 0x%x\n" \
Mohan Pallakaa348d752013-08-28 13:44:36 +0530154 "fw_vkey_support\t= %s\n" \
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530155 "fw_name\t\t= %s\n" \
Mohan Pallakaa348d752013-08-28 13:44:36 +0530156 "fw_ver\t\t= %d.%d.%d\n", id, name, \
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530157 max_tch, FT_DRIVER_VERSION, group_id, \
Mohan Pallakaa348d752013-08-28 13:44:36 +0530158 fw_vkey_support, fw_name, fw_maj, fw_min, \
159 fw_sub_min)
Mohan Pallaka768d5e32013-06-14 17:50:10 +0530160
161#define FT_DEBUG_DIR_NAME "ts_debug"
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530162
Mohan Pallakaa2595072012-01-12 22:23:15 +0530163struct ft5x06_ts_data {
164 struct i2c_client *client;
165 struct input_dev *input_dev;
Mohan Pallakaa2595072012-01-12 22:23:15 +0530166 const struct ft5x06_ts_platform_data *pdata;
167 struct regulator *vdd;
168 struct regulator *vcc_i2c;
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530169 char fw_name[FT_FW_NAME_MAX_LEN];
170 bool loading_fw;
171 u8 family_id;
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530172 struct dentry *dir;
173 u16 addr;
174 bool suspended;
Mohan Pallaka768d5e32013-06-14 17:50:10 +0530175 char *ts_info;
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530176 u8 *tch_data;
177 u32 tch_data_len;
Mohan Pallakaa348d752013-08-28 13:44:36 +0530178 u8 fw_ver[3];
Mohan Pallakaa5d601b2013-05-10 15:34:44 +0530179#if defined(CONFIG_FB)
180 struct notifier_block fb_notif;
181#elif defined(CONFIG_HAS_EARLYSUSPEND)
Mohan Pallakaa2595072012-01-12 22:23:15 +0530182 struct early_suspend early_suspend;
183#endif
184};
185
186static int ft5x06_i2c_read(struct i2c_client *client, char *writebuf,
187 int writelen, char *readbuf, int readlen)
188{
189 int ret;
190
191 if (writelen > 0) {
192 struct i2c_msg msgs[] = {
193 {
194 .addr = client->addr,
195 .flags = 0,
196 .len = writelen,
197 .buf = writebuf,
198 },
199 {
200 .addr = client->addr,
201 .flags = I2C_M_RD,
202 .len = readlen,
203 .buf = readbuf,
204 },
205 };
206 ret = i2c_transfer(client->adapter, msgs, 2);
207 if (ret < 0)
208 dev_err(&client->dev, "%s: i2c read error.\n",
209 __func__);
210 } else {
211 struct i2c_msg msgs[] = {
212 {
213 .addr = client->addr,
214 .flags = I2C_M_RD,
215 .len = readlen,
216 .buf = readbuf,
217 },
218 };
219 ret = i2c_transfer(client->adapter, msgs, 1);
220 if (ret < 0)
221 dev_err(&client->dev, "%s:i2c read error.\n", __func__);
222 }
223 return ret;
224}
225
226static int ft5x06_i2c_write(struct i2c_client *client, char *writebuf,
227 int writelen)
228{
229 int ret;
230
231 struct i2c_msg msgs[] = {
232 {
233 .addr = client->addr,
234 .flags = 0,
235 .len = writelen,
236 .buf = writebuf,
237 },
238 };
239 ret = i2c_transfer(client->adapter, msgs, 1);
240 if (ret < 0)
241 dev_err(&client->dev, "%s: i2c write error.\n", __func__);
242
243 return ret;
244}
245
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530246static int ft5x0x_write_reg(struct i2c_client *client, u8 addr, const u8 val)
247{
248 u8 buf[2] = {0};
249
250 buf[0] = addr;
251 buf[1] = val;
252
253 return ft5x06_i2c_write(client, buf, sizeof(buf));
254}
255
256static int ft5x0x_read_reg(struct i2c_client *client, u8 addr, u8 *val)
257{
258 return ft5x06_i2c_read(client, &addr, 1, val, 1);
259}
260
Mohan Pallakaa348d752013-08-28 13:44:36 +0530261static void ft5x06_update_fw_ver(struct ft5x06_ts_data *data)
262{
263 struct i2c_client *client = data->client;
264 u8 reg_addr;
265 int err;
266
267 reg_addr = FT_REG_FW_MAJ_VER;
268 err = ft5x06_i2c_read(client, &reg_addr, 1, &data->fw_ver[0], 1);
269 if (err < 0)
270 dev_err(&client->dev, "fw major version read failed");
271
272 reg_addr = FT_REG_FW_MIN_VER;
273 err = ft5x06_i2c_read(client, &reg_addr, 1, &data->fw_ver[1], 1);
274 if (err < 0)
275 dev_err(&client->dev, "fw minor version read failed");
276
277 reg_addr = FT_REG_FW_SUB_MIN_VER;
278 err = ft5x06_i2c_read(client, &reg_addr, 1, &data->fw_ver[2], 1);
279 if (err < 0)
280 dev_err(&client->dev, "fw sub minor version read failed");
281
282 dev_info(&client->dev, "Firmware version = %d.%d.%d\n",
283 data->fw_ver[0], data->fw_ver[1], data->fw_ver[2]);
284}
285
Mohan Pallakaa2595072012-01-12 22:23:15 +0530286static irqreturn_t ft5x06_ts_interrupt(int irq, void *dev_id)
287{
288 struct ft5x06_ts_data *data = dev_id;
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530289 struct input_dev *ip_dev;
290 int rc, i;
Bingzhe Cai4deceb32013-10-25 00:28:21 +0800291 u32 id, x, y, status, num_touches;
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530292 u8 reg = 0x00, *buf;
293 bool update_input = false;
Mohan Pallakaa2595072012-01-12 22:23:15 +0530294
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530295 if (!data) {
296 pr_err("%s: Invalid data\n", __func__);
297 return IRQ_HANDLED;
298 }
299
300 ip_dev = data->input_dev;
301 buf = data->tch_data;
302
303 rc = ft5x06_i2c_read(data->client, &reg, 1,
304 buf, data->tch_data_len);
305 if (rc < 0) {
306 dev_err(&data->client->dev, "%s: read data fail\n", __func__);
307 return IRQ_HANDLED;
308 }
309
310 for (i = 0; i < data->pdata->num_max_touches; i++) {
311 id = (buf[FT_TOUCH_ID_POS + FT_ONE_TCH_LEN * i]) >> 4;
312 if (id >= FT_MAX_ID)
313 break;
314
315 update_input = true;
316
317 x = (buf[FT_TOUCH_X_H_POS + FT_ONE_TCH_LEN * i] & 0x0F) << 8 |
318 (buf[FT_TOUCH_X_L_POS + FT_ONE_TCH_LEN * i]);
319 y = (buf[FT_TOUCH_Y_H_POS + FT_ONE_TCH_LEN * i] & 0x0F) << 8 |
320 (buf[FT_TOUCH_Y_L_POS + FT_ONE_TCH_LEN * i]);
321
322 status = buf[FT_TOUCH_EVENT_POS + FT_ONE_TCH_LEN * i] >> 6;
323
324 num_touches = buf[FT_TD_STATUS] & FT_STATUS_NUM_TP_MASK;
325
326 /* invalid combination */
327 if (!num_touches && !status && !id)
328 break;
329
330 input_mt_slot(ip_dev, id);
331 if (status == FT_TOUCH_DOWN || status == FT_TOUCH_CONTACT) {
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530332 input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 1);
333 input_report_abs(ip_dev, ABS_MT_POSITION_X, x);
334 input_report_abs(ip_dev, ABS_MT_POSITION_Y, y);
Mohan Pallakaa348d752013-08-28 13:44:36 +0530335 } else {
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530336 input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 0);
Mohan Pallakaa348d752013-08-28 13:44:36 +0530337 }
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530338 }
339
340 if (update_input) {
341 input_mt_report_pointer_emulation(ip_dev, false);
342 input_sync(ip_dev);
343 }
Mohan Pallakaa2595072012-01-12 22:23:15 +0530344
345 return IRQ_HANDLED;
346}
347
348static int ft5x06_power_on(struct ft5x06_ts_data *data, bool on)
349{
350 int rc;
351
352 if (!on)
353 goto power_off;
354
355 rc = regulator_enable(data->vdd);
356 if (rc) {
357 dev_err(&data->client->dev,
358 "Regulator vdd enable failed rc=%d\n", rc);
359 return rc;
360 }
361
362 rc = regulator_enable(data->vcc_i2c);
363 if (rc) {
364 dev_err(&data->client->dev,
365 "Regulator vcc_i2c enable failed rc=%d\n", rc);
366 regulator_disable(data->vdd);
367 }
368
369 return rc;
370
371power_off:
372 rc = regulator_disable(data->vdd);
373 if (rc) {
374 dev_err(&data->client->dev,
375 "Regulator vdd disable failed rc=%d\n", rc);
376 return rc;
377 }
378
379 rc = regulator_disable(data->vcc_i2c);
380 if (rc) {
381 dev_err(&data->client->dev,
382 "Regulator vcc_i2c disable failed rc=%d\n", rc);
383 regulator_enable(data->vdd);
384 }
385
386 return rc;
387}
388
389static int ft5x06_power_init(struct ft5x06_ts_data *data, bool on)
390{
391 int rc;
392
393 if (!on)
394 goto pwr_deinit;
395
396 data->vdd = regulator_get(&data->client->dev, "vdd");
397 if (IS_ERR(data->vdd)) {
398 rc = PTR_ERR(data->vdd);
399 dev_err(&data->client->dev,
400 "Regulator get failed vdd rc=%d\n", rc);
401 return rc;
402 }
403
404 if (regulator_count_voltages(data->vdd) > 0) {
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530405 rc = regulator_set_voltage(data->vdd, FT_VTG_MIN_UV,
406 FT_VTG_MAX_UV);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530407 if (rc) {
408 dev_err(&data->client->dev,
409 "Regulator set_vtg failed vdd rc=%d\n", rc);
410 goto reg_vdd_put;
411 }
412 }
413
414 data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c");
415 if (IS_ERR(data->vcc_i2c)) {
416 rc = PTR_ERR(data->vcc_i2c);
417 dev_err(&data->client->dev,
418 "Regulator get failed vcc_i2c rc=%d\n", rc);
419 goto reg_vdd_set_vtg;
420 }
421
422 if (regulator_count_voltages(data->vcc_i2c) > 0) {
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530423 rc = regulator_set_voltage(data->vcc_i2c, FT_I2C_VTG_MIN_UV,
424 FT_I2C_VTG_MAX_UV);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530425 if (rc) {
426 dev_err(&data->client->dev,
427 "Regulator set_vtg failed vcc_i2c rc=%d\n", rc);
428 goto reg_vcc_i2c_put;
429 }
430 }
431
432 return 0;
433
434reg_vcc_i2c_put:
435 regulator_put(data->vcc_i2c);
436reg_vdd_set_vtg:
437 if (regulator_count_voltages(data->vdd) > 0)
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530438 regulator_set_voltage(data->vdd, 0, FT_VTG_MAX_UV);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530439reg_vdd_put:
440 regulator_put(data->vdd);
441 return rc;
442
443pwr_deinit:
444 if (regulator_count_voltages(data->vdd) > 0)
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530445 regulator_set_voltage(data->vdd, 0, FT_VTG_MAX_UV);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530446
447 regulator_put(data->vdd);
448
449 if (regulator_count_voltages(data->vcc_i2c) > 0)
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530450 regulator_set_voltage(data->vcc_i2c, 0, FT_I2C_VTG_MAX_UV);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530451
452 regulator_put(data->vcc_i2c);
453 return 0;
454}
455
456#ifdef CONFIG_PM
457static int ft5x06_ts_suspend(struct device *dev)
458{
459 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
Figo Wang63ad82b2013-06-28 19:49:49 +0800460 char txbuf[2], i;
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530461 int err;
Mohan Pallakaa2595072012-01-12 22:23:15 +0530462
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530463 if (data->loading_fw) {
464 dev_info(dev, "Firmware loading in process...\n");
465 return 0;
466 }
467
468 if (data->suspended) {
469 dev_info(dev, "Already in suspend state\n");
470 return 0;
471 }
472
Mohan Pallakaa2595072012-01-12 22:23:15 +0530473 disable_irq(data->client->irq);
474
Figo Wang63ad82b2013-06-28 19:49:49 +0800475 /* release all touches */
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530476 for (i = 0; i < data->pdata->num_max_touches; i++) {
Figo Wang63ad82b2013-06-28 19:49:49 +0800477 input_mt_slot(data->input_dev, i);
478 input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, 0);
479 }
Bingzhe Cai4deceb32013-10-25 00:28:21 +0800480 input_mt_report_pointer_emulation(data->input_dev, false);
Figo Wang63ad82b2013-06-28 19:49:49 +0800481 input_sync(data->input_dev);
482
Mohan Pallakaa2595072012-01-12 22:23:15 +0530483 if (gpio_is_valid(data->pdata->reset_gpio)) {
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530484 txbuf[0] = FT_REG_PMODE;
485 txbuf[1] = FT_PMODE_HIBERNATE;
Mohan Pallakaa2595072012-01-12 22:23:15 +0530486 ft5x06_i2c_write(data->client, txbuf, sizeof(txbuf));
487 }
488
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530489 if (data->pdata->power_on) {
490 err = data->pdata->power_on(false);
491 if (err) {
492 dev_err(dev, "power off failed");
493 goto pwr_off_fail;
494 }
495 } else {
496 err = ft5x06_power_on(data, false);
497 if (err) {
498 dev_err(dev, "power off failed");
499 goto pwr_off_fail;
500 }
501 }
502
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530503 data->suspended = true;
504
Mohan Pallakaa2595072012-01-12 22:23:15 +0530505 return 0;
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530506
507pwr_off_fail:
508 if (gpio_is_valid(data->pdata->reset_gpio)) {
509 gpio_set_value_cansleep(data->pdata->reset_gpio, 0);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530510 msleep(data->pdata->hard_rst_dly);
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530511 gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
512 }
513 enable_irq(data->client->irq);
514 return err;
Mohan Pallakaa2595072012-01-12 22:23:15 +0530515}
516
517static int ft5x06_ts_resume(struct device *dev)
518{
519 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530520 int err;
Mohan Pallakaa2595072012-01-12 22:23:15 +0530521
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530522 if (!data->suspended) {
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530523 dev_dbg(dev, "Already in awake state\n");
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530524 return 0;
525 }
526
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530527 if (data->pdata->power_on) {
528 err = data->pdata->power_on(true);
529 if (err) {
530 dev_err(dev, "power on failed");
531 return err;
532 }
533 } else {
534 err = ft5x06_power_on(data, true);
535 if (err) {
536 dev_err(dev, "power on failed");
537 return err;
538 }
539 }
540
Mohan Pallakaa2595072012-01-12 22:23:15 +0530541 if (gpio_is_valid(data->pdata->reset_gpio)) {
542 gpio_set_value_cansleep(data->pdata->reset_gpio, 0);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530543 msleep(data->pdata->hard_rst_dly);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530544 gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
545 }
Mohan Pallakaec271e42013-07-23 15:35:28 +0530546
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530547 msleep(data->pdata->soft_rst_dly);
Mohan Pallakaec271e42013-07-23 15:35:28 +0530548
Mohan Pallakaa2595072012-01-12 22:23:15 +0530549 enable_irq(data->client->irq);
550
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530551 data->suspended = false;
552
Mohan Pallakaa2595072012-01-12 22:23:15 +0530553 return 0;
554}
555
Mohan Pallakaa5d601b2013-05-10 15:34:44 +0530556#if defined(CONFIG_FB)
557static int fb_notifier_callback(struct notifier_block *self,
558 unsigned long event, void *data)
559{
560 struct fb_event *evdata = data;
561 int *blank;
562 struct ft5x06_ts_data *ft5x06_data =
563 container_of(self, struct ft5x06_ts_data, fb_notif);
564
565 if (evdata && evdata->data && event == FB_EVENT_BLANK &&
566 ft5x06_data && ft5x06_data->client) {
567 blank = evdata->data;
568 if (*blank == FB_BLANK_UNBLANK)
569 ft5x06_ts_resume(&ft5x06_data->client->dev);
570 else if (*blank == FB_BLANK_POWERDOWN)
571 ft5x06_ts_suspend(&ft5x06_data->client->dev);
572 }
573
574 return 0;
575}
576#elif defined(CONFIG_HAS_EARLYSUSPEND)
Mohan Pallakaa2595072012-01-12 22:23:15 +0530577static void ft5x06_ts_early_suspend(struct early_suspend *handler)
578{
579 struct ft5x06_ts_data *data = container_of(handler,
580 struct ft5x06_ts_data,
581 early_suspend);
582
583 ft5x06_ts_suspend(&data->client->dev);
584}
585
586static void ft5x06_ts_late_resume(struct early_suspend *handler)
587{
588 struct ft5x06_ts_data *data = container_of(handler,
589 struct ft5x06_ts_data,
590 early_suspend);
591
592 ft5x06_ts_resume(&data->client->dev);
593}
594#endif
595
596static const struct dev_pm_ops ft5x06_ts_pm_ops = {
Mohan Pallakaa5d601b2013-05-10 15:34:44 +0530597#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND))
Mohan Pallakaa2595072012-01-12 22:23:15 +0530598 .suspend = ft5x06_ts_suspend,
599 .resume = ft5x06_ts_resume,
600#endif
601};
602#endif
603
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530604static int ft5x06_auto_cal(struct i2c_client *client)
605{
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530606 struct ft5x06_ts_data *data = i2c_get_clientdata(client);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530607 u8 temp = 0, i;
608
609 /* set to factory mode */
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530610 msleep(2 * data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530611 ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530612 msleep(data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530613
614 /* start calibration */
615 ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_START);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530616 msleep(2 * data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530617 for (i = 0; i < FT_CAL_RETRY; i++) {
618 ft5x0x_read_reg(client, FT_REG_CAL, &temp);
619 /*return to normal mode, calibration finish */
620 if (((temp & FT_CAL_MASK) >> FT_4BIT_SHIFT) == FT_CAL_FIN)
621 break;
622 }
623
624 /*calibration OK */
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530625 msleep(2 * data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530626 ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530627 msleep(data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530628
629 /* store calibration data */
630 ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_STORE);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530631 msleep(2 * data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530632
633 /* set to normal mode */
634 ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_WORKMODE_VALUE);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530635 msleep(2 * data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530636
637 return 0;
638}
639
640static int ft5x06_fw_upgrade_start(struct i2c_client *client,
641 const u8 *data, u32 data_len)
642{
643 struct ft5x06_ts_data *ts_data = i2c_get_clientdata(client);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530644 struct fw_upgrade_info info = ts_data->pdata->info;
Mohan Pallakaec271e42013-07-23 15:35:28 +0530645 u8 reset_reg;
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530646 u8 w_buf[FT_MAX_WR_BUF] = {0}, r_buf[FT_MAX_RD_BUF] = {0};
647 u8 pkt_buf[FT_FW_PKT_LEN + FT_FW_PKT_META_LEN];
648 int rc, i, j, temp;
649 u32 pkt_num, pkt_len;
650 u8 fw_ecc;
651
Mohan Pallakaec271e42013-07-23 15:35:28 +0530652 for (i = 0, j = 0; i < FT_UPGRADE_LOOP; i++) {
653 /* reset - write 0xaa and 0x55 to reset register */
654 if (ts_data->family_id == FT6X06_ID)
655 reset_reg = FT_RST_CMD_REG2;
656 else
657 reset_reg = FT_RST_CMD_REG1;
658
659 ft5x0x_write_reg(client, reset_reg, FT_UPGRADE_AA);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530660 msleep(info.delay_aa);
661
Mohan Pallakaec271e42013-07-23 15:35:28 +0530662 ft5x0x_write_reg(client, reset_reg, FT_UPGRADE_55);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530663 msleep(info.delay_55);
664
665 /* Enter upgrade mode */
666 w_buf[0] = FT_UPGRADE_55;
667 w_buf[1] = FT_UPGRADE_AA;
668 do {
Mohan Pallakaec271e42013-07-23 15:35:28 +0530669 j++;
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530670 rc = ft5x06_i2c_write(client, w_buf, 2);
671 msleep(FT_RETRY_DLY);
Mohan Pallakaec271e42013-07-23 15:35:28 +0530672 } while (rc <= 0 && j < FT_MAX_TRIES);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530673
674 /* check READ_ID */
675 msleep(info.delay_readid);
676 w_buf[0] = FT_READ_ID_REG;
677 w_buf[1] = 0x00;
678 w_buf[2] = 0x00;
679 w_buf[3] = 0x00;
680
681 ft5x06_i2c_read(client, w_buf, 4, r_buf, 2);
682
683 if (r_buf[0] != info.upgrade_id_1
684 || r_buf[1] != info.upgrade_id_2) {
685 dev_err(&client->dev, "Upgrade ID mismatch(%d)\n", i);
686 } else
687 break;
688 }
689
690 if (i >= FT_UPGRADE_LOOP) {
691 dev_err(&client->dev, "Abort upgrade\n");
692 return -EIO;
693 }
694
695 /* erase app and panel paramenter area */
696 w_buf[0] = FT_ERASE_APP_REG;
697 ft5x06_i2c_write(client, w_buf, 1);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530698 msleep(info.delay_erase_flash);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530699
700 w_buf[0] = FT_ERASE_PANEL_REG;
701 ft5x06_i2c_write(client, w_buf, 1);
702 msleep(FT_EARSE_DLY_MS);
703
704 /* program firmware */
705 data_len = data_len - 8;
706 pkt_num = (data_len) / FT_FW_PKT_LEN;
707 pkt_len = FT_FW_PKT_LEN;
708 pkt_buf[0] = FT_FW_START_REG;
709 pkt_buf[1] = 0x00;
710 fw_ecc = 0;
711
712 for (i = 0; i < pkt_num; i++) {
713 temp = i * FT_FW_PKT_LEN;
714 pkt_buf[2] = (u8) (temp >> FT_8BIT_SHIFT);
715 pkt_buf[3] = (u8) temp;
716 pkt_buf[4] = (u8) (pkt_len >> FT_8BIT_SHIFT);
717 pkt_buf[5] = (u8) pkt_len;
718
719 for (j = 0; j < FT_FW_PKT_LEN; j++) {
720 pkt_buf[6 + j] = data[i * FT_FW_PKT_LEN + j];
721 fw_ecc ^= pkt_buf[6 + j];
722 }
723
724 ft5x06_i2c_write(client, pkt_buf,
725 FT_FW_PKT_LEN + FT_FW_PKT_META_LEN);
726 msleep(FT_FW_PKT_DLY_MS);
727 }
728
729 /* send remaining bytes */
730 if ((data_len) % FT_FW_PKT_LEN > 0) {
731 temp = pkt_num * FT_FW_PKT_LEN;
732 pkt_buf[2] = (u8) (temp >> FT_8BIT_SHIFT);
733 pkt_buf[3] = (u8) temp;
734 temp = (data_len) % FT_FW_PKT_LEN;
735 pkt_buf[4] = (u8) (temp >> FT_8BIT_SHIFT);
736 pkt_buf[5] = (u8) temp;
737
738 for (i = 0; i < temp; i++) {
739 pkt_buf[6 + i] = data[pkt_num * FT_FW_PKT_LEN + i];
740 fw_ecc ^= pkt_buf[6 + i];
741 }
742
743 ft5x06_i2c_write(client, pkt_buf, temp + FT_FW_PKT_META_LEN);
744 msleep(FT_FW_PKT_DLY_MS);
745 }
746
747 /* send the finishing packet */
748 for (i = 0; i < 6; i++) {
749 temp = FT_FW_LAST_PKT + i;
750 pkt_buf[2] = (u8) (temp >> 8);
751 pkt_buf[3] = (u8) temp;
752 temp = 1;
753 pkt_buf[4] = (u8) (temp >> 8);
754 pkt_buf[5] = (u8) temp;
755 pkt_buf[6] = data[data_len + i];
756 fw_ecc ^= pkt_buf[6];
757 ft5x06_i2c_write(client, pkt_buf, temp + FT_FW_PKT_META_LEN);
758 msleep(FT_FW_PKT_DLY_MS);
759 }
760
761 /* verify checksum */
762 w_buf[0] = FT_REG_ECC;
763 ft5x06_i2c_read(client, w_buf, 1, r_buf, 1);
764 if (r_buf[0] != fw_ecc) {
765 dev_err(&client->dev, "ECC error! dev_ecc=%02x fw_ecc=%02x\n",
766 r_buf[0], fw_ecc);
767 return -EIO;
768 }
769
770 /* reset */
771 w_buf[0] = FT_REG_RESET_FW;
772 ft5x06_i2c_write(client, w_buf, 1);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530773 msleep(ts_data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530774
Mohan Pallakaec271e42013-07-23 15:35:28 +0530775 dev_info(&client->dev, "Firmware upgrade successful\n");
776
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530777 return 0;
778}
779
780static int ft5x06_fw_upgrade(struct device *dev, bool force)
781{
782 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
783 const struct firmware *fw = NULL;
784 int rc;
Mohan Pallakaa348d752013-08-28 13:44:36 +0530785 u8 fw_file_maj, fw_file_min, fw_file_sub_min;
786 bool fw_upgrade = false;
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530787
788 rc = request_firmware(&fw, data->fw_name, dev);
789 if (rc < 0) {
790 dev_err(dev, "Request firmware failed - %s (%d)\n",
791 data->fw_name, rc);
792 return rc;
793 }
794
795 if (fw->size < FT_FW_MIN_SIZE || fw->size > FT_FW_MAX_SIZE) {
796 dev_err(dev, "Invalid firmware size (%d)\n", fw->size);
797 rc = -EIO;
798 goto rel_fw;
799 }
800
Mohan Pallakaa348d752013-08-28 13:44:36 +0530801 fw_file_maj = FT_FW_FILE_MAJ_VER(fw);
802 fw_file_min = FT_FW_FILE_MIN_VER(fw);
803 fw_file_sub_min = FT_FW_FILE_SUB_MIN_VER(fw);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530804
Mohan Pallakaa348d752013-08-28 13:44:36 +0530805 dev_info(dev, "Current firmware: %d.%d.%d", data->fw_ver[0],
806 data->fw_ver[1], data->fw_ver[2]);
807 dev_info(dev, "New firmware: %d.%d.%d", fw_file_maj,
808 fw_file_min, fw_file_sub_min);
809
810 if (force) {
811 fw_upgrade = true;
812 } else if (data->fw_ver[0] == fw_file_maj) {
813 if (data->fw_ver[1] < fw_file_min)
814 fw_upgrade = true;
815 else if (data->fw_ver[2] < fw_file_sub_min)
816 fw_upgrade = true;
817 else
818 dev_info(dev, "No need to upgrade\n");
819 } else
820 dev_info(dev, "Firmware versions do not match\n");
821
822 if (!fw_upgrade) {
823 dev_info(dev, "Exiting fw upgrade...\n");
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530824 rc = -EFAULT;
825 goto rel_fw;
826 }
827
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530828 /* start firmware upgrade */
829 if (FT_FW_CHECK(fw)) {
830 rc = ft5x06_fw_upgrade_start(data->client, fw->data, fw->size);
831 if (rc < 0)
Mohan Pallakaa348d752013-08-28 13:44:36 +0530832 dev_err(dev, "update failed (%d). try later...\n", rc);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530833 else if (data->pdata->info.auto_cal)
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530834 ft5x06_auto_cal(data->client);
835 } else {
836 dev_err(dev, "FW format error\n");
837 rc = -EIO;
838 }
839
Mohan Pallakaa348d752013-08-28 13:44:36 +0530840 ft5x06_update_fw_ver(data);
841
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530842 FT_STORE_TS_INFO(data->ts_info, data->family_id, data->pdata->name,
843 data->pdata->num_max_touches, data->pdata->group_id,
Mohan Pallakaa348d752013-08-28 13:44:36 +0530844 data->pdata->fw_vkey_support ? "yes" : "no",
845 data->pdata->fw_name, data->fw_ver[0],
846 data->fw_ver[1], data->fw_ver[2]);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530847rel_fw:
848 release_firmware(fw);
849 return rc;
850}
851
852static ssize_t ft5x06_update_fw_show(struct device *dev,
853 struct device_attribute *attr, char *buf)
854{
855 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
856 return snprintf(buf, 2, "%d\n", data->loading_fw);
857}
858
859static ssize_t ft5x06_update_fw_store(struct device *dev,
860 struct device_attribute *attr,
861 const char *buf, size_t size)
862{
863 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
864 unsigned long val;
865 int rc;
866
867 if (size > 2)
868 return -EINVAL;
869
870 rc = kstrtoul(buf, 10, &val);
871 if (rc != 0)
872 return rc;
873
Mohan Pallakaa348d752013-08-28 13:44:36 +0530874 if (data->suspended) {
875 dev_info(dev, "In suspend state, try again later...\n");
876 return size;
877 }
878
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530879 mutex_lock(&data->input_dev->mutex);
880 if (!data->loading_fw && val) {
881 data->loading_fw = true;
882 ft5x06_fw_upgrade(dev, false);
883 data->loading_fw = false;
884 }
885 mutex_unlock(&data->input_dev->mutex);
886
887 return size;
888}
889
890static DEVICE_ATTR(update_fw, 0664, ft5x06_update_fw_show,
891 ft5x06_update_fw_store);
892
893static ssize_t ft5x06_force_update_fw_store(struct device *dev,
894 struct device_attribute *attr,
895 const char *buf, size_t size)
896{
897 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
898 unsigned long val;
899 int rc;
900
901 if (size > 2)
902 return -EINVAL;
903
904 rc = kstrtoul(buf, 10, &val);
905 if (rc != 0)
906 return rc;
907
908 mutex_lock(&data->input_dev->mutex);
909 if (!data->loading_fw && val) {
910 data->loading_fw = true;
911 ft5x06_fw_upgrade(dev, true);
912 data->loading_fw = false;
913 }
914 mutex_unlock(&data->input_dev->mutex);
915
916 return size;
917}
918
919static DEVICE_ATTR(force_update_fw, 0664, ft5x06_update_fw_show,
920 ft5x06_force_update_fw_store);
921
922static ssize_t ft5x06_fw_name_show(struct device *dev,
923 struct device_attribute *attr, char *buf)
924{
925 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
926 return snprintf(buf, FT_FW_NAME_MAX_LEN - 1, "%s\n", data->fw_name);
927}
928
929static ssize_t ft5x06_fw_name_store(struct device *dev,
930 struct device_attribute *attr,
931 const char *buf, size_t size)
932{
933 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
934
935 if (size > FT_FW_NAME_MAX_LEN - 1)
936 return -EINVAL;
937
938 strlcpy(data->fw_name, buf, size);
939 if (data->fw_name[size-1] == '\n')
940 data->fw_name[size-1] = 0;
941
942 return size;
943}
944
945static DEVICE_ATTR(fw_name, 0664, ft5x06_fw_name_show, ft5x06_fw_name_store);
946
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530947static bool ft5x06_debug_addr_is_valid(int addr)
948{
949 if (addr < 0 || addr > 0xFF) {
950 pr_err("FT reg address is invalid: 0x%x\n", addr);
951 return false;
952 }
953
954 return true;
955}
956
957static int ft5x06_debug_data_set(void *_data, u64 val)
958{
959 struct ft5x06_ts_data *data = _data;
960
961 mutex_lock(&data->input_dev->mutex);
962
963 if (ft5x06_debug_addr_is_valid(data->addr))
964 dev_info(&data->client->dev,
965 "Writing into FT registers not supported\n");
966
967 mutex_unlock(&data->input_dev->mutex);
968
969 return 0;
970}
971
972static int ft5x06_debug_data_get(void *_data, u64 *val)
973{
974 struct ft5x06_ts_data *data = _data;
975 int rc;
976 u8 reg;
977
978 mutex_lock(&data->input_dev->mutex);
979
980 if (ft5x06_debug_addr_is_valid(data->addr)) {
981 rc = ft5x0x_read_reg(data->client, data->addr, &reg);
982 if (rc < 0)
983 dev_err(&data->client->dev,
984 "FT read register 0x%x failed (%d)\n",
985 data->addr, rc);
986 else
987 *val = reg;
988 }
989
990 mutex_unlock(&data->input_dev->mutex);
991
992 return 0;
993}
994
995DEFINE_SIMPLE_ATTRIBUTE(debug_data_fops, ft5x06_debug_data_get,
996 ft5x06_debug_data_set, "0x%02llX\n");
997
998static int ft5x06_debug_addr_set(void *_data, u64 val)
999{
1000 struct ft5x06_ts_data *data = _data;
1001
1002 if (ft5x06_debug_addr_is_valid(val)) {
1003 mutex_lock(&data->input_dev->mutex);
1004 data->addr = val;
1005 mutex_unlock(&data->input_dev->mutex);
1006 }
1007
1008 return 0;
1009}
1010
1011static int ft5x06_debug_addr_get(void *_data, u64 *val)
1012{
1013 struct ft5x06_ts_data *data = _data;
1014
1015 mutex_lock(&data->input_dev->mutex);
1016
1017 if (ft5x06_debug_addr_is_valid(data->addr))
1018 *val = data->addr;
1019
1020 mutex_unlock(&data->input_dev->mutex);
1021
1022 return 0;
1023}
1024
1025DEFINE_SIMPLE_ATTRIBUTE(debug_addr_fops, ft5x06_debug_addr_get,
1026 ft5x06_debug_addr_set, "0x%02llX\n");
1027
1028static int ft5x06_debug_suspend_set(void *_data, u64 val)
1029{
1030 struct ft5x06_ts_data *data = _data;
1031
1032 mutex_lock(&data->input_dev->mutex);
1033
1034 if (val)
1035 ft5x06_ts_suspend(&data->client->dev);
1036 else
1037 ft5x06_ts_resume(&data->client->dev);
1038
1039 mutex_unlock(&data->input_dev->mutex);
1040
1041 return 0;
1042}
1043
1044static int ft5x06_debug_suspend_get(void *_data, u64 *val)
1045{
1046 struct ft5x06_ts_data *data = _data;
1047
1048 mutex_lock(&data->input_dev->mutex);
1049 *val = data->suspended;
1050 mutex_unlock(&data->input_dev->mutex);
1051
1052 return 0;
1053}
1054
1055DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, ft5x06_debug_suspend_get,
1056 ft5x06_debug_suspend_set, "%lld\n");
1057
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301058static int ft5x06_debug_dump_info(struct seq_file *m, void *v)
1059{
1060 struct ft5x06_ts_data *data = m->private;
1061
1062 seq_printf(m, "%s\n", data->ts_info);
1063
1064 return 0;
1065}
1066
1067static int debugfs_dump_info_open(struct inode *inode, struct file *file)
1068{
1069 return single_open(file, ft5x06_debug_dump_info, inode->i_private);
1070}
1071
1072static const struct file_operations debug_dump_info_fops = {
1073 .owner = THIS_MODULE,
1074 .open = debugfs_dump_info_open,
1075 .read = seq_read,
1076 .release = single_release,
1077};
1078
Mohan Pallaka3a138202013-05-09 16:30:00 +05301079#ifdef CONFIG_OF
1080static int ft5x06_get_dt_coords(struct device *dev, char *name,
1081 struct ft5x06_ts_platform_data *pdata)
1082{
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301083 u32 coords[FT_COORDS_ARR_SIZE];
Mohan Pallaka3a138202013-05-09 16:30:00 +05301084 struct property *prop;
1085 struct device_node *np = dev->of_node;
1086 int coords_size, rc;
1087
1088 prop = of_find_property(np, name, NULL);
1089 if (!prop)
1090 return -EINVAL;
1091 if (!prop->value)
1092 return -ENODATA;
1093
1094 coords_size = prop->length / sizeof(u32);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301095 if (coords_size != FT_COORDS_ARR_SIZE) {
Mohan Pallaka3a138202013-05-09 16:30:00 +05301096 dev_err(dev, "invalid %s\n", name);
1097 return -EINVAL;
1098 }
1099
1100 rc = of_property_read_u32_array(np, name, coords, coords_size);
1101 if (rc && (rc != -EINVAL)) {
1102 dev_err(dev, "Unable to read %s\n", name);
1103 return rc;
1104 }
1105
1106 if (!strcmp(name, "focaltech,panel-coords")) {
1107 pdata->panel_minx = coords[0];
1108 pdata->panel_miny = coords[1];
1109 pdata->panel_maxx = coords[2];
1110 pdata->panel_maxy = coords[3];
1111 } else if (!strcmp(name, "focaltech,display-coords")) {
1112 pdata->x_min = coords[0];
1113 pdata->y_min = coords[1];
1114 pdata->x_max = coords[2];
1115 pdata->y_max = coords[3];
1116 } else {
1117 dev_err(dev, "unsupported property %s\n", name);
1118 return -EINVAL;
1119 }
1120
1121 return 0;
1122}
1123
1124static int ft5x06_parse_dt(struct device *dev,
1125 struct ft5x06_ts_platform_data *pdata)
1126{
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301127 int rc;
Mohan Pallaka3a138202013-05-09 16:30:00 +05301128 struct device_node *np = dev->of_node;
1129 struct property *prop;
1130 u32 temp_val, num_buttons;
1131 u32 button_map[MAX_BUTTONS];
1132
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301133 pdata->name = "focaltech";
1134 rc = of_property_read_string(np, "focaltech,name", &pdata->name);
1135 if (rc && (rc != -EINVAL)) {
1136 dev_err(dev, "Unable to read name\n");
1137 return rc;
1138 }
1139
Mohan Pallaka3a138202013-05-09 16:30:00 +05301140 rc = ft5x06_get_dt_coords(dev, "focaltech,panel-coords", pdata);
1141 if (rc && (rc != -EINVAL))
1142 return rc;
1143
1144 rc = ft5x06_get_dt_coords(dev, "focaltech,display-coords", pdata);
1145 if (rc)
1146 return rc;
1147
1148 pdata->i2c_pull_up = of_property_read_bool(np,
1149 "focaltech,i2c-pull-up");
1150
1151 pdata->no_force_update = of_property_read_bool(np,
1152 "focaltech,no-force-update");
1153 /* reset, irq gpio info */
1154 pdata->reset_gpio = of_get_named_gpio_flags(np, "focaltech,reset-gpio",
1155 0, &pdata->reset_gpio_flags);
1156 if (pdata->reset_gpio < 0)
1157 return pdata->reset_gpio;
1158
1159 pdata->irq_gpio = of_get_named_gpio_flags(np, "focaltech,irq-gpio",
1160 0, &pdata->irq_gpio_flags);
1161 if (pdata->irq_gpio < 0)
1162 return pdata->irq_gpio;
1163
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301164 pdata->fw_name = "ft_fw.bin";
1165 rc = of_property_read_string(np, "focaltech,fw-name", &pdata->fw_name);
1166 if (rc && (rc != -EINVAL)) {
1167 dev_err(dev, "Unable to read fw name\n");
1168 return rc;
1169 }
1170
1171 rc = of_property_read_u32(np, "focaltech,group-id", &temp_val);
1172 if (!rc)
1173 pdata->group_id = temp_val;
1174 else
1175 return rc;
1176
1177 rc = of_property_read_u32(np, "focaltech,hard-reset-delay-ms",
1178 &temp_val);
1179 if (!rc)
1180 pdata->hard_rst_dly = temp_val;
1181 else
1182 return rc;
1183
1184 rc = of_property_read_u32(np, "focaltech,soft-reset-delay-ms",
1185 &temp_val);
1186 if (!rc)
1187 pdata->soft_rst_dly = temp_val;
1188 else
1189 return rc;
1190
1191 rc = of_property_read_u32(np, "focaltech,num-max-touches", &temp_val);
1192 if (!rc)
1193 pdata->num_max_touches = temp_val;
1194 else
1195 return rc;
1196
1197 rc = of_property_read_u32(np, "focaltech,fw-delay-aa-ms", &temp_val);
1198 if (rc && (rc != -EINVAL)) {
1199 dev_err(dev, "Unable to read fw delay aa\n");
1200 return rc;
1201 } else if (rc != -EINVAL)
1202 pdata->info.delay_aa = temp_val;
1203
1204 rc = of_property_read_u32(np, "focaltech,fw-delay-55-ms", &temp_val);
1205 if (rc && (rc != -EINVAL)) {
1206 dev_err(dev, "Unable to read fw delay 55\n");
1207 return rc;
1208 } else if (rc != -EINVAL)
1209 pdata->info.delay_55 = temp_val;
1210
1211 rc = of_property_read_u32(np, "focaltech,fw-upgrade-id1", &temp_val);
1212 if (rc && (rc != -EINVAL)) {
1213 dev_err(dev, "Unable to read fw upgrade id1\n");
1214 return rc;
1215 } else if (rc != -EINVAL)
1216 pdata->info.upgrade_id_1 = temp_val;
1217
1218 rc = of_property_read_u32(np, "focaltech,fw-upgrade-id2", &temp_val);
1219 if (rc && (rc != -EINVAL)) {
1220 dev_err(dev, "Unable to read fw upgrade id2\n");
1221 return rc;
1222 } else if (rc != -EINVAL)
1223 pdata->info.upgrade_id_2 = temp_val;
1224
1225 rc = of_property_read_u32(np, "focaltech,fw-delay-readid-ms",
1226 &temp_val);
1227 if (rc && (rc != -EINVAL)) {
1228 dev_err(dev, "Unable to read fw delay read id\n");
1229 return rc;
1230 } else if (rc != -EINVAL)
1231 pdata->info.delay_readid = temp_val;
1232
1233 rc = of_property_read_u32(np, "focaltech,fw-delay-era-flsh-ms",
1234 &temp_val);
1235 if (rc && (rc != -EINVAL)) {
1236 dev_err(dev, "Unable to read fw delay erase flash\n");
1237 return rc;
1238 } else if (rc != -EINVAL)
1239 pdata->info.delay_erase_flash = temp_val;
1240
1241 pdata->info.auto_cal = of_property_read_bool(np,
1242 "focaltech,fw-auto-cal");
1243
Mohan Pallakaa348d752013-08-28 13:44:36 +05301244 pdata->fw_vkey_support = of_property_read_bool(np,
1245 "focaltech,fw-vkey-support");
1246
Bingzhe Caid85a69d2013-10-09 22:15:31 +08001247 pdata->ignore_id_check = of_property_read_bool(np,
1248 "focaltech,ignore-id-check");
1249
Mohan Pallaka3a138202013-05-09 16:30:00 +05301250 rc = of_property_read_u32(np, "focaltech,family-id", &temp_val);
1251 if (!rc)
1252 pdata->family_id = temp_val;
1253 else
1254 return rc;
1255
1256 prop = of_find_property(np, "focaltech,button-map", NULL);
1257 if (prop) {
1258 num_buttons = prop->length / sizeof(temp_val);
1259 if (num_buttons > MAX_BUTTONS)
1260 return -EINVAL;
1261
1262 rc = of_property_read_u32_array(np,
1263 "focaltech,button-map", button_map,
1264 num_buttons);
1265 if (rc) {
1266 dev_err(dev, "Unable to read key codes\n");
1267 return rc;
1268 }
1269 }
1270
1271 return 0;
1272}
1273#else
1274static int ft5x06_parse_dt(struct device *dev,
1275 struct ft5x06_ts_platform_data *pdata)
1276{
1277 return -ENODEV;
1278}
1279#endif
1280
Mohan Pallakaa2595072012-01-12 22:23:15 +05301281static int ft5x06_ts_probe(struct i2c_client *client,
1282 const struct i2c_device_id *id)
1283{
Mohan Pallaka3a138202013-05-09 16:30:00 +05301284 struct ft5x06_ts_platform_data *pdata;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301285 struct ft5x06_ts_data *data;
1286 struct input_dev *input_dev;
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301287 struct dentry *temp;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301288 u8 reg_value;
1289 u8 reg_addr;
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301290 int err, len;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301291
Mohan Pallaka3a138202013-05-09 16:30:00 +05301292 if (client->dev.of_node) {
1293 pdata = devm_kzalloc(&client->dev,
1294 sizeof(struct ft5x06_ts_platform_data), GFP_KERNEL);
1295 if (!pdata) {
1296 dev_err(&client->dev, "Failed to allocate memory\n");
1297 return -ENOMEM;
1298 }
1299
1300 err = ft5x06_parse_dt(&client->dev, pdata);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301301 if (err) {
1302 dev_err(&client->dev, "DT parsing failed\n");
Mohan Pallaka3a138202013-05-09 16:30:00 +05301303 return err;
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301304 }
Mohan Pallaka3a138202013-05-09 16:30:00 +05301305 } else
1306 pdata = client->dev.platform_data;
1307
Mohan Pallakaa2595072012-01-12 22:23:15 +05301308 if (!pdata) {
1309 dev_err(&client->dev, "Invalid pdata\n");
1310 return -EINVAL;
1311 }
1312
1313 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
1314 dev_err(&client->dev, "I2C not supported\n");
1315 return -ENODEV;
1316 }
1317
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301318 data = devm_kzalloc(&client->dev,
1319 sizeof(struct ft5x06_ts_data), GFP_KERNEL);
1320 if (!data) {
1321 dev_err(&client->dev, "Not enough memory\n");
1322 return -ENOMEM;
1323 }
1324
1325 if (pdata->fw_name) {
1326 len = strlen(pdata->fw_name);
1327 if (len > FT_FW_NAME_MAX_LEN - 1) {
1328 dev_err(&client->dev, "Invalid firmware name\n");
1329 return -EINVAL;
1330 }
1331
1332 strlcpy(data->fw_name, pdata->fw_name, len + 1);
1333 }
1334
1335 data->tch_data_len = FT_TCH_LEN(pdata->num_max_touches);
1336 data->tch_data = devm_kzalloc(&client->dev,
1337 data->tch_data_len, GFP_KERNEL);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301338 if (!data) {
1339 dev_err(&client->dev, "Not enough memory\n");
1340 return -ENOMEM;
1341 }
1342
1343 input_dev = input_allocate_device();
1344 if (!input_dev) {
Mohan Pallakaa2595072012-01-12 22:23:15 +05301345 dev_err(&client->dev, "failed to allocate input device\n");
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301346 return -ENOMEM;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301347 }
1348
1349 data->input_dev = input_dev;
1350 data->client = client;
1351 data->pdata = pdata;
1352
1353 input_dev->name = "ft5x06_ts";
1354 input_dev->id.bustype = BUS_I2C;
1355 input_dev->dev.parent = &client->dev;
1356
1357 input_set_drvdata(input_dev, data);
1358 i2c_set_clientdata(client, data);
1359
1360 __set_bit(EV_KEY, input_dev->evbit);
1361 __set_bit(EV_ABS, input_dev->evbit);
1362 __set_bit(BTN_TOUCH, input_dev->keybit);
Amy Malochedd2703d2012-06-20 11:03:56 -07001363 __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301364
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301365 input_mt_init_slots(input_dev, pdata->num_max_touches);
Mohan Pallaka3a138202013-05-09 16:30:00 +05301366 input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min,
Mohan Pallakaa2595072012-01-12 22:23:15 +05301367 pdata->x_max, 0, 0);
Mohan Pallaka3a138202013-05-09 16:30:00 +05301368 input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min,
Mohan Pallakaa2595072012-01-12 22:23:15 +05301369 pdata->y_max, 0, 0);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301370
1371 err = input_register_device(input_dev);
1372 if (err) {
1373 dev_err(&client->dev, "Input device registration failed\n");
1374 goto free_inputdev;
1375 }
1376
1377 if (pdata->power_init) {
1378 err = pdata->power_init(true);
1379 if (err) {
1380 dev_err(&client->dev, "power init failed");
1381 goto unreg_inputdev;
1382 }
1383 } else {
1384 err = ft5x06_power_init(data, true);
1385 if (err) {
1386 dev_err(&client->dev, "power init failed");
1387 goto unreg_inputdev;
1388 }
1389 }
1390
1391 if (pdata->power_on) {
1392 err = pdata->power_on(true);
1393 if (err) {
1394 dev_err(&client->dev, "power on failed");
1395 goto pwr_deinit;
1396 }
1397 } else {
1398 err = ft5x06_power_on(data, true);
1399 if (err) {
1400 dev_err(&client->dev, "power on failed");
1401 goto pwr_deinit;
1402 }
1403 }
1404
1405 if (gpio_is_valid(pdata->irq_gpio)) {
1406 err = gpio_request(pdata->irq_gpio, "ft5x06_irq_gpio");
1407 if (err) {
1408 dev_err(&client->dev, "irq gpio request failed");
1409 goto pwr_off;
1410 }
1411 err = gpio_direction_input(pdata->irq_gpio);
1412 if (err) {
1413 dev_err(&client->dev,
1414 "set_direction for irq gpio failed\n");
1415 goto free_irq_gpio;
1416 }
1417 }
1418
1419 if (gpio_is_valid(pdata->reset_gpio)) {
1420 err = gpio_request(pdata->reset_gpio, "ft5x06_reset_gpio");
1421 if (err) {
1422 dev_err(&client->dev, "reset gpio request failed");
1423 goto free_irq_gpio;
1424 }
1425
1426 err = gpio_direction_output(pdata->reset_gpio, 0);
1427 if (err) {
1428 dev_err(&client->dev,
1429 "set_direction for reset gpio failed\n");
1430 goto free_reset_gpio;
1431 }
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301432 msleep(data->pdata->hard_rst_dly);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301433 gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
1434 }
1435
1436 /* make sure CTP already finish startup process */
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301437 msleep(data->pdata->soft_rst_dly);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301438
Mohan Pallaka3a138202013-05-09 16:30:00 +05301439 /* check the controller id */
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301440 reg_addr = FT_REG_ID;
Mohan Pallaka3a138202013-05-09 16:30:00 +05301441 err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
1442 if (err < 0) {
1443 dev_err(&client->dev, "version read failed");
Shantanu Jain3da65202013-07-08 19:11:07 +05301444 goto free_reset_gpio;
Mohan Pallaka3a138202013-05-09 16:30:00 +05301445 }
1446
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301447 dev_info(&client->dev, "Device ID = 0x%x\n", reg_value);
1448
Bingzhe Caid85a69d2013-10-09 22:15:31 +08001449 if ((pdata->family_id != reg_value) && (!pdata->ignore_id_check)) {
Mohan Pallaka3a138202013-05-09 16:30:00 +05301450 dev_err(&client->dev, "%s:Unsupported controller\n", __func__);
1451 goto free_reset_gpio;
1452 }
1453
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301454 data->family_id = reg_value;
1455
Mohan Pallakaa2595072012-01-12 22:23:15 +05301456 err = request_threaded_irq(client->irq, NULL,
1457 ft5x06_ts_interrupt, pdata->irqflags,
1458 client->dev.driver->name, data);
1459 if (err) {
1460 dev_err(&client->dev, "request irq failed\n");
1461 goto free_reset_gpio;
1462 }
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301463
1464 err = device_create_file(&client->dev, &dev_attr_fw_name);
1465 if (err) {
1466 dev_err(&client->dev, "sys file creation failed\n");
1467 goto irq_free;
1468 }
1469
1470 err = device_create_file(&client->dev, &dev_attr_update_fw);
1471 if (err) {
1472 dev_err(&client->dev, "sys file creation failed\n");
1473 goto free_fw_name_sys;
1474 }
1475
1476 err = device_create_file(&client->dev, &dev_attr_force_update_fw);
1477 if (err) {
1478 dev_err(&client->dev, "sys file creation failed\n");
1479 goto free_update_fw_sys;
1480 }
1481
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301482 data->dir = debugfs_create_dir(FT_DEBUG_DIR_NAME, NULL);
1483 if (data->dir == NULL || IS_ERR(data->dir)) {
1484 pr_err("debugfs_create_dir failed(%ld)\n", PTR_ERR(data->dir));
1485 err = PTR_ERR(data->dir);
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301486 goto free_force_update_fw_sys;
1487 }
1488
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301489 temp = debugfs_create_file("addr", S_IRUSR | S_IWUSR, data->dir, data,
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301490 &debug_addr_fops);
1491 if (temp == NULL || IS_ERR(temp)) {
1492 pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
1493 err = PTR_ERR(temp);
1494 goto free_debug_dir;
1495 }
1496
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301497 temp = debugfs_create_file("data", S_IRUSR | S_IWUSR, data->dir, data,
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301498 &debug_data_fops);
1499 if (temp == NULL || IS_ERR(temp)) {
1500 pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
1501 err = PTR_ERR(temp);
1502 goto free_debug_dir;
1503 }
1504
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301505 temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, data->dir,
1506 data, &debug_suspend_fops);
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301507 if (temp == NULL || IS_ERR(temp)) {
1508 pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
1509 err = PTR_ERR(temp);
1510 goto free_debug_dir;
1511 }
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301512
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301513 temp = debugfs_create_file("dump_info", S_IRUSR | S_IWUSR, data->dir,
1514 data, &debug_dump_info_fops);
1515 if (temp == NULL || IS_ERR(temp)) {
1516 pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
1517 err = PTR_ERR(temp);
1518 goto free_debug_dir;
1519 }
1520
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301521 data->ts_info = devm_kzalloc(&client->dev,
1522 FT_INFO_MAX_LEN, GFP_KERNEL);
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301523 if (!data->ts_info) {
1524 dev_err(&client->dev, "Not enough memory\n");
1525 goto free_debug_dir;
1526 }
1527
1528 /*get some register information */
1529 reg_addr = FT_REG_POINT_RATE;
1530 ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
1531 if (err < 0)
1532 dev_err(&client->dev, "report rate read failed");
1533
1534 dev_info(&client->dev, "report rate = %dHz\n", reg_value * 10);
1535
1536 reg_addr = FT_REG_THGROUP;
1537 err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
1538 if (err < 0)
1539 dev_err(&client->dev, "threshold read failed");
1540
1541 dev_dbg(&client->dev, "touch threshold = %d\n", reg_value * 4);
1542
Mohan Pallakaa348d752013-08-28 13:44:36 +05301543 ft5x06_update_fw_ver(data);
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301544
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301545 FT_STORE_TS_INFO(data->ts_info, data->family_id, data->pdata->name,
1546 data->pdata->num_max_touches, data->pdata->group_id,
Mohan Pallakaa348d752013-08-28 13:44:36 +05301547 data->pdata->fw_vkey_support ? "yes" : "no",
1548 data->pdata->fw_name, data->fw_ver[0],
1549 data->fw_ver[1], data->fw_ver[2]);
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301550
Mohan Pallakaa5d601b2013-05-10 15:34:44 +05301551#if defined(CONFIG_FB)
1552 data->fb_notif.notifier_call = fb_notifier_callback;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301553
Mohan Pallakaa5d601b2013-05-10 15:34:44 +05301554 err = fb_register_client(&data->fb_notif);
1555
1556 if (err)
1557 dev_err(&client->dev, "Unable to register fb_notifier: %d\n",
1558 err);
1559#elif defined(CONFIG_HAS_EARLYSUSPEND)
Mohan Pallakaa2595072012-01-12 22:23:15 +05301560 data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301561 FT_SUSPEND_LEVEL;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301562 data->early_suspend.suspend = ft5x06_ts_early_suspend;
1563 data->early_suspend.resume = ft5x06_ts_late_resume;
1564 register_early_suspend(&data->early_suspend);
1565#endif
1566
1567 return 0;
1568
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301569free_debug_dir:
1570 debugfs_remove_recursive(data->dir);
1571free_force_update_fw_sys:
1572 device_remove_file(&client->dev, &dev_attr_force_update_fw);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301573free_update_fw_sys:
1574 device_remove_file(&client->dev, &dev_attr_update_fw);
1575free_fw_name_sys:
1576 device_remove_file(&client->dev, &dev_attr_fw_name);
1577irq_free:
1578 free_irq(client->irq, data);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301579free_reset_gpio:
1580 if (gpio_is_valid(pdata->reset_gpio))
1581 gpio_free(pdata->reset_gpio);
1582free_irq_gpio:
1583 if (gpio_is_valid(pdata->irq_gpio))
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301584 gpio_free(pdata->irq_gpio);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301585pwr_off:
1586 if (pdata->power_on)
1587 pdata->power_on(false);
1588 else
1589 ft5x06_power_on(data, false);
1590pwr_deinit:
1591 if (pdata->power_init)
1592 pdata->power_init(false);
1593 else
1594 ft5x06_power_init(data, false);
1595unreg_inputdev:
1596 input_unregister_device(input_dev);
1597 input_dev = NULL;
1598free_inputdev:
1599 input_free_device(input_dev);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301600 return err;
1601}
1602
1603static int __devexit ft5x06_ts_remove(struct i2c_client *client)
1604{
1605 struct ft5x06_ts_data *data = i2c_get_clientdata(client);
1606
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301607 debugfs_remove_recursive(data->dir);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301608 device_remove_file(&client->dev, &dev_attr_force_update_fw);
1609 device_remove_file(&client->dev, &dev_attr_update_fw);
1610 device_remove_file(&client->dev, &dev_attr_fw_name);
1611
Mohan Pallakaa5d601b2013-05-10 15:34:44 +05301612#if defined(CONFIG_FB)
1613 if (fb_unregister_client(&data->fb_notif))
1614 dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
1615#elif defined(CONFIG_HAS_EARLYSUSPEND)
Mohan Pallakaa2595072012-01-12 22:23:15 +05301616 unregister_early_suspend(&data->early_suspend);
1617#endif
1618 free_irq(client->irq, data);
1619
1620 if (gpio_is_valid(data->pdata->reset_gpio))
1621 gpio_free(data->pdata->reset_gpio);
1622
1623 if (gpio_is_valid(data->pdata->irq_gpio))
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301624 gpio_free(data->pdata->irq_gpio);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301625
1626 if (data->pdata->power_on)
1627 data->pdata->power_on(false);
1628 else
1629 ft5x06_power_on(data, false);
1630
1631 if (data->pdata->power_init)
1632 data->pdata->power_init(false);
1633 else
1634 ft5x06_power_init(data, false);
1635
1636 input_unregister_device(data->input_dev);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301637
1638 return 0;
1639}
1640
1641static const struct i2c_device_id ft5x06_ts_id[] = {
1642 {"ft5x06_ts", 0},
1643 {},
1644};
1645
1646MODULE_DEVICE_TABLE(i2c, ft5x06_ts_id);
1647
Mohan Pallaka3a138202013-05-09 16:30:00 +05301648#ifdef CONFIG_OF
1649static struct of_device_id ft5x06_match_table[] = {
1650 { .compatible = "focaltech,5x06",},
1651 { },
1652};
1653#else
1654#define ft5x06_match_table NULL
1655#endif
1656
Mohan Pallakaa2595072012-01-12 22:23:15 +05301657static struct i2c_driver ft5x06_ts_driver = {
1658 .probe = ft5x06_ts_probe,
1659 .remove = __devexit_p(ft5x06_ts_remove),
1660 .driver = {
1661 .name = "ft5x06_ts",
1662 .owner = THIS_MODULE,
Mohan Pallaka3a138202013-05-09 16:30:00 +05301663 .of_match_table = ft5x06_match_table,
Mohan Pallakaa2595072012-01-12 22:23:15 +05301664#ifdef CONFIG_PM
1665 .pm = &ft5x06_ts_pm_ops,
1666#endif
1667 },
1668 .id_table = ft5x06_ts_id,
1669};
1670
1671static int __init ft5x06_ts_init(void)
1672{
1673 return i2c_add_driver(&ft5x06_ts_driver);
1674}
1675module_init(ft5x06_ts_init);
1676
1677static void __exit ft5x06_ts_exit(void)
1678{
1679 i2c_del_driver(&ft5x06_ts_driver);
1680}
1681module_exit(ft5x06_ts_exit);
1682
1683MODULE_DESCRIPTION("FocalTech ft5x06 TouchScreen driver");
1684MODULE_LICENSE("GPL v2");