Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0-or-later */
2 : : #ifndef __SOUND_PCM_PARAMS_H
3 : : #define __SOUND_PCM_PARAMS_H
4 : :
5 : : /*
6 : : * PCM params helpers
7 : : * Copyright (c) by Abramo Bagnara <abramo@alsa-project.org>
8 : : */
9 : :
10 : : #include <sound/pcm.h>
11 : :
12 : : int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm,
13 : : struct snd_pcm_hw_params *params,
14 : : snd_pcm_hw_param_t var, int *dir);
15 : : int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm,
16 : : struct snd_pcm_hw_params *params,
17 : : snd_pcm_hw_param_t var, int *dir);
18 : : int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params,
19 : : snd_pcm_hw_param_t var, int *dir);
20 : :
21 : : #define SNDRV_MASK_BITS 64 /* we use so far 64bits only */
22 : : #define SNDRV_MASK_SIZE (SNDRV_MASK_BITS / 32)
23 : : #define MASK_OFS(i) ((i) >> 5)
24 : : #define MASK_BIT(i) (1U << ((i) & 31))
25 : :
26 : : static inline size_t snd_mask_sizeof(void)
27 : : {
28 : : return sizeof(struct snd_mask);
29 : : }
30 : :
31 : 0 : static inline void snd_mask_none(struct snd_mask *mask)
32 : : {
33 : 0 : memset(mask, 0, sizeof(*mask));
34 : : }
35 : :
36 : 0 : static inline void snd_mask_any(struct snd_mask *mask)
37 : : {
38 : 0 : memset(mask, 0xff, SNDRV_MASK_SIZE * sizeof(u_int32_t));
39 : : }
40 : :
41 : : static inline int snd_mask_empty(const struct snd_mask *mask)
42 : : {
43 : : int i;
44 [ # # ]: 0 : for (i = 0; i < SNDRV_MASK_SIZE; i++)
45 [ # # ]: 0 : if (mask->bits[i])
46 : : return 0;
47 : : return 1;
48 : : }
49 : :
50 : 0 : static inline unsigned int snd_mask_min(const struct snd_mask *mask)
51 : : {
52 : 0 : int i;
53 [ # # # # : 0 : for (i = 0; i < SNDRV_MASK_SIZE; i++) {
# # ]
54 [ # # # # : 0 : if (mask->bits[i])
# # ]
55 : 0 : return __ffs(mask->bits[i]) + (i << 5);
56 : : }
57 : : return 0;
58 : : }
59 : :
60 : : static inline unsigned int snd_mask_max(const struct snd_mask *mask)
61 : : {
62 : : int i;
63 [ # # ]: 0 : for (i = SNDRV_MASK_SIZE - 1; i >= 0; i--) {
64 [ # # ]: 0 : if (mask->bits[i])
65 : 0 : return __fls(mask->bits[i]) + (i << 5);
66 : : }
67 : : return 0;
68 : : }
69 : :
70 : : static inline void snd_mask_set(struct snd_mask *mask, unsigned int val)
71 : : {
72 : : mask->bits[MASK_OFS(val)] |= MASK_BIT(val);
73 : : }
74 : :
75 : : /* Most of drivers need only this one */
76 : : static inline void snd_mask_set_format(struct snd_mask *mask,
77 : : snd_pcm_format_t format)
78 : : {
79 : : snd_mask_set(mask, (__force unsigned int)format);
80 : : }
81 : :
82 : 0 : static inline void snd_mask_reset(struct snd_mask *mask, unsigned int val)
83 : : {
84 : 0 : mask->bits[MASK_OFS(val)] &= ~MASK_BIT(val);
85 : 0 : }
86 : :
87 : : static inline void snd_mask_set_range(struct snd_mask *mask,
88 : : unsigned int from, unsigned int to)
89 : : {
90 : : unsigned int i;
91 : : for (i = from; i <= to; i++)
92 : : mask->bits[MASK_OFS(i)] |= MASK_BIT(i);
93 : : }
94 : :
95 : : static inline void snd_mask_reset_range(struct snd_mask *mask,
96 : : unsigned int from, unsigned int to)
97 : : {
98 : : unsigned int i;
99 : : for (i = from; i <= to; i++)
100 : : mask->bits[MASK_OFS(i)] &= ~MASK_BIT(i);
101 : : }
102 : :
103 : 0 : static inline void snd_mask_leave(struct snd_mask *mask, unsigned int val)
104 : : {
105 : 0 : unsigned int v;
106 : 0 : v = mask->bits[MASK_OFS(val)] & MASK_BIT(val);
107 : 0 : snd_mask_none(mask);
108 : 0 : mask->bits[MASK_OFS(val)] = v;
109 : : }
110 : :
111 : : static inline void snd_mask_intersect(struct snd_mask *mask,
112 : : const struct snd_mask *v)
113 : : {
114 : : int i;
115 [ # # ]: 0 : for (i = 0; i < SNDRV_MASK_SIZE; i++)
116 : 0 : mask->bits[i] &= v->bits[i];
117 : : }
118 : :
119 : 0 : static inline int snd_mask_eq(const struct snd_mask *mask,
120 : : const struct snd_mask *v)
121 : : {
122 : 0 : return ! memcmp(mask, v, SNDRV_MASK_SIZE * sizeof(u_int32_t));
123 : : }
124 : :
125 : 0 : static inline void snd_mask_copy(struct snd_mask *mask,
126 : : const struct snd_mask *v)
127 : : {
128 : 0 : *mask = *v;
129 : 0 : }
130 : :
131 : 0 : static inline int snd_mask_test(const struct snd_mask *mask, unsigned int val)
132 : : {
133 [ # # # # ]: 0 : return mask->bits[MASK_OFS(val)] & MASK_BIT(val);
134 : : }
135 : :
136 : 0 : static inline int snd_mask_single(const struct snd_mask *mask)
137 : : {
138 : 0 : int i, c = 0;
139 [ # # # # : 0 : for (i = 0; i < SNDRV_MASK_SIZE; i++) {
# # ]
140 [ # # # # : 0 : if (! mask->bits[i])
# # ]
141 : 0 : continue;
142 [ # # # # : 0 : if (mask->bits[i] & (mask->bits[i] - 1))
# # ]
143 : : return 0;
144 [ # # # # : 0 : if (c)
# # ]
145 : : return 0;
146 : : c++;
147 : : }
148 : : return 1;
149 : : }
150 : :
151 : 0 : static inline int snd_mask_refine(struct snd_mask *mask,
152 : : const struct snd_mask *v)
153 : : {
154 : 0 : struct snd_mask old;
155 : 0 : snd_mask_copy(&old, mask);
156 : : snd_mask_intersect(mask, v);
157 [ # # ]: 0 : if (snd_mask_empty(mask))
158 : : return -EINVAL;
159 : 0 : return !snd_mask_eq(mask, &old);
160 : : }
161 : :
162 : 0 : static inline int snd_mask_refine_first(struct snd_mask *mask)
163 : : {
164 [ # # ]: 0 : if (snd_mask_single(mask))
165 : : return 0;
166 : : snd_mask_leave(mask, snd_mask_min(mask));
167 : 0 : return 1;
168 : : }
169 : :
170 : 0 : static inline int snd_mask_refine_last(struct snd_mask *mask)
171 : : {
172 [ # # ]: 0 : if (snd_mask_single(mask))
173 : : return 0;
174 : : snd_mask_leave(mask, snd_mask_max(mask));
175 : 0 : return 1;
176 : : }
177 : :
178 : : static inline int snd_mask_refine_min(struct snd_mask *mask, unsigned int val)
179 : : {
180 : : if (snd_mask_min(mask) >= val)
181 : : return 0;
182 : : snd_mask_reset_range(mask, 0, val - 1);
183 : : if (snd_mask_empty(mask))
184 : : return -EINVAL;
185 : : return 1;
186 : : }
187 : :
188 : : static inline int snd_mask_refine_max(struct snd_mask *mask, unsigned int val)
189 : : {
190 : : if (snd_mask_max(mask) <= val)
191 : : return 0;
192 : : snd_mask_reset_range(mask, val + 1, SNDRV_MASK_BITS);
193 : : if (snd_mask_empty(mask))
194 : : return -EINVAL;
195 : : return 1;
196 : : }
197 : :
198 : : static inline int snd_mask_refine_set(struct snd_mask *mask, unsigned int val)
199 : : {
200 : : int changed;
201 : : changed = !snd_mask_single(mask);
202 : : snd_mask_leave(mask, val);
203 : : if (snd_mask_empty(mask))
204 : : return -EINVAL;
205 : : return changed;
206 : : }
207 : :
208 : 0 : static inline int snd_mask_value(const struct snd_mask *mask)
209 : : {
210 : 0 : return snd_mask_min(mask);
211 : : }
212 : :
213 : 0 : static inline void snd_interval_any(struct snd_interval *i)
214 : : {
215 : 0 : i->min = 0;
216 : 0 : i->openmin = 0;
217 : 0 : i->max = UINT_MAX;
218 : 0 : i->openmax = 0;
219 : 0 : i->integer = 0;
220 : 0 : i->empty = 0;
221 : : }
222 : :
223 : 0 : static inline void snd_interval_none(struct snd_interval *i)
224 : : {
225 : 0 : i->empty = 1;
226 : : }
227 : :
228 : 0 : static inline int snd_interval_checkempty(const struct snd_interval *i)
229 : : {
230 [ # # # # : 0 : return (i->min > i->max ||
# # # # ]
231 [ # # # # ]: 0 : (i->min == i->max && (i->openmin || i->openmax)));
232 : : }
233 : :
234 : 0 : static inline int snd_interval_empty(const struct snd_interval *i)
235 : : {
236 [ # # # # : 0 : return i->empty;
# # # # ]
237 : : }
238 : :
239 : 0 : static inline int snd_interval_single(const struct snd_interval *i)
240 : : {
241 [ # # # # : 0 : return (i->min == i->max ||
# # # # #
# # # ]
242 [ # # # # : 0 : (i->min + 1 == i->max && (i->openmin || i->openmax)));
# # # # #
# # # # #
# # # # #
# # # #
# ]
243 : : }
244 : :
245 : 0 : static inline int snd_interval_value(const struct snd_interval *i)
246 : : {
247 [ # # # # ]: 0 : if (i->openmin && !i->openmax)
248 : 0 : return i->max;
249 [ # # ]: 0 : return i->min;
250 : : }
251 : :
252 : : static inline int snd_interval_min(const struct snd_interval *i)
253 : : {
254 : : return i->min;
255 : : }
256 : :
257 : : static inline int snd_interval_max(const struct snd_interval *i)
258 : : {
259 : : unsigned int v;
260 : : v = i->max;
261 : : if (i->openmax)
262 : : v--;
263 : : return v;
264 : : }
265 : :
266 : 0 : static inline int snd_interval_test(const struct snd_interval *i, unsigned int val)
267 : : {
268 [ # # # # : 0 : return !((i->min > val || (i->min == val && i->openmin) ||
# # # # ]
269 [ # # # # ]: 0 : i->max < val || (i->max == val && i->openmax)));
270 : : }
271 : :
272 : 0 : static inline void snd_interval_copy(struct snd_interval *d, const struct snd_interval *s)
273 : : {
274 : 0 : *d = *s;
275 : : }
276 : :
277 : 0 : static inline int snd_interval_setinteger(struct snd_interval *i)
278 : : {
279 [ # # ]: 0 : if (i->integer)
280 : : return 0;
281 [ # # # # ]: 0 : if (i->openmin && i->openmax && i->min == i->max)
282 : : return -EINVAL;
283 : 0 : i->integer = 1;
284 : 0 : return 1;
285 : : }
286 : :
287 : : static inline int snd_interval_eq(const struct snd_interval *i1, const struct snd_interval *i2)
288 : : {
289 : : if (i1->empty)
290 : : return i2->empty;
291 : : if (i2->empty)
292 : : return i1->empty;
293 : : return i1->min == i2->min && i1->openmin == i2->openmin &&
294 : : i1->max == i2->max && i1->openmax == i2->openmax;
295 : : }
296 : :
297 : : /**
298 : : * params_access - get the access type from the hw params
299 : : * @p: hw params
300 : : */
301 : 0 : static inline snd_pcm_access_t params_access(const struct snd_pcm_hw_params *p)
302 : : {
303 : 0 : return (__force snd_pcm_access_t)snd_mask_min(hw_param_mask_c(p,
304 : : SNDRV_PCM_HW_PARAM_ACCESS));
305 : : }
306 : :
307 : : /**
308 : : * params_format - get the sample format from the hw params
309 : : * @p: hw params
310 : : */
311 : 0 : static inline snd_pcm_format_t params_format(const struct snd_pcm_hw_params *p)
312 : : {
313 : 0 : return (__force snd_pcm_format_t)snd_mask_min(hw_param_mask_c(p,
314 : : SNDRV_PCM_HW_PARAM_FORMAT));
315 : : }
316 : :
317 : : /**
318 : : * params_subformat - get the sample subformat from the hw params
319 : : * @p: hw params
320 : : */
321 : : static inline snd_pcm_subformat_t
322 : 0 : params_subformat(const struct snd_pcm_hw_params *p)
323 : : {
324 [ # # ]: 0 : return (__force snd_pcm_subformat_t)snd_mask_min(hw_param_mask_c(p,
325 : : SNDRV_PCM_HW_PARAM_SUBFORMAT));
326 : : }
327 : :
328 : : /**
329 : : * params_period_bytes - get the period size (in bytes) from the hw params
330 : : * @p: hw params
331 : : */
332 : : static inline unsigned int
333 : : params_period_bytes(const struct snd_pcm_hw_params *p)
334 : : {
335 : : return hw_param_interval_c(p, SNDRV_PCM_HW_PARAM_PERIOD_BYTES)->min;
336 : : }
337 : :
338 : : /**
339 : : * params_width - get the number of bits of the sample format from the hw params
340 : : * @p: hw params
341 : : *
342 : : * This function returns the number of bits per sample that the selected sample
343 : : * format of the hw params has.
344 : : */
345 : : static inline int params_width(const struct snd_pcm_hw_params *p)
346 : : {
347 : : return snd_pcm_format_width(params_format(p));
348 : : }
349 : :
350 : : /*
351 : : * params_physical_width - get the storage size of the sample format from the hw params
352 : : * @p: hw params
353 : : *
354 : : * This functions returns the number of bits per sample that the selected sample
355 : : * format of the hw params takes up in memory. This will be equal or larger than
356 : : * params_width().
357 : : */
358 : : static inline int params_physical_width(const struct snd_pcm_hw_params *p)
359 : : {
360 : : return snd_pcm_format_physical_width(params_format(p));
361 : : }
362 : :
363 : : static inline void
364 : : params_set_format(struct snd_pcm_hw_params *p, snd_pcm_format_t fmt)
365 : : {
366 : : snd_mask_set_format(hw_param_mask(p, SNDRV_PCM_HW_PARAM_FORMAT), fmt);
367 : : }
368 : :
369 : : #endif /* __SOUND_PCM_PARAMS_H */
|