1 /* $OpenBSD: ce4231.c,v 1.36 2018/12/27 11:06:38 claudio Exp $ */ 2 3 /* 4 * Copyright (c) 1999 Jason L. Wright (jason@thought.net) 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* 30 * Driver for CS4231 based audio found in some sun4u systems (cs4231) 31 * based on ideas from the S/Linux project and the NetBSD project. 32 * 33 * Effort sponsored in part by the Defense Advanced Research Projects 34 * Agency (DARPA) and Air Force Research Laboratory, Air Force 35 * Materiel Command, USAF, under agreement number F30602-01-2-0537. 36 * 37 */ 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/errno.h> 42 #include <sys/ioctl.h> 43 #include <sys/device.h> 44 #include <sys/proc.h> 45 #include <sys/malloc.h> 46 47 #include <machine/cpu.h> 48 #include <machine/bus.h> 49 #include <machine/intr.h> 50 #include <machine/autoconf.h> 51 52 #include <sys/audioio.h> 53 #include <dev/audio_if.h> 54 55 #include <sparc64/dev/ebusreg.h> 56 #include <sparc64/dev/ebusvar.h> 57 #include <sparc64/dev/ce4231var.h> 58 59 /* AD1418 provides basic registers, CS4231 extends with more */ 60 #include <dev/ic/ad1848reg.h> 61 #include <dev/ic/cs4231reg.h> 62 63 /* Mixer classes and mixer knobs */ 64 #define CSAUDIO_INPUT_CLASS 0 65 #define CSAUDIO_OUTPUT_CLASS 1 66 #define CSAUDIO_RECORD_CLASS 2 67 #define CSAUDIO_DAC_LVL 3 68 #define CSAUDIO_DAC_MUTE 4 69 #define CSAUDIO_OUTPUTS 5 70 #define CSAUDIO_CD_LVL 6 71 #define CSAUDIO_CD_MUTE 7 72 #define CSAUDIO_LINE_IN_LVL 8 73 #define CSAUDIO_LINE_IN_MUTE 9 74 #define CSAUDIO_MONITOR_LVL 10 75 #define CSAUDIO_MONITOR_MUTE 11 76 #define CSAUDIO_REC_LVL 12 77 #define CSAUDIO_RECORD_SOURCE 13 78 #define CSAUDIO_MIC_PREAMP 14 79 80 /* Recording sources */ 81 #define REC_PORT_LINE 0 82 #define REC_PORT_CD 1 83 #define REC_PORT_MIC 2 84 #define REC_PORT_MIX 3 85 86 /* Output ports. */ 87 #define OUT_PORT_LINE 0x1 88 #define OUT_PORT_HP 0x2 89 #define OUT_PORT_SPKR 0x4 90 91 /* Bits on the ADC reg that determine recording source */ 92 #define CS_REC_SRC_BITS 0xc0 93 94 #ifdef AUDIO_DEBUG 95 #define DPRINTF(x) printf x 96 #else 97 #define DPRINTF(x) 98 #endif 99 100 #define CS_TIMEOUT 90000 101 102 /* Read/write CS4231 direct registers */ 103 #define CS_WRITE(sc,r,v) \ 104 bus_space_write_1((sc)->sc_bustag, (sc)->sc_cshandle, (r) << 2, (v)) 105 #define CS_READ(sc,r) \ 106 bus_space_read_1((sc)->sc_bustag, (sc)->sc_cshandle, (r) << 2) 107 108 /* Read/write EBDMA playback registers */ 109 #define P_WRITE(sc,r,v) \ 110 bus_space_write_4((sc)->sc_bustag, (sc)->sc_pdmahandle, (r), (v)) 111 #define P_READ(sc,r) \ 112 bus_space_read_4((sc)->sc_bustag, (sc)->sc_pdmahandle, (r)) 113 114 /* Read/write EBDMA capture registers */ 115 #define C_WRITE(sc,r,v) \ 116 bus_space_write_4((sc)->sc_bustag, (sc)->sc_cdmahandle, (r), (v)) 117 #define C_READ(sc,r) \ 118 bus_space_read_4((sc)->sc_bustag, (sc)->sc_cdmahandle, (r)) 119 120 int ce4231_match(struct device *, void *, void *); 121 void ce4231_attach(struct device *, struct device *, void *); 122 int ce4231_cintr(void *); 123 int ce4231_pintr(void *); 124 125 int ce4231_set_speed(struct ce4231_softc *, u_long *); 126 127 void ce4231_set_outputs(struct ce4231_softc *, int); 128 int ce4231_get_outputs(struct ce4231_softc *); 129 130 void ce4231_write(struct ce4231_softc *, u_int8_t, u_int8_t); 131 u_int8_t ce4231_read(struct ce4231_softc *, u_int8_t); 132 133 /* Audio interface */ 134 int ce4231_open(void *, int); 135 void ce4231_close(void *); 136 int ce4231_set_params(void *, int, int, struct audio_params *, 137 struct audio_params *); 138 int ce4231_round_blocksize(void *, int); 139 int ce4231_commit_settings(void *); 140 int ce4231_halt_output(void *); 141 int ce4231_halt_input(void *); 142 int ce4231_set_port(void *, mixer_ctrl_t *); 143 int ce4231_get_port(void *, mixer_ctrl_t *); 144 int ce4231_query_devinfo(void *addr, mixer_devinfo_t *); 145 void * ce4231_alloc(void *, int, size_t, int, int); 146 void ce4231_free(void *, void *, int); 147 int ce4231_get_props(void *); 148 int ce4231_trigger_output(void *, void *, void *, int, 149 void (*intr)(void *), void *arg, struct audio_params *); 150 int ce4231_trigger_input(void *, void *, void *, int, 151 void (*intr)(void *), void *arg, struct audio_params *); 152 153 struct audio_hw_if ce4231_sa_hw_if = { 154 ce4231_open, 155 ce4231_close, 156 ce4231_set_params, 157 ce4231_round_blocksize, 158 ce4231_commit_settings, 159 0, 160 0, 161 0, 162 0, 163 ce4231_halt_output, 164 ce4231_halt_input, 165 0, 166 0, 167 ce4231_set_port, 168 ce4231_get_port, 169 ce4231_query_devinfo, 170 ce4231_alloc, 171 ce4231_free, 172 0, 173 ce4231_get_props, 174 ce4231_trigger_output, 175 ce4231_trigger_input 176 }; 177 178 struct cfattach audioce_ca = { 179 sizeof (struct ce4231_softc), ce4231_match, ce4231_attach 180 }; 181 182 struct cfdriver audioce_cd = { 183 NULL, "audioce", DV_DULL 184 }; 185 186 int 187 ce4231_match(struct device *parent, void *vcf, void *aux) 188 { 189 struct ebus_attach_args *ea = aux; 190 191 if (!strcmp("SUNW,CS4231", ea->ea_name) || 192 !strcmp("audio", ea->ea_name)) 193 return (1); 194 return (0); 195 } 196 197 void 198 ce4231_attach(struct device *parent, struct device *self, void *aux) 199 { 200 struct ebus_attach_args *ea = aux; 201 struct ce4231_softc *sc = (struct ce4231_softc *)self; 202 mixer_ctrl_t cp; 203 int node; 204 205 node = ea->ea_node; 206 207 sc->sc_last_format = 0xffffffff; 208 209 /* Pass on the bus tags */ 210 sc->sc_bustag = ea->ea_memtag; 211 sc->sc_dmatag = ea->ea_dmatag; 212 213 /* Make sure things are sane. */ 214 if (ea->ea_nintrs != 2) { 215 printf(": expected 2 interrupts, got %d\n", ea->ea_nintrs); 216 return; 217 } 218 if (ea->ea_nregs != 4) { 219 printf(": expected 4 register set, got %d\n", 220 ea->ea_nregs); 221 return; 222 } 223 224 sc->sc_cih = bus_intr_establish(sc->sc_bustag, ea->ea_intrs[0], 225 IPL_AUDIO, BUS_INTR_ESTABLISH_MPSAFE, ce4231_cintr, 226 sc, self->dv_xname); 227 if (sc->sc_cih == NULL) { 228 printf(": couldn't establish capture interrupt\n"); 229 return; 230 } 231 sc->sc_pih = bus_intr_establish(sc->sc_bustag, ea->ea_intrs[1], 232 IPL_AUDIO, BUS_INTR_ESTABLISH_MPSAFE, ce4231_pintr, 233 sc, self->dv_xname); 234 if (sc->sc_pih == NULL) { 235 printf(": couldn't establish play interrupt1\n"); 236 return; 237 } 238 239 /* XXX what if prom has already mapped?! */ 240 241 if (ebus_bus_map(sc->sc_bustag, 0, 242 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), ea->ea_regs[0].size, 243 BUS_SPACE_MAP_LINEAR, 0, &sc->sc_cshandle) != 0) { 244 printf(": couldn't map cs4231 registers\n"); 245 return; 246 } 247 248 if (ebus_bus_map(sc->sc_bustag, 0, 249 EBUS_PADDR_FROM_REG(&ea->ea_regs[1]), ea->ea_regs[1].size, 250 BUS_SPACE_MAP_LINEAR, 0, &sc->sc_pdmahandle) != 0) { 251 printf(": couldn't map dma1 registers\n"); 252 return; 253 } 254 255 if (ebus_bus_map(sc->sc_bustag, 0, 256 EBUS_PADDR_FROM_REG(&ea->ea_regs[2]), ea->ea_regs[2].size, 257 BUS_SPACE_MAP_LINEAR, 0, &sc->sc_cdmahandle) != 0) { 258 printf(": couldn't map dma2 registers\n"); 259 return; 260 } 261 262 if (ebus_bus_map(sc->sc_bustag, 0, 263 EBUS_PADDR_FROM_REG(&ea->ea_regs[3]), ea->ea_regs[3].size, 264 BUS_SPACE_MAP_LINEAR, 0, &sc->sc_auxhandle) != 0) { 265 printf(": couldn't map aux registers\n"); 266 return; 267 } 268 269 printf(": nvaddrs %d\n", ea->ea_nvaddrs); 270 271 audio_attach_mi(&ce4231_sa_hw_if, sc, &sc->sc_dev); 272 273 /* Enable mode 2. */ 274 ce4231_write(sc, SP_MISC_INFO, ce4231_read(sc, SP_MISC_INFO) | MODE2); 275 276 /* Attenuate DAC, CD and line-in. -22.5 dB for all. */ 277 cp.dev = CSAUDIO_DAC_LVL; 278 cp.type = AUDIO_MIXER_VALUE; 279 cp.un.value.num_channels = 2; 280 cp.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 195; 281 cp.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 195; 282 ce4231_set_port(sc, &cp); 283 284 cp.dev = CSAUDIO_CD_LVL; 285 cp.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 135; 286 cp.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 135; 287 ce4231_set_port(sc, &cp); 288 289 cp.dev = CSAUDIO_LINE_IN_LVL; 290 ce4231_set_port(sc, &cp); 291 292 /* Unmute DAC, CD and line-in */ 293 cp.dev = CSAUDIO_DAC_MUTE; 294 cp.type = AUDIO_MIXER_ENUM; 295 cp.un.ord = 0; 296 ce4231_set_port(sc, &cp); 297 298 cp.dev = CSAUDIO_CD_MUTE; 299 ce4231_set_port(sc, &cp); 300 301 cp.dev = CSAUDIO_LINE_IN_MUTE; 302 ce4231_set_port(sc, &cp); 303 304 /* XXX get real burst... */ 305 sc->sc_burst = EBDCSR_BURST_8; 306 } 307 308 /* 309 * Write to one of the indexed registers of cs4231. 310 */ 311 void 312 ce4231_write(struct ce4231_softc *sc, u_int8_t r, u_int8_t v) 313 { 314 CS_WRITE(sc, AD1848_IADDR, r); 315 CS_WRITE(sc, AD1848_IDATA, v); 316 } 317 318 /* 319 * Read from one of the indexed registers of cs4231. 320 */ 321 u_int8_t 322 ce4231_read(struct ce4231_softc *sc, u_int8_t r) 323 { 324 CS_WRITE(sc, AD1848_IADDR, r); 325 return (CS_READ(sc, AD1848_IDATA)); 326 } 327 328 int 329 ce4231_set_speed(struct ce4231_softc *sc, u_long *argp) 330 { 331 /* 332 * The available speeds are in the following table. Keep the speeds in 333 * the increasing order. 334 */ 335 typedef struct { 336 int speed; 337 u_char bits; 338 } speed_struct; 339 u_long arg = *argp; 340 341 static speed_struct speed_table[] = { 342 {5510, (0 << 1) | CLOCK_XTAL2}, 343 {5510, (0 << 1) | CLOCK_XTAL2}, 344 {6620, (7 << 1) | CLOCK_XTAL2}, 345 {8000, (0 << 1) | CLOCK_XTAL1}, 346 {9600, (7 << 1) | CLOCK_XTAL1}, 347 {11025, (1 << 1) | CLOCK_XTAL2}, 348 {16000, (1 << 1) | CLOCK_XTAL1}, 349 {18900, (2 << 1) | CLOCK_XTAL2}, 350 {22050, (3 << 1) | CLOCK_XTAL2}, 351 {27420, (2 << 1) | CLOCK_XTAL1}, 352 {32000, (3 << 1) | CLOCK_XTAL1}, 353 {33075, (6 << 1) | CLOCK_XTAL2}, 354 {33075, (4 << 1) | CLOCK_XTAL2}, 355 {44100, (5 << 1) | CLOCK_XTAL2}, 356 {48000, (6 << 1) | CLOCK_XTAL1}, 357 }; 358 359 int i, n, selected = -1; 360 361 n = sizeof(speed_table) / sizeof(speed_struct); 362 363 if (arg < speed_table[0].speed) 364 selected = 0; 365 if (arg > speed_table[n - 1].speed) 366 selected = n - 1; 367 368 for (i = 1; selected == -1 && i < n; i++) { 369 if (speed_table[i].speed == arg) 370 selected = i; 371 else if (speed_table[i].speed > arg) { 372 int diff1, diff2; 373 374 diff1 = arg - speed_table[i - 1].speed; 375 diff2 = speed_table[i].speed - arg; 376 if (diff1 < diff2) 377 selected = i - 1; 378 else 379 selected = i; 380 } 381 } 382 383 if (selected == -1) 384 selected = 3; 385 386 sc->sc_speed_bits = speed_table[selected].bits; 387 sc->sc_need_commit = 1; 388 *argp = speed_table[selected].speed; 389 390 return (0); 391 } 392 393 /* 394 * Audio interface functions 395 */ 396 int 397 ce4231_open(void *addr, int flags) 398 { 399 struct ce4231_softc *sc = addr; 400 int tries; 401 402 DPRINTF(("ce4231_open\n")); 403 404 if (sc->sc_open) 405 return (EBUSY); 406 407 sc->sc_open = 1; 408 sc->sc_rintr = 0; 409 sc->sc_rarg = 0; 410 sc->sc_pintr = 0; 411 sc->sc_parg = 0; 412 413 P_WRITE(sc, EBDMA_DCSR, EBDCSR_RESET); 414 C_WRITE(sc, EBDMA_DCSR, EBDCSR_RESET); 415 P_WRITE(sc, EBDMA_DCSR, sc->sc_burst); 416 C_WRITE(sc, EBDMA_DCSR, sc->sc_burst); 417 418 DELAY(20); 419 420 for (tries = CS_TIMEOUT; 421 tries && CS_READ(sc, AD1848_IADDR) == SP_IN_INIT; tries--) 422 DELAY(10); 423 if (tries == 0) 424 printf("%s: timeout waiting for reset\n", sc->sc_dev.dv_xname); 425 426 ce4231_write(sc, SP_PIN_CONTROL, 427 ce4231_read(sc, SP_PIN_CONTROL) | INTERRUPT_ENABLE); 428 429 return (0); 430 } 431 432 void 433 ce4231_close(void *addr) 434 { 435 struct ce4231_softc *sc = addr; 436 437 ce4231_halt_input(sc); 438 ce4231_halt_output(sc); 439 ce4231_write(sc, SP_PIN_CONTROL, 440 ce4231_read(sc, SP_PIN_CONTROL) & (~INTERRUPT_ENABLE)); 441 sc->sc_open = 0; 442 } 443 444 int 445 ce4231_set_params(void *addr, int setmode, int usemode, struct audio_params *p, 446 struct audio_params *r) 447 { 448 struct ce4231_softc *sc = (struct ce4231_softc *)addr; 449 int err, bits, enc = p->encoding; 450 451 if (p->precision > 16) 452 p->precision = 16; 453 switch (enc) { 454 case AUDIO_ENCODING_ULAW: 455 p->precision = 8; 456 bits = FMT_ULAW >> 5; 457 break; 458 case AUDIO_ENCODING_ALAW: 459 p->precision = 8; 460 bits = FMT_ALAW >> 5; 461 break; 462 case AUDIO_ENCODING_SLINEAR_LE: 463 p->precision = 16; 464 bits = FMT_TWOS_COMP >> 5; 465 break; 466 case AUDIO_ENCODING_SLINEAR_BE: 467 p->precision = 16; 468 bits = FMT_TWOS_COMP_BE >> 5; 469 break; 470 case AUDIO_ENCODING_ULINEAR_LE: 471 case AUDIO_ENCODING_ULINEAR_BE: 472 p->precision = 8; 473 break; 474 default: 475 return (EINVAL); 476 } 477 478 if (p->channels > 2) 479 p->channels = 2; 480 481 err = ce4231_set_speed(sc, &p->sample_rate); 482 if (err) 483 return (err); 484 485 p->bps = AUDIO_BPS(p->precision); 486 r->bps = AUDIO_BPS(r->precision); 487 p->msb = r->msb = 1; 488 489 sc->sc_format_bits = bits; 490 sc->sc_channels = p->channels; 491 sc->sc_precision = p->precision; 492 sc->sc_need_commit = 1; 493 return (0); 494 } 495 496 int 497 ce4231_round_blocksize(void *addr, int blk) 498 { 499 return ((blk + 3) & (-4)); 500 } 501 502 int 503 ce4231_commit_settings(void *addr) 504 { 505 struct ce4231_softc *sc = (struct ce4231_softc *)addr; 506 int tries; 507 u_int8_t r, fs; 508 509 if (sc->sc_need_commit == 0) 510 return (0); 511 512 fs = sc->sc_speed_bits | (sc->sc_format_bits << 5); 513 if (sc->sc_channels == 2) 514 fs |= FMT_STEREO; 515 516 if (sc->sc_last_format == fs) { 517 sc->sc_need_commit = 0; 518 return (0); 519 } 520 521 /* XXX: this code is called before DMA (this intrs) is stopped */ 522 mtx_enter(&audio_lock); 523 524 r = ce4231_read(sc, SP_INTERFACE_CONFIG) | AUTO_CAL_ENABLE; 525 CS_WRITE(sc, AD1848_IADDR, MODE_CHANGE_ENABLE); 526 CS_WRITE(sc, AD1848_IADDR, MODE_CHANGE_ENABLE | SP_INTERFACE_CONFIG); 527 CS_WRITE(sc, AD1848_IDATA, r); 528 529 CS_WRITE(sc, AD1848_IADDR, MODE_CHANGE_ENABLE | SP_CLOCK_DATA_FORMAT); 530 CS_WRITE(sc, AD1848_IDATA, fs); 531 CS_READ(sc, AD1848_IDATA); 532 CS_READ(sc, AD1848_IDATA); 533 tries = CS_TIMEOUT; 534 for (tries = CS_TIMEOUT; 535 tries && CS_READ(sc, AD1848_IADDR) == SP_IN_INIT; tries--) 536 DELAY(10); 537 if (tries == 0) 538 printf("%s: timeout committing fspb\n", sc->sc_dev.dv_xname); 539 540 CS_WRITE(sc, AD1848_IADDR, MODE_CHANGE_ENABLE | CS_REC_FORMAT); 541 CS_WRITE(sc, AD1848_IDATA, fs); 542 CS_READ(sc, AD1848_IDATA); 543 CS_READ(sc, AD1848_IDATA); 544 for (tries = CS_TIMEOUT; 545 tries && CS_READ(sc, AD1848_IADDR) == SP_IN_INIT; tries--) 546 DELAY(10); 547 if (tries == 0) 548 printf("%s: timeout committing cdf\n", sc->sc_dev.dv_xname); 549 550 CS_WRITE(sc, AD1848_IADDR, 0); 551 for (tries = CS_TIMEOUT; 552 tries && CS_READ(sc, AD1848_IADDR) == SP_IN_INIT; tries--) 553 DELAY(10); 554 if (tries == 0) 555 printf("%s: timeout waiting for !mce\n", sc->sc_dev.dv_xname); 556 557 CS_WRITE(sc, AD1848_IADDR, SP_TEST_AND_INIT); 558 for (tries = CS_TIMEOUT; 559 tries && CS_READ(sc, AD1848_IDATA) & AUTO_CAL_IN_PROG; tries--) 560 DELAY(10); 561 if (tries == 0) 562 printf("%s: timeout waiting for autocalibration\n", 563 sc->sc_dev.dv_xname); 564 565 mtx_leave(&audio_lock); 566 567 sc->sc_need_commit = 0; 568 return (0); 569 } 570 571 int 572 ce4231_halt_output(void *addr) 573 { 574 struct ce4231_softc *sc = (struct ce4231_softc *)addr; 575 576 P_WRITE(sc, EBDMA_DCSR, 577 P_READ(sc, EBDMA_DCSR) & ~EBDCSR_DMAEN); 578 ce4231_write(sc, SP_INTERFACE_CONFIG, 579 ce4231_read(sc, SP_INTERFACE_CONFIG) & (~PLAYBACK_ENABLE)); 580 return (0); 581 } 582 583 int 584 ce4231_halt_input(void *addr) 585 { 586 struct ce4231_softc *sc = (struct ce4231_softc *)addr; 587 588 C_WRITE(sc, EBDMA_DCSR, 589 C_READ(sc, EBDMA_DCSR) & ~EBDCSR_DMAEN); 590 ce4231_write(sc, SP_INTERFACE_CONFIG, 591 ce4231_read(sc, SP_INTERFACE_CONFIG) & (~CAPTURE_ENABLE)); 592 return (0); 593 } 594 595 void 596 ce4231_set_outputs(struct ce4231_softc *sc, int mask) 597 { 598 u_int8_t val; 599 600 val = ce4231_read(sc, CS_MONO_IO_CONTROL) & ~MONO_OUTPUT_MUTE; 601 if (!(mask & OUT_PORT_SPKR)) 602 val |= MONO_OUTPUT_MUTE; 603 ce4231_write(sc, CS_MONO_IO_CONTROL, val); 604 605 val = ce4231_read(sc, SP_PIN_CONTROL) & ~(XCTL0_ENABLE | XCTL1_ENABLE); 606 if (!(mask & OUT_PORT_LINE)) 607 val |= XCTL0_ENABLE; 608 if (!(mask & OUT_PORT_HP)) 609 val |= XCTL1_ENABLE; 610 ce4231_write(sc, SP_PIN_CONTROL, val); 611 } 612 613 int 614 ce4231_get_outputs(struct ce4231_softc *sc) 615 { 616 int mask = 0; 617 u_int8_t val; 618 619 if (!(ce4231_read(sc, CS_MONO_IO_CONTROL) & MONO_OUTPUT_MUTE)) 620 mask |= OUT_PORT_SPKR; 621 622 val = ce4231_read(sc, SP_PIN_CONTROL); 623 if (!(val & XCTL0_ENABLE)) 624 mask |= OUT_PORT_LINE; 625 if (!(val & XCTL1_ENABLE)) 626 mask |= OUT_PORT_HP; 627 628 return (mask); 629 } 630 631 int 632 ce4231_set_port(void *addr, mixer_ctrl_t *cp) 633 { 634 struct ce4231_softc *sc = (struct ce4231_softc *)addr; 635 u_int8_t l, r; 636 637 DPRINTF(("ce4231_set_port: dev=%d type=%d\n", cp->dev, cp->type)); 638 639 switch (cp->dev) { 640 641 case CSAUDIO_DAC_LVL: 642 if (cp->type != AUDIO_MIXER_VALUE) 643 return (EINVAL); 644 l = ce4231_read(sc, SP_LEFT_OUTPUT_CONTROL) & 645 OUTPUT_ATTEN_MASK; 646 r = ce4231_read(sc, SP_RIGHT_OUTPUT_CONTROL) & 647 OUTPUT_ATTEN_MASK; 648 l |= (AUDIO_MAX_GAIN - 649 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]) >> 2; 650 r |= (AUDIO_MAX_GAIN - 651 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]) >> 2; 652 ce4231_write(sc, SP_LEFT_OUTPUT_CONTROL, l); 653 ce4231_write(sc, SP_RIGHT_OUTPUT_CONTROL, r); 654 break; 655 case CSAUDIO_DAC_MUTE: 656 if (cp->type != AUDIO_MIXER_ENUM) 657 return (EINVAL); 658 l = ce4231_read(sc, SP_LEFT_OUTPUT_CONTROL) & ~OUTPUT_MUTE; 659 r = ce4231_read(sc, SP_RIGHT_OUTPUT_CONTROL) & ~OUTPUT_MUTE; 660 if (cp->un.ord) { 661 l |= OUTPUT_MUTE; 662 r |= OUTPUT_MUTE; 663 } 664 ce4231_write(sc, SP_LEFT_OUTPUT_CONTROL, l); 665 ce4231_write(sc, SP_RIGHT_OUTPUT_CONTROL, r); 666 break; 667 668 case CSAUDIO_OUTPUTS: 669 if (cp->type != AUDIO_MIXER_SET) 670 return (EINVAL); 671 ce4231_set_outputs(sc, cp->un.mask); 672 break; 673 674 case CSAUDIO_CD_LVL: 675 if (cp->type != AUDIO_MIXER_VALUE) 676 return (EINVAL); 677 l = ce4231_read(sc, SP_LEFT_AUX1_CONTROL) & 678 AUX_INPUT_ATTEN_MASK; 679 r = ce4231_read(sc, SP_RIGHT_AUX1_CONTROL) & 680 AUX_INPUT_ATTEN_MASK; 681 l |= (AUDIO_MAX_GAIN - 682 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]) >> 3; 683 r |= (AUDIO_MAX_GAIN - 684 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]) >> 3; 685 ce4231_write(sc, SP_LEFT_AUX1_CONTROL, l); 686 ce4231_write(sc, SP_RIGHT_AUX1_CONTROL, r); 687 break; 688 case CSAUDIO_CD_MUTE: 689 if (cp->type != AUDIO_MIXER_ENUM) 690 return (EINVAL); 691 l = ce4231_read(sc, SP_LEFT_AUX1_CONTROL) & ~AUX_INPUT_MUTE; 692 r = ce4231_read(sc, SP_RIGHT_AUX1_CONTROL) & ~AUX_INPUT_MUTE; 693 if (cp->un.ord) { 694 l |= AUX_INPUT_MUTE; 695 r |= AUX_INPUT_MUTE; 696 } 697 ce4231_write(sc, SP_LEFT_AUX1_CONTROL, l); 698 ce4231_write(sc, SP_RIGHT_AUX1_CONTROL, r); 699 break; 700 701 case CSAUDIO_LINE_IN_LVL: 702 if (cp->type != AUDIO_MIXER_VALUE) 703 return (EINVAL); 704 l = ce4231_read(sc, CS_LEFT_LINE_CONTROL) & 705 LINE_INPUT_ATTEN_MASK; 706 r = ce4231_read(sc, CS_RIGHT_LINE_CONTROL) & 707 LINE_INPUT_ATTEN_MASK; 708 l |= (AUDIO_MAX_GAIN - 709 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]) >> 3; 710 r |= (AUDIO_MAX_GAIN - 711 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]) >> 3; 712 ce4231_write(sc, CS_LEFT_LINE_CONTROL, l); 713 ce4231_write(sc, CS_RIGHT_LINE_CONTROL, r); 714 break; 715 case CSAUDIO_LINE_IN_MUTE: 716 l = ce4231_read(sc, CS_LEFT_LINE_CONTROL) & ~LINE_INPUT_MUTE; 717 r = ce4231_read(sc, CS_RIGHT_LINE_CONTROL) & ~LINE_INPUT_MUTE; 718 if (cp->un.ord) { 719 l |= LINE_INPUT_MUTE; 720 r |= LINE_INPUT_MUTE; 721 } 722 ce4231_write(sc, CS_LEFT_LINE_CONTROL, l); 723 ce4231_write(sc, CS_RIGHT_LINE_CONTROL, r); 724 break; 725 726 case CSAUDIO_MONITOR_LVL: 727 if (cp->type != AUDIO_MIXER_VALUE) 728 return (EINVAL); 729 if (cp->un.value.num_channels != 1) 730 return (EINVAL); 731 l = ce4231_read(sc, SP_DIGITAL_MIX) & ~MIX_ATTEN_MASK; 732 l |= (AUDIO_MAX_GAIN - 733 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]) & 734 MIX_ATTEN_MASK; 735 ce4231_write(sc, SP_DIGITAL_MIX, l); 736 break; 737 case CSAUDIO_MONITOR_MUTE: 738 if (cp->type != AUDIO_MIXER_ENUM) 739 return (EINVAL); 740 l = ce4231_read(sc, SP_DIGITAL_MIX) & ~DIGITAL_MIX1_ENABLE; 741 if (!cp->un.ord) 742 l |= DIGITAL_MIX1_ENABLE; 743 ce4231_write(sc, SP_DIGITAL_MIX, l); 744 break; 745 746 case CSAUDIO_REC_LVL: 747 if (cp->type != AUDIO_MIXER_VALUE) 748 return (EINVAL); 749 l = ce4231_read(sc, SP_LEFT_INPUT_CONTROL) & INPUT_GAIN_MASK; 750 r = ce4231_read(sc, SP_RIGHT_INPUT_CONTROL) & INPUT_GAIN_MASK; 751 l = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] >> 4; 752 r = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] >> 4; 753 ce4231_write(sc, SP_LEFT_INPUT_CONTROL, l); 754 ce4231_write(sc, SP_RIGHT_INPUT_CONTROL, r); 755 break; 756 case CSAUDIO_RECORD_SOURCE: 757 if (cp->type != AUDIO_MIXER_ENUM) 758 return (EINVAL); 759 l = ce4231_read(sc, SP_LEFT_INPUT_CONTROL) & INPUT_SOURCE_MASK; 760 r = ce4231_read(sc, SP_RIGHT_INPUT_CONTROL) & INPUT_SOURCE_MASK; 761 l |= cp->un.ord << 6; 762 r |= cp->un.ord << 6; 763 ce4231_write(sc, SP_LEFT_INPUT_CONTROL, l); 764 ce4231_write(sc, SP_RIGHT_INPUT_CONTROL, r); 765 break; 766 767 case CSAUDIO_MIC_PREAMP: 768 if (cp->type != AUDIO_MIXER_ENUM) 769 return (EINVAL); 770 l = ce4231_read(sc, SP_LEFT_INPUT_CONTROL) & 771 ~INPUT_MIC_GAIN_ENABLE; 772 r = ce4231_read(sc, SP_RIGHT_INPUT_CONTROL) & 773 ~INPUT_MIC_GAIN_ENABLE; 774 if (cp->un.ord) { 775 l |= INPUT_MIC_GAIN_ENABLE; 776 r |= INPUT_MIC_GAIN_ENABLE; 777 } 778 ce4231_write(sc, SP_LEFT_INPUT_CONTROL, l); 779 ce4231_write(sc, SP_RIGHT_INPUT_CONTROL, r); 780 break; 781 782 default: 783 return (EINVAL); 784 } 785 786 return (0); 787 } 788 789 int 790 ce4231_get_port(void *addr, mixer_ctrl_t *cp) 791 { 792 struct ce4231_softc *sc = (struct ce4231_softc *)addr; 793 794 DPRINTF(("ce4231_get_port: port=%d type=%d\n", cp->dev, cp->type)); 795 796 switch (cp->dev) { 797 798 case CSAUDIO_DAC_LVL: 799 if (cp->type != AUDIO_MIXER_VALUE) 800 return (EINVAL); 801 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 802 AUDIO_MAX_GAIN - ((ce4231_read(sc, SP_LEFT_OUTPUT_CONTROL) & 803 OUTPUT_ATTEN_BITS) << 2); 804 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 805 AUDIO_MAX_GAIN - ((ce4231_read(sc, SP_RIGHT_OUTPUT_CONTROL) & 806 OUTPUT_ATTEN_BITS) << 2); 807 break; 808 case CSAUDIO_DAC_MUTE: 809 if (cp->type != AUDIO_MIXER_ENUM) 810 return (EINVAL); 811 cp->un.ord = (ce4231_read(sc, SP_LEFT_OUTPUT_CONTROL) & 812 OUTPUT_MUTE) ? 1 : 0; 813 break; 814 815 case CSAUDIO_OUTPUTS: 816 if (cp->type != AUDIO_MIXER_SET) 817 return (EINVAL); 818 cp->un.mask = ce4231_get_outputs(sc); 819 break; 820 821 case CSAUDIO_CD_LVL: 822 if (cp->type != AUDIO_MIXER_VALUE) 823 return (EINVAL); 824 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 825 AUDIO_MAX_GAIN - ((ce4231_read(sc, SP_LEFT_AUX1_CONTROL) & 826 AUX_INPUT_ATTEN_BITS) << 3); 827 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 828 AUDIO_MAX_GAIN - ((ce4231_read(sc, SP_RIGHT_AUX1_CONTROL) & 829 AUX_INPUT_ATTEN_BITS) << 3); 830 break; 831 case CSAUDIO_CD_MUTE: 832 if (cp->type != AUDIO_MIXER_ENUM) 833 return (EINVAL); 834 cp->un.ord = (ce4231_read(sc, SP_LEFT_AUX1_CONTROL) & 835 AUX_INPUT_MUTE) ? 1 : 0; 836 break; 837 838 case CSAUDIO_LINE_IN_LVL: 839 if (cp->type != AUDIO_MIXER_VALUE) 840 return (EINVAL); 841 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 842 AUDIO_MAX_GAIN - ((ce4231_read(sc, CS_LEFT_LINE_CONTROL) & 843 LINE_INPUT_ATTEN_BITS) << 3); 844 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 845 AUDIO_MAX_GAIN - ((ce4231_read(sc, CS_RIGHT_LINE_CONTROL) & 846 LINE_INPUT_ATTEN_BITS) << 3); 847 break; 848 case CSAUDIO_LINE_IN_MUTE: 849 if (cp->type != AUDIO_MIXER_ENUM) 850 return (EINVAL); 851 cp->un.ord = (ce4231_read(sc, CS_LEFT_LINE_CONTROL) & 852 LINE_INPUT_MUTE) ? 1 : 0; 853 break; 854 855 case CSAUDIO_MONITOR_LVL: 856 if (cp->type != AUDIO_MIXER_VALUE) 857 return (EINVAL); 858 if (cp->un.value.num_channels != 1) 859 return (EINVAL); 860 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = 861 AUDIO_MAX_GAIN - (ce4231_read(sc, SP_DIGITAL_MIX) & 862 MIX_ATTEN_MASK); 863 break; 864 case CSAUDIO_MONITOR_MUTE: 865 if (cp->type != AUDIO_MIXER_ENUM) 866 return (EINVAL); 867 cp->un.ord = (ce4231_read(sc, SP_DIGITAL_MIX) & 868 DIGITAL_MIX1_ENABLE) ? 0 : 1; 869 break; 870 871 case CSAUDIO_REC_LVL: 872 if (cp->type != AUDIO_MIXER_VALUE) 873 return (EINVAL); 874 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 875 (ce4231_read(sc, SP_LEFT_INPUT_CONTROL) & 876 ~INPUT_GAIN_MASK) << 4; 877 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 878 (ce4231_read(sc, SP_RIGHT_INPUT_CONTROL) & 879 ~INPUT_GAIN_MASK) << 4; 880 break; 881 case CSAUDIO_RECORD_SOURCE: 882 if (cp->type != AUDIO_MIXER_ENUM) 883 return (EINVAL); 884 cp->un.ord = (ce4231_read(sc, SP_LEFT_INPUT_CONTROL) & 885 CS_REC_SRC_BITS) >> 6; 886 break; 887 888 case CSAUDIO_MIC_PREAMP: 889 if (cp->type != AUDIO_MIXER_ENUM) 890 return (EINVAL); 891 cp->un.ord = (ce4231_read(sc, SP_LEFT_INPUT_CONTROL) & 892 INPUT_MIC_GAIN_ENABLE) ? 1 : 0; 893 break; 894 895 default: 896 return (EINVAL); 897 } 898 return (0); 899 } 900 901 int 902 ce4231_query_devinfo(void *addr, mixer_devinfo_t *dip) 903 { 904 size_t nsize = MAX_AUDIO_DEV_LEN; 905 int err = 0; 906 907 switch (dip->index) { 908 case CSAUDIO_INPUT_CLASS: 909 dip->type = AUDIO_MIXER_CLASS; 910 dip->mixer_class = CSAUDIO_INPUT_CLASS; 911 dip->prev = dip->next = AUDIO_MIXER_LAST; 912 strlcpy(dip->label.name, AudioCinputs, nsize); 913 break; 914 case CSAUDIO_OUTPUT_CLASS: 915 dip->type = AUDIO_MIXER_CLASS; 916 dip->mixer_class = CSAUDIO_OUTPUT_CLASS; 917 dip->prev = dip->next = AUDIO_MIXER_LAST; 918 strlcpy(dip->label.name, AudioCoutputs, nsize); 919 break; 920 case CSAUDIO_RECORD_CLASS: 921 dip->type = AUDIO_MIXER_CLASS; 922 dip->mixer_class = CSAUDIO_RECORD_CLASS; 923 dip->prev = dip->next = AUDIO_MIXER_LAST; 924 strlcpy(dip->label.name, AudioCrecord, nsize); 925 break; 926 927 case CSAUDIO_DAC_LVL: 928 dip->type = AUDIO_MIXER_VALUE; 929 dip->mixer_class = CSAUDIO_OUTPUT_CLASS; 930 dip->prev = AUDIO_MIXER_LAST; 931 dip->next = CSAUDIO_DAC_MUTE; 932 strlcpy(dip->label.name, AudioNdac, nsize); 933 dip->un.v.num_channels = 2; 934 dip->un.v.delta = 4; 935 strlcpy(dip->un.v.units.name, AudioNvolume, nsize); 936 break; 937 case CSAUDIO_DAC_MUTE: 938 dip->type = AUDIO_MIXER_ENUM; 939 dip->mixer_class = CSAUDIO_OUTPUT_CLASS; 940 dip->prev = CSAUDIO_DAC_LVL; 941 dip->next = AUDIO_MIXER_LAST; 942 strlcpy(dip->label.name, AudioNmute, nsize); 943 goto onoff; 944 945 case CSAUDIO_OUTPUTS: 946 dip->type = AUDIO_MIXER_SET; 947 dip->mixer_class = CSAUDIO_OUTPUT_CLASS; 948 dip->prev = dip->next = AUDIO_MIXER_LAST; 949 strlcpy(dip->label.name, AudioNoutput, nsize); 950 dip->un.s.num_mem = 3; 951 strlcpy(dip->un.s.member[0].label.name, AudioNline, nsize); 952 dip->un.s.member[0].mask = OUT_PORT_LINE; 953 strlcpy(dip->un.s.member[1].label.name, AudioNheadphone, nsize); 954 dip->un.s.member[1].mask = OUT_PORT_HP; 955 strlcpy(dip->un.s.member[2].label.name, AudioNspeaker, nsize); 956 dip->un.s.member[2].mask = OUT_PORT_SPKR; 957 break; 958 959 case CSAUDIO_CD_LVL: 960 dip->type = AUDIO_MIXER_VALUE; 961 dip->mixer_class = CSAUDIO_INPUT_CLASS; 962 dip->prev = AUDIO_MIXER_LAST; 963 dip->next = CSAUDIO_CD_MUTE; 964 strlcpy(dip->label.name, AudioNcd, nsize); 965 dip->un.v.num_channels = 2; 966 dip->un.v.delta = 8; 967 strlcpy(dip->un.v.units.name, AudioNvolume, nsize); 968 break; 969 case CSAUDIO_CD_MUTE: 970 dip->type = AUDIO_MIXER_ENUM; 971 dip->mixer_class = CSAUDIO_INPUT_CLASS; 972 dip->prev = CSAUDIO_CD_LVL; 973 dip->next = AUDIO_MIXER_LAST; 974 strlcpy(dip->label.name, AudioNmute, nsize); 975 goto onoff; 976 977 case CSAUDIO_LINE_IN_LVL: 978 dip->type = AUDIO_MIXER_VALUE; 979 dip->mixer_class = CSAUDIO_INPUT_CLASS; 980 dip->prev = AUDIO_MIXER_LAST; 981 dip->next = CSAUDIO_LINE_IN_MUTE; 982 strlcpy(dip->label.name, AudioNline, nsize); 983 dip->un.v.num_channels = 2; 984 dip->un.v.delta = 8; 985 strlcpy(dip->un.v.units.name, AudioNvolume, nsize); 986 break; 987 case CSAUDIO_LINE_IN_MUTE: 988 dip->type = AUDIO_MIXER_ENUM; 989 dip->mixer_class = CSAUDIO_INPUT_CLASS; 990 dip->prev = CSAUDIO_LINE_IN_LVL; 991 dip->next = AUDIO_MIXER_LAST; 992 strlcpy(dip->label.name, AudioNmute, nsize); 993 goto onoff; 994 995 case CSAUDIO_MONITOR_LVL: 996 dip->type = AUDIO_MIXER_VALUE; 997 dip->mixer_class = CSAUDIO_OUTPUT_CLASS; 998 dip->prev = AUDIO_MIXER_LAST; 999 dip->next = CSAUDIO_MONITOR_MUTE; 1000 strlcpy(dip->label.name, AudioNmonitor, nsize); 1001 dip->un.v.num_channels = 1; 1002 dip->un.v.delta = 4; 1003 strlcpy(dip->un.v.units.name, AudioNvolume, nsize); 1004 break; 1005 case CSAUDIO_MONITOR_MUTE: 1006 dip->type = AUDIO_MIXER_ENUM; 1007 dip->mixer_class = CSAUDIO_OUTPUT_CLASS; 1008 dip->prev = CSAUDIO_MONITOR_LVL; 1009 dip->next = AUDIO_MIXER_LAST; 1010 strlcpy(dip->label.name, AudioNmute, nsize); 1011 goto onoff; 1012 1013 case CSAUDIO_REC_LVL: 1014 dip->type = AUDIO_MIXER_VALUE; 1015 dip->mixer_class = CSAUDIO_RECORD_CLASS; 1016 dip->prev = dip->next = AUDIO_MIXER_LAST; 1017 strlcpy(dip->label.name, AudioNvolume, nsize); 1018 dip->un.v.num_channels = 2; 1019 dip->un.v.delta = 16; 1020 strlcpy(dip->un.v.units.name, AudioNvolume, nsize); 1021 break; 1022 case CSAUDIO_RECORD_SOURCE: 1023 dip->type = AUDIO_MIXER_ENUM; 1024 dip->mixer_class = CSAUDIO_RECORD_CLASS; 1025 dip->prev = dip->next = AUDIO_MIXER_LAST; 1026 strlcpy(dip->label.name, AudioNsource, nsize); 1027 dip->un.e.num_mem = 4; 1028 strlcpy(dip->un.e.member[0].label.name, AudioNline, nsize); 1029 dip->un.e.member[0].ord = REC_PORT_LINE; 1030 strlcpy(dip->un.e.member[1].label.name, AudioNcd, nsize); 1031 dip->un.e.member[1].ord = REC_PORT_CD; 1032 strlcpy(dip->un.e.member[2].label.name, AudioNmicrophone, nsize); 1033 dip->un.e.member[2].ord = REC_PORT_MIC; 1034 strlcpy(dip->un.e.member[3].label.name, AudioNmixerout, nsize); 1035 dip->un.e.member[3].ord = REC_PORT_MIX; 1036 break; 1037 1038 case CSAUDIO_MIC_PREAMP: 1039 dip->type = AUDIO_MIXER_ENUM; 1040 dip->mixer_class = CSAUDIO_RECORD_CLASS; 1041 dip->prev = dip->next = AUDIO_MIXER_LAST; 1042 snprintf(dip->label.name, nsize, "%s_%s", AudioNmicrophone, 1043 AudioNpreamp); 1044 goto onoff; 1045 1046 onoff: 1047 dip->un.e.num_mem = 2; 1048 strlcpy(dip->un.e.member[0].label.name, AudioNon, nsize); 1049 dip->un.e.member[0].ord = 1; 1050 strlcpy(dip->un.e.member[1].label.name, AudioNoff, nsize); 1051 dip->un.e.member[1].ord = 0; 1052 break; 1053 1054 default: 1055 err = ENXIO; 1056 } 1057 1058 return (err); 1059 } 1060 1061 int 1062 ce4231_get_props(void *addr) 1063 { 1064 return (AUDIO_PROP_FULLDUPLEX); 1065 } 1066 1067 /* 1068 * Hardware interrupt handler 1069 */ 1070 /* 1071 * Don't bother with the AD1848_STATUS register. It's interrupt bit gets 1072 * set for both recording and playback interrupts. But we have separate 1073 * handlers for playback and recording, and if we clear the status in 1074 * one handler while there is an interrupt pending for the other direction 1075 * as well, we'll never notice the interrupt for the other direction. 1076 * 1077 * Instead rely solely on CS_IRQ_STATUS, which has separate bits for 1078 * playback and recording interrupts. Also note that resetting 1079 * AD1848_STATUS clears the interrupt bits in CS_IRQ_STATUS. 1080 */ 1081 1082 int 1083 ce4231_pintr(void *v) 1084 { 1085 struct ce4231_softc *sc = (struct ce4231_softc *)v; 1086 u_int32_t csr; 1087 u_int8_t reg; 1088 struct cs_dma *p; 1089 struct cs_chdma *chdma = &sc->sc_pchdma; 1090 int r = 0; 1091 1092 mtx_enter(&audio_lock); 1093 csr = P_READ(sc, EBDMA_DCSR); 1094 1095 reg = ce4231_read(sc, CS_IRQ_STATUS); 1096 if (reg & CS_IRQ_PI) { 1097 ce4231_write(sc, SP_LOWER_BASE_COUNT, 0xff); 1098 ce4231_write(sc, SP_UPPER_BASE_COUNT, 0xff); 1099 ce4231_write(sc, CS_IRQ_STATUS, reg & ~CS_IRQ_PI); 1100 } 1101 1102 P_WRITE(sc, EBDMA_DCSR, csr); 1103 1104 if (csr & EBDCSR_INT) 1105 r = 1; 1106 1107 if ((csr & EBDCSR_TC) || ((csr & EBDCSR_A_LOADED) == 0)) { 1108 u_long nextaddr, togo; 1109 1110 p = chdma->cur_dma; 1111 togo = chdma->segsz - chdma->count; 1112 if (togo == 0) { 1113 nextaddr = (u_int32_t)p->dmamap->dm_segs[0].ds_addr; 1114 chdma->count = togo = chdma->blksz; 1115 } else { 1116 nextaddr = chdma->lastaddr; 1117 if (togo > chdma->blksz) 1118 togo = chdma->blksz; 1119 chdma->count += togo; 1120 } 1121 1122 P_WRITE(sc, EBDMA_DCNT, togo); 1123 P_WRITE(sc, EBDMA_DADDR, nextaddr); 1124 chdma->lastaddr = nextaddr + togo; 1125 1126 if (sc->sc_pintr != NULL) 1127 (*sc->sc_pintr)(sc->sc_parg); 1128 r = 1; 1129 } 1130 mtx_leave(&audio_lock); 1131 return (r); 1132 } 1133 1134 int 1135 ce4231_cintr(void *v) 1136 { 1137 struct ce4231_softc *sc = (struct ce4231_softc *)v; 1138 u_int32_t csr; 1139 u_int8_t reg; 1140 struct cs_dma *p; 1141 struct cs_chdma *chdma = &sc->sc_rchdma; 1142 int r = 0; 1143 1144 mtx_enter(&audio_lock); 1145 csr = C_READ(sc, EBDMA_DCSR); 1146 1147 reg = ce4231_read(sc, CS_IRQ_STATUS); 1148 if (reg & CS_IRQ_CI) { 1149 ce4231_write(sc, CS_LOWER_REC_CNT, 0xff); 1150 ce4231_write(sc, CS_UPPER_REC_CNT, 0xff); 1151 ce4231_write(sc, CS_IRQ_STATUS, reg & ~CS_IRQ_CI); 1152 } 1153 1154 C_WRITE(sc, EBDMA_DCSR, csr); 1155 1156 if (csr & EBDCSR_INT) 1157 r = 1; 1158 1159 if ((csr & EBDCSR_TC) || ((csr & EBDCSR_A_LOADED) == 0)) { 1160 u_long nextaddr, togo; 1161 1162 p = chdma->cur_dma; 1163 togo = chdma->segsz - chdma->count; 1164 if (togo == 0) { 1165 nextaddr = (u_int32_t)p->dmamap->dm_segs[0].ds_addr; 1166 chdma->count = togo = chdma->blksz; 1167 } else { 1168 nextaddr = chdma->lastaddr; 1169 if (togo > chdma->blksz) 1170 togo = chdma->blksz; 1171 chdma->count += togo; 1172 } 1173 1174 C_WRITE(sc, EBDMA_DCNT, togo); 1175 C_WRITE(sc, EBDMA_DADDR, nextaddr); 1176 chdma->lastaddr = nextaddr + togo; 1177 1178 if (sc->sc_rintr != NULL) 1179 (*sc->sc_rintr)(sc->sc_rarg); 1180 r = 1; 1181 } 1182 mtx_leave(&audio_lock); 1183 return (r); 1184 } 1185 1186 void * 1187 ce4231_alloc(void *addr, int direction, size_t size, int pool, int flags) 1188 { 1189 struct ce4231_softc *sc = (struct ce4231_softc *)addr; 1190 bus_dma_tag_t dmat = sc->sc_dmatag; 1191 struct cs_dma *p; 1192 1193 p = (struct cs_dma *)malloc(sizeof(struct cs_dma), pool, flags); 1194 if (p == NULL) 1195 return (NULL); 1196 1197 if (bus_dmamap_create(dmat, size, 1, size, 0, 1198 BUS_DMA_NOWAIT, &p->dmamap) != 0) 1199 goto fail; 1200 1201 p->size = size; 1202 1203 if (bus_dmamem_alloc(dmat, size, 64*1024, 0, p->segs, 1204 sizeof(p->segs)/sizeof(p->segs[0]), &p->nsegs, 1205 BUS_DMA_NOWAIT) != 0) 1206 goto fail1; 1207 1208 if (bus_dmamem_map(dmat, p->segs, p->nsegs, p->size, 1209 &p->addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT) != 0) 1210 goto fail2; 1211 1212 if (bus_dmamap_load(dmat, p->dmamap, p->addr, size, NULL, 1213 BUS_DMA_NOWAIT) != 0) 1214 goto fail3; 1215 1216 p->next = sc->sc_dmas; 1217 sc->sc_dmas = p; 1218 return (p->addr); 1219 1220 fail3: 1221 bus_dmamem_unmap(dmat, p->addr, p->size); 1222 fail2: 1223 bus_dmamem_free(dmat, p->segs, p->nsegs); 1224 fail1: 1225 bus_dmamap_destroy(dmat, p->dmamap); 1226 fail: 1227 free(p, pool, 0); 1228 return (NULL); 1229 } 1230 1231 void 1232 ce4231_free(void *addr, void *ptr, int pool) 1233 { 1234 struct ce4231_softc *sc = addr; 1235 bus_dma_tag_t dmat = sc->sc_dmatag; 1236 struct cs_dma *p, **pp; 1237 1238 for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &(*pp)->next) { 1239 if (p->addr != ptr) 1240 continue; 1241 bus_dmamap_unload(dmat, p->dmamap); 1242 bus_dmamem_unmap(dmat, p->addr, p->size); 1243 bus_dmamem_free(dmat, p->segs, p->nsegs); 1244 bus_dmamap_destroy(dmat, p->dmamap); 1245 *pp = p->next; 1246 free(p, pool, 0); 1247 return; 1248 } 1249 printf("%s: attempt to free rogue pointer\n", sc->sc_dev.dv_xname); 1250 } 1251 1252 int 1253 ce4231_trigger_output(void *addr, void *start, void *end, int blksize, 1254 void (*intr)(void *), void *arg, struct audio_params *param) 1255 { 1256 struct ce4231_softc *sc = addr; 1257 struct cs_dma *p; 1258 struct cs_chdma *chdma = &sc->sc_pchdma; 1259 u_int32_t csr; 1260 vaddr_t n; 1261 1262 sc->sc_pintr = intr; 1263 sc->sc_parg = arg; 1264 1265 for (p = sc->sc_dmas; p->addr != start; p = p->next) 1266 /*EMPTY*/; 1267 if (p == NULL) { 1268 printf("%s: trigger_output: bad addr: %p\n", 1269 sc->sc_dev.dv_xname, start); 1270 return (EINVAL); 1271 } 1272 1273 n = (char *)end - (char *)start; 1274 1275 /* 1276 * Do only `blksize' at a time, so audio_pint() is kept 1277 * synchronous with us... 1278 */ 1279 chdma->cur_dma = p; 1280 chdma->blksz = blksize; 1281 chdma->segsz = n; 1282 1283 if (n > chdma->blksz) 1284 n = chdma->blksz; 1285 1286 chdma->count = n; 1287 1288 csr = P_READ(sc, EBDMA_DCSR); 1289 if (csr & EBDCSR_DMAEN) { 1290 P_WRITE(sc, EBDMA_DCNT, (u_long)n); 1291 P_WRITE(sc, EBDMA_DADDR, 1292 (u_long)p->dmamap->dm_segs[0].ds_addr); 1293 } else { 1294 P_WRITE(sc, EBDMA_DCSR, EBDCSR_RESET); 1295 P_WRITE(sc, EBDMA_DCSR, sc->sc_burst); 1296 1297 P_WRITE(sc, EBDMA_DCNT, (u_long)n); 1298 P_WRITE(sc, EBDMA_DADDR, 1299 (u_long)p->dmamap->dm_segs[0].ds_addr); 1300 1301 P_WRITE(sc, EBDMA_DCSR, sc->sc_burst | EBDCSR_DMAEN | 1302 EBDCSR_INTEN | EBDCSR_CNTEN | EBDCSR_NEXTEN); 1303 1304 ce4231_write(sc, SP_LOWER_BASE_COUNT, 0xff); 1305 ce4231_write(sc, SP_UPPER_BASE_COUNT, 0xff); 1306 ce4231_write(sc, SP_INTERFACE_CONFIG, 1307 ce4231_read(sc, SP_INTERFACE_CONFIG) | PLAYBACK_ENABLE); 1308 } 1309 chdma->lastaddr = p->dmamap->dm_segs[0].ds_addr + n; 1310 1311 return (0); 1312 } 1313 1314 int 1315 ce4231_trigger_input(void *addr, void *start, void *end, int blksize, 1316 void (*intr)(void *), void *arg, struct audio_params *param) 1317 { 1318 struct ce4231_softc *sc = addr; 1319 struct cs_dma *p; 1320 struct cs_chdma *chdma = &sc->sc_rchdma; 1321 u_int32_t csr; 1322 vaddr_t n; 1323 1324 sc->sc_rintr = intr; 1325 sc->sc_rarg = arg; 1326 1327 for (p = sc->sc_dmas; p->addr != start; p = p->next) 1328 /*EMPTY*/; 1329 if (p == NULL) { 1330 printf("%s: trigger_input: bad addr: %p\n", 1331 sc->sc_dev.dv_xname, start); 1332 return (EINVAL); 1333 } 1334 1335 n = (char *)end - (char *)start; 1336 1337 /* 1338 * Do only `blksize' at a time, so audio_rint() is kept 1339 * synchronous with us... 1340 */ 1341 chdma->cur_dma = p; 1342 chdma->blksz = blksize; 1343 chdma->segsz = n; 1344 1345 if (n > chdma->blksz) 1346 n = chdma->blksz; 1347 1348 chdma->count = n; 1349 1350 csr = C_READ(sc, EBDMA_DCSR); 1351 if (csr & EBDCSR_DMAEN) { 1352 C_WRITE(sc, EBDMA_DCNT, (u_long)n); 1353 C_WRITE(sc, EBDMA_DADDR, 1354 (u_long)p->dmamap->dm_segs[0].ds_addr); 1355 } else { 1356 C_WRITE(sc, EBDMA_DCSR, EBDCSR_RESET); 1357 C_WRITE(sc, EBDMA_DCSR, sc->sc_burst); 1358 1359 C_WRITE(sc, EBDMA_DCNT, (u_long)n); 1360 C_WRITE(sc, EBDMA_DADDR, 1361 (u_long)p->dmamap->dm_segs[0].ds_addr); 1362 1363 C_WRITE(sc, EBDMA_DCSR, sc->sc_burst | EBDCSR_WRITE | 1364 EBDCSR_DMAEN | EBDCSR_INTEN | EBDCSR_CNTEN | EBDCSR_NEXTEN); 1365 1366 ce4231_write(sc, CS_LOWER_REC_CNT, 0xff); 1367 ce4231_write(sc, CS_UPPER_REC_CNT, 0xff); 1368 ce4231_write(sc, SP_INTERFACE_CONFIG, 1369 ce4231_read(sc, SP_INTERFACE_CONFIG) | CAPTURE_ENABLE); 1370 } 1371 chdma->lastaddr = p->dmamap->dm_segs[0].ds_addr + n; 1372 1373 return (0); 1374 } 1375