Bug 8621

Summary: Soundcard registers not restored after resume on intel8x0
Product: Drivers Reporter: Johannes Weiner (hannes)
Component: Sound(ALSA)Assignee: Jaroslav Kysela (perex)
Status: REJECTED WILL_NOT_FIX    
Severity: normal CC: alan, bunk, tiwai
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: 2.6.23-rc4 Subsystem:
Regression: --- Bisected commit-id:
Bug Depends on:    
Bug Blocks: 7216    
Attachments: [PATCH] AC97: Restore codec registers more assertive on resume

Description Johannes Weiner 2007-06-13 09:10:04 UTC
Distribution:
  Slackware Linux, but custom-configured kernel from kernel.org

Hardware Environment:
  IBM ThinkPad X22
  Intel Corporation 82801CA/CAM AC'97 Audio Controller

Problem Description:
  When resuming from disk, the AC97 registers are not restored.
  alsamixer shows me correct values - the settings from before
  the suspension - but they are not in sync with the hardware.
  When I change (mute/unmute or increase/decrease) the volume,
  the settings for the specific channel are getting back in sync.
  So after suspend-resume, I modify Master and PCM and sound is
  works again.

Steps to reproduce:
  0. Have an intel8x0 ICH3 soundcard using the Cirrus Logic CS4299 rev 6 AC-97 codec.
  1. Do some mixer settings with alsamixer.
  2. Suspend the box.
  3. Resume the box.
  4. Have no sound until you change settings for the channels you have to use (Master and PCM in my case).

What I found out myself:
  I debugged the snd_ac97_write()'s in snd_ac97_restore_status() by printing what the cache register contains before it is written to the hardware register and then printing the return value of snd_ac97_read(). This was in my dmesg after a suspend/resume cycle:

-----------
snd_ac97_restore_status(): restoring register 0x2 to value 0x0
snd_ac97_restore_status(): register 0x2 now contains 0x8000
snd_ac97_restore_status(): restoring register 0x4 to value 0x91f
snd_ac97_restore_status(): register 0x4 now contains 0x8000
...
-----------

The values that should be written out reflect the true settings that were valid before the suspension. But they seem not to be written out to the regs.

-----------

$ cat /proc/asound/card0/codec97#0/codec97#0-0+regs > before
# suspend/resume
$ cat /proc/asound/card0/codec97#0/codec97#0-0+regs > after
$ diff -Naur before after
...
-0:02 = 0000
-0:04 = 91f1
...
+0:02 = 8000
+0:04 = 8000
...

-----------

Hope this helps,
Hannes
Comment 1 Johannes Weiner 2007-06-13 17:15:07 UTC
I have found a fix for it, patch attached.
This also works for the laptop of my girlfriend that (who?) had the same problem as described.

Her laptop:

  Distro: Gentoo Linux, custom-configured kernel from kernel.org version 2.6.21.1
  Hardware: HP Compaq nx6125 with atiixp sb400, ac97 codec: Conexant id 30
Comment 2 Johannes Weiner 2007-06-13 17:18:29 UTC
Created attachment 11744 [details]
[PATCH] AC97: Restore codec registers more assertive on resume

Patched against current snapshot of linux-2.6.git. Tested successfully on two boxes using AC97 codec with different hardware.
Comment 3 Johannes Weiner 2007-06-14 10:53:44 UTC
Crap, my girlfriend noticed that the sound randomly stays muted. I'll investigate on it.
Comment 4 Johannes Weiner 2007-06-14 16:17:54 UTC
Further experiments showed up, that either the waiting times in ac97_codec.c should be increased or that the driver-specific _codec_read/_codec_write functions should be more caring that it happens what they are up to.

I found out that it is important before writing the device, there should be a wait-loop for the AC97_POWERDOWN register to become !0.

Increasing the timeouts in the loops 'fixes' the problem in the sense that the registers are restored properly, but I don't think that it is the right place for fixing. The codec should not take up to 2 seconds to get ready.
Comment 5 Rafael J. Wysocki 2007-08-20 09:44:48 UTC
Can you check if this problem is also present in the 2.6.23-rc2 kernel?
Comment 6 Johannes Weiner 2007-08-30 08:34:41 UTC
I tried it with 2.6.23-rc4, the registers still don't get restored.
I catted /proc/asound/card0/codec97#0/ac97#0-0+regs before and after the resume, without doing anything in between.
Here is the diff:

symbol [~] :) diff -Naur asound-regs-before asound-regs-after 
--- asound-regs-before  2007-08-30 17:21:13.000000000 +0200
+++ asound-regs-after   2007-08-30 17:22:05.000000000 +0200
@@ -1,5 +1,5 @@
 0:00 = 1990
-0:02 = 0000
+0:02 = 8000
 0:04 = 8000
 0:06 = 8000
 0:08 = 0000
@@ -10,7 +10,7 @@
 0:12 = 8808
 0:14 = 8808
 0:16 = 8808
-0:18 = 0c0c
+0:18 = 8808
 0:1a = 0000
 0:1c = 8000
 0:1e = 0000

I can try with 2.6.23-rc2 if that is important.
Comment 7 Rafael J. Wysocki 2007-09-12 09:57:10 UTC
No, thanks.
Comment 8 Alan 2009-03-23 11:05:46 UTC
Closing out old stale bugs