blob: aa50d448915441b42a82da669ff474abb9bf2c9f [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;
291 u32 id, x, y, pressure, status, num_touches;
292 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) {
332 pressure = FT_PRESS;
333 input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 1);
334 input_report_abs(ip_dev, ABS_MT_POSITION_X, x);
335 input_report_abs(ip_dev, ABS_MT_POSITION_Y, y);
336 input_report_abs(ip_dev, ABS_MT_PRESSURE, pressure);
Mohan Pallakaa348d752013-08-28 13:44:36 +0530337 } else {
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530338 input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 0);
Mohan Pallakaa348d752013-08-28 13:44:36 +0530339 }
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530340 }
341
342 if (update_input) {
343 input_mt_report_pointer_emulation(ip_dev, false);
344 input_sync(ip_dev);
345 }
Mohan Pallakaa2595072012-01-12 22:23:15 +0530346
347 return IRQ_HANDLED;
348}
349
350static int ft5x06_power_on(struct ft5x06_ts_data *data, bool on)
351{
352 int rc;
353
354 if (!on)
355 goto power_off;
356
357 rc = regulator_enable(data->vdd);
358 if (rc) {
359 dev_err(&data->client->dev,
360 "Regulator vdd enable failed rc=%d\n", rc);
361 return rc;
362 }
363
364 rc = regulator_enable(data->vcc_i2c);
365 if (rc) {
366 dev_err(&data->client->dev,
367 "Regulator vcc_i2c enable failed rc=%d\n", rc);
368 regulator_disable(data->vdd);
369 }
370
371 return rc;
372
373power_off:
374 rc = regulator_disable(data->vdd);
375 if (rc) {
376 dev_err(&data->client->dev,
377 "Regulator vdd disable failed rc=%d\n", rc);
378 return rc;
379 }
380
381 rc = regulator_disable(data->vcc_i2c);
382 if (rc) {
383 dev_err(&data->client->dev,
384 "Regulator vcc_i2c disable failed rc=%d\n", rc);
385 regulator_enable(data->vdd);
386 }
387
388 return rc;
389}
390
391static int ft5x06_power_init(struct ft5x06_ts_data *data, bool on)
392{
393 int rc;
394
395 if (!on)
396 goto pwr_deinit;
397
398 data->vdd = regulator_get(&data->client->dev, "vdd");
399 if (IS_ERR(data->vdd)) {
400 rc = PTR_ERR(data->vdd);
401 dev_err(&data->client->dev,
402 "Regulator get failed vdd rc=%d\n", rc);
403 return rc;
404 }
405
406 if (regulator_count_voltages(data->vdd) > 0) {
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530407 rc = regulator_set_voltage(data->vdd, FT_VTG_MIN_UV,
408 FT_VTG_MAX_UV);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530409 if (rc) {
410 dev_err(&data->client->dev,
411 "Regulator set_vtg failed vdd rc=%d\n", rc);
412 goto reg_vdd_put;
413 }
414 }
415
416 data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c");
417 if (IS_ERR(data->vcc_i2c)) {
418 rc = PTR_ERR(data->vcc_i2c);
419 dev_err(&data->client->dev,
420 "Regulator get failed vcc_i2c rc=%d\n", rc);
421 goto reg_vdd_set_vtg;
422 }
423
424 if (regulator_count_voltages(data->vcc_i2c) > 0) {
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530425 rc = regulator_set_voltage(data->vcc_i2c, FT_I2C_VTG_MIN_UV,
426 FT_I2C_VTG_MAX_UV);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530427 if (rc) {
428 dev_err(&data->client->dev,
429 "Regulator set_vtg failed vcc_i2c rc=%d\n", rc);
430 goto reg_vcc_i2c_put;
431 }
432 }
433
434 return 0;
435
436reg_vcc_i2c_put:
437 regulator_put(data->vcc_i2c);
438reg_vdd_set_vtg:
439 if (regulator_count_voltages(data->vdd) > 0)
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530440 regulator_set_voltage(data->vdd, 0, FT_VTG_MAX_UV);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530441reg_vdd_put:
442 regulator_put(data->vdd);
443 return rc;
444
445pwr_deinit:
446 if (regulator_count_voltages(data->vdd) > 0)
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530447 regulator_set_voltage(data->vdd, 0, FT_VTG_MAX_UV);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530448
449 regulator_put(data->vdd);
450
451 if (regulator_count_voltages(data->vcc_i2c) > 0)
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530452 regulator_set_voltage(data->vcc_i2c, 0, FT_I2C_VTG_MAX_UV);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530453
454 regulator_put(data->vcc_i2c);
455 return 0;
456}
457
458#ifdef CONFIG_PM
459static int ft5x06_ts_suspend(struct device *dev)
460{
461 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
Figo Wang63ad82b2013-06-28 19:49:49 +0800462 char txbuf[2], i;
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530463 int err;
Mohan Pallakaa2595072012-01-12 22:23:15 +0530464
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530465 if (data->loading_fw) {
466 dev_info(dev, "Firmware loading in process...\n");
467 return 0;
468 }
469
470 if (data->suspended) {
471 dev_info(dev, "Already in suspend state\n");
472 return 0;
473 }
474
Mohan Pallakaa2595072012-01-12 22:23:15 +0530475 disable_irq(data->client->irq);
476
Figo Wang63ad82b2013-06-28 19:49:49 +0800477 /* release all touches */
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530478 for (i = 0; i < data->pdata->num_max_touches; i++) {
Figo Wang63ad82b2013-06-28 19:49:49 +0800479 input_mt_slot(data->input_dev, i);
480 input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, 0);
481 }
482 input_report_key(data->input_dev, BTN_TOUCH, 0);
483 input_sync(data->input_dev);
484
Mohan Pallakaa2595072012-01-12 22:23:15 +0530485 if (gpio_is_valid(data->pdata->reset_gpio)) {
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530486 txbuf[0] = FT_REG_PMODE;
487 txbuf[1] = FT_PMODE_HIBERNATE;
Mohan Pallakaa2595072012-01-12 22:23:15 +0530488 ft5x06_i2c_write(data->client, txbuf, sizeof(txbuf));
489 }
490
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530491 if (data->pdata->power_on) {
492 err = data->pdata->power_on(false);
493 if (err) {
494 dev_err(dev, "power off failed");
495 goto pwr_off_fail;
496 }
497 } else {
498 err = ft5x06_power_on(data, false);
499 if (err) {
500 dev_err(dev, "power off failed");
501 goto pwr_off_fail;
502 }
503 }
504
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530505 data->suspended = true;
506
Mohan Pallakaa2595072012-01-12 22:23:15 +0530507 return 0;
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530508
509pwr_off_fail:
510 if (gpio_is_valid(data->pdata->reset_gpio)) {
511 gpio_set_value_cansleep(data->pdata->reset_gpio, 0);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530512 msleep(data->pdata->hard_rst_dly);
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530513 gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
514 }
515 enable_irq(data->client->irq);
516 return err;
Mohan Pallakaa2595072012-01-12 22:23:15 +0530517}
518
519static int ft5x06_ts_resume(struct device *dev)
520{
521 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530522 int err;
Mohan Pallakaa2595072012-01-12 22:23:15 +0530523
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530524 if (!data->suspended) {
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530525 dev_dbg(dev, "Already in awake state\n");
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530526 return 0;
527 }
528
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530529 if (data->pdata->power_on) {
530 err = data->pdata->power_on(true);
531 if (err) {
532 dev_err(dev, "power on failed");
533 return err;
534 }
535 } else {
536 err = ft5x06_power_on(data, true);
537 if (err) {
538 dev_err(dev, "power on failed");
539 return err;
540 }
541 }
542
Mohan Pallakaa2595072012-01-12 22:23:15 +0530543 if (gpio_is_valid(data->pdata->reset_gpio)) {
544 gpio_set_value_cansleep(data->pdata->reset_gpio, 0);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530545 msleep(data->pdata->hard_rst_dly);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530546 gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
547 }
Mohan Pallakaec271e42013-07-23 15:35:28 +0530548
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530549 msleep(data->pdata->soft_rst_dly);
Mohan Pallakaec271e42013-07-23 15:35:28 +0530550
Mohan Pallakaa2595072012-01-12 22:23:15 +0530551 enable_irq(data->client->irq);
552
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530553 data->suspended = false;
554
Mohan Pallakaa2595072012-01-12 22:23:15 +0530555 return 0;
556}
557
Mohan Pallakaa5d601b2013-05-10 15:34:44 +0530558#if defined(CONFIG_FB)
559static int fb_notifier_callback(struct notifier_block *self,
560 unsigned long event, void *data)
561{
562 struct fb_event *evdata = data;
563 int *blank;
564 struct ft5x06_ts_data *ft5x06_data =
565 container_of(self, struct ft5x06_ts_data, fb_notif);
566
567 if (evdata && evdata->data && event == FB_EVENT_BLANK &&
568 ft5x06_data && ft5x06_data->client) {
569 blank = evdata->data;
570 if (*blank == FB_BLANK_UNBLANK)
571 ft5x06_ts_resume(&ft5x06_data->client->dev);
572 else if (*blank == FB_BLANK_POWERDOWN)
573 ft5x06_ts_suspend(&ft5x06_data->client->dev);
574 }
575
576 return 0;
577}
578#elif defined(CONFIG_HAS_EARLYSUSPEND)
Mohan Pallakaa2595072012-01-12 22:23:15 +0530579static void ft5x06_ts_early_suspend(struct early_suspend *handler)
580{
581 struct ft5x06_ts_data *data = container_of(handler,
582 struct ft5x06_ts_data,
583 early_suspend);
584
585 ft5x06_ts_suspend(&data->client->dev);
586}
587
588static void ft5x06_ts_late_resume(struct early_suspend *handler)
589{
590 struct ft5x06_ts_data *data = container_of(handler,
591 struct ft5x06_ts_data,
592 early_suspend);
593
594 ft5x06_ts_resume(&data->client->dev);
595}
596#endif
597
598static const struct dev_pm_ops ft5x06_ts_pm_ops = {
Mohan Pallakaa5d601b2013-05-10 15:34:44 +0530599#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND))
Mohan Pallakaa2595072012-01-12 22:23:15 +0530600 .suspend = ft5x06_ts_suspend,
601 .resume = ft5x06_ts_resume,
602#endif
603};
604#endif
605
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530606static int ft5x06_auto_cal(struct i2c_client *client)
607{
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530608 struct ft5x06_ts_data *data = i2c_get_clientdata(client);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530609 u8 temp = 0, i;
610
611 /* set to factory mode */
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530612 msleep(2 * data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530613 ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530614 msleep(data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530615
616 /* start calibration */
617 ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_START);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530618 msleep(2 * data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530619 for (i = 0; i < FT_CAL_RETRY; i++) {
620 ft5x0x_read_reg(client, FT_REG_CAL, &temp);
621 /*return to normal mode, calibration finish */
622 if (((temp & FT_CAL_MASK) >> FT_4BIT_SHIFT) == FT_CAL_FIN)
623 break;
624 }
625
626 /*calibration OK */
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530627 msleep(2 * data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530628 ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530629 msleep(data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530630
631 /* store calibration data */
632 ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_STORE);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530633 msleep(2 * data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530634
635 /* set to normal mode */
636 ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_WORKMODE_VALUE);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530637 msleep(2 * data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530638
639 return 0;
640}
641
642static int ft5x06_fw_upgrade_start(struct i2c_client *client,
643 const u8 *data, u32 data_len)
644{
645 struct ft5x06_ts_data *ts_data = i2c_get_clientdata(client);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530646 struct fw_upgrade_info info = ts_data->pdata->info;
Mohan Pallakaec271e42013-07-23 15:35:28 +0530647 u8 reset_reg;
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530648 u8 w_buf[FT_MAX_WR_BUF] = {0}, r_buf[FT_MAX_RD_BUF] = {0};
649 u8 pkt_buf[FT_FW_PKT_LEN + FT_FW_PKT_META_LEN];
650 int rc, i, j, temp;
651 u32 pkt_num, pkt_len;
652 u8 fw_ecc;
653
Mohan Pallakaec271e42013-07-23 15:35:28 +0530654 for (i = 0, j = 0; i < FT_UPGRADE_LOOP; i++) {
655 /* reset - write 0xaa and 0x55 to reset register */
656 if (ts_data->family_id == FT6X06_ID)
657 reset_reg = FT_RST_CMD_REG2;
658 else
659 reset_reg = FT_RST_CMD_REG1;
660
661 ft5x0x_write_reg(client, reset_reg, FT_UPGRADE_AA);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530662 msleep(info.delay_aa);
663
Mohan Pallakaec271e42013-07-23 15:35:28 +0530664 ft5x0x_write_reg(client, reset_reg, FT_UPGRADE_55);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530665 msleep(info.delay_55);
666
667 /* Enter upgrade mode */
668 w_buf[0] = FT_UPGRADE_55;
669 w_buf[1] = FT_UPGRADE_AA;
670 do {
Mohan Pallakaec271e42013-07-23 15:35:28 +0530671 j++;
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530672 rc = ft5x06_i2c_write(client, w_buf, 2);
673 msleep(FT_RETRY_DLY);
Mohan Pallakaec271e42013-07-23 15:35:28 +0530674 } while (rc <= 0 && j < FT_MAX_TRIES);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530675
676 /* check READ_ID */
677 msleep(info.delay_readid);
678 w_buf[0] = FT_READ_ID_REG;
679 w_buf[1] = 0x00;
680 w_buf[2] = 0x00;
681 w_buf[3] = 0x00;
682
683 ft5x06_i2c_read(client, w_buf, 4, r_buf, 2);
684
685 if (r_buf[0] != info.upgrade_id_1
686 || r_buf[1] != info.upgrade_id_2) {
687 dev_err(&client->dev, "Upgrade ID mismatch(%d)\n", i);
688 } else
689 break;
690 }
691
692 if (i >= FT_UPGRADE_LOOP) {
693 dev_err(&client->dev, "Abort upgrade\n");
694 return -EIO;
695 }
696
697 /* erase app and panel paramenter area */
698 w_buf[0] = FT_ERASE_APP_REG;
699 ft5x06_i2c_write(client, w_buf, 1);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530700 msleep(info.delay_erase_flash);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530701
702 w_buf[0] = FT_ERASE_PANEL_REG;
703 ft5x06_i2c_write(client, w_buf, 1);
704 msleep(FT_EARSE_DLY_MS);
705
706 /* program firmware */
707 data_len = data_len - 8;
708 pkt_num = (data_len) / FT_FW_PKT_LEN;
709 pkt_len = FT_FW_PKT_LEN;
710 pkt_buf[0] = FT_FW_START_REG;
711 pkt_buf[1] = 0x00;
712 fw_ecc = 0;
713
714 for (i = 0; i < pkt_num; i++) {
715 temp = i * FT_FW_PKT_LEN;
716 pkt_buf[2] = (u8) (temp >> FT_8BIT_SHIFT);
717 pkt_buf[3] = (u8) temp;
718 pkt_buf[4] = (u8) (pkt_len >> FT_8BIT_SHIFT);
719 pkt_buf[5] = (u8) pkt_len;
720
721 for (j = 0; j < FT_FW_PKT_LEN; j++) {
722 pkt_buf[6 + j] = data[i * FT_FW_PKT_LEN + j];
723 fw_ecc ^= pkt_buf[6 + j];
724 }
725
726 ft5x06_i2c_write(client, pkt_buf,
727 FT_FW_PKT_LEN + FT_FW_PKT_META_LEN);
728 msleep(FT_FW_PKT_DLY_MS);
729 }
730
731 /* send remaining bytes */
732 if ((data_len) % FT_FW_PKT_LEN > 0) {
733 temp = pkt_num * FT_FW_PKT_LEN;
734 pkt_buf[2] = (u8) (temp >> FT_8BIT_SHIFT);
735 pkt_buf[3] = (u8) temp;
736 temp = (data_len) % FT_FW_PKT_LEN;
737 pkt_buf[4] = (u8) (temp >> FT_8BIT_SHIFT);
738 pkt_buf[5] = (u8) temp;
739
740 for (i = 0; i < temp; i++) {
741 pkt_buf[6 + i] = data[pkt_num * FT_FW_PKT_LEN + i];
742 fw_ecc ^= pkt_buf[6 + i];
743 }
744
745 ft5x06_i2c_write(client, pkt_buf, temp + FT_FW_PKT_META_LEN);
746 msleep(FT_FW_PKT_DLY_MS);
747 }
748
749 /* send the finishing packet */
750 for (i = 0; i < 6; i++) {
751 temp = FT_FW_LAST_PKT + i;
752 pkt_buf[2] = (u8) (temp >> 8);
753 pkt_buf[3] = (u8) temp;
754 temp = 1;
755 pkt_buf[4] = (u8) (temp >> 8);
756 pkt_buf[5] = (u8) temp;
757 pkt_buf[6] = data[data_len + i];
758 fw_ecc ^= pkt_buf[6];
759 ft5x06_i2c_write(client, pkt_buf, temp + FT_FW_PKT_META_LEN);
760 msleep(FT_FW_PKT_DLY_MS);
761 }
762
763 /* verify checksum */
764 w_buf[0] = FT_REG_ECC;
765 ft5x06_i2c_read(client, w_buf, 1, r_buf, 1);
766 if (r_buf[0] != fw_ecc) {
767 dev_err(&client->dev, "ECC error! dev_ecc=%02x fw_ecc=%02x\n",
768 r_buf[0], fw_ecc);
769 return -EIO;
770 }
771
772 /* reset */
773 w_buf[0] = FT_REG_RESET_FW;
774 ft5x06_i2c_write(client, w_buf, 1);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530775 msleep(ts_data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530776
Mohan Pallakaec271e42013-07-23 15:35:28 +0530777 dev_info(&client->dev, "Firmware upgrade successful\n");
778
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530779 return 0;
780}
781
782static int ft5x06_fw_upgrade(struct device *dev, bool force)
783{
784 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
785 const struct firmware *fw = NULL;
786 int rc;
Mohan Pallakaa348d752013-08-28 13:44:36 +0530787 u8 fw_file_maj, fw_file_min, fw_file_sub_min;
788 bool fw_upgrade = false;
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530789
790 rc = request_firmware(&fw, data->fw_name, dev);
791 if (rc < 0) {
792 dev_err(dev, "Request firmware failed - %s (%d)\n",
793 data->fw_name, rc);
794 return rc;
795 }
796
797 if (fw->size < FT_FW_MIN_SIZE || fw->size > FT_FW_MAX_SIZE) {
798 dev_err(dev, "Invalid firmware size (%d)\n", fw->size);
799 rc = -EIO;
800 goto rel_fw;
801 }
802
Mohan Pallakaa348d752013-08-28 13:44:36 +0530803 fw_file_maj = FT_FW_FILE_MAJ_VER(fw);
804 fw_file_min = FT_FW_FILE_MIN_VER(fw);
805 fw_file_sub_min = FT_FW_FILE_SUB_MIN_VER(fw);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530806
Mohan Pallakaa348d752013-08-28 13:44:36 +0530807 dev_info(dev, "Current firmware: %d.%d.%d", data->fw_ver[0],
808 data->fw_ver[1], data->fw_ver[2]);
809 dev_info(dev, "New firmware: %d.%d.%d", fw_file_maj,
810 fw_file_min, fw_file_sub_min);
811
812 if (force) {
813 fw_upgrade = true;
814 } else if (data->fw_ver[0] == fw_file_maj) {
815 if (data->fw_ver[1] < fw_file_min)
816 fw_upgrade = true;
817 else if (data->fw_ver[2] < fw_file_sub_min)
818 fw_upgrade = true;
819 else
820 dev_info(dev, "No need to upgrade\n");
821 } else
822 dev_info(dev, "Firmware versions do not match\n");
823
824 if (!fw_upgrade) {
825 dev_info(dev, "Exiting fw upgrade...\n");
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530826 rc = -EFAULT;
827 goto rel_fw;
828 }
829
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530830 /* start firmware upgrade */
831 if (FT_FW_CHECK(fw)) {
832 rc = ft5x06_fw_upgrade_start(data->client, fw->data, fw->size);
833 if (rc < 0)
Mohan Pallakaa348d752013-08-28 13:44:36 +0530834 dev_err(dev, "update failed (%d). try later...\n", rc);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530835 else if (data->pdata->info.auto_cal)
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530836 ft5x06_auto_cal(data->client);
837 } else {
838 dev_err(dev, "FW format error\n");
839 rc = -EIO;
840 }
841
Mohan Pallakaa348d752013-08-28 13:44:36 +0530842 ft5x06_update_fw_ver(data);
843
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530844 FT_STORE_TS_INFO(data->ts_info, data->family_id, data->pdata->name,
845 data->pdata->num_max_touches, data->pdata->group_id,
Mohan Pallakaa348d752013-08-28 13:44:36 +0530846 data->pdata->fw_vkey_support ? "yes" : "no",
847 data->pdata->fw_name, data->fw_ver[0],
848 data->fw_ver[1], data->fw_ver[2]);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530849rel_fw:
850 release_firmware(fw);
851 return rc;
852}
853
854static ssize_t ft5x06_update_fw_show(struct device *dev,
855 struct device_attribute *attr, char *buf)
856{
857 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
858 return snprintf(buf, 2, "%d\n", data->loading_fw);
859}
860
861static ssize_t ft5x06_update_fw_store(struct device *dev,
862 struct device_attribute *attr,
863 const char *buf, size_t size)
864{
865 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
866 unsigned long val;
867 int rc;
868
869 if (size > 2)
870 return -EINVAL;
871
872 rc = kstrtoul(buf, 10, &val);
873 if (rc != 0)
874 return rc;
875
Mohan Pallakaa348d752013-08-28 13:44:36 +0530876 if (data->suspended) {
877 dev_info(dev, "In suspend state, try again later...\n");
878 return size;
879 }
880
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530881 mutex_lock(&data->input_dev->mutex);
882 if (!data->loading_fw && val) {
883 data->loading_fw = true;
884 ft5x06_fw_upgrade(dev, false);
885 data->loading_fw = false;
886 }
887 mutex_unlock(&data->input_dev->mutex);
888
889 return size;
890}
891
892static DEVICE_ATTR(update_fw, 0664, ft5x06_update_fw_show,
893 ft5x06_update_fw_store);
894
895static ssize_t ft5x06_force_update_fw_store(struct device *dev,
896 struct device_attribute *attr,
897 const char *buf, size_t size)
898{
899 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
900 unsigned long val;
901 int rc;
902
903 if (size > 2)
904 return -EINVAL;
905
906 rc = kstrtoul(buf, 10, &val);
907 if (rc != 0)
908 return rc;
909
910 mutex_lock(&data->input_dev->mutex);
911 if (!data->loading_fw && val) {
912 data->loading_fw = true;
913 ft5x06_fw_upgrade(dev, true);
914 data->loading_fw = false;
915 }
916 mutex_unlock(&data->input_dev->mutex);
917
918 return size;
919}
920
921static DEVICE_ATTR(force_update_fw, 0664, ft5x06_update_fw_show,
922 ft5x06_force_update_fw_store);
923
924static ssize_t ft5x06_fw_name_show(struct device *dev,
925 struct device_attribute *attr, char *buf)
926{
927 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
928 return snprintf(buf, FT_FW_NAME_MAX_LEN - 1, "%s\n", data->fw_name);
929}
930
931static ssize_t ft5x06_fw_name_store(struct device *dev,
932 struct device_attribute *attr,
933 const char *buf, size_t size)
934{
935 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
936
937 if (size > FT_FW_NAME_MAX_LEN - 1)
938 return -EINVAL;
939
940 strlcpy(data->fw_name, buf, size);
941 if (data->fw_name[size-1] == '\n')
942 data->fw_name[size-1] = 0;
943
944 return size;
945}
946
947static DEVICE_ATTR(fw_name, 0664, ft5x06_fw_name_show, ft5x06_fw_name_store);
948
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530949static bool ft5x06_debug_addr_is_valid(int addr)
950{
951 if (addr < 0 || addr > 0xFF) {
952 pr_err("FT reg address is invalid: 0x%x\n", addr);
953 return false;
954 }
955
956 return true;
957}
958
959static int ft5x06_debug_data_set(void *_data, u64 val)
960{
961 struct ft5x06_ts_data *data = _data;
962
963 mutex_lock(&data->input_dev->mutex);
964
965 if (ft5x06_debug_addr_is_valid(data->addr))
966 dev_info(&data->client->dev,
967 "Writing into FT registers not supported\n");
968
969 mutex_unlock(&data->input_dev->mutex);
970
971 return 0;
972}
973
974static int ft5x06_debug_data_get(void *_data, u64 *val)
975{
976 struct ft5x06_ts_data *data = _data;
977 int rc;
978 u8 reg;
979
980 mutex_lock(&data->input_dev->mutex);
981
982 if (ft5x06_debug_addr_is_valid(data->addr)) {
983 rc = ft5x0x_read_reg(data->client, data->addr, &reg);
984 if (rc < 0)
985 dev_err(&data->client->dev,
986 "FT read register 0x%x failed (%d)\n",
987 data->addr, rc);
988 else
989 *val = reg;
990 }
991
992 mutex_unlock(&data->input_dev->mutex);
993
994 return 0;
995}
996
997DEFINE_SIMPLE_ATTRIBUTE(debug_data_fops, ft5x06_debug_data_get,
998 ft5x06_debug_data_set, "0x%02llX\n");
999
1000static int ft5x06_debug_addr_set(void *_data, u64 val)
1001{
1002 struct ft5x06_ts_data *data = _data;
1003
1004 if (ft5x06_debug_addr_is_valid(val)) {
1005 mutex_lock(&data->input_dev->mutex);
1006 data->addr = val;
1007 mutex_unlock(&data->input_dev->mutex);
1008 }
1009
1010 return 0;
1011}
1012
1013static int ft5x06_debug_addr_get(void *_data, u64 *val)
1014{
1015 struct ft5x06_ts_data *data = _data;
1016
1017 mutex_lock(&data->input_dev->mutex);
1018
1019 if (ft5x06_debug_addr_is_valid(data->addr))
1020 *val = data->addr;
1021
1022 mutex_unlock(&data->input_dev->mutex);
1023
1024 return 0;
1025}
1026
1027DEFINE_SIMPLE_ATTRIBUTE(debug_addr_fops, ft5x06_debug_addr_get,
1028 ft5x06_debug_addr_set, "0x%02llX\n");
1029
1030static int ft5x06_debug_suspend_set(void *_data, u64 val)
1031{
1032 struct ft5x06_ts_data *data = _data;
1033
1034 mutex_lock(&data->input_dev->mutex);
1035
1036 if (val)
1037 ft5x06_ts_suspend(&data->client->dev);
1038 else
1039 ft5x06_ts_resume(&data->client->dev);
1040
1041 mutex_unlock(&data->input_dev->mutex);
1042
1043 return 0;
1044}
1045
1046static int ft5x06_debug_suspend_get(void *_data, u64 *val)
1047{
1048 struct ft5x06_ts_data *data = _data;
1049
1050 mutex_lock(&data->input_dev->mutex);
1051 *val = data->suspended;
1052 mutex_unlock(&data->input_dev->mutex);
1053
1054 return 0;
1055}
1056
1057DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, ft5x06_debug_suspend_get,
1058 ft5x06_debug_suspend_set, "%lld\n");
1059
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301060static int ft5x06_debug_dump_info(struct seq_file *m, void *v)
1061{
1062 struct ft5x06_ts_data *data = m->private;
1063
1064 seq_printf(m, "%s\n", data->ts_info);
1065
1066 return 0;
1067}
1068
1069static int debugfs_dump_info_open(struct inode *inode, struct file *file)
1070{
1071 return single_open(file, ft5x06_debug_dump_info, inode->i_private);
1072}
1073
1074static const struct file_operations debug_dump_info_fops = {
1075 .owner = THIS_MODULE,
1076 .open = debugfs_dump_info_open,
1077 .read = seq_read,
1078 .release = single_release,
1079};
1080
Mohan Pallaka3a138202013-05-09 16:30:00 +05301081#ifdef CONFIG_OF
1082static int ft5x06_get_dt_coords(struct device *dev, char *name,
1083 struct ft5x06_ts_platform_data *pdata)
1084{
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301085 u32 coords[FT_COORDS_ARR_SIZE];
Mohan Pallaka3a138202013-05-09 16:30:00 +05301086 struct property *prop;
1087 struct device_node *np = dev->of_node;
1088 int coords_size, rc;
1089
1090 prop = of_find_property(np, name, NULL);
1091 if (!prop)
1092 return -EINVAL;
1093 if (!prop->value)
1094 return -ENODATA;
1095
1096 coords_size = prop->length / sizeof(u32);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301097 if (coords_size != FT_COORDS_ARR_SIZE) {
Mohan Pallaka3a138202013-05-09 16:30:00 +05301098 dev_err(dev, "invalid %s\n", name);
1099 return -EINVAL;
1100 }
1101
1102 rc = of_property_read_u32_array(np, name, coords, coords_size);
1103 if (rc && (rc != -EINVAL)) {
1104 dev_err(dev, "Unable to read %s\n", name);
1105 return rc;
1106 }
1107
1108 if (!strcmp(name, "focaltech,panel-coords")) {
1109 pdata->panel_minx = coords[0];
1110 pdata->panel_miny = coords[1];
1111 pdata->panel_maxx = coords[2];
1112 pdata->panel_maxy = coords[3];
1113 } else if (!strcmp(name, "focaltech,display-coords")) {
1114 pdata->x_min = coords[0];
1115 pdata->y_min = coords[1];
1116 pdata->x_max = coords[2];
1117 pdata->y_max = coords[3];
1118 } else {
1119 dev_err(dev, "unsupported property %s\n", name);
1120 return -EINVAL;
1121 }
1122
1123 return 0;
1124}
1125
1126static int ft5x06_parse_dt(struct device *dev,
1127 struct ft5x06_ts_platform_data *pdata)
1128{
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301129 int rc;
Mohan Pallaka3a138202013-05-09 16:30:00 +05301130 struct device_node *np = dev->of_node;
1131 struct property *prop;
1132 u32 temp_val, num_buttons;
1133 u32 button_map[MAX_BUTTONS];
1134
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301135 pdata->name = "focaltech";
1136 rc = of_property_read_string(np, "focaltech,name", &pdata->name);
1137 if (rc && (rc != -EINVAL)) {
1138 dev_err(dev, "Unable to read name\n");
1139 return rc;
1140 }
1141
Mohan Pallaka3a138202013-05-09 16:30:00 +05301142 rc = ft5x06_get_dt_coords(dev, "focaltech,panel-coords", pdata);
1143 if (rc && (rc != -EINVAL))
1144 return rc;
1145
1146 rc = ft5x06_get_dt_coords(dev, "focaltech,display-coords", pdata);
1147 if (rc)
1148 return rc;
1149
1150 pdata->i2c_pull_up = of_property_read_bool(np,
1151 "focaltech,i2c-pull-up");
1152
1153 pdata->no_force_update = of_property_read_bool(np,
1154 "focaltech,no-force-update");
1155 /* reset, irq gpio info */
1156 pdata->reset_gpio = of_get_named_gpio_flags(np, "focaltech,reset-gpio",
1157 0, &pdata->reset_gpio_flags);
1158 if (pdata->reset_gpio < 0)
1159 return pdata->reset_gpio;
1160
1161 pdata->irq_gpio = of_get_named_gpio_flags(np, "focaltech,irq-gpio",
1162 0, &pdata->irq_gpio_flags);
1163 if (pdata->irq_gpio < 0)
1164 return pdata->irq_gpio;
1165
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301166 pdata->fw_name = "ft_fw.bin";
1167 rc = of_property_read_string(np, "focaltech,fw-name", &pdata->fw_name);
1168 if (rc && (rc != -EINVAL)) {
1169 dev_err(dev, "Unable to read fw name\n");
1170 return rc;
1171 }
1172
1173 rc = of_property_read_u32(np, "focaltech,group-id", &temp_val);
1174 if (!rc)
1175 pdata->group_id = temp_val;
1176 else
1177 return rc;
1178
1179 rc = of_property_read_u32(np, "focaltech,hard-reset-delay-ms",
1180 &temp_val);
1181 if (!rc)
1182 pdata->hard_rst_dly = temp_val;
1183 else
1184 return rc;
1185
1186 rc = of_property_read_u32(np, "focaltech,soft-reset-delay-ms",
1187 &temp_val);
1188 if (!rc)
1189 pdata->soft_rst_dly = temp_val;
1190 else
1191 return rc;
1192
1193 rc = of_property_read_u32(np, "focaltech,num-max-touches", &temp_val);
1194 if (!rc)
1195 pdata->num_max_touches = temp_val;
1196 else
1197 return rc;
1198
1199 rc = of_property_read_u32(np, "focaltech,fw-delay-aa-ms", &temp_val);
1200 if (rc && (rc != -EINVAL)) {
1201 dev_err(dev, "Unable to read fw delay aa\n");
1202 return rc;
1203 } else if (rc != -EINVAL)
1204 pdata->info.delay_aa = temp_val;
1205
1206 rc = of_property_read_u32(np, "focaltech,fw-delay-55-ms", &temp_val);
1207 if (rc && (rc != -EINVAL)) {
1208 dev_err(dev, "Unable to read fw delay 55\n");
1209 return rc;
1210 } else if (rc != -EINVAL)
1211 pdata->info.delay_55 = temp_val;
1212
1213 rc = of_property_read_u32(np, "focaltech,fw-upgrade-id1", &temp_val);
1214 if (rc && (rc != -EINVAL)) {
1215 dev_err(dev, "Unable to read fw upgrade id1\n");
1216 return rc;
1217 } else if (rc != -EINVAL)
1218 pdata->info.upgrade_id_1 = temp_val;
1219
1220 rc = of_property_read_u32(np, "focaltech,fw-upgrade-id2", &temp_val);
1221 if (rc && (rc != -EINVAL)) {
1222 dev_err(dev, "Unable to read fw upgrade id2\n");
1223 return rc;
1224 } else if (rc != -EINVAL)
1225 pdata->info.upgrade_id_2 = temp_val;
1226
1227 rc = of_property_read_u32(np, "focaltech,fw-delay-readid-ms",
1228 &temp_val);
1229 if (rc && (rc != -EINVAL)) {
1230 dev_err(dev, "Unable to read fw delay read id\n");
1231 return rc;
1232 } else if (rc != -EINVAL)
1233 pdata->info.delay_readid = temp_val;
1234
1235 rc = of_property_read_u32(np, "focaltech,fw-delay-era-flsh-ms",
1236 &temp_val);
1237 if (rc && (rc != -EINVAL)) {
1238 dev_err(dev, "Unable to read fw delay erase flash\n");
1239 return rc;
1240 } else if (rc != -EINVAL)
1241 pdata->info.delay_erase_flash = temp_val;
1242
1243 pdata->info.auto_cal = of_property_read_bool(np,
1244 "focaltech,fw-auto-cal");
1245
Mohan Pallakaa348d752013-08-28 13:44:36 +05301246 pdata->fw_vkey_support = of_property_read_bool(np,
1247 "focaltech,fw-vkey-support");
1248
Bingzhe Caid85a69d2013-10-09 22:15:31 +08001249 pdata->ignore_id_check = of_property_read_bool(np,
1250 "focaltech,ignore-id-check");
1251
Mohan Pallaka3a138202013-05-09 16:30:00 +05301252 rc = of_property_read_u32(np, "focaltech,family-id", &temp_val);
1253 if (!rc)
1254 pdata->family_id = temp_val;
1255 else
1256 return rc;
1257
1258 prop = of_find_property(np, "focaltech,button-map", NULL);
1259 if (prop) {
1260 num_buttons = prop->length / sizeof(temp_val);
1261 if (num_buttons > MAX_BUTTONS)
1262 return -EINVAL;
1263
1264 rc = of_property_read_u32_array(np,
1265 "focaltech,button-map", button_map,
1266 num_buttons);
1267 if (rc) {
1268 dev_err(dev, "Unable to read key codes\n");
1269 return rc;
1270 }
1271 }
1272
1273 return 0;
1274}
1275#else
1276static int ft5x06_parse_dt(struct device *dev,
1277 struct ft5x06_ts_platform_data *pdata)
1278{
1279 return -ENODEV;
1280}
1281#endif
1282
Mohan Pallakaa2595072012-01-12 22:23:15 +05301283static int ft5x06_ts_probe(struct i2c_client *client,
1284 const struct i2c_device_id *id)
1285{
Mohan Pallaka3a138202013-05-09 16:30:00 +05301286 struct ft5x06_ts_platform_data *pdata;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301287 struct ft5x06_ts_data *data;
1288 struct input_dev *input_dev;
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301289 struct dentry *temp;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301290 u8 reg_value;
1291 u8 reg_addr;
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301292 int err, len;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301293
Mohan Pallaka3a138202013-05-09 16:30:00 +05301294 if (client->dev.of_node) {
1295 pdata = devm_kzalloc(&client->dev,
1296 sizeof(struct ft5x06_ts_platform_data), GFP_KERNEL);
1297 if (!pdata) {
1298 dev_err(&client->dev, "Failed to allocate memory\n");
1299 return -ENOMEM;
1300 }
1301
1302 err = ft5x06_parse_dt(&client->dev, pdata);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301303 if (err) {
1304 dev_err(&client->dev, "DT parsing failed\n");
Mohan Pallaka3a138202013-05-09 16:30:00 +05301305 return err;
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301306 }
Mohan Pallaka3a138202013-05-09 16:30:00 +05301307 } else
1308 pdata = client->dev.platform_data;
1309
Mohan Pallakaa2595072012-01-12 22:23:15 +05301310 if (!pdata) {
1311 dev_err(&client->dev, "Invalid pdata\n");
1312 return -EINVAL;
1313 }
1314
1315 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
1316 dev_err(&client->dev, "I2C not supported\n");
1317 return -ENODEV;
1318 }
1319
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301320 data = devm_kzalloc(&client->dev,
1321 sizeof(struct ft5x06_ts_data), GFP_KERNEL);
1322 if (!data) {
1323 dev_err(&client->dev, "Not enough memory\n");
1324 return -ENOMEM;
1325 }
1326
1327 if (pdata->fw_name) {
1328 len = strlen(pdata->fw_name);
1329 if (len > FT_FW_NAME_MAX_LEN - 1) {
1330 dev_err(&client->dev, "Invalid firmware name\n");
1331 return -EINVAL;
1332 }
1333
1334 strlcpy(data->fw_name, pdata->fw_name, len + 1);
1335 }
1336
1337 data->tch_data_len = FT_TCH_LEN(pdata->num_max_touches);
1338 data->tch_data = devm_kzalloc(&client->dev,
1339 data->tch_data_len, GFP_KERNEL);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301340 if (!data) {
1341 dev_err(&client->dev, "Not enough memory\n");
1342 return -ENOMEM;
1343 }
1344
1345 input_dev = input_allocate_device();
1346 if (!input_dev) {
Mohan Pallakaa2595072012-01-12 22:23:15 +05301347 dev_err(&client->dev, "failed to allocate input device\n");
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301348 return -ENOMEM;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301349 }
1350
1351 data->input_dev = input_dev;
1352 data->client = client;
1353 data->pdata = pdata;
1354
1355 input_dev->name = "ft5x06_ts";
1356 input_dev->id.bustype = BUS_I2C;
1357 input_dev->dev.parent = &client->dev;
1358
1359 input_set_drvdata(input_dev, data);
1360 i2c_set_clientdata(client, data);
1361
1362 __set_bit(EV_KEY, input_dev->evbit);
1363 __set_bit(EV_ABS, input_dev->evbit);
1364 __set_bit(BTN_TOUCH, input_dev->keybit);
Amy Malochedd2703d2012-06-20 11:03:56 -07001365 __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301366
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301367 input_mt_init_slots(input_dev, pdata->num_max_touches);
Mohan Pallaka3a138202013-05-09 16:30:00 +05301368 input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min,
Mohan Pallakaa2595072012-01-12 22:23:15 +05301369 pdata->x_max, 0, 0);
Mohan Pallaka3a138202013-05-09 16:30:00 +05301370 input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min,
Mohan Pallakaa2595072012-01-12 22:23:15 +05301371 pdata->y_max, 0, 0);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301372 input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, FT_PRESS, 0, 0);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301373
1374 err = input_register_device(input_dev);
1375 if (err) {
1376 dev_err(&client->dev, "Input device registration failed\n");
1377 goto free_inputdev;
1378 }
1379
1380 if (pdata->power_init) {
1381 err = pdata->power_init(true);
1382 if (err) {
1383 dev_err(&client->dev, "power init failed");
1384 goto unreg_inputdev;
1385 }
1386 } else {
1387 err = ft5x06_power_init(data, true);
1388 if (err) {
1389 dev_err(&client->dev, "power init failed");
1390 goto unreg_inputdev;
1391 }
1392 }
1393
1394 if (pdata->power_on) {
1395 err = pdata->power_on(true);
1396 if (err) {
1397 dev_err(&client->dev, "power on failed");
1398 goto pwr_deinit;
1399 }
1400 } else {
1401 err = ft5x06_power_on(data, true);
1402 if (err) {
1403 dev_err(&client->dev, "power on failed");
1404 goto pwr_deinit;
1405 }
1406 }
1407
1408 if (gpio_is_valid(pdata->irq_gpio)) {
1409 err = gpio_request(pdata->irq_gpio, "ft5x06_irq_gpio");
1410 if (err) {
1411 dev_err(&client->dev, "irq gpio request failed");
1412 goto pwr_off;
1413 }
1414 err = gpio_direction_input(pdata->irq_gpio);
1415 if (err) {
1416 dev_err(&client->dev,
1417 "set_direction for irq gpio failed\n");
1418 goto free_irq_gpio;
1419 }
1420 }
1421
1422 if (gpio_is_valid(pdata->reset_gpio)) {
1423 err = gpio_request(pdata->reset_gpio, "ft5x06_reset_gpio");
1424 if (err) {
1425 dev_err(&client->dev, "reset gpio request failed");
1426 goto free_irq_gpio;
1427 }
1428
1429 err = gpio_direction_output(pdata->reset_gpio, 0);
1430 if (err) {
1431 dev_err(&client->dev,
1432 "set_direction for reset gpio failed\n");
1433 goto free_reset_gpio;
1434 }
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301435 msleep(data->pdata->hard_rst_dly);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301436 gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
1437 }
1438
1439 /* make sure CTP already finish startup process */
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301440 msleep(data->pdata->soft_rst_dly);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301441
Mohan Pallaka3a138202013-05-09 16:30:00 +05301442 /* check the controller id */
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301443 reg_addr = FT_REG_ID;
Mohan Pallaka3a138202013-05-09 16:30:00 +05301444 err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
1445 if (err < 0) {
1446 dev_err(&client->dev, "version read failed");
Shantanu Jain3da65202013-07-08 19:11:07 +05301447 goto free_reset_gpio;
Mohan Pallaka3a138202013-05-09 16:30:00 +05301448 }
1449
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301450 dev_info(&client->dev, "Device ID = 0x%x\n", reg_value);
1451
Bingzhe Caid85a69d2013-10-09 22:15:31 +08001452 if ((pdata->family_id != reg_value) && (!pdata->ignore_id_check)) {
Mohan Pallaka3a138202013-05-09 16:30:00 +05301453 dev_err(&client->dev, "%s:Unsupported controller\n", __func__);
1454 goto free_reset_gpio;
1455 }
1456
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301457 data->family_id = reg_value;
1458
Mohan Pallakaa2595072012-01-12 22:23:15 +05301459 err = request_threaded_irq(client->irq, NULL,
1460 ft5x06_ts_interrupt, pdata->irqflags,
1461 client->dev.driver->name, data);
1462 if (err) {
1463 dev_err(&client->dev, "request irq failed\n");
1464 goto free_reset_gpio;
1465 }
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301466
1467 err = device_create_file(&client->dev, &dev_attr_fw_name);
1468 if (err) {
1469 dev_err(&client->dev, "sys file creation failed\n");
1470 goto irq_free;
1471 }
1472
1473 err = device_create_file(&client->dev, &dev_attr_update_fw);
1474 if (err) {
1475 dev_err(&client->dev, "sys file creation failed\n");
1476 goto free_fw_name_sys;
1477 }
1478
1479 err = device_create_file(&client->dev, &dev_attr_force_update_fw);
1480 if (err) {
1481 dev_err(&client->dev, "sys file creation failed\n");
1482 goto free_update_fw_sys;
1483 }
1484
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301485 data->dir = debugfs_create_dir(FT_DEBUG_DIR_NAME, NULL);
1486 if (data->dir == NULL || IS_ERR(data->dir)) {
1487 pr_err("debugfs_create_dir failed(%ld)\n", PTR_ERR(data->dir));
1488 err = PTR_ERR(data->dir);
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301489 goto free_force_update_fw_sys;
1490 }
1491
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301492 temp = debugfs_create_file("addr", S_IRUSR | S_IWUSR, data->dir, data,
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301493 &debug_addr_fops);
1494 if (temp == NULL || IS_ERR(temp)) {
1495 pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
1496 err = PTR_ERR(temp);
1497 goto free_debug_dir;
1498 }
1499
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301500 temp = debugfs_create_file("data", S_IRUSR | S_IWUSR, data->dir, data,
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301501 &debug_data_fops);
1502 if (temp == NULL || IS_ERR(temp)) {
1503 pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
1504 err = PTR_ERR(temp);
1505 goto free_debug_dir;
1506 }
1507
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301508 temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, data->dir,
1509 data, &debug_suspend_fops);
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301510 if (temp == NULL || IS_ERR(temp)) {
1511 pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
1512 err = PTR_ERR(temp);
1513 goto free_debug_dir;
1514 }
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301515
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301516 temp = debugfs_create_file("dump_info", S_IRUSR | S_IWUSR, data->dir,
1517 data, &debug_dump_info_fops);
1518 if (temp == NULL || IS_ERR(temp)) {
1519 pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
1520 err = PTR_ERR(temp);
1521 goto free_debug_dir;
1522 }
1523
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301524 data->ts_info = devm_kzalloc(&client->dev,
1525 FT_INFO_MAX_LEN, GFP_KERNEL);
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301526 if (!data->ts_info) {
1527 dev_err(&client->dev, "Not enough memory\n");
1528 goto free_debug_dir;
1529 }
1530
1531 /*get some register information */
1532 reg_addr = FT_REG_POINT_RATE;
1533 ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
1534 if (err < 0)
1535 dev_err(&client->dev, "report rate read failed");
1536
1537 dev_info(&client->dev, "report rate = %dHz\n", reg_value * 10);
1538
1539 reg_addr = FT_REG_THGROUP;
1540 err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
1541 if (err < 0)
1542 dev_err(&client->dev, "threshold read failed");
1543
1544 dev_dbg(&client->dev, "touch threshold = %d\n", reg_value * 4);
1545
Mohan Pallakaa348d752013-08-28 13:44:36 +05301546 ft5x06_update_fw_ver(data);
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301547
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301548 FT_STORE_TS_INFO(data->ts_info, data->family_id, data->pdata->name,
1549 data->pdata->num_max_touches, data->pdata->group_id,
Mohan Pallakaa348d752013-08-28 13:44:36 +05301550 data->pdata->fw_vkey_support ? "yes" : "no",
1551 data->pdata->fw_name, data->fw_ver[0],
1552 data->fw_ver[1], data->fw_ver[2]);
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301553
Mohan Pallakaa5d601b2013-05-10 15:34:44 +05301554#if defined(CONFIG_FB)
1555 data->fb_notif.notifier_call = fb_notifier_callback;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301556
Mohan Pallakaa5d601b2013-05-10 15:34:44 +05301557 err = fb_register_client(&data->fb_notif);
1558
1559 if (err)
1560 dev_err(&client->dev, "Unable to register fb_notifier: %d\n",
1561 err);
1562#elif defined(CONFIG_HAS_EARLYSUSPEND)
Mohan Pallakaa2595072012-01-12 22:23:15 +05301563 data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301564 FT_SUSPEND_LEVEL;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301565 data->early_suspend.suspend = ft5x06_ts_early_suspend;
1566 data->early_suspend.resume = ft5x06_ts_late_resume;
1567 register_early_suspend(&data->early_suspend);
1568#endif
1569
1570 return 0;
1571
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301572free_debug_dir:
1573 debugfs_remove_recursive(data->dir);
1574free_force_update_fw_sys:
1575 device_remove_file(&client->dev, &dev_attr_force_update_fw);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301576free_update_fw_sys:
1577 device_remove_file(&client->dev, &dev_attr_update_fw);
1578free_fw_name_sys:
1579 device_remove_file(&client->dev, &dev_attr_fw_name);
1580irq_free:
1581 free_irq(client->irq, data);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301582free_reset_gpio:
1583 if (gpio_is_valid(pdata->reset_gpio))
1584 gpio_free(pdata->reset_gpio);
1585free_irq_gpio:
1586 if (gpio_is_valid(pdata->irq_gpio))
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301587 gpio_free(pdata->irq_gpio);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301588pwr_off:
1589 if (pdata->power_on)
1590 pdata->power_on(false);
1591 else
1592 ft5x06_power_on(data, false);
1593pwr_deinit:
1594 if (pdata->power_init)
1595 pdata->power_init(false);
1596 else
1597 ft5x06_power_init(data, false);
1598unreg_inputdev:
1599 input_unregister_device(input_dev);
1600 input_dev = NULL;
1601free_inputdev:
1602 input_free_device(input_dev);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301603 return err;
1604}
1605
1606static int __devexit ft5x06_ts_remove(struct i2c_client *client)
1607{
1608 struct ft5x06_ts_data *data = i2c_get_clientdata(client);
1609
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301610 debugfs_remove_recursive(data->dir);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301611 device_remove_file(&client->dev, &dev_attr_force_update_fw);
1612 device_remove_file(&client->dev, &dev_attr_update_fw);
1613 device_remove_file(&client->dev, &dev_attr_fw_name);
1614
Mohan Pallakaa5d601b2013-05-10 15:34:44 +05301615#if defined(CONFIG_FB)
1616 if (fb_unregister_client(&data->fb_notif))
1617 dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
1618#elif defined(CONFIG_HAS_EARLYSUSPEND)
Mohan Pallakaa2595072012-01-12 22:23:15 +05301619 unregister_early_suspend(&data->early_suspend);
1620#endif
1621 free_irq(client->irq, data);
1622
1623 if (gpio_is_valid(data->pdata->reset_gpio))
1624 gpio_free(data->pdata->reset_gpio);
1625
1626 if (gpio_is_valid(data->pdata->irq_gpio))
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301627 gpio_free(data->pdata->irq_gpio);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301628
1629 if (data->pdata->power_on)
1630 data->pdata->power_on(false);
1631 else
1632 ft5x06_power_on(data, false);
1633
1634 if (data->pdata->power_init)
1635 data->pdata->power_init(false);
1636 else
1637 ft5x06_power_init(data, false);
1638
1639 input_unregister_device(data->input_dev);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301640
1641 return 0;
1642}
1643
1644static const struct i2c_device_id ft5x06_ts_id[] = {
1645 {"ft5x06_ts", 0},
1646 {},
1647};
1648
1649MODULE_DEVICE_TABLE(i2c, ft5x06_ts_id);
1650
Mohan Pallaka3a138202013-05-09 16:30:00 +05301651#ifdef CONFIG_OF
1652static struct of_device_id ft5x06_match_table[] = {
1653 { .compatible = "focaltech,5x06",},
1654 { },
1655};
1656#else
1657#define ft5x06_match_table NULL
1658#endif
1659
Mohan Pallakaa2595072012-01-12 22:23:15 +05301660static struct i2c_driver ft5x06_ts_driver = {
1661 .probe = ft5x06_ts_probe,
1662 .remove = __devexit_p(ft5x06_ts_remove),
1663 .driver = {
1664 .name = "ft5x06_ts",
1665 .owner = THIS_MODULE,
Mohan Pallaka3a138202013-05-09 16:30:00 +05301666 .of_match_table = ft5x06_match_table,
Mohan Pallakaa2595072012-01-12 22:23:15 +05301667#ifdef CONFIG_PM
1668 .pm = &ft5x06_ts_pm_ops,
1669#endif
1670 },
1671 .id_table = ft5x06_ts_id,
1672};
1673
1674static int __init ft5x06_ts_init(void)
1675{
1676 return i2c_add_driver(&ft5x06_ts_driver);
1677}
1678module_init(ft5x06_ts_init);
1679
1680static void __exit ft5x06_ts_exit(void)
1681{
1682 i2c_del_driver(&ft5x06_ts_driver);
1683}
1684module_exit(ft5x06_ts_exit);
1685
1686MODULE_DESCRIPTION("FocalTech ft5x06 TouchScreen driver");
1687MODULE_LICENSE("GPL v2");