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