2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk>
5 * Derived from the public domain Linux driver
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
28 * $FreeBSD: src/sys/dev/sound/pci/neomagic.c,v 1.7.2.11 2002/04/22 15:49:32 cg Exp $
29 * $DragonFly: src/sys/dev/sound/pci/neomagic.c,v 1.6 2006/12/20 18:14:40 dillon Exp $
32 #include <dev/sound/pcm/sound.h>
33 #include <dev/sound/pcm/ac97.h>
34 #include <dev/sound/pci/neomagic.h>
35 #include <dev/sound/pci/neomagic-coeff.h>
37 #include <bus/pci/pcireg.h>
38 #include <bus/pci/pcivar.h>
40 SND_DECLARE_FILE("$DragonFly: src/sys/dev/sound/pci/neomagic.c,v 1.6 2006/12/20 18:14:40 dillon Exp $");
42 /* -------------------------------------------------------------------- */
44 #define NM_BUFFSIZE 16384
46 #define NM256AV_PCI_ID 0x800510c8
47 #define NM256ZX_PCI_ID 0x800610c8
51 /* channel registers */
53 int active
, spd
, dir
, fmt
;
54 u_int32_t blksize
, wmark
;
55 struct snd_dbuf
*buffer
;
56 struct pcm_channel
*channel
;
57 struct sc_info
*parent
;
60 /* device private data */
65 struct resource
*reg
, *irq
, *buf
;
66 int regid
, irqid
, bufid
;
69 u_int32_t ac97_base
, ac97_status
, ac97_busy
;
70 u_int32_t buftop
, pbuf
, rbuf
, cbuf
, acbuf
;
71 u_int32_t playint
, recint
, misc1int
, misc2int
;
72 u_int32_t irsz
, badintr
;
74 struct sc_chinfo pch
, rch
;
77 /* -------------------------------------------------------------------- */
84 static int nm_loadcoeff(struct sc_info
*sc
, int dir
, int num
);
85 static int nm_setch(struct sc_chinfo
*ch
);
86 static int nm_init(struct sc_info
*);
87 static void nm_intr(void *);
89 /* talk to the card */
90 static u_int32_t
nm_rd(struct sc_info
*, int, int);
91 static void nm_wr(struct sc_info
*, int, u_int32_t
, int);
92 static u_int32_t
nm_rdbuf(struct sc_info
*, int, int);
93 static void nm_wrbuf(struct sc_info
*, int, u_int32_t
, int);
95 static u_int32_t badcards
[] = {
101 #define NUM_BADCARDS (sizeof(badcards) / sizeof(u_int32_t))
103 /* The actual rates supported by the card. */
104 static int samplerates
[9] = {
116 /* -------------------------------------------------------------------- */
118 static u_int32_t nm_fmt
[] = {
120 AFMT_STEREO
| AFMT_U8
,
122 AFMT_STEREO
| AFMT_S16_LE
,
125 static struct pcmchan_caps nm_caps
= {4000, 48000, nm_fmt
, 0};
127 /* -------------------------------------------------------------------- */
131 nm_rd(struct sc_info
*sc
, int regno
, int size
)
133 bus_space_tag_t st
= rman_get_bustag(sc
->reg
);
134 bus_space_handle_t sh
= rman_get_bushandle(sc
->reg
);
138 return bus_space_read_1(st
, sh
, regno
);
140 return bus_space_read_2(st
, sh
, regno
);
142 return bus_space_read_4(st
, sh
, regno
);
149 nm_wr(struct sc_info
*sc
, int regno
, u_int32_t data
, int size
)
151 bus_space_tag_t st
= rman_get_bustag(sc
->reg
);
152 bus_space_handle_t sh
= rman_get_bushandle(sc
->reg
);
156 bus_space_write_1(st
, sh
, regno
, data
);
159 bus_space_write_2(st
, sh
, regno
, data
);
162 bus_space_write_4(st
, sh
, regno
, data
);
168 nm_rdbuf(struct sc_info
*sc
, int regno
, int size
)
170 bus_space_tag_t st
= rman_get_bustag(sc
->buf
);
171 bus_space_handle_t sh
= rman_get_bushandle(sc
->buf
);
175 return bus_space_read_1(st
, sh
, regno
);
177 return bus_space_read_2(st
, sh
, regno
);
179 return bus_space_read_4(st
, sh
, regno
);
186 nm_wrbuf(struct sc_info
*sc
, int regno
, u_int32_t data
, int size
)
188 bus_space_tag_t st
= rman_get_bustag(sc
->buf
);
189 bus_space_handle_t sh
= rman_get_bushandle(sc
->buf
);
193 bus_space_write_1(st
, sh
, regno
, data
);
196 bus_space_write_2(st
, sh
, regno
, data
);
199 bus_space_write_4(st
, sh
, regno
, data
);
204 /* -------------------------------------------------------------------- */
207 nm_waitcd(struct sc_info
*sc
)
213 if (nm_rd(sc
, sc
->ac97_status
, 2) & sc
->ac97_busy
) {
224 nm_initcd(kobj_t obj
, void *devinfo
)
226 struct sc_info
*sc
= (struct sc_info
*)devinfo
;
228 nm_wr(sc
, 0x6c0, 0x01, 1);
229 nm_wr(sc
, 0x6cc, 0x87, 1);
230 nm_wr(sc
, 0x6cc, 0x80, 1);
231 nm_wr(sc
, 0x6cc, 0x00, 1);
236 nm_rdcd(kobj_t obj
, void *devinfo
, int regno
)
238 struct sc_info
*sc
= (struct sc_info
*)devinfo
;
241 if (!nm_waitcd(sc
)) {
242 x
= nm_rd(sc
, sc
->ac97_base
+ regno
, 2);
246 device_printf(sc
->dev
, "ac97 codec not ready\n");
252 nm_wrcd(kobj_t obj
, void *devinfo
, int regno
, u_int32_t data
)
254 struct sc_info
*sc
= (struct sc_info
*)devinfo
;
257 if (!nm_waitcd(sc
)) {
259 nm_wr(sc
, sc
->ac97_base
+ regno
, data
, 2);
260 if (!nm_waitcd(sc
)) {
266 device_printf(sc
->dev
, "ac97 codec not ready\n");
270 static kobj_method_t nm_ac97_methods
[] = {
271 KOBJMETHOD(ac97_init
, nm_initcd
),
272 KOBJMETHOD(ac97_read
, nm_rdcd
),
273 KOBJMETHOD(ac97_write
, nm_wrcd
),
276 AC97_DECLARE(nm_ac97
);
278 /* -------------------------------------------------------------------- */
281 nm_ackint(struct sc_info
*sc
, u_int32_t num
)
283 if (sc
->type
== NM256AV_PCI_ID
) {
284 nm_wr(sc
, NM_INT_REG
, num
<< 1, 2);
285 } else if (sc
->type
== NM256ZX_PCI_ID
) {
286 nm_wr(sc
, NM_INT_REG
, num
, 4);
291 nm_loadcoeff(struct sc_info
*sc
, int dir
, int num
)
296 addr
= (dir
== PCMDIR_PLAY
)? 0x01c : 0x21c;
297 if (dir
== PCMDIR_REC
)
299 sz
= coefficientSizes
[num
];
302 ofs
+= coefficientSizes
[num
];
303 for (i
= 0; i
< sz
; i
++)
304 nm_wrbuf(sc
, sc
->cbuf
+ i
, coefficients
[ofs
+ i
], 1);
305 nm_wr(sc
, addr
, sc
->cbuf
, 4);
306 if (dir
== PCMDIR_PLAY
)
308 nm_wr(sc
, addr
+ 4, sc
->cbuf
+ sz
, 4);
313 nm_setch(struct sc_chinfo
*ch
)
315 struct sc_info
*sc
= ch
->parent
;
319 for (x
= 0; x
< 8; x
++)
320 if (ch
->spd
< (samplerates
[x
] + samplerates
[x
+ 1]) / 2)
323 if (x
== 8) return 1;
325 ch
->spd
= samplerates
[x
];
326 nm_loadcoeff(sc
, ch
->dir
, x
);
330 if (ch
->fmt
& AFMT_16BIT
) x
|= NM_RATE_BITS_16
;
331 if (ch
->fmt
& AFMT_STEREO
) x
|= NM_RATE_STEREO
;
333 base
= (ch
->dir
== PCMDIR_PLAY
)? NM_PLAYBACK_REG_OFFSET
: NM_RECORD_REG_OFFSET
;
334 nm_wr(sc
, base
+ NM_RATE_REG_OFFSET
, x
, 1);
338 /* channel interface */
340 nmchan_init(kobj_t obj
, void *devinfo
, struct snd_dbuf
*b
, struct pcm_channel
*c
, int dir
)
342 struct sc_info
*sc
= devinfo
;
343 struct sc_chinfo
*ch
;
346 chnbuf
= (dir
== PCMDIR_PLAY
)? sc
->pbuf
: sc
->rbuf
;
347 ch
= (dir
== PCMDIR_PLAY
)? &sc
->pch
: &sc
->rch
;
352 sndbuf_setup(ch
->buffer
, (u_int8_t
*)rman_get_virtual(sc
->buf
) + chnbuf
, NM_BUFFSIZE
);
354 device_printf(sc
->dev
, "%s buf %p\n", (dir
== PCMDIR_PLAY
)?
355 "play" : "rec", sndbuf_getbuf(ch
->buffer
));
363 nmchan_free(kobj_t obj
, void *data
)
369 nmchan_setformat(kobj_t obj
, void *data
, u_int32_t format
)
371 struct sc_chinfo
*ch
= data
;
378 nmchan_setspeed(kobj_t obj
, void *data
, u_int32_t speed
)
380 struct sc_chinfo
*ch
= data
;
383 return nm_setch(ch
)? 0 : ch
->spd
;
387 nmchan_setblocksize(kobj_t obj
, void *data
, u_int32_t blocksize
)
389 struct sc_chinfo
*ch
= data
;
391 ch
->blksize
= blocksize
;
397 nmchan_trigger(kobj_t obj
, void *data
, int go
)
399 struct sc_chinfo
*ch
= data
;
400 struct sc_info
*sc
= ch
->parent
;
403 if (go
== PCMTRIG_EMLDMAWR
|| go
== PCMTRIG_EMLDMARD
)
406 ssz
= (ch
->fmt
& AFMT_16BIT
)? 2 : 1;
407 if (ch
->fmt
& AFMT_STEREO
)
410 if (ch
->dir
== PCMDIR_PLAY
) {
411 if (go
== PCMTRIG_START
) {
413 ch
->wmark
= ch
->blksize
;
414 nm_wr(sc
, NM_PBUFFER_START
, sc
->pbuf
, 4);
415 nm_wr(sc
, NM_PBUFFER_END
, sc
->pbuf
+ NM_BUFFSIZE
- ssz
, 4);
416 nm_wr(sc
, NM_PBUFFER_CURRP
, sc
->pbuf
, 4);
417 nm_wr(sc
, NM_PBUFFER_WMARK
, sc
->pbuf
+ ch
->wmark
, 4);
418 nm_wr(sc
, NM_PLAYBACK_ENABLE_REG
, NM_PLAYBACK_FREERUN
|
419 NM_PLAYBACK_ENABLE_FLAG
, 1);
420 nm_wr(sc
, NM_AUDIO_MUTE_REG
, 0, 2);
423 nm_wr(sc
, NM_PLAYBACK_ENABLE_REG
, 0, 1);
424 nm_wr(sc
, NM_AUDIO_MUTE_REG
, NM_AUDIO_MUTE_BOTH
, 2);
427 if (go
== PCMTRIG_START
) {
429 ch
->wmark
= ch
->blksize
;
430 nm_wr(sc
, NM_RECORD_ENABLE_REG
, NM_RECORD_FREERUN
|
431 NM_RECORD_ENABLE_FLAG
, 1);
432 nm_wr(sc
, NM_RBUFFER_START
, sc
->rbuf
, 4);
433 nm_wr(sc
, NM_RBUFFER_END
, sc
->rbuf
+ NM_BUFFSIZE
, 4);
434 nm_wr(sc
, NM_RBUFFER_CURRP
, sc
->rbuf
, 4);
435 nm_wr(sc
, NM_RBUFFER_WMARK
, sc
->rbuf
+ ch
->wmark
, 4);
438 nm_wr(sc
, NM_RECORD_ENABLE_REG
, 0, 1);
445 nmchan_getptr(kobj_t obj
, void *data
)
447 struct sc_chinfo
*ch
= data
;
448 struct sc_info
*sc
= ch
->parent
;
450 if (ch
->dir
== PCMDIR_PLAY
)
451 return nm_rd(sc
, NM_PBUFFER_CURRP
, 4) - sc
->pbuf
;
453 return nm_rd(sc
, NM_RBUFFER_CURRP
, 4) - sc
->rbuf
;
456 static struct pcmchan_caps
*
457 nmchan_getcaps(kobj_t obj
, void *data
)
462 static kobj_method_t nmchan_methods
[] = {
463 KOBJMETHOD(channel_init
, nmchan_init
),
464 KOBJMETHOD(channel_free
, nmchan_free
),
465 KOBJMETHOD(channel_setformat
, nmchan_setformat
),
466 KOBJMETHOD(channel_setspeed
, nmchan_setspeed
),
467 KOBJMETHOD(channel_setblocksize
, nmchan_setblocksize
),
468 KOBJMETHOD(channel_trigger
, nmchan_trigger
),
469 KOBJMETHOD(channel_getptr
, nmchan_getptr
),
470 KOBJMETHOD(channel_getcaps
, nmchan_getcaps
),
473 CHANNEL_DECLARE(nmchan
);
475 /* The interrupt handler */
479 struct sc_info
*sc
= (struct sc_info
*)p
;
482 status
= nm_rd(sc
, NM_INT_REG
, sc
->irsz
);
486 if (status
& sc
->playint
) {
487 status
&= ~sc
->playint
;
488 sc
->pch
.wmark
+= sc
->pch
.blksize
;
489 sc
->pch
.wmark
%= NM_BUFFSIZE
;
490 nm_wr(sc
, NM_PBUFFER_WMARK
, sc
->pbuf
+ sc
->pch
.wmark
, 4);
492 nm_ackint(sc
, sc
->playint
);
493 chn_intr(sc
->pch
.channel
);
495 if (status
& sc
->recint
) {
496 status
&= ~sc
->recint
;
497 sc
->rch
.wmark
+= sc
->rch
.blksize
;
498 sc
->rch
.wmark
%= NM_BUFFSIZE
;
499 nm_wr(sc
, NM_RBUFFER_WMARK
, sc
->rbuf
+ sc
->rch
.wmark
, 4);
501 nm_ackint(sc
, sc
->recint
);
502 chn_intr(sc
->rch
.channel
);
504 if (status
& sc
->misc1int
) {
505 status
&= ~sc
->misc1int
;
506 nm_ackint(sc
, sc
->misc1int
);
507 x
= nm_rd(sc
, 0x400, 1);
508 nm_wr(sc
, 0x400, x
| 2, 1);
509 device_printf(sc
->dev
, "misc int 1\n");
511 if (status
& sc
->misc2int
) {
512 status
&= ~sc
->misc2int
;
513 nm_ackint(sc
, sc
->misc2int
);
514 x
= nm_rd(sc
, 0x400, 1);
515 nm_wr(sc
, 0x400, x
& ~2, 1);
516 device_printf(sc
->dev
, "misc int 2\n");
519 nm_ackint(sc
, status
);
520 device_printf(sc
->dev
, "unknown int\n");
524 /* -------------------------------------------------------------------- */
527 * Probe and attach the card
531 nm_init(struct sc_info
*sc
)
535 if (sc
->type
== NM256AV_PCI_ID
) {
536 sc
->ac97_base
= NM_MIXER_OFFSET
;
537 sc
->ac97_status
= NM_MIXER_STATUS_OFFSET
;
538 sc
->ac97_busy
= NM_MIXER_READY_MASK
;
540 sc
->buftop
= 2560 * 1024;
543 sc
->playint
= NM_PLAYBACK_INT
;
544 sc
->recint
= NM_RECORD_INT
;
545 sc
->misc1int
= NM_MISC_INT_1
;
546 sc
->misc2int
= NM_MISC_INT_2
;
547 } else if (sc
->type
== NM256ZX_PCI_ID
) {
548 sc
->ac97_base
= NM_MIXER_OFFSET
;
549 sc
->ac97_status
= NM2_MIXER_STATUS_OFFSET
;
550 sc
->ac97_busy
= NM2_MIXER_READY_MASK
;
552 sc
->buftop
= (nm_rd(sc
, 0xa0b, 2)? 6144 : 4096) * 1024;
555 sc
->playint
= NM2_PLAYBACK_INT
;
556 sc
->recint
= NM2_RECORD_INT
;
557 sc
->misc1int
= NM2_MISC_INT_1
;
558 sc
->misc2int
= NM2_MISC_INT_2
;
561 ofs
= sc
->buftop
- 0x0400;
562 sc
->buftop
-= 0x1400;
565 device_printf(sc
->dev
, "buftop is 0x%08x\n", sc
->buftop
);
566 if ((nm_rdbuf(sc
, ofs
, 4) & NM_SIG_MASK
) == NM_SIGNATURE
) {
567 i
= nm_rdbuf(sc
, ofs
+ 4, 4);
568 if (i
!= 0 && i
!= 0xffffffff) {
570 device_printf(sc
->dev
, "buftop is changed to 0x%08x\n", i
);
575 sc
->cbuf
= sc
->buftop
- NM_MAX_COEFFICIENT
;
576 sc
->rbuf
= sc
->cbuf
- NM_BUFFSIZE
;
577 sc
->pbuf
= sc
->rbuf
- NM_BUFFSIZE
;
578 sc
->acbuf
= sc
->pbuf
- (NM_TOTAL_COEFF_COUNT
* 4);
580 nm_wr(sc
, 0, 0x11, 1);
581 nm_wr(sc
, NM_RECORD_ENABLE_REG
, 0, 1);
582 nm_wr(sc
, 0x214, 0, 2);
588 nm_pci_probe(device_t dev
)
590 struct sc_info
*sc
= NULL
;
592 u_int32_t subdev
, i
, data
;
594 subdev
= (pci_get_subdevice(dev
) << 16) | pci_get_subvendor(dev
);
595 switch (pci_get_devid(dev
)) {
598 while ((i
< NUM_BADCARDS
) && (badcards
[i
] != subdev
))
601 /* Try to catch other non-ac97 cards */
603 if (i
== NUM_BADCARDS
) {
604 if (!(sc
= kmalloc(sizeof(*sc
), M_DEVBUF
, M_NOWAIT
| M_ZERO
))) {
605 device_printf(dev
, "cannot allocate softc\n");
609 data
= pci_read_config(dev
, PCIR_COMMAND
, 2);
610 pci_write_config(dev
, PCIR_COMMAND
, data
|
611 PCIM_CMD_PORTEN
| PCIM_CMD_MEMEN
|
612 PCIM_CMD_BUSMASTEREN
, 2);
614 sc
->regid
= PCIR_MAPS
+ 4;
615 sc
->reg
= bus_alloc_resource(dev
, SYS_RES_MEMORY
,
616 &sc
->regid
, 0, ~0, 1,
620 device_printf(dev
, "unable to map register space\n");
621 pci_write_config(dev
, PCIR_COMMAND
, data
, 2);
627 * My Panasonic CF-M2EV needs resetting device
628 * before checking mixer is present or not.
629 * t.ichinoseki@nifty.com.
631 nm_wr(sc
, 0, 0x11, 1); /* reset device */
632 if ((nm_rd(sc
, NM_MIXER_PRESENCE
, 2) &
633 NM_PRESENCE_MASK
) != NM_PRESENCE_VALUE
) {
634 i
= 0; /* non-ac97 card, but not listed */
635 DEB(device_printf(dev
, "subdev = 0x%x - badcard?\n",
638 pci_write_config(dev
, PCIR_COMMAND
, data
, 2);
639 bus_release_resource(dev
, SYS_RES_MEMORY
, sc
->regid
,
644 if (i
== NUM_BADCARDS
)
645 s
= "NeoMagic 256AV";
647 DEB(device_printf(dev
, "this is a non-ac97 NM256AV, not attaching\n"));
652 s
= "NeoMagic 256ZX";
656 if (s
) device_set_desc(dev
, s
);
661 nm_pci_attach(device_t dev
)
665 struct ac97_info
*codec
= 0;
666 char status
[SND_STATUSLEN
];
668 if ((sc
= kmalloc(sizeof(*sc
), M_DEVBUF
, M_NOWAIT
| M_ZERO
)) == NULL
) {
669 device_printf(dev
, "cannot allocate softc\n");
674 sc
->type
= pci_get_devid(dev
);
676 data
= pci_read_config(dev
, PCIR_COMMAND
, 2);
677 data
|= (PCIM_CMD_PORTEN
|PCIM_CMD_MEMEN
|PCIM_CMD_BUSMASTEREN
);
678 pci_write_config(dev
, PCIR_COMMAND
, data
, 2);
679 data
= pci_read_config(dev
, PCIR_COMMAND
, 2);
681 sc
->bufid
= PCIR_MAPS
;
682 sc
->buf
= bus_alloc_resource(dev
, SYS_RES_MEMORY
, &sc
->bufid
,
683 0, ~0, 1, RF_ACTIVE
);
684 sc
->regid
= PCIR_MAPS
+ 4;
685 sc
->reg
= bus_alloc_resource(dev
, SYS_RES_MEMORY
, &sc
->regid
,
686 0, ~0, 1, RF_ACTIVE
);
688 if (!sc
->buf
|| !sc
->reg
) {
689 device_printf(dev
, "unable to map register space\n");
693 if (nm_init(sc
) == -1) {
694 device_printf(dev
, "unable to initialize the card\n");
698 codec
= AC97_CREATE(dev
, sc
, nm_ac97
);
699 if (codec
== NULL
) goto bad
;
700 if (mixer_init(dev
, ac97_getmixerclass(), codec
) == -1) goto bad
;
703 sc
->irq
= bus_alloc_resource(dev
, SYS_RES_IRQ
, &sc
->irqid
,
704 0, ~0, 1, RF_ACTIVE
| RF_SHAREABLE
);
705 if (!sc
->irq
|| snd_setup_intr(dev
, sc
->irq
, 0, nm_intr
, sc
, &sc
->ih
, NULL
)) {
706 device_printf(dev
, "unable to map interrupt\n");
710 ksnprintf(status
, SND_STATUSLEN
, "at memory 0x%lx, 0x%lx irq %ld",
711 rman_get_start(sc
->buf
), rman_get_start(sc
->reg
),
712 rman_get_start(sc
->irq
));
714 if (pcm_register(dev
, sc
, 1, 1)) goto bad
;
715 pcm_addchan(dev
, PCMDIR_REC
, &nmchan_class
, sc
);
716 pcm_addchan(dev
, PCMDIR_PLAY
, &nmchan_class
, sc
);
717 pcm_setstatus(dev
, status
);
722 if (codec
) ac97_destroy(codec
);
723 if (sc
->buf
) bus_release_resource(dev
, SYS_RES_MEMORY
, sc
->bufid
, sc
->buf
);
724 if (sc
->reg
) bus_release_resource(dev
, SYS_RES_MEMORY
, sc
->regid
, sc
->reg
);
725 if (sc
->ih
) bus_teardown_intr(dev
, sc
->irq
, sc
->ih
);
726 if (sc
->irq
) bus_release_resource(dev
, SYS_RES_IRQ
, sc
->irqid
, sc
->irq
);
732 nm_pci_detach(device_t dev
)
737 r
= pcm_unregister(dev
);
741 sc
= pcm_getdevinfo(dev
);
742 bus_release_resource(dev
, SYS_RES_MEMORY
, sc
->bufid
, sc
->buf
);
743 bus_release_resource(dev
, SYS_RES_MEMORY
, sc
->regid
, sc
->reg
);
744 bus_teardown_intr(dev
, sc
->irq
, sc
->ih
);
745 bus_release_resource(dev
, SYS_RES_IRQ
, sc
->irqid
, sc
->irq
);
752 nm_pci_suspend(device_t dev
)
756 sc
= pcm_getdevinfo(dev
);
759 if (sc
->pch
.active
) {
760 nm_wr(sc
, NM_PLAYBACK_ENABLE_REG
, 0, 1);
761 nm_wr(sc
, NM_AUDIO_MUTE_REG
, NM_AUDIO_MUTE_BOTH
, 2);
764 if (sc
->rch
.active
) {
765 nm_wr(sc
, NM_RECORD_ENABLE_REG
, 0, 1);
771 nm_pci_resume(device_t dev
)
775 sc
= pcm_getdevinfo(dev
);
778 * Reinit audio device.
779 * Don't call nm_init(). It would change buftop if X ran or
780 * is running. This makes playing and recording buffer address
781 * shift but these buffers of channel layer are not changed.
782 * As a result of this inconsistency, periodic noise will be
783 * generated while playing.
785 nm_wr(sc
, 0, 0x11, 1);
786 nm_wr(sc
, 0x214, 0, 2);
789 if (mixer_reinit(dev
) == -1) {
790 device_printf(dev
, "unable to reinitialize the mixer\n");
793 /* restart playing */
794 if (sc
->pch
.active
) {
795 nm_wr(sc
, NM_PLAYBACK_ENABLE_REG
, NM_PLAYBACK_FREERUN
|
796 NM_PLAYBACK_ENABLE_FLAG
, 1);
797 nm_wr(sc
, NM_AUDIO_MUTE_REG
, 0, 2);
799 /* restart recording */
800 if (sc
->rch
.active
) {
801 nm_wr(sc
, NM_RECORD_ENABLE_REG
, NM_RECORD_FREERUN
|
802 NM_RECORD_ENABLE_FLAG
, 1);
807 static device_method_t nm_methods
[] = {
808 /* Device interface */
809 DEVMETHOD(device_probe
, nm_pci_probe
),
810 DEVMETHOD(device_attach
, nm_pci_attach
),
811 DEVMETHOD(device_detach
, nm_pci_detach
),
812 DEVMETHOD(device_suspend
, nm_pci_suspend
),
813 DEVMETHOD(device_resume
, nm_pci_resume
),
817 static driver_t nm_driver
= {
823 DRIVER_MODULE(snd_neomagic
, pci
, nm_driver
, pcm_devclass
, 0, 0);
824 MODULE_DEPEND(snd_neomagic
, snd_pcm
, PCM_MINVER
, PCM_PREFVER
, PCM_MAXVER
);
825 MODULE_VERSION(snd_neomagic
, 1);