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