Module Name:    src
Committed By:   nat
Date:           Sat Jan 21 22:22:41 UTC 2017

Modified Files:
        src/sys/dev: audio.c

Log Message:
Add auto config for channel/hw format.

Addresses PR kern/51703.
Addresses PR kern/51760.
Addresses PR kern/51879.


To generate a diff of this commit:
cvs rdiff -u -r1.291 -r1.292 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.291 src/sys/dev/audio.c:1.292
--- src/sys/dev/audio.c:1.291	Sun Jan 15 00:04:01 2017
+++ src/sys/dev/audio.c	Sat Jan 21 22:22:41 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: audio.c,v 1.291 2017/01/15 00:04:01 nat Exp $	*/
+/*	$NetBSD: audio.c,v 1.292 2017/01/21 22:22:41 nat Exp $	*/
 
 /*-
  * Copyright (c) 2016 Nathanial Sloss <nathanialsl...@yahoo.com.au>
@@ -148,7 +148,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.291 2017/01/15 00:04:01 nat Exp $");
+__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.292 2017/01/21 22:22:41 nat Exp $");
 
 #include "audio.h"
 #if NAUDIO > 0
@@ -362,6 +362,7 @@ static int
 audio_query_encoding(struct audio_softc *, struct audio_encoding *);
 static int audio_set_vchan_defaults
 	(struct audio_softc *, u_int, const struct audio_format *, int);
+static int vchan_autoconfig(struct audio_softc *);
 int	au_get_lr_value(struct audio_softc *, mixer_ctrl_t *, int *, int *);
 int	au_set_lr_value(struct audio_softc *, mixer_ctrl_t *, int, int);
 int	au_portof(struct audio_softc *, char *, int);
@@ -412,6 +413,11 @@ const struct audio_params audio_default 
 	.channels = 1,
 };
 
+int auto_config_precision[] = { 32, 24, 16, 8 };
+int auto_config_channels[] = { 32, 24, 16, 8, 6, 4, 2, 1};
+int auto_config_freq[] = { 48000, 44100, 96000, 192000, 32000,
+			   22050, 16000, 11025, 8000, 4000 };
+
 CFATTACH_DECL3_NEW(audio, sizeof(struct audio_softc),
     audioprobe, audioattach, audiodetach, audioactivate, audiorescan,
     audiochilddet, DVF_DETACH_SHUTDOWN);
@@ -606,10 +612,9 @@ bad_rec:
 
 	sc->sc_lastgain = 128;
 	sc->sc_saturate = true;
-
-	error = audio_set_vchan_defaults(sc, AUMODE_PLAY | AUMODE_PLAY_ALL |
-	    AUMODE_RECORD, &sc->sc_format[0], 0);
 	mutex_exit(sc->sc_lock);
+
+	error = vchan_autoconfig(sc);
 	if (error != 0) {
 		aprint_error_dev(sc->sc_dev, "%s: audio_set_vchan_defaults() "
 		    "failed\n", __func__);
@@ -3846,9 +3851,6 @@ audio_set_vchan_defaults(struct audio_so
 	if (error == 0)
 		error = audiosetinfo(sc, &ai, true, n);
 
-	if (error)
-		aprint_error("Invalid channel format, please check hardware "
-			     "capabilities\n");
 	return error;
 }
 
@@ -5788,6 +5790,9 @@ audio_sysctl_frequency(SYSCTLFN_ARGS)
 	sc->sc_iffreq = t;
 	error = audio_set_vchan_defaults(sc, AUMODE_PLAY | AUMODE_PLAY_ALL
 	    | AUMODE_RECORD, &sc->sc_format[0], 0);
+	if (error)
+		aprint_error("Invalid channel format, please check hardware "
+			     "capabilities\n");
 	mutex_exit(sc->sc_lock);
 
 	return error;
@@ -5837,6 +5842,9 @@ audio_sysctl_precision(SYSCTLFN_ARGS)
 
 	error = audio_set_vchan_defaults(sc, AUMODE_PLAY | AUMODE_PLAY_ALL
 	    | AUMODE_RECORD, &sc->sc_format[0], 0);
+	if (error)
+		aprint_error("Invalid channel format, please check hardware "
+			     "capabilities\n");
 	mutex_exit(sc->sc_lock);
 
 	return error;
@@ -5875,10 +5883,63 @@ audio_sysctl_channels(SYSCTLFN_ARGS)
 	sc->sc_channels = t;
 	error = audio_set_vchan_defaults(sc, AUMODE_PLAY | AUMODE_PLAY_ALL
 	    | AUMODE_RECORD, &sc->sc_format[0], 0);
-
+	if (error)
+		aprint_error("Invalid channel format, please check hardware "
+			     "capabilities\n");
 	mutex_exit(sc->sc_lock);
 
 	return error;
 }
 
+static int
+vchan_autoconfig(struct audio_softc *sc)
+{
+	struct virtual_channel *vc;
+	int error, i, j, k;
+
+	vc = sc->sc_vchan[0];
+	error = 0;
+
+	mutex_enter(sc->sc_lock);
+
+	for (i = 0; i < __arraycount(auto_config_precision); i++) {
+		sc->sc_precision = auto_config_precision[i];
+		for (j = 0; j < __arraycount(auto_config_channels); j++) {
+			sc->sc_channels = auto_config_channels[j];
+			for (k = 0; k < __arraycount(auto_config_freq); k++) {
+				sc->sc_iffreq = auto_config_freq[k];
+				error = audio_set_vchan_defaults(sc,
+				    AUMODE_PLAY | AUMODE_PLAY_ALL |
+				    AUMODE_RECORD, &sc->sc_format[0], 0);
+				if (vc->sc_npfilters > 0 &&
+				    (vc->sc_mpr.s.param.
+					sample_rate != sc->sc_iffreq ||
+				    vc->sc_mpr.s.param.
+				       precision != sc->sc_precision ||
+				    vc->sc_mpr.s.param.
+					 channels != sc->sc_channels))
+					error = EINVAL;
+
+				if (error == 0) {
+					aprint_normal("Virtual format "
+					    		      "configured - "
+					    "Format SLINEAR, precision %d, "
+					    "channels %d, frequency %d\n",
+					    sc->sc_precision, sc->sc_channels,
+					    sc->sc_iffreq);
+					mutex_exit(sc->sc_lock);
+
+					return 0;
+				}
+			}
+		}
+	}
+
+	aprint_error("Virtual format auto config failed!\n"
+		     "Please check hardware capabilities\n");
+	mutex_exit(sc->sc_lock);
+
+	return EINVAL;
+}
+
 #endif /* NAUDIO > 0 */

Reply via email to