[prev in list] [next in list] [prev in thread] [next in thread] 

List:       netbsd-bugs
Subject:    kern/26457: ac97 is not ready after suspend/resume (fix included, should be considered for 2.0)
From:       Joachim.Thiemann () Mail ! McGill ! CA
Date:       2004-07-28 1:49:00
Message-ID: 20040728014900.99A9D11153 () narn ! netbsd ! org
[Download RAW message or body]


> Number:         26457
> Category:       kern
> Synopsis:       ac97 is not ready after suspend/resume (fix included, should be \
>                 considered for 2.0)
> Confidential:   no
> Severity:       non-critical
> Priority:       medium
> Responsible:    kern-bug-people
> State:          open
> Class:          sw-bug
> Submitter-Id:   net
> Arrival-Date:   Wed Jul 28 04:14:00 UTC 2004
> Closed-Date:
> Last-Modified:
> Originator:     Joachim Thiemann
> Release:        2.0_BETA
> Organization:
> Environment:
NetBSD codaget3002 2.0_BETA NetBSD 2.0_BETA (IBMT30) #28: Thu Jul 15 21:57:25 EDT \
2004  thiemann@codaget3002:/home/thiemann/NetBSD/sys/arch/i386/compile/IBMT30 i386

from dmesg:
auich0 at pci0 dev 31 function 5: i82801CA (ICH3) AC-97 Audio
auich0: interrupting at irq 5
auich0: ac97: Analog Devices AD1881A codec; headphone, Analog Devices Phat Stereo
auich0: ac97: ext id 1<VRA>
auich0: measured ac97 link rate at 47277 Hz, will use 48000 Hz

> Description:
After a suspend/resume cycle of a laptop, the ac97 takes some time
to power up fully.  If registers are modified before that, it
the changes are ignored.  In particular, the ac97_restore_shadow
function is ignored, and the pre-suspend mixer values are lost.
Also, the chip may get stuck in the 48000 sample rate.
> How-To-Repeat:
Have a sound file sampled at low rate (eg. 8000 or 16000 Hz)
       
audioplay soundfile.wav
(suspend)
(resume)
audioplay soundfile.wav
mixerctl -w outputs.master.mute=off
mixerctl -w inputs.dac.mute=off
audioplay soundfile.wav
> Fix:
I have patched ac97.c to 1) wait until the power register claims that all subsystems \
are powered up, and 2) try modifying the master volume, until the write actually \
suceeds.

RCS file: /cvsroot/src/sys/dev/ic/ac97.c,v
retrieving revision 1.52
diff -c -r1.52 ac97.c
*** ac97.c      24 Nov 2003 16:05:10 -0000      1.52
--- ac97.c      28 Jul 2004 04:00:46 -0000
***************
*** 702,712 ****
        struct ac97_softc *as;
        const struct ac97_source_info *si;
        int idx;

        as = (struct ac97_softc *) self;
        for (idx = 0; idx < SOURCE_INFO_SIZE; idx++) {
                si = &source_info[idx];
!               ac97_write(as, si->reg, as->shadow_reg[si->reg >> 1]);
        }

        if (as->ext_id & (AC97_EXT_AUDIO_VRA | AC97_EXT_AUDIO_DRA
--- 702,740 ----
        struct ac97_softc *as;
        const struct ac97_source_info *si;
        int idx;
+       u_int16_t val;

        as = (struct ac97_softc *) self;
+
+       /* make sure chip is fully operational */
+       for (idx = 500000; idx >= 0; idx--) {
+               ac97_read(as, AC97_REG_POWER, &val);
+               if ((val & AC97_POWER_REF) &&
+                   (val & AC97_POWER_ANL) &&
+                   (val & AC97_POWER_DAC) &&
+                   (val & AC97_POWER_ADC)) break;
+               DELAY(1);
+       }
+
+       if (idx <= 0)
+               printf( "ac97 timeout on restore\n" );
+
+       /* actually try changing a value! */
+       for (idx = 500000; idx >= 0; idx--) {
+               as->host_if->write(as->host_if->arg, AC97_REG_MASTER_VOLUME, 0x1010);
+               ac97_read(as, AC97_REG_MASTER_VOLUME, &val);
+               if (val == 0x1010) break;
+               DELAY(1);
+       }
+
+       if (idx <= 0)
+               printf( "ac97 timeout on ch reg\n" );
+
        for (idx = 0; idx < SOURCE_INFO_SIZE; idx++) {
                si = &source_info[idx];
!               /* don't "restore" to the reset reg! */
!               if (si->reg)
!                       ac97_write(as, si->reg, as->shadow_reg[si->reg >> 1]);
        }

        if (as->ext_id & (AC97_EXT_AUDIO_VRA | AC97_EXT_AUDIO_DRA

> Release-Note:
> Audit-Trail:
> Unformatted:


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic