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