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 &params->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 &params->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