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