LF-3665-4 ASoC: SOF: Introduce fragment elapsed notification API
authorDaniel Baluta <daniel.baluta@nxp.com>
Mon, 18 Jan 2021 13:51:14 +0000 (15:51 +0200)
committerDaniel Baluta <daniel.baluta@nxp.com>
Wed, 28 Apr 2021 12:28:00 +0000 (15:28 +0300)
After each fragment is accepted by the DSP we need to inform
the userspace applications that they can send the next fragment.
This is done via snd_compr_fragment_elapsed.

Similar with the PCM case, in order to avoid sending an IPC before
the previous IPC is handled we need to schedule a delayed work to
call snd_compr_fragment_elapsed().

See snd_sof_pcm_period_elapsed.

To sum up this patch offers the following API to SOF code:
* snd_sof_compr_init_elapsed_work
* snd_sof_compr_fragment_elapsed

Note that implementation for compressed function is in a new file
selected via CONFIG_SND_SOC_SOF_COMPRESS config option.

For symmetry we introduce snd_sof_pcm_init_elapsed_work to setup
the work struct for PCM case.

Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
sound/soc/sof/Kconfig
sound/soc/sof/Makefile
sound/soc/sof/compress.c [new file with mode: 0644]
sound/soc/sof/ipc.c
sound/soc/sof/pcm.c
sound/soc/sof/sof-audio.h
sound/soc/sof/topology.c

index 8c1f082..336077f 100644 (file)
@@ -41,6 +41,15 @@ config SND_SOC_SOF_OF
          required to enable i.MX8 devices.
          Say Y if you need this option. If unsure select "N".
 
+config SND_SOC_SOF_COMPRESS
+       bool "SOF enable compress interface"
+       select SND_SOC_COMPRESS
+       help
+         This option enables the compress interface that can be used to
+         offload compress files decoding/encoding on the DSP.
+         Say Y if you want to enable the compress interface.
+         If unsure, select "N".
+
 config SND_SOC_SOF_DEBUG_PROBES
        bool "SOF enable data probing"
        select SND_SOC_COMPRESS
index c0b0b8b..ad8cfdc 100644 (file)
@@ -2,6 +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 utils.o sof-audio.o
+snd-sof-$(CONFIG_SND_SOC_SOF_COMPRESS) += compress.o
 snd-sof-$(CONFIG_SND_SOC_SOF_DEBUG_PROBES) += probe.o probe_compress.o
 
 snd-sof-pci-objs := sof-pci-dev.o
diff --git a/sound/soc/sof/compress.c b/sound/soc/sof/compress.c
new file mode 100644 (file)
index 0000000..8f04424
--- /dev/null
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+//
+// Copyright 2021 NXP
+//
+// Author: Daniel Baluta <daniel.baluta@nxp.com>
+
+#include <sound/soc.h>
+#include <sound/sof.h>
+#include <sound/compress_driver.h>
+#include "sof-audio.h"
+#include "sof-priv.h"
+
+static void snd_sof_compr_fragment_elapsed_work(struct work_struct *work)
+{
+       struct snd_sof_pcm_stream *sps =
+               container_of(work, struct snd_sof_pcm_stream,
+                            period_elapsed_work);
+
+       snd_compr_fragment_elapsed(sps->cstream);
+}
+
+void snd_sof_compr_init_elapsed_work(struct work_struct *work)
+{
+       INIT_WORK(work, snd_sof_compr_fragment_elapsed_work);
+}
+
+/*
+ * sof compr fragment elapse, this could be called in irq thread context
+ */
+void snd_sof_compr_fragment_elapsed(struct snd_compr_stream *cstream)
+{
+       struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+       struct snd_soc_component *component =
+               snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
+       struct snd_sof_pcm *spcm;
+
+       spcm = snd_sof_find_spcm_dai(component, rtd);
+       if (!spcm) {
+               dev_err(component->dev,
+                       "error: fragment elapsed for unknown stream!\n");
+               return;
+       }
+
+       /* use the same workqueue-based solution as for PCM, cf. snd_sof_pcm_elapsed */
+       schedule_work(&spcm->stream[cstream->direction].period_elapsed_work);
+}
index 8da0a10..e63fb9e 100644 (file)
@@ -460,8 +460,10 @@ static void ipc_period_elapsed(struct snd_sof_dev *sdev, u32 msg_id)
 
        memcpy(&stream->posn, &posn, sizeof(posn));
 
