1 /*
2 * Copyright (c) 2019-2025 Allwinner Technology Co., Ltd. ALL rights reserved.
3 *
4 * Allwinner is a trademark of Allwinner Technology Co.,Ltd., registered in
5 * the the people's Republic of China and other countries.
6 * All Allwinner Technology Co.,Ltd. trademarks are used with permission.
7 *
8 * DISCLAIMER
9 * THIRD PARTY LICENCES MAY BE REQUIRED TO IMPLEMENT THE SOLUTION/PRODUCT.
10 * IF YOU NEED TO INTEGRATE THIRD PARTY’S TECHNOLOGY (SONY, DTS, DOLBY, AVS OR MPEGLA, ETC.)
11 * IN ALLWINNERS’SDK OR PRODUCTS, YOU SHALL BE SOLELY RESPONSIBLE TO OBTAIN
12 * ALL APPROPRIATELY REQUIRED THIRD PARTY LICENCES.
13 * ALLWINNER SHALL HAVE NO WARRANTY, INDEMNITY OR OTHER OBLIGATIONS WITH RESPECT TO MATTERS
14 * COVERED UNDER ANY REQUIRED THIRD PARTY LICENSE.
15 * YOU ARE SOLELY RESPONSIBLE FOR YOUR USAGE OF THIRD PARTY’S TECHNOLOGY.
16 *
17 *
18 * THIS SOFTWARE IS PROVIDED BY ALLWINNER"AS IS" AND TO THE MAXIMUM EXTENT
19 * PERMITTED BY LAW, ALLWINNER EXPRESSLY DISCLAIMS ALL WARRANTIES OF ANY KIND,
20 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION REGARDING
21 * THE TITLE, NON-INFRINGEMENT, ACCURACY, CONDITION, COMPLETENESS, PERFORMANCE
22 * OR MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23 * IN NO EVENT SHALL ALLWINNER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS, OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30 * OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 #ifndef __SOUND_PCM_COMMON_H
33 #define __SOUND_PCM_COMMON_H
34
35 #include <stdint.h>
36 #include <errno.h>
37
38 #ifndef EBADFD
39 #define EBADFD 77
40 #endif
41 #ifndef ESTRPIPE
42 #define ESTRPIPE 86
43 #endif
44
45 #ifndef LONG_MAX
46 #define LONG_MAX ((long)(~0UL>>1))
47 #endif
48 #ifndef ULONG_MAX
49 #define ULONG_MAX (~0UL)
50 #endif
51 #ifndef UINT_MAX
52 #define UINT_MAX (~0U)
53 #endif
54
55 #define SND_PCM_APPEND (1<<8)
56
57 typedef unsigned long snd_pcm_uframes_t;
58 typedef signed long snd_pcm_sframes_t;
59 typedef union snd_interval snd_interval_t;
60
61 #define SNDRV_PCM_INFO_MMAP 0x00000001 /* hardware supports mmap */
62 #define SNDRV_PCM_INFO_MMAP_VALID 0x00000002 /* period data are valid during transfer */
63 #define SNDRV_PCM_INFO_DOUBLE 0x00000004 /* Double buffering needed for PCM start/stop */
64 #define SNDRV_PCM_INFO_BATCH 0x00000010 /* double buffering */
65 #define SNDRV_PCM_INFO_INTERLEAVED 0x00000100 /* channels are interleaved */
66 #define SNDRV_PCM_INFO_NONINTERLEAVED 0x00000200 /* channels are not interleaved */
67 #define SNDRV_PCM_INFO_COMPLEX 0x00000400 /* complex frame organization (mmap only) */
68 #define SNDRV_PCM_INFO_BLOCK_TRANSFER 0x00010000 /* hardware transfer block of samples */
69 #define SNDRV_PCM_INFO_OVERRANGE 0x00020000 /* hardware supports ADC (capture) overrange detection */
70 #define SNDRV_PCM_INFO_RESUME 0x00040000 /* hardware supports stream resume after suspend */
71 #define SNDRV_PCM_INFO_PAUSE 0x00080000 /* pause ioctl is supported */
72 #define SNDRV_PCM_INFO_HALF_DUPLEX 0x00100000 /* only half duplex */
73 #define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000 /* playback and capture stream are somewhat correlated */
74 #define SNDRV_PCM_INFO_SYNC_START 0x00400000 /* pcm support some kind of sync go */
75 #define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP 0x00800000 /* period wakeup can be disabled */
76 #define SNDRV_PCM_INFO_HAS_WALL_CLOCK 0x01000000 /* (Deprecated)has audio wall clock for audio/system time sync */
77 #define SNDRV_PCM_INFO_HAS_LINK_ATIME 0x01000000 /* report hardware link audio time, reset on startup */
78 #define SNDRV_PCM_INFO_HAS_LINK_ABSOLUTE_ATIME 0x02000000 /* report absolute hardware link audio time, not reset on startup */
79 #define SNDRV_PCM_INFO_HAS_LINK_ESTIMATED_ATIME 0x04000000 /* report estimated link audio time */
80 #define SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME 0x08000000 /* report synchronized audio/system time */
81 #define SNDRV_PCM_INFO_DRAIN_TRIGGER 0x40000000 /* internal kernel flag - trigger in drain */
82 #define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000 /* internal kernel flag - FIFO size is in frames */
83
84 /** PCM access type */
85 typedef enum _snd_pcm_access {
86 /** mmap access with simple interleaved channels */
87 SND_PCM_ACCESS_MMAP_INTERLEAVED = 0,
88 /** mmap access with simple non interleaved channels */
89 SND_PCM_ACCESS_MMAP_NONINTERLEAVED,
90 /** mmap access with complex placement */
91 SND_PCM_ACCESS_MMAP_COMPLEX,
92 /** snd_pcm_readi/snd_pcm_writei access */
93 SND_PCM_ACCESS_RW_INTERLEAVED,
94 /** snd_pcm_readn/snd_pcm_writen access */
95 SND_PCM_ACCESS_RW_NONINTERLEAVED,
96 SND_PCM_ACCESS_LAST = SND_PCM_ACCESS_RW_NONINTERLEAVED
97 } snd_pcm_access_t;
98
99 /** PCM sample format */
100 typedef enum _snd_pcm_format {
101 /** Unknown */
102 SND_PCM_FORMAT_UNKNOWN = -1,
103 /** Signed 8 bit */
104 SND_PCM_FORMAT_S8 = 0,
105 /** Unsigned 8 bit */
106 SND_PCM_FORMAT_U8,
107 /** Signed 16 bit Little Endian */
108 SND_PCM_FORMAT_S16_LE,
109 /** Signed 16 bit Big Endian */
110 SND_PCM_FORMAT_S16_BE,
111 /** Unsigned 16 bit Little Endian */
112 SND_PCM_FORMAT_U16_LE,
113 /** Unsigned 16 bit Big Endian */
114 SND_PCM_FORMAT_U16_BE,
115 /** Signed 24 bit Little Endian using low three bytes in 32-bit word */
116 SND_PCM_FORMAT_S24_LE,
117 /** Signed 24 bit Big Endian using low three bytes in 32-bit word */
118 SND_PCM_FORMAT_S24_BE,
119 /** Unsigned 24 bit Little Endian using low three bytes in 32-bit word */
120 SND_PCM_FORMAT_U24_LE,
121 /** Unsigned 24 bit Big Endian using low three bytes in 32-bit word */
122 SND_PCM_FORMAT_U24_BE,
123 /** Signed 32 bit Little Endian */
124 SND_PCM_FORMAT_S32_LE,
125 /** Signed 32 bit Big Endian */
126 SND_PCM_FORMAT_S32_BE,
127 /** Unsigned 32 bit Little Endian */
128 SND_PCM_FORMAT_U32_LE,
129 /** Unsigned 32 bit Big Endian */
130 SND_PCM_FORMAT_U32_BE,
131
132 /* only support little endian */
133 /** Signed 16 bit CPU endian */
134 SND_PCM_FORMAT_S16 = SND_PCM_FORMAT_S16_LE,
135 /** Unsigned 16 bit CPU endian */
136 SND_PCM_FORMAT_U16 = SND_PCM_FORMAT_U16_LE,
137 /** Signed 24 bit CPU endian */
138 SND_PCM_FORMAT_S24 = SND_PCM_FORMAT_S24_LE,
139 /** Unsigned 24 bit CPU endian */
140 SND_PCM_FORMAT_U24 = SND_PCM_FORMAT_U24_LE,
141 /** Signed 32 bit CPU endian */
142 SND_PCM_FORMAT_S32 = SND_PCM_FORMAT_S32_LE,
143 /** Unsigned 32 bit CPU endian */
144 SND_PCM_FORMAT_U32 = SND_PCM_FORMAT_U32_LE,
145
146 SND_PCM_FORMAT_LAST = SND_PCM_FORMAT_U32_BE,
147 } snd_pcm_format_t;
148
149 /** PCM state */
150 typedef enum _ksnd_pcm_state {
151 /** Open */
152 SNDRV_PCM_STATE_OPEN = 0,
153 /** Setup installed */
154 SNDRV_PCM_STATE_SETUP,
155 /** Ready to start */
156 SNDRV_PCM_STATE_PREPARED,
157 /** Running */
158 SNDRV_PCM_STATE_RUNNING,
159 /** Stopped: underrun (playback) or overrun (capture) detected */
160 SNDRV_PCM_STATE_XRUN,
161 /** Draining: running (playback) or stopped (capture) */
162 SNDRV_PCM_STATE_DRAINING,
163 /** Paused */
164 SNDRV_PCM_STATE_PAUSED,
165 /** Hardware is suspended */
166 SNDRV_PCM_STATE_SUSPENDED,
167 /** Hardware is disconnected */
168 SNDRV_PCM_STATE_DISCONNECTED,
169 SNDRV_PCM_STATE_LAST = SNDRV_PCM_STATE_DISCONNECTED
170 } ksnd_pcm_state_t;
171
172
173 typedef int snd_pcm_hw_param_t;
174 #define SND_PCM_HW_PARAM_ACCESS 0
175 #define SND_PCM_HW_PARAM_FORMAT 1
176 #define SND_PCM_HW_PARAM_FIRST_MASK SND_PCM_HW_PARAM_ACCESS
177 #define SND_PCM_HW_PARAM_LAST_MASK SND_PCM_HW_PARAM_FORMAT
178 #define SND_PCM_HW_PARAM_SAMPLE_BITS 2
179 #define SND_PCM_HW_PARAM_FRAME_BITS 3
180 #define SND_PCM_HW_PARAM_CHANNELS 4
181 #define SND_PCM_HW_PARAM_RATE 5
182 #define SND_PCM_HW_PARAM_PERIOD_TIME 6
183 #define SND_PCM_HW_PARAM_PERIOD_SIZE 7
184 #define SND_PCM_HW_PARAM_PERIOD_BYTES 8
185 #define SND_PCM_HW_PARAM_PERIODS 9
186 #define SND_PCM_HW_PARAM_BUFFER_TIME 10
187 #define SND_PCM_HW_PARAM_BUFFER_SIZE 11
188 #define SND_PCM_HW_PARAM_BUFFER_BYTES 12
189 #define SND_PCM_HW_PARAM_FIRST_RANGE SND_PCM_HW_PARAM_SAMPLE_BITS
190 #define SND_PCM_HW_PARAM_LAST_RANGE SND_PCM_HW_PARAM_BUFFER_BYTES
191 #define SND_PCM_HW_PARAM_FIRST_INTERVAL SND_PCM_HW_PARAM_ACCESS
192 #define SND_PCM_HW_PARAM_LAST_INTERVAL SND_PCM_HW_PARAM_BUFFER_BYTES
193
hw_is_mask(int var)194 static inline int hw_is_mask(int var)
195 {
196 return var >= SND_PCM_HW_PARAM_FIRST_MASK &&
197 var <= SND_PCM_HW_PARAM_LAST_MASK;
198 }
199
hw_is_range(int var)200 static inline int hw_is_range(int var)
201 {
202 return var >= SND_PCM_HW_PARAM_FIRST_RANGE &&
203 var <= SND_PCM_HW_PARAM_LAST_RANGE;
204 }
205
206 union snd_interval {
207 struct {
208 uint32_t min;
209 uint32_t max;
210 int openmin; /* whether the interval is left-open */
211 int openmax; /* whether the interval is right-open */
212 int integer; /* whether the value is integer or not */
213 int empty;
214 } range;
215 uint32_t mask;
216 };
217
218 typedef struct snd_pcm_hw_params {
219 union snd_interval intervals[SND_PCM_HW_PARAM_LAST_INTERVAL -
220 SND_PCM_HW_PARAM_FIRST_INTERVAL + 1];
221 unsigned int can_paused;
222
223 uint32_t rmask; /* W: requested masks */
224 uint32_t cmask; /* R: changed masks */
225 } snd_pcm_hw_params_t;
226
227 typedef struct snd_pcm_sw_params {
228 snd_pcm_uframes_t avail_min; /* min avail frames for wakeup */
229 snd_pcm_uframes_t start_threshold; /* min hw_avail frames for automatic start */
230 snd_pcm_uframes_t stop_threshold; /* min avail frames for automatic stop */
231 snd_pcm_uframes_t silence_size; /* silence block size */
232 snd_pcm_uframes_t boundary; /* pointers wrap point */
233 } snd_pcm_sw_params_t;
234
235
236 typedef long ksnd_pcm_sframes_t;
237 typedef unsigned long ksnd_pcm_uframes_t;
238
239 struct snd_pcm_mmap_status {
240 ksnd_pcm_state_t state;
241 ksnd_pcm_uframes_t hw_ptr;
242 };
243
244 struct snd_pcm_mmap_control {
245 ksnd_pcm_uframes_t appl_ptr;
246 ksnd_pcm_uframes_t avail_min;
247 };
248
249 #define SNDRV_PCM_SYNC_PTR_HWSYNC (1<<0) /* execute hwsync */
250 #define SNDRV_PCM_SYNC_PTR_APPL (1<<1) /* get appl_ptr from driver (r/w op) */
251 #define SNDRV_PCM_SYNC_PTR_AVAIL_MIN (1<<2) /* get avail_min from driver */
252
253 typedef struct _snd_pcm_channel_info {
254 unsigned int channel;
255 void *addr; /* base address of channel samples */
256 unsigned int first; /* offset to first sample in bits */
257 unsigned int step; /* samples distance in bits */
258 enum { SND_PCM_AREA_MMAP, SND_PCM_AREA_LOCAL } type;
259 } snd_pcm_channel_info_t;
260
261
div32(unsigned int a,unsigned int b,unsigned int * r)262 static inline unsigned int div32(unsigned int a, unsigned int b,
263 unsigned int *r)
264 {
265 if (b == 0) {
266 *r = 0;
267 return UINT_MAX;
268 }
269 *r = a % b;
270 return a / b;
271 }
272
div_u64_rem(uint64_t dividend,uint32_t divisor,uint32_t * remainder)273 static inline uint64_t div_u64_rem(uint64_t dividend, uint32_t divisor, uint32_t *remainder)
274 {
275 *remainder = dividend % divisor;
276 return dividend / divisor;
277 }
278
div_down(unsigned int a,unsigned int b)279 static inline unsigned int div_down(unsigned int a, unsigned int b)
280 {
281 if (b == 0)
282 return UINT_MAX;
283 return a / b;
284 }
285
div_up(unsigned int a,unsigned int b)286 static inline unsigned int div_up(unsigned int a, unsigned int b)
287 {
288 unsigned int r;
289 unsigned int q;
290 if (b == 0)
291 return UINT_MAX;
292 q = div32(a, b, &r);
293 if (r)
294 ++q;
295 return q;
296 }
297
mul(unsigned int a,unsigned int b)298 static inline unsigned int mul(unsigned int a, unsigned int b)
299 {
300 if (a == 0)
301 return 0;
302 if (div_down(UINT_MAX, a) < b)
303 return UINT_MAX;
304 return a * b;
305 }
306
add(unsigned int a,unsigned int b)307 static inline unsigned int add(unsigned int a, unsigned int b)
308 {
309 if (a >= UINT_MAX - b)
310 return UINT_MAX;
311 return a + b;
312 }
313
sub(unsigned int a,unsigned int b)314 static inline unsigned int sub(unsigned int a, unsigned int b)
315 {
316 if (a > b)
317 return a - b;
318 return 0;
319 }
320
muldiv32(unsigned int a,unsigned int b,unsigned int c,unsigned int * r)321 static inline unsigned int muldiv32(unsigned int a, unsigned int b,
322 unsigned int c, unsigned int *r)
323 {
324 uint64_t n = (uint64_t)a * (uint64_t)b;
325 uint32_t rem;
326 if (c == 0) {
327 *r = 0;
328 return UINT_MAX;
329 }
330 n = div_u64_rem(n, c, &rem);
331 if (n >= UINT_MAX) {
332 *r = 0;
333 return UINT_MAX;
334 }
335 *r = rem;
336 return n;
337 }
338
__pcm_ffs(uint32_t value)339 static inline int __pcm_ffs(uint32_t value)
340 {
341 uint32_t offset;
342
343 for (offset = 0; offset < sizeof(value)*8; offset++) {
344 if (value & (1<<offset))
345 return offset;
346 }
347 return -1;
348 }
349
__ffs(uint32_t value)350 static inline int __ffs(uint32_t value)
351 {
352 uint32_t offset;
353
354 for (offset = 0; offset < sizeof(value)*8; offset++) {
355 if (value & (1<<offset))
356 return offset;
357 }
358 return -1;
359 }
360
__fls(uint32_t value)361 static inline int __fls(uint32_t value)
362 {
363 uint32_t offset;
364
365 for (offset = sizeof(value)*8; offset > 0; offset--) {
366 if (value & (1<<(offset - 1)))
367 return offset;
368 }
369 return -1;
370 }
371
params_access(const struct snd_pcm_hw_params * p)372 static inline snd_pcm_access_t params_access(const struct snd_pcm_hw_params *p)
373 {
374 const union snd_interval *interval = NULL;
375 interval = &p->intervals[SND_PCM_HW_PARAM_ACCESS -
376 SND_PCM_HW_PARAM_FIRST_INTERVAL];
377
378 if (interval->mask != 0)
379 return (snd_pcm_access_t)__ffs(interval->mask);
380 return (snd_pcm_access_t)-1;
381 }
382
params_format(const struct snd_pcm_hw_params * p)383 static inline snd_pcm_format_t params_format(const struct snd_pcm_hw_params *p)
384 {
385 const union snd_interval *interval = NULL;
386 interval = &p->intervals[SND_PCM_HW_PARAM_FORMAT -
387 SND_PCM_HW_PARAM_FIRST_INTERVAL];
388
389 if (interval->mask != 0)
390 return (snd_pcm_format_t)__ffs(interval->mask);
391 return SND_PCM_FORMAT_UNKNOWN;
392 }
393
hw_param_interval(struct snd_pcm_hw_params * params,snd_pcm_hw_param_t var)394 static inline snd_interval_t *hw_param_interval(struct snd_pcm_hw_params *params,
395 snd_pcm_hw_param_t var)
396 {
397 return ¶ms->intervals[var];
398 }
399
hw_param_interval_c(const struct snd_pcm_hw_params * params,int var)400 static inline const union snd_interval *hw_param_interval_c(const struct snd_pcm_hw_params *params,
401 int var)
402 {
403 return ¶ms->intervals[var - SND_PCM_HW_PARAM_FIRST_INTERVAL];
404 }
405
params_channels(const struct snd_pcm_hw_params * p)406 static inline unsigned int params_channels(const struct snd_pcm_hw_params *p)
407 {
408 return hw_param_interval_c(p, SND_PCM_HW_PARAM_CHANNELS)->range.min;
409 }
410
params_rate(const struct snd_pcm_hw_params * p)411 static inline unsigned int params_rate(const struct snd_pcm_hw_params *p)
412 {
413 return hw_param_interval_c(p, SND_PCM_HW_PARAM_RATE)->range.min;
414 }
415
params_period_size(const struct snd_pcm_hw_params * p)416 static inline unsigned int params_period_size(const struct snd_pcm_hw_params *p)
417 {
418 return hw_param_interval_c(p, SND_PCM_HW_PARAM_PERIOD_SIZE)->range.min;
419 }
420
params_period_time(const struct snd_pcm_hw_params * p)421 static inline unsigned int params_period_time(const struct snd_pcm_hw_params *p)
422 {
423 return hw_param_interval_c(p, SND_PCM_HW_PARAM_PERIOD_TIME)->range.min;
424 }
425
params_periods(const struct snd_pcm_hw_params * p)426 static inline unsigned int params_periods(const struct snd_pcm_hw_params *p)
427 {
428 return hw_param_interval_c(p, SND_PCM_HW_PARAM_PERIODS)->range.min;
429 }
430
params_buffer_size(const struct snd_pcm_hw_params * p)431 static inline unsigned int params_buffer_size(const struct snd_pcm_hw_params *p)
432 {
433 return hw_param_interval_c(p, SND_PCM_HW_PARAM_BUFFER_SIZE)->range.min;
434 }
435
params_buffer_time(const struct snd_pcm_hw_params * p)436 static inline unsigned int params_buffer_time(const struct snd_pcm_hw_params *p)
437 {
438 return hw_param_interval_c(p, SND_PCM_HW_PARAM_BUFFER_TIME)->range.min;
439 }
440
441
442 int snd_pcm_format_physical_width(snd_pcm_format_t format);
443
444
445 #define SND_MASK_BITS 32
446
snd_mask_none(snd_interval_t * interval)447 static inline void snd_mask_none(snd_interval_t *interval)
448 {
449 interval->mask = 0U;
450 }
451
snd_mask_any(snd_interval_t * interval)452 static inline void snd_mask_any(snd_interval_t *interval)
453 {
454 interval->mask = ~0U;
455 }
456
snd_mask_empty(const snd_interval_t * interval)457 static inline int snd_mask_empty(const snd_interval_t *interval)
458 {
459 return !interval->mask;
460 }
461
snd_mask_full(const snd_interval_t * interval)462 static inline int snd_mask_full(const snd_interval_t *interval)
463 {
464 return interval->mask == 0xffffffff;
465 }
466
snd_mask_min(const snd_interval_t * interval)467 static inline unsigned int snd_mask_min(const snd_interval_t *interval)
468 {
469 unsigned int i;
470 for (i = 0; i < sizeof(interval->mask) * 8; i++) {
471 if (interval->mask & (1 << i))
472 return i;
473 }
474 return 0;
475 }
476
snd_mask_max(const snd_interval_t * interval)477 static inline unsigned int snd_mask_max(const snd_interval_t *interval)
478 {
479 unsigned int i;
480 for (i = sizeof(interval->mask) * 8; i > 0; i--) {
481 if (interval->mask & (1 << (i - 1)))
482 return i - 1;
483 }
484 return 0;
485 }
486
snd_mask_set(snd_interval_t * interval,unsigned int val)487 static inline void snd_mask_set(snd_interval_t *interval, unsigned int val)
488 {
489 interval->mask |= (1 << val);
490 }
491
snd_mask_reset(snd_interval_t * interval,unsigned int val)492 static inline void snd_mask_reset(snd_interval_t *interval, unsigned int val)
493 {
494 interval->mask &= ~(1 << val);
495 }
496
snd_mask_set_range(snd_interval_t * interval,unsigned int from,unsigned int to)497 static inline void snd_mask_set_range(snd_interval_t *interval,
498 unsigned int from, unsigned int to)
499 {
500 unsigned int i;
501 for (i = from; i <= to; i++)
502 interval->mask |= (1 << i);
503 }
504
snd_mask_reset_range(snd_interval_t * interval,unsigned int from,unsigned int to)505 static inline void snd_mask_reset_range(snd_interval_t *interval,
506 unsigned int from, unsigned int to)
507 {
508 unsigned int i;
509 for (i = from; i <= to; i++)
510 interval->mask &= ~(1 << i);
511 }
512
snd_mask_leave(snd_interval_t * interval,unsigned int val)513 static inline void snd_mask_leave(snd_interval_t *interval, unsigned int val)
514 {
515 snd_mask_none(interval);
516 interval->mask |= (1 << val);
517 }
518
snd_mask_intersect(snd_interval_t * interval,const snd_interval_t * v)519 static inline void snd_mask_intersect(snd_interval_t *interval, const snd_interval_t *v)
520 {
521 interval->mask &= v->mask;
522 }
523
snd_mask_eq(snd_interval_t * interval,const snd_interval_t * v)524 static inline int snd_mask_eq(snd_interval_t *interval, const snd_interval_t *v)
525 {
526 return interval->mask == v->mask;
527 }
528
snd_mask_copy(snd_interval_t * interval,const snd_interval_t * v)529 static inline void snd_mask_copy(snd_interval_t *interval, const snd_interval_t *v)
530 {
531 interval->mask = v->mask;
532 }
533
snd_mask_test(const snd_interval_t * interval,unsigned int val)534 static inline int snd_mask_test(const snd_interval_t *interval, unsigned int val)
535 {
536 return interval->mask & (1 << val);
537 }
538
snd_mask_single(const snd_interval_t * interval)539 static inline int snd_mask_single(const snd_interval_t *interval)
540 {
541 unsigned int bits = sizeof(interval->mask) * 8;
542 unsigned int i;
543 int c = 0;
544 for (i = 0; i < bits; ++i) {
545 if (!(interval->mask & (1 << i)))
546 continue;
547 if (c)
548 return 0;
549 c++;
550 }
551 return 1;
552 }
553
snd_mask_refine(snd_interval_t * interval,const snd_interval_t * v)554 static inline int snd_mask_refine(snd_interval_t *interval, const snd_interval_t *v)
555 {
556 snd_interval_t old;
557 snd_mask_copy(&old, interval);
558 snd_mask_intersect(interval, v);
559 if (snd_mask_empty(interval))
560 return -EINVAL;
561 return !snd_mask_eq(interval, &old);
562 }
563
snd_mask_refine_first(snd_interval_t * interval)564 static inline int snd_mask_refine_first(snd_interval_t *interval)
565 {
566 if (snd_mask_single(interval))
567 return 0;
568 snd_mask_leave(interval, snd_mask_min(interval));
569 return 1;
570 }
571
snd_mask_refine_last(snd_interval_t * interval)572 static inline int snd_mask_refine_last(snd_interval_t *interval)
573 {
574 if (snd_mask_single(interval))
575 return 0;
576 snd_mask_leave(interval, snd_mask_max(interval));
577 return 1;
578 }
579
snd_mask_refine_min(snd_interval_t * interval,unsigned int val)580 static inline int snd_mask_refine_min(snd_interval_t *interval, unsigned int val)
581 {
582 if (snd_mask_min(interval) >= val)
583 return 0;
584 snd_mask_reset_range(interval, 0, val - 1);
585 if (snd_mask_empty(interval))
586 return -EINVAL;
587 return 1;
588 }
589
snd_mask_refine_max(snd_interval_t * interval,unsigned int val)590 static inline int snd_mask_refine_max(snd_interval_t *interval, unsigned int val)
591 {
592 if (snd_mask_max(interval) <= val)
593 return 0;
594 snd_mask_reset_range(interval, val + 1, SND_MASK_BITS);
595 if (snd_mask_empty(interval))
596 return -EINVAL;
597 return 1;
598 }
599
snd_mask_refine_set(snd_interval_t * interval,unsigned int val)600 static inline int snd_mask_refine_set(snd_interval_t *interval, unsigned int val)
601 {
602 int changed;
603 changed = !snd_mask_single(interval);
604 snd_mask_leave(interval, val);
605 if (snd_mask_empty(interval))
606 return -EINVAL;
607 return changed;
608 }
609
snd_mask_value(const snd_interval_t * interval)610 static inline int snd_mask_value(const snd_interval_t *interval)
611 {
612 return snd_mask_min(interval);
613 }
614
snd_mask_always_eq(const snd_interval_t * m1,const snd_interval_t * m2)615 static inline int snd_mask_always_eq(const snd_interval_t *m1, const snd_interval_t *m2)
616 {
617 return snd_mask_single(m1) && snd_mask_single(m2) &&
618 snd_mask_value(m1) == snd_mask_value(m2);
619 }
620
snd_mask_never_eq(const snd_interval_t * m1,const snd_interval_t * m2)621 static inline int snd_mask_never_eq(const snd_interval_t *m1, const snd_interval_t *m2)
622 {
623 if (m1->mask & m2->mask)
624 return 0;
625 return 1;
626 }
627
snd_range_any(snd_interval_t * i)628 static inline void snd_range_any(snd_interval_t *i)
629 {
630 i->range.min = 0;
631 i->range.openmin = 0;
632 i->range.max = UINT_MAX;
633 i->range.openmax= 0;
634 i->range.integer = 0;
635 i->range.empty = 0;
636 }
637
snd_range_none(snd_interval_t * i)638 static inline void snd_range_none(snd_interval_t *i)
639 {
640 i->range.empty = 1;
641 }
642
snd_range_checkempty(snd_interval_t * i)643 static inline int snd_range_checkempty(snd_interval_t *i)
644 {
645 return (i->range.min > i->range.max ||
646 (i->range.min == i->range.max && (i->range.openmin || i->range.openmax)));
647 }
648
snd_range_empty(const snd_interval_t * i)649 static inline int snd_range_empty(const snd_interval_t *i)
650 {
651 return i->range.empty;
652 }
653
snd_range_single(const snd_interval_t * i)654 static inline int snd_range_single(const snd_interval_t *i)
655 {
656 return (i->range.min == i->range.max ||
657 (i->range.min + 1 == i->range.max && i->range.openmax));
658 }
659
snd_range_value(const snd_interval_t * i)660 static inline int snd_range_value(const snd_interval_t *i)
661 {
662 return i->range.min;
663 }
664
snd_range_set_value(snd_interval_t * i,unsigned int val)665 static inline void snd_range_set_value(snd_interval_t *i, unsigned int val)
666 {
667 i->range.openmax = i->range.openmin = 0;
668 i->range.min = i->range.max = val;
669 i->range.integer = 0;
670 i->range.empty = 0;
671 }
672
snd_range_min(const snd_interval_t * i)673 static inline int snd_range_min(const snd_interval_t *i)
674 {
675 return i->range.min;
676 }
677
snd_range_max(const snd_interval_t * i)678 static inline int snd_range_max(const snd_interval_t *i)
679 {
680 unsigned int v;
681 v = i->range.max;
682 if (i->range.openmax)
683 v--;
684 return v;
685 }
686
snd_range_set_minmax(snd_interval_t * i,unsigned int min,unsigned int max)687 static inline void snd_range_set_minmax(snd_interval_t *i, unsigned int min, unsigned int max)
688 {
689 i->range.openmax = i->range.openmin = 0;
690 i->range.min = min;
691 i->range.max = max;
692 i->range.integer = 0;
693 i->range.empty = 0;
694 }
695
snd_range_test(const snd_interval_t * i,unsigned int val)696 static inline int snd_range_test(const snd_interval_t *i, unsigned int val)
697 {
698 return !((i->range.min > val || (i->range.min == val && i->range.openmin) ||
699 i->range.max < val || (i->range.max == val && i->range.openmax)));
700 }
701
snd_range_copy(snd_interval_t * d,const snd_interval_t * s)702 static inline void snd_range_copy(snd_interval_t *d, const snd_interval_t *s)
703 {
704 d->range = s->range;
705 }
706
snd_range_setinteger(snd_interval_t * i)707 static inline int snd_range_setinteger(snd_interval_t *i)
708 {
709 if (i->range.integer)
710 return 0;
711 if (i->range.openmin && i->range.openmax && i->range.min == i->range.max)
712 return -EINVAL;
713 i->range.integer = 1;
714 return 1;
715 }
716
snd_range_floor(snd_interval_t * i)717 static inline void snd_range_floor(snd_interval_t *i)
718 {
719 if (i->range.integer || snd_range_empty(i))
720 return;
721 i->range.openmin = 0;
722 if (i->range.openmax) {
723 i->range.max--;
724 i->range.openmax = 0;
725 }
726 i->range.integer = 1;
727 }
728
snd_range_unfloor(snd_interval_t * i)729 static inline void snd_range_unfloor(snd_interval_t *i)
730 {
731 if (snd_range_empty(i))
732 return;
733 if (i->range.max == UINT_MAX)
734 return;
735 if (i->range.openmax)
736 return;
737 i->range.max++;
738 i->range.openmax = 1;
739 i->range.integer = 0;
740 }
741
snd_range_eq(const snd_interval_t * i1,const snd_interval_t * i2)742 static inline int snd_range_eq(const snd_interval_t *i1, const snd_interval_t *i2)
743 {
744 if (i1->range.empty)
745 return i2->range.empty;
746 if (i2->range.empty)
747 return i1->range.empty;
748 return i1->range.min == i2->range.min &&
749 i1->range.openmin == i2->range.openmin &&
750 i1->range.max == i2->range.max &&
751 i1->range.openmax == i2->range.openmax;
752 }
753
snd_range_always_eq(const snd_interval_t * i1,const snd_interval_t * i2)754 static inline int snd_range_always_eq(const snd_interval_t *i1, const snd_interval_t *i2)
755 {
756 return snd_range_single(i1) && snd_range_single(i2) &&
757 snd_range_value(i1) == snd_range_value(i2);
758 }
759
snd_range_never_eq(const snd_interval_t * i1,const snd_interval_t * i2)760 static inline int snd_range_never_eq(const snd_interval_t *i1, const snd_interval_t *i2)
761 {
762
763 return (i1->range.max < i2->range.min ||
764 (i1->range.max == i2->range.min &&
765 (i1->range.openmax || i1->range.openmin)) ||
766 i1->range.min > i2->range.max ||
767 (i1->range.min == i2->range.max &&
768 (i1->range.openmin || i2->range.openmax)));
769 }
770
771 int snd_range_refine(snd_interval_t *i, const snd_interval_t *v);
772 int snd_range_refine_first(snd_interval_t *i);
773 int snd_range_refine_last(snd_interval_t *i);
774 int snd_range_refine_min(snd_interval_t *i, unsigned int min, int openmin);
775 int snd_range_refine_max(snd_interval_t *i, unsigned int max, int openmax);
776 int snd_range_refine_set(snd_interval_t *i, unsigned int val);
777 void snd_range_add(const snd_interval_t *a, const snd_interval_t *b, snd_interval_t *c);
778 void snd_range_sub(const snd_interval_t *a, const snd_interval_t *b, snd_interval_t *c);
779 void snd_range_mul(const snd_interval_t *a, const snd_interval_t *b, snd_interval_t *c);
780 void snd_range_div(const snd_interval_t *a, const snd_interval_t *b, snd_interval_t *c);
781 void snd_range_muldiv(const snd_interval_t *a, const snd_interval_t *b,
782 const snd_interval_t *c, snd_interval_t *d);
783 void snd_range_muldivk(const snd_interval_t *a, const snd_interval_t *b,
784 unsigned int k, snd_interval_t *c);
785 void snd_range_mulkdiv(const snd_interval_t *a, unsigned int k,
786 const snd_interval_t *b, snd_interval_t *c);
787 int snd_range_list(snd_interval_t *i, unsigned int count,
788 const unsigned int *list, unsigned int mask);
789
790 const char *snd_pcm_hw_param_name(snd_pcm_hw_param_t param);
791
792 struct snd_pcm_hw_rule;
793 typedef int (*snd_pcm_hw_rule_func_t)(struct snd_pcm_hw_params *params,
794 struct snd_pcm_hw_rule *rule);
795
796 struct snd_pcm_hw_rule {
797 unsigned int cond;
798 int var;
799 int deps[4];
800 snd_pcm_hw_rule_func_t func;
801 void *private_data;
802 };
803
804 int snd_pcm_hw_rule_mul(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule);
805 int snd_pcm_hw_rule_div(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule);
806 int snd_pcm_hw_rule_muldivk(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule);
807 int snd_pcm_hw_rule_mulkdiv(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule);
808 int snd_pcm_hw_rule_format(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule);
809 int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule);
810 int snd_pcm_hw_rule_rate(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule);
811 int snd_pcm_hw_rule_buffer_bytes_max(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule);
812
813 #endif /* __SOUND_PCM_COMMON_H */
814