2 * Copyright (c) 1999 Cameron Grant <cg@freebsd.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
26 * $FreeBSD: src/sys/dev/sound/pci/t4dwave.c,v 1.48 2005/03/01 08:58:05 imp Exp $
27 * $DragonFly: src/sys/dev/sound/pci/t4dwave.c,v 1.10 2007/06/16 20:07:19 dillon Exp $
30 #include <dev/sound/pcm/sound.h>
31 #include <dev/sound/pcm/ac97.h>
32 #include <dev/sound/pci/t4dwave.h>
34 #include <bus/pci/pcireg.h>
35 #include <bus/pci/pcivar.h>
37 SND_DECLARE_FILE("$DragonFly: src/sys/dev/sound/pci/t4dwave.c,v 1.10 2007/06/16 20:07:19 dillon Exp $");
39 /* -------------------------------------------------------------------- */
41 #define TDX_PCI_ID 0x20001023
42 #define TNX_PCI_ID 0x20011023
43 #define ALI_PCI_ID 0x545110b9
44 #define SPA_PCI_ID 0x70181039
46 #define TR_DEFAULT_BUFSZ 0x1000
47 #define TR_TIMEOUT_CDC 0xffff
48 #define TR_MAXPLAYCH 4
50 * Though, it's not clearly documented in trident datasheet, trident
51 * audio cards can't handle DMA addresses located above 1GB. The LBA
52 * (loop begin address) register which holds DMA base address is 32bits
54 * But the MSB 2bits are used for other purposes(I guess it is really
55 * bad idea). This effectivly limits the DMA address space up to 1GB.
57 #define TR_MAXADDR ((1 << 30) - 1)
62 /* channel registers */
64 u_int32_t cso
, alpha
, fms
, fmc
, ec
;
68 u_int32_t gvsel
, pan
, vol
, ctrl
;
69 u_int32_t active
:1, was_active
:1;
71 struct snd_dbuf
*buffer
;
72 struct pcm_channel
*channel
;
73 struct tr_info
*parent
;
78 u_int32_t active
:1, was_active
:1;
79 struct snd_dbuf
*buffer
;
80 struct pcm_channel
*channel
;
81 struct tr_info
*parent
;
84 /* device private data */
90 bus_space_handle_t sh
;
91 bus_dma_tag_t parent_dmat
;
93 struct resource
*reg
, *irq
;
94 int regtype
, regid
, irqid
;
102 struct tr_chinfo chinfo
[TR_MAXPLAYCH
];
103 struct tr_rchinfo recchinfo
;
106 /* -------------------------------------------------------------------- */
108 static u_int32_t tr_recfmt
[] = {
110 AFMT_STEREO
| AFMT_U8
,
112 AFMT_STEREO
| AFMT_S8
,
114 AFMT_STEREO
| AFMT_S16_LE
,
116 AFMT_STEREO
| AFMT_U16_LE
,
119 static struct pcmchan_caps tr_reccaps
= {4000, 48000, tr_recfmt
, 0};
121 static u_int32_t tr_playfmt
[] = {
123 AFMT_STEREO
| AFMT_U8
,
125 AFMT_STEREO
| AFMT_S8
,
127 AFMT_STEREO
| AFMT_S16_LE
,
129 AFMT_STEREO
| AFMT_U16_LE
,
132 static struct pcmchan_caps tr_playcaps
= {4000, 48000, tr_playfmt
, 0};
134 /* -------------------------------------------------------------------- */
139 tr_rd(struct tr_info
*tr
, int regno
, int size
)
143 return bus_space_read_1(tr
->st
, tr
->sh
, regno
);
145 return bus_space_read_2(tr
->st
, tr
->sh
, regno
);
147 return bus_space_read_4(tr
->st
, tr
->sh
, regno
);
154 tr_wr(struct tr_info
*tr
, int regno
, u_int32_t data
, int size
)
158 bus_space_write_1(tr
->st
, tr
->sh
, regno
, data
);
161 bus_space_write_2(tr
->st
, tr
->sh
, regno
, data
);
164 bus_space_write_4(tr
->st
, tr
->sh
, regno
, data
);
169 /* -------------------------------------------------------------------- */
173 tr_rdcd(kobj_t obj
, void *devinfo
, int regno
)
175 struct tr_info
*tr
= (struct tr_info
*)devinfo
;
180 treg
=SPA_REG_CODECRD
;
185 treg
=TDX_REG_CODECWR
;
187 treg
=TDX_REG_CODECRD
;
191 treg
=TDX_REG_CODECRD
;
195 treg
=(regno
& 0x100)? TNX_REG_CODEC2RD
: TNX_REG_CODEC1RD
;
199 kprintf("!!! tr_rdcd defaulted !!!\n");
206 snd_mtxlock(tr
->lock
);
207 if (tr
->type
== ALI_PCI_ID
) {
208 u_int32_t chk1
, chk2
;
210 for (i
= TR_TIMEOUT_CDC
; (i
> 0) && (j
& trw
); i
--)
211 j
= tr_rd(tr
, treg
, 4);
213 chk1
= tr_rd(tr
, 0xc8, 4);
214 chk2
= tr_rd(tr
, 0xc8, 4);
215 for (i
= TR_TIMEOUT_CDC
; (i
> 0) && (chk1
== chk2
);
217 chk2
= tr_rd(tr
, 0xc8, 4);
220 if (tr
->type
!= ALI_PCI_ID
|| i
> 0) {
221 tr_wr(tr
, treg
, regno
| trw
, 4);
223 for (i
=TR_TIMEOUT_CDC
; (i
> 0) && (j
& trw
); i
--)
224 j
=tr_rd(tr
, treg
, 4);
226 snd_mtxunlock(tr
->lock
);
227 if (i
== 0) kprintf("codec timeout during read of register %x\n", regno
);
228 return (j
>> TR_CDC_DATA
) & 0xffff;
232 tr_wrcd(kobj_t obj
, void *devinfo
, int regno
, u_int32_t data
)
234 struct tr_info
*tr
= (struct tr_info
*)devinfo
;
239 treg
=SPA_REG_CODECWR
;
244 treg
=TDX_REG_CODECWR
;
248 treg
=TNX_REG_CODECWR
;
249 trw
=TNX_CDC_RWSTAT
| ((regno
& 0x100)? TNX_CDC_SEC
: 0);
252 kprintf("!!! tr_wrcd defaulted !!!");
260 kprintf("tr_wrcd: reg %x was %x", regno
, tr_rdcd(devinfo
, regno
));
263 snd_mtxlock(tr
->lock
);
264 if (tr
->type
== ALI_PCI_ID
) {
266 for (i
= TR_TIMEOUT_CDC
; (i
> 0) && (j
& trw
); i
--)
267 j
= tr_rd(tr
, treg
, 4);
269 u_int32_t chk1
, chk2
;
270 chk1
= tr_rd(tr
, 0xc8, 4);
271 chk2
= tr_rd(tr
, 0xc8, 4);
272 for (i
= TR_TIMEOUT_CDC
; (i
> 0) && (chk1
== chk2
);
274 chk2
= tr_rd(tr
, 0xc8, 4);
277 if (tr
->type
!= ALI_PCI_ID
|| i
> 0) {
278 for (i
=TR_TIMEOUT_CDC
; (i
>0) && (j
& trw
); i
--)
279 j
=tr_rd(tr
, treg
, 4);
280 if (tr
->type
== ALI_PCI_ID
&& tr
->rev
> 0x01)
282 tr_wr(tr
, treg
, (data
<< TR_CDC_DATA
) | regno
| trw
, 4);
285 kprintf(" - wrote %x, now %x\n", data
, tr_rdcd(devinfo
, regno
));
287 snd_mtxunlock(tr
->lock
);
288 if (i
==0) kprintf("codec timeout writing %x, data %x\n", regno
, data
);
289 return (i
> 0)? 0 : -1;
292 static kobj_method_t tr_ac97_methods
[] = {
293 KOBJMETHOD(ac97_read
, tr_rdcd
),
294 KOBJMETHOD(ac97_write
, tr_wrcd
),
297 AC97_DECLARE(tr_ac97
);
299 /* -------------------------------------------------------------------- */
300 /* playback channel interrupts */
304 tr_testint(struct tr_chinfo
*ch
)
306 struct tr_info
*tr
= ch
->parent
;
309 bank
= (ch
->index
& 0x20) ? 1 : 0;
310 chan
= ch
->index
& 0x1f;
311 return tr_rd(tr
, bank
? TR_REG_ADDRINTB
: TR_REG_ADDRINTA
, 4) & (1 << chan
);
316 tr_clrint(struct tr_chinfo
*ch
)
318 struct tr_info
*tr
= ch
->parent
;
321 bank
= (ch
->index
& 0x20) ? 1 : 0;
322 chan
= ch
->index
& 0x1f;
323 tr_wr(tr
, bank
? TR_REG_ADDRINTB
: TR_REG_ADDRINTA
, 1 << chan
, 4);
327 tr_enaint(struct tr_chinfo
*ch
, int enable
)
329 struct tr_info
*tr
= ch
->parent
;
333 snd_mtxlock(tr
->lock
);
334 bank
= (ch
->index
& 0x20) ? 1 : 0;
335 chan
= ch
->index
& 0x1f;
336 reg
= bank
? TR_REG_INTENB
: TR_REG_INTENA
;
338 i
= tr_rd(tr
, reg
, 4);
340 i
|= (enable
? 1 : 0) << chan
;
343 tr_wr(tr
, reg
, i
, 4);
344 snd_mtxunlock(tr
->lock
);
347 /* playback channels */
350 tr_selch(struct tr_chinfo
*ch
)
352 struct tr_info
*tr
= ch
->parent
;
355 i
= tr_rd(tr
, TR_REG_CIR
, 4);
357 i
|= ch
->index
& 0x3f;
358 tr_wr(tr
, TR_REG_CIR
, i
, 4);
362 tr_startch(struct tr_chinfo
*ch
)
364 struct tr_info
*tr
= ch
->parent
;
367 bank
= (ch
->index
& 0x20) ? 1 : 0;
368 chan
= ch
->index
& 0x1f;
369 tr_wr(tr
, bank
? TR_REG_STARTB
: TR_REG_STARTA
, 1 << chan
, 4);
373 tr_stopch(struct tr_chinfo
*ch
)
375 struct tr_info
*tr
= ch
->parent
;
378 bank
= (ch
->index
& 0x20) ? 1 : 0;
379 chan
= ch
->index
& 0x1f;
380 tr_wr(tr
, bank
? TR_REG_STOPB
: TR_REG_STOPA
, 1 << chan
, 4);
384 tr_wrch(struct tr_chinfo
*ch
)
386 struct tr_info
*tr
= ch
->parent
;
387 u_int32_t cr
[TR_CHN_REGS
], i
;
389 ch
->gvsel
&= 0x00000001;
390 ch
->fmc
&= 0x00000003;
391 ch
->fms
&= 0x0000000f;
392 ch
->ctrl
&= 0x0000000f;
393 ch
->pan
&= 0x0000007f;
394 ch
->rvol
&= 0x0000007f;
395 ch
->cvol
&= 0x0000007f;
396 ch
->vol
&= 0x000000ff;
397 ch
->ec
&= 0x00000fff;
398 ch
->alpha
&= 0x00000fff;
399 ch
->delta
&= 0x0000ffff;
400 ch
->lba
&= 0x3fffffff;
403 cr
[3]=(ch
->fmc
<<14) | (ch
->rvol
<<7) | (ch
->cvol
);
404 cr
[4]=(ch
->gvsel
<<31) | (ch
->pan
<<24) | (ch
->vol
<<16) | (ch
->ctrl
<<12) | (ch
->ec
);
410 ch
->cso
&= 0x0000ffff;
411 ch
->eso
&= 0x0000ffff;
412 cr
[0]=(ch
->cso
<<16) | (ch
->alpha
<<4) | (ch
->fms
);
413 cr
[2]=(ch
->eso
<<16) | (ch
->delta
);
416 ch
->cso
&= 0x00ffffff;
417 ch
->eso
&= 0x00ffffff;
418 cr
[0]=((ch
->delta
& 0xff)<<24) | (ch
->cso
);
419 cr
[2]=((ch
->delta
>>8)<<24) | (ch
->eso
);
420 cr
[3]|=(ch
->alpha
<<20) | (ch
->fms
<<16) | (ch
->fmc
<<14);
423 snd_mtxlock(tr
->lock
);
425 for (i
=0; i
<TR_CHN_REGS
; i
++)
426 tr_wr(tr
, TR_REG_CHNBASE
+(i
<<2), cr
[i
], 4);
427 snd_mtxunlock(tr
->lock
);
431 tr_rdch(struct tr_chinfo
*ch
)
433 struct tr_info
*tr
= ch
->parent
;
436 snd_mtxlock(tr
->lock
);
439 cr
[i
]=tr_rd(tr
, TR_REG_CHNBASE
+(i
<<2), 4);
440 snd_mtxunlock(tr
->lock
);
443 ch
->lba
= (cr
[1] & 0x3fffffff);
444 ch
->fmc
= (cr
[3] & 0x0000c000) >> 14;
445 ch
->rvol
= (cr
[3] & 0x00003f80) >> 7;
446 ch
->cvol
= (cr
[3] & 0x0000007f);
447 ch
->gvsel
= (cr
[4] & 0x80000000) >> 31;
448 ch
->pan
= (cr
[4] & 0x7f000000) >> 24;
449 ch
->vol
= (cr
[4] & 0x00ff0000) >> 16;
450 ch
->ctrl
= (cr
[4] & 0x0000f000) >> 12;
451 ch
->ec
= (cr
[4] & 0x00000fff);
456 ch
->cso
= (cr
[0] & 0xffff0000) >> 16;
457 ch
->alpha
= (cr
[0] & 0x0000fff0) >> 4;
458 ch
->fms
= (cr
[0] & 0x0000000f);
459 ch
->eso
= (cr
[2] & 0xffff0000) >> 16;
460 ch
->delta
= (cr
[2] & 0x0000ffff);
463 ch
->cso
= (cr
[0] & 0x00ffffff);
464 ch
->eso
= (cr
[2] & 0x00ffffff);
465 ch
->delta
= ((cr
[2] & 0xff000000) >> 16) | ((cr
[0] & 0xff000000) >> 24);
466 ch
->alpha
= (cr
[3] & 0xfff00000) >> 20;
467 ch
->fms
= (cr
[3] & 0x000f0000) >> 16;
473 tr_fmttobits(u_int32_t fmt
)
478 bits
|= (fmt
& AFMT_SIGNED
)? 0x2 : 0;
479 bits
|= (fmt
& AFMT_STEREO
)? 0x4 : 0;
480 bits
|= (fmt
& AFMT_16BIT
)? 0x8 : 0;
485 /* -------------------------------------------------------------------- */
486 /* channel interface */
489 trpchan_init(kobj_t obj
, void *devinfo
, struct snd_dbuf
*b
, struct pcm_channel
*c
, int dir
)
491 struct tr_info
*tr
= devinfo
;
492 struct tr_chinfo
*ch
;
494 KASSERT(dir
== PCMDIR_PLAY
, ("trpchan_init: bad direction"));
495 ch
= &tr
->chinfo
[tr
->playchns
];
496 ch
->index
= tr
->playchns
++;
500 if (sndbuf_alloc(ch
->buffer
, tr
->parent_dmat
, tr
->bufsz
) != 0)
507 trpchan_setformat(kobj_t obj
, void *data
, u_int32_t format
)
509 struct tr_chinfo
*ch
= data
;
511 ch
->ctrl
= tr_fmttobits(format
) | 0x01;
517 trpchan_setspeed(kobj_t obj
, void *data
, u_int32_t speed
)
519 struct tr_chinfo
*ch
= data
;
521 ch
->delta
= (speed
<< 12) / 48000;
522 return (ch
->delta
* 48000) >> 12;
526 trpchan_setblocksize(kobj_t obj
, void *data
, u_int32_t blocksize
)
528 struct tr_chinfo
*ch
= data
;
530 sndbuf_resize(ch
->buffer
, 2, blocksize
);
535 trpchan_trigger(kobj_t obj
, void *data
, int go
)
537 struct tr_chinfo
*ch
= data
;
539 if (go
== PCMTRIG_EMLDMAWR
|| go
== PCMTRIG_EMLDMARD
)
542 if (go
== PCMTRIG_START
) {
547 ch
->lba
= sndbuf_getbufaddr(ch
->buffer
);
549 ch
->eso
= (sndbuf_getsize(ch
->buffer
) / sndbuf_getbps(ch
->buffer
)) - 1;
550 ch
->rvol
= ch
->cvol
= 0x7f;
568 trpchan_getptr(kobj_t obj
, void *data
)
570 struct tr_chinfo
*ch
= data
;
573 return ch
->cso
* sndbuf_getbps(ch
->buffer
);
576 static struct pcmchan_caps
*
577 trpchan_getcaps(kobj_t obj
, void *data
)
582 static kobj_method_t trpchan_methods
[] = {
583 KOBJMETHOD(channel_init
, trpchan_init
),
584 KOBJMETHOD(channel_setformat
, trpchan_setformat
),
585 KOBJMETHOD(channel_setspeed
, trpchan_setspeed
),
586 KOBJMETHOD(channel_setblocksize
, trpchan_setblocksize
),
587 KOBJMETHOD(channel_trigger
, trpchan_trigger
),
588 KOBJMETHOD(channel_getptr
, trpchan_getptr
),
589 KOBJMETHOD(channel_getcaps
, trpchan_getcaps
),
592 CHANNEL_DECLARE(trpchan
);
594 /* -------------------------------------------------------------------- */
595 /* rec channel interface */
598 trrchan_init(kobj_t obj
, void *devinfo
, struct snd_dbuf
*b
, struct pcm_channel
*c
, int dir
)
600 struct tr_info
*tr
= devinfo
;
601 struct tr_rchinfo
*ch
;
603 KASSERT(dir
== PCMDIR_REC
, ("trrchan_init: bad direction"));
608 if (sndbuf_alloc(ch
->buffer
, tr
->parent_dmat
, tr
->bufsz
) != 0)
615 trrchan_setformat(kobj_t obj
, void *data
, u_int32_t format
)
617 struct tr_rchinfo
*ch
= data
;
618 struct tr_info
*tr
= ch
->parent
;
621 bits
= tr_fmttobits(format
);
622 /* set # of samples between interrupts */
623 i
= (sndbuf_runsz(ch
->buffer
) >> ((bits
& 0x08)? 1 : 0)) - 1;
624 tr_wr(tr
, TR_REG_SBBL
, i
| (i
<< 16), 4);
625 /* set sample format */
626 i
= 0x18 | (bits
<< 4);
627 tr_wr(tr
, TR_REG_SBCTRL
, i
, 1);
634 trrchan_setspeed(kobj_t obj
, void *data
, u_int32_t speed
)
636 struct tr_rchinfo
*ch
= data
;
637 struct tr_info
*tr
= ch
->parent
;
640 ch
->delta
= (48000 << 12) / speed
;
641 tr_wr(tr
, TR_REG_SBDELTA
, ch
->delta
, 2);
643 /* return closest possible speed */
644 return (48000 << 12) / ch
->delta
;
648 trrchan_setblocksize(kobj_t obj
, void *data
, u_int32_t blocksize
)
650 struct tr_rchinfo
*ch
= data
;
652 sndbuf_resize(ch
->buffer
, 2, blocksize
);
658 trrchan_trigger(kobj_t obj
, void *data
, int go
)
660 struct tr_rchinfo
*ch
= data
;
661 struct tr_info
*tr
= ch
->parent
;
664 if (go
== PCMTRIG_EMLDMAWR
|| go
== PCMTRIG_EMLDMARD
)
667 if (go
== PCMTRIG_START
) {
668 /* set up dma mode regs */
669 tr_wr(tr
, TR_REG_DMAR15
, 0, 1);
670 i
= tr_rd(tr
, TR_REG_DMAR11
, 1) & 0x03;
671 tr_wr(tr
, TR_REG_DMAR11
, i
| 0x54, 1);
672 /* set up base address */
673 tr_wr(tr
, TR_REG_DMAR0
, sndbuf_getbufaddr(ch
->buffer
), 4);
674 /* set up buffer size */
675 i
= tr_rd(tr
, TR_REG_DMAR4
, 4) & ~0x00ffffff;
676 tr_wr(tr
, TR_REG_DMAR4
, i
| (sndbuf_runsz(ch
->buffer
) - 1), 4);
678 tr_wr(tr
, TR_REG_SBCTRL
, tr_rd(tr
, TR_REG_SBCTRL
, 1) | 1, 1);
681 tr_wr(tr
, TR_REG_SBCTRL
, tr_rd(tr
, TR_REG_SBCTRL
, 1) & ~7, 1);
690 trrchan_getptr(kobj_t obj
, void *data
)
692 struct tr_rchinfo
*ch
= data
;
693 struct tr_info
*tr
= ch
->parent
;
695 /* return current byte offset of channel */
696 return tr_rd(tr
, TR_REG_DMAR0
, 4) - sndbuf_getbufaddr(ch
->buffer
);
699 static struct pcmchan_caps
*
700 trrchan_getcaps(kobj_t obj
, void *data
)
705 static kobj_method_t trrchan_methods
[] = {
706 KOBJMETHOD(channel_init
, trrchan_init
),
707 KOBJMETHOD(channel_setformat
, trrchan_setformat
),
708 KOBJMETHOD(channel_setspeed
, trrchan_setspeed
),
709 KOBJMETHOD(channel_setblocksize
, trrchan_setblocksize
),
710 KOBJMETHOD(channel_trigger
, trrchan_trigger
),
711 KOBJMETHOD(channel_getptr
, trrchan_getptr
),
712 KOBJMETHOD(channel_getcaps
, trrchan_getcaps
),
715 CHANNEL_DECLARE(trrchan
);
717 /* -------------------------------------------------------------------- */
718 /* The interrupt handler */
723 struct tr_info
*tr
= (struct tr_info
*)p
;
724 struct tr_chinfo
*ch
;
725 u_int32_t active
, mask
, bufhalf
, chnum
, intsrc
;
728 intsrc
= tr_rd(tr
, TR_REG_MISCINT
, 4);
729 if (intsrc
& TR_INT_ADDR
) {
733 active
= tr_rd(tr
, (chnum
< 32)? TR_REG_ADDRINTA
: TR_REG_ADDRINTB
, 4);
734 bufhalf
= tr_rd(tr
, (chnum
< 32)? TR_REG_CSPF_A
: TR_REG_CSPF_B
, 4);
738 tmp
= (bufhalf
& mask
)? 1 : 0;
739 if (chnum
< tr
->playchns
) {
740 ch
= &tr
->chinfo
[chnum
];
741 /* kprintf("%d @ %d, ", chnum, trpchan_getptr(NULL, ch)); */
742 if (ch
->bufhalf
!= tmp
) {
743 chn_intr(ch
->channel
);
750 } while (chnum
& 31);
754 tr_wr(tr
, (chnum
<= 32)? TR_REG_ADDRINTA
: TR_REG_ADDRINTB
, active
, 4);
757 if (intsrc
& TR_INT_SB
) {
758 chn_intr(tr
->recchinfo
.channel
);
759 tr_rd(tr
, TR_REG_SBR9
, 1);
760 tr_rd(tr
, TR_REG_SBR10
, 1);
764 /* -------------------------------------------------------------------- */
767 * Probe and attach the card
771 tr_init(struct tr_info
*tr
)
775 tr_wr(tr
, SPA_REG_GPIO
, 0, 4);
776 tr_wr(tr
, SPA_REG_CODECST
, SPA_RST_OFF
, 4);
779 tr_wr(tr
, TDX_REG_CODECST
, TDX_CDC_ON
, 4);
782 tr_wr(tr
, TNX_REG_CODECST
, TNX_CDC_ON
, 4);
786 tr_wr(tr
, TR_REG_CIR
, TR_CIR_MIDENA
| TR_CIR_ADDRENA
, 4);
791 tr_pci_probe(device_t dev
)
793 switch (pci_get_devid(dev
)) {
795 device_set_desc(dev
, "SiS 7018");
796 return BUS_PROBE_DEFAULT
;
798 device_set_desc(dev
, "Acer Labs M5451");
799 return BUS_PROBE_DEFAULT
;
801 device_set_desc(dev
, "Trident 4DWave DX");
802 return BUS_PROBE_DEFAULT
;
804 device_set_desc(dev
, "Trident 4DWave NX");
805 return BUS_PROBE_DEFAULT
;
812 tr_pci_attach(device_t dev
)
816 struct ac97_info
*codec
= 0;
818 char status
[SND_STATUSLEN
];
820 if ((tr
= kmalloc(sizeof(*tr
), M_DEVBUF
, M_NOWAIT
| M_ZERO
)) == NULL
) {
821 device_printf(dev
, "cannot allocate softc\n");
825 tr
->type
= pci_get_devid(dev
);
826 tr
->rev
= pci_get_revid(dev
);
827 tr
->lock
= snd_mtxcreate(device_get_nameunit(dev
), "sound softc");
829 data
= pci_read_config(dev
, PCIR_COMMAND
, 2);
830 data
|= (PCIM_CMD_PORTEN
|PCIM_CMD_MEMEN
|PCIM_CMD_BUSMASTEREN
);
831 pci_write_config(dev
, PCIR_COMMAND
, data
, 2);
832 data
= pci_read_config(dev
, PCIR_COMMAND
, 2);
834 tr
->regid
= PCIR_BAR(0);
835 tr
->regtype
= SYS_RES_IOPORT
;
836 tr
->reg
= bus_alloc_resource_any(dev
, tr
->regtype
, &tr
->regid
,
839 tr
->st
= rman_get_bustag(tr
->reg
);
840 tr
->sh
= rman_get_bushandle(tr
->reg
);
842 device_printf(dev
, "unable to map register space\n");
846 tr
->bufsz
= pcm_getbuffersize(dev
, 4096, TR_DEFAULT_BUFSZ
, 65536);
848 if (tr_init(tr
) == -1) {
849 device_printf(dev
, "unable to initialize the card\n");
854 codec
= AC97_CREATE(dev
, tr
, tr_ac97
);
855 if (codec
== NULL
) goto bad
;
856 if (mixer_init(dev
, ac97_getmixerclass(), codec
) == -1) goto bad
;
859 tr
->irq
= bus_alloc_resource_any(dev
, SYS_RES_IRQ
, &tr
->irqid
,
860 RF_ACTIVE
| RF_SHAREABLE
);
861 if (!tr
->irq
|| snd_setup_intr(dev
, tr
->irq
, 0, tr_intr
, tr
, &tr
->ih
)) {
862 device_printf(dev
, "unable to map interrupt\n");
866 if (bus_dma_tag_create(/*parent*/NULL
, /*alignment*/2, /*boundary*/0,
867 /*lowaddr*/TR_MAXADDR
,
868 /*highaddr*/BUS_SPACE_MAXADDR
,
869 /*filter*/NULL
, /*filterarg*/NULL
,
870 /*maxsize*/tr
->bufsz
, /*nsegments*/1, /*maxsegz*/0x3ffff,
872 &tr
->parent_dmat
) != 0) {
873 device_printf(dev
, "unable to create dma tag\n");
877 ksnprintf(status
, 64, "at io 0x%lx irq %ld %s",
878 rman_get_start(tr
->reg
), rman_get_start(tr
->irq
),PCM_KLDSTRING(snd_t4dwave
));
880 if (pcm_register(dev
, tr
, TR_MAXPLAYCH
, 1)) goto bad
;
881 pcm_addchan(dev
, PCMDIR_REC
, &trrchan_class
, tr
);
882 for (i
= 0; i
< TR_MAXPLAYCH
; i
++)
883 pcm_addchan(dev
, PCMDIR_PLAY
, &trpchan_class
, tr
);
884 pcm_setstatus(dev
, status
);
889 if (codec
) ac97_destroy(codec
);
890 if (tr
->reg
) bus_release_resource(dev
, tr
->regtype
, tr
->regid
, tr
->reg
);
891 if (tr
->ih
) bus_teardown_intr(dev
, tr
->irq
, tr
->ih
);
892 if (tr
->irq
) bus_release_resource(dev
, SYS_RES_IRQ
, tr
->irqid
, tr
->irq
);
893 if (tr
->parent_dmat
) bus_dma_tag_destroy(tr
->parent_dmat
);
894 if (tr
->lock
) snd_mtxfree(tr
->lock
);
900 tr_pci_detach(device_t dev
)
905 r
= pcm_unregister(dev
);
909 tr
= pcm_getdevinfo(dev
);
910 bus_release_resource(dev
, tr
->regtype
, tr
->regid
, tr
->reg
);
911 bus_teardown_intr(dev
, tr
->irq
, tr
->ih
);
912 bus_release_resource(dev
, SYS_RES_IRQ
, tr
->irqid
, tr
->irq
);
913 bus_dma_tag_destroy(tr
->parent_dmat
);
914 snd_mtxfree(tr
->lock
);
921 tr_pci_suspend(device_t dev
)
926 tr
= pcm_getdevinfo(dev
);
928 for (i
= 0; i
< tr
->playchns
; i
++) {
929 tr
->chinfo
[i
].was_active
= tr
->chinfo
[i
].active
;
930 if (tr
->chinfo
[i
].active
) {
931 trpchan_trigger(NULL
, &tr
->chinfo
[i
], PCMTRIG_STOP
);
935 tr
->recchinfo
.was_active
= tr
->recchinfo
.active
;
936 if (tr
->recchinfo
.active
) {
937 trrchan_trigger(NULL
, &tr
->recchinfo
, PCMTRIG_STOP
);
944 tr_pci_resume(device_t dev
)
949 tr
= pcm_getdevinfo(dev
);
951 if (tr_init(tr
) == -1) {
952 device_printf(dev
, "unable to initialize the card\n");
956 if (mixer_reinit(dev
) == -1) {
957 device_printf(dev
, "unable to initialize the mixer\n");
961 for (i
= 0; i
< tr
->playchns
; i
++) {
962 if (tr
->chinfo
[i
].was_active
) {
963 trpchan_trigger(NULL
, &tr
->chinfo
[i
], PCMTRIG_START
);
967 if (tr
->recchinfo
.was_active
) {
968 trrchan_trigger(NULL
, &tr
->recchinfo
, PCMTRIG_START
);
974 static device_method_t tr_methods
[] = {
975 /* Device interface */
976 DEVMETHOD(device_probe
, tr_pci_probe
),
977 DEVMETHOD(device_attach
, tr_pci_attach
),
978 DEVMETHOD(device_detach
, tr_pci_detach
),
979 DEVMETHOD(device_suspend
, tr_pci_suspend
),
980 DEVMETHOD(device_resume
, tr_pci_resume
),
984 static driver_t tr_driver
= {
990 DRIVER_MODULE(snd_t4dwave
, pci
, tr_driver
, pcm_devclass
, 0, 0);
991 MODULE_DEPEND(snd_t4dwave
, sound
, SOUND_MINVER
, SOUND_PREFVER
, SOUND_MAXVER
);
992 MODULE_VERSION(snd_t4dwave
, 1);