pt_btn.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  1. /*
  2. * pt_btn.c
  3. * Parade TrueTouch(TM) Standard Product CapSense Reports Module.
  4. * For use with Parade touchscreen controllers.
  5. * Supported parts include:
  6. * TMA5XX
  7. * TMA448
  8. * TMA445A
  9. * TT21XXX
  10. * TT31XXX
  11. * TT4XXXX
  12. * TT7XXX
  13. * TC3XXX
  14. *
  15. * Copyright (C) 2015-2020 Parade Technologies
  16. *
  17. * This program is free software; you can redistribute it and/or
  18. * modify it under the terms of the GNU General Public License
  19. * version 2, and only version 2, as published by the
  20. * Free Software Foundation.
  21. *
  22. * This program is distributed in the hope that it will be useful,
  23. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  24. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  25. * GNU General Public License for more details.
  26. *
  27. * Contact Parade Technologies at www.paradetech.com <[email protected]>
  28. */
  29. #include "pt_regs.h"
  30. /*******************************************************************************
  31. * FUNCTION: pt_btn_key_action
  32. *
  33. * SUMMARY: Reports key event
  34. *
  35. * PARAMETERS:
  36. * *bd - pointer to button data structure
  37. * btn_no - number of button
  38. * btn_state - state of button
  39. ******************************************************************************/
  40. static inline void pt_btn_key_action(struct pt_btn_data *bd,
  41. int btn_no, int btn_state)
  42. {
  43. struct device *dev = bd->dev;
  44. struct pt_sysinfo *si = bd->si;
  45. if (!si->btn[btn_no].enabled ||
  46. si->btn[btn_no].state == btn_state)
  47. return;
  48. si->btn[btn_no].state = btn_state;
  49. input_report_key(bd->input, si->btn[btn_no].key_code, btn_state);
  50. input_sync(bd->input);
  51. pt_debug(dev, DL_INFO, "%s: btn=%d key_code=%d %s\n",
  52. __func__, btn_no, si->btn[btn_no].key_code,
  53. btn_state == PT_BTN_PRESSED ?
  54. "PRESSED" : "RELEASED");
  55. }
  56. /*******************************************************************************
  57. * FUNCTION: pt_get_btn_touches
  58. *
  59. * SUMMARY: Parse and report key event
  60. *
  61. * PARAMETERS:
  62. * *bd - pointer to button data structure
  63. ******************************************************************************/
  64. static void pt_get_btn_touches(struct pt_btn_data *bd)
  65. {
  66. struct pt_sysinfo *si = bd->si;
  67. int num_btns = si->num_btns;
  68. int cur_btn;
  69. int cur_btn_state;
  70. for (cur_btn = 0; cur_btn < num_btns; cur_btn++) {
  71. /* Get current button state */
  72. cur_btn_state = (si->xy_data[0] >> (cur_btn * PT_BITS_PER_BTN))
  73. & PT_NUM_BTN_EVENT_ID;
  74. pt_btn_key_action(bd, cur_btn, cur_btn_state);
  75. }
  76. }
  77. /*******************************************************************************
  78. * FUNCTION: pt_btn_lift_all
  79. *
  80. * SUMMARY: Reports button liftoff action
  81. *
  82. * PARAMETERS:
  83. * *bd - pointer to button data structure
  84. ******************************************************************************/
  85. static void pt_btn_lift_all(struct pt_btn_data *bd)
  86. {
  87. struct pt_sysinfo *si = bd->si;
  88. int i;
  89. if (!si || si->num_btns == 0)
  90. return;
  91. for (i = 0; i < si->num_btns; i++)
  92. pt_btn_key_action(bd, i, PT_BTN_RELEASED);
  93. }
  94. /*******************************************************************************
  95. * FUNCTION: pt_xy_worker
  96. *
  97. * SUMMARY: Read xy_data for all current CapSense button touches
  98. *
  99. * RETURN:
  100. * 0 = success
  101. *
  102. * PARAMETERS:
  103. * *bd - pointer to button data structure
  104. ******************************************************************************/
  105. static int pt_xy_worker(struct pt_btn_data *bd)
  106. {
  107. struct pt_sysinfo *si = bd->si;
  108. /* extract button press/release touch information */
  109. if (si->num_btns > 0)
  110. pt_get_btn_touches(bd);
  111. return 0;
  112. }
  113. /*******************************************************************************
  114. * FUNCTION: pt_btn_attention
  115. *
  116. * SUMMARY: Wrapper function for pt_xy_worker() that register to TTDL attention
  117. * list.
  118. *
  119. * RETURN:
  120. * 0 = success
  121. * !0 = failure
  122. *
  123. * PARAMETERS:
  124. * *dev - pointer to device structure
  125. ******************************************************************************/
  126. static int pt_btn_attention(struct device *dev)
  127. {
  128. struct pt_core_data *cd = dev_get_drvdata(dev);
  129. struct pt_btn_data *bd = &cd->bd;
  130. int rc;
  131. if (bd->si->xy_mode[2] != bd->si->desc.btn_report_id)
  132. return 0;
  133. /* core handles handshake */
  134. mutex_lock(&bd->btn_lock);
  135. rc = pt_xy_worker(bd);
  136. mutex_unlock(&bd->btn_lock);
  137. if (rc < 0)
  138. pt_debug(dev, DL_ERROR,
  139. "%s: xy_worker error r=%d\n", __func__, rc);
  140. return rc;
  141. }
  142. /*******************************************************************************
  143. * FUNCTION: pt_startup_attention
  144. *
  145. * SUMMARY: Wrapper function for pt_btn_lift_all() that register to TTDL
  146. * attention list.
  147. *
  148. * RETURN:
  149. * 0 = success
  150. *
  151. * PARAMETERS:
  152. * *dev - pointer to device structure
  153. ******************************************************************************/
  154. static int pt_startup_attention(struct device *dev)
  155. {
  156. struct pt_core_data *cd = dev_get_drvdata(dev);
  157. struct pt_btn_data *bd = &cd->bd;
  158. mutex_lock(&bd->btn_lock);
  159. pt_btn_lift_all(bd);
  160. mutex_unlock(&bd->btn_lock);
  161. return 0;
  162. }
  163. /*******************************************************************************
  164. * FUNCTION: pt_btn_suspend_attention
  165. *
  166. * SUMMARY: Function for button to enter suspend state that as following steps:
  167. * 1) Lift all button
  168. * 2) Set flag with suspend state
  169. * 3) Decrese pm system count
  170. *
  171. * RETURN:
  172. * 0 = success
  173. *
  174. * PARAMETERS:
  175. * *dev - pointer to device structure
  176. ******************************************************************************/
  177. static int pt_btn_suspend_attention(struct device *dev)
  178. {
  179. struct pt_core_data *cd = dev_get_drvdata(dev);
  180. struct pt_btn_data *bd = &cd->bd;
  181. mutex_lock(&bd->btn_lock);
  182. pt_btn_lift_all(bd);
  183. bd->is_suspended = true;
  184. mutex_unlock(&bd->btn_lock);
  185. pm_runtime_put(dev);
  186. return 0;
  187. }
  188. /*******************************************************************************
  189. * FUNCTION: pt_btn_resume_attention
  190. *
  191. * SUMMARY: Function for button to leave suspend state that as following steps:
  192. * 1) Increse pm system count
  193. * 2) Clear suspend state flag
  194. *
  195. * RETURN:
  196. * 0 = success
  197. *
  198. * PARAMETERS:
  199. * *dev - pointer to device structure
  200. ******************************************************************************/
  201. static int pt_btn_resume_attention(struct device *dev)
  202. {
  203. struct pt_core_data *cd = dev_get_drvdata(dev);
  204. struct pt_btn_data *bd = &cd->bd;
  205. pm_runtime_get(dev);
  206. mutex_lock(&bd->btn_lock);
  207. bd->is_suspended = false;
  208. mutex_unlock(&bd->btn_lock);
  209. return 0;
  210. }
  211. /*******************************************************************************
  212. * FUNCTION: pt_btn_open
  213. *
  214. * SUMMARY: Open method for input device(button) that sets up call back
  215. * functions to TTDL attention list
  216. *
  217. * RETURN:
  218. * 0 = success
  219. *
  220. * PARAMETERS:
  221. * *input - pointer to input_dev structure
  222. ******************************************************************************/
  223. static int pt_btn_open(struct input_dev *input)
  224. {
  225. struct device *dev = input->dev.parent;
  226. struct pt_core_data *cd = dev_get_drvdata(dev);
  227. struct pt_btn_data *bd = &cd->bd;
  228. pm_runtime_get_sync(dev);
  229. mutex_lock(&bd->btn_lock);
  230. bd->is_suspended = false;
  231. mutex_unlock(&bd->btn_lock);
  232. pt_debug(dev, DL_INFO, "%s: setup subscriptions\n", __func__);
  233. /* set up touch call back */
  234. _pt_subscribe_attention(dev, PT_ATTEN_IRQ, PT_BTN_NAME,
  235. pt_btn_attention, PT_MODE_OPERATIONAL);
  236. /* set up startup call back */
  237. _pt_subscribe_attention(dev, PT_ATTEN_STARTUP, PT_BTN_NAME,
  238. pt_startup_attention, 0);
  239. /* set up suspend call back */
  240. _pt_subscribe_attention(dev, PT_ATTEN_SUSPEND, PT_BTN_NAME,
  241. pt_btn_suspend_attention, 0);
  242. /* set up resume call back */
  243. _pt_subscribe_attention(dev, PT_ATTEN_RESUME, PT_BTN_NAME,
  244. pt_btn_resume_attention, 0);
  245. return 0;
  246. }
  247. /*******************************************************************************
  248. * FUNCTION: pt_btn_close
  249. *
  250. * SUMMARY: Close method for input device(button) that clears call back
  251. * functions from TTDL attention list.
  252. *
  253. * PARAMETERS:
  254. * *input - pointer to input_dev structure
  255. ******************************************************************************/
  256. static void pt_btn_close(struct input_dev *input)
  257. {
  258. struct device *dev = input->dev.parent;
  259. struct pt_core_data *cd = dev_get_drvdata(dev);
  260. struct pt_btn_data *bd = &cd->bd;
  261. _pt_unsubscribe_attention(dev, PT_ATTEN_IRQ, PT_BTN_NAME,
  262. pt_btn_attention, PT_MODE_OPERATIONAL);
  263. _pt_unsubscribe_attention(dev, PT_ATTEN_STARTUP, PT_BTN_NAME,
  264. pt_startup_attention, 0);
  265. _pt_unsubscribe_attention(dev, PT_ATTEN_SUSPEND, PT_BTN_NAME,
  266. pt_btn_suspend_attention, 0);
  267. _pt_unsubscribe_attention(dev, PT_ATTEN_RESUME, PT_BTN_NAME,
  268. pt_btn_resume_attention, 0);
  269. mutex_lock(&bd->btn_lock);
  270. if (!bd->is_suspended) {
  271. pm_runtime_put(dev);
  272. bd->is_suspended = true;
  273. }
  274. mutex_unlock(&bd->btn_lock);
  275. }
  276. /*******************************************************************************
  277. * FUNCTION: pt_setup_input_device
  278. *
  279. * SUMMARY: Set up resolution, event signal capabilities and register input
  280. * device for button.
  281. *
  282. * RETURN:
  283. * 0 = success
  284. * !0 = failure
  285. *
  286. * PARAMETERS:
  287. * *dev - pointer to device structure
  288. ******************************************************************************/
  289. static int pt_setup_input_device(struct device *dev)
  290. {
  291. struct pt_core_data *cd = dev_get_drvdata(dev);
  292. struct pt_btn_data *bd = &cd->bd;
  293. int i;
  294. int rc;
  295. pt_debug(dev, DL_INFO, "%s: Initialize event signals\n",
  296. __func__);
  297. __set_bit(EV_KEY, bd->input->evbit);
  298. pt_debug(dev, DL_INFO, "%s: Number of buttons %d\n",
  299. __func__, bd->si->num_btns);
  300. for (i = 0; i < bd->si->num_btns; i++) {
  301. pt_debug(dev, DL_INFO, "%s: btn:%d keycode:%d\n",
  302. __func__, i, bd->si->btn[i].key_code);
  303. __set_bit(bd->si->btn[i].key_code, bd->input->keybit);
  304. }
  305. rc = input_register_device(bd->input);
  306. if (rc < 0)
  307. pt_debug(dev, DL_ERROR,
  308. "%s: Error, failed register input device r=%d\n",
  309. __func__, rc);
  310. else
  311. bd->input_device_registered = true;
  312. return rc;
  313. }
  314. /*******************************************************************************
  315. * FUNCTION: pt_setup_input_attention
  316. *
  317. * SUMMARY: Wrapper function for pt_setup_input_device() register to TTDL
  318. * attention list.
  319. *
  320. * RETURN:
  321. * 0 = success
  322. * !0 = failure
  323. *
  324. * PARAMETERS:
  325. * *dev - pointer to device structure
  326. ******************************************************************************/
  327. static int pt_setup_input_attention(struct device *dev)
  328. {
  329. struct pt_core_data *cd = dev_get_drvdata(dev);
  330. struct pt_btn_data *bd = &cd->bd;
  331. int rc;
  332. bd->si = _pt_request_sysinfo(dev);
  333. if (!bd->si)
  334. return -EPERM;
  335. rc = pt_setup_input_device(dev);
  336. _pt_unsubscribe_attention(dev, PT_ATTEN_STARTUP, PT_BTN_NAME,
  337. pt_setup_input_attention, 0);
  338. return rc;
  339. }
  340. /*******************************************************************************
  341. * FUNCTION: pt_btn_probe
  342. *
  343. * SUMMARY: The probe function for button input device
  344. *
  345. * RETURN:
  346. * 0 = success
  347. * !0 = failure
  348. *
  349. * PARAMETERS:
  350. * *dev - pointer to device structure
  351. ******************************************************************************/
  352. int pt_btn_probe(struct device *dev)
  353. {
  354. struct pt_core_data *cd = dev_get_drvdata(dev);
  355. struct pt_btn_data *bd = &cd->bd;
  356. struct pt_platform_data *pdata = dev_get_platdata(dev);
  357. struct pt_btn_platform_data *btn_pdata;
  358. int rc = 0;
  359. if (!pdata || !pdata->btn_pdata) {
  360. pt_debug(dev, DL_ERROR,
  361. "%s: Missing platform data\n", __func__);
  362. rc = -ENODEV;
  363. goto error_no_pdata;
  364. }
  365. btn_pdata = pdata->btn_pdata;
  366. mutex_init(&bd->btn_lock);
  367. bd->dev = dev;
  368. bd->pdata = btn_pdata;
  369. /* Create the input device and register it. */
  370. pt_debug(dev, DL_INFO,
  371. "%s: Create the input device and register it\n", __func__);
  372. bd->input = input_allocate_device();
  373. if (!bd->input) {
  374. pt_debug(dev, DL_ERROR,
  375. "%s: Error, failed to allocate input device\n",
  376. __func__);
  377. rc = -ENODEV;
  378. goto error_alloc_failed;
  379. } else
  380. bd->input_device_allocated = true;
  381. if (bd->pdata->inp_dev_name)
  382. bd->input->name = bd->pdata->inp_dev_name;
  383. else
  384. bd->input->name = PT_BTN_NAME;
  385. scnprintf(bd->phys, sizeof(bd->phys), "%s/input%d", dev_name(dev),
  386. cd->phys_num++);
  387. bd->input->phys = bd->phys;
  388. bd->input->dev.parent = bd->dev;
  389. bd->input->open = pt_btn_open;
  390. bd->input->close = pt_btn_close;
  391. input_set_drvdata(bd->input, bd);
  392. /* get sysinfo */
  393. bd->si = _pt_request_sysinfo(dev);
  394. if (bd->si) {
  395. rc = pt_setup_input_device(dev);
  396. if (rc)
  397. goto error_init_input;
  398. } else {
  399. pt_debug(dev, DL_ERROR,
  400. "%s: Fail get sysinfo pointer from core p=%p\n",
  401. __func__, bd->si);
  402. _pt_subscribe_attention(dev, PT_ATTEN_STARTUP,
  403. PT_BTN_NAME, pt_setup_input_attention, 0);
  404. }
  405. return 0;
  406. error_init_input:
  407. input_free_device(bd->input);
  408. bd->input_device_allocated = false;
  409. error_alloc_failed:
  410. error_no_pdata:
  411. pt_debug(dev, DL_ERROR, "%s failed.\n", __func__);
  412. return rc;
  413. }
  414. /*******************************************************************************
  415. * FUNCTION: pt_btn_release
  416. *
  417. * SUMMARY: The release function for button input device
  418. *
  419. * RETURN:
  420. * 0 = success
  421. *
  422. * PARAMETERS:
  423. * *dev - pointer to device structure
  424. ******************************************************************************/
  425. int pt_btn_release(struct device *dev)
  426. {
  427. struct pt_core_data *cd;
  428. struct pt_btn_data *bd;
  429. /* Ensure valid pointers before de-referencing them */
  430. if (dev) {
  431. cd = dev_get_drvdata(dev);
  432. if (cd)
  433. bd = &cd->bd;
  434. else
  435. return 0;
  436. } else {
  437. return 0;
  438. }
  439. /*
  440. * Second call this function may cause kernel panic if probe fail.
  441. * Use input_device_registered & input_device_allocated variable to
  442. * avoid unregister or free unavailable devive.
  443. */
  444. if (bd && bd->input_device_registered) {
  445. bd->input_device_registered = false;
  446. input_unregister_device(bd->input);
  447. /* Unregistering device will free the device too */
  448. bd->input_device_allocated = false;
  449. } else if (bd && bd->input_device_allocated) {
  450. bd->input_device_allocated = false;
  451. input_free_device(bd->input);
  452. _pt_unsubscribe_attention(dev, PT_ATTEN_STARTUP,
  453. PT_BTN_NAME, pt_setup_input_attention, 0);
  454. }
  455. return 0;
  456. }