cyapa_gen5.c 81 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773
  1. /*
  2. * Cypress APA trackpad with I2C interface
  3. *
  4. * Author: Dudley Du <dudl@cypress.com>
  5. *
  6. * Copyright (C) 2014 Cypress Semiconductor, Inc.
  7. *
  8. * This file is subject to the terms and conditions of the GNU General Public
  9. * License. See the file COPYING in the main directory of this archive for
  10. * more details.
  11. */
  12. #include <linux/delay.h>
  13. #include <linux/i2c.h>
  14. #include <linux/input.h>
  15. #include <linux/input/mt.h>
  16. #include <linux/mutex.h>
  17. #include <linux/completion.h>
  18. #include <linux/slab.h>
  19. #include <asm/unaligned.h>
  20. #include <linux/crc-itu-t.h>
  21. #include "cyapa.h"
  22. /* Macro of Gen5 */
  23. #define RECORD_EVENT_NONE 0
  24. #define RECORD_EVENT_TOUCHDOWN 1
  25. #define RECORD_EVENT_DISPLACE 2
  26. #define RECORD_EVENT_LIFTOFF 3
  27. #define CYAPA_TSG_FLASH_MAP_BLOCK_SIZE 0x80
  28. #define CYAPA_TSG_IMG_FW_HDR_SIZE 13
  29. #define CYAPA_TSG_FW_ROW_SIZE (CYAPA_TSG_FLASH_MAP_BLOCK_SIZE)
  30. #define CYAPA_TSG_IMG_START_ROW_NUM 0x002e
  31. #define CYAPA_TSG_IMG_END_ROW_NUM 0x01fe
  32. #define CYAPA_TSG_IMG_APP_INTEGRITY_ROW_NUM 0x01ff
  33. #define CYAPA_TSG_IMG_MAX_RECORDS (CYAPA_TSG_IMG_END_ROW_NUM - \
  34. CYAPA_TSG_IMG_START_ROW_NUM + 1 + 1)
  35. #define CYAPA_TSG_IMG_READ_SIZE (CYAPA_TSG_FLASH_MAP_BLOCK_SIZE / 2)
  36. #define CYAPA_TSG_START_OF_APPLICATION 0x1700
  37. #define CYAPA_TSG_APP_INTEGRITY_SIZE 60
  38. #define CYAPA_TSG_FLASH_MAP_METADATA_SIZE 60
  39. #define CYAPA_TSG_BL_KEY_SIZE 8
  40. #define CYAPA_TSG_MAX_CMD_SIZE 256
  41. #define GEN5_BL_CMD_VERIFY_APP_INTEGRITY 0x31
  42. #define GEN5_BL_CMD_GET_BL_INFO 0x38
  43. #define GEN5_BL_CMD_PROGRAM_VERIFY_ROW 0x39
  44. #define GEN5_BL_CMD_LAUNCH_APP 0x3b
  45. #define GEN5_BL_CMD_INITIATE_BL 0x48
  46. #define GEN5_HID_DESCRIPTOR_ADDR 0x0001
  47. #define GEN5_REPORT_DESCRIPTOR_ADDR 0x0002
  48. #define GEN5_INPUT_REPORT_ADDR 0x0003
  49. #define GEN5_OUTPUT_REPORT_ADDR 0x0004
  50. #define GEN5_CMD_DATA_ADDR 0x0006
  51. #define GEN5_TOUCH_REPORT_HEAD_SIZE 7
  52. #define GEN5_TOUCH_REPORT_MAX_SIZE 127
  53. #define GEN5_BTN_REPORT_HEAD_SIZE 6
  54. #define GEN5_BTN_REPORT_MAX_SIZE 14
  55. #define GEN5_WAKEUP_EVENT_SIZE 4
  56. #define GEN5_RAW_DATA_HEAD_SIZE 24
  57. #define GEN5_BL_CMD_REPORT_ID 0x40
  58. #define GEN5_BL_RESP_REPORT_ID 0x30
  59. #define GEN5_APP_CMD_REPORT_ID 0x2f
  60. #define GEN5_APP_RESP_REPORT_ID 0x1f
  61. #define GEN5_APP_DEEP_SLEEP_REPORT_ID 0xf0
  62. #define GEN5_DEEP_SLEEP_RESP_LENGTH 5
  63. #define GEN5_CMD_GET_PARAMETER 0x05
  64. #define GEN5_CMD_SET_PARAMETER 0x06
  65. #define GEN5_PARAMETER_ACT_INTERVL_ID 0x4d
  66. #define GEN5_PARAMETER_ACT_INTERVL_SIZE 1
  67. #define GEN5_PARAMETER_ACT_LFT_INTERVL_ID 0x4f
  68. #define GEN5_PARAMETER_ACT_LFT_INTERVL_SIZE 2
  69. #define GEN5_PARAMETER_LP_INTRVL_ID 0x4c
  70. #define GEN5_PARAMETER_LP_INTRVL_SIZE 2
  71. #define GEN5_PARAMETER_DISABLE_PIP_REPORT 0x08
  72. #define GEN5_POWER_STATE_ACTIVE 0x01
  73. #define GEN5_POWER_STATE_LOOK_FOR_TOUCH 0x02
  74. #define GEN5_POWER_STATE_READY 0x03
  75. #define GEN5_POWER_STATE_IDLE 0x04
  76. #define GEN5_POWER_STATE_BTN_ONLY 0x05
  77. #define GEN5_POWER_STATE_OFF 0x06
  78. #define GEN5_DEEP_SLEEP_STATE_MASK 0x03
  79. #define GEN5_DEEP_SLEEP_STATE_ON 0x00
  80. #define GEN5_DEEP_SLEEP_STATE_OFF 0x01
  81. #define GEN5_DEEP_SLEEP_OPCODE 0x08
  82. #define GEN5_DEEP_SLEEP_OPCODE_MASK 0x0f
  83. #define GEN5_POWER_READY_MAX_INTRVL_TIME 50 /* Unit: ms */
  84. #define GEN5_POWER_IDLE_MAX_INTRVL_TIME 250 /* Unit: ms */
  85. #define GEN5_CMD_REPORT_ID_OFFSET 4
  86. #define GEN5_RESP_REPORT_ID_OFFSET 2
  87. #define GEN5_RESP_RSVD_OFFSET 3
  88. #define GEN5_RESP_RSVD_KEY 0x00
  89. #define GEN5_RESP_BL_SOP_OFFSET 4
  90. #define GEN5_SOP_KEY 0x01 /* Start of Packet */
  91. #define GEN5_EOP_KEY 0x17 /* End of Packet */
  92. #define GEN5_RESP_APP_CMD_OFFSET 4
  93. #define GET_GEN5_CMD_CODE(reg) ((reg) & 0x7f)
  94. #define VALID_CMD_RESP_HEADER(resp, cmd) \
  95. (((resp)[GEN5_RESP_REPORT_ID_OFFSET] == GEN5_APP_RESP_REPORT_ID) && \
  96. ((resp)[GEN5_RESP_RSVD_OFFSET] == GEN5_RESP_RSVD_KEY) && \
  97. (GET_GEN5_CMD_CODE((resp)[GEN5_RESP_APP_CMD_OFFSET]) == (cmd)))
  98. #define GEN5_MIN_BL_CMD_LENGTH 13
  99. #define GEN5_MIN_BL_RESP_LENGTH 11
  100. #define GEN5_MIN_APP_CMD_LENGTH 7
  101. #define GEN5_MIN_APP_RESP_LENGTH 5
  102. #define GEN5_UNSUPPORTED_CMD_RESP_LENGTH 6
  103. #define GEN5_RESP_LENGTH_OFFSET 0x00
  104. #define GEN5_RESP_LENGTH_SIZE 2
  105. #define GEN5_HID_DESCRIPTOR_SIZE 32
  106. #define GEN5_BL_HID_REPORT_ID 0xff
  107. #define GEN5_APP_HID_REPORT_ID 0xf7
  108. #define GEN5_BL_MAX_OUTPUT_LENGTH 0x0100
  109. #define GEN5_APP_MAX_OUTPUT_LENGTH 0x00fe
  110. #define GEN5_BL_REPORT_DESCRIPTOR_SIZE 0x1d
  111. #define GEN5_BL_REPORT_DESCRIPTOR_ID 0xfe
  112. #define GEN5_APP_REPORT_DESCRIPTOR_SIZE 0xee
  113. #define GEN5_APP_CONTRACT_REPORT_DESCRIPTOR_SIZE 0xfa
  114. #define GEN5_APP_REPORT_DESCRIPTOR_ID 0xf6
  115. #define GEN5_TOUCH_REPORT_ID 0x01
  116. #define GEN5_BTN_REPORT_ID 0x03
  117. #define GEN5_WAKEUP_EVENT_REPORT_ID 0x04
  118. #define GEN5_OLD_PUSH_BTN_REPORT_ID 0x05
  119. #define GEN5_PUSH_BTN_REPORT_ID 0x06
  120. #define GEN5_CMD_COMPLETE_SUCCESS(status) ((status) == 0x00)
  121. #define GEN5_BL_INITIATE_RESP_LEN 11
  122. #define GEN5_BL_FAIL_EXIT_RESP_LEN 11
  123. #define GEN5_BL_FAIL_EXIT_STATUS_CODE 0x0c
  124. #define GEN5_BL_VERIFY_INTEGRITY_RESP_LEN 12
  125. #define GEN5_BL_INTEGRITY_CHEKC_PASS 0x00
  126. #define GEN5_BL_BLOCK_WRITE_RESP_LEN 11
  127. #define GEN5_BL_READ_APP_INFO_RESP_LEN 31
  128. #define GEN5_CMD_CALIBRATE 0x28
  129. #define CYAPA_SENSING_MODE_MUTUAL_CAP_FINE 0x00
  130. #define CYAPA_SENSING_MODE_SELF_CAP 0x02
  131. #define GEN5_CMD_RETRIEVE_DATA_STRUCTURE 0x24
  132. #define GEN5_RETRIEVE_MUTUAL_PWC_DATA 0x00
  133. #define GEN5_RETRIEVE_SELF_CAP_PWC_DATA 0x01
  134. #define GEN5_RETRIEVE_DATA_ELEMENT_SIZE_MASK 0x07
  135. #define GEN5_CMD_EXECUTE_PANEL_SCAN 0x2a
  136. #define GEN5_CMD_RETRIEVE_PANEL_SCAN 0x2b
  137. #define GEN5_PANEL_SCAN_MUTUAL_RAW_DATA 0x00
  138. #define GEN5_PANEL_SCAN_MUTUAL_BASELINE 0x01
  139. #define GEN5_PANEL_SCAN_MUTUAL_DIFFCOUNT 0x02
  140. #define GEN5_PANEL_SCAN_SELF_RAW_DATA 0x03
  141. #define GEN5_PANEL_SCAN_SELF_BASELINE 0x04
  142. #define GEN5_PANEL_SCAN_SELF_DIFFCOUNT 0x05
  143. /* The offset only valid for reterive PWC and panel scan commands */
  144. #define GEN5_RESP_DATA_STRUCTURE_OFFSET 10
  145. #define GEN5_PWC_DATA_ELEMENT_SIZE_MASK 0x07
  146. #define GEN5_NUMBER_OF_TOUCH_OFFSET 5
  147. #define GEN5_NUMBER_OF_TOUCH_MASK 0x1f
  148. #define GEN5_BUTTONS_OFFSET 5
  149. #define GEN5_BUTTONS_MASK 0x0f
  150. #define GEN5_GET_EVENT_ID(reg) (((reg) >> 5) & 0x03)
  151. #define GEN5_GET_TOUCH_ID(reg) ((reg) & 0x1f)
  152. #define GEN5_PRODUCT_FAMILY_MASK 0xf000
  153. #define GEN5_PRODUCT_FAMILY_TRACKPAD 0x1000
  154. #define TSG_INVALID_CMD 0xff
  155. struct cyapa_gen5_touch_record {
  156. /*
  157. * Bit 7 - 3: reserved
  158. * Bit 2 - 0: touch type;
  159. * 0 : standard finger;
  160. * 1 - 15 : reserved.
  161. */
  162. u8 touch_type;
  163. /*
  164. * Bit 7: indicates touch liftoff status.
  165. * 0 : touch is currently on the panel.
  166. * 1 : touch record indicates a liftoff.
  167. * Bit 6 - 5: indicates an event associated with this touch instance
  168. * 0 : no event
  169. * 1 : touchdown
  170. * 2 : significant displacement (> active distance)
  171. * 3 : liftoff (record reports last known coordinates)
  172. * Bit 4 - 0: An arbitrary ID tag associated with a finger
  173. * to allow tracking a touch as it moves around the panel.
  174. */
  175. u8 touch_tip_event_id;
  176. /* Bit 7 - 0 of X-axis coordinate of the touch in pixel. */
  177. u8 x_lo;
  178. /* Bit 15 - 8 of X-axis coordinate of the touch in pixel. */
  179. u8 x_hi;
  180. /* Bit 7 - 0 of Y-axis coordinate of the touch in pixel. */
  181. u8 y_lo;
  182. /* Bit 15 - 8 of Y-axis coordinate of the touch in pixel. */
  183. u8 y_hi;
  184. /* Touch intensity in counts, pressure value. */
  185. u8 z;
  186. /*
  187. * The length of the major axis of the ellipse of contact between
  188. * the finger and the panel (ABS_MT_TOUCH_MAJOR).
  189. */
  190. u8 major_axis_len;
  191. /*
  192. * The length of the minor axis of the ellipse of contact between
  193. * the finger and the panel (ABS_MT_TOUCH_MINOR).
  194. */
  195. u8 minor_axis_len;
  196. /*
  197. * The length of the major axis of the approaching tool.
  198. * (ABS_MT_WIDTH_MAJOR)
  199. */
  200. u8 major_tool_len;
  201. /*
  202. * The length of the minor axis of the approaching tool.
  203. * (ABS_MT_WIDTH_MINOR)
  204. */
  205. u8 minor_tool_len;
  206. /*
  207. * The angle between the panel vertical axis and
  208. * the major axis of the contact ellipse. This value is an 8-bit
  209. * signed integer. The range is -127 to +127 (corresponding to
  210. * -90 degree and +90 degree respectively).
  211. * The positive direction is clockwise from the vertical axis.
  212. * If the ellipse of contact degenerates into a circle,
  213. * orientation is reported as 0.
  214. */
  215. u8 orientation;
  216. } __packed;
  217. struct cyapa_gen5_report_data {
  218. u8 report_head[GEN5_TOUCH_REPORT_HEAD_SIZE];
  219. struct cyapa_gen5_touch_record touch_records[10];
  220. } __packed;
  221. struct cyapa_tsg_bin_image_head {
  222. u8 head_size; /* Unit: bytes, including itself. */
  223. u8 ttda_driver_major_version; /* Reserved as 0. */
  224. u8 ttda_driver_minor_version; /* Reserved as 0. */
  225. u8 fw_major_version;
  226. u8 fw_minor_version;
  227. u8 fw_revision_control_number[8];
  228. } __packed;
  229. struct cyapa_tsg_bin_image_data_record {
  230. u8 flash_array_id;
  231. __be16 row_number;
  232. /* The number of bytes of flash data contained in this record. */
  233. __be16 record_len;
  234. /* The flash program data. */
  235. u8 record_data[CYAPA_TSG_FW_ROW_SIZE];
  236. } __packed;
  237. struct cyapa_tsg_bin_image {
  238. struct cyapa_tsg_bin_image_head image_head;
  239. struct cyapa_tsg_bin_image_data_record records[0];
  240. } __packed;
  241. struct gen5_bl_packet_start {
  242. u8 sop; /* Start of packet, must be 01h */
  243. u8 cmd_code;
  244. __le16 data_length; /* Size of data parameter start from data[0] */
  245. } __packed;
  246. struct gen5_bl_packet_end {
  247. __le16 crc;
  248. u8 eop; /* End of packet, must be 17h */
  249. } __packed;
  250. struct gen5_bl_cmd_head {
  251. __le16 addr; /* Output report register address, must be 0004h */
  252. /* Size of packet not including output report register address */
  253. __le16 length;
  254. u8 report_id; /* Bootloader output report id, must be 40h */
  255. u8 rsvd; /* Reserved, must be 0 */
  256. struct gen5_bl_packet_start packet_start;
  257. u8 data[0]; /* Command data variable based on commands */
  258. } __packed;
  259. /* Initiate bootload command data structure. */
  260. struct gen5_bl_initiate_cmd_data {
  261. /* Key must be "A5h 01h 02h 03h FFh FEh FDh 5Ah" */
  262. u8 key[CYAPA_TSG_BL_KEY_SIZE];
  263. u8 metadata_raw_parameter[CYAPA_TSG_FLASH_MAP_METADATA_SIZE];
  264. __le16 metadata_crc;
  265. } __packed;
  266. struct gen5_bl_metadata_row_params {
  267. __le16 size;
  268. __le16 maximum_size;
  269. __le32 app_start;
  270. __le16 app_len;
  271. __le16 app_crc;
  272. __le32 app_entry;
  273. __le32 upgrade_start;
  274. __le16 upgrade_len;
  275. __le16 entry_row_crc;
  276. u8 padding[36]; /* Padding data must be 0 */
  277. __le16 metadata_crc; /* CRC starts at offset of 60 */
  278. } __packed;
  279. /* Bootload program and verify row command data structure */
  280. struct gen5_bl_flash_row_head {
  281. u8 flash_array_id;
  282. __le16 flash_row_id;
  283. u8 flash_data[0];
  284. } __packed;
  285. struct gen5_app_cmd_head {
  286. __le16 addr; /* Output report register address, must be 0004h */
  287. /* Size of packet not including output report register address */
  288. __le16 length;
  289. u8 report_id; /* Application output report id, must be 2Fh */
  290. u8 rsvd; /* Reserved, must be 0 */
  291. /*
  292. * Bit 7: reserved, must be 0.
  293. * Bit 6-0: command code.
  294. */
  295. u8 cmd_code;
  296. u8 parameter_data[0]; /* Parameter data variable based on cmd_code */
  297. } __packed;
  298. /* Application get/set parameter command data structure */
  299. struct gen5_app_set_parameter_data {
  300. u8 parameter_id;
  301. u8 parameter_size;
  302. __le32 value;
  303. } __packed;
  304. struct gen5_app_get_parameter_data {
  305. u8 parameter_id;
  306. } __packed;
  307. struct gen5_retrieve_panel_scan_data {
  308. __le16 read_offset;
  309. __le16 read_elements;
  310. u8 data_id;
  311. } __packed;
  312. /* Variables to record latest gen5 trackpad power states. */
  313. #define GEN5_DEV_SET_PWR_STATE(cyapa, s) ((cyapa)->dev_pwr_mode = (s))
  314. #define GEN5_DEV_GET_PWR_STATE(cyapa) ((cyapa)->dev_pwr_mode)
  315. #define GEN5_DEV_SET_SLEEP_TIME(cyapa, t) ((cyapa)->dev_sleep_time = (t))
  316. #define GEN5_DEV_GET_SLEEP_TIME(cyapa) ((cyapa)->dev_sleep_time)
  317. #define GEN5_DEV_UNINIT_SLEEP_TIME(cyapa) \
  318. (((cyapa)->dev_sleep_time) == UNINIT_SLEEP_TIME)
  319. static u8 cyapa_gen5_bl_cmd_key[] = { 0xa5, 0x01, 0x02, 0x03,
  320. 0xff, 0xfe, 0xfd, 0x5a };
  321. static int cyapa_gen5_initialize(struct cyapa *cyapa)
  322. {
  323. struct cyapa_gen5_cmd_states *gen5_pip = &cyapa->cmd_states.gen5;
  324. init_completion(&gen5_pip->cmd_ready);
  325. atomic_set(&gen5_pip->cmd_issued, 0);
  326. mutex_init(&gen5_pip->cmd_lock);
  327. gen5_pip->resp_sort_func = NULL;
  328. gen5_pip->in_progress_cmd = TSG_INVALID_CMD;
  329. gen5_pip->resp_data = NULL;
  330. gen5_pip->resp_len = NULL;
  331. cyapa->dev_pwr_mode = UNINIT_PWR_MODE;
  332. cyapa->dev_sleep_time = UNINIT_SLEEP_TIME;
  333. return 0;
  334. }
  335. /* Return negative errno, or else the number of bytes read. */
  336. static ssize_t cyapa_i2c_pip_read(struct cyapa *cyapa, u8 *buf, size_t size)
  337. {
  338. int ret;
  339. if (size == 0)
  340. return 0;
  341. if (!buf || size > CYAPA_REG_MAP_SIZE)
  342. return -EINVAL;
  343. ret = i2c_master_recv(cyapa->client, buf, size);
  344. if (ret != size)
  345. return (ret < 0) ? ret : -EIO;
  346. return size;
  347. }
  348. /**
  349. * Return a negative errno code else zero on success.
  350. */
  351. static ssize_t cyapa_i2c_pip_write(struct cyapa *cyapa, u8 *buf, size_t size)
  352. {
  353. int ret;
  354. if (!buf || !size)
  355. return -EINVAL;
  356. ret = i2c_master_send(cyapa->client, buf, size);
  357. if (ret != size)
  358. return (ret < 0) ? ret : -EIO;
  359. return 0;
  360. }
  361. /**
  362. * This function is aimed to dump all not read data in Gen5 trackpad
  363. * before send any command, otherwise, the interrupt line will be blocked.
  364. */
  365. static int cyapa_empty_pip_output_data(struct cyapa *cyapa,
  366. u8 *buf, int *len, cb_sort func)
  367. {
  368. struct cyapa_gen5_cmd_states *gen5_pip = &cyapa->cmd_states.gen5;
  369. int length;
  370. int report_count;
  371. int empty_count;
  372. int buf_len;
  373. int error;
  374. buf_len = 0;
  375. if (len) {
  376. buf_len = (*len < CYAPA_REG_MAP_SIZE) ?
  377. *len : CYAPA_REG_MAP_SIZE;
  378. *len = 0;
  379. }
  380. report_count = 8; /* max 7 pending data before command response data */
  381. empty_count = 0;
  382. do {
  383. /*
  384. * Depending on testing in cyapa driver, there are max 5 "02 00"
  385. * packets between two valid buffered data report in firmware.
  386. * So in order to dump all buffered data out and
  387. * make interrupt line release for reassert again,
  388. * we must set the empty_count check value bigger than 5 to
  389. * make it work. Otherwise, in some situation,
  390. * the interrupt line may unable to reactive again,
  391. * which will cause trackpad device unable to
  392. * report data any more.
  393. * for example, it may happen in EFT and ESD testing.
  394. */
  395. if (empty_count > 5)
  396. return 0;
  397. error = cyapa_i2c_pip_read(cyapa, gen5_pip->empty_buf,
  398. GEN5_RESP_LENGTH_SIZE);
  399. if (error < 0)
  400. return error;
  401. length = get_unaligned_le16(gen5_pip->empty_buf);
  402. if (length == GEN5_RESP_LENGTH_SIZE) {
  403. empty_count++;
  404. continue;
  405. } else if (length > CYAPA_REG_MAP_SIZE) {
  406. /* Should not happen */
  407. return -EINVAL;
  408. } else if (length == 0) {
  409. /* Application or bootloader launch data polled out. */
  410. length = GEN5_RESP_LENGTH_SIZE;
  411. if (buf && buf_len && func &&
  412. func(cyapa, gen5_pip->empty_buf, length)) {
  413. length = min(buf_len, length);
  414. memcpy(buf, gen5_pip->empty_buf, length);
  415. *len = length;
  416. /* Response found, success. */
  417. return 0;
  418. }
  419. continue;
  420. }
  421. error = cyapa_i2c_pip_read(cyapa, gen5_pip->empty_buf, length);
  422. if (error < 0)
  423. return error;
  424. report_count--;
  425. empty_count = 0;
  426. length = get_unaligned_le16(gen5_pip->empty_buf);
  427. if (length <= GEN5_RESP_LENGTH_SIZE) {
  428. empty_count++;
  429. } else if (buf && buf_len && func &&
  430. func(cyapa, gen5_pip->empty_buf, length)) {
  431. length = min(buf_len, length);
  432. memcpy(buf, gen5_pip->empty_buf, length);
  433. *len = length;
  434. /* Response found, success. */
  435. return 0;
  436. }
  437. error = -EINVAL;
  438. } while (report_count);
  439. return error;
  440. }
  441. static int cyapa_do_i2c_pip_cmd_irq_sync(
  442. struct cyapa *cyapa,
  443. u8 *cmd, size_t cmd_len,
  444. unsigned long timeout)
  445. {
  446. struct cyapa_gen5_cmd_states *gen5_pip = &cyapa->cmd_states.gen5;
  447. int error;
  448. /* Wait for interrupt to set ready completion */
  449. init_completion(&gen5_pip->cmd_ready);
  450. atomic_inc(&gen5_pip->cmd_issued);
  451. error = cyapa_i2c_pip_write(cyapa, cmd, cmd_len);
  452. if (error) {
  453. atomic_dec(&gen5_pip->cmd_issued);
  454. return (error < 0) ? error : -EIO;
  455. }
  456. /* Wait for interrupt to indicate command is completed. */
  457. timeout = wait_for_completion_timeout(&gen5_pip->cmd_ready,
  458. msecs_to_jiffies(timeout));
  459. if (timeout == 0) {
  460. atomic_dec(&gen5_pip->cmd_issued);
  461. return -ETIMEDOUT;
  462. }
  463. return 0;
  464. }
  465. static int cyapa_do_i2c_pip_cmd_polling(
  466. struct cyapa *cyapa,
  467. u8 *cmd, size_t cmd_len,
  468. u8 *resp_data, int *resp_len,
  469. unsigned long timeout,
  470. cb_sort func)
  471. {
  472. struct cyapa_gen5_cmd_states *gen5_pip = &cyapa->cmd_states.gen5;
  473. int tries;
  474. int length;
  475. int error;
  476. atomic_inc(&gen5_pip->cmd_issued);
  477. error = cyapa_i2c_pip_write(cyapa, cmd, cmd_len);
  478. if (error) {
  479. atomic_dec(&gen5_pip->cmd_issued);
  480. return error < 0 ? error : -EIO;
  481. }
  482. length = resp_len ? *resp_len : 0;
  483. if (resp_data && resp_len && length != 0 && func) {
  484. tries = timeout / 5;
  485. do {
  486. usleep_range(3000, 5000);
  487. *resp_len = length;
  488. error = cyapa_empty_pip_output_data(cyapa,
  489. resp_data, resp_len, func);
  490. if (error || *resp_len == 0)
  491. continue;
  492. else
  493. break;
  494. } while (--tries > 0);
  495. if ((error || *resp_len == 0) || tries <= 0)
  496. error = error ? error : -ETIMEDOUT;
  497. }
  498. atomic_dec(&gen5_pip->cmd_issued);
  499. return error;
  500. }
  501. static int cyapa_i2c_pip_cmd_irq_sync(
  502. struct cyapa *cyapa,
  503. u8 *cmd, int cmd_len,
  504. u8 *resp_data, int *resp_len,
  505. unsigned long timeout,
  506. cb_sort func,
  507. bool irq_mode)
  508. {
  509. struct cyapa_gen5_cmd_states *gen5_pip = &cyapa->cmd_states.gen5;
  510. int error;
  511. if (!cmd || !cmd_len)
  512. return -EINVAL;
  513. /* Commands must be serialized. */
  514. error = mutex_lock_interruptible(&gen5_pip->cmd_lock);
  515. if (error)
  516. return error;
  517. gen5_pip->resp_sort_func = func;
  518. gen5_pip->resp_data = resp_data;
  519. gen5_pip->resp_len = resp_len;
  520. if (cmd_len >= GEN5_MIN_APP_CMD_LENGTH &&
  521. cmd[4] == GEN5_APP_CMD_REPORT_ID) {
  522. /* Application command */
  523. gen5_pip->in_progress_cmd = cmd[6] & 0x7f;
  524. } else if (cmd_len >= GEN5_MIN_BL_CMD_LENGTH &&
  525. cmd[4] == GEN5_BL_CMD_REPORT_ID) {
  526. /* Bootloader command */
  527. gen5_pip->in_progress_cmd = cmd[7];
  528. }
  529. /* Send command data, wait and read output response data's length. */
  530. if (irq_mode) {
  531. gen5_pip->is_irq_mode = true;
  532. error = cyapa_do_i2c_pip_cmd_irq_sync(cyapa, cmd, cmd_len,
  533. timeout);
  534. if (error == -ETIMEDOUT && resp_data &&
  535. resp_len && *resp_len != 0 && func) {
  536. /*
  537. * For some old version, there was no interrupt for
  538. * the command response data, so need to poll here
  539. * to try to get the response data.
  540. */
  541. error = cyapa_empty_pip_output_data(cyapa,
  542. resp_data, resp_len, func);
  543. if (error || *resp_len == 0)
  544. error = error ? error : -ETIMEDOUT;
  545. }
  546. } else {
  547. gen5_pip->is_irq_mode = false;
  548. error = cyapa_do_i2c_pip_cmd_polling(cyapa, cmd, cmd_len,
  549. resp_data, resp_len, timeout, func);
  550. }
  551. gen5_pip->resp_sort_func = NULL;
  552. gen5_pip->resp_data = NULL;
  553. gen5_pip->resp_len = NULL;
  554. gen5_pip->in_progress_cmd = TSG_INVALID_CMD;
  555. mutex_unlock(&gen5_pip->cmd_lock);
  556. return error;
  557. }
  558. static bool cyapa_gen5_sort_tsg_pip_bl_resp_data(struct cyapa *cyapa,
  559. u8 *data, int len)
  560. {
  561. if (!data || len < GEN5_MIN_BL_RESP_LENGTH)
  562. return false;
  563. /* Bootloader input report id 30h */
  564. if (data[GEN5_RESP_REPORT_ID_OFFSET] == GEN5_BL_RESP_REPORT_ID &&
  565. data[GEN5_RESP_RSVD_OFFSET] == GEN5_RESP_RSVD_KEY &&
  566. data[GEN5_RESP_BL_SOP_OFFSET] == GEN5_SOP_KEY)
  567. return true;
  568. return false;
  569. }
  570. static bool cyapa_gen5_sort_tsg_pip_app_resp_data(struct cyapa *cyapa,
  571. u8 *data, int len)
  572. {
  573. struct cyapa_gen5_cmd_states *gen5_pip = &cyapa->cmd_states.gen5;
  574. int resp_len;
  575. if (!data || len < GEN5_MIN_APP_RESP_LENGTH)
  576. return false;
  577. if (data[GEN5_RESP_REPORT_ID_OFFSET] == GEN5_APP_RESP_REPORT_ID &&
  578. data[GEN5_RESP_RSVD_OFFSET] == GEN5_RESP_RSVD_KEY) {
  579. resp_len = get_unaligned_le16(&data[GEN5_RESP_LENGTH_OFFSET]);
  580. if (GET_GEN5_CMD_CODE(data[GEN5_RESP_APP_CMD_OFFSET]) == 0x00 &&
  581. resp_len == GEN5_UNSUPPORTED_CMD_RESP_LENGTH &&
  582. data[5] == gen5_pip->in_progress_cmd) {
  583. /* Unsupported command code */
  584. return false;
  585. } else if (GET_GEN5_CMD_CODE(data[GEN5_RESP_APP_CMD_OFFSET]) ==
  586. gen5_pip->in_progress_cmd) {
  587. /* Correct command response received */
  588. return true;
  589. }
  590. }
  591. return false;
  592. }
  593. static bool cyapa_gen5_sort_application_launch_data(struct cyapa *cyapa,
  594. u8 *buf, int len)
  595. {
  596. if (buf == NULL || len < GEN5_RESP_LENGTH_SIZE)
  597. return false;
  598. /*
  599. * After reset or power on, trackpad device always sets to 0x00 0x00
  600. * to indicate a reset or power on event.
  601. */
  602. if (buf[0] == 0 && buf[1] == 0)
  603. return true;
  604. return false;
  605. }
  606. static bool cyapa_gen5_sort_hid_descriptor_data(struct cyapa *cyapa,
  607. u8 *buf, int len)
  608. {
  609. int resp_len;
  610. int max_output_len;
  611. /* Check hid descriptor. */
  612. if (len != GEN5_HID_DESCRIPTOR_SIZE)
  613. return false;
  614. resp_len = get_unaligned_le16(&buf[GEN5_RESP_LENGTH_OFFSET]);
  615. max_output_len = get_unaligned_le16(&buf[16]);
  616. if (resp_len == GEN5_HID_DESCRIPTOR_SIZE) {
  617. if (buf[GEN5_RESP_REPORT_ID_OFFSET] == GEN5_BL_HID_REPORT_ID &&
  618. max_output_len == GEN5_BL_MAX_OUTPUT_LENGTH) {
  619. /* BL mode HID Descriptor */
  620. return true;
  621. } else if ((buf[GEN5_RESP_REPORT_ID_OFFSET] ==
  622. GEN5_APP_HID_REPORT_ID) &&
  623. max_output_len == GEN5_APP_MAX_OUTPUT_LENGTH) {
  624. /* APP mode HID Descriptor */
  625. return true;
  626. }
  627. }
  628. return false;
  629. }
  630. static bool cyapa_gen5_sort_deep_sleep_data(struct cyapa *cyapa,
  631. u8 *buf, int len)
  632. {
  633. if (len == GEN5_DEEP_SLEEP_RESP_LENGTH &&
  634. buf[GEN5_RESP_REPORT_ID_OFFSET] ==
  635. GEN5_APP_DEEP_SLEEP_REPORT_ID &&
  636. (buf[4] & GEN5_DEEP_SLEEP_OPCODE_MASK) ==
  637. GEN5_DEEP_SLEEP_OPCODE)
  638. return true;
  639. return false;
  640. }
  641. static int gen5_idle_state_parse(struct cyapa *cyapa)
  642. {
  643. u8 resp_data[GEN5_HID_DESCRIPTOR_SIZE];
  644. int max_output_len;
  645. int length;
  646. u8 cmd[2];
  647. int ret;
  648. int error;
  649. /*
  650. * Dump all buffered data firstly for the situation
  651. * when the trackpad is just power on the cyapa go here.
  652. */
  653. cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
  654. memset(resp_data, 0, sizeof(resp_data));
  655. ret = cyapa_i2c_pip_read(cyapa, resp_data, 3);
  656. if (ret != 3)
  657. return ret < 0 ? ret : -EIO;
  658. length = get_unaligned_le16(&resp_data[GEN5_RESP_LENGTH_OFFSET]);
  659. if (length == GEN5_RESP_LENGTH_SIZE) {
  660. /* Normal state of Gen5 with no data to respose */
  661. cyapa->gen = CYAPA_GEN5;
  662. cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
  663. /* Read description from trackpad device */
  664. cmd[0] = 0x01;
  665. cmd[1] = 0x00;
  666. length = GEN5_HID_DESCRIPTOR_SIZE;
  667. error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
  668. cmd, GEN5_RESP_LENGTH_SIZE,
  669. resp_data, &length,
  670. 300,
  671. cyapa_gen5_sort_hid_descriptor_data,
  672. false);
  673. if (error)
  674. return error;
  675. length = get_unaligned_le16(
  676. &resp_data[GEN5_RESP_LENGTH_OFFSET]);
  677. max_output_len = get_unaligned_le16(&resp_data[16]);
  678. if ((length == GEN5_HID_DESCRIPTOR_SIZE ||
  679. length == GEN5_RESP_LENGTH_SIZE) &&
  680. (resp_data[GEN5_RESP_REPORT_ID_OFFSET] ==
  681. GEN5_BL_HID_REPORT_ID) &&
  682. max_output_len == GEN5_BL_MAX_OUTPUT_LENGTH) {
  683. /* BL mode HID Description read */
  684. cyapa->state = CYAPA_STATE_GEN5_BL;
  685. } else if ((length == GEN5_HID_DESCRIPTOR_SIZE ||
  686. length == GEN5_RESP_LENGTH_SIZE) &&
  687. (resp_data[GEN5_RESP_REPORT_ID_OFFSET] ==
  688. GEN5_APP_HID_REPORT_ID) &&
  689. max_output_len == GEN5_APP_MAX_OUTPUT_LENGTH) {
  690. /* APP mode HID Description read */
  691. cyapa->state = CYAPA_STATE_GEN5_APP;
  692. } else {
  693. /* Should not happen!!! */
  694. cyapa->state = CYAPA_STATE_NO_DEVICE;
  695. }
  696. }
  697. return 0;
  698. }
  699. static int gen5_hid_description_header_parse(struct cyapa *cyapa, u8 *reg_data)
  700. {
  701. int length;
  702. u8 resp_data[32];
  703. int max_output_len;
  704. int ret;
  705. /* 0x20 0x00 0xF7 is Gen5 Application HID Description Header;
  706. * 0x20 0x00 0xFF is Gen5 Bootloader HID Description Header.
  707. *
  708. * Must read HID Description content through out,
  709. * otherwise Gen5 trackpad cannot response next command
  710. * or report any touch or button data.
  711. */
  712. ret = cyapa_i2c_pip_read(cyapa, resp_data,
  713. GEN5_HID_DESCRIPTOR_SIZE);
  714. if (ret != GEN5_HID_DESCRIPTOR_SIZE)
  715. return ret < 0 ? ret : -EIO;
  716. length = get_unaligned_le16(&resp_data[GEN5_RESP_LENGTH_OFFSET]);
  717. max_output_len = get_unaligned_le16(&resp_data[16]);
  718. if (length == GEN5_RESP_LENGTH_SIZE) {
  719. if (reg_data[GEN5_RESP_REPORT_ID_OFFSET] ==
  720. GEN5_BL_HID_REPORT_ID) {
  721. /*
  722. * BL mode HID Description has been previously
  723. * read out.
  724. */
  725. cyapa->gen = CYAPA_GEN5;
  726. cyapa->state = CYAPA_STATE_GEN5_BL;
  727. } else {
  728. /*
  729. * APP mode HID Description has been previously
  730. * read out.
  731. */
  732. cyapa->gen = CYAPA_GEN5;
  733. cyapa->state = CYAPA_STATE_GEN5_APP;
  734. }
  735. } else if (length == GEN5_HID_DESCRIPTOR_SIZE &&
  736. resp_data[2] == GEN5_BL_HID_REPORT_ID &&
  737. max_output_len == GEN5_BL_MAX_OUTPUT_LENGTH) {
  738. /* BL mode HID Description read. */
  739. cyapa->gen = CYAPA_GEN5;
  740. cyapa->state = CYAPA_STATE_GEN5_BL;
  741. } else if (length == GEN5_HID_DESCRIPTOR_SIZE &&
  742. (resp_data[GEN5_RESP_REPORT_ID_OFFSET] ==
  743. GEN5_APP_HID_REPORT_ID) &&
  744. max_output_len == GEN5_APP_MAX_OUTPUT_LENGTH) {
  745. /* APP mode HID Description read. */
  746. cyapa->gen = CYAPA_GEN5;
  747. cyapa->state = CYAPA_STATE_GEN5_APP;
  748. } else {
  749. /* Should not happen!!! */
  750. cyapa->state = CYAPA_STATE_NO_DEVICE;
  751. }
  752. return 0;
  753. }
  754. static int gen5_report_data_header_parse(struct cyapa *cyapa, u8 *reg_data)
  755. {
  756. int length;
  757. length = get_unaligned_le16(&reg_data[GEN5_RESP_LENGTH_OFFSET]);
  758. switch (reg_data[GEN5_RESP_REPORT_ID_OFFSET]) {
  759. case GEN5_TOUCH_REPORT_ID:
  760. if (length < GEN5_TOUCH_REPORT_HEAD_SIZE ||
  761. length > GEN5_TOUCH_REPORT_MAX_SIZE)
  762. return -EINVAL;
  763. break;
  764. case GEN5_BTN_REPORT_ID:
  765. case GEN5_OLD_PUSH_BTN_REPORT_ID:
  766. case GEN5_PUSH_BTN_REPORT_ID:
  767. if (length < GEN5_BTN_REPORT_HEAD_SIZE ||
  768. length > GEN5_BTN_REPORT_MAX_SIZE)
  769. return -EINVAL;
  770. break;
  771. case GEN5_WAKEUP_EVENT_REPORT_ID:
  772. if (length != GEN5_WAKEUP_EVENT_SIZE)
  773. return -EINVAL;
  774. break;
  775. default:
  776. return -EINVAL;
  777. }
  778. cyapa->gen = CYAPA_GEN5;
  779. cyapa->state = CYAPA_STATE_GEN5_APP;
  780. return 0;
  781. }
  782. static int gen5_cmd_resp_header_parse(struct cyapa *cyapa, u8 *reg_data)
  783. {
  784. struct cyapa_gen5_cmd_states *gen5_pip = &cyapa->cmd_states.gen5;
  785. int length;
  786. int ret;
  787. /*
  788. * Must read report data through out,
  789. * otherwise Gen5 trackpad cannot response next command
  790. * or report any touch or button data.
  791. */
  792. length = get_unaligned_le16(&reg_data[GEN5_RESP_LENGTH_OFFSET]);
  793. ret = cyapa_i2c_pip_read(cyapa, gen5_pip->empty_buf, length);
  794. if (ret != length)
  795. return ret < 0 ? ret : -EIO;
  796. if (length == GEN5_RESP_LENGTH_SIZE) {
  797. /* Previous command has read the data through out. */
  798. if (reg_data[GEN5_RESP_REPORT_ID_OFFSET] ==
  799. GEN5_BL_RESP_REPORT_ID) {
  800. /* Gen5 BL command response data detected */
  801. cyapa->gen = CYAPA_GEN5;
  802. cyapa->state = CYAPA_STATE_GEN5_BL;
  803. } else {
  804. /* Gen5 APP command response data detected */
  805. cyapa->gen = CYAPA_GEN5;
  806. cyapa->state = CYAPA_STATE_GEN5_APP;
  807. }
  808. } else if ((gen5_pip->empty_buf[GEN5_RESP_REPORT_ID_OFFSET] ==
  809. GEN5_BL_RESP_REPORT_ID) &&
  810. (gen5_pip->empty_buf[GEN5_RESP_RSVD_OFFSET] ==
  811. GEN5_RESP_RSVD_KEY) &&
  812. (gen5_pip->empty_buf[GEN5_RESP_BL_SOP_OFFSET] ==
  813. GEN5_SOP_KEY) &&
  814. (gen5_pip->empty_buf[length - 1] ==
  815. GEN5_EOP_KEY)) {
  816. /* Gen5 BL command response data detected */
  817. cyapa->gen = CYAPA_GEN5;
  818. cyapa->state = CYAPA_STATE_GEN5_BL;
  819. } else if (gen5_pip->empty_buf[GEN5_RESP_REPORT_ID_OFFSET] ==
  820. GEN5_APP_RESP_REPORT_ID &&
  821. gen5_pip->empty_buf[GEN5_RESP_RSVD_OFFSET] ==
  822. GEN5_RESP_RSVD_KEY) {
  823. /* Gen5 APP command response data detected */
  824. cyapa->gen = CYAPA_GEN5;
  825. cyapa->state = CYAPA_STATE_GEN5_APP;
  826. } else {
  827. /* Should not happen!!! */
  828. cyapa->state = CYAPA_STATE_NO_DEVICE;
  829. }
  830. return 0;
  831. }
  832. static int cyapa_gen5_state_parse(struct cyapa *cyapa, u8 *reg_data, int len)
  833. {
  834. int length;
  835. if (!reg_data || len < 3)
  836. return -EINVAL;
  837. cyapa->state = CYAPA_STATE_NO_DEVICE;
  838. /* Parse based on Gen5 characteristic registers and bits */
  839. length = get_unaligned_le16(&reg_data[GEN5_RESP_LENGTH_OFFSET]);
  840. if (length == 0 || length == GEN5_RESP_LENGTH_SIZE) {
  841. gen5_idle_state_parse(cyapa);
  842. } else if (length == GEN5_HID_DESCRIPTOR_SIZE &&
  843. (reg_data[2] == GEN5_BL_HID_REPORT_ID ||
  844. reg_data[2] == GEN5_APP_HID_REPORT_ID)) {
  845. gen5_hid_description_header_parse(cyapa, reg_data);
  846. } else if ((length == GEN5_APP_REPORT_DESCRIPTOR_SIZE ||
  847. length == GEN5_APP_CONTRACT_REPORT_DESCRIPTOR_SIZE) &&
  848. reg_data[2] == GEN5_APP_REPORT_DESCRIPTOR_ID) {
  849. /* 0xEE 0x00 0xF6 is Gen5 APP report description header. */
  850. cyapa->gen = CYAPA_GEN5;
  851. cyapa->state = CYAPA_STATE_GEN5_APP;
  852. } else if (length == GEN5_BL_REPORT_DESCRIPTOR_SIZE &&
  853. reg_data[2] == GEN5_BL_REPORT_DESCRIPTOR_ID) {
  854. /* 0x1D 0x00 0xFE is Gen5 BL report descriptior header. */
  855. cyapa->gen = CYAPA_GEN5;
  856. cyapa->state = CYAPA_STATE_GEN5_BL;
  857. } else if (reg_data[2] == GEN5_TOUCH_REPORT_ID ||
  858. reg_data[2] == GEN5_BTN_REPORT_ID ||
  859. reg_data[2] == GEN5_OLD_PUSH_BTN_REPORT_ID ||
  860. reg_data[2] == GEN5_PUSH_BTN_REPORT_ID ||
  861. reg_data[2] == GEN5_WAKEUP_EVENT_REPORT_ID) {
  862. gen5_report_data_header_parse(cyapa, reg_data);
  863. } else if (reg_data[2] == GEN5_BL_RESP_REPORT_ID ||
  864. reg_data[2] == GEN5_APP_RESP_REPORT_ID) {
  865. gen5_cmd_resp_header_parse(cyapa, reg_data);
  866. }
  867. if (cyapa->gen == CYAPA_GEN5) {
  868. /*
  869. * Must read the content (e.g.: report description and so on)
  870. * from trackpad device throughout. Otherwise,
  871. * Gen5 trackpad cannot response to next command or
  872. * report any touch or button data later.
  873. */
  874. cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
  875. if (cyapa->state == CYAPA_STATE_GEN5_APP ||
  876. cyapa->state == CYAPA_STATE_GEN5_BL)
  877. return 0;
  878. }
  879. return -EAGAIN;
  880. }
  881. static int cyapa_gen5_bl_initiate(struct cyapa *cyapa,
  882. const struct firmware *fw)
  883. {
  884. struct cyapa_tsg_bin_image *image;
  885. struct gen5_bl_cmd_head *bl_cmd_head;
  886. struct gen5_bl_packet_start *bl_packet_start;
  887. struct gen5_bl_initiate_cmd_data *cmd_data;
  888. struct gen5_bl_packet_end *bl_packet_end;
  889. u8 cmd[CYAPA_TSG_MAX_CMD_SIZE];
  890. int cmd_len;
  891. u16 cmd_data_len;
  892. u16 cmd_crc = 0;
  893. u16 meta_data_crc = 0;
  894. u8 resp_data[11];
  895. int resp_len;
  896. int records_num;
  897. u8 *data;
  898. int error;
  899. /* Try to dump all buffered report data before any send command. */
  900. cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
  901. memset(cmd, 0, CYAPA_TSG_MAX_CMD_SIZE);
  902. bl_cmd_head = (struct gen5_bl_cmd_head *)cmd;
  903. cmd_data_len = CYAPA_TSG_BL_KEY_SIZE + CYAPA_TSG_FLASH_MAP_BLOCK_SIZE;
  904. cmd_len = sizeof(struct gen5_bl_cmd_head) + cmd_data_len +
  905. sizeof(struct gen5_bl_packet_end);
  906. put_unaligned_le16(GEN5_OUTPUT_REPORT_ADDR, &bl_cmd_head->addr);
  907. put_unaligned_le16(cmd_len - 2, &bl_cmd_head->length);
  908. bl_cmd_head->report_id = GEN5_BL_CMD_REPORT_ID;
  909. bl_packet_start = &bl_cmd_head->packet_start;
  910. bl_packet_start->sop = GEN5_SOP_KEY;
  911. bl_packet_start->cmd_code = GEN5_BL_CMD_INITIATE_BL;
  912. /* 8 key bytes and 128 bytes block size */
  913. put_unaligned_le16(cmd_data_len, &bl_packet_start->data_length);
  914. cmd_data = (struct gen5_bl_initiate_cmd_data *)bl_cmd_head->data;
  915. memcpy(cmd_data->key, cyapa_gen5_bl_cmd_key, CYAPA_TSG_BL_KEY_SIZE);
  916. /* Copy 60 bytes Meta Data Row Parameters */
  917. image = (struct cyapa_tsg_bin_image *)fw->data;
  918. records_num = (fw->size - sizeof(struct cyapa_tsg_bin_image_head)) /
  919. sizeof(struct cyapa_tsg_bin_image_data_record);
  920. /* APP_INTEGRITY row is always the last row block */
  921. data = image->records[records_num - 1].record_data;
  922. memcpy(cmd_data->metadata_raw_parameter, data,
  923. CYAPA_TSG_FLASH_MAP_METADATA_SIZE);
  924. meta_data_crc = crc_itu_t(0xffff, cmd_data->metadata_raw_parameter,
  925. CYAPA_TSG_FLASH_MAP_METADATA_SIZE);
  926. put_unaligned_le16(meta_data_crc, &cmd_data->metadata_crc);
  927. bl_packet_end = (struct gen5_bl_packet_end *)(bl_cmd_head->data +
  928. cmd_data_len);
  929. cmd_crc = crc_itu_t(0xffff, (u8 *)bl_packet_start,
  930. sizeof(struct gen5_bl_packet_start) + cmd_data_len);
  931. put_unaligned_le16(cmd_crc, &bl_packet_end->crc);
  932. bl_packet_end->eop = GEN5_EOP_KEY;
  933. resp_len = sizeof(resp_data);
  934. error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
  935. cmd, cmd_len,
  936. resp_data, &resp_len, 12000,
  937. cyapa_gen5_sort_tsg_pip_bl_resp_data, true);
  938. if (error || resp_len != GEN5_BL_INITIATE_RESP_LEN ||
  939. resp_data[2] != GEN5_BL_RESP_REPORT_ID ||
  940. !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5]))
  941. return error ? error : -EAGAIN;
  942. return 0;
  943. }
  944. static bool cyapa_gen5_sort_bl_exit_data(struct cyapa *cyapa, u8 *buf, int len)
  945. {
  946. if (buf == NULL || len < GEN5_RESP_LENGTH_SIZE)
  947. return false;
  948. if (buf[0] == 0 && buf[1] == 0)
  949. return true;
  950. /* Exit bootloader failed for some reason. */
  951. if (len == GEN5_BL_FAIL_EXIT_RESP_LEN &&
  952. buf[GEN5_RESP_REPORT_ID_OFFSET] ==
  953. GEN5_BL_RESP_REPORT_ID &&
  954. buf[GEN5_RESP_RSVD_OFFSET] == GEN5_RESP_RSVD_KEY &&
  955. buf[GEN5_RESP_BL_SOP_OFFSET] == GEN5_SOP_KEY &&
  956. buf[10] == GEN5_EOP_KEY)
  957. return true;
  958. return false;
  959. }
  960. static int cyapa_gen5_bl_exit(struct cyapa *cyapa)
  961. {
  962. u8 bl_gen5_bl_exit[] = { 0x04, 0x00,
  963. 0x0B, 0x00, 0x40, 0x00, 0x01, 0x3b, 0x00, 0x00,
  964. 0x20, 0xc7, 0x17
  965. };
  966. u8 resp_data[11];
  967. int resp_len;
  968. int error;
  969. resp_len = sizeof(resp_data);
  970. error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
  971. bl_gen5_bl_exit, sizeof(bl_gen5_bl_exit),
  972. resp_data, &resp_len,
  973. 5000, cyapa_gen5_sort_bl_exit_data, false);
  974. if (error)
  975. return error;
  976. if (resp_len == GEN5_BL_FAIL_EXIT_RESP_LEN ||
  977. resp_data[GEN5_RESP_REPORT_ID_OFFSET] ==
  978. GEN5_BL_RESP_REPORT_ID)
  979. return -EAGAIN;
  980. if (resp_data[0] == 0x00 && resp_data[1] == 0x00)
  981. return 0;
  982. return -ENODEV;
  983. }
  984. static int cyapa_gen5_bl_enter(struct cyapa *cyapa)
  985. {
  986. u8 cmd[] = { 0x04, 0x00, 0x05, 0x00, 0x2F, 0x00, 0x01 };
  987. u8 resp_data[2];
  988. int resp_len;
  989. int error;
  990. error = cyapa_poll_state(cyapa, 500);
  991. if (error < 0)
  992. return error;
  993. if (cyapa->gen != CYAPA_GEN5)
  994. return -EINVAL;
  995. /* Already in Gen5 BL. Skipping exit. */
  996. if (cyapa->state == CYAPA_STATE_GEN5_BL)
  997. return 0;
  998. if (cyapa->state != CYAPA_STATE_GEN5_APP)
  999. return -EAGAIN;
  1000. /* Try to dump all buffered report data before any send command. */
  1001. cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
  1002. /*
  1003. * Send bootloader enter command to trackpad device,
  1004. * after enter bootloader, the response data is two bytes of 0x00 0x00.
  1005. */
  1006. resp_len = sizeof(resp_data);
  1007. memset(resp_data, 0, resp_len);
  1008. error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
  1009. cmd, sizeof(cmd),
  1010. resp_data, &resp_len,
  1011. 5000, cyapa_gen5_sort_application_launch_data,
  1012. true);
  1013. if (error || resp_data[0] != 0x00 || resp_data[1] != 0x00)
  1014. return error < 0 ? error : -EAGAIN;
  1015. cyapa->operational = false;
  1016. cyapa->state = CYAPA_STATE_GEN5_BL;
  1017. return 0;
  1018. }
  1019. static int cyapa_gen5_check_fw(struct cyapa *cyapa, const struct firmware *fw)
  1020. {
  1021. struct device *dev = &cyapa->client->dev;
  1022. const struct cyapa_tsg_bin_image *image = (const void *)fw->data;
  1023. const struct cyapa_tsg_bin_image_data_record *app_integrity;
  1024. const struct gen5_bl_metadata_row_params *metadata;
  1025. size_t flash_records_count;
  1026. u32 fw_app_start, fw_upgrade_start;
  1027. u16 fw_app_len, fw_upgrade_len;
  1028. u16 app_crc;
  1029. u16 app_integrity_crc;
  1030. int record_index;
  1031. int i;
  1032. flash_records_count = (fw->size -
  1033. sizeof(struct cyapa_tsg_bin_image_head)) /
  1034. sizeof(struct cyapa_tsg_bin_image_data_record);
  1035. /*
  1036. * APP_INTEGRITY row is always the last row block,
  1037. * and the row id must be 0x01ff.
  1038. */
  1039. app_integrity = &image->records[flash_records_count - 1];
  1040. if (app_integrity->flash_array_id != 0x00 ||
  1041. get_unaligned_be16(&app_integrity->row_number) != 0x01ff) {
  1042. dev_err(dev, "%s: invalid app_integrity data.\n", __func__);
  1043. return -EINVAL;
  1044. }
  1045. metadata = (const void *)app_integrity->record_data;
  1046. /* Verify app_integrity crc */
  1047. app_integrity_crc = crc_itu_t(0xffff, app_integrity->record_data,
  1048. CYAPA_TSG_APP_INTEGRITY_SIZE);
  1049. if (app_integrity_crc != get_unaligned_le16(&metadata->metadata_crc)) {
  1050. dev_err(dev, "%s: invalid app_integrity crc.\n", __func__);
  1051. return -EINVAL;
  1052. }
  1053. fw_app_start = get_unaligned_le32(&metadata->app_start);
  1054. fw_app_len = get_unaligned_le16(&metadata->app_len);
  1055. fw_upgrade_start = get_unaligned_le32(&metadata->upgrade_start);
  1056. fw_upgrade_len = get_unaligned_le16(&metadata->upgrade_len);
  1057. if (fw_app_start % CYAPA_TSG_FW_ROW_SIZE ||
  1058. fw_app_len % CYAPA_TSG_FW_ROW_SIZE ||
  1059. fw_upgrade_start % CYAPA_TSG_FW_ROW_SIZE ||
  1060. fw_upgrade_len % CYAPA_TSG_FW_ROW_SIZE) {
  1061. dev_err(dev, "%s: invalid image alignment.\n", __func__);
  1062. return -EINVAL;
  1063. }
  1064. /*
  1065. * Verify application image CRC
  1066. */
  1067. record_index = fw_app_start / CYAPA_TSG_FW_ROW_SIZE -
  1068. CYAPA_TSG_IMG_START_ROW_NUM;
  1069. app_crc = 0xffffU;
  1070. for (i = 0; i < fw_app_len / CYAPA_TSG_FW_ROW_SIZE; i++) {
  1071. const u8 *data = image->records[record_index + i].record_data;
  1072. app_crc = crc_itu_t(app_crc, data, CYAPA_TSG_FW_ROW_SIZE);
  1073. }
  1074. if (app_crc != get_unaligned_le16(&metadata->app_crc)) {
  1075. dev_err(dev, "%s: invalid firmware app crc check.\n", __func__);
  1076. return -EINVAL;
  1077. }
  1078. return 0;
  1079. }
  1080. static int cyapa_gen5_write_fw_block(struct cyapa *cyapa,
  1081. struct cyapa_tsg_bin_image_data_record *flash_record)
  1082. {
  1083. struct gen5_bl_cmd_head *bl_cmd_head;
  1084. struct gen5_bl_packet_start *bl_packet_start;
  1085. struct gen5_bl_flash_row_head *flash_row_head;
  1086. struct gen5_bl_packet_end *bl_packet_end;
  1087. u8 cmd[CYAPA_TSG_MAX_CMD_SIZE];
  1088. u16 cmd_len;
  1089. u8 flash_array_id;
  1090. u16 flash_row_id;
  1091. u16 record_len;
  1092. u8 *record_data;
  1093. u16 data_len;
  1094. u16 crc;
  1095. u8 resp_data[11];
  1096. int resp_len;
  1097. int error;
  1098. flash_array_id = flash_record->flash_array_id;
  1099. flash_row_id = get_unaligned_be16(&flash_record->row_number);
  1100. record_len = get_unaligned_be16(&flash_record->record_len);
  1101. record_data = flash_record->record_data;
  1102. memset(cmd, 0, CYAPA_TSG_MAX_CMD_SIZE);
  1103. bl_cmd_head = (struct gen5_bl_cmd_head *)cmd;
  1104. bl_packet_start = &bl_cmd_head->packet_start;
  1105. cmd_len = sizeof(struct gen5_bl_cmd_head) +
  1106. sizeof(struct gen5_bl_flash_row_head) +
  1107. CYAPA_TSG_FLASH_MAP_BLOCK_SIZE +
  1108. sizeof(struct gen5_bl_packet_end);
  1109. put_unaligned_le16(GEN5_OUTPUT_REPORT_ADDR, &bl_cmd_head->addr);
  1110. /* Don't include 2 bytes register address */
  1111. put_unaligned_le16(cmd_len - 2, &bl_cmd_head->length);
  1112. bl_cmd_head->report_id = GEN5_BL_CMD_REPORT_ID;
  1113. bl_packet_start->sop = GEN5_SOP_KEY;
  1114. bl_packet_start->cmd_code = GEN5_BL_CMD_PROGRAM_VERIFY_ROW;
  1115. /* 1 (Flash Array ID) + 2 (Flash Row ID) + 128 (flash data) */
  1116. data_len = sizeof(struct gen5_bl_flash_row_head) + record_len;
  1117. put_unaligned_le16(data_len, &bl_packet_start->data_length);
  1118. flash_row_head = (struct gen5_bl_flash_row_head *)bl_cmd_head->data;
  1119. flash_row_head->flash_array_id = flash_array_id;
  1120. put_unaligned_le16(flash_row_id, &flash_row_head->flash_row_id);
  1121. memcpy(flash_row_head->flash_data, record_data, record_len);
  1122. bl_packet_end = (struct gen5_bl_packet_end *)(bl_cmd_head->data +
  1123. data_len);
  1124. crc = crc_itu_t(0xffff, (u8 *)bl_packet_start,
  1125. sizeof(struct gen5_bl_packet_start) + data_len);
  1126. put_unaligned_le16(crc, &bl_packet_end->crc);
  1127. bl_packet_end->eop = GEN5_EOP_KEY;
  1128. resp_len = sizeof(resp_data);
  1129. error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, cmd_len,
  1130. resp_data, &resp_len,
  1131. 500, cyapa_gen5_sort_tsg_pip_bl_resp_data, true);
  1132. if (error || resp_len != GEN5_BL_BLOCK_WRITE_RESP_LEN ||
  1133. resp_data[2] != GEN5_BL_RESP_REPORT_ID ||
  1134. !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5]))
  1135. return error < 0 ? error : -EAGAIN;
  1136. return 0;
  1137. }
  1138. static int cyapa_gen5_do_fw_update(struct cyapa *cyapa,
  1139. const struct firmware *fw)
  1140. {
  1141. struct device *dev = &cyapa->client->dev;
  1142. struct cyapa_tsg_bin_image_data_record *flash_record;
  1143. struct cyapa_tsg_bin_image *image =
  1144. (struct cyapa_tsg_bin_image *)fw->data;
  1145. int flash_records_count;
  1146. int i;
  1147. int error;
  1148. cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
  1149. flash_records_count =
  1150. (fw->size - sizeof(struct cyapa_tsg_bin_image_head)) /
  1151. sizeof(struct cyapa_tsg_bin_image_data_record);
  1152. /*
  1153. * The last flash row 0x01ff has been written through bl_initiate
  1154. * command, so DO NOT write flash 0x01ff to trackpad device.
  1155. */
  1156. for (i = 0; i < (flash_records_count - 1); i++) {
  1157. flash_record = &image->records[i];
  1158. error = cyapa_gen5_write_fw_block(cyapa, flash_record);
  1159. if (error) {
  1160. dev_err(dev, "%s: Gen5 FW update aborted: %d\n",
  1161. __func__, error);
  1162. return error;
  1163. }
  1164. }
  1165. return 0;
  1166. }
  1167. static int cyapa_gen5_change_power_state(struct cyapa *cyapa, u8 power_state)
  1168. {
  1169. u8 cmd[8] = { 0x04, 0x00, 0x06, 0x00, 0x2f, 0x00, 0x08, 0x01 };
  1170. u8 resp_data[6];
  1171. int resp_len;
  1172. int error;
  1173. cmd[7] = power_state;
  1174. resp_len = sizeof(resp_data);
  1175. error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, sizeof(cmd),
  1176. resp_data, &resp_len,
  1177. 500, cyapa_gen5_sort_tsg_pip_app_resp_data, false);
  1178. if (error || !VALID_CMD_RESP_HEADER(resp_data, 0x08) ||
  1179. !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5]))
  1180. return error < 0 ? error : -EINVAL;
  1181. return 0;
  1182. }
  1183. static int cyapa_gen5_set_interval_time(struct cyapa *cyapa,
  1184. u8 parameter_id, u16 interval_time)
  1185. {
  1186. struct gen5_app_cmd_head *app_cmd_head;
  1187. struct gen5_app_set_parameter_data *parameter_data;
  1188. u8 cmd[CYAPA_TSG_MAX_CMD_SIZE];
  1189. int cmd_len;
  1190. u8 resp_data[7];
  1191. int resp_len;
  1192. u8 parameter_size;
  1193. int error;
  1194. memset(cmd, 0, CYAPA_TSG_MAX_CMD_SIZE);
  1195. app_cmd_head = (struct gen5_app_cmd_head *)cmd;
  1196. parameter_data = (struct gen5_app_set_parameter_data *)
  1197. app_cmd_head->parameter_data;
  1198. cmd_len = sizeof(struct gen5_app_cmd_head) +
  1199. sizeof(struct gen5_app_set_parameter_data);
  1200. switch (parameter_id) {
  1201. case GEN5_PARAMETER_ACT_INTERVL_ID:
  1202. parameter_size = GEN5_PARAMETER_ACT_INTERVL_SIZE;
  1203. break;
  1204. case GEN5_PARAMETER_ACT_LFT_INTERVL_ID:
  1205. parameter_size = GEN5_PARAMETER_ACT_LFT_INTERVL_SIZE;
  1206. break;
  1207. case GEN5_PARAMETER_LP_INTRVL_ID:
  1208. parameter_size = GEN5_PARAMETER_LP_INTRVL_SIZE;
  1209. break;
  1210. default:
  1211. return -EINVAL;
  1212. }
  1213. put_unaligned_le16(GEN5_OUTPUT_REPORT_ADDR, &app_cmd_head->addr);
  1214. /*
  1215. * Don't include unused parameter value bytes and
  1216. * 2 bytes register address.
  1217. */
  1218. put_unaligned_le16(cmd_len - (4 - parameter_size) - 2,
  1219. &app_cmd_head->length);
  1220. app_cmd_head->report_id = GEN5_APP_CMD_REPORT_ID;
  1221. app_cmd_head->cmd_code = GEN5_CMD_SET_PARAMETER;
  1222. parameter_data->parameter_id = parameter_id;
  1223. parameter_data->parameter_size = parameter_size;
  1224. put_unaligned_le32((u32)interval_time, &parameter_data->value);
  1225. resp_len = sizeof(resp_data);
  1226. error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, cmd_len,
  1227. resp_data, &resp_len,
  1228. 500, cyapa_gen5_sort_tsg_pip_app_resp_data, false);
  1229. if (error || resp_data[5] != parameter_id ||
  1230. resp_data[6] != parameter_size ||
  1231. !VALID_CMD_RESP_HEADER(resp_data, GEN5_CMD_SET_PARAMETER))
  1232. return error < 0 ? error : -EINVAL;
  1233. return 0;
  1234. }
  1235. static int cyapa_gen5_get_interval_time(struct cyapa *cyapa,
  1236. u8 parameter_id, u16 *interval_time)
  1237. {
  1238. struct gen5_app_cmd_head *app_cmd_head;
  1239. struct gen5_app_get_parameter_data *parameter_data;
  1240. u8 cmd[CYAPA_TSG_MAX_CMD_SIZE];
  1241. int cmd_len;
  1242. u8 resp_data[11];
  1243. int resp_len;
  1244. u8 parameter_size;
  1245. u16 mask, i;
  1246. int error;
  1247. memset(cmd, 0, CYAPA_TSG_MAX_CMD_SIZE);
  1248. app_cmd_head = (struct gen5_app_cmd_head *)cmd;
  1249. parameter_data = (struct gen5_app_get_parameter_data *)
  1250. app_cmd_head->parameter_data;
  1251. cmd_len = sizeof(struct gen5_app_cmd_head) +
  1252. sizeof(struct gen5_app_get_parameter_data);
  1253. *interval_time = 0;
  1254. switch (parameter_id) {
  1255. case GEN5_PARAMETER_ACT_INTERVL_ID:
  1256. parameter_size = GEN5_PARAMETER_ACT_INTERVL_SIZE;
  1257. break;
  1258. case GEN5_PARAMETER_ACT_LFT_INTERVL_ID:
  1259. parameter_size = GEN5_PARAMETER_ACT_LFT_INTERVL_SIZE;
  1260. break;
  1261. case GEN5_PARAMETER_LP_INTRVL_ID:
  1262. parameter_size = GEN5_PARAMETER_LP_INTRVL_SIZE;
  1263. break;
  1264. default:
  1265. return -EINVAL;
  1266. }
  1267. put_unaligned_le16(GEN5_HID_DESCRIPTOR_ADDR, &app_cmd_head->addr);
  1268. /* Don't include 2 bytes register address */
  1269. put_unaligned_le16(cmd_len - 2, &app_cmd_head->length);
  1270. app_cmd_head->report_id = GEN5_APP_CMD_REPORT_ID;
  1271. app_cmd_head->cmd_code = GEN5_CMD_GET_PARAMETER;
  1272. parameter_data->parameter_id = parameter_id;
  1273. resp_len = sizeof(resp_data);
  1274. error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, cmd_len,
  1275. resp_data, &resp_len,
  1276. 500, cyapa_gen5_sort_tsg_pip_app_resp_data, false);
  1277. if (error || resp_data[5] != parameter_id || resp_data[6] == 0 ||
  1278. !VALID_CMD_RESP_HEADER(resp_data, GEN5_CMD_GET_PARAMETER))
  1279. return error < 0 ? error : -EINVAL;
  1280. mask = 0;
  1281. for (i = 0; i < parameter_size; i++)
  1282. mask |= (0xff << (i * 8));
  1283. *interval_time = get_unaligned_le16(&resp_data[7]) & mask;
  1284. return 0;
  1285. }
  1286. static int cyapa_gen5_disable_pip_report(struct cyapa *cyapa)
  1287. {
  1288. struct gen5_app_cmd_head *app_cmd_head;
  1289. u8 cmd[10];
  1290. u8 resp_data[7];
  1291. int resp_len;
  1292. int error;
  1293. memset(cmd, 0, sizeof(cmd));
  1294. app_cmd_head = (struct gen5_app_cmd_head *)cmd;
  1295. put_unaligned_le16(GEN5_HID_DESCRIPTOR_ADDR, &app_cmd_head->addr);
  1296. put_unaligned_le16(sizeof(cmd) - 2, &app_cmd_head->length);
  1297. app_cmd_head->report_id = GEN5_APP_CMD_REPORT_ID;
  1298. app_cmd_head->cmd_code = GEN5_CMD_SET_PARAMETER;
  1299. app_cmd_head->parameter_data[0] = GEN5_PARAMETER_DISABLE_PIP_REPORT;
  1300. app_cmd_head->parameter_data[1] = 0x01;
  1301. app_cmd_head->parameter_data[2] = 0x01;
  1302. resp_len = sizeof(resp_data);
  1303. error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, sizeof(cmd),
  1304. resp_data, &resp_len,
  1305. 500, cyapa_gen5_sort_tsg_pip_app_resp_data, false);
  1306. if (error || resp_data[5] != GEN5_PARAMETER_DISABLE_PIP_REPORT ||
  1307. !VALID_CMD_RESP_HEADER(resp_data, GEN5_CMD_SET_PARAMETER) ||
  1308. resp_data[6] != 0x01)
  1309. return error < 0 ? error : -EINVAL;
  1310. return 0;
  1311. }
  1312. static int cyapa_gen5_deep_sleep(struct cyapa *cyapa, u8 state)
  1313. {
  1314. u8 cmd[] = { 0x05, 0x00, 0x00, 0x08};
  1315. u8 resp_data[5];
  1316. int resp_len;
  1317. int error;
  1318. cmd[2] = state & GEN5_DEEP_SLEEP_STATE_MASK;
  1319. resp_len = sizeof(resp_data);
  1320. error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, sizeof(cmd),
  1321. resp_data, &resp_len,
  1322. 500, cyapa_gen5_sort_deep_sleep_data, false);
  1323. if (error || ((resp_data[3] & GEN5_DEEP_SLEEP_STATE_MASK) != state))
  1324. return -EINVAL;
  1325. return 0;
  1326. }
  1327. static int cyapa_gen5_set_power_mode(struct cyapa *cyapa,
  1328. u8 power_mode, u16 sleep_time)
  1329. {
  1330. struct device *dev = &cyapa->client->dev;
  1331. u8 power_state;
  1332. int error;
  1333. if (cyapa->state != CYAPA_STATE_GEN5_APP)
  1334. return 0;
  1335. /* Dump all the report data before do power mode commmands. */
  1336. cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
  1337. if (GEN5_DEV_GET_PWR_STATE(cyapa) == UNINIT_PWR_MODE) {
  1338. /*
  1339. * Assume TP in deep sleep mode when driver is loaded,
  1340. * avoid driver unload and reload command IO issue caused by TP
  1341. * has been set into deep sleep mode when unloading.
  1342. */
  1343. GEN5_DEV_SET_PWR_STATE(cyapa, PWR_MODE_OFF);
  1344. }
  1345. if (GEN5_DEV_UNINIT_SLEEP_TIME(cyapa) &&
  1346. GEN5_DEV_GET_PWR_STATE(cyapa) != PWR_MODE_OFF)
  1347. if (cyapa_gen5_get_interval_time(cyapa,
  1348. GEN5_PARAMETER_LP_INTRVL_ID,
  1349. &cyapa->dev_sleep_time) != 0)
  1350. GEN5_DEV_SET_SLEEP_TIME(cyapa, UNINIT_SLEEP_TIME);
  1351. if (GEN5_DEV_GET_PWR_STATE(cyapa) == power_mode) {
  1352. if (power_mode == PWR_MODE_OFF ||
  1353. power_mode == PWR_MODE_FULL_ACTIVE ||
  1354. power_mode == PWR_MODE_BTN_ONLY ||
  1355. GEN5_DEV_GET_SLEEP_TIME(cyapa) == sleep_time) {
  1356. /* Has in correct power mode state, early return. */
  1357. return 0;
  1358. }
  1359. }
  1360. if (power_mode == PWR_MODE_OFF) {
  1361. error = cyapa_gen5_deep_sleep(cyapa, GEN5_DEEP_SLEEP_STATE_OFF);
  1362. if (error) {
  1363. dev_err(dev, "enter deep sleep fail: %d\n", error);
  1364. return error;
  1365. }
  1366. GEN5_DEV_SET_PWR_STATE(cyapa, PWR_MODE_OFF);
  1367. return 0;
  1368. }
  1369. /*
  1370. * When trackpad in power off mode, it cannot change to other power
  1371. * state directly, must be wake up from sleep firstly, then
  1372. * continue to do next power sate change.
  1373. */
  1374. if (GEN5_DEV_GET_PWR_STATE(cyapa) == PWR_MODE_OFF) {
  1375. error = cyapa_gen5_deep_sleep(cyapa, GEN5_DEEP_SLEEP_STATE_ON);
  1376. if (error) {
  1377. dev_err(dev, "deep sleep wake fail: %d\n", error);
  1378. return error;
  1379. }
  1380. }
  1381. if (power_mode == PWR_MODE_FULL_ACTIVE) {
  1382. error = cyapa_gen5_change_power_state(cyapa,
  1383. GEN5_POWER_STATE_ACTIVE);
  1384. if (error) {
  1385. dev_err(dev, "change to active fail: %d\n", error);
  1386. return error;
  1387. }
  1388. GEN5_DEV_SET_PWR_STATE(cyapa, PWR_MODE_FULL_ACTIVE);
  1389. } else if (power_mode == PWR_MODE_BTN_ONLY) {
  1390. error = cyapa_gen5_change_power_state(cyapa,
  1391. GEN5_POWER_STATE_BTN_ONLY);
  1392. if (error) {
  1393. dev_err(dev, "fail to button only mode: %d\n", error);
  1394. return error;
  1395. }
  1396. GEN5_DEV_SET_PWR_STATE(cyapa, PWR_MODE_BTN_ONLY);
  1397. } else {
  1398. /*
  1399. * Continue to change power mode even failed to set
  1400. * interval time, it won't affect the power mode change.
  1401. * except the sleep interval time is not correct.
  1402. */
  1403. if (GEN5_DEV_UNINIT_SLEEP_TIME(cyapa) ||
  1404. sleep_time != GEN5_DEV_GET_SLEEP_TIME(cyapa))
  1405. if (cyapa_gen5_set_interval_time(cyapa,
  1406. GEN5_PARAMETER_LP_INTRVL_ID,
  1407. sleep_time) == 0)
  1408. GEN5_DEV_SET_SLEEP_TIME(cyapa, sleep_time);
  1409. if (sleep_time <= GEN5_POWER_READY_MAX_INTRVL_TIME)
  1410. power_state = GEN5_POWER_STATE_READY;
  1411. else
  1412. power_state = GEN5_POWER_STATE_IDLE;
  1413. error = cyapa_gen5_change_power_state(cyapa, power_state);
  1414. if (error) {
  1415. dev_err(dev, "set power state to 0x%02x failed: %d\n",
  1416. power_state, error);
  1417. return error;
  1418. }
  1419. /*
  1420. * Disable pip report for a little time, firmware will
  1421. * re-enable it automatically. It's used to fix the issue
  1422. * that trackpad unable to report signal to wake system up
  1423. * in the special situation that system is in suspending, and
  1424. * at the same time, user touch trackpad to wake system up.
  1425. * This function can avoid the data to be buffered when system
  1426. * is suspending which may cause interrupt line unable to be
  1427. * asserted again.
  1428. */
  1429. cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
  1430. cyapa_gen5_disable_pip_report(cyapa);
  1431. GEN5_DEV_SET_PWR_STATE(cyapa,
  1432. cyapa_sleep_time_to_pwr_cmd(sleep_time));
  1433. }
  1434. return 0;
  1435. }
  1436. static int cyapa_gen5_resume_scanning(struct cyapa *cyapa)
  1437. {
  1438. u8 cmd[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x04 };
  1439. u8 resp_data[6];
  1440. int resp_len;
  1441. int error;
  1442. /* Try to dump all buffered data before doing command. */
  1443. cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
  1444. resp_len = sizeof(resp_data);
  1445. error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
  1446. cmd, sizeof(cmd),
  1447. resp_data, &resp_len,
  1448. 500, cyapa_gen5_sort_tsg_pip_app_resp_data, true);
  1449. if (error || !VALID_CMD_RESP_HEADER(resp_data, 0x04))
  1450. return -EINVAL;
  1451. /* Try to dump all buffered data when resuming scanning. */
  1452. cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
  1453. return 0;
  1454. }
  1455. static int cyapa_gen5_suspend_scanning(struct cyapa *cyapa)
  1456. {
  1457. u8 cmd[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x03 };
  1458. u8 resp_data[6];
  1459. int resp_len;
  1460. int error;
  1461. /* Try to dump all buffered data before doing command. */
  1462. cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
  1463. resp_len = sizeof(resp_data);
  1464. error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
  1465. cmd, sizeof(cmd),
  1466. resp_data, &resp_len,
  1467. 500, cyapa_gen5_sort_tsg_pip_app_resp_data, true);
  1468. if (error || !VALID_CMD_RESP_HEADER(resp_data, 0x03))
  1469. return -EINVAL;
  1470. /* Try to dump all buffered data when suspending scanning. */
  1471. cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
  1472. return 0;
  1473. }
  1474. static int cyapa_gen5_calibrate_pwcs(struct cyapa *cyapa,
  1475. u8 calibrate_sensing_mode_type)
  1476. {
  1477. struct gen5_app_cmd_head *app_cmd_head;
  1478. u8 cmd[8];
  1479. u8 resp_data[6];
  1480. int resp_len;
  1481. int error;
  1482. /* Try to dump all buffered data before doing command. */
  1483. cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
  1484. memset(cmd, 0, sizeof(cmd));
  1485. app_cmd_head = (struct gen5_app_cmd_head *)cmd;
  1486. put_unaligned_le16(GEN5_OUTPUT_REPORT_ADDR, &app_cmd_head->addr);
  1487. put_unaligned_le16(sizeof(cmd) - 2, &app_cmd_head->length);
  1488. app_cmd_head->report_id = GEN5_APP_CMD_REPORT_ID;
  1489. app_cmd_head->cmd_code = GEN5_CMD_CALIBRATE;
  1490. app_cmd_head->parameter_data[0] = calibrate_sensing_mode_type;
  1491. resp_len = sizeof(resp_data);
  1492. error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
  1493. cmd, sizeof(cmd),
  1494. resp_data, &resp_len,
  1495. 5000, cyapa_gen5_sort_tsg_pip_app_resp_data, true);
  1496. if (error || !VALID_CMD_RESP_HEADER(resp_data, GEN5_CMD_CALIBRATE) ||
  1497. !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5]))
  1498. return error < 0 ? error : -EAGAIN;
  1499. return 0;
  1500. }
  1501. static ssize_t cyapa_gen5_do_calibrate(struct device *dev,
  1502. struct device_attribute *attr,
  1503. const char *buf, size_t count)
  1504. {
  1505. struct cyapa *cyapa = dev_get_drvdata(dev);
  1506. int error, calibrate_error;
  1507. /* 1. Suspend Scanning*/
  1508. error = cyapa_gen5_suspend_scanning(cyapa);
  1509. if (error)
  1510. return error;
  1511. /* 2. Do mutual capacitance fine calibrate. */
  1512. calibrate_error = cyapa_gen5_calibrate_pwcs(cyapa,
  1513. CYAPA_SENSING_MODE_MUTUAL_CAP_FINE);
  1514. if (calibrate_error)
  1515. goto resume_scanning;
  1516. /* 3. Do self capacitance calibrate. */
  1517. calibrate_error = cyapa_gen5_calibrate_pwcs(cyapa,
  1518. CYAPA_SENSING_MODE_SELF_CAP);
  1519. if (calibrate_error)
  1520. goto resume_scanning;
  1521. resume_scanning:
  1522. /* 4. Resume Scanning*/
  1523. error = cyapa_gen5_resume_scanning(cyapa);
  1524. if (error || calibrate_error)
  1525. return error ? error : calibrate_error;
  1526. return count;
  1527. }
  1528. static s32 twos_complement_to_s32(s32 value, int num_bits)
  1529. {
  1530. if (value >> (num_bits - 1))
  1531. value |= -1 << num_bits;
  1532. return value;
  1533. }
  1534. static s32 cyapa_parse_structure_data(u8 data_format, u8 *buf, int buf_len)
  1535. {
  1536. int data_size;
  1537. bool big_endian;
  1538. bool unsigned_type;
  1539. s32 value;
  1540. data_size = (data_format & 0x07);
  1541. big_endian = ((data_format & 0x10) == 0x00);
  1542. unsigned_type = ((data_format & 0x20) == 0x00);
  1543. if (buf_len < data_size)
  1544. return 0;
  1545. switch (data_size) {
  1546. case 1:
  1547. value = buf[0];
  1548. break;
  1549. case 2:
  1550. if (big_endian)
  1551. value = get_unaligned_be16(buf);
  1552. else
  1553. value = get_unaligned_le16(buf);
  1554. break;
  1555. case 4:
  1556. if (big_endian)
  1557. value = get_unaligned_be32(buf);
  1558. else
  1559. value = get_unaligned_le32(buf);
  1560. break;
  1561. default:
  1562. /* Should not happen, just as default case here. */
  1563. value = 0;
  1564. break;
  1565. }
  1566. if (!unsigned_type)
  1567. value = twos_complement_to_s32(value, data_size * 8);
  1568. return value;
  1569. }
  1570. static void cyapa_gen5_guess_electrodes(struct cyapa *cyapa,
  1571. int *electrodes_rx, int *electrodes_tx)
  1572. {
  1573. if (cyapa->electrodes_rx != 0) {
  1574. *electrodes_rx = cyapa->electrodes_rx;
  1575. *electrodes_tx = (cyapa->electrodes_x == *electrodes_rx) ?
  1576. cyapa->electrodes_y : cyapa->electrodes_x;
  1577. } else {
  1578. *electrodes_tx = min(cyapa->electrodes_x, cyapa->electrodes_y);
  1579. *electrodes_rx = max(cyapa->electrodes_x, cyapa->electrodes_y);
  1580. }
  1581. }
  1582. /*
  1583. * Read all the global mutual or self idac data or mutual or self local PWC
  1584. * data based on the @idac_data_type.
  1585. * If the input value of @data_size is 0, then means read global mutual or
  1586. * self idac data. For read global mutual idac data, @idac_max, @idac_min and
  1587. * @idac_ave are in order used to return the max value of global mutual idac
  1588. * data, the min value of global mutual idac and the average value of the
  1589. * global mutual idac data. For read global self idac data, @idac_max is used
  1590. * to return the global self cap idac data in Rx direction, @idac_min is used
  1591. * to return the global self cap idac data in Tx direction. @idac_ave is not
  1592. * used.
  1593. * If the input value of @data_size is not 0, than means read the mutual or
  1594. * self local PWC data. The @idac_max, @idac_min and @idac_ave are used to
  1595. * return the max, min and average value of the mutual or self local PWC data.
  1596. * Note, in order to raed mutual local PWC data, must read invoke this function
  1597. * to read the mutual global idac data firstly to set the correct Rx number
  1598. * value, otherwise, the read mutual idac and PWC data may not correct.
  1599. */
  1600. static int cyapa_gen5_read_idac_data(struct cyapa *cyapa,
  1601. u8 cmd_code, u8 idac_data_type, int *data_size,
  1602. int *idac_max, int *idac_min, int *idac_ave)
  1603. {
  1604. struct gen5_app_cmd_head *cmd_head;
  1605. u8 cmd[12];
  1606. u8 resp_data[256];
  1607. int resp_len;
  1608. int read_len;
  1609. int value;
  1610. u16 offset;
  1611. int read_elements;
  1612. bool read_global_idac;
  1613. int sum, count, max_element_cnt;
  1614. int tmp_max, tmp_min, tmp_ave, tmp_sum, tmp_count;
  1615. int electrodes_rx, electrodes_tx;
  1616. int i;
  1617. int error;
  1618. if (cmd_code != GEN5_CMD_RETRIEVE_DATA_STRUCTURE ||
  1619. (idac_data_type != GEN5_RETRIEVE_MUTUAL_PWC_DATA &&
  1620. idac_data_type != GEN5_RETRIEVE_SELF_CAP_PWC_DATA) ||
  1621. !data_size || !idac_max || !idac_min || !idac_ave)
  1622. return -EINVAL;
  1623. *idac_max = INT_MIN;
  1624. *idac_min = INT_MAX;
  1625. sum = count = tmp_count = 0;
  1626. electrodes_rx = electrodes_tx = 0;
  1627. if (*data_size == 0) {
  1628. /*
  1629. * Read global idac values firstly.
  1630. * Currently, no idac data exceed 4 bytes.
  1631. */
  1632. read_global_idac = true;
  1633. offset = 0;
  1634. *data_size = 4;
  1635. tmp_max = INT_MIN;
  1636. tmp_min = INT_MAX;
  1637. tmp_ave = tmp_sum = tmp_count = 0;
  1638. if (idac_data_type == GEN5_RETRIEVE_MUTUAL_PWC_DATA) {
  1639. if (cyapa->aligned_electrodes_rx == 0) {
  1640. cyapa_gen5_guess_electrodes(cyapa,
  1641. &electrodes_rx, &electrodes_tx);
  1642. cyapa->aligned_electrodes_rx =
  1643. (electrodes_rx + 3) & ~3u;
  1644. }
  1645. max_element_cnt =
  1646. (cyapa->aligned_electrodes_rx + 7) & ~7u;
  1647. } else {
  1648. max_element_cnt = 2;
  1649. }
  1650. } else {
  1651. read_global_idac = false;
  1652. if (*data_size > 4)
  1653. *data_size = 4;
  1654. /* Calculate the start offset in bytes of local PWC data. */
  1655. if (idac_data_type == GEN5_RETRIEVE_MUTUAL_PWC_DATA) {
  1656. offset = cyapa->aligned_electrodes_rx * (*data_size);
  1657. if (cyapa->electrodes_rx == cyapa->electrodes_x)
  1658. electrodes_tx = cyapa->electrodes_y;
  1659. else
  1660. electrodes_tx = cyapa->electrodes_x;
  1661. max_element_cnt = ((cyapa->aligned_electrodes_rx + 7) &
  1662. ~7u) * electrodes_tx;
  1663. } else {
  1664. offset = 2;
  1665. max_element_cnt = cyapa->electrodes_x +
  1666. cyapa->electrodes_y;
  1667. max_element_cnt = (max_element_cnt + 3) & ~3u;
  1668. }
  1669. }
  1670. memset(cmd, 0, sizeof(cmd));
  1671. cmd_head = (struct gen5_app_cmd_head *)cmd;
  1672. put_unaligned_le16(GEN5_OUTPUT_REPORT_ADDR, &cmd_head->addr);
  1673. put_unaligned_le16(sizeof(cmd) - 2, &cmd_head->length);
  1674. cmd_head->report_id = GEN5_APP_CMD_REPORT_ID;
  1675. cmd_head->cmd_code = cmd_code;
  1676. do {
  1677. read_elements = (256 - GEN5_RESP_DATA_STRUCTURE_OFFSET) /
  1678. (*data_size);
  1679. read_elements = min(read_elements, max_element_cnt - count);
  1680. read_len = read_elements * (*data_size);
  1681. put_unaligned_le16(offset, &cmd_head->parameter_data[0]);
  1682. put_unaligned_le16(read_len, &cmd_head->parameter_data[2]);
  1683. cmd_head->parameter_data[4] = idac_data_type;
  1684. resp_len = GEN5_RESP_DATA_STRUCTURE_OFFSET + read_len;
  1685. error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
  1686. cmd, sizeof(cmd),
  1687. resp_data, &resp_len,
  1688. 500, cyapa_gen5_sort_tsg_pip_app_resp_data,
  1689. true);
  1690. if (error || resp_len < GEN5_RESP_DATA_STRUCTURE_OFFSET ||
  1691. !VALID_CMD_RESP_HEADER(resp_data, cmd_code) ||
  1692. !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5]) ||
  1693. resp_data[6] != idac_data_type)
  1694. return (error < 0) ? error : -EAGAIN;
  1695. read_len = get_unaligned_le16(&resp_data[7]);
  1696. if (read_len == 0)
  1697. break;
  1698. *data_size = (resp_data[9] & GEN5_PWC_DATA_ELEMENT_SIZE_MASK);
  1699. if (read_len < *data_size)
  1700. return -EINVAL;
  1701. if (read_global_idac &&
  1702. idac_data_type == GEN5_RETRIEVE_SELF_CAP_PWC_DATA) {
  1703. /* Rx's self global idac data. */
  1704. *idac_max = cyapa_parse_structure_data(
  1705. resp_data[9],
  1706. &resp_data[GEN5_RESP_DATA_STRUCTURE_OFFSET],
  1707. *data_size);
  1708. /* Tx's self global idac data. */
  1709. *idac_min = cyapa_parse_structure_data(
  1710. resp_data[9],
  1711. &resp_data[GEN5_RESP_DATA_STRUCTURE_OFFSET +
  1712. *data_size],
  1713. *data_size);
  1714. break;
  1715. }
  1716. /* Read mutual global idac or local mutual/self PWC data. */
  1717. offset += read_len;
  1718. for (i = 10; i < (read_len + GEN5_RESP_DATA_STRUCTURE_OFFSET);
  1719. i += *data_size) {
  1720. value = cyapa_parse_structure_data(resp_data[9],
  1721. &resp_data[i], *data_size);
  1722. *idac_min = min(value, *idac_min);
  1723. *idac_max = max(value, *idac_max);
  1724. if (idac_data_type == GEN5_RETRIEVE_MUTUAL_PWC_DATA &&
  1725. tmp_count < cyapa->aligned_electrodes_rx &&
  1726. read_global_idac) {
  1727. /*
  1728. * The value gap betwen global and local mutual
  1729. * idac data must bigger than 50%.
  1730. * Normally, global value bigger than 50,
  1731. * local values less than 10.
  1732. */
  1733. if (!tmp_ave || value > tmp_ave / 2) {
  1734. tmp_min = min(value, tmp_min);
  1735. tmp_max = max(value, tmp_max);
  1736. tmp_sum += value;
  1737. tmp_count++;
  1738. tmp_ave = tmp_sum / tmp_count;
  1739. }
  1740. }
  1741. sum += value;
  1742. count++;
  1743. if (count >= max_element_cnt)
  1744. goto out;
  1745. }
  1746. } while (true);
  1747. out:
  1748. *idac_ave = count ? (sum / count) : 0;
  1749. if (read_global_idac &&
  1750. idac_data_type == GEN5_RETRIEVE_MUTUAL_PWC_DATA) {
  1751. if (tmp_count == 0)
  1752. return 0;
  1753. if (tmp_count == cyapa->aligned_electrodes_rx) {
  1754. cyapa->electrodes_rx = cyapa->electrodes_rx ?
  1755. cyapa->electrodes_rx : electrodes_rx;
  1756. } else if (tmp_count == electrodes_rx) {
  1757. cyapa->electrodes_rx = cyapa->electrodes_rx ?
  1758. cyapa->electrodes_rx : electrodes_rx;
  1759. cyapa->aligned_electrodes_rx = electrodes_rx;
  1760. } else {
  1761. cyapa->electrodes_rx = cyapa->electrodes_rx ?
  1762. cyapa->electrodes_rx : electrodes_tx;
  1763. cyapa->aligned_electrodes_rx = tmp_count;
  1764. }
  1765. *idac_min = tmp_min;
  1766. *idac_max = tmp_max;
  1767. *idac_ave = tmp_ave;
  1768. }
  1769. return 0;
  1770. }
  1771. static int cyapa_gen5_read_mutual_idac_data(struct cyapa *cyapa,
  1772. int *gidac_mutual_max, int *gidac_mutual_min, int *gidac_mutual_ave,
  1773. int *lidac_mutual_max, int *lidac_mutual_min, int *lidac_mutual_ave)
  1774. {
  1775. int data_size;
  1776. int error;
  1777. *gidac_mutual_max = *gidac_mutual_min = *gidac_mutual_ave = 0;
  1778. *lidac_mutual_max = *lidac_mutual_min = *lidac_mutual_ave = 0;
  1779. data_size = 0;
  1780. error = cyapa_gen5_read_idac_data(cyapa,
  1781. GEN5_CMD_RETRIEVE_DATA_STRUCTURE,
  1782. GEN5_RETRIEVE_MUTUAL_PWC_DATA,
  1783. &data_size,
  1784. gidac_mutual_max, gidac_mutual_min, gidac_mutual_ave);
  1785. if (error)
  1786. return error;
  1787. error = cyapa_gen5_read_idac_data(cyapa,
  1788. GEN5_CMD_RETRIEVE_DATA_STRUCTURE,
  1789. GEN5_RETRIEVE_MUTUAL_PWC_DATA,
  1790. &data_size,
  1791. lidac_mutual_max, lidac_mutual_min, lidac_mutual_ave);
  1792. return error;
  1793. }
  1794. static int cyapa_gen5_read_self_idac_data(struct cyapa *cyapa,
  1795. int *gidac_self_rx, int *gidac_self_tx,
  1796. int *lidac_self_max, int *lidac_self_min, int *lidac_self_ave)
  1797. {
  1798. int data_size;
  1799. int error;
  1800. *gidac_self_rx = *gidac_self_tx = 0;
  1801. *lidac_self_max = *lidac_self_min = *lidac_self_ave = 0;
  1802. data_size = 0;
  1803. error = cyapa_gen5_read_idac_data(cyapa,
  1804. GEN5_CMD_RETRIEVE_DATA_STRUCTURE,
  1805. GEN5_RETRIEVE_SELF_CAP_PWC_DATA,
  1806. &data_size,
  1807. lidac_self_max, lidac_self_min, lidac_self_ave);
  1808. if (error)
  1809. return error;
  1810. *gidac_self_rx = *lidac_self_max;
  1811. *gidac_self_tx = *lidac_self_min;
  1812. error = cyapa_gen5_read_idac_data(cyapa,
  1813. GEN5_CMD_RETRIEVE_DATA_STRUCTURE,
  1814. GEN5_RETRIEVE_SELF_CAP_PWC_DATA,
  1815. &data_size,
  1816. lidac_self_max, lidac_self_min, lidac_self_ave);
  1817. return error;
  1818. }
  1819. static ssize_t cyapa_gen5_execute_panel_scan(struct cyapa *cyapa)
  1820. {
  1821. struct gen5_app_cmd_head *app_cmd_head;
  1822. u8 cmd[7];
  1823. u8 resp_data[6];
  1824. int resp_len;
  1825. int error;
  1826. memset(cmd, 0, sizeof(cmd));
  1827. app_cmd_head = (struct gen5_app_cmd_head *)cmd;
  1828. put_unaligned_le16(GEN5_OUTPUT_REPORT_ADDR, &app_cmd_head->addr);
  1829. put_unaligned_le16(sizeof(cmd) - 2, &app_cmd_head->length);
  1830. app_cmd_head->report_id = GEN5_APP_CMD_REPORT_ID;
  1831. app_cmd_head->cmd_code = GEN5_CMD_EXECUTE_PANEL_SCAN;
  1832. resp_len = sizeof(resp_data);
  1833. error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
  1834. cmd, sizeof(cmd),
  1835. resp_data, &resp_len,
  1836. 500, cyapa_gen5_sort_tsg_pip_app_resp_data, true);
  1837. if (error || resp_len != sizeof(resp_data) ||
  1838. !VALID_CMD_RESP_HEADER(resp_data,
  1839. GEN5_CMD_EXECUTE_PANEL_SCAN) ||
  1840. !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5]))
  1841. return error ? error : -EAGAIN;
  1842. return 0;
  1843. }
  1844. static int cyapa_gen5_read_panel_scan_raw_data(struct cyapa *cyapa,
  1845. u8 cmd_code, u8 raw_data_type, int raw_data_max_num,
  1846. int *raw_data_max, int *raw_data_min, int *raw_data_ave,
  1847. u8 *buffer)
  1848. {
  1849. struct gen5_app_cmd_head *app_cmd_head;
  1850. struct gen5_retrieve_panel_scan_data *panel_sacn_data;
  1851. u8 cmd[12];
  1852. u8 resp_data[256]; /* Max bytes can transfer one time. */
  1853. int resp_len;
  1854. int read_elements;
  1855. int read_len;
  1856. u16 offset;
  1857. s32 value;
  1858. int sum, count;
  1859. int data_size;
  1860. s32 *intp;
  1861. int i;
  1862. int error;
  1863. if (cmd_code != GEN5_CMD_RETRIEVE_PANEL_SCAN ||
  1864. (raw_data_type > GEN5_PANEL_SCAN_SELF_DIFFCOUNT) ||
  1865. !raw_data_max || !raw_data_min || !raw_data_ave)
  1866. return -EINVAL;
  1867. intp = (s32 *)buffer;
  1868. *raw_data_max = INT_MIN;
  1869. *raw_data_min = INT_MAX;
  1870. sum = count = 0;
  1871. offset = 0;
  1872. /* Assume max element size is 4 currently. */
  1873. read_elements = (256 - GEN5_RESP_DATA_STRUCTURE_OFFSET) / 4;
  1874. read_len = read_elements * 4;
  1875. app_cmd_head = (struct gen5_app_cmd_head *)cmd;
  1876. put_unaligned_le16(GEN5_OUTPUT_REPORT_ADDR, &app_cmd_head->addr);
  1877. put_unaligned_le16(sizeof(cmd) - 2, &app_cmd_head->length);
  1878. app_cmd_head->report_id = GEN5_APP_CMD_REPORT_ID;
  1879. app_cmd_head->cmd_code = cmd_code;
  1880. panel_sacn_data = (struct gen5_retrieve_panel_scan_data *)
  1881. app_cmd_head->parameter_data;
  1882. do {
  1883. put_unaligned_le16(offset, &panel_sacn_data->read_offset);
  1884. put_unaligned_le16(read_elements,
  1885. &panel_sacn_data->read_elements);
  1886. panel_sacn_data->data_id = raw_data_type;
  1887. resp_len = GEN5_RESP_DATA_STRUCTURE_OFFSET + read_len;
  1888. error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
  1889. cmd, sizeof(cmd),
  1890. resp_data, &resp_len,
  1891. 500, cyapa_gen5_sort_tsg_pip_app_resp_data, true);
  1892. if (error || resp_len < GEN5_RESP_DATA_STRUCTURE_OFFSET ||
  1893. !VALID_CMD_RESP_HEADER(resp_data, cmd_code) ||
  1894. !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5]) ||
  1895. resp_data[6] != raw_data_type)
  1896. return error ? error : -EAGAIN;
  1897. read_elements = get_unaligned_le16(&resp_data[7]);
  1898. if (read_elements == 0)
  1899. break;
  1900. data_size = (resp_data[9] & GEN5_PWC_DATA_ELEMENT_SIZE_MASK);
  1901. offset += read_elements;
  1902. if (read_elements) {
  1903. for (i = GEN5_RESP_DATA_STRUCTURE_OFFSET;
  1904. i < (read_elements * data_size +
  1905. GEN5_RESP_DATA_STRUCTURE_OFFSET);
  1906. i += data_size) {
  1907. value = cyapa_parse_structure_data(resp_data[9],
  1908. &resp_data[i], data_size);
  1909. *raw_data_min = min(value, *raw_data_min);
  1910. *raw_data_max = max(value, *raw_data_max);
  1911. if (intp)
  1912. put_unaligned_le32(value, &intp[count]);
  1913. sum += value;
  1914. count++;
  1915. }
  1916. }
  1917. if (count >= raw_data_max_num)
  1918. break;
  1919. read_elements = (sizeof(resp_data) -
  1920. GEN5_RESP_DATA_STRUCTURE_OFFSET) / data_size;
  1921. read_len = read_elements * data_size;
  1922. } while (true);
  1923. *raw_data_ave = count ? (sum / count) : 0;
  1924. return 0;
  1925. }
  1926. static ssize_t cyapa_gen5_show_baseline(struct device *dev,
  1927. struct device_attribute *attr, char *buf)
  1928. {
  1929. struct cyapa *cyapa = dev_get_drvdata(dev);
  1930. int gidac_mutual_max, gidac_mutual_min, gidac_mutual_ave;
  1931. int lidac_mutual_max, lidac_mutual_min, lidac_mutual_ave;
  1932. int gidac_self_rx, gidac_self_tx;
  1933. int lidac_self_max, lidac_self_min, lidac_self_ave;
  1934. int raw_cap_mutual_max, raw_cap_mutual_min, raw_cap_mutual_ave;
  1935. int raw_cap_self_max, raw_cap_self_min, raw_cap_self_ave;
  1936. int mutual_diffdata_max, mutual_diffdata_min, mutual_diffdata_ave;
  1937. int self_diffdata_max, self_diffdata_min, self_diffdata_ave;
  1938. int mutual_baseline_max, mutual_baseline_min, mutual_baseline_ave;
  1939. int self_baseline_max, self_baseline_min, self_baseline_ave;
  1940. int error, resume_error;
  1941. int size;
  1942. if (cyapa->state != CYAPA_STATE_GEN5_APP)
  1943. return -EBUSY;
  1944. /* 1. Suspend Scanning*/
  1945. error = cyapa_gen5_suspend_scanning(cyapa);
  1946. if (error)
  1947. return error;
  1948. /* 2. Read global and local mutual IDAC data. */
  1949. gidac_self_rx = gidac_self_tx = 0;
  1950. error = cyapa_gen5_read_mutual_idac_data(cyapa,
  1951. &gidac_mutual_max, &gidac_mutual_min,
  1952. &gidac_mutual_ave, &lidac_mutual_max,
  1953. &lidac_mutual_min, &lidac_mutual_ave);
  1954. if (error)
  1955. goto resume_scanning;
  1956. /* 3. Read global and local self IDAC data. */
  1957. error = cyapa_gen5_read_self_idac_data(cyapa,
  1958. &gidac_self_rx, &gidac_self_tx,
  1959. &lidac_self_max, &lidac_self_min,
  1960. &lidac_self_ave);
  1961. if (error)
  1962. goto resume_scanning;
  1963. /* 4. Execuate panel scan. It must be executed before read data. */
  1964. error = cyapa_gen5_execute_panel_scan(cyapa);
  1965. if (error)
  1966. goto resume_scanning;
  1967. /* 5. Retrieve panel scan, mutual cap raw data. */
  1968. error = cyapa_gen5_read_panel_scan_raw_data(cyapa,
  1969. GEN5_CMD_RETRIEVE_PANEL_SCAN,
  1970. GEN5_PANEL_SCAN_MUTUAL_RAW_DATA,
  1971. cyapa->electrodes_x * cyapa->electrodes_y,
  1972. &raw_cap_mutual_max, &raw_cap_mutual_min,
  1973. &raw_cap_mutual_ave,
  1974. NULL);
  1975. if (error)
  1976. goto resume_scanning;
  1977. /* 6. Retrieve panel scan, self cap raw data. */
  1978. error = cyapa_gen5_read_panel_scan_raw_data(cyapa,
  1979. GEN5_CMD_RETRIEVE_PANEL_SCAN,
  1980. GEN5_PANEL_SCAN_SELF_RAW_DATA,
  1981. cyapa->electrodes_x + cyapa->electrodes_y,
  1982. &raw_cap_self_max, &raw_cap_self_min,
  1983. &raw_cap_self_ave,
  1984. NULL);
  1985. if (error)
  1986. goto resume_scanning;
  1987. /* 7. Retrieve panel scan, mutual cap diffcount raw data. */
  1988. error = cyapa_gen5_read_panel_scan_raw_data(cyapa,
  1989. GEN5_CMD_RETRIEVE_PANEL_SCAN,
  1990. GEN5_PANEL_SCAN_MUTUAL_DIFFCOUNT,
  1991. cyapa->electrodes_x * cyapa->electrodes_y,
  1992. &mutual_diffdata_max, &mutual_diffdata_min,
  1993. &mutual_diffdata_ave,
  1994. NULL);
  1995. if (error)
  1996. goto resume_scanning;
  1997. /* 8. Retrieve panel scan, self cap diffcount raw data. */
  1998. error = cyapa_gen5_read_panel_scan_raw_data(cyapa,
  1999. GEN5_CMD_RETRIEVE_PANEL_SCAN,
  2000. GEN5_PANEL_SCAN_SELF_DIFFCOUNT,
  2001. cyapa->electrodes_x + cyapa->electrodes_y,
  2002. &self_diffdata_max, &self_diffdata_min,
  2003. &self_diffdata_ave,
  2004. NULL);
  2005. if (error)
  2006. goto resume_scanning;
  2007. /* 9. Retrieve panel scan, mutual cap baseline raw data. */
  2008. error = cyapa_gen5_read_panel_scan_raw_data(cyapa,
  2009. GEN5_CMD_RETRIEVE_PANEL_SCAN,
  2010. GEN5_PANEL_SCAN_MUTUAL_BASELINE,
  2011. cyapa->electrodes_x * cyapa->electrodes_y,
  2012. &mutual_baseline_max, &mutual_baseline_min,
  2013. &mutual_baseline_ave,
  2014. NULL);
  2015. if (error)
  2016. goto resume_scanning;
  2017. /* 10. Retrieve panel scan, self cap baseline raw data. */
  2018. error = cyapa_gen5_read_panel_scan_raw_data(cyapa,
  2019. GEN5_CMD_RETRIEVE_PANEL_SCAN,
  2020. GEN5_PANEL_SCAN_SELF_BASELINE,
  2021. cyapa->electrodes_x + cyapa->electrodes_y,
  2022. &self_baseline_max, &self_baseline_min,
  2023. &self_baseline_ave,
  2024. NULL);
  2025. if (error)
  2026. goto resume_scanning;
  2027. resume_scanning:
  2028. /* 11. Resume Scanning*/
  2029. resume_error = cyapa_gen5_resume_scanning(cyapa);
  2030. if (resume_error || error)
  2031. return resume_error ? resume_error : error;
  2032. /* 12. Output data strings */
  2033. size = scnprintf(buf, PAGE_SIZE, "%d %d %d %d %d %d %d %d %d %d %d ",
  2034. gidac_mutual_min, gidac_mutual_max, gidac_mutual_ave,
  2035. lidac_mutual_min, lidac_mutual_max, lidac_mutual_ave,
  2036. gidac_self_rx, gidac_self_tx,
  2037. lidac_self_min, lidac_self_max, lidac_self_ave);
  2038. size += scnprintf(buf + size, PAGE_SIZE - size,
  2039. "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
  2040. raw_cap_mutual_min, raw_cap_mutual_max, raw_cap_mutual_ave,
  2041. raw_cap_self_min, raw_cap_self_max, raw_cap_self_ave,
  2042. mutual_diffdata_min, mutual_diffdata_max, mutual_diffdata_ave,
  2043. self_diffdata_min, self_diffdata_max, self_diffdata_ave,
  2044. mutual_baseline_min, mutual_baseline_max, mutual_baseline_ave,
  2045. self_baseline_min, self_baseline_max, self_baseline_ave);
  2046. return size;
  2047. }
  2048. static bool cyapa_gen5_sort_system_info_data(struct cyapa *cyapa,
  2049. u8 *buf, int len)
  2050. {
  2051. /* Check the report id and command code */
  2052. if (VALID_CMD_RESP_HEADER(buf, 0x02))
  2053. return true;
  2054. return false;
  2055. }
  2056. static int cyapa_gen5_bl_query_data(struct cyapa *cyapa)
  2057. {
  2058. u8 bl_query_data_cmd[] = { 0x04, 0x00, 0x0b, 0x00, 0x40, 0x00,
  2059. 0x01, 0x3c, 0x00, 0x00, 0xb0, 0x42, 0x17
  2060. };
  2061. u8 resp_data[GEN5_BL_READ_APP_INFO_RESP_LEN];
  2062. int resp_len;
  2063. int error;
  2064. resp_len = GEN5_BL_READ_APP_INFO_RESP_LEN;
  2065. error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
  2066. bl_query_data_cmd, sizeof(bl_query_data_cmd),
  2067. resp_data, &resp_len,
  2068. 500, cyapa_gen5_sort_tsg_pip_bl_resp_data, false);
  2069. if (error || resp_len != GEN5_BL_READ_APP_INFO_RESP_LEN ||
  2070. !GEN5_CMD_COMPLETE_SUCCESS(resp_data[5]))
  2071. return error ? error : -EIO;
  2072. memcpy(&cyapa->product_id[0], &resp_data[8], 5);
  2073. cyapa->product_id[5] = '-';
  2074. memcpy(&cyapa->product_id[6], &resp_data[13], 6);
  2075. cyapa->product_id[12] = '-';
  2076. memcpy(&cyapa->product_id[13], &resp_data[19], 2);
  2077. cyapa->product_id[15] = '\0';
  2078. cyapa->fw_maj_ver = resp_data[22];
  2079. cyapa->fw_min_ver = resp_data[23];
  2080. return 0;
  2081. }
  2082. static int cyapa_gen5_get_query_data(struct cyapa *cyapa)
  2083. {
  2084. u8 get_system_information[] = {
  2085. 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x02
  2086. };
  2087. u8 resp_data[71];
  2088. int resp_len;
  2089. u16 product_family;
  2090. int error;
  2091. resp_len = sizeof(resp_data);
  2092. error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
  2093. get_system_information, sizeof(get_system_information),
  2094. resp_data, &resp_len,
  2095. 2000, cyapa_gen5_sort_system_info_data, false);
  2096. if (error || resp_len < sizeof(resp_data))
  2097. return error ? error : -EIO;
  2098. product_family = get_unaligned_le16(&resp_data[7]);
  2099. if ((product_family & GEN5_PRODUCT_FAMILY_MASK) !=
  2100. GEN5_PRODUCT_FAMILY_TRACKPAD)
  2101. return -EINVAL;
  2102. cyapa->fw_maj_ver = resp_data[15];
  2103. cyapa->fw_min_ver = resp_data[16];
  2104. cyapa->electrodes_x = resp_data[52];
  2105. cyapa->electrodes_y = resp_data[53];
  2106. cyapa->physical_size_x = get_unaligned_le16(&resp_data[54]) / 100;
  2107. cyapa->physical_size_y = get_unaligned_le16(&resp_data[56]) / 100;
  2108. cyapa->max_abs_x = get_unaligned_le16(&resp_data[58]);
  2109. cyapa->max_abs_y = get_unaligned_le16(&resp_data[60]);
  2110. cyapa->max_z = get_unaligned_le16(&resp_data[62]);
  2111. cyapa->x_origin = resp_data[64] & 0x01;
  2112. cyapa->y_origin = resp_data[65] & 0x01;
  2113. cyapa->btn_capability = (resp_data[70] << 3) & CAPABILITY_BTN_MASK;
  2114. memcpy(&cyapa->product_id[0], &resp_data[33], 5);
  2115. cyapa->product_id[5] = '-';
  2116. memcpy(&cyapa->product_id[6], &resp_data[38], 6);
  2117. cyapa->product_id[12] = '-';
  2118. memcpy(&cyapa->product_id[13], &resp_data[44], 2);
  2119. cyapa->product_id[15] = '\0';
  2120. if (!cyapa->electrodes_x || !cyapa->electrodes_y ||
  2121. !cyapa->physical_size_x || !cyapa->physical_size_y ||
  2122. !cyapa->max_abs_x || !cyapa->max_abs_y || !cyapa->max_z)
  2123. return -EINVAL;
  2124. return 0;
  2125. }
  2126. static int cyapa_gen5_do_operational_check(struct cyapa *cyapa)
  2127. {
  2128. struct device *dev = &cyapa->client->dev;
  2129. int error;
  2130. if (cyapa->gen != CYAPA_GEN5)
  2131. return -ENODEV;
  2132. switch (cyapa->state) {
  2133. case CYAPA_STATE_GEN5_BL:
  2134. error = cyapa_gen5_bl_exit(cyapa);
  2135. if (error) {
  2136. /* Rry to update trackpad product information. */
  2137. cyapa_gen5_bl_query_data(cyapa);
  2138. goto out;
  2139. }
  2140. cyapa->state = CYAPA_STATE_GEN5_APP;
  2141. case CYAPA_STATE_GEN5_APP:
  2142. /*
  2143. * If trackpad device in deep sleep mode,
  2144. * the app command will fail.
  2145. * So always try to reset trackpad device to full active when
  2146. * the device state is requeried.
  2147. */
  2148. error = cyapa_gen5_set_power_mode(cyapa,
  2149. PWR_MODE_FULL_ACTIVE, 0);
  2150. if (error)
  2151. dev_warn(dev, "%s: failed to set power active mode.\n",
  2152. __func__);
  2153. /* Get trackpad product information. */
  2154. error = cyapa_gen5_get_query_data(cyapa);
  2155. if (error)
  2156. goto out;
  2157. /* Only support product ID starting with CYTRA */
  2158. if (memcmp(cyapa->product_id, product_id,
  2159. strlen(product_id)) != 0) {
  2160. dev_err(dev, "%s: unknown product ID (%s)\n",
  2161. __func__, cyapa->product_id);
  2162. error = -EINVAL;
  2163. }
  2164. break;
  2165. default:
  2166. error = -EINVAL;
  2167. }
  2168. out:
  2169. return error;
  2170. }
  2171. /*
  2172. * Return false, do not continue process
  2173. * Return true, continue process.
  2174. */
  2175. static bool cyapa_gen5_irq_cmd_handler(struct cyapa *cyapa)
  2176. {
  2177. struct cyapa_gen5_cmd_states *gen5_pip = &cyapa->cmd_states.gen5;
  2178. int length;
  2179. if (atomic_read(&gen5_pip->cmd_issued)) {
  2180. /* Polling command response data. */
  2181. if (gen5_pip->is_irq_mode == false)
  2182. return false;
  2183. /*
  2184. * Read out all none command response data.
  2185. * these output data may caused by user put finger on
  2186. * trackpad when host waiting the command response.
  2187. */
  2188. cyapa_i2c_pip_read(cyapa, gen5_pip->irq_cmd_buf,
  2189. GEN5_RESP_LENGTH_SIZE);
  2190. length = get_unaligned_le16(gen5_pip->irq_cmd_buf);
  2191. length = (length <= GEN5_RESP_LENGTH_SIZE) ?
  2192. GEN5_RESP_LENGTH_SIZE : length;
  2193. if (length > GEN5_RESP_LENGTH_SIZE)
  2194. cyapa_i2c_pip_read(cyapa,
  2195. gen5_pip->irq_cmd_buf, length);
  2196. if (!(gen5_pip->resp_sort_func &&
  2197. gen5_pip->resp_sort_func(cyapa,
  2198. gen5_pip->irq_cmd_buf, length))) {
  2199. /*
  2200. * Work around the Gen5 V1 firmware
  2201. * that does not assert interrupt signalling
  2202. * that command response is ready if user
  2203. * keeps touching the trackpad while command
  2204. * is sent to the device.
  2205. */
  2206. length = 0;
  2207. if (gen5_pip->resp_len)
  2208. length = *gen5_pip->resp_len;
  2209. cyapa_empty_pip_output_data(cyapa,
  2210. gen5_pip->resp_data,
  2211. &length,
  2212. gen5_pip->resp_sort_func);
  2213. if (gen5_pip->resp_len && length != 0) {
  2214. *gen5_pip->resp_len = length;
  2215. atomic_dec(&gen5_pip->cmd_issued);
  2216. complete(&gen5_pip->cmd_ready);
  2217. }
  2218. return false;
  2219. }
  2220. if (gen5_pip->resp_data && gen5_pip->resp_len) {
  2221. *gen5_pip->resp_len = (*gen5_pip->resp_len < length) ?
  2222. *gen5_pip->resp_len : length;
  2223. memcpy(gen5_pip->resp_data, gen5_pip->irq_cmd_buf,
  2224. *gen5_pip->resp_len);
  2225. }
  2226. atomic_dec(&gen5_pip->cmd_issued);
  2227. complete(&gen5_pip->cmd_ready);
  2228. return false;
  2229. }
  2230. return true;
  2231. }
  2232. static void cyapa_gen5_report_buttons(struct cyapa *cyapa,
  2233. const struct cyapa_gen5_report_data *report_data)
  2234. {
  2235. struct input_dev *input = cyapa->input;
  2236. u8 buttons = report_data->report_head[GEN5_BUTTONS_OFFSET];
  2237. buttons = (buttons << CAPABILITY_BTN_SHIFT) & CAPABILITY_BTN_MASK;
  2238. if (cyapa->btn_capability & CAPABILITY_LEFT_BTN_MASK) {
  2239. input_report_key(input, BTN_LEFT,
  2240. !!(buttons & CAPABILITY_LEFT_BTN_MASK));
  2241. }
  2242. if (cyapa->btn_capability & CAPABILITY_MIDDLE_BTN_MASK) {
  2243. input_report_key(input, BTN_MIDDLE,
  2244. !!(buttons & CAPABILITY_MIDDLE_BTN_MASK));
  2245. }
  2246. if (cyapa->btn_capability & CAPABILITY_RIGHT_BTN_MASK) {
  2247. input_report_key(input, BTN_RIGHT,
  2248. !!(buttons & CAPABILITY_RIGHT_BTN_MASK));
  2249. }
  2250. input_sync(input);
  2251. }
  2252. static void cyapa_gen5_report_slot_data(struct cyapa *cyapa,
  2253. const struct cyapa_gen5_touch_record *touch)
  2254. {
  2255. struct input_dev *input = cyapa->input;
  2256. u8 event_id = GEN5_GET_EVENT_ID(touch->touch_tip_event_id);
  2257. int slot = GEN5_GET_TOUCH_ID(touch->touch_tip_event_id);
  2258. int x, y;
  2259. if (event_id == RECORD_EVENT_LIFTOFF)
  2260. return;
  2261. input_mt_slot(input, slot);
  2262. input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
  2263. x = (touch->x_hi << 8) | touch->x_lo;
  2264. if (cyapa->x_origin)
  2265. x = cyapa->max_abs_x - x;
  2266. input_report_abs(input, ABS_MT_POSITION_X, x);
  2267. y = (touch->y_hi << 8) | touch->y_lo;
  2268. if (cyapa->y_origin)
  2269. y = cyapa->max_abs_y - y;
  2270. input_report_abs(input, ABS_MT_POSITION_Y, y);
  2271. input_report_abs(input, ABS_MT_PRESSURE,
  2272. touch->z);
  2273. input_report_abs(input, ABS_MT_TOUCH_MAJOR,
  2274. touch->major_axis_len);
  2275. input_report_abs(input, ABS_MT_TOUCH_MINOR,
  2276. touch->minor_axis_len);
  2277. input_report_abs(input, ABS_MT_WIDTH_MAJOR,
  2278. touch->major_tool_len);
  2279. input_report_abs(input, ABS_MT_WIDTH_MINOR,
  2280. touch->minor_tool_len);
  2281. input_report_abs(input, ABS_MT_ORIENTATION,
  2282. touch->orientation);
  2283. }
  2284. static void cyapa_gen5_report_touches(struct cyapa *cyapa,
  2285. const struct cyapa_gen5_report_data *report_data)
  2286. {
  2287. struct input_dev *input = cyapa->input;
  2288. unsigned int touch_num;
  2289. int i;
  2290. touch_num = report_data->report_head[GEN5_NUMBER_OF_TOUCH_OFFSET] &
  2291. GEN5_NUMBER_OF_TOUCH_MASK;
  2292. for (i = 0; i < touch_num; i++)
  2293. cyapa_gen5_report_slot_data(cyapa,
  2294. &report_data->touch_records[i]);
  2295. input_mt_sync_frame(input);
  2296. input_sync(input);
  2297. }
  2298. static int cyapa_gen5_irq_handler(struct cyapa *cyapa)
  2299. {
  2300. struct device *dev = &cyapa->client->dev;
  2301. struct cyapa_gen5_report_data report_data;
  2302. int ret;
  2303. u8 report_id;
  2304. unsigned int report_len;
  2305. if (cyapa->gen != CYAPA_GEN5 ||
  2306. cyapa->state != CYAPA_STATE_GEN5_APP) {
  2307. dev_err(dev, "invalid device state, gen=%d, state=0x%02x\n",
  2308. cyapa->gen, cyapa->state);
  2309. return -EINVAL;
  2310. }
  2311. ret = cyapa_i2c_pip_read(cyapa, (u8 *)&report_data,
  2312. GEN5_RESP_LENGTH_SIZE);
  2313. if (ret != GEN5_RESP_LENGTH_SIZE) {
  2314. dev_err(dev, "failed to read length bytes, (%d)\n", ret);
  2315. return -EINVAL;
  2316. }
  2317. report_len = get_unaligned_le16(
  2318. &report_data.report_head[GEN5_RESP_LENGTH_OFFSET]);
  2319. if (report_len < GEN5_RESP_LENGTH_SIZE) {
  2320. /* Invliad length or internal reset happened. */
  2321. dev_err(dev, "invalid report_len=%d. bytes: %02x %02x\n",
  2322. report_len, report_data.report_head[0],
  2323. report_data.report_head[1]);
  2324. return -EINVAL;
  2325. }
  2326. /* Idle, no data for report. */
  2327. if (report_len == GEN5_RESP_LENGTH_SIZE)
  2328. return 0;
  2329. ret = cyapa_i2c_pip_read(cyapa, (u8 *)&report_data, report_len);
  2330. if (ret != report_len) {
  2331. dev_err(dev, "failed to read %d bytes report data, (%d)\n",
  2332. report_len, ret);
  2333. return -EINVAL;
  2334. }
  2335. report_id = report_data.report_head[GEN5_RESP_REPORT_ID_OFFSET];
  2336. if (report_id == GEN5_WAKEUP_EVENT_REPORT_ID &&
  2337. report_len == GEN5_WAKEUP_EVENT_SIZE) {
  2338. /*
  2339. * Device wake event from deep sleep mode for touch.
  2340. * This interrupt event is used to wake system up.
  2341. */
  2342. return 0;
  2343. } else if (report_id != GEN5_TOUCH_REPORT_ID &&
  2344. report_id != GEN5_BTN_REPORT_ID &&
  2345. report_id != GEN5_OLD_PUSH_BTN_REPORT_ID &&
  2346. report_id != GEN5_PUSH_BTN_REPORT_ID) {
  2347. /* Running in BL mode or unknown response data read. */
  2348. dev_err(dev, "invalid report_id=0x%02x\n", report_id);
  2349. return -EINVAL;
  2350. }
  2351. if (report_id == GEN5_TOUCH_REPORT_ID &&
  2352. (report_len < GEN5_TOUCH_REPORT_HEAD_SIZE ||
  2353. report_len > GEN5_TOUCH_REPORT_MAX_SIZE)) {
  2354. /* Invalid report data length for finger packet. */
  2355. dev_err(dev, "invalid touch packet length=%d\n", report_len);
  2356. return 0;
  2357. }
  2358. if ((report_id == GEN5_BTN_REPORT_ID ||
  2359. report_id == GEN5_OLD_PUSH_BTN_REPORT_ID ||
  2360. report_id == GEN5_PUSH_BTN_REPORT_ID) &&
  2361. (report_len < GEN5_BTN_REPORT_HEAD_SIZE ||
  2362. report_len > GEN5_BTN_REPORT_MAX_SIZE)) {
  2363. /* Invalid report data length of button packet. */
  2364. dev_err(dev, "invalid button packet length=%d\n", report_len);
  2365. return 0;
  2366. }
  2367. if (report_id == GEN5_TOUCH_REPORT_ID)
  2368. cyapa_gen5_report_touches(cyapa, &report_data);
  2369. else
  2370. cyapa_gen5_report_buttons(cyapa, &report_data);
  2371. return 0;
  2372. }
  2373. static int cyapa_gen5_bl_activate(struct cyapa *cyapa) { return 0; }
  2374. static int cyapa_gen5_bl_deactivate(struct cyapa *cyapa) { return 0; }
  2375. const struct cyapa_dev_ops cyapa_gen5_ops = {
  2376. .check_fw = cyapa_gen5_check_fw,
  2377. .bl_enter = cyapa_gen5_bl_enter,
  2378. .bl_initiate = cyapa_gen5_bl_initiate,
  2379. .update_fw = cyapa_gen5_do_fw_update,
  2380. .bl_activate = cyapa_gen5_bl_activate,
  2381. .bl_deactivate = cyapa_gen5_bl_deactivate,
  2382. .show_baseline = cyapa_gen5_show_baseline,
  2383. .calibrate_store = cyapa_gen5_do_calibrate,
  2384. .initialize = cyapa_gen5_initialize,
  2385. .state_parse = cyapa_gen5_state_parse,
  2386. .operational_check = cyapa_gen5_do_operational_check,
  2387. .irq_handler = cyapa_gen5_irq_handler,
  2388. .irq_cmd_handler = cyapa_gen5_irq_cmd_handler,
  2389. .sort_empty_output_data = cyapa_empty_pip_output_data,
  2390. .set_power_mode = cyapa_gen5_set_power_mode,
  2391. };