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
aoa_dma_set_program(struct aoa_dma * dma)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 *
aoa_dma_create(struct aoa_softc * sc)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
aoa_dma_delete(struct aoa_dma * dma)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
aoa_chan_setblocksize(kobj_t obj,void * data,u_int32_t blocksz)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
aoa_chan_setformat(kobj_t obj,void * data,u_int32_t format)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
aoa_chan_setspeed(kobj_t obj,void * data,u_int32_t speed)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
aoa_chan_getptr(kobj_t obj,void * data)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 *
aoa_chan_init(kobj_t obj,void * devinfo,struct snd_dbuf * b,struct pcm_channel * c,int dir)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
aoa_chan_trigger(kobj_t obj,void * data,int go)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
aoa_chan_free(kobj_t obj,void * data)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
aoa_interrupt(void * xsc)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 *
aoa_chan_getcaps(kobj_t obj,void * data)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
aoa_attach(void * xsc)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