summaryrefslogtreecommitdiffstats
path: root/sys/dev/sound/usb
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2015-05-08 17:07:11 +0000
committerhselasky <hselasky@FreeBSD.org>2015-05-08 17:07:11 +0000
commite88a1dfd3e17536971b129f0e01f5ac9d71e277f (patch)
tree7ec6c496e433b6a6e426e10e1adfc0ce9c693229 /sys/dev/sound/usb
parent57f3cfe7b395def62c06ef001dec5d03c776d170 (diff)
downloadFreeBSD-src-e88a1dfd3e17536971b129f0e01f5ac9d71e277f.zip
FreeBSD-src-e88a1dfd3e17536971b129f0e01f5ac9d71e277f.tar.gz
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
Diffstat (limited to 'sys/dev/sound/usb')
-rw-r--r--sys/dev/sound/usb/uaudio.c41
1 files changed, 27 insertions, 14 deletions
diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c
index 8822bf0..c255a19 100644
--- a/sys/dev/sound/usb/uaudio.c
+++ b/sys/dev/sound/usb/uaudio.c
@@ -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--) {
OpenPOWER on IntegriCloud