blob: c9905a4a87dfa3d2085487f9aeb0b7df0a67698b [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.
6 * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
7 *
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>
21#include <linux/slab.h>
22#include <linux/interrupt.h>
23#include <linux/delay.h>
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <linux/gpio.h>
27#include <linux/regulator/consumer.h>
28#include <linux/input/ft5x06_ts.h>
29
30#ifdef CONFIG_HAS_EARLYSUSPEND
31#include <linux/earlysuspend.h>
32/* Early-suspend level */
33#define FT5X06_SUSPEND_LEVEL 1
34#endif
35
36#define CFG_MAX_TOUCH_POINTS 5
37
38#define FT_STARTUP_DLY 150
39#define FT_RESET_DLY 20
40
41#define FT_PRESS 0x7F
42#define FT_MAX_ID 0x0F
43#define FT_TOUCH_STEP 6
44#define FT_TOUCH_X_H_POS 3
45#define FT_TOUCH_X_L_POS 4
46#define FT_TOUCH_Y_H_POS 5
47#define FT_TOUCH_Y_L_POS 6
48#define FT_TOUCH_EVENT_POS 3
49#define FT_TOUCH_ID_POS 5
50
51#define POINT_READ_BUF (3 + FT_TOUCH_STEP * CFG_MAX_TOUCH_POINTS)
52
53/*register address*/
54#define FT5X06_REG_PMODE 0xA5
55#define FT5X06_REG_FW_VER 0xA6
56#define FT5X06_REG_POINT_RATE 0x88
57#define FT5X06_REG_THGROUP 0x80
58
59/* power register bits*/
60#define FT5X06_PMODE_ACTIVE 0x00
61#define FT5X06_PMODE_MONITOR 0x01
62#define FT5X06_PMODE_STANDBY 0x02
63#define FT5X06_PMODE_HIBERNATE 0x03
64
65#define FT5X06_VTG_MIN_UV 2600000
66#define FT5X06_VTG_MAX_UV 3300000
67#define FT5X06_I2C_VTG_MIN_UV 1800000
68#define FT5X06_I2C_VTG_MAX_UV 1800000
69
70struct ts_event {
71 u16 x[CFG_MAX_TOUCH_POINTS]; /*x coordinate */
72 u16 y[CFG_MAX_TOUCH_POINTS]; /*y coordinate */
73 /* touch event: 0 -- down; 1-- contact; 2 -- contact */
74 u8 touch_event[CFG_MAX_TOUCH_POINTS];
75 u8 finger_id[CFG_MAX_TOUCH_POINTS]; /*touch ID */
76 u16 pressure;
77 u8 touch_point;
78};
79
80struct ft5x06_ts_data {
81 struct i2c_client *client;
82 struct input_dev *input_dev;
83 struct ts_event event;
84 const struct ft5x06_ts_platform_data *pdata;
85 struct regulator *vdd;
86 struct regulator *vcc_i2c;
87#ifdef CONFIG_HAS_EARLYSUSPEND
88 struct early_suspend early_suspend;
89#endif
90};
91
92static int ft5x06_i2c_read(struct i2c_client *client, char *writebuf,
93 int writelen, char *readbuf, int readlen)
94{
95 int ret;
96
97 if (writelen > 0) {
98 struct i2c_msg msgs[] = {
99 {
100 .addr = client->addr,
101 .flags = 0,
102 .len = writelen,
103 .buf = writebuf,
104 },
105 {
106 .addr = client->addr,
107 .flags = I2C_M_RD,
108 .len = readlen,
109 .buf = readbuf,
110 },
111 };
112 ret = i2c_transfer(client->adapter, msgs, 2);
113 if (ret < 0)
114 dev_err(&client->dev, "%s: i2c read error.\n",
115 __func__);
116 } else {
117 struct i2c_msg msgs[] = {
118 {
119 .addr = client->addr,
120 .flags = I2C_M_RD,
121 .len = readlen,
122 .buf = readbuf,
123 },
124 };
125 ret = i2c_transfer(client->adapter, msgs, 1);
126 if (ret < 0)
127 dev_err(&client->dev, "%s:i2c read error.\n", __func__);
128 }
129 return ret;
130}
131
132static int ft5x06_i2c_write(struct i2c_client *client, char *writebuf,
133 int writelen)
134{
135 int ret;
136
137 struct i2c_msg msgs[] = {
138 {
139 .addr = client->addr,
140 .flags = 0,
141 .len = writelen,
142 .buf = writebuf,
143 },
144 };
145 ret = i2c_transfer(client->adapter, msgs, 1);
146 if (ret < 0)
147 dev_err(&client->dev, "%s: i2c write error.\n", __func__);
148
149 return ret;
150}
151
152static void ft5x06_report_value(struct ft5x06_ts_data *data)
153{
154 struct ts_event *event = &data->event;
155 int i;
156 int fingerdown = 0;
157
158 for (i = 0; i < event->touch_point; i++) {
159 if (event->touch_event[i] == 0 || event->touch_event[i] == 2) {
160 event->pressure = FT_PRESS;
161 fingerdown++;
162 } else {
163 event->pressure = 0;
164 }
165
166 input_report_abs(data->input_dev, ABS_MT_POSITION_X,
167 event->x[i]);
168 input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
169 event->y[i]);
170 input_report_abs(data->input_dev, ABS_MT_PRESSURE,
171 event->pressure);
172 input_report_abs(data->input_dev, ABS_MT_TRACKING_ID,
173 event->finger_id[i]);
174 input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR,
175 event->pressure);
176 input_mt_sync(data->input_dev);
177 }
178
179 input_report_key(data->input_dev, BTN_TOUCH, !!fingerdown);
180 input_sync(data->input_dev);
181}
182
183static int ft5x06_handle_touchdata(struct ft5x06_ts_data *data)
184{
185 struct ts_event *event = &data->event;
186 int ret, i;
187 u8 buf[POINT_READ_BUF] = { 0 };
188 u8 pointid = FT_MAX_ID;
189
190 ret = ft5x06_i2c_read(data->client, buf, 1, buf, POINT_READ_BUF);
191 if (ret < 0) {
192 dev_err(&data->client->dev, "%s read touchdata failed.\n",
193 __func__);
194 return ret;
195 }
196 memset(event, 0, sizeof(struct ts_event));
197
198 event->touch_point = 0;
199 for (i = 0; i < CFG_MAX_TOUCH_POINTS; i++) {
200 pointid = (buf[FT_TOUCH_ID_POS + FT_TOUCH_STEP * i]) >> 4;
201 if (pointid >= FT_MAX_ID)
202 break;
203 else
204 event->touch_point++;
205 event->x[i] =
206 (s16) (buf[FT_TOUCH_X_H_POS + FT_TOUCH_STEP * i] & 0x0F) <<
207 8 | (s16) buf[FT_TOUCH_X_L_POS + FT_TOUCH_STEP * i];
208 event->y[i] =
209 (s16) (buf[FT_TOUCH_Y_H_POS + FT_TOUCH_STEP * i] & 0x0F) <<
210 8 | (s16) buf[FT_TOUCH_Y_L_POS + FT_TOUCH_STEP * i];
211 event->touch_event[i] =
212 buf[FT_TOUCH_EVENT_POS + FT_TOUCH_STEP * i] >> 6;
213 event->finger_id[i] =
214 (buf[FT_TOUCH_ID_POS + FT_TOUCH_STEP * i]) >> 4;
215 }
216
217 ft5x06_report_value(data);
218
219 return 0;
220}
221
222static irqreturn_t ft5x06_ts_interrupt(int irq, void *dev_id)
223{
224 struct ft5x06_ts_data *data = dev_id;
225 int rc;
226
227 rc = ft5x06_handle_touchdata(data);
228 if (rc)
229 pr_err("%s: handling touchdata failed\n", __func__);
230
231 return IRQ_HANDLED;
232}
233
234static int ft5x06_power_on(struct ft5x06_ts_data *data, bool on)
235{
236 int rc;
237
238 if (!on)
239 goto power_off;
240
241 rc = regulator_enable(data->vdd);
242 if (rc) {
243 dev_err(&data->client->dev,
244 "Regulator vdd enable failed rc=%d\n", rc);
245 return rc;
246 }
247
248 rc = regulator_enable(data->vcc_i2c);
249 if (rc) {
250 dev_err(&data->client->dev,
251 "Regulator vcc_i2c enable failed rc=%d\n", rc);
252 regulator_disable(data->vdd);
253 }
254
255 return rc;
256
257power_off:
258 rc = regulator_disable(data->vdd);
259 if (rc) {
260 dev_err(&data->client->dev,
261 "Regulator vdd disable failed rc=%d\n", rc);
262 return rc;
263 }
264
265 rc = regulator_disable(data->vcc_i2c);
266 if (rc) {
267 dev_err(&data->client->dev,
268 "Regulator vcc_i2c disable failed rc=%d\n", rc);
269 regulator_enable(data->vdd);
270 }
271
272 return rc;
273}
274
275static int ft5x06_power_init(struct ft5x06_ts_data *data, bool on)
276{
277 int rc;
278
279 if (!on)
280 goto pwr_deinit;
281
282 data->vdd = regulator_get(&data->client->dev, "vdd");
283 if (IS_ERR(data->vdd)) {
284 rc = PTR_ERR(data->vdd);
285 dev_err(&data->client->dev,
286 "Regulator get failed vdd rc=%d\n", rc);
287 return rc;
288 }
289
290 if (regulator_count_voltages(data->vdd) > 0) {
291 rc = regulator_set_voltage(data->vdd, FT5X06_VTG_MIN_UV,
292 FT5X06_VTG_MAX_UV);
293 if (rc) {
294 dev_err(&data->client->dev,
295 "Regulator set_vtg failed vdd rc=%d\n", rc);
296 goto reg_vdd_put;
297 }
298 }
299
300 data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c");
301 if (IS_ERR(data->vcc_i2c)) {
302 rc = PTR_ERR(data->vcc_i2c);
303 dev_err(&data->client->dev,
304 "Regulator get failed vcc_i2c rc=%d\n", rc);
305 goto reg_vdd_set_vtg;
306 }
307
308 if (regulator_count_voltages(data->vcc_i2c) > 0) {
309 rc = regulator_set_voltage(data->vcc_i2c, FT5X06_I2C_VTG_MIN_UV,
310 FT5X06_I2C_VTG_MAX_UV);
311 if (rc) {
312 dev_err(&data->client->dev,
313 "Regulator set_vtg failed vcc_i2c rc=%d\n", rc);
314 goto reg_vcc_i2c_put;
315 }
316 }
317
318 return 0;
319
320reg_vcc_i2c_put:
321 regulator_put(data->vcc_i2c);
322reg_vdd_set_vtg:
323 if (regulator_count_voltages(data->vdd) > 0)
324 regulator_set_voltage(data->vdd, 0, FT5X06_VTG_MAX_UV);
325reg_vdd_put:
326 regulator_put(data->vdd);
327 return rc;
328
329pwr_deinit:
330 if (regulator_count_voltages(data->vdd) > 0)
331 regulator_set_voltage(data->vdd, 0, FT5X06_VTG_MAX_UV);
332
333 regulator_put(data->vdd);
334
335 if (regulator_count_voltages(data->vcc_i2c) > 0)
336 regulator_set_voltage(data->vcc_i2c, 0, FT5X06_I2C_VTG_MAX_UV);
337
338 regulator_put(data->vcc_i2c);
339 return 0;
340}
341
342#ifdef CONFIG_PM
343static int ft5x06_ts_suspend(struct device *dev)
344{
345 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
346 char txbuf[2];
347
348 disable_irq(data->client->irq);
349
350 if (gpio_is_valid(data->pdata->reset_gpio)) {
351 txbuf[0] = FT5X06_REG_PMODE;
352 txbuf[1] = FT5X06_PMODE_HIBERNATE;
353 ft5x06_i2c_write(data->client, txbuf, sizeof(txbuf));
354 }
355
356 return 0;
357}
358
359static int ft5x06_ts_resume(struct device *dev)
360{
361 struct ft5x06_ts_data *data = dev_get_drvdata(dev);
362
363 if (gpio_is_valid(data->pdata->reset_gpio)) {
364 gpio_set_value_cansleep(data->pdata->reset_gpio, 0);
365 msleep(FT_RESET_DLY);
366 gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
367 }
368 enable_irq(data->client->irq);
369
370 return 0;
371}
372
373#ifdef CONFIG_HAS_EARLYSUSPEND
374static void ft5x06_ts_early_suspend(struct early_suspend *handler)
375{
376 struct ft5x06_ts_data *data = container_of(handler,
377 struct ft5x06_ts_data,
378 early_suspend);
379
380 ft5x06_ts_suspend(&data->client->dev);
381}
382
383static void ft5x06_ts_late_resume(struct early_suspend *handler)
384{
385 struct ft5x06_ts_data *data = container_of(handler,
386 struct ft5x06_ts_data,
387 early_suspend);
388
389 ft5x06_ts_resume(&data->client->dev);
390}
391#endif
392
393static const struct dev_pm_ops ft5x06_ts_pm_ops = {
394#ifndef CONFIG_HAS_EARLYSUSPEND
395 .suspend = ft5x06_ts_suspend,
396 .resume = ft5x06_ts_resume,
397#endif
398};
399#endif
400
401static int ft5x06_ts_probe(struct i2c_client *client,
402 const struct i2c_device_id *id)
403{
404 const struct ft5x06_ts_platform_data *pdata = client->dev.platform_data;
405 struct ft5x06_ts_data *data;
406 struct input_dev *input_dev;
407 u8 reg_value;
408 u8 reg_addr;
409 int err;
410
411 if (!pdata) {
412 dev_err(&client->dev, "Invalid pdata\n");
413 return -EINVAL;
414 }
415
416 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
417 dev_err(&client->dev, "I2C not supported\n");
418 return -ENODEV;
419 }
420
421 data = kzalloc(sizeof(struct ft5x06_ts_data), GFP_KERNEL);
422 if (!data) {
423 dev_err(&client->dev, "Not enough memory\n");
424 return -ENOMEM;
425 }
426
427 input_dev = input_allocate_device();
428 if (!input_dev) {
429 err = -ENOMEM;
430 dev_err(&client->dev, "failed to allocate input device\n");
431 goto free_mem;
432 }
433
434 data->input_dev = input_dev;
435 data->client = client;
436 data->pdata = pdata;
437
438 input_dev->name = "ft5x06_ts";
439 input_dev->id.bustype = BUS_I2C;
440 input_dev->dev.parent = &client->dev;
441
442 input_set_drvdata(input_dev, data);
443 i2c_set_clientdata(client, data);
444
445 __set_bit(EV_KEY, input_dev->evbit);
446 __set_bit(EV_ABS, input_dev->evbit);
447 __set_bit(BTN_TOUCH, input_dev->keybit);
448
449 input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0,
450 pdata->x_max, 0, 0);
451 input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0,
452 pdata->y_max, 0, 0);
453 input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0,
454 CFG_MAX_TOUCH_POINTS, 0, 0);
455 input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, FT_PRESS, 0, 0);
456 input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, FT_PRESS, 0, 0);
457
458 err = input_register_device(input_dev);
459 if (err) {
460 dev_err(&client->dev, "Input device registration failed\n");
461 goto free_inputdev;
462 }
463
464 if (pdata->power_init) {
465 err = pdata->power_init(true);
466 if (err) {
467 dev_err(&client->dev, "power init failed");
468 goto unreg_inputdev;
469 }
470 } else {
471 err = ft5x06_power_init(data, true);
472 if (err) {
473 dev_err(&client->dev, "power init failed");
474 goto unreg_inputdev;
475 }
476 }
477
478 if (pdata->power_on) {
479 err = pdata->power_on(true);
480 if (err) {
481 dev_err(&client->dev, "power on failed");
482 goto pwr_deinit;
483 }
484 } else {
485 err = ft5x06_power_on(data, true);
486 if (err) {
487 dev_err(&client->dev, "power on failed");
488 goto pwr_deinit;
489 }
490 }
491
492 if (gpio_is_valid(pdata->irq_gpio)) {
493 err = gpio_request(pdata->irq_gpio, "ft5x06_irq_gpio");
494 if (err) {
495 dev_err(&client->dev, "irq gpio request failed");
496 goto pwr_off;
497 }
498 err = gpio_direction_input(pdata->irq_gpio);
499 if (err) {
500 dev_err(&client->dev,
501 "set_direction for irq gpio failed\n");
502 goto free_irq_gpio;
503 }
504 }
505
506 if (gpio_is_valid(pdata->reset_gpio)) {
507 err = gpio_request(pdata->reset_gpio, "ft5x06_reset_gpio");
508 if (err) {
509 dev_err(&client->dev, "reset gpio request failed");
510 goto free_irq_gpio;
511 }
512
513 err = gpio_direction_output(pdata->reset_gpio, 0);
514 if (err) {
515 dev_err(&client->dev,
516 "set_direction for reset gpio failed\n");
517 goto free_reset_gpio;
518 }
519 msleep(FT_RESET_DLY);
520 gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
521 }
522
523 /* make sure CTP already finish startup process */
524 msleep(FT_STARTUP_DLY);
525
526 /*get some register information */
527 reg_addr = FT5X06_REG_FW_VER;
528 err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
529 if (err)
530 dev_err(&client->dev, "version read failed");
531
532 dev_info(&client->dev, "[FTS] Firmware version = 0x%x\n", reg_value);
533
534 reg_addr = FT5X06_REG_POINT_RATE;
535 ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
536 if (err)
537 dev_err(&client->dev, "report rate read failed");
538 dev_info(&client->dev, "[FTS] report rate is %dHz.\n", reg_value * 10);
539
540 reg_addr = FT5X06_REG_THGROUP;
541 err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
542 if (err)
543 dev_err(&client->dev, "threshold read failed");
544 dev_dbg(&client->dev, "[FTS] touch threshold is %d.\n", reg_value * 4);
545
546 err = request_threaded_irq(client->irq, NULL,
547 ft5x06_ts_interrupt, pdata->irqflags,
548 client->dev.driver->name, data);
549 if (err) {
550 dev_err(&client->dev, "request irq failed\n");
551 goto free_reset_gpio;
552 }
553
554#ifdef CONFIG_HAS_EARLYSUSPEND
555 data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
556 FT5X06_SUSPEND_LEVEL;
557 data->early_suspend.suspend = ft5x06_ts_early_suspend;
558 data->early_suspend.resume = ft5x06_ts_late_resume;
559 register_early_suspend(&data->early_suspend);
560#endif
561
562 return 0;
563
564free_reset_gpio:
565 if (gpio_is_valid(pdata->reset_gpio))
566 gpio_free(pdata->reset_gpio);
567free_irq_gpio:
568 if (gpio_is_valid(pdata->irq_gpio))
569 gpio_free(pdata->reset_gpio);
570pwr_off:
571 if (pdata->power_on)
572 pdata->power_on(false);
573 else
574 ft5x06_power_on(data, false);
575pwr_deinit:
576 if (pdata->power_init)
577 pdata->power_init(false);
578 else
579 ft5x06_power_init(data, false);
580unreg_inputdev:
581 input_unregister_device(input_dev);
582 input_dev = NULL;
583free_inputdev:
584 input_free_device(input_dev);
585free_mem:
586 kfree(data);
587 return err;
588}
589
590static int __devexit ft5x06_ts_remove(struct i2c_client *client)
591{
592 struct ft5x06_ts_data *data = i2c_get_clientdata(client);
593
594#ifdef CONFIG_HAS_EARLYSUSPEND
595 unregister_early_suspend(&data->early_suspend);
596#endif
597 free_irq(client->irq, data);
598
599 if (gpio_is_valid(data->pdata->reset_gpio))
600 gpio_free(data->pdata->reset_gpio);
601
602 if (gpio_is_valid(data->pdata->irq_gpio))
603 gpio_free(data->pdata->reset_gpio);
604
605 if (data->pdata->power_on)
606 data->pdata->power_on(false);
607 else
608 ft5x06_power_on(data, false);
609
610 if (data->pdata->power_init)
611 data->pdata->power_init(false);
612 else
613 ft5x06_power_init(data, false);
614
615 input_unregister_device(data->input_dev);
616 kfree(data);
617
618 return 0;
619}
620
621static const struct i2c_device_id ft5x06_ts_id[] = {
622 {"ft5x06_ts", 0},
623 {},
624};
625
626MODULE_DEVICE_TABLE(i2c, ft5x06_ts_id);
627
628static struct i2c_driver ft5x06_ts_driver = {
629 .probe = ft5x06_ts_probe,
630 .remove = __devexit_p(ft5x06_ts_remove),
631 .driver = {
632 .name = "ft5x06_ts",
633 .owner = THIS_MODULE,
634#ifdef CONFIG_PM
635 .pm = &ft5x06_ts_pm_ops,
636#endif
637 },
638 .id_table = ft5x06_ts_id,
639};
640
641static int __init ft5x06_ts_init(void)
642{
643 return i2c_add_driver(&ft5x06_ts_driver);
644}
645module_init(ft5x06_ts_init);
646
647static void __exit ft5x06_ts_exit(void)
648{
649 i2c_del_driver(&ft5x06_ts_driver);
650}
651module_exit(ft5x06_ts_exit);
652
653MODULE_DESCRIPTION("FocalTech ft5x06 TouchScreen driver");
654MODULE_LICENSE("GPL v2");