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