Subject: Fix for ac97.c
To: None <tech-kern@netbsd.org>
From: Julio M. Merino Vidal <jmmv@menta.net>
List: tech-kern
Date: 09/09/2003 14:21:49
Hi all,

I have an Asus motherboard that comes with the AD1980 ac97 codec.  At first, I had
ioapic and MPACPI compiled in the kernel, without pnpbios, and I got the following
messages when auvia was configured:

Sep  8 21:11:30 dawn /netbsd: auvia0 at pci0 dev 17 function 5: VIA VT8235 AC'97 Audio (rev 0x50)
Sep  8 21:11:30 dawn /netbsd: auvia0: interrupting at ioapic0 pin 22 (irq 9)
Sep  8 21:11:30 dawn /netbsd: auvia0: codec busy
Sep  8 21:11:30 dawn /netbsd: auvia0: ac97: Analog Devices AD1980 codec; headphone, 20 bit DAC, no 3D stereo
Sep  8 21:11:30 dawn /netbsd: auvia0: ac97: ext id 3c7<AMAP,LDAC,SDAC,CDAC,SPDIF,DRA,VRA>

Note the "codec busy" message.  Although, the sound card worked properly.

Yesterday I switched the kernel to use pnpbios and apm, instead of ioapic and MPACPI
because I didn't had power control support.  The following messages were printed:

Sep  9 12:44:26 dawn /netbsd: auvia0 at pci0 dev 17 function 5: VIA VT8235 AC'97 Audio (rev 0x50)
Sep  9 12:44:26 dawn /netbsd: auvia0: interrupting at irq 9
Sep  9 12:44:26 dawn /netbsd: auvia0: codec invalid
Sep  9 12:44:26 dawn /netbsd: auvia0: ac97: unknown (0x00005370) codec; headphone, 20 bit DAC, no 3D stereo
Sep  9 12:44:26 dawn /netbsd: auvia0: ac97: ext id 3c7<AMAP,LDAC,SDAC,CDAC,SPDIF,DRA,VRA>
Sep  9 12:44:26 dawn /netbsd: audio0 at auvia0: full duplex, mmap, independent

Note the "codec invalid" message.  The sound card does not work.  Also note that the
high 16 bits of the id are all 0's: this word is readed in the first place in ac97.c,
just after the code resets the codec.

So I went and got ad1980 specifications.  As I understand (which may be wrong...), the
card needs a delay of 50ns (maximun) after a reset to be up again.  So I added that
delay just after the reset register is written, and all problem have gone away.
No more "code invalid" nor "codec busy".

Attached below are two patches.  Which one looks better? (if any of them is right)

Index: ac97.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/ac97.c,v
retrieving revision 1.46
diff -u -r1.46 ac97.c
--- ac97.c	2003/09/08 13:58:21	1.46
+++ ac97.c	2003/09/09 12:21:04
@@ -894,6 +894,7 @@
 
 	host_if->write(host_if->arg, AC97_REG_POWER, 0);
 	host_if->write(host_if->arg, AC97_REG_RESET, 0);
+	delay(50);
 
 	if (host_if->flags)
 		as->host_flags = host_if->flags(host_if->arg);

Index: ac97.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/ac97.c,v
retrieving revision 1.46
diff -u -r1.46 ac97.c
--- ac97.c	2003/09/08 13:58:21	1.46
+++ ac97.c	2003/09/09 12:05:53
@@ -685,10 +685,14 @@
 	u_int8_t reg;
 	u_int16_t val;
 {
+	int res;
 
 	as->shadow_reg[reg >> 1] = val;
 
-	return (as->host_if->write(as->host_if->arg, reg, val));
+	res = as->host_if->write(as->host_if->arg, reg, val);
+	if (reg == AC97_REG_RESET)
+		delay(50);
+	return res;
 }
 
 void


Thanks.

-- 
Julio M. Merino Vidal <jmmv@menta.net>
The NetBSD Project - http://www.NetBSD.org/