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