All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/15] ASoC: SOF: Abstractions for top-level IPC ops
@ 2022-04-05 17:26 Ranjani Sridharan
  2022-04-05 17:26 ` [PATCH 01/15] ASoC: SOF: Add helper function to prepare and send an IPC message Ranjani Sridharan
                   ` (15 more replies)
  0 siblings, 16 replies; 17+ messages in thread
From: Ranjani Sridharan @ 2022-04-05 17:26 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, broonie, Ranjani Sridharan

This series is continuation of the IPC abstraction in the SOF driver in
preparation for supporting the new IPC supported by the SOF firmware.
It introduces abstraction for top-level IPC ops for sending/receiving
regular and large IPC's.

Peter Ujfalusi (15):
  ASoC: SOF: Add helper function to prepare and send an IPC message
  ASoC: SOF: Add high level IPC IO callback definitions to ipc_ops
  ASoC: SOF: ipc3: Implement the tx_msg IPC ops
  ASoC: SOF: ipc3: Use sof_ipc3_tx_msg() internally for message sending
  ASoC: SOF: ipc3: Implement the set_get_data IPC ops
  ASoC: SOF: ipc3: Implement the get_reply IPC ops
  ASoC: SOF: ipc3: Implement rx_msg IPC ops
  ASoC: SOF: ipc: Separate the ops checks by functions/topics
  ASoC: SOF: ipc: Add check for mandatory IPC message handling ops
  ASoC: SOF: ipc: Use the get_reply ops in snd_sof_ipc_get_reply()
  ASoC: SOF: ipc: Switch over to use the tx_msg and set_get_data ops
  ASoC: SOF: ipc: Switch over to use the rx_msg ops
  ASoC: SOF: Add widget_kcontrol_setup control ops for IPC3
  ASoC: SOF: sof-audio: Use the widget_kcontrol_setup ops for kcontrol
    set up
  ASoC: SOF: ipc: Move the ipc_set_get_comp_data() local to ipc3-control

 sound/soc/sof/ipc.c          | 858 ++---------------------------------
 sound/soc/sof/ipc3-control.c | 131 +++++-
 sound/soc/sof/ipc3.c         | 682 +++++++++++++++++++++++++++-
 sound/soc/sof/sof-audio.c    |  54 +--
 sound/soc/sof/sof-audio.h    |   7 +-
 sound/soc/sof/sof-priv.h     |  28 +-
 6 files changed, 880 insertions(+), 880 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 01/15] ASoC: SOF: Add helper function to prepare and send an IPC message
  2022-04-05 17:26 [PATCH 00/15] ASoC: SOF: Abstractions for top-level IPC ops Ranjani Sridharan
@ 2022-04-05 17:26 ` Ranjani Sridharan
  2022-04-05 17:26 ` [PATCH 02/15] ASoC: SOF: Add high level IPC IO callback definitions to ipc_ops Ranjani Sridharan
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ranjani Sridharan @ 2022-04-05 17:26 UTC (permalink / raw)
  To: alsa-devel
  Cc: tiwai, Peter Ujfalusi, Pierre-Louis Bossart, Ranjani Sridharan,
	broonie, Daniel Baluta

From: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>

The new sof_ipc_send_msg() can be used by IPC dependent code to prepare
the ipc->msg for a new message transmission and then call in to platform
code to send the message.

Higher level code should be handling the completion and reply.

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>
---
 sound/soc/sof/ipc.c      | 53 ++++++++++++++++++++++++++++++++++++++++
 sound/soc/sof/sof-priv.h |  2 ++
 2 files changed, 55 insertions(+)

diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c
index 17dd51d342cf..a78b74514438 100644
--- a/sound/soc/sof/ipc.c
+++ b/sound/soc/sof/ipc.c
@@ -340,6 +340,59 @@ static int sof_ipc_tx_message_unlocked(struct snd_sof_ipc *ipc,
 	return tx_wait_done(ipc, msg, reply_data);
 }
 
+/**
+ * sof_ipc_send_msg - generic function to prepare and send one IPC message
+ * @sdev:		pointer to SOF core device struct
+ * @msg_data:		pointer to a message to send
+ * @msg_bytes:		number of bytes in the message
+ * @reply_bytes:	number of bytes available for the reply.
+ *			The buffer for the reply data is not passed to this
+ *			function, the available size is an information for the
+ *			reply handling functions.
+ *
+ * On success the function returns 0, otherwise negative error number.
+ *
+ * Note: higher level sdev->ipc->tx_mutex must be held to make sure that
+ *	 transfers are synchronized.
+ */
+int sof_ipc_send_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_bytes,
+		     size_t reply_bytes)
+{
+	struct snd_sof_ipc *ipc = sdev->ipc;
+	struct snd_sof_ipc_msg *msg;
+	int ret;
+
+	if (ipc->disable_ipc_tx || sdev->fw_state != SOF_FW_BOOT_COMPLETE)
+		return -ENODEV;
+
+	/*
+	 * The spin-lock is needed to protect message objects against other
+	 * atomic contexts.
+	 */
+	spin_lock_irq(&sdev->ipc_lock);
+
+	/* initialise the message */
+	msg = &ipc->msg;
+
+	/* attach message data */
+	msg->msg_data = msg_data;
+	msg->msg_size = msg_bytes;
+
+	msg->reply_size = reply_bytes;
+	msg->reply_error = 0;
+
+	sdev->msg = msg;
+
+	ret = snd_sof_dsp_send_msg(sdev, msg);
+	/* Next reply that we receive will be related to this message */
+	if (!ret)
+		msg->ipc_complete = false;
+
+	spin_unlock_irq(&sdev->ipc_lock);
+
+	return ret;
+}
+
 /* send IPC message from host to DSP */
 int sof_ipc_tx_message(struct snd_sof_ipc *ipc, void *msg_data, size_t msg_bytes,
 		       void *reply_data, size_t reply_bytes)
diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h
index df19d58d8894..f6ae28a21482 100644
--- a/sound/soc/sof/sof-priv.h
+++ b/sound/soc/sof/sof-priv.h
@@ -588,6 +588,8 @@ int sof_ipc_tx_message(struct snd_sof_ipc *ipc, void *msg_data, size_t msg_bytes
 		       void *reply_data, size_t reply_bytes);
 int sof_ipc_tx_message_no_pm(struct snd_sof_ipc *ipc, void *msg_data, size_t msg_bytes,
 			     void *reply_data, size_t reply_bytes);
