diff mbox

[v6,3/3] ASoC: Add multiple CPU DAI support in DAPM

Message ID 1529492057-32627-4-git-send-email-shreyas.nc@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Shreyas NC June 20, 2018, 10:54 a.m. UTC
DAPM handles DAIs during soc_dapm_stream_event() and during addition
and creation of DAI widgets i.e., dapm_add_valid_dai_widget() and
dapm_connect_dai_link_widgets().

Extend these functions to handle multiple cpu dai.

Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Shreyas NC <shreyas.nc@intel.com>
---
 sound/soc/soc-dapm.c | 71 ++++++++++++++++++++++++++++++++++------------------
 1 file changed, 46 insertions(+), 25 deletions(-)

Comments

Pierre-Louis Bossart June 22, 2018, 2:55 a.m. UTC | #1
On 06/20/2018 05:54 AM, Shreyas NC wrote:
> DAPM handles DAIs during soc_dapm_stream_event() and during addition
> and creation of DAI widgets i.e., dapm_add_valid_dai_widget() and
> dapm_connect_dai_link_widgets().
can you split this patch in two, one where you add 
dapm_add_valid_dai_widget() and the second one where you add the 
multi-cpu stuff? the current diff format is really hard to read with the 
two changes lumped together.

> +	for (i = 0; i < rtd->num_codecs; i++) {
> +		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
> +
> +		for (j = 0; j < rtd->num_cpu_dai; j++) {
> +			cpu_dai = rtd->cpu_dais[j];
> +
> +			dapm_add_valid_dai_widget(card, rtd,
> +						codec_dai, cpu_dai);

I didn't click on this earlier, but what makes you think all codec_dais 
are connected to all cpu_dais?
That doesn't seem quite right.
For the multi-codec case, all the codec_dais hang from a single cpu_dai. 
it's a stretch for me to have a full M:N connectivity. And that's 
clearly not the case for SoundWire stream in the multi-link case.
Can't we use the dai_link information here to only connect cpu_ and 
codec_dais that are related?

>   		}
>   	}
>   }
> @@ -4211,7 +4230,9 @@ static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
>   {
>   	int i;
>   
> -	soc_dapm_dai_stream_event(rtd->cpu_dai, stream, event);
> +	for (i = 0; i < rtd->num_cpu_dai; i++)
> +		soc_dapm_dai_stream_event(rtd->cpu_dais[i], stream, event);
> +
>   	for (i = 0; i < rtd->num_codecs; i++)
>   		soc_dapm_dai_stream_event(rtd->codec_dais[i], stream, event);
>
Shreyas NC June 22, 2018, 5:53 a.m. UTC | #2
On Thu, Jun 21, 2018 at 09:55:54PM -0500, Pierre-Louis Bossart wrote:
> 
> 
> On 06/20/2018 05:54 AM, Shreyas NC wrote:
> >DAPM handles DAIs during soc_dapm_stream_event() and during addition
> >and creation of DAI widgets i.e., dapm_add_valid_dai_widget() and
> >dapm_connect_dai_link_widgets().
> can you split this patch in two, one where you add
> dapm_add_valid_dai_widget() and the second one where you add the multi-cpu
> stuff? the current diff format is really hard to read with the two changes
> lumped together.

As I had replied earlier, the change is really moving the same code from one
function to a new one. So, a patch split would mean we would have the same
duplicated code in one patch which surely is not desirable.

I just realized that in my earlier reply I had excluded the list and replied
only to you :)

