1 /* $NetBSD: interwave.c,v 1.14 2001/11/13 13:14:38 lukem Exp $ */ 2 3 /* 4 * Copyright (c) 1997, 1999 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Author: Kari Mettinen 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the NetBSD 20 * Foundation, Inc. and its contributors. 21 * 4. Neither the name of The NetBSD Foundation nor the names of its 22 * contributors may be used to endorse or promote products derived 23 * from this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 #include <sys/cdefs.h> 39 __KERNEL_RCSID(0, "$NetBSD: interwave.c,v 1.14 2001/11/13 13:14:38 lukem Exp $"); 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/errno.h> 44 #include <sys/ioctl.h> 45 #include <sys/syslog.h> 46 #include <sys/device.h> 47 #include <sys/proc.h> 48 #include <sys/buf.h> 49 #include <sys/fcntl.h> 50 #include <sys/malloc.h> 51 #include <sys/kernel.h> 52 53 #include <machine/cpu.h> 54 #include <machine/intr.h> 55 #include <machine/pio.h> 56 #include <machine/cpufunc.h> 57 #include <sys/audioio.h> 58 #include <dev/audio_if.h> 59 #include <dev/mulaw.h> 60 61 #include <dev/isa/isavar.h> 62 #include <dev/isa/isadmavar.h> 63 64 #include <dev/ic/interwavereg.h> 65 #include <dev/ic/interwavevar.h> 66 67 68 static void iwreset __P((struct iw_softc *, int)); 69 70 static int iw_set_speed __P((struct iw_softc *, u_long, char)); 71 static u_long iw_set_format __P((struct iw_softc *, u_long, int)); 72 static void iw_mixer_line_level __P((struct iw_softc *, int, int, int)); 73 static void iw_trigger_dma __P((struct iw_softc *, u_char)); 74 static void iw_stop_dma __P((struct iw_softc *, u_char, u_char)); 75 static void iw_dma_count __P((struct iw_softc *, u_short, int)); 76 static int iwintr __P((void *)); 77 static void iw_meminit __P((struct iw_softc *)); 78 static void iw_mempoke __P((struct iw_softc *, u_long, u_char)); 79 static u_char iw_mempeek __P((struct iw_softc *, u_long)); 80 81 #ifdef USE_WAVETABLE 82 static void iw_set_voice_place __P((struct iw_softc *, u_char, u_long)); 83 static void iw_voice_pan __P((struct iw_softc *, u_char, u_short, u_short)); 84 static void iw_voice_freq __P((struct iw_softc *, u_char, u_long)); 85 static void iw_set_loopmode __P((struct iw_softc *, u_char, u_char, u_char)); 86 static void iw_set_voice_pos __P((struct iw_softc *, u_short, u_long, u_long)); 87 static void iw_start_voice __P((struct iw_softc *, u_char)); 88 static void iw_play_voice __P((struct iw_softc *, u_long, u_long, u_short)); 89 static void iw_stop_voice __P((struct iw_softc *, u_char)); 90 static void iw_move_voice_end __P((struct iw_softc *, u_short, u_long)); 91 static void iw_initvoices __P((struct iw_softc *)); 92 #endif 93 94 struct audio_device iw_device = { 95 "Am78C201", 96 "0.1", 97 "guspnp" 98 }; 99 100 #ifdef AUDIO_DEBUG 101 int iw_debug; 102 #define DPRINTF(p) if (iw_debug) printf p 103 #else 104 #define DPRINTF(p) 105 #endif 106 107 static int iw_cc = 1; 108 #ifdef DIAGNOSTIC 109 static int outputs = 0; 110 static int iw_ints = 0; 111 static int inputs = 0; 112 static int iw_inints = 0; 113 #endif 114 115 int 116 iwintr(arg) 117 void *arg; 118 { 119 struct iw_softc *sc = arg; 120 int val = 0; 121 u_char intrs = 0; 122 123 IW_READ_DIRECT_1(6, sc->p2xr_h, intrs); /* UISR */ 124 125 /* codec ints */ 126 127 /* 128 * The proper order to do this seems to be to read CSR3 to get the 129 * int cause and fifo over underrrun status, then deal with the ints 130 * (new dma set up), and to clear ints by writing the respective bit 131 * to 0. 132 */ 133 134 /* read what ints happened */ 135 136 IW_READ_CODEC_1(CSR3I, intrs); 137 138 /* clear them */ 139 140 IW_WRITE_DIRECT_1(2, sc->codec_index_h, 0x00); 141 142 /* and process them */ 143 144 if (intrs & 0x20) { 145 #ifdef DIAGNOSTIC 146 iw_inints++; 147 #endif 148 sc->sc_reclocked = 0; 149 if (sc->sc_recintr != 0) 150 sc->sc_recintr(sc->sc_recarg); 151 val = 1; 152 } 153 if (intrs & 0x10) { 154 #ifdef DIAGNOSTIC 155 iw_ints++; 156 #endif 157 sc->sc_playlocked = 0; 158 if (sc->sc_playintr != 0) 159 sc->sc_playintr(sc->sc_playarg); 160 val = 1; 161 } 162 return val; 163 164 } 165 166 void 167 iwattach(sc) 168 struct iw_softc *sc; 169 { 170 int got_irq = 0; 171 172 DPRINTF(("iwattach sc %p\n", sc)); 173 174 sc->cdatap = 1; /* relative offsets in region */ 175 sc->csr1r = 2; 176 sc->cxdr = 3; /* CPDR or CRDR */ 177 178 sc->gmxr = 0; /* sc->p3xr */ 179 sc->gmxdr = 1; /* GMTDR or GMRDR */ 180 sc->svsr = 2; 181 sc->igidxr = 3; 182 sc->i16dp = 4; 183 sc->i8dp = 5; 184 sc->lmbdr = 7; 185 186 sc->rec_precision = sc->play_precision = 8; 187 sc->rec_channels = sc->play_channels = 1; 188 sc->rec_encoding = sc->play_encoding = AUDIO_ENCODING_ULAW; 189 sc->sc_irate = 8000; 190 sc->sc_orate = 8000; 191 192 sc->sc_fullduplex = 1; 193 194 sc->sc_reclocked = 0; 195 sc->sc_playlocked = 0; 196 197 sc->sc_dma_flags = 0; 198 199 /* 200 * We can only use a few selected irqs, see if we got one from pnp 201 * code that suits us. 202 */ 203 204 if (sc->sc_irq > 0) { 205 sc->sc_ih = isa_intr_establish(sc->sc_p2xr_ic, 206 sc->sc_irq, 207 IST_EDGE, IPL_AUDIO, iwintr, sc); 208 got_irq = 1; 209 } 210 if (!got_irq) { 211 printf("\niwattach: couldn't get a suitable irq\n"); 212 return; 213 } 214 printf("\n"); 215 iwreset(sc, 0); 216 iw_set_format(sc, AUDIO_ENCODING_ULAW, 0); 217 iw_set_format(sc, AUDIO_ENCODING_ULAW, 1); 218 printf("%s: interwave version %s\n", 219 sc->sc_dev.dv_xname, iw_device.version); 220 audio_attach_mi(sc->iw_hw_if, sc, &sc->sc_dev); 221 } 222 223 int 224 iwopen(sc, flags) 225 struct iw_softc *sc; 226 int flags; 227 { 228 int s; 229 230 s = splaudio(); 231 if (sc->sc_open) { 232 splx(s); 233 DPRINTF(("iwopen: open %x sc %p\n", sc->sc_open, sc)); 234 return EBUSY; 235 } else 236 sc->sc_open = 1; 237 splx(s); 238 239 DPRINTF(("iwopen: open %x sc %p\n", sc->sc_open, sc)); 240 241 #ifdef DIAGNOSTIC 242 outputs = 0; 243 iw_ints = 0; 244 inputs = 0; 245 iw_inints = 0; 246 #endif 247 248 iwreset(sc, 1); 249 250 /* READ/WRITE or both */ 251 252 if (flags == FREAD) { 253 sc->sc_mode |= IW_READ; 254 sc->sc_reclocked = 0; 255 } 256 if (flags == FWRITE) { 257 sc->sc_mode |= IW_WRITE; 258 sc->sc_playlocked = 0; 259 } 260 sc->sc_playdma_cnt = 0; 261 sc->sc_recdma_cnt = 0; 262 sc->playfirst = 1; 263 sc->sc_playintr = 0; 264 sc->sc_recintr = 0; 265 266 return 0; 267 } 268 269 270 271 void 272 iwclose(addr) 273 void *addr; 274 { 275 struct iw_softc *sc = addr; 276 277 DPRINTF(("iwclose sc %p\n", sc)); 278 279 #ifdef DIAGNOSTIC 280 DPRINTF(("iwclose: outputs %d ints %d inputs %d in_ints %d\n", 281 outputs, iw_ints, inputs, iw_inints)); 282 #endif 283 284 /* close hardware */ 285 sc->sc_open = 0; 286 sc->sc_flags = 0; 287 sc->sc_mode = 0; 288 sc->sc_playlocked = 0; 289 sc->sc_reclocked = 0; 290 291 iw_stop_dma(sc, IW_DMA_PLAYBACK, 1); 292 iw_stop_dma(sc, IW_DMA_RECORD, 1); 293 294 sc->sc_playdma_cnt = 0; 295 sc->sc_recdma_cnt = 0; 296 } 297 298 #define RAM_STEP 64*1024 299 300 static void 301 iw_mempoke(sc, addy, val) 302 struct iw_softc *sc; 303 u_long addy; 304 u_char val; 305 { 306 IW_WRITE_GENERAL_2(LMALI, (u_short) addy); 307 IW_WRITE_GENERAL_1(LMAHI, (u_char) (addy >> 16)); 308 309 /* Write byte to LMBDR */ 310 IW_WRITE_DIRECT_1(sc->p3xr + 7, sc->p3xr_h, val); 311 } 312 313 static u_char 314 iw_mempeek(sc, addy) 315 struct iw_softc *sc; 316 u_long addy; 317 { 318 u_char ret; 319 320 IW_WRITE_GENERAL_2(LMALI, (u_short) addy); 321 IW_WRITE_GENERAL_1(LMAHI, (u_char) (addy >> 16)); 322 323 IW_READ_DIRECT_1(sc->p3xr + 7, sc->p3xr_h, ret); 324 return ret; /* return byte from LMBDR */ 325 } 326 327 static void 328 iw_meminit(sc) 329 struct iw_softc *sc; 330 { 331 u_long bank[4] = {0L, 0L, 0L, 0L}; 332 u_long addr = 0L, base = 0L, cnt = 0L; 333 u_char i, ram = 0 /* ,memval=0 */ ; 334 u_short lmcfi; 335 u_long temppi; 336 u_long *lpbanks = &temppi; 337 338 IW_WRITE_GENERAL_1(LDMACI, 0x00); 339 340 IW_READ_GENERAL_2(LMCFI, lmcfi); /* 0x52 */ 341 lmcfi |= 0x0A0C; 342 IW_WRITE_GENERAL_2(LMCFI, lmcfi); /* max addr span */ 343 IW_WRITE_GENERAL_1(LMCI, 0x00); 344 345 /* fifo addresses */ 346 347 IW_WRITE_GENERAL_2(LMRFAI, ((4 * 1024 * 1024) >> 8)); 348 IW_WRITE_GENERAL_2(LMPFAI, ((4 * 1024 * 1024 + 16 * 1024) >> 8)); 349 350 IW_WRITE_GENERAL_2(LMFSI, 0x000); 351 352 IW_WRITE_GENERAL_2(LDICI, 0x0000); 353 354 while (addr < (16 * 1024 * 1024)) { 355 iw_mempoke(sc, addr, 0x00); 356 addr += RAM_STEP; 357 } 358 359 printf("%s:", sc->sc_dev.dv_xname); 360 361 for (i = 0; i < 4; i++) { 362 iw_mempoke(sc, base, 0xAA); /* mark start of bank */ 363 iw_mempoke(sc, base + 1L, 0x55); 364 if (iw_mempeek(sc, base) == 0xAA && 365 iw_mempeek(sc, base + 1L) == 0x55) 366 ram = 1; 367 if (ram) { 368 while (cnt < (4 * 1024 * 1024)) { 369 bank[i] += RAM_STEP; 370 cnt += RAM_STEP; 371 addr = base + cnt; 372 if (iw_mempeek(sc, addr) == 0xAA) 373 break; 374 } 375 } 376 if (lpbanks != NULL) { 377 *lpbanks = bank[i]; 378 lpbanks++; 379 } 380 bank[i] = bank[i] >> 10; 381 printf("%s bank[%d]: %ldK", i ? "," : "", i, bank[i]); 382 base += 4 * 1024 * 1024; 383 cnt = 0L; 384 ram = 0; 385 } 386 387 printf("\n"); 388 389 /* 390 * this is not really useful since GUS PnP supports memory 391 * configurations that aren't really supported by Interwave...beware 392 * of holes! Also, we don't use the memory for anything in this 393 * version of the driver. 394 * 395 * we've configured for 4M-4M-4M-4M 396 */ 397 } 398 399 400 static 401 void 402 iwreset(sc, warm) 403 struct iw_softc *sc; 404 int warm; 405 { 406 u_char reg, cmode, val = 0, mixer_image = 0; 407 408 reg = 0; /* XXX gcc -Wall */ 409 410 cmode = 0x6c; /* enhanced codec mode (full duplex) */ 411 412 /* reset */ 413 414 IW_WRITE_GENERAL_1(URSTI, 0x00); 415 delay(10); 416 IW_WRITE_GENERAL_1(URSTI, 0x07); 417 IW_WRITE_GENERAL_1(ICMPTI, 0x1f); /* disable DSP and uici and 418 * udci writes */ 419 IW_WRITE_GENERAL_1(IDECI, 0x7f); /* enable ints to ISA and 420 * codec access */ 421 IW_READ_GENERAL_1(IVERI, reg); 422 IW_WRITE_GENERAL_1(IVERI, reg | 0x01); /* hidden reg lock disable */ 423 IW_WRITE_GENERAL_1(UASBCI, 0x00); 424 425 /* synth enhanced mode (default), 0 active voices, disable ints */ 426 427 IW_WRITE_GENERAL_1(SGMI_WR, 0x01); /* enhanced mode, LFOs 428 * disabled */ 429 for (val = 0; val < 32; val++) { 430 /* set each synth sound volume to 0 */ 431 IW_WRITE_DIRECT_1(sc->p3xr + 2, sc->p3xr_h, val); 432 IW_WRITE_GENERAL_1(SVSI_WR, 0x00); 433 IW_WRITE_GENERAL_2(SASLI_WR, 0x0000); 434 IW_WRITE_GENERAL_2(SASHI_WR, 0x0000); 435 IW_WRITE_GENERAL_2(SAELI_WR, 0x0000); 436 IW_WRITE_GENERAL_2(SAEHI_WR, 0x0000); 437 IW_WRITE_GENERAL_2(SFCI_WR, 0x0000); 438 IW_WRITE_GENERAL_1(SACI_WR, 0x02); 439 IW_WRITE_GENERAL_1(SVSI_WR, 0x00); 440 IW_WRITE_GENERAL_1(SVEI_WR, 0x00); 441 IW_WRITE_GENERAL_2(SVLI_WR, 0x0000); 442 IW_WRITE_GENERAL_1(SVCI_WR, 0x02); 443 IW_WRITE_GENERAL_1(SMSI_WR, 0x02); 444 } 445 446 IW_WRITE_GENERAL_1(SAVI_WR, 0x00); 447 448 /* codec mode/init */ 449 450 /* first change mode to 1 */ 451 452 IW_WRITE_CODEC_1(CMODEI, 0x00); 453 454 /* and mode 3 */ 455 456 IW_WRITE_CODEC_1(CMODEI, cmode); 457 458 IW_READ_CODEC_1(CMODEI, reg); 459 460 DPRINTF(("cmode %x\n", reg)); 461 462 sc->revision = ((reg & 0x80) >> 3) | (reg & 0x0f); 463 464 IW_WRITE_DIRECT_1(sc->codec_index + 2, sc->p2xr_h, 0x00); 465 466 IW_WRITE_CODEC_1(CFIG1I | IW_MCE, 0x00); /* dma 2 chan access */ 467 IW_WRITE_CODEC_1(CEXTI, 0x00); /* disable ints for now */ 468 469 470 IW_WRITE_CODEC_1(CLPCTI, 0x00); /* reset playback sample counters */ 471 IW_WRITE_CODEC_1(CUPCTI, 0x00); /* always upper byte last */ 472 IW_WRITE_CODEC_1(CFIG2I, 0x80); /* full voltage range, enable record 473 * and playback sample counters, and 474 * don't center output in case or 475 * FIFO underrun */ 476 IW_WRITE_CODEC_1(CFIG3I, 0xc0); /* enable record/playback irq (still 477 * turned off from CEXTI), max dma 478 * rate */ 479 IW_WRITE_CODEC_1(CSR3I, 0x00); /* clear status 3 reg */ 480 481 482 IW_WRITE_CODEC_1(CLRCTI, 0x00); /* reset record sample counters */ 483 IW_WRITE_CODEC_1(CURCTI, 0x00); /* always upper byte last */ 484 485 486 IW_READ_GENERAL_1(IVERI, reg); 487 488 sc->vers = reg >> 4; 489 if (!warm) 490 sprintf(iw_device.version, "%d.%d", sc->vers, sc->revision); 491 492 IW_WRITE_GENERAL_1(IDECI, 0x7f); /* irqs and codec decode 493 * enable */ 494 495 496 /* ports */ 497 498 if (!warm) { 499 iw_mixer_line_level(sc, IW_LINE_OUT, 255, 255); 500 iw_mixer_line_level(sc, IW_LINE_IN, 0, 0); 501 iw_mixer_line_level(sc, IW_AUX1, 0, 0); 502 iw_mixer_line_level(sc, IW_AUX2, 200, 200); /* CD */ 503 sc->sc_dac.off = 0; 504 iw_mixer_line_level(sc, IW_DAC, 200, 200); 505 506 iw_mixer_line_level(sc, IW_MIC_IN, 0, 0); 507 iw_mixer_line_level(sc, IW_REC, 0, 0); 508 iw_mixer_line_level(sc, IW_LOOPBACK, 0, 0); 509 iw_mixer_line_level(sc, IW_MONO_IN, 0, 0); 510 511 /* mem stuff */ 512 iw_meminit(sc); 513 514 } 515 IW_WRITE_CODEC_1(CEXTI, 0x02); /* codec int enable */ 516 517 /* clear _LDMACI */ 518 519 IW_WRITE_GENERAL_1(LDMACI, 0x00); 520 521 /* enable mixer paths */ 522 mixer_image = 0x0c; 523 IW_WRITE_DIRECT_1(sc->p2xr, sc->p2xr_h, mixer_image); 524 /* 525 * enable output, line in. disable mic in bit 0 = 0 -> line in on 526 * (from codec?) bit 1 = 0 -> output on bit 2 = 1 -> mic in on bit 3 527 * = 1 -> irq&drq pin enable bit 4 = 1 -> channel interrupts to chan 528 * 1 bit 5 = 1 -> enable midi loop back bit 6 = 0 -> irq latches 529 * URCR[2:0] bit 6 = 1 -> dma latches URCR[2:0] 530 */ 531 532 533 IW_READ_DIRECT_1(sc->p2xr, sc->p2xr_h, mixer_image); 534 #ifdef AUDIO_DEBUG 535 if (!warm) 536 DPRINTF(("mix image %x \n", mixer_image)); 537 #endif 538 } 539 540 struct iw_codec_freq { 541 u_long freq; 542 u_char bits; 543 }; 544 545 int 546 iw_set_speed(sc, freq, in) 547 struct iw_softc *sc; 548 u_long freq; 549 char in; 550 { 551 u_char var, cfig3, reg; 552 553 static struct iw_codec_freq iw_cf[17] = { 554 #define FREQ_1 24576000 555 #define FREQ_2 16934400 556 #define XTAL1 0 557 #define XTAL2 1 558 {5510, 0x00 | XTAL2}, {6620, 0x0E | XTAL2}, 559 {8000, 0x00 | XTAL1}, {9600, 0x0E | XTAL1}, 560 {11025, 0x02 | XTAL2}, {16000, 0x02 | XTAL1}, 561 {18900, 0x04 | XTAL2}, {22050, 0x06 | XTAL2}, 562 {27420, 0x04 | XTAL1}, {32000, 0x06 | XTAL1}, 563 {33075, 0x0C | XTAL2}, {37800, 0x08 | XTAL2}, 564 {38400, 0x0A | XTAL1}, {44100, 0x0A | XTAL2}, 565 {44800, 0x08 | XTAL1}, {48000, 0x0C | XTAL1}, 566 {48000, 0x0C | XTAL1} /* really a dummy for indexing later */ 567 #undef XTAL1 568 #undef XTAL2 569 }; 570 571 cfig3 = 0; /* XXX gcc -Wall */ 572 573 /* 574 * if the frequency is between 3493Hz and 32KHz we can use a more 575 * accurate frequency than the ones listed above base on the formula 576 * FREQ/((16*(48+x))) where FREQ is either FREQ_1 (24576000Hz) or 577 * FREQ_2 (16934400Hz) and x is the value to be written to either 578 * CPVFI or CRVFI. To enable this option, bit 2 in CFIG3 needs to be 579 * set high 580 * 581 * NOT IMPLEMENTED! 582 * 583 * Note that if you have a 'bad' XTAL_1 (higher than 18.5 MHz), 44.8KHz 584 * and 38.4KHz modes will provide wrong frequencies to output. 585 */ 586 587 588 if (freq > 48000) 589 freq = 48000; 590 if (freq < 5510) 591 freq = 5510; 592 593 /* reset CFIG3[2] */ 594 595 IW_READ_CODEC_1(CFIG3I, cfig3); 596 597 cfig3 |= 0xc0; /* not full fifo treshhold */ 598 599 DPRINTF(("cfig3i = %x -> ", cfig3)); 600 601 cfig3 &= ~0x04; 602 IW_WRITE_CODEC_1(CFIG3I, cfig3); 603 IW_READ_CODEC_1(CFIG3I, cfig3); 604 605 DPRINTF(("%x\n", cfig3)); 606 607 for (var = 0; var < 16; var++) /* select closest frequency */ 608 if (freq <= iw_cf[var].freq) 609 break; 610 if (var != 16) 611 if (abs(freq - iw_cf[var].freq) > abs(iw_cf[var + 1].freq - freq)) 612 var++; 613 614 if (in) 615 IW_WRITE_CODEC_1(CRDFI | IW_MCE, sc->recfmtbits | iw_cf[var].bits); 616 else 617 IW_WRITE_CODEC_1(CPDFI | IW_MCE, sc->playfmtbits | iw_cf[var].bits); 618 freq = iw_cf[var].freq; 619 DPRINTF(("setting %s frequency to %d bits %x \n", 620 in ? "in" : "out", (int) freq, iw_cf[var].bits)); 621 622 IW_READ_CODEC_1(CPDFI, reg); 623 624 DPRINTF((" CPDFI %x ", reg)); 625 626 IW_READ_CODEC_1(CRDFI, reg); 627 628 DPRINTF((" CRDFI %x ", reg)); 629 630 return freq; 631 } 632 633 /* Encoding. */ 634 int 635 iw_query_encoding(addr, fp) 636 void *addr; 637 struct audio_encoding *fp; 638 { 639 /* 640 * LINEAR, ALAW, ULAW, ADPCM in HW, we'll use linear unsigned 641 * hardware mode for all 8-bit modes due to buggy (?) codec. 642 */ 643 644 /* 645 * except in wavetable synth. there we have only ulaw and 8 and 16 646 * bit linear data 647 */ 648 649 switch (fp->index) { 650 case 0: 651 strcpy(fp->name, AudioEulinear); 652 fp->encoding = AUDIO_ENCODING_ULINEAR_LE; 653 fp->precision = 8; 654 fp->flags = 0; 655 break; 656 case 1: 657 strcpy(fp->name, AudioEmulaw); 658 fp->encoding = AUDIO_ENCODING_ULAW; 659 fp->precision = 8; 660 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 661 break; 662 case 2: 663 strcpy(fp->name, AudioEalaw); 664 fp->encoding = AUDIO_ENCODING_ALAW; 665 fp->precision = 8; 666 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 667 break; 668 case 3: 669 strcpy(fp->name, AudioEadpcm); 670 fp->encoding = AUDIO_ENCODING_ADPCM; 671 fp->precision = 8; /* really 4 bit */ 672 fp->flags = 0; 673 break; 674 case 4: 675 strcpy(fp->name, AudioEslinear_le); 676 fp->encoding = AUDIO_ENCODING_SLINEAR_LE; 677 fp->precision = 16; 678 fp->flags = 0; 679 break; 680 case 5: 681 strcpy(fp->name, AudioEslinear_be); 682 fp->encoding = AUDIO_ENCODING_SLINEAR_BE; 683 fp->precision = 16; 684 fp->flags = 0; 685 break; 686 default: 687 return (EINVAL); 688 /* NOTREACHED */ 689 } 690 return (0); 691 } 692 693 694 695 u_long 696 iw_set_format(sc, precision, in) 697 struct iw_softc *sc; 698 u_long precision; 699 int in; 700 { 701 u_char data; 702 int encoding, channels; 703 704 encoding = in ? sc->rec_encoding : sc->play_encoding; 705 channels = in ? sc->rec_channels : sc->play_channels; 706 707 DPRINTF(("iw_set_format\n")); 708 709 switch (encoding) { 710 case AUDIO_ENCODING_ULAW: 711 data = 0x00; 712 break; 713 714 case AUDIO_ENCODING_ALAW: 715 data = 0x00; 716 break; 717 718 case AUDIO_ENCODING_SLINEAR_LE: 719 if (precision == 16) 720 data = 0x40; /* little endian. 0xc0 is big endian */ 721 else 722 data = 0x00; 723 break; 724 725 case AUDIO_ENCODING_SLINEAR_BE: 726 if (precision == 16) 727 data = 0xc0; 728 else 729 data = 0x00; 730 break; 731 732 case AUDIO_ENCODING_ADPCM: 733 data = 0xa0; 734 break; 735 736 default: 737 return -1; 738 } 739 740 if (channels == 2) 741 data |= 0x10; /* stereo */ 742 743 if (in) { 744 /* in */ 745 sc->recfmtbits = data; 746 /* This will zero the normal codec frequency, 747 * iw_set_speed should always be called afterwards. 748 */ 749 IW_WRITE_CODEC_1(CRDFI | IW_MCE, data); 750 } else { 751 /* out */ 752 sc->playfmtbits = data; 753 IW_WRITE_CODEC_1(CPDFI | IW_MCE, data); 754 } 755 756 DPRINTF(("formatbits %s %x", in ? "in" : "out", data)); 757 758 return encoding; 759 } 760 761 762 763 int 764 iw_set_params(addr, setmode, usemode, p, q) 765 void *addr; 766 int setmode; 767 int usemode; 768 struct audio_params *p; 769 struct audio_params *q; 770 { 771 struct iw_softc *sc = addr; 772 void (*swcode)__P((void *, u_char * buf, int cnt)) = NULL; 773 int factor = 1; 774 DPRINTF(("iw_setparams: code %d, prec %d, rate %d, chan %d\n", 775 (int) p->encoding, (int) p->precision, (int) p->sample_rate, 776 (int) p->channels)); 777 778 779 switch (p->encoding) { 780 case AUDIO_ENCODING_ULAW: 781 if (p->precision != 8) 782 return EINVAL; 783 swcode = setmode & AUMODE_PLAY ? mulaw_to_ulinear8 : ulinear8_to_mulaw; 784 factor = 1; 785 break; 786 case AUDIO_ENCODING_ALAW: 787 if (p->precision != 8) 788 return EINVAL; 789 swcode = setmode & AUMODE_PLAY ? alaw_to_ulinear8 : ulinear8_to_alaw; 790 factor = 1; 791 break; 792 case AUDIO_ENCODING_ADPCM: 793 if (p->precision != 8) 794 return EINVAL; 795 else 796 break; 797 798 case AUDIO_ENCODING_SLINEAR_LE: 799 case AUDIO_ENCODING_SLINEAR_BE: 800 if (p->precision != 8 && p->precision != 16) 801 return EINVAL; 802 else 803 break; 804 805 default: 806 return EINVAL; 807 808 } 809 810 if (setmode & AUMODE_PLAY) { 811 sc->play_channels = p->channels; 812 sc->play_encoding = p->encoding; 813 sc->play_precision = p->precision; 814 p->factor = factor; 815 p->sw_code = swcode; 816 iw_set_format(sc, p->precision, 0); 817 q->sample_rate = p->sample_rate = sc->sc_orate = 818 iw_set_speed(sc, p->sample_rate, 0); 819 } else { 820 #if 0 821 q->channels = sc->rec_channels = p->channels; 822 q->encoding = sc->rec_encoding = p->encoding; 823 q->precision = sc->rec_precision = p->precision; 824 #endif 825 sc->rec_channels = q->channels; 826 sc->rec_encoding = q->encoding; 827 sc->rec_precision = q->precision; 828 q->factor = factor; 829 q->sw_code = swcode; 830 831 iw_set_format(sc, p->precision, 1); 832 q->sample_rate = sc->sc_irate = 833 iw_set_speed(sc, q->sample_rate, 1); 834 } 835 return 0; 836 } 837 838 839 int 840 iw_round_blocksize(addr, blk) 841 void *addr; 842 int blk; 843 { 844 /* Round to a multiple of the biggest sample size. */ 845 return blk &= -4; 846 } 847 848 void 849 iw_mixer_line_level(sc, line, levl, levr) 850 struct iw_softc *sc; 851 int line; 852 int levl, levr; 853 { 854 u_char gainl, gainr, attenl, attenr; 855 856 switch (line) { 857 case IW_REC: 858 gainl = sc->sc_recsrcbits | (levl >> 4); 859 gainr = sc->sc_recsrcbits | (levr >> 4); 860 DPRINTF(("recording with %x", gainl)); 861 IW_WRITE_CODEC_1(CLICI, gainl); 862 IW_WRITE_CODEC_1(CRICI, gainr); 863 sc->sc_rec.voll = levl & 0xf0; 864 sc->sc_rec.volr = levr & 0xf0; 865 break; 866 867 case IW_AUX1: 868 869 gainl = (255 - levl) >> 3; 870 gainr = (255 - levr) >> 3; 871 872 /* mute if 0 level */ 873 if (levl == 0) 874 gainl |= 0x80; 875 if (levr == 0) 876 gainr |= 0x80; 877 878 IW_WRITE_CODEC_1(IW_LEFT_AUX1_PORT, gainl); 879 IW_WRITE_CODEC_1(IW_RIGHT_AUX1_PORT, gainr); 880 sc->sc_aux1.voll = levl & 0xf8; 881 sc->sc_aux1.volr = levr & 0xf8; 882 883 break; 884 885 case IW_AUX2: 886 887 gainl = (255 - levl) >> 3; 888 gainr = (255 - levr) >> 3; 889 890 /* mute if 0 level */ 891 if (levl == 0) 892 gainl |= 0x80; 893 if (levr == 0) 894 gainr |= 0x80; 895 896 IW_WRITE_CODEC_1(IW_LEFT_AUX2_PORT, gainl); 897 IW_WRITE_CODEC_1(IW_RIGHT_AUX2_PORT, gainr); 898 sc->sc_aux2.voll = levl & 0xf8; 899 sc->sc_aux2.volr = levr & 0xf8; 900 break; 901 case IW_DAC: 902 attenl = ((255 - levl) >> 2) | ((levl && !sc->sc_dac.off) ? 0 : 0x80); 903 attenr = ((255 - levr) >> 2) | ((levr && !sc->sc_dac.off) ? 0 : 0x80); 904 IW_WRITE_CODEC_1(CLDACI, attenl); 905 IW_WRITE_CODEC_1(CRDACI, attenr); 906 sc->sc_dac.voll = levl & 0xfc; 907 sc->sc_dac.volr = levr & 0xfc; 908 break; 909 case IW_LOOPBACK: 910 attenl = ((255 - levl) & 0xfc) | (levl ? 0x01 : 0); 911 IW_WRITE_CODEC_1(CLCI, attenl); 912 sc->sc_loopback.voll = levl & 0xfc; 913 break; 914 case IW_LINE_IN: 915 gainl = (levl >> 3) | (levl ? 0 : 0x80); 916 gainr = (levr >> 3) | (levr ? 0 : 0x80); 917 IW_WRITE_CODEC_1(CLLICI, gainl); 918 IW_WRITE_CODEC_1(CRLICI, gainr); 919 sc->sc_linein.voll = levl & 0xf8; 920 sc->sc_linein.volr = levr & 0xf8; 921 break; 922 case IW_MIC_IN: 923 gainl = ((255 - levl) >> 3) | (levl ? 0 : 0x80); 924 gainr = ((255 - levr) >> 3) | (levr ? 0 : 0x80); 925 IW_WRITE_CODEC_1(CLMICI, gainl); 926 IW_WRITE_CODEC_1(CRMICI, gainr); 927 sc->sc_mic.voll = levl & 0xf8; 928 sc->sc_mic.volr = levr & 0xf8; 929 break; 930 case IW_LINE_OUT: 931 attenl = ((255 - levl) >> 3) | (levl ? 0 : 0x80); 932 attenr = ((255 - levr) >> 3) | (levr ? 0 : 0x80); 933 IW_WRITE_CODEC_1(CLOAI, attenl); 934 IW_WRITE_CODEC_1(CROAI, attenr); 935 sc->sc_lineout.voll = levl & 0xf8; 936 sc->sc_lineout.volr = levr & 0xf8; 937 break; 938 case IW_MONO_IN: 939 attenl = ((255 - levl) >> 4) | (levl ? 0 : 0xc0); /* in/out mute */ 940 IW_WRITE_CODEC_1(CMONOI, attenl); 941 sc->sc_monoin.voll = levl & 0xf0; 942 break; 943 } 944 } 945 946 int 947 iw_commit_settings(addr) 948 void *addr; 949 { 950 return 0; 951 } 952 953 954 void 955 iw_trigger_dma(sc, io) 956 struct iw_softc *sc; 957 u_char io; 958 { 959 u_char reg; 960 int s; 961 962 s = splaudio(); 963 964 IW_READ_CODEC_1(CSR3I, reg); 965 IW_WRITE_CODEC_1(CSR3I, reg & ~(io == IW_DMA_PLAYBACK ? 0x10 : 0x20)); 966 967 IW_READ_CODEC_1(CFIG1I, reg); 968 969 IW_WRITE_CODEC_1(CFIG1I, reg | io); 970 971 /* let the counter run */ 972 IW_READ_CODEC_1(CFIG2I, reg); 973 IW_WRITE_CODEC_1(CFIG2I, reg & ~(io << 4)); 974 975 splx(s); 976 } 977 978 void 979 iw_stop_dma(sc, io, hard) 980 struct iw_softc *sc; 981 u_char io, hard; 982 { 983 u_char reg; 984 985 /* just stop the counter, no need to flush the fifo */ 986 IW_READ_CODEC_1(CFIG2I, reg); 987 IW_WRITE_CODEC_1(CFIG2I, (reg | (io << 4))); 988 989 if (hard) { 990 /* unless we're closing the device */ 991 IW_READ_CODEC_1(CFIG1I, reg); 992 IW_WRITE_CODEC_1(CFIG1I, reg & ~io); 993 } 994 } 995 996 void 997 iw_dma_count(sc, count, io) 998 struct iw_softc *sc; 999 u_short count; 1000 int io; 1001 { 1002 if (io == IW_DMA_PLAYBACK) { 1003 IW_WRITE_CODEC_1(CLPCTI, (u_char) (count & 0x00ff)); 1004 IW_WRITE_CODEC_1(CUPCTI, (u_char) ((count >> 8) & 0x00ff)); 1005 } else { 1006 IW_WRITE_CODEC_1(CLRCTI, (u_char) (count & 0x00ff)); 1007 IW_WRITE_CODEC_1(CURCTI, (u_char) ((count >> 8) & 0x00ff)); 1008 } 1009 } 1010 1011 int 1012 iw_init_output(addr, buf, cc) 1013 void *addr; 1014 void *buf; 1015 int cc; 1016 { 1017 struct iw_softc *sc = (struct iw_softc *) addr; 1018 1019 DPRINTF(("iw_init_output\n")); 1020 1021 isa_dmastart(sc->sc_ic, sc->sc_playdrq, buf, 1022 cc, NULL, DMAMODE_WRITE | DMAMODE_LOOP, BUS_DMA_NOWAIT); 1023 return 0; 1024 } 1025 1026 int 1027 iw_init_input(addr, buf, cc) 1028 void *addr; 1029 void *buf; 1030 int cc; 1031 { 1032 struct iw_softc *sc = (struct iw_softc *) addr; 1033 1034 DPRINTF(("iw_init_input\n")); 1035 1036 isa_dmastart(sc->sc_ic, sc->sc_recdrq, buf, 1037 cc, NULL, DMAMODE_READ | DMAMODE_LOOP, BUS_DMA_NOWAIT); 1038 return 0; 1039 } 1040 1041 1042 int 1043 iw_start_output(addr, p, cc, intr, arg) 1044 void *addr; 1045 void *p; 1046 int cc; 1047 void (*intr)__P((void *)); 1048 void *arg; 1049 { 1050 struct iw_softc *sc = addr; 1051 int counter; 1052 1053 #ifdef AUDIO_DEBUG 1054 if (sc->sc_playlocked) { 1055 DPRINTF(("iw_start_output: playback dma already going on\n")); 1056 /* return 0; */ 1057 } 1058 #endif 1059 1060 sc->sc_playlocked = 1; 1061 #ifdef DIAGNOSTIC 1062 if (!intr) { 1063 printf("iw_start_output: no callback!\n"); 1064 return 1; 1065 } 1066 #endif 1067 1068 sc->sc_playintr = intr; 1069 sc->sc_playarg = arg; 1070 sc->sc_dma_flags |= DMAMODE_WRITE; 1071 sc->sc_playdma_bp = p; 1072 1073 counter = 0; 1074 1075 isa_dmastart(sc->sc_ic, sc->sc_playdrq, sc->sc_playdma_bp, 1076 cc, NULL, DMAMODE_WRITE, BUS_DMA_NOWAIT); 1077 1078 1079 if (sc->play_encoding == AUDIO_ENCODING_ADPCM) 1080 cc >>= 2; 1081 if (sc->play_precision == 16) 1082 cc >>= 1; 1083 1084 if (sc->play_channels == 2 && sc->play_encoding != AUDIO_ENCODING_ADPCM) 1085 cc >>= 1; 1086 1087 cc -= iw_cc; 1088 1089 1090 /* iw_dma_access(sc,1); */ 1091 if (cc != sc->sc_playdma_cnt) { 1092 iw_dma_count(sc, (u_short) cc, IW_DMA_PLAYBACK); 1093 sc->sc_playdma_cnt = cc; 1094 1095 iw_trigger_dma(sc, IW_DMA_PLAYBACK); 1096 } 1097 1098 #ifdef DIAGNOSTIC 1099 if (outputs != iw_ints) 1100 printf("iw_start_output: out %d, int %d\n", outputs, iw_ints); 1101 outputs++; 1102 #endif 1103 return 0; 1104 } 1105 1106 1107 int 1108 iw_start_input(addr, p, cc, intr, arg) 1109 void *addr; 1110 void *p; 1111 int cc; 1112 void (*intr)__P((void *)); 1113 void *arg; 1114 { 1115 struct iw_softc *sc = addr; 1116 int counter; 1117 1118 #if AUDIO_DEBUG 1119 if (sc->sc_reclocked) { 1120 DPRINTF(("iw_start_input: record dma already going on\n")); 1121 /* return 0; */ 1122 } 1123 #endif 1124 1125 sc->sc_reclocked = 1; 1126 #ifdef DIAGNOSTIC 1127 if (!intr) { 1128 printf("iw_start_input: no callback!\n"); 1129 return 1; 1130 } 1131 #endif 1132 1133 1134 sc->sc_recintr = intr; 1135 sc->sc_recarg = arg; 1136 sc->sc_dma_flags |= DMAMODE_READ; 1137 sc->sc_recdma_bp = p; 1138 1139 counter = 0; 1140 1141 isa_dmastart(sc->sc_ic, sc->sc_recdrq, sc->sc_recdma_bp, 1142 cc, NULL, DMAMODE_READ, BUS_DMA_NOWAIT); 1143 1144 1145 if (sc->rec_encoding == AUDIO_ENCODING_ADPCM) 1146 cc >>= 2; 1147 if (sc->rec_precision == 16) 1148 cc >>= 1; 1149 1150 if (sc->rec_channels == 2 && sc->rec_encoding != AUDIO_ENCODING_ADPCM) 1151 cc >>= 1; 1152 1153 cc -= iw_cc; 1154 1155 /* iw_dma_access(sc,0); */ 1156 if (sc->sc_recdma_cnt != cc) { 1157 iw_dma_count(sc, (u_short) cc, IW_DMA_RECORD); 1158 sc->sc_recdma_cnt = cc; 1159 /* iw_dma_ctrl(sc, IW_DMA_RECORD); */ 1160 iw_trigger_dma(sc, IW_DMA_RECORD); 1161 } 1162 1163 #ifdef DIAGNOSTIC 1164 if ((inputs != iw_inints)) 1165 printf("iw_start_input: in %d, inints %d\n", inputs, iw_inints); 1166 inputs++; 1167 #endif 1168 1169 return 0; 1170 } 1171 1172 1173 int 1174 iw_halt_output(addr) 1175 void *addr; 1176 { 1177 struct iw_softc *sc = addr; 1178 iw_stop_dma(sc, IW_DMA_PLAYBACK, 0); 1179 /* sc->sc_playlocked = 0; */ 1180 return 0; 1181 } 1182 1183 1184 int 1185 iw_halt_input(addr) 1186 void *addr; 1187 { 1188 struct iw_softc *sc = addr; 1189 iw_stop_dma(sc, IW_DMA_RECORD, 0); 1190 /* sc->sc_reclocked = 0; */ 1191 return 0; 1192 } 1193 1194 1195 int 1196 iw_speaker_ctl(addr, newstate) 1197 void *addr; 1198 int newstate; 1199 { 1200 struct iw_softc *sc = addr; 1201 u_char reg; 1202 if (newstate == SPKR_ON) { 1203 sc->sc_dac.off = 0; 1204 IW_READ_CODEC_1(CLDACI, reg); 1205 IW_WRITE_CODEC_1(CLDACI, reg & 0x7f); 1206 IW_READ_CODEC_1(CRDACI, reg); 1207 IW_WRITE_CODEC_1(CRDACI, reg & 0x7f); 1208 } else { 1209 /* SPKR_OFF */ 1210 sc->sc_dac.off = 1; 1211 IW_READ_CODEC_1(CLDACI, reg); 1212 IW_WRITE_CODEC_1(CLDACI, reg | 0x80); 1213 IW_READ_CODEC_1(CRDACI, reg); 1214 IW_WRITE_CODEC_1(CRDACI, reg | 0x80); 1215 } 1216 return 0; 1217 } 1218 1219 1220 int 1221 iw_getdev(addr, retp) 1222 void *addr; 1223 struct audio_device *retp; 1224 { 1225 *retp = iw_device; 1226 return 0; 1227 } 1228 1229 1230 int 1231 iw_setfd(addr, flag) 1232 void *addr; 1233 int flag; 1234 { 1235 return 0; 1236 } 1237 1238 1239 /* Mixer (in/out ports) */ 1240 int 1241 iw_set_port(addr, cp) 1242 void *addr; 1243 mixer_ctrl_t *cp; 1244 { 1245 struct iw_softc *sc = addr; 1246 u_char vall = 0, valr = 0; 1247 int error = EINVAL; 1248 1249 switch (cp->dev) { 1250 case IW_MIC_IN_LVL: 1251 if (cp->type == AUDIO_MIXER_VALUE) { 1252 error = 0; 1253 if (cp->un.value.num_channels == 1) { 1254 vall = valr = cp->un.value.level[0]; 1255 } else { 1256 vall = cp->un.value.level[0]; 1257 valr = cp->un.value.level[1]; 1258 } 1259 sc->sc_mic.voll = vall; 1260 sc->sc_mic.volr = valr; 1261 iw_mixer_line_level(sc, IW_MIC_IN, vall, valr); 1262 } 1263 break; 1264 case IW_AUX1_LVL: 1265 if (cp->type == AUDIO_MIXER_VALUE) { 1266 error = 0; 1267 if (cp->un.value.num_channels == 1) { 1268 vall = valr = cp->un.value.level[0]; 1269 } else { 1270 vall = cp->un.value.level[0]; 1271 valr = cp->un.value.level[1]; 1272 } 1273 sc->sc_aux1.voll = vall; 1274 sc->sc_aux1.volr = valr; 1275 iw_mixer_line_level(sc, IW_AUX1, vall, valr); 1276 } 1277 break; 1278 case IW_AUX2_LVL: 1279 if (cp->type == AUDIO_MIXER_VALUE) { 1280 error = 0; 1281 if (cp->un.value.num_channels == 1) { 1282 vall = valr = cp->un.value.level[0]; 1283 } else { 1284 vall = cp->un.value.level[0]; 1285 valr = cp->un.value.level[1]; 1286 } 1287 sc->sc_aux2.voll = vall; 1288 sc->sc_aux2.volr = valr; 1289 iw_mixer_line_level(sc, IW_AUX2, vall, valr); 1290 } 1291 break; 1292 case IW_LINE_IN_LVL: 1293 if (cp->type == AUDIO_MIXER_VALUE) { 1294 error = 0; 1295 if (cp->un.value.num_channels == 1) { 1296 vall = valr = cp->un.value.level[0]; 1297 } else { 1298 vall = cp->un.value.level[0]; 1299 valr = cp->un.value.level[1]; 1300 } 1301 sc->sc_linein.voll = vall; 1302 sc->sc_linein.volr = valr; 1303 iw_mixer_line_level(sc, IW_LINE_IN, vall, valr); 1304 } 1305 break; 1306 case IW_LINE_OUT_LVL: 1307 if (cp->type == AUDIO_MIXER_VALUE) { 1308 error = 0; 1309 if (cp->un.value.num_channels == 1) { 1310 vall = valr = cp->un.value.level[0]; 1311 } else { 1312 vall = cp->un.value.level[0]; 1313 valr = cp->un.value.level[1]; 1314 } 1315 sc->sc_lineout.voll = vall; 1316 sc->sc_lineout.volr = valr; 1317 iw_mixer_line_level(sc, IW_LINE_OUT, vall, valr); 1318 } 1319 break; 1320 case IW_REC_LVL: 1321 if (cp->type == AUDIO_MIXER_VALUE) { 1322 error = 0; 1323 if (cp->un.value.num_channels == 1) { 1324 vall = valr = cp->un.value.level[0]; 1325 } else { 1326 vall = cp->un.value.level[0]; 1327 valr = cp->un.value.level[1]; 1328 } 1329 sc->sc_rec.voll = vall; 1330 sc->sc_rec.volr = valr; 1331 iw_mixer_line_level(sc, IW_REC, vall, valr); 1332 } 1333 break; 1334 1335 case IW_DAC_LVL: 1336 if (cp->type == AUDIO_MIXER_VALUE) { 1337 error = 0; 1338 if (cp->un.value.num_channels == 1) { 1339 vall = valr = cp->un.value.level[0]; 1340 } else { 1341 vall = cp->un.value.level[0]; 1342 valr = cp->un.value.level[1]; 1343 } 1344 sc->sc_dac.voll = vall; 1345 sc->sc_dac.volr = valr; 1346 iw_mixer_line_level(sc, IW_DAC, vall, valr); 1347 } 1348 break; 1349 1350 case IW_LOOPBACK_LVL: 1351 if (cp->type == AUDIO_MIXER_VALUE) { 1352 error = 0; 1353 if (cp->un.value.num_channels != 1) { 1354 return EINVAL; 1355 } else { 1356 valr = vall = cp->un.value.level[0]; 1357 } 1358 sc->sc_loopback.voll = vall; 1359 sc->sc_loopback.volr = valr; 1360 iw_mixer_line_level(sc, IW_LOOPBACK, vall, valr); 1361 } 1362 break; 1363 1364 case IW_MONO_IN_LVL: 1365 if (cp->type == AUDIO_MIXER_VALUE) { 1366 error = 0; 1367 if (cp->un.value.num_channels != 1) { 1368 return EINVAL; 1369 } else { 1370 valr = vall = cp->un.value.level[0]; 1371 } 1372 sc->sc_monoin.voll = vall; 1373 sc->sc_monoin.volr = valr; 1374 iw_mixer_line_level(sc, IW_MONO_IN, vall, valr); 1375 } 1376 break; 1377 case IW_RECORD_SOURCE: 1378 error = 0; 1379 sc->sc_recsrcbits = cp->un.ord << 6; 1380 DPRINTF(("record source %d bits %x\n", cp->un.ord, sc->sc_recsrcbits)); 1381 iw_mixer_line_level(sc, IW_REC, sc->sc_rec.voll, sc->sc_rec.volr); 1382 break; 1383 } 1384 1385 return error; 1386 } 1387 1388 1389 int 1390 iw_get_port(addr, cp) 1391 void *addr; 1392 mixer_ctrl_t *cp; 1393 { 1394 struct iw_softc *sc = addr; 1395 1396 int error = EINVAL; 1397 1398 switch (cp->dev) { 1399 case IW_MIC_IN_LVL: 1400 if (cp->type == AUDIO_MIXER_VALUE) { 1401 cp->un.value.num_channels = 2; 1402 cp->un.value.level[0] = sc->sc_mic.voll; 1403 cp->un.value.level[1] = sc->sc_mic.volr; 1404 error = 0; 1405 } 1406 break; 1407 case IW_AUX1_LVL: 1408 if (cp->type == AUDIO_MIXER_VALUE) { 1409 cp->un.value.num_channels = 2; 1410 cp->un.value.level[0] = sc->sc_aux1.voll; 1411 cp->un.value.level[1] = sc->sc_aux1.volr; 1412 error = 0; 1413 } 1414 break; 1415 case IW_AUX2_LVL: 1416 if (cp->type == AUDIO_MIXER_VALUE) { 1417 cp->un.value.num_channels = 2; 1418 cp->un.value.level[0] = sc->sc_aux2.voll; 1419 cp->un.value.level[1] = sc->sc_aux2.volr; 1420 error = 0; 1421 } 1422 break; 1423 case IW_LINE_OUT_LVL: 1424 if (cp->type == AUDIO_MIXER_VALUE) { 1425 cp->un.value.num_channels = 2; 1426 cp->un.value.level[0] = sc->sc_lineout.voll; 1427 cp->un.value.level[1] = sc->sc_lineout.volr; 1428 error = 0; 1429 } 1430 break; 1431 case IW_LINE_IN_LVL: 1432 if (cp->type == AUDIO_MIXER_VALUE) { 1433 cp->un.value.num_channels = 2; 1434 cp->un.value.level[0] = sc->sc_linein.voll; 1435 cp->un.value.level[1] = sc->sc_linein.volr; 1436 error = 0; 1437 } 1438 case IW_REC_LVL: 1439 if (cp->type == AUDIO_MIXER_VALUE) { 1440 cp->un.value.num_channels = 2; 1441 cp->un.value.level[0] = sc->sc_rec.voll; 1442 cp->un.value.level[1] = sc->sc_rec.volr; 1443 error = 0; 1444 } 1445 break; 1446 1447 case IW_DAC_LVL: 1448 if (cp->type == AUDIO_MIXER_VALUE) { 1449 cp->un.value.num_channels = 2; 1450 cp->un.value.level[0] = sc->sc_dac.voll; 1451 cp->un.value.level[1] = sc->sc_dac.volr; 1452 error = 0; 1453 } 1454 break; 1455 1456 case IW_LOOPBACK_LVL: 1457 if (cp->type == AUDIO_MIXER_VALUE) { 1458 cp->un.value.num_channels = 1; 1459 cp->un.value.level[0] = sc->sc_loopback.voll; 1460 error = 0; 1461 } 1462 break; 1463 1464 case IW_MONO_IN_LVL: 1465 if (cp->type == AUDIO_MIXER_VALUE) { 1466 cp->un.value.num_channels = 1; 1467 cp->un.value.level[0] = sc->sc_monoin.voll; 1468 error = 0; 1469 } 1470 break; 1471 case IW_RECORD_SOURCE: 1472 cp->un.ord = sc->sc_recsrcbits >> 6; 1473 error = 0; 1474 break; 1475 } 1476 1477 return error; 1478 } 1479 1480 1481 1482 int 1483 iw_query_devinfo(addr, dip) 1484 void *addr; 1485 mixer_devinfo_t *dip; 1486 { 1487 1488 switch (dip->index) { 1489 case IW_MIC_IN_LVL: /* Microphone */ 1490 dip->type = AUDIO_MIXER_VALUE; 1491 dip->mixer_class = IW_INPUT_CLASS; 1492 dip->prev = AUDIO_MIXER_LAST; 1493 dip->next = AUDIO_MIXER_LAST; 1494 strcpy(dip->label.name, AudioNmicrophone); 1495 dip->un.v.num_channels = 2; 1496 strcpy(dip->un.v.units.name, AudioNvolume); 1497 break; 1498 case IW_AUX1_LVL: 1499 dip->type = AUDIO_MIXER_VALUE; 1500 dip->mixer_class = IW_INPUT_CLASS; 1501 dip->prev = AUDIO_MIXER_LAST; 1502 dip->next = AUDIO_MIXER_LAST; 1503 strcpy(dip->label.name, AudioNline); 1504 dip->un.v.num_channels = 2; 1505 strcpy(dip->un.v.units.name, AudioNvolume); 1506 break; 1507 case IW_AUX2_LVL: 1508 dip->type = AUDIO_MIXER_VALUE; 1509 dip->mixer_class = IW_INPUT_CLASS; 1510 dip->prev = AUDIO_MIXER_LAST; 1511 dip->next = AUDIO_MIXER_LAST; 1512 strcpy(dip->label.name, AudioNcd); 1513 dip->un.v.num_channels = 2; 1514 strcpy(dip->un.v.units.name, AudioNvolume); 1515 break; 1516 case IW_LINE_OUT_LVL: 1517 dip->type = AUDIO_MIXER_VALUE; 1518 dip->mixer_class = IW_OUTPUT_CLASS; 1519 dip->prev = AUDIO_MIXER_LAST; 1520 dip->next = AUDIO_MIXER_LAST; 1521 strcpy(dip->label.name, AudioNline); 1522 dip->un.v.num_channels = 2; 1523 strcpy(dip->un.v.units.name, AudioNvolume); 1524 break; 1525 case IW_DAC_LVL: 1526 dip->type = AUDIO_MIXER_VALUE; 1527 dip->mixer_class = IW_OUTPUT_CLASS; 1528 dip->prev = AUDIO_MIXER_LAST; 1529 dip->next = AUDIO_MIXER_LAST; 1530 strcpy(dip->label.name, AudioNdac); 1531 dip->un.v.num_channels = 2; 1532 strcpy(dip->un.v.units.name, AudioNvolume); 1533 break; 1534 case IW_LINE_IN_LVL: 1535 dip->type = AUDIO_MIXER_VALUE; 1536 dip->mixer_class = IW_INPUT_CLASS; 1537 dip->prev = AUDIO_MIXER_LAST; 1538 dip->next = AUDIO_MIXER_LAST; 1539 strcpy(dip->label.name, AudioNinput); 1540 dip->un.v.num_channels = 2; 1541 strcpy(dip->un.v.units.name, AudioNvolume); 1542 break; 1543 case IW_MONO_IN_LVL: 1544 dip->type = AUDIO_MIXER_VALUE; 1545 dip->mixer_class = IW_INPUT_CLASS; 1546 dip->prev = AUDIO_MIXER_LAST; 1547 dip->next = AUDIO_MIXER_LAST; 1548 strcpy(dip->label.name, AudioNmono); 1549 dip->un.v.num_channels = 1; 1550 strcpy(dip->un.v.units.name, AudioNvolume); 1551 break; 1552 1553 case IW_REC_LVL: /* record level */ 1554 dip->type = AUDIO_MIXER_VALUE; 1555 dip->mixer_class = IW_RECORD_CLASS; 1556 dip->prev = AUDIO_MIXER_LAST; 1557 dip->next = AUDIO_MIXER_LAST; 1558 strcpy(dip->label.name, AudioNrecord); 1559 dip->un.v.num_channels = 2; 1560 strcpy(dip->un.v.units.name, AudioNvolume); 1561 break; 1562 1563 case IW_LOOPBACK_LVL: 1564 dip->type = AUDIO_MIXER_VALUE; 1565 dip->mixer_class = IW_RECORD_CLASS; 1566 dip->prev = AUDIO_MIXER_LAST; 1567 dip->next = AUDIO_MIXER_LAST; 1568 strcpy(dip->label.name, "filter"); 1569 dip->un.v.num_channels = 1; 1570 strcpy(dip->un.v.units.name, AudioNvolume); 1571 break; 1572 1573 case IW_RECORD_SOURCE: 1574 dip->mixer_class = IW_RECORD_CLASS; 1575 dip->type = AUDIO_MIXER_ENUM; 1576 dip->prev = AUDIO_MIXER_LAST; 1577 dip->next = AUDIO_MIXER_LAST; 1578 strcpy(dip->label.name, AudioNsource); 1579 dip->un.e.num_mem = 4; 1580 strcpy(dip->un.e.member[0].label.name, AudioNline); 1581 dip->un.e.member[0].ord = IW_LINE_IN_SRC; 1582 strcpy(dip->un.e.member[1].label.name, "aux1"); 1583 dip->un.e.member[1].ord = IW_AUX1_SRC; 1584 strcpy(dip->un.e.member[2].label.name, AudioNmicrophone); 1585 dip->un.e.member[2].ord = IW_MIC_IN_SRC; 1586 strcpy(dip->un.e.member[3].label.name, AudioNmixerout); 1587 dip->un.e.member[3].ord = IW_MIX_OUT_SRC; 1588 break; 1589 case IW_INPUT_CLASS: 1590 dip->type = AUDIO_MIXER_CLASS; 1591 dip->mixer_class = IW_INPUT_CLASS; 1592 dip->next = dip->prev = AUDIO_MIXER_LAST; 1593 strcpy(dip->label.name, AudioCinputs); 1594 break; 1595 case IW_OUTPUT_CLASS: 1596 dip->type = AUDIO_MIXER_CLASS; 1597 dip->mixer_class = IW_OUTPUT_CLASS; 1598 dip->next = dip->prev = AUDIO_MIXER_LAST; 1599 strcpy(dip->label.name, AudioCoutputs); 1600 break; 1601 case IW_RECORD_CLASS: /* record source class */ 1602 dip->type = AUDIO_MIXER_CLASS; 1603 dip->mixer_class = IW_RECORD_CLASS; 1604 dip->next = dip->prev = AUDIO_MIXER_LAST; 1605 strcpy(dip->label.name, AudioCrecord); 1606 return 0; 1607 default: 1608 return ENXIO; 1609 } 1610 return 0; 1611 } 1612 1613 1614 void * 1615 iw_malloc(addr, direction, size, pool, flags) 1616 void *addr; 1617 int direction; 1618 size_t size; 1619 int pool, flags; 1620 { 1621 struct iw_softc *sc = addr; 1622 int drq; 1623 1624 if (direction == AUMODE_PLAY) 1625 drq = sc->sc_playdrq; 1626 else 1627 drq = sc->sc_recdrq; 1628 return (isa_malloc(sc->sc_ic, drq, size, pool, flags)); 1629 } 1630 1631 void 1632 iw_free(addr, ptr, pool) 1633 void *addr; 1634 void *ptr; 1635 int pool; 1636 { 1637 isa_free(ptr, pool); 1638 } 1639 1640 size_t 1641 iw_round_buffersize(addr, direction, size) 1642 void *addr; 1643 int direction; 1644 size_t size; 1645 { 1646 struct iw_softc *sc = addr; 1647 bus_size_t maxsize; 1648 1649 if (direction == AUMODE_PLAY) 1650 maxsize = sc->sc_play_maxsize; 1651 else 1652 maxsize = sc->sc_rec_maxsize; 1653 1654 if (size > maxsize) 1655 size = maxsize; 1656 return (size); 1657 } 1658 1659 paddr_t 1660 iw_mappage(addr, mem, off, prot) 1661 void *addr; 1662 void *mem; 1663 off_t off; 1664 int prot; 1665 { 1666 return isa_mappage(mem, off, prot); 1667 } 1668 1669 int 1670 iw_get_props(addr) 1671 void *addr; 1672 { 1673 struct iw_softc *sc = addr; 1674 return AUDIO_PROP_MMAP | 1675 (sc->sc_fullduplex ? AUDIO_PROP_FULLDUPLEX : 0); 1676 } 1677