ASoC: add Component level pcm_new/pcm_free
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Thu, 15 Dec 2016 08:41:38 +0000 (08:41 +0000)
committerMark Brown <broonie@kernel.org>
Thu, 15 Dec 2016 16:54:23 +0000 (16:54 +0000)
In current ALSA SoC, Platform only has pcm_new/pcm_free feature,
but it should be supported on Component level. This patch adds it.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
include/sound/soc.h
sound/soc/soc-core.c
sound/soc/soc-pcm.c

index 2b502f6cc6d036be6e25c6834671be1cde2fd8da..e580a675ea77ea682c6d83637a2f9c9d155abc82 100644 (file)
@@ -785,6 +785,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,
@@ -858,6 +862,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);
index f1901bb1466ec67b12189713c66ad040f1ae75c7..981443e444d168c83ca63601e650744fdb26ac29 100644 (file)
@@ -2976,6 +2976,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;
@@ -3158,6 +3160,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
@@ -3181,6 +3198,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";
index e7a1eaa2772f4418534d094e576b424a76aaa844..a9ef8ae20e44c5b0c50308f241ceb87bcd81cb27 100644 (file)
@@ -2640,12 +2640,25 @@ 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_component *component;
+
+       list_for_each_entry(component, &rtd->card->component_dev_list,
+                           card_list) {
+               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_pcm *pcm;
        char new_name[64];
        int ret = 0, playback = 0, capture = 0;
@@ -2754,17 +2767,18 @@ 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);
-               if (ret < 0) {
-                       dev_err(platform->dev,
-                               "ASoC: pcm constructor failed: %d\n",
-                               ret);
-                       return ret;
+       list_for_each_entry(component, &rtd->card->component_dev_list, card_list) {
+               if (component->pcm_new) {
+                       ret = component->pcm_new(rtd);
+                       if (ret < 0) {
+                               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,