Blame src/pcm/pcm_params.c

Packit 4a16fb
/*
Packit 4a16fb
 *  PCM - Params functions
Packit 4a16fb
 *  Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
Packit 4a16fb
 *
Packit 4a16fb
 *
Packit 4a16fb
 *   This library is free software; you can redistribute it and/or modify
Packit 4a16fb
 *   it under the terms of the GNU Lesser General Public License as
Packit 4a16fb
 *   published by the Free Software Foundation; either version 2.1 of
Packit 4a16fb
 *   the License, or (at your option) any later version.
Packit 4a16fb
 *
Packit 4a16fb
 *   This program is distributed in the hope that it will be useful,
Packit 4a16fb
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 4a16fb
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 4a16fb
 *   GNU Lesser General Public License for more details.
Packit 4a16fb
 *
Packit 4a16fb
 *   You should have received a copy of the GNU Lesser General Public
Packit 4a16fb
 *   License along with this library; if not, write to the Free Software
Packit 4a16fb
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
Packit 4a16fb
 *
Packit 4a16fb
 */
Packit 4a16fb
  
Packit 4a16fb
#include "pcm_local.h"
Packit 4a16fb
Packit 4a16fb
#ifndef NDEBUG
Packit 4a16fb
/*
Packit 4a16fb
 * dump hw_params when $LIBASOUND_DEBUG is set to >= 1
Packit 4a16fb
 */
Packit 4a16fb
static void dump_hw_params(snd_pcm_hw_params_t *params, const char *type,
Packit 4a16fb
			   snd_pcm_hw_param_t var, unsigned int val, int err)
Packit 4a16fb
{
Packit 4a16fb
	const char *verbose = getenv("LIBASOUND_DEBUG");
Packit 4a16fb
	snd_output_t *out;
Packit 4a16fb
Packit 4a16fb
	if (! verbose || ! *verbose || atoi(verbose) < 1)
Packit 4a16fb
		return;
Packit 4a16fb
	if (snd_output_stdio_attach(&out, stderr, 0) < 0)
Packit 4a16fb
		return;
Packit 4a16fb
	fprintf(stderr, "ALSA ERROR hw_params: %s (%s)\n",
Packit 4a16fb
		type, snd_pcm_hw_param_name(var));
Packit 4a16fb
	fprintf(stderr, "           value = ");
Packit 4a16fb
	switch (var) {
Packit 4a16fb
	case SND_PCM_HW_PARAM_ACCESS:
Packit 4a16fb
		fprintf(stderr, "%s", snd_pcm_access_name(val));
Packit 4a16fb
		break;
Packit 4a16fb
	case SND_PCM_HW_PARAM_FORMAT:
Packit 4a16fb
		fprintf(stderr, "%s", snd_pcm_format_name(val));
Packit 4a16fb
		break;
Packit 4a16fb
	case SND_PCM_HW_PARAM_SUBFORMAT:
Packit 4a16fb
		fprintf(stderr, "%s", snd_pcm_subformat_name(val));
Packit 4a16fb
		break;
Packit 4a16fb
	default:
Packit 4a16fb
		fprintf(stderr, "%u", val);
Packit 4a16fb
	}
Packit 4a16fb
	fprintf(stderr, " : %s\n", snd_strerror(err));
Packit 4a16fb
	snd_pcm_hw_params_dump(params, out);
Packit 4a16fb
	snd_output_close(out);
Packit 4a16fb
}
Packit 4a16fb
#else
Packit 4a16fb
static inline void dump_hw_params(snd_pcm_hw_params_t *params, const char *type,
Packit 4a16fb
				  snd_pcm_hw_param_t var, unsigned int val, int err)
