[v4,6/8] ASoC: compress: Add support for DAI multicodec
diff mbox

Message ID 1404200881-32253-7-git-send-email-bcousson@baylibre.com
State New, archived
Headers show

Commit Message

Benoit Cousson July 1, 2014, 7:47 a.m. UTC
Add multicodec support in soc-compress.c

Signed-off-by: Benoit Cousson <bcousson@baylibre.com>
Cc: Misael Lopez Cruz <misael.lopez@ti.com>
---
 sound/soc/soc-compress.c | 94 ++++++++++++++++++++++++++++++------------------
 1 file changed, 59 insertions(+), 35 deletions(-)

Comments

Lars-Peter Clausen July 1, 2014, 1:49 p.m. UTC | #1
On 07/01/2014 09:47 AM, Benoit Cousson wrote:
[...]
for (i = 0; i < rtd->num_codecs; i++) {
> +		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
> +		/* check client and interface hw capabilities */
> +		snprintf(new_name, sizeof(new_name), "%s %s-%d",
> +			 rtd->dai_link->stream_name, codec_dai->name, num);

We may need to rethink how to do the naming for multiple CODEC DAI links 
here. This implementation will just keep overwriting new_name with each loop 
iteration and end up using the last one. Vinod may have some insights.
Vinod Koul July 1, 2014, 4:25 p.m. UTC | #2
On Tue, Jul 01, 2014 at 03:49:51PM +0200, Lars-Peter Clausen wrote:
> On 07/01/2014 09:47 AM, Benoit Cousson wrote:
And you should have cced me on this patch

> [...]
> for (i = 0; i < rtd->num_codecs; i++) {
> >+		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
> >+		/* check client and interface hw capabilities */
> >+		snprintf(new_name, sizeof(new_name), "%s %s-%d",
> >+			 rtd->dai_link->stream_name, codec_dai->name, num);
> 
> We may need to rethink how to do the naming for multiple CODEC DAI
> links here. This implementation will just keep overwriting new_name
> with each loop iteration and end up using the last one. Vinod may
> have some insights.

I am intrugued on how we do this for pcms with multi-codec support.

Looking at the patch series I dont think the soc_pcm_new() has been updated
(please point out if i missed, it is late in night)
Shouldnt this be updated for pcm too?

I would suggest makes sense is to keep appending the codec name for the
dai-link. But yes keep a check on the size. Unless we have better ideas.
Vinod Koul July 1, 2014, 4:41 p.m. UTC | #3
On Tue, Jul 01, 2014 at 09:47:59AM +0200, Benoit Cousson wrote:
> Add multicodec support in soc-compress.c
> 
> @@ -294,13 +299,19 @@ static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
>  			goto out;
>  	}
>  
> -	switch (cmd) {
> -	case SNDRV_PCM_TRIGGER_START:
> -		snd_soc_dai_digital_mute(codec_dai, 0, cstream->direction);
> -		break;
> -	case SNDRV_PCM_TRIGGER_STOP:
> -		snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
> -		break;
> +	for (i = 0; i < rtd->num_codecs; i++) {
> +		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
> +
> +		switch (cmd) {
> +		case SNDRV_PCM_TRIGGER_START:
> +			snd_soc_dai_digital_mute(codec_dai, 0,
> +						 cstream->direction);
> +			break;
> +		case SNDRV_PCM_TRIGGER_STOP:
> +			snd_soc_dai_digital_mute(codec_dai, 1,
> +						 cstream->direction);
Wouldnt it make sense to fix snd_soc_dai_digital_mute() for multi-codecs. Did
you do same thing for pcm?

> +			break;
> +		}
>  	}
>  
>  out:
> @@ -622,23 +633,33 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
>  {
>  	struct snd_soc_codec *codec = rtd->codec;
>  	struct snd_soc_platform *platform = rtd->platform;
> -	struct snd_soc_dai *codec_dai = rtd->codec_dai;
>  	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
>  	struct snd_compr *compr;
>  	struct snd_pcm *be_pcm;
>  	char new_name[64];
> -	int ret = 0, direction = 0;
> -
> -	/* check client and interface hw capabilities */
> -	snprintf(new_name, sizeof(new_name), "%s %s-%d",
> -			rtd->dai_link->stream_name, codec_dai->name, num);
> -
> -	if (codec_dai->driver->playback.channels_min)
> -		direction = SND_COMPRESS_PLAYBACK;
> -	else if (codec_dai->driver->capture.channels_min)
> -		direction = SND_COMPRESS_CAPTURE;
> -	else
> -		return -EINVAL;
> +	int i, ret = 0, direction = -1;
> +
> +	for (i = 0; i < rtd->num_codecs; i++) {
> +		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
> +		/* check client and interface hw capabilities */
> +		snprintf(new_name, sizeof(new_name), "%s %s-%d",
> +			 rtd->dai_link->stream_name, codec_dai->name, num);
> +
> +		if (direction < 0) {
> +			if (codec_dai->driver->playback.channels_min)
> +				direction = SND_COMPRESS_PLAYBACK;
> +			else if (codec_dai->driver->capture.channels_min)
> +				direction = SND_COMPRESS_CAPTURE;
direction wont change with multiple codecs, so this loop makes no sense here.
For simplcity perhaps we can use cpu_dai?
> +			else
> +				return -EINVAL;
> +		} else {
when will this get executed? You have initialized direction to -1 and if case is
always true. I think compiler will simply remove the below sinppet.
> +			if ((codec_dai->driver->playback.channels_min &&
> +					direction != SND_COMPRESS_PLAYBACK) ||
> +			    (codec_dai->driver->capture.channels_min &&
> +					direction != SND_COMPRESS_CAPTURE))
and what exactly are we trying to check here?
> +				return -EINVAL;
> +		}
> +	}
>  
>  	compr = kzalloc(sizeof(*compr), GFP_KERNEL);
>  	if (compr == NULL) {
> @@ -692,8 +713,11 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
>  	rtd->compr = compr;
>  	compr->private_data = rtd;
>  
> -	printk(KERN_INFO "compress asoc: %s <-> %s mapping ok\n", codec_dai->name,
> -		cpu_dai->name);
> +	for (i = 0; i < rtd->num_codecs; i++) {
> +		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
> +		printk(KERN_INFO "compress asoc: %s <-> %s mapping ok\n",
> +		       codec_dai->name, cpu_dai->name);
wrong again. You are not creating multiple links with multi-codec. Link is still
single.
Lars-Peter Clausen July 1, 2014, 4:42 p.m. UTC | #4
On 07/01/2014 06:25 PM, Vinod Koul wrote:
> On Tue, Jul 01, 2014 at 03:49:51PM +0200, Lars-Peter Clausen wrote:
>> On 07/01/2014 09:47 AM, Benoit Cousson wrote:
> And you should have cced me on this patch
>
>> [...]
>> for (i = 0; i < rtd->num_codecs; i++) {
>>> +		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
>>> +		/* check client and interface hw capabilities */
>>> +		snprintf(new_name, sizeof(new_name), "%s %s-%d",
>>> +			 rtd->dai_link->stream_name, codec_dai->name, num);
>>
>> We may need to rethink how to do the naming for multiple CODEC DAI
>> links here. This implementation will just keep overwriting new_name
>> with each loop iteration and end up using the last one. Vinod may
>> have some insights.
>
> I am intrugued on how we do this for pcms with multi-codec support.
>
> Looking at the patch series I dont think the soc_pcm_new() has been updated
> (please point out if i missed, it is late in night)
> Shouldnt this be updated for pcm too?
>
> I would suggest makes sense is to keep appending the codec name for the
> dai-link. But yes keep a check on the size. Unless we have better ideas.
>

This is what the patch series does for normal PCMs

  	snprintf(new_name, sizeof(new_name), "%s %s-%d",
-		rtd->dai_link->stream_name, codec_dai->name, num);
+		rtd->dai_link->stream_name,
+		(rtd->num_codecs > 1) ?
+		"multicodec" : rtd->codec_dai->name, num);
Vinod Koul July 1, 2014, 4:45 p.m. UTC | #5
On Tue, Jul 01, 2014 at 06:42:12PM +0200, Lars-Peter Clausen wrote:
> On 07/01/2014 06:25 PM, Vinod Koul wrote:
> >On Tue, Jul 01, 2014 at 03:49:51PM +0200, Lars-Peter Clausen wrote:
> >>On 07/01/2014 09:47 AM, Benoit Cousson wrote:
> >And you should have cced me on this patch
> >
> >>[...]
> >>for (i = 0; i < rtd->num_codecs; i++) {
> >>>+		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
> >>>+		/* check client and interface hw capabilities */
> >>>+		snprintf(new_name, sizeof(new_name), "%s %s-%d",
> >>>+			 rtd->dai_link->stream_name, codec_dai->name, num);
> >>
> >>We may need to rethink how to do the naming for multiple CODEC DAI
> >>links here. This implementation will just keep overwriting new_name
> >>with each loop iteration and end up using the last one. Vinod may
> >>have some insights.
> >
> >I am intrugued on how we do this for pcms with multi-codec support.
> >
> >Looking at the patch series I dont think the soc_pcm_new() has been updated
> >(please point out if i missed, it is late in night)
> >Shouldnt this be updated for pcm too?
> >
> >I would suggest makes sense is to keep appending the codec name for the
> >dai-link. But yes keep a check on the size. Unless we have better ideas.
> >
> 
> This is what the patch series does for normal PCMs
> 
>  	snprintf(new_name, sizeof(new_name), "%s %s-%d",
> -		rtd->dai_link->stream_name, codec_dai->name, num);
> +		rtd->dai_link->stream_name,
> +		(rtd->num_codecs > 1) ?
> +		"multicodec" : rtd->codec_dai->name, num);
Sounds good to me!
Benoit Cousson July 1, 2014, 5:32 p.m. UTC | #6
On 01/07/2014 18:25, Vinod Koul wrote:
> On Tue, Jul 01, 2014 at 03:49:51PM +0200, Lars-Peter Clausen wrote:
>> On 07/01/2014 09:47 AM, Benoit Cousson wrote:
> And you should have cced me on this patch

Sorry, my mistake. I'll add you for the next release.

Regards,
Benoit

>
>> [...]
>> for (i = 0; i < rtd->num_codecs; i++) {
>>> +		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
>>> +		/* check client and interface hw capabilities */
>>> +		snprintf(new_name, sizeof(new_name), "%s %s-%d",
>>> +			 rtd->dai_link->stream_name, codec_dai->name, num);
>>
>> We may need to rethink how to do the naming for multiple CODEC DAI
>> links here. This implementation will just keep overwriting new_name
>> with each loop iteration and end up using the last one. Vinod may
>> have some insights.
>
> I am intrugued on how we do this for pcms with multi-codec support.
>
> Looking at the patch series I dont think the soc_pcm_new() has been updated
> (please point out if i missed, it is late in night)
> Shouldnt this be updated for pcm too?
>
> I would suggest makes sense is to keep appending the codec name for the
> dai-link. But yes keep a check on the size. Unless we have better ideas.
>
Mark Brown July 1, 2014, 5:41 p.m. UTC | #7
On Tue, Jul 01, 2014 at 10:11:34PM +0530, Vinod Koul wrote:
> On Tue, Jul 01, 2014 at 09:47:59AM +0200, Benoit Cousson wrote:

> > +	for (i = 0; i < rtd->num_codecs; i++) {
> > +		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
> > +
> > +		switch (cmd) {
> > +		case SNDRV_PCM_TRIGGER_START:
> > +			snd_soc_dai_digital_mute(codec_dai, 0,
> > +						 cstream->direction);
> > +			break;
> > +		case SNDRV_PCM_TRIGGER_STOP:
> > +			snd_soc_dai_digital_mute(codec_dai, 1,
> > +						 cstream->direction);

> Wouldnt it make sense to fix snd_soc_dai_digital_mute() for multi-codecs. Did
> you do same thing for pcm?

Yes, the other callers also iterate through all the CODECs.  It might be
sensible to have a wrapper which does the iteration but I do think it's
reasonable for _dai_digital_mute() to just operate on one DAI.
Benoit Cousson July 2, 2014, 12:53 p.m. UTC | #8
On 01/07/2014 18:41, Vinod Koul wrote:
> On Tue, Jul 01, 2014 at 09:47:59AM +0200, Benoit Cousson wrote:
>> Add multicodec support in soc-compress.c
>>
>> @@ -294,13 +299,19 @@ static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
>>   			goto out;
>>   	}
>>
>> -	switch (cmd) {
>> -	case SNDRV_PCM_TRIGGER_START:
>> -		snd_soc_dai_digital_mute(codec_dai, 0, cstream->direction);
>> -		break;
>> -	case SNDRV_PCM_TRIGGER_STOP:
>> -		snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
>> -		break;
>> +	for (i = 0; i < rtd->num_codecs; i++) {
>> +		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
>> +
>> +		switch (cmd) {
>> +		case SNDRV_PCM_TRIGGER_START:
>> +			snd_soc_dai_digital_mute(codec_dai, 0,
>> +						 cstream->direction);
>> +			break;
>> +		case SNDRV_PCM_TRIGGER_STOP:
>> +			snd_soc_dai_digital_mute(codec_dai, 1,
>> +						 cstream->direction);
> Wouldnt it make sense to fix snd_soc_dai_digital_mute() for multi-codecs. Did
> you do same thing for pcm?

What do you mean by fix for multi-codecs?

>
>> +			break;
>> +		}
>>   	}
>>
>>   out:
>> @@ -622,23 +633,33 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
>>   {
>>   	struct snd_soc_codec *codec = rtd->codec;
>>   	struct snd_soc_platform *platform = rtd->platform;
>> -	struct snd_soc_dai *codec_dai = rtd->codec_dai;
>>   	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
>>   	struct snd_compr *compr;
>>   	struct snd_pcm *be_pcm;
>>   	char new_name[64];
>> -	int ret = 0, direction = 0;
>> -
>> -	/* check client and interface hw capabilities */
>> -	snprintf(new_name, sizeof(new_name), "%s %s-%d",
>> -			rtd->dai_link->stream_name, codec_dai->name, num);
>> -
>> -	if (codec_dai->driver->playback.channels_min)
>> -		direction = SND_COMPRESS_PLAYBACK;
>> -	else if (codec_dai->driver->capture.channels_min)
>> -		direction = SND_COMPRESS_CAPTURE;
>> -	else
>> -		return -EINVAL;
>> +	int i, ret = 0, direction = -1;
>> +
>> +	for (i = 0; i < rtd->num_codecs; i++) {
>> +		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
>> +		/* check client and interface hw capabilities */
>> +		snprintf(new_name, sizeof(new_name), "%s %s-%d",
>> +			 rtd->dai_link->stream_name, codec_dai->name, num);
>> +
>> +		if (direction < 0) {
>> +			if (codec_dai->driver->playback.channels_min)
>> +				direction = SND_COMPRESS_PLAYBACK;
>> +			else if (codec_dai->driver->capture.channels_min)
>> +				direction = SND_COMPRESS_CAPTURE;
> direction wont change with multiple codecs, so this loop makes no sense here.
> For simplcity perhaps we can use cpu_dai?
>> +			else
>> +				return -EINVAL;
>> +		} else {
> when will this get executed? You have initialized direction to -1 and if case is
> always true. I think compiler will simply remove the below sinppet.

direction is set to -1, then the first iteration will set it to the 
direction of the first codec_dai. The other iteration are just checking 
that there are all in the same direction and will fail otherwise.

>> +			if ((codec_dai->driver->playback.channels_min &&
>> +					direction != SND_COMPRESS_PLAYBACK) ||
>> +			    (codec_dai->driver->capture.channels_min &&
>> +					direction != SND_COMPRESS_CAPTURE))
> and what exactly are we trying to check here?

That every codec_dai are in the same direction.

If you think this is pointless since every DAI are always in the same 
direction, we can just remove it.

>> +				return -EINVAL;
>> +		}
>> +	}
>>
>>   	compr = kzalloc(sizeof(*compr), GFP_KERNEL);
>>   	if (compr == NULL) {
>> @@ -692,8 +713,11 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
>>   	rtd->compr = compr;
>>   	compr->private_data = rtd;
>>
>> -	printk(KERN_INFO "compress asoc: %s <-> %s mapping ok\n", codec_dai->name,
>> -		cpu_dai->name);
>> +	for (i = 0; i < rtd->num_codecs; i++) {
>> +		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
>> +		printk(KERN_INFO "compress asoc: %s <-> %s mapping ok\n",
>> +		       codec_dai->name, cpu_dai->name);
> wrong again. You are not creating multiple links with multi-codec. Link is still
> single.

Yeah, I know, the idea was to print that we have multiple codec. I'll 
use the same "multicodec" info like we did for PCM.

Thanks for the feedback,
Benoit
Vinod Koul July 3, 2014, 6:39 a.m. UTC | #9
On Tue, Jul 01, 2014 at 06:41:17PM +0100, Mark Brown wrote:
> On Tue, Jul 01, 2014 at 10:11:34PM +0530, Vinod Koul wrote:
> > On Tue, Jul 01, 2014 at 09:47:59AM +0200, Benoit Cousson wrote:
> 
> > > +	for (i = 0; i < rtd->num_codecs; i++) {
> > > +		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
> > > +
> > > +		switch (cmd) {
> > > +		case SNDRV_PCM_TRIGGER_START:
> > > +			snd_soc_dai_digital_mute(codec_dai, 0,
> > > +						 cstream->direction);
> > > +			break;
> > > +		case SNDRV_PCM_TRIGGER_STOP:
> > > +			snd_soc_dai_digital_mute(codec_dai, 1,
> > > +						 cstream->direction);
> 
> > Wouldnt it make sense to fix snd_soc_dai_digital_mute() for multi-codecs. Did
> > you do same thing for pcm?
> 
> Yes, the other callers also iterate through all the CODECs.  It might be
> sensible to have a wrapper which does the iteration but I do think it's
> reasonable for _dai_digital_mute() to just operate on one DAI.
Yes that sounds okay as well
Vinod Koul July 3, 2014, 6:41 a.m. UTC | #10
On Wed, Jul 02, 2014 at 02:53:50PM +0200, Benoit Cousson wrote:
> >>@@ -622,23 +633,33 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
> >>  {
> >>  	struct snd_soc_codec *codec = rtd->codec;
> >>  	struct snd_soc_platform *platform = rtd->platform;
> >>-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
> >>  	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
> >>  	struct snd_compr *compr;
> >>  	struct snd_pcm *be_pcm;
> >>  	char new_name[64];
> >>-	int ret = 0, direction = 0;
> >>-
> >>-	/* check client and interface hw capabilities */
> >>-	snprintf(new_name, sizeof(new_name), "%s %s-%d",
> >>-			rtd->dai_link->stream_name, codec_dai->name, num);
> >>-
> >>-	if (codec_dai->driver->playback.channels_min)
> >>-		direction = SND_COMPRESS_PLAYBACK;
> >>-	else if (codec_dai->driver->capture.channels_min)
> >>-		direction = SND_COMPRESS_CAPTURE;
> >>-	else
> >>-		return -EINVAL;
> >>+	int i, ret = 0, direction = -1;
> >>+
> >>+	for (i = 0; i < rtd->num_codecs; i++) {
> >>+		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
> >>+		/* check client and interface hw capabilities */
> >>+		snprintf(new_name, sizeof(new_name), "%s %s-%d",
> >>+			 rtd->dai_link->stream_name, codec_dai->name, num);
> >>+
> >>+		if (direction < 0) {
> >>+			if (codec_dai->driver->playback.channels_min)
> >>+				direction = SND_COMPRESS_PLAYBACK;
> >>+			else if (codec_dai->driver->capture.channels_min)
> >>+				direction = SND_COMPRESS_CAPTURE;
> >direction wont change with multiple codecs, so this loop makes no sense here.
> >For simplcity perhaps we can use cpu_dai?
> >>+			else
> >>+				return -EINVAL;
> >>+		} else {
> >when will this get executed? You have initialized direction to -1 and if case is
> >always true. I think compiler will simply remove the below sinppet.
> 
> direction is set to -1, then the first iteration will set it to the
> direction of the first codec_dai. The other iteration are just
> checking that there are all in the same direction and will fail
> otherwise.
> 
> >>+			if ((codec_dai->driver->playback.channels_min &&
> >>+					direction != SND_COMPRESS_PLAYBACK) ||
> >>+			    (codec_dai->driver->capture.channels_min &&
> >>+					direction != SND_COMPRESS_CAPTURE))
> >and what exactly are we trying to check here?
> 
> That every codec_dai are in the same direction.
> 
> If you think this is pointless since every DAI are always in the
> same direction, we can just remove it.
I think that will simplify it. we certainly dont expect different direction,
right?
Benoit Cousson July 3, 2014, 11:09 a.m. UTC | #11
On 03/07/2014 08:41, Vinod Koul wrote:
> On Wed, Jul 02, 2014 at 02:53:50PM +0200, Benoit Cousson wrote:
>>>> @@ -622,23 +633,33 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
>>>>   {
>>>>   	struct snd_soc_codec *codec = rtd->codec;
>>>>   	struct snd_soc_platform *platform = rtd->platform;
>>>> -	struct snd_soc_dai *codec_dai = rtd->codec_dai;
>>>>   	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
>>>>   	struct snd_compr *compr;
>>>>   	struct snd_pcm *be_pcm;
>>>>   	char new_name[64];
>>>> -	int ret = 0, direction = 0;
>>>> -
>>>> -	/* check client and interface hw capabilities */
>>>> -	snprintf(new_name, sizeof(new_name), "%s %s-%d",
>>>> -			rtd->dai_link->stream_name, codec_dai->name, num);
>>>> -
>>>> -	if (codec_dai->driver->playback.channels_min)
>>>> -		direction = SND_COMPRESS_PLAYBACK;
>>>> -	else if (codec_dai->driver->capture.channels_min)
>>>> -		direction = SND_COMPRESS_CAPTURE;
>>>> -	else
>>>> -		return -EINVAL;
>>>> +	int i, ret = 0, direction = -1;
>>>> +
>>>> +	for (i = 0; i < rtd->num_codecs; i++) {
>>>> +		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
>>>> +		/* check client and interface hw capabilities */
>>>> +		snprintf(new_name, sizeof(new_name), "%s %s-%d",
>>>> +			 rtd->dai_link->stream_name, codec_dai->name, num);
>>>> +
>>>> +		if (direction < 0) {
>>>> +			if (codec_dai->driver->playback.channels_min)
>>>> +				direction = SND_COMPRESS_PLAYBACK;
>>>> +			else if (codec_dai->driver->capture.channels_min)
>>>> +				direction = SND_COMPRESS_CAPTURE;
>>> direction wont change with multiple codecs, so this loop makes no sense here.
>>> For simplcity perhaps we can use cpu_dai?
>>>> +			else
>>>> +				return -EINVAL;
>>>> +		} else {
>>> when will this get executed? You have initialized direction to -1 and if case is
>>> always true. I think compiler will simply remove the below sinppet.
>>
>> direction is set to -1, then the first iteration will set it to the
>> direction of the first codec_dai. The other iteration are just
>> checking that there are all in the same direction and will fail
>> otherwise.
>>
>>>> +			if ((codec_dai->driver->playback.channels_min &&
>>>> +					direction != SND_COMPRESS_PLAYBACK) ||
>>>> +			    (codec_dai->driver->capture.channels_min &&
>>>> +					direction != SND_COMPRESS_CAPTURE))
>>> and what exactly are we trying to check here?
>>
>> That every codec_dai are in the same direction.
>>
>> If you think this is pointless since every DAI are always in the
>> same direction, we can just remove it.
> I think that will simplify it. we certainly dont expect different direction,
> right?

Lars, Mark
Any thought on that? Does that sound reasonable to you to use only the 
first codec_dai to figure out the direction?

Thanks,
Benoit
Mark Brown July 3, 2014, 11:16 a.m. UTC | #12
On Thu, Jul 03, 2014 at 01:09:28PM +0200, Benoit Cousson wrote:
> On 03/07/2014 08:41, Vinod Koul wrote:

> >I think that will simplify it. we certainly dont expect different direction,
> >right?

> Any thought on that? Does that sound reasonable to you to use only the first
> codec_dai to figure out the direction?

Yes, it seems sensible enough to me.
Lars-Peter Clausen July 3, 2014, 11:20 a.m. UTC | #13
On 07/03/2014 01:09 PM, Benoit Cousson wrote:
> On 03/07/2014 08:41, Vinod Koul wrote:
>> On Wed, Jul 02, 2014 at 02:53:50PM +0200, Benoit Cousson wrote:
>>>>> @@ -622,23 +633,33 @@ int soc_new_compress(struct snd_soc_pcm_runtime
>>>>> *rtd, int num)
>>>>>   {
>>>>>       struct snd_soc_codec *codec = rtd->codec;
>>>>>       struct snd_soc_platform *platform = rtd->platform;
>>>>> -    struct snd_soc_dai *codec_dai = rtd->codec_dai;
>>>>>       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
>>>>>       struct snd_compr *compr;
>>>>>       struct snd_pcm *be_pcm;
>>>>>       char new_name[64];
>>>>> -    int ret = 0, direction = 0;
>>>>> -
>>>>> -    /* check client and interface hw capabilities */
>>>>> -    snprintf(new_name, sizeof(new_name), "%s %s-%d",
>>>>> -            rtd->dai_link->stream_name, codec_dai->name, num);
>>>>> -
>>>>> -    if (codec_dai->driver->playback.channels_min)
>>>>> -        direction = SND_COMPRESS_PLAYBACK;
>>>>> -    else if (codec_dai->driver->capture.channels_min)
>>>>> -        direction = SND_COMPRESS_CAPTURE;
>>>>> -    else
>>>>> -        return -EINVAL;
>>>>> +    int i, ret = 0, direction = -1;
>>>>> +
>>>>> +    for (i = 0; i < rtd->num_codecs; i++) {
>>>>> +        struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
>>>>> +        /* check client and interface hw capabilities */
>>>>> +        snprintf(new_name, sizeof(new_name), "%s %s-%d",
>>>>> +             rtd->dai_link->stream_name, codec_dai->name, num);
>>>>> +
>>>>> +        if (direction < 0) {
>>>>> +            if (codec_dai->driver->playback.channels_min)
>>>>> +                direction = SND_COMPRESS_PLAYBACK;
>>>>> +            else if (codec_dai->driver->capture.channels_min)
>>>>> +                direction = SND_COMPRESS_CAPTURE;
>>>> direction wont change with multiple codecs, so this loop makes no sense
>>>> here.
>>>> For simplcity perhaps we can use cpu_dai?
>>>>> +            else
>>>>> +                return -EINVAL;
>>>>> +        } else {
>>>> when will this get executed? You have initialized direction to -1 and if
>>>> case is
>>>> always true. I think compiler will simply remove the below sinppet.
>>>
>>> direction is set to -1, then the first iteration will set it to the
>>> direction of the first codec_dai. The other iteration are just
>>> checking that there are all in the same direction and will fail
>>> otherwise.
>>>
>>>>> +            if ((codec_dai->driver->playback.channels_min &&
>>>>> +                    direction != SND_COMPRESS_PLAYBACK) ||
>>>>> +                (codec_dai->driver->capture.channels_min &&
>>>>> +                    direction != SND_COMPRESS_CAPTURE))
>>>> and what exactly are we trying to check here?
>>>
>>> That every codec_dai are in the same direction.
>>>
>>> If you think this is pointless since every DAI are always in the
>>> same direction, we can just remove it.
>> I think that will simplify it. we certainly dont expect different direction,
>> right?
>
> Lars, Mark
> Any thought on that? Does that sound reasonable to you to use only the first
> codec_dai to figure out the direction?
>

I guess it is ok. But I'm wondering if the direction shouldn't depend on the 
CPU dai rather than the CODEC dai? E.g. it is possible to have a CODEC with 
both playback and capture support in two dai_links, one for capture, one for 
playback. The check above would create a SND_COMPRESS_PLAYBACK stream in 
both cases. Even if the CPU dai only supported capture in one of the cases.

- Lars
Benoit Cousson July 3, 2014, 11:39 a.m. UTC | #14
On 03/07/2014 13:20, Lars-Peter Clausen wrote:
> On 07/03/2014 01:09 PM, Benoit Cousson wrote:
>> On 03/07/2014 08:41, Vinod Koul wrote:
>>> On Wed, Jul 02, 2014 at 02:53:50PM +0200, Benoit Cousson wrote:
>>>>>> @@ -622,23 +633,33 @@ int soc_new_compress(struct snd_soc_pcm_runtime
>>>>>> *rtd, int num)
>>>>>>   {
>>>>>>       struct snd_soc_codec *codec = rtd->codec;
>>>>>>       struct snd_soc_platform *platform = rtd->platform;
>>>>>> -    struct snd_soc_dai *codec_dai = rtd->codec_dai;
>>>>>>       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
>>>>>>       struct snd_compr *compr;
>>>>>>       struct snd_pcm *be_pcm;
>>>>>>       char new_name[64];
>>>>>> -    int ret = 0, direction = 0;
>>>>>> -
>>>>>> -    /* check client and interface hw capabilities */
>>>>>> -    snprintf(new_name, sizeof(new_name), "%s %s-%d",
>>>>>> -            rtd->dai_link->stream_name, codec_dai->name, num);
>>>>>> -
>>>>>> -    if (codec_dai->driver->playback.channels_min)
>>>>>> -        direction = SND_COMPRESS_PLAYBACK;
>>>>>> -    else if (codec_dai->driver->capture.channels_min)
>>>>>> -        direction = SND_COMPRESS_CAPTURE;
>>>>>> -    else
>>>>>> -        return -EINVAL;
>>>>>> +    int i, ret = 0, direction = -1;
>>>>>> +
>>>>>> +    for (i = 0; i < rtd->num_codecs; i++) {
>>>>>> +        struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
>>>>>> +        /* check client and interface hw capabilities */
>>>>>> +        snprintf(new_name, sizeof(new_name), "%s %s-%d",
>>>>>> +             rtd->dai_link->stream_name, codec_dai->name, num);
>>>>>> +
>>>>>> +        if (direction < 0) {
>>>>>> +            if (codec_dai->driver->playback.channels_min)
>>>>>> +                direction = SND_COMPRESS_PLAYBACK;
>>>>>> +            else if (codec_dai->driver->capture.channels_min)
>>>>>> +                direction = SND_COMPRESS_CAPTURE;
>>>>> direction wont change with multiple codecs, so this loop makes no
>>>>> sense
>>>>> here.
>>>>> For simplcity perhaps we can use cpu_dai?
>>>>>> +            else
>>>>>> +                return -EINVAL;
>>>>>> +        } else {
>>>>> when will this get executed? You have initialized direction to -1
>>>>> and if
>>>>> case is
>>>>> always true. I think compiler will simply remove the below sinppet.
>>>>
>>>> direction is set to -1, then the first iteration will set it to the
>>>> direction of the first codec_dai. The other iteration are just
>>>> checking that there are all in the same direction and will fail
>>>> otherwise.
>>>>
>>>>>> +            if ((codec_dai->driver->playback.channels_min &&
>>>>>> +                    direction != SND_COMPRESS_PLAYBACK) ||
>>>>>> +                (codec_dai->driver->capture.channels_min &&
>>>>>> +                    direction != SND_COMPRESS_CAPTURE))
>>>>> and what exactly are we trying to check here?
>>>>
>>>> That every codec_dai are in the same direction.
>>>>
>>>> If you think this is pointless since every DAI are always in the
>>>> same direction, we can just remove it.
>>> I think that will simplify it. we certainly dont expect different
>>> direction,
>>> right?
>>
>> Lars, Mark
>> Any thought on that? Does that sound reasonable to you to use only the
>> first
>> codec_dai to figure out the direction?
>>
>
> I guess it is ok. But I'm wondering if the direction shouldn't depend on
> the CPU dai rather than the CODEC dai? E.g. it is possible to have a
> CODEC with both playback and capture support in two dai_links, one for
> capture, one for playback. The check above would create a
> SND_COMPRESS_PLAYBACK stream in both cases. Even if the CPU dai only
> supported capture in one of the cases.

OK, I'll use the cpu_dai then.

Thanks,
Benoit
Lars-Peter Clausen July 3, 2014, 11:43 a.m. UTC | #15
On 07/03/2014 01:39 PM, Benoit Cousson wrote:
> On 03/07/2014 13:20, Lars-Peter Clausen wrote:
>> On 07/03/2014 01:09 PM, Benoit Cousson wrote:
>>> On 03/07/2014 08:41, Vinod Koul wrote:
>>>> On Wed, Jul 02, 2014 at 02:53:50PM +0200, Benoit Cousson wrote:
>>>>>>> @@ -622,23 +633,33 @@ int soc_new_compress(struct snd_soc_pcm_runtime
>>>>>>> *rtd, int num)
>>>>>>>   {
>>>>>>>       struct snd_soc_codec *codec = rtd->codec;
>>>>>>>       struct snd_soc_platform *platform = rtd->platform;
>>>>>>> -    struct snd_soc_dai *codec_dai = rtd->codec_dai;
>>>>>>>       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
>>>>>>>       struct snd_compr *compr;
>>>>>>>       struct snd_pcm *be_pcm;
>>>>>>>       char new_name[64];
>>>>>>> -    int ret = 0, direction = 0;
>>>>>>> -
>>>>>>> -    /* check client and interface hw capabilities */
>>>>>>> -    snprintf(new_name, sizeof(new_name), "%s %s-%d",
>>>>>>> -            rtd->dai_link->stream_name, codec_dai->name, num);
>>>>>>> -
>>>>>>> -    if (codec_dai->driver->playback.channels_min)
>>>>>>> -        direction = SND_COMPRESS_PLAYBACK;
>>>>>>> -    else if (codec_dai->driver->capture.channels_min)
>>>>>>> -        direction = SND_COMPRESS_CAPTURE;
>>>>>>> -    else
>>>>>>> -        return -EINVAL;
>>>>>>> +    int i, ret = 0, direction = -1;
>>>>>>> +
>>>>>>> +    for (i = 0; i < rtd->num_codecs; i++) {
>>>>>>> +        struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
>>>>>>> +        /* check client and interface hw capabilities */
>>>>>>> +        snprintf(new_name, sizeof(new_name), "%s %s-%d",
>>>>>>> +             rtd->dai_link->stream_name, codec_dai->name, num);
>>>>>>> +
>>>>>>> +        if (direction < 0) {
>>>>>>> +            if (codec_dai->driver->playback.channels_min)
>>>>>>> +                direction = SND_COMPRESS_PLAYBACK;
>>>>>>> +            else if (codec_dai->driver->capture.channels_min)
>>>>>>> +                direction = SND_COMPRESS_CAPTURE;
>>>>>> direction wont change with multiple codecs, so this loop makes no
>>>>>> sense
>>>>>> here.
>>>>>> For simplcity perhaps we can use cpu_dai?
>>>>>>> +            else
>>>>>>> +                return -EINVAL;
>>>>>>> +        } else {
>>>>>> when will this get executed? You have initialized direction to -1
>>>>>> and if
>>>>>> case is
>>>>>> always true. I think compiler will simply remove the below sinppet.
>>>>>
>>>>> direction is set to -1, then the first iteration will set it to the
>>>>> direction of the first codec_dai. The other iteration are just
>>>>> checking that there are all in the same direction and will fail
>>>>> otherwise.
>>>>>
>>>>>>> +            if ((codec_dai->driver->playback.channels_min &&
>>>>>>> +                    direction != SND_COMPRESS_PLAYBACK) ||
>>>>>>> +                (codec_dai->driver->capture.channels_min &&
>>>>>>> +                    direction != SND_COMPRESS_CAPTURE))
>>>>>> and what exactly are we trying to check here?
>>>>>
>>>>> That every codec_dai are in the same direction.
>>>>>
>>>>> If you think this is pointless since every DAI are always in the
>>>>> same direction, we can just remove it.
>>>> I think that will simplify it. we certainly dont expect different
>>>> direction,
>>>> right?
>>>
>>> Lars, Mark
>>> Any thought on that? Does that sound reasonable to you to use only the
>>> first
>>> codec_dai to figure out the direction?
>>>
>>
>> I guess it is ok. But I'm wondering if the direction shouldn't depend on
>> the CPU dai rather than the CODEC dai? E.g. it is possible to have a
>> CODEC with both playback and capture support in two dai_links, one for
>> capture, one for playback. The check above would create a
>> SND_COMPRESS_PLAYBACK stream in both cases. Even if the CPU dai only
>> supported capture in one of the cases.
>
> OK, I'll use the cpu_dai then.

Lets wait for Vinod's feedback on this first. He knows this code best and 
what the intentions are.

- Lars
Benoit Cousson July 3, 2014, 11:46 a.m. UTC | #16
On 03/07/2014 13:43, Lars-Peter Clausen wrote:
> On 07/03/2014 01:39 PM, Benoit Cousson wrote:
>> On 03/07/2014 13:20, Lars-Peter Clausen wrote:
>>> On 07/03/2014 01:09 PM, Benoit Cousson wrote:
>>>> On 03/07/2014 08:41, Vinod Koul wrote:
>>>>> On Wed, Jul 02, 2014 at 02:53:50PM +0200, Benoit Cousson wrote:
>>>>>>>> @@ -622,23 +633,33 @@ int soc_new_compress(struct 
>>>>>>>> snd_soc_pcm_runtime
>>>>>>>> *rtd, int num)
>>>>>>>>   {
>>>>>>>>       struct snd_soc_codec *codec = rtd->codec;
>>>>>>>>       struct snd_soc_platform *platform = rtd->platform;
>>>>>>>> -    struct snd_soc_dai *codec_dai = rtd->codec_dai;
>>>>>>>>       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
>>>>>>>>       struct snd_compr *compr;
>>>>>>>>       struct snd_pcm *be_pcm;
>>>>>>>>       char new_name[64];
>>>>>>>> -    int ret = 0, direction = 0;
>>>>>>>> -
>>>>>>>> -    /* check client and interface hw capabilities */
>>>>>>>> -    snprintf(new_name, sizeof(new_name), "%s %s-%d",
>>>>>>>> -            rtd->dai_link->stream_name, codec_dai->name, num);
>>>>>>>> -
>>>>>>>> -    if (codec_dai->driver->playback.channels_min)
>>>>>>>> -        direction = SND_COMPRESS_PLAYBACK;
>>>>>>>> -    else if (codec_dai->driver->capture.channels_min)
>>>>>>>> -        direction = SND_COMPRESS_CAPTURE;
>>>>>>>> -    else
>>>>>>>> -        return -EINVAL;
>>>>>>>> +    int i, ret = 0, direction = -1;
>>>>>>>> +
>>>>>>>> +    for (i = 0; i < rtd->num_codecs; i++) {
>>>>>>>> +        struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
>>>>>>>> +        /* check client and interface hw capabilities */
>>>>>>>> +        snprintf(new_name, sizeof(new_name), "%s %s-%d",
>>>>>>>> +             rtd->dai_link->stream_name, codec_dai->name, num);
>>>>>>>> +
>>>>>>>> +        if (direction < 0) {
>>>>>>>> +            if (codec_dai->driver->playback.channels_min)
>>>>>>>> +                direction = SND_COMPRESS_PLAYBACK;
>>>>>>>> +            else if (codec_dai->driver->capture.channels_min)
>>>>>>>> +                direction = SND_COMPRESS_CAPTURE;
>>>>>>> direction wont change with multiple codecs, so this loop makes no
>>>>>>> sense
>>>>>>> here.
>>>>>>> For simplcity perhaps we can use cpu_dai?
>>>>>>>> +            else
>>>>>>>> +                return -EINVAL;
>>>>>>>> +        } else {
>>>>>>> when will this get executed? You have initialized direction to -1
>>>>>>> and if
>>>>>>> case is
>>>>>>> always true. I think compiler will simply remove the below sinppet.
>>>>>>
>>>>>> direction is set to -1, then the first iteration will set it to the
>>>>>> direction of the first codec_dai. The other iteration are just
>>>>>> checking that there are all in the same direction and will fail
>>>>>> otherwise.
>>>>>>
>>>>>>>> +            if ((codec_dai->driver->playback.channels_min &&
>>>>>>>> +                    direction != SND_COMPRESS_PLAYBACK) ||
>>>>>>>> +                (codec_dai->driver->capture.channels_min &&
>>>>>>>> +                    direction != SND_COMPRESS_CAPTURE))
>>>>>>> and what exactly are we trying to check here?
>>>>>>
>>>>>> That every codec_dai are in the same direction.
>>>>>>
>>>>>> If you think this is pointless since every DAI are always in the
>>>>>> same direction, we can just remove it.
>>>>> I think that will simplify it. we certainly dont expect different
>>>>> direction,
>>>>> right?
>>>>
>>>> Lars, Mark
>>>> Any thought on that? Does that sound reasonable to you to use only the
>>>> first
>>>> codec_dai to figure out the direction?
>>>>
>>>
>>> I guess it is ok. But I'm wondering if the direction shouldn't depend on
>>> the CPU dai rather than the CODEC dai? E.g. it is possible to have a
>>> CODEC with both playback and capture support in two dai_links, one for
>>> capture, one for playback. The check above would create a
>>> SND_COMPRESS_PLAYBACK stream in both cases. Even if the CPU dai only
>>> supported capture in one of the cases.
>>
>> OK, I'll use the cpu_dai then.
> 
> Lets wait for Vinod's feedback on this first. He knows this code best 
> and what the intentions are.

Sure, but he was the first one to propose using that :-)

>>>>>>> direction wont change with multiple codecs, so this loop makes no
>>>>>>> sense
>>>>>>> here.
>>>>>>> For simplcity perhaps we can use cpu_dai?

Regards,
Benoit
Vinod Koul July 3, 2014, 12:06 p.m. UTC | #17
On Thu, Jul 03, 2014 at 01:46:23PM +0200, Benoit Cousson wrote:
> On 03/07/2014 13:43, Lars-Peter Clausen wrote:
> > On 07/03/2014 01:39 PM, Benoit Cousson wrote:
> >> On 03/07/2014 13:20, Lars-Peter Clausen wrote:
> >>> On 07/03/2014 01:09 PM, Benoit Cousson wrote:
> >>>> On 03/07/2014 08:41, Vinod Koul wrote:
> >>>>> On Wed, Jul 02, 2014 at 02:53:50PM +0200, Benoit Cousson wrote:
> >>>>>>>> @@ -622,23 +633,33 @@ int soc_new_compress(struct 
> >>>>>>>> snd_soc_pcm_runtime
> >>>>>>>> *rtd, int num)
> >>>>>>>>   {
> >>>>>>>>       struct snd_soc_codec *codec = rtd->codec;
> >>>>>>>>       struct snd_soc_platform *platform = rtd->platform;
> >>>>>>>> -    struct snd_soc_dai *codec_dai = rtd->codec_dai;
> >>>>>>>>       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
> >>>>>>>>       struct snd_compr *compr;
> >>>>>>>>       struct snd_pcm *be_pcm;
> >>>>>>>>       char new_name[64];
> >>>>>>>> -    int ret = 0, direction = 0;
> >>>>>>>> -
> >>>>>>>> -    /* check client and interface hw capabilities */
> >>>>>>>> -    snprintf(new_name, sizeof(new_name), "%s %s-%d",
> >>>>>>>> -            rtd->dai_link->stream_name, codec_dai->name, num);
> >>>>>>>> -
> >>>>>>>> -    if (codec_dai->driver->playback.channels_min)
> >>>>>>>> -        direction = SND_COMPRESS_PLAYBACK;
> >>>>>>>> -    else if (codec_dai->driver->capture.channels_min)
> >>>>>>>> -        direction = SND_COMPRESS_CAPTURE;
> >>>>>>>> -    else
> >>>>>>>> -        return -EINVAL;
> >>>>>>>> +    int i, ret = 0, direction = -1;
> >>>>>>>> +
> >>>>>>>> +    for (i = 0; i < rtd->num_codecs; i++) {
> >>>>>>>> +        struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
> >>>>>>>> +        /* check client and interface hw capabilities */
> >>>>>>>> +        snprintf(new_name, sizeof(new_name), "%s %s-%d",
> >>>>>>>> +             rtd->dai_link->stream_name, codec_dai->name, num);
> >>>>>>>> +
> >>>>>>>> +        if (direction < 0) {
> >>>>>>>> +            if (codec_dai->driver->playback.channels_min)
> >>>>>>>> +                direction = SND_COMPRESS_PLAYBACK;
> >>>>>>>> +            else if (codec_dai->driver->capture.channels_min)
> >>>>>>>> +                direction = SND_COMPRESS_CAPTURE;
> >>>>>>> direction wont change with multiple codecs, so this loop makes no
> >>>>>>> sense
> >>>>>>> here.
> >>>>>>> For simplcity perhaps we can use cpu_dai?
> >>>>>>>> +            else
> >>>>>>>> +                return -EINVAL;
> >>>>>>>> +        } else {
> >>>>>>> when will this get executed? You have initialized direction to -1
> >>>>>>> and if
> >>>>>>> case is
> >>>>>>> always true. I think compiler will simply remove the below sinppet.
> >>>>>>
> >>>>>> direction is set to -1, then the first iteration will set it to the
> >>>>>> direction of the first codec_dai. The other iteration are just
> >>>>>> checking that there are all in the same direction and will fail
> >>>>>> otherwise.
> >>>>>>
> >>>>>>>> +            if ((codec_dai->driver->playback.channels_min &&
> >>>>>>>> +                    direction != SND_COMPRESS_PLAYBACK) ||
> >>>>>>>> +                (codec_dai->driver->capture.channels_min &&
> >>>>>>>> +                    direction != SND_COMPRESS_CAPTURE))
> >>>>>>> and what exactly are we trying to check here?
> >>>>>>
> >>>>>> That every codec_dai are in the same direction.
> >>>>>>
> >>>>>> If you think this is pointless since every DAI are always in the
> >>>>>> same direction, we can just remove it.
> >>>>> I think that will simplify it. we certainly dont expect different
> >>>>> direction,
> >>>>> right?
> >>>>
> >>>> Lars, Mark
> >>>> Any thought on that? Does that sound reasonable to you to use only the
> >>>> first
> >>>> codec_dai to figure out the direction?
> >>>>
> >>>
> >>> I guess it is ok. But I'm wondering if the direction shouldn't depend on
> >>> the CPU dai rather than the CODEC dai? E.g. it is possible to have a
> >>> CODEC with both playback and capture support in two dai_links, one for
> >>> capture, one for playback. The check above would create a
> >>> SND_COMPRESS_PLAYBACK stream in both cases. Even if the CPU dai only
> >>> supported capture in one of the cases.
> >>
> >> OK, I'll use the cpu_dai then.
> > 
> > Lets wait for Vinod's feedback on this first. He knows this code best 
> > and what the intentions are.
> 
> Sure, but he was the first one to propose using that :-)
cpu_dai should be okay :)

BUT Now thinking over this again, does this make sense do do with multiple
codecs??

For folks haveing decoders in DSP inside SoC, the compressed device will be
actually a FE. The BE will be PCM to which codec would be linked. The folks
supporting decoders inside codec like WM wont ever need this.

Mark, do you agree to this?

So re-thinking again on why we need this??
Mark Brown July 3, 2014, 12:18 p.m. UTC | #18
On Thu, Jul 03, 2014 at 05:36:13PM +0530, Vinod Koul wrote:
> On Thu, Jul 03, 2014 at 01:46:23PM +0200, Benoit Cousson wrote:
> > On 03/07/2014 13:43, Lars-Peter Clausen wrote:
> > > On 07/03/2014 01:39 PM, Benoit Cousson wrote:
> > >> On 03/07/2014 13:20, Lars-Peter Clausen wrote:
> > >>> On 07/03/2014 01:09 PM, Benoit Cousson wrote:
> > >>>> On 03/07/2014 08:41, Vinod Koul wrote:
> > >>>>> On Wed, Jul 02, 2014 at 02:53:50PM +0200, Benoit Cousson wrote:

People, please delete irrelevant context from your e-mails - it makes it
easier to find the new content.

> BUT Now thinking over this again, does this make sense do do with multiple
> codecs??

> For folks haveing decoders in DSP inside SoC, the compressed device will be
> actually a FE. The BE will be PCM to which codec would be linked. The folks
> supporting decoders inside codec like WM wont ever need this.

> Mark, do you agree to this?

> So re-thinking again on why we need this??

The use case tends to be for applications that have one device per
physical output.  This isn't normally mobile, it's normally high
performance audio applications where people are doing things to try to
electrically isolate the analogue outputs or dealing with high power so
need to keep speaker outputs physically separate.  I can imagine set top
box type applications (which do use offloaded media decode) doing this.
Vinod Koul July 3, 2014, 4:15 p.m. UTC | #19
On Thu, Jul 03, 2014 at 01:18:46PM +0100, Mark Brown wrote:
> > BUT Now thinking over this again, does this make sense do do with multiple
> > codecs??
> 
> > For folks haveing decoders in DSP inside SoC, the compressed device will be
> > actually a FE. The BE will be PCM to which codec would be linked. The folks
> > supporting decoders inside codec like WM wont ever need this.
> 
> > Mark, do you agree to this?
> 
> > So re-thinking again on why we need this??
> 
> The use case tends to be for applications that have one device per
> physical output.  This isn't normally mobile, it's normally high
> performance audio applications where people are doing things to try to
> electrically isolate the analogue outputs or dealing with high power so
> need to keep speaker outputs physically separate.  I can imagine set top
> box type applications (which do use offloaded media decode) doing this.

Not sure if I follow you, I have no idea of how these systems work.

But if sound card has compressed device it would need to represent using DPCM as
we don't know the decoder PCM output. The multiple codecs would then connect to
the PCM BE. 
So on Compressed FE, we wont have multiple codecs.

For codecs, the compressed audio will go to one codec, multiple ones wont make
sense.

So how can we have a situation where we have compressed device linked to
multiple codecs?
Lars-Peter Clausen July 3, 2014, 6:23 p.m. UTC | #20
On 07/03/2014 06:15 PM, Vinod Koul wrote:
> On Thu, Jul 03, 2014 at 01:18:46PM +0100, Mark Brown wrote:
>>> BUT Now thinking over this again, does this make sense do do with multiple
>>> codecs??
>>
>>> For folks haveing decoders in DSP inside SoC, the compressed device will be
>>> actually a FE. The BE will be PCM to which codec would be linked. The folks
>>> supporting decoders inside codec like WM wont ever need this.
>>
>>> Mark, do you agree to this?
>>
>>> So re-thinking again on why we need this??
>>
>> The use case tends to be for applications that have one device per
>> physical output.  This isn't normally mobile, it's normally high
>> performance audio applications where people are doing things to try to
>> electrically isolate the analogue outputs or dealing with high power so
>> need to keep speaker outputs physically separate.  I can imagine set top
>> box type applications (which do use offloaded media decode) doing this.
>
> Not sure if I follow you, I have no idea of how these systems work.
>
> But if sound card has compressed device it would need to represent using DPCM as
> we don't know the decoder PCM output. The multiple codecs would then connect to
> the PCM BE.
> So on Compressed FE, we wont have multiple codecs.
>
> For codecs, the compressed audio will go to one codec, multiple ones wont make
> sense.
>
> So how can we have a situation where we have compressed device linked to
> multiple codecs?
>

If the assumption is that a DAI link that has a compressed DAI on the CPU side 
is never connected to a 'real' CODEC (or multiple CODECS) on the CODEC side. I 
think we can just leave soc-compress.c alone and just add a sanity check to 
make sure that num_codecs is always 1.

- Lars
Mark Brown July 3, 2014, 6:38 p.m. UTC | #21
On Thu, Jul 03, 2014 at 09:45:17PM +0530, Vinod Koul wrote:
> On Thu, Jul 03, 2014 at 01:18:46PM +0100, Mark Brown wrote:

> > The use case tends to be for applications that have one device per
> > physical output.  This isn't normally mobile, it's normally high
> > performance audio applications where people are doing things to try to
> > electrically isolate the analogue outputs or dealing with high power so
> > need to keep speaker outputs physically separate.  I can imagine set top
> > box type applications (which do use offloaded media decode) doing this.

> Not sure if I follow you, I have no idea of how these systems work.

They're having the SoC play stereo (or whatever) data and then having
multiple CODECs on the bus, each parsing some subset of the channels
(typically one channel per CODEC).

> So how can we have a situation where we have compressed device linked to
> multiple codecs?

If it's intended to be DPCM only (which it iss now I think about it) it
sounds like you can't have it linked to *any* real CODECS, at least not
directly!
Pierre-Louis Bossart July 3, 2014, 7:09 p.m. UTC | #22
>>> The use case tends to be for applications that have one device per
>>> physical output.  This isn't normally mobile, it's normally high
>>> performance audio applications where people are doing things to try to
>>> electrically isolate the analogue outputs or dealing with high power so
>>> need to keep speaker outputs physically separate.  I can imagine set top
>>> box type applications (which do use offloaded media decode) doing this.
>
>> Not sure if I follow you, I have no idea of how these systems work.
>
> They're having the SoC play stereo (or whatever) data and then having
> multiple CODECs on the bus, each parsing some subset of the channels
> (typically one channel per CODEC).

This sort of stream aggregation/split is a very valid use case that's 
coming to mobiles in the very near future with new interfaces being 
standardized.

>
>> So how can we have a situation where we have compressed device linked to
>> multiple codecs?
>
> If it's intended to be DPCM only (which it iss now I think about it) it
> sounds like you can't have it linked to *any* real CODECS, at least not
> directly!

there are very few references to codec_dais in soc-compress and some are 
in sections copy/pasted from soc-pcm, which makes me wonder as well if 
they needed to be there in the first place.
-Pierre
Benoit Cousson July 4, 2014, 1:55 p.m. UTC | #23
On 03/07/2014 20:23, Lars-Peter Clausen wrote:

[...]

> If the assumption is that a DAI link that has a compressed DAI on the
> CPU side is never connected to a 'real' CODEC (or multiple CODECS) on
> the CODEC side. I think we can just leave soc-compress.c alone and just
> add a sanity check to make sure that num_codecs is always 1.

OK, I'll repost the series without any change on soc-compress.c beside a 
test.

Thanks,
Benoit

Patch
diff mbox

diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index f96fb96..cd65b12 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -155,14 +155,17 @@  static void close_delayed_work(struct work_struct *work)
 {
 	struct snd_soc_pcm_runtime *rtd =
 			container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	int i;
 
 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
-	dev_dbg(rtd->dev, "ASoC: pop wq checking: %s status: %s waiting: %s\n",
-		 codec_dai->driver->playback.stream_name,
-		 codec_dai->playback_active ? "active" : "inactive",
-		 rtd->pop_wait ? "yes" : "no");
+	for (i = 0; i < rtd->num_codecs; i++) {
+		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
+		dev_dbg(rtd->dev, "ASoC: pop wq checking: %s status: %s waiting: %s\n",
+			 codec_dai->driver->playback.stream_name,
+			 codec_dai->playback_active ? "active" : "inactive",
+			 rtd->pop_wait ? "yes" : "no");
+	}
 
 	/* are we waiting on this codec DAI stream */
 	if (rtd->pop_wait == 1) {
@@ -179,8 +182,7 @@  static int soc_compr_free(struct snd_compr_stream *cstream)
 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 	struct snd_soc_platform *platform = rtd->platform;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	int stream;
+	int stream, i;
 
 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
@@ -191,14 +193,18 @@  static int soc_compr_free(struct snd_compr_stream *cstream)
 
 	snd_soc_runtime_deactivate(rtd, stream);
 
-	snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
+	for (i = 0; i < rtd->num_codecs; i++) {
+		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
+
+		snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
+
+		if (!codec_dai->active)
+			codec_dai->rate = 0;
+	}
 
 	if (!cpu_dai->active)
 		cpu_dai->rate = 0;
 
-	if (!codec_dai->active)
-		codec_dai->rate = 0;
-
 
 	if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown)
 		rtd->dai_link->compr_ops->shutdown(cstream);
@@ -283,8 +289,7 @@  static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
 
 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 	struct snd_soc_platform *platform = rtd->platform;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	int ret = 0;
+	int i, ret = 0;
 
 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
@@ -294,13 +299,19 @@  static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
 			goto out;
 	}
 
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		snd_soc_dai_digital_mute(codec_dai, 0, cstream->direction);
-		break;
-	case SNDRV_PCM_TRIGGER_STOP:
-		snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
-		break;
+	for (i = 0; i < rtd->num_codecs; i++) {
+		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
+
+		switch (cmd) {
+		case SNDRV_PCM_TRIGGER_START:
+			snd_soc_dai_digital_mute(codec_dai, 0,
+						 cstream->direction);
+			break;
+		case SNDRV_PCM_TRIGGER_STOP:
+			snd_soc_dai_digital_mute(codec_dai, 1,
+						 cstream->direction);
+			break;
+		}
 	}
 
 out:
@@ -622,23 +633,33 @@  int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
 {
 	struct snd_soc_codec *codec = rtd->codec;
 	struct snd_soc_platform *platform = rtd->platform;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	struct snd_compr *compr;
 	struct snd_pcm *be_pcm;
 	char new_name[64];
-	int ret = 0, direction = 0;
-
-	/* check client and interface hw capabilities */
-	snprintf(new_name, sizeof(new_name), "%s %s-%d",
-			rtd->dai_link->stream_name, codec_dai->name, num);
-
-	if (codec_dai->driver->playback.channels_min)
-		direction = SND_COMPRESS_PLAYBACK;
-	else if (codec_dai->driver->capture.channels_min)
-		direction = SND_COMPRESS_CAPTURE;
-	else
-		return -EINVAL;
+	int i, ret = 0, direction = -1;
+
+	for (i = 0; i < rtd->num_codecs; i++) {
+		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
+		/* check client and interface hw capabilities */
+		snprintf(new_name, sizeof(new_name), "%s %s-%d",
+			 rtd->dai_link->stream_name, codec_dai->name, num);
+
+		if (direction < 0) {
+			if (codec_dai->driver->playback.channels_min)
+				direction = SND_COMPRESS_PLAYBACK;
+			else if (codec_dai->driver->capture.channels_min)
+				direction = SND_COMPRESS_CAPTURE;
+			else
+				return -EINVAL;
+		} else {
+			if ((codec_dai->driver->playback.channels_min &&
+					direction != SND_COMPRESS_PLAYBACK) ||
+			    (codec_dai->driver->capture.channels_min &&
+					direction != SND_COMPRESS_CAPTURE))
+				return -EINVAL;
+		}
+	}
 
 	compr = kzalloc(sizeof(*compr), GFP_KERNEL);
 	if (compr == NULL) {
@@ -692,8 +713,11 @@  int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
 	rtd->compr = compr;
 	compr->private_data = rtd;
 
-	printk(KERN_INFO "compress asoc: %s <-> %s mapping ok\n", codec_dai->name,
-		cpu_dai->name);
+	for (i = 0; i < rtd->num_codecs; i++) {
+		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
+		printk(KERN_INFO "compress asoc: %s <-> %s mapping ok\n",
+		       codec_dai->name, cpu_dai->name);
+	}
 	return ret;
 
 compr_err: