summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorariff <ariff@FreeBSD.org>2007-07-09 20:41:23 +0000
committerariff <ariff@FreeBSD.org>2007-07-09 20:41:23 +0000
commitb4aac62135e0cf64cd595db2f860f0a9c7b6e960 (patch)
tree5ce04992b37ecd801608c8ff9f7e0d6e3b4d6edd /sys
parentc9dd6df88ff12cb0d8571544d31188c8f701f63c (diff)
downloadFreeBSD-src-b4aac62135e0cf64cd595db2f860f0a9c7b6e960.zip
FreeBSD-src-b4aac62135e0cf64cd595db2f860f0a9c7b6e960.tar.gz
Fix stream suspend/resume activity due to its states being
clobbered by pcm channel start/stop trigger operation. Approved by: re (hrs)
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/sound/pci/atiixp.c39
1 files changed, 27 insertions, 12 deletions
diff --git a/sys/dev/sound/pci/atiixp.c b/sys/dev/sound/pci/atiixp.c
index 6842c29..777e1b1 100644
--- a/sys/dev/sound/pci/atiixp.c
+++ b/sys/dev/sound/pci/atiixp.c
@@ -74,6 +74,9 @@ SND_DECLARE_FILE("$FreeBSD$");
#define ATI_IXP_BLK_MIN 32
#define ATI_IXP_BLK_ALIGN (~(ATI_IXP_BLK_MIN - 1))
+#define ATI_IXP_CHN_RUNNING 0x00000001
+#define ATI_IXP_CHN_SUSPEND 0x00000002
+
struct atiixp_dma_op {
volatile uint32_t addr;
volatile uint16_t status;
@@ -93,7 +96,8 @@ struct atiixp_chinfo {
uint32_t blksz, blkcnt;
uint32_t ptr, prevptr;
uint32_t fmt;
- int caps_32bit, dir, active;
+ uint32_t flags;
+ int caps_32bit, dir;
};
struct atiixp_info {
@@ -654,7 +658,7 @@ atiixp_poll_channel(struct atiixp_chinfo *ch)
uint32_t sz, delta;
volatile uint32_t ptr;
- if (ch->active == 0)
+ if (!(ch->flags & ATI_IXP_CHN_RUNNING))
return (0);
sz = ch->blksz * ch->blkcnt;
@@ -672,7 +676,8 @@ atiixp_poll_channel(struct atiixp_chinfo *ch)
return (1);
}
-#define atiixp_chan_active(sc) ((sc)->pch.active + (sc)->rch.active)
+#define atiixp_chan_active(sc) (((sc)->pch.flags | (sc)->rch.flags) & \
+ ATI_IXP_CHN_RUNNING)
static void
atiixp_poll_callback(void *arg)
@@ -754,19 +759,19 @@ atiixp_chan_trigger(kobj_t obj, void *data, int go)
atiixp_poll_callback, sc);
}
}
- ch->active = 1;
+ ch->flags |= ATI_IXP_CHN_RUNNING;
break;
case PCMTRIG_STOP:
case PCMTRIG_ABORT:
atiixp_disable_dma(ch);
atiixp_flush_dma(ch);
- ch->active = 0;
+ ch->flags &= ~ATI_IXP_CHN_RUNNING;
if (sc->polling != 0) {
if (atiixp_chan_active(sc) == 0) {
callout_stop(&sc->poll_timer);
sc->poll_ticks = 1;
} else {
- if (sc->pch.active != 0)
+ if (sc->pch.flags & ATI_IXP_CHN_RUNNING)
ch = &sc->pch;
else
ch = &sc->rch;
@@ -874,9 +879,11 @@ atiixp_intr(void *p)
return;
}
- if ((status & ATI_REG_ISR_OUT_STATUS) && sc->pch.active != 0)
+ if ((status & ATI_REG_ISR_OUT_STATUS) &&
+ (sc->pch.flags & ATI_IXP_CHN_RUNNING))
trigger |= 1;
- if ((status & ATI_REG_ISR_IN_STATUS) && sc->rch.active != 0)
+ if ((status & ATI_REG_ISR_IN_STATUS) &&
+ (sc->rch.flags & ATI_IXP_CHN_RUNNING))
trigger |= 2;
#if 0
@@ -1332,10 +1339,14 @@ atiixp_pci_suspend(device_t dev)
atiixp_unlock(sc);
/* stop everything */
- if (sc->pch.active != 0)
+ if (sc->pch.flags & ATI_IXP_CHN_RUNNING) {
atiixp_chan_trigger(NULL, &sc->pch, PCMTRIG_STOP);
- if (sc->rch.active != 0)
+ sc->pch.flags |= ATI_IXP_CHN_SUSPEND;
+ }
+ if (sc->rch.flags & ATI_IXP_CHN_RUNNING) {
atiixp_chan_trigger(NULL, &sc->rch, PCMTRIG_STOP);
+ sc->rch.flags |= ATI_IXP_CHN_SUSPEND;
+ }
/* power down aclink and pci bus */
atiixp_lock(sc);
@@ -1374,14 +1385,18 @@ atiixp_pci_resume(device_t dev)
if (sc->pch.channel != NULL) {
if (sc->pch.fmt != 0)
atiixp_chan_setformat(NULL, &sc->pch, sc->pch.fmt);
- if (sc->pch.active != 0)
+ if (sc->pch.flags & ATI_IXP_CHN_SUSPEND) {
+ sc->pch.flags &= ~ATI_IXP_CHN_SUSPEND;
atiixp_chan_trigger(NULL, &sc->pch, PCMTRIG_START);
+ }
}
if (sc->rch.channel != NULL) {
if (sc->rch.fmt != 0)
atiixp_chan_setformat(NULL, &sc->rch, sc->rch.fmt);
- if (sc->rch.active != 0)
+ if (sc->rch.flags & ATI_IXP_CHN_SUSPEND) {
+ sc->rch.flags &= ~ATI_IXP_CHN_SUSPEND;
atiixp_chan_trigger(NULL, &sc->rch, PCMTRIG_START);
+ }
}
/* enable interrupts */
OpenPOWER on IntegriCloud