OSDN Git Service

Merge branch 'for-5.5' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie...
[tomoyo/tomoyo-test1.git] / sound / soc / soc-core.c
index 1c84ff1..750469a 100644 (file)
@@ -389,22 +389,22 @@ struct snd_soc_component *snd_soc_lookup_component(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(snd_soc_lookup_component);
 
-struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card,
-               const char *dai_link, int stream)
+static const struct snd_soc_ops null_snd_soc_ops;
+
+struct snd_soc_pcm_runtime
+*snd_soc_get_pcm_runtime(struct snd_soc_card *card,
+                        struct snd_soc_dai_link *dai_link)
 {
        struct snd_soc_pcm_runtime *rtd;
 
        for_each_card_rtds(card, rtd) {
-               if (rtd->dai_link->no_pcm &&
-                       !strcmp(rtd->dai_link->name, dai_link))
-                       return rtd->pcm->streams[stream].substream;
+               if (rtd->dai_link == dai_link)
+                       return rtd;
        }
-       dev_dbg(card->dev, "ASoC: failed to find dai link %s\n", dai_link);
+       dev_dbg(card->dev, "ASoC: failed to find rtd %s\n", dai_link->name);
        return NULL;
 }
-EXPORT_SYMBOL_GPL(snd_soc_get_dai_substream);
-
-static const struct snd_soc_ops null_snd_soc_ops;
+EXPORT_SYMBOL_GPL(snd_soc_get_pcm_runtime);
 
 static void soc_release_rtd_dev(struct device *dev)
 {
@@ -517,20 +517,6 @@ free_rtd:
        return NULL;
 }
 
-struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card,
-               const char *dai_link)
-{
-       struct snd_soc_pcm_runtime *rtd;
-
-       for_each_card_rtds(card, rtd) {
-               if (!strcmp(rtd->dai_link->name, dai_link))
-                       return rtd;
-       }
-       dev_dbg(card->dev, "ASoC: failed to find rtd %s\n", dai_link);
-       return NULL;
-}
-EXPORT_SYMBOL_GPL(snd_soc_get_pcm_runtime);
-
 static void snd_soc_flush_all_delayed_work(struct snd_soc_card *card)
 {
        struct snd_soc_pcm_runtime *rtd;
@@ -926,47 +912,6 @@ struct snd_soc_dai *snd_soc_find_dai(
 }
 EXPORT_SYMBOL_GPL(snd_soc_find_dai);
 
-/**
- * snd_soc_find_dai_link - Find a DAI link
- *
- * @card: soc card
- * @id: DAI link ID to match
- * @name: DAI link name to match, optional
- * @stream_name: DAI link stream name to match, optional
- *
- * This function will search all existing DAI links of the soc card to
- * find the link of the same ID. Since DAI links may not have their
- * unique ID, so name and stream name should also match if being
- * specified.
- *
- * Return: pointer of DAI link, or NULL if not found.
- */
-struct snd_soc_dai_link *snd_soc_find_dai_link(struct snd_soc_card *card,
-                                              int id, const char *name,
-                                              const char *stream_name)
-{
-       struct snd_soc_dai_link *link;
-
-       lockdep_assert_held(&client_mutex);
-
-       for_each_card_links(card, link) {
-               if (link->id != id)
-                       continue;
-
-               if (name && (!link->name || strcmp(name, link->name)))
-                       continue;
-
-               if (stream_name && (!link->stream_name
-                       || strcmp(stream_name, link->stream_name)))
-                       continue;
-
-               return link;
-       }
-
-       return NULL;
-}
-EXPORT_SYMBOL_GPL(snd_soc_find_dai_link);
-
 static int soc_dai_link_sanity_check(struct snd_soc_card *card,
                                     struct snd_soc_dai_link *link)
 {
@@ -1064,49 +1009,40 @@ static int soc_dai_link_sanity_check(struct snd_soc_card *card,
 }
 
 /**
- * snd_soc_remove_dai_link - Remove a DAI link from the list
- * @card: The ASoC card that owns the link
- * @dai_link: The DAI link to remove
+ * snd_soc_remove_pcm_runtime - Remove a pcm_runtime from card
+ * @card: The ASoC card to which the pcm_runtime has
+ * @rtd: The pcm_runtime to remove
  *
- * This function removes a DAI link from the ASoC card's link list.
- *
- * For DAI links previously added by topology, topology should
- * remove them by using the dobj embedded in the link.
+ * This function removes a pcm_runtime from the ASoC card.
  */
-void snd_soc_remove_dai_link(struct snd_soc_card *card,
-                            struct snd_soc_dai_link *dai_link)
+void snd_soc_remove_pcm_runtime(struct snd_soc_card *card,
+                               struct snd_soc_pcm_runtime *rtd)
 {
-       struct snd_soc_pcm_runtime *rtd;
-
        lockdep_assert_held(&client_mutex);
 
        /*
         * Notify the machine driver for extra destruction
         */
        if (card->remove_dai_link)
-               card->remove_dai_link(card, dai_link);
+               card->remove_dai_link(card, rtd->dai_link);
 
-       list_del(&dai_link->list);
-
-       rtd = snd_soc_get_pcm_runtime(card, dai_link->name);
-       if (rtd)
-               soc_free_pcm_runtime(rtd);
+       soc_free_pcm_runtime(rtd);
 }
-EXPORT_SYMBOL_GPL(snd_soc_remove_dai_link);
+EXPORT_SYMBOL_GPL(snd_soc_remove_pcm_runtime);
 
 /**
- * snd_soc_add_dai_link - Add a DAI link dynamically
- * @card: The ASoC card to which the DAI link is added
- * @dai_link: The new DAI link to add
+ * snd_soc_add_pcm_runtime - Add a pcm_runtime dynamically via dai_link
+ * @card: The ASoC card to which the pcm_runtime is added
+ * @dai_link: The DAI link to find pcm_runtime
  *
- * This function adds a DAI link to the ASoC card's link list.
+ * This function adds a pcm_runtime ASoC card by using dai_link.
  *
- * Note: Topology can use this API to add DAI links when probing the
+ * Note: Topology can use this API to add pcm_runtime when probing the
  * topology component. And machine drivers can still define static
  * DAI links in dai_link array.
  */
-int snd_soc_add_dai_link(struct snd_soc_card *card,
-                        struct snd_soc_dai_link *dai_link)
+int snd_soc_add_pcm_runtime(struct snd_soc_card *card,
+                           struct snd_soc_dai_link *dai_link)
 {
        struct snd_soc_pcm_runtime *rtd;
        struct snd_soc_dai_link_component *codec, *platform;
@@ -1169,16 +1105,106 @@ int snd_soc_add_dai_link(struct snd_soc_card *card,
                }
        }
 
-       /* see for_each_card_links */
-       list_add_tail(&dai_link->list, &card->dai_link_list);
-
        return 0;
 
 _err_defer:
-       soc_free_pcm_runtime(rtd);
+       snd_soc_remove_pcm_runtime(card, rtd);
        return -EPROBE_DEFER;
 }
-EXPORT_SYMBOL_GPL(snd_soc_add_dai_link);
+EXPORT_SYMBOL_GPL(snd_soc_add_pcm_runtime);
+
+static int soc_dai_pcm_new(struct snd_soc_dai **dais, int num_dais,
+                          struct snd_soc_pcm_runtime *rtd)
+{
+       int i, ret = 0;
+
+       for (i = 0; i < num_dais; ++i) {
+               struct snd_soc_dai_driver *drv = dais[i]->driver;
+
+               if (drv->pcm_new)
+                       ret = drv->pcm_new(rtd, dais[i]);
+               if (ret < 0) {
+                       dev_err(dais[i]->dev,
+                               "ASoC: Failed to bind %s with pcm device\n",
+                               dais[i]->name);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static int soc_init_pcm_runtime(struct snd_soc_card *card,
+                               struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_soc_dai_link *dai_link = rtd->dai_link;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       struct snd_soc_rtdcom_list *rtdcom;
+       struct snd_soc_component *component;
+       int ret, num;
+
+       /* set default power off timeout */
+       rtd->pmdown_time = pmdown_time;
+
+       /* do machine specific initialization */
+       if (dai_link->init) {
+               ret = dai_link->init(rtd);
+               if (ret < 0) {
+                       dev_err(card->dev, "ASoC: failed to init %s: %d\n",
+                               dai_link->name, ret);
+                       return ret;
+               }
+       }
+
+       if (dai_link->dai_fmt) {
+               ret = snd_soc_runtime_set_dai_fmt(rtd, dai_link->dai_fmt);
+               if (ret)
+                       return ret;
+       }
+
+       /* add DPCM sysfs entries */
+       soc_dpcm_debugfs_add(rtd);
+
+       num = rtd->num;
+
+       /*
+        * most drivers will register their PCMs using DAI link ordering but
+        * topology based drivers can use the DAI link id field to set PCM
+        * device number and then use rtd + a base offset of the BEs.
+        */
+       for_each_rtd_components(rtd, rtdcom, component) {
+               if (!component->driver->use_dai_pcm_id)
+                       continue;
+
+               if (rtd->dai_link->no_pcm)
+                       num += component->driver->be_pcm_base;
+               else
+                       num = rtd->dai_link->id;
+       }
+
+       /* create compress_device if possible */
+       ret = snd_soc_dai_compress_new(cpu_dai, rtd, num);
+       if (ret != -ENOTSUPP) {
+               if (ret < 0)
+                       dev_err(card->dev, "ASoC: can't create compress %s\n",
+                               dai_link->stream_name);
+               return ret;
+       }
+
+       /* create the pcm */
+       ret = soc_new_pcm(rtd, num);
+       if (ret < 0) {
+               dev_err(card->dev, "ASoC: can't create pcm %s :%d\n",
+                       dai_link->stream_name, ret);
+               return ret;
+       }
+       ret = soc_dai_pcm_new(&cpu_dai, 1, rtd);
+       if (ret < 0)
+               return ret;
+       ret = soc_dai_pcm_new(rtd->codec_dais,
+                             rtd->num_codecs, rtd);
+       return ret;
+}
 
 static void soc_set_of_name_prefix(struct snd_soc_component *component)
 {
@@ -1194,11 +1220,11 @@ static void soc_set_of_name_prefix(struct snd_soc_component *component)
 static void soc_set_name_prefix(struct snd_soc_card *card,
                                struct snd_soc_component *component)
 {
+       struct device_node *of_node = soc_component_to_node(component);
        int i;
 
-       for (i = 0; i < card->num_configs && card->codec_conf; i++) {
+       for (i = 0; i < card->num_configs; i++) {
                struct snd_soc_codec_conf *map = &card->codec_conf[i];
-               struct device_node *of_node = soc_component_to_node(component);
 
                if (map->of_node && of_node != map->of_node)
                        continue;
@@ -1457,111 +1483,6 @@ static int soc_probe_link_components(struct snd_soc_card *card)
        return 0;
 }
 
-void snd_soc_disconnect_sync(struct device *dev)
-{
-       struct snd_soc_component *component =
-                       snd_soc_lookup_component(dev, NULL);
-
-       if (!component || !component->card)
-               return;
-
-       snd_card_disconnect_sync(component->card->snd_card);
-}
-EXPORT_SYMBOL_GPL(snd_soc_disconnect_sync);
-
-static int soc_link_dai_pcm_new(struct snd_soc_dai **dais, int num_dais,
-                               struct snd_soc_pcm_runtime *rtd)
-{
-       int i, ret = 0;
-
-       for (i = 0; i < num_dais; ++i) {
-               struct snd_soc_dai_driver *drv = dais[i]->driver;
-
-               if (drv->pcm_new)
-                       ret = drv->pcm_new(rtd, dais[i]);
-               if (ret < 0) {
-                       dev_err(dais[i]->dev,
-                               "ASoC: Failed to bind %s with pcm device\n",
-                               dais[i]->name);
-                       return ret;
-               }
-       }
-
-       return 0;
-}
-
-static int soc_link_init(struct snd_soc_card *card,
-                        struct snd_soc_pcm_runtime *rtd)
-{
-       struct snd_soc_dai_link *dai_link = rtd->dai_link;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       struct snd_soc_rtdcom_list *rtdcom;
-       struct snd_soc_component *component;
-       int ret, num;
-
-       /* set default power off timeout */
-       rtd->pmdown_time = pmdown_time;
-
-       /* do machine specific initialization */
-       if (dai_link->init) {
-               ret = dai_link->init(rtd);
-               if (ret < 0) {
-                       dev_err(card->dev, "ASoC: failed to init %s: %d\n",
-                               dai_link->name, ret);
-                       return ret;
-               }
-       }
-
-       if (dai_link->dai_fmt) {
-               ret = snd_soc_runtime_set_dai_fmt(rtd, dai_link->dai_fmt);
-               if (ret)
-                       return ret;
-       }
-
-       /* add DPCM sysfs entries */
-       soc_dpcm_debugfs_add(rtd);
-
-       num = rtd->num;
-
-       /*
-        * most drivers will register their PCMs using DAI link ordering but
-        * topology based drivers can use the DAI link id field to set PCM
-        * device number and then use rtd + a base offset of the BEs.
-        */
-       for_each_rtd_components(rtd, rtdcom, component) {
-               if (!component->driver->use_dai_pcm_id)
-                       continue;
-
-               if (rtd->dai_link->no_pcm)
-                       num += component->driver->be_pcm_base;
-               else
-                       num = rtd->dai_link->id;
-       }
-
-       /* create compress_device if possible */
-       ret = snd_soc_dai_compress_new(cpu_dai, rtd, num);
-       if (ret != -ENOTSUPP) {
-               if (ret < 0)
-                       dev_err(card->dev, "ASoC: can't create compress %s\n",
-                                        dai_link->stream_name);
-               return ret;
-       }
-
-       /* create the pcm */
-       ret = soc_new_pcm(rtd, num);
-       if (ret < 0) {
-               dev_err(card->dev, "ASoC: can't create pcm %s :%d\n",
-                       dai_link->stream_name, ret);
-               return ret;
-       }
-       ret = soc_link_dai_pcm_new(&cpu_dai, 1, rtd);
-       if (ret < 0)
-               return ret;
-       ret = soc_link_dai_pcm_new(rtd->codec_dais,
-                                  rtd->num_codecs, rtd);
-       return ret;
-}
-
 static void soc_unbind_aux_dev(struct snd_soc_card *card)
 {
        struct snd_soc_component *component, *_component;
@@ -1942,7 +1863,7 @@ static void __soc_setup_card_name(char *name, int len,
 static void soc_cleanup_card_resources(struct snd_soc_card *card,
                                       int card_probed)
 {
-       struct snd_soc_dai_link *link, *_link;
+       struct snd_soc_pcm_runtime *rtd, *n;
 
        if (card->snd_card)
                snd_card_disconnect_sync(card->snd_card);
@@ -1953,8 +1874,8 @@ static void soc_cleanup_card_resources(struct snd_soc_card *card,
        soc_remove_link_dais(card);
        soc_remove_link_components(card);
 
-       for_each_card_links_safe(card, link, _link)
-               snd_soc_remove_dai_link(card, link);
+       for_each_card_rtds_safe(card, rtd, n)
+               snd_soc_remove_pcm_runtime(card, rtd);
 
        /* remove auxiliary devices */
        soc_remove_aux_devices(card);
@@ -2012,7 +1933,7 @@ static int snd_soc_bind_card(struct snd_soc_card *card)
        /* add predefined DAI links to the list */
        card->num_rtd = 0;
        for_each_card_prelinks(card, i, dai_link) {
-               ret = snd_soc_add_dai_link(card, dai_link);
+               ret = snd_soc_add_pcm_runtime(card, dai_link);
                if (ret < 0)
                        goto probe_end;
        }
@@ -2073,8 +1994,11 @@ static int snd_soc_bind_card(struct snd_soc_card *card)
                goto probe_end;
        }
 
-       for_each_card_rtds(card, rtd)
-               soc_link_init(card, rtd);
+       for_each_card_rtds(card, rtd) {
+               ret = soc_init_pcm_runtime(card, rtd);
+               if (ret < 0)
+                       goto probe_end;
+       }
 
        snd_soc_dapm_link_dai_widgets(card);
        snd_soc_dapm_connect_dai_link_widgets(card);
@@ -2404,7 +2328,6 @@ int snd_soc_register_card(struct snd_soc_card *card)
        INIT_LIST_HEAD(&card->aux_comp_list);
        INIT_LIST_HEAD(&card->component_dev_list);
        INIT_LIST_HEAD(&card->list);
-       INIT_LIST_HEAD(&card->dai_link_list);
        INIT_LIST_HEAD(&card->rtd_list);
        INIT_LIST_HEAD(&card->dapm_dirty);
        INIT_LIST_HEAD(&card->dobj_list);
@@ -2509,6 +2432,8 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_dai);
  *
  * @component: The component the DAIs are registered for
  * @dai_drv: DAI driver to use for the DAI
+ * @legacy_dai_naming: if %true, use legacy single-name format;
+ *     if %false, use multiple-name format;
  *
  * Topology can use this API to register DAIs when probing a component.
  * These DAIs's widgets will be freed in the card cleanup and the DAIs