[alsa-devel] [PATCH v2 3/4] ASoC: simple-card: accept many DAI links

Li.Xiubo at freescale.com Li.Xiubo at freescale.com
Wed Mar 12 06:20:17 CET 2014


> Subject: [PATCH v2 3/4] ASoC: simple-card: accept many DAI links
> 
> Some simple audio cards may have many DAI links.
> This patch extends the simple-card driver for handling such cards.
> 
> Signed-off-by: Jean-Francois Moine <moinejf at free.fr>
> ---
>  sound/soc/generic/simple-card.c | 132 ++++++++++++++++++++++++++-------------
> -
>  1 file changed, 85 insertions(+), 47 deletions(-)
> 
> diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
> index 2710b52..8188c34 100644
> --- a/sound/soc/generic/simple-card.c
> +++ b/sound/soc/generic/simple-card.c
> @@ -107,6 +107,9 @@ asoc_simple_card_sub_parse_of(struct device_node *np,
>  	if (ret < 0)
>  		return ret;
> 
> +	if (!dai)
> +		return 0;
> +
>  	/* parse TDM slot */
>  	ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width);
>  	if (ret)
> @@ -154,7 +157,7 @@ static int asoc_simple_card_parse_of(struct device_node
> *node,
>  	struct snd_soc_dai_link *dai_link = priv->snd_card.dai_link;
>  	struct device_node *np;
>  	char *name;
> -	int ret;
> +	int first_link, ret;
> 
>  	/* parsing the card name from DT */
>  	snd_soc_of_parse_card_name(&priv->snd_card, "simple-audio-card,name");
> @@ -179,50 +182,67 @@ static int asoc_simple_card_parse_of(struct device_node
> *node,
>  			return ret;
>  	}
> 
> -	/* CPU sub-node */
> -	ret = -EINVAL;
> -	np = of_get_child_by_name(node, "simple-audio-card,cpu");
> -	if (np) {
> +	/* loop on the DAI links */
> +	np = NULL;
> +	first_link = 1;
> +	for (;;) {
> +		np = of_get_next_child(node, np);
> +		if (!np)
> +			break;
> +
> +		/* CPU sub-node */
> +		if (strcmp(np->name, "simple-audio-card,cpu") != 0) {
> +			dev_err(dev, "Bad CPU DAI\n");
> +			ret = -EINVAL;
> +			goto err;
> +		}
>  		ret = asoc_simple_card_sub_parse_of(np, priv->daifmt,
> -						  &priv->cpu_dai,
> +					first_link ? &priv->cpu_dai : NULL,

@Jean-Francois,

I'm not sure why only the first link needs parsing the DAIFMT ?

On my LS1 platform there are two CODECs and two CPU SAI deivces,
SGTL5000 <---> SAI
CS42888  <---> ESAI

Could the many dai links feature support this case? 

I my understanding is correct here, this patch will support the
Board, in which board there maybe only one CODEC supporting many
DAIs...


Thanks,

--
Best Regards,
Xiubo




>  						  &dai_link->cpu_of_node,
>  						  &dai_link->cpu_dai_name);
> -		of_node_put(np);
> -	}
> -	if (ret < 0)
> -		return ret;
> +		if (ret < 0)
> +			goto err;
> 
> -	/* CODEC sub-node */
> -	ret = -EINVAL;
> -	np = of_get_child_by_name(node, "simple-audio-card,codec");
> -	if (np) {
> +		/* CODEC sub-node */
> +		np = of_get_next_child(node, np);
> +		if (strcmp(np->name, "simple-audio-card,codec") != 0) {
> +			dev_err(dev, "Bad CODEC DAI\n");
> +			ret = -EINVAL;
> +			goto err;
> +		}
>  		ret = asoc_simple_card_sub_parse_of(np, priv->daifmt,
> -						  &priv->codec_dai,
> +					first_link ? &priv->codec_dai : NULL,
>  						  &dai_link->codec_of_node,
>  						  &dai_link->codec_dai_name);
> -		of_node_put(np);
> -	}
> -	if (ret < 0)
> -		return ret;
> +		if (ret < 0)
> +			goto err;
> +
> +		if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) {
> +			ret = -EINVAL;
> +			goto err;
> +		}
> 
> -	if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name)
> -		return -EINVAL;
> +		/* simple-card assumes platform == cpu */
> +		dai_link->platform_of_node = dai_link->cpu_of_node;
> +
> +		name = devm_kzalloc(dev,
> +				    strlen(dai_link->cpu_dai_name)   +
> +				    strlen(dai_link->codec_dai_name) + 2,
> +				    GFP_KERNEL);
> +		sprintf(name, "%s-%s", dai_link->cpu_dai_name,
> +					dai_link->codec_dai_name);
> +		dai_link->name = dai_link->stream_name = name;
> +
> +		dai_link++;
> +		first_link = 0;
> +	}
> 
>  	/* card name is created from CPU/CODEC dai name */
> -	name = devm_kzalloc(dev,
> -			    strlen(dai_link->cpu_dai_name)   +
> -			    strlen(dai_link->codec_dai_name) + 2,
> -			    GFP_KERNEL);
> -	sprintf(name, "%s-%s", dai_link->cpu_dai_name,
> -				dai_link->codec_dai_name);
> +	dai_link = priv->snd_card.dai_link;
>  	if (!priv->snd_card.name)
> -		priv->snd_card.name = name;
> -	dai_link->name = dai_link->stream_name = name;
> +		priv->snd_card.name = dai_link->name;
> 
> -	/* simple-card assumes platform == cpu */
> -	dai_link->platform_of_node = dai_link->cpu_of_node;
> -
> -	dev_dbg(dev, "card-name : %s\n", name);
> +	dev_dbg(dev, "card-name : %s\n", priv->snd_card.name);
>  	dev_dbg(dev, "platform : %04x\n", priv->daifmt);
>  	dev_dbg(dev, "cpu : %s / %04x / %d\n",
>  		dai_link->cpu_dai_name,
> @@ -233,18 +253,11 @@ static int asoc_simple_card_parse_of(struct device_node
> *node,
>  		priv->codec_dai.fmt,
>  		priv->codec_dai.sysclk);
> 
> -	/*
> -	 * soc_bind_dai_link() will check cpu name
> -	 * after of_node matching if dai_link has cpu_dai_name.
> -	 * but, it will never match if name was created by fmt_single_name()
> -	 * remove cpu_dai_name to escape name matching.
> -	 * see
> -	 *	fmt_single_name()
> -	 *	fmt_multiple_name()
> -	 */
> -	dai_link->cpu_dai_name = NULL;
> -
>  	return 0;
> +
> +err:
> +	of_node_put(np);
> +	return ret;
>  }
> 
>  /* update the reference count of the devices nodes at end of probe */
> @@ -274,10 +287,22 @@ static int asoc_simple_card_probe(struct platform_device
> *pdev)
>  	struct snd_soc_dai_link *dai_link;
>  	struct device_node *np = pdev->dev.of_node;
>  	struct device *dev = &pdev->dev;
> -	int ret;
> +	int num_links, ret;
> +
> +	/* get the number of DAI links */
> +	if (np) {
> +		num_links = of_get_child_count(np);
> +		if (num_links == 0 || (num_links & 1)) {
> +			dev_err(&pdev->dev, "Bad number of DAI links\n");
> +			return -EINVAL;
> +		}
> +		num_links /= 2;
> +	} else {
> +		num_links = 1;
> +	}
> 
>  	priv = devm_kzalloc(dev,
> -			sizeof(*priv) + sizeof(*dai_link),
> +			sizeof(*priv) + sizeof(*dai_link) * num_links,
>  			GFP_KERNEL);
>  	if (!priv)
>  		return -ENOMEM;
> @@ -289,7 +314,7 @@ static int asoc_simple_card_probe(struct platform_device
> *pdev)
>  	priv->snd_card.dev = dev;
>  	dai_link = priv->dai_link;
>  	priv->snd_card.dai_link = dai_link;
> -	priv->snd_card.num_links = 1;
> +	priv->snd_card.num_links = num_links;
> 
>  	if (np && of_device_is_available(np)) {
> 
> @@ -299,6 +324,19 @@ static int asoc_simple_card_probe(struct platform_device
> *pdev)
>  				dev_err(dev, "parse error %d\n", ret);
>  			goto err;
>  		}
> +
> +		/*
> +		 * soc_bind_dai_link() will check cpu name
> +		 * after of_node matching if dai_link has cpu_dai_name.
> +		 * but, it will never match if name was created by
> fmt_single_name()
> +		 * remove cpu_dai_name to escape name matching.
> +		 * see
> +		 *	fmt_single_name()
> +		 *	fmt_multiple_name()
> +		 */
> +		if (num_links == 1)
> +			dai_link->cpu_dai_name = NULL;
> +
>  	} else {
>  		struct asoc_simple_card_info *cinfo;
> 
> --
> 1.9.0
> 
> 



More information about the Alsa-devel mailing list