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:
parent
ecbe520722
commit
5a289baba9
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user