All of lore.kernel.org
 help / color / mirror / Atom feed
* Confusing about Playback/Capture, CODEC/CODEC links, and snd_soc_dapm_link_dai_widgets()
@ 2012-05-31 22:49 Stephen Warren
  2012-05-31 23:37 ` Mark Brown
  2012-06-05 20:24 ` Stephen Warren
  0 siblings, 2 replies; 11+ messages in thread
From: Stephen Warren @ 2012-05-31 22:49 UTC (permalink / raw)
  To: Mark Brown, Liam Girdwood; +Cc: alsa-devel@alsa-project.org

Mark, Liam,

recall the Tegra AHUB structure:

> +-------------+   +-----+   +--------------+   +-----+   +------+
> | FIFO pair 0 |<->| CIF |<->| Cross-bar    |<->| CIF |<->| I2S0 |<-> External IO
> +-------------+   +-----+   | (the "AHUB") |   +-----+   +------+
>               . . .         |              |         . . .
> +-------------+   +-----+   |              |   +-----+   +------+
> | FIFO pair 3 |<->| CIF |<->|              |<->| CIF |<->| I2S4 |<-> External IO
> +-------------+   +-----+   |              |   +-----+   +------+
>                             |              |
>                             |              |   +-----+   +-------+
>                             |              |<->| CIF |<->| SPDIF |<-> External IO
>                             |              |   +-----+   +-------+
>                             |              |
>                             |              |   +-----+   +-------+
>                             |              |<->| CIF |<->| DAM   |
>                             |              |   +-----+   +-------+
>                             +--------------+

(CIF is AHUB XBAR Client InterFace; basically the DAI or DAI link)

I have created a driver for the 4 FIFOs on the left, which exposes 4
(CPU) DAIs.

I have created a driver for the AHUB XBAR, which is an ASoC CODEC, and
has a DAI for each of the CIFs.

There's a CODEC/CODEC link between each FIFO DAI and the relevant AHUB
CIF DAI.

In order to connect the I2S devices to the AHUB XBAR, I had to make that
a CODEC too. This exposes two DAIs; the CIF DAI to connect to the AHUB,
and the DAP (Digital Audio Port) DAI to represent the I/O pins on the
Tegra package that are connected to the external codec.

I have an issue with the paths that snd_soc_dapm_link_dai_widgets() sets
up inside both the AHUB XBAR and the I2S. I'll use the I2S to explain
since it's internally much simpler.

The two DAIs in I2S are roughly:

> static const struct snd_soc_dai_driver tegra30_i2s_dais[] = {
>     {
> 	.playback = {
> 		.stream_name = "DAP Playback",
> 	},
> 	.capture = {
> 		.stream_name = "DAP Capture",
> 	},
>     },
>     {
> 	.playback = {
> 		.stream_name = "CIF Playback",
> 	},
> 	.capture = {
> 		.stream_name = "CIF Capture",
> 	},
>     },
> };

For the CIF-side DAI, I instantiated widgets for the AIFs:

