Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * skl-sst-ipc.c - Intel skl IPC Support
0004  *
0005  * Copyright (C) 2014-15, Intel Corporation.
0006  */
0007 #include <linux/device.h>
0008 
0009 #include "../common/sst-dsp.h"
0010 #include "../common/sst-dsp-priv.h"
0011 #include "skl.h"
0012 #include "skl-sst-dsp.h"
0013 #include "skl-sst-ipc.h"
0014 #include "sound/hdaudio_ext.h"
0015 
0016 
0017 #define IPC_IXC_STATUS_BITS     24
0018 
0019 /* Global Message - Generic */
0020 #define IPC_GLB_TYPE_SHIFT      24
0021 #define IPC_GLB_TYPE_MASK       (0xf << IPC_GLB_TYPE_SHIFT)
0022 #define IPC_GLB_TYPE(x)         ((x) << IPC_GLB_TYPE_SHIFT)
0023 
0024 /* Global Message - Reply */
0025 #define IPC_GLB_REPLY_STATUS_SHIFT  24
0026 #define IPC_GLB_REPLY_STATUS_MASK   ((0x1 << IPC_GLB_REPLY_STATUS_SHIFT) - 1)
0027 #define IPC_GLB_REPLY_STATUS(x)     ((x) << IPC_GLB_REPLY_STATUS_SHIFT)
0028 
0029 #define IPC_GLB_REPLY_TYPE_SHIFT    29
0030 #define IPC_GLB_REPLY_TYPE_MASK     0x1F
0031 #define IPC_GLB_REPLY_TYPE(x)       (((x) >> IPC_GLB_REPLY_TYPE_SHIFT) \
0032                     & IPC_GLB_RPLY_TYPE_MASK)
0033 
0034 #define IPC_TIMEOUT_MSECS       3000
0035 
0036 #define IPC_EMPTY_LIST_SIZE     8
0037 
0038 #define IPC_MSG_TARGET_SHIFT        30
0039 #define IPC_MSG_TARGET_MASK     0x1
0040 #define IPC_MSG_TARGET(x)       (((x) & IPC_MSG_TARGET_MASK) \
0041                     << IPC_MSG_TARGET_SHIFT)
0042 
0043 #define IPC_MSG_DIR_SHIFT       29
0044 #define IPC_MSG_DIR_MASK        0x1
0045 #define IPC_MSG_DIR(x)          (((x) & IPC_MSG_DIR_MASK) \
0046                     << IPC_MSG_DIR_SHIFT)
0047 /* Global Notification Message */
0048 #define IPC_GLB_NOTIFY_TYPE_SHIFT   16
0049 #define IPC_GLB_NOTIFY_TYPE_MASK    0xFF
0050 #define IPC_GLB_NOTIFY_TYPE(x)      (((x) >> IPC_GLB_NOTIFY_TYPE_SHIFT) \
0051                     & IPC_GLB_NOTIFY_TYPE_MASK)
0052 
0053 #define IPC_GLB_NOTIFY_MSG_TYPE_SHIFT   24
0054 #define IPC_GLB_NOTIFY_MSG_TYPE_MASK    0x1F
0055 #define IPC_GLB_NOTIFY_MSG_TYPE(x)  (((x) >> IPC_GLB_NOTIFY_MSG_TYPE_SHIFT) \
0056                         & IPC_GLB_NOTIFY_MSG_TYPE_MASK)
0057 
0058 #define IPC_GLB_NOTIFY_RSP_SHIFT    29
0059 #define IPC_GLB_NOTIFY_RSP_MASK     0x1
0060 #define IPC_GLB_NOTIFY_RSP_TYPE(x)  (((x) >> IPC_GLB_NOTIFY_RSP_SHIFT) \
0061                     & IPC_GLB_NOTIFY_RSP_MASK)
0062 
0063 /* Pipeline operations */
0064 
0065 /* Create pipeline message */
0066 #define IPC_PPL_MEM_SIZE_SHIFT      0
0067 #define IPC_PPL_MEM_SIZE_MASK       0x7FF
0068 #define IPC_PPL_MEM_SIZE(x)     (((x) & IPC_PPL_MEM_SIZE_MASK) \
0069                     << IPC_PPL_MEM_SIZE_SHIFT)
0070 
0071 #define IPC_PPL_TYPE_SHIFT      11
0072 #define IPC_PPL_TYPE_MASK       0x1F
0073 #define IPC_PPL_TYPE(x)         (((x) & IPC_PPL_TYPE_MASK) \
0074                     << IPC_PPL_TYPE_SHIFT)
0075 
0076 #define IPC_INSTANCE_ID_SHIFT       16
0077 #define IPC_INSTANCE_ID_MASK        0xFF
0078 #define IPC_INSTANCE_ID(x)      (((x) & IPC_INSTANCE_ID_MASK) \
0079                     << IPC_INSTANCE_ID_SHIFT)
0080 
0081 #define IPC_PPL_LP_MODE_SHIFT           0
0082 #define IPC_PPL_LP_MODE_MASK            0x1
0083 #define IPC_PPL_LP_MODE(x)              (((x) & IPC_PPL_LP_MODE_MASK) \
0084                     << IPC_PPL_LP_MODE_SHIFT)
0085 
0086 /* Set pipeline state message */
0087 #define IPC_PPL_STATE_SHIFT     0
0088 #define IPC_PPL_STATE_MASK      0x1F
0089 #define IPC_PPL_STATE(x)        (((x) & IPC_PPL_STATE_MASK) \
0090                     << IPC_PPL_STATE_SHIFT)
0091 
0092 /* Module operations primary register */
0093 #define IPC_MOD_ID_SHIFT        0
0094 #define IPC_MOD_ID_MASK     0xFFFF
0095 #define IPC_MOD_ID(x)       (((x) & IPC_MOD_ID_MASK) \
0096                     << IPC_MOD_ID_SHIFT)
0097 
0098 #define IPC_MOD_INSTANCE_ID_SHIFT   16
0099 #define IPC_MOD_INSTANCE_ID_MASK    0xFF
0100 #define IPC_MOD_INSTANCE_ID(x)  (((x) & IPC_MOD_INSTANCE_ID_MASK) \
0101                     << IPC_MOD_INSTANCE_ID_SHIFT)
0102 
0103 /* Init instance message extension register */
0104 #define IPC_PARAM_BLOCK_SIZE_SHIFT  0
0105 #define IPC_PARAM_BLOCK_SIZE_MASK   0xFFFF
0106 #define IPC_PARAM_BLOCK_SIZE(x)     (((x) & IPC_PARAM_BLOCK_SIZE_MASK) \
0107                     << IPC_PARAM_BLOCK_SIZE_SHIFT)
0108 
0109 #define IPC_PPL_INSTANCE_ID_SHIFT   16
0110 #define IPC_PPL_INSTANCE_ID_MASK    0xFF
0111 #define IPC_PPL_INSTANCE_ID(x)      (((x) & IPC_PPL_INSTANCE_ID_MASK) \
0112                     << IPC_PPL_INSTANCE_ID_SHIFT)
0113 
0114 #define IPC_CORE_ID_SHIFT       24
0115 #define IPC_CORE_ID_MASK        0x1F
0116 #define IPC_CORE_ID(x)          (((x) & IPC_CORE_ID_MASK) \
0117                     << IPC_CORE_ID_SHIFT)
0118 
0119 #define IPC_DOMAIN_SHIFT                28
0120 #define IPC_DOMAIN_MASK                 0x1
0121 #define IPC_DOMAIN(x)                   (((x) & IPC_DOMAIN_MASK) \
0122                     << IPC_DOMAIN_SHIFT)
0123 
0124 /* Bind/Unbind message extension register */
0125 #define IPC_DST_MOD_ID_SHIFT        0
0126 #define IPC_DST_MOD_ID(x)       (((x) & IPC_MOD_ID_MASK) \
0127                     << IPC_DST_MOD_ID_SHIFT)
0128 
0129 #define IPC_DST_MOD_INSTANCE_ID_SHIFT 16
0130 #define IPC_DST_MOD_INSTANCE_ID(x)  (((x) & IPC_MOD_INSTANCE_ID_MASK) \
0131                     << IPC_DST_MOD_INSTANCE_ID_SHIFT)
0132 
0133 #define IPC_DST_QUEUE_SHIFT     24
0134 #define IPC_DST_QUEUE_MASK      0x7
0135 #define IPC_DST_QUEUE(x)        (((x) & IPC_DST_QUEUE_MASK) \
0136                     << IPC_DST_QUEUE_SHIFT)
0137 
0138 #define IPC_SRC_QUEUE_SHIFT     27
0139 #define IPC_SRC_QUEUE_MASK      0x7
0140 #define IPC_SRC_QUEUE(x)        (((x) & IPC_SRC_QUEUE_MASK) \
0141                     << IPC_SRC_QUEUE_SHIFT)
0142 /* Load Module count */
0143 #define IPC_LOAD_MODULE_SHIFT       0
0144 #define IPC_LOAD_MODULE_MASK        0xFF
0145 #define IPC_LOAD_MODULE_CNT(x)      (((x) & IPC_LOAD_MODULE_MASK) \
0146                     << IPC_LOAD_MODULE_SHIFT)
0147 
0148 /* Save pipeline messgae extension register */
0149 #define IPC_DMA_ID_SHIFT        0
0150 #define IPC_DMA_ID_MASK         0x1F
0151 #define IPC_DMA_ID(x)           (((x) & IPC_DMA_ID_MASK) \
0152                     << IPC_DMA_ID_SHIFT)
0153 /* Large Config message extension register */
0154 #define IPC_DATA_OFFSET_SZ_SHIFT    0
0155 #define IPC_DATA_OFFSET_SZ_MASK     0xFFFFF
0156 #define IPC_DATA_OFFSET_SZ(x)       (((x) & IPC_DATA_OFFSET_SZ_MASK) \
0157                     << IPC_DATA_OFFSET_SZ_SHIFT)
0158 #define IPC_DATA_OFFSET_SZ_CLEAR    ~(IPC_DATA_OFFSET_SZ_MASK \
0159                       << IPC_DATA_OFFSET_SZ_SHIFT)
0160 
0161 #define IPC_LARGE_PARAM_ID_SHIFT    20
0162 #define IPC_LARGE_PARAM_ID_MASK     0xFF
0163 #define IPC_LARGE_PARAM_ID(x)       (((x) & IPC_LARGE_PARAM_ID_MASK) \
0164                     << IPC_LARGE_PARAM_ID_SHIFT)
0165 
0166 #define IPC_FINAL_BLOCK_SHIFT       28
0167 #define IPC_FINAL_BLOCK_MASK        0x1
0168 #define IPC_FINAL_BLOCK(x)      (((x) & IPC_FINAL_BLOCK_MASK) \
0169                     << IPC_FINAL_BLOCK_SHIFT)
0170 
0171 #define IPC_INITIAL_BLOCK_SHIFT     29
0172 #define IPC_INITIAL_BLOCK_MASK      0x1
0173 #define IPC_INITIAL_BLOCK(x)        (((x) & IPC_INITIAL_BLOCK_MASK) \
0174                     << IPC_INITIAL_BLOCK_SHIFT)
0175 #define IPC_INITIAL_BLOCK_CLEAR     ~(IPC_INITIAL_BLOCK_MASK \
0176                       << IPC_INITIAL_BLOCK_SHIFT)
0177 /* Set D0ix IPC extension register */
0178 #define IPC_D0IX_WAKE_SHIFT     0
0179 #define IPC_D0IX_WAKE_MASK      0x1
0180 #define IPC_D0IX_WAKE(x)        (((x) & IPC_D0IX_WAKE_MASK) \
0181                     << IPC_D0IX_WAKE_SHIFT)
0182 
0183 #define IPC_D0IX_STREAMING_SHIFT    1
0184 #define IPC_D0IX_STREAMING_MASK     0x1
0185 #define IPC_D0IX_STREAMING(x)       (((x) & IPC_D0IX_STREAMING_MASK) \
0186                     << IPC_D0IX_STREAMING_SHIFT)
0187 
0188 
0189 enum skl_ipc_msg_target {
0190     IPC_FW_GEN_MSG = 0,
0191     IPC_MOD_MSG = 1
0192 };
0193 
0194 enum skl_ipc_msg_direction {
0195     IPC_MSG_REQUEST = 0,
0196     IPC_MSG_REPLY = 1
0197 };
0198 
0199 /* Global Message Types */
0200 enum skl_ipc_glb_type {
0201     IPC_GLB_GET_FW_VERSION = 0, /* Retrieves firmware version */
0202     IPC_GLB_LOAD_MULTIPLE_MODS = 15,
0203     IPC_GLB_UNLOAD_MULTIPLE_MODS = 16,
0204     IPC_GLB_CREATE_PPL = 17,
0205     IPC_GLB_DELETE_PPL = 18,
0206     IPC_GLB_SET_PPL_STATE = 19,
0207     IPC_GLB_GET_PPL_STATE = 20,
0208     IPC_GLB_GET_PPL_CONTEXT_SIZE = 21,
0209     IPC_GLB_SAVE_PPL = 22,
0210     IPC_GLB_RESTORE_PPL = 23,
0211     IPC_GLB_LOAD_LIBRARY = 24,
0212     IPC_GLB_NOTIFY = 26,
0213     IPC_GLB_MAX_IPC_MSG_NUMBER = 31 /* Maximum message number */
0214 };
0215 
0216 enum skl_ipc_glb_reply {
0217     IPC_GLB_REPLY_SUCCESS = 0,
0218 
0219     IPC_GLB_REPLY_UNKNOWN_MSG_TYPE = 1,
0220     IPC_GLB_REPLY_ERROR_INVALID_PARAM = 2,
0221 
0222     IPC_GLB_REPLY_BUSY = 3,
0223     IPC_GLB_REPLY_PENDING = 4,
0224     IPC_GLB_REPLY_FAILURE = 5,
0225     IPC_GLB_REPLY_INVALID_REQUEST = 6,
0226 
0227     IPC_GLB_REPLY_OUT_OF_MEMORY = 7,
0228     IPC_GLB_REPLY_OUT_OF_MIPS = 8,
0229 
0230     IPC_GLB_REPLY_INVALID_RESOURCE_ID = 9,
0231     IPC_GLB_REPLY_INVALID_RESOURCE_STATE = 10,
0232 
0233     IPC_GLB_REPLY_MOD_MGMT_ERROR = 100,
0234     IPC_GLB_REPLY_MOD_LOAD_CL_FAILED = 101,
0235     IPC_GLB_REPLY_MOD_LOAD_INVALID_HASH = 102,
0236 
0237     IPC_GLB_REPLY_MOD_UNLOAD_INST_EXIST = 103,
0238     IPC_GLB_REPLY_MOD_NOT_INITIALIZED = 104,
0239 
0240     IPC_GLB_REPLY_INVALID_CONFIG_PARAM_ID = 120,
0241     IPC_GLB_REPLY_INVALID_CONFIG_DATA_LEN = 121,
0242     IPC_GLB_REPLY_GATEWAY_NOT_INITIALIZED = 140,
0243     IPC_GLB_REPLY_GATEWAY_NOT_EXIST = 141,
0244     IPC_GLB_REPLY_SCLK_ALREADY_RUNNING = 150,
0245     IPC_GLB_REPLY_MCLK_ALREADY_RUNNING = 151,
0246 
0247     IPC_GLB_REPLY_PPL_NOT_INITIALIZED = 160,
0248     IPC_GLB_REPLY_PPL_NOT_EXIST = 161,
0249     IPC_GLB_REPLY_PPL_SAVE_FAILED = 162,
0250     IPC_GLB_REPLY_PPL_RESTORE_FAILED = 163,
0251 
0252     IPC_MAX_STATUS = ((1<<IPC_IXC_STATUS_BITS)-1)
0253 };
0254 
0255 enum skl_ipc_notification_type {
0256     IPC_GLB_NOTIFY_GLITCH = 0,
0257     IPC_GLB_NOTIFY_OVERRUN = 1,
0258     IPC_GLB_NOTIFY_UNDERRUN = 2,
0259     IPC_GLB_NOTIFY_END_STREAM = 3,
0260     IPC_GLB_NOTIFY_PHRASE_DETECTED = 4,
0261     IPC_GLB_NOTIFY_RESOURCE_EVENT = 5,
0262     IPC_GLB_NOTIFY_LOG_BUFFER_STATUS = 6,
0263     IPC_GLB_NOTIFY_TIMESTAMP_CAPTURED = 7,
0264     IPC_GLB_NOTIFY_FW_READY = 8
0265 };
0266 
0267 /* Module Message Types */
0268 enum skl_ipc_module_msg {
0269     IPC_MOD_INIT_INSTANCE = 0,
0270     IPC_MOD_CONFIG_GET = 1,
0271     IPC_MOD_CONFIG_SET = 2,
0272     IPC_MOD_LARGE_CONFIG_GET = 3,
0273     IPC_MOD_LARGE_CONFIG_SET = 4,
0274     IPC_MOD_BIND = 5,
0275     IPC_MOD_UNBIND = 6,
0276     IPC_MOD_SET_DX = 7,
0277     IPC_MOD_SET_D0IX = 8
0278 };
0279 
0280 void skl_ipc_tx_data_copy(struct ipc_message *msg, char *tx_data,
0281         size_t tx_size)
0282 {
0283     if (tx_size)
0284         memcpy(msg->tx.data, tx_data, tx_size);
0285 }
0286 
0287 static bool skl_ipc_is_dsp_busy(struct sst_dsp *dsp)
0288 {
0289     u32 hipci;
0290 
0291     hipci = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCI);
0292     return (hipci & SKL_ADSP_REG_HIPCI_BUSY);
0293 }
0294 
0295 /* Lock to be held by caller */
0296 static void skl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg)
0297 {
0298     struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->tx.header);
0299 
0300     if (msg->tx.size)
0301         sst_dsp_outbox_write(ipc->dsp, msg->tx.data, msg->tx.size);
0302     sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCIE,
0303                         header->extension);
0304     sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCI,
0305         header->primary | SKL_ADSP_REG_HIPCI_BUSY);
0306 }
0307 
0308 int skl_ipc_check_D0i0(struct sst_dsp *dsp, bool state)
0309 {
0310     int ret;
0311 
0312     /* check D0i3 support */
0313     if (!dsp->fw_ops.set_state_D0i0)
0314         return 0;
0315 
0316     /* Attempt D0i0 or D0i3 based on state */
0317     if (state)
0318         ret = dsp->fw_ops.set_state_D0i0(dsp);
0319     else
0320         ret = dsp->fw_ops.set_state_D0i3(dsp);
0321 
0322     return ret;
0323 }
0324 
0325 static struct ipc_message *skl_ipc_reply_get_msg(struct sst_generic_ipc *ipc,
0326                 u64 ipc_header)
0327 {
0328     struct ipc_message *msg =  NULL;
0329     struct skl_ipc_header *header = (struct skl_ipc_header *)(&ipc_header);
0330 
0331     if (list_empty(&ipc->rx_list)) {
0332         dev_err(ipc->dev, "ipc: rx list is empty but received 0x%x\n",
0333             header->primary);
0334         goto out;
0335     }
0336 
0337     msg = list_first_entry(&ipc->rx_list, struct ipc_message, list);
0338 
0339     list_del(&msg->list);
0340 out:
0341     return msg;
0342 
0343 }
0344 
0345 int skl_ipc_process_notification(struct sst_generic_ipc *ipc,
0346         struct skl_ipc_header header)
0347 {
0348     struct skl_dev *skl = container_of(ipc, struct skl_dev, ipc);
0349 
0350     if (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) {
0351         switch (IPC_GLB_NOTIFY_TYPE(header.primary)) {
0352 
0353         case IPC_GLB_NOTIFY_UNDERRUN:
0354             dev_err(ipc->dev, "FW Underrun %x\n", header.primary);
0355             break;
0356 
0357         case IPC_GLB_NOTIFY_RESOURCE_EVENT:
0358             dev_err(ipc->dev, "MCPS Budget Violation: %x\n",
0359                         header.primary);
0360             break;
0361 
0362         case IPC_GLB_NOTIFY_FW_READY:
0363             skl->boot_complete = true;
0364             wake_up(&skl->boot_wait);
0365             break;
0366 
0367         case IPC_GLB_NOTIFY_PHRASE_DETECTED:
0368             dev_dbg(ipc->dev, "***** Phrase Detected **********\n");
0369 
0370             /*
0371              * Per HW recomendation, After phrase detection,
0372              * clear the CGCTL.MISCBDCGE.
0373              *
0374              * This will be set back on stream closure
0375              */
0376             skl->enable_miscbdcge(ipc->dev, false);
0377             skl->miscbdcg_disabled = true;
0378             break;
0379 
0380         default:
0381             dev_err(ipc->dev, "ipc: Unhandled error msg=%x\n",
0382                         header.primary);
0383             break;
0384         }
0385     }
0386 
0387     return 0;
0388 }
0389 
0390 struct skl_ipc_err_map {
0391     const char *msg;
0392     enum skl_ipc_glb_reply reply;
0393     int err;
0394 };
0395 
0396 static struct skl_ipc_err_map skl_err_map[] = {
0397     {"DSP out of memory", IPC_GLB_REPLY_OUT_OF_MEMORY, -ENOMEM},
0398     {"DSP busy", IPC_GLB_REPLY_BUSY, -EBUSY},
0399     {"SCLK already running", IPC_GLB_REPLY_SCLK_ALREADY_RUNNING,
0400             IPC_GLB_REPLY_SCLK_ALREADY_RUNNING},
0401     {"MCLK already running", IPC_GLB_REPLY_MCLK_ALREADY_RUNNING,
0402             IPC_GLB_REPLY_MCLK_ALREADY_RUNNING},
0403 };
0404 
0405 static int skl_ipc_set_reply_error_code(struct sst_generic_ipc *ipc, u32 reply)
0406 {
0407     int i;
0408 
0409     for (i = 0; i < ARRAY_SIZE(skl_err_map); i++) {
0410         if (skl_err_map[i].reply == reply)
0411             break;
0412     }
0413 
0414     if (i == ARRAY_SIZE(skl_err_map)) {
0415         dev_err(ipc->dev, "ipc FW reply: %d FW Error Code: %u\n",
0416                 reply,
0417                 ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp));
0418         return -EINVAL;
0419     }
0420 
0421     if (skl_err_map[i].err < 0)
0422         dev_err(ipc->dev, "ipc FW reply: %s FW Error Code: %u\n",
0423                 skl_err_map[i].msg,
0424                 ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp));
0425     else
0426         dev_info(ipc->dev, "ipc FW reply: %s FW Error Code: %u\n",
0427                 skl_err_map[i].msg,
0428                 ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp));
0429 
0430     return skl_err_map[i].err;
0431 }
0432 
0433 void skl_ipc_process_reply(struct sst_generic_ipc *ipc,
0434         struct skl_ipc_header header)
0435 {
0436     struct ipc_message *msg;
0437     u32 reply = header.primary & IPC_GLB_REPLY_STATUS_MASK;
0438     u64 *ipc_header = (u64 *)(&header);
0439     struct skl_dev *skl = container_of(ipc, struct skl_dev, ipc);
0440     unsigned long flags;
0441 
0442     spin_lock_irqsave(&ipc->dsp->spinlock, flags);
0443     msg = skl_ipc_reply_get_msg(ipc, *ipc_header);
0444     spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
0445     if (msg == NULL) {
0446         dev_dbg(ipc->dev, "ipc: rx list is empty\n");
0447         return;
0448     }
0449 
0450     msg->rx.header = *ipc_header;
0451     /* first process the header */
0452     if (reply == IPC_GLB_REPLY_SUCCESS) {
0453         dev_dbg(ipc->dev, "ipc FW reply %x: success\n", header.primary);
0454         /* copy the rx data from the mailbox */
0455         sst_dsp_inbox_read(ipc->dsp, msg->rx.data, msg->rx.size);
0456         switch (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) {
0457         case IPC_GLB_LOAD_MULTIPLE_MODS:
0458         case IPC_GLB_LOAD_LIBRARY:
0459             skl->mod_load_complete = true;
0460             skl->mod_load_status = true;
0461             wake_up(&skl->mod_load_wait);
0462             break;
0463 
0464         default:
0465             break;
0466 
0467         }
0468     } else {
0469         msg->errno = skl_ipc_set_reply_error_code(ipc, reply);
0470         switch (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) {
0471         case IPC_GLB_LOAD_MULTIPLE_MODS:
0472         case IPC_GLB_LOAD_LIBRARY:
0473             skl->mod_load_complete = true;
0474             skl->mod_load_status = false;
0475             wake_up(&skl->mod_load_wait);
0476             break;
0477 
0478         default:
0479             break;
0480 
0481         }
0482     }
0483 
0484     spin_lock_irqsave(&ipc->dsp->spinlock, flags);
0485     sst_ipc_tx_msg_reply_complete(ipc, msg);
0486     spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
0487 }
0488 
0489 irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context)
0490 {
0491     struct sst_dsp *dsp = context;
0492     struct skl_dev *skl = dsp->thread_context;
0493     struct sst_generic_ipc *ipc = &skl->ipc;
0494     struct skl_ipc_header header = {0};
0495     u32 hipcie, hipct, hipcte;
0496     int ipc_irq = 0;
0497 
0498     if (dsp->intr_status & SKL_ADSPIS_CL_DMA)
0499         skl_cldma_process_intr(dsp);
0500 
0501     /* Here we handle IPC interrupts only */
0502     if (!(dsp->intr_status & SKL_ADSPIS_IPC))
0503         return IRQ_NONE;
0504 
0505     hipcie = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCIE);
0506     hipct = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCT);
0507     hipcte = sst_dsp_shim_read_unlocked(dsp, SKL_ADSP_REG_HIPCTE);
0508 
0509     /* reply message from DSP */
0510     if (hipcie & SKL_ADSP_REG_HIPCIE_DONE) {
0511         sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL,
0512             SKL_ADSP_REG_HIPCCTL_DONE, 0);
0513 
0514         /* clear DONE bit - tell DSP we have completed the operation */
0515         sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCIE,
0516             SKL_ADSP_REG_HIPCIE_DONE, SKL_ADSP_REG_HIPCIE_DONE);
0517 
0518         ipc_irq = 1;
0519 
0520         /* unmask Done interrupt */
0521         sst_dsp_shim_update_bits(dsp, SKL_ADSP_REG_HIPCCTL,
0522             SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE);
0523     }
0524 
0525     /* New message from DSP */
0526     if (hipct & SKL_ADSP_REG_HIPCT_BUSY) {
0527         header.primary = hipct;
0528         header.extension = hipcte;
0529         dev_dbg(dsp->dev, "IPC irq: Firmware respond primary:%x\n",
0530                         header.primary);
0531         dev_dbg(dsp->dev, "IPC irq: Firmware respond extension:%x\n",
0532                         header.extension);
0533 
0534         if (IPC_GLB_NOTIFY_RSP_TYPE(header.primary)) {
0535             /* Handle Immediate reply from DSP Core */
0536             skl_ipc_process_reply(ipc, header);
0537         } else {
0538             dev_dbg(dsp->dev, "IPC irq: Notification from firmware\n");
0539             skl_ipc_process_notification(ipc, header);
0540         }
0541         /* clear  busy interrupt */
0542         sst_dsp_shim_update_bits_forced(dsp, SKL_ADSP_REG_HIPCT,
0543             SKL_ADSP_REG_HIPCT_BUSY, SKL_ADSP_REG_HIPCT_BUSY);
0544         ipc_irq = 1;
0545     }
0546 
0547     if (ipc_irq == 0)
0548         return IRQ_NONE;
0549 
0550     skl_ipc_int_enable(dsp);
0551 
0552     /* continue to send any remaining messages... */
0553     schedule_work(&ipc->kwork);
0554 
0555     return IRQ_HANDLED;
0556 }
0557 
0558 void skl_ipc_int_enable(struct sst_dsp *ctx)
0559 {
0560     sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_ADSPIC,
0561             SKL_ADSPIC_IPC, SKL_ADSPIC_IPC);
0562 }
0563 
0564 void skl_ipc_int_disable(struct sst_dsp *ctx)
0565 {
0566     sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPIC,
0567             SKL_ADSPIC_IPC, 0);
0568 }
0569 
0570 void skl_ipc_op_int_enable(struct sst_dsp *ctx)
0571 {
0572     /* enable IPC DONE interrupt */
0573     sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL,
0574         SKL_ADSP_REG_HIPCCTL_DONE, SKL_ADSP_REG_HIPCCTL_DONE);
0575 
0576     /* Enable IPC BUSY interrupt */
0577     sst_dsp_shim_update_bits(ctx, SKL_ADSP_REG_HIPCCTL,
0578         SKL_ADSP_REG_HIPCCTL_BUSY, SKL_ADSP_REG_HIPCCTL_BUSY);
0579 }
0580 
0581 void skl_ipc_op_int_disable(struct sst_dsp *ctx)
0582 {
0583     /* disable IPC DONE interrupt */
0584     sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL,
0585                     SKL_ADSP_REG_HIPCCTL_DONE, 0);
0586 
0587     /* Disable IPC BUSY interrupt */
0588     sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_HIPCCTL,
0589                     SKL_ADSP_REG_HIPCCTL_BUSY, 0);
0590 
0591 }
0592 
0593 bool skl_ipc_int_status(struct sst_dsp *ctx)
0594 {
0595     return sst_dsp_shim_read_unlocked(ctx,
0596             SKL_ADSP_REG_ADSPIS) & SKL_ADSPIS_IPC;
0597 }
0598 
0599 int skl_ipc_init(struct device *dev, struct skl_dev *skl)
0600 {
0601     struct sst_generic_ipc *ipc;
0602     int err;
0603 
0604     ipc = &skl->ipc;
0605     ipc->dsp = skl->dsp;
0606     ipc->dev = dev;
0607 
0608     ipc->tx_data_max_size = SKL_ADSP_W1_SZ;
0609     ipc->rx_data_max_size = SKL_ADSP_W0_UP_SZ;
0610 
0611     err = sst_ipc_init(ipc);
0612     if (err)
0613         return err;
0614 
0615     ipc->ops.tx_msg = skl_ipc_tx_msg;
0616     ipc->ops.tx_data_copy = skl_ipc_tx_data_copy;
0617     ipc->ops.is_dsp_busy = skl_ipc_is_dsp_busy;
0618 
0619     return 0;
0620 }
0621 
0622 void skl_ipc_free(struct sst_generic_ipc *ipc)
0623 {
0624     /* Disable IPC DONE interrupt */
0625     sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL,
0626         SKL_ADSP_REG_HIPCCTL_DONE, 0);
0627 
0628     /* Disable IPC BUSY interrupt */
0629     sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL,
0630         SKL_ADSP_REG_HIPCCTL_BUSY, 0);
0631 
0632     sst_ipc_fini(ipc);
0633 }
0634 
0635 int skl_ipc_create_pipeline(struct sst_generic_ipc *ipc,
0636         u16 ppl_mem_size, u8 ppl_type, u8 instance_id, u8 lp_mode)
0637 {
0638     struct skl_ipc_header header = {0};
0639     struct sst_ipc_message request = {0};
0640     int ret;
0641 
0642     header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
0643     header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
0644     header.primary |= IPC_GLB_TYPE(IPC_GLB_CREATE_PPL);
0645     header.primary |= IPC_INSTANCE_ID(instance_id);
0646     header.primary |= IPC_PPL_TYPE(ppl_type);
0647     header.primary |= IPC_PPL_MEM_SIZE(ppl_mem_size);
0648 
0649     header.extension = IPC_PPL_LP_MODE(lp_mode);
0650     request.header = *(u64 *)(&header);
0651 
0652     dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
0653     ret = sst_ipc_tx_message_wait(ipc, request, NULL);
0654     if (ret < 0) {
0655         dev_err(ipc->dev, "ipc: create pipeline fail, err: %d\n", ret);
0656         return ret;
0657     }
0658 
0659     return ret;
0660 }
0661 EXPORT_SYMBOL_GPL(skl_ipc_create_pipeline);
0662 
0663 int skl_ipc_delete_pipeline(struct sst_generic_ipc *ipc, u8 instance_id)
0664 {
0665     struct skl_ipc_header header = {0};
0666     struct sst_ipc_message request = {0};
0667     int ret;
0668 
0669     header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
0670     header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
0671     header.primary |= IPC_GLB_TYPE(IPC_GLB_DELETE_PPL);
0672     header.primary |= IPC_INSTANCE_ID(instance_id);
0673     request.header = *(u64 *)(&header);
0674 
0675     dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
0676     ret = sst_ipc_tx_message_wait(ipc, request, NULL);
0677     if (ret < 0) {
0678         dev_err(ipc->dev, "ipc: delete pipeline failed, err %d\n", ret);
0679         return ret;
0680     }
0681 
0682     return 0;
0683 }
0684 EXPORT_SYMBOL_GPL(skl_ipc_delete_pipeline);
0685 
0686 int skl_ipc_set_pipeline_state(struct sst_generic_ipc *ipc,
0687         u8 instance_id, enum skl_ipc_pipeline_state state)
0688 {
0689     struct skl_ipc_header header = {0};
0690     struct sst_ipc_message request = {0};
0691     int ret;
0692 
0693     header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
0694     header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
0695     header.primary |= IPC_GLB_TYPE(IPC_GLB_SET_PPL_STATE);
0696     header.primary |= IPC_INSTANCE_ID(instance_id);
0697     header.primary |= IPC_PPL_STATE(state);
0698     request.header = *(u64 *)(&header);
0699 
0700     dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
0701     ret = sst_ipc_tx_message_wait(ipc, request, NULL);
0702     if (ret < 0) {
0703         dev_err(ipc->dev, "ipc: set pipeline state failed, err: %d\n", ret);
0704         return ret;
0705     }
0706     return ret;
0707 }
0708 EXPORT_SYMBOL_GPL(skl_ipc_set_pipeline_state);
0709 
0710 int
0711 skl_ipc_save_pipeline(struct sst_generic_ipc *ipc, u8 instance_id, int dma_id)
0712 {
0713     struct skl_ipc_header header = {0};
0714     struct sst_ipc_message request = {0};
0715     int ret;
0716 
0717     header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
0718     header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
0719     header.primary |= IPC_GLB_TYPE(IPC_GLB_SAVE_PPL);
0720     header.primary |= IPC_INSTANCE_ID(instance_id);
0721 
0722     header.extension = IPC_DMA_ID(dma_id);
0723     request.header = *(u64 *)(&header);
0724 
0725     dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
0726     ret = sst_ipc_tx_message_wait(ipc, request, NULL);
0727     if (ret < 0) {
0728         dev_err(ipc->dev, "ipc: save pipeline failed, err: %d\n", ret);
0729         return ret;
0730     }
0731 
0732     return ret;
0733 }
0734 EXPORT_SYMBOL_GPL(skl_ipc_save_pipeline);
0735 
0736 int skl_ipc_restore_pipeline(struct sst_generic_ipc *ipc, u8 instance_id)
0737 {
0738     struct skl_ipc_header header = {0};
0739     struct sst_ipc_message request = {0};
0740     int ret;
0741 
0742     header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
0743     header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
0744     header.primary |= IPC_GLB_TYPE(IPC_GLB_RESTORE_PPL);
0745     header.primary |= IPC_INSTANCE_ID(instance_id);
0746     request.header = *(u64 *)(&header);
0747 
0748     dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary);
0749     ret = sst_ipc_tx_message_wait(ipc, request, NULL);
0750     if (ret < 0) {
0751         dev_err(ipc->dev, "ipc: restore  pipeline failed, err: %d\n", ret);
0752         return ret;
0753     }
0754 
0755     return ret;
0756 }
0757 EXPORT_SYMBOL_GPL(skl_ipc_restore_pipeline);
0758 
0759 int skl_ipc_set_dx(struct sst_generic_ipc *ipc, u8 instance_id,
0760         u16 module_id, struct skl_ipc_dxstate_info *dx)
0761 {
0762     struct skl_ipc_header header = {0};
0763     struct sst_ipc_message request;
0764     int ret;
0765 
0766     header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
0767     header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
0768     header.primary |= IPC_GLB_TYPE(IPC_MOD_SET_DX);
0769     header.primary |= IPC_MOD_INSTANCE_ID(instance_id);
0770     header.primary |= IPC_MOD_ID(module_id);
0771 
0772     request.header = *(u64 *)(&header);
0773     request.data = dx;
0774     request.size = sizeof(*dx);
0775 
0776     dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__,
0777              header.primary, header.extension);
0778     ret = sst_ipc_tx_message_wait(ipc, request, NULL);
0779     if (ret < 0) {
0780         dev_err(ipc->dev, "ipc: set dx failed, err %d\n", ret);
0781         return ret;
0782     }
0783 
0784     return ret;
0785 }
0786 EXPORT_SYMBOL_GPL(skl_ipc_set_dx);
0787 
0788 int skl_ipc_init_instance(struct sst_generic_ipc *ipc,
0789         struct skl_ipc_init_instance_msg *msg, void *param_data)
0790 {
0791     struct skl_ipc_header header = {0};
0792     struct sst_ipc_message request;
0793     int ret;
0794     u32 *buffer = (u32 *)param_data;
0795      /* param_block_size must be in dwords */
0796     u16 param_block_size = msg->param_data_size / sizeof(u32);
0797 
0798     print_hex_dump_debug("Param data:", DUMP_PREFIX_NONE,
0799         16, 4, buffer, param_block_size, false);
0800 
0801     header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
0802     header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
0803     header.primary |= IPC_GLB_TYPE(IPC_MOD_INIT_INSTANCE);
0804     header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
0805     header.primary |= IPC_MOD_ID(msg->module_id);
0806 
0807     header.extension = IPC_CORE_ID(msg->core_id);
0808     header.extension |= IPC_PPL_INSTANCE_ID(msg->ppl_instance_id);
0809     header.extension |= IPC_PARAM_BLOCK_SIZE(param_block_size);
0810     header.extension |= IPC_DOMAIN(msg->domain);
0811 
0812     request.header = *(u64 *)(&header);
0813     request.data = param_data;
0814     request.size = msg->param_data_size;
0815 
0816     dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__,
0817              header.primary, header.extension);
0818     ret = sst_ipc_tx_message_wait(ipc, request, NULL);
0819 
0820     if (ret < 0) {
0821         dev_err(ipc->dev, "ipc: init instance failed\n");
0822         return ret;
0823     }
0824 
0825     return ret;
0826 }
0827 EXPORT_SYMBOL_GPL(skl_ipc_init_instance);
0828 
0829 int skl_ipc_bind_unbind(struct sst_generic_ipc *ipc,
0830         struct skl_ipc_bind_unbind_msg *msg)
0831 {
0832     struct skl_ipc_header header = {0};
0833     struct sst_ipc_message request = {0};
0834     u8 bind_unbind = msg->bind ? IPC_MOD_BIND : IPC_MOD_UNBIND;
0835     int ret;
0836 
0837     header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
0838     header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
0839     header.primary |= IPC_GLB_TYPE(bind_unbind);
0840     header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
0841     header.primary |= IPC_MOD_ID(msg->module_id);
0842 
0843     header.extension = IPC_DST_MOD_ID(msg->dst_module_id);
0844     header.extension |= IPC_DST_MOD_INSTANCE_ID(msg->dst_instance_id);
0845     header.extension |= IPC_DST_QUEUE(msg->dst_queue);
0846     header.extension |= IPC_SRC_QUEUE(msg->src_queue);
0847     request.header = *(u64 *)(&header);
0848 
0849     dev_dbg(ipc->dev, "In %s hdr=%x ext=%x\n", __func__, header.primary,
0850              header.extension);
0851     ret = sst_ipc_tx_message_wait(ipc, request, NULL);
0852     if (ret < 0) {
0853         dev_err(ipc->dev, "ipc: bind/unbind failed\n");
0854         return ret;
0855     }
0856 
0857     return ret;
0858 }
0859 EXPORT_SYMBOL_GPL(skl_ipc_bind_unbind);
0860 
0861 /*
0862  * In order to load a module we need to send IPC to initiate that. DMA will
0863  * performed to load the module memory. The FW supports multiple module load
0864  * at single shot, so we can send IPC with N modules represented by
0865  * module_cnt
0866  */
0867 int skl_ipc_load_modules(struct sst_generic_ipc *ipc,
0868                 u8 module_cnt, void *data)
0869 {
0870     struct skl_ipc_header header = {0};
0871     struct sst_ipc_message request;
0872     int ret;
0873 
0874     header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
0875     header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
0876     header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_MULTIPLE_MODS);
0877     header.primary |= IPC_LOAD_MODULE_CNT(module_cnt);
0878 
0879     request.header = *(u64 *)(&header);
0880     request.data = data;
0881     request.size = sizeof(u16) * module_cnt;
0882 
0883     ret = sst_ipc_tx_message_nowait(ipc, request);
0884     if (ret < 0)
0885         dev_err(ipc->dev, "ipc: load modules failed :%d\n", ret);
0886 
0887     return ret;
0888 }
0889 EXPORT_SYMBOL_GPL(skl_ipc_load_modules);
0890 
0891 int skl_ipc_unload_modules(struct sst_generic_ipc *ipc, u8 module_cnt,
0892                             void *data)
0893 {
0894     struct skl_ipc_header header = {0};
0895     struct sst_ipc_message request;
0896     int ret;
0897 
0898     header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
0899     header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
0900     header.primary |= IPC_GLB_TYPE(IPC_GLB_UNLOAD_MULTIPLE_MODS);
0901     header.primary |= IPC_LOAD_MODULE_CNT(module_cnt);
0902 
0903     request.header = *(u64 *)(&header);
0904     request.data = data;
0905     request.size = sizeof(u16) * module_cnt;
0906 
0907     ret = sst_ipc_tx_message_wait(ipc, request, NULL);
0908     if (ret < 0)
0909         dev_err(ipc->dev, "ipc: unload modules failed :%d\n", ret);
0910 
0911     return ret;
0912 }
0913 EXPORT_SYMBOL_GPL(skl_ipc_unload_modules);
0914 
0915 int skl_ipc_set_large_config(struct sst_generic_ipc *ipc,
0916         struct skl_ipc_large_config_msg *msg, u32 *param)
0917 {
0918     struct skl_ipc_header header = {0};
0919     struct sst_ipc_message request;
0920     int ret = 0;
0921     size_t sz_remaining, tx_size, data_offset;
0922 
0923     header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
0924     header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
0925     header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_SET);
0926     header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
0927     header.primary |= IPC_MOD_ID(msg->module_id);
0928 
0929     header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size);
0930     header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id);
0931     header.extension |= IPC_FINAL_BLOCK(0);
0932     header.extension |= IPC_INITIAL_BLOCK(1);
0933 
0934     sz_remaining = msg->param_data_size;
0935     data_offset = 0;
0936     while (sz_remaining != 0) {
0937         tx_size = sz_remaining > SKL_ADSP_W1_SZ
0938                 ? SKL_ADSP_W1_SZ : sz_remaining;
0939         if (tx_size == sz_remaining)
0940             header.extension |= IPC_FINAL_BLOCK(1);
0941 
0942         dev_dbg(ipc->dev, "In %s primary=%#x ext=%#x\n", __func__,
0943             header.primary, header.extension);
0944         dev_dbg(ipc->dev, "transmitting offset: %#x, size: %#x\n",
0945             (unsigned)data_offset, (unsigned)tx_size);
0946 
0947         request.header = *(u64 *)(&header);
0948         request.data = ((char *)param) + data_offset;
0949         request.size = tx_size;
0950         ret = sst_ipc_tx_message_wait(ipc, request, NULL);
0951         if (ret < 0) {
0952             dev_err(ipc->dev,
0953                 "ipc: set large config fail, err: %d\n", ret);
0954             return ret;
0955         }
0956         sz_remaining -= tx_size;
0957         data_offset = msg->param_data_size - sz_remaining;
0958 
0959         /* clear the fields */
0960         header.extension &= IPC_INITIAL_BLOCK_CLEAR;
0961         header.extension &= IPC_DATA_OFFSET_SZ_CLEAR;
0962         /* fill the fields */
0963         header.extension |= IPC_INITIAL_BLOCK(0);
0964         header.extension |= IPC_DATA_OFFSET_SZ(data_offset);
0965     }
0966 
0967     return ret;
0968 }
0969 EXPORT_SYMBOL_GPL(skl_ipc_set_large_config);
0970 
0971 int skl_ipc_get_large_config(struct sst_generic_ipc *ipc,
0972         struct skl_ipc_large_config_msg *msg,
0973         u32 **payload, size_t *bytes)
0974 {
0975     struct skl_ipc_header header = {0};
0976     struct sst_ipc_message request, reply = {0};
0977     unsigned int *buf;
0978     int ret;
0979 
0980     reply.data = kzalloc(SKL_ADSP_W1_SZ, GFP_KERNEL);
0981     if (!reply.data)
0982         return -ENOMEM;
0983 
0984     header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
0985     header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
0986     header.primary |= IPC_GLB_TYPE(IPC_MOD_LARGE_CONFIG_GET);
0987     header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
0988     header.primary |= IPC_MOD_ID(msg->module_id);
0989 
0990     header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size);
0991     header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id);
0992     header.extension |= IPC_FINAL_BLOCK(1);
0993     header.extension |= IPC_INITIAL_BLOCK(1);
0994 
0995     request.header = *(u64 *)&header;
0996     request.data = *payload;
0997     request.size = *bytes;
0998     reply.size = SKL_ADSP_W1_SZ;
0999 
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         return -ENOMEM;
1008     *payload = buf;
1009     *bytes = reply.size;
1010 
1011     return ret;
1012 }
1013 EXPORT_SYMBOL_GPL(skl_ipc_get_large_config);
1014 
1015 int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc,
1016                 u8 dma_id, u8 table_id, bool wait)
1017 {
1018     struct skl_ipc_header header = {0};
1019     struct sst_ipc_message request = {0};
1020     int ret = 0;
1021 
1022     header.primary = IPC_MSG_TARGET(IPC_FW_GEN_MSG);
1023     header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
1024     header.primary |= IPC_GLB_TYPE(IPC_GLB_LOAD_LIBRARY);
1025     header.primary |= IPC_MOD_INSTANCE_ID(table_id);
1026     header.primary |= IPC_MOD_ID(dma_id);
1027     request.header = *(u64 *)(&header);
1028 
1029     if (wait)
1030         ret = sst_ipc_tx_message_wait(ipc, request, NULL);
1031     else
1032         ret = sst_ipc_tx_message_nowait(ipc, request);
1033 
1034     if (ret < 0)
1035         dev_err(ipc->dev, "ipc: load lib failed\n");
1036 
1037     return ret;
1038 }
1039 EXPORT_SYMBOL_GPL(skl_sst_ipc_load_library);
1040 
1041 int skl_ipc_set_d0ix(struct sst_generic_ipc *ipc, struct skl_ipc_d0ix_msg *msg)
1042 {
1043     struct skl_ipc_header header = {0};
1044     struct sst_ipc_message request = {0};
1045     int ret;
1046 
1047     header.primary = IPC_MSG_TARGET(IPC_MOD_MSG);
1048     header.primary |= IPC_MSG_DIR(IPC_MSG_REQUEST);
1049     header.primary |= IPC_GLB_TYPE(IPC_MOD_SET_D0IX);
1050     header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id);
1051     header.primary |= IPC_MOD_ID(msg->module_id);
1052 
1053     header.extension = IPC_D0IX_WAKE(msg->wake);
1054     header.extension |= IPC_D0IX_STREAMING(msg->streaming);
1055     request.header = *(u64 *)(&header);
1056 
1057     dev_dbg(ipc->dev, "In %s primary=%x ext=%x\n", __func__,
1058             header.primary, header.extension);
1059 
1060     /*
1061      * Use the nopm IPC here as we dont want it checking for D0iX
1062      */
1063     ret = sst_ipc_tx_message_nopm(ipc, request, NULL);
1064     if (ret < 0)
1065         dev_err(ipc->dev, "ipc: set d0ix failed, err %d\n", ret);
1066 
1067     return ret;
1068 }
1069 EXPORT_SYMBOL_GPL(skl_ipc_set_d0ix);