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