aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiam Girdwood <lrg@ti.com>2011-06-02 20:41:28 -0500
committerColin Cross <ccross@android.com>2011-06-14 09:06:11 -0700
commit6f3f95ae6a0919dc4d119398f78a905799bab6fc (patch)
tree188de9aa67252c24cd25d449c873e8decb561ef7
parent75b3c339a84fec86ce6807cfd69db619cf5d96c6 (diff)
downloadkernel_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.h4
-rw-r--r--include/sound/soc.h8
-rw-r--r--sound/soc/soc-core.c50
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);