> static const struct snd_soc_dapm_widget tegra30_i2s_widgets[] = {
> 	SND_SOC_DAPM_AIF_IN("CIF RX", "CIF Playback", 0, SND_SOC_NOPM, 0, 0),
> 	SND_SOC_DAPM_AIF_OUT("CIF TX", "CIF Capture", 0, SND_SOC_NOPM, 0, 0),

This works fine; snd_soc_dapm_link_dai_widgets() create a route from the
DAI widget "DAP Playback" that feeds into the AIF_IN widget "CIF RX".

"works fine" means that the ASoC debugfs files in
"asoc/$card/tegra30-i2s.1/dapm/CIF {Playback,RX}" show the expected
connections.

The DAPM routes inside the I2S are:

> static const struct snd_soc_dapm_route tegra30_i2s_routes[] = {
> 	{ "DAP TX", NULL, "CIF RX" },
> 	{ "CIF TX", NULL, "DAP RX" },
> };

This also works fine.

Now, I instantiated two AIF widgets to interface with the DAP-side DAI:

> 	SND_SOC_DAPM_AIF_IN("DAP RX", "DAP Capture", 0, SND_SOC_NOPM, 0, 0),
> 	SND_SOC_DAPM_AIF_OUT("DAP TX", "DAP Playback", 0, SND_SOC_NOPM, 0, 0),

However, this causes snd_soc_dapm_link_dai_widgets() to set up some
unexpected paths; "DAP Playback" ends up feeding *into* "DAP TX", rather
than feeding from/out of it...

> # cat CIF\ Playback 
> CIF Playback: Off  in 0 out 0
>  stream CIF Playback inactive
>  out "static" "CIF RX"
>  out "static" "CIF RX"
> # cat CIF\ RX
> CIF RX: Off  in 0 out 0
>  stream CIF Playback inactive
>  in  "static" "CIF Playback"
>  in  "static" "CIF Playback"
>  out "static" "DAP TX"
> # cat DAP\ TX
> DAP TX: Off  in 0 out 0
>  stream DAP Playback inactive
>  in  "static" "DAP Playback"      <<<<<<<<<<
>  in  "static" "DAP Playback"      <<<<<<<<<<
>  in  "static" "CIF RX"
> # cat DAP\ Playback 
> DAP Playback: Off  in 0 out 0
>  stream DAP Playback inactive
>  out "static" "DAP TX"
>  out "static" "DAP TX"

Now, I can fake this out by swapping the stream names on the DAP-side
AIF widgets:

> 	SND_SOC_DAPM_AIF_IN("DAP RX", "DAP Playback", 0, SND_SOC_NOPM, 0, 0),
> 	SND_SOC_DAPM_AIF_OUT("DAP TX", "DAP Capture", 0, SND_SOC_NOPM, 0, 0),

Which yields the expected paths in debugfs:

> # cat CIF\ Playback 
> CIF Playback: Off  in 0 out 0
>  stream CIF Playback inactive
>  out "static" "CIF RX"
>  out "static" "CIF RX"
> # cat CIF\ RX
> CIF RX: Off  in 0 out 0
>  stream CIF Playback inactive
>  in  "static" "CIF Playback"
>  in  "static" "CIF Playback"
>  out "static" "DAP TX"
> # cat DAP\ TX
> DAP TX: Off  in 0 out 0
>  stream DAP Capture inactive
>  in  "static" "CIF RX"
>  out "static" "DAP Capture"
>  out "static" "DAP Capture"
> # cat DAP\ Capture 
> DAP Capture: Off  in 0 out 0
>  stream DAP Capture inactive
>  in  "static" "DAP TX"
>  in  "static" "DAP TX"

But I'm not sure if that's quite correct. In the DAI definitions, is the
.playback sub-structure always meant to represent:

1) Playback from the CPU's perspective, in which case the first set of
DAP AIF definitions above would be correct

or:

2) Is it more that Playback==RX_into_codec, Capture==TX_from_codec? This
appears to be supported by the fact that the paths get set up correctly
with the second set of AIF definitions above.

But if (2) is correct, I wonder why soc_dapm_stream_event()'s first if
statement appears to consider the playback_widget of both sides of the
DAI to be coupled; wouldn't one side's playback widget be coupled to the
other side's capture widget?

As an aside, I'm not sure if it's conceptually correct to talk about
playback or capture any more (beyond the initial CPU DAI) with arbitrary
CODEC/CODEC links, since who knows what kind of routing/CPU->CPU
loopbacks/external CODEC->CODEC loopbacks/... might exist in the CODECs?

Either way though, something is still not working correctly even when
the expected paths show up in debugfs. When I start playback on a PCM
exposed by the DMA FIFO driver, I see the relevant AHUB XBAR's stream
turned on, and a route exists to the relevant AIF_IN widget, but that
widget is not considered to have any outward connections by
is_connected_output_ep(), which I think is what is causing it and none
of the rest of the path to turn on:

(from asoc/$card/asoc/tegra30-ahub-xbar/dapm)

> # cat APBIF0\ Playback 
> APBIF0 Playback: On  in 1 out 1
>  stream APBIF0 Playback active
>  out "static" "APBIF0 RX"
>  out "static" "APBIF0 RX"
> # cat APBIF0\ RX
> APBIF0 RX: Off  in 2 out 0       <<<<< last value shouldn't be 0?
>  stream APBIF0 Playback inactive <<<<< still inactive?
>  in  "static" "APBIF0 Playback"
>  in  "static" "APBIF0 Playback"
>  out "APBIF0 RX" "I2S0 TX Mux"

even though when I look at all the debugfs files, all the expected paths
are there, at least within the AHUB XBAR and I2S drivers, and the
external DAI links in the machine driver all probed as expected and
bound all the components together.

Probably related, the I2S and WM8903 (DAI) drivers aren't being called
by the ASoC core to initialize themselves for playback either; pretty
much all that happens is that DMA is started. Is the machine driver
responsible for this?

At this point, I'm not sure whether I have a gross mis-understanding of
how this is supposed to work, or whether there are simply bits missing
from the DAPM code to fully support CODEC/CODEC links, rather than
CPU/CODEC links.

Probably slightly related to all of this, but is the following code correct:

> int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
> 	struct snd_soc_dapm_widget_list **list)
...
> 	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
> 		paths = is_connected_output_ep(dai->playback_widget, list);
> 	else
> 		paths = is_connected_input_ep(dai->playback_widget, list);

