synaptics_tcm_touch.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267
  1. /*
  2. * Synaptics TCM touchscreen driver
  3. *
  4. * Copyright (C) 2017-2019 Synaptics Incorporated. All rights reserved.
  5. *
  6. * Copyright (C) 2017-2019 Scott Lin <[email protected]>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS
  19. * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY
  20. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
  21. * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS.
  22. * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION
  24. * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED
  25. * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  26. * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF
  27. * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES
  28. * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS'
  29. * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S.
  30. * DOLLARS.
  31. */
  32. #include <linux/input/mt.h>
  33. #include <linux/interrupt.h>
  34. #include "synaptics_tcm_core.h"
  35. #define TYPE_B_PROTOCOL
  36. #define USE_DEFAULT_TOUCH_REPORT_CONFIG
  37. #define TOUCH_REPORT_CONFIG_SIZE 128
  38. enum touch_status {
  39. LIFT = 0,
  40. FINGER = 1,
  41. GLOVED_FINGER = 2,
  42. NOP = -1,
  43. };
  44. enum touch_report_code {
  45. TOUCH_END = 0,
  46. TOUCH_FOREACH_ACTIVE_OBJECT,
  47. TOUCH_FOREACH_OBJECT,
  48. TOUCH_FOREACH_END,
  49. TOUCH_PAD_TO_NEXT_BYTE,
  50. TOUCH_TIMESTAMP,
  51. TOUCH_OBJECT_N_INDEX,
  52. TOUCH_OBJECT_N_CLASSIFICATION,
  53. TOUCH_OBJECT_N_X_POSITION,
  54. TOUCH_OBJECT_N_Y_POSITION,
  55. TOUCH_OBJECT_N_Z,
  56. TOUCH_OBJECT_N_X_WIDTH,
  57. TOUCH_OBJECT_N_Y_WIDTH,
  58. TOUCH_OBJECT_N_TX_POSITION_TIXELS,
  59. TOUCH_OBJECT_N_RX_POSITION_TIXELS,
  60. TOUCH_0D_BUTTONS_STATE,
  61. TOUCH_GESTURE_DOUBLE_TAP,
  62. TOUCH_FRAME_RATE,
  63. TOUCH_POWER_IM,
  64. TOUCH_CID_IM,
  65. TOUCH_RAIL_IM,
  66. TOUCH_CID_VARIANCE_IM,
  67. TOUCH_NSM_FREQUENCY,
  68. TOUCH_NSM_STATE,
  69. TOUCH_NUM_OF_ACTIVE_OBJECTS,
  70. TOUCH_NUM_OF_CPU_CYCLES_USED_SINCE_LAST_FRAME,
  71. TOUCH_TUNING_GAUSSIAN_WIDTHS = 0x80,
  72. TOUCH_TUNING_SMALL_OBJECT_PARAMS,
  73. TOUCH_TUNING_0D_BUTTONS_VARIANCE,
  74. };
  75. struct object_data {
  76. unsigned char status;
  77. unsigned int x_pos;
  78. unsigned int y_pos;
  79. unsigned int x_width;
  80. unsigned int y_width;
  81. unsigned int z;
  82. unsigned int tx_pos;
  83. unsigned int rx_pos;
  84. };
  85. struct input_params {
  86. unsigned int max_x;
  87. unsigned int max_y;
  88. unsigned int max_objects;
  89. };
  90. struct touch_data {
  91. struct object_data *object_data;
  92. unsigned int timestamp;
  93. unsigned int buttons_state;
  94. unsigned int gesture_double_tap;
  95. unsigned int frame_rate;
  96. unsigned int power_im;
  97. unsigned int cid_im;
  98. unsigned int rail_im;
  99. unsigned int cid_variance_im;
  100. unsigned int nsm_frequency;
  101. unsigned int nsm_state;
  102. unsigned int num_of_active_objects;
  103. unsigned int num_of_cpu_cycles;
  104. };
  105. struct touch_hcd {
  106. bool irq_wake;
  107. bool report_touch;
  108. bool suspend_touch;
  109. unsigned char *prev_status;
  110. unsigned int max_x;
  111. unsigned int max_y;
  112. unsigned int max_objects;
  113. struct mutex report_mutex;
  114. struct input_dev *input_dev;
  115. struct touch_data touch_data;
  116. struct input_params input_params;
  117. struct syna_tcm_buffer out;
  118. struct syna_tcm_buffer resp;
  119. struct syna_tcm_hcd *tcm_hcd;
  120. };
  121. DECLARE_COMPLETION(touch_remove_complete);
  122. static struct touch_hcd *touch_hcd;
  123. /**
  124. * touch_free_objects() - Free all touch objects
  125. *
  126. * Report finger lift events to the input subsystem for all touch objects.
  127. */
  128. static void touch_free_objects(void)
  129. {
  130. #ifdef TYPE_B_PROTOCOL
  131. unsigned int idx;
  132. #endif
  133. if (touch_hcd->input_dev == NULL)
  134. return;
  135. mutex_lock(&touch_hcd->report_mutex);
  136. #ifdef TYPE_B_PROTOCOL
  137. for (idx = 0; idx < touch_hcd->max_objects; idx++) {
  138. input_mt_slot(touch_hcd->input_dev, idx);
  139. input_mt_report_slot_state(touch_hcd->input_dev,
  140. MT_TOOL_FINGER, 0);
  141. }
  142. #endif
  143. input_report_key(touch_hcd->input_dev,
  144. BTN_TOUCH, 0);
  145. input_report_key(touch_hcd->input_dev,
  146. BTN_TOOL_FINGER, 0);
  147. #ifndef TYPE_B_PROTOCOL
  148. input_mt_sync(touch_hcd->input_dev);
  149. #endif
  150. input_sync(touch_hcd->input_dev);
  151. mutex_unlock(&touch_hcd->report_mutex);
  152. }
  153. /**
  154. * touch_get_report_data() - Retrieve data from touch report
  155. *
  156. * Retrieve data from the touch report based on the bit offset and bit length
  157. * information from the touch report configuration.
  158. */
  159. static int touch_get_report_data(unsigned int offset,
  160. unsigned int bits, unsigned int *data)
  161. {
  162. unsigned char mask;
  163. unsigned char byte_data;
  164. unsigned int output_data;
  165. unsigned int bit_offset;
  166. unsigned int byte_offset;
  167. unsigned int data_bits;
  168. unsigned int available_bits;
  169. unsigned int remaining_bits;
  170. unsigned char *touch_report;
  171. struct syna_tcm_hcd *tcm_hcd = touch_hcd->tcm_hcd;
  172. if (bits == 0 || bits > 32) {
  173. LOGE(tcm_hcd->pdev->dev.parent,
  174. "Invalid number of bits\n");
  175. return -EINVAL;
  176. }
  177. if (offset + bits > tcm_hcd->report.buffer.data_length * 8) {
  178. *data = 0;
  179. return 0;
  180. }
  181. touch_report = tcm_hcd->report.buffer.buf;
  182. output_data = 0;
  183. remaining_bits = bits;
  184. bit_offset = offset % 8;
  185. byte_offset = offset / 8;
  186. while (remaining_bits) {
  187. byte_data = touch_report[byte_offset];
  188. byte_data >>= bit_offset;
  189. available_bits = 8 - bit_offset;
  190. data_bits = MIN(available_bits, remaining_bits);
  191. mask = 0xff >> (8 - data_bits);
  192. byte_data &= mask;
  193. output_data |= byte_data << (bits - remaining_bits);
  194. bit_offset = 0;
  195. byte_offset += 1;
  196. remaining_bits -= data_bits;
  197. }
  198. *data = output_data;
  199. return 0;
  200. }
  201. /**
  202. * touch_parse_report() - Parse touch report
  203. *
  204. * Traverse through the touch report configuration and parse the touch report
  205. * generated by the device accordingly to retrieve the touch data.
  206. */
  207. static int touch_parse_report(void)
  208. {
  209. int retval;
  210. bool active_only;
  211. bool num_of_active_objects;
  212. unsigned char code;
  213. unsigned int size;
  214. unsigned int idx;
  215. unsigned int obj;
  216. unsigned int next;
  217. unsigned int data;
  218. unsigned int bits;
  219. unsigned int offset;
  220. unsigned int objects;
  221. unsigned int active_objects;
  222. unsigned int report_size;
  223. unsigned int config_size;
  224. unsigned char *config_data;
  225. struct touch_data *touch_data;
  226. struct object_data *object_data;
  227. struct syna_tcm_hcd *tcm_hcd = touch_hcd->tcm_hcd;
  228. static unsigned int end_of_foreach;
  229. touch_data = &touch_hcd->touch_data;
  230. object_data = touch_hcd->touch_data.object_data;
  231. config_data = tcm_hcd->config.buf;
  232. config_size = tcm_hcd->config.data_length;
  233. report_size = tcm_hcd->report.buffer.data_length;
  234. size = sizeof(*object_data) * touch_hcd->max_objects;
  235. memset(touch_hcd->touch_data.object_data, 0x00, size);
  236. num_of_active_objects = false;
  237. idx = 0;
  238. offset = 0;
  239. objects = 0;
  240. while (idx < config_size) {
  241. code = config_data[idx++];
  242. switch (code) {
  243. case TOUCH_END:
  244. goto exit;
  245. case TOUCH_FOREACH_ACTIVE_OBJECT:
  246. obj = 0;
  247. next = idx;
  248. active_only = true;
  249. break;
  250. case TOUCH_FOREACH_OBJECT:
  251. obj = 0;
  252. next = idx;
  253. active_only = false;
  254. break;
  255. case TOUCH_FOREACH_END:
  256. end_of_foreach = idx;
  257. if (active_only) {
  258. if (num_of_active_objects) {
  259. objects++;
  260. if (objects < active_objects)
  261. idx = next;
  262. } else if (offset < report_size * 8) {
  263. idx = next;
  264. }
  265. } else {
  266. obj++;
  267. if (obj < touch_hcd->max_objects)
  268. idx = next;
  269. }
  270. break;
  271. case TOUCH_PAD_TO_NEXT_BYTE:
  272. offset = ceil_div(offset, 8) * 8;
  273. break;
  274. case TOUCH_TIMESTAMP:
  275. bits = config_data[idx++];
  276. retval = touch_get_report_data(offset, bits, &data);
  277. if (retval < 0) {
  278. LOGE(tcm_hcd->pdev->dev.parent,
  279. "Failed to get timestamp\n");
  280. return retval;
  281. }
  282. touch_data->timestamp = data;
  283. offset += bits;
  284. break;
  285. case TOUCH_OBJECT_N_INDEX:
  286. bits = config_data[idx++];
  287. retval = touch_get_report_data(offset, bits, &obj);
  288. if (retval < 0) {
  289. LOGE(tcm_hcd->pdev->dev.parent,
  290. "Failed to get object index\n");
  291. return retval;
  292. }
  293. offset += bits;
  294. break;
  295. case TOUCH_OBJECT_N_CLASSIFICATION:
  296. bits = config_data[idx++];
  297. retval = touch_get_report_data(offset, bits, &data);
  298. if (retval < 0) {
  299. LOGE(tcm_hcd->pdev->dev.parent,
  300. "Failed to get classification data\n");
  301. return retval;
  302. }
  303. object_data[obj].status = data;
  304. offset += bits;
  305. break;
  306. case TOUCH_OBJECT_N_X_POSITION:
  307. bits = config_data[idx++];
  308. retval = touch_get_report_data(offset, bits, &data);
  309. if (retval < 0) {
  310. LOGE(tcm_hcd->pdev->dev.parent,
  311. "Failed to get object x position\n");
  312. return retval;
  313. }
  314. object_data[obj].x_pos = data;
  315. offset += bits;
  316. break;
  317. case TOUCH_OBJECT_N_Y_POSITION:
  318. bits = config_data[idx++];
  319. retval = touch_get_report_data(offset, bits, &data);
  320. if (retval < 0) {
  321. LOGE(tcm_hcd->pdev->dev.parent,
  322. "Failed to get object y position\n");
  323. return retval;
  324. }
  325. object_data[obj].y_pos = data;
  326. offset += bits;
  327. break;
  328. case TOUCH_OBJECT_N_Z:
  329. bits = config_data[idx++];
  330. retval = touch_get_report_data(offset, bits, &data);
  331. if (retval < 0) {
  332. LOGE(tcm_hcd->pdev->dev.parent,
  333. "Failed to get object z\n");
  334. return retval;
  335. }
  336. object_data[obj].z = data;
  337. offset += bits;
  338. break;
  339. case TOUCH_OBJECT_N_X_WIDTH:
  340. bits = config_data[idx++];
  341. retval = touch_get_report_data(offset, bits, &data);
  342. if (retval < 0) {
  343. LOGE(tcm_hcd->pdev->dev.parent,
  344. "Failed to get object x width\n");
  345. return retval;
  346. }
  347. object_data[obj].x_width = data;
  348. offset += bits;
  349. break;
  350. case TOUCH_OBJECT_N_Y_WIDTH:
  351. bits = config_data[idx++];
  352. retval = touch_get_report_data(offset, bits, &data);
  353. if (retval < 0) {
  354. LOGE(tcm_hcd->pdev->dev.parent,
  355. "Failed to get object y width\n");
  356. return retval;
  357. }
  358. object_data[obj].y_width = data;
  359. offset += bits;
  360. break;
  361. case TOUCH_OBJECT_N_TX_POSITION_TIXELS:
  362. bits = config_data[idx++];
  363. retval = touch_get_report_data(offset, bits, &data);
  364. if (retval < 0) {
  365. LOGE(tcm_hcd->pdev->dev.parent,
  366. "Failed to get object tx position\n");
  367. return retval;
  368. }
  369. object_data[obj].tx_pos = data;
  370. offset += bits;
  371. break;
  372. case TOUCH_OBJECT_N_RX_POSITION_TIXELS:
  373. bits = config_data[idx++];
  374. retval = touch_get_report_data(offset, bits, &data);
  375. if (retval < 0) {
  376. LOGE(tcm_hcd->pdev->dev.parent,
  377. "Failed to get object rx position\n");
  378. return retval;
  379. }
  380. object_data[obj].rx_pos = data;
  381. offset += bits;
  382. break;
  383. case TOUCH_0D_BUTTONS_STATE:
  384. bits = config_data[idx++];
  385. retval = touch_get_report_data(offset, bits, &data);
  386. if (retval < 0) {
  387. LOGE(tcm_hcd->pdev->dev.parent,
  388. "Failed to get 0D buttons state\n");
  389. return retval;
  390. }
  391. touch_data->buttons_state = data;
  392. offset += bits;
  393. break;
  394. case TOUCH_GESTURE_DOUBLE_TAP:
  395. bits = config_data[idx++];
  396. retval = touch_get_report_data(offset, bits, &data);
  397. if (retval < 0) {
  398. LOGE(tcm_hcd->pdev->dev.parent,
  399. "Failed to get gesture double tap\n");
  400. return retval;
  401. }
  402. touch_data->gesture_double_tap = data;
  403. offset += bits;
  404. break;
  405. case TOUCH_FRAME_RATE:
  406. bits = config_data[idx++];
  407. retval = touch_get_report_data(offset, bits, &data);
  408. if (retval < 0) {
  409. LOGE(tcm_hcd->pdev->dev.parent,
  410. "Failed to get frame rate\n");
  411. return retval;
  412. }
  413. touch_data->frame_rate = data;
  414. offset += bits;
  415. break;
  416. case TOUCH_POWER_IM:
  417. bits = config_data[idx++];
  418. retval = touch_get_report_data(offset, bits, &data);
  419. if (retval < 0) {
  420. LOGE(tcm_hcd->pdev->dev.parent,
  421. "Failed to get power IM\n");
  422. return retval;
  423. }
  424. touch_data->power_im = data;
  425. offset += bits;
  426. break;
  427. case TOUCH_CID_IM:
  428. bits = config_data[idx++];
  429. retval = touch_get_report_data(offset, bits, &data);
  430. if (retval < 0) {
  431. LOGE(tcm_hcd->pdev->dev.parent,
  432. "Failed to get CID IM\n");
  433. return retval;
  434. }
  435. touch_data->cid_im = data;
  436. offset += bits;
  437. break;
  438. case TOUCH_RAIL_IM:
  439. bits = config_data[idx++];
  440. retval = touch_get_report_data(offset, bits, &data);
  441. if (retval < 0) {
  442. LOGE(tcm_hcd->pdev->dev.parent,
  443. "Failed to get rail IM\n");
  444. return retval;
  445. }
  446. touch_data->rail_im = data;
  447. offset += bits;
  448. break;
  449. case TOUCH_CID_VARIANCE_IM:
  450. bits = config_data[idx++];
  451. retval = touch_get_report_data(offset, bits, &data);
  452. if (retval < 0) {
  453. LOGE(tcm_hcd->pdev->dev.parent,
  454. "Failed to get CID variance IM\n");
  455. return retval;
  456. }
  457. touch_data->cid_variance_im = data;
  458. offset += bits;
  459. break;
  460. case TOUCH_NSM_FREQUENCY:
  461. bits = config_data[idx++];
  462. retval = touch_get_report_data(offset, bits, &data);
  463. if (retval < 0) {
  464. LOGE(tcm_hcd->pdev->dev.parent,
  465. "Failed to get NSM frequency\n");
  466. return retval;
  467. }
  468. touch_data->nsm_frequency = data;
  469. offset += bits;
  470. break;
  471. case TOUCH_NSM_STATE:
  472. bits = config_data[idx++];
  473. retval = touch_get_report_data(offset, bits, &data);
  474. if (retval < 0) {
  475. LOGE(tcm_hcd->pdev->dev.parent,
  476. "Failed to get NSM state\n");
  477. return retval;
  478. }
  479. touch_data->nsm_state = data;
  480. offset += bits;
  481. break;
  482. case TOUCH_NUM_OF_ACTIVE_OBJECTS:
  483. bits = config_data[idx++];
  484. retval = touch_get_report_data(offset, bits, &data);
  485. if (retval < 0) {
  486. LOGE(tcm_hcd->pdev->dev.parent,
  487. "Failed to get number of objects\n");
  488. return retval;
  489. }
  490. active_objects = data;
  491. num_of_active_objects = true;
  492. touch_data->num_of_active_objects = data;
  493. offset += bits;
  494. if (touch_data->num_of_active_objects == 0)
  495. idx = end_of_foreach;
  496. break;
  497. case TOUCH_NUM_OF_CPU_CYCLES_USED_SINCE_LAST_FRAME:
  498. bits = config_data[idx++];
  499. retval = touch_get_report_data(offset, bits, &data);
  500. if (retval < 0) {
  501. LOGE(tcm_hcd->pdev->dev.parent,
  502. "Failed to get number of CPU cycles\n");
  503. return retval;
  504. }
  505. touch_data->num_of_cpu_cycles = data;
  506. offset += bits;
  507. break;
  508. case TOUCH_TUNING_GAUSSIAN_WIDTHS:
  509. bits = config_data[idx++];
  510. offset += bits;
  511. break;
  512. case TOUCH_TUNING_SMALL_OBJECT_PARAMS:
  513. bits = config_data[idx++];
  514. offset += bits;
  515. break;
  516. case TOUCH_TUNING_0D_BUTTONS_VARIANCE:
  517. bits = config_data[idx++];
  518. offset += bits;
  519. break;
  520. }
  521. }
  522. exit:
  523. return 0;
  524. }
  525. /**
  526. * touch_report() - Report touch events
  527. *
  528. * Retrieve data from the touch report generated by the device and report touch
  529. * events to the input subsystem.
  530. */
  531. static void touch_report(void)
  532. {
  533. int retval;
  534. unsigned int idx;
  535. unsigned int x;
  536. unsigned int y;
  537. unsigned int temp;
  538. unsigned int status;
  539. unsigned int touch_count;
  540. struct touch_data *touch_data;
  541. struct object_data *object_data;
  542. struct syna_tcm_hcd *tcm_hcd = touch_hcd->tcm_hcd;
  543. const struct syna_tcm_board_data *bdata = tcm_hcd->hw_if->bdata;
  544. if (!touch_hcd->report_touch)
  545. return;
  546. if (touch_hcd->input_dev == NULL)
  547. return;
  548. mutex_lock(&touch_hcd->report_mutex);
  549. retval = touch_parse_report();
  550. if (retval < 0) {
  551. LOGE(tcm_hcd->pdev->dev.parent,
  552. "Failed to parse touch report\n");
  553. goto exit;
  554. }
  555. touch_data = &touch_hcd->touch_data;
  556. object_data = touch_hcd->touch_data.object_data;
  557. #ifdef WAKEUP_GESTURE
  558. if (touch_data->gesture_double_tap && tcm_hcd->in_suspend) {
  559. input_report_key(touch_hcd->input_dev, KEY_WAKEUP, 1);
  560. input_sync(touch_hcd->input_dev);
  561. input_report_key(touch_hcd->input_dev, KEY_WAKEUP, 0);
  562. input_sync(touch_hcd->input_dev);
  563. }
  564. #endif
  565. if (tcm_hcd->in_suspend)
  566. goto exit;
  567. touch_count = 0;
  568. for (idx = 0; idx < touch_hcd->max_objects; idx++) {
  569. if (touch_hcd->prev_status[idx] == LIFT &&
  570. object_data[idx].status == LIFT)
  571. status = NOP;
  572. else
  573. status = object_data[idx].status;
  574. switch (status) {
  575. case LIFT:
  576. #ifdef TYPE_B_PROTOCOL
  577. input_mt_slot(touch_hcd->input_dev, idx);
  578. input_mt_report_slot_state(touch_hcd->input_dev,
  579. MT_TOOL_FINGER, 0);
  580. #endif
  581. break;
  582. case FINGER:
  583. case GLOVED_FINGER:
  584. x = object_data[idx].x_pos;
  585. y = object_data[idx].y_pos;
  586. if (bdata->swap_axes) {
  587. temp = x;
  588. x = y;
  589. y = temp;
  590. }
  591. if (bdata->x_flip)
  592. x = touch_hcd->input_params.max_x - x;
  593. if (bdata->y_flip)
  594. y = touch_hcd->input_params.max_y - y;
  595. #ifdef TYPE_B_PROTOCOL
  596. input_mt_slot(touch_hcd->input_dev, idx);
  597. input_mt_report_slot_state(touch_hcd->input_dev,
  598. MT_TOOL_FINGER, 1);
  599. #endif
  600. input_report_key(touch_hcd->input_dev,
  601. BTN_TOUCH, 1);
  602. input_report_key(touch_hcd->input_dev,
  603. BTN_TOOL_FINGER, 1);
  604. input_report_abs(touch_hcd->input_dev,
  605. ABS_MT_POSITION_X, x);
  606. input_report_abs(touch_hcd->input_dev,
  607. ABS_MT_POSITION_Y, y);
  608. #ifndef TYPE_B_PROTOCOL
  609. input_mt_sync(touch_hcd->input_dev);
  610. #endif
  611. LOGD(tcm_hcd->pdev->dev.parent,
  612. "Finger %d: x = %d, y = %d\n",
  613. idx, x, y);
  614. touch_count++;
  615. break;
  616. default:
  617. break;
  618. }
  619. touch_hcd->prev_status[idx] = object_data[idx].status;
  620. }
  621. if (touch_count == 0) {
  622. input_report_key(touch_hcd->input_dev,
  623. BTN_TOUCH, 0);
  624. input_report_key(touch_hcd->input_dev,
  625. BTN_TOOL_FINGER, 0);
  626. #ifndef TYPE_B_PROTOCOL
  627. input_mt_sync(touch_hcd->input_dev);
  628. #endif
  629. }
  630. input_sync(touch_hcd->input_dev);
  631. exit:
  632. mutex_unlock(&touch_hcd->report_mutex);
  633. }
  634. /**
  635. * touch_set_input_params() - Set input parameters
  636. *
  637. * Set the input parameters of the input device based on the information
  638. * retrieved from the application information packet. In addition, set up an
  639. * array for tracking the status of touch objects.
  640. */
  641. static int touch_set_input_params(void)
  642. {
  643. struct syna_tcm_hcd *tcm_hcd = touch_hcd->tcm_hcd;
  644. input_set_abs_params(touch_hcd->input_dev,
  645. ABS_MT_POSITION_X, 0, touch_hcd->max_x, 0, 0);
  646. input_set_abs_params(touch_hcd->input_dev,
  647. ABS_MT_POSITION_Y, 0, touch_hcd->max_y, 0, 0);
  648. input_mt_init_slots(touch_hcd->input_dev, touch_hcd->max_objects,
  649. INPUT_MT_DIRECT);
  650. touch_hcd->input_params.max_x = touch_hcd->max_x;
  651. touch_hcd->input_params.max_y = touch_hcd->max_y;
  652. touch_hcd->input_params.max_objects = touch_hcd->max_objects;
  653. if (touch_hcd->max_objects == 0)
  654. return 0;
  655. kfree(touch_hcd->prev_status);
  656. touch_hcd->prev_status = kzalloc(touch_hcd->max_objects, GFP_KERNEL);
  657. if (!touch_hcd->prev_status) {
  658. LOGE(tcm_hcd->pdev->dev.parent,
  659. "Failed to allocate memory for prev_status\n");
  660. return -ENOMEM;
  661. }
  662. return 0;
  663. }
  664. /**
  665. * touch_get_input_params() - Get input parameters
  666. *
  667. * Retrieve the input parameters to register with the input subsystem for
  668. * the input device from the application information packet. In addition,
  669. * the touch report configuration is retrieved and stored.
  670. */
  671. static int touch_get_input_params(void)
  672. {
  673. int retval;
  674. unsigned int temp;
  675. struct syna_tcm_app_info *app_info;
  676. struct syna_tcm_hcd *tcm_hcd = touch_hcd->tcm_hcd;
  677. const struct syna_tcm_board_data *bdata = tcm_hcd->hw_if->bdata;
  678. app_info = &tcm_hcd->app_info;
  679. touch_hcd->max_x = le2_to_uint(app_info->max_x);
  680. touch_hcd->max_y = le2_to_uint(app_info->max_y);
  681. touch_hcd->max_objects = le2_to_uint(app_info->max_objects);
  682. if (bdata->swap_axes) {
  683. temp = touch_hcd->max_x;
  684. touch_hcd->max_x = touch_hcd->max_y;
  685. touch_hcd->max_y = temp;
  686. }
  687. LOCK_BUFFER(tcm_hcd->config);
  688. retval = tcm_hcd->write_message(tcm_hcd,
  689. CMD_GET_TOUCH_REPORT_CONFIG,
  690. NULL,
  691. 0,
  692. &tcm_hcd->config.buf,
  693. &tcm_hcd->config.buf_size,
  694. &tcm_hcd->config.data_length,
  695. NULL,
  696. 0);
  697. if (retval < 0) {
  698. LOGE(tcm_hcd->pdev->dev.parent,
  699. "Failed to write command %s\n",
  700. STR(CMD_GET_TOUCH_REPORT_CONFIG));
  701. UNLOCK_BUFFER(tcm_hcd->config);
  702. return retval;
  703. }
  704. UNLOCK_BUFFER(tcm_hcd->config);
  705. return 0;
  706. }
  707. /**
  708. * touch_set_input_dev() - Set up input device
  709. *
  710. * Allocate an input device, configure the input device based on the particular
  711. * input events to be reported, and register the input device with the input
  712. * subsystem.
  713. */
  714. static int touch_set_input_dev(void)
  715. {
  716. int retval;
  717. struct syna_tcm_hcd *tcm_hcd = touch_hcd->tcm_hcd;
  718. touch_hcd->input_dev = input_allocate_device();
  719. if (touch_hcd->input_dev == NULL) {
  720. LOGE(tcm_hcd->pdev->dev.parent,
  721. "Failed to allocate input device\n");
  722. return -ENODEV;
  723. }
  724. touch_hcd->input_dev->name = TOUCH_INPUT_NAME;
  725. touch_hcd->input_dev->phys = TOUCH_INPUT_PHYS_PATH;
  726. touch_hcd->input_dev->id.product = SYNAPTICS_TCM_ID_PRODUCT;
  727. touch_hcd->input_dev->id.version = SYNAPTICS_TCM_ID_VERSION;
  728. touch_hcd->input_dev->dev.parent = tcm_hcd->pdev->dev.parent;
  729. input_set_drvdata(touch_hcd->input_dev, tcm_hcd);
  730. set_bit(EV_SYN, touch_hcd->input_dev->evbit);
  731. set_bit(EV_KEY, touch_hcd->input_dev->evbit);
  732. set_bit(EV_ABS, touch_hcd->input_dev->evbit);
  733. set_bit(BTN_TOUCH, touch_hcd->input_dev->keybit);
  734. set_bit(BTN_TOOL_FINGER, touch_hcd->input_dev->keybit);
  735. #ifdef INPUT_PROP_DIRECT
  736. set_bit(INPUT_PROP_DIRECT, touch_hcd->input_dev->propbit);
  737. #endif
  738. #ifdef WAKEUP_GESTURE
  739. set_bit(KEY_WAKEUP, touch_hcd->input_dev->keybit);
  740. input_set_capability(touch_hcd->input_dev, EV_KEY, KEY_WAKEUP);
  741. #endif
  742. retval = touch_set_input_params();
  743. if (retval < 0) {
  744. LOGE(tcm_hcd->pdev->dev.parent,
  745. "Failed to set input parameters\n");
  746. input_free_device(touch_hcd->input_dev);
  747. touch_hcd->input_dev = NULL;
  748. return retval;
  749. }
  750. retval = input_register_device(touch_hcd->input_dev);
  751. if (retval < 0) {
  752. LOGE(tcm_hcd->pdev->dev.parent,
  753. "Failed to register input device\n");
  754. input_free_device(touch_hcd->input_dev);
  755. touch_hcd->input_dev = NULL;
  756. return retval;
  757. }
  758. return 0;
  759. }
  760. /**
  761. * touch_set_report_config() - Set touch report configuration
  762. *
  763. * Send the SET_TOUCH_REPORT_CONFIG command to configure the format and content
  764. * of the touch report.
  765. */
  766. static int touch_set_report_config(void)
  767. {
  768. int retval;
  769. unsigned int idx;
  770. unsigned int length;
  771. struct syna_tcm_app_info *app_info;
  772. struct syna_tcm_hcd *tcm_hcd = touch_hcd->tcm_hcd;
  773. const struct syna_tcm_board_data *bdata = tcm_hcd->hw_if->bdata;
  774. if (!bdata->extend_report)
  775. return 0;
  776. app_info = &tcm_hcd->app_info;
  777. length = le2_to_uint(app_info->max_touch_report_config_size);
  778. if (length < TOUCH_REPORT_CONFIG_SIZE) {
  779. LOGE(tcm_hcd->pdev->dev.parent,
  780. "Invalid maximum touch report config size\n");
  781. return -EINVAL;
  782. }
  783. LOCK_BUFFER(touch_hcd->out);
  784. retval = syna_tcm_alloc_mem(tcm_hcd,
  785. &touch_hcd->out,
  786. length);
  787. if (retval < 0) {
  788. LOGE(tcm_hcd->pdev->dev.parent,
  789. "Failed to allocate memory for touch_hcd->out.buf\n");
  790. UNLOCK_BUFFER(touch_hcd->out);
  791. return retval;
  792. }
  793. idx = 0;
  794. #ifdef WAKEUP_GESTURE
  795. touch_hcd->out.buf[idx++] = TOUCH_GESTURE_DOUBLE_TAP;
  796. touch_hcd->out.buf[idx++] = 8;
  797. #endif
  798. touch_hcd->out.buf[idx++] = TOUCH_FOREACH_ACTIVE_OBJECT;
  799. touch_hcd->out.buf[idx++] = TOUCH_OBJECT_N_INDEX;
  800. touch_hcd->out.buf[idx++] = 4;
  801. touch_hcd->out.buf[idx++] = TOUCH_OBJECT_N_CLASSIFICATION;
  802. touch_hcd->out.buf[idx++] = 4;
  803. touch_hcd->out.buf[idx++] = TOUCH_OBJECT_N_X_POSITION;
  804. touch_hcd->out.buf[idx++] = 12;
  805. touch_hcd->out.buf[idx++] = TOUCH_OBJECT_N_Y_POSITION;
  806. touch_hcd->out.buf[idx++] = 12;
  807. touch_hcd->out.buf[idx++] = TOUCH_FOREACH_END;
  808. touch_hcd->out.buf[idx++] = TOUCH_END;
  809. LOCK_BUFFER(touch_hcd->resp);
  810. retval = tcm_hcd->write_message(tcm_hcd,
  811. CMD_SET_TOUCH_REPORT_CONFIG,
  812. touch_hcd->out.buf,
  813. length,
  814. &touch_hcd->resp.buf,
  815. &touch_hcd->resp.buf_size,
  816. &touch_hcd->resp.data_length,
  817. NULL,
  818. 0);
  819. if (retval < 0) {
  820. LOGE(tcm_hcd->pdev->dev.parent,
  821. "Failed to write command %s\n",
  822. STR(CMD_SET_TOUCH_REPORT_CONFIG));
  823. UNLOCK_BUFFER(touch_hcd->resp);
  824. UNLOCK_BUFFER(touch_hcd->out);
  825. return retval;
  826. }
  827. UNLOCK_BUFFER(touch_hcd->resp);
  828. UNLOCK_BUFFER(touch_hcd->out);
  829. return 0;
  830. }
  831. /**
  832. * touch_check_input_params() - Check input parameters
  833. *
  834. * Check if any of the input parameters registered with the input subsystem for
  835. * the input device has changed.
  836. */
  837. static int touch_check_input_params(void)
  838. {
  839. unsigned int size;
  840. struct syna_tcm_hcd *tcm_hcd = touch_hcd->tcm_hcd;
  841. if (touch_hcd->max_x == 0 && touch_hcd->max_y == 0)
  842. return 0;
  843. if (touch_hcd->input_params.max_objects != touch_hcd->max_objects) {
  844. kfree(touch_hcd->touch_data.object_data);
  845. size = sizeof(*touch_hcd->touch_data.object_data);
  846. size *= touch_hcd->max_objects;
  847. touch_hcd->touch_data.object_data = kzalloc(size, GFP_KERNEL);
  848. if (!touch_hcd->touch_data.object_data) {
  849. LOGE(tcm_hcd->pdev->dev.parent,
  850. "Failed to allocate memory for object_data\n");
  851. return -ENOMEM;
  852. }
  853. return 1;
  854. }
  855. if (touch_hcd->input_params.max_x != touch_hcd->max_x)
  856. return 1;
  857. if (touch_hcd->input_params.max_y != touch_hcd->max_y)
  858. return 1;
  859. return 0;
  860. }
  861. /**
  862. * touch_set_input_reporting() - Configure touch report and set up new input
  863. * device if necessary
  864. *
  865. * After a device reset event, configure the touch report and set up a new input
  866. * device if any of the input parameters has changed after the device reset.
  867. */
  868. static int touch_set_input_reporting(void)
  869. {
  870. int retval;
  871. struct syna_tcm_hcd *tcm_hcd = touch_hcd->tcm_hcd;
  872. if (tcm_hcd->id_info.mode != MODE_APPLICATION ||
  873. tcm_hcd->app_status != APP_STATUS_OK) {
  874. LOGN(tcm_hcd->pdev->dev.parent,
  875. "Application firmware not running\n");
  876. return 0;
  877. }
  878. touch_hcd->report_touch = false;
  879. touch_free_objects();
  880. mutex_lock(&touch_hcd->report_mutex);
  881. retval = touch_set_report_config();
  882. if (retval < 0) {
  883. LOGE(tcm_hcd->pdev->dev.parent,
  884. "Failed to set report config\n");
  885. goto exit;
  886. }
  887. retval = touch_get_input_params();
  888. if (retval < 0) {
  889. LOGE(tcm_hcd->pdev->dev.parent,
  890. "Failed to get input parameters\n");
  891. goto exit;
  892. }
  893. retval = touch_check_input_params();
  894. if (retval < 0) {
  895. LOGE(tcm_hcd->pdev->dev.parent,
  896. "Failed to check input parameters\n");
  897. goto exit;
  898. } else if (retval == 0) {
  899. LOGD(tcm_hcd->pdev->dev.parent,
  900. "Input parameters unchanged\n");
  901. goto exit;
  902. }
  903. if (touch_hcd->input_dev != NULL) {
  904. input_unregister_device(touch_hcd->input_dev);
  905. touch_hcd->input_dev = NULL;
  906. }
  907. retval = touch_set_input_dev();
  908. if (retval < 0) {
  909. LOGE(tcm_hcd->pdev->dev.parent,
  910. "Failed to set up input device\n");
  911. goto exit;
  912. }
  913. exit:
  914. mutex_unlock(&touch_hcd->report_mutex);
  915. touch_hcd->report_touch = retval < 0 ? false : true;
  916. return retval;
  917. }
  918. static int touch_init(struct syna_tcm_hcd *tcm_hcd)
  919. {
  920. int retval;
  921. touch_hcd = kzalloc(sizeof(*touch_hcd), GFP_KERNEL);
  922. if (!touch_hcd) {
  923. LOGE(tcm_hcd->pdev->dev.parent,
  924. "Failed to allocate memory for touch_hcd\n");
  925. return -ENOMEM;
  926. }
  927. touch_hcd->tcm_hcd = tcm_hcd;
  928. mutex_init(&touch_hcd->report_mutex);
  929. INIT_BUFFER(touch_hcd->out, false);
  930. INIT_BUFFER(touch_hcd->resp, false);
  931. retval = touch_set_input_reporting();
  932. if (retval < 0) {
  933. LOGE(tcm_hcd->pdev->dev.parent,
  934. "Failed to set up input reporting\n");
  935. goto err_set_input_reporting;
  936. }
  937. tcm_hcd->report_touch = touch_report;
  938. return 0;
  939. err_set_input_reporting:
  940. kfree(touch_hcd->touch_data.object_data);
  941. kfree(touch_hcd->prev_status);
  942. RELEASE_BUFFER(touch_hcd->resp);
  943. RELEASE_BUFFER(touch_hcd->out);
  944. kfree(touch_hcd);
  945. touch_hcd = NULL;
  946. return retval;
  947. }
  948. static int touch_remove(struct syna_tcm_hcd *tcm_hcd)
  949. {
  950. if (!touch_hcd)
  951. goto exit;
  952. tcm_hcd->report_touch = NULL;
  953. if (touch_hcd->input_dev)
  954. input_unregister_device(touch_hcd->input_dev);
  955. kfree(touch_hcd->touch_data.object_data);
  956. kfree(touch_hcd->prev_status);
  957. RELEASE_BUFFER(touch_hcd->resp);
  958. RELEASE_BUFFER(touch_hcd->out);
  959. kfree(touch_hcd);
  960. touch_hcd = NULL;
  961. exit:
  962. complete(&touch_remove_complete);
  963. return 0;
  964. }
  965. static int touch_syncbox(struct syna_tcm_hcd *tcm_hcd)
  966. {
  967. if (!touch_hcd)
  968. return 0;
  969. switch (tcm_hcd->report.id) {
  970. case REPORT_IDENTIFY:
  971. touch_free_objects();
  972. break;
  973. case REPORT_TOUCH:
  974. if (!touch_hcd->suspend_touch)
  975. touch_report();
  976. break;
  977. default:
  978. break;
  979. }
  980. return 0;
  981. }
  982. static int touch_asyncbox(struct syna_tcm_hcd *tcm_hcd)
  983. {
  984. int retval;
  985. if (!touch_hcd)
  986. return 0;
  987. switch (tcm_hcd->async_report_id) {
  988. case REPORT_IDENTIFY:
  989. if (tcm_hcd->id_info.mode != MODE_APPLICATION)
  990. break;
  991. retval = tcm_hcd->identify(tcm_hcd, false);
  992. if (retval < 0) {
  993. LOGE(tcm_hcd->pdev->dev.parent,
  994. "Failed to do identification\n");
  995. return retval;
  996. }
  997. retval = touch_set_input_reporting();
  998. if (retval < 0) {
  999. LOGE(tcm_hcd->pdev->dev.parent,
  1000. "Failed to set up input reporting\n");
  1001. return retval;
  1002. }
  1003. break;
  1004. default:
  1005. break;
  1006. }
  1007. return 0;
  1008. }
  1009. static int touch_reset(struct syna_tcm_hcd *tcm_hcd)
  1010. {
  1011. int retval;
  1012. if (!touch_hcd) {
  1013. retval = touch_init(tcm_hcd);
  1014. return retval;
  1015. }
  1016. if (tcm_hcd->id_info.mode == MODE_APPLICATION) {
  1017. retval = touch_set_input_reporting();
  1018. if (retval < 0) {
  1019. LOGE(tcm_hcd->pdev->dev.parent,
  1020. "Failed to set up input reporting\n");
  1021. return retval;
  1022. }
  1023. }
  1024. return 0;
  1025. }
  1026. static int touch_early_suspend(struct syna_tcm_hcd *tcm_hcd)
  1027. {
  1028. if (!touch_hcd)
  1029. return 0;
  1030. #ifdef WAKEUP_GESTURE
  1031. touch_hcd->suspend_touch = false;
  1032. #else
  1033. touch_hcd->suspend_touch = true;
  1034. #endif
  1035. touch_free_objects();
  1036. return 0;
  1037. }
  1038. static int touch_suspend(struct syna_tcm_hcd *tcm_hcd)
  1039. {
  1040. #ifdef WAKEUP_GESTURE
  1041. int retval;
  1042. #endif
  1043. if (!touch_hcd)
  1044. return 0;
  1045. touch_hcd->suspend_touch = true;
  1046. touch_free_objects();
  1047. #ifdef WAKEUP_GESTURE
  1048. if (!touch_hcd->irq_wake) {
  1049. enable_irq_wake(tcm_hcd->irq);
  1050. touch_hcd->irq_wake = true;
  1051. }
  1052. touch_hcd->suspend_touch = false;
  1053. retval = tcm_hcd->set_dynamic_config(tcm_hcd,
  1054. DC_IN_WAKEUP_GESTURE_MODE,
  1055. 1);
  1056. if (retval < 0) {
  1057. LOGE(tcm_hcd->pdev->dev.parent,
  1058. "Failed to enable wakeup gesture mode\n");
  1059. return retval;
  1060. }
  1061. #endif
  1062. return 0;
  1063. }
  1064. static int touch_resume(struct syna_tcm_hcd *tcm_hcd)
  1065. {
  1066. #ifdef WAKEUP_GESTURE
  1067. int retval;
  1068. #endif
  1069. if (!touch_hcd)
  1070. return 0;
  1071. touch_hcd->suspend_touch = false;
  1072. #ifdef WAKEUP_GESTURE
  1073. if (touch_hcd->irq_wake) {
  1074. disable_irq_wake(tcm_hcd->irq);
  1075. touch_hcd->irq_wake = false;
  1076. }
  1077. retval = tcm_hcd->set_dynamic_config(tcm_hcd,
  1078. DC_IN_WAKEUP_GESTURE_MODE,
  1079. 0);
  1080. if (retval < 0) {
  1081. LOGE(tcm_hcd->pdev->dev.parent,
  1082. "Failed to disable wakeup gesture mode\n");
  1083. return retval;
  1084. }
  1085. #endif
  1086. return 0;
  1087. }
  1088. static struct syna_tcm_module_cb touch_module = {
  1089. .type = TCM_TOUCH,
  1090. .init = touch_init,
  1091. .remove = touch_remove,
  1092. .syncbox = touch_syncbox,
  1093. .asyncbox = touch_asyncbox,
  1094. .reset = touch_reset,
  1095. .suspend = touch_suspend,
  1096. .resume = touch_resume,
  1097. .early_suspend = touch_early_suspend,
  1098. };
  1099. int touch_module_init(void)
  1100. {
  1101. return syna_tcm_add_module(&touch_module, true);
  1102. }
  1103. EXPORT_SYMBOL(touch_module_init);
  1104. void touch_module_exit(void)
  1105. {
  1106. syna_tcm_add_module(&touch_module, false);
  1107. wait_for_completion(&touch_remove_complete);
  1108. }
  1109. EXPORT_SYMBOL(touch_module_exit);