Skip to content

Commit

Permalink
ASoC: core: Use driver core probe deferral
Browse files Browse the repository at this point in the history
In version 3.4 the driver core acquired probe deferral which is a core way
of doing essentially the same thing as ASoC has been doing since forever
to make sure that all the devices needed to make up the card are present
without needing open coding in the subsystem.

Make basic use of this probe deferral mechanism for the cards, removing the
need to handle partially instantiated cards. We should be able to remove
even more code than this, though some of the checks we're currently doing
should stay since they're about things like suppressing unneeded DAPM runs
rather than deferring probes.

In order to avoid robustness issues with our teardown paths (which do need
quite a bit of TLC) add a check for aux_devs prior to attempting to set
things up, this means that we've got a reasonable idea that everything will
be there before we start. As with the removal of partial instantiation
support more work will be needed to make this work neatly.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Liam Girdwood <lrg@ti.com>
  • Loading branch information
Mark Brown committed Apr 1, 2012
1 parent 2667b4b commit b19e6e7
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 86 deletions.
1 change: 0 additions & 1 deletion include/sound/soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -896,7 +896,6 @@ struct snd_soc_pcm_runtime {
enum snd_soc_pcm_subclass pcm_subclass;
struct snd_pcm_ops ops;

unsigned int complete:1;
unsigned int dev_registered:1;

long pmdown_time;
Expand Down
147 changes: 62 additions & 85 deletions sound/soc/soc-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ EXPORT_SYMBOL_GPL(snd_soc_debugfs_root);
#endif

static DEFINE_MUTEX(client_mutex);
static LIST_HEAD(card_list);
static LIST_HEAD(dai_list);
static LIST_HEAD(platform_list);
static LIST_HEAD(codec_list);
Expand Down Expand Up @@ -785,15 +784,9 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
struct snd_soc_dai *codec_dai, *cpu_dai;
const char *platform_name;

if (rtd->complete)
return 1;
dev_dbg(card->dev, "binding %s at idx %d\n", dai_link->name, num);

/* do we already have the CPU DAI for this link ? */
if (rtd->cpu_dai) {
goto find_codec;
}
/* no, then find CPU DAI from registered DAIs*/
/* Find CPU DAI from registered DAIs*/
list_for_each_entry(cpu_dai, &dai_list, list) {
if (dai_link->cpu_dai_of_node) {
if (cpu_dai->dev->of_node != dai_link->cpu_dai_of_node)
Expand All @@ -804,18 +797,15 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
}

rtd->cpu_dai = cpu_dai;
goto find_codec;
}
dev_dbg(card->dev, "CPU DAI %s not registered\n",
dai_link->cpu_dai_name);

find_codec:
/* do we already have the CODEC for this link ? */
if (rtd->codec) {
goto find_platform;
if (!rtd->cpu_dai) {
dev_dbg(card->dev, "CPU DAI %s not registered\n",
dai_link->cpu_dai_name);
return -EPROBE_DEFER;
}

/* no, then find CODEC from registered CODECs*/
/* Find CODEC from registered CODECs */
list_for_each_entry(codec, &codec_list, list) {
if (dai_link->codec_of_node) {
if (codec->dev->of_node != dai_link->codec_of_node)
Expand All @@ -837,28 +827,28 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
dai_link->codec_dai_name)) {

rtd->codec_dai = codec_dai;
goto find_platform;
}
}
dev_dbg(card->dev, "CODEC DAI %s not registered\n",
dai_link->codec_dai_name);

goto find_platform;
if (!rtd->codec_dai) {
dev_dbg(card->dev, "CODEC DAI %s not registered\n",
dai_link->codec_dai_name);
return -EPROBE_DEFER;
}
}
dev_dbg(card->dev, "CODEC %s not registered\n",
dai_link->codec_name);

find_platform:
/* do we need a platform? */
if (rtd->platform)
goto out;
if (!rtd->codec) {
dev_dbg(card->dev, "CODEC %s not registered\n",
dai_link->codec_name);
return -EPROBE_DEFER;
}

/* if there's no platform we match on the empty platform */
platform_name = dai_link->platform_name;
if (!platform_name && !dai_link->platform_of_node)
platform_name = "snd-soc-dummy";

/* no, then find one from the set of registered platforms */
/* find one from the set of registered platforms */
list_for_each_entry(platform, &platform_list, list) {
if (dai_link->platform_of_node) {
if (platform->dev->of_node !=
Expand All @@ -870,20 +860,16 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
}

rtd->platform = platform;
goto out;
}

dev_dbg(card->dev, "platform %s not registered\n",
if (!rtd->platform) {
dev_dbg(card->dev, "platform %s not registered\n",
dai_link->platform_name);
return 0;

out:
/* mark rtd as complete if we found all 4 of our client devices */
if (rtd->codec && rtd->codec_dai && rtd->platform && rtd->cpu_dai) {
rtd->complete = 1;
card->num_rtd++;
return -EPROBE_DEFER;
}
return 1;

card->num_rtd++;

return 0;
}

static void soc_remove_codec(struct snd_soc_codec *codec)
Expand Down Expand Up @@ -1346,6 +1332,20 @@ static void soc_unregister_ac97_dai_link(struct snd_soc_codec *codec)
}
#endif

static int soc_check_aux_dev(struct snd_soc_card *card, int num)
{
struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num];
struct snd_soc_codec *codec;

/* find CODEC from registered CODECs*/
list_for_each_entry(codec, &codec_list, list) {
if (!strcmp(codec->name, aux_dev->codec_name))
return 0;
}

return -EPROBE_DEFER;
}