I would have expected this to use capture_widget on the final line, but
I haven't thought about this in detail, just noticed the lack of
symmetry by very brief inspection.

Thanks for any help. Sorry for the long email.

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

* Re: Confusing about Playback/Capture, CODEC/CODEC links, and snd_soc_dapm_link_dai_widgets()
  2012-05-31 22:49 Confusing about Playback/Capture, CODEC/CODEC links, and snd_soc_dapm_link_dai_widgets() Stephen Warren
@ 2012-05-31 23:37 ` Mark Brown
  2012-06-01 17:01   ` Liam Girdwood
                     ` (2 more replies)
  2012-06-05 20:24 ` Stephen Warren
  1 sibling, 3 replies; 11+ messages in thread
From: Mark Brown @ 2012-05-31 23:37 UTC (permalink / raw)
  To: Stephen Warren; +Cc: alsa-devel@alsa-project.org, Liam Girdwood

On Thu, May 31, 2012 at 04:49:26PM -0600, Stephen Warren wrote:

> I have an issue with the paths that snd_soc_dapm_link_dai_widgets() sets
> up inside both the AHUB XBAR and the I2S. I'll use the I2S to explain
> since it's internally much simpler.

You shouldn't be using this at all for new code, you should be using
explicit DAPM routes to link to the widgets and specifying NULL
stream_name.

> 2) Is it more that Playback==RX_into_codec, Capture==TX_from_codec? This
> appears to be supported by the fact that the paths get set up correctly
> with the second set of AIF definitions above.

Yes.

> But if (2) is correct, I wonder why soc_dapm_stream_event()'s first if
> statement appears to consider the playback_widget of both sides of the
> DAI to be coupled; wouldn't one side's playback widget be coupled to the
> other side's capture widget?

The DAIs on CPUs have the opposite sense to DAIs on CODECs.  In a
traditional CPU<->CODEC link we do connect the two playback widgets
directly to each other.  The current code isn't correct, it's not
normally noticable since most of the time the CPU DAI end of the link is
a baseband which doesn't do anything real and is always activated
bidirectionally so it really makes no odds which widget we look at.

I'll fix this tomorrow.

> As an aside, I'm not sure if it's conceptually correct to talk about
> playback or capture any more (beyond the initial CPU DAI) with arbitrary
> CODEC/CODEC links, since who knows what kind of routing/CPU->CPU
> loopbacks/external CODEC->CODEC loopbacks/... might exist in the CODECs?

We could rename everything to RX and TX but it's a pain and going to be
annoying for backporting.

> Either way though, something is still not working correctly even when
> the expected paths show up in debugfs. When I start playback on a PCM
> exposed by the DMA FIFO driver, I see the relevant AHUB XBAR's stream
> turned on, and a route exists to the relevant AIF_IN widget, but that

Works for me.

> > # cat APBIF0\ Playback 
> > APBIF0 Playback: On  in 1 out 1
> >  stream APBIF0 Playback active
> >  out "static" "APBIF0 RX"
> >  out "static" "APBIF0 RX"
> > # cat APBIF0\ RX
> > APBIF0 RX: Off  in 2 out 0       <<<<< last value shouldn't be 0?
> >  stream APBIF0 Playback inactive <<<<< still inactive?
> >  in  "static" "APBIF0 Playback"
> >  in  "static" "APBIF0 Playback"
> >  out "APBIF0 RX" "I2S0 TX Mux"

So what's the rest of the route look like - what's I2S0 TX Mux look like
and so on?  For real widgets the number of outputs is a function of the
rest of the graph so you need to trace through that, clearly you want to
have some outputs but unless they are connected all the way back to an
input DAPM will leave everything powered off.  This is just like any
other DAPM widget in this regard, everything behaves just like an
analogue link.

> Probably related, the I2S and WM8903 (DAI) drivers aren't being called
> by the ASoC core to initialize themselves for playback either; pretty
> much all that happens is that DMA is started. Is the machine driver
> responsible for this?

No, of course not.  This is what soc_dapm_stream_event() is all about.
It looks like all that's happening is that since DAPM hasn't found a
complete route it didn't power anything (including the inter device
links) on.

> At this point, I'm not sure whether I have a gross mis-understanding of
> how this is supposed to work, or whether there are simply bits missing
> from the DAPM code to fully support CODEC/CODEC links, rather than
> CPU/CODEC links.

It's really hard to comment in much more detail, you've not shown enough
information.  What are the DAI links connecting the devices?  Is the
rest of the DAPM path through the system connected?  My best guess is
that (possibly due to the linking of the playback widgets) you don't
have a full DAPM path.

This is all working just fine in mainline on littlemill.

