Skip to content

Commit

Permalink
ASoC: core - Allow components to probe/remove in sequence.
Browse files Browse the repository at this point in the history
Some ASoC components depend on other ASoC components to provide clocks and
power resources in order to probe() and vice versa for remove().

Allow components to be ordered so that components can be probed() and removed()
in sequences that conform to their dependencies.

Signed-off-by: Liam Girdwood <lrg@ti.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
  • Loading branch information
Liam Girdwood authored and Mark Brown committed Jun 7, 2011
1 parent 552d1ef commit 0168bf0
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 21 deletions.
4 changes: 4 additions & 0 deletions include/sound/soc-dai.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@ struct snd_soc_dai_driver {
struct snd_soc_pcm_stream capture;
struct snd_soc_pcm_stream playback;
unsigned int symmetric_rates:1;

/* probe ordering - for components with runtime dependencies */
int probe_order;
int remove_order;
};

/*
Expand Down
18 changes: 18 additions & 0 deletions include/sound/soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,16 @@
#define SOC_VALUE_ENUM_SINGLE_DECL(name, xreg, xshift, xmask, xtexts, xvalues) \
SOC_VALUE_ENUM_DOUBLE_DECL(name, xreg, xshift, xshift, xmask, xtexts, xvalues)

/*
* Component probe and remove ordering levels for components with runtime
* dependencies.
*/
#define SND_SOC_COMP_ORDER_FIRST -2
#define SND_SOC_COMP_ORDER_EARLY -1
#define SND_SOC_COMP_ORDER_NORMAL 0
#define SND_SOC_COMP_ORDER_LATE 1
#define SND_SOC_COMP_ORDER_LAST 2

/*
* Bias levels
*
Expand Down Expand Up @@ -613,6 +623,10 @@ struct snd_soc_codec_driver {

void (*seq_notifier)(struct snd_soc_dapm_context *,
enum snd_soc_dapm_type, int);

/* probe ordering - for components with runtime dependencies */
int probe_order;
int remove_order;
};

/* SoC platform interface */
Expand All @@ -636,6 +650,10 @@ struct snd_soc_platform_driver {

/* platform stream ops */
struct snd_pcm_ops *ops;

/* probe ordering - for components with runtime dependencies */
int probe_order;
int remove_order;
};

struct snd_soc_platform {
Expand Down
60 changes: 39 additions & 21 deletions sound/soc/soc-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1394,7 +1394,7 @@ static void soc_remove_codec(struct snd_soc_codec *codec)
module_put(codec->dev->driver->owner);
}

static void soc_remove_dai_link(struct snd_soc_card *card, int num)
static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
{
struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
struct snd_soc_codec *codec = rtd->codec;
Expand All @@ -1411,7 +1411,8 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num)
}

/* remove the CODEC DAI */
if (codec_dai && codec_dai->probed) {
if (codec_dai && codec_dai->probed &&
codec_dai->driver->remove_order == order) {
if (codec_dai->driver->remove) {
err = codec_dai->driver->remove(codec_dai);
if (err < 0)
Expand All @@ -1422,7 +1423,8 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num)
}

/* remove the platform */
if (platform && platform->probed) {
if (platform && platform->probed &&
platform->driver->remove_order == order) {
if (platform->driver->remove) {
err = platform->driver->remove(platform);
if (err < 0)
Expand All @@ -1434,11 +1436,13 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num)
}

/* remove the CODEC */
if (codec && codec->probed)
if (codec && codec->probed &&
codec->driver->remove_order == order)
soc_remove_codec(codec);

/* remove the cpu_dai */
if (cpu_dai && cpu_dai->probed) {
if (cpu_dai && cpu_dai->probed &&
cpu_dai->driver->remove_order == order) {
if (cpu_dai->driver->remove) {
err = cpu_dai->driver->remove(cpu_dai);
if (err < 0)
Expand All @@ -1452,11 +1456,13 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num)

static void soc_remove_dai_links(struct snd_soc_card *card)
{
int i;

for (i = 0; i < card->num_rtd; i++)
soc_remove_dai_link(card, i);
int dai, order;

for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
order++) {
for (dai = 0; dai < card->num_rtd; dai++)
soc_remove_dai_link(card, dai, order);
}
card->num_rtd = 0;
}

Expand Down Expand Up @@ -1597,7 +1603,7 @@ static int soc_post_component_init(struct snd_soc_card *card,
return 0;
}

static int soc_probe_dai_link(struct snd_soc_card *card, int num)
static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
{
struct snd_soc_dai_link *dai_link = &card->dai_link[num];
struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
Expand All @@ -1606,7 +1612,8 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num)
struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai;
int ret;

dev_dbg(card->dev, "probe %s dai link %d\n", card->name, num);
dev_dbg(card->dev, "probe %s dai link %d late %d\n",
card->name, num, order);

/* config components */
codec_dai->codec = codec;
Expand All @@ -1618,7 +1625,8 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num)
rtd->pmdown_time = pmdown_time;

/* probe the cpu_dai */
if (!cpu_dai->probed) {
if (!cpu_dai->probed &&
cpu_dai->driver->probe_order == order) {
if (!try_module_get(cpu_dai->dev->driver->owner))
return -ENODEV;

Expand All @@ -1637,14 +1645,16 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num)
}

/* probe the CODEC */
if (!codec->probed) {
if (!codec->probed &&
codec->driver->probe_order == order) {
ret = soc_probe_codec(card, codec);
if (ret < 0)
return ret;
}

/* probe the platform */
if (!platform->probed) {
if (!platform->probed &&
platform->driver->probe_order == order) {
if (!try_module_get(platform->dev->driver->owner))
return -ENODEV;

Expand All @@ -1663,7 +1673,7 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num)
}

/* probe the CODEC DAI */
if (!codec_dai->probed) {
if (!codec_dai->probed && codec_dai->driver->probe_order == order) {
if (codec_dai->driver->probe) {
ret = codec_dai->driver->probe(codec_dai);
if (ret < 0) {
Expand All @@ -1678,6 +1688,10 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num)
list_add(&codec_dai->card_list, &card->dai_dev_list);
}

/* complete DAI probe during last probe */
if (order != SND_SOC_COMP_ORDER_LAST)
return 0;

/* DAPM dai link stream work */
INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);

Expand Down Expand Up @@ -1818,7 +1832,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
struct snd_soc_codec *codec;
struct snd_soc_codec_conf *codec_conf;
enum snd_soc_compress_type compress_type;
int ret, i;
int ret, i, order;

mutex_lock(&card->mutex);

Expand Down Expand Up @@ -1896,12 +1910,16 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
goto card_probe_error;
}

for (i = 0; i < card->num_links; i++) {
ret = soc_probe_dai_link(card, i);
if (ret < 0) {
pr_err("asoc: failed to instantiate card %s: %d\n",
/* early DAI link probe */
for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
order++) {
for (i = 0; i < card->num_links; i++) {
ret = soc_probe_dai_link(card, i, order);
if (ret < 0) {
pr_err("asoc: failed to instantiate card %s: %d\n",
card->name, ret);
goto probe_dai_err;
goto probe_dai_err;
}
}
}

Expand Down

0 comments on commit 0168bf0

Please sign in to comment.