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*/
9 * Cypress TrueTouch(TM) Standard Product V4 CapSense touch reports module.
10 * For use with Cypress Txx4xx parts.
11 * Supported parts include:
15 * Copyright (C) 2012 Cypress Semiconductor
16 * Copyright (C) 2011 Sony Ericsson Mobile Communications AB.
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.
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.
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.
32 * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com>
36 #include "cyttsp4_bus.h"
38 #include <linux/delay.h>
39 #ifdef CONFIG_HAS_EARLYSUSPEND
40 #include <linux/earlysuspend.h>
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>
52 #include "cyttsp4_btn.h"
53 #include "cyttsp4_core.h"
54 #include "cyttsp4_regs.h"
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
;
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
;
70 u8 pr_buf
[CY_MAX_PRBUF_SIZE
];
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
)
76 struct device
*dev
= &bd
->ttsp
->dev
;
77 struct cyttsp4_sysinfo
*si
= bd
->si
;
81 cur_btn_state
= new_btn_state
== CY_BTN_PRESSED
? CY_BTN_RELEASED
:
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");
102 static void cyttsp4_get_btn_touches(struct cyttsp4_btn_data
*bd
)
104 enum cyttsp4_btn_state btn_state
= CY_BTN_RELEASED
;
105 struct cyttsp4_sysinfo
*si
= bd
->si
;
112 for (btn_state
= CY_BTN_RELEASED
; btn_state
< CY_BTN_NUM_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
+
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
);
131 static void cyttsp4_btn_lift_all(struct cyttsp4_btn_data
*bd
)
133 struct cyttsp4_sysinfo
*si
= bd
->si
;
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*/
141 num_regs
= (si
->si_ofs
.num_btns
+ CY_NUM_BTN_PER_REG
- 1)
142 / CY_NUM_BTN_PER_REG
;
144 for (btn_reg
= 0; btn_reg
< num_regs
; btn_reg
++)
145 si
->xy_mode
[si
->si_ofs
.rep_ofs
+ 2 + btn_reg
] = 0;
147 cyttsp4_get_btn_touches(bd
);
151 static void cyttsp4_log_btn_data(struct cyttsp4_btn_data
*bd
)
153 struct device
*dev
= &bd
->ttsp
->dev
;
154 struct cyttsp4_sysinfo
*si
= bd
->si
;
158 for (cur
= 0; cur
< si
->si_ofs
.num_btns
; cur
++) {
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
]);
166 dev_vdbg(dev
, "%s: %s\n", __func__
, bd
->pr_buf
);
172 /* read xy_data for all current CapSense button touches */
173 static int cyttsp4_xy_worker(struct cyttsp4_btn_data
*bd
)
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];
182 /* rep_data for bad packet check */
183 if (IS_BAD_PKT(rep_stat
)) {
184 dev_dbg(dev
, "%s: Invalid buffer detected\n", __func__
);
188 /* extract button press/release touch information */
189 if (si
->si_ofs
.num_btns
> 0) {
190 cyttsp4_get_btn_touches(bd
);
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
,
197 si
->si_ofs
.num_btns
* si
->si_ofs
.btn_rec_size
);
199 dev_err(dev
, "%s: read fail on button regs r=%d\n",
204 /* log button press/release touch information */
205 cyttsp4_log_btn_data(bd
);
209 dev_vdbg(dev
, "%s: done\n", __func__
);
214 static int cyttsp4_btn_attention(struct cyttsp4_device
*ttsp
)
216 struct device
*dev
= &ttsp
->dev
;
217 struct cyttsp4_btn_data
*bd
= dev_get_drvdata(dev
);
220 dev_vdbg(dev
, "%s\n", __func__
);
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
);
228 dev_vdbg(dev
, "%s: Ignoring report while suspended\n",
231 mutex_unlock(&bd
->report_lock
);
232 /* BEGIN PN:DTS2013041400018 ,Modified by l00184147, 2013/4/12*/
234 dev_err(dev
, "%s: xy_worker error r=%d\n", __func__
, rc
);
239 static int cyttsp4_startup_attention(struct cyttsp4_device
*ttsp
)
241 struct device
*dev
= &ttsp
->dev
;
242 struct cyttsp4_btn_data
*bd
= dev_get_drvdata(dev
);
243 struct cyttsp4_sysinfo
*si
= bd
->si
;
246 dev_vdbg(dev
, "%s\n", __func__
);
248 for (btn
= 0; btn
< si
->si_ofs
.num_btns
; btn
++)
249 bd
->si
->btn
[btn
].state
= CY_BTN_RELEASED
;
254 int cyttsp4_btn_open(struct input_dev
*input
)
256 struct device
*dev
= input
->dev
.parent
;
257 struct cyttsp4_device
*ttsp
=
258 container_of(dev
, struct cyttsp4_device
, dev
);
260 dev_dbg(dev
, "%s\n", __func__
);
264 dev_vdbg(dev
, "%s: setup subscriptions\n", __func__
);
266 /* set up touch call back */
267 cyttsp4_subscribe_attention(ttsp
, CY_ATTEN_IRQ
,
268 cyttsp4_btn_attention
, CY_MODE_OPERATIONAL
);
270 /* set up startup call back */
271 cyttsp4_subscribe_attention(ttsp
, CY_ATTEN_STARTUP
,
272 cyttsp4_startup_attention
, 0);
277 void cyttsp4_btn_close(struct input_dev
*input
)
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
);
285 dev_dbg(dev
, "%s\n", __func__
);
287 /* BEGIN PN:DTS2013041400018 ,Deleted by l00184147, 2013/4/12*/
288 /* END PN:DTS2013041400018 ,Deleted by l00184147, 2013/4/12*/
290 cyttsp4_unsubscribe_attention(ttsp
, CY_ATTEN_IRQ
,
291 cyttsp4_btn_attention
, CY_MODE_OPERATIONAL
);
293 cyttsp4_unsubscribe_attention(ttsp
, CY_ATTEN_STARTUP
,
294 cyttsp4_startup_attention
, 0);
299 #ifdef CONFIG_HAS_EARLYSUSPEND
300 static void cyttsp4_btn_early_suspend(struct early_suspend
*h
)
302 struct cyttsp4_btn_data
*bd
=
303 container_of(h
, struct cyttsp4_btn_data
, es
);
304 struct device
*dev
= &bd
->ttsp
->dev
;
306 dev_dbg(dev
, "%s\n", __func__
);
308 /* BEGIN PN:DTS2013041400018 ,Modified by l00184147, 2013/4/12*/
310 mutex_lock(&bd
->report_lock
);
311 bd
->is_suspended
= true;
312 cyttsp4_btn_lift_all(bd
);
313 mutex_unlock(&bd
->report_lock
);
315 /* END PN:DTS2013041400018 ,Modified by l00184147, 2013/4/12*/
318 static void cyttsp4_btn_late_resume(struct early_suspend
*h
)
320 struct cyttsp4_btn_data
*bd
=
321 container_of(h
, struct cyttsp4_btn_data
, es
);
322 struct device
*dev
= &bd
->ttsp
->dev
;
324 dev_dbg(dev
, "%s\n", __func__
);
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*/
334 #ifdef CONFIG_PM_RUNTIME
335 static int cyttsp4_btn_suspend(struct device
*dev
)
337 struct cyttsp4_btn_data
*bd
= dev_get_drvdata(dev
);
339 dev_dbg(dev
, "%s\n", __func__
);
342 cyttsp4_btn_lift_all(bd
);
346 static int cyttsp4_btn_resume(struct device
*dev
)
348 dev_dbg(dev
, "%s\n", __func__
);
354 static const struct dev_pm_ops cyttsp4_btn_pm_ops
= {
355 SET_RUNTIME_PM_OPS(cyttsp4_btn_suspend
, cyttsp4_btn_resume
, NULL
)
358 static int cyttsp4_setup_input_device(struct cyttsp4_device
*ttsp
)
360 struct device
*dev
= &ttsp
->dev
;
361 struct cyttsp4_btn_data
*bd
= dev_get_drvdata(dev
);
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
);
370 rc
= input_register_device(bd
->input
);
372 dev_err(dev
, "%s: Error, failed register input device r=%d\n",
375 bd
->input_device_registered
= true;
380 static int cyttsp4_setup_input_attention(struct cyttsp4_device
*ttsp
)
382 struct device
*dev
= &ttsp
->dev
;
383 struct cyttsp4_btn_data
*bd
= dev_get_drvdata(dev
);
386 dev_vdbg(dev
, "%s\n", __func__
);
388 bd
->si
= cyttsp4_request_sysinfo(ttsp
);
392 rc
= cyttsp4_setup_input_device(ttsp
);
394 cyttsp4_unsubscribe_attention(ttsp
, CY_ATTEN_STARTUP
,
395 cyttsp4_setup_input_attention
, 0);
400 static int cyttsp4_btn_probe(struct cyttsp4_device
*ttsp
)
402 struct cyttsp4_btn_data
*bd
;
403 struct device
*dev
= &ttsp
->dev
;
404 struct cyttsp4_btn_platform_data
*pdata
= dev_get_platdata(dev
);
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__
);
412 dev_err(dev
, "%s: Missing platform data\n", __func__
);
417 bd
= kzalloc(sizeof(*bd
), GFP_KERNEL
);
419 dev_err(dev
, "%s: Error, kzalloc\n", __func__
);
421 goto error_alloc_data_failed
;
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*/
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",
432 bd
->input
= input_allocate_device();
433 if (bd
->input
== NULL
) {
434 dev_err(dev
, "%s: Error, failed to allocate input device\n",
437 goto error_alloc_failed
;
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
);
448 pm_runtime_enable(dev
);
450 pm_runtime_get_sync(dev
);
452 bd
->si
= cyttsp4_request_sysinfo(ttsp
);
456 rc
= cyttsp4_setup_input_device(ttsp
);
458 goto error_init_input
;
460 dev_err(dev
, "%s: Fail get sysinfo pointer from core p=%p\n",
462 cyttsp4_subscribe_attention(ttsp
, CY_ATTEN_STARTUP
,
463 cyttsp4_setup_input_attention
, 0);
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
;
471 register_early_suspend(&bd
->es
);
474 dev_dbg(dev
, "%s: ok\n", __func__
);
478 pm_runtime_suspend(dev
);
479 pm_runtime_disable(dev
);
480 input_free_device(bd
->input
);
482 dev_set_drvdata(dev
, NULL
);
484 error_alloc_data_failed
:
486 dev_err(dev
, "%s failed.\n", __func__
);
490 static int cyttsp4_btn_release(struct cyttsp4_device
*ttsp
)
492 struct device
*dev
= &ttsp
->dev
;
493 struct cyttsp4_btn_data
*bd
= dev_get_drvdata(dev
);
495 dev_dbg(dev
, "%s\n", __func__
);
497 #ifdef CONFIG_HAS_EARLYSUSPEND
499 * This check is to prevent pm_runtime usage_count drop below zero
500 * because of removing the module while in suspended state
502 if (bd
->is_suspended
)
503 pm_runtime_get_noresume(dev
);
505 unregister_early_suspend(&bd
->es
);
508 if (bd
->input_device_registered
) {
509 input_unregister_device(bd
->input
);
511 input_free_device(bd
->input
);
512 cyttsp4_unsubscribe_attention(ttsp
, CY_ATTEN_STARTUP
,
513 cyttsp4_setup_input_attention
, 0);
516 pm_runtime_suspend(dev
);
517 pm_runtime_disable(dev
);
519 dev_set_drvdata(dev
, NULL
);
524 struct cyttsp4_driver cyttsp4_btn_driver
= {
525 .probe
= cyttsp4_btn_probe
,
526 .remove
= cyttsp4_btn_release
,
528 .name
= CYTTSP4_BTN_NAME
,
529 .bus
= &cyttsp4_bus_type
,
530 .owner
= THIS_MODULE
,
531 .pm
= &cyttsp4_btn_pm_ops
,
535 static int __init
cyttsp4_btn_init(void)
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
);
543 module_init(cyttsp4_btn_init
);
545 static void __exit
cyttsp4_btn_exit(void)
547 cyttsp4_unregister_driver(&cyttsp4_btn_driver
);
548 pr_info("%s: module exit\n", __func__
);
550 module_exit(cyttsp4_btn_exit
);
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*/