summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authororion <orion@FreeBSD.org>2001-12-21 19:20:28 +0000
committerorion <orion@FreeBSD.org>2001-12-21 19:20:28 +0000
commit748fd602244c4f8e5a41d22992ce946e0de1ab0c (patch)
tree20b165662bc52dded489ff819f6303d66dab4640 /sys
parent7ee7696269e25ee988354fd96bde6b69a11bddc5 (diff)
downloadFreeBSD-src-748fd602244c4f8e5a41d22992ce946e0de1ab0c.zip
FreeBSD-src-748fd602244c4f8e5a41d22992ce946e0de1ab0c.tar.gz
Save and restore state for suspend/resume.
PR: kern/28692 Obtained from: SAKIYAMA Nobuo <sakichan@sakichan.org>
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/sound/pci/ich.c39
1 files changed, 35 insertions, 4 deletions
diff --git a/sys/dev/sound/pci/ich.c b/sys/dev/sound/pci/ich.c
index fd391e5..9b0a757 100644
--- a/sys/dev/sound/pci/ich.c
+++ b/sys/dev/sound/pci/ich.c
@@ -51,8 +51,8 @@ struct sc_info;
/* channel registers */
struct sc_chinfo {
- u_int32_t num, run;
- u_int32_t blksz, blkcnt;
+ u_int32_t num:8, run:1, run_save:1;
+ u_int32_t blksz, blkcnt, spd;
u_int32_t regbase, spdreg;
u_int32_t imask;
u_int32_t civ;
@@ -294,11 +294,12 @@ ichchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
if (sc->ac97rate <= 32000 || sc->ac97rate >= 64000)
sc->ac97rate = 48000;
r = speed * 48000 / sc->ac97rate;
- return ac97_setrate(sc->codec, ch->spdreg, r) *
+ ch->spd = ac97_setrate(sc->codec, ch->spdreg, r) *
sc->ac97rate / 48000;
} else {
- return 48000;
+ ch->spd = 48000;
}
+ return ch->spd;
}
static int
@@ -679,9 +680,29 @@ ich_pci_detach(device_t dev)
}
static int
+ich_pci_suspend(device_t dev)
+{
+ struct sc_info *sc;
+ int i;
+
+ sc = pcm_getdevinfo(dev);
+ for (i = 0 ; i < 3; i++) {
+ sc->ch[i].run_save = sc->ch[i].run;
+ if (sc->ch[i].run) {
+ ichchan_trigger(0, &sc->ch[i], PCMTRIG_ABORT);
+ }
+ }
+
+ /* ACLINK shut off */
+ ich_wr(sc,ICH_REG_GLOB_CNT, ICH_GLOB_CTL_SHUT, 4);
+ return 0;
+}
+
+static int
ich_pci_resume(device_t dev)
{
struct sc_info *sc;
+ int i;
sc = pcm_getdevinfo(dev);
@@ -695,6 +716,15 @@ ich_pci_resume(device_t dev)
device_printf(dev, "unable to reinitialize the mixer\n");
return ENXIO;
}
+ /* Re-start DMA engines */
+ for (i = 0 ; i < 3; i++) {
+ struct sc_chinfo *ch = &sc->ch[i];
+ if (sc->ch[i].run_save) {
+ ichchan_setblocksize(0, ch, ch->blksz);
+ ichchan_setspeed(0, ch, ch->spd);
+ ichchan_trigger(0, ch, PCMTRIG_START);
+ }
+ }
return 0;
}
@@ -703,6 +733,7 @@ static device_method_t ich_methods[] = {
DEVMETHOD(device_probe, ich_pci_probe),
DEVMETHOD(device_attach, ich_pci_attach),
DEVMETHOD(device_detach, ich_pci_detach),
+ DEVMETHOD(device_suspend, ich_pci_suspend),
DEVMETHOD(device_resume, ich_pci_resume),
{ 0, 0 }
};
OpenPOWER on IntegriCloud