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
This commit is contained in:
Hans Petter Selasky 2015-05-08 17:00:33 +00:00
parent 5abe80cf6b
commit 4ece1a889b
5 changed files with 92 additions and 99 deletions

View File

@ -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;
i = sscanf(b2, "%d.%d", &ch, &ext);
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)
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);
/* check there is at least one channel */
if (ch <= ext)
return (0);
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 (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);
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;
}
}
if (strlen(tmp) == 0)
return (0);
strlcpy(buf, tmp, len);
return (snd_str2afmt(buf));
return (0);
}
int

View File

@ -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];

View File

@ -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)

View File

@ -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)

View File

@ -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,