blob: 25228a6f6754ab5745ee9ae65e9a2e0f39e4054b [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
44#define CFG_MAX_TOUCH_POINTS 5
45
46#define FT_STARTUP_DLY 150
47#define FT_RESET_DLY 20
48
49#define FT_PRESS 0x7F
50#define FT_MAX_ID 0x0F
51#define FT_TOUCH_STEP 6
52#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
56#define FT_TOUCH_EVENT_POS 3
57#define FT_TOUCH_ID_POS 5
58
59#define POINT_READ_BUF (3 + FT_TOUCH_STEP * CFG_MAX_TOUCH_POINTS)
60
61/*register address*/
Mohan Pallaka6d2ab952013-06-04 17:36:20 +053062#define FT_REG_DEV_MODE 0x00
63#define FT_DEV_MODE_REG_CAL 0x02
64#define FT_REG_ID 0xA3
65#define FT_REG_PMODE 0xA5
66#define FT_REG_FW_VER 0xA6
67#define FT_REG_POINT_RATE 0x88
68#define FT_REG_THGROUP 0x80
69#define FT_REG_ECC 0xCC
70#define FT_REG_RESET_FW 0x07
Mohan Pallakaa2595072012-01-12 22:23:15 +053071
72/* power register bits*/
Mohan Pallaka6d2ab952013-06-04 17:36:20 +053073#define FT_PMODE_ACTIVE 0x00
74#define FT_PMODE_MONITOR 0x01
75#define FT_PMODE_STANDBY 0x02
76#define FT_PMODE_HIBERNATE 0x03
77#define FT_FACTORYMODE_VALUE 0x40
78#define FT_WORKMODE_VALUE 0x00
79#define FT_RST_CMD_REG 0xFC
80#define FT_READ_ID_REG 0x90
81#define FT_ERASE_APP_REG 0x61
82#define FT_ERASE_PANEL_REG 0x63
83#define FT_FW_START_REG 0xBF
Mohan Pallakaa2595072012-01-12 22:23:15 +053084
Mohan Pallakaa2595072012-01-12 22:23:15 +053085
Mohan Pallaka6d2ab952013-06-04 17:36:20 +053086#define FT_VTG_MIN_UV 2600000
87#define FT_VTG_MAX_UV 3300000
88#define FT_I2C_VTG_MIN_UV 1800000
89#define FT_I2C_VTG_MAX_UV 1800000
90
91#define FT_COORDS_ARR_SIZE 4
Mohan Pallaka3a138202013-05-09 16:30:00 +053092#define MAX_BUTTONS 4
93
Mohan Pallaka6d2ab952013-06-04 17:36:20 +053094#define FT_8BIT_SHIFT 8
95#define FT_4BIT_SHIFT 4
96#define FT_FW_NAME_MAX_LEN 50
97
98#define FT5316_ID 0x0A
99#define FT5306I_ID 0x55
100
101#define FT_UPGRADE_AA 0xAA
102#define FT_UPGRADE_55 0x55
103
104/*upgrade config of FT5606*/
105#define FT5606_UPGRADE_AA_DELAY 50
106#define FT5606_UPGRADE_55_DELAY 10
107#define FT5606_UPGRADE_ID_1 0x79
108#define FT5606_UPGRADE_ID_2 0x06
109#define FT5606_UPGRADE_READID_DELAY 100
110#define FT5606_UPGRADE_EARSE_DELAY 2000
111
112/*upgrade config of FT5316*/
113#define FT5316_UPGRADE_AA_DELAY 50
114#define FT5316_UPGRADE_55_DELAY 30
115#define FT5316_UPGRADE_ID_1 0x79
116#define FT5316_UPGRADE_ID_2 0x07
117#define FT5316_UPGRADE_READID_DELAY 1
118#define FT5316_UPGRADE_EARSE_DELAY 1500
119
120/*upgrade config of FT5x06(x=2,3,4)*/
121#define FT5X06_UPGRADE_AA_DELAY 50
122#define FT5X06_UPGRADE_55_DELAY 30
123#define FT5X06_UPGRADE_ID_1 0x79
124#define FT5X06_UPGRADE_ID_2 0x03
125#define FT5X06_UPGRADE_READID_DELAY 1
126#define FT5X06_UPGRADE_EARSE_DELAY 2000
127
128/*upgrade config of FT6208*/
129#define FT6208_UPGRADE_AA_DELAY 60
130#define FT6208_UPGRADE_55_DELAY 10
131#define FT6208_UPGRADE_ID_1 0x79
132#define FT6208_UPGRADE_ID_2 0x05
133#define FT6208_UPGRADE_READID_DELAY 10
134#define FT6208_UPGRADE_EARSE_DELAY 2000
135
136#define FT_UPGRADE_INFO(x, y) do { \
137 x->delay_55 = y##_UPGRADE_55_DELAY; \
138 x->delay_aa = y##_UPGRADE_AA_DELAY; \
139 x->upgrade_id_1 = y##_UPGRADE_ID_1; \
140 x->upgrade_id_2 = y##_UPGRADE_ID_2; \
141 x->delay_readid = y##_UPGRADE_READID_DELAY; \
142 x->delay_earse_flash = y##_UPGRADE_EARSE_DELAY; \
143 } while (0)
144
145#define FT_FW_MIN_SIZE 8
146#define FT_FW_MAX_SIZE 32768
147#define FT_FW_FILE_VER(x) ((x)->data[(x)->size - 2])
148#define FT_FW_CHECK(x) \
149 (((x)->data[(x)->size - 8] ^ (x)->data[(x)->size - 6]) == 0xFF \
150 && (((x)->data[(x)->size - 7] ^ (x)->data[(x)->size - 5]) == 0xFF \
151 && (((x)->data[(x)->size - 3] ^ (x)->data[(x)->size - 4]) == 0xFF)))
152
153#define FT_MAX_TRIES 5
154#define FT_RETRY_DLY 20
155
156#define FT_MAX_WR_BUF 10
157#define FT_MAX_RD_BUF 2
158#define FT_FW_PKT_LEN 128
159#define FT_FW_PKT_META_LEN 6
160#define FT_FW_PKT_DLY_MS 20
161#define FT_FW_LAST_PKT 0x6ffa
162#define FT_EARSE_DLY_MS 100
163
164#define FT_UPGRADE_LOOP 3
165#define FT_CAL_START 0x04
166#define FT_CAL_FIN 0x00
167#define FT_CAL_STORE 0x05
168#define FT_CAL_RETRY 100
169#define FT_REG_CAL 0x00
170#define FT_CAL_MASK 0x70
171
Mohan Pallaka768d5e32013-06-14 17:50:10 +0530172#define FT_INFO_MAX_LEN 200
173
174#define FT_STORE_TS_INFO(buf, id, fw_ver) \
175 snprintf(buf, FT_INFO_MAX_LEN, \
176 "controller\t= focaltech\n" \
177 "model\t\t= 0x%x\n" \
178 "fw_ver\t\t= 0x%x\n", id, fw_ver)
179
180#define FT_DEBUG_DIR_NAME "ts_debug"
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530181
Mohan Pallakaa2595072012-01-12 22:23:15 +0530182struct ts_event {
183 u16 x[CFG_MAX_TOUCH_POINTS]; /*x coordinate */
184 u16 y[CFG_MAX_TOUCH_POINTS]; /*y coordinate */
185 /* touch event: 0 -- down; 1-- contact; 2 -- contact */
186 u8 touch_event[CFG_MAX_TOUCH_POINTS];
187 u8 finger_id[CFG_MAX_TOUCH_POINTS]; /*touch ID */
188 u16 pressure;
189 u8 touch_point;
190};
191
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530192struct upgrade_info {
193 u16 delay_aa; /*delay of write FT_UPGRADE_AA */
194 u16 delay_55; /*delay of write FT_UPGRADE_55 */
195 u8 upgrade_id_1; /*upgrade id 1 */
196 u8 upgrade_id_2; /*upgrade id 2 */
197 u16 delay_readid; /*delay of read id */
198 u16 delay_earse_flash; /*delay of earse flash*/
199};
200
Mohan Pallakaa2595072012-01-12 22:23:15 +0530201struct ft5x06_ts_data {
202 struct i2c_client *client;
203 struct input_dev *input_dev;
204 struct ts_event event;
205 const struct ft5x06_ts_platform_data *pdata;
206 struct regulator *vdd;
207 struct regulator *vcc_i2c;
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530208 char fw_name[FT_FW_NAME_MAX_LEN];
209 bool loading_fw;
210 u8 family_id;
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530211 struct dentry *dir;
212 u16 addr;
213 bool suspended;
Mohan Pallaka768d5e32013-06-14 17:50:10 +0530214 char *ts_info;
Mohan Pallakaa5d601b2013-05-10 15:34:44 +0530215#if defined(CONFIG_FB)
216 struct notifier_block fb_notif;
217#elif defined(CONFIG_HAS_EARLYSUSPEND)
Mohan Pallakaa2595072012-01-12 22:23:15 +0530218 struct early_suspend early_suspend;
219#endif
220};
221
222static int ft5x06_i2c_read(struct i2c_client *client, char *writebuf,
223 int writelen, char *readbuf, int readlen)
224{
225 int ret;
226
227 if (writelen > 0) {
228 struct i2c_msg msgs[] = {
229 {
230 .addr = client->addr,
231 .flags = 0,
232 .len = writelen,
233 .buf = writebuf,
234 },
235 {
236 .addr = client->addr,
237 .flags = I2C_M_RD,
238 .len = readlen,
239 .buf = readbuf,
240 },
241 };
242 ret = i2c_transfer(client->adapter, msgs, 2);
243 if (ret < 0)
244 dev_err(&client->dev, "%s: i2c read error.\n",
245 __func__);
246 } else {
247 struct i2c_msg msgs[] = {
248 {
249 .addr = client->addr,
250 .flags = I2C_M_RD,
251 .len = readlen,
252 .buf = readbuf,
253 },
254 };
255 ret = i2c_transfer(client->adapter, msgs, 1);
256 if (ret < 0)
257 dev_err(&client->dev, "%s:i2c read error.\n", __func__);
258 }
259 return ret;
260}
261
262static int ft5x06_i2c_write(struct i2c_client *client, char *writebuf,
263 int writelen)
264{
265 int ret;
266
267 struct i2c_msg msgs[] = {
268 {
269 .addr = client->addr,
270 .flags = 0,
271 .len = writelen,
272 .buf = writebuf,
273 },
274 };
275 ret = i2c_transfer(client->adapter, msgs, 1);
276 if (ret < 0)
277 dev_err(&client->dev, "%s: i2c write error.\n", __func__);
278
279 return ret;
280}
281
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530282static int ft5x0x_write_reg(struct i2c_client *client, u8 addr, const u8 val)
283{
284 u8 buf[2] = {0};
285
286 buf[0] = addr;
287 buf[1] = val;
288
289 return ft5x06_i2c_write(client, buf, sizeof(buf));
290}
291
292static int ft5x0x_read_reg(struct i2c_client *client, u8 addr, u8 *val)
293{
294 return ft5x06_i2c_read(client, &addr, 1, val, 1);
295}
296
Mohan Pallakaa2595072012-01-12 22:23:15 +0530297static void ft5x06_report_value(struct ft5x06_ts_data *data)
298{
299 struct ts_event *event = &data->event;
300 int i;
301 int fingerdown = 0;
302
303 for (i = 0; i < event->touch_point; i++) {
304 if (event->touch_event[i] == 0 || event->touch_event[i] == 2) {
305 event->pressure = FT_PRESS;
306 fingerdown++;
307 } else {
308 event->pressure = 0;
309 }
310
Figo Wang63ad82b2013-06-28 19:49:49 +0800311 input_mt_slot(data->input_dev, event->finger_id[i]);
Mohan Pallaka959a69a2013-06-14 17:12:24 +0530312 input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER,
313 !!event->pressure);
314
315 if (event->pressure == FT_PRESS) {
316 input_report_abs(data->input_dev, ABS_MT_POSITION_X,
317 event->x[i]);
318 input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
319 event->y[i]);
Mohan Pallaka959a69a2013-06-14 17:12:24 +0530320 input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR,
321 event->pressure);
322 }
Mohan Pallakaa2595072012-01-12 22:23:15 +0530323 }
324
325 input_report_key(data->input_dev, BTN_TOUCH, !!fingerdown);
326 input_sync(data->input_dev);
327}
328
329static int ft5x06_handle_touchdata(struct ft5x06_ts_data *data)
330{
331 struct ts_event *event = &data->event;
332 int ret, i;
333 u8 buf[POINT_READ_BUF] = { 0 };
334 u8 pointid = FT_MAX_ID;
335
336 ret = ft5x06_i2c_read(data->client, buf, 1, buf, POINT_READ_BUF);
337 if (ret < 0) {
338 dev_err(&data->client->dev, "%s read touchdata failed.\n",
339 __func__);
340 return ret;
341 }
342 memset(event, 0, sizeof(struct ts_event));
343
344 event->touch_point = 0;
345 for (i = 0; i < CFG_MAX_TOUCH_POINTS; i++) {
346 pointid = (buf[FT_TOUCH_ID_POS + FT_TOUCH_STEP * i]) >> 4;
347 if (pointid >= FT_MAX_ID)
348 break;
349 else
350 event->touch_point++;
351 event->x[i] =
352 (s16) (buf[FT_TOUCH_X_H_POS + FT_TOUCH_STEP * i] & 0x0F) <<
353 8 | (s16) buf[FT_TOUCH_X_L_POS + FT_TOUCH_STEP * i];
354 event->y[i] =
355 (s16) (buf[FT_TOUCH_Y_H_POS + FT_TOUCH_STEP * i] & 0x0F) <<
356 8 | (s16) buf[FT_TOUCH_Y_L_POS + FT_TOUCH_STEP * i];
357 event->touch_event[i] =
358 buf[FT_TOUCH_EVENT_POS + FT_TOUCH_STEP * i] >> 6;
359 event->finger_id[i] =
360 (buf[FT_TOUCH_ID_POS + FT_TOUCH_STEP * i]) >> 4;
361 }
362
363 ft5x06_report_value(data);
364
365 return 0;
366}
367
368static irqreturn_t ft5x06_ts_interrupt(int irq, void *dev_id)
369{
370 struct ft5x06_ts_data *data = dev_id;
371 int rc;
372
373 rc = ft5x06_handle_touchdata(data);
374 if (rc)
375 pr_err("%s: handling touchdata failed\n", __func__);
376
377 return IRQ_HANDLED;
378}
379
380static int ft5x06_power_on(struct ft5x06_ts_data *data, bool on)
381{
382 int rc;
383
384 if (!on)
385 goto power_off;
386
387 rc = regulator_enable(data->vdd);
388 if (rc) {
389 dev_err(&data->client->dev,
390 "Regulator vdd enable failed rc=%d\n", rc);
391 return rc;
392 }
393
394 rc = regulator_enable(data->vcc_i2c);
395 if (rc) {
396 dev_err(&data->client->dev,
397 "Regulator vcc_i2c enable failed rc=%d\n", rc);
398 regulator_disable(data->vdd);
399 }
400
401 return rc;
402
403power_off:
404 rc = regulator_disable(data->vdd);
405 if (rc) {
406 dev_err(&data->client->dev,
407 "Regulator vdd disable failed rc=%d\n", rc);
408 return rc;
409 }
410
411 rc = regulator_disable(data->vcc_i2c);
412 if (rc) {
413 dev_err(&data->client->dev,
414 "Regulator vcc_i2c disable failed rc=%d\n", rc);
415 regulator_enable(data->vdd);
416 }
417
418 return rc;
419}
420
421static int ft5x06_power_init(struct ft5x06_ts_data *data, bool on)
422{
423 int rc;
424
425 if (!on)
426 goto pwr_deinit;
427
428 data->vdd = regulator_get(&data->client->dev, "vdd");
429 if (IS_ERR(data->vdd)) {
430 rc = PTR_ERR(data->vdd);
431 dev_err(&data->client->dev,
432 "Regulator get failed vdd rc=%d\n", rc);
433 return rc;
434 }
435
436 if (regulator_count_voltages(data->vdd) > 0) {
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530437 rc = regulator_set_voltage(data->vdd, FT_VTG_MIN_UV,
438 FT_VTG_MAX_UV);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530439 if (rc) {
440 dev_err(&data->client->dev,
441 "Regulator set_vtg failed vdd rc=%d\n", rc);
442 goto reg_vdd_put;
443 }
444 }
445
446 data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c");
447 if (IS_ERR(data->vcc_i2c)) {
448 rc = PTR_ERR(data->vcc_i2c);
449 dev_err(&data->client->dev,
450 "Regulator get failed vcc_i2c rc=%d\n", rc);
451 goto reg_vdd_set_vtg;
452 }
453
454 if (regulator_count_voltages(data->vcc_i2c) > 0) {
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530455 rc = regulator_set_voltage(data->vcc_i2c, FT_I2C_VTG_MIN_UV,
456 FT_I2C_VTG_MAX_UV);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530457 if (rc) {
458 dev_err(&data->client->dev,
459 "Regulator set_vtg failed vcc_i2c rc=%d\n", rc);
460 goto reg_vcc_i2c_put;
461 }
462 }
463
464 return 0;
465
466reg_vcc_i2c_put:
467 regulator_put(data->vcc_i2c);
468reg_vdd_set_vtg:
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 +0530471reg_vdd_put:
472 regulator_put(data->vdd);
473 return rc;
474
475pwr_deinit:
476 if (regulator_count_voltages(data->vdd) > 0)
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530477 regulator_set_voltage(data->vdd, 0, FT_VTG_MAX_UV);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530478
479 regulator_put(data->vdd);
480
481 if (regulator_count_voltages(data->vcc_i2c) > 0)
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530482 regulator_set_voltage(data->vcc_i2c, 0, FT_I2C_VTG_MAX_UV);
Mohan Pallakaa2595072012-01-12 22:23:15 +0530483
484 regulator_put(data->vcc_i2c);
485 return 0;
486}
487
488#ifdef CONFIG_PM
489static int ft5x06_ts_suspend(struct device *dev)
490{
491 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
Figo Wang63ad82b2013-06-28 19:49:49 +0800492 char txbuf[2], i;
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530493 int err;
Mohan Pallakaa2595072012-01-12 22:23:15 +0530494
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530495 if (data->loading_fw) {
496 dev_info(dev, "Firmware loading in process...\n");
497 return 0;
498 }
499
500 if (data->suspended) {
501 dev_info(dev, "Already in suspend state\n");
502 return 0;
503 }
504
Mohan Pallakaa2595072012-01-12 22:23:15 +0530505 disable_irq(data->client->irq);
506
Figo Wang63ad82b2013-06-28 19:49:49 +0800507 /* release all touches */
508 for (i = 0; i < CFG_MAX_TOUCH_POINTS; i++) {
509 input_mt_slot(data->input_dev, i);
510 input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, 0);
511 }
512 input_report_key(data->input_dev, BTN_TOUCH, 0);
513 input_sync(data->input_dev);
514
Mohan Pallakaa2595072012-01-12 22:23:15 +0530515 if (gpio_is_valid(data->pdata->reset_gpio)) {
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530516 txbuf[0] = FT_REG_PMODE;
517 txbuf[1] = FT_PMODE_HIBERNATE;
Mohan Pallakaa2595072012-01-12 22:23:15 +0530518 ft5x06_i2c_write(data->client, txbuf, sizeof(txbuf));
519 }
520
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530521 if (data->pdata->power_on) {
522 err = data->pdata->power_on(false);
523 if (err) {
524 dev_err(dev, "power off failed");
525 goto pwr_off_fail;
526 }
527 } else {
528 err = ft5x06_power_on(data, false);
529 if (err) {
530 dev_err(dev, "power off failed");
531 goto pwr_off_fail;
532 }
533 }
534
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530535 data->suspended = true;
536
Mohan Pallakaa2595072012-01-12 22:23:15 +0530537 return 0;
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530538
539pwr_off_fail:
540 if (gpio_is_valid(data->pdata->reset_gpio)) {
541 gpio_set_value_cansleep(data->pdata->reset_gpio, 0);
542 msleep(FT_RESET_DLY);
543 gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
544 }
545 enable_irq(data->client->irq);
546 return err;
Mohan Pallakaa2595072012-01-12 22:23:15 +0530547}
548
549static int ft5x06_ts_resume(struct device *dev)
550{
551 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530552 int err;
Mohan Pallakaa2595072012-01-12 22:23:15 +0530553
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530554 if (!data->suspended) {
555 dev_info(dev, "Already in awake state\n");
556 return 0;
557 }
558
Mohan Pallakaf7ee45e2013-07-15 16:17:46 +0530559 if (data->pdata->power_on) {
560 err = data->pdata->power_on(true);
561 if (err) {
562 dev_err(dev, "power on failed");
563 return err;
564 }
565 } else {
566 err = ft5x06_power_on(data, true);
567 if (err) {
568 dev_err(dev, "power on failed");
569 return err;
570 }
571 }
572
Mohan Pallakaa2595072012-01-12 22:23:15 +0530573 if (gpio_is_valid(data->pdata->reset_gpio)) {
574 gpio_set_value_cansleep(data->pdata->reset_gpio, 0);
575 msleep(FT_RESET_DLY);
576 gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
577 }
578 enable_irq(data->client->irq);
579
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530580 data->suspended = false;
581
Mohan Pallakaa2595072012-01-12 22:23:15 +0530582 return 0;
583}
584
Mohan Pallakaa5d601b2013-05-10 15:34:44 +0530585#if defined(CONFIG_FB)
586static int fb_notifier_callback(struct notifier_block *self,
587 unsigned long event, void *data)
588{
589 struct fb_event *evdata = data;
590 int *blank;
591 struct ft5x06_ts_data *ft5x06_data =
592 container_of(self, struct ft5x06_ts_data, fb_notif);
593
594 if (evdata && evdata->data && event == FB_EVENT_BLANK &&
595 ft5x06_data && ft5x06_data->client) {
596 blank = evdata->data;
597 if (*blank == FB_BLANK_UNBLANK)
598 ft5x06_ts_resume(&ft5x06_data->client->dev);
599 else if (*blank == FB_BLANK_POWERDOWN)
600 ft5x06_ts_suspend(&ft5x06_data->client->dev);
601 }
602
603 return 0;
604}
605#elif defined(CONFIG_HAS_EARLYSUSPEND)
Mohan Pallakaa2595072012-01-12 22:23:15 +0530606static void ft5x06_ts_early_suspend(struct early_suspend *handler)
607{
608 struct ft5x06_ts_data *data = container_of(handler,
609 struct ft5x06_ts_data,
610 early_suspend);
611
612 ft5x06_ts_suspend(&data->client->dev);
613}
614
615static void ft5x06_ts_late_resume(struct early_suspend *handler)
616{
617 struct ft5x06_ts_data *data = container_of(handler,
618 struct ft5x06_ts_data,
619 early_suspend);
620
621 ft5x06_ts_resume(&data->client->dev);
622}
623#endif
624
625static const struct dev_pm_ops ft5x06_ts_pm_ops = {
Mohan Pallakaa5d601b2013-05-10 15:34:44 +0530626#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND))
Mohan Pallakaa2595072012-01-12 22:23:15 +0530627 .suspend = ft5x06_ts_suspend,
628 .resume = ft5x06_ts_resume,
629#endif
630};
631#endif
632
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530633static int ft5x06_auto_cal(struct i2c_client *client)
634{
635 u8 temp = 0, i;
636
637 /* set to factory mode */
638 msleep(2 * FT_STARTUP_DLY);
639 ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
640 msleep(FT_STARTUP_DLY);
641
642 /* start calibration */
643 ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_START);
644 msleep(2 * FT_STARTUP_DLY);
645 for (i = 0; i < FT_CAL_RETRY; i++) {
646 ft5x0x_read_reg(client, FT_REG_CAL, &temp);
647 /*return to normal mode, calibration finish */
648 if (((temp & FT_CAL_MASK) >> FT_4BIT_SHIFT) == FT_CAL_FIN)
649 break;
650 }
651
652 /*calibration OK */
653 msleep(2 * FT_STARTUP_DLY);
654 ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
655 msleep(FT_STARTUP_DLY);
656
657 /* store calibration data */
658 ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_STORE);
659 msleep(2 * FT_STARTUP_DLY);
660
661 /* set to normal mode */
662 ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_WORKMODE_VALUE);
663 msleep(2 * FT_STARTUP_DLY);
664
665 return 0;
666}
667
668static int ft5x06_get_upgrade_info(u8 family_id, struct upgrade_info *info)
669{
670 switch (family_id) {
671 case FT5306I_ID:
672 FT_UPGRADE_INFO(info, FT5X06);
673 break;
674 case FT5316_ID:
675 FT_UPGRADE_INFO(info, FT5316);
676 break;
677 default:
678 return -EINVAL;
679 }
680
681 return 0;
682}
683
684static int ft5x06_fw_upgrade_start(struct i2c_client *client,
685 const u8 *data, u32 data_len)
686{
687 struct ft5x06_ts_data *ts_data = i2c_get_clientdata(client);
688 struct upgrade_info info;
689 u8 w_buf[FT_MAX_WR_BUF] = {0}, r_buf[FT_MAX_RD_BUF] = {0};
690 u8 pkt_buf[FT_FW_PKT_LEN + FT_FW_PKT_META_LEN];
691 int rc, i, j, temp;
692 u32 pkt_num, pkt_len;
693 u8 fw_ecc;
694
695 rc = ft5x06_get_upgrade_info(ts_data->family_id, &info);
696 if (rc < 0) {
697 dev_err(&client->dev, "Cannot get upgrade information!\n");
698 return -EINVAL;
699 }
700
701 for (i = 0; i < FT_UPGRADE_LOOP; i++) {
702 /* reset - write 0xaa and 0x55 to register 0xfc */
703 ft5x0x_write_reg(client, FT_RST_CMD_REG, FT_UPGRADE_AA);
704 msleep(info.delay_aa);
705
706 ft5x0x_write_reg(client, FT_RST_CMD_REG, FT_UPGRADE_55);
707 msleep(info.delay_55);
708
709 /* Enter upgrade mode */
710 w_buf[0] = FT_UPGRADE_55;
711 w_buf[1] = FT_UPGRADE_AA;
712 do {
713 i++;
714 rc = ft5x06_i2c_write(client, w_buf, 2);
715 msleep(FT_RETRY_DLY);
716 } while (rc <= 0 && i < FT_MAX_TRIES);
717
718 /* check READ_ID */
719 msleep(info.delay_readid);
720 w_buf[0] = FT_READ_ID_REG;
721 w_buf[1] = 0x00;
722 w_buf[2] = 0x00;
723 w_buf[3] = 0x00;
724
725 ft5x06_i2c_read(client, w_buf, 4, r_buf, 2);
726
727 if (r_buf[0] != info.upgrade_id_1
728 || r_buf[1] != info.upgrade_id_2) {
729 dev_err(&client->dev, "Upgrade ID mismatch(%d)\n", i);
730 } else
731 break;
732 }
733
734 if (i >= FT_UPGRADE_LOOP) {
735 dev_err(&client->dev, "Abort upgrade\n");
736 return -EIO;
737 }
738
739 /* erase app and panel paramenter area */
740 w_buf[0] = FT_ERASE_APP_REG;
741 ft5x06_i2c_write(client, w_buf, 1);
742 msleep(info.delay_earse_flash);
743
744 w_buf[0] = FT_ERASE_PANEL_REG;
745 ft5x06_i2c_write(client, w_buf, 1);
746 msleep(FT_EARSE_DLY_MS);
747
748 /* program firmware */
749 data_len = data_len - 8;
750 pkt_num = (data_len) / FT_FW_PKT_LEN;
751 pkt_len = FT_FW_PKT_LEN;
752 pkt_buf[0] = FT_FW_START_REG;
753 pkt_buf[1] = 0x00;
754 fw_ecc = 0;
755
756 for (i = 0; i < pkt_num; i++) {
757 temp = i * FT_FW_PKT_LEN;
758 pkt_buf[2] = (u8) (temp >> FT_8BIT_SHIFT);
759 pkt_buf[3] = (u8) temp;
760 pkt_buf[4] = (u8) (pkt_len >> FT_8BIT_SHIFT);
761 pkt_buf[5] = (u8) pkt_len;
762
763 for (j = 0; j < FT_FW_PKT_LEN; j++) {
764 pkt_buf[6 + j] = data[i * FT_FW_PKT_LEN + j];
765 fw_ecc ^= pkt_buf[6 + j];
766 }
767
768 ft5x06_i2c_write(client, pkt_buf,
769 FT_FW_PKT_LEN + FT_FW_PKT_META_LEN);
770 msleep(FT_FW_PKT_DLY_MS);
771 }
772
773 /* send remaining bytes */
774 if ((data_len) % FT_FW_PKT_LEN > 0) {
775 temp = pkt_num * FT_FW_PKT_LEN;
776 pkt_buf[2] = (u8) (temp >> FT_8BIT_SHIFT);
777 pkt_buf[3] = (u8) temp;
778 temp = (data_len) % FT_FW_PKT_LEN;
779 pkt_buf[4] = (u8) (temp >> FT_8BIT_SHIFT);
780 pkt_buf[5] = (u8) temp;
781
782 for (i = 0; i < temp; i++) {
783 pkt_buf[6 + i] = data[pkt_num * FT_FW_PKT_LEN + i];
784 fw_ecc ^= pkt_buf[6 + i];
785 }
786
787 ft5x06_i2c_write(client, pkt_buf, temp + FT_FW_PKT_META_LEN);
788 msleep(FT_FW_PKT_DLY_MS);
789 }
790
791 /* send the finishing packet */
792 for (i = 0; i < 6; i++) {
793 temp = FT_FW_LAST_PKT + i;
794 pkt_buf[2] = (u8) (temp >> 8);
795 pkt_buf[3] = (u8) temp;
796 temp = 1;
797 pkt_buf[4] = (u8) (temp >> 8);
798 pkt_buf[5] = (u8) temp;
799 pkt_buf[6] = data[data_len + i];
800 fw_ecc ^= pkt_buf[6];
801 ft5x06_i2c_write(client, pkt_buf, temp + FT_FW_PKT_META_LEN);
802 msleep(FT_FW_PKT_DLY_MS);
803 }
804
805 /* verify checksum */
806 w_buf[0] = FT_REG_ECC;
807 ft5x06_i2c_read(client, w_buf, 1, r_buf, 1);
808 if (r_buf[0] != fw_ecc) {
809 dev_err(&client->dev, "ECC error! dev_ecc=%02x fw_ecc=%02x\n",
810 r_buf[0], fw_ecc);
811 return -EIO;
812 }
813
814 /* reset */
815 w_buf[0] = FT_REG_RESET_FW;
816 ft5x06_i2c_write(client, w_buf, 1);
817 msleep(FT_STARTUP_DLY);
818
819 return 0;
820}
821
822static int ft5x06_fw_upgrade(struct device *dev, bool force)
823{
824 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
825 const struct firmware *fw = NULL;
826 int rc;
827 u8 val = 0;
828
829 rc = request_firmware(&fw, data->fw_name, dev);
830 if (rc < 0) {
831 dev_err(dev, "Request firmware failed - %s (%d)\n",
832 data->fw_name, rc);
833 return rc;
834 }
835
836 if (fw->size < FT_FW_MIN_SIZE || fw->size > FT_FW_MAX_SIZE) {
837 dev_err(dev, "Invalid firmware size (%d)\n", fw->size);
838 rc = -EIO;
839 goto rel_fw;
840 }
841
842 /* check firmware version */
843 rc = ft5x0x_read_reg(data->client, FT_REG_FW_VER, &val);
844 if (rc < 0) {
845 dev_err(dev, "Get firmware version failed\n");
846 goto rel_fw;
847 }
848
849 if (val == FT_FW_FILE_VER(fw) && !force) {
850 dev_err(dev, "No need to update (0x%x)\n", val);
851 rc = -EFAULT;
852 goto rel_fw;
853 }
854
855 dev_info(dev, "upgrade to fw ver 0x%x from 0x%x\n",
856 FT_FW_FILE_VER(fw), val);
857
858 /* start firmware upgrade */
859 if (FT_FW_CHECK(fw)) {
860 rc = ft5x06_fw_upgrade_start(data->client, fw->data, fw->size);
861 if (rc < 0)
862 dev_err(dev, "update failed (%d)\n", rc);
863 else
864 ft5x06_auto_cal(data->client);
865 } else {
866 dev_err(dev, "FW format error\n");
867 rc = -EIO;
868 }
869
Mohan Pallaka768d5e32013-06-14 17:50:10 +0530870 FT_STORE_TS_INFO(data->ts_info, data->family_id, FT_FW_FILE_VER(fw));
Mohan Pallaka6d2ab952013-06-04 17:36:20 +0530871rel_fw:
872 release_firmware(fw);
873 return rc;
874}
875
876static ssize_t ft5x06_update_fw_show(struct device *dev,
877 struct device_attribute *attr, char *buf)
878{
879 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
880 return snprintf(buf, 2, "%d\n", data->loading_fw);
881}
882
883static ssize_t ft5x06_update_fw_store(struct device *dev,
884 struct device_attribute *attr,
885 const char *buf, size_t size)
886{
887 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
888 unsigned long val;
889 int rc;
890
891 if (size > 2)
892 return -EINVAL;
893
894 rc = kstrtoul(buf, 10, &val);
895 if (rc != 0)
896 return rc;
897
898 mutex_lock(&data->input_dev->mutex);
899 if (!data->loading_fw && val) {
900 data->loading_fw = true;
901 ft5x06_fw_upgrade(dev, false);
902 data->loading_fw = false;
903 }
904 mutex_unlock(&data->input_dev->mutex);
905
906 return size;
907}
908
909static DEVICE_ATTR(update_fw, 0664, ft5x06_update_fw_show,
910 ft5x06_update_fw_store);
911
912static ssize_t ft5x06_force_update_fw_store(struct device *dev,
913 struct device_attribute *attr,
914 const char *buf, size_t size)
915{
916 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
917 unsigned long val;
918 int rc;
919
920 if (size > 2)
921 return -EINVAL;
922
923 rc = kstrtoul(buf, 10, &val);
924 if (rc != 0)
925 return rc;
926
927 mutex_lock(&data->input_dev->mutex);
928 if (!data->loading_fw && val) {
929 data->loading_fw = true;
930 ft5x06_fw_upgrade(dev, true);
931 data->loading_fw = false;
932 }
933 mutex_unlock(&data->input_dev->mutex);
934
935 return size;
936}
937
938static DEVICE_ATTR(force_update_fw, 0664, ft5x06_update_fw_show,
939 ft5x06_force_update_fw_store);
940
941static ssize_t ft5x06_fw_name_show(struct device *dev,
942 struct device_attribute *attr, char *buf)
943{
944 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
945 return snprintf(buf, FT_FW_NAME_MAX_LEN - 1, "%s\n", data->fw_name);
946}
947
948static ssize_t ft5x06_fw_name_store(struct device *dev,
949 struct device_attribute *attr,
950 const char *buf, size_t size)
951{
952 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
953
954 if (size > FT_FW_NAME_MAX_LEN - 1)
955 return -EINVAL;
956
957 strlcpy(data->fw_name, buf, size);
958 if (data->fw_name[size-1] == '\n')
959 data->fw_name[size-1] = 0;
960
961 return size;
962}
963
964static DEVICE_ATTR(fw_name, 0664, ft5x06_fw_name_show, ft5x06_fw_name_store);
965
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +0530966static bool ft5x06_debug_addr_is_valid(int addr)
967{
968 if (addr < 0 || addr > 0xFF) {
969 pr_err("FT reg address is invalid: 0x%x\n", addr);
970 return false;
971 }
972
973 return true;
974}
975
976static int ft5x06_debug_data_set(void *_data, u64 val)
977{
978 struct ft5x06_ts_data *data = _data;
979
980 mutex_lock(&data->input_dev->mutex);
981
982 if (ft5x06_debug_addr_is_valid(data->addr))
983 dev_info(&data->client->dev,
984 "Writing into FT registers not supported\n");
985
986 mutex_unlock(&data->input_dev->mutex);
987
988 return 0;
989}
990
991static int ft5x06_debug_data_get(void *_data, u64 *val)
992{
993 struct ft5x06_ts_data *data = _data;
994 int rc;
995 u8 reg;
996
997 mutex_lock(&data->input_dev->mutex);
998
999 if (ft5x06_debug_addr_is_valid(data->addr)) {
1000 rc = ft5x0x_read_reg(data->client, data->addr, &reg);
1001 if (rc < 0)
1002 dev_err(&data->client->dev,
1003 "FT read register 0x%x failed (%d)\n",
1004 data->addr, rc);
1005 else
1006 *val = reg;
1007 }
1008
1009 mutex_unlock(&data->input_dev->mutex);
1010
1011 return 0;
1012}
1013
1014DEFINE_SIMPLE_ATTRIBUTE(debug_data_fops, ft5x06_debug_data_get,
1015 ft5x06_debug_data_set, "0x%02llX\n");
1016
1017static int ft5x06_debug_addr_set(void *_data, u64 val)
1018{
1019 struct ft5x06_ts_data *data = _data;
1020
1021 if (ft5x06_debug_addr_is_valid(val)) {
1022 mutex_lock(&data->input_dev->mutex);
1023 data->addr = val;
1024 mutex_unlock(&data->input_dev->mutex);
1025 }
1026
1027 return 0;
1028}
1029
1030static int ft5x06_debug_addr_get(void *_data, u64 *val)
1031{
1032 struct ft5x06_ts_data *data = _data;
1033
1034 mutex_lock(&data->input_dev->mutex);
1035
1036 if (ft5x06_debug_addr_is_valid(data->addr))
1037 *val = data->addr;
1038
1039 mutex_unlock(&data->input_dev->mutex);
1040
1041 return 0;
1042}
1043
1044DEFINE_SIMPLE_ATTRIBUTE(debug_addr_fops, ft5x06_debug_addr_get,
1045 ft5x06_debug_addr_set, "0x%02llX\n");
1046
1047static int ft5x06_debug_suspend_set(void *_data, u64 val)
1048{
1049 struct ft5x06_ts_data *data = _data;
1050
1051 mutex_lock(&data->input_dev->mutex);
1052
1053 if (val)
1054 ft5x06_ts_suspend(&data->client->dev);
1055 else
1056 ft5x06_ts_resume(&data->client->dev);
1057
1058 mutex_unlock(&data->input_dev->mutex);
1059
1060 return 0;
1061}
1062
1063static int ft5x06_debug_suspend_get(void *_data, u64 *val)
1064{
1065 struct ft5x06_ts_data *data = _data;
1066
1067 mutex_lock(&data->input_dev->mutex);
1068 *val = data->suspended;
1069 mutex_unlock(&data->input_dev->mutex);
1070
1071 return 0;
1072}
1073
1074DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, ft5x06_debug_suspend_get,
1075 ft5x06_debug_suspend_set, "%lld\n");
1076
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301077static int ft5x06_debug_dump_info(struct seq_file *m, void *v)
1078{
1079 struct ft5x06_ts_data *data = m->private;
1080
1081 seq_printf(m, "%s\n", data->ts_info);
1082
1083 return 0;
1084}
1085
1086static int debugfs_dump_info_open(struct inode *inode, struct file *file)
1087{
1088 return single_open(file, ft5x06_debug_dump_info, inode->i_private);
1089}
1090
1091static const struct file_operations debug_dump_info_fops = {
1092 .owner = THIS_MODULE,
1093 .open = debugfs_dump_info_open,
1094 .read = seq_read,
1095 .release = single_release,
1096};
1097
Mohan Pallaka3a138202013-05-09 16:30:00 +05301098#ifdef CONFIG_OF
1099static int ft5x06_get_dt_coords(struct device *dev, char *name,
1100 struct ft5x06_ts_platform_data *pdata)
1101{
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301102 u32 coords[FT_COORDS_ARR_SIZE];
Mohan Pallaka3a138202013-05-09 16:30:00 +05301103 struct property *prop;
1104 struct device_node *np = dev->of_node;
1105 int coords_size, rc;
1106
1107 prop = of_find_property(np, name, NULL);
1108 if (!prop)
1109 return -EINVAL;
1110 if (!prop->value)
1111 return -ENODATA;
1112
1113 coords_size = prop->length / sizeof(u32);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301114 if (coords_size != FT_COORDS_ARR_SIZE) {
Mohan Pallaka3a138202013-05-09 16:30:00 +05301115 dev_err(dev, "invalid %s\n", name);
1116 return -EINVAL;
1117 }
1118
1119 rc = of_property_read_u32_array(np, name, coords, coords_size);
1120 if (rc && (rc != -EINVAL)) {
1121 dev_err(dev, "Unable to read %s\n", name);
1122 return rc;
1123 }
1124
1125 if (!strcmp(name, "focaltech,panel-coords")) {
1126 pdata->panel_minx = coords[0];
1127 pdata->panel_miny = coords[1];
1128 pdata->panel_maxx = coords[2];
1129 pdata->panel_maxy = coords[3];
1130 } else if (!strcmp(name, "focaltech,display-coords")) {
1131 pdata->x_min = coords[0];
1132 pdata->y_min = coords[1];
1133 pdata->x_max = coords[2];
1134 pdata->y_max = coords[3];
1135 } else {
1136 dev_err(dev, "unsupported property %s\n", name);
1137 return -EINVAL;
1138 }
1139
1140 return 0;
1141}
1142
1143static int ft5x06_parse_dt(struct device *dev,
1144 struct ft5x06_ts_platform_data *pdata)
1145{
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301146 int rc;
Mohan Pallaka3a138202013-05-09 16:30:00 +05301147 struct device_node *np = dev->of_node;
1148 struct property *prop;
1149 u32 temp_val, num_buttons;
1150 u32 button_map[MAX_BUTTONS];
1151
1152 rc = ft5x06_get_dt_coords(dev, "focaltech,panel-coords", pdata);
1153 if (rc && (rc != -EINVAL))
1154 return rc;
1155
1156 rc = ft5x06_get_dt_coords(dev, "focaltech,display-coords", pdata);
1157 if (rc)
1158 return rc;
1159
1160 pdata->i2c_pull_up = of_property_read_bool(np,
1161 "focaltech,i2c-pull-up");
1162
1163 pdata->no_force_update = of_property_read_bool(np,
1164 "focaltech,no-force-update");
1165 /* reset, irq gpio info */
1166 pdata->reset_gpio = of_get_named_gpio_flags(np, "focaltech,reset-gpio",
1167 0, &pdata->reset_gpio_flags);
1168 if (pdata->reset_gpio < 0)
1169 return pdata->reset_gpio;
1170
1171 pdata->irq_gpio = of_get_named_gpio_flags(np, "focaltech,irq-gpio",
1172 0, &pdata->irq_gpio_flags);
1173 if (pdata->irq_gpio < 0)
1174 return pdata->irq_gpio;
1175
1176 rc = of_property_read_u32(np, "focaltech,family-id", &temp_val);
1177 if (!rc)
1178 pdata->family_id = temp_val;
1179 else
1180 return rc;
1181
1182 prop = of_find_property(np, "focaltech,button-map", NULL);
1183 if (prop) {
1184 num_buttons = prop->length / sizeof(temp_val);
1185 if (num_buttons > MAX_BUTTONS)
1186 return -EINVAL;
1187
1188 rc = of_property_read_u32_array(np,
1189 "focaltech,button-map", button_map,
1190 num_buttons);
1191 if (rc) {
1192 dev_err(dev, "Unable to read key codes\n");
1193 return rc;
1194 }
1195 }
1196
1197 return 0;
1198}
1199#else
1200static int ft5x06_parse_dt(struct device *dev,
1201 struct ft5x06_ts_platform_data *pdata)
1202{
1203 return -ENODEV;
1204}
1205#endif
1206
Mohan Pallakaa2595072012-01-12 22:23:15 +05301207static int ft5x06_ts_probe(struct i2c_client *client,
1208 const struct i2c_device_id *id)
1209{
Mohan Pallaka3a138202013-05-09 16:30:00 +05301210 struct ft5x06_ts_platform_data *pdata;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301211 struct ft5x06_ts_data *data;
1212 struct input_dev *input_dev;
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301213 struct dentry *temp;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301214 u8 reg_value;
1215 u8 reg_addr;
1216 int err;
1217
Mohan Pallaka3a138202013-05-09 16:30:00 +05301218 if (client->dev.of_node) {
1219 pdata = devm_kzalloc(&client->dev,
1220 sizeof(struct ft5x06_ts_platform_data), GFP_KERNEL);
1221 if (!pdata) {
1222 dev_err(&client->dev, "Failed to allocate memory\n");
1223 return -ENOMEM;
1224 }
1225
1226 err = ft5x06_parse_dt(&client->dev, pdata);
1227 if (err)
1228 return err;
1229 } else
1230 pdata = client->dev.platform_data;
1231
Mohan Pallakaa2595072012-01-12 22:23:15 +05301232 if (!pdata) {
1233 dev_err(&client->dev, "Invalid pdata\n");
1234 return -EINVAL;
1235 }
1236
1237 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
1238 dev_err(&client->dev, "I2C not supported\n");
1239 return -ENODEV;
1240 }
1241
1242 data = kzalloc(sizeof(struct ft5x06_ts_data), GFP_KERNEL);
1243 if (!data) {
1244 dev_err(&client->dev, "Not enough memory\n");
1245 return -ENOMEM;
1246 }
1247
1248 input_dev = input_allocate_device();
1249 if (!input_dev) {
1250 err = -ENOMEM;
1251 dev_err(&client->dev, "failed to allocate input device\n");
1252 goto free_mem;
1253 }
1254
1255 data->input_dev = input_dev;
1256 data->client = client;
1257 data->pdata = pdata;
1258
1259 input_dev->name = "ft5x06_ts";
1260 input_dev->id.bustype = BUS_I2C;
1261 input_dev->dev.parent = &client->dev;
1262
1263 input_set_drvdata(input_dev, data);
1264 i2c_set_clientdata(client, data);
1265
1266 __set_bit(EV_KEY, input_dev->evbit);
1267 __set_bit(EV_ABS, input_dev->evbit);
1268 __set_bit(BTN_TOUCH, input_dev->keybit);
Amy Malochedd2703d2012-06-20 11:03:56 -07001269 __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301270
Mohan Pallaka959a69a2013-06-14 17:12:24 +05301271 input_mt_init_slots(input_dev, CFG_MAX_TOUCH_POINTS);
Mohan Pallaka3a138202013-05-09 16:30:00 +05301272 input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min,
Mohan Pallakaa2595072012-01-12 22:23:15 +05301273 pdata->x_max, 0, 0);
Mohan Pallaka3a138202013-05-09 16:30:00 +05301274 input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min,
Mohan Pallakaa2595072012-01-12 22:23:15 +05301275 pdata->y_max, 0, 0);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301276 input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, FT_PRESS, 0, 0);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301277
1278 err = input_register_device(input_dev);
1279 if (err) {
1280 dev_err(&client->dev, "Input device registration failed\n");
1281 goto free_inputdev;
1282 }
1283
1284 if (pdata->power_init) {
1285 err = pdata->power_init(true);
1286 if (err) {
1287 dev_err(&client->dev, "power init failed");
1288 goto unreg_inputdev;
1289 }
1290 } else {
1291 err = ft5x06_power_init(data, true);
1292 if (err) {
1293 dev_err(&client->dev, "power init failed");
1294 goto unreg_inputdev;
1295 }
1296 }
1297
1298 if (pdata->power_on) {
1299 err = pdata->power_on(true);
1300 if (err) {
1301 dev_err(&client->dev, "power on failed");
1302 goto pwr_deinit;
1303 }
1304 } else {
1305 err = ft5x06_power_on(data, true);
1306 if (err) {
1307 dev_err(&client->dev, "power on failed");
1308 goto pwr_deinit;
1309 }
1310 }
1311
1312 if (gpio_is_valid(pdata->irq_gpio)) {
1313 err = gpio_request(pdata->irq_gpio, "ft5x06_irq_gpio");
1314 if (err) {
1315 dev_err(&client->dev, "irq gpio request failed");
1316 goto pwr_off;
1317 }
1318 err = gpio_direction_input(pdata->irq_gpio);
1319 if (err) {
1320 dev_err(&client->dev,
1321 "set_direction for irq gpio failed\n");
1322 goto free_irq_gpio;
1323 }
1324 }
1325
1326 if (gpio_is_valid(pdata->reset_gpio)) {
1327 err = gpio_request(pdata->reset_gpio, "ft5x06_reset_gpio");
1328 if (err) {
1329 dev_err(&client->dev, "reset gpio request failed");
1330 goto free_irq_gpio;
1331 }
1332
1333 err = gpio_direction_output(pdata->reset_gpio, 0);
1334 if (err) {
1335 dev_err(&client->dev,
1336 "set_direction for reset gpio failed\n");
1337 goto free_reset_gpio;
1338 }
1339 msleep(FT_RESET_DLY);
1340 gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
1341 }
1342
1343 /* make sure CTP already finish startup process */
1344 msleep(FT_STARTUP_DLY);
1345
Mohan Pallaka3a138202013-05-09 16:30:00 +05301346 /* check the controller id */
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301347 reg_addr = FT_REG_ID;
Mohan Pallaka3a138202013-05-09 16:30:00 +05301348 err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
1349 if (err < 0) {
1350 dev_err(&client->dev, "version read failed");
Shantanu Jain3da65202013-07-08 19:11:07 +05301351 goto free_reset_gpio;
Mohan Pallaka3a138202013-05-09 16:30:00 +05301352 }
1353
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301354 dev_info(&client->dev, "Device ID = 0x%x\n", reg_value);
1355
Mohan Pallaka3a138202013-05-09 16:30:00 +05301356 if (pdata->family_id != reg_value) {
1357 dev_err(&client->dev, "%s:Unsupported controller\n", __func__);
1358 goto free_reset_gpio;
1359 }
1360
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301361 data->family_id = reg_value;
1362
Mohan Pallakaa2595072012-01-12 22:23:15 +05301363 err = request_threaded_irq(client->irq, NULL,
1364 ft5x06_ts_interrupt, pdata->irqflags,
1365 client->dev.driver->name, data);
1366 if (err) {
1367 dev_err(&client->dev, "request irq failed\n");
1368 goto free_reset_gpio;
1369 }
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301370
1371 err = device_create_file(&client->dev, &dev_attr_fw_name);
1372 if (err) {
1373 dev_err(&client->dev, "sys file creation failed\n");
1374 goto irq_free;
1375 }
1376
1377 err = device_create_file(&client->dev, &dev_attr_update_fw);
1378 if (err) {
1379 dev_err(&client->dev, "sys file creation failed\n");
1380 goto free_fw_name_sys;
1381 }
1382
1383 err = device_create_file(&client->dev, &dev_attr_force_update_fw);
1384 if (err) {
1385 dev_err(&client->dev, "sys file creation failed\n");
1386 goto free_update_fw_sys;
1387 }
1388
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301389 data->dir = debugfs_create_dir(FT_DEBUG_DIR_NAME, NULL);
1390 if (data->dir == NULL || IS_ERR(data->dir)) {
1391 pr_err("debugfs_create_dir failed(%ld)\n", PTR_ERR(data->dir));
1392 err = PTR_ERR(data->dir);
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301393 goto free_force_update_fw_sys;
1394 }
1395
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301396 temp = debugfs_create_file("addr", S_IRUSR | S_IWUSR, data->dir, data,
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301397 &debug_addr_fops);
1398 if (temp == NULL || IS_ERR(temp)) {
1399 pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
1400 err = PTR_ERR(temp);
1401 goto free_debug_dir;
1402 }
1403
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301404 temp = debugfs_create_file("data", S_IRUSR | S_IWUSR, data->dir, data,
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301405 &debug_data_fops);
1406 if (temp == NULL || IS_ERR(temp)) {
1407 pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
1408 err = PTR_ERR(temp);
1409 goto free_debug_dir;
1410 }
1411
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301412 temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, data->dir,
1413 data, &debug_suspend_fops);
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301414 if (temp == NULL || IS_ERR(temp)) {
1415 pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
1416 err = PTR_ERR(temp);
1417 goto free_debug_dir;
1418 }
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301419
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301420 temp = debugfs_create_file("dump_info", S_IRUSR | S_IWUSR, data->dir,
1421 data, &debug_dump_info_fops);
1422 if (temp == NULL || IS_ERR(temp)) {
1423 pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
1424 err = PTR_ERR(temp);
1425 goto free_debug_dir;
1426 }
1427
1428 data->ts_info = kzalloc(FT_INFO_MAX_LEN, GFP_KERNEL);
1429 if (!data->ts_info) {
1430 dev_err(&client->dev, "Not enough memory\n");
1431 goto free_debug_dir;
1432 }
1433
1434 /*get some register information */
1435 reg_addr = FT_REG_POINT_RATE;
1436 ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
1437 if (err < 0)
1438 dev_err(&client->dev, "report rate read failed");
1439
1440 dev_info(&client->dev, "report rate = %dHz\n", reg_value * 10);
1441
1442 reg_addr = FT_REG_THGROUP;
1443 err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
1444 if (err < 0)
1445 dev_err(&client->dev, "threshold read failed");
1446
1447 dev_dbg(&client->dev, "touch threshold = %d\n", reg_value * 4);
1448
1449 reg_addr = FT_REG_FW_VER;
1450 err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
1451 if (err < 0)
1452 dev_err(&client->dev, "version read failed");
1453
1454 dev_info(&client->dev, "Firmware version = 0x%x\n", reg_value);
1455
1456 FT_STORE_TS_INFO(data->ts_info, data->family_id, reg_value);
1457
Mohan Pallakaa5d601b2013-05-10 15:34:44 +05301458#if defined(CONFIG_FB)
1459 data->fb_notif.notifier_call = fb_notifier_callback;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301460
Mohan Pallakaa5d601b2013-05-10 15:34:44 +05301461 err = fb_register_client(&data->fb_notif);
1462
1463 if (err)
1464 dev_err(&client->dev, "Unable to register fb_notifier: %d\n",
1465 err);
1466#elif defined(CONFIG_HAS_EARLYSUSPEND)
Mohan Pallakaa2595072012-01-12 22:23:15 +05301467 data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301468 FT_SUSPEND_LEVEL;
Mohan Pallakaa2595072012-01-12 22:23:15 +05301469 data->early_suspend.suspend = ft5x06_ts_early_suspend;
1470 data->early_suspend.resume = ft5x06_ts_late_resume;
1471 register_early_suspend(&data->early_suspend);
1472#endif
1473
1474 return 0;
1475
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301476free_debug_dir:
1477 debugfs_remove_recursive(data->dir);
1478free_force_update_fw_sys:
1479 device_remove_file(&client->dev, &dev_attr_force_update_fw);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301480free_update_fw_sys:
1481 device_remove_file(&client->dev, &dev_attr_update_fw);
1482free_fw_name_sys:
1483 device_remove_file(&client->dev, &dev_attr_fw_name);
1484irq_free:
1485 free_irq(client->irq, data);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301486free_reset_gpio:
1487 if (gpio_is_valid(pdata->reset_gpio))
1488 gpio_free(pdata->reset_gpio);
1489free_irq_gpio:
1490 if (gpio_is_valid(pdata->irq_gpio))
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301491 gpio_free(pdata->irq_gpio);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301492pwr_off:
1493 if (pdata->power_on)
1494 pdata->power_on(false);
1495 else
1496 ft5x06_power_on(data, false);
1497pwr_deinit:
1498 if (pdata->power_init)
1499 pdata->power_init(false);
1500 else
1501 ft5x06_power_init(data, false);
1502unreg_inputdev:
1503 input_unregister_device(input_dev);
1504 input_dev = NULL;
1505free_inputdev:
1506 input_free_device(input_dev);
1507free_mem:
1508 kfree(data);
1509 return err;
1510}
1511
1512static int __devexit ft5x06_ts_remove(struct i2c_client *client)
1513{
1514 struct ft5x06_ts_data *data = i2c_get_clientdata(client);
1515
Mohan Pallaka4fcf6f12013-06-07 17:47:42 +05301516 debugfs_remove_recursive(data->dir);
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301517 device_remove_file(&client->dev, &dev_attr_force_update_fw);
1518 device_remove_file(&client->dev, &dev_attr_update_fw);
1519 device_remove_file(&client->dev, &dev_attr_fw_name);
1520
Mohan Pallakaa5d601b2013-05-10 15:34:44 +05301521#if defined(CONFIG_FB)
1522 if (fb_unregister_client(&data->fb_notif))
1523 dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
1524#elif defined(CONFIG_HAS_EARLYSUSPEND)
Mohan Pallakaa2595072012-01-12 22:23:15 +05301525 unregister_early_suspend(&data->early_suspend);
1526#endif
1527 free_irq(client->irq, data);
1528
1529 if (gpio_is_valid(data->pdata->reset_gpio))
1530 gpio_free(data->pdata->reset_gpio);
1531
1532 if (gpio_is_valid(data->pdata->irq_gpio))
Mohan Pallaka6d2ab952013-06-04 17:36:20 +05301533 gpio_free(data->pdata->irq_gpio);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301534
1535 if (data->pdata->power_on)
1536 data->pdata->power_on(false);
1537 else
1538 ft5x06_power_on(data, false);
1539
1540 if (data->pdata->power_init)
1541 data->pdata->power_init(false);
1542 else
1543 ft5x06_power_init(data, false);
1544
1545 input_unregister_device(data->input_dev);
Mohan Pallaka768d5e32013-06-14 17:50:10 +05301546 kfree(data->ts_info);
Mohan Pallakaa2595072012-01-12 22:23:15 +05301547 kfree(data);
1548
1549 return 0;
1550}
1551
1552static const struct i2c_device_id ft5x06_ts_id[] = {
1553 {"ft5x06_ts", 0},
1554 {},
1555};
1556
1557MODULE_DEVICE_TABLE(i2c, ft5x06_ts_id);
1558
Mohan Pallaka3a138202013-05-09 16:30:00 +05301559#ifdef CONFIG_OF
1560static struct of_device_id ft5x06_match_table[] = {
1561 { .compatible = "focaltech,5x06",},
1562 { },
1563};
1564#else
1565#define ft5x06_match_table NULL
1566#endif
1567
Mohan Pallakaa2595072012-01-12 22:23:15 +05301568static struct i2c_driver ft5x06_ts_driver = {
1569 .probe = ft5x06_ts_probe,
1570 .remove = __devexit_p(ft5x06_ts_remove),
1571 .driver = {
1572 .name = "ft5x06_ts",
1573 .owner = THIS_MODULE,
Mohan Pallaka3a138202013-05-09 16:30:00 +05301574 .of_match_table = ft5x06_match_table,
Mohan Pallakaa2595072012-01-12 22:23:15 +05301575#ifdef CONFIG_PM
1576 .pm = &ft5x06_ts_pm_ops,
1577#endif
1578 },
1579 .id_table = ft5x06_ts_id,
1580};
1581
1582static int __init ft5x06_ts_init(void)
1583{
1584 return i2c_add_driver(&ft5x06_ts_driver);
1585}
1586module_init(ft5x06_ts_init);
1587
1588static void __exit ft5x06_ts_exit(void)
1589{
1590 i2c_del_driver(&ft5x06_ts_driver);
1591}
1592module_exit(ft5x06_ts_exit);
1593
1594MODULE_DESCRIPTION("FocalTech ft5x06 TouchScreen driver");
1595MODULE_LICENSE("GPL v2");