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