~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/intel/skylake/skl-sst-ipc.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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->tx.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_dev *skl = container_of(ipc, struct skl_dev, 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_dev *skl = container_of(ipc, struct skl_dev, 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         msg->rx.header = *ipc_header;
451         /* first process the header */
452         if (reply == IPC_GLB_REPLY_SUCCESS) {
453                 dev_dbg(ipc->dev, "ipc FW reply %x: success\n", header.primary);
454                 /* copy the rx data from the mailbox */
455                 sst_dsp_inbox_read(ipc->dsp, msg->rx.data, msg->rx.size);
456                 switch (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) {
457                 case IPC_GLB_LOAD_MULTIPLE_MODS:
458                 case IPC_GLB_LOAD_LIBRARY:
459                         skl->mod_load_complete = true;
460                         skl->mod_load_status = true;
461                         wake_up(&skl->mod_load_wait);
462                         break;
463 
464                 default:
465                         break;
466 
467                 }
468         } else {
469                 msg->errno = skl_ipc_set_reply_error_code(ipc, reply);
470                 switch (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) {
471                 case IPC_GLB_LOAD_MULTIPLE_MODS:
472                 case IPC_GLB_LOAD_LIBRARY:
473                         skl->mod_load_complete = true;
474                         skl->mod_load_status = false;
475                         wake_up(&skl->mod_load_wait);
476                         break;
477 
478                 default:
479                         break;
480 
481                 }
482         }
483 
484         spin_lock_irqsave(&ipc->dsp->spinlock, flags);
485         sst_ipc_tx_msg_reply_complete(ipc, msg);
486         spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
487 }
488 
489 irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context)
490 {
491         struct sst_dsp *dsp = context;
492         struct skl_dev *skl = dsp->thread_context;
493         struct sst_generic_ipc *ipc = &skl->ipc;
494         struct skl_ipc_header header = {0};
495         u32 hipcie, hipct, hipcte;
496         int ipc_irq = 0;
497 
498         if (dsp->intr_status & SKL_ADSPIS_CL_DMA)
499                 skl_cldma_process_intr(dsp);
500 
501         /* Here we handle IPC interrupts only */
502         if (!(dsp->intr_status & SKL_ADSPIS_IPC))
503                 return IRQ_NONE;
504 
505         hipcie = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCIE);
506         hipct = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCT);
507         hipcte = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCTE);
508 
509         /* reply message from DSP */
510         if (hipcie & SKL_ADSP_REG_HIPCIE_DONE) {
511                 sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL,
512                         SKL_ADSP_REG_HIPCCTL_DONE, 0);
513 
514                 /* clear DONE bit - tell DSP we have completed the operation */
515                 sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCIE,
516                         SKL_ADSP_REG_HIPCIE_DONE, SKL_ADSP_REG_HIPCIE_DONE);
517 
518                 ipc_irq = 1;
519 
520                 /* unmask Done interrupt */
521                 sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL,
522                         SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE);
523         }
524 
525         /* New message from DSP */
526         if (hipct & SKL_ADSP_REG_HIPCT_BUSY) {
527                 header.primary = hipct;
528                 header.extension = hipcte;
529                 dev_dbg(dsp->dev, "IPC irq: Firmware respond primary:%x\n",
530                                                 header.primary);
531                 dev_dbg(dsp->dev, "IPC irq: Firmware respond extension:%x\n",
532                                                 header.extension);
533 
534                 if (IPC_GLB_NOTIFY_RSP_TYPE(header.primary)) {
535                         /* Handle Immediate reply from DSP Core */
536                         skl_ipc_process_reply(ipc, header);
537                 } else {
538                         dev_dbg(dsp->dev, "IPC irq: Notification from firmware\n");
539                         skl_ipc_process_notification(ipc, header);
540                 }
541                 /* clear  busy interrupt */
542                 sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCT,
543                         SKL_ADSP_REG_HIPCT_BUSY, SKL_ADSP_REG_HIPCT_BUSY);
544                 ipc_irq = 1;
545         }
546 
547         if (ipc_irq == 0)
548                 return IRQ_NONE;
549 
550         skl_ipc_int_enable(dsp);
551 
552         /* continue to send any remaining messages... */
553         schedule_work(&ipc->kwork);
554 
555         return IRQ_HANDLED;
556 }
557 
558 void skl_ipc_int_enable(struct sst_dsp *ctx)
559 {
560         sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_ADSPIC,
561                         SKL_ADSPIC_IPC, SKL_ADSPIC_IPC);
562 }
563 
564 void skl_ipc_int_disable(struct sst_dsp *ctx)
565 {
566         sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPIC,
567                         SKL_ADSPIC_IPC, 0);
568 }
569 
570 void skl_ipc_op_int_enable(struct sst_dsp *ctx)
571 {
572         /* enable IPC DONE interrupt */
573         sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL,
574                 SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE);
575 
576         /* Enable IPC BUSY interrupt */
577         sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL,
578                 SKL_ADSP_REG_HIPCCTL_BUSY, SKL_ADSP_REG_HIPCCTL_BUSY);
579 }
580 
581 void skl_ipc_op_int_disable(struct sst_dsp *ctx)
582 {
583         /* disable IPC DONE interrupt */
584         sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL,
585                                         SKL_ADSP_REG_HIPCCTL_DONE, 0);
586 
587         /* Disable IPC BUSY interrupt */
588         sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL,
589                                         SKL_ADSP_REG_HIPCCTL_BUSY, 0);
590 
591 }
592 
593 bool skl_ipc_int_status(struct sst_dsp *ctx)
594 {
595         return sst_dsp_shim_read_unlocked(ctx,
596                         SKL_ADSP_REG_ADSPIS) & SKL_ADSPIS_IPC;
597 }
598 
599 int skl_ipc_init(struct device *dev, struct skl_dev *skl)
600 {
601         struct sst_generic_ipc *ipc;
602         int err;
603 
604         ipc = &skl->ipc;
605         ipc->dsp = skl->dsp;
606         ipc->dev = dev;
607 
608         ipc->tx_data_max_size = SKL_ADSP_W1_SZ;
609         ipc->rx_data_max_size = SKL_ADSP_W0_UP_SZ;
610 
611         err = sst_ipc_init(ipc);
612         if (err)
613                 return err;
614 
615         ipc->ops.tx_msg = skl_ipc_tx_msg;
616         ipc->ops.tx_data_copy = skl_ipc_tx_data_copy;
617         ipc->ops.is_dsp_busy = skl_ipc_is_dsp_busy;
618 
619         return 0;
620 }
621 
622 void skl_ipc_free(struct sst_generic_ipc *ipc)
623 {
624         /* Disable IPC DONE interrupt */
625         sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL,
626                 SKL_ADSP_REG_HIPCCTL_DONE, 0);
627 
628         /* Disable IPC BUSY interrupt */
629         sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL,
630                 SKL_ADSP_REG_HIPCCTL_BUSY, 0);
631 
632         sst_ipc_fini(ipc);
633 }
634 
635 int skl_ipc_create_pipeline(struct sst_generic_ipc *ipc,
636                 u16 ppl_mem_size, u8 ppl_type, u8 instance_id, u8 lp_mode)
637 {
638         struct skl_ipc_header header = {0};
639         struct sst_ipc_message request = {0};
640         int ret;
641 
642         header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
643         header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
644         header.primary |= IPC_GLB_TYPE(IPC_GLB_CREATE_PPL);
645         header.primary |= IPC_INSTANCE_ID(instance_id);
646         header.primary |= IPC_PPL_TYPE(ppl_type);
647         header.primary |= IPC_PPL_MEM_SIZE(ppl_mem_size);
648 
649         header.extension = IPC_PPL_LP_MODE(lp_mode);
650         request.header = *(u64 *)(&header);
651 
652         dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
653         ret = sst_ipc_tx_message_wait(ipc, request, NULL);
654         if (ret < 0) {
655                 dev_err(ipc->dev, "ipc: create pipeline fail, err: %d\n", ret);
656                 return ret;
657         }
658 
659         return ret;
660 }
661 EXPORT_SYMBOL_GPL(skl_ipc_create_pipeline);
662 
663 int skl_ipc_delete_pipeline(struct sst_generic_ipc *ipc, u8 instance_id)
664 {
665         struct skl_ipc_header header = {0};
666         struct sst_ipc_message request = {0};
667         int ret;
668 
669         header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
670         header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
671         header.primary |= IPC_GLB_TYPE(IPC_GLB_DELETE_PPL);
672         header.primary |= IPC_INSTANCE_ID(instance_id);
673         request.header = *(u64 *)(&header);
674 
675         dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
676         ret = sst_ipc_tx_message_wait(ipc, request, NULL);
677         if (ret < 0) {
678                 dev_err(ipc->dev, "ipc: delete pipeline failed, err %d\n", ret);
679                 return ret;
680         }
681 
682         return 0;
683 }
684 EXPORT_SYMBOL_GPL(skl_ipc_delete_pipeline);
685 
686 int skl_ipc_set_pipeline_state(struct sst_generic_ipc *ipc,
687                 u8 instance_id, enum skl_ipc_pipeline_state state)
688 {
689         struct skl_ipc_header header = {0};
690         struct sst_ipc_message request = {0};
691         int ret;
692 
693         header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
694         header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
695         header.primary |= IPC_GLB_TYPE(IPC_GLB_SET_PPL_STATE);
696         header.primary |= IPC_INSTANCE_ID(instance_id);
697         header.primary |= IPC_PPL_STATE(state);
698         request.header = *(u64 *)(&header);
699 
700         dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
701         ret = sst_ipc_tx_message_wait(ipc, request, NULL);
702         if (ret < 0) {
703                 dev_err(ipc->dev, "ipc: set pipeline state failed, err: %d\n", ret);
704                 return ret;
705         }
706         return ret;
707 }
708 EXPORT_SYMBOL_GPL(skl_ipc_set_pipeline_state);
709 
710 int
711 skl_ipc_save_pipeline(struct sst_generic_ipc *ipc, u8 instance_id, int dma_id)
712 {
713         struct skl_ipc_header header = {0};
714         struct sst_ipc_message request = {0};
715         int ret;
716 
717         header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
718         header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
719         header.primary |= IPC_GLB_TYPE(IPC_GLB_SAVE_PPL);
720         header.primary |= IPC_INSTANCE_ID(instance_id);
721 
722         header.extension = IPC_DMA_ID(dma_id);
723         request.header = *(u64 *)(&header);
724 
725         dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
726         ret = sst_ipc_tx_message_wait(ipc, request, NULL);
727         if (ret < 0) {
728                 dev_err(ipc->dev, "ipc: save pipeline failed, err: %d\n", ret);
729                 return ret;
730         }
731 
732         return ret;
733 }
734 EXPORT_SYMBOL_GPL(skl_ipc_save_pipeline);
735 
736 int skl_ipc_restore_pipeline(struct sst_generic_ipc *ipc, u8 instance_id)
737 {
738         struct skl_ipc_header header = {0};
739         struct sst_ipc_message request = {0};
740         int ret;
741 
742         header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
743         header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
744         header.primary |= IPC_GLB_TYPE(IPC_GLB_RESTORE_PPL);
745         header.primary |= IPC_INSTANCE_ID(instance_id);
746         request.header = *(u64 *)(&header);
747 
748         dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
749         ret = sst_ipc_tx_message_wait(ipc, request, NULL);
750         if (ret < 0) {
751                 dev_err(ipc->dev, "ipc: restore  pipeline failed, err: %d\n", ret);
752                 return ret;
753         }
754 
755         return ret;
756 }
757 EXPORT_SYMBOL_GPL(skl_ipc_restore_pipeline);
758 
759 int skl_ipc_set_dx(struct sst_generic_ipc *ipc, u8 instance_id,
760                 u16 module_id, struct skl_ipc_dxstate_info *dx)
761 {
762         struct skl_ipc_header header = {0};
763         struct sst_ipc_message request;
764         int ret;
765 
766         header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
767         header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
768         header.primary |= IPC_GLB_TYPE(IPC_MOD_SET_DX);
769         header.primary |= IPC_MOD_INSTANCE_ID(instance_id);
770         header.primary |= IPC_MOD_ID(module_id);
771 
772         request.header = *(u64 *)(&header);
773         request.data = dx;
774         request.size = sizeof(*dx);
775 
776         dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__,
777                          header.primary, header.extension);
778         ret = sst_ipc_tx_message_wait(ipc, request, NULL);
779         if (ret < 0) {
780                 dev_err(ipc->dev, "ipc: set dx failed, err %d\n", ret);
781                 return ret;
782         }
783 
784         return ret;
785 }
786 EXPORT_SYMBOL_GPL(skl_ipc_set_dx);
787 
788 int skl_ipc_init_instance(struct sst_generic_ipc *ipc,
789                 struct skl_ipc_init_instance_msg *msg, void *param_data)
790 {
791         struct skl_ipc_header header = {0};
792         struct sst_ipc_message request;
793         int ret;
794         u32 *buffer = (u32 *)param_data;
795          /* param_block_size must be in dwords */
796         u16 param_block_size = msg->param_data_size / sizeof(u32);
797 
798         print_hex_dump_debug("Param data:", DUMP_PREFIX_NONE,
799                 16, 4, buffer, param_block_size, false);
800 
801         header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
802         header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
803         header.primary |= IPC_GLB_TYPE(IPC_MOD_INIT_INSTANCE);
804         header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
805         header.primary |= IPC_MOD_ID(msg->module_id);
806 
807         header.extension = IPC_CORE_ID(msg->core_id);
808         header.extension |= IPC_PPL_INSTANCE_ID(msg->ppl_instance_id);
809         header.extension |= IPC_PARAM_BLOCK_SIZE(param_block_size);
810         header.extension |= IPC_DOMAIN(msg->domain);
811 
812         request.header = *(u64 *)(&header);
813         request.data = param_data;
814         request.size = msg->param_data_size;
815 
816         dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__,
817                          header.primary, header.extension);
818         ret = sst_ipc_tx_message_wait(ipc, request, NULL);
819 
820         if (ret < 0) {
821                 dev_err(ipc->dev, "ipc: init instance failed\n");
822                 return ret;
823         }
824 
825         return ret;
826 }
827 EXPORT_SYMBOL_GPL(skl_ipc_init_instance);
828 
829 int skl_ipc_bind_unbind(struct sst_generic_ipc *ipc,
830                 struct skl_ipc_bind_unbind_msg *msg)
831 {
832         struct skl_ipc_header header = {0};
833         struct sst_ipc_message request = {0};
834         u8 bind_unbind = msg->bind ? IPC_MOD_BIND : IPC_MOD_UNBIND;
835         int ret;
836 
837         header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
838         header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
839         header.primary |= IPC_GLB_TYPE(bind_unbind);
840         header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
841         header.primary |= IPC_MOD_ID(msg->module_id);
842 
843         header.extension = IPC_DST_MOD_ID(msg->dst_module_id);
844         header.extension |= IPC_DST_MOD_INSTANCE_ID(msg->dst_instance_id);
845         header.extension |= IPC_DST_QUEUE(msg->dst_queue);
846         header.extension |= IPC_SRC_QUEUE(msg->src_queue);
847         request.header = *(u64 *)(&header);
848 
849         dev_dbg(ipc->dev, "In %s hdr=%x ext=%x\n", __func__, header.primary,
850                          header.extension);
851         ret = sst_ipc_tx_message_wait(ipc, request, NULL);
852         if (ret < 0) {
853                 dev_err(ipc->dev, "ipc: bind/unbind failed\n");
854                 return ret;
855         }
856 
857         return ret;
858 }
859 EXPORT_SYMBOL_GPL(skl_ipc_bind_unbind);
860 
861 /*
862  * In order to load a module we need to send IPC to initiate that. DMA will
863  * performed to load the module memory. The FW supports multiple module load
864  * at single shot, so we can send IPC with N modules represented by
865  * module_cnt
866  */
867 int skl_ipc_load_modules(struct sst_generic_ipc *ipc,
868                                 u8 module_cnt, void *data)
869 {
870         struct skl_ipc_header header = {0};
871         struct sst_ipc_message request;
872         int ret;
873 
874         header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
875         header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
876         header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_MULTIPLE_MODS);
877         header.primary |= IPC_LOAD_MODULE_CNT(module_cnt);
878 
879         request.header = *(u64 *)(&header);
880         request.data = data;
881         request.size = sizeof(u16) * module_cnt;
882 
883         ret = sst_ipc_tx_message_nowait(ipc, request);
884         if (ret < 0)
885                 dev_err(ipc->dev, "ipc: load modules failed :%d\n", ret);
886 
887         return ret;
888 }
889 EXPORT_SYMBOL_GPL(skl_ipc_load_modules);
890 
891 int skl_ipc_unload_modules(struct sst_generic_ipc *ipc, u8 module_cnt,
892                                                         void *data)
893 {
894         struct skl_ipc_header header = {0};
895         struct sst_ipc_message request;
896         int ret;
897 
898         header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
899         header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
900         header.primary |= IPC_GLB_TYPE(IPC_GLB_UNLOAD_MULTIPLE_MODS);
901         header.primary |= IPC_LOAD_MODULE_CNT(module_cnt);
902 
903         request.header = *(u64 *)(&header);
904         request.data = data;
905         request.size = sizeof(u16) * module_cnt;
906 
907         ret = sst_ipc_tx_message_wait(ipc, request, NULL);
908         if (ret < 0)
909                 dev_err(ipc->dev, "ipc: unload modules failed :%d\n", ret);
910 
911         return ret;
912 }
913 EXPORT_SYMBOL_GPL(skl_ipc_unload_modules);
914 
915 int skl_ipc_set_large_config(struct sst_generic_ipc *ipc,
916                 struct skl_ipc_large_config_msg *msg, u32 *param)
917 {
918         struct skl_ipc_header header = {0};
919         struct sst_ipc_message request;
920         int ret = 0;
921         size_t sz_remaining, tx_size, data_offset;
922 
923         header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
924         header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
925         header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_SET);
926         header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
927         header.primary |= IPC_MOD_ID(msg->module_id);
928 
929         header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size);
930         header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id);
931         header.extension |= IPC_FINAL_BLOCK(0);
932         header.extension |= IPC_INITIAL_BLOCK(1);
933 
934         sz_remaining = msg->param_data_size;
935         data_offset = 0;
936         while (sz_remaining != 0) {
937                 tx_size = sz_remaining > SKL_ADSP_W1_SZ
938                                 ? SKL_ADSP_W1_SZ : sz_remaining;
939                 if (tx_size == sz_remaining)
940                         header.extension |= IPC_FINAL_BLOCK(1);
941 
942                 dev_dbg(ipc->dev, "In %s primary=%#x ext=%#x\n", __func__,
943                         header.primary, header.extension);
944                 dev_dbg(ipc->dev, "transmitting offset: %#x, size: %#x\n",
945                         (unsigned)data_offset, (unsigned)tx_size);
946 
947                 request.header = *(u64 *)(&header);
948                 request.data = ((char *)param) + data_offset;
949                 request.size = tx_size;
950                 ret = sst_ipc_tx_message_wait(ipc, request, NULL);
951                 if (ret < 0) {
952                         dev_err(ipc->dev,
953                                 "ipc: set large config fail, err: %d\n", ret);
954                         return ret;
955                 }
956                 sz_remaining -= tx_size;
957                 data_offset = msg->param_data_size - sz_remaining;
958 
959                 /* clear the fields */
960                 header.extension &= IPC_INITIAL_BLOCK_CLEAR;
961                 header.extension &= IPC_DATA_OFFSET_SZ_CLEAR;
962                 /* fill the fields */
963                 header.extension |= IPC_INITIAL_BLOCK(0);
964                 header.extension |= IPC_DATA_OFFSET_SZ(data_offset);
965         }
966 
967         return ret;
968 }
969 EXPORT_SYMBOL_GPL(skl_ipc_set_large_config);
970 
971 int skl_ipc_get_large_config(struct sst_generic_ipc *ipc,
972                 struct skl_ipc_large_config_msg *msg,
973                 u32 **payload, size_t *bytes)
974 {
975         struct skl_ipc_header header = {0};
976         struct sst_ipc_message request, reply = {0};
977         unsigned int *buf;
978         int ret;
979 
980         reply.data = kzalloc(SKL_ADSP_W1_SZ, GFP_KERNEL);
981         if (!reply.data)
982                 return -ENOMEM;
983 
984         header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
985         header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
986         header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_GET);
987         header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
988         header.primary |= IPC_MOD_ID(msg->module_id);
989 
990         header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size);
991         header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id);
992         header.extension |= IPC_FINAL_BLOCK(1);
993         header.extension |= IPC_INITIAL_BLOCK(1);
994 
995         request.header = *(u64 *)&header;
996         request.data = *payload;
997         request.size = *bytes;
998         reply.size = SKL_ADSP_W1_SZ;
999 
1000         ret = sst_ipc_tx_message_wait(ipc, request, &reply);
1001         if (ret < 0)
1002                 dev_err(ipc->dev, "ipc: get large config fail, err: %d\n", ret);
1003 
1004         reply.size = (reply.header >> 32) & IPC_DATA_OFFSET_SZ_MASK;
1005         buf = krealloc(reply.data, reply.size, GFP_KERNEL);
1006         if (!buf) {
1007                 kfree(reply.data);
1008                 return -ENOMEM;
1009         }
1010         *payload = buf;
1011         *bytes = reply.size;
1012 
1013         return ret;
1014 }
1015 EXPORT_SYMBOL_GPL(skl_ipc_get_large_config);
1016 
1017 int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc,
1018                                 u8 dma_id, u8 table_id, bool wait)
1019 {
1020         struct skl_ipc_header header = {0};
1021         struct sst_ipc_message request = {0};
1022         int ret = 0;
1023 
1024         header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
1025         header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
1026         header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_LIBRARY);
1027         header.primary |= IPC_MOD_INSTANCE_ID(table_id);
1028         header.primary |= IPC_MOD_ID(dma_id);
1029         request.header = *(u64 *)(&header);
1030 
1031         if (wait)
1032                 ret = sst_ipc_tx_message_wait(ipc, request, NULL);
1033         else
1034                 ret = sst_ipc_tx_message_nowait(ipc, request);
1035 
1036         if (ret < 0)
1037                 dev_err(ipc->dev, "ipc: load lib failed\n");
1038 
1039         return ret;
1040 }
1041 EXPORT_SYMBOL_GPL(skl_sst_ipc_load_library);
1042 
1043 int skl_ipc_set_d0ix(struct sst_generic_ipc *ipc, struct skl_ipc_d0ix_msg *msg)
1044 {
1045         struct skl_ipc_header header = {0};
1046         struct sst_ipc_message request = {0};
1047         int ret;
1048 
1049         header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
1050         header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
1051         header.primary |= IPC_GLB_TYPE(IPC_MOD_SET_D0IX);
1052         header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
1053         header.primary |= IPC_MOD_ID(msg->module_id);
1054 
1055         header.extension = IPC_D0IX_WAKE(msg->wake);
1056         header.extension |= IPC_D0IX_STREAMING(msg->streaming);
1057         request.header = *(u64 *)(&header);
1058 
1059         dev_dbg(ipc->dev, "In %s primary=%x ext=%x\n", __func__,
1060                         header.primary, header.extension);
1061 
1062         /*
1063          * Use the nopm IPC here as we dont want it checking for D0iX
1064          */
1065         ret = sst_ipc_tx_message_nopm(ipc, request, NULL);
1066         if (ret < 0)
1067                 dev_err(ipc->dev, "ipc: set d0ix failed, err %d\n", ret);
1068 
1069         return ret;
1070 }
1071 EXPORT_SYMBOL_GPL(skl_ipc_set_d0ix);
1072 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php