Module Name: src Committed By: isaki Date: Sun Apr 21 06:55:34 UTC 2019
Modified Files: src/sys/arch/hp300/dev [isaki-audio2]: arcofi_dio.c src/sys/dev/ic [isaki-audio2]: arcofi.c arcofivar.h Log Message: Adapt to audio2. - Use mulaw as default format. HW supports slinear_be:16 actually but it's hard to use due to several hardware restrictions. - Improve data transfer and interrupt. Tested by tsutsui@ (a few months ago). Thank you. To generate a diff of this commit: cvs rdiff -u -r1.1 -r1.1.26.1 src/sys/arch/hp300/dev/arcofi_dio.c cvs rdiff -u -r1.1.28.1 -r1.1.28.2 src/sys/dev/ic/arcofi.c cvs rdiff -u -r1.1 -r1.1.28.1 src/sys/dev/ic/arcofivar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/hp300/dev/arcofi_dio.c diff -u src/sys/arch/hp300/dev/arcofi_dio.c:1.1 src/sys/arch/hp300/dev/arcofi_dio.c:1.1.26.1 --- src/sys/arch/hp300/dev/arcofi_dio.c:1.1 Sun Aug 24 08:17:44 2014 +++ src/sys/arch/hp300/dev/arcofi_dio.c Sun Apr 21 06:55:34 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: arcofi_dio.c,v 1.1 2014/08/24 08:17:44 tsutsui Exp $ */ +/* $NetBSD: arcofi_dio.c,v 1.1.26.1 2019/04/21 06:55:34 isaki Exp $ */ /* $OpenBSD: arcofi_dio.c,v 1.1 2011/12/21 23:12:03 miod Exp $ */ /* @@ -80,11 +80,6 @@ arcofi_dio_attach(device_t parent, devic return; } - sc->sc_sih = softint_establish(SOFTINT_AUDIO, arcofi_swintr, sc); - if (sc->sc_sih == NULL) { - aprint_error(": can't register soft interrupt\n"); - return; - } ipl = da->da_ipl; dio_intr_establish(arcofi_hwintr, sc, ipl, IPL_AUDIO); Index: src/sys/dev/ic/arcofi.c diff -u src/sys/dev/ic/arcofi.c:1.1.28.1 src/sys/dev/ic/arcofi.c:1.1.28.2 --- src/sys/dev/ic/arcofi.c:1.1.28.1 Sun Apr 21 05:11:22 2019 +++ src/sys/dev/ic/arcofi.c Sun Apr 21 06:55:34 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: arcofi.c,v 1.1.28.1 2019/04/21 05:11:22 isaki Exp $ */ +/* $NetBSD: arcofi.c,v 1.1.28.2 2019/04/21 06:55:34 isaki Exp $ */ /* $OpenBSD: arcofi.c,v 1.6 2013/05/15 08:29:24 ratchov Exp $ */ /* @@ -36,15 +36,13 @@ #include <sys/kernel.h> #include <sys/proc.h> #include <sys/mutex.h> -#include <sys/condvar.h> #include <sys/bus.h> #include <sys/intr.h> #include <sys/audioio.h> #include <dev/audio_if.h> -#include <dev/auconv.h> -#include <dev/mulaw.h> +#include <dev/audio/mulaw.h> #include <dev/ic/arcofivar.h> @@ -200,11 +198,10 @@ static uint arcofi_portmask_to_cr3(int); static int arcofi_open(void *, int); static void arcofi_close(void *); -static int arcofi_drain(void *); -static int arcofi_query_encoding(void *, struct audio_encoding *); -static int arcofi_set_params(void *, int, int, - struct audio_params *, struct audio_params *, - stream_filter_list_t *, stream_filter_list_t *); +static int arcofi_query_format(void *, audio_format_query_t *); +static int arcofi_set_format(void *, int, + const audio_params_t *, const audio_params_t *, + audio_filter_reg_t *, audio_filter_reg_t *); static int arcofi_round_blocksize(void *, int, int, const audio_params_t *); static int arcofi_commit_settings(void *); @@ -224,9 +221,8 @@ static void arcofi_get_locks(void *, kmu static const struct audio_hw_if arcofi_hw_if = { .open = arcofi_open, .close = arcofi_close, - .drain = arcofi_drain, - .query_encoding = arcofi_query_encoding, - .set_params = arcofi_set_params, + .query_format = arcofi_query_format, + .set_format = arcofi_set_format, .round_blocksize = arcofi_round_blocksize, .commit_settings = arcofi_commit_settings, .start_output = arcofi_start_output, @@ -250,9 +246,10 @@ static const struct audio_hw_if arcofi_h .get_locks = arcofi_get_locks, }; -#define ARCOFI_FORMAT(enc, prec) \ +#define ARCOFI_FORMAT(prio, enc, prec) \ { \ .mode = AUMODE_PLAY | AUMODE_RECORD, \ + .priority = (prio), \ .encoding = (enc), \ .validbits = (prec), \ .precision = (prec), \ @@ -263,18 +260,15 @@ static const struct audio_hw_if arcofi_h } static const struct audio_format arcofi_formats[] = { /* - * 8-bit encodings: - * - u-Law and A-Law are native - * - linear are converted to 16-bit by auconv + * 8-bit u-Law and A-Law are native. */ - ARCOFI_FORMAT(AUDIO_ENCODING_ULAW, 8), - ARCOFI_FORMAT(AUDIO_ENCODING_ALAW, 8), + ARCOFI_FORMAT(1, AUDIO_ENCODING_ULAW, 8), + ARCOFI_FORMAT(0, AUDIO_ENCODING_ALAW, 8), /* - * 16-bit encodings: - * - slinear big-endian is native - * - unsigned or little-endian are converted by auconv + * 16-bit slinear big-endian is native. + * But it's hard to use due to hardware restrictions. */ - ARCOFI_FORMAT(AUDIO_ENCODING_SLINEAR_BE, 16), + ARCOFI_FORMAT(0, AUDIO_ENCODING_SLINEAR_BE, 16), }; #define ARCOFI_NFORMATS __arraycount(arcofi_formats) @@ -339,107 +333,60 @@ arcofi_close(void *v) { struct arcofi_softc *sc = (struct arcofi_softc *)v; - arcofi_halt_input(v); - arcofi_halt_output(v); sc->sc_open = 0; } static int -arcofi_drain(void *v) +arcofi_query_format(void *v, audio_format_query_t *afp) { - struct arcofi_softc *sc = (struct arcofi_softc *)v; - -#ifdef ARCOFI_DEBUG - printf("%s: %s, mode %d\n", - device_xname(sc->sc_dev), __func__, sc->sc_mode); -#endif - if ((arcofi_read(sc, ARCOFI_FIFO_SR) & FIFO_SR_OUT_EMPTY) == 0) { - /* enable output FIFO empty interrupt... */ - arcofi_write(sc, ARCOFI_FIFO_IR, - arcofi_read(sc, ARCOFI_FIFO_IR) | - FIFO_IR_ENABLE(FIFO_IR_OUT_EMPTY)); - /* ...and wait for it to fire */ - if (cv_timedwait(&sc->sc_cv, &sc->sc_intr_lock, - ((ARCOFI_FIFO_SIZE * hz) / 8000) + 100) != 0) { - printf("%s: drain did not complete\n", - device_xname(sc->sc_dev)); - arcofi_write(sc, ARCOFI_FIFO_IR, - arcofi_read(sc, ARCOFI_FIFO_IR) & - ~FIFO_IR_ENABLE(FIFO_IR_OUT_EMPTY)); - } - } - return 0; -} - -static int -arcofi_query_encoding(void *v, struct audio_encoding *aep) -{ - struct arcofi_softc *sc = (struct arcofi_softc *)v; - return auconv_query_encoding(sc->sc_encodings, aep); + return audio_query_format(arcofi_formats, ARCOFI_NFORMATS, afp); } -/* - * Compute proper sample and hardware settings. - */ static int -arcofi_set_params(void *handle, int setmode, int usemode, - audio_params_t *play, audio_params_t *rec, - stream_filter_list_t *pfil, stream_filter_list_t *rfil) +arcofi_set_format(void *handle, int setmode, + const audio_params_t *play, const audio_params_t *rec, + audio_filter_reg_t *pfil, audio_filter_reg_t *rfil) { struct arcofi_softc *sc; - int i; sc = handle; - for (i = 0; i < 2; i++) { - int mode; - audio_params_t *p; - stream_filter_list_t *fil; - int ind; - - switch (i) { - case 0: - mode = AUMODE_PLAY; - p = play; - fil = pfil; + + if ((setmode & AUMODE_PLAY)) { + switch (play->encoding) { + case AUDIO_ENCODING_ULAW: + pfil->codec = audio_internal_to_mulaw; break; - case 1: - mode = AUMODE_RECORD; - p = rec; - fil = rfil; + case AUDIO_ENCODING_ALAW: + pfil->codec = audio_internal_to_alaw; break; - default: - return EINVAL; } + } + if ((setmode & AUMODE_RECORD)) { + switch (rec->encoding) { + case AUDIO_ENCODING_ULAW: + rfil->codec = audio_mulaw_to_internal; + break; + case AUDIO_ENCODING_ALAW: + rfil->codec = audio_alaw_to_internal; + break; + } + } - if ((setmode & mode) == 0) - continue; - -#ifdef ARCOFI_DEBUG - printf("%s: %s, mode %d encoding %d precision %d\n", - device_xname(sc->sc_dev), __func__, - mode, p->encoding, p->precision); -#endif + /* *play and *rec are identical because !AUDIO_PROP_INDEPENDENT */ - ind = auconv_set_converter(arcofi_formats, ARCOFI_NFORMATS, - mode, p, false, fil); - if (ind < 0) - return EINVAL; - if (fil->req_size > 0) - p = &fil->filters[0].param; - if (p->precision == 8) { - if (p->encoding == AUDIO_ENCODING_ALAW) - sc->sc_shadow.cr4 &= ~CR4_ULAW; - else - sc->sc_shadow.cr4 |= CR4_ULAW; - sc->sc_shadow.cr3 = - (sc->sc_shadow.cr3 & ~CR3_OPMODE_MASK) | - CR3_OPMODE_NORMAL; - } else { - sc->sc_shadow.cr3 = - (sc->sc_shadow.cr3 & ~CR3_OPMODE_MASK) | - CR3_OPMODE_LINEAR; - } + if (play->precision == 8) { + if (play->encoding == AUDIO_ENCODING_ULAW) + sc->sc_shadow.cr4 |= CR4_ULAW; + else + sc->sc_shadow.cr4 &= ~CR4_ULAW; + sc->sc_shadow.cr3 = + (sc->sc_shadow.cr3 & ~CR3_OPMODE_MASK) | + CR3_OPMODE_NORMAL; + } else { + sc->sc_shadow.cr3 = + (sc->sc_shadow.cr3 & ~CR3_OPMODE_MASK) | + CR3_OPMODE_LINEAR; } return 0; @@ -528,6 +475,48 @@ arcofi_commit_settings(void *v) return rc; } +/* + * Take it out of the queue as much as possible. + */ +static int +arcofi_recv_data(struct arcofi_softc *sc) +{ + uint8_t *cur; + uint8_t *past; + + cur = sc->sc_recv.buf; + past = sc->sc_recv.past; + + while (cur != past && + (arcofi_read(sc, ARCOFI_FIFO_SR) & FIFO_SR_IN_EMPTY) == 0) { + *cur++ = arcofi_read(sc, ARCOFI_FIFO_DATA); + } + sc->sc_recv.buf = cur; + + return past - cur; +} + +/* + * Fill the queue as much as possible. + */ +static int +arcofi_xmit_data(struct arcofi_softc *sc) +{ + uint8_t *cur; + uint8_t *past; + + cur = sc->sc_xmit.buf; + past = sc->sc_xmit.past; + + while (cur != past && + (arcofi_read(sc, ARCOFI_FIFO_SR) & FIFO_SR_OUT_FULL) == 0) { + arcofi_write(sc, ARCOFI_FIFO_DATA, *cur++); + } + sc->sc_xmit.buf = cur; + + return past - cur; +} + static int arcofi_start_input(void *v, void *rbuf, int rsz, void (*cb)(void *), void *cbarg) @@ -1021,8 +1010,7 @@ int arcofi_hwintr(void *v) { struct arcofi_softc *sc = (struct arcofi_softc *)v; - uint8_t *cur, *past; - uint8_t csr, fir, data; + uint8_t csr, fir; int rc = 0; csr = arcofi_read(sc, ARCOFI_CSR); @@ -1032,67 +1020,35 @@ arcofi_hwintr(void *v) fir = arcofi_read(sc, ARCOFI_FIFO_IR); /* receive */ - if (fir & FIFO_IR_EVENT(FIFO_IR_IN_HALF_EMPTY)) { + if ((sc->sc_mode & AUMODE_RECORD) && + (fir & FIFO_IR_EVENT(FIFO_IR_IN_HALF_EMPTY))) { rc = 1; - cur = sc->sc_recv.buf; - past = sc->sc_recv.past; - - while ((arcofi_read(sc, ARCOFI_FIFO_SR) & - FIFO_SR_IN_EMPTY) == 0) { - data = arcofi_read(sc, ARCOFI_FIFO_DATA); - if (cur != NULL && cur != past) { - *cur++ = data; - if (cur == past) { - softint_schedule(sc->sc_sih); - break; - } - } - } - sc->sc_recv.buf = cur; - if (cur == NULL || cur == past) { - /* underrun, disable further interrupts */ + if (arcofi_recv_data(sc) == 0) { + /* disable further interrupts */ arcofi_write(sc, ARCOFI_FIFO_IR, arcofi_read(sc, ARCOFI_FIFO_IR) & ~FIFO_IR_ENABLE(FIFO_IR_IN_HALF_EMPTY)); + + /* callback */ + sc->sc_recv.cb(sc->sc_recv.cbarg); } } /* xmit */ - if (fir & FIFO_IR_EVENT(FIFO_IR_OUT_HALF_EMPTY)) { + if ((sc->sc_mode & AUMODE_PLAY) && + (fir & FIFO_IR_EVENT(FIFO_IR_OUT_HALF_EMPTY))) { rc = 1; - cur = sc->sc_xmit.buf; - past = sc->sc_xmit.past; - if (cur != NULL) { - while ((arcofi_read(sc, ARCOFI_FIFO_SR) & - FIFO_SR_OUT_FULL) == 0) { - if (cur != past) - arcofi_write(sc, ARCOFI_FIFO_DATA, - *cur++); - if (cur == past) { - softint_schedule(sc->sc_sih); - break; - } - } - } - if (cur == NULL || cur == past) { + + if (arcofi_xmit_data(sc) == 0) { /* disable further interrupts */ arcofi_write(sc, ARCOFI_FIFO_IR, arcofi_read(sc, ARCOFI_FIFO_IR) & ~FIFO_IR_ENABLE(FIFO_IR_OUT_HALF_EMPTY)); - } - sc->sc_xmit.buf = cur; - } - /* drain */ - if (fir & FIFO_IR_EVENT(FIFO_IR_OUT_EMPTY)) { - rc = 1; - arcofi_write(sc, ARCOFI_FIFO_IR, - arcofi_read(sc, ARCOFI_FIFO_IR) & - ~FIFO_IR_ENABLE(FIFO_IR_OUT_EMPTY)); - mutex_spin_enter(&sc->sc_intr_lock); - cv_signal(&sc->sc_cv); - mutex_spin_exit(&sc->sc_intr_lock); + /* callback */ + sc->sc_xmit.cb(sc->sc_xmit.cbarg); + } } #ifdef ARCOFI_DEBUG @@ -1105,30 +1061,6 @@ arcofi_hwintr(void *v) return rc; } -void -arcofi_swintr(void *v) -{ - struct arcofi_softc *sc = (struct arcofi_softc *)v; - int action; - - action = 0; - mutex_spin_enter(&sc->sc_intr_lock); - if (sc->sc_recv.buf != NULL && sc->sc_recv.buf == sc->sc_recv.past) - action |= AUMODE_RECORD; - if (sc->sc_xmit.buf != NULL && sc->sc_xmit.buf == sc->sc_xmit.past) - action |= AUMODE_PLAY; - - if (action & AUMODE_RECORD) { - if (sc->sc_recv.cb) - sc->sc_recv.cb(sc->sc_recv.cbarg); - } - if (action & AUMODE_PLAY) { - if (sc->sc_xmit.cb) - sc->sc_xmit.cb(sc->sc_xmit.cbarg); - } - mutex_spin_exit(&sc->sc_intr_lock); -} - static int arcofi_cmd(struct arcofi_softc *sc, uint8_t cmd, const uint8_t *data) { @@ -1208,11 +1140,6 @@ arcofi_attach(struct arcofi_softc *sc, c self = sc->sc_dev; mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO); - cv_init(&sc->sc_cv, device_xname(self)); - rc = auconv_create_encodings(arcofi_formats, ARCOFI_NFORMATS, - &sc->sc_encodings); - if (rc != 0) - goto out; /* * Reset logic. @@ -1275,8 +1202,6 @@ arcofi_attach(struct arcofi_softc *sc, c arcofi_write(sc, ARCOFI_ID, 0); aprint_error("%s: %02x command failed, error %d\n", __func__, op, rc); - out: - cv_destroy(&sc->sc_cv); mutex_destroy(&sc->sc_intr_lock); mutex_destroy(&sc->sc_lock); } Index: src/sys/dev/ic/arcofivar.h diff -u src/sys/dev/ic/arcofivar.h:1.1 src/sys/dev/ic/arcofivar.h:1.1.28.1 --- src/sys/dev/ic/arcofivar.h:1.1 Sun Aug 24 08:17:44 2014 +++ src/sys/dev/ic/arcofivar.h Sun Apr 21 06:55:34 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: arcofivar.h,v 1.1 2014/08/24 08:17:44 tsutsui Exp $ */ +/* $NetBSD: arcofivar.h,v 1.1.28.1 2019/04/21 06:55:34 isaki Exp $ */ /* $OpenBSD: arcofivar.h,v 1.2 2011/12/25 00:07:27 miod Exp $ */ /* @@ -26,7 +26,6 @@ struct arcofi_softc { bus_space_handle_t sc_ioh; struct audio_device sc_audio_device; - void *sc_sih; int sc_open; int sc_mode; @@ -47,10 +46,7 @@ struct arcofi_softc { sc_xmit; kmutex_t sc_lock; kmutex_t sc_intr_lock; - kcondvar_t sc_cv; - struct audio_encoding_set *sc_encodings; }; void arcofi_attach(struct arcofi_softc *, const char *); int arcofi_hwintr(void *); -void arcofi_swintr(void *);