2 * Copyright (c) 2002 Orion Hodson <orion@freebsd.org>
3 * Portions of this code derived from via82c686.c:
4 * Copyright (c) 2000 David Jones <dej@ox.org>
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, WHETHER IN 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 THE POSSIBILITY OF
28 * $FreeBSD: src/sys/dev/sound/pci/via8233.c,v 1.20.2.3 2007/04/26 08:21:44 ariff Exp $
29 * $DragonFly: src/sys/dev/sound/pci/via8233.c,v 1.10 2007/06/16 20:07:19 dillon Exp $
35 * Grzybowski Rafal, Russell Davies, Mark Handley, Daniel O'Connor for
36 * comments, machine time, testing patches, and patience. VIA for
37 * providing specs. ALSA for helpful comments and some register poke
41 #include <dev/sound/pcm/sound.h>
42 #include <dev/sound/pcm/ac97.h>
44 #include <bus/pci/pcireg.h>
45 #include <bus/pci/pcivar.h>
46 #include <sys/sysctl.h>
48 #include <dev/sound/pci/via8233.h>
50 SND_DECLARE_FILE("$DragonFly: src/sys/dev/sound/pci/via8233.c,v 1.10 2007/06/16 20:07:19 dillon Exp $");
52 #define VIA8233_PCI_ID 0x30591106
54 #define VIA8233_REV_ID_8233PRE 0x10
55 #define VIA8233_REV_ID_8233C 0x20
56 #define VIA8233_REV_ID_8233 0x30
57 #define VIA8233_REV_ID_8233A 0x40
58 #define VIA8233_REV_ID_8235 0x50
59 #define VIA8233_REV_ID_8237 0x60
60 #define VIA8233_REV_ID_8251 0x70
62 #define SEGS_PER_CHAN 2 /* Segments per channel */
63 #define NDXSCHANS 4 /* No of DXS channels */
64 #define NMSGDCHANS 1 /* No of multichannel SGD */
65 #define NWRCHANS 1 /* No of write channels */
66 #define NCHANS (NWRCHANS + NDXSCHANS + NMSGDCHANS)
67 #define NSEGS NCHANS * SEGS_PER_CHAN /* Segments in SGD table */
69 #define VIA_DEFAULT_BUFSZ 0x1000
71 /* we rely on this struct being packed to 64 bits */
73 volatile u_int32_t ptr
;
74 volatile u_int32_t flags
;
75 #define VIA_DMAOP_EOL 0x80000000
76 #define VIA_DMAOP_FLAG 0x40000000
77 #define VIA_DMAOP_STOP 0x20000000
78 #define VIA_DMAOP_COUNT(x) ((x)&0x00FFFFFF)
84 struct via_info
*parent
;
85 struct pcm_channel
*channel
;
86 struct snd_dbuf
*buffer
;
87 struct via_dma_op
*sgd_table
;
95 bus_space_handle_t sh
;
96 bus_dma_tag_t parent_dmat
;
97 bus_dma_tag_t sgd_dmat
;
98 bus_dmamap_t sgd_dmamap
;
101 struct resource
*reg
, *irq
;
104 struct ac97_info
*codec
;
107 int dxs_src
, dma_eol_wake
;
109 struct via_chinfo pch
[NDXSCHANS
+ NMSGDCHANS
];
110 struct via_chinfo rch
[NWRCHANS
];
111 struct via_dma_op
*sgd_table
;
112 u_int16_t codec_caps
;
113 u_int16_t n_dxs_registered
;
117 static u_int32_t via_fmt
[] = {
119 AFMT_STEREO
| AFMT_U8
,
121 AFMT_STEREO
| AFMT_S16_LE
,
125 static struct pcmchan_caps via_vracaps
= { 4000, 48000, via_fmt
, 0 };
126 static struct pcmchan_caps via_caps
= { 48000, 48000, via_fmt
, 0 };
130 sysctl_via8233_spdif_enable(SYSCTL_HANDLER_ARGS
)
132 struct via_info
*via
;
137 dev
= oidp
->oid_arg1
;
138 via
= pcm_getdevinfo(dev
);
139 snd_mtxlock(via
->lock
);
140 r
= pci_read_config(dev
, VIA_PCI_SPDIF
, 1);
141 snd_mtxunlock(via
->lock
);
142 new_en
= (r
& VIA_SPDIF_EN
) ? 1 : 0;
143 err
= sysctl_handle_int(oidp
, &new_en
, sizeof(new_en
), req
);
145 if (err
|| req
->newptr
== NULL
)
147 if (new_en
< 0 || new_en
> 1)
154 snd_mtxlock(via
->lock
);
155 pci_write_config(dev
, VIA_PCI_SPDIF
, r
, 1);
156 snd_mtxunlock(via
->lock
);
163 sysctl_via8233_dxs_src(SYSCTL_HANDLER_ARGS
)
165 struct via_info
*via
;
169 dev
= oidp
->oid_arg1
;
170 via
= pcm_getdevinfo(dev
);
171 snd_mtxlock(via
->lock
);
173 snd_mtxunlock(via
->lock
);
174 err
= sysctl_handle_int(oidp
, &val
, sizeof(val
), req
);
176 if (err
|| req
->newptr
== NULL
)
178 if (val
< 0 || val
> 1)
181 snd_mtxlock(via
->lock
);
183 snd_mtxunlock(via
->lock
);
188 #endif /* SND_DYNSYSCTL */
191 via_init_sysctls(device_t dev
)
194 SYSCTL_ADD_PROC(snd_sysctl_tree(dev
),
195 SYSCTL_CHILDREN(snd_sysctl_tree_top(dev
)),
196 OID_AUTO
, "spdif_enabled",
197 CTLTYPE_INT
| CTLFLAG_RW
, dev
, sizeof(dev
),
198 sysctl_via8233_spdif_enable
, "I",
199 "Enable S/PDIF output on primary playback channel");
201 SYSCTL_ADD_PROC(snd_sysctl_tree(dev
),
202 SYSCTL_CHILDREN(snd_sysctl_tree_top(dev
)),
203 OID_AUTO
, "via_dxs_src",
204 CTLTYPE_INT
| CTLFLAG_RW
, dev
, sizeof(dev
),
205 sysctl_via8233_dxs_src
, "I",
206 "Enable VIA DXS Sample Rate Converter");
211 static __inline u_int32_t
212 via_rd(struct via_info
*via
, int regno
, int size
)
216 return bus_space_read_1(via
->st
, via
->sh
, regno
);
218 return bus_space_read_2(via
->st
, via
->sh
, regno
);
220 return bus_space_read_4(via
->st
, via
->sh
, regno
);
227 via_wr(struct via_info
*via
, int regno
, u_int32_t data
, int size
)
232 bus_space_write_1(via
->st
, via
->sh
, regno
, data
);
235 bus_space_write_2(via
->st
, via
->sh
, regno
, data
);
238 bus_space_write_4(via
->st
, via
->sh
, regno
, data
);
243 /* -------------------------------------------------------------------- */
244 /* Codec interface */
247 via_waitready_codec(struct via_info
*via
)
251 /* poll until codec not busy */
252 for (i
= 0; i
< 1000; i
++) {
253 if ((via_rd(via
, VIA_AC97_CONTROL
, 4) & VIA_AC97_BUSY
) == 0)
257 kprintf("via: codec busy\n");
262 via_waitvalid_codec(struct via_info
*via
)
266 /* poll until codec valid */
267 for (i
= 0; i
< 1000; i
++) {
268 if (via_rd(via
, VIA_AC97_CONTROL
, 4) & VIA_AC97_CODEC00_VALID
)
272 kprintf("via: codec invalid\n");
277 via_write_codec(kobj_t obj
, void *addr
, int reg
, u_int32_t val
)
279 struct via_info
*via
= addr
;
281 if (via_waitready_codec(via
)) return -1;
283 via_wr(via
, VIA_AC97_CONTROL
,
284 VIA_AC97_CODEC00_VALID
| VIA_AC97_INDEX(reg
) |
285 VIA_AC97_DATA(val
), 4);
291 via_read_codec(kobj_t obj
, void *addr
, int reg
)
293 struct via_info
*via
= addr
;
295 if (via_waitready_codec(via
))
298 via_wr(via
, VIA_AC97_CONTROL
, VIA_AC97_CODEC00_VALID
|
299 VIA_AC97_READ
| VIA_AC97_INDEX(reg
), 4);
301 if (via_waitready_codec(via
))
304 if (via_waitvalid_codec(via
))
307 return via_rd(via
, VIA_AC97_CONTROL
, 2);
310 static kobj_method_t via_ac97_methods
[] = {
311 KOBJMETHOD(ac97_read
, via_read_codec
),
312 KOBJMETHOD(ac97_write
, via_write_codec
),
315 AC97_DECLARE(via_ac97
);
317 /* -------------------------------------------------------------------- */
320 via_buildsgdt(struct via_chinfo
*ch
)
322 u_int32_t phys_addr
, flag
;
325 seg_size
= sndbuf_getsize(ch
->buffer
) / SEGS_PER_CHAN
;
326 phys_addr
= sndbuf_getbufaddr(ch
->buffer
);
328 for (i
= 0; i
< SEGS_PER_CHAN
; i
++) {
329 flag
= (i
== SEGS_PER_CHAN
- 1) ? VIA_DMAOP_EOL
: VIA_DMAOP_FLAG
;
330 ch
->sgd_table
[i
].ptr
= phys_addr
+ (i
* seg_size
);
331 ch
->sgd_table
[i
].flags
= flag
| seg_size
;
337 /* -------------------------------------------------------------------- */
338 /* Format setting functions */
341 via8233wr_setformat(kobj_t obj
, void *data
, u_int32_t format
)
343 struct via_chinfo
*ch
= data
;
344 struct via_info
*via
= ch
->parent
;
346 u_int32_t f
= WR_FORMAT_STOP_INDEX
;
348 if (format
& AFMT_STEREO
)
349 f
|= WR_FORMAT_STEREO
;
350 if (format
& AFMT_S16_LE
)
351 f
|= WR_FORMAT_16BIT
;
352 snd_mtxlock(via
->lock
);
353 via_wr(via
, VIA_WR0_FORMAT
, f
, 4);
354 snd_mtxunlock(via
->lock
);
360 via8233dxs_setformat(kobj_t obj
, void *data
, u_int32_t format
)
362 struct via_chinfo
*ch
= data
;
363 struct via_info
*via
= ch
->parent
;
366 r
= ch
->rbase
+ VIA8233_RP_DXS_RATEFMT
;
367 snd_mtxlock(via
->lock
);
368 v
= via_rd(via
, r
, 4);
370 v
&= ~(VIA8233_DXS_RATEFMT_STEREO
| VIA8233_DXS_RATEFMT_16BIT
);
371 if (format
& AFMT_STEREO
)
372 v
|= VIA8233_DXS_RATEFMT_STEREO
;
373 if (format
& AFMT_16BIT
)
374 v
|= VIA8233_DXS_RATEFMT_16BIT
;
375 via_wr(via
, r
, v
, 4);
376 snd_mtxunlock(via
->lock
);
382 via8233msgd_setformat(kobj_t obj
, void *data
, u_int32_t format
)
384 struct via_chinfo
*ch
= data
;
385 struct via_info
*via
= ch
->parent
;
387 u_int32_t s
= 0xff000000;
388 u_int8_t v
= (format
& AFMT_S16_LE
) ? MC_SGD_16BIT
: MC_SGD_8BIT
;
390 if (format
& AFMT_STEREO
) {
391 v
|= MC_SGD_CHANNELS(2);
392 s
|= SLOT3(1) | SLOT4(2);
394 v
|= MC_SGD_CHANNELS(1);
395 s
|= SLOT3(1) | SLOT4(1);
398 snd_mtxlock(via
->lock
);
399 via_wr(via
, VIA_MC_SLOT_SELECT
, s
, 4);
400 via_wr(via
, VIA_MC_SGD_FORMAT
, v
, 1);
401 snd_mtxunlock(via
->lock
);
406 /* -------------------------------------------------------------------- */
407 /* Speed setting functions */
410 via8233wr_setspeed(kobj_t obj
, void *data
, u_int32_t speed
)
412 struct via_chinfo
*ch
= data
;
413 struct via_info
*via
= ch
->parent
;
415 if (via
->codec_caps
& AC97_EXTCAP_VRA
)
416 return ac97_setrate(via
->codec
, AC97_REGEXT_LADCRATE
, speed
);
422 via8233dxs_setspeed(kobj_t obj
, void *data
, u_int32_t speed
)
424 struct via_chinfo
*ch
= data
;
425 struct via_info
*via
= ch
->parent
;
428 r
= ch
->rbase
+ VIA8233_RP_DXS_RATEFMT
;
429 snd_mtxlock(via
->lock
);
430 v
= via_rd(via
, r
, 4) & ~VIA8233_DXS_RATEFMT_48K
;
432 /* Careful to avoid overflow (divide by 48 per vt8233c docs) */
434 v
|= VIA8233_DXS_RATEFMT_48K
* (speed
/ 48) / (48000 / 48);
435 via_wr(via
, r
, v
, 4);
436 snd_mtxunlock(via
->lock
);
442 via8233msgd_setspeed(kobj_t obj
, void *data
, u_int32_t speed
)
444 struct via_chinfo
*ch
= data
;
445 struct via_info
*via
= ch
->parent
;
447 if (via
->codec_caps
& AC97_EXTCAP_VRA
)
448 return ac97_setrate(via
->codec
, AC97_REGEXT_FDACRATE
, speed
);
453 /* -------------------------------------------------------------------- */
454 /* Format probing functions */
456 static struct pcmchan_caps
*
457 via8233wr_getcaps(kobj_t obj
, void *data
)
459 struct via_chinfo
*ch
= data
;
460 struct via_info
*via
= ch
->parent
;
462 /* Controlled by ac97 registers */
463 if (via
->codec_caps
& AC97_EXTCAP_VRA
)
468 static struct pcmchan_caps
*
469 via8233dxs_getcaps(kobj_t obj
, void *data
)
471 struct via_chinfo
*ch
= data
;
472 struct via_info
*via
= ch
->parent
;
475 * Controlled by onboard registers
477 * Apparently, few boards can do DXS sample rate
485 static struct pcmchan_caps
*
486 via8233msgd_getcaps(kobj_t obj
, void *data
)
488 struct via_chinfo
*ch
= data
;
489 struct via_info
*via
= ch
->parent
;
491 /* Controlled by ac97 registers */
492 if (via
->codec_caps
& AC97_EXTCAP_VRA
)
497 /* -------------------------------------------------------------------- */
498 /* Common functions */
501 via8233chan_setblocksize(kobj_t obj
, void *data
, u_int32_t blocksize
)
503 struct via_chinfo
*ch
= data
;
505 sndbuf_resize(ch
->buffer
, SEGS_PER_CHAN
, blocksize
);
506 ch
->blksz
= sndbuf_getblksz(ch
->buffer
);
511 via8233chan_getptr(kobj_t obj
, void *data
)
513 struct via_chinfo
*ch
= data
;
514 struct via_info
*via
= ch
->parent
;
515 u_int32_t v
, index
, count
;
518 snd_mtxlock(via
->lock
);
519 v
= via_rd(via
, ch
->rbase
+ VIA_RP_CURRENT_COUNT
, 4);
520 snd_mtxunlock(via
->lock
);
521 index
= v
>> 24; /* Last completed buffer */
522 count
= v
& 0x00ffffff; /* Bytes remaining */
523 ptr
= (index
+ 1) * ch
->blksz
- count
;
524 ptr
%= SEGS_PER_CHAN
* ch
->blksz
; /* Wrap to available space */
530 via8233chan_reset(struct via_info
*via
, struct via_chinfo
*ch
)
532 via_wr(via
, ch
->rbase
+ VIA_RP_CONTROL
, SGD_CONTROL_STOP
, 1);
533 via_wr(via
, ch
->rbase
+ VIA_RP_CONTROL
, 0x00, 1);
534 via_wr(via
, ch
->rbase
+ VIA_RP_STATUS
,
535 SGD_STATUS_EOL
| SGD_STATUS_FLAG
, 1);
538 /* -------------------------------------------------------------------- */
539 /* Channel initialization functions */
542 via8233chan_sgdinit(struct via_info
*via
, struct via_chinfo
*ch
, int chnum
)
544 ch
->sgd_table
= &via
->sgd_table
[chnum
* SEGS_PER_CHAN
];
545 ch
->sgd_addr
= via
->sgd_addr
+ chnum
* SEGS_PER_CHAN
* sizeof(struct via_dma_op
);
549 via8233wr_init(kobj_t obj
, void *devinfo
, struct snd_dbuf
*b
,
550 struct pcm_channel
*c
, int dir
)
552 struct via_info
*via
= devinfo
;
553 struct via_chinfo
*ch
= &via
->rch
[c
->num
];
560 ch
->rbase
= VIA_WR_BASE(c
->num
);
561 snd_mtxlock(via
->lock
);
562 via_wr(via
, ch
->rbase
+ VIA_WR_RP_SGD_FORMAT
, WR_FIFO_ENABLE
, 1);
563 snd_mtxunlock(via
->lock
);
565 if (sndbuf_alloc(ch
->buffer
, via
->parent_dmat
, via
->bufsz
) != 0)
568 snd_mtxlock(via
->lock
);
569 via8233chan_sgdinit(via
, ch
, c
->num
);
570 via8233chan_reset(via
, ch
);
571 snd_mtxunlock(via
->lock
);
577 via8233dxs_init(kobj_t obj
, void *devinfo
, struct snd_dbuf
*b
,
578 struct pcm_channel
*c
, int dir
)
580 struct via_info
*via
= devinfo
;
581 struct via_chinfo
*ch
= &via
->pch
[c
->num
];
589 * All cards apparently support DXS3, but not other DXS
590 * channels. We therefore want to align first DXS channel to
593 snd_mtxlock(via
->lock
);
594 ch
->rbase
= VIA_DXS_BASE(NDXSCHANS
- 1 - via
->n_dxs_registered
);
595 via
->n_dxs_registered
++;
596 snd_mtxunlock(via
->lock
);
598 if (sndbuf_alloc(ch
->buffer
, via
->parent_dmat
, via
->bufsz
) != 0)
601 snd_mtxlock(via
->lock
);
602 via8233chan_sgdinit(via
, ch
, NWRCHANS
+ c
->num
);
603 via8233chan_reset(via
, ch
);
604 snd_mtxunlock(via
->lock
);
610 via8233msgd_init(kobj_t obj
, void *devinfo
, struct snd_dbuf
*b
,
611 struct pcm_channel
*c
, int dir
)
613 struct via_info
*via
= devinfo
;
614 struct via_chinfo
*ch
= &via
->pch
[c
->num
];
620 ch
->rbase
= VIA_MC_SGD_STATUS
;
622 if (sndbuf_alloc(ch
->buffer
, via
->parent_dmat
, via
->bufsz
) != 0)
625 snd_mtxlock(via
->lock
);
626 via8233chan_sgdinit(via
, ch
, NWRCHANS
+ c
->num
);
627 via8233chan_reset(via
, ch
);
628 snd_mtxunlock(via
->lock
);
634 via8233chan_mute(struct via_info
*via
, struct via_chinfo
*ch
, int muted
)
636 if (BASE_IS_VIA_DXS_REG(ch
->rbase
)) {
638 muted
= (muted
) ? VIA8233_DXS_MUTE
: 0;
639 via_wr(via
, ch
->rbase
+ VIA8233_RP_DXS_LVOL
, muted
, 1);
640 via_wr(via
, ch
->rbase
+ VIA8233_RP_DXS_RVOL
, muted
, 1);
641 r
= via_rd(via
, ch
->rbase
+ VIA8233_RP_DXS_LVOL
, 1) & VIA8233_DXS_MUTE
;
643 kprintf("via: failed to set dxs volume "
644 "(dxs base 0x%02x).\n", ch
->rbase
);
650 via8233chan_trigger(kobj_t obj
, void* data
, int go
)
652 struct via_chinfo
*ch
= data
;
653 struct via_info
*via
= ch
->parent
;
655 snd_mtxlock(via
->lock
);
659 via8233chan_mute(via
, ch
, 0);
660 via_wr(via
, ch
->rbase
+ VIA_RP_TABLE_PTR
, ch
->sgd_addr
, 4);
661 via_wr(via
, ch
->rbase
+ VIA_RP_CONTROL
,
662 SGD_CONTROL_START
| SGD_CONTROL_AUTOSTART
|
663 SGD_CONTROL_I_EOL
| SGD_CONTROL_I_FLAG
, 1);
667 via_wr(via
, ch
->rbase
+ VIA_RP_CONTROL
, SGD_CONTROL_STOP
, 1);
668 via8233chan_mute(via
, ch
, 1);
669 via8233chan_reset(via
, ch
);
672 snd_mtxunlock(via
->lock
);
676 static kobj_method_t via8233wr_methods
[] = {
677 KOBJMETHOD(channel_init
, via8233wr_init
),
678 KOBJMETHOD(channel_setformat
, via8233wr_setformat
),
679 KOBJMETHOD(channel_setspeed
, via8233wr_setspeed
),
680 KOBJMETHOD(channel_getcaps
, via8233wr_getcaps
),
681 KOBJMETHOD(channel_setblocksize
, via8233chan_setblocksize
),
682 KOBJMETHOD(channel_trigger
, via8233chan_trigger
),
683 KOBJMETHOD(channel_getptr
, via8233chan_getptr
),
686 CHANNEL_DECLARE(via8233wr
);
688 static kobj_method_t via8233dxs_methods
[] = {
689 KOBJMETHOD(channel_init
, via8233dxs_init
),
690 KOBJMETHOD(channel_setformat
, via8233dxs_setformat
),
691 KOBJMETHOD(channel_setspeed
, via8233dxs_setspeed
),
692 KOBJMETHOD(channel_getcaps
, via8233dxs_getcaps
),
693 KOBJMETHOD(channel_setblocksize
, via8233chan_setblocksize
),
694 KOBJMETHOD(channel_trigger
, via8233chan_trigger
),
695 KOBJMETHOD(channel_getptr
, via8233chan_getptr
),
698 CHANNEL_DECLARE(via8233dxs
);
700 static kobj_method_t via8233msgd_methods
[] = {
701 KOBJMETHOD(channel_init
, via8233msgd_init
),
702 KOBJMETHOD(channel_setformat
, via8233msgd_setformat
),
703 KOBJMETHOD(channel_setspeed
, via8233msgd_setspeed
),
704 KOBJMETHOD(channel_getcaps
, via8233msgd_getcaps
),
705 KOBJMETHOD(channel_setblocksize
, via8233chan_setblocksize
),
706 KOBJMETHOD(channel_trigger
, via8233chan_trigger
),
707 KOBJMETHOD(channel_getptr
, via8233chan_getptr
),
710 CHANNEL_DECLARE(via8233msgd
);
712 /* -------------------------------------------------------------------- */
717 struct via_info
*via
= p
;
720 /* Poll playback channels */
721 snd_mtxlock(via
->lock
);
722 for (i
= 0; i
< NDXSCHANS
+ NMSGDCHANS
; i
++) {
723 if (via
->pch
[i
].channel
== NULL
)
725 reg
= via
->pch
[i
].rbase
+ VIA_RP_STATUS
;
726 stat
= via_rd(via
, reg
, 1);
727 if (stat
& SGD_STATUS_INTR
) {
728 if (via
->dma_eol_wake
&& ((stat
& SGD_STATUS_EOL
) ||
729 !(stat
& SGD_STATUS_ACTIVE
))) {
731 via
->pch
[i
].rbase
+ VIA_RP_CONTROL
,
733 SGD_CONTROL_AUTOSTART
|
735 SGD_CONTROL_I_FLAG
, 1);
737 via_wr(via
, reg
, stat
, 1);
738 snd_mtxunlock(via
->lock
);
739 chn_intr(via
->pch
[i
].channel
);
740 snd_mtxlock(via
->lock
);
744 /* Poll record channels */
745 for (i
= 0; i
< NWRCHANS
; i
++) {
746 if (via
->rch
[i
].channel
== NULL
)
748 reg
= via
->rch
[i
].rbase
+ VIA_RP_STATUS
;
749 stat
= via_rd(via
, reg
, 1);
750 if (stat
& SGD_STATUS_INTR
) {
751 if (via
->dma_eol_wake
&& ((stat
& SGD_STATUS_EOL
) ||
752 !(stat
& SGD_STATUS_ACTIVE
))) {
754 via
->rch
[i
].rbase
+ VIA_RP_CONTROL
,
756 SGD_CONTROL_AUTOSTART
|
758 SGD_CONTROL_I_FLAG
, 1);
760 via_wr(via
, reg
, stat
, 1);
761 snd_mtxunlock(via
->lock
);
762 chn_intr(via
->rch
[i
].channel
);
763 snd_mtxlock(via
->lock
);
766 snd_mtxunlock(via
->lock
);
770 * Probe and attach the card
773 via_probe(device_t dev
)
775 switch(pci_get_devid(dev
)) {
777 switch(pci_get_revid(dev
)) {
778 case VIA8233_REV_ID_8233PRE
:
779 device_set_desc(dev
, "VIA VT8233 (pre)");
780 return BUS_PROBE_DEFAULT
;
781 case VIA8233_REV_ID_8233C
:
782 device_set_desc(dev
, "VIA VT8233C");
783 return BUS_PROBE_DEFAULT
;
784 case VIA8233_REV_ID_8233
:
785 device_set_desc(dev
, "VIA VT8233");
786 return BUS_PROBE_DEFAULT
;
787 case VIA8233_REV_ID_8233A
:
788 device_set_desc(dev
, "VIA VT8233A");
789 return BUS_PROBE_DEFAULT
;
790 case VIA8233_REV_ID_8235
:
791 device_set_desc(dev
, "VIA VT8235");
792 return BUS_PROBE_DEFAULT
;
793 case VIA8233_REV_ID_8237
:
794 device_set_desc(dev
, "VIA VT8237");
795 return BUS_PROBE_DEFAULT
;
796 case VIA8233_REV_ID_8251
:
797 device_set_desc(dev
, "VIA VT8251");
798 return BUS_PROBE_DEFAULT
;
800 device_set_desc(dev
, "VIA VT8233X"); /* Unknown */
801 return BUS_PROBE_DEFAULT
;
808 dma_cb(void *p
, bus_dma_segment_t
*bds
, int a
, int b
)
810 struct via_info
*via
= (struct via_info
*)p
;
811 via
->sgd_addr
= bds
->ds_addr
;
815 via_chip_init(device_t dev
)
819 /* Wake up and reset AC97 if necessary */
820 data
= pci_read_config(dev
, VIA_PCI_ACLINK_STAT
, 1);
822 if ((data
& VIA_PCI_ACLINK_C00_READY
) == 0) {
823 /* Cold reset per ac97r2.3 spec (page 95) */
825 pci_write_config(dev
, VIA_PCI_ACLINK_CTRL
,
826 VIA_PCI_ACLINK_EN
, 1);
830 pci_write_config(dev
, VIA_PCI_ACLINK_CTRL
,
831 VIA_PCI_ACLINK_EN
| VIA_PCI_ACLINK_NRST
, 1);
835 pci_write_config(dev
, VIA_PCI_ACLINK_CTRL
,
836 VIA_PCI_ACLINK_EN
, 1);
840 pci_write_config(dev
, VIA_PCI_ACLINK_CTRL
,
841 VIA_PCI_ACLINK_EN
, 1);
844 pci_write_config(dev
, VIA_PCI_ACLINK_CTRL
,
845 VIA_PCI_ACLINK_EN
| VIA_PCI_ACLINK_SYNC
, 1);
846 /* Wait T_sync_high */
849 pci_write_config(dev
, VIA_PCI_ACLINK_CTRL
,
850 VIA_PCI_ACLINK_EN
, 1);
851 /* Wait T_sync2clk */
855 /* Power everything up */
856 pci_write_config(dev
, VIA_PCI_ACLINK_CTRL
, VIA_PCI_ACLINK_DESIRED
, 1);
858 /* Wait for codec to become ready (largest reported delay 310ms) */
859 for (cnt
= 0; cnt
< 2000; cnt
++) {
860 data
= pci_read_config(dev
, VIA_PCI_ACLINK_STAT
, 1);
861 if (data
& VIA_PCI_ACLINK_C00_READY
) {
866 device_printf(dev
, "primary codec not ready (cnt = 0x%02x)\n", cnt
);
871 via_attach(device_t dev
)
873 struct via_info
*via
= 0;
874 char status
[SND_STATUSLEN
];
875 int i
, via_dxs_disabled
, via_dxs_src
, via_dxs_chnum
, via_sgd_chnum
;
878 if ((via
= kmalloc(sizeof *via
, M_DEVBUF
, M_NOWAIT
| M_ZERO
)) == NULL
) {
879 device_printf(dev
, "cannot allocate softc\n");
882 via
->lock
= snd_mtxcreate(device_get_nameunit(dev
), "sound softc");
884 pci_set_powerstate(dev
, PCI_POWERSTATE_D0
);
885 pci_enable_busmaster(dev
);
887 via
->regid
= PCIR_BAR(0);
888 via
->reg
= bus_alloc_resource_any(dev
, SYS_RES_IOPORT
, &via
->regid
,
891 device_printf(dev
, "cannot allocate bus resource.");
894 via
->st
= rman_get_bustag(via
->reg
);
895 via
->sh
= rman_get_bushandle(via
->reg
);
897 via
->bufsz
= pcm_getbuffersize(dev
, 4096, VIA_DEFAULT_BUFSZ
, 65536);
900 via
->irq
= bus_alloc_resource_any(dev
, SYS_RES_IRQ
, &via
->irqid
,
901 RF_ACTIVE
| RF_SHAREABLE
);
903 snd_setup_intr(dev
, via
->irq
, INTR_MPSAFE
, via_intr
, via
, &via
->ih
)) {
904 device_printf(dev
, "unable to map interrupt\n");
908 /* DMA tag for buffers */
909 if (bus_dma_tag_create(/*parent*/NULL
, /*alignment*/2, /*boundary*/0,
910 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT
,
911 /*highaddr*/BUS_SPACE_MAXADDR
,
912 /*filter*/NULL
, /*filterarg*/NULL
,
913 /*maxsize*/via
->bufsz
, /*nsegments*/1, /*maxsegz*/0x3ffff,
915 &via
->parent_dmat
) != 0) {
916 device_printf(dev
, "unable to create dma tag\n");
921 * DMA tag for SGD table. The 686 uses scatter/gather DMA and
922 * requires a list in memory of work to do. We need only 16 bytes
923 * for this list, and it is wasteful to allocate 16K.
925 if (bus_dma_tag_create(/*parent*/NULL
, /*alignment*/2, /*boundary*/0,
926 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT
,
927 /*highaddr*/BUS_SPACE_MAXADDR
,
928 /*filter*/NULL
, /*filterarg*/NULL
,
929 /*maxsize*/NSEGS
* sizeof(struct via_dma_op
),
930 /*nsegments*/1, /*maxsegz*/0x3ffff,
932 &via
->sgd_dmat
) != 0) {
933 device_printf(dev
, "unable to create dma tag\n");
937 if (bus_dmamem_alloc(via
->sgd_dmat
, (void **)&via
->sgd_table
,
938 BUS_DMA_NOWAIT
, &via
->sgd_dmamap
) == -1)
940 if (bus_dmamap_load(via
->sgd_dmat
, via
->sgd_dmamap
, via
->sgd_table
,
941 NSEGS
* sizeof(struct via_dma_op
), dma_cb
, via
, 0))
944 if (via_chip_init(dev
))
947 via
->codec
= AC97_CREATE(dev
, via
, via_ac97
);
951 mixer_init(dev
, ac97_getmixerclass(), via
->codec
);
953 via
->codec_caps
= ac97_getextcaps(via
->codec
);
955 /* Try to set VRA without generating an error, VRM not reqrd yet */
956 if (via
->codec_caps
&
957 (AC97_EXTCAP_VRA
| AC97_EXTCAP_VRM
| AC97_EXTCAP_DRA
)) {
958 u_int16_t ext
= ac97_getextmode(via
->codec
);
959 ext
|= (via
->codec_caps
&
960 (AC97_EXTCAP_VRA
| AC97_EXTCAP_VRM
));
961 ext
&= ~AC97_EXTCAP_DRA
;
962 ac97_setextmode(via
->codec
, ext
);
965 ksnprintf(status
, SND_STATUSLEN
, "at io 0x%lx irq %ld %s",
966 rman_get_start(via
->reg
), rman_get_start(via
->irq
),PCM_KLDSTRING(snd_via8233
));
968 revid
= pci_get_revid(dev
);
971 * VIA8251 lost its interrupt after DMA EOL, and need
972 * a gentle spank on its face within interrupt handler.
974 if (revid
== VIA8233_REV_ID_8251
)
975 via
->dma_eol_wake
= 1;
977 via
->dma_eol_wake
= 0;
980 * Decide whether DXS had to be disabled or not
982 if (revid
== VIA8233_REV_ID_8233A
) {
984 * DXS channel is disabled. Reports from multiple users
985 * that it plays at half-speed. Do not see this behaviour
986 * on available 8233C or when emulating 8233A register set
987 * on 8233C (either with or without ac97 VRA).
989 via_dxs_disabled
= 1;
990 } else if (resource_int_value(device_get_name(dev
),
991 device_get_unit(dev
), "via_dxs_disabled",
992 &via_dxs_disabled
) == 0)
993 via_dxs_disabled
= (via_dxs_disabled
> 0) ? 1 : 0;
995 via_dxs_disabled
= 0;
997 if (via_dxs_disabled
) {
1001 if (resource_int_value(device_get_name(dev
),
1002 device_get_unit(dev
), "via_dxs_channels",
1003 &via_dxs_chnum
) != 0)
1004 via_dxs_chnum
= NDXSCHANS
;
1005 if (resource_int_value(device_get_name(dev
),
1006 device_get_unit(dev
), "via_sgd_channels",
1007 &via_sgd_chnum
) != 0)
1008 via_sgd_chnum
= NMSGDCHANS
;
1010 if (via_dxs_chnum
> NDXSCHANS
)
1011 via_dxs_chnum
= NDXSCHANS
;
1012 else if (via_dxs_chnum
< 0)
1014 if (via_sgd_chnum
> NMSGDCHANS
)
1015 via_sgd_chnum
= NMSGDCHANS
;
1016 else if (via_sgd_chnum
< 0)
1018 if (via_dxs_chnum
+ via_sgd_chnum
< 1) {
1023 if (via_dxs_chnum
> 0 && resource_int_value(device_get_name(dev
),
1024 device_get_unit(dev
), "via_dxs_src",
1026 via
->dxs_src
= (via_dxs_src
> 0) ? 1 : 0;
1030 if (pcm_register(dev
, via
, via_dxs_chnum
+ via_sgd_chnum
, NWRCHANS
))
1032 for (i
= 0; i
< via_dxs_chnum
; i
++)
1033 pcm_addchan(dev
, PCMDIR_PLAY
, &via8233dxs_class
, via
);
1034 for (i
= 0; i
< via_sgd_chnum
; i
++)
1035 pcm_addchan(dev
, PCMDIR_PLAY
, &via8233msgd_class
, via
);
1036 for (i
= 0; i
< NWRCHANS
; i
++)
1037 pcm_addchan(dev
, PCMDIR_REC
, &via8233wr_class
, via
);
1038 if (via_dxs_chnum
> 0)
1039 via_init_sysctls(dev
);
1040 device_printf(dev
, "<VIA DXS %sabled: DXS%s %d / SGD %d / REC %d>\n",
1041 (via_dxs_chnum
> 0) ? "En" : "Dis",
1042 (via
->dxs_src
) ? "(SRC)" : "",
1043 via_dxs_chnum
, via_sgd_chnum
, NWRCHANS
);
1045 pcm_setstatus(dev
, status
);
1049 if (via
->codec
) ac97_destroy(via
->codec
);
1050 if (via
->reg
) bus_release_resource(dev
, SYS_RES_IOPORT
, via
->regid
, via
->reg
);
1051 if (via
->ih
) bus_teardown_intr(dev
, via
->irq
, via
->ih
);
1052 if (via
->irq
) bus_release_resource(dev
, SYS_RES_IRQ
, via
->irqid
, via
->irq
);
1053 if (via
->parent_dmat
) bus_dma_tag_destroy(via
->parent_dmat
);
1054 if (via
->sgd_dmamap
) bus_dmamap_unload(via
->sgd_dmat
, via
->sgd_dmamap
);
1055 if (via
->sgd_table
) bus_dmamem_free(via
->sgd_dmat
, via
->sgd_table
, via
->sgd_dmamap
);
1056 if (via
->sgd_dmat
) bus_dma_tag_destroy(via
->sgd_dmat
);
1057 if (via
->lock
) snd_mtxfree(via
->lock
);
1058 if (via
) kfree(via
, M_DEVBUF
);
1063 via_detach(device_t dev
)
1066 struct via_info
*via
= 0;
1068 r
= pcm_unregister(dev
);
1071 via
= pcm_getdevinfo(dev
);
1072 bus_release_resource(dev
, SYS_RES_IOPORT
, via
->regid
, via
->reg
);
1073 bus_teardown_intr(dev
, via
->irq
, via
->ih
);
1074 bus_release_resource(dev
, SYS_RES_IRQ
, via
->irqid
, via
->irq
);
1075 bus_dma_tag_destroy(via
->parent_dmat
);
1076 bus_dmamap_unload(via
->sgd_dmat
, via
->sgd_dmamap
);
1077 bus_dmamem_free(via
->sgd_dmat
, via
->sgd_table
, via
->sgd_dmamap
);
1078 bus_dma_tag_destroy(via
->sgd_dmat
);
1079 snd_mtxfree(via
->lock
);
1080 kfree(via
, M_DEVBUF
);
1085 static device_method_t via_methods
[] = {
1086 DEVMETHOD(device_probe
, via_probe
),
1087 DEVMETHOD(device_attach
, via_attach
),
1088 DEVMETHOD(device_detach
, via_detach
),
1092 static driver_t via_driver
= {
1098 DRIVER_MODULE(snd_via8233
, pci
, via_driver
, pcm_devclass
, 0, 0);
1099 MODULE_DEPEND(snd_via8233
, sound
, SOUND_MINVER
, SOUND_PREFVER
, SOUND_MAXVER
);
1100 MODULE_VERSION(snd_via8233
, 1);