-       /* only inform ALSA for period_wakeup mode */
-       if (!stream->substream->runtime->no_period_wakeup)
+       if (spcm->pcm.compress)
+               snd_sof_compr_fragment_elapsed(stream->cstream);
+       else if (!stream->substream->runtime->no_period_wakeup)
+               /* only inform ALSA for period_wakeup mode */
                snd_sof_pcm_period_elapsed(stream->substream);
 }
 
index 40ae0b0..6a74440 100644 (file)
@@ -57,7 +57,7 @@ static int sof_pcm_dsp_params(struct snd_sof_pcm *spcm, struct snd_pcm_substream
 /*
  * sof pcm period elapse work
  */
-void snd_sof_pcm_period_elapsed_work(struct work_struct *work)
+static void snd_sof_pcm_period_elapsed_work(struct work_struct *work)
 {
        struct snd_sof_pcm_stream *sps =
                container_of(work, struct snd_sof_pcm_stream,
@@ -66,6 +66,11 @@ void snd_sof_pcm_period_elapsed_work(struct work_struct *work)
        snd_pcm_period_elapsed(sps->substream);
 }
 
+void snd_sof_pcm_init_elapsed_work(struct work_struct *work)
+{
+        INIT_WORK(work, snd_sof_pcm_period_elapsed_work);
+}
+
 /*
  * sof pcm period elapse, this could be called at irq thread context.
  */
index 9f645a2..b2482a4 100644 (file)
@@ -34,6 +34,7 @@ struct snd_sof_pcm_stream {
        struct snd_dma_buffer page_table;
        struct sof_ipc_stream_posn posn;
        struct snd_pcm_substream *substream;
+       struct snd_compr_stream *cstream;
        struct work_struct period_elapsed_work;
        bool d0i3_compatible; /* DSP can be in D0I3 when this pcm is opened */
        /*
@@ -201,7 +202,15 @@ struct snd_sof_pcm *snd_sof_find_spcm_pcm_id(struct snd_soc_component *scomp,
 const struct sof_ipc_pipe_new *snd_sof_pipeline_find(struct snd_sof_dev *sdev,
                                                     int pipeline_id);
 void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream);
-void snd_sof_pcm_period_elapsed_work(struct work_struct *work);
+void snd_sof_pcm_init_elapsed_work(struct work_struct *work);
+
+#if defined(CONFIG_SND_SOC_SOF_COMPRESS)
+void snd_sof_compr_fragment_elapsed(struct snd_compr_stream *cstream);
+void snd_sof_compr_init_elapsed_work(struct work_struct *work);
+#else
+static inline void snd_sof_compr_fragment_elapsed(struct snd_compr_stream *cstream) { }
+static inline void snd_sof_compr_init_elapsed_work(struct work_struct *work) { }
+#endif
 
 /*
  * Mixer IPC
index 69313fb..08b2efc 100644 (file)
@@ -2667,8 +2667,10 @@ static int sof_dai_load(struct snd_soc_component *scomp, int index,
 
        for_each_pcm_streams(stream) {
                spcm->stream[stream].comp_id = COMP_ID_UNASSIGNED;
-               INIT_WORK(&spcm->stream[stream].period_elapsed_work,
-                         snd_sof_pcm_period_elapsed_work);
+               if (pcm->compress)
+                       snd_sof_compr_init_elapsed_work(&spcm->stream[stream].period_elapsed_work);
+               else
+                       snd_sof_pcm_init_elapsed_work(&spcm->stream[stream].period_elapsed_work);
        }
 
        spcm->pcm = *pcm;