1*7eff0e4eSkn /* $OpenBSD: graphaudio.c,v 1.5 2022/10/28 15:09:45 kn Exp $ */
257d4ae74Skettenis /*
357d4ae74Skettenis * Copyright (c) 2020 Patrick Wildt <patrick@blueri.se>
457d4ae74Skettenis * Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org>
557d4ae74Skettenis *
657d4ae74Skettenis * Permission to use, copy, modify, and distribute this software for any
757d4ae74Skettenis * purpose with or without fee is hereby granted, provided that the above
857d4ae74Skettenis * copyright notice and this permission notice appear in all copies.
957d4ae74Skettenis *
1057d4ae74Skettenis * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1157d4ae74Skettenis * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1257d4ae74Skettenis * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1357d4ae74Skettenis * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1457d4ae74Skettenis * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1557d4ae74Skettenis * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1657d4ae74Skettenis * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1757d4ae74Skettenis */
1857d4ae74Skettenis
1957d4ae74Skettenis #include <sys/param.h>
2057d4ae74Skettenis #include <sys/systm.h>
2157d4ae74Skettenis #include <sys/device.h>
2257d4ae74Skettenis #include <sys/malloc.h>
2357d4ae74Skettenis
2457d4ae74Skettenis #include <machine/fdt.h>
2557d4ae74Skettenis
2657d4ae74Skettenis #include <dev/ofw/openfirm.h>
2757d4ae74Skettenis #include <dev/ofw/ofw_misc.h>
2857d4ae74Skettenis
2957d4ae74Skettenis #include <sys/audioio.h>
3057d4ae74Skettenis #include <dev/audio_if.h>
3157d4ae74Skettenis #include <dev/midi_if.h>
3257d4ae74Skettenis
3357d4ae74Skettenis struct graphaudio_softc {
3457d4ae74Skettenis struct device sc_dev;
3557d4ae74Skettenis int sc_node;
3657d4ae74Skettenis
3757d4ae74Skettenis uint32_t sc_mclk_fs;
3857d4ae74Skettenis
3957d4ae74Skettenis struct dai_device *sc_dai_cpu;
4057d4ae74Skettenis struct dai_device *sc_dai_codec;
4157d4ae74Skettenis };
4257d4ae74Skettenis
4357d4ae74Skettenis int graphaudio_match(struct device *, void *, void *);
4457d4ae74Skettenis void graphaudio_attach(struct device *, struct device *, void *);
4557d4ae74Skettenis void graphaudio_attach_deferred(struct device *);
4657d4ae74Skettenis void graphaudio_set_format(struct graphaudio_softc *, uint32_t,
4757d4ae74Skettenis uint32_t, uint32_t);
4857d4ae74Skettenis
4957d4ae74Skettenis int graphaudio_open(void *, int);
5057d4ae74Skettenis void graphaudio_close(void *);
5157d4ae74Skettenis int graphaudio_set_params(void *, int, int,
5257d4ae74Skettenis struct audio_params *, struct audio_params *);
5357d4ae74Skettenis void *graphaudio_allocm(void *, int, size_t, int, int);
5457d4ae74Skettenis void graphaudio_freem(void *, void *, int);
5557d4ae74Skettenis int graphaudio_set_port(void *, mixer_ctrl_t *);
5657d4ae74Skettenis int graphaudio_get_port(void *, mixer_ctrl_t *);
5757d4ae74Skettenis int graphaudio_query_devinfo(void *, mixer_devinfo_t *);
5857d4ae74Skettenis int graphaudio_round_blocksize(void *, int);
5957d4ae74Skettenis size_t graphaudio_round_buffersize(void *, int, size_t);
6057d4ae74Skettenis int graphaudio_trigger_output(void *, void *, void *, int,
6157d4ae74Skettenis void (*)(void *), void *, struct audio_params *);
6257d4ae74Skettenis int graphaudio_trigger_input(void *, void *, void *, int,
6357d4ae74Skettenis void (*)(void *), void *, struct audio_params *);
6457d4ae74Skettenis int graphaudio_halt_output(void *);
6557d4ae74Skettenis int graphaudio_halt_input(void *);
6657d4ae74Skettenis
670d6a2fdeSmiod const struct audio_hw_if graphaudio_hw_if = {
6857d4ae74Skettenis .open = graphaudio_open,
6957d4ae74Skettenis .close = graphaudio_close,
7057d4ae74Skettenis .set_params = graphaudio_set_params,
7157d4ae74Skettenis .allocm = graphaudio_allocm,
7257d4ae74Skettenis .freem = graphaudio_freem,
7357d4ae74Skettenis .set_port = graphaudio_set_port,
7457d4ae74Skettenis .get_port = graphaudio_get_port,
7557d4ae74Skettenis .query_devinfo = graphaudio_query_devinfo,
7657d4ae74Skettenis .round_blocksize = graphaudio_round_blocksize,
7757d4ae74Skettenis .round_buffersize = graphaudio_round_buffersize,
7857d4ae74Skettenis .trigger_output = graphaudio_trigger_output,
7957d4ae74Skettenis .trigger_input = graphaudio_trigger_input,
8057d4ae74Skettenis .halt_output = graphaudio_halt_output,
8157d4ae74Skettenis .halt_input = graphaudio_halt_input,
8257d4ae74Skettenis };
8357d4ae74Skettenis
84471aeecfSnaddy const struct cfattach graphaudio_ca = {
8557d4ae74Skettenis sizeof(struct graphaudio_softc), graphaudio_match, graphaudio_attach
8657d4ae74Skettenis };
8757d4ae74Skettenis
8857d4ae74Skettenis struct cfdriver graphaudio_cd = {
8957d4ae74Skettenis NULL, "graphaudio", DV_DULL
9057d4ae74Skettenis };
9157d4ae74Skettenis
9257d4ae74Skettenis int
graphaudio_match(struct device * parent,void * match,void * aux)9357d4ae74Skettenis graphaudio_match(struct device *parent, void *match, void *aux)
9457d4ae74Skettenis {
9557d4ae74Skettenis struct fdt_attach_args *faa = aux;
9657d4ae74Skettenis
9757d4ae74Skettenis return OF_is_compatible(faa->fa_node, "audio-graph-card");
9857d4ae74Skettenis }
9957d4ae74Skettenis
10057d4ae74Skettenis void
graphaudio_attach(struct device * parent,struct device * self,void * aux)10157d4ae74Skettenis graphaudio_attach(struct device *parent, struct device *self, void *aux)
10257d4ae74Skettenis {
10357d4ae74Skettenis struct graphaudio_softc *sc = (struct graphaudio_softc *)self;
10457d4ae74Skettenis struct fdt_attach_args *faa = aux;
10557d4ae74Skettenis
10657d4ae74Skettenis printf("\n");
10757d4ae74Skettenis
10857d4ae74Skettenis sc->sc_node = faa->fa_node;
10957d4ae74Skettenis config_defer(self, graphaudio_attach_deferred);
11057d4ae74Skettenis }
11157d4ae74Skettenis
11257d4ae74Skettenis void
graphaudio_attach_deferred(struct device * self)11357d4ae74Skettenis graphaudio_attach_deferred(struct device *self)
11457d4ae74Skettenis {
11557d4ae74Skettenis struct graphaudio_softc *sc = (struct graphaudio_softc *)self;
11657d4ae74Skettenis char format[16] = { 0 };
11757d4ae74Skettenis uint32_t fmt, pol, clk;
11857d4ae74Skettenis uint32_t dais;
11957d4ae74Skettenis struct device_ports *dp;
12057d4ae74Skettenis struct endpoint *ep, *rep;
12157d4ae74Skettenis
12257d4ae74Skettenis dais = OF_getpropint(sc->sc_node, "dais", 0);
12357d4ae74Skettenis dp = device_ports_byphandle(dais);
12457d4ae74Skettenis if (dp == NULL)
12557d4ae74Skettenis return;
12657d4ae74Skettenis
12757d4ae74Skettenis ep = endpoint_byreg(dp, -1, -1);
12857d4ae74Skettenis if (ep == NULL)
12957d4ae74Skettenis return;
13057d4ae74Skettenis
13157d4ae74Skettenis rep = endpoint_remote(ep);
13257d4ae74Skettenis if (rep == NULL)
13357d4ae74Skettenis return;
13457d4ae74Skettenis
13557d4ae74Skettenis sc->sc_mclk_fs = OF_getpropint(ep->ep_node, "mclk-fs", 0);
13657d4ae74Skettenis
13757d4ae74Skettenis sc->sc_dai_cpu = endpoint_get_cookie(ep);
13857d4ae74Skettenis sc->sc_dai_codec = endpoint_get_cookie(rep);
13957d4ae74Skettenis
14057d4ae74Skettenis if (sc->sc_dai_cpu == NULL || sc->sc_dai_codec == NULL)
14157d4ae74Skettenis return;
14257d4ae74Skettenis
14357d4ae74Skettenis OF_getprop(ep->ep_node, "dai-format", format, sizeof(format));
14457d4ae74Skettenis if (!strcmp(format, "i2s"))
14557d4ae74Skettenis fmt = DAI_FORMAT_I2S;
14657d4ae74Skettenis else if (!strcmp(format, "right_j"))
14757d4ae74Skettenis fmt = DAI_FORMAT_RJ;
14857d4ae74Skettenis else if (!strcmp(format, "left_j"))
14957d4ae74Skettenis fmt = DAI_FORMAT_LJ;
15057d4ae74Skettenis else if (!strcmp(format, "dsp_a"))
15157d4ae74Skettenis fmt = DAI_FORMAT_DSPA;
15257d4ae74Skettenis else if (!strcmp(format, "dsp_b"))
15357d4ae74Skettenis fmt = DAI_FORMAT_DSPB;
15457d4ae74Skettenis else if (!strcmp(format, "ac97"))
15557d4ae74Skettenis fmt = DAI_FORMAT_AC97;
15657d4ae74Skettenis else if (!strcmp(format, "pdm"))
15757d4ae74Skettenis fmt = DAI_FORMAT_PDM;
15857d4ae74Skettenis else if (!strcmp(format, "msb"))
15957d4ae74Skettenis fmt = DAI_FORMAT_MSB;
16057d4ae74Skettenis else if (!strcmp(format, "lsb"))
16157d4ae74Skettenis fmt = DAI_FORMAT_LSB;
16257d4ae74Skettenis else
16357d4ae74Skettenis return;
16457d4ae74Skettenis
16557d4ae74Skettenis pol = 0;
16657d4ae74Skettenis if (OF_getproplen(ep->ep_node, "frame-inversion") == 0)
16757d4ae74Skettenis pol |= DAI_POLARITY_IF;
16857d4ae74Skettenis else
16957d4ae74Skettenis pol |= DAI_POLARITY_NF;
17057d4ae74Skettenis if (OF_getproplen(ep->ep_node, "bitclock-inversion") == 0)
17157d4ae74Skettenis pol |= DAI_POLARITY_IB;
17257d4ae74Skettenis else
17357d4ae74Skettenis pol |= DAI_POLARITY_NB;
17457d4ae74Skettenis
17557d4ae74Skettenis clk = 0;
17657d4ae74Skettenis if (OF_getproplen(ep->ep_node, "frame-master") == 0)
17757d4ae74Skettenis clk |= DAI_CLOCK_CFM;
17857d4ae74Skettenis else
17957d4ae74Skettenis clk |= DAI_CLOCK_CFS;
18057d4ae74Skettenis if (OF_getproplen(ep->ep_node, "bitclock-master") == 0)
18157d4ae74Skettenis clk |= DAI_CLOCK_CBM;
18257d4ae74Skettenis else
18357d4ae74Skettenis clk |= DAI_CLOCK_CBS;
18457d4ae74Skettenis
18557d4ae74Skettenis graphaudio_set_format(sc, fmt, pol, clk);
18657d4ae74Skettenis
1872baa08e2Santon audio_attach_mi(&graphaudio_hw_if, sc, NULL, &sc->sc_dev);
18857d4ae74Skettenis }
18957d4ae74Skettenis
19057d4ae74Skettenis void
graphaudio_set_format(struct graphaudio_softc * sc,uint32_t fmt,uint32_t pol,uint32_t clk)19157d4ae74Skettenis graphaudio_set_format(struct graphaudio_softc *sc, uint32_t fmt, uint32_t pol,
19257d4ae74Skettenis uint32_t clk)
19357d4ae74Skettenis {
19457d4ae74Skettenis if (sc->sc_dai_cpu->dd_set_format)
19557d4ae74Skettenis sc->sc_dai_cpu->dd_set_format(sc->sc_dai_cpu->dd_cookie,
19657d4ae74Skettenis fmt, pol, clk);
19757d4ae74Skettenis if (sc->sc_dai_codec->dd_set_format)
19857d4ae74Skettenis sc->sc_dai_codec->dd_set_format(sc->sc_dai_codec->dd_cookie,
19957d4ae74Skettenis fmt, pol, clk);
20057d4ae74Skettenis }
20157d4ae74Skettenis
20257d4ae74Skettenis int
graphaudio_open(void * cookie,int flags)20357d4ae74Skettenis graphaudio_open(void *cookie, int flags)
20457d4ae74Skettenis {
20557d4ae74Skettenis struct graphaudio_softc *sc = cookie;
20657d4ae74Skettenis struct dai_device *dai;
2070d6a2fdeSmiod const struct audio_hw_if *hwif;
20857d4ae74Skettenis int error;
20957d4ae74Skettenis
21057d4ae74Skettenis dai = sc->sc_dai_cpu;
21157d4ae74Skettenis hwif = dai->dd_hw_if;
21257d4ae74Skettenis if (hwif->open) {
21357d4ae74Skettenis error = hwif->open(dai->dd_cookie, flags);
21457d4ae74Skettenis if (error) {
21557d4ae74Skettenis graphaudio_close(cookie);
21657d4ae74Skettenis return error;
21757d4ae74Skettenis }
21857d4ae74Skettenis }
21957d4ae74Skettenis
22057d4ae74Skettenis dai = sc->sc_dai_codec;
22157d4ae74Skettenis hwif = dai->dd_hw_if;
22257d4ae74Skettenis if (hwif->open) {
22357d4ae74Skettenis error = hwif->open(dai->dd_cookie, flags);
22457d4ae74Skettenis if (error) {
22557d4ae74Skettenis graphaudio_close(cookie);
22657d4ae74Skettenis return error;
22757d4ae74Skettenis }
22857d4ae74Skettenis }
22957d4ae74Skettenis
23057d4ae74Skettenis return 0;
23157d4ae74Skettenis }
23257d4ae74Skettenis
23357d4ae74Skettenis void
graphaudio_close(void * cookie)23457d4ae74Skettenis graphaudio_close(void *cookie)
23557d4ae74Skettenis {
23657d4ae74Skettenis struct graphaudio_softc *sc = cookie;
23757d4ae74Skettenis struct dai_device *dai;
2380d6a2fdeSmiod const struct audio_hw_if *hwif;
23957d4ae74Skettenis
24057d4ae74Skettenis dai = sc->sc_dai_codec;
24157d4ae74Skettenis hwif = dai->dd_hw_if;
24257d4ae74Skettenis if (hwif->close)
24357d4ae74Skettenis hwif->close(dai->dd_cookie);
24457d4ae74Skettenis
24557d4ae74Skettenis dai = sc->sc_dai_cpu;
24657d4ae74Skettenis hwif = dai->dd_hw_if;
24757d4ae74Skettenis if (hwif->close)
24857d4ae74Skettenis hwif->close(dai->dd_cookie);
24957d4ae74Skettenis }
25057d4ae74Skettenis
25157d4ae74Skettenis int
graphaudio_set_params(void * cookie,int setmode,int usemode,struct audio_params * play,struct audio_params * rec)25257d4ae74Skettenis graphaudio_set_params(void *cookie, int setmode, int usemode,
25357d4ae74Skettenis struct audio_params *play, struct audio_params *rec)
25457d4ae74Skettenis {
25557d4ae74Skettenis struct graphaudio_softc *sc = cookie;
25657d4ae74Skettenis struct dai_device *dai;
2570d6a2fdeSmiod const struct audio_hw_if *hwif;
25857d4ae74Skettenis uint32_t rate;
25957d4ae74Skettenis int error;
26057d4ae74Skettenis
26157d4ae74Skettenis if (sc->sc_mclk_fs) {
26257d4ae74Skettenis if (setmode & AUMODE_PLAY)
26357d4ae74Skettenis rate = play->sample_rate * sc->sc_mclk_fs;
26457d4ae74Skettenis else
26557d4ae74Skettenis rate = rec->sample_rate * sc->sc_mclk_fs;
26657d4ae74Skettenis
26757d4ae74Skettenis dai = sc->sc_dai_codec;
26857d4ae74Skettenis if (dai->dd_set_sysclk) {
26957d4ae74Skettenis error = dai->dd_set_sysclk(dai->dd_cookie, rate);
27057d4ae74Skettenis if (error)
27157d4ae74Skettenis return error;
27257d4ae74Skettenis }
27357d4ae74Skettenis
27457d4ae74Skettenis dai = sc->sc_dai_cpu;
27557d4ae74Skettenis if (dai->dd_set_sysclk) {
27657d4ae74Skettenis error = dai->dd_set_sysclk(dai->dd_cookie, rate);
27757d4ae74Skettenis if (error)
27857d4ae74Skettenis return error;
27957d4ae74Skettenis }
28057d4ae74Skettenis }
28157d4ae74Skettenis
28257d4ae74Skettenis dai = sc->sc_dai_cpu;
28357d4ae74Skettenis hwif = dai->dd_hw_if;
28457d4ae74Skettenis if (hwif->set_params) {
28557d4ae74Skettenis error = hwif->set_params(dai->dd_cookie,
28657d4ae74Skettenis setmode, usemode, play, rec);
28757d4ae74Skettenis if (error)
28857d4ae74Skettenis return error;
28957d4ae74Skettenis }
29057d4ae74Skettenis
29157d4ae74Skettenis dai = sc->sc_dai_codec;
29257d4ae74Skettenis hwif = dai->dd_hw_if;
29357d4ae74Skettenis if (hwif->set_params) {
29457d4ae74Skettenis error = hwif->set_params(dai->dd_cookie,
29557d4ae74Skettenis setmode, usemode, play, rec);
29657d4ae74Skettenis if (error)
29757d4ae74Skettenis return error;
29857d4ae74Skettenis }
29957d4ae74Skettenis
30057d4ae74Skettenis return 0;
30157d4ae74Skettenis }
30257d4ae74Skettenis
30357d4ae74Skettenis void *
graphaudio_allocm(void * cookie,int direction,size_t size,int type,int flags)30457d4ae74Skettenis graphaudio_allocm(void *cookie, int direction, size_t size, int type,
30557d4ae74Skettenis int flags)
30657d4ae74Skettenis {
30757d4ae74Skettenis struct graphaudio_softc *sc = cookie;
30857d4ae74Skettenis struct dai_device *dai = sc->sc_dai_cpu;
3090d6a2fdeSmiod const struct audio_hw_if *hwif = dai->dd_hw_if;
31057d4ae74Skettenis
31157d4ae74Skettenis if (hwif->allocm)
31257d4ae74Skettenis return hwif->allocm(dai->dd_cookie,
31357d4ae74Skettenis direction, size, type, flags);
31457d4ae74Skettenis
31557d4ae74Skettenis return NULL;
31657d4ae74Skettenis }
31757d4ae74Skettenis
31857d4ae74Skettenis void
graphaudio_freem(void * cookie,void * addr,int type)31957d4ae74Skettenis graphaudio_freem(void *cookie, void *addr, int type)
32057d4ae74Skettenis {
32157d4ae74Skettenis struct graphaudio_softc *sc = cookie;
32257d4ae74Skettenis struct dai_device *dai = sc->sc_dai_cpu;
3230d6a2fdeSmiod const struct audio_hw_if *hwif = dai->dd_hw_if;
32457d4ae74Skettenis
32557d4ae74Skettenis if (hwif->freem)
32657d4ae74Skettenis hwif->freem(dai->dd_cookie, addr, type);
32757d4ae74Skettenis }
32857d4ae74Skettenis
32957d4ae74Skettenis int
graphaudio_set_port(void * cookie,mixer_ctrl_t * cp)33057d4ae74Skettenis graphaudio_set_port(void *cookie, mixer_ctrl_t *cp)
33157d4ae74Skettenis {
33257d4ae74Skettenis struct graphaudio_softc *sc = cookie;
33357d4ae74Skettenis struct dai_device *dai = sc->sc_dai_codec;
3340d6a2fdeSmiod const struct audio_hw_if *hwif = dai->dd_hw_if;
33557d4ae74Skettenis
33657d4ae74Skettenis if (hwif->set_port)
33757d4ae74Skettenis return hwif->set_port(dai->dd_cookie, cp);
33857d4ae74Skettenis
33957d4ae74Skettenis return ENXIO;
34057d4ae74Skettenis }
34157d4ae74Skettenis
34257d4ae74Skettenis int
graphaudio_get_port(void * cookie,mixer_ctrl_t * cp)34357d4ae74Skettenis graphaudio_get_port(void *cookie, mixer_ctrl_t *cp)
34457d4ae74Skettenis {
34557d4ae74Skettenis struct graphaudio_softc *sc = cookie;
34657d4ae74Skettenis struct dai_device *dai = sc->sc_dai_codec;
3470d6a2fdeSmiod const struct audio_hw_if *hwif = dai->dd_hw_if;
34857d4ae74Skettenis
34957d4ae74Skettenis if (hwif->get_port)
35057d4ae74Skettenis return hwif->get_port(dai->dd_cookie, cp);
35157d4ae74Skettenis
35257d4ae74Skettenis return ENXIO;
35357d4ae74Skettenis }
35457d4ae74Skettenis
35557d4ae74Skettenis int
graphaudio_query_devinfo(void * cookie,mixer_devinfo_t * dip)35657d4ae74Skettenis graphaudio_query_devinfo(void *cookie, mixer_devinfo_t *dip)
35757d4ae74Skettenis {
35857d4ae74Skettenis struct graphaudio_softc *sc = cookie;
35957d4ae74Skettenis struct dai_device *dai = sc->sc_dai_codec;
3600d6a2fdeSmiod const struct audio_hw_if *hwif = dai->dd_hw_if;
36157d4ae74Skettenis
36257d4ae74Skettenis if (hwif->query_devinfo)
36357d4ae74Skettenis return hwif->query_devinfo(dai->dd_cookie, dip);
36457d4ae74Skettenis
36557d4ae74Skettenis return ENXIO;
36657d4ae74Skettenis }
36757d4ae74Skettenis
36857d4ae74Skettenis int
graphaudio_round_blocksize(void * cookie,int block)36957d4ae74Skettenis graphaudio_round_blocksize(void *cookie, int block)
37057d4ae74Skettenis {
37157d4ae74Skettenis struct graphaudio_softc *sc = cookie;
37257d4ae74Skettenis struct dai_device *dai = sc->sc_dai_cpu;
3730d6a2fdeSmiod const struct audio_hw_if *hwif = dai->dd_hw_if;
37457d4ae74Skettenis
37557d4ae74Skettenis if (hwif->round_blocksize)
37657d4ae74Skettenis return hwif->round_blocksize(dai->dd_cookie, block);
37757d4ae74Skettenis
37857d4ae74Skettenis return block;
37957d4ae74Skettenis }
38057d4ae74Skettenis
38157d4ae74Skettenis size_t
graphaudio_round_buffersize(void * cookie,int direction,size_t bufsize)38257d4ae74Skettenis graphaudio_round_buffersize(void *cookie, int direction, size_t bufsize)
38357d4ae74Skettenis {
38457d4ae74Skettenis struct graphaudio_softc *sc = cookie;
38557d4ae74Skettenis struct dai_device *dai = sc->sc_dai_cpu;
3860d6a2fdeSmiod const struct audio_hw_if *hwif = dai->dd_hw_if;
38757d4ae74Skettenis
38857d4ae74Skettenis if (hwif->round_buffersize)
38957d4ae74Skettenis return hwif->round_buffersize(dai->dd_cookie,
39057d4ae74Skettenis direction, bufsize);
39157d4ae74Skettenis
39257d4ae74Skettenis return bufsize;
39357d4ae74Skettenis }
39457d4ae74Skettenis
39557d4ae74Skettenis int
graphaudio_trigger_output(void * cookie,void * start,void * end,int blksize,void (* intr)(void *),void * arg,struct audio_params * param)39657d4ae74Skettenis graphaudio_trigger_output(void *cookie, void *start, void *end, int blksize,
39757d4ae74Skettenis void (*intr)(void *), void *arg, struct audio_params *param)
39857d4ae74Skettenis {
39957d4ae74Skettenis struct graphaudio_softc *sc = cookie;
40057d4ae74Skettenis struct dai_device *dai;
4010d6a2fdeSmiod const struct audio_hw_if *hwif;
40257d4ae74Skettenis int error;
40357d4ae74Skettenis
40457d4ae74Skettenis dai = sc->sc_dai_codec;
40557d4ae74Skettenis hwif = dai->dd_hw_if;
40657d4ae74Skettenis if (hwif->trigger_output) {
40757d4ae74Skettenis error = hwif->trigger_output(dai->dd_cookie,
40857d4ae74Skettenis start, end, blksize, intr, arg, param);
40957d4ae74Skettenis if (error) {
41057d4ae74Skettenis graphaudio_halt_output(cookie);
41157d4ae74Skettenis return error;
41257d4ae74Skettenis }
41357d4ae74Skettenis }
41457d4ae74Skettenis
41557d4ae74Skettenis dai = sc->sc_dai_cpu;
41657d4ae74Skettenis hwif = dai->dd_hw_if;
41757d4ae74Skettenis if (hwif->trigger_output) {
41857d4ae74Skettenis error = hwif->trigger_output(dai->dd_cookie,
41957d4ae74Skettenis start, end, blksize, intr, arg, param);
42057d4ae74Skettenis if (error) {
42157d4ae74Skettenis graphaudio_halt_output(cookie);
42257d4ae74Skettenis return error;
42357d4ae74Skettenis }
42457d4ae74Skettenis }
42557d4ae74Skettenis
42657d4ae74Skettenis return 0;
42757d4ae74Skettenis }
42857d4ae74Skettenis
42957d4ae74Skettenis int
graphaudio_trigger_input(void * cookie,void * start,void * end,int blksize,void (* intr)(void *),void * arg,struct audio_params * param)43057d4ae74Skettenis graphaudio_trigger_input(void *cookie, void *start, void *end, int blksize,
43157d4ae74Skettenis void (*intr)(void *), void *arg, struct audio_params *param)
43257d4ae74Skettenis {
43357d4ae74Skettenis struct graphaudio_softc *sc = cookie;
43457d4ae74Skettenis struct dai_device *dai;
4350d6a2fdeSmiod const struct audio_hw_if *hwif;
43657d4ae74Skettenis int error;
43757d4ae74Skettenis
43857d4ae74Skettenis dai = sc->sc_dai_codec;
43957d4ae74Skettenis hwif = dai->dd_hw_if;
44057d4ae74Skettenis if (hwif->trigger_input) {
44157d4ae74Skettenis error = hwif->trigger_input(dai->dd_cookie,
44257d4ae74Skettenis start, end, blksize, intr, arg, param);
44357d4ae74Skettenis if (error) {
44457d4ae74Skettenis graphaudio_halt_input(cookie);
44557d4ae74Skettenis return error;
44657d4ae74Skettenis }
44757d4ae74Skettenis }
44857d4ae74Skettenis
44957d4ae74Skettenis dai = sc->sc_dai_cpu;
45057d4ae74Skettenis hwif = dai->dd_hw_if;
45157d4ae74Skettenis if (hwif->trigger_input) {
45257d4ae74Skettenis error = hwif->trigger_input(dai->dd_cookie,
45357d4ae74Skettenis start, end, blksize, intr, arg, param);
45457d4ae74Skettenis if (error) {
45557d4ae74Skettenis graphaudio_halt_input(cookie);
45657d4ae74Skettenis return error;
45757d4ae74Skettenis }
45857d4ae74Skettenis }
45957d4ae74Skettenis
46057d4ae74Skettenis return 0;
46157d4ae74Skettenis }
46257d4ae74Skettenis
46357d4ae74Skettenis int
graphaudio_halt_output(void * cookie)46457d4ae74Skettenis graphaudio_halt_output(void *cookie)
46557d4ae74Skettenis {
46657d4ae74Skettenis struct graphaudio_softc *sc = cookie;
46757d4ae74Skettenis struct dai_device *dai;
4680d6a2fdeSmiod const struct audio_hw_if *hwif;
46957d4ae74Skettenis
47057d4ae74Skettenis dai = sc->sc_dai_codec;
47157d4ae74Skettenis hwif = dai->dd_hw_if;
47257d4ae74Skettenis if (hwif->halt_output)
47357d4ae74Skettenis hwif->halt_output(dai->dd_cookie);
47457d4ae74Skettenis
47557d4ae74Skettenis dai = sc->sc_dai_cpu;
47657d4ae74Skettenis hwif = dai->dd_hw_if;
47757d4ae74Skettenis if (hwif->halt_output)
47857d4ae74Skettenis hwif->halt_output(dai->dd_cookie);
47957d4ae74Skettenis
48057d4ae74Skettenis return 0;
48157d4ae74Skettenis }
48257d4ae74Skettenis
48357d4ae74Skettenis int
graphaudio_halt_input(void * cookie)48457d4ae74Skettenis graphaudio_halt_input(void *cookie)
48557d4ae74Skettenis {
48657d4ae74Skettenis struct graphaudio_softc *sc = cookie;
48757d4ae74Skettenis struct dai_device *dai;
4880d6a2fdeSmiod const struct audio_hw_if *hwif;
48957d4ae74Skettenis
49057d4ae74Skettenis dai = sc->sc_dai_codec;
49157d4ae74Skettenis hwif = dai->dd_hw_if;
49257d4ae74Skettenis if (hwif->halt_input)
49357d4ae74Skettenis hwif->halt_input(dai->dd_cookie);
49457d4ae74Skettenis
49557d4ae74Skettenis dai = sc->sc_dai_cpu;
49657d4ae74Skettenis hwif = dai->dd_hw_if;
49757d4ae74Skettenis if (hwif->halt_input)
49857d4ae74Skettenis hwif->halt_input(dai->dd_cookie);
49957d4ae74Skettenis
50057d4ae74Skettenis return 0;
50157d4ae74Skettenis }
502