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