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