blob: f36636468abc062c6b49e1c4b429a54fc5455eef [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
Bingzhe Cai49d56622013-10-28 19:30:27 +0800134#define FT_55_AA_DLY_NS 5000
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530135
Bingzhe Cai49d56622013-10-28 19:30:27 +0800136#define FT_UPGRADE_LOOP 30
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530137#define FT_CAL_START 0x04
138#define FT_CAL_FIN 0x00
139#define FT_CAL_STORE 0x05
140#define FT_CAL_RETRY 100
141#define FT_REG_CAL 0x00
142#define FT_CAL_MASK 0x70
143
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530144#define FT_INFO_MAX_LEN 512
Mohan Pallaka768d5e32013-06-14 17:50:10 +0530145
Bingzhe Cai49d56622013-10-28 19:30:27 +0800146#define FT_BLOADER_SIZE_OFF 12
147#define FT_BLOADER_NEW_SIZE 30
148#define FT_DATA_LEN_OFF_OLD_FW 8
149#define FT_DATA_LEN_OFF_NEW_FW 14
150#define FT_FINISHING_PKT_LEN_OLD_FW 6
151#define FT_FINISHING_PKT_LEN_NEW_FW 12
152#define FT_MAGIC_BLOADER_Z7 0x7bfa
153#define FT_MAGIC_BLOADER_LZ4 0x6ffa
154#define FT_MAGIC_BLOADER_GZF_30 0x7ff4
155#define FT_MAGIC_BLOADER_GZF 0x7bf4
156
157enum {
158 FT_BLOADER_VERSION_LZ4 = 0,
159 FT_BLOADER_VERSION_Z7 = 1,
160 FT_BLOADER_VERSION_GZF = 2,
161};
162
163enum {
164 FT_FT5336_FAMILY_ID_0x11 = 0x11,
165 FT_FT5336_FAMILY_ID_0x12 = 0x12,
166 FT_FT5336_FAMILY_ID_0x13 = 0x13,
167 FT_FT5336_FAMILY_ID_0x14 = 0x14,
168};
169
Mohan Pallakaa348d752013-08-28 13:44:36 +0530170#define FT_STORE_TS_INFO(buf, id, name, max_tch, group_id, fw_vkey_support, \
171 fw_name, fw_maj, fw_min, fw_sub_min) \
Mohan Pallaka768d5e32013-06-14 17:50:10 +0530172 snprintf(buf, FT_INFO_MAX_LEN, \
173 "controller\t= focaltech\n" \
174 "model\t\t= 0x%x\n" \
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530175 "name\t\t= %s\n" \
176 "max_touches\t= %d\n" \
177 "drv_ver\t\t= 0x%x\n" \
178 "group_id\t= 0x%x\n" \
Mohan Pallakaa348d752013-08-28 13:44:36 +0530179 "fw_vkey_support\t= %s\n" \
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530180 "fw_name\t\t= %s\n" \
Mohan Pallakaa348d752013-08-28 13:44:36 +0530181 "fw_ver\t\t= %d.%d.%d\n", id, name, \
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530182 max_tch, FT_DRIVER_VERSION, group_id, \
Mohan Pallakaa348d752013-08-28 13:44:36 +0530183 fw_vkey_support, fw_name, fw_maj, fw_min, \
184 fw_sub_min)
Mohan Pallaka768d5e32013-06-14 17:50:10 +0530185
186#define FT_DEBUG_DIR_NAME "ts_debug"
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530187
Mohan Pallakaa2595072012-01-12 22:23:15 +0530188struct ft5x06_ts_data {
189 struct i2c_client *client;
190 struct input_dev *input_dev;
Mohan Pallakaa2595072012-01-12 22:23:15 +0530191 const struct ft5x06_ts_platform_data *pdata;
192 struct regulator *vdd;
193 struct regulator *vcc_i2c;
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530194 char fw_name[FT_FW_NAME_MAX_LEN];
195 bool loading_fw;
196 u8 family_id;
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530197 struct dentry *dir;
198 u16 addr;
199 bool suspended;
Mohan Pallaka768d5e32013-06-14 17:50:10 +0530200 char *ts_info;
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530201 u8 *tch_data;
202 u32 tch_data_len;
Mohan Pallakaa348d752013-08-28 13:44:36 +0530203 u8 fw_ver[3];
Mohan Pallakaa5d601b2013-05-10 15:34:44 +0530204#if defined(CONFIG_FB)
205 struct notifier_block fb_notif;
206#elif defined(CONFIG_HAS_EARLYSUSPEND)
Mohan Pallakaa2595072012-01-12 22:23:15 +0530207 struct early_suspend early_suspend;
208#endif
209};
210
211static int ft5x06_i2c_read(struct i2c_client *client, char *writebuf,
212 int writelen, char *readbuf, int readlen)
213{
214 int ret;
215
216 if (writelen > 0) {
217 struct i2c_msg msgs[] = {
218 {
219 .addr = client->addr,
220 .flags = 0,
221 .len = writelen,
222 .buf = writebuf,
223 },
224 {
225 .addr = client->addr,
226 .flags = I2C_M_RD,
227 .len = readlen,
228 .buf = readbuf,
229 },
230 };
231 ret = i2c_transfer(client->adapter, msgs, 2);
232 if (ret < 0)
233 dev_err(&client->dev, "%s: i2c read error.\n",
234 __func__);
235 } else {
236 struct i2c_msg msgs[] = {
237 {
238 .addr = client->addr,
239 .flags = I2C_M_RD,
240 .len = readlen,
241 .buf = readbuf,
242 },
243 };
244 ret = i2c_transfer(client->adapter, msgs, 1);
245 if (ret < 0)
246 dev_err(&client->dev, "%s:i2c read error.\n", __func__);
247 }
248 return ret;
249}
250
251static int ft5x06_i2c_write(struct i2c_client *client, char *writebuf,
252 int writelen)
253{
254 int ret;
255
256 struct i2c_msg msgs[] = {
257 {
258 .addr = client->addr,
259 .flags = 0,
260 .len = writelen,
261 .buf = writebuf,
262 },
263 };
264 ret = i2c_transfer(client->adapter, msgs, 1);
265 if (ret < 0)
266 dev_err(&client->dev, "%s: i2c write error.\n", __func__);
267
268 return ret;
269}
270
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530271static int ft5x0x_write_reg(struct i2c_client *client, u8 addr, const u8 val)
272{
273 u8 buf[2] = {0};
274
275 buf[0] = addr;
276 buf[1] = val;
277
278 return ft5x06_i2c_write(client, buf, sizeof(buf));
279}
280
281static int ft5x0x_read_reg(struct i2c_client *client, u8 addr, u8 *val)
282{
283 return ft5x06_i2c_read(client, &addr, 1, val, 1);
284}
285
Mohan Pallakaa348d752013-08-28 13:44:36 +0530286static void ft5x06_update_fw_ver(struct ft5x06_ts_data *data)
287{
288 struct i2c_client *client = data->client;
289 u8 reg_addr;
290 int err;
291
292 reg_addr = FT_REG_FW_MAJ_VER;
293 err = ft5x06_i2c_read(client, &reg_addr, 1, &data->fw_ver[0], 1);
294 if (err < 0)
295 dev_err(&client->dev, "fw major version read failed");
296
297 reg_addr = FT_REG_FW_MIN_VER;
298 err = ft5x06_i2c_read(client, &reg_addr, 1, &data->fw_ver[1], 1);
299 if (err < 0)
300 dev_err(&client->dev, "fw minor version read failed");
301
302 reg_addr = FT_REG_FW_SUB_MIN_VER;
303 err = ft5x06_i2c_read(client, &reg_addr, 1, &data->fw_ver[2], 1);
304 if (err < 0)
305 dev_err(&client->dev, "fw sub minor version read failed");
306
307 dev_info(&client->dev, "Firmware version = %d.%d.%d\n",
308 data->fw_ver[0], data->fw_ver[1], data->fw_ver[2]);
309}
310
Mohan Pallakaa2595072012-01-12 22:23:15 +0530311static irqreturn_t ft5x06_ts_interrupt(int irq, void *dev_id)
312{
313 struct ft5x06_ts_data *data = dev_id;
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530314 struct input_dev *ip_dev;
315 int rc, i;
Bingzhe Cai4deceb32013-10-25 00:28:21 +0800316 u32 id, x, y, status, num_touches;
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530317 u8 reg = 0x00, *buf;
318 bool update_input = false;
Mohan Pallakaa2595072012-01-12 22:23:15 +0530319
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530320 if (!data) {
321 pr_err("%s: Invalid data\n", __func__);
322 return IRQ_HANDLED;
323 }
324
325 ip_dev = data->input_dev;
326 buf = data->tch_data;
327
328 rc = ft5x06_i2c_read(data->client, &reg, 1,
329 buf, data->tch_data_len);
330 if (rc < 0) {
331 dev_err(&data->client->dev, "%s: read data fail\n", __func__);
332 return IRQ_HANDLED;
333 }
334
335 for (i = 0; i < data->pdata->num_max_touches; i++) {
336 id = (buf[FT_TOUCH_ID_POS + FT_ONE_TCH_LEN * i]) >> 4;
337 if (id >= FT_MAX_ID)
338 break;
339
340 update_input = true;
341
342 x = (buf[FT_TOUCH_X_H_POS + FT_ONE_TCH_LEN * i] & 0x0F) << 8 |
343 (buf[FT_TOUCH_X_L_POS + FT_ONE_TCH_LEN * i]);
344 y = (buf[FT_TOUCH_Y_H_POS + FT_ONE_TCH_LEN * i] & 0x0F) << 8 |
345 (buf[FT_TOUCH_Y_L_POS + FT_ONE_TCH_LEN * i]);
346
347 status = buf[FT_TOUCH_EVENT_POS + FT_ONE_TCH_LEN * i] >> 6;
348
349 num_touches = buf[FT_TD_STATUS] & FT_STATUS_NUM_TP_MASK;
350
351 /* invalid combination */
352 if (!num_touches && !status && !id)
353 break;
354
355 input_mt_slot(ip_dev, id);
356 if (status == FT_TOUCH_DOWN || status == FT_TOUCH_CONTACT) {
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530357 input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 1);
358 input_report_abs(ip_dev, ABS_MT_POSITION_X, x);
359 input_report_abs(ip_dev, ABS_MT_POSITION_Y, y);
Mohan Pallakaa348d752013-08-28 13:44:36 +0530360 } else {
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530361 input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 0);
Mohan Pallakaa348d752013-08-28 13:44:36 +0530362 }
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530363 }
364
365 if (update_input) {
366 input_mt_report_pointer_emulation(ip_dev, false);
367 input_sync(ip_dev);
368 }
Mohan Pallakaa2595072012-01-12 22:23:15 +0530369
370 return IRQ_HANDLED;
371}
372
373static int ft5x06_power_on(struct ft5x06_ts_data *data, bool on)
374{
375 int rc;
376
377 if (!on)
378 goto power_off;
379
380 rc = regulator_enable(data->vdd);
381 if (rc) {
382 dev_err(&data->client->dev,
383 "Regulator vdd enable failed rc=%d\n", rc);
384 return rc;
385 }
386
387 rc = regulator_enable(data->vcc_i2c);
388 if (rc) {
389 dev_err(&data->client->dev,
390 "Regulator vcc_i2c enable failed rc=%d\n", rc);
391 regulator_disable(data->vdd);
392 }
393
394 return rc;
395
396power_off:
397 rc = regulator_disable(data->vdd);
398 if (rc) {
399 dev_err(&data->client->dev,
400 "Regulator vdd disable failed rc=%d\n", rc);
401 return rc;
402 }
403
404 rc = regulator_disable(data->vcc_i2c);
405 if (rc) {
406 dev_err(&data->client->dev,
407 "Regulator vcc_i2c disable failed rc=%d\n", rc);
408 regulator_enable(data->vdd);
409 }
410
411 return rc;
412}
413
414static int ft5x06_power_init(struct ft5x06_ts_data *data, bool on)
415{
416 int rc;
417
418 if (!on)
419 goto pwr_deinit;
420
421 data->vdd = regulator_get(&data->client->dev, "vdd");
422 if (IS_ERR(data->vdd)) {
423 rc = PTR_ERR(data->vdd);
424 dev_err(&data->client->dev,
425 "Regulator get failed vdd rc=%d\n", rc);
426 return rc;
427 }
428
429 if (regulator_count_voltages(data->vdd) > 0) {
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530430 rc = regulator_set_voltage(data->vdd, FT_VTG_MIN_UV,
431 FT_VTG_MAX_UV);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530432 if (rc) {
433 dev_err(&data->client->dev,
434 "Regulator set_vtg failed vdd rc=%d\n", rc);
435 goto reg_vdd_put;
436 }
437 }
438
439 data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c");
440 if (IS_ERR(data->vcc_i2c)) {
441 rc = PTR_ERR(data->vcc_i2c);
442 dev_err(&data->client->dev,
443 "Regulator get failed vcc_i2c rc=%d\n", rc);
444 goto reg_vdd_set_vtg;
445 }
446
447 if (regulator_count_voltages(data->vcc_i2c) > 0) {
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530448 rc = regulator_set_voltage(data->vcc_i2c, FT_I2C_VTG_MIN_UV,
449 FT_I2C_VTG_MAX_UV);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530450 if (rc) {
451 dev_err(&data->client->dev,
452 "Regulator set_vtg failed vcc_i2c rc=%d\n", rc);
453 goto reg_vcc_i2c_put;
454 }
455 }
456
457 return 0;
458
459reg_vcc_i2c_put:
460 regulator_put(data->vcc_i2c);
461reg_vdd_set_vtg:
462 if (regulator_count_voltages(data->vdd) > 0)
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530463 regulator_set_voltage(data->vdd, 0, FT_VTG_MAX_UV);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530464reg_vdd_put:
465 regulator_put(data->vdd);
466 return rc;
467
468pwr_deinit:
469 if (regulator_count_voltages(data->vdd) > 0)
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530470 regulator_set_voltage(data->vdd, 0, FT_VTG_MAX_UV);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530471
472 regulator_put(data->vdd);
473
474 if (regulator_count_voltages(data->vcc_i2c) > 0)
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530475 regulator_set_voltage(data->vcc_i2c, 0, FT_I2C_VTG_MAX_UV);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530476
477 regulator_put(data->vcc_i2c);
478 return 0;
479}
480
481#ifdef CONFIG_PM
482static int ft5x06_ts_suspend(struct device *dev)
483{
484 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
Figo Wang63ad82b2013-06-28 19:49:49 +0800485 char txbuf[2], i;
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530486 int err;
Mohan Pallakaa2595072012-01-12 22:23:15 +0530487
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530488 if (data->loading_fw) {
489 dev_info(dev, "Firmware loading in process...\n");
490 return 0;
491 }
492
493 if (data->suspended) {
494 dev_info(dev, "Already in suspend state\n");
495 return 0;
496 }
497
Mohan Pallakaa2595072012-01-12 22:23:15 +0530498 disable_irq(data->client->irq);
499
Figo Wang63ad82b2013-06-28 19:49:49 +0800500 /* release all touches */
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530501 for (i = 0; i < data->pdata->num_max_touches; i++) {
Figo Wang63ad82b2013-06-28 19:49:49 +0800502 input_mt_slot(data->input_dev, i);
503 input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, 0);
504 }
Bingzhe Cai4deceb32013-10-25 00:28:21 +0800505 input_mt_report_pointer_emulation(data->input_dev, false);
Figo Wang63ad82b2013-06-28 19:49:49 +0800506 input_sync(data->input_dev);
507
Mohan Pallakaa2595072012-01-12 22:23:15 +0530508 if (gpio_is_valid(data->pdata->reset_gpio)) {
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530509 txbuf[0] = FT_REG_PMODE;
510 txbuf[1] = FT_PMODE_HIBERNATE;
Mohan Pallakaa2595072012-01-12 22:23:15 +0530511 ft5x06_i2c_write(data->client, txbuf, sizeof(txbuf));
512 }
513
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530514 if (data->pdata->power_on) {
515 err = data->pdata->power_on(false);
516 if (err) {
517 dev_err(dev, "power off failed");
518 goto pwr_off_fail;
519 }
520 } else {
521 err = ft5x06_power_on(data, false);
522 if (err) {
523 dev_err(dev, "power off failed");
524 goto pwr_off_fail;
525 }
526 }
527
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530528 data->suspended = true;
529
Mohan Pallakaa2595072012-01-12 22:23:15 +0530530 return 0;
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530531
532pwr_off_fail:
533 if (gpio_is_valid(data->pdata->reset_gpio)) {
534 gpio_set_value_cansleep(data->pdata->reset_gpio, 0);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530535 msleep(data->pdata->hard_rst_dly);
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530536 gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
537 }
538 enable_irq(data->client->irq);
539 return err;
Mohan Pallakaa2595072012-01-12 22:23:15 +0530540}
541
542static int ft5x06_ts_resume(struct device *dev)
543{
544 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530545 int err;
Mohan Pallakaa2595072012-01-12 22:23:15 +0530546
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530547 if (!data->suspended) {
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530548 dev_dbg(dev, "Already in awake state\n");
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530549 return 0;
550 }
551
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530552 if (data->pdata->power_on) {
553 err = data->pdata->power_on(true);
554 if (err) {
555 dev_err(dev, "power on failed");
556 return err;
557 }
558 } else {
559 err = ft5x06_power_on(data, true);
560 if (err) {
561 dev_err(dev, "power on failed");
562 return err;
563 }
564 }
565
Mohan Pallakaa2595072012-01-12 22:23:15 +0530566 if (gpio_is_valid(data->pdata->reset_gpio)) {
567 gpio_set_value_cansleep(data->pdata->reset_gpio, 0);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530568 msleep(data->pdata->hard_rst_dly);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530569 gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
570 }
Mohan Pallakaec271e42013-07-23 15:35:28 +0530571
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530572 msleep(data->pdata->soft_rst_dly);
Mohan Pallakaec271e42013-07-23 15:35:28 +0530573
Mohan Pallakaa2595072012-01-12 22:23:15 +0530574 enable_irq(data->client->irq);
575
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530576 data->suspended = false;
577
Mohan Pallakaa2595072012-01-12 22:23:15 +0530578 return 0;
579}
580
Mohan Pallakaa5d601b2013-05-10 15:34:44 +0530581#if defined(CONFIG_FB)
582static int fb_notifier_callback(struct notifier_block *self,
583 unsigned long event, void *data)
584{
585 struct fb_event *evdata = data;
586 int *blank;
587 struct ft5x06_ts_data *ft5x06_data =
588 container_of(self, struct ft5x06_ts_data, fb_notif);
589
590 if (evdata && evdata->data && event == FB_EVENT_BLANK &&
591 ft5x06_data && ft5x06_data->client) {
592 blank = evdata->data;
593 if (*blank == FB_BLANK_UNBLANK)
594 ft5x06_ts_resume(&ft5x06_data->client->dev);
595 else if (*blank == FB_BLANK_POWERDOWN)
596 ft5x06_ts_suspend(&ft5x06_data->client->dev);
597 }
598
599 return 0;
600}
601#elif defined(CONFIG_HAS_EARLYSUSPEND)
Mohan Pallakaa2595072012-01-12 22:23:15 +0530602static void ft5x06_ts_early_suspend(struct early_suspend *handler)
603{
604 struct ft5x06_ts_data *data = container_of(handler,
605 struct ft5x06_ts_data,
606 early_suspend);
607
608 ft5x06_ts_suspend(&data->client->dev);
609}
610
611static void ft5x06_ts_late_resume(struct early_suspend *handler)
612{
613 struct ft5x06_ts_data *data = container_of(handler,
614 struct ft5x06_ts_data,
615 early_suspend);
616
617 ft5x06_ts_resume(&data->client->dev);
618}
619#endif
620
621static const struct dev_pm_ops ft5x06_ts_pm_ops = {
Mohan Pallakaa5d601b2013-05-10 15:34:44 +0530622#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND))
Mohan Pallakaa2595072012-01-12 22:23:15 +0530623 .suspend = ft5x06_ts_suspend,
624 .resume = ft5x06_ts_resume,
625#endif
626};
627#endif
628
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530629static int ft5x06_auto_cal(struct i2c_client *client)
630{
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530631 struct ft5x06_ts_data *data = i2c_get_clientdata(client);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530632 u8 temp = 0, i;
633
634 /* set to factory mode */
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530635 msleep(2 * data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530636 ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530637 msleep(data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530638
639 /* start calibration */
640 ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_START);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530641 msleep(2 * data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530642 for (i = 0; i < FT_CAL_RETRY; i++) {
643 ft5x0x_read_reg(client, FT_REG_CAL, &temp);
644 /*return to normal mode, calibration finish */
645 if (((temp & FT_CAL_MASK) >> FT_4BIT_SHIFT) == FT_CAL_FIN)
646 break;
647 }
648
649 /*calibration OK */
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530650 msleep(2 * data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530651 ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530652 msleep(data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530653
654 /* store calibration data */
655 ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_STORE);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530656 msleep(2 * data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530657
658 /* set to normal mode */
659 ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_WORKMODE_VALUE);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530660 msleep(2 * data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530661
662 return 0;
663}
664
665static int ft5x06_fw_upgrade_start(struct i2c_client *client,
666 const u8 *data, u32 data_len)
667{
668 struct ft5x06_ts_data *ts_data = i2c_get_clientdata(client);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530669 struct fw_upgrade_info info = ts_data->pdata->info;
Mohan Pallakaec271e42013-07-23 15:35:28 +0530670 u8 reset_reg;
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530671 u8 w_buf[FT_MAX_WR_BUF] = {0}, r_buf[FT_MAX_RD_BUF] = {0};
672 u8 pkt_buf[FT_FW_PKT_LEN + FT_FW_PKT_META_LEN];
Bingzhe Cai49d56622013-10-28 19:30:27 +0800673 int i, j, temp;
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530674 u32 pkt_num, pkt_len;
Bingzhe Cai49d56622013-10-28 19:30:27 +0800675 u8 is_5336_new_bootloader = false;
676 u8 is_5336_fwsize_30 = false;
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530677 u8 fw_ecc;
678
Bingzhe Cai49d56622013-10-28 19:30:27 +0800679 /* determine firmware size */
680 if (*(data + data_len - FT_BLOADER_SIZE_OFF) == FT_BLOADER_NEW_SIZE)
681 is_5336_fwsize_30 = true;
682 else
683 is_5336_fwsize_30 = false;
684
Mohan Pallakaec271e42013-07-23 15:35:28 +0530685 for (i = 0, j = 0; i < FT_UPGRADE_LOOP; i++) {
Bingzhe Cai49d56622013-10-28 19:30:27 +0800686 msleep(FT_EARSE_DLY_MS);
Mohan Pallakaec271e42013-07-23 15:35:28 +0530687 /* reset - write 0xaa and 0x55 to reset register */
688 if (ts_data->family_id == FT6X06_ID)
689 reset_reg = FT_RST_CMD_REG2;
690 else
691 reset_reg = FT_RST_CMD_REG1;
692
693 ft5x0x_write_reg(client, reset_reg, FT_UPGRADE_AA);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530694 msleep(info.delay_aa);
695
Mohan Pallakaec271e42013-07-23 15:35:28 +0530696 ft5x0x_write_reg(client, reset_reg, FT_UPGRADE_55);
Bingzhe Cai49d56622013-10-28 19:30:27 +0800697 if (i <= (FT_UPGRADE_LOOP / 2))
698 msleep(info.delay_55 + i * 3);
699 else
700 msleep(info.delay_55 - (i - (FT_UPGRADE_LOOP / 2)) * 2);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530701
702 /* Enter upgrade mode */
703 w_buf[0] = FT_UPGRADE_55;
Bingzhe Cai49d56622013-10-28 19:30:27 +0800704 ft5x06_i2c_write(client, w_buf, 1);
705 usleep(FT_55_AA_DLY_NS);
706 w_buf[0] = FT_UPGRADE_AA;
707 ft5x06_i2c_write(client, w_buf, 1);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530708
709 /* check READ_ID */
710 msleep(info.delay_readid);
711 w_buf[0] = FT_READ_ID_REG;
712 w_buf[1] = 0x00;
713 w_buf[2] = 0x00;
714 w_buf[3] = 0x00;
715
716 ft5x06_i2c_read(client, w_buf, 4, r_buf, 2);
717
718 if (r_buf[0] != info.upgrade_id_1
719 || r_buf[1] != info.upgrade_id_2) {
720 dev_err(&client->dev, "Upgrade ID mismatch(%d)\n", i);
721 } else
722 break;
723 }
724
725 if (i >= FT_UPGRADE_LOOP) {
726 dev_err(&client->dev, "Abort upgrade\n");
727 return -EIO;
728 }
729
Bingzhe Cai49d56622013-10-28 19:30:27 +0800730 w_buf[0] = 0xcd;
731 ft5x06_i2c_read(client, w_buf, 1, r_buf, 1);
732
733 if (r_buf[0] <= 4)
734 is_5336_new_bootloader = FT_BLOADER_VERSION_LZ4;
735 else if (r_buf[0] == 7)
736 is_5336_new_bootloader = FT_BLOADER_VERSION_Z7;
737 else if (r_buf[0] >= 0x0f &&
738 ((ts_data->family_id == FT_FT5336_FAMILY_ID_0x11) ||
739 (ts_data->family_id == FT_FT5336_FAMILY_ID_0x12) ||
740 (ts_data->family_id == FT_FT5336_FAMILY_ID_0x13) ||
741 (ts_data->family_id == FT_FT5336_FAMILY_ID_0x14)))
742 is_5336_new_bootloader = FT_BLOADER_VERSION_GZF;
743 else
744 is_5336_new_bootloader = FT_BLOADER_VERSION_LZ4;
745
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530746 /* erase app and panel paramenter area */
747 w_buf[0] = FT_ERASE_APP_REG;
748 ft5x06_i2c_write(client, w_buf, 1);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530749 msleep(info.delay_erase_flash);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530750
Bingzhe Cai49d56622013-10-28 19:30:27 +0800751 if (is_5336_fwsize_30) {
752 w_buf[0] = FT_ERASE_PANEL_REG;
753 ft5x06_i2c_write(client, w_buf, 1);
754 }
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530755 msleep(FT_EARSE_DLY_MS);
756
757 /* program firmware */
Bingzhe Cai49d56622013-10-28 19:30:27 +0800758 if (is_5336_new_bootloader == FT_BLOADER_VERSION_LZ4
759 || is_5336_new_bootloader == FT_BLOADER_VERSION_Z7)
760 data_len = data_len - FT_DATA_LEN_OFF_OLD_FW;
761 else
762 data_len = data_len - FT_DATA_LEN_OFF_NEW_FW;
763
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530764 pkt_num = (data_len) / FT_FW_PKT_LEN;
765 pkt_len = FT_FW_PKT_LEN;
766 pkt_buf[0] = FT_FW_START_REG;
767 pkt_buf[1] = 0x00;
768 fw_ecc = 0;
769
770 for (i = 0; i < pkt_num; i++) {
771 temp = i * FT_FW_PKT_LEN;
772 pkt_buf[2] = (u8) (temp >> FT_8BIT_SHIFT);
773 pkt_buf[3] = (u8) temp;
774 pkt_buf[4] = (u8) (pkt_len >> FT_8BIT_SHIFT);
775 pkt_buf[5] = (u8) pkt_len;
776
777 for (j = 0; j < FT_FW_PKT_LEN; j++) {
778 pkt_buf[6 + j] = data[i * FT_FW_PKT_LEN + j];
779 fw_ecc ^= pkt_buf[6 + j];
780 }
781
782 ft5x06_i2c_write(client, pkt_buf,
783 FT_FW_PKT_LEN + FT_FW_PKT_META_LEN);
784 msleep(FT_FW_PKT_DLY_MS);
785 }
786
787 /* send remaining bytes */
788 if ((data_len) % FT_FW_PKT_LEN > 0) {
789 temp = pkt_num * FT_FW_PKT_LEN;
790 pkt_buf[2] = (u8) (temp >> FT_8BIT_SHIFT);
791 pkt_buf[3] = (u8) temp;
792 temp = (data_len) % FT_FW_PKT_LEN;
793 pkt_buf[4] = (u8) (temp >> FT_8BIT_SHIFT);
794 pkt_buf[5] = (u8) temp;
795
796 for (i = 0; i < temp; i++) {
797 pkt_buf[6 + i] = data[pkt_num * FT_FW_PKT_LEN + i];
798 fw_ecc ^= pkt_buf[6 + i];
799 }
800
801 ft5x06_i2c_write(client, pkt_buf, temp + FT_FW_PKT_META_LEN);
802 msleep(FT_FW_PKT_DLY_MS);
803 }
804
805 /* send the finishing packet */
Bingzhe Cai49d56622013-10-28 19:30:27 +0800806 if (is_5336_new_bootloader == FT_BLOADER_VERSION_LZ4 ||
807 is_5336_new_bootloader == FT_BLOADER_VERSION_Z7) {
808 for (i = 0; i < FT_FINISHING_PKT_LEN_OLD_FW; i++) {
809 if (is_5336_new_bootloader == FT_BLOADER_VERSION_Z7)
810 temp = FT_MAGIC_BLOADER_Z7 + i;
811 else if (is_5336_new_bootloader ==
812 FT_BLOADER_VERSION_LZ4)
813 temp = FT_MAGIC_BLOADER_LZ4 + i;
814 pkt_buf[2] = (u8)(temp >> 8);
815 pkt_buf[3] = (u8)temp;
816 temp = 1;
817 pkt_buf[4] = (u8)(temp >> 8);
818 pkt_buf[5] = (u8)temp;
819 pkt_buf[6] = data[data_len + i];
820 fw_ecc ^= pkt_buf[6];
821
822 ft5x06_i2c_write(client,
823 pkt_buf, temp + FT_FW_PKT_META_LEN);
824 msleep(FT_FW_PKT_DLY_MS);
825 }
826 } else if (is_5336_new_bootloader == FT_BLOADER_VERSION_GZF) {
827 for (i = 0; i < FT_FINISHING_PKT_LEN_NEW_FW; i++) {
828 if (is_5336_fwsize_30)
829 temp = FT_MAGIC_BLOADER_GZF_30 + i;
830 else
831 temp = FT_MAGIC_BLOADER_GZF + i;
832 pkt_buf[2] = (u8)(temp >> 8);
833 pkt_buf[3] = (u8)temp;
834 temp = 1;
835 pkt_buf[4] = (u8)(temp >> 8);
836 pkt_buf[5] = (u8)temp;
837 pkt_buf[6] = data[data_len + i];
838 fw_ecc ^= pkt_buf[6];
839
840 ft5x06_i2c_write(client,
841 pkt_buf, temp + FT_FW_PKT_META_LEN);
842 msleep(FT_FW_PKT_DLY_MS);
843
844 }
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530845 }
846
847 /* verify checksum */
848 w_buf[0] = FT_REG_ECC;
849 ft5x06_i2c_read(client, w_buf, 1, r_buf, 1);
850 if (r_buf[0] != fw_ecc) {
851 dev_err(&client->dev, "ECC error! dev_ecc=%02x fw_ecc=%02x\n",
852 r_buf[0], fw_ecc);
853 return -EIO;
854 }
855
856 /* reset */
857 w_buf[0] = FT_REG_RESET_FW;
858 ft5x06_i2c_write(client, w_buf, 1);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530859 msleep(ts_data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530860
Mohan Pallakaec271e42013-07-23 15:35:28 +0530861 dev_info(&client->dev, "Firmware upgrade successful\n");
862
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530863 return 0;
864}
865
866static int ft5x06_fw_upgrade(struct device *dev, bool force)
867{
868 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
869 const struct firmware *fw = NULL;
870 int rc;
Mohan Pallakaa348d752013-08-28 13:44:36 +0530871 u8 fw_file_maj, fw_file_min, fw_file_sub_min;
872 bool fw_upgrade = false;
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530873
874 rc = request_firmware(&fw, data->fw_name, dev);
875 if (rc < 0) {
876 dev_err(dev, "Request firmware failed - %s (%d)\n",
877 data->fw_name, rc);
878 return rc;
879 }
880
881 if (fw->size < FT_FW_MIN_SIZE || fw->size > FT_FW_MAX_SIZE) {
882 dev_err(dev, "Invalid firmware size (%d)\n", fw->size);
883 rc = -EIO;
884 goto rel_fw;
885 }
886
Mohan Pallakaa348d752013-08-28 13:44:36 +0530887 fw_file_maj = FT_FW_FILE_MAJ_VER(fw);
888 fw_file_min = FT_FW_FILE_MIN_VER(fw);
889 fw_file_sub_min = FT_FW_FILE_SUB_MIN_VER(fw);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530890
Mohan Pallakaa348d752013-08-28 13:44:36 +0530891 dev_info(dev, "Current firmware: %d.%d.%d", data->fw_ver[0],
892 data->fw_ver[1], data->fw_ver[2]);
893 dev_info(dev, "New firmware: %d.%d.%d", fw_file_maj,
894 fw_file_min, fw_file_sub_min);
895
896 if (force) {
897 fw_upgrade = true;
898 } else if (data->fw_ver[0] == fw_file_maj) {
899 if (data->fw_ver[1] < fw_file_min)
900 fw_upgrade = true;
901 else if (data->fw_ver[2] < fw_file_sub_min)
902 fw_upgrade = true;
903 else
904 dev_info(dev, "No need to upgrade\n");
905 } else
906 dev_info(dev, "Firmware versions do not match\n");
907
908 if (!fw_upgrade) {
909 dev_info(dev, "Exiting fw upgrade...\n");
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530910 rc = -EFAULT;
911 goto rel_fw;
912 }
913
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530914 /* start firmware upgrade */
915 if (FT_FW_CHECK(fw)) {
916 rc = ft5x06_fw_upgrade_start(data->client, fw->data, fw->size);
917 if (rc < 0)
Mohan Pallakaa348d752013-08-28 13:44:36 +0530918 dev_err(dev, "update failed (%d). try later...\n", rc);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530919 else if (data->pdata->info.auto_cal)
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530920 ft5x06_auto_cal(data->client);
921 } else {
922 dev_err(dev, "FW format error\n");
923 rc = -EIO;
924 }
925
Mohan Pallakaa348d752013-08-28 13:44:36 +0530926 ft5x06_update_fw_ver(data);
927
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530928 FT_STORE_TS_INFO(data->ts_info, data->family_id, data->pdata->name,
929 data->pdata->num_max_touches, data->pdata->group_id,
Mohan Pallakaa348d752013-08-28 13:44:36 +0530930 data->pdata->fw_vkey_support ? "yes" : "no",
931 data->pdata->fw_name, data->fw_ver[0],
932 data->fw_ver[1], data->fw_ver[2]);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530933rel_fw:
934 release_firmware(fw);
935 return rc;
936}
937
938static ssize_t ft5x06_update_fw_show(struct device *dev,
939 struct device_attribute *attr, char *buf)
940{
941 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
942 return snprintf(buf, 2, "%d\n", data->loading_fw);
943}
944
945static ssize_t ft5x06_update_fw_store(struct device *dev,
946 struct device_attribute *attr,
947 const char *buf, size_t size)
948{
949 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
950 unsigned long val;
951 int rc;
952
953 if (size > 2)
954 return -EINVAL;
955
956 rc = kstrtoul(buf, 10, &val);
957 if (rc != 0)
958 return rc;
959
Mohan Pallakaa348d752013-08-28 13:44:36 +0530960 if (data->suspended) {
961 dev_info(dev, "In suspend state, try again later...\n");
962 return size;
963 }
964
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530965 mutex_lock(&data->input_dev->mutex);
966 if (!data->loading_fw && val) {
967 data->loading_fw = true;
968 ft5x06_fw_upgrade(dev, false);
969 data->loading_fw = false;
970 }
971 mutex_unlock(&data->input_dev->mutex);
972
973 return size;
974}
975
976static DEVICE_ATTR(update_fw, 0664, ft5x06_update_fw_show,
977 ft5x06_update_fw_store);
978
979static ssize_t ft5x06_force_update_fw_store(struct device *dev,
980 struct device_attribute *attr,
981 const char *buf, size_t size)
982{
983 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
984 unsigned long val;
985 int rc;
986
987 if (size > 2)
988 return -EINVAL;
989
990 rc = kstrtoul(buf, 10, &val);
991 if (rc != 0)
992 return rc;
993
994 mutex_lock(&data->input_dev->mutex);
995 if (!data->loading_fw && val) {
996 data->loading_fw = true;
997 ft5x06_fw_upgrade(dev, true);
998 data->loading_fw = false;
999 }
1000 mutex_unlock(&data->input_dev->mutex);
1001
1002 return size;
1003}
1004
1005static DEVICE_ATTR(force_update_fw, 0664, ft5x06_update_fw_show,
1006 ft5x06_force_update_fw_store);
1007
1008static ssize_t ft5x06_fw_name_show(struct device *dev,
1009 struct device_attribute *attr, char *buf)
1010{
1011 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
1012 return snprintf(buf, FT_FW_NAME_MAX_LEN - 1, "%s\n", data->fw_name);
1013}
1014
1015static ssize_t ft5x06_fw_name_store(struct device *dev,
1016 struct device_attribute *attr,
1017 const char *buf, size_t size)
1018{
1019 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
1020
1021 if (size > FT_FW_NAME_MAX_LEN - 1)
1022 return -EINVAL;
1023
1024 strlcpy(data->fw_name, buf, size);
1025 if (data->fw_name[size-1] == '\n')
1026 data->fw_name[size-1] = 0;
1027
1028 return size;
1029}
1030
1031static DEVICE_ATTR(fw_name, 0664, ft5x06_fw_name_show, ft5x06_fw_name_store);
1032
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301033static bool ft5x06_debug_addr_is_valid(int addr)
1034{
1035 if (addr < 0 || addr > 0xFF) {
1036 pr_err("FT reg address is invalid: 0x%x\n", addr);
1037 return false;
1038 }
1039
1040 return true;
1041}
1042
1043static int ft5x06_debug_data_set(void *_data, u64 val)
1044{
1045 struct ft5x06_ts_data *data = _data;
1046
1047 mutex_lock(&data->input_dev->mutex);
1048
1049 if (ft5x06_debug_addr_is_valid(data->addr))
1050 dev_info(&data->client->dev,
1051 "Writing into FT registers not supported\n");
1052
1053 mutex_unlock(&data->input_dev->mutex);
1054
1055 return 0;
1056}
1057
1058static int ft5x06_debug_data_get(void *_data, u64 *val)
1059{
1060 struct ft5x06_ts_data *data = _data;
1061 int rc;
1062 u8 reg;
1063
1064 mutex_lock(&data->input_dev->mutex);
1065
1066 if (ft5x06_debug_addr_is_valid(data->addr)) {
1067 rc = ft5x0x_read_reg(data->client, data->addr, &reg);
1068 if (rc < 0)
1069 dev_err(&data->client->dev,
1070 "FT read register 0x%x failed (%d)\n",
1071 data->addr, rc);
1072 else
1073 *val = reg;
1074 }
1075
1076 mutex_unlock(&data->input_dev->mutex);
1077
1078 return 0;
1079}
1080
1081DEFINE_SIMPLE_ATTRIBUTE(debug_data_fops, ft5x06_debug_data_get,
1082 ft5x06_debug_data_set, "0x%02llX\n");
1083
1084static int ft5x06_debug_addr_set(void *_data, u64 val)
1085{
1086 struct ft5x06_ts_data *data = _data;
1087
1088 if (ft5x06_debug_addr_is_valid(val)) {
1089 mutex_lock(&data->input_dev->mutex);
1090 data->addr = val;
1091 mutex_unlock(&data->input_dev->mutex);
1092 }
1093
1094 return 0;
1095}
1096
1097static int ft5x06_debug_addr_get(void *_data, u64 *val)
1098{
1099 struct ft5x06_ts_data *data = _data;
1100
1101 mutex_lock(&data->input_dev->mutex);
1102
1103 if (ft5x06_debug_addr_is_valid(data->addr))
1104 *val = data->addr;
1105
1106 mutex_unlock(&data->input_dev->mutex);
1107
1108 return 0;
1109}
1110
1111DEFINE_SIMPLE_ATTRIBUTE(debug_addr_fops, ft5x06_debug_addr_get,
1112 ft5x06_debug_addr_set, "0x%02llX\n");
1113
1114static int ft5x06_debug_suspend_set(void *_data, u64 val)
1115{
1116 struct ft5x06_ts_data *data = _data;
1117
1118 mutex_lock(&data->input_dev->mutex);
1119
1120 if (val)
1121 ft5x06_ts_suspend(&data->client->dev);
1122 else
1123 ft5x06_ts_resume(&data->client->dev);
1124
1125 mutex_unlock(&data->input_dev->mutex);
1126
1127 return 0;
1128}
1129
1130static int ft5x06_debug_suspend_get(void *_data, u64 *val)
1131{
1132 struct ft5x06_ts_data *data = _data;
1133
1134 mutex_lock(&data->input_dev->mutex);
1135 *val = data->suspended;
1136 mutex_unlock(&data->input_dev->mutex);
1137
1138 return 0;
1139}
1140
1141DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, ft5x06_debug_suspend_get,
1142 ft5x06_debug_suspend_set, "%lld\n");
1143
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301144static int ft5x06_debug_dump_info(struct seq_file *m, void *v)
1145{
1146 struct ft5x06_ts_data *data = m->private;
1147
1148 seq_printf(m, "%s\n", data->ts_info);
1149
1150 return 0;
1151}
1152
1153static int debugfs_dump_info_open(struct inode *inode, struct file *file)
1154{
1155 return single_open(file, ft5x06_debug_dump_info, inode->i_private);
1156}
1157
1158static const struct file_operations debug_dump_info_fops = {
1159 .owner = THIS_MODULE,
1160 .open = debugfs_dump_info_open,
1161 .read = seq_read,
1162 .release = single_release,
1163};
1164
Mohan Pallaka3a138202013-05-09 16:30:00 +05301165#ifdef CONFIG_OF
1166static int ft5x06_get_dt_coords(struct device *dev, char *name,
1167 struct ft5x06_ts_platform_data *pdata)
1168{
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301169 u32 coords[FT_COORDS_ARR_SIZE];
Mohan Pallaka3a138202013-05-09 16:30:00 +05301170 struct property *prop;
1171 struct device_node *np = dev->of_node;
1172 int coords_size, rc;
1173
1174 prop = of_find_property(np, name, NULL);
1175 if (!prop)
1176 return -EINVAL;
1177 if (!prop->value)
1178 return -ENODATA;
1179
1180 coords_size = prop->length / sizeof(u32);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301181 if (coords_size != FT_COORDS_ARR_SIZE) {
Mohan Pallaka3a138202013-05-09 16:30:00 +05301182 dev_err(dev, "invalid %s\n", name);
1183 return -EINVAL;
1184 }
1185
1186 rc = of_property_read_u32_array(np, name, coords, coords_size);
1187 if (rc && (rc != -EINVAL)) {
1188 dev_err(dev, "Unable to read %s\n", name);
1189 return rc;
1190 }
1191
1192 if (!strcmp(name, "focaltech,panel-coords")) {
1193 pdata->panel_minx = coords[0];
1194 pdata->panel_miny = coords[1];
1195 pdata->panel_maxx = coords[2];
1196 pdata->panel_maxy = coords[3];
1197 } else if (!strcmp(name, "focaltech,display-coords")) {
1198 pdata->x_min = coords[0];
1199 pdata->y_min = coords[1];
1200 pdata->x_max = coords[2];
1201 pdata->y_max = coords[3];
1202 } else {
1203 dev_err(dev, "unsupported property %s\n", name);
1204 return -EINVAL;
1205 }
1206
1207 return 0;
1208}
1209
1210static int ft5x06_parse_dt(struct device *dev,
1211 struct ft5x06_ts_platform_data *pdata)
1212{
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301213 int rc;
Mohan Pallaka3a138202013-05-09 16:30:00 +05301214 struct device_node *np = dev->of_node;
1215 struct property *prop;
1216 u32 temp_val, num_buttons;
1217 u32 button_map[MAX_BUTTONS];
1218
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301219 pdata->name = "focaltech";
1220 rc = of_property_read_string(np, "focaltech,name", &pdata->name);
1221 if (rc && (rc != -EINVAL)) {
1222 dev_err(dev, "Unable to read name\n");
1223 return rc;
1224 }
1225
Mohan Pallaka3a138202013-05-09 16:30:00 +05301226 rc = ft5x06_get_dt_coords(dev, "focaltech,panel-coords", pdata);
1227 if (rc && (rc != -EINVAL))
1228 return rc;
1229
1230 rc = ft5x06_get_dt_coords(dev, "focaltech,display-coords", pdata);
1231 if (rc)
1232 return rc;
1233
1234 pdata->i2c_pull_up = of_property_read_bool(np,
1235 "focaltech,i2c-pull-up");
1236
1237 pdata->no_force_update = of_property_read_bool(np,
1238 "focaltech,no-force-update");
1239 /* reset, irq gpio info */
1240 pdata->reset_gpio = of_get_named_gpio_flags(np, "focaltech,reset-gpio",
1241 0, &pdata->reset_gpio_flags);
1242 if (pdata->reset_gpio < 0)
1243 return pdata->reset_gpio;
1244
1245 pdata->irq_gpio = of_get_named_gpio_flags(np, "focaltech,irq-gpio",
1246 0, &pdata->irq_gpio_flags);
1247 if (pdata->irq_gpio < 0)
1248 return pdata->irq_gpio;
1249
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301250 pdata->fw_name = "ft_fw.bin";
1251 rc = of_property_read_string(np, "focaltech,fw-name", &pdata->fw_name);
1252 if (rc && (rc != -EINVAL)) {
1253 dev_err(dev, "Unable to read fw name\n");
1254 return rc;
1255 }
1256
1257 rc = of_property_read_u32(np, "focaltech,group-id", &temp_val);
1258 if (!rc)
1259 pdata->group_id = temp_val;
1260 else
1261 return rc;
1262
1263 rc = of_property_read_u32(np, "focaltech,hard-reset-delay-ms",
1264 &temp_val);
1265 if (!rc)
1266 pdata->hard_rst_dly = temp_val;
1267 else
1268 return rc;
1269
1270 rc = of_property_read_u32(np, "focaltech,soft-reset-delay-ms",
1271 &temp_val);
1272 if (!rc)
1273 pdata->soft_rst_dly = temp_val;
1274 else
1275 return rc;
1276
1277 rc = of_property_read_u32(np, "focaltech,num-max-touches", &temp_val);
1278 if (!rc)
1279 pdata->num_max_touches = temp_val;
1280 else
1281 return rc;
1282
1283 rc = of_property_read_u32(np, "focaltech,fw-delay-aa-ms", &temp_val);
1284 if (rc && (rc != -EINVAL)) {
1285 dev_err(dev, "Unable to read fw delay aa\n");
1286 return rc;
1287 } else if (rc != -EINVAL)
1288 pdata->info.delay_aa = temp_val;
1289
1290 rc = of_property_read_u32(np, "focaltech,fw-delay-55-ms", &temp_val);
1291 if (rc && (rc != -EINVAL)) {
1292 dev_err(dev, "Unable to read fw delay 55\n");
1293 return rc;
1294 } else if (rc != -EINVAL)
1295 pdata->info.delay_55 = temp_val;
1296
1297 rc = of_property_read_u32(np, "focaltech,fw-upgrade-id1", &temp_val);
1298 if (rc && (rc != -EINVAL)) {
1299 dev_err(dev, "Unable to read fw upgrade id1\n");
1300 return rc;
1301 } else if (rc != -EINVAL)
1302 pdata->info.upgrade_id_1 = temp_val;
1303
1304 rc = of_property_read_u32(np, "focaltech,fw-upgrade-id2", &temp_val);
1305 if (rc && (rc != -EINVAL)) {
1306 dev_err(dev, "Unable to read fw upgrade id2\n");
1307 return rc;
1308 } else if (rc != -EINVAL)
1309 pdata->info.upgrade_id_2 = temp_val;
1310
1311 rc = of_property_read_u32(np, "focaltech,fw-delay-readid-ms",
1312 &temp_val);
1313 if (rc && (rc != -EINVAL)) {
1314 dev_err(dev, "Unable to read fw delay read id\n");
1315 return rc;
1316 } else if (rc != -EINVAL)
1317 pdata->info.delay_readid = temp_val;
1318
1319 rc = of_property_read_u32(np, "focaltech,fw-delay-era-flsh-ms",
1320 &temp_val);
1321 if (rc && (rc != -EINVAL)) {
1322 dev_err(dev, "Unable to read fw delay erase flash\n");
1323 return rc;
1324 } else if (rc != -EINVAL)
1325 pdata->info.delay_erase_flash = temp_val;
1326
1327 pdata->info.auto_cal = of_property_read_bool(np,
1328 "focaltech,fw-auto-cal");
1329
Mohan Pallakaa348d752013-08-28 13:44:36 +05301330 pdata->fw_vkey_support = of_property_read_bool(np,
1331 "focaltech,fw-vkey-support");
1332
Bingzhe Caid85a69d2013-10-09 22:15:31 +08001333 pdata->ignore_id_check = of_property_read_bool(np,
1334 "focaltech,ignore-id-check");
1335
Mohan Pallaka3a138202013-05-09 16:30:00 +05301336 rc = of_property_read_u32(np, "focaltech,family-id", &temp_val);
1337 if (!rc)
1338 pdata->family_id = temp_val;
1339 else
1340 return rc;
1341
1342 prop = of_find_property(np, "focaltech,button-map", NULL);
1343 if (prop) {
1344 num_buttons = prop->length / sizeof(temp_val);
1345 if (num_buttons > MAX_BUTTONS)
1346 return -EINVAL;
1347
1348 rc = of_property_read_u32_array(np,
1349 "focaltech,button-map", button_map,
1350 num_buttons);
1351 if (rc) {
1352 dev_err(dev, "Unable to read key codes\n");
1353 return rc;
1354 }
1355 }
1356
1357 return 0;
1358}
1359#else
1360static int ft5x06_parse_dt(struct device *dev,
1361 struct ft5x06_ts_platform_data *pdata)
1362{
1363 return -ENODEV;
1364}
1365#endif
1366
Mohan Pallakaa2595072012-01-12 22:23:15 +05301367static int ft5x06_ts_probe(struct i2c_client *client,
1368 const struct i2c_device_id *id)
1369{
Mohan Pallaka3a138202013-05-09 16:30:00 +05301370 struct ft5x06_ts_platform_data *pdata;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301371 struct ft5x06_ts_data *data;
1372 struct input_dev *input_dev;
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301373 struct dentry *temp;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301374 u8 reg_value;
1375 u8 reg_addr;
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301376 int err, len;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301377
Mohan Pallaka3a138202013-05-09 16:30:00 +05301378 if (client->dev.of_node) {
1379 pdata = devm_kzalloc(&client->dev,
1380 sizeof(struct ft5x06_ts_platform_data), GFP_KERNEL);
1381 if (!pdata) {
1382 dev_err(&client->dev, "Failed to allocate memory\n");
1383 return -ENOMEM;
1384 }
1385
1386 err = ft5x06_parse_dt(&client->dev, pdata);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301387 if (err) {
1388 dev_err(&client->dev, "DT parsing failed\n");
Mohan Pallaka3a138202013-05-09 16:30:00 +05301389 return err;
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301390 }
Mohan Pallaka3a138202013-05-09 16:30:00 +05301391 } else
1392 pdata = client->dev.platform_data;
1393
Mohan Pallakaa2595072012-01-12 22:23:15 +05301394 if (!pdata) {
1395 dev_err(&client->dev, "Invalid pdata\n");
1396 return -EINVAL;
1397 }
1398
1399 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
1400 dev_err(&client->dev, "I2C not supported\n");
1401 return -ENODEV;
1402 }
1403
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301404 data = devm_kzalloc(&client->dev,
1405 sizeof(struct ft5x06_ts_data), GFP_KERNEL);
1406 if (!data) {
1407 dev_err(&client->dev, "Not enough memory\n");
1408 return -ENOMEM;
1409 }
1410
1411 if (pdata->fw_name) {
1412 len = strlen(pdata->fw_name);
1413 if (len > FT_FW_NAME_MAX_LEN - 1) {
1414 dev_err(&client->dev, "Invalid firmware name\n");
1415 return -EINVAL;
1416 }
1417
1418 strlcpy(data->fw_name, pdata->fw_name, len + 1);
1419 }
1420
1421 data->tch_data_len = FT_TCH_LEN(pdata->num_max_touches);
1422 data->tch_data = devm_kzalloc(&client->dev,
1423 data->tch_data_len, GFP_KERNEL);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301424 if (!data) {
1425 dev_err(&client->dev, "Not enough memory\n");
1426 return -ENOMEM;
1427 }
1428
1429 input_dev = input_allocate_device();
1430 if (!input_dev) {
Mohan Pallakaa2595072012-01-12 22:23:15 +05301431 dev_err(&client->dev, "failed to allocate input device\n");
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301432 return -ENOMEM;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301433 }
1434
1435 data->input_dev = input_dev;
1436 data->client = client;
1437 data->pdata = pdata;
1438
1439 input_dev->name = "ft5x06_ts";
1440 input_dev->id.bustype = BUS_I2C;
1441 input_dev->dev.parent = &client->dev;
1442
1443 input_set_drvdata(input_dev, data);
1444 i2c_set_clientdata(client, data);
1445
1446 __set_bit(EV_KEY, input_dev->evbit);
1447 __set_bit(EV_ABS, input_dev->evbit);
1448 __set_bit(BTN_TOUCH, input_dev->keybit);
Amy Malochedd2703d2012-06-20 11:03:56 -07001449 __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301450
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301451 input_mt_init_slots(input_dev, pdata->num_max_touches);
Mohan Pallaka3a138202013-05-09 16:30:00 +05301452 input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min,
Mohan Pallakaa2595072012-01-12 22:23:15 +05301453 pdata->x_max, 0, 0);
Mohan Pallaka3a138202013-05-09 16:30:00 +05301454 input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min,
Mohan Pallakaa2595072012-01-12 22:23:15 +05301455 pdata->y_max, 0, 0);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301456
1457 err = input_register_device(input_dev);
1458 if (err) {
1459 dev_err(&client->dev, "Input device registration failed\n");
1460 goto free_inputdev;
1461 }
1462
1463 if (pdata->power_init) {
1464 err = pdata->power_init(true);
1465 if (err) {
1466 dev_err(&client->dev, "power init failed");
1467 goto unreg_inputdev;
1468 }
1469 } else {
1470 err = ft5x06_power_init(data, true);
1471 if (err) {
1472 dev_err(&client->dev, "power init failed");
1473 goto unreg_inputdev;
1474 }
1475 }
1476
1477 if (pdata->power_on) {
1478 err = pdata->power_on(true);
1479 if (err) {
1480 dev_err(&client->dev, "power on failed");
1481 goto pwr_deinit;
1482 }
1483 } else {
1484 err = ft5x06_power_on(data, true);
1485 if (err) {
1486 dev_err(&client->dev, "power on failed");
1487 goto pwr_deinit;
1488 }
1489 }
1490
1491 if (gpio_is_valid(pdata->irq_gpio)) {
1492 err = gpio_request(pdata->irq_gpio, "ft5x06_irq_gpio");
1493 if (err) {
1494 dev_err(&client->dev, "irq gpio request failed");
1495 goto pwr_off;
1496 }
1497 err = gpio_direction_input(pdata->irq_gpio);
1498 if (err) {
1499 dev_err(&client->dev,
1500 "set_direction for irq gpio failed\n");
1501 goto free_irq_gpio;
1502 }
1503 }
1504
1505 if (gpio_is_valid(pdata->reset_gpio)) {
1506 err = gpio_request(pdata->reset_gpio, "ft5x06_reset_gpio");
1507 if (err) {
1508 dev_err(&client->dev, "reset gpio request failed");
1509 goto free_irq_gpio;
1510 }
1511
1512 err = gpio_direction_output(pdata->reset_gpio, 0);
1513 if (err) {
1514 dev_err(&client->dev,
1515 "set_direction for reset gpio failed\n");
1516 goto free_reset_gpio;
1517 }
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301518 msleep(data->pdata->hard_rst_dly);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301519 gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
1520 }
1521
1522 /* make sure CTP already finish startup process */
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301523 msleep(data->pdata->soft_rst_dly);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301524
Mohan Pallaka3a138202013-05-09 16:30:00 +05301525 /* check the controller id */
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301526 reg_addr = FT_REG_ID;
Mohan Pallaka3a138202013-05-09 16:30:00 +05301527 err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
1528 if (err < 0) {
1529 dev_err(&client->dev, "version read failed");
Shantanu Jain3da65202013-07-08 19:11:07 +05301530 goto free_reset_gpio;
Mohan Pallaka3a138202013-05-09 16:30:00 +05301531 }
1532
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301533 dev_info(&client->dev, "Device ID = 0x%x\n", reg_value);
1534
Bingzhe Caid85a69d2013-10-09 22:15:31 +08001535 if ((pdata->family_id != reg_value) && (!pdata->ignore_id_check)) {
Mohan Pallaka3a138202013-05-09 16:30:00 +05301536 dev_err(&client->dev, "%s:Unsupported controller\n", __func__);
1537 goto free_reset_gpio;
1538 }
1539
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301540 data->family_id = reg_value;
1541
Mohan Pallakaa2595072012-01-12 22:23:15 +05301542 err = request_threaded_irq(client->irq, NULL,
1543 ft5x06_ts_interrupt, pdata->irqflags,
1544 client->dev.driver->name, data);
1545 if (err) {
1546 dev_err(&client->dev, "request irq failed\n");
1547 goto free_reset_gpio;
1548 }
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301549
1550 err = device_create_file(&client->dev, &dev_attr_fw_name);
1551 if (err) {
1552 dev_err(&client->dev, "sys file creation failed\n");
1553 goto irq_free;
1554 }
1555
1556 err = device_create_file(&client->dev, &dev_attr_update_fw);
1557 if (err) {
1558 dev_err(&client->dev, "sys file creation failed\n");
1559 goto free_fw_name_sys;
1560 }
1561
1562 err = device_create_file(&client->dev, &dev_attr_force_update_fw);
1563 if (err) {
1564 dev_err(&client->dev, "sys file creation failed\n");
1565 goto free_update_fw_sys;
1566 }
1567
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301568 data->dir = debugfs_create_dir(FT_DEBUG_DIR_NAME, NULL);
1569 if (data->dir == NULL || IS_ERR(data->dir)) {
1570 pr_err("debugfs_create_dir failed(%ld)\n", PTR_ERR(data->dir));
1571 err = PTR_ERR(data->dir);
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301572 goto free_force_update_fw_sys;
1573 }
1574
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301575 temp = debugfs_create_file("addr", S_IRUSR | S_IWUSR, data->dir, data,
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301576 &debug_addr_fops);
1577 if (temp == NULL || IS_ERR(temp)) {
1578 pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
1579 err = PTR_ERR(temp);
1580 goto free_debug_dir;
1581 }
1582
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301583 temp = debugfs_create_file("data", S_IRUSR | S_IWUSR, data->dir, data,
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301584 &debug_data_fops);
1585 if (temp == NULL || IS_ERR(temp)) {
1586 pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
1587 err = PTR_ERR(temp);
1588 goto free_debug_dir;
1589 }
1590
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301591 temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, data->dir,
1592 data, &debug_suspend_fops);
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301593 if (temp == NULL || IS_ERR(temp)) {
1594 pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
1595 err = PTR_ERR(temp);
1596 goto free_debug_dir;
1597 }
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301598
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301599 temp = debugfs_create_file("dump_info", S_IRUSR | S_IWUSR, data->dir,
1600 data, &debug_dump_info_fops);
1601 if (temp == NULL || IS_ERR(temp)) {
1602 pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
1603 err = PTR_ERR(temp);
1604 goto free_debug_dir;
1605 }
1606
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301607 data->ts_info = devm_kzalloc(&client->dev,
1608 FT_INFO_MAX_LEN, GFP_KERNEL);
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301609 if (!data->ts_info) {
1610 dev_err(&client->dev, "Not enough memory\n");
1611 goto free_debug_dir;
1612 }
1613
1614 /*get some register information */
1615 reg_addr = FT_REG_POINT_RATE;
1616 ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
1617 if (err < 0)
1618 dev_err(&client->dev, "report rate read failed");
1619
1620 dev_info(&client->dev, "report rate = %dHz\n", reg_value * 10);
1621
1622 reg_addr = FT_REG_THGROUP;
1623 err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
1624 if (err < 0)
1625 dev_err(&client->dev, "threshold read failed");
1626
1627 dev_dbg(&client->dev, "touch threshold = %d\n", reg_value * 4);
1628
Mohan Pallakaa348d752013-08-28 13:44:36 +05301629 ft5x06_update_fw_ver(data);
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301630
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301631 FT_STORE_TS_INFO(data->ts_info, data->family_id, data->pdata->name,
1632 data->pdata->num_max_touches, data->pdata->group_id,
Mohan Pallakaa348d752013-08-28 13:44:36 +05301633 data->pdata->fw_vkey_support ? "yes" : "no",
1634 data->pdata->fw_name, data->fw_ver[0],
1635 data->fw_ver[1], data->fw_ver[2]);
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301636
Mohan Pallakaa5d601b2013-05-10 15:34:44 +05301637#if defined(CONFIG_FB)
1638 data->fb_notif.notifier_call = fb_notifier_callback;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301639
Mohan Pallakaa5d601b2013-05-10 15:34:44 +05301640 err = fb_register_client(&data->fb_notif);
1641
1642 if (err)
1643 dev_err(&client->dev, "Unable to register fb_notifier: %d\n",
1644 err);
1645#elif defined(CONFIG_HAS_EARLYSUSPEND)
Mohan Pallakaa2595072012-01-12 22:23:15 +05301646 data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301647 FT_SUSPEND_LEVEL;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301648 data->early_suspend.suspend = ft5x06_ts_early_suspend;
1649 data->early_suspend.resume = ft5x06_ts_late_resume;
1650 register_early_suspend(&data->early_suspend);
1651#endif
1652
1653 return 0;
1654
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301655free_debug_dir:
1656 debugfs_remove_recursive(data->dir);
1657free_force_update_fw_sys:
1658 device_remove_file(&client->dev, &dev_attr_force_update_fw);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301659free_update_fw_sys:
1660 device_remove_file(&client->dev, &dev_attr_update_fw);
1661free_fw_name_sys:
1662 device_remove_file(&client->dev, &dev_attr_fw_name);
1663irq_free:
1664 free_irq(client->irq, data);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301665free_reset_gpio:
1666 if (gpio_is_valid(pdata->reset_gpio))
1667 gpio_free(pdata->reset_gpio);
1668free_irq_gpio:
1669 if (gpio_is_valid(pdata->irq_gpio))
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301670 gpio_free(pdata->irq_gpio);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301671pwr_off:
1672 if (pdata->power_on)
1673 pdata->power_on(false);
1674 else
1675 ft5x06_power_on(data, false);
1676pwr_deinit:
1677 if (pdata->power_init)
1678 pdata->power_init(false);
1679 else
1680 ft5x06_power_init(data, false);
1681unreg_inputdev:
1682 input_unregister_device(input_dev);
1683 input_dev = NULL;
1684free_inputdev:
1685 input_free_device(input_dev);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301686 return err;
1687}
1688
1689static int __devexit ft5x06_ts_remove(struct i2c_client *client)
1690{
1691 struct ft5x06_ts_data *data = i2c_get_clientdata(client);
1692
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301693 debugfs_remove_recursive(data->dir);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301694 device_remove_file(&client->dev, &dev_attr_force_update_fw);
1695 device_remove_file(&client->dev, &dev_attr_update_fw);
1696 device_remove_file(&client->dev, &dev_attr_fw_name);
1697
Mohan Pallakaa5d601b2013-05-10 15:34:44 +05301698#if defined(CONFIG_FB)
1699 if (fb_unregister_client(&data->fb_notif))
1700 dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
1701#elif defined(CONFIG_HAS_EARLYSUSPEND)
Mohan Pallakaa2595072012-01-12 22:23:15 +05301702 unregister_early_suspend(&data->early_suspend);
1703#endif
1704 free_irq(client->irq, data);
1705
1706 if (gpio_is_valid(data->pdata->reset_gpio))
1707 gpio_free(data->pdata->reset_gpio);
1708
1709 if (gpio_is_valid(data->pdata->irq_gpio))
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301710 gpio_free(data->pdata->irq_gpio);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301711
1712 if (data->pdata->power_on)
1713 data->pdata->power_on(false);
1714 else
1715 ft5x06_power_on(data, false);
1716
1717 if (data->pdata->power_init)
1718 data->pdata->power_init(false);
1719 else
1720 ft5x06_power_init(data, false);
1721
1722 input_unregister_device(data->input_dev);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301723
1724 return 0;
1725}
1726
1727static const struct i2c_device_id ft5x06_ts_id[] = {
1728 {"ft5x06_ts", 0},
1729 {},
1730};
1731
1732MODULE_DEVICE_TABLE(i2c, ft5x06_ts_id);
1733
Mohan Pallaka3a138202013-05-09 16:30:00 +05301734#ifdef CONFIG_OF
1735static struct of_device_id ft5x06_match_table[] = {
1736 { .compatible = "focaltech,5x06",},
1737 { },
1738};
1739#else
1740#define ft5x06_match_table NULL
1741#endif
1742
Mohan Pallakaa2595072012-01-12 22:23:15 +05301743static struct i2c_driver ft5x06_ts_driver = {
1744 .probe = ft5x06_ts_probe,
1745 .remove = __devexit_p(ft5x06_ts_remove),
1746 .driver = {
1747 .name = "ft5x06_ts",
1748 .owner = THIS_MODULE,
Mohan Pallaka3a138202013-05-09 16:30:00 +05301749 .of_match_table = ft5x06_match_table,
Mohan Pallakaa2595072012-01-12 22:23:15 +05301750#ifdef CONFIG_PM
1751 .pm = &ft5x06_ts_pm_ops,
1752#endif
1753 },
1754 .id_table = ft5x06_ts_id,
1755};
1756
1757static int __init ft5x06_ts_init(void)
1758{
1759 return i2c_add_driver(&ft5x06_ts_driver);
1760}
1761module_init(ft5x06_ts_init);
1762
1763static void __exit ft5x06_ts_exit(void)
1764{
1765 i2c_del_driver(&ft5x06_ts_driver);
1766}
1767module_exit(ft5x06_ts_exit);
1768
1769MODULE_DESCRIPTION("FocalTech ft5x06 TouchScreen driver");
1770MODULE_LICENSE("GPL v2");