[alsa-devel] LSI HDA Modem is not working on HP new Laptop which has IDT 7605 HDA codec and REDHAT installed on it with ALSA ver 1.0.24.
Modem receive unwanted data on stream 0 even stream is not open by any device. Stream 0 was acquired by IDC 7605 and this codec keep sending something even after closing the stream.
On further investigation I found ALSA ver 1.0.24 have new fix "Make converter setups sticky" which changes the semantics of snd_hda_codec_cleanup_stream() not to clean up the stream at that moment but delay the action. This is the reason why Modem getting some unwanted data and stop working.
To resolve this issue we need to enable "no_sticky_stream" for these IDT codec. The fix is like putting one line of code "codec->no_sticky_stream =1;" at the end of function "patch_stac92hd83xxx" in file "/sound/pci/hda/patch_sigmatel.c".
As I am not much aware of the fix "Make converter setups sticky" and also not know the side effects of above mention fix, please analyze and fix the issue properly.
Thanks SuresH
At Thu, 29 Sep 2011 10:51:28 +0530, Gupta, Suresh wrote:
Modem receive unwanted data on stream 0 even stream is not open by any device. Stream 0 was acquired by IDC 7605 and this codec keep sending something even after closing the stream.
Why does the LSI modem device receive from the stream of IDT codec at all? In other words, how does LSI modem driver manage the allocation of streams?
Takashi
LSI Modem always checks the "opened" bit of "azx_dev" before opening the stream. Modem sets "opened" bit and use stream if and only if that "opened" bit was not set otherwise move to next stream "azx_dev".
I found that the ALSA unset this "opened" bit on close but do not reset AC_VERB_SET_CHANNEL_STREAMID of IDC codec. Due to which IDC Codec always get active and always sending data to stream 0. Now when LSI modem check the "opened" bit of stream 0, it found it is not set and open the stream 0 and start reading data from stream 0. As IDC codec still sending data on stream 0 the LSI Modem get this unexpected data and stop working.
I believe the Code (below) which checks "no_sticky_stream" is the culprit due to which "really_cleanup_stream" function is not called. I found the Analog devices codec set "no_sticky_stream" while probing their codec. This is the reason, our modem works on HP laptop with Analog device codec.
According to me the IDC codec should stop sending data after closing the stream or otherwise they should always acquire the stream which is not right.
I don't know why "no_sticky_stream" come into new code and what's it significance. Why only Analog devices use this "no_sticky_stream".
Thanks SuresH
void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid, int do_now) { struct hda_cvt_setup *p; if (!nid) return;
if (codec->no_sticky_stream) do_now = 1;
snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid); p = get_hda_cvt_setup(codec, nid); if (p) { /* here we just clear the active flag when do_now isn't set; * actual clean-ups will be done later in * purify_inactive_streams() called from snd_hda_codec_prpapre() */ if (do_now) really_cleanup_stream(codec, p); else p->active = 0; } }
-----Original Message----- From: Takashi Iwai [mailto:tiwai@suse.de] Sent: Thursday, September 29, 2011 11:51 AM To: Gupta, Suresh Cc: alsa-devel@alsa-project.org Subject: Re: [alsa-devel] LSI HDA Modem is not working on HP new Laptop which has IDT 7605 HDA codec and REDHAT installed on it with ALSA ver 1.0.24.
At Thu, 29 Sep 2011 10:51:28 +0530, Gupta, Suresh wrote:
Modem receive unwanted data on stream 0 even stream is not open by any device. Stream 0 was acquired by IDC 7605 and this codec keep sending something even after closing the stream.
Why does the LSI modem device receive from the stream of IDT codec at all? In other words, how does LSI modem driver manage the allocation of streams?
Takashi
At Thu, 29 Sep 2011 12:42:41 +0530, Gupta, Suresh wrote:
LSI Modem always checks the "opened" bit of "azx_dev" before opening the stream. Modem sets "opened" bit and use stream if and only if that "opened" bit was not set otherwise move to next stream "azx_dev".
I found that the ALSA unset this "opened" bit on close but do not reset AC_VERB_SET_CHANNEL_STREAMID of IDC codec. Due to which IDC Codec always get active and always sending data to stream 0. Now when LSI modem check the "opened" bit of stream 0, it found it is not set and open the stream 0 and start reading data from stream 0. As IDC codec still sending data on stream 0 the LSI Modem get this unexpected data and stop working.
I believe the Code (below) which checks "no_sticky_stream" is the culprit due to which "really_cleanup_stream" function is not called. I found the Analog devices codec set "no_sticky_stream" while probing their codec. This is the reason, our modem works on HP laptop with Analog device codec.
According to me the IDC codec should stop sending data after closing the stream or otherwise they should always acquire the stream which is not right.
I don't know why "no_sticky_stream" come into new code and what's it significance. Why only Analog devices use this "no_sticky_stream".
The problem is that your driver steals the stream silently. The stream is still assigned to the IDT codec driver even after the PCM is closed. It's just not used. When the PCM is opened, the very same stream is used again without reassigning the stream tag.
Now the modem driver grabs the stream and use the stream tag. Of course, the data will be fed.
The stream must be allocated via azx_assign_device(). If you don't, it's not guaranteed what happens.
Takashi
At Thu, 29 Sep 2011 09:34:17 +0200, Takashi Iwai wrote:
At Thu, 29 Sep 2011 12:42:41 +0530, Gupta, Suresh wrote:
LSI Modem always checks the "opened" bit of "azx_dev" before opening the stream. Modem sets "opened" bit and use stream if and only if that "opened" bit was not set otherwise move to next stream "azx_dev".
I found that the ALSA unset this "opened" bit on close but do not reset AC_VERB_SET_CHANNEL_STREAMID of IDC codec. Due to which IDC Codec always get active and always sending data to stream 0. Now when LSI modem check the "opened" bit of stream 0, it found it is not set and open the stream 0 and start reading data from stream 0. As IDC codec still sending data on stream 0 the LSI Modem get this unexpected data and stop working.
I believe the Code (below) which checks "no_sticky_stream" is the culprit due to which "really_cleanup_stream" function is not called. I found the Analog devices codec set "no_sticky_stream" while probing their codec. This is the reason, our modem works on HP laptop with Analog device codec.
According to me the IDC codec should stop sending data after closing the stream or otherwise they should always acquire the stream which is not right.
I don't know why "no_sticky_stream" come into new code and what's it significance. Why only Analog devices use this "no_sticky_stream".
The problem is that your driver steals the stream silently. The stream is still assigned to the IDT codec driver even after the PCM is closed. It's just not used. When the PCM is opened, the very same stream is used again without reassigning the stream tag.
Now the modem driver grabs the stream and use the stream tag. Of course, the data will be fed.
The stream must be allocated via azx_assign_device(). If you don't, it's not guaranteed what happens.
Looking back at the code, I think my previous analysis was incorrect. The problem is likely that your driver doesn't set up the stream via snd_hda_codec_setup_stream() or snd_hda_codec_prepare() isn't called properly by any reason.
The logic is: - the inactive old streams conflicting with the newly prepared stream are marked as dirty in snd_hda_codec_setup_stream(); this is supposed to be called from the codec driver's prepare callback, - then the codecs with dirty streams are cleaned up in purity_inactive_streams() called from snd_hda_codec_prepare().
Takashi
Sorry for delay, I was out for Lunch.
I believe we are in sink now, I seen the purity_inactive_streams part of code and found this is totally new logic in 1.0.24 ver. Can you please answer some question for my proper understanding?
1. Why this marking stream dirty come into picture and why ALSA code do not directly clear the AC_VERB_SET_CHANNEL_STREAMID while closing?
2. Why Analog devices codec (patch_analog.c) clear AC_VERB_SET_CHANNEL_STREAMID on close? (if (do_now) really_cleanup_stream(codec, p); )
On Thu, Sep 29, 2011 at 1:27 PM, Takashi Iwai tiwai@suse.de wrote:
At Thu, 29 Sep 2011 09:34:17 +0200, Takashi Iwai wrote:
At Thu, 29 Sep 2011 12:42:41 +0530, Gupta, Suresh wrote:
LSI Modem always checks the "opened" bit of "azx_dev" before opening
the stream. Modem sets "opened" bit and
use stream if and only if that "opened" bit was not set otherwise move
to next stream "azx_dev".
I found that the ALSA unset this "opened" bit on close but do not reset
AC_VERB_SET_CHANNEL_STREAMID of IDC codec.
Due to which IDC Codec always get active and always sending data to
stream 0. Now when LSI modem check the "opened"
bit of stream 0, it found it is not set and open the stream 0 and start
reading data from stream 0. As IDC codec
still sending data on stream 0 the LSI Modem get this unexpected data
and stop working.
I believe the Code (below) which checks "no_sticky_stream" is the
culprit due to which "really_cleanup_stream"
function is not called. I found the Analog devices codec set
"no_sticky_stream" while probing their codec.
This is the reason, our modem works on HP laptop with Analog device
codec.
According to me the IDC codec should stop sending data after closing
the stream or otherwise they should always acquire the stream which is not right.
I don't know why "no_sticky_stream" come into new code and what's it
significance. Why only Analog devices use this "no_sticky_stream".
The problem is that your driver steals the stream silently. The stream is still assigned to the IDT codec driver even after the PCM is closed. It's just not used. When the PCM is opened, the very same stream is used again without reassigning the stream tag.
Now the modem driver grabs the stream and use the stream tag. Of course, the data will be fed.
The stream must be allocated via azx_assign_device(). If you don't, it's not guaranteed what happens.
Looking back at the code, I think my previous analysis was incorrect. The problem is likely that your driver doesn't set up the stream via snd_hda_codec_setup_stream() or snd_hda_codec_prepare() isn't called properly by any reason.
The logic is:
- the inactive old streams conflicting with the newly prepared stream
are marked as dirty in snd_hda_codec_setup_stream(); this is supposed to be called from the codec driver's prepare callback,
- then the codecs with dirty streams are cleaned up in
purity_inactive_streams() called from snd_hda_codec_prepare().
Takashi _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
At Thu, 29 Sep 2011 14:01:40 +0530, suresh gupta wrote:
Sorry for delay, I was out for Lunch.
I believe we are in sink now, I seen the purity_inactive_streams part of code and found this is totally new logic in 1.0.24 ver. Can you please answer some question for my proper understanding?
- Why this marking stream dirty come into picture and why ALSA code do not
directly clear the AC_VERB_SET_CHANNEL_STREAMID while closing?
For keeping the same stream tag for the same device. A device is often shortly closed and reopened. It'd be better to keep the same stream tag for such a case.
- Why Analog devices codec (patch_analog.c) clear
AC_VERB_SET_CHANNEL_STREAMID on close? (if (do_now) really_cleanup_stream(codec, p);
It's because AD codecs (according to bug reports) don't like the sticky-tag feature by some reason. It'll be removed, once when the real culprit is found.
Takashi
)
On Thu, Sep 29, 2011 at 1:27 PM, Takashi Iwai tiwai@suse.de wrote:
At Thu, 29 Sep 2011 09:34:17 +0200, Takashi Iwai wrote:
At Thu, 29 Sep 2011 12:42:41 +0530, Gupta, Suresh wrote:
LSI Modem always checks the "opened" bit of "azx_dev" before opening
the stream. Modem sets "opened" bit and
use stream if and only if that "opened" bit was not set otherwise move
to next stream "azx_dev".
I found that the ALSA unset this "opened" bit on close but do not reset
AC_VERB_SET_CHANNEL_STREAMID of IDC codec.
Due to which IDC Codec always get active and always sending data to
stream 0. Now when LSI modem check the "opened"
bit of stream 0, it found it is not set and open the stream 0 and start
reading data from stream 0. As IDC codec
still sending data on stream 0 the LSI Modem get this unexpected data
and stop working.
I believe the Code (below) which checks "no_sticky_stream" is the
culprit due to which "really_cleanup_stream"
function is not called. I found the Analog devices codec set
"no_sticky_stream" while probing their codec.
This is the reason, our modem works on HP laptop with Analog device
codec.
According to me the IDC codec should stop sending data after closing
the stream or otherwise they should always acquire the stream which is not right.
I don't know why "no_sticky_stream" come into new code and what's it
significance. Why only Analog devices use this "no_sticky_stream".
The problem is that your driver steals the stream silently. The stream is still assigned to the IDT codec driver even after the PCM is closed. It's just not used. When the PCM is opened, the very same stream is used again without reassigning the stream tag.
Now the modem driver grabs the stream and use the stream tag. Of course, the data will be fed.
The stream must be allocated via azx_assign_device(). If you don't, it's not guaranteed what happens.
Looking back at the code, I think my previous analysis was incorrect. The problem is likely that your driver doesn't set up the stream via snd_hda_codec_setup_stream() or snd_hda_codec_prepare() isn't called properly by any reason.
The logic is:
- the inactive old streams conflicting with the newly prepared stream
are marked as dirty in snd_hda_codec_setup_stream(); this is supposed to be called from the codec driver's prepare callback,
- then the codecs with dirty streams are cleaned up in
purity_inactive_streams() called from snd_hda_codec_prepare().
Takashi _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
[2 <text/html; ISO-8859-1 (quoted-printable)>]
Thanks for answers,
I will explore more our code to understand the issue and will come back.
Again thanks for help….. SuresH
On Thu, Sep 29, 2011 at 2:16 PM, Takashi Iwai tiwai@suse.de wrote:
At Thu, 29 Sep 2011 14:01:40 +0530, suresh gupta wrote:
Sorry for delay, I was out for Lunch.
I believe we are in sink now, I seen the purity_inactive_streams part of code and found this is totally new logic in 1.0.24 ver. Can you please answer some question for my proper understanding?
- Why this marking stream dirty come into picture and why ALSA code do
not
directly clear the AC_VERB_SET_CHANNEL_STREAMID while closing?
For keeping the same stream tag for the same device. A device is often shortly closed and reopened. It'd be better to keep the same stream tag for such a case.
- Why Analog devices codec (patch_analog.c) clear
AC_VERB_SET_CHANNEL_STREAMID on close? (if (do_now) really_cleanup_stream(codec, p);
It's because AD codecs (according to bug reports) don't like the sticky-tag feature by some reason. It'll be removed, once when the real culprit is found.
Takashi
)
On Thu, Sep 29, 2011 at 1:27 PM, Takashi Iwai tiwai@suse.de wrote:
At Thu, 29 Sep 2011 09:34:17 +0200, Takashi Iwai wrote:
At Thu, 29 Sep 2011 12:42:41 +0530, Gupta, Suresh wrote:
LSI Modem always checks the "opened" bit of "azx_dev" before
opening
the stream. Modem sets "opened" bit and
use stream if and only if that "opened" bit was not set otherwise
move
to next stream "azx_dev".
I found that the ALSA unset this "opened" bit on close but do not
reset
AC_VERB_SET_CHANNEL_STREAMID of IDC codec.
Due to which IDC Codec always get active and always sending data to
stream 0. Now when LSI modem check the "opened"
bit of stream 0, it found it is not set and open the stream 0 and
start
reading data from stream 0. As IDC codec
still sending data on stream 0 the LSI Modem get this unexpected
data
and stop working.
I believe the Code (below) which checks "no_sticky_stream" is the
culprit due to which "really_cleanup_stream"
function is not called. I found the Analog devices codec set
"no_sticky_stream" while probing their codec.
This is the reason, our modem works on HP laptop with Analog device
codec.
According to me the IDC codec should stop sending data after
closing
the stream or otherwise they should always acquire the stream which is
not
right.
I don't know why "no_sticky_stream" come into new code and what's
it
significance. Why only Analog devices use this "no_sticky_stream".
The problem is that your driver steals the stream silently. The stream is still assigned to the IDT codec driver even after the PCM is closed. It's just not used. When the PCM is opened, the very same stream is used again without reassigning the stream tag.
Now the modem driver grabs the stream and use the stream tag. Of course, the data will be fed.
The stream must be allocated via azx_assign_device(). If you don't, it's not guaranteed what happens.
Looking back at the code, I think my previous analysis was incorrect. The problem is likely that your driver doesn't set up the stream via snd_hda_codec_setup_stream() or snd_hda_codec_prepare() isn't called properly by any reason.
The logic is:
- the inactive old streams conflicting with the newly prepared stream
are marked as dirty in snd_hda_codec_setup_stream(); this is supposed to be called from the codec driver's prepare callback,
- then the codecs with dirty streams are cleaned up in
purity_inactive_streams() called from snd_hda_codec_prepare().
Takashi _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
[2 <text/html; ISO-8859-1 (quoted-printable)>]
2011/9/29 Takashi Iwai tiwai@suse.de:
At Thu, 29 Sep 2011 14:01:40 +0530, suresh gupta wrote:
Sorry for delay, I was out for Lunch.
I believe we are in sink now, I seen the purity_inactive_streams part of code and found this is totally new logic in 1.0.24 ver. Can you please answer some question for my proper understanding?
- Why this marking stream dirty come into picture and why ALSA code do not
directly clear the AC_VERB_SET_CHANNEL_STREAMID while closing?
For keeping the same stream tag for the same device. A device is often shortly closed and reopened. It'd be better to keep the same stream tag for such a case.
I have doubt about this since hw_free() can also cleanup the stream tag too
http://thread.gmane.org/gmane.linux.alsa.devel/89420
- Why Analog devices codec (patch_analog.c) clear
AC_VERB_SET_CHANNEL_STREAMID on close? (if (do_now) really_cleanup_stream(codec, p);
It's because AD codecs (according to bug reports) don't like the sticky-tag feature by some reason. It'll be removed, once when the real culprit is found.
http://thread.gmane.org/gmane.linux.alsa.devel/78379
Can the converters can retrain the stream tag after suspend/resume ?
At Sat, 1 Oct 2011 10:56:55 +0800, Raymond Yau wrote:
2011/9/29 Takashi Iwai tiwai@suse.de:
At Thu, 29 Sep 2011 14:01:40 +0530, suresh gupta wrote:
Sorry for delay, I was out for Lunch.
I believe we are in sink now, I seen the purity_inactive_streams part of code and found this is totally new logic in 1.0.24 ver. Can you please answer some question for my proper understanding?
- Why this marking stream dirty come into picture and why ALSA code do not
directly clear the AC_VERB_SET_CHANNEL_STREAMID while closing?
For keeping the same stream tag for the same device. A device is often shortly closed and reopened. It'd be better to keep the same stream tag for such a case.
I have doubt about this since hw_free() can also cleanup the stream tag too
It's only in the case of no_sticky. It doesn't happen in the normal case.
- Why Analog devices codec (patch_analog.c) clear
AC_VERB_SET_CHANNEL_STREAMID on close? (if (do_now) really_cleanup_stream(codec, p);
It's because AD codecs (according to bug reports) don't like the sticky-tag feature by some reason. It'll be removed, once when the real culprit is found.
http://thread.gmane.org/gmane.linux.alsa.devel/78379
Can the converters can retrain the stream tag after suspend/resume ?
No. The flag is cleared in the suspend.
Takashi
2011/10/1 Takashi Iwai tiwai@suse.de:
- Why Analog devices codec (patch_analog.c) clear
AC_VERB_SET_CHANNEL_STREAMID on close? (if (do_now) really_cleanup_stream(codec, p);
It's because AD codecs (according to bug reports) don't like the sticky-tag feature by some reason. It'll be removed, once when the real culprit is found.
http://thread.gmane.org/gmane.linux.alsa.devel/78379
Can the converters can retrain the stream tag after suspend/resume ?
No. The flag is cleared in the suspend.
The main difference is only AD codecs have Power widget but driver does not has init verbs for this [Power widget]
e.g. ad1988 has 9 widets support power states ,
Table 13 Widet Parameters (Power states 0f) Five [Audio Output] , three [Audio Input] and [Power widget] have 00000009
Table 10 widget No. Name Description 19 Mixer Power Down Power widget Powers down the analog mixer and associated amps 23 VREF Power Down Vendor defined Powers down the internal and external VREF circularity 2f BIAS Power Down Vendor defined Powers down the internal MIC_BIAS_FILT and all MIC_BIAS pins
Node 0x19 [Power Widget] wcaps 0x500500: Mono Power states: D0 D3 Power: setting=D0, actual=D0 Connection: 2 0x20 0x21
There are two vendor defined widgets (VREF power down and BIAS power pown)
Node 0x23 [Vendor Defined Widget] wcaps 0xf00100: Mono Connection: 18 0x11* 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x24 0x25 0x38 0x39 0x3a 0x3b 0x3c
Node 0x2f [Vendor Defined Widget] wcaps 0xf00100: Mono Connection: 6 0x11* 0x12 0x14 0x15 0x16 0x17
At Mon, 3 Oct 2011 09:35:59 +0800, Raymond Yau wrote:
2011/10/1 Takashi Iwai tiwai@suse.de:
- Why Analog devices codec (patch_analog.c) clear
AC_VERB_SET_CHANNEL_STREAMID on close? (if (do_now) really_cleanup_stream(codec, p);
It's because AD codecs (according to bug reports) don't like the sticky-tag feature by some reason. It'll be removed, once when the real culprit is found.
http://thread.gmane.org/gmane.linux.alsa.devel/78379
Can the converters can retrain the stream tag after suspend/resume ?
No. The flag is cleared in the suspend.
The main difference is only AD codecs have Power widget but driver does not has init verbs for this [Power widget]
Yeah, but this has nothing to do with the sticky assignment. Actually the widget isn't touched, so it means all widgets are fully powered up or all powered down at suspend.
Takashi
At Thu, 29 Sep 2011 10:46:02 +0200, Takashi Iwai wrote:
At Thu, 29 Sep 2011 14:01:40 +0530, suresh gupta wrote:
Sorry for delay, I was out for Lunch.
I believe we are in sink now, I seen the purity_inactive_streams part of code and found this is totally new logic in 1.0.24 ver. Can you please answer some question for my proper understanding?
- Why this marking stream dirty come into picture and why ALSA code do not
directly clear the AC_VERB_SET_CHANNEL_STREAMID while closing?
For keeping the same stream tag for the same device. A device is often shortly closed and reopened. It'd be better to keep the same stream tag for such a case.
While reading the code again, it seems that the code in hda_intel.c doesn't do perfectly for some stream setups. For example, it blindly relies on pcm->device number, so playback and capture streams won't be distinguished, and the first taker will win always.
I fixed it now with the patch below.
Takashi
=== From: Takashi Iwai tiwai@suse.de Subject: ALSA: hda - Distinguish each substream for better sticky assignment
The commit ef18beded8ddbaafdf4914bab209f77e60ae3a18 introduced a mechanism to assign the previously used slot for the next reopen of a PCM stream. But the PCM device number isn't always unique (it may have multiple substreams), and also the code doesn't check the stream direction, thus both playback and capture streams share the same device number.
For avoiding this conflict, make a unique key for each substream and store/check this value at reopening.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/hda_intel.c | 9 ++++++--- 1 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 8a5dc57..90713f0 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -381,7 +381,7 @@ struct azx_dev { */ unsigned char stream_tag; /* assigned stream */ unsigned char index; /* stream index */ - int device; /* last device number assigned to */ + int assigned_key; /* last device# key assigned to */
unsigned int opened :1; unsigned int running :1; @@ -1613,6 +1613,9 @@ azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream) { int dev, i, nums; struct azx_dev *res = NULL; + /* make a non-zero unique key for the substream */ + int key = (substream->pcm->device << 16) | (substream->number << 2) | + (substream->stream + 1);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dev = chip->playback_index_offset; @@ -1624,12 +1627,12 @@ azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream) for (i = 0; i < nums; i++, dev++) if (!chip->azx_dev[dev].opened) { res = &chip->azx_dev[dev]; - if (res->device == substream->pcm->device) + if (res->assigned_key == key) break; } if (res) { res->opened = 1; - res->device = substream->pcm->device; + res->assigned_key = key; } return res; }
Our modem works with this fix, so I try to understand it and found that, the only difference is now "azx_assign_device" function assign stream from last position and assign last one. This is the reason why our modem works with this fix as our modem try to get stream from first position and get first one.
Do you really want this to do and what the significance of acquiring stream from last position?
However from your previous explanation about new logic, I fixed the issue by making change in our modem code. Thanks for your support and help. SuresH
On Thu, Oct 6, 2011 at 1:54 PM, Takashi Iwai tiwai@suse.de wrote:
At Thu, 29 Sep 2011 10:46:02 +0200, Takashi Iwai wrote:
At Thu, 29 Sep 2011 14:01:40 +0530, suresh gupta wrote:
Sorry for delay, I was out for Lunch.
I believe we are in sink now, I seen the purity_inactive_streams part
of
code and found this is totally new logic in 1.0.24 ver. Can you please answer some question for my proper understanding?
- Why this marking stream dirty come into picture and why ALSA code do
not
directly clear the AC_VERB_SET_CHANNEL_STREAMID while closing?
For keeping the same stream tag for the same device. A device is often shortly closed and reopened. It'd be better to keep the same stream tag for such a case.
While reading the code again, it seems that the code in hda_intel.c doesn't do perfectly for some stream setups. For example, it blindly relies on pcm->device number, so playback and capture streams won't be distinguished, and the first taker will win always.
I fixed it now with the patch below.
Takashi
=== From: Takashi Iwai tiwai@suse.de Subject: ALSA: hda - Distinguish each substream for better sticky assignment
The commit ef18beded8ddbaafdf4914bab209f77e60ae3a18 introduced a mechanism to assign the previously used slot for the next reopen of a PCM stream. But the PCM device number isn't always unique (it may have multiple substreams), and also the code doesn't check the stream direction, thus both playback and capture streams share the same device number.
For avoiding this conflict, make a unique key for each substream and store/check this value at reopening.
Signed-off-by: Takashi Iwai tiwai@suse.de
sound/pci/hda/hda_intel.c | 9 ++++++--- 1 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 8a5dc57..90713f0 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -381,7 +381,7 @@ struct azx_dev { */ unsigned char stream_tag; /* assigned stream */ unsigned char index; /* stream index */
int device; /* last device number assigned to
*/
int assigned_key; /* last device# key assigned to */ unsigned int opened :1; unsigned int running :1;
@@ -1613,6 +1613,9 @@ azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream) { int dev, i, nums; struct azx_dev *res = NULL;
/* make a non-zero unique key for the substream */
int key = (substream->pcm->device << 16) | (substream->number << 2)
|
(substream->stream + 1); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dev = chip->playback_index_offset;
@@ -1624,12 +1627,12 @@ azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream) for (i = 0; i < nums; i++, dev++) if (!chip->azx_dev[dev].opened) { res = &chip->azx_dev[dev];
if (res->device == substream->pcm->device)
if (res->assigned_key == key) break; } if (res) { res->opened = 1;
res->device = substream->pcm->device;
res->assigned_key = key; } return res;
}
1.7.7
At Tue, 11 Oct 2011 14:49:00 +0530, suresh gupta wrote:
Our modem works with this fix, so I try to understand it and found that, the only difference is now "azx_assign_device" function assign stream from last position and assign last one. This is the reason why our modem works with this fix as our modem try to get stream from first position and get first one.
Do you really want this to do and what the significance of acquiring stream from last position?
Not really much. The only goal is to re-use the last used stream at the next open.
Takashi
However from your previous explanation about new logic, I fixed the issue by making change in our modem code. Thanks for your support and help. SuresH
On Thu, Oct 6, 2011 at 1:54 PM, Takashi Iwai tiwai@suse.de wrote:
At Thu, 29 Sep 2011 10:46:02 +0200, Takashi Iwai wrote:
At Thu, 29 Sep 2011 14:01:40 +0530, suresh gupta wrote:
Sorry for delay, I was out for Lunch.
I believe we are in sink now, I seen the purity_inactive_streams part
of
code and found this is totally new logic in 1.0.24 ver. Can you please answer some question for my proper understanding?
- Why this marking stream dirty come into picture and why ALSA code do
not
directly clear the AC_VERB_SET_CHANNEL_STREAMID while closing?
For keeping the same stream tag for the same device. A device is often shortly closed and reopened. It'd be better to keep the same stream tag for such a case.
While reading the code again, it seems that the code in hda_intel.c doesn't do perfectly for some stream setups. For example, it blindly relies on pcm->device number, so playback and capture streams won't be distinguished, and the first taker will win always.
I fixed it now with the patch below.
Takashi
=== From: Takashi Iwai tiwai@suse.de Subject: ALSA: hda - Distinguish each substream for better sticky assignment
The commit ef18beded8ddbaafdf4914bab209f77e60ae3a18 introduced a mechanism to assign the previously used slot for the next reopen of a PCM stream. But the PCM device number isn't always unique (it may have multiple substreams), and also the code doesn't check the stream direction, thus both playback and capture streams share the same device number.
For avoiding this conflict, make a unique key for each substream and store/check this value at reopening.
Signed-off-by: Takashi Iwai tiwai@suse.de
sound/pci/hda/hda_intel.c | 9 ++++++--- 1 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 8a5dc57..90713f0 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -381,7 +381,7 @@ struct azx_dev { */ unsigned char stream_tag; /* assigned stream */ unsigned char index; /* stream index */
int device; /* last device number assigned to
*/
int assigned_key; /* last device# key assigned to */ unsigned int opened :1; unsigned int running :1;
@@ -1613,6 +1613,9 @@ azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream) { int dev, i, nums; struct azx_dev *res = NULL;
/* make a non-zero unique key for the substream */
int key = (substream->pcm->device << 16) | (substream->number << 2)
|
(substream->stream + 1); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dev = chip->playback_index_offset;
@@ -1624,12 +1627,12 @@ azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream) for (i = 0; i < nums; i++, dev++) if (!chip->azx_dev[dev].opened) { res = &chip->azx_dev[dev];
if (res->device == substream->pcm->device)
if (res->assigned_key == key) break; } if (res) { res->opened = 1;
res->device = substream->pcm->device;
res->assigned_key = key; } return res;
}
1.7.7
LSI Modem always checks the “opened” bit of “azx_dev” before opening the stream. Modem sets “opened” bit and use stream if and only if that “opened” bit was not set otherwise move to next stream “azx_dev”.
I found that the ALSA unset this "opened" bit on close but do not reset AC_VERB_SET_CHANNEL_STREAMID of IDC codec.
Due to which IDC Codec always get active and always sending data to stream 0. Now when LSI modem check the "opened"
bit of stream 0, it found it is not set and open the stream 0 and start reading data from stream 0. As IDC codec still sending data on stream 0 the LSI Modem get this unexpected data and stop working.
I believe the Code (below) which checks "no_sticky_stream" is the culprit due to which "really_cleanup_stream"
function is not called. I found the Analog devices codec set "no_sticky_stream" while probing their codec.
This is the reason, our modem works on HP laptop with Analog device codec.
According to me the IDC codec should stop sending data after closing the stream or otherwise they should always acquire the stream which is not right.
I don’t know why "no_sticky_stream" come into new code and what’s it significance. Why only Analog devices use this "no_sticky_stream".
Thanks
SuresH
void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid,
int do_now)
{
struct hda_cvt_setup *p;
if (!nid)
return;
if (codec->no_sticky_stream)
do_now = 1;
snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
p = get_hda_cvt_setup(codec, nid);
if (p) {
/* here we just clear the active flag when do_now isn't set;
* actual clean-ups will be done later in
* purify_inactive_streams() called from snd_hda_codec_prpapre()
*/
if (do_now)
really_cleanup_stream(codec, p);
else
p->active = 0;
}
}
On Thu, Sep 29, 2011 at 11:50 AM, Takashi Iwai tiwai@suse.de wrote:
At Thu, 29 Sep 2011 10:51:28 +0530, Gupta, Suresh wrote:
Modem receive unwanted data on stream 0 even stream is not open by any
device.
Stream 0 was acquired by IDC 7605 and this codec keep sending something
even after closing the stream.
Why does the LSI modem device receive from the stream of IDT codec at all? In other words, how does LSI modem driver manage the allocation of streams?
Takashi _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
participants (4)
-
Gupta, Suresh
-
Raymond Yau
-
suresh gupta
-
Takashi Iwai