Module Name: src Committed By: nat Date: Sun Dec 25 22:44:24 UTC 2016
Modified Files: src/sys/dev: audio.c Log Message: Fix suspend/resume logic. To generate a diff of this commit: cvs rdiff -u -r1.286 -r1.287 src/sys/dev/audio.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/audio.c diff -u src/sys/dev/audio.c:1.286 src/sys/dev/audio.c:1.287 --- src/sys/dev/audio.c:1.286 Fri Dec 23 21:01:00 2016 +++ src/sys/dev/audio.c Sun Dec 25 22:44:24 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: audio.c,v 1.286 2016/12/23 21:01:00 nat Exp $ */ +/* $NetBSD: audio.c,v 1.287 2016/12/25 22:44:24 nat Exp $ */ /*- * Copyright (c) 2016 Nathanial Sloss <nathanialsl...@yahoo.com.au> @@ -87,7 +87,7 @@ */ /* - * Locking: there are three locks. + * Locking: there are two locks. * * - sc_lock, provided by the underlying driver. This is an adaptive lock, * returned in the second parameter to hw_if->get_locks(). It is known @@ -148,7 +148,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.286 2016/12/23 21:01:00 nat Exp $"); +__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.287 2016/12/25 22:44:24 nat Exp $"); #include "audio.h" #if NAUDIO > 0 @@ -480,6 +480,7 @@ audioattach(device_t parent, device_t se sc->sc_trigger_started = false; sc->sc_rec_started = false; + sc->sc_dying = false; sc->sc_vchan[0] = kmem_zalloc(sizeof(struct virtual_channel), KM_SLEEP); vc = sc->sc_vchan[0]; memset(sc->sc_audiopid, -1, sizeof(sc->sc_audiopid)); @@ -853,6 +854,7 @@ audioactivate(device_t self, enum devact case DVACT_DEACTIVATE: mutex_enter(sc->sc_lock); sc->sc_dying = true; + cv_broadcast(&sc->sc_condvar); mutex_exit(sc->sc_lock); return 0; default: @@ -5018,23 +5020,27 @@ audio_suspend(device_t dv, const pmf_qua { struct audio_softc *sc = device_private(dv); const struct audio_hw_if *hwp = sc->hw_if; + struct virtual_channel *vc; int n; + bool pbus, rbus; + pbus = rbus = false; mutex_enter(sc->sc_lock); + audio_mixer_capture(sc); for (n = 1; n < VAUDIOCHANS; n++) { - if (sc->sc_audiopid[n].pid == curproc->p_pid) - break; - } - if (n == VAUDIOCHANS) { - mutex_exit(sc->sc_lock); - return false; - } + if (sc->sc_audiopid[n].pid == -1) + continue; - audio_mixer_capture(sc); + vc = sc->sc_vchan[n]; + if (vc->sc_pbus && !pbus) + pbus = true; + if (vc->sc_rbus && !rbus) + rbus = true; + } mutex_enter(sc->sc_intr_lock); - if (sc->sc_vchan[n]->sc_pbus == true) + if (pbus == true) hwp->halt_output(sc->hw_hdl); - if (sc->sc_recopens == 1 && sc->sc_vchan[n]->sc_rbus == true) + if (rbus == true) hwp->halt_input(sc->hw_hdl); mutex_exit(sc->sc_intr_lock); #ifdef AUDIO_PM_IDLE @@ -5052,25 +5058,28 @@ audio_resume(device_t dv, const pmf_qual struct virtual_channel *vc; int n; - for (n = 1; n < VAUDIOCHANS; n++) { - if (sc->sc_audiopid[n].pid == curproc->p_pid) - break; - } - - if (n == VAUDIOCHANS) - return false; - vc = sc->sc_vchan[n]; - mutex_enter(sc->sc_lock); - if (vc->sc_lastinfovalid) - audiosetinfo(sc, &vc->sc_lastinfo, true, n); + sc->sc_trigger_started = false; + sc->sc_rec_started = false; + + audio_set_vchan_defaults(sc, AUMODE_PLAY | AUMODE_PLAY_ALL | + AUMODE_RECORD, &vaudio_formats[0], 0); + audio_mixer_restore(sc); - mutex_enter(sc->sc_intr_lock); - if ((vc->sc_pbus == true) && !vc->sc_mpr.pause) - audiostartp(sc, n); - if ((vc->sc_rbus == true) && !vc->sc_mrr.pause) - audiostartr(sc, n); - mutex_exit(sc->sc_intr_lock); + for (n = 1; n < VAUDIOCHANS; n++) { + if (sc->sc_audiopid[n].pid == -1) + continue; + vc = sc->sc_vchan[n]; + + if (vc->sc_lastinfovalid == true) + audiosetinfo(sc, &vc->sc_lastinfo, true, n); + mutex_enter(sc->sc_intr_lock); + if (vc->sc_pbus == true && !vc->sc_mpr.pause) + audiostartp(sc, n); + if (vc->sc_rbus == true && !vc->sc_mrr.pause) + audiostartr(sc, n); + mutex_exit(sc->sc_intr_lock); + } mutex_exit(sc->sc_lock); return true; @@ -5248,6 +5257,7 @@ mix_write(void *arg) vc = sc->sc_vchan[0]; blksize = vc->sc_mpr.blksize; cc = blksize; + error = 0; cc1 = cc; if (vc->sc_pustream->inp + cc > vc->sc_pustream->end) @@ -5280,13 +5290,15 @@ mix_write(void *arg) error = sc->hw_if->start_output(sc->hw_hdl, __UNCONST(vc->sc_mpr.s.outp), blksize, audio_pint, (void *)sc); - if (error) { - /* XXX does this really help? */ - DPRINTF(("audio_mix restart failed: %d\n", error)); - audio_clear(sc, 0); - } } sc->sc_trigger_started = true; + + if (error) { + /* XXX does this really help? */ + DPRINTF(("audio_mix restart failed: %d\n", error)); + audio_clear(sc, 0); + sc->sc_trigger_started = false; + } } void