summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/sof/Makefile2
-rw-r--r--sound/soc/sof/ipc.c5
-rw-r--r--sound/soc/sof/ipc3-ops.h1
-rw-r--r--sound/soc/sof/ipc3-pcm.c43
-rw-r--r--sound/soc/sof/ipc3.c1
-rw-r--r--sound/soc/sof/pcm.c44
-rw-r--r--sound/soc/sof/sof-audio.c11
7 files changed, 72 insertions, 35 deletions
diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile
index f6d68a3096d9..18acbc001b9a 100644
--- a/sound/soc/sof/Makefile
+++ b/sound/soc/sof/Makefile
@@ -2,7 +2,7 @@
snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\
control.o trace.o iomem-utils.o sof-audio.o stream-ipc.o\
- ipc3-topology.o ipc3.o ipc3-control.o
+ ipc3-topology.o ipc3.o ipc3-control.o ipc3-pcm.o
ifneq ($(CONFIG_SND_SOC_SOF_CLIENT),)
snd-sof-objs += sof-client.o
endif
diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c
index af0ae137842b..5f5753608c79 100644
--- a/sound/soc/sof/ipc.c
+++ b/sound/soc/sof/ipc.c
@@ -1033,8 +1033,9 @@ struct snd_sof_ipc *snd_sof_ipc_init(struct snd_sof_dev *sdev)
ipc->ops = &ipc3_ops;
/* check for mandatory ops */
- if (!ipc->ops->tplg || !ipc->ops->tplg->widget || !ipc->ops->tplg->control) {
- dev_err(sdev->dev, "Invalid topology IPC ops\n");
+ if (!ipc->ops->pcm || !ipc->ops->tplg || !ipc->ops->tplg->widget ||
+ !ipc->ops->tplg->control) {
+ dev_err(sdev->dev, "Invalid IPC ops\n");
return NULL;
}
diff --git a/sound/soc/sof/ipc3-ops.h b/sound/soc/sof/ipc3-ops.h
index f3d6010d0b77..a4784626a3d7 100644
--- a/sound/soc/sof/ipc3-ops.h
+++ b/sound/soc/sof/ipc3-ops.h
@@ -16,5 +16,6 @@
extern const struct sof_ipc_tplg_ops ipc3_tplg_ops;
extern const struct sof_ipc_ops ipc3_ops;
extern const struct sof_ipc_tplg_control_ops tplg_ipc3_control_ops;
+extern const struct sof_ipc_pcm_ops ipc3_pcm_ops;
#endif
diff --git a/sound/soc/sof/ipc3-pcm.c b/sound/soc/sof/ipc3-pcm.c
new file mode 100644
index 000000000000..96f498b4b2d6
--- /dev/null
+++ b/sound/soc/sof/ipc3-pcm.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+//
+// This file is provided under a dual BSD/GPLv2 license. When using or
+// redistributing this file, you may do so under either license.
+//
+// Copyright(c) 2021 Intel Corporation. All rights reserved.
+//
+//
+
+#include <sound/pcm_params.h>
+#include "ipc3-ops.h"
+#include "ops.h"
+#include "sof-priv.h"
+#include "sof-audio.h"
+
+static int sof_ipc3_pcm_hw_free(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+ struct sof_ipc_stream stream;
+ struct sof_ipc_reply reply;
+ struct snd_sof_pcm *spcm;
+
+ spcm = snd_sof_find_spcm_dai(component, rtd);
+ if (!spcm)
+ return -EINVAL;
+
+ if (!spcm->prepared[substream->stream])
+ return 0;
+
+ stream.hdr.size = sizeof(stream);
+ stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_FREE;
+ stream.comp_id = spcm->stream[substream->stream].comp_id;
+
+ /* send IPC to the DSP */
+ return sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream,
+ sizeof(stream), &reply, sizeof(reply));
+}
+
+const struct sof_ipc_pcm_ops ipc3_pcm_ops = {
+ .hw_free = sof_ipc3_pcm_hw_free,
+};
diff --git a/sound/soc/sof/ipc3.c b/sound/soc/sof/ipc3.c
index e71cf30908c6..03e914b62728 100644
--- a/sound/soc/sof/ipc3.c
+++ b/sound/soc/sof/ipc3.c
@@ -41,4 +41,5 @@ static const struct sof_ipc_pm_ops ipc3_pm_ops = {
const struct sof_ipc_ops ipc3_ops = {
.tplg = &ipc3_tplg_ops,
.pm = &ipc3_pm_ops,
+ .pcm = &ipc3_pcm_ops,
};
diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c
index 47599b57ff19..8ef477aff938 100644
--- a/sound/soc/sof/pcm.c
+++ b/sound/soc/sof/pcm.c
@@ -82,29 +82,6 @@ void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream)
}
EXPORT_SYMBOL(snd_sof_pcm_period_elapsed);
-int sof_pcm_dsp_pcm_free(struct snd_pcm_substream *substream, struct snd_sof_dev *sdev,
- struct snd_sof_pcm *spcm)
-{
- struct sof_ipc_stream stream;
- struct sof_ipc_reply reply;
- int ret;
-
- if (!spcm->prepared[substream->stream])
- return 0;
-
- stream.hdr.size = sizeof(stream);
- stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_FREE;
- stream.comp_id = spcm->stream[substream->stream].comp_id;
-
- /* send IPC to the DSP */
- ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream,
- sizeof(stream), &reply, sizeof(reply));
- if (!ret)
- spcm->prepared[substream->stream] = false;
-
- return ret;
-}
-
int sof_pcm_setup_connected_widgets(struct snd_sof_dev *sdev, struct snd_soc_pcm_runtime *rtd,
struct snd_sof_pcm *spcm, int dir)
{
@@ -145,6 +122,7 @@ static int sof_pcm_hw_params(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
+ const struct sof_ipc_pcm_ops *pcm_ops = sdev->ipc->ops->pcm;
struct snd_sof_platform_stream_params platform_params = { 0 };
struct sof_ipc_fw_version *v = &sdev->fw_ready.version;
struct snd_sof_pcm *spcm;
@@ -164,9 +142,13 @@ static int sof_pcm_hw_params(struct snd_soc_component *component,
* Handle repeated calls to hw_params() without free_pcm() in
* between. At least ALSA OSS emulation depends on this.
*/
- ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);
- if (ret < 0)
- return ret;
+ if (pcm_ops->hw_free && spcm->prepared[substream->stream]) {
+ ret = pcm_ops->hw_free(component, substream);
+ if (ret < 0)
+ return ret;
+
+ spcm->prepared[substream->stream] = false;
+ }
dev_dbg(component->dev, "pcm: hw params stream %d dir %d\n",
spcm->pcm.pcm_id, substream->stream);
@@ -289,6 +271,7 @@ static int sof_pcm_hw_free(struct snd_soc_component *component,
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
+ const struct sof_ipc_pcm_ops *pcm_ops = sdev->ipc->ops->pcm;
struct snd_sof_pcm *spcm;
int ret, err = 0;
@@ -304,10 +287,13 @@ static int sof_pcm_hw_free(struct snd_soc_component *component,
spcm->pcm.pcm_id, substream->stream);
/* free PCM in the DSP */
- ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);
- if (ret < 0)
- err = ret;
+ if (pcm_ops->hw_free && spcm->prepared[substream->stream]) {
+ ret = pcm_ops->hw_free(component, substream);
+ if (ret < 0)
+ err = ret;
+ spcm->prepared[substream->stream] = false;
+ }
/* stop DMA */
ret = snd_sof_pcm_platform_hw_free(sdev, substream);
diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c
index 7aa4ac313de3..5088ec7019ed 100644
--- a/sound/soc/sof/sof-audio.c
+++ b/sound/soc/sof/sof-audio.c
@@ -591,12 +591,17 @@ int sof_set_up_pipelines(struct snd_sof_dev *sdev, bool verify)
int sof_pcm_stream_free(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream,
struct snd_sof_pcm *spcm, int dir, bool free_widget_list)
{
+ const struct sof_ipc_pcm_ops *pcm_ops = sdev->ipc->ops->pcm;
int ret;
/* Send PCM_FREE IPC to reset pipeline */
- ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);
- if (ret < 0)
- return ret;
+ if (pcm_ops->hw_free && spcm->prepared[substream->stream]) {
+ ret = pcm_ops->hw_free(sdev->component, substream);
+ if (ret < 0)
+ return ret;
+ }
+
+ spcm->prepared[substream->stream] = false;
/* stop the DMA */
ret = snd_sof_pcm_platform_hw_free(sdev, substream);