vserver 1.9.3
[linux-2.6.git] / sound / core / pcm_misc.c
1 /*
2  *  PCM Interface - misc routines
3  *  Copyright (c) 1998 by Jaroslav Kysela <perex@suse.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 <sound/driver.h>
23 #include <linux/time.h>
24 #include <sound/core.h>
25 #include <sound/pcm.h>
26 #define SND_PCM_FORMAT_UNKNOWN (-1)
27
28 struct pcm_format_data {
29         char width;     /* bit width */
30         char phys;      /* physical bit width */
31         char le;        /* 0 = big-endian, 1 = little-endian, -1 = others */
32         char signd;     /* 0 = unsigned, 1 = signed, -1 = others */
33         unsigned char silence[8];       /* silence data to fill */
34 };
35
36 static struct pcm_format_data pcm_formats[SNDRV_PCM_FORMAT_LAST+1] = {
37         [SNDRV_PCM_FORMAT_S8] = {
38                 .width = 8, .phys = 8, .le = -1, .signd = 1,
39                 .silence = {},
40         },
41         [SNDRV_PCM_FORMAT_U8] = {
42                 .width = 8, .phys = 8, .le = -1, .signd = 0,
43                 .silence = { 0x80 },
44         },
45         [SNDRV_PCM_FORMAT_S16_LE] = {
46                 .width = 16, .phys = 16, .le = 1, .signd = 1,
47                 .silence = {},
48         },
49         [SNDRV_PCM_FORMAT_S16_BE] = {
50                 .width = 16, .phys = 16, .le = 0, .signd = 1,
51                 .silence = {},
52         },
53         [SNDRV_PCM_FORMAT_U16_LE] = {
54                 .width = 16, .phys = 16, .le = 1, .signd = 0,
55                 .silence = { 0x00, 0x80 },
56         },
57         [SNDRV_PCM_FORMAT_U16_BE] = {
58                 .width = 16, .phys = 16, .le = 0, .signd = 0,
59                 .silence = { 0x80, 0x00 },
60         },
61         [SNDRV_PCM_FORMAT_S24_LE] = {
62                 .width = 24, .phys = 32, .le = 1, .signd = 1,
63                 .silence = {},
64         },
65         [SNDRV_PCM_FORMAT_S24_BE] = {
66                 .width = 24, .phys = 32, .le = 0, .signd = 1,
67                 .silence = {},
68         },
69         [SNDRV_PCM_FORMAT_U24_LE] = {
70                 .width = 24, .phys = 32, .le = 1, .signd = 0,
71                 .silence = { 0x00, 0x00, 0x80 },
72         },
73         [SNDRV_PCM_FORMAT_U24_BE] = {
74                 .width = 24, .phys = 32, .le = 0, .signd = 0,
75                 .silence = { 0x80, 0x00, 0x00 },
76         },
77         [SNDRV_PCM_FORMAT_S32_LE] = {
78                 .width = 32, .phys = 32, .le = 1, .signd = 1,
79                 .silence = {},
80         },
81         [SNDRV_PCM_FORMAT_S32_BE] = {
82                 .width = 32, .phys = 32, .le = 0, .signd = 1,
83                 .silence = {},
84         },
85         [SNDRV_PCM_FORMAT_U32_LE] = {
86                 .width = 32, .phys = 32, .le = 1, .signd = 0,
87                 .silence = { 0x00, 0x00, 0x00, 0x80 },
88         },
89         [SNDRV_PCM_FORMAT_U32_BE] = {
90                 .width = 32, .phys = 32, .le = 0, .signd = 0,
91                 .silence = { 0x80, 0x00, 0x00, 0x00 },
92         },
93         [SNDRV_PCM_FORMAT_FLOAT_LE] = {
94                 .width = 32, .phys = 32, .le = 1, .signd = -1,
95                 .silence = {},
96         },
97         [SNDRV_PCM_FORMAT_FLOAT_BE] = {
98                 .width = 32, .phys = 32, .le = 0, .signd = -1,
99                 .silence = {},
100         },
101         [SNDRV_PCM_FORMAT_FLOAT64_LE] = {
102                 .width = 64, .phys = 64, .le = 1, .signd = -1,
103                 .silence = {},
104         },
105         [SNDRV_PCM_FORMAT_FLOAT64_BE] = {
106                 .width = 64, .phys = 64, .le = 0, .signd = -1,
107                 .silence = {},
108         },
109         [SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE] = {
110                 .width = 32, .phys = 32, .le = 1, .signd = -1,
111                 .silence = {},
112         },
113         [SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE] = {
114                 .width = 32, .phys = 32, .le = 0, .signd = -1,
115                 .silence = {},
116         },
117         [SNDRV_PCM_FORMAT_MU_LAW] = {
118                 .width = 8, .phys = 8, .le = -1, .signd = -1,
119                 .silence = { 0x7f },
120         },
121         [SNDRV_PCM_FORMAT_A_LAW] = {
122                 .width = 8, .phys = 8, .le = -1, .signd = -1,
123                 .silence = { 0x55 },
124         },
125         [SNDRV_PCM_FORMAT_IMA_ADPCM] = {
126                 .width = 4, .phys = 4, .le = -1, .signd = -1,
127                 .silence = {},
128         },
129         /* FIXME: the following three formats are not defined properly yet */
130         [SNDRV_PCM_FORMAT_MPEG] = {
131                 .le = -1, .signd = -1,
132         },
133         [SNDRV_PCM_FORMAT_GSM] = {
134                 .le = -1, .signd = -1,
135         },
136         [SNDRV_PCM_FORMAT_SPECIAL] = {
137                 .le = -1, .signd = -1,
138         },
139         [SNDRV_PCM_FORMAT_S24_3LE] = {
140                 .width = 24, .phys = 24, .le = 1, .signd = 1,
141                 .silence = {},
142         },
143         [SNDRV_PCM_FORMAT_S24_3BE] = {
144                 .width = 24, .phys = 24, .le = 0, .signd = 1,
145                 .silence = {},
146         },
147         [SNDRV_PCM_FORMAT_U24_3LE] = {
148                 .width = 24, .phys = 24, .le = 1, .signd = 0,
149                 .silence = { 0x00, 0x00, 0x80 },
150         },
151         [SNDRV_PCM_FORMAT_U24_3BE] = {
152                 .width = 24, .phys = 24, .le = 0, .signd = 0,
153                 .silence = { 0x80, 0x00, 0x00 },
154         },
155         [SNDRV_PCM_FORMAT_S20_3LE] = {
156                 .width = 20, .phys = 24, .le = 1, .signd = 1,
157                 .silence = {},
158         },
159         [SNDRV_PCM_FORMAT_S20_3BE] = {
160                 .width = 20, .phys = 24, .le = 0, .signd = 1,
161                 .silence = {},
162         },
163         [SNDRV_PCM_FORMAT_U20_3LE] = {
164                 .width = 20, .phys = 24, .le = 1, .signd = 0,
165                 .silence = { 0x00, 0x00, 0x08 },
166         },
167         [SNDRV_PCM_FORMAT_U20_3BE] = {
168                 .width = 20, .phys = 24, .le = 0, .signd = 0,
169                 .silence = { 0x08, 0x00, 0x00 },
170         },
171         [SNDRV_PCM_FORMAT_S18_3LE] = {
172                 .width = 18, .phys = 24, .le = 1, .signd = 1,
173                 .silence = {},
174         },
175         [SNDRV_PCM_FORMAT_S18_3BE] = {
176                 .width = 18, .phys = 24, .le = 0, .signd = 1,
177                 .silence = {},
178         },
179         [SNDRV_PCM_FORMAT_U18_3LE] = {
180                 .width = 18, .phys = 24, .le = 1, .signd = 0,
181                 .silence = { 0x00, 0x00, 0x02 },
182         },
183         [SNDRV_PCM_FORMAT_U18_3BE] = {
184                 .width = 18, .phys = 24, .le = 0, .signd = 0,
185                 .silence = { 0x02, 0x00, 0x00 },
186         },
187 };
188
189
190 /**
191  * snd_pcm_format_signed - Check the PCM format is signed linear
192  * @format: the format to check
193  *
194  * Returns 1 if the given PCM format is signed linear, 0 if unsigned
195  * linear, and a negative error code for non-linear formats.
196  */
197 int snd_pcm_format_signed(snd_pcm_format_t format)
198 {
199         int val;
200         if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
201                 return -EINVAL;
202         if ((val = pcm_formats[format].signd) < 0)
203                 return -EINVAL;
204         return val;
205 }
206
207 /**
208  * snd_pcm_format_unsigned - Check the PCM format is unsigned linear
209  * @format: the format to check
210  *
211  * Returns 1 if the given PCM format is unsigned linear, 0 if signed
212  * linear, and a negative error code for non-linear formats.
213  */
214 int snd_pcm_format_unsigned(snd_pcm_format_t format)
215 {
216         int val;
217
218         val = snd_pcm_format_signed(format);
219         if (val < 0)
220                 return val;
221         return !val;
222 }
223
224 /**
225  * snd_pcm_format_linear - Check the PCM format is linear
226  * @format: the format to check
227  *
228  * Returns 1 if the given PCM format is linear, 0 if not.
229  */
230 int snd_pcm_format_linear(snd_pcm_format_t format)
231 {
232         return snd_pcm_format_signed(format) >= 0;
233 }
234
235 /**
236  * snd_pcm_format_little_endian - Check the PCM format is little-endian
237  * @format: the format to check
238  *
239  * Returns 1 if the given PCM format is little-endian, 0 if
240  * big-endian, or a negative error code if endian not specified.
241  */
242 int snd_pcm_format_little_endian(snd_pcm_format_t format)
243 {
244         int val;
245         if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
246                 return -EINVAL;
247         if ((val = pcm_formats[format].le) < 0)
248                 return -EINVAL;
249         return val;
250 }
251
252 /**
253  * snd_pcm_format_big_endian - Check the PCM format is big-endian
254  * @format: the format to check
255  *
256  * Returns 1 if the given PCM format is big-endian, 0 if
257  * little-endian, or a negative error code if endian not specified.
258  */
259 int snd_pcm_format_big_endian(snd_pcm_format_t format)
260 {
261         int val;
262
263         val = snd_pcm_format_little_endian(format);
264         if (val < 0)
265                 return val;
266         return !val;
267 }
268
269 /**
270  * snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian
271  * @format: the format to check
272  *
273  * Returns 1 if the given PCM format is CPU-endian, 0 if
274  * opposite, or a negative error code if endian not specified.
275  */
276 int snd_pcm_format_cpu_endian(snd_pcm_format_t format)
277 {
278 #ifdef SNDRV_LITTLE_ENDIAN
279         return snd_pcm_format_little_endian(format);
280 #else
281         return snd_pcm_format_big_endian(format);
282 #endif
283 }
284
285 /**
286  * snd_pcm_format_width - return the bit-width of the format
287  * @format: the format to check
288  *
289  * Returns the bit-width of the format, or a negative error code
290  * if unknown format.
291  */
292 int snd_pcm_format_width(snd_pcm_format_t format)
293 {
294         int val;
295         if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
296                 return -EINVAL;
297         if ((val = pcm_formats[format].width) == 0)
298                 return -EINVAL;
299         return val;
300 }
301
302 /**
303  * snd_pcm_format_physical_width - return the physical bit-width of the format
304  * @format: the format to check
305  *
306  * Returns the physical bit-width of the format, or a negative error code
307  * if unknown format.
308  */
309 int snd_pcm_format_physical_width(snd_pcm_format_t format)
310 {
311         int val;
312         if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
313                 return -EINVAL;
314         if ((val = pcm_formats[format].phys) == 0)
315                 return -EINVAL;
316         return val;
317 }
318
319 /**
320  * snd_pcm_format_size - return the byte size of samples on the given format
321  * @format: the format to check
322  *
323  * Returns the byte size of the given samples for the format, or a
324  * negative error code if unknown format.
325  */
326 ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples)
327 {
328         int phys_width = snd_pcm_format_physical_width(format);
329         if (phys_width < 0)
330                 return -EINVAL;
331         return samples * phys_width / 8;
332 }
333
334 /**
335  * snd_pcm_format_silence_64 - return the silent data in 8 bytes array
336  * @format: the format to check
337  *
338  * Returns the format pattern to fill or NULL if error.
339  */
340 const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format)
341 {
342         if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
343                 return NULL;
344         if (! pcm_formats[format].phys)
345                 return NULL;
346         return pcm_formats[format].silence;
347 }
348
349 /**
350  * snd_pcm_format_set_silence - set the silence data on the buffer
351  * @format: the PCM format
352  * @data: the buffer pointer
353  * @samples: the number of samples to set silence
354  *
355  * Sets the silence data on the buffer for the given samples.
356  *
357  * Returns zero if successful, or a negative error code on failure.
358  */
359 int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int samples)
360 {
361         int width;
362         unsigned char *dst, *pat;
363
364         if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
365                 return -EINVAL;
366         if (samples == 0)
367                 return 0;
368         width = pcm_formats[format].phys; /* physical width */
369         pat = pcm_formats[format].silence;
370         if (! width)
371                 return -EINVAL;
372         /* signed or 1 byte data */
373         if (pcm_formats[format].signd == 1 || width <= 8) {
374                 unsigned int bytes = samples * width / 8;
375                 memset(data, *pat, bytes);
376                 return 0;
377         }
378         /* non-zero samples, fill using a loop */
379         width /= 8;
380         dst = data;
381 #if 0
382         while (samples--) {
383                 memcpy(dst, pat, width);
384                 dst += width;
385         }
386 #else
387         /* a bit optimization for constant width */
388         switch (width) {
389         case 2:
390                 while (samples--) {
391                         memcpy(dst, pat, 2);
392                         dst += 2;
393                 }
394                 break;
395         case 3:
396                 while (samples--) {
397                         memcpy(dst, pat, 3);
398                         dst += 3;
399                 }
400                 break;
401         case 4:
402                 while (samples--) {
403                         memcpy(dst, pat, 4);
404                         dst += 4;
405                 }
406                 break;
407         case 8:
408                 while (samples--) {
409                         memcpy(dst, pat, 8);
410                         dst += 8;
411                 }
412                 break;
413         }
414 #endif
415         return 0;
416 }
417
418 /* [width][unsigned][bigendian] */
419 static int linear_formats[4][2][2] = {
420         {{ SNDRV_PCM_FORMAT_S8, SNDRV_PCM_FORMAT_S8},
421          { SNDRV_PCM_FORMAT_U8, SNDRV_PCM_FORMAT_U8}},
422         {{SNDRV_PCM_FORMAT_S16_LE, SNDRV_PCM_FORMAT_S16_BE},
423          {SNDRV_PCM_FORMAT_U16_LE, SNDRV_PCM_FORMAT_U16_BE}},
424         {{SNDRV_PCM_FORMAT_S24_LE, SNDRV_PCM_FORMAT_S24_BE},
425          {SNDRV_PCM_FORMAT_U24_LE, SNDRV_PCM_FORMAT_U24_BE}},
426         {{SNDRV_PCM_FORMAT_S32_LE, SNDRV_PCM_FORMAT_S32_BE},
427          {SNDRV_PCM_FORMAT_U32_LE, SNDRV_PCM_FORMAT_U32_BE}}
428 };
429
430 /**
431  * snd_pcm_build_linear_format - return the suitable linear format for the given condition
432  * @width: the bit-width
433  * @unsignd: 1 if unsigned, 0 if signed.
434  * @big_endian: 1 if big-endian, 0 if little-endian
435  *
436  * Returns the suitable linear format for the given condition.
437  */
438 snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian)
439 {
440         if (width & 7)
441                 return SND_PCM_FORMAT_UNKNOWN;
442         width = (width / 8) - 1;
443         if (width < 0 || width >= 4)
444                 return SND_PCM_FORMAT_UNKNOWN;
445         return linear_formats[width][!!unsignd][!!big_endian];
446 }
447
448 /**
449  * snd_pcm_limit_hw_rates - determine rate_min/rate_max fields
450  * @runtime: the runtime instance
451  *
452  * Determines the rate_min and rate_max fields from the rates bits of
453  * the given runtime->hw.
454  *
455  * Returns zero if successful.
456  */
457 int snd_pcm_limit_hw_rates(snd_pcm_runtime_t *runtime)
458 {
459         static unsigned rates[] = {
460                 /* ATTENTION: these values depend on the definition in pcm.h! */
461                 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000,
462                 64000, 88200, 96000, 176400, 192000
463         };
464         int i;
465         for (i = 0; i < (int)ARRAY_SIZE(rates); i++) {
466                 if (runtime->hw.rates & (1 << i)) {
467                         runtime->hw.rate_min = rates[i];
468                         break;
469                 }
470         }
471         for (i = (int)ARRAY_SIZE(rates) - 1; i >= 0; i--) {
472                 if (runtime->hw.rates & (1 << i)) {
473                         runtime->hw.rate_max = rates[i];
474                         break;
475                 }
476         }
477         return 0;
478 }