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