> > int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
> > 	struct snd_soc_dapm_widget_list **list)
> ...
> > 	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
> > 		paths = is_connected_output_ep(dai->playback_widget, list);
> > 	else
> > 		paths = is_connected_input_ep(dai->playback_widget, list);

> I would have expected this to use capture_widget on the final line, but
> I haven't thought about this in detail, just noticed the lack of
> symmetry by very brief inspection.

Yes, that looks buggy.  Don't think there's any mainline users so nobody
would notice.

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

* Re: Confusing about Playback/Capture, CODEC/CODEC links, and snd_soc_dapm_link_dai_widgets()
  2012-05-31 23:37 ` Mark Brown
@ 2012-06-01 17:01   ` Liam Girdwood
  2012-06-04 13:02     ` Sebastien LEDUC
  2012-06-01 21:41   ` Mark Brown
  2012-06-01 22:31   ` Confusion " Stephen Warren
  2 siblings, 1 reply; 11+ messages in thread
From: Liam Girdwood @ 2012-06-01 17:01 UTC (permalink / raw)
  To: Mark Brown; +Cc: alsa-devel@alsa-project.org, Stephen Warren

On Fri, 2012-06-01 at 00:37 +0100, Mark Brown wrote:
> On Thu, May 31, 2012 at 04:49:26PM -0600, Stephen Warren wrote:

> 
> This is all working just fine in mainline on littlemill.
> 
> > > int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
> > > 	struct snd_soc_dapm_widget_list **list)
> > ...
> > > 	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
> > > 		paths = is_connected_output_ep(dai->playback_widget, list);
> > > 	else
> > > 		paths = is_connected_input_ep(dai->playback_widget, list);
> 
> > I would have expected this to use capture_widget on the final line, but
> > I haven't thought about this in detail, just noticed the lack of
> > symmetry by very brief inspection.
> 
> Yes, that looks buggy.  Don't think there's any mainline users so nobody
> would notice.

Gah, it's a bug - I did have it fixed before the upstreaming but this
fix seems to have been lost.

Patch on it's way.

Liam

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

* Re: Confusing about Playback/Capture, CODEC/CODEC links, and snd_soc_dapm_link_dai_widgets()
  2012-05-31 23:37 ` Mark Brown
  2012-06-01 17:01   ` Liam Girdwood
@ 2012-06-01 21:41   ` Mark Brown
  2012-06-01 22:31   ` Confusion " Stephen Warren
  2 siblings, 0 replies; 11+ messages in thread
From: Mark Brown @ 2012-06-01 21:41 UTC (permalink / raw)
  To: Stephen Warren; +Cc: alsa-devel@alsa-project.org, Liam Girdwood


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

On Fri, Jun 01, 2012 at 12:37:09AM +0100, Mark Brown wrote:
> On Thu, May 31, 2012 at 04:49:26PM -0600, Stephen Warren wrote:

> > But if (2) is correct, I wonder why soc_dapm_stream_event()'s first if
> > statement appears to consider the playback_widget of both sides of the
> > DAI to be coupled; wouldn't one side's playback widget be coupled to the
> > other side's capture widget?

> The DAIs on CPUs have the opposite sense to DAIs on CODECs.  In a
> traditional CPU<->CODEC link we do connect the two playback widgets
> directly to each other.  The current code isn't correct, it's not
> normally noticable since most of the time the CPU DAI end of the link is
> a baseband which doesn't do anything real and is always activated
> bidirectionally so it really makes no odds which widget we look at.

> I'll fix this tomorrow.

Sorry, I misremembered the context here (should've looked at the code
not the quote!).  The current code is correct, it will only be used in
the case where we have a "real CPU" not the CODEC<->CODEC case so it's
doing the right thing.

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

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



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

* Re: Confusion about Playback/Capture, CODEC/CODEC links, and snd_soc_dapm_link_dai_widgets()
  2012-05-31 23:37 ` Mark Brown
  2012-06-01 17:01   ` Liam Girdwood
  2012-06-01 21:41   ` Mark Brown
