summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>2002-06-09 02:31:21 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>2002-06-09 02:31:21 +0000
commit9d88e955dcdc2e5d812dd9c2cd56b548cd01c3ad (patch)
tree99c20dd9005db60ee053eec7f8149bd1c64ee349 /sys/dev/pci
parent29d850b51edb32a5830ad3ad7566ca2fc6e3f28a (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.c169
-rw-r--r--sys/dev/pci/esovar.h3
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;