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