aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2007-08-08 10:49:08 -0400
committerJaroslav Kysela <perex@perex.cz>2007-10-16 09:58:31 -0400
commit64d27f96cb719cf8b5dae634c4c548049d4ae6bf (patch)
treef10c68d67e15711d48a92ed258c93ca9018e5584 /sound/core
parent9390ec85c0ab98444140190f936a37fa4eb945a2 (diff)
[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: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/oss/pcm_plugin.c56
-rw-r--r--sound/core/pcm_misc.c32
2 files changed, 29 insertions, 59 deletions
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
index c0afb92869d3..25dcf96a5dc6 100644
--- a/sound/core/oss/pcm_plugin.c
+++ b/sound/core/oss/pcm_plugin.c
@@ -264,6 +264,8 @@ static int snd_pcm_plug_formats(struct snd_mask *mask, int format)
264 SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE | 264 SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE |
265 SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_S24_LE | 265 SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_S24_LE |
266 SNDRV_PCM_FMTBIT_U24_BE | SNDRV_PCM_FMTBIT_S24_BE | 266 SNDRV_PCM_FMTBIT_U24_BE | SNDRV_PCM_FMTBIT_S24_BE |
267 SNDRV_PCM_FMTBIT_U24_3LE | SNDRV_PCM_FMTBIT_S24_3LE |
268 SNDRV_PCM_FMTBIT_U24_3BE | SNDRV_PCM_FMTBIT_S24_3BE |
267 SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE | 269 SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE |
268 SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE); 270 SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE);
269 snd_mask_set(&formats, SNDRV_PCM_FORMAT_MU_LAW); 271 snd_mask_set(&formats, SNDRV_PCM_FORMAT_MU_LAW);
@@ -280,6 +282,10 @@ static int preferred_formats[] = {
280 SNDRV_PCM_FORMAT_S16_BE, 282 SNDRV_PCM_FORMAT_S16_BE,
281 SNDRV_PCM_FORMAT_U16_LE, 283 SNDRV_PCM_FORMAT_U16_LE,
282 SNDRV_PCM_FORMAT_U16_BE, 284 SNDRV_PCM_FORMAT_U16_BE,
285 SNDRV_PCM_FORMAT_S24_3LE,
286 SNDRV_PCM_FORMAT_S24_3BE,
287 SNDRV_PCM_FORMAT_U24_3LE,
288 SNDRV_PCM_FORMAT_U24_3BE,
283 SNDRV_PCM_FORMAT_S24_LE, 289 SNDRV_PCM_FORMAT_S24_LE,
284 SNDRV_PCM_FORMAT_S24_BE, 290 SNDRV_PCM_FORMAT_S24_BE,
285 SNDRV_PCM_FORMAT_U24_LE, 291 SNDRV_PCM_FORMAT_U24_LE,
@@ -294,41 +300,37 @@ static int preferred_formats[] = {
294 300
295int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask) 301int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask)
296{ 302{
303 int i;
304
297 if (snd_mask_test(format_mask, format)) 305 if (snd_mask_test(format_mask, format))
298 return format; 306 return format;
299 if (! snd_pcm_plug_formats(format_mask, format)) 307 if (! snd_pcm_plug_formats(format_mask, format))
300 return -EINVAL; 308 return -EINVAL;
301 if (snd_pcm_format_linear(format)) { 309 if (snd_pcm_format_linear(format)) {
302 int width = snd_pcm_format_width(format); 310 unsigned int width = snd_pcm_format_width(format);
303 int unsignd = snd_pcm_format_unsigned(format); 311 int unsignd = snd_pcm_format_unsigned(format) > 0;
304 int big = snd_pcm_format_big_endian(format); 312 int big = snd_pcm_format_big_endian(format) > 0;
305 int format1; 313 unsigned int badness, best = -1;
306 int wid, width1=width; 314 int best_format = -1;
307 int dwidth1 = 8; 315 for (i = 0; i < ARRAY_SIZE(preferred_formats); i++) {
308 for (wid = 0; wid < 4; ++wid) { 316 int f = preferred_formats[i];
309 int end, big1 = big; 317 unsigned int w;
310 for (end = 0; end < 2; ++end) { 318 if (!snd_mask_test(format_mask, f))
311 int sgn, unsignd1 = unsignd; 319 continue;
312 for (sgn = 0; sgn < 2; ++sgn) { 320 w = snd_pcm_format_width(f);
313 format1 = snd_pcm_build_linear_format(width1, unsignd1, big1); 321 if (w >= width)
314 if (format1 >= 0 && 322 badness = w - width;
315 snd_mask_test(format_mask, format1)) 323 else
316 goto _found; 324 badness = width - w + 32;
317 unsignd1 = !unsignd1; 325 badness += snd_pcm_format_unsigned(f) != unsignd;
318 } 326 badness += snd_pcm_format_big_endian(f) != big;
319 big1 = !big1; 327 if (badness < best) {
320 } 328 best_format = f;
321 if (width1 == 32) { 329 best = badness;
322 dwidth1 = -dwidth1;
323 width1 = width;
324 } 330 }
325 width1 += dwidth1;
326 } 331 }
327 return -EINVAL; 332 return best_format >= 0 ? best_format : -EINVAL;
328 _found:
329 return format1;
330 } else { 333 } else {
331 unsigned int i;
332 switch (format) { 334 switch (format) {
333 case SNDRV_PCM_FORMAT_MU_LAW: 335 case SNDRV_PCM_FORMAT_MU_LAW:
334 for (i = 0; i < ARRAY_SIZE(preferred_formats); ++i) { 336 for (i = 0; i < ARRAY_SIZE(preferred_formats); ++i) {
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
index 0019c59a779d..9142fce4dda2 100644
--- a/sound/core/pcm_misc.c
+++ b/sound/core/pcm_misc.c
@@ -422,38 +422,6 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int
422 422
423EXPORT_SYMBOL(snd_pcm_format_set_silence); 423EXPORT_SYMBOL(snd_pcm_format_set_silence);
424 424
425/* [width][unsigned][bigendian] */
426static int linear_formats[4][2][2] = {
427 {{ SNDRV_PCM_FORMAT_S8, SNDRV_PCM_FORMAT_S8},
428 { SNDRV_PCM_FORMAT_U8, SNDRV_PCM_FORMAT_U8}},
429 {{SNDRV_PCM_FORMAT_S16_LE, SNDRV_PCM_FORMAT_S16_BE},
430 {SNDRV_PCM_FORMAT_U16_LE, SNDRV_PCM_FORMAT_U16_BE}},
431 {{SNDRV_PCM_FORMAT_S24_LE, SNDRV_PCM_FORMAT_S24_BE},
432 {SNDRV_PCM_FORMAT_U24_LE, SNDRV_PCM_FORMAT_U24_BE}},
433 {{SNDRV_PCM_FORMAT_S32_LE, SNDRV_PCM_FORMAT_S32_BE},
434 {SNDRV_PCM_FORMAT_U32_LE, SNDRV_PCM_FORMAT_U32_BE}}
435};
436
437/**
438 * snd_pcm_build_linear_format - return the suitable linear format for the given condition
439 * @width: the bit-width
440 * @unsignd: 1 if unsigned, 0 if signed.
441 * @big_endian: 1 if big-endian, 0 if little-endian
442 *
443 * Returns the suitable linear format for the given condition.
444 */
445snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian)
446{
447 if (width & 7)
448 return SND_PCM_FORMAT_UNKNOWN;
449 width = (width / 8) - 1;
450 if (width < 0 || width >= 4)
451 return SND_PCM_FORMAT_UNKNOWN;
452 return linear_formats[width][!!unsignd][!!big_endian];
453}
454
455EXPORT_SYMBOL(snd_pcm_build_linear_format);
456
457/** 425/**
458 * snd_pcm_limit_hw_rates - determine rate_min/rate_max fields 426 * snd_pcm_limit_hw_rates - determine rate_min/rate_max fields
459 * @runtime: the runtime instance 427 * @runtime: the runtime instance