summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2015-05-08 17:00:33 +0000
committerhselasky <hselasky@FreeBSD.org>2015-05-08 17:00:33 +0000
commit57f3cfe7b395def62c06ef001dec5d03c776d170 (patch)
tree25937c2b80456d238dea4896376843b573c97f0c
parent481dc6ddd12b2bf30fb3fa1ef01c9374934c4b56 (diff)
downloadFreeBSD-src-57f3cfe7b395def62c06ef001dec5d03c776d170.zip
FreeBSD-src-57f3cfe7b395def62c06ef001dec5d03c776d170.tar.gz
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
-rw-r--r--sys/dev/sound/pcm/channel.c147
-rw-r--r--sys/dev/sound/pcm/channel.h1
-rw-r--r--sys/dev/sound/pcm/feeder_chain.c35
-rw-r--r--sys/dev/sound/pcm/sound.h8
-rw-r--r--sys/sys/param.h2
5 files changed, 93 insertions, 100 deletions
diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c
index fbf49f6..83ec6c1 100644
--- a/sys/dev/sound/pcm/channel.c
+++ b/sys/dev/sound/pcm/channel.c
@@ -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));
- }
- }
-
- if (afmt == 0)
+ i = sscanf(b2, "%d.%d", &ch, &ext);
+
+ 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
diff --git a/sys/dev/sound/pcm/channel.h b/sys/dev/sound/pcm/channel.h
index 6601b54..45f43b5 100644
--- a/sys/dev/sound/pcm/channel.h
+++ b/sys/dev/sound/pcm/channel.h
@@ -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];
diff --git a/sys/dev/sound/pcm/feeder_chain.c b/sys/dev/sound/pcm/feeder_chain.c
index a647269..308d5f2 100644
--- a/sys/dev/sound/pcm/feeder_chain.c
+++ b/sys/dev/sound/pcm/feeder_chain.c
@@ -561,6 +561,20 @@ feeder_build_mixer(struct pcm_channel *c, struct feeder_chain_desc *cdesc)
((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)
diff --git a/sys/dev/sound/pcm/sound.h b/sys/dev/sound/pcm/sound.h
index 3565ca5..32e0343 100644
--- a/sys/dev/sound/pcm/sound.h
+++ b/sys/dev/sound/pcm/sound.h
@@ -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)
diff --git a/sys/sys/param.h b/sys/sys/param.h
index bc722df..cbc2901 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -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,
OpenPOWER on IntegriCloud