Author: hselasky
Date: Fri May  8 17:07:11 2015
New Revision: 282651
URL: https://svnweb.freebsd.org/changeset/base/282651

Log:
  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

Modified:
  head/sys/dev/sound/usb/uaudio.c

Modified: head/sys/dev/sound/usb/uaudio.c
==============================================================================
--- head/sys/dev/sound/usb/uaudio.c     Fri May  8 17:00:33 2015        
(r282650)
+++ head/sys/dev/sound/usb/uaudio.c     Fri May  8 17:07:11 2015        
(r282651)
@@ -115,6 +115,8 @@ SYSCTL_INT(_hw_usb_uaudio, OID_AUTO, def
 #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_cla
                 */
                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_
 
                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_
                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_soft
                        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--) {
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to