blob: 2f9ea10c938b68ebcb172e14e21e8b6d958616ac [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 input_report_abs(ip_dev, ABS_MT_PRESSURE, 0);
340 }
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530341 }
342
343 if (update_input) {
344 input_mt_report_pointer_emulation(ip_dev, false);
345 input_sync(ip_dev);
346 }
Mohan Pallakaa2595072012-01-12 22:23:15 +0530347
348 return IRQ_HANDLED;
349}
350
351static int ft5x06_power_on(struct ft5x06_ts_data *data, bool on)
352{
353 int rc;
354
355 if (!on)
356 goto power_off;
357
358 rc = regulator_enable(data->vdd);
359 if (rc) {
360 dev_err(&data->client->dev,
361 "Regulator vdd enable failed rc=%d\n", rc);
362 return rc;
363 }
364
365 rc = regulator_enable(data->vcc_i2c);
366 if (rc) {
367 dev_err(&data->client->dev,
368 "Regulator vcc_i2c enable failed rc=%d\n", rc);
369 regulator_disable(data->vdd);
370 }
371
372 return rc;
373
374power_off:
375 rc = regulator_disable(data->vdd);
376 if (rc) {
377 dev_err(&data->client->dev,
378 "Regulator vdd disable failed rc=%d\n", rc);
379 return rc;
380 }
381
382 rc = regulator_disable(data->vcc_i2c);
383 if (rc) {
384 dev_err(&data->client->dev,
385 "Regulator vcc_i2c disable failed rc=%d\n", rc);
386 regulator_enable(data->vdd);
387 }
388
389 return rc;
390}
391
392static int ft5x06_power_init(struct ft5x06_ts_data *data, bool on)
393{
394 int rc;
395
396 if (!on)
397 goto pwr_deinit;
398
399 data->vdd = regulator_get(&data->client->dev, "vdd");
400 if (IS_ERR(data->vdd)) {
401 rc = PTR_ERR(data->vdd);
402 dev_err(&data->client->dev,
403 "Regulator get failed vdd rc=%d\n", rc);
404 return rc;
405 }
406
407 if (regulator_count_voltages(data->vdd) > 0) {
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530408 rc = regulator_set_voltage(data->vdd, FT_VTG_MIN_UV,
409 FT_VTG_MAX_UV);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530410 if (rc) {
411 dev_err(&data->client->dev,
412 "Regulator set_vtg failed vdd rc=%d\n", rc);
413 goto reg_vdd_put;
414 }
415 }
416
417 data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c");
418 if (IS_ERR(data->vcc_i2c)) {
419 rc = PTR_ERR(data->vcc_i2c);
420 dev_err(&data->client->dev,
421 "Regulator get failed vcc_i2c rc=%d\n", rc);
422 goto reg_vdd_set_vtg;
423 }
424
425 if (regulator_count_voltages(data->vcc_i2c) > 0) {
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530426 rc = regulator_set_voltage(data->vcc_i2c, FT_I2C_VTG_MIN_UV,
427 FT_I2C_VTG_MAX_UV);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530428 if (rc) {
429 dev_err(&data->client->dev,
430 "Regulator set_vtg failed vcc_i2c rc=%d\n", rc);
431 goto reg_vcc_i2c_put;
432 }
433 }
434
435 return 0;
436
437reg_vcc_i2c_put:
438 regulator_put(data->vcc_i2c);
439reg_vdd_set_vtg:
440 if (regulator_count_voltages(data->vdd) > 0)
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530441 regulator_set_voltage(data->vdd, 0, FT_VTG_MAX_UV);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530442reg_vdd_put:
443 regulator_put(data->vdd);
444 return rc;
445
446pwr_deinit:
447 if (regulator_count_voltages(data->vdd) > 0)
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530448 regulator_set_voltage(data->vdd, 0, FT_VTG_MAX_UV);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530449
450 regulator_put(data->vdd);
451
452 if (regulator_count_voltages(data->vcc_i2c) > 0)
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530453 regulator_set_voltage(data->vcc_i2c, 0, FT_I2C_VTG_MAX_UV);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530454
455 regulator_put(data->vcc_i2c);
456 return 0;
457}
458
459#ifdef CONFIG_PM
460static int ft5x06_ts_suspend(struct device *dev)
461{
462 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
Figo Wang63ad82b2013-06-28 19:49:49 +0800463 char txbuf[2], i;
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530464 int err;
Mohan Pallakaa2595072012-01-12 22:23:15 +0530465
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530466 if (data->loading_fw) {
467 dev_info(dev, "Firmware loading in process...\n");
468 return 0;
469 }
470
471 if (data->suspended) {
472 dev_info(dev, "Already in suspend state\n");
473 return 0;
474 }
475
Mohan Pallakaa2595072012-01-12 22:23:15 +0530476 disable_irq(data->client->irq);
477
Figo Wang63ad82b2013-06-28 19:49:49 +0800478 /* release all touches */
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530479 for (i = 0; i < data->pdata->num_max_touches; i++) {
Figo Wang63ad82b2013-06-28 19:49:49 +0800480 input_mt_slot(data->input_dev, i);
481 input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, 0);
482 }
483 input_report_key(data->input_dev, BTN_TOUCH, 0);
484 input_sync(data->input_dev);
485
Mohan Pallakaa2595072012-01-12 22:23:15 +0530486 if (gpio_is_valid(data->pdata->reset_gpio)) {
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530487 txbuf[0] = FT_REG_PMODE;
488 txbuf[1] = FT_PMODE_HIBERNATE;
Mohan Pallakaa2595072012-01-12 22:23:15 +0530489 ft5x06_i2c_write(data->client, txbuf, sizeof(txbuf));
490 }
491
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530492 if (data->pdata->power_on) {
493 err = data->pdata->power_on(false);
494 if (err) {
495 dev_err(dev, "power off failed");
496 goto pwr_off_fail;
497 }
498 } else {
499 err = ft5x06_power_on(data, false);
500 if (err) {
501 dev_err(dev, "power off failed");
502 goto pwr_off_fail;
503 }
504 }
505
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530506 data->suspended = true;
507
Mohan Pallakaa2595072012-01-12 22:23:15 +0530508 return 0;
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530509
510pwr_off_fail:
511 if (gpio_is_valid(data->pdata->reset_gpio)) {
512 gpio_set_value_cansleep(data->pdata->reset_gpio, 0);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530513 msleep(data->pdata->hard_rst_dly);
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530514 gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
515 }
516 enable_irq(data->client->irq);
517 return err;
Mohan Pallakaa2595072012-01-12 22:23:15 +0530518}
519
520static int ft5x06_ts_resume(struct device *dev)
521{
522 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530523 int err;
Mohan Pallakaa2595072012-01-12 22:23:15 +0530524
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530525 if (!data->suspended) {
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530526 dev_dbg(dev, "Already in awake state\n");
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530527 return 0;
528 }
529
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530530 if (data->pdata->power_on) {
531 err = data->pdata->power_on(true);
532 if (err) {
533 dev_err(dev, "power on failed");
534 return err;
535 }
536 } else {
537 err = ft5x06_power_on(data, true);
538 if (err) {
539 dev_err(dev, "power on failed");
540 return err;
541 }
542 }
543
Mohan Pallakaa2595072012-01-12 22:23:15 +0530544 if (gpio_is_valid(data->pdata->reset_gpio)) {
545 gpio_set_value_cansleep(data->pdata->reset_gpio, 0);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530546 msleep(data->pdata->hard_rst_dly);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530547 gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
548 }
Mohan Pallakaec271e42013-07-23 15:35:28 +0530549
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530550 msleep(data->pdata->soft_rst_dly);
Mohan Pallakaec271e42013-07-23 15:35:28 +0530551
Mohan Pallakaa2595072012-01-12 22:23:15 +0530552 enable_irq(data->client->irq);
553
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530554 data->suspended = false;
555
Mohan Pallakaa2595072012-01-12 22:23:15 +0530556 return 0;
557}
558
Mohan Pallakaa5d601b2013-05-10 15:34:44 +0530559#if defined(CONFIG_FB)
560static int fb_notifier_callback(struct notifier_block *self,
561 unsigned long event, void *data)
562{
563 struct fb_event *evdata = data;
564 int *blank;
565 struct ft5x06_ts_data *ft5x06_data =
566 container_of(self, struct ft5x06_ts_data, fb_notif);
567
568 if (evdata && evdata->data && event == FB_EVENT_BLANK &&
569 ft5x06_data && ft5x06_data->client) {
570 blank = evdata->data;
571 if (*blank == FB_BLANK_UNBLANK)
572 ft5x06_ts_resume(&ft5x06_data->client->dev);
573 else if (*blank == FB_BLANK_POWERDOWN)
574 ft5x06_ts_suspend(&ft5x06_data->client->dev);
575 }
576
577 return 0;
578}
579#elif defined(CONFIG_HAS_EARLYSUSPEND)
Mohan Pallakaa2595072012-01-12 22:23:15 +0530580static void ft5x06_ts_early_suspend(struct early_suspend *handler)
581{
582 struct ft5x06_ts_data *data = container_of(handler,
583 struct ft5x06_ts_data,
584 early_suspend);
585
586 ft5x06_ts_suspend(&data->client->dev);
587}
588
589static void ft5x06_ts_late_resume(struct early_suspend *handler)
590{
591 struct ft5x06_ts_data *data = container_of(handler,
592 struct ft5x06_ts_data,
593 early_suspend);
594
595 ft5x06_ts_resume(&data->client->dev);
596}
597#endif
598
599static const struct dev_pm_ops ft5x06_ts_pm_ops = {
Mohan Pallakaa5d601b2013-05-10 15:34:44 +0530600#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND))
Mohan Pallakaa2595072012-01-12 22:23:15 +0530601 .suspend = ft5x06_ts_suspend,
602 .resume = ft5x06_ts_resume,
603#endif
604};
605#endif
606
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530607static int ft5x06_auto_cal(struct i2c_client *client)
608{
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530609 struct ft5x06_ts_data *data = i2c_get_clientdata(client);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530610 u8 temp = 0, i;
611
612 /* set to factory mode */
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530613 msleep(2 * data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530614 ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530615 msleep(data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530616
617 /* start calibration */
618 ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_START);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530619 msleep(2 * data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530620 for (i = 0; i < FT_CAL_RETRY; i++) {
621 ft5x0x_read_reg(client, FT_REG_CAL, &temp);
622 /*return to normal mode, calibration finish */
623 if (((temp & FT_CAL_MASK) >> FT_4BIT_SHIFT) == FT_CAL_FIN)
624 break;
625 }
626
627 /*calibration OK */
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530628 msleep(2 * data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530629 ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530630 msleep(data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530631
632 /* store calibration data */
633 ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_STORE);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530634 msleep(2 * data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530635
636 /* set to normal mode */
637 ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_WORKMODE_VALUE);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530638 msleep(2 * data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530639
640 return 0;
641}
642
643static int ft5x06_fw_upgrade_start(struct i2c_client *client,
644 const u8 *data, u32 data_len)
645{
646 struct ft5x06_ts_data *ts_data = i2c_get_clientdata(client);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530647 struct fw_upgrade_info info = ts_data->pdata->info;
Mohan Pallakaec271e42013-07-23 15:35:28 +0530648 u8 reset_reg;
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530649 u8 w_buf[FT_MAX_WR_BUF] = {0}, r_buf[FT_MAX_RD_BUF] = {0};
650 u8 pkt_buf[FT_FW_PKT_LEN + FT_FW_PKT_META_LEN];
651 int rc, i, j, temp;
652 u32 pkt_num, pkt_len;
653 u8 fw_ecc;
654
Mohan Pallakaec271e42013-07-23 15:35:28 +0530655 for (i = 0, j = 0; i < FT_UPGRADE_LOOP; i++) {
656 /* reset - write 0xaa and 0x55 to reset register */
657 if (ts_data->family_id == FT6X06_ID)
658 reset_reg = FT_RST_CMD_REG2;
659 else
660 reset_reg = FT_RST_CMD_REG1;
661
662 ft5x0x_write_reg(client, reset_reg, FT_UPGRADE_AA);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530663 msleep(info.delay_aa);
664
Mohan Pallakaec271e42013-07-23 15:35:28 +0530665 ft5x0x_write_reg(client, reset_reg, FT_UPGRADE_55);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530666 msleep(info.delay_55);
667
668 /* Enter upgrade mode */
669 w_buf[0] = FT_UPGRADE_55;
670 w_buf[1] = FT_UPGRADE_AA;
671 do {
Mohan Pallakaec271e42013-07-23 15:35:28 +0530672 j++;
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530673 rc = ft5x06_i2c_write(client, w_buf, 2);
674 msleep(FT_RETRY_DLY);
Mohan Pallakaec271e42013-07-23 15:35:28 +0530675 } while (rc <= 0 && j < FT_MAX_TRIES);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530676
677 /* check READ_ID */
678 msleep(info.delay_readid);
679 w_buf[0] = FT_READ_ID_REG;
680 w_buf[1] = 0x00;
681 w_buf[2] = 0x00;
682 w_buf[3] = 0x00;
683
684 ft5x06_i2c_read(client, w_buf, 4, r_buf, 2);
685
686 if (r_buf[0] != info.upgrade_id_1
687 || r_buf[1] != info.upgrade_id_2) {
688 dev_err(&client->dev, "Upgrade ID mismatch(%d)\n", i);
689 } else
690 break;
691 }
692
693 if (i >= FT_UPGRADE_LOOP) {
694 dev_err(&client->dev, "Abort upgrade\n");
695 return -EIO;
696 }
697
698 /* erase app and panel paramenter area */
699 w_buf[0] = FT_ERASE_APP_REG;
700 ft5x06_i2c_write(client, w_buf, 1);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530701 msleep(info.delay_erase_flash);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530702
703 w_buf[0] = FT_ERASE_PANEL_REG;
704 ft5x06_i2c_write(client, w_buf, 1);
705 msleep(FT_EARSE_DLY_MS);
706
707 /* program firmware */
708 data_len = data_len - 8;
709 pkt_num = (data_len) / FT_FW_PKT_LEN;
710 pkt_len = FT_FW_PKT_LEN;
711 pkt_buf[0] = FT_FW_START_REG;
712 pkt_buf[1] = 0x00;
713 fw_ecc = 0;
714
715 for (i = 0; i < pkt_num; i++) {
716 temp = i * FT_FW_PKT_LEN;
717 pkt_buf[2] = (u8) (temp >> FT_8BIT_SHIFT);
718 pkt_buf[3] = (u8) temp;
719 pkt_buf[4] = (u8) (pkt_len >> FT_8BIT_SHIFT);
720 pkt_buf[5] = (u8) pkt_len;
721
722 for (j = 0; j < FT_FW_PKT_LEN; j++) {
723 pkt_buf[6 + j] = data[i * FT_FW_PKT_LEN + j];
724 fw_ecc ^= pkt_buf[6 + j];
725 }
726
727 ft5x06_i2c_write(client, pkt_buf,
728 FT_FW_PKT_LEN + FT_FW_PKT_META_LEN);
729 msleep(FT_FW_PKT_DLY_MS);
730 }
731
732 /* send remaining bytes */
733 if ((data_len) % FT_FW_PKT_LEN > 0) {
734 temp = pkt_num * FT_FW_PKT_LEN;
735 pkt_buf[2] = (u8) (temp >> FT_8BIT_SHIFT);
736 pkt_buf[3] = (u8) temp;
737 temp = (data_len) % FT_FW_PKT_LEN;
738 pkt_buf[4] = (u8) (temp >> FT_8BIT_SHIFT);
739 pkt_buf[5] = (u8) temp;
740
741 for (i = 0; i < temp; i++) {
742 pkt_buf[6 + i] = data[pkt_num * FT_FW_PKT_LEN + i];
743 fw_ecc ^= pkt_buf[6 + i];
744 }
745
746 ft5x06_i2c_write(client, pkt_buf, temp + FT_FW_PKT_META_LEN);
747 msleep(FT_FW_PKT_DLY_MS);
748 }
749
750 /* send the finishing packet */
751 for (i = 0; i < 6; i++) {
752 temp = FT_FW_LAST_PKT + i;
753 pkt_buf[2] = (u8) (temp >> 8);
754 pkt_buf[3] = (u8) temp;
755 temp = 1;
756 pkt_buf[4] = (u8) (temp >> 8);
757 pkt_buf[5] = (u8) temp;
758 pkt_buf[6] = data[data_len + i];
759 fw_ecc ^= pkt_buf[6];
760 ft5x06_i2c_write(client, pkt_buf, temp + FT_FW_PKT_META_LEN);
761 msleep(FT_FW_PKT_DLY_MS);
762 }
763
764 /* verify checksum */
765 w_buf[0] = FT_REG_ECC;
766 ft5x06_i2c_read(client, w_buf, 1, r_buf, 1);
767 if (r_buf[0] != fw_ecc) {
768 dev_err(&client->dev, "ECC error! dev_ecc=%02x fw_ecc=%02x\n",
769 r_buf[0], fw_ecc);
770 return -EIO;
771 }
772
773 /* reset */
774 w_buf[0] = FT_REG_RESET_FW;
775 ft5x06_i2c_write(client, w_buf, 1);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530776 msleep(ts_data->pdata->soft_rst_dly);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530777
Mohan Pallakaec271e42013-07-23 15:35:28 +0530778 dev_info(&client->dev, "Firmware upgrade successful\n");
779
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530780 return 0;
781}
782
783static int ft5x06_fw_upgrade(struct device *dev, bool force)
784{
785 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
786 const struct firmware *fw = NULL;
787 int rc;
Mohan Pallakaa348d752013-08-28 13:44:36 +0530788 u8 fw_file_maj, fw_file_min, fw_file_sub_min;
789 bool fw_upgrade = false;
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530790
791 rc = request_firmware(&fw, data->fw_name, dev);
792 if (rc < 0) {
793 dev_err(dev, "Request firmware failed - %s (%d)\n",
794 data->fw_name, rc);
795 return rc;
796 }
797
798 if (fw->size < FT_FW_MIN_SIZE || fw->size > FT_FW_MAX_SIZE) {
799 dev_err(dev, "Invalid firmware size (%d)\n", fw->size);
800 rc = -EIO;
801 goto rel_fw;
802 }
803
Mohan Pallakaa348d752013-08-28 13:44:36 +0530804 fw_file_maj = FT_FW_FILE_MAJ_VER(fw);
805 fw_file_min = FT_FW_FILE_MIN_VER(fw);
806 fw_file_sub_min = FT_FW_FILE_SUB_MIN_VER(fw);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530807
Mohan Pallakaa348d752013-08-28 13:44:36 +0530808 dev_info(dev, "Current firmware: %d.%d.%d", data->fw_ver[0],
809 data->fw_ver[1], data->fw_ver[2]);
810 dev_info(dev, "New firmware: %d.%d.%d", fw_file_maj,
811 fw_file_min, fw_file_sub_min);
812
813 if (force) {
814 fw_upgrade = true;
815 } else if (data->fw_ver[0] == fw_file_maj) {
816 if (data->fw_ver[1] < fw_file_min)
817 fw_upgrade = true;
818 else if (data->fw_ver[2] < fw_file_sub_min)
819 fw_upgrade = true;
820 else
821 dev_info(dev, "No need to upgrade\n");
822 } else
823 dev_info(dev, "Firmware versions do not match\n");
824
825 if (!fw_upgrade) {
826 dev_info(dev, "Exiting fw upgrade...\n");
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530827 rc = -EFAULT;
828 goto rel_fw;
829 }
830
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530831 /* start firmware upgrade */
832 if (FT_FW_CHECK(fw)) {
833 rc = ft5x06_fw_upgrade_start(data->client, fw->data, fw->size);
834 if (rc < 0)
Mohan Pallakaa348d752013-08-28 13:44:36 +0530835 dev_err(dev, "update failed (%d). try later...\n", rc);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530836 else if (data->pdata->info.auto_cal)
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530837 ft5x06_auto_cal(data->client);
838 } else {
839 dev_err(dev, "FW format error\n");
840 rc = -EIO;
841 }
842
Mohan Pallakaa348d752013-08-28 13:44:36 +0530843 ft5x06_update_fw_ver(data);
844
Mohan Pallaka9eb064d2013-08-13 16:11:47 +0530845 FT_STORE_TS_INFO(data->ts_info, data->family_id, data->pdata->name,
846 data->pdata->num_max_touches, data->pdata->group_id,
Mohan Pallakaa348d752013-08-28 13:44:36 +0530847 data->pdata->fw_vkey_support ? "yes" : "no",
848 data->pdata->fw_name, data->fw_ver[0],
849 data->fw_ver[1], data->fw_ver[2]);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530850rel_fw:
851 release_firmware(fw);
852 return rc;
853}
854
855static ssize_t ft5x06_update_fw_show(struct device *dev,
856 struct device_attribute *attr, char *buf)
857{
858 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
859 return snprintf(buf, 2, "%d\n", data->loading_fw);
860}
861
862static ssize_t ft5x06_update_fw_store(struct device *dev,
863 struct device_attribute *attr,
864 const char *buf, size_t size)
865{
866 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
867 unsigned long val;
868 int rc;
869
870 if (size > 2)
871 return -EINVAL;
872
873 rc = kstrtoul(buf, 10, &val);
874 if (rc != 0)
875 return rc;
876
Mohan Pallakaa348d752013-08-28 13:44:36 +0530877 if (data->suspended) {
878 dev_info(dev, "In suspend state, try again later...\n");
879 return size;
880 }
881
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530882 mutex_lock(&data->input_dev->mutex);
883 if (!data->loading_fw && val) {
884 data->loading_fw = true;
885 ft5x06_fw_upgrade(dev, false);
886 data->loading_fw = false;
887 }
888 mutex_unlock(&data->input_dev->mutex);
889
890 return size;
891}
892
893static DEVICE_ATTR(update_fw, 0664, ft5x06_update_fw_show,
894 ft5x06_update_fw_store);
895
896static ssize_t ft5x06_force_update_fw_store(struct device *dev,
897 struct device_attribute *attr,
898 const char *buf, size_t size)
899{
900 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
901 unsigned long val;
902 int rc;
903
904 if (size > 2)
905 return -EINVAL;
906
907 rc = kstrtoul(buf, 10, &val);
908 if (rc != 0)
909 return rc;
910
911 mutex_lock(&data->input_dev->mutex);
912 if (!data->loading_fw && val) {
913 data->loading_fw = true;
914 ft5x06_fw_upgrade(dev, true);
915 data->loading_fw = false;
916 }
917 mutex_unlock(&data->input_dev->mutex);
918
919 return size;
920}
921
922static DEVICE_ATTR(force_update_fw, 0664, ft5x06_update_fw_show,
923 ft5x06_force_update_fw_store);
924
925static ssize_t ft5x06_fw_name_show(struct device *dev,
926 struct device_attribute *attr, char *buf)
927{
928 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
929 return snprintf(buf, FT_FW_NAME_MAX_LEN - 1, "%s\n", data->fw_name);
930}
931
932static ssize_t ft5x06_fw_name_store(struct device *dev,
933 struct device_attribute *attr,
934 const char *buf, size_t size)
935{
936 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
937
938 if (size > FT_FW_NAME_MAX_LEN - 1)
939 return -EINVAL;
940
941 strlcpy(data->fw_name, buf, size);
942 if (data->fw_name[size-1] == '\n')
943 data->fw_name[size-1] = 0;
944
945 return size;
946}
947
948static DEVICE_ATTR(fw_name, 0664, ft5x06_fw_name_show, ft5x06_fw_name_store);
949
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530950static bool ft5x06_debug_addr_is_valid(int addr)
951{
952 if (addr < 0 || addr > 0xFF) {
953 pr_err("FT reg address is invalid: 0x%x\n", addr);
954 return false;
955 }
956
957 return true;
958}
959
960static int ft5x06_debug_data_set(void *_data, u64 val)
961{
962 struct ft5x06_ts_data *data = _data;
963
964 mutex_lock(&data->input_dev->mutex);
965
966 if (ft5x06_debug_addr_is_valid(data->addr))
967 dev_info(&data->client->dev,
968 "Writing into FT registers not supported\n");
969
970 mutex_unlock(&data->input_dev->mutex);
971
972 return 0;
973}
974
975static int ft5x06_debug_data_get(void *_data, u64 *val)
976{
977 struct ft5x06_ts_data *data = _data;
978 int rc;
979 u8 reg;
980
981 mutex_lock(&data->input_dev->mutex);
982
983 if (ft5x06_debug_addr_is_valid(data->addr)) {
984 rc = ft5x0x_read_reg(data->client, data->addr, &reg);
985 if (rc < 0)
986 dev_err(&data->client->dev,
987 "FT read register 0x%x failed (%d)\n",
988 data->addr, rc);
989 else
990 *val = reg;
991 }
992
993 mutex_unlock(&data->input_dev->mutex);
994
995 return 0;
996}
997
998DEFINE_SIMPLE_ATTRIBUTE(debug_data_fops, ft5x06_debug_data_get,
999 ft5x06_debug_data_set, "0x%02llX\n");
1000
1001static int ft5x06_debug_addr_set(void *_data, u64 val)
1002{
1003 struct ft5x06_ts_data *data = _data;
1004
1005 if (ft5x06_debug_addr_is_valid(val)) {
1006 mutex_lock(&data->input_dev->mutex);
1007 data->addr = val;
1008 mutex_unlock(&data->input_dev->mutex);
1009 }
1010
1011 return 0;
1012}
1013
1014static int ft5x06_debug_addr_get(void *_data, u64 *val)
1015{
1016 struct ft5x06_ts_data *data = _data;
1017
1018 mutex_lock(&data->input_dev->mutex);
1019
1020 if (ft5x06_debug_addr_is_valid(data->addr))
1021 *val = data->addr;
1022
1023 mutex_unlock(&data->input_dev->mutex);
1024
1025 return 0;
1026}
1027
1028DEFINE_SIMPLE_ATTRIBUTE(debug_addr_fops, ft5x06_debug_addr_get,
1029 ft5x06_debug_addr_set, "0x%02llX\n");
1030
1031static int ft5x06_debug_suspend_set(void *_data, u64 val)
1032{
1033 struct ft5x06_ts_data *data = _data;
1034
1035 mutex_lock(&data->input_dev->mutex);
1036
1037 if (val)
1038 ft5x06_ts_suspend(&data->client->dev);
1039 else
1040 ft5x06_ts_resume(&data->client->dev);
1041
1042 mutex_unlock(&data->input_dev->mutex);
1043
1044 return 0;
1045}
1046
1047static int ft5x06_debug_suspend_get(void *_data, u64 *val)
1048{
1049 struct ft5x06_ts_data *data = _data;
1050
1051 mutex_lock(&data->input_dev->mutex);
1052 *val = data->suspended;
1053 mutex_unlock(&data->input_dev->mutex);
1054
1055 return 0;
1056}
1057
1058DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, ft5x06_debug_suspend_get,
1059 ft5x06_debug_suspend_set, "%lld\n");
1060
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301061static int ft5x06_debug_dump_info(struct seq_file *m, void *v)
1062{
1063 struct ft5x06_ts_data *data = m->private;
1064
1065 seq_printf(m, "%s\n", data->ts_info);
1066
1067 return 0;
1068}
1069
1070static int debugfs_dump_info_open(struct inode *inode, struct file *file)
1071{
1072 return single_open(file, ft5x06_debug_dump_info, inode->i_private);
1073}
1074
1075static const struct file_operations debug_dump_info_fops = {
1076 .owner = THIS_MODULE,
1077 .open = debugfs_dump_info_open,
1078 .read = seq_read,
1079 .release = single_release,
1080};
1081
Mohan Pallaka3a138202013-05-09 16:30:00 +05301082#ifdef CONFIG_OF
1083static int ft5x06_get_dt_coords(struct device *dev, char *name,
1084 struct ft5x06_ts_platform_data *pdata)
1085{
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301086 u32 coords[FT_COORDS_ARR_SIZE];
Mohan Pallaka3a138202013-05-09 16:30:00 +05301087 struct property *prop;
1088 struct device_node *np = dev->of_node;
1089 int coords_size, rc;
1090
1091 prop = of_find_property(np, name, NULL);
1092 if (!prop)
1093 return -EINVAL;
1094 if (!prop->value)
1095 return -ENODATA;
1096
1097 coords_size = prop->length / sizeof(u32);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301098 if (coords_size != FT_COORDS_ARR_SIZE) {
Mohan Pallaka3a138202013-05-09 16:30:00 +05301099 dev_err(dev, "invalid %s\n", name);
1100 return -EINVAL;
1101 }
1102
1103 rc = of_property_read_u32_array(np, name, coords, coords_size);
1104 if (rc && (rc != -EINVAL)) {
1105 dev_err(dev, "Unable to read %s\n", name);
1106 return rc;
1107 }
1108
1109 if (!strcmp(name, "focaltech,panel-coords")) {
1110 pdata->panel_minx = coords[0];
1111 pdata->panel_miny = coords[1];
1112 pdata->panel_maxx = coords[2];
1113 pdata->panel_maxy = coords[3];
1114 } else if (!strcmp(name, "focaltech,display-coords")) {
1115 pdata->x_min = coords[0];
1116 pdata->y_min = coords[1];
1117 pdata->x_max = coords[2];
1118 pdata->y_max = coords[3];
1119 } else {
1120 dev_err(dev, "unsupported property %s\n", name);
1121 return -EINVAL;
1122 }
1123
1124 return 0;
1125}
1126
1127static int ft5x06_parse_dt(struct device *dev,
1128 struct ft5x06_ts_platform_data *pdata)
1129{
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301130 int rc;
Mohan Pallaka3a138202013-05-09 16:30:00 +05301131 struct device_node *np = dev->of_node;
1132 struct property *prop;
1133 u32 temp_val, num_buttons;
1134 u32 button_map[MAX_BUTTONS];
1135
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301136 pdata->name = "focaltech";
1137 rc = of_property_read_string(np, "focaltech,name", &pdata->name);
1138 if (rc && (rc != -EINVAL)) {
1139 dev_err(dev, "Unable to read name\n");
1140 return rc;
1141 }
1142
Mohan Pallaka3a138202013-05-09 16:30:00 +05301143 rc = ft5x06_get_dt_coords(dev, "focaltech,panel-coords", pdata);
1144 if (rc && (rc != -EINVAL))
1145 return rc;
1146
1147 rc = ft5x06_get_dt_coords(dev, "focaltech,display-coords", pdata);
1148 if (rc)
1149 return rc;
1150
1151 pdata->i2c_pull_up = of_property_read_bool(np,
1152 "focaltech,i2c-pull-up");
1153
1154 pdata->no_force_update = of_property_read_bool(np,
1155 "focaltech,no-force-update");
1156 /* reset, irq gpio info */
1157 pdata->reset_gpio = of_get_named_gpio_flags(np, "focaltech,reset-gpio",
1158 0, &pdata->reset_gpio_flags);
1159 if (pdata->reset_gpio < 0)
1160 return pdata->reset_gpio;
1161
1162 pdata->irq_gpio = of_get_named_gpio_flags(np, "focaltech,irq-gpio",
1163 0, &pdata->irq_gpio_flags);
1164 if (pdata->irq_gpio < 0)
1165 return pdata->irq_gpio;
1166
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301167 pdata->fw_name = "ft_fw.bin";
1168 rc = of_property_read_string(np, "focaltech,fw-name", &pdata->fw_name);
1169 if (rc && (rc != -EINVAL)) {
1170 dev_err(dev, "Unable to read fw name\n");
1171 return rc;
1172 }
1173
1174 rc = of_property_read_u32(np, "focaltech,group-id", &temp_val);
1175 if (!rc)
1176 pdata->group_id = temp_val;
1177 else
1178 return rc;
1179
1180 rc = of_property_read_u32(np, "focaltech,hard-reset-delay-ms",
1181 &temp_val);
1182 if (!rc)
1183 pdata->hard_rst_dly = temp_val;
1184 else
1185 return rc;
1186
1187 rc = of_property_read_u32(np, "focaltech,soft-reset-delay-ms",
1188 &temp_val);
1189 if (!rc)
1190 pdata->soft_rst_dly = temp_val;
1191 else
1192 return rc;
1193
1194 rc = of_property_read_u32(np, "focaltech,num-max-touches", &temp_val);
1195 if (!rc)
1196 pdata->num_max_touches = temp_val;
1197 else
1198 return rc;
1199
1200 rc = of_property_read_u32(np, "focaltech,fw-delay-aa-ms", &temp_val);
1201 if (rc && (rc != -EINVAL)) {
1202 dev_err(dev, "Unable to read fw delay aa\n");
1203 return rc;
1204 } else if (rc != -EINVAL)
1205 pdata->info.delay_aa = temp_val;
1206
1207 rc = of_property_read_u32(np, "focaltech,fw-delay-55-ms", &temp_val);
1208 if (rc && (rc != -EINVAL)) {
1209 dev_err(dev, "Unable to read fw delay 55\n");
1210 return rc;
1211 } else if (rc != -EINVAL)
1212 pdata->info.delay_55 = temp_val;
1213
1214 rc = of_property_read_u32(np, "focaltech,fw-upgrade-id1", &temp_val);
1215 if (rc && (rc != -EINVAL)) {
1216 dev_err(dev, "Unable to read fw upgrade id1\n");
1217 return rc;
1218 } else if (rc != -EINVAL)
1219 pdata->info.upgrade_id_1 = temp_val;
1220
1221 rc = of_property_read_u32(np, "focaltech,fw-upgrade-id2", &temp_val);
1222 if (rc && (rc != -EINVAL)) {
1223 dev_err(dev, "Unable to read fw upgrade id2\n");
1224 return rc;
1225 } else if (rc != -EINVAL)
1226 pdata->info.upgrade_id_2 = temp_val;
1227
1228 rc = of_property_read_u32(np, "focaltech,fw-delay-readid-ms",
1229 &temp_val);
1230 if (rc && (rc != -EINVAL)) {
1231 dev_err(dev, "Unable to read fw delay read id\n");
1232 return rc;
1233 } else if (rc != -EINVAL)
1234 pdata->info.delay_readid = temp_val;
1235
1236 rc = of_property_read_u32(np, "focaltech,fw-delay-era-flsh-ms",
1237 &temp_val);
1238 if (rc && (rc != -EINVAL)) {
1239 dev_err(dev, "Unable to read fw delay erase flash\n");
1240 return rc;
1241 } else if (rc != -EINVAL)
1242 pdata->info.delay_erase_flash = temp_val;
1243
1244 pdata->info.auto_cal = of_property_read_bool(np,
1245 "focaltech,fw-auto-cal");
1246
Mohan Pallakaa348d752013-08-28 13:44:36 +05301247 pdata->fw_vkey_support = of_property_read_bool(np,
1248 "focaltech,fw-vkey-support");
1249
Mohan Pallaka3a138202013-05-09 16:30:00 +05301250 rc = of_property_read_u32(np, "focaltech,family-id", &temp_val);
1251 if (!rc)
1252 pdata->family_id = temp_val;
1253 else
1254 return rc;
1255
1256 prop = of_find_property(np, "focaltech,button-map", NULL);
1257 if (prop) {
1258 num_buttons = prop->length / sizeof(temp_val);
1259 if (num_buttons > MAX_BUTTONS)
1260 return -EINVAL;
1261
1262 rc = of_property_read_u32_array(np,
1263 "focaltech,button-map", button_map,
1264 num_buttons);
1265 if (rc) {
1266 dev_err(dev, "Unable to read key codes\n");
1267 return rc;
1268 }
1269 }
1270
1271 return 0;
1272}
1273#else
1274static int ft5x06_parse_dt(struct device *dev,
1275 struct ft5x06_ts_platform_data *pdata)
1276{
1277 return -ENODEV;
1278}
1279#endif
1280
Mohan Pallakaa2595072012-01-12 22:23:15 +05301281static int ft5x06_ts_probe(struct i2c_client *client,
1282 const struct i2c_device_id *id)
1283{
Mohan Pallaka3a138202013-05-09 16:30:00 +05301284 struct ft5x06_ts_platform_data *pdata;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301285 struct ft5x06_ts_data *data;
1286 struct input_dev *input_dev;
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301287 struct dentry *temp;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301288 u8 reg_value;
1289 u8 reg_addr;
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301290 int err, len;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301291
Mohan Pallaka3a138202013-05-09 16:30:00 +05301292 if (client->dev.of_node) {
1293 pdata = devm_kzalloc(&client->dev,
1294 sizeof(struct ft5x06_ts_platform_data), GFP_KERNEL);
1295 if (!pdata) {
1296 dev_err(&client->dev, "Failed to allocate memory\n");
1297 return -ENOMEM;
1298 }
1299
1300 err = ft5x06_parse_dt(&client->dev, pdata);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301301 if (err) {
1302 dev_err(&client->dev, "DT parsing failed\n");
Mohan Pallaka3a138202013-05-09 16:30:00 +05301303 return err;
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301304 }
Mohan Pallaka3a138202013-05-09 16:30:00 +05301305 } else
1306 pdata = client->dev.platform_data;
1307
Mohan Pallakaa2595072012-01-12 22:23:15 +05301308 if (!pdata) {
1309 dev_err(&client->dev, "Invalid pdata\n");
1310 return -EINVAL;
1311 }
1312
1313 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
1314 dev_err(&client->dev, "I2C not supported\n");
1315 return -ENODEV;
1316 }
1317
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301318 data = devm_kzalloc(&client->dev,
1319 sizeof(struct ft5x06_ts_data), GFP_KERNEL);
1320 if (!data) {
1321 dev_err(&client->dev, "Not enough memory\n");
1322 return -ENOMEM;
1323 }
1324
1325 if (pdata->fw_name) {
1326 len = strlen(pdata->fw_name);
1327 if (len > FT_FW_NAME_MAX_LEN - 1) {
1328 dev_err(&client->dev, "Invalid firmware name\n");
1329 return -EINVAL;
1330 }
1331
1332 strlcpy(data->fw_name, pdata->fw_name, len + 1);
1333 }
1334
1335 data->tch_data_len = FT_TCH_LEN(pdata->num_max_touches);
1336 data->tch_data = devm_kzalloc(&client->dev,
1337 data->tch_data_len, GFP_KERNEL);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301338 if (!data) {
1339 dev_err(&client->dev, "Not enough memory\n");
1340 return -ENOMEM;
1341 }
1342
1343 input_dev = input_allocate_device();
1344 if (!input_dev) {
Mohan Pallakaa2595072012-01-12 22:23:15 +05301345 dev_err(&client->dev, "failed to allocate input device\n");
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301346 return -ENOMEM;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301347 }
1348
1349 data->input_dev = input_dev;
1350 data->client = client;
1351 data->pdata = pdata;
1352
1353 input_dev->name = "ft5x06_ts";
1354 input_dev->id.bustype = BUS_I2C;
1355 input_dev->dev.parent = &client->dev;
1356
1357 input_set_drvdata(input_dev, data);
1358 i2c_set_clientdata(client, data);
1359
1360 __set_bit(EV_KEY, input_dev->evbit);
1361 __set_bit(EV_ABS, input_dev->evbit);
1362 __set_bit(BTN_TOUCH, input_dev->keybit);
Amy Malochedd2703d2012-06-20 11:03:56 -07001363 __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301364
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301365 input_mt_init_slots(input_dev, pdata->num_max_touches);
Mohan Pallaka3a138202013-05-09 16:30:00 +05301366 input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min,
Mohan Pallakaa2595072012-01-12 22:23:15 +05301367 pdata->x_max, 0, 0);
Mohan Pallaka3a138202013-05-09 16:30:00 +05301368 input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min,
Mohan Pallakaa2595072012-01-12 22:23:15 +05301369 pdata->y_max, 0, 0);
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301370 input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, FT_PRESS, 0, 0);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301371
1372 err = input_register_device(input_dev);
1373 if (err) {
1374 dev_err(&client->dev, "Input device registration failed\n");
1375 goto free_inputdev;
1376 }
1377
1378 if (pdata->power_init) {
1379 err = pdata->power_init(true);
1380 if (err) {
1381 dev_err(&client->dev, "power init failed");
1382 goto unreg_inputdev;
1383 }
1384 } else {
1385 err = ft5x06_power_init(data, true);
1386 if (err) {
1387 dev_err(&client->dev, "power init failed");
1388 goto unreg_inputdev;
1389 }
1390 }
1391
1392 if (pdata->power_on) {
1393 err = pdata->power_on(true);
1394 if (err) {
1395 dev_err(&client->dev, "power on failed");
1396 goto pwr_deinit;
1397 }
1398 } else {
1399 err = ft5x06_power_on(data, true);
1400 if (err) {
1401 dev_err(&client->dev, "power on failed");
1402 goto pwr_deinit;
1403 }
1404 }
1405
1406 if (gpio_is_valid(pdata->irq_gpio)) {
1407 err = gpio_request(pdata->irq_gpio, "ft5x06_irq_gpio");
1408 if (err) {
1409 dev_err(&client->dev, "irq gpio request failed");
1410 goto pwr_off;
1411 }
1412 err = gpio_direction_input(pdata->irq_gpio);
1413 if (err) {
1414 dev_err(&client->dev,
1415 "set_direction for irq gpio failed\n");
1416 goto free_irq_gpio;
1417 }
1418 }
1419
1420 if (gpio_is_valid(pdata->reset_gpio)) {
1421 err = gpio_request(pdata->reset_gpio, "ft5x06_reset_gpio");
1422 if (err) {
1423 dev_err(&client->dev, "reset gpio request failed");
1424 goto free_irq_gpio;
1425 }
1426
1427 err = gpio_direction_output(pdata->reset_gpio, 0);
1428 if (err) {
1429 dev_err(&client->dev,
1430 "set_direction for reset gpio failed\n");
1431 goto free_reset_gpio;
1432 }
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301433 msleep(data->pdata->hard_rst_dly);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301434 gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
1435 }
1436
1437 /* make sure CTP already finish startup process */
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301438 msleep(data->pdata->soft_rst_dly);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301439
Mohan Pallaka3a138202013-05-09 16:30:00 +05301440 /* check the controller id */
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301441 reg_addr = FT_REG_ID;
Mohan Pallaka3a138202013-05-09 16:30:00 +05301442 err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
1443 if (err < 0) {
1444 dev_err(&client->dev, "version read failed");
Shantanu Jain3da65202013-07-08 19:11:07 +05301445 goto free_reset_gpio;
Mohan Pallaka3a138202013-05-09 16:30:00 +05301446 }
1447
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301448 dev_info(&client->dev, "Device ID = 0x%x\n", reg_value);
1449
Mohan Pallaka3a138202013-05-09 16:30:00 +05301450 if (pdata->family_id != reg_value) {
1451 dev_err(&client->dev, "%s:Unsupported controller\n", __func__);
1452 goto free_reset_gpio;
1453 }
1454
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301455 data->family_id = reg_value;
1456
Mohan Pallakaa2595072012-01-12 22:23:15 +05301457 err = request_threaded_irq(client->irq, NULL,
1458 ft5x06_ts_interrupt, pdata->irqflags,
1459 client->dev.driver->name, data);
1460 if (err) {
1461 dev_err(&client->dev, "request irq failed\n");
1462 goto free_reset_gpio;
1463 }
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301464
1465 err = device_create_file(&client->dev, &dev_attr_fw_name);
1466 if (err) {
1467 dev_err(&client->dev, "sys file creation failed\n");
1468 goto irq_free;
1469 }
1470
1471 err = device_create_file(&client->dev, &dev_attr_update_fw);
1472 if (err) {
1473 dev_err(&client->dev, "sys file creation failed\n");
1474 goto free_fw_name_sys;
1475 }
1476
1477 err = device_create_file(&client->dev, &dev_attr_force_update_fw);
1478 if (err) {
1479 dev_err(&client->dev, "sys file creation failed\n");
1480 goto free_update_fw_sys;
1481 }
1482
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301483 data->dir = debugfs_create_dir(FT_DEBUG_DIR_NAME, NULL);
1484 if (data->dir == NULL || IS_ERR(data->dir)) {
1485 pr_err("debugfs_create_dir failed(%ld)\n", PTR_ERR(data->dir));
1486 err = PTR_ERR(data->dir);
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301487 goto free_force_update_fw_sys;
1488 }
1489
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301490 temp = debugfs_create_file("addr", S_IRUSR | S_IWUSR, data->dir, data,
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301491 &debug_addr_fops);
1492 if (temp == NULL || IS_ERR(temp)) {
1493 pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
1494 err = PTR_ERR(temp);
1495 goto free_debug_dir;
1496 }
1497
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301498 temp = debugfs_create_file("data", S_IRUSR | S_IWUSR, data->dir, data,
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301499 &debug_data_fops);
1500 if (temp == NULL || IS_ERR(temp)) {
1501 pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
1502 err = PTR_ERR(temp);
1503 goto free_debug_dir;
1504 }
1505
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301506 temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, data->dir,
1507 data, &debug_suspend_fops);
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301508 if (temp == NULL || IS_ERR(temp)) {
1509 pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
1510 err = PTR_ERR(temp);
1511 goto free_debug_dir;
1512 }
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301513
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301514 temp = debugfs_create_file("dump_info", S_IRUSR | S_IWUSR, data->dir,
1515 data, &debug_dump_info_fops);
1516 if (temp == NULL || IS_ERR(temp)) {
1517 pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
1518 err = PTR_ERR(temp);
1519 goto free_debug_dir;
1520 }
1521
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301522 data->ts_info = devm_kzalloc(&client->dev,
1523 FT_INFO_MAX_LEN, GFP_KERNEL);
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301524 if (!data->ts_info) {
1525 dev_err(&client->dev, "Not enough memory\n");
1526 goto free_debug_dir;
1527 }
1528
1529 /*get some register information */
1530 reg_addr = FT_REG_POINT_RATE;
1531 ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
1532 if (err < 0)
1533 dev_err(&client->dev, "report rate read failed");
1534
1535 dev_info(&client->dev, "report rate = %dHz\n", reg_value * 10);
1536
1537 reg_addr = FT_REG_THGROUP;
1538 err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
1539 if (err < 0)
1540 dev_err(&client->dev, "threshold read failed");
1541
1542 dev_dbg(&client->dev, "touch threshold = %d\n", reg_value * 4);
1543
Mohan Pallakaa348d752013-08-28 13:44:36 +05301544 ft5x06_update_fw_ver(data);
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301545
Mohan Pallaka9eb064d2013-08-13 16:11:47 +05301546 FT_STORE_TS_INFO(data->ts_info, data->family_id, data->pdata->name,
1547 data->pdata->num_max_touches, data->pdata->group_id,
Mohan Pallakaa348d752013-08-28 13:44:36 +05301548 data->pdata->fw_vkey_support ? "yes" : "no",
1549 data->pdata->fw_name, data->fw_ver[0],
1550 data->fw_ver[1], data->fw_ver[2]);
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301551
Mohan Pallakaa5d601b2013-05-10 15:34:44 +05301552#if defined(CONFIG_FB)
1553 data->fb_notif.notifier_call = fb_notifier_callback;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301554
Mohan Pallakaa5d601b2013-05-10 15:34:44 +05301555 err = fb_register_client(&data->fb_notif);
1556
1557 if (err)
1558 dev_err(&client->dev, "Unable to register fb_notifier: %d\n",
1559 err);
1560#elif defined(CONFIG_HAS_EARLYSUSPEND)
Mohan Pallakaa2595072012-01-12 22:23:15 +05301561 data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301562 FT_SUSPEND_LEVEL;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301563 data->early_suspend.suspend = ft5x06_ts_early_suspend;
1564 data->early_suspend.resume = ft5x06_ts_late_resume;
1565 register_early_suspend(&data->early_suspend);
1566#endif
1567
1568 return 0;
1569
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301570free_debug_dir:
1571 debugfs_remove_recursive(data->dir);
1572free_force_update_fw_sys:
1573 device_remove_file(&client->dev, &dev_attr_force_update_fw);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301574free_update_fw_sys:
1575 device_remove_file(&client->dev, &dev_attr_update_fw);
1576free_fw_name_sys:
1577 device_remove_file(&client->dev, &dev_attr_fw_name);
1578irq_free:
1579 free_irq(client->irq, data);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301580free_reset_gpio:
1581 if (gpio_is_valid(pdata->reset_gpio))
1582 gpio_free(pdata->reset_gpio);
1583free_irq_gpio:
1584 if (gpio_is_valid(pdata->irq_gpio))
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301585 gpio_free(pdata->irq_gpio);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301586pwr_off:
1587 if (pdata->power_on)
1588 pdata->power_on(false);
1589 else
1590 ft5x06_power_on(data, false);
1591pwr_deinit:
1592 if (pdata->power_init)
1593 pdata->power_init(false);
1594 else
1595 ft5x06_power_init(data, false);
1596unreg_inputdev:
1597 input_unregister_device(input_dev);
1598 input_dev = NULL;
1599free_inputdev:
1600 input_free_device(input_dev);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301601 return err;
1602}
1603
1604static int __devexit ft5x06_ts_remove(struct i2c_client *client)
1605{
1606 struct ft5x06_ts_data *data = i2c_get_clientdata(client);
1607
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301608 debugfs_remove_recursive(data->dir);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301609 device_remove_file(&client->dev, &dev_attr_force_update_fw);
1610 device_remove_file(&client->dev, &dev_attr_update_fw);
1611 device_remove_file(&client->dev, &dev_attr_fw_name);
1612
Mohan Pallakaa5d601b2013-05-10 15:34:44 +05301613#if defined(CONFIG_FB)
1614 if (fb_unregister_client(&data->fb_notif))
1615 dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
1616#elif defined(CONFIG_HAS_EARLYSUSPEND)
Mohan Pallakaa2595072012-01-12 22:23:15 +05301617 unregister_early_suspend(&data->early_suspend);
1618#endif
1619 free_irq(client->irq, data);
1620
1621 if (gpio_is_valid(data->pdata->reset_gpio))
1622 gpio_free(data->pdata->reset_gpio);
1623
1624 if (gpio_is_valid(data->pdata->irq_gpio))
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301625 gpio_free(data->pdata->irq_gpio);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301626
1627 if (data->pdata->power_on)
1628 data->pdata->power_on(false);
1629 else
1630 ft5x06_power_on(data, false);
1631
1632 if (data->pdata->power_init)
1633 data->pdata->power_init(false);
1634 else
1635 ft5x06_power_init(data, false);
1636
1637 input_unregister_device(data->input_dev);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301638
1639 return 0;
1640}
1641
1642static const struct i2c_device_id ft5x06_ts_id[] = {
1643 {"ft5x06_ts", 0},
1644 {},
1645};
1646
1647MODULE_DEVICE_TABLE(i2c, ft5x06_ts_id);
1648
Mohan Pallaka3a138202013-05-09 16:30:00 +05301649#ifdef CONFIG_OF
1650static struct of_device_id ft5x06_match_table[] = {
1651 { .compatible = "focaltech,5x06",},
1652 { },
1653};
1654#else
1655#define ft5x06_match_table NULL
1656#endif
1657
Mohan Pallakaa2595072012-01-12 22:23:15 +05301658static struct i2c_driver ft5x06_ts_driver = {
1659 .probe = ft5x06_ts_probe,
1660 .remove = __devexit_p(ft5x06_ts_remove),
1661 .driver = {
1662 .name = "ft5x06_ts",
1663 .owner = THIS_MODULE,
Mohan Pallaka3a138202013-05-09 16:30:00 +05301664 .of_match_table = ft5x06_match_table,
Mohan Pallakaa2595072012-01-12 22:23:15 +05301665#ifdef CONFIG_PM
1666 .pm = &ft5x06_ts_pm_ops,
1667#endif
1668 },
1669 .id_table = ft5x06_ts_id,
1670};
1671
1672static int __init ft5x06_ts_init(void)
1673{
1674 return i2c_add_driver(&ft5x06_ts_driver);
1675}
1676module_init(ft5x06_ts_init);
1677
1678static void __exit ft5x06_ts_exit(void)
1679{
1680 i2c_del_driver(&ft5x06_ts_driver);
1681}
1682module_exit(ft5x06_ts_exit);
1683
1684MODULE_DESCRIPTION("FocalTech ft5x06 TouchScreen driver");
1685MODULE_LICENSE("GPL v2");