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