diff options
author | Orion Hodson <orion@FreeBSD.org> | 2003-03-26 06:11:36 +0000 |
---|---|---|
committer | Orion Hodson <orion@FreeBSD.org> | 2003-03-26 06:11:36 +0000 |
commit | abe88fc97257fa03b06523d5225169c6fb46db31 (patch) | |
tree | a1c26789d45e96775ecd055afc1eb52136b82655 /sys/dev/sound | |
parent | 8f832fd0bac9292f5783c316fcb38ef17a484518 (diff) | |
download | src-abe88fc97257fa03b06523d5225169c6fb46db31.tar.gz src-abe88fc97257fa03b06523d5225169c6fb46db31.zip |
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.
Notes
Notes:
svn path=/head/; revision=112672
Diffstat (limited to 'sys/dev/sound')
-rw-r--r-- | sys/dev/sound/pci/via82c686.c | 33 |
1 files changed, 20 insertions, 13 deletions
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; |