1/*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com> 5 * 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29/* 30 * Vybrid Family Synchronous Audio Interface (SAI) 31 * Chapter 51, Vybrid Reference Manual, Rev. 5, 07/2013 32 */ 33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/bus.h> 37#include <sys/kernel.h> 38#include <sys/module.h> 39#include <sys/malloc.h> 40#include <sys/rman.h> 41#include <sys/timeet.h> 42#include <sys/timetc.h> 43#include <sys/watchdog.h> 44 45#include <dev/sound/pcm/sound.h> 46#include <mixer_if.h> 47 48#include <dev/ofw/openfirm.h> 49#include <dev/ofw/ofw_bus.h> 50#include <dev/ofw/ofw_bus_subr.h> 51 52#include <machine/bus.h> 53#include <machine/cpu.h> 54#include <machine/intr.h> 55 56#include <arm/freescale/vybrid/vf_common.h> 57#include <arm/freescale/vybrid/vf_dmamux.h> 58#include <arm/freescale/vybrid/vf_edma.h> 59 60#define I2S_TCSR 0x00 /* SAI Transmit Control */ 61#define I2S_TCR1 0x04 /* SAI Transmit Configuration 1 */ 62#define I2S_TCR2 0x08 /* SAI Transmit Configuration 2 */ 63#define I2S_TCR3 0x0C /* SAI Transmit Configuration 3 */ 64#define I2S_TCR4 0x10 /* SAI Transmit Configuration 4 */ 65#define I2S_TCR5 0x14 /* SAI Transmit Configuration 5 */ 66#define I2S_TDR0 0x20 /* SAI Transmit Data */ 67#define I2S_TFR0 0x40 /* SAI Transmit FIFO */ 68#define I2S_TMR 0x60 /* SAI Transmit Mask */ 69#define I2S_RCSR 0x80 /* SAI Receive Control */ 70#define I2S_RCR1 0x84 /* SAI Receive Configuration 1 */ 71#define I2S_RCR2 0x88 /* SAI Receive Configuration 2 */ 72#define I2S_RCR3 0x8C /* SAI Receive Configuration 3 */ 73#define I2S_RCR4 0x90 /* SAI Receive Configuration 4 */ 74#define I2S_RCR5 0x94 /* SAI Receive Configuration 5 */ 75#define I2S_RDR0 0xA0 /* SAI Receive Data */ 76#define I2S_RFR0 0xC0 /* SAI Receive FIFO */ 77#define I2S_RMR 0xE0 /* SAI Receive Mask */ 78 79#define TCR1_TFW_M 0x1f /* Transmit FIFO Watermark Mask */ 80#define TCR1_TFW_S 0 /* Transmit FIFO Watermark Shift */ 81#define TCR2_MSEL_M 0x3 /* MCLK Select Mask*/ 82#define TCR2_MSEL_S 26 /* MCLK Select Shift*/ 83#define TCR2_BCP (1 << 25) /* Bit Clock Polarity */ 84#define TCR2_BCD (1 << 24) /* Bit Clock Direction */ 85#define TCR3_TCE (1 << 16) /* Transmit Channel Enable */ 86#define TCR4_FRSZ_M 0x1f /* Frame size Mask */ 87#define TCR4_FRSZ_S 16 /* Frame size Shift */ 88#define TCR4_SYWD_M 0x1f /* Sync Width Mask */ 89#define TCR4_SYWD_S 8 /* Sync Width Shift */ 90#define TCR4_MF (1 << 4) /* MSB First */ 91#define TCR4_FSE (1 << 3) /* Frame Sync Early */ 92#define TCR4_FSP (1 << 1) /* Frame Sync Polarity Low */ 93#define TCR4_FSD (1 << 0) /* Frame Sync Direction Master */ 94#define TCR5_FBT_M 0x1f /* First Bit Shifted */ 95#define TCR5_FBT_S 8 /* First Bit Shifted */ 96#define TCR5_W0W_M 0x1f /* Word 0 Width */ 97#define TCR5_W0W_S 16 /* Word 0 Width */ 98#define TCR5_WNW_M 0x1f /* Word N Width */ 99#define TCR5_WNW_S 24 /* Word N Width */ 100#define TCSR_TE (1 << 31) /* Transmitter Enable */ 101#define TCSR_BCE (1 << 28) /* Bit Clock Enable */ 102#define TCSR_FRDE (1 << 0) /* FIFO Request DMA Enable */ 103 104#define SAI_NCHANNELS 1 105 106static MALLOC_DEFINE(M_SAI, "sai", "sai audio"); 107 108struct sai_rate { 109 uint32_t speed; 110 uint32_t div; /* Bit Clock Divide. Division value is (div + 1) * 2. */ 111 uint32_t mfi; /* PLL4 Multiplication Factor Integer */ 112 uint32_t mfn; /* PLL4 Multiplication Factor Numerator */ 113 uint32_t mfd; /* PLL4 Multiplication Factor Denominator */ 114}; 115 116/* 117 * Bit clock divider formula 118 * (div + 1) * 2 = MCLK/(nch * LRCLK * bits/1000000), 119 * where: 120 * MCLK - master clock 121 * nch - number of channels 122 * LRCLK - left right clock 123 * e.g. (div + 1) * 2 = 16.9344/(2 * 44100 * 24/1000000) 124 * 125 * Example for 96khz, 24bit, 18.432 Mhz mclk (192fs) 126 * { 96000, 1, 18, 40176000, 93000000 }, 127 */ 128 129static struct sai_rate rate_map[] = { 130 { 44100, 7, 33, 80798400, 93000000 }, /* 33.8688 Mhz */ 131 { 96000, 3, 36, 80352000, 93000000 }, /* 36.864 Mhz */ 132 { 192000, 1, 36, 80352000, 93000000 }, /* 36.864 Mhz */ 133 { 0, 0 }, 134}; 135 136struct sc_info { 137 struct resource *res[2]; 138 bus_space_tag_t bst; 139 bus_space_handle_t bsh; 140 device_t dev; 141 struct mtx *lock; 142 uint32_t speed; 143 uint32_t period; 144 void *ih; 145 int pos; 146 int dma_size; 147 bus_dma_tag_t dma_tag; 148 bus_dmamap_t dma_map; 149 bus_addr_t buf_base_phys; 150 uint32_t *buf_base; 151 struct tcd_conf *tcd; 152 struct sai_rate *sr; 153 struct edma_softc *edma_sc; 154 int edma_chnum; 155}; 156 157/* Channel registers */ 158struct sc_chinfo { 159 struct snd_dbuf *buffer; 160 struct pcm_channel *channel; 161 struct sc_pcminfo *parent; 162 163 /* Channel information */ 164 uint32_t dir; 165 uint32_t format; 166 167 /* Flags */ 168 uint32_t run; 169}; 170 171/* PCM device private data */ 172struct sc_pcminfo { 173 device_t dev; 174 uint32_t (*ih) (struct sc_pcminfo *scp); 175 uint32_t chnum; 176 struct sc_chinfo chan[SAI_NCHANNELS]; 177 struct sc_info *sc; 178}; 179 180static struct resource_spec sai_spec[] = { 181 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 182 { SYS_RES_IRQ, 0, RF_ACTIVE }, 183 { -1, 0 } 184}; 185 186static int setup_dma(struct sc_pcminfo *scp); 187static void setup_sai(struct sc_info *); 188static void sai_configure_clock(struct sc_info *); 189 190/* 191 * Mixer interface. 192 */ 193 194static int 195saimixer_init(struct snd_mixer *m) 196{ 197 struct sc_pcminfo *scp; 198 struct sc_info *sc; 199 int mask; 200 201 scp = mix_getdevinfo(m); 202 sc = scp->sc; 203 204 if (sc == NULL) 205 return -1; 206 207 mask = SOUND_MASK_PCM; 208 209 snd_mtxlock(sc->lock); 210 pcm_setflags(scp->dev, pcm_getflags(scp->dev) | SD_F_SOFTPCMVOL); 211 mix_setdevs(m, mask); 212 snd_mtxunlock(sc->lock); 213 214 return (0); 215} 216 217static int 218saimixer_set(struct snd_mixer *m, unsigned dev, 219 unsigned left, unsigned right) 220{ 221#if 0 222 struct sc_pcminfo *scp; 223 224 scp = mix_getdevinfo(m); 225 226 device_printf(scp->dev, "saimixer_set() %d %d\n", 227 left, right); 228#endif 229 230 return (0); 231} 232 233static kobj_method_t saimixer_methods[] = { 234 KOBJMETHOD(mixer_init, saimixer_init), 235 KOBJMETHOD(mixer_set, saimixer_set), 236 KOBJMETHOD_END 237}; 238MIXER_DECLARE(saimixer); 239 240/* 241 * Channel interface. 242 */ 243 244static void * 245saichan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, 246 struct pcm_channel *c, int dir) 247{ 248 struct sc_pcminfo *scp; 249 struct sc_chinfo *ch; 250 struct sc_info *sc; 251 252 scp = (struct sc_pcminfo *)devinfo; 253 sc = scp->sc; 254 255 snd_mtxlock(sc->lock); 256 ch = &scp->chan[0]; 257 ch->dir = dir; 258 ch->run = 0; 259 ch->buffer = b; 260 ch->channel = c; 261 ch->parent = scp; 262 snd_mtxunlock(sc->lock); 263 264 if (sndbuf_setup(ch->buffer, sc->buf_base, sc->dma_size) != 0) { 265 device_printf(scp->dev, "Can't setup sndbuf.\n"); 266 return NULL; 267 } 268 269 return ch; 270} 271 272static int 273saichan_free(kobj_t obj, void *data) 274{ 275 struct sc_chinfo *ch = data; 276 struct sc_pcminfo *scp = ch->parent; 277 struct sc_info *sc = scp->sc; 278 279#if 0 280 device_printf(scp->dev, "saichan_free()\n"); 281#endif 282 283 snd_mtxlock(sc->lock); 284 /* TODO: free channel buffer */ 285 snd_mtxunlock(sc->lock); 286 287 return (0); 288} 289 290static int 291saichan_setformat(kobj_t obj, void *data, uint32_t format) 292{ 293 struct sc_chinfo *ch = data; 294 295 ch->format = format; 296 297 return (0); 298} 299 300static uint32_t 301saichan_setspeed(kobj_t obj, void *data, uint32_t speed) 302{ 303 struct sc_pcminfo *scp; 304 struct sc_chinfo *ch; 305 struct sai_rate *sr; 306 struct sc_info *sc; 307 int threshold; 308 int i; 309 310 ch = data; 311 scp = ch->parent; 312 sc = scp->sc; 313 314 sr = NULL; 315 316 /* First look for equal frequency. */ 317 for (i = 0; rate_map[i].speed != 0; i++) { 318 if (rate_map[i].speed == speed) 319 sr = &rate_map[i]; 320 } 321 322 /* If no match, just find nearest. */ 323 if (sr == NULL) { 324 for (i = 0; rate_map[i].speed != 0; i++) { 325 sr = &rate_map[i]; 326 threshold = sr->speed + ((rate_map[i + 1].speed != 0) ? 327 ((rate_map[i + 1].speed - sr->speed) >> 1) : 0); 328 if (speed < threshold) 329 break; 330 } 331 } 332 333 sc->sr = sr; 334 335 sai_configure_clock(sc); 336 337 return (sr->speed); 338} 339 340static void 341sai_configure_clock(struct sc_info *sc) 342{ 343 struct sai_rate *sr; 344 int reg; 345 346 sr = sc->sr; 347 348 /* 349 * Manual says that TCR/RCR registers must not be 350 * altered when TCSR[TE] is set. 351 * We ignore it since we have problem sometimes 352 * after re-enabling transmitter (DMA goes stall). 353 */ 354 355 reg = READ4(sc, I2S_TCR2); 356 reg &= ~(0xff << 0); 357 reg |= (sr->div << 0); 358 WRITE4(sc, I2S_TCR2, reg); 359 360 pll4_configure_output(sr->mfi, sr->mfn, sr->mfd); 361} 362 363static uint32_t 364saichan_setblocksize(kobj_t obj, void *data, uint32_t blocksize) 365{ 366 struct sc_chinfo *ch = data; 367 struct sc_pcminfo *scp = ch->parent; 368 struct sc_info *sc = scp->sc; 369 370 sndbuf_resize(ch->buffer, sc->dma_size / blocksize, blocksize); 371 372 sc->period = sndbuf_getblksz(ch->buffer); 373 return (sc->period); 374} 375 376uint32_t sai_dma_intr(void *arg, int chn); 377uint32_t 378sai_dma_intr(void *arg, int chn) 379{ 380 struct sc_pcminfo *scp; 381 struct sc_chinfo *ch; 382 struct sc_info *sc; 383 struct tcd_conf *tcd; 384 385 scp = arg; 386 ch = &scp->chan[0]; 387 388 sc = scp->sc; 389 tcd = sc->tcd; 390 391 sc->pos += (tcd->nbytes * tcd->nmajor); 392 if (sc->pos >= sc->dma_size) 393 sc->pos -= sc->dma_size; 394 395 if (ch->run) 396 chn_intr(ch->channel); 397 398 return (0); 399} 400 401static int 402find_edma_controller(struct sc_info *sc) 403{ 404 struct edma_softc *edma_sc; 405 phandle_t node, edma_node; 406 int edma_src_transmit; 407 int edma_mux_group; 408 int edma_device_id; 409 device_t edma_dev; 410 int dts_value; 411 int len; 412 int i; 413 414 if ((node = ofw_bus_get_node(sc->dev)) == -1) 415 return (ENXIO); 416 417 if ((len = OF_getproplen(node, "edma-controller")) <= 0) 418 return (ENXIO); 419 if ((len = OF_getproplen(node, "edma-src-transmit")) <= 0) 420 return (ENXIO); 421 if ((len = OF_getproplen(node, "edma-mux-group")) <= 0) 422 return (ENXIO); 423 424 OF_getencprop(node, "edma-src-transmit", &dts_value, len); 425 edma_src_transmit = dts_value; 426 OF_getencprop(node, "edma-mux-group", &dts_value, len); 427 edma_mux_group = dts_value; 428 OF_getencprop(node, "edma-controller", &dts_value, len); 429 edma_node = OF_node_from_xref(dts_value); 430 431 if ((len = OF_getproplen(edma_node, "device-id")) <= 0) { 432 return (ENXIO); 433 } 434 435 OF_getencprop(edma_node, "device-id", &dts_value, len); 436 edma_device_id = dts_value; 437 438 edma_sc = NULL; 439 440 for (i = 0; i < EDMA_NUM_DEVICES; i++) { 441 edma_dev = devclass_get_device(devclass_find("edma"), i); 442 if (edma_dev) { 443 edma_sc = device_get_softc(edma_dev); 444 if (edma_sc->device_id == edma_device_id) { 445 /* found */ 446 break; 447 } 448 449 edma_sc = NULL; 450 } 451 } 452 453 if (edma_sc == NULL) { 454 device_printf(sc->dev, "no eDMA. can't operate\n"); 455 return (ENXIO); 456 } 457 458 sc->edma_sc = edma_sc; 459 460 sc->edma_chnum = edma_sc->channel_configure(edma_sc, edma_mux_group, 461 edma_src_transmit); 462 if (sc->edma_chnum < 0) { 463 /* can't setup eDMA */ 464 return (ENXIO); 465 } 466 467 return (0); 468}; 469 470static int 471setup_dma(struct sc_pcminfo *scp) 472{ 473 struct tcd_conf *tcd; 474 struct sc_info *sc; 475 476 sc = scp->sc; 477 478 tcd = malloc(sizeof(struct tcd_conf), M_DEVBUF, M_WAITOK | M_ZERO); 479 tcd->channel = sc->edma_chnum; 480 tcd->ih = sai_dma_intr; 481 tcd->ih_user = scp; 482 tcd->saddr = sc->buf_base_phys; 483 tcd->daddr = rman_get_start(sc->res[0]) + I2S_TDR0; 484 485 /* 486 * Bytes to transfer per each minor loop. 487 * Hardware FIFO buffer size is 32x32bits. 488 */ 489 tcd->nbytes = 64; 490 491 tcd->nmajor = 512; 492 tcd->smod = 17; /* dma_size range */ 493 tcd->dmod = 0; 494 tcd->esg = 0; 495 tcd->soff = 0x4; 496 tcd->doff = 0; 497 tcd->ssize = 0x2; 498 tcd->dsize = 0x2; 499 tcd->slast = 0; 500 tcd->dlast_sga = 0; 501 502 sc->tcd = tcd; 503 504 sc->edma_sc->dma_setup(sc->edma_sc, sc->tcd); 505 506 return (0); 507} 508 509static int 510saichan_trigger(kobj_t obj, void *data, int go) 511{ 512 struct sc_chinfo *ch = data; 513 struct sc_pcminfo *scp = ch->parent; 514 struct sc_info *sc = scp->sc; 515 516 snd_mtxlock(sc->lock); 517 518 switch (go) { 519 case PCMTRIG_START: 520#if 0 521 device_printf(scp->dev, "trigger start\n"); 522#endif 523 ch->run = 1; 524 break; 525 526 case PCMTRIG_STOP: 527 case PCMTRIG_ABORT: 528#if 0 529 device_printf(scp->dev, "trigger stop or abort\n"); 530#endif 531 ch->run = 0; 532 break; 533 } 534 535 snd_mtxunlock(sc->lock); 536 537 return (0); 538} 539 540static uint32_t 541saichan_getptr(kobj_t obj, void *data) 542{ 543 struct sc_pcminfo *scp; 544 struct sc_chinfo *ch; 545 struct sc_info *sc; 546 547 ch = data; 548 scp = ch->parent; 549 sc = scp->sc; 550 551 return (sc->pos); 552} 553 554static uint32_t sai_pfmt[] = { 555 /* 556 * eDMA doesn't allow 24-bit coping, 557 * so we use 32. 558 */ 559 SND_FORMAT(AFMT_S32_LE, 2, 0), 560 0 561}; 562 563static struct pcmchan_caps sai_pcaps = {44100, 192000, sai_pfmt, 0}; 564 565static struct pcmchan_caps * 566saichan_getcaps(kobj_t obj, void *data) 567{ 568 569 return (&sai_pcaps); 570} 571 572static kobj_method_t saichan_methods[] = { 573 KOBJMETHOD(channel_init, saichan_init), 574 KOBJMETHOD(channel_free, saichan_free), 575 KOBJMETHOD(channel_setformat, saichan_setformat), 576 KOBJMETHOD(channel_setspeed, saichan_setspeed), 577 KOBJMETHOD(channel_setblocksize, saichan_setblocksize), 578 KOBJMETHOD(channel_trigger, saichan_trigger), 579 KOBJMETHOD(channel_getptr, saichan_getptr), 580 KOBJMETHOD(channel_getcaps, saichan_getcaps), 581 KOBJMETHOD_END 582}; 583CHANNEL_DECLARE(saichan); 584 585static int 586sai_probe(device_t dev) 587{ 588 589 if (!ofw_bus_status_okay(dev)) 590 return (ENXIO); 591 592 if (!ofw_bus_is_compatible(dev, "fsl,mvf600-sai")) 593 return (ENXIO); 594 595 device_set_desc(dev, "Vybrid Family Synchronous Audio Interface"); 596 return (BUS_PROBE_DEFAULT); 597} 598 599static void 600sai_intr(void *arg) 601{ 602 struct sc_pcminfo *scp; 603 struct sc_info *sc; 604 605 scp = arg; 606 sc = scp->sc; 607 608 device_printf(sc->dev, "Error I2S_TCSR == 0x%08x\n", 609 READ4(sc, I2S_TCSR)); 610} 611 612static void 613setup_sai(struct sc_info *sc) 614{ 615 int reg; 616 617 /* 618 * TCR/RCR registers must not be altered when TCSR[TE] is set. 619 */ 620 621 reg = READ4(sc, I2S_TCSR); 622 reg &= ~(TCSR_BCE | TCSR_TE | TCSR_FRDE); 623 WRITE4(sc, I2S_TCSR, reg); 624 625 reg = READ4(sc, I2S_TCR3); 626 reg &= ~(TCR3_TCE); 627 WRITE4(sc, I2S_TCR3, reg); 628 629 reg = (64 << TCR1_TFW_S); 630 WRITE4(sc, I2S_TCR1, reg); 631 632 reg = READ4(sc, I2S_TCR2); 633 reg &= ~(TCR2_MSEL_M << TCR2_MSEL_S); 634 reg |= (1 << TCR2_MSEL_S); 635 reg |= (TCR2_BCP | TCR2_BCD); 636 WRITE4(sc, I2S_TCR2, reg); 637 638 sai_configure_clock(sc); 639 640 reg = READ4(sc, I2S_TCR3); 641 reg |= (TCR3_TCE); 642 WRITE4(sc, I2S_TCR3, reg); 643 644 /* Configure to 32-bit I2S mode */ 645 reg = READ4(sc, I2S_TCR4); 646 reg &= ~(TCR4_FRSZ_M << TCR4_FRSZ_S); 647 reg |= (1 << TCR4_FRSZ_S); /* 2 words per frame */ 648 reg &= ~(TCR4_SYWD_M << TCR4_SYWD_S); 649 reg |= (23 << TCR4_SYWD_S); 650 reg |= (TCR4_MF | TCR4_FSE | TCR4_FSP | TCR4_FSD); 651 WRITE4(sc, I2S_TCR4, reg); 652 653 reg = READ4(sc, I2S_TCR5); 654 reg &= ~(TCR5_W0W_M << TCR5_W0W_S); 655 reg |= (23 << TCR5_W0W_S); 656 reg &= ~(TCR5_WNW_M << TCR5_WNW_S); 657 reg |= (23 << TCR5_WNW_S); 658 reg &= ~(TCR5_FBT_M << TCR5_FBT_S); 659 reg |= (31 << TCR5_FBT_S); 660 WRITE4(sc, I2S_TCR5, reg); 661 662 /* Enable transmitter */ 663 reg = READ4(sc, I2S_TCSR); 664 reg |= (TCSR_BCE | TCSR_TE | TCSR_FRDE); 665 reg |= (1 << 10); /* FEIE */ 666 WRITE4(sc, I2S_TCSR, reg); 667} 668 669static void 670sai_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err) 671{ 672 bus_addr_t *addr; 673 674 if (err) 675 return; 676 677 addr = (bus_addr_t*)arg; 678 *addr = segs[0].ds_addr; 679} 680 681static int 682sai_attach(device_t dev) 683{ 684 char status[SND_STATUSLEN]; 685 struct sc_pcminfo *scp; 686 struct sc_info *sc; 687 int err; 688 689 sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO); 690 sc->dev = dev; 691 sc->sr = &rate_map[0]; 692 sc->pos = 0; 693 694 sc->lock = snd_mtxcreate(device_get_nameunit(dev), "sai softc"); 695 if (sc->lock == NULL) { 696 device_printf(dev, "Cant create mtx\n"); 697 return (ENXIO); 698 } 699 700 if (bus_alloc_resources(dev, sai_spec, sc->res)) { 701 device_printf(dev, "could not allocate resources\n"); 702 return (ENXIO); 703 } 704 705 /* Memory interface */ 706 sc->bst = rman_get_bustag(sc->res[0]); 707 sc->bsh = rman_get_bushandle(sc->res[0]); 708 709 /* eDMA */ 710 if (find_edma_controller(sc)) { 711 device_printf(dev, "could not find active eDMA\n"); 712 return (ENXIO); 713 } 714 715 /* Setup PCM */ 716 scp = malloc(sizeof(struct sc_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO); 717 scp->sc = sc; 718 scp->dev = dev; 719 720 /* DMA */ 721 sc->dma_size = 131072; 722 723 /* 724 * Must use dma_size boundary as modulo feature required. 725 * Modulo feature allows setup circular buffer. 726 */ 727 728 err = bus_dma_tag_create( 729 bus_get_dma_tag(sc->dev), 730 4, sc->dma_size, /* alignment, boundary */ 731 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 732 BUS_SPACE_MAXADDR, /* highaddr */ 733 NULL, NULL, /* filter, filterarg */ 734 sc->dma_size, 1, /* maxsize, nsegments */ 735 sc->dma_size, 0, /* maxsegsize, flags */ 736 NULL, NULL, /* lockfunc, lockarg */ 737 &sc->dma_tag); 738 739 err = bus_dmamem_alloc(sc->dma_tag, (void **)&sc->buf_base, 740 BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &sc->dma_map); 741 if (err) { 742 device_printf(dev, "cannot allocate framebuffer\n"); 743 return (ENXIO); 744 } 745 746 err = bus_dmamap_load(sc->dma_tag, sc->dma_map, sc->buf_base, 747 sc->dma_size, sai_dmamap_cb, &sc->buf_base_phys, BUS_DMA_NOWAIT); 748 if (err) { 749 device_printf(dev, "cannot load DMA map\n"); 750 return (ENXIO); 751 } 752 753 bzero(sc->buf_base, sc->dma_size); 754 755 /* Setup interrupt handler */ 756 err = bus_setup_intr(dev, sc->res[1], INTR_MPSAFE | INTR_TYPE_AV, 757 NULL, sai_intr, scp, &sc->ih); 758 if (err) { 759 device_printf(dev, "Unable to alloc interrupt resource.\n"); 760 return (ENXIO); 761 } 762 763 pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE); 764 765 err = pcm_register(dev, scp, 1, 0); 766 if (err) { 767 device_printf(dev, "Can't register pcm.\n"); 768 return (ENXIO); 769 } 770 771 scp->chnum = 0; 772 pcm_addchan(dev, PCMDIR_PLAY, &saichan_class, scp); 773 scp->chnum++; 774 775 snprintf(status, SND_STATUSLEN, "at simplebus"); 776 pcm_setstatus(dev, status); 777 778 mixer_init(dev, &saimixer_class, scp); 779 780 setup_dma(scp); 781 setup_sai(sc); 782 783 return (0); 784} 785 786static device_method_t sai_pcm_methods[] = { 787 DEVMETHOD(device_probe, sai_probe), 788 DEVMETHOD(device_attach, sai_attach), 789 { 0, 0 } 790}; 791 792static driver_t sai_pcm_driver = { 793 "pcm", 794 sai_pcm_methods, 795 PCM_SOFTC_SIZE, 796}; 797 798DRIVER_MODULE(sai, simplebus, sai_pcm_driver, 0, 0); 799MODULE_DEPEND(sai, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 800MODULE_VERSION(sai, 1); 801