diff options
Diffstat (limited to 'include/sound/pcm_params.h')
-rw-r--r-- | include/sound/pcm_params.h | 366 |
1 files changed, 366 insertions, 0 deletions
diff --git a/include/sound/pcm_params.h b/include/sound/pcm_params.h new file mode 100644 index 000000000000..60b0e92e26f3 --- /dev/null +++ b/include/sound/pcm_params.h | |||
@@ -0,0 +1,366 @@ | |||
1 | #ifndef __SOUND_PCM_PARAMS_H | ||
2 | #define __SOUND_PCM_PARAMS_H | ||
3 | |||
4 | /* | ||
5 | * PCM params helpers | ||
6 | * Copyright (c) by Abramo Bagnara <abramo@alsa-project.org> | ||
7 | * | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | extern int snd_pcm_hw_param_mask(snd_pcm_substream_t *pcm, snd_pcm_hw_params_t *params, | ||
26 | snd_pcm_hw_param_t var, const snd_mask_t *val); | ||
27 | extern unsigned int snd_pcm_hw_param_value_min(const snd_pcm_hw_params_t *params, | ||
28 | snd_pcm_hw_param_t var, int *dir); | ||
29 | extern unsigned int snd_pcm_hw_param_value_max(const snd_pcm_hw_params_t *params, | ||
30 | snd_pcm_hw_param_t var, int *dir); | ||
31 | extern int _snd_pcm_hw_param_min(snd_pcm_hw_params_t *params, | ||
32 | snd_pcm_hw_param_t var, unsigned int val, int dir); | ||
33 | extern int _snd_pcm_hw_param_setinteger(snd_pcm_hw_params_t *params, | ||
34 | snd_pcm_hw_param_t var); | ||
35 | extern int _snd_pcm_hw_param_set(snd_pcm_hw_params_t *params, | ||
36 | snd_pcm_hw_param_t var, unsigned int val, int dir); | ||
37 | |||
38 | /* To share the same code we have alsa-lib */ | ||
39 | #define INLINE static inline | ||
40 | #define assert(a) (void)(a) | ||
41 | |||
42 | #define SNDRV_MASK_BITS 64 /* we use so far 64bits only */ | ||
43 | #define SNDRV_MASK_SIZE (SNDRV_MASK_BITS / 32) | ||
44 | #define MASK_OFS(i) ((i) >> 5) | ||
45 | #define MASK_BIT(i) (1U << ((i) & 31)) | ||
46 | |||
47 | INLINE unsigned int ld2(u_int32_t v) | ||
48 | { | ||
49 | unsigned r = 0; | ||
50 | |||
51 | if (v >= 0x10000) { | ||
52 | v >>= 16; | ||
53 | r += 16; | ||
54 | } | ||
55 | if (v >= 0x100) { | ||
56 | v >>= 8; | ||
57 | r += 8; | ||
58 | } | ||
59 | if (v >= 0x10) { | ||
60 | v >>= 4; | ||
61 | r += 4; | ||
62 | } | ||
63 | if (v >= 4) { | ||
64 | v >>= 2; | ||
65 | r += 2; | ||
66 | } | ||
67 | if (v >= 2) | ||
68 | r++; | ||
69 | return r; | ||
70 | } | ||
71 | |||
72 | INLINE size_t snd_mask_sizeof(void) | ||
73 | { | ||
74 | return sizeof(snd_mask_t); | ||
75 | } | ||
76 | |||
77 | INLINE void snd_mask_none(snd_mask_t *mask) | ||
78 | { | ||
79 | memset(mask, 0, sizeof(*mask)); | ||
80 | } | ||
81 | |||
82 | INLINE void snd_mask_any(snd_mask_t *mask) | ||
83 | { | ||
84 | memset(mask, 0xff, SNDRV_MASK_SIZE * sizeof(u_int32_t)); | ||
85 | } | ||
86 | |||
87 | INLINE int snd_mask_empty(const snd_mask_t *mask) | ||
88 | { | ||
89 | int i; | ||
90 | for (i = 0; i < SNDRV_MASK_SIZE; i++) | ||
91 | if (mask->bits[i]) | ||
92 | return 0; | ||
93 | return 1; | ||
94 | } | ||
95 | |||
96 | INLINE unsigned int snd_mask_min(const snd_mask_t *mask) | ||
97 | { | ||
98 | int i; | ||
99 | assert(!snd_mask_empty(mask)); | ||
100 | for (i = 0; i < SNDRV_MASK_SIZE; i++) { | ||
101 | if (mask->bits[i]) | ||
102 | return ffs(mask->bits[i]) - 1 + (i << 5); | ||
103 | } | ||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | INLINE unsigned int snd_mask_max(const snd_mask_t *mask) | ||
108 | { | ||
109 | int i; | ||
110 | assert(!snd_mask_empty(mask)); | ||
111 | for (i = SNDRV_MASK_SIZE - 1; i >= 0; i--) { | ||
112 | if (mask->bits[i]) | ||
113 | return ld2(mask->bits[i]) + (i << 5); | ||
114 | } | ||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | INLINE void snd_mask_set(snd_mask_t *mask, unsigned int val) | ||
119 | { | ||
120 | assert(val <= SNDRV_MASK_BITS); | ||
121 | mask->bits[MASK_OFS(val)] |= MASK_BIT(val); | ||
122 | } | ||
123 | |||
124 | INLINE void snd_mask_reset(snd_mask_t *mask, unsigned int val) | ||
125 | { | ||
126 | assert(val <= SNDRV_MASK_BITS); | ||
127 | mask->bits[MASK_OFS(val)] &= ~MASK_BIT(val); | ||
128 | } | ||
129 | |||
130 | INLINE void snd_mask_set_range(snd_mask_t *mask, unsigned int from, unsigned int to) | ||
131 | { | ||
132 | unsigned int i; | ||
133 | assert(to <= SNDRV_MASK_BITS && from <= to); | ||
134 | for (i = from; i <= to; i++) | ||
135 | mask->bits[MASK_OFS(i)] |= MASK_BIT(i); | ||
136 | } | ||
137 | |||
138 | INLINE void snd_mask_reset_range(snd_mask_t *mask, unsigned int from, unsigned int to) | ||
139 | { | ||
140 | unsigned int i; | ||
141 | assert(to <= SNDRV_MASK_BITS && from <= to); | ||
142 | for (i = from; i <= to; i++) | ||
143 | mask->bits[MASK_OFS(i)] &= ~MASK_BIT(i); | ||
144 | } | ||
145 | |||
146 | INLINE void snd_mask_leave(snd_mask_t *mask, unsigned int val) | ||
147 | { | ||
148 | unsigned int v; | ||
149 | assert(val <= SNDRV_MASK_BITS); | ||
150 | v = mask->bits[MASK_OFS(val)] & MASK_BIT(val); | ||
151 | snd_mask_none(mask); | ||
152 | mask->bits[MASK_OFS(val)] = v; | ||
153 | } | ||
154 | |||
155 | INLINE void snd_mask_intersect(snd_mask_t *mask, const snd_mask_t *v) | ||
156 | { | ||
157 | int i; | ||
158 | for (i = 0; i < SNDRV_MASK_SIZE; i++) | ||
159 | mask->bits[i] &= v->bits[i]; | ||
160 | } | ||
161 | |||
162 | INLINE int snd_mask_eq(const snd_mask_t *mask, const snd_mask_t *v) | ||
163 | { | ||
164 | return ! memcmp(mask, v, SNDRV_MASK_SIZE * sizeof(u_int32_t)); | ||
165 | } | ||
166 | |||
167 | INLINE void snd_mask_copy(snd_mask_t *mask, const snd_mask_t *v) | ||
168 | { | ||
169 | *mask = *v; | ||
170 | } | ||
171 | |||
172 | INLINE int snd_mask_test(const snd_mask_t *mask, unsigned int val) | ||
173 | { | ||
174 | assert(val <= SNDRV_MASK_BITS); | ||
175 | return mask->bits[MASK_OFS(val)] & MASK_BIT(val); | ||
176 | } | ||
177 | |||
178 | INLINE int snd_mask_single(const snd_mask_t *mask) | ||
179 | { | ||
180 | int i, c = 0; | ||
181 | assert(!snd_mask_empty(mask)); | ||
182 | for (i = 0; i < SNDRV_MASK_SIZE; i++) { | ||
183 | if (! mask->bits[i]) | ||
184 | continue; | ||
185 | if (mask->bits[i] & (mask->bits[i] - 1)) | ||
186 | return 0; | ||
187 | if (c) | ||
188 | return 0; | ||
189 | c++; | ||
190 | } | ||
191 | return 1; | ||
192 | } | ||
193 | |||
194 | INLINE int snd_mask_refine(snd_mask_t *mask, const snd_mask_t *v) | ||
195 | { | ||
196 | snd_mask_t old; | ||
197 | assert(!snd_mask_empty(mask)); | ||
198 | snd_mask_copy(&old, mask); | ||
199 | snd_mask_intersect(mask, v); | ||
200 | if (snd_mask_empty(mask)) | ||
201 | return -EINVAL; | ||
202 | return !snd_mask_eq(mask, &old); | ||
203 | } | ||
204 | |||
205 | INLINE int snd_mask_refine_first(snd_mask_t *mask) | ||
206 | { | ||
207 | assert(!snd_mask_empty(mask)); | ||
208 | if (snd_mask_single(mask)) | ||
209 | return 0; | ||
210 | snd_mask_leave(mask, snd_mask_min(mask)); | ||
211 | return 1; | ||
212 | } | ||
213 | |||
214 | INLINE int snd_mask_refine_last(snd_mask_t *mask) | ||
215 | { | ||
216 | assert(!snd_mask_empty(mask)); | ||
217 | if (snd_mask_single(mask)) | ||
218 | return 0; | ||
219 | snd_mask_leave(mask, snd_mask_max(mask)); | ||
220 | return 1; | ||
221 | } | ||
222 | |||
223 | INLINE int snd_mask_refine_min(snd_mask_t *mask, unsigned int val) | ||
224 | { | ||
225 | assert(!snd_mask_empty(mask)); | ||
226 | if (snd_mask_min(mask) >= val) | ||
227 | return 0; | ||
228 | snd_mask_reset_range(mask, 0, val - 1); | ||
229 | if (snd_mask_empty(mask)) | ||
230 | return -EINVAL; | ||
231 | return 1; | ||
232 | } | ||
233 | |||
234 | INLINE int snd_mask_refine_max(snd_mask_t *mask, unsigned int val) | ||
235 | { | ||
236 | assert(!snd_mask_empty(mask)); | ||
237 | if (snd_mask_max(mask) <= val) | ||
238 | return 0; | ||
239 | snd_mask_reset_range(mask, val + 1, SNDRV_MASK_BITS); | ||
240 | if (snd_mask_empty(mask)) | ||
241 | return -EINVAL; | ||
242 | return 1; | ||
243 | } | ||
244 | |||
245 | INLINE int snd_mask_refine_set(snd_mask_t *mask, unsigned int val) | ||
246 | { | ||
247 | int changed; | ||
248 | assert(!snd_mask_empty(mask)); | ||
249 | changed = !snd_mask_single(mask); | ||
250 | snd_mask_leave(mask, val); | ||
251 | if (snd_mask_empty(mask)) | ||
252 | return -EINVAL; | ||
253 | return changed; | ||
254 | } | ||
255 | |||
256 | INLINE int snd_mask_value(const snd_mask_t *mask) | ||
257 | { | ||
258 | assert(!snd_mask_empty(mask)); | ||
259 | return snd_mask_min(mask); | ||
260 | } | ||
261 | |||
262 | INLINE void snd_interval_any(snd_interval_t *i) | ||
263 | { | ||
264 | i->min = 0; | ||
265 | i->openmin = 0; | ||
266 | i->max = UINT_MAX; | ||
267 | i->openmax = 0; | ||
268 | i->integer = 0; | ||
269 | i->empty = 0; | ||
270 | } | ||
271 | |||
272 | INLINE void snd_interval_none(snd_interval_t *i) | ||
273 | { | ||
274 | i->empty = 1; | ||
275 | } | ||
276 | |||
277 | INLINE int snd_interval_checkempty(const snd_interval_t *i) | ||
278 | { | ||
279 | return (i->min > i->max || | ||
280 | (i->min == i->max && (i->openmin || i->openmax))); | ||
281 | } | ||
282 | |||
283 | INLINE int snd_interval_empty(const snd_interval_t *i) | ||
284 | { | ||
285 | return i->empty; | ||
286 | } | ||
287 | |||
288 | INLINE int snd_interval_single(const snd_interval_t *i) | ||
289 | { | ||
290 | assert(!snd_interval_empty(i)); | ||
291 | return (i->min == i->max || | ||
292 | (i->min + 1 == i->max && i->openmax)); | ||
293 | } | ||
294 | |||
295 | INLINE int snd_interval_value(const snd_interval_t *i) | ||
296 | { | ||
297 | assert(snd_interval_single(i)); | ||
298 | return i->min; | ||
299 | } | ||
300 | |||
301 | INLINE int snd_interval_min(const snd_interval_t *i) | ||
302 | { | ||
303 | assert(!snd_interval_empty(i)); | ||
304 | return i->min; | ||
305 | } | ||
306 | |||
307 | INLINE int snd_interval_max(const snd_interval_t *i) | ||
308 | { | ||
309 | unsigned int v; | ||
310 | assert(!snd_interval_empty(i)); | ||
311 | v = i->max; | ||
312 | if (i->openmax) | ||
313 | v--; | ||
314 | return v; | ||
315 | } | ||
316 | |||
317 | INLINE int snd_interval_test(const snd_interval_t *i, unsigned int val) | ||
318 | { | ||
319 | return !((i->min > val || (i->min == val && i->openmin) || | ||
320 | i->max < val || (i->max == val && i->openmax))); | ||
321 | } | ||
322 | |||
323 | INLINE void snd_interval_copy(snd_interval_t *d, const snd_interval_t *s) | ||
324 | { | ||
325 | *d = *s; | ||
326 | } | ||
327 | |||
328 | INLINE int snd_interval_setinteger(snd_interval_t *i) | ||
329 | { | ||
330 | if (i->integer) | ||
331 | return 0; | ||
332 | if (i->openmin && i->openmax && i->min == i->max) | ||
333 | return -EINVAL; | ||
334 | i->integer = 1; | ||
335 | return 1; | ||
336 | } | ||
337 | |||
338 | INLINE int snd_interval_eq(const snd_interval_t *i1, const snd_interval_t *i2) | ||
339 | { | ||
340 | if (i1->empty) | ||
341 | return i2->empty; | ||
342 | if (i2->empty) | ||
343 | return i1->empty; | ||
344 | return i1->min == i2->min && i1->openmin == i2->openmin && | ||
345 | i1->max == i2->max && i1->openmax == i2->openmax; | ||
346 | } | ||
347 | |||
348 | static inline unsigned int add(unsigned int a, unsigned int b) | ||
349 | { | ||
350 | if (a >= UINT_MAX - b) | ||
351 | return UINT_MAX; | ||
352 | return a + b; | ||
353 | } | ||
354 | |||
355 | static inline unsigned int sub(unsigned int a, unsigned int b) | ||
356 | { | ||
357 | if (a > b) | ||
358 | return a - b; | ||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | #undef INLINE | ||
363 | #undef assert | ||
364 | |||
365 | #endif /* __SOUND_PCM_PARAMS_H */ | ||
366 | |||