Packit 4a16fb
{
Packit 4a16fb
}
Packit 4a16fb
#endif
Packit 4a16fb
Packit 4a16fb
static inline int hw_is_mask(snd_pcm_hw_param_t var)
Packit 4a16fb
{
Packit 4a16fb
#if SND_PCM_HW_PARAM_FIRST_MASK == 0
Packit 4a16fb
	return var <= SND_PCM_HW_PARAM_LAST_MASK;
Packit 4a16fb
#else
Packit 4a16fb
	return var >= SND_PCM_HW_PARAM_FIRST_MASK &&
Packit 4a16fb
		var <= SND_PCM_HW_PARAM_LAST_MASK;
Packit 4a16fb
#endif
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
static inline int hw_is_interval(snd_pcm_hw_param_t var)
Packit 4a16fb
{
Packit 4a16fb
	return var >= SND_PCM_HW_PARAM_FIRST_INTERVAL &&
Packit 4a16fb
		var <= SND_PCM_HW_PARAM_LAST_INTERVAL;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
#define hw_param_mask(params,var) \
Packit 4a16fb
	&((params)->masks[(var) - SND_PCM_HW_PARAM_FIRST_MASK])
Packit 4a16fb
Packit 4a16fb
#define hw_param_interval(params,var) \
Packit 4a16fb
	&((params)->intervals[(var) - SND_PCM_HW_PARAM_FIRST_INTERVAL])
Packit 4a16fb
Packit 4a16fb
#define hw_param_mask_c hw_param_mask
Packit 4a16fb
#define hw_param_interval_c hw_param_interval
Packit 4a16fb
Packit 4a16fb
static void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var)
Packit 4a16fb
{
Packit 4a16fb
	if (hw_is_mask(var)) {
Packit 4a16fb
		snd_mask_any(hw_param_mask(params, var));
Packit 4a16fb
		params->cmask |= 1 << var;
Packit 4a16fb
		params->rmask |= 1 << var;
Packit 4a16fb
		return;
Packit 4a16fb
	}
Packit 4a16fb
	if (hw_is_interval(var)) {
Packit 4a16fb
		snd_interval_any(hw_param_interval(params, var));
Packit 4a16fb
		params->cmask |= 1 << var;
Packit 4a16fb
		params->rmask |= 1 << var;
Packit 4a16fb
		return;
Packit 4a16fb
	}
Packit 4a16fb
	assert(0);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
int snd_pcm_hw_param_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
Packit 4a16fb
			 snd_pcm_hw_param_t var)
Packit 4a16fb
{
Packit 4a16fb
	_snd_pcm_hw_param_any(params, var);
Packit 4a16fb
	return snd_pcm_hw_refine(pcm, params);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params)
Packit 4a16fb
{
Packit 4a16fb
	unsigned int k;
Packit 4a16fb
	memset(params, 0, sizeof(*params));
Packit 4a16fb
	for (k = SND_PCM_HW_PARAM_FIRST_MASK; k <= SND_PCM_HW_PARAM_LAST_MASK; k++)
Packit 4a16fb
		_snd_pcm_hw_param_any(params, k);
Packit 4a16fb
	for (k = SND_PCM_HW_PARAM_FIRST_INTERVAL; k <= SND_PCM_HW_PARAM_LAST_INTERVAL; k++)
Packit 4a16fb
		_snd_pcm_hw_param_any(params, k);
Packit 4a16fb
	params->rmask = ~0U;
Packit 4a16fb
	params->cmask = 0;
Packit 4a16fb
	params->info = ~0U;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/* Return the value for field PAR if it's fixed in configuration space 
Packit 4a16fb
   defined by PARAMS. Return -EINVAL otherwise
Packit 4a16fb
*/
Packit 4a16fb
int snd_pcm_hw_param_get(const snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var,
Packit 4a16fb
			 unsigned int *val, int *dir)
Packit 4a16fb
{
Packit 4a16fb
	if (hw_is_mask(var)) {
Packit 4a16fb
		const snd_mask_t *mask = hw_param_mask_c(params, var);
Packit 4a16fb
		if (snd_mask_empty(mask) || !snd_mask_single(mask))
Packit 4a16fb
			return -EINVAL;
Packit 4a16fb
		if (dir)
Packit 4a16fb
			*dir = 0;
Packit 4a16fb
		if (val)
Packit 4a16fb
			*val = snd_mask_value(mask);
Packit 4a16fb
		return 0;
Packit 4a16fb
	} else if (hw_is_interval(var)) {
Packit 4a16fb
		const snd_interval_t *i = hw_param_interval_c(params, var);
Packit 4a16fb
		if (snd_interval_empty(i) || !snd_interval_single(i))
Packit 4a16fb
			return -EINVAL;
Packit 4a16fb
		if (dir)
Packit 4a16fb
			*dir = i->openmin;
Packit 4a16fb
		if (val)
Packit 4a16fb
			*val = snd_interval_value(i);
Packit 4a16fb
		return 0;
Packit 4a16fb
	}
Packit 4a16fb
	assert(0);
Packit 4a16fb
	return -EINVAL;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/* Return the minimum value for field PAR. */
Packit 4a16fb
int snd_pcm_hw_param_get_min(const snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var,
Packit 4a16fb
			     unsigned int *val, int *dir)
Packit 4a16fb
{
Packit 4a16fb
	if (hw_is_mask(var)) {
Packit 4a16fb
		const snd_mask_t *m = hw_param_mask_c(params, var);
Packit 4a16fb
		assert(!snd_mask_empty(m));
Packit 4a16fb
		if (dir)
Packit 4a16fb
			*dir = 0;
Packit 4a16fb
		if (val)
Packit 4a16fb
			*val = snd_mask_min(m);
Packit 4a16fb
		return 0;
Packit 4a16fb
	} else if (hw_is_interval(var)) {
Packit 4a16fb
		const snd_interval_t *i = hw_param_interval_c(params, var);
Packit 4a16fb
		assert(!snd_interval_empty(i));
Packit 4a16fb
		if (dir)
Packit 4a16fb
			*dir = i->openmin;
Packit 4a16fb
		if (val)
Packit 4a16fb
			*val = snd_interval_min(i);
Packit 4a16fb
		return 0;
Packit 4a16fb
	}
Packit 4a16fb
	assert(0);
Packit 4a16fb
	return 0;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/* Return the maximum value for field PAR. */
Packit 4a16fb
int snd_pcm_hw_param_get_max(const snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var,
Packit 4a16fb
			     unsigned int *val, int *dir)
Packit 4a16fb
{
Packit 4a16fb
	if (hw_is_mask(var)) {
Packit 4a16fb
		const snd_mask_t *m = hw_param_mask_c(params, var);
Packit 4a16fb
		assert(!snd_mask_empty(m));
Packit 4a16fb
		if (dir)
Packit 4a16fb
			*dir = 0;
Packit 4a16fb
		if (val)
Packit 4a16fb
			*val = snd_mask_max(m);
Packit 4a16fb
		return 0;
Packit 4a16fb
	} else if (hw_is_interval(var)) {
Packit 4a16fb
		const snd_interval_t *i = hw_param_interval_c(params, var);
Packit 4a16fb
		assert(!snd_interval_empty(i));
Packit 4a16fb
		if (dir)
Packit 4a16fb
			*dir = - (int) i->openmax;
Packit 4a16fb
		if (val)
Packit 4a16fb
			*val = snd_interval_max(i);
Packit 4a16fb
		return 0;
Packit 4a16fb
	}
Packit 4a16fb
	assert(0);
Packit 4a16fb
	return 0;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/* Return the mask for field PAR.
Packit 4a16fb
   This function can be called only for SND_PCM_HW_PARAM_ACCESS,
Packit 4a16fb
   SND_PCM_HW_PARAM_FORMAT, SND_PCM_HW_PARAM_SUBFORMAT. */
Packit 4a16fb
const snd_mask_t *snd_pcm_hw_param_get_mask(const snd_pcm_hw_params_t *params,
Packit 4a16fb
					   snd_pcm_hw_param_t var)
Packit 4a16fb
{
Packit 4a16fb
	assert(hw_is_mask(var));
Packit 4a16fb
	return hw_param_mask_c(params, var);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/* Return the interval for field PAR.
Packit 4a16fb
   This function cannot be called for SND_PCM_HW_PARAM_ACCESS,
Packit 4a16fb
   SND_PCM_HW_PARAM_FORMAT, SND_PCM_HW_PARAM_SUBFORMAT. */
Packit 4a16fb
const snd_interval_t *snd_pcm_hw_param_get_interval(const snd_pcm_hw_params_t *params,
Packit 4a16fb
						  snd_pcm_hw_param_t var)
Packit 4a16fb
{
Packit 4a16fb
	assert(hw_is_interval(var));
Packit 4a16fb
	return hw_param_interval_c(params, var);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/* --- Refinement functions --- */
Packit 4a16fb
Packit 4a16fb
int _snd_pcm_hw_param_set_interval(snd_pcm_hw_params_t *params,
Packit 4a16fb
				   snd_pcm_hw_param_t var,
Packit 4a16fb
				   const snd_interval_t *val)
Packit 4a16fb
{
Packit 4a16fb
	int changed;
Packit 4a16fb
	assert(hw_is_interval(var));
Packit 4a16fb
	changed = snd_interval_refine(hw_param_interval(params, var), val);
Packit 4a16fb
	if (changed) {
Packit 4a16fb
		params->cmask |= 1 << var;
Packit 4a16fb
		params->rmask |= 1 << var;
Packit 4a16fb
	}
Packit 4a16fb
	return changed;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
void _snd_pcm_hw_param_set_empty(snd_pcm_hw_params_t *params,
Packit 4a16fb
				 snd_pcm_hw_param_t var)
Packit 4a16fb
{
Packit 4a16fb
	if (hw_is_mask(var)) {
Packit 4a16fb
		snd_mask_none(hw_param_mask(params, var));
Packit 4a16fb
		params->cmask |= 1 << var;
Packit 4a16fb
		params->rmask |= 1 << var;
Packit 4a16fb
	} else if (hw_is_interval(var)) {
Packit 4a16fb
		snd_interval_none(hw_param_interval(params, var));
Packit 4a16fb
		params->cmask |= 1 << var;
Packit 4a16fb
		params->rmask |= 1 << var;
Packit 4a16fb
	} else {
Packit 4a16fb
		assert(0);
Packit 4a16fb
	}
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
static int _snd_pcm_hw_param_set_integer(snd_pcm_hw_params_t *params,
Packit 4a16fb
					 snd_pcm_hw_param_t var)
Packit 4a16fb
{
Packit 4a16fb
	int changed;
Packit 4a16fb
	assert(hw_is_interval(var));
Packit 4a16fb
	changed = snd_interval_setinteger(hw_param_interval(params, var));
Packit 4a16fb
	if (changed) {
Packit 4a16fb
		params->cmask |= 1 << var;
Packit 4a16fb
		params->rmask |= 1 << var;
Packit 4a16fb
	}
Packit 4a16fb
	return changed;
Packit 4a16fb
}
Packit 4a16fb
	
Packit 4a16fb
/* Inside configuration space defined by PARAMS remove from PAR all 
Packit 4a16fb
   non integer values. Reduce configuration space accordingly.
Packit 4a16fb
   Return -EINVAL if the configuration space is empty
Packit 4a16fb
*/
Packit 4a16fb
int snd_pcm_hw_param_set_integer(snd_pcm_t *pcm, 
Packit 4a16fb
				 snd_pcm_hw_params_t *params,
Packit 4a16fb
				 snd_set_mode_t mode,
Packit 4a16fb
				 snd_pcm_hw_param_t var)
Packit 4a16fb
{
Packit 4a16fb
	snd_pcm_hw_params_t save;
Packit 4a16fb
	int err;
Packit 4a16fb
	switch (mode) {
Packit 4a16fb
	case SND_CHANGE:
Packit 4a16fb
		break;
Packit 4a16fb
	case SND_TRY:
Packit 4a16fb
		save = *params;
Packit 4a16fb
		break;
Packit 4a16fb
	case SND_TEST:
Packit 4a16fb
		save = *params;
Packit 4a16fb
		params = &sav;;
Packit 4a16fb
		break;
Packit 4a16fb
	default:
Packit 4a16fb
		assert(0);
Packit 4a16fb
		return -EINVAL;
Packit 4a16fb
	}
Packit 4a16fb
	err = _snd_pcm_hw_param_set_integer(params, var);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		goto _fail;
Packit 4a16fb
	if (params->rmask) {
Packit 4a16fb
		err = snd_pcm_hw_refine(pcm, params);
Packit 4a16fb
		if (err < 0)
Packit 4a16fb
			goto _fail;
Packit 4a16fb
	}
Packit 4a16fb
	return 0;
Packit 4a16fb
 _fail:
Packit 4a16fb
	if (mode == SND_TRY)
Packit 4a16fb
		*params = save;
Packit 4a16fb
	return err;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
static int _snd_pcm_hw_param_set_first(snd_pcm_hw_params_t *params,
Packit 4a16fb
				       snd_pcm_hw_param_t var)
Packit 4a16fb
{
Packit 4a16fb
	int changed;
Packit 4a16fb
	if (hw_is_mask(var))
Packit 4a16fb
		changed = snd_mask_refine_first(hw_param_mask(params, var));
Packit 4a16fb
	else if (hw_is_interval(var))
Packit 4a16fb
		changed = snd_interval_refine_first(hw_param_interval(params, var));
Packit 4a16fb
	else {
Packit 4a16fb
		assert(0);
Packit 4a16fb
		return -EINVAL;
Packit 4a16fb
	}
Packit 4a16fb
	if (changed > 0) {
Packit 4a16fb
		params->cmask |= 1 << var;
Packit 4a16fb
		params->rmask |= 1 << var;
Packit 4a16fb
	}
Packit 4a16fb
	return changed;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
Packit 4a16fb
/* Inside configuration space defined by PARAMS remove from PAR all 
Packit 4a16fb
   values > minimum. Reduce configuration space accordingly.
Packit 4a16fb
   Return the minimum.
Packit 4a16fb
*/
Packit 4a16fb
int snd_pcm_hw_param_set_first(snd_pcm_t *pcm, 
Packit 4a16fb
			       snd_pcm_hw_params_t *params, 
Packit 4a16fb
			       snd_pcm_hw_param_t var,
Packit 4a16fb
			       unsigned int *rval, int *dir)
Packit 4a16fb
{
Packit 4a16fb
	int err;
Packit 4a16fb
Packit 4a16fb
	err = _snd_pcm_hw_param_set_first(params, var);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		return err;
Packit 4a16fb
	if (params->rmask) {
Packit 4a16fb
		err = snd_pcm_hw_refine(pcm, params);
Packit 4a16fb
		if (err < 0)
Packit 4a16fb
			return err;
Packit 4a16fb
	}
Packit 4a16fb
	return snd_pcm_hw_param_get(params, var, rval, dir);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
static int _snd_pcm_hw_param_set_last(snd_pcm_hw_params_t *params,
Packit 4a16fb
				      snd_pcm_hw_param_t var)
Packit 4a16fb
{
Packit 4a16fb
	int changed;
Packit 4a16fb
	if (hw_is_mask(var))
Packit 4a16fb
		changed = snd_mask_refine_last(hw_param_mask(params, var));
Packit 4a16fb
	else if (hw_is_interval(var))
Packit 4a16fb
		changed = snd_interval_refine_last(hw_param_interval(params, var));
Packit 4a16fb
	else {
Packit 4a16fb
		assert(0);
Packit 4a16fb
		return -EINVAL;
Packit 4a16fb
	}
Packit 4a16fb
	if (changed > 0) {
Packit 4a16fb
		params->cmask |= 1 << var;
Packit 4a16fb
		params->rmask |= 1 << var;
Packit 4a16fb
	}
Packit 4a16fb
	return changed;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
Packit 4a16fb
/* Inside configuration space defined by PARAMS remove from PAR all 
Packit 4a16fb
   values < maximum. Reduce configuration space accordingly.
Packit 4a16fb
   Return the maximum.
Packit 4a16fb
*/
Packit 4a16fb
int snd_pcm_hw_param_set_last(snd_pcm_t *pcm, 
Packit 4a16fb
			      snd_pcm_hw_params_t *params,
Packit 4a16fb
			      snd_pcm_hw_param_t var,
Packit 4a16fb
			      unsigned int *rval, int *dir)
Packit 4a16fb
{
Packit 4a16fb
	int err;
Packit 4a16fb
Packit 4a16fb
	err = _snd_pcm_hw_param_set_last(params, var);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		return err;
Packit 4a16fb
	if (params->rmask) {
Packit 4a16fb
		err = snd_pcm_hw_refine(pcm, params);
Packit 4a16fb
		if (err < 0)
Packit 4a16fb
			return err;
Packit 4a16fb
	}
Packit 4a16fb
	return snd_pcm_hw_param_get(params, var, rval, dir);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
int _snd_pcm_hw_param_set_min(snd_pcm_hw_params_t *params,
Packit 4a16fb
			      snd_pcm_hw_param_t var, unsigned int val, int dir)
Packit 4a16fb
{
Packit 4a16fb
	int changed;
Packit 4a16fb
	int openmin = 0;
Packit 4a16fb
	if (dir) {
Packit 4a16fb
		if (dir > 0) {
Packit 4a16fb
			openmin = 1;
Packit 4a16fb
		} else if (dir < 0) {
Packit 4a16fb
			if (val > 0) {
Packit 4a16fb
				openmin = 1;
Packit 4a16fb
				val--;
Packit 4a16fb
			}
Packit 4a16fb
		}
Packit 4a16fb
	}
Packit 4a16fb
	if (hw_is_mask(var))
Packit 4a16fb
		changed = snd_mask_refine_min(hw_param_mask(params, var), val + !!openmin);
Packit 4a16fb
	else if (hw_is_interval(var))
Packit 4a16fb
		changed = snd_interval_refine_min(hw_param_interval(params, var), val, openmin);
Packit 4a16fb
	else {
Packit 4a16fb
		assert(0);
Packit 4a16fb
		return -EINVAL;
Packit 4a16fb
	}
Packit 4a16fb
	if (changed) {
Packit 4a16fb
		params->cmask |= 1 << var;
Packit 4a16fb
		params->rmask |= 1 << var;
Packit 4a16fb
	}
Packit 4a16fb
	return changed;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/* Inside configuration space defined by PARAMS remove from PAR all 
Packit 4a16fb
   values < VAL. Reduce configuration space accordingly.
Packit 4a16fb
   Return new minimum or -EINVAL if the configuration space is empty
Packit 4a16fb
*/
Packit 4a16fb
int snd_pcm_hw_param_set_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
Packit 4a16fb
			     snd_set_mode_t mode,
Packit 4a16fb
			     snd_pcm_hw_param_t var, unsigned int *val, int *dir)
Packit 4a16fb
{
Packit 4a16fb
	snd_pcm_hw_params_t save;
Packit 4a16fb
	int err;
Packit 4a16fb
	switch (mode) {
Packit 4a16fb
	case SND_CHANGE:
Packit 4a16fb
		break;
Packit 4a16fb
	case SND_TRY:
Packit 4a16fb
		save = *params;
Packit 4a16fb
		break;
Packit 4a16fb
	case SND_TEST:
Packit 4a16fb
		save = *params;
Packit 4a16fb
		params = &sav;;
Packit 4a16fb
		break;
Packit 4a16fb
	default:
Packit 4a16fb
		assert(0);
Packit 4a16fb
		return -EINVAL;
Packit 4a16fb
	}
Packit 4a16fb
	err = _snd_pcm_hw_param_set_min(params, var, *val, dir ? *dir : 0);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		goto _fail;
Packit 4a16fb
	if ((mode != SND_TEST || hw_is_interval(var)) && params->rmask) {
Packit 4a16fb
		err = snd_pcm_hw_refine(pcm, params);
Packit 4a16fb
		if (err < 0)
Packit 4a16fb
			goto _fail;
Packit 4a16fb
		if (snd_pcm_hw_param_empty(params, var)) {
Packit 4a16fb
			err = -ENOENT;
Packit 4a16fb
			goto _fail;
Packit 4a16fb
		}
Packit 4a16fb
	}
Packit 4a16fb
	return snd_pcm_hw_param_get_min(params, var, val, dir);
Packit 4a16fb
 _fail:
Packit 4a16fb
	if (mode == SND_TRY)
Packit 4a16fb
		*params = save;
Packit 4a16fb
	if (err < 0 && mode == SND_TRY)
Packit 4a16fb
		dump_hw_params(params, "set_min", var, *val, err);
Packit 4a16fb
	return err;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
int _snd_pcm_hw_param_set_max(snd_pcm_hw_params_t *params,
Packit 4a16fb
			      snd_pcm_hw_param_t var, unsigned int val, int dir)
Packit 4a16fb
{
Packit 4a16fb
	int changed;
Packit 4a16fb
	int openmax = 0;
Packit 4a16fb
	if (dir) {
Packit 4a16fb
		if (dir < 0) {
Packit 4a16fb
			openmax = 1;
Packit 4a16fb
		} else if (dir > 0) {
Packit 4a16fb
			openmax = 1;
Packit 4a16fb
			val++;
Packit 4a16fb
		}
Packit 4a16fb
	}
Packit 4a16fb
	if (hw_is_mask(var)) {
Packit 4a16fb
		if (val == 0 && openmax) {
Packit 4a16fb
		snd_mask_none(hw_param_mask(params, var));
Packit 4a16fb
			changed = -EINVAL;
Packit 4a16fb
		} else
Packit 4a16fb
			changed = snd_mask_refine_max(hw_param_mask(params, var), val - !!openmax);
Packit 4a16fb
	} else if (hw_is_interval(var))
Packit 4a16fb
		changed = snd_interval_refine_max(hw_param_interval(params, var), val, openmax);
Packit 4a16fb
	else {
Packit 4a16fb
		assert(0);
Packit 4a16fb
		return -EINVAL;
Packit 4a16fb
	}
Packit 4a16fb
	if (changed) {
Packit 4a16fb
		params->cmask |= 1 << var;
Packit 4a16fb
		params->rmask |= 1 << var;
Packit 4a16fb
	}
Packit 4a16fb
	return changed;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/* Inside configuration space defined by PARAMS remove from PAR all 
Packit 4a16fb
   values >= VAL + 1. Reduce configuration space accordingly.
Packit 4a16fb
   Return new maximum or -EINVAL if the configuration space is empty
Packit 4a16fb
*/
Packit 4a16fb
int snd_pcm_hw_param_set_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
Packit 4a16fb
			     snd_set_mode_t mode,
Packit 4a16fb
			     snd_pcm_hw_param_t var, unsigned int *val, int *dir)
Packit 4a16fb
{
Packit 4a16fb
	snd_pcm_hw_params_t save;
Packit 4a16fb
	int err;
Packit 4a16fb
	switch (mode) {
Packit 4a16fb
	case SND_CHANGE:
Packit 4a16fb
		break;
Packit 4a16fb
	case SND_TRY:
Packit 4a16fb
		save = *params;
Packit 4a16fb
		break;
Packit 4a16fb
	case SND_TEST:
Packit 4a16fb
		save = *params;
Packit 4a16fb
		params = &sav;;
Packit 4a16fb
		break;
Packit 4a16fb
	default:
Packit 4a16fb
		assert(0);
Packit 4a16fb
		return -EINVAL;
Packit 4a16fb
	}
Packit 4a16fb
	err = _snd_pcm_hw_param_set_max(params, var, *val, dir ? *dir : 0);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		goto _fail;
Packit 4a16fb
	if ((mode != SND_TEST || hw_is_interval(var)) && params->rmask) {
Packit 4a16fb
		err = snd_pcm_hw_refine(pcm, params);
Packit 4a16fb
		if (err < 0)
Packit 4a16fb
			goto _fail;
Packit 4a16fb
		if (snd_pcm_hw_param_empty(params, var)) {
Packit 4a16fb
			err = -ENOENT;
Packit 4a16fb
			goto _fail;
Packit 4a16fb
		}
Packit 4a16fb
	}
Packit 4a16fb
	return snd_pcm_hw_param_get_max(params, var, val, dir);
Packit 4a16fb
 _fail:
Packit 4a16fb
	if (mode == SND_TRY)
Packit 4a16fb
		*params = save;
Packit 4a16fb
	if (err < 0 && mode == SND_TRY)
Packit 4a16fb
		dump_hw_params(params, "set_max", var, *val, err);
Packit 4a16fb
	return err;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
int _snd_pcm_hw_param_set_minmax(snd_pcm_hw_params_t *params,
Packit 4a16fb
				 snd_pcm_hw_param_t var,
Packit 4a16fb
				 unsigned int min, int mindir,
Packit 4a16fb
				 unsigned int max, int maxdir)
Packit 4a16fb
{
Packit 4a16fb
	int changed, c1, c2;
Packit 4a16fb
	int openmin = 0, openmax = 0;
Packit 4a16fb
	if (mindir) {
Packit 4a16fb
		if (mindir > 0) {
Packit 4a16fb
			openmin = 1;
Packit 4a16fb
		} else if (mindir < 0) {
Packit 4a16fb
			if (min > 0) {
Packit 4a16fb
				openmin = 1;
Packit 4a16fb
				min--;
Packit 4a16fb
			}
Packit 4a16fb
		}
Packit 4a16fb
	}
Packit 4a16fb
	if (maxdir) {
Packit 4a16fb
		if (maxdir < 0) {
Packit 4a16fb
			openmax = 1;
Packit 4a16fb
		} else if (maxdir > 0) {
Packit 4a16fb
			openmax = 1;
Packit 4a16fb
			max++;
Packit 4a16fb
		}
Packit 4a16fb
	}
Packit 4a16fb
	if (hw_is_mask(var)) {
Packit 4a16fb
		snd_mask_t *mask = hw_param_mask(params, var);
Packit 4a16fb
		if (max == 0 && openmax) {
Packit 4a16fb
			snd_mask_none(mask);
Packit 4a16fb
			changed = -EINVAL;
Packit 4a16fb
		} else {
Packit 4a16fb
			c1 = snd_mask_refine_min(mask, min + !!openmin);
Packit 4a16fb
			if (c1 < 0)
Packit 4a16fb
				changed = c1;
Packit 4a16fb
			else {
Packit 4a16fb
				c2 = snd_mask_refine_max(mask, max - !!openmax);
Packit 4a16fb
				if (c2 < 0)
Packit 4a16fb
					changed = c2;
Packit 4a16fb
				else
Packit 4a16fb
					changed = (c1 || c2);
Packit 4a16fb
			}
Packit 4a16fb
		}
Packit 4a16fb
	}
Packit 4a16fb
	else if (hw_is_interval(var)) {
Packit 4a16fb
		snd_interval_t *i = hw_param_interval(params, var);
Packit 4a16fb
		c1 = snd_interval_refine_min(i, min, openmin);
Packit 4a16fb
		if (c1 < 0)
Packit 4a16fb
			changed = c1;
Packit 4a16fb
		else {
Packit 4a16fb
			c2 = snd_interval_refine_max(i, max, openmax);
Packit 4a16fb
			if (c2 < 0)
Packit 4a16fb
				changed = c2;
Packit 4a16fb
			else
Packit 4a16fb
				changed = (c1 || c2);
Packit 4a16fb
		}
Packit 4a16fb
	} else {
Packit 4a16fb
		assert(0);
Packit 4a16fb
		return -EINVAL;
Packit 4a16fb
	}
Packit 4a16fb
	if (changed) {
Packit 4a16fb
		params->cmask |= 1 << var;
Packit 4a16fb
		params->rmask |= 1 << var;
Packit 4a16fb
	}
Packit 4a16fb
	return changed;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/* Inside configuration space defined by PARAMS remove from PAR all 
Packit 4a16fb
   values < MIN and all values > MAX. Reduce configuration space accordingly.
Packit 4a16fb
   Return 0 or -EINVAL if the configuration space is empty
Packit 4a16fb
*/
Packit 4a16fb
int snd_pcm_hw_param_set_minmax(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
Packit 4a16fb
				snd_set_mode_t mode,
Packit 4a16fb
				snd_pcm_hw_param_t var,
Packit 4a16fb
				unsigned int *min, int *mindir,
Packit 4a16fb
				unsigned int *max, int *maxdir)
Packit 4a16fb
{
Packit 4a16fb
	snd_pcm_hw_params_t save;
Packit 4a16fb
	int err;
Packit 4a16fb
	switch (mode) {
Packit 4a16fb
	case SND_CHANGE:
Packit 4a16fb
		break;
Packit 4a16fb
	case SND_TRY:
Packit 4a16fb
		save = *params;
Packit 4a16fb
		break;
Packit 4a16fb
	case SND_TEST:
Packit 4a16fb
		save = *params;
Packit 4a16fb
		params = &sav;;
Packit 4a16fb
		break;
Packit 4a16fb
	default:
Packit 4a16fb
		assert(0);
Packit 4a16fb
		return -EINVAL;
Packit 4a16fb
	}
Packit 4a16fb
	err = _snd_pcm_hw_param_set_minmax(params, var, 
Packit 4a16fb
					   *min, mindir ? *mindir : 0,
Packit 4a16fb
					   *max, maxdir ? *maxdir : 0);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		goto _fail;
Packit 4a16fb
	if ((mode != SND_TEST || hw_is_interval(var)) && params->rmask) {
Packit 4a16fb
		err = snd_pcm_hw_refine(pcm, params);
Packit 4a16fb
		if (err < 0)
Packit 4a16fb
			goto _fail;
Packit 4a16fb
	}
Packit 4a16fb
	err = snd_pcm_hw_param_get_min(params, var, min, mindir);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		return err;
Packit 4a16fb
	return snd_pcm_hw_param_get_max(params, var, max, maxdir);
Packit 4a16fb
 _fail:
Packit 4a16fb
	if (mode == SND_TRY)
Packit 4a16fb
		*params = save;
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		dump_hw_params(params, "set_minmax", var, *min, err);
Packit 4a16fb
	return err;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
int _snd_pcm_hw_param_set(snd_pcm_hw_params_t *params,
Packit 4a16fb
			  snd_pcm_hw_param_t var, unsigned int val, int dir)
Packit 4a16fb
{
Packit 4a16fb
	int changed;
Packit 4a16fb
	if (hw_is_mask(var)) {
Packit 4a16fb
		snd_mask_t *m = hw_param_mask(params, var);
Packit 4a16fb
		if (val == 0 && dir < 0) {
Packit 4a16fb
			changed = -EINVAL;
Packit 4a16fb
			snd_mask_none(m);
Packit 4a16fb
		} else {
Packit 4a16fb
			if (dir > 0)
Packit 4a16fb
				val++;
Packit 4a16fb
			else if (dir < 0)
Packit 4a16fb
				val--;
Packit 4a16fb
			changed = snd_mask_refine_set(hw_param_mask(params, var), val);
Packit 4a16fb
		}
Packit 4a16fb
	} else if (hw_is_interval(var)) {
Packit 4a16fb
		snd_interval_t *i = hw_param_interval(params, var);
Packit 4a16fb
		if (val == 0 && dir < 0) {
Packit 4a16fb
			changed = -EINVAL;
Packit 4a16fb
			snd_interval_none(i);
Packit 4a16fb
		} else if (dir == 0)
Packit 4a16fb
			changed = snd_interval_refine_set(i, val);
Packit 4a16fb
		else {
Packit 4a16fb
			snd_interval_t t;
Packit 4a16fb
			t.openmin = 1;
Packit 4a16fb
			t.openmax = 1;
Packit 4a16fb
			t.empty = 0;
Packit 4a16fb
			t.integer = 0;
Packit 4a16fb
			if (dir < 0) {
Packit 4a16fb
				t.min = val - 1;
Packit 4a16fb
				t.max = val;
Packit 4a16fb
			} else {
Packit 4a16fb
				t.min = val;
Packit 4a16fb
				t.max = val+1;
Packit 4a16fb
			}
Packit 4a16fb
			changed = snd_interval_refine(i, &t);
Packit 4a16fb
		}
Packit 4a16fb
	} else {
Packit 4a16fb
		assert(0);
Packit 4a16fb
		return -EINVAL;
Packit 4a16fb
	}
Packit 4a16fb
	if (changed) {
Packit 4a16fb
		params->cmask |= 1 << var;
Packit 4a16fb
		params->rmask |= 1 << var;
Packit 4a16fb
	}
Packit 4a16fb
	return changed;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/* Inside configuration space defined by PARAMS remove from PAR all 
Packit 4a16fb
   values != VAL. Reduce configuration space accordingly.
Packit 4a16fb
   Return -EINVAL if the configuration space is empty
Packit 4a16fb
*/
Packit 4a16fb
int snd_pcm_hw_param_set(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
Packit 4a16fb
			 snd_set_mode_t mode,
Packit 4a16fb
			 snd_pcm_hw_param_t var, unsigned int val, int dir)
Packit 4a16fb
{
Packit 4a16fb
	snd_pcm_hw_params_t save;
Packit 4a16fb
	int err;
Packit 4a16fb
	switch (mode) {
Packit 4a16fb
	case SND_CHANGE:
Packit 4a16fb
		break;
Packit 4a16fb
	case SND_TRY:
Packit 4a16fb
		save = *params;
Packit 4a16fb
		break;
Packit 4a16fb
	case SND_TEST:
Packit 4a16fb
		save = *params;
Packit 4a16fb
		params = &sav;;
Packit 4a16fb
		break;
Packit 4a16fb
	default:
Packit 4a16fb
		assert(0);
Packit 4a16fb
		return -EINVAL;
Packit 4a16fb
	}
Packit 4a16fb
	err = _snd_pcm_hw_param_set(params, var, val, dir);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		goto _fail;
Packit 4a16fb
	if ((mode != SND_TEST || hw_is_interval(var)) && params->rmask) {
Packit 4a16fb
		err = snd_pcm_hw_refine(pcm, params);
Packit 4a16fb
		if (err < 0)
Packit 4a16fb
			goto _fail;
Packit 4a16fb
	}
Packit 4a16fb
	return 0;
Packit 4a16fb
 _fail:
Packit 4a16fb
	if (mode == SND_TRY)
Packit 4a16fb
		*params = save;
Packit 4a16fb
	if (err < 0 && mode == SND_TRY)
Packit 4a16fb
		dump_hw_params(params, "set", var, val, err);
Packit 4a16fb
	return err;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
int _snd_pcm_hw_param_set_mask(snd_pcm_hw_params_t *params,
Packit 4a16fb
			       snd_pcm_hw_param_t var, const snd_mask_t *val)
Packit 4a16fb
{
Packit 4a16fb
	int changed;
Packit 4a16fb
	assert(hw_is_mask(var));
Packit 4a16fb
	changed = snd_mask_refine(hw_param_mask(params, var), val);
Packit 4a16fb
	if (changed) {
Packit 4a16fb
		params->cmask |= 1 << var;
Packit 4a16fb
		params->rmask |= 1 << var;
Packit 4a16fb
	}
Packit 4a16fb
	return changed;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/* Inside configuration space defined by PARAMS remove from PAR all values
Packit 4a16fb
   not contained in MASK. Reduce configuration space accordingly.
Packit 4a16fb
   This function can be called only for SND_PCM_HW_PARAM_ACCESS,
Packit 4a16fb
   SND_PCM_HW_PARAM_FORMAT, SND_PCM_HW_PARAM_SUBFORMAT.
Packit 4a16fb
   Return 0 on success or -EINVAL
Packit 4a16fb
   if the configuration space is empty
Packit 4a16fb
*/
Packit 4a16fb
int snd_pcm_hw_param_set_mask(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
Packit 4a16fb
			      snd_set_mode_t mode,
Packit 4a16fb
			      snd_pcm_hw_param_t var, const snd_mask_t *val)
Packit 4a16fb
{
Packit 4a16fb
	snd_pcm_hw_params_t save;
Packit 4a16fb
	int err;
Packit 4a16fb
	switch (mode) {
Packit 4a16fb
	case SND_CHANGE:
Packit 4a16fb
		break;
Packit 4a16fb
	case SND_TRY:
Packit 4a16fb
		save = *params;
Packit 4a16fb
		break;
Packit 4a16fb
	case SND_TEST:
Packit 4a16fb
		save = *params;
Packit 4a16fb
		params = &sav;;
Packit 4a16fb
		break;
Packit 4a16fb
	default:
Packit 4a16fb
		assert(0);
Packit 4a16fb
		return -EINVAL;
Packit 4a16fb
	}
Packit 4a16fb
	err = _snd_pcm_hw_param_set_mask(params, var, val);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		goto _fail;
Packit 4a16fb
	if (mode != SND_TEST && params->rmask) {
Packit 4a16fb
		err = snd_pcm_hw_refine(pcm, params);
Packit 4a16fb
		if (err < 0)
Packit 4a16fb
			goto _fail;
Packit 4a16fb
	}
Packit 4a16fb
	return 0;
Packit 4a16fb
 _fail:
Packit 4a16fb
	if (mode == SND_TRY)
Packit 4a16fb
		*params = save;
Packit 4a16fb
	return err;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/* Inside configuration space defined by PARAMS set PAR to the available value
Packit 4a16fb
   nearest to VAL. Reduce configuration space accordingly.
Packit 4a16fb
   This function cannot be called for SND_PCM_HW_PARAM_ACCESS,
Packit 4a16fb
   SND_PCM_HW_PARAM_FORMAT, SND_PCM_HW_PARAM_SUBFORMAT.
Packit 4a16fb
   Return the value found.
Packit 4a16fb
 */
Packit 4a16fb
int snd_pcm_hw_param_set_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
Packit 4a16fb
			      snd_pcm_hw_param_t var,
Packit 4a16fb
			      unsigned int *val, int *dir)
Packit 4a16fb
{
Packit 4a16fb
	snd_pcm_hw_params_t save;
Packit 4a16fb
	int err;
Packit 4a16fb
	unsigned int best = *val, saved_min;
Packit 4a16fb
	int last = 0;
Packit 4a16fb
	unsigned int min, max;
Packit 4a16fb
	int mindir, maxdir;
Packit 4a16fb
	int valdir = dir ? *dir : 0;
Packit 4a16fb
	snd_interval_t *i;
Packit 4a16fb
	/* FIXME */
Packit 4a16fb
	if (best > INT_MAX)
Packit 4a16fb
		best = INT_MAX;
Packit 4a16fb
	min = max = best;
Packit 4a16fb
	mindir = maxdir = valdir;
Packit 4a16fb
	if (maxdir > 0)
Packit 4a16fb
		maxdir = 0;
Packit 4a16fb
	else if (maxdir == 0)
Packit 4a16fb
		maxdir = -1;
Packit 4a16fb
	else {
Packit 4a16fb
		maxdir = 1;
Packit 4a16fb
		max--;
Packit 4a16fb
	}
Packit 4a16fb
	save = *params;
Packit 4a16fb
	saved_min = min;
Packit 4a16fb
	err = snd_pcm_hw_param_set_min(pcm, params, SND_CHANGE, var, &min, &mindir);
Packit 4a16fb
Packit 4a16fb
	i = hw_param_interval(params, var);
Packit 4a16fb
	if (!snd_interval_empty(i) && snd_interval_single(i)) {
Packit 4a16fb
		err = snd_pcm_hw_param_get_min(params, var, val, dir);
Packit 4a16fb
		if (err < 0)
Packit 4a16fb
			dump_hw_params(params, "set_near", var, *val, err);
Packit 4a16fb
		return err;
Packit 4a16fb
	}
Packit 4a16fb
	
Packit 4a16fb
	if (err >= 0) {
Packit 4a16fb
		snd_pcm_hw_params_t params1;
Packit 4a16fb
		if (min == saved_min && mindir == valdir)
Packit 4a16fb
			goto _end;
Packit 4a16fb
		params1 = save;
Packit 4a16fb
		err = snd_pcm_hw_param_set_max(pcm, &params1, SND_CHANGE, var, &max, &maxdir);
Packit 4a16fb
		if (err < 0)
Packit 4a16fb
			goto _end;
Packit 4a16fb
		if (boundary_nearer(max, maxdir, best, valdir, min, mindir)) {
Packit 4a16fb
			*params = params1;
Packit 4a16fb
			last = 1;
Packit 4a16fb
		}
Packit 4a16fb
	} else {
Packit 4a16fb
		*params = save;
Packit 4a16fb
		err = snd_pcm_hw_param_set_max(pcm, params, SND_CHANGE, var, &max, &maxdir);
Packit 4a16fb
		if (err < 0) {
Packit 4a16fb
			dump_hw_params(params, "set_near", var, *val, err);
Packit 4a16fb
			return err;
Packit 4a16fb
		}
Packit 4a16fb
		last = 1;
Packit 4a16fb
	}
Packit 4a16fb
 _end:
Packit 4a16fb
	if (last)
Packit 4a16fb
		err = snd_pcm_hw_param_set_last(pcm, params, var, val, dir);
Packit 4a16fb
	else
Packit 4a16fb
		err = snd_pcm_hw_param_set_first(pcm, params, var, val, dir);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		dump_hw_params(params, "set_near", var, *val, err);
Packit 4a16fb
	return err;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
#if 0
Packit 4a16fb
/* Inside configuration space defined by PARAMS set PAR to the available value
Packit 4a16fb
   nearest to BEST after VAL (on equal difference values less than BEST are
Packit 4a16fb
   returned first).
Packit 4a16fb
   Reduce configuration space accordingly.
Packit 4a16fb
   This function cannot be called for SND_PCM_HW_PARAM_ACCESS,
Packit 4a16fb
   SND_PCM_HW_PARAM_FORMAT, SND_PCM_HW_PARAM_SUBFORMAT.
Packit 4a16fb
   Return the value found.
Packit 4a16fb
 */
Packit 4a16fb
int snd_pcm_hw_param_set_next(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
Packit 4a16fb
			      snd_pcm_hw_param_t var, 
Packit 4a16fb
			      unsigned int best, int bestdir,
Packit 4a16fb
			      unsigned int val, int *dir)
Packit 4a16fb
{
Packit 4a16fb
	snd_pcm_hw_params_t save;
Packit 4a16fb
	int v, err;
Packit 4a16fb
	int last = 0;
Packit 4a16fb
	int min, max;
Packit 4a16fb
	int mindir, maxdir;
Packit 4a16fb
	int diff, diffdir;
Packit 4a16fb
	int valdir = dir ? *dir : 0;
Packit 4a16fb
	/* FIXME */
Packit 4a16fb
	if (best > INT_MAX)
Packit 4a16fb
		best = INT_MAX;
Packit 4a16fb
	boundary_sub(val, valdir, best, bestdir, &diff, &diffdir);
Packit 4a16fb
	if (diff < 0 || (diff == 0 && diffdir < 0)) {
Packit 4a16fb
		min = best - diff;
Packit 4a16fb
		mindir = bestdir - diffdir;
Packit 4a16fb
		max = val;
Packit 4a16fb
		maxdir = bestdir - 1;
Packit 4a16fb
	} else {
Packit 4a16fb
		min = val;
Packit 4a16fb
		mindir = bestdir + 1;
Packit 4a16fb
		max = best + diff;
Packit 4a16fb
		maxdir = bestdir + diffdir + 1;
Packit 4a16fb
	}
Packit 4a16fb
	min += mindir / 2;
Packit 4a16fb
	mindir %= 2;
Packit 4a16fb
	max += maxdir / 2;
Packit 4a16fb
	maxdir %= 2;
Packit 4a16fb
	save = *params;
Packit 4a16fb
	if (min >= 0 &&
Packit 4a16fb
	    (err = snd_pcm_hw_param_set_min(pcm, params, SND_CHANGE, var, &min, &mindir)) >= 0) {
Packit 4a16fb
		snd_pcm_hw_params_t params1;
Packit 4a16fb
		if (max < 0)
Packit 4a16fb
			goto _end;
Packit 4a16fb
		params1 = save;
Packit 4a16fb
		err = snd_pcm_hw_param_set_max(pcm, &params1, SND_CHANGE, var, &max, &maxdir);
Packit 4a16fb
		if (err < 0)
Packit 4a16fb
			goto _end;
Packit 4a16fb
		if (boundary_nearer(max, maxdir, best, bestdir, min, mindir)) {
Packit 4a16fb
			*params = params1;
Packit 4a16fb
			last = 1;
Packit 4a16fb
		}
Packit 4a16fb
	} else {
Packit 4a16fb
		if (max < 0)
Packit 4a16fb
			return -EINVAL;
Packit 4a16fb
		*params = save;
Packit 4a16fb
		err = snd_pcm_hw_param_set_max(pcm, params, SND_CHANGE, var, &max, &maxdir);
Packit 4a16fb
		if (err < 0)
Packit 4a16fb
			return max;
Packit 4a16fb
		last = 1;
Packit 4a16fb
	}
Packit 4a16fb
 _end:
Packit 4a16fb
	if (last)
Packit 4a16fb
		v = snd_pcm_hw_param_set_last(pcm, params, var, dir);
Packit 4a16fb
	else
Packit 4a16fb
		v = snd_pcm_hw_param_set_first(pcm, params, var, dir);
Packit 4a16fb
	assert(v >= 0);
Packit 4a16fb
	return v;
Packit 4a16fb
}
Packit 4a16fb
#endif
Packit 4a16fb
Packit 4a16fb
static int snd_pcm_hw_param_set_near_minmax(snd_pcm_t *pcm,
Packit 4a16fb
					    snd_pcm_hw_params_t *params,
Packit 4a16fb
					    snd_pcm_hw_param_t var,
Packit 4a16fb
					    unsigned int min, int *mindir,
Packit 4a16fb
					    unsigned int max, int *maxdir)
Packit 4a16fb
{
Packit 4a16fb
	snd_pcm_hw_params_t tmp;
Packit 4a16fb
	int err;
Packit 4a16fb
	if (!boundary_lt(min, *mindir, max, *maxdir))
Packit 4a16fb
		return snd_pcm_hw_param_set_near(pcm, params, var, &min, mindir);
Packit 4a16fb
	tmp = *params;
Packit 4a16fb
	err = snd_pcm_hw_param_set_near(pcm, &tmp, var, &min, mindir);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		return err;
Packit 4a16fb
	if (boundary_lt(min, *mindir, max, *maxdir)) {
Packit 4a16fb
		tmp = *params;
Packit 4a16fb
		err = snd_pcm_hw_param_set_near(pcm, &tmp, var, &max, maxdir);
Packit 4a16fb
	} else {
Packit 4a16fb
		max = min;
Packit 4a16fb
		*maxdir = *mindir;
Packit 4a16fb
	}
Packit 4a16fb
	err = snd_pcm_hw_param_set_minmax(pcm, params, SND_CHANGE, var, &min, mindir,
Packit 4a16fb
					  &max, maxdir);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		return err;
Packit 4a16fb
	return 0;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
int snd_pcm_hw_param_refine_near(snd_pcm_t *pcm,
Packit 4a16fb
				 snd_pcm_hw_params_t *params,
Packit 4a16fb
				 snd_pcm_hw_param_t var,
Packit 4a16fb
				 const snd_pcm_hw_params_t *src)
Packit 4a16fb
{
Packit 4a16fb
	unsigned int min, max;
Packit 4a16fb
	int mindir, maxdir, err;
Packit 4a16fb
Packit 4a16fb
	if ((err = snd_pcm_hw_param_get_min(src, var, &min, &mindir)) < 0)
Packit 4a16fb
		return err;
Packit 4a16fb
	if ((err = snd_pcm_hw_param_get_max(src, var, &max, &maxdir)) < 0)
Packit 4a16fb
		return err;
Packit 4a16fb
	if ((err = snd_pcm_hw_param_set_near_minmax(pcm, params, var,
Packit 4a16fb
						    min, &mindir, max, &maxdir)) < 0)
Packit 4a16fb
		return err;
Packit 4a16fb
	return 0;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
int snd_pcm_hw_param_refine_multiple(snd_pcm_t *pcm,
Packit 4a16fb
				     snd_pcm_hw_params_t *params,
Packit 4a16fb
				     snd_pcm_hw_param_t var,
Packit 4a16fb
				     const snd_pcm_hw_params_t *src)
Packit 4a16fb
{
Packit 4a16fb
	const snd_interval_t *it = hw_param_interval_c(src, var);
Packit 4a16fb
	const snd_interval_t *st = hw_param_interval_c(params, var);
Packit 4a16fb
	if (snd_interval_single(it)) {
Packit 4a16fb
		unsigned int best = snd_interval_min(it), cur, prev;
Packit 4a16fb
		cur = best;
Packit 4a16fb
		for (;;) {
Packit 4a16fb
			if (st->max < cur || (st->max == cur && st->openmax))
Packit 4a16fb
				break;
Packit 4a16fb
			if (it->min <= cur && ! (it->min == cur && st->openmin)) {
Packit 4a16fb
				if (! snd_pcm_hw_param_set(pcm, params, SND_TRY, var, cur, 0))
Packit 4a16fb
					return 0; /* ok */
Packit 4a16fb
			}
Packit 4a16fb
			prev = cur;
Packit 4a16fb
			cur += best;
Packit 4a16fb
			if (cur <= prev)
Packit 4a16fb
				break;
Packit 4a16fb
		}
Packit 4a16fb
	}
Packit 4a16fb
	return snd_pcm_hw_param_refine_near(pcm, params, var, src);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/* ---- end of refinement functions ---- */
Packit 4a16fb
Packit 4a16fb
int snd_pcm_hw_param_empty(const snd_pcm_hw_params_t *params,
Packit 4a16fb
			   snd_pcm_hw_param_t var)
Packit 4a16fb
{
Packit 4a16fb
	if (hw_is_mask(var))
Packit 4a16fb
		return snd_mask_empty(hw_param_mask_c(params, var));
Packit 4a16fb
	if (hw_is_interval(var))
Packit 4a16fb
		return snd_interval_empty(hw_param_interval_c(params, var));
Packit 4a16fb
	assert(0);
Packit 4a16fb
	return -EINVAL;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
int snd_pcm_hw_param_always_eq(const snd_pcm_hw_params_t *params,
Packit 4a16fb
			       snd_pcm_hw_param_t var,
Packit 4a16fb
			       const snd_pcm_hw_params_t *params1)
Packit 4a16fb
{
Packit 4a16fb
	if (hw_is_mask(var))
Packit 4a16fb
		return snd_mask_always_eq(hw_param_mask_c(params, var),
Packit 4a16fb
					  hw_param_mask_c(params1, var));
Packit 4a16fb
	if (hw_is_interval(var))
Packit 4a16fb
		return snd_interval_always_eq(hw_param_interval_c(params, var),
Packit 4a16fb
					      hw_param_interval_c(params1, var));
Packit 4a16fb
	assert(0);
Packit 4a16fb
	return -EINVAL;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
int snd_pcm_hw_param_never_eq(const snd_pcm_hw_params_t *params,
Packit 4a16fb
			      snd_pcm_hw_param_t var,
Packit 4a16fb
			      const snd_pcm_hw_params_t *params1)
Packit 4a16fb
{
Packit 4a16fb
	if (hw_is_mask(var))
Packit 4a16fb
		return snd_mask_never_eq(hw_param_mask_c(params, var),
Packit 4a16fb
					 hw_param_mask_c(params1, var));
Packit 4a16fb
	if (hw_is_interval(var))
Packit 4a16fb
		return snd_interval_never_eq(hw_param_interval_c(params, var),
Packit 4a16fb
					     hw_param_interval_c(params1, var));
Packit 4a16fb
	assert(0);
Packit 4a16fb
	return -EINVAL;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
#if 0
Packit 4a16fb
#define CHOOSE_DEBUG
Packit 4a16fb
#endif
Packit 4a16fb
Packit 4a16fb
/* Choose one configuration from configuration space defined by PARAMS
Packit 4a16fb
   The configuration chosen is that obtained fixing in this order:
Packit 4a16fb
   first access
Packit 4a16fb
   first format
Packit 4a16fb
   first subformat
Packit 4a16fb
   min channels
Packit 4a16fb
   min rate
Packit 4a16fb
   min period time
Packit 4a16fb
   max buffer size
Packit 4a16fb
   min tick time
Packit 4a16fb
*/
Packit 4a16fb
static int snd_pcm_hw_params_choose(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
Packit 4a16fb
{
Packit 4a16fb
	int err;
Packit 4a16fb
#ifdef CHOOSE_DEBUG
Packit 4a16fb
	snd_output_t *log;
Packit 4a16fb
	snd_output_stdio_attach(&log, stderr, 0);
Packit 4a16fb
	snd_output_printf(log, "CHOOSE called:\n");
Packit 4a16fb
	snd_pcm_hw_params_dump(params, log);
Packit 4a16fb
#endif
Packit 4a16fb
Packit 4a16fb
	err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_ACCESS, NULL, 0);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		return err;
Packit 4a16fb
	err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_FORMAT, NULL, 0);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		return err;
Packit 4a16fb
	err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_SUBFORMAT, NULL, 0);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		return err;
Packit 4a16fb
	err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_CHANNELS, NULL, 0);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		return err;
Packit 4a16fb
	err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_RATE, NULL, 0);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		return err;
Packit 4a16fb
	if (pcm->minperiodtime > 0) {
Packit 4a16fb
		unsigned int min, max;
Packit 4a16fb
		int dir = 1;
Packit 4a16fb
		err = snd_pcm_hw_param_get_min(params, SND_PCM_HW_PARAM_PERIOD_TIME, &min, &dir;;
Packit 4a16fb
		if (err >= 0)
Packit 4a16fb
			err = snd_pcm_hw_param_get_max(params, SND_PCM_HW_PARAM_PERIOD_TIME, &max, &dir;;
Packit 4a16fb
		if (err >= 0 && (long)min < pcm->minperiodtime &&
Packit 4a16fb
			        (long)max > pcm->minperiodtime) {
Packit 4a16fb
			min = pcm->minperiodtime; dir = 1;
Packit 4a16fb
			snd_pcm_hw_param_set_min(pcm, params, SND_CHANGE, SND_PCM_HW_PARAM_PERIOD_TIME, &min, &dir;;
Packit 4a16fb
		}
Packit 4a16fb
	}
Packit 4a16fb
	if (pcm->compat) {
Packit 4a16fb
		/* old mode */
Packit 4a16fb
		err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_PERIOD_TIME, NULL, 0);
Packit 4a16fb
		if (err < 0)
Packit 4a16fb
			return err;
Packit 4a16fb
		err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_PERIOD_SIZE, NULL, 0);
Packit 4a16fb
		if (err < 0)
Packit 4a16fb
			return err;
Packit 4a16fb
		err = snd_pcm_hw_param_set_last(pcm, params, SND_PCM_HW_PARAM_BUFFER_SIZE, NULL, 0);
Packit 4a16fb
		if (err < 0)
Packit 4a16fb
			return err;
Packit 4a16fb
	} else {
Packit 4a16fb
		/* determine buffer size first */
Packit 4a16fb
		err = snd_pcm_hw_param_set_last(pcm, params, SND_PCM_HW_PARAM_BUFFER_SIZE, NULL, 0);
Packit 4a16fb
		if (err < 0)
Packit 4a16fb
			return err;
Packit 4a16fb
		err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_PERIOD_SIZE, NULL, 0);
Packit 4a16fb
		if (err < 0)
Packit 4a16fb
			return err;
Packit 4a16fb
		err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_PERIOD_TIME, NULL, 0);
Packit 4a16fb
		if (err < 0)
Packit 4a16fb
			return err;
Packit 4a16fb
	}
Packit 4a16fb
	err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_TICK_TIME, NULL, 0);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		return err;
Packit 4a16fb
#ifdef CHOOSE_DEBUG
Packit 4a16fb
	snd_output_printf(log, "choose done\n");
Packit 4a16fb
	snd_pcm_hw_params_dump(params, log);
Packit 4a16fb
	snd_output_close(log);
Packit 4a16fb
#endif
Packit 4a16fb
	return 0;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
#if 0
Packit 4a16fb
static unsigned int snd_pcm_hw_param_count(const snd_pcm_hw_params_t *params,
Packit 4a16fb
					   snd_pcm_hw_param_t var)
Packit 4a16fb
{
Packit 4a16fb
	if (hw_is_mask(var)) {
Packit 4a16fb
		const snd_mask_t *mask = hw_param_mask_c(params, var);
Packit 4a16fb
		return snd_mask_count(mask);
Packit 4a16fb
	}
Packit 4a16fb
	if (hw_is_interval(var)) {
Packit 4a16fb
		const snd_interval_t *i = hw_param_interval_c(params, var);
Packit 4a16fb
		return snd_interval_max(i) - snd_interval_min(i) + 1;
Packit 4a16fb
	}
Packit 4a16fb
	assert(0);
Packit 4a16fb
	return 0;
Packit 4a16fb
}
Packit 4a16fb
#endif
Packit 4a16fb
Packit 4a16fb
int _snd_pcm_hw_param_refine(snd_pcm_hw_params_t *params,
Packit 4a16fb
			     snd_pcm_hw_param_t var,
Packit 4a16fb
			     const snd_pcm_hw_params_t *src)
Packit 4a16fb
{
Packit 4a16fb
	int changed = 0;
Packit 4a16fb
	if (hw_is_mask(var)) {
Packit 4a16fb
		snd_mask_t *d = hw_param_mask(params, var);
Packit 4a16fb
		const snd_mask_t *s = hw_param_mask_c(src, var);
Packit 4a16fb
		changed = snd_mask_refine(d, s);
Packit 4a16fb
	} else if (hw_is_interval(var)) {
Packit 4a16fb
		snd_interval_t *d = hw_param_interval(params, var);
Packit 4a16fb
		const snd_interval_t *s = hw_param_interval_c(src, var);
Packit 4a16fb
		changed = snd_interval_refine(d, s);
Packit 4a16fb
	} else
Packit 4a16fb
		return 0; /* NOP / reserved */
Packit 4a16fb
	if (changed) {
Packit 4a16fb
		params->cmask |= 1 << var;
Packit 4a16fb
		params->rmask |= 1 << var;
Packit 4a16fb
	}
Packit 4a16fb
	return changed;
Packit 4a16fb
}
Packit 4a16fb
			     
Packit 4a16fb
#if 0
Packit 4a16fb
static void _snd_pcm_hw_param_copy(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var,
Packit 4a16fb
				   const snd_pcm_hw_params_t *src)
Packit 4a16fb
{
Packit 4a16fb
	if (hw_is_mask(var)) {
Packit 4a16fb
		snd_mask_t *d = hw_param_mask(params, var);
Packit 4a16fb
		const snd_mask_t *s = hw_param_mask_c(src, var);
Packit 4a16fb
		snd_mask_copy(d, s);
Packit 4a16fb
		params->cmask |= 1 << var;
Packit 4a16fb
		params->rmask |= 1 << var;
Packit 4a16fb
		return;
Packit 4a16fb
	}
Packit 4a16fb
	if (hw_is_interval(var)) {
Packit 4a16fb
		snd_interval_t *d = hw_param_interval(params, var);
Packit 4a16fb
		const snd_interval_t *s = hw_param_interval_c(src, var);
Packit 4a16fb
		snd_interval_copy(d, s);
Packit 4a16fb
		params->cmask |= 1 << var;
Packit 4a16fb
		params->rmask |= 1 << var;
Packit 4a16fb
		return;
Packit 4a16fb
	}
Packit 4a16fb
	assert(0);
Packit 4a16fb
}
Packit 4a16fb
#endif
Packit 4a16fb
Packit 4a16fb
void snd_pcm_hw_param_dump(const snd_pcm_hw_params_t *params,
Packit 4a16fb
			   snd_pcm_hw_param_t var, snd_output_t *out)
Packit 4a16fb
{
Packit 4a16fb
	if (hw_is_mask(var)) {
Packit 4a16fb
		const snd_mask_t *mask = hw_param_mask_c(params, var);
Packit 4a16fb
		if (snd_mask_empty(mask))
Packit 4a16fb
			snd_output_puts(out, " NONE");
Packit 4a16fb
		else if (snd_mask_full(mask))
Packit 4a16fb
			snd_output_puts(out, " ALL");
Packit 4a16fb
		else {
Packit 4a16fb
			unsigned int k;
Packit 4a16fb
			for (k = 0; k <= SND_MASK_MAX; ++k) {
Packit 4a16fb
				if (snd_mask_test(mask, k)) {
Packit 4a16fb
					const char *s;
Packit 4a16fb
					switch (var) {
Packit 4a16fb
					case SND_PCM_HW_PARAM_ACCESS:
Packit 4a16fb
						s = snd_pcm_access_name(k);
Packit 4a16fb
						break;
Packit 4a16fb
					case SND_PCM_HW_PARAM_FORMAT:
Packit 4a16fb
						s = snd_pcm_format_name(k);
Packit 4a16fb
						break;
Packit 4a16fb
					case SND_PCM_HW_PARAM_SUBFORMAT:
Packit 4a16fb
						s = snd_pcm_subformat_name(k);
Packit 4a16fb
						break;
Packit 4a16fb
					default:
Packit 4a16fb
						assert(0);
Packit 4a16fb
						s = NULL;
Packit 4a16fb
					}
Packit 4a16fb
					if (s) {
Packit 4a16fb
						snd_output_putc(out, ' ');
Packit 4a16fb
						snd_output_puts(out, s);
Packit 4a16fb
					}
Packit 4a16fb
				}
Packit 4a16fb
			}
Packit 4a16fb
		}
Packit 4a16fb
		return;
Packit 4a16fb
	}
Packit 4a16fb
	if (hw_is_interval(var)) {
Packit 4a16fb
		snd_interval_print(hw_param_interval_c(params, var), out);
Packit 4a16fb
		return;
Packit 4a16fb
	}
Packit 4a16fb
	assert(0);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
#define HW_PARAM(v) [SND_PCM_HW_PARAM_##v] = #v
Packit 4a16fb
Packit 4a16fb
static const char *const snd_pcm_hw_param_names[] = {
Packit 4a16fb
	HW_PARAM(ACCESS),
Packit 4a16fb
	HW_PARAM(FORMAT),
Packit 4a16fb
	HW_PARAM(SUBFORMAT),
Packit 4a16fb
	HW_PARAM(SAMPLE_BITS),
Packit 4a16fb
	HW_PARAM(FRAME_BITS),
Packit 4a16fb
	HW_PARAM(CHANNELS),
Packit 4a16fb
	HW_PARAM(RATE),
Packit 4a16fb
	HW_PARAM(PERIOD_TIME),
Packit 4a16fb
	HW_PARAM(PERIOD_SIZE),
Packit 4a16fb
	HW_PARAM(PERIOD_BYTES),
Packit 4a16fb
	HW_PARAM(PERIODS),
Packit 4a16fb
	HW_PARAM(BUFFER_TIME),
Packit 4a16fb
	HW_PARAM(BUFFER_SIZE),
Packit 4a16fb
	HW_PARAM(BUFFER_BYTES),
Packit 4a16fb
	HW_PARAM(TICK_TIME),
Packit 4a16fb
};
Packit 4a16fb
Packit 4a16fb
const char *snd_pcm_hw_param_name(snd_pcm_hw_param_t param)
Packit 4a16fb
{
Packit 4a16fb
	assert(param <= SND_PCM_HW_PARAM_LAST_INTERVAL);
Packit 4a16fb
	return snd_pcm_hw_param_names[param];
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
#if 0
Packit 4a16fb
/* Strategies */
Packit 4a16fb
Packit 4a16fb
struct _snd_pcm_hw_strategy {
Packit 4a16fb
	unsigned int badness_min, badness_max;
Packit 4a16fb
	int (*choose_param)(const snd_pcm_hw_params_t *params,
Packit 4a16fb
			    snd_pcm_t *pcm,
Packit 4a16fb
			    const snd_pcm_hw_strategy_t *strategy);
Packit 4a16fb
	int (*next_value)(snd_pcm_hw_params_t *params,
Packit 4a16fb
			  unsigned int param,
Packit 4a16fb
			  int value, int *dir,
Packit 4a16fb
			  snd_pcm_t *pcm,
Packit 4a16fb
			  const snd_pcm_hw_strategy_t *strategy);
Packit 4a16fb
	int (*min_badness)(const snd_pcm_hw_params_t *params,
Packit 4a16fb
			   unsigned int max_badness,
Packit 4a16fb
			   snd_pcm_t *pcm,
Packit 4a16fb
			   const snd_pcm_hw_strategy_t *strategy);
Packit 4a16fb
	void *private_data;
Packit 4a16fb
	void (*free)(snd_pcm_hw_strategy_t *strategy);
Packit 4a16fb
};
Packit 4a16fb
Packit 4a16fb
/* Independent badness */
Packit 4a16fb
typedef struct _snd_pcm_hw_strategy_simple snd_pcm_hw_strategy_simple_t;
Packit 4a16fb
Packit 4a16fb
struct _snd_pcm_hw_strategy_simple {
Packit 4a16fb
	int valid;
Packit 4a16fb
	unsigned int order;
Packit 4a16fb
	int (*next_value)(snd_pcm_hw_params_t *params,
Packit 4a16fb
			  unsigned int param,
Packit 4a16fb
			  int value, int *dir,
Packit 4a16fb
			  snd_pcm_t *pcm,
Packit 4a16fb
			  const snd_pcm_hw_strategy_simple_t *par);
Packit 4a16fb
	unsigned int (*min_badness)(const snd_pcm_hw_params_t *params,
Packit 4a16fb
				    unsigned int param,
Packit 4a16fb
				    snd_pcm_t *pcm,
Packit 4a16fb
				    const snd_pcm_hw_strategy_simple_t *par);
Packit 4a16fb
	void *private_data;
Packit 4a16fb
	void (*free)(snd_pcm_hw_strategy_simple_t *strategy);
Packit 4a16fb
};
Packit 4a16fb
Packit 4a16fb
typedef struct _snd_pcm_hw_strategy_simple_near {
Packit 4a16fb
	int best;
Packit 4a16fb
	unsigned int mul;
Packit 4a16fb
} snd_pcm_hw_strategy_simple_near_t;
Packit 4a16fb
Packit 4a16fb
typedef struct _snd_pcm_hw_strategy_simple_choices {
Packit 4a16fb
	unsigned int count;
Packit 4a16fb
	/* choices need to be sorted on ascending badness */
Packit 4a16fb
	snd_pcm_hw_strategy_simple_choices_list_t *choices;
Packit 4a16fb
} snd_pcm_hw_strategy_simple_choices_t;
Packit 4a16fb
Packit 4a16fb
int snd_pcm_hw_params_strategy(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
Packit 4a16fb
			       const snd_pcm_hw_strategy_t *strategy,
Packit 4a16fb
			       unsigned int badness_min,
Packit 4a16fb
			       unsigned int badness_max)
Packit 4a16fb
{
Packit 4a16fb
	snd_pcm_hw_params_t best_params;
Packit 4a16fb
	int var;
Packit 4a16fb
	int value, dir;
Packit 4a16fb
	unsigned int best_badness;
Packit 4a16fb
	int badness = strategy->min_badness(params, badness_max, pcm, strategy);
Packit 4a16fb
	snd_pcm_hw_params_t params1;
Packit 4a16fb
#if 0
Packit 4a16fb
	printf("\nBadness: %d\n", badness);
Packit 4a16fb
	snd_pcm_hw_params_dump(params, stdout);
Packit 4a16fb
#endif
Packit 4a16fb
	if (badness < 0)
Packit 4a16fb
		return badness;
Packit 4a16fb
	if ((unsigned int)badness > badness_min)
Packit 4a16fb
		badness_min = badness_min;
Packit 4a16fb
	var = strategy->choose_param(params, pcm, strategy);
Packit 4a16fb
	if (var < 0)
Packit 4a16fb
		return badness;
Packit 4a16fb
	best_badness = UINT_MAX;
Packit 4a16fb
	value = -1;
Packit 4a16fb
	while (1) {
Packit 4a16fb
		params1 = *params;
Packit 4a16fb
		value = strategy->next_value(&params1, var, value, &dir, pcm, strategy);
Packit 4a16fb
		if (value < 0)
Packit 4a16fb
			break;
Packit 4a16fb
		badness = snd_pcm_hw_params_strategy(pcm, &params1, strategy, badness_min, badness_max);
Packit 4a16fb
		if (badness >= 0) {
Packit 4a16fb
			if ((unsigned int) badness <= badness_min) {
Packit 4a16fb
				*params = params1;
Packit 4a16fb
				return badness;
Packit 4a16fb
			}
Packit 4a16fb
			best_badness = badness;
Packit 4a16fb
			best_params = params1;
Packit 4a16fb
			badness_max = badness - 1;
Packit 4a16fb
		}
Packit 4a16fb
	}
Packit 4a16fb
	if (best_badness == UINT_MAX) {
Packit 4a16fb
		return -EINVAL;
Packit 4a16fb
	}
Packit 4a16fb
	*params = best_params;
Packit 4a16fb
	return best_badness;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
void snd_pcm_hw_strategy_simple_free(snd_pcm_hw_strategy_t *strategy)
Packit 4a16fb
{
Packit 4a16fb
	snd_pcm_hw_strategy_simple_t *pars = strategy->private_data;
Packit 4a16fb
	int k;
Packit 4a16fb
	for (k = 0; k <= SND_PCM_HW_PARAM_LAST_INTERVAL; ++k) {
Packit 4a16fb
		if (pars[k].valid && pars[k].free)
Packit 4a16fb
			pars[k].free(&pars[k]);
Packit 4a16fb
	}
Packit 4a16fb
	free(pars);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
int snd_pcm_hw_strategy_simple_choose_param(const snd_pcm_hw_params_t *params,
Packit 4a16fb
					 snd_pcm_t *pcm ATTRIBUTE_UNUSED,
Packit 4a16fb
					 const snd_pcm_hw_strategy_t *strategy)
Packit 4a16fb
{
Packit 4a16fb
	snd_pcm_hw_param_t var;
Packit 4a16fb
	int best_var = -1;
Packit 4a16fb
	const snd_pcm_hw_strategy_simple_t *pars = strategy->private_data;
Packit 4a16fb
	unsigned int min_choices = UINT_MAX;
Packit 4a16fb
	unsigned int min_order = UINT_MAX;
Packit 4a16fb
	for (var = 0; var <= SND_PCM_HW_PARAM_LAST_INTERVAL; ++var) {
Packit 4a16fb
		const snd_pcm_hw_strategy_simple_t *p = &pars[var];
Packit 4a16fb
		unsigned int choices;
Packit 4a16fb
		if (!p->valid)
Packit 4a16fb
			continue;
Packit 4a16fb
		choices = snd_pcm_hw_param_count(params, var);
Packit 4a16fb
		if (choices == 1)
Packit 4a16fb
			continue;
Packit 4a16fb
		assert(choices != 0);
Packit 4a16fb
		if (p->order < min_order ||
Packit 4a16fb
		    (p->order == min_order &&
Packit 4a16fb
		     choices < min_choices)) {
Packit 4a16fb
			min_order = p->order;
Packit 4a16fb
			min_choices = choices;
Packit 4a16fb
			best_var = var;
Packit 4a16fb
		}
Packit 4a16fb
	}
Packit 4a16fb
	return best_var;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
int snd_pcm_hw_strategy_simple_next_value(snd_pcm_hw_params_t *params,
Packit 4a16fb
					  snd_pcm_hw_param_t var,
Packit 4a16fb
					  int value, int *dir,
Packit 4a16fb
					  snd_pcm_t *pcm,
Packit 4a16fb
					  const snd_pcm_hw_strategy_t *strategy)
Packit 4a16fb
{
Packit 4a16fb
	const snd_pcm_hw_strategy_simple_t *pars = strategy->private_data;
Packit 4a16fb
	assert(pars[var].valid);
Packit 4a16fb
	return pars[var].next_value(params, var, value, dir, pcm, &pars[var]);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
Packit 4a16fb
int snd_pcm_hw_strategy_simple_min_badness(const snd_pcm_hw_params_t *params,
Packit 4a16fb
					unsigned int max_badness,
Packit 4a16fb
					snd_pcm_t *pcm,
Packit 4a16fb
					const snd_pcm_hw_strategy_t *strategy)
Packit 4a16fb
{
Packit 4a16fb
	snd_pcm_hw_param_t var;
Packit 4a16fb
	unsigned int badness = 0;
Packit 4a16fb
	const snd_pcm_hw_strategy_simple_t *pars = strategy->private_data;
Packit 4a16fb
	for (var = 0; var <= SND_PCM_HW_PARAM_LAST_INTERVAL; ++var) {
Packit 4a16fb
		unsigned int b;
Packit 4a16fb
		if (!pars[var].valid)
Packit 4a16fb
			continue;
Packit 4a16fb
		b = pars[var].min_badness(params, var, pcm, &pars[var]);
Packit 4a16fb
		if (b > max_badness || max_badness - b < badness)
Packit 4a16fb
			return -E2BIG;
Packit 4a16fb
		badness += b;
Packit 4a16fb
	}
Packit 4a16fb
	return badness;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
Packit 4a16fb
void snd_pcm_hw_strategy_simple_near_free(snd_pcm_hw_strategy_simple_t *par)
Packit 4a16fb
{
Packit 4a16fb
	snd_pcm_hw_strategy_simple_near_t *p = par->private_data;
Packit 4a16fb
	free(p);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
unsigned int snd_pcm_hw_strategy_simple_near_min_badness(const snd_pcm_hw_params_t *params,
Packit 4a16fb
						      snd_pcm_hw_param_t var,
Packit 4a16fb
						      snd_pcm_t *pcm,
Packit 4a16fb
						      const snd_pcm_hw_strategy_simple_t *par)
Packit 4a16fb
{
Packit 4a16fb
	const snd_pcm_hw_strategy_simple_near_t *p = par->private_data;
Packit 4a16fb
	snd_pcm_hw_params_t params1 = *params;
Packit 4a16fb
	int value = snd_pcm_hw_param_set_near(pcm, &params1, var, p->best, 0);
Packit 4a16fb
	int diff;
Packit 4a16fb
	assert(value >= 0);
Packit 4a16fb
	diff = p->best - value;
Packit 4a16fb
	if (diff < 0)
Packit 4a16fb
		diff = -diff;
Packit 4a16fb
	return diff * p->mul;
Packit 4a16fb
}
Packit 4a16fb
	
Packit 4a16fb
int snd_pcm_hw_strategy_simple_near_next_value(snd_pcm_hw_params_t *params,
Packit 4a16fb
					       snd_pcm_hw_param_t var,
Packit 4a16fb
					       int value, int *dir,
Packit 4a16fb
					       snd_pcm_t *pcm,
Packit 4a16fb
					       const snd_pcm_hw_strategy_simple_t *par)
Packit 4a16fb
{
Packit 4a16fb
	const snd_pcm_hw_strategy_simple_near_t *p = par->private_data;
Packit 4a16fb
	if (value < 0) {
Packit 4a16fb
		*dir = 0;
Packit 4a16fb
		return snd_pcm_hw_param_set_near(pcm, params, var, p->best, dir);
Packit 4a16fb
	} else
Packit 4a16fb
		return snd_pcm_hw_param_set_next(pcm, params, var, p->best, 0, value, dir);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
void snd_pcm_hw_strategy_simple_choices_free(snd_pcm_hw_strategy_simple_t *par)
Packit 4a16fb
{
Packit 4a16fb
	snd_pcm_hw_strategy_simple_choices_t *p = par->private_data;
Packit 4a16fb
//	free(p->choices);
Packit 4a16fb
	free(p);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
unsigned int snd_pcm_hw_strategy_simple_choices_min_badness(const snd_pcm_hw_params_t *params,
Packit 4a16fb
							 snd_pcm_hw_param_t var,
Packit 4a16fb
							 snd_pcm_t *pcm,
Packit 4a16fb
							 const snd_pcm_hw_strategy_simple_t *par)
Packit 4a16fb
{
Packit 4a16fb
	const snd_pcm_hw_strategy_simple_choices_t *p = par->private_data;
Packit 4a16fb
	unsigned int k;
Packit 4a16fb
	for (k = 0; k < p->count; ++k) {
Packit 4a16fb
		if (snd_pcm_hw_param_set(pcm, (snd_pcm_hw_params_t *) params, SND_TEST, var, p->choices[k].value, 0))
Packit 4a16fb
			return p->choices[k].badness;
Packit 4a16fb
	}
Packit 4a16fb
	assert(0);
Packit 4a16fb
	return UINT_MAX;
Packit 4a16fb
}
Packit 4a16fb
	
Packit 4a16fb
int snd_pcm_hw_strategy_simple_choices_next_value(snd_pcm_hw_params_t *params,
Packit 4a16fb
						  snd_pcm_hw_param_t var,
Packit 4a16fb
						  int value, int *dir,
Packit 4a16fb
						  snd_pcm_t *pcm,
Packit 4a16fb
						  const snd_pcm_hw_strategy_simple_t *par)
Packit 4a16fb
{
Packit 4a16fb
	const snd_pcm_hw_strategy_simple_choices_t *p = par->private_data;
Packit 4a16fb
	unsigned int k = 0;
Packit 4a16fb
	if (value >= 0) {
Packit 4a16fb
		for (; k < p->count; ++k) {
Packit 4a16fb
			if (p->choices[k].value == (unsigned int) value) {
Packit 4a16fb
				k++;
Packit 4a16fb
				break;
Packit 4a16fb
			}
Packit 4a16fb
		}
Packit 4a16fb
	}
Packit 4a16fb
	for (; k < p->count; ++k) {
Packit 4a16fb
		unsigned int v = p->choices[k].value;
Packit 4a16fb
		int err = snd_pcm_hw_param_set(pcm, params, SND_TRY, var, v, 0);
Packit 4a16fb
		if (err < 0)
Packit 4a16fb
			continue;
Packit 4a16fb
		*dir = 0;
Packit 4a16fb
		return v;
Packit 4a16fb
	}
Packit 4a16fb
	return -1;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
void snd_pcm_hw_strategy_free(snd_pcm_hw_strategy_t *strategy)
Packit 4a16fb
{
Packit 4a16fb
	if (strategy->free)
Packit 4a16fb
		strategy->free(strategy);
Packit 4a16fb
	free(strategy);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
int snd_pcm_hw_strategy_simple(snd_pcm_hw_strategy_t **strategyp,
Packit 4a16fb
			    unsigned int badness_min,
Packit 4a16fb
			    unsigned int badness_max)
Packit 4a16fb
{
Packit 4a16fb
	snd_pcm_hw_strategy_simple_t *data;
Packit 4a16fb
	snd_pcm_hw_strategy_t *s;
Packit 4a16fb
	assert(strategyp);
Packit 4a16fb
	data = calloc(SND_PCM_HW_PARAM_LAST_INTERVAL + 1, sizeof(*data));
Packit 4a16fb
	if (!data)
Packit 4a16fb
		return -ENOMEM;
Packit 4a16fb
	s = calloc(1, sizeof(*s));
Packit 4a16fb
	if (!s) {
Packit 4a16fb
		free(data);
Packit 4a16fb
		return -ENOMEM;
Packit 4a16fb
	}
Packit 4a16fb
	s->choose_param = snd_pcm_hw_strategy_simple_choose_param;
Packit 4a16fb
	s->next_value = snd_pcm_hw_strategy_simple_next_value;
Packit 4a16fb
	s->min_badness = snd_pcm_hw_strategy_simple_min_badness;
Packit 4a16fb
	s->badness_min = badness_min;
Packit 4a16fb
	s->badness_max = badness_max;
Packit 4a16fb
	s->private_data = data;
Packit 4a16fb
	s->free = snd_pcm_hw_strategy_simple_free;
Packit 4a16fb
	*strategyp = s;
Packit 4a16fb
	return 0;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
int snd_pcm_hw_strategy_simple_near(snd_pcm_hw_strategy_t *strategy,
Packit 4a16fb
				 int order,
Packit 4a16fb
				 snd_pcm_hw_param_t var,
Packit 4a16fb
				 unsigned int best,
Packit 4a16fb
				 unsigned int mul)
Packit 4a16fb
{
Packit 4a16fb
	snd_pcm_hw_strategy_simple_t *s = strategy->private_data;
Packit 4a16fb
	snd_pcm_hw_strategy_simple_near_t *data;
Packit 4a16fb
	assert(strategy);
Packit 4a16fb
	assert(var <= SND_PCM_HW_PARAM_LAST_INTERVAL);
Packit 4a16fb
	assert(!s->valid);
Packit 4a16fb
	data = calloc(1, sizeof(*data));
Packit 4a16fb
	if (!data)
Packit 4a16fb
		return -ENOMEM;
Packit 4a16fb
	data->best = best;
Packit 4a16fb
	data->mul = mul;
Packit 4a16fb
	s += var;
Packit 4a16fb
	s->order = order;
Packit 4a16fb
	s->valid = 1;
Packit 4a16fb
	s->next_value = snd_pcm_hw_strategy_simple_near_next_value;
Packit 4a16fb
	s->min_badness = snd_pcm_hw_strategy_simple_near_min_badness;
Packit 4a16fb
	s->private_data = data;
Packit 4a16fb
	s->free = snd_pcm_hw_strategy_simple_near_free;
Packit 4a16fb
	return 0;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
int snd_pcm_hw_strategy_simple_choices(snd_pcm_hw_strategy_t *strategy,
Packit 4a16fb
				    int order,
Packit 4a16fb
				    snd_pcm_hw_param_t var,
Packit 4a16fb
				    unsigned int count,
Packit 4a16fb
				    snd_pcm_hw_strategy_simple_choices_list_t *choices)
Packit 4a16fb
{
Packit 4a16fb
	snd_pcm_hw_strategy_simple_t *s = strategy->private_data;
Packit 4a16fb
	snd_pcm_hw_strategy_simple_choices_t *data;
Packit 4a16fb
	assert(strategy);
Packit 4a16fb
	assert(var <= SND_PCM_HW_PARAM_LAST_INTERVAL);
Packit 4a16fb
	assert(!s->valid);
Packit 4a16fb
	data = calloc(1, sizeof(*data));
Packit 4a16fb
	if (!data)
Packit 4a16fb
		return -ENOMEM;
Packit 4a16fb
	data->count = count;
Packit 4a16fb
	data->choices = choices;
Packit 4a16fb
	s += var;
Packit 4a16fb
	s->valid = 1;
Packit 4a16fb
	s->order = order;
Packit 4a16fb
	s->next_value = snd_pcm_hw_strategy_simple_choices_next_value;
Packit 4a16fb
	s->min_badness = snd_pcm_hw_strategy_simple_choices_min_badness;
Packit 4a16fb
	s->private_data = data;
Packit 4a16fb
	s->free = snd_pcm_hw_strategy_simple_choices_free;
Packit 4a16fb
	return 0;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
int snd_pcm_hw_params_try_explain_failure1(snd_pcm_t *pcm,
Packit 4a16fb
					   snd_pcm_hw_params_t *fail,
Packit 4a16fb
					   snd_pcm_hw_params_t *success,
Packit 4a16fb
					   unsigned int depth,
Packit 4a16fb
					   snd_output_t *out)
Packit 4a16fb
{
Packit 4a16fb
	snd_pcm_hw_param_t var;
Packit 4a16fb
	snd_pcm_hw_params_t i;
Packit 4a16fb
	if (depth < 1)
Packit 4a16fb
		return -ENOENT;
Packit 4a16fb
	for (var = 0; var <= SND_PCM_HW_PARAM_LAST_INTERVAL; var++) {
Packit 4a16fb
		int err;
Packit 4a16fb
		i = *success;
Packit 4a16fb
		_snd_pcm_hw_param_copy(&i, var, fail);
Packit 4a16fb
		err = snd_pcm_hw_refine(pcm, &i);
Packit 4a16fb
		if (err == 0 && 
Packit 4a16fb
		    snd_pcm_hw_params_try_explain_failure1(pcm, fail, &i, depth - 1, out) < 0)
Packit 4a16fb
			continue;
Packit 4a16fb
		snd_output_printf(out, "%s: ", snd_pcm_hw_param_name(var));
Packit 4a16fb
		snd_pcm_hw_param_dump(fail, var, out);
Packit 4a16fb
		snd_output_putc(out, '\n');
Packit 4a16fb
		return 0;
Packit 4a16fb
	}
Packit 4a16fb
	return -ENOENT;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
int snd_pcm_hw_params_try_explain_failure(snd_pcm_t *pcm,
Packit 4a16fb
					  snd_pcm_hw_params_t *fail,
Packit 4a16fb
					  snd_pcm_hw_params_t *success,
Packit 4a16fb
					  unsigned int depth,
Packit 4a16fb
					  snd_output_t *out)
Packit 4a16fb
{
Packit 4a16fb
	snd_pcm_hw_params_t i, any;
Packit 4a16fb
	int err;
Packit 4a16fb
	snd_pcm_hw_param_t var;
Packit 4a16fb
	int done = 0;
Packit 4a16fb
	assert(pcm && fail);
Packit 4a16fb
	for (var = 0; var <= SND_PCM_HW_PARAM_LAST_INTERVAL; var++) {
Packit 4a16fb
		if (!snd_pcm_hw_param_empty(fail, var))
Packit 4a16fb
			continue;
Packit 4a16fb
		snd_output_printf(out, "%s is empty\n", snd_pcm_hw_param_name(var));
Packit 4a16fb
		done = 1;
Packit 4a16fb
	}
Packit 4a16fb
	if (done)
Packit 4a16fb
		return 0;
Packit 4a16fb
	i = *fail;
Packit 4a16fb
	err = snd_pcm_hw_refine(pcm, &i);
Packit 4a16fb
	if (err == 0) {
Packit 4a16fb
		snd_output_printf(out, "Configuration is virtually correct\n");
Packit 4a16fb
		return 0;
Packit 4a16fb
	}
Packit 4a16fb
	if (!success) {
Packit 4a16fb
		snd_pcm_hw_params_any(pcm, &any;;
Packit 4a16fb
		success = &any;
Packit 4a16fb
	}
Packit 4a16fb
	return snd_pcm_hw_params_try_explain_failure1(pcm, fail, success, depth, out);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
#endif
Packit 4a16fb
Packit 4a16fb
typedef struct _snd_pcm_hw_rule snd_pcm_hw_rule_t;
Packit 4a16fb
Packit 4a16fb
typedef int (*snd_pcm_hw_rule_func_t)(snd_pcm_hw_params_t *params,
Packit 4a16fb
				      const snd_pcm_hw_rule_t *rule);
Packit 4a16fb
Packit 4a16fb
struct _snd_pcm_hw_rule {
Packit 4a16fb
	int var;
Packit 4a16fb
	snd_pcm_hw_rule_func_t func;
Packit 4a16fb
	int deps[4];
Packit 4a16fb
	void *private_data;
Packit 4a16fb
};
Packit 4a16fb
Packit 4a16fb
static int snd_pcm_hw_rule_mul(snd_pcm_hw_params_t *params,
Packit 4a16fb
			       const snd_pcm_hw_rule_t *rule)
Packit 4a16fb
{
Packit 4a16fb
	snd_interval_t t;
Packit 4a16fb
	snd_interval_mul(hw_param_interval_c(params, rule->deps[0]),
Packit 4a16fb
		     hw_param_interval_c(params, rule->deps[1]), &t);
Packit 4a16fb
	return snd_interval_refine(hw_param_interval(params, rule->var), &t);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
static int snd_pcm_hw_rule_div(snd_pcm_hw_params_t *params,
Packit 4a16fb
			const snd_pcm_hw_rule_t *rule)
Packit 4a16fb
{
Packit 4a16fb
	snd_interval_t t;
Packit 4a16fb
	snd_interval_div(hw_param_interval_c(params, rule->deps[0]),
Packit 4a16fb
		     hw_param_interval_c(params, rule->deps[1]), &t);
Packit 4a16fb
	return snd_interval_refine(hw_param_interval(params, rule->var), &t);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
static int snd_pcm_hw_rule_muldivk(snd_pcm_hw_params_t *params,
Packit 4a16fb
				   const snd_pcm_hw_rule_t *rule)
Packit 4a16fb
{
Packit 4a16fb
	snd_interval_t t;
Packit 4a16fb
	snd_interval_muldivk(hw_param_interval_c(params, rule->deps[0]),
Packit 4a16fb
			 hw_param_interval_c(params, rule->deps[1]),
Packit 4a16fb
			 (unsigned long) rule->private_data, &t);
Packit 4a16fb
	return snd_interval_refine(hw_param_interval(params, rule->var), &t);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
static int snd_pcm_hw_rule_mulkdiv(snd_pcm_hw_params_t *params,
Packit 4a16fb
				   const snd_pcm_hw_rule_t *rule)
Packit 4a16fb
{
Packit 4a16fb
	snd_interval_t t;
Packit 4a16fb
	snd_interval_mulkdiv(hw_param_interval_c(params, rule->deps[0]),
Packit 4a16fb
			 (unsigned long) rule->private_data,
Packit 4a16fb
			 hw_param_interval_c(params, rule->deps[1]), &t);
Packit 4a16fb
	return snd_interval_refine(hw_param_interval(params, rule->var), &t);
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
static int snd_pcm_hw_rule_format(snd_pcm_hw_params_t *params,
Packit 4a16fb
				  const snd_pcm_hw_rule_t *rule)
Packit 4a16fb
{
Packit 4a16fb
	int changed = 0;
Packit 4a16fb
	snd_pcm_format_t k;
Packit 4a16fb
	snd_mask_t *mask = hw_param_mask(params, rule->var);
Packit 4a16fb
	snd_interval_t *i = hw_param_interval(params, rule->deps[0]);
Packit 4a16fb
	for (k = 0; k <= SND_PCM_FORMAT_LAST; k++) {
Packit 4a16fb
		int bits;
Packit 4a16fb
		if (!snd_pcm_format_mask_test(mask, k))
Packit 4a16fb
			continue;
Packit 4a16fb
		bits = snd_pcm_format_physical_width(k);
Packit 4a16fb
		if (bits < 0)
Packit 4a16fb
			continue;
Packit 4a16fb
		if (!snd_interval_test(i, (unsigned int) bits)) {
Packit 4a16fb
			snd_pcm_format_mask_reset(mask, k);
Packit 4a16fb
			if (snd_mask_empty(mask))
Packit 4a16fb
				return -EINVAL;
Packit 4a16fb
			changed = 1;
Packit 4a16fb
		}
Packit 4a16fb
	}
Packit 4a16fb
	return changed;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
Packit 4a16fb
static int snd_pcm_hw_rule_sample_bits(snd_pcm_hw_params_t *params,
Packit 4a16fb
				       const snd_pcm_hw_rule_t *rule)
Packit 4a16fb
{
Packit 4a16fb
	unsigned int min, max;
Packit 4a16fb
	snd_pcm_format_t k;
Packit 4a16fb
	snd_interval_t *i = hw_param_interval(params, rule->var);
Packit 4a16fb
	snd_mask_t *mask = hw_param_mask(params, rule->deps[0]);
Packit 4a16fb
	int c, changed = 0;
Packit 4a16fb
	min = UINT_MAX;
Packit 4a16fb
	max = 0;
Packit 4a16fb
	for (k = 0; k <= SND_PCM_FORMAT_LAST; k++) {
Packit 4a16fb
		int bits;
Packit 4a16fb
		if (!snd_pcm_format_mask_test(mask, k))
Packit 4a16fb
			continue;
Packit 4a16fb
		bits = snd_pcm_format_physical_width(k);
Packit 4a16fb
		if (bits < 0)
Packit 4a16fb
			continue;
Packit 4a16fb
		if (min > (unsigned)bits)
Packit 4a16fb
			min = bits;
Packit 4a16fb
		if (max < (unsigned)bits)
Packit 4a16fb
			max = bits;
Packit 4a16fb
	}
Packit 4a16fb
	c = snd_interval_refine_min(i, min, 0);
Packit 4a16fb
	if (c < 0)
Packit 4a16fb
		return c;
Packit 4a16fb
	if (c)
Packit 4a16fb
		changed = 1;
Packit 4a16fb
	c = snd_interval_refine_max(i, max, 0);
Packit 4a16fb
	if (c < 0)
Packit 4a16fb
		return c;
Packit 4a16fb
	if (c)
Packit 4a16fb
		changed = 1;
Packit 4a16fb
	return changed;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
static const snd_pcm_hw_rule_t refine_rules[] = {
Packit 4a16fb
	{
Packit 4a16fb
		.var = SND_PCM_HW_PARAM_FORMAT,
Packit 4a16fb
		.func = snd_pcm_hw_rule_format,
Packit 4a16fb
		.deps = { SND_PCM_HW_PARAM_SAMPLE_BITS, -1 },
Packit 4a16fb
		.private_data = 0,
Packit 4a16fb
	},
Packit 4a16fb
	{
Packit 4a16fb
		.var = SND_PCM_HW_PARAM_SAMPLE_BITS, 
Packit 4a16fb
		.func = snd_pcm_hw_rule_sample_bits,
Packit 4a16fb
		.deps = { SND_PCM_HW_PARAM_FORMAT, 
Packit 4a16fb
			SND_PCM_HW_PARAM_SAMPLE_BITS, -1 },
Packit 4a16fb
		.private_data = 0,
Packit 4a16fb
	},
Packit 4a16fb
	{
Packit 4a16fb
		.var = SND_PCM_HW_PARAM_SAMPLE_BITS, 
Packit 4a16fb
		.func = snd_pcm_hw_rule_div,
Packit 4a16fb
		.deps = { SND_PCM_HW_PARAM_FRAME_BITS,
Packit 4a16fb
			SND_PCM_HW_PARAM_CHANNELS, -1 },
Packit 4a16fb
		.private_data = 0,
Packit 4a16fb
	},
Packit 4a16fb
	{
Packit 4a16fb
		.var = SND_PCM_HW_PARAM_FRAME_BITS, 
Packit 4a16fb
		.func = snd_pcm_hw_rule_mul,
Packit 4a16fb
		.deps = { SND_PCM_HW_PARAM_SAMPLE_BITS,
Packit 4a16fb
			SND_PCM_HW_PARAM_CHANNELS, -1 },
Packit 4a16fb
		.private_data = 0,
Packit 4a16fb
	},
Packit 4a16fb
	{
Packit 4a16fb
		.var = SND_PCM_HW_PARAM_FRAME_BITS, 
Packit 4a16fb
		.func = snd_pcm_hw_rule_mulkdiv,
Packit 4a16fb
		.deps = { SND_PCM_HW_PARAM_PERIOD_BYTES,
Packit 4a16fb
			SND_PCM_HW_PARAM_PERIOD_SIZE, -1 },
Packit 4a16fb
		.private_data = (void*) 8,
Packit 4a16fb
	},
Packit 4a16fb
	{
Packit 4a16fb
		.var = SND_PCM_HW_PARAM_FRAME_BITS, 
Packit 4a16fb
		.func = snd_pcm_hw_rule_mulkdiv,
Packit 4a16fb
		.deps = { SND_PCM_HW_PARAM_BUFFER_BYTES,
Packit 4a16fb
			SND_PCM_HW_PARAM_BUFFER_SIZE, -1 },
Packit 4a16fb
		.private_data = (void*) 8,
Packit 4a16fb
	},
Packit 4a16fb
	{
Packit 4a16fb
		.var = SND_PCM_HW_PARAM_CHANNELS, 
Packit 4a16fb
		.func = snd_pcm_hw_rule_div,
Packit 4a16fb
		.deps = { SND_PCM_HW_PARAM_FRAME_BITS,
Packit 4a16fb
			SND_PCM_HW_PARAM_SAMPLE_BITS, -1 },
Packit 4a16fb
		.private_data = 0,
Packit 4a16fb
	},
Packit 4a16fb
	{
Packit 4a16fb
		.var = SND_PCM_HW_PARAM_RATE, 
Packit 4a16fb
		.func = snd_pcm_hw_rule_mulkdiv,
Packit 4a16fb
		.deps = { SND_PCM_HW_PARAM_PERIOD_SIZE,
Packit 4a16fb
			SND_PCM_HW_PARAM_PERIOD_TIME, -1 },
Packit 4a16fb
		.private_data = (void*) 1000000,
Packit 4a16fb
	},
Packit 4a16fb
	{
Packit 4a16fb
		.var = SND_PCM_HW_PARAM_RATE, 
Packit 4a16fb
		.func = snd_pcm_hw_rule_mulkdiv,
Packit 4a16fb
		.deps = { SND_PCM_HW_PARAM_BUFFER_SIZE,
Packit 4a16fb
			SND_PCM_HW_PARAM_BUFFER_TIME, -1 },
Packit 4a16fb
		.private_data = (void*) 1000000,
Packit 4a16fb
	},
Packit 4a16fb
	{
Packit 4a16fb
		.var = SND_PCM_HW_PARAM_PERIODS, 
Packit 4a16fb
		.func = snd_pcm_hw_rule_div,
Packit 4a16fb
		.deps = { SND_PCM_HW_PARAM_BUFFER_SIZE,
Packit 4a16fb
			SND_PCM_HW_PARAM_PERIOD_SIZE, -1 },
Packit 4a16fb
		.private_data = 0,
Packit 4a16fb
	},
Packit 4a16fb
	{
Packit 4a16fb
		.var = SND_PCM_HW_PARAM_PERIOD_SIZE, 
Packit 4a16fb
		.func = snd_pcm_hw_rule_div,
Packit 4a16fb
		.deps = { SND_PCM_HW_PARAM_BUFFER_SIZE,
Packit 4a16fb
			SND_PCM_HW_PARAM_PERIODS, -1 },
Packit 4a16fb
		.private_data = 0,
Packit 4a16fb
	},
Packit 4a16fb
	{
Packit 4a16fb
		.var = SND_PCM_HW_PARAM_PERIOD_SIZE, 
Packit 4a16fb
		.func = snd_pcm_hw_rule_mulkdiv,
Packit 4a16fb
		.deps = { SND_PCM_HW_PARAM_PERIOD_BYTES,
Packit 4a16fb
			SND_PCM_HW_PARAM_FRAME_BITS, -1 },
Packit 4a16fb
		.private_data = (void*) 8,
Packit 4a16fb
	},
Packit 4a16fb
	{
Packit 4a16fb
		.var = SND_PCM_HW_PARAM_PERIOD_SIZE, 
Packit 4a16fb
		.func = snd_pcm_hw_rule_muldivk,
Packit 4a16fb
		.deps = { SND_PCM_HW_PARAM_PERIOD_TIME,
Packit 4a16fb
			SND_PCM_HW_PARAM_RATE, -1 },
Packit 4a16fb
		.private_data = (void*) 1000000,
Packit 4a16fb
	},
Packit 4a16fb
	{
Packit 4a16fb
		.var = SND_PCM_HW_PARAM_BUFFER_SIZE, 
Packit 4a16fb
		.func = snd_pcm_hw_rule_mul,
Packit 4a16fb
		.deps = { SND_PCM_HW_PARAM_PERIOD_SIZE,
Packit 4a16fb
			SND_PCM_HW_PARAM_PERIODS, -1 },
Packit 4a16fb
		.private_data = 0,
Packit 4a16fb
	},
Packit 4a16fb
	{
Packit 4a16fb
		.var = SND_PCM_HW_PARAM_BUFFER_SIZE, 
Packit 4a16fb
		.func = snd_pcm_hw_rule_mulkdiv,
Packit 4a16fb
		.deps = { SND_PCM_HW_PARAM_BUFFER_BYTES,
Packit 4a16fb
			SND_PCM_HW_PARAM_FRAME_BITS, -1 },
Packit 4a16fb
		.private_data = (void*) 8,
Packit 4a16fb
	},
Packit 4a16fb
	{
Packit 4a16fb
		.var = SND_PCM_HW_PARAM_BUFFER_SIZE, 
Packit 4a16fb
		.func = snd_pcm_hw_rule_muldivk,
Packit 4a16fb
		.deps = { SND_PCM_HW_PARAM_BUFFER_TIME,
Packit 4a16fb
			SND_PCM_HW_PARAM_RATE, -1 },
Packit 4a16fb
		.private_data = (void*) 1000000,
Packit 4a16fb
	},
Packit 4a16fb
	{
Packit 4a16fb
		.var = SND_PCM_HW_PARAM_PERIOD_BYTES, 
Packit 4a16fb
		.func = snd_pcm_hw_rule_muldivk,
Packit 4a16fb
		.deps = { SND_PCM_HW_PARAM_PERIOD_SIZE,
Packit 4a16fb
			SND_PCM_HW_PARAM_FRAME_BITS, -1 },
Packit 4a16fb
		.private_data = (void*) 8,
Packit 4a16fb
	},
Packit 4a16fb
	{
Packit 4a16fb
		.var = SND_PCM_HW_PARAM_BUFFER_BYTES, 
Packit 4a16fb
		.func = snd_pcm_hw_rule_muldivk,
Packit 4a16fb
		.deps = { SND_PCM_HW_PARAM_BUFFER_SIZE,
Packit 4a16fb
			SND_PCM_HW_PARAM_FRAME_BITS, -1 },
Packit 4a16fb
		.private_data = (void*) 8,
Packit 4a16fb
	},
Packit 4a16fb
	{
Packit 4a16fb
		.var = SND_PCM_HW_PARAM_PERIOD_TIME, 
Packit 4a16fb
		.func = snd_pcm_hw_rule_mulkdiv,
Packit 4a16fb
		.deps = { SND_PCM_HW_PARAM_PERIOD_SIZE,
Packit 4a16fb
			SND_PCM_HW_PARAM_RATE, -1 },
Packit 4a16fb
		.private_data = (void*) 1000000,
Packit 4a16fb
	},
Packit 4a16fb
	{
Packit 4a16fb
		.var = SND_PCM_HW_PARAM_BUFFER_TIME, 
Packit 4a16fb
		.func = snd_pcm_hw_rule_mulkdiv,
Packit 4a16fb
		.deps = { SND_PCM_HW_PARAM_BUFFER_SIZE,
Packit 4a16fb
			SND_PCM_HW_PARAM_RATE, -1 },
Packit 4a16fb
		.private_data = (void*) 1000000,
Packit 4a16fb
	},
Packit 4a16fb
};
Packit 4a16fb
Packit 4a16fb
#define RULES (sizeof(refine_rules) / sizeof(refine_rules[0]))
Packit 4a16fb
#define PCM_BIT(x) \
Packit 4a16fb
	(1U << ((x) < 32 ? (x) : ((x) - 32)))
Packit 4a16fb
Packit 4a16fb
static const snd_mask_t refine_masks[SND_PCM_HW_PARAM_LAST_MASK - SND_PCM_HW_PARAM_FIRST_MASK + 1] = {
Packit 4a16fb
	[SND_PCM_HW_PARAM_ACCESS - SND_PCM_HW_PARAM_FIRST_MASK] = {
Packit 4a16fb
		.bits = {
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_ACCESS_MMAP_COMPLEX) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_ACCESS_RW_INTERLEAVED) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
Packit 4a16fb
		},
Packit 4a16fb
	},
Packit 4a16fb
	[SND_PCM_HW_PARAM_FORMAT - SND_PCM_HW_PARAM_FIRST_MASK] = {
Packit 4a16fb
		.bits = {
Packit 4a16fb
			/* first 32bits */
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_S8) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_U8) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_S16_LE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_S16_BE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_U16_LE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_U16_BE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_S24_LE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_S24_BE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_U24_LE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_U24_BE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_S32_LE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_S32_BE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_U32_LE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_U32_BE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_FLOAT_LE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_FLOAT_BE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_FLOAT64_LE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_FLOAT64_BE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_IEC958_SUBFRAME) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_IEC958_SUBFRAME) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_MU_LAW) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_A_LAW) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_IMA_ADPCM) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_MPEG) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_GSM) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_S20_LE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_S20_BE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_U20_LE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_U20_BE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_SPECIAL),
Packit 4a16fb
			/* second 32bits */
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_S24_3LE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_S24_3BE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_U24_3LE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_U24_3BE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_S20_3LE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_S20_3BE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_U20_3LE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_U20_3BE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_S18_3LE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_S18_3BE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_U18_3LE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_U18_3BE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_G723_24) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_G723_24) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_G723_40) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_G723_40) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_DSD_U8) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_DSD_U16_LE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_DSD_U32_LE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_DSD_U16_BE) |
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_FORMAT_DSD_U32_BE)
Packit 4a16fb
		},
Packit 4a16fb
	},
Packit 4a16fb
	[SND_PCM_HW_PARAM_SUBFORMAT - SND_PCM_HW_PARAM_FIRST_MASK] = {
Packit 4a16fb
		.bits = {
Packit 4a16fb
			PCM_BIT(SNDRV_PCM_SUBFORMAT_STD)
Packit 4a16fb
		},
Packit 4a16fb
	},
Packit 4a16fb
};
Packit 4a16fb
  
Packit 4a16fb
static const snd_interval_t refine_intervals[SND_PCM_HW_PARAM_LAST_INTERVAL - SND_PCM_HW_PARAM_FIRST_INTERVAL + 1] = {
Packit 4a16fb
	[SND_PCM_HW_PARAM_SAMPLE_BITS - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
Packit 4a16fb
		.min = 1, .max = UINT_MAX,
Packit 4a16fb
		.openmin = 0, .openmax = 0, .integer = 1, .empty = 0,
Packit 4a16fb
	},
Packit 4a16fb
	[SND_PCM_HW_PARAM_FRAME_BITS - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
Packit 4a16fb
		.min = 1, .max = UINT_MAX,
Packit 4a16fb
		.openmin = 0, .openmax = 0, .integer = 1, .empty = 0,
Packit 4a16fb
	},
Packit 4a16fb
	[SND_PCM_HW_PARAM_CHANNELS - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
Packit 4a16fb
		.min = 1, .max = UINT_MAX,
Packit 4a16fb
		.openmin = 0, .openmax = 0, .integer = 1, .empty = 0,
Packit 4a16fb
	},
Packit 4a16fb
	[SND_PCM_HW_PARAM_RATE - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
Packit 4a16fb
		.min = 1, .max = UINT_MAX,
Packit 4a16fb
		.openmin = 0, .openmax = 0, .integer = 0, .empty = 0,
Packit 4a16fb
	},
Packit 4a16fb
	[SND_PCM_HW_PARAM_PERIOD_TIME - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
Packit 4a16fb
		.min = 0, .max = UINT_MAX,
Packit 4a16fb
		.openmin = 0, .openmax = 0, .integer = 0, .empty = 0,
Packit 4a16fb
	},
Packit 4a16fb
	[SND_PCM_HW_PARAM_PERIOD_SIZE - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
Packit 4a16fb
		.min = 0, .max = UINT_MAX,
Packit 4a16fb
		.openmin = 0, .openmax = 0, .integer = 0, .empty = 0,
Packit 4a16fb
	},
Packit 4a16fb
	[SND_PCM_HW_PARAM_PERIOD_BYTES - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
Packit 4a16fb
		.min = 0, .max = UINT_MAX,
Packit 4a16fb
		.openmin = 0, .openmax = 0, .integer = 0, .empty = 0,
Packit 4a16fb
	},
Packit 4a16fb
	[SND_PCM_HW_PARAM_PERIODS - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
Packit 4a16fb
		.min = 0, .max = UINT_MAX,
Packit 4a16fb
		.openmin = 0, .openmax = 0, .integer = 0, .empty = 0,
Packit 4a16fb
	},
Packit 4a16fb
	[SND_PCM_HW_PARAM_BUFFER_TIME - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
Packit 4a16fb
		.min = 1, .max = UINT_MAX,
Packit 4a16fb
		.openmin = 0, .openmax = 0, .integer = 0, .empty = 0,
Packit 4a16fb
	},
Packit 4a16fb
	[SND_PCM_HW_PARAM_BUFFER_SIZE - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
Packit 4a16fb
		.min = 1, .max = UINT_MAX,
Packit 4a16fb
		.openmin = 0, .openmax = 0, .integer = 1, .empty = 0,
Packit 4a16fb
	},
Packit 4a16fb
	[SND_PCM_HW_PARAM_BUFFER_BYTES - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
Packit 4a16fb
		.min = 1, .max = UINT_MAX,
Packit 4a16fb
		.openmin = 0, .openmax = 0, .integer = 1, .empty = 0,
Packit 4a16fb
	},
Packit 4a16fb
	[SND_PCM_HW_PARAM_TICK_TIME - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
Packit 4a16fb
		.min = 0, .max = UINT_MAX,
Packit 4a16fb
		.openmin = 0, .openmax = 0, .integer = 0, .empty = 0,
Packit 4a16fb
	},
Packit 4a16fb
};
Packit 4a16fb
Packit 4a16fb
#if 0
Packit 4a16fb
#define RULES_DEBUG
Packit 4a16fb
#endif
Packit 4a16fb
Packit 4a16fb
int snd_pcm_hw_refine_soft(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params)
Packit 4a16fb
{
Packit 4a16fb
	unsigned int k;
Packit 4a16fb
	snd_interval_t *i;
Packit 4a16fb
	unsigned int rstamps[RULES];
Packit 4a16fb
	unsigned int vstamps[SND_PCM_HW_PARAM_LAST_INTERVAL + 1];
Packit 4a16fb
	unsigned int stamp = 2;
Packit 4a16fb
	int changed, again;
Packit 4a16fb
#ifdef RULES_DEBUG
Packit 4a16fb
	snd_output_t *log;
Packit 4a16fb
	snd_output_stdio_attach(&log, stderr, 0);
Packit 4a16fb
	snd_output_printf(log, "refine_soft '%s' (begin)\n", pcm->name);
Packit 4a16fb
	snd_pcm_hw_params_dump(params, log);
Packit 4a16fb
#endif
Packit 4a16fb
Packit 4a16fb
	for (k = SND_PCM_HW_PARAM_FIRST_MASK; k <= SND_PCM_HW_PARAM_LAST_MASK; k++) {
Packit 4a16fb
		if (!(params->rmask & (1 << k)))
Packit 4a16fb
			continue;
Packit 4a16fb
		changed = snd_mask_refine(hw_param_mask(params, k),
Packit 4a16fb
					  &refine_masks[k - SND_PCM_HW_PARAM_FIRST_MASK]);
Packit 4a16fb
		if (changed)
Packit 4a16fb
			params->cmask |= 1 << k;
Packit 4a16fb
		if (changed < 0)
Packit 4a16fb
			goto _err;
Packit 4a16fb
	}
Packit 4a16fb
Packit 4a16fb
	for (k = SND_PCM_HW_PARAM_FIRST_INTERVAL; k <= SND_PCM_HW_PARAM_LAST_INTERVAL; k++) {
Packit 4a16fb
		if (!(params->rmask & (1 << k)))
Packit 4a16fb
			continue;
Packit 4a16fb
		changed = snd_interval_refine(hw_param_interval(params, k),
Packit 4a16fb
				      &refine_intervals[k - SND_PCM_HW_PARAM_FIRST_INTERVAL]);
Packit 4a16fb
		if (changed)
Packit 4a16fb
			params->cmask |= 1 << k;
Packit 4a16fb
		if (changed < 0)
Packit 4a16fb
			goto _err;
Packit 4a16fb
	}
Packit 4a16fb
Packit 4a16fb
	for (k = 0; k < RULES; k++)
Packit 4a16fb
		rstamps[k] = 0;
Packit 4a16fb
	for (k = 0; k <= SND_PCM_HW_PARAM_LAST_INTERVAL; k++)
Packit 4a16fb
		vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0;
Packit 4a16fb
	do {
Packit 4a16fb
		again = 0;
Packit 4a16fb
		for (k = 0; k < RULES; k++) {
Packit 4a16fb
			const snd_pcm_hw_rule_t *r = &refine_rules[k];
Packit 4a16fb
			unsigned int d;
Packit 4a16fb
			int doit = 0;
Packit 4a16fb
			for (d = 0; r->deps[d] >= 0; d++) {
Packit 4a16fb
				if (vstamps[r->deps[d]] > rstamps[k]) {
Packit 4a16fb
					doit = 1;
Packit 4a16fb
					break;
Packit 4a16fb
				}
Packit 4a16fb
			}
Packit 4a16fb
			if (!doit)
Packit 4a16fb
				continue;
Packit 4a16fb
#ifdef RULES_DEBUG
Packit 4a16fb
			snd_output_printf(log, "Rule %d (%p): ", k, r->func);
Packit 4a16fb
			if (r->var >= 0) {
Packit 4a16fb
				snd_output_printf(log, "%s=", snd_pcm_hw_param_name(r->var));
Packit 4a16fb
				snd_pcm_hw_param_dump(params, r->var, log);
Packit 4a16fb
				snd_output_puts(log, " -> ");
Packit 4a16fb
			}
Packit 4a16fb
#endif
Packit 4a16fb
			changed = r->func(params, r);
Packit 4a16fb
#ifdef RULES_DEBUG
Packit 4a16fb
			if (r->var >= 0)
Packit 4a16fb
				snd_pcm_hw_param_dump(params, r->var, log);
Packit 4a16fb
			for (d = 0; r->deps[d] >= 0; d++) {
Packit 4a16fb
				snd_output_printf(log, " %s=", snd_pcm_hw_param_name(r->deps[d]));
Packit 4a16fb
				snd_pcm_hw_param_dump(params, r->deps[d], log);
Packit 4a16fb
			}
Packit 4a16fb
			snd_output_putc(log, '\n');
Packit 4a16fb
#endif
Packit 4a16fb
			rstamps[k] = stamp;
Packit 4a16fb
			if (changed && r->var >= 0) {
Packit 4a16fb
				params->cmask |= 1 << r->var;
Packit 4a16fb
				vstamps[r->var] = stamp;
Packit 4a16fb
				again = 1;
Packit 4a16fb
			}
Packit 4a16fb
			if (changed < 0)
Packit 4a16fb
				goto _err;
Packit 4a16fb
			stamp++;
Packit 4a16fb
		}
Packit 4a16fb
	} while (again);
Packit 4a16fb
	if (!params->msbits) {
Packit 4a16fb
		i = hw_param_interval(params, SND_PCM_HW_PARAM_SAMPLE_BITS);
Packit 4a16fb
		if (snd_interval_single(i))
Packit 4a16fb
			params->msbits = snd_interval_value(i);
Packit 4a16fb
	}
Packit 4a16fb
Packit 4a16fb
	if (!params->rate_den) {
Packit 4a16fb
		i = hw_param_interval(params, SND_PCM_HW_PARAM_RATE);
Packit 4a16fb
		if (snd_interval_single(i)) {
Packit 4a16fb
			params->rate_num = snd_interval_value(i);
Packit 4a16fb
			params->rate_den = 1;
Packit 4a16fb
		}
Packit 4a16fb
	}
Packit 4a16fb
	params->rmask = 0;
Packit 4a16fb
	return 0;
Packit 4a16fb
 _err:
Packit 4a16fb
#ifdef RULES_DEBUG
Packit 4a16fb
	snd_output_printf(log, "refine_soft '%s' (end-%i)\n", pcm->name, changed);
Packit 4a16fb
	snd_pcm_hw_params_dump(params, log);
Packit 4a16fb
	snd_output_close(log);
Packit 4a16fb
#endif
Packit 4a16fb
	return changed;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
int _snd_pcm_hw_params_refine(snd_pcm_hw_params_t *params,
Packit 4a16fb
			      unsigned int vars,
Packit 4a16fb
			      const snd_pcm_hw_params_t *src)
Packit 4a16fb
{
Packit 4a16fb
	int changed, err = 0;
Packit 4a16fb
	unsigned int k;
Packit 4a16fb
	for (k = 0; k <= SND_PCM_HW_PARAM_LAST_INTERVAL; ++k) {
Packit 4a16fb
		if (!(vars & (1 << k)))
Packit 4a16fb
			continue;
Packit 4a16fb
		changed = _snd_pcm_hw_param_refine(params, k, src);
Packit 4a16fb
		if (changed < 0)
Packit 4a16fb
			err = changed;
Packit 4a16fb
	}
Packit 4a16fb
	params->info &= src->info;
Packit 4a16fb
	params->flags = src->flags; /* propagate all flags to slave */
Packit 4a16fb
	return err;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
int snd_pcm_hw_refine_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
Packit 4a16fb
			    int (*cprepare)(snd_pcm_t *pcm,
Packit 4a16fb
					    snd_pcm_hw_params_t *params),
Packit 4a16fb
			    int (*cchange)(snd_pcm_t *pcm,
Packit 4a16fb
					   snd_pcm_hw_params_t *params,
Packit 4a16fb
					   snd_pcm_hw_params_t *sparams),
Packit 4a16fb
			    int (*sprepare)(snd_pcm_t *pcm,
Packit 4a16fb
					    snd_pcm_hw_params_t *params),
Packit 4a16fb
			    int (*schange)(snd_pcm_t *pcm,
Packit 4a16fb
					   snd_pcm_hw_params_t *params,
Packit 4a16fb
					   snd_pcm_hw_params_t *sparams),
Packit 4a16fb
			    int (*srefine)(snd_pcm_t *pcm,
Packit 4a16fb
					   snd_pcm_hw_params_t *sparams))
Packit 4a16fb
Packit 4a16fb
{
Packit 4a16fb
#ifdef RULES_DEBUG
Packit 4a16fb
	snd_output_t *log;
Packit 4a16fb
#endif
Packit 4a16fb
	snd_pcm_hw_params_t sparams;
Packit 4a16fb
	int err;
Packit 4a16fb
	unsigned int cmask, changed;
Packit 4a16fb
#ifdef RULES_DEBUG
Packit 4a16fb
	snd_output_stdio_attach(&log, stderr, 0);
Packit 4a16fb
#endif
Packit 4a16fb
	err = cprepare(pcm, params);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		return err;
Packit 4a16fb
	err = sprepare(pcm, &sparams);
Packit 4a16fb
	if (err < 0) {
Packit 4a16fb
		SNDERR("Slave PCM not usable");
Packit 4a16fb
		return err;
Packit 4a16fb
	}
Packit 4a16fb
#ifdef RULES_DEBUG
Packit 4a16fb
	snd_output_printf(log, "hw_refine_slave - enter '%s'\n", pcm->name);
Packit 4a16fb
#endif
Packit 4a16fb
	do {
Packit 4a16fb
		cmask = params->cmask;
Packit 4a16fb
		params->cmask = 0;
Packit 4a16fb
#ifdef RULES_DEBUG
Packit 4a16fb
		snd_output_printf(log, "schange '%s' (client)\n", pcm->name);
Packit 4a16fb
		snd_pcm_hw_params_dump(params, log);
Packit 4a16fb
		snd_output_printf(log, "schange '%s' (slave)\n", pcm->name);
Packit 4a16fb
		snd_pcm_hw_params_dump(&sparams, log);
Packit 4a16fb
#endif
Packit 4a16fb
		err = schange(pcm, params, &sparams);
Packit 4a16fb
		if (err >= 0) {
Packit 4a16fb
#ifdef RULES_DEBUG
Packit 4a16fb
			snd_output_printf(log, "srefine '%s' (client)\n", pcm->name);
Packit 4a16fb
			snd_pcm_hw_params_dump(params, log);
Packit 4a16fb
			snd_output_printf(log, "srefine '%s' (slave)\n", pcm->name);
Packit 4a16fb
			snd_pcm_hw_params_dump(&sparams, log);
Packit 4a16fb
#endif
Packit 4a16fb
			err = srefine(pcm, &sparams);
Packit 4a16fb
			if (err < 0) {
Packit 4a16fb
#ifdef RULES_DEBUG
Packit 4a16fb
				snd_output_printf(log, "srefine '%s', err < 0 (%i) (client)\n", pcm->name, err);
Packit 4a16fb
				snd_pcm_hw_params_dump(params, log);
Packit 4a16fb
				snd_output_printf(log, "srefine '%s', err < 0 (%i) (slave)\n", pcm->name, err);
Packit 4a16fb
				snd_pcm_hw_params_dump(&sparams, log);
Packit 4a16fb
#endif
Packit 4a16fb
				cchange(pcm, params, &sparams);
Packit 4a16fb
				return err;
Packit 4a16fb
			}
Packit 4a16fb
		} else {
Packit 4a16fb
#ifdef RULES_DEBUG
Packit 4a16fb
			snd_output_printf(log, "schange '%s', err < 0 (%i) (client)\n", pcm->name, err);
Packit 4a16fb
			snd_pcm_hw_params_dump(params, log);
Packit 4a16fb
			snd_output_printf(log, "schange '%s', err < 0 (%i) (slave)\n", pcm->name, err);
Packit 4a16fb
			snd_pcm_hw_params_dump(&sparams, log);
Packit 4a16fb
#endif
Packit 4a16fb
			cchange(pcm, params, &sparams);
Packit 4a16fb
			return err;
Packit 4a16fb
		}
Packit 4a16fb
#ifdef RULES_DEBUG
Packit 4a16fb
		snd_output_printf(log, "cchange '%s'\n", pcm->name);
Packit 4a16fb
#endif
Packit 4a16fb
		err = cchange(pcm, params, &sparams);
Packit 4a16fb
		if (err < 0)
Packit 4a16fb
			return err;
Packit 4a16fb
#ifdef RULES_DEBUG
Packit 4a16fb
		snd_output_printf(log, "refine_soft '%s'\n", pcm->name);
Packit 4a16fb
#endif
Packit 4a16fb
		err = snd_pcm_hw_refine_soft(pcm, params);
Packit 4a16fb
		changed = params->cmask;
Packit 4a16fb
		params->cmask |= cmask;
Packit 4a16fb
		if (err < 0)
Packit 4a16fb
			return err;
Packit 4a16fb
#ifdef RULES_DEBUG
Packit 4a16fb
		snd_output_printf(log, "refine_soft ok '%s'\n", pcm->name);
Packit 4a16fb
#endif
Packit 4a16fb
	} while (changed);
Packit 4a16fb
#ifdef RULES_DEBUG
Packit 4a16fb
	snd_output_printf(log, "refine_slave - leave '%s'\n", pcm->name);
Packit 4a16fb
	snd_output_close(log);
Packit 4a16fb
#endif
Packit 4a16fb
	return 0;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
int snd_pcm_hw_params_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
Packit 4a16fb
			    int (*cchange)(snd_pcm_t *pcm,
Packit 4a16fb
					   snd_pcm_hw_params_t *params,
Packit 4a16fb
					   snd_pcm_hw_params_t *sparams),
Packit 4a16fb
			    int (*sprepare)(snd_pcm_t *pcm,
Packit 4a16fb
					    snd_pcm_hw_params_t *params),
Packit 4a16fb
			    int (*schange)(snd_pcm_t *pcm,
Packit 4a16fb
					   snd_pcm_hw_params_t *params,
Packit 4a16fb
					   snd_pcm_hw_params_t *sparams),
Packit 4a16fb
			    int (*sparams)(snd_pcm_t *pcm,
Packit 4a16fb
					   snd_pcm_hw_params_t *sparams))
Packit 4a16fb
Packit 4a16fb
{
Packit 4a16fb
	snd_pcm_hw_params_t slave_params;
Packit 4a16fb
	int err;
Packit 4a16fb
	err = sprepare(pcm, &slave_params);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		return err;
Packit 4a16fb
	err = schange(pcm, params, &slave_params);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		return err;
Packit 4a16fb
	err = sparams(pcm, &slave_params);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		cchange(pcm, params, &slave_params);
Packit 4a16fb
	return err;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
static int snd_pcm_sw_params_default(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
Packit 4a16fb
{
Packit 4a16fb
	assert(pcm && params);
Packit 4a16fb
	assert(pcm->setup);
Packit 4a16fb
	params->proto = SNDRV_PCM_VERSION;
Packit 4a16fb
	params->tstamp_mode = SND_PCM_TSTAMP_NONE;
Packit 4a16fb
	params->tstamp_type = pcm->tstamp_type;
Packit 4a16fb
	params->period_step = 1;
Packit 4a16fb
	params->sleep_min = 0;
Packit 4a16fb
	params->avail_min = pcm->period_size;
Packit 4a16fb
	params->xfer_align = 1;
Packit 4a16fb
	params->start_threshold = 1;
Packit 4a16fb
	params->stop_threshold = pcm->buffer_size;
Packit 4a16fb
	params->silence_threshold = 0;
Packit 4a16fb
	params->silence_size = 0;
Packit 4a16fb
	params->boundary = pcm->buffer_size;
Packit 4a16fb
	while (params->boundary * 2 <= LONG_MAX - pcm->buffer_size)
Packit 4a16fb
		params->boundary *= 2;
Packit 4a16fb
	return 0;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
#if 0
Packit 4a16fb
#define REFINE_DEBUG
Packit 4a16fb
#endif
Packit 4a16fb
Packit 4a16fb
int snd_pcm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
Packit 4a16fb
{
Packit 4a16fb
	int res;
Packit 4a16fb
#ifdef REFINE_DEBUG
Packit 4a16fb
	snd_output_t *log;
Packit 4a16fb
	snd_output_stdio_attach(&log, stderr, 0);
Packit 4a16fb
#endif
Packit 4a16fb
	assert(pcm && params);
Packit 4a16fb
#ifdef REFINE_DEBUG
Packit 4a16fb
	snd_output_printf(log, "REFINE called:\n");
Packit 4a16fb
	snd_pcm_hw_params_dump(params, log);
Packit 4a16fb
#endif
Packit 4a16fb
	if (pcm->ops->hw_refine)
Packit 4a16fb
		res = pcm->ops->hw_refine(pcm->op_arg, params);
Packit 4a16fb
	else
Packit 4a16fb
		res = -ENOSYS;
Packit 4a16fb
#ifdef REFINE_DEBUG
Packit 4a16fb
	snd_output_printf(log, "refine done - result = %i\n", res);
Packit 4a16fb
	snd_pcm_hw_params_dump(params, log);
Packit 4a16fb
	snd_output_close(log);
Packit 4a16fb
#endif
Packit 4a16fb
	return res;
Packit 4a16fb
}
Packit 4a16fb
Packit 4a16fb
/* Install one of the configurations present in configuration
Packit 4a16fb
   space defined by PARAMS.
Packit 4a16fb
   The configuration chosen is that obtained fixing in this order:
Packit 4a16fb
   first access
Packit 4a16fb
   first format
Packit 4a16fb
   first subformat
Packit 4a16fb
   min channels
Packit 4a16fb
   min rate
Packit 4a16fb
   min period_size
Packit 4a16fb
   max periods
Packit 4a16fb
   Return 0 on success otherwise a negative error code
Packit 4a16fb
*/
Packit 4a16fb
int _snd_pcm_hw_params_internal(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
Packit 4a16fb
{
Packit 4a16fb
	int err;
Packit 4a16fb
	snd_pcm_sw_params_t sw;
Packit 4a16fb
	int fb, min_align;
Packit 4a16fb
	err = snd_pcm_hw_refine(pcm, params);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		return err;
Packit 4a16fb
	snd_pcm_hw_params_choose(pcm, params);
Packit 4a16fb
	if (pcm->setup) {
Packit 4a16fb
		err = snd_pcm_hw_free(pcm);
Packit 4a16fb
		if (err < 0)
Packit 4a16fb
			return err;
Packit 4a16fb
	}
Packit 4a16fb
	if (pcm->ops->hw_params)
Packit 4a16fb
		err = pcm->ops->hw_params(pcm->op_arg, params);
Packit 4a16fb
	else
Packit 4a16fb
		err = -ENOSYS;
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		return err;
Packit 4a16fb
Packit 4a16fb
	pcm->setup = 1;
Packit 4a16fb
	INTERNAL(snd_pcm_hw_params_get_access)(params, &pcm->access);
Packit 4a16fb
	INTERNAL(snd_pcm_hw_params_get_format)(params, &pcm->format);
Packit 4a16fb
	INTERNAL(snd_pcm_hw_params_get_subformat)(params, &pcm->subformat);
Packit 4a16fb
	INTERNAL(snd_pcm_hw_params_get_channels)(params, &pcm->channels);
Packit 4a16fb
	INTERNAL(snd_pcm_hw_params_get_rate)(params, &pcm->rate, 0);
Packit 4a16fb
	INTERNAL(snd_pcm_hw_params_get_period_time)(params, &pcm->period_time, 0);
Packit 4a16fb
	INTERNAL(snd_pcm_hw_params_get_period_size)(params, &pcm->period_size, 0);
Packit 4a16fb
	INTERNAL(snd_pcm_hw_params_get_buffer_size)(params, &pcm->buffer_size);
Packit 4a16fb
	pcm->sample_bits = snd_pcm_format_physical_width(pcm->format);
Packit 4a16fb
	pcm->frame_bits = pcm->sample_bits * pcm->channels;
Packit 4a16fb
	fb = pcm->frame_bits;
Packit 4a16fb
	min_align = 1;
Packit 4a16fb
	while (fb % 8) {
Packit 4a16fb
		fb *= 2;
Packit 4a16fb
		min_align *= 2;
Packit 4a16fb
	}
Packit 4a16fb
	pcm->min_align = min_align;
Packit 4a16fb
	
Packit 4a16fb
	pcm->hw_flags = params->flags;
Packit 4a16fb
	pcm->info = params->info;
Packit 4a16fb
	pcm->msbits = params->msbits;
Packit 4a16fb
	pcm->rate_num = params->rate_num;
Packit 4a16fb
	pcm->rate_den = params->rate_den;
Packit 4a16fb
	pcm->fifo_size = params->fifo_size;
Packit 4a16fb
	
Packit 4a16fb
	/* Default sw params */
Packit 4a16fb
	memset(&sw, 0, sizeof(sw));
Packit 4a16fb
	snd_pcm_sw_params_default(pcm, &sw);
Packit 4a16fb
	err = snd_pcm_sw_params(pcm, &sw);
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		return err;
Packit 4a16fb
Packit 4a16fb
	if (pcm->mmap_rw || 
Packit 4a16fb
	    pcm->access == SND_PCM_ACCESS_MMAP_INTERLEAVED ||
Packit 4a16fb
	    pcm->access == SND_PCM_ACCESS_MMAP_NONINTERLEAVED ||
Packit 4a16fb
	    pcm->access == SND_PCM_ACCESS_MMAP_COMPLEX) {
Packit 4a16fb
		err = snd_pcm_mmap(pcm);
Packit 4a16fb
	}
Packit 4a16fb
	if (err < 0)
Packit 4a16fb
		return err;
Packit 4a16fb
	return 0;
Packit 4a16fb
}
Packit 4a16fb