Loading include/sound/soc-dai.h +1 −0 Original line number Diff line number Diff line Loading @@ -222,6 +222,7 @@ struct snd_soc_dai_driver { const char *name; unsigned int id; unsigned int base; struct snd_soc_dobj dobj; /* DAI driver callbacks */ int (*probe)(struct snd_soc_dai *dai); Loading include/sound/soc.h +9 −2 Original line number Diff line number Diff line Loading @@ -798,6 +798,7 @@ struct snd_soc_component { unsigned int registered_as_component:1; struct list_head list; struct list_head list_aux; /* for auxiliary component of the card */ struct snd_soc_dai_driver *dai_drv; int num_dai; Loading Loading @@ -841,6 +842,9 @@ struct snd_soc_component { int (*probe)(struct snd_soc_component *); void (*remove)(struct snd_soc_component *); /* machine specific init */ int (*init)(struct snd_soc_component *component); #ifdef CONFIG_DEBUG_FS void (*init_debugfs)(struct snd_soc_component *component); const char *debugfs_prefix; Loading Loading @@ -1141,8 +1145,7 @@ struct snd_soc_card { */ struct snd_soc_aux_dev *aux_dev; int num_aux_devs; struct snd_soc_pcm_runtime *rtd_aux; int num_aux_rtd; struct list_head aux_comp_list; const struct snd_kcontrol_new *controls; int num_controls; Loading Loading @@ -1550,6 +1553,7 @@ static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card) INIT_LIST_HEAD(&card->widgets); INIT_LIST_HEAD(&card->paths); INIT_LIST_HEAD(&card->dapm_list); INIT_LIST_HEAD(&card->aux_comp_list); } static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) Loading Loading @@ -1676,6 +1680,9 @@ int snd_soc_add_dai_link(struct snd_soc_card *card, void snd_soc_remove_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); int snd_soc_register_dai(struct snd_soc_component *component, struct snd_soc_dai_driver *dai_drv); #include <sound/soc-dai.h> #ifdef CONFIG_DEBUG_FS Loading sound/soc/soc-core.c +170 −104 Original line number Diff line number Diff line Loading @@ -1413,6 +1413,16 @@ static int soc_probe_component(struct snd_soc_card *card, component->name); } /* machine specific init */ if (component->init) { ret = component->init(component); if (ret < 0) { dev_err(component->dev, "Failed to do machine specific init %d\n", ret); goto err_probe; } } if (component->controls) snd_soc_add_component_controls(component, component->controls, component->num_controls); Loading Loading @@ -1657,65 +1667,81 @@ static int soc_probe_link_dais(struct snd_soc_card *card, static int soc_bind_aux_dev(struct snd_soc_card *card, int num) { struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; const char *name = aux_dev->codec_name; struct snd_soc_component *component; const char *name; struct device_node *codec_of_node; if (aux_dev->codec_of_node || aux_dev->codec_name) { /* codecs, usually analog devices */ name = aux_dev->codec_name; codec_of_node = aux_dev->codec_of_node; component = soc_find_component(codec_of_node, name); if (!component) { if (codec_of_node) name = of_node_full_name(codec_of_node); goto err_defer; } } else if (aux_dev->name) { /* generic components */ name = aux_dev->name; component = soc_find_component(NULL, name); if (!component) goto err_defer; } else { dev_err(card->dev, "ASoC: Invalid auxiliary device\n"); return -EINVAL; } rtd->component = soc_find_component(aux_dev->codec_of_node, name); if (!rtd->component) { if (aux_dev->codec_of_node) name = of_node_full_name(aux_dev->codec_of_node); component->init = aux_dev->init; list_add(&component->list_aux, &card->aux_comp_list); return 0; err_defer: dev_err(card->dev, "ASoC: %s not registered\n", name); return -EPROBE_DEFER; } /* * Some places still reference rtd->codec, so we have to keep that * initialized if the component is a CODEC. Once all those references * have been removed, this code can be removed as well. */ rtd->codec = rtd->component->codec; return 0; } static int soc_probe_aux_dev(struct snd_soc_card *card, int num) static int soc_probe_aux_devices(struct snd_soc_card *card) { struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; struct snd_soc_component *comp; int order; int ret; ret = soc_probe_component(card, rtd->component); if (ret < 0) return ret; /* do machine specific initialization */ if (aux_dev->init) { ret = aux_dev->init(rtd->component); for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; order++) { list_for_each_entry(comp, &card->aux_comp_list, list_aux) { if (comp->driver->probe_order == order) { ret = soc_probe_component(card, comp); if (ret < 0) { dev_err(card->dev, "ASoC: failed to init %s: %d\n", aux_dev->name, ret); dev_err(card->dev, "ASoC: failed to probe aux component %s %d\n", comp->name, ret); return ret; } } } } return soc_post_component_init(rtd, aux_dev->name); return 0; } static void soc_remove_aux_dev(struct snd_soc_card *card, int num) static void soc_remove_aux_devices(struct snd_soc_card *card) { struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; struct snd_soc_component *component = rtd->component; struct snd_soc_component *comp, *_comp; int order; /* unregister the rtd device */ if (rtd->dev_registered) { device_unregister(rtd->dev); rtd->dev_registered = 0; for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; order++) { list_for_each_entry_safe(comp, _comp, &card->aux_comp_list, list_aux) { if (comp->driver->remove_order == order) { soc_remove_component(comp); /* remove it from the card's aux_comp_list */ list_del(&comp->list_aux); } } } if (component) soc_remove_component(component); } static int snd_soc_init_codec_cache(struct snd_soc_codec *codec) Loading Loading @@ -1894,6 +1920,11 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) } } /* probe auxiliary components */ ret = soc_probe_aux_devices(card); if (ret < 0) goto probe_dai_err; /* Find new DAI links added during probing components and bind them. * Components with topology may bring new DAIs and DAI links. */ Loading Loading @@ -1923,16 +1954,6 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) } } for (i = 0; i < card->num_aux_devs; i++) { ret = soc_probe_aux_dev(card, i); if (ret < 0) { dev_err(card->dev, "ASoC: failed to add auxiliary devices %d\n", ret); goto probe_aux_dev_err; } } snd_soc_dapm_link_dai_widgets(card); snd_soc_dapm_connect_dai_link_widgets(card); Loading Loading @@ -1992,8 +2013,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) return 0; probe_aux_dev_err: for (i = 0; i < card->num_aux_devs; i++) soc_remove_aux_dev(card, i); soc_remove_aux_devices(card); probe_dai_err: soc_remove_dai_links(card); Loading Loading @@ -2039,20 +2059,18 @@ static int soc_probe(struct platform_device *pdev) static int soc_cleanup_card_resources(struct snd_soc_card *card) { struct snd_soc_pcm_runtime *rtd; int i; /* make sure any delayed work runs */ list_for_each_entry(rtd, &card->rtd_list, list) flush_delayed_work(&rtd->delayed_work); /* remove auxiliary devices */ for (i = 0; i < card->num_aux_devs; i++) soc_remove_aux_dev(card, i); /* remove and free each DAI */ soc_remove_dai_links(card); soc_remove_pcm_runtimes(card); /* remove auxiliary devices */ soc_remove_aux_devices(card); soc_cleanup_card_debugfs(card); /* remove the card */ Loading Loading @@ -2608,16 +2626,6 @@ int snd_soc_register_card(struct snd_soc_card *card) INIT_LIST_HEAD(&card->rtd_list); card->num_rtd = 0; card->rtd_aux = devm_kzalloc(card->dev, sizeof(struct snd_soc_pcm_runtime) * card->num_aux_devs, GFP_KERNEL); if (card->rtd_aux == NULL) return -ENOMEM; for (i = 0; i < card->num_aux_devs; i++) card->rtd_aux[i].card = card; INIT_LIST_HEAD(&card->dapm_dirty); INIT_LIST_HEAD(&card->dobj_list); card->instantiated = 0; Loading Loading @@ -2744,36 +2752,19 @@ static void snd_soc_unregister_dais(struct snd_soc_component *component) } } /** * snd_soc_register_dais - Register a DAI with the ASoC core * * @component: The component the DAIs are registered for * @dai_drv: DAI driver to use for the DAIs * @count: Number of DAIs * @legacy_dai_naming: Use the legacy naming scheme and let the DAI inherit the * parent's name. */ static int snd_soc_register_dais(struct snd_soc_component *component, struct snd_soc_dai_driver *dai_drv, size_t count, /* Create a DAI and add it to the component's DAI list */ static struct snd_soc_dai *soc_add_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; unsigned int i; int ret; dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count); component->dai_drv = dai_drv; component->num_dai = count; for (i = 0; i < count; i++) { 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; } if (dai == NULL) return NULL; /* * Back in the old days when we still had component-less DAIs, Loading @@ -2783,31 +2774,64 @@ static int snd_soc_register_dais(struct snd_soc_component *component, * the same naming style even though those DAIs are not * component-less anymore. */ if (count == 1 && legacy_dai_naming && (dai_drv[i].id == 0 || dai_drv[i].name == NULL)) { if (legacy_dai_naming && (dai_drv->id == 0 || dai_drv->name == NULL)) { dai->name = fmt_single_name(dev, &dai->id); } else { dai->name = fmt_multiple_name(dev, &dai_drv[i]); if (dai_drv[i].id) dai->id = dai_drv[i].id; dai->name = fmt_multiple_name(dev, dai_drv); if (dai_drv->id) dai->id = dai_drv->id; else dai->id = i; dai->id = component->num_dai; } if (dai->name == NULL) { kfree(dai); ret = -ENOMEM; goto err; return NULL; } dai->component = component; dai->dev = dev; dai->driver = &dai_drv[i]; 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; } /** * snd_soc_register_dais - Register a DAI with the ASoC core * * @component: The component the DAIs are registered for * @dai_drv: DAI driver to use for the DAIs * @count: Number of DAIs * @legacy_dai_naming: Use the legacy naming scheme and let the DAI inherit the * parent's name. */ static int snd_soc_register_dais(struct snd_soc_component *component, struct snd_soc_dai_driver *dai_drv, size_t count, bool legacy_dai_naming) { struct device *dev = component->dev; struct snd_soc_dai *dai; unsigned int i; int ret; dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count); component->dai_drv = dai_drv; for (i = 0; i < count; i++) { dai = soc_add_dai(component, dai_drv + i, count == 1 && legacy_dai_naming); if (dai == NULL) { ret = -ENOMEM; goto err; } } return 0; Loading @@ -2818,6 +2842,48 @@ static int snd_soc_register_dais(struct snd_soc_component *component, return ret; } /** * snd_soc_register_dai - Register a DAI dynamically & create its widgets * * @component: The component the DAIs are registered for * @dai_drv: DAI driver to use for the DAI * * 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 * will be freed in the component cleanup. */ int snd_soc_register_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_dai *dai; int ret; if (dai_drv->dobj.type != SND_SOC_DOBJ_PCM) { dev_err(component->dev, "Invalid dai type %d\n", dai_drv->dobj.type); return -EINVAL; } lockdep_assert_held(&client_mutex); dai = soc_add_dai(component, dai_drv, false); if (!dai) return -ENOMEM; /* Create the DAI widgets here. After adding DAIs, topology may * also add routes that need these widgets as source or sink. */ ret = snd_soc_dapm_new_dai_widgets(dapm, dai); if (ret != 0) { dev_err(component->dev, "Failed to create DAI widgets %d\n", ret); } return ret; } EXPORT_SYMBOL_GPL(snd_soc_register_dai); static void snd_soc_component_seq_notifier(struct snd_soc_dapm_context *dapm, enum snd_soc_dapm_type type, int subseq) { Loading Loading
include/sound/soc-dai.h +1 −0 Original line number Diff line number Diff line Loading @@ -222,6 +222,7 @@ struct snd_soc_dai_driver { const char *name; unsigned int id; unsigned int base; struct snd_soc_dobj dobj; /* DAI driver callbacks */ int (*probe)(struct snd_soc_dai *dai); Loading
include/sound/soc.h +9 −2 Original line number Diff line number Diff line Loading @@ -798,6 +798,7 @@ struct snd_soc_component { unsigned int registered_as_component:1; struct list_head list; struct list_head list_aux; /* for auxiliary component of the card */ struct snd_soc_dai_driver *dai_drv; int num_dai; Loading Loading @@ -841,6 +842,9 @@ struct snd_soc_component { int (*probe)(struct snd_soc_component *); void (*remove)(struct snd_soc_component *); /* machine specific init */ int (*init)(struct snd_soc_component *component); #ifdef CONFIG_DEBUG_FS void (*init_debugfs)(struct snd_soc_component *component); const char *debugfs_prefix; Loading Loading @@ -1141,8 +1145,7 @@ struct snd_soc_card { */ struct snd_soc_aux_dev *aux_dev; int num_aux_devs; struct snd_soc_pcm_runtime *rtd_aux; int num_aux_rtd; struct list_head aux_comp_list; const struct snd_kcontrol_new *controls; int num_controls; Loading Loading @@ -1550,6 +1553,7 @@ static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card) INIT_LIST_HEAD(&card->widgets); INIT_LIST_HEAD(&card->paths); INIT_LIST_HEAD(&card->dapm_list); INIT_LIST_HEAD(&card->aux_comp_list); } static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) Loading Loading @@ -1676,6 +1680,9 @@ int snd_soc_add_dai_link(struct snd_soc_card *card, void snd_soc_remove_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); int snd_soc_register_dai(struct snd_soc_component *component, struct snd_soc_dai_driver *dai_drv); #include <sound/soc-dai.h> #ifdef CONFIG_DEBUG_FS Loading
sound/soc/soc-core.c +170 −104 Original line number Diff line number Diff line Loading @@ -1413,6 +1413,16 @@ static int soc_probe_component(struct snd_soc_card *card, component->name); } /* machine specific init */ if (component->init) { ret = component->init(component); if (ret < 0) { dev_err(component->dev, "Failed to do machine specific init %d\n", ret); goto err_probe; } } if (component->controls) snd_soc_add_component_controls(component, component->controls, component->num_controls); Loading Loading @@ -1657,65 +1667,81 @@ static int soc_probe_link_dais(struct snd_soc_card *card, static int soc_bind_aux_dev(struct snd_soc_card *card, int num) { struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; const char *name = aux_dev->codec_name; struct snd_soc_component *component; const char *name; struct device_node *codec_of_node; if (aux_dev->codec_of_node || aux_dev->codec_name) { /* codecs, usually analog devices */ name = aux_dev->codec_name; codec_of_node = aux_dev->codec_of_node; component = soc_find_component(codec_of_node, name); if (!component) { if (codec_of_node) name = of_node_full_name(codec_of_node); goto err_defer; } } else if (aux_dev->name) { /* generic components */ name = aux_dev->name; component = soc_find_component(NULL, name); if (!component) goto err_defer; } else { dev_err(card->dev, "ASoC: Invalid auxiliary device\n"); return -EINVAL; } rtd->component = soc_find_component(aux_dev->codec_of_node, name); if (!rtd->component) { if (aux_dev->codec_of_node) name = of_node_full_name(aux_dev->codec_of_node); component->init = aux_dev->init; list_add(&component->list_aux, &card->aux_comp_list); return 0; err_defer: dev_err(card->dev, "ASoC: %s not registered\n", name); return -EPROBE_DEFER; } /* * Some places still reference rtd->codec, so we have to keep that * initialized if the component is a CODEC. Once all those references * have been removed, this code can be removed as well. */ rtd->codec = rtd->component->codec; return 0; } static int soc_probe_aux_dev(struct snd_soc_card *card, int num) static int soc_probe_aux_devices(struct snd_soc_card *card) { struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; struct snd_soc_component *comp; int order; int ret; ret = soc_probe_component(card, rtd->component); if (ret < 0) return ret; /* do machine specific initialization */ if (aux_dev->init) { ret = aux_dev->init(rtd->component); for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; order++) { list_for_each_entry(comp, &card->aux_comp_list, list_aux) { if (comp->driver->probe_order == order) { ret = soc_probe_component(card, comp); if (ret < 0) { dev_err(card->dev, "ASoC: failed to init %s: %d\n", aux_dev->name, ret); dev_err(card->dev, "ASoC: failed to probe aux component %s %d\n", comp->name, ret); return ret; } } } } return soc_post_component_init(rtd, aux_dev->name); return 0; } static void soc_remove_aux_dev(struct snd_soc_card *card, int num) static void soc_remove_aux_devices(struct snd_soc_card *card) { struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; struct snd_soc_component *component = rtd->component; struct snd_soc_component *comp, *_comp; int order; /* unregister the rtd device */ if (rtd->dev_registered) { device_unregister(rtd->dev); rtd->dev_registered = 0; for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; order++) { list_for_each_entry_safe(comp, _comp, &card->aux_comp_list, list_aux) { if (comp->driver->remove_order == order) { soc_remove_component(comp); /* remove it from the card's aux_comp_list */ list_del(&comp->list_aux); } } } if (component) soc_remove_component(component); } static int snd_soc_init_codec_cache(struct snd_soc_codec *codec) Loading Loading @@ -1894,6 +1920,11 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) } } /* probe auxiliary components */ ret = soc_probe_aux_devices(card); if (ret < 0) goto probe_dai_err; /* Find new DAI links added during probing components and bind them. * Components with topology may bring new DAIs and DAI links. */ Loading Loading @@ -1923,16 +1954,6 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) } } for (i = 0; i < card->num_aux_devs; i++) { ret = soc_probe_aux_dev(card, i); if (ret < 0) { dev_err(card->dev, "ASoC: failed to add auxiliary devices %d\n", ret); goto probe_aux_dev_err; } } snd_soc_dapm_link_dai_widgets(card); snd_soc_dapm_connect_dai_link_widgets(card); Loading Loading @@ -1992,8 +2013,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) return 0; probe_aux_dev_err: for (i = 0; i < card->num_aux_devs; i++) soc_remove_aux_dev(card, i); soc_remove_aux_devices(card); probe_dai_err: soc_remove_dai_links(card); Loading Loading @@ -2039,20 +2059,18 @@ static int soc_probe(struct platform_device *pdev) static int soc_cleanup_card_resources(struct snd_soc_card *card) { struct snd_soc_pcm_runtime *rtd; int i; /* make sure any delayed work runs */ list_for_each_entry(rtd, &card->rtd_list, list) flush_delayed_work(&rtd->delayed_work); /* remove auxiliary devices */ for (i = 0; i < card->num_aux_devs; i++) soc_remove_aux_dev(card, i); /* remove and free each DAI */ soc_remove_dai_links(card); soc_remove_pcm_runtimes(card); /* remove auxiliary devices */ soc_remove_aux_devices(card); soc_cleanup_card_debugfs(card); /* remove the card */ Loading Loading @@ -2608,16 +2626,6 @@ int snd_soc_register_card(struct snd_soc_card *card) INIT_LIST_HEAD(&card->rtd_list); card->num_rtd = 0; card->rtd_aux = devm_kzalloc(card->dev, sizeof(struct snd_soc_pcm_runtime) * card->num_aux_devs, GFP_KERNEL); if (card->rtd_aux == NULL) return -ENOMEM; for (i = 0; i < card->num_aux_devs; i++) card->rtd_aux[i].card = card; INIT_LIST_HEAD(&card->dapm_dirty); INIT_LIST_HEAD(&card->dobj_list); card->instantiated = 0; Loading Loading @@ -2744,36 +2752,19 @@ static void snd_soc_unregister_dais(struct snd_soc_component *component) } } /** * snd_soc_register_dais - Register a DAI with the ASoC core * * @component: The component the DAIs are registered for * @dai_drv: DAI driver to use for the DAIs * @count: Number of DAIs * @legacy_dai_naming: Use the legacy naming scheme and let the DAI inherit the * parent's name. */ static int snd_soc_register_dais(struct snd_soc_component *component, struct snd_soc_dai_driver *dai_drv, size_t count, /* Create a DAI and add it to the component's DAI list */ static struct snd_soc_dai *soc_add_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; unsigned int i; int ret; dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count); component->dai_drv = dai_drv; component->num_dai = count; for (i = 0; i < count; i++) { 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; } if (dai == NULL) return NULL; /* * Back in the old days when we still had component-less DAIs, Loading @@ -2783,31 +2774,64 @@ static int snd_soc_register_dais(struct snd_soc_component *component, * the same naming style even though those DAIs are not * component-less anymore. */ if (count == 1 && legacy_dai_naming && (dai_drv[i].id == 0 || dai_drv[i].name == NULL)) { if (legacy_dai_naming && (dai_drv->id == 0 || dai_drv->name == NULL)) { dai->name = fmt_single_name(dev, &dai->id); } else { dai->name = fmt_multiple_name(dev, &dai_drv[i]); if (dai_drv[i].id) dai->id = dai_drv[i].id; dai->name = fmt_multiple_name(dev, dai_drv); if (dai_drv->id) dai->id = dai_drv->id; else dai->id = i; dai->id = component->num_dai; } if (dai->name == NULL) { kfree(dai); ret = -ENOMEM; goto err; return NULL; } dai->component = component; dai->dev = dev; dai->driver = &dai_drv[i]; 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; } /** * snd_soc_register_dais - Register a DAI with the ASoC core * * @component: The component the DAIs are registered for * @dai_drv: DAI driver to use for the DAIs * @count: Number of DAIs * @legacy_dai_naming: Use the legacy naming scheme and let the DAI inherit the * parent's name. */ static int snd_soc_register_dais(struct snd_soc_component *component, struct snd_soc_dai_driver *dai_drv, size_t count, bool legacy_dai_naming) { struct device *dev = component->dev; struct snd_soc_dai *dai; unsigned int i; int ret; dev_dbg(dev, "ASoC: dai register %s #%Zu\n", dev_name(dev), count); component->dai_drv = dai_drv; for (i = 0; i < count; i++) { dai = soc_add_dai(component, dai_drv + i, count == 1 && legacy_dai_naming); if (dai == NULL) { ret = -ENOMEM; goto err; } } return 0; Loading @@ -2818,6 +2842,48 @@ static int snd_soc_register_dais(struct snd_soc_component *component, return ret; } /** * snd_soc_register_dai - Register a DAI dynamically & create its widgets * * @component: The component the DAIs are registered for * @dai_drv: DAI driver to use for the DAI * * 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 * will be freed in the component cleanup. */ int snd_soc_register_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_dai *dai; int ret; if (dai_drv->dobj.type != SND_SOC_DOBJ_PCM) { dev_err(component->dev, "Invalid dai type %d\n", dai_drv->dobj.type); return -EINVAL; } lockdep_assert_held(&client_mutex); dai = soc_add_dai(component, dai_drv, false); if (!dai) return -ENOMEM; /* Create the DAI widgets here. After adding DAIs, topology may * also add routes that need these widgets as source or sink. */ ret = snd_soc_dapm_new_dai_widgets(dapm, dai); if (ret != 0) { dev_err(component->dev, "Failed to create DAI widgets %d\n", ret); } return ret; } EXPORT_SYMBOL_GPL(snd_soc_register_dai); static void snd_soc_component_seq_notifier(struct snd_soc_dapm_context *dapm, enum snd_soc_dapm_type type, int subseq) { Loading