Perform warm or cold reset AC97 per the spec depending on state of the

codec during initialization.  This code mirrors the reset code used on
the VIA82c686 and fixes a codec initialization failure (SoundMAX
AD1885) reported by Matthias Schuendehuette.
This commit is contained in:
Orion Hodson 2003-04-17 15:04:11 +00:00
parent ecbe520722
commit 5a289baba9
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=113598
2 changed files with 47 additions and 20 deletions

View File

@ -653,33 +653,56 @@ dma_cb(void *p, bus_dma_segment_t *bds, int a, int b)
static int
via_chip_init(device_t dev)
{
int i, s;
u_int32_t data, cnt;
pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 0, 1);
DELAY(100);
/* Wake up and reset AC97 if necessary */
data = pci_read_config(dev, VIA_PCI_ACLINK_STAT, 1);
/* assert ACLink reset */
pci_write_config(dev, VIA_PCI_ACLINK_CTRL, VIA_PCI_ACLINK_NRST, 1);
DELAY(2);
if ((data & VIA_PCI_ACLINK_C00_READY) == 0) {
/* Cold reset per ac97r2.3 spec (page 95) */
/* Assert low */
pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
VIA_PCI_ACLINK_EN, 1);
/* Wait T_rst_low */
DELAY(100);
/* Assert high */
pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
VIA_PCI_ACLINK_EN | VIA_PCI_ACLINK_NRST, 1);
/* Wait T_rst2clk */
DELAY(5);
/* Assert low */
pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
VIA_PCI_ACLINK_EN, 1);
} else {
/* Warm reset */
/* Force no sync */
pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
VIA_PCI_ACLINK_EN, 1);
DELAY(100);
/* Sync */
pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
VIA_PCI_ACLINK_EN | VIA_PCI_ACLINK_SYNC, 1);
/* Wait T_sync_high */
DELAY(5);
/* Force no sync */
pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
VIA_PCI_ACLINK_EN, 1);
/* Wait T_sync2clk */
DELAY(5);
}
/* deassert ACLink reset, force SYNC (warm AC'97 reset) */
pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
VIA_PCI_ACLINK_NRST | VIA_PCI_ACLINK_SYNC, 1);
/* Power everything up */
pci_write_config(dev, VIA_PCI_ACLINK_CTRL, VIA_PCI_ACLINK_DESIRED, 1);
/* ACLink on, deassert ACLink reset, VSR, SGD data out */
pci_write_config(dev, VIA_PCI_ACLINK_CTRL,
VIA_PCI_ACLINK_EN | VIA_PCI_ACLINK_NRST
| VIA_PCI_ACLINK_VRATE | VIA_PCI_ACLINK_SGD, 1);
for (i = 0; i < 100; i++) {
s = pci_read_config(dev, VIA_PCI_ACLINK_STAT, 1);
if (s & VIA_PCI_ACLINK_C00_READY) {
s = pci_read_config(dev, VIA_PCI_ACLINK_CTRL, 1);
/* Wait for codec to become ready (largest reported delay 310ms) */
for (cnt = 0; cnt < 2000; cnt++) {
data = pci_read_config(dev, VIA_PCI_ACLINK_STAT, 1);
if (data & VIA_PCI_ACLINK_C00_READY) {
return 0;
}
DELAY(10);
DELAY(5000);
}
device_printf(dev, "primary codec not ready (s = 0x%02x)\n", s);
device_printf(dev, "primary codec not ready (cnt = 0x%02x)\n", cnt);
return ENXIO;
}

View File

@ -72,6 +72,10 @@
# define VIA_PCI_ACLINK_SERIAL 0x10
# define VIA_PCI_ACLINK_VRATE 0x08
# define VIA_PCI_ACLINK_SGD 0x04
# define VIA_PCI_ACLINK_DESIRED (VIA_PCI_ACLINK_EN | \
VIA_PCI_ACLINK_NRST | \
VIA_PCI_ACLINK_VRATE | \
VIA_PCI_ACLINK_SGD)
#define VIA_MC_SGD_STATUS 0x40
#define VIA_WR0_SGD_STATUS 0x60