diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c index fbf49f61850c..83ec6c1e729c 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; + 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 diff --git a/sys/dev/sound/pcm/channel.h b/sys/dev/sound/pcm/channel.h index 6601b546a353..45f43b55498b 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 a647269dba6d..308d5f2e8b61 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 3565ca530e13..32e034330f74 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 bc722df6f25a..cbc290129516 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,