1 /* $OpenBSD: eap.c,v 1.58 2020/01/11 09:09:09 cheloha Exp $ */ 2 /* $NetBSD: eap.c,v 1.46 2001/09/03 15:07:37 reinoud Exp $ */ 3 4 /* 5 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Lennart Augustsson <augustss@netbsd.org> and Charles M. Hannum. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Debugging: Andreas Gustafsson <gson@araneus.fi> 35 * Testing: Chuck Cranor <chuck@maria.wustl.edu> 36 * Phil Nelson <phil@cs.wwu.edu> 37 * 38 * ES1371/AC97: Ezra Story <ezy@panix.com> 39 */ 40 41 /* 42 * Ensoniq ES1370 + AK4531 and ES1371/ES1373 + AC97 43 * 44 * Documentation links: 45 * 46 * ftp://ftp.alsa-project.org/pub/manuals/ensoniq/ 47 * ftp://ftp.alsa-project.org/pub/manuals/asahi_kasei/4531.pdf 48 */ 49 50 #include "midi.h" 51 52 #include <sys/param.h> 53 #include <sys/systm.h> 54 #include <sys/kernel.h> 55 #include <sys/fcntl.h> 56 #include <sys/device.h> 57 58 #include <dev/pci/pcidevs.h> 59 #include <dev/pci/pcivar.h> 60 61 #include <sys/audioio.h> 62 #include <dev/audio_if.h> 63 #include <dev/midi_if.h> 64 #include <dev/ic/ac97.h> 65 66 #include <machine/bus.h> 67 68 #include <dev/pci/eapreg.h> 69 70 struct cfdriver eap_cd = { 71 NULL, "eap", DV_DULL 72 }; 73 74 #define PCI_CBIO 0x10 75 76 /* Debug */ 77 #ifdef AUDIO_DEBUG 78 #define DPRINTF(x) if (eapdebug) printf x 79 #define DPRINTFN(n,x) if (eapdebug>(n)) printf x 80 int eapdebug = 1; 81 #else 82 #define DPRINTF(x) 83 #define DPRINTFN(n,x) 84 #endif 85 86 int eap_match(struct device *, void *, void *); 87 void eap_attach(struct device *, struct device *, void *); 88 int eap_activate(struct device *, int); 89 int eap_intr(void *); 90 91 struct eap_dma { 92 bus_dmamap_t map; 93 caddr_t addr; 94 bus_dma_segment_t segs[1]; 95 int nsegs; 96 size_t size; 97 struct eap_dma *next; 98 }; 99 100 #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr) 101 #define KERNADDR(p) ((void *)((p)->addr)) 102 103 struct eap_softc { 104 struct device sc_dev; /* base device */ 105 void *sc_ih; /* interrupt vectoring */ 106 bus_space_tag_t iot; 107 bus_space_handle_t ioh; 108 bus_dma_tag_t sc_dmatag; /* DMA tag */ 109 110 struct eap_dma *sc_dmas; 111 112 void (*sc_pintr)(void *); /* dma completion intr handler */ 113 void *sc_parg; /* arg for sc_intr() */ 114 #ifdef DIAGNOSTIC 115 char sc_prun; 116 #endif 117 118 void (*sc_rintr)(void *); /* dma completion intr handler */ 119 void *sc_rarg; /* arg for sc_intr() */ 120 #ifdef DIAGNOSTIC 121 char sc_rrun; 122 #endif 123 124 #if NMIDI > 0 125 void (*sc_iintr)(void *, int); /* midi input ready handler */ 126 void (*sc_ointr)(void *); /* midi output ready handler */ 127 void *sc_arg; 128 int sc_uctrl; 129 struct device *sc_mididev; 130 #endif 131 132 u_short sc_port[AK_NPORTS]; /* mirror of the hardware setting */ 133 u_int sc_record_source; /* recording source mask */ 134 u_int sc_input_source; /* input source mask */ 135 u_int sc_mic_preamp; 136 char sc_1371; /* Using ES1371/AC97 codec */ 137 char sc_ct5880; /* CT5880 chip */ 138 139 struct ac97_codec_if *codec_if; 140 struct ac97_host_if host_if; 141 142 int flags; 143 }; 144 145 enum ac97_host_flags eap_flags_codec(void *); 146 int eap_allocmem(struct eap_softc *, size_t, size_t, struct eap_dma *); 147 int eap_freemem(struct eap_softc *, struct eap_dma *); 148 149 #define EWRITE1(sc, r, x) bus_space_write_1((sc)->iot, (sc)->ioh, (r), (x)) 150 #define EWRITE2(sc, r, x) bus_space_write_2((sc)->iot, (sc)->ioh, (r), (x)) 151 #define EWRITE4(sc, r, x) bus_space_write_4((sc)->iot, (sc)->ioh, (r), (x)) 152 #define EREAD1(sc, r) bus_space_read_1((sc)->iot, (sc)->ioh, (r)) 153 #define EREAD2(sc, r) bus_space_read_2((sc)->iot, (sc)->ioh, (r)) 154 #define EREAD4(sc, r) bus_space_read_4((sc)->iot, (sc)->ioh, (r)) 155 156 struct cfattach eap_ca = { 157 sizeof(struct eap_softc), eap_match, eap_attach, NULL, eap_activate 158 }; 159 160 int eap_open(void *, int); 161 void eap_close(void *); 162 int eap_set_params(void *, int, int, struct audio_params *, struct audio_params *); 163 int eap_round_blocksize(void *, int); 164 int eap_trigger_output(void *, void *, void *, int, void (*)(void *), 165 void *, struct audio_params *); 166 int eap_trigger_input(void *, void *, void *, int, void (*)(void *), 167 void *, struct audio_params *); 168 int eap_halt_output(void *); 169 int eap_halt_input(void *); 170 void eap_resume(struct eap_softc *); 171 void eap1370_write_codec(struct eap_softc *, int, int); 172 int eap1370_mixer_set_port(void *, mixer_ctrl_t *); 173 int eap1370_mixer_get_port(void *, mixer_ctrl_t *); 174 int eap1371_mixer_set_port(void *, mixer_ctrl_t *); 175 int eap1371_mixer_get_port(void *, mixer_ctrl_t *); 176 int eap1370_query_devinfo(void *, mixer_devinfo_t *); 177 void *eap_malloc(void *, int, size_t, int, int); 178 void eap_free(void *, void *, int); 179 int eap_get_props(void *); 180 void eap1370_set_mixer(struct eap_softc *sc, int a, int d); 181 u_int32_t eap1371_src_wait(struct eap_softc *sc); 182 void eap1371_src_write(struct eap_softc *sc, int a, int d); 183 int eap1371_query_devinfo(void *addr, mixer_devinfo_t *dip); 184 185 int eap1371_attach_codec(void *sc, struct ac97_codec_if *); 186 int eap1371_read_codec(void *sc, u_int8_t a, u_int16_t *d); 187 int eap1371_write_codec(void *sc, u_int8_t a, u_int16_t d); 188 void eap1371_reset_codec(void *sc); 189 #if NMIDI > 0 190 void eap_midi_close(void *); 191 void eap_midi_getinfo(void *, struct midi_info *); 192 int eap_midi_open(void *, int, void (*)(void *, int), 193 void (*)(void *), void *); 194 int eap_midi_output(void *, int); 195 #endif 196 197 struct audio_hw_if eap1370_hw_if = { 198 eap_open, 199 eap_close, 200 eap_set_params, 201 eap_round_blocksize, 202 NULL, 203 NULL, 204 NULL, 205 NULL, 206 NULL, 207 eap_halt_output, 208 eap_halt_input, 209 NULL, 210 NULL, 211 eap1370_mixer_set_port, 212 eap1370_mixer_get_port, 213 eap1370_query_devinfo, 214 eap_malloc, 215 eap_free, 216 NULL, 217 eap_get_props, 218 eap_trigger_output, 219 eap_trigger_input 220 }; 221 222 struct audio_hw_if eap1371_hw_if = { 223 eap_open, 224 eap_close, 225 eap_set_params, 226 eap_round_blocksize, 227 NULL, 228 NULL, 229 NULL, 230 NULL, 231 NULL, 232 eap_halt_output, 233 eap_halt_input, 234 NULL, 235 NULL, 236 eap1371_mixer_set_port, 237 eap1371_mixer_get_port, 238 eap1371_query_devinfo, 239 eap_malloc, 240 eap_free, 241 NULL, 242 eap_get_props, 243 eap_trigger_output, 244 eap_trigger_input 245 }; 246 247 #if NMIDI > 0 248 struct midi_hw_if eap_midi_hw_if = { 249 eap_midi_open, 250 eap_midi_close, 251 eap_midi_output, 252 0, /* flush */ 253 eap_midi_getinfo, 254 0, /* ioctl */ 255 }; 256 #endif 257 258 const struct pci_matchid eap_devices[] = { 259 { PCI_VENDOR_CREATIVELABS, PCI_PRODUCT_CREATIVELABS_EV1938 }, 260 { PCI_VENDOR_ENSONIQ, PCI_PRODUCT_ENSONIQ_AUDIOPCI }, 261 { PCI_VENDOR_ENSONIQ, PCI_PRODUCT_ENSONIQ_AUDIOPCI97 }, 262 { PCI_VENDOR_ENSONIQ, PCI_PRODUCT_ENSONIQ_CT5880 }, 263 }; 264 265 int 266 eap_match(struct device *parent, void *match, void *aux) 267 { 268 return (pci_matchbyid((struct pci_attach_args *)aux, eap_devices, 269 nitems(eap_devices))); 270 } 271 272 int 273 eap_activate(struct device *self, int act) 274 { 275 struct eap_softc *sc = (struct eap_softc *)self; 276 277 switch (act) { 278 case DVACT_RESUME: 279 eap_resume(sc); 280 break; 281 default: 282 break; 283 } 284 return (config_activate_children(self, act)); 285 } 286 287 void 288 eap1370_write_codec(struct eap_softc *sc, int a, int d) 289 { 290 int icss, to; 291 292 to = EAP_WRITE_TIMEOUT; 293 do { 294 icss = EREAD4(sc, EAP_ICSS); 295 DPRINTFN(5,("eap: codec %d prog: icss=0x%08x\n", a, icss)); 296 if (!to--) { 297 printf("%s: timeout writing to codec\n", 298 sc->sc_dev.dv_xname); 299 return; 300 } 301 } while (icss & EAP_CWRIP); /* XXX could use CSTAT here */ 302 EWRITE4(sc, EAP_CODEC, EAP_SET_CODEC(a, d)); 303 } 304 305 /* 306 * Reading and writing the CODEC is very convoluted. This mimics the 307 * FreeBSD and Linux drivers. 308 */ 309 310 static __inline void 311 eap1371_ready_codec(struct eap_softc *sc, u_int8_t a, u_int32_t wd) 312 { 313 int to; 314 u_int32_t src, t; 315 316 for (to = 0; to < EAP_WRITE_TIMEOUT; to++) { 317 if (!(EREAD4(sc, E1371_CODEC) & E1371_CODEC_WIP)) 318 break; 319 delay(1); 320 } 321 if (to == EAP_WRITE_TIMEOUT) 322 printf("%s: eap1371_ready_codec timeout 1\n", 323 sc->sc_dev.dv_xname); 324 325 mtx_enter(&audio_lock); 326 src = eap1371_src_wait(sc) & E1371_SRC_CTLMASK; 327 EWRITE4(sc, E1371_SRC, src | E1371_SRC_STATE_OK); 328 329 for (to = 0; to < EAP_READ_TIMEOUT; to++) { 330 t = EREAD4(sc, E1371_SRC); 331 if ((t & E1371_SRC_STATE_MASK) == 0) 332 break; 333 delay(1); 334 } 335 if (to == EAP_READ_TIMEOUT) 336 printf("%s: eap1371_ready_codec timeout 2\n", 337 sc->sc_dev.dv_xname); 338 339 for (to = 0; to < EAP_READ_TIMEOUT; to++) { 340 t = EREAD4(sc, E1371_SRC); 341 if ((t & E1371_SRC_STATE_MASK) == E1371_SRC_STATE_OK) 342 break; 343 delay(1); 344 } 345 if (to == EAP_READ_TIMEOUT) 346 printf("%s: eap1371_ready_codec timeout 3\n", 347 sc->sc_dev.dv_xname); 348 349 EWRITE4(sc, E1371_CODEC, wd); 350 351 eap1371_src_wait(sc); 352 EWRITE4(sc, E1371_SRC, src); 353 354 mtx_leave(&audio_lock); 355 } 356 357 int 358 eap1371_read_codec(void *sc_, u_int8_t a, u_int16_t *d) 359 { 360 struct eap_softc *sc = sc_; 361 int to; 362 u_int32_t t; 363 364 eap1371_ready_codec(sc, a, E1371_SET_CODEC(a, 0) | E1371_CODEC_READ); 365 366 for (to = 0; to < EAP_WRITE_TIMEOUT; to++) { 367 if (!(EREAD4(sc, E1371_CODEC) & E1371_CODEC_WIP)) 368 break; 369 delay(1); 370 } 371 if (to == EAP_WRITE_TIMEOUT) 372 printf("%s: eap1371_read_codec timeout 1\n", 373 sc->sc_dev.dv_xname); 374 375 for (to = 0; to < EAP_WRITE_TIMEOUT; to++) { 376 t = EREAD4(sc, E1371_CODEC); 377 if (t & E1371_CODEC_VALID) 378 break; 379 delay(1); 380 } 381 if (to == EAP_WRITE_TIMEOUT) 382 printf("%s: eap1371_read_codec timeout 2\n", 383 sc->sc_dev.dv_xname); 384 385 *d = (u_int16_t)t; 386 387 DPRINTFN(10, ("eap1371: reading codec (%x) = %x\n", a, *d)); 388 389 return (0); 390 } 391 392 int 393 eap1371_write_codec(void *sc_, u_int8_t a, u_int16_t d) 394 { 395 struct eap_softc *sc = sc_; 396 397 eap1371_ready_codec(sc, a, E1371_SET_CODEC(a, d)); 398 399 DPRINTFN(10, ("eap1371: writing codec %x --> %x\n", d, a)); 400 401 return (0); 402 } 403 404 u_int32_t 405 eap1371_src_wait(struct eap_softc *sc) 406 { 407 int to; 408 u_int32_t src = 0; 409 410 for (to = 0; to < EAP_READ_TIMEOUT; to++) { 411 src = EREAD4(sc, E1371_SRC); 412 if (!(src & E1371_SRC_RBUSY)) 413 return (src); 414 delay(1); 415 } 416 printf("%s: eap1371_src_wait timeout\n", sc->sc_dev.dv_xname); 417 return (src); 418 } 419 420 void 421 eap1371_src_write(struct eap_softc *sc, int a, int d) 422 { 423 u_int32_t r; 424 425 r = eap1371_src_wait(sc) & E1371_SRC_CTLMASK; 426 r |= E1371_SRC_RAMWE | E1371_SRC_ADDR(a) | E1371_SRC_DATA(d); 427 EWRITE4(sc, E1371_SRC, r); 428 } 429 430 void 431 eap_attach(struct device *parent, struct device *self, void *aux) 432 { 433 struct eap_softc *sc = (struct eap_softc *)self; 434 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 435 pci_chipset_tag_t pc = pa->pa_pc; 436 struct audio_hw_if *eap_hw_if; 437 char const *intrstr; 438 pci_intr_handle_t ih; 439 mixer_ctrl_t ctl; 440 int i; 441 int revision; 442 443 /* Flag if we're "creative" */ 444 sc->sc_1371 = !(PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ENSONIQ && 445 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ENSONIQ_AUDIOPCI); 446 447 revision = PCI_REVISION(pa->pa_class); 448 if (sc->sc_1371) { 449 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ENSONIQ && 450 ((PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ENSONIQ_AUDIOPCI97 && 451 (revision == EAP_ES1373_8 || revision == EAP_CT5880_A)) || 452 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ENSONIQ_CT5880)) 453 sc->sc_ct5880 = 1; 454 } 455 456 /* Map I/O register */ 457 if (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0, 458 &sc->iot, &sc->ioh, NULL, NULL, 0)) { 459 return; 460 } 461 462 sc->sc_dmatag = pa->pa_dmat; 463 464 /* Map and establish the interrupt. */ 465 if (pci_intr_map(pa, &ih)) { 466 printf(": couldn't map interrupt\n"); 467 return; 468 } 469 intrstr = pci_intr_string(pc, ih); 470 sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO | IPL_MPSAFE, 471 eap_intr, sc, sc->sc_dev.dv_xname); 472 if (sc->sc_ih == NULL) { 473 printf(": couldn't establish interrupt"); 474 if (intrstr != NULL) 475 printf(" at %s", intrstr); 476 printf("\n"); 477 return; 478 } 479 printf(": %s\n", intrstr); 480 481 if (!sc->sc_1371) { 482 /* Enable interrupts and looping mode. */ 483 /* enable the parts we need */ 484 EWRITE4(sc, EAP_SIC, EAP_P2_INTR_EN | EAP_R1_INTR_EN); 485 EWRITE4(sc, EAP_ICSC, EAP_CDC_EN); 486 487 /* reset codec */ 488 /* normal operation */ 489 /* select codec clocks */ 490 eap1370_write_codec(sc, AK_RESET, AK_PD); 491 eap1370_write_codec(sc, AK_RESET, AK_PD | AK_NRST); 492 eap1370_write_codec(sc, AK_CS, 0x0); 493 494 eap_hw_if = &eap1370_hw_if; 495 496 /* Enable all relevant mixer switches. */ 497 ctl.dev = EAP_INPUT_SOURCE; 498 ctl.type = AUDIO_MIXER_SET; 499 ctl.un.mask = 1 << EAP_VOICE_VOL | 1 << EAP_FM_VOL | 500 1 << EAP_CD_VOL | 1 << EAP_LINE_VOL | 1 << EAP_AUX_VOL | 501 1 << EAP_MIC_VOL; 502 eap_hw_if->set_port(sc, &ctl); 503 504 ctl.type = AUDIO_MIXER_VALUE; 505 ctl.un.value.num_channels = 1; 506 for (ctl.dev = EAP_MASTER_VOL; ctl.dev < EAP_MIC_VOL; 507 ctl.dev++) { 508 ctl.un.value.level[AUDIO_MIXER_LEVEL_MONO] = VOL_0DB; 509 eap_hw_if->set_port(sc, &ctl); 510 } 511 ctl.un.value.level[AUDIO_MIXER_LEVEL_MONO] = 0; 512 eap_hw_if->set_port(sc, &ctl); 513 ctl.dev = EAP_MIC_PREAMP; 514 ctl.type = AUDIO_MIXER_ENUM; 515 ctl.un.ord = 0; 516 eap_hw_if->set_port(sc, &ctl); 517 ctl.dev = EAP_RECORD_SOURCE; 518 ctl.type = AUDIO_MIXER_SET; 519 ctl.un.mask = 1 << EAP_MIC_VOL; 520 eap_hw_if->set_port(sc, &ctl); 521 } else { 522 /* clean slate */ 523 524 EWRITE4(sc, EAP_SIC, 0); 525 EWRITE4(sc, EAP_ICSC, 0); 526 EWRITE4(sc, E1371_LEGACY, 0); 527 528 if (sc->sc_ct5880) { 529 EWRITE4(sc, EAP_ICSS, EAP_CT5880_AC97_RESET); 530 /* Let codec wake up */ 531 delay(20000); 532 } 533 534 /* Reset from es1371's perspective */ 535 EWRITE4(sc, EAP_ICSC, E1371_SYNC_RES); 536 delay(20); 537 EWRITE4(sc, EAP_ICSC, 0); 538 539 /* 540 * Must properly reprogram sample rate converter, 541 * or it locks up. 542 * 543 * We don't know how to program it (no documentation), 544 * and the linux/oss magic receipe doesn't work (breaks 545 * full-duplex, by selecting different play and record 546 * rates). On the other hand, the sample rate converter 547 * can't be disabled (disabling it would disable DMA), 548 * so we use these magic defaults that make it "resample" 549 * 48kHz to 48kHz without breaking full-duplex. 550 */ 551 EWRITE4(sc, E1371_SRC, E1371_SRC_DISABLE); 552 for (i = 0; i < 0x80; i++) 553 eap1371_src_write(sc, i, 0); 554 eap1371_src_write(sc, ESRC_ADC + ESRC_TRUNC_N, ESRC_SET_N(16)); 555 eap1371_src_write(sc, ESRC_ADC + ESRC_IREGS, ESRC_SET_VFI(16)); 556 eap1371_src_write(sc, ESRC_ADC + ESRC_VFF, 0); 557 eap1371_src_write(sc, ESRC_ADC_VOLL, ESRC_SET_ADC_VOL(16)); 558 eap1371_src_write(sc, ESRC_ADC_VOLR, ESRC_SET_ADC_VOL(16)); 559 eap1371_src_write(sc, ESRC_DAC1 + ESRC_TRUNC_N, ESRC_SET_N(16)); 560 eap1371_src_write(sc, ESRC_DAC1 + ESRC_IREGS, ESRC_SET_VFI(16)); 561 eap1371_src_write(sc, ESRC_DAC1 + ESRC_VFF, 0); 562 eap1371_src_write(sc, ESRC_DAC1_VOLL, ESRC_SET_DAC_VOLI(1)); 563 eap1371_src_write(sc, ESRC_DAC1_VOLR, ESRC_SET_DAC_VOLI(1)); 564 eap1371_src_write(sc, ESRC_DAC2 + ESRC_IREGS, ESRC_SET_VFI(16)); 565 eap1371_src_write(sc, ESRC_DAC2 + ESRC_TRUNC_N, ESRC_SET_N(16)); 566 eap1371_src_write(sc, ESRC_DAC2 + ESRC_VFF, 0); 567 eap1371_src_write(sc, ESRC_DAC2_VOLL, ESRC_SET_DAC_VOLI(1)); 568 eap1371_src_write(sc, ESRC_DAC2_VOLR, ESRC_SET_DAC_VOLI(1)); 569 EWRITE4(sc, E1371_SRC, 0); 570 571 /* Reset codec */ 572 573 /* Interrupt enable */ 574 sc->host_if.arg = sc; 575 sc->host_if.attach = eap1371_attach_codec; 576 sc->host_if.read = eap1371_read_codec; 577 sc->host_if.write = eap1371_write_codec; 578 sc->host_if.reset = eap1371_reset_codec; 579 sc->host_if.flags = eap_flags_codec; 580 sc->flags = AC97_HOST_DONT_READ; 581 582 if (ac97_attach(&sc->host_if) == 0) { 583 /* Interrupt enable */ 584 EWRITE4(sc, EAP_SIC, EAP_P2_INTR_EN | EAP_R1_INTR_EN); 585 } else 586 return; 587 588 eap_hw_if = &eap1371_hw_if; 589 } 590 591 audio_attach_mi(eap_hw_if, sc, &sc->sc_dev); 592 #if NMIDI > 0 593 sc->sc_mididev = midi_attach_mi(&eap_midi_hw_if, sc, &sc->sc_dev); 594 #endif 595 } 596 597 void 598 eap_resume(struct eap_softc *sc) 599 { 600 int i; 601 602 if (!sc->sc_1371) { 603 /* Enable interrupts and looping mode. */ 604 /* enable the parts we need */ 605 EWRITE4(sc, EAP_SIC, EAP_P2_INTR_EN | EAP_R1_INTR_EN); 606 EWRITE4(sc, EAP_ICSC, EAP_CDC_EN); 607 608 /* reset codec */ 609 /* normal operation */ 610 /* select codec clocks */ 611 eap1370_write_codec(sc, AK_RESET, AK_PD); 612 eap1370_write_codec(sc, AK_RESET, AK_PD | AK_NRST); 613 eap1370_write_codec(sc, AK_CS, 0x0); 614 615 } else { 616 /* clean slate */ 617 618 EWRITE4(sc, EAP_SIC, 0); 619 EWRITE4(sc, EAP_ICSC, 0); 620 EWRITE4(sc, E1371_LEGACY, 0); 621 622 if (sc->sc_ct5880) { 623 EWRITE4(sc, EAP_ICSS, EAP_CT5880_AC97_RESET); 624 /* Let codec wake up */ 625 delay(20000); 626 } 627 628 ac97_resume(&sc->host_if, sc->codec_if); 629 630 EWRITE4(sc, E1371_SRC, E1371_SRC_DISABLE); 631 for (i = 0; i < 0x80; i++) 632 eap1371_src_write(sc, i, 0); 633 eap1371_src_write(sc, ESRC_ADC + ESRC_TRUNC_N, ESRC_SET_N(16)); 634 eap1371_src_write(sc, ESRC_ADC + ESRC_IREGS, ESRC_SET_VFI(16)); 635 eap1371_src_write(sc, ESRC_ADC + ESRC_VFF, 0); 636 eap1371_src_write(sc, ESRC_ADC_VOLL, ESRC_SET_ADC_VOL(16)); 637 eap1371_src_write(sc, ESRC_ADC_VOLR, ESRC_SET_ADC_VOL(16)); 638 eap1371_src_write(sc, ESRC_DAC1 + ESRC_TRUNC_N, ESRC_SET_N(16)); 639 eap1371_src_write(sc, ESRC_DAC1 + ESRC_IREGS, ESRC_SET_VFI(16)); 640 eap1371_src_write(sc, ESRC_DAC1 + ESRC_VFF, 0); 641 eap1371_src_write(sc, ESRC_DAC1_VOLL, ESRC_SET_DAC_VOLI(1)); 642 eap1371_src_write(sc, ESRC_DAC1_VOLR, ESRC_SET_DAC_VOLI(1)); 643 eap1371_src_write(sc, ESRC_DAC2 + ESRC_IREGS, ESRC_SET_VFI(16)); 644 eap1371_src_write(sc, ESRC_DAC2 + ESRC_TRUNC_N, ESRC_SET_N(16)); 645 eap1371_src_write(sc, ESRC_DAC2 + ESRC_VFF, 0); 646 eap1371_src_write(sc, ESRC_DAC2_VOLL, ESRC_SET_DAC_VOLI(1)); 647 eap1371_src_write(sc, ESRC_DAC2_VOLR, ESRC_SET_DAC_VOLI(1)); 648 EWRITE4(sc, E1371_SRC, 0); 649 650 /* Interrupt enable */ 651 EWRITE4(sc, EAP_SIC, EAP_P2_INTR_EN | EAP_R1_INTR_EN); 652 } 653 } 654 655 656 int 657 eap1371_attach_codec(void *sc_, struct ac97_codec_if *codec_if) 658 { 659 struct eap_softc *sc = sc_; 660 661 sc->codec_if = codec_if; 662 return (0); 663 } 664 665 void 666 eap1371_reset_codec(void *sc_) 667 { 668 struct eap_softc *sc = sc_; 669 u_int32_t icsc; 670 671 mtx_enter(&audio_lock); 672 icsc = EREAD4(sc, EAP_ICSC); 673 EWRITE4(sc, EAP_ICSC, icsc | E1371_SYNC_RES); 674 delay(20); 675 EWRITE4(sc, EAP_ICSC, icsc & ~E1371_SYNC_RES); 676 delay(1); 677 mtx_leave(&audio_lock); 678 679 return; 680 } 681 682 int 683 eap_intr(void *p) 684 { 685 struct eap_softc *sc = p; 686 u_int32_t intr, sic; 687 688 mtx_enter(&audio_lock); 689 intr = EREAD4(sc, EAP_ICSS); 690 if (!(intr & EAP_INTR)) { 691 mtx_leave(&audio_lock); 692 return (0); 693 } 694 sic = EREAD4(sc, EAP_SIC); 695 DPRINTFN(5, ("eap_intr: ICSS=0x%08x, SIC=0x%08x\n", intr, sic)); 696 if (intr & EAP_I_ADC) { 697 #if 0 698 /* 699 * XXX This is a hack! 700 * The EAP chip sometimes generates the recording interrupt 701 * while it is still transferring the data. To make sure 702 * it has all arrived we busy wait until the count is right. 703 * The transfer we are waiting for is 8 longwords. 704 */ 705 int s, nw, n; 706 707 EWRITE4(sc, EAP_MEMPAGE, EAP_ADC_PAGE); 708 s = EREAD4(sc, EAP_ADC_CSR); 709 nw = ((s & 0xffff) + 1) >> 2; /* # of words in DMA */ 710 n = 0; 711 while (((EREAD4(sc, EAP_ADC_SIZE) >> 16) + 8) % nw == 0) { 712 delay(10); 713 if (++n > 100) { 714 printf("eapintr: dma fix timeout"); 715 break; 716 } 717 } 718 /* Continue with normal interrupt handling. */ 719 #endif 720 EWRITE4(sc, EAP_SIC, sic & ~EAP_R1_INTR_EN); 721 EWRITE4(sc, EAP_SIC, sic | EAP_R1_INTR_EN); 722 if (sc->sc_rintr) 723 sc->sc_rintr(sc->sc_rarg); 724 } 725 if (intr & EAP_I_DAC2) { 726 EWRITE4(sc, EAP_SIC, sic & ~EAP_P2_INTR_EN); 727 EWRITE4(sc, EAP_SIC, sic | EAP_P2_INTR_EN); 728 if (sc->sc_pintr) 729 sc->sc_pintr(sc->sc_parg); 730 } 731 #if NMIDI > 0 732 if (intr & EAP_I_UART) { 733 u_int32_t data; 734 735 if (EREAD1(sc, EAP_UART_STATUS) & EAP_US_RXINT) { 736 while (EREAD1(sc, EAP_UART_STATUS) & EAP_US_RXRDY) { 737 data = EREAD1(sc, EAP_UART_DATA); 738 if (sc->sc_iintr) 739 sc->sc_iintr(sc->sc_arg, data); 740 } 741 } 742 if (EREAD1(sc, EAP_UART_STATUS) & EAP_US_TXINT) { 743 sc->sc_uctrl &= ~EAP_UC_TXINTEN; 744 EWRITE1(sc, EAP_UART_CONTROL, sc->sc_uctrl); 745 if (sc->sc_ointr) 746 sc->sc_ointr(sc->sc_arg); 747 } 748 } 749 #endif 750 mtx_leave(&audio_lock); 751 return (1); 752 } 753 754 int 755 eap_allocmem(struct eap_softc *sc, size_t size, size_t align, struct eap_dma *p) 756 { 757 int error; 758 759 p->size = size; 760 error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0, 761 p->segs, nitems(p->segs), 762 &p->nsegs, BUS_DMA_NOWAIT); 763 if (error) 764 return (error); 765 766 error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size, 767 &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT); 768 if (error) 769 goto free; 770 771 error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size, 772 0, BUS_DMA_NOWAIT, &p->map); 773 if (error) 774 goto unmap; 775 776 error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL, 777 BUS_DMA_NOWAIT); 778 if (error) 779 goto destroy; 780 return (0); 781 782 destroy: 783 bus_dmamap_destroy(sc->sc_dmatag, p->map); 784 unmap: 785 bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size); 786 free: 787 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs); 788 return (error); 789 } 790 791 int 792 eap_freemem(struct eap_softc *sc, struct eap_dma *p) 793 { 794 bus_dmamap_unload(sc->sc_dmatag, p->map); 795 bus_dmamap_destroy(sc->sc_dmatag, p->map); 796 bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size); 797 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs); 798 return (0); 799 } 800 801 int 802 eap_open(void *addr, int flags) 803 { 804 return (0); 805 } 806 807 /* 808 * Close function is called at splaudio(). 809 */ 810 void 811 eap_close(void *addr) 812 { 813 struct eap_softc *sc = addr; 814 815 eap_halt_output(sc); 816 eap_halt_input(sc); 817 818 sc->sc_pintr = 0; 819 sc->sc_rintr = 0; 820 } 821 822 int 823 eap_set_params(void *addr, int setmode, int usemode, 824 struct audio_params *play, struct audio_params *rec) 825 { 826 struct eap_softc *sc = addr; 827 struct audio_params *p; 828 int mode; 829 u_int32_t div; 830 831 /* 832 * The es1370 only has one clock, so make the sample rates match. 833 */ 834 if (!sc->sc_1371) { 835 if (play->sample_rate != rec->sample_rate && 836 usemode == (AUMODE_PLAY | AUMODE_RECORD)) { 837 if (setmode == AUMODE_PLAY) { 838 rec->sample_rate = play->sample_rate; 839 setmode |= AUMODE_RECORD; 840 } else if (setmode == AUMODE_RECORD) { 841 play->sample_rate = rec->sample_rate; 842 setmode |= AUMODE_PLAY; 843 } else 844 return (EINVAL); 845 } 846 } 847 848 for (mode = AUMODE_RECORD; mode != -1; 849 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) { 850 if ((setmode & mode) == 0) 851 continue; 852 853 p = mode == AUMODE_PLAY ? play : rec; 854 855 if (sc->sc_1371) 856 p->sample_rate = 48000; 857 if (p->sample_rate < 4000) 858 p->sample_rate = 4000; 859 if (p->sample_rate > 48000) 860 p->sample_rate = 48000; 861 if (p->precision > 16) 862 p->precision = 16; 863 if (p->channels > 2) 864 p->channels = 2; 865 switch (p->encoding) { 866 case AUDIO_ENCODING_SLINEAR_LE: 867 if (p->precision != 16) 868 return EINVAL; 869 break; 870 case AUDIO_ENCODING_ULINEAR_LE: 871 case AUDIO_ENCODING_ULINEAR_BE: 872 if (p->precision != 8) 873 return EINVAL; 874 default: 875 return (EINVAL); 876 } 877 p->bps = AUDIO_BPS(p->precision); 878 p->msb = 1; 879 } 880 881 if (!sc->sc_1371) { 882 /* Set the speed */ 883 DPRINTFN(2, ("eap_set_params: old ICSC = 0x%08x\n", 884 EREAD4(sc, EAP_ICSC))); 885 div = EREAD4(sc, EAP_ICSC) & ~EAP_PCLKBITS; 886 /* 887 * XXX 888 * The -2 isn't documented, but seemed to make the wall 889 * time match 890 * what I expect. - mycroft 891 */ 892 if (usemode == AUMODE_RECORD) 893 div |= EAP_SET_PCLKDIV(EAP_XTAL_FREQ / 894 rec->sample_rate - 2); 895 else 896 div |= EAP_SET_PCLKDIV(EAP_XTAL_FREQ / 897 play->sample_rate - 2); 898 div |= EAP_CCB_INTRM; 899 EWRITE4(sc, EAP_ICSC, div); 900 DPRINTFN(2, ("eap_set_params: set ICSC = 0x%08x\n", div)); 901 } 902 903 return (0); 904 } 905 906 int 907 eap_round_blocksize(void *addr, int blk) 908 { 909 return ((blk + 31) & -32); /* keep good alignment */ 910 } 911 912 int 913 eap_trigger_output( 914 void *addr, 915 void *start, 916 void *end, 917 int blksize, 918 void (*intr)(void *), 919 void *arg, 920 struct audio_params *param) 921 { 922 struct eap_softc *sc = addr; 923 struct eap_dma *p; 924 u_int32_t icsc, sic; 925 int sampshift; 926 927 #ifdef DIAGNOSTIC 928 if (sc->sc_prun) 929 panic("eap_trigger_output: already running"); 930 sc->sc_prun = 1; 931 #endif 932 933 DPRINTFN(1, ("eap_trigger_output: sc=%p start=%p end=%p " 934 "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg)); 935 sc->sc_pintr = intr; 936 sc->sc_parg = arg; 937 mtx_enter(&audio_lock); 938 sic = EREAD4(sc, EAP_SIC); 939 sic &= ~(EAP_P2_S_EB | EAP_P2_S_MB | EAP_INC_BITS); 940 sic |= EAP_SET_P2_ST_INC(0) | EAP_SET_P2_END_INC(param->precision / 8); 941 sampshift = 0; 942 if (param->precision == 16) { 943 sic |= EAP_P2_S_EB; 944 sampshift++; 945 } 946 if (param->channels == 2) { 947 sic |= EAP_P2_S_MB; 948 sampshift++; 949 } 950 EWRITE4(sc, EAP_SIC, sic & ~EAP_P2_INTR_EN); 951 EWRITE4(sc, EAP_SIC, sic | EAP_P2_INTR_EN); 952 953 for (p = sc->sc_dmas; p && KERNADDR(p) != start; p = p->next) 954 ; 955 if (!p) { 956 mtx_leave(&audio_lock); 957 printf("eap_trigger_output: bad addr %p\n", start); 958 return (EINVAL); 959 } 960 961 DPRINTF(("eap_trigger_output: DAC2_ADDR=0x%x, DAC2_SIZE=0x%x\n", 962 (int)DMAADDR(p), 963 (int)EAP_SET_SIZE(0, (((char *)end - (char *)start) >> 2) - 1))); 964 EWRITE4(sc, EAP_MEMPAGE, EAP_DAC_PAGE); 965 EWRITE4(sc, EAP_DAC2_ADDR, DMAADDR(p)); 966 EWRITE4(sc, EAP_DAC2_SIZE, 967 EAP_SET_SIZE(0, (((char *)end - (char *)start) >> 2) - 1)); 968 969 EWRITE4(sc, EAP_DAC2_CSR, (blksize >> sampshift) - 1); 970 971 if (sc->sc_1371) 972 EWRITE4(sc, E1371_SRC, 0); 973 974 icsc = EREAD4(sc, EAP_ICSC); 975 EWRITE4(sc, EAP_ICSC, icsc | EAP_DAC2_EN); 976 977 DPRINTFN(1, ("eap_trigger_output: set ICSC = 0x%08x\n", icsc)); 978 mtx_leave(&audio_lock); 979 return (0); 980 } 981 982 int 983 eap_trigger_input( 984 void *addr, 985 void *start, 986 void *end, 987 int blksize, 988 void (*intr)(void *), 989 void *arg, 990 struct audio_params *param) 991 { 992 struct eap_softc *sc = addr; 993 struct eap_dma *p; 994 u_int32_t icsc, sic; 995 int sampshift; 996 997 #ifdef DIAGNOSTIC 998 if (sc->sc_rrun) 999 panic("eap_trigger_input: already running"); 1000 sc->sc_rrun = 1; 1001 #endif 1002 1003 DPRINTFN(1, ("eap_trigger_input: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n", 1004 addr, start, end, blksize, intr, arg)); 1005 sc->sc_rintr = intr; 1006 sc->sc_rarg = arg; 1007 mtx_enter(&audio_lock); 1008 sic = EREAD4(sc, EAP_SIC); 1009 sic &= ~(EAP_R1_S_EB | EAP_R1_S_MB); 1010 sampshift = 0; 1011 if (param->precision == 16) { 1012 sic |= EAP_R1_S_EB; 1013 sampshift++; 1014 } 1015 if (param->channels == 2) { 1016 sic |= EAP_R1_S_MB; 1017 sampshift++; 1018 } 1019 EWRITE4(sc, EAP_SIC, sic & ~EAP_R1_INTR_EN); 1020 EWRITE4(sc, EAP_SIC, sic | EAP_R1_INTR_EN); 1021 1022 for (p = sc->sc_dmas; p && KERNADDR(p) != start; p = p->next) 1023 ; 1024 if (!p) { 1025 mtx_leave(&audio_lock); 1026 printf("eap_trigger_input: bad addr %p\n", start); 1027 return (EINVAL); 1028 } 1029 1030 DPRINTF(("eap_trigger_input: ADC_ADDR=0x%x, ADC_SIZE=0x%x\n", 1031 (int)DMAADDR(p), 1032 (int)EAP_SET_SIZE(0, (((char *)end - (char *)start) >> 2) - 1))); 1033 EWRITE4(sc, EAP_MEMPAGE, EAP_ADC_PAGE); 1034 EWRITE4(sc, EAP_ADC_ADDR, DMAADDR(p)); 1035 EWRITE4(sc, EAP_ADC_SIZE, 1036 EAP_SET_SIZE(0, (((char *)end - (char *)start) >> 2) - 1)); 1037 1038 EWRITE4(sc, EAP_ADC_CSR, (blksize >> sampshift) - 1); 1039 1040 if (sc->sc_1371) 1041 EWRITE4(sc, E1371_SRC, 0); 1042 1043 icsc = EREAD4(sc, EAP_ICSC); 1044 EWRITE4(sc, EAP_ICSC, icsc | EAP_ADC_EN); 1045 1046 DPRINTFN(1, ("eap_trigger_input: set ICSC = 0x%08x\n", icsc)); 1047 mtx_leave(&audio_lock); 1048 return (0); 1049 } 1050 1051 int 1052 eap_halt_output(void *addr) 1053 { 1054 struct eap_softc *sc = addr; 1055 u_int32_t icsc; 1056 1057 DPRINTF(("eap: eap_halt_output\n")); 1058 mtx_enter(&audio_lock); 1059 icsc = EREAD4(sc, EAP_ICSC); 1060 EWRITE4(sc, EAP_ICSC, icsc & ~EAP_DAC2_EN); 1061 #ifdef DIAGNOSTIC 1062 sc->sc_prun = 0; 1063 #endif 1064 mtx_leave(&audio_lock); 1065 return (0); 1066 } 1067 1068 int 1069 eap_halt_input(void *addr) 1070 { 1071 struct eap_softc *sc = addr; 1072 u_int32_t icsc; 1073 1074 DPRINTF(("eap: eap_halt_input\n")); 1075 mtx_enter(&audio_lock); 1076 icsc = EREAD4(sc, EAP_ICSC); 1077 EWRITE4(sc, EAP_ICSC, icsc & ~EAP_ADC_EN); 1078 #ifdef DIAGNOSTIC 1079 sc->sc_rrun = 0; 1080 #endif 1081 mtx_leave(&audio_lock); 1082 return (0); 1083 } 1084 1085 int 1086 eap1371_mixer_set_port(void *addr, mixer_ctrl_t *cp) 1087 { 1088 struct eap_softc *sc = addr; 1089 1090 return (sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp)); 1091 } 1092 1093 int 1094 eap1371_mixer_get_port(void *addr, mixer_ctrl_t *cp) 1095 { 1096 struct eap_softc *sc = addr; 1097 1098 return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp)); 1099 } 1100 1101 int 1102 eap1371_query_devinfo(void *addr, mixer_devinfo_t *dip) 1103 { 1104 struct eap_softc *sc = addr; 1105 1106 return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, dip)); 1107 } 1108 1109 void 1110 eap1370_set_mixer(struct eap_softc *sc, int a, int d) 1111 { 1112 eap1370_write_codec(sc, a, d); 1113 1114 sc->sc_port[a] = d; 1115 DPRINTFN(1, ("eap1370_mixer_set_port port 0x%02x = 0x%02x\n", a, d)); 1116 } 1117 1118 int 1119 eap1370_mixer_set_port(void *addr, mixer_ctrl_t *cp) 1120 { 1121 struct eap_softc *sc = addr; 1122 int lval, rval, l, r, la, ra; 1123 int l1, r1, l2, r2, m, o1, o2; 1124 1125 if (cp->dev == EAP_RECORD_SOURCE) { 1126 if (cp->type != AUDIO_MIXER_SET) 1127 return (EINVAL); 1128 m = sc->sc_record_source = cp->un.mask; 1129 l1 = l2 = r1 = r2 = 0; 1130 if (m & (1 << EAP_VOICE_VOL)) 1131 l2 |= AK_M_VOICE, r2 |= AK_M_VOICE; 1132 if (m & (1 << EAP_FM_VOL)) 1133 l1 |= AK_M_FM_L, r1 |= AK_M_FM_R; 1134 if (m & (1 << EAP_CD_VOL)) 1135 l1 |= AK_M_CD_L, r1 |= AK_M_CD_R; 1136 if (m & (1 << EAP_LINE_VOL)) 1137 l1 |= AK_M_LINE_L, r1 |= AK_M_LINE_R; 1138 if (m & (1 << EAP_AUX_VOL)) 1139 l2 |= AK_M2_AUX_L, r2 |= AK_M2_AUX_R; 1140 if (m & (1 << EAP_MIC_VOL)) 1141 l2 |= AK_M_TMIC, r2 |= AK_M_TMIC; 1142 eap1370_set_mixer(sc, AK_IN_MIXER1_L, l1); 1143 eap1370_set_mixer(sc, AK_IN_MIXER1_R, r1); 1144 eap1370_set_mixer(sc, AK_IN_MIXER2_L, l2); 1145 eap1370_set_mixer(sc, AK_IN_MIXER2_R, r2); 1146 return (0); 1147 } 1148 if (cp->dev == EAP_INPUT_SOURCE) { 1149 if (cp->type != AUDIO_MIXER_SET) 1150 return (EINVAL); 1151 m = sc->sc_input_source = cp->un.mask; 1152 o1 = o2 = 0; 1153 if (m & (1 << EAP_VOICE_VOL)) 1154 o2 |= AK_M_VOICE_L | AK_M_VOICE_R; 1155 if (m & (1 << EAP_FM_VOL)) 1156 o1 |= AK_M_FM_L | AK_M_FM_R; 1157 if (m & (1 << EAP_CD_VOL)) 1158 o1 |= AK_M_CD_L | AK_M_CD_R; 1159 if (m & (1 << EAP_LINE_VOL)) 1160 o1 |= AK_M_LINE_L | AK_M_LINE_R; 1161 if (m & (1 << EAP_AUX_VOL)) 1162 o2 |= AK_M_AUX_L | AK_M_AUX_R; 1163 if (m & (1 << EAP_MIC_VOL)) 1164 o1 |= AK_M_MIC; 1165 eap1370_set_mixer(sc, AK_OUT_MIXER1, o1); 1166 eap1370_set_mixer(sc, AK_OUT_MIXER2, o2); 1167 return (0); 1168 } 1169 if (cp->dev == EAP_MIC_PREAMP) { 1170 if (cp->type != AUDIO_MIXER_ENUM) 1171 return (EINVAL); 1172 if (cp->un.ord != 0 && cp->un.ord != 1) 1173 return (EINVAL); 1174 sc->sc_mic_preamp = cp->un.ord; 1175 eap1370_set_mixer(sc, AK_MGAIN, cp->un.ord); 1176 return (0); 1177 } 1178 if (cp->type != AUDIO_MIXER_VALUE) 1179 return (EINVAL); 1180 if (cp->un.value.num_channels == 1) 1181 lval = rval = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 1182 else if (cp->un.value.num_channels == 2) { 1183 lval = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 1184 rval = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 1185 } else 1186 return (EINVAL); 1187 ra = -1; 1188 switch (cp->dev) { 1189 case EAP_MASTER_VOL: 1190 l = VOL_TO_ATT5(lval); 1191 r = VOL_TO_ATT5(rval); 1192 la = AK_MASTER_L; 1193 ra = AK_MASTER_R; 1194 break; 1195 case EAP_MIC_VOL: 1196 if (cp->un.value.num_channels != 1) 1197 return (EINVAL); 1198 la = AK_MIC; 1199 goto lr; 1200 case EAP_VOICE_VOL: 1201 la = AK_VOICE_L; 1202 ra = AK_VOICE_R; 1203 goto lr; 1204 case EAP_FM_VOL: 1205 la = AK_FM_L; 1206 ra = AK_FM_R; 1207 goto lr; 1208 case EAP_CD_VOL: 1209 la = AK_CD_L; 1210 ra = AK_CD_R; 1211 goto lr; 1212 case EAP_LINE_VOL: 1213 la = AK_LINE_L; 1214 ra = AK_LINE_R; 1215 goto lr; 1216 case EAP_AUX_VOL: 1217 la = AK_AUX_L; 1218 ra = AK_AUX_R; 1219 lr: 1220 l = VOL_TO_GAIN5(lval); 1221 r = VOL_TO_GAIN5(rval); 1222 break; 1223 default: 1224 return (EINVAL); 1225 } 1226 eap1370_set_mixer(sc, la, l); 1227 if (ra >= 0) { 1228 eap1370_set_mixer(sc, ra, r); 1229 } 1230 return (0); 1231 } 1232 1233 int 1234 eap1370_mixer_get_port(void *addr, mixer_ctrl_t *cp) 1235 { 1236 struct eap_softc *sc = addr; 1237 int la, ra, l, r; 1238 1239 switch (cp->dev) { 1240 case EAP_RECORD_SOURCE: 1241 if (cp->type != AUDIO_MIXER_SET) 1242 return (EINVAL); 1243 cp->un.mask = sc->sc_record_source; 1244 return (0); 1245 case EAP_INPUT_SOURCE: 1246 if (cp->type != AUDIO_MIXER_SET) 1247 return (EINVAL); 1248 cp->un.mask = sc->sc_input_source; 1249 return (0); 1250 case EAP_MIC_PREAMP: 1251 if (cp->type != AUDIO_MIXER_ENUM) 1252 return (EINVAL); 1253 cp->un.ord = sc->sc_mic_preamp; 1254 return (0); 1255 case EAP_MASTER_VOL: 1256 l = ATT5_TO_VOL(sc->sc_port[AK_MASTER_L]); 1257 r = ATT5_TO_VOL(sc->sc_port[AK_MASTER_R]); 1258 break; 1259 case EAP_MIC_VOL: 1260 if (cp->un.value.num_channels != 1) 1261 return (EINVAL); 1262 la = ra = AK_MIC; 1263 goto lr; 1264 case EAP_VOICE_VOL: 1265 la = AK_VOICE_L; 1266 ra = AK_VOICE_R; 1267 goto lr; 1268 case EAP_FM_VOL: 1269 la = AK_FM_L; 1270 ra = AK_FM_R; 1271 goto lr; 1272 case EAP_CD_VOL: 1273 la = AK_CD_L; 1274 ra = AK_CD_R; 1275 goto lr; 1276 case EAP_LINE_VOL: 1277 la = AK_LINE_L; 1278 ra = AK_LINE_R; 1279 goto lr; 1280 case EAP_AUX_VOL: 1281 la = AK_AUX_L; 1282 ra = AK_AUX_R; 1283 lr: 1284 l = GAIN5_TO_VOL(sc->sc_port[la]); 1285 r = GAIN5_TO_VOL(sc->sc_port[ra]); 1286 break; 1287 default: 1288 return (EINVAL); 1289 } 1290 if (cp->un.value.num_channels == 1) 1291 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = (l+r) / 2; 1292 else if (cp->un.value.num_channels == 2) { 1293 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l; 1294 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r; 1295 } else 1296 return (EINVAL); 1297 return (0); 1298 } 1299 1300 int 1301 eap1370_query_devinfo(void *addr, mixer_devinfo_t *dip) 1302 { 1303 switch (dip->index) { 1304 case EAP_MASTER_VOL: 1305 dip->type = AUDIO_MIXER_VALUE; 1306 dip->mixer_class = EAP_OUTPUT_CLASS; 1307 dip->prev = dip->next = AUDIO_MIXER_LAST; 1308 strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name); 1309 dip->un.v.num_channels = 2; 1310 strlcpy(dip->un.v.units.name, AudioNvolume, 1311 sizeof dip->un.v.units.name); 1312 return (0); 1313 case EAP_VOICE_VOL: 1314 dip->type = AUDIO_MIXER_VALUE; 1315 dip->mixer_class = EAP_INPUT_CLASS; 1316 dip->prev = AUDIO_MIXER_LAST; 1317 dip->next = AUDIO_MIXER_LAST; 1318 strlcpy(dip->label.name, AudioNdac, sizeof dip->label.name); 1319 dip->un.v.num_channels = 2; 1320 strlcpy(dip->un.v.units.name, AudioNvolume, 1321 sizeof dip->un.v.units.name); 1322 return (0); 1323 case EAP_FM_VOL: 1324 dip->type = AUDIO_MIXER_VALUE; 1325 dip->mixer_class = EAP_INPUT_CLASS; 1326 dip->prev = AUDIO_MIXER_LAST; 1327 dip->next = AUDIO_MIXER_LAST; 1328 strlcpy(dip->label.name, AudioNfmsynth, 1329 sizeof dip->label.name); 1330 dip->un.v.num_channels = 2; 1331 strlcpy(dip->un.v.units.name, AudioNvolume, 1332 sizeof dip->un.v.units.name); 1333 return (0); 1334 case EAP_CD_VOL: 1335 dip->type = AUDIO_MIXER_VALUE; 1336 dip->mixer_class = EAP_INPUT_CLASS; 1337 dip->prev = AUDIO_MIXER_LAST; 1338 dip->next = AUDIO_MIXER_LAST; 1339 strlcpy(dip->label.name, AudioNcd, sizeof dip->label.name); 1340 dip->un.v.num_channels = 2; 1341 strlcpy(dip->un.v.units.name, AudioNvolume, 1342 sizeof dip->un.v.units.name); 1343 return (0); 1344 case EAP_LINE_VOL: 1345 dip->type = AUDIO_MIXER_VALUE; 1346 dip->mixer_class = EAP_INPUT_CLASS; 1347 dip->prev = AUDIO_MIXER_LAST; 1348 dip->next = AUDIO_MIXER_LAST; 1349 strlcpy(dip->label.name, AudioNline, sizeof dip->label.name); 1350 dip->un.v.num_channels = 2; 1351 strlcpy(dip->un.v.units.name, AudioNvolume, 1352 sizeof dip->un.v.units.name); 1353 return (0); 1354 case EAP_AUX_VOL: 1355 dip->type = AUDIO_MIXER_VALUE; 1356 dip->mixer_class = EAP_INPUT_CLASS; 1357 dip->prev = AUDIO_MIXER_LAST; 1358 dip->next = AUDIO_MIXER_LAST; 1359 strlcpy(dip->label.name, AudioNaux, sizeof dip->label.name); 1360 dip->un.v.num_channels = 2; 1361 strlcpy(dip->un.v.units.name, AudioNvolume, 1362 sizeof dip->un.v.units.name); 1363 return (0); 1364 case EAP_MIC_VOL: 1365 dip->type = AUDIO_MIXER_VALUE; 1366 dip->mixer_class = EAP_INPUT_CLASS; 1367 dip->prev = AUDIO_MIXER_LAST; 1368 dip->next = EAP_MIC_PREAMP; 1369 strlcpy(dip->label.name, AudioNmicrophone, 1370 sizeof dip->label.name); 1371 dip->un.v.num_channels = 1; 1372 strlcpy(dip->un.v.units.name, AudioNvolume, 1373 sizeof dip->un.v.units.name); 1374 return (0); 1375 case EAP_RECORD_SOURCE: 1376 dip->mixer_class = EAP_RECORD_CLASS; 1377 dip->prev = dip->next = AUDIO_MIXER_LAST; 1378 strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name); 1379 dip->type = AUDIO_MIXER_SET; 1380 dip->un.s.num_mem = 6; 1381 strlcpy(dip->un.s.member[0].label.name, AudioNmicrophone, 1382 sizeof dip->un.s.member[0].label.name); 1383 dip->un.s.member[0].mask = 1 << EAP_MIC_VOL; 1384 strlcpy(dip->un.s.member[1].label.name, AudioNcd, 1385 sizeof dip->un.s.member[1].label.name); 1386 dip->un.s.member[1].mask = 1 << EAP_CD_VOL; 1387 strlcpy(dip->un.s.member[2].label.name, AudioNline, 1388 sizeof dip->un.s.member[2].label.name); 1389 dip->un.s.member[2].mask = 1 << EAP_LINE_VOL; 1390 strlcpy(dip->un.s.member[3].label.name, AudioNfmsynth, 1391 sizeof dip->un.s.member[3].label.name); 1392 dip->un.s.member[3].mask = 1 << EAP_FM_VOL; 1393 strlcpy(dip->un.s.member[4].label.name, AudioNaux, 1394 sizeof dip->un.s.member[4].label.name); 1395 dip->un.s.member[4].mask = 1 << EAP_AUX_VOL; 1396 strlcpy(dip->un.s.member[5].label.name, AudioNdac, 1397 sizeof dip->un.s.member[5].label.name); 1398 dip->un.s.member[5].mask = 1 << EAP_VOICE_VOL; 1399 return (0); 1400 case EAP_INPUT_SOURCE: 1401 dip->mixer_class = EAP_INPUT_CLASS; 1402 dip->prev = dip->next = AUDIO_MIXER_LAST; 1403 strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name); 1404 dip->type = AUDIO_MIXER_SET; 1405 dip->un.s.num_mem = 6; 1406 strlcpy(dip->un.s.member[0].label.name, AudioNmicrophone, 1407 sizeof dip->un.s.member[0].label.name); 1408 dip->un.s.member[0].mask = 1 << EAP_MIC_VOL; 1409 strlcpy(dip->un.s.member[1].label.name, AudioNcd, 1410 sizeof dip->un.s.member[1].label.name); 1411 dip->un.s.member[1].mask = 1 << EAP_CD_VOL; 1412 strlcpy(dip->un.s.member[2].label.name, AudioNline, 1413 sizeof dip->un.s.member[2].label.name); 1414 dip->un.s.member[2].mask = 1 << EAP_LINE_VOL; 1415 strlcpy(dip->un.s.member[3].label.name, AudioNfmsynth, 1416 sizeof dip->un.s.member[3].label.name); 1417 dip->un.s.member[3].mask = 1 << EAP_FM_VOL; 1418 strlcpy(dip->un.s.member[4].label.name, AudioNaux, 1419 sizeof dip->un.s.member[4].label.name); 1420 dip->un.s.member[4].mask = 1 << EAP_AUX_VOL; 1421 strlcpy(dip->un.s.member[5].label.name, AudioNdac, 1422 sizeof dip->un.s.member[5].label.name); 1423 dip->un.s.member[5].mask = 1 << EAP_VOICE_VOL; 1424 return (0); 1425 case EAP_MIC_PREAMP: 1426 dip->type = AUDIO_MIXER_ENUM; 1427 dip->mixer_class = EAP_INPUT_CLASS; 1428 dip->prev = EAP_MIC_VOL; 1429 dip->next = AUDIO_MIXER_LAST; 1430 strlcpy(dip->label.name, AudioNpreamp, sizeof dip->label.name); 1431 dip->un.e.num_mem = 2; 1432 strlcpy(dip->un.e.member[0].label.name, AudioNoff, 1433 sizeof dip->un.e.member[0].label.name); 1434 dip->un.e.member[0].ord = 0; 1435 strlcpy(dip->un.e.member[1].label.name, AudioNon, 1436 sizeof dip->un.e.member[1].label.name); 1437 dip->un.e.member[1].ord = 1; 1438 return (0); 1439 case EAP_OUTPUT_CLASS: 1440 dip->type = AUDIO_MIXER_CLASS; 1441 dip->mixer_class = EAP_OUTPUT_CLASS; 1442 dip->next = dip->prev = AUDIO_MIXER_LAST; 1443 strlcpy(dip->label.name, AudioCoutputs, 1444 sizeof dip->label.name); 1445 return (0); 1446 case EAP_RECORD_CLASS: 1447 dip->type = AUDIO_MIXER_CLASS; 1448 dip->mixer_class = EAP_RECORD_CLASS; 1449 dip->next = dip->prev = AUDIO_MIXER_LAST; 1450 strlcpy(dip->label.name, AudioCrecord, sizeof dip->label.name); 1451 return (0); 1452 case EAP_INPUT_CLASS: 1453 dip->type = AUDIO_MIXER_CLASS; 1454 dip->mixer_class = EAP_INPUT_CLASS; 1455 dip->next = dip->prev = AUDIO_MIXER_LAST; 1456 strlcpy(dip->label.name, AudioCinputs, sizeof dip->label.name); 1457 return (0); 1458 } 1459 return (ENXIO); 1460 } 1461 1462 void * 1463 eap_malloc(void *addr, int direction, size_t size, int pool, int flags) 1464 { 1465 struct eap_softc *sc = addr; 1466 struct eap_dma *p; 1467 int error; 1468 1469 p = malloc(sizeof(*p), pool, flags); 1470 if (!p) 1471 return (0); 1472 error = eap_allocmem(sc, size, 16, p); 1473 if (error) { 1474 free(p, pool, sizeof(*p)); 1475 return (0); 1476 } 1477 p->next = sc->sc_dmas; 1478 sc->sc_dmas = p; 1479 return (KERNADDR(p)); 1480 } 1481 1482 void 1483 eap_free(void *addr, void *ptr, int pool) 1484 { 1485 struct eap_softc *sc = addr; 1486 struct eap_dma **pp, *p; 1487 1488 for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) { 1489 if (KERNADDR(p) == ptr) { 1490 eap_freemem(sc, p); 1491 *pp = p->next; 1492 free(p, pool, sizeof(*p)); 1493 return; 1494 } 1495 } 1496 } 1497 1498 int 1499 eap_get_props(void *addr) 1500 { 1501 return (AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | 1502 AUDIO_PROP_FULLDUPLEX); 1503 } 1504 1505 enum ac97_host_flags 1506 eap_flags_codec(void *v) 1507 { 1508 struct eap_softc *sc = v; 1509 1510 return (sc->flags); 1511 } 1512 #if NMIDI > 0 1513 int 1514 eap_midi_open(void *addr, int flags, 1515 void (*iintr)(void *, int), 1516 void (*ointr)(void *), 1517 void *arg) 1518 { 1519 struct eap_softc *sc = addr; 1520 1521 sc->sc_iintr = iintr; 1522 sc->sc_ointr = ointr; 1523 sc->sc_arg = arg; 1524 1525 EWRITE4(sc, EAP_ICSC, EREAD4(sc, EAP_ICSC) | EAP_UART_EN); 1526 sc->sc_uctrl = 0; 1527 if (flags & FREAD) 1528 sc->sc_uctrl |= EAP_UC_RXINTEN; 1529 EWRITE1(sc, EAP_UART_CONTROL, sc->sc_uctrl); 1530 1531 return (0); 1532 } 1533 1534 void 1535 eap_midi_close(void *addr) 1536 { 1537 struct eap_softc *sc = addr; 1538 1539 /* give uart a chance to drain */ 1540 tsleep_nsec(sc, PWAIT, "eapclm", MSEC_TO_NSEC(100)); 1541 1542 EWRITE1(sc, EAP_UART_CONTROL, 0); 1543 EWRITE4(sc, EAP_ICSC, EREAD4(sc, EAP_ICSC) & ~EAP_UART_EN); 1544 1545 sc->sc_iintr = 0; 1546 sc->sc_ointr = 0; 1547 } 1548 1549 int 1550 eap_midi_output(void *addr, int d) 1551 { 1552 struct eap_softc *sc = addr; 1553 1554 if (!(EREAD1(sc, EAP_UART_STATUS) & EAP_US_TXRDY)) 1555 return 0; 1556 EWRITE1(sc, EAP_UART_DATA, d); 1557 sc->sc_uctrl |= EAP_UC_TXINTEN; 1558 EWRITE1(sc, EAP_UART_CONTROL, sc->sc_uctrl); 1559 return 1; 1560 } 1561 1562 void 1563 eap_midi_getinfo(void *addr, struct midi_info *mi) 1564 { 1565 mi->name = "AudioPCI MIDI UART"; 1566 mi->props = MIDI_PROP_CAN_INPUT | MIDI_PROP_OUT_INTR; 1567 } 1568 1569 #endif 1570