+int sof_ipc_send_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_bytes,
+		     size_t reply_bytes);
 int sof_ipc_init_msg_memory(struct snd_sof_dev *sdev);
 static inline void snd_sof_ipc_process_reply(struct snd_sof_dev *sdev, u32 msg_id)
 {
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 02/15] ASoC: SOF: Add high level IPC IO callback definitions to ipc_ops
  2022-04-05 17:26 [PATCH 00/15] ASoC: SOF: Abstractions for top-level IPC ops Ranjani Sridharan
  2022-04-05 17:26 ` [PATCH 01/15] ASoC: SOF: Add helper function to prepare and send an IPC message Ranjani Sridharan
@ 2022-04-05 17:26 ` Ranjani Sridharan
  2022-04-05 17:26 ` [PATCH 03/15] ASoC: SOF: ipc3: Implement the tx_msg IPC ops Ranjani Sridharan
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ranjani Sridharan @ 2022-04-05 17:26 UTC (permalink / raw)
  To: alsa-devel
  Cc: tiwai, Daniel Baluta, broonie, Peter Ujfalusi, Ranjani Sridharan

From: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>

Add tx_msg(), rx_msg(), set_get_data() and get_reply() ops, which can
be used as a generic API for sending, receiving single messages and
to write and read large data.

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>
---
 sound/soc/sof/sof-priv.h | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h
index f6ae28a21482..2bf7844f01d7 100644
--- a/sound/soc/sof/sof-priv.h
+++ b/sound/soc/sof/sof-priv.h
@@ -377,11 +377,32 @@ struct sof_ipc_pcm_ops;
  * @tplg:	Pointer to IPC-specific topology ops
  * @pm:		Pointer to PM ops
  * @pcm:	Pointer to PCM ops
+ *
+ * @tx_msg:	Function pointer for sending a 'short' IPC message
+ * @set_get_data: Function pointer for set/get data ('large' IPC message). This
+ *		function may split up the 'large' message and use the @tx_msg
+ *		path to transfer individual chunks, or use other means to transfer
+ *		the message.
+ * @get_reply:	Function pointer for fetching the reply to
+ *		sdev->ipc->msg.reply_data
+ * @rx_msg:	Function pointer for handling a received message
+ *
+ * Note: both @tx_msg and @set_get_data considered as TX functions and they are
+ * serialized for the duration of the instructed transfer. A large message sent
+ * via @set_get_data is a single transfer even if at the hardware level it is
+ * handled with multiple chunks.
  */
 struct sof_ipc_ops {
 	const struct sof_ipc_tplg_ops *tplg;
 	const struct sof_ipc_pm_ops *pm;
 	const struct sof_ipc_pcm_ops *pcm;
+
+	int (*tx_msg)(struct snd_sof_dev *sdev, void *msg_data, size_t msg_bytes,
+		      void *reply_data, size_t reply_bytes, bool no_pm);
+	int (*set_get_data)(struct snd_sof_dev *sdev, void *data, size_t data_bytes,
+			    bool set);
+	int (*get_reply)(struct snd_sof_dev *sdev);
+	void (*rx_msg)(struct snd_sof_dev *sdev);
 };
 
 /* SOF generic IPC data */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 03/15] ASoC: SOF: ipc3: Implement the tx_msg IPC ops
  2022-04-05 17:26 [PATCH 00/15] ASoC: SOF: Abstractions for top-level IPC ops Ranjani Sridharan
  2022-04-05 17:26 ` [PATCH 01/15] ASoC: SOF: Add helper function to prepare and send an IPC message Ranjani Sridharan
  2022-04-05 17:26 ` [PATCH 02/15] ASoC: SOF: Add high level IPC IO callback definitions to ipc_ops Ranjani Sridharan
@ 2022-04-05 17:26 ` Ranjani Sridharan
  2022-04-05 17:26 ` [PATCH 04/15] ASoC: SOF: ipc3: Use sof_ipc3_tx_msg() internally for message sending Ranjani Sridharan
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ranjani Sridharan @ 2022-04-05 17:26 UTC (permalink / raw)
  To: alsa-devel
  Cc: tiwai, Peter Ujfalusi, Pierre-Louis Bossart, Ranjani Sridharan,
	broonie, Daniel Baluta

From: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>

Add the implementation for the IPC3 tx_msg callback for sending a single
IPC message.

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>
---
 sound/soc/sof/ipc3.c | 308 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 308 insertions(+)

diff --git a/sound/soc/sof/ipc3.c b/sound/soc/sof/ipc3.c
index a7289804efda..7f80035d3a88 100644
--- a/sound/soc/sof/ipc3.c
+++ b/sound/soc/sof/ipc3.c
@@ -9,6 +9,312 @@
 
 #include "sof-priv.h"
 #include "ipc3-ops.h"
+#include "ops.h"
+
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_VERBOSE_IPC)
+static void ipc3_log_header(struct device *dev, u8 *text, u32 cmd)
+{
+	u8 *str;
+	u8 *str2 = NULL;
+	u32 glb;
+	u32 type;
+	bool vdbg = false;
+
+	glb = cmd & SOF_GLB_TYPE_MASK;
+	type = cmd & SOF_CMD_TYPE_MASK;
+
+	switch (glb) {
+	case SOF_IPC_GLB_REPLY:
+		str = "GLB_REPLY"; break;
+	case SOF_IPC_GLB_COMPOUND:
+		str = "GLB_COMPOUND"; break;
+	case SOF_IPC_GLB_TPLG_MSG:
+		str = "GLB_TPLG_MSG";
+		switch (type) {
+		case SOF_IPC_TPLG_COMP_NEW:
+			str2 = "COMP_NEW"; break;
+		case SOF_IPC_TPLG_COMP_FREE:
+			str2 = "COMP_FREE"; break;
+		case SOF_IPC_TPLG_COMP_CONNECT:
+			str2 = "COMP_CONNECT"; break;
+		case SOF_IPC_TPLG_PIPE_NEW:
+			str2 = "PIPE_NEW"; break;
+		case SOF_IPC_TPLG_PIPE_FREE:
+			str2 = "PIPE_FREE"; break;
+		case SOF_IPC_TPLG_PIPE_CONNECT:
+			str2 = "PIPE_CONNECT"; break;
+		case SOF_IPC_TPLG_PIPE_COMPLETE:
+			str2 = "PIPE_COMPLETE"; break;
+		case SOF_IPC_TPLG_BUFFER_NEW:
+			str2 = "BUFFER_NEW"; break;
+		case SOF_IPC_TPLG_BUFFER_FREE:
+			str2 = "BUFFER_FREE"; break;
+		default:
+			str2 = "unknown type"; break;
+		}
+		break;
+	case SOF_IPC_GLB_PM_MSG:
+		str = "GLB_PM_MSG";
+		switch (type) {
+		case SOF_IPC_PM_CTX_SAVE:
+			str2 = "CTX_SAVE"; break;
+		case SOF_IPC_PM_CTX_RESTORE:
+			str2 = "CTX_RESTORE"; break;
+		case SOF_IPC_PM_CTX_SIZE:
+			str2 = "CTX_SIZE"; break;
+		case SOF_IPC_PM_CLK_SET:
+			str2 = "CLK_SET"; break;
+		case SOF_IPC_PM_CLK_GET:
+			str2 = "CLK_GET"; break;
+		case SOF_IPC_PM_CLK_REQ:
+			str2 = "CLK_REQ"; break;
+		case SOF_IPC_PM_CORE_ENABLE:
+			str2 = "CORE_ENABLE"; break;
+		case SOF_IPC_PM_GATE:
+			str2 = "GATE"; break;
+		default:
+			str2 = "unknown type"; break;
+		}
+		break;
+	case SOF_IPC_GLB_COMP_MSG:
+		str = "GLB_COMP_MSG";
+		switch (type) {
+		case SOF_IPC_COMP_SET_VALUE:
+			str2 = "SET_VALUE"; break;
+		case SOF_IPC_COMP_GET_VALUE:
+			str2 = "GET_VALUE"; break;
+		case SOF_IPC_COMP_SET_DATA:
+			str2 = "SET_DATA"; break;
+		case SOF_IPC_COMP_GET_DATA:
+			str2 = "GET_DATA"; break;
+		default:
+			str2 = "unknown type"; break;
+		}
+		break;
+	case SOF_IPC_GLB_STREAM_MSG:
+		str = "GLB_STREAM_MSG";
+		switch (type) {
+		case SOF_IPC_STREAM_PCM_PARAMS:
+			str2 = "PCM_PARAMS"; break;
+		case SOF_IPC_STREAM_PCM_PARAMS_REPLY:
+			str2 = "PCM_REPLY"; break;
+		case SOF_IPC_STREAM_PCM_FREE:
+			str2 = "PCM_FREE"; break;
+		case SOF_IPC_STREAM_TRIG_START:
+			str2 = "TRIG_START"; break;
+		case SOF_IPC_STREAM_TRIG_STOP:
+			str2 = "TRIG_STOP"; break;
+		case SOF_IPC_STREAM_TRIG_PAUSE:
+			str2 = "TRIG_PAUSE"; break;
+		case SOF_IPC_STREAM_TRIG_RELEASE:
+			str2 = "TRIG_RELEASE"; break;
+		case SOF_IPC_STREAM_TRIG_DRAIN:
+			str2 = "TRIG_DRAIN"; break;
+		case SOF_IPC_STREAM_TRIG_XRUN:
+			str2 = "TRIG_XRUN"; break;
+		case SOF_IPC_STREAM_POSITION:
+			vdbg = true;
+			str2 = "POSITION"; break;
+		case SOF_IPC_STREAM_VORBIS_PARAMS:
+			str2 = "VORBIS_PARAMS"; break;
+		case SOF_IPC_STREAM_VORBIS_FREE:
+			str2 = "VORBIS_FREE"; break;
+		default:
+			str2 = "unknown type"; break;
+		}
+		break;
+	case SOF_IPC_FW_READY:
+		str = "FW_READY"; break;
+	case SOF_IPC_GLB_DAI_MSG:
+		str = "GLB_DAI_MSG";
+		switch (type) {
+		case SOF_IPC_DAI_CONFIG:
+			str2 = "CONFIG"; break;
+		case SOF_IPC_DAI_LOOPBACK:
+			str2 = "LOOPBACK"; break;
+		default:
+			str2 = "unknown type"; break;
+		}
+		break;
+	case SOF_IPC_GLB_TRACE_MSG:
+		str = "GLB_TRACE_MSG";
+		switch (type) {
+		case SOF_IPC_TRACE_DMA_PARAMS:
+			str2 = "DMA_PARAMS"; break;
+		case SOF_IPC_TRACE_DMA_POSITION:
+			str2 = "DMA_POSITION"; break;
+		case SOF_IPC_TRACE_DMA_PARAMS_EXT:
+			str2 = "DMA_PARAMS_EXT"; break;
+		case SOF_IPC_TRACE_FILTER_UPDATE:
+			str2 = "FILTER_UPDATE"; break;
+		case SOF_IPC_TRACE_DMA_FREE:
+			str2 = "DMA_FREE"; break;
+		default:
+			str2 = "unknown type"; break;
+		}
+		break;
+	case SOF_IPC_GLB_TEST_MSG:
+		str = "GLB_TEST_MSG";
+		switch (type) {
+		case SOF_IPC_TEST_IPC_FLOOD:
+			str2 = "IPC_FLOOD"; break;
+		default:
+			str2 = "unknown type"; break;
+		}
+		break;
+	case SOF_IPC_GLB_DEBUG:
+		str = "GLB_DEBUG";
+		switch (type) {
+		case SOF_IPC_DEBUG_MEM_USAGE:
+			str2 = "MEM_USAGE"; break;
+		default:
+			str2 = "unknown type"; break;
+		}
+		break;
+	case SOF_IPC_GLB_PROBE:
+		str = "GLB_PROBE";
+		switch (type) {
+		case SOF_IPC_PROBE_INIT:
+			str2 = "INIT"; break;
+		case SOF_IPC_PROBE_DEINIT:
+			str2 = "DEINIT"; break;
+		case SOF_IPC_PROBE_DMA_ADD:
+			str2 = "DMA_ADD"; break;
+		case SOF_IPC_PROBE_DMA_INFO:
+			str2 = "DMA_INFO"; break;
+		case SOF_IPC_PROBE_DMA_REMOVE:
+			str2 = "DMA_REMOVE"; break;
+		case SOF_IPC_PROBE_POINT_ADD:
+			str2 = "POINT_ADD"; break;
+		case SOF_IPC_PROBE_POINT_INFO:
+			str2 = "POINT_INFO"; break;
+		case SOF_IPC_PROBE_POINT_REMOVE:
+			str2 = "POINT_REMOVE"; break;
+		default:
+			str2 = "unknown type"; break;
+		}
+		break;
+	default:
+		str = "unknown GLB command"; break;
+	}
+
+	if (str2) {
+		if (vdbg)
+			dev_vdbg(dev, "%s: 0x%x: %s: %s\n", text, cmd, str, str2);
+		else
+			dev_dbg(dev, "%s: 0x%x: %s: %s\n", text, cmd, str, str2);
+	} else {
+		dev_dbg(dev, "%s: 0x%x: %s\n", text, cmd, str);
+	}
+}
+#else
+static inline void ipc3_log_header(struct device *dev, u8 *text, u32 cmd)
+{
+	if ((cmd & SOF_GLB_TYPE_MASK) != SOF_IPC_GLB_TRACE_MSG)
+		dev_dbg(dev, "%s: 0x%x\n", text, cmd);
+}
+#endif
+
+/* wait for IPC message reply */
+static int ipc3_wait_tx_done(struct snd_sof_ipc *ipc, void *reply_data)
+{
+	struct snd_sof_ipc_msg *msg = &ipc->msg;
+	struct sof_ipc_cmd_hdr *hdr = msg->msg_data;
+	struct snd_sof_dev *sdev = ipc->sdev;
+	int ret;
+
+	/* wait for DSP IPC completion */
+	ret = wait_event_timeout(msg->waitq, msg->ipc_complete,
+				 msecs_to_jiffies(sdev->ipc_timeout));
+
+	if (ret == 0) {
+		dev_err(sdev->dev,
+			"ipc tx timed out for %#x (msg/reply size: %d/%zu)\n",
+			hdr->cmd, hdr->size, msg->reply_size);
+		snd_sof_handle_fw_exception(ipc->sdev);
+		ret = -ETIMEDOUT;
+	} else {
+		ret = msg->reply_error;
+		if (ret < 0) {
+			dev_err(sdev->dev,
+				"ipc tx error for %#x (msg/reply size: %d/%zu): %d\n",
+				hdr->cmd, hdr->size, msg->reply_size, ret);
+		} else {
+			ipc3_log_header(sdev->dev, "ipc tx succeeded", hdr->cmd);
+			if (msg->reply_size)
+				/* copy the data returned from DSP */
+				memcpy(reply_data, msg->reply_data,
+				       msg->reply_size);
+		}
+
+		/* re-enable dumps after successful IPC tx */
+		if (sdev->ipc_dump_printed) {
+			sdev->dbg_dump_printed = false;
+			sdev->ipc_dump_printed = false;
+		}
+	}
+
+	return ret;
+}
+
+/* send IPC message from host to DSP */
+static int ipc3_tx_msg_unlocked(struct snd_sof_ipc *ipc,
+				void *msg_data, size_t msg_bytes,
+				void *reply_data, size_t reply_bytes)
+{
+	struct sof_ipc_cmd_hdr *hdr = msg_data;
+	struct snd_sof_dev *sdev = ipc->sdev;
+	int ret;
+
+	ret = sof_ipc_send_msg(sdev, msg_data, msg_bytes, reply_bytes);
+
+	if (ret) {
+		dev_err_ratelimited(sdev->dev,
+				    "%s: ipc message send for %#x failed: %d\n",
+				    __func__, hdr->cmd, ret);
+		return ret;
+	}
+
+	ipc3_log_header(sdev->dev, "ipc tx", hdr->cmd);
+
+	/* now wait for completion */
+	return ipc3_wait_tx_done(ipc, reply_data);
+}
+
+static int sof_ipc3_tx_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_bytes,
+			   void *reply_data, size_t reply_bytes, bool no_pm)
+{
+	struct snd_sof_ipc *ipc = sdev->ipc;
+	int ret;
+
+	if (!msg_data || msg_bytes < sizeof(struct sof_ipc_cmd_hdr)) {
+		dev_err_ratelimited(sdev->dev, "No IPC message to send\n");
+		return -EINVAL;
+	}
+
+	if (!no_pm) {
+		const struct sof_dsp_power_state target_state = {
+			.state = SOF_DSP_PM_D0,
+		};
+
+		/* ensure the DSP is in D0 before sending a new IPC */
+		ret = snd_sof_dsp_set_power_state(sdev, &target_state);
+		if (ret < 0) {
+			dev_err(sdev->dev, "%s: resuming DSP failed: %d\n",
+				__func__, ret);
+			return ret;
+		}
+	}
+
+	/* Serialise IPC TX */
+	mutex_lock(&ipc->tx_mutex);
+
+	ret = ipc3_tx_msg_unlocked(ipc, msg_data, msg_bytes, reply_data, reply_bytes);
+
+	mutex_unlock(&ipc->tx_mutex);
+
+	return ret;
+}
 
 static int sof_ipc3_ctx_ipc(struct snd_sof_dev *sdev, int cmd)
 {
@@ -42,4 +348,6 @@ const struct sof_ipc_ops ipc3_ops = {
 	.tplg = &ipc3_tplg_ops,
 	.pm = &ipc3_pm_ops,
 	.pcm = &ipc3_pcm_ops,
+
+	.tx_msg = sof_ipc3_tx_msg,
 };
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 04/15] ASoC: SOF: ipc3: Use sof_ipc3_tx_msg() internally for message sending
  2022-04-05 17:26 [PATCH 00/15] ASoC: SOF: Abstractions for top-level IPC ops Ranjani Sridharan
                   ` (2 preceding siblings ...)
  2022-04-05 17:26 ` [PATCH 03/15] ASoC: SOF: ipc3: Implement the tx_msg IPC ops Ranjani Sridharan
@ 2022-04-05 17:26 ` Ranjani Sridharan
  2022-04-05 17:26 ` [PATCH 05/15] ASoC: SOF: ipc3: Implement the set_get_data IPC ops Ranjani Sridharan
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ranjani Sridharan @ 2022-04-05 17:26 UTC (permalink / raw)
  To: alsa-devel
  Cc: tiwai, Peter Ujfalusi, Pierre-Louis Bossart, Ranjani Sridharan,
	broonie, Daniel Baluta

From: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>

Instead of using sof_ipc_tx_message() for sending message, use the
sof_ipc3_tx_msg() directly within ipc3.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>
---
 sound/soc/sof/ipc3.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sound/soc/sof/ipc3.c b/sound/soc/sof/ipc3.c
index 7f80035d3a88..6b59d4d0727f 100644
--- a/sound/soc/sof/ipc3.c
+++ b/sound/soc/sof/ipc3.c
@@ -325,8 +325,8 @@ static int sof_ipc3_ctx_ipc(struct snd_sof_dev *sdev, int cmd)
 	struct sof_ipc_reply reply;
 
 	/* send ctx save ipc to dsp */
-	return sof_ipc_tx_message(sdev->ipc, &pm_ctx, sizeof(pm_ctx),
-				  &reply, sizeof(reply));
+	return sof_ipc3_tx_msg(sdev, &pm_ctx, sizeof(pm_ctx),
+			       &reply, sizeof(reply), false);
 }
 
 static int sof_ipc3_ctx_save(struct snd_sof_dev *sdev)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 05/15] ASoC: SOF: ipc3: Implement the set_get_data IPC ops
  2022-04-05 17:26 [PATCH 00/15] ASoC: SOF: Abstractions for top-level IPC ops Ranjani Sridharan
                   ` (3 preceding siblings ...)
  2022-04-05 17:26 ` [PATCH 04/15] ASoC: SOF: ipc3: Use sof_ipc3_tx_msg() internally for message sending Ranjani Sridharan
@ 2022-04-05 17:26 ` Ranjani Sridharan
  2022-04-05 17:26 ` [PATCH 06/15] ASoC: SOF: ipc3: Implement the get_reply " Ranjani Sridharan
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ranjani Sridharan @ 2022-04-05 17:26 UTC (permalink / raw)
  To: alsa-devel
  Cc: Bard Liao, tiwai, Peter Ujfalusi, Pierre-Louis Bossart,
	Ranjani Sridharan, broonie, Daniel Baluta

From: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>

Add the implementation for the set_get_data callback for handling large
data set and get.

The set_get_data() in IPC3 can be used only for component messages. The
function expects the caller to prepare the message behind the data pointer
for sending/receiving data. The callback only implements the needed code
to be able to split up a message if needed for transfer.

The set_get_data ops is based on the existing
snd_sof_ipc_set_get_comp_data() and sof_set_get_large_ctrl_data() but made
it generic entry point.

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>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
---
 sound/soc/sof/ipc3.c | 103 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 103 insertions(+)

diff --git a/sound/soc/sof/ipc3.c b/sound/soc/sof/ipc3.c
index 6b59d4d0727f..9aa263b4af0a 100644
--- a/sound/soc/sof/ipc3.c
+++ b/sound/soc/sof/ipc3.c
@@ -7,6 +7,8 @@
 //
 //
 
+#include <sound/sof/stream.h>
+#include <sound/sof/control.h>
 #include "sof-priv.h"
 #include "ipc3-ops.h"
 #include "ops.h"
@@ -316,6 +318,106 @@ static int sof_ipc3_tx_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_
 	return ret;
 }
 
+static int sof_ipc3_set_get_data(struct snd_sof_dev *sdev, void *data, size_t data_bytes,
+				 bool set)
+{
+	size_t msg_bytes, hdr_bytes, payload_size, send_bytes;
+	struct sof_ipc_ctrl_data *cdata = data;
+	struct sof_ipc_ctrl_data *cdata_chunk;
+	struct snd_sof_ipc *ipc = sdev->ipc;
+	size_t offset = 0;
+	u8 *src, *dst;
+	u32 num_msg;
+	int ret = 0;
+	int i;
+
+	if (!cdata || data_bytes < sizeof(*cdata))
+		return -EINVAL;
+
+	if ((cdata->rhdr.hdr.cmd & SOF_GLB_TYPE_MASK) != SOF_IPC_GLB_COMP_MSG) {
+		dev_err(sdev->dev, "%s: Not supported message type of %#x\n",
+			__func__, cdata->rhdr.hdr.cmd);
+		return -EINVAL;
+	}
+
+	/* send normal size ipc in one part */
+	if (cdata->rhdr.hdr.size <= ipc->max_payload_size)
+		return sof_ipc3_tx_msg(sdev, cdata, cdata->rhdr.hdr.size,
+				       cdata, cdata->rhdr.hdr.size, false);
+
+	cdata_chunk = kzalloc(ipc->max_payload_size, GFP_KERNEL);
+	if (!cdata_chunk)
+		return -ENOMEM;
+
+	switch (cdata->type) {
+	case SOF_CTRL_TYPE_VALUE_CHAN_GET:
+	case SOF_CTRL_TYPE_VALUE_CHAN_SET:
+		hdr_bytes = sizeof(struct sof_ipc_ctrl_data);
+		if (set) {
+			src = (u8 *)cdata->chanv;
+			dst = (u8 *)cdata_chunk->chanv;
+		} else {
+			src = (u8 *)cdata_chunk->chanv;
+			dst = (u8 *)cdata->chanv;
+		}
+		break;
+	case SOF_CTRL_TYPE_DATA_GET:
+	case SOF_CTRL_TYPE_DATA_SET:
+		hdr_bytes = sizeof(struct sof_ipc_ctrl_data) + sizeof(struct sof_abi_hdr);
+		if (set) {
+			src = (u8 *)cdata->data->data;
+			dst = (u8 *)cdata_chunk->data->data;
+		} else {
+			src = (u8 *)cdata_chunk->data->data;
+			dst = (u8 *)cdata->data->data;
+		}
+		break;
+	default:
+		kfree(cdata_chunk);
+		return -EINVAL;
+	}
+
+	msg_bytes = cdata->rhdr.hdr.size - hdr_bytes;
+	payload_size = ipc->max_payload_size - hdr_bytes;
+	num_msg = DIV_ROUND_UP(msg_bytes, payload_size);
+
+	/* copy the header data */
+	memcpy(cdata_chunk, cdata, hdr_bytes);
+
+	/* Serialise IPC TX */
+	mutex_lock(&sdev->ipc->tx_mutex);
+
+	/* copy the payload data in a loop */
+	for (i = 0; i < num_msg; i++) {
+		send_bytes = min(msg_bytes, payload_size);
+		cdata_chunk->num_elems = send_bytes;
+		cdata_chunk->rhdr.hdr.size = hdr_bytes + send_bytes;
+		cdata_chunk->msg_index = i;
+		msg_bytes -= send_bytes;
+		cdata_chunk->elems_remaining = msg_bytes;
+
+		if (set)
+			memcpy(dst, src + offset, send_bytes);
+
+		ret = ipc3_tx_msg_unlocked(sdev->ipc,
+					   cdata_chunk, cdata_chunk->rhdr.hdr.size,
+					   cdata_chunk, cdata_chunk->rhdr.hdr.size);
+		if (ret < 0)
+			break;
+
+		if (!set)
+			memcpy(dst + offset, src, send_bytes);
+
+		offset += payload_size;
+	}
+
+	mutex_unlock(&sdev->ipc->tx_mutex);
+
+	kfree(cdata_chunk);
+
+	return ret;
+}
+
 static int sof_ipc3_ctx_ipc(struct snd_sof_dev *sdev, int cmd)
 {
 	struct sof_ipc_pm_ctx pm_ctx = {
@@ -350,4 +452,5 @@ const struct sof_ipc_ops ipc3_ops = {
 	.pcm = &ipc3_pcm_ops,
 
 	.tx_msg = sof_ipc3_tx_msg,
+	.set_get_data = sof_ipc3_set_get_data,
 };
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 06/15] ASoC: SOF: ipc3: Implement the get_reply IPC ops
  2022-04-05 17:26 [PATCH 00/15] ASoC: SOF: Abstractions for top-level IPC ops Ranjani Sridharan
                   ` (4 preceding siblings ...)
  2022-04-05 17:26 ` [PATCH 05/15] ASoC: SOF: ipc3: Implement the set_get_data IPC ops Ranjani Sridharan
@ 2022-04-05 17:26 ` Ranjani Sridharan
  2022-04-05 17:27 ` [PATCH 07/15] ASoC: SOF: ipc3: Implement rx_msg " Ranjani Sridharan
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ranjani Sridharan @ 2022-04-05 17:26 UTC (permalink / raw)
  To: alsa-devel
  Cc: tiwai, Peter Ujfalusi, Pierre-Louis Bossart, Ranjani Sridharan,
	broonie, Daniel Baluta

From: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>

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>
---
 sound/soc/sof/ipc3.c | 55 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)

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,
 };
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 07/15] ASoC: SOF: ipc3: Implement rx_msg IPC ops
  2022-04-05 17:26 [PATCH 00/15] ASoC: SOF: Abstractions for top-level IPC ops Ranjani Sridharan
                   ` (5 preceding siblings ...)
  2022-04-05 17:26 ` [PATCH 06/15] ASoC: SOF: ipc3: Implement the get_reply " Ranjani Sridharan
@ 2022-04-05 17:27 ` Ranjani Sridharan
  2022-04-05 17:27 ` [PATCH 08/15] ASoC: SOF: ipc: Separate the ops checks by functions/topics Ranjani Sridharan
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ranjani Sridharan @ 2022-04-05 17:27 UTC (permalink / raw)
  To: alsa-devel
  Cc: tiwai, Peter Ujfalusi, Pierre-Louis Bossart, Ranjani Sridharan,
	broonie, Daniel Baluta

From: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>

Add the implementation for the rx_msg callback to handle message reception
for IPC3.

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>
---
 sound/soc/sof/ipc3.c | 212 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 212 insertions(+)

diff --git a/sound/soc/sof/ipc3.c b/sound/soc/sof/ipc3.c
index 2ecd3bb061f3..8480a1b5733a 100644
--- a/sound/soc/sof/ipc3.c
+++ b/sound/soc/sof/ipc3.c
@@ -10,9 +10,12 @@
 #include <sound/sof/stream.h>
 #include <sound/sof/control.h>
 #include "sof-priv.h"
+#include "sof-audio.h"
 #include "ipc3-ops.h"
 #include "ops.h"
 
+typedef void (*ipc3_rx_callback)(struct snd_sof_dev *sdev, void *msg_buf);
+
 #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_VERBOSE_IPC)
 static void ipc3_log_header(struct device *dev, u8 *text, u32 cmd)
 {
@@ -472,6 +475,214 @@ static int sof_ipc3_set_get_data(struct snd_sof_dev *sdev, void *data, size_t da
 	return ret;
 }
 
+/* IPC stream position. */
+static void ipc3_period_elapsed(struct snd_sof_dev *sdev, u32 msg_id)
+{
+	struct snd_soc_component *scomp = sdev->component;
+	struct snd_sof_pcm_stream *stream;
+	struct sof_ipc_stream_posn posn;
+	struct snd_sof_pcm *spcm;
+	int direction, ret;
+
+	spcm = snd_sof_find_spcm_comp(scomp, msg_id, &direction);
+	if (!spcm) {
+		dev_err(sdev->dev, "period elapsed for unknown stream, msg_id %d\n",
+			msg_id);
+		return;
+	}
+
+	stream = &spcm->stream[direction];
+	ret = snd_sof_ipc_msg_data(sdev, stream->substream, &posn, sizeof(posn));
+	if (ret < 0) {
+		dev_warn(sdev->dev, "failed to read stream position: %d\n", ret);
+		return;
+	}
+
+	dev_vdbg(sdev->dev, "posn : host 0x%llx dai 0x%llx wall 0x%llx\n",
+		 posn.host_posn, posn.dai_posn, posn.wallclock);
+
+	memcpy(&stream->posn, &posn, sizeof(posn));
+
+	if (spcm->pcm.compress)
+		snd_sof_compr_fragment_elapsed(stream->cstream);
+	else if (stream->substream->runtime &&
+		 !stream->substream->runtime->no_period_wakeup)
+		/* only inform ALSA for period_wakeup mode */
+		snd_sof_pcm_period_elapsed(stream->substream);
+}
+
+/* DSP notifies host of an XRUN within FW */
+static void ipc3_xrun(struct snd_sof_dev *sdev, u32 msg_id)
+{
+	struct snd_soc_component *scomp = sdev->component;
+	struct snd_sof_pcm_stream *stream;
+	struct sof_ipc_stream_posn posn;
+	struct snd_sof_pcm *spcm;
+	int direction, ret;
+
+	spcm = snd_sof_find_spcm_comp(scomp, msg_id, &direction);
+	if (!spcm) {
+		dev_err(sdev->dev, "XRUN for unknown stream, msg_id %d\n",
+			msg_id);
+		return;
+	}
+
+	stream = &spcm->stream[direction];
+	ret = snd_sof_ipc_msg_data(sdev, stream->substream, &posn, sizeof(posn));
+	if (ret < 0) {
+		dev_warn(sdev->dev, "failed to read overrun position: %d\n", ret);
+		return;
+	}
+
+	dev_dbg(sdev->dev,  "posn XRUN: host %llx comp %d size %d\n",
+		posn.host_posn, posn.xrun_comp_id, posn.xrun_size);
+
+#if defined(CONFIG_SND_SOC_SOF_DEBUG_XRUN_STOP)
+	/* stop PCM on XRUN - used for pipeline debug */
+	memcpy(&stream->posn, &posn, sizeof(posn));
+	snd_pcm_stop_xrun(stream->substream);
+#endif
+}
+
+/* stream notifications from firmware */
+static void ipc3_stream_message(struct snd_sof_dev *sdev, void *msg_buf)
+{
+	struct sof_ipc_cmd_hdr *hdr = msg_buf;
+	u32 msg_type = hdr->cmd & SOF_CMD_TYPE_MASK;
+	u32 msg_id = SOF_IPC_MESSAGE_ID(hdr->cmd);
+
+	switch (msg_type) {
+	case SOF_IPC_STREAM_POSITION:
+		ipc3_period_elapsed(sdev, msg_id);
+		break;
+	case SOF_IPC_STREAM_TRIG_XRUN:
+		ipc3_xrun(sdev, msg_id);
+		break;
+	default:
+		dev_err(sdev->dev, "unhandled stream message %#x\n",
+			msg_id);
+		break;
+	}
+}
+
+/* component notifications from firmware */
+static void ipc3_comp_notification(struct snd_sof_dev *sdev, void *msg_buf)
+{
+	const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg;
+	struct sof_ipc_cmd_hdr *hdr = msg_buf;
+	u32 msg_type = hdr->cmd & SOF_CMD_TYPE_MASK;
+
+	switch (msg_type) {
+	case SOF_IPC_COMP_GET_VALUE:
+	case SOF_IPC_COMP_GET_DATA:
+		break;
+	default:
+		dev_err(sdev->dev, "unhandled component message %#x\n", msg_type);
+		return;
+	}
+
+	if (tplg_ops->control->update)
+		tplg_ops->control->update(sdev, msg_buf);
+}
+
+static void ipc3_trace_message(struct snd_sof_dev *sdev, void *msg_buf)
+{
+	struct sof_ipc_cmd_hdr *hdr = msg_buf;
+	u32 msg_type = hdr->cmd & SOF_CMD_TYPE_MASK;
+
+	switch (msg_type) {
+	case SOF_IPC_TRACE_DMA_POSITION:
+		snd_sof_trace_update_pos(sdev, msg_buf);
+		break;
+	default:
+		dev_err(sdev->dev, "unhandled trace message %#x\n", msg_type);
+		break;
+	}
+}
+
+/* DSP firmware has sent host a message  */
+static void sof_ipc3_rx_msg(struct snd_sof_dev *sdev)
+{
+	ipc3_rx_callback rx_callback = NULL;
+	struct sof_ipc_cmd_hdr hdr;
+	void *msg_buf;
+	u32 cmd;
+	int err;
+
+	/* read back header */
+	err = snd_sof_ipc_msg_data(sdev, NULL, &hdr, sizeof(hdr));
+	if (err < 0) {
+		dev_warn(sdev->dev, "failed to read IPC header: %d\n", err);
+		return;
+	}
+
+	if (hdr.size < sizeof(hdr)) {
+		dev_err(sdev->dev, "The received message size is invalid\n");
+		return;
+	}
+
+	ipc3_log_header(sdev->dev, "ipc rx", hdr.cmd);
+
+	cmd = hdr.cmd & SOF_GLB_TYPE_MASK;
+
+	/* check message type */
+	switch (cmd) {
+	case SOF_IPC_GLB_REPLY:
+		dev_err(sdev->dev, "ipc reply unknown\n");
+		break;
+	case SOF_IPC_FW_READY:
+		/* check for FW boot completion */
+		if (sdev->fw_state == SOF_FW_BOOT_IN_PROGRESS) {
+			err = sof_ops(sdev)->fw_ready(sdev, cmd);
+			if (err < 0)
+				sof_set_fw_state(sdev, SOF_FW_BOOT_READY_FAILED);
+			else
+				sof_set_fw_state(sdev, SOF_FW_BOOT_READY_OK);
+
+			/* wake up firmware loader */
+			wake_up(&sdev->boot_wait);
+		}
+		break;
+	case SOF_IPC_GLB_COMPOUND:
+	case SOF_IPC_GLB_TPLG_MSG:
+	case SOF_IPC_GLB_PM_MSG:
+		break;
+	case SOF_IPC_GLB_COMP_MSG:
+		rx_callback = ipc3_comp_notification;
+		break;
+	case SOF_IPC_GLB_STREAM_MSG:
+		rx_callback = ipc3_stream_message;
+		break;
+	case SOF_IPC_GLB_TRACE_MSG:
+		rx_callback = ipc3_trace_message;
+		break;
+	default:
+		dev_err(sdev->dev, "%s: Unknown DSP message: 0x%x\n", __func__, cmd);
+		break;
+	}
+
+	/* read the full message */
+	msg_buf = kmalloc(hdr.size, GFP_KERNEL);
+	if (!msg_buf)
+		return;
+
+	err = snd_sof_ipc_msg_data(sdev, NULL, msg_buf, hdr.size);
+	if (err < 0) {
+		dev_err(sdev->dev, "%s: Failed to read message: %d\n", __func__, err);
+	} else {
+		/* Call local handler for the message */
+		if (rx_callback)
+			rx_callback(sdev, msg_buf);
+
+		/* Notify registered clients */
+		sof_client_ipc_rx_dispatcher(sdev, msg_buf);
+	}
+
+	kfree(msg_buf);
+
+	ipc3_log_header(sdev->dev, "ipc rx done", hdr.cmd);
+}
+
 static int sof_ipc3_ctx_ipc(struct snd_sof_dev *sdev, int cmd)
 {
 	struct sof_ipc_pm_ctx pm_ctx = {
@@ -506,6 +717,7 @@ const struct sof_ipc_ops ipc3_ops = {
 	.pcm = &ipc3_pcm_ops,
 
 	.tx_msg = sof_ipc3_tx_msg,
+	.rx_msg = sof_ipc3_rx_msg,
 	.set_get_data = sof_ipc3_set_get_data,
 	.get_reply = sof_ipc3_get_reply,
 };
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 08/15] ASoC: SOF: ipc: Separate the ops checks by functions/topics
  2022-04-05 17:26 [PATCH 00/15] ASoC: SOF: Abstractions for top-level IPC ops Ranjani Sridharan
                   ` (6 preceding siblings ...)
  2022-04-05 17:27 ` [PATCH 07/15] ASoC: SOF: ipc3: Implement rx_msg " Ranjani Sridharan
@ 2022-04-05 17:27 ` Ranjani Sridharan
  2022-04-05 17:27 ` [PATCH 09/15] ASoC: SOF: ipc: Add check for mandatory IPC message handling ops Ranjani Sridharan
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ranjani Sridharan @ 2022-04-05 17:27 UTC (permalink / raw)
  To: alsa-devel
  Cc: tiwai, Peter Ujfalusi, Pierre-Louis Bossart, Ranjani Sridharan,
	broonie, Daniel Baluta

From: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>

Separate the mandatory ops checks by topics (pcm and topology for now) to
be able to provide intuitive feedback on the possible missing ops and to
make it easier to add new mandatory ops checks in the future.

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>
---
 sound/soc/sof/ipc.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c
index a78b74514438..4966a2a41704 100644
--- a/sound/soc/sof/ipc.c
+++ b/sound/soc/sof/ipc.c
@@ -1043,6 +1043,7 @@ struct snd_sof_ipc *snd_sof_ipc_init(struct snd_sof_dev *sdev)
 {
 	struct snd_sof_ipc *ipc;
 	struct snd_sof_ipc_msg *msg;
+	const struct sof_ipc_ops *ops;
 
 	ipc = devm_kzalloc(sdev->dev, sizeof(*ipc), GFP_KERNEL);
 	if (!ipc)
@@ -1062,11 +1063,16 @@ struct snd_sof_ipc *snd_sof_ipc_init(struct snd_sof_dev *sdev)
 	 * versions, this will need to be modified to use the selected version at runtime.
 	 */
 	ipc->ops = &ipc3_ops;
+	ops = ipc->ops;
 
 	/* check for mandatory ops */
-	if (!ipc->ops->pcm || !ipc->ops->tplg || !ipc->ops->tplg->widget ||
-	    !ipc->ops->tplg->control) {
-		dev_err(sdev->dev, "Invalid IPC ops\n");
+	if (!ops->pcm) {
+		dev_err(sdev->dev, "Missing IPC PCM ops\n");
+		return NULL;
+	}
+
+	if (!ops->tplg || !ops->tplg->widget || !ops->tplg->control) {
+		dev_err(sdev->dev, "Missing IPC topology ops\n");
 		return NULL;
 	}
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 09/15] ASoC: SOF: ipc: Add check for mandatory IPC message handling ops
  2022-04-05 17:26 [PATCH 00/15] ASoC: SOF: Abstractions for top-level IPC ops Ranjani Sridharan
                   ` (7 preceding siblings ...)
  2022-04-05 17:27 ` [PATCH 08/15] ASoC: SOF: ipc: Separate the ops checks by functions/topics Ranjani Sridharan
@ 2022-04-05 17:27 ` Ranjani Sridharan
  2022-04-05 17:27 ` [PATCH 10/15] ASoC: SOF: ipc: Use the get_reply ops in snd_sof_ipc_get_reply() Ranjani Sridharan
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ranjani Sridharan @ 2022-04-05 17:27 UTC (permalink / raw)
  To: alsa-devel
  Cc: tiwai, Peter Ujfalusi, Pierre-Louis Bossart, Ranjani Sridharan,
	broonie, Daniel Baluta

From: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>

Make sure that the mandatory IPC message handling ops are provided by the
IPC implementation.

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>
---
 sound/soc/sof/ipc.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c
index 4966a2a41704..d11c5e6e57fb 100644
--- a/sound/soc/sof/ipc.c
+++ b/sound/soc/sof/ipc.c
@@ -1066,6 +1066,11 @@ struct snd_sof_ipc *snd_sof_ipc_init(struct snd_sof_dev *sdev)
 	ops = ipc->ops;
 
 	/* check for mandatory ops */
+	if (!ops->tx_msg || !ops->rx_msg || !ops->set_get_data || !ops->get_reply) {
+		dev_err(sdev->dev, "Missing IPC message handling ops\n");
+		return NULL;
+	}
+
 	if (!ops->pcm) {
 		dev_err(sdev->dev, "Missing IPC PCM ops\n");
 		return NULL;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 10/15] ASoC: SOF: ipc: Use the get_reply ops in snd_sof_ipc_get_reply()
  2022-04-05 17:26 [PATCH 00/15] ASoC: SOF: Abstractions for top-level IPC ops Ranjani Sridharan
                   ` (8 preceding siblings ...)
  2022-04-05 17:27 ` [PATCH 09/15] ASoC: SOF: ipc: Add check for mandatory IPC message handling ops Ranjani Sridharan
@ 2022-04-05 17:27 ` Ranjani Sridharan
  2022-04-05 17:27 ` [PATCH 11/15] ASoC: SOF: ipc: Switch over to use the tx_msg and set_get_data ops Ranjani Sridharan
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ranjani Sridharan @ 2022-04-05 17:27 UTC (permalink / raw)
  To: alsa-devel
  Cc: tiwai, Peter Ujfalusi, Pierre-Louis Bossart, Ranjani Sridharan,
	broonie, Daniel Baluta

From: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>

Use the get_reply ops to allow IPC dependent handling of the reply message.

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>
---
 sound/soc/sof/ipc.c | 50 ++-------------------------------------------
 1 file changed, 2 insertions(+), 48 deletions(-)

diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c
index d11c5e6e57fb..39ec4361048a 100644
--- a/sound/soc/sof/ipc.c
+++ b/sound/soc/sof/ipc.c
@@ -443,63 +443,17 @@ EXPORT_SYMBOL(sof_ipc_tx_message_no_pm);
 /* Generic helper function to retrieve the reply */
 void snd_sof_ipc_get_reply(struct snd_sof_dev *sdev)
 {
-	struct snd_sof_ipc_msg *msg = sdev->msg;
-	struct sof_ipc_reply *reply;
-	int ret = 0;
-
 	/*
 	 * Sometimes, there is unexpected reply ipc arriving. The reply
 	 * ipc belongs to none of the ipcs sent from driver.
 	 * In this case, the driver must ignore the ipc.
 	 */
-	if (!msg) {
+	if (!sdev->msg) {
 		dev_warn(sdev->dev, "unexpected ipc interrupt raised!\n");
 		return;
 	}
 
-	/* 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) {
-		ret = reply->error;
-	} else 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");
-
-		ret = -EINVAL;
-	} else 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);
-	}
-
-	msg->reply_error = ret;
+	sdev->msg->reply_error = sdev->ipc->ops->get_reply(sdev);
 }
 EXPORT_SYMBOL(snd_sof_ipc_get_reply);
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 11/15] ASoC: SOF: ipc: Switch over to use the tx_msg and set_get_data ops
  2022-04-05 17:26 [PATCH 00/15] ASoC: SOF: Abstractions for top-level IPC ops Ranjani Sridharan
                   ` (9 preceding siblings ...)
  2022-04-05 17:27 ` [PATCH 10/15] ASoC: SOF: ipc: Use the get_reply ops in snd_sof_ipc_get_reply() Ranjani Sridharan
@ 2022-04-05 17:27 ` Ranjani Sridharan
  2022-04-05 17:27 ` [PATCH 12/15] ASoC: SOF: ipc: Switch over to use the rx_msg ops Ranjani Sridharan
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ranjani Sridharan @ 2022-04-05 17:27 UTC (permalink / raw)
  To: alsa-devel
  Cc: tiwai, Peter Ujfalusi, Pierre-Louis Bossart, Ranjani Sridharan,
	broonie, Daniel Baluta

From: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>

Use the new ops for sending messages and to handle large component data
set get operation.

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>
---
 sound/soc/sof/ipc.c | 301 ++++----------------------------------------
 1 file changed, 23 insertions(+), 278 deletions(-)

diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c
index 39ec4361048a..05c1ba0c2206 100644
--- a/sound/soc/sof/ipc.c
+++ b/sound/soc/sof/ipc.c
@@ -24,20 +24,6 @@ typedef void (*ipc_rx_callback)(struct snd_sof_dev *sdev, void *msg_buf);
 static void ipc_trace_message(struct snd_sof_dev *sdev, void *msg_buf);
 static void ipc_stream_message(struct snd_sof_dev *sdev, void *msg_buf);
 
-/*
- * IPC message Tx/Rx message handling.
- */
-
-struct sof_ipc_ctrl_data_params {
-	size_t msg_bytes;
-	size_t hdr_bytes;
-	size_t pl_size;
-	size_t elems;
-	u32 num_msg;
-	u8 *src;
-	u8 *dst;
-};
-
 #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_VERBOSE_IPC)
 static void ipc_log_header(struct device *dev, u8 *text, u32 cmd)
 {
@@ -242,104 +228,6 @@ static inline void ipc_log_header(struct device *dev, u8 *text, u32 cmd)
 }
 #endif
 
-/* wait for IPC message reply */
-static int tx_wait_done(struct snd_sof_ipc *ipc, struct snd_sof_ipc_msg *msg,
-			void *reply_data)
-{
-	struct snd_sof_dev *sdev = ipc->sdev;
-	struct sof_ipc_cmd_hdr *hdr = msg->msg_data;
-	int ret;
-
-	/* wait for DSP IPC completion */
-	ret = wait_event_timeout(msg->waitq, msg->ipc_complete,
-				 msecs_to_jiffies(sdev->ipc_timeout));
-
-	if (ret == 0) {
-		dev_err(sdev->dev,
-			"ipc tx timed out for %#x (msg/reply size: %d/%zu)\n",
-			hdr->cmd, hdr->size, msg->reply_size);
-		snd_sof_handle_fw_exception(ipc->sdev);
-		ret = -ETIMEDOUT;
-	} else {
-		ret = msg->reply_error;
-		if (ret < 0) {
-			dev_err(sdev->dev,
-				"ipc tx error for %#x (msg/reply size: %d/%zu): %d\n",
-				hdr->cmd, hdr->size, msg->reply_size, ret);
-		} else {
-			ipc_log_header(sdev->dev, "ipc tx succeeded", hdr->cmd);
-			if (msg->reply_size)
-				/* copy the data returned from DSP */
-				memcpy(reply_data, msg->reply_data,
-				       msg->reply_size);
-		}
-
-		/* re-enable dumps after successful IPC tx */
-		if (sdev->ipc_dump_printed) {
-			sdev->dbg_dump_printed = false;
-			sdev->ipc_dump_printed = false;
-		}
-	}
-
-	return ret;
-}
-
-/* send IPC message from host to DSP */
-static int sof_ipc_tx_message_unlocked(struct snd_sof_ipc *ipc,
-				       void *msg_data, size_t msg_bytes,
-				       void *reply_data, size_t reply_bytes)
-{
-	struct sof_ipc_cmd_hdr *hdr = msg_data;
-	struct snd_sof_dev *sdev = ipc->sdev;
-	struct snd_sof_ipc_msg *msg;
-	int ret;
-
-	if (!msg_data || msg_bytes < sizeof(*hdr)) {
-		dev_err_ratelimited(sdev->dev, "No IPC message to send\n");
-		return -EINVAL;
-	}
-
-	if (ipc->disable_ipc_tx || sdev->fw_state != SOF_FW_BOOT_COMPLETE)
-		return -ENODEV;
-
-	/*
-	 * The spin-lock is also still needed to protect message objects against
-	 * other atomic contexts.
-	 */
-	spin_lock_irq(&sdev->ipc_lock);
-
-	/* initialise the message */
-	msg = &ipc->msg;
-
-	/* attach message data */
-	msg->msg_data = msg_data;
-	msg->msg_size = msg_bytes;
-
-	msg->reply_size = reply_bytes;
-	msg->reply_error = 0;
-
-	sdev->msg = msg;
-
-	ret = snd_sof_dsp_send_msg(sdev, msg);
-	/* Next reply that we receive will be related to this message */
-	if (!ret)
-		msg->ipc_complete = false;
-
-	spin_unlock_irq(&sdev->ipc_lock);
-
-	if (ret) {
-		dev_err_ratelimited(sdev->dev,
-				    "error: ipc tx failed with error %d\n",
-				    ret);
-		return ret;
-	}
-
-	ipc_log_header(sdev->dev, "ipc tx", hdr->cmd);
-
-	/* now wait for completion */
-	return tx_wait_done(ipc, msg, reply_data);
-}
-
 /**
  * sof_ipc_send_msg - generic function to prepare and send one IPC message
  * @sdev:		pointer to SOF core device struct
@@ -397,20 +285,12 @@ int sof_ipc_send_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_bytes,
 int sof_ipc_tx_message(struct snd_sof_ipc *ipc, void *msg_data, size_t msg_bytes,
 		       void *reply_data, size_t reply_bytes)
 {
-	const struct sof_dsp_power_state target_state = {
-		.state = SOF_DSP_PM_D0,
-	};
-	int ret;
-
-	/* ensure the DSP is in D0 before sending a new IPC */
-	ret = snd_sof_dsp_set_power_state(ipc->sdev, &target_state);
-	if (ret < 0) {
-		dev_err(ipc->sdev->dev, "error: resuming DSP %d\n", ret);
-		return ret;
-	}
+	if (msg_bytes > ipc->max_payload_size ||
+	    reply_bytes > ipc->max_payload_size)
+		return -ENOBUFS;
 
-	return sof_ipc_tx_message_no_pm(ipc, msg_data, msg_bytes,
-					reply_data, reply_bytes);
+	return ipc->ops->tx_msg(ipc->sdev, msg_data, msg_bytes, reply_data,
+				reply_bytes, false);
 }
 EXPORT_SYMBOL(sof_ipc_tx_message);
 
@@ -422,21 +302,12 @@ EXPORT_SYMBOL(sof_ipc_tx_message);
 int sof_ipc_tx_message_no_pm(struct snd_sof_ipc *ipc, void *msg_data, size_t msg_bytes,
 			     void *reply_data, size_t reply_bytes)
 {
-	int ret;
-
 	if (msg_bytes > ipc->max_payload_size ||
 	    reply_bytes > ipc->max_payload_size)
 		return -ENOBUFS;
 
-	/* Serialise IPC TX */
-	mutex_lock(&ipc->tx_mutex);
-
-	ret = sof_ipc_tx_message_unlocked(ipc, msg_data, msg_bytes,
-					  reply_data, reply_bytes);
-
-	mutex_unlock(&ipc->tx_mutex);
-
-	return ret;
+	return ipc->ops->tx_msg(ipc->sdev, msg_data, msg_bytes, reply_data,
+				reply_bytes, true);
 }
 EXPORT_SYMBOL(sof_ipc_tx_message_no_pm);
 
@@ -718,103 +589,6 @@ int snd_sof_ipc_stream_posn(struct snd_soc_component *scomp,
 }
 EXPORT_SYMBOL(snd_sof_ipc_stream_posn);
 
-static int sof_get_ctrl_copy_params(enum sof_ipc_ctrl_type ctrl_type,
-				    struct sof_ipc_ctrl_data *src,
-				    struct sof_ipc_ctrl_data *dst,
-				    struct sof_ipc_ctrl_data_params *sparams)
-{
-	switch (ctrl_type) {
-	case SOF_CTRL_TYPE_VALUE_CHAN_GET:
-	case SOF_CTRL_TYPE_VALUE_CHAN_SET:
-		sparams->src = (u8 *)src->chanv;
-		sparams->dst = (u8 *)dst->chanv;
-		break;
-	case SOF_CTRL_TYPE_DATA_GET:
-	case SOF_CTRL_TYPE_DATA_SET:
-		sparams->src = (u8 *)src->data->data;
-		sparams->dst = (u8 *)dst->data->data;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/* calculate payload size and number of messages */
-	sparams->pl_size = SOF_IPC_MSG_MAX_SIZE - sparams->hdr_bytes;
-	sparams->num_msg = DIV_ROUND_UP(sparams->msg_bytes, sparams->pl_size);
-
-	return 0;
-}
-
-static int sof_set_get_large_ctrl_data(struct snd_sof_dev *sdev,
-				       struct sof_ipc_ctrl_data *cdata,
-				       struct sof_ipc_ctrl_data_params *sparams,
-				       bool set)
-{
-	struct sof_ipc_ctrl_data *partdata;
-	size_t send_bytes;
-	size_t offset = 0;
-	size_t msg_bytes;
-	size_t pl_size;
-	int err;
-	int i;
-
-	/* allocate max ipc size because we have at least one */
-	partdata = kzalloc(SOF_IPC_MSG_MAX_SIZE, GFP_KERNEL);
-	if (!partdata)
-		return -ENOMEM;
-
-	if (set)
-		err = sof_get_ctrl_copy_params(cdata->type, cdata, partdata,
-					       sparams);
-	else
-		err = sof_get_ctrl_copy_params(cdata->type, partdata, cdata,
-					       sparams);
-	if (err < 0) {
-		kfree(partdata);
-		return err;
-	}
-
-	msg_bytes = sparams->msg_bytes;
-	pl_size = sparams->pl_size;
-
-	/* copy the header data */
-	memcpy(partdata, cdata, sparams->hdr_bytes);
-
-	/* Serialise IPC TX */
-	mutex_lock(&sdev->ipc->tx_mutex);
-
-	/* copy the payload data in a loop */
-	for (i = 0; i < sparams->num_msg; i++) {
-		send_bytes = min(msg_bytes, pl_size);
-		partdata->num_elems = send_bytes;
-		partdata->rhdr.hdr.size = sparams->hdr_bytes + send_bytes;
-		partdata->msg_index = i;
-		msg_bytes -= send_bytes;
-		partdata->elems_remaining = msg_bytes;
-
-		if (set)
-			memcpy(sparams->dst, sparams->src + offset, send_bytes);
-
-		err = sof_ipc_tx_message_unlocked(sdev->ipc,
-						  partdata,
-						  partdata->rhdr.hdr.size,
-						  partdata,
-						  partdata->rhdr.hdr.size);
-		if (err < 0)
-			break;
-
-		if (!set)
-			memcpy(sparams->dst + offset, sparams->src, send_bytes);
-
-		offset += pl_size;
-	}
-
-	mutex_unlock(&sdev->ipc->tx_mutex);
-
-	kfree(partdata);
-	return err;
-}
-
 /*
  * IPC get()/set() for kcontrols.
  */
@@ -823,14 +597,11 @@ int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol, bool set)
 	struct snd_soc_component *scomp = scontrol->scomp;
 	struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
-	struct sof_ipc_fw_ready *ready = &sdev->fw_ready;
-	struct sof_ipc_fw_version *v = &ready->version;
-	struct sof_ipc_ctrl_data_params sparams;
+	const struct sof_ipc_ops *iops = sdev->ipc->ops;
 	enum sof_ipc_ctrl_type ctrl_type;
 	struct snd_sof_widget *swidget;
 	bool widget_found = false;
-	u32 ipc_cmd;
-	int err;
+	u32 ipc_cmd, msg_bytes;
 
 	list_for_each_entry(swidget, &sdev->widget_list, list) {
 		if (swidget->comp_id == scontrol->comp_id) {
@@ -840,7 +611,8 @@ int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol, bool set)
 	}
 
 	if (!widget_found) {
-		dev_err(sdev->dev, "error: can't find widget with id %d\n", scontrol->comp_id);
+		dev_err(sdev->dev, "%s: can't find widget with id %d\n", __func__,
+			scontrol->comp_id);
 		return -EINVAL;
 	}
 
@@ -875,55 +647,28 @@ int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol, bool set)
 	switch (cdata->type) {
 	case SOF_CTRL_TYPE_VALUE_CHAN_GET:
 	case SOF_CTRL_TYPE_VALUE_CHAN_SET:
-		sparams.msg_bytes = scontrol->num_channels *
-			sizeof(struct sof_ipc_ctrl_value_chan);
-		sparams.hdr_bytes = sizeof(struct sof_ipc_ctrl_data);
-		sparams.elems = scontrol->num_channels;
+		cdata->num_elems = scontrol->num_channels;
+
+		msg_bytes = scontrol->num_channels *
+			    sizeof(struct sof_ipc_ctrl_value_chan);
+		msg_bytes += sizeof(struct sof_ipc_ctrl_data);
 		break;
 	case SOF_CTRL_TYPE_DATA_GET:
 	case SOF_CTRL_TYPE_DATA_SET:
-		sparams.msg_bytes = cdata->data->size;
-		sparams.hdr_bytes = sizeof(struct sof_ipc_ctrl_data) +
-			sizeof(struct sof_abi_hdr);
-		sparams.elems = cdata->data->size;
+		cdata->num_elems = cdata->data->size;
+
+		msg_bytes = cdata->data->size;
+		msg_bytes += sizeof(struct sof_ipc_ctrl_data) +
+			     sizeof(struct sof_abi_hdr);
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	cdata->rhdr.hdr.size = sparams.msg_bytes + sparams.hdr_bytes;
-	cdata->num_elems = sparams.elems;
+	cdata->rhdr.hdr.size = msg_bytes;
 	cdata->elems_remaining = 0;
 
-	/* send normal size ipc in one part */
-	if (cdata->rhdr.hdr.size <= SOF_IPC_MSG_MAX_SIZE) {
-		err = sof_ipc_tx_message(sdev->ipc, cdata, cdata->rhdr.hdr.size,
-					 cdata, cdata->rhdr.hdr.size);
-
-		if (err < 0)
-			dev_err(sdev->dev, "error: set/get ctrl ipc comp %d\n",
-				cdata->comp_id);
-
-		return err;
-	}
-
-	/* data is bigger than max ipc size, chop into smaller pieces */
-	dev_dbg(sdev->dev, "large ipc size %u, control size %u\n",
-		cdata->rhdr.hdr.size, scontrol->size);
-
-	/* large messages is only supported from ABI 3.3.0 onwards */
-	if (v->abi_version < SOF_ABI_VER(3, 3, 0)) {
-		dev_err(sdev->dev, "error: incompatible FW ABI version\n");
-		return -EINVAL;
-	}
-
-	err = sof_set_get_large_ctrl_data(sdev, cdata, &sparams, set);
-
-	if (err < 0)
-		dev_err(sdev->dev, "error: set/get large ctrl ipc comp %d\n",
-			cdata->comp_id);
-
-	return err;
+	return iops->set_get_data(sdev, cdata, cdata->rhdr.hdr.size, set);
 }
 EXPORT_SYMBOL(snd_sof_ipc_set_get_comp_data);
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 12/15] ASoC: SOF: ipc: Switch over to use the rx_msg ops
  2022-04-05 17:26 [PATCH 00/15] ASoC: SOF: Abstractions for top-level IPC ops Ranjani Sridharan
                   ` (10 preceding siblings ...)
  2022-04-05 17:27 ` [PATCH 11/15] ASoC: SOF: ipc: Switch over to use the tx_msg and set_get_data ops Ranjani Sridharan
@ 2022-04-05 17:27 ` Ranjani Sridharan
  2022-04-05 17:27 ` [PATCH 13/15] ASoC: SOF: Add widget_kcontrol_setup control ops for IPC3 Ranjani Sridharan
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ranjani Sridharan @ 2022-04-05 17:27 UTC (permalink / raw)
  To: alsa-devel
  Cc: tiwai, Peter Ujfalusi, Pierre-Louis Bossart, Ranjani Sridharan,
	broonie, Daniel Baluta

From: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>

Use the new ops for handling message reception.

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>
---
 sound/soc/sof/ipc.c      | 452 ---------------------------------------
 sound/soc/sof/sof-priv.h |   5 +-
 2 files changed, 4 insertions(+), 453 deletions(-)

diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c
index 05c1ba0c2206..45c487ab8b54 100644
--- a/sound/soc/sof/ipc.c
+++ b/sound/soc/sof/ipc.c
@@ -19,215 +19,6 @@
 #include "ops.h"
 #include "ipc3-ops.h"
 
-typedef void (*ipc_rx_callback)(struct snd_sof_dev *sdev, void *msg_buf);
-
-static void ipc_trace_message(struct snd_sof_dev *sdev, void *msg_buf);
-static void ipc_stream_message(struct snd_sof_dev *sdev, void *msg_buf);
-
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_VERBOSE_IPC)
-static void ipc_log_header(struct device *dev, u8 *text, u32 cmd)
-{
-	u8 *str;
-	u8 *str2 = NULL;
-	u32 glb;
-	u32 type;
-	bool vdbg = false;
-
-	glb = cmd & SOF_GLB_TYPE_MASK;
-	type = cmd & SOF_CMD_TYPE_MASK;
-
-	switch (glb) {
-	case SOF_IPC_GLB_REPLY:
-		str = "GLB_REPLY"; break;
-	case SOF_IPC_GLB_COMPOUND:
-		str = "GLB_COMPOUND"; break;
-	case SOF_IPC_GLB_TPLG_MSG:
-		str = "GLB_TPLG_MSG";
-		switch (type) {
-		case SOF_IPC_TPLG_COMP_NEW:
-			str2 = "COMP_NEW"; break;
-		case SOF_IPC_TPLG_COMP_FREE:
-			str2 = "COMP_FREE"; break;
-		case SOF_IPC_TPLG_COMP_CONNECT:
-			str2 = "COMP_CONNECT"; break;
-		case SOF_IPC_TPLG_PIPE_NEW:
-			str2 = "PIPE_NEW"; break;
-		case SOF_IPC_TPLG_PIPE_FREE:
-			str2 = "PIPE_FREE"; break;
-		case SOF_IPC_TPLG_PIPE_CONNECT:
-			str2 = "PIPE_CONNECT"; break;
-		case SOF_IPC_TPLG_PIPE_COMPLETE:
-			str2 = "PIPE_COMPLETE"; break;
-		case SOF_IPC_TPLG_BUFFER_NEW:
-			str2 = "BUFFER_NEW"; break;
-		case SOF_IPC_TPLG_BUFFER_FREE:
-			str2 = "BUFFER_FREE"; break;
-		default:
-			str2 = "unknown type"; break;
-		}
-		break;
-	case SOF_IPC_GLB_PM_MSG:
-		str = "GLB_PM_MSG";
-		switch (type) {
-		case SOF_IPC_PM_CTX_SAVE:
-			str2 = "CTX_SAVE"; break;
-		case SOF_IPC_PM_CTX_RESTORE:
-			str2 = "CTX_RESTORE"; break;
-		case SOF_IPC_PM_CTX_SIZE:
-			str2 = "CTX_SIZE"; break;
-		case SOF_IPC_PM_CLK_SET:
-			str2 = "CLK_SET"; break;
-		case SOF_IPC_PM_CLK_GET:
-			str2 = "CLK_GET"; break;
-		case SOF_IPC_PM_CLK_REQ:
-			str2 = "CLK_REQ"; break;
-		case SOF_IPC_PM_CORE_ENABLE:
-			str2 = "CORE_ENABLE"; break;
-		case SOF_IPC_PM_GATE:
-			str2 = "GATE"; break;
-		default:
-			str2 = "unknown type"; break;
-		}
-		break;
-	case SOF_IPC_GLB_COMP_MSG:
-		str = "GLB_COMP_MSG";
-		switch (type) {
-		case SOF_IPC_COMP_SET_VALUE:
-			str2 = "SET_VALUE"; break;
-		case SOF_IPC_COMP_GET_VALUE:
-			str2 = "GET_VALUE"; break;
-		case SOF_IPC_COMP_SET_DATA:
-			str2 = "SET_DATA"; break;
-		case SOF_IPC_COMP_GET_DATA:
-			str2 = "GET_DATA"; break;
-		default:
-			str2 = "unknown type"; break;
-		}
-		break;
-	case SOF_IPC_GLB_STREAM_MSG:
-		str = "GLB_STREAM_MSG";
-		switch (type) {
-		case SOF_IPC_STREAM_PCM_PARAMS:
-			str2 = "PCM_PARAMS"; break;
-		case SOF_IPC_STREAM_PCM_PARAMS_REPLY:
-			str2 = "PCM_REPLY"; break;
-		case SOF_IPC_STREAM_PCM_FREE:
-			str2 = "PCM_FREE"; break;
-		case SOF_IPC_STREAM_TRIG_START:
-			str2 = "TRIG_START"; break;
-		case SOF_IPC_STREAM_TRIG_STOP:
-			str2 = "TRIG_STOP"; break;
-		case SOF_IPC_STREAM_TRIG_PAUSE:
-			str2 = "TRIG_PAUSE"; break;
-		case SOF_IPC_STREAM_TRIG_RELEASE:
-			str2 = "TRIG_RELEASE"; break;
-		case SOF_IPC_STREAM_TRIG_DRAIN:
-			str2 = "TRIG_DRAIN"; break;
-		case SOF_IPC_STREAM_TRIG_XRUN:
-			str2 = "TRIG_XRUN"; break;
-		case SOF_IPC_STREAM_POSITION:
-			vdbg = true;
-			str2 = "POSITION"; break;
-		case SOF_IPC_STREAM_VORBIS_PARAMS:
-			str2 = "VORBIS_PARAMS"; break;
-		case SOF_IPC_STREAM_VORBIS_FREE:
-			str2 = "VORBIS_FREE"; break;
-		default:
-			str2 = "unknown type"; break;
-		}
-		break;
-	case SOF_IPC_FW_READY:
-		str = "FW_READY"; break;
-	case SOF_IPC_GLB_DAI_MSG:
-		str = "GLB_DAI_MSG";
-		switch (type) {
-		case SOF_IPC_DAI_CONFIG:
-			str2 = "CONFIG"; break;
-		case SOF_IPC_DAI_LOOPBACK:
-			str2 = "LOOPBACK"; break;
-		default:
-			str2 = "unknown type"; break;
-		}
-		break;
-	case SOF_IPC_GLB_TRACE_MSG:
-		str = "GLB_TRACE_MSG";
-		switch (type) {
-		case SOF_IPC_TRACE_DMA_PARAMS:
-			str2 = "DMA_PARAMS"; break;
-		case SOF_IPC_TRACE_DMA_POSITION:
-			str2 = "DMA_POSITION"; break;
-		case SOF_IPC_TRACE_DMA_PARAMS_EXT:
-			str2 = "DMA_PARAMS_EXT"; break;
-		case SOF_IPC_TRACE_FILTER_UPDATE:
-			str2 = "FILTER_UPDATE"; break;
-		case SOF_IPC_TRACE_DMA_FREE:
-			str2 = "DMA_FREE"; break;
-		default:
-			str2 = "unknown type"; break;
-		}
-		break;
-	case SOF_IPC_GLB_TEST_MSG:
-		str = "GLB_TEST_MSG";
-		switch (type) {
-		case SOF_IPC_TEST_IPC_FLOOD:
-			str2 = "IPC_FLOOD"; break;
-		default:
-			str2 = "unknown type"; break;
-		}
-		break;
-	case SOF_IPC_GLB_DEBUG:
-		str = "GLB_DEBUG";
-		switch (type) {
-		case SOF_IPC_DEBUG_MEM_USAGE:
-			str2 = "MEM_USAGE"; break;
-		default:
-			str2 = "unknown type"; break;
-		}
-		break;
-	case SOF_IPC_GLB_PROBE:
-		str = "GLB_PROBE";
-		switch (type) {
-		case SOF_IPC_PROBE_INIT:
-			str2 = "INIT"; break;
-		case SOF_IPC_PROBE_DEINIT:
-			str2 = "DEINIT"; break;
-		case SOF_IPC_PROBE_DMA_ADD:
-			str2 = "DMA_ADD"; break;
-		case SOF_IPC_PROBE_DMA_INFO:
-			str2 = "DMA_INFO"; break;
-		case SOF_IPC_PROBE_DMA_REMOVE:
-			str2 = "DMA_REMOVE"; break;
-		case SOF_IPC_PROBE_POINT_ADD:
-			str2 = "POINT_ADD"; break;
-		case SOF_IPC_PROBE_POINT_INFO:
-			str2 = "POINT_INFO"; break;
-		case SOF_IPC_PROBE_POINT_REMOVE:
-			str2 = "POINT_REMOVE"; break;
-		default:
-			str2 = "unknown type"; break;
-		}
-		break;
-	default:
-		str = "unknown GLB command"; break;
-	}
-
-	if (str2) {
-		if (vdbg)
-			dev_vdbg(dev, "%s: 0x%x: %s: %s\n", text, cmd, str, str2);
-		else
-			dev_dbg(dev, "%s: 0x%x: %s: %s\n", text, cmd, str, str2);
-	} else {
-		dev_dbg(dev, "%s: 0x%x: %s\n", text, cmd, str);
-	}
-}
-#else
-static inline void ipc_log_header(struct device *dev, u8 *text, u32 cmd)
-{
-	if ((cmd & SOF_GLB_TYPE_MASK) != SOF_IPC_GLB_TRACE_MSG)
-		dev_dbg(dev, "%s: 0x%x\n", text, cmd);
-}
-#endif
-
 /**
  * sof_ipc_send_msg - generic function to prepare and send one IPC message
  * @sdev:		pointer to SOF core device struct
@@ -346,249 +137,6 @@ void snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id)
 }
 EXPORT_SYMBOL(snd_sof_ipc_reply);
 
-static void ipc_comp_notification(struct snd_sof_dev *sdev, void *msg_buf)
-{
-	const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg;
-	struct sof_ipc_cmd_hdr *hdr = msg_buf;
-	u32 msg_type = hdr->cmd & SOF_CMD_TYPE_MASK;
-
-	switch (msg_type) {
-	case SOF_IPC_COMP_GET_VALUE:
-	case SOF_IPC_COMP_GET_DATA:
-		break;
-	default:
-		dev_err(sdev->dev, "error: unhandled component message %#x\n", msg_type);
-		return;
-	}
-
-	if (tplg_ops->control->update)
-		tplg_ops->control->update(sdev, msg_buf);
-}
-
-/* DSP firmware has sent host a message  */
-void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev)
-{
-	ipc_rx_callback rx_callback = NULL;
-	struct sof_ipc_cmd_hdr hdr;
-	void *msg_buf;
-	u32 cmd;
-	int err;
-
-	/* read back header */
-	err = snd_sof_ipc_msg_data(sdev, NULL, &hdr, sizeof(hdr));
-	if (err < 0) {
-		dev_warn(sdev->dev, "failed to read IPC header: %d\n", err);
-		return;
-	}
-
-	if (hdr.size < sizeof(hdr)) {
-		dev_err(sdev->dev, "The received message size is invalid\n");
-		return;
-	}
-
-	ipc_log_header(sdev->dev, "ipc rx", hdr.cmd);
-
-	cmd = hdr.cmd & SOF_GLB_TYPE_MASK;
-
-	/* check message type */
-	switch (cmd) {
-	case SOF_IPC_GLB_REPLY:
-		dev_err(sdev->dev, "error: ipc reply unknown\n");
-		break;
-	case SOF_IPC_FW_READY:
-		/* check for FW boot completion */
-		if (sdev->fw_state == SOF_FW_BOOT_IN_PROGRESS) {
-			err = sof_ops(sdev)->fw_ready(sdev, cmd);
-			if (err < 0)
-				sof_set_fw_state(sdev, SOF_FW_BOOT_READY_FAILED);
-			else
-				sof_set_fw_state(sdev, SOF_FW_BOOT_READY_OK);
-
-			/* wake up firmware loader */
-			wake_up(&sdev->boot_wait);
-		}
-		break;
-	case SOF_IPC_GLB_COMPOUND:
-	case SOF_IPC_GLB_TPLG_MSG:
-	case SOF_IPC_GLB_PM_MSG:
-		break;
-	case SOF_IPC_GLB_COMP_MSG:
-		rx_callback = ipc_comp_notification;
-		break;
-	case SOF_IPC_GLB_STREAM_MSG:
-		rx_callback = ipc_stream_message;
-		break;
-	case SOF_IPC_GLB_TRACE_MSG:
-		rx_callback = ipc_trace_message;
-		break;
-	default:
-		dev_err(sdev->dev, "%s: Unknown DSP message: 0x%x\n", __func__, cmd);
-		break;
-	}
-
-	/* read the full message */
-	msg_buf = kmalloc(hdr.size, GFP_KERNEL);
-	if (!msg_buf)
-		return;
-
-	err = snd_sof_ipc_msg_data(sdev, NULL, msg_buf, hdr.size);
-	if (err < 0) {
-		dev_err(sdev->dev, "%s: Failed to read message: %d\n", __func__, err);
-	} else {
-		/* Call local handler for the message */
-		if (rx_callback)
-			rx_callback(sdev, msg_buf);
-
-		/* Notify registered clients */
-		sof_client_ipc_rx_dispatcher(sdev, msg_buf);
-	}
-
-	kfree(msg_buf);
-
-	ipc_log_header(sdev->dev, "ipc rx done", hdr.cmd);
-}
-EXPORT_SYMBOL(snd_sof_ipc_msgs_rx);
-
-/*
- * IPC trace mechanism.
- */
-
-static void ipc_trace_message(struct snd_sof_dev *sdev, void *msg_buf)
-{
-	struct sof_ipc_cmd_hdr *hdr = msg_buf;
-	u32 msg_type = hdr->cmd & SOF_CMD_TYPE_MASK;
-
-	switch (msg_type) {
-	case SOF_IPC_TRACE_DMA_POSITION:
-		snd_sof_trace_update_pos(sdev, msg_buf);
-		break;
-	default:
-		dev_err(sdev->dev, "error: unhandled trace message %#x\n", msg_type);
-		break;
-	}
-}
-
-/*
- * IPC stream position.
- */
-
-static void ipc_period_elapsed(struct snd_sof_dev *sdev, u32 msg_id)
-{
-	struct snd_soc_component *scomp = sdev->component;
-	struct snd_sof_pcm_stream *stream;
-	struct sof_ipc_stream_posn posn;
-	struct snd_sof_pcm *spcm;
-	int direction, ret;
-
-	spcm = snd_sof_find_spcm_comp(scomp, msg_id, &direction);
-	if (!spcm) {
-		dev_err(sdev->dev,
-			"error: period elapsed for unknown stream, msg_id %d\n",
-			msg_id);
-		return;
-	}
-
-	stream = &spcm->stream[direction];
-	ret = snd_sof_ipc_msg_data(sdev, stream->substream, &posn, sizeof(posn));
-	if (ret < 0) {
-		dev_warn(sdev->dev, "failed to read stream position: %d\n", ret);
-		return;
-	}
-
-	dev_vdbg(sdev->dev, "posn : host 0x%llx dai 0x%llx wall 0x%llx\n",
-		 posn.host_posn, posn.dai_posn, posn.wallclock);
-
-	memcpy(&stream->posn, &posn, sizeof(posn));
-
-	if (spcm->pcm.compress)
-		snd_sof_compr_fragment_elapsed(stream->cstream);
-	else if (stream->substream->runtime &&
-		 !stream->substream->runtime->no_period_wakeup)
-		/* only inform ALSA for period_wakeup mode */
-		snd_sof_pcm_period_elapsed(stream->substream);
-}
-
-/* DSP notifies host of an XRUN within FW */
-static void ipc_xrun(struct snd_sof_dev *sdev, u32 msg_id)
-{
-	struct snd_soc_component *scomp = sdev->component;
-	struct snd_sof_pcm_stream *stream;
-	struct sof_ipc_stream_posn posn;
-	struct snd_sof_pcm *spcm;
-	int direction, ret;
-
-	spcm = snd_sof_find_spcm_comp(scomp, msg_id, &direction);
-	if (!spcm) {
-		dev_err(sdev->dev, "error: XRUN for unknown stream, msg_id %d\n",
-			msg_id);
-		return;
-	}
-
-	stream = &spcm->stream[direction];
-	ret = snd_sof_ipc_msg_data(sdev, stream->substream, &posn, sizeof(posn));
-	if (ret < 0) {
-		dev_warn(sdev->dev, "failed to read overrun position: %d\n", ret);
-		return;
-	}
-
-	dev_dbg(sdev->dev,  "posn XRUN: host %llx comp %d size %d\n",
-		posn.host_posn, posn.xrun_comp_id, posn.xrun_size);
-
-#if defined(CONFIG_SND_SOC_SOF_DEBUG_XRUN_STOP)
-	/* stop PCM on XRUN - used for pipeline debug */
-	memcpy(&stream->posn, &posn, sizeof(posn));
-	snd_pcm_stop_xrun(stream->substream);
-#endif
-}
-
-/* stream notifications from DSP FW */
-static void ipc_stream_message(struct snd_sof_dev *sdev, void *msg_buf)
-{
-	struct sof_ipc_cmd_hdr *hdr = msg_buf;
-	u32 msg_type = hdr->cmd & SOF_CMD_TYPE_MASK;
-	u32 msg_id = SOF_IPC_MESSAGE_ID(hdr->cmd);
-
-	switch (msg_type) {
-	case SOF_IPC_STREAM_POSITION:
-		ipc_period_elapsed(sdev, msg_id);
-		break;
-	case SOF_IPC_STREAM_TRIG_XRUN:
-		ipc_xrun(sdev, msg_id);
-		break;
-	default:
-		dev_err(sdev->dev, "error: unhandled stream message %#x\n",
-			msg_id);
-		break;
-	}
-}
-
-/* get stream position IPC - use faster MMIO method if available on platform */
-int snd_sof_ipc_stream_posn(struct snd_soc_component *scomp,
-			    struct snd_sof_pcm *spcm, int direction,
-			    struct sof_ipc_stream_posn *posn)
-{
-	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
-	struct sof_ipc_stream stream;
-	int err;
-
-	/* read position via slower IPC */
-	stream.hdr.size = sizeof(stream);
-	stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_POSITION;
-	stream.comp_id = spcm->stream[direction].comp_id;
-
-	/* send IPC to the DSP */
-	err = sof_ipc_tx_message(sdev->ipc, &stream, sizeof(stream), posn,
-				 sizeof(*posn));
-	if (err < 0) {
-		dev_err(sdev->dev, "error: failed to get stream %d position\n",
-			stream.comp_id);
-		return err;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(snd_sof_ipc_stream_posn);
-
 /*
  * IPC get()/set() for kcontrols.
  */
diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h
index 2bf7844f01d7..6a09e5a73a50 100644
--- a/sound/soc/sof/sof-priv.h
+++ b/sound/soc/sof/sof-priv.h
@@ -603,7 +603,10 @@ struct snd_sof_ipc *snd_sof_ipc_init(struct snd_sof_dev *sdev);
 void snd_sof_ipc_free(struct snd_sof_dev *sdev);
 void snd_sof_ipc_get_reply(struct snd_sof_dev *sdev);
 void snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id);
-void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev);
+static inline void snd_sof_ipc_msgs_rx(struct snd_sof_dev *sdev)
+{
+	sdev->ipc->ops->rx_msg(sdev);
+}
 int snd_sof_ipc_valid(struct snd_sof_dev *sdev);
 int sof_ipc_tx_message(struct snd_sof_ipc *ipc, void *msg_data, size_t msg_bytes,
 		       void *reply_data, size_t reply_bytes);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 13/15] ASoC: SOF: Add widget_kcontrol_setup control ops for IPC3
  2022-04-05 17:26 [PATCH 00/15] ASoC: SOF: Abstractions for top-level IPC ops Ranjani Sridharan
                   ` (11 preceding siblings ...)
  2022-04-05 17:27 ` [PATCH 12/15] ASoC: SOF: ipc: Switch over to use the rx_msg ops Ranjani Sridharan
@ 2022-04-05 17:27 ` Ranjani Sridharan
  2022-04-05 17:27 ` [PATCH 14/15] ASoC: SOF: sof-audio: Use the widget_kcontrol_setup ops for kcontrol set up Ranjani Sridharan
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ranjani Sridharan @ 2022-04-05 17:27 UTC (permalink / raw)
  To: alsa-devel
  Cc: tiwai, Peter Ujfalusi, Pierre-Louis Bossart, Ranjani Sridharan,
	broonie, Daniel Baluta

From: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>

Define and set the widget_kcontrol_setup control IPC ops for IPC3.

The widget_kcontrol_setup callback can be used to set up all
kcontrols associated with the swidget.

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>
---
 sound/soc/sof/ipc3-control.c | 38 ++++++++++++++++++++++++++++++++++++
 sound/soc/sof/sof-audio.h    |  2 ++
 2 files changed, 40 insertions(+)

diff --git a/sound/soc/sof/ipc3-control.c b/sound/soc/sof/ipc3-control.c
index cdd5ad860a94..4e647142dc2b 100644
--- a/sound/soc/sof/ipc3-control.c
+++ b/sound/soc/sof/ipc3-control.c
@@ -578,6 +578,43 @@ static void sof_ipc3_control_update(struct snd_sof_dev *sdev, void *ipc_control_
 	snd_ctl_notify_one(swidget->scomp->card->snd_card, SNDRV_CTL_EVENT_MASK_VALUE, kc, 0);
 }
 
+static int sof_ipc3_widget_kcontrol_setup(struct snd_sof_dev *sdev,
+					  struct snd_sof_widget *swidget)
+{
+	struct snd_sof_control *scontrol;
+	int ret;
+
+	/* set up all controls for the widget */
+	list_for_each_entry(scontrol, &sdev->kcontrol_list, list)
+		if (scontrol->comp_id == swidget->comp_id) {
+			/* set kcontrol data in DSP */
+			ret = snd_sof_ipc_set_get_comp_data(scontrol, true);
+			if (ret < 0) {
+				dev_err(sdev->dev,
+					"kcontrol %d set up failed for widget %s\n",
+					scontrol->comp_id, swidget->widget->name);
+				return ret;
+			}
+
+			/*
+			 * Read back the data from the DSP for static widgets.
+			 * This is particularly useful for binary kcontrols
+			 * associated with static pipeline widgets to initialize
+			 * the data size to match that in the DSP.
+			 */
+			if (swidget->dynamic_pipeline_widget)
+				continue;
+
+			ret = snd_sof_ipc_set_get_comp_data(scontrol, false);
+			if (ret < 0)
+				dev_warn(sdev->dev,
+					 "kcontrol %d read failed for widget %s\n",
+					 scontrol->comp_id, swidget->widget->name);
+		}
+
+	return 0;
+}
+
 const struct sof_ipc_tplg_control_ops tplg_ipc3_control_ops = {
 	.volume_put = sof_ipc3_volume_put,
 	.volume_get = sof_ipc3_volume_get,
@@ -591,4 +628,5 @@ const struct sof_ipc_tplg_control_ops tplg_ipc3_control_ops = {
 	.bytes_ext_get = sof_ipc3_bytes_ext_get,
 	.bytes_ext_volatile_get = sof_ipc3_bytes_ext_volatile_get,
 	.update = sof_ipc3_control_update,
+	.widget_kcontrol_setup = sof_ipc3_widget_kcontrol_setup,
 };
diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h
index 4a8cd7f2a0eb..c85461dbe945 100644
--- a/sound/soc/sof/sof-audio.h
+++ b/sound/soc/sof/sof-audio.h
@@ -86,6 +86,8 @@ struct sof_ipc_tplg_control_ops {
 			     const unsigned int __user *binary_data, unsigned int size);
 	/* update control data based on notification from the DSP */
 	void (*update)(struct snd_sof_dev *sdev, void *ipc_control_message);
+	/* Optional callback to setup kcontrols associated with an swidget */
+	int (*widget_kcontrol_setup)(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget);
 };
 
 /**
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 14/15] ASoC: SOF: sof-audio: Use the widget_kcontrol_setup ops for kcontrol set up
  2022-04-05 17:26 [PATCH 00/15] ASoC: SOF: Abstractions for top-level IPC ops Ranjani Sridharan
                   ` (12 preceding siblings ...)
  2022-04-05 17:27 ` [PATCH 13/15] ASoC: SOF: Add widget_kcontrol_setup control ops for IPC3 Ranjani Sridharan
@ 2022-04-05 17:27 ` Ranjani Sridharan
  2022-04-05 17:27 ` [PATCH 15/15] ASoC: SOF: ipc: Move the ipc_set_get_comp_data() local to ipc3-control Ranjani Sridharan
  2022-04-12 17:38 ` [PATCH 00/15] ASoC: SOF: Abstractions for top-level IPC ops Mark Brown
  15 siblings, 0 replies; 17+ messages in thread
