In current ALSA SoC, Platform only has pcm_new/pcm_free feature, but it should be supported on Component level. This patch adds it.
The v1 was added commit 99b04f4c4051f7 ("ASoC: add Component level pcm_new/pcm_free") but it called all "card" connected component's pcm_new/free, it was wrong. This patch calls "rtd" connected component.
Not-yet-Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- include/sound/soc.h | 6 ++++++ sound/soc/soc-core.c | 21 +++++++++++++++++++++ sound/soc/soc-pcm.c | 33 ++++++++++++++++++++++++++------- 3 files changed, 53 insertions(+), 7 deletions(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h index 963eef6..103ae43 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -806,6 +806,10 @@ struct snd_soc_component_driver { int (*suspend)(struct snd_soc_component *); int (*resume)(struct snd_soc_component *);
+ /* pcm creation and destruction */ + int (*pcm_new)(struct snd_soc_pcm_runtime *); + void (*pcm_free)(struct snd_pcm *); + /* DT */ int (*of_xlate_dai_name)(struct snd_soc_component *component, struct of_phandle_args *args, @@ -881,6 +885,8 @@ struct snd_soc_component { void (*remove)(struct snd_soc_component *); int (*suspend)(struct snd_soc_component *); int (*resume)(struct snd_soc_component *); + int (*pcm_new)(struct snd_soc_pcm_runtime *); + void (*pcm_free)(struct snd_pcm *);
/* machine specific init */ int (*init)(struct snd_soc_component *component); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 646c722..5459e5b 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3214,6 +3214,8 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, component->remove = component->driver->remove; component->suspend = component->driver->suspend; component->resume = component->driver->resume; + component->pcm_new = component->driver->pcm_new; + component->pcm_free= component->driver->pcm_free;
dapm = &component->dapm; dapm->dev = dev; @@ -3441,6 +3443,21 @@ static void snd_soc_platform_drv_remove(struct snd_soc_component *component) platform->driver->remove(platform); }
+static int snd_soc_platform_drv_pcm_new(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_platform *platform = rtd->platform; + + return platform->driver->pcm_new(rtd); +} + +static void snd_soc_platform_drv_pcm_free(struct snd_pcm *pcm) +{ + struct snd_soc_pcm_runtime *rtd = pcm->private_data; + struct snd_soc_platform *platform = rtd->platform; + + platform->driver->pcm_free(pcm); +} + /** * snd_soc_add_platform - Add a platform to the ASoC core * @dev: The parent device for the platform @@ -3464,6 +3481,10 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform, platform->component.probe = snd_soc_platform_drv_probe; if (platform_drv->remove) platform->component.remove = snd_soc_platform_drv_remove; + if (platform_drv->pcm_new) + platform->component.pcm_new = snd_soc_platform_drv_pcm_new; + if (platform_drv->pcm_free) + platform->component.pcm_free = snd_soc_platform_drv_pcm_free;
#ifdef CONFIG_DEBUG_FS platform->component.debugfs_prefix = "platform"; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index d801c93..36b3035 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2634,12 +2634,28 @@ static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream) return ret; }
+static void soc_pcm_free(struct snd_pcm *pcm) +{ + struct snd_soc_pcm_runtime *rtd = pcm->private_data; + struct snd_soc_rtdcom_list *rtdcom; + struct snd_soc_component *component; + + for_each_rtdcom(rtd, rtdcom) { + component = rtdcom->component; + + if (component->pcm_free) + component->pcm_free(pcm); + } +} + /* create a new pcm */ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) { struct snd_soc_platform *platform = rtd->platform; struct snd_soc_dai *codec_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_component *component; + struct snd_soc_rtdcom_list *rtdcom; struct snd_pcm *pcm; char new_name[64]; int ret = 0, playback = 0, capture = 0; @@ -2749,17 +2765,20 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) if (capture) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &rtd->ops);
- if (platform->driver->pcm_new) { - ret = platform->driver->pcm_new(rtd); + for_each_rtdcom(rtd, rtdcom) { + component = rtdcom->component; + + if (!component->pcm_new) + continue; + + ret = component->pcm_new(rtd); if (ret < 0) { - dev_err(platform->dev, - "ASoC: pcm constructor failed: %d\n", - ret); + dev_err(component->dev, + "ASoC: pcm constructor failed: %d\n", ret); return ret; } } - - pcm->private_free = platform->driver->pcm_free; + pcm->private_free = soc_pcm_free; out: dev_info(rtd->card->dev, "%s <-> %s mapping ok\n", (rtd->num_codecs > 1) ? "multicodec" : rtd->codec_dai->name,