> 
> >+	for (i = 0; i < rtd->num_codecs; i++) {
> >+		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
> >+
> >+		for (j = 0; j < rtd->num_cpu_dai; j++) {
> >+			cpu_dai = rtd->cpu_dais[j];
> >+
> >+			dapm_add_valid_dai_widget(card, rtd,
> >+						codec_dai, cpu_dai);
> 
> I didn't click on this earlier, but what makes you think all codec_dais are
> connected to all cpu_dais?

Yes, there need not be a M:N connectivity. But, how do you find that out ?

> That doesn't seem quite right.
> For the multi-codec case, all the codec_dais hang from a single cpu_dai.
> it's a stretch for me to have a full M:N connectivity. And that's clearly
> not the case for SoundWire stream in the multi-link case.

I mostly do not disagree with you here..

> Can't we use the dai_link information here to only connect cpu_ and
> codec_dais that are related?

Which DAI Link information are you referring to here ?
Other than the machine driver which sets the audio route, I am unable to
figure out how we will find out the connected cpu_dai and codec_dais at
ASoC core level.

May be I am missing something :(

--Shreyas
Pierre-Louis Bossart June 22, 2018, 4:18 p.m. UTC | #3
On 6/22/18 12:53 AM, Shreyas NC wrote:
> On Thu, Jun 21, 2018 at 09:55:54PM -0500, Pierre-Louis Bossart wrote:
>>
>>
>> On 06/20/2018 05:54 AM, Shreyas NC wrote:
>>> DAPM handles DAIs during soc_dapm_stream_event() and during addition
>>> and creation of DAI widgets i.e., dapm_add_valid_dai_widget() and
>>> dapm_connect_dai_link_widgets().
>> can you split this patch in two, one where you add
>> dapm_add_valid_dai_widget() and the second one where you add the multi-cpu
>> stuff? the current diff format is really hard to read with the two changes
>> lumped together.
> 
> As I had replied earlier, the change is really moving the same code from one
> function to a new one. So, a patch split would mean we would have the same
> duplicated code in one patch which surely is not desirable.

I don't understand your answer. It's fine to have a small preparation 
patch that just moves one piece of code to another function, and they 
change how that function is called.

> I just realized that in my earlier reply I had excluded the list and replied
> only to you :)
> 
>>
>>> +	for (i = 0; i < rtd->num_codecs; i++) {
>>> +		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
>>> +
>>> +		for (j = 0; j < rtd->num_cpu_dai; j++) {
>>> +			cpu_dai = rtd->cpu_dais[j];
>>> +
>>> +			dapm_add_valid_dai_widget(card, rtd,
>>> +						codec_dai, cpu_dai);
>>
>> I didn't click on this earlier, but what makes you think all codec_dais are
>> connected to all cpu_dais?
> 
> Yes, there need not be a M:N connectivity. But, how do you find that out ?
> 
>> That doesn't seem quite right.
>> For the multi-codec case, all the codec_dais hang from a single cpu_dai.
>> it's a stretch for me to have a full M:N connectivity. And that's clearly
>> not the case for SoundWire stream in the multi-link case.
> 
> I mostly do not disagree with you here..
> 
>> Can't we use the dai_link information here to only connect cpu_ and
>> codec_dais that are related?
> 
> Which DAI Link information are you referring to here ?
> Other than the machine driver which sets the audio route, I am unable to
> figure out how we will find out the connected cpu_dai and codec_dais at
> ASoC core level.
> 
> May be I am missing something :(

How is it different from the multi-codec support? You must have a 
description somewhere that tells you how the cpu_dai is connected to 
various codec_dais.

Maybe we should start with the examples you provided for Soundwire and 
describe how the dailinks would be represented.

With the M:N connectivity you'd end-up having spurious events with 
non-existent connections, it's not necessarily fatal but certainly not 
elegant and may or may not work depending on state management in codec 
drivers.
Shreyas NC June 26, 2018, 10:35 a.m. UTC | #4
> >>>DAPM handles DAIs during soc_dapm_stream_event() and during addition
> >>>and creation of DAI widgets i.e., dapm_add_valid_dai_widget() and
> >>>dapm_connect_dai_link_widgets().
> >>can you split this patch in two, one where you add
> >>dapm_add_valid_dai_widget() and the second one where you add the multi-cpu
> >>stuff? the current diff format is really hard to read with the two changes
> >>lumped together.
> >
> >As I had replied earlier, the change is really moving the same code from one
> >function to a new one. So, a patch split would mean we would have the same
> >duplicated code in one patch which surely is not desirable.
> 
> I don't understand your answer. It's fine to have a small preparation patch
> that just moves one piece of code to another function, and they change how
> that function is called.
> 

Ok, I will give it a try :)

> >I just realized that in my earlier reply I had excluded the list and replied
> >only to you :)
> >
> >>
> >>>+	for (i = 0; i < rtd->num_codecs; i++) {
> >>>+		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
> >>>+
> >>>+		for (j = 0; j < rtd->num_cpu_dai; j++) {
> >>>+			cpu_dai = rtd->cpu_dais[j];
> >>>+
> >>>+			dapm_add_valid_dai_widget(card, rtd,
> >>>+						codec_dai, cpu_dai);
> >>
> >>I didn't click on this earlier, but what makes you think all codec_dais are
> >>connected to all cpu_dais?
> >
> >Yes, there need not be a M:N connectivity. But, how do you find that out ?
> >
> >>That doesn't seem quite right.
> >>For the multi-codec case, all the codec_dais hang from a single cpu_dai.
> >>it's a stretch for me to have a full M:N connectivity. And that's clearly
> >>not the case for SoundWire stream in the multi-link case.
> >
> >I mostly do not disagree with you here..
> >
> >>Can't we use the dai_link information here to only connect cpu_ and
> >>codec_dais that are related?
> >
> >Which DAI Link information are you referring to here ?
> >Other than the machine driver which sets the audio route, I am unable to
> >figure out how we will find out the connected cpu_dai and codec_dais at
> >ASoC core level.
> >
> >May be I am missing something :(
> 
> How is it different from the multi-codec support? You must have a
> description somewhere that tells you how the cpu_dai is connected to various
> codec_dais.
> 

No, there is no such description that I could find.

My reference was skl_nau88l25_ssm4567.c machine driver:

/* Back End DAI links */
        {
                /* SSP0 - Codec */
                .name = "SSP0-Codec",
                .id = 0,
                .cpu_dai_name = "SSP0 Pin",
                .platform_name = "0000:00:1f.3",
                .no_pcm = 1,
                .codecs = ssm4567_codec_components,
                .num_codecs = ARRAY_SIZE(ssm4567_codec_components),
                ..
        },

The only way I could infer the connection was from DAPM route:
{
        /* CODEC BE connections */
        { "Left Playback", NULL, "ssp0 Tx"},
        { "Right Playback", NULL, "ssp0 Tx"},
        { "ssp0 Tx", NULL, "codec0_out"},
}

> Maybe we should start with the examples you provided for Soundwire and
> describe how the dailinks would be represented.
> 

Ok , sure. Let me describe a case where we would want to play a 2 ch stream
and we have two Masters "int-sdw.1" and "int-sdw.2"

So, DAI Link would look this way:

Here I specify the multi CPU DAIs
static struct snd_soc_dai_link_component sdw_multi_cpu_comp[] = {
        { /* Left */
                .name = "int-sdw.1",
                .dai_name = "SDW1 Pin0",
        },
        { /* Right */
                .name = "int-sdw.2",
                .dai_name = "SDW2 Pin0",
        },
};

static struct snd_soc_codec_conf rt700_codec_conf[] = {
        {
                .dev_name = "sdw:1:25d:700:0:0",
                .name_prefix = "Left",
        },
        {
                .dev_name = "sdw:2:25d:701:0:0",
                .name_prefix = "Right",
        },
};

And the DAI Link as:
struct snd_soc_dai_link cnl_rt700_msic_dailink[] = {
{
        ...
        {
                .name = "SDW0-Codec",
                .cpu_dai = sdw_multi_cpu_comp,
                .num_cpu_dai = ARRAY_SIZE(sdw_multi_cpu_comp),
                .platform_name = "0000:00:1f.3",
                .codecs = sdw_multi_codec_comp,
                .num_codecs = ARRAY_SIZE(sdw_multi_codec_comp),
	..
        },
}

And it is in the DAPM route that I would specify :
{
         ...
        { "Left DP1 Playback", NULL, "SDW1 Tx0"},
        { "SDW1 Tx0", NULL, "codec0_out"},

        { "Right DP1 Playback", NULL, "SDW2 Tx0"},
        { "SDW2 Tx0", NULL, "codec0_out"},
        ...
}

> With the M:N connectivity you'd end-up having spurious events with
> non-existent connections, it's not necessarily fatal but certainly not
> elegant and may or may not work depending on state management in codec
> drivers.
>

What are the events that you are referring to here?
The reason I ask that is because my understanding is that we will get these
events only for those widgets marked connected by DAPM after parsing the DAPM
route map.
I will check further if you can let me know of the events you are suspecting
:)

Sorry for the longish mail. I thought it would be better to put in the
details rather than go back and forth over them :)

--Shreyas
>
diff mbox

Patch

diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index a099c3e..865c47f 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -4113,38 +4113,57 @@  int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
 	return 0;
 }
 
-static void dapm_connect_dai_link_widgets(struct snd_soc_card *card,
-					  struct snd_soc_pcm_runtime *rtd)
+static void dapm_add_valid_dai_widget(struct snd_soc_card *card,
+					struct snd_soc_pcm_runtime *rtd,
+					struct snd_soc_dai *codec_dai,
+					struct snd_soc_dai *cpu_dai)
 {
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	struct snd_soc_dapm_widget *sink, *source;
-	int i;
 
-	for (i = 0; i < rtd->num_codecs; i++) {
-		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
+	/* connect BE DAI playback if widgets are valid */
+	if (codec_dai->playback_widget && cpu_dai->playback_widget) {
+		source = cpu_dai->playback_widget;
+		sink = codec_dai->playback_widget;
+		dev_err(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
+				cpu_dai->component->name,
+				source->name,
+				codec_dai->component->name,
+				sink->name);
+
+		snd_soc_dapm_add_path(&card->dapm, source, sink,
+				NULL, NULL);
+	}
 
-		/* connect BE DAI playback if widgets are valid */
-		if (codec_dai->playback_widget && cpu_dai->playback_widget) {
-			source = cpu_dai->playback_widget;
-			sink = codec_dai->playback_widget;
-			dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
-				cpu_dai->component->name, source->name,
-				codec_dai->component->name, sink->name);
+	/* connect BE DAI capture if widgets are valid */
+	if (codec_dai->capture_widget && cpu_dai->capture_widget) {
+		source = codec_dai->capture_widget;
+		sink = cpu_dai->capture_widget;
+		dev_err(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
+				codec_dai->component->name,
+				source->name,
+				cpu_dai->component->name,
+				sink->name);
 
-			snd_soc_dapm_add_path(&card->dapm, source, sink,
+		snd_soc_dapm_add_path(&card->dapm, source, sink,
 				NULL, NULL);
-		}
+	}
+
+}
 
-		/* connect BE DAI capture if widgets are valid */
-		if (codec_dai->capture_widget && cpu_dai->capture_widget) {
-			source = codec_dai->capture_widget;
-			sink = cpu_dai->capture_widget;
-			dev_dbg(rtd->dev, "connected DAI link %s:%s -> %s:%s\n",
-				codec_dai->component->name, source->name,
-				cpu_dai->component->name, sink->name);
+static void dapm_connect_dai_link_widgets(struct snd_soc_card *card,
+					  struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_dai *cpu_dai;
+	int i, j;
 
-			snd_soc_dapm_add_path(&card->dapm, source, sink,
-				NULL, NULL);
+	for (i = 0; i < rtd->num_codecs; i++) {
+		struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
+
+		for (j = 0; j < rtd->num_cpu_dai; j++) {
+			cpu_dai = rtd->cpu_dais[j];
+
+			dapm_add_valid_dai_widget(card, rtd,
+						codec_dai, cpu_dai);
 		}
 	}
 }
@@ -4211,7 +4230,9 @@  static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
 {
 	int i;
 
-	soc_dapm_dai_stream_event(rtd->cpu_dai, stream, event);
+	for (i = 0; i < rtd->num_cpu_dai; i++)
+		soc_dapm_dai_stream_event(rtd->cpu_dais[i], stream, event);
+
 	for (i = 0; i < rtd->num_codecs; i++)
 		soc_dapm_dai_stream_event(rtd->codec_dais[i], stream, event);