diff options
author | orion <orion@FreeBSD.org> | 2003-04-17 15:04:11 +0000 |
---|---|---|
committer | orion <orion@FreeBSD.org> | 2003-04-17 15:04:11 +0000 |
commit | 7d2c2298b42ed0bbc811d0d9b88b750d50ec73ec (patch) | |
tree | 3e63643d8aba592aec1d472cb1595806babe39a7 /sys/dev/sound/pci | |
parent | 94c5c3f52000bd6d5940e90453a25c00d7449318 (diff) | |
download | FreeBSD-src-7d2c2298b42ed0bbc811d0d9b88b750d50ec73ec.zip FreeBSD-src-7d2c2298b42ed0bbc811d0d9b88b750d50ec73ec.tar.gz |
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.
Diffstat (limited to 'sys/dev/sound/pci')
-rw-r--r-- | sys/dev/sound/pci/via8233.c | 67 | ||||
-rw-r--r-- | sys/dev/sound/pci/via8233.h | 4 |
2 files changed, 49 insertions, 22 deletions
diff --git a/sys/dev/sound/pci/via8233.c b/sys/dev/sound/pci/via8233.c index 883012c..f8f136e 100644 --- a/sys/dev/sound/pci/via8233.c +++ b/sys/dev/sound/pci/via8233.c @@ -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; - - pci_write_config(dev, VIA_PCI_ACLINK_CTRL, 0, 1); - DELAY(100); - - /* assert ACLink reset */ - pci_write_config(dev, VIA_PCI_ACLINK_CTRL, VIA_PCI_ACLINK_NRST, 1); - DELAY(2); - - /* 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); + u_int32_t data, cnt; + + /* Wake up and reset AC97 if necessary */ + data = pci_read_config(dev, VIA_PCI_ACLINK_STAT, 1); + + 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); + } - /* 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); + /* Power everything up */ + pci_write_config(dev, VIA_PCI_ACLINK_CTRL, VIA_PCI_ACLINK_DESIRED, 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; } diff --git a/sys/dev/sound/pci/via8233.h b/sys/dev/sound/pci/via8233.h index f0caca5..bc6f57a 100644 --- a/sys/dev/sound/pci/via8233.h +++ b/sys/dev/sound/pci/via8233.h @@ -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 |