import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / input / touchscreen / mediatek / cy8ctma / cyttsp4_btn.c
1 /* BEGIN PN:DTS2013051703879 ,Added by l00184147, 2013/5/17*/
2 //add Touch driver for G610-T11
3 /* BEGIN PN:DTS2013012601133 ,Modified by l00184147, 2013/1/26*/
4 /* BEGIN PN:SPBB-1218 ,Added by l00184147, 2012/12/20*/
5 #define DEBUG
6
7 /*
8 * cyttsp4_btn.c
9 * Cypress TrueTouch(TM) Standard Product V4 CapSense touch reports module.
10 * For use with Cypress Txx4xx parts.
11 * Supported parts include:
12 * TMA4XX
13 * TMA1036
14 *
15 * Copyright (C) 2012 Cypress Semiconductor
16 * Copyright (C) 2011 Sony Ericsson Mobile Communications AB.
17 *
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * version 2, and only version 2, as published by the
21 * Free Software Foundation.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License along
29 * with this program; if not, write to the Free Software Foundation, Inc.,
30 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
31 *
32 * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com>
33 *
34 */
35
36 #include "cyttsp4_bus.h"
37
38 #include <linux/delay.h>
39 #ifdef CONFIG_HAS_EARLYSUSPEND
40 #include <linux/earlysuspend.h>
41 #endif
42 #include <linux/gpio.h>
43 #include <linux/input.h>
44 #include <linux/interrupt.h>
45 #include <linux/irq.h>
46 #include <linux/limits.h>
47 #include <linux/module.h>
48 #include <linux/pm_runtime.h>
49 #include <linux/slab.h>
50 #include <linux/workqueue.h>
51
52 #include "cyttsp4_btn.h"
53 #include "cyttsp4_core.h"
54 #include "cyttsp4_regs.h"
55
56 struct cyttsp4_btn_data {
57 struct cyttsp4_device *ttsp;
58 struct cyttsp4_btn_platform_data *pdata;
59 struct cyttsp4_sysinfo *si;
60 struct input_dev *input;
61 #ifdef CONFIG_HAS_EARLYSUSPEND
62 struct early_suspend es;
63 bool is_suspended;
64 #endif
65 /* BEGIN PN:DTS2013041400018 ,Added by l00184147, 2013/4/12*/
66 struct mutex report_lock;
67 /* END PN:DTS2013041400018 ,Added by l00184147, 2013/4/12*/
68 bool input_device_registered;
69 char phys[NAME_MAX];
70 u8 pr_buf[CY_MAX_PRBUF_SIZE];
71 };
72
73 static void cyttsp4_btn_key_action(struct cyttsp4_btn_data *bd,
74 int cur_btn, u8 cur_btn_mask, int num_btns, int new_btn_state)
75 {
76 struct device *dev = &bd->ttsp->dev;
77 struct cyttsp4_sysinfo *si = bd->si;
78 int btn;
79 int cur_btn_state;
80
81 cur_btn_state = new_btn_state == CY_BTN_PRESSED ? CY_BTN_RELEASED :
82 CY_BTN_PRESSED;
83
84 for (btn = 0; btn < num_btns; btn++) {
85 if ((si->btn[cur_btn + btn].enabled) &&
86 (((cur_btn_mask >> (btn * CY_BITS_PER_BTN)) &
87 (CY_NUM_BTN_EVENT_ID - 1)) == new_btn_state) &&
88 (si->btn[cur_btn + btn].state == cur_btn_state)) {
89 input_report_key(bd->input, si->btn
90 [cur_btn + btn].key_code, new_btn_state);
91 si->btn[cur_btn + btn].state = new_btn_state;
92 input_sync(bd->input);
93 dev_dbg(dev, "%s: btn=%d key_code=%d %s\n", __func__,
94 cur_btn + btn, si->btn[cur_btn + btn].key_code,
95 new_btn_state == CY_BTN_PRESSED ?
96 "PRESSED" : "RELEASED");
97 }
98 }
99 return;
100 }
101
102 static void cyttsp4_get_btn_touches(struct cyttsp4_btn_data *bd)
103 {
104 enum cyttsp4_btn_state btn_state = CY_BTN_RELEASED;
105 struct cyttsp4_sysinfo *si = bd->si;
106 int num_btn;
107 int num_cur_btn;
108 int cur_reg;
109 int cur_btn;
110 u8 cur_btn_mask;
111
112 for (btn_state = CY_BTN_RELEASED; btn_state < CY_BTN_NUM_STATE;
113 btn_state++) {
114 for (cur_reg = cur_btn = 0, num_cur_btn = si->si_ofs.num_btns;
115 cur_reg < si->si_ofs.num_btn_regs;
116 cur_reg++, cur_btn += CY_NUM_BTN_PER_REG,
117 num_cur_btn -= CY_NUM_BTN_PER_REG) {
118 if (num_cur_btn > 0) {
119 cur_btn_mask = si->xy_mode[si->si_ofs.rep_ofs +
120 2 + cur_reg];
121 num_btn = num_cur_btn / CY_NUM_BTN_PER_REG ?
122 CY_NUM_BTN_PER_REG : num_cur_btn;
123 cyttsp4_btn_key_action(bd, cur_btn,
124 cur_btn_mask, num_btn, btn_state);
125 }
126 }
127 }
128 return;
129 }
130
131 static void cyttsp4_btn_lift_all(struct cyttsp4_btn_data *bd)
132 {
133 struct cyttsp4_sysinfo *si = bd->si;
134 int btn_reg;
135 int num_regs;
136 /* BEGIN PN:DTS2013041400018 ,Modified by l00184147, 2013/4/12*/
137 if (!si || si->si_ofs.num_btns == 0)
138 /* END PN:DTS2013041400018 ,Modified by l00184147, 2013/4/12*/
139 return;
140
141 num_regs = (si->si_ofs.num_btns + CY_NUM_BTN_PER_REG - 1)
142 / CY_NUM_BTN_PER_REG;
143
144 for (btn_reg = 0; btn_reg < num_regs; btn_reg++)
145 si->xy_mode[si->si_ofs.rep_ofs + 2 + btn_reg] = 0;
146
147 cyttsp4_get_btn_touches(bd);
148 }
149
150 #ifdef VERBOSE_DEBUG
151 static void cyttsp4_log_btn_data(struct cyttsp4_btn_data *bd)
152 {
153 struct device *dev = &bd->ttsp->dev;
154 struct cyttsp4_sysinfo *si = bd->si;
155 int cur;
156 int t;
157
158 for (cur = 0; cur < si->si_ofs.num_btns; cur++) {
159 bd->pr_buf[0] = 0;
160 snprintf(bd->pr_buf, CY_MAX_PRBUF_SIZE, "btn_rec[%d]=0x", cur);
161 for (t = 0; t < si->si_ofs.btn_rec_size; t++)
162 snprintf(bd->pr_buf, CY_MAX_PRBUF_SIZE, "%s%02X",
163 bd->pr_buf, si->btn_rec_data
164 [(cur * si->si_ofs.btn_rec_size) + t]);
165
166 dev_vdbg(dev, "%s: %s\n", __func__, bd->pr_buf);
167 }
168 return;
169 }
170 #endif
171
172 /* read xy_data for all current CapSense button touches */
173 static int cyttsp4_xy_worker(struct cyttsp4_btn_data *bd)
174 {
175 struct device *dev = &bd->ttsp->dev;
176 struct cyttsp4_sysinfo *si = bd->si;
177 u8 rep_stat = si->xy_mode[si->si_ofs.rep_ofs + 1];
178 #ifdef VERBOSE_DEBUG
179 int rc;
180 #endif
181
182 /* rep_data for bad packet check */
183 if (IS_BAD_PKT(rep_stat)) {
184 dev_dbg(dev, "%s: Invalid buffer detected\n", __func__);
185 return 0;
186 }
187
188 /* extract button press/release touch information */
189 if (si->si_ofs.num_btns > 0) {
190 cyttsp4_get_btn_touches(bd);
191 #ifdef VERBOSE_DEBUG
192 /* read button diff data */
193 rc = cyttsp4_read(bd->ttsp, CY_MODE_OPERATIONAL,
194 si->si_ofs.tt_stat_ofs + 1 +
195 si->si_ofs.max_tchs * si->si_ofs.tch_rec_size,
196 si->btn_rec_data,
197 si->si_ofs.num_btns * si->si_ofs.btn_rec_size);
198 if (rc < 0) {
199 dev_err(dev, "%s: read fail on button regs r=%d\n",
200 __func__, rc);
201 return 0;
202 }
203
204 /* log button press/release touch information */
205 cyttsp4_log_btn_data(bd);
206 #endif
207 }
208
209 dev_vdbg(dev, "%s: done\n", __func__);
210
211 return 0;
212 }
213
214 static int cyttsp4_btn_attention(struct cyttsp4_device *ttsp)
215 {
216 struct device *dev = &ttsp->dev;
217 struct cyttsp4_btn_data *bd = dev_get_drvdata(dev);
218 int rc = 0;
219
220 dev_vdbg(dev, "%s\n", __func__);
221
222 /* BEGIN PN:DTS2013041400018 ,Modified by l00184147, 2013/4/12*/
223 mutex_lock(&bd->report_lock);
224 if (!bd->is_suspended) {
225 /* core handles handshake */
226 rc = cyttsp4_xy_worker(bd);
227 } else {
228 dev_vdbg(dev, "%s: Ignoring report while suspended\n",
229 __func__);
230 }
231 mutex_unlock(&bd->report_lock);
232 /* BEGIN PN:DTS2013041400018 ,Modified by l00184147, 2013/4/12*/
233 if (rc < 0)
234 dev_err(dev, "%s: xy_worker error r=%d\n", __func__, rc);
235
236 return rc;
237 }
238
239 static int cyttsp4_startup_attention(struct cyttsp4_device *ttsp)
240 {
241 struct device *dev = &ttsp->dev;
242 struct cyttsp4_btn_data *bd = dev_get_drvdata(dev);
243 struct cyttsp4_sysinfo *si = bd->si;
244 int btn;
245
246 dev_vdbg(dev, "%s\n", __func__);
247
248 for (btn = 0; btn < si->si_ofs.num_btns; btn++)
249 bd->si->btn[btn].state = CY_BTN_RELEASED;
250
251 return 0;
252 }
253
254 int cyttsp4_btn_open(struct input_dev *input)
255 {
256 struct device *dev = input->dev.parent;
257 struct cyttsp4_device *ttsp =
258 container_of(dev, struct cyttsp4_device, dev);
259
260 dev_dbg(dev, "%s\n", __func__);
261
262 pm_runtime_get(dev);
263
264 dev_vdbg(dev, "%s: setup subscriptions\n", __func__);
265
266 /* set up touch call back */
267 cyttsp4_subscribe_attention(ttsp, CY_ATTEN_IRQ,
268 cyttsp4_btn_attention, CY_MODE_OPERATIONAL);
269
270 /* set up startup call back */
271 cyttsp4_subscribe_attention(ttsp, CY_ATTEN_STARTUP,
272 cyttsp4_startup_attention, 0);
273
274 return 0;
275 }
276
277 void cyttsp4_btn_close(struct input_dev *input)
278 {
279 struct device *dev = input->dev.parent;
280 /* BEGIN PN:DTS2013041400018 ,Deleted by l00184147, 2013/4/12*/
281 /* END PN:DTS2013041400018 ,Deleted by l00184147, 2013/4/12*/
282 struct cyttsp4_device *ttsp =
283 container_of(dev, struct cyttsp4_device, dev);
284
285 dev_dbg(dev, "%s\n", __func__);
286
287 /* BEGIN PN:DTS2013041400018 ,Deleted by l00184147, 2013/4/12*/
288 /* END PN:DTS2013041400018 ,Deleted by l00184147, 2013/4/12*/
289
290 cyttsp4_unsubscribe_attention(ttsp, CY_ATTEN_IRQ,
291 cyttsp4_btn_attention, CY_MODE_OPERATIONAL);
292
293 cyttsp4_unsubscribe_attention(ttsp, CY_ATTEN_STARTUP,
294 cyttsp4_startup_attention, 0);
295
296 pm_runtime_put(dev);
297 }
298
299 #ifdef CONFIG_HAS_EARLYSUSPEND
300 static void cyttsp4_btn_early_suspend(struct early_suspend *h)
301 {
302 struct cyttsp4_btn_data *bd =
303 container_of(h, struct cyttsp4_btn_data, es);
304 struct device *dev = &bd->ttsp->dev;
305
306 dev_dbg(dev, "%s\n", __func__);
307
308 /* BEGIN PN:DTS2013041400018 ,Modified by l00184147, 2013/4/12*/
309 if (bd->si){
310 mutex_lock(&bd->report_lock);
311 bd->is_suspended = true;
312 cyttsp4_btn_lift_all(bd);
313 mutex_unlock(&bd->report_lock);
314 }
315 /* END PN:DTS2013041400018 ,Modified by l00184147, 2013/4/12*/
316 }
317
318 static void cyttsp4_btn_late_resume(struct early_suspend *h)
319 {
320 struct cyttsp4_btn_data *bd =
321 container_of(h, struct cyttsp4_btn_data, es);
322 struct device *dev = &bd->ttsp->dev;
323
324 dev_dbg(dev, "%s\n", __func__);
325
326 /* BEGIN PN:DTS2013041400018 ,Modified by l00184147, 2013/4/12*/
327 mutex_lock(&bd->report_lock);
328 bd->is_suspended = false;
329 mutex_unlock(&bd->report_lock);
330 /* END PN:DTS2013041400018 ,Modified by l00184147, 2013/4/12*/
331 }
332 #endif
333
334 #ifdef CONFIG_PM_RUNTIME
335 static int cyttsp4_btn_suspend(struct device *dev)
336 {
337 struct cyttsp4_btn_data *bd = dev_get_drvdata(dev);
338
339 dev_dbg(dev, "%s\n", __func__);
340
341 if (bd->si)
342 cyttsp4_btn_lift_all(bd);
343 return 0;
344 }
345
346 static int cyttsp4_btn_resume(struct device *dev)
347 {
348 dev_dbg(dev, "%s\n", __func__);
349
350 return 0;
351 }
352 #endif
353
354 static const struct dev_pm_ops cyttsp4_btn_pm_ops = {
355 SET_RUNTIME_PM_OPS(cyttsp4_btn_suspend, cyttsp4_btn_resume, NULL)
356 };
357
358 static int cyttsp4_setup_input_device(struct cyttsp4_device *ttsp)
359 {
360 struct device *dev = &ttsp->dev;
361 struct cyttsp4_btn_data *bd = dev_get_drvdata(dev);
362 int i;
363 int rc;
364
365 dev_vdbg(dev, "%s: Initialize event signals\n", __func__);
366 __set_bit(EV_KEY, bd->input->evbit);
367 for (i = 0; i < bd->si->si_ofs.num_btns; i++)
368 __set_bit(bd->si->btn[i].key_code, bd->input->keybit);
369
370 rc = input_register_device(bd->input);
371 if (rc < 0)
372 dev_err(dev, "%s: Error, failed register input device r=%d\n",
373 __func__, rc);
374 else
375 bd->input_device_registered = true;
376
377 return rc;
378 }
379
380 static int cyttsp4_setup_input_attention(struct cyttsp4_device *ttsp)
381 {
382 struct device *dev = &ttsp->dev;
383 struct cyttsp4_btn_data *bd = dev_get_drvdata(dev);
384 int rc;
385
386 dev_vdbg(dev, "%s\n", __func__);
387
388 bd->si = cyttsp4_request_sysinfo(ttsp);
389 if (!bd->si)
390 return -1;
391
392 rc = cyttsp4_setup_input_device(ttsp);
393
394 cyttsp4_unsubscribe_attention(ttsp, CY_ATTEN_STARTUP,
395 cyttsp4_setup_input_attention, 0);
396
397 return rc;
398 }
399
400 static int cyttsp4_btn_probe(struct cyttsp4_device *ttsp)
401 {
402 struct cyttsp4_btn_data *bd;
403 struct device *dev = &ttsp->dev;
404 struct cyttsp4_btn_platform_data *pdata = dev_get_platdata(dev);
405 int rc = 0;
406
407 dev_info(dev, "%s\n", __func__);
408 dev_dbg(dev, "%s: debug on\n", __func__);
409 dev_vdbg(dev, "%s: verbose debug on\n", __func__);
410
411 if (pdata == NULL) {
412 dev_err(dev, "%s: Missing platform data\n", __func__);
413 rc = -ENODEV;
414 goto error_no_pdata;
415 }
416
417 bd = kzalloc(sizeof(*bd), GFP_KERNEL);
418 if (bd == NULL) {
419 dev_err(dev, "%s: Error, kzalloc\n", __func__);
420 rc = -ENOMEM;
421 goto error_alloc_data_failed;
422 }
423 /* BEGIN PN:DTS2013041400018 ,Added by l00184147, 2013/4/12*/
424 mutex_init(&bd->report_lock);
425 /* END PN:DTS2013041400018 ,Added by l00184147, 2013/4/12*/
426 bd->ttsp = ttsp;
427 bd->pdata = pdata;
428 dev_set_drvdata(dev, bd);
429 /* Create the input device and register it. */
430 dev_vdbg(dev, "%s: Create the input device and register it\n",
431 __func__);
432 bd->input = input_allocate_device();
433 if (bd->input == NULL) {
434 dev_err(dev, "%s: Error, failed to allocate input device\n",
435 __func__);
436 rc = -ENOSYS;
437 goto error_alloc_failed;
438 }
439
440 bd->input->name = ttsp->name;
441 scnprintf(bd->phys, sizeof(bd->phys)-1, "%s", dev_name(dev));
442 bd->input->phys = bd->phys;
443 bd->input->dev.parent = &bd->ttsp->dev;
444 bd->input->open = cyttsp4_btn_open;
445 bd->input->close = cyttsp4_btn_close;
446 input_set_drvdata(bd->input, bd);
447
448 pm_runtime_enable(dev);
449
450 pm_runtime_get_sync(dev);
451 /* get sysinfo */
452 bd->si = cyttsp4_request_sysinfo(ttsp);
453 pm_runtime_put(dev);
454
455 if (bd->si) {
456 rc = cyttsp4_setup_input_device(ttsp);
457 if (rc)
458 goto error_init_input;
459 } else {
460 dev_err(dev, "%s: Fail get sysinfo pointer from core p=%p\n",
461 __func__, bd->si);
462 cyttsp4_subscribe_attention(ttsp, CY_ATTEN_STARTUP,
463 cyttsp4_setup_input_attention, 0);
464 }
465
466 #ifdef CONFIG_HAS_EARLYSUSPEND
467 bd->es.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
468 bd->es.suspend = cyttsp4_btn_early_suspend;
469 bd->es.resume = cyttsp4_btn_late_resume;
470
471 register_early_suspend(&bd->es);
472 #endif
473
474 dev_dbg(dev, "%s: ok\n", __func__);
475 return 0;
476
477 error_init_input:
478 pm_runtime_suspend(dev);
479 pm_runtime_disable(dev);
480 input_free_device(bd->input);
481 error_alloc_failed:
482 dev_set_drvdata(dev, NULL);
483 kfree(bd);
484 error_alloc_data_failed:
485 error_no_pdata:
486 dev_err(dev, "%s failed.\n", __func__);
487 return rc;
488 }
489
490 static int cyttsp4_btn_release(struct cyttsp4_device *ttsp)
491 {
492 struct device *dev = &ttsp->dev;
493 struct cyttsp4_btn_data *bd = dev_get_drvdata(dev);
494
495 dev_dbg(dev, "%s\n", __func__);
496
497 #ifdef CONFIG_HAS_EARLYSUSPEND
498 /*
499 * This check is to prevent pm_runtime usage_count drop below zero
500 * because of removing the module while in suspended state
501 */
502 if (bd->is_suspended)
503 pm_runtime_get_noresume(dev);
504
505 unregister_early_suspend(&bd->es);
506 #endif
507
508 if (bd->input_device_registered) {
509 input_unregister_device(bd->input);
510 } else {
511 input_free_device(bd->input);
512 cyttsp4_unsubscribe_attention(ttsp, CY_ATTEN_STARTUP,
513 cyttsp4_setup_input_attention, 0);
514 }
515
516 pm_runtime_suspend(dev);
517 pm_runtime_disable(dev);
518
519 dev_set_drvdata(dev, NULL);
520 kfree(bd);
521 return 0;
522 }
523
524 struct cyttsp4_driver cyttsp4_btn_driver = {
525 .probe = cyttsp4_btn_probe,
526 .remove = cyttsp4_btn_release,
527 .driver = {
528 .name = CYTTSP4_BTN_NAME,
529 .bus = &cyttsp4_bus_type,
530 .owner = THIS_MODULE,
531 .pm = &cyttsp4_btn_pm_ops,
532 },
533 };
534
535 static int __init cyttsp4_btn_init(void)
536 {
537 int rc = 0;
538 rc = cyttsp4_register_driver(&cyttsp4_btn_driver);
539 pr_info("%s: Cypress TTSP MT v4 CapSense BTN (Built %s), rc=%d\n",
540 __func__, CY_DRIVER_DATE, rc);
541 return rc;
542 }
543 module_init(cyttsp4_btn_init);
544
545 static void __exit cyttsp4_btn_exit(void)
546 {
547 cyttsp4_unregister_driver(&cyttsp4_btn_driver);
548 pr_info("%s: module exit\n", __func__);
549 }
550 module_exit(cyttsp4_btn_exit);
551
552 MODULE_LICENSE("GPL");
553 MODULE_DESCRIPTION("Cypress TTSP 2D multi-touch CapSense BTN driver");
554 MODULE_AUTHOR("Cypress Semiconductor");
555 /* END PN:SPBB-1218 ,Added by l00184147, 2012/12/20*/
556 /* END PN:DTS2013012601133 ,Modified by l00184147, 2013/1/26*/
557 /* END PN:DTS2013051703879 ,Added by l00184147, 2013/5/17*/