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