18486eb86SNathan Whitehorn /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 3718cf2ccSPedro F. Giffuni * 48486eb86SNathan Whitehorn * Copyright 2008 by Marco Trillo. All rights reserved. 58486eb86SNathan Whitehorn * 68486eb86SNathan Whitehorn * Redistribution and use in source and binary forms, with or without 78486eb86SNathan Whitehorn * modification, are permitted provided that the following conditions 88486eb86SNathan Whitehorn * are met: 98486eb86SNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 108486eb86SNathan Whitehorn * notice, this list of conditions and the following disclaimer. 118486eb86SNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 128486eb86SNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 138486eb86SNathan Whitehorn * documentation and/or other materials provided with the distribution. 148486eb86SNathan Whitehorn * 158486eb86SNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 168486eb86SNathan Whitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 178486eb86SNathan Whitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 188486eb86SNathan Whitehorn * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 198486eb86SNathan Whitehorn * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 208486eb86SNathan Whitehorn * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 218486eb86SNathan Whitehorn * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 228486eb86SNathan Whitehorn * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 238486eb86SNathan Whitehorn * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 248486eb86SNathan Whitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 258486eb86SNathan Whitehorn * SUCH DAMAGE. 268486eb86SNathan Whitehorn */ 278486eb86SNathan Whitehorn 288486eb86SNathan Whitehorn /* 298486eb86SNathan Whitehorn * Apple Onboard Audio (AOA). 308486eb86SNathan Whitehorn */ 318486eb86SNathan Whitehorn 328486eb86SNathan Whitehorn #include <sys/cdefs.h> 338486eb86SNathan Whitehorn 348486eb86SNathan Whitehorn #include <sys/param.h> 358486eb86SNathan Whitehorn #include <sys/systm.h> 368486eb86SNathan Whitehorn #include <sys/kernel.h> 378486eb86SNathan Whitehorn #include <sys/bus.h> 388486eb86SNathan Whitehorn #include <sys/malloc.h> 398486eb86SNathan Whitehorn #include <sys/lock.h> 408486eb86SNathan Whitehorn #include <sys/mutex.h> 418486eb86SNathan Whitehorn #include <machine/dbdma.h> 428486eb86SNathan Whitehorn #include <machine/resource.h> 438486eb86SNathan Whitehorn #include <machine/bus.h> 448486eb86SNathan Whitehorn #include <sys/rman.h> 458486eb86SNathan Whitehorn #include <dev/ofw/ofw_bus.h> 4690da2b28SAriff Abdullah 4790da2b28SAriff Abdullah #ifdef HAVE_KERNEL_OPTION_HEADERS 4890da2b28SAriff Abdullah #include "opt_snd.h" 4990da2b28SAriff Abdullah #endif 5090da2b28SAriff Abdullah 518486eb86SNathan Whitehorn #include <dev/sound/pcm/sound.h> 528486eb86SNathan Whitehorn #include <dev/sound/macio/aoa.h> 5390da2b28SAriff Abdullah 548486eb86SNathan Whitehorn #include "mixer_if.h" 558486eb86SNathan Whitehorn 568486eb86SNathan Whitehorn struct aoa_dma { 578486eb86SNathan Whitehorn struct mtx mutex; 588486eb86SNathan Whitehorn struct resource *reg; /* DBDMA registers */ 598486eb86SNathan Whitehorn dbdma_channel_t *channel; /* DBDMA channel */ 608486eb86SNathan Whitehorn bus_dma_tag_t tag; /* bus_dma tag */ 618486eb86SNathan Whitehorn struct pcm_channel *pcm; /* PCM channel */ 628486eb86SNathan Whitehorn struct snd_dbuf *buf; /* PCM buffer */ 638486eb86SNathan Whitehorn u_int slots; /* # of slots */ 648486eb86SNathan Whitehorn u_int slot; /* current slot */ 658486eb86SNathan Whitehorn u_int bufsz; /* buffer size */ 668486eb86SNathan Whitehorn u_int blksz; /* block size */ 678486eb86SNathan Whitehorn int running; 688486eb86SNathan Whitehorn }; 698486eb86SNathan Whitehorn 708486eb86SNathan Whitehorn static void 718486eb86SNathan Whitehorn aoa_dma_set_program(struct aoa_dma *dma) 728486eb86SNathan Whitehorn { 738486eb86SNathan Whitehorn u_int32_t addr; 748486eb86SNathan Whitehorn int i; 758486eb86SNathan Whitehorn 768486eb86SNathan Whitehorn addr = (u_int32_t) sndbuf_getbufaddr(dma->buf); 778486eb86SNathan Whitehorn KASSERT(dma->bufsz == sndbuf_getsize(dma->buf), ("bad size")); 788486eb86SNathan Whitehorn 798486eb86SNathan Whitehorn dma->slots = dma->bufsz / dma->blksz; 808486eb86SNathan Whitehorn 818486eb86SNathan Whitehorn for (i = 0; i < dma->slots; ++i) { 828486eb86SNathan Whitehorn dbdma_insert_command(dma->channel, 838486eb86SNathan Whitehorn i, /* slot */ 848486eb86SNathan Whitehorn DBDMA_OUTPUT_MORE, /* command */ 858486eb86SNathan Whitehorn 0, /* stream */ 868486eb86SNathan Whitehorn addr, /* data */ 878486eb86SNathan Whitehorn dma->blksz, /* count */ 888486eb86SNathan Whitehorn DBDMA_ALWAYS, /* interrupt */ 898486eb86SNathan Whitehorn DBDMA_COND_TRUE, /* branch */ 908486eb86SNathan Whitehorn DBDMA_NEVER, /* wait */ 918486eb86SNathan Whitehorn dma->slots + 1 /* branch_slot */ 928486eb86SNathan Whitehorn ); 938486eb86SNathan Whitehorn 948486eb86SNathan Whitehorn addr += dma->blksz; 958486eb86SNathan Whitehorn } 968486eb86SNathan Whitehorn 978486eb86SNathan Whitehorn /* Branch back to beginning. */ 988486eb86SNathan Whitehorn dbdma_insert_branch(dma->channel, dma->slots, 0); 998486eb86SNathan Whitehorn 1008486eb86SNathan Whitehorn /* STOP command to branch when S0 is asserted. */ 1018486eb86SNathan Whitehorn dbdma_insert_stop(dma->channel, dma->slots + 1); 1028486eb86SNathan Whitehorn 1038486eb86SNathan Whitehorn /* Set S0 as the condition to branch to STOP. */ 1048486eb86SNathan Whitehorn dbdma_set_branch_selector(dma->channel, 1 << 0, 1 << 0); 1058486eb86SNathan Whitehorn dbdma_set_device_status(dma->channel, 1 << 0, 0); 1068486eb86SNathan Whitehorn 1078486eb86SNathan Whitehorn dbdma_sync_commands(dma->channel, BUS_DMASYNC_PREWRITE); 1088486eb86SNathan Whitehorn } 1098486eb86SNathan Whitehorn 1108486eb86SNathan Whitehorn #define AOA_BUFFER_SIZE 65536 1118486eb86SNathan Whitehorn 1128486eb86SNathan Whitehorn static struct aoa_dma * 1139772bc0bSNathan Whitehorn aoa_dma_create(struct aoa_softc *sc) 1148486eb86SNathan Whitehorn { 1158486eb86SNathan Whitehorn struct aoa_dma *dma; 1168486eb86SNathan Whitehorn bus_dma_tag_t tag; 1178486eb86SNathan Whitehorn int err; 1189772bc0bSNathan Whitehorn device_t self; 1198486eb86SNathan Whitehorn 1209772bc0bSNathan Whitehorn self = sc->sc_dev; 1218486eb86SNathan Whitehorn err = bus_dma_tag_create(bus_get_dma_tag(self), 1228486eb86SNathan Whitehorn 4, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 1238486eb86SNathan Whitehorn AOA_BUFFER_SIZE, 1, AOA_BUFFER_SIZE, 0, NULL, NULL, &tag); 1248486eb86SNathan Whitehorn if (err != 0) 1258486eb86SNathan Whitehorn return (NULL); 1268486eb86SNathan Whitehorn 1278486eb86SNathan Whitehorn dma = malloc(sizeof(*dma), M_DEVBUF, M_WAITOK | M_ZERO); 1288486eb86SNathan Whitehorn dma->tag = tag; 1298486eb86SNathan Whitehorn dma->bufsz = AOA_BUFFER_SIZE; 1308486eb86SNathan Whitehorn dma->blksz = PAGE_SIZE; /* initial blocksize */ 1318486eb86SNathan Whitehorn 1328486eb86SNathan Whitehorn mtx_init(&dma->mutex, "AOA", NULL, MTX_DEF); 1338486eb86SNathan Whitehorn 1348486eb86SNathan Whitehorn sc->sc_intrp = dma; 1358486eb86SNathan Whitehorn 1368486eb86SNathan Whitehorn return (dma); 1378486eb86SNathan Whitehorn } 1388486eb86SNathan Whitehorn 1398486eb86SNathan Whitehorn static void 1408486eb86SNathan Whitehorn aoa_dma_delete(struct aoa_dma *dma) 1418486eb86SNathan Whitehorn { 1428486eb86SNathan Whitehorn bus_dma_tag_destroy(dma->tag); 1438486eb86SNathan Whitehorn mtx_destroy(&dma->mutex); 1448486eb86SNathan Whitehorn free(dma, M_DEVBUF); 1458486eb86SNathan Whitehorn } 1468486eb86SNathan Whitehorn 14790da2b28SAriff Abdullah static u_int32_t 1488486eb86SNathan Whitehorn aoa_chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksz) 1498486eb86SNathan Whitehorn { 1508486eb86SNathan Whitehorn struct aoa_dma *dma = data; 1518486eb86SNathan Whitehorn int err, lz; 1528486eb86SNathan Whitehorn 1538486eb86SNathan Whitehorn DPRINTF(("aoa_chan_setblocksize: blocksz = %u, dma->blksz = %u\n", 1548486eb86SNathan Whitehorn blocksz, dma->blksz)); 1558486eb86SNathan Whitehorn KASSERT(!dma->running, ("dma is running")); 1568486eb86SNathan Whitehorn KASSERT(blocksz > 0, ("bad blocksz")); 1578486eb86SNathan Whitehorn 1588486eb86SNathan Whitehorn /* Round blocksz down to a power of two... */ 1598486eb86SNathan Whitehorn __asm volatile ("cntlzw %0,%1" : "=r"(lz) : "r"(blocksz)); 1608486eb86SNathan Whitehorn blocksz = 1 << (31 - lz); 1618486eb86SNathan Whitehorn DPRINTF(("blocksz = %u\n", blocksz)); 1628486eb86SNathan Whitehorn 1638486eb86SNathan Whitehorn /* ...but no more than the buffer. */ 1648486eb86SNathan Whitehorn if (blocksz > dma->bufsz) 1658486eb86SNathan Whitehorn blocksz = dma->bufsz; 1668486eb86SNathan Whitehorn 1678486eb86SNathan Whitehorn err = sndbuf_resize(dma->buf, dma->bufsz / blocksz, blocksz); 1688486eb86SNathan Whitehorn if (err != 0) { 1698486eb86SNathan Whitehorn DPRINTF(("sndbuf_resize returned %d\n", err)); 1708486eb86SNathan Whitehorn return (0); 1718486eb86SNathan Whitehorn } 1728486eb86SNathan Whitehorn 1738486eb86SNathan Whitehorn if (blocksz == dma->blksz) 1748486eb86SNathan Whitehorn return (dma->blksz); 1758486eb86SNathan Whitehorn 1768486eb86SNathan Whitehorn /* One slot per block plus branch to 0 plus STOP. */ 1778486eb86SNathan Whitehorn err = dbdma_resize_channel(dma->channel, 2 + dma->bufsz / blocksz); 1788486eb86SNathan Whitehorn if (err != 0) { 1798486eb86SNathan Whitehorn DPRINTF(("dbdma_resize_channel returned %d\n", err)); 1808486eb86SNathan Whitehorn return (0); 1818486eb86SNathan Whitehorn } 1828486eb86SNathan Whitehorn 1838486eb86SNathan Whitehorn /* Set the new blocksize. */ 1848486eb86SNathan Whitehorn dma->blksz = blocksz; 1858486eb86SNathan Whitehorn aoa_dma_set_program(dma); 1868486eb86SNathan Whitehorn 1878486eb86SNathan Whitehorn return (dma->blksz); 1888486eb86SNathan Whitehorn } 1898486eb86SNathan Whitehorn 1908486eb86SNathan Whitehorn static int 1918486eb86SNathan Whitehorn aoa_chan_setformat(kobj_t obj, void *data, u_int32_t format) 1928486eb86SNathan Whitehorn { 1938486eb86SNathan Whitehorn DPRINTF(("aoa_chan_setformat: format = %u\n", format)); 1948486eb86SNathan Whitehorn 19590da2b28SAriff Abdullah if (format != SND_FORMAT(AFMT_S16_BE, 2, 0)) 1968486eb86SNathan Whitehorn return (EINVAL); 1978486eb86SNathan Whitehorn 1988486eb86SNathan Whitehorn return (0); 1998486eb86SNathan Whitehorn } 2008486eb86SNathan Whitehorn 20190da2b28SAriff Abdullah static u_int32_t 2028486eb86SNathan Whitehorn aoa_chan_setspeed(kobj_t obj, void *data, u_int32_t speed) 2038486eb86SNathan Whitehorn { 2048486eb86SNathan Whitehorn DPRINTF(("aoa_chan_setspeed: speed = %u\n", speed)); 2058486eb86SNathan Whitehorn 2068486eb86SNathan Whitehorn return (44100); 2078486eb86SNathan Whitehorn } 2088486eb86SNathan Whitehorn 20990da2b28SAriff Abdullah static u_int32_t 2108486eb86SNathan Whitehorn aoa_chan_getptr(kobj_t obj, void *data) 2118486eb86SNathan Whitehorn { 2128486eb86SNathan Whitehorn struct aoa_dma *dma = data; 2138486eb86SNathan Whitehorn 2148486eb86SNathan Whitehorn if (!dma->running) 2158486eb86SNathan Whitehorn return (0); 2168486eb86SNathan Whitehorn 2178486eb86SNathan Whitehorn return (dma->slot * dma->blksz); 2188486eb86SNathan Whitehorn } 2198486eb86SNathan Whitehorn 2208486eb86SNathan Whitehorn static void * 2218486eb86SNathan Whitehorn aoa_chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, 2228486eb86SNathan Whitehorn struct pcm_channel *c, int dir) 2238486eb86SNathan Whitehorn { 2249772bc0bSNathan Whitehorn struct aoa_softc *sc = devinfo; 2258486eb86SNathan Whitehorn struct aoa_dma *dma; 2268486eb86SNathan Whitehorn int max_slots, err; 2278486eb86SNathan Whitehorn 2288486eb86SNathan Whitehorn KASSERT(dir == PCMDIR_PLAY, ("bad dir")); 2298486eb86SNathan Whitehorn 2309772bc0bSNathan Whitehorn dma = aoa_dma_create(sc); 2318486eb86SNathan Whitehorn if (!dma) 2328486eb86SNathan Whitehorn return (NULL); 2338486eb86SNathan Whitehorn dma->pcm = c; 2348486eb86SNathan Whitehorn dma->buf = b; 2358486eb86SNathan Whitehorn dma->reg = sc->sc_odma; 2368486eb86SNathan Whitehorn 2378486eb86SNathan Whitehorn /* One slot per block, plus branch to 0 plus STOP. */ 2388486eb86SNathan Whitehorn max_slots = 2 + dma->bufsz / dma->blksz; 2399772bc0bSNathan Whitehorn err = dbdma_allocate_channel(dma->reg, 0, bus_get_dma_tag(sc->sc_dev), 2408486eb86SNathan Whitehorn max_slots, &dma->channel ); 2418486eb86SNathan Whitehorn if (err != 0) { 2428486eb86SNathan Whitehorn aoa_dma_delete(dma); 2438486eb86SNathan Whitehorn return (NULL); 2448486eb86SNathan Whitehorn } 2458486eb86SNathan Whitehorn 2468486eb86SNathan Whitehorn if (sndbuf_alloc(dma->buf, dma->tag, 0, dma->bufsz) != 0) { 2478486eb86SNathan Whitehorn dbdma_free_channel(dma->channel); 2488486eb86SNathan Whitehorn aoa_dma_delete(dma); 2498486eb86SNathan Whitehorn return (NULL); 2508486eb86SNathan Whitehorn } 2518486eb86SNathan Whitehorn 2528486eb86SNathan Whitehorn aoa_dma_set_program(dma); 2538486eb86SNathan Whitehorn 2548486eb86SNathan Whitehorn return (dma); 2558486eb86SNathan Whitehorn } 2568486eb86SNathan Whitehorn 2578486eb86SNathan Whitehorn static int 2588486eb86SNathan Whitehorn aoa_chan_trigger(kobj_t obj, void *data, int go) 2598486eb86SNathan Whitehorn { 2608486eb86SNathan Whitehorn struct aoa_dma *dma = data; 2618486eb86SNathan Whitehorn int i; 2628486eb86SNathan Whitehorn 2638486eb86SNathan Whitehorn switch (go) { 2648486eb86SNathan Whitehorn case PCMTRIG_START: 2658486eb86SNathan Whitehorn 2668486eb86SNathan Whitehorn /* Start the DMA. */ 2678486eb86SNathan Whitehorn dma->running = 1; 2688486eb86SNathan Whitehorn 2698486eb86SNathan Whitehorn dma->slot = 0; 2708486eb86SNathan Whitehorn dbdma_set_current_cmd(dma->channel, dma->slot); 2718486eb86SNathan Whitehorn 2728486eb86SNathan Whitehorn dbdma_run(dma->channel); 2738486eb86SNathan Whitehorn 2748486eb86SNathan Whitehorn return (0); 2758486eb86SNathan Whitehorn 2768486eb86SNathan Whitehorn case PCMTRIG_STOP: 2778486eb86SNathan Whitehorn case PCMTRIG_ABORT: 2788486eb86SNathan Whitehorn 2798486eb86SNathan Whitehorn mtx_lock(&dma->mutex); 2808486eb86SNathan Whitehorn 2818486eb86SNathan Whitehorn dma->running = 0; 2828486eb86SNathan Whitehorn 2838486eb86SNathan Whitehorn /* Make it branch to the STOP command. */ 2848486eb86SNathan Whitehorn dbdma_set_device_status(dma->channel, 1 << 0, 1 << 0); 2858486eb86SNathan Whitehorn 2868486eb86SNathan Whitehorn /* XXX should wait for DBDMA_ACTIVE to clear. */ 2878486eb86SNathan Whitehorn DELAY(40000); 2888486eb86SNathan Whitehorn 2898486eb86SNathan Whitehorn /* Reset the DMA. */ 2908486eb86SNathan Whitehorn dbdma_stop(dma->channel); 2918486eb86SNathan Whitehorn dbdma_set_device_status(dma->channel, 1 << 0, 0); 2928486eb86SNathan Whitehorn 2938486eb86SNathan Whitehorn for (i = 0; i < dma->slots; ++i) 2948486eb86SNathan Whitehorn dbdma_clear_cmd_status(dma->channel, i); 2958486eb86SNathan Whitehorn 2968486eb86SNathan Whitehorn mtx_unlock(&dma->mutex); 2978486eb86SNathan Whitehorn 2988486eb86SNathan Whitehorn return (0); 2998486eb86SNathan Whitehorn } 3008486eb86SNathan Whitehorn 3018486eb86SNathan Whitehorn return (0); 3028486eb86SNathan Whitehorn } 3038486eb86SNathan Whitehorn 3048486eb86SNathan Whitehorn static int 3058486eb86SNathan Whitehorn aoa_chan_free(kobj_t obj, void *data) 3068486eb86SNathan Whitehorn { 3078486eb86SNathan Whitehorn struct aoa_dma *dma = data; 3088486eb86SNathan Whitehorn 3098486eb86SNathan Whitehorn sndbuf_free(dma->buf); 3108486eb86SNathan Whitehorn dbdma_free_channel(dma->channel); 3118486eb86SNathan Whitehorn aoa_dma_delete(dma); 3128486eb86SNathan Whitehorn 3138486eb86SNathan Whitehorn return (0); 3148486eb86SNathan Whitehorn } 3158486eb86SNathan Whitehorn 3168486eb86SNathan Whitehorn void 3179772bc0bSNathan Whitehorn aoa_interrupt(void *xsc) 3188486eb86SNathan Whitehorn { 3199772bc0bSNathan Whitehorn struct aoa_softc *sc = xsc; 3208486eb86SNathan Whitehorn struct aoa_dma *dma; 3218486eb86SNathan Whitehorn 3228486eb86SNathan Whitehorn if (!(dma = sc->sc_intrp) || !dma->running) 3238486eb86SNathan Whitehorn return; 3248486eb86SNathan Whitehorn 3258486eb86SNathan Whitehorn mtx_lock(&dma->mutex); 3268486eb86SNathan Whitehorn 3278486eb86SNathan Whitehorn while (dbdma_get_cmd_status(dma->channel, dma->slot)) { 3288486eb86SNathan Whitehorn dbdma_clear_cmd_status(dma->channel, dma->slot); 3298486eb86SNathan Whitehorn dma->slot = (dma->slot + 1) % dma->slots; 3308486eb86SNathan Whitehorn 3318486eb86SNathan Whitehorn mtx_unlock(&dma->mutex); 3328486eb86SNathan Whitehorn chn_intr(dma->pcm); 3338486eb86SNathan Whitehorn mtx_lock(&dma->mutex); 3348486eb86SNathan Whitehorn } 3358486eb86SNathan Whitehorn 3368486eb86SNathan Whitehorn mtx_unlock(&dma->mutex); 3378486eb86SNathan Whitehorn } 3388486eb86SNathan Whitehorn 3398486eb86SNathan Whitehorn static u_int32_t sc_fmt[] = { 34090da2b28SAriff Abdullah SND_FORMAT(AFMT_S16_BE, 2, 0), 3418486eb86SNathan Whitehorn 0 3428486eb86SNathan Whitehorn }; 3438486eb86SNathan Whitehorn static struct pcmchan_caps aoa_caps = {44100, 44100, sc_fmt, 0}; 3448486eb86SNathan Whitehorn 3458486eb86SNathan Whitehorn static struct pcmchan_caps * 3468486eb86SNathan Whitehorn aoa_chan_getcaps(kobj_t obj, void *data) 3478486eb86SNathan Whitehorn { 3488486eb86SNathan Whitehorn return (&aoa_caps); 3498486eb86SNathan Whitehorn } 3508486eb86SNathan Whitehorn 3518486eb86SNathan Whitehorn static kobj_method_t aoa_chan_methods[] = { 3528486eb86SNathan Whitehorn KOBJMETHOD(channel_init, aoa_chan_init), 3538486eb86SNathan Whitehorn KOBJMETHOD(channel_free, aoa_chan_free), 3548486eb86SNathan Whitehorn KOBJMETHOD(channel_setformat, aoa_chan_setformat), 3558486eb86SNathan Whitehorn KOBJMETHOD(channel_setspeed, aoa_chan_setspeed), 3568486eb86SNathan Whitehorn KOBJMETHOD(channel_setblocksize,aoa_chan_setblocksize), 3578486eb86SNathan Whitehorn KOBJMETHOD(channel_trigger, aoa_chan_trigger), 3588486eb86SNathan Whitehorn KOBJMETHOD(channel_getptr, aoa_chan_getptr), 3598486eb86SNathan Whitehorn KOBJMETHOD(channel_getcaps, aoa_chan_getcaps), 36090da2b28SAriff Abdullah KOBJMETHOD_END 3618486eb86SNathan Whitehorn }; 3628486eb86SNathan Whitehorn CHANNEL_DECLARE(aoa_chan); 3638486eb86SNathan Whitehorn 3648486eb86SNathan Whitehorn int 3659772bc0bSNathan Whitehorn aoa_attach(void *xsc) 3668486eb86SNathan Whitehorn { 3678486eb86SNathan Whitehorn char status[SND_STATUSLEN]; 3689772bc0bSNathan Whitehorn struct aoa_softc *sc; 3699772bc0bSNathan Whitehorn device_t self; 370b8ef5a7eSJohn Baldwin int err __unused; 3718486eb86SNathan Whitehorn 3729772bc0bSNathan Whitehorn sc = xsc; 3739772bc0bSNathan Whitehorn self = sc->sc_dev; 3749772bc0bSNathan Whitehorn 375*516a9c02SChristos Margiolis pcm_init(self, sc); 3768486eb86SNathan Whitehorn 3778486eb86SNathan Whitehorn err = pcm_getbuffersize(self, AOA_BUFFER_SIZE, AOA_BUFFER_SIZE, 3788486eb86SNathan Whitehorn AOA_BUFFER_SIZE); 3798486eb86SNathan Whitehorn DPRINTF(("pcm_getbuffersize returned %d\n", err)); 3808486eb86SNathan Whitehorn 3819772bc0bSNathan Whitehorn pcm_addchan(self, PCMDIR_PLAY, &aoa_chan_class, sc); 3828486eb86SNathan Whitehorn 3838486eb86SNathan Whitehorn snprintf(status, sizeof(status), "at %s", ofw_bus_get_name(self)); 3848486eb86SNathan Whitehorn 385*516a9c02SChristos Margiolis return (pcm_register(self, status)); 3868486eb86SNathan Whitehorn } 387