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