@ 2012-06-01 22:31   ` Stephen Warren
  2 siblings, 0 replies; 11+ messages in thread
From: Stephen Warren @ 2012-06-01 22:31 UTC (permalink / raw)
  To: Mark Brown; +Cc: alsa-devel@alsa-project.org, Liam Girdwood

On 05/31/2012 05:37 PM, Mark Brown wrote:
> On Thu, May 31, 2012 at 04:49:26PM -0600, Stephen Warren wrote:
>> [ having problems getting codec/codec DAI links working] 
...
> It's really hard to comment in much more detail, you've not shown enough
> information.  What are the DAI links connecting the devices?  Is the
> rest of the DAPM path through the system connected?  My best guess is
> that (possibly due to the linking of the playback widgets) you don't
> have a full DAPM path.

Here's hopefully everything:

I'm playing back audio on CPU DAI named APBIF0. This is connected to
AHUB XBAR DAI also named APBIF0. This link appears to be working, since
the XBAR's stream node is active:

# cat tegra30-ahub-xbar/dapm/APBIF0\ Receive
APBIF0 Receive: On  in 1 out 1
 stream APBIF0 Receive active
 out "static" "APBIF0 RX"

Tracing the path through the XBAR, the paths seem set up OK, but nothing
else is active:

# cat tegra30-ahub-xbar/dapm/APBIF0\ RX
APBIF0 RX: Off  in 1 out 0
 in  "static" "APBIF0 Receive"
 out "APBIF0 RX" "I2S1 Mux"

# cat tegra30-ahub-xbar/dapm/I2S1\ Mux
I2S1 Mux: Off  in 1 out 0
 in  "APBIF0 RX" "APBIF0 RX"
 out "static" "I2S1 TX"

# cat tegra30-ahub-xbar/dapm/I2S1\ TX
I2S1 TX: Off  in 1 out 0
 in  "static" "I2S1 Mux"
 out "static" "I2S1 Transmit"

# cat tegra30-ahub-xbar/dapm/I2S1\ Transmit
I2S1 Transmit: Off  in 1 out 0
 stream I2S1 Transmit inactive
 in  "static" "I2S1 TX"

There is also a DAI link from XBAR's I2S1 TX/Transmit to the I2S
controller's CIF Receive/RX, which appears to have been linked correctly
since both DAI names show up in the I2S controller's CIF Receive stream
debugfs file (see "in" line):

# cat tegra30-i2s.1/dapm/CIF\ Receive
CIF Receive: Off  in 0 out 0
 stream CIF Receive inactive
 in  "static" "I2S1 Transmit-CIF Receive"
 out "static" "CIF RX"

(I assume that the "in" line of the AHUB's "APBIF0 Receive" debugfs file
way above is only "APBIF0" instead of "APBIF0-APBIF0" since it's a
cpu/codec link not a codec/codec link?)

And again, the path through the I2S controller looks complete:

# cat tegra30-i2s.1/dapm/CIF\ RX
CIF RX: Off  in 0 out 0
 in  "static" "CIF Receive"
 out "static" "DAP TX"

# cat tegra30-i2s.1/dapm/DAP\ TX
DAP TX: Off  in 0 out 0
 in  "static" "CIF RX"
 out "static" "DAP Transmit"

# cat tegra30-i2s.1/dapm/DAP\ Transmit
DAP Transmit: Off  in 0 out 0
 stream DAP Transmit inactive
 in  "static" "DAP TX"

Finally, there's a DAI link from the I2S controller's DAP DAI to the
WM8903's DAI, which again shows up in the debugfs file:

# cat wm8903.4-001a/dapm/Playback
Playback: Off  in 0 out 8
 stream Playback inactive
 in  "static" "DAP Transmit-Playback"
 out "static" "AIFRXL"
 out "static" "AIFRXR"
 out "static" "AIFRXL"
 out "static" "AIFRXR"

For completeness, here's the route through the WM8903, although nothing
in that codec has changed since before I started reworking the Tegra
drivers:

# cd wm8903.4-001a/dapm/

# cat AIFRXL
AIFRXL: Off  in 0 out 2
 stream Left Playback inactive
 in  "static" "Playback"
 in  "static" "Playback"
 out "Left" "Left Playback Mux"

# cat Left\ Playback\ Mux
Left Playback Mux: Off  in 0 out 2
 in  "Left" "AIFRXL"
 out "static" "DACL"

# cat DACL
DACL: Off  in 0 out 2 - R18(0x12) bit 3
 in  "static" "CLK_DSP"
 in  "static" "DACL Sidetone"
 in  "static" "Left Playback Mux"
 out "DACL Switch" "Left Speaker Mixer"
 out "DACL Switch" "Left Output Mixer"

# cat Left\ Speaker\ Mixer
Left Speaker Mixer: Off  in 0 out 2 - R16(0x10) bit 1
 in  "DACL Switch" "DACL"
 out "static" "Left Speaker PGA"

# cat Left\ Speaker\ PGA
Left Speaker PGA: Off  in 0 out 2 - R17(0x11) bit 1
 in  "static" "Left Speaker Mixer"
 out "static" "LON"
 out "static" "LOP"

# cat LON
LON: Off  in 0 out 1
 in  "static" "Left Speaker PGA"
 out "static" "Int Spk"

# amixer cget name='Int Spk Switch'
numid=87,iface=MIXER,name='Int Spk Switch'
  ; type=BOOLEAN,access=rw------,values=1
  : values=on

(I do note that on IRC you said soc-pcm might be a better fit for this
HW now, but since I figure I'm very close, I'd like to get this working
and experiment with it a bit either way)

Thanks so much for the help.

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

* Re: Confusing about Playback/Capture, CODEC/CODEC links, and snd_soc_dapm_link_dai_widgets()
  2012-06-01 17:01   ` Liam Girdwood
