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