1 /* $NetBSD: sbdsp.c,v 1.132 2009/09/01 21:47:30 jmcneill Exp $ */
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * Copyright (c) 1991-1993 Regents of the University of California.
34 * All rights reserved.
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. All advertising materials mentioning features or use of this software
45 * must display the following acknowledgement:
46 * This product includes software developed by the Computer Systems
47 * Engineering Group at Lawrence Berkeley Laboratory.
48 * 4. Neither the name of the University nor of the Laboratory may be used
49 * to endorse or promote products derived from this software without
50 * specific prior written permission.
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
67 * SoundBlaster Pro code provided by John Kohl, based on lots of
68 * information he gleaned from Steve Haehnichen <steve@vigra.com>'s
69 * SBlast driver for 386BSD and DOS driver code from Daniel Sachs
70 * <sachs@meibm15.cen.uiuc.edu>.
71 * Lots of rewrites by Lennart Augustsson <augustss@cs.chalmers.se>
72 * with information from SB "Hardware Programming Guide" and the
76 #include <sys/cdefs.h>
77 __KERNEL_RCSID(0, "$NetBSD: sbdsp.c,v 1.132 2009/09/01 21:47:30 jmcneill Exp $");
82 #include <sys/param.h>
83 #include <sys/systm.h>
84 #include <sys/kernel.h>
85 #include <sys/errno.h>
86 #include <sys/ioctl.h>
87 #include <sys/syslog.h>
88 #include <sys/device.h>
96 #include <sys/audioio.h>
97 #include <dev/audio_if.h>
98 #include <dev/midi_if.h>
99 #include <dev/mulaw.h>
100 #include <dev/auconv.h>
102 #include <dev/isa/isavar.h>
103 #include <dev/isa/isadmavar.h>
105 #include <dev/isa/sbreg.h>
106 #include <dev/isa/sbdspvar.h>
110 #define DPRINTF(x) if (sbdspdebug) printf x
111 #define DPRINTFN(n,x) if (sbdspdebug >= (n)) printf x
115 #define DPRINTFN(n,x)
119 #define SBDSP_NPOLL 3000
129 * Time constant routines follow. See SBK, section 12.
130 * Although they don't come out and say it (in the docs),
131 * the card clearly uses a 1MHz countdown timer, as the
132 * low-speed formula (p. 12-4) is:
133 * tc = 256 - 10^6 / sr
134 * In high-speed mode, the constant is the upper byte of a 16-bit counter,
135 * and a 256MHz clock is used:
136 * tc = 65536 - 256 * 10^ 6 / sr
137 * Since we can only use the upper byte of the HS TC, the two formulae
138 * are equivalent. (Why didn't they say so?) E.g.,
139 * (65536 - 256 * 10 ^ 6 / x) >> 8 = 256 - 10^6 / x
141 * The crossover point (from low- to high-speed modes) is different
142 * for the SBPRO and SB20. The table on p. 12-5 gives the following data:
146 * input ls min 4 kHz 4 kHz
147 * input ls max 23 kHz 13 kHz
148 * input hs max 44.1 kHz 15 kHz
149 * output ls min 4 kHz 4 kHz
150 * output ls max 23 kHz 23 kHz
151 * output hs max 44.1 kHz 44.1 kHz
153 /* XXX Should we round the tc?
154 #define SB_RATE_TO_TC(x) (((65536 - 256 * 1000000 / (x)) + 128) >> 8)
156 #define SB_RATE_TO_TC(x) (256 - 1000000 / (x))
157 #define SB_TC_TO_RATE(tc) (1000000 / (256 - (tc)))
163 u_short lowrate
, highrate
;
168 static struct sbmode sbpmodes
[] = {
169 { SB_1
, 1, 8, 4000,22727,SB_DSP_WDMA
,SB_DSP_HALT
,SB_DSP_CONT
, 0, },
170 { SB_20
, 1, 8, 4000,22727,SB_DSP_WDMA_LOOP
,SB_DSP_HALT
,SB_DSP_CONT
, 0, },
171 { SB_2x
, 1, 8,22727,45454,SB_DSP_HS_OUTPUT
,SB_DSP_HALT
,SB_DSP_CONT
, 0, },
172 { SB_2x
, 1, 8, 4000,22727,SB_DSP_WDMA_LOOP
,SB_DSP_HALT
,SB_DSP_CONT
, 0, },
173 { SB_PRO
, 1, 8,22727,45454,SB_DSP_HS_OUTPUT
,SB_DSP_HALT
,SB_DSP_CONT
, 0, },
174 { SB_PRO
, 1, 8, 4000,22727,SB_DSP_WDMA_LOOP
,SB_DSP_HALT
,SB_DSP_CONT
, 0, },
175 { SB_PRO
, 2, 8,11025,22727,SB_DSP_HS_OUTPUT
,SB_DSP_HALT
,SB_DSP_CONT
, 0, },
176 /* Yes, we write the record mode to set 16-bit playback mode. weird, huh? */
177 { SB_JAZZ
,1, 8,22727,45454,SB_DSP_HS_OUTPUT
,SB_DSP_HALT
,SB_DSP_CONT
,SB_DSP_RECORD_MONO
},
178 { SB_JAZZ
,1, 8, 4000,22727,SB_DSP_WDMA_LOOP
,SB_DSP_HALT
,SB_DSP_CONT
,SB_DSP_RECORD_MONO
},
179 { SB_JAZZ
,2, 8,11025,22727,SB_DSP_HS_OUTPUT
,SB_DSP_HALT
,SB_DSP_CONT
,SB_DSP_RECORD_STEREO
},
180 { SB_JAZZ
,1,16,22727,45454,SB_DSP_HS_OUTPUT
,SB_DSP_HALT
,SB_DSP_CONT
,JAZZ16_RECORD_MONO
},
181 { SB_JAZZ
,1,16, 4000,22727,SB_DSP_WDMA_LOOP
,SB_DSP_HALT
,SB_DSP_CONT
,JAZZ16_RECORD_MONO
},
182 { SB_JAZZ
,2,16,11025,22727,SB_DSP_HS_OUTPUT
,SB_DSP_HALT
,SB_DSP_CONT
,JAZZ16_RECORD_STEREO
},
183 { SB_16
, 1, 8, 5000,49000,SB_DSP16_WDMA_8
,SB_DSP_HALT
,SB_DSP_CONT
, 0, },
184 { SB_16
, 2, 8, 5000,49000,SB_DSP16_WDMA_8
,SB_DSP_HALT
,SB_DSP_CONT
, 0, },
185 #define PLAY16 15 /* must be the index of the next entry in the table */
186 { SB_16
, 1,16, 5000,49000,SB_DSP16_WDMA_16
,SB_DSP16_HALT
,SB_DSP16_CONT
, 0, },
187 { SB_16
, 2,16, 5000,49000,SB_DSP16_WDMA_16
,SB_DSP16_HALT
,SB_DSP16_CONT
, 0, },
190 static struct sbmode sbrmodes
[] = {
191 { SB_1
, 1, 8, 4000,12987,SB_DSP_RDMA
,SB_DSP_HALT
,SB_DSP_CONT
, 0, },
192 { SB_20
, 1, 8, 4000,12987,SB_DSP_RDMA_LOOP
,SB_DSP_HALT
,SB_DSP_CONT
, 0, },
193 { SB_2x
, 1, 8,12987,14925,SB_DSP_HS_INPUT
,SB_DSP_HALT
,SB_DSP_CONT
, 0, },
194 { SB_2x
, 1, 8, 4000,12987,SB_DSP_RDMA_LOOP
,SB_DSP_HALT
,SB_DSP_CONT
, 0, },
195 { SB_PRO
, 1, 8,22727,45454,SB_DSP_HS_INPUT
,SB_DSP_HALT
,SB_DSP_CONT
,SB_DSP_RECORD_MONO
},
196 { SB_PRO
, 1, 8, 4000,22727,SB_DSP_RDMA_LOOP
,SB_DSP_HALT
,SB_DSP_CONT
,SB_DSP_RECORD_MONO
},
197 { SB_PRO
, 2, 8,11025,22727,SB_DSP_HS_INPUT
,SB_DSP_HALT
,SB_DSP_CONT
,SB_DSP_RECORD_STEREO
},
198 { SB_JAZZ
,1, 8,22727,45454,SB_DSP_HS_INPUT
,SB_DSP_HALT
,SB_DSP_CONT
,SB_DSP_RECORD_MONO
},
199 { SB_JAZZ
,1, 8, 4000,22727,SB_DSP_RDMA_LOOP
,SB_DSP_HALT
,SB_DSP_CONT
,SB_DSP_RECORD_MONO
},
200 { SB_JAZZ
,2, 8,11025,22727,SB_DSP_HS_INPUT
,SB_DSP_HALT
,SB_DSP_CONT
,SB_DSP_RECORD_STEREO
},
201 { SB_JAZZ
,1,16,22727,45454,SB_DSP_HS_INPUT
,SB_DSP_HALT
,SB_DSP_CONT
,JAZZ16_RECORD_MONO
},
202 { SB_JAZZ
,1,16, 4000,22727,SB_DSP_RDMA_LOOP
,SB_DSP_HALT
,SB_DSP_CONT
,JAZZ16_RECORD_MONO
},
203 { SB_JAZZ
,2,16,11025,22727,SB_DSP_HS_INPUT
,SB_DSP_HALT
,SB_DSP_CONT
,JAZZ16_RECORD_STEREO
},
204 { SB_16
, 1, 8, 5000,49000,SB_DSP16_RDMA_8
,SB_DSP_HALT
,SB_DSP_CONT
, 0, },
205 { SB_16
, 2, 8, 5000,49000,SB_DSP16_RDMA_8
,SB_DSP_HALT
,SB_DSP_CONT
, 0, },
206 { SB_16
, 1,16, 5000,49000,SB_DSP16_RDMA_16
,SB_DSP16_HALT
,SB_DSP16_CONT
, 0, },
207 { SB_16
, 2,16, 5000,49000,SB_DSP16_RDMA_16
,SB_DSP16_HALT
,SB_DSP16_CONT
, 0, },
211 void sbversion(struct sbdsp_softc
*);
212 void sbdsp_jazz16_probe(struct sbdsp_softc
*);
213 void sbdsp_set_mixer_gain(struct sbdsp_softc
*, int);
214 void sbdsp_pause(struct sbdsp_softc
*);
215 int sbdsp_set_timeconst(struct sbdsp_softc
*, int);
216 int sbdsp16_set_rate(struct sbdsp_softc
*, int, int);
217 int sbdsp_set_in_ports(struct sbdsp_softc
*, int);
218 void sbdsp_set_ifilter(void *, int);
219 int sbdsp_get_ifilter(void *);
221 int sbdsp_block_output(void *);
222 int sbdsp_block_input(void *);
223 static int sbdsp_adjust(int, int);
225 int sbdsp_midi_intr(void *);
227 static bool sbdsp_resume(device_t
, pmf_qual_t
);
230 void sb_printsc(struct sbdsp_softc
*);
233 sb_printsc(struct sbdsp_softc
*sc
)
237 printf("open %d DMA chan %d/%d %d/%d iobase 0x%x irq %d\n",
238 (int)sc
->sc_open
, sc
->sc_i
.run
, sc
->sc_o
.run
,
239 sc
->sc_drq8
, sc
->sc_drq16
,
240 sc
->sc_iobase
, sc
->sc_irq
);
241 printf("irate %d itc %x orate %d otc %x\n",
242 sc
->sc_i
.rate
, sc
->sc_i
.tc
,
243 sc
->sc_o
.rate
, sc
->sc_o
.tc
);
244 printf("spkron %u nintr %lu\n",
245 sc
->spkr_state
, sc
->sc_interrupts
);
246 printf("intr8 %p intr16 %p\n",
247 sc
->sc_intr8
, sc
->sc_intr16
);
249 for (i
= 0; i
< SB_NDEVS
; i
++)
250 printf(" %u,%u", sc
->gain
[i
][SB_LEFT
], sc
->gain
[i
][SB_RIGHT
]);
253 #endif /* AUDIO_DEBUG */
256 * Probe / attach routines.
260 * Probe for the soundblaster hardware.
263 sbdsp_probe(struct sbdsp_softc
*sc
, cfdata_t match
)
266 if (sbdsp_reset(sc
) < 0) {
267 DPRINTF(("sbdsp: couldn't reset card\n"));
270 /* if flags set, go and probe the jazz16 stuff */
271 if (match
->cf_flags
& 1)
272 sbdsp_jazz16_probe(sc
);
275 if (sc
->sc_model
== SB_UNK
) {
276 /* Unknown SB model found. */
277 DPRINTF(("sbdsp: unknown SB model found\n"));
284 * Try add-on stuff for Jazz16.
287 sbdsp_jazz16_probe(struct sbdsp_softc
*sc
)
289 static u_char jazz16_irq_conf
[16] = {
294 static u_char jazz16_drq_conf
[8] = {
299 bus_space_handle_t ioh
;
304 DPRINTF(("jazz16 probe\n"));
306 if (bus_space_map(iot
, JAZZ16_CONFIG_PORT
, 1, 0, &ioh
)) {
307 DPRINTF(("bus map failed\n"));
311 if (jazz16_drq_conf
[sc
->sc_drq8
] == (u_char
)-1 ||
312 jazz16_irq_conf
[sc
->sc_irq
] == (u_char
)-1) {
313 DPRINTF(("drq/irq check failed\n"));
314 goto done
; /* give up, we can't do it. */
317 bus_space_write_1(iot
, ioh
, 0, JAZZ16_WAKEUP
);
318 delay(10000); /* delay 10 ms */
319 bus_space_write_1(iot
, ioh
, 0, JAZZ16_SETBASE
);
320 bus_space_write_1(iot
, ioh
, 0, sc
->sc_iobase
& 0x70);
322 if (sbdsp_reset(sc
) < 0) {
323 DPRINTF(("sbdsp_reset check failed\n"));
324 goto done
; /* XXX? what else could we do? */
327 if (sbdsp_wdsp(sc
, JAZZ16_READ_VER
)) {
328 DPRINTF(("read16 setup failed\n"));
332 if (sbdsp_rdsp(sc
) != JAZZ16_VER_JAZZ
) {
333 DPRINTF(("read16 failed\n"));
337 /* XXX set both 8 & 16-bit drq to same channel, it works fine. */
338 sc
->sc_drq16
= sc
->sc_drq8
;
339 if (sbdsp_wdsp(sc
, JAZZ16_SET_DMAINTR
) ||
340 (sc
->sc_drq16
>= 0 &&
341 sbdsp_wdsp(sc
, (jazz16_drq_conf
[sc
->sc_drq16
] << 4) |
342 jazz16_drq_conf
[sc
->sc_drq8
])) ||
343 sbdsp_wdsp(sc
, jazz16_irq_conf
[sc
->sc_irq
])) {
344 DPRINTF(("sbdsp: can't write jazz16 probe stuff\n"));
346 DPRINTF(("jazz16 detected!\n"));
347 sc
->sc_model
= SB_JAZZ
;
348 sc
->sc_mixer_model
= SBM_CT1345
; /* XXX really? */
352 bus_space_unmap(iot
, ioh
, 1);
356 * Attach hardware to driver, attach hardware driver to audio
357 * pseudo-device driver .
360 sbdsp_attach(struct sbdsp_softc
*sc
)
365 sbdsp_set_in_ports(sc
, 1 << SB_MIC_VOL
);
367 if (sc
->sc_mixer_model
!= SBM_NONE
) {
368 /* Reset the mixer.*/
369 sbdsp_mix_write(sc
, SBP_MIX_RESET
, SBP_MIX_RESET
);
370 /* And set our own default values */
371 for (i
= 0; i
< SB_NDEVS
; i
++) {
379 v
= SB_ADJUST_GAIN(sc
, AUDIO_MAX_GAIN
/ 2);
383 case SB_LINE_IN_MUTE
:
384 case SB_MIDI_IN_MUTE
:
390 case SB_MIC_OUT_MUTE
:
391 case SB_LINE_OUT_MUTE
:
395 v
= SB_ADJUST_GAIN(sc
, AUDIO_MAX_GAIN
/ 2);
398 sc
->gain
[i
][SB_LEFT
] = sc
->gain
[i
][SB_RIGHT
] = v
;
399 sbdsp_set_mixer_gain(sc
, i
);
401 sc
->in_filter
= 0; /* no filters turned on, please */
405 aprint_normal(": dsp v%d.%02d%s\n",
406 SBVER_MAJOR(sc
->sc_version
), SBVER_MINOR(sc
->sc_version
),
407 sc
->sc_model
== SB_JAZZ
? ": <Jazz16>" : "");
409 sc
->sc_fullduplex
= ISSB16CLASS(sc
) &&
410 sc
->sc_drq8
!= -1 && sc
->sc_drq16
!= -1 &&
411 sc
->sc_drq8
!= sc
->sc_drq16
;
413 if (sc
->sc_drq8
!= -1) {
414 sc
->sc_drq8_maxsize
= isa_dmamaxsize(sc
->sc_ic
,
416 error
= isa_dmamap_create(sc
->sc_ic
, sc
->sc_drq8
,
417 sc
->sc_drq8_maxsize
, BUS_DMA_NOWAIT
|BUS_DMA_ALLOCNOW
);
419 aprint_error_dev(sc
->sc_dev
,
420 "can't create map for drq %d\n", sc
->sc_drq8
);
425 if (sc
->sc_drq16
!= -1 && sc
->sc_drq16
!= sc
->sc_drq8
) {
426 sc
->sc_drq16_maxsize
= isa_dmamaxsize(sc
->sc_ic
,
428 error
= isa_dmamap_create(sc
->sc_ic
, sc
->sc_drq16
,
429 sc
->sc_drq16_maxsize
, BUS_DMA_NOWAIT
|BUS_DMA_ALLOCNOW
);
431 aprint_error_dev(sc
->sc_dev
,
432 "can't create map for drq %d\n", sc
->sc_drq16
);
433 isa_dmamap_destroy(sc
->sc_ic
, sc
->sc_drq8
);
438 if (!pmf_device_register(sc
->sc_dev
, NULL
, sbdsp_resume
))
439 aprint_error_dev(sc
->sc_dev
, "couldn't establish power handler\n");
443 sbdsp_resume(device_t dv
, pmf_qual_t qual
)
445 struct sbdsp_softc
*sc
= device_private(dv
);
447 /* Reset the mixer. */
448 sbdsp_mix_write(sc
, SBP_MIX_RESET
, SBP_MIX_RESET
);
454 sbdsp_mix_write(struct sbdsp_softc
*sc
, int mixerport
, int val
)
457 bus_space_handle_t ioh
;
463 bus_space_write_1(iot
, ioh
, SBP_MIXER_ADDR
, mixerport
);
465 bus_space_write_1(iot
, ioh
, SBP_MIXER_DATA
, val
);
471 sbdsp_mix_read(struct sbdsp_softc
*sc
, int mixerport
)
474 bus_space_handle_t ioh
;
481 bus_space_write_1(iot
, ioh
, SBP_MIXER_ADDR
, mixerport
);
483 val
= bus_space_read_1(iot
, ioh
, SBP_MIXER_DATA
);
490 * Various routines to interface to higher level audio driver
494 sbdsp_query_encoding(void *addr
, struct audio_encoding
*fp
)
496 struct sbdsp_softc
*sc
;
500 emul
= ISSB16CLASS(sc
) ? 0 : AUDIO_ENCODINGFLAG_EMULATED
;
504 strcpy(fp
->name
, AudioEulinear
);
505 fp
->encoding
= AUDIO_ENCODING_ULINEAR
;
510 strcpy(fp
->name
, AudioEmulaw
);
511 fp
->encoding
= AUDIO_ENCODING_ULAW
;
513 fp
->flags
= AUDIO_ENCODINGFLAG_EMULATED
;
516 strcpy(fp
->name
, AudioEalaw
);
517 fp
->encoding
= AUDIO_ENCODING_ALAW
;
519 fp
->flags
= AUDIO_ENCODINGFLAG_EMULATED
;
522 strcpy(fp
->name
, AudioEslinear
);
523 fp
->encoding
= AUDIO_ENCODING_SLINEAR
;
528 if (!ISSB16CLASS(sc
) && sc
->sc_model
!= SB_JAZZ
)
533 strcpy(fp
->name
, AudioEslinear_le
);
534 fp
->encoding
= AUDIO_ENCODING_SLINEAR_LE
;
539 strcpy(fp
->name
, AudioEulinear_le
);
540 fp
->encoding
= AUDIO_ENCODING_ULINEAR_LE
;
545 strcpy(fp
->name
, AudioEslinear_be
);
546 fp
->encoding
= AUDIO_ENCODING_SLINEAR_BE
;
548 fp
->flags
= AUDIO_ENCODINGFLAG_EMULATED
;
551 strcpy(fp
->name
, AudioEulinear_be
);
552 fp
->encoding
= AUDIO_ENCODING_ULINEAR_BE
;
554 fp
->flags
= AUDIO_ENCODINGFLAG_EMULATED
;
565 int setmode
, int usemode
,
566 audio_params_t
*play
, audio_params_t
*rec
,
567 stream_filter_list_t
*pfil
, stream_filter_list_t
*rfil
)
569 struct sbdsp_softc
*sc
;
571 u_int rate
, tc
, bmode
;
572 stream_filter_factory_t
*swcode
;
575 struct audio_params
*p
;
577 stream_filter_list_t
*fil
;
581 if (sc
->sc_open
== SB_OPEN_MIDI
)
584 /* Later models work like SB16. */
585 model
= min(sc
->sc_model
, SB_16
);
588 * Prior to the SB16, we have only one clock, so make the sample
591 if (!ISSB16CLASS(sc
) &&
592 play
->sample_rate
!= rec
->sample_rate
&&
593 usemode
== (AUMODE_PLAY
| AUMODE_RECORD
)) {
594 if (setmode
== AUMODE_PLAY
) {
595 rec
->sample_rate
= play
->sample_rate
;
596 setmode
|= AUMODE_RECORD
;
597 } else if (setmode
== AUMODE_RECORD
) {
598 play
->sample_rate
= rec
->sample_rate
;
599 setmode
|= AUMODE_PLAY
;
604 /* Set first record info, then play info */
605 for (mode
= AUMODE_RECORD
; mode
!= -1;
606 mode
= mode
== AUMODE_RECORD
? AUMODE_PLAY
: -1) {
607 if ((setmode
& mode
) == 0)
610 p
= mode
== AUMODE_PLAY
? play
: rec
;
611 /* Locate proper commands */
612 for (m
= mode
== AUMODE_PLAY
? sbpmodes
: sbrmodes
;
613 m
->model
!= -1; m
++) {
614 if (model
== m
->model
&&
615 p
->channels
== m
->channels
&&
616 p
->precision
== m
->precision
&&
617 p
->sample_rate
>= m
->lowrate
&&
618 p
->sample_rate
<= m
->highrate
)
623 rate
= p
->sample_rate
;
625 fil
= mode
== AUMODE_PLAY
? pfil
: rfil
;
629 if (model
== SB_16
) {
630 switch (p
->encoding
) {
631 case AUDIO_ENCODING_SLINEAR_BE
:
632 if (p
->precision
== 16) {
633 hw
.encoding
= AUDIO_ENCODING_SLINEAR_LE
;
637 case AUDIO_ENCODING_SLINEAR_LE
:
638 bmode
= SB_BMODE_SIGNED
;
641 case AUDIO_ENCODING_ULINEAR_BE
:
642 if (p
->precision
== 16) {
643 hw
.encoding
= AUDIO_ENCODING_ULINEAR_LE
;
647 case AUDIO_ENCODING_ULINEAR_LE
:
648 bmode
= SB_BMODE_UNSIGNED
;
651 case AUDIO_ENCODING_ULAW
:
652 hw
.encoding
= AUDIO_ENCODING_ULINEAR_LE
;
653 if (mode
== AUMODE_PLAY
) {
654 hw
.precision
= hw
.validbits
= 16;
655 swcode
= mulaw_to_linear16
;
656 m
= &sbpmodes
[PLAY16
];
658 swcode
= linear8_to_mulaw
;
659 bmode
= SB_BMODE_UNSIGNED
;
662 case AUDIO_ENCODING_ALAW
:
663 hw
.encoding
= AUDIO_ENCODING_ULINEAR_LE
;
664 if (mode
== AUMODE_PLAY
) {
665 hw
.precision
= hw
.validbits
= 16;
666 swcode
= alaw_to_linear16
;
667 m
= &sbpmodes
[PLAY16
];
669 swcode
= linear8_to_alaw
;
670 bmode
= SB_BMODE_UNSIGNED
;
675 if (p
->channels
== 2)
676 bmode
|= SB_BMODE_STEREO
;
677 } else if (m
->model
== SB_JAZZ
&& m
->precision
== 16) {
678 switch (p
->encoding
) {
679 case AUDIO_ENCODING_SLINEAR_LE
:
681 case AUDIO_ENCODING_ULINEAR_LE
:
682 hw
.encoding
= AUDIO_ENCODING_SLINEAR_LE
;
683 swcode
= change_sign16
;
685 case AUDIO_ENCODING_SLINEAR_BE
:
686 hw
.encoding
= AUDIO_ENCODING_SLINEAR_LE
;
689 case AUDIO_ENCODING_ULINEAR_BE
:
690 hw
.encoding
= AUDIO_ENCODING_SLINEAR_LE
;
691 swcode
= swap_bytes_change_sign16
;
693 case AUDIO_ENCODING_ULAW
:
694 hw
.encoding
= AUDIO_ENCODING_ULINEAR_LE
;
695 swcode
= mode
== AUMODE_PLAY
?
696 mulaw_to_linear8
: linear8_to_mulaw
;
698 case AUDIO_ENCODING_ALAW
:
699 hw
.encoding
= AUDIO_ENCODING_ULINEAR_LE
;
700 swcode
= mode
== AUMODE_PLAY
?
701 alaw_to_linear8
: linear8_to_alaw
;
706 tc
= SB_RATE_TO_TC(p
->sample_rate
* p
->channels
);
707 p
->sample_rate
= SB_TC_TO_RATE(tc
) / p
->channels
;
708 hw
.sample_rate
= p
->sample_rate
;
710 switch (p
->encoding
) {
711 case AUDIO_ENCODING_SLINEAR_BE
:
712 case AUDIO_ENCODING_SLINEAR_LE
:
713 hw
.encoding
= AUDIO_ENCODING_ULINEAR_LE
;
714 swcode
= change_sign8
;
716 case AUDIO_ENCODING_ULINEAR_BE
:
717 case AUDIO_ENCODING_ULINEAR_LE
:
719 case AUDIO_ENCODING_ULAW
:
720 hw
.encoding
= AUDIO_ENCODING_ULINEAR_LE
;
721 swcode
= mode
== AUMODE_PLAY
?
722 mulaw_to_linear8
: linear8_to_mulaw
;
724 case AUDIO_ENCODING_ALAW
:
725 hw
.encoding
= AUDIO_ENCODING_ULINEAR_LE
;
726 swcode
= mode
== AUMODE_PLAY
?
727 alaw_to_linear8
: linear8_to_alaw
;
732 tc
= SB_RATE_TO_TC(p
->sample_rate
* p
->channels
);
733 p
->sample_rate
= SB_TC_TO_RATE(tc
) / p
->channels
;
734 hw
.sample_rate
= p
->sample_rate
;
737 chan
= m
->precision
== 16 ? sc
->sc_drq16
: sc
->sc_drq8
;
738 if (mode
== AUMODE_PLAY
) {
739 sc
->sc_o
.rate
= rate
;
742 sc
->sc_o
.bmode
= bmode
;
743 sc
->sc_o
.dmachan
= chan
;
745 sc
->sc_i
.rate
= rate
;
748 sc
->sc_i
.bmode
= bmode
;
749 sc
->sc_i
.dmachan
= chan
;
753 fil
->append(fil
, swcode
, &hw
);
754 DPRINTF(("sbdsp_set_params: model=%d, mode=%d, rate=%u, "
755 "prec=%d, chan=%d, enc=%d -> tc=%02x, cmd=%02x, "
756 "bmode=%02x, cmdchan=%02x\n", sc
->sc_model
, mode
,
757 p
->sample_rate
, p
->precision
, p
->channels
,
758 p
->encoding
, tc
, m
->cmd
, bmode
, m
->cmdchan
));
762 if (sc
->sc_fullduplex
&&
763 usemode
== (AUMODE_PLAY
| AUMODE_RECORD
) &&
764 sc
->sc_i
.dmachan
== sc
->sc_o
.dmachan
) {
765 DPRINTF(("sbdsp_set_params: fd=%d, usemode=%d, idma=%d, "
766 "odma=%d\n", sc
->sc_fullduplex
, usemode
,
767 sc
->sc_i
.dmachan
, sc
->sc_o
.dmachan
));
768 if (sc
->sc_o
.dmachan
== sc
->sc_drq8
) {
769 /* Use 16 bit DMA for playing by expanding the samples. */
770 hw
.precision
= hw
.validbits
= 16;
771 pfil
->append(pfil
, linear8_to_linear16
, &hw
);
772 sc
->sc_o
.modep
= &sbpmodes
[PLAY16
];
773 sc
->sc_o
.dmachan
= sc
->sc_drq16
;
778 DPRINTF(("sbdsp_set_params ichan=%d, ochan=%d\n",
779 sc
->sc_i
.dmachan
, sc
->sc_o
.dmachan
));
785 sbdsp_set_ifilter(void *addr
, int which
)
787 struct sbdsp_softc
*sc
;
791 mixval
= sbdsp_mix_read(sc
, SBP_INFILTER
) & ~SBP_IFILTER_MASK
;
794 mixval
|= SBP_FILTER_OFF
;
797 mixval
|= SBP_FILTER_ON
| SBP_IFILTER_HIGH
;
800 mixval
|= SBP_FILTER_ON
| SBP_IFILTER_LOW
;
805 sc
->in_filter
= mixval
& SBP_IFILTER_MASK
;
806 sbdsp_mix_write(sc
, SBP_INFILTER
, mixval
);
810 sbdsp_get_ifilter(void *addr
)
812 struct sbdsp_softc
*sc
;
816 sbdsp_mix_read(sc
, SBP_INFILTER
) & SBP_IFILTER_MASK
;
817 switch (sc
->in_filter
) {
818 case SBP_FILTER_ON
|SBP_IFILTER_HIGH
:
820 case SBP_FILTER_ON
|SBP_IFILTER_LOW
:
828 sbdsp_set_in_ports(struct sbdsp_softc
*sc
, int mask
)
833 if (sc
->sc_open
== SB_OPEN_MIDI
)
836 DPRINTF(("sbdsp_set_in_ports: model=%d, mask=%x\n",
837 sc
->sc_mixer_model
, mask
));
839 switch(sc
->sc_mixer_model
) {
843 if (mask
!= (1 << SB_MIC_VOL
))
848 case 1 << SB_MIC_VOL
:
849 sbport
= SBP_FROM_MIC
;
851 case 1 << SB_LINE_IN_VOL
:
852 sbport
= SBP_FROM_LINE
;
855 sbport
= SBP_FROM_CD
;
860 sbdsp_mix_write(sc
, SBP_RECORD_SOURCE
, sbport
| sc
->in_filter
);
864 if (mask
& ~((1<<SB_MIDI_VOL
) | (1<<SB_LINE_IN_VOL
) |
865 (1<<SB_CD_VOL
) | (1<<SB_MIC_VOL
)))
868 if (mask
& (1<<SB_MIDI_VOL
)) bitsr
|= SBP_MIDI_SRC_R
;
869 if (mask
& (1<<SB_LINE_IN_VOL
)) bitsr
|= SBP_LINE_SRC_R
;
870 if (mask
& (1<<SB_CD_VOL
)) bitsr
|= SBP_CD_SRC_R
;
871 bitsl
= SB_SRC_R_TO_L(bitsr
);
872 if (mask
& (1<<SB_MIC_VOL
)) {
873 bitsl
|= SBP_MIC_SRC
;
874 bitsr
|= SBP_MIC_SRC
;
876 sbdsp_mix_write(sc
, SBP_RECORD_SOURCE_L
, bitsl
);
877 sbdsp_mix_write(sc
, SBP_RECORD_SOURCE_R
, bitsr
);
886 sbdsp_speaker_ctl(void *addr
, int newstate
)
888 struct sbdsp_softc
*sc
;
891 if (sc
->sc_open
== SB_OPEN_MIDI
)
894 if ((newstate
== SPKR_ON
) &&
895 (sc
->spkr_state
== SPKR_OFF
)) {
897 sc
->spkr_state
= SPKR_ON
;
899 if ((newstate
== SPKR_OFF
) &&
900 (sc
->spkr_state
== SPKR_ON
)) {
902 sc
->spkr_state
= SPKR_OFF
;
908 sbdsp_round_blocksize(void *addr
, int blk
, int mode
,
909 const audio_params_t
*param
)
911 return blk
& -4; /* round to biggest sample size */
915 sbdsp_open(void *addr
, int flags
)
917 struct sbdsp_softc
*sc
;
921 DPRINTF(("sbdsp_open: sc=%p\n", sc
));
923 if (sc
->sc_open
!= SB_CLOSED
)
925 sc
->sc_open
= SB_OPEN_AUDIO
;
928 if (sc
->sc_drq8
!= -1) {
929 error
= isa_drq_alloc(sc
->sc_ic
, sc
->sc_drq8
);
935 if (sc
->sc_drq16
!= -1 && sc
->sc_drq16
!= sc
->sc_drq8
) {
936 error
= isa_drq_alloc(sc
->sc_ic
, sc
->sc_drq16
);
943 if (sbdsp_reset(sc
) != 0) {
949 sbdsp_wdsp(sc
, SB_DSP_RECORD_MONO
) < 0) {
950 DPRINTF(("sbdsp_open: can't set mono mode\n"));
951 /* we'll readjust when it's time for DMA. */
955 * Leave most things as they were; users must change things if
956 * the previous process didn't leave it they way they wanted.
957 * Looked at another way, it's easy to set up a configuration
958 * in one program and leave it for another to inherit.
960 DPRINTF(("sbdsp_open: opened\n"));
966 isa_drq_free(sc
->sc_ic
, sc
->sc_drq8
);
968 isa_drq_free(sc
->sc_ic
, sc
->sc_drq16
);
970 sc
->sc_open
= SB_CLOSED
;
975 sbdsp_close(void *addr
)
977 struct sbdsp_softc
*sc
;
980 DPRINTF(("sbdsp_close: sc=%p\n", sc
));
983 sc
->spkr_state
= SPKR_OFF
;
988 if (sc
->sc_drq8
!= -1)
989 isa_drq_free(sc
->sc_ic
, sc
->sc_drq8
);
990 if (sc
->sc_drq16
!= -1 && sc
->sc_drq16
!= sc
->sc_drq8
)
991 isa_drq_free(sc
->sc_ic
, sc
->sc_drq16
);
993 sc
->sc_open
= SB_CLOSED
;
994 DPRINTF(("sbdsp_close: closed\n"));
998 * Lower-level routines
1003 * Return non-zero if the card isn't detected.
1006 sbdsp_reset(struct sbdsp_softc
*sc
)
1008 bus_space_tag_t iot
;
1009 bus_space_handle_t ioh
;
1018 * See SBK, section 11.3.
1019 * We pulse a reset signal into the card.
1020 * Gee, what a brilliant hardware design.
1022 bus_space_write_1(iot
, ioh
, SBP_DSP_RESET
, 1);
1024 bus_space_write_1(iot
, ioh
, SBP_DSP_RESET
, 0);
1026 if (sbdsp_rdsp(sc
) != SB_MAGIC
)
1033 * Write a byte to the dsp.
1034 * We are at the mercy of the card as we use a
1035 * polling loop and wait until it can take the byte.
1038 sbdsp_wdsp(struct sbdsp_softc
*sc
, int v
)
1040 bus_space_tag_t iot
;
1041 bus_space_handle_t ioh
;
1047 for (i
= SBDSP_NPOLL
; --i
>= 0; ) {
1048 x
= bus_space_read_1(iot
, ioh
, SBP_DSP_WSTAT
);
1050 if ((x
& SB_DSP_BUSY
) == 0) {
1051 bus_space_write_1(iot
, ioh
, SBP_DSP_WRITE
, v
);
1061 * Read a byte from the DSP, using polling.
1064 sbdsp_rdsp(struct sbdsp_softc
*sc
)
1066 bus_space_tag_t iot
;
1067 bus_space_handle_t ioh
;
1073 for (i
= SBDSP_NPOLL
; --i
>= 0; ) {
1074 x
= bus_space_read_1(iot
, ioh
, SBP_DSP_RSTAT
);
1076 if (x
& SB_DSP_READY
) {
1077 x
= bus_space_read_1(iot
, ioh
, SBP_DSP_READ
);
1087 sbdsp_pause(struct sbdsp_softc
*sc
)
1090 (void) tsleep(sbdsp_pause
, PWAIT
, "sbpause", hz
/ 8);
1094 * Turn on the speaker. The SBK documention says this operation
1095 * can take up to 1/10 of a second. Higher level layers should
1096 * probably let the task sleep for this amount of time after
1097 * calling here. Otherwise, things might not work (because
1098 * sbdsp_wdsp() and sbdsp_rdsp() will probably timeout.)
1100 * These engineers had their heads up their ass when
1101 * they designed this card.
1104 sbdsp_spkron(struct sbdsp_softc
*sc
)
1107 (void)sbdsp_wdsp(sc
, SB_DSP_SPKR_ON
);
1112 * Turn off the speaker; see comment above.
1115 sbdsp_spkroff(struct sbdsp_softc
*sc
)
1118 (void)sbdsp_wdsp(sc
, SB_DSP_SPKR_OFF
);
1123 * Read the version number out of the card.
1124 * Store version information in the softc.
1127 sbversion(struct sbdsp_softc
*sc
)
1131 sc
->sc_model
= SB_UNK
;
1133 if (sbdsp_wdsp(sc
, SB_DSP_VERSION
) < 0)
1135 v
= sbdsp_rdsp(sc
) << 8;
1136 v
|= sbdsp_rdsp(sc
);
1140 switch(SBVER_MAJOR(v
)) {
1142 sc
->sc_mixer_model
= SBM_NONE
;
1143 sc
->sc_model
= SB_1
;
1146 /* Some SB2 have a mixer, some don't. */
1147 sbdsp_mix_write(sc
, SBP_1335_MASTER_VOL
, 0x04);
1148 sbdsp_mix_write(sc
, SBP_1335_MIDI_VOL
, 0x06);
1149 /* Check if we can read back the mixer values. */
1150 if ((sbdsp_mix_read(sc
, SBP_1335_MASTER_VOL
) & 0x0e) == 0x04 &&
1151 (sbdsp_mix_read(sc
, SBP_1335_MIDI_VOL
) & 0x0e) == 0x06)
1152 sc
->sc_mixer_model
= SBM_CT1335
;
1154 sc
->sc_mixer_model
= SBM_NONE
;
1155 if (SBVER_MINOR(v
) == 0)
1156 sc
->sc_model
= SB_20
;
1158 sc
->sc_model
= SB_2x
;
1161 sc
->sc_mixer_model
= SBM_CT1345
;
1162 sc
->sc_model
= SB_PRO
;
1166 /* XXX This does not work */
1167 /* Most SB16 have a tone controls, but some don't. */
1168 sbdsp_mix_write(sc
, SB16P_TREBLE_L
, 0x80);
1169 /* Check if we can read back the mixer value. */
1170 if ((sbdsp_mix_read(sc
, SB16P_TREBLE_L
) & 0xf0) == 0x80)
1171 sc
->sc_mixer_model
= SBM_CT1745
;
1173 sc
->sc_mixer_model
= SBM_CT1XX5
;
1175 sc
->sc_mixer_model
= SBM_CT1745
;
1178 /* XXX figure out a good way of determining the model */
1179 /* XXX what about SB_32 */
1180 if (SBVER_MINOR(v
) == 16)
1181 sc
->sc_model
= SB_64
;
1184 sc
->sc_model
= SB_16
;
1190 sbdsp_set_timeconst(struct sbdsp_softc
*sc
, int tc
)
1193 DPRINTF(("sbdsp_set_timeconst: sc=%p tc=%d\n", sc
, tc
));
1194 if (sbdsp_wdsp(sc
, SB_DSP_TIMECONST
) < 0 ||
1195 sbdsp_wdsp(sc
, tc
) < 0)
1201 sbdsp16_set_rate(struct sbdsp_softc
*sc
, int cmd
, int rate
)
1204 DPRINTF(("sbdsp16_set_rate: sc=%p cmd=0x%02x rate=%d\n", sc
, cmd
, rate
));
1205 if (sbdsp_wdsp(sc
, cmd
) < 0 ||
1206 sbdsp_wdsp(sc
, rate
>> 8) < 0 ||
1207 sbdsp_wdsp(sc
, rate
) < 0)
1213 sbdsp_trigger_input(
1215 void *start
, void *end
,
1217 void (*intr
)(void *),
1219 const audio_params_t
*param
)
1221 struct sbdsp_softc
*sc
;
1227 stereo
= param
->channels
== 2;
1228 width
= param
->precision
;
1230 if (stereo
&& (blksize
& 1)) {
1231 DPRINTF(("stereo record odd bytes (%d)\n", blksize
));
1234 if (sc
->sc_i
.run
!= SB_NOTRUNNING
)
1235 printf("sbdsp_trigger_input: already running\n");
1238 sc
->sc_intrr
= intr
;
1243 if (sc
->sc_i
.dmachan
!= sc
->sc_drq8
) {
1244 printf("sbdsp_trigger_input: width=%d bad chan %d\n",
1245 width
, sc
->sc_i
.dmachan
);
1249 sc
->sc_intr8
= sbdsp_block_input
;
1252 if (sc
->sc_i
.dmachan
!= sc
->sc_drq16
) {
1253 printf("sbdsp_trigger_input: width=%d bad chan %d\n",
1254 width
, sc
->sc_i
.dmachan
);
1258 sc
->sc_intr16
= sbdsp_block_input
;
1261 if ((sc
->sc_model
== SB_JAZZ
) ? (sc
->sc_i
.dmachan
> 3) : (width
== 16))
1264 sc
->sc_i
.blksize
= blksize
;
1267 if (sbdsp_wdsp(sc
, sc
->sc_i
.modep
->cmdchan
) < 0)
1269 filter
= stereo
? SBP_FILTER_OFF
: sc
->in_filter
;
1270 sbdsp_mix_write(sc
, SBP_INFILTER
,
1271 (sbdsp_mix_read(sc
, SBP_INFILTER
) & ~SBP_IFILTER_MASK
) |
1275 if (ISSB16CLASS(sc
)) {
1276 if (sbdsp16_set_rate(sc
, SB_DSP16_INPUTRATE
, sc
->sc_i
.rate
)) {
1277 DPRINTF(("sbdsp_trigger_input: rate=%d set failed\n",
1282 if (sbdsp_set_timeconst(sc
, sc
->sc_i
.tc
)) {
1283 DPRINTF(("sbdsp_trigger_input: tc=%d set failed\n",
1289 DPRINTF(("sbdsp: DMA start loop input start=%p end=%p chan=%d\n",
1290 start
, end
, sc
->sc_i
.dmachan
));
1291 isa_dmastart(sc
->sc_ic
, sc
->sc_i
.dmachan
, start
,
1292 (char *)end
- (char *)start
, NULL
,
1293 DMAMODE_READ
| DMAMODE_LOOPDEMAND
, BUS_DMA_NOWAIT
);
1295 return sbdsp_block_input(addr
);
1299 sbdsp_block_input(void *addr
)
1301 struct sbdsp_softc
*sc
;
1305 cc
= sc
->sc_i
.blksize
;
1306 DPRINTFN(2, ("sbdsp_block_input: sc=%p cc=%d\n", addr
, cc
));
1308 if (sc
->sc_i
.run
!= SB_NOTRUNNING
)
1309 sc
->sc_intrr(sc
->sc_argr
);
1311 if (sc
->sc_model
== SB_1
) {
1312 /* Non-looping mode, start DMA */
1313 if (sbdsp_wdsp(sc
, sc
->sc_i
.modep
->cmd
) < 0 ||
1314 sbdsp_wdsp(sc
, cc
) < 0 ||
1315 sbdsp_wdsp(sc
, cc
>> 8) < 0) {
1316 DPRINTF(("sbdsp_block_input: SB1 DMA start failed\n"));
1319 sc
->sc_i
.run
= SB_RUNNING
;
1320 } else if (sc
->sc_i
.run
== SB_NOTRUNNING
) {
1321 /* Initialize looping PCM */
1322 if (ISSB16CLASS(sc
)) {
1323 DPRINTFN(3, ("sbdsp16 input command cmd=0x%02x bmode=0x%02x cc=%d\n",
1324 sc
->sc_i
.modep
->cmd
, sc
->sc_i
.bmode
, cc
));
1325 if (sbdsp_wdsp(sc
, sc
->sc_i
.modep
->cmd
) < 0 ||
1326 sbdsp_wdsp(sc
, sc
->sc_i
.bmode
) < 0 ||
1327 sbdsp_wdsp(sc
, cc
) < 0 ||
1328 sbdsp_wdsp(sc
, cc
>> 8) < 0) {
1329 DPRINTF(("sbdsp_block_input: SB16 DMA start failed\n"));
1333 DPRINTF(("sbdsp_block_input: set blocksize=%d\n", cc
));
1334 if (sbdsp_wdsp(sc
, SB_DSP_BLOCKSIZE
) < 0 ||
1335 sbdsp_wdsp(sc
, cc
) < 0 ||
1336 sbdsp_wdsp(sc
, cc
>> 8) < 0) {
1337 DPRINTF(("sbdsp_block_input: SB2 DMA blocksize failed\n"));
1340 if (sbdsp_wdsp(sc
, sc
->sc_i
.modep
->cmd
) < 0) {
1341 DPRINTF(("sbdsp_block_input: SB2 DMA start failed\n"));
1345 sc
->sc_i
.run
= SB_LOOPING
;
1352 sbdsp_trigger_output(
1354 void *start
, void *end
,
1356 void (*intr
)(void *),
1358 const audio_params_t
*param
)
1360 struct sbdsp_softc
*sc
;
1366 stereo
= param
->channels
== 2;
1367 width
= param
->precision
;
1369 if (stereo
&& (blksize
& 1)) {
1370 DPRINTF(("stereo playback odd bytes (%d)\n", blksize
));
1373 if (sc
->sc_o
.run
!= SB_NOTRUNNING
)
1374 printf("sbdsp_trigger_output: already running\n");
1377 sc
->sc_intrp
= intr
;
1382 if (sc
->sc_o
.dmachan
!= sc
->sc_drq8
) {
1383 printf("sbdsp_trigger_output: width=%d bad chan %d\n",
1384 width
, sc
->sc_o
.dmachan
);
1388 sc
->sc_intr8
= sbdsp_block_output
;
1391 if (sc
->sc_o
.dmachan
!= sc
->sc_drq16
) {
1392 printf("sbdsp_trigger_output: width=%d bad chan %d\n",
1393 width
, sc
->sc_o
.dmachan
);
1397 sc
->sc_intr16
= sbdsp_block_output
;
1400 if ((sc
->sc_model
== SB_JAZZ
) ? (sc
->sc_o
.dmachan
> 3) : (width
== 16))
1403 sc
->sc_o
.blksize
= blksize
;
1406 /* make sure we re-set stereo mixer bit when we start output. */
1407 sbdsp_mix_write(sc
, SBP_STEREO
,
1408 (sbdsp_mix_read(sc
, SBP_STEREO
) & ~SBP_PLAYMODE_MASK
) |
1409 (stereo
? SBP_PLAYMODE_STEREO
: SBP_PLAYMODE_MONO
));
1410 cmd
= sc
->sc_o
.modep
->cmdchan
;
1411 if (cmd
&& sbdsp_wdsp(sc
, cmd
) < 0)
1415 if (ISSB16CLASS(sc
)) {
1416 if (sbdsp16_set_rate(sc
, SB_DSP16_OUTPUTRATE
, sc
->sc_o
.rate
)) {
1417 DPRINTF(("sbdsp_trigger_output: rate=%d set failed\n",
1422 if (sbdsp_set_timeconst(sc
, sc
->sc_o
.tc
)) {
1423 DPRINTF(("sbdsp_trigger_output: tc=%d set failed\n",
1429 DPRINTF(("sbdsp: DMA start loop output start=%p end=%p chan=%d\n",
1430 start
, end
, sc
->sc_o
.dmachan
));
1431 isa_dmastart(sc
->sc_ic
, sc
->sc_o
.dmachan
, start
,
1432 (char *)end
- (char *)start
, NULL
,
1433 DMAMODE_WRITE
| DMAMODE_LOOPDEMAND
, BUS_DMA_NOWAIT
);
1435 return sbdsp_block_output(addr
);
1439 sbdsp_block_output(void *addr
)
1441 struct sbdsp_softc
*sc
;
1445 cc
= sc
->sc_o
.blksize
;
1446 DPRINTFN(2, ("sbdsp_block_output: sc=%p cc=%d\n", addr
, cc
));
1448 if (sc
->sc_o
.run
!= SB_NOTRUNNING
)
1449 sc
->sc_intrp(sc
->sc_argp
);
1451 if (sc
->sc_model
== SB_1
) {
1452 /* Non-looping mode, initialized. Start DMA and PCM */
1453 if (sbdsp_wdsp(sc
, sc
->sc_o
.modep
->cmd
) < 0 ||
1454 sbdsp_wdsp(sc
, cc
) < 0 ||
1455 sbdsp_wdsp(sc
, cc
>> 8) < 0) {
1456 DPRINTF(("sbdsp_block_output: SB1 DMA start failed\n"));
1459 sc
->sc_o
.run
= SB_RUNNING
;
1460 } else if (sc
->sc_o
.run
== SB_NOTRUNNING
) {
1461 /* Initialize looping PCM */
1462 if (ISSB16CLASS(sc
)) {
1463 DPRINTF(("sbdsp_block_output: SB16 cmd=0x%02x bmode=0x%02x cc=%d\n",
1464 sc
->sc_o
.modep
->cmd
,sc
->sc_o
.bmode
, cc
));
1465 if (sbdsp_wdsp(sc
, sc
->sc_o
.modep
->cmd
) < 0 ||
1466 sbdsp_wdsp(sc
, sc
->sc_o
.bmode
) < 0 ||
1467 sbdsp_wdsp(sc
, cc
) < 0 ||
1468 sbdsp_wdsp(sc
, cc
>> 8) < 0) {
1469 DPRINTF(("sbdsp_block_output: SB16 DMA start failed\n"));
1473 DPRINTF(("sbdsp_block_output: set blocksize=%d\n", cc
));
1474 if (sbdsp_wdsp(sc
, SB_DSP_BLOCKSIZE
) < 0 ||
1475 sbdsp_wdsp(sc
, cc
) < 0 ||
1476 sbdsp_wdsp(sc
, cc
>> 8) < 0) {
1477 DPRINTF(("sbdsp_block_output: SB2 DMA blocksize failed\n"));
1480 if (sbdsp_wdsp(sc
, sc
->sc_o
.modep
->cmd
) < 0) {
1481 DPRINTF(("sbdsp_block_output: SB2 DMA start failed\n"));
1485 sc
->sc_o
.run
= SB_LOOPING
;
1492 sbdsp_halt_output(void *addr
)
1494 struct sbdsp_softc
*sc
;
1497 if (sc
->sc_o
.run
!= SB_NOTRUNNING
) {
1498 if (sbdsp_wdsp(sc
, sc
->sc_o
.modep
->halt
) < 0)
1499 printf("sbdsp_halt_output: failed to halt\n");
1500 isa_dmaabort(sc
->sc_ic
, sc
->sc_o
.dmachan
);
1501 sc
->sc_o
.run
= SB_NOTRUNNING
;
1507 sbdsp_halt_input(void *addr
)
1509 struct sbdsp_softc
*sc
;
1512 if (sc
->sc_i
.run
!= SB_NOTRUNNING
) {
1513 if (sbdsp_wdsp(sc
, sc
->sc_i
.modep
->halt
) < 0)
1514 printf("sbdsp_halt_input: failed to halt\n");
1515 isa_dmaabort(sc
->sc_ic
, sc
->sc_i
.dmachan
);
1516 sc
->sc_i
.run
= SB_NOTRUNNING
;
1522 * Only the DSP unit on the sound blaster generates interrupts.
1523 * There are three cases of interrupt: reception of a midi byte
1524 * (when mode is enabled), completion of DMA transmission, or
1525 * completion of a DMA reception.
1527 * If there is interrupt sharing or a spurious interrupt occurs
1528 * there is no way to distinguish this on an SB2. So if you have
1529 * an SB2 and experience problems, buy an SB16 (it's only $40).
1532 sbdsp_intr(void *arg
)
1534 struct sbdsp_softc
*sc
= arg
;
1536 struct mpu_softc
*sc_mpu
= device_private(sc
->sc_mpudev
);
1540 DPRINTFN(2, ("sbdsp_intr: intr8=%p, intr16=%p\n",
1541 sc
->sc_intr8
, sc
->sc_intr16
));
1542 if (ISSB16CLASS(sc
)) {
1543 irq
= sbdsp_mix_read(sc
, SBP_IRQ_STATUS
);
1544 if ((irq
& (SBP_IRQ_DMA8
| SBP_IRQ_DMA16
| SBP_IRQ_MPU401
)) == 0) {
1545 DPRINTF(("sbdsp_intr: Spurious interrupt 0x%x\n", irq
));
1549 /* XXXX CHECK FOR INTERRUPT */
1553 sc
->sc_interrupts
++;
1554 delay(10); /* XXX why? */
1556 /* clear interrupt */
1557 if (irq
& SBP_IRQ_DMA8
) {
1558 bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, SBP_DSP_IRQACK8
);
1562 if (irq
& SBP_IRQ_DMA16
) {
1563 bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, SBP_DSP_IRQACK16
);
1568 if ((irq
& SBP_IRQ_MPU401
) && sc_mpu
) {
1575 /* Like val & mask, but make sure the result is correctly rounded. */
1578 sbdsp_adjust(int val
, int mask
)
1581 val
+= (MAXVAL
- mask
) >> 1;
1588 sbdsp_set_mixer_gain(struct sbdsp_softc
*sc
, int port
)
1592 switch(sc
->sc_mixer_model
) {
1596 gain
= SB_1335_GAIN(sc
->gain
[port
][SB_LEFT
]);
1599 src
= SBP_1335_MASTER_VOL
;
1602 src
= SBP_1335_MIDI_VOL
;
1605 src
= SBP_1335_CD_VOL
;
1608 src
= SBP_1335_VOICE_VOL
;
1609 gain
= SB_1335_MASTER_GAIN(sc
->gain
[port
][SB_LEFT
]);
1614 sbdsp_mix_write(sc
, src
, gain
);
1617 gain
= SB_STEREO_GAIN(sc
->gain
[port
][SB_LEFT
],
1618 sc
->gain
[port
][SB_RIGHT
]);
1622 gain
= SB_MIC_GAIN(sc
->gain
[port
][SB_LEFT
]);
1625 src
= SBP_MASTER_VOL
;
1627 case SB_LINE_IN_VOL
:
1631 src
= SBP_VOICE_VOL
;
1642 sbdsp_mix_write(sc
, src
, gain
);
1651 src
= SB16P_MASTER_L
;
1653 case SB_LINE_IN_VOL
:
1657 src
= SB16P_VOICE_L
;
1666 src
= SB16P_INPUT_GAIN_L
;
1668 case SB_OUTPUT_GAIN
:
1669 src
= SB16P_OUTPUT_GAIN_L
;
1672 src
= SB16P_TREBLE_L
;
1678 sbdsp_mix_write(sc
, SB16P_PCSPEAKER
, sc
->gain
[port
][SB_LEFT
]);
1683 sbdsp_mix_write(sc
, src
, sc
->gain
[port
][SB_LEFT
]);
1684 sbdsp_mix_write(sc
, SB16P_L_TO_R(src
), sc
->gain
[port
][SB_RIGHT
]);
1690 sbdsp_mixer_set_port(void *addr
, mixer_ctrl_t
*cp
)
1692 struct sbdsp_softc
*sc
;
1695 int lmask
, rmask
, lbits
, rbits
;
1699 if (sc
->sc_open
== SB_OPEN_MIDI
)
1702 DPRINTF(("sbdsp_mixer_set_port: port=%d num_channels=%d\n", cp
->dev
,
1703 cp
->un
.value
.num_channels
));
1705 if (sc
->sc_mixer_model
== SBM_NONE
)
1711 if (sc
->sc_mixer_model
== SBM_CT1345
||
1712 sc
->sc_mixer_model
== SBM_CT1XX5
) {
1713 if (cp
->type
!= AUDIO_MIXER_ENUM
)
1717 sbdsp_set_ifilter(addr
, cp
->un
.ord
? SB_TREBLE
: 0);
1720 sbdsp_set_ifilter(addr
, cp
->un
.ord
? SB_BASS
: 0);
1726 case SB_OUTPUT_GAIN
:
1730 case SB_LINE_IN_VOL
:
1731 if (sc
->sc_mixer_model
== SBM_CT1335
)
1737 if (cp
->type
!= AUDIO_MIXER_VALUE
)
1741 * All the mixer ports are stereo except for the microphone.
1742 * If we get a single-channel gain value passed in, then we
1743 * duplicate it to both left and right channels.
1748 if (cp
->un
.value
.num_channels
!= 1)
1751 lgain
= rgain
= SB_ADJUST_MIC_GAIN(sc
,
1752 cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_MONO
]);
1755 if (cp
->un
.value
.num_channels
!= 1)
1759 case SB_OUTPUT_GAIN
:
1760 lgain
= rgain
= SB_ADJUST_2_GAIN(sc
,
1761 cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_MONO
]);
1764 switch (cp
->un
.value
.num_channels
) {
1766 lgain
= rgain
= SB_ADJUST_GAIN(sc
,
1767 cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_MONO
]);
1770 if (sc
->sc_mixer_model
== SBM_CT1335
)
1772 lgain
= SB_ADJUST_GAIN(sc
,
1773 cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_LEFT
]);
1774 rgain
= SB_ADJUST_GAIN(sc
,
1775 cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_RIGHT
]);
1782 sc
->gain
[cp
->dev
][SB_LEFT
] = lgain
;
1783 sc
->gain
[cp
->dev
][SB_RIGHT
] = rgain
;
1785 sbdsp_set_mixer_gain(sc
, cp
->dev
);
1788 case SB_RECORD_SOURCE
:
1789 if (ISSBM1745(sc
)) {
1790 if (cp
->type
!= AUDIO_MIXER_SET
)
1792 return sbdsp_set_in_ports(sc
, cp
->un
.mask
);
1794 if (cp
->type
!= AUDIO_MIXER_ENUM
)
1796 sc
->in_port
= cp
->un
.ord
;
1797 return sbdsp_set_in_ports(sc
, 1 << cp
->un
.ord
);
1802 if (!ISSBM1745(sc
) || cp
->type
!= AUDIO_MIXER_ENUM
)
1804 sbdsp_mix_write(sc
, SB16P_AGC
, cp
->un
.ord
& 1);
1807 case SB_CD_OUT_MUTE
:
1810 case SB_MIC_OUT_MUTE
:
1811 mask
= SB16P_SW_MIC
;
1813 case SB_LINE_OUT_MUTE
:
1814 mask
= SB16P_SW_LINE
;
1816 if (cp
->type
!= AUDIO_MIXER_ENUM
)
1818 bits
= sbdsp_mix_read(sc
, SB16P_OSWITCH
);
1819 sc
->gain
[cp
->dev
][SB_LR
] = cp
->un
.ord
!= 0;
1821 bits
= bits
& ~mask
;
1824 sbdsp_mix_write(sc
, SB16P_OSWITCH
, bits
);
1827 case SB_MIC_IN_MUTE
:
1829 lmask
= rmask
= SB16P_SW_MIC
;
1833 lmask
= SB16P_SW_CD_L
;
1834 rmask
= SB16P_SW_CD_R
;
1836 case SB_LINE_IN_MUTE
:
1838 lmask
= SB16P_SW_LINE_L
;
1839 rmask
= SB16P_SW_LINE_R
;
1841 case SB_MIDI_IN_MUTE
:
1843 lmask
= SB16P_SW_MIDI_L
;
1844 rmask
= SB16P_SW_MIDI_R
;
1846 if (cp
->type
!= AUDIO_MIXER_ENUM
)
1848 mask
= lmask
| rmask
;
1849 lbits
= sbdsp_mix_read(sc
, SB16P_ISWITCH_L
) & ~mask
;
1850 rbits
= sbdsp_mix_read(sc
, SB16P_ISWITCH_R
) & ~mask
;
1851 sc
->gain
[cp
->dev
][SB_LR
] = cp
->un
.ord
!= 0;
1852 if (SB_IS_IN_MUTE(cp
->dev
)) {
1854 swap
= mute
- SB_CD_IN_MUTE
+ SB_CD_SWAP
;
1857 mute
= swap
+ SB_CD_IN_MUTE
- SB_CD_SWAP
;
1859 if (sc
->gain
[swap
][SB_LR
]) {
1864 if (!sc
->gain
[mute
][SB_LR
]) {
1865 lbits
= lbits
| lmask
;
1866 rbits
= rbits
| rmask
;
1868 sbdsp_mix_write(sc
, SB16P_ISWITCH_L
, lbits
);
1869 sbdsp_mix_write(sc
, SB16P_ISWITCH_L
, rbits
);
1880 sbdsp_mixer_get_port(void *addr
, mixer_ctrl_t
*cp
)
1882 struct sbdsp_softc
*sc
;
1885 if (sc
->sc_open
== SB_OPEN_MIDI
)
1888 DPRINTF(("sbdsp_mixer_get_port: port=%d\n", cp
->dev
));
1890 if (sc
->sc_mixer_model
== SBM_NONE
)
1896 if (sc
->sc_mixer_model
== SBM_CT1345
||
1897 sc
->sc_mixer_model
== SBM_CT1XX5
) {
1900 cp
->un
.ord
= sbdsp_get_ifilter(addr
) == SB_TREBLE
;
1903 cp
->un
.ord
= sbdsp_get_ifilter(addr
) == SB_BASS
;
1909 case SB_OUTPUT_GAIN
:
1913 case SB_LINE_IN_VOL
:
1914 if (sc
->sc_mixer_model
== SBM_CT1335
)
1923 if (cp
->un
.value
.num_channels
!= 1)
1927 switch (cp
->un
.value
.num_channels
) {
1929 cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_MONO
] =
1930 sc
->gain
[cp
->dev
][SB_LEFT
];
1933 cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_LEFT
] =
1934 sc
->gain
[cp
->dev
][SB_LEFT
];
1935 cp
->un
.value
.level
[AUDIO_MIXER_LEVEL_RIGHT
] =
1936 sc
->gain
[cp
->dev
][SB_RIGHT
];
1945 case SB_RECORD_SOURCE
:
1947 cp
->un
.mask
= sc
->in_mask
;
1949 cp
->un
.ord
= sc
->in_port
;
1955 cp
->un
.ord
= sbdsp_mix_read(sc
, SB16P_AGC
);
1959 case SB_MIC_IN_MUTE
:
1960 case SB_LINE_IN_MUTE
:
1961 case SB_MIDI_IN_MUTE
:
1966 case SB_CD_OUT_MUTE
:
1967 case SB_MIC_OUT_MUTE
:
1968 case SB_LINE_OUT_MUTE
:
1969 cp
->un
.ord
= sc
->gain
[cp
->dev
][SB_LR
];
1980 sbdsp_mixer_query_devinfo(void *addr
, mixer_devinfo_t
*dip
)
1982 struct sbdsp_softc
*sc
= addr
;
1983 int chan
, class, is1745
;
1986 DPRINTF(("sbdsp_mixer_query_devinfo: model=%d index=%d\n",
1987 sc
->sc_mixer_model
, dip
->index
));
1989 if (sc
->sc_mixer_model
== SBM_NONE
)
1992 chan
= sc
->sc_mixer_model
== SBM_CT1335
? 1 : 2;
1993 is1745
= ISSBM1745(sc
);
1994 class = is1745
? SB_INPUT_CLASS
: SB_OUTPUT_CLASS
;
1996 switch (dip
->index
) {
1998 dip
->type
= AUDIO_MIXER_VALUE
;
1999 dip
->mixer_class
= SB_OUTPUT_CLASS
;
2000 dip
->prev
= dip
->next
= AUDIO_MIXER_LAST
;
2001 strcpy(dip
->label
.name
, AudioNmaster
);
2002 dip
->un
.v
.num_channels
= chan
;
2003 strcpy(dip
->un
.v
.units
.name
, AudioNvolume
);
2006 dip
->type
= AUDIO_MIXER_VALUE
;
2007 dip
->mixer_class
= class;
2008 dip
->prev
= AUDIO_MIXER_LAST
;
2009 dip
->next
= is1745
? SB_MIDI_IN_MUTE
: AUDIO_MIXER_LAST
;
2010 strcpy(dip
->label
.name
, AudioNfmsynth
);
2011 dip
->un
.v
.num_channels
= chan
;
2012 strcpy(dip
->un
.v
.units
.name
, AudioNvolume
);
2015 dip
->type
= AUDIO_MIXER_VALUE
;
2016 dip
->mixer_class
= class;
2017 dip
->prev
= AUDIO_MIXER_LAST
;
2018 dip
->next
= is1745
? SB_CD_IN_MUTE
: AUDIO_MIXER_LAST
;
2019 strcpy(dip
->label
.name
, AudioNcd
);
2020 dip
->un
.v
.num_channels
= chan
;
2021 strcpy(dip
->un
.v
.units
.name
, AudioNvolume
);
2024 dip
->type
= AUDIO_MIXER_VALUE
;
2025 dip
->mixer_class
= class;
2026 dip
->prev
= AUDIO_MIXER_LAST
;
2027 dip
->next
= AUDIO_MIXER_LAST
;
2028 strcpy(dip
->label
.name
, AudioNdac
);
2029 dip
->un
.v
.num_channels
= chan
;
2030 strcpy(dip
->un
.v
.units
.name
, AudioNvolume
);
2032 case SB_OUTPUT_CLASS
:
2033 dip
->type
= AUDIO_MIXER_CLASS
;
2034 dip
->mixer_class
= SB_OUTPUT_CLASS
;
2035 dip
->next
= dip
->prev
= AUDIO_MIXER_LAST
;
2036 strcpy(dip
->label
.name
, AudioCoutputs
);
2040 if (sc
->sc_mixer_model
== SBM_CT1335
)
2043 switch (dip
->index
) {
2045 dip
->type
= AUDIO_MIXER_VALUE
;
2046 dip
->mixer_class
= class;
2047 dip
->prev
= AUDIO_MIXER_LAST
;
2048 dip
->next
= is1745
? SB_MIC_IN_MUTE
: AUDIO_MIXER_LAST
;
2049 strcpy(dip
->label
.name
, AudioNmicrophone
);
2050 dip
->un
.v
.num_channels
= 1;
2051 strcpy(dip
->un
.v
.units
.name
, AudioNvolume
);
2054 case SB_LINE_IN_VOL
:
2055 dip
->type
= AUDIO_MIXER_VALUE
;
2056 dip
->mixer_class
= class;
2057 dip
->prev
= AUDIO_MIXER_LAST
;
2058 dip
->next
= is1745
? SB_LINE_IN_MUTE
: AUDIO_MIXER_LAST
;
2059 strcpy(dip
->label
.name
, AudioNline
);
2060 dip
->un
.v
.num_channels
= 2;
2061 strcpy(dip
->un
.v
.units
.name
, AudioNvolume
);
2064 case SB_RECORD_SOURCE
:
2065 dip
->mixer_class
= SB_RECORD_CLASS
;
2066 dip
->prev
= dip
->next
= AUDIO_MIXER_LAST
;
2067 strcpy(dip
->label
.name
, AudioNsource
);
2068 if (ISSBM1745(sc
)) {
2069 dip
->type
= AUDIO_MIXER_SET
;
2070 dip
->un
.s
.num_mem
= 4;
2071 strcpy(dip
->un
.s
.member
[0].label
.name
, AudioNmicrophone
);
2072 dip
->un
.s
.member
[0].mask
= 1 << SB_MIC_VOL
;
2073 strcpy(dip
->un
.s
.member
[1].label
.name
, AudioNcd
);
2074 dip
->un
.s
.member
[1].mask
= 1 << SB_CD_VOL
;
2075 strcpy(dip
->un
.s
.member
[2].label
.name
, AudioNline
);
2076 dip
->un
.s
.member
[2].mask
= 1 << SB_LINE_IN_VOL
;
2077 strcpy(dip
->un
.s
.member
[3].label
.name
, AudioNfmsynth
);
2078 dip
->un
.s
.member
[3].mask
= 1 << SB_MIDI_VOL
;
2080 dip
->type
= AUDIO_MIXER_ENUM
;
2081 dip
->un
.e
.num_mem
= 3;
2082 strcpy(dip
->un
.e
.member
[0].label
.name
, AudioNmicrophone
);
2083 dip
->un
.e
.member
[0].ord
= SB_MIC_VOL
;
2084 strcpy(dip
->un
.e
.member
[1].label
.name
, AudioNcd
);
2085 dip
->un
.e
.member
[1].ord
= SB_CD_VOL
;
2086 strcpy(dip
->un
.e
.member
[2].label
.name
, AudioNline
);
2087 dip
->un
.e
.member
[2].ord
= SB_LINE_IN_VOL
;
2092 dip
->prev
= dip
->next
= AUDIO_MIXER_LAST
;
2093 strcpy(dip
->label
.name
, AudioNbass
);
2094 if (sc
->sc_mixer_model
== SBM_CT1745
) {
2095 dip
->type
= AUDIO_MIXER_VALUE
;
2096 dip
->mixer_class
= SB_EQUALIZATION_CLASS
;
2097 dip
->un
.v
.num_channels
= 2;
2098 strcpy(dip
->un
.v
.units
.name
, AudioNbass
);
2100 dip
->type
= AUDIO_MIXER_ENUM
;
2101 dip
->mixer_class
= SB_INPUT_CLASS
;
2102 dip
->un
.e
.num_mem
= 2;
2103 strcpy(dip
->un
.e
.member
[0].label
.name
, AudioNoff
);
2104 dip
->un
.e
.member
[0].ord
= 0;
2105 strcpy(dip
->un
.e
.member
[1].label
.name
, AudioNon
);
2106 dip
->un
.e
.member
[1].ord
= 1;
2111 dip
->prev
= dip
->next
= AUDIO_MIXER_LAST
;
2112 strcpy(dip
->label
.name
, AudioNtreble
);
2113 if (sc
->sc_mixer_model
== SBM_CT1745
) {
2114 dip
->type
= AUDIO_MIXER_VALUE
;
2115 dip
->mixer_class
= SB_EQUALIZATION_CLASS
;
2116 dip
->un
.v
.num_channels
= 2;
2117 strcpy(dip
->un
.v
.units
.name
, AudioNtreble
);
2119 dip
->type
= AUDIO_MIXER_ENUM
;
2120 dip
->mixer_class
= SB_INPUT_CLASS
;
2121 dip
->un
.e
.num_mem
= 2;
2122 strcpy(dip
->un
.e
.member
[0].label
.name
, AudioNoff
);
2123 dip
->un
.e
.member
[0].ord
= 0;
2124 strcpy(dip
->un
.e
.member
[1].label
.name
, AudioNon
);
2125 dip
->un
.e
.member
[1].ord
= 1;
2129 case SB_RECORD_CLASS
: /* record source class */
2130 dip
->type
= AUDIO_MIXER_CLASS
;
2131 dip
->mixer_class
= SB_RECORD_CLASS
;
2132 dip
->next
= dip
->prev
= AUDIO_MIXER_LAST
;
2133 strcpy(dip
->label
.name
, AudioCrecord
);
2136 case SB_INPUT_CLASS
:
2137 dip
->type
= AUDIO_MIXER_CLASS
;
2138 dip
->mixer_class
= SB_INPUT_CLASS
;
2139 dip
->next
= dip
->prev
= AUDIO_MIXER_LAST
;
2140 strcpy(dip
->label
.name
, AudioCinputs
);
2145 if (sc
->sc_mixer_model
== SBM_CT1345
)
2148 switch(dip
->index
) {
2150 dip
->type
= AUDIO_MIXER_VALUE
;
2151 dip
->mixer_class
= SB_INPUT_CLASS
;
2152 dip
->prev
= dip
->next
= AUDIO_MIXER_LAST
;
2153 strcpy(dip
->label
.name
, "pc_speaker");
2154 dip
->un
.v
.num_channels
= 1;
2155 strcpy(dip
->un
.v
.units
.name
, AudioNvolume
);
2159 dip
->type
= AUDIO_MIXER_VALUE
;
2160 dip
->mixer_class
= SB_INPUT_CLASS
;
2161 dip
->prev
= dip
->next
= AUDIO_MIXER_LAST
;
2162 strcpy(dip
->label
.name
, AudioNinput
);
2163 dip
->un
.v
.num_channels
= 2;
2164 strcpy(dip
->un
.v
.units
.name
, AudioNvolume
);
2167 case SB_OUTPUT_GAIN
:
2168 dip
->type
= AUDIO_MIXER_VALUE
;
2169 dip
->mixer_class
= SB_OUTPUT_CLASS
;
2170 dip
->prev
= dip
->next
= AUDIO_MIXER_LAST
;
2171 strcpy(dip
->label
.name
, AudioNoutput
);
2172 dip
->un
.v
.num_channels
= 2;
2173 strcpy(dip
->un
.v
.units
.name
, AudioNvolume
);
2177 dip
->type
= AUDIO_MIXER_ENUM
;
2178 dip
->mixer_class
= SB_INPUT_CLASS
;
2179 dip
->prev
= dip
->next
= AUDIO_MIXER_LAST
;
2180 strcpy(dip
->label
.name
, "agc");
2181 dip
->un
.e
.num_mem
= 2;
2182 strcpy(dip
->un
.e
.member
[0].label
.name
, AudioNoff
);
2183 dip
->un
.e
.member
[0].ord
= 0;
2184 strcpy(dip
->un
.e
.member
[1].label
.name
, AudioNon
);
2185 dip
->un
.e
.member
[1].ord
= 1;
2188 case SB_EQUALIZATION_CLASS
:
2189 dip
->type
= AUDIO_MIXER_CLASS
;
2190 dip
->mixer_class
= SB_EQUALIZATION_CLASS
;
2191 dip
->next
= dip
->prev
= AUDIO_MIXER_LAST
;
2192 strcpy(dip
->label
.name
, AudioCequalization
);
2196 dip
->prev
= SB_CD_VOL
;
2197 dip
->next
= SB_CD_SWAP
;
2198 dip
->mixer_class
= SB_INPUT_CLASS
;
2201 case SB_MIC_IN_MUTE
:
2202 dip
->prev
= SB_MIC_VOL
;
2203 dip
->next
= SB_MIC_SWAP
;
2204 dip
->mixer_class
= SB_INPUT_CLASS
;
2207 case SB_LINE_IN_MUTE
:
2208 dip
->prev
= SB_LINE_IN_VOL
;
2209 dip
->next
= SB_LINE_SWAP
;
2210 dip
->mixer_class
= SB_INPUT_CLASS
;
2213 case SB_MIDI_IN_MUTE
:
2214 dip
->prev
= SB_MIDI_VOL
;
2215 dip
->next
= SB_MIDI_SWAP
;
2216 dip
->mixer_class
= SB_INPUT_CLASS
;
2220 dip
->prev
= SB_CD_IN_MUTE
;
2221 dip
->next
= SB_CD_OUT_MUTE
;
2225 dip
->prev
= SB_MIC_IN_MUTE
;
2226 dip
->next
= SB_MIC_OUT_MUTE
;
2230 dip
->prev
= SB_LINE_IN_MUTE
;
2231 dip
->next
= SB_LINE_OUT_MUTE
;
2235 dip
->prev
= SB_MIDI_IN_MUTE
;
2236 dip
->next
= AUDIO_MIXER_LAST
;
2238 dip
->mixer_class
= SB_INPUT_CLASS
;
2239 strcpy(dip
->label
.name
, AudioNswap
);
2242 case SB_CD_OUT_MUTE
:
2243 dip
->prev
= SB_CD_SWAP
;
2244 dip
->next
= AUDIO_MIXER_LAST
;
2245 dip
->mixer_class
= SB_OUTPUT_CLASS
;
2248 case SB_MIC_OUT_MUTE
:
2249 dip
->prev
= SB_MIC_SWAP
;
2250 dip
->next
= AUDIO_MIXER_LAST
;
2251 dip
->mixer_class
= SB_OUTPUT_CLASS
;
2254 case SB_LINE_OUT_MUTE
:
2255 dip
->prev
= SB_LINE_SWAP
;
2256 dip
->next
= AUDIO_MIXER_LAST
;
2257 dip
->mixer_class
= SB_OUTPUT_CLASS
;
2259 strcpy(dip
->label
.name
, AudioNmute
);
2261 dip
->type
= AUDIO_MIXER_ENUM
;
2262 dip
->un
.e
.num_mem
= 2;
2263 strcpy(dip
->un
.e
.member
[0].label
.name
, AudioNoff
);
2264 dip
->un
.e
.member
[0].ord
= 0;
2265 strcpy(dip
->un
.e
.member
[1].label
.name
, AudioNon
);
2266 dip
->un
.e
.member
[1].ord
= 1;
2275 sb_malloc(void *addr
, int direction
, size_t size
,
2276 struct malloc_type
*pool
, int flags
)
2278 struct sbdsp_softc
*sc
;
2282 if (sc
->sc_drq8
!= -1)
2286 return isa_malloc(sc
->sc_ic
, drq
, size
, pool
, flags
);
2290 sb_free(void *addr
, void *ptr
, struct malloc_type
*pool
)
2293 isa_free(ptr
, pool
);
2297 sb_round_buffersize(void *addr
, int direction
, size_t size
)
2299 struct sbdsp_softc
*sc
;
2303 if (sc
->sc_drq8
!= -1)
2304 maxsize
= sc
->sc_drq8_maxsize
;
2306 maxsize
= sc
->sc_drq16_maxsize
;
2314 sb_mappage(void *addr
, void *mem
, off_t off
, int prot
)
2317 return isa_mappage(mem
, off
, prot
);
2321 sbdsp_get_props(void *addr
)
2323 struct sbdsp_softc
*sc
;
2326 return AUDIO_PROP_MMAP
| AUDIO_PROP_INDEPENDENT
|
2327 (sc
->sc_fullduplex
? AUDIO_PROP_FULLDUPLEX
: 0);
2332 * MIDI related routines.
2336 sbdsp_midi_open(void *addr
, int flags
, void (*iintr
)(void *, int),
2337 void (*ointr
)(void *), void *arg
)
2339 struct sbdsp_softc
*sc
;
2342 DPRINTF(("sbdsp_midi_open: sc=%p\n", sc
));
2344 if (sc
->sc_open
!= SB_CLOSED
)
2346 if (sbdsp_reset(sc
) != 0)
2349 sc
->sc_open
= SB_OPEN_MIDI
;
2351 if (sc
->sc_model
>= SB_20
)
2352 if (sbdsp_wdsp(sc
, SB_MIDI_UART_INTR
)) /* enter UART mode */
2355 sc
->sc_intr8
= sbdsp_midi_intr
;
2356 sc
->sc_intrm
= iintr
;
2363 sbdsp_midi_close(void *addr
)
2365 struct sbdsp_softc
*sc
;
2368 DPRINTF(("sbdsp_midi_close: sc=%p\n", sc
));
2370 if (sc
->sc_model
>= SB_20
)
2371 sbdsp_reset(sc
); /* exit UART mode */
2374 sc
->sc_open
= SB_CLOSED
;
2378 sbdsp_midi_output(void *addr
, int d
)
2380 struct sbdsp_softc
*sc
;
2383 if (sc
->sc_model
< SB_20
&& sbdsp_wdsp(sc
, SB_MIDI_WRITE
))
2385 if (sbdsp_wdsp(sc
, d
))
2391 sbdsp_midi_getinfo(void *addr
, struct midi_info
*mi
)
2393 struct sbdsp_softc
*sc
;
2396 mi
->name
= sc
->sc_model
< SB_20
? "SB MIDI cmd" : "SB MIDI UART";
2397 mi
->props
= MIDI_PROP_CAN_INPUT
;
2401 sbdsp_midi_intr(void *addr
)
2403 struct sbdsp_softc
*sc
;
2406 sc
->sc_intrm(sc
->sc_argm
, sbdsp_rdsp(sc
));