ASoC: SOF: Introduce IPC3 PCM hw_free op
authorRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Thu, 17 Mar 2022 17:50:38 +0000 (10:50 -0700)
committerMark Brown <broonie@kernel.org>
Fri, 18 Mar 2022 16:04:47 +0000 (16:04 +0000)
Add the IPC3 PCM ops, define the hw_free op and modify all users to use
the op.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Link: https://lore.kernel.org/r/20220317175044.1752400-14-ranjani.sridharan@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sof/Makefile
sound/soc/sof/ipc.c
sound/soc/sof/ipc3-ops.h
sound/soc/sof/ipc3-pcm.c [new file with mode: 0644]
sound/soc/sof/ipc3.c
sound/soc/sof/pcm.c
sound/soc/sof/sof-audio.c

index f6d68a3..18acbc0 100644 (file)
@@ -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
index af0ae13..5f57536 100644 (file)
@@ -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;
        }
 
index f3d6010..a478462 100644 (file)
@@ -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 (file)
index 0000000..96f498b
--- /dev/null
@@ -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,
+};
index e71cf30..03e914b 100644 (file)
@@ -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,
 };
index 47599b5..8ef477a 100644 (file)
@@ -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);
index 7aa4ac3..5088ec7 100644 (file)
@@ -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);