Author: hselasky
Date: Wed Jun  3 15:32:43 2015
New Revision: 283950
URL: https://svnweb.freebsd.org/changeset/base/283950

Log:
  MFC r282650 and r282651:
  Extend the maximum number of allowed PCM channels in a PCM stream to
  127 and decrease the maximum number of sub-channels to 1. These
  definitions are only used inside the kernel and can be changed later
  if more than one sub-channel is desired. This has been done to allow
  so-called USB audio rack modules to work with FreeBSD.
  
  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.
  
  Bump the FreeBSD version to force recompiling all external modules.

Modified:
  stable/10/sys/dev/sound/pcm/channel.c
  stable/10/sys/dev/sound/pcm/channel.h
  stable/10/sys/dev/sound/pcm/feeder_chain.c
  stable/10/sys/dev/sound/pcm/sound.h
  stable/10/sys/dev/sound/usb/uaudio.c
  stable/10/sys/sys/param.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/sound/pcm/channel.c
==============================================================================
--- stable/10/sys/dev/sound/pcm/channel.c       Wed Jun  3 15:18:32 2015        
(r283949)
+++ stable/10/sys/dev/sound/pcm/channel.c       Wed Jun  3 15:32:43 2015        
(r283950)
@@ -1029,32 +1029,17 @@ static const struct {
        {    NULL,  NULL, NULL, 0           }
 };
 
-static const struct {
-       char *name, *alias1, *alias2;
-       int matrix_id;
-} matrix_id_tab[] = {
-       { "1.0",  "1",   "mono", SND_CHN_MATRIX_1_0     },
-       { "2.0",  "2", "stereo", SND_CHN_MATRIX_2_0     },
-       { "2.1", NULL,     NULL, SND_CHN_MATRIX_2_1     },
-       { "3.0",  "3",     NULL, SND_CHN_MATRIX_3_0     },
-       { "3.1", NULL,     NULL, SND_CHN_MATRIX_3_1     },
-       { "4.0",  "4",   "quad", SND_CHN_MATRIX_4_0     },
-       { "4.1", NULL,     NULL, SND_CHN_MATRIX_4_1     },
-       { "5.0",  "5",     NULL, SND_CHN_MATRIX_5_0     },
-       { "5.1",  "6",     NULL, SND_CHN_MATRIX_5_1     },
-       { "6.0", NULL,     NULL, SND_CHN_MATRIX_6_0     },
-       { "6.1",  "7",     NULL, SND_CHN_MATRIX_6_1     },
-       { "7.0", NULL,     NULL, SND_CHN_MATRIX_7_0     },
-       { "7.1",  "8",     NULL, SND_CHN_MATRIX_7_1     },
-       {  NULL, NULL,     NULL, SND_CHN_MATRIX_UNKNOWN }
-};
-
 uint32_t
 snd_str2afmt(const char *req)
 {
-       uint32_t i, afmt;
-       int matrix_id;
-       char b1[8], b2[8];
+       int ext;
+       int ch;
+       int i;
+       char b1[8];
+       char b2[8];
+
+       memset(b1, 0, sizeof(b1));
+       memset(b2, 0, sizeof(b2));
 
        i = sscanf(req, "%5[^:]:%6s", b1, b2);
 
@@ -1068,88 +1053,78 @@ snd_str2afmt(const char *req)
        } else
                return (0);
 
-       afmt = 0;
-       matrix_id = SND_CHN_MATRIX_UNKNOWN;
-
-       for (i = 0; afmt == 0 && afmt_tab[i].name != NULL; i++) {
-               if (strcasecmp(afmt_tab[i].name, b1) == 0 ||
-                   (afmt_tab[i].alias1 != NULL &&
-                   strcasecmp(afmt_tab[i].alias1, b1) == 0) ||
-                   (afmt_tab[i].alias2 != NULL &&
-                   strcasecmp(afmt_tab[i].alias2, b1) == 0)) {
-                       afmt = afmt_tab[i].afmt;
-                       strlcpy(b1, afmt_tab[i].name, sizeof(b1));
-               }
-       }
+       i = sscanf(b2, "%d.%d", &ch, &ext);
 
-       if (afmt == 0)
+       if (i == 0) {
+               if (strcasecmp(b2, "mono") == 0) {
+                       ch = 1;
+                       ext = 0;
+               } else if (strcasecmp(b2, "stereo") == 0) {
+                       ch = 2;
+                       ext = 0;
+               } else if (strcasecmp(b2, "quad") == 0) {
+                       ch = 4;
+                       ext = 0;
+               } else
+                       return (0);
+       } else if (i == 1) {
+               if (ch < 1 || ch > AFMT_CHANNEL_MAX)
+                       return (0);
+               ext = 0;
+       } else if (i == 2) {
+               if (ext < 0 || ext > AFMT_EXTCHANNEL_MAX)
+                       return (0);
+               if (ch < 1 || (ch + ext) > AFMT_CHANNEL_MAX)
+                       return (0);
+       } else
                return (0);
 