@ 2012-06-04 13:02     ` Sebastien LEDUC
  2012-06-04 16:57       ` Liam Girdwood
  0 siblings, 1 reply; 11+ messages in thread
From: Sebastien LEDUC @ 2012-06-04 13:02 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown; +Cc: alsa-devel@alsa-project.org, Stephen Warren

Hi Liam
There seem to be a similar mistake in the implementation of is_connected_output_ep / is_connected_input_ep:

In function is_connected_output_ep:
-----------------------------------------------

 list_for_each_entry(path, &widget->sinks, list_source) {
                ...
                err = dapm_list_add_widget(list, path->sink);
                ...
}

In function is_connected_input_ep:
---------------------------------------------

list_for_each_entry(path, &widget->sources, list_sink) {
...
                err = dapm_list_add_widget(list, path->sink);
}


I would have expected to have for the latter:
err = dapm_list_add_widget(list, path->source);

regards
Sebastien

-----Original Message-----
From: alsa-devel-bounces@alsa-project.org [mailto:alsa-devel-bounces@alsa-project.org] On Behalf Of Liam Girdwood
Sent: Friday, June 01, 2012 7:02 PM
To: Mark Brown
Cc: alsa-devel@alsa-project.org; Stephen Warren
Subject: Re: [alsa-devel] Confusing about Playback/Capture, CODEC/CODEC links, and snd_soc_dapm_link_dai_widgets()

On Fri, 2012-06-01 at 00:37 +0100, Mark Brown wrote:
> On Thu, May 31, 2012 at 04:49:26PM -0600, Stephen Warren wrote:

> 
> This is all working just fine in mainline on littlemill.
> 
> > > int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
> > > 	struct snd_soc_dapm_widget_list **list)
> > ...
> > > 	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
> > > 		paths = is_connected_output_ep(dai->playback_widget, list);
> > > 	else
> > > 		paths = is_connected_input_ep(dai->playback_widget, list);
> 
> > I would have expected this to use capture_widget on the final line, but
> > I haven't thought about this in detail, just noticed the lack of
> > symmetry by very brief inspection.
> 
> Yes, that looks buggy.  Don't think there's any mainline users so nobody
> would notice.

Gah, it's a bug - I did have it fixed before the upstreaming but this
fix seems to have been lost.

Patch on it's way.

Liam

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

* Re: Confusing about Playback/Capture, CODEC/CODEC links, and snd_soc_dapm_link_dai_widgets()
  2012-06-04 13:02     ` Sebastien LEDUC
@ 2012-06-04 16:57       ` Liam Girdwood
  0 siblings, 0 replies; 11+ messages in thread
From: Liam Girdwood @ 2012-06-04 16:57 UTC (permalink / raw)
  To: Sebastien LEDUC; +Cc: alsa-devel@alsa-project.org, Mark Brown, Stephen Warren

On Mon, 2012-06-04 at 15:02 +0200, Sebastien LEDUC wrote:
> Hi Liam
> There seem to be a similar mistake in the implementation of is_connected_output_ep / is_connected_input_ep:
> 
> In function is_connected_output_ep:
> -----------------------------------------------
> 
>  list_for_each_entry(path, &widget->sinks, list_source) {
>                 ...
>                 err = dapm_list_add_widget(list, path->sink);
>                 ...
> }
> 
> In function is_connected_input_ep:
> ---------------------------------------------
> 
> list_for_each_entry(path, &widget->sources, list_sink) {
> ...
>                 err = dapm_list_add_widget(list, path->sink);
> }
> 
> 
> I would have expected to have for the latter:
> err = dapm_list_add_widget(list, path->source);

Your right, this patch also got somehow dropped from squashing prior to
upstream. I'll send the fix shortly.

Thanks

Liam

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

