sbdsp.c revision 1.12 1 1.12 brezak /* $NetBSD: sbdsp.c,v 1.12 1995/07/07 02:19:55 brezak Exp $ */
2 1.1 brezak
3 1.1 brezak /*
4 1.1 brezak * Copyright (c) 1991-1993 Regents of the University of California.
5 1.1 brezak * All rights reserved.
6 1.1 brezak *
7 1.1 brezak * Redistribution and use in source and binary forms, with or without
8 1.1 brezak * modification, are permitted provided that the following conditions
9 1.1 brezak * are met:
10 1.1 brezak * 1. Redistributions of source code must retain the above copyright
11 1.1 brezak * notice, this list of conditions and the following disclaimer.
12 1.1 brezak * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 brezak * notice, this list of conditions and the following disclaimer in the
14 1.1 brezak * documentation and/or other materials provided with the distribution.
15 1.1 brezak * 3. All advertising materials mentioning features or use of this software
16 1.1 brezak * must display the following acknowledgement:
17 1.1 brezak * This product includes software developed by the Computer Systems
18 1.1 brezak * Engineering Group at Lawrence Berkeley Laboratory.
19 1.1 brezak * 4. Neither the name of the University nor of the Laboratory may be used
20 1.1 brezak * to endorse or promote products derived from this software without
21 1.1 brezak * specific prior written permission.
22 1.1 brezak *
23 1.1 brezak * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 1.1 brezak * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 1.1 brezak * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 1.1 brezak * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 1.1 brezak * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 1.1 brezak * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 1.1 brezak * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 1.1 brezak * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 1.1 brezak * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 1.1 brezak * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 1.1 brezak * SUCH DAMAGE.
34 1.1 brezak *
35 1.1 brezak */
36 1.1 brezak /*
37 1.1 brezak * SoundBlaster Pro code provided by John Kohl, based on lots of
38 1.1 brezak * information he gleaned from Steve Haehnichen <steve (at) vigra.com>'s
39 1.1 brezak * SBlast driver for 386BSD and DOS driver code from Daniel Sachs
40 1.1 brezak * <sachs (at) meibm15.cen.uiuc.edu>.
41 1.1 brezak */
42 1.1 brezak
43 1.1 brezak #include <sys/param.h>
44 1.1 brezak #include <sys/systm.h>
45 1.1 brezak #include <sys/errno.h>
46 1.1 brezak #include <sys/ioctl.h>
47 1.1 brezak #include <sys/syslog.h>
48 1.1 brezak #include <sys/device.h>
49 1.1 brezak #include <sys/proc.h>
50 1.1 brezak #include <sys/buf.h>
51 1.1 brezak #include <vm/vm.h>
52 1.1 brezak
53 1.1 brezak #include <machine/cpu.h>
54 1.1 brezak #include <machine/pio.h>
55 1.1 brezak
56 1.1 brezak #include <sys/audioio.h>
57 1.1 brezak #include <dev/audio_if.h>
58 1.1 brezak
59 1.6 cgd #include <dev/isa/isavar.h>
60 1.6 cgd #include <dev/isa/isadmavar.h>
61 1.7 cgd #include <i386/isa/icu.h> /* XXX BROKEN; WHY? */
62 1.1 brezak
63 1.7 cgd #include <dev/isa/sbreg.h>
64 1.7 cgd #include <dev/isa/sbdspvar.h>
65 1.1 brezak
66 1.12 brezak #ifdef AUDIO_DEBUG
67 1.1 brezak extern void Dprintf __P((const char *, ...));
68 1.12 brezak #define DPRINTF(x) if (sbdspdebug) Dprintf x
69 1.1 brezak int sbdspdebug = 0;
70 1.1 brezak #else
71 1.1 brezak #define DPRINTF(x)
72 1.1 brezak #endif
73 1.1 brezak
74 1.1 brezak #ifndef SBDSP_NPOLL
75 1.1 brezak #define SBDSP_NPOLL 3000
76 1.1 brezak #endif
77 1.1 brezak
78 1.1 brezak struct {
79 1.1 brezak int wdsp;
80 1.1 brezak int rdsp;
81 1.1 brezak int wmidi;
82 1.1 brezak } sberr;
83 1.1 brezak
84 1.12 brezak #ifdef AUDIO_DEBUG
85 1.1 brezak void
86 1.1 brezak sb_printsc(struct sbdsp_softc *sc)
87 1.1 brezak {
88 1.1 brezak int i;
89 1.1 brezak
90 1.1 brezak printf("open %d dmachan %d iobase %x locked %d\n", sc->sc_open, sc->sc_drq,
91 1.1 brezak sc->sc_iobase, sc->sc_locked);
92 1.1 brezak printf("hispeed %d irate %d orate %d encoding %x\n",
93 1.1 brezak sc->sc_adacmode, sc->sc_irate, sc->sc_orate, sc->encoding);
94 1.1 brezak printf("outport %d inport %d spkron %d nintr %d\n",
95 1.1 brezak sc->out_port, sc->in_port, sc->spkr_state, sc->sc_interrupts);
96 1.1 brezak printf("tc %x chans %x scintr %x arg %x\n", sc->sc_adactc, sc->sc_chans,
97 1.1 brezak sc->sc_intr, sc->sc_arg);
98 1.1 brezak printf("gain: ");
99 1.1 brezak for (i = 0; i < SB_NDEVS; i++)
100 1.1 brezak printf("%d ", sc->gain[i]);
101 1.1 brezak printf("\n");
102 1.1 brezak }
103 1.1 brezak #endif
104 1.1 brezak
105 1.1 brezak /*
106 1.1 brezak * Probe / attach routines.
107 1.1 brezak */
108 1.1 brezak
109 1.1 brezak /*
110 1.1 brezak * Probe for the soundblaster hardware.
111 1.1 brezak */
112 1.1 brezak int
113 1.1 brezak sbdsp_probe(sc)
114 1.1 brezak struct sbdsp_softc *sc;
115 1.1 brezak {
116 1.1 brezak register u_short iobase = sc->sc_iobase;
117 1.1 brezak
118 1.1 brezak if (sbdsp_reset(sc) < 0) {
119 1.1 brezak DPRINTF(("sbdsp: couldn't reset card\n"));
120 1.1 brezak return 0;
121 1.1 brezak }
122 1.1 brezak sc->sc_model = sbversion(sc);
123 1.1 brezak
124 1.1 brezak return 1;
125 1.1 brezak }
126 1.1 brezak
127 1.1 brezak /*
128 1.1 brezak * Attach hardware to driver, attach hardware driver to audio
129 1.1 brezak * pseudo-device driver .
130 1.1 brezak */
131 1.1 brezak void
132 1.1 brezak sbdsp_attach(sc)
133 1.1 brezak struct sbdsp_softc *sc;
134 1.1 brezak {
135 1.1 brezak register u_short iobase = sc->sc_iobase;
136 1.1 brezak
137 1.1 brezak sc->sc_locked = 0;
138 1.1 brezak
139 1.1 brezak /* Set defaults */
140 1.1 brezak if (ISSBPROCLASS(sc))
141 1.1 brezak sc->sc_irate = sc->sc_orate = 45454;
142 1.1 brezak else
143 1.1 brezak sc->sc_irate = sc->sc_orate = 14925;
144 1.1 brezak sc->sc_chans = 1;
145 1.1 brezak sc->encoding = AUDIO_ENCODING_LINEAR;
146 1.1 brezak
147 1.5 mycroft (void) sbdsp_set_in_sr_real(sc, sc->sc_irate);
148 1.5 mycroft (void) sbdsp_set_out_sr_real(sc, sc->sc_orate);
149 1.1 brezak
150 1.5 mycroft (void) sbdsp_set_in_port(sc, SB_MIC_PORT);
151 1.5 mycroft (void) sbdsp_set_out_port(sc, SB_SPEAKER);
152 1.1 brezak
153 1.1 brezak if (ISSBPROCLASS(sc)) {
154 1.1 brezak int i;
155 1.1 brezak
156 1.1 brezak /* set mixer to default levels, by sending a mixer
157 1.1 brezak reset command. */
158 1.1 brezak sbdsp_mix_write(sc, SBP_MIX_RESET, SBP_MIX_RESET);
159 1.1 brezak /* then some adjustments :) */
160 1.1 brezak sbdsp_mix_write(sc, SBP_CD_VOL,
161 1.1 brezak sbdsp_stereo_vol(SBP_MAXVOL, SBP_MAXVOL));
162 1.1 brezak sbdsp_mix_write(sc, SBP_DAC_VOL,
163 1.1 brezak sbdsp_stereo_vol(SBP_MAXVOL, SBP_MAXVOL));
164 1.1 brezak sbdsp_mix_write(sc, SBP_MASTER_VOL,
165 1.1 brezak sbdsp_stereo_vol(SBP_MAXVOL, SBP_MAXVOL));
166 1.1 brezak sbdsp_mix_write(sc, SBP_LINE_VOL,
167 1.1 brezak sbdsp_stereo_vol(SBP_MAXVOL, SBP_MAXVOL));
168 1.1 brezak for (i = 0; i < SB_NDEVS; i++)
169 1.1 brezak sc->gain[i] = sbdsp_stereo_vol(SBP_MAXVOL, SBP_MAXVOL);
170 1.1 brezak }
171 1.9 brezak printf(": dsp v%d.%02d\n",
172 1.1 brezak SBVER_MAJOR(sc->sc_model), SBVER_MINOR(sc->sc_model));
173 1.1 brezak }
174 1.1 brezak
175 1.1 brezak /*
176 1.1 brezak * Various routines to interface to higher level audio driver
177 1.1 brezak */
178 1.1 brezak
179 1.1 brezak void
180 1.1 brezak sbdsp_mix_write(sc, mixerport, val)
181 1.1 brezak struct sbdsp_softc *sc;
182 1.1 brezak int mixerport;
183 1.1 brezak int val;
184 1.1 brezak {
185 1.1 brezak int iobase = sc->sc_iobase;
186 1.1 brezak outb(iobase + SBP_MIXER_ADDR, mixerport);
187 1.1 brezak delay(10);
188 1.1 brezak outb(iobase + SBP_MIXER_DATA, val);
189 1.1 brezak delay(30);
190 1.1 brezak }
191 1.1 brezak
192 1.1 brezak int
193 1.1 brezak sbdsp_mix_read(sc, mixerport)
194 1.1 brezak struct sbdsp_softc *sc;
195 1.1 brezak int mixerport;
196 1.1 brezak {
197 1.1 brezak int iobase = sc->sc_iobase;
198 1.1 brezak outb(iobase + SBP_MIXER_ADDR, mixerport);
199 1.1 brezak delay(10);
200 1.1 brezak return inb(iobase + SBP_MIXER_DATA);
201 1.1 brezak }
202 1.1 brezak
203 1.1 brezak int
204 1.1 brezak sbdsp_set_in_sr(addr, sr)
205 1.5 mycroft void *addr;
206 1.1 brezak u_long sr;
207 1.1 brezak {
208 1.5 mycroft register struct sbdsp_softc *sc = addr;
209 1.1 brezak
210 1.1 brezak sc->sc_irate = sr;
211 1.1 brezak
212 1.1 brezak return 0;
213 1.1 brezak }
214 1.1 brezak
215 1.1 brezak int
216 1.1 brezak sbdsp_set_in_sr_real(addr, sr)
217 1.5 mycroft void *addr;
218 1.1 brezak u_long sr;
219 1.1 brezak {
220 1.5 mycroft register struct sbdsp_softc *sc = addr;
221 1.1 brezak int rval;
222 1.1 brezak
223 1.1 brezak if (rval = sbdsp_set_sr(sc, &sr, SB_INPUT_RATE))
224 1.1 brezak return rval;
225 1.1 brezak sc->sc_irate = sr;
226 1.1 brezak sc->sc_dmain_inprogress = 0; /* do it again on next DMA out */
227 1.1 brezak sc->sc_dmaout_inprogress = 0;
228 1.1 brezak return(0);
229 1.1 brezak }
230 1.1 brezak
231 1.1 brezak u_long
232 1.1 brezak sbdsp_get_in_sr(addr)
233 1.5 mycroft void *addr;
234 1.1 brezak {
235 1.5 mycroft register struct sbdsp_softc *sc = addr;
236 1.1 brezak
237 1.1 brezak return(sc->sc_irate);
238 1.1 brezak }
239 1.1 brezak
240 1.1 brezak int
241 1.1 brezak sbdsp_set_out_sr(addr, sr)
242 1.5 mycroft void *addr;
243 1.1 brezak u_long sr;
244 1.1 brezak {
245 1.5 mycroft register struct sbdsp_softc *sc = addr;
246 1.1 brezak
247 1.1 brezak sc->sc_orate = sr;
248 1.1 brezak return(0);
249 1.1 brezak }
250 1.1 brezak
251 1.1 brezak int
252 1.1 brezak sbdsp_set_out_sr_real(addr, sr)
253 1.5 mycroft void *addr;
254 1.1 brezak u_long sr;
255 1.1 brezak {
256 1.5 mycroft register struct sbdsp_softc *sc = addr;
257 1.1 brezak int rval;
258 1.1 brezak
259 1.1 brezak if (rval = sbdsp_set_sr(sc, &sr, SB_OUTPUT_RATE))
260 1.1 brezak return rval;
261 1.1 brezak sc->sc_orate = sr;
262 1.1 brezak sc->sc_dmain_inprogress = 0; /* do it again on next DMA out */
263 1.1 brezak return(0);
264 1.1 brezak }
265 1.1 brezak
266 1.1 brezak u_long
267 1.1 brezak sbdsp_get_out_sr(addr)
268 1.5 mycroft void *addr;
269 1.1 brezak {
270 1.5 mycroft register struct sbdsp_softc *sc = addr;
271 1.1 brezak
272 1.1 brezak return(sc->sc_orate);
273 1.1 brezak }
274 1.1 brezak
275 1.1 brezak int
276 1.1 brezak sbdsp_query_encoding(addr, fp)
277 1.5 mycroft void *addr;
278 1.1 brezak struct audio_encoding *fp;
279 1.1 brezak {
280 1.5 mycroft register struct sbdsp_softc *sc = addr;
281 1.1 brezak
282 1.1 brezak switch (fp->index) {
283 1.1 brezak case 0:
284 1.1 brezak strcpy(fp->name, "MU-Law");
285 1.1 brezak fp->format_id = AUDIO_ENCODING_ULAW;
286 1.1 brezak break;
287 1.1 brezak case 2:
288 1.1 brezak strcpy(fp->name, "pcm16");
289 1.1 brezak fp->format_id = AUDIO_ENCODING_PCM16;
290 1.1 brezak break;
291 1.1 brezak default:
292 1.1 brezak return(EINVAL);
293 1.1 brezak /*NOTREACHED*/
294 1.1 brezak }
295 1.1 brezak return (0);
296 1.1 brezak }
297 1.1 brezak
298 1.1 brezak int
299 1.1 brezak sbdsp_set_encoding(addr, enc)
300 1.5 mycroft void *addr;
301 1.1 brezak u_int enc;
302 1.1 brezak {
303 1.5 mycroft register struct sbdsp_softc *sc = addr;
304 1.1 brezak
305 1.1 brezak switch(enc){
306 1.1 brezak case AUDIO_ENCODING_ULAW:
307 1.1 brezak sc->encoding = AUDIO_ENCODING_ULAW;
308 1.1 brezak break;
309 1.1 brezak case AUDIO_ENCODING_LINEAR:
310 1.1 brezak sc->encoding = AUDIO_ENCODING_LINEAR;
311 1.1 brezak break;
312 1.1 brezak default:
313 1.1 brezak return (EINVAL);
314 1.1 brezak }
315 1.1 brezak return (0);
316 1.1 brezak }
317 1.1 brezak
318 1.1 brezak int
319 1.1 brezak sbdsp_get_encoding(addr)
320 1.5 mycroft void *addr;
321 1.1 brezak {
322 1.5 mycroft register struct sbdsp_softc *sc = addr;
323 1.1 brezak
324 1.1 brezak return(sc->encoding);
325 1.1 brezak }
326 1.1 brezak
327 1.1 brezak int
328 1.1 brezak sbdsp_set_precision(addr, prec)
329 1.5 mycroft void *addr;
330 1.1 brezak u_int prec;
331 1.1 brezak {
332 1.1 brezak
333 1.1 brezak if (prec != 8)
334 1.1 brezak return(EINVAL);
335 1.1 brezak return(0);
336 1.1 brezak }
337 1.1 brezak
338 1.1 brezak int
339 1.1 brezak sbdsp_get_precision(addr)
340 1.5 mycroft void *addr;
341 1.1 brezak {
342 1.1 brezak return(8);
343 1.1 brezak }
344 1.1 brezak
345 1.1 brezak int
346 1.1 brezak sbdsp_set_channels(addr, chans)
347 1.5 mycroft void *addr;
348 1.1 brezak int chans;
349 1.1 brezak {
350 1.5 mycroft register struct sbdsp_softc *sc = addr;
351 1.1 brezak int rval;
352 1.1 brezak
353 1.1 brezak if (ISSBPROCLASS(sc)) {
354 1.1 brezak if (chans != 1 && chans != 2)
355 1.1 brezak return(EINVAL);
356 1.1 brezak
357 1.1 brezak sc->sc_chans = chans;
358 1.1 brezak if (rval = sbdsp_set_in_sr_real(addr, sc->sc_irate))
359 1.1 brezak return rval;
360 1.1 brezak sbdsp_mix_write(sc, SBP_STEREO,
361 1.1 brezak (sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK) |
362 1.1 brezak (chans == 2 ? SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO));
363 1.1 brezak /* recording channels needs to be done right when we start
364 1.1 brezak DMA recording. Just record number of channels for now
365 1.1 brezak and set stereo when ready. */
366 1.1 brezak }
367 1.1 brezak else {
368 1.1 brezak if (chans != 1)
369 1.1 brezak return(EINVAL);
370 1.1 brezak sc->sc_chans = 1;
371 1.1 brezak }
372 1.1 brezak
373 1.1 brezak return(0);
374 1.1 brezak }
375 1.1 brezak
376 1.1 brezak int
377 1.1 brezak sbdsp_get_channels(addr)
378 1.5 mycroft void *addr;
379 1.1 brezak {
380 1.5 mycroft register struct sbdsp_softc *sc = addr;
381 1.1 brezak
382 1.1 brezak #if 0
383 1.1 brezak /* recording stereo may frob the mixer output */
384 1.1 brezak if (ISSBPROCLASS(sc)) {
385 1.1 brezak if ((sbdsp_mix_read(sc, SBP_STEREO) & SBP_PLAYMODE_MASK) == SBP_PLAYMODE_STEREO) {
386 1.1 brezak sc->sc_chans = 2;
387 1.1 brezak }
388 1.1 brezak else {
389 1.1 brezak sc->sc_chans = 1;
390 1.1 brezak }
391 1.1 brezak }
392 1.1 brezak else {
393 1.1 brezak sc->sc_chans = 1;
394 1.1 brezak }
395 1.1 brezak #endif
396 1.1 brezak
397 1.1 brezak return(sc->sc_chans);
398 1.1 brezak }
399 1.1 brezak
400 1.1 brezak int
401 1.1 brezak sbdsp_set_out_port(addr, port)
402 1.5 mycroft void *addr;
403 1.1 brezak int port;
404 1.1 brezak {
405 1.5 mycroft register struct sbdsp_softc *sc = addr;
406 1.1 brezak
407 1.1 brezak sc->out_port = port; /* Just record it */
408 1.1 brezak
409 1.1 brezak return(0);
410 1.1 brezak }
411 1.1 brezak
412 1.1 brezak int
413 1.1 brezak sbdsp_get_out_port(addr)
414 1.5 mycroft void *addr;
415 1.1 brezak {
416 1.5 mycroft register struct sbdsp_softc *sc = addr;
417 1.1 brezak
418 1.1 brezak return(sc->out_port);
419 1.1 brezak }
420 1.1 brezak
421 1.1 brezak
422 1.1 brezak int
423 1.1 brezak sbdsp_set_in_port(addr, port)
424 1.5 mycroft void *addr;
425 1.1 brezak int port;
426 1.1 brezak {
427 1.5 mycroft register struct sbdsp_softc *sc = addr;
428 1.1 brezak int mixport, sbport;
429 1.1 brezak
430 1.1 brezak if (ISSBPROCLASS(sc)) {
431 1.1 brezak switch (port) {
432 1.8 mycroft case SB_MIC_PORT:
433 1.8 mycroft sbport = SBP_FROM_MIC;
434 1.8 mycroft mixport = SBP_MIC_VOL;
435 1.8 mycroft break;
436 1.1 brezak case SB_LINE_IN_PORT:
437 1.1 brezak sbport = SBP_FROM_LINE;
438 1.1 brezak mixport = SBP_LINE_VOL;
439 1.1 brezak break;
440 1.1 brezak case SB_CD_PORT:
441 1.1 brezak sbport = SBP_FROM_CD;
442 1.1 brezak mixport = SBP_CD_VOL;
443 1.1 brezak break;
444 1.1 brezak case SB_DAC_PORT:
445 1.1 brezak case SB_FM_PORT:
446 1.1 brezak default:
447 1.1 brezak return(EINVAL);
448 1.1 brezak /*NOTREACHED*/
449 1.1 brezak }
450 1.1 brezak }
451 1.1 brezak else {
452 1.8 mycroft switch (port) {
453 1.8 mycroft case SB_MIC_PORT:
454 1.8 mycroft sbport = SBP_FROM_MIC;
455 1.8 mycroft mixport = SBP_MIC_VOL;
456 1.8 mycroft break;
457 1.8 mycroft default:
458 1.8 mycroft return(EINVAL);
459 1.8 mycroft /*NOTREACHED*/
460 1.8 mycroft }
461 1.1 brezak }
462 1.1 brezak
463 1.1 brezak sc->in_port = port; /* Just record it */
464 1.1 brezak
465 1.1 brezak if (ISSBPROCLASS(sc)) {
466 1.1 brezak /* record from that port */
467 1.1 brezak sbdsp_mix_write(sc, SBP_RECORD_SOURCE,
468 1.1 brezak SBP_RECORD_FROM(sbport, SBP_FILTER_OFF,
469 1.1 brezak SBP_FILTER_HIGH));
470 1.1 brezak /* fetch gain from that port */
471 1.1 brezak sc->gain[port] = sbdsp_mix_read(sc, mixport);
472 1.1 brezak }
473 1.1 brezak
474 1.1 brezak return(0);
475 1.1 brezak }
476 1.1 brezak
477 1.1 brezak int
478 1.1 brezak sbdsp_get_in_port(addr)
479 1.5 mycroft void *addr;
480 1.1 brezak {
481 1.5 mycroft register struct sbdsp_softc *sc = addr;
482 1.1 brezak
483 1.1 brezak return(sc->in_port);
484 1.1 brezak }
485 1.1 brezak
486 1.1 brezak
487 1.1 brezak int
488 1.1 brezak sbdsp_speaker_ctl(addr, newstate)
489 1.5 mycroft void *addr;
490 1.1 brezak int newstate;
491 1.1 brezak {
492 1.5 mycroft register struct sbdsp_softc *sc = addr;
493 1.1 brezak
494 1.1 brezak if ((newstate == SPKR_ON) &&
495 1.1 brezak (sc->spkr_state == SPKR_OFF)) {
496 1.1 brezak sbdsp_spkron(sc);
497 1.1 brezak sc->spkr_state = SPKR_ON;
498 1.1 brezak }
499 1.1 brezak if ((newstate == SPKR_OFF) &&
500 1.1 brezak (sc->spkr_state == SPKR_ON)) {
501 1.1 brezak sbdsp_spkroff(sc);
502 1.1 brezak sc->spkr_state = SPKR_OFF;
503 1.1 brezak }
504 1.1 brezak return(0);
505 1.1 brezak }
506 1.1 brezak
507 1.1 brezak int
508 1.1 brezak sbdsp_round_blocksize(addr, blk)
509 1.5 mycroft void *addr;
510 1.1 brezak int blk;
511 1.1 brezak {
512 1.5 mycroft register struct sbdsp_softc *sc = addr;
513 1.1 brezak
514 1.1 brezak sc->sc_last_hsr_size = sc->sc_last_hsw_size = 0;
515 1.1 brezak
516 1.1 brezak /* Higher speeds need bigger blocks to avoid popping and silence gaps. */
517 1.1 brezak if ((sc->sc_orate > 8000 || sc->sc_irate > 8000) &&
518 1.1 brezak (blk > NBPG/2 || blk < NBPG/4))
519 1.1 brezak blk = NBPG/2;
520 1.1 brezak /* don't try to DMA too much at once, though. */
521 1.1 brezak if (blk > NBPG) blk = NBPG;
522 1.1 brezak if (sc->sc_chans == 2)
523 1.1 brezak return (blk & ~1); /* must be even to preserve stereo separation */
524 1.1 brezak else
525 1.1 brezak return(blk); /* Anything goes :-) */
526 1.1 brezak }
527 1.1 brezak
528 1.1 brezak int
529 1.1 brezak sbdsp_commit_settings(addr)
530 1.5 mycroft void *addr;
531 1.1 brezak {
532 1.1 brezak /* due to potentially unfortunate ordering in the above layers,
533 1.1 brezak re-do a few sets which may be important--input gains
534 1.1 brezak (adjust the proper channels), number of input channels (hit the
535 1.1 brezak record rate and set mode) */
536 1.1 brezak
537 1.5 mycroft register struct sbdsp_softc *sc = addr;
538 1.1 brezak
539 1.3 brezak sbdsp_set_out_sr_real(addr, sc->sc_orate);
540 1.3 brezak sbdsp_set_in_sr_real(addr, sc->sc_irate);
541 1.3 brezak
542 1.1 brezak sc->sc_last_hsw_size = sc->sc_last_hsr_size = 0;
543 1.1 brezak return(0);
544 1.1 brezak }
545 1.1 brezak
546 1.1 brezak
547 1.1 brezak int
548 1.1 brezak sbdsp_open(sc, dev, flags)
549 1.1 brezak register struct sbdsp_softc *sc;
550 1.1 brezak dev_t dev;
551 1.1 brezak int flags;
552 1.1 brezak {
553 1.1 brezak DPRINTF(("sbdsp_open: sc=0x%x\n", sc));
554 1.1 brezak
555 1.1 brezak if (sc->sc_open != 0 || sbdsp_reset(sc) != 0)
556 1.1 brezak return ENXIO;
557 1.1 brezak
558 1.1 brezak sc->sc_open = 1;
559 1.1 brezak sc->sc_mintr = 0;
560 1.1 brezak sc->sc_intr = 0;
561 1.1 brezak sc->sc_arg = 0;
562 1.1 brezak sc->sc_locked = 0;
563 1.1 brezak if (ISSBPROCLASS(sc) &&
564 1.1 brezak sbdsp_wdsp(sc->sc_iobase, SB_DSP_RECORD_MONO) < 0) {
565 1.1 brezak DPRINTF(("sbdsp_open: can't set mono mode\n"));
566 1.1 brezak /* we'll readjust when it's time for DMA. */
567 1.1 brezak }
568 1.1 brezak sc->sc_dmain_inprogress = 0;
569 1.1 brezak sc->sc_dmaout_inprogress = 0;
570 1.1 brezak
571 1.1 brezak /*
572 1.1 brezak * Leave most things as they were; users must change things if
573 1.1 brezak * the previous process didn't leave it they way they wanted.
574 1.1 brezak * Looked at another way, it's easy to set up a configuration
575 1.1 brezak * in one program and leave it for another to inherit.
576 1.1 brezak */
577 1.1 brezak DPRINTF(("sbdsp_open: opened\n"));
578 1.1 brezak
579 1.1 brezak return 0;
580 1.1 brezak }
581 1.1 brezak
582 1.1 brezak void
583 1.1 brezak sbdsp_close(addr)
584 1.5 mycroft void *addr;
585 1.1 brezak {
586 1.5 mycroft struct sbdsp_softc *sc = addr;
587 1.1 brezak
588 1.1 brezak DPRINTF(("sbdsp_close: sc=0x%x\n", sc));
589 1.1 brezak
590 1.1 brezak sc->sc_open = 0;
591 1.1 brezak sbdsp_spkroff(sc);
592 1.1 brezak sc->spkr_state = SPKR_OFF;
593 1.1 brezak sc->sc_intr = 0;
594 1.1 brezak sc->sc_mintr = 0;
595 1.1 brezak /* XXX this will turn off any dma */
596 1.1 brezak sbdsp_reset(sc);
597 1.1 brezak
598 1.1 brezak DPRINTF(("sbdsp_close: closed\n"));
599 1.1 brezak }
600 1.1 brezak
601 1.1 brezak /*
602 1.1 brezak * Lower-level routines
603 1.1 brezak */
604 1.1 brezak
605 1.1 brezak /*
606 1.1 brezak * Reset the card.
607 1.1 brezak * Return non-zero if the card isn't detected.
608 1.1 brezak */
609 1.1 brezak int
610 1.1 brezak sbdsp_reset(sc)
611 1.1 brezak register struct sbdsp_softc *sc;
612 1.1 brezak {
613 1.1 brezak register u_short iobase = sc->sc_iobase;
614 1.1 brezak
615 1.1 brezak /*
616 1.1 brezak * erase any memory of last transfer size.
617 1.1 brezak */
618 1.1 brezak sc->sc_last_hsr_size = sc->sc_last_hsw_size = 0;
619 1.1 brezak /*
620 1.1 brezak * See SBK, section 11.3.
621 1.1 brezak * We pulse a reset signal into the card.
622 1.1 brezak * Gee, what a brilliant hardware design.
623 1.1 brezak */
624 1.1 brezak outb(iobase + SBP_DSP_RESET, 1);
625 1.1 brezak delay(3);
626 1.1 brezak outb(iobase + SBP_DSP_RESET, 0);
627 1.1 brezak if (sbdsp_rdsp(iobase) != SB_MAGIC)
628 1.1 brezak return -1;
629 1.1 brezak return 0;
630 1.1 brezak }
631 1.1 brezak
632 1.1 brezak /*
633 1.1 brezak * Write a byte to the dsp.
634 1.1 brezak * XXX We are at the mercy of the card as we use a
635 1.1 brezak * polling loop and wait until it can take the byte.
636 1.1 brezak */
637 1.1 brezak int
638 1.1 brezak sbdsp_wdsp(u_short iobase, int v)
639 1.1 brezak {
640 1.1 brezak register int i;
641 1.1 brezak
642 1.1 brezak for (i = SBDSP_NPOLL; --i >= 0; ) {
643 1.1 brezak if ((inb(iobase + SBP_DSP_WSTAT) & SB_DSP_BUSY) != 0) {
644 1.1 brezak delay(10); continue;
645 1.1 brezak }
646 1.1 brezak outb(iobase + SBP_DSP_WRITE, v);
647 1.1 brezak return 0;
648 1.1 brezak }
649 1.1 brezak ++sberr.wdsp;
650 1.1 brezak return -1;
651 1.1 brezak }
652 1.1 brezak
653 1.1 brezak /*
654 1.1 brezak * Read a byte from the DSP, using polling.
655 1.1 brezak */
656 1.1 brezak int
657 1.1 brezak sbdsp_rdsp(u_short iobase)
658 1.1 brezak {
659 1.1 brezak register int i;
660 1.1 brezak
661 1.1 brezak for (i = SBDSP_NPOLL; --i >= 0; ) {
662 1.1 brezak if ((inb(iobase + SBP_DSP_RSTAT) & SB_DSP_READY) == 0)
663 1.1 brezak continue;
664 1.1 brezak return inb(iobase + SBP_DSP_READ);
665 1.1 brezak }
666 1.1 brezak ++sberr.rdsp;
667 1.1 brezak return -1;
668 1.1 brezak }
669 1.1 brezak
670 1.1 brezak /*
671 1.1 brezak * Doing certain things (like toggling the speaker) make
672 1.1 brezak * the SB hardware go away for a while, so pause a little.
673 1.1 brezak */
674 1.1 brezak void
675 1.1 brezak sbdsp_to(arg)
676 1.1 brezak void *arg;
677 1.1 brezak {
678 1.1 brezak wakeup(arg);
679 1.1 brezak }
680 1.1 brezak
681 1.1 brezak void
682 1.1 brezak sbdsp_pause(sc)
683 1.1 brezak struct sbdsp_softc *sc;
684 1.1 brezak {
685 1.1 brezak extern int hz;
686 1.1 brezak
687 1.1 brezak timeout(sbdsp_to, sbdsp_to, hz/8);
688 1.5 mycroft (void)tsleep(sbdsp_to, PWAIT, "sbpause", 0);
689 1.1 brezak }
690 1.1 brezak
691 1.1 brezak /*
692 1.1 brezak * Turn on the speaker. The SBK documention says this operation
693 1.1 brezak * can take up to 1/10 of a second. Higher level layers should
694 1.1 brezak * probably let the task sleep for this amount of time after
695 1.1 brezak * calling here. Otherwise, things might not work (because
696 1.1 brezak * sbdsp_wdsp() and sbdsp_rdsp() will probably timeout.)
697 1.1 brezak *
698 1.1 brezak * These engineers had their heads up their ass when
699 1.1 brezak * they designed this card.
700 1.1 brezak */
701 1.1 brezak void
702 1.1 brezak sbdsp_spkron(sc)
703 1.1 brezak struct sbdsp_softc *sc;
704 1.1 brezak {
705 1.1 brezak (void)sbdsp_wdsp(sc->sc_iobase, SB_DSP_SPKR_ON);
706 1.1 brezak sbdsp_pause(sc);
707 1.1 brezak }
708 1.1 brezak
709 1.1 brezak /*
710 1.1 brezak * Turn off the speaker; see comment above.
711 1.1 brezak */
712 1.1 brezak void
713 1.1 brezak sbdsp_spkroff(sc)
714 1.1 brezak struct sbdsp_softc *sc;
715 1.1 brezak {
716 1.1 brezak (void)sbdsp_wdsp(sc->sc_iobase, SB_DSP_SPKR_OFF);
717 1.1 brezak sbdsp_pause(sc);
718 1.1 brezak }
719 1.1 brezak
720 1.1 brezak /*
721 1.1 brezak * Read the version number out of the card. Return major code
722 1.1 brezak * in high byte, and minor code in low byte.
723 1.1 brezak */
724 1.1 brezak short
725 1.1 brezak sbversion(sc)
726 1.1 brezak struct sbdsp_softc *sc;
727 1.1 brezak {
728 1.1 brezak register u_short iobase = sc->sc_iobase;
729 1.1 brezak short v;
730 1.1 brezak
731 1.1 brezak if (sbdsp_wdsp(iobase, SB_DSP_VERSION) < 0)
732 1.1 brezak return 0;
733 1.1 brezak v = sbdsp_rdsp(iobase) << 8;
734 1.1 brezak v |= sbdsp_rdsp(iobase);
735 1.1 brezak return ((v >= 0) ? v : 0);
736 1.1 brezak }
737 1.1 brezak
738 1.1 brezak /*
739 1.1 brezak * Halt a DMA in progress. A low-speed transfer can be
740 1.1 brezak * resumed with sbdsp_contdma().
741 1.1 brezak */
742 1.1 brezak int
743 1.1 brezak sbdsp_haltdma(addr)
744 1.5 mycroft void *addr;
745 1.1 brezak {
746 1.5 mycroft register struct sbdsp_softc *sc = addr;
747 1.1 brezak
748 1.1 brezak DPRINTF(("sbdsp_haltdma: sc=0x%x\n", sc));
749 1.1 brezak
750 1.1 brezak if (sc->sc_locked)
751 1.1 brezak sbdsp_reset(sc);
752 1.1 brezak else
753 1.1 brezak (void)sbdsp_wdsp(sc->sc_iobase, SB_DSP_HALT);
754 1.1 brezak
755 1.1 brezak isa_dmaabort(sc->sc_drq);
756 1.1 brezak sc->dmaaddr = 0;
757 1.1 brezak sc->dmacnt = 0;
758 1.1 brezak sc->sc_locked = 0;
759 1.1 brezak sc->dmaflags = 0;
760 1.1 brezak sc->sc_dmain_inprogress = sc->sc_dmaout_inprogress = 0;
761 1.1 brezak return(0);
762 1.1 brezak }
763 1.1 brezak
764 1.1 brezak int
765 1.1 brezak sbdsp_contdma(addr)
766 1.5 mycroft void *addr;
767 1.1 brezak {
768 1.5 mycroft register struct sbdsp_softc *sc = addr;
769 1.1 brezak
770 1.1 brezak DPRINTF(("sbdsp_contdma: sc=0x%x\n", sc));
771 1.1 brezak
772 1.1 brezak /* XXX how do we reinitialize the DMA controller state? do we care? */
773 1.1 brezak (void)sbdsp_wdsp(sc->sc_iobase, SB_DSP_CONT);
774 1.1 brezak return(0);
775 1.1 brezak }
776 1.1 brezak
777 1.1 brezak /*
778 1.1 brezak * Time constant routines follow. See SBK, section 12.
779 1.1 brezak * Although they don't come out and say it (in the docs),
780 1.1 brezak * the card clearly uses a 1MHz countdown timer, as the
781 1.1 brezak * low-speed formula (p. 12-4) is:
782 1.1 brezak * tc = 256 - 10^6 / sr
783 1.1 brezak * In high-speed mode, the constant is the upper byte of a 16-bit counter,
784 1.1 brezak * and a 256MHz clock is used:
785 1.1 brezak * tc = 65536 - 256 * 10^ 6 / sr
786 1.1 brezak * Since we can only use the upper byte of the HS TC, the two formulae
787 1.1 brezak * are equivalent. (Why didn't they say so?) E.g.,
788 1.1 brezak * (65536 - 256 * 10 ^ 6 / x) >> 8 = 256 - 10^6 / x
789 1.1 brezak *
790 1.1 brezak * The crossover point (from low- to high-speed modes) is different
791 1.1 brezak * for the SBPRO and SB20. The table on p. 12-5 gives the following data:
792 1.1 brezak *
793 1.1 brezak * SBPRO SB20
794 1.1 brezak * ----- --------
795 1.1 brezak * input ls min 4 KHz 4 KHz
796 1.1 brezak * input ls max 23 KHz 13 KHz
797 1.1 brezak * input hs max 44.1 KHz 15 KHz
798 1.1 brezak * output ls min 4 KHz 4 KHz
799 1.1 brezak * output ls max 23 KHz 23 KHz
800 1.1 brezak * output hs max 44.1 KHz 44.1 KHz
801 1.1 brezak */
802 1.1 brezak #define SB_LS_MIN 0x06 /* 4000 Hz */
803 1.1 brezak #define SBPRO_ADC_LS_MAX 0xd4 /* 22727 Hz */
804 1.1 brezak #define SBPRO_ADC_HS_MAX 0xea /* 45454 Hz */
805 1.1 brezak #define SBCLA_ADC_LS_MAX 0xb3 /* 12987 Hz */
806 1.1 brezak #define SBCLA_ADC_HS_MAX 0xbd /* 14925 Hz */
807 1.1 brezak #define SB_DAC_LS_MAX 0xd4 /* 22727 Hz */
808 1.1 brezak #define SB_DAC_HS_MAX 0xea /* 45454 Hz */
809 1.1 brezak
810 1.1 brezak /*
811 1.1 brezak * Convert a linear sampling rate into the DAC time constant.
812 1.1 brezak * Set *mode to indicate the high/low-speed DMA operation.
813 1.1 brezak * Because of limitations of the card, not all rates are possible.
814 1.1 brezak * We return the time constant of the closest possible rate.
815 1.1 brezak * The sampling rate limits are different for the DAC and ADC,
816 1.1 brezak * so isdac indicates output, and !isdac indicates input.
817 1.1 brezak */
818 1.1 brezak int
819 1.1 brezak sbdsp_srtotc(sc, sr, mode, isdac)
820 1.1 brezak register struct sbdsp_softc *sc;
821 1.1 brezak int sr;
822 1.1 brezak int *mode;
823 1.1 brezak int isdac;
824 1.1 brezak {
825 1.1 brezak int adc_ls_max, adc_hs_max;
826 1.1 brezak register int tc;
827 1.1 brezak
828 1.1 brezak if (sr == 0) {
829 1.1 brezak *mode = SB_ADAC_LS;
830 1.1 brezak return SB_LS_MIN;
831 1.1 brezak }
832 1.1 brezak tc = 256 - 1000000 / sr;
833 1.1 brezak
834 1.1 brezak /* XXX use better rounding--compare distance to nearest tc on both
835 1.1 brezak sides of requested speed */
836 1.1 brezak if (ISSBPROCLASS(sc)) {
837 1.1 brezak adc_ls_max = SBPRO_ADC_LS_MAX;
838 1.1 brezak adc_hs_max = SBPRO_ADC_HS_MAX;
839 1.1 brezak }
840 1.1 brezak else {
841 1.1 brezak adc_ls_max = SBCLA_ADC_LS_MAX;
842 1.1 brezak adc_hs_max = SBCLA_ADC_HS_MAX;
843 1.1 brezak }
844 1.1 brezak
845 1.1 brezak if (tc < SB_LS_MIN) {
846 1.1 brezak tc = SB_LS_MIN;
847 1.1 brezak *mode = SB_ADAC_LS;
848 1.1 brezak } else if (isdac) {
849 1.1 brezak if (tc <= SB_DAC_LS_MAX)
850 1.1 brezak *mode = SB_ADAC_LS;
851 1.1 brezak else {
852 1.1 brezak *mode = SB_ADAC_HS;
853 1.1 brezak if (tc > SB_DAC_HS_MAX)
854 1.1 brezak tc = SB_DAC_HS_MAX;
855 1.1 brezak }
856 1.1 brezak } else {
857 1.1 brezak if (tc <= adc_ls_max)
858 1.1 brezak *mode = SB_ADAC_LS;
859 1.1 brezak else {
860 1.1 brezak *mode = SB_ADAC_HS;
861 1.1 brezak if (tc > adc_hs_max)
862 1.1 brezak tc = adc_hs_max;
863 1.1 brezak }
864 1.1 brezak }
865 1.1 brezak return tc;
866 1.1 brezak }
867 1.1 brezak
868 1.1 brezak /*
869 1.1 brezak * Convert a DAC time constant to a sampling rate.
870 1.1 brezak * See SBK, section 12.
871 1.1 brezak */
872 1.1 brezak int
873 1.1 brezak sbdsp_tctosr(sc, tc)
874 1.1 brezak register struct sbdsp_softc *sc;
875 1.1 brezak int tc;
876 1.1 brezak {
877 1.1 brezak int adc;
878 1.1 brezak
879 1.1 brezak if (ISSBPROCLASS(sc))
880 1.1 brezak adc = SBPRO_ADC_HS_MAX;
881 1.1 brezak else
882 1.1 brezak adc = SBCLA_ADC_HS_MAX;
883 1.1 brezak
884 1.1 brezak if (tc > adc)
885 1.1 brezak tc = adc;
886 1.1 brezak
887 1.1 brezak return (1000000 / (256 - tc));
888 1.1 brezak }
889 1.1 brezak
890 1.1 brezak int
891 1.1 brezak sbdsp_set_sr(sc, srp, isdac)
892 1.1 brezak register struct sbdsp_softc *sc;
893 1.1 brezak u_long *srp;
894 1.1 brezak int isdac;
895 1.1 brezak {
896 1.1 brezak register int tc;
897 1.1 brezak int mode;
898 1.1 brezak int sr = *srp;
899 1.1 brezak register u_short iobase;
900 1.1 brezak
901 1.1 brezak /*
902 1.1 brezak * A SBPro in stereo mode uses time constants at double the
903 1.1 brezak * actual rate.
904 1.1 brezak */
905 1.1 brezak if (ISSBPRO(sc) && sc->sc_chans == 2) {
906 1.1 brezak if (sr > 22727)
907 1.1 brezak sr = 22727; /* Can't bounce it...order of
908 1.1 brezak operations may yield bogus
909 1.1 brezak sr here. */
910 1.1 brezak sr *= 2;
911 1.1 brezak }
912 1.1 brezak else if (!ISSBPROCLASS(sc) && sc->sc_chans != 1)
913 1.1 brezak return EINVAL;
914 1.1 brezak
915 1.1 brezak tc = sbdsp_srtotc(sc, sr, &mode, isdac);
916 1.1 brezak DPRINTF(("sbdsp_set_sr: sc=0x%x sr=%d mode=0x%x\n", sc, sr, mode));
917 1.1 brezak
918 1.1 brezak iobase = sc->sc_iobase;
919 1.1 brezak if (sbdsp_wdsp(iobase, SB_DSP_TIMECONST) < 0 ||
920 1.1 brezak sbdsp_wdsp(iobase, tc) < 0)
921 1.1 brezak return EIO;
922 1.1 brezak
923 1.1 brezak sr = sbdsp_tctosr(sc, tc);
924 1.1 brezak if (ISSBPRO(sc) && sc->sc_chans == 2)
925 1.1 brezak *srp = sr / 2;
926 1.1 brezak else
927 1.1 brezak *srp = sr;
928 1.1 brezak
929 1.1 brezak sc->sc_adacmode = mode;
930 1.1 brezak sc->sc_adactc = tc;
931 1.1 brezak return 0;
932 1.1 brezak }
933 1.1 brezak
934 1.1 brezak int
935 1.1 brezak sbdsp_dma_input(addr, p, cc, intr, arg)
936 1.5 mycroft void *addr;
937 1.1 brezak void *p;
938 1.1 brezak int cc;
939 1.1 brezak void (*intr)();
940 1.1 brezak void *arg;
941 1.1 brezak {
942 1.5 mycroft register struct sbdsp_softc *sc = addr;
943 1.1 brezak register u_short iobase;
944 1.1 brezak u_int phys;
945 1.1 brezak
946 1.12 brezak #ifdef AUDIO_DEBUG
947 1.1 brezak if (sbdspdebug > 1)
948 1.1 brezak Dprintf("sbdsp_dma_input: cc=%d 0x%x (0x%x)\n", cc, intr, arg);
949 1.1 brezak #endif
950 1.1 brezak if (sc->sc_chans == 2 && (cc & 1)) {
951 1.1 brezak DPRINTF(("sbdsp_dma_input: stereo input, odd bytecnt\n"));
952 1.1 brezak return EIO;
953 1.1 brezak }
954 1.1 brezak iobase = sc->sc_iobase;
955 1.1 brezak if (ISSBPROCLASS(sc) && !sc->sc_dmain_inprogress) {
956 1.1 brezak if (sc->sc_chans == 2) {
957 1.1 brezak if (sbdsp_wdsp(iobase, SB_DSP_RECORD_STEREO) < 0)
958 1.1 brezak goto badmode;
959 1.1 brezak sbdsp_mix_write(sc, SBP_STEREO,
960 1.1 brezak sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK);
961 1.1 brezak sbdsp_mix_write(sc, SBP_INFILTER,
962 1.1 brezak sbdsp_mix_read(sc, SBP_INFILTER) | SBP_FILTER_OFF);
963 1.1 brezak }
964 1.1 brezak else {
965 1.1 brezak if (sbdsp_wdsp(iobase, SB_DSP_RECORD_MONO) < 0)
966 1.1 brezak goto badmode;
967 1.1 brezak sbdsp_mix_write(sc, SBP_STEREO,
968 1.1 brezak sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK);
969 1.1 brezak sbdsp_mix_write(sc, SBP_INFILTER,
970 1.1 brezak sc->sc_irate <= 8000 ?
971 1.1 brezak sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_FILTER_MASK :
972 1.1 brezak sbdsp_mix_read(sc, SBP_INFILTER) | SBP_FILTER_OFF);
973 1.1 brezak }
974 1.1 brezak sc->sc_dmain_inprogress = 1;
975 1.1 brezak sc->sc_last_hsr_size = 0; /* restarting */
976 1.1 brezak }
977 1.1 brezak sc->sc_dmaout_inprogress = 0;
978 1.1 brezak
979 1.12 brezak isa_dmastart(B_READ, p, cc, sc->sc_drq);
980 1.1 brezak sc->sc_intr = intr;
981 1.1 brezak sc->sc_arg = arg;
982 1.1 brezak sc->dmaflags = B_READ;
983 1.1 brezak sc->dmaaddr = p;
984 1.1 brezak sc->dmacnt = --cc; /* DMA controller is strange...? */
985 1.1 brezak if (sc->sc_adacmode == SB_ADAC_LS) {
986 1.1 brezak if (sbdsp_wdsp(iobase, SB_DSP_RDMA) < 0 ||
987 1.1 brezak sbdsp_wdsp(iobase, cc) < 0 ||
988 1.1 brezak sbdsp_wdsp(iobase, cc >> 8) < 0) {
989 1.1 brezak goto giveup;
990 1.1 brezak }
991 1.1 brezak }
992 1.1 brezak else {
993 1.1 brezak if (cc != sc->sc_last_hsr_size) {
994 1.1 brezak if (sbdsp_wdsp(iobase, SB_DSP_BLOCKSIZE) < 0 ||
995 1.1 brezak sbdsp_wdsp(iobase, cc) < 0 ||
996 1.1 brezak sbdsp_wdsp(iobase, cc >> 8) < 0)
997 1.1 brezak goto giveup;
998 1.1 brezak }
999 1.1 brezak if (sbdsp_wdsp(iobase, SB_DSP_HS_INPUT) < 0)
1000 1.1 brezak goto giveup;
1001 1.1 brezak sc->sc_last_hsr_size = cc;
1002 1.1 brezak sc->sc_locked = 1;
1003 1.1 brezak }
1004 1.1 brezak return 0;
1005 1.1 brezak
1006 1.1 brezak giveup:
1007 1.1 brezak isa_dmaabort(sc->sc_drq);
1008 1.1 brezak sbdsp_reset(sc);
1009 1.1 brezak sc->sc_intr = 0;
1010 1.1 brezak sc->sc_arg = 0;
1011 1.1 brezak return EIO;
1012 1.1 brezak badmode:
1013 1.1 brezak DPRINTF(("sbdsp_dma_input: can't set %s mode\n",
1014 1.1 brezak sc->sc_chans == 2 ? "stereo" : "mono"));
1015 1.1 brezak return EIO;
1016 1.1 brezak }
1017 1.1 brezak
1018 1.1 brezak int
1019 1.1 brezak sbdsp_dma_output(addr, p, cc, intr, arg)
1020 1.5 mycroft void *addr;
1021 1.1 brezak void *p;
1022 1.1 brezak int cc;
1023 1.1 brezak void (*intr)();
1024 1.1 brezak void *arg;
1025 1.1 brezak {
1026 1.5 mycroft register struct sbdsp_softc *sc = addr;
1027 1.1 brezak register u_short iobase;
1028 1.1 brezak
1029 1.12 brezak #ifdef AUDIO_DEBUG
1030 1.1 brezak if (sbdspdebug > 1)
1031 1.1 brezak Dprintf("sbdsp_dma_output: cc=%d 0x%x (0x%x)\n", cc, intr, arg);
1032 1.1 brezak #endif
1033 1.1 brezak if (sc->sc_chans == 2 && cc & 1) {
1034 1.1 brezak DPRINTF(("stereo playback odd bytes (%d)\n", cc));
1035 1.1 brezak return EIO;
1036 1.1 brezak }
1037 1.1 brezak
1038 1.1 brezak if (ISSBPROCLASS(sc) && !sc->sc_dmaout_inprogress) {
1039 1.1 brezak /* make sure we re-set stereo mixer bit when we start
1040 1.1 brezak output. */
1041 1.1 brezak sbdsp_mix_write(sc, SBP_STEREO,
1042 1.1 brezak (sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK) |
1043 1.1 brezak (sc->sc_chans == 2 ?
1044 1.1 brezak SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO));
1045 1.1 brezak sc->sc_dmaout_inprogress = 1;
1046 1.1 brezak sc->sc_last_hsw_size = 0; /* restarting */
1047 1.1 brezak }
1048 1.1 brezak sc->sc_dmain_inprogress = 0;
1049 1.12 brezak isa_dmastart(B_WRITE, p, cc, sc->sc_drq);
1050 1.1 brezak sc->sc_intr = intr;
1051 1.1 brezak sc->sc_arg = arg;
1052 1.1 brezak sc->dmaflags = B_WRITE;
1053 1.1 brezak sc->dmaaddr = p;
1054 1.1 brezak sc->dmacnt = --cc; /* a vagary of how DMA works, apparently. */
1055 1.1 brezak
1056 1.1 brezak iobase = sc->sc_iobase;
1057 1.1 brezak if (sc->sc_adacmode == SB_ADAC_LS) {
1058 1.1 brezak if (sbdsp_wdsp(iobase, SB_DSP_WDMA) < 0 ||
1059 1.1 brezak sbdsp_wdsp(iobase, cc) < 0 ||
1060 1.1 brezak sbdsp_wdsp(iobase, cc >> 8) < 0) {
1061 1.1 brezak DPRINTF(("sbdsp_dma_output: LS DMA start failed\n"));
1062 1.1 brezak goto giveup;
1063 1.1 brezak }
1064 1.1 brezak }
1065 1.1 brezak else {
1066 1.1 brezak if (cc != sc->sc_last_hsw_size) {
1067 1.1 brezak if (sbdsp_wdsp(iobase, SB_DSP_BLOCKSIZE) < 0) {
1068 1.1 brezak /* sometimes fails initial startup?? */
1069 1.1 brezak delay(100);
1070 1.1 brezak if (sbdsp_wdsp(iobase, SB_DSP_BLOCKSIZE) < 0) {
1071 1.1 brezak DPRINTF(("sbdsp_dma_output: BLOCKSIZE failed\n"));
1072 1.1 brezak goto giveup;
1073 1.1 brezak }
1074 1.1 brezak }
1075 1.1 brezak if (sbdsp_wdsp(iobase, cc) < 0 ||
1076 1.1 brezak sbdsp_wdsp(iobase, cc >> 8) < 0) {
1077 1.1 brezak DPRINTF(("sbdsp_dma_output: HS DMA start failed\n"));
1078 1.1 brezak goto giveup;
1079 1.1 brezak }
1080 1.1 brezak sc->sc_last_hsw_size = cc;
1081 1.1 brezak }
1082 1.1 brezak if (sbdsp_wdsp(iobase, SB_DSP_HS_OUTPUT) < 0) {
1083 1.1 brezak delay(100);
1084 1.1 brezak if (sbdsp_wdsp(iobase, SB_DSP_HS_OUTPUT) < 0) {
1085 1.1 brezak DPRINTF(("sbdsp_dma_output: HS DMA restart failed\n"));
1086 1.1 brezak goto giveup;
1087 1.1 brezak }
1088 1.1 brezak }
1089 1.1 brezak sc->sc_locked = 1;
1090 1.1 brezak }
1091 1.1 brezak
1092 1.1 brezak return 0;
1093 1.1 brezak
1094 1.1 brezak giveup:
1095 1.1 brezak isa_dmaabort(sc->sc_drq);
1096 1.1 brezak sbdsp_reset(sc);
1097 1.1 brezak sc->sc_intr = 0;
1098 1.1 brezak sc->sc_arg = 0;
1099 1.1 brezak return EIO;
1100 1.1 brezak }
1101 1.1 brezak
1102 1.1 brezak /*
1103 1.1 brezak * Only the DSP unit on the sound blaster generates interrupts.
1104 1.1 brezak * There are three cases of interrupt: reception of a midi byte
1105 1.1 brezak * (when mode is enabled), completion of dma transmission, or
1106 1.1 brezak * completion of a dma reception. The three modes are mutually
1107 1.1 brezak * exclusive so we know a priori which event has occurred.
1108 1.1 brezak */
1109 1.1 brezak int
1110 1.6 cgd sbdsp_intr(arg)
1111 1.6 cgd void *arg;
1112 1.1 brezak {
1113 1.6 cgd register struct sbdsp_softc *sc = arg;
1114 1.1 brezak
1115 1.12 brezak #ifdef AUDIO_DEBUG
1116 1.1 brezak if (sbdspdebug > 1)
1117 1.1 brezak Dprintf("sbdsp_intr: intr=0x%x\n", sc->sc_intr);
1118 1.1 brezak #endif
1119 1.1 brezak sc->sc_interrupts++;
1120 1.1 brezak sc->sc_locked = 0;
1121 1.1 brezak /* clear interrupt */
1122 1.1 brezak inb(sc->sc_iobase + SBP_DSP_RSTAT);
1123 1.1 brezak #if 0
1124 1.1 brezak if (sc->sc_mintr != 0) {
1125 1.1 brezak int c = sbdsp_rdsp(sc->sc_iobase);
1126 1.1 brezak (*sc->sc_mintr)(sc->sc_arg, c);
1127 1.1 brezak } else
1128 1.1 brezak #endif
1129 1.1 brezak if (sc->sc_intr != 0) {
1130 1.1 brezak /*
1131 1.1 brezak * The SBPro used to develop and test this driver often
1132 1.1 brezak * generated dma underruns--it interrupted to signal
1133 1.1 brezak * completion of the DMA input recording block, but the
1134 1.1 brezak * ISA DMA controller didn't think the channel was
1135 1.1 brezak * finished. Maybe this is just a bus speed issue, I dunno,
1136 1.1 brezak * but it seems strange and leads to channel-flipping with stereo
1137 1.1 brezak * recording. Sigh.
1138 1.1 brezak */
1139 1.1 brezak isa_dmadone(sc->dmaflags, sc->dmaaddr, sc->dmacnt,
1140 1.1 brezak sc->sc_drq);
1141 1.1 brezak sc->dmaflags = 0;
1142 1.1 brezak sc->dmaaddr = 0;
1143 1.1 brezak sc->dmacnt = 0;
1144 1.1 brezak (*sc->sc_intr)(sc->sc_arg);
1145 1.1 brezak }
1146 1.1 brezak else
1147 1.1 brezak return 0;
1148 1.1 brezak return 1;
1149 1.1 brezak }
1150 1.1 brezak
1151 1.1 brezak #if 0
1152 1.1 brezak /*
1153 1.1 brezak * Enter midi uart mode and arrange for read interrupts
1154 1.1 brezak * to vector to `intr'. This puts the card in a mode
1155 1.1 brezak * which allows only midi I/O; the card must be reset
1156 1.1 brezak * to leave this mode. Unfortunately, the card does not
1157 1.1 brezak * use transmit interrupts, so bytes must be output
1158 1.1 brezak * using polling. To keep the polling overhead to a
1159 1.1 brezak * minimum, output should be driven off a timer.
1160 1.1 brezak * This is a little tricky since only 320us separate
1161 1.1 brezak * consecutive midi bytes.
1162 1.1 brezak */
1163 1.1 brezak void
1164 1.1 brezak sbdsp_set_midi_mode(sc, intr, arg)
1165 1.1 brezak struct sbdsp_softc *sc;
1166 1.1 brezak void (*intr)();
1167 1.1 brezak void *arg;
1168 1.1 brezak {
1169 1.1 brezak
1170 1.1 brezak sbdsp_wdsp(sc->sc_iobase, SB_MIDI_UART_INTR);
1171 1.1 brezak sc->sc_mintr = intr;
1172 1.1 brezak sc->sc_intr = 0;
1173 1.1 brezak sc->sc_arg = arg;
1174 1.1 brezak }
1175 1.1 brezak
1176 1.1 brezak /*
1177 1.1 brezak * Write a byte to the midi port, when in midi uart mode.
1178 1.1 brezak */
1179 1.1 brezak void
1180 1.1 brezak sbdsp_midi_output(sc, v)
1181 1.1 brezak struct sbdsp_softc *sc;
1182 1.1 brezak int v;
1183 1.1 brezak {
1184 1.1 brezak
1185 1.1 brezak if (sbdsp_wdsp(sc->sc_iobase, v) < 0)
1186 1.1 brezak ++sberr.wmidi;
1187 1.1 brezak }
1188 1.1 brezak #endif
1189 1.1 brezak
1190 1.1 brezak u_int
1191 1.1 brezak sbdsp_get_silence(enc)
1192 1.1 brezak int enc;
1193 1.1 brezak {
1194 1.1 brezak #define ULAW_SILENCE 0x7f
1195 1.1 brezak #define LINEAR_SILENCE 0
1196 1.1 brezak u_int auzero;
1197 1.1 brezak
1198 1.1 brezak switch (enc) {
1199 1.1 brezak case AUDIO_ENCODING_ULAW:
1200 1.1 brezak auzero = ULAW_SILENCE;
1201 1.1 brezak break;
1202 1.1 brezak case AUDIO_ENCODING_PCM16:
1203 1.1 brezak default:
1204 1.1 brezak auzero = LINEAR_SILENCE;
1205 1.1 brezak break;
1206 1.1 brezak }
1207 1.1 brezak
1208 1.1 brezak return(auzero);
1209 1.1 brezak }
1210 1.1 brezak
1211 1.1 brezak static u_char mulawtolin[256] = {
1212 1.1 brezak 128, 4, 8, 12, 16, 20, 24, 28,
1213 1.1 brezak 32, 36, 40, 44, 48, 52, 56, 60,
1214 1.1 brezak 64, 66, 68, 70, 72, 74, 76, 78,
1215 1.1 brezak 80, 82, 84, 86, 88, 90, 92, 94,
1216 1.1 brezak 96, 97, 98, 99, 100, 101, 102, 103,
1217 1.1 brezak 104, 105, 106, 107, 108, 109, 110, 111,
1218 1.1 brezak 112, 112, 113, 113, 114, 114, 115, 115,
1219 1.1 brezak 116, 116, 117, 117, 118, 118, 119, 119,
1220 1.1 brezak 120, 120, 120, 121, 121, 121, 121, 122,
1221 1.1 brezak 122, 122, 122, 123, 123, 123, 123, 124,
1222 1.1 brezak 124, 124, 124, 124, 125, 125, 125, 125,
1223 1.1 brezak 125, 125, 125, 125, 126, 126, 126, 126,
1224 1.1 brezak 126, 126, 126, 126, 126, 126, 126, 126,
1225 1.1 brezak 127, 127, 127, 127, 127, 127, 127, 127,
1226 1.1 brezak 127, 127, 127, 127, 127, 127, 127, 127,
1227 1.1 brezak 127, 127, 127, 127, 127, 127, 127, 127,
1228 1.1 brezak 255, 251, 247, 243, 239, 235, 231, 227,
1229 1.1 brezak 223, 219, 215, 211, 207, 203, 199, 195,
1230 1.1 brezak 191, 189, 187, 185, 183, 181, 179, 177,
1231 1.1 brezak 175, 173, 171, 169, 167, 165, 163, 161,
1232 1.1 brezak 159, 158, 157, 156, 155, 154, 153, 152,
1233 1.1 brezak 151, 150, 149, 148, 147, 146, 145, 144,
1234 1.1 brezak 143, 143, 142, 142, 141, 141, 140, 140,
1235 1.1 brezak 139, 139, 138, 138, 137, 137, 136, 136,
1236 1.1 brezak 135, 135, 135, 134, 134, 134, 134, 133,
1237 1.1 brezak 133, 133, 133, 132, 132, 132, 132, 131,
1238 1.1 brezak 131, 131, 131, 131, 130, 130, 130, 130,
1239 1.1 brezak 130, 130, 130, 130, 129, 129, 129, 129,
1240 1.1 brezak 129, 129, 129, 129, 129, 129, 129, 129,
1241 1.1 brezak 128, 128, 128, 128, 128, 128, 128, 128,
1242 1.1 brezak 128, 128, 128, 128, 128, 128, 128, 128,
1243 1.1 brezak 128, 128, 128, 128, 128, 128, 128, 128,
1244 1.1 brezak };
1245 1.1 brezak
1246 1.1 brezak static u_char lintomulaw[256] = {
1247 1.1 brezak 0, 0, 0, 0, 0, 1, 1, 1,
1248 1.1 brezak 1, 2, 2, 2, 2, 3, 3, 3,
1249 1.1 brezak 3, 4, 4, 4, 4, 5, 5, 5,
1250 1.1 brezak 5, 6, 6, 6, 6, 7, 7, 7,
1251 1.1 brezak 7, 8, 8, 8, 8, 9, 9, 9,
1252 1.1 brezak 9, 10, 10, 10, 10, 11, 11, 11,
1253 1.1 brezak 11, 12, 12, 12, 12, 13, 13, 13,
1254 1.1 brezak 13, 14, 14, 14, 14, 15, 15, 15,
1255 1.1 brezak 15, 16, 16, 17, 17, 18, 18, 19,
1256 1.1 brezak 19, 20, 20, 21, 21, 22, 22, 23,
1257 1.1 brezak 23, 24, 24, 25, 25, 26, 26, 27,
1258 1.1 brezak 27, 28, 28, 29, 29, 30, 30, 31,
1259 1.1 brezak 31, 32, 33, 34, 35, 36, 37, 38,
1260 1.1 brezak 39, 40, 41, 42, 43, 44, 45, 46,
1261 1.1 brezak 47, 48, 50, 52, 54, 56, 58, 60,
1262 1.1 brezak 62, 65, 69, 73, 77, 83, 91, 103,
1263 1.1 brezak 255, 231, 219, 211, 205, 201, 197, 193,
1264 1.1 brezak 190, 188, 186, 184, 182, 180, 178, 176,
1265 1.1 brezak 175, 174, 173, 172, 171, 170, 169, 168,
1266 1.1 brezak 167, 166, 165, 164, 163, 162, 161, 160,
1267 1.1 brezak 159, 159, 158, 158, 157, 157, 156, 156,
1268 1.1 brezak 155, 155, 154, 154, 153, 153, 152, 152,
1269 1.1 brezak 151, 151, 150, 150, 149, 149, 148, 148,
1270 1.1 brezak 147, 147, 146, 146, 145, 145, 144, 144,
1271 1.1 brezak 143, 143, 143, 143, 142, 142, 142, 142,
1272 1.1 brezak 141, 141, 141, 141, 140, 140, 140, 140,
1273 1.1 brezak 139, 139, 139, 139, 138, 138, 138, 138,
1274 1.1 brezak 137, 137, 137, 137, 136, 136, 136, 136,
1275 1.1 brezak 135, 135, 135, 135, 134, 134, 134, 134,
1276 1.1 brezak 133, 133, 133, 133, 132, 132, 132, 132,
1277 1.1 brezak 131, 131, 131, 131, 130, 130, 130, 130,
1278 1.1 brezak 129, 129, 129, 129, 128, 128, 128, 128,
1279 1.1 brezak };
1280 1.1 brezak
1281 1.1 brezak void
1282 1.1 brezak sbdsp_compress(e, p, cc)
1283 1.1 brezak int e;
1284 1.1 brezak u_char *p;
1285 1.1 brezak int cc;
1286 1.1 brezak {
1287 1.1 brezak u_char *tab;
1288 1.1 brezak
1289 1.1 brezak switch (e) {
1290 1.1 brezak case AUDIO_ENCODING_ULAW:
1291 1.1 brezak tab = lintomulaw;
1292 1.1 brezak break;
1293 1.1 brezak default:
1294 1.1 brezak return;
1295 1.1 brezak }
1296 1.1 brezak
1297 1.1 brezak while (--cc >= 0) {
1298 1.1 brezak *p = tab[*p];
1299 1.1 brezak ++p;
1300 1.1 brezak }
1301 1.1 brezak }
1302 1.1 brezak
1303 1.1 brezak void
1304 1.1 brezak sbdsp_expand(e, p, cc)
1305 1.1 brezak int e;
1306 1.1 brezak u_char *p;
1307 1.1 brezak int cc;
1308 1.1 brezak {
1309 1.1 brezak u_char *tab;
1310 1.1 brezak
1311 1.1 brezak switch (e) {
1312 1.1 brezak case AUDIO_ENCODING_ULAW:
1313 1.1 brezak tab = mulawtolin;
1314 1.1 brezak break;
1315 1.1 brezak default:
1316 1.1 brezak return;
1317 1.1 brezak }
1318 1.1 brezak
1319 1.1 brezak while (--cc >= 0) {
1320 1.1 brezak *p = tab[*p];
1321 1.1 brezak ++p;
1322 1.1 brezak }
1323 1.1 brezak }
1324 1.1 brezak
1325 1.1 brezak int
1326 1.1 brezak sbdsp_setfd(addr, flag)
1327 1.5 mycroft void *addr;
1328 1.1 brezak int flag;
1329 1.1 brezak {
1330 1.1 brezak /* Can't do full-duplex */
1331 1.1 brezak return(ENOTTY);
1332 1.1 brezak }
1333 1.1 brezak
1334 1.1 brezak int
1335 1.1 brezak sbdsp_mixer_set_port(addr, cp)
1336 1.5 mycroft void *addr;
1337 1.1 brezak mixer_ctrl_t *cp;
1338 1.1 brezak {
1339 1.5 mycroft register struct sbdsp_softc *sc = addr;
1340 1.1 brezak int error = 0;
1341 1.1 brezak int src, gain;
1342 1.1 brezak int left, right;
1343 1.1 brezak
1344 1.1 brezak DPRINTF(("sbdsp_mixer_set_port: port=%d num_channels=%d\n", cp->dev, cp->un.value.num_channels));
1345 1.1 brezak
1346 1.1 brezak /*
1347 1.1 brezak * Everything is a value except for SBPro special OUTPUT_MODE and
1348 1.1 brezak * RECORD_SOURCE
1349 1.1 brezak */
1350 1.1 brezak if (cp->type != AUDIO_MIXER_VALUE) {
1351 1.1 brezak if (!ISSBPROCLASS(sc) || (cp->dev != SB_OUTPUT_MODE &&
1352 1.1 brezak cp->dev != SB_RECORD_SOURCE))
1353 1.1 brezak return EINVAL;
1354 1.1 brezak }
1355 1.1 brezak else {
1356 1.1 brezak /*
1357 1.1 brezak * All the mixer ports are stereo except for the microphone.
1358 1.1 brezak * If we get a single-channel gain value passed in, then we
1359 1.1 brezak * duplicate it to both left and right channels.
1360 1.1 brezak */
1361 1.1 brezak if (cp->un.value.num_channels == 2) {
1362 1.1 brezak left = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
1363 1.1 brezak right = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
1364 1.1 brezak }
1365 1.1 brezak else
1366 1.1 brezak left = right = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
1367 1.1 brezak }
1368 1.1 brezak
1369 1.1 brezak if (ISSBPROCLASS(sc)) {
1370 1.1 brezak /* The _PORT things are all signal inputs to the mixer.
1371 1.1 brezak * Here we are tweaking their mixing level.
1372 1.1 brezak *
1373 1.1 brezak * We can also tweak the output stage volume (MASTER_VOL)
1374 1.1 brezak */
1375 1.1 brezak gain = sbdsp_stereo_vol(SBP_AGAIN_TO_SBGAIN(left),
1376 1.1 brezak SBP_AGAIN_TO_SBGAIN(right));
1377 1.1 brezak switch(cp->dev) {
1378 1.1 brezak case SB_MIC_PORT:
1379 1.1 brezak src = SBP_MIC_VOL;
1380 1.1 brezak if (cp->un.value.num_channels != 1)
1381 1.1 brezak error = EINVAL;
1382 1.1 brezak else
1383 1.1 brezak /* handle funny microphone gain */
1384 1.1 brezak gain = SBP_AGAIN_TO_MICGAIN(left);
1385 1.1 brezak break;
1386 1.1 brezak case SB_LINE_IN_PORT:
1387 1.1 brezak src = SBP_LINE_VOL;
1388 1.1 brezak break;
1389 1.1 brezak case SB_DAC_PORT:
1390 1.1 brezak src = SBP_DAC_VOL;
1391 1.1 brezak break;
1392 1.1 brezak case SB_FM_PORT:
1393 1.1 brezak src = SBP_FM_VOL;
1394 1.1 brezak break;
1395 1.1 brezak case SB_CD_PORT:
1396 1.1 brezak src = SBP_CD_VOL;
1397 1.1 brezak break;
1398 1.1 brezak case SB_SPEAKER:
1399 1.1 brezak cp->dev = SB_MASTER_VOL;
1400 1.1 brezak case SB_MASTER_VOL:
1401 1.1 brezak src = SBP_MASTER_VOL;
1402 1.1 brezak break;
1403 1.1 brezak #if 0
1404 1.1 brezak case SB_OUTPUT_MODE:
1405 1.1 brezak if (cp->type == AUDIO_MIXER_ENUM)
1406 1.1 brezak return sbdsp_set_channels(addr, cp->un.ord);
1407 1.1 brezak /* fall through...carefully! */
1408 1.1 brezak #endif
1409 1.1 brezak case SB_RECORD_SOURCE:
1410 1.1 brezak if (cp->type == AUDIO_MIXER_ENUM)
1411 1.1 brezak return sbdsp_set_in_port(addr, cp->un.ord);
1412 1.1 brezak /* else fall through: bad input */
1413 1.1 brezak case SB_TREBLE:
1414 1.1 brezak case SB_BASS:
1415 1.1 brezak default:
1416 1.1 brezak error = EINVAL;
1417 1.1 brezak break;
1418 1.1 brezak }
1419 1.1 brezak if (!error)
1420 1.1 brezak sbdsp_mix_write(sc, src, gain);
1421 1.1 brezak }
1422 1.1 brezak else if (cp->dev != SB_MIC_PORT &&
1423 1.1 brezak cp->dev != SB_SPEAKER)
1424 1.1 brezak error = EINVAL;
1425 1.1 brezak
1426 1.1 brezak if (!error)
1427 1.1 brezak sc->gain[cp->dev] = gain;
1428 1.1 brezak
1429 1.1 brezak return(error);
1430 1.1 brezak }
1431 1.1 brezak
1432 1.1 brezak int
1433 1.1 brezak sbdsp_mixer_get_port(addr, cp)
1434 1.5 mycroft void *addr;
1435 1.1 brezak mixer_ctrl_t *cp;
1436 1.1 brezak {
1437 1.5 mycroft register struct sbdsp_softc *sc = addr;
1438 1.1 brezak int error = 0;
1439 1.1 brezak int done = 0;
1440 1.1 brezak
1441 1.1 brezak DPRINTF(("sbdsp_mixer_get_port: port=%d", cp->dev));
1442 1.1 brezak
1443 1.1 brezak if (ISSBPROCLASS(sc))
1444 1.1 brezak switch(cp->dev) {
1445 1.1 brezak case SB_MIC_PORT:
1446 1.1 brezak if (cp->un.value.num_channels == 1) {
1447 1.1 brezak cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1448 1.1 brezak SBP_MICGAIN_TO_AGAIN(sc->gain[cp->dev]);
1449 1.1 brezak return 0;
1450 1.1 brezak }
1451 1.1 brezak else
1452 1.1 brezak return EINVAL;
1453 1.1 brezak break;
1454 1.1 brezak case SB_LINE_IN_PORT:
1455 1.1 brezak case SB_DAC_PORT:
1456 1.1 brezak case SB_FM_PORT:
1457 1.1 brezak case SB_CD_PORT:
1458 1.1 brezak case SB_MASTER_VOL:
1459 1.1 brezak break;
1460 1.1 brezak case SB_SPEAKER:
1461 1.1 brezak cp->dev = SB_MASTER_VOL;
1462 1.1 brezak break;
1463 1.1 brezak default:
1464 1.1 brezak error = EINVAL;
1465 1.1 brezak break;
1466 1.1 brezak }
1467 1.1 brezak else {
1468 1.1 brezak if (cp->un.value.num_channels != 1) /* no stereo on SB classic */
1469 1.1 brezak error = EINVAL;
1470 1.1 brezak else
1471 1.1 brezak switch(cp->dev) {
1472 1.1 brezak case SB_MIC_PORT:
1473 1.1 brezak break;
1474 1.1 brezak case SB_SPEAKER:
1475 1.1 brezak break;
1476 1.1 brezak default:
1477 1.1 brezak error = EINVAL;
1478 1.1 brezak break;
1479 1.1 brezak }
1480 1.1 brezak }
1481 1.1 brezak if (error == 0) {
1482 1.1 brezak if (cp->un.value.num_channels == 1) {
1483 1.1 brezak cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1484 1.1 brezak SBP_SBGAIN_TO_AGAIN(sc->gain[cp->dev]);
1485 1.1 brezak }
1486 1.1 brezak else if (cp->un.value.num_channels == 2) {
1487 1.1 brezak cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
1488 1.1 brezak SBP_LEFTGAIN(sc->gain[cp->dev]);
1489 1.1 brezak cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
1490 1.1 brezak SBP_RIGHTGAIN(sc->gain[cp->dev]);
1491 1.1 brezak } else
1492 1.1 brezak return EINVAL;
1493 1.1 brezak }
1494 1.1 brezak return(error);
1495 1.1 brezak }
1496 1.1 brezak
1497 1.1 brezak int
1498 1.1 brezak sbdsp_mixer_query_devinfo(addr, dip)
1499 1.5 mycroft void *addr;
1500 1.1 brezak register mixer_devinfo_t *dip;
1501 1.1 brezak {
1502 1.5 mycroft register struct sbdsp_softc *sc = addr;
1503 1.1 brezak int done = 0;
1504 1.1 brezak
1505 1.1 brezak DPRINTF(("sbdsp_mixer_query_devinfo: index=%d\n", dip->index));
1506 1.1 brezak
1507 1.1 brezak switch (dip->index) {
1508 1.1 brezak case SB_MIC_PORT:
1509 1.1 brezak dip->type = AUDIO_MIXER_VALUE;
1510 1.1 brezak dip->mixer_class = SB_INPUT_CLASS;
1511 1.1 brezak dip->prev = AUDIO_MIXER_LAST;
1512 1.1 brezak dip->next = AUDIO_MIXER_LAST;
1513 1.1 brezak strcpy(dip->label.name, AudioNmicrophone);
1514 1.1 brezak dip->un.v.num_channels = 1;
1515 1.1 brezak strcpy(dip->un.v.units.name, AudioNvolume);
1516 1.1 brezak done = 1;
1517 1.1 brezak break;
1518 1.1 brezak case SB_SPEAKER:
1519 1.1 brezak dip->type = AUDIO_MIXER_VALUE;
1520 1.1 brezak dip->mixer_class = SB_OUTPUT_CLASS;
1521 1.1 brezak dip->prev = AUDIO_MIXER_LAST;
1522 1.1 brezak dip->next = AUDIO_MIXER_LAST;
1523 1.1 brezak strcpy(dip->label.name, AudioNspeaker);
1524 1.1 brezak dip->un.v.num_channels = 1;
1525 1.1 brezak strcpy(dip->un.v.units.name, AudioNvolume);
1526 1.1 brezak done = 1;
1527 1.1 brezak break;
1528 1.1 brezak case SB_INPUT_CLASS:
1529 1.1 brezak dip->type = AUDIO_MIXER_CLASS;
1530 1.1 brezak dip->mixer_class = SB_INPUT_CLASS;
1531 1.1 brezak dip->next = dip->prev = AUDIO_MIXER_LAST;
1532 1.1 brezak strcpy(dip->label.name, AudioCInputs);
1533 1.1 brezak done = 1;
1534 1.1 brezak break;
1535 1.1 brezak case SB_OUTPUT_CLASS:
1536 1.1 brezak dip->type = AUDIO_MIXER_CLASS;
1537 1.1 brezak dip->mixer_class = SB_OUTPUT_CLASS;
1538 1.1 brezak dip->next = dip->prev = AUDIO_MIXER_LAST;
1539 1.1 brezak strcpy(dip->label.name, AudioCOutputs);
1540 1.1 brezak done = 1;
1541 1.1 brezak break;
1542 1.1 brezak }
1543 1.1 brezak
1544 1.1 brezak if (!done) {
1545 1.1 brezak if (ISSBPROCLASS(sc))
1546 1.1 brezak switch(dip->index) {
1547 1.1 brezak case SB_LINE_IN_PORT:
1548 1.1 brezak dip->type = AUDIO_MIXER_VALUE;
1549 1.1 brezak dip->mixer_class = SB_INPUT_CLASS;
1550 1.1 brezak dip->prev = AUDIO_MIXER_LAST;
1551 1.1 brezak dip->next = AUDIO_MIXER_LAST;
1552 1.1 brezak strcpy(dip->label.name, AudioNline);
1553 1.1 brezak dip->un.v.num_channels = 2;
1554 1.1 brezak strcpy(dip->un.v.units.name, AudioNvolume);
1555 1.1 brezak break;
1556 1.1 brezak case SB_DAC_PORT:
1557 1.1 brezak dip->type = AUDIO_MIXER_VALUE;
1558 1.10 brezak dip->mixer_class = SB_OUTPUT_CLASS;
1559 1.1 brezak dip->prev = AUDIO_MIXER_LAST;
1560 1.1 brezak dip->next = AUDIO_MIXER_LAST;
1561 1.1 brezak strcpy(dip->label.name, AudioNdac);
1562 1.1 brezak dip->un.v.num_channels = 2;
1563 1.1 brezak strcpy(dip->un.v.units.name, AudioNvolume);
1564 1.1 brezak break;
1565 1.1 brezak case SB_CD_PORT:
1566 1.1 brezak dip->type = AUDIO_MIXER_VALUE;
1567 1.1 brezak dip->mixer_class = SB_INPUT_CLASS;
1568 1.1 brezak dip->prev = AUDIO_MIXER_LAST;
1569 1.1 brezak dip->next = AUDIO_MIXER_LAST;
1570 1.1 brezak strcpy(dip->label.name, AudioNcd);
1571 1.1 brezak dip->un.v.num_channels = 2;
1572 1.1 brezak strcpy(dip->un.v.units.name, AudioNvolume);
1573 1.1 brezak break;
1574 1.1 brezak case SB_FM_PORT:
1575 1.1 brezak dip->type = AUDIO_MIXER_VALUE;
1576 1.10 brezak dip->mixer_class = SB_OUTPUT_CLASS;
1577 1.1 brezak dip->prev = AUDIO_MIXER_LAST;
1578 1.1 brezak dip->next = AUDIO_MIXER_LAST;
1579 1.1 brezak strcpy(dip->label.name, "fmsynth"); /* XXX move to audioio.h */
1580 1.1 brezak dip->un.v.num_channels = 2;
1581 1.1 brezak strcpy(dip->un.v.units.name, AudioNvolume);
1582 1.1 brezak break;
1583 1.1 brezak case SB_MASTER_VOL:
1584 1.1 brezak dip->type = AUDIO_MIXER_VALUE;
1585 1.1 brezak dip->mixer_class = SB_OUTPUT_CLASS;
1586 1.1 brezak dip->prev = AUDIO_MIXER_LAST;
1587 1.10 brezak dip->next = /*TREBLE, BASS not handled, nor is SB_OUTPUT_MODE*/SB_RECORD_SOURCE;
1588 1.1 brezak strcpy(dip->label.name, AudioNvolume);
1589 1.1 brezak dip->un.v.num_channels = 2;
1590 1.1 brezak strcpy(dip->un.v.units.name, AudioNvolume);
1591 1.1 brezak break;
1592 1.1 brezak #if 0
1593 1.1 brezak case SB_OUTPUT_MODE:
1594 1.1 brezak dip->mixer_class = SB_OUTPUT_CLASS;
1595 1.1 brezak dip->type = AUDIO_MIXER_ENUM;
1596 1.1 brezak dip->prev = SB_MASTER_VOL;
1597 1.1 brezak dip->next = AUDIO_MIXER_LAST;
1598 1.1 brezak strcpy(dip->label.name, AudioNmode);
1599 1.1 brezak dip->un.e.num_mem = 2;
1600 1.1 brezak strcpy(dip->un.e.member[0].label.name, AudioNmono);
1601 1.1 brezak dip->un.e.member[0].ord = 1; /* nchans */
1602 1.1 brezak strcpy(dip->un.e.member[1].label.name, AudioNstereo);
1603 1.1 brezak dip->un.e.member[1].ord = 2; /* nchans */
1604 1.1 brezak break;
1605 1.1 brezak #endif
1606 1.1 brezak case SB_RECORD_SOURCE:
1607 1.1 brezak dip->mixer_class = SB_RECORD_CLASS;
1608 1.1 brezak dip->type = AUDIO_MIXER_ENUM;
1609 1.1 brezak dip->prev = AUDIO_MIXER_LAST;
1610 1.1 brezak dip->next = AUDIO_MIXER_LAST;
1611 1.1 brezak strcpy(dip->label.name, AudioNsource);
1612 1.1 brezak dip->un.e.num_mem = 3;
1613 1.1 brezak strcpy(dip->un.e.member[0].label.name, AudioNmicrophone);
1614 1.1 brezak dip->un.e.member[0].ord = SB_MIC_PORT;
1615 1.1 brezak strcpy(dip->un.e.member[1].label.name, AudioNcd);
1616 1.1 brezak dip->un.e.member[1].ord = SB_CD_PORT;
1617 1.1 brezak strcpy(dip->un.e.member[2].label.name, AudioNline);
1618 1.1 brezak dip->un.e.member[2].ord = SB_LINE_IN_PORT;
1619 1.1 brezak break;
1620 1.1 brezak case SB_BASS:
1621 1.1 brezak case SB_TREBLE:
1622 1.1 brezak default:
1623 1.1 brezak return ENXIO;
1624 1.1 brezak /*NOTREACHED*/
1625 1.1 brezak }
1626 1.1 brezak else
1627 1.1 brezak return ENXIO;
1628 1.1 brezak }
1629 1.1 brezak
1630 1.1 brezak DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
1631 1.1 brezak
1632 1.1 brezak return 0;
1633 1.1 brezak }
1634