xref: /openbsd-src/sys/arch/arm64/dev/aplaudio.c (revision ee8269ddb4b2451f6b04c27d348abc5a38574ca8)
1*ee8269ddSkettenis /*	$OpenBSD: aplaudio.c,v 1.6 2023/01/14 23:35:09 kettenis Exp $	*/
27400b107Skettenis /*
37400b107Skettenis  * Copyright (c) 2022 Mark Kettenis <kettenis@openbsd.org>
47400b107Skettenis  * Copyright (c) 2020 Patrick Wildt <patrick@blueri.se>
57400b107Skettenis  *
67400b107Skettenis  * Permission to use, copy, modify, and distribute this software for any
77400b107Skettenis  * purpose with or without fee is hereby granted, provided that the above
87400b107Skettenis  * copyright notice and this permission notice appear in all copies.
97400b107Skettenis  *
107400b107Skettenis  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
117400b107Skettenis  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
127400b107Skettenis  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
137400b107Skettenis  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
147400b107Skettenis  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
157400b107Skettenis  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
167400b107Skettenis  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
177400b107Skettenis  */
187400b107Skettenis 
197400b107Skettenis #include <sys/param.h>
207400b107Skettenis #include <sys/systm.h>
217400b107Skettenis #include <sys/device.h>
227400b107Skettenis #include <sys/malloc.h>
237400b107Skettenis 
247400b107Skettenis #include <machine/bus.h>
257400b107Skettenis #include <machine/fdt.h>
267400b107Skettenis 
277400b107Skettenis #include <dev/ofw/openfirm.h>
287400b107Skettenis #include <dev/ofw/ofw_misc.h>
297400b107Skettenis #include <dev/ofw/fdt.h>
307400b107Skettenis 
317400b107Skettenis #include <sys/audioio.h>
327400b107Skettenis #include <dev/audio_if.h>
337400b107Skettenis 
347400b107Skettenis #include <arm64/dev/aplmca.h>
357400b107Skettenis 
367400b107Skettenis struct aplaudio_softc {
377400b107Skettenis 	struct device		sc_dev;
387400b107Skettenis 
397400b107Skettenis 	struct dai_device	*sc_dai_cpu;
4012e50ba5Skettenis 	struct dai_device	*sc_dai_codec[6];
417400b107Skettenis };
427400b107Skettenis 
437400b107Skettenis void	aplaudio_set_format(struct aplaudio_softc *, uint32_t,
447400b107Skettenis 	    uint32_t, uint32_t);
4512e50ba5Skettenis void	aplaudio_set_tdm_slots(struct aplaudio_softc *);
467400b107Skettenis 
477400b107Skettenis int	aplaudio_open(void *, int);
487400b107Skettenis void	aplaudio_close(void *);
497400b107Skettenis int	aplaudio_set_params(void *, int, int,
507400b107Skettenis 	    struct audio_params *, struct audio_params *);
517400b107Skettenis void	*aplaudio_allocm(void *, int, size_t, int, int);
527400b107Skettenis void	aplaudio_freem(void *, void *, int);
537400b107Skettenis int	aplaudio_set_port(void *, mixer_ctrl_t *);
547400b107Skettenis int	aplaudio_get_port(void *, mixer_ctrl_t *);
557400b107Skettenis int	aplaudio_query_devinfo(void *, mixer_devinfo_t *);
567400b107Skettenis int	aplaudio_round_blocksize(void *, int);
577400b107Skettenis size_t	aplaudio_round_buffersize(void *, int, size_t);
587400b107Skettenis int	aplaudio_trigger_output(void *, void *, void *, int,
597400b107Skettenis 	    void (*)(void *), void *, struct audio_params *);
607400b107Skettenis int	aplaudio_trigger_input(void *, void *, void *, int,
617400b107Skettenis 	    void (*)(void *), void *, struct audio_params *);
627400b107Skettenis int	aplaudio_halt_output(void *);
637400b107Skettenis int	aplaudio_halt_input(void *);
647400b107Skettenis 
657400b107Skettenis const struct audio_hw_if aplaudio_hw_if = {
667400b107Skettenis 	.open = aplaudio_open,
677400b107Skettenis 	.close = aplaudio_close,
687400b107Skettenis 	.set_params = aplaudio_set_params,
697400b107Skettenis 	.allocm = aplaudio_allocm,
707400b107Skettenis 	.freem = aplaudio_freem,
717400b107Skettenis 	.set_port = aplaudio_set_port,
727400b107Skettenis 	.get_port = aplaudio_get_port,
737400b107Skettenis 	.query_devinfo = aplaudio_query_devinfo,
747400b107Skettenis 	.round_blocksize = aplaudio_round_blocksize,
757400b107Skettenis 	.round_buffersize = aplaudio_round_buffersize,
767400b107Skettenis 	.trigger_output = aplaudio_trigger_output,
777400b107Skettenis 	.trigger_input = aplaudio_trigger_input,
787400b107Skettenis 	.halt_output = aplaudio_halt_output,
797400b107Skettenis 	.halt_input = aplaudio_halt_input,
807400b107Skettenis };
817400b107Skettenis 
827400b107Skettenis int	aplaudio_match(struct device *, void *, void *);
837400b107Skettenis void	aplaudio_attach(struct device *, struct device *, void *);
847400b107Skettenis 
857400b107Skettenis const struct cfattach aplaudio_ca = {
867400b107Skettenis 	sizeof (struct aplaudio_softc), aplaudio_match, aplaudio_attach
877400b107Skettenis };
887400b107Skettenis 
897400b107Skettenis struct cfdriver aplaudio_cd = {
907400b107Skettenis 	NULL, "aplaudio", DV_DULL
917400b107Skettenis };
927400b107Skettenis 
937400b107Skettenis int
aplaudio_match(struct device * parent,void * match,void * aux)947400b107Skettenis aplaudio_match(struct device *parent, void *match, void *aux)
957400b107Skettenis {
967400b107Skettenis 	struct fdt_attach_args *faa = aux;
977400b107Skettenis 
987400b107Skettenis 	return OF_is_compatible(faa->fa_node, "apple,macaudio");
997400b107Skettenis }
1007400b107Skettenis 
1017400b107Skettenis void
aplaudio_attach(struct device * parent,struct device * self,void * aux)1027400b107Skettenis aplaudio_attach(struct device *parent, struct device *self, void *aux)
1037400b107Skettenis {
1047400b107Skettenis 	struct aplaudio_softc *sc = (struct aplaudio_softc *)self;
1057400b107Skettenis 	struct fdt_attach_args *faa = aux;
1067400b107Skettenis 	uint32_t fmt, pol, clk;
1077400b107Skettenis 	uint32_t node, cpu, codec;
10812e50ba5Skettenis 	uint32_t *dais;
10946401559Skettenis 	char status[32];
11012e50ba5Skettenis 	int count = 0;
11112e50ba5Skettenis 	int i, ncells;
11212e50ba5Skettenis 	int len;
1137400b107Skettenis 
1147400b107Skettenis 	printf("\n");
1157400b107Skettenis 
1167400b107Skettenis 	for (node = OF_child(faa->fa_node); node; node = OF_peer(node)) {
11746401559Skettenis 		if (OF_getprop(node, "status", status, sizeof(status)) > 0 &&
11846401559Skettenis 		    strcmp(status, "disabled") == 0)
11946401559Skettenis 			continue;
12046401559Skettenis 
1217400b107Skettenis 		cpu = OF_getnodebyname(node, "cpu");
1227400b107Skettenis 		if (cpu == 0)
1237400b107Skettenis 			continue;
1247400b107Skettenis 
1257400b107Skettenis 		sc->sc_dai_cpu = aplmca_alloc_cluster(cpu);
1267400b107Skettenis 		if (sc->sc_dai_cpu == NULL)
1277400b107Skettenis 			continue;
1287400b107Skettenis 
1297400b107Skettenis 		codec = OF_getnodebyname(node, "codec");
1307400b107Skettenis 		if (codec == 0)
1317400b107Skettenis 			continue;
1327400b107Skettenis 
13312e50ba5Skettenis 		len = OF_getproplen(codec, "sound-dai");
13412e50ba5Skettenis 		if (len < 0)
1357400b107Skettenis 			continue;
1367400b107Skettenis 
13712e50ba5Skettenis 		dais = malloc(len, M_TEMP, M_WAITOK);
13812e50ba5Skettenis 		OF_getpropintarray(codec, "sound-dai", dais, len);
13912e50ba5Skettenis 
14012e50ba5Skettenis 		ncells = len / sizeof(uint32_t);
14112e50ba5Skettenis 		ncells = MIN(ncells, nitems(sc->sc_dai_codec));
14212e50ba5Skettenis 		for (i = 0; i < ncells; i++) {
14312e50ba5Skettenis 			sc->sc_dai_codec[i] = dai_byphandle(dais[i]);
14412e50ba5Skettenis 			if (sc->sc_dai_codec[i] == NULL)
14512e50ba5Skettenis 				continue;
14612e50ba5Skettenis 			count++;
14712e50ba5Skettenis 		}
14812e50ba5Skettenis 
14912e50ba5Skettenis 		free(dais, M_TEMP, len);
15012e50ba5Skettenis 
15112e50ba5Skettenis 		if (count == 0)
15212e50ba5Skettenis 			continue;
15312e50ba5Skettenis 		if (count > 1)
15412e50ba5Skettenis 			aplaudio_set_tdm_slots(sc);
15512e50ba5Skettenis 
1567400b107Skettenis 		/* XXX Parameters are missing from the device tree? */
1577400b107Skettenis 		fmt = DAI_FORMAT_LJ;
1587400b107Skettenis 		pol = 0;
1597400b107Skettenis 		clk = DAI_CLOCK_CFM | DAI_CLOCK_CBM;
1607400b107Skettenis 		aplaudio_set_format(sc, fmt, pol, clk);
1617400b107Skettenis 
1627400b107Skettenis 		audio_attach_mi(&aplaudio_hw_if, sc, NULL, self);
1637400b107Skettenis 
1647400b107Skettenis 		/* XXX Only attach the first set of interfaces for now. */
1657400b107Skettenis 		return;
1667400b107Skettenis 	}
1677400b107Skettenis }
1687400b107Skettenis 
1697400b107Skettenis void
aplaudio_set_format(struct aplaudio_softc * sc,uint32_t fmt,uint32_t pol,uint32_t clk)1707400b107Skettenis aplaudio_set_format(struct aplaudio_softc *sc, uint32_t fmt, uint32_t pol,
1717400b107Skettenis     uint32_t clk)
1727400b107Skettenis {
17312e50ba5Skettenis 	struct dai_device *dai;
17412e50ba5Skettenis 	int i;
17512e50ba5Skettenis 
1767400b107Skettenis 	if (sc->sc_dai_cpu->dd_set_format)
1777400b107Skettenis 		sc->sc_dai_cpu->dd_set_format(sc->sc_dai_cpu->dd_cookie,
1787400b107Skettenis 		    fmt, pol, clk);
17912e50ba5Skettenis 	for (i = 0; i < nitems(sc->sc_dai_codec); i++) {
18012e50ba5Skettenis 		dai = sc->sc_dai_codec[i];
18112e50ba5Skettenis 		if (dai == NULL)
18212e50ba5Skettenis 			continue;
18312e50ba5Skettenis 		if (dai->dd_set_format)
18412e50ba5Skettenis 			dai->dd_set_format(dai->dd_cookie, fmt, pol, clk);
18512e50ba5Skettenis 	}
18612e50ba5Skettenis }
18712e50ba5Skettenis 
18812e50ba5Skettenis void
aplaudio_set_tdm_slots(struct aplaudio_softc * sc)18912e50ba5Skettenis aplaudio_set_tdm_slots(struct aplaudio_softc *sc)
19012e50ba5Skettenis {
19112e50ba5Skettenis 	struct dai_device *dai;
19212e50ba5Skettenis 	int i;
19312e50ba5Skettenis 
19412e50ba5Skettenis 	for (i = 0; i < nitems(sc->sc_dai_codec); i++) {
19512e50ba5Skettenis 		dai = sc->sc_dai_codec[i];
19612e50ba5Skettenis 		if (dai == NULL)
19712e50ba5Skettenis 			continue;
198*ee8269ddSkettenis 		if (dai->dd_set_tdm_slot) {
199*ee8269ddSkettenis 			char prefix[8];
200*ee8269ddSkettenis 			int slot = 0;
201*ee8269ddSkettenis 
202*ee8269ddSkettenis 			if (OF_getprop(dai->dd_node, "sound-name-prefix",
203*ee8269ddSkettenis 			    prefix, sizeof(prefix)) > 0) {
204*ee8269ddSkettenis 				if (strncmp(prefix, "Right", 5) == 0)
205*ee8269ddSkettenis 					slot = 1;
206*ee8269ddSkettenis 			}
207*ee8269ddSkettenis 
208*ee8269ddSkettenis 			dai->dd_set_tdm_slot(dai->dd_cookie, slot);
209*ee8269ddSkettenis 		}
21012e50ba5Skettenis 	}
2117400b107Skettenis }
2127400b107Skettenis 
2137400b107Skettenis int
aplaudio_open(void * cookie,int flags)2147400b107Skettenis aplaudio_open(void *cookie, int flags)
2157400b107Skettenis {
2167400b107Skettenis 	struct aplaudio_softc *sc = cookie;
2177400b107Skettenis 	struct dai_device *dai;
2187400b107Skettenis 	const struct audio_hw_if *hwif;
2197400b107Skettenis 	int error;
22012e50ba5Skettenis 	int i;
2217400b107Skettenis 
2227400b107Skettenis 	dai = sc->sc_dai_cpu;
2237400b107Skettenis 	hwif = dai->dd_hw_if;
2247400b107Skettenis 	if (hwif->open) {
2257400b107Skettenis 		error = hwif->open(dai->dd_cookie, flags);
2267400b107Skettenis 		if (error) {
2277400b107Skettenis 			aplaudio_close(cookie);
2287400b107Skettenis 			return error;
2297400b107Skettenis 		}
2307400b107Skettenis 	}
2317400b107Skettenis 
23212e50ba5Skettenis 	for (i = 0; i < nitems(sc->sc_dai_codec); i++) {
23312e50ba5Skettenis 		dai = sc->sc_dai_codec[i];
23412e50ba5Skettenis 		if (dai == NULL)
23512e50ba5Skettenis 			continue;
2367400b107Skettenis 		hwif = dai->dd_hw_if;
2377400b107Skettenis 		if (hwif->open) {
2387400b107Skettenis 			error = hwif->open(dai->dd_cookie, flags);
2397400b107Skettenis 			if (error) {
2407400b107Skettenis 				aplaudio_close(cookie);
2417400b107Skettenis 				return error;
2427400b107Skettenis 			}
2437400b107Skettenis 		}
24412e50ba5Skettenis 	}
2457400b107Skettenis 
2467400b107Skettenis 	return 0;
2477400b107Skettenis }
2487400b107Skettenis 
2497400b107Skettenis void
aplaudio_close(void * cookie)2507400b107Skettenis aplaudio_close(void *cookie)
2517400b107Skettenis {
2527400b107Skettenis 	struct aplaudio_softc *sc = cookie;
2537400b107Skettenis 	struct dai_device *dai;
2547400b107Skettenis 	const struct audio_hw_if *hwif;
25512e50ba5Skettenis 	int i;
2567400b107Skettenis 
25712e50ba5Skettenis 	for (i = 0; i < nitems(sc->sc_dai_codec); i++) {
25812e50ba5Skettenis 		dai = sc->sc_dai_codec[i];
25912e50ba5Skettenis 		if (dai == NULL)
26012e50ba5Skettenis 			continue;
2617400b107Skettenis 		hwif = dai->dd_hw_if;
2627400b107Skettenis 		if (hwif->close)
2637400b107Skettenis 			hwif->close(dai->dd_cookie);
26412e50ba5Skettenis 	}
2657400b107Skettenis 
2667400b107Skettenis 	dai = sc->sc_dai_cpu;
2677400b107Skettenis 	hwif = dai->dd_hw_if;
2687400b107Skettenis 	if (hwif->close)
2697400b107Skettenis 		hwif->close(dai->dd_cookie);
2707400b107Skettenis }
2717400b107Skettenis 
2727400b107Skettenis int
aplaudio_set_params(void * cookie,int setmode,int usemode,struct audio_params * play,struct audio_params * rec)2737400b107Skettenis aplaudio_set_params(void *cookie, int setmode, int usemode,
2747400b107Skettenis     struct audio_params *play, struct audio_params *rec)
2757400b107Skettenis {
2767400b107Skettenis 	struct aplaudio_softc *sc = cookie;
2777400b107Skettenis 	struct dai_device *dai;
2787400b107Skettenis 	const struct audio_hw_if *hwif;
2797400b107Skettenis 	uint32_t rate;
2807400b107Skettenis 	int error;
28112e50ba5Skettenis 	int i;
2827400b107Skettenis 
283603e43a2Skettenis 	dai = sc->sc_dai_cpu;
284603e43a2Skettenis 	hwif = dai->dd_hw_if;
285603e43a2Skettenis 	if (hwif->set_params) {
286603e43a2Skettenis 		error = hwif->set_params(dai->dd_cookie,
287603e43a2Skettenis 		    setmode, usemode, play, rec);
288603e43a2Skettenis 		if (error)
289603e43a2Skettenis 			return error;
290603e43a2Skettenis 	}
291603e43a2Skettenis 
2927400b107Skettenis 	if (setmode & AUMODE_PLAY)
293603e43a2Skettenis 		rate = play->sample_rate * play->channels * play->bps * 8;
2947400b107Skettenis 	else
295603e43a2Skettenis 		rate = rec->sample_rate * rec->channels * rec->bps * 8;
2967400b107Skettenis 
29712e50ba5Skettenis 	for (i = 0; i < nitems(sc->sc_dai_codec); i++) {
29812e50ba5Skettenis 		dai = sc->sc_dai_codec[i];
29912e50ba5Skettenis 		if (dai == NULL)
30012e50ba5Skettenis 			continue;
3017400b107Skettenis 		if (dai->dd_set_sysclk) {
3027400b107Skettenis 			error = dai->dd_set_sysclk(dai->dd_cookie, rate);
3037400b107Skettenis 			if (error)
3047400b107Skettenis 				return error;
3057400b107Skettenis 		}
30612e50ba5Skettenis 	}
3077400b107Skettenis 
3087400b107Skettenis 	dai = sc->sc_dai_cpu;
3097400b107Skettenis 	if (dai->dd_set_sysclk) {
3107400b107Skettenis 		error = dai->dd_set_sysclk(dai->dd_cookie, rate);
3117400b107Skettenis 		if (error)
3127400b107Skettenis 			return error;
3137400b107Skettenis 	}
3147400b107Skettenis 
3157400b107Skettenis 	return 0;
3167400b107Skettenis }
3177400b107Skettenis 
3187400b107Skettenis void *
aplaudio_allocm(void * cookie,int direction,size_t size,int type,int flags)3197400b107Skettenis aplaudio_allocm(void *cookie, int direction, size_t size, int type,
3207400b107Skettenis     int flags)
3217400b107Skettenis {
3227400b107Skettenis 	struct aplaudio_softc *sc = cookie;
3237400b107Skettenis 	struct dai_device *dai = sc->sc_dai_cpu;
3247400b107Skettenis 	const struct audio_hw_if *hwif = dai->dd_hw_if;
3257400b107Skettenis 
3267400b107Skettenis 	if (hwif->allocm)
3277400b107Skettenis 		return hwif->allocm(dai->dd_cookie,
3287400b107Skettenis 		    direction, size, type, flags);
3297400b107Skettenis 
3307400b107Skettenis 	return NULL;
3317400b107Skettenis }
3327400b107Skettenis 
3337400b107Skettenis void
aplaudio_freem(void * cookie,void * addr,int type)3347400b107Skettenis aplaudio_freem(void *cookie, void *addr, int type)
3357400b107Skettenis {
3367400b107Skettenis 	struct aplaudio_softc *sc = cookie;
3377400b107Skettenis 	struct dai_device *dai = sc->sc_dai_cpu;
3387400b107Skettenis 	const struct audio_hw_if *hwif = dai->dd_hw_if;
3397400b107Skettenis 
3407400b107Skettenis 	if (hwif->freem)
3417400b107Skettenis 		hwif->freem(dai->dd_cookie, addr, type);
3427400b107Skettenis }
3437400b107Skettenis 
3447400b107Skettenis int
aplaudio_set_port(void * cookie,mixer_ctrl_t * cp)3457400b107Skettenis aplaudio_set_port(void *cookie, mixer_ctrl_t *cp)
3467400b107Skettenis {
3477400b107Skettenis 	struct aplaudio_softc *sc = cookie;
34812e50ba5Skettenis 	struct dai_device *dai;
34912e50ba5Skettenis 	const struct audio_hw_if *hwif;
35012e50ba5Skettenis 	int error = ENXIO;
35112e50ba5Skettenis 	int i;
3527400b107Skettenis 
35312e50ba5Skettenis 	for (i = 0; i < nitems(sc->sc_dai_codec); i++) {
35412e50ba5Skettenis 		dai = sc->sc_dai_codec[i];
35512e50ba5Skettenis 		if (dai == NULL)
35612e50ba5Skettenis 			continue;
35712e50ba5Skettenis 		hwif = dai->dd_hw_if;
3587400b107Skettenis 		if (hwif->set_port)
35912e50ba5Skettenis 			error = hwif->set_port(dai->dd_cookie, cp);
36012e50ba5Skettenis 	}
3617400b107Skettenis 
36212e50ba5Skettenis 	return error;
3637400b107Skettenis }
3647400b107Skettenis 
3657400b107Skettenis int
aplaudio_get_port(void * cookie,mixer_ctrl_t * cp)3667400b107Skettenis aplaudio_get_port(void *cookie, mixer_ctrl_t *cp)
3677400b107Skettenis {
3687400b107Skettenis 	struct aplaudio_softc *sc = cookie;
36912e50ba5Skettenis 	struct dai_device *dai;
37012e50ba5Skettenis 	const struct audio_hw_if *hwif;
37112e50ba5Skettenis 	int error = ENXIO;
37212e50ba5Skettenis 	int i;
3737400b107Skettenis 
37412e50ba5Skettenis 	for (i = 0; i < nitems(sc->sc_dai_codec); i++) {
37512e50ba5Skettenis 		dai = sc->sc_dai_codec[i];
37612e50ba5Skettenis 		if (dai == NULL)
37712e50ba5Skettenis 			continue;
37812e50ba5Skettenis 		hwif = dai->dd_hw_if;
3797400b107Skettenis 		if (hwif->get_port)
38012e50ba5Skettenis 			error = hwif->get_port(dai->dd_cookie, cp);
38112e50ba5Skettenis 	}
3827400b107Skettenis 
38312e50ba5Skettenis 	return error;
3847400b107Skettenis }
3857400b107Skettenis 
3867400b107Skettenis int
aplaudio_query_devinfo(void * cookie,mixer_devinfo_t * dip)3877400b107Skettenis aplaudio_query_devinfo(void *cookie, mixer_devinfo_t *dip)
3887400b107Skettenis {
3897400b107Skettenis 	struct aplaudio_softc *sc = cookie;
39012e50ba5Skettenis 	struct dai_device *dai;
39112e50ba5Skettenis 	const struct audio_hw_if *hwif;
39212e50ba5Skettenis 	int i;
3937400b107Skettenis 
39412e50ba5Skettenis 	for (i = 0; i < nitems(sc->sc_dai_codec); i++) {
39512e50ba5Skettenis 		dai = sc->sc_dai_codec[i];
39612e50ba5Skettenis 		if (dai == NULL)
39712e50ba5Skettenis 			continue;
39812e50ba5Skettenis 		hwif = dai->dd_hw_if;
3997400b107Skettenis 		if (hwif->query_devinfo)
4007400b107Skettenis 			return hwif->query_devinfo(dai->dd_cookie, dip);
40112e50ba5Skettenis 	}
4027400b107Skettenis 
4037400b107Skettenis 	return ENXIO;
4047400b107Skettenis }
4057400b107Skettenis 
4067400b107Skettenis int
aplaudio_round_blocksize(void * cookie,int block)4077400b107Skettenis aplaudio_round_blocksize(void *cookie, int block)
4087400b107Skettenis {
4097400b107Skettenis 	struct aplaudio_softc *sc = cookie;
4107400b107Skettenis 	struct dai_device *dai = sc->sc_dai_cpu;
4117400b107Skettenis 	const struct audio_hw_if *hwif = dai->dd_hw_if;
4127400b107Skettenis 
4137400b107Skettenis 	if (hwif->round_blocksize)
4147400b107Skettenis 		return hwif->round_blocksize(dai->dd_cookie, block);
4157400b107Skettenis 
4167400b107Skettenis 	return block;
4177400b107Skettenis }
4187400b107Skettenis 
4197400b107Skettenis size_t
aplaudio_round_buffersize(void * cookie,int direction,size_t bufsize)4207400b107Skettenis aplaudio_round_buffersize(void *cookie, int direction, size_t bufsize)
4217400b107Skettenis {
4227400b107Skettenis 	struct aplaudio_softc *sc = cookie;
4237400b107Skettenis 	struct dai_device *dai = sc->sc_dai_cpu;
4247400b107Skettenis 	const struct audio_hw_if *hwif = dai->dd_hw_if;
4257400b107Skettenis 
4267400b107Skettenis 	if (hwif->round_buffersize)
4277400b107Skettenis 		return hwif->round_buffersize(dai->dd_cookie,
4287400b107Skettenis 		    direction, bufsize);
4297400b107Skettenis 
4307400b107Skettenis 	return bufsize;
4317400b107Skettenis }
4327400b107Skettenis 
4337400b107Skettenis int
aplaudio_trigger_output(void * cookie,void * start,void * end,int blksize,void (* intr)(void *),void * arg,struct audio_params * param)4347400b107Skettenis aplaudio_trigger_output(void *cookie, void *start, void *end, int blksize,
4357400b107Skettenis     void (*intr)(void *), void *arg, struct audio_params *param)
4367400b107Skettenis {
4377400b107Skettenis 	struct aplaudio_softc *sc = cookie;
4387400b107Skettenis 	struct dai_device *dai;
4397400b107Skettenis 	const struct audio_hw_if *hwif;
4407400b107Skettenis 	int error;
44112e50ba5Skettenis 	int i;
4427400b107Skettenis 
44312e50ba5Skettenis 	for (i = 0; i < nitems(sc->sc_dai_codec); i++) {
44412e50ba5Skettenis 		dai = sc->sc_dai_codec[i];
44512e50ba5Skettenis 		if (dai == NULL)
44612e50ba5Skettenis 			continue;
4477400b107Skettenis 		hwif = dai->dd_hw_if;
4487400b107Skettenis 		if (hwif->trigger_output) {
4497400b107Skettenis 			error = hwif->trigger_output(dai->dd_cookie,
4507400b107Skettenis 			    start, end, blksize, intr, arg, param);
4517400b107Skettenis 			if (error) {
4527400b107Skettenis 				aplaudio_halt_output(cookie);
4537400b107Skettenis 				return error;
4547400b107Skettenis 			}
4557400b107Skettenis 		}
45612e50ba5Skettenis 	}
4577400b107Skettenis 
4587400b107Skettenis 	dai = sc->sc_dai_cpu;
4597400b107Skettenis 	hwif = dai->dd_hw_if;
4607400b107Skettenis 	if (hwif->trigger_output) {
4617400b107Skettenis 		error = hwif->trigger_output(dai->dd_cookie,
4627400b107Skettenis 		    start, end, blksize, intr, arg, param);
4637400b107Skettenis 		if (error) {
4647400b107Skettenis 			aplaudio_halt_output(cookie);
4657400b107Skettenis 			return error;
4667400b107Skettenis 		}
4677400b107Skettenis 	}
4687400b107Skettenis 
4697400b107Skettenis 	return 0;
4707400b107Skettenis }
4717400b107Skettenis 
4727400b107Skettenis int
aplaudio_trigger_input(void * cookie,void * start,void * end,int blksize,void (* intr)(void *),void * arg,struct audio_params * param)4737400b107Skettenis aplaudio_trigger_input(void *cookie, void *start, void *end, int blksize,
4747400b107Skettenis     void (*intr)(void *), void *arg, struct audio_params *param)
4757400b107Skettenis {
4767400b107Skettenis 	struct aplaudio_softc *sc = cookie;
4777400b107Skettenis 	struct dai_device *dai;
4787400b107Skettenis 	const struct audio_hw_if *hwif;
4797400b107Skettenis 	int error;
48012e50ba5Skettenis 	int i;
4817400b107Skettenis 
48212e50ba5Skettenis 	for (i = 0; i < nitems(sc->sc_dai_codec); i++) {
48312e50ba5Skettenis 		dai = sc->sc_dai_codec[i];
48412e50ba5Skettenis 		if (dai == NULL)
48512e50ba5Skettenis 			continue;
4867400b107Skettenis 		hwif = dai->dd_hw_if;
4877400b107Skettenis 		if (hwif->trigger_input) {
4887400b107Skettenis 			error = hwif->trigger_input(dai->dd_cookie,
4897400b107Skettenis 			    start, end, blksize, intr, arg, param);
4907400b107Skettenis 			if (error) {
4917400b107Skettenis 				aplaudio_halt_input(cookie);
4927400b107Skettenis 				return error;
4937400b107Skettenis 			}
4947400b107Skettenis 		}
49512e50ba5Skettenis 	}
4967400b107Skettenis 
4977400b107Skettenis 	dai = sc->sc_dai_cpu;
4987400b107Skettenis 	hwif = dai->dd_hw_if;
4997400b107Skettenis 	if (hwif->trigger_input) {
5007400b107Skettenis 		error = hwif->trigger_input(dai->dd_cookie,
5017400b107Skettenis 		    start, end, blksize, intr, arg, param);
5027400b107Skettenis 		if (error) {
5037400b107Skettenis 			aplaudio_halt_input(cookie);
5047400b107Skettenis 			return error;
5057400b107Skettenis 		}
5067400b107Skettenis 	}
5077400b107Skettenis 
5087400b107Skettenis 	return 0;
5097400b107Skettenis }
5107400b107Skettenis 
5117400b107Skettenis int
aplaudio_halt_output(void * cookie)5127400b107Skettenis aplaudio_halt_output(void *cookie)
5137400b107Skettenis {
5147400b107Skettenis 	struct aplaudio_softc *sc = cookie;
5157400b107Skettenis 	struct dai_device *dai;
5167400b107Skettenis 	const struct audio_hw_if *hwif;
51712e50ba5Skettenis 	int i;
5187400b107Skettenis 
51912e50ba5Skettenis 	for (i = 0; i < nitems(sc->sc_dai_codec); i++) {
52012e50ba5Skettenis 		dai = sc->sc_dai_codec[i];
52112e50ba5Skettenis 		if (dai == NULL)
52212e50ba5Skettenis 			continue;
5237400b107Skettenis 		hwif = dai->dd_hw_if;
5247400b107Skettenis 		if (hwif->halt_output)
5257400b107Skettenis 			hwif->halt_output(dai->dd_cookie);
52612e50ba5Skettenis 	}
5277400b107Skettenis 
5287400b107Skettenis 	dai = sc->sc_dai_cpu;
5297400b107Skettenis 	hwif = dai->dd_hw_if;
5307400b107Skettenis 	if (hwif->halt_output)
5317400b107Skettenis 		hwif->halt_output(dai->dd_cookie);
5327400b107Skettenis 
5337400b107Skettenis 	return 0;
5347400b107Skettenis }
5357400b107Skettenis 
5367400b107Skettenis int
aplaudio_halt_input(void * cookie)5377400b107Skettenis aplaudio_halt_input(void *cookie)
5387400b107Skettenis {
5397400b107Skettenis 	struct aplaudio_softc *sc = cookie;
5407400b107Skettenis 	struct dai_device *dai;
5417400b107Skettenis 	const struct audio_hw_if *hwif;
54212e50ba5Skettenis 	int i;
5437400b107Skettenis 
54412e50ba5Skettenis 	for (i = 0; i < nitems(sc->sc_dai_codec); i++) {
54512e50ba5Skettenis 		dai = sc->sc_dai_codec[i];
54612e50ba5Skettenis 		if (dai == NULL)
54712e50ba5Skettenis 			continue;
5487400b107Skettenis 		hwif = dai->dd_hw_if;
5497400b107Skettenis 		if (hwif->halt_input)
5507400b107Skettenis 			hwif->halt_input(dai->dd_cookie);
55112e50ba5Skettenis 	}
5527400b107Skettenis 
5537400b107Skettenis 	dai = sc->sc_dai_cpu;
5547400b107Skettenis 	hwif = dai->dd_hw_if;
5557400b107Skettenis 	if (hwif->halt_input)
5567400b107Skettenis 		hwif->halt_input(dai->dd_cookie);
5577400b107Skettenis 
5587400b107Skettenis 	return 0;
5597400b107Skettenis }
560