• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/sound/core/
1/*
2 *  PCM Interface - misc routines
3 *  Copyright (c) 1998 by Jaroslav Kysela <perex@perex.cz>
4 *
5 *
6 *   This library is free software; you can redistribute it and/or modify
7 *   it under the terms of the GNU Library General Public License as
8 *   published by the Free Software Foundation; either version 2 of
9 *   the License, or (at your option) any later version.
10 *
11 *   This program is distributed in the hope that it will be useful,
12 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 *   GNU Library General Public License for more details.
15 *
16 *   You should have received a copy of the GNU Library General Public
17 *   License along with this library; if not, write to the Free Software
18 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 *
20 */
21
22#include <linux/time.h>
23#include <sound/core.h>
24#include <sound/pcm.h>
25#define SND_PCM_FORMAT_UNKNOWN (-1)
26
27/* NOTE: "signed" prefix must be given below since the default char is
28 *       unsigned on some architectures!
29 */
30struct pcm_format_data {
31	unsigned char width;	/* bit width */
32	unsigned char phys;	/* physical bit width */
33	signed char le;	/* 0 = big-endian, 1 = little-endian, -1 = others */
34	signed char signd;	/* 0 = unsigned, 1 = signed, -1 = others */
35	unsigned char silence[8];	/* silence data to fill */
36};
37
38static struct pcm_format_data pcm_formats[SNDRV_PCM_FORMAT_LAST+1] = {
39	[SNDRV_PCM_FORMAT_S8] = {
40		.width = 8, .phys = 8, .le = -1, .signd = 1,
41		.silence = {},
42	},
43	[SNDRV_PCM_FORMAT_U8] = {
44		.width = 8, .phys = 8, .le = -1, .signd = 0,
45		.silence = { 0x80 },
46	},
47	[SNDRV_PCM_FORMAT_S16_LE] = {
48		.width = 16, .phys = 16, .le = 1, .signd = 1,
49		.silence = {},
50	},
51	[SNDRV_PCM_FORMAT_S16_BE] = {
52		.width = 16, .phys = 16, .le = 0, .signd = 1,
53		.silence = {},
54	},
55	[SNDRV_PCM_FORMAT_U16_LE] = {
56		.width = 16, .phys = 16, .le = 1, .signd = 0,
57		.silence = { 0x00, 0x80 },
58	},
59	[SNDRV_PCM_FORMAT_U16_BE] = {
60		.width = 16, .phys = 16, .le = 0, .signd = 0,
61		.silence = { 0x80, 0x00 },
62	},
63	[SNDRV_PCM_FORMAT_S24_LE] = {
64		.width = 24, .phys = 32, .le = 1, .signd = 1,
65		.silence = {},
66	},
67	[SNDRV_PCM_FORMAT_S24_BE] = {
68		.width = 24, .phys = 32, .le = 0, .signd = 1,
69		.silence = {},
70	},
71	[SNDRV_PCM_FORMAT_U24_LE] = {
72		.width = 24, .phys = 32, .le = 1, .signd = 0,
73		.silence = { 0x00, 0x00, 0x80 },
74	},
75	[SNDRV_PCM_FORMAT_U24_BE] = {
76		.width = 24, .phys = 32, .le = 0, .signd = 0,
77		.silence = { 0x00, 0x80, 0x00, 0x00 },
78	},
79	[SNDRV_PCM_FORMAT_S32_LE] = {
80		.width = 32, .phys = 32, .le = 1, .signd = 1,
81		.silence = {},
82	},
83	[SNDRV_PCM_FORMAT_S32_BE] = {
84		.width = 32, .phys = 32, .le = 0, .signd = 1,
85		.silence = {},
86	},
87	[SNDRV_PCM_FORMAT_U32_LE] = {
88		.width = 32, .phys = 32, .le = 1, .signd = 0,
89		.silence = { 0x00, 0x00, 0x00, 0x80 },
90	},
91	[SNDRV_PCM_FORMAT_U32_BE] = {
92		.width = 32, .phys = 32, .le = 0, .signd = 0,
93		.silence = { 0x80, 0x00, 0x00, 0x00 },
94	},
95	[SNDRV_PCM_FORMAT_FLOAT_LE] = {
96		.width = 32, .phys = 32, .le = 1, .signd = -1,
97		.silence = {},
98	},
99	[SNDRV_PCM_FORMAT_FLOAT_BE] = {
100		.width = 32, .phys = 32, .le = 0, .signd = -1,
101		.silence = {},
102	},
103	[SNDRV_PCM_FORMAT_FLOAT64_LE] = {
104		.width = 64, .phys = 64, .le = 1, .signd = -1,
105		.silence = {},
106	},
107	[SNDRV_PCM_FORMAT_FLOAT64_BE] = {
108		.width = 64, .phys = 64, .le = 0, .signd = -1,
109		.silence = {},
110	},
111	[SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE] = {
112		.width = 32, .phys = 32, .le = 1, .signd = -1,
113		.silence = {},
114	},
115	[SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE] = {
116		.width = 32, .phys = 32, .le = 0, .signd = -1,
117		.silence = {},
118	},
119	[SNDRV_PCM_FORMAT_MU_LAW] = {
120		.width = 8, .phys = 8, .le = -1, .signd = -1,
121		.silence = { 0x7f },
122	},
123	[SNDRV_PCM_FORMAT_A_LAW] = {
124		.width = 8, .phys = 8, .le = -1, .signd = -1,
125		.silence = { 0x55 },
126	},
127	[SNDRV_PCM_FORMAT_IMA_ADPCM] = {
128		.width = 4, .phys = 4, .le = -1, .signd = -1,
129		.silence = {},
130	},
131	[SNDRV_PCM_FORMAT_G723_24] = {
132		.width = 3, .phys = 3, .le = -1, .signd = -1,
133		.silence = {},
134	},
135	[SNDRV_PCM_FORMAT_G723_40] = {
136		.width = 5, .phys = 5, .le = -1, .signd = -1,
137		.silence = {},
138	},
139	[SNDRV_PCM_FORMAT_MPEG] = {
140		.le = -1, .signd = -1,
141	},
142	[SNDRV_PCM_FORMAT_GSM] = {
143		.le = -1, .signd = -1,
144	},
145	[SNDRV_PCM_FORMAT_SPECIAL] = {
146		.le = -1, .signd = -1,
147	},
148	[SNDRV_PCM_FORMAT_S24_3LE] = {
149		.width = 24, .phys = 24, .le = 1, .signd = 1,
150		.silence = {},
151	},
152	[SNDRV_PCM_FORMAT_S24_3BE] = {
153		.width = 24, .phys = 24, .le = 0, .signd = 1,
154		.silence = {},
155	},
156	[SNDRV_PCM_FORMAT_U24_3LE] = {
157		.width = 24, .phys = 24, .le = 1, .signd = 0,
158		.silence = { 0x00, 0x00, 0x80 },
159	},
160	[SNDRV_PCM_FORMAT_U24_3BE] = {
161		.width = 24, .phys = 24, .le = 0, .signd = 0,
162		.silence = { 0x80, 0x00, 0x00 },
163	},
164	[SNDRV_PCM_FORMAT_S20_3LE] = {
165		.width = 20, .phys = 24, .le = 1, .signd = 1,
166		.silence = {},
167	},
168	[SNDRV_PCM_FORMAT_S20_3BE] = {
169		.width = 20, .phys = 24, .le = 0, .signd = 1,
170		.silence = {},
171	},
172	[SNDRV_PCM_FORMAT_U20_3LE] = {
173		.width = 20, .phys = 24, .le = 1, .signd = 0,
174		.silence = { 0x00, 0x00, 0x08 },
175	},
176	[SNDRV_PCM_FORMAT_U20_3BE] = {
177		.width = 20, .phys = 24, .le = 0, .signd = 0,
178		.silence = { 0x08, 0x00, 0x00 },
179	},
180	[SNDRV_PCM_FORMAT_S18_3LE] = {
181		.width = 18, .phys = 24, .le = 1, .signd = 1,
182		.silence = {},
183	},
184	[SNDRV_PCM_FORMAT_S18_3BE] = {
185		.width = 18, .phys = 24, .le = 0, .signd = 1,
186		.silence = {},
187	},
188	[SNDRV_PCM_FORMAT_U18_3LE] = {
189		.width = 18, .phys = 24, .le = 1, .signd = 0,
190		.silence = { 0x00, 0x00, 0x02 },
191	},
192	[SNDRV_PCM_FORMAT_U18_3BE] = {
193		.width = 18, .phys = 24, .le = 0, .signd = 0,
194		.silence = { 0x02, 0x00, 0x00 },
195	},
196	[SNDRV_PCM_FORMAT_G723_24_1B] = {
197		.width = 3, .phys = 8, .le = -1, .signd = -1,
198		.silence = {},
199	},
200	[SNDRV_PCM_FORMAT_G723_40_1B] = {
201		.width = 5, .phys = 8, .le = -1, .signd = -1,
202		.silence = {},
203	},
204};
205
206
207/**
208 * snd_pcm_format_signed - Check the PCM format is signed linear
209 * @format: the format to check
210 *
211 * Returns 1 if the given PCM format is signed linear, 0 if unsigned
212 * linear, and a negative error code for non-linear formats.
213 */
214int snd_pcm_format_signed(snd_pcm_format_t format)
215{
216	int val;
217	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
218		return -EINVAL;
219	if ((val = pcm_formats[format].signd) < 0)
220		return -EINVAL;
221	return val;
222}
223
224EXPORT_SYMBOL(snd_pcm_format_signed);
225
226/**
227 * snd_pcm_format_unsigned - Check the PCM format is unsigned linear
228 * @format: the format to check
229 *
230 * Returns 1 if the given PCM format is unsigned linear, 0 if signed
231 * linear, and a negative error code for non-linear formats.
232 */
233int snd_pcm_format_unsigned(snd_pcm_format_t format)
234{
235	int val;
236
237	val = snd_pcm_format_signed(format);
238	if (val < 0)
239		return val;
240	return !val;
241}
242
243EXPORT_SYMBOL(snd_pcm_format_unsigned);
244
245/**
246 * snd_pcm_format_linear - Check the PCM format is linear
247 * @format: the format to check
248 *
249 * Returns 1 if the given PCM format is linear, 0 if not.
250 */
251int snd_pcm_format_linear(snd_pcm_format_t format)
252{
253	return snd_pcm_format_signed(format) >= 0;
254}
255
256EXPORT_SYMBOL(snd_pcm_format_linear);
257
258/**
259 * snd_pcm_format_little_endian - Check the PCM format is little-endian
260 * @format: the format to check
261 *
262 * Returns 1 if the given PCM format is little-endian, 0 if
263 * big-endian, or a negative error code if endian not specified.
264 */
265int snd_pcm_format_little_endian(snd_pcm_format_t format)
266{
267	int val;
268	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
269		return -EINVAL;
270	if ((val = pcm_formats[format].le) < 0)
271		return -EINVAL;
272	return val;
273}
274
275EXPORT_SYMBOL(snd_pcm_format_little_endian);
276
277/**
278 * snd_pcm_format_big_endian - Check the PCM format is big-endian
279 * @format: the format to check
280 *
281 * Returns 1 if the given PCM format is big-endian, 0 if
282 * little-endian, or a negative error code if endian not specified.
283 */
284int snd_pcm_format_big_endian(snd_pcm_format_t format)
285{
286	int val;
287
288	val = snd_pcm_format_little_endian(format);
289	if (val < 0)
290		return val;
291	return !val;
292}
293
294EXPORT_SYMBOL(snd_pcm_format_big_endian);
295
296/**
297 * snd_pcm_format_width - return the bit-width of the format
298 * @format: the format to check
299 *
300 * Returns the bit-width of the format, or a negative error code
301 * if unknown format.
302 */
303int snd_pcm_format_width(snd_pcm_format_t format)
304{
305	int val;
306	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
307		return -EINVAL;
308	if ((val = pcm_formats[format].width) == 0)
309		return -EINVAL;
310	return val;
311}
312
313EXPORT_SYMBOL(snd_pcm_format_width);
314
315/**
316 * snd_pcm_format_physical_width - return the physical bit-width of the format
317 * @format: the format to check
318 *
319 * Returns the physical bit-width of the format, or a negative error code
320 * if unknown format.
321 */
322int snd_pcm_format_physical_width(snd_pcm_format_t format)
323{
324	int val;
325	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
326		return -EINVAL;
327	if ((val = pcm_formats[format].phys) == 0)
328		return -EINVAL;
329	return val;
330}
331
332EXPORT_SYMBOL(snd_pcm_format_physical_width);
333
334/**
335 * snd_pcm_format_size - return the byte size of samples on the given format
336 * @format: the format to check
337 * @samples: sampling rate
338 *
339 * Returns the byte size of the given samples for the format, or a
340 * negative error code if unknown format.
341 */
342ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples)
343{
344	int phys_width = snd_pcm_format_physical_width(format);
345	if (phys_width < 0)
346		return -EINVAL;
347	return samples * phys_width / 8;
348}
349
350EXPORT_SYMBOL(snd_pcm_format_size);
351
352/**
353 * snd_pcm_format_silence_64 - return the silent data in 8 bytes array
354 * @format: the format to check
355 *
356 * Returns the format pattern to fill or NULL if error.
357 */
358const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format)
359{
360	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
361		return NULL;
362	if (! pcm_formats[format].phys)
363		return NULL;
364	return pcm_formats[format].silence;
365}
366
367EXPORT_SYMBOL(snd_pcm_format_silence_64);
368
369/**
370 * snd_pcm_format_set_silence - set the silence data on the buffer
371 * @format: the PCM format
372 * @data: the buffer pointer
373 * @samples: the number of samples to set silence
374 *
375 * Sets the silence data on the buffer for the given samples.
376 *
377 * Returns zero if successful, or a negative error code on failure.
378 */
379int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int samples)
380{
381	int width;
382	unsigned char *dst, *pat;
383
384	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
385		return -EINVAL;
386	if (samples == 0)
387		return 0;
388	width = pcm_formats[format].phys; /* physical width */
389	pat = pcm_formats[format].silence;
390	if (! width)
391		return -EINVAL;
392	/* signed or 1 byte data */
393	if (pcm_formats[format].signd == 1 || width <= 8) {
394		unsigned int bytes = samples * width / 8;
395		memset(data, *pat, bytes);
396		return 0;
397	}
398	/* non-zero samples, fill using a loop */
399	width /= 8;
400	dst = data;
401	/* a bit optimization for constant width */
402	switch (width) {
403	case 2:
404		while (samples--) {
405			memcpy(dst, pat, 2);
406			dst += 2;
407		}
408		break;
409	case 3:
410		while (samples--) {
411			memcpy(dst, pat, 3);
412			dst += 3;
413		}
414		break;
415	case 4:
416		while (samples--) {
417			memcpy(dst, pat, 4);
418			dst += 4;
419		}
420		break;
421	case 8:
422		while (samples--) {
423			memcpy(dst, pat, 8);
424			dst += 8;
425		}
426		break;
427	}
428	return 0;
429}
430
431EXPORT_SYMBOL(snd_pcm_format_set_silence);
432
433/**
434 * snd_pcm_limit_hw_rates - determine rate_min/rate_max fields
435 * @runtime: the runtime instance
436 *
437 * Determines the rate_min and rate_max fields from the rates bits of
438 * the given runtime->hw.
439 *
440 * Returns zero if successful.
441 */
442int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime)
443{
444	int i;
445	for (i = 0; i < (int)snd_pcm_known_rates.count; i++) {
446		if (runtime->hw.rates & (1 << i)) {
447			runtime->hw.rate_min = snd_pcm_known_rates.list[i];
448			break;
449		}
450	}
451	for (i = (int)snd_pcm_known_rates.count - 1; i >= 0; i--) {
452		if (runtime->hw.rates & (1 << i)) {
453			runtime->hw.rate_max = snd_pcm_known_rates.list[i];
454			break;
455		}
456	}
457	return 0;
458}
459
460EXPORT_SYMBOL(snd_pcm_limit_hw_rates);
461
462/**
463 * snd_pcm_rate_to_rate_bit - converts sample rate to SNDRV_PCM_RATE_xxx bit
464 * @rate: the sample rate to convert
465 *
466 * Returns the SNDRV_PCM_RATE_xxx flag that corresponds to the given rate, or
467 * SNDRV_PCM_RATE_KNOT for an unknown rate.
468 */
469unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate)
470{
471	unsigned int i;
472
473	for (i = 0; i < snd_pcm_known_rates.count; i++)
474		if (snd_pcm_known_rates.list[i] == rate)
475			return 1u << i;
476	return SNDRV_PCM_RATE_KNOT;
477}
478EXPORT_SYMBOL(snd_pcm_rate_to_rate_bit);
479