Patch for broken ICH5 audio on 865PERL board

5 views
Skip to first unread message

Michael van der Westhuizen

unread,
Jun 12, 2004, 3:53:14 PM6/12/04
to te...@openbsd.org
Hi All,

The following patch affects src/sys/dev/pci/auich.c
and src/sys/dev/ic/ac97.c. It's in two pieces.

The auich part of the patch brings in the following three changes from
the NetBSD version of the file:
1.49,1.57: auich_reset_codec: wait for readiness of one of all codecs
(I've applied this to auich_attach as well)
1.42: acking the wrong interrupt in auich_intr: (gsts & AUICH_PIINT)
1.58,1.56,1.55: For ICH4/ICH5, use native BARs instead of compatible
BARs. (original patch by Lars Heidieke). When native i/o mapping
fails, try compatible i/o mapping. remove/modify confusing error
messsges.

The specific issue I've been trying to resolve is on an Intel 865PERL
board, where I got the following in the dmesg:
auich0 at pci0 dev 31 function 5 "Intel 82801EB/ER AC97 Audio" rev
0x02pci_io_find: expected type i/o, found mem
: can't map codec i/o space
The auich patches resolve this completely (after applying 1.55, 1.56 and
1.58 I got codec read failures, so I applied 1.49 and 1.57 as well).
I applied 1.42 because it looked like the right thing to do - a pretty
obvious fix.

After these fixes I *still* got no audio, so I poked around in the
ac97.c CVS history in the NetBSD repo and came up with something that
looked suitable. Basically this change just reorders the register reads
slightly - the NetBSD CVS logs say "An ICH board" needs this - it
appears I have one of those boards. This is NetBSD revision 1.52 of
ac97.c.

I can now listen to song35 on my 865PERL-based system (nice), but I have
to do:
mixerctl -w outputs.surround.mute=off
before I get audio... c'est la vie. From what I can see, there's quite a
lot more synching work to be done in ac97.c to address these kinds of
oddities.

I've tested these changes on my HP d530 (where the sound did work
previously - but it needs outputs.mono to be unmuted for the internal
speaker to work). The d530 is an 865G-based system.

If the postman screws up the patch, you can find it at:
https://skanky.homeunix.net/openbsd_stuff/auich_ac97.patch

I've tested on the following devices:
(this was working all along)
auich0 at pci0 dev 31 function 5 "Intel 82801EB/ER AC97 Audio" rev 0x02:
irq 5, ICH5 AC97
ac97: codec id 0x41445374 (Analog Devices AD1981B)
ac97: codec features headphone, 20 bit DAC, No 3D Stereo
audio0 at auich0
auich0: measured ac97 link rate at 48005 Hz, will use 48000 Hz

(this used to be broken)
auich0 at pci0 dev 31 function 5 "Intel 82801EB/ER AC97 Audio" rev 0x02:
irq 3, ICH5 AC97
ac97: codec id 0x41445375 (Analog Devices AD1985)
ac97: codec features headphone, 20 bit DAC, No 3D Stereo
audio0 at auich0

Thanks to the SMP testing for reminding me that I still had these
changes lying around!

Michael

Index: sys/dev/ic/ac97.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/ac97.c,v
retrieving revision 1.43
diff -u -r1.43 ac97.c
--- sys/dev/ic/ac97.c 2004/04/23 09:31:47 1.43
+++ sys/dev/ic/ac97.c 2004/06/12 18:54:49
@@ -699,9 +699,9 @@
as->host_flags = host_if->flags(host_if->arg);

ac97_setup_defaults(as);
+ ac97_read(as, AC97_REG_RESET, &as->caps);
ac97_read(as, AC97_REG_VENDOR_ID1, &id1);
ac97_read(as, AC97_REG_VENDOR_ID2, &id2);
- ac97_read(as, AC97_REG_RESET, &as->caps);

