1 /* $OpenBSD: cmpci.c,v 1.2 2001/06/12 15:40:30 niklas Exp $ */ 2 3 /* 4 * Copyright (c) 2000 Takuya SHIOZAKI 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 AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 */ 29 30 /* 31 * C-Media CMI8x38 Audio Chip Support. 32 * 33 * TODO: 34 * - Legacy MPU, OPL and Joystick support (but, I have no interest...) 35 * - SPDIF support 36 * 37 */ 38 39 #undef CMPCI_SPDIF_SUPPORT /* XXX: not working */ 40 41 #if defined(AUDIO_DEBUG) || defined(DEBUG) 42 #define DPRINTF(x) printf x 43 #else 44 #define DPRINTF(x) 45 #endif 46 47 #include <sys/param.h> 48 #include <sys/systm.h> 49 #include <sys/kernel.h> 50 #include <sys/malloc.h> 51 #include <sys/device.h> 52 #include <sys/proc.h> 53 54 #include <dev/pci/pcidevs.h> 55 #include <dev/pci/pcivar.h> 56 57 #include <sys/audioio.h> 58 #include <dev/audio_if.h> 59 #include <dev/mulaw.h> 60 #include <dev/auconv.h> 61 62 #include <dev/pci/cmpcireg.h> 63 #include <dev/pci/cmpcivar.h> 64 65 #include <machine/bus.h> 66 #include <machine/intr.h> 67 68 /* 69 * Low-level HW interface 70 */ 71 static __inline uint8_t cmpci_mixerreg_read __P((struct cmpci_softc *, 72 uint8_t)); 73 static __inline void cmpci_mixerreg_write __P((struct cmpci_softc *, 74 uint8_t, uint8_t)); 75 static __inline void cmpci_reg_partial_write_4 __P((struct cmpci_softc *, 76 int, int, 77 uint32_t, uint32_t)); 78 static __inline void cmpci_reg_set_4 __P((struct cmpci_softc *, 79 int, uint32_t)); 80 static __inline void cmpci_reg_clear_4 __P((struct cmpci_softc *, 81 int, uint32_t)); 82 static int cmpci_rate_to_index __P((int)); 83 static __inline int cmpci_index_to_rate __P((int)); 84 static __inline int cmpci_index_to_divider __P((int)); 85 86 static int cmpci_adjust __P((int, int)); 87 static void cmpci_set_mixer_gain __P((struct cmpci_softc *, int)); 88 static int cmpci_set_in_ports __P((struct cmpci_softc *, int)); 89 90 91 /* 92 * autoconf interface 93 */ 94 int cmpci_match __P((struct device *, void *, void *)); 95 void cmpci_attach __P((struct device *, struct device *, void *)); 96 97 struct cfdriver cmpci_cd = { 98 NULL, "cmpci", DV_DULL 99 }; 100 101 struct cfattach cmpci_ca = { 102 sizeof (struct cmpci_softc), cmpci_match, cmpci_attach 103 }; 104 105 struct audio_device cmpci_device = { 106 "CMI PCI Audio", 107 "", 108 "cmpci" 109 }; 110 111 /* interrupt */ 112 int cmpci_intr __P((void *)); 113 114 115 /* 116 * DMA stuff 117 */ 118 int cmpci_alloc_dmamem __P((struct cmpci_softc *, 119 size_t, int, int, caddr_t *)); 120 int cmpci_free_dmamem __P((struct cmpci_softc *, caddr_t, int)); 121 struct cmpci_dmanode * cmpci_find_dmamem __P((struct cmpci_softc *, 122 caddr_t)); 123 124 /* 125 * Interface to machine independent layer 126 */ 127 int cmpci_open __P((void *, int)); 128 void cmpci_close __P((void *)); 129 int cmpci_query_encoding __P((void *, struct audio_encoding *)); 130 int cmpci_set_params __P((void *, int, int, 131 struct audio_params *, 132 struct audio_params *)); 133 int cmpci_round_blocksize __P((void *, int)); 134 int cmpci_halt_output __P((void *)); 135 int cmpci_halt_input __P((void *)); 136 int cmpci_getdev __P((void *, struct audio_device *)); 137 int cmpci_set_port __P((void *, mixer_ctrl_t *)); 138 int cmpci_get_port __P((void *, mixer_ctrl_t *)); 139 int cmpci_query_devinfo __P((void *, mixer_devinfo_t *)); 140 void *cmpci_malloc __P((void *, u_long, int, int)); 141 void cmpci_free __P((void *, void *, int)); 142 u_long cmpci_round_buffersize __P((void *, u_long)); 143 int cmpci_mappage __P((void *, void *, int, int)); 144 int cmpci_get_props __P((void *)); 145 int cmpci_trigger_output __P((void *, void *, void *, int, 146 void (*)(void *), void *, 147 struct audio_params *)); 148 int cmpci_trigger_input __P((void *, void *, void *, int, 149 void (*)(void *), void *, 150 struct audio_params *)); 151 152 struct audio_hw_if cmpci_hw_if = { 153 cmpci_open, /* open */ 154 cmpci_close, /* close */ 155 NULL, /* drain */ 156 cmpci_query_encoding, /* query_encoding */ 157 cmpci_set_params, /* set_params */ 158 cmpci_round_blocksize, /* round_blocksize */ 159 NULL, /* commit_settings */ 160 NULL, /* init_output */ 161 NULL, /* init_input */ 162 NULL, /* start_output */ 163 NULL, /* start_input */ 164 cmpci_halt_output, /* halt_output */ 165 cmpci_halt_input, /* halt_input */ 166 NULL, /* speaker_ctl */ 167 cmpci_getdev, /* getdev */ 168 NULL, /* setfd */ 169 cmpci_set_port, /* set_port */ 170 cmpci_get_port, /* get_port */ 171 cmpci_query_devinfo, /* query_devinfo */ 172 cmpci_malloc, /* malloc */ 173 cmpci_free, /* free */ 174 cmpci_round_buffersize, /* round_buffersize */ 175 cmpci_mappage, /* mappage */ 176 cmpci_get_props, /* get_props */ 177 cmpci_trigger_output, /* trigger_output */ 178 cmpci_trigger_input /* trigger_input */ 179 }; 180 181 182 /* 183 * Low-level HW interface 184 */ 185 186 /* mixer register read/write */ 187 static __inline uint8_t 188 cmpci_mixerreg_read(sc, no) 189 struct cmpci_softc *sc; 190 uint8_t no; 191 { 192 uint8_t ret; 193 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBADDR, no); 194 delay(10); 195 ret = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBDATA); 196 delay(10); 197 return ret; 198 } 199 200 static __inline void 201 cmpci_mixerreg_write(sc, no, val) 202 struct cmpci_softc *sc; 203 uint8_t no, val; 204 { 205 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBADDR, no); 206 delay(10); 207 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBDATA, val); 208 delay(10); 209 } 210 211 /* register partial write */ 212 static __inline void 213 cmpci_reg_partial_write_4(sc, no, shift, mask, val) 214 struct cmpci_softc *sc; 215 int no, shift; 216 uint32_t mask, val; 217 { 218 bus_space_write_4(sc->sc_iot, sc->sc_ioh, no, 219 (val<<shift) | 220 (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) & ~(mask<<shift))); 221 delay(10); 222 } 223 224 /* register set/clear bit */ 225 static __inline void 226 cmpci_reg_set_4(sc, no, mask) 227 struct cmpci_softc *sc; 228 int no; 229 uint32_t mask; 230 { 231 bus_space_write_4(sc->sc_iot, sc->sc_ioh, no, 232 (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) | mask)); 233 delay(10); 234 } 235 236 static __inline void 237 cmpci_reg_clear_4(sc, no, mask) 238 struct cmpci_softc *sc; 239 int no; 240 uint32_t mask; 241 { 242 bus_space_write_4(sc->sc_iot, sc->sc_ioh, no, 243 (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) & ~mask)); 244 delay(10); 245 } 246 247 248 /* rate */ 249 struct { 250 int rate; 251 int divider; 252 } cmpci_rate_table[CMPCI_REG_NUMRATE] = { 253 #define _RATE(n) { n, CMPCI_REG_RATE_ ## n } 254 _RATE(5512), 255 _RATE(8000), 256 _RATE(11025), 257 _RATE(16000), 258 _RATE(22050), 259 _RATE(32000), 260 _RATE(44100), 261 _RATE(48000) 262 #undef _RATE 263 }; 264 265 int 266 cmpci_rate_to_index(rate) 267 int rate; 268 { 269 int i; 270 for (i=0; i<CMPCI_REG_NUMRATE-2; i++) 271 if (rate <= 272 (cmpci_rate_table[i].rate + cmpci_rate_table[i+1].rate) / 2) 273 return i; 274 return i; /* 48000 */ 275 } 276 277 static __inline int 278 cmpci_index_to_rate(index) 279 int index; 280 { 281 282 return cmpci_rate_table[index].rate; 283 } 284 285 static __inline int 286 cmpci_index_to_divider(index) 287 int index; 288 { 289 return cmpci_rate_table[index].divider; 290 } 291 292 293 /* 294 * interface to configure the device. 295 */ 296 int 297 cmpci_match(parent, match, aux) 298 struct device *parent; 299 void *match; 300 void *aux; 301 { 302 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 303 304 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_CMI && 305 (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMI_CMI8338A || 306 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMI_CMI8338B || 307 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMI_CMI8738)) 308 return 1; 309 310 return 0; 311 } 312 313 void 314 cmpci_attach(parent, self, aux) 315 struct device *parent, *self; 316 void *aux; 317 { 318 struct cmpci_softc *sc = (struct cmpci_softc *)self; 319 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 320 pci_intr_handle_t ih; 321 char const *intrstr; 322 int i, v; 323 324 /* map I/O space */ 325 if (pci_mapreg_map(pa, CMPCI_PCI_IOBASEREG, PCI_MAPREG_TYPE_IO, 0, 326 &sc->sc_iot, &sc->sc_ioh, NULL, NULL, 0)) { 327 printf("\n%s: failed to map I/O space\n", sc->sc_dev.dv_xname); 328 return; 329 } 330 331 /* interrupt */ 332 if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 333 pa->pa_intrline, &ih)) { 334 printf("\n%s: failed to map interrupt\n", sc->sc_dev.dv_xname); 335 return; 336 } 337 intrstr = pci_intr_string(pa->pa_pc, ih); 338 sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, cmpci_intr, 339 sc, sc->sc_dev.dv_xname); 340 341 if (sc->sc_ih == NULL) { 342 printf("\n%s: couldn't establish interrupt", 343 sc->sc_dev.dv_xname); 344 if (intrstr) 345 printf(" at %s", intrstr); 346 printf("\n"); 347 return; 348 } 349 printf(": %s\n", intrstr); 350 351 sc->sc_dmat = pa->pa_dmat; 352 353 audio_attach_mi(&cmpci_hw_if, sc, &sc->sc_dev); 354 355 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_RESET, 0); 356 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, 0); 357 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, 0); 358 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_OUTMIX, 359 CMPCI_SB16_SW_CD|CMPCI_SB16_SW_MIC| 360 CMPCI_SB16_SW_LINE); 361 for (i = 0; i < CMPCI_NDEVS; i++) { 362 switch(i) { 363 case CMPCI_MIC_VOL: 364 case CMPCI_LINE_IN_VOL: 365 v = 0; 366 break; 367 case CMPCI_BASS: 368 case CMPCI_TREBLE: 369 v = CMPCI_ADJUST_GAIN(sc, AUDIO_MAX_GAIN / 2); 370 break; 371 case CMPCI_CD_IN_MUTE: 372 case CMPCI_MIC_IN_MUTE: 373 case CMPCI_LINE_IN_MUTE: 374 case CMPCI_FM_IN_MUTE: 375 case CMPCI_CD_SWAP: 376 case CMPCI_MIC_SWAP: 377 case CMPCI_LINE_SWAP: 378 case CMPCI_FM_SWAP: 379 v = 0; 380 break; 381 case CMPCI_CD_OUT_MUTE: 382 case CMPCI_MIC_OUT_MUTE: 383 case CMPCI_LINE_OUT_MUTE: 384 v = 1; 385 break; 386 default: 387 v = CMPCI_ADJUST_GAIN(sc, AUDIO_MAX_GAIN / 2); 388 } 389 sc->gain[i][CMPCI_LEFT] = sc->gain[i][CMPCI_RIGHT] = v; 390 cmpci_set_mixer_gain(sc, i); 391 } 392 } 393 394 int 395 cmpci_intr(handle) 396 void *handle; 397 { 398 struct cmpci_softc *sc = handle; 399 uint32_t intrstat; 400 int s; 401 402 intrstat = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 403 CMPCI_REG_INTR_STATUS); 404 delay(10); 405 406 if (!(intrstat & CMPCI_REG_ANY_INTR)) 407 return 0; 408 409 /* disable and reset intr */ 410 s = splaudio(); 411 if (intrstat & CMPCI_REG_CH0_INTR) 412 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, 413 CMPCI_REG_CH0_INTR_ENABLE); 414 if (intrstat&CMPCI_REG_CH1_INTR) 415 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, 416 CMPCI_REG_CH1_INTR_ENABLE); 417 splx(s); 418 419 if (intrstat & CMPCI_REG_CH0_INTR) { 420 if (sc->sc_play.intr) 421 (*sc->sc_play.intr)(sc->sc_play.intr_arg); 422 } 423 if (intrstat & CMPCI_REG_CH1_INTR) { 424 if (sc->sc_rec.intr) 425 (*sc->sc_rec.intr)(sc->sc_rec.intr_arg); 426 } 427 428 /* enable intr */ 429 s = splaudio(); 430 if ( intrstat & CMPCI_REG_CH0_INTR ) 431 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, 432 CMPCI_REG_CH0_INTR_ENABLE); 433 if (intrstat & CMPCI_REG_CH1_INTR) 434 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, 435 CMPCI_REG_CH1_INTR_ENABLE); 436 splx(s); 437 438 return 0; 439 } 440 441 /* open/close */ 442 int 443 cmpci_open(handle, flags) 444 void *handle; 445 int flags; 446 { 447 struct cmpci_softc *sc = handle; 448 (void)sc; 449 (void)flags; 450 451 return 0; 452 } 453 454 void 455 cmpci_close(handle) 456 void *handle; 457 { 458 (void)handle; 459 } 460 461 int 462 cmpci_query_encoding(handle, fp) 463 void *handle; 464 struct audio_encoding *fp; 465 { 466 struct cmpci_softc *sc = handle; 467 (void)sc; 468 469 switch (fp->index) { 470 case 0: 471 strcpy(fp->name, AudioEulinear); 472 fp->encoding = AUDIO_ENCODING_ULINEAR; 473 fp->precision = 8; 474 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 475 break; 476 case 1: 477 strcpy(fp->name, AudioEmulaw); 478 fp->encoding = AUDIO_ENCODING_ULAW; 479 fp->precision = 8; 480 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 481 break; 482 case 2: 483 strcpy(fp->name, AudioEalaw); 484 fp->encoding = AUDIO_ENCODING_ALAW; 485 fp->precision = 8; 486 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 487 break; 488 case 3: 489 strcpy(fp->name, AudioEslinear); 490 fp->encoding = AUDIO_ENCODING_SLINEAR; 491 fp->precision = 8; 492 fp->flags = 0; 493 break; 494 case 4: 495 strcpy(fp->name, AudioEslinear_le); 496 fp->encoding = AUDIO_ENCODING_SLINEAR_LE; 497 fp->precision = 16; 498 fp->flags = 0; 499 break; 500 case 5: 501 strcpy(fp->name, AudioEulinear_le); 502 fp->encoding = AUDIO_ENCODING_ULINEAR_LE; 503 fp->precision = 16; 504 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 505 break; 506 case 6: 507 strcpy(fp->name, AudioEslinear_be); 508 fp->encoding = AUDIO_ENCODING_SLINEAR_BE; 509 fp->precision = 16; 510 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 511 break; 512 case 7: 513 strcpy(fp->name, AudioEulinear_be); 514 fp->encoding = AUDIO_ENCODING_ULINEAR_BE; 515 fp->precision = 16; 516 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 517 break; 518 default: 519 return EINVAL; 520 } 521 return 0; 522 } 523 524 525 int 526 cmpci_set_params(handle, setmode, usemode, play, rec) 527 void *handle; 528 int setmode, usemode; 529 struct audio_params *play, *rec; 530 { 531 int i; 532 struct cmpci_softc *sc = handle; 533 534 for (i=0; i<2; i++) { 535 int md_format; 536 int md_divide; 537 int md_index; 538 int mode; 539 struct audio_params *p; 540 541 switch (i) { 542 case 0: 543 mode = AUMODE_PLAY; 544 p = play; 545 break; 546 case 1: 547 mode = AUMODE_RECORD; 548 p = rec; 549 break; 550 } 551 552 if (!(setmode & mode)) 553 continue; 554 555 /* format */ 556 p->sw_code = NULL; 557 switch (p->channels) { 558 case 1: 559 md_format = CMPCI_REG_FORMAT_MONO; 560 break; 561 case 2: 562 md_format = CMPCI_REG_FORMAT_STEREO; 563 break; 564 default: 565 return (EINVAL); 566 } 567 switch (p->encoding) { 568 case AUDIO_ENCODING_ULAW: 569 if (p->precision != 8) 570 return (EINVAL); 571 if (mode & AUMODE_PLAY) { 572 p->factor = 2; 573 p->sw_code = mulaw_to_slinear16; 574 md_format |= CMPCI_REG_FORMAT_16BIT; 575 } else 576 p->sw_code = ulinear8_to_mulaw; 577 md_format |= CMPCI_REG_FORMAT_8BIT; 578 break; 579 case AUDIO_ENCODING_ALAW: 580 if (p->precision != 8) 581 return (EINVAL); 582 if (mode & AUMODE_PLAY) { 583 p->factor = 2; 584 p->sw_code = alaw_to_slinear16; 585 md_format |= CMPCI_REG_FORMAT_16BIT; 586 } else 587 p->sw_code = ulinear8_to_alaw; 588 md_format |= CMPCI_REG_FORMAT_8BIT; 589 break; 590 case AUDIO_ENCODING_SLINEAR_LE: 591 switch (p->precision) { 592 case 8: 593 p->sw_code = change_sign8; 594 md_format |= CMPCI_REG_FORMAT_8BIT; 595 break; 596 case 16: 597 md_format |= CMPCI_REG_FORMAT_16BIT; 598 break; 599 default: 600 return (EINVAL); 601 } 602 break; 603 case AUDIO_ENCODING_SLINEAR_BE: 604 switch (p->precision) { 605 case 8: 606 md_format |= CMPCI_REG_FORMAT_8BIT; 607 p->sw_code = change_sign8; 608 break; 609 case 16: 610 md_format |= CMPCI_REG_FORMAT_16BIT; 611 p->sw_code = swap_bytes; 612 break; 613 default: 614 return (EINVAL); 615 } 616 break; 617 case AUDIO_ENCODING_ULINEAR_LE: 618 switch ( p->precision ) { 619 case 8: 620 md_format |= CMPCI_REG_FORMAT_8BIT; 621 break; 622 case 16: 623 md_format |= CMPCI_REG_FORMAT_16BIT; 624 p->sw_code = change_sign16; 625 break; 626 default: 627 return (EINVAL); 628 } 629 break; 630 case AUDIO_ENCODING_ULINEAR_BE: 631 switch (p->precision) { 632 case 8: 633 md_format |= CMPCI_REG_FORMAT_8BIT; 634 break; 635 case 16: 636 md_format |= CMPCI_REG_FORMAT_16BIT; 637 if ( mode&AUMODE_PLAY ) 638 p->sw_code = swap_bytes_change_sign16; 639 else 640 p->sw_code = change_sign16_swap_bytes; 641 break; 642 default: 643 return (EINVAL); 644 } 645 break; 646 default: 647 return (EINVAL); 648 } 649 if (mode & AUMODE_PLAY) 650 cmpci_reg_partial_write_4(sc, 651 CMPCI_REG_CHANNEL_FORMAT, 652 CMPCI_REG_CH0_FORMAT_SHIFT, 653 CMPCI_REG_CH0_FORMAT_MASK, 654 md_format); 655 else 656 cmpci_reg_partial_write_4(sc, 657 CMPCI_REG_CHANNEL_FORMAT, 658 CMPCI_REG_CH1_FORMAT_SHIFT, 659 CMPCI_REG_CH1_FORMAT_MASK, 660 md_format); 661 /* sample rate */ 662 md_index = cmpci_rate_to_index(p->sample_rate); 663 md_divide = cmpci_index_to_divider(md_index); 664 p->sample_rate = cmpci_index_to_rate(md_index); 665 #if 0 666 DPRINTF(("%s: sample:%d, divider=%d\n", 667 sc->sc_dev.dv_xname, (int)p->sample_rate, md_divide)); 668 #endif 669 if (mode & AUMODE_PLAY) { 670 cmpci_reg_partial_write_4(sc, 671 CMPCI_REG_FUNC_1, 672 CMPCI_REG_DAC_FS_SHIFT, 673 CMPCI_REG_DAC_FS_MASK, 674 md_divide); 675 #ifdef CMPCI_SPDIF_SUPPORT 676 switch (md_divide) { 677 case CMPCI_REG_RATE_44100: 678 cmpci_reg_clear_4(sc, CMPCI_REG_MISC, 679 CMPCI_REG_SPDIF_48K); 680 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1, 681 CMPCI_REG_SPDIF_LOOP); 682 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1, 683 CMPCI_REG_SPDIF0_ENABLE); 684 break; 685 case CMPCI_REG_RATE_48000: 686 cmpci_reg_set_4(sc, CMPCI_REG_MISC, 687 CMPCI_REG_SPDIF_48K); 688 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1, 689 CMPCI_REG_SPDIF_LOOP); 690 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1, 691 CMPCI_REG_SPDIF0_ENABLE); 692 break; 693 default: 694 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1, 695 CMPCI_REG_SPDIF0_ENABLE); 696 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1, 697 CMPCI_REG_SPDIF_LOOP); 698 } 699 #endif 700 } else { 701 cmpci_reg_partial_write_4(sc, 702 CMPCI_REG_FUNC_1, 703 CMPCI_REG_ADC_FS_SHIFT, 704 CMPCI_REG_ADC_FS_MASK, 705 md_divide); 706 #ifdef CMPCI_SPDIF_SUPPORT 707 if ( sc->in_mask&CMPCI_SPDIF_IN) { 708 switch (md_divide) { 709 case CMPCI_REG_RATE_44100: 710 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1, 711 CMPCI_REG_SPDIF1_ENABLE); 712 break; 713 default: 714 return EINVAL; 715 } 716 } else 717 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1, 718 CMPCI_REG_SPDIF1_ENABLE); 719 #endif 720 } 721 } 722 return 0; 723 } 724 725 /* ARGSUSED */ 726 int 727 cmpci_round_blocksize(handle, block) 728 void *handle; 729 int block; 730 { 731 return (block & -4); 732 } 733 734 int 735 cmpci_halt_output(handle) 736 void *handle; 737 { 738 struct cmpci_softc *sc = handle; 739 int s; 740 741 s = splaudio(); 742 sc->sc_play.intr = NULL; 743 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE); 744 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE); 745 /* wait for reset DMA */ 746 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET); 747 delay(10); 748 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET); 749 splx(s); 750 751 return 0; 752 } 753 754 int 755 cmpci_halt_input(handle) 756 void *handle; 757 { 758 struct cmpci_softc *sc = handle; 759 int s; 760 761 s = splaudio(); 762 sc->sc_rec.intr = NULL; 763 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE); 764 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE); 765 /* wait for reset DMA */ 766 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET); 767 delay(10); 768 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET); 769 splx(s); 770 771 return 0; 772 } 773 774 int 775 cmpci_getdev(handle, retp) 776 void *handle; 777 struct audio_device *retp; 778 { 779 *retp = cmpci_device; 780 return 0; 781 } 782 783 784 /* mixer device information */ 785 int 786 cmpci_query_devinfo(handle, dip) 787 void *handle; 788 mixer_devinfo_t *dip; 789 { 790 struct cmpci_softc *sc = handle; 791 (void)sc; 792 793 switch (dip->index) { 794 case CMPCI_MASTER_VOL: 795 dip->type = AUDIO_MIXER_VALUE; 796 dip->mixer_class = CMPCI_OUTPUT_CLASS; 797 dip->prev = dip->next = AUDIO_MIXER_LAST; 798 strcpy(dip->label.name, AudioNmaster); 799 dip->un.v.num_channels = 2; 800 strcpy(dip->un.v.units.name, AudioNvolume); 801 return 0; 802 case CMPCI_FM_VOL: 803 dip->type = AUDIO_MIXER_VALUE; 804 dip->mixer_class = CMPCI_INPUT_CLASS; 805 dip->prev = AUDIO_MIXER_LAST; 806 dip->next = CMPCI_FM_IN_MUTE; 807 strcpy(dip->label.name, AudioNfmsynth); 808 dip->un.v.num_channels = 2; 809 strcpy(dip->un.v.units.name, AudioNvolume); 810 return 0; 811 case CMPCI_CD_VOL: 812 dip->type = AUDIO_MIXER_VALUE; 813 dip->mixer_class = CMPCI_INPUT_CLASS; 814 dip->prev = AUDIO_MIXER_LAST; 815 dip->next = CMPCI_CD_IN_MUTE; 816 strcpy(dip->label.name, AudioNcd); 817 dip->un.v.num_channels = 2; 818 strcpy(dip->un.v.units.name, AudioNvolume); 819 return 0; 820 case CMPCI_VOICE_VOL: 821 dip->type = AUDIO_MIXER_VALUE; 822 dip->mixer_class = CMPCI_OUTPUT_CLASS; 823 dip->prev = AUDIO_MIXER_LAST; 824 dip->next = AUDIO_MIXER_LAST; 825 strcpy(dip->label.name, AudioNdac); 826 dip->un.v.num_channels = 2; 827 strcpy(dip->un.v.units.name, AudioNvolume); 828 return 0; 829 case CMPCI_OUTPUT_CLASS: 830 dip->type = AUDIO_MIXER_CLASS; 831 dip->mixer_class = CMPCI_INPUT_CLASS; 832 dip->next = dip->prev = AUDIO_MIXER_LAST; 833 strcpy(dip->label.name, AudioCoutputs); 834 return 0; 835 case CMPCI_MIC_VOL: 836 dip->type = AUDIO_MIXER_VALUE; 837 dip->mixer_class = CMPCI_INPUT_CLASS; 838 dip->prev = AUDIO_MIXER_LAST; 839 dip->next = CMPCI_MIC_IN_MUTE; 840 strcpy(dip->label.name, AudioNmicrophone); 841 dip->un.v.num_channels = 1; 842 strcpy(dip->un.v.units.name, AudioNvolume); 843 return 0; 844 case CMPCI_LINE_IN_VOL: 845 dip->type = AUDIO_MIXER_VALUE; 846 dip->mixer_class = CMPCI_INPUT_CLASS; 847 dip->prev = AUDIO_MIXER_LAST; 848 dip->next = CMPCI_LINE_IN_MUTE; 849 strcpy(dip->label.name, AudioNline); 850 dip->un.v.num_channels = 2; 851 strcpy(dip->un.v.units.name, AudioNvolume); 852 return 0; 853 case CMPCI_RECORD_SOURCE: 854 dip->mixer_class = CMPCI_RECORD_CLASS; 855 dip->prev = dip->next = AUDIO_MIXER_LAST; 856 strcpy(dip->label.name, AudioNsource); 857 dip->type = AUDIO_MIXER_SET; 858 #ifdef CMPCI_SPDIF_SUPPORT 859 dip->un.s.num_mem = 5; 860 #else 861 dip->un.s.num_mem = 4; 862 #endif 863 strcpy(dip->un.s.member[0].label.name, AudioNmicrophone); 864 dip->un.s.member[0].mask = 1 << CMPCI_MIC_VOL; 865 strcpy(dip->un.s.member[1].label.name, AudioNcd); 866 dip->un.s.member[1].mask = 1 << CMPCI_CD_VOL; 867 strcpy(dip->un.s.member[2].label.name, AudioNline); 868 dip->un.s.member[2].mask = 1 << CMPCI_LINE_IN_VOL; 869 strcpy(dip->un.s.member[3].label.name, AudioNfmsynth); 870 dip->un.s.member[3].mask = 1 << CMPCI_FM_VOL; 871 #ifdef CMPCI_SPDIF_SUPPORT 872 strcpy(dip->un.s.member[4].label.name, CmpciNspdif); 873 dip->un.s.member[4].mask = 1 << CMPCI_SPDIF_IN; 874 #endif 875 return 0; 876 case CMPCI_BASS: 877 dip->prev = dip->next = AUDIO_MIXER_LAST; 878 strcpy(dip->label.name, AudioNbass); 879 dip->type = AUDIO_MIXER_VALUE; 880 dip->mixer_class = CMPCI_EQUALIZATION_CLASS; 881 dip->un.v.num_channels = 2; 882 strcpy(dip->un.v.units.name, AudioNbass); 883 return 0; 884 case CMPCI_TREBLE: 885 dip->prev = dip->next = AUDIO_MIXER_LAST; 886 strcpy(dip->label.name, AudioNtreble); 887 dip->type = AUDIO_MIXER_VALUE; 888 dip->mixer_class = CMPCI_EQUALIZATION_CLASS; 889 dip->un.v.num_channels = 2; 890 strcpy(dip->un.v.units.name, AudioNtreble); 891 return 0; 892 case CMPCI_RECORD_CLASS: 893 dip->type = AUDIO_MIXER_CLASS; 894 dip->mixer_class = CMPCI_RECORD_CLASS; 895 dip->next = dip->prev = AUDIO_MIXER_LAST; 896 strcpy(dip->label.name, AudioCrecord); 897 return 0; 898 case CMPCI_INPUT_CLASS: 899 dip->type = AUDIO_MIXER_CLASS; 900 dip->mixer_class = CMPCI_INPUT_CLASS; 901 dip->next = dip->prev = AUDIO_MIXER_LAST; 902 strcpy(dip->label.name, AudioCinputs); 903 return 0; 904 case CMPCI_PCSPEAKER: 905 dip->type = AUDIO_MIXER_VALUE; 906 dip->mixer_class = CMPCI_INPUT_CLASS; 907 dip->prev = dip->next = AUDIO_MIXER_LAST; 908 strcpy(dip->label.name, "pc_speaker"); 909 dip->un.v.num_channels = 1; 910 strcpy(dip->un.v.units.name, AudioNvolume); 911 return 0; 912 case CMPCI_INPUT_GAIN: 913 dip->type = AUDIO_MIXER_VALUE; 914 dip->mixer_class = CMPCI_INPUT_CLASS; 915 dip->prev = dip->next = AUDIO_MIXER_LAST; 916 strcpy(dip->label.name, AudioNinput); 917 dip->un.v.num_channels = 2; 918 strcpy(dip->un.v.units.name, AudioNvolume); 919 return 0; 920 case CMPCI_OUTPUT_GAIN: 921 dip->type = AUDIO_MIXER_VALUE; 922 dip->mixer_class = CMPCI_OUTPUT_CLASS; 923 dip->prev = dip->next = AUDIO_MIXER_LAST; 924 strcpy(dip->label.name, AudioNoutput); 925 dip->un.v.num_channels = 2; 926 strcpy(dip->un.v.units.name, AudioNvolume); 927 return 0; 928 case CMPCI_AGC: 929 dip->type = AUDIO_MIXER_ENUM; 930 dip->mixer_class = CMPCI_INPUT_CLASS; 931 dip->prev = dip->next = AUDIO_MIXER_LAST; 932 strcpy(dip->label.name, "agc"); 933 dip->un.e.num_mem = 2; 934 strcpy(dip->un.e.member[0].label.name, AudioNoff); 935 dip->un.e.member[0].ord = 0; 936 strcpy(dip->un.e.member[1].label.name, AudioNon); 937 dip->un.e.member[1].ord = 1; 938 return 0; 939 case CMPCI_EQUALIZATION_CLASS: 940 dip->type = AUDIO_MIXER_CLASS; 941 dip->mixer_class = CMPCI_EQUALIZATION_CLASS; 942 dip->next = dip->prev = AUDIO_MIXER_LAST; 943 strcpy(dip->label.name, AudioCequalization); 944 return 0; 945 case CMPCI_CD_IN_MUTE: 946 dip->prev = CMPCI_CD_VOL; 947 dip->next = CMPCI_CD_SWAP; 948 dip->mixer_class = CMPCI_INPUT_CLASS; 949 goto mute; 950 case CMPCI_MIC_IN_MUTE: 951 dip->prev = CMPCI_MIC_VOL; 952 dip->next = CMPCI_MIC_SWAP; 953 dip->mixer_class = CMPCI_INPUT_CLASS; 954 goto mute; 955 case CMPCI_LINE_IN_MUTE: 956 dip->prev = CMPCI_LINE_IN_VOL; 957 dip->next = CMPCI_LINE_SWAP; 958 dip->mixer_class = CMPCI_INPUT_CLASS; 959 goto mute; 960 case CMPCI_FM_IN_MUTE: 961 dip->prev = CMPCI_FM_VOL; 962 dip->next = CMPCI_FM_SWAP; 963 dip->mixer_class = CMPCI_INPUT_CLASS; 964 goto mute; 965 case CMPCI_CD_SWAP: 966 dip->prev = CMPCI_CD_IN_MUTE; 967 dip->next = CMPCI_CD_OUT_MUTE; 968 goto swap; 969 case CMPCI_MIC_SWAP: 970 dip->prev = CMPCI_MIC_IN_MUTE; 971 dip->next = CMPCI_MIC_OUT_MUTE; 972 goto swap; 973 case CMPCI_LINE_SWAP: 974 dip->prev = CMPCI_LINE_IN_MUTE; 975 dip->next = CMPCI_LINE_OUT_MUTE; 976 goto swap; 977 case CMPCI_FM_SWAP: 978 dip->prev = CMPCI_FM_IN_MUTE; 979 dip->next = AUDIO_MIXER_LAST; 980 swap: 981 dip->mixer_class = CMPCI_INPUT_CLASS; 982 strcpy(dip->label.name, AudioNswap); 983 goto mute1; 984 case CMPCI_CD_OUT_MUTE: 985 dip->prev = CMPCI_CD_SWAP; 986 dip->next = AUDIO_MIXER_LAST; 987 dip->mixer_class = CMPCI_OUTPUT_CLASS; 988 goto mute; 989 case CMPCI_MIC_OUT_MUTE: 990 dip->prev = CMPCI_MIC_SWAP; 991 dip->next = AUDIO_MIXER_LAST; 992 dip->mixer_class = CMPCI_OUTPUT_CLASS; 993 goto mute; 994 case CMPCI_LINE_OUT_MUTE: 995 dip->prev = CMPCI_LINE_SWAP; 996 dip->next = AUDIO_MIXER_LAST; 997 dip->mixer_class = CMPCI_OUTPUT_CLASS; 998 mute: 999 strcpy(dip->label.name, AudioNmute); 1000 mute1: 1001 dip->type = AUDIO_MIXER_ENUM; 1002 dip->un.e.num_mem = 2; 1003 strcpy(dip->un.e.member[0].label.name, AudioNoff); 1004 dip->un.e.member[0].ord = 0; 1005 strcpy(dip->un.e.member[1].label.name, AudioNon); 1006 dip->un.e.member[1].ord = 1; 1007 return 0; 1008 } 1009 1010 return ENXIO; 1011 } 1012 1013 int 1014 cmpci_alloc_dmamem(sc, size, type, flags, r_addr) 1015 struct cmpci_softc *sc; 1016 size_t size; 1017 int type, flags; 1018 caddr_t *r_addr; 1019 { 1020 int ret = 0; 1021 struct cmpci_dmanode *n; 1022 int w; 1023 1024 if ( NULL == (n=malloc(sizeof(struct cmpci_dmanode), type, flags)) ) { 1025 ret = ENOMEM; 1026 goto quit; 1027 } 1028 1029 w = (flags & M_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK; 1030 #define CMPCI_DMABUF_ALIGN 0x4 1031 #define CMPCI_DMABUF_BOUNDARY 0x0 1032 n->cd_tag = sc->sc_dmat; 1033 n->cd_size = size; 1034 if ( (ret=bus_dmamem_alloc(n->cd_tag, n->cd_size, 1035 CMPCI_DMABUF_ALIGN, CMPCI_DMABUF_BOUNDARY, 1036 n->cd_segs, 1037 sizeof(n->cd_segs)/sizeof(n->cd_segs[0]), 1038 &n->cd_nsegs, w)) ) 1039 goto mfree; 1040 if ( (ret=bus_dmamem_map(n->cd_tag, n->cd_segs, n->cd_nsegs, n->cd_size, 1041 &n->cd_addr, w | BUS_DMA_COHERENT)) ) 1042 goto dmafree; 1043 if ( (ret=bus_dmamap_create(n->cd_tag, n->cd_size, 1, n->cd_size, 0, 1044 w, &n->cd_map)) ) 1045 goto unmap; 1046 if ( (ret=bus_dmamap_load(n->cd_tag, n->cd_map, n->cd_addr, n->cd_size, 1047 NULL, w)) ) 1048 goto destroy; 1049 1050 n->cd_next = sc->sc_dmap; 1051 sc->sc_dmap = n; 1052 *r_addr = KVADDR(n); 1053 return 0; 1054 1055 destroy: 1056 bus_dmamap_destroy(n->cd_tag, n->cd_map); 1057 unmap: 1058 bus_dmamem_unmap(n->cd_tag, n->cd_addr, n->cd_size); 1059 dmafree: 1060 bus_dmamem_free(n->cd_tag, 1061 n->cd_segs, sizeof(n->cd_segs)/sizeof(n->cd_segs[0])); 1062 mfree: 1063 free(n, type); 1064 quit: 1065 return ret; 1066 } 1067 1068 int 1069 cmpci_free_dmamem(sc, addr, type) 1070 struct cmpci_softc *sc; 1071 caddr_t addr; 1072 int type; 1073 { 1074 struct cmpci_dmanode **nnp; 1075 1076 for (nnp = &sc->sc_dmap; *nnp; nnp = &(*nnp)->cd_next) { 1077 if ((*nnp)->cd_addr == addr) { 1078 struct cmpci_dmanode *n = *nnp; 1079 1080 bus_dmamap_unload(n->cd_tag, n->cd_map); 1081 bus_dmamap_destroy(n->cd_tag, n->cd_map); 1082 bus_dmamem_unmap(n->cd_tag, n->cd_addr, n->cd_size); 1083 bus_dmamem_free(n->cd_tag, n->cd_segs, 1084 sizeof(n->cd_segs)/sizeof(n->cd_segs[0])); 1085 free(n, type); 1086 return 0; 1087 } 1088 } 1089 return -1; 1090 } 1091 1092 struct cmpci_dmanode * 1093 cmpci_find_dmamem(sc, addr) 1094 struct cmpci_softc *sc; 1095 caddr_t addr; 1096 { 1097 struct cmpci_dmanode *p; 1098 for (p = sc->sc_dmap; p; p = p->cd_next) { 1099 if (KVADDR(p) == (void *)addr) 1100 break; 1101 } 1102 return p; 1103 } 1104 1105 #if 0 1106 void 1107 cmpci_print_dmamem __P((struct cmpci_dmanode *p)); 1108 void 1109 cmpci_print_dmamem(p) 1110 struct cmpci_dmanode *p; 1111 { 1112 DPRINTF(("DMA at virt:%p, dmaseg:%p, mapseg:%p, size:%p\n", 1113 (void *)p->cd_addr, (void *)p->cd_segs[0].ds_addr, 1114 (void *)DMAADDR(p), (void *)p->cd_size)); 1115 } 1116 #endif /* DEBUG */ 1117 1118 void * 1119 cmpci_malloc(handle, size, type, flags) 1120 void *handle; 1121 u_long size; 1122 int type, flags; 1123 { 1124 struct cmpci_softc *sc = handle; 1125 caddr_t addr; 1126 1127 if ( cmpci_alloc_dmamem(sc, size, type, flags, &addr) ) 1128 return NULL; 1129 return addr; 1130 } 1131 1132 void 1133 cmpci_free(handle, addr, type) 1134 void *handle; 1135 void *addr; 1136 int type; 1137 { 1138 struct cmpci_softc *sc = handle; 1139 1140 cmpci_free_dmamem(sc, addr, type); 1141 } 1142 1143 #define MAXVAL 256 1144 int 1145 cmpci_adjust(val, mask) 1146 int val, mask; 1147 { 1148 val += (MAXVAL - mask) >> 1; 1149 if (val >= MAXVAL) 1150 val = MAXVAL-1; 1151 return val & mask; 1152 } 1153 1154 void 1155 cmpci_set_mixer_gain(sc, port) 1156 struct cmpci_softc *sc; 1157 int port; 1158 { 1159 int src; 1160 1161 switch (port) { 1162 case CMPCI_MIC_VOL: 1163 src = CMPCI_SB16_MIXER_MIC; 1164 break; 1165 case CMPCI_MASTER_VOL: 1166 src = CMPCI_SB16_MIXER_MASTER_L; 1167 break; 1168 case CMPCI_LINE_IN_VOL: 1169 src = CMPCI_SB16_MIXER_LINE_L; 1170 break; 1171 case CMPCI_VOICE_VOL: 1172 src = CMPCI_SB16_MIXER_VOICE_L; 1173 break; 1174 case CMPCI_FM_VOL: 1175 src = CMPCI_SB16_MIXER_FM_L; 1176 break; 1177 case CMPCI_CD_VOL: 1178 src = CMPCI_SB16_MIXER_CDDA_L; 1179 break; 1180 case CMPCI_INPUT_GAIN: 1181 src = CMPCI_SB16_MIXER_INGAIN_L; 1182 break; 1183 case CMPCI_OUTPUT_GAIN: 1184 src = CMPCI_SB16_MIXER_OUTGAIN_L; 1185 break; 1186 case CMPCI_TREBLE: 1187 src = CMPCI_SB16_MIXER_TREBLE_L; 1188 break; 1189 case CMPCI_BASS: 1190 src = CMPCI_SB16_MIXER_BASS_L; 1191 break; 1192 case CMPCI_PCSPEAKER: 1193 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_SPEAKER, 1194 sc->gain[port][CMPCI_LEFT]); 1195 return; 1196 default: 1197 return; 1198 } 1199 cmpci_mixerreg_write(sc, src, sc->gain[port][CMPCI_LEFT]); 1200 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_L_TO_R(src), 1201 sc->gain[port][CMPCI_RIGHT]); 1202 } 1203 1204 int 1205 cmpci_set_in_ports(sc, mask) 1206 struct cmpci_softc *sc; 1207 int mask; 1208 { 1209 int bitsl, bitsr; 1210 1211 if (mask & ~((1<<CMPCI_FM_VOL) | (1<<CMPCI_LINE_IN_VOL) | 1212 (1<<CMPCI_CD_VOL) | (1<<CMPCI_MIC_VOL) 1213 #ifdef CMPCI_SPDIF_SUPPORT 1214 | (1<<CMPCI_SPDIF_IN) 1215 #endif 1216 )) 1217 return EINVAL; 1218 bitsr = 0; 1219 if (mask & (1<<CMPCI_FM_VOL)) 1220 bitsr |= CMPCI_SB16_MIXER_FM_SRC_R; 1221 if (mask & (1<<CMPCI_LINE_IN_VOL)) 1222 bitsr |= CMPCI_SB16_MIXER_LINE_SRC_R; 1223 if (mask & (1<<CMPCI_CD_VOL)) 1224 bitsr |= CMPCI_SB16_MIXER_CD_SRC_R; 1225 bitsl = CMPCI_SB16_MIXER_SRC_R_TO_L(bitsr); 1226 if (mask & (1<<CMPCI_MIC_VOL)) { 1227 bitsl |= CMPCI_SB16_MIXER_MIC_SRC; 1228 bitsr |= CMPCI_SB16_MIXER_MIC_SRC; 1229 } 1230 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, bitsl); 1231 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, bitsr); 1232 1233 sc->in_mask = mask; 1234 1235 return 0; 1236 } 1237 1238 int 1239 cmpci_set_port(handle, cp) 1240 void *handle; 1241 mixer_ctrl_t *cp; 1242 { 1243 struct cmpci_softc *sc = handle; 1244 int lgain, rgain; 1245 int mask, bits; 1246 int lmask, rmask, lbits, rbits; 1247 int mute, swap; 1248 1249 switch (cp->dev) { 1250 case CMPCI_TREBLE: 1251 case CMPCI_BASS: 1252 case CMPCI_PCSPEAKER: 1253 case CMPCI_INPUT_GAIN: 1254 case CMPCI_OUTPUT_GAIN: 1255 case CMPCI_MIC_VOL: 1256 case CMPCI_LINE_IN_VOL: 1257 case CMPCI_VOICE_VOL: 1258 case CMPCI_FM_VOL: 1259 case CMPCI_CD_VOL: 1260 case CMPCI_MASTER_VOL: 1261 if (cp->type != AUDIO_MIXER_VALUE) 1262 return EINVAL; 1263 switch (cp->dev) { 1264 case CMPCI_MIC_VOL: 1265 if (cp->un.value.num_channels != 1) 1266 return EINVAL; 1267 1268 lgain = rgain = CMPCI_ADJUST_MIC_GAIN(sc, 1269 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]); 1270 break; 1271 case CMPCI_PCSPEAKER: 1272 if (cp->un.value.num_channels != 1) 1273 return EINVAL; 1274 /* FALLTHROUGH */ 1275 case CMPCI_INPUT_GAIN: 1276 case CMPCI_OUTPUT_GAIN: 1277 lgain = rgain = CMPCI_ADJUST_2_GAIN(sc, 1278 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]); 1279 break; 1280 default: 1281 switch (cp->un.value.num_channels) { 1282 case 1: 1283 lgain = rgain = CMPCI_ADJUST_GAIN(sc, 1284 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]); 1285 break; 1286 case 2: 1287 lgain = CMPCI_ADJUST_GAIN(sc, 1288 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]); 1289 rgain = CMPCI_ADJUST_GAIN(sc, 1290 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]); 1291 break; 1292 default: 1293 return EINVAL; 1294 } 1295 break; 1296 } 1297 sc->gain[cp->dev][CMPCI_LEFT] = lgain; 1298 sc->gain[cp->dev][CMPCI_RIGHT] = rgain; 1299 1300 cmpci_set_mixer_gain(sc, cp->dev); 1301 break; 1302 1303 case CMPCI_RECORD_SOURCE: 1304 if (cp->type != AUDIO_MIXER_SET) 1305 return EINVAL; 1306 #ifdef CMPCI_SPDIF_SUPPORT 1307 if ( cp->un.mask&(1<<CMPCI_SPDIF_IN) ) 1308 cp->un.mask = 1<<CMPCI_SPDIF_IN; 1309 #endif 1310 return cmpci_set_in_ports(sc, cp->un.mask); 1311 1312 case CMPCI_AGC: 1313 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_AGC, cp->un.ord & 1); 1314 break; 1315 case CMPCI_CD_OUT_MUTE: 1316 mask = CMPCI_SB16_SW_CD; 1317 goto omute; 1318 case CMPCI_MIC_OUT_MUTE: 1319 mask = CMPCI_SB16_SW_MIC; 1320 goto omute; 1321 case CMPCI_LINE_OUT_MUTE: 1322 mask = CMPCI_SB16_SW_LINE; 1323 omute: 1324 if (cp->type != AUDIO_MIXER_ENUM) 1325 return EINVAL; 1326 bits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_OUTMIX); 1327 sc->gain[cp->dev][CMPCI_LR] = cp->un.ord != 0; 1328 if (cp->un.ord) 1329 bits = bits & ~mask; 1330 else 1331 bits = bits | mask; 1332 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_OUTMIX, bits); 1333 break; 1334 1335 case CMPCI_MIC_IN_MUTE: 1336 case CMPCI_MIC_SWAP: 1337 lmask = rmask = CMPCI_SB16_SW_MIC; 1338 goto imute; 1339 case CMPCI_CD_IN_MUTE: 1340 case CMPCI_CD_SWAP: 1341 lmask = CMPCI_SB16_SW_CD_L; 1342 rmask = CMPCI_SB16_SW_CD_R; 1343 goto imute; 1344 case CMPCI_LINE_IN_MUTE: 1345 case CMPCI_LINE_SWAP: 1346 lmask = CMPCI_SB16_SW_LINE_L; 1347 rmask = CMPCI_SB16_SW_LINE_R; 1348 goto imute; 1349 case CMPCI_FM_IN_MUTE: 1350 case CMPCI_FM_SWAP: 1351 lmask = CMPCI_SB16_SW_FM_L; 1352 rmask = CMPCI_SB16_SW_FM_R; 1353 imute: 1354 if (cp->type != AUDIO_MIXER_ENUM) 1355 return EINVAL; 1356 mask = lmask | rmask; 1357 lbits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_ADCMIX_L) 1358 & ~mask; 1359 rbits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_ADCMIX_R) 1360 & ~mask; 1361 sc->gain[cp->dev][CMPCI_LR] = cp->un.ord != 0; 1362 if (CMPCI_IS_IN_MUTE(cp->dev)) { 1363 mute = cp->dev; 1364 swap = mute - CMPCI_CD_IN_MUTE + CMPCI_CD_SWAP; 1365 } else { 1366 swap = cp->dev; 1367 mute = swap + CMPCI_CD_IN_MUTE - CMPCI_CD_SWAP; 1368 } 1369 if (sc->gain[swap][CMPCI_LR]) { 1370 mask = lmask; 1371 lmask = rmask; 1372 rmask = mask; 1373 } 1374 if (!sc->gain[mute][CMPCI_LR]) { 1375 lbits = lbits | lmask; 1376 rbits = rbits | rmask; 1377 } 1378 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, lbits); 1379 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, rbits); 1380 break; 1381 1382 default: 1383 return EINVAL; 1384 } 1385 1386 return 0; 1387 } 1388 1389 int 1390 cmpci_get_port(handle, cp) 1391 void *handle; 1392 mixer_ctrl_t *cp; 1393 { 1394 struct cmpci_softc *sc = handle; 1395 1396 switch (cp->dev) { 1397 case CMPCI_MIC_VOL: 1398 case CMPCI_LINE_IN_VOL: 1399 if (cp->un.value.num_channels != 1) 1400 return EINVAL; 1401 /* FALLTHROUGH */ 1402 case CMPCI_TREBLE: 1403 case CMPCI_BASS: 1404 case CMPCI_PCSPEAKER: 1405 case CMPCI_INPUT_GAIN: 1406 case CMPCI_OUTPUT_GAIN: 1407 case CMPCI_VOICE_VOL: 1408 case CMPCI_FM_VOL: 1409 case CMPCI_CD_VOL: 1410 case CMPCI_MASTER_VOL: 1411 switch (cp->un.value.num_channels) { 1412 case 1: 1413 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = 1414 sc->gain[cp->dev][CMPCI_LEFT]; 1415 break; 1416 case 2: 1417 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 1418 sc->gain[cp->dev][CMPCI_LEFT]; 1419 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 1420 sc->gain[cp->dev][CMPCI_RIGHT]; 1421 break; 1422 default: 1423 return EINVAL; 1424 } 1425 break; 1426 1427 case CMPCI_RECORD_SOURCE: 1428 cp->un.mask = sc->in_mask; 1429 break; 1430 1431 case CMPCI_AGC: 1432 cp->un.ord = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_AGC); 1433 break; 1434 1435 case CMPCI_CD_IN_MUTE: 1436 case CMPCI_MIC_IN_MUTE: 1437 case CMPCI_LINE_IN_MUTE: 1438 case CMPCI_FM_IN_MUTE: 1439 case CMPCI_CD_SWAP: 1440 case CMPCI_MIC_SWAP: 1441 case CMPCI_LINE_SWAP: 1442 case CMPCI_FM_SWAP: 1443 case CMPCI_CD_OUT_MUTE: 1444 case CMPCI_MIC_OUT_MUTE: 1445 case CMPCI_LINE_OUT_MUTE: 1446 cp->un.ord = sc->gain[cp->dev][CMPCI_LR]; 1447 break; 1448 1449 default: 1450 return EINVAL; 1451 } 1452 1453 return 0; 1454 } 1455 1456 /* ARGSUSED */ 1457 u_long 1458 cmpci_round_buffersize(handle, bufsize) 1459 void *handle; 1460 u_long bufsize; 1461 { 1462 if (bufsize > 0x10000) 1463 bufsize = 0x10000; 1464 1465 return bufsize; 1466 } 1467 1468 int 1469 cmpci_mappage(handle, addr, offset, prot) 1470 void *handle; 1471 void *addr; 1472 int offset; 1473 int prot; 1474 { 1475 struct cmpci_softc *sc = handle; 1476 struct cmpci_dmanode *p; 1477 1478 if ( offset < 0 || (p = cmpci_find_dmamem(sc, addr)) == NULL) 1479 return -1; 1480 1481 return bus_dmamem_mmap(p->cd_tag, p->cd_segs, 1482 sizeof(p->cd_segs)/sizeof(p->cd_segs[0]), 1483 offset, prot, BUS_DMA_WAITOK); 1484 } 1485 1486 /* ARGSUSED */ 1487 int 1488 cmpci_get_props(handle) 1489 void *handle; 1490 { 1491 return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX; 1492 } 1493 1494 1495 int 1496 cmpci_trigger_output(handle, start, end, blksize, intr, arg, param) 1497 void *handle; 1498 void *start, *end; 1499 int blksize; 1500 void (*intr) __P((void *)); 1501 void *arg; 1502 struct audio_params *param; 1503 { 1504 struct cmpci_softc *sc = handle; 1505 struct cmpci_dmanode *p; 1506 int bps; 1507 1508 sc->sc_play.intr = intr; 1509 sc->sc_play.intr_arg = arg; 1510 bps = param->channels * param->precision * param->factor / 8; 1511 if (!bps) 1512 return EINVAL; 1513 1514 /* set DMA frame */ 1515 if (!(p = cmpci_find_dmamem(sc, start))) 1516 return EINVAL; 1517 bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_BASE, 1518 DMAADDR(p)); 1519 delay(10); 1520 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_BYTES, 1521 ((caddr_t)end-(caddr_t)start+1)/bps-1); 1522 delay(10); 1523 1524 /* set interrupt count */ 1525 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_SAMPLES, 1526 (blksize+bps-1)/bps-1); 1527 delay(10); 1528 1529 /* start DMA */ 1530 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_DIR); /* PLAY */ 1531 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE); 1532 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE); 1533 1534 return 0; 1535 } 1536 1537 int 1538 cmpci_trigger_input(handle, start, end, blksize, intr, arg, param) 1539 void *handle; 1540 void *start, *end; 1541 int blksize; 1542 void (*intr) __P((void *)); 1543 void *arg; 1544 struct audio_params *param; 1545 { 1546 struct cmpci_softc *sc = handle; 1547 struct cmpci_dmanode *p; 1548 int bps; 1549 1550 sc->sc_rec.intr = intr; 1551 sc->sc_rec.intr_arg = arg; 1552 bps = param->channels*param->precision*param->factor/8; 1553 if (!bps) 1554 return EINVAL; 1555 1556 /* set DMA frame */ 1557 if (!(p = cmpci_find_dmamem(sc, start))) 1558 return EINVAL; 1559 bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_BASE, 1560 DMAADDR(p)); 1561 delay(10); 1562 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_BYTES, 1563 ((caddr_t)end-(caddr_t)start+1)/bps-1); 1564 delay(10); 1565 1566 /* set interrupt count */ 1567 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_SAMPLES, 1568 (blksize+bps-1)/bps-1); 1569 delay(10); 1570 1571 /* start DMA */ 1572 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_DIR); /* REC */ 1573 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE); 1574 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE); 1575 1576 return 0; 1577 } 1578