summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcg <cg@FreeBSD.org>2000-07-30 21:15:35 +0000
committercg <cg@FreeBSD.org>2000-07-30 21:15:35 +0000
commit0c173f44b34991f342b56f952cf263d57dfdd13c (patch)
tree82bd05fe378cefaee5f3a28ae0e982659bfb4b31
parentc4e079d075d1f3b37bcabbc448dba06bf20dd2b6 (diff)
downloadFreeBSD-src-0c173f44b34991f342b56f952cf263d57dfdd13c.zip
FreeBSD-src-0c173f44b34991f342b56f952cf263d57dfdd13c.tar.gz
add suspend/resume for yamaha chips
Submitted by: Ira L Cooper <ira@MIT.EDU>
-rw-r--r--sys/dev/sound/isa/mss.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/sys/dev/sound/isa/mss.c b/sys/dev/sound/isa/mss.c
index 4e1967f..5240938 100644
--- a/sys/dev/sound/isa/mss.c
+++ b/sys/dev/sound/isa/mss.c
@@ -36,6 +36,8 @@
#define MSS_BUFFSIZE (65536 - 256)
#define abs(x) (((x) < 0) ? -(x) : (x))
+#define MSS_INDEXED_REGS 0x20
+#define OPL_INDEXED_REGS 0x19
struct mss_info;
@@ -60,6 +62,8 @@ struct mss_info {
int drq2_rid;
bus_dma_tag_t parent_dmat;
+ char mss_indexed_regs[MSS_INDEXED_REGS];
+ char opl_indexed_regs[OPL_INDEXED_REGS];
int pdma, rdma;
int bd_id; /* used to hold board-id info, eg. sb version,
* mss codec type, etc. etc.
@@ -944,10 +948,79 @@ mss_attach(device_t dev)
return mss_doattach(dev, mss);
}
+/*
+ * mss_resume() is the code to allow a laptop to resume using the sound
+ * card.
+ *
+ * This routine re-sets the state of the board to the state before going
+ * to sleep. According to the yamaha docs this is the right thing to do,
+ * but getting DMA restarted appears to be a bit of a trick, so the device
+ * has to be closed and re-opened to be re-used, but there is no skipping
+ * problem, and volume, bass/treble and most other things are restored
+ * properly.
+ *
+ */
+
+static int
+mss_resume(device_t dev)
+{
+ /*
+ * Restore the state taken below.
+ */
+ struct mss_info *mss;
+ int i;
+
+ mss = pcm_getdevinfo(dev);
+
+ if (mss->bd_id == MD_YM0020)
+ {
+ /* This works on a Toshiba Libretto 100CT. */
+ for (i = 0; i < MSS_INDEXED_REGS; i++)
+ ad_write(mss, i, mss->mss_indexed_regs[i]);
+ for (i = 0; i < OPL_INDEXED_REGS; i++)
+ conf_wr(mss, i, mss->opl_indexed_regs[i]);
+ mss_intr(mss);
+ }
+ return 0;
+
+}
+
+/*
+ * mss_suspend() is the code that gets called right before a laptop
+ * suspends.
+ *
+ * This code saves the state of the sound card right before shutdown
+ * so it can be restored above.
+ *
+ */
+
+static int
+mss_suspend(device_t dev)
+{
+ int i;
+ struct mss_info *mss;
+
+ mss = pcm_getdevinfo(dev);
+
+ if(mss->bd_id == MD_YM0020)
+ {
+ /* this stops playback. */
+ conf_wr(mss, 0x12, 0x0c);
+ for(i = 0; i < MSS_INDEXED_REGS; i++)
+ mss->mss_indexed_regs[i] = ad_read(mss, i);
+ for(i = 0; i < OPL_INDEXED_REGS; i++)
+ mss->opl_indexed_regs[i] = conf_rd(mss, i);
+ mss->opl_indexed_regs[0x12] = 0x0;
+ }
+ return 0;
+}
+
static device_method_t mss_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, mss_probe),
DEVMETHOD(device_attach, mss_attach),
+ DEVMETHOD(device_suspend, mss_suspend),
+ DEVMETHOD(device_resume, mss_resume),
{ 0, 0 }
};
@@ -1443,6 +1516,8 @@ static device_method_t pnpmss_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, pnpmss_probe),
DEVMETHOD(device_attach, pnpmss_attach),
+ DEVMETHOD(device_suspend, mss_suspend),
+ DEVMETHOD(device_resume, mss_resume),
{ 0, 0 }
};
OpenPOWER on IntegriCloud