@@ -1081,6 +1081,7 @@ struct snd_soc_card {
int (*set_bias_level_post)(struct snd_soc_card *,
struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level);
+ int (*add_dai)(struct snd_soc_card *, struct snd_soc_dai_driver*);
long pmdown_time;
@@ -1634,6 +1635,9 @@ int snd_soc_of_get_dai_link_codecs(struct device *dev,
void snd_soc_add_dai_link(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_link);
+int snd_soc_add_dai(struct snd_soc_component *component,
+ struct snd_soc_dai_driver *dai_drv);
+
#include <sound/soc-dai.h>
#ifdef CONFIG_DEBUG_FS
@@ -2792,6 +2792,98 @@ err:
return ret;
}
+static struct snd_soc_dai *soc_register_dai(struct snd_soc_component *component,
+ struct snd_soc_dai_driver *dai_drv,
+ bool legacy_dai_naming)
+{
+ struct device *dev = component->dev;
+ struct snd_soc_dai *dai;
+ int ret;
+
+ dev_dbg(dev, "ASoC: dynamically register DAI %s\n", dev_name(dev));
+
+ dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);
+ if (dai == NULL) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ /*
+ * Back in the old days when we still had component-less DAIs,
+ * instead of having a static name, component-less DAIs would
+ * inherit the name of the parent device so it is possible to
+ * register multiple instances of the DAI. We still need to keep
+ * the same naming style even though those DAIs are not
+ * component-less anymore.
+ */
+ if (legacy_dai_naming) {
+ dai->name = fmt_single_name(dev, &dai->id);
+ } else {
+ dai->name = fmt_multiple_name(dev, dai_drv);
+ if (dai_drv->id)
+ dai->id = dai_drv->id;
+ else
+ dai->id = component->num_dai;
+ }
+ if (dai->name == NULL) {
+ kfree(dai);
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ dai->component = component;
+ dai->dev = dev;
+ dai->driver = dai_drv;
+ if (!dai->driver->ops)
+ dai->driver->ops = &null_dai_ops;
+
+ list_add(&dai->list, &component->dai_list);
+ component->num_dai++;
+
+ dev_dbg(dev, "ASoC: Registered DAI '%s'\n", dai->name);
+ return dai;
+
+err:
+ kfree(dai);
+ return NULL;
+}
+
+/**
+ * snd_soc_add_dai - Add a DAI dynamically with the ASoC core
+ *
+ * @component: The component the DAIs are registered for
+ * @dai_drv: DAI driver to use for the DAI
+ */
+int snd_soc_add_dai(struct snd_soc_component *component,
+ struct snd_soc_dai_driver *dai_drv)
+{
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_component_get_dapm(component);
+ struct snd_soc_card *card = component->card;
+ struct snd_soc_dai *dai;
+ int ret;
+
+ lockdep_assert_held(&client_mutex);
+ dai = soc_register_dai(component, dai_drv, false);
+ if (!dai)
+ return -ENOMEM;
+
+ ret = snd_soc_dapm_new_dai_widgets(dapm, dai);
+ if (ret != 0) {
+ dev_err(component->dev,
+ "Failed to create DAI widgets %d\n", ret);
+ }
+
+ /* Notify the machine driver a new DAI is added, so the machine driver
+ * can add new DAI links in the callback context.
+ */
+ if (card && card->add_dai)
+ card->add_dai(card, dai_drv);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_add_dai);
+
static void snd_soc_component_seq_notifier(struct snd_soc_dapm_context *dapm,
enum snd_soc_dapm_type type, int subseq)
{