Add auto config for channel/hw format.

Addresses PR kern/51703.
Addresses PR kern/51760.
Addresses PR kern/51879.
This commit is contained in:
nat 2017-01-21 22:22:41 +00:00
parent b1d8d816a1
commit d78960acf3
1 changed files with 70 additions and 9 deletions

View File

@ -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 <nathanialsloss@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_softc *sc, u_int mode,
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 */