summaryrefslogtreecommitdiff
path: root/sound/soc/soc-pcm.c
diff options
context:
space:
mode:
authorJerome Brunet <jbrunet@baylibre.com>2019-07-25 18:59:47 +0200
committerMark Brown <broonie@kernel.org>2019-08-01 13:54:25 +0100
commita342031cdd0818cb0fbcb44798211c7a02c7ca27 (patch)
treea5f4e89d4fb309ec641930c339137696335d495a /sound/soc/soc-pcm.c
parentcaa918ef14065b812737f3ee4ac349dcfff196e6 (diff)
ASoC: create pcm for codec2codec links as well
At the moment, codec to codec links uses an ephemeral variable for the struct snd_pcm_substream. Also the struct snd_soc_pcm_runtime does not have real struct snd_pcm. This might a problem if the functions used by a codec on codec to codec link expect these structures to exist, and keep on existing during the life of the codec. For example, it is the case of the hdmi-codec, which uses snd_pcm_add_chmap_ctls(). For the controls to works, the pcm and substream must to exist. This change is first step, it create pcm (and substreams) for codec to codec links, in the same way as dpcm backend links. Signed-off-by: Jerome Brunet <jbrunet@baylibre.com> Link: https://lore.kernel.org/r/20190725165949.29699-5-jbrunet@baylibre.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/soc-pcm.c')
-rw-r--r--sound/soc/soc-pcm.c35
1 files changed, 32 insertions, 3 deletions
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index fabeac164a6c..30264bc592f6 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -678,6 +678,16 @@ static void close_delayed_work(struct work_struct *work)
mutex_unlock(&rtd->pcm_mutex);
}
+static void codec2codec_close_delayed_work(struct work_struct *work)
+{
+ /*
+ * Currently nothing to do for c2c links
+ * Since c2c links are internal nodes in the DAPM graph and
+ * don't interface with the outside world or application layer
+ * we don't have to do any special handling on close.
+ */
+}
+
/*
* Called by ALSA when a PCM substream is closed. Private data can be
* freed here. The cpu DAI, codec DAI, machine and components are also
@@ -3011,6 +3021,12 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
playback = rtd->dai_link->dpcm_playback;
capture = rtd->dai_link->dpcm_capture;
} else {
+ /* Adapt stream for codec2codec links */
+ struct snd_soc_pcm_stream *cpu_capture = rtd->dai_link->params ?
+ &cpu_dai->driver->playback : &cpu_dai->driver->capture;
+ struct snd_soc_pcm_stream *cpu_playback = rtd->dai_link->params ?
+ &cpu_dai->driver->capture : &cpu_dai->driver->playback;
+
for_each_rtd_codec_dai(rtd, i, codec_dai) {
if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK))
@@ -3019,6 +3035,9 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE))
capture = 1;
}
+
+ capture = capture && cpu_capture->channels_min;
+ playback = playback && cpu_playback->channels_min;
}
if (rtd->dai_link->playback_only) {
@@ -3032,7 +3051,13 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
}
/* create the PCM */
- if (rtd->dai_link->no_pcm) {
+ if (rtd->dai_link->params) {
+ snprintf(new_name, sizeof(new_name), "codec2codec(%s)",
+ rtd->dai_link->stream_name);
+
+ ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
+ playback, capture, &pcm);
+ } else if (rtd->dai_link->no_pcm) {
snprintf(new_name, sizeof(new_name), "(%s)",
rtd->dai_link->stream_name);
@@ -3059,13 +3084,17 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
dev_dbg(rtd->card->dev, "ASoC: registered pcm #%d %s\n",num, new_name);
/* DAPM dai link stream work */
- INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
+ if (rtd->dai_link->params)
+ INIT_DELAYED_WORK(&rtd->delayed_work,
+ codec2codec_close_delayed_work);
+ else
+ INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
pcm->nonatomic = rtd->dai_link->nonatomic;
rtd->pcm = pcm;
pcm->private_data = rtd;
- if (rtd->dai_link->no_pcm) {
+ if (rtd->dai_link->no_pcm || rtd->dai_link->params) {
if (playback)
pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
if (capture)