From: Ranjani Sridharan @ 2022-04-05 17:27 UTC (permalink / raw)
  To: alsa-devel
  Cc: tiwai, Peter Ujfalusi, Pierre-Louis Bossart, Ranjani Sridharan,
	broonie, Daniel Baluta

From: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>

Remove the local implementation and switch to the IPC neutral ops to
set up the kcontrols associated with the swidget.

The set up call uses snd_sof_ipc_set_get_comp_data() which is largely an
IPC3 parsing function.

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>
---
 sound/soc/sof/sof-audio.c | 54 +++------------------------------------
 1 file changed, 4 insertions(+), 50 deletions(-)

diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c
index 49fdfe06a9a3..c0a442272ad6 100644
--- a/sound/soc/sof/sof-audio.c
+++ b/sound/soc/sof/sof-audio.c
@@ -12,51 +12,6 @@
 #include "sof-audio.h"
 #include "ops.h"
 
-static int sof_kcontrol_setup(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol)
-{
-	int ret;
-
-	ret = snd_sof_ipc_set_get_comp_data(scontrol, true);
-	if (ret < 0)
-		dev_err(sdev->dev, "error: failed kcontrol value set for widget: %d\n",
-			scontrol->comp_id);
-
-	return ret;
-}
-
-static int sof_widget_kcontrol_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
-{
-	struct snd_sof_control *scontrol;
-	int ret;
-
-	/* set up all controls for the widget */
-	list_for_each_entry(scontrol, &sdev->kcontrol_list, list)
-		if (scontrol->comp_id == swidget->comp_id) {
-			/* set kcontrol data in DSP */
-			ret = sof_kcontrol_setup(sdev, scontrol);
-			if (ret < 0) {
-				dev_err(sdev->dev, "error: fail to set up kcontrols for widget %s\n",
-					swidget->widget->name);
-				return ret;
-			}
-
-			/*
-			 * Read back the data from the DSP for static widgets. This is particularly
-			 * useful for binary kcontrols associated with static pipeline widgets to
-			 * initialize the data size to match that in the DSP.
-			 */
-			if (swidget->dynamic_pipeline_widget)
-				continue;
-
-			ret = snd_sof_ipc_set_get_comp_data(scontrol, false);
-			if (ret < 0)
-				dev_warn(sdev->dev, "Failed kcontrol get for control in widget %s\n",
-					 swidget->widget->name);
-		}
-
-	return 0;
-}
-
 static void sof_reset_route_setup_status(struct snd_sof_dev *sdev, struct snd_sof_widget *widget)
 {
 	struct snd_sof_route *sroute;
@@ -176,11 +131,10 @@ int sof_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
 	}
 
 	/* restore kcontrols for widget */
