Skip to content

Commit

Permalink
ASoC: core: add support to card rebind
Browse files Browse the repository at this point in the history
Current behaviour of ASoC core w.r.t to component removal is that it
unregisters dependent sound card totally. There is no support to
rebind the card if the component comes back.
Typical use case is DSP restart or kernel modules itself.

With this patch, core now maintains list of cards that are unbind due to
any of its depended components are removed and card not unregistered yet.
This list is cleared when the card is rebind successfully or when the
card is unregistered from machine driver.

This list of unbind cards are tried to bind once again after every new
component is successfully added, giving a fair chance for card bind
to be successful.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
  • Loading branch information
Srinivas Kandagatla authored and Mark Brown committed Sep 12, 2018
1 parent e1e38ea commit e894efe
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 27 deletions.
2 changes: 2 additions & 0 deletions include/sound/soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -1097,6 +1097,7 @@ struct snd_soc_card {

/* lists of probed devices belonging to this card */
struct list_head component_dev_list;
struct list_head list;

struct list_head widgets;
struct list_head paths;
Expand Down Expand Up @@ -1373,6 +1374,7 @@ static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card)
INIT_LIST_HEAD(&card->dapm_list);
INIT_LIST_HEAD(&card->aux_comp_list);
INIT_LIST_HEAD(&card->component_dev_list);
INIT_LIST_HEAD(&card->list);
}

static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc)
Expand Down
85 changes: 58 additions & 27 deletions sound/soc/soc-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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().
Expand Down Expand Up @@ -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
*
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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;
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -3166,6 +3196,7 @@ int snd_soc_add_component(struct device *dev,
}

snd_soc_component_add(component);
snd_soc_try_rebind_card();

return 0;

Expand Down

0 comments on commit e894efe

Please sign in to comment.