diff options
author | Liam Girdwood <lrg@ti.com> | 2011-06-02 20:41:28 -0500 |
---|---|---|
committer | Colin Cross <ccross@android.com> | 2011-06-14 09:06:11 -0700 |
commit | 6f3f95ae6a0919dc4d119398f78a905799bab6fc (patch) | |
tree | 188de9aa67252c24cd25d449c873e8decb561ef7 | |
parent | 75b3c339a84fec86ce6807cfd69db619cf5d96c6 (diff) | |
download | kernel_samsung_tuna-6f3f95ae6a0919dc4d119398f78a905799bab6fc.zip kernel_samsung_tuna-6f3f95ae6a0919dc4d119398f78a905799bab6fc.tar.gz kernel_samsung_tuna-6f3f95ae6a0919dc4d119398f78a905799bab6fc.tar.bz2 |
ASoC: core - Allow some components to probe/remove later or earlier
Some ASoC components depend on other ASoC components to provide clocks and
power resources in order to probe().
Provide a method to allow some components to be probed() later and be also
removed() earlier.
Signed-off-by: Liam Girdwood <lrg@ti.com>
-rw-r--r-- | include/sound/soc-dai.h | 4 | ||||
-rw-r--r-- | include/sound/soc.h | 8 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 50 |
3 files changed, 48 insertions, 14 deletions
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 1bafe95..ada1f24 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 */ + bool late_probe; + bool early_remove; }; /* diff --git a/include/sound/soc.h b/include/sound/soc.h index f1de3e0..a2139d4 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -613,6 +613,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 */ + bool late_probe; + bool early_remove; }; /* SoC platform interface */ @@ -637,6 +641,10 @@ struct snd_soc_platform_driver { /* platform stream ops */ struct snd_pcm_ops *ops; + + /* probe ordering - for components with runtime dependencies */ + bool late_probe; + bool early_remove; }; struct snd_soc_platform { diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index d2acd06..5406786 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1393,7 +1393,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 early) { struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; struct snd_soc_codec *codec = rtd->codec; @@ -1410,7 +1410,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->early_remove == early) { if (codec_dai->driver->remove) { err = codec_dai->driver->remove(codec_dai); if (err < 0) @@ -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->early_remove == early) { if (platform->driver->remove) { err = platform->driver->remove(platform); if (err < 0) @@ -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->early_remove == early) soc_remove_codec(codec); /* remove the cpu_dai */ - if (cpu_dai && cpu_dai->probed) { + if (cpu_dai && cpu_dai->probed && + cpu_dai->driver->early_remove == early) { if (cpu_dai->driver->remove) { err = cpu_dai->driver->remove(cpu_dai); if (err < 0) @@ -1455,7 +1459,9 @@ 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); + soc_remove_dai_link(card, i, 1); /* early remove */ + for (i = 0; i < card->num_rtd; i++) + soc_remove_dai_link(card, i, 0); /* late remove */ card->num_rtd = 0; } @@ -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 late) { struct snd_soc_dai_link *dai_link = &card->dai_link[num]; struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; @@ -1606,7 +1612,7 @@ 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, late); /* config components */ codec_dai->codec = codec; @@ -1618,8 +1624,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->late_probe == late) { if (!try_module_get(cpu_dai->dev->driver->owner)) return -ENODEV; @@ -1638,14 +1644,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->late_probe == late) { ret = soc_probe_codec(card, codec); if (ret < 0) return ret; } /* probe the platform */ - if (!platform->probed) { + if (!platform->probed && + platform->driver->late_probe == late) { if (!try_module_get(platform->dev->driver->owner)) return -ENODEV; @@ -1664,7 +1672,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->late_probe == late) { if (!try_module_get(codec_dai->dev->driver->owner)) return -ENODEV; if (codec_dai->driver->probe) { @@ -1682,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 late probe */ + if (!late) + return 0; + /* DAPM dai link stream work */ INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); @@ -1900,8 +1912,18 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) goto card_probe_error; } + /* early DAI link probe */ + for (i = 0; i < card->num_links; i++) { + ret = soc_probe_dai_link(card, i, 0); + if (ret < 0) { + pr_err("asoc: failed to instantiate card %s: %d\n", + card->name, ret); + goto probe_dai_err; + } + } + /* late DAI link probe */ for (i = 0; i < card->num_links; i++) { - ret = soc_probe_dai_link(card, i); + ret = soc_probe_dai_link(card, i, 1); if (ret < 0) { pr_err("asoc: failed to instantiate card %s: %d\n", card->name, ret); |