0006-ipts.patch 57 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061
  1. From 2a57236358e1eaf2bdb4f3f6a247d1a8e25afd8b Mon Sep 17 00:00:00 2001
  2. From: Dorian Stoll <dorian.stoll@tmsp.io>
  3. Date: Mon, 27 Jan 2020 21:16:20 +0100
  4. Subject: [PATCH 6/6] ipts
  5. ---
  6. drivers/input/touchscreen/Kconfig | 2 +
  7. drivers/input/touchscreen/Makefile | 1 +
  8. drivers/input/touchscreen/ipts/Kconfig | 16 ++
  9. drivers/input/touchscreen/ipts/Makefile | 17 ++
  10. drivers/input/touchscreen/ipts/context.h | 60 ++++
  11. drivers/input/touchscreen/ipts/control.c | 94 +++++++
  12. drivers/input/touchscreen/ipts/control.h | 18 ++
  13. drivers/input/touchscreen/ipts/data.c | 107 +++++++
  14. drivers/input/touchscreen/ipts/data.h | 12 +
  15. drivers/input/touchscreen/ipts/hid.c | 38 +++
  16. drivers/input/touchscreen/ipts/hid.h | 13 +
  17. drivers/input/touchscreen/ipts/init.c | 93 ++++++
  18. drivers/input/touchscreen/ipts/math.c | 103 +++++++
  19. drivers/input/touchscreen/ipts/math.h | 21 ++
  20. drivers/input/touchscreen/ipts/params.c | 27 ++
  21. drivers/input/touchscreen/ipts/params.h | 15 +
  22. drivers/input/touchscreen/ipts/payload.c | 52 ++++
  23. drivers/input/touchscreen/ipts/payload.h | 14 +
  24. .../touchscreen/ipts/protocol/commands.h | 61 ++++
  25. .../input/touchscreen/ipts/protocol/data.h | 30 ++
  26. .../input/touchscreen/ipts/protocol/events.h | 29 ++
  27. .../touchscreen/ipts/protocol/feedback.h | 30 ++
  28. .../input/touchscreen/ipts/protocol/payload.h | 47 ++++
  29. .../touchscreen/ipts/protocol/responses.h | 62 ++++
  30. .../touchscreen/ipts/protocol/singletouch.h | 17 ++
  31. .../input/touchscreen/ipts/protocol/stylus.h | 52 ++++
  32. drivers/input/touchscreen/ipts/receiver.c | 265 ++++++++++++++++++
  33. drivers/input/touchscreen/ipts/receiver.h | 8 +
  34. drivers/input/touchscreen/ipts/resources.c | 131 +++++++++
  35. drivers/input/touchscreen/ipts/resources.h | 11 +
  36. drivers/input/touchscreen/ipts/singletouch.c | 64 +++++
  37. drivers/input/touchscreen/ipts/singletouch.h | 14 +
  38. drivers/input/touchscreen/ipts/stylus.c | 179 ++++++++++++
  39. drivers/input/touchscreen/ipts/stylus.h | 14 +
  40. drivers/misc/mei/hw-me-regs.h | 2 +
  41. drivers/misc/mei/pci-me.c | 2 +
  42. include/uapi/linux/input.h | 1 +
  43. 37 files changed, 1722 insertions(+)
  44. create mode 100644 drivers/input/touchscreen/ipts/Kconfig
  45. create mode 100644 drivers/input/touchscreen/ipts/Makefile
  46. create mode 100644 drivers/input/touchscreen/ipts/context.h
  47. create mode 100644 drivers/input/touchscreen/ipts/control.c
  48. create mode 100644 drivers/input/touchscreen/ipts/control.h
  49. create mode 100644 drivers/input/touchscreen/ipts/data.c
  50. create mode 100644 drivers/input/touchscreen/ipts/data.h
  51. create mode 100644 drivers/input/touchscreen/ipts/hid.c
  52. create mode 100644 drivers/input/touchscreen/ipts/hid.h
  53. create mode 100644 drivers/input/touchscreen/ipts/init.c
  54. create mode 100644 drivers/input/touchscreen/ipts/math.c
  55. create mode 100644 drivers/input/touchscreen/ipts/math.h
  56. create mode 100644 drivers/input/touchscreen/ipts/params.c
  57. create mode 100644 drivers/input/touchscreen/ipts/params.h
  58. create mode 100644 drivers/input/touchscreen/ipts/payload.c
  59. create mode 100644 drivers/input/touchscreen/ipts/payload.h
  60. create mode 100644 drivers/input/touchscreen/ipts/protocol/commands.h
  61. create mode 100644 drivers/input/touchscreen/ipts/protocol/data.h
  62. create mode 100644 drivers/input/touchscreen/ipts/protocol/events.h
  63. create mode 100644 drivers/input/touchscreen/ipts/protocol/feedback.h
  64. create mode 100644 drivers/input/touchscreen/ipts/protocol/payload.h
  65. create mode 100644 drivers/input/touchscreen/ipts/protocol/responses.h
  66. create mode 100644 drivers/input/touchscreen/ipts/protocol/singletouch.h
  67. create mode 100644 drivers/input/touchscreen/ipts/protocol/stylus.h
  68. create mode 100644 drivers/input/touchscreen/ipts/receiver.c
  69. create mode 100644 drivers/input/touchscreen/ipts/receiver.h
  70. create mode 100644 drivers/input/touchscreen/ipts/resources.c
  71. create mode 100644 drivers/input/touchscreen/ipts/resources.h
  72. create mode 100644 drivers/input/touchscreen/ipts/singletouch.c
  73. create mode 100644 drivers/input/touchscreen/ipts/singletouch.h
  74. create mode 100644 drivers/input/touchscreen/ipts/stylus.c
  75. create mode 100644 drivers/input/touchscreen/ipts/stylus.h
  76. diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
  77. index 46ad9090493bb..c476a153b2f80 100644
  78. --- a/drivers/input/touchscreen/Kconfig
  79. +++ b/drivers/input/touchscreen/Kconfig
  80. @@ -1314,4 +1314,6 @@ config TOUCHSCREEN_IQS5XX
  81. To compile this driver as a module, choose M here: the
  82. module will be called iqs5xx.
  83. +source "drivers/input/touchscreen/ipts/Kconfig"
  84. +
  85. endif
  86. diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
  87. index 94c6162409b37..864f0e092ab67 100644
  88. --- a/drivers/input/touchscreen/Makefile
  89. +++ b/drivers/input/touchscreen/Makefile
  90. @@ -45,6 +45,7 @@ obj-$(CONFIG_TOUCHSCREEN_EXC3000) += exc3000.o
  91. obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
  92. obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o
  93. obj-$(CONFIG_TOUCHSCREEN_HIDEEP) += hideep.o
  94. +obj-$(CONFIG_TOUCHSCREEN_IPTS) += ipts/
  95. obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o
  96. obj-$(CONFIG_TOUCHSCREEN_IMX6UL_TSC) += imx6ul_tsc.o
  97. obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
  98. diff --git a/drivers/input/touchscreen/ipts/Kconfig b/drivers/input/touchscreen/ipts/Kconfig
  99. new file mode 100644
  100. index 0000000000000..d3c530dafa948
  101. --- /dev/null
  102. +++ b/drivers/input/touchscreen/ipts/Kconfig
  103. @@ -0,0 +1,16 @@
  104. +# SPDX-License-Identifier: GPL-2.0-or-later
  105. +
  106. +config TOUCHSCREEN_IPTS
  107. + tristate "Intel Precise Touch & Stylus"
  108. + select INTEL_MEI
  109. + depends on X86
  110. + depends on PCI
  111. + depends on HID
  112. + help
  113. + Say Y here if your system has a touchscreen using Intels
  114. + Precise Touch & Stylus (IPTS).
  115. +
  116. + If unsure say N.
  117. +
  118. + To compile this driver as a module, choose M here: the
  119. + module will be called ipts.
  120. diff --git a/drivers/input/touchscreen/ipts/Makefile b/drivers/input/touchscreen/ipts/Makefile
  121. new file mode 100644
  122. index 0000000000000..0f7c904e73171
  123. --- /dev/null
  124. +++ b/drivers/input/touchscreen/ipts/Makefile
  125. @@ -0,0 +1,17 @@
  126. +# SPDX-License-Identifier: GPL-2.0-or-later
  127. +#
  128. +# Makefile for the IPTS touchscreen driver
  129. +#
  130. +
  131. +obj-$(CONFIG_TOUCHSCREEN_IPTS) += ipts.o
  132. +ipts-objs := control.o
  133. +ipts-objs += data.o
  134. +ipts-objs += hid.o
  135. +ipts-objs += init.o
  136. +ipts-objs += math.o
  137. +ipts-objs += params.o
  138. +ipts-objs += payload.o
  139. +ipts-objs += receiver.o
  140. +ipts-objs += resources.o
  141. +ipts-objs += singletouch.o
  142. +ipts-objs += stylus.o
  143. diff --git a/drivers/input/touchscreen/ipts/context.h b/drivers/input/touchscreen/ipts/context.h
  144. new file mode 100644
  145. index 0000000000000..ab26552579a5c
  146. --- /dev/null
  147. +++ b/drivers/input/touchscreen/ipts/context.h
  148. @@ -0,0 +1,60 @@
  149. +/* SPDX-License-Identifier: GPL-2.0-or-later */
  150. +
  151. +#ifndef _IPTS_CONTEXT_H_
  152. +#define _IPTS_CONTEXT_H_
  153. +
  154. +#include <linux/kthread.h>
  155. +#include <linux/input.h>
  156. +#include <linux/mei_cl_bus.h>
  157. +#include <linux/types.h>
  158. +
  159. +#include "protocol/commands.h"
  160. +#include "protocol/responses.h"
  161. +
  162. +/* HACK: Workaround for DKMS build without BUS_MEI patch */
  163. +#ifndef BUS_MEI
  164. +#define BUS_MEI 0x44
  165. +#endif
  166. +
  167. +/* IPTS driver states */
  168. +enum ipts_host_status {
  169. + IPTS_HOST_STATUS_NONE,
  170. + IPTS_HOST_STATUS_INIT,
  171. + IPTS_HOST_STATUS_RESOURCE_READY,
  172. + IPTS_HOST_STATUS_STARTED,
  173. + IPTS_HOST_STATUS_STOPPING,
  174. + IPTS_HOST_STATUS_RESTARTING
  175. +};
  176. +
  177. +struct ipts_buffer_info {
  178. + u8 *address;
  179. + dma_addr_t dma_address;
  180. +};
  181. +
  182. +struct ipts_context {
  183. + struct mei_cl_device *client_dev;
  184. + struct device *dev;
  185. + struct ipts_device_info device_info;
  186. +
  187. + enum ipts_host_status status;
  188. + enum ipts_sensor_mode mode;
  189. +
  190. + struct ipts_buffer_info data[16];
  191. + struct ipts_buffer_info feedback[16];
  192. + struct ipts_buffer_info doorbell;
  193. +
  194. + /*
  195. + * These buffers are not actually used by anything, but they need
  196. + * to be allocated and passed to the ME to get proper functionality.
  197. + */
  198. + struct ipts_buffer_info workqueue;
  199. + struct ipts_buffer_info host2me;
  200. +
  201. + struct task_struct *receiver_loop;
  202. + struct task_struct *data_loop;
  203. +
  204. + struct input_dev *stylus;
  205. + struct input_dev *singletouch;
  206. +};
  207. +
  208. +#endif /* _IPTS_CONTEXT_H_ */
  209. diff --git a/drivers/input/touchscreen/ipts/control.c b/drivers/input/touchscreen/ipts/control.c
  210. new file mode 100644
  211. index 0000000000000..9179eca665585
  212. --- /dev/null
  213. +++ b/drivers/input/touchscreen/ipts/control.c
  214. @@ -0,0 +1,94 @@
  215. +// SPDX-License-Identifier: GPL-2.0-or-later
  216. +
  217. +#include <linux/mei_cl_bus.h>
  218. +#include <linux/types.h>
  219. +
  220. +#include "context.h"
  221. +#include "data.h"
  222. +#include "params.h"
  223. +#include "protocol/commands.h"
  224. +#include "protocol/events.h"
  225. +#include "protocol/feedback.h"
  226. +#include "resources.h"
  227. +
  228. +int ipts_control_send(struct ipts_context *ipts,
  229. + u32 cmd, void *data, u32 size)
  230. +{
  231. + int ret;
  232. + struct ipts_command msg;
  233. +
  234. + memset(&msg, 0, sizeof(struct ipts_command));
  235. + msg.code = cmd;
  236. +
  237. + // Copy message payload
  238. + if (data && size > 0)
  239. + memcpy(&msg.data, data, size);
  240. +
  241. + ret = mei_cldev_send(ipts->client_dev, (u8 *)&msg,
  242. + sizeof(msg.code) + size);
  243. + if (ret < 0) {
  244. + dev_err(ipts->dev, "%s: error 0x%X:%d\n", __func__, cmd, ret);
  245. + return ret;
  246. + }
  247. +
  248. + return 0;
  249. +}
  250. +
  251. +int ipts_control_send_feedback(struct ipts_context *ipts,
  252. + u32 buffer, u32 transaction)
  253. +{
  254. + struct ipts_buffer_info feedback_buffer;
  255. + struct ipts_feedback *feedback;
  256. + struct ipts_feedback_cmd cmd;
  257. +
  258. + feedback_buffer = ipts->feedback[buffer];
  259. + feedback = (struct ipts_feedback *)feedback_buffer.address;
  260. +
  261. + memset(feedback, 0, sizeof(struct ipts_feedback));
  262. + memset(&cmd, 0, sizeof(struct ipts_feedback_cmd));
  263. +
  264. + feedback->type = IPTS_FEEDBACK_TYPE_NONE;
  265. + feedback->transaction = transaction;
  266. +
  267. + cmd.buffer = buffer;
  268. + cmd.transaction = transaction;
  269. +
  270. + return ipts_control_send(ipts, IPTS_CMD(FEEDBACK),
  271. + &cmd, sizeof(struct ipts_feedback_cmd));
  272. +}
  273. +
  274. +int ipts_control_start(struct ipts_context *ipts)
  275. +{
  276. + ipts->status = IPTS_HOST_STATUS_INIT;
  277. +
  278. + if (ipts_params.singletouch)
  279. + ipts->mode = IPTS_SENSOR_MODE_SINGLETOUCH;
  280. + else
  281. + ipts->mode = IPTS_SENSOR_MODE_MULTITOUCH;
  282. +
  283. + return ipts_control_send(ipts, IPTS_CMD(NOTIFY_DEV_READY), NULL, 0);
  284. +}
  285. +
  286. +void ipts_control_stop(struct ipts_context *ipts)
  287. +{
  288. + enum ipts_host_status old_status = ipts->status;
  289. +
  290. + ipts->status = IPTS_HOST_STATUS_STOPPING;
  291. + ipts_control_send(ipts, IPTS_CMD(QUIESCE_IO), NULL, 0);
  292. + ipts_control_send(ipts, IPTS_CMD(CLEAR_MEM_WINDOW), NULL, 0);
  293. +
  294. + if (old_status < IPTS_HOST_STATUS_RESOURCE_READY)
  295. + return;
  296. +
  297. + ipts_data_free(ipts);
  298. + ipts_resources_free(ipts);
  299. +}
  300. +
  301. +int ipts_control_restart(struct ipts_context *ipts)
  302. +{
  303. + dev_info(ipts->dev, "Restarting IPTS\n");
  304. + ipts_control_stop(ipts);
  305. +
  306. + ipts->status = IPTS_HOST_STATUS_RESTARTING;
  307. + return ipts_control_send(ipts, IPTS_CMD(QUIESCE_IO), NULL, 0);
  308. +}
  309. diff --git a/drivers/input/touchscreen/ipts/control.h b/drivers/input/touchscreen/ipts/control.h
  310. new file mode 100644
  311. index 0000000000000..e57609c85d62a
  312. --- /dev/null
  313. +++ b/drivers/input/touchscreen/ipts/control.h
  314. @@ -0,0 +1,18 @@
  315. +/* SPDX-License-Identifier: GPL-2.0-or-later */
  316. +
  317. +#ifndef _IPTS_CONTROL_H_
  318. +#define _IPTS_CONTROL_H_
  319. +
  320. +#include <linux/types.h>
  321. +
  322. +#include "context.h"
  323. +
  324. +int ipts_control_start(struct ipts_context *ipts);
  325. +void ipts_control_stop(struct ipts_context *ipts);
  326. +int ipts_control_restart(struct ipts_context *ipts);
  327. +int ipts_control_send(struct ipts_context *ipts,
  328. + u32 cmd, void *data, u32 size);
  329. +int ipts_control_send_feedback(struct ipts_context *ipts,
  330. + u32 buffer, u32 transaction);
  331. +
  332. +#endif /* _IPTS_CONTROL_H_ */
  333. diff --git a/drivers/input/touchscreen/ipts/data.c b/drivers/input/touchscreen/ipts/data.c
  334. new file mode 100644
  335. index 0000000000000..568bf04f7ea6e
  336. --- /dev/null
  337. +++ b/drivers/input/touchscreen/ipts/data.c
  338. @@ -0,0 +1,107 @@
  339. +// SPDX-License-Identifier: GPL-2.0-or-later
  340. +
  341. +#include <linux/delay.h>
  342. +#include <linux/kthread.h>
  343. +#include <linux/ktime.h>
  344. +
  345. +#include "context.h"
  346. +#include "control.h"
  347. +#include "hid.h"
  348. +#include "params.h"
  349. +#include "payload.h"
  350. +#include "protocol/data.h"
  351. +
  352. +static void ipts_data_handle_input(struct ipts_context *ipts, int buffer_id)
  353. +{
  354. + struct ipts_buffer_info buffer;
  355. + struct ipts_data *data;
  356. +
  357. + buffer = ipts->data[buffer_id];
  358. + data = (struct ipts_data *)buffer.address;
  359. +
  360. + if (ipts_params.debug) {
  361. + dev_info(ipts->dev, "Buffer %d\n", buffer_id);
  362. + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 32, 1,
  363. + data->data, data->size, false);
  364. + }
  365. +
  366. + switch (data->type) {
  367. + case IPTS_DATA_TYPE_PAYLOAD:
  368. + ipts_payload_handle_input(ipts, data);
  369. + break;
  370. + case IPTS_DATA_TYPE_HID_REPORT:
  371. + ipts_hid_handle_input(ipts, data);
  372. + break;
  373. + default:
  374. + // ignore
  375. + break;
  376. + }
  377. +
  378. + ipts_control_send_feedback(ipts, buffer_id, data->transaction);
  379. +}
  380. +
  381. +int ipts_data_loop(void *data)
  382. +{
  383. + time64_t timeout;
  384. + u32 doorbell;
  385. + u32 last_doorbell;
  386. + struct ipts_context *ipts;
  387. +
  388. + timeout = ktime_get_seconds() + 5;
  389. + ipts = (struct ipts_context *)data;
  390. + last_doorbell = 0;
  391. + doorbell = 0;
  392. +
  393. + dev_info(ipts->dev, "Starting data loop\n");
  394. +
  395. + while (!kthread_should_stop()) {
  396. + if (ipts->status != IPTS_HOST_STATUS_STARTED) {
  397. + msleep(1000);
  398. + continue;
  399. + }
  400. +
  401. + // IPTS will increment the doorbell after if filled up one of
  402. + // the data buffers. If the doorbell didn't change, there is
  403. + // no work for us to do. Otherwise, the value of the doorbell
  404. + // will stand for the *next* buffer thats going to be filled.
  405. + doorbell = *(u32 *)ipts->doorbell.address;
  406. + if (doorbell == last_doorbell)
  407. + goto sleep;
  408. +
  409. + timeout = ktime_get_seconds() + 5;
  410. +
  411. + while (last_doorbell != doorbell) {
  412. + ipts_data_handle_input(ipts, last_doorbell % 16);
  413. + last_doorbell++;
  414. + }
  415. +sleep:
  416. + if (timeout > ktime_get_seconds())
  417. + usleep_range(5000, 30000);
  418. + else
  419. + msleep(200);
  420. + }
  421. +
  422. + dev_info(ipts->dev, "Stopping data loop\n");
  423. + return 0;
  424. +}
  425. +
  426. +int ipts_data_init(struct ipts_context *ipts)
  427. +{
  428. + int ret;
  429. +
  430. + ret = ipts_payload_init(ipts);
  431. + if (ret)
  432. + return ret;
  433. +
  434. + ret = ipts_hid_init(ipts);
  435. + if (ret)
  436. + return ret;
  437. +
  438. + return 0;
  439. +}
  440. +
  441. +void ipts_data_free(struct ipts_context *ipts)
  442. +{
  443. + ipts_payload_free(ipts);
  444. + ipts_hid_free(ipts);
  445. +}
  446. diff --git a/drivers/input/touchscreen/ipts/data.h b/drivers/input/touchscreen/ipts/data.h
  447. new file mode 100644
  448. index 0000000000000..fa72c1be09451
  449. --- /dev/null
  450. +++ b/drivers/input/touchscreen/ipts/data.h
  451. @@ -0,0 +1,12 @@
  452. +/* SPDX-License-Identifier: GPL-2.0-or-later */
  453. +
  454. +#ifndef _IPTS_DATA_H_
  455. +#define _IPTS_DATA_H_
  456. +
  457. +#include "context.h"
  458. +
  459. +int ipts_data_loop(void *data);
  460. +int ipts_data_init(struct ipts_context *ipts);
  461. +void ipts_data_free(struct ipts_context *ipts);
  462. +
  463. +#endif /* _IPTS_DATA_H_ */
  464. diff --git a/drivers/input/touchscreen/ipts/hid.c b/drivers/input/touchscreen/ipts/hid.c
  465. new file mode 100644
  466. index 0000000000000..2642990b8c420
  467. --- /dev/null
  468. +++ b/drivers/input/touchscreen/ipts/hid.c
  469. @@ -0,0 +1,38 @@
  470. +// SPDX-License-Identifier: GPL-2.0-or-later
  471. +
  472. +#include "context.h"
  473. +#include "protocol/data.h"
  474. +#include "singletouch.h"
  475. +
  476. +/*
  477. + * IPTS on surface gen7 appears to make heavy use of HID reports, unlike
  478. + * previous generations. This file can be used to implement handling for
  479. + * them in the future, seperated from the actual singletouch implementation.
  480. + */
  481. +
  482. +void ipts_hid_handle_input(struct ipts_context *ipts, struct ipts_data *data)
  483. +{
  484. + // Make sure that we only handle singletouch inputs
  485. + // 40 is the report id of the singletouch device in the generic
  486. + // IPTS HID descriptor.
  487. + if (data->data[0] != 0x40)
  488. + return;
  489. +
  490. + ipts_singletouch_handle_input(ipts, data);
  491. +}
  492. +
  493. +int ipts_hid_init(struct ipts_context *ipts)
  494. +{
  495. + int ret;
  496. +
  497. + ret = ipts_singletouch_init(ipts);
  498. + if (ret)
  499. + return ret;
  500. +
  501. + return 0;
  502. +}
  503. +
  504. +void ipts_hid_free(struct ipts_context *ipts)
  505. +{
  506. + ipts_singletouch_free(ipts);
  507. +}
  508. diff --git a/drivers/input/touchscreen/ipts/hid.h b/drivers/input/touchscreen/ipts/hid.h
  509. new file mode 100644
  510. index 0000000000000..e6cf38fce4541
  511. --- /dev/null
  512. +++ b/drivers/input/touchscreen/ipts/hid.h
  513. @@ -0,0 +1,13 @@
  514. +/* SPDX-License-Identifier: GPL-2.0-or-later */
  515. +
  516. +#ifndef _IPTS_HID_H_
  517. +#define _IPTS_HID_H_
  518. +
  519. +#include "context.h"
  520. +#include "protocol/data.h"
  521. +
  522. +int ipts_hid_handle_input(struct ipts_context *ipts, struct ipts_data *data);
  523. +int ipts_hid_init(struct ipts_context *ipts);
  524. +void ipts_hid_free(struct ipts_context *ipts);
  525. +
  526. +#endif /* _IPTS_HID_H_ */
  527. diff --git a/drivers/input/touchscreen/ipts/init.c b/drivers/input/touchscreen/ipts/init.c
  528. new file mode 100644
  529. index 0000000000000..fb70d55542af7
  530. --- /dev/null
  531. +++ b/drivers/input/touchscreen/ipts/init.c
  532. @@ -0,0 +1,93 @@
  533. +// SPDX-License-Identifier: GPL-2.0-or-later
  534. +
  535. +#include <linux/dma-mapping.h>
  536. +#include <linux/mei_cl_bus.h>
  537. +#include <linux/module.h>
  538. +#include <linux/mod_devicetable.h>
  539. +
  540. +#include "context.h"
  541. +#include "control.h"
  542. +#include "data.h"
  543. +#include "receiver.h"
  544. +
  545. +#define IPTS_MEI_UUID UUID_LE(0x3e8d0870, 0x271a, 0x4208, \
  546. + 0x8e, 0xb5, 0x9a, 0xcb, 0x94, 0x02, 0xae, 0x04)
  547. +
  548. +static int ipts_init_probe(struct mei_cl_device *cldev,
  549. + const struct mei_cl_device_id *id)
  550. +{
  551. + int ret;
  552. + struct ipts_context *ipts = NULL;
  553. +
  554. + dev_info(&cldev->dev, "Probing IPTS\n");
  555. +
  556. + // Setup the DMA bit mask
  557. + if (!dma_coerce_mask_and_coherent(&cldev->dev, DMA_BIT_MASK(64))) {
  558. + dev_info(&cldev->dev, "IPTS using DMA_BIT_MASK(64)\n");
  559. + } else if (!dma_coerce_mask_and_coherent(&cldev->dev,
  560. + DMA_BIT_MASK(32))) {
  561. + dev_info(&cldev->dev, "IPTS using DMA_BIT_MASK(32)");
  562. + } else {
  563. + dev_err(&cldev->dev, "No suitable DMA for IPTS available\n");
  564. + return -EFAULT;
  565. + }
  566. +
  567. + ret = mei_cldev_enable(cldev);
  568. + if (ret) {
  569. + dev_err(&cldev->dev, "Cannot enable IPTS\n");
  570. + return ret;
  571. + }
  572. +
  573. + ipts = devm_kzalloc(&cldev->dev,
  574. + sizeof(struct ipts_context), GFP_KERNEL);
  575. + if (!ipts) {
  576. + mei_cldev_disable(cldev);
  577. + return -ENOMEM;
  578. + }
  579. +
  580. + ipts->client_dev = cldev;
  581. + ipts->dev = &cldev->dev;
  582. +
  583. + mei_cldev_set_drvdata(cldev, ipts);
  584. +
  585. + ipts->receiver_loop = kthread_run(ipts_receiver_loop, (void *)ipts,
  586. + "ipts_receiver_loop");
  587. + ipts->data_loop = kthread_run(ipts_data_loop, (void *)ipts,
  588. + "ipts_data_loop");
  589. +
  590. + ipts_control_start(ipts);
  591. +
  592. + return 0;
  593. +}
  594. +
  595. +static int ipts_init_remove(struct mei_cl_device *cldev)
  596. +{
  597. + struct ipts_context *ipts = mei_cldev_get_drvdata(cldev);
  598. +
  599. + dev_info(&cldev->dev, "Removing IPTS\n");
  600. +
  601. + ipts_control_stop(ipts);
  602. + mei_cldev_disable(cldev);
  603. + kthread_stop(ipts->receiver_loop);
  604. + kthread_stop(ipts->data_loop);
  605. +
  606. + return 0;
  607. +}
  608. +
  609. +static struct mei_cl_device_id ipts_device_id[] = {
  610. + { "", IPTS_MEI_UUID, MEI_CL_VERSION_ANY },
  611. + { },
  612. +};
  613. +MODULE_DEVICE_TABLE(mei, ipts_device_id);
  614. +
  615. +static struct mei_cl_driver ipts_driver = {
  616. + .id_table = ipts_device_id,
  617. + .name = "ipts",
  618. + .probe = ipts_init_probe,
  619. + .remove = ipts_init_remove,
  620. +};
  621. +module_mei_cl_driver(ipts_driver);
  622. +
  623. +MODULE_DESCRIPTION("IPTS touchscreen driver");
  624. +MODULE_AUTHOR("Dorian Stoll <dorian.stoll@tmsp.io>");
  625. +MODULE_LICENSE("GPL");
  626. diff --git a/drivers/input/touchscreen/ipts/math.c b/drivers/input/touchscreen/ipts/math.c
  627. new file mode 100644
  628. index 0000000000000..df956e5447e03
  629. --- /dev/null
  630. +++ b/drivers/input/touchscreen/ipts/math.c
  631. @@ -0,0 +1,103 @@
  632. +// SPDX-License-Identifier: GPL-2.0-or-later
  633. +
  634. +#include <linux/bug.h>
  635. +#include <linux/fixp-arith.h>
  636. +#include <linux/kernel.h>
  637. +#include <linux/types.h>
  638. +
  639. +#include "math.h"
  640. +
  641. +/*
  642. + * Since we need to work with [-pi, pi] in the atan functions, we are using
  643. + * 1 << 29 for the fixed point numbers. This allows us to store numbers from
  644. + * [-4, 4] using the full 32-bit signed integer range.
  645. + *
  646. + * Some constants such as PI have been already converted to the fixed-point
  647. + * format and are defined in math.h.
  648. + */
  649. +
  650. +static inline s32 ipts_math_mul(s32 x, s32 y)
  651. +{
  652. + return (x * (s64)y) >> 29;
  653. +}
  654. +
  655. +static inline s32 ipts_math_div(s32 x, s32 y)
  656. +{
  657. + return ((s64)x << 29) / y;
  658. +}
  659. +
  660. +static s32 ipts_math_atan(s32 x)
  661. +{
  662. + s32 tmp = ipts_math_mul(
  663. + ipts_math_mul(x, (abs(x) - (1 << 29))),
  664. + CONST_2447 + ipts_math_mul(CONST_0663, abs(x)));
  665. +
  666. + return ipts_math_mul(M_PI_4, x) - tmp;
  667. +}
  668. +
  669. +static s32 ipts_math_atan2(s32 y, s32 x)
  670. +{
  671. + s32 z;
  672. +
  673. + if (x != 0) {
  674. + if (abs(x) > abs(y)) {
  675. + z = ipts_math_div(y, x);
  676. + if (x > 0)
  677. + return ipts_math_atan(z);
  678. + else if (y >= 0)
  679. + return ipts_math_atan(z) + M_PI;
  680. + else
  681. + return ipts_math_atan(z) - M_PI;
  682. + } else {
  683. + z = ipts_math_div(x, y);
  684. + if (y > 0)
  685. + return -ipts_math_atan(z) + M_PI_2;
  686. + else
  687. + return -ipts_math_atan(z) - M_PI_2;
  688. + }
  689. + } else {
  690. + if (y > 0)
  691. + return M_PI_2;
  692. + else if (y < 0)
  693. + return -M_PI_2;
  694. + }
  695. +
  696. + return 0;
  697. +}
  698. +
  699. +/*
  700. + * Convert altitude in range [0, 9000] and azimuth in range [0, 36000]
  701. + * to x-/y-tilt in range [-9000, 9000]. Azimuth is given
  702. + * counter-clockwise, starting with zero on the right. Altitude is
  703. + * given as angle between stylus and z-axis.
  704. + */
  705. +void ipts_math_altitude_azimuth_to_tilt(s32 alt, s32 azm, s32 *tx, s32 *ty)
  706. +{
  707. + s32 sin_alt, cos_alt;
  708. + s32 sin_azm, cos_azm;
  709. +
  710. + s32 x, y, z;
  711. + s64 atan_x, atan_y;
  712. +
  713. + sin_alt = fixp_sin32_rad(alt, 36000) / 4;
  714. + sin_azm = fixp_sin32_rad(azm, 36000) / 4;
  715. +
  716. + cos_alt = fixp_cos32_rad(alt, 36000) / 4;
  717. + cos_azm = fixp_cos32_rad(azm, 36000) / 4;
  718. +
  719. + x = ipts_math_mul(sin_alt, cos_azm);
  720. + y = ipts_math_mul(sin_alt, sin_azm);
  721. + z = cos_alt;
  722. +
  723. + atan_x = ipts_math_atan2(z, x);
  724. + atan_y = ipts_math_atan2(z, y);
  725. +
  726. + atan_x = atan_x * 4500;
  727. + atan_y = atan_y * 4500;
  728. +
  729. + atan_x = atan_x / M_PI_4;
  730. + atan_y = atan_y / M_PI_4;
  731. +
  732. + *tx = 9000 - atan_x;
  733. + *ty = atan_y - 9000;
  734. +}
  735. diff --git a/drivers/input/touchscreen/ipts/math.h b/drivers/input/touchscreen/ipts/math.h
  736. new file mode 100644
  737. index 0000000000000..8e831074ab60b
  738. --- /dev/null
  739. +++ b/drivers/input/touchscreen/ipts/math.h
  740. @@ -0,0 +1,21 @@
  741. +/* SPDX-License-Identifier: GPL-2.0-or-later */
  742. +
  743. +#ifndef _IPTS_MATH_H_
  744. +#define _IPTS_MATH_H_
  745. +
  746. +#include <linux/types.h>
  747. +
  748. +/* (pi / 4) * (1 << 29) */
  749. +#define M_PI_4 421657428
  750. +#define M_PI_2 (M_PI_4 * 2)
  751. +#define M_PI (M_PI_2 * 2)
  752. +
  753. +/* 0.2447 * (1 << 29) */
  754. +#define CONST_2447 131372312
  755. +
  756. +/* 0.0663 * (1 << 29) */
  757. +#define CONST_0663 35594541
  758. +
  759. +void ipts_math_altitude_azimuth_to_tilt(s32 alt, s32 azm, s32 *tx, s32 *ty);
  760. +
  761. +#endif /* _IPTS_MATH_H_ */
  762. diff --git a/drivers/input/touchscreen/ipts/params.c b/drivers/input/touchscreen/ipts/params.c
  763. new file mode 100644
  764. index 0000000000000..6aa3f5cf1d762
  765. --- /dev/null
  766. +++ b/drivers/input/touchscreen/ipts/params.c
  767. @@ -0,0 +1,27 @@
  768. +// SPDX-License-Identifier: GPL-2.0-or-later
  769. +
  770. +#include <linux/moduleparam.h>
  771. +#include <linux/types.h>
  772. +
  773. +#include "params.h"
  774. +
  775. +#define IPTS_PARM(NAME, TYPE, PERM) \
  776. + module_param_named(NAME, ipts_params.NAME, TYPE, PERM)
  777. +
  778. +#define IPTS_DESC(NAME, DESC) \
  779. + MODULE_PARM_DESC(NAME, DESC)
  780. +
  781. +struct ipts_modparams ipts_params = {
  782. + .debug = false,
  783. + .singletouch = false,
  784. +};
  785. +
  786. +IPTS_PARM(debug, bool, 0400);
  787. +IPTS_DESC(debug,
  788. + "Enable additional debugging in the IPTS driver (default: false)"
  789. +);
  790. +
  791. +IPTS_PARM(singletouch, bool, 0400);
  792. +IPTS_DESC(singletouch,
  793. + "Enables IPTS single touch mode (disables stylus) (default: false)"
  794. +);
  795. diff --git a/drivers/input/touchscreen/ipts/params.h b/drivers/input/touchscreen/ipts/params.h
  796. new file mode 100644
  797. index 0000000000000..1f992a3bc21b9
  798. --- /dev/null
  799. +++ b/drivers/input/touchscreen/ipts/params.h
  800. @@ -0,0 +1,15 @@
  801. +/* SPDX-License-Identifier: GPL-2.0-or-later */
  802. +
  803. +#ifndef _IPTS_PARAMS_H_
  804. +#define _IPTS_PARAMS_H_
  805. +
  806. +#include <linux/types.h>
  807. +
  808. +struct ipts_modparams {
  809. + bool debug;
  810. + bool singletouch;
  811. +};
  812. +
  813. +extern struct ipts_modparams ipts_params;
  814. +
  815. +#endif /* _IPTS_PARAMS_H_ */
  816. diff --git a/drivers/input/touchscreen/ipts/payload.c b/drivers/input/touchscreen/ipts/payload.c
  817. new file mode 100644
  818. index 0000000000000..3572ddc0f2fb0
  819. --- /dev/null
  820. +++ b/drivers/input/touchscreen/ipts/payload.c
  821. @@ -0,0 +1,52 @@
  822. +// SPDX-License-Identifier: GPL-2.0-or-later
  823. +
  824. +#include <linux/types.h>
  825. +
  826. +#include "context.h"
  827. +#include "protocol/data.h"
  828. +#include "protocol/payload.h"
  829. +#include "stylus.h"
  830. +
  831. +void ipts_payload_handle_input(struct ipts_context *ipts,
  832. + struct ipts_data *data)
  833. +{
  834. + u32 i, offset;
  835. + struct ipts_payload *payload;
  836. + struct ipts_payload_frame *frame;
  837. +
  838. + payload = (struct ipts_payload *)data->data;
  839. + offset = 0;
  840. +
  841. + for (i = 0; i < payload->num_frames; i++) {
  842. + frame = (struct ipts_payload_frame *)&payload->data[offset];
  843. + offset += sizeof(struct ipts_payload_frame) + frame->size;
  844. +
  845. + switch (frame->type) {
  846. + case IPTS_PAYLOAD_FRAME_TYPE_STYLUS:
  847. + ipts_stylus_handle_input(ipts, frame);
  848. + break;
  849. + case IPTS_PAYLOAD_FRAME_TYPE_TOUCH:
  850. + // ignored (for the moment)
  851. + break;
  852. + default:
  853. + // ignored
  854. + break;
  855. + }
  856. + }
  857. +}
  858. +
  859. +int ipts_payload_init(struct ipts_context *ipts)
  860. +{
  861. + int ret;
  862. +
  863. + ret = ipts_stylus_init(ipts);
  864. + if (ret)
  865. + return ret;
  866. +
  867. + return 0;
  868. +}
  869. +
  870. +void ipts_payload_free(struct ipts_context *ipts)
  871. +{
  872. + ipts_stylus_free(ipts);
  873. +}
  874. diff --git a/drivers/input/touchscreen/ipts/payload.h b/drivers/input/touchscreen/ipts/payload.h
  875. new file mode 100644
  876. index 0000000000000..6603714bb6fd0
  877. --- /dev/null
  878. +++ b/drivers/input/touchscreen/ipts/payload.h
  879. @@ -0,0 +1,14 @@
  880. +/* SPDX-License-Identifier: GPL-2.0-or-later */
  881. +
  882. +#ifndef _IPTS_PAYLOAD_H_
  883. +#define _IPTS_PAYLOAD_H_
  884. +
  885. +#include "context.h"
  886. +#include "protocol/data.h"
  887. +
  888. +void ipts_payload_handle_input(struct ipts_context *ipts,
  889. + struct ipts_data *data);
  890. +int ipts_payload_init(struct ipts_context *ipts);
  891. +void ipts_payload_free(struct ipts_context *ipts);
  892. +
  893. +#endif /* _IPTS_PAYLOAD_H_ */
  894. diff --git a/drivers/input/touchscreen/ipts/protocol/commands.h b/drivers/input/touchscreen/ipts/protocol/commands.h
  895. new file mode 100644
  896. index 0000000000000..2533dfb13584a
  897. --- /dev/null
  898. +++ b/drivers/input/touchscreen/ipts/protocol/commands.h
  899. @@ -0,0 +1,61 @@
  900. +/* SPDX-License-Identifier: GPL-2.0-or-later */
  901. +
  902. +#ifndef _IPTS_PROTOCOL_COMMANDS_H_
  903. +#define _IPTS_PROTOCOL_COMMANDS_H_
  904. +
  905. +#include <linux/build_bug.h>
  906. +#include <linux/types.h>
  907. +
  908. +enum ipts_sensor_mode {
  909. + IPTS_SENSOR_MODE_SINGLETOUCH = 0,
  910. + IPTS_SENSOR_MODE_MULTITOUCH,
  911. + IPTS_SENSOR_MODE_MAX
  912. +};
  913. +
  914. +struct ipts_set_mode_cmd {
  915. + u32 sensor_mode;
  916. + u8 reserved[12];
  917. +} __packed;
  918. +
  919. +struct ipts_set_mem_window_cmd {
  920. + u32 data_buffer_addr_lower[16];
  921. + u32 data_buffer_addr_upper[16];
  922. + u32 workqueue_addr_lower;
  923. + u32 workqueue_addr_upper;
  924. + u32 doorbell_addr_lower;
  925. + u32 doorbell_addr_upper;
  926. + u32 feedback_buffer_addr_lower[16];
  927. + u32 feedback_buffer_addr_upper[16];
  928. + u32 host2me_addr_lower;
  929. + u32 host2me_addr_upper;
  930. + u32 host2me_size;
  931. + u8 reserved1;
  932. + u8 workqueue_item_size;
  933. + u16 workqueue_size;
  934. + u8 reserved[32];
  935. +} __packed;
  936. +
  937. +struct ipts_feedback_cmd {
  938. + u32 buffer;
  939. + u32 transaction;
  940. + u8 reserved[8];
  941. +} __packed;
  942. +
  943. +/*
  944. + * Commands are sent from the host to the ME
  945. + */
  946. +struct ipts_command {
  947. + u32 code;
  948. + union {
  949. + struct ipts_set_mode_cmd set_mode;
  950. + struct ipts_set_mem_window_cmd set_mem_window;
  951. + struct ipts_feedback_cmd feedback;
  952. + } data;
  953. +} __packed;
  954. +
  955. +static_assert(sizeof(struct ipts_set_mode_cmd) == 16);
  956. +static_assert(sizeof(struct ipts_set_mem_window_cmd) == 320);
  957. +static_assert(sizeof(struct ipts_feedback_cmd) == 16);
  958. +static_assert(sizeof(struct ipts_command) == 324);
  959. +
  960. +#endif /* _IPTS_PROTOCOL_COMMANDS_H_ */
  961. diff --git a/drivers/input/touchscreen/ipts/protocol/data.h b/drivers/input/touchscreen/ipts/protocol/data.h
  962. new file mode 100644
  963. index 0000000000000..148e0545b2e4e
  964. --- /dev/null
  965. +++ b/drivers/input/touchscreen/ipts/protocol/data.h
  966. @@ -0,0 +1,30 @@
  967. +/* SPDX-License-Identifier: GPL-2.0-or-later */
  968. +
  969. +#ifndef _IPTS_PROTOCOL_DATA_H_
  970. +#define _IPTS_PROTOCOL_DATA_H_
  971. +
  972. +#include <linux/build_bug.h>
  973. +#include <linux/types.h>
  974. +
  975. +enum ipts_data_type {
  976. + IPTS_DATA_TYPE_PAYLOAD = 0,
  977. + IPTS_DATA_TYPE_ERROR,
  978. + IPTS_DATA_TYPE_VENDOR_DATA,
  979. + IPTS_DATA_TYPE_HID_REPORT,
  980. + IPTS_DATA_TYPE_GET_FEATURES,
  981. + IPTS_DATA_TYPE_MAX
  982. +};
  983. +
  984. +struct ipts_data {
  985. + u32 type;
  986. + u32 size;
  987. + u32 buffer;
  988. + u8 reserved1[20];
  989. + u8 transaction;
  990. + u8 reserved2[31];
  991. + u8 data[];
  992. +} __packed;
  993. +
  994. +static_assert(sizeof(struct ipts_data) == 64);
  995. +
  996. +#endif /* _IPTS_PROTOCOL_DATA_H_ */
  997. diff --git a/drivers/input/touchscreen/ipts/protocol/events.h b/drivers/input/touchscreen/ipts/protocol/events.h
  998. new file mode 100644
  999. index 0000000000000..f8b771f90bd2b
  1000. --- /dev/null
  1001. +++ b/drivers/input/touchscreen/ipts/protocol/events.h
  1002. @@ -0,0 +1,29 @@
  1003. +/* SPDX-License-Identifier: GPL-2.0-or-later */
  1004. +
  1005. +#ifndef _IPTS_PROTOCOL_EVENTS_H_
  1006. +#define _IPTS_PROTOCOL_EVENTS_H_
  1007. +
  1008. +/*
  1009. + * Helpers to avoid writing boilerplate code.
  1010. + * The response to a command code is always 0x8000000x, where x
  1011. + * is the command code itself. Instead of writing two definitions,
  1012. + * we use macros to calculate the value on the fly instead.
  1013. + */
  1014. +#define IPTS_CMD(COMMAND) IPTS_EVT_##COMMAND
  1015. +#define IPTS_RSP(COMMAND) (IPTS_CMD(COMMAND) + 0x80000000)
  1016. +
  1017. +/*
  1018. + * Events that can be sent to / received from the ME
  1019. + */
  1020. +enum ipts_evt_code {
  1021. + IPTS_EVT_GET_DEVICE_INFO = 1,
  1022. + IPTS_EVT_SET_MODE,
  1023. + IPTS_EVT_SET_MEM_WINDOW,
  1024. + IPTS_EVT_QUIESCE_IO,
  1025. + IPTS_EVT_READY_FOR_DATA,
  1026. + IPTS_EVT_FEEDBACK,
  1027. + IPTS_EVT_CLEAR_MEM_WINDOW,
  1028. + IPTS_EVT_NOTIFY_DEV_READY,
  1029. +};
  1030. +
  1031. +#endif /* _IPTS_PROTOCOL_EVENTS_H_ */
  1032. diff --git a/drivers/input/touchscreen/ipts/protocol/feedback.h b/drivers/input/touchscreen/ipts/protocol/feedback.h
  1033. new file mode 100644
  1034. index 0000000000000..8b3d8b689ee83
  1035. --- /dev/null
  1036. +++ b/drivers/input/touchscreen/ipts/protocol/feedback.h
  1037. @@ -0,0 +1,30 @@
  1038. +/* SPDX-License-Identifier: GPL-2.0-or-later */
  1039. +
  1040. +#ifndef _IPTS_PROTOCOL_FEEDBACK_H_
  1041. +#define _IPTS_PROTOCOL_FEEDBACK_H_
  1042. +
  1043. +#include <linux/build_bug.h>
  1044. +#include <linux/types.h>
  1045. +
  1046. +enum ipts_feedback_type {
  1047. + IPTS_FEEDBACK_TYPE_NONE = 0,
  1048. + IPTS_FEEDBACK_TYPE_SOFT_RESET,
  1049. + IPTS_FEEDBACK_TYPE_GOTO_ARMED,
  1050. + IPTS_FEEDBACK_TYPE_GOTO_SENSING,
  1051. + IPTS_FEEDBACK_TYPE_GOTO_SLEEP,
  1052. + IPTS_FEEDBACK_TYPE_GOTO_DOZE,
  1053. + IPTS_FEEDBACK_TYPE_HARD_RESET,
  1054. + IPTS_FEEDBACK_TYPE_MAX
  1055. +};
  1056. +
  1057. +struct ipts_feedback {
  1058. + u32 type;
  1059. + u32 size;
  1060. + u32 transaction;
  1061. + u8 reserved[52];
  1062. + u8 data[];
  1063. +} __packed;
  1064. +
  1065. +static_assert(sizeof(struct ipts_feedback) == 64);
  1066. +
  1067. +#endif /* _IPTS_PROTOCOL_FEEDBACK_H_ */
  1068. diff --git a/drivers/input/touchscreen/ipts/protocol/payload.h b/drivers/input/touchscreen/ipts/protocol/payload.h
  1069. new file mode 100644
  1070. index 0000000000000..f46da4ea81f25
  1071. --- /dev/null
  1072. +++ b/drivers/input/touchscreen/ipts/protocol/payload.h
  1073. @@ -0,0 +1,47 @@
  1074. +/* SPDX-License-Identifier: GPL-2.0-or-later */
  1075. +
  1076. +#ifndef _IPTS_PROTOCOL_PAYLOAD_H_
  1077. +#define _IPTS_PROTOCOL_PAYLOAD_H_
  1078. +
  1079. +#include <linux/build_bug.h>
  1080. +#include <linux/types.h>
  1081. +
  1082. +enum ipts_payload_frame_type {
  1083. + IPTS_PAYLOAD_FRAME_TYPE_STYLUS = 6,
  1084. + IPTS_PAYLOAD_FRAME_TYPE_TOUCH = 8,
  1085. +};
  1086. +
  1087. +enum ipts_report_type {
  1088. + IPTS_REPORT_TYPE_TOUCH_HEATMAP_DIM = 0x0403,
  1089. + IPTS_REPORT_TYPE_TOUCH_HEATMAP = 0x0425,
  1090. + IPTS_REPORT_TYPE_STYLUS_NO_TILT = 0x0410,
  1091. + IPTS_REPORT_TYPE_STYLUS_TILT = 0x0461,
  1092. + IPTS_REPORT_TYPE_STYLUS_TILT_SERIAL = 0x0460,
  1093. +};
  1094. +
  1095. +struct ipts_payload {
  1096. + u32 counter;
  1097. + u32 num_frames;
  1098. + u8 reserved[4];
  1099. + u8 data[];
  1100. +} __packed;
  1101. +
  1102. +struct ipts_payload_frame {
  1103. + u16 index;
  1104. + u16 type;
  1105. + u32 size;
  1106. + u8 reserved[8];
  1107. + u8 data[];
  1108. +} __packed;
  1109. +
  1110. +struct ipts_report {
  1111. + u16 type;
  1112. + u16 size;
  1113. + u8 data[];
  1114. +} __packed;
  1115. +
  1116. +static_assert(sizeof(struct ipts_payload) == 12);
  1117. +static_assert(sizeof(struct ipts_payload_frame) == 16);
  1118. +static_assert(sizeof(struct ipts_report) == 4);
  1119. +
  1120. +#endif /* _IPTS_PROTOCOL_PAYLOAD_H_ */
  1121. diff --git a/drivers/input/touchscreen/ipts/protocol/responses.h b/drivers/input/touchscreen/ipts/protocol/responses.h
  1122. new file mode 100644
  1123. index 0000000000000..27153d82a5d67
  1124. --- /dev/null
  1125. +++ b/drivers/input/touchscreen/ipts/protocol/responses.h
  1126. @@ -0,0 +1,62 @@
  1127. +/* SPDX-License-Identifier: GPL-2.0-or-later */
  1128. +
  1129. +#ifndef _IPTS_PROTOCOL_RESPONSES_H_
  1130. +#define _IPTS_PROTOCOL_RESPONSES_H_
  1131. +
  1132. +#include <linux/build_bug.h>
  1133. +#include <linux/types.h>
  1134. +
  1135. +enum ipts_me_status {
  1136. + IPTS_ME_STATUS_SUCCESS = 0,
  1137. + IPTS_ME_STATUS_INVALID_PARAMS,
  1138. + IPTS_ME_STATUS_ACCESS_DENIED,
  1139. + IPTS_ME_STATUS_CMD_SIZE_ERROR,
  1140. + IPTS_ME_STATUS_NOT_READY,
  1141. + IPTS_ME_STATUS_REQUEST_OUTSTANDING,
  1142. + IPTS_ME_STATUS_NO_SENSOR_FOUND,
  1143. + IPTS_ME_STATUS_OUT_OF_MEMORY,
  1144. + IPTS_ME_STATUS_INTERNAL_ERROR,
  1145. + IPTS_ME_STATUS_SENSOR_DISABLED,
  1146. + IPTS_ME_STATUS_COMPAT_CHECK_FAIL,
  1147. + IPTS_ME_STATUS_SENSOR_EXPECTED_RESET,
  1148. + IPTS_ME_STATUS_SENSOR_UNEXPECTED_RESET,
  1149. + IPTS_ME_STATUS_RESET_FAILED,
  1150. + IPTS_ME_STATUS_TIMEOUT,
  1151. + IPTS_ME_STATUS_TEST_MODE_FAIL,
  1152. + IPTS_ME_STATUS_SENSOR_FAIL_FATAL,
  1153. + IPTS_ME_STATUS_SENSOR_FAIL_NONFATAL,
  1154. + IPTS_ME_STATUS_INVALID_DEVICE_CAPS,
  1155. + IPTS_ME_STATUS_QUIESCE_IO_IN_PROGRESS,
  1156. + IPTS_ME_STATUS_MAX
  1157. +};
  1158. +
  1159. +struct ipts_device_info {
  1160. + u16 vendor_id;
  1161. + u16 device_id;
  1162. + u32 hw_rev;
  1163. + u32 fw_rev;
  1164. +
  1165. + /* Required size of one touch data buffer */
  1166. + u32 data_size;
  1167. +
  1168. + /* Required size of one feedback buffer */
  1169. + u32 feedback_size;
  1170. + u8 reserved[24];
  1171. +} __packed;
  1172. +
  1173. +/*
  1174. + * Responses are sent from the ME to the host, reacting to a command.
  1175. + */
  1176. +struct ipts_response {
  1177. + u32 code;
  1178. + u32 status;
  1179. + union {
  1180. + struct ipts_device_info device_info;
  1181. + u8 reserved[80];
  1182. + } data;
  1183. +} __packed;
  1184. +
  1185. +static_assert(sizeof(struct ipts_device_info) == 44);
  1186. +static_assert(sizeof(struct ipts_response) == 88);
  1187. +
  1188. +#endif /* _IPTS_PROTOCOL_RESPONSES_H_ */
  1189. diff --git a/drivers/input/touchscreen/ipts/protocol/singletouch.h b/drivers/input/touchscreen/ipts/protocol/singletouch.h
  1190. new file mode 100644
  1191. index 0000000000000..bf9912ee2af4c
  1192. --- /dev/null
  1193. +++ b/drivers/input/touchscreen/ipts/protocol/singletouch.h
  1194. @@ -0,0 +1,17 @@
  1195. +/* SPDX-License-Identifier: GPL-2.0-or-later */
  1196. +
  1197. +#ifndef _IPTS_PROTOCOL_SINGLETOUCH_H_
  1198. +#define _IPTS_PROTOCOL_SINGLETOUCH_H_
  1199. +
  1200. +#include <linux/build_bug.h>
  1201. +#include <linux/types.h>
  1202. +
  1203. +struct ipts_singletouch_report {
  1204. + u8 touch;
  1205. + u16 x;
  1206. + u16 y;
  1207. +} __packed;
  1208. +
  1209. +static_assert(sizeof(struct ipts_singletouch_report) == 5);
  1210. +
  1211. +#endif /* _IPTS_PROTOCOL_SINGLETOUCH_H_ */
  1212. diff --git a/drivers/input/touchscreen/ipts/protocol/stylus.h b/drivers/input/touchscreen/ipts/protocol/stylus.h
  1213. new file mode 100644
  1214. index 0000000000000..950850b365dfb
  1215. --- /dev/null
  1216. +++ b/drivers/input/touchscreen/ipts/protocol/stylus.h
  1217. @@ -0,0 +1,52 @@
  1218. +/* SPDX-License-Identifier: GPL-2.0-or-later */
  1219. +
  1220. +#ifndef _IPTS_PROTOCOL_STYLUS_H_
  1221. +#define _IPTS_PROTOCOL_STYLUS_H_
  1222. +
  1223. +#include <linux/build_bug.h>
  1224. +#include <linux/types.h>
  1225. +
  1226. +struct ipts_stylus_report {
  1227. + u8 reports;
  1228. + u8 reserved[3];
  1229. + u8 data[];
  1230. +} __packed;
  1231. +
  1232. +struct ipts_stylus_report_serial {
  1233. + u8 reports;
  1234. + u8 reserved[3];
  1235. + u32 serial;
  1236. + u8 data[];
  1237. +} __packed;
  1238. +
  1239. +struct ipts_stylus_report_data {
  1240. + u16 timestamp;
  1241. + u16 mode;
  1242. + u16 x;
  1243. + u16 y;
  1244. + u16 pressure;
  1245. + u16 altitude;
  1246. + u16 azimuth;
  1247. + u16 reserved;
  1248. +} __packed;
  1249. +
  1250. +struct ipts_stylus_report_data_no_tilt {
  1251. + u8 reserved[4];
  1252. + u8 mode;
  1253. + u16 x;
  1254. + u16 y;
  1255. + u16 pressure;
  1256. + u8 reserved2;
  1257. +} __packed;
  1258. +
  1259. +#define IPTS_STYLUS_REPORT_MODE_PROX BIT(0)
  1260. +#define IPTS_STYLUS_REPORT_MODE_TOUCH BIT(1)
  1261. +#define IPTS_STYLUS_REPORT_MODE_BUTTON BIT(2)
  1262. +#define IPTS_STYLUS_REPORT_MODE_ERASER BIT(3)
  1263. +
  1264. +static_assert(sizeof(struct ipts_stylus_report) == 4);
  1265. +static_assert(sizeof(struct ipts_stylus_report_serial) == 8);
  1266. +static_assert(sizeof(struct ipts_stylus_report_data) == 16);
  1267. +static_assert(sizeof(struct ipts_stylus_report_data_no_tilt) == 12);
  1268. +
  1269. +#endif /* _IPTS_PAYLOAD_STYLUS_H_ */
  1270. diff --git a/drivers/input/touchscreen/ipts/receiver.c b/drivers/input/touchscreen/ipts/receiver.c
  1271. new file mode 100644
  1272. index 0000000000000..ab283994c3e5f
  1273. --- /dev/null
  1274. +++ b/drivers/input/touchscreen/ipts/receiver.c
  1275. @@ -0,0 +1,265 @@
  1276. +// SPDX-License-Identifier: GPL-2.0-or-later
  1277. +
  1278. +#include <linux/types.h>
  1279. +
  1280. +#include "context.h"
  1281. +#include "control.h"
  1282. +#include "data.h"
  1283. +#include "protocol/commands.h"
  1284. +#include "protocol/events.h"
  1285. +#include "protocol/responses.h"
  1286. +#include "resources.h"
  1287. +
  1288. +static void ipts_receiver_handle_notify_dev_ready(struct ipts_context *ipts,
  1289. + struct ipts_response *msg, int *cmd_status)
  1290. +{
  1291. + if (msg->status != IPTS_ME_STATUS_SENSOR_FAIL_NONFATAL &&
  1292. + msg->status != IPTS_ME_STATUS_SUCCESS) {
  1293. + dev_err(ipts->dev, "0x%08x failed - status = %d\n",
  1294. + msg->code, msg->status);
  1295. + return;
  1296. + }
  1297. +
  1298. + *cmd_status = ipts_control_send(ipts,
  1299. + IPTS_CMD(GET_DEVICE_INFO), NULL, 0);
  1300. +}
  1301. +
  1302. +static void ipts_receiver_handle_get_device_info(struct ipts_context *ipts,
  1303. + struct ipts_response *msg, int *cmd_status)
  1304. +{
  1305. + if (msg->status != IPTS_ME_STATUS_COMPAT_CHECK_FAIL &&
  1306. + msg->status != IPTS_ME_STATUS_SUCCESS) {
  1307. + dev_err(ipts->dev, "0x%08x failed - status = %d\n",
  1308. + msg->code, msg->status);
  1309. + return;
  1310. + }
  1311. +
  1312. + memcpy(&ipts->device_info, &msg->data.device_info,
  1313. + sizeof(struct ipts_device_info));
  1314. +
  1315. + dev_info(ipts->dev, "Device %04hX:%04hX found\n",
  1316. + ipts->device_info.vendor_id,
  1317. + ipts->device_info.device_id);
  1318. +
  1319. + if (ipts_data_init(ipts))
  1320. + return;
  1321. +
  1322. + *cmd_status = ipts_control_send(ipts,
  1323. + IPTS_CMD(CLEAR_MEM_WINDOW), NULL, 0);
  1324. +}
  1325. +
  1326. +static void ipts_receiver_handle_clear_mem_window(struct ipts_context *ipts,
  1327. + struct ipts_response *msg, int *cmd_status, int *ret)
  1328. +{
  1329. + struct ipts_set_mode_cmd sensor_mode_cmd;
  1330. +
  1331. + if (msg->status != IPTS_ME_STATUS_TIMEOUT &&
  1332. + msg->status != IPTS_ME_STATUS_SUCCESS) {
  1333. + dev_err(ipts->dev, "0x%08x failed - status = %d\n",
  1334. + msg->code, msg->status);
  1335. + return;
  1336. + }
  1337. +
  1338. + if (ipts->status == IPTS_HOST_STATUS_STOPPING)
  1339. + return;
  1340. +
  1341. + if (ipts_resources_init(ipts))
  1342. + return;
  1343. +
  1344. + ipts->status = IPTS_HOST_STATUS_RESOURCE_READY;
  1345. +
  1346. + memset(&sensor_mode_cmd, 0, sizeof(struct ipts_set_mode_cmd));
  1347. + sensor_mode_cmd.sensor_mode = ipts->mode;
  1348. +
  1349. + *cmd_status = ipts_control_send(ipts, IPTS_CMD(SET_MODE),
  1350. + &sensor_mode_cmd, sizeof(struct ipts_set_mode_cmd));
  1351. +}
  1352. +
  1353. +static void ipts_receiver_handle_set_mode(struct ipts_context *ipts,
  1354. + struct ipts_response *msg, int *cmd_status)
  1355. +{
  1356. + int i;
  1357. + struct ipts_set_mem_window_cmd cmd;
  1358. +
  1359. + if (msg->status != IPTS_ME_STATUS_SUCCESS) {
  1360. + dev_err(ipts->dev, "0x%08x failed - status = %d\n",
  1361. + msg->code, msg->status);
  1362. + return;
  1363. + }
  1364. +
  1365. + memset(&cmd, 0, sizeof(struct ipts_set_mem_window_cmd));
  1366. +
  1367. + for (i = 0; i < 16; i++) {
  1368. + cmd.data_buffer_addr_lower[i] =
  1369. + lower_32_bits(ipts->data[i].dma_address);
  1370. +
  1371. + cmd.data_buffer_addr_upper[i] =
  1372. + upper_32_bits(ipts->data[i].dma_address);
  1373. +
  1374. + cmd.feedback_buffer_addr_lower[i] =
  1375. + lower_32_bits(ipts->feedback[i].dma_address);
  1376. +
  1377. + cmd.feedback_buffer_addr_upper[i] =
  1378. + upper_32_bits(ipts->feedback[i].dma_address);
  1379. + }
  1380. +
  1381. + cmd.workqueue_addr_lower = lower_32_bits(ipts->workqueue.dma_address);
  1382. + cmd.workqueue_addr_upper = upper_32_bits(ipts->workqueue.dma_address);
  1383. +
  1384. + cmd.doorbell_addr_lower = lower_32_bits(ipts->doorbell.dma_address);
  1385. + cmd.doorbell_addr_upper = upper_32_bits(ipts->doorbell.dma_address);
  1386. +
  1387. + cmd.host2me_addr_lower = lower_32_bits(ipts->host2me.dma_address);
  1388. + cmd.host2me_addr_upper = upper_32_bits(ipts->host2me.dma_address);
  1389. + cmd.host2me_size = ipts->device_info.data_size;
  1390. +
  1391. + cmd.workqueue_size = 8192;
  1392. + cmd.workqueue_item_size = 16;
  1393. +
  1394. + *cmd_status = ipts_control_send(ipts, IPTS_CMD(SET_MEM_WINDOW),
  1395. + &cmd, sizeof(struct ipts_set_mem_window_cmd));
  1396. +}
  1397. +
  1398. +static void ipts_receiver_handle_set_mem_window(struct ipts_context *ipts,
  1399. + struct ipts_response *msg, int *cmd_status)
  1400. +{
  1401. + if (msg->status != IPTS_ME_STATUS_SUCCESS) {
  1402. + dev_err(ipts->dev, "0x%08x failed - status = %d\n",
  1403. + msg->code, msg->status);
  1404. + return;
  1405. + }
  1406. +
  1407. + *cmd_status = ipts_control_send(ipts,
  1408. + IPTS_CMD(READY_FOR_DATA), NULL, 0);
  1409. + if (*cmd_status)
  1410. + return;
  1411. +
  1412. + ipts->status = IPTS_HOST_STATUS_STARTED;
  1413. + dev_info(ipts->dev, "IPTS enabled\n");
  1414. +}
  1415. +
  1416. +static void ipts_receiver_handle_ready_for_data(struct ipts_context *ipts,
  1417. + struct ipts_response *msg)
  1418. +{
  1419. + if (msg->status != IPTS_ME_STATUS_SENSOR_DISABLED &&
  1420. + msg->status != IPTS_ME_STATUS_SUCCESS) {
  1421. + dev_err(ipts->dev, "0x%08x failed - status = %d\n",
  1422. + msg->code, msg->status);
  1423. + return;
  1424. + }
  1425. +
  1426. + if (ipts->mode != IPTS_SENSOR_MODE_SINGLETOUCH ||
  1427. + ipts->status != IPTS_HOST_STATUS_STARTED)
  1428. + return;
  1429. +
  1430. + // Increment the doorbell manually to indicate that a new buffer
  1431. + // filled with touch data is available
  1432. + *((u32 *)ipts->doorbell.address) += 1;
  1433. +}
  1434. +
  1435. +static void ipts_recever_handle_feedback(struct ipts_context *ipts,
  1436. + struct ipts_response *msg, int *cmd_status)
  1437. +{
  1438. + if (msg->status != IPTS_ME_STATUS_COMPAT_CHECK_FAIL &&
  1439. + msg->status != IPTS_ME_STATUS_SUCCESS &&
  1440. + msg->status != IPTS_ME_STATUS_INVALID_PARAMS) {
  1441. + dev_err(ipts->dev, "0x%08x failed - status = %d\n",
  1442. + msg->code, msg->status);
  1443. + return;
  1444. + }
  1445. +
  1446. + if (ipts->mode != IPTS_SENSOR_MODE_SINGLETOUCH)
  1447. + return;
  1448. +
  1449. + *cmd_status = ipts_control_send(ipts,
  1450. + IPTS_CMD(READY_FOR_DATA), NULL, 0);
  1451. +}
  1452. +
  1453. +static void ipts_receiver_handle_quiesce_io(struct ipts_context *ipts,
  1454. + struct ipts_response *msg)
  1455. +{
  1456. + if (msg->status != IPTS_ME_STATUS_SUCCESS) {
  1457. + dev_err(ipts->dev, "0x%08x failed - status = %d\n",
  1458. + msg->code, msg->status);
  1459. + return;
  1460. + }
  1461. +
  1462. + if (ipts->status == IPTS_HOST_STATUS_RESTARTING)
  1463. + ipts_control_start(ipts);
  1464. +}
  1465. +
  1466. +
  1467. +static int ipts_receiver_handle_response(struct ipts_context *ipts,
  1468. + struct ipts_response *msg, u32 msg_len)
  1469. +{
  1470. + int cmd_status = 0;
  1471. + int ret = 0;
  1472. +
  1473. + switch (msg->code) {
  1474. + case IPTS_RSP(NOTIFY_DEV_READY):
  1475. + ipts_receiver_handle_notify_dev_ready(ipts, msg, &cmd_status);
  1476. + break;
  1477. + case IPTS_RSP(GET_DEVICE_INFO):
  1478. + ipts_receiver_handle_get_device_info(ipts, msg, &cmd_status);
  1479. + break;
  1480. + case IPTS_RSP(CLEAR_MEM_WINDOW):
  1481. + ipts_receiver_handle_clear_mem_window(ipts, msg,
  1482. + &cmd_status, &ret);
  1483. + break;
  1484. + case IPTS_RSP(SET_MODE):
  1485. + ipts_receiver_handle_set_mode(ipts, msg, &cmd_status);
  1486. + break;
  1487. + case IPTS_RSP(SET_MEM_WINDOW):
  1488. + ipts_receiver_handle_set_mem_window(ipts, msg, &cmd_status);
  1489. + break;
  1490. + case IPTS_RSP(READY_FOR_DATA):
  1491. + ipts_receiver_handle_ready_for_data(ipts, msg);
  1492. + break;
  1493. + case IPTS_RSP(FEEDBACK):
  1494. + ipts_recever_handle_feedback(ipts, msg, &cmd_status);
  1495. + break;
  1496. + case IPTS_RSP(QUIESCE_IO):
  1497. + ipts_receiver_handle_quiesce_io(ipts, msg);
  1498. + break;
  1499. + }
  1500. +
  1501. + if (ipts->status == IPTS_HOST_STATUS_STOPPING)
  1502. + return 0;
  1503. +
  1504. + if (msg->status == IPTS_ME_STATUS_SENSOR_UNEXPECTED_RESET ||
  1505. + msg->status == IPTS_ME_STATUS_SENSOR_EXPECTED_RESET) {
  1506. + dev_info(ipts->dev, "Sensor has been reset: %d\n", msg->status);
  1507. + ipts_control_restart(ipts);
  1508. + }
  1509. +
  1510. + if (cmd_status)
  1511. + ipts_control_restart(ipts);
  1512. +
  1513. + return ret;
  1514. +}
  1515. +
  1516. +int ipts_receiver_loop(void *data)
  1517. +{
  1518. + u32 msg_len;
  1519. + struct ipts_context *ipts;
  1520. + struct ipts_response msg;
  1521. +
  1522. + ipts = (struct ipts_context *)data;
  1523. + dev_info(ipts->dev, "Starting receive loop\n");
  1524. +
  1525. + while (!kthread_should_stop()) {
  1526. + msg_len = mei_cldev_recv(ipts->client_dev,
  1527. + (u8 *)&msg, sizeof(msg));
  1528. +
  1529. + if (msg_len <= 0) {
  1530. + dev_err(ipts->dev, "Error in reading ME message\n");
  1531. + continue;
  1532. + }
  1533. +
  1534. + if (ipts_receiver_handle_response(ipts, &msg, msg_len))
  1535. + dev_err(ipts->dev, "Error in handling ME message\n");
  1536. + }
  1537. +
  1538. + dev_info(ipts->dev, "Stopping receive loop\n");
  1539. + return 0;
  1540. +}
  1541. diff --git a/drivers/input/touchscreen/ipts/receiver.h b/drivers/input/touchscreen/ipts/receiver.h
  1542. new file mode 100644
  1543. index 0000000000000..4d413a0abd4c5
  1544. --- /dev/null
  1545. +++ b/drivers/input/touchscreen/ipts/receiver.h
  1546. @@ -0,0 +1,8 @@
  1547. +/* SPDX-License-Identifier: GPL-2.0-or-later */
  1548. +
  1549. +#ifndef _IPTS_RECEIVER_H_
  1550. +#define _IPTS_RECEIVER_H_
  1551. +
  1552. +int ipts_receiver_loop(void *data);
  1553. +
  1554. +#endif /* _IPTS_RECEIVER_H_ */
  1555. diff --git a/drivers/input/touchscreen/ipts/resources.c b/drivers/input/touchscreen/ipts/resources.c
  1556. new file mode 100644
  1557. index 0000000000000..704db9fdd3fd4
  1558. --- /dev/null
  1559. +++ b/drivers/input/touchscreen/ipts/resources.c
  1560. @@ -0,0 +1,131 @@
  1561. +// SPDX-License-Identifier: GPL-2.0-or-later
  1562. +
  1563. +#include <linux/dma-mapping.h>
  1564. +
  1565. +#include "context.h"
  1566. +
  1567. +void ipts_resources_free(struct ipts_context *ipts)
  1568. +{
  1569. + int i;
  1570. + u32 touch_buffer_size;
  1571. + u32 feedback_buffer_size;
  1572. + struct ipts_buffer_info *buffers;
  1573. +
  1574. + touch_buffer_size = ipts->device_info.data_size;
  1575. + feedback_buffer_size = ipts->device_info.feedback_size;
  1576. +
  1577. + buffers = ipts->data;
  1578. + for (i = 0; i < 16; i++) {
  1579. + if (!buffers[i].address)
  1580. + continue;
  1581. +
  1582. + dmam_free_coherent(ipts->dev, touch_buffer_size,
  1583. + buffers[i].address, buffers[i].dma_address);
  1584. +
  1585. + buffers[i].address = 0;
  1586. + buffers[i].dma_address = 0;
  1587. + }
  1588. +
  1589. + buffers = ipts->feedback;
  1590. + for (i = 0; i < 16; i++) {
  1591. + if (!buffers[i].address)
  1592. + continue;
  1593. +
  1594. + dmam_free_coherent(ipts->dev, feedback_buffer_size,
  1595. + buffers[i].address, buffers[i].dma_address);
  1596. +
  1597. + buffers[i].address = 0;
  1598. + buffers[i].dma_address = 0;
  1599. + }
  1600. +
  1601. + if (ipts->doorbell.address) {
  1602. + dmam_free_coherent(ipts->dev, sizeof(u32),
  1603. + ipts->doorbell.address,
  1604. + ipts->doorbell.dma_address);
  1605. +
  1606. + ipts->doorbell.address = 0;
  1607. + ipts->doorbell.dma_address = 0;
  1608. + }
  1609. +
  1610. + if (ipts->workqueue.address) {
  1611. + dmam_free_coherent(ipts->dev, sizeof(u32),
  1612. + ipts->workqueue.address,
  1613. + ipts->workqueue.dma_address);
  1614. +
  1615. + ipts->workqueue.address = 0;
  1616. + ipts->workqueue.dma_address = 0;
  1617. + }
  1618. +
  1619. + if (ipts->host2me.address) {
  1620. + dmam_free_coherent(ipts->dev, touch_buffer_size,
  1621. + ipts->host2me.address,
  1622. + ipts->host2me.dma_address);
  1623. +
  1624. + ipts->host2me.address = 0;
  1625. + ipts->host2me.dma_address = 0;
  1626. + }
  1627. +}
  1628. +
  1629. +int ipts_resources_init(struct ipts_context *ipts)
  1630. +{
  1631. + int i;
  1632. + u32 touch_buffer_size;
  1633. + u32 feedback_buffer_size;
  1634. + struct ipts_buffer_info *buffers;
  1635. +
  1636. + touch_buffer_size = ipts->device_info.data_size;
  1637. + feedback_buffer_size = ipts->device_info.feedback_size;
  1638. +
  1639. + buffers = ipts->data;
  1640. + for (i = 0; i < 16; i++) {
  1641. + buffers[i].address = dmam_alloc_coherent(ipts->dev,
  1642. + touch_buffer_size,
  1643. + &buffers[i].dma_address,
  1644. + GFP_ATOMIC | __GFP_ZERO);
  1645. +
  1646. + if (!buffers[i].address)
  1647. + goto release_resources;
  1648. + }
  1649. +
  1650. + buffers = ipts->feedback;
  1651. + for (i = 0; i < 16; i++) {
  1652. + buffers[i].address = dmam_alloc_coherent(ipts->dev,
  1653. + feedback_buffer_size,
  1654. + &buffers[i].dma_address,
  1655. + GFP_ATOMIC | __GFP_ZERO);
  1656. +
  1657. + if (!buffers[i].address)
  1658. + goto release_resources;
  1659. + }
  1660. +
  1661. + ipts->doorbell.address = dmam_alloc_coherent(ipts->dev,
  1662. + sizeof(u32),
  1663. + &ipts->doorbell.dma_address,
  1664. + GFP_ATOMIC | __GFP_ZERO);
  1665. +
  1666. + if (!ipts->doorbell.address)
  1667. + goto release_resources;
  1668. +
  1669. + ipts->workqueue.address = dmam_alloc_coherent(ipts->dev,
  1670. + sizeof(u32),
  1671. + &ipts->workqueue.dma_address,
  1672. + GFP_ATOMIC | __GFP_ZERO);
  1673. +
  1674. + if (!ipts->workqueue.address)
  1675. + goto release_resources;
  1676. +
  1677. + ipts->host2me.address = dmam_alloc_coherent(ipts->dev,
  1678. + touch_buffer_size,
  1679. + &ipts->host2me.dma_address,
  1680. + GFP_ATOMIC | __GFP_ZERO);
  1681. +
  1682. + if (!ipts->workqueue.address)
  1683. + goto release_resources;
  1684. +
  1685. + return 0;
  1686. +
  1687. +release_resources:
  1688. +
  1689. + ipts_resources_free(ipts);
  1690. + return -ENOMEM;
  1691. +}
  1692. diff --git a/drivers/input/touchscreen/ipts/resources.h b/drivers/input/touchscreen/ipts/resources.h
  1693. new file mode 100644
  1694. index 0000000000000..cf9807b0dbe62
  1695. --- /dev/null
  1696. +++ b/drivers/input/touchscreen/ipts/resources.h
  1697. @@ -0,0 +1,11 @@
  1698. +/* SPDX-License-Identifier: GPL-2.0-or-later */
  1699. +
  1700. +#ifndef _IPTS_RESOURCES_H_
  1701. +#define _IPTS_RESOURCES_H_
  1702. +
  1703. +#include "context.h"
  1704. +
  1705. +int ipts_resources_init(struct ipts_context *ipts);
  1706. +void ipts_resources_free(struct ipts_context *ipts);
  1707. +
  1708. +#endif /* _IPTS_RESOURCES_H_ */
  1709. diff --git a/drivers/input/touchscreen/ipts/singletouch.c b/drivers/input/touchscreen/ipts/singletouch.c
  1710. new file mode 100644
  1711. index 0000000000000..ed70444f649c4
  1712. --- /dev/null
  1713. +++ b/drivers/input/touchscreen/ipts/singletouch.c
  1714. @@ -0,0 +1,64 @@
  1715. +// SPDX-License-Identifier: GPL-2.0-or-later
  1716. +
  1717. +#include <linux/input.h>
  1718. +#include <linux/kernel.h>
  1719. +
  1720. +#include "context.h"
  1721. +#include "protocol/data.h"
  1722. +#include "protocol/singletouch.h"
  1723. +
  1724. +void ipts_singletouch_handle_input(struct ipts_context *ipts,
  1725. + struct ipts_data *data)
  1726. +{
  1727. + struct ipts_singletouch_report *report =
  1728. + (struct ipts_singletouch_report *)&data->data[1];
  1729. +
  1730. + input_report_key(ipts->singletouch, BTN_TOUCH, report->touch);
  1731. + input_report_abs(ipts->singletouch, ABS_X, report->x);
  1732. + input_report_abs(ipts->singletouch, ABS_Y, report->y);
  1733. +
  1734. + input_sync(ipts->singletouch);
  1735. +}
  1736. +
  1737. +int ipts_singletouch_init(struct ipts_context *ipts)
  1738. +{
  1739. + int ret;
  1740. +
  1741. + ipts->singletouch = input_allocate_device();
  1742. + if (!ipts->singletouch)
  1743. + return -ENOMEM;
  1744. +
  1745. + __set_bit(INPUT_PROP_DIRECT, ipts->singletouch->propbit);
  1746. +
  1747. + input_set_capability(ipts->singletouch, EV_KEY, BTN_TOUCH);
  1748. + input_set_abs_params(ipts->singletouch, ABS_X, 0, 32767, 0, 0);
  1749. + input_abs_set_res(ipts->singletouch, ABS_X, 112);
  1750. + input_set_abs_params(ipts->singletouch, ABS_Y, 0, 32767, 0, 0);
  1751. + input_abs_set_res(ipts->singletouch, ABS_Y, 199);
  1752. +
  1753. + ipts->singletouch->id.bustype = BUS_MEI;
  1754. + ipts->singletouch->id.vendor = ipts->device_info.vendor_id;
  1755. + ipts->singletouch->id.product = ipts->device_info.device_id;
  1756. + ipts->singletouch->id.version = ipts->device_info.fw_rev;
  1757. +
  1758. + ipts->singletouch->phys = "heci3";
  1759. + ipts->singletouch->name = "IPTS Singletouch";
  1760. +
  1761. + ret = input_register_device(ipts->singletouch);
  1762. + if (ret) {
  1763. + dev_err(ipts->dev, "Cannot register input device: %s (%d)\n",
  1764. + ipts->singletouch->name, ret);
  1765. + input_free_device(ipts->singletouch);
  1766. + return ret;
  1767. + }
  1768. +
  1769. + return 0;
  1770. +}
  1771. +
  1772. +void ipts_singletouch_free(struct ipts_context *ipts)
  1773. +{
  1774. + if (!ipts->singletouch)
  1775. + return;
  1776. +
  1777. + input_unregister_device(ipts->singletouch);
  1778. +}
  1779. diff --git a/drivers/input/touchscreen/ipts/singletouch.h b/drivers/input/touchscreen/ipts/singletouch.h
  1780. new file mode 100644
  1781. index 0000000000000..53207497a4628
  1782. --- /dev/null
  1783. +++ b/drivers/input/touchscreen/ipts/singletouch.h
  1784. @@ -0,0 +1,14 @@
  1785. +/* SPDX-License-Identifier: GPL-2.0-or-later */
  1786. +
  1787. +#ifndef _IPTS_SINGLETOUCH_H_
  1788. +#define _IPTS_SINGLETOUCH_H_
  1789. +
  1790. +#include "context.h"
  1791. +#include "protocol/data.h"
  1792. +
  1793. +void ipts_singletouch_handle_input(struct ipts_context *ipts,
  1794. + struct ipts_data *data);
  1795. +int ipts_singletouch_init(struct ipts_context *ipts);
  1796. +void ipts_singletouch_free(struct ipts_context *ipts);
  1797. +
  1798. +#endif /* _IPTS_SINGLETOUCH_H_ */
  1799. diff --git a/drivers/input/touchscreen/ipts/stylus.c b/drivers/input/touchscreen/ipts/stylus.c
  1800. new file mode 100644
  1801. index 0000000000000..987fa756fec33
  1802. --- /dev/null
  1803. +++ b/drivers/input/touchscreen/ipts/stylus.c
  1804. @@ -0,0 +1,179 @@
  1805. +// SPDX-License-Identifier: GPL-2.0-or-later
  1806. +
  1807. +#include <linux/input.h>
  1808. +#include <linux/kernel.h>
  1809. +
  1810. +#include "context.h"
  1811. +#include "math.h"
  1812. +#include "protocol/payload.h"
  1813. +#include "protocol/stylus.h"
  1814. +
  1815. +static void ipts_stylus_handle_stylus_data(struct ipts_context *ipts,
  1816. + struct ipts_stylus_report_data *data)
  1817. +{
  1818. + u8 prox = data->mode & IPTS_STYLUS_REPORT_MODE_PROX;
  1819. + u8 touch = data->mode & IPTS_STYLUS_REPORT_MODE_TOUCH;
  1820. + u8 button = data->mode & IPTS_STYLUS_REPORT_MODE_BUTTON;
  1821. + u8 rubber = data->mode & IPTS_STYLUS_REPORT_MODE_ERASER;
  1822. +
  1823. + s32 tx = 0;
  1824. + s32 ty = 0;
  1825. +
  1826. + // avoid unnecessary computations
  1827. + // altitude is zero if stylus does not touch the screen
  1828. + if (data->altitude) {
  1829. + ipts_math_altitude_azimuth_to_tilt(data->altitude,
  1830. + data->azimuth, &tx, &ty);
  1831. + }
  1832. +
  1833. + input_report_key(ipts->stylus, BTN_TOUCH, touch);
  1834. + input_report_key(ipts->stylus, BTN_TOOL_PEN, prox && !rubber);
  1835. + input_report_key(ipts->stylus, BTN_TOOL_RUBBER, prox && rubber);
  1836. + input_report_key(ipts->stylus, BTN_STYLUS, button);
  1837. +
  1838. + input_report_abs(ipts->stylus, ABS_X, data->x);
  1839. + input_report_abs(ipts->stylus, ABS_Y, data->y);
  1840. + input_report_abs(ipts->stylus, ABS_PRESSURE, data->pressure);
  1841. + input_report_abs(ipts->stylus, ABS_MISC, data->timestamp);
  1842. +
  1843. + input_report_abs(ipts->stylus, ABS_TILT_X, tx);
  1844. + input_report_abs(ipts->stylus, ABS_TILT_Y, ty);
  1845. +
  1846. + input_sync(ipts->stylus);
  1847. +}
  1848. +
  1849. +static void ipts_stylus_handle_report_tilt_serial(struct ipts_context *ipts,
  1850. + struct ipts_report *report)
  1851. +{
  1852. + int i;
  1853. + struct ipts_stylus_report_serial *stylus_report;
  1854. + struct ipts_stylus_report_data *data;
  1855. +
  1856. + stylus_report = (struct ipts_stylus_report_serial *)report->data;
  1857. + data = (struct ipts_stylus_report_data *)stylus_report->data;
  1858. +
  1859. + // TODO: Track serial number and support multiple styli
  1860. +
  1861. + for (i = 0; i < stylus_report->reports; i++)
  1862. + ipts_stylus_handle_stylus_data(ipts, &data[i]);
  1863. +}
  1864. +
  1865. +static void ipts_stylus_handle_report_tilt(struct ipts_context *ipts,
  1866. + struct ipts_report *report)
  1867. +{
  1868. + int i;
  1869. + struct ipts_stylus_report *stylus_report;
  1870. + struct ipts_stylus_report_data *data;
  1871. +
  1872. + stylus_report = (struct ipts_stylus_report *)report->data;
  1873. + data = (struct ipts_stylus_report_data *)stylus_report->data;
  1874. +
  1875. + for (i = 0; i < stylus_report->reports; i++)
  1876. + ipts_stylus_handle_stylus_data(ipts, &data[i]);
  1877. +}
  1878. +
  1879. +static void ipts_stylus_handle_report_no_tilt(struct ipts_context *ipts,
  1880. + struct ipts_report *report)
  1881. +{
  1882. + int i;
  1883. + struct ipts_stylus_report_serial *stylus_report;
  1884. + struct ipts_stylus_report_data_no_tilt *data;
  1885. + struct ipts_stylus_report_data new_data;
  1886. +
  1887. + stylus_report = (struct ipts_stylus_report_serial *)report->data;
  1888. + data = (struct ipts_stylus_report_data_no_tilt *)stylus_report->data;
  1889. +
  1890. + for (i = 0; i < stylus_report->reports; i++) {
  1891. + new_data.mode = data[i].mode;
  1892. + new_data.x = data[i].x;
  1893. + new_data.y = data[i].y;
  1894. + new_data.pressure = data[i].pressure * 4;
  1895. + new_data.altitude = 0;
  1896. + new_data.azimuth = 0;
  1897. + new_data.timestamp = 0;
  1898. +
  1899. + ipts_stylus_handle_stylus_data(ipts, &new_data);
  1900. + }
  1901. +}
  1902. +
  1903. +void ipts_stylus_handle_input(struct ipts_context *ipts,
  1904. + struct ipts_payload_frame *frame)
  1905. +{
  1906. + int size;
  1907. + struct ipts_report *report;
  1908. +
  1909. + size = 0;
  1910. +
  1911. + while (size < frame->size) {
  1912. + report = (struct ipts_report *)&frame->data[size];
  1913. + size += sizeof(struct ipts_report) + report->size;
  1914. +
  1915. + switch (report->type) {
  1916. + case IPTS_REPORT_TYPE_STYLUS_NO_TILT:
  1917. + ipts_stylus_handle_report_no_tilt(ipts, report);
  1918. + break;
  1919. + case IPTS_REPORT_TYPE_STYLUS_TILT:
  1920. + ipts_stylus_handle_report_tilt(ipts, report);
  1921. + break;
  1922. + case IPTS_REPORT_TYPE_STYLUS_TILT_SERIAL:
  1923. + ipts_stylus_handle_report_tilt_serial(ipts, report);
  1924. + break;
  1925. + default:
  1926. + // ignored
  1927. + break;
  1928. + }
  1929. + }
  1930. +}
  1931. +
  1932. +int ipts_stylus_init(struct ipts_context *ipts)
  1933. +{
  1934. + int ret;
  1935. +
  1936. + ipts->stylus = input_allocate_device();
  1937. + if (!ipts->stylus)
  1938. + return -ENOMEM;
  1939. +
  1940. + __set_bit(INPUT_PROP_DIRECT, ipts->stylus->propbit);
  1941. + __set_bit(INPUT_PROP_POINTER, ipts->stylus->propbit);
  1942. +
  1943. + input_set_abs_params(ipts->stylus, ABS_X, 0, 9600, 0, 0);
  1944. + input_abs_set_res(ipts->stylus, ABS_X, 34);
  1945. + input_set_abs_params(ipts->stylus, ABS_Y, 0, 7200, 0, 0);
  1946. + input_abs_set_res(ipts->stylus, ABS_Y, 38);
  1947. + input_set_abs_params(ipts->stylus, ABS_PRESSURE, 0, 4096, 0, 0);
  1948. + input_set_abs_params(ipts->stylus, ABS_TILT_X, -9000, 9000, 0, 0);
  1949. + input_abs_set_res(ipts->stylus, ABS_TILT_X, 5730);
  1950. + input_set_abs_params(ipts->stylus, ABS_TILT_Y, -9000, 9000, 0, 0);
  1951. + input_abs_set_res(ipts->stylus, ABS_TILT_Y, 5730);
  1952. + input_set_abs_params(ipts->stylus, ABS_MISC, 0, 65535, 0, 0);
  1953. + input_set_capability(ipts->stylus, EV_KEY, BTN_TOUCH);
  1954. + input_set_capability(ipts->stylus, EV_KEY, BTN_STYLUS);
  1955. + input_set_capability(ipts->stylus, EV_KEY, BTN_TOOL_PEN);
  1956. + input_set_capability(ipts->stylus, EV_KEY, BTN_TOOL_RUBBER);
  1957. +
  1958. + ipts->stylus->id.bustype = BUS_MEI;
  1959. + ipts->stylus->id.vendor = ipts->device_info.vendor_id;
  1960. + ipts->stylus->id.product = ipts->device_info.device_id;
  1961. + ipts->stylus->id.version = ipts->device_info.fw_rev;
  1962. +
  1963. + ipts->stylus->phys = "heci3";
  1964. + ipts->stylus->name = "IPTS Stylus";
  1965. +
  1966. + ret = input_register_device(ipts->stylus);
  1967. + if (ret) {
  1968. + dev_err(ipts->dev, "Cannot register input device: %s (%d)\n",
  1969. + ipts->stylus->name, ret);
  1970. + input_free_device(ipts->stylus);
  1971. + return ret;
  1972. + }
  1973. +
  1974. + return 0;
  1975. +}
  1976. +
  1977. +void ipts_stylus_free(struct ipts_context *ipts)
  1978. +{
  1979. + if (!ipts->stylus)
  1980. + return;
  1981. +
  1982. + input_unregister_device(ipts->stylus);
  1983. +}
  1984. diff --git a/drivers/input/touchscreen/ipts/stylus.h b/drivers/input/touchscreen/ipts/stylus.h
  1985. new file mode 100644
  1986. index 0000000000000..5b93add1eac2d
  1987. --- /dev/null
  1988. +++ b/drivers/input/touchscreen/ipts/stylus.h
  1989. @@ -0,0 +1,14 @@
  1990. +/* SPDX-License-Identifier: GPL-2.0-or-later */
  1991. +
  1992. +#ifndef _IPTS_STYLUS_H_
  1993. +#define _IPTS_STYLUS_H_
  1994. +
  1995. +#include "context.h"
  1996. +#include "protocol/payload.h"
  1997. +
  1998. +void ipts_stylus_handle_input(struct ipts_context *ipts,
  1999. + struct ipts_payload_frame *frame);
  2000. +int ipts_stylus_init(struct ipts_context *ipts);
  2001. +void ipts_stylus_free(struct ipts_context *ipts);
  2002. +
  2003. +#endif /* _IPTS_STYLUS_H_ */
  2004. diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
  2005. index e56dc47540646..a55c61c89238a 100644
  2006. --- a/drivers/misc/mei/hw-me-regs.h
  2007. +++ b/drivers/misc/mei/hw-me-regs.h
  2008. @@ -59,6 +59,7 @@
  2009. #define MEI_DEV_ID_SPT 0x9D3A /* Sunrise Point */
  2010. #define MEI_DEV_ID_SPT_2 0x9D3B /* Sunrise Point 2 */
  2011. +#define MEI_DEV_ID_SPT_4 0x9D3E /* Sunrise Point 4 (iTouch) */
  2012. #define MEI_DEV_ID_SPT_H 0xA13A /* Sunrise Point H */
  2013. #define MEI_DEV_ID_SPT_H_2 0xA13B /* Sunrise Point H 2 */
  2014. @@ -90,6 +91,7 @@
  2015. #define MEI_DEV_ID_CDF 0x18D3 /* Cedar Fork */
  2016. #define MEI_DEV_ID_ICP_LP 0x34E0 /* Ice Lake Point LP */
  2017. +#define MEI_DEV_ID_ICP_LP_4 0x34E4 /* Ice Lake Point LP 4 (iTouch) */
  2018. #define MEI_DEV_ID_TGP_LP 0xA0E0 /* Tiger Lake Point LP */
  2019. diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
  2020. index 75ab2ffbf235f..78790904d77cb 100644
  2021. --- a/drivers/misc/mei/pci-me.c
  2022. +++ b/drivers/misc/mei/pci-me.c
  2023. @@ -77,6 +77,7 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
  2024. {MEI_PCI_DEVICE(MEI_DEV_ID_SPT, MEI_ME_PCH8_CFG)},
  2025. {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, MEI_ME_PCH8_CFG)},
  2026. + {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_4, MEI_ME_PCH8_CFG)},
  2027. {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, MEI_ME_PCH8_SPS_CFG)},
  2028. {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, MEI_ME_PCH8_SPS_CFG)},
  2029. {MEI_PCI_DEVICE(MEI_DEV_ID_LBG, MEI_ME_PCH12_CFG)},
  2030. @@ -103,6 +104,7 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
  2031. {MEI_PCI_DEVICE(MEI_DEV_ID_CMP_H_3, MEI_ME_PCH8_CFG)},
  2032. {MEI_PCI_DEVICE(MEI_DEV_ID_ICP_LP, MEI_ME_PCH12_CFG)},
  2033. + {MEI_PCI_DEVICE(MEI_DEV_ID_ICP_LP_4, MEI_ME_PCH12_CFG)},
  2034. {MEI_PCI_DEVICE(MEI_DEV_ID_TGP_LP, MEI_ME_PCH12_CFG)},
  2035. diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
  2036. index 9a61c28ed3ae4..47fc20975245d 100644
  2037. --- a/include/uapi/linux/input.h
  2038. +++ b/include/uapi/linux/input.h
  2039. @@ -271,6 +271,7 @@ struct input_mask {
  2040. #define BUS_RMI 0x1D
  2041. #define BUS_CEC 0x1E
  2042. #define BUS_INTEL_ISHTP 0x1F
  2043. +#define BUS_MEI 0x44
  2044. /*
  2045. * MT_TOOL types
  2046. --
  2047. 2.28.0