diff options
author | Michael Shalayeff <mickey@cvs.openbsd.org> | 2002-06-09 02:31:21 +0000 |
---|---|---|
committer | Michael Shalayeff <mickey@cvs.openbsd.org> | 2002-06-09 02:31:21 +0000 |
commit | 9d88e955dcdc2e5d812dd9c2cd56b548cd01c3ad (patch) | |
tree | 99c20dd9005db60ee053eec7f8149bd1c64ee349 /sys/dev/pci | |
parent | 29d850b51edb32a5830ad3ad7566ca2fc6e3f28a (diff) |
fix resuming the eso through the powerhook; from marius aamodt eriksen <marius@gone.crockster.net> via pr2704; from the #40 train
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/eso.c | 169 | ||||
-rw-r--r-- | sys/dev/pci/esovar.h | 3 |
2 files changed, 108 insertions, 64 deletions
diff --git a/sys/dev/pci/eso.c b/sys/dev/pci/eso.c index ba4c0ba275d..8fecf1c3dfd 100644 --- a/sys/dev/pci/eso.c +++ b/sys/dev/pci/eso.c @@ -1,4 +1,4 @@ -/* $OpenBSD: eso.c,v 1.17 2002/03/14 03:16:06 millert Exp $ */ +/* $OpenBSD: eso.c,v 1.18 2002/06/09 02:31:20 mickey Exp $ */ /* $NetBSD: eso.c,v 1.3 1999/08/02 17:37:43 augustss Exp $ */ /* @@ -140,6 +140,10 @@ HIDE int eso_trigger_output(void *, void *, void *, int, void (*)(void *), void *, struct audio_params *); HIDE int eso_trigger_input(void *, void *, void *, int, void (*)(void *), void *, struct audio_params *); +HIDE void eso_setup(struct eso_softc *, int); + +HIDE void eso_powerhook(int, void *); + HIDE struct audio_hw_if eso_hw_if = { eso_open, @@ -222,8 +226,6 @@ eso_attach(parent, self, aux) pci_intr_handle_t ih; bus_addr_t vcbase; const char *intrstring; - int idx; - uint8_t a2mode; sc->sc_revision = PCI_REVISION(pa->pa_class); @@ -267,61 +269,13 @@ eso_attach(parent, self, aux) /* Enable bus mastering. */ pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, - pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) | - PCI_COMMAND_MASTER_ENABLE); - - /* Reset the device; bail out upon failure. */ - if (eso_reset(sc) != 0) { - printf(", can't reset\n"); - return; - } + pci_conf_read(pa->pa_pc, pa->pa_tag, + PCI_COMMAND_STATUS_REG) | + PCI_COMMAND_MASTER_ENABLE); - /* Select the DMA/IRQ policy: DDMA, ISA IRQ emulation disabled. */ - pci_conf_write(pa->pa_pc, pa->pa_tag, ESO_PCI_S1C, - pci_conf_read(pa->pa_pc, pa->pa_tag, ESO_PCI_S1C) & - ~(ESO_PCI_S1C_IRQP_MASK | ESO_PCI_S1C_DMAP_MASK)); + eso_setup(sc, 1); - /* Enable the relevant DMA interrupts. */ - bus_space_write_1(sc->sc_iot, sc->sc_ioh, ESO_IO_IRQCTL, - ESO_IO_IRQCTL_A1IRQ | ESO_IO_IRQCTL_A2IRQ); - - /* Set up A1's sample rate generator for new-style parameters. */ - a2mode = eso_read_mixreg(sc, ESO_MIXREG_A2MODE); - a2mode |= ESO_MIXREG_A2MODE_NEWA1 | ESO_MIXREG_A2MODE_ASYNC; - eso_write_mixreg(sc, ESO_MIXREG_A2MODE, a2mode); - - /* Set mixer regs to something reasonable, needs work. */ - for (idx = 0; idx < ESO_NGAINDEVS; idx++) { - int v; - - switch (idx) { - case ESO_MIC_PLAY_VOL: - case ESO_LINE_PLAY_VOL: - case ESO_CD_PLAY_VOL: - case ESO_MONO_PLAY_VOL: - case ESO_AUXB_PLAY_VOL: - case ESO_DAC_REC_VOL: - case ESO_LINE_REC_VOL: - case ESO_SYNTH_REC_VOL: - case ESO_CD_REC_VOL: - case ESO_MONO_REC_VOL: - case ESO_AUXB_REC_VOL: - case ESO_SPATIALIZER: - v = 0; - break; - case ESO_MASTER_VOL: - v = ESO_GAIN_TO_6BIT(AUDIO_MAX_GAIN / 2); - break; - default: - v = ESO_GAIN_TO_4BIT(AUDIO_MAX_GAIN / 2); - break; - } - sc->sc_gain[idx][ESO_LEFT] = sc->sc_gain[idx][ESO_RIGHT] = v; - eso_set_gain(sc, idx); - } - eso_set_recsrc(sc, ESO_MIXREG_ERS_MIC); - - /* Map and establish the interrupt. */ + /* map and establish the interrupt. */ if (pci_intr_map(pa, &ih)) { printf(", couldn't map interrupt\n"); return; @@ -329,7 +283,7 @@ eso_attach(parent, self, aux) intrstring = pci_intr_string(pa->pa_pc, ih); #ifdef __OpenBSD__ sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, eso_intr, sc, - sc->sc_dev.dv_xname); + sc->sc_dev.dv_xname); #else sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, eso_intr, sc); #endif @@ -358,18 +312,19 @@ eso_attach(parent, self, aux) * only, but experimenting has shown we're safe. * -kjk */ + if (ESO_VALID_DDMAC_BASE(vcbase)) { pci_conf_write(pa->pa_pc, pa->pa_tag, ESO_PCI_DDMAC, - vcbase | ESO_PCI_DDMAC_DE); + vcbase | ESO_PCI_DDMAC_DE); sc->sc_dmac_configured = 1; - + printf("%s: mapping Audio 1 DMA using VC I/O space at 0x%lx\n", - sc->sc_dev.dv_xname, (unsigned long)vcbase); + sc->sc_dev.dv_xname, (unsigned long)vcbase); } else { DPRINTF(("%s: VC I/O space at 0x%lx not suitable, deferring\n", - sc->sc_dev.dv_xname, (unsigned long)vcbase)); - sc->sc_pa = *pa; - config_defer(self, eso_defer); + sc->sc_dev.dv_xname, (unsigned long)vcbase)); + sc->sc_pa = *pa; + config_defer((struct device *)sc, eso_defer); } audio_attach_mi(&eso_hw_if, sc, &sc->sc_dev); @@ -379,6 +334,8 @@ eso_attach(parent, self, aux) aa.hdl = NULL; (void)config_found(&sc->sc_dev, &aa, audioprint); + sc->sc_powerhook = powerhook_establish(&eso_powerhook, sc); + #if 0 aa.type = AUDIODEV_TYPE_MPU; aa.hwif = NULL; @@ -388,6 +345,67 @@ eso_attach(parent, self, aux) } HIDE void +eso_setup(sc, verbose) + struct eso_softc *sc; + int verbose; +{ + struct pci_attach_args *pa = &sc->sc_pa; + uint8_t a2mode; + int idx; + + /* Reset the device; bail out upon failure. */ + if (eso_reset(sc) != 0) { + if (verbose) printf(", can't reset\n"); + return; + } + + /* Select the DMA/IRQ policy: DDMA, ISA IRQ emulation disabled. */ + pci_conf_write(pa->pa_pc, pa->pa_tag, ESO_PCI_S1C, + pci_conf_read(pa->pa_pc, pa->pa_tag, ESO_PCI_S1C) & + ~(ESO_PCI_S1C_IRQP_MASK | ESO_PCI_S1C_DMAP_MASK)); + + /* Enable the relevant DMA interrupts. */ + bus_space_write_1(sc->sc_iot, sc->sc_ioh, ESO_IO_IRQCTL, + ESO_IO_IRQCTL_A1IRQ | ESO_IO_IRQCTL_A2IRQ); + + /* Set up A1's sample rate generator for new-style parameters. */ + a2mode = eso_read_mixreg(sc, ESO_MIXREG_A2MODE); + a2mode |= ESO_MIXREG_A2MODE_NEWA1 | ESO_MIXREG_A2MODE_ASYNC; + eso_write_mixreg(sc, ESO_MIXREG_A2MODE, a2mode); + + /* Set mixer regs to something reasonable, needs work. */ + for (idx = 0; idx < ESO_NGAINDEVS; idx++) { + int v; + + switch (idx) { + case ESO_MIC_PLAY_VOL: + case ESO_LINE_PLAY_VOL: + case ESO_CD_PLAY_VOL: + case ESO_MONO_PLAY_VOL: + case ESO_AUXB_PLAY_VOL: + case ESO_DAC_REC_VOL: + case ESO_LINE_REC_VOL: + case ESO_SYNTH_REC_VOL: + case ESO_CD_REC_VOL: + case ESO_MONO_REC_VOL: + case ESO_AUXB_REC_VOL: + case ESO_SPATIALIZER: + v = 0; + break; + case ESO_MASTER_VOL: + v = ESO_GAIN_TO_6BIT(AUDIO_MAX_GAIN / 2); + break; + default: + v = ESO_GAIN_TO_4BIT(AUDIO_MAX_GAIN / 2); + break; + } + sc->sc_gain[idx][ESO_LEFT] = sc->sc_gain[idx][ESO_RIGHT] = v; + eso_set_gain(sc, idx); + } + eso_set_recsrc(sc, ESO_MIXREG_ERS_MIC); +} + +HIDE void eso_defer(self) struct device *self; { @@ -1877,3 +1895,28 @@ eso_set_gain(sc, port) eso_write_mixreg(sc, mixreg, ESO_4BIT_GAIN_TO_STEREO( sc->sc_gain[port][ESO_LEFT], sc->sc_gain[port][ESO_RIGHT])); } + + +HIDE void +eso_powerhook(why, self) + int why; + void *self; +{ + struct eso_softc *sc = (struct eso_softc *)self; + + if (why != PWR_RESUME) { + eso_halt_output(sc); + eso_halt_input(sc); + + bus_space_write_1(sc->sc_iot, sc->sc_ioh, ESO_IO_A2DMAM, 0); + bus_space_write_1(sc->sc_dmac_iot, + sc->sc_dmac_ioh, ESO_DMAC_CLEAR, 0); + bus_space_write_1(sc->sc_sb_iot, + sc->sc_sb_ioh, ESO_SB_STATUSFLAGS, 3); + + /* shut down dma */ + pci_conf_write(sc->sc_pa.pa_pc, + sc->sc_pa.pa_tag, ESO_PCI_DDMAC, 0); + } else + eso_setup(sc, 0); +} diff --git a/sys/dev/pci/esovar.h b/sys/dev/pci/esovar.h index f0bc97d7d2a..4e399369747 100644 --- a/sys/dev/pci/esovar.h +++ b/sys/dev/pci/esovar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: esovar.h,v 1.2 2002/03/14 01:26:58 millert Exp $ */ +/* $OpenBSD: esovar.h,v 1.3 2002/06/09 02:31:20 mickey Exp $ */ /* $NetBSD: esovar.h,v 1.2 1999/08/02 17:37:43 augustss Exp $ */ /* @@ -86,6 +86,7 @@ struct eso_softc { struct device sc_dev; pci_intr_handle_t * sc_ih; unsigned int sc_revision; /* PCI Revision ID */ + void * sc_powerhook; /* Optionally deferred configuration of Audio 1 DMAC I/O space */ struct pci_attach_args sc_pa; |