summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authororion <orion@FreeBSD.org>2003-03-26 06:11:36 +0000
committerorion <orion@FreeBSD.org>2003-03-26 06:11:36 +0000
commit24e75d3601d3dbdf2f3fe8108ce212c0ccacdc1f (patch)
treea1c26789d45e96775ecd055afc1eb52136b82655
parent37d7dbbe56ec1ddca7525dce4758b065dca447ac (diff)
downloadFreeBSD-src-24e75d3601d3dbdf2f3fe8108ce212c0ccacdc1f.zip
FreeBSD-src-24e75d3601d3dbdf2f3fe8108ce212c0ccacdc1f.tar.gz
Re-work ac97 initialization to match cold reset described in AC97r.23
and be prepared to wait much longer for codec to become ready. Credit to Hugo D. Valentim <hvalentim@gmx.net> for reporting the problem, providing useful pointers, and repeated diff testing.
-rw-r--r--sys/dev/sound/pci/via82c686.c33
1 files changed, 20 insertions, 13 deletions
diff --git a/sys/dev/sound/pci/via82c686.c b/sys/dev/sound/pci/via82c686.c
index b76987f..262ac5a 100644
--- a/sys/dev/sound/pci/via82c686.c
+++ b/sys/dev/sound/pci/via82c686.c
@@ -462,7 +462,7 @@ via_attach(device_t dev)
{
struct via_info *via = 0;
char status[SND_STATUSLEN];
- u_int32_t data;
+ u_int32_t data, cnt;
if ((via = malloc(sizeof *via, M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
device_printf(dev, "cannot allocate softc\n");
@@ -476,18 +476,25 @@ via_attach(device_t dev)
data = pci_read_config(dev, PCIR_COMMAND, 2);
/* Wake up and reset AC97 if necessary */
- if (!(pci_read_config(dev, VIA_AC97STATUS, 1) & VIA_AC97STATUS_RDY)) {
- pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_EN | VIA_ACLINK_NRST | VIA_ACLINK_SYNC, 1);
- DELAY(1000);
- pci_write_config(dev, VIA_ACLINKCTRL, 0, 1);
- DELAY(1000);
- pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_DESIRED, 1);
- DELAY(1000);
- }
-
- if (pci_read_config(dev, VIA_ACLINKCTRL, 1) != VIA_ACLINK_DESIRED) {
- pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_DESIRED, 1);
- DELAY(1000);
+ data = pci_read_config(dev, VIA_AC97STATUS, 1);
+ if ((data & VIA_AC97STATUS_RDY) == 0) {
+ /* Cold reset per ac97r2.3 spec (page 95) */
+ pci_write_config(dev, VIA_ACLINKCTRL, 0, 1); /* Assert low */
+ DELAY(100); /* Wait T_rst_low */
+ pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_NRST, 1); /* Assert high */
+ DELAY(1); /* Wait T_rst2clk */
+ pci_write_config(dev, VIA_ACLINKCTRL, 0, 1); /* Assert low */
+
+ /* Power everything up */
+ pci_write_config(dev, VIA_ACLINKCTRL, VIA_ACLINK_DESIRED, 1);
+
+ /* Wait for codec to become ready (largest reported delay here 310ms) */
+ for (cnt = 0; cnt < 2000; cnt++) {
+ data = pci_read_config(dev, VIA_AC97STATUS, 1);
+ if (data & VIA_AC97STATUS_RDY)
+ break;
+ DELAY(5000);
+ }
}
via->regid = PCIR_MAPS;
OpenPOWER on IntegriCloud