All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] ASoC: when initializing CPU DAI, don't duplicate any CODEC init
@ 2012-06-08 18:34 Stephen Warren
  2012-06-08 18:34 ` [PATCH 2/4] ASoC: when removing a CPU DAI, clean up its DAPM context Stephen Warren
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Stephen Warren @ 2012-06-08 18:34 UTC (permalink / raw)
  To: Mark Brown, Liam Girdwood; +Cc: alsa-devel, Stephen Warren

From: Stephen Warren <swarren@nvidia.com>

If the CPU-side of a DAI link is a CODEC rather than a standalone DAI,
the codec initialization will call try_module_get() and create the DAI
widgets. Ensure that this isn't duplicated when the CPU DAI itself is
probed, if the CPU DAI is part of a CODEC.

Note that this is not a complete fix on its own, since there's no
guarantee that the CODEC itself will be initialized - currently that only
happens if the CODEC is also used as the CODEC-side of a DAI link, and
that initialization may happen before or after the DAIs within the CODEC
are initialized. However, such a scenario doesn't necessarily currently
work, and I don't think this change alone makes it any worse. This is
fixed in a couple patches time.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
 sound/soc/soc-core.c |   14 +++++++++-----
 1 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 3d803f3..448d4a7 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -983,7 +983,9 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
 		}
 		cpu_dai->probed = 0;
 		list_del(&cpu_dai->card_list);
-		module_put(cpu_dai->dev->driver->owner);
+
+		if (!cpu_dai->codec)
+			module_put(cpu_dai->dev->driver->owner);
 	}
 }
 
@@ -1257,11 +1259,13 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
 	/* probe the cpu_dai */
 	if (!cpu_dai->probed &&
 			cpu_dai->driver->probe_order == order) {
-		cpu_dai->dapm.card = card;
-		if (!try_module_get(cpu_dai->dev->driver->owner))
-			return -ENODEV;
+		if (!cpu_dai->codec) {
+			cpu_dai->dapm.card = card;
+			if (!try_module_get(cpu_dai->dev->driver->owner))
+				return -ENODEV;
 
-		snd_soc_dapm_new_dai_widgets(&cpu_dai->dapm, cpu_dai);
+			snd_soc_dapm_new_dai_widgets(&cpu_dai->dapm, cpu_dai);
+		}
 
 		if (cpu_dai->driver->probe) {
 			ret = cpu_dai->driver->probe(cpu_dai);
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/4] ASoC: when removing a CPU DAI, clean up its DAPM context
  2012-06-08 18:34 [PATCH 1/4] ASoC: when initializing CPU DAI, don't duplicate any CODEC init Stephen Warren
@ 2012-06-08 18:34 ` Stephen Warren
  2012-06-08 18:34 ` [PATCH 3/4] ASoC: factor out soc_remove_platform() Stephen Warren
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Stephen Warren @ 2012-06-08 18:34 UTC (permalink / raw)
  To: Mark Brown, Liam Girdwood; +Cc: alsa-devel, Stephen Warren

From: Stephen Warren <swarren@nvidia.com>

When a standalone CPU DAI (one not part of a CODEC) is probed, widgets
are created for it. Add a call to snd_soc_dapm_free() in order to clean
these up when the CPU DAI is removed.

In order for snd_soc_dapm_free() to work, the CPU DAI's DAPM context's
list member must be initialized, since snd_soc_dapm_free() removes that
from the list it's part of. Add it to the card's list of DAPM contexts.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
 sound/soc/soc-core.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 448d4a7..621c5bd 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -984,8 +984,10 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
 		cpu_dai->probed = 0;
 		list_del(&cpu_dai->card_list);
 
-		if (!cpu_dai->codec)
+		if (!cpu_dai->codec) {
+			snd_soc_dapm_free(&cpu_dai->dapm);
 			module_put(cpu_dai->dev->driver->owner);
+		}
 	}
 }
 
@@ -1264,6 +1266,7 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
 			if (!try_module_get(cpu_dai->dev->driver->owner))
 				return -ENODEV;
 
+			list_add(&cpu_dai->dapm.list, &card->dapm_list);
 			snd_soc_dapm_new_dai_widgets(&cpu_dai->dapm, cpu_dai);
 		}
 
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/4] ASoC: factor out soc_remove_platform()
  2012-06-08 18:34 [PATCH 1/4] ASoC: when initializing CPU DAI, don't duplicate any CODEC init Stephen Warren
  2012-06-08 18:34 ` [PATCH 2/4] ASoC: when removing a CPU DAI, clean up its DAPM context Stephen Warren
