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