1*7eff0e4eSkn /* $OpenBSD: simpleaudio.c,v 1.7 2022/10/28 15:09:45 kn Exp $ */
23a55c935Spatrick /*
33a55c935Spatrick * Copyright (c) 2020 Patrick Wildt <patrick@blueri.se>
43a55c935Spatrick *
53a55c935Spatrick * Permission to use, copy, modify, and distribute this software for any
63a55c935Spatrick * purpose with or without fee is hereby granted, provided that the above
73a55c935Spatrick * copyright notice and this permission notice appear in all copies.
83a55c935Spatrick *
93a55c935Spatrick * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
103a55c935Spatrick * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
113a55c935Spatrick * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
123a55c935Spatrick * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
133a55c935Spatrick * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
143a55c935Spatrick * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
153a55c935Spatrick * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
163a55c935Spatrick */
173a55c935Spatrick
183a55c935Spatrick #include <sys/param.h>
193a55c935Spatrick #include <sys/systm.h>
203a55c935Spatrick #include <sys/device.h>
213a55c935Spatrick #include <sys/malloc.h>
223a55c935Spatrick
233a55c935Spatrick #include <machine/fdt.h>
243a55c935Spatrick
253a55c935Spatrick #include <dev/ofw/openfirm.h>
263a55c935Spatrick #include <dev/ofw/ofw_misc.h>
273a55c935Spatrick #include <dev/ofw/ofw_pinctrl.h>
283a55c935Spatrick
293a55c935Spatrick #include <sys/audioio.h>
303a55c935Spatrick #include <dev/audio_if.h>
313a55c935Spatrick #include <dev/midi_if.h>
323a55c935Spatrick
333a55c935Spatrick struct simpleaudio_softc {
343a55c935Spatrick struct device sc_dev;
353a55c935Spatrick int sc_node;
363a55c935Spatrick
373a55c935Spatrick uint32_t sc_mclk_fs;
383a55c935Spatrick
393a55c935Spatrick struct dai_device *sc_dai_cpu;
403a55c935Spatrick struct dai_device *sc_dai_codec;
413a55c935Spatrick struct dai_device **sc_dai_aux;
423a55c935Spatrick int sc_dai_naux;
433a55c935Spatrick };
443a55c935Spatrick
453a55c935Spatrick int simpleaudio_match(struct device *, void *, void *);
463a55c935Spatrick void simpleaudio_attach(struct device *, struct device *, void *);
473a55c935Spatrick void simpleaudio_attach_deferred(struct device *);
483a55c935Spatrick void simpleaudio_set_format(struct simpleaudio_softc *, uint32_t,
493a55c935Spatrick uint32_t, uint32_t);
503a55c935Spatrick
513a55c935Spatrick int simpleaudio_open(void *, int);
523a55c935Spatrick void simpleaudio_close(void *);
533a55c935Spatrick int simpleaudio_set_params(void *, int, int,
543a55c935Spatrick struct audio_params *, struct audio_params *);
553a55c935Spatrick void *simpleaudio_allocm(void *, int, size_t, int, int);
563a55c935Spatrick void simpleaudio_freem(void *, void *, int);
573a55c935Spatrick int simpleaudio_set_port(void *, mixer_ctrl_t *);
583a55c935Spatrick int simpleaudio_get_port(void *, mixer_ctrl_t *);
593a55c935Spatrick int simpleaudio_query_devinfo(void *, mixer_devinfo_t *);
603a55c935Spatrick int simpleaudio_round_blocksize(void *, int);
613a55c935Spatrick size_t simpleaudio_round_buffersize(void *, int, size_t);
623a55c935Spatrick int simpleaudio_trigger_output(void *, void *, void *, int,
633a55c935Spatrick void (*)(void *), void *, struct audio_params *);
643a55c935Spatrick int simpleaudio_trigger_input(void *, void *, void *, int,
653a55c935Spatrick void (*)(void *), void *, struct audio_params *);
663a55c935Spatrick int simpleaudio_halt_output(void *);
673a55c935Spatrick int simpleaudio_halt_input(void *);
683a55c935Spatrick
690d6a2fdeSmiod const struct audio_hw_if simpleaudio_hw_if = {
703a55c935Spatrick .open = simpleaudio_open,
713a55c935Spatrick .close = simpleaudio_close,
723a55c935Spatrick .set_params = simpleaudio_set_params,
733a55c935Spatrick .allocm = simpleaudio_allocm,
743a55c935Spatrick .freem = simpleaudio_freem,
753a55c935Spatrick .set_port = simpleaudio_set_port,
763a55c935Spatrick .get_port = simpleaudio_get_port,
773a55c935Spatrick .query_devinfo = simpleaudio_query_devinfo,
783a55c935Spatrick .round_blocksize = simpleaudio_round_blocksize,
793a55c935Spatrick .round_buffersize = simpleaudio_round_buffersize,
803a55c935Spatrick .trigger_output = simpleaudio_trigger_output,
813a55c935Spatrick .trigger_input = simpleaudio_trigger_input,
823a55c935Spatrick .halt_output = simpleaudio_halt_output,
833a55c935Spatrick .halt_input = simpleaudio_halt_input,
843a55c935Spatrick };
853a55c935Spatrick
86471aeecfSnaddy const struct cfattach simpleaudio_ca = {
873a55c935Spatrick sizeof(struct simpleaudio_softc), simpleaudio_match, simpleaudio_attach
883a55c935Spatrick };
893a55c935Spatrick
903a55c935Spatrick struct cfdriver simpleaudio_cd = {
913a55c935Spatrick NULL, "simpleaudio", DV_DULL
923a55c935Spatrick };
933a55c935Spatrick
943a55c935Spatrick int
simpleaudio_match(struct device * parent,void * match,void * aux)953a55c935Spatrick simpleaudio_match(struct device *parent, void *match, void *aux)
963a55c935Spatrick {
973a55c935Spatrick struct fdt_attach_args *faa = aux;
983a55c935Spatrick
993a55c935Spatrick return OF_is_compatible(faa->fa_node, "simple-audio-card");
1003a55c935Spatrick }
1013a55c935Spatrick
1023a55c935Spatrick void
simpleaudio_attach(struct device * parent,struct device * self,void * aux)1033a55c935Spatrick simpleaudio_attach(struct device *parent, struct device *self, void *aux)
1043a55c935Spatrick {
1053a55c935Spatrick struct simpleaudio_softc *sc = (struct simpleaudio_softc *)self;
1063a55c935Spatrick struct fdt_attach_args *faa = aux;
1073a55c935Spatrick
1083a55c935Spatrick printf("\n");
1093a55c935Spatrick
1103a55c935Spatrick pinctrl_byname(faa->fa_node, "default");
1113a55c935Spatrick
1123a55c935Spatrick sc->sc_node = faa->fa_node;
1133a55c935Spatrick config_defer(self, simpleaudio_attach_deferred);
1143a55c935Spatrick }
1153a55c935Spatrick
1163a55c935Spatrick void
simpleaudio_attach_deferred(struct device * self)1173a55c935Spatrick simpleaudio_attach_deferred(struct device *self)
1183a55c935Spatrick {
1193a55c935Spatrick struct simpleaudio_softc *sc = (struct simpleaudio_softc *)self;
1203a55c935Spatrick char format[16] = { 0 };
1213a55c935Spatrick uint32_t fmt, pol, clk;
1223a55c935Spatrick uint32_t *auxdevs;
1233a55c935Spatrick ssize_t len;
1243a55c935Spatrick int i, node;
1253a55c935Spatrick
1263a55c935Spatrick /* TODO: implement simple-audio-card,dai-link */
1273a55c935Spatrick if (OF_getnodebyname(sc->sc_node, "simple-audio-card,cpu") == 0 ||
1283a55c935Spatrick OF_getnodebyname(sc->sc_node, "simple-audio-card,codec") == 0)
1293a55c935Spatrick return;
1303a55c935Spatrick
1313a55c935Spatrick sc->sc_mclk_fs = OF_getpropint(sc->sc_node,
1323a55c935Spatrick "simple-audio-card,mclk-fs", 0);
1333a55c935Spatrick
1343a55c935Spatrick node = OF_getnodebyname(sc->sc_node, "simple-audio-card,cpu");
1353a55c935Spatrick sc->sc_dai_cpu = dai_byphandle(OF_getpropint(node, "sound-dai", 0));
1363a55c935Spatrick
1373a55c935Spatrick node = OF_getnodebyname(sc->sc_node, "simple-audio-card,codec");
1383a55c935Spatrick sc->sc_dai_codec = dai_byphandle(OF_getpropint(node, "sound-dai", 0));
1393a55c935Spatrick
1403a55c935Spatrick if (sc->sc_dai_cpu == NULL || sc->sc_dai_codec == NULL)
1413a55c935Spatrick return;
1423a55c935Spatrick
1433a55c935Spatrick OF_getprop(sc->sc_node, "simple-audio-card,format",
1443a55c935Spatrick format, sizeof(format));
1453a55c935Spatrick if (!strcmp(format, "i2s"))
1463a55c935Spatrick fmt = DAI_FORMAT_I2S;
1473a55c935Spatrick else if (!strcmp(format, "right_j"))
1483a55c935Spatrick fmt = DAI_FORMAT_RJ;
1493a55c935Spatrick else if (!strcmp(format, "left_j"))
1503a55c935Spatrick fmt = DAI_FORMAT_LJ;
1513a55c935Spatrick else if (!strcmp(format, "dsp_a"))
1523a55c935Spatrick fmt = DAI_FORMAT_DSPA;
1533a55c935Spatrick else if (!strcmp(format, "dsp_b"))
1543a55c935Spatrick fmt = DAI_FORMAT_DSPB;
1553a55c935Spatrick else if (!strcmp(format, "ac97"))
1563a55c935Spatrick fmt = DAI_FORMAT_AC97;
1573a55c935Spatrick else if (!strcmp(format, "pdm"))
1583a55c935Spatrick fmt = DAI_FORMAT_PDM;
1593a55c935Spatrick else if (!strcmp(format, "msb"))
1603a55c935Spatrick fmt = DAI_FORMAT_MSB;
1613a55c935Spatrick else if (!strcmp(format, "lsb"))
1623a55c935Spatrick fmt = DAI_FORMAT_LSB;
1633a55c935Spatrick else
1643a55c935Spatrick return;
1653a55c935Spatrick
1663a55c935Spatrick pol = 0;
1673a55c935Spatrick if (OF_getproplen(sc->sc_node, "simple-audio-card,frame-inversion") == 0)
1683a55c935Spatrick pol |= DAI_POLARITY_IF;
1693a55c935Spatrick else
1703a55c935Spatrick pol |= DAI_POLARITY_NF;
1713a55c935Spatrick if (OF_getproplen(sc->sc_node, "simple-audio-card,bitclock-inversion") == 0)
1723a55c935Spatrick pol |= DAI_POLARITY_IB;
1733a55c935Spatrick else
1743a55c935Spatrick pol |= DAI_POLARITY_NB;
1753a55c935Spatrick
1763a55c935Spatrick clk = 0;
1773a55c935Spatrick if (OF_getproplen(sc->sc_node, "simple-audio-card,frame-master") == 0)
1783a55c935Spatrick clk |= DAI_CLOCK_CFM;
1793a55c935Spatrick else
1803a55c935Spatrick clk |= DAI_CLOCK_CFS;
1813a55c935Spatrick if (OF_getproplen(sc->sc_node, "simple-audio-card,bitclock-master") == 0)
1823a55c935Spatrick clk |= DAI_CLOCK_CBM;
1833a55c935Spatrick else
1843a55c935Spatrick clk |= DAI_CLOCK_CBS;
1853a55c935Spatrick
1863a55c935Spatrick len = OF_getproplen(sc->sc_node, "simple-audio-card,aux-devs");
1873a55c935Spatrick if (len > 0) {
1883a55c935Spatrick if (len % sizeof(uint32_t) != 0)
1893a55c935Spatrick return;
1903a55c935Spatrick
1913a55c935Spatrick auxdevs = malloc(len, M_TEMP, M_WAITOK);
1923a55c935Spatrick OF_getpropintarray(sc->sc_node, "simple-audio-card,aux-devs",
1933a55c935Spatrick auxdevs, len);
1943a55c935Spatrick
1953a55c935Spatrick sc->sc_dai_naux = len / sizeof(uint32_t);
1963a55c935Spatrick sc->sc_dai_aux = mallocarray(sc->sc_dai_naux,
1973a55c935Spatrick sizeof(struct dai_device *), M_DEVBUF, M_WAITOK | M_ZERO);
1983a55c935Spatrick
1993a55c935Spatrick for (i = 0; i < sc->sc_dai_naux; i++)
2003a55c935Spatrick sc->sc_dai_aux[i] = dai_byphandle(auxdevs[i]);
2013a55c935Spatrick
2023a55c935Spatrick free(auxdevs, M_TEMP, len);
2033a55c935Spatrick }
2043a55c935Spatrick
2053a55c935Spatrick simpleaudio_set_format(sc, fmt, pol, clk);
2063a55c935Spatrick
2072baa08e2Santon audio_attach_mi(&simpleaudio_hw_if, sc, NULL, &sc->sc_dev);
2083a55c935Spatrick }
2093a55c935Spatrick
2103a55c935Spatrick void
simpleaudio_set_format(struct simpleaudio_softc * sc,uint32_t fmt,uint32_t pol,uint32_t clk)2113a55c935Spatrick simpleaudio_set_format(struct simpleaudio_softc *sc, uint32_t fmt, uint32_t pol,
2123a55c935Spatrick uint32_t clk)
2133a55c935Spatrick {
2143a55c935Spatrick if (sc->sc_dai_cpu->dd_set_format)
2153a55c935Spatrick sc->sc_dai_cpu->dd_set_format(sc->sc_dai_cpu->dd_cookie,
2163a55c935Spatrick fmt, pol, clk);
2173a55c935Spatrick if (sc->sc_dai_codec->dd_set_format)
2183a55c935Spatrick sc->sc_dai_codec->dd_set_format(sc->sc_dai_codec->dd_cookie,
2193a55c935Spatrick fmt, pol, clk);
2203a55c935Spatrick }
2213a55c935Spatrick
2223a55c935Spatrick int
simpleaudio_open(void * cookie,int flags)2233a55c935Spatrick simpleaudio_open(void *cookie, int flags)
2243a55c935Spatrick {
2253a55c935Spatrick struct simpleaudio_softc *sc = cookie;
2263a55c935Spatrick struct dai_device *dai;
2270d6a2fdeSmiod const struct audio_hw_if *hwif;
2283a55c935Spatrick int error, i;
2293a55c935Spatrick
2303a55c935Spatrick dai = sc->sc_dai_cpu;
2313a55c935Spatrick hwif = dai->dd_hw_if;
2323a55c935Spatrick if (hwif->open) {
2333a55c935Spatrick error = hwif->open(dai->dd_cookie, flags);
2343a55c935Spatrick if (error) {
2353a55c935Spatrick simpleaudio_close(cookie);
2363a55c935Spatrick return error;
2373a55c935Spatrick }
2383a55c935Spatrick }
2393a55c935Spatrick
2403a55c935Spatrick dai = sc->sc_dai_codec;
2413a55c935Spatrick hwif = dai->dd_hw_if;
2423a55c935Spatrick if (hwif->open) {
2433a55c935Spatrick error = hwif->open(dai->dd_cookie, flags);
2443a55c935Spatrick if (error) {
2453a55c935Spatrick simpleaudio_close(cookie);
2463a55c935Spatrick return error;
2473a55c935Spatrick }
2483a55c935Spatrick }
2493a55c935Spatrick
2503a55c935Spatrick for (i = 0; i < sc->sc_dai_naux; i++) {
2513a55c935Spatrick dai = sc->sc_dai_aux[i];
2523a55c935Spatrick hwif = dai->dd_hw_if;
2533a55c935Spatrick if (hwif->open) {
2543a55c935Spatrick error = hwif->open(dai->dd_cookie, flags);
2553a55c935Spatrick if (error) {
2563a55c935Spatrick simpleaudio_close(cookie);
2573a55c935Spatrick return error;
2583a55c935Spatrick }
2593a55c935Spatrick }
2603a55c935Spatrick }
2613a55c935Spatrick
2623a55c935Spatrick return 0;
2633a55c935Spatrick }
2643a55c935Spatrick
2653a55c935Spatrick void
simpleaudio_close(void * cookie)2663a55c935Spatrick simpleaudio_close(void *cookie)
2673a55c935Spatrick {
2683a55c935Spatrick struct simpleaudio_softc *sc = cookie;
2693a55c935Spatrick struct dai_device *dai;
2700d6a2fdeSmiod const struct audio_hw_if *hwif;
2713a55c935Spatrick int i;
2723a55c935Spatrick
2733a55c935Spatrick for (i = 0; i < sc->sc_dai_naux; i++) {
2743a55c935Spatrick dai = sc->sc_dai_aux[i];
2753a55c935Spatrick hwif = dai->dd_hw_if;
2763a55c935Spatrick if (hwif->close)
2773a55c935Spatrick hwif->close(dai->dd_cookie);
2783a55c935Spatrick }
2793a55c935Spatrick
2803a55c935Spatrick dai = sc->sc_dai_codec;
2813a55c935Spatrick hwif = dai->dd_hw_if;
2823a55c935Spatrick if (hwif->close)
2833a55c935Spatrick hwif->close(dai->dd_cookie);
2843a55c935Spatrick
2853a55c935Spatrick dai = sc->sc_dai_cpu;
2863a55c935Spatrick hwif = dai->dd_hw_if;
2873a55c935Spatrick if (hwif->close)
2883a55c935Spatrick hwif->close(dai->dd_cookie);
2893a55c935Spatrick }
2903a55c935Spatrick
2913a55c935Spatrick int
simpleaudio_set_params(void * cookie,int setmode,int usemode,struct audio_params * play,struct audio_params * rec)2923a55c935Spatrick simpleaudio_set_params(void *cookie, int setmode, int usemode,
2933a55c935Spatrick struct audio_params *play, struct audio_params *rec)
2943a55c935Spatrick {
2953a55c935Spatrick struct simpleaudio_softc *sc = cookie;
2963a55c935Spatrick struct dai_device *dai;
2970d6a2fdeSmiod const struct audio_hw_if *hwif;
2983a55c935Spatrick uint32_t rate;
2993a55c935Spatrick int error;
3003a55c935Spatrick
3013a55c935Spatrick if (sc->sc_mclk_fs) {
3023a55c935Spatrick if (setmode & AUMODE_PLAY)
3033a55c935Spatrick rate = play->sample_rate * sc->sc_mclk_fs;
3043a55c935Spatrick else
3053a55c935Spatrick rate = rec->sample_rate * sc->sc_mclk_fs;
3063a55c935Spatrick
3073a55c935Spatrick dai = sc->sc_dai_codec;
3083a55c935Spatrick if (dai->dd_set_sysclk) {
3093a55c935Spatrick error = dai->dd_set_sysclk(dai->dd_cookie, rate);
3103a55c935Spatrick if (error)
3113a55c935Spatrick return error;
3123a55c935Spatrick }
3133a55c935Spatrick
3143a55c935Spatrick dai = sc->sc_dai_cpu;
3153a55c935Spatrick if (dai->dd_set_sysclk) {
3163a55c935Spatrick error = dai->dd_set_sysclk(dai->dd_cookie, rate);
3173a55c935Spatrick if (error)
3183a55c935Spatrick return error;
3193a55c935Spatrick }
3203a55c935Spatrick }
3213a55c935Spatrick
322071459beSkn dai = sc->sc_dai_cpu;
323071459beSkn hwif = dai->dd_hw_if;
324071459beSkn if (hwif->set_params) {
325071459beSkn error = hwif->set_params(dai->dd_cookie,
326071459beSkn setmode, usemode, play, rec);
327071459beSkn if (error)
328071459beSkn return error;
329071459beSkn }
330071459beSkn
331071459beSkn dai = sc->sc_dai_codec;
332071459beSkn hwif = dai->dd_hw_if;
333071459beSkn if (hwif->set_params) {
334071459beSkn error = hwif->set_params(dai->dd_cookie,
335071459beSkn setmode, usemode, play, rec);
336071459beSkn if (error)
337071459beSkn return error;
338071459beSkn }
339071459beSkn
3403a55c935Spatrick return 0;
3413a55c935Spatrick }
3423a55c935Spatrick
3433a55c935Spatrick void *
simpleaudio_allocm(void * cookie,int direction,size_t size,int type,int flags)3443a55c935Spatrick simpleaudio_allocm(void *cookie, int direction, size_t size, int type,
3453a55c935Spatrick int flags)
3463a55c935Spatrick {
3473a55c935Spatrick struct simpleaudio_softc *sc = cookie;
3483a55c935Spatrick struct dai_device *dai = sc->sc_dai_cpu;
3490d6a2fdeSmiod const struct audio_hw_if *hwif = dai->dd_hw_if;
3503a55c935Spatrick
3513a55c935Spatrick if (hwif->allocm)
3523a55c935Spatrick return hwif->allocm(dai->dd_cookie,
3533a55c935Spatrick direction, size, type, flags);
3543a55c935Spatrick
3553a55c935Spatrick return NULL;
3563a55c935Spatrick }
3573a55c935Spatrick
3583a55c935Spatrick void
simpleaudio_freem(void * cookie,void * addr,int type)3593a55c935Spatrick simpleaudio_freem(void *cookie, void *addr, int type)
3603a55c935Spatrick {
3613a55c935Spatrick struct simpleaudio_softc *sc = cookie;
3623a55c935Spatrick struct dai_device *dai = sc->sc_dai_cpu;
3630d6a2fdeSmiod const struct audio_hw_if *hwif = dai->dd_hw_if;
3643a55c935Spatrick
3653a55c935Spatrick if (hwif->freem)
3663a55c935Spatrick hwif->freem(dai->dd_cookie, addr, type);
3673a55c935Spatrick }
3683a55c935Spatrick
3693a55c935Spatrick int
simpleaudio_set_port(void * cookie,mixer_ctrl_t * cp)3703a55c935Spatrick simpleaudio_set_port(void *cookie, mixer_ctrl_t *cp)
3713a55c935Spatrick {
3723a55c935Spatrick struct simpleaudio_softc *sc = cookie;
3733a55c935Spatrick struct dai_device *dai = sc->sc_dai_codec;
3740d6a2fdeSmiod const struct audio_hw_if *hwif = dai->dd_hw_if;
3753a55c935Spatrick
3763a55c935Spatrick if (hwif->set_port)
3773a55c935Spatrick return hwif->set_port(dai->dd_cookie, cp);
3783a55c935Spatrick
3793a55c935Spatrick return ENXIO;
3803a55c935Spatrick }
3813a55c935Spatrick
3823a55c935Spatrick int
simpleaudio_get_port(void * cookie,mixer_ctrl_t * cp)3833a55c935Spatrick simpleaudio_get_port(void *cookie, mixer_ctrl_t *cp)
3843a55c935Spatrick {
3853a55c935Spatrick struct simpleaudio_softc *sc = cookie;
3863a55c935Spatrick struct dai_device *dai = sc->sc_dai_codec;
3870d6a2fdeSmiod const struct audio_hw_if *hwif = dai->dd_hw_if;
3883a55c935Spatrick
3893a55c935Spatrick if (hwif->get_port)
3903a55c935Spatrick return hwif->get_port(dai->dd_cookie, cp);
3913a55c935Spatrick
3923a55c935Spatrick return ENXIO;
3933a55c935Spatrick }
3943a55c935Spatrick
3953a55c935Spatrick int
simpleaudio_query_devinfo(void * cookie,mixer_devinfo_t * dip)3963a55c935Spatrick simpleaudio_query_devinfo(void *cookie, mixer_devinfo_t *dip)
3973a55c935Spatrick {
3983a55c935Spatrick struct simpleaudio_softc *sc = cookie;
3993a55c935Spatrick struct dai_device *dai = sc->sc_dai_codec;
4000d6a2fdeSmiod const struct audio_hw_if *hwif = dai->dd_hw_if;
4013a55c935Spatrick
4023a55c935Spatrick if (hwif->query_devinfo)
4033a55c935Spatrick return hwif->query_devinfo(dai->dd_cookie, dip);
4043a55c935Spatrick
4053a55c935Spatrick return ENXIO;
4063a55c935Spatrick }
4073a55c935Spatrick
4083a55c935Spatrick int
simpleaudio_round_blocksize(void * cookie,int block)4093a55c935Spatrick simpleaudio_round_blocksize(void *cookie, int block)
4103a55c935Spatrick {
4113a55c935Spatrick struct simpleaudio_softc *sc = cookie;
4123a55c935Spatrick struct dai_device *dai = sc->sc_dai_cpu;
4130d6a2fdeSmiod const struct audio_hw_if *hwif = dai->dd_hw_if;
4143a55c935Spatrick
4153a55c935Spatrick if (hwif->round_blocksize)
4163a55c935Spatrick return hwif->round_blocksize(dai->dd_cookie, block);
4173a55c935Spatrick
4183a55c935Spatrick return block;
4193a55c935Spatrick }
4203a55c935Spatrick
4213a55c935Spatrick size_t
simpleaudio_round_buffersize(void * cookie,int direction,size_t bufsize)4223a55c935Spatrick simpleaudio_round_buffersize(void *cookie, int direction, size_t bufsize)
4233a55c935Spatrick {
4243a55c935Spatrick struct simpleaudio_softc *sc = cookie;
4253a55c935Spatrick struct dai_device *dai = sc->sc_dai_cpu;
4260d6a2fdeSmiod const struct audio_hw_if *hwif = dai->dd_hw_if;
4273a55c935Spatrick
4283a55c935Spatrick if (hwif->round_buffersize)
4293a55c935Spatrick return hwif->round_buffersize(dai->dd_cookie,
4303a55c935Spatrick direction, bufsize);
4313a55c935Spatrick
4323a55c935Spatrick return bufsize;
4333a55c935Spatrick }
4343a55c935Spatrick
4353a55c935Spatrick int
simpleaudio_trigger_output(void * cookie,void * start,void * end,int blksize,void (* intr)(void *),void * arg,struct audio_params * param)4363a55c935Spatrick simpleaudio_trigger_output(void *cookie, void *start, void *end, int blksize,
4373a55c935Spatrick void (*intr)(void *), void *arg, struct audio_params *param)
4383a55c935Spatrick {
4393a55c935Spatrick struct simpleaudio_softc *sc = cookie;
4403a55c935Spatrick struct dai_device *dai;
4410d6a2fdeSmiod const struct audio_hw_if *hwif;
4423a55c935Spatrick int error, i;
4433a55c935Spatrick
4443a55c935Spatrick for (i = 0; i < sc->sc_dai_naux; i++) {
4453a55c935Spatrick dai = sc->sc_dai_aux[i];
4463a55c935Spatrick hwif = dai->dd_hw_if;
4473a55c935Spatrick if (hwif->trigger_output) {
4483a55c935Spatrick error = hwif->trigger_output(dai->dd_cookie,
4493a55c935Spatrick start, end, blksize, intr, arg, param);
4503a55c935Spatrick if (error) {
4513a55c935Spatrick simpleaudio_halt_output(cookie);
4523a55c935Spatrick return error;
4533a55c935Spatrick }
4543a55c935Spatrick }
4553a55c935Spatrick }
4563a55c935Spatrick
4573a55c935Spatrick dai = sc->sc_dai_codec;
4583a55c935Spatrick hwif = dai->dd_hw_if;
4593a55c935Spatrick if (hwif->trigger_output) {
4603a55c935Spatrick error = hwif->trigger_output(dai->dd_cookie,
4613a55c935Spatrick start, end, blksize, intr, arg, param);
4623a55c935Spatrick if (error) {
4633a55c935Spatrick simpleaudio_halt_output(cookie);
4643a55c935Spatrick return error;
4653a55c935Spatrick }
4663a55c935Spatrick }
4673a55c935Spatrick
4683a55c935Spatrick dai = sc->sc_dai_cpu;
4693a55c935Spatrick hwif = dai->dd_hw_if;
4703a55c935Spatrick if (hwif->trigger_output) {
4713a55c935Spatrick error = hwif->trigger_output(dai->dd_cookie,
4723a55c935Spatrick start, end, blksize, intr, arg, param);
4733a55c935Spatrick if (error) {
4743a55c935Spatrick simpleaudio_halt_output(cookie);
4753a55c935Spatrick return error;
4763a55c935Spatrick }
4773a55c935Spatrick }
4783a55c935Spatrick
4793a55c935Spatrick return 0;
4803a55c935Spatrick }
4813a55c935Spatrick
4823a55c935Spatrick int
simpleaudio_trigger_input(void * cookie,void * start,void * end,int blksize,void (* intr)(void *),void * arg,struct audio_params * param)4833a55c935Spatrick simpleaudio_trigger_input(void *cookie, void *start, void *end, int blksize,
4843a55c935Spatrick void (*intr)(void *), void *arg, struct audio_params *param)
4853a55c935Spatrick {
4863a55c935Spatrick struct simpleaudio_softc *sc = cookie;
4873a55c935Spatrick struct dai_device *dai;
4880d6a2fdeSmiod const struct audio_hw_if *hwif;
4893a55c935Spatrick int error, i;
4903a55c935Spatrick
4913a55c935Spatrick for (i = 0; i < sc->sc_dai_naux; i++) {
4923a55c935Spatrick dai = sc->sc_dai_aux[i];
4933a55c935Spatrick hwif = dai->dd_hw_if;
4943a55c935Spatrick if (hwif->trigger_input) {
4953a55c935Spatrick error = hwif->trigger_input(dai->dd_cookie,
4963a55c935Spatrick start, end, blksize, intr, arg, param);
4973a55c935Spatrick if (error) {
4983a55c935Spatrick simpleaudio_halt_input(cookie);
4993a55c935Spatrick return error;
5003a55c935Spatrick }
5013a55c935Spatrick }
5023a55c935Spatrick }
5033a55c935Spatrick
5043a55c935Spatrick dai = sc->sc_dai_codec;
5053a55c935Spatrick hwif = dai->dd_hw_if;
5063a55c935Spatrick if (hwif->trigger_input) {
5073a55c935Spatrick error = hwif->trigger_input(dai->dd_cookie,
5083a55c935Spatrick start, end, blksize, intr, arg, param);
5093a55c935Spatrick if (error) {
5103a55c935Spatrick simpleaudio_halt_input(cookie);
5113a55c935Spatrick return error;
5123a55c935Spatrick }
5133a55c935Spatrick }
5143a55c935Spatrick
5153a55c935Spatrick dai = sc->sc_dai_cpu;
5163a55c935Spatrick hwif = dai->dd_hw_if;
5173a55c935Spatrick if (hwif->trigger_input) {
5183a55c935Spatrick error = hwif->trigger_input(dai->dd_cookie,
5193a55c935Spatrick start, end, blksize, intr, arg, param);
5203a55c935Spatrick if (error) {
5213a55c935Spatrick simpleaudio_halt_input(cookie);
5223a55c935Spatrick return error;
5233a55c935Spatrick }
5243a55c935Spatrick }
5253a55c935Spatrick
5263a55c935Spatrick return 0;
5273a55c935Spatrick }
5283a55c935Spatrick
529842e4130Skettenis int
simpleaudio_halt_output(void * cookie)530842e4130Skettenis simpleaudio_halt_output(void *cookie)
5313a55c935Spatrick {
5323a55c935Spatrick struct simpleaudio_softc *sc = cookie;
5333a55c935Spatrick struct dai_device *dai;
5340d6a2fdeSmiod const struct audio_hw_if *hwif;
5353a55c935Spatrick int i;
5363a55c935Spatrick
5373a55c935Spatrick for (i = 0; i < sc->sc_dai_naux; i++) {
5383a55c935Spatrick dai = sc->sc_dai_aux[i];
5393a55c935Spatrick hwif = dai->dd_hw_if;
5403a55c935Spatrick if (hwif->halt_output)
5413a55c935Spatrick hwif->halt_output(dai->dd_cookie);
5423a55c935Spatrick }
5433a55c935Spatrick
5443a55c935Spatrick dai = sc->sc_dai_codec;
5453a55c935Spatrick hwif = dai->dd_hw_if;
5463a55c935Spatrick if (hwif->halt_output)
5473a55c935Spatrick hwif->halt_output(dai->dd_cookie);
5483a55c935Spatrick
5493a55c935Spatrick dai = sc->sc_dai_cpu;
5503a55c935Spatrick hwif = dai->dd_hw_if;
5513a55c935Spatrick if (hwif->halt_output)
5523a55c935Spatrick hwif->halt_output(dai->dd_cookie);
5533a55c935Spatrick
5543a55c935Spatrick return 0;
5553a55c935Spatrick }
5563a55c935Spatrick
557842e4130Skettenis int
simpleaudio_halt_input(void * cookie)558842e4130Skettenis simpleaudio_halt_input(void *cookie)
5593a55c935Spatrick {
5603a55c935Spatrick struct simpleaudio_softc *sc = cookie;
5613a55c935Spatrick struct dai_device *dai;
5620d6a2fdeSmiod const struct audio_hw_if *hwif;
5633a55c935Spatrick int i;
5643a55c935Spatrick
5653a55c935Spatrick for (i = 0; i < sc->sc_dai_naux; i++) {
5663a55c935Spatrick dai = sc->sc_dai_aux[i];
5673a55c935Spatrick hwif = dai->dd_hw_if;
5683a55c935Spatrick if (hwif->halt_input)
5693a55c935Spatrick hwif->halt_input(dai->dd_cookie);
5703a55c935Spatrick }
5713a55c935Spatrick
5723a55c935Spatrick dai = sc->sc_dai_codec;
5733a55c935Spatrick hwif = dai->dd_hw_if;
5743a55c935Spatrick if (hwif->halt_input)
5753a55c935Spatrick hwif->halt_input(dai->dd_cookie);
5763a55c935Spatrick
5773a55c935Spatrick dai = sc->sc_dai_cpu;
5783a55c935Spatrick hwif = dai->dd_hw_if;
5793a55c935Spatrick if (hwif->halt_input)
5803a55c935Spatrick hwif->halt_input(dai->dd_cookie);
5813a55c935Spatrick
5823a55c935Spatrick return 0;
5833a55c935Spatrick }
584