18486eb86SNathan Whitehorn /*- 2718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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 * $FreeBSD$ 288486eb86SNathan Whitehorn */ 298486eb86SNathan Whitehorn 308486eb86SNathan Whitehorn /* 318486eb86SNathan Whitehorn * Apple Onboard Audio (AOA). 328486eb86SNathan Whitehorn */ 338486eb86SNathan Whitehorn 348486eb86SNathan Whitehorn #include <sys/cdefs.h> 358486eb86SNathan Whitehorn 368486eb86SNathan Whitehorn #include <sys/param.h> 378486eb86SNathan Whitehorn #include <sys/systm.h> 388486eb86SNathan Whitehorn #include <sys/kernel.h> 398486eb86SNathan Whitehorn #include <sys/bus.h> 408486eb86SNathan Whitehorn #include <sys/malloc.h> 418486eb86SNathan Whitehorn #include <sys/lock.h> 428486eb86SNathan Whitehorn #include <sys/mutex.h> 438486eb86SNathan Whitehorn #include <machine/dbdma.h> 448486eb86SNathan Whitehorn #include <machine/resource.h> 458486eb86SNathan Whitehorn #include <machine/bus.h> 468486eb86SNathan Whitehorn #include <sys/rman.h> 478486eb86SNathan Whitehorn #include <dev/ofw/ofw_bus.h> 4890da2b28SAriff Abdullah 4990da2b28SAriff Abdullah #ifdef HAVE_KERNEL_OPTION_HEADERS 5090da2b28SAriff Abdullah #include "opt_snd.h" 5190da2b28SAriff Abdullah #endif 5290da2b28SAriff Abdullah 538486eb86SNathan Whitehorn #include <dev/sound/pcm/sound.h> 548486eb86SNathan Whitehorn #include <dev/sound/macio/aoa.h> 5590da2b28SAriff Abdullah 568486eb86SNathan Whitehorn #include "mixer_if.h" 578486eb86SNathan Whitehorn 588486eb86SNathan Whitehorn struct aoa_dma { 598486eb86SNathan Whitehorn struct mtx mutex; 608486eb86SNathan Whitehorn struct resource *reg; /* DBDMA registers */ 618486eb86SNathan Whitehorn dbdma_channel_t *channel; /* DBDMA channel */ 628486eb86SNathan Whitehorn bus_dma_tag_t tag; /* bus_dma tag */ 638486eb86SNathan Whitehorn struct pcm_channel *pcm; /* PCM channel */ 648486eb86SNathan Whitehorn struct snd_dbuf *buf; /* PCM buffer */ 658486eb86SNathan Whitehorn u_int slots; /* # of slots */ 668486eb86SNathan Whitehorn u_int slot; /* current slot */ 678486eb86SNathan Whitehorn u_int bufsz; /* buffer size */ 688486eb86SNathan Whitehorn u_int blksz; /* block size */ 698486eb86SNathan Whitehorn int running; 708486eb86SNathan Whitehorn }; 718486eb86SNathan Whitehorn 728486eb86SNathan Whitehorn static void 738486eb86SNathan Whitehorn aoa_dma_set_program(struct aoa_dma *dma) 748486eb86SNathan Whitehorn { 758486eb86SNathan Whitehorn u_int32_t addr; 768486eb86SNathan Whitehorn int i; 778486eb86SNathan Whitehorn 788486eb86SNathan Whitehorn addr = (u_int32_t) sndbuf_getbufaddr(dma->buf); 798486eb86SNathan Whitehorn KASSERT(dma->bufsz == sndbuf_getsize(dma->buf), ("bad size")); 808486eb86SNathan Whitehorn 818486eb86SNathan Whitehorn dma->slots = dma->bufsz / dma->blksz; 828486eb86SNathan Whitehorn 838486eb86SNathan Whitehorn for (i = 0; i < dma->slots; ++i) { 848486eb86SNathan Whitehorn dbdma_insert_command(dma->channel, 858486eb86SNathan Whitehorn i, /* slot */ 868486eb86SNathan Whitehorn DBDMA_OUTPUT_MORE, /* command */ 878486eb86SNathan Whitehorn 0, /* stream */ 888486eb86SNathan Whitehorn addr, /* data */ 898486eb86SNathan Whitehorn dma->blksz, /* count */ 908486eb86SNathan Whitehorn DBDMA_ALWAYS, /* interrupt */ 918486eb86SNathan Whitehorn DBDMA_COND_TRUE, /* branch */ 928486eb86SNathan Whitehorn DBDMA_NEVER, /* wait */ 938486eb86SNathan Whitehorn dma->slots + 1 /* branch_slot */ 948486eb86SNathan Whitehorn ); 958486eb86SNathan Whitehorn 968486eb86SNathan Whitehorn addr += dma->blksz; 978486eb86SNathan Whitehorn } 988486eb86SNathan Whitehorn 998486eb86SNathan Whitehorn /* Branch back to beginning. */ 1008486eb86SNathan Whitehorn dbdma_insert_branch(dma->channel, dma->slots, 0); 1018486eb86SNathan Whitehorn 1028486eb86SNathan Whitehorn /* STOP command to branch when S0 is asserted. */ 1038486eb86SNathan Whitehorn dbdma_insert_stop(dma->channel, dma->slots + 1); 1048486eb86SNathan Whitehorn 1058486eb86SNathan Whitehorn /* Set S0 as the condition to branch to STOP. */ 1068486eb86SNathan Whitehorn dbdma_set_branch_selector(dma->channel, 1 << 0, 1 << 0); 1078486eb86SNathan Whitehorn dbdma_set_device_status(dma->channel, 1 << 0, 0); 1088486eb86SNathan Whitehorn 1098486eb86SNathan Whitehorn dbdma_sync_commands(dma->channel, BUS_DMASYNC_PREWRITE); 1108486eb86SNathan Whitehorn } 1118486eb86SNathan Whitehorn 1128486eb86SNathan Whitehorn #define AOA_BUFFER_SIZE 65536 1138486eb86SNathan Whitehorn 1148486eb86SNathan Whitehorn static struct aoa_dma * 1159772bc0bSNathan Whitehorn aoa_dma_create(struct aoa_softc *sc) 1168486eb86SNathan Whitehorn { 1178486eb86SNathan Whitehorn struct aoa_dma *dma; 1188486eb86SNathan Whitehorn bus_dma_tag_t tag; 1198486eb86SNathan Whitehorn int err; 1209772bc0bSNathan Whitehorn device_t self; 1218486eb86SNathan Whitehorn 1229772bc0bSNathan Whitehorn self = sc->sc_dev; 1238486eb86SNathan Whitehorn err = bus_dma_tag_create(bus_get_dma_tag(self), 1248486eb86SNathan Whitehorn 4, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 1258486eb86SNathan Whitehorn AOA_BUFFER_SIZE, 1, AOA_BUFFER_SIZE, 0, NULL, NULL, &tag); 1268486eb86SNathan Whitehorn if (err != 0) 1278486eb86SNathan Whitehorn return (NULL); 1288486eb86SNathan Whitehorn 1298486eb86SNathan Whitehorn dma = malloc(sizeof(*dma), M_DEVBUF, M_WAITOK | M_ZERO); 1308486eb86SNathan Whitehorn dma->tag = tag; 1318486eb86SNathan Whitehorn dma->bufsz = AOA_BUFFER_SIZE; 1328486eb86SNathan Whitehorn dma->blksz = PAGE_SIZE; /* initial blocksize */ 1338486eb86SNathan Whitehorn 1348486eb86SNathan Whitehorn mtx_init(&dma->mutex, "AOA", NULL, MTX_DEF); 1358486eb86SNathan Whitehorn 1368486eb86SNathan Whitehorn sc->sc_intrp = dma; 1378486eb86SNathan Whitehorn 1388486eb86SNathan Whitehorn return (dma); 1398486eb86SNathan Whitehorn } 1408486eb86SNathan Whitehorn 1418486eb86SNathan Whitehorn static void 1428486eb86SNathan Whitehorn aoa_dma_delete(struct aoa_dma *dma) 1438486eb86SNathan Whitehorn { 1448486eb86SNathan Whitehorn bus_dma_tag_destroy(dma->tag); 1458486eb86SNathan Whitehorn mtx_destroy(&dma->mutex); 1468486eb86SNathan Whitehorn free(dma, M_DEVBUF); 1478486eb86SNathan Whitehorn } 1488486eb86SNathan Whitehorn 14990da2b28SAriff Abdullah static u_int32_t 1508486eb86SNathan Whitehorn aoa_chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksz) 1518486eb86SNathan Whitehorn { 1528486eb86SNathan Whitehorn struct aoa_dma *dma = data; 1538486eb86SNathan Whitehorn int err, lz; 1548486eb86SNathan Whitehorn 1558486eb86SNathan Whitehorn DPRINTF(("aoa_chan_setblocksize: blocksz = %u, dma->blksz = %u\n", 1568486eb86SNathan Whitehorn blocksz, dma->blksz)); 1578486eb86SNathan Whitehorn KASSERT(!dma->running, ("dma is running")); 1588486eb86SNathan Whitehorn KASSERT(blocksz > 0, ("bad blocksz")); 1598486eb86SNathan Whitehorn 1608486eb86SNathan Whitehorn /* Round blocksz down to a power of two... */ 1618486eb86SNathan Whitehorn __asm volatile ("cntlzw %0,%1" : "=r"(lz) : "r"(blocksz)); 1628486eb86SNathan Whitehorn blocksz = 1 << (31 - lz); 1638486eb86SNathan Whitehorn DPRINTF(("blocksz = %u\n", blocksz)); 1648486eb86SNathan Whitehorn 1658486eb86SNathan Whitehorn /* ...but no more than the buffer. */ 1668486eb86SNathan Whitehorn if (blocksz > dma->bufsz) 1678486eb86SNathan Whitehorn blocksz = dma->bufsz; 1688486eb86SNathan Whitehorn 1698486eb86SNathan Whitehorn err = sndbuf_resize(dma->buf, dma->bufsz / blocksz, blocksz); 1708486eb86SNathan Whitehorn if (err != 0) { 1718486eb86SNathan Whitehorn DPRINTF(("sndbuf_resize returned %d\n", err)); 1728486eb86SNathan Whitehorn return (0); 1738486eb86SNathan Whitehorn } 1748486eb86SNathan Whitehorn 1758486eb86SNathan Whitehorn if (blocksz == dma->blksz) 1768486eb86SNathan Whitehorn return (dma->blksz); 1778486eb86SNathan Whitehorn 1788486eb86SNathan Whitehorn /* One slot per block plus branch to 0 plus STOP. */ 1798486eb86SNathan Whitehorn err = dbdma_resize_channel(dma->channel, 2 + dma->bufsz / blocksz); 1808486eb86SNathan Whitehorn if (err != 0) { 1818486eb86SNathan Whitehorn DPRINTF(("dbdma_resize_channel returned %d\n", err)); 1828486eb86SNathan Whitehorn return (0); 1838486eb86SNathan Whitehorn } 1848486eb86SNathan Whitehorn 1858486eb86SNathan Whitehorn /* Set the new blocksize. */ 1868486eb86SNathan Whitehorn dma->blksz = blocksz; 1878486eb86SNathan Whitehorn aoa_dma_set_program(dma); 1888486eb86SNathan Whitehorn 1898486eb86SNathan Whitehorn return (dma->blksz); 1908486eb86SNathan Whitehorn } 1918486eb86SNathan Whitehorn 1928486eb86SNathan Whitehorn static int 1938486eb86SNathan Whitehorn aoa_chan_setformat(kobj_t obj, void *data, u_int32_t format) 1948486eb86SNathan Whitehorn { 1958486eb86SNathan Whitehorn DPRINTF(("aoa_chan_setformat: format = %u\n", format)); 1968486eb86SNathan Whitehorn 19790da2b28SAriff Abdullah if (format != SND_FORMAT(AFMT_S16_BE, 2, 0)) 1988486eb86SNathan Whitehorn return (EINVAL); 1998486eb86SNathan Whitehorn 2008486eb86SNathan Whitehorn return (0); 2018486eb86SNathan Whitehorn } 2028486eb86SNathan Whitehorn 20390da2b28SAriff Abdullah static u_int32_t 2048486eb86SNathan Whitehorn aoa_chan_setspeed(kobj_t obj, void *data, u_int32_t speed) 2058486eb86SNathan Whitehorn { 2068486eb86SNathan Whitehorn DPRINTF(("aoa_chan_setspeed: speed = %u\n", speed)); 2078486eb86SNathan Whitehorn 2088486eb86SNathan Whitehorn return (44100); 2098486eb86SNathan Whitehorn } 2108486eb86SNathan Whitehorn 21190da2b28SAriff Abdullah static u_int32_t 2128486eb86SNathan Whitehorn aoa_chan_getptr(kobj_t obj, void *data) 2138486eb86SNathan Whitehorn { 2148486eb86SNathan Whitehorn struct aoa_dma *dma = data; 2158486eb86SNathan Whitehorn 2168486eb86SNathan Whitehorn if (!dma->running) 2178486eb86SNathan Whitehorn return (0); 2188486eb86SNathan Whitehorn 2198486eb86SNathan Whitehorn return (dma->slot * dma->blksz); 2208486eb86SNathan Whitehorn } 2218486eb86SNathan Whitehorn 2228486eb86SNathan Whitehorn static void * 2238486eb86SNathan Whitehorn aoa_chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, 2248486eb86SNathan Whitehorn struct pcm_channel *c, int dir) 2258486eb86SNathan Whitehorn { 2269772bc0bSNathan Whitehorn struct aoa_softc *sc = devinfo; 2278486eb86SNathan Whitehorn struct aoa_dma *dma; 2288486eb86SNathan Whitehorn int max_slots, err; 2298486eb86SNathan Whitehorn 2308486eb86SNathan Whitehorn KASSERT(dir == PCMDIR_PLAY, ("bad dir")); 2318486eb86SNathan Whitehorn 2329772bc0bSNathan Whitehorn dma = aoa_dma_create(sc); 2338486eb86SNathan Whitehorn if (!dma) 2348486eb86SNathan Whitehorn return (NULL); 2358486eb86SNathan Whitehorn dma->pcm = c; 2368486eb86SNathan Whitehorn dma->buf = b; 2378486eb86SNathan Whitehorn dma->reg = sc->sc_odma; 2388486eb86SNathan Whitehorn 2398486eb86SNathan Whitehorn /* One slot per block, plus branch to 0 plus STOP. */ 2408486eb86SNathan Whitehorn max_slots = 2 + dma->bufsz / dma->blksz; 2419772bc0bSNathan Whitehorn err = dbdma_allocate_channel(dma->reg, 0, bus_get_dma_tag(sc->sc_dev), 2428486eb86SNathan Whitehorn max_slots, &dma->channel ); 2438486eb86SNathan Whitehorn if (err != 0) { 2448486eb86SNathan Whitehorn aoa_dma_delete(dma); 2458486eb86SNathan Whitehorn return (NULL); 2468486eb86SNathan Whitehorn } 2478486eb86SNathan Whitehorn 2488486eb86SNathan Whitehorn if (sndbuf_alloc(dma->buf, dma->tag, 0, dma->bufsz) != 0) { 2498486eb86SNathan Whitehorn dbdma_free_channel(dma->channel); 2508486eb86SNathan Whitehorn aoa_dma_delete(dma); 2518486eb86SNathan Whitehorn return (NULL); 2528486eb86SNathan Whitehorn } 2538486eb86SNathan Whitehorn 2548486eb86SNathan Whitehorn aoa_dma_set_program(dma); 2558486eb86SNathan Whitehorn 2568486eb86SNathan Whitehorn return (dma); 2578486eb86SNathan Whitehorn } 2588486eb86SNathan Whitehorn 2598486eb86SNathan Whitehorn static int 2608486eb86SNathan Whitehorn aoa_chan_trigger(kobj_t obj, void *data, int go) 2618486eb86SNathan Whitehorn { 2628486eb86SNathan Whitehorn struct aoa_dma *dma = data; 2638486eb86SNathan Whitehorn int i; 2648486eb86SNathan Whitehorn 2658486eb86SNathan Whitehorn switch (go) { 2668486eb86SNathan Whitehorn case PCMTRIG_START: 2678486eb86SNathan Whitehorn 2688486eb86SNathan Whitehorn /* Start the DMA. */ 2698486eb86SNathan Whitehorn dma->running = 1; 2708486eb86SNathan Whitehorn 2718486eb86SNathan Whitehorn dma->slot = 0; 2728486eb86SNathan Whitehorn dbdma_set_current_cmd(dma->channel, dma->slot); 2738486eb86SNathan Whitehorn 2748486eb86SNathan Whitehorn dbdma_run(dma->channel); 2758486eb86SNathan Whitehorn 2768486eb86SNathan Whitehorn return (0); 2778486eb86SNathan Whitehorn 2788486eb86SNathan Whitehorn case PCMTRIG_STOP: 2798486eb86SNathan Whitehorn case PCMTRIG_ABORT: 2808486eb86SNathan Whitehorn 2818486eb86SNathan Whitehorn mtx_lock(&dma->mutex); 2828486eb86SNathan Whitehorn 2838486eb86SNathan Whitehorn dma->running = 0; 2848486eb86SNathan Whitehorn 2858486eb86SNathan Whitehorn /* Make it branch to the STOP command. */ 2868486eb86SNathan Whitehorn dbdma_set_device_status(dma->channel, 1 << 0, 1 << 0); 2878486eb86SNathan Whitehorn 2888486eb86SNathan Whitehorn /* XXX should wait for DBDMA_ACTIVE to clear. */ 2898486eb86SNathan Whitehorn DELAY(40000); 2908486eb86SNathan Whitehorn 2918486eb86SNathan Whitehorn /* Reset the DMA. */ 2928486eb86SNathan Whitehorn dbdma_stop(dma->channel); 2938486eb86SNathan Whitehorn dbdma_set_device_status(dma->channel, 1 << 0, 0); 2948486eb86SNathan Whitehorn 2958486eb86SNathan Whitehorn for (i = 0; i < dma->slots; ++i) 2968486eb86SNathan Whitehorn dbdma_clear_cmd_status(dma->channel, i); 2978486eb86SNathan Whitehorn 2988486eb86SNathan Whitehorn mtx_unlock(&dma->mutex); 2998486eb86SNathan Whitehorn 3008486eb86SNathan Whitehorn return (0); 3018486eb86SNathan Whitehorn } 3028486eb86SNathan Whitehorn 3038486eb86SNathan Whitehorn return (0); 3048486eb86SNathan Whitehorn } 3058486eb86SNathan Whitehorn 3068486eb86SNathan Whitehorn static int 3078486eb86SNathan Whitehorn aoa_chan_free(kobj_t obj, void *data) 3088486eb86SNathan Whitehorn { 3098486eb86SNathan Whitehorn struct aoa_dma *dma = data; 3108486eb86SNathan Whitehorn 3118486eb86SNathan Whitehorn sndbuf_free(dma->buf); 3128486eb86SNathan Whitehorn dbdma_free_channel(dma->channel); 3138486eb86SNathan Whitehorn aoa_dma_delete(dma); 3148486eb86SNathan Whitehorn 3158486eb86SNathan Whitehorn return (0); 3168486eb86SNathan Whitehorn } 3178486eb86SNathan Whitehorn 3188486eb86SNathan Whitehorn void 3199772bc0bSNathan Whitehorn aoa_interrupt(void *xsc) 3208486eb86SNathan Whitehorn { 3219772bc0bSNathan Whitehorn struct aoa_softc *sc = xsc; 3228486eb86SNathan Whitehorn struct aoa_dma *dma; 3238486eb86SNathan Whitehorn 3248486eb86SNathan Whitehorn if (!(dma = sc->sc_intrp) || !dma->running) 3258486eb86SNathan Whitehorn return; 3268486eb86SNathan Whitehorn 3278486eb86SNathan Whitehorn mtx_lock(&dma->mutex); 3288486eb86SNathan Whitehorn 3298486eb86SNathan Whitehorn while (dbdma_get_cmd_status(dma->channel, dma->slot)) { 3308486eb86SNathan Whitehorn dbdma_clear_cmd_status(dma->channel, dma->slot); 3318486eb86SNathan Whitehorn dma->slot = (dma->slot + 1) % dma->slots; 3328486eb86SNathan Whitehorn 3338486eb86SNathan Whitehorn mtx_unlock(&dma->mutex); 3348486eb86SNathan Whitehorn chn_intr(dma->pcm); 3358486eb86SNathan Whitehorn mtx_lock(&dma->mutex); 3368486eb86SNathan Whitehorn } 3378486eb86SNathan Whitehorn 3388486eb86SNathan Whitehorn mtx_unlock(&dma->mutex); 3398486eb86SNathan Whitehorn } 3408486eb86SNathan Whitehorn 3418486eb86SNathan Whitehorn static u_int32_t sc_fmt[] = { 34290da2b28SAriff Abdullah SND_FORMAT(AFMT_S16_BE, 2, 0), 3438486eb86SNathan Whitehorn 0 3448486eb86SNathan Whitehorn }; 3458486eb86SNathan Whitehorn static struct pcmchan_caps aoa_caps = {44100, 44100, sc_fmt, 0}; 3468486eb86SNathan Whitehorn 3478486eb86SNathan Whitehorn static struct pcmchan_caps * 3488486eb86SNathan Whitehorn aoa_chan_getcaps(kobj_t obj, void *data) 3498486eb86SNathan Whitehorn { 3508486eb86SNathan Whitehorn return (&aoa_caps); 3518486eb86SNathan Whitehorn } 3528486eb86SNathan Whitehorn 3538486eb86SNathan Whitehorn static kobj_method_t aoa_chan_methods[] = { 3548486eb86SNathan Whitehorn KOBJMETHOD(channel_init, aoa_chan_init), 3558486eb86SNathan Whitehorn KOBJMETHOD(channel_free, aoa_chan_free), 3568486eb86SNathan Whitehorn KOBJMETHOD(channel_setformat, aoa_chan_setformat), 3578486eb86SNathan Whitehorn KOBJMETHOD(channel_setspeed, aoa_chan_setspeed), 3588486eb86SNathan Whitehorn KOBJMETHOD(channel_setblocksize,aoa_chan_setblocksize), 3598486eb86SNathan Whitehorn KOBJMETHOD(channel_trigger, aoa_chan_trigger), 3608486eb86SNathan Whitehorn KOBJMETHOD(channel_getptr, aoa_chan_getptr), 3618486eb86SNathan Whitehorn KOBJMETHOD(channel_getcaps, aoa_chan_getcaps), 36290da2b28SAriff Abdullah KOBJMETHOD_END 3638486eb86SNathan Whitehorn }; 3648486eb86SNathan Whitehorn CHANNEL_DECLARE(aoa_chan); 3658486eb86SNathan Whitehorn 3668486eb86SNathan Whitehorn int 3679772bc0bSNathan Whitehorn aoa_attach(void *xsc) 3688486eb86SNathan Whitehorn { 3698486eb86SNathan Whitehorn char status[SND_STATUSLEN]; 3709772bc0bSNathan Whitehorn struct aoa_softc *sc; 3719772bc0bSNathan Whitehorn device_t self; 372*b8ef5a7eSJohn Baldwin int err __unused; 3738486eb86SNathan Whitehorn 3749772bc0bSNathan Whitehorn sc = xsc; 3759772bc0bSNathan Whitehorn self = sc->sc_dev; 3769772bc0bSNathan Whitehorn 377a808d017SNathan Whitehorn if (pcm_register(self, sc, 1, 0)) 3788486eb86SNathan Whitehorn return (ENXIO); 3798486eb86SNathan Whitehorn 3808486eb86SNathan Whitehorn err = pcm_getbuffersize(self, AOA_BUFFER_SIZE, AOA_BUFFER_SIZE, 3818486eb86SNathan Whitehorn AOA_BUFFER_SIZE); 3828486eb86SNathan Whitehorn DPRINTF(("pcm_getbuffersize returned %d\n", err)); 3838486eb86SNathan Whitehorn 3849772bc0bSNathan Whitehorn pcm_addchan(self, PCMDIR_PLAY, &aoa_chan_class, sc); 3858486eb86SNathan Whitehorn 3868486eb86SNathan Whitehorn snprintf(status, sizeof(status), "at %s", ofw_bus_get_name(self)); 3878486eb86SNathan Whitehorn pcm_setstatus(self, status); 3888486eb86SNathan Whitehorn 3898486eb86SNathan Whitehorn return (0); 3908486eb86SNathan Whitehorn } 391