blob: ba184f49f7e18cfcb25863392cad654fe7b99561 [file] [log] [blame]
Thomas Gleixner1a59d1b82019-05-27 08:55:05 +02001/* SPDX-License-Identifier: GPL-2.0-or-later */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002#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>
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 */
9
Mark Brownf3761c32012-06-19 19:31:48 +010010#include <sound/pcm.h>
11
Takashi Iwaie88e8ae62006-04-28 15:13:40 +020012int 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);
15int 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);
18int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params,
19 snd_pcm_hw_param_t var, int *dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -070020
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#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
Takashi Iwai9bb22e22006-04-28 15:13:39 +020026static inline void snd_mask_none(struct snd_mask *mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -070027{
28 memset(mask, 0, sizeof(*mask));
29}
30
Takashi Iwai9bb22e22006-04-28 15:13:39 +020031static inline void snd_mask_any(struct snd_mask *mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -070032{
33 memset(mask, 0xff, SNDRV_MASK_SIZE * sizeof(u_int32_t));
34}
35
Takashi Iwai9bb22e22006-04-28 15:13:39 +020036static inline int snd_mask_empty(const struct snd_mask *mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -070037{
38 int i;
39 for (i = 0; i < SNDRV_MASK_SIZE; i++)
40 if (mask->bits[i])
41 return 0;
42 return 1;
43}
44
Takashi Iwai9bb22e22006-04-28 15:13:39 +020045static inline unsigned int snd_mask_min(const struct snd_mask *mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -070046{
47 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070048 for (i = 0; i < SNDRV_MASK_SIZE; i++) {
49 if (mask->bits[i])
Lars-Peter Clausen599ee322014-12-29 19:41:44 +010050 return __ffs(mask->bits[i]) + (i << 5);
Linus Torvalds1da177e2005-04-16 15:20:36 -070051 }
52 return 0;
53}
54
Takashi Iwai9bb22e22006-04-28 15:13:39 +020055static inline unsigned int snd_mask_max(const struct snd_mask *mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -070056{
57 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070058 for (i = SNDRV_MASK_SIZE - 1; i >= 0; i--) {
59 if (mask->bits[i])
Lars-Peter Clausen757b0372014-12-29 19:41:46 +010060 return __fls(mask->bits[i]) + (i << 5);
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 }
62 return 0;
63}
64
Takashi Iwai9bb22e22006-04-28 15:13:39 +020065static inline void snd_mask_set(struct snd_mask *mask, unsigned int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -070066{
Linus Torvalds1da177e2005-04-16 15:20:36 -070067 mask->bits[MASK_OFS(val)] |= MASK_BIT(val);
68}
69
Takashi Iwai0b628342018-07-25 23:17:17 +020070/* Most of drivers need only this one */
71static inline void snd_mask_set_format(struct snd_mask *mask,
72 snd_pcm_format_t format)
73{
74 snd_mask_set(mask, (__force unsigned int)format);
75}
76
Takashi Iwai9bb22e22006-04-28 15:13:39 +020077static inline void snd_mask_reset(struct snd_mask *mask, unsigned int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -070078{
Linus Torvalds1da177e2005-04-16 15:20:36 -070079 mask->bits[MASK_OFS(val)] &= ~MASK_BIT(val);
80}
81
Takashi Iwai9bb22e22006-04-28 15:13:39 +020082static inline void snd_mask_set_range(struct snd_mask *mask,
83 unsigned int from, unsigned int to)
Linus Torvalds1da177e2005-04-16 15:20:36 -070084{
85 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 for (i = from; i <= to; i++)
87 mask->bits[MASK_OFS(i)] |= MASK_BIT(i);
88}
89
Takashi Iwai9bb22e22006-04-28 15:13:39 +020090static inline void snd_mask_reset_range(struct snd_mask *mask,
91 unsigned int from, unsigned int to)
Linus Torvalds1da177e2005-04-16 15:20:36 -070092{
93 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070094 for (i = from; i <= to; i++)
95 mask->bits[MASK_OFS(i)] &= ~MASK_BIT(i);
96}
97
Takashi Iwai9bb22e22006-04-28 15:13:39 +020098static inline void snd_mask_leave(struct snd_mask *mask, unsigned int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -070099{
100 unsigned int v;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101 v = mask->bits[MASK_OFS(val)] & MASK_BIT(val);
102 snd_mask_none(mask);
103 mask->bits[MASK_OFS(val)] = v;
104}
105
Takashi Iwai9bb22e22006-04-28 15:13:39 +0200106static inline void snd_mask_intersect(struct snd_mask *mask,
107 const struct snd_mask *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108{
109 int i;
110 for (i = 0; i < SNDRV_MASK_SIZE; i++)
111 mask->bits[i] &= v->bits[i];
112}
113
Takashi Iwai9bb22e22006-04-28 15:13:39 +0200114static inline int snd_mask_eq(const struct snd_mask *mask,
115 const struct snd_mask *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116{
117 return ! memcmp(mask, v, SNDRV_MASK_SIZE * sizeof(u_int32_t));
118}
119
Takashi Iwai9bb22e22006-04-28 15:13:39 +0200120static inline void snd_mask_copy(struct snd_mask *mask,
121 const struct snd_mask *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122{
123 *mask = *v;
124}
125
Takashi Iwai9bb22e22006-04-28 15:13:39 +0200126static inline int snd_mask_test(const struct snd_mask *mask, unsigned int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 return mask->bits[MASK_OFS(val)] & MASK_BIT(val);
129}
130
Takashi Iwaib9c7d412020-02-06 17:39:39 +0100131/* Most of drivers need only this one */
132static inline int snd_mask_test_format(const struct snd_mask *mask,
133 snd_pcm_format_t format)
134{
135 return snd_mask_test(mask, (__force unsigned int)format);
136}
137
Takashi Iwai9bb22e22006-04-28 15:13:39 +0200138static inline int snd_mask_single(const struct snd_mask *mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139{
140 int i, c = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 for (i = 0; i < SNDRV_MASK_SIZE; i++) {
142 if (! mask->bits[i])
143 continue;
144 if (mask->bits[i] & (mask->bits[i] - 1))
145 return 0;
146 if (c)
147 return 0;
148 c++;
149 }
150 return 1;
151}
152
Takashi Iwai9bb22e22006-04-28 15:13:39 +0200153static inline int snd_mask_refine(struct snd_mask *mask,
154 const struct snd_mask *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155{
Takashi Iwai877211f2005-11-17 13:59:38 +0100156 struct snd_mask old;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 snd_mask_copy(&old, mask);
158 snd_mask_intersect(mask, v);
159 if (snd_mask_empty(mask))
160 return -EINVAL;
161 return !snd_mask_eq(mask, &old);
162}
163
Takashi Iwai9bb22e22006-04-28 15:13:39 +0200164static inline int snd_mask_refine_first(struct snd_mask *mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 if (snd_mask_single(mask))
167 return 0;
168 snd_mask_leave(mask, snd_mask_min(mask));
169 return 1;
170}
171
Takashi Iwai9bb22e22006-04-28 15:13:39 +0200172static inline int snd_mask_refine_last(struct snd_mask *mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 if (snd_mask_single(mask))
175 return 0;
176 snd_mask_leave(mask, snd_mask_max(mask));
177 return 1;
178}
179
Takashi Iwai9bb22e22006-04-28 15:13:39 +0200180static inline int snd_mask_refine_min(struct snd_mask *mask, unsigned int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 if (snd_mask_min(mask) >= val)
183 return 0;
184 snd_mask_reset_range(mask, 0, val - 1);
185 if (snd_mask_empty(mask))
186 return -EINVAL;
187 return 1;
188}
189
Takashi Iwai9bb22e22006-04-28 15:13:39 +0200190static inline int snd_mask_refine_max(struct snd_mask *mask, unsigned int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 if (snd_mask_max(mask) <= val)
193 return 0;
194 snd_mask_reset_range(mask, val + 1, SNDRV_MASK_BITS);
195 if (snd_mask_empty(mask))
196 return -EINVAL;
197 return 1;
198}
199
Takashi Iwai9bb22e22006-04-28 15:13:39 +0200200static inline int snd_mask_refine_set(struct snd_mask *mask, unsigned int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201{
202 int changed;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 changed = !snd_mask_single(mask);
204 snd_mask_leave(mask, val);
205 if (snd_mask_empty(mask))
206 return -EINVAL;
207 return changed;
208}
209
Takashi Iwai9bb22e22006-04-28 15:13:39 +0200210static inline int snd_mask_value(const struct snd_mask *mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 return snd_mask_min(mask);
213}
214
Takashi Iwai9bb22e22006-04-28 15:13:39 +0200215static inline void snd_interval_any(struct snd_interval *i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216{
217 i->min = 0;
218 i->openmin = 0;
219 i->max = UINT_MAX;
220 i->openmax = 0;
221 i->integer = 0;
222 i->empty = 0;
223}
224
Takashi Iwai9bb22e22006-04-28 15:13:39 +0200225static inline void snd_interval_none(struct snd_interval *i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226{
227 i->empty = 1;
228}
229
Takashi Iwai9bb22e22006-04-28 15:13:39 +0200230static inline int snd_interval_checkempty(const struct snd_interval *i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231{
232 return (i->min > i->max ||
233 (i->min == i->max && (i->openmin || i->openmax)));
234}
235
Takashi Iwai9bb22e22006-04-28 15:13:39 +0200236static inline int snd_interval_empty(const struct snd_interval *i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237{
238 return i->empty;
239}
240
Takashi Iwai9bb22e22006-04-28 15:13:39 +0200241static inline int snd_interval_single(const struct snd_interval *i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 return (i->min == i->max ||
Takashi Iwai53638572018-11-29 12:05:19 +0100244 (i->min + 1 == i->max && (i->openmin || i->openmax)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245}
246
Takashi Iwai9bb22e22006-04-28 15:13:39 +0200247static inline int snd_interval_value(const struct snd_interval *i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248{
Takashi Iwai53638572018-11-29 12:05:19 +0100249 if (i->openmin && !i->openmax)
250 return i->max;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 return i->min;
252}
253
Takashi Iwai9bb22e22006-04-28 15:13:39 +0200254static inline int snd_interval_min(const struct snd_interval *i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 return i->min;
257}
258
Takashi Iwai9bb22e22006-04-28 15:13:39 +0200259static inline int snd_interval_max(const struct snd_interval *i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260{
261 unsigned int v;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 v = i->max;
263 if (i->openmax)
264 v--;
265 return v;
266}
267
Takashi Iwai9bb22e22006-04-28 15:13:39 +0200268static inline int snd_interval_test(const struct snd_interval *i, unsigned int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269{
270 return !((i->min > val || (i->min == val && i->openmin) ||
271 i->max < val || (i->max == val && i->openmax)));
272}
273
Takashi Iwai9bb22e22006-04-28 15:13:39 +0200274static inline void snd_interval_copy(struct snd_interval *d, const struct snd_interval *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275{
276 *d = *s;
277}
278
Takashi Iwai9bb22e22006-04-28 15:13:39 +0200279static inline int snd_interval_setinteger(struct snd_interval *i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280{
281 if (i->integer)
282 return 0;
283 if (i->openmin && i->openmax && i->min == i->max)
284 return -EINVAL;
285 i->integer = 1;
286 return 1;
287}
288
Takashi Iwai9bb22e22006-04-28 15:13:39 +0200289static inline int snd_interval_eq(const struct snd_interval *i1, const struct snd_interval *i2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290{
291 if (i1->empty)
292 return i2->empty;
293 if (i2->empty)
294 return i1->empty;
295 return i1->min == i2->min && i1->openmin == i2->openmin &&
296 i1->max == i2->max && i1->openmax == i2->openmax;
297}
298
Lars-Peter Clausen89827ca2014-12-29 19:41:42 +0100299/**
300 * params_access - get the access type from the hw params
301 * @p: hw params
302 */
Lars-Peter Clausen744c2ad2014-12-29 19:41:41 +0100303static inline snd_pcm_access_t params_access(const struct snd_pcm_hw_params *p)
304{
305 return (__force snd_pcm_access_t)snd_mask_min(hw_param_mask_c(p,
306 SNDRV_PCM_HW_PARAM_ACCESS));
307}
308
Lars-Peter Clausen89827ca2014-12-29 19:41:42 +0100309/**
310 * params_format - get the sample format from the hw params
311 * @p: hw params
312 */
Lars-Peter Clausen744c2ad2014-12-29 19:41:41 +0100313static inline snd_pcm_format_t params_format(const struct snd_pcm_hw_params *p)
314{
315 return (__force snd_pcm_format_t)snd_mask_min(hw_param_mask_c(p,
316 SNDRV_PCM_HW_PARAM_FORMAT));
317}
318
Lars-Peter Clausen89827ca2014-12-29 19:41:42 +0100319/**
320 * params_subformat - get the sample subformat from the hw params
321 * @p: hw params
322 */
Lars-Peter Clausen744c2ad2014-12-29 19:41:41 +0100323static inline snd_pcm_subformat_t
324params_subformat(const struct snd_pcm_hw_params *p)
325{
326 return (__force snd_pcm_subformat_t)snd_mask_min(hw_param_mask_c(p,
327 SNDRV_PCM_HW_PARAM_SUBFORMAT));
328}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329
Lars-Peter Clausen89827ca2014-12-29 19:41:42 +0100330/**
331 * params_period_bytes - get the period size (in bytes) from the hw params
332 * @p: hw params
333 */
Takashi Iwaib51beb72011-07-26 12:02:56 +0200334static inline unsigned int
335params_period_bytes(const struct snd_pcm_hw_params *p)
336{
Lars-Peter Clausencd9978f2014-12-29 19:41:43 +0100337 return hw_param_interval_c(p, SNDRV_PCM_HW_PARAM_PERIOD_BYTES)->min;
Takashi Iwaib51beb72011-07-26 12:02:56 +0200338}
339
Lars-Peter Clausen89827ca2014-12-29 19:41:42 +0100340/**
341 * params_width - get the number of bits of the sample format from the hw params
342 * @p: hw params
343 *
344 * This function returns the number of bits per sample that the selected sample
345 * format of the hw params has.
346 */
347static inline int params_width(const struct snd_pcm_hw_params *p)
Mark Brown8c5178f2013-12-24 12:24:28 +0000348{
349 return snd_pcm_format_width(params_format(p));
350}
351
Lars-Peter Clausen89827ca2014-12-29 19:41:42 +0100352/*
353 * params_physical_width - get the storage size of the sample format from the hw params
354 * @p: hw params
355 *
356 * This functions returns the number of bits per sample that the selected sample
357 * format of the hw params takes up in memory. This will be equal or larger than
358 * params_width().
359 */
360static inline int params_physical_width(const struct snd_pcm_hw_params *p)
Mark Brown8c5178f2013-12-24 12:24:28 +0000361{
362 return snd_pcm_format_physical_width(params_format(p));
363}
364
Fang, Yang A052a9f62015-02-09 00:18:11 -0800365static inline void
366params_set_format(struct snd_pcm_hw_params *p, snd_pcm_format_t fmt)
367{
Takashi Iwai0b628342018-07-25 23:17:17 +0200368 snd_mask_set_format(hw_param_mask(p, SNDRV_PCM_HW_PARAM_FORMAT), fmt);
Fang, Yang A052a9f62015-02-09 00:18:11 -0800369}
370
Takashi Iwaib51beb72011-07-26 12:02:56 +0200371#endif /* __SOUND_PCM_PARAMS_H */