Catch up vs_set_params() to recent MI audio (after in-kernel mixer).

Before that, MD part had to support all encodings I'd like to support,
but currently it's no longer necessary.  The hardware is
4bit/1ch/15.6kHz ADPCM but it behaves as 16bit/1ch/16.0kHz PCM.

For audio.c < 1.362, the device attach succeeded and playback is
still working.
For audio.c >= 1.363, the device attach fails again.
It does not work yet but I commit it for milestone.
This commit is contained in:
isaki 2017-07-09 12:49:26 +00:00
parent 53779488e1
commit 5c899c2dfd

View File

@ -1,4 +1,4 @@
/* $NetBSD: vs.c,v 1.38 2017/06/25 06:26:40 isaki Exp $ */ /* $NetBSD: vs.c,v 1.39 2017/07/09 12:49:26 isaki Exp $ */
/* /*
* Copyright (c) 2001 Tetsuya Isaki. All rights reserved. * Copyright (c) 2001 Tetsuya Isaki. All rights reserved.
@ -30,7 +30,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: vs.c,v 1.38 2017/06/25 06:26:40 isaki Exp $"); __KERNEL_RCSID(0, "$NetBSD: vs.c,v 1.39 2017/07/09 12:49:26 isaki Exp $");
#include "audio.h" #include "audio.h"
#include "vs.h" #include "vs.h"
@ -160,19 +160,6 @@ struct {
#define NUM_RATE (sizeof(vs_l2r)/sizeof(vs_l2r[0])) #define NUM_RATE (sizeof(vs_l2r)/sizeof(vs_l2r[0]))
struct {
const char *name;
int encoding;
int precision;
} vs_encodings[] = {
{AudioEadpcm, AUDIO_ENCODING_ADPCM, 4},
{AudioEslinear, AUDIO_ENCODING_SLINEAR, 8},
{AudioEulinear, AUDIO_ENCODING_ULINEAR, 8},
{AudioEmulaw, AUDIO_ENCODING_ULAW, 8},
{AudioEslinear_be, AUDIO_ENCODING_SLINEAR_BE, 16},
{AudioEslinear_le, AUDIO_ENCODING_SLINEAR_LE, 16},
};
static int static int
vs_match(device_t parent, cfdata_t cf, void *aux) vs_match(device_t parent, cfdata_t cf, void *aux)
{ {
@ -338,17 +325,15 @@ vs_query_encoding(void *hdl, struct audio_encoding *fp)
{ {
DPRINTF(1, ("vs_query_encoding\n")); DPRINTF(1, ("vs_query_encoding\n"));
if (fp->index >= sizeof(vs_encodings) / sizeof(vs_encodings[0]))
return EINVAL;
strcpy(fp->name, vs_encodings[fp->index].name); if (fp->index == 0) {
fp->encoding = vs_encodings[fp->index].encoding; strcpy(fp->name, AudioEslinear_be);
fp->precision = vs_encodings[fp->index].precision; fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
if (fp->encoding == AUDIO_ENCODING_ADPCM) fp->precision = 16;
fp->flags = 0; fp->flags = 0;
else return 0;
fp->flags = AUDIO_ENCODINGFLAG_EMULATED; }
return 0; return EINVAL;
} }
static int static int
@ -385,95 +370,48 @@ vs_set_params(void *hdl, int setmode, int usemode,
stream_filter_list_t *pfil, stream_filter_list_t *rfil) stream_filter_list_t *pfil, stream_filter_list_t *rfil)
{ {
struct vs_softc *sc; struct vs_softc *sc;
struct audio_params *p;
int mode;
int rate; int rate;
audio_params_t hw;
int matched;
DPRINTF(1, ("vs_set_params: setmode=%d, usemode=%d\n",
setmode, usemode));
sc = hdl; sc = hdl;
/* set first record info, then play info */
for (mode = AUMODE_RECORD; mode != -1;
mode = (mode == AUMODE_RECORD) ? AUMODE_PLAY : -1) {
if ((setmode & mode) == 0)
continue;
p = (mode == AUMODE_PLAY) ? play : rec; DPRINTF(1, ("vs_set_params: mode=%d enc=%d rate=%d prec=%d ch=%d: ",
setmode, play->encoding, play->sample_rate,
play->precision, play->channels));
if (p->channels != 1) if (play->channels != 1) {
return EINVAL; DPRINTF(1, ("channels not matched\n"));
return EINVAL;
rate = p->sample_rate;
hw = *p;
hw.encoding = AUDIO_ENCODING_ADPCM;
hw.precision = hw.validbits = 4;
DPRINTF(1, ("vs_set_params: encoding=%d, precision=%d\n",
p->encoding, p->precision));
matched = 0;
switch (p->precision) {
case 4:
if (p->encoding == AUDIO_ENCODING_ADPCM)
matched = 1;
break;
case 8:
switch (p->encoding) {
case AUDIO_ENCODING_ULAW:
matched = 1;
hw.encoding = AUDIO_ENCODING_ULINEAR_LE;
hw.precision = hw.validbits = 8;
pfil->prepend(pfil, mulaw_to_linear8, &hw);
hw.encoding = AUDIO_ENCODING_ADPCM;
hw.precision = hw.validbits = 4;
pfil->prepend(pfil, msm6258_linear8_to_adpcm, &hw);
rfil->append(rfil, msm6258_adpcm_to_linear8, &hw);
hw.encoding = AUDIO_ENCODING_ULINEAR_LE;
hw.precision = hw.validbits = 8;
rfil->append(rfil, linear8_to_mulaw, &hw);
break;
case AUDIO_ENCODING_SLINEAR:
case AUDIO_ENCODING_SLINEAR_LE:
case AUDIO_ENCODING_SLINEAR_BE:
case AUDIO_ENCODING_ULINEAR:
case AUDIO_ENCODING_ULINEAR_LE:
case AUDIO_ENCODING_ULINEAR_BE:
matched = 1;
pfil->append(pfil, msm6258_linear8_to_adpcm, &hw);
rfil->append(rfil, msm6258_adpcm_to_linear8, &hw);
break;
}
break;
case 16:
switch (p->encoding) {
case AUDIO_ENCODING_SLINEAR_LE:
case AUDIO_ENCODING_SLINEAR_BE:
matched = 1;
pfil->append(pfil, msm6258_slinear16_to_adpcm, &hw);
rfil->append(rfil, msm6258_adpcm_to_slinear16, &hw);
break;
}
break;
}
if (matched == 0) {
DPRINTF(1, ("vs_set_params: mode=%d, encoding=%d\n",
mode, p->encoding));
return EINVAL;
}
DPRINTF(1, ("vs_set_params: rate=%d -> ", rate));
rate = vs_round_sr(rate);
DPRINTF(1, ("%d\n", rate));
if (rate < 0)
return EINVAL;
if (mode == AUMODE_PLAY) {
sc->sc_current.prate = rate;
} else {
sc->sc_current.rrate = rate;
}
} }
rate = vs_round_sr(play->sample_rate);
if (rate < 0) {
DPRINTF(1, ("rate not matched\n"));
return EINVAL;
}
if (play->encoding != AUDIO_ENCODING_SLINEAR_BE) {
DPRINTF(1, ("encoding not matched\n"));
return EINVAL;
}
if (play->precision != 16) {
DPRINTF(1, ("precision not matched\n"));
return EINVAL;
}
play->encoding = AUDIO_ENCODING_ADPCM;
play->validbits = 4;
play->precision = 4;
pfil->prepend(pfil, msm6258_slinear16_to_adpcm, play);
rfil->prepend(rfil, msm6258_adpcm_to_slinear16, play);
sc->sc_current.prate = rate;
sc->sc_current.rrate = rate;
/* copy to rec because it's !AUDIO_PROP_INDEPENDENT */
*rec = *play;
DPRINTF(1, ("accepted\n"));
return 0; return 0;
} }