* Re: Confusion about Playback/Capture, CODEC/CODEC links, and snd_soc_dapm_link_dai_widgets()
  2012-05-31 22:49 Confusing about Playback/Capture, CODEC/CODEC links, and snd_soc_dapm_link_dai_widgets() Stephen Warren
  2012-05-31 23:37 ` Mark Brown
@ 2012-06-05 20:24 ` Stephen Warren
  2012-06-05 20:48   ` Mark Brown
  1 sibling, 1 reply; 11+ messages in thread
From: Stephen Warren @ 2012-06-05 20:24 UTC (permalink / raw)
  To: Mark Brown, Liam Girdwood; +Cc: alsa-devel@alsa-project.org

On 05/31/2012 04:49 PM, Stephen Warren wrote:
> [I'm having issues with CODEC/CODEC links]

I believe I've tracked down the issue I'm having. Playback isn't working
because of a lack of a complete DAPM path from CPU DAI to the final
CODEC in the chain. This path does not exist, because some DAIs on some
CODECs in the chain are getting DAI widgets created multiple times.

I have the following DAIs/links:

CPU DAI is dev=tegra30-ahub-apbif dai=APBIF0

link (1) from APBIF0 in ^ to APBIF0 in \/

CODEC dev=tegra30-ahub-xbar with DAIs APBIF0, I2S1

link (2) from I2S1 in ^ to CIF in \/

CODEC dev=tegra30-i2s.1 with DAIs CIF, DAP

link (3) from DAP in ^ to wm8903-hifi in \/

CODEC wm8903.4-001a dai=wm8903-hifi

The links in the machine driver are listed in order (1) (3) (2).

The problem is that when link (3) is instantiated, the DAP DAI is probed
on its own as just a CPU DAI. This happens in soc_probe_dai_link() in
the "probe the cpu_daiI" logic.

Then later when link (2) is instantiated, the entire tegra30-i2s.1 CODEC
is probed. This happens in soc_probe_dai_link() in the "probe the CODEC"
logic.

Both those two things call snd_soc_dapm_new_dai_widgets() for the I2S
CODEC's DAP DAI. Furthermore, the DAPM context in each case is
different. For link (2) it's the I2S1 CODEC's DAPM context; see the call
to snd_soc_dapm_new_dai_widgets() from soc_probe_dai_link(). For link
(3), it's the DAP DAI's own context; see the call to
snd_soc_dapm_new_dai_widgets() from snd_soc_probe_codec().

So, there end up being two DAP DAI widgets created for the one DAI.

In turn, I believe that snd_soc_dapm_add_route() ends up being confused
by this, either setting up the wrong route, or none.

To solve this:

Initially, I thought that snd_soc_dapm_new_dai_widgets() could just
return if the DAI already had widgets, but that doesn't work, since the
widgets were created for the wrong DAPM context - the I2S1 DAP DAI's
rather than the I2S CODEC's.

Perhaps instead of blindly probing the CPU DAI, soc_probe_dai_link()
should check whether that DAI is part of a CODEC, and instead of calling
try_module_get() and snd_soc_dapm_new_dai_widgets(), it should just call
soc_probe_codec() on the parent CODEC (guarded by whether the CODEC was
already probed). Does that sound right? I'm attempting to make that work
now, in case it's right.

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

* Re: Confusion about Playback/Capture, CODEC/CODEC links, and snd_soc_dapm_link_dai_widgets()
  2012-06-05 20:24 ` Stephen Warren
@ 2012-06-05 20:48   ` Mark Brown
  2012-06-05 21:17     ` Stephen Warren
  0 siblings, 1 reply; 11+ messages in thread
From: Mark Brown @ 2012-06-05 20:48 UTC (permalink / raw)
  To: Stephen Warren; +Cc: alsa-devel@alsa-project.org, Liam Girdwood

On Tue, Jun 05, 2012 at 02:24:47PM -0600, Stephen Warren wrote:

> Initially, I thought that snd_soc_dapm_new_dai_widgets() could just
> return if the DAI already had widgets, but that doesn't work, since the
> widgets were created for the wrong DAPM context - the I2S1 DAP DAI's
> rather than the I2S CODEC's.

> Perhaps instead of blindly probing the CPU DAI, soc_probe_dai_link()
> should check whether that DAI is part of a CODEC, and instead of calling
> try_module_get() and snd_soc_dapm_new_dai_widgets(), it should just call
> soc_probe_codec() on the parent CODEC (guarded by whether the CODEC was
> already probed). Does that sound right? I'm attempting to make that work
> now, in case it's right.

No, we should just probe CODECs sensibly before we do any of the DAIs
instead of trying to guess what we're doing in the middle of handling
the DAI links.  Your changes will be making the logic even more
complicated here, it should be getting simpler - the reason this blew up
for you is that the probe logic is already far too baroque.  Given the
data we have it'll boil down to similar checks bit it'll be in a clear,
comprehensible CODEC probe step rather than intertwined with other
stuff.  This will also mean that aux_devs make more sense.

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