@ 2012-06-08 18:34 ` Stephen Warren
  2012-06-08 18:34 ` [PATCH 4/4] ASoC: probe CODECs and platforms before DAIs and links Stephen Warren
  2012-06-13 12:18 ` [PATCH 1/4] ASoC: when initializing CPU DAI, don't duplicate any CODEC init Mark Brown
  3 siblings, 0 replies; 5+ messages in thread
From: Stephen Warren @ 2012-06-08 18:34 UTC (permalink / raw)
  To: Mark Brown, Liam Girdwood; +Cc: alsa-devel, Stephen Warren

From: Stephen Warren <swarren@nvidia.com>

This change simply factors out part of soc_remove_dai_link() into a
standalone function. This makes platform and CODEC removal much more
similar at the call-sites.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
 sound/soc/soc-core.c |   40 ++++++++++++++++++++++++----------------
 1 files changed, 24 insertions(+), 16 deletions(-)

diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 621c5bd..a539ade 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -898,6 +898,28 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
 	return 0;
 }
 
+static int soc_remove_platform(struct snd_soc_platform *platform)
+{
+	int ret;
+
+	if (platform->driver->remove) {
+		ret = platform->driver->remove(platform);
+		if (ret < 0)
+			pr_err("asoc: failed to remove %s: %d\n",
+				platform->name, ret);
+	}
+
+	/* Make sure all DAPM widgets are freed */
+	snd_soc_dapm_free(&platform->dapm);
+
+	soc_cleanup_platform_debugfs(platform);
+	platform->probed = 0;
+	list_del(&platform->card_list);
+	module_put(platform->dev->driver->owner);
+
+	return 0;
+}
+
 static void soc_remove_codec(struct snd_soc_codec *codec)
 {
 	int err;
@@ -950,22 +972,8 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
 
 	/* remove the platform */
 	if (platform && platform->probed &&
-			platform->driver->remove_order == order) {
-		if (platform->driver->remove) {
-			err = platform->driver->remove(platform);
-			if (err < 0)
-				pr_err("asoc: failed to remove %s: %d\n",
-							platform->name, err);
-		}
-
-		/* Make sure all DAPM widgets are freed */
-		snd_soc_dapm_free(&platform->dapm);
-
-		soc_cleanup_platform_debugfs(platform);
-		platform->probed = 0;
-		list_del(&platform->card_list);
-		module_put(platform->dev->driver->owner);
-	}
+			platform->driver->remove_order == order)
+		soc_remove_platform(platform);
 
 	/* remove the CODEC */
 	if (codec && codec->probed &&
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 4/4] ASoC: probe CODECs and platforms before DAIs and links
  2012-06-08 18:34 [PATCH 1/4] ASoC: when initializing CPU DAI, don't duplicate any CODEC init Stephen Warren
  2012-06-08 18:34 ` [PATCH 2/4] ASoC: when removing a CPU DAI, clean up its DAPM context Stephen Warren
  2012-06-08 18:34 ` [PATCH 3/4] ASoC: factor out soc_remove_platform() Stephen Warren
@ 2012-06-08 18:34 ` Stephen Warren
  2012-06-13 12:18 ` [PATCH 1/4] ASoC: when initializing CPU DAI, don't duplicate any CODEC init Mark Brown
  3 siblings, 0 replies; 5+ messages in thread
From: Stephen Warren @ 2012-06-08 18:34 UTC (permalink / raw)
  To: Mark Brown, Liam Girdwood; +Cc: alsa-devel, Stephen Warren

From: Stephen Warren <swarren@nvidia.com>

soc_probe_dai_link() currently inter-mixes the probing of CODECs,
platforms, and DAIs. This can lead to problems such as a CODEC's DAI
being probed before the CODEC, if that DAI is used as the CPU-side of
a DAI link without any other of the CODEC's DAIs having been used as
the CODEC-side of any DAI link that was probed earlier.

To solve this, split soc_probe_dai_link() into soc_probe_link_components()
and soc_probe_link_dais(). The former is used to probe all CODECs and
platforms used by a card first, and then the latter is used to probe all
the DAIs and links later.

A similar change is made to soc_remove_dai_links().

Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
 sound/soc/soc-core.c |  129 ++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 95 insertions(+), 34 deletions(-)

diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index a539ade..fe16135 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -941,11 +941,9 @@ 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, int order)
+static void soc_remove_link_dais(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;
-	struct snd_soc_platform *platform = rtd->platform;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai;
 	int err;
 
@@ -970,16 +968,6 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
 		list_del(&codec_dai->card_list);
 	}
 
-	/* remove the platform */
-	if (platform && platform->probed &&
-			platform->driver->remove_order == order)
-		soc_remove_platform(platform);
-
-	/* remove the CODEC */
-	if (codec && codec->probed &&
-			codec->driver->remove_order == order)
-		soc_remove_codec(codec);
-
 	/* remove the cpu_dai */
 	if (cpu_dai && cpu_dai->probed &&
 			cpu_dai->driver->remove_order == order) {
@@ -999,6 +987,38 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
 	}
 }
 
+static void soc_remove_link_components(struct snd_soc_card *card, int num,
+				       int order)
+{
+	struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_platform *platform = rtd->platform;
+	struct snd_soc_codec *codec;
+
+	/* remove the platform */
+	if (platform && platform->probed &&
+	    platform->driver->remove_order == order) {
+		soc_remove_platform(platform);
+	}
+
+	/* remove the CODEC-side CODEC */
+	if (codec_dai) {
+		codec = codec_dai->codec;
+		if (codec && codec->probed &&
+		    codec->driver->remove_order == order)
+			soc_remove_codec(codec);
+	}
+
+	/* remove any CPU-side CODEC */
+	if (cpu_dai) {
+		codec = cpu_dai->codec;
+		if (codec && codec->probed &&
+		    codec->driver->remove_order == order)
+			soc_remove_codec(codec);
+	}
+}
+
 static void soc_remove_dai_links(struct snd_soc_card *card)
 {
 	int dai, order;
@@ -1006,8 +1026,15 @@ static void soc_remove_dai_links(struct snd_soc_card *card)
 	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);
+			soc_remove_link_dais(card, 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_link_components(card, dai, order);
 	}
+
 	card->num_rtd = 0;
 }
 
@@ -1244,7 +1271,44 @@ out:
 	return 0;
 }
 
-static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
+static int soc_probe_link_components(struct snd_soc_card *card, int num,
+				     int order)
+{
+	struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_platform *platform = rtd->platform;
+	int ret;
+
+	/* probe the CPU-side component, if it is a CODEC */
+	if (cpu_dai->codec &&
+	    !cpu_dai->codec->probed &&
+	    cpu_dai->codec->driver->probe_order == order) {
+		ret = soc_probe_codec(card, cpu_dai->codec);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* probe the CODEC-side component */
+	if (!codec_dai->codec->probed &&
+	    codec_dai->codec->driver->probe_order == order) {
+		ret = soc_probe_codec(card, codec_dai->codec);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* probe the platform */
+	if (!platform->probed &&
+	    platform->driver->probe_order == order) {
+		ret = soc_probe_platform(card, platform);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int soc_probe_link_dais(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];
@@ -1292,22 +1356,6 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
 		list_add(&cpu_dai->card_list, &card->dai_dev_list);
 	}
 
-	/* probe the CODEC */
-	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 &&
-			platform->driver->probe_order == order) {
-		ret = soc_probe_platform(card, platform);
-		if (ret < 0)
-			return ret;
-	}
-
 	/* probe the CODEC DAI */
 	if (!codec_dai->probed && codec_dai->driver->probe_order == order) {
 		if (codec_dai->driver->probe) {
@@ -1582,14 +1630,27 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
 			goto card_probe_error;
 	}
 
-	/* early DAI link probe */
+	/* probe all components used by DAI links on this card */
 	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);
+			ret = soc_probe_link_components(card, i, order);
 			if (ret < 0) {
 				pr_err("asoc: failed to instantiate card %s: %d\n",
-			       card->name, ret);
+				       card->name, ret);
+				goto probe_dai_err;
+			}
+		}
+	}
+
+	/* probe all DAI links on this card */
+	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_link_dais(card, i, order);
+			if (ret < 0) {
+				pr_err("asoc: failed to instantiate card %s: %d\n",
+				       card->name, ret);
 				goto probe_dai_err;
 			}
 		}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/4] ASoC: when initializing CPU DAI, don't duplicate any CODEC init
  2012-06-08 18:34 [PATCH 1/4] ASoC: when initializing CPU DAI, don't duplicate any CODEC init Stephen Warren
                   ` (2 preceding siblings ...)
  2012-06-08 18:34 ` [PATCH 4/4] ASoC: probe CODECs and platforms before DAIs and links Stephen Warren
@ 2012-06-13 12:18 ` Mark Brown
  3 siblings, 0 replies; 5+ messages in thread
