⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcm_lib.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
 * * c = a * k / b * * Returns non-zero if the value is changed, zero if not changed. */void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k,		      const struct snd_interval *b, struct snd_interval *c){	unsigned int r;	if (a->empty || b->empty) {		snd_interval_none(c);		return;	}	c->empty = 0;	c->min = muldiv32(a->min, k, b->max, &r);	c->openmin = (r || a->openmin || b->openmax);	if (b->min > 0) {		c->max = muldiv32(a->max, k, b->min, &r);		if (r) {			c->max++;			c->openmax = 1;		} else			c->openmax = (a->openmax || b->openmin);	} else {		c->max = UINT_MAX;		c->openmax = 0;	}	c->integer = 0;}/* ---- *//** * snd_interval_ratnum - refine the interval value * @i: interval to refine * @rats_count: number of ratnum_t  * @rats: ratnum_t array * @nump: pointer to store the resultant numerator * @denp: pointer to store the resultant denominator * * Returns non-zero if the value is changed, zero if not changed. */int snd_interval_ratnum(struct snd_interval *i,			unsigned int rats_count, struct snd_ratnum *rats,			unsigned int *nump, unsigned int *denp){	unsigned int best_num, best_diff, best_den;	unsigned int k;	struct snd_interval t;	int err;	best_num = best_den = best_diff = 0;	for (k = 0; k < rats_count; ++k) {		unsigned int num = rats[k].num;		unsigned int den;		unsigned int q = i->min;		int diff;		if (q == 0)			q = 1;		den = div_down(num, q);		if (den < rats[k].den_min)			continue;		if (den > rats[k].den_max)			den = rats[k].den_max;		else {			unsigned int r;			r = (den - rats[k].den_min) % rats[k].den_step;			if (r != 0)				den -= r;		}		diff = num - q * den;		if (best_num == 0 ||		    diff * best_den < best_diff * den) {			best_diff = diff;			best_den = den;			best_num = num;		}	}	if (best_den == 0) {		i->empty = 1;		return -EINVAL;	}	t.min = div_down(best_num, best_den);	t.openmin = !!(best_num % best_den);		best_num = best_den = best_diff = 0;	for (k = 0; k < rats_count; ++k) {		unsigned int num = rats[k].num;		unsigned int den;		unsigned int q = i->max;		int diff;		if (q == 0) {			i->empty = 1;			return -EINVAL;		}		den = div_up(num, q);		if (den > rats[k].den_max)			continue;		if (den < rats[k].den_min)			den = rats[k].den_min;		else {			unsigned int r;			r = (den - rats[k].den_min) % rats[k].den_step;			if (r != 0)				den += rats[k].den_step - r;		}		diff = q * den - num;		if (best_num == 0 ||		    diff * best_den < best_diff * den) {			best_diff = diff;			best_den = den;			best_num = num;		}	}	if (best_den == 0) {		i->empty = 1;		return -EINVAL;	}	t.max = div_up(best_num, best_den);	t.openmax = !!(best_num % best_den);	t.integer = 0;	err = snd_interval_refine(i, &t);	if (err < 0)		return err;	if (snd_interval_single(i)) {		if (nump)			*nump = best_num;		if (denp)			*denp = best_den;	}	return err;}EXPORT_SYMBOL(snd_interval_ratnum);/** * snd_interval_ratden - refine the interval value * @i: interval to refine * @rats_count: number of struct ratden * @rats: struct ratden array * @nump: pointer to store the resultant numerator * @denp: pointer to store the resultant denominator * * Returns non-zero if the value is changed, zero if not changed. */static int snd_interval_ratden(struct snd_interval *i,			       unsigned int rats_count, struct snd_ratden *rats,			       unsigned int *nump, unsigned int *denp){	unsigned int best_num, best_diff, best_den;	unsigned int k;	struct snd_interval t;	int err;	best_num = best_den = best_diff = 0;	for (k = 0; k < rats_count; ++k) {		unsigned int num;		unsigned int den = rats[k].den;		unsigned int q = i->min;		int diff;		num = mul(q, den);		if (num > rats[k].num_max)			continue;		if (num < rats[k].num_min)			num = rats[k].num_max;		else {			unsigned int r;			r = (num - rats[k].num_min) % rats[k].num_step;			if (r != 0)				num += rats[k].num_step - r;		}		diff = num - q * den;		if (best_num == 0 ||		    diff * best_den < best_diff * den) {			best_diff = diff;			best_den = den;			best_num = num;		}	}	if (best_den == 0) {		i->empty = 1;		return -EINVAL;	}	t.min = div_down(best_num, best_den);	t.openmin = !!(best_num % best_den);		best_num = best_den = best_diff = 0;	for (k = 0; k < rats_count; ++k) {		unsigned int num;		unsigned int den = rats[k].den;		unsigned int q = i->max;		int diff;		num = mul(q, den);		if (num < rats[k].num_min)			continue;		if (num > rats[k].num_max)			num = rats[k].num_max;		else {			unsigned int r;			r = (num - rats[k].num_min) % rats[k].num_step;			if (r != 0)				num -= r;		}		diff = q * den - num;		if (best_num == 0 ||		    diff * best_den < best_diff * den) {			best_diff = diff;			best_den = den;			best_num = num;		}	}	if (best_den == 0) {		i->empty = 1;		return -EINVAL;	}	t.max = div_up(best_num, best_den);	t.openmax = !!(best_num % best_den);	t.integer = 0;	err = snd_interval_refine(i, &t);	if (err < 0)		return err;	if (snd_interval_single(i)) {		if (nump)			*nump = best_num;		if (denp)			*denp = best_den;	}	return err;}/** * snd_interval_list - refine the interval value from the list * @i: the interval value to refine * @count: the number of elements in the list * @list: the value list * @mask: the bit-mask to evaluate * * Refines the interval value from the list. * When mask is non-zero, only the elements corresponding to bit 1 are * evaluated. * * Returns non-zero if the value is changed, zero if not changed. */int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask){        unsigned int k;	int changed = 0;	if (!count) {		i->empty = 1;		return -EINVAL;	}        for (k = 0; k < count; k++) {		if (mask && !(mask & (1 << k)))			continue;                if (i->min == list[k] && !i->openmin)                        goto _l1;                if (i->min < list[k]) {                        i->min = list[k];			i->openmin = 0;			changed = 1;                        goto _l1;                }        }        i->empty = 1;        return -EINVAL; _l1:        for (k = count; k-- > 0;) {		if (mask && !(mask & (1 << k)))			continue;                if (i->max == list[k] && !i->openmax)                        goto _l2;                if (i->max > list[k]) {                        i->max = list[k];			i->openmax = 0;			changed = 1;                        goto _l2;                }        }        i->empty = 1;        return -EINVAL; _l2:	if (snd_interval_checkempty(i)) {		i->empty = 1;		return -EINVAL;	}        return changed;}EXPORT_SYMBOL(snd_interval_list);static int snd_interval_step(struct snd_interval *i, unsigned int min, unsigned int step){	unsigned int n;	int changed = 0;	n = (i->min - min) % step;	if (n != 0 || i->openmin) {		i->min += step - n;		changed = 1;	}	n = (i->max - min) % step;	if (n != 0 || i->openmax) {		i->max -= n;		changed = 1;	}	if (snd_interval_checkempty(i)) {		i->empty = 1;		return -EINVAL;	}	return changed;}/* Info constraints helpers *//** * snd_pcm_hw_rule_add - add the hw-constraint rule * @runtime: the pcm runtime instance * @cond: condition bits * @var: the variable to evaluate * @func: the evaluation function * @private: the private data pointer passed to function * @dep: the dependent variables * * Returns zero if successful, or a negative error code on failure. */int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond,			int var,			snd_pcm_hw_rule_func_t func, void *private,			int dep, ...){	struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;	struct snd_pcm_hw_rule *c;	unsigned int k;	va_list args;	va_start(args, dep);	if (constrs->rules_num >= constrs->rules_all) {		struct snd_pcm_hw_rule *new;		unsigned int new_rules = constrs->rules_all + 16;		new = kcalloc(new_rules, sizeof(*c), GFP_KERNEL);		if (!new)			return -ENOMEM;		if (constrs->rules) {			memcpy(new, constrs->rules,			       constrs->rules_num * sizeof(*c));			kfree(constrs->rules);		}		constrs->rules = new;		constrs->rules_all = new_rules;	}	c = &constrs->rules[constrs->rules_num];	c->cond = cond;	c->func = func;	c->var = var;	c->private = private;	k = 0;	while (1) {		snd_assert(k < ARRAY_SIZE(c->deps), return -EINVAL);		c->deps[k++] = dep;		if (dep < 0)			break;		dep = va_arg(args, int);	}	constrs->rules_num++;	va_end(args);	return 0;}				    EXPORT_SYMBOL(snd_pcm_hw_rule_add);/** * snd_pcm_hw_constraint_mask * @runtime: PCM runtime instance * @var: hw_params variable to apply the mask * @mask: the bitmap mask * * Apply the constraint of the given bitmap mask to a mask parameter. */int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,			       u_int32_t mask){	struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;	struct snd_mask *maskp = constrs_mask(constrs, var);	*maskp->bits &= mask;	memset(maskp->bits + 1, 0, (SNDRV_MASK_MAX-32) / 8); /* clear rest */	if (*maskp->bits == 0)		return -EINVAL;	return 0;}/** * snd_pcm_hw_constraint_mask64 * @runtime: PCM runtime instance * @var: hw_params variable to apply the mask * @mask: the 64bit bitmap mask * * Apply the constraint of the given bitmap mask to a mask parameter. */int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,				 u_int64_t mask){	struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;	struct snd_mask *maskp = constrs_mask(constrs, var);	maskp->bits[0] &= (u_int32_t)mask;	maskp->bits[1] &= (u_int32_t)(mask >> 32);	memset(maskp->bits + 2, 0, (SNDRV_MASK_MAX-64) / 8); /* clear rest */	if (! maskp->bits[0] && ! maskp->bits[1])		return -EINVAL;	return 0;}/** * snd_pcm_hw_constraint_integer * @runtime: PCM runtime instance * @var: hw_params variable to apply the integer constraint * * Apply the constraint of integer to an interval parameter. */int snd_pcm_hw_constraint_integer(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var){	struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;	return snd_interval_setinteger(constrs_interval(constrs, var));}EXPORT_SYMBOL(snd_pcm_hw_constraint_integer);/** * snd_pcm_hw_constraint_minmax * @runtime: PCM runtime instance * @var: hw_params variable to apply the range * @min: the minimal value * @max: the maximal value *  * Apply the min/max range constraint to an interval parameter. */int snd_pcm_hw_constraint_minmax(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,				 unsigned int min, unsigned int max){	struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;	struct snd_interval t;	t.min = min;	t.max = max;	t.openmin = t.openmax = 0;	t.integer = 0;	return snd_interval_refine(constrs_interval(constrs, var), &t);}EXPORT_SYMBOL(snd_pcm_hw_constraint_minmax);static int snd_pcm_hw_rule_list(struct snd_pcm_hw_params *params,				struct snd_pcm_hw_rule *rule){	struct snd_pcm_hw_constraint_list *list = rule->private;	return snd_interval_list(hw_param_interval(params, rule->var), list->count, list->list, list->mask);}		/** * snd_pcm_hw_constraint_list * @runtime: PCM runtime instance * @cond: condition bits * @var: hw_params variable to apply the list constraint * @l: list *  * Apply the list of constraints to an interval parameter. */int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime,			       unsigned int cond,			       snd_pcm_hw_param_t var,			       struct snd_pcm_hw_constraint_list *l){	return snd_pcm_hw_rule_add(runtime, cond, var,				   snd_pcm_hw_rule_list, l,				   var, -1);}EXPORT_SYMBOL(snd_pcm_hw_constraint_list);static int snd_pcm_hw_rule_ratnums(struct snd_pcm_hw_params *params,				   struct snd_pcm_hw_rule *rule){	struct snd_pcm_hw_constraint_ratnums *r = rule->private;	unsigned int num = 0, den = 0;	int err;	err = snd_interval_ratnum(hw_param_interval(params, rule->var),				  r->nrats, r->rats, &num, &den);	if (err >= 0 && den && rule->var == SNDRV_PCM_HW_PARAM_RATE) {		params->rate_num = num;		params->rate_den = den;	}	return err;}/** * snd_pcm_hw_constraint_ratnums * @runtime: PCM runtime instance * @cond: condition bits * @var: hw_params variable to apply the ratnums constraint * @r: struct snd_ratnums constriants */int snd_pcm_hw_constraint_ratnums(struct snd_pcm_runtime *runtime, 				  unsigned int cond,				  snd_pcm_hw_param_t var,				  struct snd_pcm_hw_constraint_ratnums *r){	return snd_pcm_hw_rule_add(runtime, cond, var,				   snd_pcm_hw_rule_ratnums, r,				   var, -1);}EXPORT_SYMBOL(snd_pcm_hw_constraint_ratnums);static int snd_pcm_hw_rule_ratdens(struct snd_pcm_hw_params *params,				   struct snd_pcm_hw_rule *rule){	struct snd_pcm_hw_constraint_ratdens *r = rule->private;	unsigned int num = 0, den = 0;	int err = snd_interval_ratden(hw_param_interval(params, rule->var),				  r->nrats, r->rats, &num, &den);	if (err >= 0 && den && rule->var == SNDRV_PCM_HW_PARAM_RATE) {		params->rate_num = num;		params->rate_den = den;	}	return err;}/** * snd_pcm_hw_constraint_ratdens * @runtime: PCM runtime instance * @cond: condition bits * @var: hw_params variable to apply the ratdens constraint

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -