Author: hselasky
Date: Fri May  8 17:00:33 2015
New Revision: 282650
URL: https://svnweb.freebsd.org/changeset/base/282650

Log:
  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.
  
  Bump the FreeBSD version to force recompiling all external modules.
  
  MFC after:    2 weeks
  Reviewed by:  mav

Modified:
  head/sys/dev/sound/pcm/channel.c
  head/sys/dev/sound/pcm/channel.h
  head/sys/dev/sound/pcm/feeder_chain.c
  head/sys/dev/sound/pcm/sound.h
  head/sys/sys/param.h

Modified: head/sys/dev/sound/pcm/channel.c
==============================================================================
--- head/sys/dev/sound/pcm/channel.c    Fri May  8 16:43:01 2015        
(r282649)
+++ head/sys/dev/sound/pcm/channel.c    Fri May  8 17:00:33 2015        
(r282650)
@@ -1020,32 +1020,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);
 
@@ -1059,88 +1044,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: head/sys/dev/sound/pcm/channel.h
==============================================================================
--- head/sys/dev/sound/pcm/channel.h    Fri May  8 16:43:01 2015        
(r282649)
+++ head/sys/dev/sound/pcm/channel.h    Fri May  8 17:00:33 2015        
(r282650)
@@ -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: head/sys/dev/sound/pcm/feeder_chain.c
==============================================================================
--- head/sys/dev/sound/pcm/feeder_chain.c       Fri May  8 16:43:01 2015        
(r282649)
+++ head/sys/dev/sound/pcm/feeder_chain.c       Fri May  8 17:00:33 2015        
(r282650)
@@ -561,6 +561,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)
 {
@@ -641,10 +655,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);
@@ -656,13 +670,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: head/sys/dev/sound/pcm/sound.h
==============================================================================
--- head/sys/dev/sound/pcm/sound.h      Fri May  8 16:43:01 2015        
(r282649)
+++ head/sys/dev/sound/pcm/sound.h      Fri May  8 17:00:33 2015        
(r282650)
@@ -213,10 +213,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: head/sys/sys/param.h
==============================================================================
--- head/sys/sys/param.h        Fri May  8 16:43:01 2015        (r282649)
+++ head/sys/sys/param.h        Fri May  8 17:00:33 2015        (r282650)
@@ -58,7 +58,7 @@
  *             in the range 5 to 9.
  */
 #undef __FreeBSD_version
-#define __FreeBSD_version 1100072      /* Master, propagated to newvers */
+#define __FreeBSD_version 1100073      /* Master, propagated to newvers */
 
 /*
  * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
_______________________________________________
[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