Index: audiovar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/audiovar.h,v
retrieving revision 1.68
diff -u -p -r1.68 audiovar.h
--- audiovar.h 15 Nov 2017 04:28:45 -0000 1.68
+++ audiovar.h 23 Jun 2018 01:39:02 -0000
@@ -279,10 +279,8 @@ struct audio_softc {
bool schedule_wih;
bool schedule_rih;
- lwp_t *sc_playthread;
- kcondvar_t sc_condvar;
- lwp_t *sc_recthread;
- kcondvar_t sc_rcondvar;
+ void *sc_playmix_ih;
+ void *sc_recmix_ih;
/* These are changeable by sysctl to set the vchan common format */
struct sysctllog *sc_log; /* sysctl log */
Index: audio.c
===================================================================
RCS file: /cvsroot/src/sys/dev/audio.c,v
retrieving revision 1.457
diff -u -p -r1.457 audio.c
--- audio.c 22 May 2018 01:35:49 -0000 1.457
+++ audio.c 23 Jun 2018 01:39:03 -0000
@@ -182,7 +182,6 @@ __KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.
#include <sys/audioio.h>
#include <sys/device.h>
#include <sys/intr.h>
-#include <sys/kthread.h>
#include <sys/cpu.h>
#include <sys/mman.h>
@@ -227,6 +226,12 @@ int audio_idle_timeout = 30;
mutex_exit(sc->sc_intr_lock); \
} while (0)
+#define AUDIO_SOFTINT(x) do { \
+ kpreempt_disable(); \
+ softint_schedule(x); \
+ kpreempt_enable(); \
+} while (0)
+
int audio_blk_ms = AUDIO_BLK_MS;
int audiosetinfo(struct audio_softc *, struct audio_info *, bool,
@@ -270,12 +275,12 @@ void audio_rint(void *);
void audio_pint(void *);
void audio_mix(void *);
void audio_upmix(void *);
-void audio_play_thread(void *);
-void audio_rec_thread(void *);
+void audio_play_mix(void *);
+void audio_rec_mix(void *);
void recswvol_func(struct audio_softc *, struct audio_ringbuffer *,
size_t, struct virtual_channel *);
void mix_func(struct audio_softc *, struct audio_ringbuffer *,
- struct virtual_channel *);
+ struct virtual_channel *, uint8_t *, size_t, bool);
int mix_write(void *);
int mix_read(void *);
int audio_check_params(struct audio_params *);
@@ -285,6 +290,7 @@ static void audio_setblksize(struct audi
struct virtual_channel *, int, int);
int audio_calc_blksize(struct audio_softc *, const audio_params_t *);
void audio_fill_silence(const struct audio_params *, uint8_t *, int);
+void audio_wrap_silence(audio_stream_t *, int, int);
int audio_silence_copyout(struct audio_softc *, int, struct uio *);
static int audio_allocbufs(struct audio_softc *);
@@ -546,8 +552,6 @@ audioattach(device_t parent, device_t se
cv_init(&sc->sc_rchan, "audiord");
cv_init(&sc->sc_wchan, "audiowr");
cv_init(&sc->sc_lchan, "audiolk");
- cv_init(&sc->sc_condvar,"play");
- cv_init(&sc->sc_rcondvar,"record");
if (hwp == NULL || hwp->get_locks == NULL) {
aprint_error(": missing method\n");
@@ -855,10 +859,10 @@ audioattach(device_t parent, device_t se
#ifdef AUDIO_PM_IDLE
callout_schedule(&sc->sc_idle_counter, audio_idle_timeout * hz);
#endif
- kthread_create(PRI_SOFTSERIAL, KTHREAD_MPSAFE | KTHREAD_MUSTJOIN, NULL,
- audio_rec_thread, sc, &sc->sc_recthread, "audiorec");
- kthread_create(PRI_SOFTSERIAL, KTHREAD_MPSAFE | KTHREAD_MUSTJOIN, NULL,
- audio_play_thread, sc, &sc->sc_playthread, "audiomix");
+ sc->sc_recmix_ih = softint_establish(SOFTINT_SERIAL | SOFTINT_MPSAFE,
+ audio_rec_mix, sc);
+ sc->sc_playmix_ih = softint_establish(SOFTINT_SERIAL | SOFTINT_MPSAFE,
+ audio_play_mix, sc);
audiorescan(self, "audio", NULL);
}
@@ -872,8 +876,6 @@ audioactivate(device_t self, enum devact
mutex_enter(sc->sc_lock);
sc->sc_dying = true;
mutex_enter(sc->sc_intr_lock);
- cv_broadcast(&sc->sc_condvar);
- cv_broadcast(&sc->sc_rcondvar);
cv_broadcast(&sc->sc_wchan);
cv_broadcast(&sc->sc_rchan);
cv_broadcast(&sc->sc_lchan);
@@ -902,16 +904,6 @@ audiodetach(device_t self, int flags)
sc->sc_dying = true;
cv_broadcast(&sc->sc_wchan);
cv_broadcast(&sc->sc_rchan);
- mutex_enter(sc->sc_intr_lock);
- cv_broadcast(&sc->sc_condvar);
- cv_broadcast(&sc->sc_rcondvar);
- mutex_exit(sc->sc_intr_lock);
- mutex_exit(sc->sc_lock);
- kthread_join(sc->sc_playthread);
- kthread_join(sc->sc_recthread);
- mutex_enter(sc->sc_lock);
- cv_destroy(&sc->sc_condvar);
- cv_destroy(&sc->sc_rcondvar);
mutex_exit(sc->sc_lock);
/* delete sysctl nodes */
@@ -967,6 +959,14 @@ audiodetach(device_t self, int flags)
auconv_delete_encodings(sc->sc_encodings);
+ if (sc->sc_recmix_ih) {
+ softint_disestablish(sc->sc_recmix_ih);
+ sc->sc_recmix_ih = NULL;
+ }
+ if (sc->sc_playmix_ih) {
+ softint_disestablish(sc->sc_playmix_ih);
+ sc->sc_playmix_ih = NULL;
+ }
if (sc->sc_sih_rd) {
softint_disestablish(sc->sc_sih_rd);
sc->sc_sih_rd = NULL;
@@ -2450,36 +2450,29 @@ audio_drain(struct audio_softc *sc, stru
if (used <= 0)
return 0;
+ int blksize;
+ if (sc->sc_usemixer)
+ blksize = sc->sc_mixring.sc_mpr.blksize;
+ else
+ blksize = cb->blksize;
+
if (hw == false && !vc->sc_pbus) {
/* We've never started playing, probably because the
* block was too short. Pad it and start now.
*/
uint8_t *inp = cb->s.inp;
- int blksize = sc->sc_mixring.sc_mpr.blksize;
cc = blksize - (inp - cb->s.start) % blksize;
- audio_fill_silence(&cb->s.param, inp, cc);
- cb->s.inp = audio_stream_add_inp(&cb->s, inp, cc);
+ audio_wrap_silence(&cb->s, blksize, cc);
mutex_exit(sc->sc_intr_lock);
error = audiostartp(sc, vc);
mutex_enter(sc->sc_intr_lock);
if (error)
return error;
} else if (hw == true) {
- used = cb->blksize - (sc->sc_mixring.sc_mpr.s.inp -
- sc->sc_mixring.sc_mpr.s.start) % cb->blksize;
- while (used > 0) {
- cc = sc->sc_mixring.sc_mpr.s.end -
- sc->sc_mixring.sc_mpr.s.inp;
- if (cc > used)
- cc = used;
- audio_fill_silence(&cb->s.param,
- sc->sc_mixring.sc_mpr.s.inp, cc);
- sc->sc_mixring.sc_mpr.s.inp =
- audio_stream_add_inp(&sc->sc_mixring.sc_mpr.s,
- sc->sc_mixring.sc_mpr.s.inp, cc);
- used -= cc;
- }
+ cc = blksize - (sc->sc_mixring.sc_mpr.s.inp -
+ sc->sc_mixring.sc_mpr.s.start) % blksize;
+ audio_wrap_silence(&sc->sc_mixring.sc_mpr.s, blksize, cc);
mix_write(sc);
}
/*
@@ -2497,13 +2490,8 @@ audio_drain(struct audio_softc *sc, stru
vc->sc_draining = true;
drops = cb->drops;
- if (vc == sc->sc_hwvc)
- drops += cb->blksize;
- else if (sc->sc_usemixer)
- drops += sc->sc_mixring.sc_mpr.blksize * PREFILL_BLOCKS;
-
error = 0;
- while (cb->drops <= drops && !error) {
+ while (cb->drops == drops && !error) {
DPRINTF(("audio_drain: vc=%p used=%d, drops=%ld\n",
vc,
audio_stream_get_used(&vc->sc_mpr.s),
@@ -2798,6 +2786,22 @@ audio_calc_blksize(struct audio_softc *s
}
void
+audio_wrap_silence(audio_stream_t *stream, int blksize, int n)
+{
+ int cc, total;
+
+ total = n;
+ while (total > 0) {
+ cc = stream->end - stream->inp;
+ if (cc > total)
+ cc = total;
+ audio_fill_silence(&stream->param, stream->inp, cc);
+ stream->inp = audio_stream_add_inp(stream, stream->inp, cc);
+ total -= cc;
+ }
+};
+
+void
audio_fill_silence(const struct audio_params *params, uint8_t *p, int n)
{
uint8_t auzero0, auzero1;
@@ -3607,7 +3611,7 @@ audiostartr(struct audio_softc *sc, stru
mutex_enter(sc->sc_intr_lock);
error = mix_read(sc);
if (sc->sc_usemixer)
- cv_broadcast(&sc->sc_rcondvar);
+ AUDIO_SOFTINT(sc->sc_recmix_ih);
mutex_exit(sc->sc_intr_lock);
}
vc->sc_rbus = true;
@@ -3662,7 +3666,6 @@ audiostartp(struct audio_softc *sc, stru
audio_stream_add_outp(&vc->sc_mpr.s,
vc->sc_mpr.s.outp, vc->sc_mpr.blksize);
error = mix_write(sc);
- cv_broadcast(&sc->sc_condvar);
}
done:
mutex_exit(sc->sc_intr_lock);
@@ -3723,20 +3726,25 @@ audio_pint(void *v)
struct audio_softc *sc;
struct audio_ringbuffer *cb;
struct virtual_channel *vc;
- int blksize, cc, used;
+ audio_stream_t *stream;
+ int blksize, cc, silblksize, used;
sc = v;
vc = sc->sc_hwvc;
blksize = vc->sc_mpr.blksize;
+ if (sc->sc_usemixer) {
+ stream = &sc->sc_mixring.sc_mpr.s;
+ silblksize = sc->sc_mixring.sc_mpr.blksize;
+ cb = &sc->sc_mixring.sc_mpr;
+ } else {
+ stream = vc->sc_pustream;
+ silblksize = blksize;
+ cb = &vc->sc_mpr;
+ }
if (sc->sc_dying == true || sc->sc_trigger_started == false)
return;
- if (sc->sc_usemixer)
- cb = &sc->sc_mixring.sc_mpr;
- else
- cb = &vc->sc_mpr;
-
if (vc->sc_draining && cb->drops != sc->sc_last_drops) {
vc->sc_mpr.drops += blksize;
cv_broadcast(&sc->sc_wchan);
@@ -3747,27 +3755,22 @@ audio_pint(void *v)
vc->sc_mpr.s.outp = audio_stream_add_outp(&vc->sc_mpr.s,
vc->sc_mpr.s.outp, blksize);
- if (audio_stream_get_used(&cb->s) < blksize) {
+ used = audio_stream_get_used(stream);
+
+ if (used < silblksize) {
DPRINTFN(3, ("HW RING - INSERT SILENCE\n"));
- used = blksize;
- while (used > 0) {
- cc = cb->s.end - cb->s.inp;
- if (cc > used)
- cc = used;
- audio_fill_silence(&cb->s.param, cb->s.inp, cc);
- cb->s.inp =
- audio_stream_add_inp(&cb->s, cb->s.inp, cc);
- used -= cc;
- }
- vc->sc_mpr.drops += blksize;
+ cc = silblksize - used;
+ audio_wrap_silence(stream, silblksize, cc);
+ cb->drops += silblksize;
}
mix_write(sc);
- if (sc->sc_usemixer)
- cv_broadcast(&sc->sc_condvar);
- else
+ if (!sc->sc_usemixer)
cv_broadcast(&sc->sc_wchan);
+ else if (!vc->sc_draining)
+ AUDIO_SOFTINT(sc->sc_playmix_ih);
+
}
void
@@ -3778,9 +3781,13 @@ audio_mix(void *v)
struct audio_chan *chan;
struct virtual_channel *vc;
struct audio_ringbuffer *cb;
+ audio_stream_t *hwstream;
stream_fetcher_t *fetcher;
uint8_t *inp;
- int cc, cc1, used, blksize;
+ int cc, used, blksize;
+ size_t total;
+ unsigned int chancount;
+ bool first;
sc = v;
@@ -3792,7 +3799,13 @@ audio_mix(void *v)
if (sc->sc_dying == true)
return;
+ chancount = 0;
blksize = sc->sc_mixring.sc_mpr.blksize;
+ hwstream = &sc->sc_mixring.sc_mpr.s;
+
+ if (audio_stream_get_used(hwstream) > sc->sc_hwvc->sc_mpr.usedlow)
+ return;
+
SIMPLEQ_FOREACH(chan, &sc->sc_audiochan, entries) {
vc = chan->vc;
@@ -3804,15 +3817,27 @@ audio_mix(void *v)
cb = &vc->sc_mpr;
sc->sc_writeme = true;
+ chancount++;
+ if (chancount == 1)
+ first = true;
+ else
+ first = false;
inp = cb->s.inp;
cb->stamp += blksize;
+ total = blksize;
+
if (cb->mmapped) {
DPRINTF(("audio_pint: vc=%p mmapped outp=%p cc=%d "
"inp=%p\n", vc, cb->s.outp, blksize,
cb->s.inp));
mutex_enter(sc->sc_intr_lock);
- mix_func(sc, cb, vc);
+ if (first)
+ mix_func(sc, cb, vc, hwstream->inp, total,
+ first);
+ else
+ mix_func(sc, cb, vc, __UNCONST(hwstream->outp),
+ total, first);
cb->s.outp = audio_stream_add_outp(&cb->s, cb->s.outp,
blksize);
mutex_exit(sc->sc_intr_lock);
@@ -3861,7 +3886,7 @@ audio_mix(void *v)
* at accurate timing. If used < blksize, uaudio(4) already
* request transfer of garbage data.
*/
- if (used <= sc->sc_hwvc->sc_mpr.usedlow && !cb->copying &&
+ if (used <= cb->usedlow && !cb->copying &&
vc->sc_npfilters > 0) {
/* we might have data in filter pipeline */
null_fetcher.fetch_to = null_fetcher_fetch_to;
@@ -3876,6 +3901,7 @@ audio_mix(void *v)
cb->fstamp += used -
audio_stream_get_used(vc->sc_pustream);
used = audio_stream_get_used(&cb->s);
+ sc->schedule_wih = true;
}
if (used < blksize) {
/* we don't have a full block to use */
@@ -3889,31 +3915,37 @@ audio_mix(void *v)
"used=%d blksize=%d\n", vc, used,
blksize));
inp = cb->s.inp;
- cc = blksize - (inp - cb->s.start) % blksize;
+ cc = blksize - used;
if (cb->pause)
cb->pdrops += cc;
else {
cb->drops += cc;
vc->sc_playdrop += cc;
}
-
- audio_fill_silence(&cb->s.param, inp, cc);
- cb->s.inp = audio_stream_add_inp(&cb->s, inp,
- cc);
-
- /* Clear next block to keep ahead of the DMA. */
- used = audio_stream_get_used(&cb->s);
- if (used + blksize < cb->s.end - cb->s.start) {
- audio_fill_silence(&cb->s.param, cb->s.inp,
- blksize);
+ if (first)
+ audio_wrap_silence(&cb->s, blksize, cc);
+ else {
+ total = blksize - cc;
+ cb->s.inp = audio_stream_add_inp(&cb->s,
+ inp, cc);
}
}
}
DPRINTFN(5, ("audio_pint: vc=%p outp=%p used=%d cc=%d\n", vc,
cb->s.outp, used, blksize));
+
+ /*
+ * Mix at the tail of the ringbuffer if it's the first vc
+ * otherwize mix at the current playback position in the
+ * mix ring. This imroves latency for virtual channels
+ * greater than 1.
+ */
mutex_enter(sc->sc_intr_lock);
- mix_func(sc, cb, vc);
+ if (first)
+ mix_func(sc, cb, vc, hwstream->inp, total, first);
+ else
+ mix_func(sc, cb, vc, __UNCONST(hwstream->outp), total, first);
mutex_exit(sc->sc_intr_lock);
cb->s.outp = audio_stream_add_outp(&cb->s, cb->s.outp, blksize);
@@ -3932,27 +3964,16 @@ audio_mix(void *v)
mutex_enter(sc->sc_intr_lock);
vc = sc->sc_hwvc;
- cb = &sc->sc_mixring.sc_mpr;
- inp = cb->s.inp;
- cc = blksize - (inp - cb->s.start) % blksize;
+ inp = hwstream->inp;
if (sc->sc_writeme == false) {
+ cc = blksize - audio_stream_get_used(hwstream);
DPRINTFN(3, ("MIX RING EMPTY - INSERT SILENCE\n"));
- audio_fill_silence(&vc->sc_pustream->param, inp, cc);
- sc->sc_mixring.sc_mpr.drops += cc;
- } else
+ audio_wrap_silence(hwstream, blksize, cc);
+ vc->sc_mpr.drops += cc;
+ } else {
cc = blksize;
- cb->s.inp = audio_stream_add_inp(&cb->s, cb->s.inp, cc);
- cc = blksize;
- cc1 = sc->sc_mixring.sc_mpr.s.end - sc->sc_mixring.sc_mpr.s.inp;
- if (cc1 < cc) {
- audio_fill_silence(&vc->sc_pustream->param,
- sc->sc_mixring.sc_mpr.s.inp, cc1);
- cc -= cc1;
- audio_fill_silence(&vc->sc_pustream->param,
- sc->sc_mixring.sc_mpr.s.start, cc);
- } else
- audio_fill_silence(&vc->sc_pustream->param,
- sc->sc_mixring.sc_mpr.s.inp, cc);
+ hwstream->inp = audio_stream_add_inp(hwstream, inp, cc);
+ }
mutex_exit(sc->sc_intr_lock);
kpreempt_disable();
@@ -3989,7 +4010,7 @@ audio_rint(void *v)
mix_read(sc);
if (sc->sc_usemixer)
- cv_broadcast(&sc->sc_rcondvar);
+ AUDIO_SOFTINT(sc->sc_recmix_ih);
else
cv_broadcast(&sc->sc_rchan);
}
@@ -4114,9 +4135,7 @@ audio_upmix(void *v)
blksize);
}
}
- kpreempt_disable();
- softint_schedule(sc->sc_sih_rd);
- kpreempt_enable();
+ AUDIO_SOFTINT(sc->sc_sih_rd);
}
int
@@ -4243,6 +4262,8 @@ audio_set_vchan_defaults(struct audio_so
vc->sc_rparams = sc->sc_vchan_params;
vc->sc_pparams = sc->sc_vchan_params;
+ vc->sc_pustream = &vc->sc_mpr.s;
+ vc->sc_rustream = &vc->sc_mrr.s;
}
return error;
@@ -5586,19 +5607,24 @@ mix_write(void *arg)
stream_filter_t *filter;
stream_fetcher_t *fetcher;
stream_fetcher_t null_fetcher;
- int cc, cc1, cc2, error, used;
+ int blksize, cc, cc1, cc2, error, used;
const uint8_t *orig;
uint8_t *tocopy;
vc = sc->sc_hwvc;
error = 0;
+ if (sc->sc_usemixer)
+ blksize = sc->sc_mixring.sc_mpr.blksize;
+ else
+ blksize = vc->sc_mpr.blksize;
+
if (sc->sc_usemixer &&
- audio_stream_get_used(vc->sc_pustream) <=
- sc->sc_mixring.sc_mpr.blksize) {
+ audio_stream_get_used(vc->sc_pustream) <
+ vc->sc_mpr.usedlow) {
tocopy = vc->sc_pustream->inp;
orig = sc->sc_mixring.sc_mpr.s.outp;
- used = sc->sc_mixring.sc_mpr.blksize;
+ used = blksize;
while (used > 0) {
cc = used;
@@ -5621,35 +5647,34 @@ mix_write(void *arg)
}
vc->sc_pustream->inp = audio_stream_add_inp(vc->sc_pustream,
- vc->sc_pustream->inp, sc->sc_mixring.sc_mpr.blksize);
+ vc->sc_pustream->inp, blksize);
sc->sc_mixring.sc_mpr.s.outp =
audio_stream_add_outp(&sc->sc_mixring.sc_mpr.s,
- sc->sc_mixring.sc_mpr.s.outp,
- sc->sc_mixring.sc_mpr.blksize);
+ sc->sc_mixring.sc_mpr.s.outp, blksize);
}
+ blksize = vc->sc_mpr.blksize;
if (vc->sc_npfilters > 0 &&
(sc->sc_usemixer || sc->sc_trigger_started)) {
null_fetcher.fetch_to = null_fetcher_fetch_to;
filter = vc->sc_pfilters[0];
filter->set_fetcher(filter, &null_fetcher);
fetcher = &vc->sc_pfilters[vc->sc_npfilters - 1]->base;
- fetcher->fetch_to(sc, fetcher, &vc->sc_mpr.s,
- vc->sc_mpr.blksize * 2);
+ fetcher->fetch_to(sc, fetcher, &vc->sc_mpr.s, blksize * 2);
}
if (sc->hw_if->trigger_output && sc->sc_trigger_started == false) {
DPRINTF(("%s: call trigger_output\n", __func__));
sc->sc_trigger_started = true;
error = sc->hw_if->trigger_output(sc->hw_hdl,
- vc->sc_mpr.s.start, vc->sc_mpr.s.end, vc->sc_mpr.blksize,
+ vc->sc_mpr.s.start, vc->sc_mpr.s.end, blksize,
audio_pint, (void *)sc, &vc->sc_mpr.s.param);
} else if (sc->hw_if->start_output) {
DPRINTF(("%s: call start_output\n", __func__));
sc->sc_trigger_started = true;
error = sc->hw_if->start_output(sc->hw_hdl,
- __UNCONST(vc->sc_mpr.s.outp), vc->sc_mpr.blksize,
+ __UNCONST(vc->sc_mpr.s.outp), blksize,
audio_pint, (void *)sc);
}
@@ -5666,18 +5691,18 @@ mix_write(void *arg)
#define DEF_MIX_FUNC(bits, type, bigger_type, MINVAL, MAXVAL) \
static void \
mix_func##bits(struct audio_softc *sc, struct audio_ringbuffer *cb, \
- struct virtual_channel *vc) \
+ struct virtual_channel *vc, uint8_t *target, \
+ size_t bytes, bool first) \
{ \
- int blksize, cc, cc1, cc2, m, resid; \
+ int cc, cc1, cc2, m, resid; \
bigger_type product; \
bigger_type result; \
type *orig, *tomix; \
\
- blksize = sc->sc_mixring.sc_mpr.blksize; \
- resid = blksize; \
+ resid = bytes; \
\
tomix = __UNCONST(cb->s.outp); \
- orig = (type *)(sc->sc_mixring.sc_mpr.s.inp); \
+ orig = (type *)(target); \
\
while (resid > 0) { \
cc = resid; \
@@ -5695,22 +5720,23 @@ mix_write(void *arg)
tomix[m] = (bigger_type)tomix[m] * \
(bigger_type)(vc->sc_swvol) / 255; \
vol_done: \
+ if (first) { \
+ orig[m] = tomix[m]; \
+ continue; \
+ } \
result = (bigger_type)orig[m] + tomix[m]; \
- if (sc->sc_opens == 1) \
- goto adj_done; \
product = (bigger_type)orig[m] * tomix[m]; \
if (orig[m] > 0 && tomix[m] > 0) \
result -= product / MAXVAL; \
else if (orig[m] < 0 && tomix[m] < 0) \
result -= product / MINVAL; \
-adj_done: \
orig[m] = result; \
} \
\
if (&orig[m] >= \
(type *)sc->sc_mixring.sc_mpr.s.end) \
orig = \
- (type *)sc->sc_mixring.sc_mpr.s.start; \
+ (type *)sc->sc_mixring.sc_mpr.s.start; \
if (&tomix[m] >= (type *)cb->s.end) \
tomix = (type *)cb->s.start; \
\
@@ -5724,18 +5750,18 @@ DEF_MIX_FUNC(32, int32_t, int64_t, INT32
void
mix_func(struct audio_softc *sc, struct audio_ringbuffer *cb,
- struct virtual_channel *vc)
+ struct virtual_channel *vc, uint8_t *target, size_t used, bool first)
{
switch (sc->sc_vchan_params.precision) {
case 8:
- mix_func8(sc, cb, vc);
+ mix_func8(sc, cb, vc, target, used, first);
break;
case 16:
- mix_func16(sc, cb, vc);
+ mix_func16(sc, cb, vc, target, used, first);
break;
case 24:
case 32:
- mix_func32(sc, cb, vc);
+ mix_func32(sc, cb, vc, target, used, first);
break;
default:
break;
@@ -5967,59 +5993,43 @@ audio_query_encoding(struct audio_softc
}
void
-audio_play_thread(void *v)
+audio_play_mix(void *v)
{
struct audio_softc *sc;
sc = (struct audio_softc *)v;
- for (;;) {
- mutex_enter(sc->sc_lock);
- if (sc->sc_dying) {
- mutex_exit(sc->sc_lock);
- kthread_exit(0);
- }
- if (!sc->sc_trigger_started)
- goto play_wait;
-
- while (!sc->sc_dying && sc->sc_usemixer &&
- audio_stream_get_used(&sc->sc_mixring.sc_mpr.s) <
- sc->sc_mixring.sc_mpr.blksize)
- audio_mix(sc);
-
-play_wait:
+ mutex_enter(sc->sc_lock);
+ if (sc->sc_dying) {
mutex_exit(sc->sc_lock);
-
- mutex_enter(sc->sc_intr_lock);
- cv_wait_sig(&sc->sc_condvar, sc->sc_intr_lock);
- mutex_exit(sc->sc_intr_lock);
+ return;
+ }
+
+ int i;
+ for (i = 0; i < PREFILL_BLOCKS; i++) {
+ int used = audio_stream_get_used(&sc->sc_mixring.sc_mpr.s);
+ if (!sc->sc_dying && !sc->sc_hwvc->sc_draining &&
+ sc->sc_usemixer && used < sc->sc_mixring.sc_mpr.blksize *
+ PREFILL_BLOCKS)
+ audio_mix(sc);
}
+ mutex_exit(sc->sc_lock);
}
void
-audio_rec_thread(void *v)
+audio_rec_mix(void *v)
{
struct audio_softc *sc;
sc = (struct audio_softc *)v;
- for (;;) {
- mutex_enter(sc->sc_lock);
- if (sc->sc_dying) {
- mutex_exit(sc->sc_lock);
- kthread_exit(0);
- }
- if (!sc->sc_rec_started)
- goto rec_wait;
-
- audio_upmix(sc);
-rec_wait:
+ mutex_enter(sc->sc_lock);
+ if (sc->sc_dying) {
mutex_exit(sc->sc_lock);
-
- mutex_enter(sc->sc_intr_lock);
- cv_wait_sig(&sc->sc_rcondvar, sc->sc_intr_lock);
- mutex_exit(sc->sc_intr_lock);
+ return;
}
+ audio_upmix(sc);
+ mutex_exit(sc->sc_lock);
}