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