static int soc_probe_aux_dev(struct snd_soc_card *card, int num)
{
struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num];
Expand All @@ -1366,7 +1366,7 @@ static int soc_probe_aux_dev(struct snd_soc_card *card, int num)
}
/* codec not found */
dev_err(card->dev, "asoc: codec %s not found", aux_dev->codec_name);
goto out;
return -EPROBE_DEFER;

found:
ret = soc_probe_codec(card, codec);
Expand Down Expand Up @@ -1416,7 +1416,7 @@ static int snd_soc_init_codec_cache(struct snd_soc_codec *codec,
return 0;
}

static void snd_soc_instantiate_card(struct snd_soc_card *card)
static int snd_soc_instantiate_card(struct snd_soc_card *card)
{
struct snd_soc_codec *codec;
struct snd_soc_codec_conf *codec_conf;
Expand All @@ -1426,19 +1426,18 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)

mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT);

if (card->instantiated) {
mutex_unlock(&card->mutex);
return;
}

/* bind DAIs */
for (i = 0; i < card->num_links; i++)
soc_bind_dai_link(card, i);
for (i = 0; i < card->num_links; i++) {
ret = soc_bind_dai_link(card, i);
if (ret != 0)
goto base_error;
}

/* bind completed ? */
if (card->num_rtd != card->num_links) {
mutex_unlock(&card->mutex);
return;
/* check aux_devs too */
for (i = 0; i < card->num_aux_devs; i++) {
ret = soc_check_aux_dev(card, i);
if (ret != 0)
goto base_error;
}

/* initialize the register cache for each available codec */
Expand All @@ -1458,10 +1457,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
}
}
ret = snd_soc_init_codec_cache(codec, compress_type);
if (ret < 0) {
mutex_unlock(&card->mutex);
return;
}
if (ret < 0)
goto base_error;
}

/* card bind complete so register a sound card */
Expand All @@ -1470,8 +1467,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
if (ret < 0) {
pr_err("asoc: can't create sound card for card %s: %d\n",
card->name, ret);
mutex_unlock(&card->mutex);
return;
goto base_error;
}
card->snd_card->dev = card->dev;

Expand Down Expand Up @@ -1611,7 +1607,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
card->instantiated = 1;
snd_soc_dapm_sync(&card->dapm);
mutex_unlock(&card->mutex);
return;

return 0;

probe_aux_dev_err:
for (i = 0; i < card->num_aux_devs; i++)
Expand All @@ -1626,18 +1623,10 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)

snd_card_free(card->snd_card);

base_error:
mutex_unlock(&card->mutex);
}

/*
* Attempt to initialise any uninitialised cards. Must be called with
* client_mutex.
*/
static void snd_soc_instantiate_cards(void)
{
struct snd_soc_card *card;
list_for_each_entry(card, &card_list, list)
snd_soc_instantiate_card(card);
return ret;
}

/* probes a new socdev */
Expand Down Expand Up @@ -3072,7 +3061,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
*/
int snd_soc_register_card(struct snd_soc_card *card)
{
int i;
int i, ret;

if (!card->name || !card->dev)
return -EINVAL;
Expand Down Expand Up @@ -3136,14 +3125,11 @@ int snd_soc_register_card(struct snd_soc_card *card)
mutex_init(&card->mutex);
mutex_init(&card->dapm_mutex);

mutex_lock(&client_mutex);
list_add(&card->list, &card_list);
snd_soc_instantiate_cards();
mutex_unlock(&client_mutex);
ret = snd_soc_instantiate_card(card);
if (ret != 0)
soc_cleanup_card_debugfs(card);

dev_dbg(card->dev, "Registered card '%s'\n", card->name);

return 0;
return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_register_card);

Expand All @@ -3157,9 +3143,6 @@ int snd_soc_unregister_card(struct snd_soc_card *card)
{
if (card->instantiated)
soc_cleanup_card_resources(card);
mutex_lock(&client_mutex);
list_del(&card->list);
mutex_unlock(&client_mutex);
dev_dbg(card->dev, "Unregistered card '%s'\n", card->name);

return 0;
Expand Down Expand Up @@ -3256,7 +3239,6 @@ int snd_soc_register_dai(struct device *dev,

mutex_lock(&client_mutex);
list_add(&dai->list, &dai_list);
snd_soc_instantiate_cards();
mutex_unlock(&client_mutex);

pr_debug("Registered DAI '%s'\n", dai->name);
Expand Down Expand Up @@ -3338,9 +3320,6 @@ int snd_soc_register_dais(struct device *dev,
pr_debug("Registered DAI '%s'\n", dai->name);
}

mutex_lock(&client_mutex);
snd_soc_instantiate_cards();
mutex_unlock(&client_mutex);
return 0;

err:
Expand Down Expand Up @@ -3398,7 +3377,6 @@ int snd_soc_register_platform(struct device *dev,

mutex_lock(&client_mutex);
list_add(&platform->list, &platform_list);
snd_soc_instantiate_cards();
mutex_unlock(&client_mutex);

pr_debug("Registered platform '%s'\n", platform->name);
Expand Down Expand Up @@ -3557,7 +3535,6 @@ int snd_soc_register_codec(struct device *dev,

mutex_lock(&client_mutex);
list_add(&codec->list, &codec_list);
snd_soc_instantiate_cards();
mutex_unlock(&client_mutex);

pr_debug("Registered codec '%s'\n", codec->name);
Expand Down

0 comments on commit b19e6e7

Please sign in to comment.