All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] ASoC: Implement DAI links in a list & some code refactoring
@ 2015-11-23 15:59 mengdong.lin
  2015-11-23 16:01 ` [PATCH 1/3] ASoC: Define soc_init_dai_link() to wrap link intialization mengdong.lin
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: mengdong.lin @ 2015-11-23 15:59 UTC (permalink / raw
  To: alsa-devel, broonie
  Cc: Mengdong Lin, vinod.koul, mengdong.lin, liam.r.girdwood, jeeja.kp,
	subhransu.s.prusty

From: Mengdong Lin <mengdong.lin@linux.intel.com>

This is still a preparation for topology to create PCM at dynamically.

First two patches are code refactoring.

The 3rd patch implements the DAI links into a list, so that the number of
links can add/shrink by topology at runtime. 
The use scenario may be like this:
- When instantiating the soc card, probing a component with topology can
  bring new DAI links. The ASoC will probe the new links (in later patches).
- When unregistering the soc card, removing this component will also remove
  DAI  links created by it. 

For backward compatiblity, the machine driver can still define a static link
array. And the ASoC core will add these links into the list when instantiating
the soc card.

Mengdong Lin (3):
  ASoC: Define soc_init_dai_link() to wrap link intialization.
  ASoC: Change 2nd argument of soc_bind_dai_link() to DAI link pointer
  ASoC: Implement DAI links in a list & define API to add/remove a link

 include/sound/soc.h  |  15 ++-
 sound/soc/soc-core.c | 251 +++++++++++++++++++++++++++++++++------------------
 2 files changed, 177 insertions(+), 89 deletions(-)

-- 
2.5.0

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

* [PATCH 1/3] ASoC: Define soc_init_dai_link() to wrap link intialization.
  2015-11-23 15:59 [PATCH 0/3] ASoC: Implement DAI links in a list & some code refactoring mengdong.lin
@ 2015-11-23 16:01 ` mengdong.lin
  2015-11-23 16:03 ` [PATCH 2/3] ASoC: Change 2nd argument of soc_bind_dai_link() to DAI link pointer mengdong.lin
  2015-11-23 16:04 ` [PATCH 3/3] ASoC: Implement DAI links in a list & define API to add/remove a link mengdong.lin
  2 siblings, 0 replies; 5+ messages in thread
From: mengdong.lin @ 2015-11-23 16:01 UTC (permalink / raw
  To: alsa-devel, broonie
  Cc: Mengdong Lin, vinod.koul, mengdong.lin, liam.r.girdwood, jeeja.kp,
	subhransu.s.prusty

From: Mengdong Lin <mengdong.lin@linux.intel.com>

Define soc_init_dai_link() to wrap link initialization, to reuse it later
by snd_soc_instantiate_card() when adding new DAI links from topology in
component probing phase.

Move static func snd_soc_init_multicodec(), so that it can be reused by
soc_init_dai_link(). This saves adding a function declaration for
snd_soc_init_multicodec().

Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>

diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 2c95de7..2ecd094 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1134,6 +1134,100 @@ static void soc_remove_dai_links(struct snd_soc_card *card)
 	}
 }
 
