Ticket #2478 (new defect)
linux 2.6.39: alsa state not correctly restored in resume
| Reported by: | lindi | Owned by: | openmoko-kernel |
|---|---|---|---|
| Priority: | high | Milestone: | |
| Component: | kernel | Version: | |
| Severity: | blocker | Keywords: | kernel alsa suspend resume linux 2.6.39 |
| Cc: | Blocked By: | ||
| Blocking: | Estimated Completion (week): | ||
| HasPatchForReview: | no | PatchReviewResult: | |
| Reproducible: | always |
Description
I am using SHR 2.6.39-nodrm branch at 74c481b35be9bf9b7d74c481b35be9bf9b7d with config from http://build.shr-project.org/tests/jama/kernel-nodrm/config-2.6.39.gz
Steps to reproduce: 1) save the attached statefile as stereoout.state 2) alsactl restore -f stereoout.state 3) alsactl store -f step3.state 4) speaker-test -t sine 5) echo mem > /sys/power/state 6) alsactl store -f step6.state 7) speaker-test -t sine Expected results: 3 & 6) alsa states look identical 4 & 7) sine wave can be heard Actual results: 3 & 6) alsa states look identical 4) sine wave can be heard 7) nothing can be heard More info: 1) After step7 I can fix the situation if I run amixer -qc0 cset numid=27,name='Capture Filter Switch' off amixer -qc0 cset numid=27,name='Capture Filter Switch' on amixer -qc0 cset numid=24,name='Capture Switch' on,on amixer -qc0 cset numid=24,name='Capture Switch' off,off amixer -qc0 cset numid=67,name='ALC Mixer Mic2 Capture Switch' on amixer -qc0 cset numid=67,name='ALC Mixer Mic2 Capture Switch' off amixer -qc0 cset numid=59,name='Amp Spk Switch' off amixer -qc0 cset numid=59,name='Amp Spk Switch' on amixer -qc0 cset numid=92,name='Left Mixer Left Playback Switch' off amixer -qc0 cset numid=92,name='Left Mixer Left Playback Switch' on speaker-test -t sine 2) My guess is that kernel is caching some value and does not write it to hardware since it thinks it already has the right value. Toggling the controls back and forth thus can fix the issue.
Attachments
Change History
comment:1 Changed 19 months ago by lindi
Here are some results from systemtap during suspend/resume:
$ stap -e 'probe module("snd_soc_core").function("snd_soc_resume") { printf("%s %s\n", probefunc(), $$parms); }'
prints ""snd_soc_resume dev=0xc7af5c08"
$ stap -e 'probe module("snd_soc_wm8753").function("wm8753_resume") { printf("%s %s\n", probefunc(), $$parms); }'
does not print anything.
dmesg has "soc-audio soc-audio: resume work item may be lost"
Does this mean that the resume handling of wm8753 was completely skipped?
comment:2 Changed 19 months ago by lindi
The
"soc-audio soc-audio: resume work item may be lost"
part is probably fixed upstream in
http://mailman.alsa-project.org/pipermail/alsa-devel/2011-May/040185.html
but I don't think this explains why wm8753_resume never gets called
comment:3 Changed 19 months ago by lindi
lindi@ginger:~$ stap -v -e 'probe module("snd_soc_core").statement("snd_soc_suspend@/home/lindi/debian/debian-linux-2.6/linux-2.6-2.6.39/debian/build/source_armel_none/sound/soc/soc-core.c:1126") { printf("%s %d %x %d\n", pp(), $codec->suspended, $codec->driver->suspend, $codec->dapm->bias_level); }'
Pass 1: parsed user script and 74 library script(s) using 21340virt/12972res/2156shr kb, in 4090usr/290sys/4378real ms.
Pass 2: analyzed script: 1 probe(s), 4 function(s), 3 embed(s), 0 global(s) using 62840virt/14988res/3020shr kb, in 500usr/430sys/1482real ms.
Pass 3: translated to C into "/tmp/stapXzhuo1/stap_a0b7707bb6646bdaa8e34301146c98da_4336.c" using 63748virt/16496res/4084shr kb, in 990usr/210sys/1208real ms.
Pass 4: compiled C into "stap_a0b7707bb6646bdaa8e34301146c98da_4336.ko" in 52030usr/6460sys/58859real ms.
Pass 5: starting run.
module("snd_soc_core").statement("snd_soc_suspend@/home/lindi/debian/debian-linux-2.6/linux-2.6-2.6.39/debian/build/source_armel_none/sound/soc/soc-core.c:1127") 0 0 0
module("snd_soc_core").statement("snd_soc_suspend@/home/lindi/debian/debian-linux-2.6/linux-2.6-2.6.39/debian/build/source_armel_none/sound/soc/soc-core.c:1127") 0 bf09088c 3
shows that we have two codecs.
The first one has no ".suspend".
The second one has ".suspend" but its "dapm.bias_level" is set to 3 which is SND_SOC_BIAS_ON. This means that the codec->driver->suspend(codec, PMSG_SUSPEND); line is not executed and I guess same goes also for codec->driver->resume(codec);.
If I change bias_level to SND_SOC_BIAS_OFF using
#!/usr/bin/stap
probe module("snd_soc_core").statement("snd_soc_suspend@/home/lindi/debian/debian-linux-2.6/linux-2.6-2.6.39/debian/build/source_armel_none/sound/soc/soc-core.c:1126") {
if ($codec->dapm->bias_level == 3) {
$codec->dapm->bias_level = 0;
}
}
probe module("snd_soc_wm8753").function("wm8753_suspend") {
printf("%s\n", pp());
}
probe module("snd_soc_wm8753").function("wm8753_resume") {
printf("%s\n", pp());
}
then wm8753_suspend and wm8753_resume are called and speaker-test works!
comment:5 Changed 19 months ago by lindi
Interestingly if I load the "headset.state" then bias is 1 (STANDBY) and suspend and resume hooks do get called.
comment:6 Changed 19 months ago by lindi
It seems to be
amixer -qc0 cset numid=93,name='Left Mixer Bypass Playback Switch' on
that is enough to cause bias to rise:
wm8753_set_bias_level codec=0xc79770a0 level=0x2 wm8753_set_bias_level codec=0xc79770a0 level=0x3 }}
comment:7 Changed 19 months ago by lindi
Seems these calls to wm8753_set_bias_level come from
[ 3191.245000] [<bf17e7d8>] (wm8753_set_bias_level+0x0/0xb4 [snd_soc_wm8753]) from [<bf155424>] (dapm_pre_sequence_async+0x34/0xb4 [snd_soc_core]) [ 3191.245000] [<bf155424>] (dapm_pre_sequence_async+0x34/0xb4 [snd_soc_core]) from [<c005a1c0>] (async_run_entry_fn+0x7c/0x1b8) [ 3191.245000] [<c005a1c0>] (async_run_entry_fn+0x7c/0x1b8) from [<c004ff68>] (process_one_work+0x11c/0x3d8) [ 3191.245000] [<c004ff68>] (process_one_work+0x11c/0x3d8) from [<c00505b8>] (worker_thread+0x13c/0x478) [ 3191.245000] [<c00505b8>] (worker_thread+0x13c/0x478) from [<c0054138>] (kthread+0x88/0x90)
and
[ 3191.260000] [<bf17e7d8>] (wm8753_set_bias_level+0x0/0xb4 [snd_soc_wm8753]) from [<bf155358>] (dapm_post_sequence_async+0x3c/0xd4 [snd_soc_core]) [ 3191.260000] [<bf155358>] (dapm_post_sequence_async+0x3c/0xd4 [snd_soc_core]) from [<c005a1c0>] (async_run_entry_fn+0x7c/0x1b8) [ 3191.260000] [<c005a1c0>] (async_run_entry_fn+0x7c/0x1b8) from [<c004ff68>] (process_one_work+0x11c/0x3d8) [ 3191.260000] [<c004ff68>] (process_one_work+0x11c/0x3d8) from [<c00505b8>] (worker_thread+0x13c/0x478) [ 3191.260000] [<c00505b8>] (worker_thread+0x13c/0x478) from [<c0054138>] (kthread+0x88/0x90)
respectively.
comment:8 Changed 19 months ago by lindi
It seems
amixer -qc0 cset numid=93,name='Left Mixer Bypass Playback Switch' on
is actually not needed in stereoout.state at all since it is enough that only data from left dac reaches LEFTMIX.
In any case, wrong alsa state should not cause wrong data in cache.
comment:9 Changed 19 months ago by lindi
Thanks to broonie on #alsa-soc I think the solution is to remove the lines
/* allow audio paths from the GSM modem to run during suspend */
snd_soc_dapm_ignore_suspend(dapm, "GSM Line Out");
snd_soc_dapm_ignore_suspend(dapm, "GSM Line In");
snd_soc_dapm_ignore_suspend(dapm, "Headset Mic");
snd_soc_dapm_ignore_suspend(dapm, "Handset Mic");
comment:10 Changed 19 months ago by lindi
I can confirm that removing the snd_soc_dapm_ignore_suspend calls fixes the bug.
comment:11 Changed 16 months ago by GNUtoo
The fix doesn't work for me:
On serial console(with apm -s in the middle):
root@om-gta02:~# speaker-test -t sine speaker-test 1.0.24.2 Playback device is default Stream parameters are 48000Hz, S16_LE, 1 channels Sine wave rate is 440.0000Hz Rate set to 48000Hz (requested 48000Hz) Buffer size range from 2048 to 16384 Period size range from 1024 to 1024 Using max buffer size 16384 Periods = 4 was set period_size = 1024 was set buffer_size = 16384 0 - Front Left Time per period = 2.845838 0 - Front Left T[ 96.155000] soc-audio soc-audio: resume work item may be lost Write error: -86,Streams pipe error [ 96.260000] dma2: channel has nothing loaded
I applied that patch to meta-smartphone:
diff --git a/meta-openmoko/recipes-kernel/linux/linux-2.6.39/shr.patch b/meta-openmoko/recipes-kernel/linux/linux-2.6.39/shr.patch
index 65d087c..efa59e7 100644
--- a/meta-openmoko/recipes-kernel/linux/linux-2.6.39/shr.patch
+++ b/meta-openmoko/recipes-kernel/linux/linux-2.6.39/shr.patch
@@ -3,6 +3,7 @@ rebased on top of openmoko kernel repository (om-2.6.39-stable)
https://gitorious.org/shr/linux/commits/shr-2.6.39-nodrm
+31bdfe1: ASOC: samsung: neo1973_wm8753.c: fix openmoko bug #2478
b851f9f: glamo-mci: disable glamo_mci_pre_request & glamo_mci_post_request
6e1d25a: shr-create-patch.sh: utility used to generate shr.patch for meta-smartphone
352f236: wm8753: Workaround toolchain bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48783
@@ -2401,7 +2402,7 @@ index 8275a2f..8e3e56e 100644
#endif /* __GLAMO_CORE_H */
diff --git a/shr-create-patch.sh b/shr-create-patch.sh
new file mode 100755
-index 0000000..b251946
+index 0000000..a09d4c2
--- /dev/null
+++ b/shr-create-patch.sh
@@ -0,0 +1,12 @@
@@ -2413,9 +2414,9 @@ index 0000000..b251946
+
+https://gitorious.org/shr/linux/commits/shr-2.6.39-nodrm
+
-+$(git log --pretty=format:"%h: %s" gitorious/om-2.6.39-stable..)
++$(git log --pretty=format:"%h: %s" d09e21824bacd5f9ac0285c14c6ddc2d79b96608..)
+
-+$(git diff om-2.6.39-stable)
++$(git diff d09e21824bacd5f9ac0285c14c6ddc2d79b96608)
+EOF
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index ffa2ffe..69c499a 100644
@@ -2441,7 +2442,7 @@ index ffa2ffe..69c499a 100644
{
u64 Kpart;
diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c
-index 4f845fe..a3a1cc8 100644
+index 4f845fe..a7095d9 100644
--- a/sound/soc/samsung/neo1973_wm8753.c
+++ b/sound/soc/samsung/neo1973_wm8753.c
@@ -19,6 +19,7 @@
@@ -2507,7 +2508,20 @@ index 4f845fe..a3a1cc8 100644
return 0;
}
-@@ -527,6 +569,7 @@ module_init(neo1973_init);
+@@ -358,12 +400,6 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
+ snd_soc_dapm_disable_pin(dapm, "Headset Mic");
+ snd_soc_dapm_disable_pin(dapm, "Handset Mic");
+
+- /* allow audio paths from the GSM modem to run during suspend */
+- snd_soc_dapm_ignore_suspend(dapm, "GSM Line Out");
+- snd_soc_dapm_ignore_suspend(dapm, "GSM Line In");
+- snd_soc_dapm_ignore_suspend(dapm, "Headset Mic");
+- snd_soc_dapm_ignore_suspend(dapm, "Handset Mic");
+-
+ if (machine_is_neo1973_gta02()) {
+ ret = neo1973_gta02_wm8753_init(codec);
+ if (ret)
+@@ -527,6 +563,7 @@ module_init(neo1973_init);
static void __exit neo1973_exit(void)
{
diff --git a/meta-openmoko/recipes-kernel/linux/linux_2.6.39.bb b/meta-openmoko/recipes-kernel/linux/linux_2.6.39.bb
index beebcec..0ff4433 100644
--- a/meta-openmoko/recipes-kernel/linux/linux_2.6.39.bb
+++ b/meta-openmoko/recipes-kernel/linux/linux_2.6.39.bb
@@ -1,6 +1,6 @@
require linux.inc
-PR = "r6"
+PR = "r7"
# Mark archs/machines that this kernel supports
DEFAULT_PREFERENCE = "-1"
And build fso2-console-image and did the test mentioned above.
comment:12 Changed 16 months ago by GNUtoo
with echo mem > /sys/power/state I've:
root@om-gta02:~# speaker-test -t sine speaker-test 1.0.24.2 Playback device is default Stream parameters are 48000Hz, S16_LE, 1 channels Sine wave rate is 440.0000Hz Rate set to 48000Hz (requested 48000Hz) Buffer size range from 2048 to 16384 Period size range from 1024 to 1024 Using max buffer size 16384 Periods = 4 was set period_size = 1024 was set buffer_size = 16384 0 - Front Left Time per period = 2.965543 0 - Front Left Time per period = 2.990143 0 - Front Left T[ 70.315000] soc-audio soc-audio: resume work item may be lost Write error: -86,Streams pipe error [ 70.430000] dma2: channel has nothing loaded Write error: -32,Broken pipe
doesn't work means that at resume I've no more sound.
Denis.
comment:13 Changed 16 months ago by lindi
So you start speaker-test, suspend and resume -- you never stop speaker-test at all?
comment:14 Changed 16 months ago by GNUtoo
indeed that's what I did.
use cases:
- a call arrives right when you're suspending => you start playing the ringtone and resume(manually for instance)
- you forget to disable suspend while playing music.
however stopping the sound/music after resuming and retrying to play it doesn't make the play work again.
Denis.
comment:15 Changed 16 months ago by lindi
Ok, so this is possibly a new and different bug then.
I assume it still works if you follow the steps that I listed in the bug report?
comment:16 Changed 16 months ago by GNUtoo
I also tried that:
- playback sound
- suspend+resume no sound
- stop playback no sound
- play again and stop again no sound
- suspend+resume again
- play again sound
comment:17 follow-up: ↓ 19 Changed 16 months ago by lindi
My theory: wm8753_suspend does not get called since the audio path is busy. This means alsa state is not restored on resume either.
comment:18 Changed 16 months ago by GNUtoo
with the test procedure at the beginning, speaker test still can't be ear after suspend,
and here's the diff between step3 and step6:
root@om-gta02:~# diff -u step3.state step6.state
--- step3.state
+++ step6.state
@@ -1117,4 +1117,16 @@
count 1
}
}
+ control.94 {
+ iface MIXER
+ name 'Media Volume'
+ value.0 255
+ value.1 255
+ comment {
+ access 'read write locked user'
+ type INTEGER
+ count 2
+ range '0 - 255'
+ }
+ }
}
which is something normal under fso2 images(that's because of a software volume in /etc/asound.conf, which only appear after playing something).
Denis.
comment:19 in reply to: ↑ 17 Changed 16 months ago by GNUtoo
Replying to lindi:
My theory: wm8753_suspend does not get called since the audio path is busy. This means alsa state is not restored on resume either.
what should I do?
1)check if it's not called
2)how would I fix it then? still call it?
comment:20 Changed 16 months ago by GNUtoo
I did step 1 to 4 in a console
and step 5 to 7 in a new console,
which is not what the bug reporter intended....
I'll open a new bug...
Denis
comment:21 Changed 16 months ago by GNUtoo
I've verified that the original bug reported here is fixed by the fix reported here.
Thanks a lot.
Denis.