-       for (i = 0; matrix_id == SND_CHN_MATRIX_UNKNOWN &&
-           matrix_id_tab[i].name != NULL; i++) {
-               if (strcmp(matrix_id_tab[i].name, b2) == 0 ||
-                   (matrix_id_tab[i].alias1 != NULL &&
-                   strcmp(matrix_id_tab[i].alias1, b2) == 0) ||
-                   (matrix_id_tab[i].alias2 != NULL &&
-                   strcasecmp(matrix_id_tab[i].alias2, b2) == 0)) {
-                       matrix_id = matrix_id_tab[i].matrix_id;
-                       strlcpy(b2, matrix_id_tab[i].name, sizeof(b2));
+       for (i = 0; afmt_tab[i].name != NULL; i++) {
+               if (strcasecmp(afmt_tab[i].name, b1) != 0) {
+                       if (afmt_tab[i].alias1 == NULL)
+                               continue;
+                       if (strcasecmp(afmt_tab[i].alias1, b1) != 0) {
+                               if (afmt_tab[i].alias2 == NULL)
+                                       continue;
+                               if (strcasecmp(afmt_tab[i].alias2, b1) != 0)
+                                       continue;
+                       }
                }
+               /* found a match */
+               return (SND_FORMAT(afmt_tab[i].afmt, ch + ext, ext));   
        }
-
-       if (matrix_id == SND_CHN_MATRIX_UNKNOWN)
-               return (0);
-
-#ifndef _KERNEL
-       printf("Parse OK: '%s' -> '%s:%s' %d\n", req, b1, b2,
-           (int)(b2[0]) - '0' + (int)(b2[2]) - '0');
-#endif
-
-       return (SND_FORMAT(afmt, b2[0] - '0' + b2[2] - '0', b2[2] - '0'));
+       /* not a valid format */
+       return (0);
 }
 
 uint32_t
 snd_afmt2str(uint32_t afmt, char *buf, size_t len)
 {
-       uint32_t i, enc, ch, ext;
-       char tmp[AFMTSTR_LEN];
+       uint32_t enc;
+       uint32_t ext;
+       uint32_t ch;
+       int i;
 
        if (buf == NULL || len < AFMTSTR_LEN)
                return (0);
 
-       
-       bzero(tmp, sizeof(tmp));
+       memset(buf, 0, len);
 
        enc = AFMT_ENCODING(afmt);
        ch = AFMT_CHANNEL(afmt);
        ext = AFMT_EXTCHANNEL(afmt);
-
-       for (i = 0; afmt_tab[i].name != NULL; i++) {
-               if (enc == afmt_tab[i].afmt) {
-                       strlcpy(tmp, afmt_tab[i].name, sizeof(tmp));
-                       strlcat(tmp, ":", sizeof(tmp));
-                       break;
-               }
-       }
-
-       if (strlen(tmp) == 0)
+       /* check there is at least one channel */
+       if (ch <= ext)
                return (0);
-       
-       for (i = 0; matrix_id_tab[i].name != NULL; i++) {
-               if (ch == (matrix_id_tab[i].name[0] - '0' +
-                   matrix_id_tab[i].name[2] - '0') &&
-                   ext == (matrix_id_tab[i].name[2] - '0')) {
-                       strlcat(tmp, matrix_id_tab[i].name, sizeof(tmp));
-                       break;
-               }
+       for (i = 0; afmt_tab[i].name != NULL; i++) {
+               if (enc != afmt_tab[i].afmt)
+                       continue;
+               /* found a match */
+               snprintf(buf, len, "%s:%d.%d",
+                   afmt_tab[i].name, ch - ext, ext);
+               return (SND_FORMAT(enc, ch, ext));
        }
-
-       if (strlen(tmp) == 0)
-               return (0);
-
-       strlcpy(buf, tmp, len);
-
-       return (snd_str2afmt(buf));
+       return (0);
 }
 
 int

Modified: stable/10/sys/dev/sound/pcm/channel.h
==============================================================================
--- stable/10/sys/dev/sound/pcm/channel.h       Wed Jun  3 15:18:32 2015        
(r283949)
+++ stable/10/sys/dev/sound/pcm/channel.h       Wed Jun  3 15:32:43 2015        
(r283950)
@@ -162,6 +162,7 @@ struct pcm_channel {
        } channels;
 
        struct pcmchan_matrix matrix;
+       struct pcmchan_matrix matrix_scratch;
 
        int volume[SND_VOL_C_MAX][SND_CHN_T_VOL_MAX];
 

Modified: stable/10/sys/dev/sound/pcm/feeder_chain.c
==============================================================================
--- stable/10/sys/dev/sound/pcm/feeder_chain.c  Wed Jun  3 15:18:32 2015        
(r283949)
+++ stable/10/sys/dev/sound/pcm/feeder_chain.c  Wed Jun  3 15:32:43 2015        
(r283950)
@@ -562,6 +562,20 @@ feeder_build_mixer(struct pcm_channel *c
        ((c)->mode == FEEDER_CHAIN_LEAN &&                              \
        !((c)->current.afmt & (AFMT_S16_NE | AFMT_S32_NE)))))
 
+static void
+feeder_default_matrix(struct pcmchan_matrix *m, uint32_t fmt, int id)
+{
+       int x;
+
+       memset(m, 0, sizeof(*m));
+
+       m->id = id;
+       m->channels = AFMT_CHANNEL(fmt);
+       m->ext = AFMT_EXTCHANNEL(fmt);
+       for (x = 0; x != SND_CHN_T_MAX; x++)
+               m->offset[x] = -1;
+}
+
 int
 feeder_chain(struct pcm_channel *c)
 {
@@ -642,10 +656,10 @@ feeder_chain(struct pcm_channel *c)
         */
        hwmatrix = CHANNEL_GETMATRIX(c->methods, c->devinfo, hwfmt);
        if (hwmatrix == NULL) {
-               device_printf(c->dev,
-                   "%s(): failed to acquire hw matrix [0x%08x]\n",
-                   __func__, hwfmt);
-               return (ENODEV);
+               /* setup a default matrix */
+               hwmatrix = &c->matrix_scratch;
+               feeder_default_matrix(hwmatrix, hwfmt,
+                   SND_CHN_MATRIX_UNKNOWN);
        }
        /* ..... and rebuild hwfmt. */
        hwfmt = SND_FORMAT(hwfmt, hwmatrix->channels, hwmatrix->ext);
@@ -657,13 +671,14 @@ feeder_chain(struct pcm_channel *c)
            softmatrix->ext != AFMT_EXTCHANNEL(softfmt)) {
                softmatrix = feeder_matrix_format_map(softfmt);
                if (softmatrix == NULL) {
-                       device_printf(c->dev,
-                           "%s(): failed to acquire soft matrix [0x%08x]\n",
-                           __func__, softfmt);
-                       return (ENODEV);
+                       /* setup a default matrix */
+                       softmatrix = &c->matrix;
+                       feeder_default_matrix(softmatrix, softfmt,
+                           SND_CHN_MATRIX_PCMCHANNEL);
+               } else {
+                       c->matrix = *softmatrix;
+                       c->matrix.id = SND_CHN_MATRIX_PCMCHANNEL;
                }
-               c->matrix = *softmatrix;
-               c->matrix.id = SND_CHN_MATRIX_PCMCHANNEL;
        }
        softfmt = SND_FORMAT(softfmt, softmatrix->channels, softmatrix->ext);
        if (softfmt != c->format)

Modified: stable/10/sys/dev/sound/pcm/sound.h
==============================================================================
--- stable/10/sys/dev/sound/pcm/sound.h Wed Jun  3 15:18:32 2015        
(r283949)
+++ stable/10/sys/dev/sound/pcm/sound.h Wed Jun  3 15:32:43 2015        
(r283950)
@@ -220,10 +220,12 @@ struct snd_mixer;
  * ~(0xb00ff7ff)
  */
 #define AFMT_ENCODING_MASK     0xf00fffff
-#define AFMT_CHANNEL_MASK      0x01f00000
+#define AFMT_CHANNEL_MASK      0x07f00000
 #define AFMT_CHANNEL_SHIFT     20
-#define AFMT_EXTCHANNEL_MASK   0x0e000000
-#define AFMT_EXTCHANNEL_SHIFT  25
+#define AFMT_CHANNEL_MAX       0x7f
+#define AFMT_EXTCHANNEL_MASK   0x08000000
+#define AFMT_EXTCHANNEL_SHIFT  27
+#define AFMT_EXTCHANNEL_MAX    1
 
 #define AFMT_ENCODING(v)       ((v) & AFMT_ENCODING_MASK)
 

Modified: stable/10/sys/dev/sound/usb/uaudio.c
==============================================================================
--- stable/10/sys/dev/sound/usb/uaudio.c        Wed Jun  3 15:18:32 2015        
(r283949)
+++ stable/10/sys/dev/sound/usb/uaudio.c        Wed Jun  3 15:32:43 2015        
(r283950)
@@ -121,6 +121,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)
@@ -352,6 +354,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 {
@@ -1068,6 +1071,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;
@@ -1842,19 +1849,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;
                }
 
@@ -1881,6 +1890,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)
@@ -1955,15 +1968,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--) {

Modified: stable/10/sys/sys/param.h
==============================================================================
--- stable/10/sys/sys/param.h   Wed Jun  3 15:18:32 2015        (r283949)
+++ stable/10/sys/sys/param.h   Wed Jun  3 15:32:43 2015        (r283950)
@@ -58,7 +58,7 @@
  *             in the range 5 to 9.
  */
 #undef __FreeBSD_version
-#define __FreeBSD_version 1001516      /* Master, propagated to newvers */
+#define __FreeBSD_version 1001517      /* Master, propagated to newvers */
 
 /*
  * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
_______________________________________________
svn-src-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to