1 /* $NetBSD: eap.c,v 1.25 1999/02/18 07:59:30 mycroft Exp $ */ 2 3 /* 4 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Lennart Augustsson <augustss@netbsd.org> and Charles M. Hannum. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Debugging: Andreas Gustafsson <gson@araneus.fi> 41 * Testing: Chuck Cranor <chuck@maria.wustl.edu> 42 * Phil Nelson <phil@cs.wwu.edu> 43 */ 44 45 /* 46 * Ensoniq AudoiPCI ES1370 + AK4531 driver. 47 * Data sheets can be found at 48 * http://www.ensoniq.com/multimedia/semi_html/html/es1370.zip 49 * and 50 * http://206.214.38.151/pdf/4531.pdf 51 */ 52 53 #include <sys/param.h> 54 #include <sys/systm.h> 55 #include <sys/kernel.h> 56 #include <sys/malloc.h> 57 #include <sys/device.h> 58 59 #include <dev/pci/pcidevs.h> 60 #include <dev/pci/pcivar.h> 61 62 #include <sys/audioio.h> 63 #include <dev/audio_if.h> 64 #include <dev/mulaw.h> 65 #include <dev/auconv.h> 66 67 #include <machine/bus.h> 68 69 #define PCI_CBIO 0x10 70 71 #define EAP_ICSC 0x00 /* interrupt / chip select control */ 72 #define EAP_SERR_DISABLE 0x00000001 73 #define EAP_CDC_EN 0x00000002 74 #define EAP_JYSTK_EN 0x00000004 75 #define EAP_UART_EN 0x00000008 76 #define EAP_ADC_EN 0x00000010 77 #define EAP_DAC2_EN 0x00000020 78 #define EAP_DAC1_EN 0x00000040 79 #define EAP_BREQ 0x00000080 80 #define EAP_XTCL0 0x00000100 81 #define EAP_M_CB 0x00000200 82 #define EAP_CCB_INTRM 0x00000400 83 #define EAP_DAC_SYNC 0x00000800 84 #define EAP_WTSRSEL 0x00003000 85 #define EAP_WTSRSEL_5 0x00000000 86 #define EAP_WTSRSEL_11 0x00001000 87 #define EAP_WTSRSEL_22 0x00002000 88 #define EAP_WTSRSEL_44 0x00003000 89 #define EAP_M_SBB 0x00004000 90 #define EAP_MSFMTSEL 0x00008000 91 #define EAP_SET_PCLKDIV(n) (((n)&0x1fff)<<16) 92 #define EAP_GET_PCLKDIV(n) (((n)>>16)&0x1fff) 93 #define EAP_PCLKBITS 0x1fff0000 94 #define EAP_XTCL1 0x40000000 95 #define EAP_ADC_STOP 0x80000000 96 97 #define EAP_ICSS 0x04 /* interrupt / chip select status */ 98 #define EAP_I_ADC 0x00000001 99 #define EAP_I_DAC2 0x00000002 100 #define EAP_I_DAC1 0x00000004 101 #define EAP_I_UART 0x00000008 102 #define EAP_I_MCCB 0x00000010 103 #define EAP_VC 0x00000060 104 #define EAP_CWRIP 0x00000100 105 #define EAP_CBUSY 0x00000200 106 #define EAP_CSTAT 0x00000400 107 #define EAP_INTR 0x80000000 108 109 #define EAP_UART_DATA 0x08 110 #define EAP_UART_STATUS 0x09 111 #define EAP_UART_CONTROL 0x09 112 #define EAP_MEMPAGE 0x0c 113 #define EAP_CODEC 0x10 114 #define EAP_SET_CODEC(a,d) (((a)<<8) | (d)) 115 116 #define EAP_SIC 0x20 117 #define EAP_P1_S_MB 0x00000001 118 #define EAP_P1_S_EB 0x00000002 119 #define EAP_P2_S_MB 0x00000004 120 #define EAP_P2_S_EB 0x00000008 121 #define EAP_R1_S_MB 0x00000010 122 #define EAP_R1_S_EB 0x00000020 123 #define EAP_P2_DAC_SEN 0x00000040 124 #define EAP_P1_SCT_RLD 0x00000080 125 #define EAP_P1_INTR_EN 0x00000100 126 #define EAP_P2_INTR_EN 0x00000200 127 #define EAP_R1_INTR_EN 0x00000400 128 #define EAP_P1_PAUSE 0x00000800 129 #define EAP_P2_PAUSE 0x00001000 130 #define EAP_P1_LOOP_SEL 0x00002000 131 #define EAP_P2_LOOP_SEL 0x00004000 132 #define EAP_R1_LOOP_SEL 0x00008000 133 #define EAP_SET_P2_ST_INC(i) ((i) << 16) 134 #define EAP_SET_P2_END_INC(i) ((i) << 19) 135 #define EAP_INC_BITS 0x003f0000 136 137 #define EAP_DAC1_CSR 0x24 138 #define EAP_DAC2_CSR 0x28 139 #define EAP_ADC_CSR 0x2c 140 #define EAP_GET_CURRSAMP(r) ((r) >> 16) 141 142 #define EAP_DAC_PAGE 0xc 143 #define EAP_ADC_PAGE 0xd 144 #define EAP_UART_PAGE1 0xe 145 #define EAP_UART_PAGE2 0xf 146 147 #define EAP_DAC1_ADDR 0x30 148 #define EAP_DAC1_SIZE 0x34 149 #define EAP_DAC2_ADDR 0x38 150 #define EAP_DAC2_SIZE 0x3c 151 #define EAP_ADC_ADDR 0x30 152 #define EAP_ADC_SIZE 0x34 153 #define EAP_SET_SIZE(c,s) (((c)<<16) | (s)) 154 155 #define EAP_XTAL_FREQ 1411200 /* 22.5792 / 16 MHz */ 156 157 /* AK4531 registers */ 158 #define AK_MASTER_L 0x00 159 #define AK_MASTER_R 0x01 160 #define AK_VOICE_L 0x02 161 #define AK_VOICE_R 0x03 162 #define AK_FM_L 0x04 163 #define AK_FM_R 0x05 164 #define AK_CD_L 0x06 165 #define AK_CD_R 0x07 166 #define AK_LINE_L 0x08 167 #define AK_LINE_R 0x09 168 #define AK_AUX_L 0x0a 169 #define AK_AUX_R 0x0b 170 #define AK_MONO1 0x0c 171 #define AK_MONO2 0x0d 172 #define AK_MIC 0x0e 173 #define AK_MONO 0x0f 174 #define AK_OUT_MIXER1 0x10 175 #define AK_M_FM_L 0x40 176 #define AK_M_FM_R 0x20 177 #define AK_M_LINE_L 0x10 178 #define AK_M_LINE_R 0x08 179 #define AK_M_CD_L 0x04 180 #define AK_M_CD_R 0x02 181 #define AK_M_MIC 0x01 182 #define AK_OUT_MIXER2 0x11 183 #define AK_M_AUX_L 0x20 184 #define AK_M_AUX_R 0x10 185 #define AK_M_VOICE_L 0x08 186 #define AK_M_VOICE_R 0x04 187 #define AK_M_MONO2 0x02 188 #define AK_M_MONO1 0x01 189 #define AK_IN_MIXER1_L 0x12 190 #define AK_IN_MIXER1_R 0x13 191 #define AK_IN_MIXER2_L 0x14 192 #define AK_IN_MIXER2_R 0x15 193 #define AK_M_TMIC 0x80 194 #define AK_M_TMONO1 0x40 195 #define AK_M_TMONO2 0x20 196 #define AK_M2_AUX_L 0x10 197 #define AK_M2_AUX_R 0x08 198 #define AK_M_VOICE 0x04 199 #define AK_M2_MONO2 0x02 200 #define AK_M2_MONO1 0x01 201 #define AK_RESET 0x16 202 #define AK_PD 0x02 203 #define AK_NRST 0x01 204 #define AK_CS 0x17 205 #define AK_ADSEL 0x18 206 #define AK_MGAIN 0x19 207 208 #define AK_NPORTS 16 209 210 #define VOL_TO_ATT5(v) (0x1f - ((v) >> 3)) 211 #define VOL_TO_GAIN5(v) VOL_TO_ATT5(v) 212 #define ATT5_TO_VOL(v) ((0x1f - (v)) << 3) 213 #define GAIN5_TO_VOL(v) ATT5_TO_VOL(v) 214 #define VOL_0DB 200 215 216 #define EAP_MASTER_VOL 0 217 #define EAP_VOICE_VOL 1 218 #define EAP_FM_VOL 2 219 #define EAP_CD_VOL 3 220 #define EAP_LINE_VOL 4 221 #define EAP_AUX_VOL 5 222 #define EAP_MIC_VOL 6 223 #define EAP_RECORD_SOURCE 7 224 #define EAP_OUTPUT_SELECT 8 225 #define EAP_MIC_PREAMP 9 226 #define EAP_OUTPUT_CLASS 10 227 #define EAP_RECORD_CLASS 11 228 #define EAP_INPUT_CLASS 12 229 230 #ifdef AUDIO_DEBUG 231 #define DPRINTF(x) if (eapdebug) printf x 232 #define DPRINTFN(n,x) if (eapdebug>(n)) printf x 233 int eapdebug = 0; 234 #else 235 #define DPRINTF(x) 236 #define DPRINTFN(n,x) 237 #endif 238 239 int eap_match __P((struct device *, struct cfdata *, void *)); 240 void eap_attach __P((struct device *, struct device *, void *)); 241 int eap_intr __P((void *)); 242 243 struct eap_dma { 244 bus_dmamap_t map; 245 caddr_t addr; 246 bus_dma_segment_t segs[1]; 247 int nsegs; 248 size_t size; 249 struct eap_dma *next; 250 }; 251 #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr) 252 #define KERNADDR(p) ((void *)((p)->addr)) 253 254 struct eap_softc { 255 struct device sc_dev; /* base device */ 256 void *sc_ih; /* interrupt vectoring */ 257 bus_space_tag_t iot; 258 bus_space_handle_t ioh; 259 bus_dma_tag_t sc_dmatag; /* DMA tag */ 260 261 struct eap_dma *sc_dmas; 262 263 void (*sc_pintr)(void *); /* dma completion intr handler */ 264 void *sc_parg; /* arg for sc_intr() */ 265 #ifdef DIAGNOSTIC 266 char sc_prun; 267 #endif 268 269 void (*sc_rintr)(void *); /* dma completion intr handler */ 270 void *sc_rarg; /* arg for sc_intr() */ 271 #ifdef DIAGNOSTIC 272 char sc_rrun; 273 #endif 274 275 u_char sc_port[AK_NPORTS]; /* mirror of the hardware setting */ 276 u_int sc_record_source; /* recording source mask */ 277 u_int sc_output_source; /* output source mask */ 278 u_int sc_mic_preamp; 279 }; 280 281 int eap_allocmem __P((struct eap_softc *, size_t, size_t, struct eap_dma *)); 282 int eap_freemem __P((struct eap_softc *, struct eap_dma *)); 283 284 #define EWRITE2(sc, r, x) bus_space_write_2((sc)->iot, (sc)->ioh, (r), (x)) 285 #define EWRITE4(sc, r, x) bus_space_write_4((sc)->iot, (sc)->ioh, (r), (x)) 286 #define EREAD2(sc, r) bus_space_read_2((sc)->iot, (sc)->ioh, (r)) 287 #define EREAD4(sc, r) bus_space_read_4((sc)->iot, (sc)->ioh, (r)) 288 289 struct cfattach eap_ca = { 290 sizeof(struct eap_softc), eap_match, eap_attach 291 }; 292 293 int eap_open __P((void *, int)); 294 void eap_close __P((void *)); 295 int eap_query_encoding __P((void *, struct audio_encoding *)); 296 int eap_set_params __P((void *, int, int, struct audio_params *, struct audio_params *)); 297 int eap_round_blocksize __P((void *, int)); 298 int eap_trigger_output __P((void *, void *, void *, int, void (*)(void *), 299 void *, struct audio_params *)); 300 int eap_trigger_input __P((void *, void *, void *, int, void (*)(void *), 301 void *, struct audio_params *)); 302 int eap_halt_output __P((void *)); 303 int eap_halt_input __P((void *)); 304 int eap_getdev __P((void *, struct audio_device *)); 305 int eap_mixer_set_port __P((void *, mixer_ctrl_t *)); 306 int eap_mixer_get_port __P((void *, mixer_ctrl_t *)); 307 int eap_query_devinfo __P((void *, mixer_devinfo_t *)); 308 void *eap_malloc __P((void *, int, size_t, int, int)); 309 void eap_free __P((void *, void *, int)); 310 size_t eap_round_buffersize __P((void *, int, size_t)); 311 int eap_mappage __P((void *, void *, int, int)); 312 int eap_get_props __P((void *)); 313 void eap_write_codec __P((struct eap_softc *sc, int a, int d)); 314 void eap_set_mixer __P((struct eap_softc *sc, int a, int d)); 315 316 struct audio_hw_if eap_hw_if = { 317 eap_open, 318 eap_close, 319 NULL, 320 eap_query_encoding, 321 eap_set_params, 322 eap_round_blocksize, 323 NULL, 324 NULL, 325 NULL, 326 NULL, 327 NULL, 328 eap_halt_output, 329 eap_halt_input, 330 NULL, 331 eap_getdev, 332 NULL, 333 eap_mixer_set_port, 334 eap_mixer_get_port, 335 eap_query_devinfo, 336 eap_malloc, 337 eap_free, 338 eap_round_buffersize, 339 eap_mappage, 340 eap_get_props, 341 eap_trigger_output, 342 eap_trigger_input, 343 }; 344 345 struct audio_device eap_device = { 346 "Ensoniq AudioPCI", 347 "", 348 "eap" 349 }; 350 351 int 352 eap_match(parent, match, aux) 353 struct device *parent; 354 struct cfdata *match; 355 void *aux; 356 { 357 struct pci_attach_args *pa = (struct pci_attach_args *) aux; 358 359 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_ENSONIQ) 360 return (0); 361 if (PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_ENSONIQ_AUDIOPCI) 362 return (0); 363 364 return (1); 365 } 366 367 void 368 eap_write_codec(sc, a, d) 369 struct eap_softc *sc; 370 int a, d; 371 { 372 int icss; 373 374 do { 375 icss = EREAD4(sc, EAP_ICSS); 376 DPRINTFN(5,("eap: codec %d prog: icss=0x%08x\n", a, icss)); 377 } while(icss & EAP_CWRIP); 378 EWRITE4(sc, EAP_CODEC, EAP_SET_CODEC(a, d)); 379 } 380 381 void 382 eap_attach(parent, self, aux) 383 struct device *parent; 384 struct device *self; 385 void *aux; 386 { 387 struct eap_softc *sc = (struct eap_softc *)self; 388 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 389 pci_chipset_tag_t pc = pa->pa_pc; 390 char const *intrstr; 391 pci_intr_handle_t ih; 392 pcireg_t csr; 393 char devinfo[256]; 394 mixer_ctrl_t ctl; 395 396 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo); 397 printf(": %s (rev. 0x%02x)\n", devinfo, PCI_REVISION(pa->pa_class)); 398 399 /* Map I/O register */ 400 if (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0, 401 &sc->iot, &sc->ioh, NULL, NULL)) { 402 printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname); 403 return; 404 } 405 406 sc->sc_dmatag = pa->pa_dmat; 407 408 /* Enable the device. */ 409 csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 410 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 411 csr | PCI_COMMAND_MASTER_ENABLE); 412 413 /* Map and establish the interrupt. */ 414 if (pci_intr_map(pc, pa->pa_intrtag, pa->pa_intrpin, 415 pa->pa_intrline, &ih)) { 416 printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname); 417 return; 418 } 419 intrstr = pci_intr_string(pc, ih); 420 sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, eap_intr, sc); 421 if (sc->sc_ih == NULL) { 422 printf("%s: couldn't establish interrupt", 423 sc->sc_dev.dv_xname); 424 if (intrstr != NULL) 425 printf(" at %s", intrstr); 426 printf("\n"); 427 return; 428 } 429 printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr); 430 431 /* Enable interrupts and looping mode. */ 432 EWRITE4(sc, EAP_SIC, EAP_P2_INTR_EN | EAP_R1_INTR_EN); 433 EWRITE4(sc, EAP_ICSC, EAP_CDC_EN); /* enable the parts we need */ 434 435 eap_write_codec(sc, AK_RESET, AK_PD); /* reset codec */ 436 eap_write_codec(sc, AK_RESET, AK_PD | AK_NRST); /* normal operation */ 437 eap_write_codec(sc, AK_CS, 0x0); /* select codec clocks */ 438 439 /* Enable all relevant mixer switches. */ 440 ctl.dev = EAP_OUTPUT_SELECT; 441 ctl.type = AUDIO_MIXER_SET; 442 ctl.un.mask = 1 << EAP_VOICE_VOL | 1 << EAP_FM_VOL | 1 << EAP_CD_VOL | 443 1 << EAP_LINE_VOL | 1 << EAP_AUX_VOL | 1 << EAP_MIC_VOL; 444 eap_mixer_set_port(sc, &ctl); 445 446 ctl.type = AUDIO_MIXER_VALUE; 447 ctl.un.value.num_channels = 1; 448 for (ctl.dev = EAP_MASTER_VOL; ctl.dev < EAP_MIC_VOL; ctl.dev++) { 449 ctl.un.value.level[AUDIO_MIXER_LEVEL_MONO] = VOL_0DB; 450 eap_mixer_set_port(sc, &ctl); 451 } 452 ctl.un.value.level[AUDIO_MIXER_LEVEL_MONO] = 0; 453 eap_mixer_set_port(sc, &ctl); /* set the mic to 0 */ 454 ctl.dev = EAP_MIC_PREAMP; 455 ctl.type = AUDIO_MIXER_ENUM; 456 ctl.un.ord = 0; 457 eap_mixer_set_port(sc, &ctl); 458 ctl.dev = EAP_RECORD_SOURCE; 459 ctl.type = AUDIO_MIXER_SET; 460 ctl.un.mask = 1 << EAP_MIC_VOL; 461 eap_mixer_set_port(sc, &ctl); 462 463 audio_attach_mi(&eap_hw_if, sc, &sc->sc_dev); 464 } 465 466 int 467 eap_intr(p) 468 void *p; 469 { 470 struct eap_softc *sc = p; 471 u_int32_t intr, sic; 472 473 intr = EREAD4(sc, EAP_ICSS); 474 if (!(intr & EAP_INTR)) 475 return (0); 476 sic = EREAD4(sc, EAP_SIC); 477 DPRINTFN(5, ("eap_intr: ICSS=0x%08x, SIC=0x%08x\n", intr, sic)); 478 if (intr & EAP_I_ADC) { 479 /* 480 * XXX This is a hack! 481 * The EAP chip sometimes generates the recording interrupt 482 * while it is still transferring the data. To make sure 483 * it has all arrived we busy wait until the count is right. 484 * The transfer we are waiting for is 8 longwords. 485 */ 486 int s, nw, n; 487 EWRITE4(sc, EAP_MEMPAGE, EAP_ADC_PAGE); 488 s = EREAD4(sc, EAP_ADC_CSR); 489 nw = ((s & 0xffff) + 1) >> 2; /* # of words in DMA */ 490 n = 0; 491 while (((EREAD4(sc, EAP_ADC_SIZE) >> 16) + 8) % nw == 0) { 492 delay(10); 493 if (++n > 100) { 494 printf("eapintr: dma fix timeout"); 495 break; 496 } 497 } 498 /* Continue with normal interrupt handling. */ 499 EWRITE4(sc, EAP_SIC, sic & ~EAP_R1_INTR_EN); 500 EWRITE4(sc, EAP_SIC, sic); 501 if (sc->sc_rintr) 502 sc->sc_rintr(sc->sc_rarg); 503 } 504 if (intr & EAP_I_DAC2) { 505 EWRITE4(sc, EAP_SIC, sic & ~EAP_P2_INTR_EN); 506 EWRITE4(sc, EAP_SIC, sic); 507 if (sc->sc_pintr) 508 sc->sc_pintr(sc->sc_parg); 509 } 510 return (1); 511 } 512 513 int 514 eap_allocmem(sc, size, align, p) 515 struct eap_softc *sc; 516 size_t size; 517 size_t align; 518 struct eap_dma *p; 519 { 520 int error; 521 522 p->size = size; 523 error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0, 524 p->segs, sizeof(p->segs)/sizeof(p->segs[0]), 525 &p->nsegs, BUS_DMA_NOWAIT); 526 if (error) 527 return (error); 528 529 error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size, 530 &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT); 531 if (error) 532 goto free; 533 534 error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size, 535 0, BUS_DMA_NOWAIT, &p->map); 536 if (error) 537 goto unmap; 538 539 error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL, 540 BUS_DMA_NOWAIT); 541 if (error) 542 goto destroy; 543 return (0); 544 545 destroy: 546 bus_dmamap_destroy(sc->sc_dmatag, p->map); 547 unmap: 548 bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size); 549 free: 550 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs); 551 return (error); 552 } 553 554 int 555 eap_freemem(sc, p) 556 struct eap_softc *sc; 557 struct eap_dma *p; 558 { 559 bus_dmamap_unload(sc->sc_dmatag, p->map); 560 bus_dmamap_destroy(sc->sc_dmatag, p->map); 561 bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size); 562 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs); 563 return (0); 564 } 565 566 int 567 eap_open(addr, flags) 568 void *addr; 569 int flags; 570 { 571 572 return (0); 573 } 574 575 /* 576 * Close function is called at splaudio(). 577 */ 578 void 579 eap_close(addr) 580 void *addr; 581 { 582 struct eap_softc *sc = addr; 583 584 eap_halt_output(sc); 585 eap_halt_input(sc); 586 587 sc->sc_pintr = 0; 588 sc->sc_rintr = 0; 589 } 590 591 int 592 eap_query_encoding(addr, fp) 593 void *addr; 594 struct audio_encoding *fp; 595 { 596 switch (fp->index) { 597 case 0: 598 strcpy(fp->name, AudioEulinear); 599 fp->encoding = AUDIO_ENCODING_ULINEAR; 600 fp->precision = 8; 601 fp->flags = 0; 602 return (0); 603 case 1: 604 strcpy(fp->name, AudioEmulaw); 605 fp->encoding = AUDIO_ENCODING_ULAW; 606 fp->precision = 8; 607 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 608 return (0); 609 case 2: 610 strcpy(fp->name, AudioEalaw); 611 fp->encoding = AUDIO_ENCODING_ALAW; 612 fp->precision = 8; 613 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 614 return (0); 615 case 3: 616 strcpy(fp->name, AudioEslinear); 617 fp->encoding = AUDIO_ENCODING_SLINEAR; 618 fp->precision = 8; 619 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 620 return (0); 621 case 4: 622 strcpy(fp->name, AudioEslinear_le); 623 fp->encoding = AUDIO_ENCODING_SLINEAR_LE; 624 fp->precision = 16; 625 fp->flags = 0; 626 return (0); 627 case 5: 628 strcpy(fp->name, AudioEulinear_le); 629 fp->encoding = AUDIO_ENCODING_ULINEAR_LE; 630 fp->precision = 16; 631 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 632 return (0); 633 case 6: 634 strcpy(fp->name, AudioEslinear_be); 635 fp->encoding = AUDIO_ENCODING_SLINEAR_BE; 636 fp->precision = 16; 637 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 638 return (0); 639 case 7: 640 strcpy(fp->name, AudioEulinear_be); 641 fp->encoding = AUDIO_ENCODING_ULINEAR_BE; 642 fp->precision = 16; 643 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 644 return (0); 645 default: 646 return (EINVAL); 647 } 648 } 649 650 int 651 eap_set_params(addr, setmode, usemode, play, rec) 652 void *addr; 653 int setmode, usemode; 654 struct audio_params *play, *rec; 655 { 656 struct eap_softc *sc = addr; 657 struct audio_params *p; 658 int mode; 659 u_int32_t div; 660 661 /* 662 * This device only has one clock, so make the sample rates match. 663 */ 664 if (play->sample_rate != rec->sample_rate && 665 usemode == (AUMODE_PLAY | AUMODE_RECORD)) { 666 if (setmode == AUMODE_PLAY) { 667 rec->sample_rate = play->sample_rate; 668 setmode |= AUMODE_RECORD; 669 } else if (setmode == AUMODE_RECORD) { 670 play->sample_rate = rec->sample_rate; 671 setmode |= AUMODE_PLAY; 672 } else 673 return (EINVAL); 674 } 675 676 for (mode = AUMODE_RECORD; mode != -1; 677 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) { 678 if ((setmode & mode) == 0) 679 continue; 680 681 p = mode == AUMODE_PLAY ? play : rec; 682 683 if (p->sample_rate < 4000 || p->sample_rate > 50000 || 684 (p->precision != 8 && p->precision != 16) || 685 (p->channels != 1 && p->channels != 2)) 686 return (EINVAL); 687 688 p->factor = 1; 689 p->sw_code = 0; 690 switch (p->encoding) { 691 case AUDIO_ENCODING_SLINEAR_BE: 692 if (p->precision == 16) 693 p->sw_code = swap_bytes; 694 else 695 p->sw_code = change_sign8; 696 break; 697 case AUDIO_ENCODING_SLINEAR_LE: 698 if (p->precision != 16) 699 p->sw_code = change_sign8; 700 break; 701 case AUDIO_ENCODING_ULINEAR_BE: 702 if (p->precision == 16) { 703 if (mode == AUMODE_PLAY) 704 p->sw_code = swap_bytes_change_sign16; 705 else 706 p->sw_code = change_sign16_swap_bytes; 707 } 708 break; 709 case AUDIO_ENCODING_ULINEAR_LE: 710 if (p->precision == 16) 711 p->sw_code = change_sign16; 712 break; 713 case AUDIO_ENCODING_ULAW: 714 if (mode == AUMODE_PLAY) { 715 p->factor = 2; 716 p->sw_code = mulaw_to_slinear16; 717 } else 718 p->sw_code = ulinear8_to_mulaw; 719 break; 720 case AUDIO_ENCODING_ALAW: 721 if (mode == AUMODE_PLAY) { 722 p->factor = 2; 723 p->sw_code = alaw_to_slinear16; 724 } else 725 p->sw_code = ulinear8_to_alaw; 726 break; 727 default: 728 return (EINVAL); 729 } 730 } 731 732 /* Set the speed */ 733 DPRINTFN(2, ("eap_set_params: old ICSC = 0x%08x\n", 734 EREAD4(sc, EAP_ICSC))); 735 div = EREAD4(sc, EAP_ICSC) & ~EAP_PCLKBITS; 736 /* 737 * XXX 738 * The -2 isn't documented, but seemed to make the wall time match 739 * what I expect. - mycroft 740 */ 741 if (usemode == AUMODE_RECORD) 742 div |= EAP_SET_PCLKDIV(EAP_XTAL_FREQ / rec->sample_rate - 2); 743 else 744 div |= EAP_SET_PCLKDIV(EAP_XTAL_FREQ / play->sample_rate - 2); 745 div |= EAP_CCB_INTRM; 746 EWRITE4(sc, EAP_ICSC, div); 747 DPRINTFN(2, ("eap_set_params: set ICSC = 0x%08x\n", div)); 748 749 return (0); 750 } 751 752 int 753 eap_round_blocksize(addr, blk) 754 void *addr; 755 int blk; 756 { 757 return (blk & -32); /* keep good alignment */ 758 } 759 760 int 761 eap_trigger_output(addr, start, end, blksize, intr, arg, param) 762 void *addr; 763 void *start, *end; 764 int blksize; 765 void (*intr) __P((void *)); 766 void *arg; 767 struct audio_params *param; 768 { 769 struct eap_softc *sc = addr; 770 struct eap_dma *p; 771 u_int32_t icsc, sic; 772 int sampshift; 773 774 #ifdef DIAGNOSTIC 775 if (sc->sc_prun) 776 panic("eap_trigger_output: already running"); 777 sc->sc_prun = 1; 778 #endif 779 780 DPRINTFN(1, ("eap_trigger_output: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n", 781 addr, start, end, blksize, intr, arg)); 782 sc->sc_pintr = intr; 783 sc->sc_parg = arg; 784 785 icsc = EREAD4(sc, EAP_ICSC); 786 EWRITE4(sc, EAP_ICSC, icsc & ~EAP_DAC2_EN); 787 788 sic = EREAD4(sc, EAP_SIC); 789 sic &= ~(EAP_P2_S_EB | EAP_P2_S_MB | EAP_INC_BITS); 790 sic |= EAP_SET_P2_ST_INC(0) | EAP_SET_P2_END_INC(param->precision * param->factor / 8); 791 sampshift = 0; 792 if (param->precision * param->factor == 16) { 793 sic |= EAP_P2_S_EB; 794 sampshift++; 795 } 796 if (param->channels == 2) { 797 sic |= EAP_P2_S_MB; 798 sampshift++; 799 } 800 EWRITE4(sc, EAP_SIC, sic); 801 802 for (p = sc->sc_dmas; p && KERNADDR(p) != start; p = p->next) 803 ; 804 if (!p) { 805 printf("eap_trigger_output: bad addr %p\n", start); 806 return (EINVAL); 807 } 808 809 DPRINTF(("eap_trigger_output: DAC2_ADDR=0x%x, DAC2_SIZE=0x%x\n", 810 (int)DMAADDR(p), 811 EAP_SET_SIZE(0, (((char *)end - (char *)start) >> 2) - 1))); 812 EWRITE4(sc, EAP_MEMPAGE, EAP_DAC_PAGE); 813 EWRITE4(sc, EAP_DAC2_ADDR, DMAADDR(p)); 814 EWRITE4(sc, EAP_DAC2_SIZE, 815 EAP_SET_SIZE(0, (((char *)end - (char *)start) >> 2) - 1)); 816 817 EWRITE2(sc, EAP_DAC2_CSR, (blksize >> sampshift) - 1); 818 819 EWRITE4(sc, EAP_ICSC, icsc | EAP_DAC2_EN); 820 821 DPRINTFN(1, ("eap_trigger_output: set ICSC = 0x%08x\n", icsc)); 822 823 return (0); 824 } 825 826 int 827 eap_trigger_input(addr, start, end, blksize, intr, arg, param) 828 void *addr; 829 void *start, *end; 830 int blksize; 831 void (*intr) __P((void *)); 832 void *arg; 833 struct audio_params *param; 834 { 835 struct eap_softc *sc = addr; 836 struct eap_dma *p; 837 u_int32_t icsc, sic; 838 int sampshift; 839 840 #ifdef DIAGNOSTIC 841 if (sc->sc_rrun) 842 panic("eap_trigger_input: already running"); 843 sc->sc_rrun = 1; 844 #endif 845 846 DPRINTFN(1, ("eap_trigger_input: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n", 847 addr, start, end, blksize, intr, arg)); 848 sc->sc_rintr = intr; 849 sc->sc_rarg = arg; 850 851 icsc = EREAD4(sc, EAP_ICSC); 852 EWRITE4(sc, EAP_ICSC, icsc & ~EAP_ADC_EN); 853 854 sic = EREAD4(sc, EAP_SIC); 855 sic &= ~(EAP_R1_S_EB | EAP_R1_S_MB); 856 sampshift = 0; 857 if (param->precision * param->factor == 16) { 858 sic |= EAP_R1_S_EB; 859 sampshift++; 860 } 861 if (param->channels == 2) { 862 sic |= EAP_R1_S_MB; 863 sampshift++; 864 } 865 EWRITE4(sc, EAP_SIC, sic); 866 867 for (p = sc->sc_dmas; p && KERNADDR(p) != start; p = p->next) 868 ; 869 if (!p) { 870 printf("eap_trigger_input: bad addr %p\n", start); 871 return (EINVAL); 872 } 873 874 DPRINTF(("eap_trigger_input: ADC_ADDR=0x%x, ADC_SIZE=0x%x\n", 875 (int)DMAADDR(p), 876 EAP_SET_SIZE(0, (((char *)end - (char *)start) >> 2) - 1))); 877 EWRITE4(sc, EAP_MEMPAGE, EAP_ADC_PAGE); 878 EWRITE4(sc, EAP_ADC_ADDR, DMAADDR(p)); 879 EWRITE4(sc, EAP_ADC_SIZE, 880 EAP_SET_SIZE(0, (((char *)end - (char *)start) >> 2) - 1)); 881 882 EWRITE2(sc, EAP_ADC_CSR, (blksize >> sampshift) - 1); 883 884 EWRITE4(sc, EAP_ICSC, icsc | EAP_ADC_EN); 885 886 DPRINTFN(1, ("eap_trigger_input: set ICSC = 0x%08x\n", icsc)); 887 888 return (0); 889 } 890 891 int 892 eap_halt_output(addr) 893 void *addr; 894 { 895 struct eap_softc *sc = addr; 896 u_int32_t icsc; 897 898 DPRINTF(("eap: eap_halt_output\n")); 899 icsc = EREAD4(sc, EAP_ICSC); 900 EWRITE4(sc, EAP_ICSC, icsc & ~EAP_DAC2_EN); 901 #ifdef DIAGNOSTIC 902 sc->sc_prun = 0; 903 #endif 904 return (0); 905 } 906 907 int 908 eap_halt_input(addr) 909 void *addr; 910 { 911 struct eap_softc *sc = addr; 912 u_int32_t icsc; 913 914 DPRINTF(("eap: eap_halt_input\n")); 915 icsc = EREAD4(sc, EAP_ICSC); 916 EWRITE4(sc, EAP_ICSC, icsc & ~EAP_ADC_EN); 917 #ifdef DIAGNOSTIC 918 sc->sc_rrun = 0; 919 #endif 920 return (0); 921 } 922 923 int 924 eap_getdev(addr, retp) 925 void *addr; 926 struct audio_device *retp; 927 { 928 *retp = eap_device; 929 return (0); 930 } 931 932 void 933 eap_set_mixer(sc, a, d) 934 struct eap_softc *sc; 935 int a, d; 936 { 937 eap_write_codec(sc, a, d); 938 DPRINTFN(1, ("eap_mixer_set_port port 0x%02x = 0x%02x\n", a, d)); 939 } 940 941 942 int 943 eap_mixer_set_port(addr, cp) 944 void *addr; 945 mixer_ctrl_t *cp; 946 { 947 struct eap_softc *sc = addr; 948 int lval, rval, l, r, la, ra; 949 int l1, r1, l2, r2, m, o1, o2; 950 951 if (cp->dev == EAP_RECORD_SOURCE) { 952 if (cp->type != AUDIO_MIXER_SET) 953 return (EINVAL); 954 m = sc->sc_record_source = cp->un.mask; 955 l1 = l2 = r1 = r2 = 0; 956 if (m & (1 << EAP_VOICE_VOL)) 957 l2 |= AK_M_VOICE, r2 |= AK_M_VOICE; 958 if (m & (1 << EAP_FM_VOL)) 959 l1 |= AK_M_FM_L, r1 |= AK_M_FM_R; 960 if (m & (1 << EAP_CD_VOL)) 961 l1 |= AK_M_CD_L, r1 |= AK_M_CD_R; 962 if (m & (1 << EAP_LINE_VOL)) 963 l1 |= AK_M_LINE_L, r1 |= AK_M_LINE_R; 964 if (m & (1 << EAP_AUX_VOL)) 965 l2 |= AK_M2_AUX_L, r2 |= AK_M2_AUX_R; 966 if (m & (1 << EAP_MIC_VOL)) 967 l2 |= AK_M_TMIC, r2 |= AK_M_TMIC; 968 eap_set_mixer(sc, AK_IN_MIXER1_L, l1); 969 eap_set_mixer(sc, AK_IN_MIXER1_R, r1); 970 eap_set_mixer(sc, AK_IN_MIXER2_L, l2); 971 eap_set_mixer(sc, AK_IN_MIXER2_R, r2); 972 return (0); 973 } 974 if (cp->dev == EAP_OUTPUT_SELECT) { 975 if (cp->type != AUDIO_MIXER_SET) 976 return (EINVAL); 977 m = sc->sc_output_source = cp->un.mask; 978 o1 = o2 = 0; 979 if (m & (1 << EAP_VOICE_VOL)) 980 o2 |= AK_M_VOICE_L | AK_M_VOICE_R; 981 if (m & (1 << EAP_FM_VOL)) 982 o1 |= AK_M_FM_L | AK_M_FM_R; 983 if (m & (1 << EAP_CD_VOL)) 984 o1 |= AK_M_CD_L | AK_M_CD_R; 985 if (m & (1 << EAP_LINE_VOL)) 986 o1 |= AK_M_LINE_L | AK_M_LINE_R; 987 if (m & (1 << EAP_AUX_VOL)) 988 o2 |= AK_M_AUX_L | AK_M_AUX_R; 989 if (m & (1 << EAP_MIC_VOL)) 990 o1 |= AK_M_MIC; 991 eap_set_mixer(sc, AK_OUT_MIXER1, o1); 992 eap_set_mixer(sc, AK_OUT_MIXER2, o2); 993 return (0); 994 } 995 if (cp->dev == EAP_MIC_PREAMP) { 996 if (cp->type != AUDIO_MIXER_ENUM) 997 return (EINVAL); 998 if (cp->un.ord != 0 && cp->un.ord != 1) 999 return (EINVAL); 1000 sc->sc_mic_preamp = cp->un.ord; 1001 eap_set_mixer(sc, AK_MGAIN, cp->un.ord); 1002 return (0); 1003 } 1004 if (cp->type != AUDIO_MIXER_VALUE) 1005 return (EINVAL); 1006 if (cp->un.value.num_channels == 1) 1007 lval = rval = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 1008 else if (cp->un.value.num_channels == 2) { 1009 lval = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 1010 rval = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 1011 } else 1012 return (EINVAL); 1013 ra = -1; 1014 switch (cp->dev) { 1015 case EAP_MASTER_VOL: 1016 l = VOL_TO_ATT5(lval); 1017 r = VOL_TO_ATT5(rval); 1018 la = AK_MASTER_L; 1019 ra = AK_MASTER_R; 1020 break; 1021 case EAP_MIC_VOL: 1022 if (cp->un.value.num_channels != 1) 1023 return (EINVAL); 1024 la = AK_MIC; 1025 goto lr; 1026 case EAP_VOICE_VOL: 1027 la = AK_VOICE_L; 1028 ra = AK_VOICE_R; 1029 goto lr; 1030 case EAP_FM_VOL: 1031 la = AK_FM_L; 1032 ra = AK_FM_R; 1033 goto lr; 1034 case EAP_CD_VOL: 1035 la = AK_CD_L; 1036 ra = AK_CD_R; 1037 goto lr; 1038 case EAP_LINE_VOL: 1039 la = AK_LINE_L; 1040 ra = AK_LINE_R; 1041 goto lr; 1042 case EAP_AUX_VOL: 1043 la = AK_AUX_L; 1044 ra = AK_AUX_R; 1045 lr: 1046 l = VOL_TO_GAIN5(lval); 1047 r = VOL_TO_GAIN5(rval); 1048 break; 1049 default: 1050 return (EINVAL); 1051 } 1052 eap_set_mixer(sc, la, l); 1053 sc->sc_port[la] = l; 1054 if (ra >= 0) { 1055 eap_set_mixer(sc, ra, r); 1056 sc->sc_port[ra] = r; 1057 } 1058 return (0); 1059 } 1060 1061 int 1062 eap_mixer_get_port(addr, cp) 1063 void *addr; 1064 mixer_ctrl_t *cp; 1065 { 1066 struct eap_softc *sc = addr; 1067 int la, ra, l, r; 1068 1069 switch (cp->dev) { 1070 case EAP_RECORD_SOURCE: 1071 if (cp->type != AUDIO_MIXER_SET) 1072 return (EINVAL); 1073 cp->un.mask = sc->sc_record_source; 1074 return (0); 1075 case EAP_OUTPUT_SELECT: 1076 if (cp->type != AUDIO_MIXER_SET) 1077 return (EINVAL); 1078 cp->un.mask = sc->sc_output_source; 1079 return (0); 1080 case EAP_MIC_PREAMP: 1081 if (cp->type != AUDIO_MIXER_ENUM) 1082 return (EINVAL); 1083 cp->un.ord = sc->sc_mic_preamp; 1084 return (0); 1085 case EAP_MASTER_VOL: 1086 l = ATT5_TO_VOL(sc->sc_port[AK_MASTER_L]); 1087 r = ATT5_TO_VOL(sc->sc_port[AK_MASTER_R]); 1088 break; 1089 case EAP_MIC_VOL: 1090 if (cp->un.value.num_channels != 1) 1091 return (EINVAL); 1092 la = ra = AK_MIC; 1093 goto lr; 1094 case EAP_VOICE_VOL: 1095 la = AK_VOICE_L; 1096 ra = AK_VOICE_R; 1097 goto lr; 1098 case EAP_FM_VOL: 1099 la = AK_FM_L; 1100 ra = AK_FM_R; 1101 goto lr; 1102 case EAP_CD_VOL: 1103 la = AK_CD_L; 1104 ra = AK_CD_R; 1105 goto lr; 1106 case EAP_LINE_VOL: 1107 la = AK_LINE_L; 1108 ra = AK_LINE_R; 1109 goto lr; 1110 case EAP_AUX_VOL: 1111 la = AK_AUX_L; 1112 ra = AK_AUX_R; 1113 lr: 1114 l = GAIN5_TO_VOL(sc->sc_port[la]); 1115 r = GAIN5_TO_VOL(sc->sc_port[ra]); 1116 break; 1117 default: 1118 return (EINVAL); 1119 } 1120 if (cp->un.value.num_channels == 1) 1121 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = (l+r) / 2; 1122 else if (cp->un.value.num_channels == 2) { 1123 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l; 1124 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r; 1125 } else 1126 return (EINVAL); 1127 return (0); 1128 } 1129 1130 int 1131 eap_query_devinfo(addr, dip) 1132 void *addr; 1133 mixer_devinfo_t *dip; 1134 { 1135 switch (dip->index) { 1136 case EAP_MASTER_VOL: 1137 dip->type = AUDIO_MIXER_VALUE; 1138 dip->mixer_class = EAP_OUTPUT_CLASS; 1139 dip->prev = dip->next = AUDIO_MIXER_LAST; 1140 strcpy(dip->label.name, AudioNmaster); 1141 dip->un.v.num_channels = 2; 1142 strcpy(dip->un.v.units.name, AudioNvolume); 1143 return (0); 1144 case EAP_VOICE_VOL: 1145 dip->type = AUDIO_MIXER_VALUE; 1146 dip->mixer_class = EAP_INPUT_CLASS; 1147 dip->prev = AUDIO_MIXER_LAST; 1148 dip->next = AUDIO_MIXER_LAST; 1149 strcpy(dip->label.name, AudioNdac); 1150 dip->un.v.num_channels = 2; 1151 strcpy(dip->un.v.units.name, AudioNvolume); 1152 return (0); 1153 case EAP_FM_VOL: 1154 dip->type = AUDIO_MIXER_VALUE; 1155 dip->mixer_class = EAP_INPUT_CLASS; 1156 dip->prev = AUDIO_MIXER_LAST; 1157 dip->next = AUDIO_MIXER_LAST; 1158 strcpy(dip->label.name, AudioNfmsynth); 1159 dip->un.v.num_channels = 2; 1160 strcpy(dip->un.v.units.name, AudioNvolume); 1161 return (0); 1162 case EAP_CD_VOL: 1163 dip->type = AUDIO_MIXER_VALUE; 1164 dip->mixer_class = EAP_INPUT_CLASS; 1165 dip->prev = AUDIO_MIXER_LAST; 1166 dip->next = AUDIO_MIXER_LAST; 1167 strcpy(dip->label.name, AudioNcd); 1168 dip->un.v.num_channels = 2; 1169 strcpy(dip->un.v.units.name, AudioNvolume); 1170 return (0); 1171 case EAP_LINE_VOL: 1172 dip->type = AUDIO_MIXER_VALUE; 1173 dip->mixer_class = EAP_INPUT_CLASS; 1174 dip->prev = AUDIO_MIXER_LAST; 1175 dip->next = AUDIO_MIXER_LAST; 1176 strcpy(dip->label.name, AudioNline); 1177 dip->un.v.num_channels = 2; 1178 strcpy(dip->un.v.units.name, AudioNvolume); 1179 return (0); 1180 case EAP_AUX_VOL: 1181 dip->type = AUDIO_MIXER_VALUE; 1182 dip->mixer_class = EAP_INPUT_CLASS; 1183 dip->prev = AUDIO_MIXER_LAST; 1184 dip->next = AUDIO_MIXER_LAST; 1185 strcpy(dip->label.name, AudioNaux); 1186 dip->un.v.num_channels = 2; 1187 strcpy(dip->un.v.units.name, AudioNvolume); 1188 return (0); 1189 case EAP_MIC_VOL: 1190 dip->type = AUDIO_MIXER_VALUE; 1191 dip->mixer_class = EAP_INPUT_CLASS; 1192 dip->prev = AUDIO_MIXER_LAST; 1193 dip->next = EAP_MIC_PREAMP; 1194 strcpy(dip->label.name, AudioNmicrophone); 1195 dip->un.v.num_channels = 1; 1196 strcpy(dip->un.v.units.name, AudioNvolume); 1197 return (0); 1198 case EAP_RECORD_SOURCE: 1199 dip->mixer_class = EAP_RECORD_CLASS; 1200 dip->prev = dip->next = AUDIO_MIXER_LAST; 1201 strcpy(dip->label.name, AudioNsource); 1202 dip->type = AUDIO_MIXER_SET; 1203 dip->un.s.num_mem = 6; 1204 strcpy(dip->un.s.member[0].label.name, AudioNmicrophone); 1205 dip->un.s.member[0].mask = 1 << EAP_MIC_VOL; 1206 strcpy(dip->un.s.member[1].label.name, AudioNcd); 1207 dip->un.s.member[1].mask = 1 << EAP_CD_VOL; 1208 strcpy(dip->un.s.member[2].label.name, AudioNline); 1209 dip->un.s.member[2].mask = 1 << EAP_LINE_VOL; 1210 strcpy(dip->un.s.member[3].label.name, AudioNfmsynth); 1211 dip->un.s.member[3].mask = 1 << EAP_FM_VOL; 1212 strcpy(dip->un.s.member[4].label.name, AudioNaux); 1213 dip->un.s.member[4].mask = 1 << EAP_AUX_VOL; 1214 strcpy(dip->un.s.member[5].label.name, AudioNdac); 1215 dip->un.s.member[5].mask = 1 << EAP_VOICE_VOL; 1216 return (0); 1217 case EAP_OUTPUT_SELECT: 1218 dip->mixer_class = EAP_OUTPUT_CLASS; 1219 dip->prev = dip->next = AUDIO_MIXER_LAST; 1220 strcpy(dip->label.name, AudioNselect); 1221 dip->type = AUDIO_MIXER_SET; 1222 dip->un.s.num_mem = 6; 1223 strcpy(dip->un.s.member[0].label.name, AudioNmicrophone); 1224 dip->un.s.member[0].mask = 1 << EAP_MIC_VOL; 1225 strcpy(dip->un.s.member[1].label.name, AudioNcd); 1226 dip->un.s.member[1].mask = 1 << EAP_CD_VOL; 1227 strcpy(dip->un.s.member[2].label.name, AudioNline); 1228 dip->un.s.member[2].mask = 1 << EAP_LINE_VOL; 1229 strcpy(dip->un.s.member[3].label.name, AudioNfmsynth); 1230 dip->un.s.member[3].mask = 1 << EAP_FM_VOL; 1231 strcpy(dip->un.s.member[4].label.name, AudioNaux); 1232 dip->un.s.member[4].mask = 1 << EAP_AUX_VOL; 1233 strcpy(dip->un.s.member[5].label.name, AudioNdac); 1234 dip->un.s.member[5].mask = 1 << EAP_VOICE_VOL; 1235 return (0); 1236 case EAP_MIC_PREAMP: 1237 dip->type = AUDIO_MIXER_ENUM; 1238 dip->mixer_class = EAP_INPUT_CLASS; 1239 dip->prev = EAP_MIC_VOL; 1240 dip->next = AUDIO_MIXER_LAST; 1241 strcpy(dip->label.name, AudioNpreamp); 1242 dip->un.e.num_mem = 2; 1243 strcpy(dip->un.e.member[0].label.name, AudioNoff); 1244 dip->un.e.member[0].ord = 0; 1245 strcpy(dip->un.e.member[1].label.name, AudioNon); 1246 dip->un.e.member[1].ord = 1; 1247 return (0); 1248 case EAP_OUTPUT_CLASS: 1249 dip->type = AUDIO_MIXER_CLASS; 1250 dip->mixer_class = EAP_OUTPUT_CLASS; 1251 dip->next = dip->prev = AUDIO_MIXER_LAST; 1252 strcpy(dip->label.name, AudioCoutputs); 1253 return (0); 1254 case EAP_RECORD_CLASS: 1255 dip->type = AUDIO_MIXER_CLASS; 1256 dip->mixer_class = EAP_RECORD_CLASS; 1257 dip->next = dip->prev = AUDIO_MIXER_LAST; 1258 strcpy(dip->label.name, AudioCrecord); 1259 return (0); 1260 case EAP_INPUT_CLASS: 1261 dip->type = AUDIO_MIXER_CLASS; 1262 dip->mixer_class = EAP_INPUT_CLASS; 1263 dip->next = dip->prev = AUDIO_MIXER_LAST; 1264 strcpy(dip->label.name, AudioCinputs); 1265 return (0); 1266 } 1267 return (ENXIO); 1268 } 1269 1270 void * 1271 eap_malloc(addr, direction, size, pool, flags) 1272 void *addr; 1273 int direction; 1274 size_t size; 1275 int pool, flags; 1276 { 1277 struct eap_softc *sc = addr; 1278 struct eap_dma *p; 1279 int error; 1280 1281 p = malloc(sizeof(*p), pool, flags); 1282 if (!p) 1283 return (0); 1284 error = eap_allocmem(sc, size, 16, p); 1285 if (error) { 1286 free(p, pool); 1287 return (0); 1288 } 1289 p->next = sc->sc_dmas; 1290 sc->sc_dmas = p; 1291 return (KERNADDR(p)); 1292 } 1293 1294 void 1295 eap_free(addr, ptr, pool) 1296 void *addr; 1297 void *ptr; 1298 int pool; 1299 { 1300 struct eap_softc *sc = addr; 1301 struct eap_dma **p; 1302 1303 for (p = &sc->sc_dmas; *p; p = &(*p)->next) { 1304 if (KERNADDR(*p) == ptr) { 1305 eap_freemem(sc, *p); 1306 *p = (*p)->next; 1307 free(*p, pool); 1308 return; 1309 } 1310 } 1311 } 1312 1313 size_t 1314 eap_round_buffersize(addr, direction, size) 1315 void *addr; 1316 int direction; 1317 size_t size; 1318 { 1319 return (size); 1320 } 1321 1322 int 1323 eap_mappage(addr, mem, off, prot) 1324 void *addr; 1325 void *mem; 1326 int off; 1327 int prot; 1328 { 1329 struct eap_softc *sc = addr; 1330 struct eap_dma *p; 1331 1332 if (off < 0) 1333 return (-1); 1334 for (p = sc->sc_dmas; p && KERNADDR(p) != mem; p = p->next) 1335 ; 1336 if (!p) 1337 return (-1); 1338 return (bus_dmamem_mmap(sc->sc_dmatag, p->segs, p->nsegs, 1339 off, prot, BUS_DMA_WAITOK)); 1340 } 1341 1342 int 1343 eap_get_props(addr) 1344 void *addr; 1345 { 1346 return (AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX); 1347 } 1348