[alsa-devel] [PATCH] ASoC: core - Allow some components to probe/remove later or earlier.

Liam Girdwood lrg at ti.com
Tue May 24 18:39:52 CEST 2011


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 at ti.com>
---
 include/sound/soc-dai.h |    4 +++
 include/sound/soc.h     |    8 +++++++
 sound/soc/soc-core.c    |   49 ++++++++++++++++++++++++++++++++++------------
 3 files changed, 48 insertions(+), 13 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 f9667f6..321182e 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)
@@ -1421,7 +1422,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)
@@ -1433,11 +1435,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)
@@ -1454,7 +1458,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;
 }
@@ -1596,7 +1602,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];
@@ -1605,7 +1611,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;
@@ -1617,7 +1623,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;
 
@@ -1636,14 +1643,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;
 
@@ -1662,7 +1671,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 (codec_dai->driver->probe) {
 			ret = codec_dai->driver->probe(codec_dai);
 			if (ret < 0) {
@@ -1677,6 +1686,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);
 
@@ -1895,8 +1908,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);
-- 
1.7.4.1



More information about the Alsa-devel mailing list