1 /* $NetBSD: sv.c,v 1.43 2009/08/18 11:12:05 drochner Exp $ */
2 /* $OpenBSD: sv.c,v 1.2 1998/07/13 01:50:15 csapuntz Exp $ */
5 * Copyright (c) 1999 The NetBSD Foundation, Inc.
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Charles M. Hannum.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
34 * Copyright (c) 1998 Constantine Paul Sapuntzakis
37 * Author: Constantine Paul Sapuntzakis (csapuntz@cvs.openbsd.org)
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 * 3. The author's name or those of the contributors may be used to
48 * endorse or promote products derived from this software without
49 * specific prior written permission.
51 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS
52 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
53 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
54 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
55 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
56 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
57 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
58 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
59 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
61 * POSSIBILITY OF SUCH DAMAGE.
65 * S3 SonicVibes driver
66 * Heavily based on the eap driver by Lennart Augustsson
69 #include <sys/cdefs.h>
70 __KERNEL_RCSID(0, "$NetBSD: sv.c,v 1.43 2009/08/18 11:12:05 drochner Exp $");
72 #include <sys/param.h>
73 #include <sys/systm.h>
74 #include <sys/kernel.h>
75 #include <sys/malloc.h>
76 #include <sys/device.h>
78 #include <dev/pci/pcireg.h>
79 #include <dev/pci/pcivar.h>
80 #include <dev/pci/pcidevs.h>
82 #include <sys/audioio.h>
83 #include <dev/audio_if.h>
84 #include <dev/mulaw.h>
85 #include <dev/auconv.h>
87 #include <dev/ic/i8237reg.h>
88 #include <dev/pci/svreg.h>
89 #include <dev/pci/svvar.h>
94 * The SonicVibes DMA is broken and only works on 24-bit addresses.
95 * As long as bus_dmamem_alloc_range() is missing we use the ISA
101 #include <dev/isa/isavar.h>
106 #define DPRINTF(x) if (svdebug) printf x
107 #define DPRINTFN(n,x) if (svdebug>(n)) printf x
111 #define DPRINTFN(n,x)
114 static int sv_match(device_t
, cfdata_t
, void *);
115 static void sv_attach(device_t
, device_t
, void *);
116 static int sv_intr(void *);
121 bus_dma_segment_t segs
[1];
126 #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
127 #define KERNADDR(p) ((void *)((p)->addr))
129 CFATTACH_DECL(sv
, sizeof(struct sv_softc
),
130 sv_match
, sv_attach
, NULL
, NULL
);
132 static struct audio_device sv_device
= {
138 #define ARRAY_SIZE(foo) ((sizeof(foo)) / sizeof(foo[0]))
140 static int sv_allocmem(struct sv_softc
*, size_t, size_t, int,
142 static int sv_freemem(struct sv_softc
*, struct sv_dma
*);
144 static void sv_init_mixer(struct sv_softc
*);
146 static int sv_open(void *, int);
147 static int sv_query_encoding(void *, struct audio_encoding
*);
148 static int sv_set_params(void *, int, int, audio_params_t
*,
149 audio_params_t
*, stream_filter_list_t
*,
150 stream_filter_list_t
*);
151 static int sv_round_blocksize(void *, int, int, const audio_params_t
*);
152 static int sv_trigger_output(void *, void *, void *, int, void (*)(void *),
153 void *, const audio_params_t
*);
154 static int sv_trigger_input(void *, void *, void *, int, void (*)(void *),
155 void *, const audio_params_t
*);
156 static int sv_halt_output(void *);
157 static int sv_halt_input(void *);
158 static int sv_getdev(void *, struct audio_device
*);
159 static int sv_mixer_set_port(void *, mixer_ctrl_t
*);
160 static int sv_mixer_get_port(void *, mixer_ctrl_t
*);
161 static int sv_query_devinfo(void *, mixer_devinfo_t
*);
162 static void * sv_malloc(void *, int, size_t, struct malloc_type
*, int);
163 static void sv_free(void *, void *, struct malloc_type
*);
164 static size_t sv_round_buffersize(void *, int, size_t);
165 static paddr_t
sv_mappage(void *, void *, off_t
, int);
166 static int sv_get_props(void *);
169 void sv_dumpregs(struct sv_softc
*sc
);
172 static const struct audio_hw_if sv_hw_if
= {
203 #define SV_NFORMATS 4
204 static const struct audio_format sv_formats
[SV_NFORMATS
] = {
205 {NULL
, AUMODE_PLAY
| AUMODE_RECORD
, AUDIO_ENCODING_SLINEAR_LE
, 16, 16,
206 2, AUFMT_STEREO
, 0, {2000, 48000}},
207 {NULL
, AUMODE_PLAY
| AUMODE_RECORD
, AUDIO_ENCODING_SLINEAR_LE
, 16, 16,
208 1, AUFMT_MONAURAL
, 0, {2000, 48000}},
209 {NULL
, AUMODE_PLAY
| AUMODE_RECORD
, AUDIO_ENCODING_ULINEAR_LE
, 8, 8,
210 2, AUFMT_STEREO
, 0, {2000, 48000}},
211 {NULL
, AUMODE_PLAY
| AUMODE_RECORD
, AUDIO_ENCODING_ULINEAR_LE
, 8, 8,
212 1, AUFMT_MONAURAL
, 0, {2000, 48000}},
217 sv_write(struct sv_softc
*sc
, uint8_t reg
, uint8_t val
)
220 DPRINTFN(8,("sv_write(0x%x, 0x%x)\n", reg
, val
));
221 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, reg
, val
);
225 sv_read(struct sv_softc
*sc
, uint8_t reg
)
229 val
= bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, reg
);
230 DPRINTFN(8,("sv_read(0x%x) = 0x%x\n", reg
, val
));
235 sv_read_indirect(struct sv_softc
*sc
, uint8_t reg
)
241 sv_write(sc
, SV_CODEC_IADDR
, reg
& SV_IADDR_MASK
);
242 val
= sv_read(sc
, SV_CODEC_IDATA
);
248 sv_write_indirect(struct sv_softc
*sc
, uint8_t reg
, uint8_t val
)
253 iaddr
= reg
& SV_IADDR_MASK
;
255 if (reg
== SV_DMA_DATA_FORMAT
)
256 iaddr
|= SV_IADDR_MCE
;
258 sv_write(sc
, SV_CODEC_IADDR
, iaddr
);
259 sv_write(sc
, SV_CODEC_IDATA
, val
);
264 sv_match(device_t parent
, cfdata_t match
, void *aux
)
266 struct pci_attach_args
*pa
;
269 if (PCI_VENDOR(pa
->pa_id
) == PCI_VENDOR_S3
&&
270 PCI_PRODUCT(pa
->pa_id
) == PCI_PRODUCT_S3_SONICVIBES
)
276 static pcireg_t pci_io_alloc_low
, pci_io_alloc_high
;
279 pci_alloc_io(pci_chipset_tag_t pc
, pcitag_t pt
, int pcioffs
,
280 bus_space_tag_t iot
, bus_size_t size
, bus_size_t align
,
281 bus_size_t bound
, int flags
, bus_space_handle_t
*ioh
)
286 error
= bus_space_alloc(iot
, pci_io_alloc_low
, pci_io_alloc_high
,
287 size
, align
, bound
, flags
, &addr
, ioh
);
291 pci_conf_write(pc
, pt
, pcioffs
, addr
);
296 * Allocate IO addresses when all other configuration is done.
299 sv_defer(device_t self
)
302 pci_chipset_tag_t pc
;
306 sc
= device_private(self
);
307 pc
= sc
->sc_pa
.pa_pc
;
308 pt
= sc
->sc_pa
.pa_tag
;
309 DPRINTF(("sv_defer: %p\n", sc
));
312 * Get a reasonable default for the I/O range.
313 * Assume the range around SB_PORTBASE is valid on this PCI bus.
315 pci_io_alloc_low
= pci_conf_read(pc
, pt
, SV_SB_PORTBASE_SLOT
);
316 pci_io_alloc_high
= pci_io_alloc_low
+ 0x1000;
318 if (pci_alloc_io(pc
, pt
, SV_DMAA_CONFIG_OFF
,
319 sc
->sc_iot
, SV_DMAA_SIZE
, SV_DMAA_ALIGN
, 0,
320 0, &sc
->sc_dmaa_ioh
)) {
321 printf("sv_attach: cannot allocate DMA A range\n");
324 dmaio
= pci_conf_read(pc
, pt
, SV_DMAA_CONFIG_OFF
);
325 DPRINTF(("sv_attach: addr a dmaio=0x%lx\n", (u_long
)dmaio
));
326 pci_conf_write(pc
, pt
, SV_DMAA_CONFIG_OFF
,
327 dmaio
| SV_DMA_CHANNEL_ENABLE
| SV_DMAA_EXTENDED_ADDR
);
329 if (pci_alloc_io(pc
, pt
, SV_DMAC_CONFIG_OFF
,
330 sc
->sc_iot
, SV_DMAC_SIZE
, SV_DMAC_ALIGN
, 0,
331 0, &sc
->sc_dmac_ioh
)) {
332 printf("sv_attach: cannot allocate DMA C range\n");
335 dmaio
= pci_conf_read(pc
, pt
, SV_DMAC_CONFIG_OFF
);
336 DPRINTF(("sv_attach: addr c dmaio=0x%lx\n", (u_long
)dmaio
));
337 pci_conf_write(pc
, pt
, SV_DMAC_CONFIG_OFF
,
338 dmaio
| SV_DMA_CHANNEL_ENABLE
);
344 sv_attach(device_t parent
, device_t self
, void *aux
)
347 struct pci_attach_args
*pa
;
348 pci_chipset_tag_t pc
;
350 pci_intr_handle_t ih
;
354 struct audio_attach_args arg
;
356 sc
= device_private(self
);
362 /* Map I/O registers */
363 if (pci_mapreg_map(pa
, SV_ENHANCED_PORTBASE_SLOT
,
364 PCI_MAPREG_TYPE_IO
, 0,
365 &sc
->sc_iot
, &sc
->sc_ioh
, NULL
, NULL
)) {
366 aprint_error_dev(&sc
->sc_dev
, "can't map enhanced i/o space\n");
369 if (pci_mapreg_map(pa
, SV_FM_PORTBASE_SLOT
,
370 PCI_MAPREG_TYPE_IO
, 0,
371 &sc
->sc_opliot
, &sc
->sc_oplioh
, NULL
, NULL
)) {
372 aprint_error_dev(&sc
->sc_dev
, "can't map FM i/o space\n");
375 if (pci_mapreg_map(pa
, SV_MIDI_PORTBASE_SLOT
,
376 PCI_MAPREG_TYPE_IO
, 0,
377 &sc
->sc_midiiot
, &sc
->sc_midiioh
, NULL
, NULL
)) {
378 aprint_error_dev(&sc
->sc_dev
, "can't map MIDI i/o space\n");
381 DPRINTF(("sv: IO ports: enhanced=0x%x, OPL=0x%x, MIDI=0x%x\n",
382 (int)sc
->sc_ioh
, (int)sc
->sc_oplioh
, (int)sc
->sc_midiioh
));
385 /* XXX Force allocation through the SGMAP. */
386 sc
->sc_dmatag
= alphabus_dma_get_tag(pa
->pa_dmat
, ALPHA_BUS_ISA
);
387 #elif defined(i386) && NISA > 0
389 * The SonicVibes DMA is broken and only works on 24-bit addresses.
390 * As long as bus_dmamem_alloc_range() is missing we use the ISA
393 sc
->sc_dmatag
= &isa_bus_dma_tag
;
395 sc
->sc_dmatag
= pa
->pa_dmat
;
398 pci_conf_write(pc
, pt
, SV_DMAA_CONFIG_OFF
, SV_DMAA_EXTENDED_ADDR
);
399 pci_conf_write(pc
, pt
, SV_DMAC_CONFIG_OFF
, 0);
401 /* Enable the device. */
402 csr
= pci_conf_read(pc
, pt
, PCI_COMMAND_STATUS_REG
);
403 pci_conf_write(pc
, pt
, PCI_COMMAND_STATUS_REG
,
404 csr
| PCI_COMMAND_MASTER_ENABLE
);
406 sv_write_indirect(sc
, SV_ANALOG_POWER_DOWN_CONTROL
, 0);
407 sv_write_indirect(sc
, SV_DIGITAL_POWER_DOWN_CONTROL
, 0);
409 /* initialize codec registers */
410 reg
= sv_read(sc
, SV_CODEC_CONTROL
);
412 sv_write(sc
, SV_CODEC_CONTROL
, reg
);
415 reg
= sv_read(sc
, SV_CODEC_CONTROL
);
416 reg
&= ~SV_CTL_RESET
;
417 reg
|= SV_CTL_INTA
| SV_CTL_ENHANCED
;
419 /* This write clears the reset */
420 sv_write(sc
, SV_CODEC_CONTROL
, reg
);
423 /* This write actually shoves the new values in */
424 sv_write(sc
, SV_CODEC_CONTROL
, reg
);
426 DPRINTF(("sv_attach: control=0x%x\n", sv_read(sc
, SV_CODEC_CONTROL
)));
428 /* Enable DMA interrupts */
429 reg
= sv_read(sc
, SV_CODEC_INTMASK
);
430 reg
&= ~(SV_INTMASK_DMAA
| SV_INTMASK_DMAC
);
431 reg
|= SV_INTMASK_UD
| SV_INTMASK_SINT
| SV_INTMASK_MIDI
;
432 sv_write(sc
, SV_CODEC_INTMASK
, reg
);
434 sv_read(sc
, SV_CODEC_STATUS
);
436 /* Map and establish the interrupt. */
437 if (pci_intr_map(pa
, &ih
)) {
438 aprint_error_dev(&sc
->sc_dev
, "couldn't map interrupt\n");
441 intrstr
= pci_intr_string(pc
, ih
);
442 sc
->sc_ih
= pci_intr_establish(pc
, ih
, IPL_AUDIO
, sv_intr
, sc
);
443 if (sc
->sc_ih
== NULL
) {
444 aprint_error_dev(&sc
->sc_dev
, "couldn't establish interrupt");
446 aprint_error(" at %s", intrstr
);
450 printf("%s: interrupting at %s\n", device_xname(&sc
->sc_dev
), intrstr
);
451 printf("%s: rev %d", device_xname(&sc
->sc_dev
),
452 sv_read_indirect(sc
, SV_REVISION_LEVEL
));
453 if (sv_read(sc
, SV_CODEC_CONTROL
) & SV_CTL_MD1
)
454 printf(", reverb SRAM present");
455 if (!(sv_read_indirect(sc
, SV_WAVETABLE_SOURCE_SELECT
) & SV_WSS_WT0
))
456 printf(", wavetable ROM present");
461 audio_attach_mi(&sv_hw_if
, sc
, &sc
->sc_dev
);
463 arg
.type
= AUDIODEV_TYPE_OPL
;
466 (void)config_found(&sc
->sc_dev
, &arg
, audioprint
);
468 sc
->sc_pa
= *pa
; /* for deferred setup */
469 config_defer(self
, sv_defer
);
474 sv_dumpregs(struct sv_softc
*sc
)
479 for (idx
= 0; idx
< 0x50; idx
+= 4)
480 printf ("%02x = %x\n", idx
,
481 pci_conf_read(pa
->pa_pc
, pa
->pa_tag
, idx
));
484 for (idx
= 0; idx
< 6; idx
++)
485 printf ("REG %02x = %02x\n", idx
, sv_read(sc
, idx
));
487 for (idx
= 0; idx
< 0x32; idx
++)
488 printf ("IREG %02x = %02x\n", idx
, sv_read_indirect(sc
, idx
));
490 for (idx
= 0; idx
< 0x10; idx
++)
491 printf ("DMA %02x = %02x\n", idx
,
492 bus_space_read_1(sc
->sc_iot
, sc
->sc_dmaa_ioh
, idx
));
503 intr
= sv_read(sc
, SV_CODEC_STATUS
);
504 DPRINTFN(5,("sv_intr: intr=0x%x\n", intr
));
506 if (!(intr
& (SV_INTSTATUS_DMAA
| SV_INTSTATUS_DMAC
)))
509 if (intr
& SV_INTSTATUS_DMAA
) {
511 sc
->sc_pintr(sc
->sc_parg
);
514 if (intr
& SV_INTSTATUS_DMAC
) {
516 sc
->sc_rintr(sc
->sc_rarg
);
523 sv_allocmem(struct sv_softc
*sc
, size_t size
, size_t align
,
524 int direction
, struct sv_dma
*p
)
529 error
= bus_dmamem_alloc(sc
->sc_dmatag
, p
->size
, align
, 0,
530 p
->segs
, ARRAY_SIZE(p
->segs
), &p
->nsegs
, BUS_DMA_NOWAIT
);
534 error
= bus_dmamem_map(sc
->sc_dmatag
, p
->segs
, p
->nsegs
, p
->size
,
535 &p
->addr
, BUS_DMA_NOWAIT
|BUS_DMA_COHERENT
);
539 error
= bus_dmamap_create(sc
->sc_dmatag
, p
->size
, 1, p
->size
,
540 0, BUS_DMA_NOWAIT
, &p
->map
);
544 error
= bus_dmamap_load(sc
->sc_dmatag
, p
->map
, p
->addr
, p
->size
, NULL
,
545 BUS_DMA_NOWAIT
| (direction
== AUMODE_RECORD
) ? BUS_DMA_READ
: BUS_DMA_WRITE
);
548 DPRINTF(("sv_allocmem: pa=%lx va=%lx pba=%lx\n",
549 (long)p
->segs
[0].ds_addr
, (long)KERNADDR(p
), (long)DMAADDR(p
)));
553 bus_dmamap_destroy(sc
->sc_dmatag
, p
->map
);
555 bus_dmamem_unmap(sc
->sc_dmatag
, p
->addr
, p
->size
);
557 bus_dmamem_free(sc
->sc_dmatag
, p
->segs
, p
->nsegs
);
562 sv_freemem(struct sv_softc
*sc
, struct sv_dma
*p
)
565 bus_dmamap_unload(sc
->sc_dmatag
, p
->map
);
566 bus_dmamap_destroy(sc
->sc_dmatag
, p
->map
);
567 bus_dmamem_unmap(sc
->sc_dmatag
, p
->addr
, p
->size
);
568 bus_dmamem_free(sc
->sc_dmatag
, p
->segs
, p
->nsegs
);
573 sv_open(void *addr
, int flags
)
578 DPRINTF(("sv_open\n"));
586 sv_query_encoding(void *addr
, struct audio_encoding
*fp
)
591 strcpy(fp
->name
, AudioEulinear
);
592 fp
->encoding
= AUDIO_ENCODING_ULINEAR
;
597 strcpy(fp
->name
, AudioEmulaw
);
598 fp
->encoding
= AUDIO_ENCODING_ULAW
;
600 fp
->flags
= AUDIO_ENCODINGFLAG_EMULATED
;
603 strcpy(fp
->name
, AudioEalaw
);
604 fp
->encoding
= AUDIO_ENCODING_ALAW
;
606 fp
->flags
= AUDIO_ENCODINGFLAG_EMULATED
;
609 strcpy(fp
->name
, AudioEslinear
);
610 fp
->encoding
= AUDIO_ENCODING_SLINEAR
;
612 fp
->flags
= AUDIO_ENCODINGFLAG_EMULATED
;
615 strcpy(fp
->name
, AudioEslinear_le
);
616 fp
->encoding
= AUDIO_ENCODING_SLINEAR_LE
;
621 strcpy(fp
->name
, AudioEulinear_le
);
622 fp
->encoding
= AUDIO_ENCODING_ULINEAR_LE
;
624 fp
->flags
= AUDIO_ENCODINGFLAG_EMULATED
;
627 strcpy(fp
->name
, AudioEslinear_be
);
628 fp
->encoding
= AUDIO_ENCODING_SLINEAR_BE
;
630 fp
->flags
= AUDIO_ENCODINGFLAG_EMULATED
;
633 strcpy(fp
->name
, AudioEulinear_be
);
634 fp
->encoding
= AUDIO_ENCODING_ULINEAR_BE
;
636 fp
->flags
= AUDIO_ENCODINGFLAG_EMULATED
;
644 sv_set_params(void *addr
, int setmode
, int usemode
, audio_params_t
*play
,
645 audio_params_t
*rec
, stream_filter_list_t
*pfil
, stream_filter_list_t
*rfil
)
654 * This device only has one clock, so make the sample rates match.
656 if (play
->sample_rate
!= rec
->sample_rate
&&
657 usemode
== (AUMODE_PLAY
| AUMODE_RECORD
)) {
658 if (setmode
== AUMODE_PLAY
) {
659 rec
->sample_rate
= play
->sample_rate
;
660 setmode
|= AUMODE_RECORD
;
661 } else if (setmode
== AUMODE_RECORD
) {
662 play
->sample_rate
= rec
->sample_rate
;
663 setmode
|= AUMODE_PLAY
;
668 if (setmode
& AUMODE_RECORD
) {
670 if (auconv_set_converter(sv_formats
, SV_NFORMATS
,
671 AUMODE_RECORD
, rec
, FALSE
, rfil
) < 0)
674 if (setmode
& AUMODE_PLAY
) {
676 if (auconv_set_converter(sv_formats
, SV_NFORMATS
,
677 AUMODE_PLAY
, play
, FALSE
, pfil
) < 0)
684 val
= p
->sample_rate
* 65536 / 48000;
686 * If the sample rate is exactly 48 kHz, the fraction would overflow the
687 * register, so we have to bias it. This causes a little clock drift.
688 * The drift is below normal crystal tolerance (.0001%), so although
689 * this seems a little silly, we can pretty much ignore it.
690 * (I tested the output speed with values of 1-20, just to be sure this
691 * register isn't *supposed* to have a bias. It isn't.)
697 sv_write_indirect(sc
, SV_PCM_SAMPLE_RATE_0
, val
& 0xff);
698 sv_write_indirect(sc
, SV_PCM_SAMPLE_RATE_1
, val
>> 8);
700 #define F_REF 24576000
702 #define ABS(x) (((x) < 0) ? (-x) : (x))
704 if (setmode
& AUMODE_RECORD
) {
705 /* The ADC reference frequency (f_out) is 512 * sample rate */
707 /* f_out is dervied from the 24.576MHz crystal by three values:
708 M & N & R. The equation is as follows:
710 f_out = (m + 2) * f_ref / ((n + 2) * (2 ^ a))
712 with the constraint that:
714 80 MHz < (m + 2) / (n + 2) * f_ref <= 150MHz
719 int a
, n
, m
, best_n
, best_m
, best_error
;
723 goal_f_out
= 512 * rec
->sample_rate
;
726 best_error
= 10000000;
727 for (a
= 0; a
< 8; a
++) {
728 if ((goal_f_out
* (1 << a
)) >= 80000000)
732 /* a != 8 because sample_rate >= 2000 */
734 for (n
= 33; n
> 2; n
--) {
735 m
= (goal_f_out
* n
* (1 << a
)) / F_REF
;
736 if ((m
> 257) || (m
< 3))
739 pll_sample
= (m
* F_REF
) / (n
* (1 << a
));
742 /* Threshold might be good here */
743 error
= pll_sample
- rec
->sample_rate
;
746 if (error
< best_error
) {
750 if (error
== 0) break;
757 sv_write_indirect(sc
, SV_ADC_PLL_M
, best_m
);
758 sv_write_indirect(sc
, SV_ADC_PLL_N
,
759 best_n
| (a
<< SV_PLL_R_SHIFT
));
766 sv_round_blocksize(void *addr
, int blk
, int mode
,
767 const audio_params_t
*param
)
770 return blk
& -32; /* keep good alignment */
774 sv_trigger_output(void *addr
, void *start
, void *end
, int blksize
,
775 void (*intr
)(void *), void *arg
, const audio_params_t
*param
)
782 DPRINTFN(1, ("sv_trigger_output: sc=%p start=%p end=%p blksize=%d "
783 "intr=%p(%p)\n", addr
, start
, end
, blksize
, intr
, arg
));
788 mode
= sv_read_indirect(sc
, SV_DMA_DATA_FORMAT
);
789 mode
&= ~(SV_DMAA_FORMAT16
| SV_DMAA_STEREO
);
790 if (param
->precision
== 16)
791 mode
|= SV_DMAA_FORMAT16
;
792 if (param
->channels
== 2)
793 mode
|= SV_DMAA_STEREO
;
794 sv_write_indirect(sc
, SV_DMA_DATA_FORMAT
, mode
);
796 for (p
= sc
->sc_dmas
; p
&& KERNADDR(p
) != start
; p
= p
->next
)
799 printf("sv_trigger_output: bad addr %p\n", start
);
803 dma_count
= ((char *)end
- (char *)start
) - 1;
804 DPRINTF(("sv_trigger_output: DMA start loop input addr=%x cc=%d\n",
805 (int)DMAADDR(p
), dma_count
));
807 bus_space_write_4(sc
->sc_iot
, sc
->sc_dmaa_ioh
, SV_DMA_ADDR0
,
809 bus_space_write_4(sc
->sc_iot
, sc
->sc_dmaa_ioh
, SV_DMA_COUNT0
,
811 bus_space_write_1(sc
->sc_iot
, sc
->sc_dmaa_ioh
, SV_DMA_MODE
,
812 DMA37MD_READ
| DMA37MD_LOOP
);
814 DPRINTF(("sv_trigger_output: current addr=%x\n",
815 bus_space_read_4(sc
->sc_iot
, sc
->sc_dmaa_ioh
, SV_DMA_ADDR0
)));
817 dma_count
= blksize
- 1;
819 sv_write_indirect(sc
, SV_DMAA_COUNT1
, dma_count
>> 8);
820 sv_write_indirect(sc
, SV_DMAA_COUNT0
, dma_count
& 0xFF);
822 mode
= sv_read_indirect(sc
, SV_PLAY_RECORD_ENABLE
);
823 sv_write_indirect(sc
, SV_PLAY_RECORD_ENABLE
, mode
| SV_PLAY_ENABLE
);
829 sv_trigger_input(void *addr
, void *start
, void *end
, int blksize
,
830 void (*intr
)(void *), void *arg
, const audio_params_t
*param
)
837 DPRINTFN(1, ("sv_trigger_input: sc=%p start=%p end=%p blksize=%d "
838 "intr=%p(%p)\n", addr
, start
, end
, blksize
, intr
, arg
));
843 mode
= sv_read_indirect(sc
, SV_DMA_DATA_FORMAT
);
844 mode
&= ~(SV_DMAC_FORMAT16
| SV_DMAC_STEREO
);
845 if (param
->precision
== 16)
846 mode
|= SV_DMAC_FORMAT16
;
847 if (param
->channels
== 2)
848 mode
|= SV_DMAC_STEREO
;
849 sv_write_indirect(sc
, SV_DMA_DATA_FORMAT
, mode
);
851 for (p
= sc
->sc_dmas
; p
&& KERNADDR(p
) != start
; p
= p
->next
)
854 printf("sv_trigger_input: bad addr %p\n", start
);
858 dma_count
= (((char *)end
- (char *)start
) >> 1) - 1;
859 DPRINTF(("sv_trigger_input: DMA start loop input addr=%x cc=%d\n",
860 (int)DMAADDR(p
), dma_count
));
862 bus_space_write_4(sc
->sc_iot
, sc
->sc_dmac_ioh
, SV_DMA_ADDR0
,
864 bus_space_write_4(sc
->sc_iot
, sc
->sc_dmac_ioh
, SV_DMA_COUNT0
,
866 bus_space_write_1(sc
->sc_iot
, sc
->sc_dmac_ioh
, SV_DMA_MODE
,
867 DMA37MD_WRITE
| DMA37MD_LOOP
);
869 DPRINTF(("sv_trigger_input: current addr=%x\n",
870 bus_space_read_4(sc
->sc_iot
, sc
->sc_dmac_ioh
, SV_DMA_ADDR0
)));
872 dma_count
= (blksize
>> 1) - 1;
874 sv_write_indirect(sc
, SV_DMAC_COUNT1
, dma_count
>> 8);
875 sv_write_indirect(sc
, SV_DMAC_COUNT0
, dma_count
& 0xFF);
877 mode
= sv_read_indirect(sc
, SV_PLAY_RECORD_ENABLE
);
878 sv_write_indirect(sc
, SV_PLAY_RECORD_ENABLE
, mode
| SV_RECORD_ENABLE
);
884 sv_halt_output(void *addr
)
889 DPRINTF(("sv: sv_halt_output\n"));
891 mode
= sv_read_indirect(sc
, SV_PLAY_RECORD_ENABLE
);
892 sv_write_indirect(sc
, SV_PLAY_RECORD_ENABLE
, mode
& ~SV_PLAY_ENABLE
);
899 sv_halt_input(void *addr
)
904 DPRINTF(("sv: sv_halt_input\n"));
906 mode
= sv_read_indirect(sc
, SV_PLAY_RECORD_ENABLE
);
907 sv_write_indirect(sc
, SV_PLAY_RECORD_ENABLE
, mode
& ~SV_RECORD_ENABLE
);
914 sv_getdev(void *addr
, struct audio_device
*retp
)
923 * Mixer related code is here
927 #define SV_INPUT_CLASS 0
928 #define SV_OUTPUT_CLASS 1
929 #define SV_RECORD_CLASS 2
931 #define SV_LAST_CLASS 2
933 static const char *mixer_classes
[] =
934 { AudioCinputs
, AudioCoutputs
, AudioCrecord
};
936 static const struct {
943 { SV_LEFT_AUX1_INPUT_CONTROL
, SV_RIGHT_AUX1_INPUT_CONTROL
, SV_AUX1_MASK
,
944 SV_INPUT_CLASS
, "aux1" },
945 { SV_LEFT_CD_INPUT_CONTROL
, SV_RIGHT_CD_INPUT_CONTROL
, SV_CD_MASK
,
946 SV_INPUT_CLASS
, AudioNcd
},
947 { SV_LEFT_LINE_IN_INPUT_CONTROL
, SV_RIGHT_LINE_IN_INPUT_CONTROL
, SV_LINE_IN_MASK
,
948 SV_INPUT_CLASS
, AudioNline
},
949 { SV_MIC_INPUT_CONTROL
, 0, SV_MIC_MASK
, SV_INPUT_CLASS
, AudioNmicrophone
},
950 { SV_LEFT_SYNTH_INPUT_CONTROL
, SV_RIGHT_SYNTH_INPUT_CONTROL
,
951 SV_SYNTH_MASK
, SV_INPUT_CLASS
, AudioNfmsynth
},
952 { SV_LEFT_AUX2_INPUT_CONTROL
, SV_RIGHT_AUX2_INPUT_CONTROL
, SV_AUX2_MASK
,
953 SV_INPUT_CLASS
, "aux2" },
954 { SV_LEFT_PCM_INPUT_CONTROL
, SV_RIGHT_PCM_INPUT_CONTROL
, SV_PCM_MASK
,
955 SV_INPUT_CLASS
, AudioNdac
},
956 { SV_LEFT_MIXER_OUTPUT_CONTROL
, SV_RIGHT_MIXER_OUTPUT_CONTROL
,
957 SV_MIXER_OUT_MASK
, SV_OUTPUT_CLASS
, AudioNmaster
}
961 static const struct {
964 } record_sources
[] = {
965 { SV_REC_CD
, AudioNcd
},
966 { SV_REC_DAC
, AudioNdac
},
967 { SV_REC_AUX2
, "aux2" },
968 { SV_REC_LINE
, AudioNline
},
969 { SV_REC_AUX1
, "aux1" },
970 { SV_REC_MIC
, AudioNmicrophone
},
971 { SV_REC_MIXER
, AudioNmixerout
}
975 #define SV_DEVICES_PER_PORT 2
976 #define SV_FIRST_MIXER (SV_LAST_CLASS + 1)
977 #define SV_LAST_MIXER (SV_DEVICES_PER_PORT * (ARRAY_SIZE(ports)) + SV_LAST_CLASS)
978 #define SV_RECORD_SOURCE (SV_LAST_MIXER + 1)
979 #define SV_MIC_BOOST (SV_LAST_MIXER + 2)
980 #define SV_RECORD_GAIN (SV_LAST_MIXER + 3)
981 #define SV_SRS_MODE (SV_LAST_MIXER + 4)
984 sv_query_devinfo(void *addr
, mixer_devinfo_t
*dip
)
989 if (dip
->index
<= SV_LAST_CLASS
) {
990 dip
->type
= AUDIO_MIXER_CLASS
;
991 dip
->mixer_class
= dip
->index
;
992 dip
->next
= dip
->prev
= AUDIO_MIXER_LAST
;
993 strcpy(dip
->label
.name
, mixer_classes
[dip
->index
]);
997 if (dip
->index
>= SV_FIRST_MIXER
&&
998 dip
->index
<= SV_LAST_MIXER
) {
1001 off
= dip
->index
- SV_FIRST_MIXER
;
1002 mute
= (off
% SV_DEVICES_PER_PORT
);
1003 idx
= off
/ SV_DEVICES_PER_PORT
;
1004 dip
->mixer_class
= ports
[idx
].class;
1005 strcpy(dip
->label
.name
, ports
[idx
].audio
);
1008 dip
->type
= AUDIO_MIXER_VALUE
;
1009 dip
->prev
= AUDIO_MIXER_LAST
;
1010 dip
->next
= dip
->index
+ 1;
1012 if (ports
[idx
].r_port
!= 0)
1013 dip
->un
.v
.num_channels
= 2;
1015 dip
->un
.v
.num_channels
= 1;
1017 strcpy(dip
->un
.v
.units
.name
, AudioNvolume
);
1019 dip
->type
= AUDIO_MIXER_ENUM
;
1020 dip
->prev
= dip
->index
- 1;
1021 dip
->next
= AUDIO_MIXER_LAST
;
1023 strcpy(dip
->label
.name
, AudioNmute
);
1024 dip
->un
.e
.num_mem
= 2;
1025 strcpy(dip
->un
.e
.member
[0].label
.name
, AudioNoff
);
1026 dip
->un
.e
.member
[0].ord
= 0;
1027 strcpy(dip
->un
.e
.member
[1].label
.name
, AudioNon
);
1028 dip
->un
.e
.member
[1].ord
= 1;
1034 switch (dip
->index
) {
1035 case SV_RECORD_SOURCE
:
1036 dip
->mixer_class
= SV_RECORD_CLASS
;
1037 dip
->prev
= AUDIO_MIXER_LAST
;
1038 dip
->next
= SV_RECORD_GAIN
;
1039 strcpy(dip
->label
.name
, AudioNsource
);
1040 dip
->type
= AUDIO_MIXER_ENUM
;
1042 dip
->un
.e
.num_mem
= ARRAY_SIZE(record_sources
);
1043 for (i
= 0; i
< ARRAY_SIZE(record_sources
); i
++) {
1044 strcpy(dip
->un
.e
.member
[i
].label
.name
,
1045 record_sources
[i
].name
);
1046 dip
->un
.e
.member
[i
].ord
= record_sources
[i
].idx
;
1050 case SV_RECORD_GAIN
:
1051 dip
->mixer_class
= SV_RECORD_CLASS
;
1052 dip
->prev
= SV_RECORD_SOURCE
;
1053 dip
->next
= AUDIO_MIXER_LAST
;
1054 strcpy(dip
->label
.name
, "gain");
1055 dip
->type
= AUDIO_MIXER_VALUE
;
1056 dip
->un
.v
.num_channels
= 1;
1057 strcpy(dip
->un
.v
.units
.name
, AudioNvolume
);
1061 dip
->mixer_class
= SV_RECORD_CLASS
;
1062 dip
->prev
= AUDIO_MIXER_LAST
;
1063 dip
->next
= AUDIO_MIXER_LAST
;
1064 strcpy(dip
->label
.name
, "micboost");
1068 dip
->mixer_class
= SV_OUTPUT_CLASS
;
1069 dip
->prev
= dip
->next
= AUDIO_MIXER_LAST
;
1070 strcpy(dip
->label
.name
, AudioNspatial
);
1073 dip
->type
= AUDIO_MIXER_ENUM
;
1074 dip
->un
.e
.num_mem
= 2;
1075 strcpy(dip
->un
.e
.member
[0].label
.name
, AudioNoff
);
1076 dip
->un
.e
.member
[0].ord
= 0;
1077 strcpy(dip
->un
.e
.member
[1].label
.name
, AudioNon
);
1078 dip
->un
.e
.member
[1].ord
= 1;
1086 sv_mixer_set_port(void *addr
, mixer_ctrl_t
*cp
)
1088 struct sv_softc
*sc
;
1093 if (cp
->dev
>= SV_FIRST_MIXER
&&
1094 cp
->dev
<= SV_LAST_MIXER
) {
1097 off
= cp
->dev
- SV_FIRST_MIXER
;
1098 mute
= (off
% SV_DEVICES_PER_PORT
);
1099 idx
= off
/ SV_DEVICES_PER_PORT
;
1102 if (cp
->type
!= AUDIO_MIXER_ENUM
)
1105 reg
= sv_read_indirect(sc
, ports
[idx
].l_port
);
1109 reg
&= ~SV_MUTE_BIT
;
1110 sv_write_indirect(sc
, ports
[idx
].l_port
, reg
);
1112 if (ports
[idx
].r_port
) {
1113 reg
= sv_read_indirect(sc
, ports
[idx
].r_port
);
1117 reg
&= ~SV_MUTE_BIT
;
1118 sv_write_indirect(sc
, ports
[idx
].r_port
, reg
);
1123 if (cp
->type
!= AUDIO_MIXER_VALUE
)
1126 if (cp
->un
.value
.num_channels
!= 1 &&
1127 cp
->un
.value
.num_channels
!= 2)
1130 if (ports
[idx
].r_port
== 0) {
1131 if (cp
->un
.value
.num_channels
!= 1)
1133 lval
= cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_MONO
];
1134 rval
= 0; /* shut up GCC */
1136 if (cp
->un
.value
.num_channels
!= 2)
1139 lval
= cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_LEFT
];
1140 rval
= cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_RIGHT
];
1144 reg
= sv_read_indirect(sc
, ports
[idx
].l_port
);
1145 reg
&= ~(ports
[idx
].mask
);
1146 lval
= (AUDIO_MAX_GAIN
- lval
) * ports
[idx
].mask
/
1149 sv_write_indirect(sc
, ports
[idx
].l_port
, reg
);
1151 if (ports
[idx
].r_port
!= 0) {
1152 reg
= sv_read_indirect(sc
, ports
[idx
].r_port
);
1153 reg
&= ~(ports
[idx
].mask
);
1155 rval
= (AUDIO_MAX_GAIN
- rval
) * ports
[idx
].mask
/
1159 sv_write_indirect(sc
, ports
[idx
].r_port
, reg
);
1162 sv_read_indirect(sc
, ports
[idx
].l_port
);
1170 case SV_RECORD_SOURCE
:
1171 if (cp
->type
!= AUDIO_MIXER_ENUM
)
1174 for (idx
= 0; idx
< ARRAY_SIZE(record_sources
); idx
++) {
1175 if (record_sources
[idx
].idx
== cp
->un
.ord
)
1182 reg
= sv_read_indirect(sc
, SV_LEFT_ADC_INPUT_CONTROL
);
1183 reg
&= ~SV_REC_SOURCE_MASK
;
1184 reg
|= (((cp
->un
.ord
) << SV_REC_SOURCE_SHIFT
) & SV_REC_SOURCE_MASK
);
1185 sv_write_indirect(sc
, SV_LEFT_ADC_INPUT_CONTROL
, reg
);
1187 reg
= sv_read_indirect(sc
, SV_RIGHT_ADC_INPUT_CONTROL
);
1188 reg
&= ~SV_REC_SOURCE_MASK
;
1189 reg
|= (((cp
->un
.ord
) << SV_REC_SOURCE_SHIFT
) & SV_REC_SOURCE_MASK
);
1190 sv_write_indirect(sc
, SV_RIGHT_ADC_INPUT_CONTROL
, reg
);
1193 case SV_RECORD_GAIN
:
1197 if (cp
->type
!= AUDIO_MIXER_VALUE
)
1200 if (cp
->un
.value
.num_channels
!= 1)
1203 val
= (cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_MONO
]
1204 * SV_REC_GAIN_MASK
) / AUDIO_MAX_GAIN
;
1206 reg
= sv_read_indirect(sc
, SV_LEFT_ADC_INPUT_CONTROL
);
1207 reg
&= ~SV_REC_GAIN_MASK
;
1209 sv_write_indirect(sc
, SV_LEFT_ADC_INPUT_CONTROL
, reg
);
1211 reg
= sv_read_indirect(sc
, SV_RIGHT_ADC_INPUT_CONTROL
);
1212 reg
&= ~SV_REC_GAIN_MASK
;
1214 sv_write_indirect(sc
, SV_RIGHT_ADC_INPUT_CONTROL
, reg
);
1219 if (cp
->type
!= AUDIO_MIXER_ENUM
)
1222 reg
= sv_read_indirect(sc
, SV_LEFT_ADC_INPUT_CONTROL
);
1224 reg
|= SV_MIC_BOOST_BIT
;
1226 reg
&= ~SV_MIC_BOOST_BIT
;
1229 sv_write_indirect(sc
, SV_LEFT_ADC_INPUT_CONTROL
, reg
);
1233 if (cp
->type
!= AUDIO_MIXER_ENUM
)
1236 reg
= sv_read_indirect(sc
, SV_SRS_SPACE_CONTROL
);
1238 reg
&= ~SV_SRS_SPACE_ONOFF
;
1240 reg
|= SV_SRS_SPACE_ONOFF
;
1243 sv_write_indirect(sc
, SV_SRS_SPACE_CONTROL
, reg
);
1251 sv_mixer_get_port(void *addr
, mixer_ctrl_t
*cp
)
1253 struct sv_softc
*sc
;
1258 if (cp
->dev
>= SV_FIRST_MIXER
&&
1259 cp
->dev
<= SV_LAST_MIXER
) {
1260 int off
= cp
->dev
- SV_FIRST_MIXER
;
1261 int mute
= (off
% 2);
1264 off
= cp
->dev
- SV_FIRST_MIXER
;
1268 if (cp
->type
!= AUDIO_MIXER_ENUM
)
1271 reg
= sv_read_indirect(sc
, ports
[idx
].l_port
);
1272 cp
->un
.ord
= ((reg
& SV_MUTE_BIT
) ? 1 : 0);
1274 if (cp
->type
!= AUDIO_MIXER_VALUE
)
1277 if (cp
->un
.value
.num_channels
!= 1 &&
1278 cp
->un
.value
.num_channels
!= 2)
1281 if ((ports
[idx
].r_port
== 0 &&
1282 cp
->un
.value
.num_channels
!= 1) ||
1283 (ports
[idx
].r_port
!= 0 &&
1284 cp
->un
.value
.num_channels
!= 2))
1287 reg
= sv_read_indirect(sc
, ports
[idx
].l_port
);
1288 reg
&= ports
[idx
].mask
;
1290 val
= AUDIO_MAX_GAIN
- ((reg
* AUDIO_MAX_GAIN
) / ports
[idx
].mask
);
1292 if (ports
[idx
].r_port
!= 0) {
1293 cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_LEFT
] = val
;
1295 reg
= sv_read_indirect(sc
, ports
[idx
].r_port
);
1296 reg
&= ports
[idx
].mask
;
1298 val
= AUDIO_MAX_GAIN
- ((reg
* AUDIO_MAX_GAIN
)
1300 cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_RIGHT
] = val
;
1302 cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_MONO
] = val
;
1309 case SV_RECORD_SOURCE
:
1310 if (cp
->type
!= AUDIO_MIXER_ENUM
)
1313 reg
= sv_read_indirect(sc
, SV_LEFT_ADC_INPUT_CONTROL
);
1314 cp
->un
.ord
= ((reg
& SV_REC_SOURCE_MASK
) >> SV_REC_SOURCE_SHIFT
);
1318 case SV_RECORD_GAIN
:
1319 if (cp
->type
!= AUDIO_MIXER_VALUE
)
1321 if (cp
->un
.value
.num_channels
!= 1)
1324 reg
= sv_read_indirect(sc
, SV_LEFT_ADC_INPUT_CONTROL
) & SV_REC_GAIN_MASK
;
1325 cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_MONO
] =
1326 (((unsigned int)reg
) * AUDIO_MAX_GAIN
) / SV_REC_GAIN_MASK
;
1331 if (cp
->type
!= AUDIO_MIXER_ENUM
)
1333 reg
= sv_read_indirect(sc
, SV_LEFT_ADC_INPUT_CONTROL
);
1334 cp
->un
.ord
= ((reg
& SV_MIC_BOOST_BIT
) ? 1 : 0);
1338 if (cp
->type
!= AUDIO_MIXER_ENUM
)
1340 reg
= sv_read_indirect(sc
, SV_SRS_SPACE_CONTROL
);
1341 cp
->un
.ord
= ((reg
& SV_SRS_SPACE_ONOFF
) ? 0 : 1);
1349 sv_init_mixer(struct sv_softc
*sc
)
1354 cp
.type
= AUDIO_MIXER_ENUM
;
1355 cp
.dev
= SV_SRS_MODE
;
1358 sv_mixer_set_port(sc
, &cp
);
1360 for (i
= 0; i
< ARRAY_SIZE(ports
); i
++) {
1361 if (!strcmp(ports
[i
].audio
, AudioNdac
)) {
1362 cp
.type
= AUDIO_MIXER_ENUM
;
1363 cp
.dev
= SV_FIRST_MIXER
+ i
* SV_DEVICES_PER_PORT
+ 1;
1365 sv_mixer_set_port(sc
, &cp
);
1372 sv_malloc(void *addr
, int direction
, size_t size
,
1373 struct malloc_type
*pool
, int flags
)
1375 struct sv_softc
*sc
;
1380 p
= malloc(sizeof(*p
), pool
, flags
);
1383 error
= sv_allocmem(sc
, size
, 16, direction
, p
);
1388 p
->next
= sc
->sc_dmas
;
1394 sv_free(void *addr
, void *ptr
, struct malloc_type
*pool
)
1396 struct sv_softc
*sc
;
1397 struct sv_dma
**pp
, *p
;
1400 for (pp
= &sc
->sc_dmas
; (p
= *pp
) != NULL
; pp
= &p
->next
) {
1401 if (KERNADDR(p
) == ptr
) {
1411 sv_round_buffersize(void *addr
, int direction
, size_t size
)
1418 sv_mappage(void *addr
, void *mem
, off_t off
, int prot
)
1420 struct sv_softc
*sc
;
1426 for (p
= sc
->sc_dmas
; p
&& KERNADDR(p
) != mem
; p
= p
->next
)
1430 return bus_dmamem_mmap(sc
->sc_dmatag
, p
->segs
, p
->nsegs
,
1431 off
, prot
, BUS_DMA_WAITOK
);
1435 sv_get_props(void *addr
)
1437 return AUDIO_PROP_MMAP
| AUDIO_PROP_INDEPENDENT
| AUDIO_PROP_FULLDUPLEX
;