+static int snd_soc_init_multicodec(struct snd_soc_card *card,
+				   struct snd_soc_dai_link *dai_link)
+{
+	/* Legacy codec/codec_dai link is a single entry in multicodec */
+	if (dai_link->codec_name || dai_link->codec_of_node ||
+	    dai_link->codec_dai_name) {
+		dai_link->num_codecs = 1;
+
+		dai_link->codecs = devm_kzalloc(card->dev,
+				sizeof(struct snd_soc_dai_link_component),
+				GFP_KERNEL);
+		if (!dai_link->codecs)
+			return -ENOMEM;
+
+		dai_link->codecs[0].name = dai_link->codec_name;
+		dai_link->codecs[0].of_node = dai_link->codec_of_node;
+		dai_link->codecs[0].dai_name = dai_link->codec_dai_name;
+	}
+
+	if (!dai_link->codecs) {
+		dev_err(card->dev, "ASoC: DAI link has no CODECs\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int soc_init_dai_link(struct snd_soc_card *card,
+				   struct snd_soc_dai_link *link)
+{
+	int i, ret;
+
+	ret = snd_soc_init_multicodec(card, link);
+	if (ret) {
+		dev_err(card->dev, "ASoC: failed to init multicodec\n");
+		return ret;
+	}
+
+	for (i = 0; i < link->num_codecs; i++) {
+		/*
+		 * Codec must be specified by 1 of name or OF node,
+		 * not both or neither.
+		 */
+		if (!!link->codecs[i].name ==
+		    !!link->codecs[i].of_node) {
+			dev_err(card->dev, "ASoC: Neither/both codec name/of_node are set for %s\n",
+				link->name);
+			return -EINVAL;
+		}
+		/* Codec DAI name must be specified */
+		if (!link->codecs[i].dai_name) {
+			dev_err(card->dev, "ASoC: codec_dai_name not set for %s\n",
+				link->name);
+			return -EINVAL;
+		}
+	}
+
+	/*
+	 * Platform may be specified by either name or OF node, but
+	 * can be left unspecified, and a dummy platform will be used.
+	 */
+	if (link->platform_name && link->platform_of_node) {
+		dev_err(card->dev,
+			"ASoC: Both platform name/of_node are set for %s\n",
+			link->name);
+		return -EINVAL;
+	}
+
+	/*
+	 * CPU device may be specified by either name or OF node, but
+	 * can be left unspecified, and will be matched based on DAI
+	 * name alone..
+	 */
+	if (link->cpu_name && link->cpu_of_node) {
+		dev_err(card->dev,
+			"ASoC: Neither/both cpu name/of_node are set for %s\n",
+			link->name);
+		return -EINVAL;
+	}
+	/*
+	 * At least one of CPU DAI name or CPU device name/node must be
+	 * specified
+	 */
+	if (!link->cpu_dai_name &&
+	    !(link->cpu_name || link->cpu_of_node)) {
+		dev_err(card->dev,
+			"ASoC: Neither cpu_dai_name nor cpu_name/of_node are set for %s\n",
+			link->name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static void soc_set_name_prefix(struct snd_soc_card *card,
 				struct snd_soc_component *component)
 {
@@ -2356,33 +2450,6 @@ int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute,
 }
 EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
 
-static int snd_soc_init_multicodec(struct snd_soc_card *card,
-				   struct snd_soc_dai_link *dai_link)
-{
-	/* Legacy codec/codec_dai link is a single entry in multicodec */
-	if (dai_link->codec_name || dai_link->codec_of_node ||
-	    dai_link->codec_dai_name) {
-		dai_link->num_codecs = 1;
-
-		dai_link->codecs = devm_kzalloc(card->dev,
-				sizeof(struct snd_soc_dai_link_component),
-				GFP_KERNEL);
-		if (!dai_link->codecs)
-			return -ENOMEM;
-
-		dai_link->codecs[0].name = dai_link->codec_name;
-		dai_link->codecs[0].of_node = dai_link->codec_of_node;
-		dai_link->codecs[0].dai_name = dai_link->codec_dai_name;
-	}
-
-	if (!dai_link->codecs) {
-		dev_err(card->dev, "ASoC: DAI link has no CODECs\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 /**
  * snd_soc_register_card - Register a card with the ASoC core
  *
@@ -2391,7 +2458,7 @@ static int snd_soc_init_multicodec(struct snd_soc_card *card,
  */
 int snd_soc_register_card(struct snd_soc_card *card)
 {
-	int i, j, ret;
+	int i, ret;
 	struct snd_soc_pcm_runtime *rtd;
 
 	if (!card->name || !card->dev)
@@ -2400,63 +2467,11 @@ int snd_soc_register_card(struct snd_soc_card *card)
 	for (i = 0; i < card->num_links; i++) {
 		struct snd_soc_dai_link *link = &card->dai_link[i];
 
-		ret = snd_soc_init_multicodec(card, link);
+		ret = soc_init_dai_link(card, link);
 		if (ret) {
-			dev_err(card->dev, "ASoC: failed to init multicodec\n");
-			return ret;
-		}
-
-		for (j = 0; j < link->num_codecs; j++) {
-			/*
-			 * Codec must be specified by 1 of name or OF node,
-			 * not both or neither.
-			 */
-			if (!!link->codecs[j].name ==
-			    !!link->codecs[j].of_node) {
-				dev_err(card->dev, "ASoC: Neither/both codec name/of_node are set for %s\n",
-					link->name);
-				return -EINVAL;
-			}
-			/* Codec DAI name must be specified */
-			if (!link->codecs[j].dai_name) {
-				dev_err(card->dev, "ASoC: codec_dai_name not set for %s\n",
-					link->name);
-				return -EINVAL;
-			}
-		}
-
-		/*
-		 * Platform may be specified by either name or OF node, but
-		 * can be left unspecified, and a dummy platform will be used.
-		 */
-		if (link->platform_name && link->platform_of_node) {
-			dev_err(card->dev,
-				"ASoC: Both platform name/of_node are set for %s\n",
+			dev_err(card->dev, "ASoC: failed to init link %s\n",
 				link->name);
-			return -EINVAL;
-		}
-
-		/*
-		 * CPU device may be specified by either name or OF node, but
-		 * can be left unspecified, and will be matched based on DAI
-		 * name alone..
-		 */
-		if (link->cpu_name && link->cpu_of_node) {
-			dev_err(card->dev,
-				"ASoC: Neither/both cpu name/of_node are set for %s\n",
-				link->name);
-			return -EINVAL;
-		}
-		/*
-		 * At least one of CPU DAI name or CPU device name/node must be
-		 * specified
-		 */
-		if (!link->cpu_dai_name &&
-		    !(link->cpu_name || link->cpu_of_node)) {
-			dev_err(card->dev,
-				"ASoC: Neither cpu_dai_name nor cpu_name/of_node are set for %s\n",
-				link->name);
-			return -EINVAL;
+			return ret;
 		}
 	}
 
-- 
2.5.0

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

* [PATCH 2/3] ASoC: Change 2nd argument of soc_bind_dai_link() to DAI link pointer
  2015-11-23 15:59 [PATCH 0/3] ASoC: Implement DAI links in a list & some code refactoring mengdong.lin
  2015-11-23 16:01 ` [PATCH 1/3] ASoC: Define soc_init_dai_link() to wrap link intialization mengdong.lin
@ 2015-11-23 16:03 ` mengdong.lin
  2015-11-23 16:04 ` [PATCH 3/3] ASoC: Implement DAI links in a list & define API to add/remove a link mengdong.lin
  2 siblings, 0 replies; 5+ messages in thread
From: mengdong.lin @ 2015-11-23 16:03 UTC (permalink / raw
  To: alsa-devel, broonie
  Cc: Mengdong Lin, vinod.koul, mengdong.lin, liam.r.girdwood, jeeja.kp,
	subhransu.s.prusty

From: Mengdong Lin <mengdong.lin@linux.intel.com>

Just code refactoring, to reuse it if new DAI Links are added later
based on topology in component probing phase.

Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>

diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 2ecd094..878a9fe 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -960,9 +960,9 @@ static struct snd_soc_dai *snd_soc_find_dai(
 	return NULL;
 }
 
-static int soc_bind_dai_link(struct snd_soc_card *card, int num)
+static int soc_bind_dai_link(struct snd_soc_card *card,
+	struct snd_soc_dai_link *dai_link)
 {
-	struct snd_soc_dai_link *dai_link = &card->dai_link[num];
 	struct snd_soc_pcm_runtime *rtd;
 	struct snd_soc_dai_link_component *codecs = dai_link->codecs;
 	struct snd_soc_dai_link_component cpu_dai_component;
@@ -971,7 +971,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
 	const char *platform_name;
 	int i;
 
-	dev_dbg(card->dev, "ASoC: binding %s at idx %d\n", dai_link->name, num);
+	dev_dbg(card->dev, "ASoC: binding %s\n", dai_link->name);
 
 	rtd = soc_new_pcm_runtime(card, dai_link);
 	if (!rtd)
@@ -1710,7 +1710,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
 
 	/* bind DAIs */
 	for (i = 0; i < card->num_links; i++) {
-		ret = soc_bind_dai_link(card, i);
+		ret = soc_bind_dai_link(card, &card->dai_link[i]);
 		if (ret != 0)
 			goto base_error;
 	}
-- 
2.5.0

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

* [PATCH 3/3] ASoC: Implement DAI links in a list & define API to add/remove a link
  2015-11-23 15:59 [PATCH 0/3] ASoC: Implement DAI links in a list & some code refactoring mengdong.lin
  2015-11-23 16:01 ` [PATCH 1/3] ASoC: Define soc_init_dai_link() to wrap link intialization mengdong.lin
  2015-11-23 16:03 ` [PATCH 2/3] ASoC: Change 2nd argument of soc_bind_dai_link() to DAI link pointer mengdong.lin
@ 2015-11-23 16:04 ` mengdong.lin
  2015-12-01 15:58   ` Mark Brown
  2 siblings, 1 reply; 5+ messages in thread
From: mengdong.lin @ 2015-11-23 16:04 UTC (permalink / raw
  To: alsa-devel, broonie
  Cc: Mengdong Lin, vinod.koul, mengdong.lin, liam.r.girdwood, jeeja.kp,
	subhransu.s.prusty

From: Mengdong Lin <mengdong.lin@linux.intel.com>

Implement a dai link list for the soc card.

Add APIs to add/remove a DAI links dynamically, e.g. by topology.

And a dobj is embedded into the struct snd_soc_dai_link. Topology can
use the dobj to find the links created by it and remove them when the
topology component is unloaded.

The predefined DAI links are reserved to keep backward compatibility.
And they will also be added to the list.

Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>

diff --git a/include/sound/soc.h b/include/sound/soc.h
index 232b30d..8ec025d 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -1037,6 +1037,9 @@ struct snd_soc_dai_link {
 
 	/* pmdown_time is ignored at stop */
 	unsigned int ignore_pmdown_time:1;
+
+	struct list_head list; /* DAI link list of the soc card */
+	struct snd_soc_dobj dobj; /* For topology */
 };
 
 struct snd_soc_codec_conf {
@@ -1104,8 +1107,11 @@ struct snd_soc_card {
 	long pmdown_time;
 
 	/* CPU <--> Codec DAI links  */
-	struct snd_soc_dai_link *dai_link;
-	int num_links;
+	struct snd_soc_dai_link *dai_link;  /* predefined links only */
+	int num_links;  /* predefined links only */
+	struct list_head dai_link_list; /* all links */
+	int num_dai_links;
+
 	struct list_head rtd_list;
 	int num_rtd;
 
@@ -1647,6 +1653,11 @@ int snd_soc_of_get_dai_link_codecs(struct device *dev,
 				   struct device_node *of_node,
 				   struct snd_soc_dai_link *dai_link);
 
+void snd_soc_add_dai_link(struct snd_soc_card *card,
+				struct snd_soc_dai_link *dai_link);
+void snd_soc_remove_dai_link(struct snd_soc_card *card,
+			     struct snd_soc_dai_link *dai_link);
+
 #include <sound/soc-dai.h>
 
 #ifdef CONFIG_DEBUG_FS
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 878a9fe..b97147d 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1120,6 +1120,7 @@ static void soc_remove_dai_links(struct snd_soc_card *card)
 {
 	int order;
 	struct snd_soc_pcm_runtime *rtd;
+	struct snd_soc_dai_link *link, *_link;
 
 	for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
 			order++) {
@@ -1132,6 +1133,14 @@ static void soc_remove_dai_links(struct snd_soc_card *card)
 		list_for_each_entry(rtd, &card->rtd_list, list)
 			soc_remove_link_components(card, rtd, order);
 	}
+
+	list_for_each_entry_safe(link, _link, &card->dai_link_list, list) {
+		if (link->dobj.type)
+			dev_warn(card->dev, "Forgot to remove link %s?\n",
+				link->name);
+		list_del(&link->list);
+		card->num_dai_links--;
+	}
 }
 
 static int snd_soc_init_multicodec(struct snd_soc_card *card,
@@ -1228,6 +1237,52 @@ static int soc_init_dai_link(struct snd_soc_card *card,
 	return 0;
 }
 
+/**
+ * snd_soc_add_dai_link - Add a DAI link dynamically
+ * @card: The ASoC card to which the DAI link is added
+ * @dai_link: The new DAI link to add
+ *
+ * This function adds a DAI link to the ASoC card's link list.
+ *
+ * Note: Topology can use this API to add DAI links when probing the
+ * topology component. And machine drivers can still define static
+ * DAI links in dai_link array.
+ */
+void snd_soc_add_dai_link(struct snd_soc_card *card,
+		struct snd_soc_dai_link *dai_link)
+{
+	lockdep_assert_held(&client_mutex);
+	list_add_tail(&dai_link->list, &card->dai_link_list);
+	card->num_dai_links++;
+}
+EXPORT_SYMBOL_GPL(snd_soc_add_dai_link);
+
+/**
+ * snd_soc_remove_dai_link - Remove a DAI link from the list
+ * @card: The ASoC card that owns the link
+ * @dai_link: The DAI link to remove
+ *
+ * This function removes a DAI link from the ASoC card's link list.
+ *
+ * For DAI links previously added by topology, topology should
+ * remove them by using the dobj embedded in the link.
+ */
+void snd_soc_remove_dai_link(struct snd_soc_card *card,
+			     struct snd_soc_dai_link *dai_link)
+{
+	struct snd_soc_dai_link *link, *_link;
+
+	lockdep_assert_held(&client_mutex);
+	list_for_each_entry_safe(link, _link, &card->dai_link_list, list) {
+		if (link == dai_link) {
+			list_del(&link->list);
+			card->num_dai_links--;
+			return;
+		}
+	}
+}
+EXPORT_SYMBOL_GPL(snd_soc_remove_dai_link);
+
 static void soc_set_name_prefix(struct snd_soc_card *card,
 				struct snd_soc_component *component)
 {
@@ -1722,6 +1777,10 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
 			goto base_error;
 	}
 
+	/* add predefined DAI links to the list */
+	for (i = 0; i < card->num_links; i++)
+		snd_soc_add_dai_link(card, card->dai_link+i);
+
 	/* initialize the register cache for each available codec */
 	list_for_each_entry(codec, &codec_list, list) {
 		if (codec->cache_init)
@@ -2479,6 +2538,9 @@ int snd_soc_register_card(struct snd_soc_card *card)
 
 	snd_soc_initialize_card_lists(card);
 
+	INIT_LIST_HEAD(&card->dai_link_list);
+	card->num_dai_links = 0;
+
 	INIT_LIST_HEAD(&card->rtd_list);
 	card->num_rtd = 0;
 
-- 
2.5.0

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

* Re: [PATCH 3/3] ASoC: Implement DAI links in a list & define API to add/remove a link
  2015-11-23 16:04 ` [PATCH 3/3] ASoC: Implement DAI links in a list & define API to add/remove a link mengdong.lin
@ 2015-12-01 15:58   ` Mark Brown
  0 siblings, 0 replies; 5+ messages in thread
From: Mark Brown @ 2015-12-01 15:58 UTC (permalink / raw
  To: mengdong.lin
  Cc: alsa-devel, vinod.koul, mengdong.lin, liam.r.girdwood, jeeja.kp,
	subhransu.s.prusty


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

On Mon, Nov 23, 2015 at 11:04:04AM -0500, mengdong.lin@linux.intel.com wrote:

A couple of small things but otherwise this looks fine:

> +	struct snd_soc_dai_link *dai_link;  /* predefined links only */
> +	int num_links;  /* predefined links only */
> +	struct list_head dai_link_list; /* all links */
> +	int num_dai_links;

Why are we keeping a count of num_dai_links?  I can't see any users.

> +	/* add predefined DAI links to the list */
> +	for (i = 0; i < card->num_links; i++)
> +		snd_soc_add_dai_link(card, card->dai_link+i);

Missing spaces around the + here.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

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



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

end of thread, other threads:[~2015-12-01 15:58 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-11-23 15:59 [PATCH 0/3] ASoC: Implement DAI links in a list & some code refactoring mengdong.lin
2015-11-23 16:01 ` [PATCH 1/3] ASoC: Define soc_init_dai_link() to wrap link intialization mengdong.lin
2015-11-23 16:03 ` [PATCH 2/3] ASoC: Change 2nd argument of soc_bind_dai_link() to DAI link pointer mengdong.lin
2015-11-23 16:04 ` [PATCH 3/3] ASoC: Implement DAI links in a list & define API to add/remove a link mengdong.lin
2015-12-01 15:58   ` 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.