Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 64d27f96 authored by Takashi Iwai's avatar Takashi Iwai Committed by Jaroslav Kysela
Browse files

[ALSA] Support 3-bytes 24bit format in PCM OSS emulation



Add the support of 3-bytes 24bit formats in PCM OSS emulation.
Also removed snd_pcm_build_linear_format() function.  It's exported
just for OSS emulation, and now the code was changed without calling
this function.

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarJaroslav Kysela <perex@suse.cz>
parent 9390ec85
Loading
Loading
Loading
Loading
+29 −27
Original line number Diff line number Diff line
@@ -264,6 +264,8 @@ static int snd_pcm_plug_formats(struct snd_mask *mask, int format)
		       SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE |
		       SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_S24_LE |
		       SNDRV_PCM_FMTBIT_U24_BE | SNDRV_PCM_FMTBIT_S24_BE |
		       SNDRV_PCM_FMTBIT_U24_3LE | SNDRV_PCM_FMTBIT_S24_3LE |
		       SNDRV_PCM_FMTBIT_U24_3BE | SNDRV_PCM_FMTBIT_S24_3BE |
		       SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE |
		       SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE);
	snd_mask_set(&formats, SNDRV_PCM_FORMAT_MU_LAW);
@@ -280,6 +282,10 @@ static int preferred_formats[] = {
	SNDRV_PCM_FORMAT_S16_BE,
	SNDRV_PCM_FORMAT_U16_LE,
	SNDRV_PCM_FORMAT_U16_BE,
	SNDRV_PCM_FORMAT_S24_3LE,
	SNDRV_PCM_FORMAT_S24_3BE,
	SNDRV_PCM_FORMAT_U24_3LE,
	SNDRV_PCM_FORMAT_U24_3BE,
	SNDRV_PCM_FORMAT_S24_LE,
	SNDRV_PCM_FORMAT_S24_BE,
	SNDRV_PCM_FORMAT_U24_LE,
@@ -294,41 +300,37 @@ static int preferred_formats[] = {

int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask)
{
	int i;

	if (snd_mask_test(format_mask, format))
		return format;
	if (! snd_pcm_plug_formats(format_mask, format))
		return -EINVAL;
	if (snd_pcm_format_linear(format)) {
		int width = snd_pcm_format_width(format);
		int unsignd = snd_pcm_format_unsigned(format);
		int big = snd_pcm_format_big_endian(format);
		int format1;
		int wid, width1=width;
		int dwidth1 = 8;
		for (wid = 0; wid < 4; ++wid) {
			int end, big1 = big;
			for (end = 0; end < 2; ++end) {
				int sgn, unsignd1 = unsignd;
				for (sgn = 0; sgn < 2; ++sgn) {
					format1 = snd_pcm_build_linear_format(width1, unsignd1, big1);
					if (format1 >= 0 &&
					    snd_mask_test(format_mask, format1))
						goto _found;
					unsignd1 = !unsignd1;
				}
				big1 = !big1;
			}
			if (width1 == 32) {
				dwidth1 = -dwidth1;
				width1 = width;
			}
			width1 += dwidth1;
		unsigned int width = snd_pcm_format_width(format);
		int unsignd = snd_pcm_format_unsigned(format) > 0;
		int big = snd_pcm_format_big_endian(format) > 0;
		unsigned int badness, best = -1;
		int best_format = -1;
		for (i = 0; i < ARRAY_SIZE(preferred_formats); i++) {
			int f = preferred_formats[i];
			unsigned int w;
			if (!snd_mask_test(format_mask, f))
				continue;
			w = snd_pcm_format_width(f);
			if (w >= width)
				badness = w - width;
			else
				badness = width - w + 32;
			badness += snd_pcm_format_unsigned(f) != unsignd;
			badness += snd_pcm_format_big_endian(f) != big;
			if (badness < best) {
				best_format = f;
				best = badness;
			}
		return -EINVAL;
	_found:
		return format1;
		}
		return best_format >= 0 ? best_format : -EINVAL;
	} else {
		unsigned int i;
		switch (format) {
		case SNDRV_PCM_FORMAT_MU_LAW:
			for (i = 0; i < ARRAY_SIZE(preferred_formats); ++i) {
+0 −32
Original line number Diff line number Diff line
@@ -422,38 +422,6 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int

EXPORT_SYMBOL(snd_pcm_format_set_silence);

/* [width][unsigned][bigendian] */
static int linear_formats[4][2][2] = {
	{{ SNDRV_PCM_FORMAT_S8, SNDRV_PCM_FORMAT_S8},
	 { SNDRV_PCM_FORMAT_U8, SNDRV_PCM_FORMAT_U8}},
	{{SNDRV_PCM_FORMAT_S16_LE, SNDRV_PCM_FORMAT_S16_BE},
	 {SNDRV_PCM_FORMAT_U16_LE, SNDRV_PCM_FORMAT_U16_BE}},
	{{SNDRV_PCM_FORMAT_S24_LE, SNDRV_PCM_FORMAT_S24_BE},
	 {SNDRV_PCM_FORMAT_U24_LE, SNDRV_PCM_FORMAT_U24_BE}},
	{{SNDRV_PCM_FORMAT_S32_LE, SNDRV_PCM_FORMAT_S32_BE},
	 {SNDRV_PCM_FORMAT_U32_LE, SNDRV_PCM_FORMAT_U32_BE}}
};

/**
 * snd_pcm_build_linear_format - return the suitable linear format for the given condition
 * @width: the bit-width
 * @unsignd: 1 if unsigned, 0 if signed.
 * @big_endian: 1 if big-endian, 0 if little-endian
 *
 * Returns the suitable linear format for the given condition.
 */
snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian)
{
	if (width & 7)
		return SND_PCM_FORMAT_UNKNOWN;
	width = (width / 8) - 1;
	if (width < 0 || width >= 4)
		return SND_PCM_FORMAT_UNKNOWN;
	return linear_formats[width][!!unsignd][!!big_endian];
}

EXPORT_SYMBOL(snd_pcm_build_linear_format);

/**
 * snd_pcm_limit_hw_rates - determine rate_min/rate_max fields
 * @runtime: the runtime instance