-	ret = sof_widget_kcontrol_setup(sdev, swidget);
-	if (ret < 0) {
-		dev_err(sdev->dev, "error: failed to restore kcontrols for widget %s\n",
-			swidget->widget->name);
-		goto widget_free;
+	if (tplg_ops->control->widget_kcontrol_setup) {
+		ret = tplg_ops->control->widget_kcontrol_setup(sdev, swidget);
+		if (ret < 0)
+			goto widget_free;
 	}
 
 	dev_dbg(sdev->dev, "widget %s setup complete\n", swidget->widget->name);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 15/15] ASoC: SOF: ipc: Move the ipc_set_get_comp_data() local to ipc3-control
  2022-04-05 17:26 [PATCH 00/15] ASoC: SOF: Abstractions for top-level IPC ops Ranjani Sridharan
                   ` (13 preceding siblings ...)
  2022-04-05 17:27 ` [PATCH 14/15] ASoC: SOF: sof-audio: Use the widget_kcontrol_setup ops for kcontrol set up Ranjani Sridharan
@ 2022-04-05 17:27 ` Ranjani Sridharan
  2022-04-12 17:38 ` [PATCH 00/15] ASoC: SOF: Abstractions for top-level IPC ops Mark Brown
  15 siblings, 0 replies; 17+ messages in thread
