summaryrefslogtreecommitdiffstats
path: root/sys/dev/sound/pci/ds1.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/sound/pci/ds1.c')
-rw-r--r--sys/dev/sound/pci/ds1.c76
1 files changed, 66 insertions, 10 deletions
diff --git a/sys/dev/sound/pci/ds1.c b/sys/dev/sound/pci/ds1.c
index 81ecaa7..1d21064 100644
--- a/sys/dev/sound/pci/ds1.c
+++ b/sys/dev/sound/pci/ds1.c
@@ -109,6 +109,7 @@ struct sc_info {
bus_space_tag_t st;
bus_space_handle_t sh;
bus_dma_tag_t parent_dmat;
+ bus_dmamap_t map;
struct resource *reg, *irq;
int regid, irqid;
@@ -216,6 +217,14 @@ static pcm_channel ds_pchantemplate = {
ds1pchan_trigger,
ds1pchan_getptr,
ds1pchan_getcaps,
+ NULL, /* free */
+ NULL, /* nop1 */
+ NULL, /* nop2 */
+ NULL, /* nop3 */
+ NULL, /* nop4 */
+ NULL, /* nop5 */
+ NULL, /* nop6 */
+ NULL, /* nop7 */
};
static pcm_channel ds_rchantemplate = {
@@ -227,6 +236,14 @@ static pcm_channel ds_rchantemplate = {
ds1rchan_trigger,
ds1rchan_getptr,
ds1rchan_getcaps,
+ NULL, /* free */
+ NULL, /* nop1 */
+ NULL, /* nop2 */
+ NULL, /* nop3 */
+ NULL, /* nop4 */
+ NULL, /* nop5 */
+ NULL, /* nop6 */
+ NULL, /* nop7 */
};
/* -------------------------------------------------------------------- */
@@ -778,7 +795,6 @@ ds_init(struct sc_info *sc)
u_int32_t *ci, r, pcs, rcs, ecs, ws, memsz, cb;
u_int8_t *t;
void *buf;
- bus_dmamap_t map;
ci = ds_devs[sc->type].mcode;
@@ -821,9 +837,9 @@ ds_init(struct sc_info *sc)
memsz += (64 + 1) * 4;
if (sc->regbase == NULL) {
- if (bus_dmamem_alloc(sc->parent_dmat, &buf, BUS_DMA_NOWAIT, &map))
+ if (bus_dmamem_alloc(sc->parent_dmat, &buf, BUS_DMA_NOWAIT, &sc->map))
return -1;
- if (bus_dmamap_load(sc->parent_dmat, map, buf, memsz, ds_setmap, sc, 0)
+ if (bus_dmamap_load(sc->parent_dmat, sc->map, buf, memsz, ds_setmap, sc, 0)
|| !sc->ctrlbase) {
device_printf(sc->dev, "pcs=%d, rcs=%d, ecs=%d, ws=%d, memsz=%d\n",
pcs, rcs, ecs, ws, memsz);
@@ -868,6 +884,27 @@ ds_init(struct sc_info *sc)
}
static int
+ds_uninit(struct sc_info *sc)
+{
+ ds_wr(sc, YDSXGR_NATIVEDACOUTVOL, 0x00000000, 4);
+ ds_wr(sc, YDSXGR_NATIVEADCINVOL, 0, 4);
+ ds_wr(sc, YDSXGR_NATIVEDACINVOL, 0, 4);
+ ds_enadsp(sc, 0);
+ ds_wr(sc, YDSXGR_MODE, 0x00010000, 4);
+ ds_wr(sc, YDSXGR_MAPOFREC, 0x00000000, 4);
+ ds_wr(sc, YDSXGR_MAPOFEFFECT, 0x00000000, 4);
+ ds_wr(sc, YDSXGR_PLAYCTRLBASE, 0x00000000, 4);
+ ds_wr(sc, YDSXGR_RECCTRLBASE, 0x00000000, 4);
+ ds_wr(sc, YDSXGR_EFFCTRLBASE, 0x00000000, 4);
+ ds_wr(sc, YDSXGR_GLOBALCTRL, 0, 2);
+
+ bus_dmamap_unload(sc->parent_dmat, sc->map);
+ bus_dmamem_free(sc->parent_dmat, sc->regbase, sc->map);
+
+ return 0;
+}
+
+static int
ds_finddev(u_int32_t dev, u_int32_t subdev)
{
int i;
@@ -898,14 +935,12 @@ ds_pci_probe(device_t dev)
static int
ds_pci_attach(device_t dev)
{
- snddev_info *d;
u_int32_t data;
u_int32_t subdev, i;
struct sc_info *sc;
struct ac97_info *codec;
char status[SND_STATUSLEN];
- d = device_get_softc(dev);
if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT)) == NULL) {
device_printf(dev, "cannot allocate softc\n");
return ENXIO;
@@ -952,7 +987,7 @@ ds_pci_attach(device_t dev)
codec = ac97_create(dev, sc, ds_initcd, ds_rdcd, ds_wrcd);
if (codec == NULL)
goto bad;
- mixer_init(d, &ac97_mixer, codec);
+ mixer_init(dev, &ac97_mixer, codec);
sc->irqid = 0;
sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid,
@@ -990,28 +1025,49 @@ bad:
static int
ds_pci_resume(device_t dev)
{
- snddev_info *d;
struct sc_info *sc;
- d = device_get_softc(dev);
sc = pcm_getdevinfo(dev);
if (ds_init(sc) == -1) {
device_printf(dev, "unable to reinitialize the card\n");
return ENXIO;
}
- if (mixer_reinit(d) == -1) {
+ if (mixer_reinit(dev) == -1) {
device_printf(dev, "unable to reinitialize the mixer\n");
return ENXIO;
}
return 0;
}
+static int
+ds_pci_detach(device_t dev)
+{
+ int r;
+ struct sc_info *sc;
+
+ r = pcm_unregister(dev);
+ if (r)
+ return r;
+
+ sc = pcm_getdevinfo(dev);
+ ds_uninit(sc);
+ if (sc->reg)
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg);
+ if (sc->ih)
+ bus_teardown_intr(dev, sc->irq, sc->ih);
+ if (sc->irq)
+ bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
+ free(sc, M_DEVBUF);
+ return 0;
+}
+
static device_method_t ds1_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ds_pci_probe),
DEVMETHOD(device_attach, ds_pci_attach),
- DEVMETHOD(device_resume, ds_pci_resume),
+ DEVMETHOD(device_detach, ds_pci_detach),
+ DEVMETHOD(device_resume, ds_pci_resume),
{ 0, 0 }
};
OpenPOWER on IntegriCloud