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