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