summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authororion <orion@FreeBSD.org>2003-04-17 15:04:11 +0000
committerorion <orion@FreeBSD.org>2003-04-17 15:04:11 +0000
commit7d2c2298b42ed0bbc811d0d9b88b750d50ec73ec (patch)
tree3e63643d8aba592aec1d472cb1595806babe39a7
parent94c5c3f52000bd6d5940e90453a25c00d7449318 (diff)
downloadFreeBSD-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.
-rw-r--r--sys/dev/sound/pci/via8233.c67
-rw-r--r--sys/dev/sound/pci/via8233.h4
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
OpenPOWER on IntegriCloud