This patch improves am7930 family drivers to share more code among them. - audioamd(4) on sparc - vsaudio(4) on vax - bba(4) on alpha Index: sys/arch/sparc/conf/files.sparc =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/conf/files.sparc,v retrieving revision 1.159 diff -u -r1.159 files.sparc --- sys/arch/sparc/conf/files.sparc 1 Mar 2019 02:28:27 -0000 1.159 +++ sys/arch/sparc/conf/files.sparc 4 Sep 2020 13:11:23 -0000 @@ -233,7 +233,6 @@ attach audioamd at obio with audioamd_obio attach audioamd at sbus with audioamd_sbus file arch/sparc/dev/audioamd.c audioamd -file arch/sparc/sparc/amd7930intr.s audioamd device apc attach apc at sbus Index: sys/arch/sparc/dev/audioamd.c =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/dev/audioamd.c,v retrieving revision 1.29 diff -u -r1.29 audioamd.c --- sys/arch/sparc/dev/audioamd.c 8 May 2019 13:40:16 -0000 1.29 +++ sys/arch/sparc/dev/audioamd.c 4 Sep 2020 13:11:23 -0000 @@ -52,52 +52,14 @@ #include #include -#include #define AUDIO_ROM_NAME "audio" -#ifdef AUDIO_DEBUG -#define DPRINTF(x) if (am7930debug) printf x -#define DPRINTFN(n,x) if (am7930debug>(n)) printf x -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif /* AUDIO_DEBUG */ - - -/* interrupt interfaces */ -int am7930hwintr(void *); -struct auio *auiop; -void am7930swintr(void *); - -/* from amd7930intr.s: */ -void amd7930_trap(void); - -/* - * interrupt-handler status - */ -struct am7930_intrhand { - int (*ih_fun)(void *); - void *ih_arg; -}; - struct audioamd_softc { struct am7930_softc sc_am7930; /* glue to MI code */ bus_space_tag_t sc_bt; /* bus cookie */ bus_space_handle_t sc_bh; /* device registers */ - - struct am7930_intrhand sc_ih; /* interrupt vector (hw or sw) */ - void (*sc_rintr)(void*); /* input completion intr handler */ - void *sc_rarg; /* arg for sc_rintr() */ - void (*sc_pintr)(void*); /* output completion intr handler */ - void *sc_parg; /* arg for sc_pintr() */ - - /* sc_au is special in that the hardware interrupt handler uses it */ - struct auio sc_au; /* recv and xmit buffers, etc */ -#define sc_intrcnt sc_au.au_intrcnt /* statistics */ - void *sc_sicookie; /* softintr(9) cookie */ - kmutex_t sc_lock; }; int audioamd_mainbus_match(device_t, cfdata_t, void *); @@ -121,40 +83,25 @@ * Define our interface into the am7930 MI driver. */ -uint8_t audioamd_codec_iread(struct am7930_softc *, int); -uint16_t audioamd_codec_iread16(struct am7930_softc *, int); -uint8_t audioamd_codec_dread(struct audioamd_softc *, int); -void audioamd_codec_iwrite(struct am7930_softc *, int, uint8_t); -void audioamd_codec_iwrite16(struct am7930_softc *, int, uint16_t); -void audioamd_codec_dwrite(struct audioamd_softc *, int, uint8_t); -void audioamd_onopen(struct am7930_softc *); -void audioamd_onclose(struct am7930_softc *); +uint8_t audioamd_codec_dread(struct am7930_softc *, int); +void audioamd_codec_dwrite(struct am7930_softc *, int, uint8_t); struct am7930_glue audioamd_glue = { - audioamd_codec_iread, - audioamd_codec_iwrite, - audioamd_codec_iread16, - audioamd_codec_iwrite16, - audioamd_onopen, - audioamd_onclose, + audioamd_codec_dread, + audioamd_codec_dwrite, }; /* * Define our interface to the higher level audio driver. */ -int audioamd_start_output(void *, void *, int, void (*)(void *), void *); -int audioamd_start_input(void *, void *, int, void (*)(void *), void *); int audioamd_getdev(void *, struct audio_device *); -void audioamd_get_locks(void *opaque, kmutex_t **intr, kmutex_t **thread); const struct audio_hw_if sa_hw_if = { - .open = am7930_open, - .close = am7930_close, .query_format = am7930_query_format, .set_format = am7930_set_format, .commit_settings = am7930_commit_settings, - .start_output = audioamd_start_output, /* md */ - .start_input = audioamd_start_input, /* md */ + .trigger_output = am7930_trigger_output, + .trigger_input = am7930_trigger_input, .halt_output = am7930_halt_output, .halt_input = am7930_halt_input, .getdev = audioamd_getdev, @@ -162,7 +109,7 @@ .get_port = am7930_get_port, .query_devinfo = am7930_query_devinfo, .get_props = am7930_get_props, - .get_locks = audioamd_get_locks, + .get_locks = am7930_get_locks, }; struct audio_device audioamd_device = { @@ -280,258 +227,42 @@ void audioamd_attach(struct audioamd_softc *sc, int pri) { + struct am7930_softc *amsc = &sc->sc_am7930; device_t self; /* * Set up glue for MI code early; we use some of it here. */ - self = sc->sc_am7930.sc_dev; - sc->sc_am7930.sc_glue = &audioamd_glue; - mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_HIGH); - - am7930_init(&sc->sc_am7930, AUDIOAMD_POLL_MODE); - - auiop = &sc->sc_au; + amsc->sc_glue = &audioamd_glue; + am7930_init(amsc, AUDIOAMD_POLL_MODE); - /* Copy bus tag & handle for use by am7930_trap */ - sc->sc_au.au_bt = sc->sc_bt; - sc->sc_au.au_bh = sc->sc_bh; (void)bus_intr_establish2(sc->sc_bt, pri, IPL_HIGH, - am7930hwintr, sc, -#ifdef notyet /* XXX amd7930intr.s needs to be fixed for MI softint(9) */ - amd7930_trap -#else - NULL -#endif - ); - - sc->sc_sicookie = softint_establish(SOFTINT_SERIAL, am7930swintr, sc); - if (sc->sc_sicookie == NULL) { - printf("\n%s: cannot establish software interrupt\n", - device_xname(self)); - return; - } - - printf(" softpri %d\n", IPL_SOFTAUDIO); + am7930_hwintr, sc, NULL); + printf("\n"); - evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL, + self = amsc->sc_dev; + evcnt_attach_dynamic(&amsc->sc_intrcnt, EVCNT_TYPE_INTR, NULL, device_xname(self), "intr"); audio_attach_mi(&sa_hw_if, sc, self); } -void -audioamd_onopen(struct am7930_softc *sc) -{ - struct audioamd_softc *mdsc; - - mdsc = (struct audioamd_softc *)sc; - - /* reset pdma state */ - mutex_spin_enter(&mdsc->sc_lock); - mdsc->sc_rintr = 0; - mdsc->sc_rarg = 0; - mdsc->sc_pintr = 0; - mdsc->sc_parg = 0; - mdsc->sc_au.au_rdata = 0; - mdsc->sc_au.au_pdata = 0; - mutex_spin_exit(&mdsc->sc_lock); -} - - -void -audioamd_onclose(struct am7930_softc *sc) -{ - /* On sparc, just do the chipset-level halt. */ - am7930_halt_input(sc); - am7930_halt_output(sc); -} - -int -audioamd_start_output(void *addr, void *p, int cc, - void (*intr)(void *), void *arg) -{ - struct audioamd_softc *sc; - - DPRINTFN(1, ("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg)); - sc = addr; - - mutex_spin_enter(&sc->sc_lock); - audioamd_codec_iwrite(&sc->sc_am7930, - AM7930_IREG_INIT, AM7930_INIT_PMS_ACTIVE); - sc->sc_pintr = intr; - sc->sc_parg = arg; - sc->sc_au.au_pdata = p; - sc->sc_au.au_pend = (char *)p + cc - 1; - mutex_spin_exit(&sc->sc_lock); - - DPRINTF(("sa_start_output: started intrs.\n")); - return(0); -} - -int -audioamd_start_input(void *addr, void *p, int cc, - void (*intr)(void *), void *arg) -{ - struct audioamd_softc *sc; - - DPRINTFN(1, ("sa_start_input: cc=%d %p (%p)\n", cc, intr, arg)); - sc = addr; - - mutex_spin_enter(&sc->sc_lock); - audioamd_codec_iwrite(&sc->sc_am7930, - AM7930_IREG_INIT, AM7930_INIT_PMS_ACTIVE); - sc->sc_rintr = intr; - sc->sc_rarg = arg; - sc->sc_au.au_rdata = p; - sc->sc_au.au_rend = (char *)p + cc -1; - mutex_spin_exit(&sc->sc_lock); - - DPRINTF(("sa_start_input: started intrs.\n")); - - return(0); -} - - -/* - * Pseudo-DMA support: either C or locore assember. - */ - -int -am7930hwintr(void *v) -{ - struct audioamd_softc *sc; - struct auio *au; - uint8_t *d, *e; - int k; - - sc = v; - au = &sc->sc_au; - mutex_spin_enter(&sc->sc_lock); - - /* clear interrupt */ - k = audioamd_codec_dread(sc, AM7930_DREG_IR); - if ((k & (AM7930_IR_DTTHRSH|AM7930_IR_DRTHRSH|AM7930_IR_DSRI| - AM7930_IR_DERI|AM7930_IR_BBUFF)) == 0) { - mutex_spin_exit(&sc->sc_lock); - return 0; - } - - /* receive incoming data */ - d = au->au_rdata; - e = au->au_rend; - if (d && d <= e) { - *d = audioamd_codec_dread(sc, AM7930_DREG_BBRB); - au->au_rdata++; - if (d == e) { - DPRINTFN(1, ("am7930hwintr: swintr(r) requested")); - softint_schedule(sc->sc_sicookie); - } - } - - /* send outgoing data */ - d = au->au_pdata; - e = au->au_pend; - if (d && d <= e) { - audioamd_codec_dwrite(sc, AM7930_DREG_BBTB, *d); - au->au_pdata++; - if (d == e) { - DPRINTFN(1, ("am7930hwintr: swintr(p) requested")); - softint_schedule(sc->sc_sicookie); - } - } - - au->au_intrcnt.ev_count++; - mutex_spin_exit(&sc->sc_lock); - - return 1; -} - -void -am7930swintr(void *sc0) -{ - struct audioamd_softc *sc; - struct auio *au; - bool pint; - - sc = sc0; - DPRINTFN(1, ("audiointr: sc=%p\n", sc);); - - au = &sc->sc_au; - - mutex_spin_enter(&sc->sc_am7930.sc_lock); - if (au->au_rdata > au->au_rend && sc->sc_rintr != NULL) { - (*sc->sc_rintr)(sc->sc_rarg); - } - pint = (au->au_pdata > au->au_pend && sc->sc_pintr != NULL); - if (pint) - (*sc->sc_pintr)(sc->sc_parg); - - mutex_spin_exit(&sc->sc_am7930.sc_lock); -} - - -/* indirect write */ -void -audioamd_codec_iwrite(struct am7930_softc *sc, int reg, uint8_t val) -{ - struct audioamd_softc *mdsc; - - mdsc = (struct audioamd_softc *)sc; - audioamd_codec_dwrite(mdsc, AM7930_DREG_CR, reg); - audioamd_codec_dwrite(mdsc, AM7930_DREG_DR, val); -} - -void -audioamd_codec_iwrite16(struct am7930_softc *sc, int reg, uint16_t val) -{ - struct audioamd_softc *mdsc; - - mdsc = (struct audioamd_softc *)sc; - audioamd_codec_dwrite(mdsc, AM7930_DREG_CR, reg); - audioamd_codec_dwrite(mdsc, AM7930_DREG_DR, val); - audioamd_codec_dwrite(mdsc, AM7930_DREG_DR, val>>8); -} - - -/* indirect read */ -uint8_t -audioamd_codec_iread(struct am7930_softc *sc, int reg) -{ - struct audioamd_softc *mdsc; - - mdsc = (struct audioamd_softc *)sc; - audioamd_codec_dwrite(mdsc, AM7930_DREG_CR, reg); - return (audioamd_codec_dread(mdsc, AM7930_DREG_DR)); -} - -uint16_t -audioamd_codec_iread16(struct am7930_softc *sc, int reg) -{ - struct audioamd_softc *mdsc; - uint8_t lo, hi; - - mdsc = (struct audioamd_softc *)sc; - audioamd_codec_dwrite(mdsc, AM7930_DREG_CR, reg); - lo = audioamd_codec_dread(mdsc, AM7930_DREG_DR); - hi = audioamd_codec_dread(mdsc, AM7930_DREG_DR); - return (hi << 8) | lo; -} - /* direct read */ uint8_t -audioamd_codec_dread(struct audioamd_softc *sc, int reg) +audioamd_codec_dread(struct am7930_softc *amsc, int reg) { + struct audioamd_softc *sc = (struct audioamd_softc *)amsc; return bus_space_read_1(sc->sc_bt, sc->sc_bh, reg); } /* direct write */ void -audioamd_codec_dwrite(struct audioamd_softc *sc, int reg, uint8_t val) +audioamd_codec_dwrite(struct am7930_softc *amsc, int reg, uint8_t val) { + struct audioamd_softc *sc = (struct audioamd_softc *)amsc; bus_space_write_1(sc->sc_bt, sc->sc_bh, reg, val); } @@ -544,14 +275,4 @@ return 0; } -void -audioamd_get_locks(void *opaque, kmutex_t **intr, kmutex_t **thread) -{ - struct audioamd_softc *asc = opaque; - struct am7930_softc *sc = &asc->sc_am7930; - - *intr = &sc->sc_intr_lock; - *thread = &sc->sc_lock; -} - #endif /* NAUDIO > 0 */ Index: sys/arch/sparc/dev/audioamdvar.h =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/dev/audioamdvar.h,v retrieving revision 1.4 diff -u -r1.4 audioamdvar.h --- sys/arch/sparc/dev/audioamdvar.h 11 Dec 2005 12:19:05 -0000 1.4 +++ sys/arch/sparc/dev/audioamdvar.h 4 Sep 2020 13:11:23 -0000 @@ -1,45 +0,0 @@ -/* $NetBSD: audioamdvar.h,v 1.4 2005/12/11 12:19:05 christos Exp $ */ - -/* - * Copyright (c) 1995 Rolf Grossmann - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Rolf Grossmann. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * pdma state - */ -struct auio { - bus_space_tag_t au_bt; /* bus tag */ - bus_space_handle_t au_bh; /* handle to chip registers */ - - uint8_t *au_rdata; /* record data */ - uint8_t *au_rend; /* end of record data */ - uint8_t *au_pdata; /* play data */ - uint8_t *au_pend; /* end of play data */ - struct evcnt au_intrcnt; /* statistics */ -}; Index: sys/arch/sparc/include/am7930_machdep.h =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/include/am7930_machdep.h,v retrieving revision 1.1 diff -u -r1.1 am7930_machdep.h --- sys/arch/sparc/include/am7930_machdep.h 14 Mar 1999 22:29:00 -0000 1.1 +++ sys/arch/sparc/include/am7930_machdep.h 4 Sep 2020 13:11:23 -0000 @@ -1,14 +0,0 @@ -/* $NetBSD: am7930_machdep.h,v 1.1 1999/03/14 22:29:00 jonathan Exp $ */ - -/* - * Machine-dependent register accessors for am7930. - * On Sparc, these are direct bus_space operations. - */ - -#define AM7930_REGOFF(reg) (offsetof(struct am7930, reg)) - -#define AM7930_WRITE_REG(bt, bh, reg, val) \ - bus_space_write_1((bt), (bh), AM7930_REGOFF(reg), (val)) - -#define AM7930_READ_REG(bt, bh, reg) \ - bus_space_read_1((bt), (bh), AM7930_REGOFF(reg), (val)) Index: sys/arch/sparc/sparc/amd7930intr.s =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/sparc/amd7930intr.s,v retrieving revision 1.23 diff -u -r1.23 amd7930intr.s --- sys/arch/sparc/sparc/amd7930intr.s 20 Dec 2010 00:25:43 -0000 1.23 +++ sys/arch/sparc/sparc/amd7930intr.s 4 Sep 2020 13:11:23 -0000 @@ -1,205 +0,0 @@ -/* $NetBSD: amd7930intr.s,v 1.23 2010/12/20 00:25:43 matt Exp $ */ -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This software was developed by the Computer Systems Engineering group - * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and - * contributed to Berkeley. - * - * All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Lawrence Berkeley Laboratory. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)bsd_audiointr.s 8.1 (Berkeley) 6/11/93 - */ - -/* - * Copyright (c) 1995 Rolf Grossmann. - * - * This software was developed by the Computer Systems Engineering group - * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and - * contributed to Berkeley. - * - * All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Lawrence Berkeley Laboratory. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)bsd_audiointr.s 8.1 (Berkeley) 6/11/93 - */ - -#ifndef AUDIO_C_HANDLER -#include "assym.h" -#include -#include -#include -#include -#include -#include - -#define AUDIO_SET_SWINTR_4C \ - sethi %hi(INTRREG_VA), %l5; \ - ldub [%l5 + %lo(INTRREG_VA)], %l6; \ - or %l6, IE_L4, %l6; \ - stb %l6, [%l5 + %lo(INTRREG_VA)] - -! raise(0,IPL_SOFTAUDIO) ! NOTE: CPU#0 -#define AUDIO_SET_SWINTR_4M \ - sethi %hi(PINTR_SINTRLEV(IPL_SOFTAUDIO)), %l5;\ - set ICR_PI_SET, %l6; \ - st %l5, [%l6] - -/* set software interrupt */ -#if (defined(SUN4) || defined(SUN4C)) && !defined(SUN4M) -#define AUDIO_SET_SWINTR AUDIO_SET_SWINTR_4C -#elif !(defined(SUN4) || defined(SUN4C)) && defined(SUN4M) -#define AUDIO_SET_SWINTR AUDIO_SET_SWINTR_4M -#else -#define AUDIO_SET_SWINTR \ - sethi %hi(_C_LABEL(cputyp)), %l5; \ - ld [%l5 + %lo(_C_LABEL(cputyp))], %l5; \ - cmp %l5, CPU_SUN4M; \ - be 8f; \ - AUDIO_SET_SWINTR_4C; \ - ba,a 9f; \ -8: \ - AUDIO_SET_SWINTR_4M; \ -9: -#endif - -#define R_amd %l2 -#define R_data %l3 -#define R_end %l4 - - .seg "data" - .align 8 -savepc: - .word 0 - - .seg "text" - .align 4 - -_ENTRY(_C_LABEL(amd7930_trap)) - sethi %hi(savepc), %l7 - st %l2, [%l7 + %lo(savepc)] - - ! tally interrupt (curcpu()->cpu_data.cpu_nintr++) - INCR64X(CPUINFO_VA + CPUINFO_NINTR, %l4, %l5, %l7) - - sethi %hi(_C_LABEL(auiop)), %l7 - ld [%l7 + %lo(_C_LABEL(auiop))], %l7 - - ! tally interrupt (au_intrcnt.ev_count++) - ldd [%l7 + AU_EVCNT], %l4 - inccc %l5 - addx %l4, 0, %l4 - std %l4, [%l7 + AU_EVCNT] - - ld [%l7 + AU_BH], R_amd - ldub [R_amd + AM7930_DREG_IR], %g0 ! clear interrupt - - ! receive incoming data - ld [%l7 + AU_RDATA], R_data - ld [%l7 + AU_REND], R_end - - cmp R_data, 0 ! if (d && d <= e) - be 1f - cmp R_data, R_end - bgu 1f - nop - - ldub [R_amd + AM7930_DREG_BBRB], %l6 ! *d = amd->bbrb - stb %l6, [R_data] - - cmp R_data, R_end - inc R_data ! au->au_rdata++ - bne 1f ! if (d == e) - st R_data, [%l7 + AU_RDATA] - - AUDIO_SET_SWINTR - -1: - ! write outgoing data - ld [%l7 + AU_PDATA], R_data - ld [%l7 + AU_PEND], R_end - - cmp R_data, 0 ! if (d && d <= e) - be 2f - cmp R_data, R_end - bgu 2f - nop - - ldub [R_data], %l6 ! amd->bbtb = *d - stb %l6, [R_amd + AM7930_DREG_BBTB] - - cmp R_data, R_end - inc R_data ! au->au_pdata++ - bne 2f ! if (d == e) - st R_data, [%l7 + AU_PDATA] - - AUDIO_SET_SWINTR - -2: - /* - * Restore psr -- note: psr delay honored by pc restore loads. - */ - mov %l0, %psr - sethi %hi(savepc), %l7 - ld [%l7 + %lo(savepc)], %l2 - jmp %l1 - rett %l2 -#endif /* !AUDIO_C_HANDLER */ Index: sys/arch/sparc/sparc/genassym.cf =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/sparc/genassym.cf,v retrieving revision 1.70 diff -u -r1.70 genassym.cf --- sys/arch/sparc/sparc/genassym.cf 20 Feb 2020 08:27:39 -0000 1.70 +++ sys/arch/sparc/sparc/genassym.cf 4 Sep 2020 13:11:27 -0000 @@ -97,7 +97,6 @@ endif include -include include include @@ -237,14 +236,6 @@ define ZSRR1_DO_bit ffs(ZSRR1_DO) - 1 endif -# audio trap handler fields -define AU_BH offsetof(struct auio, au_bh) -define AU_RDATA offsetof(struct auio, au_rdata) -define AU_REND offsetof(struct auio, au_rend) -define AU_PDATA offsetof(struct auio, au_pdata) -define AU_PEND offsetof(struct auio, au_pend) -define AU_EVCNT offsetof(struct auio, au_intrcnt.ev_count) - define PROM_BASE PROM_BASE define PV_MAGIC offsetof(struct promvec, pv_magic) Index: sys/arch/vax/vsa/vsaudio.c =================================================================== RCS file: /cvsroot/src/sys/arch/vax/vsa/vsaudio.c,v retrieving revision 1.6 diff -u -r1.6 vsaudio.c --- sys/arch/vax/vsa/vsaudio.c 26 Aug 2020 12:59:28 -0000 1.6 +++ sys/arch/vax/vsa/vsaudio.c 4 Sep 2020 13:11:31 -0000 @@ -82,111 +82,47 @@ #include #include -#ifdef AUDIO_DEBUG -#define DPRINTF(x) if (am7930debug) printf x -#define DPRINTFN(n,x) if (am7930debug>(n)) printf x -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif /* AUDIO_DEBUG */ - /* physical addresses of the AM79C30 chip */ #define VSAUDIO_CSR 0x200d0000 #define VSAUDIO_CSR_KA49 0x26800000 -/* pdma state */ -struct auio { - bus_space_tag_t au_bt; /* bus tag */ - bus_space_handle_t au_bh; /* handle to chip registers */ - - uint8_t *au_rdata; /* record data */ - uint8_t *au_rend; /* end of record data */ - uint8_t *au_pdata; /* play data */ - uint8_t *au_pend; /* end of play data */ - struct evcnt au_intrcnt; /* statistics */ -}; - -struct am7930_intrhand { - int (*ih_fun)(void *); - void *ih_arg; -}; - - struct vsaudio_softc { struct am7930_softc sc_am7930; /* glue to MI code */ + bus_space_tag_t sc_bt; /* bus cookie */ bus_space_handle_t sc_bh; /* device registers */ - - struct am7930_intrhand sc_ih; /* interrupt vector (hw or sw) */ - void (*sc_rintr)(void*); /* input completion intr handler */ - void *sc_rarg; /* arg for sc_rintr() */ - void (*sc_pintr)(void*); /* output completion intr handler */ - void *sc_parg; /* arg for sc_pintr() */ - - uint8_t *sc_rdata; /* record data */ - uint8_t *sc_rend; /* end of record data */ - uint8_t *sc_pdata; /* play data */ - uint8_t *sc_pend; /* end of play data */ - - struct auio sc_au; /* recv and xmit buffers, etc */ -#define sc_intrcnt sc_au.au_intrcnt /* statistics */ - void *sc_sicookie; /* softintr(9) cookie */ - int sc_cvec; - kmutex_t sc_lock; }; static int vsaudio_match(struct device *parent, struct cfdata *match, void *); static void vsaudio_attach(device_t parent, device_t self, void *); +static void vsaudio_hwintr(void *); + CFATTACH_DECL_NEW(vsaudio, sizeof(struct vsaudio_softc), vsaudio_match, vsaudio_attach, NULL, NULL); /* * Hardware access routines for the MI code */ -uint8_t vsaudio_codec_iread(struct am7930_softc *, int); -uint16_t vsaudio_codec_iread16(struct am7930_softc *, int); -uint8_t vsaudio_codec_dread(struct vsaudio_softc *, int); -void vsaudio_codec_iwrite(struct am7930_softc *, int, uint8_t); -void vsaudio_codec_iwrite16(struct am7930_softc *, int, uint16_t); -void vsaudio_codec_dwrite(struct vsaudio_softc *, int, uint8_t); -void vsaudio_onopen(struct am7930_softc *); -void vsaudio_onclose(struct am7930_softc *); - -/* -static stream_filter_factory_t vsaudio_output_conv; -static stream_filter_factory_t vsaudio_input_conv; -static int vsaudio_output_conv_fetch_to(struct audio_softc *, - stream_fetcher_t *, audio_stream_t *, int); -static int vsaudio_input_conv_fetch_to(struct audio_softc *, - stream_fetcher_t *, audio_stream_t *, int); - */ +uint8_t vsaudio_codec_dread(struct am7930_softc *, int); +void vsaudio_codec_dwrite(struct am7930_softc *, int, uint8_t); struct am7930_glue vsaudio_glue = { - vsaudio_codec_iread, - vsaudio_codec_iwrite, - vsaudio_codec_iread16, - vsaudio_codec_iwrite16, - vsaudio_onopen, - vsaudio_onclose, + vsaudio_codec_dread, + vsaudio_codec_dwrite, }; /* * Interface to the MI audio layer. */ -int vsaudio_start_output(void *, void *, int, void (*)(void *), void *); -int vsaudio_start_input(void *, void *, int, void (*)(void *), void *); int vsaudio_getdev(void *, struct audio_device *); -void vsaudio_get_locks(void *opaque, kmutex_t **intr, kmutex_t **thread); struct audio_hw_if vsaudio_hw_if = { - .open = am7930_open, - .close = am7930_close, .query_format = am7930_query_format, .set_format = am7930_set_format, .commit_settings = am7930_commit_settings, - .start_output = vsaudio_start_output, - .start_input = vsaudio_start_input, + .trigger_output = am7930_trigger_output, + .trigger_input = am7930_trigger_input, .halt_output = am7930_halt_output, .halt_input = am7930_halt_input, .getdev = vsaudio_getdev, @@ -194,7 +130,7 @@ .get_port = am7930_get_port, .query_devinfo = am7930_query_devinfo, .get_props = am7930_get_props, - .get_locks = vsaudio_get_locks, + .get_locks = am7930_get_locks, }; @@ -204,15 +140,10 @@ "vsaudio" }; -void vsaudio_hwintr(void *); -void vsaudio_swintr(void *); -struct auio *auiop; - static int vsaudio_match(struct device *parent, struct cfdata *match, void *aux) { - struct vsbus_softc *sc __attribute__((__unused__)) = device_private(parent); struct vsbus_attach_args *va = aux; volatile uint32_t *regs; int i; @@ -264,6 +195,7 @@ { struct vsbus_attach_args *va = aux; struct vsaudio_softc *sc = device_private(self); + struct am7930_softc *amsc = &sc->sc_am7930; if (bus_space_map(va->va_memt, va->va_paddr, AM7930_DREG_SIZE << 2, 0, &sc->sc_bh) != 0) { @@ -271,249 +203,49 @@ return; } sc->sc_bt = va->va_memt; - sc->sc_am7930.sc_dev = self; - sc->sc_am7930.sc_glue = &vsaudio_glue; - mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_HIGH); - am7930_init(&sc->sc_am7930, AUDIOAMD_POLL_MODE); - auiop = &sc->sc_au; - /* Copy bus tag & handle for use by am7930_trap */ - sc->sc_au.au_bt = sc->sc_bt; - sc->sc_au.au_bh = sc->sc_bh; - scb_vecalloc(va->va_cvec, vsaudio_hwintr, sc, SCB_ISTACK, - &sc->sc_intrcnt); - sc->sc_cvec = va->va_cvec; - evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL, + amsc->sc_dev = self; + amsc->sc_glue = &vsaudio_glue; + am7930_init(amsc, AUDIOAMD_POLL_MODE); + scb_vecalloc(va->va_cvec, vsaudio_hwintr, amsc, SCB_ISTACK, + &amsc->sc_intrcnt); + evcnt_attach_dynamic(&amsc->sc_intrcnt, EVCNT_TYPE_INTR, NULL, device_xname(self), "intr"); - sc->sc_sicookie = softint_establish(SOFTINT_SERIAL, - &vsaudio_swintr, sc); - if (sc->sc_sicookie == NULL) { - aprint_normal("\n%s: cannot establish software interrupt\n", - device_xname(self)); - return; - } - aprint_normal("\n"); audio_attach_mi(&vsaudio_hw_if, sc, self); - -} - -void -vsaudio_onopen(struct am7930_softc *sc) -{ - struct vsaudio_softc *vssc = (struct vsaudio_softc *)sc; - - mutex_spin_enter(&vssc->sc_lock); - /* reset pdma state */ - vssc->sc_rintr = NULL; - vssc->sc_rarg = 0; - vssc->sc_pintr = NULL; - vssc->sc_parg = 0; - - vssc->sc_rdata = NULL; - vssc->sc_pdata = NULL; - mutex_spin_exit(&vssc->sc_lock); } -void -vsaudio_onclose(struct am7930_softc *sc) -{ - am7930_halt_input(sc); - am7930_halt_output(sc); -} - -/* - * this is called by interrupt code-path, don't lock - */ -int -vsaudio_start_output(void *addr, void *p, int cc, - void (*intr)(void *), void *arg) -{ - struct vsaudio_softc *sc = addr; - - DPRINTFN(1, ("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg)); - - mutex_spin_enter(&sc->sc_lock); - vsaudio_codec_iwrite(&sc->sc_am7930, - AM7930_IREG_INIT, AM7930_INIT_PMS_ACTIVE); - DPRINTF(("sa_start_output: started intrs.\n")); - sc->sc_pintr = intr; - sc->sc_parg = arg; - sc->sc_au.au_pdata = p; - sc->sc_au.au_pend = (char *)p + cc - 1; - mutex_spin_exit(&sc->sc_lock); - return 0; -} - -/* - * this is called by interrupt code-path, don't lock - */ -int -vsaudio_start_input(void *addr, void *p, int cc, - void (*intr)(void *), void *arg) -{ - struct vsaudio_softc *sc = addr; - - DPRINTFN(1, ("sa_start_input: cc=%d %p (%p)\n", cc, intr, arg)); - - mutex_spin_enter(&sc->sc_lock); - vsaudio_codec_iwrite(&sc->sc_am7930, - AM7930_IREG_INIT, AM7930_INIT_PMS_ACTIVE); - - sc->sc_rintr = intr; - sc->sc_rarg = arg; - sc->sc_au.au_rdata = p; - sc->sc_au.au_rend = (char *)p + cc -1; - mutex_spin_exit(&sc->sc_lock); - DPRINTF(("sa_start_input: started intrs.\n")); - return 0; -} - - -void -vsaudio_hwintr(void *v) -{ - struct vsaudio_softc *sc; - struct auio *au; - uint8_t *d, *e; - int __attribute__((__unused__)) k; - - sc = v; - au = &sc->sc_au; - mutex_spin_enter(&sc->sc_lock); - /* clear interrupt */ - k = vsaudio_codec_dread(sc, AM7930_DREG_IR); -#if 0 /* interrupt is not shared, this shouldn't happen */ - if ((k & (AM7930_IR_DTTHRSH | AM7930_IR_DRTHRSH | AM7930_IR_DSRI | - AM7930_IR_DERI | AM7930_IR_BBUFF)) == 0) { - mtx_leave(&audio_lock); - return 0; - } -#endif - /* receive incoming data */ - d = au->au_rdata; - e = au->au_rend; - if (d != NULL && d <= e) { - *d = vsaudio_codec_dread(sc, AM7930_DREG_BBRB); - au->au_rdata++; - if (d == e) { - DPRINTFN(1, ("vsaudio_hwintr: swintr(r) requested")); - softint_schedule(sc->sc_sicookie); - } - } - - /* send outgoing data */ - d = au->au_pdata; - e = au->au_pend; - if (d != NULL && d <= e) { - vsaudio_codec_dwrite(sc, AM7930_DREG_BBTB, *d); - au->au_pdata++; - if (d == e) { - DPRINTFN(1, ("vsaudio_hwintr: swintr(p) requested")); - softint_schedule(sc->sc_sicookie); - } - } - mutex_spin_exit(&sc->sc_lock); -} - -void -vsaudio_swintr(void *v) -{ - struct vsaudio_softc *sc; - struct auio *au; - int dor, dow; - - sc = v; - au = &sc->sc_au; - - DPRINTFN(1, ("audiointr: sc=%p\n", sc)); - - dor = dow = 0; - mutex_spin_enter(&sc->sc_am7930.sc_intr_lock); - if (au->au_rdata > au->au_rend && sc->sc_rintr != NULL) - dor = 1; - if (au->au_pdata > au->au_pend && sc->sc_pintr != NULL) - dow = 1; - - if (dor != 0) - (*sc->sc_rintr)(sc->sc_rarg); - if (dow != 0) - (*sc->sc_pintr)(sc->sc_parg); - mutex_spin_exit(&sc->sc_am7930.sc_intr_lock); -} - - -/* indirect write */ -void -vsaudio_codec_iwrite(struct am7930_softc *sc, int reg, uint8_t val) -{ - struct vsaudio_softc *vssc = (struct vsaudio_softc *)sc; - - vsaudio_codec_dwrite(vssc, AM7930_DREG_CR, reg); - vsaudio_codec_dwrite(vssc, AM7930_DREG_DR, val); -} - -void -vsaudio_codec_iwrite16(struct am7930_softc *sc, int reg, uint16_t val) -{ - struct vsaudio_softc *vssc = (struct vsaudio_softc *)sc; - - vsaudio_codec_dwrite(vssc, AM7930_DREG_CR, reg); - vsaudio_codec_dwrite(vssc, AM7930_DREG_DR, val); - vsaudio_codec_dwrite(vssc, AM7930_DREG_DR, val >> 8); -} - -/* indirect read */ -uint8_t -vsaudio_codec_iread(struct am7930_softc *sc, int reg) -{ - struct vsaudio_softc *vssc = (struct vsaudio_softc *)sc; - - vsaudio_codec_dwrite(vssc, AM7930_DREG_CR, reg); - return vsaudio_codec_dread(vssc, AM7930_DREG_DR); -} - -uint16_t -vsaudio_codec_iread16(struct am7930_softc *sc, int reg) +static void +vsaudio_hwintr(void *arg) { - struct vsaudio_softc *vssc = (struct vsaudio_softc *)sc; - uint lo, hi; - vsaudio_codec_dwrite(vssc, AM7930_DREG_CR, reg); - lo = vsaudio_codec_dread(vssc, AM7930_DREG_DR); - hi = vsaudio_codec_dread(vssc, AM7930_DREG_DR); - return (hi << 8) | lo; + am7930_hwintr(arg); } /* direct read */ uint8_t -vsaudio_codec_dread(struct vsaudio_softc *sc, int reg) +vsaudio_codec_dread(struct am7930_softc *amsc, int reg) { + struct vsaudio_softc *sc = (struct vsaudio_softc *)amsc; + return bus_space_read_1(sc->sc_bt, sc->sc_bh, reg << 2); } /* direct write */ void -vsaudio_codec_dwrite(struct vsaudio_softc *sc, int reg, uint8_t val) +vsaudio_codec_dwrite(struct am7930_softc *amsc, int reg, uint8_t val) { + struct vsaudio_softc *sc = (struct vsaudio_softc *)amsc; + bus_space_write_1(sc->sc_bt, sc->sc_bh, reg << 2, val); } int vsaudio_getdev(void *addr, struct audio_device *retp) { + *retp = vsaudio_device; return 0; } -void -vsaudio_get_locks(void *opaque, kmutex_t **intr, kmutex_t **thread) -{ - struct vsaudio_softc *asc = opaque; - struct am7930_softc *sc = &asc->sc_am7930; - - *intr = &sc->sc_intr_lock; - *thread = &sc->sc_lock; -} - #endif /* NAUDIO > 0 */ diff --git a/ic/am7930.c b/ic/am7930.c index f12d528..1c510df 100644 --- sys/dev/ic/am7930.c +++ sys/dev/ic/am7930.c @@ -43,6 +43,7 @@ __KERNEL_RCSID(0, "$NetBSD: am7930.c,v 1.59 2019/06/08 08:02:38 isaki Exp $"); #include #include +#include #include #include #include @@ -148,6 +149,51 @@ static const struct audio_format am7930_format = { .frequency = { 8000 }, }; +/* + * Indirect access functions. + */ + +static void +am7930_iwrite(struct am7930_softc *sc, int reg, uint8_t val) +{ + + AM7930_DWRITE(sc, AM7930_DREG_CR, reg); + AM7930_DWRITE(sc, AM7930_DREG_DR, val); +} + +static uint8_t +am7930_iread(struct am7930_softc *sc, int reg) +{ + + AM7930_DWRITE(sc, AM7930_DREG_CR, reg); + return AM7930_DREAD(sc, AM7930_DREG_DR); +} + +static void +am7930_iwrite16(struct am7930_softc *sc, int reg, uint16_t val) +{ + + AM7930_DWRITE(sc, AM7930_DREG_CR, reg); + AM7930_DWRITE(sc, AM7930_DREG_DR, val); + AM7930_DWRITE(sc, AM7930_DREG_DR, val >> 8); +} + +static uint16_t __unused +am7930_iread16(struct am7930_softc *sc, int reg) +{ + uint lo, hi; + + AM7930_DWRITE(sc, AM7930_DREG_CR, reg); + lo = AM7930_DREAD(sc, AM7930_DREG_DR); + hi = AM7930_DREAD(sc, AM7930_DREG_DR); + return (hi << 8) | lo; +} + +#define AM7930_IWRITE(sc,r,v) am7930_iwrite(sc,r,v) +#define AM7930_IREAD(sc,r) am7930_iread(sc,r) +#define AM7930_IWRITE16(sc,r,v) am7930_iwrite16(sc,r,v) +#define AM7930_IREAD16(sc,r) am7930_iread16(sc,r) + /* * Reset chip and set boot-time softc defaults. */ @@ -155,7 +201,7 @@ void am7930_init(struct am7930_softc *sc, int flag) { - DPRINTF(("am7930_init()\n")); + DPRINTF(("%s\n", __func__)); /* set boot defaults */ sc->sc_rlevel = 128; @@ -164,6 +210,9 @@ am7930_init(struct am7930_softc *sc, int flag) sc->sc_out_port = AUDIOAMD_SPEAKER_VOL; sc->sc_mic_mute = 0; + memset(&sc->sc_p, 0, sizeof(sc->sc_p)); + memset(&sc->sc_r, 0, sizeof(sc->sc_r)); + /* disable sample interrupts */ AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR4, 0); @@ -184,6 +233,7 @@ am7930_init(struct am7930_softc *sc, int flag) AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR2, AM7930_MCRCHAN_NC); AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR3, AM7930_MCRCHAN_NC); + mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED); } else { /* @@ -198,33 +248,18 @@ am7930_init(struct am7930_softc *sc, int flag) (AM7930_MCRCHAN_BB << 4) | AM7930_MCRCHAN_BA); AM7930_IWRITE(sc, AM7930_IREG_MUX_MCR4, AM7930_MCR4_INT_ENABLE); + + mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SOFTSERIAL); } mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); - mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED); -} -int -am7930_open(void *addr, int flags) -{ - struct am7930_softc *sc; - - sc = addr; - DPRINTF(("sa_open: unit %p\n", sc)); - sc->sc_glue->onopen(sc); - DPRINTF(("saopen: ok -> sc=%p\n",sc)); - return 0; -} - -void -am7930_close(void *addr) -{ - struct am7930_softc *sc; - - sc = addr; - DPRINTF(("sa_close: sc=%p\n", sc)); - sc->sc_glue->onclose(sc); - DPRINTF(("sa_close: closed.\n")); + sc->sc_sicookie = softint_establish(SOFTINT_SERIAL, &am7930_swintr, sc); + if (sc->sc_sicookie == NULL) { + aprint_error_dev(sc->sc_dev, + "cannot establish software interrupt\n"); + return; + } } int @@ -258,7 +293,7 @@ am7930_commit_settings(void *addr) uint8_t mmr2, mmr3; int level; - DPRINTF(("sa_commit.\n")); + DPRINTF(("%s\n", __func__)); sc = addr; gx = gx_coeff[sc->sc_rlevel]; stgr = gx_coeff[sc->sc_mlevel]; @@ -302,15 +337,66 @@ am7930_commit_settings(void *addr) return 0; } +int +am7930_trigger_output(void *addr, void *start, void *end, int blksize, + void (*intr)(void *), void *arg, const audio_params_t *params) +{ + struct am7930_softc *sc; + + DPRINTF(("%s: blksize=%d %p(%p)\n", __func__, blksize, intr, arg)); + sc = addr; + sc->sc_p.intr = intr; + sc->sc_p.arg = arg; + sc->sc_p.start = start; + sc->sc_p.end = end; + sc->sc_p.blksize = blksize; + sc->sc_p.data = sc->sc_p.start; + sc->sc_p.blkend = sc->sc_p.start + sc->sc_p.blksize; + + /* Start if either play or rec start. */ + if (sc->sc_r.intr == NULL) { + AM7930_IWRITE(sc, AM7930_IREG_INIT, AM7930_INIT_PMS_ACTIVE); + DPRINTF(("%s: started intrs.\n", __func__)); + } + return 0; +} + +int +am7930_trigger_input(void *addr, void *start, void *end, int blksize, + void (*intr)(void *), void *arg, const audio_params_t *params) +{ + struct am7930_softc *sc; + + DPRINTF(("%s: blksize=%d %p(%p)\n", __func__, blksize, intr, arg)); + sc = addr; + sc->sc_r.intr = intr; + sc->sc_r.arg = arg; + sc->sc_r.start = start; + sc->sc_r.end = end; + sc->sc_r.blksize = blksize; + sc->sc_r.data = sc->sc_r.start; + sc->sc_r.blkend = sc->sc_r.start + sc->sc_r.blksize; + + /* Start if either play or rec start. */ + if (sc->sc_p.intr == NULL) { + AM7930_IWRITE(sc, AM7930_IREG_INIT, AM7930_INIT_PMS_ACTIVE); + DPRINTF(("%s: started intrs.\n", __func__)); + } + return 0; +} + int am7930_halt_output(void *addr) { struct am7930_softc *sc; sc = addr; - /* XXX only halt, if input is also halted ?? */ - AM7930_IWRITE(sc, AM7930_IREG_INIT, - AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE); + sc->sc_p.intr = NULL; + /* Halt if both of play and rec halt. */ + if (sc->sc_r.intr == NULL) { + AM7930_IWRITE(sc, AM7930_IREG_INIT, + AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE); + } return 0; } @@ -320,12 +406,85 @@ am7930_halt_input(void *addr) struct am7930_softc *sc; sc = addr; - /* XXX only halt, if output is also halted ?? */ - AM7930_IWRITE(sc, AM7930_IREG_INIT, - AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE); + sc->sc_r.intr = NULL; + /* Halt if both of play and rec halt. */ + if (sc->sc_p.intr == NULL) { + AM7930_IWRITE(sc, AM7930_IREG_INIT, + AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_DISABLE); + } return 0; } +int +am7930_hwintr(void *arg) +{ + struct am7930_softc *sc; + int k __unused; + + sc = arg; + + /* + * This hwintr is called as pseudo-DMA. So don't acquire intr_lock. + */ + + /* clear interrupt */ + k = AM7930_DREAD(sc, AM7930_DREG_IR); +#if !defined(__vax__) + /* On vax, interrupt is not shared, this shouldn't happen */ + if ((k & (AM7930_IR_DTTHRSH | AM7930_IR_DRTHRSH | AM7930_IR_DSRI | + AM7930_IR_DERI | AM7930_IR_BBUFF)) == 0) { + return 0; + } +#endif + + /* receive incoming data */ + if (sc->sc_r.intr) { + *sc->sc_r.data++ = AM7930_DREAD(sc, AM7930_DREG_BBRB); + if (sc->sc_r.data == sc->sc_r.blkend) { + if (sc->sc_r.blkend == sc->sc_r.end) { + sc->sc_r.data = sc->sc_r.start; + sc->sc_r.blkend = sc->sc_r.start; + } + sc->sc_r.blkend += sc->sc_r.blksize; + atomic_store_relaxed(&sc->sc_r.intr_pending, 1); + softint_schedule(sc->sc_sicookie); + } + } + + /* send outgoing data */ + if (sc->sc_p.intr) { + AM7930_DWRITE(sc, AM7930_DREG_BBTB, *sc->sc_p.data++); + if (sc->sc_p.data == sc->sc_p.blkend) { + if (sc->sc_p.blkend == sc->sc_p.end) { + sc->sc_p.data = sc->sc_p.start; + sc->sc_p.blkend = sc->sc_p.start; + } + sc->sc_p.blkend += sc->sc_p.blksize; + atomic_store_relaxed(&sc->sc_p.intr_pending, 1); + softint_schedule(sc->sc_sicookie); + } + } + + sc->sc_intrcnt.ev_count++; + return 1; +} + +void +am7930_swintr(void *cookie) +{ + struct am7930_softc *sc = cookie; + + mutex_enter(&sc->sc_intr_lock); + if (atomic_cas_uint(&sc->sc_r.intr_pending, 1, 0) == 1) { + (*sc->sc_r.intr)(sc->sc_r.arg); + } + if (atomic_cas_uint(&sc->sc_p.intr_pending, 1, 0) == 1) { + (*sc->sc_p.intr)(sc->sc_p.arg); + } + mutex_exit(&sc->sc_intr_lock); +} + + /* * XXX chip is full-duplex, but really attach-dependent. * For now we know of no half-duplex attachments. @@ -346,7 +505,7 @@ am7930_set_port(void *addr, mixer_ctrl_t *cp) { struct am7930_softc *sc; - DPRINTF(("am7930_set_port: port=%d", cp->dev)); + DPRINTF(("%s: port=%d\n", __func__, cp->dev)); sc = addr; if (cp->dev == AUDIOAMD_RECORD_SOURCE || cp->dev == AUDIOAMD_MONITOR_OUTPUT || @@ -394,7 +553,7 @@ am7930_get_port(void *addr, mixer_ctrl_t *cp) { struct am7930_softc *sc; - DPRINTF(("am7930_get_port: port=%d\n", cp->dev)); + DPRINTF(("%s: port=%d\n", __func__, cp->dev)); sc = addr; if (cp->dev == AUDIOAMD_RECORD_SOURCE || cp->dev == AUDIOAMD_MONITOR_OUTPUT || @@ -441,7 +600,7 @@ int am7930_query_devinfo(void *addr, mixer_devinfo_t *dip) { - DPRINTF(("am7930_query_devinfo()\n")); + DPRINTF(("%s\n", __func__)); switch(dip->index) { case AUDIOAMD_MIC_VOL: @@ -543,4 +702,14 @@ am7930_query_devinfo(void *addr, mixer_devinfo_t *dip) return 0; } +void +am7930_get_locks(void *addr, kmutex_t **intr, kmutex_t **thread) +{ + struct am7930_softc *sc; + + sc = addr; + *intr = &sc->sc_intr_lock; + *thread = &sc->sc_lock; +} + #endif /* NAUDIO */ diff --git a/ic/am7930var.h b/ic/am7930var.h index 8e113f7..190fbfe 100644 --- sys/dev/ic/am7930var.h +++ sys/dev/ic/am7930var.h @@ -3,12 +3,20 @@ struct am7930_softc; struct am7930_glue { - uint8_t (*codec_iread)(struct am7930_softc *sc, int); - void (*codec_iwrite)(struct am7930_softc *sc, int, uint8_t); - uint16_t (*codec_iread16)(struct am7930_softc *sc, int); - void (*codec_iwrite16)(struct am7930_softc *sc, int, uint16_t); - void (*onopen)(struct am7930_softc *sc); - void (*onclose)(struct am7930_softc *sc); + uint8_t (*codec_dread)(struct am7930_softc *sc, int); + void (*codec_dwrite)(struct am7930_softc *sc, int, uint8_t); +}; + +struct am7930_buf { + uint8_t *start; + uint8_t *end; + uint8_t *data; + uint8_t *blkend; + uint blksize; + + void (*intr)(void *); + void *arg; + uint intr_pending; }; struct am7930_softc { @@ -21,19 +29,25 @@ struct am7930_softc { uint8_t sc_mic_mute; struct am7930_glue *sc_glue; + struct am7930_buf sc_p; /* for play */ + struct am7930_buf sc_r; /* for rec */ kmutex_t sc_lock; kmutex_t sc_intr_lock; + void *sc_sicookie; /* softint(9) cookie */ + struct evcnt sc_intrcnt; /* statistics */ }; extern int am7930debug; void am7930_init(struct am7930_softc *, int); +int am7930_hwintr(void *); +void am7930_swintr(void *); + +/* direct access functions */ +#define AM7930_DWRITE(x,y,z) (*(x)->sc_glue->codec_dwrite)((x),(y),(z)) +#define AM7930_DREAD(x,y) (*(x)->sc_glue->codec_dread)((x),(y)) -#define AM7930_IWRITE(x,y,z) (*(x)->sc_glue->codec_iwrite)((x),(y),(z)) -#define AM7930_IREAD(x,y) (*(x)->sc_glue->codec_iread)((x),(y)) -#define AM7930_IWRITE16(x,y,z) (*(x)->sc_glue->codec_iwrite16)((x),(y),(z)) -#define AM7930_IREAD16(x,y) (*(x)->sc_glue->codec_iread16)((x),(y)) #define AUDIOAMD_POLL_MODE 0 #define AUDIOAMD_DMA_MODE 1 @@ -61,17 +75,15 @@ void am7930_init(struct am7930_softc *, int); * audio(9) MI callbacks from upper-level audio layer. */ -struct audio_device; -struct audio_encoding; -struct audio_params; - -int am7930_open(void *, int); -void am7930_close(void *); int am7930_query_format(void *, audio_format_query_t *); int am7930_set_format(void *, int, const audio_params_t *, const audio_params_t *, audio_filter_reg_t *, audio_filter_reg_t *); int am7930_commit_settings(void *); +int am7930_trigger_output(void *, void *, void *, int, void (*)(void *), + void *, const audio_params_t *); +int am7930_trigger_input(void *, void *, void *, int, void (*)(void *), + void *, const audio_params_t *); int am7930_halt_output(void *); int am7930_halt_input(void *); int am7930_getdev(void *, struct audio_device *); @@ -79,3 +91,4 @@ int am7930_get_props(void *); int am7930_set_port(void *, mixer_ctrl_t *); int am7930_get_port(void *, mixer_ctrl_t *); int am7930_query_devinfo(void *, mixer_devinfo_t *); +void am7930_get_locks(void *, kmutex_t **, kmutex_t **); diff --git a/tc/bba.c b/tc/bba.c index 1ba412c..c70090c 100644 --- sys/dev/tc/bba.c +++ sys/dev/tc/bba.c @@ -107,20 +107,12 @@ CFATTACH_DECL_NEW(bba, sizeof(struct bba_softc), * Define our interface into the am7930 MI driver. */ -static uint8_t bba_codec_iread(struct am7930_softc *, int); -static uint16_t bba_codec_iread16(struct am7930_softc *, int); -static void bba_codec_iwrite(struct am7930_softc *, int, uint8_t); -static void bba_codec_iwrite16(struct am7930_softc *, int, uint16_t); -static void bba_onopen(struct am7930_softc *); -static void bba_onclose(struct am7930_softc *); +static uint8_t bba_codec_dread(struct am7930_softc *, int); +static void bba_codec_dwrite(struct am7930_softc *, int, uint8_t); struct am7930_glue bba_glue = { - bba_codec_iread, - bba_codec_iwrite, - bba_codec_iread16, - bba_codec_iwrite16, - bba_onopen, - bba_onclose, + bba_codec_dread, + bba_codec_dwrite, }; /* @@ -144,12 +136,8 @@ static int bba_trigger_output(void *, void *, void *, int, static int bba_trigger_input(void *, void *, void *, int, void (*)(void *), void *, const audio_params_t *); -static void bba_get_locks(void *opaque, kmutex_t **intr, - kmutex_t **thread); static const struct audio_hw_if sa_hw_if = { - .open = am7930_open, - .close = am7930_close, .query_format = bba_query_format, .set_format = bba_set_format, .round_blocksize = bba_round_blocksize, /* md */ @@ -166,7 +154,7 @@ static const struct audio_hw_if sa_hw_if = { .get_props = am7930_get_props, .trigger_output = bba_trigger_output, /* md */ .trigger_input = bba_trigger_input, /* md */ - .get_locks = bba_get_locks, + .get_locks = am7930_get_locks, }; static struct audio_device bba_device = { @@ -188,8 +176,6 @@ static const struct audio_format bba_format = { static int bba_intr(void *); static void bba_reset(struct bba_softc *, int); -static void bba_codec_dwrite(struct am7930_softc *, int, uint8_t); -static uint8_t bba_codec_dread(struct am7930_softc *, int); static int bba_match(device_t parent, cfdata_t cf, void *aux) @@ -210,13 +196,13 @@ bba_attach(device_t parent, device_t self, void *aux) { struct ioasicdev_attach_args *ia; struct bba_softc *sc; - struct am7930_softc *asc; + struct am7930_softc *amsc; struct ioasic_softc *iosc = device_private(parent); ia = aux; sc = device_private(self); - asc = &sc->sc_am7930; - asc->sc_dev = self; + amsc = &sc->sc_am7930; + amsc->sc_dev = self; sc->sc_bst = iosc->sc_bst; sc->sc_bsh = iosc->sc_bsh; sc->sc_dmat = iosc->sc_dmat; @@ -235,29 +221,17 @@ bba_attach(device_t parent, device_t self, void *aux) /* * Set up glue for MI code early; we use some of it here. */ - asc->sc_glue = &bba_glue; + amsc->sc_glue = &bba_glue; /* * MI initialisation. We will be doing DMA. */ - am7930_init(asc, AUDIOAMD_DMA_MODE); + am7930_init(amsc, AUDIOAMD_DMA_MODE); ioasic_intr_establish(parent, ia->iada_cookie, TC_IPL_NONE, bba_intr, sc); - audio_attach_mi(&sa_hw_if, asc, self); -} - - -static void -bba_onopen(struct am7930_softc *sc) -{ -} - - -static void -bba_onclose(struct am7930_softc *sc) -{ + audio_attach_mi(&sa_hw_if, sc, self); } @@ -291,7 +265,7 @@ bba_reset(struct bba_softc *sc, int reset) static void * bba_allocm(void *addr, int direction, size_t size) { - struct am7930_softc *asc; + struct am7930_softc *amsc; struct bba_softc *sc; bus_dma_segment_t seg; int rseg; @@ -300,20 +274,20 @@ bba_allocm(void *addr, int direction, size_t size) int state; DPRINTF(("bba_allocm: size = %zu\n", size)); - asc = addr; sc = addr; + amsc = addr; state = 0; if (bus_dmamem_alloc(sc->sc_dmat, size, BBA_DMABUF_ALIGN, BBA_DMABUF_BOUNDARY, &seg, 1, &rseg, BUS_DMA_WAITOK)) { - aprint_error_dev(asc->sc_dev, "can't allocate DMA buffer\n"); + aprint_error_dev(amsc->sc_dev, "can't allocate DMA buffer\n"); goto bad; } state |= 1; if (bus_dmamem_map(sc->sc_dmat, &seg, rseg, size, &kva, BUS_DMA_WAITOK | BUS_DMA_COHERENT)) { - aprint_error_dev(asc->sc_dev, "can't map DMA buffer\n"); + aprint_error_dev(amsc->sc_dev, "can't map DMA buffer\n"); goto bad; } state |= 2; @@ -569,16 +543,6 @@ bad: return 1; } -static void -bba_get_locks(void *opaque, kmutex_t **intr, kmutex_t **thread) -{ - struct bba_softc *bsc = opaque; - struct am7930_softc *sc = &bsc->sc_am7930; - - *intr = &sc->sc_intr_lock; - *thread = &sc->sc_lock; -} - static int bba_intr(void *addr) { @@ -647,64 +611,13 @@ bba_round_blocksize(void *addr, int blk, int mode, const audio_params_t *param) } -/* indirect write */ -static void -bba_codec_iwrite(struct am7930_softc *sc, int reg, uint8_t val) -{ - - DPRINTF(("bba_codec_iwrite(): sc=%p, reg=%d, val=%d\n", sc, reg, val)); - bba_codec_dwrite(sc, AM7930_DREG_CR, reg); - bba_codec_dwrite(sc, AM7930_DREG_DR, val); -} - - -static void -bba_codec_iwrite16(struct am7930_softc *sc, int reg, uint16_t val) -{ - - DPRINTF(("bba_codec_iwrite16(): sc=%p, reg=%d, val=%d\n", sc, reg, val)); - bba_codec_dwrite(sc, AM7930_DREG_CR, reg); - bba_codec_dwrite(sc, AM7930_DREG_DR, val); - bba_codec_dwrite(sc, AM7930_DREG_DR, val>>8); -} - - -static uint16_t -bba_codec_iread16(struct am7930_softc *sc, int reg) -{ - uint16_t val; - - DPRINTF(("bba_codec_iread16(): sc=%p, reg=%d\n", sc, reg)); - bba_codec_dwrite(sc, AM7930_DREG_CR, reg); - val = bba_codec_dread(sc, AM7930_DREG_DR) << 8; - val |= bba_codec_dread(sc, AM7930_DREG_DR); - - return val; -} - - -/* indirect read */ -static uint8_t -bba_codec_iread(struct am7930_softc *sc, int reg) -{ - uint8_t val; - - DPRINTF(("bba_codec_iread(): sc=%p, reg=%d\n", sc, reg)); - bba_codec_dwrite(sc, AM7930_DREG_CR, reg); - val = bba_codec_dread(sc, AM7930_DREG_DR); - - DPRINTF(("read 0x%x (%d)\n", val, val)); - - return val; -} - /* direct write */ static void -bba_codec_dwrite(struct am7930_softc *asc, int reg, uint8_t val) +bba_codec_dwrite(struct am7930_softc *amsc, int reg, uint8_t val) { struct bba_softc *sc; - sc = (struct bba_softc *)asc; + sc = (struct bba_softc *)amsc; DPRINTF(("bba_codec_dwrite(): sc=%p, reg=%d, val=%d\n", sc, reg, val)); #if defined(__alpha__) @@ -718,11 +631,11 @@ bba_codec_dwrite(struct am7930_softc *asc, int reg, uint8_t val) /* direct read */ static uint8_t -bba_codec_dread(struct am7930_softc *asc, int reg) +bba_codec_dread(struct am7930_softc *amsc, int reg) { struct bba_softc *sc; - sc = (struct bba_softc *)asc; + sc = (struct bba_softc *)amsc; DPRINTF(("bba_codec_dread(): sc=%p, reg=%d\n", sc, reg)); #if defined(__alpha__)