1 /* $OpenBSD: cs4281.c,v 1.37 2019/12/28 07:55:48 fcambus Exp $ */ 2 /* $Tera: cs4281.c,v 1.18 2000/12/27 14:24:45 tacha Exp $ */ 3 4 /* 5 * Copyright (c) 2000 Tatoku Ogaito. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Tatoku Ogaito 18 * for the NetBSD Project. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * Cirrus Logic CS4281 driver. 36 * Data sheets can be found 37 * http://www.cirrus.com/pubs/4281.pdf?DocumentID=30 38 * ftp://ftp.alsa-project.org/pub/manuals/cirrus/cs4281tm.pdf 39 * 40 * TODO: 41 * 1: midi and FM support 42 */ 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/kernel.h> 47 #include <sys/malloc.h> 48 #include <sys/fcntl.h> 49 #include <sys/device.h> 50 51 #include <dev/pci/pcidevs.h> 52 #include <dev/pci/pcivar.h> 53 #include <dev/pci/cs4281reg.h> 54 55 #include <sys/audioio.h> 56 #include <dev/audio_if.h> 57 #include <dev/midi_if.h> 58 59 #include <dev/ic/ac97.h> 60 61 #include <machine/bus.h> 62 63 #define CSCC_PCI_BA0 0x10 64 #define CSCC_PCI_BA1 0x14 65 66 struct cs4281_dma { 67 bus_dmamap_t map; 68 caddr_t addr; /* real dma buffer */ 69 bus_dma_segment_t segs[1]; 70 int nsegs; 71 size_t size; 72 struct cs4281_dma *next; 73 }; 74 #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr) 75 #define KERNADDR(p) ((void *)((p)->addr)) 76 77 /* 78 * Software state 79 */ 80 struct cs4281_softc { 81 struct device sc_dev; 82 83 pci_intr_handle_t *sc_ih; 84 85 /* I/O (BA0) */ 86 bus_space_tag_t ba0t; 87 bus_space_handle_t ba0h; 88 89 /* BA1 */ 90 bus_space_tag_t ba1t; 91 bus_space_handle_t ba1h; 92 93 /* DMA */ 94 bus_dma_tag_t sc_dmatag; 95 struct cs4281_dma *sc_dmas; 96 97 /* playback */ 98 void (*sc_pintr)(void *); /* dma completion intr handler */ 99 void *sc_parg; /* arg for sc_intr() */ 100 int (*halt_output)(void *); 101 #ifdef DIAGNOSTIC 102 char sc_prun; 103 #endif 104 105 /* capturing */ 106 void (*sc_rintr)(void *); /* dma completion intr handler */ 107 void *sc_rarg; /* arg for sc_intr() */ 108 int sc_rparam; /* record format */ 109 int (*halt_input)(void *); 110 #ifdef DIAGNOSTIC 111 char sc_rrun; 112 #endif 113 114 #if NMIDI > 0 115 void (*sc_iintr)(void *, int); /* midi input ready handler */ 116 void (*sc_ointr)(void *); /* midi output ready handler */ 117 void *sc_arg; 118 #endif 119 120 /* AC97 CODEC */ 121 struct ac97_codec_if *codec_if; 122 struct ac97_host_if host_if; 123 124 /* Power Management */ 125 u_int16_t ac97_reg[CS4281_SAVE_REG_MAX + 1]; /* Save ac97 registers */ 126 }; 127 128 #define BA0READ4(sc, r) bus_space_read_4((sc)->ba0t, (sc)->ba0h, (r)) 129 #define BA0WRITE4(sc, r, x) bus_space_write_4((sc)->ba0t, (sc)->ba0h, (r), (x)) 130 131 #if defined(ENABLE_SECONDARY_CODEC) 132 #define MAX_CHANNELS (4) 133 #define MAX_FIFO_SIZE 32 /* 128/4 channels */ 134 #else 135 #define MAX_CHANNELS (2) 136 #define MAX_FIFO_SIZE 64 /* 128/2 channels */ 137 #endif 138 139 /* 140 * Hardware imposes the buffer size to be twice the block size, this 141 * is OK, except that round_blocksize() is the only mean to expose 142 * this hardware constraint but it doesn't know the buffer size. 143 * 144 * So we've no other choice than hardcoding a buffer size 145 */ 146 #define DMA_SIZE (1024 * 4 * 2) 147 #define DMA_ALIGN 0x10 148 149 int cs4281_match(struct device *, void *, void *); 150 void cs4281_attach(struct device *, struct device *, void *); 151 int cs4281_activate(struct device *, int); 152 int cs4281_intr(void *); 153 int cs4281_set_params(void *, int, int, struct audio_params *, 154 struct audio_params *); 155 int cs4281_halt_output(void *); 156 int cs4281_halt_input(void *); 157 int cs4281_trigger_output(void *, void *, void *, int, void (*)(void *), 158 void *, struct audio_params *); 159 int cs4281_trigger_input(void *, void *, void *, int, void (*)(void *), 160 void *, struct audio_params *); 161 u_int8_t cs4281_sr2regval(int); 162 void cs4281_set_dac_rate(struct cs4281_softc *, int); 163 void cs4281_set_adc_rate(struct cs4281_softc *, int); 164 int cs4281_init(struct cs4281_softc *); 165 166 int cs4281_open(void *, int); 167 void cs4281_close(void *); 168 int cs4281_round_blocksize(void *, int); 169 int cs4281_get_props(void *); 170 int cs4281_attach_codec(void *, struct ac97_codec_if *); 171 int cs4281_read_codec(void *, u_int8_t , u_int16_t *); 172 int cs4281_write_codec(void *, u_int8_t, u_int16_t); 173 void cs4281_reset_codec(void *); 174 175 int cs4281_mixer_set_port(void *, mixer_ctrl_t *); 176 int cs4281_mixer_get_port(void *, mixer_ctrl_t *); 177 int cs4281_query_devinfo(void *, mixer_devinfo_t *); 178 void *cs4281_malloc(void *, int, size_t, int, int); 179 size_t cs4281_round_buffersize(void *, int, size_t); 180 void cs4281_free(void *, void *, int); 181 182 int cs4281_allocmem(struct cs4281_softc *, size_t, int, int, 183 struct cs4281_dma *); 184 int cs4281_src_wait(struct cs4281_softc *); 185 186 #if defined(CS4281_DEBUG) 187 #undef DPRINTF 188 #undef DPRINTFN 189 #define DPRINTF(x) if (cs4281_debug) printf x 190 #define DPRINTFN(n,x) if (cs4281_debug>(n)) printf x 191 int cs4281_debug = 5; 192 #else 193 #define DPRINTF(x) 194 #define DPRINTFN(n,x) 195 #endif 196 197 struct audio_hw_if cs4281_hw_if = { 198 cs4281_open, 199 cs4281_close, 200 cs4281_set_params, 201 cs4281_round_blocksize, 202 NULL, 203 NULL, 204 NULL, 205 NULL, 206 NULL, 207 cs4281_halt_output, 208 cs4281_halt_input, 209 NULL, 210 NULL, 211 cs4281_mixer_set_port, 212 cs4281_mixer_get_port, 213 cs4281_query_devinfo, 214 cs4281_malloc, 215 cs4281_free, 216 cs4281_round_buffersize, 217 cs4281_get_props, 218 cs4281_trigger_output, 219 cs4281_trigger_input 220 }; 221 222 #if NMIDI > 0 223 /* Midi Interface */ 224 void cs4281_midi_close(void *); 225 void cs4281_midi_getinfo(void *, struct midi_info *); 226 int cs4281_midi_open(void *, int, void (*)(void *, int), 227 void (*)(void *), void *); 228 int cs4281_midi_output(void *, int); 229 230 struct midi_hw_if cs4281_midi_hw_if = { 231 cs4281_midi_open, 232 cs4281_midi_close, 233 cs4281_midi_output, 234 cs4281_midi_getinfo, 235 0, 236 }; 237 #endif 238 239 struct cfattach clct_ca = { 240 sizeof(struct cs4281_softc), cs4281_match, cs4281_attach, NULL, 241 cs4281_activate 242 }; 243 244 struct cfdriver clct_cd = { 245 NULL, "clct", DV_DULL 246 }; 247 248 int 249 cs4281_match(parent, match, aux) 250 struct device *parent; 251 void *match; 252 void *aux; 253 { 254 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 255 256 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CIRRUS || 257 PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_CIRRUS_CS4281) 258 return (0); 259 260 return (1); 261 } 262 263 void 264 cs4281_attach(parent, self, aux) 265 struct device *parent; 266 struct device *self; 267 void *aux; 268 { 269 struct cs4281_softc *sc = (struct cs4281_softc *)self; 270 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 271 pci_chipset_tag_t pc = pa->pa_pc; 272 char const *intrstr; 273 pci_intr_handle_t ih; 274 275 /* Map I/O register */ 276 if (pci_mapreg_map(pa, CSCC_PCI_BA0, 277 PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->ba0t, 278 &sc->ba0h, NULL, NULL, 0)) { 279 printf("%s: can't map BA0 space\n", sc->sc_dev.dv_xname); 280 return; 281 } 282 if (pci_mapreg_map(pa, CSCC_PCI_BA1, 283 PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->ba1t, 284 &sc->ba1h, NULL, NULL, 0)) { 285 printf("%s: can't map BA1 space\n", sc->sc_dev.dv_xname); 286 return; 287 } 288 289 sc->sc_dmatag = pa->pa_dmat; 290 291 /* 292 * Set Power State D0. 293 * Without doing this, 0xffffffff is read from all registers after 294 * using Windows and rebooting into OpenBSD. 295 * On my IBM ThinkPad X20, it is set to D3 after using Windows2000. 296 */ 297 pci_set_powerstate(pc, pa->pa_tag, PCI_PMCSR_STATE_D0); 298 299 /* Map and establish the interrupt. */ 300 if (pci_intr_map(pa, &ih)) { 301 printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname); 302 return; 303 } 304 intrstr = pci_intr_string(pc, ih); 305 306 sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO | IPL_MPSAFE, 307 cs4281_intr, sc, sc->sc_dev.dv_xname); 308 if (sc->sc_ih == NULL) { 309 printf("%s: couldn't establish interrupt",sc->sc_dev.dv_xname); 310 if (intrstr != NULL) 311 printf(" at %s", intrstr); 312 printf("\n"); 313 return; 314 } 315 printf(": %s\n", intrstr); 316 317 /* 318 * Sound System start-up 319 */ 320 if (cs4281_init(sc) != 0) 321 return; 322 323 sc->halt_input = cs4281_halt_input; 324 sc->halt_output = cs4281_halt_output; 325 326 /* AC 97 attachment */ 327 sc->host_if.arg = sc; 328 sc->host_if.attach = cs4281_attach_codec; 329 sc->host_if.read = cs4281_read_codec; 330 sc->host_if.write = cs4281_write_codec; 331 sc->host_if.reset = cs4281_reset_codec; 332 if (ac97_attach(&sc->host_if) != 0) { 333 printf("%s: ac97_attach failed\n", sc->sc_dev.dv_xname); 334 return; 335 } 336 audio_attach_mi(&cs4281_hw_if, sc, &sc->sc_dev); 337 338 #if NMIDI > 0 339 midi_attach_mi(&cs4281_midi_hw_if, sc, &sc->sc_dev); 340 #endif 341 } 342 343 344 int 345 cs4281_intr(p) 346 void *p; 347 { 348 struct cs4281_softc *sc = p; 349 u_int32_t intr, val; 350 351 mtx_enter(&audio_lock); 352 intr = BA0READ4(sc, CS4281_HISR); 353 if (!(intr & (HISR_DMA0 | HISR_DMA1 | HISR_MIDI))) { 354 BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM); 355 mtx_leave(&audio_lock); 356 return (-1); 357 } 358 DPRINTF(("cs4281_intr:")); 359 360 if (intr & HISR_DMA0) 361 val = BA0READ4(sc, CS4281_HDSR0); /* clear intr condition */ 362 if (intr & HISR_DMA1) 363 val = BA0READ4(sc, CS4281_HDSR1); /* clear intr condition */ 364 BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM); 365 366 /* Playback Interrupt */ 367 if (intr & HISR_DMA0) { 368 DPRINTF((" PB DMA 0x%x(%d)", (int)BA0READ4(sc, CS4281_DCA0), 369 (int)BA0READ4(sc, CS4281_DCC0))); 370 if (sc->sc_pintr) { 371 sc->sc_pintr(sc->sc_parg); 372 } else { 373 #ifdef DIAGNOSTIC 374 printf("%s: unexpected play intr\n", 375 sc->sc_dev.dv_xname); 376 #endif 377 } 378 } 379 if (intr & HISR_DMA1) { 380 val = BA0READ4(sc, CS4281_HDSR1); 381 /* copy from dma */ 382 DPRINTF((" CP DMA 0x%x(%d)", (int)BA0READ4(sc, CS4281_DCA1), 383 (int)BA0READ4(sc, CS4281_DCC1))); 384 if (sc->sc_rintr) { 385 sc->sc_rintr(sc->sc_rarg); 386 } else { 387 #ifdef DIAGNOSTIC 388 printf("%s: unexpected record intr\n", 389 sc->sc_dev.dv_xname); 390 #endif 391 } 392 } 393 DPRINTF(("\n")); 394 mtx_leave(&audio_lock); 395 return (1); 396 } 397 398 int 399 cs4281_set_params(addr, setmode, usemode, play, rec) 400 void *addr; 401 int setmode, usemode; 402 struct audio_params *play, *rec; 403 { 404 struct cs4281_softc *sc = addr; 405 struct audio_params *p; 406 int mode; 407 408 for (mode = AUMODE_RECORD; mode != -1; 409 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) { 410 if ((setmode & mode) == 0) 411 continue; 412 413 p = mode == AUMODE_PLAY ? play : rec; 414 415 if (p == play) { 416 DPRINTFN(5,("play: samp=%ld precision=%d channels=%d\n", 417 p->sample_rate, p->precision, p->channels)); 418 } else { 419 DPRINTFN(5,("rec: samp=%ld precision=%d channels=%d\n", 420 p->sample_rate, p->precision, p->channels)); 421 } 422 if (p->sample_rate < 6023) 423 p->sample_rate = 6023; 424 if (p->sample_rate > 48000) 425 p->sample_rate = 48000; 426 if (p->precision > 16) 427 p->precision = 16; 428 if (p->channels > 2) 429 p->channels = 2; 430 431 switch (p->encoding) { 432 case AUDIO_ENCODING_SLINEAR_BE: 433 break; 434 case AUDIO_ENCODING_SLINEAR_LE: 435 break; 436 case AUDIO_ENCODING_ULINEAR_BE: 437 break; 438 case AUDIO_ENCODING_ULINEAR_LE: 439 break; 440 default: 441 return (EINVAL); 442 } 443 p->bps = AUDIO_BPS(p->precision); 444 p->msb = 1; 445 } 446 447 /* set sample rate */ 448 cs4281_set_dac_rate(sc, play->sample_rate); 449 cs4281_set_adc_rate(sc, rec->sample_rate); 450 return (0); 451 } 452 453 int 454 cs4281_halt_output(addr) 455 void *addr; 456 { 457 struct cs4281_softc *sc = addr; 458 459 BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) | DCRn_MSK); 460 #ifdef DIAGNOSTIC 461 sc->sc_prun = 0; 462 #endif 463 return (0); 464 } 465 466 int 467 cs4281_halt_input(addr) 468 void *addr; 469 { 470 struct cs4281_softc *sc = addr; 471 472 BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) | DCRn_MSK); 473 #ifdef DIAGNOSTIC 474 sc->sc_rrun = 0; 475 #endif 476 return (0); 477 } 478 479 int 480 cs4281_trigger_output(addr, start, end, blksize, intr, arg, param) 481 void *addr; 482 void *start, *end; 483 int blksize; 484 void (*intr)(void *); 485 void *arg; 486 struct audio_params *param; 487 { 488 struct cs4281_softc *sc = addr; 489 u_int32_t fmt = 0; 490 struct cs4281_dma *p; 491 int dma_count; 492 493 #ifdef DIAGNOSTIC 494 if (sc->sc_prun) 495 printf("cs4281_trigger_output: already running\n"); 496 sc->sc_prun = 1; 497 #endif 498 499 if ((char *)end - (char *)start != 2 * blksize) { 500 #ifdef DIAGNOSTIC 501 printf("%s: play block size must be half the buffer size\n", 502 sc->sc_dev.dv_xname); 503 #endif 504 return EIO; 505 } 506 507 DPRINTF(("cs4281_trigger_output: sc=%p start=%p end=%p " 508 "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg)); 509 sc->sc_pintr = intr; 510 sc->sc_parg = arg; 511 512 /* stop playback DMA */ 513 BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) | DCRn_MSK); 514 515 DPRINTF(("param: precision=%d channels=%d encoding=%d\n", 516 param->precision, param->channels, 517 param->encoding)); 518 for (p = sc->sc_dmas; p != NULL && KERNADDR(p) != start; p = p->next) 519 ; 520 if (p == NULL) { 521 printf("cs4281_trigger_output: bad addr %p\n", start); 522 mtx_leave(&audio_lock); 523 return (EINVAL); 524 } 525 526 dma_count = (char *)end - (char *)start; 527 if (param->precision != 8) 528 dma_count /= 2; /* 16 bit */ 529 if (param->channels > 1) 530 dma_count /= 2; /* Stereo */ 531 532 DPRINTF(("cs4281_trigger_output: DMAADDR(p)=0x%x count=%d\n", 533 (int)DMAADDR(p), dma_count)); 534 BA0WRITE4(sc, CS4281_DBA0, DMAADDR(p)); 535 BA0WRITE4(sc, CS4281_DBC0, dma_count - 1); 536 537 /* set playback format */ 538 fmt = BA0READ4(sc, CS4281_DMR0) & ~DMRn_FMTMSK; 539 if (param->precision == 8) 540 fmt |= DMRn_SIZE8; 541 if (param->channels == 1) 542 fmt |= DMRn_MONO; 543 if (param->encoding == AUDIO_ENCODING_ULINEAR_BE || 544 param->encoding == AUDIO_ENCODING_SLINEAR_BE) 545 fmt |= DMRn_BEND; 546 if (param->encoding == AUDIO_ENCODING_ULINEAR_BE || 547 param->encoding == AUDIO_ENCODING_ULINEAR_LE) 548 fmt |= DMRn_USIGN; 549 BA0WRITE4(sc, CS4281_DMR0, fmt); 550 551 /* set sample rate */ 552 cs4281_set_dac_rate(sc, param->sample_rate); 553 554 /* start DMA */ 555 mtx_enter(&audio_lock); 556 BA0WRITE4(sc, CS4281_DCR0, BA0READ4(sc, CS4281_DCR0) & ~DCRn_MSK); 557 /* Enable interrupts */ 558 BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM); 559 560 BA0WRITE4(sc, CS4281_PPRVC, 7); 561 BA0WRITE4(sc, CS4281_PPLVC, 7); 562 563 DPRINTF(("HICR =0x%08x(expected 0x00000001)\n", BA0READ4(sc, CS4281_HICR))); 564 DPRINTF(("HIMR =0x%08x(expected 0x00f0fc3f)\n", BA0READ4(sc, CS4281_HIMR))); 565 DPRINTF(("DMR0 =0x%08x(expected 0x2???0018)\n", BA0READ4(sc, CS4281_DMR0))); 566 DPRINTF(("DCR0 =0x%08x(expected 0x00030000)\n", BA0READ4(sc, CS4281_DCR0))); 567 DPRINTF(("FCR0 =0x%08x(expected 0x81000f00)\n", BA0READ4(sc, CS4281_FCR0))); 568 DPRINTF(("DACSR=0x%08x(expected 1 for 44kHz 5 for 8kHz)\n", 569 BA0READ4(sc, CS4281_DACSR))); 570 DPRINTF(("SRCSA=0x%08x(expected 0x0b0a0100)\n", BA0READ4(sc, CS4281_SRCSA))); 571 DPRINTF(("SSPM&SSPM_PSRCEN =0x%08x(expected 0x00000010)\n", 572 BA0READ4(sc, CS4281_SSPM) & SSPM_PSRCEN)); 573 mtx_leave(&audio_lock); 574 return (0); 575 } 576 577 int 578 cs4281_trigger_input(addr, start, end, blksize, intr, arg, param) 579 void *addr; 580 void *start, *end; 581 int blksize; 582 void (*intr)(void *); 583 void *arg; 584 struct audio_params *param; 585 { 586 struct cs4281_softc *sc = addr; 587 struct cs4281_dma *p; 588 u_int32_t fmt = 0; 589 int dma_count; 590 591 if ((char *)end - (char *)start != 2 * blksize) { 592 #ifdef DIAGNOSTIC 593 printf("%s: rec block size must be half the buffer size\n", 594 sc->sc_dev.dv_xname); 595 #endif 596 return EIO; 597 } 598 599 #ifdef DIAGNOSTIC 600 if (sc->sc_rrun) 601 printf("cs4281_trigger_input: already running\n"); 602 sc->sc_rrun = 1; 603 #endif 604 DPRINTF(("cs4281_trigger_input: sc=%p start=%p end=%p " 605 "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg)); 606 sc->sc_rintr = intr; 607 sc->sc_rarg = arg; 608 609 /* stop recording DMA */ 610 BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) | DCRn_MSK); 611 612 for (p = sc->sc_dmas; p && KERNADDR(p) != start; p = p->next) 613 ; 614 if (!p) { 615 printf("cs4281_trigger_input: bad addr %p\n", start); 616 return (EINVAL); 617 } 618 619 dma_count = (char *)end - (char *)start; 620 if (param->precision != 8) 621 dma_count /= 2; 622 if (param->channels > 1) 623 dma_count /= 2; 624 625 DPRINTF(("cs4281_trigger_input: DMAADDR(p)=0x%x count=%d\n", 626 (int)DMAADDR(p), dma_count)); 627 BA0WRITE4(sc, CS4281_DBA1, DMAADDR(p)); 628 BA0WRITE4(sc, CS4281_DBC1, dma_count-1); 629 630 /* set recording format */ 631 fmt = BA0READ4(sc, CS4281_DMR1) & ~DMRn_FMTMSK; 632 if (param->precision == 8) 633 fmt |= DMRn_SIZE8; 634 if (param->channels == 1) 635 fmt |= DMRn_MONO; 636 if (param->encoding == AUDIO_ENCODING_ULINEAR_BE || 637 param->encoding == AUDIO_ENCODING_SLINEAR_BE) 638 fmt |= DMRn_BEND; 639 if (param->encoding == AUDIO_ENCODING_ULINEAR_BE || 640 param->encoding == AUDIO_ENCODING_ULINEAR_LE) 641 fmt |= DMRn_USIGN; 642 BA0WRITE4(sc, CS4281_DMR1, fmt); 643 644 /* set sample rate */ 645 cs4281_set_adc_rate(sc, param->sample_rate); 646 647 /* Start DMA */ 648 mtx_enter(&audio_lock); 649 BA0WRITE4(sc, CS4281_DCR1, BA0READ4(sc, CS4281_DCR1) & ~DCRn_MSK); 650 /* Enable interrupts */ 651 BA0WRITE4(sc, CS4281_HICR, HICR_IEV | HICR_CHGM); 652 653 DPRINTF(("HICR=0x%08x\n", BA0READ4(sc, CS4281_HICR))); 654 DPRINTF(("HIMR=0x%08x\n", BA0READ4(sc, CS4281_HIMR))); 655 DPRINTF(("DMR1=0x%08x\n", BA0READ4(sc, CS4281_DMR1))); 656 DPRINTF(("DCR1=0x%08x\n", BA0READ4(sc, CS4281_DCR1))); 657 mtx_leave(&audio_lock); 658 return (0); 659 } 660 661 /* convert sample rate to register value */ 662 u_int8_t 663 cs4281_sr2regval(rate) 664 int rate; 665 { 666 u_int8_t retval; 667 668 /* We don't have to change here. but anyway ... */ 669 if (rate > 48000) 670 rate = 48000; 671 if (rate < 6023) 672 rate = 6023; 673 674 switch (rate) { 675 case 8000: 676 retval = 5; 677 break; 678 case 11025: 679 retval = 4; 680 break; 681 case 16000: 682 retval = 3; 683 break; 684 case 22050: 685 retval = 2; 686 break; 687 case 44100: 688 retval = 1; 689 break; 690 case 48000: 691 retval = 0; 692 break; 693 default: 694 retval = 1536000/rate; /* == 24576000/(rate*16) */ 695 } 696 return (retval); 697 } 698 699 700 void 701 cs4281_set_dac_rate(sc, rate) 702 struct cs4281_softc *sc; 703 int rate; 704 { 705 BA0WRITE4(sc, CS4281_DACSR, cs4281_sr2regval(rate)); 706 } 707 708 void 709 cs4281_set_adc_rate(sc, rate) 710 struct cs4281_softc *sc; 711 int rate; 712 { 713 BA0WRITE4(sc, CS4281_ADCSR, cs4281_sr2regval(rate)); 714 } 715 716 int 717 cs4281_init(sc) 718 struct cs4281_softc *sc; 719 { 720 int n; 721 u_int16_t data; 722 u_int32_t dat32; 723 724 /* set "Configuration Write Protect" register to 725 * 0x4281 to allow to write */ 726 BA0WRITE4(sc, CS4281_CWPR, 0x4281); 727 728 /* 729 * Unset "Full Power-Down bit of Extended PCI Power Management 730 * Control" register to release the reset state. 731 */ 732 dat32 = BA0READ4(sc, CS4281_EPPMC); 733 if (dat32 & EPPMC_FPDN) 734 BA0WRITE4(sc, CS4281_EPPMC, dat32 & ~EPPMC_FPDN); 735 736 /* Start PLL out in known state */ 737 BA0WRITE4(sc, CS4281_CLKCR1, 0); 738 /* Start serial ports out in known state */ 739 BA0WRITE4(sc, CS4281_SERMC, 0); 740 741 /* Reset codec */ 742 BA0WRITE4(sc, CS4281_ACCTL, 0); 743 delay(50); /* delay 50us */ 744 745 BA0WRITE4(sc, CS4281_SPMC, 0); 746 delay(100); /* delay 100us */ 747 BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN); 748 #if defined(ENABLE_SECONDARY_CODEC) 749 BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN | SPCM_ASDIN2E); 750 BA0WRITE4(sc, CS4281_SERMC, SERMC_TCID); 751 #endif 752 delay(50000); /* XXX: delay 50ms */ 753 754 /* Turn on Sound System clocks based on ABITCLK */ 755 BA0WRITE4(sc, CS4281_CLKCR1, CLKCR1_DLLP); 756 delay(50000); /* XXX: delay 50ms */ 757 BA0WRITE4(sc, CS4281_CLKCR1, CLKCR1_SWCE | CLKCR1_DLLP); 758 759 /* Set enables for sections that are needed in the SSPM registers */ 760 BA0WRITE4(sc, CS4281_SSPM, 761 SSPM_MIXEN | /* Mixer */ 762 SSPM_CSRCEN | /* Capture SRC */ 763 SSPM_PSRCEN | /* Playback SRC */ 764 SSPM_JSEN | /* Joystick */ 765 SSPM_ACLEN | /* AC LINK */ 766 SSPM_FMEN /* FM */ 767 ); 768 769 /* Wait for clock stabilization */ 770 n = 0; 771 while ((BA0READ4(sc, CS4281_CLKCR1)& (CLKCR1_DLLRDY | CLKCR1_CLKON)) 772 != (CLKCR1_DLLRDY | CLKCR1_CLKON)) { 773 delay(100); 774 if (++n > 1000) 775 return (-1); 776 } 777 778 /* Enable ASYNC generation */ 779 BA0WRITE4(sc, CS4281_ACCTL, ACCTL_ESYN); 780 781 /* Wait for Codec ready. Linux driver wait 50ms here */ 782 n = 0; 783 while((BA0READ4(sc, CS4281_ACSTS) & ACSTS_CRDY) == 0) { 784 delay(100); 785 if (++n > 1000) 786 return (-1); 787 } 788 789 #if defined(ENABLE_SECONDARY_CODEC) 790 /* secondary codec ready*/ 791 n = 0; 792 while((BA0READ4(sc, CS4281_ACSTS2) & ACSTS2_CRDY2) == 0) { 793 delay(100); 794 if (++n > 1000) 795 return (-1); 796 } 797 #endif 798 799 /* Set the serial timing configuration */ 800 /* XXX: undocumented but the Linux driver do this */ 801 BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97); 802 803 /* Wait for Codec ready signal */ 804 n = 0; 805 do { 806 delay(1000); 807 if (++n > 1000) { 808 printf("%s: Timeout waiting for Codec ready\n", 809 sc->sc_dev.dv_xname); 810 return -1; 811 } 812 dat32 = BA0READ4(sc, CS4281_ACSTS) & ACSTS_CRDY; 813 } while (dat32 == 0); 814 815 /* Enable Valid Frame output on ASDOUT */ 816 BA0WRITE4(sc, CS4281_ACCTL, ACCTL_ESYN | ACCTL_VFRM); 817 818 /* Wait until Codec Calibration is finished. Codec register 26h */ 819 n = 0; 820 do { 821 delay(1); 822 if (++n > 1000) { 823 printf("%s: Timeout waiting for Codec calibration\n", 824 sc->sc_dev.dv_xname); 825 return -1; 826 } 827 cs4281_read_codec(sc, AC97_REG_POWER, &data); 828 } while ((data & 0x0f) != 0x0f); 829 830 /* Set the serial timing configuration again */ 831 /* XXX: undocumented but the Linux driver do this */ 832 BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97); 833 834 /* Wait until we've sampled input slots 3 & 4 as valid */ 835 n = 0; 836 do { 837 delay(1000); 838 if (++n > 1000) { 839 printf("%s: Timeout waiting for sampled input slots as valid\n", 840 sc->sc_dev.dv_xname); 841 return -1; 842 } 843 dat32 = BA0READ4(sc, CS4281_ACISV) & (ACISV_ISV3 | ACISV_ISV4); 844 } while (dat32 != (ACISV_ISV3 | ACISV_ISV4)); 845 846 /* Start digital data transfer of audio data to the codec */ 847 BA0WRITE4(sc, CS4281_ACOSV, (ACOSV_SLV3 | ACOSV_SLV4)); 848 849 cs4281_write_codec(sc, AC97_REG_HEADPHONE_VOLUME, 0); 850 cs4281_write_codec(sc, AC97_REG_MASTER_VOLUME, 0); 851 852 /* Power on the DAC */ 853 cs4281_read_codec(sc, AC97_REG_POWER, &data); 854 cs4281_write_codec(sc, AC97_REG_POWER, data &= 0xfdff); 855 856 /* Wait until we sample a DAC ready state. 857 * Not documented, but Linux driver does. 858 */ 859 for (n = 0; n < 32; ++n) { 860 delay(1000); 861 cs4281_read_codec(sc, AC97_REG_POWER, &data); 862 if (data & 0x02) 863 break; 864 } 865 866 /* Power on the ADC */ 867 cs4281_read_codec(sc, AC97_REG_POWER, &data); 868 cs4281_write_codec(sc, AC97_REG_POWER, data &= 0xfeff); 869 870 /* Wait until we sample ADC ready state. 871 * Not documented, but Linux driver does. 872 */ 873 for (n = 0; n < 32; ++n) { 874 delay(1000); 875 cs4281_read_codec(sc, AC97_REG_POWER, &data); 876 if (data & 0x01) 877 break; 878 } 879 880 #if 0 881 /* Initialize SSCR register features */ 882 /* XXX: hardware volume setting */ 883 BA0WRITE4(sc, CS4281_SSCR, ~SSCR_HVC); /* disable HW volume setting */ 884 #endif 885 886 /* disable Sound Blaster Pro emulation */ 887 /* XXX: 888 * Cannot set since the documents does not describe which bit is 889 * correspond to SSCR_SB. Since the reset value of SSCR is 0, 890 * we can ignore it.*/ 891 #if 0 892 BA0WRITE4(sc, CS4281_SSCR, SSCR_SB); 893 #endif 894 895 /* map AC97 PCM playback to DMA Channel 0 */ 896 /* Reset FEN bit to setup first */ 897 BA0WRITE4(sc, CS4281_FCR0, (BA0READ4(sc,CS4281_FCR0) & ~FCRn_FEN)); 898 /* 899 *| RS[4:0]/| | 900 *| LS[4:0] | AC97 | Slot Function 901 *|---------+--------+-------------------- 902 *| 0 | 3 | Left PCM Playback 903 *| 1 | 4 | Right PCM Playback 904 *| 2 | 5 | Phone Line 1 DAC 905 *| 3 | 6 | Center PCM Playback 906 *.... 907 * quoted from Table 29(p109) 908 */ 909 dat32 = 0x01 << 24 | /* RS[4:0] = 1 see above */ 910 0x00 << 16 | /* LS[4:0] = 0 see above */ 911 0x0f << 8 | /* SZ[6:0] = 15 size of buffer */ 912 0x00 << 0 ; /* OF[6:0] = 0 offset */ 913 BA0WRITE4(sc, CS4281_FCR0, dat32); 914 BA0WRITE4(sc, CS4281_FCR0, dat32 | FCRn_FEN); 915 916 /* map AC97 PCM record to DMA Channel 1 */ 917 /* Reset FEN bit to setup first */ 918 BA0WRITE4(sc, CS4281_FCR1, (BA0READ4(sc,CS4281_FCR1) & ~FCRn_FEN)); 919 /* 920 *| RS[4:0]/| 921 *| LS[4:0] | AC97 | Slot Function 922 *|---------+------+------------------- 923 *| 10 | 3 | Left PCM Record 924 *| 11 | 4 | Right PCM Record 925 *| 12 | 5 | Phone Line 1 ADC 926 *| 13 | 6 | Mic ADC 927 *.... 928 * quoted from Table 30(p109) 929 */ 930 dat32 = 0x0b << 24 | /* RS[4:0] = 11 See above */ 931 0x0a << 16 | /* LS[4:0] = 10 See above */ 932 0x0f << 8 | /* SZ[6:0] = 15 Size of buffer */ 933 0x10 << 0 ; /* OF[6:0] = 16 offset */ 934 935 /* XXX: I cannot understand why FCRn_PSH is needed here. */ 936 BA0WRITE4(sc, CS4281_FCR1, dat32 | FCRn_PSH); 937 BA0WRITE4(sc, CS4281_FCR1, dat32 | FCRn_FEN); 938 939 #if 0 940 /* Disable DMA Channel 2, 3 */ 941 BA0WRITE4(sc, CS4281_FCR2, (BA0READ4(sc,CS4281_FCR2) & ~FCRn_FEN)); 942 BA0WRITE4(sc, CS4281_FCR3, (BA0READ4(sc,CS4281_FCR3) & ~FCRn_FEN)); 943 #endif 944 945 /* Set the SRC Slot Assignment accordingly */ 946 /*| PLSS[4:0]/ 947 *| PRSS[4:0] | AC97 | Slot Function 948 *|-----------+------+---------------- 949 *| 0 | 3 | Left PCM Playback 950 *| 1 | 4 | Right PCM Playback 951 *| 2 | 5 | phone line 1 DAC 952 *| 3 | 6 | Center PCM Playback 953 *| 4 | 7 | Left Surround PCM Playback 954 *| 5 | 8 | Right Surround PCM Playback 955 *...... 956 * 957 *| CLSS[4:0]/ 958 *| CRSS[4:0] | AC97 | Codec |Slot Function 959 *|-----------+------+-------+----------------- 960 *| 10 | 3 |Primary| Left PCM Record 961 *| 11 | 4 |Primary| Right PCM Record 962 *| 12 | 5 |Primary| Phone Line 1 ADC 963 *| 13 | 6 |Primary| Mic ADC 964 *|..... 965 *| 20 | 3 | Sec. | Left PCM Record 966 *| 21 | 4 | Sec. | Right PCM Record 967 *| 22 | 5 | Sec. | Phone Line 1 ADC 968 *| 23 | 6 | Sec. | Mic ADC 969 */ 970 dat32 = 0x0b << 24 | /* CRSS[4:0] Right PCM Record(primary) */ 971 0x0a << 16 | /* CLSS[4:0] Left PCM Record(primary) */ 972 0x01 << 8 | /* PRSS[4:0] Right PCM Playback */ 973 0x00 << 0; /* PLSS[4:0] Left PCM Playback */ 974 BA0WRITE4(sc, CS4281_SRCSA, dat32); 975 976 /* Set interrupt to occurred at Half and Full terminal 977 * count interrupt enable for DMA channel 0 and 1. 978 * To keep DMA stop, set MSK. 979 */ 980 dat32 = DCRn_HTCIE | DCRn_TCIE | DCRn_MSK; 981 BA0WRITE4(sc, CS4281_DCR0, dat32); 982 BA0WRITE4(sc, CS4281_DCR1, dat32); 983 984 /* Set Auto-Initialize Control enable */ 985 BA0WRITE4(sc, CS4281_DMR0, 986 DMRn_DMA | DMRn_AUTO | DMRn_TR_READ); 987 BA0WRITE4(sc, CS4281_DMR1, 988 DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE); 989 990 /* Clear DMA Mask in HIMR */ 991 dat32 = BA0READ4(sc, CS4281_HIMR) & 0xfffbfcff; 992 BA0WRITE4(sc, CS4281_HIMR, dat32); 993 return (0); 994 } 995 996 int 997 cs4281_activate(struct device *self, int act) 998 { 999 struct cs4281_softc *sc = (struct cs4281_softc *)self; 1000 int rv = 0; 1001 1002 switch (act) { 1003 case DVACT_SUSPEND: 1004 /* should I powerdown here ? */ 1005 cs4281_write_codec(sc, AC97_REG_POWER, CS4281_POWER_DOWN_ALL); 1006 break; 1007 case DVACT_RESUME: 1008 cs4281_init(sc); 1009 ac97_resume(&sc->host_if, sc->codec_if); 1010 rv = config_activate_children(self, act); 1011 break; 1012 default: 1013 rv = config_activate_children(self, act); 1014 break; 1015 } 1016 return (rv); 1017 } 1018 1019 void 1020 cs4281_reset_codec(void *addr) 1021 { 1022 struct cs4281_softc *sc; 1023 u_int16_t data; 1024 u_int32_t dat32; 1025 int n; 1026 1027 sc = addr; 1028 1029 DPRINTFN(3,("cs4281_reset_codec\n")); 1030 1031 /* Reset codec */ 1032 BA0WRITE4(sc, CS4281_ACCTL, 0); 1033 delay(50); /* delay 50us */ 1034 1035 BA0WRITE4(sc, CS4281_SPMC, 0); 1036 delay(100); /* delay 100us */ 1037 BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN); 1038 #if defined(ENABLE_SECONDARY_CODEC) 1039 BA0WRITE4(sc, CS4281_SPMC, SPMC_RSTN | SPCM_ASDIN2E); 1040 BA0WRITE4(sc, CS4281_SERMC, SERMC_TCID); 1041 #endif 1042 delay(50000); /* XXX: delay 50ms */ 1043 1044 /* Enable ASYNC generation */ 1045 BA0WRITE4(sc, CS4281_ACCTL, ACCTL_ESYN); 1046 1047 /* Wait for Codec ready. Linux driver wait 50ms here */ 1048 n = 0; 1049 while((BA0READ4(sc, CS4281_ACSTS) & ACSTS_CRDY) == 0) { 1050 delay(100); 1051 if (++n > 1000) { 1052 printf("%s: AC97 codec ready timeout\n", 1053 sc->sc_dev.dv_xname); 1054 return; 1055 } 1056 } 1057 #if defined(ENABLE_SECONDARY_CODEC) 1058 /* secondary codec ready*/ 1059 n = 0; 1060 while((BA0READ4(sc, CS4281_ACSTS2) & ACSTS2_CRDY2) == 0) { 1061 delay(100); 1062 if (++n > 1000) 1063 return; 1064 } 1065 #endif 1066 /* Set the serial timing configuration */ 1067 /* XXX: undocumented but the Linux driver do this */ 1068 BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97); 1069 1070 /* Wait for Codec ready signal */ 1071 n = 0; 1072 do { 1073 delay(1000); 1074 if (++n > 1000) { 1075 printf("%s: Timeout waiting for Codec ready\n", 1076 sc->sc_dev.dv_xname); 1077 return; 1078 } 1079 dat32 = BA0READ4(sc, CS4281_ACSTS) & ACSTS_CRDY; 1080 } while (dat32 == 0); 1081 1082 /* Enable Valid Frame output on ASDOUT */ 1083 BA0WRITE4(sc, CS4281_ACCTL, ACCTL_ESYN | ACCTL_VFRM); 1084 1085 /* Wait until Codec Calibration is finished. Codec register 26h */ 1086 n = 0; 1087 do { 1088 delay(1); 1089 if (++n > 1000) { 1090 printf("%s: Timeout waiting for Codec calibration\n", 1091 sc->sc_dev.dv_xname); 1092 return ; 1093 } 1094 cs4281_read_codec(sc, AC97_REG_POWER, &data); 1095 } while ((data & 0x0f) != 0x0f); 1096 1097 /* Set the serial timing configuration again */ 1098 /* XXX: undocumented but the Linux driver do this */ 1099 BA0WRITE4(sc, CS4281_SERMC, SERMC_PTCAC97); 1100 1101 /* Wait until we've sampled input slots 3 & 4 as valid */ 1102 n = 0; 1103 do { 1104 delay(1000); 1105 if (++n > 1000) { 1106 printf("%s: Timeout waiting for sampled input slots as valid\n", 1107 sc->sc_dev.dv_xname); 1108 return; 1109 } 1110 dat32 = BA0READ4(sc, CS4281_ACISV) & (ACISV_ISV3 | ACISV_ISV4) ; 1111 } while (dat32 != (ACISV_ISV3 | ACISV_ISV4)); 1112 1113 /* Start digital data transfer of audio data to the codec */ 1114 BA0WRITE4(sc, CS4281_ACOSV, (ACOSV_SLV3 | ACOSV_SLV4)); 1115 } 1116 1117 int 1118 cs4281_open(void *addr, int flags) 1119 { 1120 return (0); 1121 } 1122 1123 void 1124 cs4281_close(void *addr) 1125 { 1126 struct cs4281_softc *sc; 1127 1128 sc = addr; 1129 1130 (*sc->halt_output)(sc); 1131 (*sc->halt_input)(sc); 1132 1133 sc->sc_pintr = 0; 1134 sc->sc_rintr = 0; 1135 } 1136 1137 int 1138 cs4281_round_blocksize(void *addr, int blk) 1139 { 1140 return DMA_SIZE / 2; 1141 } 1142 1143 int 1144 cs4281_mixer_set_port(void *addr, mixer_ctrl_t *cp) 1145 { 1146 struct cs4281_softc *sc; 1147 int val; 1148 1149 sc = addr; 1150 val = sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp); 1151 DPRINTFN(3,("mixer_set_port: val=%d\n", val)); 1152 return (val); 1153 } 1154 1155 int 1156 cs4281_mixer_get_port(void *addr, mixer_ctrl_t *cp) 1157 { 1158 struct cs4281_softc *sc; 1159 1160 sc = addr; 1161 return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp)); 1162 } 1163 1164 1165 int 1166 cs4281_query_devinfo(void *addr, mixer_devinfo_t *dip) 1167 { 1168 struct cs4281_softc *sc; 1169 1170 sc = addr; 1171 return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, dip)); 1172 } 1173 1174 void * 1175 cs4281_malloc(void *addr, int direction, size_t size, int pool, int flags) 1176 { 1177 struct cs4281_softc *sc; 1178 struct cs4281_dma *p; 1179 int error; 1180 1181 sc = addr; 1182 1183 p = malloc(sizeof(*p), pool, flags); 1184 if (!p) 1185 return (0); 1186 1187 error = cs4281_allocmem(sc, size, pool, flags, p); 1188 1189 if (error) { 1190 free(p, pool, sizeof(*p)); 1191 return (0); 1192 } 1193 1194 p->next = sc->sc_dmas; 1195 sc->sc_dmas = p; 1196 return (KERNADDR(p)); 1197 } 1198 1199 1200 1201 void 1202 cs4281_free(void *addr, void *ptr, int pool) 1203 { 1204 struct cs4281_softc *sc; 1205 struct cs4281_dma **pp, *p; 1206 1207 sc = addr; 1208 for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) { 1209 if (KERNADDR(p) == ptr) { 1210 bus_dmamap_unload(sc->sc_dmatag, p->map); 1211 bus_dmamap_destroy(sc->sc_dmatag, p->map); 1212 bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size); 1213 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs); 1214 *pp = p->next; 1215 free(p, pool, sizeof(*p)); 1216 return; 1217 } 1218 } 1219 } 1220 1221 size_t 1222 cs4281_round_buffersize(void *addr, int direction, size_t size) 1223 { 1224 return (DMA_SIZE); 1225 } 1226 1227 int 1228 cs4281_get_props(void *addr) 1229 { 1230 int retval; 1231 1232 retval = AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX; 1233 #ifdef MMAP_READY 1234 retval |= AUDIO_PROP_MMAP; 1235 #endif 1236 return (retval); 1237 } 1238 1239 /* AC97 */ 1240 int 1241 cs4281_attach_codec(void *addr, struct ac97_codec_if *codec_if) 1242 { 1243 struct cs4281_softc *sc; 1244 1245 DPRINTF(("cs4281_attach_codec:\n")); 1246 sc = addr; 1247 sc->codec_if = codec_if; 1248 return (0); 1249 } 1250 1251 1252 int 1253 cs4281_read_codec(void *addr, u_int8_t ac97_addr, u_int16_t *ac97_data) 1254 { 1255 struct cs4281_softc *sc; 1256 u_int32_t acctl; 1257 int n; 1258 1259 sc = addr; 1260 1261 DPRINTFN(5,("read_codec: add=0x%02x ", ac97_addr)); 1262 /* 1263 * Make sure that there is not data sitting around from a preivous 1264 * uncompleted access. 1265 */ 1266 BA0READ4(sc, CS4281_ACSDA); 1267 1268 /* Set up AC97 control registers. */ 1269 BA0WRITE4(sc, CS4281_ACCAD, ac97_addr); 1270 BA0WRITE4(sc, CS4281_ACCDA, 0); 1271 1272 acctl = ACCTL_ESYN | ACCTL_VFRM | ACCTL_CRW | ACCTL_DCV; 1273 BA0WRITE4(sc, CS4281_ACCTL, acctl); 1274 1275 if (cs4281_src_wait(sc) < 0) { 1276 printf("%s: AC97 read prob. (DCV!=0) for add=0x%0x\n", 1277 sc->sc_dev.dv_xname, ac97_addr); 1278 return 1; 1279 } 1280 1281 /* wait for valid status bit is active */ 1282 n = 0; 1283 while ((BA0READ4(sc, CS4281_ACSTS) & ACSTS_VSTS) == 0) { 1284 delay(1); 1285 while (++n > 1000) { 1286 printf("%s: AC97 read fail (VSTS==0) for add=0x%0x\n", 1287 sc->sc_dev.dv_xname, ac97_addr); 1288 return 1; 1289 } 1290 } 1291 *ac97_data = BA0READ4(sc, CS4281_ACSDA); 1292 DPRINTFN(5,("data=0x%04x\n", *ac97_data)); 1293 return (0); 1294 } 1295 1296 int 1297 cs4281_write_codec(void *addr, u_int8_t ac97_addr, u_int16_t ac97_data) 1298 { 1299 struct cs4281_softc *sc; 1300 u_int32_t acctl; 1301 1302 sc = addr; 1303 1304 DPRINTFN(5,("write_codec: add=0x%02x data=0x%04x\n", ac97_addr, ac97_data)); 1305 BA0WRITE4(sc, CS4281_ACCAD, ac97_addr); 1306 BA0WRITE4(sc, CS4281_ACCDA, ac97_data); 1307 1308 acctl = ACCTL_ESYN | ACCTL_VFRM | ACCTL_DCV; 1309 BA0WRITE4(sc, CS4281_ACCTL, acctl); 1310 1311 if (cs4281_src_wait(sc) < 0) { 1312 printf("%s: AC97 write fail (DCV!=0) for add=0x%02x data=" 1313 "0x%04x\n", sc->sc_dev.dv_xname, ac97_addr, ac97_data); 1314 return (1); 1315 } 1316 return (0); 1317 } 1318 1319 int 1320 cs4281_allocmem(struct cs4281_softc *sc, size_t size, int pool, int flags, 1321 struct cs4281_dma *p) 1322 { 1323 int error; 1324 1325 if (size != DMA_SIZE) { 1326 printf("%s: dma size is %zd should be %d\n", 1327 sc->sc_dev.dv_xname, size, DMA_SIZE); 1328 return ENOMEM; 1329 1330 } 1331 p->size = size; 1332 1333 /* allocate memory for upper audio driver */ 1334 error = bus_dmamem_alloc(sc->sc_dmatag, p->size, DMA_ALIGN, 0, 1335 p->segs, nitems(p->segs), 1336 &p->nsegs, BUS_DMA_NOWAIT); 1337 if (error) { 1338 printf("%s: unable to allocate dma. error=%d\n", 1339 sc->sc_dev.dv_xname, error); 1340 return (error); 1341 } 1342 1343 error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size, 1344 &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT); 1345 if (error) { 1346 printf("%s: unable to map dma, error=%d\n", 1347 sc->sc_dev.dv_xname, error); 1348 goto free; 1349 } 1350 1351 error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size, 1352 0, BUS_DMA_NOWAIT, &p->map); 1353 if (error) { 1354 printf("%s: unable to create dma map, error=%d\n", 1355 sc->sc_dev.dv_xname, error); 1356 goto unmap; 1357 } 1358 1359 error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL, 1360 BUS_DMA_NOWAIT); 1361 if (error) { 1362 printf("%s: unable to load dma map, error=%d\n", 1363 sc->sc_dev.dv_xname, error); 1364 goto destroy; 1365 } 1366 return (0); 1367 1368 destroy: 1369 bus_dmamap_destroy(sc->sc_dmatag, p->map); 1370 unmap: 1371 bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size); 1372 free: 1373 bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs); 1374 return (error); 1375 } 1376 1377 1378 int 1379 cs4281_src_wait(sc) 1380 struct cs4281_softc *sc; 1381 { 1382 int n; 1383 1384 n = 0; 1385 while ((BA0READ4(sc, CS4281_ACCTL) & ACCTL_DCV)) { 1386 delay(1000); 1387 if (++n > 1000) 1388 return (-1); 1389 } 1390 return (0); 1391 } 1392