From: Mark Brown @ 2012-06-13 12:18 UTC (permalink / raw)
  To: Stephen Warren; +Cc: alsa-devel, Stephen Warren, Liam Girdwood


[-- Attachment #1.1: Type: text/plain, Size: 405 bytes --]

On Fri, Jun 08, 2012 at 12:34:20PM -0600, Stephen Warren wrote:
> From: Stephen Warren <swarren@nvidia.com>
> 
> If the CPU-side of a DAI link is a CODEC rather than a standalone DAI,
> the codec initialization will call try_module_get() and create the DAI
> widgets. Ensure that this isn't duplicated when the CPU DAI itself is
> probed, if the CPU DAI is part of a CODEC.

Applied all, thanks.

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2012-06-13 12:18 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-08 18:34 [PATCH 1/4] ASoC: when initializing CPU DAI, don't duplicate any CODEC init Stephen Warren
2012-06-08 18:34 ` [PATCH 2/4] ASoC: when removing a CPU DAI, clean up its DAPM context Stephen Warren
2012-06-08 18:34 ` [PATCH 3/4] ASoC: factor out soc_remove_platform() Stephen Warren
2012-06-08 18:34 ` [PATCH 4/4] ASoC: probe CODECs and platforms before DAIs and links Stephen Warren
2012-06-13 12:18 ` [PATCH 1/4] ASoC: when initializing CPU DAI, don't duplicate any CODEC init Mark Brown

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.