pcm_params.h 8.3 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
#ifndef __SOUND_PCM_PARAMS_H
#define __SOUND_PCM_PARAMS_H

/*
 *  PCM params helpers
 *  Copyright (c) by Abramo Bagnara <abramo@alsa-project.org>
 *
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 */

extern int snd_pcm_hw_param_mask(snd_pcm_substream_t *pcm, snd_pcm_hw_params_t *params,
				 snd_pcm_hw_param_t var, const snd_mask_t *val);
extern unsigned int snd_pcm_hw_param_value_min(const snd_pcm_hw_params_t *params,
					       snd_pcm_hw_param_t var, int *dir);
extern unsigned int snd_pcm_hw_param_value_max(const snd_pcm_hw_params_t *params,
					       snd_pcm_hw_param_t var, int *dir);
extern int _snd_pcm_hw_param_min(snd_pcm_hw_params_t *params,
				 snd_pcm_hw_param_t var, unsigned int val, int dir);
extern int _snd_pcm_hw_param_setinteger(snd_pcm_hw_params_t *params,
					snd_pcm_hw_param_t var);
extern int _snd_pcm_hw_param_set(snd_pcm_hw_params_t *params,
				 snd_pcm_hw_param_t var, unsigned int val, int dir);

/* To share the same code we have  alsa-lib */
#define INLINE static inline
#define assert(a) (void)(a)

#define SNDRV_MASK_BITS	64	/* we use so far 64bits only */
#define SNDRV_MASK_SIZE	(SNDRV_MASK_BITS / 32)
#define MASK_OFS(i)	((i) >> 5)
#define MASK_BIT(i)	(1U << ((i) & 31))

INLINE unsigned int ld2(u_int32_t v)
{
        unsigned r = 0;

        if (v >= 0x10000) {
                v >>= 16;
                r += 16;
        }
        if (v >= 0x100) {
                v >>= 8;
                r += 8;
        }
        if (v >= 0x10) {
                v >>= 4;
                r += 4;
        }
        if (v >= 4) {
                v >>= 2;
                r += 2;
        }
        if (v >= 2)
                r++;
        return r;
}

INLINE size_t snd_mask_sizeof(void)
{
	return sizeof(snd_mask_t);
}

INLINE void snd_mask_none(snd_mask_t *mask)
{
	memset(mask, 0, sizeof(*mask));
}

INLINE void snd_mask_any(snd_mask_t *mask)
{
	memset(mask, 0xff, SNDRV_MASK_SIZE * sizeof(u_int32_t));
}

INLINE int snd_mask_empty(const snd_mask_t *mask)
{
	int i;
	for (i = 0; i < SNDRV_MASK_SIZE; i++)
		if (mask->bits[i])
			return 0;
	return 1;
}

INLINE unsigned int snd_mask_min(const snd_mask_t *mask)
{
	int i;
	assert(!snd_mask_empty(mask));
	for (i = 0; i < SNDRV_MASK_SIZE; i++) {
		if (mask->bits[i])
			return ffs(mask->bits[i]) - 1 + (i << 5);
	}
	return 0;
}

INLINE unsigned int snd_mask_max(const snd_mask_t *mask)
{
	int i;
	assert(!snd_mask_empty(mask));
	for (i = SNDRV_MASK_SIZE - 1; i >= 0; i--) {
		if (mask->bits[i])
			return ld2(mask->bits[i]) + (i << 5);
	}
	return 0;
}

INLINE void snd_mask_set(snd_mask_t *mask, unsigned int val)
{
	assert(val <= SNDRV_MASK_BITS);
	mask->bits[MASK_OFS(val)] |= MASK_BIT(val);
}

INLINE void snd_mask_reset(snd_mask_t *mask, unsigned int val)
{
	assert(val <= SNDRV_MASK_BITS);
	mask->bits[MASK_OFS(val)] &= ~MASK_BIT(val);
}

INLINE void snd_mask_set_range(snd_mask_t *mask, unsigned int from, unsigned int to)
{
	unsigned int i;
	assert(to <= SNDRV_MASK_BITS && from <= to);
	for (i = from; i <= to; i++)
		mask->bits[MASK_OFS(i)] |= MASK_BIT(i);
}

INLINE void snd_mask_reset_range(snd_mask_t *mask, unsigned int from, unsigned int to)
{
	unsigned int i;
	assert(to <= SNDRV_MASK_BITS && from <= to);
	for (i = from; i <= to; i++)
		mask->bits[MASK_OFS(i)] &= ~MASK_BIT(i);
}

INLINE void snd_mask_leave(snd_mask_t *mask, unsigned int val)
{
	unsigned int v;
	assert(val <= SNDRV_MASK_BITS);
	v = mask->bits[MASK_OFS(val)] & MASK_BIT(val);
	snd_mask_none(mask);
	mask->bits[MASK_OFS(val)] = v;
}

INLINE void snd_mask_intersect(snd_mask_t *mask, const snd_mask_t *v)
{
	int i;
	for (i = 0; i < SNDRV_MASK_SIZE; i++)
		mask->bits[i] &= v->bits[i];
}

INLINE int snd_mask_eq(const snd_mask_t *mask, const snd_mask_t *v)
{
	return ! memcmp(mask, v, SNDRV_MASK_SIZE * sizeof(u_int32_t));
}

