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 : : static inline void snd_mask_none(struct snd_mask *mask) 32 : : { 33 : 0 : memset(mask, 0, sizeof(*mask)); 34 : : } 35 : : 36 : : 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 : : static inline unsigned int snd_mask_min(const struct snd_mask *mask) 51 : : { 52 : : 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 : : 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 : : } 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 : : unsigned int v; 106 : 0 : v = mask->bits[MASK_OFS(val)] & MASK_BIT(val); 107 : : snd_mask_none(mask); 108 : 0 : mask->bits[MASK_OFS(val)] = v; 109 : 0 : } 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 : : 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 : : static inline void snd_mask_copy(struct snd_mask *mask, 126 : : const struct snd_mask *v) 127 : : { 128 : 0 : *mask = *v; 129 : : } 130 : : 131 : : 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 : : static inline int snd_mask_single(const struct snd_mask *mask) 137 : : { 138 : : 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 : 0 : 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 : : struct snd_mask old; 155 : : 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 : 0 : 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 : 0 : 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 : : static inline int snd_mask_value(const struct snd_mask *mask) 209 : : { 210 : 0 : return snd_mask_min(mask); 211 : : } 212 : : 213 : : 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 : : static inline void snd_interval_none(struct snd_interval *i) 224 : : { 225 : 0 : i->empty = 1; 226 : : } 227 : : 228 : : 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 : : static inline int snd_interval_empty(const struct snd_interval *i) 235 : : { 236 : 0 : return i->empty; 237 : : } 238 : : 239 : : 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 : : 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 : : static inline void snd_interval_copy(struct snd_interval *d, const struct snd_interval *s) 273 : : { 274 : 0 : *d = *s; 275 : : } 276 : : 277 : : 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 : : 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 : : 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 : : 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 : : 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 */