linux/include/sound/pcm_params.h
<<
>>
Prefs
   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
  12int 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);
  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
  26static inline void snd_mask_none(struct snd_mask *mask)
  27{
  28        memset(mask, 0, sizeof(*mask));
  29}
  30
  31static inline void snd_mask_any(struct snd_mask *mask)
  32{
  33        memset(mask, 0xff, SNDRV_MASK_SIZE * sizeof(u_int32_t));
  34}
  35
  36static inline int snd_mask_empty(const struct snd_mask *mask)
  37{
  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
  45static inline unsigned int snd_mask_min(const struct snd_mask *mask)
  46{
  47        int i;
  48        for (i = 0; i < SNDRV_MASK_SIZE; i++) {
  49                if (mask->bits[i])
  50                        return __ffs(mask->bits[i]) + (i << 5);
  51        }
  52        return 0;
  53}
  54
  55static inline unsigned int snd_mask_max(const struct snd_mask *mask)
  56{
  57        int i;
  58        for (i = SNDRV_MASK_SIZE - 1; i >= 0; i--) {
  59                if (mask->bits[i])
  60                        return __fls(mask->bits[i]) + (i << 5);
  61        }
  62        return 0;
  63}
  64
  65static inline void snd_mask_set(struct snd_mask *mask, unsigned int val)
  66{
  67        mask->bits[MASK_OFS(val)] |= MASK_BIT(val);
  68}
  69
  70/* 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
  77static inline void snd_mask_reset(struct snd_mask *mask, unsigned int val)
  78{
  79        mask->bits[MASK_OFS(val)] &= ~MASK_BIT(val);
  80}
  81
  82static inline void snd_mask_set_range(struct snd_mask *mask,
  83                                      unsigned int from, unsigned int to)
  84{
  85        unsigned int i;
  86        for (i = from; i <= to; i++)
  87                mask->bits[MASK_OFS(i)] |= MASK_BIT(i);
  88}
  89
  90static inline void snd_mask_reset_range(struct snd_mask *mask,
  91                                        unsigned int from, unsigned int to)
  92{
  93        unsigned int i;
  94        for (i = from; i <= to; i++)
  95                mask->bits[MASK_OFS(i)] &= ~MASK_BIT(i);
  96}
  97
  98static inline void snd_mask_leave(struct snd_mask *mask, unsigned int val)
  99{
 100        unsigned int v;
 101        v = mask->bits[MASK_OFS(val)] & MASK_BIT(val);
 102        snd_mask_none(mask);
 103        mask->bits[MASK_OFS(val)] = v;
 104}
 105
 106static inline void snd_mask_intersect(struct snd_mask *mask,
 107                                      const struct snd_mask *v)
 108{
 109        int i;
 110        for (i = 0; i < SNDRV_MASK_SIZE; i++)
 111                mask->bits[i] &= v->bits[i];
 112}
 113
 114static inline int snd_mask_eq(const struct snd_mask *mask,
 115                              const struct snd_mask *v)
 116{
 117        return ! memcmp(mask, v, SNDRV_MASK_SIZE * sizeof(u_int32_t));
 118}
 119
 120static inline void snd_mask_copy(struct snd_mask *mask,
 121                                 const struct snd_mask *v)
 122{
 123        *mask = *v;
 124}
 125
 126static inline int snd_mask_test(const struct snd_mask *mask, unsigned int val)
 127{
 128        return mask->bits[MASK_OFS(val)] & MASK_BIT(val);
 129}
 130
 131/* 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
 138static inline int snd_mask_single(const struct snd_mask *mask)
 139{
 140        int i, c = 0;
 141        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
 153static inline int snd_mask_refine(struct snd_mask *mask,
 154                                  const struct snd_mask *v)
 155{
 156        struct snd_mask old;
 157        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
 164static inline int snd_mask_refine_first(struct snd_mask *mask)
 165{
 166        if (snd_mask_single(mask))
 167                return 0;
 168        snd_mask_leave(mask, snd_mask_min(mask));
 169        return 1;
 170}
 171
 172static inline int snd_mask_refine_last(struct snd_mask *mask)
 173{
 174        if (snd_mask_single(mask))
 175                return 0;
 176        snd_mask_leave(mask, snd_mask_max(mask));
 177        return 1;
 178}
 179
 180static inline int snd_mask_refine_min(struct snd_mask *mask, unsigned int val)
 181{
 182        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
 190static inline int snd_mask_refine_max(struct snd_mask *mask, unsigned int val)
 191{
 192        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
 200static inline int snd_mask_refine_set(struct snd_mask *mask, unsigned int val)
 201{
 202        int changed;
 203        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
 210static inline int snd_mask_value(const struct snd_mask *mask)
 211{
 212        return snd_mask_min(mask);
 213}
 214
 215static inline void snd_interval_any(struct snd_interval *i)
 216{
 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
 225static inline void snd_interval_none(struct snd_interval *i)
 226{
 227        i->empty = 1;
 228}
 229
 230static inline int snd_interval_checkempty(const struct snd_interval *i)
 231{
 232        return (i->min > i->max ||
 233                (i->min == i->max && (i->openmin || i->openmax)));
 234}
 235
 236static inline int snd_interval_empty(const struct snd_interval *i)
 237{
 238        return i->empty;
 239}
 240
 241static inline int snd_interval_single(const struct snd_interval *i)
 242{
 243        return (i->min == i->max || 
 244                (i->min + 1 == i->max && (i->openmin || i->openmax)));
 245}
 246
 247static inline int snd_interval_value(const struct snd_interval *i)
 248{
 249        if (i->openmin && !i->openmax)
 250                return i->max;
 251        return i->min;
 252}
 253
 254static inline int snd_interval_min(const struct snd_interval *i)
 255{
 256        return i->min;
 257}
 258
 259static inline int snd_interval_max(const struct snd_interval *i)
 260{
 261        unsigned int v;
 262        v = i->max;
 263        if (i->openmax)
 264                v--;
 265        return v;
 266}
 267
 268static inline int snd_interval_test(const struct snd_interval *i, unsigned int val)
 269{
 270        return !((i->min > val || (i->min == val && i->openmin) ||
 271                  i->max < val || (i->max == val && i->openmax)));
 272}
 273
 274static inline void snd_interval_copy(struct snd_interval *d, const struct snd_interval *s)
 275{
 276        *d = *s;
 277}
 278
 279static inline int snd_interval_setinteger(struct snd_interval *i)
 280{
 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
 289static inline int snd_interval_eq(const struct snd_interval *i1, const struct snd_interval *i2)
 290{
 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
 299/**
 300 * params_access - get the access type from the hw params
 301 * @p: hw params
 302 */
 303static 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
 309/**
 310 * params_format - get the sample format from the hw params
 311 * @p: hw params
 312 */
 313static 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
 319/**
 320 * params_subformat - get the sample subformat from the hw params
 321 * @p: hw params
 322 */
 323static 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}
 329
 330/**
 331 * params_period_bytes - get the period size (in bytes) from the hw params
 332 * @p: hw params
 333 */
 334static inline unsigned int
 335params_period_bytes(const struct snd_pcm_hw_params *p)
 336{
 337        return hw_param_interval_c(p, SNDRV_PCM_HW_PARAM_PERIOD_BYTES)->min;
 338}
 339
 340/**
 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)
 348{
 349        return snd_pcm_format_width(params_format(p));
 350}
 351
 352/*
 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)
 361{
 362        return snd_pcm_format_physical_width(params_format(p));
 363}
 364
 365static inline void
 366params_set_format(struct snd_pcm_hw_params *p, snd_pcm_format_t fmt)
 367{
 368        snd_mask_set_format(hw_param_mask(p, SNDRV_PCM_HW_PARAM_FORMAT), fmt);
 369}
 370
 371#endif /* __SOUND_PCM_PARAMS_H */
 372