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