From 3e47be4df9acdbe5ce7425cec5ebcff9c961d373 Mon Sep 17 00:00:00 2001 From: jmcneill Date: Mon, 19 Jun 2006 13:55:40 +0000 Subject: [PATCH] Restore yds(4) state on resume. --- sys/dev/pci/yds.c | 52 ++++++++++++++++++++++++++++++++++++++++---- sys/dev/pci/ydsvar.h | 10 ++++++++- 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/sys/dev/pci/yds.c b/sys/dev/pci/yds.c index 80e1f8062957..495153636a34 100644 --- a/sys/dev/pci/yds.c +++ b/sys/dev/pci/yds.c @@ -1,4 +1,4 @@ -/* $NetBSD: yds.c,v 1.31 2006/06/07 15:34:47 nakayama Exp $ */ +/* $NetBSD: yds.c,v 1.32 2006/06/19 13:55:40 jmcneill Exp $ */ /* * Copyright (c) 2000, 2001 Kazuki Sakamoto and Minoura Makoto. @@ -39,7 +39,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: yds.c,v 1.31 2006/06/07 15:34:47 nakayama Exp $"); +__KERNEL_RCSID(0, "$NetBSD: yds.c,v 1.32 2006/06/19 13:55:40 jmcneill Exp $"); #include "mpu.h" @@ -679,16 +679,60 @@ static void yds_powerhook(int why, void *addr) { struct yds_softc *sc; + pci_chipset_tag_t pc; + pcitag_t tag; + pcireg_t reg; + int s; - if (why == PWR_RESUME) { - sc = addr; + sc = (struct yds_softc *)addr; + pc = sc->sc_pc; + tag = sc->sc_pcitag; + + s = splaudio(); + switch (why) { + case PWR_SUSPEND: + pci_conf_capture(pc, tag, &sc->sc_pciconf); + + sc->sc_dsctrl = pci_conf_read(pc, tag, YDS_PCI_DSCTRL); + sc->sc_legacy = pci_conf_read(pc, tag, YDS_PCI_LEGACY); + sc->sc_ba[0] = pci_conf_read(pc, tag, YDS_PCI_FM_BA); + sc->sc_ba[1] = pci_conf_read(pc, tag, YDS_PCI_MPU_BA); + break; + case PWR_RESUME: + pci_conf_restore(pc, tag, &sc->sc_pciconf); + + /* Disable legacy mode */ + reg = pci_conf_read(pc, tag, YDS_PCI_LEGACY); + pci_conf_write(pc, tag, YDS_PCI_LEGACY, + reg & YDS_PCI_LEGACY_LAD); + + /* Enable the device. */ + reg = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); + reg |= (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | + PCI_COMMAND_MASTER_ENABLE); + pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, reg); + reg = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); if (yds_init(sc)) { printf("%s: reinitialize failed\n", sc->sc_dev.dv_xname); + splx(s); return; } + pci_conf_write(pc, tag, YDS_PCI_DSCTRL, sc->sc_dsctrl); sc->sc_codec[0].codec_if->vtbl->restore_ports(sc->sc_codec[0].codec_if); + break; + case PWR_SOFTRESUME: + pci_conf_write(pc, tag, YDS_PCI_LEGACY, sc->sc_legacy); + pci_conf_write(pc, tag, YDS_PCI_FM_BA, sc->sc_ba[0]); + pci_conf_write(pc, tag, YDS_PCI_MPU_BA, sc->sc_ba[1]); +#if notyet + yds_configure_legacy(addr); +#endif + break; } + splx(s); + + return; } static void diff --git a/sys/dev/pci/ydsvar.h b/sys/dev/pci/ydsvar.h index ec46ad2273ea..c7582d5606f8 100644 --- a/sys/dev/pci/ydsvar.h +++ b/sys/dev/pci/ydsvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: ydsvar.h,v 1.6 2005/12/11 12:22:51 christos Exp $ */ +/* $NetBSD: ydsvar.h,v 1.7 2006/06/19 13:55:41 jmcneill Exp $ */ /* * Copyright (c) 2000, 2001 Kazuki Sakamoto and Minoura Makoto. @@ -111,6 +111,14 @@ struct yds_softc { bus_space_handle_t sc_mpu_ioh; struct audio_encoding_set *sc_encodings; + + /* + * Power management + */ + struct pci_conf_state sc_pciconf; + pcireg_t sc_dsctrl; + pcireg_t sc_legacy; + pcireg_t sc_ba[2]; }; #define sc_opl_iot sc_legacy_iot #define sc_mpu_iot sc_legacy_iot