summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorPeter Ujfalusi <peter.ujfalusi@linux.intel.com>2022-04-05 10:26:59 -0700
committerMark Brown <broonie@kernel.org>2022-04-11 19:17:52 +0100
commit783b5f1797595a9df4476dd66f7bf34915be246b (patch)
tree08455a25bdfc3fd1dcbe720f293f5d56d72de4cf /sound
parente974b8e190d30fdd0c5edc1447ee1425a30d15ea (diff)
ASoC: SOF: ipc3: Implement the get_reply IPC ops
Add the implementation for the get_reply callback to copy the reply message from mailbox to msg->reply_data buffer. The implementation is equivalent to the currently used code in ipc.c Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Link: https://lore.kernel.org/r/20220405172708.122168-7-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/sof/ipc3.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/sound/soc/sof/ipc3.c b/sound/soc/sof/ipc3.c
index 9aa263b4af0a..2ecd3bb061f3 100644
--- a/sound/soc/sof/ipc3.c
+++ b/sound/soc/sof/ipc3.c
@@ -217,6 +217,60 @@ static inline void ipc3_log_header(struct device *dev, u8 *text, u32 cmd)
}
#endif
+static int sof_ipc3_get_reply(struct snd_sof_dev *sdev)
+{
+ struct snd_sof_ipc_msg *msg = sdev->msg;
+ struct sof_ipc_reply *reply;
+ int ret = 0;
+
+ /* get the generic reply */
+ reply = msg->reply_data;
+ snd_sof_dsp_mailbox_read(sdev, sdev->host_box.offset, reply, sizeof(*reply));
+
+ if (reply->error < 0)
+ return reply->error;
+
+ if (!reply->hdr.size) {
+ /* Reply should always be >= sizeof(struct sof_ipc_reply) */
+ if (msg->reply_size)
+ dev_err(sdev->dev,
+ "empty reply received, expected %zu bytes\n",
+ msg->reply_size);
+ else
+ dev_err(sdev->dev, "empty reply received\n");
+
+ return -EINVAL;
+ }
+
+ if (msg->reply_size > 0) {
+ if (reply->hdr.size == msg->reply_size) {
+ ret = 0;
+ } else if (reply->hdr.size < msg->reply_size) {
+ dev_dbg(sdev->dev,
+ "reply size (%u) is less than expected (%zu)\n",
+ reply->hdr.size, msg->reply_size);
+
+ msg->reply_size = reply->hdr.size;
+ ret = 0;
+ } else {
+ dev_err(sdev->dev,
+ "reply size (%u) exceeds the buffer size (%zu)\n",
+ reply->hdr.size, msg->reply_size);
+ ret = -EINVAL;
+ }
+
+ /*
+ * get the full message if reply->hdr.size <= msg->reply_size
+ * and the reply->hdr.size > sizeof(struct sof_ipc_reply)
+ */
+ if (!ret && msg->reply_size > sizeof(*reply))
+ snd_sof_dsp_mailbox_read(sdev, sdev->host_box.offset,
+ msg->reply_data, msg->reply_size);
+ }
+
+ return ret;
+}
+
/* wait for IPC message reply */
static int ipc3_wait_tx_done(struct snd_sof_ipc *ipc, void *reply_data)
{
@@ -453,4 +507,5 @@ const struct sof_ipc_ops ipc3_ops = {
.tx_msg = sof_ipc3_tx_msg,
.set_get_data = sof_ipc3_set_get_data,
+ .get_reply = sof_ipc3_get_reply,
};