1261982Sbr/*- 2261982Sbr * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com> 3261982Sbr * All rights reserved. 4261982Sbr * 5261982Sbr * Redistribution and use in source and binary forms, with or without 6261982Sbr * modification, are permitted provided that the following conditions 7261982Sbr * are met: 8261982Sbr * 1. Redistributions of source code must retain the above copyright 9261982Sbr * notice, this list of conditions and the following disclaimer. 10261982Sbr * 2. Redistributions in binary form must reproduce the above copyright 11261982Sbr * notice, this list of conditions and the following disclaimer in the 12261982Sbr * documentation and/or other materials provided with the distribution. 13261982Sbr * 14261982Sbr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15261982Sbr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16261982Sbr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17261982Sbr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18261982Sbr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19261982Sbr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20261982Sbr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21261982Sbr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22261982Sbr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23261982Sbr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24261982Sbr * SUCH DAMAGE. 25261982Sbr */ 26261982Sbr 27261982Sbr/* 28261982Sbr * Vybrid Family Synchronous Audio Interface (SAI) 29261982Sbr * Chapter 51, Vybrid Reference Manual, Rev. 5, 07/2013 30261982Sbr */ 31261982Sbr 32261982Sbr#include <sys/cdefs.h> 33261982Sbr__FBSDID("$FreeBSD: releng/11.0/sys/arm/freescale/vybrid/vf_sai.c 297793 2016-04-10 23:07:00Z pfg $"); 34261982Sbr 35261982Sbr#include <sys/param.h> 36261982Sbr#include <sys/systm.h> 37261982Sbr#include <sys/bus.h> 38261982Sbr#include <sys/kernel.h> 39261982Sbr#include <sys/module.h> 40261982Sbr#include <sys/malloc.h> 41261982Sbr#include <sys/rman.h> 42261982Sbr#include <sys/timeet.h> 43261982Sbr#include <sys/timetc.h> 44261982Sbr#include <sys/watchdog.h> 45261982Sbr 46261982Sbr#include <dev/sound/pcm/sound.h> 47261982Sbr#include <dev/sound/chip.h> 48261982Sbr#include <mixer_if.h> 49261982Sbr 50261982Sbr#include <dev/fdt/fdt_common.h> 51261982Sbr#include <dev/ofw/openfirm.h> 52261982Sbr#include <dev/ofw/ofw_bus.h> 53261982Sbr#include <dev/ofw/ofw_bus_subr.h> 54261982Sbr 55261982Sbr#include <machine/bus.h> 56261982Sbr#include <machine/cpu.h> 57261982Sbr#include <machine/intr.h> 58261982Sbr 59261982Sbr#include <arm/freescale/vybrid/vf_common.h> 60261982Sbr#include <arm/freescale/vybrid/vf_dmamux.h> 61261982Sbr#include <arm/freescale/vybrid/vf_edma.h> 62261982Sbr 63261982Sbr#define I2S_TCSR 0x00 /* SAI Transmit Control */ 64261982Sbr#define I2S_TCR1 0x04 /* SAI Transmit Configuration 1 */ 65261982Sbr#define I2S_TCR2 0x08 /* SAI Transmit Configuration 2 */ 66261982Sbr#define I2S_TCR3 0x0C /* SAI Transmit Configuration 3 */ 67261982Sbr#define I2S_TCR4 0x10 /* SAI Transmit Configuration 4 */ 68261982Sbr#define I2S_TCR5 0x14 /* SAI Transmit Configuration 5 */ 69261982Sbr#define I2S_TDR0 0x20 /* SAI Transmit Data */ 70261982Sbr#define I2S_TFR0 0x40 /* SAI Transmit FIFO */ 71261982Sbr#define I2S_TMR 0x60 /* SAI Transmit Mask */ 72261982Sbr#define I2S_RCSR 0x80 /* SAI Receive Control */ 73261982Sbr#define I2S_RCR1 0x84 /* SAI Receive Configuration 1 */ 74261982Sbr#define I2S_RCR2 0x88 /* SAI Receive Configuration 2 */ 75261982Sbr#define I2S_RCR3 0x8C /* SAI Receive Configuration 3 */ 76261982Sbr#define I2S_RCR4 0x90 /* SAI Receive Configuration 4 */ 77261982Sbr#define I2S_RCR5 0x94 /* SAI Receive Configuration 5 */ 78261982Sbr#define I2S_RDR0 0xA0 /* SAI Receive Data */ 79261982Sbr#define I2S_RFR0 0xC0 /* SAI Receive FIFO */ 80261982Sbr#define I2S_RMR 0xE0 /* SAI Receive Mask */ 81261982Sbr 82261982Sbr#define TCR1_TFW_M 0x1f /* Transmit FIFO Watermark Mask */ 83261982Sbr#define TCR1_TFW_S 0 /* Transmit FIFO Watermark Shift */ 84261982Sbr#define TCR2_MSEL_M 0x3 /* MCLK Select Mask*/ 85261982Sbr#define TCR2_MSEL_S 26 /* MCLK Select Shift*/ 86261982Sbr#define TCR2_BCP (1 << 25) /* Bit Clock Polarity */ 87261982Sbr#define TCR2_BCD (1 << 24) /* Bit Clock Direction */ 88261982Sbr#define TCR3_TCE (1 << 16) /* Transmit Channel Enable */ 89261982Sbr#define TCR4_FRSZ_M 0x1f /* Frame size Mask */ 90261982Sbr#define TCR4_FRSZ_S 16 /* Frame size Shift */ 91261982Sbr#define TCR4_SYWD_M 0x1f /* Sync Width Mask */ 92261982Sbr#define TCR4_SYWD_S 8 /* Sync Width Shift */ 93261982Sbr#define TCR4_MF (1 << 4) /* MSB First */ 94261982Sbr#define TCR4_FSE (1 << 3) /* Frame Sync Early */ 95261982Sbr#define TCR4_FSP (1 << 1) /* Frame Sync Polarity Low */ 96261982Sbr#define TCR4_FSD (1 << 0) /* Frame Sync Direction Master */ 97261982Sbr#define TCR5_FBT_M 0x1f /* First Bit Shifted */ 98261982Sbr#define TCR5_FBT_S 8 /* First Bit Shifted */ 99261982Sbr#define TCR5_W0W_M 0x1f /* Word 0 Width */ 100261982Sbr#define TCR5_W0W_S 16 /* Word 0 Width */ 101261982Sbr#define TCR5_WNW_M 0x1f /* Word N Width */ 102261982Sbr#define TCR5_WNW_S 24 /* Word N Width */ 103261982Sbr#define TCSR_TE (1 << 31) /* Transmitter Enable */ 104261982Sbr#define TCSR_BCE (1 << 28) /* Bit Clock Enable */ 105261982Sbr#define TCSR_FRDE (1 << 0) /* FIFO Request DMA Enable */ 106261982Sbr 107261982Sbr#define SAI_NCHANNELS 1 108261982Sbr 109261982Sbrstatic MALLOC_DEFINE(M_SAI, "sai", "sai audio"); 110261982Sbr 111261982Sbrstruct sai_rate { 112261982Sbr uint32_t speed; 113261982Sbr uint32_t div; /* Bit Clock Divide. Division value is (div + 1) * 2. */ 114261982Sbr uint32_t mfi; /* PLL4 Multiplication Factor Integer */ 115261982Sbr uint32_t mfn; /* PLL4 Multiplication Factor Numerator */ 116261982Sbr uint32_t mfd; /* PLL4 Multiplication Factor Denominator */ 117261982Sbr}; 118261982Sbr 119261982Sbr/* 120261982Sbr * Bit clock divider formula 121261982Sbr * (div + 1) * 2 = MCLK/(nch * LRCLK * bits/1000000), 122261982Sbr * where: 123261982Sbr * MCLK - master clock 124261982Sbr * nch - number of channels 125261982Sbr * LRCLK - left right clock 126261982Sbr * e.g. (div + 1) * 2 = 16.9344/(2 * 44100 * 24/1000000) 127261982Sbr * 128261982Sbr * Example for 96khz, 24bit, 18.432 Mhz mclk (192fs) 129261982Sbr * { 96000, 1, 18, 40176000, 93000000 }, 130261982Sbr */ 131261982Sbr 132261982Sbrstatic struct sai_rate rate_map[] = { 133261982Sbr { 44100, 7, 33, 80798400, 93000000 }, /* 33.8688 Mhz */ 134261982Sbr { 96000, 3, 36, 80352000, 93000000 }, /* 36.864 Mhz */ 135261982Sbr { 192000, 1, 36, 80352000, 93000000 }, /* 36.864 Mhz */ 136261982Sbr { 0, 0 }, 137261982Sbr}; 138261982Sbr 139261982Sbrstruct sc_info { 140261982Sbr struct resource *res[2]; 141261982Sbr bus_space_tag_t bst; 142261982Sbr bus_space_handle_t bsh; 143261982Sbr device_t dev; 144261982Sbr struct mtx *lock; 145261982Sbr uint32_t speed; 146261982Sbr uint32_t period; 147261982Sbr void *ih; 148261982Sbr int pos; 149261982Sbr int dma_size; 150261982Sbr bus_dma_tag_t dma_tag; 151261982Sbr bus_dmamap_t dma_map; 152261982Sbr bus_addr_t buf_base_phys; 153261982Sbr uint32_t *buf_base; 154261982Sbr struct tcd_conf *tcd; 155261982Sbr struct sai_rate *sr; 156261982Sbr struct edma_softc *edma_sc; 157261982Sbr int edma_chnum; 158261982Sbr}; 159261982Sbr 160261982Sbr/* Channel registers */ 161261982Sbrstruct sc_chinfo { 162261982Sbr struct snd_dbuf *buffer; 163261982Sbr struct pcm_channel *channel; 164261982Sbr struct sc_pcminfo *parent; 165261982Sbr 166261982Sbr /* Channel information */ 167261982Sbr uint32_t dir; 168261982Sbr uint32_t format; 169261982Sbr 170261982Sbr /* Flags */ 171261982Sbr uint32_t run; 172261982Sbr}; 173261982Sbr 174261982Sbr/* PCM device private data */ 175261982Sbrstruct sc_pcminfo { 176261982Sbr device_t dev; 177261982Sbr uint32_t (*ih) (struct sc_pcminfo *scp); 178261982Sbr uint32_t chnum; 179261982Sbr struct sc_chinfo chan[SAI_NCHANNELS]; 180261982Sbr struct sc_info *sc; 181261982Sbr}; 182261982Sbr 183261982Sbrstatic struct resource_spec sai_spec[] = { 184261982Sbr { SYS_RES_MEMORY, 0, RF_ACTIVE }, 185261982Sbr { SYS_RES_IRQ, 0, RF_ACTIVE }, 186261982Sbr { -1, 0 } 187261982Sbr}; 188261982Sbr 189261982Sbrstatic int setup_dma(struct sc_pcminfo *scp); 190261982Sbrstatic void setup_sai(struct sc_info *); 191261982Sbrstatic void sai_configure_clock(struct sc_info *); 192261982Sbr 193261982Sbr/* 194261982Sbr * Mixer interface. 195261982Sbr */ 196261982Sbr 197261982Sbrstatic int 198261982Sbrsaimixer_init(struct snd_mixer *m) 199261982Sbr{ 200261982Sbr struct sc_pcminfo *scp; 201261982Sbr struct sc_info *sc; 202261982Sbr int mask; 203261982Sbr 204261982Sbr scp = mix_getdevinfo(m); 205261982Sbr sc = scp->sc; 206261982Sbr 207261982Sbr if (sc == NULL) 208261982Sbr return -1; 209261982Sbr 210261982Sbr mask = SOUND_MASK_PCM; 211261982Sbr 212261982Sbr snd_mtxlock(sc->lock); 213261982Sbr pcm_setflags(scp->dev, pcm_getflags(scp->dev) | SD_F_SOFTPCMVOL); 214261982Sbr mix_setdevs(m, mask); 215261982Sbr snd_mtxunlock(sc->lock); 216261982Sbr 217261982Sbr return (0); 218261982Sbr} 219261982Sbr 220261982Sbrstatic int 221261982Sbrsaimixer_set(struct snd_mixer *m, unsigned dev, 222261982Sbr unsigned left, unsigned right) 223261982Sbr{ 224261982Sbr struct sc_pcminfo *scp; 225261982Sbr 226261982Sbr scp = mix_getdevinfo(m); 227261982Sbr 228261982Sbr#if 0 229261982Sbr device_printf(scp->dev, "saimixer_set() %d %d\n", 230261982Sbr left, right); 231261982Sbr#endif 232261982Sbr 233261982Sbr return (0); 234261982Sbr} 235261982Sbr 236261982Sbrstatic kobj_method_t saimixer_methods[] = { 237261982Sbr KOBJMETHOD(mixer_init, saimixer_init), 238261982Sbr KOBJMETHOD(mixer_set, saimixer_set), 239261982Sbr KOBJMETHOD_END 240261982Sbr}; 241261982SbrMIXER_DECLARE(saimixer); 242261982Sbr 243261982Sbr/* 244261982Sbr * Channel interface. 245261982Sbr */ 246261982Sbr 247261982Sbrstatic void * 248261982Sbrsaichan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, 249261982Sbr struct pcm_channel *c, int dir) 250261982Sbr{ 251261982Sbr struct sc_pcminfo *scp; 252261982Sbr struct sc_chinfo *ch; 253261982Sbr struct sc_info *sc; 254261982Sbr 255261982Sbr scp = (struct sc_pcminfo *)devinfo; 256261982Sbr sc = scp->sc; 257261982Sbr 258261982Sbr snd_mtxlock(sc->lock); 259261982Sbr ch = &scp->chan[0]; 260261982Sbr ch->dir = dir; 261261982Sbr ch->run = 0; 262261982Sbr ch->buffer = b; 263261982Sbr ch->channel = c; 264261982Sbr ch->parent = scp; 265261982Sbr snd_mtxunlock(sc->lock); 266261982Sbr 267261982Sbr if (sndbuf_setup(ch->buffer, sc->buf_base, sc->dma_size) != 0) { 268261982Sbr device_printf(scp->dev, "Can't setup sndbuf.\n"); 269261982Sbr return NULL; 270261982Sbr } 271261982Sbr 272261982Sbr return ch; 273261982Sbr} 274261982Sbr 275261982Sbrstatic int 276261982Sbrsaichan_free(kobj_t obj, void *data) 277261982Sbr{ 278261982Sbr struct sc_chinfo *ch = data; 279261982Sbr struct sc_pcminfo *scp = ch->parent; 280261982Sbr struct sc_info *sc = scp->sc; 281261982Sbr 282261982Sbr#if 0 283261982Sbr device_printf(scp->dev, "saichan_free()\n"); 284261982Sbr#endif 285261982Sbr 286261982Sbr snd_mtxlock(sc->lock); 287261982Sbr /* TODO: free channel buffer */ 288261982Sbr snd_mtxunlock(sc->lock); 289261982Sbr 290261982Sbr return (0); 291261982Sbr} 292261982Sbr 293261982Sbrstatic int 294261982Sbrsaichan_setformat(kobj_t obj, void *data, uint32_t format) 295261982Sbr{ 296261982Sbr struct sc_chinfo *ch = data; 297261982Sbr 298261982Sbr ch->format = format; 299261982Sbr 300261982Sbr return (0); 301261982Sbr} 302261982Sbr 303261982Sbrstatic uint32_t 304261982Sbrsaichan_setspeed(kobj_t obj, void *data, uint32_t speed) 305261982Sbr{ 306261982Sbr struct sc_pcminfo *scp; 307261982Sbr struct sc_chinfo *ch; 308261982Sbr struct sai_rate *sr; 309261982Sbr struct sc_info *sc; 310261982Sbr int threshold; 311261982Sbr int i; 312261982Sbr 313261982Sbr ch = data; 314261982Sbr scp = ch->parent; 315261982Sbr sc = scp->sc; 316261982Sbr 317261982Sbr sr = NULL; 318261982Sbr 319261982Sbr /* First look for equal frequency. */ 320261982Sbr for (i = 0; rate_map[i].speed != 0; i++) { 321261982Sbr if (rate_map[i].speed == speed) 322261982Sbr sr = &rate_map[i]; 323261982Sbr } 324261982Sbr 325261982Sbr /* If no match, just find nearest. */ 326261982Sbr if (sr == NULL) { 327261982Sbr for (i = 0; rate_map[i].speed != 0; i++) { 328261982Sbr sr = &rate_map[i]; 329261982Sbr threshold = sr->speed + ((rate_map[i + 1].speed != 0) ? 330261982Sbr ((rate_map[i + 1].speed - sr->speed) >> 1) : 0); 331261982Sbr if (speed < threshold) 332261982Sbr break; 333261982Sbr } 334261982Sbr } 335261982Sbr 336261982Sbr sc->sr = sr; 337261982Sbr 338261982Sbr sai_configure_clock(sc); 339261982Sbr 340261982Sbr return (sr->speed); 341261982Sbr} 342261982Sbr 343261982Sbrstatic void 344261982Sbrsai_configure_clock(struct sc_info *sc) 345261982Sbr{ 346261982Sbr struct sai_rate *sr; 347261982Sbr int reg; 348261982Sbr 349261982Sbr sr = sc->sr; 350261982Sbr 351261982Sbr /* 352261982Sbr * Manual says that TCR/RCR registers must not be 353261982Sbr * altered when TCSR[TE] is set. 354261982Sbr * We ignore it since we have problem sometimes 355261982Sbr * after re-enabling transmitter (DMA goes stall). 356261982Sbr */ 357261982Sbr 358261982Sbr reg = READ4(sc, I2S_TCR2); 359261982Sbr reg &= ~(0xff << 0); 360261982Sbr reg |= (sr->div << 0); 361261982Sbr WRITE4(sc, I2S_TCR2, reg); 362261982Sbr 363261982Sbr pll4_configure_output(sr->mfi, sr->mfn, sr->mfd); 364261982Sbr} 365261982Sbr 366261982Sbrstatic uint32_t 367261982Sbrsaichan_setblocksize(kobj_t obj, void *data, uint32_t blocksize) 368261982Sbr{ 369261982Sbr struct sc_chinfo *ch = data; 370261982Sbr struct sc_pcminfo *scp = ch->parent; 371261982Sbr struct sc_info *sc = scp->sc; 372261982Sbr 373261982Sbr sndbuf_resize(ch->buffer, sc->dma_size / blocksize, blocksize); 374261982Sbr 375261982Sbr sc->period = sndbuf_getblksz(ch->buffer); 376261982Sbr return (sc->period); 377261982Sbr} 378261982Sbr 379261982Sbruint32_t sai_dma_intr(void *arg, int chn); 380261982Sbruint32_t 381261982Sbrsai_dma_intr(void *arg, int chn) 382261982Sbr{ 383261982Sbr struct sc_pcminfo *scp; 384261982Sbr struct sc_chinfo *ch; 385261982Sbr struct sc_info *sc; 386261982Sbr struct tcd_conf *tcd; 387261982Sbr 388261982Sbr scp = arg; 389261982Sbr ch = &scp->chan[0]; 390261982Sbr 391261982Sbr sc = scp->sc; 392261982Sbr tcd = sc->tcd; 393261982Sbr 394261982Sbr sc->pos += (tcd->nbytes * tcd->nmajor); 395261982Sbr if (sc->pos >= sc->dma_size) 396261982Sbr sc->pos -= sc->dma_size; 397261982Sbr 398261987Sbr if (ch->run) 399261987Sbr chn_intr(ch->channel); 400261982Sbr 401261982Sbr return (0); 402261982Sbr} 403261982Sbr 404261982Sbrstatic int 405261982Sbrfind_edma_controller(struct sc_info *sc) 406261982Sbr{ 407261982Sbr struct edma_softc *edma_sc; 408261982Sbr phandle_t node, edma_node; 409261982Sbr int edma_src_transmit; 410261982Sbr int edma_mux_group; 411261982Sbr int edma_device_id; 412261982Sbr device_t edma_dev; 413261982Sbr int dts_value; 414261982Sbr int len; 415261982Sbr int i; 416261982Sbr 417261982Sbr if ((node = ofw_bus_get_node(sc->dev)) == -1) 418261982Sbr return (ENXIO); 419261982Sbr 420261982Sbr if ((len = OF_getproplen(node, "edma-controller")) <= 0) 421261982Sbr return (ENXIO); 422261982Sbr if ((len = OF_getproplen(node, "edma-src-transmit")) <= 0) 423261982Sbr return (ENXIO); 424261982Sbr if ((len = OF_getproplen(node, "edma-mux-group")) <= 0) 425261982Sbr return (ENXIO); 426261982Sbr 427261982Sbr OF_getprop(node, "edma-src-transmit", &dts_value, len); 428261982Sbr edma_src_transmit = fdt32_to_cpu(dts_value); 429261982Sbr OF_getprop(node, "edma-mux-group", &dts_value, len); 430261982Sbr edma_mux_group = fdt32_to_cpu(dts_value); 431261982Sbr OF_getprop(node, "edma-controller", &dts_value, len); 432270945Sian edma_node = OF_node_from_xref(fdt32_to_cpu(dts_value)); 433261982Sbr 434261982Sbr if ((len = OF_getproplen(edma_node, "device-id")) <= 0) { 435261982Sbr return (ENXIO); 436297793Spfg } 437261982Sbr 438261982Sbr OF_getprop(edma_node, "device-id", &dts_value, len); 439261982Sbr edma_device_id = fdt32_to_cpu(dts_value); 440261982Sbr 441261982Sbr edma_sc = NULL; 442261982Sbr 443261982Sbr for (i = 0; i < EDMA_NUM_DEVICES; i++) { 444261982Sbr edma_dev = devclass_get_device(devclass_find("edma"), i); 445261982Sbr if (edma_dev) { 446261982Sbr edma_sc = device_get_softc(edma_dev); 447261982Sbr if (edma_sc->device_id == edma_device_id) { 448261982Sbr /* found */ 449261982Sbr break; 450297793Spfg } 451261982Sbr 452261982Sbr edma_sc = NULL; 453297793Spfg } 454297793Spfg } 455261982Sbr 456261982Sbr if (edma_sc == NULL) { 457261982Sbr device_printf(sc->dev, "no eDMA. can't operate\n"); 458261982Sbr return (ENXIO); 459297793Spfg } 460261982Sbr 461261982Sbr sc->edma_sc = edma_sc; 462261982Sbr 463261982Sbr sc->edma_chnum = edma_sc->channel_configure(edma_sc, edma_mux_group, 464261982Sbr edma_src_transmit); 465261982Sbr if (sc->edma_chnum < 0) { 466261982Sbr /* cant setup eDMA */ 467261982Sbr return (ENXIO); 468297793Spfg } 469261982Sbr 470261982Sbr return (0); 471261982Sbr}; 472261982Sbr 473261982Sbrstatic int 474261982Sbrsetup_dma(struct sc_pcminfo *scp) 475261982Sbr{ 476261982Sbr struct tcd_conf *tcd; 477261982Sbr struct sc_info *sc; 478261982Sbr 479261982Sbr sc = scp->sc; 480261982Sbr 481261982Sbr tcd = malloc(sizeof(struct tcd_conf), M_DEVBUF, M_WAITOK | M_ZERO); 482261982Sbr tcd->channel = sc->edma_chnum; 483261982Sbr tcd->ih = sai_dma_intr; 484261982Sbr tcd->ih_user = scp; 485261982Sbr tcd->saddr = sc->buf_base_phys; 486261982Sbr tcd->daddr = rman_get_start(sc->res[0]) + I2S_TDR0; 487261982Sbr 488261982Sbr /* 489261982Sbr * Bytes to transfer per each minor loop. 490261982Sbr * Hardware FIFO buffer size is 32x32bits. 491261982Sbr */ 492261982Sbr tcd->nbytes = 64; 493261982Sbr 494261982Sbr tcd->nmajor = 512; 495261987Sbr tcd->smod = 17; /* dma_size range */ 496261982Sbr tcd->dmod = 0; 497261982Sbr tcd->esg = 0; 498261982Sbr tcd->soff = 0x4; 499261982Sbr tcd->doff = 0; 500261982Sbr tcd->ssize = 0x2; 501261982Sbr tcd->dsize = 0x2; 502261982Sbr tcd->slast = 0; 503261982Sbr tcd->dlast_sga = 0; 504261982Sbr 505261982Sbr sc->tcd = tcd; 506261982Sbr 507261982Sbr sc->edma_sc->dma_setup(sc->edma_sc, sc->tcd); 508261982Sbr 509261982Sbr return (0); 510261982Sbr} 511261982Sbr 512261982Sbrstatic int 513261982Sbrsaichan_trigger(kobj_t obj, void *data, int go) 514261982Sbr{ 515261982Sbr struct sc_chinfo *ch = data; 516261982Sbr struct sc_pcminfo *scp = ch->parent; 517261982Sbr struct sc_info *sc = scp->sc; 518261982Sbr 519261982Sbr snd_mtxlock(sc->lock); 520261982Sbr 521261982Sbr switch (go) { 522261982Sbr case PCMTRIG_START: 523261982Sbr#if 0 524261982Sbr device_printf(scp->dev, "trigger start\n"); 525261982Sbr#endif 526261987Sbr ch->run = 1; 527261982Sbr break; 528261982Sbr 529261982Sbr case PCMTRIG_STOP: 530261982Sbr case PCMTRIG_ABORT: 531261982Sbr#if 0 532261982Sbr device_printf(scp->dev, "trigger stop or abort\n"); 533261982Sbr#endif 534261987Sbr ch->run = 0; 535261982Sbr break; 536261982Sbr } 537261982Sbr 538261982Sbr snd_mtxunlock(sc->lock); 539261982Sbr 540261982Sbr return (0); 541261982Sbr} 542261982Sbr 543261982Sbrstatic uint32_t 544261982Sbrsaichan_getptr(kobj_t obj, void *data) 545261982Sbr{ 546261982Sbr struct sc_pcminfo *scp; 547261982Sbr struct sc_chinfo *ch; 548261982Sbr struct sc_info *sc; 549261982Sbr 550261982Sbr ch = data; 551261982Sbr scp = ch->parent; 552261982Sbr sc = scp->sc; 553261982Sbr 554261982Sbr return (sc->pos); 555261982Sbr} 556261982Sbr 557261982Sbrstatic uint32_t sai_pfmt[] = { 558261982Sbr /* 559261982Sbr * eDMA doesn't allow 24-bit coping, 560261982Sbr * so we use 32. 561261982Sbr */ 562261982Sbr SND_FORMAT(AFMT_S32_LE, 2, 0), 563261982Sbr 0 564261982Sbr}; 565261982Sbr 566261982Sbrstatic struct pcmchan_caps sai_pcaps = {44100, 192000, sai_pfmt, 0}; 567261982Sbr 568261982Sbrstatic struct pcmchan_caps * 569261982Sbrsaichan_getcaps(kobj_t obj, void *data) 570261982Sbr{ 571261982Sbr 572261982Sbr return (&sai_pcaps); 573261982Sbr} 574261982Sbr 575261982Sbrstatic kobj_method_t saichan_methods[] = { 576261982Sbr KOBJMETHOD(channel_init, saichan_init), 577261982Sbr KOBJMETHOD(channel_free, saichan_free), 578261982Sbr KOBJMETHOD(channel_setformat, saichan_setformat), 579261982Sbr KOBJMETHOD(channel_setspeed, saichan_setspeed), 580261982Sbr KOBJMETHOD(channel_setblocksize, saichan_setblocksize), 581261982Sbr KOBJMETHOD(channel_trigger, saichan_trigger), 582261982Sbr KOBJMETHOD(channel_getptr, saichan_getptr), 583261982Sbr KOBJMETHOD(channel_getcaps, saichan_getcaps), 584261982Sbr KOBJMETHOD_END 585261982Sbr}; 586261982SbrCHANNEL_DECLARE(saichan); 587261982Sbr 588261982Sbrstatic int 589261982Sbrsai_probe(device_t dev) 590261982Sbr{ 591261982Sbr 592261982Sbr if (!ofw_bus_status_okay(dev)) 593261982Sbr return (ENXIO); 594261982Sbr 595261982Sbr if (!ofw_bus_is_compatible(dev, "fsl,mvf600-sai")) 596261982Sbr return (ENXIO); 597261982Sbr 598261982Sbr device_set_desc(dev, "Vybrid Family Synchronous Audio Interface"); 599261982Sbr return (BUS_PROBE_DEFAULT); 600261982Sbr} 601261982Sbr 602261982Sbrstatic void 603261982Sbrsai_intr(void *arg) 604261982Sbr{ 605261982Sbr struct sc_pcminfo *scp; 606261982Sbr struct sc_info *sc; 607261982Sbr 608261982Sbr scp = arg; 609261982Sbr sc = scp->sc; 610261982Sbr 611261982Sbr device_printf(sc->dev, "Error I2S_TCSR == 0x%08x\n", 612261982Sbr READ4(sc, I2S_TCSR)); 613261982Sbr} 614261982Sbr 615261982Sbrstatic void 616261982Sbrsetup_sai(struct sc_info *sc) 617261982Sbr{ 618261982Sbr int reg; 619261982Sbr 620261982Sbr /* 621261982Sbr * TCR/RCR registers must not be altered when TCSR[TE] is set. 622261982Sbr */ 623261982Sbr 624261982Sbr reg = READ4(sc, I2S_TCSR); 625261982Sbr reg &= ~(TCSR_BCE | TCSR_TE | TCSR_FRDE); 626261982Sbr WRITE4(sc, I2S_TCSR, reg); 627261982Sbr 628261982Sbr reg = READ4(sc, I2S_TCR3); 629261982Sbr reg &= ~(TCR3_TCE); 630261982Sbr WRITE4(sc, I2S_TCR3, reg); 631261982Sbr 632261982Sbr reg = (64 << TCR1_TFW_S); 633261982Sbr WRITE4(sc, I2S_TCR1, reg); 634261982Sbr 635261982Sbr reg = READ4(sc, I2S_TCR2); 636261982Sbr reg &= ~(TCR2_MSEL_M << TCR2_MSEL_S); 637261982Sbr reg |= (1 << TCR2_MSEL_S); 638261982Sbr reg |= (TCR2_BCP | TCR2_BCD); 639261982Sbr WRITE4(sc, I2S_TCR2, reg); 640261982Sbr 641261982Sbr sai_configure_clock(sc); 642261982Sbr 643261982Sbr reg = READ4(sc, I2S_TCR3); 644261982Sbr reg |= (TCR3_TCE); 645261982Sbr WRITE4(sc, I2S_TCR3, reg); 646261982Sbr 647261982Sbr /* Configure to 32-bit I2S mode */ 648261982Sbr reg = READ4(sc, I2S_TCR4); 649261982Sbr reg &= ~(TCR4_FRSZ_M << TCR4_FRSZ_S); 650261982Sbr reg |= (1 << TCR4_FRSZ_S); /* 2 words per frame */ 651261982Sbr reg &= ~(TCR4_SYWD_M << TCR4_SYWD_S); 652261982Sbr reg |= (23 << TCR4_SYWD_S); 653261982Sbr reg |= (TCR4_MF | TCR4_FSE | TCR4_FSP | TCR4_FSD); 654261982Sbr WRITE4(sc, I2S_TCR4, reg); 655261982Sbr 656261982Sbr reg = READ4(sc, I2S_TCR5); 657261982Sbr reg &= ~(TCR5_W0W_M << TCR5_W0W_S); 658261982Sbr reg |= (23 << TCR5_W0W_S); 659261982Sbr reg &= ~(TCR5_WNW_M << TCR5_WNW_S); 660261982Sbr reg |= (23 << TCR5_WNW_S); 661261982Sbr reg &= ~(TCR5_FBT_M << TCR5_FBT_S); 662261982Sbr reg |= (31 << TCR5_FBT_S); 663261982Sbr WRITE4(sc, I2S_TCR5, reg); 664261982Sbr 665261982Sbr /* Enable transmitter */ 666261982Sbr reg = READ4(sc, I2S_TCSR); 667261982Sbr reg |= (TCSR_BCE | TCSR_TE | TCSR_FRDE); 668261982Sbr reg |= (1 << 10); /* FEIE */ 669261982Sbr WRITE4(sc, I2S_TCSR, reg); 670261982Sbr} 671261982Sbr 672261982Sbr 673261982Sbrstatic void 674261982Sbrsai_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err) 675261982Sbr{ 676261982Sbr bus_addr_t *addr; 677261982Sbr 678261982Sbr if (err) 679261982Sbr return; 680261982Sbr 681261982Sbr addr = (bus_addr_t*)arg; 682261982Sbr *addr = segs[0].ds_addr; 683261982Sbr} 684261982Sbr 685261982Sbrstatic int 686261982Sbrsai_attach(device_t dev) 687261982Sbr{ 688261982Sbr char status[SND_STATUSLEN]; 689261982Sbr struct sc_pcminfo *scp; 690261982Sbr struct sc_info *sc; 691261982Sbr int err; 692261982Sbr 693261982Sbr sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO); 694261982Sbr sc->dev = dev; 695261982Sbr sc->sr = &rate_map[0]; 696261982Sbr sc->pos = 0; 697261982Sbr 698261982Sbr sc->lock = snd_mtxcreate(device_get_nameunit(dev), "sai softc"); 699261982Sbr if (sc->lock == NULL) { 700261982Sbr device_printf(dev, "Cant create mtx\n"); 701261982Sbr return (ENXIO); 702261982Sbr } 703261982Sbr 704261982Sbr if (bus_alloc_resources(dev, sai_spec, sc->res)) { 705261982Sbr device_printf(dev, "could not allocate resources\n"); 706261982Sbr return (ENXIO); 707261982Sbr } 708261982Sbr 709261982Sbr /* Memory interface */ 710261982Sbr sc->bst = rman_get_bustag(sc->res[0]); 711261982Sbr sc->bsh = rman_get_bushandle(sc->res[0]); 712261982Sbr 713261982Sbr /* eDMA */ 714261982Sbr if (find_edma_controller(sc)) { 715261982Sbr device_printf(dev, "could not find active eDMA\n"); 716261982Sbr return (ENXIO); 717261982Sbr } 718261982Sbr 719261982Sbr /* Setup PCM */ 720261982Sbr scp = malloc(sizeof(struct sc_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO); 721261982Sbr scp->sc = sc; 722261982Sbr scp->dev = dev; 723261982Sbr 724261982Sbr /* DMA */ 725261987Sbr sc->dma_size = 131072; 726261982Sbr 727261982Sbr /* 728261982Sbr * Must use dma_size boundary as modulo feature required. 729261982Sbr * Modulo feature allows setup circular buffer. 730261982Sbr */ 731261982Sbr 732261982Sbr err = bus_dma_tag_create( 733261982Sbr bus_get_dma_tag(sc->dev), 734261982Sbr 4, sc->dma_size, /* alignment, boundary */ 735261982Sbr BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 736261982Sbr BUS_SPACE_MAXADDR, /* highaddr */ 737261982Sbr NULL, NULL, /* filter, filterarg */ 738261982Sbr sc->dma_size, 1, /* maxsize, nsegments */ 739261982Sbr sc->dma_size, 0, /* maxsegsize, flags */ 740261982Sbr NULL, NULL, /* lockfunc, lockarg */ 741261982Sbr &sc->dma_tag); 742261982Sbr 743261982Sbr err = bus_dmamem_alloc(sc->dma_tag, (void **)&sc->buf_base, 744261982Sbr BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &sc->dma_map); 745261982Sbr if (err) { 746261982Sbr device_printf(dev, "cannot allocate framebuffer\n"); 747261982Sbr return (ENXIO); 748261982Sbr } 749261982Sbr 750261982Sbr err = bus_dmamap_load(sc->dma_tag, sc->dma_map, sc->buf_base, 751261982Sbr sc->dma_size, sai_dmamap_cb, &sc->buf_base_phys, BUS_DMA_NOWAIT); 752261982Sbr if (err) { 753261982Sbr device_printf(dev, "cannot load DMA map\n"); 754261982Sbr return (ENXIO); 755261982Sbr } 756261982Sbr 757261982Sbr bzero(sc->buf_base, sc->dma_size); 758261982Sbr 759261982Sbr /* Setup interrupt handler */ 760261982Sbr err = bus_setup_intr(dev, sc->res[1], INTR_MPSAFE | INTR_TYPE_AV, 761261982Sbr NULL, sai_intr, scp, &sc->ih); 762261982Sbr if (err) { 763261982Sbr device_printf(dev, "Unable to alloc interrupt resource.\n"); 764261982Sbr return (ENXIO); 765261982Sbr } 766261982Sbr 767261982Sbr pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE); 768261982Sbr 769261982Sbr err = pcm_register(dev, scp, 1, 0); 770261982Sbr if (err) { 771261982Sbr device_printf(dev, "Can't register pcm.\n"); 772261982Sbr return (ENXIO); 773261982Sbr } 774261982Sbr 775261982Sbr scp->chnum = 0; 776261982Sbr pcm_addchan(dev, PCMDIR_PLAY, &saichan_class, scp); 777261982Sbr scp->chnum++; 778261982Sbr 779261982Sbr snprintf(status, SND_STATUSLEN, "at simplebus"); 780261982Sbr pcm_setstatus(dev, status); 781261982Sbr 782261982Sbr mixer_init(dev, &saimixer_class, scp); 783261982Sbr 784261982Sbr setup_dma(scp); 785261982Sbr setup_sai(sc); 786261982Sbr 787261982Sbr return (0); 788261982Sbr} 789261982Sbr 790261982Sbrstatic device_method_t sai_pcm_methods[] = { 791261982Sbr DEVMETHOD(device_probe, sai_probe), 792261982Sbr DEVMETHOD(device_attach, sai_attach), 793261982Sbr { 0, 0 } 794261982Sbr}; 795261982Sbr 796261982Sbrstatic driver_t sai_pcm_driver = { 797261982Sbr "pcm", 798261982Sbr sai_pcm_methods, 799261982Sbr PCM_SOFTC_SIZE, 800261982Sbr}; 801261982Sbr 802261982SbrDRIVER_MODULE(sai, simplebus, sai_pcm_driver, pcm_devclass, 0, 0); 803261982SbrMODULE_DEPEND(sai, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 804261982SbrMODULE_VERSION(sai, 1); 805