skl-sst-ipc.c 30 KB

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