Module Name:    src
Committed By:   snj
Date:           Fri Oct 16 05:43:38 UTC 2009

Modified Files:
        src/share/man/man4 [netbsd-5]: audio.4
        src/sys/dev [netbsd-5]: audio.c audio_if.h
        src/sys/dev/pci/hdaudio [netbsd-5]: hdaudio_afg.c
        src/sys/sys [netbsd-5]: audioio.h

Log Message:
Pull up following revision(s) (requested by sborrill in ticket #1038):
        share/man/man4/audio.4: revision 1.70 via patch
        sys/dev/audio.c: revision 1.248
        sys/dev/audio_if.h: revision 1.66
        sys/dev/pci/hdaudio/hdaudio_afg.c: revision 1.16
        sys/sys/audioio.h: revision 1.33
Add support for playback- or capture-only devices.
Fixes PR 42050


To generate a diff of this commit:
cvs rdiff -u -r1.68 -r1.68.4.1 src/share/man/man4/audio.4
cvs rdiff -u -r1.243.6.2 -r1.243.6.3 src/sys/dev/audio.c
cvs rdiff -u -r1.65 -r1.65.14.1 src/sys/dev/audio_if.h
cvs rdiff -u -r1.14.2.3 -r1.14.2.4 src/sys/dev/pci/hdaudio/hdaudio_afg.c
cvs rdiff -u -r1.32 -r1.32.44.1 src/sys/sys/audioio.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/share/man/man4/audio.4
diff -u src/share/man/man4/audio.4:1.68 src/share/man/man4/audio.4:1.68.4.1
--- src/share/man/man4/audio.4:1.68	Wed Apr 30 13:10:53 2008
+++ src/share/man/man4/audio.4	Fri Oct 16 05:43:37 2009
@@ -1,4 +1,4 @@
-.\"	$NetBSD: audio.4,v 1.68 2008/04/30 13:10:53 martin Exp $
+.\"	$NetBSD: audio.4,v 1.68.4.1 2009/10/16 05:43:37 snj Exp $
 .\"
 .\" Copyright (c) 1996 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -27,7 +27,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd June 11, 2007
+.Dd September 29, 2009
 .Dt AUDIO 4
 .Os
 .Sh NAME
@@ -243,6 +243,10 @@
 .It Dv AUDIO_PROP_INDEPENDENT
 the device can set the playing and recording encoding parameters
 independently.
+.It Dv AUDIO_PROP_PLAYBACK
+the device is capable of audio playback.
+.It Dv AUDIO_PROP_CAPTURE
+the device is capable of audio capture.
 .El
 .It Dv AUDIO_GETIOFFS (audio_offset_t)
 .It Dv AUDIO_GETOOFFS (audio_offset_t)

Index: src/sys/dev/audio.c
diff -u src/sys/dev/audio.c:1.243.6.2 src/sys/dev/audio.c:1.243.6.3
--- src/sys/dev/audio.c:1.243.6.2	Tue Sep 29 22:50:11 2009
+++ src/sys/dev/audio.c	Fri Oct 16 05:43:37 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: audio.c,v 1.243.6.2 2009/09/29 22:50:11 snj Exp $	*/
+/*	$NetBSD: audio.c,v 1.243.6.3 2009/10/16 05:43:37 snj Exp $	*/
 
 /*
  * Copyright (c) 1991-1993 Regents of the University of California.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.243.6.2 2009/09/29 22:50:11 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.243.6.3 2009/10/16 05:43:37 snj Exp $");
 
 #include "audio.h"
 #if NAUDIO > 0
@@ -192,6 +192,10 @@
 static void	audio_mixer_capture(struct audio_softc *);
 static void	audio_mixer_restore(struct audio_softc *);
 
+static int	audio_get_props(struct audio_softc *);
+static bool	audio_can_playback(struct audio_softc *);
+static bool	audio_can_capture(struct audio_softc *);
+
 static void	audio_softintr_rd(void *);
 static void	audio_softintr_wr(void *);
 
@@ -314,41 +318,51 @@
 	}
 #endif
 
-	props = hwp->get_props(hdlp);
+	sc->hw_if = hwp;
+	sc->hw_hdl = hdlp;
+	sc->sc_dev = parent;
+	sc->sc_opencnt = 0;
+	sc->sc_writing = sc->sc_waitcomp = 0;
+	sc->sc_lastinfovalid = false;
 
-	aprint_naive("\n");
+	props = audio_get_props(sc);
 
 	if (props & AUDIO_PROP_FULLDUPLEX)
 		aprint_normal(": full duplex");
 	else
 		aprint_normal(": half duplex");
 
+	if (props & AUDIO_PROP_PLAYBACK)
+		aprint_normal(", playback");
+	if (props & AUDIO_PROP_CAPTURE)
+		aprint_normal(", capture");
 	if (props & AUDIO_PROP_MMAP)
 		aprint_normal(", mmap");
 	if (props & AUDIO_PROP_INDEPENDENT)
 		aprint_normal(", independent");
 
+	aprint_naive("\n");
 	aprint_normal("\n");
 
-	sc->hw_if = hwp;
-	sc->hw_hdl = hdlp;
-	sc->sc_dev = parent;
-	sc->sc_opencnt = 0;
-	sc->sc_writing = sc->sc_waitcomp = 0;
-	sc->sc_lastinfovalid = false;
-
-	error = audio_alloc_ring(sc, &sc->sc_pr, AUMODE_PLAY, AU_RING_SIZE);
-	if (error) {
-		sc->hw_if = NULL;
-		aprint_error("audio: could not allocate play buffer\n");
-		return;
+	if (audio_can_playback(sc)) {
+		error = audio_alloc_ring(sc, &sc->sc_pr,
+		    AUMODE_PLAY, AU_RING_SIZE);
+		if (error) {
+			sc->hw_if = NULL;
+			aprint_error("audio: could not allocate play buffer\n");
+			return;
+		}
 	}
-	error = audio_alloc_ring(sc, &sc->sc_rr, AUMODE_RECORD, AU_RING_SIZE);
-	if (error) {
-		audio_free_ring(sc, &sc->sc_pr);
-		sc->hw_if = NULL;
-		aprint_error("audio: could not allocate record buffer\n");
-		return;
+	if (audio_can_capture(sc)) {
+		error = audio_alloc_ring(sc, &sc->sc_rr,
+		    AUMODE_RECORD, AU_RING_SIZE);
+		if (error) {
+			if (sc->sc_pr.s.start != 0)
+				audio_free_ring(sc, &sc->sc_pr);
+			sc->hw_if = NULL;
+			aprint_error("audio: could not allocate record buffer\n");
+			return;
+		}
 	}
 
 	sc->sc_lastgain = 128;
@@ -741,6 +755,8 @@
 void
 audio_free_ring(struct audio_softc *sc, struct audio_ringbuffer *r)
 {
+	if (r->s.start == 0)
+		return;
 
 	if (sc->hw_if->freem)
 		sc->hw_if->freem(sc->hw_hdl, r->s.start, M_DEVBUF);
@@ -1300,41 +1316,49 @@
 
 	DPRINTF(("audio_initbufs: mode=0x%x\n", sc->sc_mode));
 	hw = sc->hw_if;
-	audio_init_ringbuffer(sc, &sc->sc_rr, AUMODE_RECORD);
-	if (hw->init_input && (sc->sc_mode & AUMODE_RECORD)) {
-		error = hw->init_input(sc->hw_hdl, sc->sc_rr.s.start,
+	if (audio_can_capture(sc)) {
+		audio_init_ringbuffer(sc, &sc->sc_rr, AUMODE_RECORD);
+		if (hw->init_input && (sc->sc_mode & AUMODE_RECORD)) {
+			error = hw->init_input(sc->hw_hdl, sc->sc_rr.s.start,
 				       sc->sc_rr.s.end - sc->sc_rr.s.start);
-		if (error)
-			return error;
+			if (error)
+				return error;
+		}
 	}
 
-	audio_init_ringbuffer(sc, &sc->sc_pr, AUMODE_PLAY);
-	sc->sc_sil_count = 0;
-	if (hw->init_output && (sc->sc_mode & AUMODE_PLAY)) {
-		error = hw->init_output(sc->hw_hdl, sc->sc_pr.s.start,
+	if (audio_can_playback(sc)) {
+		audio_init_ringbuffer(sc, &sc->sc_pr, AUMODE_PLAY);
+		sc->sc_sil_count = 0;
+		if (hw->init_output && (sc->sc_mode & AUMODE_PLAY)) {
+			error = hw->init_output(sc->hw_hdl, sc->sc_pr.s.start,
 					sc->sc_pr.s.end - sc->sc_pr.s.start);
-		if (error)
-			return error;
+			if (error)
+				return error;
+		}
 	}
 
 #ifdef AUDIO_INTR_TIME
 #define double u_long
-	sc->sc_pnintr = 0;
-	sc->sc_pblktime = (u_long)(
-	    (double)sc->sc_pr.blksize * 100000 /
-	    (double)(sc->sc_pparams.precision / NBBY *
-		     sc->sc_pparams.channels *
-		     sc->sc_pparams.sample_rate)) * 10;
-	DPRINTF(("audio: play blktime = %lu for %d\n",
-		 sc->sc_pblktime, sc->sc_pr.blksize));
-	sc->sc_rnintr = 0;
-	sc->sc_rblktime = (u_long)(
-	    (double)sc->sc_rr.blksize * 100000 /
-	    (double)(sc->sc_rparams.precision / NBBY *
-		     sc->sc_rparams.channels *
-		     sc->sc_rparams.sample_rate)) * 10;
-	DPRINTF(("audio: record blktime = %lu for %d\n",
-		 sc->sc_rblktime, sc->sc_rr.blksize));
+	if (audio_can_playback(sc)) {
+		sc->sc_pnintr = 0;
+		sc->sc_pblktime = (u_long)(
+		    (double)sc->sc_pr.blksize * 100000 /
+		    (double)(sc->sc_pparams.precision / NBBY *
+			     sc->sc_pparams.channels *
+			     sc->sc_pparams.sample_rate)) * 10;
+		DPRINTF(("audio: play blktime = %lu for %d\n",
+			 sc->sc_pblktime, sc->sc_pr.blksize));
+	}
+	if (audio_can_capture(sc)) {
+		sc->sc_rnintr = 0;
+		sc->sc_rblktime = (u_long)(
+		    (double)sc->sc_rr.blksize * 100000 /
+		    (double)(sc->sc_rparams.precision / NBBY *
+			     sc->sc_rparams.channels *
+			     sc->sc_rparams.sample_rate)) * 10;
+		DPRINTF(("audio: record blktime = %lu for %d\n",
+			 sc->sc_rblktime, sc->sc_rr.blksize));
+	}
 #undef double
 #endif
 
@@ -1346,18 +1370,24 @@
 {
 
 	/* set high at 100% */
-	sc->sc_pr.usedhigh = sc->sc_pustream->end - sc->sc_pustream->start;
-	/* set low at 75% of usedhigh */
-	sc->sc_pr.usedlow = sc->sc_pr.usedhigh * 3 / 4;
-	if (sc->sc_pr.usedlow == sc->sc_pr.usedhigh)
-		sc->sc_pr.usedlow -= sc->sc_pr.blksize;
-
-	sc->sc_rr.usedhigh = sc->sc_rustream->end - sc->sc_rustream->start
-		- sc->sc_rr.blksize;
-	sc->sc_rr.usedlow = 0;
-	DPRINTF(("%s: plow=%d phigh=%d rlow=%d rhigh=%d\n", __func__,
-		 sc->sc_pr.usedlow, sc->sc_pr.usedhigh,
-		 sc->sc_rr.usedlow, sc->sc_rr.usedhigh));
+	if (audio_can_playback(sc)) {
+		sc->sc_pr.usedhigh =
+		    sc->sc_pustream->end - sc->sc_pustream->start;
+		/* set low at 75% of usedhigh */
+		sc->sc_pr.usedlow = sc->sc_pr.usedhigh * 3 / 4;
+		if (sc->sc_pr.usedlow == sc->sc_pr.usedhigh)
+			sc->sc_pr.usedlow -= sc->sc_pr.blksize;
+	}
+
+	if (audio_can_capture(sc)) {
+		sc->sc_rr.usedhigh =
+		    sc->sc_rustream->end - sc->sc_rustream->start -
+		    sc->sc_rr.blksize;
+		sc->sc_rr.usedlow = 0;
+		DPRINTF(("%s: plow=%d phigh=%d rlow=%d rhigh=%d\n", __func__,
+			 sc->sc_pr.usedlow, sc->sc_pr.usedhigh,
+			 sc->sc_rr.usedlow, sc->sc_rr.usedhigh));
+	}
 }
 
 static inline int
