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