sbdsp.c revision 1.55 1 /* $NetBSD: sbdsp.c,v 1.55 1997/05/28 00:07:49 augustss Exp $ */
2
3 /*
4 * Copyright (c) 1991-1993 Regents of the University of California.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the Computer Systems
18 * Engineering Group at Lawrence Berkeley Laboratory.
19 * 4. Neither the name of the University nor of the Laboratory may be used
20 * to endorse or promote products derived from this software without
21 * specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 */
36
37 /*
38 * SoundBlaster Pro code provided by John Kohl, based on lots of
39 * information he gleaned from Steve Haehnichen <steve (at) vigra.com>'s
40 * SBlast driver for 386BSD and DOS driver code from Daniel Sachs
41 * <sachs (at) meibm15.cen.uiuc.edu>.
42 * Lots of rewrites by Lennart Augustsson <augustss (at) cs.chalmers.se>
43 * with information from SB "Hardware Programming Guide" and the
44 * Linux drivers.
45 */
46
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/errno.h>
50 #include <sys/ioctl.h>
51 #include <sys/syslog.h>
52 #include <sys/device.h>
53 #include <sys/proc.h>
54 #include <sys/buf.h>
55 #include <vm/vm.h>
56
57 #include <machine/cpu.h>
58 #include <machine/intr.h>
59 #include <machine/pio.h>
60
61 #include <sys/audioio.h>
62 #include <dev/audio_if.h>
63 #include <dev/mulaw.h>
64
65 #include <dev/isa/isavar.h>
66 #include <dev/isa/isadmavar.h>
67
68 #include <dev/isa/sbreg.h>
69 #include <dev/isa/sbdspvar.h>
70
71 #ifdef AUDIO_DEBUG
72 extern void Dprintf __P((const char *, ...));
73 #define DPRINTF(x) if (sbdspdebug) Dprintf x
74 int sbdspdebug = 0;
75 #else
76 #define DPRINTF(x)
77 #endif
78
79 #ifndef SBDSP_NPOLL
80 #define SBDSP_NPOLL 3000
81 #endif
82
83 struct {
84 int wdsp;
85 int rdsp;
86 int wmidi;
87 } sberr;
88
89 /*
90 * Time constant routines follow. See SBK, section 12.
91 * Although they don't come out and say it (in the docs),
92 * the card clearly uses a 1MHz countdown timer, as the
93 * low-speed formula (p. 12-4) is:
94 * tc = 256 - 10^6 / sr
95 * In high-speed mode, the constant is the upper byte of a 16-bit counter,
96 * and a 256MHz clock is used:
97 * tc = 65536 - 256 * 10^ 6 / sr
98 * Since we can only use the upper byte of the HS TC, the two formulae
99 * are equivalent. (Why didn't they say so?) E.g.,
100 * (65536 - 256 * 10 ^ 6 / x) >> 8 = 256 - 10^6 / x
101 *
102 * The crossover point (from low- to high-speed modes) is different
103 * for the SBPRO and SB20. The table on p. 12-5 gives the following data:
104 *
105 * SBPRO SB20
106 * ----- --------
107 * input ls min 4 KHz 4 KHz
108 * input ls max 23 KHz 13 KHz
109 * input hs max 44.1 KHz 15 KHz
110 * output ls min 4 KHz 4 KHz
111 * output ls max 23 KHz 23 KHz
112 * output hs max 44.1 KHz 44.1 KHz
113 */
114 /* XXX Should we round the tc?
115 #define SB_RATE_TO_TC(x) (((65536 - 256 * 1000000 / (x)) + 128) >> 8)
116 */
117 #define SB_RATE_TO_TC(x) (256 - 1000000 / (x))
118 #define SB_TC_TO_RATE(tc) (1000000 / (256 - (tc)))
119
120 struct sbmode {
121 short model;
122 u_char channels;
123 u_char precision;
124 u_short lowrate, highrate;
125 u_char cmd;
126 short cmdchan;
127 };
128 static struct sbmode sbpmodes[] = {
129 { SB_1, 1, 8, 4000, 22727, SB_DSP_WDMA },
130 { SB_20, 1, 8, 4000, 22727, SB_DSP_WDMA_LOOP },
131 { SB_2x, 1, 8, 4000, 22727, SB_DSP_WDMA_LOOP },
132 { SB_2x, 1, 8, 22727, 45454, SB_DSP_HS_OUTPUT },
133 { SB_PRO, 1, 8, 4000, 22727, SB_DSP_WDMA_LOOP },
134 { SB_PRO, 1, 8, 22727, 45454, SB_DSP_HS_OUTPUT },
135 { SB_PRO, 2, 8, 11025, 22727, SB_DSP_HS_OUTPUT },
136 { SB_JAZZ, 1, 8, 4000, 22727, SB_DSP_WDMA_LOOP, SB_DSP_RECORD_MONO },
137 { SB_JAZZ, 1, 8, 22727, 45454, SB_DSP_HS_OUTPUT, SB_DSP_RECORD_MONO },
138 { SB_JAZZ, 2, 8, 11025, 22727, SB_DSP_HS_OUTPUT, SB_DSP_RECORD_STEREO },
139 { SB_JAZZ, 1, 16, 4000, 22727, SB_DSP_WDMA_LOOP, JAZZ16_RECORD_MONO },
140 { SB_JAZZ, 1, 16, 22727, 45454, SB_DSP_HS_OUTPUT, JAZZ16_RECORD_MONO },
141 { SB_JAZZ, 2, 16, 11025, 22727, SB_DSP_HS_OUTPUT, JAZZ16_RECORD_STEREO },
142 { SB_16, 1, 8, 5000, 45000, SB_DSP16_WDMA_8 },
143 { SB_16, 2, 8, 5000, 45000, SB_DSP16_WDMA_8 },
144 { SB_16, 1, 16, 5000, 45000, SB_DSP16_WDMA_16 },
145 { SB_16, 2, 16, 5000, 45000, SB_DSP16_WDMA_16 },
146 { -1 }
147 };
148 static struct sbmode sbrmodes[] = {
149 { SB_1, 1, 8, 4000, 12987, SB_DSP_RDMA },
150 { SB_20, 1, 8, 4000, 12987, SB_DSP_RDMA_LOOP },
151 { SB_2x, 1, 8, 4000, 12987, SB_DSP_RDMA_LOOP },
152 { SB_2x, 1, 8, 12987, 14925, SB_DSP_HS_INPUT },
153 { SB_PRO, 1, 8, 4000, 22727, SB_DSP_RDMA_LOOP, SB_DSP_RECORD_MONO },
154 { SB_PRO, 1, 8, 22727, 45454, SB_DSP_HS_INPUT, SB_DSP_RECORD_MONO },
155 { SB_PRO, 2, 8, 11025, 22727, SB_DSP_HS_INPUT, SB_DSP_RECORD_STEREO },
156 { SB_JAZZ, 1, 8, 4000, 22727, SB_DSP_RDMA_LOOP, SB_DSP_RECORD_MONO },
157 { SB_JAZZ, 1, 8, 22727, 45454, SB_DSP_HS_INPUT, SB_DSP_RECORD_MONO },
158 { SB_JAZZ, 2, 8, 11025, 22727, SB_DSP_HS_INPUT, SB_DSP_RECORD_STEREO },
159 { SB_JAZZ, 1, 16, 4000, 22727, SB_DSP_RDMA_LOOP, JAZZ16_RECORD_MONO },
160 { SB_JAZZ, 1, 16, 22727, 45454, SB_DSP_HS_INPUT, JAZZ16_RECORD_MONO },
161 { SB_JAZZ, 2, 16, 11025, 22727, SB_DSP_HS_INPUT, JAZZ16_RECORD_STEREO },
162 { SB_16, 1, 8, 5000, 45000, SB_DSP16_RDMA_8 },
163 { SB_16, 2, 8, 5000, 45000, SB_DSP16_RDMA_8 },
164 { SB_16, 1, 16, 5000, 45000, SB_DSP16_RDMA_16 },
165 { SB_16, 2, 16, 5000, 45000, SB_DSP16_RDMA_16 },
166 { -1 }
167 };
168
169 void sbversion __P((struct sbdsp_softc *));
170 void sbdsp_jazz16_probe __P((struct sbdsp_softc *));
171 void sbdsp_set_mixer_gain __P((struct sbdsp_softc *sc, int port));
172 int sbdsp16_wait __P((struct sbdsp_softc *));
173 void sbdsp_to __P((void *));
174 void sbdsp_pause __P((struct sbdsp_softc *));
175 int sbdsp_set_timeconst __P((struct sbdsp_softc *, int));
176 int sbdsp16_set_rate __P((struct sbdsp_softc *, int, int));
177 int sbdsp_set_in_ports __P((struct sbdsp_softc *, int));
178 void sbdsp_set_ifilter __P((void *, int));
179 int sbdsp_get_ifilter __P((void *));
180
181 #ifdef AUDIO_DEBUG
182 void sb_printsc __P((struct sbdsp_softc *));
183
184 void
185 sb_printsc(sc)
186 struct sbdsp_softc *sc;
187 {
188 int i;
189
190 printf("open %d dmachan %d/%d/%d iobase 0x%x irq %d\n",
191 (int)sc->sc_open, sc->dmachan, sc->sc_drq8, sc->sc_drq16,
192 sc->sc_iobase, sc->sc_irq);
193 printf("irate %d itc %x orate %d otc %x\n",
194 sc->sc_irate, sc->sc_itc,
195 sc->sc_orate, sc->sc_otc);
196 printf("outport %u inport %u spkron %u nintr %lu\n",
197 sc->out_port, sc->in_port, sc->spkr_state, sc->sc_interrupts);
198 printf("intr %p arg %p\n",
199 sc->sc_intr, sc->sc_arg);
200 printf("gain:");
201 for (i = 0; i < SB_NDEVS; i++)
202 printf(" %u,%u", sc->gain[i][SB_LEFT], sc->gain[i][SB_RIGHT]);
203 printf("\n");
204 }
205 #endif /* AUDIO_DEBUG */
206
207 /*
208 * Probe / attach routines.
209 */
210
211 /*
212 * Probe for the soundblaster hardware.
213 */
214 int
215 sbdsp_probe(sc)
216 struct sbdsp_softc *sc;
217 {
218
219 if (sbdsp_reset(sc) < 0) {
220 DPRINTF(("sbdsp: couldn't reset card\n"));
221 return 0;
222 }
223 /* if flags set, go and probe the jazz16 stuff */
224 if (sc->sc_dev.dv_cfdata->cf_flags & 1)
225 sbdsp_jazz16_probe(sc);
226 else
227 sbversion(sc);
228 if (sc->sc_model == SB_UNK) {
229 /* Unknown SB model found. */
230 DPRINTF(("sbdsp: unknown SB model found\n"));
231 return 0;
232 }
233 return 1;
234 }
235
236 /*
237 * Try add-on stuff for Jazz16.
238 */
239 void
240 sbdsp_jazz16_probe(sc)
241 struct sbdsp_softc *sc;
242 {
243 static u_char jazz16_irq_conf[16] = {
244 -1, -1, 0x02, 0x03,
245 -1, 0x01, -1, 0x04,
246 -1, 0x02, 0x05, -1,
247 -1, -1, -1, 0x06};
248 static u_char jazz16_drq_conf[8] = {
249 -1, 0x01, -1, 0x02,
250 -1, 0x03, -1, 0x04};
251
252 bus_space_tag_t iot = sc->sc_iot;
253 bus_space_handle_t ioh;
254
255 sbversion(sc);
256
257 DPRINTF(("jazz16 probe\n"));
258
259 if (bus_space_map(iot, JAZZ16_CONFIG_PORT, 1, 0, &ioh)) {
260 DPRINTF(("bus map failed\n"));
261 return;
262 }
263
264 if (jazz16_drq_conf[sc->sc_drq8] == (u_char)-1 ||
265 jazz16_irq_conf[sc->sc_irq] == (u_char)-1) {
266 DPRINTF(("drq/irq check failed\n"));
267 goto done; /* give up, we can't do it. */
268 }
269
270 bus_space_write_1(iot, ioh, 0, JAZZ16_WAKEUP);
271 delay(10000); /* delay 10 ms */
272 bus_space_write_1(iot, ioh, 0, JAZZ16_SETBASE);
273 bus_space_write_1(iot, ioh, 0, sc->sc_iobase & 0x70);
274
275 if (sbdsp_reset(sc) < 0) {
276 DPRINTF(("sbdsp_reset check failed\n"));
277 goto done; /* XXX? what else could we do? */
278 }
279
280 if (sbdsp_wdsp(sc, JAZZ16_READ_VER)) {
281 DPRINTF(("read16 setup failed\n"));
282 goto done;
283 }
284
285 if (sbdsp_rdsp(sc) != JAZZ16_VER_JAZZ) {
286 DPRINTF(("read16 failed\n"));
287 goto done;
288 }
289
290 /* XXX set both 8 & 16-bit drq to same channel, it works fine. */
291 sc->sc_drq16 = sc->sc_drq8;
292 if (sbdsp_wdsp(sc, JAZZ16_SET_DMAINTR) ||
293 sbdsp_wdsp(sc, (jazz16_drq_conf[sc->sc_drq16] << 4) |
294 jazz16_drq_conf[sc->sc_drq8]) ||
295 sbdsp_wdsp(sc, jazz16_irq_conf[sc->sc_irq])) {
296 DPRINTF(("sbdsp: can't write jazz16 probe stuff\n"));
297 } else {
298 DPRINTF(("jazz16 detected!\n"));
299 sc->sc_model = SB_JAZZ;
300 sc->sc_mixer_model = SBM_CT1345; /* XXX really? */
301 }
302
303 done:
304 bus_space_unmap(iot, ioh, 1);
305 }
306
307 /*
308 * Attach hardware to driver, attach hardware driver to audio
309 * pseudo-device driver .
310 */
311 void
312 sbdsp_attach(sc)
313 struct sbdsp_softc *sc;
314 {
315 struct audio_params xparams;
316 int i;
317 u_int v;
318
319 sbdsp_set_params(sc, AUMODE_RECORD, &audio_default, &xparams);
320 sbdsp_set_params(sc, AUMODE_PLAY, &audio_default, &xparams);
321
322 sbdsp_set_in_port(sc, SB_MIC_VOL);
323 sbdsp_set_out_port(sc, SB_MASTER_VOL);
324
325 if (sc->sc_mixer_model != SBM_NONE) {
326 /* Reset the mixer.*/
327 sbdsp_mix_write(sc, SBP_MIX_RESET, SBP_MIX_RESET);
328 /* And set our own default values */
329 for (i = 0; i < SB_NDEVS; i++) {
330 switch(i) {
331 case SB_MIC_VOL:
332 case SB_LINE_IN_VOL:
333 v = 0;
334 break;
335 case SB_BASS:
336 case SB_TREBLE:
337 v = SB_ADJUST_GAIN(sc, AUDIO_MAX_GAIN/2);
338 break;
339 default:
340 v = SB_ADJUST_GAIN(sc, AUDIO_MAX_GAIN * 3 / 4);
341 break;
342 }
343 sc->gain[i][SB_LEFT] = sc->gain[i][SB_RIGHT] = v;
344 sbdsp_set_mixer_gain(sc, i);
345 }
346 sc->in_filter = 0; /* no filters turned on, please */
347 }
348
349 printf(": dsp v%d.%02d%s\n",
350 SBVER_MAJOR(sc->sc_version), SBVER_MINOR(sc->sc_version),
351 sc->sc_model == SB_JAZZ ? ": <Jazz16>" : "");
352 }
353
354 void
355 sbdsp_mix_write(sc, mixerport, val)
356 struct sbdsp_softc *sc;
357 int mixerport;
358 int val;
359 {
360 bus_space_tag_t iot = sc->sc_iot;
361 bus_space_handle_t ioh = sc->sc_ioh;
362 int s;
363
364 s = splaudio();
365 bus_space_write_1(iot, ioh, SBP_MIXER_ADDR, mixerport);
366 delay(20);
367 bus_space_write_1(iot, ioh, SBP_MIXER_DATA, val);
368 delay(30);
369 splx(s);
370 }
371
372 int
373 sbdsp_mix_read(sc, mixerport)
374 struct sbdsp_softc *sc;
375 int mixerport;
376 {
377 bus_space_tag_t iot = sc->sc_iot;
378 bus_space_handle_t ioh = sc->sc_ioh;
379 int val;
380 int s;
381
382 s = splaudio();
383 bus_space_write_1(iot, ioh, SBP_MIXER_ADDR, mixerport);
384 delay(20);
385 val = bus_space_read_1(iot, ioh, SBP_MIXER_DATA);
386 delay(30);
387 splx(s);
388 return val;
389 }
390
391 /*
392 * Various routines to interface to higher level audio driver
393 */
394
395 int
396 sbdsp_query_encoding(addr, fp)
397 void *addr;
398 struct audio_encoding *fp;
399 {
400 struct sbdsp_softc *sc = addr;
401 int emul;
402
403 emul = ISSB16CLASS(sc) ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
404
405 switch (fp->index) {
406 case 0:
407 strcpy(fp->name, AudioEulinear);
408 fp->encoding = AUDIO_ENCODING_ULINEAR;
409 fp->precision = 8;
410 fp->flags = 0;
411 return 0;
412 case 1:
413 strcpy(fp->name, AudioEmulaw);
414 fp->encoding = AUDIO_ENCODING_ULAW;
415 fp->precision = 8;
416 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
417 return 0;
418 case 2:
419 strcpy(fp->name, AudioEalaw);
420 fp->encoding = AUDIO_ENCODING_ALAW;
421 fp->precision = 8;
422 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
423 return 0;
424 case 3:
425 strcpy(fp->name, AudioElinear);
426 fp->encoding = AUDIO_ENCODING_LINEAR;
427 fp->precision = 8;
428 fp->flags = emul;
429 return 0;
430 }
431 if (!ISSB16CLASS(sc) && sc->sc_model != SB_JAZZ)
432 return EINVAL;
433
434 switch(fp->index) {
435 case 4:
436 strcpy(fp->name, AudioElinear_le);
437 fp->encoding = AUDIO_ENCODING_LINEAR_LE;
438 fp->precision = 16;
439 fp->flags = 0;
440 return 0;
441 case 5:
442 strcpy(fp->name, AudioEulinear_le);
443 fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
444 fp->precision = 16;
445 fp->flags = emul;
446 return 0;
447 case 6:
448 strcpy(fp->name, AudioElinear_be);
449 fp->encoding = AUDIO_ENCODING_LINEAR_BE;
450 fp->precision = 16;
451 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
452 return 0;
453 case 7:
454 strcpy(fp->name, AudioEulinear_be);
455 fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
456 fp->precision = 16;
457 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
458 return 0;
459 default:
460 return EINVAL;
461 }
462 return 0;
463 }
464
465 int
466 sbdsp_set_params(addr, mode, p, q)
467 void *addr;
468 int mode;
469 struct audio_params *p, *q;
470 {
471 struct sbdsp_softc *sc = addr;
472 struct sbmode *m;
473 u_int rate, tc = 1, bmode = -1;
474 void (*swcode) __P((void *, u_char *buf, int cnt));
475
476 for(m = mode == AUMODE_PLAY ? sbpmodes : sbrmodes;
477 m->model != -1; m++) {
478 if (sc->sc_model == m->model &&
479 p->channels == m->channels &&
480 p->precision == m->precision &&
481 p->sample_rate >= m->lowrate &&
482 p->sample_rate < m->highrate)
483 break;
484 }
485 if (m->model == -1)
486 return EINVAL;
487 rate = p->sample_rate;
488 swcode = 0;
489 if (m->model == SB_16) {
490 switch (p->encoding) {
491 case AUDIO_ENCODING_LINEAR_BE:
492 if (p->precision == 16)
493 swcode = swap_bytes;
494 /* fall into */
495 case AUDIO_ENCODING_LINEAR_LE:
496 bmode = 0x10;
497 break;
498 case AUDIO_ENCODING_ULINEAR_BE:
499 if (p->precision == 16)
500 swcode = swap_bytes;
501 /* fall into */
502 case AUDIO_ENCODING_ULINEAR_LE:
503 bmode = 0;
504 break;
505 case AUDIO_ENCODING_ULAW:
506 swcode = mode == AUMODE_PLAY ?
507 mulaw_to_ulinear8 : ulinear8_to_mulaw;
508 bmode = 0;
509 break;
510 case AUDIO_ENCODING_ALAW:
511 swcode = mode == AUMODE_PLAY ?
512 alaw_to_ulinear8 : ulinear8_to_alaw;
513 bmode = 0;
514 break;
515 default:
516 return EINVAL;
517 }
518 if (p->channels == 2)
519 bmode |= 0x20;
520 } else if (m->model == SB_JAZZ && m->precision == 16) {
521 switch (p->encoding) {
522 case AUDIO_ENCODING_LINEAR_LE:
523 break;
524 case AUDIO_ENCODING_ULINEAR_LE:
525 swcode = change_sign16;
526 break;
527 case AUDIO_ENCODING_LINEAR_BE:
528 swcode = swap_bytes;
529 break;
530 case AUDIO_ENCODING_ULINEAR_BE:
531 swcode = mode == AUMODE_PLAY ?
532 swap_bytes_change_sign16 : change_sign16_swap_bytes;
533 break;
534 case AUDIO_ENCODING_ULAW:
535 swcode = mode == AUMODE_PLAY ?
536 mulaw_to_ulinear8 : ulinear8_to_mulaw;
537 break;
538 case AUDIO_ENCODING_ALAW:
539 swcode = mode == AUMODE_PLAY ?
540 alaw_to_ulinear8 : ulinear8_to_alaw;
541 break;
542 default:
543 return EINVAL;
544 }
545 } else {
546 switch (p->encoding) {
547 case AUDIO_ENCODING_LINEAR_BE:
548 case AUDIO_ENCODING_LINEAR_LE:
549 swcode = change_sign8;
550 break;
551 case AUDIO_ENCODING_ULINEAR_BE:
552 case AUDIO_ENCODING_ULINEAR_LE:
553 break;
554 case AUDIO_ENCODING_ULAW:
555 swcode = mode == AUMODE_PLAY ?
556 mulaw_to_ulinear8 : ulinear8_to_mulaw;
557 break;
558 case AUDIO_ENCODING_ALAW:
559 swcode = mode == AUMODE_PLAY ?
560 alaw_to_ulinear8 : ulinear8_to_alaw;
561 break;
562 default:
563 return EINVAL;
564 }
565 tc = SB_RATE_TO_TC(p->sample_rate * p->channels);
566 p->sample_rate = SB_TC_TO_RATE(tc) / p->channels;
567 }
568
569 if (mode == AUMODE_PLAY) {
570 sc->sc_orate = rate;
571 sc->sc_otc = tc;
572 sc->sc_omodep = m;
573 sc->sc_obmode = bmode;
574 } else {
575 sc->sc_irate = rate;
576 sc->sc_itc = tc;
577 sc->sc_imodep = m;
578 sc->sc_ibmode = bmode;
579 }
580
581 p->sw_code = swcode;
582
583 /* Update setting for the other mode. */
584 q->encoding = p->encoding;
585 q->channels = p->channels;
586 q->precision = p->precision;
587
588 /*
589 * XXX
590 * Should wait for chip to be idle.
591 */
592 sc->sc_dmadir = SB_DMA_NONE;
593
594 DPRINTF(("set_params: model=%d, rate=%ld, prec=%d, chan=%d, enc=%d -> tc=%02x, cmd=%02x, bmode=%02x, cmdchan=%02x, swcode=%p\n",
595 sc->sc_model, p->sample_rate, p->precision, p->channels,
596 p->encoding, tc, m->cmd, bmode, m->cmdchan, swcode));
597
598 return 0;
599 }
600
601 void
602 sbdsp_set_ifilter(addr, which)
603 void *addr;
604 int which;
605 {
606 struct sbdsp_softc *sc = addr;
607 int mixval;
608
609 mixval = sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_IFILTER_MASK;
610 switch (which) {
611 case 0:
612 mixval |= SBP_FILTER_OFF;
613 break;
614 case SB_TREBLE:
615 mixval |= SBP_FILTER_ON | SBP_IFILTER_HIGH;
616 break;
617 case SB_BASS:
618 mixval |= SBP_FILTER_ON | SBP_IFILTER_LOW;
619 break;
620 default:
621 return;
622 }
623 sc->in_filter = mixval & SBP_IFILTER_MASK;
624 sbdsp_mix_write(sc, SBP_INFILTER, mixval);
625 }
626
627 int
628 sbdsp_get_ifilter(addr)
629 void *addr;
630 {
631 struct sbdsp_softc *sc = addr;
632
633 sc->in_filter =
634 sbdsp_mix_read(sc, SBP_INFILTER) & SBP_IFILTER_MASK;
635 switch (sc->in_filter) {
636 case SBP_FILTER_ON|SBP_IFILTER_HIGH:
637 return SB_TREBLE;
638 case SBP_FILTER_ON|SBP_IFILTER_LOW:
639 return SB_BASS;
640 default:
641 return 0;
642 }
643 }
644
645 int
646 sbdsp_set_out_port(addr, port)
647 void *addr;
648 int port;
649 {
650 struct sbdsp_softc *sc = addr;
651
652 sc->out_port = port; /* Just record it */
653
654 return 0;
655 }
656
657 int
658 sbdsp_get_out_port(addr)
659 void *addr;
660 {
661 struct sbdsp_softc *sc = addr;
662
663 return sc->out_port;
664 }
665
666
667 int
668 sbdsp_set_in_port(addr, port)
669 void *addr;
670 int port;
671 {
672 return sbdsp_set_in_ports(addr, 1 << port);
673 }
674
675 int
676 sbdsp_set_in_ports(sc, mask)
677 struct sbdsp_softc *sc;
678 int mask;
679 {
680 int bitsl, bitsr;
681 int sbport;
682 int i;
683
684 DPRINTF(("sbdsp_set_in_ports: model=%d, mask=%x\n",
685 sc->sc_mixer_model, mask));
686
687 switch(sc->sc_mixer_model) {
688 case SBM_NONE:
689 return EINVAL;
690 case SBM_CT1335:
691 if (mask != (1 << SB_MIC_VOL))
692 return EINVAL;
693 break;
694 case SBM_CT1345:
695 switch (mask) {
696 case 1 << SB_MIC_VOL:
697 sbport = SBP_FROM_MIC;
698 break;
699 case 1 << SB_LINE_IN_VOL:
700 sbport = SBP_FROM_LINE;
701 break;
702 case 1 << SB_CD_VOL:
703 sbport = SBP_FROM_CD;
704 break;
705 default:
706 return EINVAL;
707 }
708 sbdsp_mix_write(sc, SBP_RECORD_SOURCE,
709 SBP_RECORD_FROM(sbport, SBP_FILTER_OFF, SBP_IFILTER_HIGH));
710 break;
711 case SBM_CT1745:
712 if (mask & ~((1<<SB_MIDI_VOL) | (1<<SB_LINE_IN_VOL) |
713 (1<<SB_CD_VOL) | (1<<SB_MIC_VOL)))
714 return EINVAL;
715 bitsr = 0;
716 if (mask & SB_MIDI_VOL) bitsr |= SBP_MIDI_SRC_R;
717 if (mask & SB_LINE_IN_VOL) bitsr |= SBP_LINE_SRC_R;
718 if (mask & SB_CD_VOL) bitsr |= SBP_CD_SRC_R;
719 bitsl = SB_SRC_R_TO_L(bitsr);
720 if (mask & SB_MIC_VOL) {
721 bitsl |= SBP_MIC_SRC;
722 bitsr |= SBP_MIC_SRC;
723 }
724 sbdsp_mix_write(sc, SBP_RECORD_SOURCE_L, bitsl);
725 sbdsp_mix_write(sc, SBP_RECORD_SOURCE_R, bitsr);
726 break;
727 }
728
729 sc->in_mask = mask;
730
731 /* XXX
732 * We have to fake a single port since the upper layer
733 * expects one.
734 */
735 for(i = 0; i < SB_NPORT; i++) {
736 if (mask & (1 << i)) {
737 sc->in_port = i;
738 break;
739 }
740 }
741 return 0;
742 }
743
744 int
745 sbdsp_get_in_port(addr)
746 void *addr;
747 {
748 struct sbdsp_softc *sc = addr;
749
750 return sc->in_port;
751 }
752
753
754 int
755 sbdsp_speaker_ctl(addr, newstate)
756 void *addr;
757 int newstate;
758 {
759 struct sbdsp_softc *sc = addr;
760
761 if ((newstate == SPKR_ON) &&
762 (sc->spkr_state == SPKR_OFF)) {
763 sbdsp_spkron(sc);
764 sc->spkr_state = SPKR_ON;
765 }
766 if ((newstate == SPKR_OFF) &&
767 (sc->spkr_state == SPKR_ON)) {
768 sbdsp_spkroff(sc);
769 sc->spkr_state = SPKR_OFF;
770 }
771 return 0;
772 }
773
774 int
775 sbdsp_round_blocksize(addr, blk)
776 void *addr;
777 int blk;
778 {
779 if (blk > NBPG/3)
780 blk = NBPG/3; /* XXX allow at least 3 blocks */
781
782 /* Round to a multiple of the biggest sample size. */
783 blk &= -4;
784
785 return blk;
786 }
787
788 int
789 sbdsp_commit_settings(addr)
790 void *addr;
791 {
792 return 0;
793 }
794
795 int
796 sbdsp_open(sc, dev, flags)
797 struct sbdsp_softc *sc;
798 dev_t dev;
799 int flags;
800 {
801 DPRINTF(("sbdsp_open: sc=%p\n", sc));
802
803 if (sc->sc_open != 0 || sbdsp_reset(sc) != 0)
804 return ENXIO;
805
806 sc->sc_open = 1;
807 sc->sc_mintr = 0;
808 if (ISSBPRO(sc) &&
809 sbdsp_wdsp(sc, SB_DSP_RECORD_MONO) < 0) {
810 DPRINTF(("sbdsp_open: can't set mono mode\n"));
811 /* we'll readjust when it's time for DMA. */
812 }
813
814 /*
815 * Leave most things as they were; users must change things if
816 * the previous process didn't leave it they way they wanted.
817 * Looked at another way, it's easy to set up a configuration
818 * in one program and leave it for another to inherit.
819 */
820 DPRINTF(("sbdsp_open: opened\n"));
821
822 return 0;
823 }
824
825 void
826 sbdsp_close(addr)
827 void *addr;
828 {
829 struct sbdsp_softc *sc = addr;
830
831 DPRINTF(("sbdsp_close: sc=%p\n", sc));
832
833 sc->sc_open = 0;
834 sbdsp_spkroff(sc);
835 sc->spkr_state = SPKR_OFF;
836 sc->sc_intr = 0;
837 sc->sc_mintr = 0;
838 sbdsp_haltdma(sc);
839
840 DPRINTF(("sbdsp_close: closed\n"));
841 }
842
843 /*
844 * Lower-level routines
845 */
846
847 /*
848 * Reset the card.
849 * Return non-zero if the card isn't detected.
850 */
851 int
852 sbdsp_reset(sc)
853 struct sbdsp_softc *sc;
854 {
855 bus_space_tag_t iot = sc->sc_iot;
856 bus_space_handle_t ioh = sc->sc_ioh;
857
858 sc->sc_intr = 0;
859 if (sc->sc_dmadir != SB_DMA_NONE) {
860 isa_dmaabort(sc->dmachan);
861 sc->sc_dmadir = SB_DMA_NONE;
862 }
863
864 /*
865 * See SBK, section 11.3.
866 * We pulse a reset signal into the card.
867 * Gee, what a brilliant hardware design.
868 */
869 bus_space_write_1(iot, ioh, SBP_DSP_RESET, 1);
870 delay(10);
871 bus_space_write_1(iot, ioh, SBP_DSP_RESET, 0);
872 delay(30);
873 if (sbdsp_rdsp(sc) != SB_MAGIC)
874 return -1;
875
876 return 0;
877 }
878
879 int
880 sbdsp16_wait(sc)
881 struct sbdsp_softc *sc;
882 {
883 bus_space_tag_t iot = sc->sc_iot;
884 bus_space_handle_t ioh = sc->sc_ioh;
885 int i;
886 u_char x;
887
888 for (i = SBDSP_NPOLL; --i >= 0; ) {
889 x = bus_space_read_1(iot, ioh, SBP_DSP_WSTAT);
890 delay(10);
891 if ((x & SB_DSP_BUSY) == 0)
892 continue;
893 return 0;
894 }
895 ++sberr.wdsp;
896 return -1;
897 }
898
899 /*
900 * Write a byte to the dsp.
901 * XXX We are at the mercy of the card as we use a
902 * polling loop and wait until it can take the byte.
903 */
904 int
905 sbdsp_wdsp(sc, v)
906 struct sbdsp_softc *sc;
907 int v;
908 {
909 bus_space_tag_t iot = sc->sc_iot;
910 bus_space_handle_t ioh = sc->sc_ioh;
911 int i;
912 u_char x;
913
914 for (i = SBDSP_NPOLL; --i >= 0; ) {
915 x = bus_space_read_1(iot, ioh, SBP_DSP_WSTAT);
916 delay(10);
917 if ((x & SB_DSP_BUSY) != 0)
918 continue;
919 bus_space_write_1(iot, ioh, SBP_DSP_WRITE, v);
920 delay(10);
921 return 0;
922 }
923 ++sberr.wdsp;
924 return -1;
925 }
926
927 /*
928 * Read a byte from the DSP, using polling.
929 */
930 int
931 sbdsp_rdsp(sc)
932 struct sbdsp_softc *sc;
933 {
934 bus_space_tag_t iot = sc->sc_iot;
935 bus_space_handle_t ioh = sc->sc_ioh;
936 int i;
937 u_char x;
938
939 for (i = SBDSP_NPOLL; --i >= 0; ) {
940 x = bus_space_read_1(iot, ioh, SBP_DSP_RSTAT);
941 delay(10);
942 if ((x & SB_DSP_READY) == 0)
943 continue;
944 x = bus_space_read_1(iot, ioh, SBP_DSP_READ);
945 delay(10);
946 return x;
947 }
948 ++sberr.rdsp;
949 return -1;
950 }
951
952 /*
953 * Doing certain things (like toggling the speaker) make
954 * the SB hardware go away for a while, so pause a little.
955 */
956 void
957 sbdsp_to(arg)
958 void *arg;
959 {
960 wakeup(arg);
961 }
962
963 void
964 sbdsp_pause(sc)
965 struct sbdsp_softc *sc;
966 {
967 extern int hz;
968
969 timeout(sbdsp_to, sbdsp_to, hz/8);
970 (void)tsleep(sbdsp_to, PWAIT, "sbpause", 0);
971 }
972
973 /*
974 * Turn on the speaker. The SBK documention says this operation
975 * can take up to 1/10 of a second. Higher level layers should
976 * probably let the task sleep for this amount of time after
977 * calling here. Otherwise, things might not work (because
978 * sbdsp_wdsp() and sbdsp_rdsp() will probably timeout.)
979 *
980 * These engineers had their heads up their ass when
981 * they designed this card.
982 */
983 void
984 sbdsp_spkron(sc)
985 struct sbdsp_softc *sc;
986 {
987 (void)sbdsp_wdsp(sc, SB_DSP_SPKR_ON);
988 sbdsp_pause(sc);
989 }
990
991 /*
992 * Turn off the speaker; see comment above.
993 */
994 void
995 sbdsp_spkroff(sc)
996 struct sbdsp_softc *sc;
997 {
998 (void)sbdsp_wdsp(sc, SB_DSP_SPKR_OFF);
999 sbdsp_pause(sc);
1000 }
1001
1002 /*
1003 * Read the version number out of the card. Return major code
1004 * in high byte, and minor code in low byte.
1005 */
1006 void
1007 sbversion(sc)
1008 struct sbdsp_softc *sc;
1009 {
1010 int v;
1011
1012 sc->sc_model = SB_UNK;
1013 sc->sc_version = 0;
1014 if (sbdsp_wdsp(sc, SB_DSP_VERSION) < 0)
1015 return;
1016 v = sbdsp_rdsp(sc) << 8;
1017 v |= sbdsp_rdsp(sc);
1018 if (v < 0)
1019 return;
1020 sc->sc_version = v;
1021 switch(SBVER_MAJOR(v)) {
1022 case 1:
1023 sc->sc_mixer_model = SBM_NONE;
1024 sc->sc_model = SB_1;
1025 break;
1026 case 2:
1027 /* Some SB2 have a mixer, some don't. */
1028 sbdsp_mix_write(sc, SBP_1335_MASTER_VOL, 0x04);
1029 sbdsp_mix_write(sc, SBP_1335_MIDI_VOL, 0x06);
1030 /* Check if we can read back the mixer values. */
1031 if ((sbdsp_mix_read(sc, SBP_1335_MASTER_VOL) & 0x0e) == 0x04 &&
1032 (sbdsp_mix_read(sc, SBP_1335_MIDI_VOL) & 0x0e) == 0x06)
1033 sc->sc_mixer_model = SBM_CT1335;
1034 else
1035 sc->sc_mixer_model = SBM_NONE;
1036 if (SBVER_MINOR(v) == 0)
1037 sc->sc_model = SB_20;
1038 else
1039 sc->sc_model = SB_2x;
1040 break;
1041 case 3:
1042 sc->sc_mixer_model = SBM_CT1345;
1043 sc->sc_model = SB_PRO;
1044 break;
1045 case 4:
1046 sc->sc_mixer_model = SBM_CT1745;
1047 sc->sc_model = SB_16;
1048 break;
1049 }
1050 }
1051
1052 /*
1053 * Halt a DMA in progress. A low-speed transfer can be
1054 * resumed with sbdsp_contdma().
1055 */
1056 int
1057 sbdsp_haltdma(addr)
1058 void *addr;
1059 {
1060 struct sbdsp_softc *sc = addr;
1061
1062 DPRINTF(("sbdsp_haltdma: sc=%p\n", sc));
1063
1064 sbdsp_reset(sc);
1065 return 0;
1066 }
1067
1068 int
1069 sbdsp_contdma(addr)
1070 void *addr;
1071 {
1072 struct sbdsp_softc *sc = addr;
1073
1074 DPRINTF(("sbdsp_contdma: sc=%p\n", sc));
1075
1076 /* XXX how do we reinitialize the DMA controller state? do we care? */
1077 (void)sbdsp_wdsp(sc, SB_DSP_CONT);
1078 return 0;
1079 }
1080
1081 int
1082 sbdsp_set_timeconst(sc, tc)
1083 struct sbdsp_softc *sc;
1084 int tc;
1085 {
1086 DPRINTF(("sbdsp_set_timeconst: sc=%p tc=%d\n", sc, tc));
1087
1088 if (sbdsp_wdsp(sc, SB_DSP_TIMECONST) < 0 ||
1089 sbdsp_wdsp(sc, tc) < 0)
1090 return EIO;
1091
1092 return 0;
1093 }
1094
1095 int
1096 sbdsp16_set_rate(sc, cmd, rate)
1097 struct sbdsp_softc *sc;
1098 int cmd, rate;
1099 {
1100 DPRINTF(("sbdsp16_set_rate: sc=%p rate=%d\n", sc, rate));
1101
1102 if (sbdsp_wdsp(sc, cmd) < 0 ||
1103 sbdsp_wdsp(sc, rate >> 8) < 0 ||
1104 sbdsp_wdsp(sc, rate) < 0)
1105 return EIO;
1106 return 0;
1107 }
1108
1109 int
1110 sbdsp_dma_input(addr, p, cc, intr, arg)
1111 void *addr;
1112 void *p;
1113 int cc;
1114 void (*intr) __P((void *));
1115 void *arg;
1116 {
1117 struct sbdsp_softc *sc = addr;
1118 int loop = sc->sc_model != SB_1;
1119 int stereo = sc->sc_imodep->channels == 2;
1120 int filter;
1121
1122 #ifdef AUDIO_DEBUG
1123 if (sbdspdebug > 1)
1124 Dprintf("sbdsp_dma_input: cc=%d 0x%x (0x%x)\n", cc, intr, arg);
1125 #endif
1126 #ifdef DIAGNOSTIC
1127 if (sc->sc_imodep->channels == 2 && (cc & 1)) {
1128 DPRINTF(("stereo record odd bytes (%d)\n", cc));
1129 return EIO;
1130 }
1131 #endif
1132
1133 if (sc->sc_dmadir != SB_DMA_IN) {
1134 if (ISSBPRO(sc)) {
1135 if (sbdsp_wdsp(sc, sc->sc_imodep->cmdchan) < 0)
1136 goto badmode;
1137 filter = stereo ? SBP_FILTER_OFF : sc->in_filter;
1138 sbdsp_mix_write(sc, SBP_INFILTER,
1139 (sbdsp_mix_read(sc, SBP_INFILTER) &
1140 ~SBP_IFILTER_MASK) | filter);
1141 }
1142
1143 if (ISSB16CLASS(sc)) {
1144 if (sbdsp16_set_rate(sc, SB_DSP16_INPUTRATE,
1145 sc->sc_irate))
1146 goto giveup;
1147 } else {
1148 if (sbdsp_set_timeconst(sc, sc->sc_itc))
1149 goto giveup;
1150 }
1151
1152 sc->sc_dmadir = SB_DMA_IN;
1153 sc->dmaflags = DMAMODE_READ;
1154 if (loop)
1155 sc->dmaflags |= DMAMODE_LOOP;
1156 } else {
1157 /* If already started; just return. */
1158 if (loop)
1159 return 0;
1160 }
1161
1162 sc->dmaaddr = p;
1163 sc->dmacnt = loop ? (NBPG/cc)*cc : cc;
1164 sc->dmachan = sc->sc_imodep->precision == 16 ? sc->sc_drq16 : sc->sc_drq8;
1165 #ifdef AUDIO_DEBUG
1166 if (sbdspdebug > 1)
1167 Dprintf("sbdsp_dma_input: dmastart %x %p %d %d\n",
1168 sc->dmaflags, sc->dmaaddr, sc->dmacnt, sc->dmachan);
1169 #endif
1170 isa_dmastart(sc->dmaflags, sc->dmaaddr, sc->dmacnt, sc->dmachan);
1171 sc->sc_intr = intr;
1172 sc->sc_arg = arg;
1173
1174 if (sc->sc_imodep->precision == 16)
1175 cc >>= 1;
1176 --cc;
1177 if (ISSB16CLASS(sc)) {
1178 if (sbdsp_wdsp(sc, sc->sc_imodep->cmd) < 0 ||
1179 sbdsp_wdsp(sc, sc->sc_ibmode) < 0 ||
1180 sbdsp16_wait(sc) ||
1181 sbdsp_wdsp(sc, cc) < 0 ||
1182 sbdsp_wdsp(sc, cc >> 8) < 0) {
1183 DPRINTF(("sbdsp_dma_input: SB16 DMA start failed\n"));
1184 goto giveup;
1185 }
1186 } else {
1187 if (loop) {
1188 DPRINTF(("sbdsp_dma_input: set blocksize=%d\n", cc));
1189 if (sbdsp_wdsp(sc, SB_DSP_BLOCKSIZE) < 0 ||
1190 sbdsp_wdsp(sc, cc) < 0 ||
1191 sbdsp_wdsp(sc, cc >> 8) < 0) {
1192 DPRINTF(("sbdsp_dma_input: SB2 DMA start failed\n"));
1193 goto giveup;
1194 }
1195 if (sbdsp_wdsp(sc, sc->sc_imodep->cmd) < 0) {
1196 DPRINTF(("sbdsp_dma_input: SB2 DMA restart failed\n"));
1197 goto giveup;
1198 }
1199 } else {
1200 if (sbdsp_wdsp(sc, sc->sc_imodep->cmd) < 0 ||
1201 sbdsp_wdsp(sc, cc) < 0 ||
1202 sbdsp_wdsp(sc, cc >> 8) < 0) {
1203 DPRINTF(("sbdsp_dma_input: SB1 DMA start failed\n"));
1204 goto giveup;
1205 }
1206 }
1207 }
1208 return 0;
1209
1210 giveup:
1211 sbdsp_reset(sc);
1212 return EIO;
1213
1214 badmode:
1215 DPRINTF(("sbdsp_dma_input: can't set mode\n"));
1216 return EIO;
1217 }
1218
1219 int
1220 sbdsp_dma_output(addr, p, cc, intr, arg)
1221 void *addr;
1222 void *p;
1223 int cc;
1224 void (*intr) __P((void *));
1225 void *arg;
1226 {
1227 struct sbdsp_softc *sc = addr;
1228 int loop = sc->sc_model != SB_1;
1229 int stereo = sc->sc_omodep->channels == 2;
1230 int cmd;
1231
1232 #ifdef AUDIO_DEBUG
1233 if (sbdspdebug > 1)
1234 Dprintf("sbdsp_dma_output: cc=%d 0x%x (0x%x)\n", cc, intr, arg);
1235 #endif
1236 #ifdef DIAGNOSTIC
1237 if (sc->sc_omodep->channels == 2 && (cc & 1)) {
1238 DPRINTF(("stereo playback odd bytes (%d)\n", cc));
1239 return EIO;
1240 }
1241 #endif
1242
1243 if (sc->sc_dmadir != SB_DMA_OUT) {
1244 if (ISSBPRO(sc)) {
1245 /* make sure we re-set stereo mixer bit when we start
1246 output. */
1247 sbdsp_mix_write(sc, SBP_STEREO,
1248 (sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK) |
1249 (stereo ? SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO));
1250 cmd = sc->sc_omodep->cmdchan;
1251 if (cmd && sbdsp_wdsp(sc, cmd) < 0)
1252 goto badmode;
1253 }
1254
1255 if (ISSB16CLASS(sc)) {
1256 if (sbdsp16_set_rate(sc, SB_DSP16_OUTPUTRATE,
1257 sc->sc_orate))
1258 goto giveup;
1259 } else {
1260 if (sbdsp_set_timeconst(sc, sc->sc_otc))
1261 goto giveup;
1262 }
1263
1264 sc->sc_dmadir = SB_DMA_OUT;
1265 sc->dmaflags = DMAMODE_WRITE;
1266 if (loop)
1267 sc->dmaflags |= DMAMODE_LOOP;
1268 } else {
1269 /* Already started; just return. */
1270 if (loop)
1271 return 0;
1272 }
1273
1274 sc->dmaaddr = p;
1275 sc->dmacnt = loop ? (NBPG/cc)*cc : cc;
1276 sc->dmachan = sc->sc_omodep->precision == 16 ? sc->sc_drq16 : sc->sc_drq8;
1277 #ifdef AUDIO_DEBUG
1278 if (sbdspdebug > 1)
1279 Dprintf("sbdsp_dma_output: dmastart %x %p %d %d\n",
1280 sc->dmaflags, sc->dmaaddr, sc->dmacnt, sc->dmachan);
1281 #endif
1282 isa_dmastart(sc->dmaflags, sc->dmaaddr, sc->dmacnt, sc->dmachan);
1283 sc->sc_intr = intr;
1284 sc->sc_arg = arg;
1285
1286 if (sc->sc_omodep->precision == 16)
1287 cc >>= 1;
1288 --cc;
1289 if (ISSB16CLASS(sc)) {
1290 if (sbdsp_wdsp(sc, sc->sc_omodep->cmd) < 0 ||
1291 sbdsp_wdsp(sc, sc->sc_obmode) < 0 ||
1292 sbdsp16_wait(sc) ||
1293 sbdsp_wdsp(sc, cc) < 0 ||
1294 sbdsp_wdsp(sc, cc >> 8) < 0) {
1295 DPRINTF(("sbdsp_dma_output: SB16 DMA start failed\n"));
1296 goto giveup;
1297 }
1298 } else {
1299 if (loop) {
1300 DPRINTF(("sbdsp_dma_output: set blocksize=%d\n", cc));
1301 if (sbdsp_wdsp(sc, SB_DSP_BLOCKSIZE) < 0 ||
1302 sbdsp_wdsp(sc, cc) < 0 ||
1303 sbdsp_wdsp(sc, cc >> 8) < 0) {
1304 DPRINTF(("sbdsp_dma_output: SB2 DMA blocksize failed\n"));
1305 goto giveup;
1306 }
1307 if (sbdsp_wdsp(sc, sc->sc_omodep->cmd) < 0) {
1308 DPRINTF(("sbdsp_dma_output: SB2 DMA start failed\n"));
1309 goto giveup;
1310 }
1311 } else {
1312 if (sbdsp_wdsp(sc, sc->sc_omodep->cmd) < 0 ||
1313 sbdsp_wdsp(sc, cc) < 0 ||
1314 sbdsp_wdsp(sc, cc >> 8) < 0) {
1315 DPRINTF(("sbdsp_dma_output: SB1 DMA start failed\n"));
1316 goto giveup;
1317 }
1318 }
1319 }
1320 return 0;
1321
1322 giveup:
1323 sbdsp_reset(sc);
1324 return EIO;
1325
1326 badmode:
1327 DPRINTF(("sbdsp_dma_output: can't set mode\n"));
1328 return EIO;
1329 }
1330
1331 /*
1332 * Only the DSP unit on the sound blaster generates interrupts.
1333 * There are three cases of interrupt: reception of a midi byte
1334 * (when mode is enabled), completion of dma transmission, or
1335 * completion of a dma reception. The three modes are mutually
1336 * exclusive so we know a priori which event has occurred.
1337 */
1338 int
1339 sbdsp_intr(arg)
1340 void *arg;
1341 {
1342 struct sbdsp_softc *sc = arg;
1343 int loop = sc->sc_model != SB_1;
1344 u_char irq;
1345
1346 #ifdef AUDIO_DEBUG
1347 if (sbdspdebug > 1)
1348 Dprintf("sbdsp_intr: intr=0x%x\n", sc->sc_intr);
1349 #endif
1350 if (ISSB16CLASS(sc)) {
1351 irq = sbdsp_mix_read(sc, SBP_IRQ_STATUS);
1352 if ((irq & (SBP_IRQ_DMA8 | SBP_IRQ_DMA16)) == 0)
1353 return 0;
1354 } else {
1355 if (!loop && !isa_dmafinished(sc->dmachan))
1356 return 0;
1357 irq = SBP_IRQ_DMA8;
1358 }
1359 sc->sc_interrupts++;
1360 delay(10); /* XXX why? */
1361 #if 0
1362 if (sc->sc_mintr != 0) {
1363 x = sbdsp_rdsp(sc);
1364 (*sc->sc_mintr)(sc->sc_arg, x);
1365 } else
1366 #endif
1367 if (sc->sc_intr != 0) {
1368 /* clear interrupt */
1369 if (irq & SBP_IRQ_DMA8)
1370 bus_space_read_1(sc->sc_iot, sc->sc_ioh, SBP_DSP_IRQACK8);
1371 if (irq & SBP_IRQ_DMA16)
1372 bus_space_read_1(sc->sc_iot, sc->sc_ioh, SBP_DSP_IRQACK16);
1373 if (!loop)
1374 isa_dmadone(sc->dmaflags, sc->dmaaddr, sc->dmacnt,
1375 sc->dmachan);
1376 (*sc->sc_intr)(sc->sc_arg);
1377 } else {
1378 return 0;
1379 }
1380 return 1;
1381 }
1382
1383 #if 0
1384 /*
1385 * Enter midi uart mode and arrange for read interrupts
1386 * to vector to `intr'. This puts the card in a mode
1387 * which allows only midi I/O; the card must be reset
1388 * to leave this mode. Unfortunately, the card does not
1389 * use transmit interrupts, so bytes must be output
1390 * using polling. To keep the polling overhead to a
1391 * minimum, output should be driven off a timer.
1392 * This is a little tricky since only 320us separate
1393 * consecutive midi bytes.
1394 */
1395 void
1396 sbdsp_set_midi_mode(sc, intr, arg)
1397 struct sbdsp_softc *sc;
1398 void (*intr)();
1399 void *arg;
1400 {
1401
1402 sbdsp_wdsp(sc, SB_MIDI_UART_INTR);
1403 sc->sc_mintr = intr;
1404 sc->sc_intr = 0;
1405 sc->sc_arg = arg;
1406 }
1407
1408 /*
1409 * Write a byte to the midi port, when in midi uart mode.
1410 */
1411 void
1412 sbdsp_midi_output(sc, v)
1413 struct sbdsp_softc *sc;
1414 int v;
1415 {
1416
1417 if (sbdsp_wdsp(sc, v) < 0)
1418 ++sberr.wmidi;
1419 }
1420 #endif
1421
1422 int
1423 sbdsp_setfd(addr, flag)
1424 void *addr;
1425 int flag;
1426 {
1427 /* Can't do full-duplex */
1428 return ENOTTY;
1429 }
1430
1431 void
1432 sbdsp_set_mixer_gain(sc, port)
1433 struct sbdsp_softc *sc;
1434 int port;
1435 {
1436 int src, gain;
1437
1438 switch(sc->sc_mixer_model) {
1439 case SBM_NONE:
1440 return;
1441 case SBM_CT1335:
1442 gain = SB_1335_GAIN(sc->gain[port][SB_LEFT]);
1443 switch(port) {
1444 case SB_MASTER_VOL:
1445 src = SBP_1335_MASTER_VOL;
1446 break;
1447 case SB_MIDI_VOL:
1448 src = SBP_1335_MIDI_VOL;
1449 break;
1450 case SB_CD_VOL:
1451 src = SBP_1335_CD_VOL;
1452 break;
1453 case SB_VOICE_VOL:
1454 src = SBP_1335_VOICE_VOL;
1455 gain = SB_1335_MASTER_GAIN(sc->gain[port][SB_LEFT]);
1456 break;
1457 default:
1458 return;
1459 }
1460 sbdsp_mix_write(sc, src, gain);
1461 break;
1462 case SBM_CT1345:
1463 gain = SB_STEREO_GAIN(sc->gain[port][SB_LEFT],
1464 sc->gain[port][SB_RIGHT]);
1465 switch (port) {
1466 case SB_MIC_VOL:
1467 src = SBP_MIC_VOL;
1468 gain = SB_MIC_GAIN(sc->gain[port][SB_LEFT]);
1469 break;
1470 case SB_MASTER_VOL:
1471 src = SBP_MASTER_VOL;
1472 break;
1473 case SB_LINE_IN_VOL:
1474 src = SBP_LINE_VOL;
1475 break;
1476 case SB_VOICE_VOL:
1477 src = SBP_VOICE_VOL;
1478 break;
1479 case SB_MIDI_VOL:
1480 src = SBP_MIDI_VOL;
1481 break;
1482 case SB_CD_VOL:
1483 src = SBP_CD_VOL;
1484 break;
1485 default:
1486 return;
1487 }
1488 sbdsp_mix_write(sc, src, gain);
1489 break;
1490 case SBM_CT1745:
1491 switch (port) {
1492 case SB_MIC_VOL:
1493 src = SB16P_MIC_L;
1494 break;
1495 case SB_MASTER_VOL:
1496 src = SB16P_MASTER_L;
1497 break;
1498 case SB_LINE_IN_VOL:
1499 src = SB16P_LINE_L;
1500 break;
1501 case SB_VOICE_VOL:
1502 src = SB16P_VOICE_L;
1503 break;
1504 case SB_MIDI_VOL:
1505 src = SB16P_MIDI_L;
1506 break;
1507 case SB_CD_VOL:
1508 src = SB16P_CD_L;
1509 break;
1510 case SB_INPUT_GAIN:
1511 src = SB16P_INPUT_GAIN_L;
1512 break;
1513 case SB_OUTPUT_GAIN:
1514 src = SB16P_OUTPUT_GAIN_L;
1515 break;
1516 case SB_TREBLE:
1517 src = SB16P_TREBLE_L;
1518 break;
1519 case SB_BASS:
1520 src = SB16P_BASS_L;
1521 break;
1522 case SB_PCSPEAKER:
1523 sbdsp_mix_write(sc, SB16P_PCSPEAKER, sc->gain[port][SB_LEFT]);
1524 return;
1525 default:
1526 return;
1527 }
1528 sbdsp_mix_write(sc, src, sc->gain[port][SB_LEFT]);
1529 sbdsp_mix_write(sc, SB16P_L_TO_R(src), sc->gain[port][SB_RIGHT]);
1530 break;
1531 }
1532 }
1533
1534 int
1535 sbdsp_mixer_set_port(addr, cp)
1536 void *addr;
1537 mixer_ctrl_t *cp;
1538 {
1539 struct sbdsp_softc *sc = addr;
1540 int lgain, rgain;
1541
1542 DPRINTF(("sbdsp_mixer_set_port: port=%d num_channels=%d\n", cp->dev,
1543 cp->un.value.num_channels));
1544
1545 if (sc->sc_mixer_model == SBM_NONE)
1546 return EINVAL;
1547
1548 switch (cp->dev) {
1549 case SB_TREBLE:
1550 case SB_BASS:
1551 if (sc->sc_mixer_model == SBM_CT1345) {
1552 if (cp->type != AUDIO_MIXER_ENUM)
1553 return EINVAL;
1554 switch (cp->dev) {
1555 case SB_TREBLE:
1556 sbdsp_set_ifilter(addr, cp->un.ord ? SB_TREBLE : 0);
1557 return 0;
1558 case SB_BASS:
1559 sbdsp_set_ifilter(addr, cp->un.ord ? SB_BASS : 0);
1560 return 0;
1561 }
1562 }
1563 case SB_PCSPEAKER:
1564 case SB_INPUT_GAIN:
1565 case SB_OUTPUT_GAIN:
1566 if (sc->sc_mixer_model != SBM_CT1745)
1567 return EINVAL;
1568 case SB_MIC_VOL:
1569 case SB_LINE_IN_VOL:
1570 if (sc->sc_mixer_model == SBM_CT1335)
1571 return EINVAL;
1572 case SB_VOICE_VOL:
1573 case SB_MIDI_VOL:
1574 case SB_CD_VOL:
1575 case SB_MASTER_VOL:
1576 if (cp->type != AUDIO_MIXER_VALUE)
1577 return EINVAL;
1578
1579 /*
1580 * All the mixer ports are stereo except for the microphone.
1581 * If we get a single-channel gain value passed in, then we
1582 * duplicate it to both left and right channels.
1583 */
1584
1585 switch (cp->dev) {
1586 case SB_MIC_VOL:
1587 if (cp->un.value.num_channels != 1)
1588 return EINVAL;
1589
1590 lgain = rgain = SB_ADJUST_MIC_GAIN(sc,
1591 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1592 break;
1593 case SB_PCSPEAKER:
1594 if (cp->un.value.num_channels != 1)
1595 return EINVAL;
1596 /* fall into */
1597 case SB_INPUT_GAIN:
1598 case SB_OUTPUT_GAIN:
1599 lgain = rgain = SB_ADJUST_2_GAIN(sc,
1600 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1601 break;
1602 default:
1603 switch (cp->un.value.num_channels) {
1604 case 1:
1605 lgain = rgain = SB_ADJUST_GAIN(sc,
1606 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1607 break;
1608 case 2:
1609 if (sc->sc_mixer_model == SBM_CT1335)
1610 return EINVAL;
1611 lgain = SB_ADJUST_GAIN(sc,
1612 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]);
1613 rgain = SB_ADJUST_GAIN(sc,
1614 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]);
1615 break;
1616 default:
1617 return EINVAL;
1618 }
1619 break;
1620 }
1621 sc->gain[cp->dev][SB_LEFT] = lgain;
1622 sc->gain[cp->dev][SB_RIGHT] = rgain;
1623
1624 sbdsp_set_mixer_gain(sc, cp->dev);
1625 break;
1626
1627 case SB_RECORD_SOURCE:
1628 if (sc->sc_mixer_model == SBM_CT1745) {
1629 if (cp->type != AUDIO_MIXER_SET)
1630 return EINVAL;
1631 return sbdsp_set_in_ports(sc, cp->un.mask);
1632 } else {
1633 if (cp->type != AUDIO_MIXER_ENUM)
1634 return EINVAL;
1635 return sbdsp_set_in_port(sc, cp->un.ord);
1636 }
1637 break;
1638
1639 case SB_AGC:
1640 if (sc->sc_mixer_model != SBM_CT1745 || cp->type != AUDIO_MIXER_ENUM)
1641 return EINVAL;
1642 sbdsp_mix_write(sc, SB16P_AGC, cp->un.ord & 1);
1643 break;
1644
1645 default:
1646 return EINVAL;
1647 }
1648
1649 return 0;
1650 }
1651
1652 int
1653 sbdsp_mixer_get_port(addr, cp)
1654 void *addr;
1655 mixer_ctrl_t *cp;
1656 {
1657 struct sbdsp_softc *sc = addr;
1658
1659 DPRINTF(("sbdsp_mixer_get_port: port=%d\n", cp->dev));
1660
1661 if (sc->sc_mixer_model == SBM_NONE)
1662 return EINVAL;
1663
1664 switch (cp->dev) {
1665 case SB_TREBLE:
1666 case SB_BASS:
1667 if (sc->sc_mixer_model == SBM_CT1345) {
1668 switch (cp->dev) {
1669 case SB_TREBLE:
1670 cp->un.ord = sbdsp_get_ifilter(addr) == SB_TREBLE;
1671 return 0;
1672 case SB_BASS:
1673 cp->un.ord = sbdsp_get_ifilter(addr) == SB_BASS;
1674 return 0;
1675 }
1676 }
1677 case SB_PCSPEAKER:
1678 case SB_INPUT_GAIN:
1679 case SB_OUTPUT_GAIN:
1680 if (sc->sc_mixer_model != SBM_CT1745)
1681 return EINVAL;
1682 case SB_MIC_VOL:
1683 case SB_LINE_IN_VOL:
1684 if (sc->sc_mixer_model == SBM_CT1335)
1685 return EINVAL;
1686 case SB_VOICE_VOL:
1687 case SB_MIDI_VOL:
1688 case SB_CD_VOL:
1689 case SB_MASTER_VOL:
1690 switch (cp->dev) {
1691 case SB_MIC_VOL:
1692 case SB_PCSPEAKER:
1693 if (cp->un.value.num_channels != 1)
1694 return EINVAL;
1695 /* fall into */
1696 default:
1697 switch (cp->un.value.num_channels) {
1698 case 1:
1699 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1700 sc->gain[cp->dev][SB_LEFT];
1701 break;
1702 case 2:
1703 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
1704 sc->gain[cp->dev][SB_LEFT];
1705 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
1706 sc->gain[cp->dev][SB_RIGHT];
1707 break;
1708 default:
1709 return EINVAL;
1710 }
1711 break;
1712 }
1713 break;
1714
1715 case SB_RECORD_SOURCE:
1716 if (sc->sc_mixer_model == SBM_CT1745)
1717 cp->un.mask = sc->in_mask;
1718 else
1719 cp->un.ord = sc->in_port;
1720 break;
1721
1722 case SB_AGC:
1723 if (sc->sc_mixer_model != SBM_CT1745)
1724 return EINVAL;
1725 cp->un.ord = sbdsp_mix_read(sc, SB16P_AGC);
1726 break;
1727
1728 default:
1729 return EINVAL;
1730 }
1731
1732 return 0;
1733 }
1734
1735 int
1736 sbdsp_mixer_query_devinfo(addr, dip)
1737 void *addr;
1738 mixer_devinfo_t *dip;
1739 {
1740 struct sbdsp_softc *sc = addr;
1741 int chan, class;
1742
1743 DPRINTF(("sbdsp_mixer_query_devinfo: model=%d index=%d\n",
1744 sc->sc_mixer_model, dip->index));
1745
1746 if (sc->sc_mixer_model == SBM_NONE)
1747 return ENXIO;
1748
1749 chan = sc->sc_mixer_model == SBM_CT1335 ? 1 : 2;
1750 class = sc->sc_mixer_model == SBM_CT1745 ? SB_INPUT_CLASS : SB_OUTPUT_CLASS;
1751
1752 switch (dip->index) {
1753 case SB_MASTER_VOL:
1754 dip->type = AUDIO_MIXER_VALUE;
1755 dip->mixer_class = SB_OUTPUT_CLASS;
1756 dip->prev = dip->next = AUDIO_MIXER_LAST;
1757 strcpy(dip->label.name, AudioNmaster);
1758 dip->un.v.num_channels = chan;
1759 strcpy(dip->un.v.units.name, AudioNvolume);
1760 return 0;
1761 case SB_MIDI_VOL:
1762 dip->type = AUDIO_MIXER_VALUE;
1763 dip->mixer_class = class;
1764 dip->prev = AUDIO_MIXER_LAST;
1765 dip->next = AUDIO_MIXER_LAST;
1766 strcpy(dip->label.name, AudioNfmsynth);
1767 dip->un.v.num_channels = chan;
1768 strcpy(dip->un.v.units.name, AudioNvolume);
1769 return 0;
1770 case SB_CD_VOL:
1771 dip->type = AUDIO_MIXER_VALUE;
1772 dip->mixer_class = class;
1773 dip->prev = AUDIO_MIXER_LAST;
1774 dip->next = AUDIO_MIXER_LAST;
1775 strcpy(dip->label.name, AudioNcd);
1776 dip->un.v.num_channels = chan;
1777 strcpy(dip->un.v.units.name, AudioNvolume);
1778 return 0;
1779 case SB_VOICE_VOL:
1780 dip->type = AUDIO_MIXER_VALUE;
1781 dip->mixer_class = class;
1782 dip->prev = AUDIO_MIXER_LAST;
1783 dip->next = AUDIO_MIXER_LAST;
1784 strcpy(dip->label.name, AudioNdac);
1785 dip->un.v.num_channels = chan;
1786 strcpy(dip->un.v.units.name, AudioNvolume);
1787 return 0;
1788 case SB_OUTPUT_CLASS:
1789 dip->type = AUDIO_MIXER_CLASS;
1790 dip->mixer_class = SB_OUTPUT_CLASS;
1791 dip->next = dip->prev = AUDIO_MIXER_LAST;
1792 strcpy(dip->label.name, AudioCOutputs);
1793 return 0;
1794 }
1795
1796 if (sc->sc_mixer_model == SBM_CT1335)
1797 return ENXIO;
1798
1799 switch (dip->index) {
1800 case SB_MIC_VOL:
1801 dip->type = AUDIO_MIXER_VALUE;
1802 dip->mixer_class = class;
1803 dip->prev = AUDIO_MIXER_LAST;
1804 dip->next = AUDIO_MIXER_LAST;
1805 strcpy(dip->label.name, AudioNmicrophone);
1806 dip->un.v.num_channels = 1;
1807 strcpy(dip->un.v.units.name, AudioNvolume);
1808 return 0;
1809
1810 case SB_LINE_IN_VOL:
1811 dip->type = AUDIO_MIXER_VALUE;
1812 dip->mixer_class = class;
1813 dip->prev = AUDIO_MIXER_LAST;
1814 dip->next = AUDIO_MIXER_LAST;
1815 strcpy(dip->label.name, AudioNline);
1816 dip->un.v.num_channels = 2;
1817 strcpy(dip->un.v.units.name, AudioNvolume);
1818 return 0;
1819
1820 case SB_RECORD_SOURCE:
1821 dip->mixer_class = SB_RECORD_CLASS;
1822 dip->prev = dip->next = AUDIO_MIXER_LAST;
1823 strcpy(dip->label.name, AudioNsource);
1824 if (sc->sc_mixer_model == SBM_CT1745) {
1825 dip->type = AUDIO_MIXER_SET;
1826 dip->un.s.num_mem = 4;
1827 strcpy(dip->un.s.member[0].label.name, AudioNmicrophone);
1828 dip->un.s.member[0].mask = 1 << SB_MIC_VOL;
1829 strcpy(dip->un.s.member[1].label.name, AudioNcd);
1830 dip->un.s.member[1].mask = 1 << SB_CD_VOL;
1831 strcpy(dip->un.s.member[2].label.name, AudioNline);
1832 dip->un.s.member[2].mask = 1 << SB_LINE_IN_VOL;
1833 strcpy(dip->un.s.member[3].label.name, AudioNfmsynth);
1834 dip->un.s.member[3].mask = 1 << SB_MIDI_VOL;
1835 } else {
1836 dip->type = AUDIO_MIXER_ENUM;
1837 dip->un.e.num_mem = 3;
1838 strcpy(dip->un.e.member[0].label.name, AudioNmicrophone);
1839 dip->un.e.member[0].ord = SB_MIC_VOL;
1840 strcpy(dip->un.e.member[1].label.name, AudioNcd);
1841 dip->un.e.member[1].ord = SB_CD_VOL;
1842 strcpy(dip->un.e.member[2].label.name, AudioNline);
1843 dip->un.e.member[2].ord = SB_LINE_IN_VOL;
1844 }
1845 return 0;
1846
1847 case SB_BASS:
1848 dip->prev = dip->next = AUDIO_MIXER_LAST;
1849 strcpy(dip->label.name, AudioNbass);
1850 if (sc->sc_mixer_model == SBM_CT1745) {
1851 dip->type = AUDIO_MIXER_VALUE;
1852 dip->mixer_class = SB_EQUALIZATION_CLASS;
1853 dip->un.v.num_channels = 2;
1854 strcpy(dip->un.v.units.name, AudioNbass);
1855 } else {
1856 dip->type = AUDIO_MIXER_ENUM;
1857 dip->mixer_class = SB_INPUT_CLASS;
1858 dip->un.e.num_mem = 2;
1859 strcpy(dip->un.e.member[0].label.name, AudioNoff);
1860 dip->un.e.member[0].ord = 0;
1861 strcpy(dip->un.e.member[1].label.name, AudioNon);
1862 dip->un.e.member[1].ord = 1;
1863 }
1864 return 0;
1865
1866 case SB_TREBLE:
1867 dip->prev = dip->next = AUDIO_MIXER_LAST;
1868 strcpy(dip->label.name, AudioNtreble);
1869 if (sc->sc_mixer_model == SBM_CT1745) {
1870 dip->type = AUDIO_MIXER_VALUE;
1871 dip->mixer_class = SB_EQUALIZATION_CLASS;
1872 dip->un.v.num_channels = 2;
1873 strcpy(dip->un.v.units.name, AudioNtreble);
1874 } else {
1875 dip->type = AUDIO_MIXER_ENUM;
1876 dip->mixer_class = SB_INPUT_CLASS;
1877 dip->un.e.num_mem = 2;
1878 strcpy(dip->un.e.member[0].label.name, AudioNoff);
1879 dip->un.e.member[0].ord = 0;
1880 strcpy(dip->un.e.member[1].label.name, AudioNon);
1881 dip->un.e.member[1].ord = 1;
1882 }
1883 return 0;
1884
1885 case SB_RECORD_CLASS: /* record source class */
1886 dip->type = AUDIO_MIXER_CLASS;
1887 dip->mixer_class = SB_RECORD_CLASS;
1888 dip->next = dip->prev = AUDIO_MIXER_LAST;
1889 strcpy(dip->label.name, AudioCRecord);
1890 return 0;
1891
1892 }
1893
1894 if (sc->sc_mixer_model == SBM_CT1345)
1895 return ENXIO;
1896
1897 switch(dip->index) {
1898 case SB_PCSPEAKER:
1899 dip->type = AUDIO_MIXER_VALUE;
1900 dip->mixer_class = SB_INPUT_CLASS;
1901 dip->prev = dip->next = AUDIO_MIXER_LAST;
1902 strcpy(dip->label.name, "pc_speaker");
1903 dip->un.v.num_channels = 1;
1904 strcpy(dip->un.v.units.name, AudioNvolume);
1905 return 0;
1906
1907 case SB_INPUT_GAIN:
1908 dip->type = AUDIO_MIXER_VALUE;
1909 dip->mixer_class = SB_INPUT_CLASS;
1910 dip->prev = dip->next = AUDIO_MIXER_LAST;
1911 strcpy(dip->label.name, AudioNinput);
1912 dip->un.v.num_channels = 2;
1913 strcpy(dip->un.v.units.name, AudioNvolume);
1914 return 0;
1915
1916 case SB_OUTPUT_GAIN:
1917 dip->type = AUDIO_MIXER_VALUE;
1918 dip->mixer_class = SB_OUTPUT_CLASS;
1919 dip->prev = dip->next = AUDIO_MIXER_LAST;
1920 strcpy(dip->label.name, AudioNoutput);
1921 dip->un.v.num_channels = 2;
1922 strcpy(dip->un.v.units.name, AudioNvolume);
1923 return 0;
1924
1925 case SB_AGC:
1926 dip->type = AUDIO_MIXER_ENUM;
1927 dip->mixer_class = SB_INPUT_CLASS;
1928 dip->prev = dip->next = AUDIO_MIXER_LAST;
1929 strcpy(dip->label.name, "AGC");
1930 dip->un.e.num_mem = 2;
1931 strcpy(dip->un.e.member[0].label.name, AudioNoff);
1932 dip->un.e.member[0].ord = 0;
1933 strcpy(dip->un.e.member[1].label.name, AudioNon);
1934 dip->un.e.member[1].ord = 1;
1935 return 0;
1936
1937 case SB_INPUT_CLASS:
1938 dip->type = AUDIO_MIXER_CLASS;
1939 dip->mixer_class = SB_INPUT_CLASS;
1940 dip->next = dip->prev = AUDIO_MIXER_LAST;
1941 strcpy(dip->label.name, AudioCInputs);
1942 return 0;
1943
1944 case SB_EQUALIZATION_CLASS:
1945 dip->type = AUDIO_MIXER_CLASS;
1946 dip->mixer_class = SB_EQUALIZATION_CLASS;
1947 dip->next = dip->prev = AUDIO_MIXER_LAST;
1948 strcpy(dip->label.name, AudioCEqualization);
1949 return 0;
1950 }
1951
1952 return ENXIO;
1953 }
1954