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