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