skl-sst-ipc.c 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033
  1. /*
  2. * skl-sst-ipc.c - Intel skl IPC Support
  3. *
  4. * Copyright (C) 2014-15, Intel Corporation.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as version 2, as
  8. * published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. */
  15. #include <linux/device.h>
  16. #include "../common/sst-dsp.h"
  17. #include "../common/sst-dsp-priv.h"
  18. #include "skl.h"
  19. #include "skl-sst-dsp.h"
  20. #include "skl-sst-ipc.h"
  21. #include "sound/hdaudio_ext.h"
  22. #define IPC_IXC_STATUS_BITS 24
  23. /* Global Message - Generic */
  24. #define IPC_GLB_TYPE_SHIFT 24
  25. #define IPC_GLB_TYPE_MASK (0xf << IPC_GLB_TYPE_SHIFT)
  26. #define IPC_GLB_TYPE(x) ((x) << IPC_GLB_TYPE_SHIFT)
  27. /* Global Message - Reply */
  28. #define IPC_GLB_REPLY_STATUS_SHIFT 24
  29. #define IPC_GLB_REPLY_STATUS_MASK ((0x1 << IPC_GLB_REPLY_STATUS_SHIFT) - 1)
  30. #define IPC_GLB_REPLY_STATUS(x) ((x) << IPC_GLB_REPLY_STATUS_SHIFT)
  31. #define IPC_GLB_REPLY_TYPE_SHIFT 29
  32. #define IPC_GLB_REPLY_TYPE_MASK 0x1F
  33. #define IPC_GLB_REPLY_TYPE(x) (((x) >> IPC_GLB_REPLY_TYPE_SHIFT) \
  34. & IPC_GLB_RPLY_TYPE_MASK)
  35. #define IPC_TIMEOUT_MSECS 3000
  36. #define IPC_EMPTY_LIST_SIZE 8
  37. #define IPC_MSG_TARGET_SHIFT 30
  38. #define IPC_MSG_TARGET_MASK 0x1
  39. #define IPC_MSG_TARGET(x) (((x) & IPC_MSG_TARGET_MASK) \
  40. << IPC_MSG_TARGET_SHIFT)
  41. #define IPC_MSG_DIR_SHIFT 29
  42. #define IPC_MSG_DIR_MASK 0x1
  43. #define IPC_MSG_DIR(x) (((x) & IPC_MSG_DIR_MASK) \
  44. << IPC_MSG_DIR_SHIFT)
  45. /* Global Notification Message */
  46. #define IPC_GLB_NOTIFY_TYPE_SHIFT 16
  47. #define IPC_GLB_NOTIFY_TYPE_MASK 0xFF
  48. #define IPC_GLB_NOTIFY_TYPE(x) (((x) >> IPC_GLB_NOTIFY_TYPE_SHIFT) \
  49. & IPC_GLB_NOTIFY_TYPE_MASK)
  50. #define IPC_GLB_NOTIFY_MSG_TYPE_SHIFT 24
  51. #define IPC_GLB_NOTIFY_MSG_TYPE_MASK 0x1F
  52. #define IPC_GLB_NOTIFY_MSG_TYPE(x) (((x) >> IPC_GLB_NOTIFY_MSG_TYPE_SHIFT) \
  53. & IPC_GLB_NOTIFY_MSG_TYPE_MASK)
  54. #define IPC_GLB_NOTIFY_RSP_SHIFT 29
  55. #define IPC_GLB_NOTIFY_RSP_MASK 0x1
  56. #define IPC_GLB_NOTIFY_RSP_TYPE(x) (((x) >> IPC_GLB_NOTIFY_RSP_SHIFT) \
  57. & IPC_GLB_NOTIFY_RSP_MASK)
  58. /* Pipeline operations */
  59. /* Create pipeline message */
  60. #define IPC_PPL_MEM_SIZE_SHIFT 0
  61. #define IPC_PPL_MEM_SIZE_MASK 0x7FF
  62. #define IPC_PPL_MEM_SIZE(x) (((x) & IPC_PPL_MEM_SIZE_MASK) \
  63. << IPC_PPL_MEM_SIZE_SHIFT)
  64. #define IPC_PPL_TYPE_SHIFT 11
  65. #define IPC_PPL_TYPE_MASK 0x1F
  66. #define IPC_PPL_TYPE(x) (((x) & IPC_PPL_TYPE_MASK) \
  67. << IPC_PPL_TYPE_SHIFT)
  68. #define IPC_INSTANCE_ID_SHIFT 16
  69. #define IPC_INSTANCE_ID_MASK 0xFF
  70. #define IPC_INSTANCE_ID(x) (((x) & IPC_INSTANCE_ID_MASK) \
  71. << IPC_INSTANCE_ID_SHIFT)
  72. #define IPC_PPL_LP_MODE_SHIFT 0
  73. #define IPC_PPL_LP_MODE_MASK 0x1
  74. #define IPC_PPL_LP_MODE(x) (((x) & IPC_PPL_LP_MODE_MASK) \
  75. << IPC_PPL_LP_MODE_SHIFT)
  76. /* Set pipeline state message */
  77. #define IPC_PPL_STATE_SHIFT 0
  78. #define IPC_PPL_STATE_MASK 0x1F
  79. #define IPC_PPL_STATE(x) (((x) & IPC_PPL_STATE_MASK) \
  80. << IPC_PPL_STATE_SHIFT)
  81. /* Module operations primary register */
  82. #define IPC_MOD_ID_SHIFT 0
  83. #define IPC_MOD_ID_MASK 0xFFFF
  84. #define IPC_MOD_ID(x) (((x) & IPC_MOD_ID_MASK) \
  85. << IPC_MOD_ID_SHIFT)
  86. #define IPC_MOD_INSTANCE_ID_SHIFT 16
  87. #define IPC_MOD_INSTANCE_ID_MASK 0xFF
  88. #define IPC_MOD_INSTANCE_ID(x) (((x) & IPC_MOD_INSTANCE_ID_MASK) \
  89. << IPC_MOD_INSTANCE_ID_SHIFT)
  90. /* Init instance message extension register */
  91. #define IPC_PARAM_BLOCK_SIZE_SHIFT 0
  92. #define IPC_PARAM_BLOCK_SIZE_MASK 0xFFFF
  93. #define IPC_PARAM_BLOCK_SIZE(x) (((x) & IPC_PARAM_BLOCK_SIZE_MASK) \
  94. << IPC_PARAM_BLOCK_SIZE_SHIFT)
  95. #define IPC_PPL_INSTANCE_ID_SHIFT 16
  96. #define IPC_PPL_INSTANCE_ID_MASK 0xFF
  97. #define IPC_PPL_INSTANCE_ID(x) (((x) & IPC_PPL_INSTANCE_ID_MASK) \
  98. << IPC_PPL_INSTANCE_ID_SHIFT)
  99. #define IPC_CORE_ID_SHIFT 24
  100. #define IPC_CORE_ID_MASK 0x1F
  101. #define IPC_CORE_ID(x) (((x) & IPC_CORE_ID_MASK) \
  102. << IPC_CORE_ID_SHIFT)
  103. #define IPC_DOMAIN_SHIFT 28
  104. #define IPC_DOMAIN_MASK 0x1
  105. #define IPC_DOMAIN(x) (((x) & IPC_DOMAIN_MASK) \
  106. << IPC_DOMAIN_SHIFT)
  107. /* Bind/Unbind message extension register */
  108. #define IPC_DST_MOD_ID_SHIFT 0
  109. #define IPC_DST_MOD_ID(x) (((x) & IPC_MOD_ID_MASK) \
  110. << IPC_DST_MOD_ID_SHIFT)
  111. #define IPC_DST_MOD_INSTANCE_ID_SHIFT 16
  112. #define IPC_DST_MOD_INSTANCE_ID(x) (((x) & IPC_MOD_INSTANCE_ID_MASK) \
  113. << IPC_DST_MOD_INSTANCE_ID_SHIFT)
  114. #define IPC_DST_QUEUE_SHIFT 24
  115. #define IPC_DST_QUEUE_MASK 0x7
  116. #define IPC_DST_QUEUE(x) (((x) & IPC_DST_QUEUE_MASK) \
  117. << IPC_DST_QUEUE_SHIFT)
  118. #define IPC_SRC_QUEUE_SHIFT 27
  119. #define IPC_SRC_QUEUE_MASK 0x7
  120. #define IPC_SRC_QUEUE(x) (((x) & IPC_SRC_QUEUE_MASK) \
  121. << IPC_SRC_QUEUE_SHIFT)
  122. /* Load Module count */
  123. #define IPC_LOAD_MODULE_SHIFT 0
  124. #define IPC_LOAD_MODULE_MASK 0xFF
  125. #define IPC_LOAD_MODULE_CNT(x) (((x) & IPC_LOAD_MODULE_MASK) \
  126. << IPC_LOAD_MODULE_SHIFT)
  127. /* Save pipeline messgae extension register */
  128. #define IPC_DMA_ID_SHIFT 0
  129. #define IPC_DMA_ID_MASK 0x1F
  130. #define IPC_DMA_ID(x) (((x) & IPC_DMA_ID_MASK) \
  131. << IPC_DMA_ID_SHIFT)
  132. /* Large Config message extension register */
  133. #define IPC_DATA_OFFSET_SZ_SHIFT 0
  134. #define IPC_DATA_OFFSET_SZ_MASK 0xFFFFF
  135. #define IPC_DATA_OFFSET_SZ(x) (((x) & IPC_DATA_OFFSET_SZ_MASK) \
  136. << IPC_DATA_OFFSET_SZ_SHIFT)
  137. #define IPC_DATA_OFFSET_SZ_CLEAR ~(IPC_DATA_OFFSET_SZ_MASK \
  138. << IPC_DATA_OFFSET_SZ_SHIFT)
  139. #define IPC_LARGE_PARAM_ID_SHIFT 20
  140. #define IPC_LARGE_PARAM_ID_MASK 0xFF
  141. #define IPC_LARGE_PARAM_ID(x) (((x) & IPC_LARGE_PARAM_ID_MASK) \
  142. << IPC_LARGE_PARAM_ID_SHIFT)
  143. #define IPC_FINAL_BLOCK_SHIFT 28
  144. #define IPC_FINAL_BLOCK_MASK 0x1
  145. #define IPC_FINAL_BLOCK(x) (((x) & IPC_FINAL_BLOCK_MASK) \
  146. << IPC_FINAL_BLOCK_SHIFT)
  147. #define IPC_INITIAL_BLOCK_SHIFT 29
  148. #define IPC_INITIAL_BLOCK_MASK 0x1
  149. #define IPC_INITIAL_BLOCK(x) (((x) & IPC_INITIAL_BLOCK_MASK) \
  150. << IPC_INITIAL_BLOCK_SHIFT)
  151. #define IPC_INITIAL_BLOCK_CLEAR ~(IPC_INITIAL_BLOCK_MASK \
  152. << IPC_INITIAL_BLOCK_SHIFT)
  153. /* Set D0ix IPC extension register */
  154. #define IPC_D0IX_WAKE_SHIFT 0
  155. #define IPC_D0IX_WAKE_MASK 0x1
  156. #define IPC_D0IX_WAKE(x) (((x) & IPC_D0IX_WAKE_MASK) \
  157. << IPC_D0IX_WAKE_SHIFT)
  158. #define IPC_D0IX_STREAMING_SHIFT 1
  159. #define IPC_D0IX_STREAMING_MASK 0x1
  160. #define IPC_D0IX_STREAMING(x) (((x) & IPC_D0IX_STREAMING_MASK) \
  161. << IPC_D0IX_STREAMING_SHIFT)
  162. enum skl_ipc_msg_target {
  163. IPC_FW_GEN_MSG = 0,
  164. IPC_MOD_MSG = 1
  165. };
  166. enum skl_ipc_msg_direction {
  167. IPC_MSG_REQUEST = 0,
  168. IPC_MSG_REPLY = 1
  169. };
  170. /* Global Message Types */
  171. enum skl_ipc_glb_type {
  172. IPC_GLB_GET_FW_VERSION = 0, /* Retrieves firmware version */
  173. IPC_GLB_LOAD_MULTIPLE_MODS = 15,
  174. IPC_GLB_UNLOAD_MULTIPLE_MODS = 16,
  175. IPC_GLB_CREATE_PPL = 17,
  176. IPC_GLB_DELETE_PPL = 18,
  177. IPC_GLB_SET_PPL_STATE = 19,
  178. IPC_GLB_GET_PPL_STATE = 20,
  179. IPC_GLB_GET_PPL_CONTEXT_SIZE = 21,
  180. IPC_GLB_SAVE_PPL = 22,
  181. IPC_GLB_RESTORE_PPL = 23,
  182. IPC_GLB_LOAD_LIBRARY = 24,
  183. IPC_GLB_NOTIFY = 26,
  184. IPC_GLB_MAX_IPC_MSG_NUMBER = 31 /* Maximum message number */
  185. };
  186. enum skl_ipc_glb_reply {
  187. IPC_GLB_REPLY_SUCCESS = 0,
  188. IPC_GLB_REPLY_UNKNOWN_MSG_TYPE = 1,
  189. IPC_GLB_REPLY_ERROR_INVALID_PARAM = 2,
  190. IPC_GLB_REPLY_BUSY = 3,
  191. IPC_GLB_REPLY_PENDING = 4,
  192. IPC_GLB_REPLY_FAILURE = 5,
  193. IPC_GLB_REPLY_INVALID_REQUEST = 6,
  194. IPC_GLB_REPLY_OUT_OF_MEMORY = 7,
  195. IPC_GLB_REPLY_OUT_OF_MIPS = 8,
  196. IPC_GLB_REPLY_INVALID_RESOURCE_ID = 9,
  197. IPC_GLB_REPLY_INVALID_RESOURCE_STATE = 10,
  198. IPC_GLB_REPLY_MOD_MGMT_ERROR = 100,
  199. IPC_GLB_REPLY_MOD_LOAD_CL_FAILED = 101,
  200. IPC_GLB_REPLY_MOD_LOAD_INVALID_HASH = 102,
  201. IPC_GLB_REPLY_MOD_UNLOAD_INST_EXIST = 103,
  202. IPC_GLB_REPLY_MOD_NOT_INITIALIZED = 104,
  203. IPC_GLB_REPLY_INVALID_CONFIG_PARAM_ID = 120,
  204. IPC_GLB_REPLY_INVALID_CONFIG_DATA_LEN = 121,
  205. IPC_GLB_REPLY_GATEWAY_NOT_INITIALIZED = 140,
  206. IPC_GLB_REPLY_GATEWAY_NOT_EXIST = 141,
  207. IPC_GLB_REPLY_PPL_NOT_INITIALIZED = 160,
  208. IPC_GLB_REPLY_PPL_NOT_EXIST = 161,
  209. IPC_GLB_REPLY_PPL_SAVE_FAILED = 162,
  210. IPC_GLB_REPLY_PPL_RESTORE_FAILED = 163,
  211. IPC_MAX_STATUS = ((1<<IPC_IXC_STATUS_BITS)-1)
  212. };
  213. enum skl_ipc_notification_type {
  214. IPC_GLB_NOTIFY_GLITCH = 0,
  215. IPC_GLB_NOTIFY_OVERRUN = 1,
  216. IPC_GLB_NOTIFY_UNDERRUN = 2,
  217. IPC_GLB_NOTIFY_END_STREAM = 3,
  218. IPC_GLB_NOTIFY_PHRASE_DETECTED = 4,
  219. IPC_GLB_NOTIFY_RESOURCE_EVENT = 5,
  220. IPC_GLB_NOTIFY_LOG_BUFFER_STATUS = 6,
  221. IPC_GLB_NOTIFY_TIMESTAMP_CAPTURED = 7,
  222. IPC_GLB_NOTIFY_FW_READY = 8
  223. };
  224. /* Module Message Types */
  225. enum skl_ipc_module_msg {
  226. IPC_MOD_INIT_INSTANCE = 0,
  227. IPC_MOD_CONFIG_GET = 1,
  228. IPC_MOD_CONFIG_SET = 2,
  229. IPC_MOD_LARGE_CONFIG_GET = 3,
  230. IPC_MOD_LARGE_CONFIG_SET = 4,
  231. IPC_MOD_BIND = 5,
  232. IPC_MOD_UNBIND = 6,
  233. IPC_MOD_SET_DX = 7,
  234. IPC_MOD_SET_D0IX = 8
  235. };
  236. void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data,
  237. size_t tx_size)
  238. {
  239. if (tx_size)
  240. memcpy(msg->tx_data, tx_data, tx_size);
  241. }
  242. static bool skl_ipc_is_dsp_busy(struct sst_dsp *dsp)
  243. {
  244. u32 hipci;
  245. hipci = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCI);
  246. return (hipci & SKL_ADSP_REG_HIPCI_BUSY);
  247. }
  248. /* Lock to be held by caller */
  249. static void skl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg)
  250. {
  251. struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->header);
  252. if (msg->tx_size)
  253. sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size);
  254. sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCIE,
  255. header->extension);
  256. sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCI,
  257. header->primary | SKL_ADSP_REG_HIPCI_BUSY);
  258. }
  259. int skl_ipc_check_D0i0(struct sst_dsp *dsp, bool state)
  260. {
  261. int ret;
  262. /* check D0i3 support */
  263. if (!dsp->fw_ops.set_state_D0i0)
  264. return 0;
  265. /* Attempt D0i0 or D0i3 based on state */
  266. if (state)
  267. ret = dsp->fw_ops.set_state_D0i0(dsp);
  268. else
  269. ret = dsp->fw_ops.set_state_D0i3(dsp);
  270. return ret;
  271. }
  272. static struct ipc_message *skl_ipc_reply_get_msg(struct sst_generic_ipc *ipc,
  273. u64 ipc_header)
  274. {
  275. struct ipc_message *msg = NULL;
  276. struct skl_ipc_header *header = (struct skl_ipc_header *)(&ipc_header);
  277. if (list_empty(&ipc->rx_list)) {
  278. dev_err(ipc->dev, "ipc: rx list is empty but received 0x%x\n",
  279. header->primary);
  280. goto out;
  281. }
  282. msg = list_first_entry(&ipc->rx_list, struct ipc_message, list);
  283. out:
  284. return msg;
  285. }
  286. int skl_ipc_process_notification(struct sst_generic_ipc *ipc,
  287. struct skl_ipc_header header)
  288. {
  289. struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc);
  290. if (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) {
  291. switch (IPC_GLB_NOTIFY_TYPE(header.primary)) {
  292. case IPC_GLB_NOTIFY_UNDERRUN:
  293. dev_err(ipc->dev, "FW Underrun %x\n", header.primary);
  294. break;
  295. case IPC_GLB_NOTIFY_RESOURCE_EVENT:
  296. dev_err(ipc->dev, "MCPS Budget Violation: %x\n",
  297. header.primary);
  298. break;
  299. case IPC_GLB_NOTIFY_FW_READY:
  300. skl->boot_complete = true;
  301. wake_up(&skl->boot_wait);
  302. break;
  303. case IPC_GLB_NOTIFY_PHRASE_DETECTED:
  304. dev_dbg(ipc->dev, "***** Phrase Detected **********\n");
  305. /*
  306. * Per HW recomendation, After phrase detection,
  307. * clear the CGCTL.MISCBDCGE.
  308. *
  309. * This will be set back on stream closure
  310. */
  311. skl->enable_miscbdcge(ipc->dev, false);
  312. skl->miscbdcg_disabled = true;
  313. break;
  314. default:
  315. dev_err(ipc->dev, "ipc: Unhandled error msg=%x\n",
  316. header.primary);
  317. break;
  318. }
  319. }
  320. return 0;
  321. }
  322. static int skl_ipc_set_reply_error_code(u32 reply)
  323. {
  324. switch (reply) {
  325. case IPC_GLB_REPLY_OUT_OF_MEMORY:
  326. return -ENOMEM;
  327. case IPC_GLB_REPLY_BUSY:
  328. return -EBUSY;
  329. default:
  330. return -EINVAL;
  331. }
  332. }
  333. void skl_ipc_process_reply(struct sst_generic_ipc *ipc,
  334. struct skl_ipc_header header)
  335. {
  336. struct ipc_message *msg;
  337. u32 reply = header.primary & IPC_GLB_REPLY_STATUS_MASK;
  338. u64 *ipc_header = (u64 *)(&header);
  339. struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc);
  340. unsigned long flags;
  341. spin_lock_irqsave(&ipc->dsp->spinlock, flags);
  342. msg = skl_ipc_reply_get_msg(ipc, *ipc_header);
  343. spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
  344. if (msg == NULL) {
  345. dev_dbg(ipc->dev, "ipc: rx list is empty\n");
  346. return;
  347. }
  348. /* first process the header */
  349. if (reply == IPC_GLB_REPLY_SUCCESS) {
  350. dev_dbg(ipc->dev, "ipc FW reply %x: success\n", header.primary);
  351. /* copy the rx data from the mailbox */
  352. sst_dsp_inbox_read(ipc->dsp, msg->rx_data, msg->rx_size);
  353. switch (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) {
  354. case IPC_GLB_LOAD_MULTIPLE_MODS:
  355. case IPC_GLB_LOAD_LIBRARY:
  356. skl->mod_load_complete = true;
  357. skl->mod_load_status = true;
  358. wake_up(&skl->mod_load_wait);
  359. break;
  360. default:
  361. break;
  362. }
  363. } else {
  364. msg->errno = skl_ipc_set_reply_error_code(reply);
  365. dev_err(ipc->dev, "ipc FW reply: reply=%d\n", reply);
  366. dev_err(ipc->dev, "FW Error Code: %u\n",
  367. ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp));
  368. switch (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) {
  369. case IPC_GLB_LOAD_MULTIPLE_MODS:
  370. case IPC_GLB_LOAD_LIBRARY:
  371. skl->mod_load_complete = true;
  372. skl->mod_load_status = false;
  373. wake_up(&skl->mod_load_wait);
  374. break;
  375. default:
  376. break;
  377. }
  378. }
  379. spin_lock_irqsave(&ipc->dsp->spinlock, flags);
  380. list_del(&msg->list);
  381. sst_ipc_tx_msg_reply_complete(ipc, msg);
  382. spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
  383. }
  384. irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context)
  385. {
  386. struct sst_dsp *dsp = context;
  387. struct skl_sst *skl = sst_dsp_get_thread_context(dsp);
  388. struct sst_generic_ipc *ipc = &skl->ipc;
  389. struct skl_ipc_header header = {0};
  390. u32 hipcie, hipct, hipcte;
  391. int ipc_irq = 0;
  392. if (dsp->intr_status & SKL_ADSPIS_CL_DMA)
  393. skl_cldma_process_intr(dsp);
  394. /* Here we handle IPC interrupts only */
  395. if (!(dsp->intr_status & SKL_ADSPIS_IPC))
  396. return IRQ_NONE;
  397. hipcie = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCIE);
  398. hipct = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCT);
  399. /* reply message from DSP */
  400. if (hipcie & SKL_ADSP_REG_HIPCIE_DONE) {
  401. sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL,
  402. SKL_ADSP_REG_HIPCCTL_DONE, 0);
  403. /* clear DONE bit - tell DSP we have completed the operation */
  404. sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCIE,
  405. SKL_ADSP_REG_HIPCIE_DONE, SKL_ADSP_REG_HIPCIE_DONE);
  406. ipc_irq = 1;
  407. /* unmask Done interrupt */
  408. sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL,
  409. SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE);
  410. }
  411. /* New message from DSP */
  412. if (hipct & SKL_ADSP_REG_HIPCT_BUSY) {
  413. hipcte = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCTE);
  414. header.primary = hipct;
  415. header.extension = hipcte;
  416. dev_dbg(dsp->dev, "IPC irq: Firmware respond primary:%x\n",
  417. header.primary);
  418. dev_dbg(dsp->dev, "IPC irq: Firmware respond extension:%x\n",
  419. header.extension);
  420. if (IPC_GLB_NOTIFY_RSP_TYPE(header.primary)) {
  421. /* Handle Immediate reply from DSP Core */
  422. skl_ipc_process_reply(ipc, header);
  423. } else {
  424. dev_dbg(dsp->dev, "IPC irq: Notification from firmware\n");
  425. skl_ipc_process_notification(ipc, header);
  426. }
  427. /* clear busy interrupt */
  428. sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCT,
  429. SKL_ADSP_REG_HIPCT_BUSY, SKL_ADSP_REG_HIPCT_BUSY);
  430. ipc_irq = 1;
  431. }
  432. if (ipc_irq == 0)
  433. return IRQ_NONE;
  434. skl_ipc_int_enable(dsp);
  435. /* continue to send any remaining messages... */
  436. schedule_work(&ipc->kwork);
  437. return IRQ_HANDLED;
  438. }
  439. void skl_ipc_int_enable(struct sst_dsp *ctx)
  440. {
  441. sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_ADSPIC,
  442. SKL_ADSPIC_IPC, SKL_ADSPIC_IPC);
  443. }
  444. void skl_ipc_int_disable(struct sst_dsp *ctx)
  445. {
  446. sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPIC,
  447. SKL_ADSPIC_IPC, 0);
  448. }
  449. void skl_ipc_op_int_enable(struct sst_dsp *ctx)
  450. {
  451. /* enable IPC DONE interrupt */
  452. sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL,
  453. SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE);
  454. /* Enable IPC BUSY interrupt */
  455. sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL,
  456. SKL_ADSP_REG_HIPCCTL_BUSY, SKL_ADSP_REG_HIPCCTL_BUSY);
  457. }
  458. void skl_ipc_op_int_disable(struct sst_dsp *ctx)
  459. {
  460. /* disable IPC DONE interrupt */
  461. sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL,
  462. SKL_ADSP_REG_HIPCCTL_DONE, 0);
  463. /* Disable IPC BUSY interrupt */
  464. sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL,
  465. SKL_ADSP_REG_HIPCCTL_BUSY, 0);
  466. }
  467. bool skl_ipc_int_status(struct sst_dsp *ctx)
  468. {
  469. return sst_dsp_shim_read_unlocked(ctx,
  470. SKL_ADSP_REG_ADSPIS) & SKL_ADSPIS_IPC;
  471. }
  472. int skl_ipc_init(struct device *dev, struct skl_sst *skl)
  473. {
  474. struct sst_generic_ipc *ipc;
  475. int err;
  476. ipc = &skl->ipc;
  477. ipc->dsp = skl->dsp;
  478. ipc->dev = dev;
  479. ipc->tx_data_max_size = SKL_ADSP_W1_SZ;
  480. ipc->rx_data_max_size = SKL_ADSP_W0_UP_SZ;
  481. err = sst_ipc_init(ipc);
  482. if (err)
  483. return err;
  484. ipc->ops.tx_msg = skl_ipc_tx_msg;
  485. ipc->ops.tx_data_copy = skl_ipc_tx_data_copy;
  486. ipc->ops.is_dsp_busy = skl_ipc_is_dsp_busy;
  487. return 0;
  488. }
  489. void skl_ipc_free(struct sst_generic_ipc *ipc)
  490. {
  491. /* Disable IPC DONE interrupt */
  492. sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL,
  493. SKL_ADSP_REG_HIPCCTL_DONE, 0);
  494. /* Disable IPC BUSY interrupt */
  495. sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL,
  496. SKL_ADSP_REG_HIPCCTL_BUSY, 0);
  497. sst_ipc_fini(ipc);
  498. }
  499. int skl_ipc_create_pipeline(struct sst_generic_ipc *ipc,
  500. u16 ppl_mem_size, u8 ppl_type, u8 instance_id, u8 lp_mode)
  501. {
  502. struct skl_ipc_header header = {0};
  503. u64 *ipc_header = (u64 *)(&header);
  504. int ret;
  505. header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
  506. header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
  507. header.primary |= IPC_GLB_TYPE(IPC_GLB_CREATE_PPL);
  508. header.primary |= IPC_INSTANCE_ID(instance_id);
  509. header.primary |= IPC_PPL_TYPE(ppl_type);
  510. header.primary |= IPC_PPL_MEM_SIZE(ppl_mem_size);
  511. header.extension = IPC_PPL_LP_MODE(lp_mode);
  512. dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
  513. ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
  514. if (ret < 0) {
  515. dev_err(ipc->dev, "ipc: create pipeline fail, err: %d\n", ret);
  516. return ret;
  517. }
  518. return ret;
  519. }
  520. EXPORT_SYMBOL_GPL(skl_ipc_create_pipeline);
  521. int skl_ipc_delete_pipeline(struct sst_generic_ipc *ipc, u8 instance_id)
  522. {
  523. struct skl_ipc_header header = {0};
  524. u64 *ipc_header = (u64 *)(&header);
  525. int ret;
  526. header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
  527. header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
  528. header.primary |= IPC_GLB_TYPE(IPC_GLB_DELETE_PPL);
  529. header.primary |= IPC_INSTANCE_ID(instance_id);
  530. dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
  531. ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
  532. if (ret < 0) {
  533. dev_err(ipc->dev, "ipc: delete pipeline failed, err %d\n", ret);
  534. return ret;
  535. }
  536. return 0;
  537. }
  538. EXPORT_SYMBOL_GPL(skl_ipc_delete_pipeline);
  539. int skl_ipc_set_pipeline_state(struct sst_generic_ipc *ipc,
  540. u8 instance_id, enum skl_ipc_pipeline_state state)
  541. {
  542. struct skl_ipc_header header = {0};
  543. u64 *ipc_header = (u64 *)(&header);
  544. int ret;
  545. header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
  546. header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
  547. header.primary |= IPC_GLB_TYPE(IPC_GLB_SET_PPL_STATE);
  548. header.primary |= IPC_INSTANCE_ID(instance_id);
  549. header.primary |= IPC_PPL_STATE(state);
  550. dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
  551. ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
  552. if (ret < 0) {
  553. dev_err(ipc->dev, "ipc: set pipeline state failed, err: %d\n", ret);
  554. return ret;
  555. }
  556. return ret;
  557. }
  558. EXPORT_SYMBOL_GPL(skl_ipc_set_pipeline_state);
  559. int
  560. skl_ipc_save_pipeline(struct sst_generic_ipc *ipc, u8 instance_id, int dma_id)
  561. {
  562. struct skl_ipc_header header = {0};
  563. u64 *ipc_header = (u64 *)(&header);
  564. int ret;
  565. header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
  566. header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
  567. header.primary |= IPC_GLB_TYPE(IPC_GLB_SAVE_PPL);
  568. header.primary |= IPC_INSTANCE_ID(instance_id);
  569. header.extension = IPC_DMA_ID(dma_id);
  570. dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
  571. ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
  572. if (ret < 0) {
  573. dev_err(ipc->dev, "ipc: save pipeline failed, err: %d\n", ret);
  574. return ret;
  575. }
  576. return ret;
  577. }
  578. EXPORT_SYMBOL_GPL(skl_ipc_save_pipeline);
  579. int skl_ipc_restore_pipeline(struct sst_generic_ipc *ipc, u8 instance_id)
  580. {
  581. struct skl_ipc_header header = {0};
  582. u64 *ipc_header = (u64 *)(&header);
  583. int ret;
  584. header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
  585. header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
  586. header.primary |= IPC_GLB_TYPE(IPC_GLB_RESTORE_PPL);
  587. header.primary |= IPC_INSTANCE_ID(instance_id);
  588. dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
  589. ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
  590. if (ret < 0) {
  591. dev_err(ipc->dev, "ipc: restore pipeline failed, err: %d\n", ret);
  592. return ret;
  593. }
  594. return ret;
  595. }
  596. EXPORT_SYMBOL_GPL(skl_ipc_restore_pipeline);
  597. int skl_ipc_set_dx(struct sst_generic_ipc *ipc, u8 instance_id,
  598. u16 module_id, struct skl_ipc_dxstate_info *dx)
  599. {
  600. struct skl_ipc_header header = {0};
  601. u64 *ipc_header = (u64 *)(&header);
  602. int ret;
  603. header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
  604. header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
  605. header.primary |= IPC_GLB_TYPE(IPC_MOD_SET_DX);
  606. header.primary |= IPC_MOD_INSTANCE_ID(instance_id);
  607. header.primary |= IPC_MOD_ID(module_id);
  608. dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__,
  609. header.primary, header.extension);
  610. ret = sst_ipc_tx_message_wait(ipc, *ipc_header,
  611. dx, sizeof(*dx), NULL, 0);
  612. if (ret < 0) {
  613. dev_err(ipc->dev, "ipc: set dx failed, err %d\n", ret);
  614. return ret;
  615. }
  616. return ret;
  617. }
  618. EXPORT_SYMBOL_GPL(skl_ipc_set_dx);
  619. int skl_ipc_init_instance(struct sst_generic_ipc *ipc,
  620. struct skl_ipc_init_instance_msg *msg, void *param_data)
  621. {
  622. struct skl_ipc_header header = {0};
  623. u64 *ipc_header = (u64 *)(&header);
  624. int ret;
  625. u32 *buffer = (u32 *)param_data;
  626. /* param_block_size must be in dwords */
  627. u16 param_block_size = msg->param_data_size / sizeof(u32);
  628. print_hex_dump_debug("Param data:", DUMP_PREFIX_NONE,
  629. 16, 4, buffer, param_block_size, false);
  630. header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
  631. header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
  632. header.primary |= IPC_GLB_TYPE(IPC_MOD_INIT_INSTANCE);
  633. header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
  634. header.primary |= IPC_MOD_ID(msg->module_id);
  635. header.extension = IPC_CORE_ID(msg->core_id);
  636. header.extension |= IPC_PPL_INSTANCE_ID(msg->ppl_instance_id);
  637. header.extension |= IPC_PARAM_BLOCK_SIZE(param_block_size);
  638. header.extension |= IPC_DOMAIN(msg->domain);
  639. dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__,
  640. header.primary, header.extension);
  641. ret = sst_ipc_tx_message_wait(ipc, *ipc_header, param_data,
  642. msg->param_data_size, NULL, 0);
  643. if (ret < 0) {
  644. dev_err(ipc->dev, "ipc: init instance failed\n");
  645. return ret;
  646. }
  647. return ret;
  648. }
  649. EXPORT_SYMBOL_GPL(skl_ipc_init_instance);
  650. int skl_ipc_bind_unbind(struct sst_generic_ipc *ipc,
  651. struct skl_ipc_bind_unbind_msg *msg)
  652. {
  653. struct skl_ipc_header header = {0};
  654. u64 *ipc_header = (u64 *)(&header);
  655. u8 bind_unbind = msg->bind ? IPC_MOD_BIND : IPC_MOD_UNBIND;
  656. int ret;
  657. header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
  658. header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
  659. header.primary |= IPC_GLB_TYPE(bind_unbind);
  660. header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
  661. header.primary |= IPC_MOD_ID(msg->module_id);
  662. header.extension = IPC_DST_MOD_ID(msg->dst_module_id);
  663. header.extension |= IPC_DST_MOD_INSTANCE_ID(msg->dst_instance_id);
  664. header.extension |= IPC_DST_QUEUE(msg->dst_queue);
  665. header.extension |= IPC_SRC_QUEUE(msg->src_queue);
  666. dev_dbg(ipc->dev, "In %s hdr=%x ext=%x\n", __func__, header.primary,
  667. header.extension);
  668. ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0, NULL, 0);
  669. if (ret < 0) {
  670. dev_err(ipc->dev, "ipc: bind/unbind failed\n");
  671. return ret;
  672. }
  673. return ret;
  674. }
  675. EXPORT_SYMBOL_GPL(skl_ipc_bind_unbind);
  676. /*
  677. * In order to load a module we need to send IPC to initiate that. DMA will
  678. * performed to load the module memory. The FW supports multiple module load
  679. * at single shot, so we can send IPC with N modules represented by
  680. * module_cnt
  681. */
  682. int skl_ipc_load_modules(struct sst_generic_ipc *ipc,
  683. u8 module_cnt, void *data)
  684. {
  685. struct skl_ipc_header header = {0};
  686. u64 *ipc_header = (u64 *)(&header);
  687. int ret;
  688. header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
  689. header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
  690. header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_MULTIPLE_MODS);
  691. header.primary |= IPC_LOAD_MODULE_CNT(module_cnt);
  692. ret = sst_ipc_tx_message_nowait(ipc, *ipc_header, data,
  693. (sizeof(u16) * module_cnt));
  694. if (ret < 0)
  695. dev_err(ipc->dev, "ipc: load modules failed :%d\n", ret);
  696. return ret;
  697. }
  698. EXPORT_SYMBOL_GPL(skl_ipc_load_modules);
  699. int skl_ipc_unload_modules(struct sst_generic_ipc *ipc, u8 module_cnt,
  700. void *data)
  701. {
  702. struct skl_ipc_header header = {0};
  703. u64 *ipc_header = (u64 *)(&header);
  704. int ret;
  705. header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
  706. header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
  707. header.primary |= IPC_GLB_TYPE(IPC_GLB_UNLOAD_MULTIPLE_MODS);
  708. header.primary |= IPC_LOAD_MODULE_CNT(module_cnt);
  709. ret = sst_ipc_tx_message_wait(ipc, *ipc_header, data,
  710. (sizeof(u16) * module_cnt), NULL, 0);
  711. if (ret < 0)
  712. dev_err(ipc->dev, "ipc: unload modules failed :%d\n", ret);
  713. return ret;
  714. }
  715. EXPORT_SYMBOL_GPL(skl_ipc_unload_modules);
  716. int skl_ipc_set_large_config(struct sst_generic_ipc *ipc,
  717. struct skl_ipc_large_config_msg *msg, u32 *param)
  718. {
  719. struct skl_ipc_header header = {0};
  720. u64 *ipc_header = (u64 *)(&header);
  721. int ret = 0;
  722. size_t sz_remaining, tx_size, data_offset;
  723. header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
  724. header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
  725. header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_SET);
  726. header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
  727. header.primary |= IPC_MOD_ID(msg->module_id);
  728. header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size);
  729. header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id);
  730. header.extension |= IPC_FINAL_BLOCK(0);
  731. header.extension |= IPC_INITIAL_BLOCK(1);
  732. sz_remaining = msg->param_data_size;
  733. data_offset = 0;
  734. while (sz_remaining != 0) {
  735. tx_size = sz_remaining > SKL_ADSP_W1_SZ
  736. ? SKL_ADSP_W1_SZ : sz_remaining;
  737. if (tx_size == sz_remaining)
  738. header.extension |= IPC_FINAL_BLOCK(1);
  739. dev_dbg(ipc->dev, "In %s primary=%#x ext=%#x\n", __func__,
  740. header.primary, header.extension);
  741. dev_dbg(ipc->dev, "transmitting offset: %#x, size: %#x\n",
  742. (unsigned)data_offset, (unsigned)tx_size);
  743. ret = sst_ipc_tx_message_wait(ipc, *ipc_header,
  744. ((char *)param) + data_offset,
  745. tx_size, NULL, 0);
  746. if (ret < 0) {
  747. dev_err(ipc->dev,
  748. "ipc: set large config fail, err: %d\n", ret);
  749. return ret;
  750. }
  751. sz_remaining -= tx_size;
  752. data_offset = msg->param_data_size - sz_remaining;
  753. /* clear the fields */
  754. header.extension &= IPC_INITIAL_BLOCK_CLEAR;
  755. header.extension &= IPC_DATA_OFFSET_SZ_CLEAR;
  756. /* fill the fields */
  757. header.extension |= IPC_INITIAL_BLOCK(0);
  758. header.extension |= IPC_DATA_OFFSET_SZ(data_offset);
  759. }
  760. return ret;
  761. }
  762. EXPORT_SYMBOL_GPL(skl_ipc_set_large_config);
  763. int skl_ipc_get_large_config(struct sst_generic_ipc *ipc,
  764. struct skl_ipc_large_config_msg *msg, u32 *param)
  765. {
  766. struct skl_ipc_header header = {0};
  767. u64 *ipc_header = (u64 *)(&header);
  768. int ret = 0;
  769. size_t sz_remaining, rx_size, data_offset;
  770. header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
  771. header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
  772. header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_GET);
  773. header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
  774. header.primary |= IPC_MOD_ID(msg->module_id);
  775. header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size);
  776. header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id);
  777. header.extension |= IPC_FINAL_BLOCK(1);
  778. header.extension |= IPC_INITIAL_BLOCK(1);
  779. sz_remaining = msg->param_data_size;
  780. data_offset = 0;
  781. while (sz_remaining != 0) {
  782. rx_size = sz_remaining > SKL_ADSP_W1_SZ
  783. ? SKL_ADSP_W1_SZ : sz_remaining;
  784. if (rx_size == sz_remaining)
  785. header.extension |= IPC_FINAL_BLOCK(1);
  786. ret = sst_ipc_tx_message_wait(ipc, *ipc_header, NULL, 0,
  787. ((char *)param) + data_offset,
  788. msg->param_data_size);
  789. if (ret < 0) {
  790. dev_err(ipc->dev,
  791. "ipc: get large config fail, err: %d\n", ret);
  792. return ret;
  793. }
  794. sz_remaining -= rx_size;
  795. data_offset = msg->param_data_size - sz_remaining;
  796. /* clear the fields */
  797. header.extension &= IPC_INITIAL_BLOCK_CLEAR;
  798. header.extension &= IPC_DATA_OFFSET_SZ_CLEAR;
  799. /* fill the fields */
  800. header.extension |= IPC_INITIAL_BLOCK(1);
  801. header.extension |= IPC_DATA_OFFSET_SZ(data_offset);
  802. }
  803. return ret;
  804. }
  805. EXPORT_SYMBOL_GPL(skl_ipc_get_large_config);
  806. int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc,
  807. u8 dma_id, u8 table_id, bool wait)
  808. {
  809. struct skl_ipc_header header = {0};
  810. u64 *ipc_header = (u64 *)(&header);
  811. int ret = 0;
  812. header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
  813. header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
  814. header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_LIBRARY);
  815. header.primary |= IPC_MOD_INSTANCE_ID(table_id);
  816. header.primary |= IPC_MOD_ID(dma_id);
  817. if (wait)
  818. ret = sst_ipc_tx_message_wait(ipc, *ipc_header,
  819. NULL, 0, NULL, 0);
  820. else
  821. ret = sst_ipc_tx_message_nowait(ipc, *ipc_header, NULL, 0);
  822. if (ret < 0)
  823. dev_err(ipc->dev, "ipc: load lib failed\n");
  824. return ret;
  825. }
  826. EXPORT_SYMBOL_GPL(skl_sst_ipc_load_library);
  827. int skl_ipc_set_d0ix(struct sst_generic_ipc *ipc, struct skl_ipc_d0ix_msg *msg)
  828. {
  829. struct skl_ipc_header header = {0};
  830. u64 *ipc_header = (u64 *)(&header);
  831. int ret;
  832. header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
  833. header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
  834. header.primary |= IPC_GLB_TYPE(IPC_MOD_SET_D0IX);
  835. header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
  836. header.primary |= IPC_MOD_ID(msg->module_id);
  837. header.extension = IPC_D0IX_WAKE(msg->wake);
  838. header.extension |= IPC_D0IX_STREAMING(msg->streaming);
  839. dev_dbg(ipc->dev, "In %s primary=%x ext=%x\n", __func__,
  840. header.primary, header.extension);
  841. /*
  842. * Use the nopm IPC here as we dont want it checking for D0iX
  843. */
  844. ret = sst_ipc_tx_message_nopm(ipc, *ipc_header, NULL, 0, NULL, 0);
  845. if (ret < 0)
  846. dev_err(ipc->dev, "ipc: set d0ix failed, err %d\n", ret);
  847. return ret;
  848. }
  849. EXPORT_SYMBOL_GPL(skl_ipc_set_d0ix);