1 /* $NetBSD: auacer.c,v 1.21 2008/04/28 20:23:54 martin Exp $ */ 2 3 /*- 4 * Copyright (c) 2004 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Lennart Augustsson. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Acer Labs M5455 audio driver 34 * 35 * Acer provides data sheets after signing an NDA, so this is guess work. 36 * The chip behaves somewhat like the Intel i8x0, so this driver 37 * is loosely based on the auich driver. Additional information taken from 38 * the ALSA intel8x0.c driver (which handles M5455 as well). 39 * 40 * As an historical note one can observe that the auich driver borrows 41 * lot from the first NetBSD PCI audio driver, the eap driver. But this 42 * is not attributed anywhere. 43 */ 44 45 46 #include <sys/cdefs.h> 47 __KERNEL_RCSID(0, "$NetBSD: auacer.c,v 1.21 2008/04/28 20:23:54 martin Exp $"); 48 49 #include <sys/param.h> 50 #include <sys/systm.h> 51 #include <sys/kernel.h> 52 #include <sys/malloc.h> 53 #include <sys/device.h> 54 #include <sys/fcntl.h> 55 #include <sys/proc.h> 56 57 #include <uvm/uvm_extern.h> /* for PAGE_SIZE */ 58 59 #include <dev/pci/pcidevs.h> 60 #include <dev/pci/pcivar.h> 61 #include <dev/pci/auacerreg.h> 62 63 #include <sys/audioio.h> 64 #include <dev/audio_if.h> 65 #include <dev/mulaw.h> 66 #include <dev/auconv.h> 67 68 #include <sys/bus.h> 69 70 #include <dev/ic/ac97reg.h> 71 #include <dev/ic/ac97var.h> 72 73 struct auacer_dma { 74 bus_dmamap_t map; 75 void *addr; 76 bus_dma_segment_t segs[1]; 77 int nsegs; 78 size_t size; 79 struct auacer_dma *next; 80 }; 81 82 #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr) 83 #define KERNADDR(p) ((void *)((p)->addr)) 84 85 struct auacer_cdata { 86 struct auacer_dmalist ic_dmalist_pcmo[ALI_DMALIST_MAX]; 87 }; 88 89 struct auacer_chan { 90 uint32_t ptr; 91 uint32_t start, p, end; 92 uint32_t blksize, fifoe; 93 uint32_t ack; 94 uint32_t port; 95 struct auacer_dmalist *dmalist; 96 void (*intr)(void *); 97 void *arg; 98 }; 99 100 struct auacer_softc { 101 struct device sc_dev; 102 void *sc_ih; 103 104 audio_device_t sc_audev; 105 106 bus_space_tag_t iot; 107 bus_space_handle_t mix_ioh; 108 bus_space_handle_t aud_ioh; 109 bus_dma_tag_t dmat; 110 111 struct ac97_codec_if *codec_if; 112 struct ac97_host_if host_if; 113 114 /* DMA scatter-gather lists. */ 115 bus_dmamap_t sc_cddmamap; 116 #define sc_cddma sc_cddmamap->dm_segs[0].ds_addr 117 118 struct auacer_cdata *sc_cdata; 119 120 struct auacer_chan sc_pcmo; 121 122 struct auacer_dma *sc_dmas; 123 124 pci_chipset_tag_t sc_pc; 125 pcitag_t sc_pt; 126 127 int sc_dmamap_flags; 128 129 #define AUACER_NFORMATS 3 130 struct audio_format sc_formats[AUACER_NFORMATS]; 131 struct audio_encoding_set *sc_encodings; 132 }; 133 134 #define READ1(sc, a) bus_space_read_1(sc->iot, sc->aud_ioh, a) 135 #define READ2(sc, a) bus_space_read_2(sc->iot, sc->aud_ioh, a) 136 #define READ4(sc, a) bus_space_read_4(sc->iot, sc->aud_ioh, a) 137 #define WRITE1(sc, a, v) bus_space_write_1(sc->iot, sc->aud_ioh, a, v) 138 #define WRITE2(sc, a, v) bus_space_write_2(sc->iot, sc->aud_ioh, a, v) 139 #define WRITE4(sc, a, v) bus_space_write_4(sc->iot, sc->aud_ioh, a, v) 140 141 /* Debug */ 142 #ifdef AUACER_DEBUG 143 #define DPRINTF(l,x) do { if (auacer_debug & (l)) printf x; } while(0) 144 int auacer_debug = 0; 145 #define ALI_DEBUG_CODECIO 0x0001 146 #define ALI_DEBUG_DMA 0x0002 147 #define ALI_DEBUG_INTR 0x0004 148 #define ALI_DEBUG_API 0x0008 149 #define ALI_DEBUG_MIXERAPI 0x0010 150 #else 151 #define DPRINTF(x,y) /* nothing */ 152 #endif 153 154 static int auacer_intr(void *); 155 156 static int auacer_query_encoding(void *, struct audio_encoding *); 157 static int auacer_set_params(void *, int, int, audio_params_t *, 158 audio_params_t *, stream_filter_list_t *, 159 stream_filter_list_t *); 160 static int auacer_round_blocksize(void *, int, int, 161 const audio_params_t *); 162 static int auacer_halt_output(void *); 163 static int auacer_halt_input(void *); 164 static int auacer_getdev(void *, struct audio_device *); 165 static int auacer_set_port(void *, mixer_ctrl_t *); 166 static int auacer_get_port(void *, mixer_ctrl_t *); 167 static int auacer_query_devinfo(void *, mixer_devinfo_t *); 168 static void *auacer_allocm(void *, int, size_t, struct malloc_type *, int); 169 static void auacer_freem(void *, void *, struct malloc_type *); 170 static size_t auacer_round_buffersize(void *, int, size_t); 171 static paddr_t auacer_mappage(void *, void *, off_t, int); 172 static int auacer_get_props(void *); 173 static int auacer_trigger_output(void *, void *, void *, int, 174 void (*)(void *), void *, 175 const audio_params_t *); 176 static int auacer_trigger_input(void *, void *, void *, int, 177 void (*)(void *), void *, 178 const audio_params_t *); 179 180 static int auacer_alloc_cdata(struct auacer_softc *); 181 182 static int auacer_allocmem(struct auacer_softc *, size_t, size_t, 183 struct auacer_dma *); 184 static int auacer_freemem(struct auacer_softc *, struct auacer_dma *); 185 186 static bool auacer_resume(device_t PMF_FN_PROTO); 187 static int auacer_set_rate(struct auacer_softc *, int, u_int); 188 189 static void auacer_reset(struct auacer_softc *sc); 190 191 static struct audio_hw_if auacer_hw_if = { 192 NULL, /* open */ 193 NULL, /* close */ 194 NULL, /* drain */ 195 auacer_query_encoding, 196 auacer_set_params, 197 auacer_round_blocksize, 198 NULL, /* commit_setting */ 199 NULL, /* init_output */ 200 NULL, /* init_input */ 201 NULL, /* start_output */ 202 NULL, /* start_input */ 203 auacer_halt_output, 204 auacer_halt_input, 205 NULL, /* speaker_ctl */ 206 auacer_getdev, 207 NULL, /* getfd */ 208 auacer_set_port, 209 auacer_get_port, 210 auacer_query_devinfo, 211 auacer_allocm, 212 auacer_freem, 213 auacer_round_buffersize, 214 auacer_mappage, 215 auacer_get_props, 216 auacer_trigger_output, 217 auacer_trigger_input, 218 NULL, /* dev_ioctl */ 219 NULL, /* powerstate */ 220 }; 221 222 #define AUACER_FORMATS_4CH 1 223 #define AUACER_FORMATS_6CH 2 224 static const struct audio_format auacer_formats[AUACER_NFORMATS] = { 225 {NULL, AUMODE_PLAY | AUMODE_RECORD, AUDIO_ENCODING_SLINEAR_LE, 16, 16, 226 2, AUFMT_STEREO, 0, {8000, 48000}}, 227 {NULL, AUMODE_PLAY, AUDIO_ENCODING_SLINEAR_LE, 16, 16, 228 4, AUFMT_SURROUND4, 0, {8000, 48000}}, 229 {NULL, AUMODE_PLAY, AUDIO_ENCODING_SLINEAR_LE, 16, 16, 230 6, AUFMT_DOLBY_5_1, 0, {8000, 48000}}, 231 }; 232 233 static int auacer_attach_codec(void *, struct ac97_codec_if *); 234 static int auacer_read_codec(void *, uint8_t, uint16_t *); 235 static int auacer_write_codec(void *, uint8_t, uint16_t); 236 static int auacer_reset_codec(void *); 237 238 static int 239 auacer_match(struct device *parent, struct cfdata *match, 240 void *aux) 241 { 242 struct pci_attach_args *pa; 243 244 pa = (struct pci_attach_args *)aux; 245 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ALI && 246 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ALI_M5455) 247 return 1; 248 return 0; 249 } 250 251 static void 252 auacer_attach(struct device *parent, struct device *self, void *aux) 253 { 254 struct auacer_softc *sc; 255 struct pci_attach_args *pa; 256 pci_intr_handle_t ih; 257 bus_size_t aud_size; 258 pcireg_t v; 259 const char *intrstr; 260 int i; 261 262 sc = (struct auacer_softc *)self; 263 pa = aux; 264 aprint_normal(": Acer Labs M5455 Audio controller\n"); 265 266 if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, &sc->iot, 267 &sc->aud_ioh, NULL, &aud_size)) { 268 aprint_error(": can't map i/o space\n"); 269 return; 270 } 271 272 sc->sc_pc = pa->pa_pc; 273 sc->sc_pt = pa->pa_tag; 274 sc->dmat = pa->pa_dmat; 275 276 sc->sc_dmamap_flags = BUS_DMA_COHERENT; /* XXX remove */ 277 278 /* enable bus mastering */ 279 v = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 280 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 281 v | PCI_COMMAND_MASTER_ENABLE); 282 283 /* Map and establish the interrupt. */ 284 if (pci_intr_map(pa, &ih)) { 285 aprint_error_dev(&sc->sc_dev, "can't map interrupt\n"); 286 return; 287 } 288 intrstr = pci_intr_string(pa->pa_pc, ih); 289 sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, 290 auacer_intr, sc); 291 if (sc->sc_ih == NULL) { 292 aprint_error_dev(&sc->sc_dev, "can't establish interrupt"); 293 if (intrstr != NULL) 294 aprint_normal(" at %s", intrstr); 295 aprint_normal("\n"); 296 return; 297 } 298 aprint_normal_dev(&sc->sc_dev, "interrupting at %s\n", intrstr); 299 300 strlcpy(sc->sc_audev.name, "M5455 AC97", MAX_AUDIO_DEV_LEN); 301 snprintf(sc->sc_audev.version, MAX_AUDIO_DEV_LEN, 302 "0x%02x", PCI_REVISION(pa->pa_class)); 303 strlcpy(sc->sc_audev.config, device_xname(&sc->sc_dev), MAX_AUDIO_DEV_LEN); 304 305 /* Set up DMA lists. */ 306 auacer_alloc_cdata(sc); 307 sc->sc_pcmo.dmalist = sc->sc_cdata->ic_dmalist_pcmo; 308 sc->sc_pcmo.ptr = 0; 309 sc->sc_pcmo.port = ALI_BASE_PO; 310 311 DPRINTF(ALI_DEBUG_DMA, ("auacer_attach: lists %p\n", 312 sc->sc_pcmo.dmalist)); 313 314 sc->host_if.arg = sc; 315 sc->host_if.attach = auacer_attach_codec; 316 sc->host_if.read = auacer_read_codec; 317 sc->host_if.write = auacer_write_codec; 318 sc->host_if.reset = auacer_reset_codec; 319 320 if (ac97_attach(&sc->host_if, self) != 0) 321 return; 322 323 /* setup audio_format */ 324 memcpy(sc->sc_formats, auacer_formats, sizeof(auacer_formats)); 325 if (!AC97_IS_4CH(sc->codec_if)) 326 AUFMT_INVALIDATE(&sc->sc_formats[AUACER_FORMATS_4CH]); 327 if (!AC97_IS_6CH(sc->codec_if)) 328 AUFMT_INVALIDATE(&sc->sc_formats[AUACER_FORMATS_6CH]); 329 if (AC97_IS_FIXED_RATE(sc->codec_if)) { 330 for (i = 0; i < AUACER_NFORMATS; i++) { 331 sc->sc_formats[i].frequency_type = 1; 332 sc->sc_formats[i].frequency[0] = 48000; 333 } 334 } 335 336 if (0 != auconv_create_encodings(sc->sc_formats, AUACER_NFORMATS, 337 &sc->sc_encodings)) { 338 return; 339 } 340 341 audio_attach_mi(&auacer_hw_if, sc, &sc->sc_dev); 342 343 auacer_reset(sc); 344 345 if (!pmf_device_register(self, NULL, auacer_resume)) 346 aprint_error_dev(self, "couldn't establish power handler\n"); 347 } 348 349 CFATTACH_DECL(auacer, sizeof(struct auacer_softc), 350 auacer_match, auacer_attach, NULL, NULL); 351 352 static int 353 auacer_ready_codec(struct auacer_softc *sc, int mask) 354 { 355 int count; 356 357 for (count = 0; count < 0x7f; count++) { 358 int val = READ1(sc, ALI_CSPSR); 359 if (val & mask) 360 return 0; 361 } 362 363 aprint_normal("auacer_ready_codec: AC97 codec ready timeout.\n"); 364 return EBUSY; 365 } 366 367 static int 368 auacer_sema_codec(struct auacer_softc *sc) 369 { 370 int ttime; 371 372 ttime = 100; 373 while (ttime-- && (READ4(sc, ALI_CAS) & ALI_CAS_SEM_BUSY)) 374 delay(1); 375 if (!ttime) 376 aprint_normal("auacer_sema_codec: timeout\n"); 377 return auacer_ready_codec(sc, ALI_CSPSR_CODEC_READY); 378 } 379 380 static int 381 auacer_read_codec(void *v, uint8_t reg, uint16_t *val) 382 { 383 struct auacer_softc *sc; 384 385 sc = v; 386 if (auacer_sema_codec(sc)) 387 return EIO; 388 389 reg |= ALI_CPR_ADDR_READ; 390 #if 0 391 if (ac97->num) 392 reg |= ALI_CPR_ADDR_SECONDARY; 393 #endif 394 WRITE2(sc, ALI_CPR_ADDR, reg); 395 if (auacer_ready_codec(sc, ALI_CSPSR_READ_OK)) 396 return EIO; 397 *val = READ2(sc, ALI_SPR); 398 399 DPRINTF(ALI_DEBUG_CODECIO, ("auacer_read_codec: reg=0x%x val=0x%x\n", 400 reg, *val)); 401 402 return 0; 403 } 404 405 int 406 auacer_write_codec(void *v, uint8_t reg, uint16_t val) 407 { 408 struct auacer_softc *sc; 409 410 DPRINTF(ALI_DEBUG_CODECIO, ("auacer_write_codec: reg=0x%x val=0x%x\n", 411 reg, val)); 412 sc = v; 413 if (auacer_sema_codec(sc)) 414 return EIO; 415 WRITE2(sc, ALI_CPR, val); 416 #if 0 417 if (ac97->num) 418 reg |= ALI_CPR_ADDR_SECONDARY; 419 #endif 420 WRITE2(sc, ALI_CPR_ADDR, reg); 421 auacer_ready_codec(sc, ALI_CSPSR_WRITE_OK); 422 return 0; 423 } 424 425 static int 426 auacer_attach_codec(void *v, struct ac97_codec_if *cif) 427 { 428 struct auacer_softc *sc; 429 430 sc = v; 431 sc->codec_if = cif; 432 return 0; 433 } 434 435 static int 436 auacer_reset_codec(void *v) 437 { 438 struct auacer_softc *sc; 439 uint32_t reg; 440 int i; 441 442 sc = v; 443 i = 0; 444 reg = READ4(sc, ALI_SCR); 445 if ((reg & 2) == 0) /* Cold required */ 446 reg |= 2; 447 else 448 reg |= 1; /* Warm */ 449 reg &= ~0x80000000; /* ACLink on */ 450 WRITE4(sc, ALI_SCR, reg); 451 452 while (i < 10) { 453 if ((READ4(sc, ALI_INTERRUPTSR) & ALI_INT_GPIO) == 0) 454 break; 455 delay(50000); /* XXX */ 456 i++; 457 } 458 if (i == 10) { 459 return EIO; 460 } 461 462 for (i = 0; i < 10; i++) { 463 reg = READ4(sc, ALI_RTSR); 464 if (reg & 0x80) /* primary codec */ 465 break; 466 WRITE4(sc, ALI_RTSR, reg | 0x80); 467 delay(50000); /* XXX */ 468 } 469 470 return 0; 471 } 472 473 static void 474 auacer_reset(struct auacer_softc *sc) 475 { 476 WRITE4(sc, ALI_SCR, ALI_SCR_RESET); 477 WRITE4(sc, ALI_FIFOCR1, 0x83838383); 478 WRITE4(sc, ALI_FIFOCR2, 0x83838383); 479 WRITE4(sc, ALI_FIFOCR3, 0x83838383); 480 WRITE4(sc, ALI_INTERFACECR, ALI_IF_PO); /* XXX pcm out only */ 481 WRITE4(sc, ALI_INTERRUPTCR, 0x00000000); 482 WRITE4(sc, ALI_INTERRUPTSR, 0x00000000); 483 } 484 485 static int 486 auacer_query_encoding(void *v, struct audio_encoding *aep) 487 { 488 struct auacer_softc *sc; 489 490 DPRINTF(ALI_DEBUG_API, ("auacer_query_encoding\n")); 491 sc = v; 492 return auconv_query_encoding(sc->sc_encodings, aep); 493 } 494 495 static int 496 auacer_set_rate(struct auacer_softc *sc, int mode, u_int srate) 497 { 498 int ret; 499 u_int ratetmp; 500 501 DPRINTF(ALI_DEBUG_API, ("auacer_set_rate: srate=%u\n", srate)); 502 503 ratetmp = srate; 504 if (mode == AUMODE_RECORD) 505 return sc->codec_if->vtbl->set_rate(sc->codec_if, 506 AC97_REG_PCM_LR_ADC_RATE, &ratetmp); 507 ret = sc->codec_if->vtbl->set_rate(sc->codec_if, 508 AC97_REG_PCM_FRONT_DAC_RATE, &ratetmp); 509 if (ret) 510 return ret; 511 ratetmp = srate; 512 ret = sc->codec_if->vtbl->set_rate(sc->codec_if, 513 AC97_REG_PCM_SURR_DAC_RATE, &ratetmp); 514 if (ret) 515 return ret; 516 ratetmp = srate; 517 ret = sc->codec_if->vtbl->set_rate(sc->codec_if, 518 AC97_REG_PCM_LFE_DAC_RATE, &ratetmp); 519 return ret; 520 } 521 522 static int 523 auacer_set_params(void *v, int setmode, int usemode, 524 audio_params_t *play, audio_params_t *rec, stream_filter_list_t *pfil, 525 stream_filter_list_t *rfil) 526 { 527 struct auacer_softc *sc; 528 struct audio_params *p; 529 stream_filter_list_t *fil; 530 uint32_t control; 531 int mode, index; 532 533 DPRINTF(ALI_DEBUG_API, ("auacer_set_params\n")); 534 sc = v; 535 for (mode = AUMODE_RECORD; mode != -1; 536 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) { 537 if ((setmode & mode) == 0) 538 continue; 539 540 p = mode == AUMODE_PLAY ? play : rec; 541 if (p == NULL) 542 continue; 543 544 if ((p->sample_rate != 8000) && 545 (p->sample_rate != 11025) && 546 (p->sample_rate != 12000) && 547 (p->sample_rate != 16000) && 548 (p->sample_rate != 22050) && 549 (p->sample_rate != 24000) && 550 (p->sample_rate != 32000) && 551 (p->sample_rate != 44100) && 552 (p->sample_rate != 48000)) 553 return (EINVAL); 554 555 fil = mode == AUMODE_PLAY ? pfil : rfil; 556 index = auconv_set_converter(sc->sc_formats, AUACER_NFORMATS, 557 mode, p, TRUE, fil); 558 if (index < 0) 559 return EINVAL; 560 if (fil->req_size > 0) 561 p = &fil->filters[0].param; 562 /* p points HW encoding */ 563 if (sc->sc_formats[index].frequency_type != 1 564 && auacer_set_rate(sc, mode, p->sample_rate)) 565 return EINVAL; 566 if (mode == AUMODE_PLAY) { 567 control = READ4(sc, ALI_SCR); 568 control &= ~ALI_SCR_PCM_246_MASK; 569 if (p->channels == 4) 570 control |= ALI_SCR_PCM_4; 571 else if (p->channels == 6) 572 control |= ALI_SCR_PCM_6; 573 WRITE4(sc, ALI_SCR, control); 574 } 575 } 576 577 return (0); 578 } 579 580 static int 581 auacer_round_blocksize(void *v, int blk, int mode, 582 const audio_params_t *param) 583 { 584 585 return blk & ~0x3f; /* keep good alignment */ 586 } 587 588 static void 589 auacer_halt(struct auacer_softc *sc, struct auacer_chan *chan) 590 { 591 uint32_t val; 592 uint8_t port; 593 uint32_t slot; 594 595 port = chan->port; 596 DPRINTF(ALI_DEBUG_API, ("auacer_halt: port=0x%x\n", port)); 597 chan->intr = 0; 598 599 slot = ALI_PORT2SLOT(port); 600 601 val = READ4(sc, ALI_DMACR); 602 val |= 1 << (slot+16); /* pause */ 603 val &= ~(1 << slot); /* no start */ 604 WRITE4(sc, ALI_DMACR, val); 605 WRITE1(sc, port + ALI_OFF_CR, 0); 606 while (READ1(sc, port + ALI_OFF_CR)) 607 ; 608 /* reset whole DMA things */ 609 WRITE1(sc, port + ALI_OFF_CR, ALI_CR_RR); 610 /* clear interrupts */ 611 WRITE1(sc, port + ALI_OFF_SR, READ1(sc, port+ALI_OFF_SR) | ALI_SR_W1TC); 612 WRITE4(sc, ALI_INTERRUPTSR, ALI_PORT2INTR(port)); 613 } 614 615 static int 616 auacer_halt_output(void *v) 617 { 618 struct auacer_softc *sc; 619 620 DPRINTF(ALI_DEBUG_DMA, ("auacer_halt_output\n")); 621 sc = v; 622 auacer_halt(sc, &sc->sc_pcmo); 623 624 return 0; 625 } 626 627 static int 628 auacer_halt_input(void *v) 629 { 630 DPRINTF(ALI_DEBUG_DMA, ("auacer_halt_input\n")); 631 632 return 0; 633 } 634 635 static int 636 auacer_getdev(void *v, struct audio_device *adp) 637 { 638 struct auacer_softc *sc; 639 640 DPRINTF(ALI_DEBUG_API, ("auacer_getdev\n")); 641 sc = v; 642 *adp = sc->sc_audev; 643 return 0; 644 } 645 646 static int 647 auacer_set_port(void *v, mixer_ctrl_t *cp) 648 { 649 struct auacer_softc *sc; 650 651 DPRINTF(ALI_DEBUG_MIXERAPI, ("auacer_set_port\n")); 652 sc = v; 653 return sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp); 654 } 655 656 static int 657 auacer_get_port(void *v, mixer_ctrl_t *cp) 658 { 659 struct auacer_softc *sc; 660 661 DPRINTF(ALI_DEBUG_MIXERAPI, ("auacer_get_port\n")); 662 sc = v; 663 return sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp); 664 } 665 666 static int 667 auacer_query_devinfo(void *v, mixer_devinfo_t *dp) 668 { 669 struct auacer_softc *sc; 670 671 DPRINTF(ALI_DEBUG_MIXERAPI, ("auacer_query_devinfo\n")); 672 sc = v; 673 return sc->codec_if->vtbl->query_devinfo(sc->codec_if, dp); 674 } 675 676 static void * 677 auacer_allocm(void *v, int direction, size_t size, 678 struct malloc_type *pool, int flags) 679 { 680 struct auacer_softc *sc; 681 struct auacer_dma *p; 682 int error; 683 684 if (size > (ALI_DMALIST_MAX * ALI_DMASEG_MAX)) 685 return NULL; 686 687 p = malloc(sizeof(*p), pool, flags | M_ZERO); 688 if (p == NULL) 689 return NULL; 690 sc = v; 691 error = auacer_allocmem(sc, size, 0, p); 692 if (error) { 693 free(p, pool); 694 return NULL; 695 } 696 697 p->next = sc->sc_dmas; 698 sc->sc_dmas = p; 699 700 return KERNADDR(p); 701 } 702 703 static void 704 auacer_freem(void *v, void *ptr, struct malloc_type *pool) 705 { 706 struct auacer_softc *sc; 707 struct auacer_dma *p, **pp; 708 709 sc = v; 710 for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) { 711 if (KERNADDR(p) == ptr) { 712 auacer_freemem(sc, p); 713 *pp = p->next; 714 free(p, pool); 715 return; 716 } 717 } 718 } 719 720 static size_t 721 auacer_round_buffersize(void *v, int direction, size_t size) 722 { 723 724 if (size > (ALI_DMALIST_MAX * ALI_DMASEG_MAX)) 725 size = ALI_DMALIST_MAX * ALI_DMASEG_MAX; 726 727 return size; 728 } 729 730 static paddr_t 731 auacer_mappage(void *v, void *mem, off_t off, int prot) 732 { 733 struct auacer_softc *sc; 734 struct auacer_dma *p; 735 736 if (off < 0) 737 return -1; 738 sc = v; 739 for (p = sc->sc_dmas; p && KERNADDR(p) != mem; p = p->next) 740 continue; 741 if (p == NULL) 742 return -1; 743 return bus_dmamem_mmap(sc->dmat, p->segs, p->nsegs, 744 off, prot, BUS_DMA_WAITOK); 745 } 746 747 static int 748 auacer_get_props(void *v) 749 { 750 struct auacer_softc *sc; 751 int props; 752 753 sc = v; 754 props = AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX; 755 /* 756 * Even if the codec is fixed-rate, set_param() succeeds for any sample 757 * rate because of aurateconv. Applications can't know what rate the 758 * device can process in the case of mmap(). 759 */ 760 if (!AC97_IS_FIXED_RATE(sc->codec_if)) 761 props |= AUDIO_PROP_MMAP; 762 return props; 763 } 764 765 static void 766 auacer_add_entry(struct auacer_chan *chan) 767 { 768 struct auacer_dmalist *q; 769 770 q = &chan->dmalist[chan->ptr]; 771 772 DPRINTF(ALI_DEBUG_INTR, 773 ("auacer_add_entry: %p = %x @ 0x%x\n", 774 q, chan->blksize / 2, chan->p)); 775 776 q->base = htole32(chan->p); 777 q->len = htole32((chan->blksize / ALI_SAMPLE_SIZE) | ALI_DMAF_IOC); 778 chan->p += chan->blksize; 779 if (chan->p >= chan->end) 780 chan->p = chan->start; 781 782 if (++chan->ptr >= ALI_DMALIST_MAX) 783 chan->ptr = 0; 784 } 785 786 static void 787 auacer_upd_chan(struct auacer_softc *sc, struct auacer_chan *chan) 788 { 789 uint32_t sts; 790 uint32_t civ; 791 792 sts = READ2(sc, chan->port + ALI_OFF_SR); 793 /* intr ack */ 794 WRITE2(sc, chan->port + ALI_OFF_SR, sts & ALI_SR_W1TC); 795 WRITE4(sc, ALI_INTERRUPTSR, ALI_PORT2INTR(chan->port)); 796 797 DPRINTF(ALI_DEBUG_INTR, ("auacer_upd_chan: sts=0x%x\n", sts)); 798 799 if (sts & ALI_SR_DMA_INT_FIFO) { 800 printf("%s: fifo underrun # %u\n", 801 device_xname(&sc->sc_dev), ++chan->fifoe); 802 } 803 804 civ = READ1(sc, chan->port + ALI_OFF_CIV); 805 806 DPRINTF(ALI_DEBUG_INTR,("auacer_intr: civ=%u ptr=%u\n",civ,chan->ptr)); 807 808 /* XXX */ 809 while (chan->ptr != civ) { 810 auacer_add_entry(chan); 811 } 812 813 WRITE1(sc, chan->port + ALI_OFF_LVI, (chan->ptr - 1) & ALI_LVI_MASK); 814 815 while (chan->ack != civ) { 816 if (chan->intr) { 817 DPRINTF(ALI_DEBUG_INTR,("auacer_upd_chan: callback\n")); 818 chan->intr(chan->arg); 819 } 820 chan->ack++; 821 if (chan->ack >= ALI_DMALIST_MAX) 822 chan->ack = 0; 823 } 824 } 825 826 static int 827 auacer_intr(void *v) 828 { 829 struct auacer_softc *sc; 830 int ret, intrs; 831 832 sc = v; 833 intrs = READ4(sc, ALI_INTERRUPTSR); 834 DPRINTF(ALI_DEBUG_INTR, ("auacer_intr: intrs=0x%x\n", intrs)); 835 836 ret = 0; 837 if (intrs & ALI_INT_PCMOUT) { 838 auacer_upd_chan(sc, &sc->sc_pcmo); 839 ret++; 840 } 841 842 return ret != 0; 843 } 844 845 static void 846 auacer_setup_chan(struct auacer_softc *sc, struct auacer_chan *chan, 847 uint32_t start, uint32_t size, uint32_t blksize, 848 void (*intr)(void *), void *arg) 849 { 850 uint32_t port, slot; 851 uint32_t offs, val; 852 853 chan->start = start; 854 chan->ptr = 0; 855 chan->p = chan->start; 856 chan->end = chan->start + size; 857 chan->blksize = blksize; 858 chan->ack = 0; 859 chan->intr = intr; 860 chan->arg = arg; 861 862 auacer_add_entry(chan); 863 auacer_add_entry(chan); 864 865 port = chan->port; 866 slot = ALI_PORT2SLOT(port); 867 868 WRITE1(sc, port + ALI_OFF_CIV, 0); 869 WRITE1(sc, port + ALI_OFF_LVI, (chan->ptr - 1) & ALI_LVI_MASK); 870 offs = (char *)chan->dmalist - (char *)sc->sc_cdata; 871 WRITE4(sc, port + ALI_OFF_BDBAR, sc->sc_cddma + offs); 872 WRITE1(sc, port + ALI_OFF_CR, 873 ALI_CR_IOCE | ALI_CR_FEIE | ALI_CR_LVBIE | ALI_CR_RPBM); 874 val = READ4(sc, ALI_DMACR); 875 val &= ~(1 << (slot+16)); /* no pause */ 876 val |= 1 << slot; /* start */ 877 WRITE4(sc, ALI_DMACR, val); 878 } 879 880 static int 881 auacer_trigger_output(void *v, void *start, void *end, int blksize, 882 void (*intr)(void *), void *arg, const audio_params_t *param) 883 { 884 struct auacer_softc *sc; 885 struct auacer_dma *p; 886 uint32_t size; 887 888 DPRINTF(ALI_DEBUG_DMA, 889 ("auacer_trigger_output(%p, %p, %d, %p, %p, %p)\n", 890 start, end, blksize, intr, arg, param)); 891 sc = v; 892 for (p = sc->sc_dmas; p && KERNADDR(p) != start; p = p->next) 893 continue; 894 if (!p) { 895 printf("auacer_trigger_output: bad addr %p\n", start); 896 return (EINVAL); 897 } 898 899 size = (char *)end - (char *)start; 900 auacer_setup_chan(sc, &sc->sc_pcmo, DMAADDR(p), size, blksize, 901 intr, arg); 902 903 return 0; 904 } 905 906 static int 907 auacer_trigger_input(void *v, void *start, void *end, 908 int blksize, void (*intr)(void *), void *arg, 909 const audio_params_t *param) 910 { 911 return EINVAL; 912 } 913 914 static int 915 auacer_allocmem(struct auacer_softc *sc, size_t size, size_t align, 916 struct auacer_dma *p) 917 { 918 int error; 919 920 p->size = size; 921 error = bus_dmamem_alloc(sc->dmat, p->size, align, 0, 922 p->segs, sizeof(p->segs)/sizeof(p->segs[0]), 923 &p->nsegs, BUS_DMA_NOWAIT); 924 if (error) 925 return error; 926 927 error = bus_dmamem_map(sc->dmat, p->segs, p->nsegs, p->size, 928 &p->addr, BUS_DMA_NOWAIT|sc->sc_dmamap_flags); 929 if (error) 930 goto free; 931 932 error = bus_dmamap_create(sc->dmat, p->size, 1, p->size, 933 0, BUS_DMA_NOWAIT, &p->map); 934 if (error) 935 goto unmap; 936 937 error = bus_dmamap_load(sc->dmat, p->map, p->addr, p->size, NULL, 938 BUS_DMA_NOWAIT); 939 if (error) 940 goto destroy; 941 return (0); 942 943 destroy: 944 bus_dmamap_destroy(sc->dmat, p->map); 945 unmap: 946 bus_dmamem_unmap(sc->dmat, p->addr, p->size); 947 free: 948 bus_dmamem_free(sc->dmat, p->segs, p->nsegs); 949 return error; 950 } 951 952 static int 953 auacer_freemem(struct auacer_softc *sc, struct auacer_dma *p) 954 { 955 956 bus_dmamap_unload(sc->dmat, p->map); 957 bus_dmamap_destroy(sc->dmat, p->map); 958 bus_dmamem_unmap(sc->dmat, p->addr, p->size); 959 bus_dmamem_free(sc->dmat, p->segs, p->nsegs); 960 return 0; 961 } 962 963 static int 964 auacer_alloc_cdata(struct auacer_softc *sc) 965 { 966 bus_dma_segment_t seg; 967 int error, rseg; 968 969 /* 970 * Allocate the control data structure, and create and load the 971 * DMA map for it. 972 */ 973 if ((error = bus_dmamem_alloc(sc->dmat, 974 sizeof(struct auacer_cdata), 975 PAGE_SIZE, 0, &seg, 1, &rseg, 0)) != 0) { 976 aprint_error_dev(&sc->sc_dev, "unable to allocate control data, error = %d\n", 977 error); 978 goto fail_0; 979 } 980 981 if ((error = bus_dmamem_map(sc->dmat, &seg, rseg, 982 sizeof(struct auacer_cdata), 983 (void **) &sc->sc_cdata, 984 sc->sc_dmamap_flags)) != 0) { 985 aprint_error_dev(&sc->sc_dev, "unable to map control data, error = %d\n", 986 error); 987 goto fail_1; 988 } 989 990 if ((error = bus_dmamap_create(sc->dmat, sizeof(struct auacer_cdata), 1, 991 sizeof(struct auacer_cdata), 0, 0, 992 &sc->sc_cddmamap)) != 0) { 993 aprint_error_dev(&sc->sc_dev, "unable to create control data DMA map, " 994 "error = %d\n", error); 995 goto fail_2; 996 } 997 998 if ((error = bus_dmamap_load(sc->dmat, sc->sc_cddmamap, 999 sc->sc_cdata, sizeof(struct auacer_cdata), 1000 NULL, 0)) != 0) { 1001 aprint_error_dev(&sc->sc_dev, "unable to load control data DMA map, " 1002 "error = %d\n", error); 1003 goto fail_3; 1004 } 1005 1006 return 0; 1007 1008 fail_3: 1009 bus_dmamap_destroy(sc->dmat, sc->sc_cddmamap); 1010 fail_2: 1011 bus_dmamem_unmap(sc->dmat, (void *) sc->sc_cdata, 1012 sizeof(struct auacer_cdata)); 1013 fail_1: 1014 bus_dmamem_free(sc->dmat, &seg, rseg); 1015 fail_0: 1016 return error; 1017 } 1018 1019 static bool 1020 auacer_resume(device_t dv PMF_FN_ARGS) 1021 { 1022 struct auacer_softc *sc = device_private(dv); 1023 1024 auacer_reset_codec(sc); 1025 delay(1000); 1026 sc->codec_if->vtbl->restore_ports(sc->codec_if); 1027 1028 return true; 1029 } 1030