1 /* $NetBSD: cmpci.c,v 1.7 2001/02/12 18:47:12 tshiozak 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 <tshiozak@netbsd.org> . 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. 38 * 39 */ 40 41 #if defined(AUDIO_DEBUG) || defined(DEBUG) 42 #define DPRINTF(x) if (cmpcidebug) printf x 43 int cmpcidebug = 0; 44 #else 45 #define DPRINTF(x) 46 #endif 47 48 #include <sys/param.h> 49 #include <sys/systm.h> 50 #include <sys/kernel.h> 51 #include <sys/malloc.h> 52 #include <sys/device.h> 53 #include <sys/proc.h> 54 55 #include <dev/pci/pcidevs.h> 56 #include <dev/pci/pcivar.h> 57 58 #include <sys/audioio.h> 59 #include <dev/audio_if.h> 60 #include <dev/midi_if.h> 61 62 #include <dev/mulaw.h> 63 #include <dev/auconv.h> 64 #include <dev/pci/cmpcireg.h> 65 #include <dev/pci/cmpcivar.h> 66 67 #include <dev/ic/mpuvar.h> 68 #include <machine/bus.h> 69 #include <machine/intr.h> 70 71 /* 72 * Low-level HW interface 73 */ 74 static __inline uint8_t cmpci_mixerreg_read __P((struct cmpci_softc *, 75 uint8_t)); 76 static __inline void cmpci_mixerreg_write __P((struct cmpci_softc *, 77 uint8_t, uint8_t)); 78 static __inline void cmpci_reg_partial_write_4 __P((struct cmpci_softc *, 79 int, int, 80 uint32_t, uint32_t)); 81 static __inline void cmpci_reg_set_1 __P((struct cmpci_softc *, 82 int, uint8_t)); 83 static __inline void cmpci_reg_clear_1 __P((struct cmpci_softc *, 84 int, uint8_t)); 85 static __inline void cmpci_reg_set_4 __P((struct cmpci_softc *, 86 int, uint32_t)); 87 static __inline void cmpci_reg_clear_4 __P((struct cmpci_softc *, 88 int, uint32_t)); 89 static int cmpci_rate_to_index __P((int)); 90 static __inline int cmpci_index_to_rate __P((int)); 91 static __inline int cmpci_index_to_divider __P((int)); 92 93 static int cmpci_adjust __P((int, int)); 94 static void cmpci_set_mixer_gain __P((struct cmpci_softc *, int)); 95 static void cmpci_set_out_ports __P((struct cmpci_softc *)); 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_1(sc, no, mask) 228 struct cmpci_softc *sc; 229 int no; 230 uint8_t mask; 231 { 232 bus_space_write_1(sc->sc_iot, sc->sc_ioh, no, 233 (bus_space_read_1(sc->sc_iot, sc->sc_ioh, no) | mask)); 234 delay(10); 235 } 236 237 static __inline void 238 cmpci_reg_clear_1(sc, no, mask) 239 struct cmpci_softc *sc; 240 int no; 241 uint8_t mask; 242 { 243 bus_space_write_1(sc->sc_iot, sc->sc_ioh, no, 244 (bus_space_read_1(sc->sc_iot, sc->sc_ioh, no) & ~mask)); 245 delay(10); 246 } 247 248 249 static __inline void 250 cmpci_reg_set_4(sc, no, mask) 251 struct cmpci_softc *sc; 252 int no; 253 uint32_t mask; 254 { 255 bus_space_write_4(sc->sc_iot, sc->sc_ioh, no, 256 (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) | mask)); 257 delay(10); 258 } 259 260 static __inline void 261 cmpci_reg_clear_4(sc, no, mask) 262 struct cmpci_softc *sc; 263 int no; 264 uint32_t mask; 265 { 266 bus_space_write_4(sc->sc_iot, sc->sc_ioh, no, 267 (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) & ~mask)); 268 delay(10); 269 } 270 271 272 /* rate */ 273 static const struct { 274 int rate; 275 int divider; 276 } cmpci_rate_table[CMPCI_REG_NUMRATE] = { 277 #define _RATE(n) { n, CMPCI_REG_RATE_ ## n } 278 _RATE(5512), 279 _RATE(8000), 280 _RATE(11025), 281 _RATE(16000), 282 _RATE(22050), 283 _RATE(32000), 284 _RATE(44100), 285 _RATE(48000) 286 #undef _RATE 287 }; 288 289 static int 290 cmpci_rate_to_index(rate) 291 int rate; 292 { 293 int i; 294 295 for (i = 0; i < CMPCI_REG_NUMRATE - 2; i++) 296 if (rate <= 297 (cmpci_rate_table[i].rate+cmpci_rate_table[i+1].rate) / 2) 298 return i; 299 return i; /* 48000 */ 300 } 301 302 static __inline int 303 cmpci_index_to_rate(index) 304 int index; 305 { 306 return cmpci_rate_table[index].rate; 307 } 308 309 static __inline int 310 cmpci_index_to_divider(index) 311 int index; 312 { 313 return cmpci_rate_table[index].divider; 314 } 315 316 317 /* 318 * interface to configure the device. 319 */ 320 321 static int 322 cmpci_match(parent, match, aux) 323 struct device *parent; 324 struct cfdata *match; 325 void *aux; 326 { 327 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 328 329 if ( PCI_VENDOR(pa->pa_id) == PCI_VENDOR_CMEDIA && 330 (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMEDIA_CMI8338A || 331 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMEDIA_CMI8338B || 332 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMEDIA_CMI8738 || 333 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMEDIA_CMI8738B) ) 334 return 1; 335 336 return 0; 337 } 338 339 static void 340 cmpci_attach(parent, self, aux) 341 struct device *parent, *self; 342 void *aux; 343 { 344 struct cmpci_softc *sc = (struct cmpci_softc *)self; 345 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 346 pci_intr_handle_t ih; 347 char const *strintr; 348 char devinfo[256]; 349 int i, v; 350 351 sc->sc_id = pa->pa_id; 352 sc->sc_class = pa->pa_class; 353 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo); 354 printf(": %s (rev. 0x%02x)\n", devinfo, PCI_REVISION(sc->sc_class)); 355 switch (PCI_PRODUCT(sc->sc_id)) { 356 case PCI_PRODUCT_CMEDIA_CMI8338A: 357 /*FALLTHROUGH*/ 358 case PCI_PRODUCT_CMEDIA_CMI8338B: 359 sc->sc_capable = CMPCI_CAP_CMI8338; 360 break; 361 case PCI_PRODUCT_CMEDIA_CMI8738: 362 /*FALLTHROUGH*/ 363 case PCI_PRODUCT_CMEDIA_CMI8738B: 364 sc->sc_capable = CMPCI_CAP_CMI8738; 365 break; 366 } 367 368 /* map I/O space */ 369 if (pci_mapreg_map(pa, CMPCI_PCI_IOBASEREG, PCI_MAPREG_TYPE_IO, 0, 370 &sc->sc_iot, &sc->sc_ioh, NULL, NULL)) { 371 printf("%s: failed to map I/O space\n", sc->sc_dev.dv_xname); 372 return; 373 } 374 375 /* interrupt */ 376 if (pci_intr_map(pa, &ih)) { 377 printf("%s: failed to map interrupt\n", sc->sc_dev.dv_xname); 378 return; 379 } 380 strintr = pci_intr_string(pa->pa_pc, ih); 381 sc->sc_ih=pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, cmpci_intr, sc); 382 if (sc->sc_ih == NULL) { 383 printf("%s: failed to establish interrupt", 384 sc->sc_dev.dv_xname); 385 if (strintr != NULL) 386 printf(" at %s", strintr); 387 printf("\n"); 388 return; 389 } 390 printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, strintr); 391 392 sc->sc_dmat = pa->pa_dmat; 393 394 audio_attach_mi(&cmpci_hw_if, sc, &sc->sc_dev); 395 396 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_RESET, 0); 397 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, 0); 398 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, 0); 399 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_OUTMIX, 400 CMPCI_SB16_SW_CD|CMPCI_SB16_SW_MIC | CMPCI_SB16_SW_LINE); 401 for (i = 0; i < CMPCI_NDEVS; i++) { 402 switch(i) { 403 case CMPCI_MIC_VOL: 404 case CMPCI_LINE_IN_VOL: 405 v = 0; 406 break; 407 case CMPCI_BASS: 408 case CMPCI_TREBLE: 409 v = CMPCI_ADJUST_GAIN(sc, AUDIO_MAX_GAIN / 2); 410 break; 411 case CMPCI_CD_IN_MUTE: 412 case CMPCI_MIC_IN_MUTE: 413 case CMPCI_LINE_IN_MUTE: 414 case CMPCI_FM_IN_MUTE: 415 case CMPCI_CD_SWAP: 416 case CMPCI_MIC_SWAP: 417 case CMPCI_LINE_SWAP: 418 case CMPCI_FM_SWAP: 419 case CMPCI_SPDIF_LOOP: 420 case CMPCI_SPDIF_OUT_VOLTAGE: 421 case CMPCI_SPDIF_IN_PHASE: 422 case CMPCI_REAR: 423 case CMPCI_INDIVIDUAL: 424 case CMPCI_REVERSE: 425 case CMPCI_SURROUND: 426 v = 0; 427 break; 428 case CMPCI_CD_OUT_MUTE: 429 case CMPCI_MIC_OUT_MUTE: 430 case CMPCI_LINE_OUT_MUTE: 431 case CMPCI_SPDIF_IN_MUTE: 432 v = 1; 433 break; 434 default: 435 v = CMPCI_ADJUST_GAIN(sc, AUDIO_MAX_GAIN / 2); 436 } 437 sc->sc_gain[i][CMPCI_LEFT] = sc->sc_gain[i][CMPCI_RIGHT] = v; 438 cmpci_set_mixer_gain(sc, i); 439 } 440 } 441 442 443 static int 444 cmpci_intr(handle) 445 void *handle; 446 { 447 struct cmpci_softc *sc = handle; 448 uint32_t intrstat; 449 450 intrstat = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 451 CMPCI_REG_INTR_STATUS); 452 delay(10); 453 454 if (!(intrstat & CMPCI_REG_ANY_INTR)) 455 return 0; 456 457 /* disable and reset intr */ 458 if (intrstat & CMPCI_REG_CH0_INTR) 459 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, 460 CMPCI_REG_CH0_INTR_ENABLE); 461 if (intrstat & CMPCI_REG_CH1_INTR) 462 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, 463 CMPCI_REG_CH1_INTR_ENABLE); 464 465 if (intrstat & CMPCI_REG_CH0_INTR) { 466 if (sc->sc_play.intr != NULL) 467 (*sc->sc_play.intr)(sc->sc_play.intr_arg); 468 } 469 if (intrstat & CMPCI_REG_CH1_INTR) { 470 if (sc->sc_rec.intr != NULL) 471 (*sc->sc_rec.intr)(sc->sc_rec.intr_arg); 472 } 473 474 /* enable intr */ 475 if (intrstat & CMPCI_REG_CH0_INTR) 476 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, 477 CMPCI_REG_CH0_INTR_ENABLE); 478 if (intrstat & CMPCI_REG_CH1_INTR) 479 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, 480 CMPCI_REG_CH1_INTR_ENABLE); 481 482 return 0; 483 } 484 485 486 /* open/close */ 487 static int 488 cmpci_open(handle, flags) 489 void *handle; 490 int flags; 491 { 492 return 0; 493 } 494 495 static void 496 cmpci_close(handle) 497 void *handle; 498 { 499 } 500 501 static int 502 cmpci_query_encoding(handle, fp) 503 void *handle; 504 struct audio_encoding *fp; 505 { 506 switch (fp->index) { 507 case 0: 508 strcpy(fp->name, AudioEulinear); 509 fp->encoding = AUDIO_ENCODING_ULINEAR; 510 fp->precision = 8; 511 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 512 break; 513 case 1: 514 strcpy(fp->name, AudioEmulaw); 515 fp->encoding = AUDIO_ENCODING_ULAW; 516 fp->precision = 8; 517 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 518 break; 519 case 2: 520 strcpy(fp->name, AudioEalaw); 521 fp->encoding = AUDIO_ENCODING_ALAW; 522 fp->precision = 8; 523 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 524 break; 525 case 3: 526 strcpy(fp->name, AudioEslinear); 527 fp->encoding = AUDIO_ENCODING_SLINEAR; 528 fp->precision = 8; 529 fp->flags = 0; 530 break; 531 case 4: 532 strcpy(fp->name, AudioEslinear_le); 533 fp->encoding = AUDIO_ENCODING_SLINEAR_LE; 534 fp->precision = 16; 535 fp->flags = 0; 536 break; 537 case 5: 538 strcpy(fp->name, AudioEulinear_le); 539 fp->encoding = AUDIO_ENCODING_ULINEAR_LE; 540 fp->precision = 16; 541 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 542 break; 543 case 6: 544 strcpy(fp->name, AudioEslinear_be); 545 fp->encoding = AUDIO_ENCODING_SLINEAR_BE; 546 fp->precision = 16; 547 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 548 break; 549 case 7: 550 strcpy(fp->name, AudioEulinear_be); 551 fp->encoding = AUDIO_ENCODING_ULINEAR_BE; 552 fp->precision = 16; 553 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 554 break; 555 default: 556 return EINVAL; 557 } 558 return 0; 559 } 560 561 562 static int 563 cmpci_set_params(handle, setmode, usemode, play, rec) 564 void *handle; 565 int setmode, usemode; 566 struct audio_params *play, *rec; 567 { 568 int i; 569 struct cmpci_softc *sc = handle; 570 571 for (i = 0; i < 2; i++) { 572 int md_format; 573 int md_divide; 574 int md_index; 575 int mode; 576 struct audio_params *p; 577 578 switch (i) { 579 case 0: 580 mode = AUMODE_PLAY; 581 p = play; 582 break; 583 case 1: 584 mode = AUMODE_RECORD; 585 p = rec; 586 break; 587 } 588 589 if (!(setmode & mode)) 590 continue; 591 592 593 /* format */ 594 p->sw_code = NULL; 595 switch ( p->channels ) { 596 case 1: 597 md_format = CMPCI_REG_FORMAT_MONO; 598 break; 599 case 2: 600 md_format = CMPCI_REG_FORMAT_STEREO; 601 break; 602 default: 603 return (EINVAL); 604 } 605 switch (p->encoding) { 606 case AUDIO_ENCODING_ULAW: 607 if (p->precision != 8) 608 return (EINVAL); 609 if (mode & AUMODE_PLAY) { 610 p->factor = 2; 611 p->sw_code = mulaw_to_slinear16_le; 612 md_format |= CMPCI_REG_FORMAT_16BIT; 613 } else { 614 p->sw_code = ulinear8_to_mulaw; 615 md_format |= CMPCI_REG_FORMAT_8BIT; 616 } 617 break; 618 case AUDIO_ENCODING_ALAW: 619 if (p->precision != 8) 620 return (EINVAL); 621 if (mode & AUMODE_PLAY) { 622 p->factor = 2; 623 p->sw_code = alaw_to_slinear16_le; 624 md_format |= CMPCI_REG_FORMAT_16BIT; 625 } else { 626 p->sw_code = ulinear8_to_alaw; 627 md_format |= CMPCI_REG_FORMAT_8BIT; 628 } 629 break; 630 case AUDIO_ENCODING_SLINEAR_LE: 631 switch (p->precision) { 632 case 8: 633 p->sw_code = change_sign8; 634 md_format |= CMPCI_REG_FORMAT_8BIT; 635 break; 636 case 16: 637 md_format |= CMPCI_REG_FORMAT_16BIT; 638 break; 639 default: 640 return (EINVAL); 641 } 642 break; 643 case AUDIO_ENCODING_SLINEAR_BE: 644 switch (p->precision) { 645 case 8: 646 md_format |= CMPCI_REG_FORMAT_8BIT; 647 p->sw_code = change_sign8; 648 break; 649 case 16: 650 md_format |= CMPCI_REG_FORMAT_16BIT; 651 p->sw_code = swap_bytes; 652 break; 653 default: 654 return (EINVAL); 655 } 656 break; 657 case AUDIO_ENCODING_ULINEAR_LE: 658 switch (p->precision) { 659 case 8: 660 md_format |= CMPCI_REG_FORMAT_8BIT; 661 break; 662 case 16: 663 md_format |= CMPCI_REG_FORMAT_16BIT; 664 p->sw_code = change_sign16_le; 665 break; 666 default: 667 return (EINVAL); 668 } 669 break; 670 case AUDIO_ENCODING_ULINEAR_BE: 671 switch (p->precision) { 672 case 8: 673 md_format |= CMPCI_REG_FORMAT_8BIT; 674 break; 675 case 16: 676 md_format |= CMPCI_REG_FORMAT_16BIT; 677 if (mode & AUMODE_PLAY) 678 p->sw_code = 679 swap_bytes_change_sign16_le; 680 else 681 p->sw_code = 682 change_sign16_swap_bytes_le; 683 break; 684 default: 685 return (EINVAL); 686 } 687 break; 688 default: 689 return (EINVAL); 690 } 691 if (mode & AUMODE_PLAY) 692 cmpci_reg_partial_write_4(sc, 693 CMPCI_REG_CHANNEL_FORMAT, 694 CMPCI_REG_CH0_FORMAT_SHIFT, 695 CMPCI_REG_CH0_FORMAT_MASK, md_format); 696 else 697 cmpci_reg_partial_write_4(sc, 698 CMPCI_REG_CHANNEL_FORMAT, 699 CMPCI_REG_CH1_FORMAT_SHIFT, 700 CMPCI_REG_CH1_FORMAT_MASK, md_format); 701 /* sample rate */ 702 md_index = cmpci_rate_to_index(p->sample_rate); 703 md_divide = cmpci_index_to_divider(md_index); 704 p->sample_rate = cmpci_index_to_rate(md_index); 705 DPRINTF(("%s: sample:%d, divider=%d\n", 706 sc->sc_dev.dv_xname, (int)p->sample_rate, md_divide)); 707 if (mode & AUMODE_PLAY) { 708 cmpci_reg_partial_write_4(sc, 709 CMPCI_REG_FUNC_1, CMPCI_REG_DAC_FS_SHIFT, 710 CMPCI_REG_DAC_FS_MASK, md_divide); 711 sc->sc_play.md_divide = md_divide; 712 } else { 713 cmpci_reg_partial_write_4(sc, 714 CMPCI_REG_FUNC_1, CMPCI_REG_ADC_FS_SHIFT, 715 CMPCI_REG_ADC_FS_MASK, md_divide); 716 sc->sc_rec.md_divide = md_divide; 717 } 718 cmpci_set_mixer_gain(sc, CMPCI_SPDIF_LOOP); 719 } 720 return 0; 721 } 722 723 /* ARGSUSED */ 724 static int 725 cmpci_round_blocksize(handle, block) 726 void *handle; 727 int block; 728 { 729 return (block & -4); 730 } 731 732 static int 733 cmpci_halt_output(handle) 734 void *handle; 735 { 736 struct cmpci_softc *sc = handle; 737 int s; 738 739 s = splaudio(); 740 sc->sc_play.intr = NULL; 741 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE); 742 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE); 743 /* wait for reset DMA */ 744 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET); 745 delay(10); 746 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET); 747 splx(s); 748 749 return 0; 750 } 751 752 static int 753 cmpci_halt_input(handle) 754 void *handle; 755 { 756 struct cmpci_softc *sc = handle; 757 int s; 758 759 s = splaudio(); 760 sc->sc_rec.intr = NULL; 761 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE); 762 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE); 763 /* wait for reset DMA */ 764 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET); 765 delay(10); 766 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET); 767 splx(s); 768 769 return 0; 770 } 771 772 773 /* get audio device information */ 774 static int 775 cmpci_getdev(handle, ad) 776 void *handle; 777 struct audio_device *ad; 778 { 779 struct cmpci_softc *sc = handle; 780 781 strncpy(ad->name, "CMI PCI Audio", sizeof(ad->name)); 782 snprintf(ad->version, sizeof(ad->version), "0x%02x", 783 PCI_REVISION(sc->sc_class)); 784 switch (PCI_PRODUCT(sc->sc_id)) { 785 case PCI_PRODUCT_CMEDIA_CMI8338A: 786 strncpy(ad->config, "CMI8338A", sizeof(ad->config)); 787 break; 788 case PCI_PRODUCT_CMEDIA_CMI8338B: 789 strncpy(ad->config, "CMI8338B", sizeof(ad->config)); 790 break; 791 case PCI_PRODUCT_CMEDIA_CMI8738: 792 strncpy(ad->config, "CMI8738", sizeof(ad->config)); 793 break; 794 case PCI_PRODUCT_CMEDIA_CMI8738B: 795 strncpy(ad->config, "CMI8738B", sizeof(ad->config)); 796 break; 797 default: 798 strncpy(ad->config, "unknown", sizeof(ad->config)); 799 } 800 801 return 0; 802 } 803 804 805 /* mixer device information */ 806 int 807 cmpci_query_devinfo(handle, dip) 808 void *handle; 809 mixer_devinfo_t *dip; 810 { 811 switch (dip->index) { 812 case CMPCI_MASTER_VOL: 813 dip->type = AUDIO_MIXER_VALUE; 814 dip->mixer_class = CMPCI_OUTPUT_CLASS; 815 dip->prev = dip->next = AUDIO_MIXER_LAST; 816 strcpy(dip->label.name, AudioNmaster); 817 dip->un.v.num_channels = 2; 818 strcpy(dip->un.v.units.name, AudioNvolume); 819 return 0; 820 case CMPCI_FM_VOL: 821 dip->type = AUDIO_MIXER_VALUE; 822 dip->mixer_class = CMPCI_INPUT_CLASS; 823 dip->prev = AUDIO_MIXER_LAST; 824 dip->next = CMPCI_FM_IN_MUTE; 825 strcpy(dip->label.name, AudioNfmsynth); 826 dip->un.v.num_channels = 2; 827 strcpy(dip->un.v.units.name, AudioNvolume); 828 return 0; 829 case CMPCI_CD_VOL: 830 dip->type = AUDIO_MIXER_VALUE; 831 dip->mixer_class = CMPCI_INPUT_CLASS; 832 dip->prev = AUDIO_MIXER_LAST; 833 dip->next = CMPCI_CD_IN_MUTE; 834 strcpy(dip->label.name, AudioNcd); 835 dip->un.v.num_channels = 2; 836 strcpy(dip->un.v.units.name, AudioNvolume); 837 return 0; 838 case CMPCI_VOICE_VOL: 839 dip->type = AUDIO_MIXER_VALUE; 840 dip->mixer_class = CMPCI_OUTPUT_CLASS; 841 dip->prev = AUDIO_MIXER_LAST; 842 dip->next = AUDIO_MIXER_LAST; 843 strcpy(dip->label.name, AudioNdac); 844 dip->un.v.num_channels = 2; 845 strcpy(dip->un.v.units.name, AudioNvolume); 846 return 0; 847 case CMPCI_OUTPUT_CLASS: 848 dip->type = AUDIO_MIXER_CLASS; 849 dip->mixer_class = CMPCI_INPUT_CLASS; 850 dip->next = dip->prev = AUDIO_MIXER_LAST; 851 strcpy(dip->label.name, AudioCoutputs); 852 return 0; 853 case CMPCI_MIC_VOL: 854 dip->type = AUDIO_MIXER_VALUE; 855 dip->mixer_class = CMPCI_INPUT_CLASS; 856 dip->prev = AUDIO_MIXER_LAST; 857 dip->next = CMPCI_MIC_IN_MUTE; 858 strcpy(dip->label.name, AudioNmicrophone); 859 dip->un.v.num_channels = 1; 860 strcpy(dip->un.v.units.name, AudioNvolume); 861 return 0; 862 case CMPCI_LINE_IN_VOL: 863 dip->type = AUDIO_MIXER_VALUE; 864 dip->mixer_class = CMPCI_INPUT_CLASS; 865 dip->prev = AUDIO_MIXER_LAST; 866 dip->next = CMPCI_LINE_IN_MUTE; 867 strcpy(dip->label.name, AudioNline); 868 dip->un.v.num_channels = 2; 869 strcpy(dip->un.v.units.name, AudioNvolume); 870 return 0; 871 case CMPCI_RECORD_SOURCE: 872 dip->mixer_class = CMPCI_RECORD_CLASS; 873 dip->prev = dip->next = AUDIO_MIXER_LAST; 874 strcpy(dip->label.name, AudioNsource); 875 dip->type = AUDIO_MIXER_SET; 876 dip->un.s.num_mem = 5; 877 strcpy(dip->un.s.member[0].label.name, AudioNmicrophone); 878 dip->un.s.member[0].mask = 1 << CMPCI_MIC_VOL; 879 strcpy(dip->un.s.member[1].label.name, AudioNcd); 880 dip->un.s.member[1].mask = 1 << CMPCI_CD_VOL; 881 strcpy(dip->un.s.member[2].label.name, AudioNline); 882 dip->un.s.member[2].mask = 1 << CMPCI_LINE_IN_VOL; 883 strcpy(dip->un.s.member[3].label.name, AudioNfmsynth); 884 dip->un.s.member[3].mask = 1 << CMPCI_FM_VOL; 885 strcpy(dip->un.s.member[4].label.name, CmpciNspdif); 886 dip->un.s.member[4].mask = 1 << CMPCI_SPDIF_CLASS; 887 return 0; 888 case CMPCI_BASS: 889 dip->prev = dip->next = AUDIO_MIXER_LAST; 890 strcpy(dip->label.name, AudioNbass); 891 dip->type = AUDIO_MIXER_VALUE; 892 dip->mixer_class = CMPCI_EQUALIZATION_CLASS; 893 dip->un.v.num_channels = 2; 894 strcpy(dip->un.v.units.name, AudioNbass); 895 return 0; 896 case CMPCI_TREBLE: 897 dip->prev = dip->next = AUDIO_MIXER_LAST; 898 strcpy(dip->label.name, AudioNtreble); 899 dip->type = AUDIO_MIXER_VALUE; 900 dip->mixer_class = CMPCI_EQUALIZATION_CLASS; 901 dip->un.v.num_channels = 2; 902 strcpy(dip->un.v.units.name, AudioNtreble); 903 return 0; 904 case CMPCI_RECORD_CLASS: 905 dip->type = AUDIO_MIXER_CLASS; 906 dip->mixer_class = CMPCI_RECORD_CLASS; 907 dip->next = dip->prev = AUDIO_MIXER_LAST; 908 strcpy(dip->label.name, AudioCrecord); 909 return 0; 910 case CMPCI_INPUT_CLASS: 911 dip->type = AUDIO_MIXER_CLASS; 912 dip->mixer_class = CMPCI_INPUT_CLASS; 913 dip->next = dip->prev = AUDIO_MIXER_LAST; 914 strcpy(dip->label.name, AudioCinputs); 915 return 0; 916 case CMPCI_PCSPEAKER: 917 dip->type = AUDIO_MIXER_VALUE; 918 dip->mixer_class = CMPCI_INPUT_CLASS; 919 dip->prev = dip->next = AUDIO_MIXER_LAST; 920 strcpy(dip->label.name, "pc_speaker"); 921 dip->un.v.num_channels = 1; 922 strcpy(dip->un.v.units.name, AudioNvolume); 923 return 0; 924 case CMPCI_INPUT_GAIN: 925 dip->type = AUDIO_MIXER_VALUE; 926 dip->mixer_class = CMPCI_INPUT_CLASS; 927 dip->prev = dip->next = AUDIO_MIXER_LAST; 928 strcpy(dip->label.name, AudioNinput); 929 dip->un.v.num_channels = 2; 930 strcpy(dip->un.v.units.name, AudioNvolume); 931 return 0; 932 case CMPCI_OUTPUT_GAIN: 933 dip->type = AUDIO_MIXER_VALUE; 934 dip->mixer_class = CMPCI_OUTPUT_CLASS; 935 dip->prev = dip->next = AUDIO_MIXER_LAST; 936 strcpy(dip->label.name, AudioNoutput); 937 dip->un.v.num_channels = 2; 938 strcpy(dip->un.v.units.name, AudioNvolume); 939 return 0; 940 case CMPCI_AGC: 941 dip->type = AUDIO_MIXER_ENUM; 942 dip->mixer_class = CMPCI_INPUT_CLASS; 943 dip->prev = dip->next = AUDIO_MIXER_LAST; 944 strcpy(dip->label.name, "agc"); 945 goto on_off; 946 case CMPCI_EQUALIZATION_CLASS: 947 dip->type = AUDIO_MIXER_CLASS; 948 dip->mixer_class = CMPCI_EQUALIZATION_CLASS; 949 dip->next = dip->prev = AUDIO_MIXER_LAST; 950 strcpy(dip->label.name, AudioCequalization); 951 return 0; 952 case CMPCI_SPDIF_IN_MUTE: 953 dip->type = AUDIO_MIXER_CLASS; 954 dip->mixer_class = CMPCI_INPUT_CLASS; 955 dip->next = dip->prev = AUDIO_MIXER_LAST; 956 strcpy(dip->label.name, CmpciNspdif); 957 return 0; 958 case CMPCI_SPDIF_CLASS: 959 dip->type = AUDIO_MIXER_CLASS; 960 dip->mixer_class = CMPCI_SPDIF_CLASS; 961 dip->next = dip->prev = AUDIO_MIXER_LAST; 962 strcpy(dip->label.name, CmpciCspdif); 963 return 0; 964 case CMPCI_SPDIF_LOOP: 965 dip->mixer_class = CMPCI_SPDIF_CLASS; 966 dip->prev = dip->next = AUDIO_MIXER_LAST; 967 strcpy(dip->label.name, CmpciNloop); 968 goto on_off; 969 case CMPCI_SPDIF_LEGACY: 970 dip->mixer_class = CMPCI_SPDIF_CLASS; 971 dip->prev = dip->next = AUDIO_MIXER_LAST; 972 strcpy(dip->label.name, CmpciNlegacy); 973 goto on_off; 974 case CMPCI_SPDIF_OUT_VOLTAGE: 975 dip->mixer_class = CMPCI_SPDIF_CLASS; 976 dip->prev = dip->next = AUDIO_MIXER_LAST; 977 strcpy(dip->label.name, CmpciNout_voltage); 978 dip->type = AUDIO_MIXER_ENUM; 979 dip->un.e.num_mem = 2; 980 strcpy(dip->un.e.member[0].label.name, CmpciNlow_v); 981 dip->un.e.member[0].ord = 0; 982 strcpy(dip->un.e.member[1].label.name, CmpciNhigh_v); 983 dip->un.e.member[1].ord = 1; 984 return 0; 985 case CMPCI_SPDIF_IN_PHASE: 986 dip->mixer_class = CMPCI_SPDIF_CLASS; 987 dip->prev = dip->next = AUDIO_MIXER_LAST; 988 strcpy(dip->label.name, CmpciNin_phase); 989 goto on_off; 990 case CMPCI_REAR: 991 dip->mixer_class = CMPCI_OUTPUT_CLASS; 992 dip->prev = AUDIO_MIXER_LAST; 993 dip->next = CMPCI_INDIVIDUAL; 994 strcpy(dip->label.name, CmpciNrear); 995 goto on_off; 996 case CMPCI_INDIVIDUAL: 997 dip->mixer_class = CMPCI_OUTPUT_CLASS; 998 dip->prev = CMPCI_REAR; 999 dip->next = CMPCI_REVERSE; 1000 strcpy(dip->label.name, CmpciNindividual); 1001 goto on_off; 1002 case CMPCI_REVERSE: 1003 dip->mixer_class = CMPCI_OUTPUT_CLASS; 1004 dip->prev = CMPCI_INDIVIDUAL; 1005 dip->next = AUDIO_MIXER_LAST; 1006 strcpy(dip->label.name, CmpciNreverse); 1007 dip->type = AUDIO_MIXER_ENUM; 1008 dip->un.e.num_mem = 2; 1009 strcpy(dip->un.e.member[0].label.name, CmpciNpositive); 1010 dip->un.e.member[0].ord = 0; 1011 strcpy(dip->un.e.member[1].label.name, CmpciNnegative); 1012 dip->un.e.member[1].ord = 1; 1013 return 0; 1014 case CMPCI_SURROUND: 1015 dip->mixer_class = CMPCI_OUTPUT_CLASS; 1016 dip->prev = dip->next = AUDIO_MIXER_LAST; 1017 strcpy(dip->label.name, CmpciNsurround); 1018 goto on_off; 1019 1020 case CMPCI_CD_IN_MUTE: 1021 dip->prev = CMPCI_CD_VOL; 1022 dip->next = CMPCI_CD_SWAP; 1023 dip->mixer_class = CMPCI_INPUT_CLASS; 1024 goto mute; 1025 case CMPCI_MIC_IN_MUTE: 1026 dip->prev = CMPCI_MIC_VOL; 1027 dip->next = CMPCI_MIC_SWAP; 1028 dip->mixer_class = CMPCI_INPUT_CLASS; 1029 goto mute; 1030 case CMPCI_LINE_IN_MUTE: 1031 dip->prev = CMPCI_LINE_IN_VOL; 1032 dip->next = CMPCI_LINE_SWAP; 1033 dip->mixer_class = CMPCI_INPUT_CLASS; 1034 goto mute; 1035 case CMPCI_FM_IN_MUTE: 1036 dip->prev = CMPCI_FM_VOL; 1037 dip->next = CMPCI_FM_SWAP; 1038 dip->mixer_class = CMPCI_INPUT_CLASS; 1039 goto mute; 1040 case CMPCI_CD_SWAP: 1041 dip->prev = CMPCI_CD_IN_MUTE; 1042 dip->next = CMPCI_CD_OUT_MUTE; 1043 goto swap; 1044 case CMPCI_MIC_SWAP: 1045 dip->prev = CMPCI_MIC_IN_MUTE; 1046 dip->next = CMPCI_MIC_OUT_MUTE; 1047 goto swap; 1048 case CMPCI_LINE_SWAP: 1049 dip->prev = CMPCI_LINE_IN_MUTE; 1050 dip->next = CMPCI_LINE_OUT_MUTE; 1051 goto swap; 1052 case CMPCI_FM_SWAP: 1053 dip->prev = CMPCI_FM_IN_MUTE; 1054 dip->next = AUDIO_MIXER_LAST; 1055 swap: 1056 dip->mixer_class = CMPCI_INPUT_CLASS; 1057 strcpy(dip->label.name, AudioNswap); 1058 goto on_off; 1059 1060 case CMPCI_CD_OUT_MUTE: 1061 dip->prev = CMPCI_CD_SWAP; 1062 dip->next = AUDIO_MIXER_LAST; 1063 dip->mixer_class = CMPCI_OUTPUT_CLASS; 1064 goto mute; 1065 case CMPCI_MIC_OUT_MUTE: 1066 dip->prev = CMPCI_MIC_SWAP; 1067 dip->next = AUDIO_MIXER_LAST; 1068 dip->mixer_class = CMPCI_OUTPUT_CLASS; 1069 goto mute; 1070 case CMPCI_LINE_OUT_MUTE: 1071 dip->prev = CMPCI_LINE_SWAP; 1072 dip->next = AUDIO_MIXER_LAST; 1073 dip->mixer_class = CMPCI_OUTPUT_CLASS; 1074 mute: 1075 strcpy(dip->label.name, AudioNmute); 1076 on_off: 1077 dip->type = AUDIO_MIXER_ENUM; 1078 dip->un.e.num_mem = 2; 1079 strcpy(dip->un.e.member[0].label.name, AudioNoff); 1080 dip->un.e.member[0].ord = 0; 1081 strcpy(dip->un.e.member[1].label.name, AudioNon); 1082 dip->un.e.member[1].ord = 1; 1083 return 0; 1084 } 1085 1086 return ENXIO; 1087 } 1088 1089 static int 1090 cmpci_alloc_dmamem(sc, size, type, flags, r_addr) 1091 struct cmpci_softc *sc; 1092 size_t size; 1093 int type, flags; 1094 caddr_t *r_addr; 1095 { 1096 int error = 0; 1097 struct cmpci_dmanode *n; 1098 int w; 1099 1100 n = malloc(sizeof(struct cmpci_dmanode), type, flags); 1101 if (n == NULL) { 1102 error = ENOMEM; 1103 goto quit; 1104 } 1105 1106 w = (flags & M_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK; 1107 #define CMPCI_DMABUF_ALIGN 0x4 1108 #define CMPCI_DMABUF_BOUNDARY 0x0 1109 n->cd_tag = sc->sc_dmat; 1110 n->cd_size = size; 1111 error = bus_dmamem_alloc(n->cd_tag, n->cd_size, 1112 CMPCI_DMABUF_ALIGN, CMPCI_DMABUF_BOUNDARY, n->cd_segs, 1113 sizeof(n->cd_segs)/sizeof(n->cd_segs[0]), &n->cd_nsegs, w); 1114 if (error) 1115 goto mfree; 1116 error = bus_dmamem_map(n->cd_tag, n->cd_segs, n->cd_nsegs, n->cd_size, 1117 &n->cd_addr, w | BUS_DMA_COHERENT); 1118 if (error) 1119 goto dmafree; 1120 error = bus_dmamap_create(n->cd_tag, n->cd_size, 1, n->cd_size, 0, 1121 w, &n->cd_map); 1122 if (error) 1123 goto unmap; 1124 error = bus_dmamap_load(n->cd_tag, n->cd_map, n->cd_addr, n->cd_size, 1125 NULL, w); 1126 if (error) 1127 goto destroy; 1128 1129 n->cd_next = sc->sc_dmap; 1130 sc->sc_dmap = n; 1131 *r_addr = KVADDR(n); 1132 return 0; 1133 1134 destroy: 1135 bus_dmamap_destroy(n->cd_tag, n->cd_map); 1136 unmap: 1137 bus_dmamem_unmap(n->cd_tag, n->cd_addr, n->cd_size); 1138 dmafree: 1139 bus_dmamem_free(n->cd_tag, 1140 n->cd_segs, sizeof(n->cd_segs)/sizeof(n->cd_segs[0])); 1141 mfree: 1142 free(n, type); 1143 quit: 1144 return error; 1145 } 1146 1147 static int 1148 cmpci_free_dmamem(sc, addr, type) 1149 struct cmpci_softc *sc; 1150 caddr_t addr; 1151 int type; 1152 { 1153 struct cmpci_dmanode **nnp; 1154 1155 for (nnp = &sc->sc_dmap; *nnp; nnp= &(*nnp)->cd_next) { 1156 if ((*nnp)->cd_addr == addr) { 1157 struct cmpci_dmanode *n = *nnp; 1158 bus_dmamap_unload(n->cd_tag, n->cd_map); 1159 bus_dmamap_destroy(n->cd_tag, n->cd_map); 1160 bus_dmamem_unmap(n->cd_tag, n->cd_addr, n->cd_size); 1161 bus_dmamem_free(n->cd_tag, n->cd_segs, 1162 sizeof(n->cd_segs)/sizeof(n->cd_segs[0])); 1163 free(n, type); 1164 return 0; 1165 } 1166 } 1167 return -1; 1168 } 1169 1170 static struct cmpci_dmanode * 1171 cmpci_find_dmamem(sc, addr) 1172 struct cmpci_softc *sc; 1173 caddr_t addr; 1174 { 1175 struct cmpci_dmanode *p; 1176 for (p=sc->sc_dmap; p; p=p->cd_next) 1177 if ( KVADDR(p) == (void *)addr ) 1178 break; 1179 return p; 1180 } 1181 1182 1183 #if 0 1184 static void 1185 cmpci_print_dmamem __P((struct cmpci_dmanode *p)); 1186 static void 1187 cmpci_print_dmamem(p) 1188 struct cmpci_dmanode *p; 1189 { 1190 DPRINTF(("DMA at virt:%p, dmaseg:%p, mapseg:%p, size:%p\n", 1191 (void *)p->cd_addr, (void *)p->cd_segs[0].ds_addr, 1192 (void *)DMAADDR(p), (void *)p->cd_size)); 1193 } 1194 #endif /* DEBUG */ 1195 1196 1197 static void * 1198 cmpci_allocm(handle, direction, size, type, flags) 1199 void *handle; 1200 int direction; 1201 size_t size; 1202 int type, flags; 1203 { 1204 struct cmpci_softc *sc = handle; 1205 caddr_t addr; 1206 1207 if (cmpci_alloc_dmamem(sc, size, type, flags, &addr)) 1208 return NULL; 1209 return addr; 1210 } 1211 1212 static void 1213 cmpci_freem(handle, addr, type) 1214 void *handle; 1215 void *addr; 1216 int type; 1217 { 1218 struct cmpci_softc *sc = handle; 1219 1220 cmpci_free_dmamem(sc, addr, type); 1221 } 1222 1223 1224 #define MAXVAL 256 1225 static int 1226 cmpci_adjust(val, mask) 1227 int val, mask; 1228 { 1229 val += (MAXVAL - mask) >> 1; 1230 if (val >= MAXVAL) 1231 val = MAXVAL-1; 1232 return val & mask; 1233 } 1234 1235 static void 1236 cmpci_set_mixer_gain(sc, port) 1237 struct cmpci_softc *sc; 1238 int port; 1239 { 1240 int src; 1241 1242 switch (port) { 1243 case CMPCI_MIC_VOL: 1244 src = CMPCI_SB16_MIXER_MIC; 1245 break; 1246 case CMPCI_MASTER_VOL: 1247 src = CMPCI_SB16_MIXER_MASTER_L; 1248 break; 1249 case CMPCI_LINE_IN_VOL: 1250 src = CMPCI_SB16_MIXER_LINE_L; 1251 break; 1252 case CMPCI_VOICE_VOL: 1253 src = CMPCI_SB16_MIXER_VOICE_L; 1254 break; 1255 case CMPCI_FM_VOL: 1256 src = CMPCI_SB16_MIXER_FM_L; 1257 break; 1258 case CMPCI_CD_VOL: 1259 src = CMPCI_SB16_MIXER_CDDA_L; 1260 break; 1261 case CMPCI_INPUT_GAIN: 1262 src = CMPCI_SB16_MIXER_INGAIN_L; 1263 break; 1264 case CMPCI_OUTPUT_GAIN: 1265 src = CMPCI_SB16_MIXER_OUTGAIN_L; 1266 break; 1267 case CMPCI_TREBLE: 1268 src = CMPCI_SB16_MIXER_TREBLE_L; 1269 break; 1270 case CMPCI_BASS: 1271 src = CMPCI_SB16_MIXER_BASS_L; 1272 break; 1273 case CMPCI_PCSPEAKER: 1274 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_SPEAKER, 1275 sc->sc_gain[port][CMPCI_LEFT]); 1276 return; 1277 case CMPCI_SPDIF_IN_MUTE: 1278 if (CMPCI_ISCAP(sc, SPDIN_MONITOR)) { 1279 if (sc->sc_gain[CMPCI_SPDIF_IN_MUTE][CMPCI_LR]) 1280 cmpci_reg_set_4(sc, CMPCI_REG_MIXER24, 1281 CMPCI_REG_SPDIN_MONITOR); 1282 else 1283 cmpci_reg_set_4(sc, CMPCI_REG_MIXER24, 1284 CMPCI_REG_SPDIN_MONITOR); 1285 } 1286 1287 case CMPCI_SPDIF_LOOP: 1288 /*FALLTHROUGH*/ 1289 case CMPCI_SPDIF_LEGACY: 1290 cmpci_set_out_ports(sc); 1291 return; 1292 case CMPCI_SPDIF_OUT_VOLTAGE: 1293 if (CMPCI_ISCAP(sc, SPDOUT_VOLTAGE)) { 1294 if (sc->sc_gain[CMPCI_SPDIF_OUT_VOLTAGE][CMPCI_LR]) 1295 cmpci_reg_set_4(sc, CMPCI_REG_MISC, 1296 CMPCI_REG_5V); 1297 else 1298 cmpci_reg_clear_4(sc, CMPCI_REG_MISC, 1299 CMPCI_REG_5V); 1300 } 1301 return; 1302 case CMPCI_SURROUND: 1303 if (CMPCI_ISCAP(sc, SURROUND)) { 1304 if (sc->sc_gain[CMPCI_SURROUND][CMPCI_LR]) 1305 cmpci_reg_set_1(sc, CMPCI_REG_MIXER24, 1306 CMPCI_REG_SURROUND); 1307 else 1308 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24, 1309 CMPCI_REG_SURROUND); 1310 } 1311 return; 1312 case CMPCI_REAR: 1313 if (CMPCI_ISCAP(sc, REAR)) { 1314 if (sc->sc_gain[CMPCI_REAR][CMPCI_LR]) 1315 cmpci_reg_set_4(sc, CMPCI_REG_MISC, 1316 CMPCI_REG_N4SPK3D); 1317 else 1318 cmpci_reg_clear_4(sc, CMPCI_REG_MISC, 1319 CMPCI_REG_N4SPK3D); 1320 } 1321 return; 1322 case CMPCI_INDIVIDUAL: 1323 if (CMPCI_ISCAP(sc, INDIVIDUAL_REAR)) { 1324 if (sc->sc_gain[CMPCI_REAR][CMPCI_LR]) 1325 cmpci_reg_set_1(sc, CMPCI_REG_MIXER24, 1326 CMPCI_REG_INDIVIDUAL); 1327 else 1328 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24, 1329 CMPCI_REG_INDIVIDUAL); 1330 } 1331 return; 1332 case CMPCI_REVERSE: 1333 if (CMPCI_ISCAP(sc, REVERSE_FR)) { 1334 if (sc->sc_gain[CMPCI_REVERSE][CMPCI_LR]) 1335 cmpci_reg_set_1(sc, CMPCI_REG_MIXER24, 1336 CMPCI_REG_REVERSE_FR); 1337 else 1338 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24, 1339 CMPCI_REG_REVERSE_FR); 1340 } 1341 return; 1342 case CMPCI_SPDIF_IN_PHASE: 1343 if (CMPCI_ISCAP(sc, SPDIN_PHASE)) { 1344 if (sc->sc_gain[CMPCI_SPDIF_IN_PHASE][CMPCI_LR]) 1345 cmpci_reg_set_1(sc, CMPCI_REG_MIXER27, 1346 CMPCI_REG_PHASE); 1347 else 1348 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER27, 1349 CMPCI_REG_PHASE); 1350 } 1351 return; 1352 default: 1353 return; 1354 } 1355 cmpci_mixerreg_write(sc, src, sc->sc_gain[port][CMPCI_LEFT]); 1356 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_L_TO_R(src), 1357 sc->sc_gain[port][CMPCI_RIGHT]); 1358 } 1359 1360 static void 1361 cmpci_set_out_ports(sc) 1362 struct cmpci_softc *sc; 1363 { 1364 if (!CMPCI_ISCAP(sc, SPDLOOP)) 1365 return; 1366 if (sc->sc_gain[CMPCI_SPDIF_LOOP][CMPCI_LR]) { 1367 /* loop on */ 1368 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1, 1369 CMPCI_REG_SPDIF0_ENABLE | 1370 CMPCI_REG_SPDIF1_ENABLE); 1371 cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL, 1372 CMPCI_REG_LEGACY_SPDIF_ENABLE); 1373 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1, 1374 CMPCI_REG_SPDIF_LOOP); 1375 } else { 1376 /* loop off */ 1377 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1, 1378 CMPCI_REG_SPDIF_LOOP); 1379 cmpci_set_in_ports(sc, sc->sc_in_mask); 1380 if (CMPCI_ISCAP(sc, SPDOUT) && 1381 (sc->sc_play.md_divide==CMPCI_REG_RATE_44100 || 1382 (CMPCI_ISCAP(sc, SPDOUT_48K) && 1383 sc->sc_play.md_divide==CMPCI_REG_RATE_48000))) { 1384 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1, 1385 CMPCI_REG_SPDIF0_ENABLE); 1386 if (CMPCI_ISCAP(sc, XSPDOUT)) 1387 cmpci_reg_set_4(sc, 1388 CMPCI_REG_LEGACY_CTRL, 1389 CMPCI_REG_XSPDIF_ENABLE); 1390 if (sc->sc_play.md_divide==CMPCI_REG_RATE_48000) 1391 cmpci_reg_set_4(sc, 1392 CMPCI_REG_MISC, 1393 CMPCI_REG_SPDIF_48K); 1394 else 1395 cmpci_reg_clear_4(sc, 1396 CMPCI_REG_MISC, 1397 CMPCI_REG_SPDIF_48K); 1398 } else { 1399 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1, 1400 CMPCI_REG_SPDIF0_ENABLE); 1401 if (CMPCI_ISCAP(sc, XSPDOUT)) 1402 cmpci_reg_clear_4(sc, 1403 CMPCI_REG_LEGACY_CTRL, 1404 CMPCI_REG_XSPDIF_ENABLE); 1405 if (CMPCI_ISCAP(sc, SPDOUT_48K)) 1406 cmpci_reg_clear_4(sc, 1407 CMPCI_REG_MISC, 1408 CMPCI_REG_SPDIF_48K); 1409 } 1410 if (CMPCI_ISCAP(sc, SPDLEGACY)) { 1411 if (sc->sc_gain[CMPCI_SPDIF_LEGACY][CMPCI_LR]) 1412 cmpci_reg_set_4(sc, CMPCI_REG_LEGACY_CTRL, 1413 CMPCI_REG_LEGACY_SPDIF_ENABLE); 1414 else 1415 cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL, 1416 CMPCI_REG_LEGACY_SPDIF_ENABLE); 1417 } 1418 } 1419 } 1420 1421 static int 1422 cmpci_set_in_ports(sc, mask) 1423 struct cmpci_softc *sc; 1424 int mask; 1425 { 1426 int bitsl, bitsr; 1427 1428 if (mask & ~((1<<CMPCI_FM_VOL) | (1<<CMPCI_LINE_IN_VOL) | 1429 (1<<CMPCI_CD_VOL) | (1<<CMPCI_MIC_VOL) | 1430 (1<<CMPCI_SPDIF_CLASS))) 1431 return EINVAL; 1432 bitsr = 0; 1433 if (mask & (1<<CMPCI_FM_VOL)) bitsr |= CMPCI_SB16_MIXER_FM_SRC_R; 1434 if (mask & (1<<CMPCI_LINE_IN_VOL)) bitsr |= CMPCI_SB16_MIXER_LINE_SRC_R; 1435 if (mask & (1<<CMPCI_CD_VOL)) bitsr |= CMPCI_SB16_MIXER_CD_SRC_R; 1436 bitsl = CMPCI_SB16_MIXER_SRC_R_TO_L(bitsr); 1437 if (mask & (1<<CMPCI_MIC_VOL)) { 1438 bitsl |= CMPCI_SB16_MIXER_MIC_SRC; 1439 bitsr |= CMPCI_SB16_MIXER_MIC_SRC; 1440 } 1441 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, bitsl); 1442 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, bitsr); 1443 if (CMPCI_ISCAP(sc, SPDIN) && 1444 sc->sc_rec.md_divide == CMPCI_REG_RATE_44100 && 1445 !sc->sc_gain[CMPCI_SPDIF_LOOP][CMPCI_LR]) { 1446 if (mask & (1<<CMPCI_SPDIF_CLASS)) { 1447 /* enable SPDIF/in */ 1448 cmpci_reg_set_4(sc, 1449 CMPCI_REG_FUNC_1, 1450 CMPCI_REG_SPDIF1_ENABLE); 1451 } else { 1452 cmpci_reg_clear_4(sc, 1453 CMPCI_REG_FUNC_1, 1454 CMPCI_REG_SPDIF1_ENABLE); 1455 } 1456 } 1457 1458 sc->sc_in_mask = mask; 1459 1460 return 0; 1461 } 1462 1463 static int 1464 cmpci_set_port(handle, cp) 1465 void *handle; 1466 mixer_ctrl_t *cp; 1467 { 1468 struct cmpci_softc *sc = handle; 1469 int lgain, rgain; 1470 int mask, bits; 1471 int lmask, rmask, lbits, rbits; 1472 int mute, swap; 1473 1474 switch (cp->dev) { 1475 case CMPCI_TREBLE: 1476 case CMPCI_BASS: 1477 case CMPCI_PCSPEAKER: 1478 case CMPCI_INPUT_GAIN: 1479 case CMPCI_OUTPUT_GAIN: 1480 case CMPCI_MIC_VOL: 1481 case CMPCI_LINE_IN_VOL: 1482 case CMPCI_VOICE_VOL: 1483 case CMPCI_FM_VOL: 1484 case CMPCI_CD_VOL: 1485 case CMPCI_MASTER_VOL: 1486 if (cp->type != AUDIO_MIXER_VALUE) 1487 return EINVAL; 1488 switch (cp->dev) { 1489 case CMPCI_MIC_VOL: 1490 if (cp->un.value.num_channels != 1) 1491 return EINVAL; 1492 1493 lgain = rgain = 1494 CMPCI_ADJUST_MIC_GAIN(sc, 1495 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]); 1496 break; 1497 case CMPCI_PCSPEAKER: 1498 if (cp->un.value.num_channels != 1) 1499 return EINVAL; 1500 /* fall into */ 1501 case CMPCI_INPUT_GAIN: 1502 case CMPCI_OUTPUT_GAIN: 1503 lgain = rgain = CMPCI_ADJUST_2_GAIN(sc, 1504 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]); 1505 break; 1506 default: 1507 switch (cp->un.value.num_channels) { 1508 case 1: 1509 lgain = rgain = CMPCI_ADJUST_GAIN(sc, 1510 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] 1511 ); 1512 break; 1513 case 2: 1514 lgain = CMPCI_ADJUST_GAIN(sc, 1515 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] 1516 ); 1517 rgain = CMPCI_ADJUST_GAIN(sc, 1518 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] 1519 ); 1520 break; 1521 default: 1522 return EINVAL; 1523 } 1524 break; 1525 } 1526 sc->sc_gain[cp->dev][CMPCI_LEFT] = lgain; 1527 sc->sc_gain[cp->dev][CMPCI_RIGHT] = rgain; 1528 1529 cmpci_set_mixer_gain(sc, cp->dev); 1530 break; 1531 1532 case CMPCI_RECORD_SOURCE: 1533 if (cp->type != AUDIO_MIXER_SET) 1534 return EINVAL; 1535 #ifdef CMPCI_SPDIF_SUPPORT 1536 if (cp->un.mask & (1<<CMPCI_SPDIF_IN)) 1537 cp->un.mask = 1<<CMPCI_SPDIF_IN; 1538 #endif 1539 return cmpci_set_in_ports(sc, cp->un.mask); 1540 1541 case CMPCI_AGC: 1542 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_AGC, cp->un.ord & 1); 1543 break; 1544 1545 case CMPCI_CD_OUT_MUTE: 1546 mask = CMPCI_SB16_SW_CD; 1547 goto omute; 1548 case CMPCI_MIC_OUT_MUTE: 1549 mask = CMPCI_SB16_SW_MIC; 1550 goto omute; 1551 case CMPCI_LINE_OUT_MUTE: 1552 mask = CMPCI_SB16_SW_LINE; 1553 omute: 1554 if (cp->type != AUDIO_MIXER_ENUM) 1555 return EINVAL; 1556 bits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_OUTMIX); 1557 sc->sc_gain[cp->dev][CMPCI_LR] = cp->un.ord != 0; 1558 if (cp->un.ord) 1559 bits = bits & ~mask; 1560 else 1561 bits = bits | mask; 1562 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_OUTMIX, bits); 1563 break; 1564 1565 case CMPCI_MIC_IN_MUTE: 1566 case CMPCI_MIC_SWAP: 1567 lmask = rmask = CMPCI_SB16_SW_MIC; 1568 goto imute; 1569 case CMPCI_CD_IN_MUTE: 1570 case CMPCI_CD_SWAP: 1571 lmask = CMPCI_SB16_SW_CD_L; 1572 rmask = CMPCI_SB16_SW_CD_R; 1573 goto imute; 1574 case CMPCI_LINE_IN_MUTE: 1575 case CMPCI_LINE_SWAP: 1576 lmask = CMPCI_SB16_SW_LINE_L; 1577 rmask = CMPCI_SB16_SW_LINE_R; 1578 goto imute; 1579 case CMPCI_FM_IN_MUTE: 1580 case CMPCI_FM_SWAP: 1581 lmask = CMPCI_SB16_SW_FM_L; 1582 rmask = CMPCI_SB16_SW_FM_R; 1583 imute: 1584 if (cp->type != AUDIO_MIXER_ENUM) 1585 return EINVAL; 1586 mask = lmask | rmask; 1587 lbits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_ADCMIX_L) 1588 & ~mask; 1589 rbits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_ADCMIX_R) 1590 & ~mask; 1591 sc->sc_gain[cp->dev][CMPCI_LR] = cp->un.ord != 0; 1592 if (CMPCI_IS_IN_MUTE(cp->dev)) { 1593 mute = cp->dev; 1594 swap = mute - CMPCI_CD_IN_MUTE + CMPCI_CD_SWAP; 1595 } else { 1596 swap = cp->dev; 1597 mute = swap + CMPCI_CD_IN_MUTE - CMPCI_CD_SWAP; 1598 } 1599 if (sc->sc_gain[swap][CMPCI_LR]) { 1600 mask = lmask; 1601 lmask = rmask; 1602 rmask = mask; 1603 } 1604 if (!sc->sc_gain[mute][CMPCI_LR]) { 1605 lbits = lbits | lmask; 1606 rbits = rbits | rmask; 1607 } 1608 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, lbits); 1609 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, rbits); 1610 break; 1611 case CMPCI_SPDIF_LOOP: 1612 case CMPCI_SPDIF_OUT_VOLTAGE: 1613 case CMPCI_SPDIF_IN_PHASE: 1614 case CMPCI_REAR: 1615 case CMPCI_INDIVIDUAL: 1616 case CMPCI_REVERSE: 1617 case CMPCI_SURROUND: 1618 sc->sc_gain[cp->dev][CMPCI_LR] = cp->un.ord; 1619 break; 1620 1621 default: 1622 return EINVAL; 1623 } 1624 1625 return 0; 1626 } 1627 1628 static int 1629 cmpci_get_port(handle, cp) 1630 void *handle; 1631 mixer_ctrl_t *cp; 1632 { 1633 struct cmpci_softc *sc = handle; 1634 1635 switch (cp->dev) { 1636 case CMPCI_MIC_VOL: 1637 case CMPCI_LINE_IN_VOL: 1638 if (cp->un.value.num_channels != 1) 1639 return EINVAL; 1640 /* fall into */ 1641 case CMPCI_TREBLE: 1642 case CMPCI_BASS: 1643 case CMPCI_PCSPEAKER: 1644 case CMPCI_INPUT_GAIN: 1645 case CMPCI_OUTPUT_GAIN: 1646 case CMPCI_VOICE_VOL: 1647 case CMPCI_FM_VOL: 1648 case CMPCI_CD_VOL: 1649 case CMPCI_MASTER_VOL: 1650 switch (cp->un.value.num_channels) { 1651 case 1: 1652 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = 1653 sc->sc_gain[cp->dev][CMPCI_LEFT]; 1654 break; 1655 case 2: 1656 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 1657 sc->sc_gain[cp->dev][CMPCI_LEFT]; 1658 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 1659 sc->sc_gain[cp->dev][CMPCI_RIGHT]; 1660 break; 1661 default: 1662 return EINVAL; 1663 } 1664 break; 1665 1666 case CMPCI_RECORD_SOURCE: 1667 cp->un.mask = sc->sc_in_mask; 1668 break; 1669 1670 case CMPCI_AGC: 1671 cp->un.ord = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_AGC); 1672 break; 1673 1674 case CMPCI_CD_IN_MUTE: 1675 case CMPCI_MIC_IN_MUTE: 1676 case CMPCI_LINE_IN_MUTE: 1677 case CMPCI_FM_IN_MUTE: 1678 case CMPCI_CD_SWAP: 1679 case CMPCI_MIC_SWAP: 1680 case CMPCI_LINE_SWAP: 1681 case CMPCI_FM_SWAP: 1682 case CMPCI_CD_OUT_MUTE: 1683 case CMPCI_MIC_OUT_MUTE: 1684 case CMPCI_LINE_OUT_MUTE: 1685 case CMPCI_SPDIF_IN_MUTE: 1686 case CMPCI_SPDIF_LOOP: 1687 case CMPCI_SPDIF_LEGACY: 1688 case CMPCI_SPDIF_OUT_VOLTAGE: 1689 case CMPCI_SPDIF_IN_PHASE: 1690 case CMPCI_REAR: 1691 case CMPCI_INDIVIDUAL: 1692 case CMPCI_REVERSE: 1693 case CMPCI_SURROUND: 1694 cp->un.ord = sc->sc_gain[cp->dev][CMPCI_LR]; 1695 break; 1696 1697 default: 1698 return EINVAL; 1699 } 1700 1701 return 0; 1702 } 1703 1704 /* ARGSUSED */ 1705 static size_t 1706 cmpci_round_buffersize(handle, direction, bufsize) 1707 void *handle; 1708 int direction; 1709 size_t bufsize; 1710 { 1711 if (bufsize > 0x10000) 1712 bufsize = 0x10000; 1713 1714 return bufsize; 1715 } 1716 1717 1718 static paddr_t 1719 cmpci_mappage(handle, addr, offset, prot) 1720 void *handle; 1721 void *addr; 1722 off_t offset; 1723 int prot; 1724 { 1725 struct cmpci_softc *sc = handle; 1726 struct cmpci_dmanode *p; 1727 1728 if (offset < 0 || NULL == (p = cmpci_find_dmamem(sc, addr))) 1729 return -1; 1730 1731 return bus_dmamem_mmap(p->cd_tag, p->cd_segs, 1732 sizeof(p->cd_segs)/sizeof(p->cd_segs[0]), 1733 offset, prot, BUS_DMA_WAITOK); 1734 } 1735 1736 1737 /* ARGSUSED */ 1738 static int 1739 cmpci_get_props(handle) 1740 void *handle; 1741 { 1742 return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX; 1743 } 1744 1745 1746 static int 1747 cmpci_trigger_output(handle, start, end, blksize, intr, arg, param) 1748 void *handle; 1749 void *start, *end; 1750 int blksize; 1751 void (*intr) __P((void *)); 1752 void *arg; 1753 struct audio_params *param; 1754 { 1755 struct cmpci_softc *sc = handle; 1756 struct cmpci_dmanode *p; 1757 int bps; 1758 1759 sc->sc_play.intr = intr; 1760 sc->sc_play.intr_arg = arg; 1761 bps = param->channels*param->precision*param->factor / 8; 1762 if (!bps) 1763 return EINVAL; 1764 1765 /* set DMA frame */ 1766 if (!(p = cmpci_find_dmamem(sc, start))) 1767 return EINVAL; 1768 bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_BASE, 1769 DMAADDR(p)); 1770 delay(10); 1771 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_BYTES, 1772 ((caddr_t)end - (caddr_t)start + 1) / bps - 1); 1773 delay(10); 1774 1775 /* set interrupt count */ 1776 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_SAMPLES, 1777 (blksize + bps - 1) / bps - 1); 1778 delay(10); 1779 1780 /* start DMA */ 1781 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_DIR); /* PLAY */ 1782 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE); 1783 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE); 1784 1785 return 0; 1786 } 1787 1788 static int 1789 cmpci_trigger_input(handle, start, end, blksize, intr, arg, param) 1790 void *handle; 1791 void *start, *end; 1792 int blksize; 1793 void (*intr) __P((void *)); 1794 void *arg; 1795 struct audio_params *param; 1796 { 1797 struct cmpci_softc *sc = handle; 1798 struct cmpci_dmanode *p; 1799 int bps; 1800 1801 sc->sc_rec.intr = intr; 1802 sc->sc_rec.intr_arg = arg; 1803 bps = param->channels*param->precision*param->factor/8; 1804 if (!bps) 1805 return EINVAL; 1806 1807 /* set DMA frame */ 1808 if (!(p=cmpci_find_dmamem(sc, start))) 1809 return EINVAL; 1810 bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_BASE, 1811 DMAADDR(p)); 1812 delay(10); 1813 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_BYTES, 1814 ((caddr_t)end - (caddr_t)start + 1) / bps - 1); 1815 delay(10); 1816 1817 /* set interrupt count */ 1818 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_SAMPLES, 1819 (blksize + bps - 1) / bps - 1); 1820 delay(10); 1821 1822 /* start DMA */ 1823 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_DIR); /* REC */ 1824 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE); 1825 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE); 1826 1827 return 0; 1828 } 1829 1830 1831 /* end of file */ 1832