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