static void skl_ipc_process_reply(struct sst_generic_ipc *ipc, struct skl_ipc_header header) { struct ipc_message *msg; u32 reply = header.primary & IPC_GLB_REPLY_STATUS_MASK; u64 *ipc_header = (u64 *)(&header); struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc); unsigned long flags; spin_lock_irqsave(&ipc->dsp->spinlock, flags); msg = skl_ipc_reply_get_msg(ipc, *ipc_header); spin_unlock_irqrestore(&ipc->dsp->spinlock, flags); if (msg == NULL) { dev_dbg(ipc->dev, "ipc: rx list is empty\n"); return; } /* first process the header */ if (reply == IPC_GLB_REPLY_SUCCESS) { dev_dbg(ipc->dev, "ipc FW reply %x: success\n", header.primary); /* copy the rx data from the mailbox */ sst_dsp_inbox_read(ipc->dsp, msg->rx_data, msg->rx_size); switch (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) { case IPC_GLB_LOAD_MULTIPLE_MODS: case IPC_GLB_LOAD_LIBRARY: skl->mod_load_complete = true; skl->mod_load_status = true; wake_up(&skl->mod_load_wait); break; default: break; } } else { msg->errno = skl_ipc_set_reply_error_code(reply); dev_err(ipc->dev, "ipc FW reply: reply=%d\n", reply); dev_err(ipc->dev, "FW Error Code: %u\n", ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp)); switch (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) { case IPC_GLB_LOAD_MULTIPLE_MODS: case IPC_GLB_LOAD_LIBRARY: skl->mod_load_complete = true; skl->mod_load_status = false; wake_up(&skl->mod_load_wait); break; default: break; } } spin_lock_irqsave(&ipc->dsp->spinlock, flags); list_del(&msg->list); sst_ipc_tx_msg_reply_complete(ipc, msg); spin_unlock_irqrestore(&ipc->dsp->spinlock, flags); }
static int skl_ipc_process_notification(struct sst_generic_ipc *ipc, struct skl_ipc_header header) { struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc); if (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) { switch (IPC_GLB_NOTIFY_TYPE(header.primary)) { case IPC_GLB_NOTIFY_UNDERRUN: dev_err(ipc->dev, "FW Underrun %x\n", header.primary); break; case IPC_GLB_NOTIFY_RESOURCE_EVENT: dev_err(ipc->dev, "MCPS Budget Violation: %x\n", header.primary); break; case IPC_GLB_NOTIFY_FW_READY: skl->boot_complete = true; wake_up(&skl->boot_wait); break; default: dev_err(ipc->dev, "ipc: Unhandled error msg=%x", header.primary); break; } } return 0; }
static int skl_ipc_process_notification(struct sst_generic_ipc *ipc, struct skl_ipc_header header) { struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc); if (IPC_GLB_NOTIFY_MSG_TYPE(header.primary)) { switch (IPC_GLB_NOTIFY_TYPE(header.primary)) { case IPC_GLB_NOTIFY_UNDERRUN: dev_err(ipc->dev, "FW Underrun %x\n", header.primary); break; case IPC_GLB_NOTIFY_RESOURCE_EVENT: dev_err(ipc->dev, "MCPS Budget Violation: %x\n", header.primary); break; case IPC_GLB_NOTIFY_FW_READY: skl->boot_complete = true; wake_up(&skl->boot_wait); break; case IPC_GLB_NOTIFY_PHRASE_DETECTED: dev_dbg(ipc->dev, "***** Phrase Detected **********\n"); /* * Per HW recomendation, After phrase detection, * clear the CGCTL.MISCBDCGE. * * This will be set back on stream closure */ skl->enable_miscbdcge(ipc->dev, false); skl->miscbdcg_disabled = true; break; default: dev_err(ipc->dev, "ipc: Unhandled error msg=%x\n", header.primary); break; } } return 0; }