|
@@ -52,6 +52,7 @@ EXPORT_SYMBOL_GPL(snd_soc_debugfs_root);
|
|
|
|
|
|
static DEFINE_MUTEX(client_mutex);
|
|
|
static LIST_HEAD(component_list);
|
|
|
+static LIST_HEAD(unbind_card_list);
|
|
|
|
|
|
/*
|
|
|
* This is a timeout to do a DAPM powerdown after a stream is closed().
|
|
@@ -2679,6 +2680,33 @@ int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute,
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
|
|
|
|
|
|
+static int snd_soc_bind_card(struct snd_soc_card *card)
|
|
|
+{
|
|
|
+ struct snd_soc_pcm_runtime *rtd;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = snd_soc_instantiate_card(card);
|
|
|
+ if (ret != 0)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ /* deactivate pins to sleep state */
|
|
|
+ list_for_each_entry(rtd, &card->rtd_list, list) {
|
|
|
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
|
|
+ struct snd_soc_dai *codec_dai;
|
|
|
+ int j;
|
|
|
+
|
|
|
+ for_each_rtd_codec_dai(rtd, j, codec_dai) {
|
|
|
+ if (!codec_dai->active)
|
|
|
+ pinctrl_pm_select_sleep_state(codec_dai->dev);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!cpu_dai->active)
|
|
|
+ pinctrl_pm_select_sleep_state(cpu_dai->dev);
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* snd_soc_register_card - Register a card with the ASoC core
|
|
|
*
|
|
@@ -2688,7 +2716,6 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
|
|
|
int snd_soc_register_card(struct snd_soc_card *card)
|
|
|
{
|
|
|
int i, ret;
|
|
|
- struct snd_soc_pcm_runtime *rtd;
|
|
|
|
|
|
if (!card->name || !card->dev)
|
|
|
return -EINVAL;
|
|
@@ -2719,28 +2746,23 @@ int snd_soc_register_card(struct snd_soc_card *card)
|
|
|
mutex_init(&card->mutex);
|
|
|
mutex_init(&card->dapm_mutex);
|
|
|
|
|
|
- ret = snd_soc_instantiate_card(card);
|
|
|
- if (ret != 0)
|
|
|
- return ret;
|
|
|
-
|
|
|
- /* deactivate pins to sleep state */
|
|
|
- list_for_each_entry(rtd, &card->rtd_list, list) {
|
|
|
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
|
|
- struct snd_soc_dai *codec_dai;
|
|
|
- int j;
|
|
|
-
|
|
|
- for_each_rtd_codec_dai(rtd, j, codec_dai) {
|
|
|
- if (!codec_dai->active)
|
|
|
- pinctrl_pm_select_sleep_state(codec_dai->dev);
|
|
|
- }
|
|
|
+ return snd_soc_bind_card(card);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(snd_soc_register_card);
|
|
|
|
|
|
- if (!cpu_dai->active)
|
|
|
- pinctrl_pm_select_sleep_state(cpu_dai->dev);
|
|
|
+static void snd_soc_unbind_card(struct snd_soc_card *card, bool unregister)
|
|
|
+{
|
|
|
+ if (card->instantiated) {
|
|
|
+ card->instantiated = false;
|
|
|
+ snd_soc_dapm_shutdown(card);
|
|
|
+ soc_cleanup_card_resources(card);
|
|
|
+ if (!unregister)
|
|
|
+ list_add(&card->list, &unbind_card_list);
|
|
|
+ } else {
|
|
|
+ if (unregister)
|
|
|
+ list_del(&card->list);
|
|
|
}
|
|
|
-
|
|
|
- return ret;
|
|
|
}
|
|
|
-EXPORT_SYMBOL_GPL(snd_soc_register_card);
|
|
|
|
|
|
/**
|
|
|
* snd_soc_unregister_card - Unregister a card with the ASoC core
|
|
@@ -2750,12 +2772,8 @@ EXPORT_SYMBOL_GPL(snd_soc_register_card);
|
|
|
*/
|
|
|
int snd_soc_unregister_card(struct snd_soc_card *card)
|
|
|
{
|
|
|
- if (card->instantiated) {
|
|
|
- card->instantiated = false;
|
|
|
- snd_soc_dapm_shutdown(card);
|
|
|
- soc_cleanup_card_resources(card);
|
|
|
- dev_dbg(card->dev, "ASoC: Unregistered card '%s'\n", card->name);
|
|
|
- }
|
|
|
+ snd_soc_unbind_card(card, true);
|
|
|
+ dev_dbg(card->dev, "ASoC: Unregistered card '%s'\n", card->name);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -3099,7 +3117,7 @@ static void snd_soc_component_del_unlocked(struct snd_soc_component *component)
|
|
|
struct snd_soc_card *card = component->card;
|
|
|
|
|
|
if (card)
|
|
|
- snd_soc_unregister_card(card);
|
|
|
+ snd_soc_unbind_card(card, false);
|
|
|
|
|
|
list_del(&component->list);
|
|
|
}
|
|
@@ -3139,6 +3157,18 @@ static void convert_endianness_formats(struct snd_soc_pcm_stream *stream)
|
|
|
stream->formats |= endianness_format_map[i];
|
|
|
}
|
|
|
|
|
|
+static void snd_soc_try_rebind_card(void)
|
|
|
+{
|
|
|
+ struct snd_soc_card *card, *c;
|
|
|
+
|
|
|
+ if (!list_empty(&unbind_card_list)) {
|
|
|
+ list_for_each_entry_safe(card, c, &unbind_card_list, list) {
|
|
|
+ if (!snd_soc_bind_card(card))
|
|
|
+ list_del(&card->list);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
int snd_soc_add_component(struct device *dev,
|
|
|
struct snd_soc_component *component,
|
|
|
const struct snd_soc_component_driver *component_driver,
|
|
@@ -3166,6 +3196,7 @@ int snd_soc_add_component(struct device *dev,
|
|
|
}
|
|
|
|
|
|
snd_soc_component_add(component);
|
|
|
+ snd_soc_try_rebind_card();
|
|
|
|
|
|
return 0;
|
|
|
|