| From 94df9e9b6182759ffe6a44fb699a5bd97bd5ca53 Mon Sep 17 00:00:00 2001 |
| From: Liam Girdwood <lrg@ti.com> |
| Date: Tue, 7 Jun 2011 16:08:05 +0100 |
| Subject: ASoC: core - Allow components to probe/remove in sequence. |
| |
| 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> |
| (cherry picked from commit 0168bf0d130de83cd3532b834237c6228a6158dd) |
| |
| Signed-off-by: Simon Horman <horms@verge.net.au> |
| --- |
| include/sound/soc-dai.h | 4 ++++ |
| include/sound/soc.h | 18 +++++++++++++++ |
| sound/soc/soc-core.c | 60 ++++++++++++++++++++++++++++++++----------------- |
| 3 files changed, 61 insertions(+), 21 deletions(-) |
| |
| diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h |
| index 1bafe95..5ad5f3a 100644 |
| --- a/include/sound/soc-dai.h |
| +++ b/include/sound/soc-dai.h |
| @@ -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; |
| }; |
| |
| /* |
| diff --git a/include/sound/soc.h b/include/sound/soc.h |
| index e9db08c..447232c 100644 |
| --- a/include/sound/soc.h |
| +++ b/include/sound/soc.h |
| @@ -203,6 +203,16 @@ |
| 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 |
| * |
| * @ON: Bias is fully on for audio playback and capture operations. |
| @@ -612,6 +622,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 */ |
| @@ -635,6 +649,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 { |
| diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c |
| index f2a920a..841b1c9 100644 |
| --- a/sound/soc/soc-core.c |
| +++ b/sound/soc/soc-core.c |
| @@ -1396,7 +1396,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; |
| @@ -1413,7 +1413,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) |
| @@ -1424,7 +1425,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) |
| @@ -1436,11 +1438,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) |
| @@ -1454,11 +1458,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; |
| } |
| |
| @@ -1599,7 +1605,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]; |
| @@ -1608,7 +1614,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; |
| @@ -1620,7 +1627,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; |
| |
| @@ -1639,14 +1647,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; |
| |
| @@ -1665,7 +1675,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) { |
| @@ -1680,6 +1690,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); |
| |
| @@ -1820,7 +1834,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); |
| |
| @@ -1898,12 +1912,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; |
| + } |
| } |
| } |
| |
| -- |
| 1.7.10.2.565.gbd578b5 |
| |