id = (id1 << 16) | id2;
if (id) {
Index: sys/dev/pci/auich.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/auich.c,v
retrieving revision 1.39
diff -u -r1.39 auich.c
--- sys/dev/pci/auich.c 2004/05/10 20:12:49 1.39
+++ sys/dev/pci/auich.c 2004/06/12 18:54:54
@@ -67,6 +67,17 @@
/* 12.1.11 NABMBAR - native audio bus mastering base address register */
#define AUICH_NABMBAR 0x14

+/*
+ * MMBAR/MBBAR/CFG - from NetBSD auichreg.h 1.6 -> 1.7
+ */
+#define AUICH_CFG 0x41
+#define AUICH_CFG_IOSE 0x01
+/* ICH4/ICH5 native audio mixer BAR */
+#define AUICH_MMBAR 0x18
+/* ICH4/ICH5 native bus mastering BAR */
+#define AUICH_MBBAR 0x1c
+#define AUICH_S2CR 0x10000000 /* tertiary codec ready */
+
/* table 12-3. native audio bus master control registers */
#define AUICH_BDBAR 0x00 /* 8-byte aligned address */
#define AUICH_CIV 0x04 /* 5 bits current index value */
@@ -344,17 +355,55 @@
sc->sc_sts_reg = AUICH_STS;
sc->sc_sample_size = 2;
}
-
- if (pci_mapreg_map(pa, AUICH_NAMBAR, PCI_MAPREG_TYPE_IO, 0,
- &sc->iot, &sc->mix_ioh, NULL, &mix_size, 0)) {
- printf(": can't map codec i/o space\n");
- return;
- }
- if (pci_mapreg_map(pa, AUICH_NABMBAR, PCI_MAPREG_TYPE_IO, 0,
- &sc->iot, &sc->aud_ioh, NULL, &aud_size, 0)) {
- printf(": can't map device i/o space\n");
- bus_space_unmap(sc->iot, sc->mix_ioh, mix_size);
- return;
+
+ if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL &&
+ (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801DB_ACA ||
+ PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801EB_ACA)) {
+ /*
+ * Use native mode for ICH4/ICH5
+ */
+ if (pci_mapreg_map(pa, AUICH_MMBAR, PCI_MAPREG_TYPE_MEM, 0,
+ &sc->iot, &sc->mix_ioh, NULL, &mix_size,
+ 0)) {
+ csr = pci_conf_read(pa->pa_pc, pa->pa_tag, AUICH_CFG);
+ pci_conf_write(pa->pa_pc, pa->pa_tag, AUICH_CFG,
+ csr | AUICH_CFG_IOSE);
+ if (pci_mapreg_map(pa, AUICH_NAMBAR, PCI_MAPREG_TYPE_IO,
+ 0, &sc->iot, &sc->mix_ioh, NULL,
+ &mix_size, 0)) {
+ printf(": can't map compatible codec i/o "
+ "space\n");
+ return;
+ }
+ }
+ if (pci_mapreg_map(pa, AUICH_MBBAR, PCI_MAPREG_TYPE_MEM, 0,
+ &sc->iot, &sc->aud_ioh, NULL, &aud_size,
+ 0)) {
+ csr = pci_conf_read(pa->pa_pc, pa->pa_tag, AUICH_CFG);
+ pci_conf_write(pa->pa_pc, pa->pa_tag, AUICH_CFG,
+ csr | AUICH_CFG_IOSE);
+ if (pci_mapreg_map(pa, AUICH_NABMBAR,
+ PCI_MAPREG_TYPE_IO, 0, &sc->iot,
+ &sc->aud_ioh, NULL, &aud_size, 0)) {
+ printf(": can't map device i/o space\n");
+ bus_space_unmap(sc->iot, sc->mix_ioh, mix_size);
+ return;
+ }
+ }
+ } else {
+ if (pci_mapreg_map(pa, AUICH_NAMBAR, PCI_MAPREG_TYPE_IO,
+ 0, &sc->iot, &sc->mix_ioh,
+ NULL, &mix_size, 0)) {
+ printf(": can't map codec i/o space\n");
+ return;
+ }
+ if (pci_mapreg_map(pa, AUICH_NABMBAR, PCI_MAPREG_TYPE_IO,
+ 0, &sc->iot, &sc->aud_ioh,
+ NULL, &aud_size, 0)) {
+ printf(": can't map device i/o space\n");
+ bus_space_unmap(sc->iot, sc->mix_ioh, mix_size);
+ return;
+ }
}
sc->dmat = pa->pa_dmat;

@@ -407,7 +456,8 @@
/* Reset codec and AC'97 */
auich_reset_codec(sc);
status = bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GSTS);
- if (!(status & AUICH_PCR)) { /* reset failure */
+ if (!(status & (AUICH_PCR | AUICH_SCR | AUICH_S2CR))) {
+ /* reset failure */
if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL &&
PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82801DB_ACA) {
/* MSI 845G Max never return AUICH_PCR */
@@ -509,21 +559,34 @@
void *v;
{
struct auich_softc *sc = v;
- u_int32_t control;
+ u_int32_t control, status;
int i;

control = bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GCTRL);
control &= ~(AUICH_ACLSO | AUICH_PCM246_MASK);
control |= (control & AUICH_CRESET) ? AUICH_WRESET : AUICH_CRESET;
- bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_GCTRL, AUICH_CRESET);
-
- for (i = AUICH_RESETIMO; i-- &&
- !(bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GSTS) & AUICH_PCR);
- DELAY(1));
+ bus_space_write_4(sc->iot, sc->aud_ioh, AUICH_GCTRL, control);

+ for (i = AUICH_RESETIMO; i >= 0; i++) {
+ status = bus_space_read_4(sc->iot, sc->aud_ioh, AUICH_GSTS);
+ if (status & (AUICH_PCR | AUICH_SCR | AUICH_S2CR))
+ break;
+ DELAY(1);
+ }
if (i < 0)
+ {
DPRINTF(AUICH_DEBUG_CODECIO,
("%s: reset_codec timeout\n", sc->sc_dev.dv_xname));
+ } else {
+#ifdef AUICH_DEBUG
+ if (status & AUICH_SCR)
+ printf("%s: The second codec is ready.\n",
+ sc->sc_dev.dv_xname);
+ if (status & AUICH_S2CR)
+ printf("%s: The third codec is ready.\n",
+ sc->sc_dev.dv_xname);
+#endif
+ }
}

enum ac97_host_flags
@@ -1152,7 +1215,7 @@
bus_space_write_2(sc->iot, sc->aud_ioh,
AUICH_PCMI + sc->sc_sts_reg, sts &
(AUICH_LVBCI | AUICH_CELV | AUICH_BCIS | AUICH_FIFOE));
- bus_space_write_2(sc->iot, sc->aud_ioh, AUICH_GSTS, AUICH_POINT);
+ bus_space_write_2(sc->iot, sc->aud_ioh, AUICH_GSTS, AUICH_PIINT);
ret++;
}

Reply all
Reply to author
Forward
0 new messages