0007-ipts.patch 57 KB

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