From abe88fc97257fa03b06523d5225169c6fb46db31 Mon Sep 17 00:00:00 2001 From: Orion Hodson Date: Wed, 26 Mar 2003 06:11:36 +0000 Subject: 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 for reporting the problem, providing useful pointers, and repeated diff testing. --- sys/dev/sound/pci/via82c686.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'sys/dev/sound') diff --git a/sys/dev/sound/pci/via82c686.c b/sys/dev/sound/pci/via82c686.c index b76987f87677..262ac5ac60f0 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; -- cgit v1.2.3