* Re: Confusion about Playback/Capture, CODEC/CODEC links, and snd_soc_dapm_link_dai_widgets()
  2012-06-05 20:48   ` Mark Brown
@ 2012-06-05 21:17     ` Stephen Warren
  2012-06-05 21:34       ` Mark Brown
  0 siblings, 1 reply; 11+ messages in thread
From: Stephen Warren @ 2012-06-05 21:17 UTC (permalink / raw)
  To: Mark Brown; +Cc: alsa-devel@alsa-project.org, Liam Girdwood

On 06/05/2012 02:48 PM, Mark Brown wrote:
> On Tue, Jun 05, 2012 at 02:24:47PM -0600, Stephen Warren wrote:
> 
>> Initially, I thought that snd_soc_dapm_new_dai_widgets() could just
>> return if the DAI already had widgets, but that doesn't work, since the
>> widgets were created for the wrong DAPM context - the I2S1 DAP DAI's
>> rather than the I2S CODEC's.
> 
>> Perhaps instead of blindly probing the CPU DAI, soc_probe_dai_link()
>> should check whether that DAI is part of a CODEC, and instead of calling
>> try_module_get() and snd_soc_dapm_new_dai_widgets(), it should just call
>> soc_probe_codec() on the parent CODEC (guarded by whether the CODEC was
>> already probed). Does that sound right? I'm attempting to make that work
>> now, in case it's right.
> 
> No, we should just probe CODECs sensibly before we do any of the DAIs
> instead of trying to guess what we're doing in the middle of handling
> the DAI links.  Your changes will be making the logic even more
> complicated here, it should be getting simpler - the reason this blew up
> for you is that the probe logic is already far too baroque.  Given the
> data we have it'll boil down to similar checks bit it'll be in a clear,
> comprehensible CODEC probe step rather than intertwined with other
> stuff.  This will also mean that aux_devs make more sense.

OK, that's actually what my inclination was, but I wasn't sure about
changing all the probing in such a radical way, so I didn't mention it.

So, should the logic be something like this early-ish in
snd_soc_instantiate_card():

for every dai link:
    if cpu side is a codec and it isn't probed
        probe it
    if codec side isn't probed
        probe it
something similar for aux devs
something similar for platforms?

And modify soc_probe_dai_link() to only probe DAIs, never anything else.

Is the following loop still required:

> 	/* early DAI link probe */
> 	for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
> 			order++) {

I'm not sure what the probe ordering stuff is achieving, and whether
it's really intended for just CPU DAIs, just all DAIs, just CODECS,
everything...

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

* Re: Confusion about Playback/Capture, CODEC/CODEC links, and snd_soc_dapm_link_dai_widgets()
  2012-06-05 21:17     ` Stephen Warren
@ 2012-06-05 21:34       ` Mark Brown
  0 siblings, 0 replies; 11+ messages in thread
From: Mark Brown @ 2012-06-05 21:34 UTC (permalink / raw)
  To: Stephen Warren; +Cc: alsa-devel@alsa-project.org, Liam Girdwood

On Tue, Jun 05, 2012 at 03:17:15PM -0600, Stephen Warren wrote:

> So, should the logic be something like this early-ish in
> snd_soc_instantiate_card():

> for every dai link:
>     if cpu side is a codec and it isn't probed
>         probe it
>     if codec side isn't probed
>         probe it
> something similar for aux devs
> something similar for platforms?

> And modify soc_probe_dai_link() to only probe DAIs, never anything else.

Yeah, something like this.

> Is the following loop still required:

> > 	/* early DAI link probe */
> > 	for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
> > 			order++) {

> I'm not sure what the probe ordering stuff is achieving, and whether
> it's really intended for just CPU DAIs, just all DAIs, just CODECS,
> everything...

The only user of that is OMAP, I can't remember if they've actually got
their users for that upstream or not.  IIRC it's there to resolve clock
order dependencies but I'm not sure there isn't a neater solution with
something like cache only register I/O especially now we've got better
infrastructure.  Or if we can add something based on having a usable
clock API, we can rely on but that doesn't seem too realistic in the
medium term.

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

end of thread, other threads:[~2012-06-05 21:34 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-05-31 22:49 Confusing about Playback/Capture, CODEC/CODEC links, and snd_soc_dapm_link_dai_widgets() Stephen Warren
2012-05-31 23:37 ` Mark Brown
2012-06-01 17:01   ` Liam Girdwood
2012-06-04 13:02     ` Sebastien LEDUC
2012-06-04 16:57       ` Liam Girdwood
2012-06-01 21:41   ` Mark Brown
2012-06-01 22:31   ` Confusion " Stephen Warren
2012-06-05 20:24 ` Stephen Warren
2012-06-05 20:48   ` Mark Brown
2012-06-05 21:17     ` Stephen Warren
2012-06-05 21:34       ` 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.