@@ -1435,7 +1465,7 @@
 
 	sc->sc_full_duplex = 
 		(flags & (FWRITE|FREAD)) == (FWRITE|FREAD) &&
-		(hw->get_props(sc->hw_hdl) & AUDIO_PROP_FULLDUPLEX);
+		(audio_get_props(sc) & AUDIO_PROP_FULLDUPLEX);
 
 	mode = 0;
 	if (flags & FREAD) {
@@ -2250,7 +2280,7 @@
 	case AUDIO_SETFD:
 		DPRINTF(("AUDIO_SETFD\n"));
 		fd = *(int *)addr;
-		if (hw->get_props(sc->hw_hdl) & AUDIO_PROP_FULLDUPLEX) {
+		if (audio_get_props(sc) & AUDIO_PROP_FULLDUPLEX) {
 			if (hw->setfd)
 				error = hw->setfd(sc->hw_hdl, fd);
 			else
@@ -2267,7 +2297,7 @@
 
 	case AUDIO_GETPROPS:
 		DPRINTF(("AUDIO_GETPROPS\n"));
-		*(int *)addr = hw->get_props(sc->hw_hdl);
+		*(int *)addr = audio_get_props(sc);
 		break;
 
 	default:
@@ -2438,7 +2468,7 @@
 
 	DPRINTF(("audio_mmap: off=%lld, prot=%d\n", (long long)off, prot));
 	hw = sc->hw_if;
-	if (!(hw->get_props(sc->hw_hdl) & AUDIO_PROP_MMAP) || !hw->mappage)
+	if (!(audio_get_props(sc) & AUDIO_PROP_MMAP) || !hw->mappage)
 		return -1;
 #if 0
 /* XXX
@@ -2497,6 +2527,9 @@
 		 sc->sc_rr.s.start, audio_stream_get_used(&sc->sc_rr.s),
 		 sc->sc_rr.usedhigh, sc->sc_rr.mmapped));
 
+	if (!audio_can_capture(sc))
+		return EINVAL;
+
 	if (sc->hw_if->trigger_input)
 		error = sc->hw_if->trigger_input(sc->hw_hdl, sc->sc_rr.s.start,
 		    sc->sc_rr.s.end, sc->sc_rr.blksize,
@@ -2523,6 +2556,9 @@
 		 sc->sc_pr.s.start, used, sc->sc_pr.usedhigh,
 		 sc->sc_pr.blksize, sc->sc_pr.mmapped));
 
+	if (!audio_can_playback(sc))
+		return EINVAL;
+
 	if (!sc->sc_pr.mmapped && used < sc->sc_pr.blksize) {
 		wakeup(&sc->sc_wchan);
 		DPRINTF(("%s: wakeup and return\n", __func__));
@@ -3330,6 +3366,12 @@
 		rp.channels = r->channels;
 		nr++;
 	}
+
+	if (!audio_can_capture(sc))
+		nr = 0;
+	if (!audio_can_playback(sc))
+		np = 0;
+
 #ifdef AUDIO_DEBUG
 	if (audiodebug && nr > 0)
 	    audio_print_params("audiosetinfo() Setting record params:", &rp);
@@ -3381,7 +3423,7 @@
 	if (modechange) {
 		int indep;
 
-		indep = hw->get_props(sc->hw_hdl) & AUDIO_PROP_INDEPENDENT;
+		indep = audio_get_props(sc) & AUDIO_PROP_INDEPENDENT;
 		if (!indep) {
 			if (setmode == AUMODE_RECORD)
 				pp = rp;
@@ -3715,12 +3757,15 @@
 	p->active = sc->sc_pbus;
 	r->active = sc->sc_rbus;
 
-	p->buffer_size = sc->sc_pustream->bufsize;
-	r->buffer_size = sc->sc_rustream->bufsize;
+	p->buffer_size = sc->sc_pustream ? sc->sc_pustream->bufsize : 0;
+	r->buffer_size = sc->sc_rustream ? sc->sc_rustream->bufsize : 0;
 
 	ai->blocksize = sc->sc_pr.blksize;
-	ai->hiwat = sc->sc_pr.usedhigh / sc->sc_pr.blksize;
-	ai->lowat = sc->sc_pr.usedlow / sc->sc_pr.blksize;
+	if (sc->sc_pr.blksize > 0) {
+		ai->hiwat = sc->sc_pr.usedhigh / sc->sc_pr.blksize;
+		ai->lowat = sc->sc_pr.usedlow / sc->sc_pr.blksize;
+	} else
+		ai->hiwat = ai->lowat = 0;
 	ai->mode = sc->sc_mode;
 
 	return 0;
@@ -4136,4 +4181,35 @@
 	splx(s);
 }
 
+static int
+audio_get_props(struct audio_softc *sc)
+{
+	const struct audio_hw_if *hw;
+	int props;
+
+	hw = sc->hw_if;
+	props = hw->get_props(sc->hw_hdl);
+
+	/*
+	 * if neither playback nor capture properties are reported,
+	 * assume both are supported by the device driver
+	 */
+	if ((props & (AUDIO_PROP_PLAYBACK|AUDIO_PROP_CAPTURE)) == 0)
+		props |= (AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE);
+
+	return props;
+}
+
+static bool
+audio_can_playback(struct audio_softc *sc)
+{
+	return audio_get_props(sc) & AUDIO_PROP_PLAYBACK ? true : false;
+}
+
+static bool
+audio_can_capture(struct audio_softc *sc)
+{
+	return audio_get_props(sc) & AUDIO_PROP_CAPTURE ? true : false;
+}
+
 #endif /* NAUDIO > 0 */

Index: src/sys/dev/audio_if.h
diff -u src/sys/dev/audio_if.h:1.65 src/sys/dev/audio_if.h:1.65.14.1
--- src/sys/dev/audio_if.h:1.65	Tue Mar  4 18:23:44 2008
+++ src/sys/dev/audio_if.h	Fri Oct 16 05:43:38 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: audio_if.h,v 1.65 2008/03/04 18:23:44 cube Exp $	*/
+/*	$NetBSD: audio_if.h,v 1.65.14.1 2009/10/16 05:43:38 snj Exp $	*/
 
 /*
  * Copyright (c) 1994 Havard Eidnes.
@@ -86,13 +86,15 @@
 static __inline int
 audio_stream_get_space(const audio_stream_t *s)
 {
-	return (s->end - s->start) - s->used;
+	if (s)
+		return (s->end - s->start) - s->used;
+	return 0;
 }
 
 static __inline int
 audio_stream_get_used(const audio_stream_t *s)
 {
-	return s->used;
+	return s ? s->used : 0;
 }
 
 static __inline uint8_t *

Index: src/sys/dev/pci/hdaudio/hdaudio_afg.c
diff -u src/sys/dev/pci/hdaudio/hdaudio_afg.c:1.14.2.3 src/sys/dev/pci/hdaudio/hdaudio_afg.c:1.14.2.4
--- src/sys/dev/pci/hdaudio/hdaudio_afg.c:1.14.2.3	Mon Sep 28 00:40:21 2009
+++ src/sys/dev/pci/hdaudio/hdaudio_afg.c	Fri Oct 16 05:43:38 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: hdaudio_afg.c,v 1.14.2.3 2009/09/28 00:40:21 snj Exp $ */
+/* $NetBSD: hdaudio_afg.c,v 1.14.2.4 2009/10/16 05:43:38 snj Exp $ */
 
 /*
  * Copyright (c) 2009 Precedence Technologies Ltd <supp...@precedence.co.uk>
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hdaudio_afg.c,v 1.14.2.3 2009/09/28 00:40:21 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hdaudio_afg.c,v 1.14.2.4 2009/10/16 05:43:38 snj Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -3323,13 +3323,11 @@
 	int bufsize;
 
 	st = (mode == AUMODE_PLAY) ? ad->ad_playback : ad->ad_capture;
-#ifdef DIAGNOSTIC
 	if (st == NULL) {
-		hda_error(ad->ad_sc,
+		hda_trace(ad->ad_sc,
 		    "round_blocksize called for invalid stream\n");
-		return 256;
+		return 128;
 	}
-#endif
 
 	/* Multiple of 128 */
 	blksize &= ~128;
@@ -3583,8 +3581,21 @@
 static int
 hdaudio_afg_get_props(void *opaque)
 {
+	struct hdaudio_audiodev *ad = opaque;
+	int props = 0;
+
+	if (ad->ad_playback)
+		props |= AUDIO_PROP_PLAYBACK;
+	if (ad->ad_capture)
+		props |= AUDIO_PROP_CAPTURE;
+	if (ad->ad_playback && ad->ad_capture) {
+		props |= AUDIO_PROP_FULLDUPLEX;
+		props |= AUDIO_PROP_INDEPENDENT;
+	}
+
 	/* TODO: AUDIO_PROP_MMAP */
-	return AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
+
+	return props;
 }
 
 static int

Index: src/sys/sys/audioio.h
diff -u src/sys/sys/audioio.h:1.32 src/sys/sys/audioio.h:1.32.44.1
--- src/sys/sys/audioio.h:1.32	Mon Jun 11 13:05:47 2007
+++ src/sys/sys/audioio.h	Fri Oct 16 05:43:38 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: audioio.h,v 1.32 2007/06/11 13:05:47 joerg Exp $	*/
+/*	$NetBSD: audioio.h,v 1.32.44.1 2009/10/16 05:43:38 snj Exp $	*/
 
 /*
  * Copyright (c) 1991-1993 Regents of the University of California.
@@ -185,6 +185,8 @@
 #define  AUDIO_PROP_FULLDUPLEX	0x01
 #define  AUDIO_PROP_MMAP	0x02
 #define  AUDIO_PROP_INDEPENDENT	0x04
+#define  AUDIO_PROP_PLAYBACK	0x10
+#define  AUDIO_PROP_CAPTURE	0x20
 #define AUDIO_GETBUFINFO	_IOR('A', 35, struct audio_info)
 
 /*

Reply via email to