sbdsp.c revision 1.102 1 /* $NetBSD: sbdsp.c,v 1.102 1999/11/01 18:12:20 augustss Exp $ */
2
3 /*-
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
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.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * Copyright (c) 1991-1993 Regents of the University of California.
41 * All rights reserved.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 * 3. All advertising materials mentioning features or use of this software
52 * must display the following acknowledgement:
53 * This product includes software developed by the Computer Systems
54 * Engineering Group at Lawrence Berkeley Laboratory.
55 * 4. Neither the name of the University nor of the Laboratory may be used
56 * to endorse or promote products derived from this software without
57 * specific prior written permission.
58 *
59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * SUCH DAMAGE.
70 *
71 */
72
73 /*
74 * SoundBlaster Pro code provided by John Kohl, based on lots of
75 * information he gleaned from Steve Haehnichen <steve (at) vigra.com>'s
76 * SBlast driver for 386BSD and DOS driver code from Daniel Sachs
77 * <sachs (at) meibm15.cen.uiuc.edu>.
78 * Lots of rewrites by Lennart Augustsson <augustss (at) cs.chalmers.se>
79 * with information from SB "Hardware Programming Guide" and the
80 * Linux drivers.
81 */
82
83 #include "midi.h"
84 #include "mpu.h"
85
86 #include <sys/param.h>
87 #include <sys/systm.h>
88 #include <sys/errno.h>
89 #include <sys/ioctl.h>
90 #include <sys/syslog.h>
91 #include <sys/device.h>
92 #include <sys/proc.h>
93 #include <sys/buf.h>
94 #include <vm/vm.h>
95
96 #include <machine/cpu.h>
97 #include <machine/intr.h>
98 #include <machine/bus.h>
99
100 #include <sys/audioio.h>
101 #include <dev/audio_if.h>
102 #include <dev/midi_if.h>
103 #include <dev/mulaw.h>
104 #include <dev/auconv.h>
105
106 #include <dev/isa/isavar.h>
107 #include <dev/isa/isadmavar.h>
108
109 #include <dev/isa/sbreg.h>
110 #include <dev/isa/sbdspvar.h>
111
112
113 #ifdef AUDIO_DEBUG
114 #define DPRINTF(x) if (sbdspdebug) printf x
115 #define DPRINTFN(n,x) if (sbdspdebug >= (n)) printf x
116 int sbdspdebug = 0;
117 #else
118 #define DPRINTF(x)
119 #define DPRINTFN(n,x)
120 #endif
121
122 #ifndef SBDSP_NPOLL
123 #define SBDSP_NPOLL 3000
124 #endif
125
126 struct {
127 int wdsp;
128 int rdsp;
129 int wmidi;
130 } sberr;
131
132 /*
133 * Time constant routines follow. See SBK, section 12.
134 * Although they don't come out and say it (in the docs),
135 * the card clearly uses a 1MHz countdown timer, as the
136 * low-speed formula (p. 12-4) is:
137 * tc = 256 - 10^6 / sr
138 * In high-speed mode, the constant is the upper byte of a 16-bit counter,
139 * and a 256MHz clock is used:
140 * tc = 65536 - 256 * 10^ 6 / sr
141 * Since we can only use the upper byte of the HS TC, the two formulae
142 * are equivalent. (Why didn't they say so?) E.g.,
143 * (65536 - 256 * 10 ^ 6 / x) >> 8 = 256 - 10^6 / x
144 *
145 * The crossover point (from low- to high-speed modes) is different
146 * for the SBPRO and SB20. The table on p. 12-5 gives the following data:
147 *
148 * SBPRO SB20
149 * ----- --------
150 * input ls min 4 KHz 4 KHz
151 * input ls max 23 KHz 13 KHz
152 * input hs max 44.1 KHz 15 KHz
153 * output ls min 4 KHz 4 KHz
154 * output ls max 23 KHz 23 KHz
155 * output hs max 44.1 KHz 44.1 KHz
156 */
157 /* XXX Should we round the tc?
158 #define SB_RATE_TO_TC(x) (((65536 - 256 * 1000000 / (x)) + 128) >> 8)
159 */
160 #define SB_RATE_TO_TC(x) (256 - 1000000 / (x))
161 #define SB_TC_TO_RATE(tc) (1000000 / (256 - (tc)))
162
163 struct sbmode {
164 short model;
165 u_char channels;
166 u_char precision;
167 u_short lowrate, highrate;
168 u_char cmd;
169 u_char halt, cont;
170 u_char cmdchan;
171 };
172 static struct sbmode sbpmodes[] = {
173 { SB_1, 1, 8, 4000,22727,SB_DSP_WDMA ,SB_DSP_HALT ,SB_DSP_CONT },
174 { SB_20, 1, 8, 4000,22727,SB_DSP_WDMA_LOOP,SB_DSP_HALT ,SB_DSP_CONT },
175 { SB_2x, 1, 8,22727,45454,SB_DSP_HS_OUTPUT,SB_DSP_HALT ,SB_DSP_CONT },
176 { SB_2x, 1, 8, 4000,22727,SB_DSP_WDMA_LOOP,SB_DSP_HALT ,SB_DSP_CONT },
177 { SB_PRO, 1, 8,22727,45454,SB_DSP_HS_OUTPUT,SB_DSP_HALT ,SB_DSP_CONT },
178 { SB_PRO, 1, 8, 4000,22727,SB_DSP_WDMA_LOOP,SB_DSP_HALT ,SB_DSP_CONT },
179 { SB_PRO, 2, 8,11025,22727,SB_DSP_HS_OUTPUT,SB_DSP_HALT ,SB_DSP_CONT },
180 /* Yes, we write the record mode to set 16-bit playback mode. weird, huh? */
181 { SB_JAZZ,1, 8,22727,45454,SB_DSP_HS_OUTPUT,SB_DSP_HALT ,SB_DSP_CONT ,SB_DSP_RECORD_MONO },
182 { SB_JAZZ,1, 8, 4000,22727,SB_DSP_WDMA_LOOP,SB_DSP_HALT ,SB_DSP_CONT ,SB_DSP_RECORD_MONO },
183 { SB_JAZZ,2, 8,11025,22727,SB_DSP_HS_OUTPUT,SB_DSP_HALT ,SB_DSP_CONT ,SB_DSP_RECORD_STEREO },
184 { SB_JAZZ,1,16,22727,45454,SB_DSP_HS_OUTPUT,SB_DSP_HALT ,SB_DSP_CONT ,JAZZ16_RECORD_MONO },
185 { SB_JAZZ,1,16, 4000,22727,SB_DSP_WDMA_LOOP,SB_DSP_HALT ,SB_DSP_CONT ,JAZZ16_RECORD_MONO },
186 { SB_JAZZ,2,16,11025,22727,SB_DSP_HS_OUTPUT,SB_DSP_HALT ,SB_DSP_CONT ,JAZZ16_RECORD_STEREO },
187 { SB_16, 1, 8, 5000,45000,SB_DSP16_WDMA_8 ,SB_DSP_HALT ,SB_DSP_CONT },
188 { SB_16, 2, 8, 5000,45000,SB_DSP16_WDMA_8 ,SB_DSP_HALT ,SB_DSP_CONT },
189 #define PLAY16 15 /* must be the index of the next entry in the table */
190 { SB_16, 1,16, 5000,45000,SB_DSP16_WDMA_16,SB_DSP16_HALT,SB_DSP16_CONT},
191 { SB_16, 2,16, 5000,45000,SB_DSP16_WDMA_16,SB_DSP16_HALT,SB_DSP16_CONT},
192 { -1 }
193 };
194 static struct sbmode sbrmodes[] = {
195 { SB_1, 1, 8, 4000,12987,SB_DSP_RDMA ,SB_DSP_HALT ,SB_DSP_CONT },
196 { SB_20, 1, 8, 4000,12987,SB_DSP_RDMA_LOOP,SB_DSP_HALT ,SB_DSP_CONT },
197 { SB_2x, 1, 8,12987,14925,SB_DSP_HS_INPUT ,SB_DSP_HALT ,SB_DSP_CONT },
198 { SB_2x, 1, 8, 4000,12987,SB_DSP_RDMA_LOOP,SB_DSP_HALT ,SB_DSP_CONT },
199 { SB_PRO, 1, 8,22727,45454,SB_DSP_HS_INPUT ,SB_DSP_HALT ,SB_DSP_CONT ,SB_DSP_RECORD_MONO },
200 { SB_PRO, 1, 8, 4000,22727,SB_DSP_RDMA_LOOP,SB_DSP_HALT ,SB_DSP_CONT ,SB_DSP_RECORD_MONO },
201 { SB_PRO, 2, 8,11025,22727,SB_DSP_HS_INPUT ,SB_DSP_HALT ,SB_DSP_CONT ,SB_DSP_RECORD_STEREO },
202 { SB_JAZZ,1, 8,22727,45454,SB_DSP_HS_INPUT ,SB_DSP_HALT ,SB_DSP_CONT ,SB_DSP_RECORD_MONO },
203 { SB_JAZZ,1, 8, 4000,22727,SB_DSP_RDMA_LOOP,SB_DSP_HALT ,SB_DSP_CONT ,SB_DSP_RECORD_MONO },
204 { SB_JAZZ,2, 8,11025,22727,SB_DSP_HS_INPUT ,SB_DSP_HALT ,SB_DSP_CONT ,SB_DSP_RECORD_STEREO },
205 { SB_JAZZ,1,16,22727,45454,SB_DSP_HS_INPUT ,SB_DSP_HALT ,SB_DSP_CONT ,JAZZ16_RECORD_MONO },
206 { SB_JAZZ,1,16, 4000,22727,SB_DSP_RDMA_LOOP,SB_DSP_HALT ,SB_DSP_CONT ,JAZZ16_RECORD_MONO },
207 { SB_JAZZ,2,16,11025,22727,SB_DSP_HS_INPUT ,SB_DSP_HALT ,SB_DSP_CONT ,JAZZ16_RECORD_STEREO },
208 { SB_16, 1, 8, 5000,45000,SB_DSP16_RDMA_8 ,SB_DSP_HALT ,SB_DSP_CONT },
209 { SB_16, 2, 8, 5000,45000,SB_DSP16_RDMA_8 ,SB_DSP_HALT ,SB_DSP_CONT },
210 { SB_16, 1,16, 5000,45000,SB_DSP16_RDMA_16,SB_DSP16_HALT,SB_DSP16_CONT},
211 { SB_16, 2,16, 5000,45000,SB_DSP16_RDMA_16,SB_DSP16_HALT,SB_DSP16_CONT},
212 { -1 }
213 };
214
215 void sbversion __P((struct sbdsp_softc *));
216 void sbdsp_jazz16_probe __P((struct sbdsp_softc *));
217 void sbdsp_set_mixer_gain __P((struct sbdsp_softc *sc, int port));
218 void sbdsp_to __P((void *));
219 void sbdsp_pause __P((struct sbdsp_softc *));
220 int sbdsp_set_timeconst __P((struct sbdsp_softc *, int));
221 int sbdsp16_set_rate __P((struct sbdsp_softc *, int, int));
222 int sbdsp_set_in_ports __P((struct sbdsp_softc *, int));
223 void sbdsp_set_ifilter __P((void *, int));
224 int sbdsp_get_ifilter __P((void *));
225
226 int sbdsp_block_output __P((void *));
227 int sbdsp_block_input __P((void *));
228 static int sbdsp_adjust __P((int, int));
229
230 int sbdsp_midi_intr __P((void *));
231
232 #ifdef AUDIO_DEBUG
233 void sb_printsc __P((struct sbdsp_softc *));
234
235 void
236 sb_printsc(sc)
237 struct sbdsp_softc *sc;
238 {
239 int i;
240
241 printf("open %d dmachan %d/%d %d/%d iobase 0x%x irq %d\n",
242 (int)sc->sc_open, sc->sc_i.run, sc->sc_o.run,
243 sc->sc_drq8, sc->sc_drq16,
244 sc->sc_iobase, sc->sc_irq);
245 printf("irate %d itc %x orate %d otc %x\n",
246 sc->sc_i.rate, sc->sc_i.tc,
247 sc->sc_o.rate, sc->sc_o.tc);
248 printf("spkron %u nintr %lu\n",
249 sc->spkr_state, sc->sc_interrupts);
250 printf("intr8 %p intr16 %p\n",
251 sc->sc_intr8, sc->sc_intr16);
252 printf("gain:");
253 for (i = 0; i < SB_NDEVS; i++)
254 printf(" %u,%u", sc->gain[i][SB_LEFT], sc->gain[i][SB_RIGHT]);
255 printf("\n");
256 }
257 #endif /* AUDIO_DEBUG */
258
259 /*
260 * Probe / attach routines.
261 */
262
263 /*
264 * Probe for the soundblaster hardware.
265 */
266 int
267 sbdsp_probe(sc)
268 struct sbdsp_softc *sc;
269 {
270
271 if (sbdsp_reset(sc) < 0) {
272 DPRINTF(("sbdsp: couldn't reset card\n"));
273 return 0;
274 }
275 /* if flags set, go and probe the jazz16 stuff */
276 if (sc->sc_dev.dv_cfdata->cf_flags & 1)
277 sbdsp_jazz16_probe(sc);
278 else
279 sbversion(sc);
280 if (sc->sc_model == SB_UNK) {
281 /* Unknown SB model found. */
282 DPRINTF(("sbdsp: unknown SB model found\n"));
283 return 0;
284 }
285 return 1;
286 }
287
288 /*
289 * Try add-on stuff for Jazz16.
290 */
291 void
292 sbdsp_jazz16_probe(sc)
293 struct sbdsp_softc *sc;
294 {
295 static u_char jazz16_irq_conf[16] = {
296 -1, -1, 0x02, 0x03,
297 -1, 0x01, -1, 0x04,
298 -1, 0x02, 0x05, -1,
299 -1, -1, -1, 0x06};
300 static u_char jazz16_drq_conf[8] = {
301 -1, 0x01, -1, 0x02,
302 -1, 0x03, -1, 0x04};
303
304 bus_space_tag_t iot = sc->sc_iot;
305 bus_space_handle_t ioh;
306
307 sbversion(sc);
308
309 DPRINTF(("jazz16 probe\n"));
310
311 if (bus_space_map(iot, JAZZ16_CONFIG_PORT, 1, 0, &ioh)) {
312 DPRINTF(("bus map failed\n"));
313 return;
314 }
315
316 if (jazz16_drq_conf[sc->sc_drq8] == (u_char)-1 ||
317 jazz16_irq_conf[sc->sc_irq] == (u_char)-1) {
318 DPRINTF(("drq/irq check failed\n"));
319 goto done; /* give up, we can't do it. */
320 }
321
322 bus_space_write_1(iot, ioh, 0, JAZZ16_WAKEUP);
323 delay(10000); /* delay 10 ms */
324 bus_space_write_1(iot, ioh, 0, JAZZ16_SETBASE);
325 bus_space_write_1(iot, ioh, 0, sc->sc_iobase & 0x70);
326
327 if (sbdsp_reset(sc) < 0) {
328 DPRINTF(("sbdsp_reset check failed\n"));
329 goto done; /* XXX? what else could we do? */
330 }
331
332 if (sbdsp_wdsp(sc, JAZZ16_READ_VER)) {
333 DPRINTF(("read16 setup failed\n"));
334 goto done;
335 }
336
337 if (sbdsp_rdsp(sc) != JAZZ16_VER_JAZZ) {
338 DPRINTF(("read16 failed\n"));
339 goto done;
340 }
341
342 /* XXX set both 8 & 16-bit drq to same channel, it works fine. */
343 sc->sc_drq16 = sc->sc_drq8;
344 if (sbdsp_wdsp(sc, JAZZ16_SET_DMAINTR) ||
345 sbdsp_wdsp(sc, (jazz16_drq_conf[sc->sc_drq16] << 4) |
346 jazz16_drq_conf[sc->sc_drq8]) ||
347 sbdsp_wdsp(sc, jazz16_irq_conf[sc->sc_irq])) {
348 DPRINTF(("sbdsp: can't write jazz16 probe stuff\n"));
349 } else {
350 DPRINTF(("jazz16 detected!\n"));
351 sc->sc_model = SB_JAZZ;
352 sc->sc_mixer_model = SBM_CT1345; /* XXX really? */
353 }
354
355 done:
356 bus_space_unmap(iot, ioh, 1);
357 }
358
359 /*
360 * Attach hardware to driver, attach hardware driver to audio
361 * pseudo-device driver .
362 */
363 void
364 sbdsp_attach(sc)
365 struct sbdsp_softc *sc;
366 {
367 struct audio_params pparams, rparams;
368 int i;
369 u_int v;
370
371 pparams = audio_default;
372 rparams = audio_default;
373 sbdsp_set_params(sc, AUMODE_RECORD|AUMODE_PLAY, 0, &pparams, &rparams);
374
375 sbdsp_set_in_ports(sc, 1 << SB_MIC_VOL);
376
377 if (sc->sc_mixer_model != SBM_NONE) {
378 /* Reset the mixer.*/
379 sbdsp_mix_write(sc, SBP_MIX_RESET, SBP_MIX_RESET);
380 /* And set our own default values */
381 for (i = 0; i < SB_NDEVS; i++) {
382 switch(i) {
383 case SB_MIC_VOL:
384 case SB_LINE_IN_VOL:
385 v = 0;
386 break;
387 case SB_BASS:
388 case SB_TREBLE:
389 v = SB_ADJUST_GAIN(sc, AUDIO_MAX_GAIN / 2);
390 break;
391 case SB_CD_IN_MUTE:
392 case SB_MIC_IN_MUTE:
393 case SB_LINE_IN_MUTE:
394 case SB_MIDI_IN_MUTE:
395 case SB_CD_SWAP:
396 case SB_MIC_SWAP:
397 case SB_LINE_SWAP:
398 case SB_MIDI_SWAP:
399 case SB_CD_OUT_MUTE:
400 case SB_MIC_OUT_MUTE:
401 case SB_LINE_OUT_MUTE:
402 v = 0;
403 break;
404 default:
405 v = SB_ADJUST_GAIN(sc, AUDIO_MAX_GAIN / 2);
406 break;
407 }
408 sc->gain[i][SB_LEFT] = sc->gain[i][SB_RIGHT] = v;
409 sbdsp_set_mixer_gain(sc, i);
410 }
411 sc->in_filter = 0; /* no filters turned on, please */
412 }
413
414 printf(": dsp v%d.%02d%s\n",
415 SBVER_MAJOR(sc->sc_version), SBVER_MINOR(sc->sc_version),
416 sc->sc_model == SB_JAZZ ? ": <Jazz16>" : "");
417
418 sc->sc_fullduplex = ISSB16CLASS(sc) &&
419 sc->sc_drq8 != -1 && sc->sc_drq16 != -1 &&
420 sc->sc_drq8 != sc->sc_drq16;
421 }
422
423 void
424 sbdsp_mix_write(sc, mixerport, val)
425 struct sbdsp_softc *sc;
426 int mixerport;
427 int val;
428 {
429 bus_space_tag_t iot = sc->sc_iot;
430 bus_space_handle_t ioh = sc->sc_ioh;
431 int s;
432
433 s = splaudio();
434 bus_space_write_1(iot, ioh, SBP_MIXER_ADDR, mixerport);
435 delay(20);
436 bus_space_write_1(iot, ioh, SBP_MIXER_DATA, val);
437 delay(30);
438 splx(s);
439 }
440
441 int
442 sbdsp_mix_read(sc, mixerport)
443 struct sbdsp_softc *sc;
444 int mixerport;
445 {
446 bus_space_tag_t iot = sc->sc_iot;
447 bus_space_handle_t ioh = sc->sc_ioh;
448 int val;
449 int s;
450
451 s = splaudio();
452 bus_space_write_1(iot, ioh, SBP_MIXER_ADDR, mixerport);
453 delay(20);
454 val = bus_space_read_1(iot, ioh, SBP_MIXER_DATA);
455 delay(30);
456 splx(s);
457 return val;
458 }
459
460 /*
461 * Various routines to interface to higher level audio driver
462 */
463
464 int
465 sbdsp_query_encoding(addr, fp)
466 void *addr;
467 struct audio_encoding *fp;
468 {
469 struct sbdsp_softc *sc = addr;
470 int emul;
471
472 emul = ISSB16CLASS(sc) ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
473
474 switch (fp->index) {
475 case 0:
476 strcpy(fp->name, AudioEulinear);
477 fp->encoding = AUDIO_ENCODING_ULINEAR;
478 fp->precision = 8;
479 fp->flags = 0;
480 return 0;
481 case 1:
482 strcpy(fp->name, AudioEmulaw);
483 fp->encoding = AUDIO_ENCODING_ULAW;
484 fp->precision = 8;
485 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
486 return 0;
487 case 2:
488 strcpy(fp->name, AudioEalaw);
489 fp->encoding = AUDIO_ENCODING_ALAW;
490 fp->precision = 8;
491 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
492 return 0;
493 case 3:
494 strcpy(fp->name, AudioEslinear);
495 fp->encoding = AUDIO_ENCODING_SLINEAR;
496 fp->precision = 8;
497 fp->flags = emul;
498 return 0;
499 }
500 if (!ISSB16CLASS(sc) && sc->sc_model != SB_JAZZ)
501 return EINVAL;
502
503 switch(fp->index) {
504 case 4:
505 strcpy(fp->name, AudioEslinear_le);
506 fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
507 fp->precision = 16;
508 fp->flags = 0;
509 return 0;
510 case 5:
511 strcpy(fp->name, AudioEulinear_le);
512 fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
513 fp->precision = 16;
514 fp->flags = emul;
515 return 0;
516 case 6:
517 strcpy(fp->name, AudioEslinear_be);
518 fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
519 fp->precision = 16;
520 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
521 return 0;
522 case 7:
523 strcpy(fp->name, AudioEulinear_be);
524 fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
525 fp->precision = 16;
526 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
527 return 0;
528 default:
529 return EINVAL;
530 }
531 return 0;
532 }
533
534 int
535 sbdsp_set_params(addr, setmode, usemode, play, rec)
536 void *addr;
537 int setmode, usemode;
538 struct audio_params *play, *rec;
539 {
540 struct sbdsp_softc *sc = addr;
541 struct sbmode *m;
542 u_int rate, tc, bmode;
543 void (*swcode) __P((void *, u_char *buf, int cnt));
544 int factor;
545 int model;
546 int chan;
547 struct audio_params *p;
548 int mode;
549
550 if (sc->sc_open == SB_OPEN_MIDI)
551 return EBUSY;
552
553 /* Later models work like SB16. */
554 model = min(sc->sc_model, SB_16);
555
556 /*
557 * Prior to the SB16, we have only one clock, so make the sample
558 * rates match.
559 */
560 if (!ISSB16CLASS(sc) &&
561 play->sample_rate != rec->sample_rate &&
562 usemode == (AUMODE_PLAY | AUMODE_RECORD)) {
563 if (setmode == AUMODE_PLAY) {
564 rec->sample_rate = play->sample_rate;
565 setmode |= AUMODE_RECORD;
566 } else if (setmode == AUMODE_RECORD) {
567 play->sample_rate = rec->sample_rate;
568 setmode |= AUMODE_PLAY;
569 } else
570 return (EINVAL);
571 }
572
573 /* Set first record info, then play info */
574 for (mode = AUMODE_RECORD; mode != -1;
575 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
576 if ((setmode & mode) == 0)
577 continue;
578
579 p = mode == AUMODE_PLAY ? play : rec;
580 /* Locate proper commands */
581 for (m = mode == AUMODE_PLAY ? sbpmodes : sbrmodes;
582 m->model != -1; m++) {
583 if (model == m->model &&
584 p->channels == m->channels &&
585 p->precision == m->precision &&
586 p->sample_rate >= m->lowrate &&
587 p->sample_rate <= m->highrate)
588 break;
589 }
590 if (m->model == -1)
591 return EINVAL;
592 rate = p->sample_rate;
593 swcode = 0;
594 factor = 1;
595 tc = 1;
596 bmode = -1;
597 if (model == SB_16) {
598 switch (p->encoding) {
599 case AUDIO_ENCODING_SLINEAR_BE:
600 if (p->precision == 16)
601 swcode = swap_bytes;
602 /* fall into */
603 case AUDIO_ENCODING_SLINEAR_LE:
604 bmode = SB_BMODE_SIGNED;
605 break;
606 case AUDIO_ENCODING_ULINEAR_BE:
607 if (p->precision == 16)
608 swcode = swap_bytes;
609 /* fall into */
610 case AUDIO_ENCODING_ULINEAR_LE:
611 bmode = SB_BMODE_UNSIGNED;
612 break;
613 case AUDIO_ENCODING_ULAW:
614 if (mode == AUMODE_PLAY) {
615 swcode = mulaw_to_ulinear16_le;
616 factor = 2;
617 m = &sbpmodes[PLAY16];
618 } else
619 swcode = ulinear8_to_mulaw;
620 bmode = SB_BMODE_UNSIGNED;
621 break;
622 case AUDIO_ENCODING_ALAW:
623 if (mode == AUMODE_PLAY) {
624 swcode = alaw_to_ulinear16_le;
625 factor = 2;
626 m = &sbpmodes[PLAY16];
627 } else
628 swcode = ulinear8_to_alaw;
629 bmode = SB_BMODE_UNSIGNED;
630 break;
631 default:
632 return EINVAL;
633 }
634 if (p->channels == 2)
635 bmode |= SB_BMODE_STEREO;
636 } else if (m->model == SB_JAZZ && m->precision == 16) {
637 switch (p->encoding) {
638 case AUDIO_ENCODING_SLINEAR_LE:
639 break;
640 case AUDIO_ENCODING_ULINEAR_LE:
641 swcode = change_sign16_le;
642 break;
643 case AUDIO_ENCODING_SLINEAR_BE:
644 swcode = swap_bytes;
645 break;
646 case AUDIO_ENCODING_ULINEAR_BE:
647 swcode = mode == AUMODE_PLAY ?
648 swap_bytes_change_sign16_le :
649 change_sign16_swap_bytes_le;
650 break;
651 case AUDIO_ENCODING_ULAW:
652 swcode = mode == AUMODE_PLAY ?
653 mulaw_to_ulinear8 : ulinear8_to_mulaw;
654 break;
655 case AUDIO_ENCODING_ALAW:
656 swcode = mode == AUMODE_PLAY ?
657 alaw_to_ulinear8 : ulinear8_to_alaw;
658 break;
659 default:
660 return EINVAL;
661 }
662 tc = SB_RATE_TO_TC(p->sample_rate * p->channels);
663 p->sample_rate = SB_TC_TO_RATE(tc) / p->channels;
664 } else {
665 switch (p->encoding) {
666 case AUDIO_ENCODING_SLINEAR_BE:
667 case AUDIO_ENCODING_SLINEAR_LE:
668 swcode = change_sign8;
669 break;
670 case AUDIO_ENCODING_ULINEAR_BE:
671 case AUDIO_ENCODING_ULINEAR_LE:
672 break;
673 case AUDIO_ENCODING_ULAW:
674 swcode = mode == AUMODE_PLAY ?
675 mulaw_to_ulinear8 : ulinear8_to_mulaw;
676 break;
677 case AUDIO_ENCODING_ALAW:
678 swcode = mode == AUMODE_PLAY ?
679 alaw_to_ulinear8 : ulinear8_to_alaw;
680 break;
681 default:
682 return EINVAL;
683 }
684 tc = SB_RATE_TO_TC(p->sample_rate * p->channels);
685 p->sample_rate = SB_TC_TO_RATE(tc) / p->channels;
686 }
687
688 chan = m->precision == 16 ? sc->sc_drq16 : sc->sc_drq8;
689 if (mode == AUMODE_PLAY) {
690 sc->sc_o.rate = rate;
691 sc->sc_o.tc = tc;
692 sc->sc_o.modep = m;
693 sc->sc_o.bmode = bmode;
694 sc->sc_o.dmachan = chan;
695 } else {
696 sc->sc_i.rate = rate;
697 sc->sc_i.tc = tc;
698 sc->sc_i.modep = m;
699 sc->sc_i.bmode = bmode;
700 sc->sc_i.dmachan = chan;
701 }
702
703 p->sw_code = swcode;
704 p->factor = factor;
705 DPRINTF(("sbdsp_set_params: model=%d, mode=%d, rate=%ld, prec=%d, chan=%d, enc=%d -> tc=%02x, cmd=%02x, bmode=%02x, cmdchan=%02x, swcode=%p, factor=%d\n",
706 sc->sc_model, mode, p->sample_rate, p->precision, p->channels,
707 p->encoding, tc, m->cmd, bmode, m->cmdchan, swcode, factor));
708
709 }
710
711 if (sc->sc_fullduplex &&
712 usemode == (AUMODE_PLAY | AUMODE_RECORD) &&
713 sc->sc_i.dmachan == sc->sc_o.dmachan) {
714 DPRINTF(("sbdsp_set_params: fd=%d, usemode=%d, idma=%d, odma=%d\n", sc->sc_fullduplex, usemode, sc->sc_i.dmachan, sc->sc_o.dmachan));
715 if (sc->sc_o.dmachan == sc->sc_drq8) {
716 /* Use 16 bit DMA for playing by expanding the samples. */
717 play->sw_code = linear8_to_linear16_le;
718 play->factor = 2;
719 sc->sc_o.modep = &sbpmodes[PLAY16];
720 sc->sc_o.dmachan = sc->sc_drq16;
721 } else {
722 return EINVAL;
723 }
724 }
725 DPRINTF(("sbdsp_set_params ichan=%d, ochan=%d\n",
726 sc->sc_i.dmachan, sc->sc_o.dmachan));
727
728 return (0);
729 }
730
731 void
732 sbdsp_set_ifilter(addr, which)
733 void *addr;
734 int which;
735 {
736 struct sbdsp_softc *sc = addr;
737 int mixval;
738
739 mixval = sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_IFILTER_MASK;
740 switch (which) {
741 case 0:
742 mixval |= SBP_FILTER_OFF;
743 break;
744 case SB_TREBLE:
745 mixval |= SBP_FILTER_ON | SBP_IFILTER_HIGH;
746 break;
747 case SB_BASS:
748 mixval |= SBP_FILTER_ON | SBP_IFILTER_LOW;
749 break;
750 default:
751 return;
752 }
753 sc->in_filter = mixval & SBP_IFILTER_MASK;
754 sbdsp_mix_write(sc, SBP_INFILTER, mixval);
755 }
756
757 int
758 sbdsp_get_ifilter(addr)
759 void *addr;
760 {
761 struct sbdsp_softc *sc = addr;
762
763 sc->in_filter =
764 sbdsp_mix_read(sc, SBP_INFILTER) & SBP_IFILTER_MASK;
765 switch (sc->in_filter) {
766 case SBP_FILTER_ON|SBP_IFILTER_HIGH:
767 return SB_TREBLE;
768 case SBP_FILTER_ON|SBP_IFILTER_LOW:
769 return SB_BASS;
770 default:
771 return 0;
772 }
773 }
774
775 int
776 sbdsp_set_in_ports(sc, mask)
777 struct sbdsp_softc *sc;
778 int mask;
779 {
780 int bitsl, bitsr;
781 int sbport;
782
783 if (sc->sc_open == SB_OPEN_MIDI)
784 return EBUSY;
785
786 DPRINTF(("sbdsp_set_in_ports: model=%d, mask=%x\n",
787 sc->sc_mixer_model, mask));
788
789 switch(sc->sc_mixer_model) {
790 case SBM_NONE:
791 return EINVAL;
792 case SBM_CT1335:
793 if (mask != (1 << SB_MIC_VOL))
794 return EINVAL;
795 break;
796 case SBM_CT1345:
797 switch (mask) {
798 case 1 << SB_MIC_VOL:
799 sbport = SBP_FROM_MIC;
800 break;
801 case 1 << SB_LINE_IN_VOL:
802 sbport = SBP_FROM_LINE;
803 break;
804 case 1 << SB_CD_VOL:
805 sbport = SBP_FROM_CD;
806 break;
807 default:
808 return (EINVAL);
809 }
810 sbdsp_mix_write(sc, SBP_RECORD_SOURCE, sbport | sc->in_filter);
811 break;
812 case SBM_CT1XX5:
813 case SBM_CT1745:
814 if (mask & ~((1<<SB_MIDI_VOL) | (1<<SB_LINE_IN_VOL) |
815 (1<<SB_CD_VOL) | (1<<SB_MIC_VOL)))
816 return EINVAL;
817 bitsr = 0;
818 if (mask & (1<<SB_MIDI_VOL)) bitsr |= SBP_MIDI_SRC_R;
819 if (mask & (1<<SB_LINE_IN_VOL)) bitsr |= SBP_LINE_SRC_R;
820 if (mask & (1<<SB_CD_VOL)) bitsr |= SBP_CD_SRC_R;
821 bitsl = SB_SRC_R_TO_L(bitsr);
822 if (mask & (1<<SB_MIC_VOL)) {
823 bitsl |= SBP_MIC_SRC;
824 bitsr |= SBP_MIC_SRC;
825 }
826 sbdsp_mix_write(sc, SBP_RECORD_SOURCE_L, bitsl);
827 sbdsp_mix_write(sc, SBP_RECORD_SOURCE_R, bitsr);
828 break;
829 }
830 sc->in_mask = mask;
831
832 return 0;
833 }
834
835 int
836 sbdsp_speaker_ctl(addr, newstate)
837 void *addr;
838 int newstate;
839 {
840 struct sbdsp_softc *sc = addr;
841
842 if (sc->sc_open == SB_OPEN_MIDI)
843 return EBUSY;
844
845 if ((newstate == SPKR_ON) &&
846 (sc->spkr_state == SPKR_OFF)) {
847 sbdsp_spkron(sc);
848 sc->spkr_state = SPKR_ON;
849 }
850 if ((newstate == SPKR_OFF) &&
851 (sc->spkr_state == SPKR_ON)) {
852 sbdsp_spkroff(sc);
853 sc->spkr_state = SPKR_OFF;
854 }
855 return 0;
856 }
857
858 int
859 sbdsp_round_blocksize(addr, blk)
860 void *addr;
861 int blk;
862 {
863 return blk & -4; /* round to biggest sample size */
864 }
865
866 int
867 sbdsp_open(addr, flags)
868 void *addr;
869 int flags;
870 {
871 struct sbdsp_softc *sc = addr;
872 int error, state;
873
874 DPRINTF(("sbdsp_open: sc=%p\n", sc));
875
876 if (sc->sc_open != SB_CLOSED)
877 return (EBUSY);
878 sc->sc_open = SB_OPEN_AUDIO;
879 sc->sc_openflags = flags;
880 state = 0;
881
882 if (sc->sc_drq8 != -1) {
883 error = isa_dmamap_create(sc->sc_ic, sc->sc_drq8,
884 MAX_ISADMA, BUS_DMA_NOWAIT);
885 if (error) {
886 printf("%s: can't create map for drq %d\n",
887 sc->sc_dev.dv_xname, sc->sc_drq8);
888 goto bad;
889 }
890 state |= 1;
891 }
892 if (sc->sc_drq16 != -1 && sc->sc_drq16 != sc->sc_drq8) {
893 error = isa_dmamap_create(sc->sc_ic, sc->sc_drq16,
894 MAX_ISADMA, BUS_DMA_NOWAIT);
895 if (error) {
896 printf("%s: can't create map for drq %d\n",
897 sc->sc_dev.dv_xname, sc->sc_drq16);
898 goto bad;
899 }
900 state |= 2;
901 }
902
903 if (sbdsp_reset(sc) != 0) {
904 error = EIO;
905 goto bad;
906 }
907
908 if (ISSBPRO(sc) &&
909 sbdsp_wdsp(sc, SB_DSP_RECORD_MONO) < 0) {
910 DPRINTF(("sbdsp_open: can't set mono mode\n"));
911 /* we'll readjust when it's time for DMA. */
912 }
913
914 /*
915 * Leave most things as they were; users must change things if
916 * the previous process didn't leave it they way they wanted.
917 * Looked at another way, it's easy to set up a configuration
918 * in one program and leave it for another to inherit.
919 */
920 DPRINTF(("sbdsp_open: opened\n"));
921
922 return (0);
923
924 bad:
925 if (state & 1)
926 isa_dmamap_destroy(sc->sc_ic, sc->sc_drq8);
927 if (state & 2)
928 isa_dmamap_destroy(sc->sc_ic, sc->sc_drq16);
929
930 sc->sc_open = SB_CLOSED;
931 return (error);
932 }
933
934 void
935 sbdsp_close(addr)
936 void *addr;
937 {
938 struct sbdsp_softc *sc = addr;
939
940 DPRINTF(("sbdsp_close: sc=%p\n", sc));
941
942 sbdsp_spkroff(sc);
943 sc->spkr_state = SPKR_OFF;
944
945 sbdsp_halt_output(sc);
946 sbdsp_halt_input(sc);
947
948 sc->sc_intr8 = 0;
949 sc->sc_intr16 = 0;
950
951 if (sc->sc_drq8 != -1)
952 isa_dmamap_destroy(sc->sc_ic, sc->sc_drq8);
953 if (sc->sc_drq16 != -1 && sc->sc_drq16 != sc->sc_drq8)
954 isa_dmamap_destroy(sc->sc_ic, sc->sc_drq16);
955
956 sc->sc_open = SB_CLOSED;
957 DPRINTF(("sbdsp_close: closed\n"));
958 }
959
960 /*
961 * Lower-level routines
962 */
963
964 /*
965 * Reset the card.
966 * Return non-zero if the card isn't detected.
967 */
968 int
969 sbdsp_reset(sc)
970 struct sbdsp_softc *sc;
971 {
972 bus_space_tag_t iot = sc->sc_iot;
973 bus_space_handle_t ioh = sc->sc_ioh;
974
975 sc->sc_intr8 = 0;
976 sc->sc_intr16 = 0;
977 sc->sc_intrm = 0;
978
979 /*
980 * See SBK, section 11.3.
981 * We pulse a reset signal into the card.
982 * Gee, what a brilliant hardware design.
983 */
984 bus_space_write_1(iot, ioh, SBP_DSP_RESET, 1);
985 delay(10);
986 bus_space_write_1(iot, ioh, SBP_DSP_RESET, 0);
987 delay(30);
988 if (sbdsp_rdsp(sc) != SB_MAGIC)
989 return -1;
990
991 return 0;
992 }
993
994 /*
995 * Write a byte to the dsp.
996 * We are at the mercy of the card as we use a
997 * polling loop and wait until it can take the byte.
998 */
999 int
1000 sbdsp_wdsp(sc, v)
1001 struct sbdsp_softc *sc;
1002 int v;
1003 {
1004 bus_space_tag_t iot = sc->sc_iot;
1005 bus_space_handle_t ioh = sc->sc_ioh;
1006 int i;
1007 u_char x;
1008
1009 for (i = SBDSP_NPOLL; --i >= 0; ) {
1010 x = bus_space_read_1(iot, ioh, SBP_DSP_WSTAT);
1011 delay(10);
1012 if ((x & SB_DSP_BUSY) == 0) {
1013 bus_space_write_1(iot, ioh, SBP_DSP_WRITE, v);
1014 delay(10);
1015 return 0;
1016 }
1017 }
1018 ++sberr.wdsp;
1019 return -1;
1020 }
1021
1022 /*
1023 * Read a byte from the DSP, using polling.
1024 */
1025 int
1026 sbdsp_rdsp(sc)
1027 struct sbdsp_softc *sc;
1028 {
1029 bus_space_tag_t iot = sc->sc_iot;
1030 bus_space_handle_t ioh = sc->sc_ioh;
1031 int i;
1032 u_char x;
1033
1034 for (i = SBDSP_NPOLL; --i >= 0; ) {
1035 x = bus_space_read_1(iot, ioh, SBP_DSP_RSTAT);
1036 delay(10);
1037 if (x & SB_DSP_READY) {
1038 x = bus_space_read_1(iot, ioh, SBP_DSP_READ);
1039 delay(10);
1040 return x;
1041 }
1042 }
1043 ++sberr.rdsp;
1044 return -1;
1045 }
1046
1047 /*
1048 * Doing certain things (like toggling the speaker) make
1049 * the SB hardware go away for a while, so pause a little.
1050 */
1051 void
1052 sbdsp_to(arg)
1053 void *arg;
1054 {
1055 wakeup(arg);
1056 }
1057
1058 void
1059 sbdsp_pause(sc)
1060 struct sbdsp_softc *sc;
1061 {
1062 extern int hz;
1063
1064 timeout(sbdsp_to, sbdsp_to, hz/8);
1065 (void)tsleep(sbdsp_to, PWAIT, "sbpause", 0);
1066 }
1067
1068 /*
1069 * Turn on the speaker. The SBK documention says this operation
1070 * can take up to 1/10 of a second. Higher level layers should
1071 * probably let the task sleep for this amount of time after
1072 * calling here. Otherwise, things might not work (because
1073 * sbdsp_wdsp() and sbdsp_rdsp() will probably timeout.)
1074 *
1075 * These engineers had their heads up their ass when
1076 * they designed this card.
1077 */
1078 void
1079 sbdsp_spkron(sc)
1080 struct sbdsp_softc *sc;
1081 {
1082 (void)sbdsp_wdsp(sc, SB_DSP_SPKR_ON);
1083 sbdsp_pause(sc);
1084 }
1085
1086 /*
1087 * Turn off the speaker; see comment above.
1088 */
1089 void
1090 sbdsp_spkroff(sc)
1091 struct sbdsp_softc *sc;
1092 {
1093 (void)sbdsp_wdsp(sc, SB_DSP_SPKR_OFF);
1094 sbdsp_pause(sc);
1095 }
1096
1097 /*
1098 * Read the version number out of the card.
1099 * Store version information in the softc.
1100 */
1101 void
1102 sbversion(sc)
1103 struct sbdsp_softc *sc;
1104 {
1105 int v;
1106
1107 sc->sc_model = SB_UNK;
1108 sc->sc_version = 0;
1109 if (sbdsp_wdsp(sc, SB_DSP_VERSION) < 0)
1110 return;
1111 v = sbdsp_rdsp(sc) << 8;
1112 v |= sbdsp_rdsp(sc);
1113 if (v < 0)
1114 return;
1115 sc->sc_version = v;
1116 switch(SBVER_MAJOR(v)) {
1117 case 1:
1118 sc->sc_mixer_model = SBM_NONE;
1119 sc->sc_model = SB_1;
1120 break;
1121 case 2:
1122 /* Some SB2 have a mixer, some don't. */
1123 sbdsp_mix_write(sc, SBP_1335_MASTER_VOL, 0x04);
1124 sbdsp_mix_write(sc, SBP_1335_MIDI_VOL, 0x06);
1125 /* Check if we can read back the mixer values. */
1126 if ((sbdsp_mix_read(sc, SBP_1335_MASTER_VOL) & 0x0e) == 0x04 &&
1127 (sbdsp_mix_read(sc, SBP_1335_MIDI_VOL) & 0x0e) == 0x06)
1128 sc->sc_mixer_model = SBM_CT1335;
1129 else
1130 sc->sc_mixer_model = SBM_NONE;
1131 if (SBVER_MINOR(v) == 0)
1132 sc->sc_model = SB_20;
1133 else
1134 sc->sc_model = SB_2x;
1135 break;
1136 case 3:
1137 sc->sc_mixer_model = SBM_CT1345;
1138 sc->sc_model = SB_PRO;
1139 break;
1140 case 4:
1141 #if 0
1142 /* XXX This does not work */
1143 /* Most SB16 have a tone controls, but some don't. */
1144 sbdsp_mix_write(sc, SB16P_TREBLE_L, 0x80);
1145 /* Check if we can read back the mixer value. */
1146 if ((sbdsp_mix_read(sc, SB16P_TREBLE_L) & 0xf0) == 0x80)
1147 sc->sc_mixer_model = SBM_CT1745;
1148 else
1149 sc->sc_mixer_model = SBM_CT1XX5;
1150 #else
1151 sc->sc_mixer_model = SBM_CT1745;
1152 #endif
1153 #if 0
1154 /* XXX figure out a good way of determining the model */
1155 /* XXX what about SB_32 */
1156 if (SBVER_MINOR(v) == 16)
1157 sc->sc_model = SB_64;
1158 else
1159 #endif
1160 sc->sc_model = SB_16;
1161 break;
1162 }
1163 }
1164
1165 int
1166 sbdsp_set_timeconst(sc, tc)
1167 struct sbdsp_softc *sc;
1168 int tc;
1169 {
1170 DPRINTF(("sbdsp_set_timeconst: sc=%p tc=%d\n", sc, tc));
1171
1172 if (sbdsp_wdsp(sc, SB_DSP_TIMECONST) < 0 ||
1173 sbdsp_wdsp(sc, tc) < 0)
1174 return EIO;
1175
1176 return 0;
1177 }
1178
1179 int
1180 sbdsp16_set_rate(sc, cmd, rate)
1181 struct sbdsp_softc *sc;
1182 int cmd, rate;
1183 {
1184 DPRINTF(("sbdsp16_set_rate: sc=%p cmd=0x%02x rate=%d\n", sc, cmd, rate));
1185
1186 if (sbdsp_wdsp(sc, cmd) < 0 ||
1187 sbdsp_wdsp(sc, rate >> 8) < 0 ||
1188 sbdsp_wdsp(sc, rate) < 0)
1189 return EIO;
1190 return 0;
1191 }
1192
1193 int
1194 sbdsp_trigger_input(addr, start, end, blksize, intr, arg, param)
1195 void *addr;
1196 void *start, *end;
1197 int blksize;
1198 void (*intr) __P((void *));
1199 void *arg;
1200 struct audio_params *param;
1201 {
1202 struct sbdsp_softc *sc = addr;
1203 int stereo = param->channels == 2;
1204 int width = param->precision * param->factor;
1205 int filter;
1206
1207 #ifdef DIAGNOSTIC
1208 if (stereo && (blksize & 1)) {
1209 DPRINTF(("stereo record odd bytes (%d)\n", blksize));
1210 return (EIO);
1211 }
1212 if (sc->sc_i.run != SB_NOTRUNNING)
1213 printf("sbdsp_trigger_input: already running\n");
1214 #endif
1215
1216 sc->sc_intrr = intr;
1217 sc->sc_argr = arg;
1218
1219 if (width == 8) {
1220 #ifdef DIAGNOSTIC
1221 if (sc->sc_i.dmachan != sc->sc_drq8) {
1222 printf("sbdsp_trigger_input: width=%d bad chan %d\n",
1223 width, sc->sc_i.dmachan);
1224 return (EIO);
1225 }
1226 #endif
1227 sc->sc_intr8 = sbdsp_block_input;
1228 } else {
1229 #ifdef DIAGNOSTIC
1230 if (sc->sc_i.dmachan != sc->sc_drq16) {
1231 printf("sbdsp_trigger_input: width=%d bad chan %d\n",
1232 width, sc->sc_i.dmachan);
1233 return (EIO);
1234 }
1235 #endif
1236 sc->sc_intr16 = sbdsp_block_input;
1237 }
1238
1239 if ((sc->sc_model == SB_JAZZ) ? (sc->sc_i.dmachan > 3) : (width == 16))
1240 blksize >>= 1;
1241 --blksize;
1242 sc->sc_i.blksize = blksize;
1243
1244 if (ISSBPRO(sc)) {
1245 if (sbdsp_wdsp(sc, sc->sc_i.modep->cmdchan) < 0)
1246 return (EIO);
1247 filter = stereo ? SBP_FILTER_OFF : sc->in_filter;
1248 sbdsp_mix_write(sc, SBP_INFILTER,
1249 (sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_IFILTER_MASK) |
1250 filter);
1251 }
1252
1253 if (ISSB16CLASS(sc)) {
1254 if (sbdsp16_set_rate(sc, SB_DSP16_INPUTRATE, sc->sc_i.rate)) {
1255 DPRINTF(("sbdsp_trigger_input: rate=%d set failed\n",
1256 sc->sc_i.rate));
1257 return (EIO);
1258 }
1259 } else {
1260 if (sbdsp_set_timeconst(sc, sc->sc_i.tc)) {
1261 DPRINTF(("sbdsp_trigger_input: tc=%d set failed\n",
1262 sc->sc_i.rate));
1263 return (EIO);
1264 }
1265 }
1266
1267 DPRINTF(("sbdsp: dma start loop input start=%p end=%p chan=%d\n",
1268 start, end, sc->sc_i.dmachan));
1269 isa_dmastart(sc->sc_ic, sc->sc_i.dmachan, start,
1270 (char *)end - (char *)start, NULL,
1271 DMAMODE_READ | DMAMODE_LOOPDEMAND, BUS_DMA_NOWAIT);
1272
1273 return sbdsp_block_input(addr);
1274 }
1275
1276 int
1277 sbdsp_block_input(addr)
1278 void *addr;
1279 {
1280 struct sbdsp_softc *sc = addr;
1281 int cc = sc->sc_i.blksize;
1282
1283 DPRINTFN(2, ("sbdsp_block_input: sc=%p cc=%d\n", addr, cc));
1284
1285 if (sc->sc_i.run != SB_NOTRUNNING)
1286 sc->sc_intrr(sc->sc_argr);
1287
1288 if (sc->sc_model == SB_1) {
1289 /* Non-looping mode, start DMA */
1290 if (sbdsp_wdsp(sc, sc->sc_i.modep->cmd) < 0 ||
1291 sbdsp_wdsp(sc, cc) < 0 ||
1292 sbdsp_wdsp(sc, cc >> 8) < 0) {
1293 DPRINTF(("sbdsp_block_input: SB1 DMA start failed\n"));
1294 return (EIO);
1295 }
1296 sc->sc_i.run = SB_RUNNING;
1297 } else if (sc->sc_i.run == SB_NOTRUNNING) {
1298 /* Initialize looping PCM */
1299 if (ISSB16CLASS(sc)) {
1300 DPRINTFN(3, ("sbdsp16 input command cmd=0x%02x bmode=0x%02x cc=%d\n",
1301 sc->sc_i.modep->cmd, sc->sc_i.bmode, cc));
1302 if (sbdsp_wdsp(sc, sc->sc_i.modep->cmd) < 0 ||
1303 sbdsp_wdsp(sc, sc->sc_i.bmode) < 0 ||
1304 sbdsp_wdsp(sc, cc) < 0 ||
1305 sbdsp_wdsp(sc, cc >> 8) < 0) {
1306 DPRINTF(("sbdsp_block_input: SB16 DMA start failed\n"));
1307 return (EIO);
1308 }
1309 } else {
1310 DPRINTF(("sbdsp_block_input: set blocksize=%d\n", cc));
1311 if (sbdsp_wdsp(sc, SB_DSP_BLOCKSIZE) < 0 ||
1312 sbdsp_wdsp(sc, cc) < 0 ||
1313 sbdsp_wdsp(sc, cc >> 8) < 0) {
1314 DPRINTF(("sbdsp_block_input: SB2 DMA blocksize failed\n"));
1315 return (EIO);
1316 }
1317 if (sbdsp_wdsp(sc, sc->sc_i.modep->cmd) < 0) {
1318 DPRINTF(("sbdsp_block_input: SB2 DMA start failed\n"));
1319 return (EIO);
1320 }
1321 }
1322 sc->sc_i.run = SB_LOOPING;
1323 }
1324
1325 return (0);
1326 }
1327
1328 int
1329 sbdsp_trigger_output(addr, start, end, blksize, intr, arg, param)
1330 void *addr;
1331 void *start, *end;
1332 int blksize;
1333 void (*intr) __P((void *));
1334 void *arg;
1335 struct audio_params *param;
1336 {
1337 struct sbdsp_softc *sc = addr;
1338 int stereo = param->channels == 2;
1339 int width = param->precision * param->factor;
1340 int cmd;
1341
1342 #ifdef DIAGNOSTIC
1343 if (stereo && (blksize & 1)) {
1344 DPRINTF(("stereo playback odd bytes (%d)\n", blksize));
1345 return (EIO);
1346 }
1347 if (sc->sc_o.run != SB_NOTRUNNING)
1348 printf("sbdsp_trigger_output: already running\n");
1349 #endif
1350
1351 sc->sc_intrp = intr;
1352 sc->sc_argp = arg;
1353
1354 if (width == 8) {
1355 #ifdef DIAGNOSTIC
1356 if (sc->sc_o.dmachan != sc->sc_drq8) {
1357 printf("sbdsp_trigger_output: width=%d bad chan %d\n",
1358 width, sc->sc_o.dmachan);
1359 return (EIO);
1360 }
1361 #endif
1362 sc->sc_intr8 = sbdsp_block_output;
1363 } else {
1364 #ifdef DIAGNOSTIC
1365 if (sc->sc_o.dmachan != sc->sc_drq16) {
1366 printf("sbdsp_trigger_output: width=%d bad chan %d\n",
1367 width, sc->sc_o.dmachan);
1368 return (EIO);
1369 }
1370 #endif
1371 sc->sc_intr16 = sbdsp_block_output;
1372 }
1373
1374 if ((sc->sc_model == SB_JAZZ) ? (sc->sc_o.dmachan > 3) : (width == 16))
1375 blksize >>= 1;
1376 --blksize;
1377 sc->sc_o.blksize = blksize;
1378
1379 if (ISSBPRO(sc)) {
1380 /* make sure we re-set stereo mixer bit when we start output. */
1381 sbdsp_mix_write(sc, SBP_STEREO,
1382 (sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK) |
1383 (stereo ? SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO));
1384 cmd = sc->sc_o.modep->cmdchan;
1385 if (cmd && sbdsp_wdsp(sc, cmd) < 0)
1386 return (EIO);
1387 }
1388
1389 if (ISSB16CLASS(sc)) {
1390 if (sbdsp16_set_rate(sc, SB_DSP16_OUTPUTRATE, sc->sc_o.rate)) {
1391 DPRINTF(("sbdsp_trigger_output: rate=%d set failed\n",
1392 sc->sc_o.rate));
1393 return (EIO);
1394 }
1395 } else {
1396 if (sbdsp_set_timeconst(sc, sc->sc_o.tc)) {
1397 DPRINTF(("sbdsp_trigger_output: tc=%d set failed\n",
1398 sc->sc_o.rate));
1399 return (EIO);
1400 }
1401 }
1402
1403 DPRINTF(("sbdsp: dma start loop output start=%p end=%p chan=%d\n",
1404 start, end, sc->sc_o.dmachan));
1405 isa_dmastart(sc->sc_ic, sc->sc_o.dmachan, start,
1406 (char *)end - (char *)start, NULL,
1407 DMAMODE_WRITE | DMAMODE_LOOPDEMAND, BUS_DMA_NOWAIT);
1408
1409 return sbdsp_block_output(addr);
1410 }
1411
1412 int
1413 sbdsp_block_output(addr)
1414 void *addr;
1415 {
1416 struct sbdsp_softc *sc = addr;
1417 int cc = sc->sc_o.blksize;
1418
1419 DPRINTFN(2, ("sbdsp_block_output: sc=%p cc=%d\n", addr, cc));
1420
1421 if (sc->sc_o.run != SB_NOTRUNNING)
1422 sc->sc_intrp(sc->sc_argp);
1423
1424 if (sc->sc_model == SB_1) {
1425 /* Non-looping mode, initialized. Start DMA and PCM */
1426 if (sbdsp_wdsp(sc, sc->sc_o.modep->cmd) < 0 ||
1427 sbdsp_wdsp(sc, cc) < 0 ||
1428 sbdsp_wdsp(sc, cc >> 8) < 0) {
1429 DPRINTF(("sbdsp_block_output: SB1 DMA start failed\n"));
1430 return (EIO);
1431 }
1432 sc->sc_o.run = SB_RUNNING;
1433 } else if (sc->sc_o.run == SB_NOTRUNNING) {
1434 /* Initialize looping PCM */
1435 if (ISSB16CLASS(sc)) {
1436 DPRINTF(("sbdsp_block_output: SB16 cmd=0x%02x bmode=0x%02x cc=%d\n",
1437 sc->sc_o.modep->cmd,sc->sc_o.bmode, cc));
1438 if (sbdsp_wdsp(sc, sc->sc_o.modep->cmd) < 0 ||
1439 sbdsp_wdsp(sc, sc->sc_o.bmode) < 0 ||
1440 sbdsp_wdsp(sc, cc) < 0 ||
1441 sbdsp_wdsp(sc, cc >> 8) < 0) {
1442 DPRINTF(("sbdsp_block_output: SB16 DMA start failed\n"));
1443 return (EIO);
1444 }
1445 } else {
1446 DPRINTF(("sbdsp_block_output: set blocksize=%d\n", cc));
1447 if (sbdsp_wdsp(sc, SB_DSP_BLOCKSIZE) < 0 ||
1448 sbdsp_wdsp(sc, cc) < 0 ||
1449 sbdsp_wdsp(sc, cc >> 8) < 0) {
1450 DPRINTF(("sbdsp_block_output: SB2 DMA blocksize failed\n"));
1451 return (EIO);
1452 }
1453 if (sbdsp_wdsp(sc, sc->sc_o.modep->cmd) < 0) {
1454 DPRINTF(("sbdsp_block_output: SB2 DMA start failed\n"));
1455 return (EIO);
1456 }
1457 }
1458 sc->sc_o.run = SB_LOOPING;
1459 }
1460
1461 return (0);
1462 }
1463
1464 int
1465 sbdsp_halt_output(addr)
1466 void *addr;
1467 {
1468 struct sbdsp_softc *sc = addr;
1469
1470 if (sc->sc_o.run != SB_NOTRUNNING) {
1471 if (sbdsp_wdsp(sc, sc->sc_o.modep->halt) < 0)
1472 printf("sbdsp_halt_output: failed to halt\n");
1473 isa_dmaabort(sc->sc_ic, sc->sc_o.dmachan);
1474 sc->sc_o.run = SB_NOTRUNNING;
1475 }
1476
1477 return (0);
1478 }
1479
1480 int
1481 sbdsp_halt_input(addr)
1482 void *addr;
1483 {
1484 struct sbdsp_softc *sc = addr;
1485
1486 if (sc->sc_i.run != SB_NOTRUNNING) {
1487 if (sbdsp_wdsp(sc, sc->sc_i.modep->halt) < 0)
1488 printf("sbdsp_halt_input: failed to halt\n");
1489 isa_dmaabort(sc->sc_ic, sc->sc_i.dmachan);
1490 sc->sc_i.run = SB_NOTRUNNING;
1491 }
1492
1493 return (0);
1494 }
1495
1496 /*
1497 * Only the DSP unit on the sound blaster generates interrupts.
1498 * There are three cases of interrupt: reception of a midi byte
1499 * (when mode is enabled), completion of dma transmission, or
1500 * completion of a dma reception.
1501 *
1502 * If there is interrupt sharing or a spurious interrupt occurs
1503 * there is no way to distinguish this on an SB2. So if you have
1504 * an SB2 and experience problems, buy an SB16 (it's only $40).
1505 */
1506 int
1507 sbdsp_intr(arg)
1508 void *arg;
1509 {
1510 struct sbdsp_softc *sc = arg;
1511 u_char irq;
1512
1513 DPRINTFN(2, ("sbdsp_intr: intr8=%p, intr16=%p\n",
1514 sc->sc_intr8, sc->sc_intr16));
1515 if (ISSB16CLASS(sc)) {
1516 irq = sbdsp_mix_read(sc, SBP_IRQ_STATUS);
1517 if ((irq & (SBP_IRQ_DMA8 | SBP_IRQ_DMA16 | SBP_IRQ_MPU401)) == 0) {
1518 DPRINTF(("sbdsp_intr: Spurious interrupt 0x%x\n", irq));
1519 return 0;
1520 }
1521 } else {
1522 /* XXXX CHECK FOR INTERRUPT */
1523 irq = SBP_IRQ_DMA8;
1524 }
1525
1526 sc->sc_interrupts++;
1527 delay(10); /* XXX why? */
1528
1529 /* clear interrupt */
1530 if (irq & SBP_IRQ_DMA8) {
1531 bus_space_read_1(sc->sc_iot, sc->sc_ioh, SBP_DSP_IRQACK8);
1532 if (sc->sc_intr8)
1533 sc->sc_intr8(arg);
1534 }
1535 if (irq & SBP_IRQ_DMA16) {
1536 bus_space_read_1(sc->sc_iot, sc->sc_ioh, SBP_DSP_IRQACK16);
1537 if (sc->sc_intr16)
1538 sc->sc_intr16(arg);
1539 }
1540 #if NMPU > 0
1541 if ((irq & SBP_IRQ_MPU401) && sc->sc_mpudev) {
1542 mpu_intr(sc->sc_mpudev);
1543 }
1544 #endif
1545 return 1;
1546 }
1547
1548 /* Like val & mask, but make sure the result is correctly rounded. */
1549 #define MAXVAL 256
1550 static int
1551 sbdsp_adjust(val, mask)
1552 int val, mask;
1553 {
1554 val += (MAXVAL - mask) >> 1;
1555 if (val >= MAXVAL)
1556 val = MAXVAL-1;
1557 return val & mask;
1558 }
1559
1560 void
1561 sbdsp_set_mixer_gain(sc, port)
1562 struct sbdsp_softc *sc;
1563 int port;
1564 {
1565 int src, gain;
1566
1567 switch(sc->sc_mixer_model) {
1568 case SBM_NONE:
1569 return;
1570 case SBM_CT1335:
1571 gain = SB_1335_GAIN(sc->gain[port][SB_LEFT]);
1572 switch(port) {
1573 case SB_MASTER_VOL:
1574 src = SBP_1335_MASTER_VOL;
1575 break;
1576 case SB_MIDI_VOL:
1577 src = SBP_1335_MIDI_VOL;
1578 break;
1579 case SB_CD_VOL:
1580 src = SBP_1335_CD_VOL;
1581 break;
1582 case SB_VOICE_VOL:
1583 src = SBP_1335_VOICE_VOL;
1584 gain = SB_1335_MASTER_GAIN(sc->gain[port][SB_LEFT]);
1585 break;
1586 default:
1587 return;
1588 }
1589 sbdsp_mix_write(sc, src, gain);
1590 break;
1591 case SBM_CT1345:
1592 gain = SB_STEREO_GAIN(sc->gain[port][SB_LEFT],
1593 sc->gain[port][SB_RIGHT]);
1594 switch (port) {
1595 case SB_MIC_VOL:
1596 src = SBP_MIC_VOL;
1597 gain = SB_MIC_GAIN(sc->gain[port][SB_LEFT]);
1598 break;
1599 case SB_MASTER_VOL:
1600 src = SBP_MASTER_VOL;
1601 break;
1602 case SB_LINE_IN_VOL:
1603 src = SBP_LINE_VOL;
1604 break;
1605 case SB_VOICE_VOL:
1606 src = SBP_VOICE_VOL;
1607 break;
1608 case SB_MIDI_VOL:
1609 src = SBP_MIDI_VOL;
1610 break;
1611 case SB_CD_VOL:
1612 src = SBP_CD_VOL;
1613 break;
1614 default:
1615 return;
1616 }
1617 sbdsp_mix_write(sc, src, gain);
1618 break;
1619 case SBM_CT1XX5:
1620 case SBM_CT1745:
1621 switch (port) {
1622 case SB_MIC_VOL:
1623 src = SB16P_MIC_L;
1624 break;
1625 case SB_MASTER_VOL:
1626 src = SB16P_MASTER_L;
1627 break;
1628 case SB_LINE_IN_VOL:
1629 src = SB16P_LINE_L;
1630 break;
1631 case SB_VOICE_VOL:
1632 src = SB16P_VOICE_L;
1633 break;
1634 case SB_MIDI_VOL:
1635 src = SB16P_MIDI_L;
1636 break;
1637 case SB_CD_VOL:
1638 src = SB16P_CD_L;
1639 break;
1640 case SB_INPUT_GAIN:
1641 src = SB16P_INPUT_GAIN_L;
1642 break;
1643 case SB_OUTPUT_GAIN:
1644 src = SB16P_OUTPUT_GAIN_L;
1645 break;
1646 case SB_TREBLE:
1647 src = SB16P_TREBLE_L;
1648 break;
1649 case SB_BASS:
1650 src = SB16P_BASS_L;
1651 break;
1652 case SB_PCSPEAKER:
1653 sbdsp_mix_write(sc, SB16P_PCSPEAKER, sc->gain[port][SB_LEFT]);
1654 return;
1655 default:
1656 return;
1657 }
1658 sbdsp_mix_write(sc, src, sc->gain[port][SB_LEFT]);
1659 sbdsp_mix_write(sc, SB16P_L_TO_R(src), sc->gain[port][SB_RIGHT]);
1660 break;
1661 }
1662 }
1663
1664 int
1665 sbdsp_mixer_set_port(addr, cp)
1666 void *addr;
1667 mixer_ctrl_t *cp;
1668 {
1669 struct sbdsp_softc *sc = addr;
1670 int lgain, rgain;
1671 int mask, bits;
1672 int lmask, rmask, lbits, rbits;
1673 int mute, swap;
1674
1675 if (sc->sc_open == SB_OPEN_MIDI)
1676 return EBUSY;
1677
1678 DPRINTF(("sbdsp_mixer_set_port: port=%d num_channels=%d\n", cp->dev,
1679 cp->un.value.num_channels));
1680
1681 if (sc->sc_mixer_model == SBM_NONE)
1682 return EINVAL;
1683
1684 switch (cp->dev) {
1685 case SB_TREBLE:
1686 case SB_BASS:
1687 if (sc->sc_mixer_model == SBM_CT1345 ||
1688 sc->sc_mixer_model == SBM_CT1XX5) {
1689 if (cp->type != AUDIO_MIXER_ENUM)
1690 return EINVAL;
1691 switch (cp->dev) {
1692 case SB_TREBLE:
1693 sbdsp_set_ifilter(addr, cp->un.ord ? SB_TREBLE : 0);
1694 return 0;
1695 case SB_BASS:
1696 sbdsp_set_ifilter(addr, cp->un.ord ? SB_BASS : 0);
1697 return 0;
1698 }
1699 }
1700 case SB_PCSPEAKER:
1701 case SB_INPUT_GAIN:
1702 case SB_OUTPUT_GAIN:
1703 if (!ISSBM1745(sc))
1704 return EINVAL;
1705 case SB_MIC_VOL:
1706 case SB_LINE_IN_VOL:
1707 if (sc->sc_mixer_model == SBM_CT1335)
1708 return EINVAL;
1709 case SB_VOICE_VOL:
1710 case SB_MIDI_VOL:
1711 case SB_CD_VOL:
1712 case SB_MASTER_VOL:
1713 if (cp->type != AUDIO_MIXER_VALUE)
1714 return EINVAL;
1715
1716 /*
1717 * All the mixer ports are stereo except for the microphone.
1718 * If we get a single-channel gain value passed in, then we
1719 * duplicate it to both left and right channels.
1720 */
1721
1722 switch (cp->dev) {
1723 case SB_MIC_VOL:
1724 if (cp->un.value.num_channels != 1)
1725 return EINVAL;
1726
1727 lgain = rgain = SB_ADJUST_MIC_GAIN(sc,
1728 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1729 break;
1730 case SB_PCSPEAKER:
1731 if (cp->un.value.num_channels != 1)
1732 return EINVAL;
1733 /* fall into */
1734 case SB_INPUT_GAIN:
1735 case SB_OUTPUT_GAIN:
1736 lgain = rgain = SB_ADJUST_2_GAIN(sc,
1737 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1738 break;
1739 default:
1740 switch (cp->un.value.num_channels) {
1741 case 1:
1742 lgain = rgain = SB_ADJUST_GAIN(sc,
1743 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1744 break;
1745 case 2:
1746 if (sc->sc_mixer_model == SBM_CT1335)
1747 return EINVAL;
1748 lgain = SB_ADJUST_GAIN(sc,
1749 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]);
1750 rgain = SB_ADJUST_GAIN(sc,
1751 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]);
1752 break;
1753 default:
1754 return EINVAL;
1755 }
1756 break;
1757 }
1758 sc->gain[cp->dev][SB_LEFT] = lgain;
1759 sc->gain[cp->dev][SB_RIGHT] = rgain;
1760
1761 sbdsp_set_mixer_gain(sc, cp->dev);
1762 break;
1763
1764 case SB_RECORD_SOURCE:
1765 if (ISSBM1745(sc)) {
1766 if (cp->type != AUDIO_MIXER_SET)
1767 return EINVAL;
1768 return sbdsp_set_in_ports(sc, cp->un.mask);
1769 } else {
1770 if (cp->type != AUDIO_MIXER_ENUM)
1771 return EINVAL;
1772 sc->in_port = cp->un.ord;
1773 return sbdsp_set_in_ports(sc, 1 << cp->un.ord);
1774 }
1775 break;
1776
1777 case SB_AGC:
1778 if (!ISSBM1745(sc) || cp->type != AUDIO_MIXER_ENUM)
1779 return EINVAL;
1780 sbdsp_mix_write(sc, SB16P_AGC, cp->un.ord & 1);
1781 break;
1782
1783 case SB_CD_OUT_MUTE:
1784 mask = SB16P_SW_CD;
1785 goto omute;
1786 case SB_MIC_OUT_MUTE:
1787 mask = SB16P_SW_MIC;
1788 goto omute;
1789 case SB_LINE_OUT_MUTE:
1790 mask = SB16P_SW_LINE;
1791 omute:
1792 if (cp->type != AUDIO_MIXER_ENUM)
1793 return EINVAL;
1794 bits = sbdsp_mix_read(sc, SB16P_OSWITCH);
1795 sc->gain[cp->dev][SB_LR] = cp->un.ord != 0;
1796 if (cp->un.ord)
1797 bits = bits & ~mask;
1798 else
1799 bits = bits | mask;
1800 sbdsp_mix_write(sc, SB16P_OSWITCH, bits);
1801 break;
1802
1803 case SB_MIC_IN_MUTE:
1804 case SB_MIC_SWAP:
1805 lmask = rmask = SB16P_SW_MIC;
1806 goto imute;
1807 case SB_CD_IN_MUTE:
1808 case SB_CD_SWAP:
1809 lmask = SB16P_SW_CD_L;
1810 rmask = SB16P_SW_CD_R;
1811 goto imute;
1812 case SB_LINE_IN_MUTE:
1813 case SB_LINE_SWAP:
1814 lmask = SB16P_SW_LINE_L;
1815 rmask = SB16P_SW_LINE_R;
1816 goto imute;
1817 case SB_MIDI_IN_MUTE:
1818 case SB_MIDI_SWAP:
1819 lmask = SB16P_SW_MIDI_L;
1820 rmask = SB16P_SW_MIDI_R;
1821 imute:
1822 if (cp->type != AUDIO_MIXER_ENUM)
1823 return EINVAL;
1824 mask = lmask | rmask;
1825 lbits = sbdsp_mix_read(sc, SB16P_ISWITCH_L) & ~mask;
1826 rbits = sbdsp_mix_read(sc, SB16P_ISWITCH_R) & ~mask;
1827 sc->gain[cp->dev][SB_LR] = cp->un.ord != 0;
1828 if (SB_IS_IN_MUTE(cp->dev)) {
1829 mute = cp->dev;
1830 swap = mute - SB_CD_IN_MUTE + SB_CD_SWAP;
1831 } else {
1832 swap = cp->dev;
1833 mute = swap + SB_CD_IN_MUTE - SB_CD_SWAP;
1834 }
1835 if (sc->gain[swap][SB_LR]) {
1836 mask = lmask;
1837 lmask = rmask;
1838 rmask = mask;
1839 }
1840 if (!sc->gain[mute][SB_LR]) {
1841 lbits = lbits | lmask;
1842 rbits = rbits | rmask;
1843 }
1844 sbdsp_mix_write(sc, SB16P_ISWITCH_L, lbits);
1845 sbdsp_mix_write(sc, SB16P_ISWITCH_L, rbits);
1846 break;
1847
1848 default:
1849 return EINVAL;
1850 }
1851
1852 return 0;
1853 }
1854
1855 int
1856 sbdsp_mixer_get_port(addr, cp)
1857 void *addr;
1858 mixer_ctrl_t *cp;
1859 {
1860 struct sbdsp_softc *sc = addr;
1861
1862 if (sc->sc_open == SB_OPEN_MIDI)
1863 return EBUSY;
1864
1865 DPRINTF(("sbdsp_mixer_get_port: port=%d\n", cp->dev));
1866
1867 if (sc->sc_mixer_model == SBM_NONE)
1868 return EINVAL;
1869
1870 switch (cp->dev) {
1871 case SB_TREBLE:
1872 case SB_BASS:
1873 if (sc->sc_mixer_model == SBM_CT1345 ||
1874 sc->sc_mixer_model == SBM_CT1XX5) {
1875 switch (cp->dev) {
1876 case SB_TREBLE:
1877 cp->un.ord = sbdsp_get_ifilter(addr) == SB_TREBLE;
1878 return 0;
1879 case SB_BASS:
1880 cp->un.ord = sbdsp_get_ifilter(addr) == SB_BASS;
1881 return 0;
1882 }
1883 }
1884 case SB_PCSPEAKER:
1885 case SB_INPUT_GAIN:
1886 case SB_OUTPUT_GAIN:
1887 if (!ISSBM1745(sc))
1888 return EINVAL;
1889 case SB_MIC_VOL:
1890 case SB_LINE_IN_VOL:
1891 if (sc->sc_mixer_model == SBM_CT1335)
1892 return EINVAL;
1893 case SB_VOICE_VOL:
1894 case SB_MIDI_VOL:
1895 case SB_CD_VOL:
1896 case SB_MASTER_VOL:
1897 switch (cp->dev) {
1898 case SB_MIC_VOL:
1899 case SB_PCSPEAKER:
1900 if (cp->un.value.num_channels != 1)
1901 return EINVAL;
1902 /* fall into */
1903 default:
1904 switch (cp->un.value.num_channels) {
1905 case 1:
1906 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1907 sc->gain[cp->dev][SB_LEFT];
1908 break;
1909 case 2:
1910 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
1911 sc->gain[cp->dev][SB_LEFT];
1912 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
1913 sc->gain[cp->dev][SB_RIGHT];
1914 break;
1915 default:
1916 return EINVAL;
1917 }
1918 break;
1919 }
1920 break;
1921
1922 case SB_RECORD_SOURCE:
1923 if (ISSBM1745(sc))
1924 cp->un.mask = sc->in_mask;
1925 else
1926 cp->un.ord = sc->in_port;
1927 break;
1928
1929 case SB_AGC:
1930 if (!ISSBM1745(sc))
1931 return EINVAL;
1932 cp->un.ord = sbdsp_mix_read(sc, SB16P_AGC);
1933 break;
1934
1935 case SB_CD_IN_MUTE:
1936 case SB_MIC_IN_MUTE:
1937 case SB_LINE_IN_MUTE:
1938 case SB_MIDI_IN_MUTE:
1939 case SB_CD_SWAP:
1940 case SB_MIC_SWAP:
1941 case SB_LINE_SWAP:
1942 case SB_MIDI_SWAP:
1943 case SB_CD_OUT_MUTE:
1944 case SB_MIC_OUT_MUTE:
1945 case SB_LINE_OUT_MUTE:
1946 cp->un.ord = sc->gain[cp->dev][SB_LR];
1947 break;
1948
1949 default:
1950 return EINVAL;
1951 }
1952
1953 return 0;
1954 }
1955
1956 int
1957 sbdsp_mixer_query_devinfo(addr, dip)
1958 void *addr;
1959 mixer_devinfo_t *dip;
1960 {
1961 struct sbdsp_softc *sc = addr;
1962 int chan, class, is1745;
1963
1964 DPRINTF(("sbdsp_mixer_query_devinfo: model=%d index=%d\n",
1965 sc->sc_mixer_model, dip->index));
1966
1967 if (sc->sc_mixer_model == SBM_NONE)
1968 return ENXIO;
1969
1970 chan = sc->sc_mixer_model == SBM_CT1335 ? 1 : 2;
1971 is1745 = ISSBM1745(sc);
1972 class = is1745 ? SB_INPUT_CLASS : SB_OUTPUT_CLASS;
1973
1974 switch (dip->index) {
1975 case SB_MASTER_VOL:
1976 dip->type = AUDIO_MIXER_VALUE;
1977 dip->mixer_class = SB_OUTPUT_CLASS;
1978 dip->prev = dip->next = AUDIO_MIXER_LAST;
1979 strcpy(dip->label.name, AudioNmaster);
1980 dip->un.v.num_channels = chan;
1981 strcpy(dip->un.v.units.name, AudioNvolume);
1982 return 0;
1983 case SB_MIDI_VOL:
1984 dip->type = AUDIO_MIXER_VALUE;
1985 dip->mixer_class = class;
1986 dip->prev = AUDIO_MIXER_LAST;
1987 dip->next = is1745 ? SB_MIDI_IN_MUTE : AUDIO_MIXER_LAST;
1988 strcpy(dip->label.name, AudioNfmsynth);
1989 dip->un.v.num_channels = chan;
1990 strcpy(dip->un.v.units.name, AudioNvolume);
1991 return 0;
1992 case SB_CD_VOL:
1993 dip->type = AUDIO_MIXER_VALUE;
1994 dip->mixer_class = class;
1995 dip->prev = AUDIO_MIXER_LAST;
1996 dip->next = is1745 ? SB_CD_IN_MUTE : AUDIO_MIXER_LAST;
1997 strcpy(dip->label.name, AudioNcd);
1998 dip->un.v.num_channels = chan;
1999 strcpy(dip->un.v.units.name, AudioNvolume);
2000 return 0;
2001 case SB_VOICE_VOL:
2002 dip->type = AUDIO_MIXER_VALUE;
2003 dip->mixer_class = class;
2004 dip->prev = AUDIO_MIXER_LAST;
2005 dip->next = AUDIO_MIXER_LAST;
2006 strcpy(dip->label.name, AudioNdac);
2007 dip->un.v.num_channels = chan;
2008 strcpy(dip->un.v.units.name, AudioNvolume);
2009 return 0;
2010 case SB_OUTPUT_CLASS:
2011 dip->type = AUDIO_MIXER_CLASS;
2012 dip->mixer_class = SB_OUTPUT_CLASS;
2013 dip->next = dip->prev = AUDIO_MIXER_LAST;
2014 strcpy(dip->label.name, AudioCoutputs);
2015 return 0;
2016 }
2017
2018 if (sc->sc_mixer_model == SBM_CT1335)
2019 return ENXIO;
2020
2021 switch (dip->index) {
2022 case SB_MIC_VOL:
2023 dip->type = AUDIO_MIXER_VALUE;
2024 dip->mixer_class = class;
2025 dip->prev = AUDIO_MIXER_LAST;
2026 dip->next = is1745 ? SB_MIC_IN_MUTE : AUDIO_MIXER_LAST;
2027 strcpy(dip->label.name, AudioNmicrophone);
2028 dip->un.v.num_channels = 1;
2029 strcpy(dip->un.v.units.name, AudioNvolume);
2030 return 0;
2031
2032 case SB_LINE_IN_VOL:
2033 dip->type = AUDIO_MIXER_VALUE;
2034 dip->mixer_class = class;
2035 dip->prev = AUDIO_MIXER_LAST;
2036 dip->next = is1745 ? SB_LINE_IN_MUTE : AUDIO_MIXER_LAST;
2037 strcpy(dip->label.name, AudioNline);
2038 dip->un.v.num_channels = 2;
2039 strcpy(dip->un.v.units.name, AudioNvolume);
2040 return 0;
2041
2042 case SB_RECORD_SOURCE:
2043 dip->mixer_class = SB_RECORD_CLASS;
2044 dip->prev = dip->next = AUDIO_MIXER_LAST;
2045 strcpy(dip->label.name, AudioNsource);
2046 if (ISSBM1745(sc)) {
2047 dip->type = AUDIO_MIXER_SET;
2048 dip->un.s.num_mem = 4;
2049 strcpy(dip->un.s.member[0].label.name, AudioNmicrophone);
2050 dip->un.s.member[0].mask = 1 << SB_MIC_VOL;
2051 strcpy(dip->un.s.member[1].label.name, AudioNcd);
2052 dip->un.s.member[1].mask = 1 << SB_CD_VOL;
2053 strcpy(dip->un.s.member[2].label.name, AudioNline);
2054 dip->un.s.member[2].mask = 1 << SB_LINE_IN_VOL;
2055 strcpy(dip->un.s.member[3].label.name, AudioNfmsynth);
2056 dip->un.s.member[3].mask = 1 << SB_MIDI_VOL;
2057 } else {
2058 dip->type = AUDIO_MIXER_ENUM;
2059 dip->un.e.num_mem = 3;
2060 strcpy(dip->un.e.member[0].label.name, AudioNmicrophone);
2061 dip->un.e.member[0].ord = SB_MIC_VOL;
2062 strcpy(dip->un.e.member[1].label.name, AudioNcd);
2063 dip->un.e.member[1].ord = SB_CD_VOL;
2064 strcpy(dip->un.e.member[2].label.name, AudioNline);
2065 dip->un.e.member[2].ord = SB_LINE_IN_VOL;
2066 }
2067 return 0;
2068
2069 case SB_BASS:
2070 dip->prev = dip->next = AUDIO_MIXER_LAST;
2071 strcpy(dip->label.name, AudioNbass);
2072 if (sc->sc_mixer_model == SBM_CT1745) {
2073 dip->type = AUDIO_MIXER_VALUE;
2074 dip->mixer_class = SB_EQUALIZATION_CLASS;
2075 dip->un.v.num_channels = 2;
2076 strcpy(dip->un.v.units.name, AudioNbass);
2077 } else {
2078 dip->type = AUDIO_MIXER_ENUM;
2079 dip->mixer_class = SB_INPUT_CLASS;
2080 dip->un.e.num_mem = 2;
2081 strcpy(dip->un.e.member[0].label.name, AudioNoff);
2082 dip->un.e.member[0].ord = 0;
2083 strcpy(dip->un.e.member[1].label.name, AudioNon);
2084 dip->un.e.member[1].ord = 1;
2085 }
2086 return 0;
2087
2088 case SB_TREBLE:
2089 dip->prev = dip->next = AUDIO_MIXER_LAST;
2090 strcpy(dip->label.name, AudioNtreble);
2091 if (sc->sc_mixer_model == SBM_CT1745) {
2092 dip->type = AUDIO_MIXER_VALUE;
2093 dip->mixer_class = SB_EQUALIZATION_CLASS;
2094 dip->un.v.num_channels = 2;
2095 strcpy(dip->un.v.units.name, AudioNtreble);
2096 } else {
2097 dip->type = AUDIO_MIXER_ENUM;
2098 dip->mixer_class = SB_INPUT_CLASS;
2099 dip->un.e.num_mem = 2;
2100 strcpy(dip->un.e.member[0].label.name, AudioNoff);
2101 dip->un.e.member[0].ord = 0;
2102 strcpy(dip->un.e.member[1].label.name, AudioNon);
2103 dip->un.e.member[1].ord = 1;
2104 }
2105 return 0;
2106
2107 case SB_RECORD_CLASS: /* record source class */
2108 dip->type = AUDIO_MIXER_CLASS;
2109 dip->mixer_class = SB_RECORD_CLASS;
2110 dip->next = dip->prev = AUDIO_MIXER_LAST;
2111 strcpy(dip->label.name, AudioCrecord);
2112 return 0;
2113
2114 case SB_INPUT_CLASS:
2115 dip->type = AUDIO_MIXER_CLASS;
2116 dip->mixer_class = SB_INPUT_CLASS;
2117 dip->next = dip->prev = AUDIO_MIXER_LAST;
2118 strcpy(dip->label.name, AudioCinputs);
2119 return 0;
2120
2121 }
2122
2123 if (sc->sc_mixer_model == SBM_CT1345)
2124 return ENXIO;
2125
2126 switch(dip->index) {
2127 case SB_PCSPEAKER:
2128 dip->type = AUDIO_MIXER_VALUE;
2129 dip->mixer_class = SB_INPUT_CLASS;
2130 dip->prev = dip->next = AUDIO_MIXER_LAST;
2131 strcpy(dip->label.name, "pc_speaker");
2132 dip->un.v.num_channels = 1;
2133 strcpy(dip->un.v.units.name, AudioNvolume);
2134 return 0;
2135
2136 case SB_INPUT_GAIN:
2137 dip->type = AUDIO_MIXER_VALUE;
2138 dip->mixer_class = SB_INPUT_CLASS;
2139 dip->prev = dip->next = AUDIO_MIXER_LAST;
2140 strcpy(dip->label.name, AudioNinput);
2141 dip->un.v.num_channels = 2;
2142 strcpy(dip->un.v.units.name, AudioNvolume);
2143 return 0;
2144
2145 case SB_OUTPUT_GAIN:
2146 dip->type = AUDIO_MIXER_VALUE;
2147 dip->mixer_class = SB_OUTPUT_CLASS;
2148 dip->prev = dip->next = AUDIO_MIXER_LAST;
2149 strcpy(dip->label.name, AudioNoutput);
2150 dip->un.v.num_channels = 2;
2151 strcpy(dip->un.v.units.name, AudioNvolume);
2152 return 0;
2153
2154 case SB_AGC:
2155 dip->type = AUDIO_MIXER_ENUM;
2156 dip->mixer_class = SB_INPUT_CLASS;
2157 dip->prev = dip->next = AUDIO_MIXER_LAST;
2158 strcpy(dip->label.name, "agc");
2159 dip->un.e.num_mem = 2;
2160 strcpy(dip->un.e.member[0].label.name, AudioNoff);
2161 dip->un.e.member[0].ord = 0;
2162 strcpy(dip->un.e.member[1].label.name, AudioNon);
2163 dip->un.e.member[1].ord = 1;
2164 return 0;
2165
2166 case SB_EQUALIZATION_CLASS:
2167 dip->type = AUDIO_MIXER_CLASS;
2168 dip->mixer_class = SB_EQUALIZATION_CLASS;
2169 dip->next = dip->prev = AUDIO_MIXER_LAST;
2170 strcpy(dip->label.name, AudioCequalization);
2171 return 0;
2172
2173 case SB_CD_IN_MUTE:
2174 dip->prev = SB_CD_VOL;
2175 dip->next = SB_CD_SWAP;
2176 dip->mixer_class = SB_INPUT_CLASS;
2177 goto mute;
2178
2179 case SB_MIC_IN_MUTE:
2180 dip->prev = SB_MIC_VOL;
2181 dip->next = SB_MIC_SWAP;
2182 dip->mixer_class = SB_INPUT_CLASS;
2183 goto mute;
2184
2185 case SB_LINE_IN_MUTE:
2186 dip->prev = SB_LINE_IN_VOL;
2187 dip->next = SB_LINE_SWAP;
2188 dip->mixer_class = SB_INPUT_CLASS;
2189 goto mute;
2190
2191 case SB_MIDI_IN_MUTE:
2192 dip->prev = SB_MIDI_VOL;
2193 dip->next = SB_MIDI_SWAP;
2194 dip->mixer_class = SB_INPUT_CLASS;
2195 goto mute;
2196
2197 case SB_CD_SWAP:
2198 dip->prev = SB_CD_IN_MUTE;
2199 dip->next = SB_CD_OUT_MUTE;
2200 goto swap;
2201
2202 case SB_MIC_SWAP:
2203 dip->prev = SB_MIC_IN_MUTE;
2204 dip->next = SB_MIC_OUT_MUTE;
2205 goto swap;
2206
2207 case SB_LINE_SWAP:
2208 dip->prev = SB_LINE_IN_MUTE;
2209 dip->next = SB_LINE_OUT_MUTE;
2210 goto swap;
2211
2212 case SB_MIDI_SWAP:
2213 dip->prev = SB_MIDI_IN_MUTE;
2214 dip->next = AUDIO_MIXER_LAST;
2215 swap:
2216 dip->mixer_class = SB_INPUT_CLASS;
2217 strcpy(dip->label.name, AudioNswap);
2218 goto mute1;
2219
2220 case SB_CD_OUT_MUTE:
2221 dip->prev = SB_CD_SWAP;
2222 dip->next = AUDIO_MIXER_LAST;
2223 dip->mixer_class = SB_OUTPUT_CLASS;
2224 goto mute;
2225
2226 case SB_MIC_OUT_MUTE:
2227 dip->prev = SB_MIC_SWAP;
2228 dip->next = AUDIO_MIXER_LAST;
2229 dip->mixer_class = SB_OUTPUT_CLASS;
2230 goto mute;
2231
2232 case SB_LINE_OUT_MUTE:
2233 dip->prev = SB_LINE_SWAP;
2234 dip->next = AUDIO_MIXER_LAST;
2235 dip->mixer_class = SB_OUTPUT_CLASS;
2236 mute:
2237 strcpy(dip->label.name, AudioNmute);
2238 mute1:
2239 dip->type = AUDIO_MIXER_ENUM;
2240 dip->un.e.num_mem = 2;
2241 strcpy(dip->un.e.member[0].label.name, AudioNoff);
2242 dip->un.e.member[0].ord = 0;
2243 strcpy(dip->un.e.member[1].label.name, AudioNon);
2244 dip->un.e.member[1].ord = 1;
2245 return 0;
2246
2247 }
2248
2249 return ENXIO;
2250 }
2251
2252 void *
2253 sb_malloc(addr, direction, size, pool, flags)
2254 void *addr;
2255 int direction;
2256 size_t size;
2257 int pool, flags;
2258 {
2259 struct sbdsp_softc *sc = addr;
2260 int drq;
2261
2262 if (sc->sc_drq8 != -1)
2263 drq = sc->sc_drq8;
2264 else
2265 drq = sc->sc_drq16;
2266 return (isa_malloc(sc->sc_ic, drq, size, pool, flags));
2267 }
2268
2269 void
2270 sb_free(addr, ptr, pool)
2271 void *addr;
2272 void *ptr;
2273 int pool;
2274 {
2275 isa_free(ptr, pool);
2276 }
2277
2278 size_t
2279 sb_round_buffersize(addr, direction, size)
2280 void *addr;
2281 int direction;
2282 size_t size;
2283 {
2284 if (size > MAX_ISADMA)
2285 size = MAX_ISADMA;
2286 return (size);
2287 }
2288
2289 int
2290 sb_mappage(addr, mem, off, prot)
2291 void *addr;
2292 void *mem;
2293 int off;
2294 int prot;
2295 {
2296 return isa_mappage(mem, off, prot);
2297 }
2298
2299 int
2300 sbdsp_get_props(addr)
2301 void *addr;
2302 {
2303 struct sbdsp_softc *sc = addr;
2304 return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT |
2305 (sc->sc_fullduplex ? AUDIO_PROP_FULLDUPLEX : 0);
2306 }
2307
2308 #if NMPU > 0
2309 /*
2310 * MIDI related routines.
2311 */
2312
2313 int
2314 sbdsp_midi_open(addr, flags, iintr, ointr, arg)
2315 void *addr;
2316 int flags;
2317 void (*iintr)__P((void *, int));
2318 void (*ointr)__P((void *));
2319 void *arg;
2320 {
2321 struct sbdsp_softc *sc = addr;
2322
2323 DPRINTF(("sbdsp_midi_open: sc=%p\n", sc));
2324
2325 if (sc->sc_open != SB_CLOSED)
2326 return EBUSY;
2327 if (sbdsp_reset(sc) != 0)
2328 return EIO;
2329
2330 sc->sc_open = SB_OPEN_MIDI;
2331 sc->sc_openflags = flags;
2332
2333 if (sc->sc_model >= SB_20)
2334 if (sbdsp_wdsp(sc, SB_MIDI_UART_INTR)) /* enter UART mode */
2335 return EIO;
2336
2337 sc->sc_intr8 = sbdsp_midi_intr;
2338 sc->sc_intrm = iintr;
2339 sc->sc_argm = arg;
2340
2341 return 0;
2342 }
2343
2344 void
2345 sbdsp_midi_close(addr)
2346 void *addr;
2347 {
2348 struct sbdsp_softc *sc = addr;
2349
2350 DPRINTF(("sbdsp_midi_close: sc=%p\n", sc));
2351
2352 if (sc->sc_model >= SB_20)
2353 sbdsp_reset(sc); /* exit UART mode */
2354
2355 sc->sc_intrm = 0;
2356 sc->sc_open = SB_CLOSED;
2357 }
2358
2359 int
2360 sbdsp_midi_output(addr, d)
2361 void *addr;
2362 int d;
2363 {
2364 struct sbdsp_softc *sc = addr;
2365
2366 if (sc->sc_model < SB_20 && sbdsp_wdsp(sc, SB_MIDI_WRITE))
2367 return EIO;
2368 if (sbdsp_wdsp(sc, d))
2369 return EIO;
2370 return 0;
2371 }
2372
2373 void
2374 sbdsp_midi_getinfo(addr, mi)
2375 void *addr;
2376 struct midi_info *mi;
2377 {
2378 struct sbdsp_softc *sc = addr;
2379
2380 mi->name = sc->sc_model < SB_20 ? "SB MIDI cmd" : "SB MIDI UART";
2381 mi->props = MIDI_PROP_CAN_INPUT;
2382 }
2383
2384 int
2385 sbdsp_midi_intr(addr)
2386 void *addr;
2387 {
2388 struct sbdsp_softc *sc = addr;
2389
2390 sc->sc_intrm(sc->sc_argm, sbdsp_rdsp(sc));
2391 return (0);
2392 }
2393
2394 #endif
2395
2396