Lines Matching +full:ipc +full:- +full:3

1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
10 // Generic IPC layer that can work over MMIO and SPI/I2C. PHY layer provided
17 #include "sof-priv.h"
18 #include "sof-audio.h"
22 * sof_ipc_send_msg - generic function to prepare and send one IPC message
33 * Note: higher level sdev->ipc->tx_mutex must be held to make sure that
39 struct snd_sof_ipc *ipc = sdev->ipc; in sof_ipc_send_msg() local
43 if (ipc->disable_ipc_tx || sdev->fw_state != SOF_FW_BOOT_COMPLETE) in sof_ipc_send_msg()
44 return -ENODEV; in sof_ipc_send_msg()
47 * The spin-lock is needed to protect message objects against other in sof_ipc_send_msg()
50 spin_lock_irq(&sdev->ipc_lock); in sof_ipc_send_msg()
53 msg = &ipc->msg; in sof_ipc_send_msg()
56 msg->msg_data = msg_data; in sof_ipc_send_msg()
57 msg->msg_size = msg_bytes; in sof_ipc_send_msg()
59 msg->reply_size = reply_bytes; in sof_ipc_send_msg()
60 msg->reply_error = 0; in sof_ipc_send_msg()
62 sdev->msg = msg; in sof_ipc_send_msg()
67 msg->ipc_complete = false; in sof_ipc_send_msg()
69 spin_unlock_irq(&sdev->ipc_lock); in sof_ipc_send_msg()
74 /* send IPC message from host to DSP */
75 int sof_ipc_tx_message(struct snd_sof_ipc *ipc, void *msg_data, size_t msg_bytes, in sof_ipc_tx_message() argument
78 if (msg_bytes > ipc->max_payload_size || in sof_ipc_tx_message()
79 reply_bytes > ipc->max_payload_size) in sof_ipc_tx_message()
80 return -ENOBUFS; in sof_ipc_tx_message()
82 return ipc->ops->tx_msg(ipc->sdev, msg_data, msg_bytes, reply_data, in sof_ipc_tx_message()
88 * send IPC message from host to DSP without modifying the DSP state.
89 * This will be used for IPC's that can be handled by the DSP
90 * even in a low-power D0 substate.
92 int sof_ipc_tx_message_no_pm(struct snd_sof_ipc *ipc, void *msg_data, size_t msg_bytes, in sof_ipc_tx_message_no_pm() argument
95 if (msg_bytes > ipc->max_payload_size || in sof_ipc_tx_message_no_pm()
96 reply_bytes > ipc->max_payload_size) in sof_ipc_tx_message_no_pm()
97 return -ENOBUFS; in sof_ipc_tx_message_no_pm()
99 return ipc->ops->tx_msg(ipc->sdev, msg_data, msg_bytes, reply_data, in sof_ipc_tx_message_no_pm()
108 * Sometimes, there is unexpected reply ipc arriving. The reply in snd_sof_ipc_get_reply()
109 * ipc belongs to none of the ipcs sent from driver. in snd_sof_ipc_get_reply()
110 * In this case, the driver must ignore the ipc. in snd_sof_ipc_get_reply()
112 if (!sdev->msg) { in snd_sof_ipc_get_reply()
113 dev_warn(sdev->dev, "unexpected ipc interrupt raised!\n"); in snd_sof_ipc_get_reply()
117 sdev->msg->reply_error = sdev->ipc->ops->get_reply(sdev); in snd_sof_ipc_get_reply()
124 struct snd_sof_ipc_msg *msg = &sdev->ipc->msg; in snd_sof_ipc_reply()
126 if (msg->ipc_complete) { in snd_sof_ipc_reply()
127 dev_dbg(sdev->dev, in snd_sof_ipc_reply()
134 msg->ipc_complete = true; in snd_sof_ipc_reply()
135 wake_up(&msg->waitq); in snd_sof_ipc_reply()
141 struct snd_sof_ipc *ipc; in snd_sof_ipc_init() local
145 ipc = devm_kzalloc(sdev->dev, sizeof(*ipc), GFP_KERNEL); in snd_sof_ipc_init()
146 if (!ipc) in snd_sof_ipc_init()
149 mutex_init(&ipc->tx_mutex); in snd_sof_ipc_init()
150 ipc->sdev = sdev; in snd_sof_ipc_init()
151 msg = &ipc->msg; in snd_sof_ipc_init()
154 msg->ipc_complete = true; in snd_sof_ipc_init()
156 init_waitqueue_head(&msg->waitq); in snd_sof_ipc_init()
158 switch (sdev->pdata->ipc_type) { in snd_sof_ipc_init()
170 dev_err(sdev->dev, "Not supported IPC version: %d\n", in snd_sof_ipc_init()
171 sdev->pdata->ipc_type); in snd_sof_ipc_init()
176 if (!ops->tx_msg || !ops->rx_msg || !ops->set_get_data || !ops->get_reply) { in snd_sof_ipc_init()
177 dev_err(sdev->dev, "Missing IPC message handling ops\n"); in snd_sof_ipc_init()
181 if (!ops->fw_loader || !ops->fw_loader->validate || in snd_sof_ipc_init()
182 !ops->fw_loader->parse_ext_manifest) { in snd_sof_ipc_init()
183 dev_err(sdev->dev, "Missing IPC firmware loading ops\n"); in snd_sof_ipc_init()
187 if (!ops->pcm) { in snd_sof_ipc_init()
188 dev_err(sdev->dev, "Missing IPC PCM ops\n"); in snd_sof_ipc_init()
192 if (!ops->tplg || !ops->tplg->widget || !ops->tplg->control) { in snd_sof_ipc_init()
193 dev_err(sdev->dev, "Missing IPC topology ops\n"); in snd_sof_ipc_init()
197 if (ops->fw_tracing && (!ops->fw_tracing->init || !ops->fw_tracing->suspend || in snd_sof_ipc_init()
198 !ops->fw_tracing->resume)) { in snd_sof_ipc_init()
199 dev_err(sdev->dev, "Missing firmware tracing ops\n"); in snd_sof_ipc_init()
203 ipc->ops = ops; in snd_sof_ipc_init()
205 return ipc; in snd_sof_ipc_init()
211 struct snd_sof_ipc *ipc = sdev->ipc; in snd_sof_ipc_free() local
213 if (!ipc) in snd_sof_ipc_free()
216 /* disable sending of ipc's */ in snd_sof_ipc_free()
217 mutex_lock(&ipc->tx_mutex); in snd_sof_ipc_free()
218 ipc->disable_ipc_tx = true; in snd_sof_ipc_free()
219 mutex_unlock(&ipc->tx_mutex); in snd_sof_ipc_free()