From aaa167872e36f46b23440089fdef7d497e46e63a Mon Sep 17 00:00:00 2001 From: Orion Hodson Date: Fri, 21 Dec 2001 19:20:28 +0000 Subject: [PATCH] Save and restore state for suspend/resume. PR: kern/28692 Obtained from: SAKIYAMA Nobuo --- sys/dev/sound/pci/ich.c | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/sys/dev/sound/pci/ich.c b/sys/dev/sound/pci/ich.c index fd391e577150..9b0a757ac3da 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 @@ -678,10 +679,30 @@ ich_pci_detach(device_t dev) return 0; } +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 } };