xref: /freebsd/sys/dev/sound/macio/aoa.c (revision b8ef5a7ea0c14c7ae995f4905479082edfb6f8aa)
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