Blame src/pcm/pcm_params.c

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