Module Name: src
Committed By: nat
Date: Wed Dec 28 02:44:59 UTC 2016
Modified Files:
src/sys/dev: audio.c audiovar.h
Log Message:
Audio device won't fail if one cannot set the common/hw format.
Audio won't be able to be opened though unless a common format is
configured properly.
This would alow the user to change the common format via sysctls
until hardware is configured.
Simplification of several functions.
To generate a diff of this commit:
cvs rdiff -u -r1.287 -r1.288 src/sys/dev/audio.c
cvs rdiff -u -r1.47 -r1.48 src/sys/dev/audiovar.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/dev/audio.c
diff -u src/sys/dev/audio.c:1.287 src/sys/dev/audio.c:1.288
--- src/sys/dev/audio.c:1.287 Sun Dec 25 22:44:24 2016
+++ src/sys/dev/audio.c Wed Dec 28 02:44:59 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: audio.c,v 1.287 2016/12/25 22:44:24 nat Exp $ */
+/* $NetBSD: audio.c,v 1.288 2016/12/28 02:44:59 nat Exp $ */
/*-
* Copyright (c) 2016 Nathanial Sloss <[email protected]>
@@ -148,7 +148,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.287 2016/12/25 22:44:24 nat Exp $");
+__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.288 2016/12/28 02:44:59 nat Exp $");
#include "audio.h"
#if NAUDIO > 0
@@ -196,18 +196,6 @@ int audiodebug = AUDIO_DEBUG;
#define SPECIFIED(x) (x != ~0)
#define SPECIFIED_CH(x) (x != (u_char)~0)
-#define VAUDIO_NFORMATS 1
-static const struct audio_format vaudio_formats[VAUDIO_NFORMATS] = {
- { NULL, AUMODE_PLAY | AUMODE_RECORD,
-#if BYTE_ORDER == LITTLE_ENDIAN
- AUDIO_ENCODING_SLINEAR_LE,
-#else
- AUDIO_ENCODING_SLINEAR_BE,
-#endif
- 16, 16, 2, AUFMT_STEREO, 1, { 44100 }
- }
-};
-
/* #define AUDIO_PM_IDLE */
#ifdef AUDIO_PM_IDLE
int audio_idle_timeout = 30;
@@ -415,19 +403,6 @@ const struct cdevsw audio_cdevsw = {
.d_flag = D_MCLOSE | D_MPSAFE
};
-/* The default vchan mode: 44.1 kHz stereo signed linear */
-struct audio_params vchan_default = {
- .sample_rate = 44100,
-#if BYTE_ORDER == LITTLE_ENDIAN
- .encoding = AUDIO_ENCODING_SLINEAR_LE,
-#else
- .encoding = AUDIO_ENCODING_SLINEAR_BE,
-#endif
- .precision = 16,
- .validbits = 16,
- .channels = 2,
-};
-
/* The default audio mode: 8 kHz mono mu-law */
const struct audio_params audio_default = {
.sample_rate = 8000,
@@ -477,6 +452,31 @@ audioattach(device_t parent, device_t se
sc->sc_opens = 0;
sc->sc_recopens = 0;
sc->sc_aivalid = false;
+ sc->sc_ready = true;
+
+ sc->sc_format[0].mode = AUMODE_PLAY | AUMODE_RECORD;
+ sc->sc_format[0].encoding =
+#if BYTE_ORDER == LITTLE_ENDIAN
+ AUDIO_ENCODING_SLINEAR_LE;
+#else
+ AUDIO_ENCODING_SLINEAR_BE;
+#endif
+ sc->sc_format[0].precision = 16;
+ sc->sc_format[0].validbits = 16;
+ sc->sc_format[0].channels = 2;
+ sc->sc_format[0].channel_mask = AUFMT_STEREO;
+ sc->sc_format[0].frequency_type = 1;
+ sc->sc_format[0].frequency[0] = 44100;
+
+ sc->sc_vchan_params.sample_rate = 44100;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ sc->sc_vchan_params.encoding = AUDIO_ENCODING_SLINEAR_LE;
+#else
+ sc->sc_vchan_params.encoding = AUDIO_ENCODING_SLINEAR_BE;
+#endif
+ sc->sc_vchan_params.precision = 16;
+ sc->sc_vchan_params.validbits = 16;
+ sc->sc_vchan_params.channels = 2;
sc->sc_trigger_started = false;
sc->sc_rec_started = false;
@@ -497,7 +497,7 @@ audioattach(device_t parent, device_t se
sc->sc_precision = 16;
sc->sc_channels = 2;
- if (auconv_create_encodings(vaudio_formats, VAUDIO_NFORMATS,
+ if (auconv_create_encodings(sc->sc_format, VAUDIO_NFORMATS,
&sc->sc_encodings) != 0) {
aprint_error_dev(self, "couldn't create encodings\n");
return;
@@ -608,13 +608,11 @@ bad_rec:
sc->sc_saturate = true;
error = audio_set_vchan_defaults(sc, AUMODE_PLAY | AUMODE_PLAY_ALL |
- AUMODE_RECORD, &vaudio_formats[0], 0);
+ AUMODE_RECORD, &sc->sc_format[0], 0);
mutex_exit(sc->sc_lock);
if (error != 0) {
aprint_error_dev(sc->sc_dev, "%s: audio_set_vchan_defaults() "
"failed\n", __func__);
- sc->hw_if = NULL;
- return;
}
sc->sc_pr.blksize = sc->sc_vchan[0]->sc_mpr.blksize;
@@ -1872,7 +1870,7 @@ audio_open(dev_t dev, struct audio_softc
KASSERT(mutex_owned(sc->sc_lock));
- if (sc->sc_opens >= VAUDIOCHANS)
+ if (sc->sc_ready == false || sc->sc_opens >= VAUDIOCHANS)
return ENXIO;
for (n = 1; n < VAUDIOCHANS; n++) {
@@ -3810,15 +3808,23 @@ audio_set_vchan_defaults(struct audio_so
{
struct virtual_channel *vc = sc->sc_vchan[n];
struct audio_info ai;
- bool reset;
- int i, error;
+ int error;
KASSERT(mutex_owned(sc->sc_lock));
- reset = false;
+ sc->sc_vchan_params.sample_rate = sc->sc_iffreq;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ sc->sc_vchan_params.encoding = AUDIO_ENCODING_SLINEAR_LE;
+#else
+ sc->sc_vchan_params.encoding = AUDIO_ENCODING_SLINEAR_BE;
+#endif
+ sc->sc_vchan_params.precision = sc->sc_precision;
+ sc->sc_vchan_params.validbits = sc->sc_precision;
+ sc->sc_vchan_params.channels = sc->sc_channels;
+
/* default parameters */
- vc->sc_rparams = vchan_default;
- vc->sc_pparams = vchan_default;
+ vc->sc_rparams = sc->sc_vchan_params;
+ vc->sc_pparams = sc->sc_vchan_params;
vc->sc_blkset = false;
AUDIO_INITINFO(&ai);
@@ -3834,62 +3840,21 @@ audio_set_vchan_defaults(struct audio_so
ai.play.pause = false;
ai.mode = mode;
- for (i = 0; i < vc->sc_npfilters; i++) {
- vc->sc_pfilters[i]->dtor(vc->sc_pfilters[i]);
- vc->sc_pfilters[i] = NULL;
- audio_stream_dtor(&vc->sc_pstreams[i]);
- }
- vc->sc_npfilters = 0;
+ sc->sc_format->channels = sc->sc_channels;
+ sc->sc_format->precision = sc->sc_precision;
+ sc->sc_format->validbits = sc->sc_precision;
+ sc->sc_format->frequency[0] = sc->sc_iffreq;
- for (i = 0; i < vc->sc_nrfilters; i++) {
- vc->sc_rfilters[i]->dtor(vc->sc_rfilters[i]);
- vc->sc_rfilters[i] = NULL;
- audio_stream_dtor(&vc->sc_rstreams[i]);
- }
- vc->sc_nrfilters = 0;
-
- error = audiosetinfo(sc, &ai, true, n);
- if (vc->sc_npfilters > 0) {
- ai.play.sample_rate = vc->sc_pstreams[vc->sc_npfilters - 1].
- param.sample_rate;
- vc->sc_pparams.sample_rate = ai.play.sample_rate;
- ai.play.precision = vc->sc_pstreams[vc->sc_npfilters - 1].
- param.precision;
- vc->sc_pparams.precision = ai.play.precision;
- ai.play.channels = vc->sc_pstreams[vc->sc_npfilters - 1].
- param.channels;
- vc->sc_pparams.channels = ai.play.channels;
-
- for (i = 0; i < vc->sc_npfilters; i++) {
- vc->sc_pfilters[i]->dtor(vc->sc_pfilters[i]);
- vc->sc_pfilters[i] = NULL;
- audio_stream_dtor(&vc->sc_pstreams[i]);
- }
- vc->sc_npfilters = 0;
- reset = true;
+ auconv_delete_encodings(sc->sc_encodings);
+ error = auconv_create_encodings(sc->sc_format, VAUDIO_NFORMATS,
+ &sc->sc_encodings);
- }
- if (vc->sc_nrfilters > 0) {
- ai.record.sample_rate = vc->sc_rstreams[0].
- param.sample_rate;
- vc->sc_rparams.sample_rate = ai.record.sample_rate;
- ai.record.precision = vc->sc_rstreams[0].
- param.precision;
- vc->sc_rparams.precision = ai.record.precision;
- ai.record.channels = vc->sc_rstreams[0].
- param.channels;
- vc->sc_rparams.channels = ai.record.channels;
- for (i = 0; i < vc->sc_nrfilters; i++) {
- vc->sc_rfilters[i]->dtor(vc->sc_rfilters[i]);
- vc->sc_rfilters[i] = NULL;
- audio_stream_dtor(&vc->sc_rstreams[i]);
- }
- vc->sc_nrfilters = 0;
- reset = true;
- }
- if (reset)
+ if (error == 0)
error = audiosetinfo(sc, &ai, true, n);
+ if (error)
+ aprint_error("Invalid channel format, please check hardware "
+ "capabilities\n");
return error;
}
@@ -5063,7 +5028,7 @@ audio_resume(device_t dv, const pmf_qual
sc->sc_rec_started = false;
audio_set_vchan_defaults(sc, AUMODE_PLAY | AUMODE_PLAY_ALL |
- AUMODE_RECORD, &vaudio_formats[0], 0);
+ AUMODE_RECORD, &sc->sc_format[0], 0);
audio_mixer_restore(sc);
for (n = 1; n < VAUDIOCHANS; n++) {
@@ -5716,50 +5681,29 @@ audio_set_params(struct audio_softc *sc,
audio_params_t *play, audio_params_t *rec,
stream_filter_list_t *pfil, stream_filter_list_t *rfil, int n)
{
- struct virtual_channel *vc = sc->sc_vchan[0];
- struct audio_format norm_format[VAUDIO_NFORMATS] = {
- { NULL, AUMODE_PLAY | AUMODE_RECORD,
-#if BYTE_ORDER == LITTLE_ENDIAN
- AUDIO_ENCODING_SLINEAR_LE,
-#else
- AUDIO_ENCODING_SLINEAR_BE,
-#endif
- 16, 16, 2, AUFMT_STEREO, 1, { 44100 }
- }
- };
+ int error = 0;
KASSERT(mutex_owned(sc->sc_lock));
if (n == 0 && sc->hw_if->set_params != NULL) {
- return sc->hw_if->set_params(sc->hw_hdl, setmode, usemode,
- play, rec, pfil, rfil);
+ sc->sc_ready = true;
+ if (sc->sc_precision == 8)
+ play->encoding = rec->encoding = AUDIO_ENCODING_SLINEAR;
+ error = sc->hw_if->set_params(sc->hw_hdl, setmode, usemode,
+ play, rec, pfil, rfil);
+ if (error != 0)
+ sc->sc_ready = false;
+
+ return error;
}
- norm_format[0].frequency[0] = vc->sc_pparams.sample_rate;
- norm_format[0].channels = vc->sc_pparams.channels;
- norm_format[0].precision = vc->sc_pparams.precision;
- norm_format[0].validbits = vc->sc_pparams.validbits;
- if (setmode & AUMODE_PLAY && auconv_set_converter(norm_format,
+ if (setmode & AUMODE_PLAY && auconv_set_converter(sc->sc_format,
VAUDIO_NFORMATS, AUMODE_PLAY, play, true, pfil) < 0)
return EINVAL;
if (pfil->req_size > 0)
play = &pfil->filters[0].param;
-#if 0
- norm_format[0].frequency[0] = sc->sc_vchan[0]->sc_rparams.sample_rate;
- if (sc->sc_recopens == 1 && setmode & AUMODE_RECORD &&
- sc->hw_if->set_params != NULL && audio_get_props(sc) &
- AUDIO_PROP_INDEPENDENT) {
- (void)sc->hw_if->set_params(sc->hw_hdl, setmode, usemode,
- &vc->sc_pparams, rec, pfil, rfil);
- }
-#endif
-
- norm_format[0].frequency[0] = vc->sc_rparams.sample_rate;
- norm_format[0].channels = vc->sc_rparams.channels;
- norm_format[0].precision = vc->sc_rparams.precision;
- norm_format[0].validbits = vc->sc_rparams.validbits;
- if (setmode & AUMODE_RECORD && auconv_set_converter(norm_format,
+ if (setmode & AUMODE_RECORD && auconv_set_converter(sc->sc_format,
VAUDIO_NFORMATS, AUMODE_RECORD, rec, true, rfil) < 0)
return EINVAL;
@@ -5823,7 +5767,7 @@ audio_sysctl_frequency(SYSCTLFN_ARGS)
{
struct sysctlnode node;
struct audio_softc *sc;
- int t, oldfreq, error;
+ int t, error;
node = *rnode;
sc = node.sysctl_data;
@@ -5847,15 +5791,9 @@ audio_sysctl_frequency(SYSCTLFN_ARGS)
return EINVAL;
}
- oldfreq = sc->sc_iffreq;
sc->sc_iffreq = t;
error = audio_set_vchan_defaults(sc, AUMODE_PLAY | AUMODE_PLAY_ALL
- | AUMODE_RECORD, &vaudio_formats[0], 0);
- if (error) {
- sc->sc_iffreq = oldfreq;
- error = audio_set_vchan_defaults(sc, AUMODE_PLAY |
- AUMODE_PLAY_ALL | AUMODE_RECORD, &vaudio_formats[0], 0);
- }
+ | AUMODE_RECORD, &sc->sc_format[0], 0);
mutex_exit(sc->sc_lock);
return error;
@@ -5867,7 +5805,7 @@ audio_sysctl_precision(SYSCTLFN_ARGS)
{
struct sysctlnode node;
struct audio_softc *sc;
- int t, oldprecision, error;
+ int t, error;
node = *rnode;
sc = node.sysctl_data;
@@ -5891,15 +5829,20 @@ audio_sysctl_precision(SYSCTLFN_ARGS)
return EINVAL;
}
- oldprecision = sc->sc_precision;
sc->sc_precision = t;
+
+ if (sc->sc_precision != 8) {
+ sc->sc_format[0].encoding =
+#if BYTE_ORDER == LITTLE_ENDIAN
+ AUDIO_ENCODING_SLINEAR_LE;
+#else
+ AUDIO_ENCODING_SLINEAR_BE;
+#endif
+ } else
+ sc->sc_format[0].encoding = AUDIO_ENCODING_SLINEAR_LE;
+
error = audio_set_vchan_defaults(sc, AUMODE_PLAY | AUMODE_PLAY_ALL
- | AUMODE_RECORD, &vaudio_formats[0], 0);
- if (error) {
- sc->sc_precision = oldprecision;
- error = audio_set_vchan_defaults(sc, AUMODE_PLAY |
- AUMODE_PLAY_ALL | AUMODE_RECORD, &vaudio_formats[0], 0);
- }
+ | AUMODE_RECORD, &sc->sc_format[0], 0);
mutex_exit(sc->sc_lock);
return error;
@@ -5911,7 +5854,7 @@ audio_sysctl_channels(SYSCTLFN_ARGS)
{
struct sysctlnode node;
struct audio_softc *sc;
- int t, oldchan, error;
+ int t, error;
node = *rnode;
sc = node.sysctl_data;
@@ -5935,15 +5878,10 @@ audio_sysctl_channels(SYSCTLFN_ARGS)
return EINVAL;
}
- oldchan = sc->sc_channels;
sc->sc_channels = t;
error = audio_set_vchan_defaults(sc, AUMODE_PLAY | AUMODE_PLAY_ALL
- | AUMODE_RECORD, &vaudio_formats[0], 0);
- if (error) {
- sc->sc_channels = oldchan;
- error = audio_set_vchan_defaults(sc, AUMODE_PLAY |
- AUMODE_PLAY_ALL | AUMODE_RECORD, &vaudio_formats[0], 0);
- }
+ | AUMODE_RECORD, &sc->sc_format[0], 0);
+
mutex_exit(sc->sc_lock);
return error;
Index: src/sys/dev/audiovar.h
diff -u src/sys/dev/audiovar.h:1.47 src/sys/dev/audiovar.h:1.48
--- src/sys/dev/audiovar.h:1.47 Thu Dec 8 10:28:44 2016
+++ src/sys/dev/audiovar.h Wed Dec 28 02:44:59 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: audiovar.h,v 1.47 2016/12/08 10:28:44 nat Exp $ */
+/* $NetBSD: audiovar.h,v 1.48 2016/12/28 02:44:59 nat Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -70,6 +70,7 @@
#include <sys/proc.h>
#include <dev/audio_if.h>
+#include <dev/auconv.h>
/*
* Initial/default block duration is both configurable and patchable.
@@ -194,6 +195,7 @@ struct audio_softc {
bool sc_trigger_started;
bool sc_rec_started;
bool sc_writeme;
+ bool sc_ready; /* audio hw configured properly */
int sc_opens;
int sc_recopens;
bool sc_dying;
@@ -281,6 +283,9 @@ struct audio_softc {
bool sc_saturate;
struct audio_info sc_ai; /* Recent info for dev sound */
bool sc_aivalid;
+#define VAUDIO_NFORMATS 1
+ struct audio_format sc_format[VAUDIO_NFORMATS];
+ struct audio_params sc_vchan_params;
};
#endif /* _SYS_DEV_AUDIOVAR_H_ */