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