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