1 /* $NetBSD: cmpci.c,v 1.56 2019/06/08 08:02:38 isaki Exp $ */ 2 3 /* 4 * Copyright (c) 2000, 2001, 2008 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.56 2019/06/08 08:02:38 isaki 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/kmem.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/audio_if.h> 69 #include <dev/midi_if.h> 70 71 #include <dev/pci/cmpcireg.h> 72 #include <dev/pci/cmpcivar.h> 73 74 #include <dev/ic/mpuvar.h> 75 #include <sys/bus.h> 76 #include <sys/intr.h> 77 78 /* 79 * Low-level HW interface 80 */ 81 static inline uint8_t cmpci_mixerreg_read(struct cmpci_softc *, uint8_t); 82 static inline void cmpci_mixerreg_write(struct cmpci_softc *, 83 uint8_t, uint8_t); 84 static inline void cmpci_reg_partial_write_1(struct cmpci_softc *, int, int, 85 unsigned, unsigned); 86 static inline void cmpci_reg_partial_write_4(struct cmpci_softc *, int, int, 87 uint32_t, uint32_t); 88 static inline void cmpci_reg_set_1(struct cmpci_softc *, int, uint8_t); 89 static inline void cmpci_reg_clear_1(struct cmpci_softc *, int, uint8_t); 90 static inline void cmpci_reg_set_4(struct cmpci_softc *, int, uint32_t); 91 static inline void cmpci_reg_clear_4(struct cmpci_softc *, int, uint32_t); 92 static inline void cmpci_reg_set_reg_misc(struct cmpci_softc *, uint32_t); 93 static inline void cmpci_reg_clear_reg_misc(struct cmpci_softc *, uint32_t); 94 static int cmpci_rate_to_index(int); 95 static inline int cmpci_index_to_divider(int); 96 97 static int cmpci_adjust(int, int); 98 static void cmpci_set_mixer_gain(struct cmpci_softc *, int); 99 static void cmpci_set_out_ports(struct cmpci_softc *); 100 static int cmpci_set_in_ports(struct cmpci_softc *); 101 102 103 /* 104 * autoconf interface 105 */ 106 static int cmpci_match(device_t, cfdata_t, void *); 107 static void cmpci_attach(device_t, device_t, void *); 108 109 CFATTACH_DECL_NEW(cmpci, sizeof (struct cmpci_softc), 110 cmpci_match, cmpci_attach, NULL, NULL); 111 112 /* interrupt */ 113 static int cmpci_intr(void *); 114 115 116 /* 117 * DMA stuffs 118 */ 119 static int cmpci_alloc_dmamem(struct cmpci_softc *, size_t, void **); 120 static int cmpci_free_dmamem(struct cmpci_softc *, void *, size_t); 121 static struct cmpci_dmanode * cmpci_find_dmamem(struct cmpci_softc *, 122 void *); 123 124 125 /* 126 * interface to machine independent layer 127 */ 128 static int cmpci_query_format(void *, audio_format_query_t *); 129 static int cmpci_set_format(void *, int, 130 const audio_params_t *, const audio_params_t *, 131 audio_filter_reg_t *, audio_filter_reg_t *); 132 static int cmpci_round_blocksize(void *, int, int, const audio_params_t *); 133 static int cmpci_halt_output(void *); 134 static int cmpci_halt_input(void *); 135 static int cmpci_getdev(void *, struct audio_device *); 136 static int cmpci_set_port(void *, mixer_ctrl_t *); 137 static int cmpci_get_port(void *, mixer_ctrl_t *); 138 static int cmpci_query_devinfo(void *, mixer_devinfo_t *); 139 static void *cmpci_allocm(void *, int, size_t); 140 static void cmpci_freem(void *, void *, size_t); 141 static size_t cmpci_round_buffersize(void *, int, size_t); 142 static int cmpci_get_props(void *); 143 static int cmpci_trigger_output(void *, void *, void *, int, 144 void (*)(void *), void *, const audio_params_t *); 145 static int cmpci_trigger_input(void *, void *, void *, int, 146 void (*)(void *), void *, const audio_params_t *); 147 static void cmpci_get_locks(void *, kmutex_t **, kmutex_t **); 148 149 static const struct audio_hw_if cmpci_hw_if = { 150 .query_format = cmpci_query_format, 151 .set_format = cmpci_set_format, 152 .round_blocksize = cmpci_round_blocksize, 153 .halt_output = cmpci_halt_output, 154 .halt_input = cmpci_halt_input, 155 .getdev = cmpci_getdev, 156 .set_port = cmpci_set_port, 157 .get_port = cmpci_get_port, 158 .query_devinfo = cmpci_query_devinfo, 159 .allocm = cmpci_allocm, 160 .freem = cmpci_freem, 161 .round_buffersize = cmpci_round_buffersize, 162 .get_props = cmpci_get_props, 163 .trigger_output = cmpci_trigger_output, 164 .trigger_input = cmpci_trigger_input, 165 .get_locks = cmpci_get_locks, 166 }; 167 168 static const struct audio_format cmpci_formats[] = { 169 { 170 .mode = AUMODE_PLAY | AUMODE_RECORD, 171 .encoding = AUDIO_ENCODING_SLINEAR_LE, 172 .validbits = 16, 173 .precision = 16, 174 .channels = 2, 175 .channel_mask = AUFMT_STEREO, 176 .frequency_type = 8, 177 .frequency = 178 { 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000 }, 179 }, 180 }; 181 #define CMPCI_NFORMATS __arraycount(cmpci_formats) 182 183 184 /* 185 * Low-level HW interface 186 */ 187 188 /* mixer register read/write */ 189 static inline uint8_t 190 cmpci_mixerreg_read(struct cmpci_softc *sc, uint8_t no) 191 { 192 uint8_t ret; 193 194 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBADDR, no); 195 delay(10); 196 ret = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBDATA); 197 delay(10); 198 return ret; 199 } 200 201 static inline void 202 cmpci_mixerreg_write(struct cmpci_softc *sc, uint8_t no, uint8_t val) 203 { 204 205 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBADDR, no); 206 delay(10); 207 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBDATA, val); 208 delay(10); 209 } 210 211 212 /* register partial write */ 213 static inline void 214 cmpci_reg_partial_write_1(struct cmpci_softc *sc, int no, int shift, 215 unsigned mask, unsigned val) 216 { 217 218 bus_space_write_1(sc->sc_iot, sc->sc_ioh, no, 219 (val<<shift) | 220 (bus_space_read_1(sc->sc_iot, sc->sc_ioh, no) & ~(mask<<shift))); 221 delay(10); 222 } 223 224 static inline void 225 cmpci_reg_partial_write_4(struct cmpci_softc *sc, int no, int shift, 226 uint32_t mask, uint32_t val) 227 { 228 229 bus_space_write_4(sc->sc_iot, sc->sc_ioh, no, 230 (val<<shift) | 231 (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) & ~(mask<<shift))); 232 delay(10); 233 } 234 235 /* register set/clear bit */ 236 static inline void 237 cmpci_reg_set_1(struct cmpci_softc *sc, int no, uint8_t mask) 238 { 239 240 bus_space_write_1(sc->sc_iot, sc->sc_ioh, no, 241 (bus_space_read_1(sc->sc_iot, sc->sc_ioh, no) | mask)); 242 delay(10); 243 } 244 245 static inline void 246 cmpci_reg_clear_1(struct cmpci_softc *sc, int no, uint8_t mask) 247 { 248 249 bus_space_write_1(sc->sc_iot, sc->sc_ioh, no, 250 (bus_space_read_1(sc->sc_iot, sc->sc_ioh, no) & ~mask)); 251 delay(10); 252 } 253 254 static inline void 255 cmpci_reg_set_4(struct cmpci_softc *sc, int no, uint32_t mask) 256 { 257 258 /* use cmpci_reg_set_reg_misc() for CMPCI_REG_MISC */ 259 KDASSERT(no != CMPCI_REG_MISC); 260 261 bus_space_write_4(sc->sc_iot, sc->sc_ioh, no, 262 (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) | mask)); 263 delay(10); 264 } 265 266 static inline void 267 cmpci_reg_clear_4(struct cmpci_softc *sc, int no, uint32_t mask) 268 { 269 270 /* use cmpci_reg_clear_reg_misc() for CMPCI_REG_MISC */ 271 KDASSERT(no != CMPCI_REG_MISC); 272 273 bus_space_write_4(sc->sc_iot, sc->sc_ioh, no, 274 (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) & ~mask)); 275 delay(10); 276 } 277 278 /* 279 * The CMPCI_REG_MISC register needs special handling, since one of 280 * its bits has different read/write values. 281 */ 282 static inline void 283 cmpci_reg_set_reg_misc(struct cmpci_softc *sc, uint32_t mask) 284 { 285 286 sc->sc_reg_misc |= mask; 287 bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_MISC, 288 sc->sc_reg_misc); 289 delay(10); 290 } 291 292 static inline void 293 cmpci_reg_clear_reg_misc(struct cmpci_softc *sc, uint32_t mask) 294 { 295 296 sc->sc_reg_misc &= ~mask; 297 bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_MISC, 298 sc->sc_reg_misc); 299 delay(10); 300 } 301 302 /* rate */ 303 static const struct { 304 int rate; 305 int divider; 306 } cmpci_rate_table[CMPCI_REG_NUMRATE] = { 307 #define _RATE(n) { n, CMPCI_REG_RATE_ ## n } 308 _RATE(5512), 309 _RATE(8000), 310 _RATE(11025), 311 _RATE(16000), 312 _RATE(22050), 313 _RATE(32000), 314 _RATE(44100), 315 _RATE(48000) 316 #undef _RATE 317 }; 318 319 static int 320 cmpci_rate_to_index(int rate) 321 { 322 int i; 323 324 for (i = 0; i < CMPCI_REG_NUMRATE - 1; i++) 325 if (rate == cmpci_rate_table[i].rate) 326 return i; 327 return i; /* 48000 */ 328 } 329 330 static inline int 331 cmpci_index_to_divider(int index) 332 { 333 334 return cmpci_rate_table[index].divider; 335 } 336 337 /* 338 * interface to configure the device. 339 */ 340 static int 341 cmpci_match(device_t parent, cfdata_t match, void *aux) 342 { 343 struct pci_attach_args *pa; 344 345 pa = (struct pci_attach_args *)aux; 346 if ( PCI_VENDOR(pa->pa_id) == PCI_VENDOR_CMEDIA && 347 (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMEDIA_CMI8338A || 348 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMEDIA_CMI8338B || 349 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMEDIA_CMI8738 || 350 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMEDIA_CMI8738B) ) 351 return 1; 352 353 return 0; 354 } 355 356 static void 357 cmpci_attach(device_t parent, device_t self, void *aux) 358 { 359 struct cmpci_softc *sc; 360 struct pci_attach_args *pa; 361 struct audio_attach_args aa; 362 pci_intr_handle_t ih; 363 char const *strintr; 364 int i, v; 365 char intrbuf[PCI_INTRSTR_LEN]; 366 367 sc = device_private(self); 368 sc->sc_dev = self; 369 pa = (struct pci_attach_args *)aux; 370 371 sc->sc_id = pa->pa_id; 372 sc->sc_class = pa->pa_class; 373 pci_aprint_devinfo(pa, "Audio controller"); 374 switch (PCI_PRODUCT(sc->sc_id)) { 375 case PCI_PRODUCT_CMEDIA_CMI8338A: 376 /*FALLTHROUGH*/ 377 case PCI_PRODUCT_CMEDIA_CMI8338B: 378 sc->sc_capable = CMPCI_CAP_CMI8338; 379 break; 380 case PCI_PRODUCT_CMEDIA_CMI8738: 381 /*FALLTHROUGH*/ 382 case PCI_PRODUCT_CMEDIA_CMI8738B: 383 sc->sc_capable = CMPCI_CAP_CMI8738; 384 break; 385 } 386 387 /* map I/O space */ 388 if (pci_mapreg_map(pa, CMPCI_PCI_IOBASEREG, PCI_MAPREG_TYPE_IO, 0, 389 &sc->sc_iot, &sc->sc_ioh, NULL, NULL)) { 390 aprint_error_dev(sc->sc_dev, "failed to map I/O space\n"); 391 return; 392 } 393 394 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); 395 mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO); 396 397 /* interrupt */ 398 if (pci_intr_map(pa, &ih)) { 399 aprint_error_dev(sc->sc_dev, "failed to map interrupt\n"); 400 return; 401 } 402 strintr = pci_intr_string(pa->pa_pc, ih, intrbuf, sizeof(intrbuf)); 403 sc->sc_ih = pci_intr_establish_xname(pa->pa_pc, ih, IPL_AUDIO, 404 cmpci_intr, sc, device_xname(self)); 405 if (sc->sc_ih == NULL) { 406 aprint_error_dev(sc->sc_dev, "failed to establish interrupt"); 407 if (strintr != NULL) 408 aprint_error(" at %s", strintr); 409 aprint_error("\n"); 410 mutex_destroy(&sc->sc_lock); 411 mutex_destroy(&sc->sc_intr_lock); 412 return; 413 } 414 aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", strintr); 415 416 sc->sc_dmat = pa->pa_dmat; 417 418 audio_attach_mi(&cmpci_hw_if, sc, sc->sc_dev); 419 420 /* attach OPL device */ 421 aa.type = AUDIODEV_TYPE_OPL; 422 aa.hwif = NULL; 423 aa.hdl = NULL; 424 (void)config_found(sc->sc_dev, &aa, audioprint); 425 426 /* attach MPU-401 device */ 427 aa.type = AUDIODEV_TYPE_MPU; 428 aa.hwif = NULL; 429 aa.hdl = NULL; 430 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 431 CMPCI_REG_MPU_BASE, CMPCI_REG_MPU_SIZE, &sc->sc_mpu_ioh) == 0) 432 sc->sc_mpudev = config_found(sc->sc_dev, &aa, audioprint); 433 434 /* get initial value (this is 0 and may be omitted but just in case) */ 435 sc->sc_reg_misc = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 436 CMPCI_REG_MISC) & ~CMPCI_REG_SPDIF48K; 437 438 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_RESET, 0); 439 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, 0); 440 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, 0); 441 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_OUTMIX, 442 CMPCI_SB16_SW_CD|CMPCI_SB16_SW_MIC | CMPCI_SB16_SW_LINE); 443 for (i = 0; i < CMPCI_NDEVS; i++) { 444 switch (i) { 445 /* 446 * CMI8738 defaults are 447 * master: 0xe0 (0x00 - 0xf8) 448 * FM, DAC: 0xc0 (0x00 - 0xf8) 449 * PC speaker: 0x80 (0x00 - 0xc0) 450 * others: 0 451 */ 452 /* volume */ 453 case CMPCI_MASTER_VOL: 454 v = 128; /* 224 */ 455 break; 456 case CMPCI_FM_VOL: 457 case CMPCI_DAC_VOL: 458 v = 192; 459 break; 460 case CMPCI_PCSPEAKER: 461 v = 128; 462 break; 463 464 /* booleans, set to true */ 465 case CMPCI_CD_MUTE: 466 case CMPCI_MIC_MUTE: 467 case CMPCI_LINE_IN_MUTE: 468 case CMPCI_AUX_IN_MUTE: 469 v = 1; 470 break; 471 472 /* volume with inital value 0 */ 473 case CMPCI_CD_VOL: 474 case CMPCI_LINE_IN_VOL: 475 case CMPCI_AUX_IN_VOL: 476 case CMPCI_MIC_VOL: 477 case CMPCI_MIC_RECVOL: 478 /* FALLTHROUGH */ 479 480 /* others are cleared */ 481 case CMPCI_MIC_PREAMP: 482 case CMPCI_RECORD_SOURCE: 483 case CMPCI_PLAYBACK_MODE: 484 case CMPCI_SPDIF_IN_SELECT: 485 case CMPCI_SPDIF_IN_PHASE: 486 case CMPCI_SPDIF_LOOP: 487 case CMPCI_SPDIF_OUT_PLAYBACK: 488 case CMPCI_SPDIF_OUT_VOLTAGE: 489 case CMPCI_MONITOR_DAC: 490 case CMPCI_REAR: 491 case CMPCI_INDIVIDUAL: 492 case CMPCI_REVERSE: 493 case CMPCI_SURROUND: 494 default: 495 v = 0; 496 break; 497 } 498 sc->sc_gain[i][CMPCI_LEFT] = sc->sc_gain[i][CMPCI_RIGHT] = v; 499 cmpci_set_mixer_gain(sc, i); 500 } 501 } 502 503 static int 504 cmpci_intr(void *handle) 505 { 506 struct cmpci_softc *sc = handle; 507 #if NMPU > 0 508 struct mpu_softc *sc_mpu = device_private(sc->sc_mpudev); 509 #endif 510 uint32_t intrstat; 511 512 mutex_spin_enter(&sc->sc_intr_lock); 513 514 intrstat = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 515 CMPCI_REG_INTR_STATUS); 516 517 if (!(intrstat & CMPCI_REG_ANY_INTR)) { 518 mutex_spin_exit(&sc->sc_intr_lock); 519 return 0; 520 } 521 522 delay(10); 523 524 /* disable and reset intr */ 525 if (intrstat & CMPCI_REG_CH0_INTR) 526 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, 527 CMPCI_REG_CH0_INTR_ENABLE); 528 if (intrstat & CMPCI_REG_CH1_INTR) 529 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, 530 CMPCI_REG_CH1_INTR_ENABLE); 531 532 if (intrstat & CMPCI_REG_CH0_INTR) { 533 if (sc->sc_play.intr != NULL) 534 (*sc->sc_play.intr)(sc->sc_play.intr_arg); 535 } 536 if (intrstat & CMPCI_REG_CH1_INTR) { 537 if (sc->sc_rec.intr != NULL) 538 (*sc->sc_rec.intr)(sc->sc_rec.intr_arg); 539 } 540 541 /* enable intr */ 542 if (intrstat & CMPCI_REG_CH0_INTR) 543 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, 544 CMPCI_REG_CH0_INTR_ENABLE); 545 if (intrstat & CMPCI_REG_CH1_INTR) 546 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, 547 CMPCI_REG_CH1_INTR_ENABLE); 548 549 #if NMPU > 0 550 if (intrstat & CMPCI_REG_UART_INTR && sc_mpu != NULL) 551 mpu_intr(sc_mpu); 552 #endif 553 554 mutex_spin_exit(&sc->sc_intr_lock); 555 return 1; 556 } 557 558 static int 559 cmpci_query_format(void *handle, audio_format_query_t *afp) 560 { 561 562 return audio_query_format(cmpci_formats, CMPCI_NFORMATS, afp); 563 } 564 565 static int 566 cmpci_set_format(void *handle, int setmode, 567 const audio_params_t *play, const audio_params_t *rec, 568 audio_filter_reg_t *pfil, audio_filter_reg_t *rfil) 569 { 570 int i; 571 struct cmpci_softc *sc; 572 573 sc = handle; 574 for (i = 0; i < 2; i++) { 575 int md_format; 576 int md_divide; 577 int md_index; 578 int mode; 579 const audio_params_t *p; 580 581 switch (i) { 582 case 0: 583 mode = AUMODE_PLAY; 584 p = play; 585 break; 586 case 1: 587 mode = AUMODE_RECORD; 588 p = rec; 589 break; 590 default: 591 return EINVAL; 592 } 593 594 if (!(setmode & mode)) 595 continue; 596 597 md_index = cmpci_rate_to_index(p->sample_rate); 598 md_divide = cmpci_index_to_divider(md_index); 599 DPRINTF(("%s: sample:%u, divider=%d\n", 600 device_xname(sc->sc_dev), p->sample_rate, md_divide)); 601 602 /* format */ 603 md_format = p->channels == 1 604 ? CMPCI_REG_FORMAT_MONO : CMPCI_REG_FORMAT_STEREO; 605 md_format |= p->precision == 16 606 ? CMPCI_REG_FORMAT_16BIT : CMPCI_REG_FORMAT_8BIT; 607 if (mode & AUMODE_PLAY) { 608 cmpci_reg_partial_write_4(sc, 609 CMPCI_REG_CHANNEL_FORMAT, 610 CMPCI_REG_CH0_FORMAT_SHIFT, 611 CMPCI_REG_CH0_FORMAT_MASK, md_format); 612 cmpci_reg_partial_write_4(sc, 613 CMPCI_REG_FUNC_1, CMPCI_REG_DAC_FS_SHIFT, 614 CMPCI_REG_DAC_FS_MASK, md_divide); 615 sc->sc_play.md_divide = md_divide; 616 } else { 617 cmpci_reg_partial_write_4(sc, 618 CMPCI_REG_CHANNEL_FORMAT, 619 CMPCI_REG_CH1_FORMAT_SHIFT, 620 CMPCI_REG_CH1_FORMAT_MASK, md_format); 621 cmpci_reg_partial_write_4(sc, 622 CMPCI_REG_FUNC_1, CMPCI_REG_ADC_FS_SHIFT, 623 CMPCI_REG_ADC_FS_MASK, md_divide); 624 sc->sc_rec.md_divide = md_divide; 625 } 626 cmpci_set_out_ports(sc); 627 cmpci_set_in_ports(sc); 628 } 629 return 0; 630 } 631 632 /* ARGSUSED */ 633 static int 634 cmpci_round_blocksize(void *handle, int block, 635 int mode, const audio_params_t *param) 636 { 637 638 return block & -4; 639 } 640 641 static int 642 cmpci_halt_output(void *handle) 643 { 644 struct cmpci_softc *sc; 645 646 sc = handle; 647 sc->sc_play.intr = NULL; 648 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE); 649 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE); 650 /* wait for reset DMA */ 651 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET); 652 delay(10); 653 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET); 654 655 return 0; 656 } 657 658 static int 659 cmpci_halt_input(void *handle) 660 { 661 struct cmpci_softc *sc; 662 663 sc = handle; 664 sc->sc_rec.intr = NULL; 665 cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE); 666 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE); 667 /* wait for reset DMA */ 668 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET); 669 delay(10); 670 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET); 671 672 return 0; 673 } 674 675 /* get audio device information */ 676 static int 677 cmpci_getdev(void *handle, struct audio_device *ad) 678 { 679 struct cmpci_softc *sc; 680 681 sc = handle; 682 strncpy(ad->name, "CMI PCI Audio", sizeof(ad->name)); 683 snprintf(ad->version, sizeof(ad->version), "0x%02x", 684 PCI_REVISION(sc->sc_class)); 685 switch (PCI_PRODUCT(sc->sc_id)) { 686 case PCI_PRODUCT_CMEDIA_CMI8338A: 687 strncpy(ad->config, "CMI8338A", sizeof(ad->config)); 688 break; 689 case PCI_PRODUCT_CMEDIA_CMI8338B: 690 strncpy(ad->config, "CMI8338B", sizeof(ad->config)); 691 break; 692 case PCI_PRODUCT_CMEDIA_CMI8738: 693 strncpy(ad->config, "CMI8738", sizeof(ad->config)); 694 break; 695 case PCI_PRODUCT_CMEDIA_CMI8738B: 696 strncpy(ad->config, "CMI8738B", sizeof(ad->config)); 697 break; 698 default: 699 strncpy(ad->config, "unknown", sizeof(ad->config)); 700 } 701 702 return 0; 703 } 704 705 /* mixer device information */ 706 int 707 cmpci_query_devinfo(void *handle, mixer_devinfo_t *dip) 708 { 709 static const char *const mixer_port_names[] = { 710 AudioNdac, AudioNfmsynth, AudioNcd, AudioNline, AudioNaux, 711 AudioNmicrophone 712 }; 713 static const char *const mixer_classes[] = { 714 AudioCinputs, AudioCoutputs, AudioCrecord, CmpciCplayback, 715 CmpciCspdif 716 }; 717 struct cmpci_softc *sc; 718 int i; 719 720 sc = handle; 721 dip->prev = dip->next = AUDIO_MIXER_LAST; 722 723 switch (dip->index) { 724 case CMPCI_INPUT_CLASS: 725 case CMPCI_OUTPUT_CLASS: 726 case CMPCI_RECORD_CLASS: 727 case CMPCI_PLAYBACK_CLASS: 728 case CMPCI_SPDIF_CLASS: 729 dip->type = AUDIO_MIXER_CLASS; 730 dip->mixer_class = dip->index; 731 strcpy(dip->label.name, 732 mixer_classes[dip->index - CMPCI_INPUT_CLASS]); 733 return 0; 734 735 case CMPCI_AUX_IN_VOL: 736 dip->un.v.delta = 1 << (8 - CMPCI_REG_AUX_VALBITS); 737 goto vol1; 738 case CMPCI_DAC_VOL: 739 case CMPCI_FM_VOL: 740 case CMPCI_CD_VOL: 741 case CMPCI_LINE_IN_VOL: 742 case CMPCI_MIC_VOL: 743 dip->un.v.delta = 1 << (8 - CMPCI_SB16_MIXER_VALBITS); 744 vol1: dip->mixer_class = CMPCI_INPUT_CLASS; 745 dip->next = dip->index + 6; /* CMPCI_xxx_MUTE */ 746 strcpy(dip->label.name, mixer_port_names[dip->index]); 747 dip->un.v.num_channels = (dip->index == CMPCI_MIC_VOL ? 1 : 2); 748 vol: 749 dip->type = AUDIO_MIXER_VALUE; 750 strcpy(dip->un.v.units.name, AudioNvolume); 751 return 0; 752 753 case CMPCI_MIC_MUTE: 754 dip->next = CMPCI_MIC_PREAMP; 755 /* FALLTHROUGH */ 756 case CMPCI_DAC_MUTE: 757 case CMPCI_FM_MUTE: 758 case CMPCI_CD_MUTE: 759 case CMPCI_LINE_IN_MUTE: 760 case CMPCI_AUX_IN_MUTE: 761 dip->prev = dip->index - 6; /* CMPCI_xxx_VOL */ 762 dip->mixer_class = CMPCI_INPUT_CLASS; 763 strcpy(dip->label.name, AudioNmute); 764 goto on_off; 765 on_off: 766 dip->type = AUDIO_MIXER_ENUM; 767 dip->un.e.num_mem = 2; 768 strcpy(dip->un.e.member[0].label.name, AudioNoff); 769 dip->un.e.member[0].ord = 0; 770 strcpy(dip->un.e.member[1].label.name, AudioNon); 771 dip->un.e.member[1].ord = 1; 772 return 0; 773 774 case CMPCI_MIC_PREAMP: 775 dip->mixer_class = CMPCI_INPUT_CLASS; 776 dip->prev = CMPCI_MIC_MUTE; 777 strcpy(dip->label.name, AudioNpreamp); 778 goto on_off; 779 case CMPCI_PCSPEAKER: 780 dip->mixer_class = CMPCI_INPUT_CLASS; 781 strcpy(dip->label.name, AudioNspeaker); 782 dip->un.v.num_channels = 1; 783 dip->un.v.delta = 1 << (8 - CMPCI_SB16_MIXER_SPEAKER_VALBITS); 784 goto vol; 785 case CMPCI_RECORD_SOURCE: 786 dip->mixer_class = CMPCI_RECORD_CLASS; 787 strcpy(dip->label.name, AudioNsource); 788 dip->type = AUDIO_MIXER_SET; 789 dip->un.s.num_mem = 7; 790 strcpy(dip->un.s.member[0].label.name, AudioNmicrophone); 791 dip->un.s.member[0].mask = CMPCI_RECORD_SOURCE_MIC; 792 strcpy(dip->un.s.member[1].label.name, AudioNcd); 793 dip->un.s.member[1].mask = CMPCI_RECORD_SOURCE_CD; 794 strcpy(dip->un.s.member[2].label.name, AudioNline); 795 dip->un.s.member[2].mask = CMPCI_RECORD_SOURCE_LINE_IN; 796 strcpy(dip->un.s.member[3].label.name, AudioNaux); 797 dip->un.s.member[3].mask = CMPCI_RECORD_SOURCE_AUX_IN; 798 strcpy(dip->un.s.member[4].label.name, AudioNwave); 799 dip->un.s.member[4].mask = CMPCI_RECORD_SOURCE_WAVE; 800 strcpy(dip->un.s.member[5].label.name, AudioNfmsynth); 801 dip->un.s.member[5].mask = CMPCI_RECORD_SOURCE_FM; 802 strcpy(dip->un.s.member[6].label.name, CmpciNspdif); 803 dip->un.s.member[6].mask = CMPCI_RECORD_SOURCE_SPDIF; 804 return 0; 805 case CMPCI_MIC_RECVOL: 806 dip->mixer_class = CMPCI_RECORD_CLASS; 807 strcpy(dip->label.name, AudioNmicrophone); 808 dip->un.v.num_channels = 1; 809 dip->un.v.delta = 1 << (8 - CMPCI_REG_ADMIC_VALBITS); 810 goto vol; 811 812 case CMPCI_PLAYBACK_MODE: 813 dip->mixer_class = CMPCI_PLAYBACK_CLASS; 814 dip->type = AUDIO_MIXER_ENUM; 815 strcpy(dip->label.name, AudioNmode); 816 dip->un.e.num_mem = 2; 817 strcpy(dip->un.e.member[0].label.name, AudioNdac); 818 dip->un.e.member[0].ord = CMPCI_PLAYBACK_MODE_WAVE; 819 strcpy(dip->un.e.member[1].label.name, CmpciNspdif); 820 dip->un.e.member[1].ord = CMPCI_PLAYBACK_MODE_SPDIF; 821 return 0; 822 case CMPCI_SPDIF_IN_SELECT: 823 dip->mixer_class = CMPCI_SPDIF_CLASS; 824 dip->type = AUDIO_MIXER_ENUM; 825 dip->next = CMPCI_SPDIF_IN_PHASE; 826 strcpy(dip->label.name, AudioNinput); 827 i = 0; 828 strcpy(dip->un.e.member[i].label.name, CmpciNspdin1); 829 dip->un.e.member[i++].ord = CMPCI_SPDIF_IN_SPDIN1; 830 if (CMPCI_ISCAP(sc, 2ND_SPDIN)) { 831 strcpy(dip->un.e.member[i].label.name, CmpciNspdin2); 832 dip->un.e.member[i++].ord = CMPCI_SPDIF_IN_SPDIN2; 833 } 834 strcpy(dip->un.e.member[i].label.name, CmpciNspdout); 835 dip->un.e.member[i++].ord = CMPCI_SPDIF_IN_SPDOUT; 836 dip->un.e.num_mem = i; 837 return 0; 838 case CMPCI_SPDIF_IN_PHASE: 839 dip->mixer_class = CMPCI_SPDIF_CLASS; 840 dip->prev = CMPCI_SPDIF_IN_SELECT; 841 strcpy(dip->label.name, CmpciNphase); 842 dip->type = AUDIO_MIXER_ENUM; 843 dip->un.e.num_mem = 2; 844 strcpy(dip->un.e.member[0].label.name, CmpciNpositive); 845 dip->un.e.member[0].ord = CMPCI_SPDIF_IN_PHASE_POSITIVE; 846 strcpy(dip->un.e.member[1].label.name, CmpciNnegative); 847 dip->un.e.member[1].ord = CMPCI_SPDIF_IN_PHASE_NEGATIVE; 848 return 0; 849 case CMPCI_SPDIF_LOOP: 850 dip->mixer_class = CMPCI_SPDIF_CLASS; 851 dip->next = CMPCI_SPDIF_OUT_PLAYBACK; 852 strcpy(dip->label.name, AudioNoutput); 853 dip->type = AUDIO_MIXER_ENUM; 854 dip->un.e.num_mem = 2; 855 strcpy(dip->un.e.member[0].label.name, CmpciNplayback); 856 dip->un.e.member[0].ord = CMPCI_SPDIF_LOOP_OFF; 857 strcpy(dip->un.e.member[1].label.name, CmpciNspdin); 858 dip->un.e.member[1].ord = CMPCI_SPDIF_LOOP_ON; 859 return 0; 860 case CMPCI_SPDIF_OUT_PLAYBACK: 861 dip->mixer_class = CMPCI_SPDIF_CLASS; 862 dip->prev = CMPCI_SPDIF_LOOP; 863 dip->next = CMPCI_SPDIF_OUT_VOLTAGE; 864 strcpy(dip->label.name, CmpciNplayback); 865 dip->type = AUDIO_MIXER_ENUM; 866 dip->un.e.num_mem = 2; 867 strcpy(dip->un.e.member[0].label.name, AudioNwave); 868 dip->un.e.member[0].ord = CMPCI_SPDIF_OUT_PLAYBACK_WAVE; 869 strcpy(dip->un.e.member[1].label.name, CmpciNlegacy); 870 dip->un.e.member[1].ord = CMPCI_SPDIF_OUT_PLAYBACK_LEGACY; 871 return 0; 872 case CMPCI_SPDIF_OUT_VOLTAGE: 873 dip->mixer_class = CMPCI_SPDIF_CLASS; 874 dip->prev = CMPCI_SPDIF_OUT_PLAYBACK; 875 strcpy(dip->label.name, CmpciNvoltage); 876 dip->type = AUDIO_MIXER_ENUM; 877 dip->un.e.num_mem = 2; 878 strcpy(dip->un.e.member[0].label.name, CmpciNhigh_v); 879 dip->un.e.member[0].ord = CMPCI_SPDIF_OUT_VOLTAGE_HIGH; 880 strcpy(dip->un.e.member[1].label.name, CmpciNlow_v); 881 dip->un.e.member[1].ord = CMPCI_SPDIF_OUT_VOLTAGE_LOW; 882 return 0; 883 case CMPCI_MONITOR_DAC: 884 dip->mixer_class = CMPCI_SPDIF_CLASS; 885 strcpy(dip->label.name, AudioNmonitor); 886 dip->type = AUDIO_MIXER_ENUM; 887 dip->un.e.num_mem = 3; 888 strcpy(dip->un.e.member[0].label.name, AudioNoff); 889 dip->un.e.member[0].ord = CMPCI_MONITOR_DAC_OFF; 890 strcpy(dip->un.e.member[1].label.name, CmpciNspdin); 891 dip->un.e.member[1].ord = CMPCI_MONITOR_DAC_SPDIN; 892 strcpy(dip->un.e.member[2].label.name, CmpciNspdout); 893 dip->un.e.member[2].ord = CMPCI_MONITOR_DAC_SPDOUT; 894 return 0; 895 896 case CMPCI_MASTER_VOL: 897 dip->mixer_class = CMPCI_OUTPUT_CLASS; 898 strcpy(dip->label.name, AudioNmaster); 899 dip->un.v.num_channels = 2; 900 dip->un.v.delta = 1 << (8 - CMPCI_SB16_MIXER_VALBITS); 901 goto vol; 902 case CMPCI_REAR: 903 dip->mixer_class = CMPCI_OUTPUT_CLASS; 904 dip->next = CMPCI_INDIVIDUAL; 905 strcpy(dip->label.name, CmpciNrear); 906 goto on_off; 907 case CMPCI_INDIVIDUAL: 908 dip->mixer_class = CMPCI_OUTPUT_CLASS; 909 dip->prev = CMPCI_REAR; 910 dip->next = CMPCI_REVERSE; 911 strcpy(dip->label.name, CmpciNindividual); 912 goto on_off; 913 case CMPCI_REVERSE: 914 dip->mixer_class = CMPCI_OUTPUT_CLASS; 915 dip->prev = CMPCI_INDIVIDUAL; 916 strcpy(dip->label.name, CmpciNreverse); 917 goto on_off; 918 case CMPCI_SURROUND: 919 dip->mixer_class = CMPCI_OUTPUT_CLASS; 920 strcpy(dip->label.name, CmpciNsurround); 921 goto on_off; 922 } 923 924 return ENXIO; 925 } 926 927 static int 928 cmpci_alloc_dmamem(struct cmpci_softc *sc, size_t size, void **r_addr) 929 { 930 int error; 931 struct cmpci_dmanode *n; 932 933 error = 0; 934 n = kmem_alloc(sizeof(*n), KM_SLEEP); 935 936 #define CMPCI_DMABUF_ALIGN 0x4 937 #define CMPCI_DMABUF_BOUNDARY 0x0 938 n->cd_tag = sc->sc_dmat; 939 n->cd_size = size; 940 error = bus_dmamem_alloc(n->cd_tag, n->cd_size, 941 CMPCI_DMABUF_ALIGN, CMPCI_DMABUF_BOUNDARY, n->cd_segs, 942 sizeof(n->cd_segs)/sizeof(n->cd_segs[0]), &n->cd_nsegs, 943 BUS_DMA_WAITOK); 944 if (error) 945 goto mfree; 946 error = bus_dmamem_map(n->cd_tag, n->cd_segs, n->cd_nsegs, n->cd_size, 947 &n->cd_addr, BUS_DMA_WAITOK | BUS_DMA_COHERENT); 948 if (error) 949 goto dmafree; 950 error = bus_dmamap_create(n->cd_tag, n->cd_size, 1, n->cd_size, 0, 951 BUS_DMA_WAITOK, &n->cd_map); 952 if (error) 953 goto unmap; 954 error = bus_dmamap_load(n->cd_tag, n->cd_map, n->cd_addr, n->cd_size, 955 NULL, BUS_DMA_WAITOK); 956 if (error) 957 goto destroy; 958 959 n->cd_next = sc->sc_dmap; 960 sc->sc_dmap = n; 961 *r_addr = KVADDR(n); 962 return 0; 963 964 destroy: 965 bus_dmamap_destroy(n->cd_tag, n->cd_map); 966 unmap: 967 bus_dmamem_unmap(n->cd_tag, n->cd_addr, n->cd_size); 968 dmafree: 969 bus_dmamem_free(n->cd_tag, 970 n->cd_segs, sizeof(n->cd_segs)/sizeof(n->cd_segs[0])); 971 mfree: 972 kmem_free(n, sizeof(*n)); 973 return error; 974 } 975 976 static int 977 cmpci_free_dmamem(struct cmpci_softc *sc, void *addr, size_t size) 978 { 979 struct cmpci_dmanode **nnp; 980 981 for (nnp = &sc->sc_dmap; *nnp; nnp= &(*nnp)->cd_next) { 982 if ((*nnp)->cd_addr == addr) { 983 struct cmpci_dmanode *n = *nnp; 984 bus_dmamap_unload(n->cd_tag, n->cd_map); 985 bus_dmamap_destroy(n->cd_tag, n->cd_map); 986 bus_dmamem_unmap(n->cd_tag, n->cd_addr, n->cd_size); 987 bus_dmamem_free(n->cd_tag, n->cd_segs, 988 sizeof(n->cd_segs)/sizeof(n->cd_segs[0])); 989 kmem_free(n, sizeof(*n)); 990 return 0; 991 } 992 } 993 return -1; 994 } 995 996 static struct cmpci_dmanode * 997 cmpci_find_dmamem(struct cmpci_softc *sc, void *addr) 998 { 999 struct cmpci_dmanode *p; 1000 1001 for (p = sc->sc_dmap; p; p = p->cd_next) 1002 if (KVADDR(p) == (void *)addr) 1003 break; 1004 return p; 1005 } 1006 1007 #if 0 1008 static void 1009 cmpci_print_dmamem(struct cmpci_dmanode *); 1010 static void 1011 cmpci_print_dmamem(struct cmpci_dmanode *p) 1012 { 1013 1014 DPRINTF(("DMA at virt:%p, dmaseg:%p, mapseg:%p, size:%p\n", 1015 (void *)p->cd_addr, (void *)p->cd_segs[0].ds_addr, 1016 (void *)DMAADDR(p), (void *)p->cd_size)); 1017 } 1018 #endif /* DEBUG */ 1019 1020 static void * 1021 cmpci_allocm(void *handle, int direction, size_t size) 1022 { 1023 void *addr; 1024 1025 addr = NULL; /* XXX gcc */ 1026 1027 if (cmpci_alloc_dmamem(handle, size, &addr)) 1028 return NULL; 1029 return addr; 1030 } 1031 1032 static void 1033 cmpci_freem(void *handle, void *addr, size_t size) 1034 { 1035 1036 cmpci_free_dmamem(handle, addr, size); 1037 } 1038 1039 #define MAXVAL 256 1040 static int 1041 cmpci_adjust(int val, int mask) 1042 { 1043 1044 val += (MAXVAL - mask) >> 1; 1045 if (val >= MAXVAL) 1046 val = MAXVAL-1; 1047 return val & mask; 1048 } 1049 1050 static void 1051 cmpci_set_mixer_gain(struct cmpci_softc *sc, int port) 1052 { 1053 int src; 1054 int bits, mask; 1055 1056 switch (port) { 1057 case CMPCI_MIC_VOL: 1058 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_MIC, 1059 CMPCI_ADJUST_MIC_GAIN(sc, sc->sc_gain[port][CMPCI_LR])); 1060 return; 1061 case CMPCI_MASTER_VOL: 1062 src = CMPCI_SB16_MIXER_MASTER_L; 1063 break; 1064 case CMPCI_LINE_IN_VOL: 1065 src = CMPCI_SB16_MIXER_LINE_L; 1066 break; 1067 case CMPCI_AUX_IN_VOL: 1068 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_MIXER_AUX, 1069 CMPCI_ADJUST_AUX_GAIN(sc, sc->sc_gain[port][CMPCI_LEFT], 1070 sc->sc_gain[port][CMPCI_RIGHT])); 1071 return; 1072 case CMPCI_MIC_RECVOL: 1073 cmpci_reg_partial_write_1(sc, CMPCI_REG_MIXER25, 1074 CMPCI_REG_ADMIC_SHIFT, CMPCI_REG_ADMIC_MASK, 1075 CMPCI_ADJUST_ADMIC_GAIN(sc, sc->sc_gain[port][CMPCI_LR])); 1076 return; 1077 case CMPCI_DAC_VOL: 1078 src = CMPCI_SB16_MIXER_VOICE_L; 1079 break; 1080 case CMPCI_FM_VOL: 1081 src = CMPCI_SB16_MIXER_FM_L; 1082 break; 1083 case CMPCI_CD_VOL: 1084 src = CMPCI_SB16_MIXER_CDDA_L; 1085 break; 1086 case CMPCI_PCSPEAKER: 1087 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_SPEAKER, 1088 CMPCI_ADJUST_2_GAIN(sc, sc->sc_gain[port][CMPCI_LR])); 1089 return; 1090 case CMPCI_MIC_PREAMP: 1091 if (sc->sc_gain[port][CMPCI_LR]) 1092 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER25, 1093 CMPCI_REG_MICGAINZ); 1094 else 1095 cmpci_reg_set_1(sc, CMPCI_REG_MIXER25, 1096 CMPCI_REG_MICGAINZ); 1097 return; 1098 1099 case CMPCI_DAC_MUTE: 1100 if (sc->sc_gain[port][CMPCI_LR]) 1101 cmpci_reg_set_1(sc, CMPCI_REG_MIXER24, 1102 CMPCI_REG_WSMUTE); 1103 else 1104 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24, 1105 CMPCI_REG_WSMUTE); 1106 return; 1107 case CMPCI_FM_MUTE: 1108 if (sc->sc_gain[port][CMPCI_LR]) 1109 cmpci_reg_set_1(sc, CMPCI_REG_MIXER24, 1110 CMPCI_REG_FMMUTE); 1111 else 1112 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24, 1113 CMPCI_REG_FMMUTE); 1114 return; 1115 case CMPCI_AUX_IN_MUTE: 1116 if (sc->sc_gain[port][CMPCI_LR]) 1117 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER25, 1118 CMPCI_REG_VAUXRM|CMPCI_REG_VAUXLM); 1119 else 1120 cmpci_reg_set_1(sc, CMPCI_REG_MIXER25, 1121 CMPCI_REG_VAUXRM|CMPCI_REG_VAUXLM); 1122 return; 1123 case CMPCI_CD_MUTE: 1124 mask = CMPCI_SB16_SW_CD; 1125 goto sbmute; 1126 case CMPCI_MIC_MUTE: 1127 mask = CMPCI_SB16_SW_MIC; 1128 goto sbmute; 1129 case CMPCI_LINE_IN_MUTE: 1130 mask = CMPCI_SB16_SW_LINE; 1131 sbmute: 1132 bits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_OUTMIX); 1133 if (sc->sc_gain[port][CMPCI_LR]) 1134 bits = bits & ~mask; 1135 else 1136 bits = bits | mask; 1137 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_OUTMIX, bits); 1138 return; 1139 1140 case CMPCI_SPDIF_IN_SELECT: 1141 case CMPCI_MONITOR_DAC: 1142 case CMPCI_PLAYBACK_MODE: 1143 case CMPCI_SPDIF_LOOP: 1144 case CMPCI_SPDIF_OUT_PLAYBACK: 1145 cmpci_set_out_ports(sc); 1146 return; 1147 case CMPCI_SPDIF_OUT_VOLTAGE: 1148 if (CMPCI_ISCAP(sc, SPDOUT_VOLTAGE)) { 1149 if (sc->sc_gain[CMPCI_SPDIF_OUT_VOLTAGE][CMPCI_LR] 1150 == CMPCI_SPDIF_OUT_VOLTAGE_HIGH) 1151 cmpci_reg_clear_reg_misc(sc, CMPCI_REG_5V); 1152 else 1153 cmpci_reg_set_reg_misc(sc, CMPCI_REG_5V); 1154 } 1155 return; 1156 case CMPCI_SURROUND: 1157 if (CMPCI_ISCAP(sc, SURROUND)) { 1158 if (sc->sc_gain[CMPCI_SURROUND][CMPCI_LR]) 1159 cmpci_reg_set_1(sc, CMPCI_REG_MIXER24, 1160 CMPCI_REG_SURROUND); 1161 else 1162 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24, 1163 CMPCI_REG_SURROUND); 1164 } 1165 return; 1166 case CMPCI_REAR: 1167 if (CMPCI_ISCAP(sc, REAR)) { 1168 if (sc->sc_gain[CMPCI_REAR][CMPCI_LR]) 1169 cmpci_reg_set_reg_misc(sc, CMPCI_REG_N4SPK3D); 1170 else 1171 cmpci_reg_clear_reg_misc(sc, CMPCI_REG_N4SPK3D); 1172 } 1173 return; 1174 case CMPCI_INDIVIDUAL: 1175 if (CMPCI_ISCAP(sc, INDIVIDUAL_REAR)) { 1176 if (sc->sc_gain[CMPCI_REAR][CMPCI_LR]) 1177 cmpci_reg_set_1(sc, CMPCI_REG_MIXER24, 1178 CMPCI_REG_INDIVIDUAL); 1179 else 1180 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24, 1181 CMPCI_REG_INDIVIDUAL); 1182 } 1183 return; 1184 case CMPCI_REVERSE: 1185 if (CMPCI_ISCAP(sc, REVERSE_FR)) { 1186 if (sc->sc_gain[CMPCI_REVERSE][CMPCI_LR]) 1187 cmpci_reg_set_1(sc, CMPCI_REG_MIXER24, 1188 CMPCI_REG_REVERSE_FR); 1189 else 1190 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24, 1191 CMPCI_REG_REVERSE_FR); 1192 } 1193 return; 1194 case CMPCI_SPDIF_IN_PHASE: 1195 if (CMPCI_ISCAP(sc, SPDIN_PHASE)) { 1196 if (sc->sc_gain[CMPCI_SPDIF_IN_PHASE][CMPCI_LR] 1197 == CMPCI_SPDIF_IN_PHASE_POSITIVE) 1198 cmpci_reg_clear_1(sc, CMPCI_REG_CHANNEL_FORMAT, 1199 CMPCI_REG_SPDIN_PHASE); 1200 else 1201 cmpci_reg_set_1(sc, CMPCI_REG_CHANNEL_FORMAT, 1202 CMPCI_REG_SPDIN_PHASE); 1203 } 1204 return; 1205 default: 1206 return; 1207 } 1208 1209 cmpci_mixerreg_write(sc, src, 1210 CMPCI_ADJUST_GAIN(sc, sc->sc_gain[port][CMPCI_LEFT])); 1211 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_L_TO_R(src), 1212 CMPCI_ADJUST_GAIN(sc, sc->sc_gain[port][CMPCI_RIGHT])); 1213 } 1214 1215 static void 1216 cmpci_set_out_ports(struct cmpci_softc *sc) 1217 { 1218 uint8_t v; 1219 int enspdout; 1220 1221 if (!CMPCI_ISCAP(sc, SPDLOOP)) 1222 return; 1223 1224 /* SPDIF/out select */ 1225 if (sc->sc_gain[CMPCI_SPDIF_LOOP][CMPCI_LR] == CMPCI_SPDIF_LOOP_OFF) { 1226 /* playback */ 1227 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIF_LOOP); 1228 } else { 1229 /* monitor SPDIF/in */ 1230 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIF_LOOP); 1231 } 1232 1233 /* SPDIF in select */ 1234 v = sc->sc_gain[CMPCI_SPDIF_IN_SELECT][CMPCI_LR]; 1235 if (v & CMPCI_SPDIFIN_SPDIFIN2) 1236 cmpci_reg_set_reg_misc(sc, CMPCI_REG_2ND_SPDIFIN); 1237 else 1238 cmpci_reg_clear_reg_misc(sc, CMPCI_REG_2ND_SPDIFIN); 1239 if (v & CMPCI_SPDIFIN_SPDIFOUT) 1240 cmpci_reg_set_reg_misc(sc, CMPCI_REG_SPDFLOOPI); 1241 else 1242 cmpci_reg_clear_reg_misc(sc, CMPCI_REG_SPDFLOOPI); 1243 1244 enspdout = 0; 1245 /* playback to ... */ 1246 if (CMPCI_ISCAP(sc, SPDOUT) && 1247 sc->sc_gain[CMPCI_PLAYBACK_MODE][CMPCI_LR] 1248 == CMPCI_PLAYBACK_MODE_SPDIF && 1249 (sc->sc_play.md_divide == CMPCI_REG_RATE_44100 || 1250 (CMPCI_ISCAP(sc, SPDOUT_48K) && 1251 sc->sc_play.md_divide==CMPCI_REG_RATE_48000))) { 1252 /* playback to SPDIF */ 1253 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIF0_ENABLE); 1254 enspdout = 1; 1255 if (sc->sc_play.md_divide==CMPCI_REG_RATE_48000) 1256 cmpci_reg_set_reg_misc(sc, 1257 CMPCI_REG_SPDIFOUT_48K | CMPCI_REG_SPDIF48K); 1258 else 1259 cmpci_reg_clear_reg_misc(sc, 1260 CMPCI_REG_SPDIFOUT_48K | CMPCI_REG_SPDIF48K); 1261 } else { 1262 /* playback to DAC */ 1263 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1, 1264 CMPCI_REG_SPDIF0_ENABLE); 1265 if (CMPCI_ISCAP(sc, SPDOUT_48K)) 1266 cmpci_reg_clear_reg_misc(sc, 1267 CMPCI_REG_SPDIFOUT_48K | CMPCI_REG_SPDIF48K); 1268 } 1269 1270 /* legacy to SPDIF/out or not */ 1271 if (CMPCI_ISCAP(sc, SPDLEGACY)) { 1272 if (sc->sc_gain[CMPCI_SPDIF_OUT_PLAYBACK][CMPCI_LR] 1273 == CMPCI_SPDIF_OUT_PLAYBACK_WAVE) 1274 cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL, 1275 CMPCI_REG_LEGACY_SPDIF_ENABLE); 1276 else { 1277 cmpci_reg_set_4(sc, CMPCI_REG_LEGACY_CTRL, 1278 CMPCI_REG_LEGACY_SPDIF_ENABLE); 1279 enspdout = 1; 1280 } 1281 } 1282 1283 /* enable/disable SPDIF/out */ 1284 if (CMPCI_ISCAP(sc, XSPDOUT) && enspdout) 1285 cmpci_reg_set_4(sc, CMPCI_REG_LEGACY_CTRL, 1286 CMPCI_REG_XSPDIF_ENABLE); 1287 else 1288 cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL, 1289 CMPCI_REG_XSPDIF_ENABLE); 1290 1291 /* SPDIF monitor (digital to analog output) */ 1292 if (CMPCI_ISCAP(sc, SPDIN_MONITOR)) { 1293 v = sc->sc_gain[CMPCI_MONITOR_DAC][CMPCI_LR]; 1294 if (!(v & CMPCI_MONDAC_ENABLE)) 1295 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24, 1296 CMPCI_REG_SPDIN_MONITOR); 1297 if (v & CMPCI_MONDAC_SPDOUT) 1298 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1, 1299 CMPCI_REG_SPDIFOUT_DAC); 1300 else 1301 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1, 1302 CMPCI_REG_SPDIFOUT_DAC); 1303 if (v & CMPCI_MONDAC_ENABLE) 1304 cmpci_reg_set_1(sc, CMPCI_REG_MIXER24, 1305 CMPCI_REG_SPDIN_MONITOR); 1306 } 1307 } 1308 1309 static int 1310 cmpci_set_in_ports(struct cmpci_softc *sc) 1311 { 1312 int mask; 1313 int bitsl, bitsr; 1314 1315 mask = sc->sc_in_mask; 1316 1317 /* 1318 * Note CMPCI_RECORD_SOURCE_CD, CMPCI_RECORD_SOURCE_LINE_IN and 1319 * CMPCI_RECORD_SOURCE_FM are defined to the corresponding bit 1320 * of the mixer register. 1321 */ 1322 bitsr = mask & (CMPCI_RECORD_SOURCE_CD | CMPCI_RECORD_SOURCE_LINE_IN | 1323 CMPCI_RECORD_SOURCE_FM); 1324 1325 bitsl = CMPCI_SB16_MIXER_SRC_R_TO_L(bitsr); 1326 if (mask & CMPCI_RECORD_SOURCE_MIC) { 1327 bitsl |= CMPCI_SB16_MIXER_MIC_SRC; 1328 bitsr |= CMPCI_SB16_MIXER_MIC_SRC; 1329 } 1330 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, bitsl); 1331 cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, bitsr); 1332 1333 if (mask & CMPCI_RECORD_SOURCE_AUX_IN) 1334 cmpci_reg_set_1(sc, CMPCI_REG_MIXER25, 1335 CMPCI_REG_RAUXREN | CMPCI_REG_RAUXLEN); 1336 else 1337 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER25, 1338 CMPCI_REG_RAUXREN | CMPCI_REG_RAUXLEN); 1339 1340 if (mask & CMPCI_RECORD_SOURCE_WAVE) 1341 cmpci_reg_set_1(sc, CMPCI_REG_MIXER24, 1342 CMPCI_REG_WAVEINL | CMPCI_REG_WAVEINR); 1343 else 1344 cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24, 1345 CMPCI_REG_WAVEINL | CMPCI_REG_WAVEINR); 1346 1347 if (CMPCI_ISCAP(sc, SPDIN) && 1348 (sc->sc_rec.md_divide == CMPCI_REG_RATE_44100 || 1349 (CMPCI_ISCAP(sc, SPDOUT_48K) && 1350 sc->sc_rec.md_divide == CMPCI_REG_RATE_48000/* XXX? */))) { 1351 if (mask & CMPCI_RECORD_SOURCE_SPDIF) { 1352 /* enable SPDIF/in */ 1353 cmpci_reg_set_4(sc, 1354 CMPCI_REG_FUNC_1, 1355 CMPCI_REG_SPDIF1_ENABLE); 1356 } else { 1357 cmpci_reg_clear_4(sc, 1358 CMPCI_REG_FUNC_1, 1359 CMPCI_REG_SPDIF1_ENABLE); 1360 } 1361 } 1362 1363 return 0; 1364 } 1365 1366 static int 1367 cmpci_set_port(void *handle, mixer_ctrl_t *cp) 1368 { 1369 struct cmpci_softc *sc; 1370 int lgain, rgain; 1371 1372 sc = handle; 1373 switch (cp->dev) { 1374 case CMPCI_MIC_VOL: 1375 case CMPCI_PCSPEAKER: 1376 case CMPCI_MIC_RECVOL: 1377 if (cp->un.value.num_channels != 1) 1378 return EINVAL; 1379 /* FALLTHROUGH */ 1380 case CMPCI_DAC_VOL: 1381 case CMPCI_FM_VOL: 1382 case CMPCI_CD_VOL: 1383 case CMPCI_LINE_IN_VOL: 1384 case CMPCI_AUX_IN_VOL: 1385 case CMPCI_MASTER_VOL: 1386 if (cp->type != AUDIO_MIXER_VALUE) 1387 return EINVAL; 1388 switch (cp->un.value.num_channels) { 1389 case 1: 1390 lgain = rgain = 1391 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 1392 break; 1393 case 2: 1394 lgain = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 1395 rgain = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 1396 break; 1397 default: 1398 return EINVAL; 1399 } 1400 sc->sc_gain[cp->dev][CMPCI_LEFT] = lgain; 1401 sc->sc_gain[cp->dev][CMPCI_RIGHT] = rgain; 1402 1403 cmpci_set_mixer_gain(sc, cp->dev); 1404 break; 1405 1406 case CMPCI_RECORD_SOURCE: 1407 if (cp->type != AUDIO_MIXER_SET) 1408 return EINVAL; 1409 1410 if (cp->un.mask & ~(CMPCI_RECORD_SOURCE_MIC | 1411 CMPCI_RECORD_SOURCE_CD | CMPCI_RECORD_SOURCE_LINE_IN | 1412 CMPCI_RECORD_SOURCE_AUX_IN | CMPCI_RECORD_SOURCE_WAVE | 1413 CMPCI_RECORD_SOURCE_FM | CMPCI_RECORD_SOURCE_SPDIF)) 1414 return EINVAL; 1415 1416 if (cp->un.mask & CMPCI_RECORD_SOURCE_SPDIF) 1417 cp->un.mask = CMPCI_RECORD_SOURCE_SPDIF; 1418 1419 sc->sc_in_mask = cp->un.mask; 1420 return cmpci_set_in_ports(sc); 1421 1422 /* boolean */ 1423 case CMPCI_DAC_MUTE: 1424 case CMPCI_FM_MUTE: 1425 case CMPCI_CD_MUTE: 1426 case CMPCI_LINE_IN_MUTE: 1427 case CMPCI_AUX_IN_MUTE: 1428 case CMPCI_MIC_MUTE: 1429 case CMPCI_MIC_PREAMP: 1430 case CMPCI_PLAYBACK_MODE: 1431 case CMPCI_SPDIF_IN_PHASE: 1432 case CMPCI_SPDIF_LOOP: 1433 case CMPCI_SPDIF_OUT_PLAYBACK: 1434 case CMPCI_SPDIF_OUT_VOLTAGE: 1435 case CMPCI_REAR: 1436 case CMPCI_INDIVIDUAL: 1437 case CMPCI_REVERSE: 1438 case CMPCI_SURROUND: 1439 if (cp->type != AUDIO_MIXER_ENUM) 1440 return EINVAL; 1441 sc->sc_gain[cp->dev][CMPCI_LR] = cp->un.ord != 0; 1442 cmpci_set_mixer_gain(sc, cp->dev); 1443 break; 1444 1445 case CMPCI_SPDIF_IN_SELECT: 1446 switch (cp->un.ord) { 1447 case CMPCI_SPDIF_IN_SPDIN1: 1448 case CMPCI_SPDIF_IN_SPDIN2: 1449 case CMPCI_SPDIF_IN_SPDOUT: 1450 break; 1451 default: 1452 return EINVAL; 1453 } 1454 goto xenum; 1455 case CMPCI_MONITOR_DAC: 1456 switch (cp->un.ord) { 1457 case CMPCI_MONITOR_DAC_OFF: 1458 case CMPCI_MONITOR_DAC_SPDIN: 1459 case CMPCI_MONITOR_DAC_SPDOUT: 1460 break; 1461 default: 1462 return EINVAL; 1463 } 1464 xenum: 1465 if (cp->type != AUDIO_MIXER_ENUM) 1466 return EINVAL; 1467 sc->sc_gain[cp->dev][CMPCI_LR] = cp->un.ord; 1468 cmpci_set_mixer_gain(sc, cp->dev); 1469 break; 1470 1471 default: 1472 return EINVAL; 1473 } 1474 1475 return 0; 1476 } 1477 1478 static int 1479 cmpci_get_port(void *handle, mixer_ctrl_t *cp) 1480 { 1481 struct cmpci_softc *sc; 1482 1483 sc = handle; 1484 switch (cp->dev) { 1485 case CMPCI_MIC_VOL: 1486 case CMPCI_PCSPEAKER: 1487 case CMPCI_MIC_RECVOL: 1488 if (cp->un.value.num_channels != 1) 1489 return EINVAL; 1490 /*FALLTHROUGH*/ 1491 case CMPCI_DAC_VOL: 1492 case CMPCI_FM_VOL: 1493 case CMPCI_CD_VOL: 1494 case CMPCI_LINE_IN_VOL: 1495 case CMPCI_AUX_IN_VOL: 1496 case CMPCI_MASTER_VOL: 1497 switch (cp->un.value.num_channels) { 1498 case 1: 1499 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = 1500 sc->sc_gain[cp->dev][CMPCI_LEFT]; 1501 break; 1502 case 2: 1503 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 1504 sc->sc_gain[cp->dev][CMPCI_LEFT]; 1505 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 1506 sc->sc_gain[cp->dev][CMPCI_RIGHT]; 1507 break; 1508 default: 1509 return EINVAL; 1510 } 1511 break; 1512 1513 case CMPCI_RECORD_SOURCE: 1514 cp->un.mask = sc->sc_in_mask; 1515 break; 1516 1517 case CMPCI_DAC_MUTE: 1518 case CMPCI_FM_MUTE: 1519 case CMPCI_CD_MUTE: 1520 case CMPCI_LINE_IN_MUTE: 1521 case CMPCI_AUX_IN_MUTE: 1522 case CMPCI_MIC_MUTE: 1523 case CMPCI_MIC_PREAMP: 1524 case CMPCI_PLAYBACK_MODE: 1525 case CMPCI_SPDIF_IN_SELECT: 1526 case CMPCI_SPDIF_IN_PHASE: 1527 case CMPCI_SPDIF_LOOP: 1528 case CMPCI_SPDIF_OUT_PLAYBACK: 1529 case CMPCI_SPDIF_OUT_VOLTAGE: 1530 case CMPCI_MONITOR_DAC: 1531 case CMPCI_REAR: 1532 case CMPCI_INDIVIDUAL: 1533 case CMPCI_REVERSE: 1534 case CMPCI_SURROUND: 1535 cp->un.ord = sc->sc_gain[cp->dev][CMPCI_LR]; 1536 break; 1537 1538 default: 1539 return EINVAL; 1540 } 1541 1542 return 0; 1543 } 1544 1545 /* ARGSUSED */ 1546 static size_t 1547 cmpci_round_buffersize(void *handle, int direction, 1548 size_t bufsize) 1549 { 1550 1551 if (bufsize > 0x10000) 1552 bufsize = 0x10000; 1553 1554 return bufsize; 1555 } 1556 1557 /* ARGSUSED */ 1558 static int 1559 cmpci_get_props(void *handle) 1560 { 1561 1562 return AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE | 1563 AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX; 1564 } 1565 1566 static int 1567 cmpci_trigger_output(void *handle, void *start, void *end, int blksize, 1568 void (*intr)(void *), void *arg, 1569 const audio_params_t *param) 1570 { 1571 struct cmpci_softc *sc; 1572 struct cmpci_dmanode *p; 1573 int bps; 1574 1575 sc = handle; 1576 sc->sc_play.intr = intr; 1577 sc->sc_play.intr_arg = arg; 1578 bps = param->channels * param->precision / 8; 1579 if (!bps) 1580 return EINVAL; 1581 1582 /* set DMA frame */ 1583 if (!(p = cmpci_find_dmamem(sc, start))) 1584 return EINVAL; 1585 bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_BASE, 1586 DMAADDR(p)); 1587 delay(10); 1588 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_BYTES, 1589 ((char *)end - (char *)start + 1) / bps - 1); 1590 delay(10); 1591 1592 /* set interrupt count */ 1593 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_SAMPLES, 1594 (blksize + bps - 1) / bps - 1); 1595 delay(10); 1596 1597 /* start DMA */ 1598 cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_DIR); /* PLAY */ 1599 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE); 1600 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE); 1601 1602 return 0; 1603 } 1604 1605 static int 1606 cmpci_trigger_input(void *handle, void *start, void *end, int blksize, 1607 void (*intr)(void *), void *arg, 1608 const audio_params_t *param) 1609 { 1610 struct cmpci_softc *sc; 1611 struct cmpci_dmanode *p; 1612 int bps; 1613 1614 sc = handle; 1615 sc->sc_rec.intr = intr; 1616 sc->sc_rec.intr_arg = arg; 1617 bps = param->channels * param->precision / 8; 1618 if (!bps) 1619 return EINVAL; 1620 1621 /* set DMA frame */ 1622 if (!(p=cmpci_find_dmamem(sc, start))) 1623 return EINVAL; 1624 bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_BASE, 1625 DMAADDR(p)); 1626 delay(10); 1627 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_BYTES, 1628 ((char *)end - (char *)start + 1) / bps - 1); 1629 delay(10); 1630 1631 /* set interrupt count */ 1632 bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_SAMPLES, 1633 (blksize + bps - 1) / bps - 1); 1634 delay(10); 1635 1636 /* start DMA */ 1637 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_DIR); /* REC */ 1638 cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE); 1639 cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE); 1640 1641 return 0; 1642 } 1643 1644 static void 1645 cmpci_get_locks(void *addr, kmutex_t **intr, kmutex_t **thread) 1646 { 1647 struct cmpci_softc *sc; 1648 1649 sc = addr; 1650 *intr = &sc->sc_intr_lock; 1651 *thread = &sc->sc_lock; 1652 } 1653 1654 /* end of file */ 1655