diff options
author | orion <orion@FreeBSD.org> | 2001-04-04 13:48:33 +0000 |
---|---|---|
committer | orion <orion@FreeBSD.org> | 2001-04-04 13:48:33 +0000 |
commit | 98f3e45dfe64cd33cfeab2bc3e07b6d9a6d4647c (patch) | |
tree | fd82522111bc70505a44f98445564b25b3a4ae10 /sys | |
parent | 7ac0ff015f9982b79239d070c36511a8526065f9 (diff) | |
download | FreeBSD-src-98f3e45dfe64cd33cfeab2bc3e07b6d9a6d4647c.zip FreeBSD-src-98f3e45dfe64cd33cfeab2bc3e07b6d9a6d4647c.tar.gz |
Centralize DMA buffer configuration.
Simplify initialization and remove offending DMA channel resets there.
The resets trash whatever is pointed to DMA registers, but at cmi_attach()
time the DMA registers have not been initialized with valid addresses.
Reviewed by: Cameron Grant <gandalf@vilnya.demon.co.uk>
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/sound/pci/cmi.c | 91 |
1 files changed, 38 insertions, 53 deletions
diff --git a/sys/dev/sound/pci/cmi.c b/sys/dev/sound/pci/cmi.c index a6e7b23..ae0a23a 100644 --- a/sys/dev/sound/pci/cmi.c +++ b/sys/dev/sound/pci/cmi.c @@ -104,7 +104,7 @@ struct sc_info { bus_space_tag_t st; bus_space_handle_t sh; bus_dma_tag_t parent_dmat; - struct resource *reg, *irq; + struct resource *reg, *irq; int regid, irqid; void *ih; @@ -232,23 +232,32 @@ cmpci_regvalue_to_rate(u_int32_t r) * playback or capture. We use ch0 for playback and ch1 for capture. */ static void -cmi_ch0_start(struct sc_info *sc, struct sc_chinfo *ch) +cmi_dma_prog(struct sc_info *sc, struct sc_chinfo *ch, u_int32_t base) { - u_int32_t s, i, sz; + u_int32_t s, i, sz, physbuf; - ch->phys_buf = vtophys(sndbuf_getbuf(ch->buffer)); - cmi_wr(sc, CMPCI_REG_DMA0_BASE, ch->phys_buf, 4); + physbuf = vtophys(sndbuf_getbuf(ch->buffer)); + cmi_wr(sc, base, physbuf, 4); sz = (u_int32_t)sndbuf_getsize(ch->buffer); s = sz / ch->bps - 1; - cmi_wr(sc, CMPCI_REG_DMA0_MAX_SAMPLES, s, 2); + cmi_wr(sc, base + 4, s, 2); i = sz / (ch->bps * CMI_INTR_PER_BUFFER) - 1; - cmi_wr(sc, CMPCI_REG_DMA0_INTR_SAMPLES, i, 2); + cmi_wr(sc, base + 6, i, 2); +} + + +static void +cmi_ch0_start(struct sc_info *sc, struct sc_chinfo *ch) +{ + cmi_dma_prog(sc, ch, CMPCI_REG_DMA0_BASE); + + cmi_set4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE); + cmi_set4(sc, CMPCI_REG_INTR_CTRL, + CMPCI_REG_CH0_INTR_ENABLE); - DEB(printf("cmi_ch0_start: dma prog\n")); - cmi_clr4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_PAUSE); ch->dma_active = 1; } @@ -257,8 +266,8 @@ cmi_ch0_stop(struct sc_info *sc, struct sc_chinfo *ch) { u_int32_t r = ch->dma_active; - cmi_set4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_PAUSE); - DEB(printf("cmi_ch0_reset\n")); + cmi_clr4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE); + cmi_clr4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE); ch->dma_active = 0; return r; } @@ -266,19 +275,12 @@ cmi_ch0_stop(struct sc_info *sc, struct sc_chinfo *ch) static void cmi_ch1_start(struct sc_info *sc, struct sc_chinfo *ch) { - u_int32_t s, i, sz; - - ch->phys_buf = vtophys(sndbuf_getbuf(ch->buffer)); - cmi_wr(sc, CMPCI_REG_DMA1_BASE, ch->phys_buf, 4); - - sz = (u_int32_t)sndbuf_getsize(ch->buffer); - s = sz / ch->bps - 1; - cmi_wr(sc, CMPCI_REG_DMA1_MAX_SAMPLES, s, 2); - i = sz / (ch->bps * CMI_INTR_PER_BUFFER) - 1; - cmi_wr(sc, CMPCI_REG_DMA1_INTR_SAMPLES, i, 2); - + cmi_dma_prog(sc, ch, CMPCI_REG_DMA1_BASE); + cmi_set4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE); + /* Enable Interrupts */ + cmi_set4(sc, CMPCI_REG_INTR_CTRL, + CMPCI_REG_CH1_INTR_ENABLE); DEB(printf("cmi_ch1_start: dma prog\n")); - cmi_clr4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_PAUSE); ch->dma_active = 1; } @@ -287,8 +289,8 @@ cmi_ch1_stop(struct sc_info *sc, struct sc_chinfo *ch) { u_int32_t r = ch->dma_active; - cmi_clr4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_PAUSE); - DEB(printf("cmi_ch1_reset\n")); + cmi_clr4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE); + cmi_clr4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE); ch->dma_active = 0; return r; } @@ -337,10 +339,10 @@ cmichan_init(kobj_t obj, void *devinfo, } ch->dir = dir; - if (dir == PCMDIR_PLAY) { - cmi_clr4(ch->parent, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_DIR); + if (ch->dir == PCMDIR_PLAY) { + cmi_dma_prog(sc, ch, CMPCI_REG_DMA0_BASE); } else { - cmi_set4(ch->parent, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_DIR); + cmi_dma_prog(sc, ch, CMPCI_REG_DMA1_BASE); } return ch; @@ -728,12 +730,14 @@ cmi_init(struct sc_info *sc) cmi_clr4(sc, CMPCI_REG_MISC, CMPCI_REG_BUS_AND_DSP_RESET); /* Disable interrupts and channels */ - cmi_clr4(sc, CMPCI_REG_INTR_CTRL, - CMPCI_REG_CH0_INTR_ENABLE | - CMPCI_REG_CH1_INTR_ENABLE | - CMPCI_REG_TDMA_INTR_ENABLE); cmi_clr4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE | CMPCI_REG_CH1_ENABLE); + cmi_clr4(sc, CMPCI_REG_INTR_CTRL, + CMPCI_REG_CH0_INTR_ENABLE | CMPCI_REG_CH1_INTR_ENABLE); + + /* Configure DMA channels, ch0 = play, ch1 = capture */ + cmi_clr4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_DIR); + cmi_set4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_DIR); /* Attempt to enable 4 Channel output */ cmi_set4(sc, CMPCI_REG_MISC, CMPCI_REG_N4SPK3D); @@ -742,26 +746,6 @@ cmi_init(struct sc_info *sc) cmi_clr4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIF1_ENABLE); cmi_clr4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIF_LOOP); - /* Reset DMA Channels */ - cmi_set4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET); - cmi_set4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET); - DELAY(100); - cmi_clr4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET); - cmi_clr4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET); - - /* Configure DMA channels, ch0 = play, ch1 = capture */ - cmi_clr4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_DIR); - cmi_set4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE); - cmi_set4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_PAUSE); - - cmi_set4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_DIR); - cmi_set4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE); - cmi_set4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_PAUSE); - - /* Enable Interrupts */ - cmi_set4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE); - cmi_set4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE); - return 0; } @@ -852,7 +836,8 @@ cmi_attach(device_t dev) } cmi_power(sc, 0); - cmi_init(sc); + if (cmi_init(sc)) + goto bad; if (mixer_init(dev, &cmi_mixer_class, sc)) goto bad; |