1 /* $OpenBSD: cs4231.c,v 1.38 2017/01/04 07:33:14 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_SLINEAR_BE: 498 if (p->precision == 16) 499 bits = FMT_TWOS_COMP_BE >> 5; 500 else 501 return (EINVAL); 502 break; 503 case AUDIO_ENCODING_ULINEAR_LE: 504 case AUDIO_ENCODING_ULINEAR_BE: 505 if (p->precision == 8) 506 bits = FMT_PCM8 >> 5; 507 else 508 return (EINVAL); 509 break; 510 default: 511 return (EINVAL); 512 } 513 514 if (p->channels != 1 && p->channels != 2) 515 return (EINVAL); 516 517 err = cs4231_set_speed(sc, &p->sample_rate); 518 if (err) 519 return (err); 520 521 p->bps = AUDIO_BPS(p->precision); 522 r->bps = AUDIO_BPS(r->precision); 523 p->msb = r->msb = 1; 524 525 sc->sc_format_bits = bits; 526 sc->sc_channels = p->channels; 527 sc->sc_precision = p->precision; 528 sc->sc_need_commit = 1; 529 return (0); 530 } 531 532 int 533 cs4231_round_blocksize(void *vsc, int blk) 534 { 535 return ((blk + 3) & (-4)); 536 } 537 538 int 539 cs4231_commit_settings(void *vsc) 540 { 541 struct cs4231_softc *sc = (struct cs4231_softc *)vsc; 542 int tries; 543 u_int8_t r, fs; 544 545 if (sc->sc_need_commit == 0) 546 return (0); 547 548 fs = sc->sc_speed_bits | (sc->sc_format_bits << 5); 549 if (sc->sc_channels == 2) 550 fs |= FMT_STEREO; 551 552 /* XXX: this is called before DMA is setup, useful ? */ 553 mtx_enter(&audio_lock); 554 555 r = cs4231_read(sc, SP_INTERFACE_CONFIG) | AUTO_CAL_ENABLE; 556 CS_WRITE(sc, AD1848_IADDR, MODE_CHANGE_ENABLE); 557 CS_WRITE(sc, AD1848_IADDR, MODE_CHANGE_ENABLE | SP_INTERFACE_CONFIG); 558 CS_WRITE(sc, AD1848_IDATA, r); 559 560 CS_WRITE(sc, AD1848_IADDR, MODE_CHANGE_ENABLE | SP_CLOCK_DATA_FORMAT); 561 CS_WRITE(sc, AD1848_IDATA, fs); 562 CS_READ(sc, AD1848_IDATA); 563 CS_READ(sc, AD1848_IDATA); 564 tries = CS_TIMEOUT; 565 for (tries = CS_TIMEOUT; 566 tries && CS_READ(sc, AD1848_IADDR) == SP_IN_INIT; tries--) 567 DELAY(10); 568 if (tries == 0) 569 printf("%s: timeout committing fspb\n", sc->sc_dev.dv_xname); 570 571 CS_WRITE(sc, AD1848_IADDR, MODE_CHANGE_ENABLE | CS_REC_FORMAT); 572 CS_WRITE(sc, AD1848_IDATA, fs); 573 CS_READ(sc, AD1848_IDATA); 574 CS_READ(sc, AD1848_IDATA); 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 cdf\n", sc->sc_dev.dv_xname); 580 581 CS_WRITE(sc, AD1848_IADDR, 0); 582 for (tries = CS_TIMEOUT; 583 tries && CS_READ(sc, AD1848_IADDR) == SP_IN_INIT; tries--) 584 DELAY(10); 585 if (tries == 0) 586 printf("%s: timeout waiting for !mce\n", sc->sc_dev.dv_xname); 587 588 CS_WRITE(sc, AD1848_IADDR, SP_TEST_AND_INIT); 589 for (tries = CS_TIMEOUT; 590 tries && CS_READ(sc, AD1848_IDATA) & AUTO_CAL_IN_PROG; tries--) 591 DELAY(10); 592 if (tries == 0) 593 printf("%s: timeout waiting for autocalibration\n", 594 sc->sc_dev.dv_xname); 595 596 mtx_leave(&audio_lock); 597 598 sc->sc_need_commit = 0; 599 return (0); 600 } 601 602 int 603 cs4231_halt_output(void *vsc) 604 { 605 struct cs4231_softc *sc = (struct cs4231_softc *)vsc; 606 607 /* XXX Kills some capture bits */ 608 mtx_enter(&audio_lock); 609 APC_WRITE(sc, APC_CSR, APC_READ(sc, APC_CSR) & 610 ~(APC_CSR_EI | APC_CSR_GIE | APC_CSR_PIE | 611 APC_CSR_EIE | APC_CSR_PDMA_GO | APC_CSR_PMIE)); 612 cs4231_write(sc, SP_INTERFACE_CONFIG, 613 cs4231_read(sc, SP_INTERFACE_CONFIG) & (~PLAYBACK_ENABLE)); 614 sc->sc_playback.cs_locked = 0; 615 mtx_leave(&audio_lock); 616 return (0); 617 } 618 619 int 620 cs4231_halt_input(void *vsc) 621 { 622 struct cs4231_softc *sc = (struct cs4231_softc *)vsc; 623 624 /* XXX Kills some playback bits */ 625 mtx_enter(&audio_lock); 626 APC_WRITE(sc, APC_CSR, APC_CSR_CAPTURE_PAUSE); 627 cs4231_write(sc, SP_INTERFACE_CONFIG, 628 cs4231_read(sc, SP_INTERFACE_CONFIG) & (~CAPTURE_ENABLE)); 629 sc->sc_capture.cs_locked = 0; 630 mtx_leave(&audio_lock); 631 return (0); 632 } 633 634 int 635 cs4231_set_port(void *vsc, mixer_ctrl_t *cp) 636 { 637 struct cs4231_softc *sc = (struct cs4231_softc *)vsc; 638 int error = EINVAL; 639 640 DPRINTF(("cs4231_set_port: port=%d type=%d\n", cp->dev, cp->type)); 641 642 switch (cp->dev) { 643 case CSAUDIO_DAC_LVL: 644 if (cp->type != AUDIO_MIXER_VALUE) 645 break; 646 if (cp->un.value.num_channels == 1) 647 cs4231_write(sc, SP_LEFT_AUX1_CONTROL, 648 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] & 649 LINE_INPUT_ATTEN_BITS); 650 else if (cp->un.value.num_channels == 2) { 651 cs4231_write(sc, SP_LEFT_AUX1_CONTROL, 652 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] & 653 LINE_INPUT_ATTEN_BITS); 654 cs4231_write(sc, SP_RIGHT_AUX1_CONTROL, 655 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] & 656 LINE_INPUT_ATTEN_BITS); 657 } else 658 break; 659 error = 0; 660 break; 661 case CSAUDIO_LINE_IN_LVL: 662 if (cp->type != AUDIO_MIXER_VALUE) 663 break; 664 if (cp->un.value.num_channels == 1) 665 cs4231_write(sc, CS_LEFT_LINE_CONTROL, 666 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] & 667 AUX_INPUT_ATTEN_BITS); 668 else if (cp->un.value.num_channels == 2) { 669 cs4231_write(sc, CS_LEFT_LINE_CONTROL, 670 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] & 671 AUX_INPUT_ATTEN_BITS); 672 cs4231_write(sc, CS_RIGHT_LINE_CONTROL, 673 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] & 674 AUX_INPUT_ATTEN_BITS); 675 } else 676 break; 677 error = 0; 678 break; 679 case CSAUDIO_MIC_LVL: 680 if (cp->type != AUDIO_MIXER_VALUE) 681 break; 682 if (cp->un.value.num_channels == 1) { 683 #if 0 684 cs4231_write(sc, CS_MONO_IO_CONTROL, 685 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] & 686 MONO_INPUT_ATTEN_BITS); 687 #endif 688 } else 689 break; 690 error = 0; 691 break; 692 case CSAUDIO_CD_LVL: 693 if (cp->type != AUDIO_MIXER_VALUE) 694 break; 695 if (cp->un.value.num_channels == 1) { 696 cs4231_write(sc, SP_LEFT_AUX2_CONTROL, 697 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] & 698 LINE_INPUT_ATTEN_BITS); 699 } else if (cp->un.value.num_channels == 2) { 700 cs4231_write(sc, SP_LEFT_AUX2_CONTROL, 701 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] & 702 LINE_INPUT_ATTEN_BITS); 703 cs4231_write(sc, SP_RIGHT_AUX2_CONTROL, 704 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] & 705 LINE_INPUT_ATTEN_BITS); 706 } else 707 break; 708 error = 0; 709 break; 710 case CSAUDIO_MONITOR_LVL: 711 if (cp->type != AUDIO_MIXER_VALUE) 712 break; 713 if (cp->un.value.num_channels == 1) 714 cs4231_write(sc, SP_DIGITAL_MIX, 715 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] << 2); 716 else 717 break; 718 error = 0; 719 break; 720 case CSAUDIO_OUTPUT_LVL: 721 if (cp->type != AUDIO_MIXER_VALUE) 722 break; 723 if (cp->un.value.num_channels == 1) { 724 sc->sc_volume[CSPORT_SPEAKER].left = 725 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 726 sc->sc_volume[CSPORT_SPEAKER].right = 727 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 728 } 729 else if (cp->un.value.num_channels == 2) { 730 sc->sc_volume[CSPORT_SPEAKER].left = 731 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 732 sc->sc_volume[CSPORT_SPEAKER].right = 733 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 734 } 735 else 736 break; 737 738 cs4231_setup_output(sc); 739 error = 0; 740 break; 741 case CSAUDIO_OUTPUT: 742 if (cp->type != AUDIO_MIXER_ENUM) 743 break; 744 if (cp->un.ord != CSPORT_LINEOUT && 745 cp->un.ord != CSPORT_SPEAKER && 746 cp->un.ord != CSPORT_HEADPHONE) 747 return (EINVAL); 748 sc->sc_out_port = cp->un.ord; 749 cs4231_setup_output(sc); 750 error = 0; 751 break; 752 case CSAUDIO_LINE_IN_MUTE: 753 if (cp->type != AUDIO_MIXER_ENUM) 754 break; 755 sc->sc_mute[CSPORT_LINEIN] = cp->un.ord ? 1 : 0; 756 error = 0; 757 break; 758 case CSAUDIO_DAC_MUTE: 759 if (cp->type != AUDIO_MIXER_ENUM) 760 break; 761 sc->sc_mute[CSPORT_AUX1] = cp->un.ord ? 1 : 0; 762 error = 0; 763 break; 764 case CSAUDIO_CD_MUTE: 765 if (cp->type != AUDIO_MIXER_ENUM) 766 break; 767 sc->sc_mute[CSPORT_AUX2] = cp->un.ord ? 1 : 0; 768 error = 0; 769 break; 770 case CSAUDIO_MIC_MUTE: 771 if (cp->type != AUDIO_MIXER_ENUM) 772 break; 773 sc->sc_mute[CSPORT_MONO] = cp->un.ord ? 1 : 0; 774 error = 0; 775 break; 776 case CSAUDIO_MONITOR_MUTE: 777 if (cp->type != AUDIO_MIXER_ENUM) 778 break; 779 sc->sc_mute[CSPORT_MONITOR] = cp->un.ord ? 1 : 0; 780 error = 0; 781 break; 782 case CSAUDIO_OUTPUT_MUTE: 783 if (cp->type != AUDIO_MIXER_ENUM) 784 break; 785 sc->sc_mute[CSPORT_SPEAKER] = cp->un.ord ? 1 : 0; 786 cs4231_setup_output(sc); 787 error = 0; 788 break; 789 case CSAUDIO_REC_LVL: 790 if (cp->type != AUDIO_MIXER_VALUE) 791 break; 792 if (cp->un.value.num_channels == 1) { 793 sc->sc_adc.left = 794 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 795 sc->sc_adc.right = 796 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 797 } else if (cp->un.value.num_channels == 2) { 798 sc->sc_adc.left = 799 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 800 sc->sc_adc.right = 801 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 802 } else 803 break; 804 cs4231_setup_output(sc); 805 error = 0; 806 break; 807 case CSAUDIO_RECORD_SOURCE: 808 if (cp->type != AUDIO_MIXER_ENUM) 809 break; 810 if (cp->un.ord == CSPORT_MICROPHONE || 811 cp->un.ord == CSPORT_LINEIN || 812 cp->un.ord == CSPORT_AUX1 || 813 cp->un.ord == CSPORT_DAC) { 814 sc->sc_in_port = cp->un.ord; 815 error = 0; 816 cs4231_setup_output(sc); 817 } 818 break; 819 } 820 821 return (error); 822 } 823 824 int 825 cs4231_get_port(void *vsc, mixer_ctrl_t *cp) 826 { 827 struct cs4231_softc *sc = (struct cs4231_softc *)vsc; 828 int error = EINVAL; 829 830 DPRINTF(("cs4231_get_port: port=%d type=%d\n", cp->dev, cp->type)); 831 832 switch (cp->dev) { 833 case CSAUDIO_DAC_LVL: 834 if (cp->type != AUDIO_MIXER_VALUE) 835 break; 836 if (cp->un.value.num_channels == 1) 837 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]= 838 cs4231_read(sc, SP_LEFT_AUX1_CONTROL) & 839 LINE_INPUT_ATTEN_BITS; 840 else if (cp->un.value.num_channels == 2) { 841 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 842 cs4231_read(sc, SP_LEFT_AUX1_CONTROL) & 843 LINE_INPUT_ATTEN_BITS; 844 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 845 cs4231_read(sc, SP_RIGHT_AUX1_CONTROL) & 846 LINE_INPUT_ATTEN_BITS; 847 } else 848 break; 849 error = 0; 850 break; 851 case CSAUDIO_LINE_IN_LVL: 852 if (cp->type != AUDIO_MIXER_VALUE) 853 break; 854 if (cp->un.value.num_channels == 1) 855 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = 856 cs4231_read(sc, CS_LEFT_LINE_CONTROL) & AUX_INPUT_ATTEN_BITS; 857 else if (cp->un.value.num_channels == 2) { 858 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 859 cs4231_read(sc, CS_LEFT_LINE_CONTROL) & AUX_INPUT_ATTEN_BITS; 860 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 861 cs4231_read(sc, CS_RIGHT_LINE_CONTROL) & AUX_INPUT_ATTEN_BITS; 862 } else 863 break; 864 error = 0; 865 break; 866 case CSAUDIO_MIC_LVL: 867 if (cp->type != AUDIO_MIXER_VALUE) 868 break; 869 if (cp->un.value.num_channels == 1) { 870 #if 0 871 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = 872 cs4231_read(sc, CS_MONO_IO_CONTROL) & 873 MONO_INPUT_ATTEN_BITS; 874 #endif 875 } else 876 break; 877 error = 0; 878 break; 879 case CSAUDIO_CD_LVL: 880 if (cp->type != AUDIO_MIXER_VALUE) 881 break; 882 if (cp->un.value.num_channels == 1) 883 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = 884 cs4231_read(sc, SP_LEFT_AUX2_CONTROL) & 885 LINE_INPUT_ATTEN_BITS; 886 else if (cp->un.value.num_channels == 2) { 887 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 888 cs4231_read(sc, SP_LEFT_AUX2_CONTROL) & 889 LINE_INPUT_ATTEN_BITS; 890 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 891 cs4231_read(sc, SP_RIGHT_AUX2_CONTROL) & 892 LINE_INPUT_ATTEN_BITS; 893 } 894 else 895 break; 896 error = 0; 897 break; 898 case CSAUDIO_MONITOR_LVL: 899 if (cp->type != AUDIO_MIXER_VALUE) 900 break; 901 if (cp->un.value.num_channels != 1) 902 break; 903 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = 904 cs4231_read(sc, SP_DIGITAL_MIX) >> 2; 905 error = 0; 906 break; 907 case CSAUDIO_OUTPUT_LVL: 908 if (cp->type != AUDIO_MIXER_VALUE) 909 break; 910 if (cp->un.value.num_channels == 1) 911 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = 912 sc->sc_volume[CSPORT_SPEAKER].left; 913 else if (cp->un.value.num_channels == 2) { 914 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 915 sc->sc_volume[CSPORT_SPEAKER].left; 916 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 917 sc->sc_volume[CSPORT_SPEAKER].right; 918 } 919 else 920 break; 921 error = 0; 922 break; 923 case CSAUDIO_LINE_IN_MUTE: 924 if (cp->type != AUDIO_MIXER_ENUM) 925 break; 926 cp->un.ord = sc->sc_mute[CSPORT_LINEIN] ? 1 : 0; 927 error = 0; 928 break; 929 case CSAUDIO_DAC_MUTE: 930 if (cp->type != AUDIO_MIXER_ENUM) 931 break; 932 cp->un.ord = sc->sc_mute[CSPORT_AUX1] ? 1 : 0; 933 error = 0; 934 break; 935 case CSAUDIO_CD_MUTE: 936 if (cp->type != AUDIO_MIXER_ENUM) 937 break; 938 cp->un.ord = sc->sc_mute[CSPORT_AUX2] ? 1 : 0; 939 error = 0; 940 break; 941 case CSAUDIO_MIC_MUTE: 942 if (cp->type != AUDIO_MIXER_ENUM) 943 break; 944 cp->un.ord = sc->sc_mute[CSPORT_MONO] ? 1 : 0; 945 error = 0; 946 break; 947 case CSAUDIO_MONITOR_MUTE: 948 if (cp->type != AUDIO_MIXER_ENUM) 949 break; 950 cp->un.ord = sc->sc_mute[CSPORT_MONITOR] ? 1 : 0; 951 error = 0; 952 break; 953 case CSAUDIO_OUTPUT_MUTE: 954 if (cp->type != AUDIO_MIXER_ENUM) 955 break; 956 cp->un.ord = sc->sc_mute[CSPORT_SPEAKER] ? 1 : 0; 957 error = 0; 958 break; 959 case CSAUDIO_REC_LVL: 960 if (cp->type != AUDIO_MIXER_VALUE) 961 break; 962 if (cp->un.value.num_channels == 1) { 963 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = 964 sc->sc_adc.left; 965 } else if (cp->un.value.num_channels == 2) { 966 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 967 sc->sc_adc.left; 968 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 969 sc->sc_adc.right; 970 } else 971 break; 972 error = 0; 973 break; 974 case CSAUDIO_RECORD_SOURCE: 975 if (cp->type != AUDIO_MIXER_ENUM) 976 break; 977 cp->un.ord = sc->sc_in_port; 978 error = 0; 979 break; 980 case CSAUDIO_OUTPUT: 981 if (cp->type != AUDIO_MIXER_ENUM) 982 break; 983 cp->un.ord = sc->sc_out_port; 984 error = 0; 985 break; 986 } 987 return (error); 988 } 989 990 int 991 cs4231_query_devinfo(void *vsc, mixer_devinfo_t *dip) 992 { 993 int err = 0; 994 995 switch (dip->index) { 996 case CSAUDIO_MIC_LVL: /* mono/microphone mixer */ 997 dip->type = AUDIO_MIXER_VALUE; 998 dip->mixer_class = CSAUDIO_INPUT_CLASS; 999 dip->prev = AUDIO_MIXER_LAST; 1000 dip->next = CSAUDIO_MIC_MUTE; 1001 strlcpy(dip->label.name, AudioNmicrophone, 1002 sizeof dip->label.name); 1003 dip->un.v.num_channels = 1; 1004 strlcpy(dip->un.v.units.name, AudioNvolume, 1005 sizeof dip->un.v.units.name); 1006 break; 1007 case CSAUDIO_DAC_LVL: /* dacout */ 1008 dip->type = AUDIO_MIXER_VALUE; 1009 dip->mixer_class = CSAUDIO_INPUT_CLASS; 1010 dip->prev = AUDIO_MIXER_LAST; 1011 dip->next = CSAUDIO_DAC_MUTE; 1012 strlcpy(dip->label.name, AudioNdac, 1013 sizeof dip->label.name); 1014 dip->un.v.num_channels = 2; 1015 strlcpy(dip->un.v.units.name, AudioNvolume, 1016 sizeof dip->un.v.units.name); 1017 break; 1018 case CSAUDIO_LINE_IN_LVL: /* line */ 1019 dip->type = AUDIO_MIXER_VALUE; 1020 dip->mixer_class = CSAUDIO_INPUT_CLASS; 1021 dip->prev = AUDIO_MIXER_LAST; 1022 dip->next = CSAUDIO_LINE_IN_MUTE; 1023 strlcpy(dip->label.name, AudioNline, 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_CD_LVL: /* cd */ 1029 dip->type = AUDIO_MIXER_VALUE; 1030 dip->mixer_class = CSAUDIO_INPUT_CLASS; 1031 dip->prev = AUDIO_MIXER_LAST; 1032 dip->next = CSAUDIO_CD_MUTE; 1033 strlcpy(dip->label.name, AudioNcd, 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_MONITOR_LVL: /* monitor level */ 1039 dip->type = AUDIO_MIXER_VALUE; 1040 dip->mixer_class = CSAUDIO_MONITOR_CLASS; 1041 dip->prev = AUDIO_MIXER_LAST; 1042 dip->next = CSAUDIO_MONITOR_MUTE; 1043 strlcpy(dip->label.name, AudioNmonitor, 1044 sizeof dip->label.name); 1045 dip->un.v.num_channels = 1; 1046 strlcpy(dip->un.v.units.name, AudioNvolume, 1047 sizeof dip->un.v.units.name); 1048 break; 1049 case CSAUDIO_OUTPUT_LVL: 1050 dip->type = AUDIO_MIXER_VALUE; 1051 dip->mixer_class = CSAUDIO_OUTPUT_CLASS; 1052 dip->prev = AUDIO_MIXER_LAST; 1053 dip->next = CSAUDIO_OUTPUT_MUTE; 1054 strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name); 1055 dip->un.v.num_channels = 2; 1056 strlcpy(dip->un.v.units.name, AudioNvolume, 1057 sizeof dip->un.v.units.name); 1058 break; 1059 case CSAUDIO_LINE_IN_MUTE: 1060 dip->type = AUDIO_MIXER_ENUM; 1061 dip->mixer_class = CSAUDIO_INPUT_CLASS; 1062 dip->prev = CSAUDIO_LINE_IN_LVL; 1063 dip->next = AUDIO_MIXER_LAST; 1064 goto mute; 1065 case CSAUDIO_DAC_MUTE: 1066 dip->type = AUDIO_MIXER_ENUM; 1067 dip->mixer_class = CSAUDIO_INPUT_CLASS; 1068 dip->prev = CSAUDIO_DAC_LVL; 1069 dip->next = AUDIO_MIXER_LAST; 1070 goto mute; 1071 case CSAUDIO_CD_MUTE: 1072 dip->type = AUDIO_MIXER_ENUM; 1073 dip->mixer_class = CSAUDIO_INPUT_CLASS; 1074 dip->prev = CSAUDIO_CD_LVL; 1075 dip->next = AUDIO_MIXER_LAST; 1076 goto mute; 1077 case CSAUDIO_MIC_MUTE: 1078 dip->type = AUDIO_MIXER_ENUM; 1079 dip->mixer_class = CSAUDIO_INPUT_CLASS; 1080 dip->prev = CSAUDIO_MIC_LVL; 1081 dip->next = AUDIO_MIXER_LAST; 1082 goto mute; 1083 case CSAUDIO_MONITOR_MUTE: 1084 dip->type = AUDIO_MIXER_ENUM; 1085 dip->mixer_class = CSAUDIO_OUTPUT_CLASS; 1086 dip->prev = CSAUDIO_MONITOR_LVL; 1087 dip->next = AUDIO_MIXER_LAST; 1088 goto mute; 1089 case CSAUDIO_OUTPUT_MUTE: 1090 dip->type = AUDIO_MIXER_ENUM; 1091 dip->mixer_class = CSAUDIO_OUTPUT_CLASS; 1092 dip->prev = CSAUDIO_OUTPUT_LVL; 1093 dip->next = AUDIO_MIXER_LAST; 1094 goto mute; 1095 1096 mute: 1097 strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name); 1098 dip->un.e.num_mem = 2; 1099 strlcpy(dip->un.e.member[0].label.name, AudioNon, 1100 sizeof dip->un.e.member[0].label.name); 1101 dip->un.e.member[0].ord = 0; 1102 strlcpy(dip->un.e.member[1].label.name, AudioNoff, 1103 sizeof dip->un.e.member[1].label.name); 1104 dip->un.e.member[1].ord = 1; 1105 break; 1106 case CSAUDIO_REC_LVL: /* record level */ 1107 dip->type = AUDIO_MIXER_VALUE; 1108 dip->mixer_class = CSAUDIO_RECORD_CLASS; 1109 dip->prev = AUDIO_MIXER_LAST; 1110 dip->next = CSAUDIO_RECORD_SOURCE; 1111 strlcpy(dip->label.name, AudioNrecord, sizeof dip->label.name); 1112 dip->un.v.num_channels = 2; 1113 strlcpy(dip->un.v.units.name, AudioNvolume, 1114 sizeof dip->un.v.units.name); 1115 break; 1116 case CSAUDIO_RECORD_SOURCE: 1117 dip->type = AUDIO_MIXER_ENUM; 1118 dip->mixer_class = CSAUDIO_RECORD_CLASS; 1119 dip->prev = CSAUDIO_REC_LVL; 1120 dip->next = AUDIO_MIXER_LAST; 1121 strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name); 1122 dip->un.e.num_mem = 4; 1123 strlcpy(dip->un.e.member[0].label.name, AudioNmicrophone, 1124 sizeof dip->un.e.member[0].label.name); 1125 dip->un.e.member[0].ord = CSPORT_MICROPHONE; 1126 strlcpy(dip->un.e.member[1].label.name, AudioNline, 1127 sizeof dip->un.e.member[1].label.name); 1128 dip->un.e.member[1].ord = CSPORT_LINEIN; 1129 strlcpy(dip->un.e.member[2].label.name, AudioNcd, 1130 sizeof dip->un.e.member[2].label.name); 1131 dip->un.e.member[2].ord = CSPORT_AUX1; 1132 strlcpy(dip->un.e.member[3].label.name, AudioNdac, 1133 sizeof dip->un.e.member[3].label.name); 1134 dip->un.e.member[3].ord = CSPORT_DAC; 1135 break; 1136 case CSAUDIO_OUTPUT: 1137 dip->type = AUDIO_MIXER_ENUM; 1138 dip->mixer_class = CSAUDIO_MONITOR_CLASS; 1139 dip->prev = dip->next = AUDIO_MIXER_LAST; 1140 strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name); 1141 dip->un.e.num_mem = 3; 1142 strlcpy(dip->un.e.member[0].label.name, AudioNspeaker, 1143 sizeof dip->un.e.member[0].label.name); 1144 dip->un.e.member[0].ord = CSPORT_SPEAKER; 1145 strlcpy(dip->un.e.member[1].label.name, AudioNline, 1146 sizeof dip->un.e.member[1].label.name); 1147 dip->un.e.member[1].ord = CSPORT_LINEOUT; 1148 strlcpy(dip->un.e.member[2].label.name, AudioNheadphone, 1149 sizeof dip->un.e.member[2].label.name); 1150 dip->un.e.member[2].ord = CSPORT_HEADPHONE; 1151 break; 1152 case CSAUDIO_INPUT_CLASS: /* input class descriptor */ 1153 dip->type = AUDIO_MIXER_CLASS; 1154 dip->mixer_class = CSAUDIO_INPUT_CLASS; 1155 dip->prev = AUDIO_MIXER_LAST; 1156 dip->next = AUDIO_MIXER_LAST; 1157 strlcpy(dip->label.name, AudioCinputs, sizeof dip->label.name); 1158 break; 1159 case CSAUDIO_OUTPUT_CLASS: /* output class descriptor */ 1160 dip->type = AUDIO_MIXER_CLASS; 1161 dip->mixer_class = CSAUDIO_OUTPUT_CLASS; 1162 dip->prev = AUDIO_MIXER_LAST; 1163 dip->next = AUDIO_MIXER_LAST; 1164 strlcpy(dip->label.name, AudioCoutputs, 1165 sizeof dip->label.name); 1166 break; 1167 case CSAUDIO_MONITOR_CLASS: /* monitor class descriptor */ 1168 dip->type = AUDIO_MIXER_CLASS; 1169 dip->mixer_class = CSAUDIO_MONITOR_CLASS; 1170 dip->prev = AUDIO_MIXER_LAST; 1171 dip->next = AUDIO_MIXER_LAST; 1172 strlcpy(dip->label.name, AudioCmonitor, 1173 sizeof dip->label.name); 1174 break; 1175 case CSAUDIO_RECORD_CLASS: /* record class descriptor */ 1176 dip->type = AUDIO_MIXER_CLASS; 1177 dip->mixer_class = CSAUDIO_RECORD_CLASS; 1178 dip->prev = AUDIO_MIXER_LAST; 1179 dip->next = AUDIO_MIXER_LAST; 1180 strlcpy(dip->label.name, AudioCrecord, sizeof dip->label.name); 1181 break; 1182 default: 1183 err = ENXIO; 1184 } 1185 1186 return (err); 1187 } 1188 1189 int 1190 cs4231_get_props(void *vsc) 1191 { 1192 return (AUDIO_PROP_FULLDUPLEX); 1193 } 1194 1195 /* 1196 * Hardware interrupt handler 1197 */ 1198 int 1199 cs4231_intr(void *vsc) 1200 { 1201 struct cs4231_softc *sc = (struct cs4231_softc *)vsc; 1202 u_int32_t csr; 1203 u_int8_t reg, status; 1204 struct cs_dma *p; 1205 int r = 0; 1206 1207 mtx_enter(&audio_lock); 1208 csr = APC_READ(sc, APC_CSR); 1209 APC_WRITE(sc, APC_CSR, csr); 1210 1211 if ((csr & APC_CSR_EIE) && (csr & APC_CSR_EI)) { 1212 printf("%s: error interrupt\n", sc->sc_dev.dv_xname); 1213 r = 1; 1214 } 1215 1216 if ((csr & APC_CSR_PIE) && (csr & APC_CSR_PI)) { 1217 /* playback interrupt */ 1218 r = 1; 1219 } 1220 1221 if ((csr & APC_CSR_GIE) && (csr & APC_CSR_GI)) { 1222 /* general interrupt */ 1223 status = CS_READ(sc, AD1848_STATUS); 1224 if (status & (INTERRUPT_STATUS | SAMPLE_ERROR)) { 1225 reg = cs4231_read(sc, CS_IRQ_STATUS); 1226 if (reg & CS_AFS_PI) { 1227 cs4231_write(sc, SP_LOWER_BASE_COUNT, 0xff); 1228 cs4231_write(sc, SP_UPPER_BASE_COUNT, 0xff); 1229 } 1230 if (reg & CS_AFS_CI) { 1231 cs4231_write(sc, CS_LOWER_REC_CNT, 0xff); 1232 cs4231_write(sc, CS_UPPER_REC_CNT, 0xff); 1233 } 1234 CS_WRITE(sc, AD1848_STATUS, 0); 1235 } 1236 r = 1; 1237 } 1238 1239 1240 if (csr & (APC_CSR_PI|APC_CSR_PMI|APC_CSR_PIE|APC_CSR_PD)) 1241 r = 1; 1242 1243 if ((csr & APC_CSR_PMIE) && (csr & APC_CSR_PMI)) { 1244 struct cs_channel *chan = &sc->sc_playback; 1245 u_long nextaddr, togo; 1246 1247 p = chan->cs_curdma; 1248 togo = chan->cs_segsz - chan->cs_cnt; 1249 if (togo == 0) { 1250 nextaddr = (u_int32_t)p->dmamap->dm_segs[0].ds_addr; 1251 chan->cs_cnt = togo = chan->cs_blksz; 1252 } else { 1253 nextaddr = APC_READ(sc, APC_PNVA) + chan->cs_blksz; 1254 if (togo > chan->cs_blksz) 1255 togo = chan->cs_blksz; 1256 chan->cs_cnt += togo; 1257 } 1258 1259 APC_WRITE(sc, APC_PNVA, nextaddr); 1260 APC_WRITE(sc, APC_PNC, togo); 1261 1262 if (chan->cs_intr != NULL) 1263 (*chan->cs_intr)(chan->cs_arg); 1264 r = 1; 1265 } 1266 1267 if ((csr & APC_CSR_CIE) && (csr & APC_CSR_CI)) { 1268 if (csr & APC_CSR_CD) { 1269 struct cs_channel *chan = &sc->sc_capture; 1270 u_long nextaddr, togo; 1271 1272 p = chan->cs_curdma; 1273 togo = chan->cs_segsz - chan->cs_cnt; 1274 if (togo == 0) { 1275 nextaddr = 1276 (u_int32_t)p->dmamap->dm_segs[0].ds_addr; 1277 chan->cs_cnt = togo = chan->cs_blksz; 1278 } else { 1279 nextaddr = APC_READ(sc, APC_CNVA) + 1280 chan->cs_blksz; 1281 if (togo > chan->cs_blksz) 1282 togo = chan->cs_blksz; 1283 chan->cs_cnt += togo; 1284 } 1285 1286 APC_WRITE(sc, APC_CNVA, nextaddr); 1287 APC_WRITE(sc, APC_CNC, togo); 1288 1289 if (chan->cs_intr != NULL) 1290 (*chan->cs_intr)(chan->cs_arg); 1291 } 1292 r = 1; 1293 } 1294 1295 if ((csr & APC_CSR_CMIE) && (csr & APC_CSR_CMI)) { 1296 /* capture empty */ 1297 r = 1; 1298 } 1299 1300 mtx_leave(&audio_lock); 1301 return (r); 1302 } 1303 1304 void * 1305 cs4231_alloc(void *vsc, int direction, size_t size, int pool, int flags) 1306 { 1307 struct cs4231_softc *sc = (struct cs4231_softc *)vsc; 1308 bus_dma_tag_t dmat = sc->sc_dmatag; 1309 struct cs_dma *p; 1310 1311 p = (struct cs_dma *)malloc(sizeof(struct cs_dma), pool, flags); 1312 if (p == NULL) 1313 return (NULL); 1314 1315 if (bus_dmamap_create(dmat, size, 1, size, 0, 1316 BUS_DMA_NOWAIT, &p->dmamap) != 0) 1317 goto fail; 1318 1319 p->size = size; 1320 1321 if (bus_dmamem_alloc(dmat, size, 64*1024, 0, p->segs, 1322 nitems(p->segs), &p->nsegs, 1323 BUS_DMA_NOWAIT) != 0) 1324 goto fail1; 1325 1326 if (bus_dmamem_map(dmat, p->segs, p->nsegs, p->size, 1327 &p->addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT) != 0) 1328 goto fail2; 1329 1330 if (bus_dmamap_load(dmat, p->dmamap, p->addr, size, NULL, 1331 BUS_DMA_NOWAIT) != 0) 1332 goto fail3; 1333 1334 p->next = sc->sc_dmas; 1335 sc->sc_dmas = p; 1336 return (p->addr); 1337 1338 fail3: 1339 bus_dmamem_unmap(dmat, p->addr, p->size); 1340 fail2: 1341 bus_dmamem_free(dmat, p->segs, p->nsegs); 1342 fail1: 1343 bus_dmamap_destroy(dmat, p->dmamap); 1344 fail: 1345 free(p, pool, 0); 1346 return (NULL); 1347 } 1348 1349 void 1350 cs4231_free(void *vsc, void *ptr, int pool) 1351 { 1352 struct cs4231_softc *sc = vsc; 1353 bus_dma_tag_t dmat = sc->sc_dmatag; 1354 struct cs_dma *p, **pp; 1355 1356 for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &(*pp)->next) { 1357 if (p->addr != ptr) 1358 continue; 1359 bus_dmamap_unload(dmat, p->dmamap); 1360 bus_dmamem_unmap(dmat, p->addr, p->size); 1361 bus_dmamem_free(dmat, p->segs, p->nsegs); 1362 bus_dmamap_destroy(dmat, p->dmamap); 1363 *pp = p->next; 1364 free(p, pool, 0); 1365 return; 1366 } 1367 printf("%s: attempt to free rogue pointer\n", sc->sc_dev.dv_xname); 1368 } 1369 1370 int 1371 cs4231_trigger_output(void *vsc, void *start, void *end, int blksize, 1372 void (*intr)(void *), void *arg, struct audio_params *param) 1373 { 1374 struct cs4231_softc *sc = vsc; 1375 struct cs_channel *chan = &sc->sc_playback; 1376 struct cs_dma *p; 1377 u_int32_t csr; 1378 u_long n; 1379 1380 if (chan->cs_locked != 0) { 1381 printf("%s: trigger_output: already running\n", 1382 sc->sc_dev.dv_xname); 1383 return (EINVAL); 1384 } 1385 1386 chan->cs_locked = 1; 1387 chan->cs_intr = intr; 1388 chan->cs_arg = arg; 1389 1390 for (p = sc->sc_dmas; p->addr != start; p = p->next) 1391 /*EMPTY*/; 1392 if (p == NULL) { 1393 printf("%s: trigger_output: bad addr: %p\n", 1394 sc->sc_dev.dv_xname, start); 1395 return (EINVAL); 1396 } 1397 1398 n = (char *)end - (char *)start; 1399 1400 /* 1401 * Do only `blksize' at a time, so audio_pint() is kept 1402 * synchronous with us... 1403 */ 1404 chan->cs_blksz = blksize; 1405 chan->cs_curdma = p; 1406 chan->cs_segsz = n; 1407 1408 if (n > chan->cs_blksz) 1409 n = chan->cs_blksz; 1410 1411 chan->cs_cnt = n; 1412 1413 mtx_enter(&audio_lock); 1414 csr = APC_READ(sc, APC_CSR); 1415 1416 APC_WRITE(sc, APC_PNVA, (u_long)p->dmamap->dm_segs[0].ds_addr); 1417 APC_WRITE(sc, APC_PNC, (u_long)n); 1418 1419 if ((csr & APC_CSR_PDMA_GO) == 0 || (csr & APC_CSR_PPAUSE) != 0) { 1420 APC_WRITE(sc, APC_CSR, 1421 APC_READ(sc, APC_CSR) & ~(APC_CSR_PIE | APC_CSR_PPAUSE)); 1422 APC_WRITE(sc, APC_CSR, APC_READ(sc, APC_CSR) | 1423 APC_CSR_EI | APC_CSR_GIE | APC_CSR_PIE | APC_CSR_EIE | 1424 APC_CSR_PMIE | APC_CSR_PDMA_GO); 1425 cs4231_write(sc, SP_LOWER_BASE_COUNT, 0xff); 1426 cs4231_write(sc, SP_UPPER_BASE_COUNT, 0xff); 1427 cs4231_write(sc, SP_INTERFACE_CONFIG, 1428 cs4231_read(sc, SP_INTERFACE_CONFIG) | PLAYBACK_ENABLE); 1429 } 1430 mtx_leave(&audio_lock); 1431 return (0); 1432 } 1433 1434 int 1435 cs4231_trigger_input(void *vsc, void *start, void *end, int blksize, 1436 void (*intr)(void *), void *arg, struct audio_params *param) 1437 { 1438 struct cs4231_softc *sc = vsc; 1439 struct cs_channel *chan = &sc->sc_capture; 1440 struct cs_dma *p; 1441 u_int32_t csr; 1442 u_long n; 1443 1444 if (chan->cs_locked != 0) { 1445 printf("%s: trigger_input: already running\n", 1446 sc->sc_dev.dv_xname); 1447 return (EINVAL); 1448 } 1449 chan->cs_locked = 1; 1450 chan->cs_intr = intr; 1451 chan->cs_arg = arg; 1452 1453 for (p = sc->sc_dmas; p->addr != start; p = p->next) 1454 /*EMPTY*/; 1455 if (p == NULL) { 1456 printf("%s: trigger_input: bad addr: %p\n", 1457 sc->sc_dev.dv_xname, start); 1458 return (EINVAL); 1459 } 1460 1461 n = (char *)end - (char *)start; 1462 1463 /* 1464 * Do only `blksize' at a time, so audio_cint() is kept 1465 * synchronous with us... 1466 */ 1467 chan->cs_blksz = blksize; 1468 chan->cs_curdma = p; 1469 chan->cs_segsz = n; 1470 1471 if (n > chan->cs_blksz) 1472 n = chan->cs_blksz; 1473 chan->cs_cnt = n; 1474 1475 mtx_enter(&audio_lock); 1476 APC_WRITE(sc, APC_CNVA, p->dmamap->dm_segs[0].ds_addr); 1477 APC_WRITE(sc, APC_CNC, (u_long)n); 1478 1479 csr = APC_READ(sc, APC_CSR); 1480 if ((csr & APC_CSR_CDMA_GO) == 0 || (csr & APC_CSR_CPAUSE) != 0) { 1481 csr &= APC_CSR_CPAUSE; 1482 csr |= APC_CSR_GIE | APC_CSR_CMIE | APC_CSR_CIE | APC_CSR_EI | 1483 APC_CSR_CDMA_GO; 1484 APC_WRITE(sc, APC_CSR, csr); 1485 cs4231_write(sc, CS_LOWER_REC_CNT, 0xff); 1486 cs4231_write(sc, CS_UPPER_REC_CNT, 0xff); 1487 cs4231_write(sc, SP_INTERFACE_CONFIG, 1488 cs4231_read(sc, SP_INTERFACE_CONFIG) | CAPTURE_ENABLE); 1489 } 1490 1491 if (APC_READ(sc, APC_CSR) & APC_CSR_CD) { 1492 u_long nextaddr, togo; 1493 1494 p = chan->cs_curdma; 1495 togo = chan->cs_segsz - chan->cs_cnt; 1496 if (togo == 0) { 1497 nextaddr = (u_int32_t)p->dmamap->dm_segs[0].ds_addr; 1498 chan->cs_cnt = togo = chan->cs_blksz; 1499 } else { 1500 nextaddr = APC_READ(sc, APC_CNVA) + chan->cs_blksz; 1501 if (togo > chan->cs_blksz) 1502 togo = chan->cs_blksz; 1503 chan->cs_cnt += togo; 1504 } 1505 1506 APC_WRITE(sc, APC_CNVA, nextaddr); 1507 APC_WRITE(sc, APC_CNC, togo); 1508 } 1509 1510 mtx_leave(&audio_lock); 1511 return (0); 1512 } 1513