Ticket #2478 (new defect)

Opened 3 years ago

Last modified 3 years ago

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

stereoout.state (16.3 KB) - added by lindi 3 years ago.

Change History

Changed 3 years ago by lindi

comment:1 Changed 3 years 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 3 years 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 3 years 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:4 Changed 3 years ago by lindi

comment:5 Changed 3 years 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 3 years 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 3 years 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 3 years 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 3 years 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 3 years ago by lindi

I can confirm that removing the snd_soc_dapm_ignore_suspend calls fixes the bug.

comment:11 Changed 3 years 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 3 years 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 3 years ago by lindi

So you start speaker-test, suspend and resume -- you never stop speaker-test at all?

comment:14 Changed 3 years 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 3 years 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 3 years 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 3 years 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 3 years 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 3 years 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 3 years 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 3 years ago by GNUtoo

I've verified that the original bug reported here is fixed by the fix reported here.

Thanks a lot.

Denis.

Note: See TracTickets for help on using tickets.