INLINE void snd_mask_copy(snd_mask_t *mask, const snd_mask_t *v)
{
	*mask = *v;
}

INLINE int snd_mask_test(const snd_mask_t *mask, unsigned int val)
{
	assert(val <= SNDRV_MASK_BITS);
	return mask->bits[MASK_OFS(val)] & MASK_BIT(val);
}

INLINE int snd_mask_single(const snd_mask_t *mask)
{
	int i, c = 0;
	assert(!snd_mask_empty(mask));
	for (i = 0; i < SNDRV_MASK_SIZE; i++) {
		if (! mask->bits[i])
			continue;
		if (mask->bits[i] & (mask->bits[i] - 1))
			return 0;
		if (c)
			return 0;
		c++;
	}
	return 1;
}

INLINE int snd_mask_refine(snd_mask_t *mask, const snd_mask_t *v)
{
	snd_mask_t old;
	assert(!snd_mask_empty(mask));
	snd_mask_copy(&old, mask);
	snd_mask_intersect(mask, v);
	if (snd_mask_empty(mask))
		return -EINVAL;
	return !snd_mask_eq(mask, &old);
}

INLINE int snd_mask_refine_first(snd_mask_t *mask)
{
	assert(!snd_mask_empty(mask));
	if (snd_mask_single(mask))
		return 0;
	snd_mask_leave(mask, snd_mask_min(mask));
	return 1;
}

INLINE int snd_mask_refine_last(snd_mask_t *mask)
{
	assert(!snd_mask_empty(mask));
	if (snd_mask_single(mask))
		return 0;
	snd_mask_leave(mask, snd_mask_max(mask));
	return 1;
}

INLINE int snd_mask_refine_min(snd_mask_t *mask, unsigned int val)
{
	assert(!snd_mask_empty(mask));
	if (snd_mask_min(mask) >= val)
		return 0;
	snd_mask_reset_range(mask, 0, val - 1);
	if (snd_mask_empty(mask))
		return -EINVAL;
	return 1;
}

INLINE int snd_mask_refine_max(snd_mask_t *mask, unsigned int val)
{
	assert(!snd_mask_empty(mask));
	if (snd_mask_max(mask) <= val)
		return 0;
	snd_mask_reset_range(mask, val + 1, SNDRV_MASK_BITS);
	if (snd_mask_empty(mask))
		return -EINVAL;
	return 1;
}

INLINE int snd_mask_refine_set(snd_mask_t *mask, unsigned int val)
{
	int changed;
	assert(!snd_mask_empty(mask));
	changed = !snd_mask_single(mask);
	snd_mask_leave(mask, val);
	if (snd_mask_empty(mask))
		return -EINVAL;
	return changed;
}

INLINE int snd_mask_value(const snd_mask_t *mask)
{
	assert(!snd_mask_empty(mask));
	return snd_mask_min(mask);
}

INLINE void snd_interval_any(snd_interval_t *i)
{
	i->min = 0;
	i->openmin = 0;
	i->max = UINT_MAX;
	i->openmax = 0;
	i->integer = 0;
	i->empty = 0;
}

INLINE void snd_interval_none(snd_interval_t *i)
{
	i->empty = 1;
}

INLINE int snd_interval_checkempty(const snd_interval_t *i)
{
	return (i->min > i->max ||
		(i->min == i->max && (i->openmin || i->openmax)));
}

INLINE int snd_interval_empty(const snd_interval_t *i)
{
	return i->empty;
}

INLINE int snd_interval_single(const snd_interval_t *i)
{
	assert(!snd_interval_empty(i));
	return (i->min == i->max || 
		(i->min + 1 == i->max && i->openmax));
}

INLINE int snd_interval_value(const snd_interval_t *i)
{
	assert(snd_interval_single(i));
	return i->min;
}

INLINE int snd_interval_min(const snd_interval_t *i)
{
	assert(!snd_interval_empty(i));
	return i->min;
}

INLINE int snd_interval_max(const snd_interval_t *i)
{
	unsigned int v;
	assert(!snd_interval_empty(i));
	v = i->max;
	if (i->openmax)
		v--;
	return v;
}

INLINE int snd_interval_test(const snd_interval_t *i, unsigned int val)
{
	return !((i->min > val || (i->min == val && i->openmin) ||
		  i->max < val || (i->max == val && i->openmax)));
}

INLINE void snd_interval_copy(snd_interval_t *d, const snd_interval_t *s)
{
	*d = *s;
}

INLINE int snd_interval_setinteger(snd_interval_t *i)
{
	if (i->integer)
		return 0;
	if (i->openmin && i->openmax && i->min == i->max)
		return -EINVAL;
	i->integer = 1;
	return 1;
}

INLINE int snd_interval_eq(const snd_interval_t *i1, const snd_interval_t *i2)
{
	if (i1->empty)
		return i2->empty;
	if (i2->empty)
		return i1->empty;
	return i1->min == i2->min && i1->openmin == i2->openmin &&
		i1->max == i2->max && i1->openmax == i2->openmax;
}

static inline unsigned int add(unsigned int a, unsigned int b)
{
	if (a >= UINT_MAX - b)
		return UINT_MAX;
	return a + b;
}

static inline unsigned int sub(unsigned int a, unsigned int b)
{
	if (a > b)
		return a - b;
	return 0;
}

#undef INLINE
#undef assert

#endif /* __SOUND_PCM_PARAMS_H */