Add support for more than 8 audio channels per PCM stream for USB
audio class compliant devices under FreeBSD. Tested using 16 recording and 16 playback audio channels simultaneously. MFC after: 2 weeks
This commit is contained in:
parent
4ece1a889b
commit
9dd1273385
@ -115,6 +115,8 @@ SYSCTL_INT(_hw_usb_uaudio, OID_AUTO, default_channels, CTLFLAG_RWTUN,
|
||||
#define UAUDIO_NFRAMES 64 /* must be factor of 8 due HS-USB */
|
||||
#define UAUDIO_NCHANBUFS 2 /* number of outstanding request */
|
||||
#define UAUDIO_RECURSE_LIMIT 255 /* rounds */
|
||||
#define UAUDIO_CHANNELS_MAX MIN(64, AFMT_CHANNEL_MAX)
|
||||
#define UAUDIO_MATRIX_MAX 8 /* channels */
|
||||
|
||||
#define MAKE_WORD(h,l) (((h) << 8) | (l))
|
||||
#define BIT_TEST(bm,bno) (((bm)[(bno) / 8] >> (7 - ((bno) % 8))) & 1)
|
||||
@ -346,6 +348,7 @@ struct uaudio_softc {
|
||||
uint8_t sc_uq_au_no_xu:1;
|
||||
uint8_t sc_uq_bad_adc:1;
|
||||
uint8_t sc_uq_au_vendor_class:1;
|
||||
uint8_t sc_pcm_bitperfect:1;
|
||||
};
|
||||
|
||||
struct uaudio_terminal_node {
|
||||
@ -1062,6 +1065,10 @@ uaudio_attach_sub(device_t dev, kobj_class_t mixer_class, kobj_class_t chan_clas
|
||||
*/
|
||||
uaudio_pcm_setflags(dev, SD_F_SOFTPCMVOL);
|
||||
}
|
||||
if (sc->sc_pcm_bitperfect) {
|
||||
DPRINTF("device needs bitperfect by default\n");
|
||||
uaudio_pcm_setflags(dev, SD_F_BITPERFECT);
|
||||
}
|
||||
if (mixer_init(dev, mixer_class, sc))
|
||||
goto detach;
|
||||
sc->sc_mixer_init = 1;
|
||||
@ -1826,19 +1833,21 @@ uaudio_chan_fill_info_sub(struct uaudio_softc *sc, struct usb_device *udev,
|
||||
|
||||
format = chan_alt->p_fmt->freebsd_fmt;
|
||||
|
||||
/* get default SND_FORMAT() */
|
||||
format = SND_FORMAT(format, chan_alt->channels, 0);
|
||||
|
||||
switch (chan_alt->channels) {
|
||||
case 2:
|
||||
/* stereo */
|
||||
format = SND_FORMAT(format, 2, 0);
|
||||
break;
|
||||
uint32_t temp_fmt;
|
||||
case 1:
|
||||
/* mono */
|
||||
format = SND_FORMAT(format, 1, 0);
|
||||
case 2:
|
||||
/* mono and stereo */
|
||||
break;
|
||||
default:
|
||||
/* surround and more */
|
||||
format = feeder_matrix_default_format(
|
||||
SND_FORMAT(format, chan_alt->channels, 0));
|
||||
temp_fmt = feeder_matrix_default_format(format);
|
||||
/* if multichannel, then format can be zero */
|
||||
if (temp_fmt != 0)
|
||||
format = temp_fmt;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1865,6 +1874,10 @@ uaudio_chan_fill_info_sub(struct uaudio_softc *sc, struct usb_device *udev,
|
||||
chan->pcm_cap.fmtlist = chan->pcm_format;
|
||||
chan->pcm_cap.fmtlist[0] = format;
|
||||
|
||||
/* check if device needs bitperfect */
|
||||
if (chan_alt->channels > UAUDIO_MATRIX_MAX)
|
||||
sc->sc_pcm_bitperfect = 1;
|
||||
|
||||
if (rate < chan->pcm_cap.minspeed || chan->pcm_cap.minspeed == 0)
|
||||
chan->pcm_cap.minspeed = rate;
|
||||
if (rate > chan->pcm_cap.maxspeed || chan->pcm_cap.maxspeed == 0)
|
||||
@ -1939,15 +1952,15 @@ uaudio_chan_fill_info(struct uaudio_softc *sc, struct usb_device *udev)
|
||||
channels = 4;
|
||||
break;
|
||||
default:
|
||||
channels = 16;
|
||||
channels = UAUDIO_CHANNELS_MAX;
|
||||
break;
|
||||
}
|
||||
} else if (channels > 16) {
|
||||
channels = 16;
|
||||
}
|
||||
if (sbuf_new(&sc->sc_sndstat, NULL, 4096, SBUF_AUTOEXTEND)) {
|
||||
} else if (channels > UAUDIO_CHANNELS_MAX)
|
||||
channels = UAUDIO_CHANNELS_MAX;
|
||||
|
||||
if (sbuf_new(&sc->sc_sndstat, NULL, 4096, SBUF_AUTOEXTEND))
|
||||
sc->sc_sndstat_valid = 1;
|
||||
}
|
||||
|
||||
/* try to search for a valid config */
|
||||
|
||||
for (x = channels; x; x--) {
|
||||
|
Loading…
Reference in New Issue
Block a user