@@ -1084,6 +1084,7 @@ struct snd_soc_card {
struct list_head paths;
struct list_head dapm_list;
struct list_head dapm_dirty;
+ struct list_head unbinded_list;
/* Generic DAPM context for the card */
struct snd_soc_dapm_context dapm;
@@ -56,6 +56,7 @@ static DEFINE_MUTEX(client_mutex);
static LIST_HEAD(platform_list);
static LIST_HEAD(codec_list);
static LIST_HEAD(component_list);
+static LIST_HEAD(unbinded_card_list);
/*
* This is a timeout to do a DAPM powerdown after a stream is closed().
@@ -2379,6 +2380,7 @@ int snd_soc_register_card(struct snd_soc_card *card)
card->rtd_aux[i].card = card;
INIT_LIST_HEAD(&card->dapm_dirty);
+ INIT_LIST_HEAD(&card->unbinded_list);
card->instantiated = 0;
mutex_init(&card->mutex);
mutex_init(&card->dapm_mutex);
@@ -2406,6 +2408,10 @@ int snd_soc_unregister_card(struct snd_soc_card *card)
dev_dbg(card->dev, "ASoC: Unregistered card '%s'\n", card->name);
}
+ mutex_lock(&client_mutex);
+ list_del_init(&card->unbinded_list);
+ mutex_unlock(&client_mutex);
+
return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_unregister_card);
@@ -2669,6 +2675,9 @@ EXPORT_SYMBOL_GPL(snd_soc_component_exit_regmap);
static void snd_soc_component_add_unlocked(struct snd_soc_component *component)
{
+ struct snd_soc_card *card, *_card;
+ int ret;
+
if (!component->write && !component->read) {
if (!component->regmap)
component->regmap = dev_get_regmap(component->dev, NULL);
@@ -2677,6 +2686,16 @@ static void snd_soc_component_add_unlocked(struct snd_soc_component *component)
}
list_add(&component->list, &component_list);
+
+ /* re-add temporarily removed card if exist */
+ list_for_each_entry_safe(card, _card, &unbinded_card_list,
+ unbinded_list) {
+ ret = snd_soc_instantiate_card(card);
+ if (ret < 0)
+ continue;
+
+ list_del_init(&card->unbinded_list);
+ }
}
static void snd_soc_component_add(struct snd_soc_component *component)
@@ -2694,7 +2713,15 @@ static void snd_soc_component_cleanup(struct snd_soc_component *component)
static void snd_soc_component_del_unlocked(struct snd_soc_component *component)
{
+ struct snd_soc_card *card = component->card;
+
list_del(&component->list);
+
+ /* card is removed temporarily */
+ if (component->probed && card->instantiated) {
+ list_add(&card->unbinded_list, &unbinded_card_list);
+ snd_soc_remove_card(card);
+ }
}
static void snd_soc_component_del(struct snd_soc_component *component)