From: Ranjani Sridharan @ 2022-04-05 17:27 UTC (permalink / raw)
  To: alsa-devel
  Cc: tiwai, Peter Ujfalusi, Pierre-Louis Bossart, Ranjani Sridharan,
	broonie, Daniel Baluta

From: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>

The snd_sof_ipc_set_get_comp_data() only used for kcontrol data update
and it is an IPC3 message parsing function.

Move it out from the generic ipc.c to ipc3-control.c and rename it to
better describe it's function.

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>
---
 sound/soc/sof/ipc.c          | 83 ------------------------------
 sound/soc/sof/ipc3-control.c | 97 ++++++++++++++++++++++++++++++++----
 sound/soc/sof/sof-audio.h    |  5 --
 3 files changed, 88 insertions(+), 97 deletions(-)

diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c
index 45c487ab8b54..6f8ac3fb195f 100644
--- a/sound/soc/sof/ipc.c
+++ b/sound/soc/sof/ipc.c
@@ -137,89 +137,6 @@ void snd_sof_ipc_reply(struct snd_sof_dev *sdev, u32 msg_id)
 }
 EXPORT_SYMBOL(snd_sof_ipc_reply);
 
-/*
- * IPC get()/set() for kcontrols.
- */
-int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol, bool set)
-{
-	struct snd_soc_component *scomp = scontrol->scomp;
-	struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
-	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
-	const struct sof_ipc_ops *iops = sdev->ipc->ops;
-	enum sof_ipc_ctrl_type ctrl_type;
-	struct snd_sof_widget *swidget;
-	bool widget_found = false;
-	u32 ipc_cmd, msg_bytes;
-
-	list_for_each_entry(swidget, &sdev->widget_list, list) {
-		if (swidget->comp_id == scontrol->comp_id) {
-			widget_found = true;
-			break;
-		}
-	}
-
-	if (!widget_found) {
-		dev_err(sdev->dev, "%s: can't find widget with id %d\n", __func__,
-			scontrol->comp_id);
-		return -EINVAL;
-	}
-
-	/*
-	 * Volatile controls should always be part of static pipelines and the widget use_count
-	 * would always be > 0 in this case. For the others, just return the cached value if the
-	 * widget is not set up.
-	 */
-	if (!swidget->use_count)
-		return 0;
-
-	/*
-	 * Select the IPC cmd and the ctrl_type based on the ctrl_cmd and the
-	 * direction
-	 * Note: SOF_CTRL_TYPE_VALUE_COMP_* is not used and supported currently
-	 *	 for ctrl_type
-	 */
-	if (cdata->cmd == SOF_CTRL_CMD_BINARY) {
-		ipc_cmd = set ? SOF_IPC_COMP_SET_DATA : SOF_IPC_COMP_GET_DATA;
-		ctrl_type = set ? SOF_CTRL_TYPE_DATA_SET : SOF_CTRL_TYPE_DATA_GET;
-	} else {
-		ipc_cmd = set ? SOF_IPC_COMP_SET_VALUE : SOF_IPC_COMP_GET_VALUE;
-		ctrl_type = set ? SOF_CTRL_TYPE_VALUE_CHAN_SET : SOF_CTRL_TYPE_VALUE_CHAN_GET;
-	}
-
-	cdata->rhdr.hdr.cmd = SOF_IPC_GLB_COMP_MSG | ipc_cmd;
-	cdata->type = ctrl_type;
-	cdata->comp_id = scontrol->comp_id;
-	cdata->msg_index = 0;
-
-	/* calculate header and data size */
-	switch (cdata->type) {
-	case SOF_CTRL_TYPE_VALUE_CHAN_GET:
-	case SOF_CTRL_TYPE_VALUE_CHAN_SET:
-		cdata->num_elems = scontrol->num_channels;
-
-		msg_bytes = scontrol->num_channels *
-			    sizeof(struct sof_ipc_ctrl_value_chan);
-		msg_bytes += sizeof(struct sof_ipc_ctrl_data);
-		break;
-	case SOF_CTRL_TYPE_DATA_GET:
-	case SOF_CTRL_TYPE_DATA_SET:
-		cdata->num_elems = cdata->data->size;
-
-		msg_bytes = cdata->data->size;
-		msg_bytes += sizeof(struct sof_ipc_ctrl_data) +
-			     sizeof(struct sof_abi_hdr);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	cdata->rhdr.hdr.size = msg_bytes;
-	cdata->elems_remaining = 0;
-
-	return iops->set_get_data(sdev, cdata, cdata->rhdr.hdr.size, set);
-}
-EXPORT_SYMBOL(snd_sof_ipc_set_get_comp_data);
-
 int snd_sof_ipc_valid(struct snd_sof_dev *sdev)
 {
 	struct sof_ipc_fw_ready *ready = &sdev->fw_ready;
diff --git a/sound/soc/sof/ipc3-control.c b/sound/soc/sof/ipc3-control.c
index 4e647142dc2b..cde9e481f7f2 100644
--- a/sound/soc/sof/ipc3-control.c
+++ b/sound/soc/sof/ipc3-control.c
@@ -11,6 +11,85 @@
 #include "sof-audio.h"
 #include "ipc3-ops.h"
 
+/* IPC set()/get() for kcontrols. */
+static int sof_ipc3_set_get_kcontrol_data(struct snd_sof_control *scontrol, bool set)
+{
+	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scontrol->scomp);
+	struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
+	const struct sof_ipc_ops *iops = sdev->ipc->ops;
+	enum sof_ipc_ctrl_type ctrl_type;
+	struct snd_sof_widget *swidget;
+	bool widget_found = false;
+	u32 ipc_cmd, msg_bytes;
+
+	list_for_each_entry(swidget, &sdev->widget_list, list) {
+		if (swidget->comp_id == scontrol->comp_id) {
+			widget_found = true;
+			break;
+		}
+	}
+
+	if (!widget_found) {
+		dev_err(sdev->dev, "%s: can't find widget with id %d\n", __func__,
+			scontrol->comp_id);
+		return -EINVAL;
+	}
+
+	/*
+	 * Volatile controls should always be part of static pipelines and the widget use_count
+	 * would always be > 0 in this case. For the others, just return the cached value if the
+	 * widget is not set up.
+	 */
+	if (!swidget->use_count)
+		return 0;
+
+	/*
+	 * Select the IPC cmd and the ctrl_type based on the ctrl_cmd and the
+	 * direction
+	 * Note: SOF_CTRL_TYPE_VALUE_COMP_* is not used and supported currently
+	 *	 for ctrl_type
+	 */
+	if (cdata->cmd == SOF_CTRL_CMD_BINARY) {
+		ipc_cmd = set ? SOF_IPC_COMP_SET_DATA : SOF_IPC_COMP_GET_DATA;
+		ctrl_type = set ? SOF_CTRL_TYPE_DATA_SET : SOF_CTRL_TYPE_DATA_GET;
+	} else {
+		ipc_cmd = set ? SOF_IPC_COMP_SET_VALUE : SOF_IPC_COMP_GET_VALUE;
+		ctrl_type = set ? SOF_CTRL_TYPE_VALUE_CHAN_SET : SOF_CTRL_TYPE_VALUE_CHAN_GET;
+	}
+
+	cdata->rhdr.hdr.cmd = SOF_IPC_GLB_COMP_MSG | ipc_cmd;
+	cdata->type = ctrl_type;
+	cdata->comp_id = scontrol->comp_id;
+	cdata->msg_index = 0;
+
+	/* calculate header and data size */
+	switch (cdata->type) {
+	case SOF_CTRL_TYPE_VALUE_CHAN_GET:
+	case SOF_CTRL_TYPE_VALUE_CHAN_SET:
+		cdata->num_elems = scontrol->num_channels;
+
+		msg_bytes = scontrol->num_channels *
+			    sizeof(struct sof_ipc_ctrl_value_chan);
+		msg_bytes += sizeof(struct sof_ipc_ctrl_data);
+		break;
+	case SOF_CTRL_TYPE_DATA_GET:
+	case SOF_CTRL_TYPE_DATA_SET:
+		cdata->num_elems = cdata->data->size;
+
+		msg_bytes = cdata->data->size;
+		msg_bytes += sizeof(struct sof_ipc_ctrl_data) +
+			     sizeof(struct sof_abi_hdr);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	cdata->rhdr.hdr.size = msg_bytes;
+	cdata->elems_remaining = 0;
+
+	return iops->set_get_data(sdev, cdata, cdata->rhdr.hdr.size, set);
+}
+
 static inline u32 mixer_to_ipc(unsigned int value, u32 *volume_map, int size)
 {
 	if (value >= size)
@@ -49,7 +128,7 @@ static void snd_sof_refresh_control(struct snd_sof_control *scontrol)
 
 	/* refresh the component data from DSP */
 	scontrol->comp_data_dirty = false;
-	ret = snd_sof_ipc_set_get_comp_data(scontrol, false);
+	ret = sof_ipc3_set_get_kcontrol_data(scontrol, false);
 	if (ret < 0) {
 		dev_err(scomp->dev, "Failed to get control data: %d\n", ret);
 
@@ -97,7 +176,7 @@ static bool sof_ipc3_volume_put(struct snd_sof_control *scontrol,
 
 	/* notify DSP of mixer updates */
 	if (pm_runtime_active(scomp->dev)) {
-		int ret = snd_sof_ipc_set_get_comp_data(scontrol, true);
+		int ret = sof_ipc3_set_get_kcontrol_data(scontrol, true);
 
 		if (ret < 0) {
 			dev_err(scomp->dev, "Failed to set mixer updates for %s\n",
@@ -145,7 +224,7 @@ static bool sof_ipc3_switch_put(struct snd_sof_control *scontrol,
 
 	/* notify DSP of mixer updates */
 	if (pm_runtime_active(scomp->dev)) {
-		int ret = snd_sof_ipc_set_get_comp_data(scontrol, true);
+		int ret = sof_ipc3_set_get_kcontrol_data(scontrol, true);
 
 		if (ret < 0) {
 			dev_err(scomp->dev, "Failed to set mixer updates for %s\n",
@@ -193,7 +272,7 @@ static bool sof_ipc3_enum_put(struct snd_sof_control *scontrol,
 
 	/* notify DSP of enum updates */
 	if (pm_runtime_active(scomp->dev)) {
-		int ret = snd_sof_ipc_set_get_comp_data(scontrol, true);
+		int ret = sof_ipc3_set_get_kcontrol_data(scontrol, true);
 
 		if (ret < 0) {
 			dev_err(scomp->dev, "Failed to set enum updates for %s\n",
@@ -265,7 +344,7 @@ static int sof_ipc3_bytes_put(struct snd_sof_control *scontrol,
 
 	/* notify DSP of byte control updates */
 	if (pm_runtime_active(scomp->dev))
-		return snd_sof_ipc_set_get_comp_data(scontrol, true);
+		return sof_ipc3_set_get_kcontrol_data(scontrol, true);
 
 	return 0;
 }
@@ -379,7 +458,7 @@ static int sof_ipc3_bytes_ext_put(struct snd_sof_control *scontrol,
 
 	/* notify DSP of byte control updates */
 	if (pm_runtime_active(scomp->dev))
-		return snd_sof_ipc_set_get_comp_data(scontrol, true);
+		return sof_ipc3_set_get_kcontrol_data(scontrol, true);
 
 	return 0;
 }
@@ -409,7 +488,7 @@ static int sof_ipc3_bytes_ext_volatile_get(struct snd_sof_control *scontrol,
 	cdata->data->abi = SOF_ABI_VERSION;
 
 	/* get all the component data from DSP */
-	ret = snd_sof_ipc_set_get_comp_data(scontrol, false);
+	ret = sof_ipc3_set_get_kcontrol_data(scontrol, false);
 	if (ret < 0)
 		return ret;
 
@@ -588,7 +667,7 @@ static int sof_ipc3_widget_kcontrol_setup(struct snd_sof_dev *sdev,
 	list_for_each_entry(scontrol, &sdev->kcontrol_list, list)
 		if (scontrol->comp_id == swidget->comp_id) {
 			/* set kcontrol data in DSP */
-			ret = snd_sof_ipc_set_get_comp_data(scontrol, true);
+			ret = sof_ipc3_set_get_kcontrol_data(scontrol, true);
 			if (ret < 0) {
 				dev_err(sdev->dev,
 					"kcontrol %d set up failed for widget %s\n",
@@ -605,7 +684,7 @@ static int sof_ipc3_widget_kcontrol_setup(struct snd_sof_dev *sdev,
 			if (swidget->dynamic_pipeline_widget)
 				continue;
 
-			ret = snd_sof_ipc_set_get_comp_data(scontrol, false);
+			ret = sof_ipc3_set_get_kcontrol_data(scontrol, false);
 			if (ret < 0)
 				dev_warn(sdev->dev,
 					 "kcontrol %d read failed for widget %s\n",
diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h
index c85461dbe945..0898f4dbe29f 100644
--- a/sound/soc/sof/sof-audio.h
+++ b/sound/soc/sof/sof-audio.h
@@ -431,11 +431,6 @@ static inline void snd_sof_compr_fragment_elapsed(struct snd_compr_stream *cstre
 static inline void snd_sof_compr_init_elapsed_work(struct work_struct *work) { }
 #endif
 
-/*
- * Mixer IPC
- */
-int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol, bool set);
-
 /* DAI link fixup */
 int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params);
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH 00/15] ASoC: SOF: Abstractions for top-level IPC ops
  2022-04-05 17:26 [PATCH 00/15] ASoC: SOF: Abstractions for top-level IPC ops Ranjani Sridharan
                   ` (14 preceding siblings ...)
  2022-04-05 17:27 ` [PATCH 15/15] ASoC: SOF: ipc: Move the ipc_set_get_comp_data() local to ipc3-control Ranjani Sridharan
@ 2022-04-12 17:38 ` Mark Brown
  15 siblings, 0 replies; 17+ messages in thread
From: Mark Brown @ 2022-04-12 17:38 UTC (permalink / raw)
  To: ranjani.sridharan, alsa-devel; +Cc: tiwai

On Tue, 5 Apr 2022 10:26:53 -0700, Ranjani Sridharan wrote:
> This series is continuation of the IPC abstraction in the SOF driver in
> preparation for supporting the new IPC supported by the SOF firmware.
> It introduces abstraction for top-level IPC ops for sending/receiving
> regular and large IPC's.
> 
> Peter Ujfalusi (15):
>   ASoC: SOF: Add helper function to prepare and send an IPC message
>   ASoC: SOF: Add high level IPC IO callback definitions to ipc_ops
>   ASoC: SOF: ipc3: Implement the tx_msg IPC ops
>   ASoC: SOF: ipc3: Use sof_ipc3_tx_msg() internally for message sending
>   ASoC: SOF: ipc3: Implement the set_get_data IPC ops
>   ASoC: SOF: ipc3: Implement the get_reply IPC ops
>   ASoC: SOF: ipc3: Implement rx_msg IPC ops
>   ASoC: SOF: ipc: Separate the ops checks by functions/topics
>   ASoC: SOF: ipc: Add check for mandatory IPC message handling ops
>   ASoC: SOF: ipc: Use the get_reply ops in snd_sof_ipc_get_reply()
>   ASoC: SOF: ipc: Switch over to use the tx_msg and set_get_data ops
>   ASoC: SOF: ipc: Switch over to use the rx_msg ops
>   ASoC: SOF: Add widget_kcontrol_setup control ops for IPC3
>   ASoC: SOF: sof-audio: Use the widget_kcontrol_setup ops for kcontrol
>     set up
>   ASoC: SOF: ipc: Move the ipc_set_get_comp_data() local to ipc3-control
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[01/15] ASoC: SOF: Add helper function to prepare and send an IPC message
        commit: b4dcafe45e46f107b5f65a004d49e11e56fe4f87
[02/15] ASoC: SOF: Add high level IPC IO callback definitions to ipc_ops
        commit: 25e77672c4e18fe76dbf2e21ab8c7c36d6a323cc
[03/15] ASoC: SOF: ipc3: Implement the tx_msg IPC ops
        commit: 0881918087ac7adfeed2652a03b4edb1131826ba
[04/15] ASoC: SOF: ipc3: Use sof_ipc3_tx_msg() internally for message sending
        commit: dbcf543cf91edc7f6fe833d51b58fe65265f2a72
[05/15] ASoC: SOF: ipc3: Implement the set_get_data IPC ops
        commit: e974b8e190d30fdd0c5edc1447ee1425a30d15ea
[06/15] ASoC: SOF: ipc3: Implement the get_reply IPC ops
        commit: 783b5f1797595a9df4476dd66f7bf34915be246b
[07/15] ASoC: SOF: ipc3: Implement rx_msg IPC ops
        commit: 74ad8ed6512186134527fc82440f62007a98ff48
[08/15] ASoC: SOF: ipc: Separate the ops checks by functions/topics
        commit: 785b3fbe61c6c1c413b696e335e9f288aaec4364
[09/15] ASoC: SOF: ipc: Add check for mandatory IPC message handling ops
        commit: defad9d2e2703b040c3a001978c09c75970357f0
[10/15] ASoC: SOF: ipc: Use the get_reply ops in snd_sof_ipc_get_reply()
        commit: 045bc49bc9572f883db1a0740cb36bf6eeb206db
[11/15] ASoC: SOF: ipc: Switch over to use the tx_msg and set_get_data ops
        commit: 85d0f881471531ffb081711b13df32b1f6f1f637
[12/15] ASoC: SOF: ipc: Switch over to use the rx_msg ops
        commit: 2f1f5a438899a9d2933ef004a1f0f2c962b29fb4
[13/15] ASoC: SOF: Add widget_kcontrol_setup control ops for IPC3
        commit: e394ffb82f9c24fd6f7f4d896cb4ef32771dae7a
[14/15] ASoC: SOF: sof-audio: Use the widget_kcontrol_setup ops for kcontrol set up
        commit: 50d4d8cf544dfbb9668dce87a21580fedb6e827f
[15/15] ASoC: SOF: ipc: Move the ipc_set_get_comp_data() local to ipc3-control
        commit: e760f102c92c16307abebffd24a31bdb3ccd78ac

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2022-04-12 17:39 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-05 17:26 [PATCH 00/15] ASoC: SOF: Abstractions for top-level IPC ops Ranjani Sridharan
2022-04-05 17:26 ` [PATCH 01/15] ASoC: SOF: Add helper function to prepare and send an IPC message Ranjani Sridharan
2022-04-05 17:26 ` [PATCH 02/15] ASoC: SOF: Add high level IPC IO callback definitions to ipc_ops Ranjani Sridharan
2022-04-05 17:26 ` [PATCH 03/15] ASoC: SOF: ipc3: Implement the tx_msg IPC ops Ranjani Sridharan
2022-04-05 17:26 ` [PATCH 04/15] ASoC: SOF: ipc3: Use sof_ipc3_tx_msg() internally for message sending Ranjani Sridharan
2022-04-05 17:26 ` [PATCH 05/15] ASoC: SOF: ipc3: Implement the set_get_data IPC ops Ranjani Sridharan
2022-04-05 17:26 ` [PATCH 06/15] ASoC: SOF: ipc3: Implement the get_reply " Ranjani Sridharan
2022-04-05 17:27 ` [PATCH 07/15] ASoC: SOF: ipc3: Implement rx_msg " Ranjani Sridharan
2022-04-05 17:27 ` [PATCH 08/15] ASoC: SOF: ipc: Separate the ops checks by functions/topics Ranjani Sridharan
2022-04-05 17:27 ` [PATCH 09/15] ASoC: SOF: ipc: Add check for mandatory IPC message handling ops Ranjani Sridharan
2022-04-05 17:27 ` [PATCH 10/15] ASoC: SOF: ipc: Use the get_reply ops in snd_sof_ipc_get_reply() Ranjani Sridharan
2022-04-05 17:27 ` [PATCH 11/15] ASoC: SOF: ipc: Switch over to use the tx_msg and set_get_data ops Ranjani Sridharan
2022-04-05 17:27 ` [PATCH 12/15] ASoC: SOF: ipc: Switch over to use the rx_msg ops Ranjani Sridharan
2022-04-05 17:27 ` [PATCH 13/15] ASoC: SOF: Add widget_kcontrol_setup control ops for IPC3 Ranjani Sridharan
2022-04-05 17:27 ` [PATCH 14/15] ASoC: SOF: sof-audio: Use the widget_kcontrol_setup ops for kcontrol set up Ranjani Sridharan
2022-04-05 17:27 ` [PATCH 15/15] ASoC: SOF: ipc: Move the ipc_set_get_comp_data() local to ipc3-control Ranjani Sridharan
2022-04-12 17:38 ` [PATCH 00/15] ASoC: SOF: Abstractions for top-level IPC ops Mark Brown

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.